summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--.qmake.conf2
-rw-r--r--config_help.txt16
-rw-r--r--configure.json138
-rw-r--r--configure.pri54
-rw-r--r--dist/changes-5.13.0308
-rw-r--r--doc/global/qt-html-templates-offline.qdocconf2
-rw-r--r--doc/global/qt-html-templates-online.qdocconf2
-rw-r--r--examples/corelib/ipc/localfortuneclient/client.h4
-rw-r--r--examples/corelib/ipc/localfortuneserver/main.cpp3
-rw-r--r--examples/corelib/ipc/localfortuneserver/server.cpp8
-rw-r--r--examples/corelib/ipc/sharedmemory/dialog.cpp9
-rw-r--r--examples/corelib/ipc/sharedmemory/dialog.h6
-rw-r--r--examples/corelib/mimetypes/mimetypebrowser/main.cpp3
-rw-r--r--examples/corelib/mimetypes/mimetypebrowser/mainwindow.cpp4
-rw-r--r--examples/corelib/mimetypes/mimetypebrowser/mimetypemodel.cpp3
-rw-r--r--examples/corelib/serialization/convert/cborconverter.cpp16
-rw-r--r--examples/corelib/serialization/convert/textconverter.cpp6
-rw-r--r--examples/corelib/serialization/savegame/game.cpp2
-rw-r--r--examples/corelib/serialization/savegame/level.cpp2
-rw-r--r--examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp11
-rw-r--r--examples/corelib/threads/mandelbrot/mandelbrotwidget.h2
-rw-r--r--examples/corelib/threads/mandelbrot/renderthread.cpp2
-rw-r--r--examples/corelib/threads/mandelbrot/renderthread.h2
-rw-r--r--examples/corelib/threads/queuedcustomtype/block.cpp8
-rw-r--r--examples/corelib/threads/queuedcustomtype/block.h1
-rw-r--r--examples/corelib/threads/queuedcustomtype/renderthread.h2
-rw-r--r--examples/corelib/threads/queuedcustomtype/window.cpp31
-rw-r--r--examples/corelib/threads/queuedcustomtype/window.h2
-rw-r--r--examples/corelib/tools/contiguouscache/randomlistmodel.cpp1
-rw-r--r--examples/corelib/tools/contiguouscache/randomlistmodel.h2
-rw-r--r--examples/corelib/tools/customtype/main.cpp1
-rw-r--r--examples/corelib/tools/customtype/message.cpp8
-rw-r--r--examples/corelib/tools/customtype/message.h1
-rw-r--r--examples/corelib/tools/customtypesending/main.cpp11
-rw-r--r--examples/corelib/tools/customtypesending/message.cpp6
-rw-r--r--examples/corelib/tools/customtypesending/message.h1
-rw-r--r--examples/corelib/tools/customtypesending/window.cpp9
-rw-r--r--examples/corelib/tools/customtypesending/window.h2
-rw-r--r--examples/corelib/tools/doc/src/customtype.qdoc7
-rw-r--r--examples/dbus/listnames/listnames.cpp3
-rw-r--r--examples/embedded/lightmaps/slippymap.cpp11
-rw-r--r--examples/embedded/raycasting/raycasting.cpp4
-rw-r--r--examples/network/bearermonitor/bearermonitor.cpp6
-rw-r--r--examples/network/bearermonitor/bearermonitor.pro2
-rw-r--r--examples/network/dnslookup/dnslookup.cpp24
-rw-r--r--examples/network/downloadmanager/downloadmanager.cpp4
-rw-r--r--examples/network/downloadmanager/downloadmanager.h2
-rw-r--r--examples/network/googlesuggest/googlesuggest.cpp2
-rw-r--r--examples/network/http/httpwindow.cpp26
-rw-r--r--examples/network/http/httpwindow.h8
-rw-r--r--examples/network/loopback/dialog.cpp6
-rw-r--r--examples/network/network-chat/client.cpp7
-rw-r--r--examples/network/network-chat/peermanager.cpp12
-rw-r--r--examples/network/network-chat/peermanager.h2
-rw-r--r--examples/network/securesocketclient/sslclient.cpp3
-rw-r--r--examples/network/secureudpserver/server.cpp23
-rw-r--r--examples/network/secureudpserver/server.h8
-rw-r--r--examples/network/torrent/addtorrentdialog.cpp3
-rw-r--r--examples/network/torrent/filemanager.cpp7
-rw-r--r--examples/network/torrent/mainwindow.cpp8
-rw-r--r--examples/network/torrent/metainfo.cpp8
-rw-r--r--examples/network/torrent/ratecontroller.cpp18
-rw-r--r--examples/network/torrent/ratecontroller.h4
-rw-r--r--examples/network/torrent/torrentclient.cpp96
-rw-r--r--examples/network/torrent/torrentserver.cpp2
-rw-r--r--examples/opengl/contextinfo/widget.cpp4
-rw-r--r--examples/opengl/legacy/overpainting/glwidget.cpp8
-rw-r--r--examples/opengl/qopenglwidget/glwidget.cpp13
-rw-r--r--examples/opengl/qopenglwidget/glwidget.h4
-rw-r--r--examples/opengl/qopenglwidget/mainwindow.cpp2
-rw-r--r--examples/opengl/threadedqopenglwidget/main.cpp6
-rw-r--r--examples/qpa/windows/main.cpp4
-rw-r--r--examples/qtconcurrent/wordcount/main.cpp19
-rw-r--r--examples/sql/drilldown/imageitem.cpp5
-rw-r--r--examples/sql/querymodel/customsqlmodel.cpp2
-rw-r--r--examples/sql/relationaltablemodel/relationaltablemodel.cpp10
-rw-r--r--examples/vulkan/hellovulkancubes/renderer.cpp7
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp14
-rw-r--r--examples/widgets/animation/animatedtiles/main.cpp2
-rw-r--r--examples/widgets/animation/easing/window.cpp15
-rw-r--r--examples/widgets/animation/easing/window.h2
-rw-r--r--examples/widgets/animation/moveblocks/main.cpp7
-rw-r--r--examples/widgets/animation/states/main.cpp6
-rw-r--r--examples/widgets/animation/stickman/animation.cpp8
-rw-r--r--examples/widgets/animation/stickman/graphicsview.cpp4
-rw-r--r--examples/widgets/animation/stickman/graphicsview.h2
-rw-r--r--examples/widgets/animation/stickman/lifecycle.cpp23
-rw-r--r--examples/widgets/animation/stickman/stickman.cpp5
-rw-r--r--examples/widgets/animation/sub-attaq/animationmanager.cpp10
-rw-r--r--examples/widgets/animation/sub-attaq/boat.cpp15
-rw-r--r--examples/widgets/animation/sub-attaq/boat_p.h19
-rw-r--r--examples/widgets/animation/sub-attaq/bomb.cpp14
-rw-r--r--examples/widgets/animation/sub-attaq/graphicsscene.cpp24
-rw-r--r--examples/widgets/animation/sub-attaq/mainwindow.cpp3
-rw-r--r--examples/widgets/animation/sub-attaq/mainwindow.h2
-rw-r--r--examples/widgets/animation/sub-attaq/pixmapitem.cpp3
-rw-r--r--examples/widgets/animation/sub-attaq/pixmapitem.h2
-rw-r--r--examples/widgets/animation/sub-attaq/qanimationstate.cpp10
-rw-r--r--examples/widgets/animation/sub-attaq/states.cpp19
-rw-r--r--examples/widgets/animation/sub-attaq/submarine.cpp12
-rw-r--r--examples/widgets/animation/sub-attaq/submarine_p.h3
-rw-r--r--examples/widgets/animation/sub-attaq/torpedo.cpp14
-rw-r--r--examples/widgets/desktop/screenshot/screenshot.cpp3
-rw-r--r--examples/widgets/desktop/systray/main.cpp2
-rw-r--r--examples/widgets/desktop/systray/window.cpp2
-rw-r--r--examples/widgets/dialogs/classwizard/classwizard.cpp4
-rw-r--r--examples/widgets/dialogs/extension/finddialog.cpp2
-rw-r--r--examples/widgets/dialogs/findfiles/window.cpp4
-rw-r--r--examples/widgets/dialogs/standarddialogs/dialog.cpp8
-rw-r--r--examples/widgets/doc/dropsite.qdoc8
-rw-r--r--examples/widgets/doc/src/addressbook.qdoc11
-rw-r--r--examples/widgets/doc/src/application.qdoc9
-rw-r--r--examples/widgets/doc/src/diagramscene.qdoc2
-rw-r--r--examples/widgets/doc/src/fetchmore.qdoc2
-rw-r--r--examples/widgets/doc/src/icons.qdoc7
-rw-r--r--examples/widgets/doc/src/orderform.qdoc2
-rw-r--r--examples/widgets/doc/src/plugandpaint.qdoc4
-rw-r--r--examples/widgets/doc/src/simpletreemodel.qdoc5
-rw-r--r--examples/widgets/doc/src/stardelegate.qdoc14
-rw-r--r--examples/widgets/draganddrop/dropsite/dropsitewindow.cpp3
-rw-r--r--examples/widgets/effects/fademessage/fademessage.cpp2
-rw-r--r--examples/widgets/gestures/imagegestures/imagewidget.cpp2
-rw-r--r--examples/widgets/graphicsview/boxes/glbuffers.cpp4
-rw-r--r--examples/widgets/graphicsview/boxes/glbuffers.h2
-rw-r--r--examples/widgets/graphicsview/boxes/qtbox.cpp24
-rw-r--r--examples/widgets/graphicsview/boxes/scene.cpp100
-rw-r--r--examples/widgets/graphicsview/boxes/scene.h2
-rw-r--r--examples/widgets/graphicsview/chip/chip.cpp6
-rw-r--r--examples/widgets/graphicsview/chip/view.cpp32
-rw-r--r--examples/widgets/graphicsview/collidingmice/main.cpp2
-rw-r--r--examples/widgets/graphicsview/collidingmice/mouse.cpp11
-rw-r--r--examples/widgets/graphicsview/diagramscene/arrow.cpp12
-rw-r--r--examples/widgets/graphicsview/diagramscene/diagramitem.cpp5
-rw-r--r--examples/widgets/graphicsview/diagramscene/diagramscene.cpp18
-rw-r--r--examples/widgets/graphicsview/diagramscene/diagramscene.h2
-rw-r--r--examples/widgets/graphicsview/diagramscene/mainwindow.cpp86
-rw-r--r--examples/widgets/graphicsview/dragdroprobot/robot.cpp6
-rw-r--r--examples/widgets/graphicsview/elasticnodes/graphwidget.cpp10
-rw-r--r--examples/widgets/graphicsview/elasticnodes/node.cpp11
-rw-r--r--examples/widgets/graphicsview/embeddeddialogs/customproxy.cpp12
-rw-r--r--examples/widgets/graphicsview/embeddeddialogs/embeddeddialog.cpp8
-rw-r--r--examples/widgets/graphicsview/embeddeddialogs/main.cpp2
-rw-r--r--examples/widgets/graphicsview/flowlayout/flowlayout.cpp9
-rw-r--r--examples/widgets/graphicsview/padnavigator/roundrectitem.cpp6
-rw-r--r--examples/widgets/graphicsview/padnavigator/splashitem.cpp2
-rw-r--r--examples/widgets/itemviews/addressbook/adddialog.cpp38
-rw-r--r--examples/widgets/itemviews/addressbook/adddialog.h14
-rw-r--r--examples/widgets/itemviews/addressbook/addresswidget.cpp69
-rw-r--r--examples/widgets/itemviews/addressbook/addresswidget.h5
-rw-r--r--examples/widgets/itemviews/addressbook/mainwindow.cpp18
-rw-r--r--examples/widgets/itemviews/addressbook/mainwindow.h6
-rw-r--r--examples/widgets/itemviews/addressbook/newaddresstab.cpp21
-rw-r--r--examples/widgets/itemviews/addressbook/newaddresstab.h10
-rw-r--r--examples/widgets/itemviews/addressbook/tablemodel.cpp52
-rw-r--r--examples/widgets/itemviews/addressbook/tablemodel.h10
-rw-r--r--examples/widgets/itemviews/coloreditorfactory/colorlisteditor.cpp10
-rw-r--r--examples/widgets/itemviews/coloreditorfactory/colorlisteditor.h4
-rw-r--r--examples/widgets/itemviews/coloreditorfactory/window.cpp17
-rw-r--r--examples/widgets/itemviews/customsortfiltermodel/filterwidget.cpp5
-rw-r--r--examples/widgets/itemviews/customsortfiltermodel/filterwidget.h2
-rw-r--r--examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp6
-rw-r--r--examples/widgets/itemviews/customsortfiltermodel/window.cpp13
-rw-r--r--examples/widgets/itemviews/editabletreemodel/main.cpp4
-rw-r--r--examples/widgets/itemviews/editabletreemodel/mainwindow.cpp32
-rw-r--r--examples/widgets/itemviews/editabletreemodel/mainwindow.h3
-rw-r--r--examples/widgets/itemviews/editabletreemodel/treeitem.cpp22
-rw-r--r--examples/widgets/itemviews/editabletreemodel/treeitem.h5
-rw-r--r--examples/widgets/itemviews/editabletreemodel/treemodel.cpp66
-rw-r--r--examples/widgets/itemviews/editabletreemodel/treemodel.h2
-rw-r--r--examples/widgets/itemviews/fetchmore/filelistmodel.cpp25
-rw-r--r--examples/widgets/itemviews/fetchmore/filelistmodel.h3
-rw-r--r--examples/widgets/itemviews/fetchmore/window.cpp4
-rw-r--r--examples/widgets/itemviews/fetchmore/window.h2
-rw-r--r--examples/widgets/itemviews/interview/model.cpp3
-rw-r--r--examples/widgets/itemviews/interview/model.h4
-rw-r--r--examples/widgets/itemviews/pixelator/mainwindow.cpp2
-rw-r--r--examples/widgets/itemviews/pixelator/pixeldelegate.cpp14
-rw-r--r--examples/widgets/itemviews/pixelator/pixeldelegate.h6
-rw-r--r--examples/widgets/itemviews/puzzle/piecesmodel.cpp9
-rw-r--r--examples/widgets/itemviews/puzzle/piecesmodel.h10
-rw-r--r--examples/widgets/itemviews/puzzle/puzzlewidget.cpp2
-rw-r--r--examples/widgets/itemviews/simpledommodel/domitem.cpp30
-rw-r--r--examples/widgets/itemviews/simpledommodel/domitem.h6
-rw-r--r--examples/widgets/itemviews/simpledommodel/dommodel.cpp40
-rw-r--r--examples/widgets/itemviews/simpledommodel/dommodel.h2
-rw-r--r--examples/widgets/itemviews/simpledommodel/mainwindow.cpp9
-rw-r--r--examples/widgets/itemviews/simpledommodel/mainwindow.h2
-rw-r--r--examples/widgets/itemviews/simpletreemodel/treeitem.cpp18
-rw-r--r--examples/widgets/itemviews/simpletreemodel/treeitem.h8
-rw-r--r--examples/widgets/itemviews/simpletreemodel/treemodel.cpp35
-rw-r--r--examples/widgets/itemviews/simpletreemodel/treemodel.h2
-rw-r--r--examples/widgets/itemviews/simplewidgetmapper/window.h2
-rw-r--r--examples/widgets/itemviews/spinboxdelegate/delegate.cpp7
-rw-r--r--examples/widgets/itemviews/spinboxdelegate/delegate.h6
-rw-r--r--examples/widgets/itemviews/spreadsheet/main.cpp3
-rw-r--r--examples/widgets/itemviews/spreadsheet/printview.cpp5
-rw-r--r--examples/widgets/itemviews/spreadsheet/spreadsheet.cpp92
-rw-r--r--examples/widgets/itemviews/spreadsheet/spreadsheet.h4
-rw-r--r--examples/widgets/itemviews/spreadsheet/spreadsheetdelegate.cpp12
-rw-r--r--examples/widgets/itemviews/spreadsheet/spreadsheetdelegate.h4
-rw-r--r--examples/widgets/itemviews/spreadsheet/spreadsheetitem.cpp35
-rw-r--r--examples/widgets/itemviews/spreadsheet/spreadsheetitem.h7
-rw-r--r--examples/widgets/itemviews/stardelegate/main.cpp5
-rw-r--r--examples/widgets/itemviews/stardelegate/stardelegate.cpp8
-rw-r--r--examples/widgets/itemviews/stardelegate/stardelegate.h3
-rw-r--r--examples/widgets/itemviews/stardelegate/stareditor.cpp20
-rw-r--r--examples/widgets/itemviews/stardelegate/stareditor.h5
-rw-r--r--examples/widgets/itemviews/stardelegate/starrating.cpp27
-rw-r--r--examples/widgets/itemviews/stardelegate/starrating.h8
-rw-r--r--examples/widgets/itemviews/storageview/main.cpp7
-rw-r--r--examples/widgets/itemviews/storageview/storagemodel.cpp8
-rw-r--r--examples/widgets/itemviews/storageview/storagemodel.h2
-rw-r--r--examples/widgets/layouts/basiclayouts/dialog.cpp6
-rw-r--r--examples/widgets/layouts/borderlayout/borderlayout.cpp13
-rw-r--r--examples/widgets/layouts/borderlayout/borderlayout.h2
-rw-r--r--examples/widgets/layouts/dynamiclayouts/dialog.cpp2
-rw-r--r--examples/widgets/layouts/flowlayout/flowlayout.cpp16
-rw-r--r--examples/widgets/mainwindows/application/mainwindow.cpp38
-rw-r--r--examples/widgets/mainwindows/dockwidgets/mainwindow.cpp4
-rw-r--r--examples/widgets/mainwindows/mainwindow/colorswatch.cpp17
-rw-r--r--examples/widgets/mainwindows/mainwindow/toolbar.cpp9
-rw-r--r--examples/widgets/mainwindows/mdi/main.cpp3
-rw-r--r--examples/widgets/mainwindows/mdi/mainwindow.cpp9
-rw-r--r--examples/widgets/mainwindows/mdi/mdichild.cpp33
-rw-r--r--examples/widgets/mainwindows/menus/mainwindow.cpp2
-rw-r--r--examples/widgets/mainwindows/sdi/main.cpp3
-rw-r--r--examples/widgets/mainwindows/sdi/mainwindow.cpp38
-rw-r--r--examples/widgets/painting/affine/main.cpp8
-rw-r--r--examples/widgets/painting/affine/xform.cpp5
-rw-r--r--examples/widgets/painting/basicdrawing/window.cpp32
-rw-r--r--examples/widgets/painting/composition/composition.cpp78
-rw-r--r--examples/widgets/painting/composition/composition.h10
-rw-r--r--examples/widgets/painting/composition/main.cpp10
-rw-r--r--examples/widgets/painting/concentriccircles/window.cpp4
-rw-r--r--examples/widgets/painting/deform/main.cpp8
-rw-r--r--examples/widgets/painting/deform/pathdeform.cpp55
-rw-r--r--examples/widgets/painting/deform/pathdeform.h8
-rw-r--r--examples/widgets/painting/fontsampler/mainwindow.cpp50
-rw-r--r--examples/widgets/painting/gradients/gradients.cpp10
-rw-r--r--examples/widgets/painting/gradients/main.cpp4
-rw-r--r--examples/widgets/painting/imagecomposition/imagecomposer.cpp9
-rw-r--r--examples/widgets/painting/painterpaths/window.cpp46
-rw-r--r--examples/widgets/painting/pathstroke/main.cpp4
-rw-r--r--examples/widgets/painting/pathstroke/pathstroke.cpp79
-rw-r--r--examples/widgets/painting/shared/arthurstyle.cpp10
-rw-r--r--examples/widgets/painting/shared/arthurwidgets.cpp46
-rw-r--r--examples/widgets/painting/shared/hoverpoints.cpp9
-rw-r--r--examples/widgets/painting/transformations/window.cpp7
-rw-r--r--examples/widgets/qnx/foreignwindows/collector.cpp176
-rw-r--r--examples/widgets/qnx/foreignwindows/collector.h (renamed from src/plugins/platforms/mirclient/qmirclientscreenobserver.h)57
-rw-r--r--examples/widgets/qnx/foreignwindows/foreignwindows.pro11
-rw-r--r--examples/widgets/qnx/foreignwindows/main.cpp (renamed from src/plugins/platforms/mirclient/qmirclientdesktopwindow.cpp)21
-rw-r--r--examples/widgets/richtext/calendar/mainwindow.cpp10
-rw-r--r--examples/widgets/richtext/orderform/mainwindow.cpp6
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/highlighter.cpp39
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/mainwindow.cpp13
-rw-r--r--examples/widgets/richtext/textedit/example.md102
-rw-r--r--examples/widgets/richtext/textedit/images/mac/checkbox-checked.pngbin0 -> 1167 bytes
-rw-r--r--examples/widgets/richtext/textedit/images/mac/checkbox.pngbin0 -> 779 bytes
-rw-r--r--examples/widgets/richtext/textedit/images/mac/format-indent-less.pngbin0 -> 1201 bytes
-rw-r--r--examples/widgets/richtext/textedit/images/mac/format-indent-more.pngbin0 -> 993 bytes
-rw-r--r--examples/widgets/richtext/textedit/images/win/checkbox-checked.pngbin0 -> 1167 bytes
-rw-r--r--examples/widgets/richtext/textedit/images/win/checkbox.pngbin0 -> 779 bytes
-rw-r--r--examples/widgets/richtext/textedit/images/win/format-indent-less.pngbin0 -> 1201 bytes
-rw-r--r--examples/widgets/richtext/textedit/images/win/format-indent-more.pngbin0 -> 993 bytes
-rw-r--r--examples/widgets/richtext/textedit/textedit.cpp153
-rw-r--r--examples/widgets/richtext/textedit/textedit.h7
-rw-r--r--examples/widgets/richtext/textedit/textedit.qrc8
-rw-r--r--examples/widgets/scroller/graphicsview/main.cpp3
-rw-r--r--examples/widgets/statemachine/factorial/main.cpp7
-rw-r--r--examples/widgets/statemachine/rogue/window.cpp6
-rw-r--r--examples/widgets/statemachine/trafficlight/main.cpp22
-rw-r--r--examples/widgets/statemachine/twowaybutton/main.cpp4
-rw-r--r--examples/widgets/tools/codecs/mainwindow.cpp14
-rw-r--r--examples/widgets/tools/codecs/previewform.cpp2
-rw-r--r--examples/widgets/tools/completer/mainwindow.cpp24
-rw-r--r--examples/widgets/tools/customcompleter/mainwindow.cpp10
-rw-r--r--examples/widgets/tools/customcompleter/textedit.cpp4
-rw-r--r--examples/widgets/tools/echoplugin/echowindow/echowindow.cpp3
-rw-r--r--examples/widgets/tools/i18n/languagechooser.cpp15
-rw-r--r--examples/widgets/tools/plugandpaint/app/interfaces.h6
-rw-r--r--examples/widgets/tools/plugandpaint/app/paintarea.cpp2
-rw-r--r--examples/widgets/tools/plugandpaint/app/plugindialog.cpp2
-rw-r--r--examples/widgets/tools/regexp/regexpdialog.cpp18
-rw-r--r--examples/widgets/tools/regularexpression/regularexpressiondialog.cpp4
-rw-r--r--examples/widgets/tools/settingseditor/settingstree.cpp6
-rw-r--r--examples/widgets/tools/treemodelcompleter/mainwindow.cpp30
-rw-r--r--examples/widgets/tools/undo/document.cpp6
-rw-r--r--examples/widgets/tools/undo/mainwindow.cpp50
-rw-r--r--examples/widgets/tools/undoframework/mainwindow.cpp22
-rw-r--r--examples/widgets/touch/dials/main.cpp4
-rw-r--r--examples/widgets/touch/fingerpaint/mainwindow.cpp22
-rw-r--r--examples/widgets/touch/fingerpaint/scribblearea.cpp6
-rw-r--r--examples/widgets/touch/pinchzoom/mouse.cpp2
-rw-r--r--examples/widgets/tutorials/addressbook/part2/addressbook.cpp9
-rw-r--r--examples/widgets/tutorials/addressbook/part3/addressbook.cpp16
-rw-r--r--examples/widgets/tutorials/addressbook/part4/addressbook.cpp21
-rw-r--r--examples/widgets/tutorials/addressbook/part5/addressbook.cpp24
-rw-r--r--examples/widgets/tutorials/addressbook/part5/finddialog.cpp6
-rw-r--r--examples/widgets/tutorials/addressbook/part6/addressbook.cpp30
-rw-r--r--examples/widgets/tutorials/addressbook/part6/finddialog.cpp6
-rw-r--r--examples/widgets/tutorials/addressbook/part7/addressbook.cpp33
-rw-r--r--examples/widgets/tutorials/addressbook/part7/finddialog.cpp6
-rw-r--r--examples/widgets/tutorials/gettingStarted/gsQt/part2/main.cpp3
-rw-r--r--examples/widgets/tutorials/gettingStarted/gsQt/part3/main.cpp3
-rw-r--r--examples/widgets/tutorials/gettingStarted/gsQt/part4/main.cpp10
-rw-r--r--examples/widgets/tutorials/gettingStarted/gsQt/part5/main.cpp10
-rw-r--r--examples/widgets/tutorials/widgets/nestedlayouts/main.cpp35
-rw-r--r--examples/widgets/widgets/analogclock/analogclock.cpp6
-rw-r--r--examples/widgets/widgets/analogclock/analogclock.h2
-rw-r--r--examples/widgets/widgets/calculator/button.cpp4
-rw-r--r--examples/widgets/widgets/calculator/button.h2
-rw-r--r--examples/widgets/widgets/calculator/calculator.cpp6
-rw-r--r--examples/widgets/widgets/calculator/calculator.h2
-rw-r--r--examples/widgets/widgets/calendarwidget/window.cpp79
-rw-r--r--examples/widgets/widgets/calendarwidget/window.h2
-rw-r--r--examples/widgets/widgets/charactermap/characterwidget.cpp4
-rw-r--r--examples/widgets/widgets/charactermap/characterwidget.h3
-rw-r--r--examples/widgets/widgets/charactermap/mainwindow.cpp20
-rw-r--r--examples/widgets/widgets/charactermap/mainwindow.h2
-rw-r--r--examples/widgets/widgets/codeeditor/codeeditor.cpp6
-rw-r--r--examples/widgets/widgets/codeeditor/codeeditor.h3
-rw-r--r--examples/widgets/widgets/digitalclock/digitalclock.cpp4
-rw-r--r--examples/widgets/widgets/digitalclock/digitalclock.h2
-rw-r--r--examples/widgets/widgets/elidedlabel/elidedlabel.cpp2
-rw-r--r--examples/widgets/widgets/elidedlabel/elidedlabel.h9
-rw-r--r--examples/widgets/widgets/elidedlabel/main.cpp2
-rw-r--r--examples/widgets/widgets/elidedlabel/testwidget.cpp13
-rw-r--r--examples/widgets/widgets/elidedlabel/testwidget.h9
-rw-r--r--examples/widgets/widgets/groupbox/window.h2
-rw-r--r--examples/widgets/widgets/icons/iconpreviewarea.cpp44
-rw-r--r--examples/widgets/widgets/icons/iconsizespinbox.cpp4
-rw-r--r--examples/widgets/widgets/icons/imagedelegate.cpp4
-rw-r--r--examples/widgets/widgets/icons/mainwindow.cpp25
-rw-r--r--examples/widgets/widgets/icons/mainwindow.h4
-rw-r--r--examples/widgets/widgets/imageviewer/imageviewer.cpp15
-rw-r--r--examples/widgets/widgets/imageviewer/imageviewer.h2
-rw-r--r--examples/widgets/widgets/lineedits/window.cpp25
-rw-r--r--examples/widgets/widgets/lineedits/window.h3
-rw-r--r--examples/widgets/widgets/mousebuttons/buttontester.h5
-rw-r--r--examples/widgets/widgets/mousebuttons/main.cpp2
-rw-r--r--examples/widgets/widgets/movie/movieplayer.cpp27
-rw-r--r--examples/widgets/widgets/movie/movieplayer.h2
-rw-r--r--examples/widgets/widgets/scribble/mainwindow.cpp31
-rw-r--r--examples/widgets/widgets/scribble/mainwindow.h2
-rw-r--r--examples/widgets/widgets/scribble/scribblearea.cpp4
-rw-r--r--examples/widgets/widgets/scribble/scribblearea.h2
-rw-r--r--examples/widgets/widgets/shapedclock/shapedclock.cpp4
-rw-r--r--examples/widgets/widgets/shapedclock/shapedclock.h2
-rw-r--r--examples/widgets/widgets/sliders/slidersgroup.cpp12
-rw-r--r--examples/widgets/widgets/sliders/slidersgroup.h2
-rw-r--r--examples/widgets/widgets/sliders/window.cpp51
-rw-r--r--examples/widgets/widgets/sliders/window.h2
-rw-r--r--examples/widgets/widgets/spinboxes/window.cpp11
-rw-r--r--examples/widgets/widgets/spinboxes/window.h2
-rw-r--r--examples/widgets/widgets/styles/norwegianwoodstyle.cpp12
-rw-r--r--examples/widgets/widgets/styles/widgetgallery.cpp36
-rw-r--r--examples/widgets/widgets/styles/widgetgallery.h2
-rw-r--r--examples/widgets/widgets/stylesheet/mainwindow.cpp7
-rw-r--r--examples/widgets/widgets/stylesheet/mainwindow.h2
-rw-r--r--examples/widgets/widgets/stylesheet/stylesheeteditor.cpp4
-rw-r--r--examples/widgets/widgets/stylesheet/stylesheeteditor.h2
-rw-r--r--examples/widgets/widgets/tablet/tabletapplication.cpp4
-rw-r--r--examples/widgets/widgets/tablet/tabletapplication.h5
-rw-r--r--examples/widgets/widgets/tetrix/main.cpp6
-rw-r--r--examples/widgets/widgets/tetrix/tetrixboard.cpp10
-rw-r--r--examples/widgets/widgets/tetrix/tetrixboard.h2
-rw-r--r--examples/widgets/widgets/tetrix/tetrixpiece.cpp6
-rw-r--r--examples/widgets/widgets/tetrix/tetrixwindow.cpp3
-rw-r--r--examples/widgets/widgets/tetrix/tetrixwindow.h3
-rw-r--r--examples/widgets/widgets/tooltips/shapeitem.cpp2
-rw-r--r--examples/widgets/widgets/tooltips/sortingbox.cpp15
-rw-r--r--examples/widgets/widgets/tooltips/sortingbox.h6
-rw-r--r--examples/widgets/widgets/validators/ledwidget.cpp2
-rw-r--r--examples/widgets/widgets/validators/ledwidget.h2
-rw-r--r--examples/widgets/widgets/validators/localeselector.cpp7
-rw-r--r--examples/widgets/widgets/validators/localeselector.h2
-rw-r--r--examples/widgets/widgets/validators/main.cpp85
-rw-r--r--examples/widgets/widgets/validators/validators.pro4
-rw-r--r--examples/widgets/widgets/validators/validatorwidget.cpp122
-rw-r--r--examples/widgets/widgets/validators/validatorwidget.h (renamed from src/widgets/doc/snippets/code/doc_src_examples_dropsite.qdoc)23
-rw-r--r--examples/widgets/widgets/wiggly/dialog.cpp6
-rw-r--r--examples/widgets/widgets/wiggly/dialog.h2
-rw-r--r--examples/widgets/widgets/wiggly/main.cpp4
-rw-r--r--examples/widgets/widgets/wiggly/wigglywidget.cpp4
-rw-r--r--examples/widgets/widgets/wiggly/wigglywidget.h2
-rw-r--r--examples/widgets/widgets/windowflags/controllerwindow.cpp12
-rw-r--r--examples/widgets/widgets/windowflags/controllerwindow.h2
-rw-r--r--examples/widgets/widgets/windowflags/previewwindow.cpp7
-rw-r--r--examples/widgets/widgets/windowflags/previewwindow.h2
-rw-r--r--examples/xml/dombookmarks/xbeltree.cpp2
-rw-r--r--examples/xml/htmlinfo/main.cpp44
-rw-r--r--examples/xml/saxbookmarks/xbelgenerator.cpp2
-rw-r--r--examples/xml/saxbookmarks/xbelhandler.cpp2
-rw-r--r--examples/xml/streambookmarks/xbelreader.cpp2
-rw-r--r--examples/xml/streambookmarks/xbelwriter.cpp2
-rw-r--r--mkspecs/android-clang/qmake.conf6
-rw-r--r--mkspecs/common/android-base-head.conf6
-rw-r--r--mkspecs/common/clang.conf12
-rw-r--r--mkspecs/common/g++-base.conf2
-rw-r--r--mkspecs/common/g++-win32.conf2
-rw-r--r--mkspecs/common/gcc-base-unix.conf2
-rw-r--r--mkspecs/common/gcc-base.conf4
-rw-r--r--mkspecs/common/msvc-desktop.conf1
-rw-r--r--mkspecs/common/msvc-version.conf2
-rw-r--r--mkspecs/common/rtems-base.conf73
-rw-r--r--mkspecs/common/rtems/qplatformdefs.h (renamed from src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h)45
-rw-r--r--mkspecs/common/windows-desktop.conf5
-rw-r--r--mkspecs/common/winrt_winphone/qmake.conf2
-rw-r--r--mkspecs/features/android/android.prf18
-rw-r--r--mkspecs/features/android/android_deployment_settings.prf2
-rw-r--r--mkspecs/features/android/sdk.prf2
-rw-r--r--mkspecs/features/coverage.prf7
-rw-r--r--mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in115
-rw-r--r--mkspecs/features/data/testserver/Dockerfile27
-rw-r--r--mkspecs/features/default_post.prf14
-rw-r--r--mkspecs/features/exclusive_builds.prf4
-rw-r--r--mkspecs/features/lex.prf50
-rw-r--r--mkspecs/features/ltcg.prf2
-rw-r--r--mkspecs/features/qml_plugin.prf4
-rw-r--r--mkspecs/features/qmltestcase.prf10
-rw-r--r--mkspecs/features/qt.prf2
-rw-r--r--mkspecs/features/qt_common.prf28
-rw-r--r--mkspecs/features/qt_configure.prf15
-rw-r--r--mkspecs/features/qt_module.prf9
-rw-r--r--mkspecs/features/qt_plugin.prf1
-rw-r--r--mkspecs/features/rtti.prf (renamed from mkspecs/features/win32/rtti.prf)0
-rw-r--r--mkspecs/features/rtti_off.prf (renamed from mkspecs/features/win32/rtti_off.prf)0
-rw-r--r--mkspecs/features/sanitizer.prf25
-rw-r--r--mkspecs/features/testcase.prf16
-rw-r--r--mkspecs/features/unsupported/testserver.prf221
-rw-r--r--mkspecs/features/wasm/wasm.prf42
-rw-r--r--mkspecs/features/wayland-scanner.prf6
-rw-r--r--mkspecs/features/winrt/package_manifest.prf7
-rw-r--r--mkspecs/features/yacc.prf59
-rw-r--r--mkspecs/linux-clang-32/qmake.conf20
-rw-r--r--mkspecs/linux-clang-32/qplatformdefs.h (renamed from src/plugins/platforms/offscreen/qoffscreenintegration_dummy.cpp)9
-rw-r--r--mkspecs/linux-clang-libc++-32/qmake.conf10
-rw-r--r--mkspecs/linux-clang-libc++-32/qplatformdefs.h (renamed from src/plugins/platforms/mirclient/qmirclientdesktopwindow.h)19
-rw-r--r--mkspecs/wasm-emscripten/qmake.conf64
-rw-r--r--mkspecs/win32-clang-g++/qmake.conf8
-rw-r--r--mkspecs/win32-clang-msvc/qmake.conf10
-rw-r--r--mkspecs/win32-g++/qmake.conf1
-rw-r--r--qmake/Makefile.unix16
-rw-r--r--qmake/Makefile.win3212
-rw-r--r--qmake/doc/qmake.qdocconf2
-rw-r--r--qmake/doc/src/qmake-manual.qdoc78
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp39
-rw-r--r--qmake/generators/mac/pbuilder_pbx.h7
-rw-r--r--qmake/generators/makefile.cpp357
-rw-r--r--qmake/generators/makefile.h12
-rw-r--r--qmake/generators/metamakefile.cpp1
-rw-r--r--qmake/generators/projectgenerator.cpp28
-rw-r--r--qmake/generators/projectgenerator.h5
-rw-r--r--qmake/generators/unix/unixmake.cpp11
-rw-r--r--qmake/generators/unix/unixmake.h9
-rw-r--r--qmake/generators/unix/unixmake2.cpp183
-rw-r--r--qmake/generators/win32/mingw_make.cpp28
-rw-r--r--qmake/generators/win32/mingw_make.h6
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp24
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp43
-rw-r--r--qmake/generators/win32/msvc_nmake.h11
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp96
-rw-r--r--qmake/generators/win32/msvc_objectmodel.h4
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp39
-rw-r--r--qmake/generators/win32/msvc_vcproj.h5
-rw-r--r--qmake/generators/win32/winmakefile.cpp114
-rw-r--r--qmake/generators/win32/winmakefile.h7
-rw-r--r--qmake/generators/xmloutput.cpp6
-rw-r--r--qmake/library/ioutils.cpp1
-rw-r--r--qmake/library/proitems.h6
-rw-r--r--qmake/library/qmakebuiltins.cpp15
-rw-r--r--qmake/library/qmakeevaluator.cpp30
-rw-r--r--qmake/library/qmakeevaluator.h15
-rw-r--r--qmake/library/qmakeevaluator_p.h2
-rw-r--r--qmake/library/qmakeglobals.cpp1
-rw-r--r--qmake/project.cpp8
-rw-r--r--qmake/project.h6
-rw-r--r--qmake/property.cpp14
-rw-r--r--qmake/qmake.pro16
-rw-r--r--src/3rdparty/VulkanMemoryAllocator.pri1
-rw-r--r--src/3rdparty/VulkanMemoryAllocator/LICENSE.txt19
-rw-r--r--src/3rdparty/VulkanMemoryAllocator/patches/0001-Avoid-compiler-warnings.patch402
-rw-r--r--src/3rdparty/VulkanMemoryAllocator/patches/0002-Fix-gcc8-warning.patch14
-rw-r--r--src/3rdparty/VulkanMemoryAllocator/patches/0003-Disable-srwlock-for-mingw.patch13
-rw-r--r--src/3rdparty/VulkanMemoryAllocator/qt_attribution.json16
-rw-r--r--src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h16790
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES.cpp2
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp2
-rw-r--r--src/3rdparty/harfbuzz/tests/shaping/main.cpp4
-rw-r--r--src/3rdparty/libjpeg/LICENSE29
-rw-r--r--src/3rdparty/libjpeg/jconfig.h18
-rw-r--r--src/3rdparty/libjpeg/qt_attribution.json4
-rw-r--r--src/3rdparty/libjpeg/src/ChangeLog.md70
-rw-r--r--src/3rdparty/libjpeg/src/jconfig.h.in28
-rw-r--r--src/3rdparty/libjpeg/src/jdcolor.c2
-rw-r--r--src/3rdparty/libjpeg/src/jdmerge.c2
-rw-r--r--src/3rdparty/libjpeg/src/jquant1.c2
-rw-r--r--src/3rdparty/libjpeg/src/jversion.h6
-rw-r--r--src/3rdparty/md4c.pri3
-rw-r--r--src/3rdparty/md4c/LICENSE.md22
-rw-r--r--src/3rdparty/md4c/md4c.c6109
-rw-r--r--src/3rdparty/md4c/md4c.h362
-rw-r--r--src/3rdparty/md4c/qt_attribution.json15
-rw-r--r--src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch28
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitUtils.c2
-rw-r--r--src/3rdparty/sqlite.pri4
-rw-r--r--src/3rdparty/wasm/DejaVuSansMono.ttfbin0 -> 237788 bytes
-rw-r--r--src/3rdparty/wasm/qt_attribution.json2
-rw-r--r--src/android/jar/jar.pro1
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java42
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java46
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java13
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java2
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java100
-rw-r--r--src/android/templates/AndroidManifest.xml2
-rw-r--r--src/android/templates/build.gradle2
-rw-r--r--src/angle/src/config.pri5
-rw-r--r--src/concurrent/qtconcurrentcompilertest.h2
-rw-r--r--src/concurrent/qtconcurrentfilterkernel.h2
-rw-r--r--src/concurrent/qtconcurrentfunctionwrappers.h2
-rw-r--r--src/concurrent/qtconcurrentiteratekernel.h8
-rw-r--r--src/concurrent/qtconcurrentmapkernel.h2
-rw-r--r--src/concurrent/qtconcurrentrun.h8
-rw-r--r--src/concurrent/qtconcurrentthreadengine.cpp10
-rw-r--r--src/corelib/Qt5CoreMacros.cmake2
-rw-r--r--src/corelib/animation/qabstractanimation.cpp20
-rw-r--r--src/corelib/animation/qabstractanimation.h7
-rw-r--r--src/corelib/animation/qabstractanimation_p.h2
-rw-r--r--src/corelib/animation/qanimationgroup.cpp25
-rw-r--r--src/corelib/animation/qanimationgroup_p.h4
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp19
-rw-r--r--src/corelib/animation/qpropertyanimation_p.h2
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.cpp3
-rw-r--r--src/corelib/animation/qsequentialanimationgroup_p.h2
-rw-r--r--src/corelib/animation/qvariantanimation.cpp8
-rw-r--r--src/corelib/codecs/qbig5codec_p.h20
-rw-r--r--src/corelib/codecs/qlatincodec.cpp4
-rw-r--r--src/corelib/codecs/qsimplecodec.cpp6
-rw-r--r--src/corelib/codecs/qtextcodec.cpp44
-rw-r--r--src/corelib/codecs/qtextcodec_p.h2
-rw-r--r--src/corelib/codecs/qutfcodec.cpp4
-rw-r--r--src/corelib/codecs/qutfcodec_p.h2
-rw-r--r--src/corelib/configure.json110
-rw-r--r--src/corelib/corelib.pro10
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qset.cpp4
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp6
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp4
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp2
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp14
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp2
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp28
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp8
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp10
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp30
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp2
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp12
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp6
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp4
-rw-r--r--src/corelib/doc/snippets/qstack/main.cpp2
-rw-r--r--src/corelib/doc/snippets/qstringlist/main.cpp6
-rw-r--r--src/corelib/doc/snippets/resource-system/mainwindow.cpp8
-rw-r--r--src/corelib/doc/src/containers.qdoc5
-rw-r--r--src/corelib/doc/src/datastreamformat.qdoc402
-rw-r--r--src/corelib/doc/src/dontdocument.qdoc41
-rw-r--r--src/corelib/doc/src/objectmodel/metaobjects.qdoc2
-rw-r--r--src/corelib/doc/src/resource-system.qdoc67
-rw-r--r--src/corelib/eval.pri4
-rw-r--r--src/corelib/global/archdetect.cpp4
-rw-r--r--src/corelib/global/global.pri17
-rw-r--r--src/corelib/global/qcompilerdetection.h13
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h5
-rw-r--r--src/corelib/global/qflags.h90
-rw-r--r--src/corelib/global/qfloat16.cpp47
-rw-r--r--src/corelib/global/qfloat16.h159
-rw-r--r--src/corelib/global/qfloat16_f16c.c4
-rw-r--r--src/corelib/global/qfloat16tables.cpp3266
-rw-r--r--src/corelib/global/qglobal.cpp214
-rw-r--r--src/corelib/global/qglobal.h178
-rw-r--r--src/corelib/global/qglobal_p.h13
-rw-r--r--src/corelib/global/qglobalstatic.h22
-rw-r--r--src/corelib/global/qhooks.cpp2
-rw-r--r--src/corelib/global/qlibraryinfo.cpp9
-rw-r--r--src/corelib/global/qlibraryinfo.h4
-rw-r--r--src/corelib/global/qlogging.cpp128
-rw-r--r--src/corelib/global/qlogging.h29
-rw-r--r--src/corelib/global/qmalloc.cpp8
-rw-r--r--src/corelib/global/qmemory_p.h (renamed from src/corelib/global/qfloat16_p.h)54
-rw-r--r--src/corelib/global/qnamespace.h68
-rw-r--r--src/corelib/global/qnamespace.qdoc23
-rw-r--r--src/corelib/global/qnumeric.cpp26
-rw-r--r--src/corelib/global/qnumeric.h4
-rw-r--r--src/corelib/global/qnumeric_p.h25
-rw-r--r--src/corelib/global/qoperatingsystemversion.cpp2
-rw-r--r--src/corelib/global/qoperatingsystemversion.h2
-rw-r--r--src/corelib/global/qoperatingsystemversion_win.cpp4
-rw-r--r--src/corelib/global/qprocessordetection.h15
-rw-r--r--src/corelib/global/qrandom.cpp28
-rw-r--r--src/corelib/global/qrandom.h6
-rw-r--r--src/corelib/global/qsystemdetection.h2
-rw-r--r--src/corelib/global/qt_pch.h6
-rw-r--r--src/corelib/global/qtrace_p.h2
-rw-r--r--src/corelib/global/qtypeinfo.h31
-rw-r--r--src/corelib/io/io.pri7
-rw-r--r--src/corelib/io/qabstractfileengine.cpp10
-rw-r--r--src/corelib/io/qabstractfileengine_p.h6
-rw-r--r--src/corelib/io/qbuffer.cpp6
-rw-r--r--src/corelib/io/qdebug.cpp184
-rw-r--r--src/corelib/io/qdebug.h22
-rw-r--r--src/corelib/io/qdir.cpp11
-rw-r--r--src/corelib/io/qdir.h12
-rw-r--r--src/corelib/io/qdiriterator.cpp1
-rw-r--r--src/corelib/io/qfile.cpp56
-rw-r--r--src/corelib/io/qfile.h8
-rw-r--r--src/corelib/io/qfiledevice.cpp10
-rw-r--r--src/corelib/io/qfiledevice.h2
-rw-r--r--src/corelib/io/qfileinfo.cpp23
-rw-r--r--src/corelib/io/qfileinfo.h11
-rw-r--r--src/corelib/io/qfileinfo_p.h2
-rw-r--r--src/corelib/io/qfilesystemengine.cpp4
-rw-r--r--src/corelib/io/qfilesystemengine_p.h2
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp54
-rw-r--r--src/corelib/io/qfilesystemiterator_p.h2
-rw-r--r--src/corelib/io/qfilesystemiterator_unix.cpp6
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h4
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp76
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents.mm4
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp27
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue.cpp27
-rw-r--r--src/corelib/io/qfilesystemwatcher_polling.cpp41
-rw-r--r--src/corelib/io/qfilesystemwatcher_win.cpp69
-rw-r--r--src/corelib/io/qfilesystemwatcher_win_p.h6
-rw-r--r--src/corelib/io/qfsfileengine.cpp16
-rw-r--r--src/corelib/io/qfsfileengine_p.h2
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp20
-rw-r--r--src/corelib/io/qiodevice.cpp4
-rw-r--r--src/corelib/io/qipaddress.cpp12
-rw-r--r--src/corelib/io/qipaddress_p.h2
-rw-r--r--src/corelib/io/qlockfile_unix.cpp7
-rw-r--r--src/corelib/io/qloggingcategory.cpp18
-rw-r--r--src/corelib/io/qloggingcategory.h51
-rw-r--r--src/corelib/io/qloggingregistry.cpp4
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp2
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h12
-rw-r--r--src/corelib/io/qprocess.cpp22
-rw-r--r--src/corelib/io/qprocess.h33
-rw-r--r--src/corelib/io/qprocess_p.h7
-rw-r--r--src/corelib/io/qprocess_unix.cpp7
-rw-r--r--src/corelib/io/qresource.cpp326
-rw-r--r--src/corelib/io/qresource.h11
-rw-r--r--src/corelib/io/qresource_p.h58
-rw-r--r--src/corelib/io/qsavefile.cpp16
-rw-r--r--src/corelib/io/qsettings.cpp52
-rw-r--r--src/corelib/io/qsettings.h12
-rw-r--r--src/corelib/io/qsettings_win.cpp28
-rw-r--r--src/corelib/io/qstandardpaths_android.cpp16
-rw-r--r--src/corelib/io/qstandardpaths_unix.cpp34
-rw-r--r--src/corelib/io/qstorageinfo.h6
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp4
-rw-r--r--src/corelib/io/qt_attribution.json8
-rw-r--r--src/corelib/io/qtemporaryfile.cpp6
-rw-r--r--src/corelib/io/qurl.cpp77
-rw-r--r--src/corelib/io/qurl.h12
-rw-r--r--src/corelib/io/qurl_p.h2
-rw-r--r--src/corelib/io/qurlidna.cpp6
-rw-r--r--src/corelib/io/qurlquery.cpp24
-rw-r--r--src/corelib/io/qurlquery.h19
-rw-r--r--src/corelib/io/qurlrecode.cpp4
-rw-r--r--src/corelib/io/qurltlds_p.h27271
-rw-r--r--src/corelib/io/qwindowspipereader.cpp4
-rw-r--r--src/corelib/io/qwindowspipereader_p.h2
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp4
-rw-r--r--src/corelib/io/qwindowspipewriter_p.h2
-rw-r--r--src/corelib/itemmodels/itemmodels.pri17
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp30
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.h46
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel_p.h9
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.cpp12
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.h3
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel_p.h2
-rw-r--r--src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp750
-rw-r--r--src/corelib/itemmodels/qconcatenatetablesproxymodel.h102
-rw-r--r--src/corelib/itemmodels/qidentityproxymodel.cpp10
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.cpp4
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.h10
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel_p.h2
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp2
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.cpp87
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.h7
-rw-r--r--src/corelib/itemmodels/qtransposeproxymodel.cpp447
-rw-r--r--src/corelib/itemmodels/qtransposeproxymodel.h85
-rw-r--r--src/corelib/itemmodels/qtransposeproxymodel_p.h84
-rw-r--r--src/corelib/kernel/kernel.pri2
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp6
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h4
-rw-r--r--src/corelib/kernel/qabstractnativeeventfilter.cpp1
-rw-r--r--src/corelib/kernel/qabstractnativeeventfilter.h4
-rw-r--r--src/corelib/kernel/qbasictimer.cpp85
-rw-r--r--src/corelib/kernel/qbasictimer.h31
-rw-r--r--src/corelib/kernel/qcore_foundation.mm18
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm4
-rw-r--r--src/corelib/kernel/qcore_mac_p.h2
-rw-r--r--src/corelib/kernel/qcore_unix_p.h8
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp104
-rw-r--r--src/corelib/kernel/qcoreapplication.h1
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h10
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp6
-rw-r--r--src/corelib/kernel/qcoreevent.cpp14
-rw-r--r--src/corelib/kernel/qcoreevent.h2
-rw-r--r--src/corelib/kernel/qcoreglobaldata.cpp4
-rw-r--r--src/corelib/kernel/qdeadlinetimer.cpp24
-rw-r--r--src/corelib/kernel/qdeadlinetimer.h50
-rw-r--r--src/corelib/kernel/qelapsedtimer.cpp8
-rw-r--r--src/corelib/kernel/qelapsedtimer.h30
-rw-r--r--src/corelib/kernel/qelapsedtimer_generic.cpp22
-rw-r--r--src/corelib/kernel/qelapsedtimer_mac.cpp24
-rw-r--r--src/corelib/kernel/qelapsedtimer_unix.cpp24
-rw-r--r--src/corelib/kernel/qelapsedtimer_win.cpp22
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf.mm2
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp11
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib_p.h6
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp10
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h22
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp156
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h36
-rw-r--r--src/corelib/kernel/qeventloop.cpp10
-rw-r--r--src/corelib/kernel/qeventloop_p.h4
-rw-r--r--src/corelib/kernel/qfunctions_fake_env_p.h4
-rw-r--r--src/corelib/kernel/qjni.cpp8
-rw-r--r--src/corelib/kernel/qjni_p.h2
-rw-r--r--src/corelib/kernel/qmetaobject.cpp34
-rw-r--r--src/corelib/kernel/qmetaobject.h3
-rw-r--r--src/corelib/kernel/qmetaobject_moc_p.h4
-rw-r--r--src/corelib/kernel/qmetaobject_p.h10
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h10
-rw-r--r--src/corelib/kernel/qmetatype.cpp700
-rw-r--r--src/corelib/kernel/qmetatype.h21
-rw-r--r--src/corelib/kernel/qmetatype_p.h18
-rw-r--r--src/corelib/kernel/qmetatypeswitcher_p.h2
-rw-r--r--src/corelib/kernel/qmimedata.cpp5
-rw-r--r--src/corelib/kernel/qobject.cpp1115
-rw-r--r--src/corelib/kernel/qobject.h55
-rw-r--r--src/corelib/kernel/qobject_p.h276
-rw-r--r--src/corelib/kernel/qobjectdefs.h31
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h6
-rw-r--r--src/corelib/kernel/qpointer.cpp8
-rw-r--r--src/corelib/kernel/qpointer.h11
-rw-r--r--src/corelib/kernel/qpoll.cpp9
-rw-r--r--src/corelib/kernel/qppsattribute.cpp2
-rw-r--r--src/corelib/kernel/qppsattribute_p.h2
-rw-r--r--src/corelib/kernel/qppsobject_p.h2
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp19
-rw-r--r--src/corelib/kernel/qsharedmemory.h29
-rw-r--r--src/corelib/kernel/qsharedmemory_p.h16
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp7
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp5
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp4
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp6
-rw-r--r--src/corelib/kernel/qsystemerror.cpp7
-rw-r--r--src/corelib/kernel/qsystemsemaphore_systemv.cpp6
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp560
-rw-r--r--src/corelib/kernel/qtestsupport_core.cpp2
-rw-r--r--src/corelib/kernel/qtimer.cpp31
-rw-r--r--src/corelib/kernel/qtimer.h6
-rw-r--r--src/corelib/kernel/qtimerinfo_unix.cpp8
-rw-r--r--src/corelib/kernel/qtranslator.cpp33
-rw-r--r--src/corelib/kernel/qvariant.cpp67
-rw-r--r--src/corelib/kernel/qvariant.h97
-rw-r--r--src/corelib/kernel/qvariant_p.h10
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp6
-rw-r--r--src/corelib/mimetypes/mime/packages/freedesktop.org.xml4417
-rw-r--r--src/corelib/mimetypes/mimetypes.pri2
-rw-r--r--src/corelib/mimetypes/mimetypes.qrc2
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp64
-rw-r--r--src/corelib/mimetypes/qmimedatabase_p.h9
-rw-r--r--src/corelib/mimetypes/qmimeglobpattern.cpp12
-rw-r--r--src/corelib/mimetypes/qmimeglobpattern_p.h2
-rw-r--r--src/corelib/mimetypes/qmimemagicrule_p.h2
-rw-r--r--src/corelib/mimetypes/qmimemagicrulematcher_p.h2
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp9
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h16
-rw-r--r--src/corelib/mimetypes/qmimetype.cpp28
-rw-r--r--src/corelib/mimetypes/qmimetype.h12
-rw-r--r--src/corelib/mimetypes/qmimetype_p.h21
-rw-r--r--src/corelib/mimetypes/qmimetypeparser.cpp3
-rw-r--r--src/corelib/mimetypes/qmimetypeparser_p.h2
-rw-r--r--src/corelib/platform/platform.pri1
-rw-r--r--src/corelib/platform/wasm/qstdweb.cpp236
-rw-r--r--src/corelib/platform/wasm/qstdweb_p.h169
-rw-r--r--src/corelib/platform/wasm/wasm.pri3
-rw-r--r--src/corelib/plugin/qfactoryinterface.h3
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp2
-rw-r--r--src/corelib/plugin/qlibrary.cpp42
-rw-r--r--src/corelib/plugin/qlibrary_p.h4
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp12
-rw-r--r--src/corelib/plugin/qplugin.h46
-rw-r--r--src/corelib/plugin/qplugin_p.h6
-rw-r--r--src/corelib/plugin/quuid.cpp18
-rw-r--r--src/corelib/plugin/quuid.h44
-rw-r--r--src/corelib/serialization/qcborarray.cpp20
-rw-r--r--src/corelib/serialization/qcborarray.h7
-rw-r--r--src/corelib/serialization/qcborcommon.h5
-rw-r--r--src/corelib/serialization/qcbormap.cpp19
-rw-r--r--src/corelib/serialization/qcbormap.h14
-rw-r--r--src/corelib/serialization/qcborstream.cpp16
-rw-r--r--src/corelib/serialization/qcborvalue.cpp552
-rw-r--r--src/corelib/serialization/qcborvalue.h28
-rw-r--r--src/corelib/serialization/qdatastream.cpp34
-rw-r--r--src/corelib/serialization/qdatastream.h38
-rw-r--r--src/corelib/serialization/qjson_p.h20
-rw-r--r--src/corelib/serialization/qjsonarray.cpp41
-rw-r--r--src/corelib/serialization/qjsonarray.h17
-rw-r--r--src/corelib/serialization/qjsoncbor.cpp2
-rw-r--r--src/corelib/serialization/qjsondocument.cpp30
-rw-r--r--src/corelib/serialization/qjsondocument.h11
-rw-r--r--src/corelib/serialization/qjsonobject.cpp27
-rw-r--r--src/corelib/serialization/qjsonobject.h15
-rw-r--r--src/corelib/serialization/qjsonparser.cpp6
-rw-r--r--src/corelib/serialization/qjsonvalue.cpp91
-rw-r--r--src/corelib/serialization/qjsonvalue.h14
-rw-r--r--src/corelib/serialization/qjsonwriter.cpp12
-rw-r--r--src/corelib/serialization/qtextstream.cpp136
-rw-r--r--src/corelib/serialization/qtextstream.h23
-rw-r--r--src/corelib/serialization/qxmlstream.cpp46
-rw-r--r--src/corelib/serialization/qxmlstream.g16
-rw-r--r--src/corelib/serialization/qxmlstream.h34
-rw-r--r--src/corelib/serialization/qxmlstream_p.h10
-rw-r--r--src/corelib/statemachine/qabstractstate.cpp7
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp14
-rw-r--r--src/corelib/statemachine/qsignaleventgenerator_p.h2
-rw-r--r--src/corelib/statemachine/qsignaltransition_p.h2
-rw-r--r--src/corelib/statemachine/qstate.cpp5
-rw-r--r--src/corelib/statemachine/qstate_p.h8
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp63
-rw-r--r--src/corelib/statemachine/qstatemachine.h3
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h26
-rw-r--r--src/corelib/thread/qatomic.cpp75
-rw-r--r--src/corelib/thread/qatomic.h24
-rw-r--r--src/corelib/thread/qatomic_bootstrap.h10
-rw-r--r--src/corelib/thread/qatomic_cxx11.h106
-rw-r--r--src/corelib/thread/qatomic_msvc.h94
-rw-r--r--src/corelib/thread/qbasicatomic.h206
-rw-r--r--src/corelib/thread/qfutex_p.h32
-rw-r--r--src/corelib/thread/qfuture.h82
-rw-r--r--src/corelib/thread/qfutureinterface.cpp42
-rw-r--r--src/corelib/thread/qfutureinterface_p.h4
-rw-r--r--src/corelib/thread/qfuturewatcher.cpp8
-rw-r--r--src/corelib/thread/qgenericatomic.h120
-rw-r--r--src/corelib/thread/qmutex.cpp58
-rw-r--r--src/corelib/thread/qmutex.h56
-rw-r--r--src/corelib/thread/qmutex_linux.cpp12
-rw-r--r--src/corelib/thread/qmutex_mac.cpp2
-rw-r--r--src/corelib/thread/qmutex_p.h14
-rw-r--r--src/corelib/thread/qmutex_unix.cpp6
-rw-r--r--src/corelib/thread/qmutex_win.cpp2
-rw-r--r--src/corelib/thread/qmutexpool.cpp6
-rw-r--r--src/corelib/thread/qmutexpool_p.h2
-rw-r--r--src/corelib/thread/qorderedmutexlocker_p.h62
-rw-r--r--src/corelib/thread/qreadwritelock.cpp12
-rw-r--r--src/corelib/thread/qreadwritelock.h36
-rw-r--r--src/corelib/thread/qresultstore.cpp15
-rw-r--r--src/corelib/thread/qresultstore.h6
-rw-r--r--src/corelib/thread/qsemaphore.cpp10
-rw-r--r--src/corelib/thread/qsemaphore.h14
-rw-r--r--src/corelib/thread/qthread.cpp14
-rw-r--r--src/corelib/thread/qthread.h6
-rw-r--r--src/corelib/thread/qthread_p.h23
-rw-r--r--src/corelib/thread/qthread_unix.cpp48
-rw-r--r--src/corelib/thread/qthread_win.cpp20
-rw-r--r--src/corelib/thread/qthreadpool_p.h2
-rw-r--r--src/corelib/thread/qthreadstorage.cpp6
-rw-r--r--src/corelib/thread/qthreadstorage.h4
-rw-r--r--src/corelib/thread/qwaitcondition_unix.cpp2
-rw-r--r--src/corelib/time/qdatetime.cpp (renamed from src/corelib/tools/qdatetime.cpp)488
-rw-r--r--src/corelib/time/qdatetime.h (renamed from src/corelib/tools/qdatetime.h)50
-rw-r--r--src/corelib/time/qdatetime_p.h (renamed from src/corelib/tools/qdatetime_p.h)2
-rw-r--r--src/corelib/time/qdatetimeparser.cpp (renamed from src/corelib/tools/qdatetimeparser.cpp)69
-rw-r--r--src/corelib/time/qdatetimeparser_p.h (renamed from src/corelib/tools/qdatetimeparser_p.h)15
-rw-r--r--src/corelib/time/qtimezone.cpp (renamed from src/corelib/tools/qtimezone.cpp)2
-rw-r--r--src/corelib/time/qtimezone.h (renamed from src/corelib/tools/qtimezone.h)8
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp (renamed from src/corelib/tools/qtimezoneprivate.cpp)0
-rw-r--r--src/corelib/time/qtimezoneprivate_android.cpp (renamed from src/corelib/tools/qtimezoneprivate_android.cpp)0
-rw-r--r--src/corelib/time/qtimezoneprivate_data_p.h1257
-rw-r--r--src/corelib/time/qtimezoneprivate_icu.cpp (renamed from src/corelib/tools/qtimezoneprivate_icu.cpp)0
-rw-r--r--src/corelib/time/qtimezoneprivate_mac.mm (renamed from src/corelib/tools/qtimezoneprivate_mac.mm)0
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h (renamed from src/corelib/tools/qtimezoneprivate_p.h)6
-rw-r--r--src/corelib/time/qtimezoneprivate_tz.cpp (renamed from src/corelib/tools/qtimezoneprivate_tz.cpp)33
-rw-r--r--src/corelib/time/qtimezoneprivate_win.cpp (renamed from src/corelib/tools/qtimezoneprivate_win.cpp)0
-rw-r--r--src/corelib/time/time.pri34
-rw-r--r--src/corelib/tools/qalgorithms.h66
-rw-r--r--src/corelib/tools/qarraydata.cpp119
-rw-r--r--src/corelib/tools/qarraydata.h44
-rw-r--r--src/corelib/tools/qarraydataops.h4
-rw-r--r--src/corelib/tools/qarraydatapointer.h10
-rw-r--r--src/corelib/tools/qbitarray.h12
-rw-r--r--src/corelib/tools/qbytearray.cpp244
-rw-r--r--src/corelib/tools/qbytearray.h118
-rw-r--r--src/corelib/tools/qbytearraylist.cpp22
-rw-r--r--src/corelib/tools/qbytearraylist.h12
-rw-r--r--src/corelib/tools/qbytearraymatcher.cpp12
-rw-r--r--src/corelib/tools/qbytearraymatcher.h14
-rw-r--r--src/corelib/tools/qbytedata_p.h2
-rw-r--r--src/corelib/tools/qcache.h18
-rw-r--r--src/corelib/tools/qcache.qdoc6
-rw-r--r--src/corelib/tools/qchar.cpp58
-rw-r--r--src/corelib/tools/qchar.h263
-rw-r--r--src/corelib/tools/qcollator.cpp130
-rw-r--r--src/corelib/tools/qcollator.h23
-rw-r--r--src/corelib/tools/qcollator_icu.cpp41
-rw-r--r--src/corelib/tools/qcollator_macx.cpp46
-rw-r--r--src/corelib/tools/qcollator_p.h4
-rw-r--r--src/corelib/tools/qcollator_posix.cpp14
-rw-r--r--src/corelib/tools/qcollator_win.cpp34
-rw-r--r--src/corelib/tools/qcommandlineoption.cpp4
-rw-r--r--src/corelib/tools/qcommandlineoption.h6
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp60
-rw-r--r--src/corelib/tools/qcontainertools_impl.h136
-rw-r--r--src/corelib/tools/qcontiguouscache.h20
-rw-r--r--src/corelib/tools/qcryptographichash.cpp4
-rw-r--r--src/corelib/tools/qeasingcurve.cpp53
-rw-r--r--src/corelib/tools/qeasingcurve.h8
-rw-r--r--src/corelib/tools/qfreelist_p.h20
-rw-r--r--src/corelib/tools/qhash.cpp66
-rw-r--r--src/corelib/tools/qhash.h80
-rw-r--r--src/corelib/tools/qhashfunctions.h100
-rw-r--r--src/corelib/tools/qiterator.h6
-rw-r--r--src/corelib/tools/qline.cpp28
-rw-r--r--src/corelib/tools/qline.h9
-rw-r--r--src/corelib/tools/qlinkedlist.cpp8
-rw-r--r--src/corelib/tools/qlinkedlist.h84
-rw-r--r--src/corelib/tools/qlist.cpp35
-rw-r--r--src/corelib/tools/qlist.h243
-rw-r--r--src/corelib/tools/qlocale.cpp258
-rw-r--r--src/corelib/tools/qlocale.h37
-rw-r--r--src/corelib/tools/qlocale.qdoc653
-rw-r--r--src/corelib/tools/qlocale_data_p.h65
-rw-r--r--src/corelib/tools/qlocale_mac.mm8
-rw-r--r--src/corelib/tools/qlocale_p.h27
-rw-r--r--src/corelib/tools/qlocale_tools.cpp4
-rw-r--r--src/corelib/tools/qlocale_unix.cpp8
-rw-r--r--src/corelib/tools/qlocale_win.cpp8
-rw-r--r--src/corelib/tools/qmakearray_p.h4
-rw-r--r--src/corelib/tools/qmap.cpp30
-rw-r--r--src/corelib/tools/qmap.h35
-rw-r--r--src/corelib/tools/qmargins.h208
-rw-r--r--src/corelib/tools/qoffsetstringarray_p.h198
-rw-r--r--src/corelib/tools/qpair.h37
-rw-r--r--src/corelib/tools/qpoint.h6
-rw-r--r--src/corelib/tools/qqueue.h4
-rw-r--r--src/corelib/tools/qrect.cpp26
-rw-r--r--src/corelib/tools/qrect.h624
-rw-r--r--src/corelib/tools/qrefcount.h26
-rw-r--r--src/corelib/tools/qregexp.cpp32
-rw-r--r--src/corelib/tools/qregexp.h10
-rw-r--r--src/corelib/tools/qregularexpression.cpp35
-rw-r--r--src/corelib/tools/qregularexpression.h24
-rw-r--r--src/corelib/tools/qringbuffer.cpp4
-rw-r--r--src/corelib/tools/qringbuffer_p.h14
-rw-r--r--src/corelib/tools/qscopedpointer.cpp37
-rw-r--r--src/corelib/tools/qscopedpointer.h38
-rw-r--r--src/corelib/tools/qscopedvaluerollback.h14
-rw-r--r--src/corelib/tools/qscopeguard.h20
-rw-r--r--src/corelib/tools/qset.h60
-rw-r--r--src/corelib/tools/qset.qdoc11
-rw-r--r--src/corelib/tools/qshareddata.cpp18
-rw-r--r--src/corelib/tools/qshareddata.h46
-rw-r--r--src/corelib/tools/qsharedpointer.cpp149
-rw-r--r--src/corelib/tools/qsharedpointer.h6
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h219
-rw-r--r--src/corelib/tools/qsimd.cpp7
-rw-r--r--src/corelib/tools/qsimd_p.h12
-rw-r--r--src/corelib/tools/qsize.cpp8
-rw-r--r--src/corelib/tools/qsize.h254
-rw-r--r--src/corelib/tools/qstack.h2
-rw-r--r--src/corelib/tools/qstring.cpp1229
-rw-r--r--src/corelib/tools/qstring.h680
-rw-r--r--src/corelib/tools/qstringalgorithms.h49
-rw-r--r--src/corelib/tools/qstringalgorithms_p.h4
-rw-r--r--src/corelib/tools/qstringbuilder.cpp2
-rw-r--r--src/corelib/tools/qstringbuilder.h10
-rw-r--r--src/corelib/tools/qstringlist.cpp60
-rw-r--r--src/corelib/tools/qstringlist.h61
-rw-r--r--src/corelib/tools/qstringliteral.h2
-rw-r--r--src/corelib/tools/qstringmatcher.cpp88
-rw-r--r--src/corelib/tools/qstringmatcher.h5
-rw-r--r--src/corelib/tools/qstringview.cpp113
-rw-r--r--src/corelib/tools/qstringview.h108
-rw-r--r--src/corelib/tools/qt_attribution.json2
-rw-r--r--src/corelib/tools/qtimezoneprivate_data_p.h1154
-rw-r--r--src/corelib/tools/qtools_p.h18
-rw-r--r--src/corelib/tools/qunicodetables.cpp16
-rw-r--r--src/corelib/tools/qunicodetables_p.h20
-rw-r--r--src/corelib/tools/qunicodetools.cpp29
-rw-r--r--src/corelib/tools/qunicodetools_p.h1
-rw-r--r--src/corelib/tools/qvarlengtharray.h41
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc16
-rw-r--r--src/corelib/tools/qvector.h320
-rw-r--r--src/corelib/tools/qvector.qdoc33
-rw-r--r--src/corelib/tools/qversionnumber.cpp6
-rw-r--r--src/corelib/tools/qversionnumber.h50
-rw-r--r--src/corelib/tools/tools.pri32
-rw-r--r--src/dbus/dbus.pro15
-rw-r--r--src/dbus/dbus_minimal_p.h32
-rw-r--r--src/dbus/doc/qtdbus.qdocconf2
-rw-r--r--src/dbus/doc/src/dontdocument.qdoc30
-rw-r--r--src/dbus/qdbusabstractinterface.cpp133
-rw-r--r--src/dbus/qdbusabstractinterface.h94
-rw-r--r--src/dbus/qdbusargument.cpp6
-rw-r--r--src/dbus/qdbusargument.h21
-rw-r--r--src/dbus/qdbusargument_p.h10
-rw-r--r--src/dbus/qdbusconnection.h10
-rw-r--r--src/dbus/qdbusconnection_p.h32
-rw-r--r--src/dbus/qdbuserror.cpp145
-rw-r--r--src/dbus/qdbuserror.h8
-rw-r--r--src/dbus/qdbusextratypes.h20
-rw-r--r--src/dbus/qdbusintegrator.cpp124
-rw-r--r--src/dbus/qdbusintegrator_p.h25
-rw-r--r--src/dbus/qdbusinternalfilters.cpp20
-rw-r--r--src/dbus/qdbusmarshaller.cpp12
-rw-r--r--src/dbus/qdbusmessage.h6
-rw-r--r--src/dbus/qdbusmetaobject.cpp2
-rw-r--r--src/dbus/qdbusmetatype.cpp4
-rw-r--r--src/dbus/qdbuspendingcall.cpp18
-rw-r--r--src/dbus/qdbuspendingcall.h8
-rw-r--r--src/dbus/qdbuspendingcall_p.h2
-rw-r--r--src/dbus/qdbuspendingreply.cpp29
-rw-r--r--src/dbus/qdbuspendingreply.h5
-rw-r--r--src/dbus/qdbusreply.cpp6
-rw-r--r--src/dbus/qdbusreply.h4
-rw-r--r--src/dbus/qdbusserver.cpp2
-rw-r--r--src/dbus/qdbusservicewatcher.cpp11
-rw-r--r--src/dbus/qdbusunixfiledescriptor.cpp10
-rw-r--r--src/dbus/qdbusunixfiledescriptor.h10
-rw-r--r--src/dbus/qdbusutil.cpp30
-rw-r--r--src/dbus/qdbusutil_p.h14
-rw-r--r--src/dbus/qdbusxmlgenerator.cpp14
-rw-r--r--src/dbus/qt_attribution.json2
-rw-r--r--src/gui/accessible/qaccessible.cpp6
-rw-r--r--src/gui/accessible/qaccessible.h2
-rw-r--r--src/gui/accessible/qaccessiblecache_p.h2
-rw-r--r--src/gui/accessible/qaccessibleobject.h2
-rw-r--r--src/gui/configure.json90
-rw-r--r--src/gui/doc/snippets/clipboard/clipwindow.cpp9
-rw-r--r--src/gui/doc/snippets/code/doc_src_coordsys.cpp2
-rw-r--r--src/gui/doc/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp8
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp9
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qguiapplication_x11.cpp4
-rw-r--r--src/gui/doc/snippets/draganddrop/mainwindow.cpp10
-rw-r--r--src/gui/doc/snippets/picture/picture.cpp10
-rw-r--r--src/gui/doc/snippets/qfontdatabase/main.cpp11
-rw-r--r--src/gui/doc/snippets/separations/screenwidget.cpp4
-rw-r--r--src/gui/doc/snippets/separations/viewer.cpp18
-rw-r--r--src/gui/doc/snippets/textblock-fragments/mainwindow.cpp8
-rw-r--r--src/gui/doc/snippets/textdocument-blocks/mainwindow.cpp8
-rw-r--r--src/gui/doc/snippets/textdocument-frames/mainwindow.cpp8
-rw-r--r--src/gui/doc/snippets/textdocument-lists/mainwindow.cpp5
-rw-r--r--src/gui/doc/snippets/textdocument-printing/mainwindow.cpp2
-rw-r--r--src/gui/doc/snippets/textdocument-selections/mainwindow.cpp5
-rw-r--r--src/gui/doc/snippets/textdocument-tables/mainwindow.cpp8
-rw-r--r--src/gui/doc/snippets/textdocumentendsnippet.cpp2
-rw-r--r--src/gui/doc/src/coordsys.qdoc9
-rw-r--r--src/gui/doc/src/dontdocument.qdoc66
-rw-r--r--src/gui/doc/src/richtext.qdoc3
-rw-r--r--src/gui/gui.pro2
-rw-r--r--src/gui/image/qbitmap.cpp2
-rw-r--r--src/gui/image/qbitmap.h5
-rw-r--r--src/gui/image/qbmphandler.cpp2
-rw-r--r--src/gui/image/qbmphandler_p.h3
-rw-r--r--src/gui/image/qicon.cpp23
-rw-r--r--src/gui/image/qicon.h13
-rw-r--r--src/gui/image/qiconengine.h2
-rw-r--r--src/gui/image/qimage.cpp216
-rw-r--r--src/gui/image/qimage.h37
-rw-r--r--src/gui/image/qimage_conversions.cpp340
-rw-r--r--src/gui/image/qimage_p.h7
-rw-r--r--src/gui/image/qimageiohandler.cpp4
-rw-r--r--src/gui/image/qimageiohandler.h5
-rw-r--r--src/gui/image/qimagereader.cpp10
-rw-r--r--src/gui/image/qimagewriter.cpp6
-rw-r--r--src/gui/image/qimagewriter.h5
-rw-r--r--src/gui/image/qmovie.cpp7
-rw-r--r--src/gui/image/qpaintengine_pic_p.h2
-rw-r--r--src/gui/image/qpicture.cpp15
-rw-r--r--src/gui/image/qpicture.h6
-rw-r--r--src/gui/image/qpixmap.cpp41
-rw-r--r--src/gui/image/qpixmap.h24
-rw-r--r--src/gui/image/qpixmap_raster.cpp3
-rw-r--r--src/gui/image/qpixmap_win.cpp2
-rw-r--r--src/gui/image/qpixmapcache.cpp14
-rw-r--r--src/gui/image/qpixmapcache.h14
-rw-r--r--src/gui/image/qpixmapcache_p.h2
-rw-r--r--src/gui/image/qpnghandler.cpp94
-rw-r--r--src/gui/image/qpnghandler_p.h2
-rw-r--r--src/gui/image/qppmhandler.cpp16
-rw-r--r--src/gui/image/qppmhandler_p.h4
-rw-r--r--src/gui/image/qxbmhandler.cpp3
-rw-r--r--src/gui/image/qxbmhandler_p.h2
-rw-r--r--src/gui/image/qxpmhandler.cpp13
-rw-r--r--src/gui/image/qxpmhandler_p.h2
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.cpp16
-rw-r--r--src/gui/itemmodels/qstandarditemmodel_p.h14
-rw-r--r--src/gui/kernel/kernel.pri2
-rw-r--r--src/gui/kernel/qclipboard.cpp2
-rw-r--r--src/gui/kernel/qcursor.cpp10
-rw-r--r--src/gui/kernel/qcursor.h14
-rw-r--r--src/gui/kernel/qdnd_p.h8
-rw-r--r--src/gui/kernel/qdrag.cpp2
-rw-r--r--src/gui/kernel/qdrag.h3
-rw-r--r--src/gui/kernel/qevent.cpp66
-rw-r--r--src/gui/kernel/qevent.h22
-rw-r--r--src/gui/kernel/qevent_p.h2
-rw-r--r--src/gui/kernel/qguiapplication.cpp161
-rw-r--r--src/gui/kernel/qguiapplication.h2
-rw-r--r--src/gui/kernel/qguiapplication_p.h28
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h2
-rw-r--r--src/gui/kernel/qinputdevicemanager.cpp4
-rw-r--r--src/gui/kernel/qinputdevicemanager_p.h4
-rw-r--r--src/gui/kernel/qinputdevicemanager_p_p.h5
-rw-r--r--src/gui/kernel/qinputmethod_p.h2
-rw-r--r--src/gui/kernel/qkeymapper_p.h2
-rw-r--r--src/gui/kernel/qkeysequence.cpp13
-rw-r--r--src/gui/kernel/qkeysequence.h10
-rw-r--r--src/gui/kernel/qoffscreensurface.h2
-rw-r--r--src/gui/kernel/qopenglcontext.cpp16
-rw-r--r--src/gui/kernel/qopenglcontext_p.h26
-rw-r--r--src/gui/kernel/qopenglwindow.cpp2
-rw-r--r--src/gui/kernel/qpalette.cpp12
-rw-r--r--src/gui/kernel/qpalette.h21
-rw-r--r--src/gui/kernel/qpixelformat.h64
-rw-r--r--src/gui/kernel/qplatformclipboard.h3
-rw-r--r--src/gui/kernel/qplatformcursor.cpp2
-rw-r--r--src/gui/kernel/qplatformcursor.h2
-rw-r--r--src/gui/kernel/qplatformdialoghelper.cpp30
-rw-r--r--src/gui/kernel/qplatformdialoghelper.h9
-rw-r--r--src/gui/kernel/qplatformdrag.h4
-rw-r--r--src/gui/kernel/qplatformgraphicsbuffer.cpp2
-rw-r--r--src/gui/kernel/qplatformgraphicsbuffer.h2
-rw-r--r--src/gui/kernel/qplatforminputcontext.h2
-rw-r--r--src/gui/kernel/qplatformintegration.cpp40
-rw-r--r--src/gui/kernel/qplatformintegration.h14
-rw-r--r--src/gui/kernel/qplatformscreen.cpp4
-rw-r--r--src/gui/kernel/qplatformscreen.h4
-rw-r--r--src/gui/kernel/qplatformservices.h2
-rw-r--r--src/gui/kernel/qplatformsessionmanager.h4
-rw-r--r--src/gui/kernel/qplatformsurface.h2
-rw-r--r--src/gui/kernel/qplatformtheme.h6
-rw-r--r--src/gui/kernel/qplatformwindow.cpp4
-rw-r--r--src/gui/kernel/qplatformwindow.h4
-rw-r--r--src/gui/kernel/qscreen.cpp22
-rw-r--r--src/gui/kernel/qscreen_p.h18
-rw-r--r--src/gui/kernel/qsessionmanager.cpp6
-rw-r--r--src/gui/kernel/qsessionmanager_p.h2
-rw-r--r--src/gui/kernel/qshapedpixmapdndwindow_p.h2
-rw-r--r--src/gui/kernel/qshortcutmap.cpp6
-rw-r--r--src/gui/kernel/qsimpledrag.cpp1
-rw-r--r--src/gui/kernel/qsimpledrag_p.h2
-rw-r--r--src/gui/kernel/qstylehints.cpp51
-rw-r--r--src/gui/kernel/qstylehints.h4
-rw-r--r--src/gui/kernel/qsurfaceformat.cpp2
-rw-r--r--src/gui/kernel/qt_gui_pch.h31
-rw-r--r--src/gui/kernel/qwindow.cpp45
-rw-r--r--src/gui/kernel/qwindow.h9
-rw-r--r--src/gui/kernel/qwindow_p.h92
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp17
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h4
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h12
-rw-r--r--src/gui/math3d/qgenericmatrix.h4
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp10
-rw-r--r--src/gui/opengl/qopengl.cpp15
-rw-r--r--src/gui/opengl/qopenglcustomshaderstage_p.h2
-rw-r--r--src/gui/opengl/qopengldebug.h6
-rw-r--r--src/gui/opengl/qopenglengineshadermanager_p.h2
-rw-r--r--src/gui/opengl/qopengles2ext.h442
-rw-r--r--src/gui/opengl/qopenglext.h566
-rw-r--r--src/gui/opengl/qopenglextensions_p.h2
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp4
-rw-r--r--src/gui/opengl/qopenglframebufferobject_p.h8
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp7
-rw-r--r--src/gui/opengl/qopenglfunctions.h18
-rw-r--r--src/gui/opengl/qopenglfunctions_1_0.cpp4
-rw-r--r--src/gui/opengl/qopenglfunctions_1_1.cpp8
-rw-r--r--src/gui/opengl/qopenglfunctions_1_2.cpp12
-rw-r--r--src/gui/opengl/qopenglfunctions_1_3.cpp16
-rw-r--r--src/gui/opengl/qopenglfunctions_1_4.cpp20
-rw-r--r--src/gui/opengl/qopenglfunctions_1_5.cpp22
-rw-r--r--src/gui/opengl/qopenglfunctions_2_0.cpp24
-rw-r--r--src/gui/opengl/qopenglfunctions_2_1.cpp26
-rw-r--r--src/gui/opengl/qopenglfunctions_3_0.cpp28
-rw-r--r--src/gui/opengl/qopenglfunctions_3_1.cpp20
-rw-r--r--src/gui/opengl/qopenglfunctions_3_2_compatibility.cpp32
-rw-r--r--src/gui/opengl/qopenglfunctions_3_2_core.cpp22
-rw-r--r--src/gui/opengl/qopenglfunctions_3_3_compatibility.cpp36
-rw-r--r--src/gui/opengl/qopenglfunctions_3_3_core.cpp24
-rw-r--r--src/gui/opengl/qopenglfunctions_4_0_compatibility.cpp38
-rw-r--r--src/gui/opengl/qopenglfunctions_4_0_core.cpp26
-rw-r--r--src/gui/opengl/qopenglfunctions_4_1_compatibility.cpp40
-rw-r--r--src/gui/opengl/qopenglfunctions_4_1_core.cpp28
-rw-r--r--src/gui/opengl/qopenglfunctions_4_2_compatibility.cpp42
-rw-r--r--src/gui/opengl/qopenglfunctions_4_2_core.cpp30
-rw-r--r--src/gui/opengl/qopenglfunctions_4_3_compatibility.cpp44
-rw-r--r--src/gui/opengl/qopenglfunctions_4_3_core.cpp32
-rw-r--r--src/gui/opengl/qopenglfunctions_4_4_compatibility.cpp46
-rw-r--r--src/gui/opengl/qopenglfunctions_4_4_core.cpp34
-rw-r--r--src/gui/opengl/qopenglfunctions_4_5_compatibility.cpp50
-rw-r--r--src/gui/opengl/qopenglfunctions_4_5_core.cpp36
-rw-r--r--src/gui/opengl/qopenglgradientcache_p.h2
-rw-r--r--src/gui/opengl/qopenglpaintdevice.h2
-rw-r--r--src/gui/opengl/qopenglpaintengine.cpp5
-rw-r--r--src/gui/opengl/qopenglpaintengine_p.h10
-rw-r--r--src/gui/opengl/qopenglpixeltransferoptions.h6
-rw-r--r--src/gui/opengl/qopenglqueryhelper_p.h24
-rw-r--r--src/gui/opengl/qopenglshaderprogram.cpp6
-rw-r--r--src/gui/opengl/qopenglshaderprogram.h11
-rw-r--r--src/gui/opengl/qopengltexture.cpp265
-rw-r--r--src/gui/opengl/qopengltexture.h26
-rw-r--r--src/gui/opengl/qopengltexture_p.h4
-rw-r--r--src/gui/opengl/qopengltextureglyphcache_p.h2
-rw-r--r--src/gui/opengl/qopengltexturehelper_p.h18
-rw-r--r--src/gui/opengl/qopengltextureuploader.cpp30
-rw-r--r--src/gui/opengl/qopengltextureuploader_p.h2
-rw-r--r--src/gui/opengl/qopenglversionfunctions.h3
-rw-r--r--src/gui/painting/painting.pri16
-rw-r--r--src/gui/painting/qbackingstore.cpp2
-rw-r--r--src/gui/painting/qblendfunctions.cpp18
-rw-r--r--src/gui/painting/qblendfunctions_p.h135
-rw-r--r--src/gui/painting/qbrush.cpp57
-rw-r--r--src/gui/painting/qbrush.h15
-rw-r--r--src/gui/painting/qcolor.cpp420
-rw-r--r--src/gui/painting/qcolor.h202
-rw-r--r--src/gui/painting/qcolormatrix_p.h249
-rw-r--r--src/gui/painting/qcolorspace.cpp744
-rw-r--r--src/gui/painting/qcolorspace.h139
-rw-r--r--src/gui/painting/qcolorspace_p.h138
-rw-r--r--src/gui/painting/qcolortransferfunction_p.h207
-rw-r--r--src/gui/painting/qcolortransfertable_p.h245
-rw-r--r--src/gui/painting/qcolortransform.cpp703
-rw-r--r--src/gui/painting/qcolortransform.h93
-rw-r--r--src/gui/painting/qcolortransform_p.h89
-rw-r--r--src/gui/painting/qcolortrc_p.h148
-rw-r--r--src/gui/painting/qcolortrclut.cpp (renamed from src/gui/painting/qcolorprofile.cpp)41
-rw-r--r--src/gui/painting/qcolortrclut_p.h (renamed from src/gui/painting/qcolorprofile_p.h)72
-rw-r--r--src/gui/painting/qcompositionfunctions.cpp790
-rw-r--r--src/gui/painting/qcosmeticstroker.cpp2
-rw-r--r--src/gui/painting/qcosmeticstroker_p.h4
-rw-r--r--src/gui/painting/qdatabuffer_p.h6
-rw-r--r--src/gui/painting/qdrawhelper.cpp1029
-rw-r--r--src/gui/painting/qdrawhelper_avx2.cpp314
-rw-r--r--src/gui/painting/qdrawhelper_mips_dsp.cpp2
-rw-r--r--src/gui/painting/qdrawhelper_mips_dsp_p.h2
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp98
-rw-r--r--src/gui/painting/qdrawhelper_neon_p.h2
-rw-r--r--src/gui/painting/qdrawhelper_p.h172
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp138
-rw-r--r--src/gui/painting/qdrawhelper_sse4.cpp83
-rw-r--r--src/gui/painting/qdrawhelper_ssse3.cpp169
-rw-r--r--src/gui/painting/qdrawhelper_x86_p.h7
-rw-r--r--src/gui/painting/qdrawingprimitive_sse2_p.h4
-rw-r--r--src/gui/painting/qicc.cpp669
-rw-r--r--src/gui/painting/qicc_p.h70
-rw-r--r--src/gui/painting/qimagescale.cpp7
-rw-r--r--src/gui/painting/qimagescale_sse4.cpp4
-rw-r--r--src/gui/painting/qmatrix.cpp6
-rw-r--r--src/gui/painting/qmatrix.h10
-rw-r--r--src/gui/painting/qmemrotate.cpp14
-rw-r--r--src/gui/painting/qoutlinemapper.cpp5
-rw-r--r--src/gui/painting/qoutlinemapper_p.h4
-rw-r--r--src/gui/painting/qpagelayout.h6
-rw-r--r--src/gui/painting/qpagesize.h6
-rw-r--r--src/gui/painting/qpaintdevice.cpp2
-rw-r--r--src/gui/painting/qpaintdevice.h2
-rw-r--r--src/gui/painting/qpaintengine_p.h6
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp217
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h23
-rw-r--r--src/gui/painting/qpaintengineex.cpp7
-rw-r--r--src/gui/painting/qpainter.cpp64
-rw-r--r--src/gui/painting/qpainter.h50
-rw-r--r--src/gui/painting/qpainter_p.h12
-rw-r--r--src/gui/painting/qpainterpath.cpp105
-rw-r--r--src/gui/painting/qpainterpath.h56
-rw-r--r--src/gui/painting/qpainterpath_p.h64
-rw-r--r--src/gui/painting/qpathclipper_p.h14
-rw-r--r--src/gui/painting/qpdf.cpp30
-rw-r--r--src/gui/painting/qpdf_p.h2
-rw-r--r--src/gui/painting/qpdfwriter.cpp12
-rw-r--r--src/gui/painting/qpdfwriter.h6
-rw-r--r--src/gui/painting/qpen.cpp10
-rw-r--r--src/gui/painting/qpen.h12
-rw-r--r--src/gui/painting/qplatformbackingstore.h4
-rw-r--r--src/gui/painting/qpolygon.h22
-rw-r--r--src/gui/painting/qrbtree_p.h14
-rw-r--r--src/gui/painting/qregion.cpp12
-rw-r--r--src/gui/painting/qregion.h28
-rw-r--r--src/gui/painting/qrgba64.h40
-rw-r--r--src/gui/painting/qstroker.cpp16
-rw-r--r--src/gui/painting/qstroker_p.h5
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp12
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h2
-rw-r--r--src/gui/painting/qtransform.cpp34
-rw-r--r--src/gui/painting/qtransform.h19
-rw-r--r--src/gui/painting/qtriangulator_p.h25
-rw-r--r--src/gui/painting/qvectorpath_p.h16
-rw-r--r--src/gui/platform/platform.pri1
-rw-r--r--src/gui/platform/wasm/qwasmlocalfileaccess.cpp169
-rw-r--r--src/gui/platform/wasm/qwasmlocalfileaccess_p.h78
-rw-r--r--src/gui/platform/wasm/wasm.pri3
-rw-r--r--src/gui/rhi/qrhi.cpp4891
-rw-r--r--src/gui/rhi/qrhi_p.h1375
-rw-r--r--src/gui/rhi/qrhi_p_p.h544
-rw-r--r--src/gui/rhi/qrhid3d11.cpp3388
-rw-r--r--src/gui/rhi/qrhid3d11_p.h76
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h624
-rw-r--r--src/gui/rhi/qrhigles2.cpp2975
-rw-r--r--src/gui/rhi/qrhigles2_p.h84
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h695
-rw-r--r--src/gui/rhi/qrhimetal.mm3249
-rw-r--r--src/gui/rhi/qrhimetal_p.h80
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h410
-rw-r--r--src/gui/rhi/qrhinull.cpp709
-rw-r--r--src/gui/rhi/qrhinull_p.h69
-rw-r--r--src/gui/rhi/qrhinull_p_p.h279
-rw-r--r--src/gui/rhi/qrhiprofiler.cpp603
-rw-r--r--src/gui/rhi/qrhiprofiler_p.h120
-rw-r--r--src/gui/rhi/qrhiprofiler_p_p.h121
-rw-r--r--src/gui/rhi/qrhivulkan.cpp5681
-rw-r--r--src/gui/rhi/qrhivulkan_p.h85
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h859
-rw-r--r--src/gui/rhi/qrhivulkanext_p.h81
-rw-r--r--src/gui/rhi/qshader.cpp586
-rw-r--r--src/gui/rhi/qshader_p.h227
-rw-r--r--src/gui/rhi/qshader_p_p.h84
-rw-r--r--src/gui/rhi/qshaderdescription.cpp1088
-rw-r--r--src/gui/rhi/qshaderdescription_p.h278
-rw-r--r--src/gui/rhi/qshaderdescription_p_p.h95
-rw-r--r--src/gui/rhi/rhi.pri57
-rw-r--r--src/gui/text/qabstracttextdocumentlayout.cpp31
-rw-r--r--src/gui/text/qabstracttextdocumentlayout.h3
-rw-r--r--src/gui/text/qabstracttextdocumentlayout_p.h6
-rw-r--r--src/gui/text/qcssparser.cpp69
-rw-r--r--src/gui/text/qcssparser_p.h16
-rw-r--r--src/gui/text/qcssscanner.cpp847
-rw-r--r--src/gui/text/qdistancefield.cpp5
-rw-r--r--src/gui/text/qdistancefield_p.h3
-rw-r--r--src/gui/text/qfont.cpp287
-rw-r--r--src/gui/text/qfont.h31
-rw-r--r--src/gui/text/qfont_p.h37
-rw-r--r--src/gui/text/qfontdatabase.cpp72
-rw-r--r--src/gui/text/qfontengine.cpp17
-rw-r--r--src/gui/text/qfontengine_p.h29
-rw-r--r--src/gui/text/qfontengine_qpf2.cpp6
-rw-r--r--src/gui/text/qfontmetrics.cpp31
-rw-r--r--src/gui/text/qfontmetrics.h45
-rw-r--r--src/gui/text/qfragmentmap_p.h2
-rw-r--r--src/gui/text/qglyphrun.cpp2
-rw-r--r--src/gui/text/qglyphrun.h6
-rw-r--r--src/gui/text/qglyphrun_p.h2
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp13
-rw-r--r--src/gui/text/qplatformfontdatabase.h2
-rw-r--r--src/gui/text/qrawfont.cpp2
-rw-r--r--src/gui/text/qrawfont.h8
-rw-r--r--src/gui/text/qrawfont_p.h24
-rw-r--r--src/gui/text/qstatictext.cpp4
-rw-r--r--src/gui/text/qstatictext.h6
-rw-r--r--src/gui/text/qstatictext_p.h2
-rw-r--r--src/gui/text/qsyntaxhighlighter.cpp7
-rw-r--r--src/gui/text/qsyntaxhighlighter.h2
-rw-r--r--src/gui/text/qtextcursor.h6
-rw-r--r--src/gui/text/qtextdocument.cpp93
-rw-r--r--src/gui/text/qtextdocument.h24
-rw-r--r--src/gui/text/qtextdocument_p.cpp18
-rw-r--r--src/gui/text/qtextdocument_p.h7
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp10
-rw-r--r--src/gui/text/qtextdocumentfragment_p.h8
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp68
-rw-r--r--src/gui/text/qtextdocumentwriter.cpp27
-rw-r--r--src/gui/text/qtextengine.cpp12
-rw-r--r--src/gui/text/qtextengine_p.h18
-rw-r--r--src/gui/text/qtextformat.cpp116
-rw-r--r--src/gui/text/qtextformat.h33
-rw-r--r--src/gui/text/qtextformat_p.h2
-rw-r--r--src/gui/text/qtexthtmlparser.cpp58
-rw-r--r--src/gui/text/qtexthtmlparser_p.h2
-rw-r--r--src/gui/text/qtextimagehandler_p.h2
-rw-r--r--src/gui/text/qtextlayout.cpp21
-rw-r--r--src/gui/text/qtextlayout.h14
-rw-r--r--src/gui/text/qtextlist.cpp2
-rw-r--r--src/gui/text/qtextlist.h3
-rw-r--r--src/gui/text/qtextmarkdownimporter.cpp568
-rw-r--r--src/gui/text/qtextmarkdownimporter_p.h143
-rw-r--r--src/gui/text/qtextmarkdownwriter.cpp559
-rw-r--r--src/gui/text/qtextmarkdownwriter_p.h95
-rw-r--r--src/gui/text/qtextobject.cpp20
-rw-r--r--src/gui/text/qtextobject.h9
-rw-r--r--src/gui/text/qtextobject_p.h2
-rw-r--r--src/gui/text/qtextodfwriter.cpp38
-rw-r--r--src/gui/text/qtexttable_p.h2
-rw-r--r--src/gui/text/qzipreader_p.h6
-rw-r--r--src/gui/text/qzipwriter_p.h2
-rw-r--r--src/gui/text/text.pri19
-rw-r--r--src/gui/util/qastchandler.cpp168
-rw-r--r--src/gui/util/qastchandler_p.h (renamed from src/plugins/platforms/mirclient/qmirclientplatformservices.h)40
-rw-r--r--src/gui/util/qgridlayoutengine_p.h8
-rw-r--r--src/gui/util/qlayoutpolicy_p.h1
-rw-r--r--src/gui/util/qshaderformat.cpp24
-rw-r--r--src/gui/util/qshaderformat_p.h26
-rw-r--r--src/gui/util/qshadergraph.cpp12
-rw-r--r--src/gui/util/qshadergraph_p.h16
-rw-r--r--src/gui/util/qshadergraphloader.cpp14
-rw-r--r--src/gui/util/qshadergraphloader_p.h14
-rw-r--r--src/gui/util/qshadernode.cpp16
-rw-r--r--src/gui/util/qshadernode_p.h18
-rw-r--r--src/gui/util/qshadernodeport.cpp4
-rw-r--r--src/gui/util/qshadernodeport_p.h6
-rw-r--r--src/gui/util/qshadernodesloader.cpp10
-rw-r--r--src/gui/util/qshadernodesloader_p.h10
-rw-r--r--src/gui/util/qtexturefilereader.cpp5
-rw-r--r--src/gui/util/qvalidator.h1
-rw-r--r--src/gui/util/util.pri15
-rw-r--r--src/gui/vulkan/qplatformvulkaninstance.cpp5
-rw-r--r--src/gui/vulkan/qplatformvulkaninstance.h1
-rw-r--r--src/gui/vulkan/qvulkaninstance.cpp50
-rw-r--r--src/gui/vulkan/qvulkaninstance.h17
-rw-r--r--src/gui/vulkan/qvulkanwindow_p.h2
-rw-r--r--src/network/access/http2/bitstreams_p.h2
-rw-r--r--src/network/access/http2/hpacktable_p.h2
-rw-r--r--src/network/access/qabstractnetworkcache.cpp14
-rw-r--r--src/network/access/qabstractnetworkcache.h6
-rw-r--r--src/network/access/qftp.cpp23
-rw-r--r--src/network/access/qftp_p.h9
-rw-r--r--src/network/access/qhsts.cpp4
-rw-r--r--src/network/access/qhstspolicy.h4
-rw-r--r--src/network/access/qhstsstore_p.h2
-rw-r--r--src/network/access/qhttpmultipart.h6
-rw-r--r--src/network/access/qhttpmultipart_p.h2
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp77
-rw-r--r--src/network/access/qhttpnetworkconnection_p.h23
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp13
-rw-r--r--src/network/access/qhttpnetworkreply.cpp3
-rw-r--r--src/network/access/qhttpnetworkreply_p.h2
-rw-r--r--src/network/access/qhttpnetworkrequest.cpp15
-rw-r--r--src/network/access/qhttpnetworkrequest_p.h3
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp15
-rw-r--r--src/network/access/qhttpthreaddelegate_p.h10
-rw-r--r--src/network/access/qnetworkaccessauthenticationmanager_p.h4
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp6
-rw-r--r--src/network/access/qnetworkaccesscache.cpp32
-rw-r--r--src/network/access/qnetworkaccessftpbackend.cpp9
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp215
-rw-r--r--src/network/access/qnetworkaccessmanager.h8
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h10
-rw-r--r--src/network/access/qnetworkcookie.cpp1
-rw-r--r--src/network/access/qnetworkcookie.h6
-rw-r--r--src/network/access/qnetworkcookiejar.cpp21
-rw-r--r--src/network/access/qnetworkdiskcache_p.h4
-rw-r--r--src/network/access/qnetworkfile.cpp12
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp18
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp24
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h8
-rw-r--r--src/network/access/qnetworkreplywasmimpl.cpp104
-rw-r--r--src/network/access/qnetworkrequest.cpp39
-rw-r--r--src/network/access/qnetworkrequest.h9
-rw-r--r--src/network/bearer/qbearerengine.cpp2
-rw-r--r--src/network/bearer/qbearerengine_p.h2
-rw-r--r--src/network/bearer/qbearerplugin_p.h2
-rw-r--r--src/network/bearer/qnetworkconfiguration.cpp31
-rw-r--r--src/network/bearer/qnetworkconfiguration.h6
-rw-r--r--src/network/bearer/qnetworkconfiguration_p.h9
-rw-r--r--src/network/bearer/qsharednetworksession.cpp34
-rw-r--r--src/network/bearer/qsharednetworksession_p.h16
-rw-r--r--src/network/configure.json73
-rw-r--r--src/network/doc/src/dontdocument.qdoc30
-rw-r--r--src/network/doc/src/ssl.qdoc15
-rw-r--r--src/network/kernel/kernel.pri14
-rw-r--r--src/network/kernel/qauthenticator.cpp421
-rw-r--r--src/network/kernel/qauthenticator_p.h17
-rw-r--r--src/network/kernel/qdnslookup.h30
-rw-r--r--src/network/kernel/qdnslookup_p.h2
-rw-r--r--src/network/kernel/qhostaddress.cpp2
-rw-r--r--src/network/kernel/qhostaddress.h11
-rw-r--r--src/network/kernel/qhostinfo.cpp201
-rw-r--r--src/network/kernel/qhostinfo.h11
-rw-r--r--src/network/kernel/qhostinfo_p.h9
-rw-r--r--src/network/kernel/qhostinfo_unix.cpp139
-rw-r--r--src/network/kernel/qhostinfo_win.cpp110
-rw-r--r--src/network/kernel/qnetconmonitor_darwin.mm419
-rw-r--r--src/network/kernel/qnetconmonitor_p.h126
-rw-r--r--src/network/kernel/qnetconmonitor_stub.cpp141
-rw-r--r--src/network/kernel/qnetworkdatagram.h6
-rw-r--r--src/network/kernel/qnetworkinterface.h12
-rw-r--r--src/network/kernel/qnetworkinterface_p.h2
-rw-r--r--src/network/kernel/qnetworkinterface_unix_p.h2
-rw-r--r--src/network/kernel/qnetworkproxy.cpp4
-rw-r--r--src/network/kernel/qnetworkproxy.h12
-rw-r--r--src/network/kernel/qnetworkproxy_win.cpp4
-rw-r--r--src/network/socket/qabstractsocket.cpp34
-rw-r--r--src/network/socket/qabstractsocket.h2
-rw-r--r--src/network/socket/qabstractsocket_p.h3
-rw-r--r--src/network/socket/qabstractsocketengine_p.h14
-rw-r--r--src/network/socket/qhttpsocketengine.cpp10
-rw-r--r--src/network/socket/qhttpsocketengine_p.h10
-rw-r--r--src/network/socket/qlocalserver.cpp6
-rw-r--r--src/network/socket/qlocalserver_p.h2
-rw-r--r--src/network/socket/qlocalsocket_win.cpp4
-rw-r--r--src/network/socket/qnativesocketengine.cpp8
-rw-r--r--src/network/socket/qnativesocketengine_p.h12
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp26
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h2
-rw-r--r--src/network/socket/qsctpserver.cpp7
-rw-r--r--src/network/socket/qsocks5socketengine.cpp10
-rw-r--r--src/network/socket/qsocks5socketengine_p.h12
-rw-r--r--src/network/socket/qtcpserver.cpp4
-rw-r--r--src/network/socket/socket.pri2
-rw-r--r--src/network/ssl/qasn1element_p.h6
-rw-r--r--src/network/ssl/qdtls.cpp2
-rw-r--r--src/network/ssl/qdtls.h2
-rw-r--r--src/network/ssl/qdtls_openssl.cpp2
-rw-r--r--src/network/ssl/qocsp_p.h (renamed from src/plugins/platforms/mirclient/qmirclientbackingstore.h)62
-rw-r--r--src/network/ssl/qocspresponse.cpp258
-rw-r--r--src/network/ssl/qocspresponse.h116
-rw-r--r--src/network/ssl/qocspresponse_p.h84
-rw-r--r--src/network/ssl/qssl.cpp26
-rw-r--r--src/network/ssl/qssl.h6
-rw-r--r--src/network/ssl/qsslcertificate.cpp5
-rw-r--r--src/network/ssl/qsslcertificate.h10
-rw-r--r--src/network/ssl/qsslcertificate_openssl.cpp50
-rw-r--r--src/network/ssl/qsslcertificate_p.h20
-rw-r--r--src/network/ssl/qsslcertificate_qt.cpp36
-rw-r--r--src/network/ssl/qsslcertificate_schannel.cpp (renamed from src/plugins/platforms/mirclient/qmirclientcursor.h)38
-rw-r--r--src/network/ssl/qsslcertificateextension.h6
-rw-r--r--src/network/ssl/qsslcipher.h6
-rw-r--r--src/network/ssl/qsslconfiguration.cpp41
-rw-r--r--src/network/ssl/qsslconfiguration.h9
-rw-r--r--src/network/ssl/qsslconfiguration_p.h6
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp24
-rw-r--r--src/network/ssl/qsslcontext_openssl11.cpp19
-rw-r--r--src/network/ssl/qsslcontext_openssl_p.h2
-rw-r--r--src/network/ssl/qsslcontext_opensslpre11.cpp22
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters.cpp14
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters.h24
-rw-r--r--src/network/ssl/qsslellipticcurve.cpp2
-rw-r--r--src/network/ssl/qsslellipticcurve.h18
-rw-r--r--src/network/ssl/qsslellipticcurve_dummy.cpp2
-rw-r--r--src/network/ssl/qsslellipticcurve_openssl.cpp2
-rw-r--r--src/network/ssl/qsslerror.cpp54
-rw-r--r--src/network/ssl/qsslerror.h20
-rw-r--r--src/network/ssl/qsslkey.h7
-rw-r--r--src/network/ssl/qsslkey_mac.cpp22
-rw-r--r--src/network/ssl/qsslkey_openssl.cpp55
-rw-r--r--src/network/ssl/qsslkey_p.cpp30
-rw-r--r--src/network/ssl/qsslkey_p.h10
-rw-r--r--src/network/ssl/qsslkey_qt.cpp82
-rw-r--r--src/network/ssl/qsslkey_schannel.cpp178
-rw-r--r--src/network/ssl/qsslkey_winrt.cpp9
-rw-r--r--src/network/ssl/qsslpresharedkeyauthenticator.cpp2
-rw-r--r--src/network/ssl/qsslpresharedkeyauthenticator.h6
-rw-r--r--src/network/ssl/qsslsocket.cpp130
-rw-r--r--src/network/ssl/qsslsocket.h5
-rw-r--r--src/network/ssl/qsslsocket_mac.cpp289
-rw-r--r--src/network/ssl/qsslsocket_mac_p.h4
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp427
-rw-r--r--src/network/ssl/qsslsocket_openssl11.cpp16
-rw-r--r--src/network/ssl/qsslsocket_openssl11_symbols_p.h18
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h13
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp162
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h99
-rw-r--r--src/network/ssl/qsslsocket_opensslpre11.cpp16
-rw-r--r--src/network/ssl/qsslsocket_opensslpre11_symbols_p.h47
-rw-r--r--src/network/ssl/qsslsocket_p.h26
-rw-r--r--src/network/ssl/qsslsocket_qt.cpp307
-rw-r--r--src/network/ssl/qsslsocket_schannel.cpp1994
-rw-r--r--src/network/ssl/qsslsocket_schannel_p.h155
-rw-r--r--src/network/ssl/qsslsocket_winrt.cpp12
-rw-r--r--src/network/ssl/ssl.pri23
-rw-r--r--src/opengl/doc/qtopengl.qdocconf2
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h2
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h6
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h2
-rw-r--r--src/opengl/qgl.cpp41
-rw-r--r--src/opengl/qgl.h16
-rw-r--r--src/opengl/qgl_p.h12
-rw-r--r--src/opengl/qglcolormap.cpp2
-rw-r--r--src/opengl/qglcolormap.h2
-rw-r--r--src/opengl/qglframebufferobject.cpp4
-rw-r--r--src/opengl/qglframebufferobject_p.h6
-rw-r--r--src/opengl/qglfunctions.cpp5
-rw-r--r--src/opengl/qglpixelbuffer_p.h2
-rw-r--r--src/opengl/qglshaderprogram.cpp6
-rw-r--r--src/opengl/qglshaderprogram.h11
-rw-r--r--src/opengl/qgraphicsshadereffect_p.h4
-rw-r--r--src/platformheaders/doc/qtplatformheaders.qdocconf2
-rw-r--r--src/platformheaders/doc/src/dontdocument.qdoc30
-rw-r--r--src/platformheaders/nativecontexts/qeglnativecontext.h4
-rw-r--r--src/platformheaders/windowsfunctions/qwindowswindowfunctions.h9
-rw-r--r--src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc33
-rw-r--r--src/platformsupport/devicediscovery/qdevicediscovery_p.h4
-rw-r--r--src/platformsupport/devicediscovery/qdevicediscovery_udev_p.h2
-rw-r--r--src/platformsupport/eglconvenience/qeglpbuffer_p.h2
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp8
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext_p.h4
-rw-r--r--src/platformsupport/eglconvenience/qeglstreamconvenience_p.h11
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h4
-rw-r--r--src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h2
-rw-r--r--src/platformsupport/fbconvenience/qfbvthandler_p.h2
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp4
-rw-r--r--src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp328
-rw-r--r--src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h2
-rw-r--r--src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp3
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp69
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp4
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h6
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h2
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp2
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h2
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h2
-rw-r--r--src/platformsupport/fontdatabases/windows/windows.pri4
-rw-r--r--src/platformsupport/fontdatabases/winrt/winrt.pri4
-rw-r--r--src/platformsupport/glxconvenience/glxconvenience.pro2
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp21
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp29
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h14
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp76
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h8
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp6
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h4
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp65
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h8
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp22
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h4
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp61
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h9
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp53
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp60
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h7
-rw-r--r--src/platformsupport/input/input-support.pro35
-rw-r--r--src/platformsupport/input/input.pro37
-rw-r--r--src/platformsupport/input/libinput/libinput.pri5
-rw-r--r--src/platformsupport/input/libinput/qlibinputhandler.cpp3
-rw-r--r--src/platformsupport/input/libinput/qlibinputkeyboard.cpp185
-rw-r--r--src/platformsupport/input/libinput/qlibinputkeyboard_p.h8
-rw-r--r--src/platformsupport/input/libinput/qlibinputpointer.cpp18
-rw-r--r--src/platformsupport/input/libinput/qlibinputpointer_p.h1
-rw-r--r--src/platformsupport/input/libinput/qlibinputtouch_p.h2
-rw-r--r--src/platformsupport/input/shared/devicehandlerlist_p.h (renamed from src/plugins/platforms/mirclient/qmirclientclipboard.h)87
-rw-r--r--src/platformsupport/input/shared/qevdevutil.cpp (renamed from src/plugins/platforms/mirclient/qmirclientplugin.cpp)40
-rw-r--r--src/platformsupport/input/shared/qevdevutil_p.h (renamed from src/plugins/platforms/mirclient/qmirclientglcontext.h)49
-rw-r--r--src/platformsupport/input/shared/shared.pri3
-rw-r--r--src/platformsupport/input/tslib/qtslib.cpp30
-rw-r--r--src/platformsupport/input/tslib/qtslib_p.h9
-rw-r--r--src/platformsupport/input/xkbcommon/qxkbcommon.cpp828
-rw-r--r--src/platformsupport/input/xkbcommon/qxkbcommon_3rdparty.cpp (renamed from src/plugins/platforms/xcb/qxcbxkbcommon.h)28
-rw-r--r--src/platformsupport/input/xkbcommon/qxkbcommon_p.h122
-rw-r--r--src/platformsupport/input/xkbcommon/xkbcommon.pro23
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp4
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor.cpp9
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor_p.h2
-rw-r--r--src/platformsupport/linuxaccessibility/cache_p.h2
-rw-r--r--src/platformsupport/linuxaccessibility/dbusconnection_p.h2
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h2
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp3
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor.cpp3
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h3
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes.cpp12
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes_p.h4
-rw-r--r--src/platformsupport/themes/qabstractfileiconengine.cpp2
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp16
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h4
-rw-r--r--src/platformsupport/vkconvenience/qvkconvenience.cpp217
-rw-r--r--src/platformsupport/vkconvenience/qvkconvenience_p.h (renamed from src/plugins/platforms/mirclient/qmirclientappstatecontroller.h)41
-rw-r--r--src/platformsupport/vkconvenience/vkconvenience.pro2
-rw-r--r--src/plugins/bearer/connman/qconnmanengine.h2
-rw-r--r--src/plugins/bearer/connman/qconnmanservice_linux_p.h6
-rw-r--r--src/plugins/bearer/generic/qgenericengine.h2
-rw-r--r--src/plugins/bearer/linux_common/qofonoservice_linux_p.h10
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp4
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.h4
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp37
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.h22
-rw-r--r--src/plugins/bearer/nla/nla.pro2
-rw-r--r--src/plugins/bearer/nla/qnlaengine.cpp39
-rw-r--r--src/plugins/bearer/qbearerengine_impl.h2
-rw-r--r--src/plugins/bearer/qnetworksession_impl.cpp4
-rw-r--r--src/plugins/bearer/qnetworksession_impl.h2
-rw-r--r--src/plugins/generic/tuiotouch/qtuiohandler.cpp10
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler.cpp14
-rw-r--r--src/plugins/platforminputcontexts/compose/compose.pro8
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp658
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h145
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp297
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h33
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp4
-rw-r--r--src/plugins/platforminputcontexts/ibus/ibus.pro2
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h2
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp60
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h6
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusproxy.h2
-rw-r--r--src/plugins/platforminputcontexts/platforminputcontexts.pro11
-rw-r--r--src/plugins/platforms/android/android.pro8
-rw-r--r--src/plugins/platforms/android/androidcontentfileengine.cpp (renamed from src/plugins/platforms/mirclient/qmirclientappstatecontroller.cpp)84
-rw-r--r--src/plugins/platforms/android/androidcontentfileengine.h (renamed from src/plugins/platforms/mirclient/qmirclientplugin.h)26
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp5
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp7
-rw-r--r--src/plugins/platforms/android/extract-dummy.cpp10
-rw-r--r--src/plugins/platforms/android/extract.cpp40
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.cpp4
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.h2
-rw-r--r--src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp149
-rw-r--r--src/plugins/platforms/android/qandroidplatformfiledialoghelper.h81
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.cpp5
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm308
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h12
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h7
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm91
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.h31
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.mm220
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm6
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm11
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.mm15
-rw-r--r--src/plugins/platforms/cocoa/qnsview_drawing.mm2
-rw-r--r--src/plugins/platforms/cocoa/qnsview_gestures.mm10
-rw-r--r--src/plugins/platforms/cocoa/qnsview_mouse.mm5
-rw-r--r--src/plugins/platforms/cocoa/qnsview_touch.mm8
-rw-r--r--src/plugins/platforms/direct2d/direct2d.pro4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp18
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp4
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp50
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp5
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp2
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm2
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.h2
-rw-r--r--src/plugins/platforms/mirclient/mirclient.json3
-rw-r--r--src/plugins/platforms/mirclient/mirclient.pro61
-rw-r--r--src/plugins/platforms/mirclient/qmirclientbackingstore.cpp157
-rw-r--r--src/plugins/platforms/mirclient/qmirclientclipboard.cpp181
-rw-r--r--src/plugins/platforms/mirclient/qmirclientcursor.cpp209
-rw-r--r--src/plugins/platforms/mirclient/qmirclientdebugextension.cpp79
-rw-r--r--src/plugins/platforms/mirclient/qmirclientglcontext.cpp132
-rw-r--r--src/plugins/platforms/mirclient/qmirclientinput.cpp708
-rw-r--r--src/plugins/platforms/mirclient/qmirclientinput.h86
-rw-r--r--src/plugins/platforms/mirclient/qmirclientintegration.cpp412
-rw-r--r--src/plugins/platforms/mirclient/qmirclientintegration.h131
-rw-r--r--src/plugins/platforms/mirclient/qmirclientlogging.h55
-rw-r--r--src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp217
-rw-r--r--src/plugins/platforms/mirclient/qmirclientnativeinterface.h83
-rw-r--r--src/plugins/platforms/mirclient/qmirclientplatformservices.cpp75
-rw-r--r--src/plugins/platforms/mirclient/qmirclientscreen.cpp262
-rw-r--r--src/plugins/platforms/mirclient/qmirclientscreen.h106
-rw-r--r--src/plugins/platforms/mirclient/qmirclientscreenobserver.cpp161
-rw-r--r--src/plugins/platforms/mirclient/qmirclienttheme.h57
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.cpp968
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.h118
-rw-r--r--src/plugins/platforms/offscreen/offscreen.pro5
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.cpp14
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.h1
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp117
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration_x11.h12
-rw-r--r--src/plugins/platforms/openwfd/qopenwfdscreen.h1
-rw-r--r--src/plugins/platforms/platforms.pro2
-rw-r--r--src/plugins/platforms/qnx/qnx.pro2
-rw-r--r--src/plugins/platforms/qnx/qqnxforeignwindow.cpp (renamed from src/plugins/platforms/mirclient/qmirclienttheme.cpp)38
-rw-r--r--src/plugins/platforms/qnx/qqnxforeignwindow.h (renamed from src/plugins/platforms/mirclient/qmirclientdebugextension.h)34
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp34
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.h7
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp58
-rw-r--r--src/plugins/platforms/qnx/qqnxscreentraits.h127
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp184
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h12
-rw-r--r--src/plugins/platforms/vnc/qvnc.cpp10
-rw-r--r--src/plugins/platforms/vnc/qvnc_p.h2
-rw-r--r--src/plugins/platforms/vnc/qvncscreen.cpp2
-rw-r--r--src/plugins/platforms/vnc/qvncscreen.h6
-rw-r--r--src/plugins/platforms/wasm/qtloader.js101
-rw-r--r--src/plugins/platforms/wasm/qtlogo.svg29
-rw-r--r--src/plugins/platforms/wasm/qwasmbackingstore.cpp6
-rw-r--r--src/plugins/platforms/wasm/qwasmbackingstore.h1
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.cpp229
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.h60
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp63
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.h10
-rw-r--r--src/plugins/platforms/wasm/qwasmcursor.cpp22
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp733
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.h184
-rw-r--r--src/plugins/platforms/wasm/qwasmfontdatabase.cpp8
-rw-r--r--src/plugins/platforms/wasm/qwasmfontdatabase.h1
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp205
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.h34
-rw-r--r--src/plugins/platforms/wasm/qwasmoffscreensurface.cpp41
-rw-r--r--src/plugins/platforms/wasm/qwasmoffscreensurface.h49
-rw-r--r--src/plugins/platforms/wasm/qwasmopenglcontext.cpp81
-rw-r--r--src/plugins/platforms/wasm/qwasmopenglcontext.h8
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp92
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.h25
-rw-r--r--src/plugins/platforms/wasm/qwasmservices.cpp45
-rw-r--r--src/plugins/platforms/wasm/qwasmservices.h45
-rw-r--r--src/plugins/platforms/wasm/qwasmtheme.cpp15
-rw-r--r--src/plugins/platforms/wasm/qwasmtheme.h3
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp10
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.h1
-rw-r--r--src/plugins/platforms/wasm/wasm.pro13
-rw-r--r--src/plugins/platforms/wasm/wasm_shell.html26
-rw-r--r--src/plugins/platforms/windows/qwin10helpers.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.h6
-rw-r--r--src/plugins/platforms/windows/qwindowscombase.h2
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp36
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h6
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp30
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h12
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h5
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp24
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp28
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp16
-rw-r--r--src/plugins/platforms/windows/qwindowsopenglcontext.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp42
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsservices.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowssessionmanager.h2
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp84
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.h4
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp35
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsthreadpoolrunner.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.h2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp112
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h48
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp6
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp6
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/uiautomation.pri3
-rw-r--r--src/plugins/platforms/windows/windows.pri16
-rw-r--r--src/plugins/platforms/windows/windows.pro3
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp8
-rw-r--r--src/plugins/platforms/winrt/winrt.pro3
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationplugin.h2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp4
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp4
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h2
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp2
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qt_x11_p.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp17
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp23
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp34
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h14
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_basic.cpp14
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_basic.h7
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_screens.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp729
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h36
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp10
-rw-r--r--src/plugins/platforms/xcb/qxcbobject.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbsessionmanager.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp37
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h2
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro4
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h4
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine_p.h4
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintersupport.h2
-rw-r--r--src/plugins/printsupport/windows/windows.pro3
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp12
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc.cpp2
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc_p.h4
-rw-r--r--src/plugins/sqldrivers/psql/main.cpp8
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp298
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql_p.h18
-rw-r--r--src/plugins/sqldrivers/sqlite/qsql_sqlite_p.h4
-rw-r--r--src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp1
-rw-r--r--src/plugins/sqldrivers/sqlite2/smain.cpp1
-rw-r--r--src/plugins/sqldrivers/tds/main.cpp1
-rw-r--r--src/plugins/sqldrivers/tds/qsql_tds.cpp2
-rw-r--r--src/plugins/styles/android/qandroidstyle_p.h2
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm111
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p.h2
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h119
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle.cpp12
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle_p.h2
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle.cpp26
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle_p.h2
-rw-r--r--src/plugins/styles/windowsvista/windowsvista.pro2
-rw-r--r--src/printsupport/dialogs/qabstractprintdialog.h6
-rw-r--r--src/printsupport/dialogs/qpagesetupdialog_unix.cpp26
-rw-r--r--src/printsupport/dialogs/qprintdialog_unix.cpp14
-rw-r--r--src/printsupport/dialogs/qprintpreviewdialog.cpp16
-rw-r--r--src/printsupport/doc/src/dontdocument.qdoc30
-rw-r--r--src/printsupport/kernel/kernel.pri5
-rw-r--r--src/printsupport/kernel/qcups.cpp4
-rw-r--r--src/printsupport/kernel/qplatformprintdevice.cpp26
-rw-r--r--src/printsupport/kernel/qprintdevice_p.h2
-rw-r--r--src/printsupport/kernel/qprinter.cpp2
-rw-r--r--src/printsupport/kernel/qprinterinfo.cpp29
-rw-r--r--src/printsupport/kernel/qprinterinfo.h3
-rw-r--r--src/printsupport/widgets/qcupsjobwidget_p.h2
-rw-r--r--src/sql/doc/snippets/code/doc_src_sql-driver.qdoc13
-rw-r--r--src/sql/doc/snippets/sqldatabase/sqldatabase.cpp4
-rw-r--r--src/sql/doc/src/dontdocument.qdoc30
-rw-r--r--src/sql/doc/src/sql-driver.qdoc21
-rw-r--r--src/sql/kernel/qsqldatabase.cpp46
-rw-r--r--src/sql/kernel/qsqldatabase.h1
-rw-r--r--src/sql/kernel/qsqldriver.cpp16
-rw-r--r--src/sql/kernel/qsqlerror.cpp2
-rw-r--r--src/sql/kernel/qsqlerror.h6
-rw-r--r--src/sql/kernel/qsqlquery.cpp4
-rw-r--r--src/sql/kernel/qsqlrecord.cpp2
-rw-r--r--src/sql/kernel/qsqlresult.cpp1
-rw-r--r--src/sql/models/qsqlquerymodel_p.h2
-rw-r--r--src/sql/models/qsqlrelationaldelegate.h2
-rw-r--r--src/sql/models/qsqlrelationaltablemodel.cpp10
-rw-r--r--src/sql/models/qsqlrelationaltablemodel.h4
-rw-r--r--src/sql/models/qsqltablemodel.cpp11
-rw-r--r--src/sql/models/qsqltablemodel.h3
-rw-r--r--src/sql/models/qsqltablemodel_p.h2
-rw-r--r--src/src.pro20
-rw-r--r--src/testlib/configure.json12
-rw-r--r--src/testlib/doc/qttestlib.qdocconf2
-rw-r--r--src/testlib/doc/src/dontdocument.qdoc32
-rw-r--r--src/testlib/doc/src/qttest-index.qdoc10
-rw-r--r--src/testlib/qabstractitemmodeltester.h4
-rw-r--r--src/testlib/qabstracttestlogger_p.h6
-rw-r--r--src/testlib/qbenchmark.cpp2
-rw-r--r--src/testlib/qbenchmark_p.h8
-rw-r--r--src/testlib/qbenchmarkevent.cpp4
-rw-r--r--src/testlib/qbenchmarkevent_p.h4
-rw-r--r--src/testlib/qbenchmarkvalgrind.cpp22
-rw-r--r--src/testlib/qbenchmarkvalgrind_p.h2
-rw-r--r--src/testlib/qcsvbenchmarklogger_p.h4
-rw-r--r--src/testlib/qplaintestlogger_p.h6
-rw-r--r--src/testlib/qsignaldumper.cpp11
-rw-r--r--src/testlib/qsignalspy.h2
-rw-r--r--src/testlib/qsignalspy.qdoc4
-rw-r--r--src/testlib/qtaptestlogger.cpp24
-rw-r--r--src/testlib/qtaptestlogger_p.h4
-rw-r--r--src/testlib/qteamcitylogger.cpp2
-rw-r--r--src/testlib/qteamcitylogger_p.h4
-rw-r--r--src/testlib/qtest.h85
-rw-r--r--src/testlib/qtestblacklist.cpp42
-rw-r--r--src/testlib/qtestblacklist_p.h1
-rw-r--r--src/testlib/qtestcase.cpp326
-rw-r--r--src/testlib/qtestcase.h25
-rw-r--r--src/testlib/qtestcoreelement_p.h10
-rw-r--r--src/testlib/qtestcorelist_p.h25
-rw-r--r--src/testlib/qtestlog.cpp7
-rw-r--r--src/testlib/qxmltestlogger_p.h4
-rw-r--r--src/testlib/qxunittestlogger_p.h4
-rw-r--r--src/testlib/selfcover.pri28
-rw-r--r--src/testlib/testlib.pro10
-rw-r--r--src/tools/androiddeployqt/main.cpp185
-rw-r--r--src/tools/androidtestrunner/androidtestrunner.pro13
-rw-r--r--src/tools/androidtestrunner/main.cpp490
-rw-r--r--src/tools/bootstrap/bootstrap.pro26
-rw-r--r--src/tools/moc/generator.cpp16
-rw-r--r--src/tools/moc/generator.h2
-rw-r--r--src/tools/moc/moc.cpp80
-rw-r--r--src/tools/moc/moc.h76
-rw-r--r--src/tools/moc/parser.h6
-rwxr-xr-xsrc/tools/moc/util/generate.sh2
-rw-r--r--src/tools/moc/util/generate_keywords.pro1
-rw-r--r--src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp1
-rw-r--r--src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp333
-rw-r--r--src/tools/qfloat16-tables/qfloat16-tables.pro9
-rw-r--r--src/tools/qlalr/cppgenerator.cpp194
-rw-r--r--src/tools/qlalr/dotgraph.cpp22
-rw-r--r--src/tools/qlalr/lalr.cpp22
-rw-r--r--src/tools/qlalr/lalr.g12
-rw-r--r--src/tools/qlalr/lalr.h94
-rw-r--r--src/tools/qlalr/main.cpp24
-rw-r--r--src/tools/qlalr/parsetable.cpp26
-rw-r--r--src/tools/qlalr/recognizer.cpp12
-rw-r--r--src/tools/qvkgen/qvkgen.cpp45
-rw-r--r--src/tools/rcc/main.cpp56
-rw-r--r--src/tools/rcc/rcc.cpp465
-rw-r--r--src/tools/rcc/rcc.h30
-rw-r--r--src/tools/rcc/rcc.pro11
-rw-r--r--src/tools/tracegen/etw.cpp1
-rw-r--r--src/tools/tracegen/helpers.cpp2
-rw-r--r--src/tools/tracegen/lttng.cpp1
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.cpp16
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.h14
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp1243
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.h33
-rw-r--r--src/tools/uic/customwidgetsinfo.cpp39
-rw-r--r--src/tools/uic/customwidgetsinfo.h10
-rw-r--r--src/tools/uic/databaseinfo.cpp9
-rw-r--r--src/tools/uic/databaseinfo.h6
-rw-r--r--src/tools/uic/driver.cpp180
-rw-r--r--src/tools/uic/driver.h71
-rw-r--r--src/tools/uic/main.cpp14
-rw-r--r--src/tools/uic/python/python.pri8
-rw-r--r--src/tools/uic/python/pythonwritedeclaration.cpp73
-rw-r--r--src/tools/uic/python/pythonwritedeclaration.h62
-rw-r--r--src/tools/uic/python/pythonwriteimports.cpp94
-rw-r--r--src/tools/uic/python/pythonwriteimports.h58
-rw-r--r--src/tools/uic/qclass_lib_map.h2
-rw-r--r--src/tools/uic/shared/language.cpp426
-rw-r--r--src/tools/uic/shared/language.h208
-rw-r--r--src/tools/uic/shared/shared.pri5
-rw-r--r--src/tools/uic/treewalker.h6
-rw-r--r--src/tools/uic/uic.cpp160
-rw-r--r--src/tools/uic/uic.h10
-rw-r--r--src/tools/uic/uic.pri1
-rw-r--r--src/tools/uic/uic.pro2
-rw-r--r--src/tools/uic/utils.h49
-rw-r--r--src/widgets/accessible/qaccessiblemenu.cpp13
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp4
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp22
-rw-r--r--src/widgets/dialogs/qdialog.cpp48
-rw-r--r--src/widgets/dialogs/qdialog.h15
-rw-r--r--src/widgets/dialogs/qdialog_p.h20
-rw-r--r--src/widgets/dialogs/qerrormessage.cpp4
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp232
-rw-r--r--src/widgets/dialogs/qfiledialog.h29
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h30
-rw-r--r--src/widgets/dialogs/qfileinfogatherer.cpp16
-rw-r--r--src/widgets/dialogs/qfileinfogatherer_p.h2
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp7
-rw-r--r--src/widgets/dialogs/qfilesystemmodel_p.h12
-rw-r--r--src/widgets/dialogs/qfontdialog.cpp2
-rw-r--r--src/widgets/dialogs/qfscompleter_p.h4
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp27
-rw-r--r--src/widgets/dialogs/qmessagebox.h4
-rw-r--r--src/widgets/dialogs/qprogressdialog.cpp10
-rw-r--r--src/widgets/dialogs/qsidebar.cpp2
-rw-r--r--src/widgets/dialogs/qsidebar_p.h6
-rw-r--r--src/widgets/dialogs/qwizard.cpp40
-rw-r--r--src/widgets/dialogs/qwizard.h4
-rw-r--r--src/widgets/dialogs/qwizard_win.cpp26
-rw-r--r--src/widgets/dialogs/qwizard_win_p.h10
-rw-r--r--src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc16
-rw-r--r--src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp11
-rw-r--r--src/widgets/doc/snippets/code/src_gui_itemviews_qdatawidgetmapper.cpp8
-rw-r--r--src/widgets/doc/snippets/code/src_gui_kernel_qapplication.cpp12
-rw-r--r--src/widgets/doc/snippets/code/src_gui_widgets_qmenu.cpp2
-rw-r--r--src/widgets/doc/snippets/dialogs/dialogs.cpp9
-rw-r--r--src/widgets/doc/snippets/dockwidgets/mainwindow.cpp8
-rw-r--r--src/widgets/doc/snippets/mdiareasnippets.cpp4
-rw-r--r--src/widgets/doc/snippets/qlistview-dnd/mainwindow.cpp3
-rw-r--r--src/widgets/doc/snippets/qlistview-dnd/model.cpp8
-rw-r--r--src/widgets/doc/snippets/qlistwidget-dnd/mainwindow.cpp4
-rw-r--r--src/widgets/doc/snippets/qlistwidget-using/mainwindow.cpp17
-rw-r--r--src/widgets/doc/snippets/qsortfilterproxymodel/main.cpp7
-rw-r--r--src/widgets/doc/snippets/qstackedlayout/main.cpp9
-rw-r--r--src/widgets/doc/snippets/qstackedwidget/main.cpp7
-rw-r--r--src/widgets/doc/snippets/qtablewidget-resizing/mainwindow.cpp8
-rw-r--r--src/widgets/doc/snippets/qtablewidget-using/mainwindow.cpp20
-rw-r--r--src/widgets/doc/snippets/qtreewidget-using/mainwindow.cpp35
-rw-r--r--src/widgets/doc/snippets/qtreewidgetitemiterator-using/mainwindow.cpp21
-rw-r--r--src/widgets/doc/snippets/reading-selections/window.cpp18
-rw-r--r--src/widgets/doc/snippets/timeline/main.cpp4
-rw-r--r--src/widgets/doc/snippets/updating-selections/window.cpp17
-rw-r--r--src/widgets/doc/src/dontdocument.qdoc30
-rw-r--r--src/widgets/doc/src/model-view-programming.qdoc21
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc18
-rw-r--r--src/widgets/effects/qgraphicseffect_p.h10
-rw-r--r--src/widgets/effects/qpixmapfilter.cpp5
-rw-r--r--src/widgets/effects/qpixmapfilter_p.h8
-rw-r--r--src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp2
-rw-r--r--src/widgets/graphicsview/qgraphicsanchorlayout_p.h12
-rw-r--r--src/widgets/graphicsview/qgraphicsgridlayout.cpp11
-rw-r--r--src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h4
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp105
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.h8
-rw-r--r--src/widgets/graphicsview/qgraphicsitem_p.h28
-rw-r--r--src/widgets/graphicsview/qgraphicsitemanimation.cpp35
-rw-r--r--src/widgets/graphicsview/qgraphicsitemanimation.h8
-rw-r--r--src/widgets/graphicsview/qgraphicslayout.h2
-rw-r--r--src/widgets/graphicsview/qgraphicslayout_p.h4
-rw-r--r--src/widgets/graphicsview/qgraphicslayoutitem.cpp14
-rw-r--r--src/widgets/graphicsview/qgraphicslayoutitem.h2
-rw-r--r--src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp8
-rw-r--r--src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h6
-rw-r--r--src/widgets/graphicsview/qgraphicsproxywidget.cpp4
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp64
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.h8
-rw-r--r--src/widgets/graphicsview/qgraphicsscene_p.h8
-rw-r--r--src/widgets/graphicsview/qgraphicsscenebsptreeindex_p.h4
-rw-r--r--src/widgets/graphicsview/qgraphicssceneevent.cpp4
-rw-r--r--src/widgets/graphicsview/qgraphicssceneindex_p.h6
-rw-r--r--src/widgets/graphicsview/qgraphicsscenelinearindex_p.h2
-rw-r--r--src/widgets/graphicsview/qgraphicstransform_p.h2
-rw-r--r--src/widgets/graphicsview/qgraphicsview.cpp2
-rw-r--r--src/widgets/graphicsview/qgraphicswidget.cpp129
-rw-r--r--src/widgets/graphicsview/qgraphicswidget.h2
-rw-r--r--src/widgets/graphicsview/qgraphicswidget_p.cpp26
-rw-r--r--src/widgets/graphicsview/qgraphicswidget_p.h9
-rw-r--r--src/widgets/graphicsview/qsimplex_p.cpp2
-rw-r--r--src/widgets/graphicsview/qsimplex_p.h4
-rw-r--r--src/widgets/itemviews/qabstractitemdelegate.cpp6
-rw-r--r--src/widgets/itemviews/qabstractitemdelegate.h3
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp32
-rw-r--r--src/widgets/itemviews/qabstractitemview.h10
-rw-r--r--src/widgets/itemviews/qcolumnview.cpp2
-rw-r--r--src/widgets/itemviews/qcolumnview_p.h5
-rw-r--r--src/widgets/itemviews/qcolumnviewgrip_p.h6
-rw-r--r--src/widgets/itemviews/qdatawidgetmapper.cpp1
-rw-r--r--src/widgets/itemviews/qdirmodel.cpp3
-rw-r--r--src/widgets/itemviews/qheaderview.cpp45
-rw-r--r--src/widgets/itemviews/qheaderview_p.h2
-rw-r--r--src/widgets/itemviews/qitemdelegate.cpp42
-rw-r--r--src/widgets/itemviews/qitemdelegate.h5
-rw-r--r--src/widgets/itemviews/qitemeditorfactory.cpp16
-rw-r--r--src/widgets/itemviews/qitemeditorfactory.h4
-rw-r--r--src/widgets/itemviews/qlistview.cpp35
-rw-r--r--src/widgets/itemviews/qlistview_p.h10
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp188
-rw-r--r--src/widgets/itemviews/qlistwidget.h46
-rw-r--r--src/widgets/itemviews/qlistwidget_p.h4
-rw-r--r--src/widgets/itemviews/qstyleditemdelegate.cpp4
-rw-r--r--src/widgets/itemviews/qtableview.cpp108
-rw-r--r--src/widgets/itemviews/qtableview.h6
-rw-r--r--src/widgets/itemviews/qtableview_p.h12
-rw-r--r--src/widgets/itemviews/qtablewidget.cpp126
-rw-r--r--src/widgets/itemviews/qtablewidget.h33
-rw-r--r--src/widgets/itemviews/qtablewidget_p.h3
-rw-r--r--src/widgets/itemviews/qtreeview.cpp131
-rw-r--r--src/widgets/itemviews/qtreeview.h6
-rw-r--r--src/widgets/itemviews/qtreeview_p.h6
-rw-r--r--src/widgets/itemviews/qtreewidget.cpp274
-rw-r--r--src/widgets/itemviews/qtreewidget.h65
-rw-r--r--src/widgets/itemviews/qtreewidget_p.h8
-rw-r--r--src/widgets/itemviews/qtreewidgetitemiterator.cpp8
-rw-r--r--src/widgets/kernel/kernel.pri7
-rw-r--r--src/widgets/kernel/mac.pri5
-rw-r--r--src/widgets/kernel/qaction.cpp5
-rw-r--r--src/widgets/kernel/qactiongroup.cpp100
-rw-r--r--src/widgets/kernel/qactiongroup.h11
-rw-r--r--src/widgets/kernel/qapplication.cpp35
-rw-r--r--src/widgets/kernel/qapplication.h8
-rw-r--r--src/widgets/kernel/qapplication_p.h8
-rw-r--r--src/widgets/kernel/qdesktopwidget.cpp36
-rw-r--r--src/widgets/kernel/qdesktopwidget.h2
-rw-r--r--src/widgets/kernel/qformlayout.cpp17
-rw-r--r--src/widgets/kernel/qgesture_p.h2
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp62
-rw-r--r--src/widgets/kernel/qgridlayout.cpp6
-rw-r--r--src/widgets/kernel/qlayout.cpp45
-rw-r--r--src/widgets/kernel/qlayout.h8
-rw-r--r--src/widgets/kernel/qlayout_p.h2
-rw-r--r--src/widgets/kernel/qlayoutengine_p.h6
-rw-r--r--src/widgets/kernel/qlayoutitem.cpp29
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp11
-rw-r--r--src/widgets/kernel/qsizepolicy.cpp4
-rw-r--r--src/widgets/kernel/qsizepolicy.h56
-rw-r--r--src/widgets/kernel/qstackedlayout.cpp12
-rw-r--r--src/widgets/kernel/qt_widgets_pch.h38
-rw-r--r--src/widgets/kernel/qtooltip.cpp6
-rw-r--r--src/widgets/kernel/qtooltip.h2
-rw-r--r--src/widgets/kernel/qwhatsthis.cpp6
-rw-r--r--src/widgets/kernel/qwhatsthis.h2
-rw-r--r--src/widgets/kernel/qwidget.cpp197
-rw-r--r--src/widgets/kernel/qwidget.h12
-rw-r--r--src/widgets/kernel/qwidget_p.h66
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp276
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h15
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp17
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h4
-rw-r--r--src/widgets/kernel/qwindowcontainer_p.h2
-rw-r--r--src/widgets/kernel/win.pri5
-rw-r--r--src/widgets/statemachine/qbasickeyeventtransition_p.h8
-rw-r--r--src/widgets/statemachine/qbasicmouseeventtransition_p.h6
-rw-r--r--src/widgets/styles/qcommonstyle.cpp102
-rw-r--r--src/widgets/styles/qcommonstyle_p.h2
-rw-r--r--src/widgets/styles/qdrawutil.cpp2
-rw-r--r--src/widgets/styles/qfusionstyle.cpp76
-rw-r--r--src/widgets/styles/qfusionstyle_p.h18
-rw-r--r--src/widgets/styles/qfusionstyle_p_p.h2
-rw-r--r--src/widgets/styles/qpixmapstyle_p.h2
-rw-r--r--src/widgets/styles/qproxystyle_p.h2
-rw-r--r--src/widgets/styles/qstyle.cpp14
-rw-r--r--src/widgets/styles/qstyle.h36
-rw-r--r--src/widgets/styles/qstyle_p.h4
-rw-r--r--src/widgets/styles/qstylehelper_p.h4
-rw-r--r--src/widgets/styles/qstyleoption.cpp8
-rw-r--r--src/widgets/styles/qstyleoption.h23
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp75
-rw-r--r--src/widgets/styles/qstylesheetstyle_p.h34
-rw-r--r--src/widgets/styles/qwindowsstyle.cpp75
-rw-r--r--src/widgets/styles/qwindowsstyle_p.h24
-rw-r--r--src/widgets/styles/qwindowsstyle_p_p.h4
-rw-r--r--src/widgets/util/qcompleter_p.h3
-rw-r--r--src/widgets/util/qflickgesture.cpp2
-rw-r--r--src/widgets/util/qflickgesture_p.h5
-rw-r--r--src/widgets/util/qsystemtrayicon.cpp2
-rw-r--r--src/widgets/util/qundostack.cpp12
-rw-r--r--src/widgets/util/qundostack_p.h4
-rw-r--r--src/widgets/util/qundoview.cpp2
-rw-r--r--src/widgets/widgets.pro2
-rw-r--r--src/widgets/widgets/qabstractscrollarea.cpp10
-rw-r--r--src/widgets/widgets/qabstractslider_p.h2
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp34
-rw-r--r--src/widgets/widgets/qabstractspinbox_p.h2
-rw-r--r--src/widgets/widgets/qbuttongroup.cpp8
-rw-r--r--src/widgets/widgets/qcalendarwidget.cpp23
-rw-r--r--src/widgets/widgets/qcombobox.cpp71
-rw-r--r--src/widgets/widgets/qcombobox.h24
-rw-r--r--src/widgets/widgets/qcombobox_p.h7
-rw-r--r--src/widgets/widgets/qcommandlinkbutton.h6
-rw-r--r--src/widgets/widgets/qdatetimeedit.cpp21
-rw-r--r--src/widgets/widgets/qdatetimeedit_p.h4
-rw-r--r--src/widgets/widgets/qdialogbuttonbox.cpp15
-rw-r--r--src/widgets/widgets/qdockarealayout_p.h2
-rw-r--r--src/widgets/widgets/qdockwidget.cpp49
-rw-r--r--src/widgets/widgets/qdockwidget_p.h37
-rw-r--r--src/widgets/widgets/qfontcombobox.cpp16
-rw-r--r--src/widgets/widgets/qlabel.cpp2
-rw-r--r--src/widgets/widgets/qlineedit.cpp14
-rw-r--r--src/widgets/widgets/qlineedit_p.cpp13
-rw-r--r--src/widgets/widgets/qlineedit_p.h8
-rw-r--r--src/widgets/widgets/qmainwindow.cpp12
-rw-r--r--src/widgets/widgets/qmainwindow.h6
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp35
-rw-r--r--src/widgets/widgets/qmainwindowlayout_p.h8
-rw-r--r--src/widgets/widgets/qmdiarea.cpp42
-rw-r--r--src/widgets/widgets/qmdiarea_p.h4
-rw-r--r--src/widgets/widgets/qmdisubwindow.cpp14
-rw-r--r--src/widgets/widgets/qmdisubwindow_p.h8
-rw-r--r--src/widgets/widgets/qmenu.cpp60
-rw-r--r--src/widgets/widgets/qmenu.h4
-rw-r--r--src/widgets/widgets/qmenu_p.h16
-rw-r--r--src/widgets/widgets/qmenubar.cpp4
-rw-r--r--src/widgets/widgets/qmenubar_p.h4
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp26
-rw-r--r--src/widgets/widgets/qplaintextedit.h4
-rw-r--r--src/widgets/widgets/qpushbutton.cpp4
-rw-r--r--src/widgets/widgets/qscrollarea.cpp2
-rw-r--r--src/widgets/widgets/qscrollarea_p.h2
-rw-r--r--src/widgets/widgets/qspinbox.cpp51
-rw-r--r--src/widgets/widgets/qspinbox.h8
-rw-r--r--src/widgets/widgets/qsplitter.cpp10
-rw-r--r--src/widgets/widgets/qsplitter.h4
-rw-r--r--src/widgets/widgets/qsplitter_p.h6
-rw-r--r--src/widgets/widgets/qstackedwidget.cpp6
-rw-r--r--src/widgets/widgets/qstatusbar.cpp6
-rw-r--r--src/widgets/widgets/qtabbar.cpp9
-rw-r--r--src/widgets/widgets/qtabbar_p.h4
-rw-r--r--src/widgets/widgets/qtabwidget.cpp8
-rw-r--r--src/widgets/widgets/qtextbrowser.cpp110
-rw-r--r--src/widgets/widgets/qtextbrowser.h11
-rw-r--r--src/widgets/widgets/qtextedit.cpp113
-rw-r--r--src/widgets/widgets/qtextedit.h16
-rw-r--r--src/widgets/widgets/qtextedit_p.h3
-rw-r--r--src/widgets/widgets/qtoolbar.cpp40
-rw-r--r--src/widgets/widgets/qtoolbar.h8
-rw-r--r--src/widgets/widgets/qtoolbar_p.h2
-rw-r--r--src/widgets/widgets/qtoolbararealayout.cpp8
-rw-r--r--src/widgets/widgets/qtoolbararealayout_p.h4
-rw-r--r--src/widgets/widgets/qtoolbarlayout.cpp45
-rw-r--r--src/widgets/widgets/qtoolbarlayout_p.h2
-rw-r--r--src/widgets/widgets/qtoolbox.cpp101
-rw-r--r--src/widgets/widgets/qtoolbutton.cpp5
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol_p.h4
-rw-r--r--src/widgets/widgets/qwidgetresizehandler_p.h4
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp93
-rw-r--r--src/widgets/widgets/qwidgettextcontrol_p.h33
-rw-r--r--src/widgets/widgets/qwidgettextcontrol_p_p.h8
-rw-r--r--src/winmain/winmain.pro2
-rw-r--r--src/xml/doc/snippets/code/src_xml_dom_qdom.cpp8
-rw-r--r--src/xml/doc/src/dontdocument.qdoc30
-rw-r--r--src/xml/dom/qdom.cpp258
-rw-r--r--src/xml/sax/qxml.cpp157
-rw-r--r--src/xml/sax/qxml.h8
-rw-r--r--src/xml/sax/qxml_p.h2
-rw-r--r--sync.profile1
-rwxr-xr-xtests/auto/android/runtests_androiddeployqt.pl550
-rw-r--r--tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp24
-rw-r--r--tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp57
-rw-r--r--tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp40
-rw-r--r--tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp11
-rw-r--r--tests/auto/corelib/corelib.pro1
-rw-r--r--tests/auto/corelib/global/qflags/tst_qflags.cpp11
-rw-r--r--tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp161
-rw-r--r--tests/auto/corelib/global/qglobal/qglobal.c2
-rw-r--r--tests/auto/corelib/global/qglobal/qglobal.pro1
-rw-r--r--tests/auto/corelib/global/qglobal/tst_qglobal.cpp44
-rw-r--r--tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp18
-rw-r--r--tests/auto/corelib/global/qlogging/tst_qlogging.cpp22
-rw-r--r--tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp65
-rw-r--r--tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp4
-rw-r--r--tests/auto/corelib/io/largefile/tst_largefile.cpp5
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp8
-rw-r--r--tests/auto/corelib/io/qdir/tst_qdir.cpp32
-rw-r--r--tests/auto/corelib/io/qfile/test.pro2
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp4
-rw-r--r--tests/auto/corelib/io/qfileinfo/qfileinfo.pro2
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp170
-rw-r--r--tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp12
-rw-r--r--tests/auto/corelib/io/qlockfile/tst_qlockfile.pro2
-rw-r--r--tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp6
-rw-r--r--tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro2
-rw-r--r--tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro2
-rw-r--r--tests/auto/corelib/io/qprocess/tst_qprocess.cpp25
-rw-r--r--tests/auto/corelib/io/qsettings/qsettings.pro2
-rw-r--r--tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp14
-rw-r--r--tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp4
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp159
-rw-r--r--tests/auto/corelib/io/qurlquery/tst_qurlquery.cpp8
-rw-r--r--tests/auto/corelib/itemmodels/itemmodels.pro2
-rw-r--r--tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp16
-rw-r--r--tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp20
-rw-r--r--tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro5
-rw-r--r--tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp823
-rw-r--r--tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp6
-rw-r--r--tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp4
-rw-r--r--tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp12
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp2
-rw-r--r--tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp178
-rw-r--r--tests/auto/corelib/itemmodels/qtransposeproxymodel/qtransposeproxymodel.pro6
-rw-r--r--tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp915
-rw-r--r--tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp24
-rw-r--r--tests/auto/corelib/kernel/qeventloop/qeventloop.pro2
-rw-r--r--tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp6
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp100
-rw-r--r--tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp6
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp46
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h2
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp1640
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp3
-rw-r--r--tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp5
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp175
-rw-r--r--tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp2
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp533
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp12
-rw-r--r--tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp4
-rw-r--r--tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp8
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro1
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/staticplugin/.gitignore3
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp (renamed from src/tools/uic/globaldefs.h)26
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/staticplugin/staticplugin.pro7
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst/tst.pro5
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp38
-rw-r--r--tests/auto/corelib/serialization/json/tst_qtjson.cpp203
-rw-r--r--tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp140
-rw-r--r--tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp301
-rw-r--r--tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp2
-rw-r--r--tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp146
-rw-r--r--tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp30
-rw-r--r--tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp26
-rw-r--r--tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp53
-rw-r--r--tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp202
-rw-r--r--tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp176
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp67
-rw-r--r--tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp3
-rw-r--r--tests/auto/corelib/thread/qmutex/tst_qmutex.cpp24
-rw-r--r--tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp27
-rw-r--r--tests/auto/corelib/thread/qthread/tst_qthread.cpp32
-rw-r--r--tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp8
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp85
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp12
-rw-r--r--tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp32
-rw-r--r--tests/auto/corelib/time/qdate/.gitignore (renamed from tests/auto/corelib/tools/qdate/.gitignore)0
-rw-r--r--tests/auto/corelib/time/qdate/qdate.pro (renamed from tests/auto/corelib/tools/qdate/qdate.pro)2
-rw-r--r--tests/auto/corelib/time/qdate/tst_qdate.cpp (renamed from tests/auto/corelib/tools/qdate/tst_qdate.cpp)200
-rw-r--r--tests/auto/corelib/time/qdatetime/.gitignore (renamed from tests/auto/corelib/tools/qdatetime/.gitignore)0
-rw-r--r--tests/auto/corelib/time/qdatetime/BLACKLIST (renamed from tests/auto/corelib/tools/qdatetime/BLACKLIST)0
-rw-r--r--tests/auto/corelib/time/qdatetime/qdatetime.pro (renamed from tests/auto/corelib/tools/qdatetime/qdatetime.pro)0
-rw-r--r--tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp (renamed from tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp)74
-rw-r--r--tests/auto/corelib/time/qdatetime/tst_qdatetime_mac.mm (renamed from tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm)0
-rw-r--r--tests/auto/corelib/time/qtime/.gitignore (renamed from tests/auto/corelib/tools/qtime/.gitignore)0
-rw-r--r--tests/auto/corelib/time/qtime/qtime.pro (renamed from tests/auto/corelib/tools/qtime/qtime.pro)0
-rw-r--r--tests/auto/corelib/time/qtime/tst_qtime.cpp (renamed from tests/auto/corelib/tools/qtime/tst_qtime.cpp)5
-rw-r--r--tests/auto/corelib/time/qtimezone/BLACKLIST (renamed from tests/auto/corelib/tools/qtimezone/BLACKLIST)0
-rw-r--r--tests/auto/corelib/time/qtimezone/qtimezone.pro (renamed from tests/auto/corelib/tools/qtimezone/qtimezone.pro)0
-rw-r--r--tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp (renamed from tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp)11
-rw-r--r--tests/auto/corelib/time/qtimezone/tst_qtimezone_darwin.mm (renamed from tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm)0
-rw-r--r--tests/auto/corelib/time/time.pro6
-rw-r--r--tests/auto/corelib/tools/collections/tst_collections.cpp95
-rw-r--r--tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp723
-rw-r--r--tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp22
-rw-r--r--tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp46
-rw-r--r--tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp35
-rw-r--r--tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp40
-rw-r--r--tests/auto/corelib/tools/qcollator/tst_qcollator.cpp6
-rw-r--r--tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp101
-rw-r--r--tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp4
-rw-r--r--tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp39
-rw-r--r--tests/auto/corelib/tools/qhash/tst_qhash.cpp4
-rw-r--r--tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp36
-rw-r--r--tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp42
-rw-r--r--tests/auto/corelib/tools/qline/tst_qline.cpp2
-rw-r--r--tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp2
-rw-r--r--tests/auto/corelib/tools/qlist/tst_qlist.cpp12
-rw-r--r--tests/auto/corelib/tools/qlocale/tst_qlocale.cpp21
-rw-r--r--tests/auto/corelib/tools/qmap/tst_qmap.cpp4
-rw-r--r--tests/auto/corelib/tools/qoffsetstringarray/qoffsetstringarray.pro6
-rw-r--r--tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp121
-rw-r--r--tests/auto/corelib/tools/qpair/qpair.pro3
-rw-r--r--tests/auto/corelib/tools/qpair/tst_qpair.cpp30
-rw-r--r--tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp42
-rw-r--r--tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp13
-rw-r--r--tests/auto/corelib/tools/qset/tst_qset.cpp12
-rw-r--r--tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp179
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp152
-rw-r--r--tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp566
-rw-r--r--tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp106
-rw-r--r--tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp6
-rw-r--r--tests/auto/corelib/tools/qstringview/tst_qstringview.cpp43
-rw-r--r--tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp4
-rw-r--r--tests/auto/corelib/tools/qvector/tst_qvector.cpp73
-rw-r--r--tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp19
-rw-r--r--tests/auto/corelib/tools/tools.pro6
-rw-r--r--tests/auto/dbus/qdbusservicewatcher/tst_qdbusservicewatcher.cpp137
-rw-r--r--tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp4
-rw-r--r--tests/auto/gui/gui.pro1
-rw-r--r--tests/auto/gui/image/qimage/qimage.pro2
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp48
-rw-r--r--tests/auto/gui/image/qimagereader/tst_qimagereader.cpp2
-rw-r--r--tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp6
-rw-r--r--tests/auto/gui/image/qpixmap/qpixmap.pro2
-rw-r--r--tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp4
-rw-r--r--tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp12
-rw-r--r--tests/auto/gui/kernel/noqteventloop/noqteventloop.pro2
-rw-r--r--tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp2
-rw-r--r--tests/auto/gui/kernel/qguiapplication/qguiapplication.pro1
-rw-r--r--tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp54
-rw-r--r--tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp46
-rw-r--r--tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp2
-rw-r--r--tests/auto/gui/kernel/qpalette/tst_qpalette.cpp46
-rw-r--r--tests/auto/gui/kernel/qwindow/qwindow.pro2
-rw-r--r--tests/auto/gui/painting/painting.pro1
-rw-r--r--tests/auto/gui/painting/qbrush/tst_qbrush.cpp6
-rw-r--r--tests/auto/gui/painting/qcolor/tst_qcolor.cpp220
-rw-r--r--tests/auto/gui/painting/qcolorspace/qcolorspace.pro9
-rw-r--r--tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpgbin0 -> 30900 bytes
-rw-r--r--tests/auto/gui/painting/qcolorspace/resources/sRGB2014.iccbin0 -> 3024 bytes
-rw-r--r--tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp361
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp20
-rw-r--r--tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp43
-rw-r--r--tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp13
-rw-r--r--tests/auto/gui/painting/qpen/tst_qpen.cpp8
-rw-r--r--tests/auto/gui/painting/qregion/tst_qregion.cpp55
-rw-r--r--tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp6
-rw-r--r--tests/auto/gui/rhi/qrhi/data/texture.frag12
-rw-r--r--tests/auto/gui/rhi/qrhi/data/texture.vert18
-rw-r--r--tests/auto/gui/rhi/qrhi/qrhi.pro8
-rw-r--r--tests/auto/gui/rhi/qrhi/qrhi.qrc5
-rw-r--r--tests/auto/gui/rhi/qrhi/tst_qrhi.cpp246
-rw-r--r--tests/auto/gui/rhi/qshader/data/color.vert18
-rw-r--r--tests/auto/gui/rhi/qshader/data/color.vert.qsbbin0 -> 1847 bytes
-rw-r--r--tests/auto/gui/rhi/qshader/data/color_simple.vert.qsbbin0 -> 813 bytes
-rw-r--r--tests/auto/gui/rhi/qshader/qshader.pro8
-rw-r--r--tests/auto/gui/rhi/qshader/qshader.qrc5
-rw-r--r--tests/auto/gui/rhi/qshader/tst_qshader.cpp233
-rw-r--r--tests/auto/gui/rhi/rhi.pro4
-rw-r--r--tests/auto/gui/text/qcssparser/tst_qcssparser.cpp21
-rw-r--r--tests/auto/gui/text/qfont/qfont.pro1
-rw-r--r--tests/auto/gui/text/qfont/testfont.qrc5
-rw-r--r--tests/auto/gui/text/qfont/tst_qfont.cpp141
-rw-r--r--tests/auto/gui/text/qfont/weirdfont.otfbin0 -> 25008 bytes
-rw-r--r--tests/auto/gui/text/qfontcache/tst_qfontcache.cpp47
-rw-r--r--tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp4
-rw-r--r--tests/auto/gui/text/qglyphrun/BLACKLIST1
-rw-r--r--tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp4
-rw-r--r--tests/auto/gui/text/qstatictext/tst_qstatictext.cpp2
-rw-r--r--tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp2
-rw-r--r--tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp56
-rw-r--r--tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp35
-rw-r--r--tests/auto/gui/text/qtextlist/tst_qtextlist.cpp2
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md28
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md17
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro9
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp163
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST3
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md62
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/example.md95
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md12
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md13
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro9
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp464
-rw-r--r--tests/auto/gui/text/text.pro4
-rw-r--r--tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc2
-rw-r--r--tests/auto/gui/util/qtexturefilereader/texturefiles/newlogo.astcbin0 -> 2512 bytes
-rw-r--r--tests/auto/gui/util/qtexturefilereader/texturefiles/newlogo_srgb.astcbin0 -> 2512 bytes
-rw-r--r--tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp70
-rw-r--r--tests/auto/network-settings.h90
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp3
-rw-r--r--tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro2
-rw-r--r--tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp7
-rw-r--r--tests/auto/network/access/qftp/qftp.pro3
-rw-r--r--tests/auto/network/access/qftp/tst_qftp.cpp252
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro3
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp76
-rw-r--r--tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp15
-rw-r--r--tests/auto/network/access/qnetworkreply/certs/qt-test-server-host-network-cacert.pem16
-rw-r--r--tests/auto/network/access/qnetworkreply/test/test.pro2
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp285
-rw-r--r--tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp8
-rw-r--r--tests/auto/network/kernel/qhostaddress/qhostaddress.pro2
-rw-r--r--tests/auto/network/kernel/qhostinfo/qhostinfo.pro2
-rw-r--r--tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp3
-rw-r--r--tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp2
-rw-r--r--tests/auto/network/socket/platformsocketengine/BLACKLIST7
-rw-r--r--tests/auto/network/socket/platformsocketengine/platformsocketengine.pri2
-rw-r--r--tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp6
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/BLACKLIST5
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro5
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp49
-rw-r--r--tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp7
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/BLACKLIST3
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro6
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp42
-rw-r--r--tests/auto/network/socket/qtcpserver/crashingServer/main.cpp4
-rw-r--r--tests/auto/network/socket/qtcpserver/test/test.pro8
-rw-r--r--tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp43
-rw-r--r--tests/auto/network/socket/qtcpsocket/test/test.pro8
-rw-r--r--tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp185
-rw-r--r--tests/auto/network/socket/qudpsocket/test/test.pro6
-rw-r--r--tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp22
-rw-r--r--tests/auto/network/ssl/qocsp/certs/alice.crt24
-rw-r--r--tests/auto/network/ssl/qocsp/certs/alice.key28
-rw-r--r--tests/auto/network/ssl/qocsp/certs/ca1.crt24
-rw-r--r--tests/auto/network/ssl/qocsp/certs/ca1.key28
-rw-r--r--tests/auto/network/ssl/qocsp/certs/infbob.key28
-rw-r--r--tests/auto/network/ssl/qocsp/certs/infbobchain.crt49
-rw-r--r--tests/auto/network/ssl/qocsp/certs/ss1-private.key28
-rw-r--r--tests/auto/network/ssl/qocsp/certs/ss1.crt25
-rw-r--r--tests/auto/network/ssl/qocsp/qocsp.pro15
-rw-r--r--tests/auto/network/ssl/qocsp/tst_qocsp.cpp823
-rw-r--r--tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp10
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pri-1024.derbin0 -> 293 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pri-1024.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pri-2048.derbin0 -> 554 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pri-2048.pem14
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pri-512.derbin0 -> 159 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pri-512.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pub-1024.derbin0 -> 291 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pub-1024.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pub-2048.derbin0 -> 552 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pub-2048.pem14
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pub-512.derbin0 -> 157 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dh-pub-512.pem6
-rwxr-xr-xtests/auto/network/ssl/qsslkey/keys/genkeys.sh21
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes128.pem30
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes192.pem30
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes256.pem30
-rw-r--r--tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp175
-rw-r--r--tests/auto/network/ssl/qsslsocket/BLACKLIST16
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/127-0-0-1-as-CN.crt19
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cert.pem16
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/subjectAltNameIP.crt20
-rw-r--r--tests/auto/network/ssl/qsslsocket/qsslsocket.pro7
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp570
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/BLACKLIST2
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro6
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp21
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro6
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp22
-rw-r--r--tests/auto/network/ssl/ssl.pro2
-rw-r--r--tests/auto/opengl/qglthreads/tst_qglthreads.cpp19
-rw-r--r--tests/auto/other/compiler/tst_compiler.cpp2
-rw-r--r--tests/auto/other/gestures/BLACKLIST1
-rw-r--r--tests/auto/other/lancelot/paintcommands.cpp3
-rw-r--r--tests/auto/other/networkselftest/tst_networkselftest.cpp5
-rw-r--r--tests/auto/other/other.pro5
-rw-r--r--tests/auto/other/qabstractitemmodelutils/dynamictreemodel.cpp17
-rw-r--r--tests/auto/other/qabstractitemmodelutils/dynamictreemodel.h2
-rw-r--r--tests/auto/other/qaccessibility/qaccessibility.pro3
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp1
-rw-r--r--tests/auto/other/qobjectrace/tst_qobjectrace.cpp20
-rw-r--r--tests/auto/other/toolsupport/tst_toolsupport.cpp4
-rw-r--r--tests/auto/other/xkbkeyboard/tst_xkbkeyboard.cpp60
-rw-r--r--tests/auto/other/xkbkeyboard/xkbkeyboard.pro7
-rw-r--r--tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp8
-rw-r--r--tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp33
-rw-r--r--tests/auto/sql/kernel/qsqldatabase/tst_databases.h14
-rw-r--r--tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp147
-rw-r--r--tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp24
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp14
-rw-r--r--tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp2
-rw-r--r--tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp14
-rw-r--r--tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp17
-rw-r--r--tests/auto/testlib/outformat/outformat.pro7
-rw-r--r--tests/auto/testlib/outformat/tst_outformat.cpp71
-rw-r--r--tests/auto/testlib/qabstractitemmodeltester/qabstractitemmodeltester.pro2
-rw-r--r--tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp6
-rw-r--r--tests/auto/testlib/qsignalspy/qsignalspy.pro2
-rw-r--r--tests/auto/testlib/selftests/alive/.gitignore1
-rw-r--r--tests/auto/testlib/selftests/alive/alive.pro8
-rw-r--r--tests/auto/testlib/selftests/alive/qtestalive.cpp147
-rw-r--r--tests/auto/testlib/selftests/assert/assert.pro2
-rw-r--r--tests/auto/testlib/selftests/badxml/badxml.pro2
-rw-r--r--tests/auto/testlib/selftests/benchlibcallgrind/benchlibcallgrind.pro2
-rw-r--r--tests/auto/testlib/selftests/benchlibcallgrind/tst_benchlibcallgrind.cpp4
-rw-r--r--tests/auto/testlib/selftests/benchlibcounting/benchlibcounting.pro2
-rw-r--r--tests/auto/testlib/selftests/benchlibeventcounter/benchlibeventcounter.pro2
-rw-r--r--tests/auto/testlib/selftests/benchliboptions/benchliboptions.pro2
-rw-r--r--tests/auto/testlib/selftests/benchlibtickcounter/benchlibtickcounter.pro2
-rw-r--r--tests/auto/testlib/selftests/benchlibwalltime/benchlibwalltime.pro2
-rw-r--r--tests/auto/testlib/selftests/blacklisted/BLACKLIST14
-rw-r--r--tests/auto/testlib/selftests/blacklisted/blacklisted.pro2
-rw-r--r--tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp24
-rw-r--r--tests/auto/testlib/selftests/cmptest/cmptest.pro2
-rw-r--r--tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp2
-rw-r--r--tests/auto/testlib/selftests/commandlinedata/commandlinedata.pro2
-rw-r--r--tests/auto/testlib/selftests/counting/counting.pro2
-rw-r--r--tests/auto/testlib/selftests/crashes/crashes.pro2
-rw-r--r--tests/auto/testlib/selftests/datatable/datatable.pro2
-rw-r--r--tests/auto/testlib/selftests/datetime/datetime.pro2
-rw-r--r--tests/auto/testlib/selftests/deleteLater/deleteLater.pro2
-rw-r--r--tests/auto/testlib/selftests/deleteLater_noApp/deleteLater_noApp.pro2
-rw-r--r--tests/auto/testlib/selftests/differentexec/differentexec.pro2
-rw-r--r--tests/auto/testlib/selftests/exceptionthrow/exceptionthrow.pro2
-rw-r--r--tests/auto/testlib/selftests/expected_blacklisted.tap8
-rw-r--r--tests/auto/testlib/selftests/expected_crashes_5.txt5
-rw-r--r--tests/auto/testlib/selftests/expected_faildatatype.lightxml22
-rw-r--r--tests/auto/testlib/selftests/expected_faildatatype.tap16
-rw-r--r--tests/auto/testlib/selftests/expected_faildatatype.teamcity8
-rw-r--r--tests/auto/testlib/selftests/expected_faildatatype.txt9
-rw-r--r--tests/auto/testlib/selftests/expected_faildatatype.xml25
-rw-r--r--tests/auto/testlib/selftests/expected_faildatatype.xunitxml18
-rw-r--r--tests/auto/testlib/selftests/expected_failfetchtype.lightxml21
-rw-r--r--tests/auto/testlib/selftests/expected_failfetchtype.tap15
-rw-r--r--tests/auto/testlib/selftests/expected_failfetchtype.teamcity8
-rw-r--r--tests/auto/testlib/selftests/expected_failfetchtype.txt8
-rw-r--r--tests/auto/testlib/selftests/expected_failfetchtype.xml24
-rw-r--r--tests/auto/testlib/selftests/expected_failfetchtype.xunitxml16
-rw-r--r--tests/auto/testlib/selftests/expected_float.lightxml216
-rw-r--r--tests/auto/testlib/selftests/expected_float.tap659
-rw-r--r--tests/auto/testlib/selftests/expected_float.teamcity111
-rw-r--r--tests/auto/testlib/selftests/expected_float.txt135
-rw-r--r--tests/auto/testlib/selftests/expected_float.xml216
-rw-r--r--tests/auto/testlib/selftests/expected_float.xunitxml97
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.lightxml155
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.tap77
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.teamcity47
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.txt94
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.xml155
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.xunitxml128
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.lightxml578
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.tap151
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.teamcity61
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.txt149
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.xml581
-rw-r--r--tests/auto/testlib/selftests/expected_signaldumper.xunitxml284
-rw-r--r--tests/auto/testlib/selftests/expected_testlib.lightxml45
-rw-r--r--tests/auto/testlib/selftests/expected_testlib.tap22
-rw-r--r--tests/auto/testlib/selftests/expected_testlib.teamcity23
-rw-r--r--tests/auto/testlib/selftests/expected_testlib.txt15
-rw-r--r--tests/auto/testlib/selftests/expected_testlib.xml48
-rw-r--r--tests/auto/testlib/selftests/expected_testlib.xunitxml16
-rw-r--r--tests/auto/testlib/selftests/expected_watchdog.lightxml19
-rw-r--r--tests/auto/testlib/selftests/expected_watchdog.tap15
-rw-r--r--tests/auto/testlib/selftests/expected_watchdog.teamcity8
-rw-r--r--tests/auto/testlib/selftests/expected_watchdog.txt8
-rw-r--r--tests/auto/testlib/selftests/expected_watchdog.xml22
-rw-r--r--tests/auto/testlib/selftests/expected_watchdog.xunitxml16
-rw-r--r--tests/auto/testlib/selftests/expectfail/expectfail.pro2
-rw-r--r--tests/auto/testlib/selftests/failcleanup/failcleanup.pro2
-rw-r--r--tests/auto/testlib/selftests/faildatatype/BLACKLIST4
-rw-r--r--tests/auto/testlib/selftests/faildatatype/faildatatype.pro9
-rw-r--r--tests/auto/testlib/selftests/faildatatype/tst_faildatatype.cpp57
-rw-r--r--tests/auto/testlib/selftests/failfetchtype/BLACKLIST4
-rw-r--r--tests/auto/testlib/selftests/failfetchtype/failfetchtype.pro9
-rw-r--r--tests/auto/testlib/selftests/failfetchtype/tst_failfetchtype.cpp55
-rw-r--r--tests/auto/testlib/selftests/failinit/failinit.pro2
-rw-r--r--tests/auto/testlib/selftests/failinitdata/failinitdata.pro2
-rw-r--r--tests/auto/testlib/selftests/fetchbogus/fetchbogus.pro2
-rw-r--r--tests/auto/testlib/selftests/findtestdata/findtestdata.pro2
-rw-r--r--tests/auto/testlib/selftests/float/float.pro2
-rw-r--r--tests/auto/testlib/selftests/float/tst_float.cpp188
-rwxr-xr-xtests/auto/testlib/selftests/generate_expected_output.py88
-rw-r--r--tests/auto/testlib/selftests/globaldata/globaldata.pro2
-rw-r--r--tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp44
-rw-r--r--tests/auto/testlib/selftests/keyboard/keyboard.pro2
-rw-r--r--tests/auto/testlib/selftests/longstring/longstring.pro2
-rw-r--r--tests/auto/testlib/selftests/maxwarnings/maxwarnings.pro2
-rw-r--r--tests/auto/testlib/selftests/mouse/mouse.pro2
-rw-r--r--tests/auto/testlib/selftests/multiexec/multiexec.pro2
-rw-r--r--tests/auto/testlib/selftests/pairdiagnostics/pairdiagnostics.pro2
-rw-r--r--tests/auto/testlib/selftests/printdatatags/printdatatags.pro2
-rw-r--r--tests/auto/testlib/selftests/printdatatagswithglobaltags/printdatatagswithglobaltags.pro2
-rw-r--r--tests/auto/testlib/selftests/qexecstringlist/qexecstringlist.pro2
-rw-r--r--tests/auto/testlib/selftests/selftests.pri6
-rw-r--r--tests/auto/testlib/selftests/signaldumper/signaldumper.pro9
-rw-r--r--tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp417
-rw-r--r--tests/auto/testlib/selftests/silent/silent.pro2
-rw-r--r--tests/auto/testlib/selftests/silent/tst_silent.cpp21
-rw-r--r--tests/auto/testlib/selftests/singleskip/singleskip.pro2
-rw-r--r--tests/auto/testlib/selftests/skip/skip.pro2
-rw-r--r--tests/auto/testlib/selftests/skipcleanup/skipcleanup.pro2
-rw-r--r--tests/auto/testlib/selftests/skipinit/skipinit.pro2
-rw-r--r--tests/auto/testlib/selftests/skipinitdata/skipinitdata.pro2
-rw-r--r--tests/auto/testlib/selftests/sleep/sleep.pro2
-rw-r--r--tests/auto/testlib/selftests/sleep/tst_sleep.cpp3
-rw-r--r--tests/auto/testlib/selftests/strcmp/strcmp.pro2
-rw-r--r--tests/auto/testlib/selftests/subtest/subtest.pro2
-rw-r--r--tests/auto/testlib/selftests/test/test.pro1
-rw-r--r--tests/auto/testlib/selftests/testlib/testlib.pro9
-rw-r--r--tests/auto/testlib/selftests/testlib/tst_testlib.cpp97
-rw-r--r--tests/auto/testlib/selftests/tst_selftests.cpp69
-rw-r--r--tests/auto/testlib/selftests/tuplediagnostics/tuplediagnostics.pro2
-rw-r--r--tests/auto/testlib/selftests/verbose1/verbose1.pro2
-rw-r--r--tests/auto/testlib/selftests/verbose2/verbose2.pro2
-rw-r--r--tests/auto/testlib/selftests/verifyexceptionthrown/verifyexceptionthrown.pro2
-rw-r--r--tests/auto/testlib/selftests/warnings/warnings.pro2
-rw-r--r--tests/auto/testlib/selftests/watchdog/tst_watchdog.cpp51
-rw-r--r--tests/auto/testlib/selftests/watchdog/watchdog.pro14
-rw-r--r--tests/auto/testlib/selftests/xunit/xunit.pro2
-rw-r--r--tests/auto/testlib/testlib.pro7
-rw-r--r--tests/auto/testserver.pri109
-rw-r--r--tests/auto/tools/moc/cxx-attributes.h103
-rw-r--r--tests/auto/tools/moc/cxx11-enums.h18
-rw-r--r--tests/auto/tools/moc/moc.pro3
-rw-r--r--tests/auto/tools/moc/parse-defines.h11
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp90
-rw-r--r--tests/auto/tools/qmakelib/qmakelib.pro2
-rw-r--r--tests/auto/tools/rcc/data/images/images.expected7
-rw-r--r--tests/auto/tools/rcc/data/sizes/data/data-0.txt0
-rw-r--r--tests/auto/tools/rcc/data/sizes/data/data-1.txt1
-rw-r--r--tests/auto/tools/rcc/data/sizes/data/data-2.txt1
-rw-r--r--tests/auto/tools/rcc/data/sizes/data/data-35.txt1
-rw-r--r--tests/auto/tools/rcc/data/sizes/size-0.expected89
-rw-r--r--tests/auto/tools/rcc/data/sizes/size-0.qrc5
-rw-r--r--tests/auto/tools/rcc/data/sizes/size-1.expected90
-rw-r--r--tests/auto/tools/rcc/data/sizes/size-1.qrc5
-rw-r--r--tests/auto/tools/rcc/data/sizes/size-2-0-35-1.expected127
-rw-r--r--tests/auto/tools/rcc/data/sizes/size-2-0-35-1.qrc8
-rw-r--r--tests/auto/tools/rcc/data/sizes/size-2-0-35-1_python.expected68
-rw-r--r--tests/auto/tools/rcc/rcc.pro7
-rw-r--r--tests/auto/tools/rcc/tst_rcc.cpp265
-rw-r--r--tests/auto/tools/uic/baseline/Dialog_with_Buttons_Bottom.ui.h4
-rw-r--r--tests/auto/tools/uic/baseline/Dialog_with_Buttons_Right.ui.h4
-rw-r--r--tests/auto/tools/uic/baseline/Dialog_without_Buttons.ui.h4
-rw-r--r--tests/auto/tools/uic/baseline/Main_Window.ui.h4
-rw-r--r--tests/auto/tools/uic/baseline/Widget.ui.h10
-rw-r--r--tests/auto/tools/uic/baseline/addlinkdialog.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/addtorrentform.ui.h36
-rw-r--r--tests/auto/tools/uic/baseline/authenticationdialog.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/backside.ui.h40
-rw-r--r--tests/auto/tools/uic/baseline/batchtranslation.ui.h26
-rw-r--r--tests/auto/tools/uic/baseline/bookmarkdialog.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/bookwindow.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/browserwidget.ui.h36
-rw-r--r--tests/auto/tools/uic/baseline/bug18156QTreeWidget.ui.h6
-rw-r--r--tests/auto/tools/uic/baseline/buttongroup.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/calculator.ui.h58
-rw-r--r--tests/auto/tools/uic/baseline/calculatorform.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/certificateinfo.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/chatdialog.ui.h6
-rw-r--r--tests/auto/tools/uic/baseline/chatmainwindow.ui.h52
-rw-r--r--tests/auto/tools/uic/baseline/chatsetnickname.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/config.ui.h78
-rw-r--r--tests/auto/tools/uic/baseline/connectdialog.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/controller.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/cookies.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/cookiesexceptions.ui.h20
-rw-r--r--tests/auto/tools/uic/baseline/default.ui.h146
-rw-r--r--tests/auto/tools/uic/baseline/dialog.ui.h10
-rw-r--r--tests/auto/tools/uic/baseline/downloaditem.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/downloads.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/embeddeddialog.ui.h22
-rw-r--r--tests/auto/tools/uic/baseline/enumnostdset.ui.h2
-rw-r--r--tests/auto/tools/uic/baseline/filespage.ui.h10
-rw-r--r--tests/auto/tools/uic/baseline/filternamedialog.ui.h6
-rw-r--r--tests/auto/tools/uic/baseline/filterpage.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/finddialog.ui.h74
-rw-r--r--tests/auto/tools/uic/baseline/form.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/formwindowsettings.ui.h28
-rw-r--r--tests/auto/tools/uic/baseline/generalpage.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/gridalignment.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/gridpanel.ui.h22
-rw-r--r--tests/auto/tools/uic/baseline/helpdialog.ui3
-rw-r--r--tests/auto/tools/uic/baseline/helpdialog.ui.h147
-rw-r--r--tests/auto/tools/uic/baseline/history.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/icontheme.ui.h10
-rw-r--r--tests/auto/tools/uic/baseline/idbased.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/identifierpage.ui.h10
-rw-r--r--tests/auto/tools/uic/baseline/imagedialog.ui.h22
-rw-r--r--tests/auto/tools/uic/baseline/inputpage.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/installdialog.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/languagesdialog.ui.h42
-rw-r--r--tests/auto/tools/uic/baseline/listwidgeteditor.ui.h46
-rw-r--r--tests/auto/tools/uic/baseline/mainwindow.ui.h50
-rw-r--r--tests/auto/tools/uic/baseline/mydialog.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/myform.ui.h24
-rw-r--r--tests/auto/tools/uic/baseline/newactiondialog.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/newdynamicpropertydialog.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/newform.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/orderdialog.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/outputpage.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/pagefold.ui.h146
-rw-r--r--tests/auto/tools/uic/baseline/paletteeditor.ui.h26
-rw-r--r--tests/auto/tools/uic/baseline/passworddialog.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/pathpage.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/phrasebookbox.ui.h70
-rw-r--r--tests/auto/tools/uic/baseline/pixmapfunction.ui.h4
-rw-r--r--tests/auto/tools/uic/baseline/plugindialog.ui.h10
-rw-r--r--tests/auto/tools/uic/baseline/preferencesdialog.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/previewconfigurationwidget.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/previewdialogbase.ui.h20
-rw-r--r--tests/auto/tools/uic/baseline/previewwidget.ui.h28
-rw-r--r--tests/auto/tools/uic/baseline/proxy.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/qfiledialog.ui.h42
-rw-r--r--tests/auto/tools/uic/baseline/qpagesetupwidget.ui.h82
-rw-r--r--tests/auto/tools/uic/baseline/qprintpropertieswidget.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/qprintsettingsoutput.ui.h44
-rw-r--r--tests/auto/tools/uic/baseline/qprintwidget.ui.h24
-rw-r--r--tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h30
-rw-r--r--tests/auto/tools/uic/baseline/qtgradientdialog.ui.h4
-rw-r--r--tests/auto/tools/uic/baseline/qtgradienteditor.ui.h224
-rw-r--r--tests/auto/tools/uic/baseline/qtgradientview.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/qtgradientviewdialog.ui.h4
-rw-r--r--tests/auto/tools/uic/baseline/qtresourceeditordialog.ui.h40
-rw-r--r--tests/auto/tools/uic/baseline/qttoolbardialog.ui.h68
-rw-r--r--tests/auto/tools/uic/baseline/querywidget.ui.h10
-rw-r--r--tests/auto/tools/uic/baseline/remotecontrol.ui.h28
-rw-r--r--tests/auto/tools/uic/baseline/saveformastemplate.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/settings.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/signalslotdialog.ui.h40
-rw-r--r--tests/auto/tools/uic/baseline/sslclient.ui.h24
-rw-r--r--tests/auto/tools/uic/baseline/sslerrors.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/statistics.ui.h28
-rw-r--r--tests/auto/tools/uic/baseline/stringlisteditor.ui.h44
-rw-r--r--tests/auto/tools/uic/baseline/stylesheeteditor.ui.h22
-rw-r--r--tests/auto/tools/uic/baseline/tabbedbrowser.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/tablewidgeteditor.ui.h98
-rw-r--r--tests/auto/tools/uic/baseline/tetrixwindow.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/textfinder.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/topicchooser.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/translatedialog.ui.h62
-rw-r--r--tests/auto/tools/uic/baseline/translationsettings.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/treewidgeteditor.ui.h114
-rw-r--r--tests/auto/tools/uic/baseline/trpreviewtool.ui.h36
-rw-r--r--tests/auto/tools/uic/baseline/validators.ui.h30
-rw-r--r--tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h52
-rw-r--r--tests/auto/tools/uic/tst_uic.cpp204
-rw-r--r--tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp8
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp40
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp8
-rw-r--r--tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST2
-rw-r--r--tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp4
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp156
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp112
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp40
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp5
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp78
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro2
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp4
-rw-r--r--tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp2
-rw-r--r--tests/auto/widgets/itemviews/qlistview/qlistview.pro2
-rw-r--r--tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp4
-rw-r--r--tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp184
-rw-r--r--tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp38
-rw-r--r--tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp132
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp154
-rw-r--r--tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp261
-rw-r--r--tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp16
-rw-r--r--tests/auto/widgets/kernel/kernel.pro2
-rw-r--r--tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp63
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp15
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp68
-rw-r--r--tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp5
-rw-r--r--tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp8
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST4
-rw-r--r--tests/auto/widgets/kernel/qwidget/qwidget.pro2
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp49
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/BLACKLIST1
-rw-r--r--tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp47
-rw-r--r--tests/auto/widgets/styles/qstyle/tst_qstyle.cpp2
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp76
-rw-r--r--tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp27
-rw-r--r--tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp10
-rw-r--r--tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp10
-rw-r--r--tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp8
-rw-r--r--tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp50
-rw-r--r--tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp54
-rw-r--r--tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp38
-rw-r--r--tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp2
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp12
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp26
-rw-r--r--tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp38
-rw-r--r--tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp5
-rw-r--r--tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp74
-rw-r--r--tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp4
-rw-r--r--tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp46
-rw-r--r--tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/heading.html2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/markdown.md2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/markdown.really2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp64
-rw-r--r--tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp88
-rw-r--r--tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp3
-rw-r--r--tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp4
-rw-r--r--tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp12
-rw-r--r--tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak5
-rw-r--r--tests/baselineserver/shared/baselineprotocol.cpp4
-rw-r--r--tests/benchmarks/corelib/corelib.pro1
-rw-r--r--tests/benchmarks/corelib/io/qfileinfo/main.cpp8
-rw-r--r--tests/benchmarks/corelib/io/qtextstream/qtextstream.pro2
-rw-r--r--tests/benchmarks/corelib/kernel/kernel.pro3
-rw-r--r--tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp88
-rw-r--r--tests/benchmarks/corelib/mimetypes/qmimedatabase/main.cpp11
-rw-r--r--tests/benchmarks/corelib/time/qdate/qdate.pro4
-rw-r--r--tests/benchmarks/corelib/time/qdate/tst_bench_qdate.cpp53
-rw-r--r--tests/benchmarks/corelib/time/qdatetime/main.cpp (renamed from tests/benchmarks/corelib/tools/qdatetime/main.cpp)5
-rw-r--r--tests/benchmarks/corelib/time/qdatetime/qdatetime.pro (renamed from tests/benchmarks/corelib/tools/qdatetime/qdatetime.pro)0
-rw-r--r--tests/benchmarks/corelib/time/qtimezone/main.cpp (renamed from tests/benchmarks/corelib/tools/qtimezone/main.cpp)0
-rw-r--r--tests/benchmarks/corelib/time/qtimezone/qtimezone.pro (renamed from tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro)0
-rw-r--r--tests/benchmarks/corelib/time/time.pro5
-rw-r--r--tests/benchmarks/corelib/tools/qmap/qmap.pro2
-rw-r--r--tests/benchmarks/corelib/tools/qstringbuilder/main.cpp2
-rw-r--r--tests/benchmarks/corelib/tools/tools.pro2
-rw-r--r--tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp14
-rw-r--r--tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp12
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp1
-rw-r--r--tests/benchmarks/widgets/itemviews/itemviews.pro3
-rw-r--r--tests/benchmarks/widgets/itemviews/qlistview/qlistview.pro7
-rw-r--r--tests/benchmarks/widgets/itemviews/qlistview/tst_qlistview.cpp (renamed from tests/auto/testlib/selftests/alive/tst_alive.cpp)72
-rw-r--r--tests/libfuzzer/README39
-rw-r--r--tests/libfuzzer/corelib/serialization/qxmlstream/qxmlstreamreader/readnext/main.cpp36
-rw-r--r--tests/libfuzzer/corelib/serialization/qxmlstream/qxmlstreamreader/readnext/readnext.pro5
-rw-r--r--tests/libfuzzer/gui/text/qtextdocument/setHtml/main.cpp37
-rw-r--r--tests/libfuzzer/gui/text/qtextdocument/setHtml/setHtml.pro3
-rw-r--r--tests/manual/diaglib/diaglib.pri2
-rw-r--r--tests/manual/dialogs/filedialogpanel.cpp6
-rw-r--r--tests/manual/dialogs/printdialogpanel.cpp12
-rw-r--r--tests/manual/foreignwindows/main.cpp11
-rw-r--r--tests/manual/highdpi/dragwidget.cpp2
-rw-r--r--tests/manual/lance/interactivewidget.cpp2
-rw-r--r--tests/manual/lance/main.cpp10
-rw-r--r--tests/manual/lance/widgets.h62
-rw-r--r--tests/manual/manual.pro3
-rw-r--r--tests/manual/markdown/html2md.cpp64
-rw-r--r--tests/manual/markdown/html2md.pro6
-rw-r--r--tests/manual/qcursor/grab_override/mainwindow.cpp4
-rw-r--r--tests/manual/qsslsocket/main.cpp12
-rw-r--r--tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.cpp198
-rw-r--r--tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.pro8
-rw-r--r--tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.qrc7
-rw-r--r--tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.cpp213
-rw-r--r--tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.pro8
-rw-r--r--tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.qrc8
-rw-r--r--tests/manual/rhi/cubemap/buildshaders.bat2
-rw-r--r--tests/manual/rhi/cubemap/c.pngbin0 -> 27923 bytes
-rw-r--r--tests/manual/rhi/cubemap/cubemap.cpp179
-rw-r--r--tests/manual/rhi/cubemap/cubemap.frag10
-rw-r--r--tests/manual/rhi/cubemap/cubemap.frag.qsbbin0 -> 1311 bytes
-rw-r--r--tests/manual/rhi/cubemap/cubemap.pro8
-rw-r--r--tests/manual/rhi/cubemap/cubemap.qrc7
-rw-r--r--tests/manual/rhi/cubemap/cubemap.vert15
-rw-r--r--tests/manual/rhi/cubemap/cubemap.vert.qsbbin0 -> 1499 bytes
-rw-r--r--tests/manual/rhi/floattexture/floattexture.cpp328
-rw-r--r--tests/manual/rhi/floattexture/floattexture.pro8
-rw-r--r--tests/manual/rhi/floattexture/floattexture.qrc7
-rw-r--r--tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp554
-rw-r--r--tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro8
-rw-r--r--tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.qrc6
-rw-r--r--tests/manual/rhi/mrt/buildshaders.bat2
-rw-r--r--tests/manual/rhi/mrt/mrt.cpp296
-rw-r--r--tests/manual/rhi/mrt/mrt.frag22
-rw-r--r--tests/manual/rhi/mrt/mrt.frag.qsbbin0 -> 1934 bytes
-rw-r--r--tests/manual/rhi/mrt/mrt.pro8
-rw-r--r--tests/manual/rhi/mrt/mrt.qrc8
-rw-r--r--tests/manual/rhi/mrt/mrt.vert19
-rw-r--r--tests/manual/rhi/mrt/mrt.vert.qsbbin0 -> 1633 bytes
-rw-r--r--tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.cpp259
-rw-r--r--tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.pro8
-rw-r--r--tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.qrc8
-rw-r--r--tests/manual/rhi/msaatexture/msaatexture.cpp329
-rw-r--r--tests/manual/rhi/msaatexture/msaatexture.pro8
-rw-r--r--tests/manual/rhi/msaatexture/msaatexture.qrc9
-rw-r--r--tests/manual/rhi/multiwindow/multiwindow.cpp644
-rw-r--r--tests/manual/rhi/multiwindow/multiwindow.pro8
-rw-r--r--tests/manual/rhi/multiwindow/multiwindow.qrc6
-rw-r--r--tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp829
-rw-r--r--tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.pro12
-rw-r--r--tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.qrc7
-rw-r--r--tests/manual/rhi/multiwindow_threaded/window.cpp142
-rw-r--r--tests/manual/rhi/multiwindow_threaded/window.h86
-rw-r--r--tests/manual/rhi/offscreen/offscreen.cpp366
-rw-r--r--tests/manual/rhi/offscreen/offscreen.pro9
-rw-r--r--tests/manual/rhi/offscreen/offscreen.qrc6
-rw-r--r--tests/manual/rhi/qrhiprof/qrhiprof.cpp671
-rw-r--r--tests/manual/rhi/qrhiprof/qrhiprof.pro6
-rw-r--r--tests/manual/rhi/rhi.pro22
-rw-r--r--tests/manual/rhi/shadowmap/buildshaders.bat4
-rwxr-xr-xtests/manual/rhi/shadowmap/buildshaders.sh4
-rw-r--r--tests/manual/rhi/shadowmap/main.frag30
-rw-r--r--tests/manual/rhi/shadowmap/main.frag.qsbbin0 -> 2489 bytes
-rw-r--r--tests/manual/rhi/shadowmap/main.vert20
-rw-r--r--tests/manual/rhi/shadowmap/main.vert.qsbbin0 -> 1595 bytes
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.cpp304
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.frag5
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.frag.qsbbin0 -> 408 bytes
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.pro8
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.qrc8
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.vert14
-rw-r--r--tests/manual/rhi/shadowmap/shadowmap.vert.qsbbin0 -> 1215 bytes
-rw-r--r--tests/manual/rhi/shared/OpenfootageNET_fieldairport-512.hdrbin0 -> 385303 bytes
-rw-r--r--tests/manual/rhi/shared/buildshaders.bat5
-rw-r--r--tests/manual/rhi/shared/bwqt224_64.pngbin0 -> 6339 bytes
-rw-r--r--tests/manual/rhi/shared/bwqt224_64_nomips.ddsbin0 -> 9712 bytes
-rw-r--r--tests/manual/rhi/shared/color.frag15
-rw-r--r--tests/manual/rhi/shared/color.frag.qsbbin0 -> 1483 bytes
-rw-r--r--tests/manual/rhi/shared/color.vert19
-rw-r--r--tests/manual/rhi/shared/color.vert.qsbbin0 -> 1648 bytes
-rw-r--r--tests/manual/rhi/shared/cube.h119
-rw-r--r--tests/manual/rhi/shared/dds_bc1.h137
-rw-r--r--tests/manual/rhi/shared/examplefw.h548
-rw-r--r--tests/manual/rhi/shared/qt256.pngbin0 -> 6208 bytes
-rw-r--r--tests/manual/rhi/shared/qt256_bc1_9mips.ddsbin0 -> 43832 bytes
-rw-r--r--tests/manual/rhi/shared/texture.frag18
-rw-r--r--tests/manual/rhi/shared/texture.frag.qsbbin0 -> 1710 bytes
-rw-r--r--tests/manual/rhi/shared/texture.vert21
-rw-r--r--tests/manual/rhi/shared/texture.vert.qsbbin0 -> 1897 bytes
-rw-r--r--tests/manual/rhi/shared/texture_ms4.frag20
-rw-r--r--tests/manual/rhi/shared/texture_ms4.frag.qsbbin0 -> 1847 bytes
-rw-r--r--tests/manual/rhi/texuploads/texuploads.cpp314
-rw-r--r--tests/manual/rhi/texuploads/texuploads.pro8
-rw-r--r--tests/manual/rhi/texuploads/texuploads.qrc7
-rw-r--r--tests/manual/rhi/triquadcube/quadrenderer.cpp148
-rw-r--r--tests/manual/rhi/triquadcube/quadrenderer.h87
-rw-r--r--tests/manual/rhi/triquadcube/texturedcuberenderer.cpp222
-rw-r--r--tests/manual/rhi/triquadcube/texturedcuberenderer.h86
-rw-r--r--tests/manual/rhi/triquadcube/triangleoncuberenderer.cpp292
-rw-r--r--tests/manual/rhi/triquadcube/triangleoncuberenderer.h95
-rw-r--r--tests/manual/rhi/triquadcube/trianglerenderer.cpp202
-rw-r--r--tests/manual/rhi/triquadcube/trianglerenderer.h93
-rw-r--r--tests/manual/rhi/triquadcube/triquadcube.cpp271
-rw-r--r--tests/manual/rhi/triquadcube/triquadcube.pro18
-rw-r--r--tests/manual/rhi/triquadcube/triquadcube.qrc9
-rw-r--r--tests/manual/shortcuts/main.cpp3
-rw-r--r--tests/manual/widgets/itemviews/itemviews.pro8
-rw-r--r--tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/main.cpp88
-rw-r--r--tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro8
-rw-r--r--tests/manual/widgets/widgets/qmainwindow/saveStateSize/main.cpp111
-rw-r--r--tests/manual/widgets/widgets/qmainwindow/saveStateSize/saveStateSize.pro4
-rw-r--r--tests/shared/filesystem.h34
-rw-r--r--tests/testserver/apache2/.gitattributes2
-rwxr-xr-xtests/testserver/apache2/apache2.sh3
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol-expire.cgi7
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol.cgi13
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol200.cgi9
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag200.cgi5
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag304.cgi11
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires200.cgi5
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires304.cgi11
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified200.cgi5
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified304.cgi11
-rw-r--r--tests/testserver/apache2/testdata/www/htdocs/rfcs/.gitattributes1
-rw-r--r--tests/testserver/apache2/testdata/www/htdocs/rfcs/rfc2616.html8380
-rw-r--r--tests/testserver/common/.gitattributes2
-rwxr-xr-xtests/testserver/common/ssl.sh3
-rwxr-xr-xtests/testserver/common/startup.sh15
-rw-r--r--tests/testserver/common/testdata/ssl/qt-test-server-host-network-cacert.pem16
-rwxr-xr-xtests/testserver/cyrus/cyrus.sh40
-rw-r--r--tests/testserver/danted/.gitattributes2
-rwxr-xr-xtests/testserver/danted/danted.sh19
-rw-r--r--tests/testserver/docker-compose-for-macOS.yml113
-rw-r--r--tests/testserver/docker-compose-for-windows.yml113
-rw-r--r--tests/testserver/docker-compose.yml150
-rwxr-xr-xtests/testserver/echo/echo.sh7
-rw-r--r--tests/testserver/ftp-proxy/.gitattributes2
-rwxr-xr-xtests/testserver/ftp-proxy/ftp-proxy.sh4
-rwxr-xr-xtests/testserver/iptables/iptables.sh34
-rw-r--r--tests/testserver/squid/.gitattributes2
-rw-r--r--tests/testserver/vsftpd/.gitattributes2
-rw-r--r--tests/testserver/vsftpd/testdata/vsftpd.conf4
-rwxr-xr-xtests/testserver/vsftpd/vsftpd.sh11
-rw-r--r--util/corelib/qurl-generateTLDs/main.cpp178
-rw-r--r--util/lexgen/README3
-rw-r--r--util/lexgen/css3-simplified.lexgen2
-rw-r--r--util/lexgen/generator.cpp15
-rw-r--r--util/lexgen/main.cpp2
-rw-r--r--util/local_database/README1
-rw-r--r--util/local_database/enumdata.py873
-rw-r--r--util/locale_database/README5
-rwxr-xr-xutil/locale_database/cldr2qlocalexml.py (renamed from util/local_database/cldr2qlocalexml.py)173
-rwxr-xr-xutil/locale_database/cldr2qtimezone.py (renamed from util/local_database/cldr2qtimezone.py)6
-rwxr-xr-xutil/locale_database/dateconverter.py (renamed from util/local_database/dateconverter.py)0
-rw-r--r--util/locale_database/enumdata.py880
-rw-r--r--util/locale_database/formattags.txt (renamed from util/local_database/formattags.txt)0
-rw-r--r--util/locale_database/localexml.py (renamed from util/local_database/localexml.py)0
-rwxr-xr-xutil/locale_database/qlocalexml2cpp.py (renamed from util/local_database/qlocalexml2cpp.py)2
-rw-r--r--util/locale_database/testlocales/localemodel.cpp (renamed from util/local_database/testlocales/localemodel.cpp)0
-rw-r--r--util/locale_database/testlocales/localemodel.h (renamed from util/local_database/testlocales/localemodel.h)0
-rw-r--r--util/locale_database/testlocales/localewidget.cpp (renamed from util/local_database/testlocales/localewidget.cpp)0
-rw-r--r--util/locale_database/testlocales/localewidget.h (renamed from util/local_database/testlocales/localewidget.h)0
-rw-r--r--util/locale_database/testlocales/main.cpp (renamed from util/local_database/testlocales/main.cpp)0
-rw-r--r--util/locale_database/testlocales/testlocales.pro (renamed from util/local_database/testlocales/testlocales.pro)0
-rw-r--r--util/locale_database/xpathlite.py (renamed from util/local_database/xpathlite.py)34
-rw-r--r--util/qfloat16-tables/gen_qfloat16_tables.cpp (renamed from src/tools/qfloat16-tables/gen_qfloat16_tables.cpp)108
-rw-r--r--util/qfloat16-tables/qfloat16-tables.pro2
-rw-r--r--util/unicode/main.cpp36
3149 files changed, 169147 insertions, 55706 deletions
diff --git a/.gitignore b/.gitignore
index b9188d84f7..e4079c6b4d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,8 +56,6 @@ qt*-config.pri
/src/angle/src/QtANGLE/libANGLE/
/src/angle/src/libGLESv2/libANGLE/
-/src/corelib/global/qfloat16tables.cpp
-
/examples/*/*/*
!/examples/*/*/*[.]*
!/examples/*/*/README
diff --git a/.qmake.conf b/.qmake.conf
index 888bd8f66e..08e1a4723c 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -4,4 +4,4 @@ CONFIG += warning_clean
QT_SOURCE_TREE = $$PWD
QT_BUILD_TREE = $$shadowed($$PWD)
-MODULE_VERSION = 5.12.4
+MODULE_VERSION = 5.14.0
diff --git a/config_help.txt b/config_help.txt
index fb37cbaed9..3f31fd351f 100644
--- a/config_help.txt
+++ b/config_help.txt
@@ -122,6 +122,7 @@ Build options:
-qtnamespace <name> .. Wrap all Qt library code in 'namespace <name> {...}'.
-qtlibinfix <infix> .. Rename all libQt5*.so to libQt5*<infix>.so.
+ -qtlibinfix-plugins .. Rename Qt plugins according to -qtlibinfix [no]
-testcocoon .......... Instrument with the TestCocoon code coverage tool [no]
-gcov ................ Instrument with the GCov code coverage tool [no]
@@ -136,8 +137,11 @@ Build options:
for example, -sanitize address cannot be combined with
-sanitize thread.
- -c++std <edition> .... Select C++ standard <edition> [c++1z/c++14/c++11]
- (Not supported with MSVC)
+ -coverage {trace-pc-guard}
+ Add code coverage instrumentation (Clang only)
+
+ -c++std <edition> .... Select C++ standard <edition> [c++2a/c++17/c++14/c++11]
+ (Not supported with MSVC 2015)
-sse2 ................ Use SSE2 instructions [auto]
-sse3/-ssse3/-sse4.1/-sse4.2/-avx/-avx2/-avx512
@@ -164,7 +168,8 @@ Build options:
-pch ................. Use precompiled headers [auto]
-ltcg ................ Use Link Time Code Generation [no]
- -use-gold-linker ..... Use the GNU gold linker [auto]
+ -linker [bfd,gold,lld] Force use of the GNU ld, GNU gold or LLVM/LLD linker
+ instead of default one (GCC only)
-incredibuild-xge .... Use the IncrediBuild XGE [no] (Windows only)
-ccache .............. Use the ccache compiler cache [no] (Unix only)
-make-tool <tool> .... Use <tool> to build qmake [nmake] (Windows only)
@@ -199,7 +204,7 @@ Build environment:
-android-ndk-host .... Set Android NDK host (linux-x86, linux-x86_64, etc.)
[$ANDROID_NDK_HOST]
-android-arch ........ Set Android architecture (armeabi, armeabi-v7a,
- arm64-v8a, x86, x86_64, mips, mips64)
+ arm64-v8a, x86, x86_64)
-android-toolchain-version ... Set Android toolchain version
-android-style-assets Automatically extract style assets from the device at
run time. This option makes the Android style behave
@@ -237,7 +242,7 @@ Core options:
-inotify ............. Enable inotify support
-iconv ............... Enable iconv(3) support [posix/sun/gnu/no] (Unix only)
-icu ................. Enable ICU support [auto]
- -pcre ................ Select used libpcre2 [system/qt]
+ -pcre ................ Select used libpcre2 [system/qt/no]
-pps ................. Enable PPS support [auto] (QNX only)
-zlib ................ Select used zlib [system/qt]
@@ -292,7 +297,6 @@ Gui, printing, widget options:
-gbm ............... Enable backends for GBM [auto] (Linux only)
-kms ............... Enable backends for KMS [auto] (Linux only)
-linuxfb ........... Enable Linux Framebuffer support [auto] (Linux only)
- -mirclient ......... Enable Mir client support [no] (Linux only)
-xcb ............... Enable X11 support. Select used xcb-* libraries [system/qt/no]
(-qt-xcb still uses system version of libxcb itself)
diff --git a/configure.json b/configure.json
index c93bea46bc..f817101de1 100644
--- a/configure.json
+++ b/configure.json
@@ -67,6 +67,7 @@
"commercial": "void",
"compile-examples": { "type": "boolean", "name": "compile_examples" },
"confirm-license": "void",
+ "coverage": "coverage",
"dbus": { "type": "optionalString", "values": [ "no", "yes", "linked", "runtime" ] },
"dbus-linked": { "type": "void", "name": "dbus", "value": "linked" },
"dbus-runtime": { "type": "void", "name": "dbus", "value": "runtime" },
@@ -89,6 +90,7 @@
"headersclean": "boolean",
"incredibuild-xge": { "type": "boolean", "name": "incredibuild_xge" },
"libudev": "boolean",
+ "linker": { "type": "optionalString", "values": [ "bfd", "gold", "lld" ] },
"ltcg": "boolean",
"make": { "type": "addString", "values": [ "examples", "libs", "tests", "tools" ] },
"make-tool": "string",
@@ -108,6 +110,7 @@
"profile": "boolean",
"qreal": "string",
"qtlibinfix": { "type": "string", "name": "qt_libinfix" },
+ "qtlibinfix-plugins": { "type": "boolean", "name": "qt_libinfix_plugins" },
"qtnamespace": { "type": "string", "name": "qt_namespace" },
"reduce-exports": { "type": "boolean", "name": "reduce_exports" },
"reduce-relocations": { "type": "boolean", "name": "reduce_relocations" },
@@ -130,12 +133,13 @@
"syncqt": "boolean",
"sysroot": "string",
"testcocoon": "boolean",
- "use-gold-linker": { "type": "boolean", "name": "use_gold_linker" },
+ "use-gold-linker": { "type": "boolean", "name": "use_gold_linker_alias" },
"warnings-are-errors": { "type": "boolean", "name": "warnings_are_errors" },
"Werror": { "type": "boolean", "name": "warnings_are_errors" },
"widgets": "boolean",
"xplatform": "string",
- "zlib": { "type": "enum", "name": "system-zlib", "values": { "system": "yes", "qt": "no" } }
+ "zlib": { "type": "enum", "name": "system-zlib", "values": { "system": "yes", "qt": "no" } },
+ "zstd": "boolean"
},
"prefix": {
"D": "defines",
@@ -166,6 +170,21 @@
{ "libs": "-s USE_ZLIB=1", "condition": "config.wasm" }
]
},
+ "zstd": {
+ "label": "Zstandard",
+ "test": {
+ "include": "zstd.h",
+ "main": [
+ "(void) ZSTD_compress(NULL, 0, NULL, 0, 1);",
+ "unsigned long long n = ZSTD_getFrameContentSize(NULL, 0);",
+ "(void) ZSTD_decompress(NULL, 0, NULL, n);"
+ ]
+ },
+ "sources": [
+ { "type": "pkgConfig", "args": "libzstd >= 1.3" },
+ "-lzstd"
+ ]
+ },
"dbus": {
"label": "D-Bus >= 1.2",
"test": {
@@ -207,8 +226,8 @@
},
"testTypeDependencies": {
- "linkerSupportsFlag": [ "use_gold_linker" ],
- "verifySpec": [ "shared", "use_gold_linker", "compiler-flags", "qmakeargs", "commit" ],
+ "linkerSupportsFlag": [ "use_bfd_linker", "use_gold_linker", "use_lld_linker" ],
+ "verifySpec": [ "shared", "use_bfd_linker", "use_gold_linker", "use_lld_linker", "compiler-flags", "qmakeargs", "commit" ],
"compile": [ "verifyspec" ],
"detectPkgConfig": [ "cross_compile", "machineTuple" ],
"library": [ "pkg-config", "compiler-flags" ],
@@ -301,7 +320,7 @@
}
},
"c++1z": {
- "label": "C++1z support",
+ "label": "C++17 support",
"type": "compile",
"test": {
"head": [
@@ -321,6 +340,20 @@
"qmake": "CONFIG += c++11 c++14 c++1z"
}
},
+ "c++2a": {
+ "label": "C++2a support",
+ "type": "compile",
+ "test": {
+ "head": [
+ "#if __cplusplus > 201703L",
+ "// Compiler claims to support experimental C++2a, trust it",
+ "#else",
+ "# error __cplusplus must be > 201703L (the value for C++17)",
+ "#endif"
+ ],
+ "qmake": "CONFIG += c++11 c++14 c++1z c++2a"
+ }
+ },
"precompile_header": {
"label": "precompiled header support",
"type": "compile",
@@ -340,11 +373,21 @@
]
}
},
+ "use_bfd_linker": {
+ "label": "bfd linker",
+ "type": "compilerSupportsFlag",
+ "flag": "-fuse-ld=bfd"
+ },
"use_gold_linker": {
"label": "gold linker",
"type": "compilerSupportsFlag",
"flag": "-fuse-ld=gold"
},
+ "use_lld_linker" : {
+ "label": "lld linker",
+ "type": "compilerSupportsFlag",
+ "flag": "-fuse-ld=lld"
+ },
"optimize_debug": {
"label": "-Og support",
"type": "compilerSupportsFlag",
@@ -596,7 +639,7 @@
"shared": {
"label": "Building shared libraries",
"autoDetect": "!config.uikit",
- "condition": "!config.integrity && !config.wasm",
+ "condition": "!config.integrity && !config.wasm && !config.rtems",
"output": [
"shared",
"publicFeature",
@@ -632,11 +675,34 @@
"output": [ "qmakeArgs" ],
"condition": "input.qmakeArgs != ''"
},
+ "use_bfd_linker": {
+ "label": "bfd",
+ "autoDetect": "false",
+ "enable" : "input.linker == 'bfd'",
+ "disable" : "input.linker == 'gold' || input.linker == 'lld'",
+ "condition": "!config.win32 && !config.integrity && !config.wasm && tests.use_bfd_linker",
+ "output": [ "privateConfig", "useBFDLinker" ]
+ },
+ "use_gold_linker_alias": {
+ "autoDetect": "false",
+ "condition": "!config.win32 && !config.integrity && !config.wasm && tests.use_gold_linker"
+ },
"use_gold_linker": {
- "label": "Using gold linker",
- "condition": "!config.win32 && !config.integrity && !config.wasm && tests.use_gold_linker",
+ "label": "gold",
+ "autoDetect": "false",
+ "enable" : "input.linker == 'gold' || features.use_gold_linker_alias" ,
+ "disable" : "input.linker == 'bfd' || input.linker == 'lld'",
+ "condition": "!config.win32 && !config.integrity && !config.wasm && !config.rtems && tests.use_gold_linker",
"output": [ "privateConfig", "useGoldLinker" ]
},
+ "use_lld_linker": {
+ "label": "lld",
+ "autoDetect": "false",
+ "enable" : "input.linker == 'lld'",
+ "disable" : "input.linker == 'bfd' || input.linker == 'gold'",
+ "condition": "!config.win32 && !config.integrity && !config.wasm && tests.use_lld_linker",
+ "output": [ "privateConfig", "useLLDLinker" ]
+ },
"optimize_debug": {
"label": "Optimize debug build",
"autoDetect": "!features.developer-build",
@@ -760,7 +826,7 @@
},
"largefile": {
"label": "Large file support",
- "condition": "!config.android && !config.integrity && !config.winrt",
+ "condition": "!config.android && !config.integrity && !config.winrt && !config.rtems",
"output": [
"privateConfig",
{ "type": "define", "name": "QT_LARGEFILE_SUPPORT", "value": 64 }
@@ -806,6 +872,16 @@
"condition": "features.sanitize_address || features.sanitize_thread || features.sanitize_memory || features.sanitize_undefined",
"output": [ "sanitizer", "publicConfig" ]
},
+ "coverage_trace_pc_guard": {
+ "label": "trace-pc-guard",
+ "autoDetect": false,
+ "output": [ "publicConfig" ]
+ },
+ "coverage": {
+ "label": "Code Coverage Instrumentation",
+ "condition": "features.coverage_trace_pc_guard",
+ "output": [ "publicConfig" ]
+ },
"GNUmake": {
"label": "GNU make",
"autoDetect": false,
@@ -847,10 +923,16 @@
"output": [ "publicFeature", "publicQtConfig" ]
},
"c++1z": {
- "label": "C++1z",
+ "label": "C++17",
"condition": "features.c++14 && tests.c++1z",
"output": [ "publicFeature", "publicQtConfig" ]
},
+ "c++2a": {
+ "label": "C++2a",
+ "autoDetect": false,
+ "condition": "features.c++1z && tests.c++2a",
+ "output": [ "publicFeature", "publicQtConfig" ]
+ },
"c89": {
"label": "C89"
},
@@ -1130,11 +1212,16 @@
"condition": "libs.zlib",
"output": [ "privateFeature" ]
},
+ "zstd": {
+ "label": "Zstandard support",
+ "condition": "libs.zstd",
+ "output": [ "privateFeature" ]
+ },
"thread": {
"label": "Thread support",
"purpose": "Provides QThread and related classes.",
"section": "Kernel",
- "condition": "!config.wasm",
+ "autoDetect": "!config.wasm",
"output": [ "publicFeature" ]
},
"future": {
@@ -1216,6 +1303,12 @@
"condition": "libs.libudev",
"output": [ "privateFeature" ]
},
+ "qt_libinfix_plugins": {
+ "label": "Use QT_LIBINFIX for Plugins",
+ "autoDetect": false,
+ "enable": "input.qt_libinfix != '' && input.qt_libinfix_plugins == 'yes'",
+ "output": [ "privateConfig" ]
+ },
"compile_examples": {
"label": "Compile examples",
"autoDetect": "!config.wasm",
@@ -1284,6 +1377,11 @@ Qt can be built in release mode with separate debug information, so
"type": "error",
"condition": "(features.rpath || features.rpath_dir) && var.QMAKE_LFLAGS_RPATH == ''",
"message": "This platform does not support RPATH"
+ },
+ {
+ "type": "error",
+ "condition": "features.coverage && !config.clang",
+ "message": "Command line option -coverage is only supported with clang compilers."
}
],
@@ -1343,14 +1441,19 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
{
"message": "Using C++ standard",
"type": "firstAvailableFeature",
- "args": "c++1z c++14 c++11"
+ "args": "c++2a c++1z c++14 c++11"
},
{
"type": "feature",
"args": "ccache",
"condition": "config.unix"
},
- "use_gold_linker",
+ {
+ "message": "Linker",
+ "type": "firstAvailableFeature",
+ "args": "use_bfd_linker use_gold_linker use_lld_linker",
+ "condition": "features.use_bfd_linker || features.use_gold_linker || features.use_lld_linker"
+ },
{
"type": "feature",
"args": "enable_new_dtags",
@@ -1418,6 +1521,12 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
"entries": [ "sanitize_address", "sanitize_thread", "sanitize_memory", "sanitize_undefined" ]
},
{
+ "message": "Code Coverage Instrumentation",
+ "type": "firstAvailableFeature",
+ "args": "coverage_trace_pc_guard",
+ "condition": "features.coverage"
+ },
+ {
"message": "Build parts",
"type": "buildParts"
},
@@ -1445,7 +1554,8 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
"entries": [
"pkg-config",
"libudev",
- "system-zlib"
+ "system-zlib",
+ "zstd"
]
}
]
diff --git a/configure.pri b/configure.pri
index 131aa868c2..81133da3d7 100644
--- a/configure.pri
+++ b/configure.pri
@@ -14,21 +14,26 @@ defineTest(qtConfCommandline_qmakeArgs) {
}
defineTest(qtConfCommandline_cxxstd) {
- msvc: \
- qtConfAddError("Command line option -c++std is not supported with MSVC compilers.")
-
arg = $${1}
val = $${2}
isEmpty(val): val = $$qtConfGetNextCommandlineArg()
!contains(val, "^-.*"):!isEmpty(val) {
contains(val, "(c\+\+)?11") {
qtConfCommandlineSetInput("c++14", "no")
+ qtConfCommandlineSetInput("c++1z", "no")
+ qtConfCommandlineSetInput("c++2a", "no")
} else: contains(val, "(c\+\+)?(14|1y)") {
qtConfCommandlineSetInput("c++14", "yes")
qtConfCommandlineSetInput("c++1z", "no")
- } else: contains(val, "(c\+\+)?(1z)") {
+ qtConfCommandlineSetInput("c++2a", "no")
+ } else: contains(val, "(c\+\+)?(17|1z)") {
qtConfCommandlineSetInput("c++14", "yes")
qtConfCommandlineSetInput("c++1z", "yes")
+ qtConfCommandlineSetInput("c++2a", "no")
+ } else: contains(val, "(c\+\+)?(2a)") {
+ qtConfCommandlineSetInput("c++14", "yes")
+ qtConfCommandlineSetInput("c++1z", "yes")
+ qtConfCommandlineSetInput("c++2a", "yes")
} else {
qtConfAddError("Invalid argument $$val to command line parameter $$arg")
}
@@ -58,6 +63,21 @@ defineTest(qtConfCommandline_sanitize) {
}
}
+defineTest(qtConfCommandline_coverage) {
+ arg = $${1}
+ val = $${2}
+ isEmpty(val): val = $$qtConfGetNextCommandlineArg()
+ !contains(val, "^-.*"):!isEmpty(val) {
+ equals(val, "trace-pc-guard") {
+ qtConfCommandlineSetInput("coverage_trace_pc_guard", "yes")
+ } else {
+ qtConfAddError("Invalid argument $$val to command line parameter $$arg")
+ }
+ } else {
+ qtConfAddError("Missing argument to command line parameter $$arg")
+ }
+}
+
# callbacks
defineReplace(qtConfFunc_crossCompile) {
@@ -276,6 +296,8 @@ defineTest(qtConfTest_architecture) {
content = $$cat($$test_out_dir/libarch.so, blob)
else: wasm:exists($$test_out_dir/arch.wasm): \
content = $$cat($$test_out_dir/arch.wasm, blob)
+ else: wasm:exists($$test_out_dir/arch.o): \
+ content = $$cat($$test_out_dir/arch.o, blob)
else: \
error("$$eval($${1}.label) detection binary not found.")
@@ -606,14 +628,8 @@ defineTest(qtConfOutput_prepareOptions) {
target_arch = armeabi-v7a
platform = $$eval(config.input.android-ndk-platform)
- isEmpty(platform): equals(target_arch, arm64-v8a): \
- platform = android-21
-
- isEmpty(platform): equals(target_arch, x86_64): \
- platform = android-21
-
isEmpty(platform): \
- platform = android-16 ### the windows configure disagrees ...
+ platform = android-21
$${currentConfig}.output.devicePro += \
"DEFAULT_ANDROID_SDK_ROOT = $$val_escape(sdk_root)" \
@@ -1020,6 +1036,14 @@ defineTest(qtConfOutput_crossCompile) {
export(CONFIG)
}
+defineTest(qtConfOutput_useBFDLinker) {
+ !$${2}: return()
+
+ # We need to preempt the output here, so that qtConfTest_linkerSupportsFlag can work properly in qtbase
+ CONFIG += use_bfd_linker
+ export(CONFIG)
+}
+
defineTest(qtConfOutput_useGoldLinker) {
!$${2}: return()
@@ -1028,6 +1052,14 @@ defineTest(qtConfOutput_useGoldLinker) {
export(CONFIG)
}
+defineTest(qtConfOutput_useLLDLinker) {
+ !$${2}: return()
+
+ # We need to preempt the output here, so that qtConfTest_linkerSupportsFlag can work properly in qtbase
+ CONFIG += use_lld_linker
+ export(CONFIG)
+}
+
defineTest(qtConfOutput_debugAndRelease) {
$$qtConfEvaluate("features.debug") {
qtConfOutputVar(append, "publicPro", "CONFIG", "debug")
diff --git a/dist/changes-5.13.0 b/dist/changes-5.13.0
new file mode 100644
index 0000000000..2891739fa4
--- /dev/null
+++ b/dist/changes-5.13.0
@@ -0,0 +1,308 @@
+Qt 5.13 introduces many new features and improvements as well as bugfixes
+over the 5.12.x series. For more details, refer to the online documentation
+included in this distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.13 series is binary compatible with the 5.12.x series.
+Applications compiled for 5.12 will continue to run with 5.13.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Important Source Incompatible Changes *
+****************************************************************************
+
+ - Moc generated files include the standard <memory> header file now.
+ A side effect of this is that code including the Moc output from within
+ a namespace will fail to compile.
+
+****************************************************************************
+* Important Behavior Changes *
+****************************************************************************
+
+ - The Qt resource system now supports compressing content using the
+ Zstandard (https://zstd.net) algorithm. Compared to zlib, it compresses
+ better for the same CPU time, so this algorithm is the default.
+ QResource::isCompressed() returns true for either compression algorithm.
+ Use QResource::compressionAlgorithm() to find out which algorithm to
+ decompress. QFile will automatically decompress using the correct
+ algorithm.
+
+ - QDataStream version bumped up to 19 to account for changes in the
+ serialization of QFont.
+
+ - [QTBUG-73048] Qt now enables by default warnings when using APIs
+ marked as deprecated. It is possible to disable such warnings by
+ defining the QT_NO_DEPRECATED_WARNINGS macro. The old
+ QT_DEPRECATED_WARNINGS macro which was used to enable this warning
+ now has no effect (warnings are automatically enabled).
+
+****************************************************************************
+* Third-Party Code *
+****************************************************************************
+
+ - Updated bundled SQLite to version 3.28.0.
+ - [QTBUG-72623] Updated DNS public suffix list
+ - [QTBUG-73883] libjpeg-turbo was updated to version 2.0.2
+ - Bundled libpng was updated to version 1.6.37
+
+****************************************************************************
+* Platform-Specific Changes *
+****************************************************************************
+
+ - X11 / XCB:
+ * [QTBUG-45375] QTabletEvent coordinates now come from AbsX/AbsY
+ valuators in the X11 event, in more precise 32.32 fixed-point format,
+ scaled to fit the virtual desktop. It's possible to revert to using
+ the legacy 16.16-format event_x/event_y coordinates as in previous
+ releases by setting the QT_XCB_TABLET_LEGACY_COORDINATES environment
+ variable.
+ * [plugins] platforminputcontexts now use libxkbcommon-compose APIs for
+ compose key input, instead of Qt's own implementation.
+
+ - Android
+ * Increased the minimum supported Android version to Android 5.0
+ (API level 21).
+
+ - Windows
+ * [QTBUG-47247][QTBUG-71855] Add a default setting for
+ hasBorderInFullScreen in QtPlatformHeaders, QWindowsWindowFunctions
+ * [QTBUG-57180] Removed confusing DirectWrite warning when loading
+ bitmap fonts.
+
+ - macOS
+ * Accessibility: VoiceOver now reads all lines in multiline text
+ components when navigating by lines.
+
+****************************************************************************
+* Tools *
+****************************************************************************
+
+ - configure & build system:
+ * Added --linker=[bfg,lld,gold] configure flag.
+ * The default OpenGL configuration changed from ANGLE to dynamic OpenGL.
+ * Added -schannel option to enable Schannel support on Desktop Windows.
+ * Added -coverage option for recording coverage data during execution
+
+ - CMake
+ * Added support for automatic linking of transitive dependencies in
+ static builds
+
+ - qmake
+ * [QTBUG-53654] Introduced the variables WINDOWS_TARGET_PLATFORM_VERSION
+ and WINDOWS_TARGET_PLATFORM_MIN_VERSION for overriding the default
+ values of WindowsTargetPlatformVersion and
+ WindowsTargetPlatformMinVersion in Visual Studio project files.
+
+ - RCC now supports compressing content using the Zstandard
+ (https://zstd.net) algorithm. Compared to zlib, it compresses better for
+ the same CPU time, so this algorithm is the default. To go back to the
+ previous algorithm, pass command-line option --compress-algo=zlib.
+ Compression levels range from 1 (fastest, least compression) to 19
+ (slowest, best compression). Level 0 tells the library to choose an
+ implementation-defined default. The default compression level is
+ "heuristic" (level -1): under this mode, RCC will attempt a very fast
+ compression (level 1) and check if the file was sufficiently compressed.
+ If it was, then RCC will compress again using an implementation-defined
+ level.
+
+****************************************************************************
+* QtCore *
+****************************************************************************
+
+ - New class QConcatenateTablesProxyModel, to concatenate the rows from
+ multiple source models.
+ - New class QTransposeProxyModel to swap rows and columns of the source
+ model.
+ - Added macros Q_DISABLE_MOVE and Q_DISABLE_COPY_MOVE complementing
+ Q_DISABLE_COPY.
+ - Qt Containers and meta type system now use C++11 type traits
+ (std::is_trivial, std::is_trivially_copyable and
+ std::is_trivially_destructible) to detect the class of a type not
+ explicitly set by Q_DECLARE_TYPEINFO. (Q_DECLARE_TYPEINFO is still
+ needed for QList.)
+
+ - QCommandLineParser:
+ * [QTBUG-58490] The application name (if set in QCoreApplication) is now
+ shown in error messages.
+
+ - QDateTime:
+ * [QTBUG-71030] Fixed race conditions in getting the local time zone. Qt now
+ has a mutex lock around all calls to tzset() and mktime(). Application
+ code should avoid calling those functions directly.
+
+ - QFile:
+ * Made QFile::copy() issue a filesystem-synchronization system call,
+ which would make it less likely to result in incomplete or corrupt
+ files if the system reboots or uncleanly shuts down soon after the
+ function returns. New code is advised to use QSaveFile instead, which
+ also allows display of a progress report while copying.
+
+ - QFileInfo:
+ * [QTBUG-63970][QTBUG-30401][QTBUG-20791] Fixed resolving of symbolic
+ links to UNC shares on NTFS file systems.
+
+ - QJsonArray:
+ * [QTBUG-32793] Added cbegin() and cend() methods for compatibility with
+ the Standard Library container concepts.
+
+ - QJsonDocument:
+ * [QTBUG-71445] Added the ability to stream QJsonDocument into and from
+ QDataStream if it is contained in a QVariant.
+
+ - QLocale:
+ * Added support for Western Balochi, Ido, Lojban, Sicilian and
+ Southern Kurdish.
+ * [QTBUG-71445] Added a const overload for formattedDataSize().
+ * [QTBUG-782] Added toLong() and toULong().
+
+ - QMetaObject:
+ * Non-copyable lambdas can now be used with invokeMethod(). For
+ consistency reasons, the functor object is now always moved.
+
+ - QMimeDatabase:
+ * Added configure option -no-mimetype-database that tells Qt not to
+ bundle its own copy of the XDG MIME database. If this option is
+ passed, QMimeDatabase will only work if there's a system copy in
+ $XDG_DATA_DIRS/mime. This option is useful for Linux distributions
+ that ensure the data is always present.
+
+ - QSettings:
+ * Added QSettings(Scope...) constructor to avoid using #ifdef in Qt
+ applications.
+
+ - QStringListModel:
+ * [QTBUG-69807] Implemented moveRows
+
+ - QUrlQuery:
+ * QUrlQuery now provides an initializer list constructor. It can be
+ created using a list of key/value pairs.
+
+ - QVector:
+ * QVector no longer requires a default constructor for its template
+ argument.
+
+****************************************************************************
+* QtDBus *
+****************************************************************************
+
+ - Matching namespace prefixes using QDBusServiceWatcher (instead of full
+ service names) is now possible. For example, "com.example.backend1*"
+ will match "com.example.backend1", "com.example.backend1.foo" and
+ "com.example.backend1.foo.bar", but not "com.example.backend12".
+
+****************************************************************************
+* QtGui *
+****************************************************************************
+
+ - CSS:
+ * Added support for HSL/HSLA colors.
+ * Fix the range of the hue parameter when parsing a color given in HSL
+ or HSV.
+
+ - QFont:
+ * Add setFamilies()/families() to support use of font families with
+ commas and quotes in their name.
+
+ - QImage:
+ * [QTBUG-41176] Added support for 16-bit grayscale format.
+ * A new method convertTo has been added to change the format of a QImage
+ in place.
+
+ - QPainterPath:
+ * Added clear(), reserve(), capacity(). clear() removes allocated
+ QPainterPath elements but preserves allocated memory, which can be
+ useful for application with complex paths that are often recreated.
+ reserve() and capacity() follow QVector semantics.
+
+ - QWindow:
+ * [QTBUG-67903][QTBUG-52944] QWindow::transientParent is now a property.
+
+ - Text:
+ * [QTBUG-60813] Deprecated QFont::lastResortFamily() and
+ QFont::lastResortFont() which are not in use in Qt 5 and did not
+ provide any useful information.
+ * [QTBUG-22813] Added support for setting the font's style name in
+ QTextCharFormat.
+
+****************************************************************************
+* QtNetwork *
+****************************************************************************
+
+ - TLS (SSL):
+ * Support for SSLv2 and SSLv3 sockets has been dropped, as per RFC 6176
+ (2011) and RFC 7568 (2015).
+ * The Schannel backend now supports ALPN and thus HTTP/2.
+ * [QTBUG-62637] Added support for Schannel on Desktop Windows. To build
+ Qt with Schannel support use '-schannel' during configure.
+ * Added class QOcspResponse as a part of OCSP stapling support.
+ * [QTBUG-12812][QTBUG-17158] Added OCSP-stapling support for OpenSSL
+ backend
+ * [QTBUG-71828][QTBUG-73289] Fixed SSL verification when connecting to IP
+ address (no host name) if that IP address is listed in the certificate.
+
+****************************************************************************
+* QtTestLib *
+****************************************************************************
+
+ - Added QTest::toString(const QModelIndex &idx)
+
+ - Removed support for GPU_BLACKLIST files. Reimplementations or
+ equivalents of QTEST_MAIN() should remove their uses of
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT and its _DEFS; they are still vacuously
+ defined, but serve no remaining purpose and shall be undefined in due
+ course.
+
+****************************************************************************
+* QtWidgets *
+****************************************************************************
+
+ - QAbstractScrollArea:
+ * [QTBUG-69120] QTableView/QTreeView, when reporting their
+ viewportSizeHint(), now correctly take into account their scroll
+ bars' visibility and visibilityPolicy.
+
+ - QHeaderView:
+ * dataChanged now respects the given roles to avoid useless
+ recomputations.
+
+ - QLabel:
+ * Minor performance improvement when painting a label with an image.
+
+ - QListWidget:
+ * [QTBUG-69807] Implemented moveRows in model
+ * [QTBUG-68977] Sped up handling of hidden items when working with large
+ data sets.
+
+ - QPlainTextEdit:
+ * Added QRegularExpression find() method overload.
+
+ - QTextEdit:
+ * Added QRegularExpression find() method overload.
+
+ - QTreeView:
+ * Added expandRecursively() to expand all items below a given index.
+
+ - QWidgetTextControlPrivate:
+ * [QTBUG-69735] Moved cursor selection to start.
+
+****************************************************************************
+* QtSql *
+****************************************************************************
+
+ - SQLite:
+ * [QTBUG-63498] The json1-extension for the SQLite3 plugin is now enabled
+ by default.
+
+ - PostgreSQL:
+ * QSqlDatabase is now stricter about table names when used with record()
+ and primaryIndex(). If the tablename was not quoted when it was
+ created, then the table name passed to record() and primaryIndex()
+ needs to be in lower case so that PostgreSQL is able to find it.
diff --git a/doc/global/qt-html-templates-offline.qdocconf b/doc/global/qt-html-templates-offline.qdocconf
index 0c012f11d6..39f49fd3da 100644
--- a/doc/global/qt-html-templates-offline.qdocconf
+++ b/doc/global/qt-html-templates-offline.qdocconf
@@ -3,6 +3,8 @@ include(html-config.qdocconf)
include(html-header-offline.qdocconf)
include(html-footer.qdocconf)
+defines += offlinedocs
+
#uncomment if navigation bar is not wanted
#HTML.nonavigationbar = "true"
diff --git a/doc/global/qt-html-templates-online.qdocconf b/doc/global/qt-html-templates-online.qdocconf
index 502c406453..468cbe1808 100644
--- a/doc/global/qt-html-templates-online.qdocconf
+++ b/doc/global/qt-html-templates-online.qdocconf
@@ -4,6 +4,8 @@ HTML.tocdepth = 2
include(html-header-online.qdocconf)
include(html-footer-online.qdocconf)
+defines += onlinedocs
+
#uncomment if navigation bar is not wanted
#HTML.nonavigationbar = "true"
diff --git a/examples/corelib/ipc/localfortuneclient/client.h b/examples/corelib/ipc/localfortuneclient/client.h
index 0c1ede94c9..7248428440 100644
--- a/examples/corelib/ipc/localfortuneclient/client.h
+++ b/examples/corelib/ipc/localfortuneclient/client.h
@@ -53,14 +53,12 @@
#include <QDialog>
#include <QDataStream>
-
-#include <qlocalsocket.h>
+#include <QLocalSocket>
QT_BEGIN_NAMESPACE
class QLabel;
class QLineEdit;
class QPushButton;
-class QLocalSocket;
QT_END_NAMESPACE
class Client : public QDialog
diff --git a/examples/corelib/ipc/localfortuneserver/main.cpp b/examples/corelib/ipc/localfortuneserver/main.cpp
index 6f8ec539fe..430005a1d3 100644
--- a/examples/corelib/ipc/localfortuneserver/main.cpp
+++ b/examples/corelib/ipc/localfortuneserver/main.cpp
@@ -49,9 +49,6 @@
****************************************************************************/
#include <QApplication>
-#include <QtCore>
-
-#include <stdlib.h>
#include "server.h"
diff --git a/examples/corelib/ipc/localfortuneserver/server.cpp b/examples/corelib/ipc/localfortuneserver/server.cpp
index be8d4750d6..9be5ed5051 100644
--- a/examples/corelib/ipc/localfortuneserver/server.cpp
+++ b/examples/corelib/ipc/localfortuneserver/server.cpp
@@ -48,15 +48,11 @@
**
****************************************************************************/
+#include "server.h"
+
#include <QtWidgets>
#include <QtNetwork>
-#include <stdlib.h>
-
-#include "server.h"
-#include <qlocalserver.h>
-#include <qlocalsocket.h>
-
Server::Server(QWidget *parent)
: QDialog(parent)
{
diff --git a/examples/corelib/ipc/sharedmemory/dialog.cpp b/examples/corelib/ipc/sharedmemory/dialog.cpp
index ce5a4547bb..4e999d1bcf 100644
--- a/examples/corelib/ipc/sharedmemory/dialog.cpp
+++ b/examples/corelib/ipc/sharedmemory/dialog.cpp
@@ -51,7 +51,6 @@
#include "dialog.h"
#include <QFileDialog>
#include <QBuffer>
-#include <QtCore/QDebug>
/*!
\class Dialog
@@ -81,10 +80,10 @@ Dialog::Dialog(QWidget *parent)
: QDialog(parent), sharedMemory("QSharedMemoryExample")
{
ui.setupUi(this);
- connect(ui.loadFromFileButton, SIGNAL(clicked()), SLOT(loadFromFile()));
- connect(ui.loadFromSharedMemoryButton,
- SIGNAL(clicked()),
- SLOT(loadFromMemory()));
+ connect(ui.loadFromFileButton, &QPushButton::clicked,
+ this, &Dialog::loadFromFile);
+ connect(ui.loadFromSharedMemoryButton, &QPushButton::clicked,
+ this, &Dialog::loadFromMemory);
setWindowTitle(tr("SharedMemory Example"));
}
//! [0]
diff --git a/examples/corelib/ipc/sharedmemory/dialog.h b/examples/corelib/ipc/sharedmemory/dialog.h
index 1662654441..693333256c 100644
--- a/examples/corelib/ipc/sharedmemory/dialog.h
+++ b/examples/corelib/ipc/sharedmemory/dialog.h
@@ -51,8 +51,8 @@
#ifndef DIALOG_H
#define DIALOG_H
-#include <qdialog.h>
-#include <qsharedmemory.h>
+#include <QDialog>
+#include <QSharedMemory>
#include "ui_dialog.h"
//! [0]
@@ -61,7 +61,7 @@ class Dialog : public QDialog
Q_OBJECT
public:
- Dialog(QWidget *parent = 0);
+ Dialog(QWidget *parent = nullptr);
public slots:
void loadFromFile();
diff --git a/examples/corelib/mimetypes/mimetypebrowser/main.cpp b/examples/corelib/mimetypes/mimetypebrowser/main.cpp
index f4462df411..cf87004a01 100644
--- a/examples/corelib/mimetypes/mimetypebrowser/main.cpp
+++ b/examples/corelib/mimetypes/mimetypebrowser/main.cpp
@@ -55,9 +55,6 @@
#include <QCommandLineParser>
#include <QCommandLineOption>
-#include <QDebug>
-#include <QMimeDatabase>
-#include <QMimeType>
int main(int argc, char *argv[])
{
diff --git a/examples/corelib/mimetypes/mimetypebrowser/mainwindow.cpp b/examples/corelib/mimetypes/mimetypebrowser/mainwindow.cpp
index bc7ec17d1c..2e5c8069b8 100644
--- a/examples/corelib/mimetypes/mimetypebrowser/mainwindow.cpp
+++ b/examples/corelib/mimetypes/mimetypebrowser/mainwindow.cpp
@@ -185,7 +185,9 @@ void MainWindow::find()
m_findMatches.clear();
m_findIndex = 0;
- foreach (const QStandardItem *item, m_model->findItems(value, Qt::MatchContains | Qt::MatchFixedString | Qt::MatchRecursive))
+ const QList<QStandardItem *> items =
+ m_model->findItems(value, Qt::MatchContains | Qt::MatchFixedString | Qt::MatchRecursive);
+ for (const QStandardItem *item : items)
m_findMatches.append(m_model->indexFromItem(item));
statusBar()->showMessage(tr("%n mime types match \"%1\".", 0, m_findMatches.size()).arg(value));
updateFindActions();
diff --git a/examples/corelib/mimetypes/mimetypebrowser/mimetypemodel.cpp b/examples/corelib/mimetypes/mimetypebrowser/mimetypemodel.cpp
index ee83de092d..f755e060c6 100644
--- a/examples/corelib/mimetypes/mimetypebrowser/mimetypemodel.cpp
+++ b/examples/corelib/mimetypes/mimetypebrowser/mimetypemodel.cpp
@@ -50,9 +50,8 @@
#include "mimetypemodel.h"
-#include <QIcon>
-
#include <QDebug>
+#include <QIcon>
#include <QMimeDatabase>
#include <QTextStream>
#include <QVariant>
diff --git a/examples/corelib/serialization/convert/cborconverter.cpp b/examples/corelib/serialization/convert/cborconverter.cpp
index 41724c935e..f907bb0af6 100644
--- a/examples/corelib/serialization/convert/cborconverter.cpp
+++ b/examples/corelib/serialization/convert/cborconverter.cpp
@@ -56,7 +56,6 @@
#include <QCborArray>
#include <QCborValue>
#include <QDataStream>
-#include <QDebug>
#include <QFloat16>
#include <QFile>
#include <QMetaType>
@@ -84,19 +83,6 @@ static const char diagnosticHelp[] =
QT_BEGIN_NAMESPACE
-QDataStream &operator<<(QDataStream &ds, QCborSimpleType st)
-{
- return ds << quint8(st);
-}
-
-QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
-{
- quint8 v;
- ds >> v;
- st = QCborSimpleType(v);
- return ds;
-}
-
QDataStream &operator<<(QDataStream &ds, QCborTag tag)
{
return ds << quint64(tag);
@@ -240,7 +226,7 @@ void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, cons
QTextStream out(f);
out << convertFromVariant(contents, Double).toDiagnosticNotation(opts)
- << endl;
+ << Qt::endl;
}
CborConverter::CborConverter()
diff --git a/examples/corelib/serialization/convert/textconverter.cpp b/examples/corelib/serialization/convert/textconverter.cpp
index e80e69a0b5..7aed08f96c 100644
--- a/examples/corelib/serialization/convert/textconverter.cpp
+++ b/examples/corelib/serialization/convert/textconverter.cpp
@@ -66,7 +66,7 @@ static void dumpVariant(QTextStream &out, const QVariant &v)
case QVariant::String: {
const QStringList list = v.toStringList();
for (const QString &s : list)
- out << s << endl;
+ out << s << Qt::endl;
break;
}
@@ -80,11 +80,11 @@ static void dumpVariant(QTextStream &out, const QVariant &v)
}
case QMetaType::Nullptr:
- out << "(null)" << endl;
+ out << "(null)" << Qt::endl;
break;
default:
- out << v.toString() << endl;
+ out << v.toString() << Qt::endl;
break;
}
}
diff --git a/examples/corelib/serialization/savegame/game.cpp b/examples/corelib/serialization/savegame/game.cpp
index 4caec71a03..c39362bc68 100644
--- a/examples/corelib/serialization/savegame/game.cpp
+++ b/examples/corelib/serialization/savegame/game.cpp
@@ -185,7 +185,7 @@ void Game::write(QJsonObject &json) const
json["player"] = playerObject;
QJsonArray levelArray;
- foreach (const Level level, mLevels) {
+ for (const Level &level : mLevels) {
QJsonObject levelObject;
level.write(levelObject);
levelArray.append(levelObject);
diff --git a/examples/corelib/serialization/savegame/level.cpp b/examples/corelib/serialization/savegame/level.cpp
index 8eda107f46..6fe46e8938 100644
--- a/examples/corelib/serialization/savegame/level.cpp
+++ b/examples/corelib/serialization/savegame/level.cpp
@@ -97,7 +97,7 @@ void Level::write(QJsonObject &json) const
{
json["name"] = mName;
QJsonArray npcArray;
- foreach (const Character npc, mNpcs) {
+ for (const Character &npc : mNpcs) {
QJsonObject npcObject;
npc.write(npcObject);
npcArray.append(npcObject);
diff --git a/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp b/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp
index b3e4af5dc8..71d0abb09f 100644
--- a/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp
+++ b/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp
@@ -48,14 +48,13 @@
**
****************************************************************************/
+#include "mandelbrotwidget.h"
+
#include <QPainter>
#include <QKeyEvent>
#include <math.h>
-#include "mandelbrotwidget.h"
-
-
//! [0]
const double DefaultCenterX = -0.637011f;
const double DefaultCenterY = -0.0395159f;
@@ -75,7 +74,8 @@ MandelbrotWidget::MandelbrotWidget(QWidget *parent)
pixmapScale = DefaultScale;
curScale = DefaultScale;
- connect(&thread, SIGNAL(renderedImage(QImage,double)), this, SLOT(updatePixmap(QImage,double)));
+ connect(&thread, &RenderThread::renderedImage,
+ this, &MandelbrotWidget::updatePixmap);
setWindowTitle(tr("Mandelbrot"));
#ifndef QT_NO_CURSOR
@@ -117,7 +117,8 @@ void MandelbrotWidget::paintEvent(QPaintEvent * /* event */)
painter.save();
painter.translate(newX, newY);
painter.scale(scaleFactor, scaleFactor);
- QRectF exposed = painter.matrix().inverted().mapRect(rect()).adjusted(-1, -1, 1, 1);
+
+ QRectF exposed = painter.transform().inverted().mapRect(rect()).adjusted(-1, -1, 1, 1);
painter.drawPixmap(exposed, pixmap, exposed);
painter.restore();
}
diff --git a/examples/corelib/threads/mandelbrot/mandelbrotwidget.h b/examples/corelib/threads/mandelbrot/mandelbrotwidget.h
index a04bfa6e81..cb40962535 100644
--- a/examples/corelib/threads/mandelbrot/mandelbrotwidget.h
+++ b/examples/corelib/threads/mandelbrot/mandelbrotwidget.h
@@ -62,7 +62,7 @@ class MandelbrotWidget : public QWidget
Q_OBJECT
public:
- MandelbrotWidget(QWidget *parent = 0);
+ MandelbrotWidget(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event) override;
diff --git a/examples/corelib/threads/mandelbrot/renderthread.cpp b/examples/corelib/threads/mandelbrot/renderthread.cpp
index c57b696e25..eee44c7242 100644
--- a/examples/corelib/threads/mandelbrot/renderthread.cpp
+++ b/examples/corelib/threads/mandelbrot/renderthread.cpp
@@ -50,7 +50,7 @@
#include "renderthread.h"
-#include <QtWidgets>
+#include <QImage>
#include <cmath>
//! [0]
diff --git a/examples/corelib/threads/mandelbrot/renderthread.h b/examples/corelib/threads/mandelbrot/renderthread.h
index b5e9226fb8..4f0394d554 100644
--- a/examples/corelib/threads/mandelbrot/renderthread.h
+++ b/examples/corelib/threads/mandelbrot/renderthread.h
@@ -66,7 +66,7 @@ class RenderThread : public QThread
Q_OBJECT
public:
- RenderThread(QObject *parent = 0);
+ RenderThread(QObject *parent = nullptr);
~RenderThread();
void render(double centerX, double centerY, double scaleFactor, QSize resultSize);
diff --git a/examples/corelib/threads/queuedcustomtype/block.cpp b/examples/corelib/threads/queuedcustomtype/block.cpp
index a5058cc5ae..9cfad8673c 100644
--- a/examples/corelib/threads/queuedcustomtype/block.cpp
+++ b/examples/corelib/threads/queuedcustomtype/block.cpp
@@ -48,8 +48,6 @@
**
****************************************************************************/
-#include <QColor>
-#include <QRect>
#include "block.h"
Block::Block()
@@ -57,9 +55,8 @@ Block::Block()
}
Block::Block(const Block &other)
+ : m_rect(other.m_rect), m_color(other.m_color)
{
- m_rect = other.m_rect;
- m_color = other.m_color;
}
Block::~Block()
@@ -67,9 +64,8 @@ Block::~Block()
}
Block::Block(const QRect &rect, const QColor &color)
+ : m_rect(rect), m_color(color)
{
- m_rect = rect;
- m_color = color;
}
QColor Block::color() const
diff --git a/examples/corelib/threads/queuedcustomtype/block.h b/examples/corelib/threads/queuedcustomtype/block.h
index 547cc10f0a..eef48b25c2 100644
--- a/examples/corelib/threads/queuedcustomtype/block.h
+++ b/examples/corelib/threads/queuedcustomtype/block.h
@@ -52,7 +52,6 @@
#define BLOCK_H
#include <QColor>
-#include <QDebug>
#include <QMetaType>
#include <QRect>
diff --git a/examples/corelib/threads/queuedcustomtype/renderthread.h b/examples/corelib/threads/queuedcustomtype/renderthread.h
index 318ef293b4..9375b60e74 100644
--- a/examples/corelib/threads/queuedcustomtype/renderthread.h
+++ b/examples/corelib/threads/queuedcustomtype/renderthread.h
@@ -62,7 +62,7 @@ class RenderThread : public QThread
Q_OBJECT
public:
- RenderThread(QObject *parent = 0);
+ RenderThread(QObject *parent = nullptr);
~RenderThread();
void processImage(const QImage &image);
diff --git a/examples/corelib/threads/queuedcustomtype/window.cpp b/examples/corelib/threads/queuedcustomtype/window.cpp
index 2cefba1e17..183d9824cb 100644
--- a/examples/corelib/threads/queuedcustomtype/window.cpp
+++ b/examples/corelib/threads/queuedcustomtype/window.cpp
@@ -48,30 +48,34 @@
**
****************************************************************************/
-#include <QtWidgets>
#include "window.h"
+#include <QtWidgets>
//! [Window constructor start]
-Window::Window()
+Window::Window(QWidget *parent)
+ : QWidget(parent), thread(new RenderThread(this))
{
- thread = new RenderThread();
//! [Window constructor start] //! [set up widgets and connections]
- label = new QLabel();
+ label = new QLabel(this);
label->setAlignment(Qt::AlignCenter);
- loadButton = new QPushButton(tr("&Load image..."));
- resetButton = new QPushButton(tr("&Stop"));
+ loadButton = new QPushButton(tr("&Load image..."), this);
+ resetButton = new QPushButton(tr("&Stop"), this);
resetButton->setEnabled(false);
- connect(loadButton, SIGNAL(clicked()), this, SLOT(loadImage()));
- connect(resetButton, SIGNAL(clicked()), thread, SLOT(stopProcess()));
- connect(thread, SIGNAL(finished()), this, SLOT(resetUi()));
+ connect(loadButton, &QPushButton::clicked,
+ this, QOverload<>::of(&Window::loadImage));
+ connect(resetButton, &QPushButton::clicked,
+ thread, &RenderThread::stopProcess);
+ connect(thread, &RenderThread::finished,
+ this, &Window::resetUi);
//! [set up widgets and connections] //! [connecting signal with custom type]
- connect(thread, SIGNAL(sendBlock(Block)), this, SLOT(addBlock(Block)));
+ connect(thread, &RenderThread::sendBlock,
+ this, &Window::addBlock);
//! [connecting signal with custom type]
- QHBoxLayout *buttonLayout = new QHBoxLayout();
+ QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch();
buttonLayout->addWidget(loadButton);
buttonLayout->addWidget(resetButton);
@@ -89,9 +93,10 @@ Window::Window()
void Window::loadImage()
{
QStringList formats;
- foreach (QByteArray format, QImageReader::supportedImageFormats())
+ const QList<QByteArray> supportedFormats = QImageReader::supportedImageFormats();
+ for (const QByteArray &format : supportedFormats)
if (format.toLower() == format)
- formats.append("*." + format);
+ formats.append(QLatin1String("*.") + QString::fromLatin1(format));
QString newPath = QFileDialog::getOpenFileName(this, tr("Open Image"),
path, tr("Image files (%1)").arg(formats.join(' ')));
diff --git a/examples/corelib/threads/queuedcustomtype/window.h b/examples/corelib/threads/queuedcustomtype/window.h
index c472c0fea7..4215dfd5a7 100644
--- a/examples/corelib/threads/queuedcustomtype/window.h
+++ b/examples/corelib/threads/queuedcustomtype/window.h
@@ -65,7 +65,7 @@ class Window : public QWidget
Q_OBJECT
public:
- Window();
+ Window(QWidget *parent = nullptr);
void loadImage(const QImage &image);
public slots:
diff --git a/examples/corelib/tools/contiguouscache/randomlistmodel.cpp b/examples/corelib/tools/contiguouscache/randomlistmodel.cpp
index ccaa45a28b..d028b896f2 100644
--- a/examples/corelib/tools/contiguouscache/randomlistmodel.cpp
+++ b/examples/corelib/tools/contiguouscache/randomlistmodel.cpp
@@ -49,7 +49,6 @@
****************************************************************************/
#include "randomlistmodel.h"
#include <QRandomGenerator>
-#include <stdlib.h>
static const int bufferSize(500);
static const int lookAhead(100);
diff --git a/examples/corelib/tools/contiguouscache/randomlistmodel.h b/examples/corelib/tools/contiguouscache/randomlistmodel.h
index e6192b434f..1fabb0d9f5 100644
--- a/examples/corelib/tools/contiguouscache/randomlistmodel.h
+++ b/examples/corelib/tools/contiguouscache/randomlistmodel.h
@@ -59,7 +59,7 @@ class RandomListModel : public QAbstractListModel
{
Q_OBJECT
public:
- RandomListModel(QObject *parent = 0);
+ RandomListModel(QObject *parent = nullptr);
~RandomListModel();
int rowCount(const QModelIndex & = QModelIndex()) const override;
diff --git a/examples/corelib/tools/customtype/main.cpp b/examples/corelib/tools/customtype/main.cpp
index ced317e208..d50bf9efea 100644
--- a/examples/corelib/tools/customtype/main.cpp
+++ b/examples/corelib/tools/customtype/main.cpp
@@ -49,6 +49,7 @@
****************************************************************************/
#include <QCoreApplication>
+#include <QDebug>
#include <QVariant>
#include "message.h"
diff --git a/examples/corelib/tools/customtype/message.cpp b/examples/corelib/tools/customtype/message.cpp
index 8b2c295e46..cc96aee978 100644
--- a/examples/corelib/tools/customtype/message.cpp
+++ b/examples/corelib/tools/customtype/message.cpp
@@ -50,15 +50,16 @@
#include "message.h"
+#include <QDebug>
+
//! [Message class implementation]
Message::Message()
{
}
Message::Message(const Message &other)
+ : m_body(other.m_body), m_headers(other.m_headers)
{
- m_body = other.m_body;
- m_headers = other.m_headers;
}
Message::~Message()
@@ -67,9 +68,8 @@ Message::~Message()
//! [Message class implementation]
Message::Message(const QString &body, const QStringList &headers)
+ : m_body(body), m_headers(headers)
{
- m_body = body;
- m_headers = headers;
}
//! [custom type streaming operator]
diff --git a/examples/corelib/tools/customtype/message.h b/examples/corelib/tools/customtype/message.h
index 9871a7d52d..c1b8243237 100644
--- a/examples/corelib/tools/customtype/message.h
+++ b/examples/corelib/tools/customtype/message.h
@@ -51,7 +51,6 @@
#ifndef MESSAGE_H
#define MESSAGE_H
-#include <QDebug>
#include <QMetaType>
#include <QStringList>
diff --git a/examples/corelib/tools/customtypesending/main.cpp b/examples/corelib/tools/customtypesending/main.cpp
index 966c284d9a..c5d643b9d1 100644
--- a/examples/corelib/tools/customtypesending/main.cpp
+++ b/examples/corelib/tools/customtypesending/main.cpp
@@ -57,19 +57,20 @@ int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- Window window1;
QStringList headers;
headers << "Subject: Hello World"
<< "From: address@example.com";
QString body = "This is a test.\r\n";
Message message(body, headers);
+
+ Window window1;
window1.setMessage(message);
Window window2;
- QObject::connect(&window1, SIGNAL(messageSent(Message)),
- &window2, SLOT(setMessage(Message)));
- QObject::connect(&window2, SIGNAL(messageSent(Message)),
- &window1, SLOT(setMessage(Message)));
+ QObject::connect(&window1, &Window::messageSent,
+ &window2, &Window::setMessage);
+ QObject::connect(&window2, &Window::messageSent,
+ &window1, &Window::setMessage);
window1.show();
window2.show();
return app.exec();
diff --git a/examples/corelib/tools/customtypesending/message.cpp b/examples/corelib/tools/customtypesending/message.cpp
index c990768079..9386b93898 100644
--- a/examples/corelib/tools/customtypesending/message.cpp
+++ b/examples/corelib/tools/customtypesending/message.cpp
@@ -55,9 +55,8 @@ Message::Message()
}
Message::Message(const Message &other)
+ : m_body(other.m_body), m_headers(other.m_headers)
{
- m_body = other.m_body;
- m_headers = other.m_headers;
}
Message::~Message()
@@ -65,9 +64,8 @@ Message::~Message()
}
Message::Message(const QString &body, const QStringList &headers)
+ : m_body(body), m_headers(headers)
{
- m_body = body;
- m_headers = headers;
}
QString Message::body() const
diff --git a/examples/corelib/tools/customtypesending/message.h b/examples/corelib/tools/customtypesending/message.h
index a8d6d6be05..a93f111e45 100644
--- a/examples/corelib/tools/customtypesending/message.h
+++ b/examples/corelib/tools/customtypesending/message.h
@@ -51,7 +51,6 @@
#ifndef MESSAGE_H
#define MESSAGE_H
-#include <QDebug>
#include <QMetaType>
#include <QStringList>
diff --git a/examples/corelib/tools/customtypesending/window.cpp b/examples/corelib/tools/customtypesending/window.cpp
index 224656f94c..db4b52a985 100644
--- a/examples/corelib/tools/customtypesending/window.cpp
+++ b/examples/corelib/tools/customtypesending/window.cpp
@@ -52,14 +52,15 @@
#include "window.h"
//! [Window constructor]
-Window::Window()
+Window::Window(QWidget *parent)
+ : QWidget(parent), editor(new QTextEdit(this))
{
- editor = new QTextEdit();
QPushButton *sendButton = new QPushButton(tr("&Send message"));
- connect(sendButton, SIGNAL(clicked()), this, SLOT(sendMessage()));
+ connect(sendButton, &QPushButton::clicked,
+ this, &Window::sendMessage);
- QHBoxLayout *buttonLayout = new QHBoxLayout();
+ QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch();
buttonLayout->addWidget(sendButton);
buttonLayout->addStretch();
diff --git a/examples/corelib/tools/customtypesending/window.h b/examples/corelib/tools/customtypesending/window.h
index d050931b74..048fecef67 100644
--- a/examples/corelib/tools/customtypesending/window.h
+++ b/examples/corelib/tools/customtypesending/window.h
@@ -62,7 +62,7 @@ class Window : public QWidget
Q_OBJECT
public:
- Window();
+ Window(QWidget *parent = nullptr);
signals:
void messageSent(const Message &message);
diff --git a/examples/corelib/tools/doc/src/customtype.qdoc b/examples/corelib/tools/doc/src/customtype.qdoc
index 91b814808a..7ccfc95c70 100644
--- a/examples/corelib/tools/doc/src/customtype.qdoc
+++ b/examples/corelib/tools/doc/src/customtype.qdoc
@@ -117,8 +117,8 @@
\snippet tools/customtype/main.cpp storing a custom value
- Alternatively, the QVariant::fromValue() and qVariantSetValue() functions
- can be used if you are using a compiler without support for member template
+ Alternatively, the QVariant::fromValue() function can be used if
+ you are using a compiler without support for member template
functions.
The value can be retrieved using the QVariant::value() member template
@@ -126,9 +126,6 @@
\snippet tools/customtype/main.cpp retrieving a custom value
- Alternatively, the qVariantValue() template function can be used if
- you are using a compiler without support for member template functions.
-
\section1 Further Reading
The custom \c Message type can also be used with direct signal-slot
diff --git a/examples/dbus/listnames/listnames.cpp b/examples/dbus/listnames/listnames.cpp
index c0afec062d..50203da73d 100644
--- a/examples/dbus/listnames/listnames.cpp
+++ b/examples/dbus/listnames/listnames.cpp
@@ -62,7 +62,8 @@ void method1()
qDebug() << "Error:" << reply.error().message();
exit(1);
}
- foreach (QString name, reply.value())
+ const QStringList values = reply.value();
+ for (const QString &name : values)
qDebug() << name;
}
diff --git a/examples/embedded/lightmaps/slippymap.cpp b/examples/embedded/lightmaps/slippymap.cpp
index ff43261700..da003981ff 100644
--- a/examples/embedded/lightmaps/slippymap.cpp
+++ b/examples/embedded/lightmaps/slippymap.cpp
@@ -162,7 +162,6 @@ void SlippyMap::handleNetworkData(QNetworkReply *reply)
{
QImage img;
QPoint tp = reply->request().attribute(QNetworkRequest::User).toPoint();
- QUrl url = reply->url();
if (!reply->error())
if (!img.load(reply, 0))
img = QImage();
@@ -173,10 +172,12 @@ void SlippyMap::handleNetworkData(QNetworkReply *reply)
emit updated(tileRect(tp));
// purge unused spaces
- QRect bound = m_tilesRect.adjusted(-2, -2, 2, 2);
- foreach(QPoint tp, m_tilePixmaps.keys())
- if (!bound.contains(tp))
- m_tilePixmaps.remove(tp);
+ const QRect bound = m_tilesRect.adjusted(-2, -2, 2, 2);
+ for (auto it = m_tilePixmaps.keyBegin(); it != m_tilePixmaps.keyEnd(); ++it) {
+ const QPoint &tp = *it;
+ if (!bound.contains(tp))
+ m_tilePixmaps.remove(tp);
+ }
download();
}
diff --git a/examples/embedded/raycasting/raycasting.cpp b/examples/embedded/raycasting/raycasting.cpp
index d37b9f5d2e..7213811213 100644
--- a/examples/embedded/raycasting/raycasting.cpp
+++ b/examples/embedded/raycasting/raycasting.cpp
@@ -255,11 +255,7 @@ public:
protected:
void resizeEvent(QResizeEvent*) {
-#if defined(Q_OS_WINCE_WM)
- touchDevice = true;
-#else
touchDevice = false;
-#endif
if (touchDevice) {
if (width() < height()) {
trackPad = QRect(0, height() / 2, width(), height() / 2);
diff --git a/examples/network/bearermonitor/bearermonitor.cpp b/examples/network/bearermonitor/bearermonitor.cpp
index f9b899b06b..1a54f5ec8a 100644
--- a/examples/network/bearermonitor/bearermonitor.cpp
+++ b/examples/network/bearermonitor/bearermonitor.cpp
@@ -142,7 +142,8 @@ void BearerMonitor::configurationAdded(const QNetworkConfiguration &config, QTre
treeWidget->addTopLevelItem(item);
if (config.type() == QNetworkConfiguration::ServiceNetwork) {
- foreach (const QNetworkConfiguration &child, config.children())
+ const QList<QNetworkConfiguration> children = config.children();
+ for (const QNetworkConfiguration &child : children)
configurationAdded(child, item);
}
}
@@ -181,7 +182,8 @@ void BearerMonitor::configurationChanged(const QNetworkConfiguration &config)
void BearerMonitor::updateSnapConfiguration(QTreeWidgetItem *parent, const QNetworkConfiguration &snap)
{
QMap<QString, QTreeWidgetItem *> itemMap;
- foreach (QTreeWidgetItem *item, parent->takeChildren())
+ const QList<QTreeWidgetItem *> children = parent->takeChildren();
+ for (QTreeWidgetItem *item : children)
itemMap.insert(item->data(0, Qt::UserRole).toString(), item);
QList<QNetworkConfiguration> allConfigurations = snap.children();
diff --git a/examples/network/bearermonitor/bearermonitor.pro b/examples/network/bearermonitor/bearermonitor.pro
index 7d90b408e0..16ac41298a 100644
--- a/examples/network/bearermonitor/bearermonitor.pro
+++ b/examples/network/bearermonitor/bearermonitor.pro
@@ -13,7 +13,7 @@ FORMS = bearermonitor_240_320.ui \
bearermonitor_640_480.ui \
sessionwidget.ui
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
CONFIG += console
diff --git a/examples/network/dnslookup/dnslookup.cpp b/examples/network/dnslookup/dnslookup.cpp
index 63819b170c..a2d927d43d 100644
--- a/examples/network/dnslookup/dnslookup.cpp
+++ b/examples/network/dnslookup/dnslookup.cpp
@@ -172,35 +172,43 @@ void DnsManager::showResults()
printf("Error: %i (%s)\n", dns->error(), qPrintable(dns->errorString()));
// CNAME records
- foreach (const QDnsDomainNameRecord &record, dns->canonicalNameRecords())
+ const QList<QDnsDomainNameRecord> cnameRecords = dns->canonicalNameRecords();
+ for (const QDnsDomainNameRecord &record : cnameRecords)
printf("%s\t%i\tIN\tCNAME\t%s\n", qPrintable(record.name()), record.timeToLive(), qPrintable(record.value()));
// A and AAAA records
- foreach (const QDnsHostAddressRecord &record, dns->hostAddressRecords()) {
+ const QList<QDnsHostAddressRecord> aRecords = dns->hostAddressRecords();
+ for (const QDnsHostAddressRecord &record : aRecords) {
const char *type = (record.value().protocol() == QAbstractSocket::IPv6Protocol) ? "AAAA" : "A";
printf("%s\t%i\tIN\t%s\t%s\n", qPrintable(record.name()), record.timeToLive(), type, qPrintable(record.value().toString()));
}
// MX records
- foreach (const QDnsMailExchangeRecord &record, dns->mailExchangeRecords())
+ const QList<QDnsMailExchangeRecord> mxRecords = dns->mailExchangeRecords();
+ for (const QDnsMailExchangeRecord &record : mxRecords)
printf("%s\t%i\tIN\tMX\t%u %s\n", qPrintable(record.name()), record.timeToLive(), record.preference(), qPrintable(record.exchange()));
// NS records
- foreach (const QDnsDomainNameRecord &record, dns->nameServerRecords())
+ const QList<QDnsDomainNameRecord> nsRecords = dns->nameServerRecords();
+ for (const QDnsDomainNameRecord &record : nsRecords)
printf("%s\t%i\tIN\tNS\t%s\n", qPrintable(record.name()), record.timeToLive(), qPrintable(record.value()));
// PTR records
- foreach (const QDnsDomainNameRecord &record, dns->pointerRecords())
+ const QList<QDnsDomainNameRecord> ptrRecords = dns->pointerRecords();
+ for (const QDnsDomainNameRecord &record : ptrRecords)
printf("%s\t%i\tIN\tPTR\t%s\n", qPrintable(record.name()), record.timeToLive(), qPrintable(record.value()));
// SRV records
- foreach (const QDnsServiceRecord &record, dns->serviceRecords())
+ const QList<QDnsServiceRecord> srvRecords = dns->serviceRecords();
+ for (const QDnsServiceRecord &record : srvRecords)
printf("%s\t%i\tIN\tSRV\t%u %u %u %s\n", qPrintable(record.name()), record.timeToLive(), record.priority(), record.weight(), record.port(), qPrintable(record.target()));
// TXT records
- foreach (const QDnsTextRecord &record, dns->textRecords()) {
+ const QList<QDnsTextRecord> txtRecords = dns->textRecords();
+ for (const QDnsTextRecord &record : txtRecords) {
QStringList values;
- foreach (const QByteArray &ba, record.values())
+ const QList<QByteArray> dnsRecords = record.values();
+ for (const QByteArray &ba : dnsRecords)
values << "\"" + QString::fromLatin1(ba) + "\"";
printf("%s\t%i\tIN\tTXT\t%s\n", qPrintable(record.name()), record.timeToLive(), qPrintable(values.join(' ')));
}
diff --git a/examples/network/downloadmanager/downloadmanager.cpp b/examples/network/downloadmanager/downloadmanager.cpp
index e820b4ff70..9e0c03c6af 100644
--- a/examples/network/downloadmanager/downloadmanager.cpp
+++ b/examples/network/downloadmanager/downloadmanager.cpp
@@ -132,7 +132,7 @@ void DownloadManager::startNextDownload()
// prepare the output
printf("Downloading %s...\n", url.toEncoded().constData());
- downloadTime.start();
+ downloadTimer.start();
}
void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
@@ -140,7 +140,7 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
progressBar.setStatus(bytesReceived, bytesTotal);
// calculate the download speed
- double speed = bytesReceived * 1000.0 / downloadTime.elapsed();
+ double speed = bytesReceived * 1000.0 / downloadTimer.elapsed();
QString unit;
if (speed < 1024) {
unit = "bytes/sec";
diff --git a/examples/network/downloadmanager/downloadmanager.h b/examples/network/downloadmanager/downloadmanager.h
index 4bc6351ff9..818a774f1f 100644
--- a/examples/network/downloadmanager/downloadmanager.h
+++ b/examples/network/downloadmanager/downloadmanager.h
@@ -83,7 +83,7 @@ private:
QQueue<QUrl> downloadQueue;
QNetworkReply *currentDownload = nullptr;
QFile output;
- QTime downloadTime;
+ QElapsedTimer downloadTimer;
TextProgressBar progressBar;
int downloadedCount = 0;
diff --git a/examples/network/googlesuggest/googlesuggest.cpp b/examples/network/googlesuggest/googlesuggest.cpp
index 24fdde0a5c..d27beafd1e 100644
--- a/examples/network/googlesuggest/googlesuggest.cpp
+++ b/examples/network/googlesuggest/googlesuggest.cpp
@@ -160,7 +160,7 @@ void GSuggestCompletion::showCompletion(const QVector<QString> &choices)
for (const auto &choice : choices) {
auto item = new QTreeWidgetItem(popup);
item->setText(0, choice);
- item->setTextColor(0, color);
+ item->setForeground(0, color);
}
popup->setCurrentItem(popup->topLevelItem(0));
diff --git a/examples/network/http/httpwindow.cpp b/examples/network/http/httpwindow.cpp
index ec90b8f7fe..c7bf0c0dff 100644
--- a/examples/network/http/httpwindow.cpp
+++ b/examples/network/http/httpwindow.cpp
@@ -48,13 +48,14 @@
**
****************************************************************************/
+#include "httpwindow.h"
+
+#include "ui_authenticationdialog.h"
+
#include <QtWidgets>
#include <QtNetwork>
#include <QUrl>
-#include "httpwindow.h"
-#include "ui_authenticationdialog.h"
-
#if QT_CONFIG(ssl)
const char defaultUrl[] = "https://www.qt.io/";
#else
@@ -74,6 +75,10 @@ ProgressDialog::ProgressDialog(const QUrl &url, QWidget *parent)
setMinimumSize(QSize(400, 75));
}
+ProgressDialog::~ProgressDialog()
+{
+}
+
void ProgressDialog::networkReplyProgress(qint64 bytesRead, qint64 totalBytes)
{
setMaximum(totalBytes);
@@ -137,6 +142,10 @@ HttpWindow::HttpWindow(QWidget *parent)
urlLineEdit->setFocus();
}
+HttpWindow::~HttpWindow()
+{
+}
+
void HttpWindow::startRequest(const QUrl &requestedUrl)
{
url = requestedUrl;
@@ -204,9 +213,9 @@ void HttpWindow::downloadFile()
startRequest(newUrl);
}
-QFile *HttpWindow::openFileForWrite(const QString &fileName)
+std::unique_ptr<QFile> HttpWindow::openFileForWrite(const QString &fileName)
{
- QScopedPointer<QFile> file(new QFile(fileName));
+ std::unique_ptr<QFile> file(new QFile(fileName));
if (!file->open(QIODevice::WriteOnly)) {
QMessageBox::information(this, tr("Error"),
tr("Unable to save the file %1: %2.")
@@ -214,7 +223,7 @@ QFile *HttpWindow::openFileForWrite(const QString &fileName)
file->errorString()));
return nullptr;
}
- return file.take();
+ return file;
}
void HttpWindow::cancelDownload()
@@ -231,8 +240,7 @@ void HttpWindow::httpFinished()
if (file) {
fi.setFile(file->fileName());
file->close();
- delete file;
- file = nullptr;
+ file.reset();
}
if (httpRequestAborted) {
@@ -319,7 +327,7 @@ void HttpWindow::slotAuthenticationRequired(QNetworkReply *, QAuthenticator *aut
void HttpWindow::sslErrors(QNetworkReply *, const QList<QSslError> &errors)
{
QString errorString;
- foreach (const QSslError &error, errors) {
+ for (const QSslError &error : errors) {
if (!errorString.isEmpty())
errorString += '\n';
errorString += error.errorString();
diff --git a/examples/network/http/httpwindow.h b/examples/network/http/httpwindow.h
index 20ad2bb4da..f7bd0047de 100644
--- a/examples/network/http/httpwindow.h
+++ b/examples/network/http/httpwindow.h
@@ -55,6 +55,8 @@
#include <QNetworkAccessManager>
#include <QUrl>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QFile;
class QLabel;
@@ -72,6 +74,7 @@ class ProgressDialog : public QProgressDialog {
public:
explicit ProgressDialog(const QUrl &url, QWidget *parent = nullptr);
+ ~ProgressDialog();
public slots:
void networkReplyProgress(qint64 bytesRead, qint64 totalBytes);
@@ -83,6 +86,7 @@ class HttpWindow : public QDialog
public:
explicit HttpWindow(QWidget *parent = nullptr);
+ ~HttpWindow();
void startRequest(const QUrl &requestedUrl);
@@ -98,7 +102,7 @@ private slots:
#endif
private:
- QFile *openFileForWrite(const QString &fileName);
+ std::unique_ptr<QFile> openFileForWrite(const QString &fileName);
QLabel *statusLabel;
QLineEdit *urlLineEdit;
@@ -110,7 +114,7 @@ private:
QUrl url;
QNetworkAccessManager qnam;
QNetworkReply *reply;
- QFile *file;
+ std::unique_ptr<QFile> file;
bool httpRequestAborted;
};
diff --git a/examples/network/loopback/dialog.cpp b/examples/network/loopback/dialog.cpp
index b4e6b0fd5e..d87f024031 100644
--- a/examples/network/loopback/dialog.cpp
+++ b/examples/network/loopback/dialog.cpp
@@ -99,7 +99,7 @@ void Dialog::start()
startButton->setEnabled(false);
#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(Qt::WaitCursor);
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
#endif
bytesWritten = 0;
@@ -162,7 +162,7 @@ void Dialog::updateServerProgress()
tcpServerConnection->close();
startButton->setEnabled(true);
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
}
}
@@ -198,6 +198,6 @@ void Dialog::displayError(QAbstractSocket::SocketError socketError)
serverStatusLabel->setText(tr("Server ready"));
startButton->setEnabled(true);
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
}
diff --git a/examples/network/network-chat/client.cpp b/examples/network/network-chat/client.cpp
index 97c2c44b6b..b76ef18238 100644
--- a/examples/network/network-chat/client.cpp
+++ b/examples/network/network-chat/client.cpp
@@ -71,8 +71,7 @@ void Client::sendMessage(const QString &message)
if (message.isEmpty())
return;
- QList<Connection *> connections = peers.values();
- foreach (Connection *connection, connections)
+ for (Connection *connection : qAsConst(peers))
connection->sendMessage(message);
}
@@ -90,8 +89,8 @@ bool Client::hasConnection(const QHostAddress &senderIp, int senderPort) const
if (!peers.contains(senderIp))
return false;
- QList<Connection *> connections = peers.values(senderIp);
- foreach (Connection *connection, connections) {
+ const QList<Connection *> connections = peers.values(senderIp);
+ for (const Connection *connection : connections) {
if (connection->peerPort() == senderPort)
return true;
}
diff --git a/examples/network/network-chat/peermanager.cpp b/examples/network/network-chat/peermanager.cpp
index 38fa2e8e50..5c48edb1b9 100644
--- a/examples/network/network-chat/peermanager.cpp
+++ b/examples/network/network-chat/peermanager.cpp
@@ -104,9 +104,9 @@ void PeerManager::startBroadcasting()
broadcastTimer.start();
}
-bool PeerManager::isLocalHostAddress(const QHostAddress &address)
+bool PeerManager::isLocalHostAddress(const QHostAddress &address) const
{
- foreach (QHostAddress localAddress, ipAddresses) {
+ for (const QHostAddress &localAddress : ipAddresses) {
if (address.isEqual(localAddress))
return true;
}
@@ -125,7 +125,7 @@ void PeerManager::sendBroadcastDatagram()
}
bool validBroadcastAddresses = true;
- foreach (QHostAddress address, broadcastAddresses) {
+ for (const QHostAddress &address : qAsConst(broadcastAddresses)) {
if (broadcastSocket.writeDatagram(datagram, address,
broadcastPort) == -1)
validBroadcastAddresses = false;
@@ -182,8 +182,10 @@ void PeerManager::updateAddresses()
{
broadcastAddresses.clear();
ipAddresses.clear();
- foreach (QNetworkInterface interface, QNetworkInterface::allInterfaces()) {
- foreach (QNetworkAddressEntry entry, interface.addressEntries()) {
+ const QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
+ for (const QNetworkInterface &interface : interfaces) {
+ const QList<QNetworkAddressEntry> entries = interface.addressEntries();
+ for (const QNetworkAddressEntry &entry : entries) {
QHostAddress broadcastAddress = entry.broadcast();
if (broadcastAddress != QHostAddress::Null && entry.ip() != QHostAddress::LocalHost) {
broadcastAddresses << broadcastAddress;
diff --git a/examples/network/network-chat/peermanager.h b/examples/network/network-chat/peermanager.h
index b79028235b..6105c83115 100644
--- a/examples/network/network-chat/peermanager.h
+++ b/examples/network/network-chat/peermanager.h
@@ -70,7 +70,7 @@ public:
void setServerPort(int port);
QString userName() const;
void startBroadcasting();
- bool isLocalHostAddress(const QHostAddress &address);
+ bool isLocalHostAddress(const QHostAddress &address) const;
signals:
void newConnection(Connection *connection);
diff --git a/examples/network/securesocketclient/sslclient.cpp b/examples/network/securesocketclient/sslclient.cpp
index afeec033ff..79ed7746d6 100644
--- a/examples/network/securesocketclient/sslclient.cpp
+++ b/examples/network/securesocketclient/sslclient.cpp
@@ -206,7 +206,8 @@ void SslClient::setupUi()
padLock->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
QHBoxLayout *layout = new QHBoxLayout(form->hostNameEdit);
- layout->setMargin(form->hostNameEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
+ const int margin = form->hostNameEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ layout->setContentsMargins(margin, margin, margin, margin);
layout->setSpacing(0);
layout->addStretch();
layout->addWidget(padLock);
diff --git a/examples/network/secureudpserver/server.cpp b/examples/network/secureudpserver/server.cpp
index 0d83fa9b51..450eb9e68d 100644
--- a/examples/network/secureudpserver/server.cpp
+++ b/examples/network/secureudpserver/server.cpp
@@ -62,7 +62,7 @@ QString peer_info(const QHostAddress &address, quint16 port)
return info.arg(address.toString()).arg(port);
}
-QString connection_info(QSharedPointer<QDtls> connection)
+QString connection_info(QDtls *connection)
{
QString info(DtlsServer::tr("Session cipher: "));
info += connection->sessionCipher().name();
@@ -157,7 +157,7 @@ void DtlsServer::readyRead()
}
const auto client = std::find_if(knownClients.begin(), knownClients.end(),
- [&](const DtlsConnection &connection){
+ [&](const std::unique_ptr<QDtls> &connection){
return connection->peerAddress() == peerAddress
&& connection->peerPort() == peerPort;
});
@@ -170,7 +170,7 @@ void DtlsServer::readyRead()
//! [6]
if ((*client)->isConnectionEncrypted()) {
- decryptDatagram(*client, dgram);
+ decryptDatagram(client->get(), dgram);
if ((*client)->dtlsError() == QDtlsError::RemoteClosedConnectionError)
knownClients.erase(client);
return;
@@ -178,7 +178,7 @@ void DtlsServer::readyRead()
//! [6]
//! [7]
- doHandshake(*client, dgram);
+ doHandshake(client->get(), dgram);
//! [7]
}
@@ -205,13 +205,13 @@ void DtlsServer::handleNewConnection(const QHostAddress &peerAddress,
emit infoMessage(peerInfo + tr(": verified, starting a handshake"));
//! [8]
//! [9]
- DtlsConnection newConnection(new QDtls(QSslSocket::SslServerMode));
+ std::unique_ptr<QDtls> newConnection{new QDtls{QSslSocket::SslServerMode}};
newConnection->setDtlsConfiguration(serverConfiguration);
newConnection->setPeer(peerAddress, peerPort);
- newConnection->connect(newConnection.data(), &QDtls::pskRequired,
+ newConnection->connect(newConnection.get(), &QDtls::pskRequired,
this, &DtlsServer::pskRequired);
- knownClients.push_back(newConnection);
- doHandshake(newConnection, clientHello);
+ knownClients.push_back(std::move(newConnection));
+ doHandshake(knownClients.back().get(), clientHello);
//! [9]
} else if (cookieSender.dtlsError() != QDtlsError::NoError) {
emit errorMessage(tr("DTLS error: ") + cookieSender.dtlsErrorString());
@@ -221,7 +221,7 @@ void DtlsServer::handleNewConnection(const QHostAddress &peerAddress,
}
//! [11]
-void DtlsServer::doHandshake(DtlsConnection newConnection, const QByteArray &clientHello)
+void DtlsServer::doHandshake(QDtls *newConnection, const QByteArray &clientHello)
{
const bool result = newConnection->doHandshake(&serverSocket, clientHello);
if (!result) {
@@ -246,7 +246,7 @@ void DtlsServer::doHandshake(DtlsConnection newConnection, const QByteArray &cli
//! [11]
//! [12]
-void DtlsServer::decryptDatagram(DtlsConnection connection, const QByteArray &clientMessage)
+void DtlsServer::decryptDatagram(QDtls *connection, const QByteArray &clientMessage)
{
Q_ASSERT(connection->isConnectionEncrypted());
@@ -266,10 +266,9 @@ void DtlsServer::decryptDatagram(DtlsConnection connection, const QByteArray &cl
//! [14]
void DtlsServer::shutdown()
{
- for (DtlsConnection &connection : knownClients)
+ for (const auto &connection : qExchange(knownClients, {}))
connection->shutdown(&serverSocket);
- knownClients.clear();
serverSocket.close();
}
//! [14]
diff --git a/examples/network/secureudpserver/server.h b/examples/network/secureudpserver/server.h
index b720368e7b..1af8aef8a2 100644
--- a/examples/network/secureudpserver/server.h
+++ b/examples/network/secureudpserver/server.h
@@ -54,6 +54,7 @@
#include <QtNetwork>
#include <vector>
+#include <memory>
QT_BEGIN_NAMESPACE
@@ -86,9 +87,8 @@ private:
void handleNewConnection(const QHostAddress &peerAddress, quint16 peerPort,
const QByteArray &clientHello);
- using DtlsConnection = QSharedPointer<QDtls>;
- void doHandshake(DtlsConnection newConnection, const QByteArray &clientHello);
- void decryptDatagram(DtlsConnection connection, const QByteArray &clientMessage);
+ void doHandshake(QDtls *newConnection, const QByteArray &clientHello);
+ void decryptDatagram(QDtls *connection, const QByteArray &clientMessage);
void shutdown();
bool listening = false;
@@ -96,7 +96,7 @@ private:
QSslConfiguration serverConfiguration;
QDtlsClientVerifier cookieSender;
- QVector<DtlsConnection> knownClients;
+ std::vector<std::unique_ptr<QDtls>> knownClients;
Q_DISABLE_COPY(DtlsServer)
};
diff --git a/examples/network/torrent/addtorrentdialog.cpp b/examples/network/torrent/addtorrentdialog.cpp
index 0d197ec5fa..c87110ac4a 100644
--- a/examples/network/torrent/addtorrentdialog.cpp
+++ b/examples/network/torrent/addtorrentdialog.cpp
@@ -148,7 +148,8 @@ void AddTorrentDialog::setTorrent(const QString &torrentFile)
ui.torrentContents->setHtml(metaInfo.singleFile().name);
} else {
QString html;
- foreach (MetaInfoMultiFile file, metaInfo.multiFiles()) {
+ const QList<MetaInfoMultiFile> multiFiles = metaInfo.multiFiles();
+ for (const MetaInfoMultiFile &file : multiFiles) {
QString name = metaInfo.name();
if (!name.isEmpty()) {
html += name;
diff --git a/examples/network/torrent/filemanager.cpp b/examples/network/torrent/filemanager.cpp
index d05408cebc..69345442c7 100644
--- a/examples/network/torrent/filemanager.cpp
+++ b/examples/network/torrent/filemanager.cpp
@@ -77,7 +77,7 @@ FileManager::~FileManager()
cond.wakeOne();
wait();
- foreach (QFile *file, files) {
+ for (QFile *file : qAsConst(files)) {
file->close();
delete file;
}
@@ -285,7 +285,8 @@ bool FileManager::generateFiles()
return false;
}
- foreach (const MetaInfoMultiFile &entry, metaInfo.multiFiles()) {
+ const QList<MetaInfoMultiFile> multiFiles = metaInfo.multiFiles();
+ for (const MetaInfoMultiFile &entry : multiFiles) {
QString filePath = QFileInfo(prefix + entry.path).path();
if (!QFile::exists(filePath)) {
if (!dir.mkpath(filePath)) {
@@ -437,7 +438,7 @@ void FileManager::verifyFileContents()
}
// Verify all pending pieces
- foreach (int index, newPendingVerificationRequests)
+ for (int index : qAsConst(newPendingVerificationRequests))
emit pieceVerified(index, verifySinglePiece(index));
}
diff --git a/examples/network/torrent/mainwindow.cpp b/examples/network/torrent/mainwindow.cpp
index 660472c05c..704012ef6d 100644
--- a/examples/network/torrent/mainwindow.cpp
+++ b/examples/network/torrent/mainwindow.cpp
@@ -239,7 +239,7 @@ int MainWindow::rowOfClient(TorrentClient *client) const
// Return the row that displays this client's status, or -1 if the
// client is not known.
int row = 0;
- foreach (Job job, jobs) {
+ for (const Job &job : jobs) {
if (job.client == client)
return row;
++row;
@@ -358,7 +358,7 @@ bool MainWindow::addTorrent(const QString &fileName, const QString &destinationF
const QByteArray &resumeState)
{
// Check if the torrent is already being downloaded.
- foreach (Job job, jobs) {
+ for (const Job &job : qAsConst(jobs)) {
if (job.torrentFileName == fileName && job.destinationDirectory == destinationFolder) {
QMessageBox::warning(this, tr("Already downloading"),
tr("The torrent file %1 is "
@@ -630,7 +630,7 @@ void MainWindow::about()
QPushButton *quitButton = new QPushButton("OK");
QHBoxLayout *topLayout = new QHBoxLayout;
- topLayout->setMargin(10);
+ topLayout->setContentsMargins(10, 10, 10, 10);
topLayout->setSpacing(10);
topLayout->addWidget(icon);
topLayout->addWidget(text);
@@ -684,7 +684,7 @@ void MainWindow::closeEvent(QCloseEvent *)
// them to signal that they have stopped.
jobsToStop = 0;
jobsStopped = 0;
- foreach (Job job, jobs) {
+ for (const Job &job : qAsConst(jobs)) {
++jobsToStop;
TorrentClient *client = job.client;
client->disconnect();
diff --git a/examples/network/torrent/metainfo.cpp b/examples/network/torrent/metainfo.cpp
index 565533e2f9..29b34b12a0 100644
--- a/examples/network/torrent/metainfo.cpp
+++ b/examples/network/torrent/metainfo.cpp
@@ -101,10 +101,10 @@ bool MetaInfo::parse(const QByteArray &data)
QList<QVariant> files = info.value("files").toList();
for (int i = 0; i < files.size(); ++i) {
- QMap<QByteArray, QVariant> file = qvariant_cast<Dictionary>(files.at(i));
- QList<QVariant> pathElements = file.value("path").toList();
+ const QMap<QByteArray, QVariant> file = qvariant_cast<Dictionary>(files.at(i));
+ const QList<QVariant> pathElements = file.value("path").toList();
QByteArray path;
- foreach (QVariant p, pathElements) {
+ for (const QVariant &p : pathElements) {
if (!path.isEmpty())
path += '/';
path += p.toByteArray();
@@ -221,7 +221,7 @@ qint64 MetaInfo::totalSize() const
return singleFile().length;
qint64 size = 0;
- foreach (MetaInfoMultiFile file, multiFiles())
+ for (const MetaInfoMultiFile &file : metaInfoMultiFiles)
size += file.length;
return size;
}
diff --git a/examples/network/torrent/ratecontroller.cpp b/examples/network/torrent/ratecontroller.cpp
index cec05c7455..96474806f5 100644
--- a/examples/network/torrent/ratecontroller.cpp
+++ b/examples/network/torrent/ratecontroller.cpp
@@ -78,7 +78,7 @@ void RateController::removeSocket(PeerWireClient *socket)
void RateController::setDownloadLimit(int bytesPerSecond)
{
downLimit = bytesPerSecond;
- foreach (PeerWireClient *socket, sockets)
+ for (PeerWireClient *socket : qAsConst(sockets))
socket->setReadBufferSize(downLimit * 4);
}
@@ -96,8 +96,8 @@ void RateController::transfer()
if (sockets.isEmpty())
return;
- int msecs = 1000;
- if (!stopWatch.isNull())
+ qint64 msecs = 1000;
+ if (stopWatch.isValid())
msecs = qMin(msecs, stopWatch.elapsed());
qint64 bytesToWrite = (upLimit * msecs) / 1000;
@@ -108,7 +108,7 @@ void RateController::transfer()
}
QSet<PeerWireClient *> pendingSockets;
- foreach (PeerWireClient *client, sockets) {
+ for (PeerWireClient *client : qAsConst(sockets)) {
if (client->canTransferMore())
pendingSockets << client;
}
@@ -123,11 +123,11 @@ void RateController::transfer()
qint64 writeChunk = qMax<qint64>(1, bytesToWrite / pendingSockets.size());
qint64 readChunk = qMax<qint64>(1, bytesToRead / pendingSockets.size());
- QSetIterator<PeerWireClient *> it(pendingSockets);
- while (it.hasNext() && (bytesToWrite > 0 || bytesToRead > 0)) {
- PeerWireClient *socket = it.next();
+ for (auto it = pendingSockets.begin(), end = pendingSockets.end(); it != end && (bytesToWrite > 0 || bytesToRead > 0); /*erasing*/) {
+ auto current = it++;
+ PeerWireClient *socket = *current;
if (socket->state() != QAbstractSocket::ConnectedState) {
- pendingSockets.remove(socket);
+ pendingSockets.erase(current);
continue;
}
@@ -156,7 +156,7 @@ void RateController::transfer()
if (dataTransferred && socket->canTransferMore())
canTransferMore = true;
else
- pendingSockets.remove(socket);
+ pendingSockets.erase(current);
}
} while (canTransferMore && (bytesToWrite > 0 || bytesToRead > 0) && !pendingSockets.isEmpty());
diff --git a/examples/network/torrent/ratecontroller.h b/examples/network/torrent/ratecontroller.h
index a4aa596ce1..f8bff0cc36 100644
--- a/examples/network/torrent/ratecontroller.h
+++ b/examples/network/torrent/ratecontroller.h
@@ -53,7 +53,7 @@
#include <QObject>
#include <QSet>
-#include <QTime>
+#include <QElapsedTimer>
class PeerWireClient;
@@ -79,7 +79,7 @@ public slots:
void scheduleTransfer();
private:
- QTime stopWatch;
+ QElapsedTimer stopWatch;
QSet<PeerWireClient *> sockets;
int upLimit;
int downLimit;
diff --git a/examples/network/torrent/torrentclient.cpp b/examples/network/torrent/torrentclient.cpp
index 95232646ab..bddf3caa1a 100644
--- a/examples/network/torrent/torrentclient.cpp
+++ b/examples/network/torrent/torrentclient.cpp
@@ -383,7 +383,7 @@ qint64 TorrentClient::uploadedBytes() const
int TorrentClient::connectedPeerCount() const
{
int tmp = 0;
- foreach (PeerWireClient *client, d->connections) {
+ for (PeerWireClient *client : d->connections) {
if (client->state() == QAbstractSocket::ConnectedState)
++tmp;
}
@@ -393,7 +393,7 @@ int TorrentClient::connectedPeerCount() const
int TorrentClient::seedCount() const
{
int tmp = 0;
- foreach (PeerWireClient *client, d->connections) {
+ for (PeerWireClient *client : d->connections) {
if (client->availablePieces().count(true) == d->pieceCount)
++tmp;
}
@@ -464,7 +464,7 @@ void TorrentClient::stop()
}
// Abort all existing connections
- foreach (PeerWireClient *client, d->connections) {
+ for (PeerWireClient *client : qAsConst(d->connections)) {
RateController::instance()->removeSocket(client);
ConnectionManager::instance()->removeConnection(client);
client->abort();
@@ -487,7 +487,7 @@ void TorrentClient::setPaused(bool paused)
// connections to 0. Keep the list of peers, so we can quickly
// resume later.
d->setState(Paused);
- foreach (PeerWireClient *client, d->connections)
+ for (PeerWireClient *client : qAsConst(d->connections))
client->abort();
d->connections.clear();
TorrentServer::instance()->removeClient(this);
@@ -622,7 +622,7 @@ void TorrentClient::pieceVerified(int pieceIndex, bool ok)
}
// Update the peer list so we know who's still interesting.
- foreach (TorrentPeer *peer, d->peers) {
+ for (TorrentPeer *peer : qAsConst(d->peers)) {
if (!peer->interesting)
continue;
bool interesting = false;
@@ -642,7 +642,7 @@ void TorrentClient::pieceVerified(int pieceIndex, bool ok)
d->incompletePieces.clearBit(pieceIndex);
// Notify connected peers.
- foreach (PeerWireClient *client, d->connections) {
+ for (PeerWireClient *client : qAsConst(d->connections)) {
if (client->state() == QAbstractSocket::ConnectedState
&& !client->availablePieces().testBit(pieceIndex)) {
client->sendPieceNotification(pieceIndex);
@@ -720,9 +720,9 @@ QList<TorrentPeer *> TorrentClient::weighedFreePeers() const
qint64 now = QDateTime::currentSecsSinceEpoch();
QList<TorrentPeer *> freePeers;
QMap<QString, int> connectionsPerPeer;
- foreach (TorrentPeer *peer, d->peers) {
+ for (TorrentPeer *peer : qAsConst(d->peers)) {
bool busy = false;
- foreach (PeerWireClient *client, d->connections) {
+ for (PeerWireClient *client : qAsConst(d->connections)) {
if (client->state() == PeerWireClient::ConnectedState
&& client->peerAddress() == peer->address
&& client->peerPort() == peer->port) {
@@ -742,7 +742,7 @@ QList<TorrentPeer *> TorrentClient::weighedFreePeers() const
// Assign points based on connection speed and pieces available.
QList<QPair<int, TorrentPeer *> > points;
- foreach (TorrentPeer *peer, freePeers) {
+ for (TorrentPeer *peer : qAsConst(freePeers)) {
int tmp = 0;
if (peer->interesting) {
tmp += peer->numCompletedPieces;
@@ -765,7 +765,7 @@ QList<TorrentPeer *> TorrentClient::weighedFreePeers() const
QMultiMap<int, TorrentPeer *> pointMap;
int lowestScore = 0;
int lastIndex = 0;
- foreach (PointPair point, points) {
+ for (const PointPair &point : qAsConst(points)) {
if (point.first > lowestScore) {
lowestScore = point.first;
++lastIndex;
@@ -816,7 +816,7 @@ void TorrentClient::setupOutgoingConnection()
PeerWireClient *client = qobject_cast<PeerWireClient *>(sender());
// Update connection statistics.
- foreach (TorrentPeer *peer, d->peers) {
+ for (TorrentPeer *peer : qAsConst(d->peers)) {
if (peer->port == client->peerPort() && peer->address == client->peerAddress()) {
peer->connectTime = peer->lastVisited - peer->connectStart;
break;
@@ -874,8 +874,7 @@ void TorrentClient::removeClient()
// Remove the client from RateController and all structures.
RateController::instance()->removeSocket(client);
d->connections.removeAll(client);
- QMultiMap<PeerWireClient *, TorrentPiece *>::Iterator it = d->payloads.find(client);
- while (it != d->payloads.end() && it.key() == client) {
+ for (auto it = d->payloads.find(client); it != d->payloads.end() && it.key() == client; /*erasing*/) {
TorrentPiece *piece = it.value();
piece->inProgress = false;
piece->requestedBlocks.fill(false);
@@ -883,9 +882,12 @@ void TorrentClient::removeClient()
}
// Remove pending read requests.
- QMapIterator<int, PeerWireClient *> it2(d->readIds);
- while (it2.findNext(client))
- d->readIds.remove(it2.key());
+ for (auto it = d->readIds.begin(), end = d->readIds.end(); it != end; /*erasing*/) {
+ if (it.value() == client)
+ it = d->readIds.erase(it);
+ else
+ ++it;
+ }
// Delete the client later.
disconnect(client, SIGNAL(disconnected()), this, SLOT(removeClient()));
@@ -1084,25 +1086,25 @@ void TorrentClient::scheduleUploads()
// seeding, we sort by upload speed. Seeds are left out; there's
// no use in unchoking them.
QList<PeerWireClient *> allClients = d->connections;
- QMultiMap<int, PeerWireClient *> transferSpeeds;
- foreach (PeerWireClient *client, allClients) {
+ QVector<QPair<qint64, PeerWireClient *>> transferSpeeds;
+ for (PeerWireClient *client : qAsConst(allClients)) {
if (client->state() == QAbstractSocket::ConnectedState
&& client->availablePieces().count(true) != d->pieceCount) {
if (d->state == Seeding) {
- transferSpeeds.insert(client->uploadSpeed(), client);
+ transferSpeeds.push_back({client->uploadSpeed(), client});
} else {
- transferSpeeds.insert(client->downloadSpeed(), client);
+ transferSpeeds.push_back({client->downloadSpeed(), client});
}
}
}
+ std::sort(transferSpeeds.begin(), transferSpeeds.end());
+
// Unchoke the top 'MaxUploads' downloaders (peers that we are
// uploading to) and choke all others.
int maxUploaders = MaxUploads;
- QMapIterator<int, PeerWireClient *> it(transferSpeeds);
- it.toBack();
- while (it.hasPrevious()) {
- PeerWireClient *client = it.previous().value();
+ for (auto rit = transferSpeeds.crbegin(), rend = transferSpeeds.crend(); rit != rend; ++rit) {
+ PeerWireClient *client = rit->second;
bool interested = (client->peerWireState() & PeerWireClient::PeerIsInterested);
if (maxUploaders) {
@@ -1143,7 +1145,7 @@ void TorrentClient::scheduleDownloads()
// Check what each client is doing, and assign payloads to those
// who are either idle or done.
- foreach (PeerWireClient *client, d->connections)
+ for (PeerWireClient *client : qAsConst(d->connections))
schedulePieceForClient(client);
}
@@ -1222,7 +1224,7 @@ void TorrentClient::schedulePieceForClient(PeerWireClient *client)
incompletePiecesAvailableToClient &= client->availablePieces();
// Remove all pieces that this client has already requested.
- foreach (int i, currentPieces)
+ for (int i : qAsConst(currentPieces))
incompletePiecesAvailableToClient.clearBit(i);
// Only continue if more pieces can be scheduled. If no pieces
@@ -1258,7 +1260,7 @@ void TorrentClient::schedulePieceForClient(PeerWireClient *client)
memset(occurrences, 0, d->pieceCount * sizeof(int));
// Count how many of each piece are available.
- foreach (PeerWireClient *peer, d->connections) {
+ for (PeerWireClient *peer : qAsConst(d->connections)) {
QBitArray peerPieces = peer->availablePieces();
int peerPiecesSize = peerPieces.size();
for (int i = 0; i < peerPiecesSize; ++i) {
@@ -1356,7 +1358,7 @@ void TorrentClient::requestMore(PeerWireClient *client)
// Starting with the first piece that we're waiting for, request
// blocks until the quota is filled up.
- foreach (TorrentPiece *piece, piecesInProgress) {
+ for (TorrentPiece *piece : qAsConst(piecesInProgress)) {
numBlocksInProgress += requestBlocks(client, piece, maxInProgress - numBlocksInProgress);
if (numBlocksInProgress == maxInProgress)
break;
@@ -1450,8 +1452,8 @@ void TorrentClient::peerUnchoked()
void TorrentClient::addToPeerList(const QList<TorrentPeer> &peerList)
{
// Add peers we don't already know of to our list of peers.
- QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
- foreach (TorrentPeer peer, peerList) {
+ const QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
+ for (const TorrentPeer &peer : peerList) {
if (addresses.contains(peer.address)
&& peer.port == TorrentServer::instance()->serverPort()) {
// Skip our own server.
@@ -1459,7 +1461,7 @@ void TorrentClient::addToPeerList(const QList<TorrentPeer> &peerList)
}
bool known = false;
- foreach (TorrentPeer *knownPeer, d->peers) {
+ for (const TorrentPeer *knownPeer : qAsConst(d->peers)) {
if (knownPeer->port == peer.port
&& knownPeer->address == peer.address) {
known = true;
@@ -1484,30 +1486,26 @@ void TorrentClient::addToPeerList(const QList<TorrentPeer> &peerList)
// of the peers that have no (or low) activity.
int maxPeers = ConnectionManager::instance()->maxConnections() * 3;
if (d->peers.size() > maxPeers) {
+ auto tooMany = d->peers.size() - maxPeers;
+
// Find what peers are currently connected & active
- QSet<TorrentPeer *> activePeers;
- foreach (TorrentPeer *peer, d->peers) {
- foreach (PeerWireClient *client, d->connections) {
+ const auto firstNInactivePeers = [&tooMany, this] (TorrentPeer *peer) {
+ if (!tooMany)
+ return false;
+ for (const PeerWireClient *client : qAsConst(d->connections)) {
if (client->peer() == peer && (client->downloadSpeed() + client->uploadSpeed()) > 1024)
- activePeers << peer;
+ return false;
}
- }
-
+ --tooMany;
+ return true;
+ };
// Remove inactive peers from the peer list until we're below
// the max connections count.
- QList<int> toRemove;
- for (int i = 0; i < d->peers.size() && (d->peers.size() - toRemove.size()) > maxPeers; ++i) {
- if (!activePeers.contains(d->peers.at(i)))
- toRemove << i;
- }
- QListIterator<int> toRemoveIterator(toRemove);
- toRemoveIterator.toBack();
- while (toRemoveIterator.hasPrevious())
- d->peers.removeAt(toRemoveIterator.previous());
-
+ d->peers.erase(std::remove_if(d->peers.begin(), d->peers.end(),
+ firstNInactivePeers),
+ d->peers.end());
// If we still have too many peers, remove the oldest ones.
- while (d->peers.size() > maxPeers)
- d->peers.takeFirst();
+ d->peers.erase(d->peers.begin(), d->peers.begin() + tooMany);
}
if (d->state != Paused && d->state != Stopping && d->state != Idle) {
diff --git a/examples/network/torrent/torrentserver.cpp b/examples/network/torrent/torrentserver.cpp
index da98529fe0..c68f33249c 100644
--- a/examples/network/torrent/torrentserver.cpp
+++ b/examples/network/torrent/torrentserver.cpp
@@ -102,7 +102,7 @@ void TorrentServer::removeClient()
void TorrentServer::processInfoHash(const QByteArray &infoHash)
{
PeerWireClient *peer = qobject_cast<PeerWireClient *>(sender());
- foreach (TorrentClient *client, clients) {
+ for (TorrentClient *client : qAsConst(clients)) {
if (client->state() >= TorrentClient::Searching && client->infoHash() == infoHash) {
peer->disconnect(peer, 0, this, 0);
client->setupIncomingConnection(peer);
diff --git a/examples/opengl/contextinfo/widget.cpp b/examples/opengl/contextinfo/widget.cpp
index a5d9e98bf8..0762c91662 100644
--- a/examples/opengl/contextinfo/widget.cpp
+++ b/examples/opengl/contextinfo/widget.cpp
@@ -384,10 +384,10 @@ void Widget::renderWindowReady()
m_output->append(tr("Qt OpenGL library handle: %1")
.arg(QString::number(qintptr(QOpenGLContext::openGLModuleHandle()), 16)));
- QList<QByteArray> extensionList = context->extensions().toList();
+ QList<QByteArray> extensionList = context->extensions().values();
std::sort(extensionList.begin(), extensionList.end());
m_extensions->append(tr("Found %1 extensions:").arg(extensionList.count()));
- Q_FOREACH (const QByteArray &ext, extensionList)
+ for (const QByteArray &ext : qAsConst(extensionList))
m_extensions->append(QString::fromLatin1(ext));
m_output->moveCursor(QTextCursor::Start);
diff --git a/examples/opengl/legacy/overpainting/glwidget.cpp b/examples/opengl/legacy/overpainting/glwidget.cpp
index 1ec7bd731c..0094f8ead7 100644
--- a/examples/opengl/legacy/overpainting/glwidget.cpp
+++ b/examples/opengl/legacy/overpainting/glwidget.cpp
@@ -201,7 +201,7 @@ void GLWidget::paintEvent(QPaintEvent *event)
//! [10]
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
- foreach (Bubble *bubble, bubbles) {
+ for (Bubble *bubble : qAsConst(bubbles)) {
if (bubble->rect().intersects(event->rect()))
bubble->drawBubble(&painter);
}
@@ -247,12 +247,8 @@ void GLWidget::createBubbles(int number)
//! [13]
void GLWidget::animate()
{
- QMutableListIterator<Bubble*> iter(bubbles);
-
- while (iter.hasNext()) {
- Bubble *bubble = iter.next();
+ for (Bubble *bubble : qAsConst(bubbles))
bubble->move(rect());
- }
update();
}
//! [13]
diff --git a/examples/opengl/qopenglwidget/glwidget.cpp b/examples/opengl/qopenglwidget/glwidget.cpp
index 3fe919f94b..5057291f12 100644
--- a/examples/opengl/qopenglwidget/glwidget.cpp
+++ b/examples/opengl/qopenglwidget/glwidget.cpp
@@ -385,10 +385,10 @@ void GLWidget::paintGL()
painter.endNativePainting();
- if (m_showBubbles)
- foreach (Bubble *bubble, m_bubbles) {
+ if (m_showBubbles) {
+ for (Bubble *bubble : qAsConst(m_bubbles))
bubble->drawBubble(&painter);
- }
+ }
if (const int elapsed = m_time.elapsed()) {
QString framesPerSecond;
@@ -399,12 +399,9 @@ void GLWidget::paintGL()
painter.end();
- QMutableListIterator<Bubble*> iter(m_bubbles);
-
- while (iter.hasNext()) {
- Bubble *bubble = iter.next();
+ for (Bubble *bubble : qAsConst(m_bubbles))
bubble->move(rect());
- }
+
if (!(m_frames % 100)) {
m_time.start();
m_frames = 0;
diff --git a/examples/opengl/qopenglwidget/glwidget.h b/examples/opengl/qopenglwidget/glwidget.h
index de7805a907..0ad2581cb8 100644
--- a/examples/opengl/qopenglwidget/glwidget.h
+++ b/examples/opengl/qopenglwidget/glwidget.h
@@ -56,7 +56,7 @@
#include <QOpenGLBuffer>
#include <QVector3D>
#include <QMatrix4x4>
-#include <QTime>
+#include <QElapsedTimer>
#include <QVector>
#include <QPushButton>
@@ -106,7 +106,7 @@ private:
bool m_qtLogo;
QList<Bubble *> m_bubbles;
int m_frames;
- QTime m_time;
+ QElapsedTimer m_time;
QOpenGLShader *m_vshader1;
QOpenGLShader *m_fshader1;
QOpenGLShader *m_vshader2;
diff --git a/examples/opengl/qopenglwidget/mainwindow.cpp b/examples/opengl/qopenglwidget/mainwindow.cpp
index 4bd123628f..6fab3df79e 100644
--- a/examples/opengl/qopenglwidget/mainwindow.cpp
+++ b/examples/opengl/qopenglwidget/mainwindow.cpp
@@ -176,7 +176,7 @@ void MainWindow::timerUsageChanged(bool enabled)
m_timer->start();
} else {
m_timer->stop();
- foreach (QOpenGLWidget *w, m_glWidgets)
+ for (QOpenGLWidget *w : qAsConst(m_glWidgets))
w->update();
}
}
diff --git a/examples/opengl/threadedqopenglwidget/main.cpp b/examples/opengl/threadedqopenglwidget/main.cpp
index b9e491040f..983f608543 100644
--- a/examples/opengl/threadedqopenglwidget/main.cpp
+++ b/examples/opengl/threadedqopenglwidget/main.cpp
@@ -58,6 +58,8 @@
#include "mainwindow.h"
#include "glwidget.h"
+#include <memory>
+
static QString getGlString(QOpenGLFunctions *functions, GLenum name)
{
if (const GLubyte *p = functions->glGetString(name))
@@ -104,8 +106,8 @@ int main( int argc, char ** argv )
const QString toolTip = supportsThreading ? glInfo : glInfo + QStringLiteral("\ndoes not support threaded OpenGL.");
topLevelGlWidget.setToolTip(toolTip);
- QScopedPointer<MainWindow> mw1;
- QScopedPointer<MainWindow> mw2;
+ std::unique_ptr<MainWindow> mw1;
+ std::unique_ptr<MainWindow> mw2;
if (!parser.isSet(singleOption)) {
if (supportsThreading) {
pos += QPoint(100, 100);
diff --git a/examples/qpa/windows/main.cpp b/examples/qpa/windows/main.cpp
index 9d22d146d8..80f44ae0dc 100644
--- a/examples/qpa/windows/main.cpp
+++ b/examples/qpa/windows/main.cpp
@@ -79,9 +79,9 @@ int main(int argc, char **argv)
// create one window on each additional screen as well
- QList<QScreen *> screens = app.screens();
QList<WindowPtr> windows;
- foreach (QScreen *screen, screens) {
+ const QList<QScreen *> screens = app.screens();
+ for (QScreen *screen : screens) {
if (screen == app.primaryScreen())
continue;
WindowPtr window(new Window(screen));
diff --git a/examples/qtconcurrent/wordcount/main.cpp b/examples/qtconcurrent/wordcount/main.cpp
index ff7ea24ee7..ae8542a761 100644
--- a/examples/qtconcurrent/wordcount/main.cpp
+++ b/examples/qtconcurrent/wordcount/main.cpp
@@ -54,7 +54,7 @@
#include <QString>
#include <QStringList>
#include <QDir>
-#include <QTime>
+#include <QElapsedTimer>
#include <QApplication>
#include <QDebug>
@@ -126,11 +126,8 @@ WordCount countWords(const QString &file)
// at a time.
void reduce(WordCount &result, const WordCount &w)
{
- QMapIterator<QString, int> i(w);
- while (i.hasNext()) {
- i.next();
+ for (auto i = w.begin(), end = w.end(); i != end; ++i)
result[i.key()] += i.value();
- }
}
int main(int argc, char** argv)
@@ -149,19 +146,19 @@ int main(int argc, char** argv)
int singleThreadTime = 0;
{
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
WordCount total = singleThreadedWordCount(files);
- singleThreadTime = time.elapsed();
+ singleThreadTime = timer.elapsed();
qDebug() << "single thread" << singleThreadTime;
}
int mapReduceTime = 0;
{
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
WordCount total = mappedReduced(files, countWords, reduce);
- mapReduceTime = time.elapsed();
+ mapReduceTime = timer.elapsed();
qDebug() << "MapReduce" << mapReduceTime;
}
qDebug() << "MapReduce speedup x" << ((double)singleThreadTime - (double)mapReduceTime) / (double)mapReduceTime + 1;
diff --git a/examples/sql/drilldown/imageitem.cpp b/examples/sql/drilldown/imageitem.cpp
index 04ec614755..72de623373 100644
--- a/examples/sql/drilldown/imageitem.cpp
+++ b/examples/sql/drilldown/imageitem.cpp
@@ -109,9 +109,8 @@ void ImageItem::setFrame(int frame)
//! [4]
void ImageItem::adjust()
{
- QMatrix matrix;
- matrix.scale(120/ boundingRect().width(), 120/ boundingRect().height());
- setMatrix(matrix);
+ setTransform(QTransform::fromScale(120 / boundingRect().width(),
+ 120 / boundingRect().height()));
}
//! [4]
diff --git a/examples/sql/querymodel/customsqlmodel.cpp b/examples/sql/querymodel/customsqlmodel.cpp
index 21bedee727..7be0a65882 100644
--- a/examples/sql/querymodel/customsqlmodel.cpp
+++ b/examples/sql/querymodel/customsqlmodel.cpp
@@ -67,7 +67,7 @@ QVariant CustomSqlModel::data(const QModelIndex &index, int role) const
else if (index.column() == 2)
return value.toString().toUpper();
}
- if (role == Qt::TextColorRole && index.column() == 1)
+ if (role == Qt::ForegroundRole && index.column() == 1)
return QVariant::fromValue(QColor(Qt::blue));
return value;
}
diff --git a/examples/sql/relationaltablemodel/relationaltablemodel.cpp b/examples/sql/relationaltablemodel/relationaltablemodel.cpp
index c3c7d48d70..df4eae6e6e 100644
--- a/examples/sql/relationaltablemodel/relationaltablemodel.cpp
+++ b/examples/sql/relationaltablemodel/relationaltablemodel.cpp
@@ -53,6 +53,8 @@
#include "../connection.h"
+#include <memory>
+
void initializeModel(QSqlRelationalTableModel *model)
{
//! [0]
@@ -76,12 +78,12 @@ void initializeModel(QSqlRelationalTableModel *model)
model->select();
}
-QTableView *createView(const QString &title, QSqlTableModel *model)
+std::unique_ptr<QTableView> createView(const QString &title, QSqlTableModel *model)
{
//! [4]
- QTableView *view = new QTableView;
+ std::unique_ptr<QTableView> view{new QTableView};
view->setModel(model);
- view->setItemDelegate(new QSqlRelationalDelegate(view));
+ view->setItemDelegate(new QSqlRelationalDelegate(view.get()));
//! [4]
view->setWindowTitle(title);
return view;
@@ -118,7 +120,7 @@ int main(int argc, char *argv[])
initializeModel(&model);
- QScopedPointer<QTableView> view(createView(QObject::tr("Relational Table Model"), &model));
+ std::unique_ptr<QTableView> view = createView(QObject::tr("Relational Table Model"), &model);
view->show();
return app.exec();
diff --git a/examples/vulkan/hellovulkancubes/renderer.cpp b/examples/vulkan/hellovulkancubes/renderer.cpp
index 5ada79ce79..f104d79002 100644
--- a/examples/vulkan/hellovulkancubes/renderer.cpp
+++ b/examples/vulkan/hellovulkancubes/renderer.cpp
@@ -49,6 +49,7 @@
****************************************************************************/
#include "renderer.h"
+#include "qrandom.h"
#include <QVulkanFunctions>
#include <QtConcurrentRun>
#include <QTime>
@@ -77,8 +78,6 @@ Renderer::Renderer(VulkanWindow *w, int initialCount)
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);
@@ -793,7 +792,9 @@ void Renderer::ensureInstanceBuffer()
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); };
+ auto gen = [](int a, int b) {
+ return float(QRandomGenerator::global()->bounded(double(b - a)) + 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) };
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp
index 81daa9bb96..cf95a0e6a0 100644
--- a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp
@@ -140,12 +140,12 @@ void VulkanRenderer::initResources()
m_devFuncs = inst->deviceFunctions(m_window->device());
QString info;
- info += QString().sprintf("Number of physical devices: %d\n", m_window->availablePhysicalDevices().count());
+ info += QString::asprintf("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",
+ info += QString::asprintf("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),
@@ -154,19 +154,19 @@ void VulkanRenderer::initResources()
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 += QString::asprintf(" %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 += QString::asprintf(" %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 += QString::asprintf(" %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::asprintf(" %s\n", ext.constData());
- info += QString().sprintf("Color format: %u\nDepth-stencil format: %u\n",
+ info += QString::asprintf("Color format: %u\nDepth-stencil format: %u\n",
m_window->colorFormat(), m_window->depthStencilFormat());
info += QStringLiteral("Supported sample counts:");
diff --git a/examples/widgets/animation/animatedtiles/main.cpp b/examples/widgets/animation/animatedtiles/main.cpp
index 8edd64e482..553b620e41 100644
--- a/examples/widgets/animation/animatedtiles/main.cpp
+++ b/examples/widgets/animation/animatedtiles/main.cpp
@@ -69,7 +69,7 @@ class Button : public QGraphicsWidget
{
Q_OBJECT
public:
- Button(const QPixmap &pixmap, QGraphicsItem *parent = 0)
+ Button(const QPixmap &pixmap, QGraphicsItem *parent = nullptr)
: QGraphicsWidget(parent), _pix(pixmap)
{
setAcceptHoverEvents(true);
diff --git a/examples/widgets/animation/easing/window.cpp b/examples/widgets/animation/easing/window.cpp
index 8c03e0534d..aa12147388 100644
--- a/examples/widgets/animation/easing/window.cpp
+++ b/examples/widgets/animation/easing/window.cpp
@@ -66,11 +66,16 @@ Window::Window(QWidget *parent)
m_ui.amplitudeSpinBox->setValue(dummy.amplitude());
m_ui.overshootSpinBox->setValue(dummy.overshoot());
- connect(m_ui.easingCurvePicker, SIGNAL(currentRowChanged(int)), this, SLOT(curveChanged(int)));
- connect(buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(pathChanged(int)));
- connect(m_ui.periodSpinBox, SIGNAL(valueChanged(double)), this, SLOT(periodChanged(double)));
- connect(m_ui.amplitudeSpinBox, SIGNAL(valueChanged(double)), this, SLOT(amplitudeChanged(double)));
- connect(m_ui.overshootSpinBox, SIGNAL(valueChanged(double)), this, SLOT(overshootChanged(double)));
+ connect(m_ui.easingCurvePicker, &QListWidget::currentRowChanged,
+ this, &Window::curveChanged);
+ connect(buttonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked),
+ this, &Window::pathChanged);
+ connect(m_ui.periodSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
+ this, &Window::periodChanged);
+ connect(m_ui.amplitudeSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
+ this, &Window::amplitudeChanged);
+ connect(m_ui.overshootSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
+ this, &Window::overshootChanged);
createCurveIcons();
QPixmap pix(QLatin1String(":/images/qt-logo.png"));
diff --git a/examples/widgets/animation/easing/window.h b/examples/widgets/animation/easing/window.h
index 2b7b2a5bf3..541377a981 100644
--- a/examples/widgets/animation/easing/window.h
+++ b/examples/widgets/animation/easing/window.h
@@ -66,7 +66,7 @@ public:
class Window : public QWidget {
Q_OBJECT
public:
- Window(QWidget *parent = 0);
+ Window(QWidget *parent = nullptr);
private slots:
void curveChanged(int row);
void pathChanged(int index);
diff --git a/examples/widgets/animation/moveblocks/main.cpp b/examples/widgets/animation/moveblocks/main.cpp
index 6d17696108..d03b57cd5e 100644
--- a/examples/widgets/animation/moveblocks/main.cpp
+++ b/examples/widgets/animation/moveblocks/main.cpp
@@ -169,7 +169,8 @@ class GraphicsView : public QGraphicsView
{
Q_OBJECT
public:
- GraphicsView(QGraphicsScene *scene, QWidget *parent = NULL) : QGraphicsView(scene, parent)
+ GraphicsView(QGraphicsScene *scene, QWidget *parent = nullptr)
+ : QGraphicsView(scene, parent)
{
}
@@ -214,7 +215,7 @@ int main(int argc, char **argv)
QTimer timer;
timer.setInterval(1250);
timer.setSingleShot(true);
- QObject::connect(group, SIGNAL(entered()), &timer, SLOT(start()));
+ QObject::connect(group, &QState::entered, &timer, QOverload<>::of(&QTimer::start));
//![2]
//![3]
@@ -302,7 +303,7 @@ int main(int argc, char **argv)
//![7]
StateSwitcher *stateSwitcher = new StateSwitcher(&machine);
stateSwitcher->setObjectName("stateSwitcher");
- group->addTransition(&timer, SIGNAL(timeout()), stateSwitcher);
+ group->addTransition(&timer, &QTimer::timeout, stateSwitcher);
stateSwitcher->addState(state1, &animationGroup);
stateSwitcher->addState(state2, &animationGroup);
//![7]
diff --git a/examples/widgets/animation/states/main.cpp b/examples/widgets/animation/states/main.cpp
index 14d193c301..0f61b7457a 100644
--- a/examples/widgets/animation/states/main.cpp
+++ b/examples/widgets/animation/states/main.cpp
@@ -214,7 +214,7 @@ int main(int argc, char *argv[])
state3->assignProperty(p5, "opacity", qreal(1));
state3->assignProperty(p6, "opacity", qreal(1));
- QAbstractTransition *t1 = state1->addTransition(button, SIGNAL(clicked()), state2);
+ QAbstractTransition *t1 = state1->addTransition(button, &QAbstractButton::clicked, state2);
QSequentialAnimationGroup *animation1SubGroup = new QSequentialAnimationGroup;
animation1SubGroup->addPause(250);
animation1SubGroup->addAnimation(new QPropertyAnimation(box, "geometry"));
@@ -239,7 +239,7 @@ int main(int argc, char *argv[])
t1->addAnimation(new QPropertyAnimation(p5, "opacity"));
t1->addAnimation(new QPropertyAnimation(p6, "opacity"));
- QAbstractTransition *t2 = state2->addTransition(button, SIGNAL(clicked()), state3);
+ QAbstractTransition *t2 = state2->addTransition(button, &QAbstractButton::clicked, state3);
t2->addAnimation(new QPropertyAnimation(box, "geometry"));
t2->addAnimation(new QPropertyAnimation(widget, "geometry"));
t2->addAnimation(new QPropertyAnimation(p1, "pos"));
@@ -261,7 +261,7 @@ int main(int argc, char *argv[])
t2->addAnimation(new QPropertyAnimation(p5, "opacity"));
t2->addAnimation(new QPropertyAnimation(p6, "opacity"));
- QAbstractTransition *t3 = state3->addTransition(button, SIGNAL(clicked()), state1);
+ QAbstractTransition *t3 = state3->addTransition(button, &QAbstractButton::clicked, state1);
t3->addAnimation(new QPropertyAnimation(box, "geometry"));
t3->addAnimation(new QPropertyAnimation(widget, "geometry"));
t3->addAnimation(new QPropertyAnimation(p1, "pos"));
diff --git a/examples/widgets/animation/stickman/animation.cpp b/examples/widgets/animation/stickman/animation.cpp
index 94a92749bc..5c2d1682af 100644
--- a/examples/widgets/animation/stickman/animation.cpp
+++ b/examples/widgets/animation/stickman/animation.cpp
@@ -159,18 +159,16 @@ void Animation::save(QIODevice *device) const
QDataStream stream(device);
stream << m_name;
stream << m_frames.size();
- foreach (Frame *frame, m_frames) {
+ for (const Frame *frame : qAsConst(m_frames)) {
stream << frame->nodeCount();
- for (int i=0; i<frame->nodeCount(); ++i)
+ for (int i = 0; i < frame->nodeCount(); ++i)
stream << frame->nodePos(i);
}
}
void Animation::load(QIODevice *device)
{
- if (!m_frames.isEmpty())
- qDeleteAll(m_frames);
-
+ qDeleteAll(m_frames);
m_frames.clear();
QDataStream stream(device);
diff --git a/examples/widgets/animation/stickman/graphicsview.cpp b/examples/widgets/animation/stickman/graphicsview.cpp
index 9cb57fcd9e..7058e15345 100644
--- a/examples/widgets/animation/stickman/graphicsview.cpp
+++ b/examples/widgets/animation/stickman/graphicsview.cpp
@@ -55,7 +55,9 @@
#include <QtWidgets/QGraphicsScene>
#include <QtWidgets/QGraphicsView>
-GraphicsView::GraphicsView(QWidget *parent) : QGraphicsView(parent), m_editor(0) {}
+GraphicsView::GraphicsView(QWidget *parent)
+ : QGraphicsView(parent), m_editor(nullptr)
+{}
void GraphicsView::keyPressEvent(QKeyEvent *e)
{
diff --git a/examples/widgets/animation/stickman/graphicsview.h b/examples/widgets/animation/stickman/graphicsview.h
index 56396bb780..361fee219d 100644
--- a/examples/widgets/animation/stickman/graphicsview.h
+++ b/examples/widgets/animation/stickman/graphicsview.h
@@ -58,7 +58,7 @@ class GraphicsView: public QGraphicsView
{
Q_OBJECT
public:
- GraphicsView(QWidget *parent = 0);
+ GraphicsView(QWidget *parent = nullptr);
protected:
void resizeEvent(QResizeEvent *event) override;
diff --git a/examples/widgets/animation/stickman/lifecycle.cpp b/examples/widgets/animation/stickman/lifecycle.cpp
index dbe9a299b4..046e3f4cd1 100644
--- a/examples/widgets/animation/stickman/lifecycle.cpp
+++ b/examples/widgets/animation/stickman/lifecycle.cpp
@@ -61,11 +61,11 @@ class KeyPressTransition: public QSignalTransition
{
public:
KeyPressTransition(GraphicsView *receiver, Qt::Key key)
- : QSignalTransition(receiver, SIGNAL(keyPressed(int))), m_key(key)
+ : QSignalTransition(receiver, &GraphicsView::keyPressed), m_key(key)
{
}
KeyPressTransition(GraphicsView *receiver, Qt::Key key, QAbstractState *target)
- : QSignalTransition(receiver, SIGNAL(keyPressed(int))), m_key(key)
+ : QSignalTransition(receiver, &GraphicsView::keyPressed), m_key(key)
{
setTargetState(target);
}
@@ -132,8 +132,10 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver)
QTimer *timer = new QTimer(lightningBlink);
timer->setSingleShot(true);
timer->setInterval(100);
- QObject::connect(lightningBlink, SIGNAL(entered()), timer, SLOT(start()));
- QObject::connect(lightningBlink, SIGNAL(exited()), timer, SLOT(stop()));
+ QObject::connect(lightningBlink, &QAbstractState::entered,
+ timer, QOverload<>::of(&QTimer::start));
+ QObject::connect(lightningBlink, &QAbstractState::exited,
+ timer, &QTimer::stop);
//! [5]
m_dead = new QState(m_machine);
@@ -151,7 +153,7 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver)
// Lightning strikes at random
m_alive->addTransition(new LightningStrikesTransition(lightningBlink));
//! [0]
- lightningBlink->addTransition(timer, SIGNAL(timeout()), m_dead);
+ lightningBlink->addTransition(timer, &QTimer::timeout, m_dead);
//! [0]
m_machine->setInitialState(m_alive);
@@ -173,9 +175,8 @@ void LifeCycle::addActivity(const QString &fileName, Qt::Key key, QObject *sende
QState *state = makeState(m_alive, fileName);
m_alive->addTransition(new KeyPressTransition(m_keyReceiver, key, state));
- if((sender != NULL) || (signal != NULL)) {
+ if (sender || signal)
m_alive->addTransition(sender, signal, state);
- }
}
QState *LifeCycle::makeState(QState *parentState, const QString &animationFileName)
@@ -190,7 +191,7 @@ QState *LifeCycle::makeState(QState *parentState, const QString &animationFileNa
}
const int frameCount = animation.totalFrames();
- QState *previousState = 0;
+ QState *previousState = nullptr;
for (int i=0; i<frameCount; ++i) {
animation.setCurrentFrame(i);
@@ -202,18 +203,18 @@ QState *LifeCycle::makeState(QState *parentState, const QString &animationFileNa
//! [1]
frameState->setObjectName(QString::fromLatin1("frame %0").arg(i));
- if (previousState == 0)
+ if (previousState == nullptr)
topLevel->setInitialState(frameState);
else
//! [2]
- previousState->addTransition(previousState, SIGNAL(propertiesAssigned()), frameState);
+ previousState->addTransition(previousState, &QState::propertiesAssigned, frameState);
//! [2]
previousState = frameState;
}
// Loop
- previousState->addTransition(previousState, SIGNAL(propertiesAssigned()), topLevel->initialState());
+ previousState->addTransition(previousState, &QState::propertiesAssigned, topLevel->initialState());
return topLevel;
diff --git a/examples/widgets/animation/stickman/stickman.cpp b/examples/widgets/animation/stickman/stickman.cpp
index b7a2d87ada..5725f64eec 100644
--- a/examples/widgets/animation/stickman/stickman.cpp
+++ b/examples/widgets/animation/stickman/stickman.cpp
@@ -126,7 +126,7 @@ StickMan::StickMan()
// Set up start position of limbs
for (int i=0; i<NodeCount; ++i) {
m_nodes[i] = new Node(QPointF(Coords[i * 2], Coords[i * 2 + 1]), this);
- connect(m_nodes[i], SIGNAL(positionChanged()), this, SLOT(childPositionChanged()));
+ connect(m_nodes[i], &Node::positionChanged, this, &StickMan::childPositionChanged);
}
for (int i=0; i<BoneCount; ++i) {
@@ -176,8 +176,7 @@ Node *StickMan::node(int idx) const
{
if (idx >= 0 && idx < NodeCount)
return m_nodes[idx];
- else
- return 0;
+ return nullptr;
}
void StickMan::timerEvent(QTimerEvent *)
diff --git a/examples/widgets/animation/sub-attaq/animationmanager.cpp b/examples/widgets/animation/sub-attaq/animationmanager.cpp
index b6e399967f..a611641613 100644
--- a/examples/widgets/animation/sub-attaq/animationmanager.cpp
+++ b/examples/widgets/animation/sub-attaq/animationmanager.cpp
@@ -56,7 +56,7 @@
#include <QtCore/QDebug>
// the universe's only animation manager
-AnimationManager *AnimationManager::instance = 0;
+AnimationManager *AnimationManager::instance = nullptr;
AnimationManager::AnimationManager()
{
@@ -71,7 +71,7 @@ AnimationManager *AnimationManager::self()
void AnimationManager::registerAnimation(QAbstractAnimation *anim)
{
- QObject::connect(anim, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterAnimation_helper(QObject*)));
+ QObject::connect(anim, &QObject::destroyed, this, &AnimationManager::unregisterAnimation_helper);
animations.append(anim);
}
@@ -82,7 +82,7 @@ void AnimationManager::unregisterAnimation_helper(QObject *obj)
void AnimationManager::unregisterAnimation(QAbstractAnimation *anim)
{
- QObject::disconnect(anim, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterAnimation_helper(QObject*)));
+ QObject::disconnect(anim, &QObject::destroyed, this, &AnimationManager::unregisterAnimation_helper);
animations.removeAll(anim);
}
@@ -93,14 +93,14 @@ void AnimationManager::unregisterAllAnimations()
void AnimationManager::pauseAll()
{
- foreach (QAbstractAnimation* animation, animations) {
+ for (QAbstractAnimation *animation : qAsConst(animations)) {
if (animation->state() == QAbstractAnimation::Running)
animation->pause();
}
}
void AnimationManager::resumeAll()
{
- foreach (QAbstractAnimation* animation, animations) {
+ for (QAbstractAnimation *animation : qAsConst(animations)) {
if (animation->state() == QAbstractAnimation::Paused)
animation->resume();
}
diff --git a/examples/widgets/animation/sub-attaq/boat.cpp b/examples/widgets/animation/sub-attaq/boat.cpp
index 145d373e99..9037d54878 100644
--- a/examples/widgets/animation/sub-attaq/boat.cpp
+++ b/examples/widgets/animation/sub-attaq/boat.cpp
@@ -92,8 +92,9 @@ static QAbstractAnimation *setupDestroyAnimation(Boat *boat)
-Boat::Boat() : PixmapItem(QString("boat"), GraphicsScene::Big),
- speed(0), bombsAlreadyLaunched(0), direction(Boat::None), movementAnimation(0)
+Boat::Boat()
+ : PixmapItem(QString("boat"), GraphicsScene::Big),
+ speed(0), bombsAlreadyLaunched(0), direction(Boat::None)
{
setZValue(4);
setFlags(QGraphicsItem::ItemIsFocusable);
@@ -148,8 +149,8 @@ Boat::Boat() : PixmapItem(QString("boat"), GraphicsScene::Big),
stopState->addTransition(leftMoveStop);
//The animation is finished, it means we reached the border of the screen, the boat is stopped so we move to the stop state
- moveStateLeft->addTransition(movementAnimation, SIGNAL(finished()), stopState);
- moveStateRight->addTransition(movementAnimation, SIGNAL(finished()), stopState);
+ moveStateLeft->addTransition(movementAnimation, &QAbstractAnimation::finished, stopState);
+ moveStateRight->addTransition(movementAnimation, &QAbstractAnimation::finished, stopState);
//We set up the keys for dropping bombs
KeyLaunchTransition *upFireLeft = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Up);
@@ -187,13 +188,13 @@ Boat::Boat() : PixmapItem(QString("boat"), GraphicsScene::Big),
destroyedState->setAnimation(destroyAnimation);
//Play a nice animation when the boat is destroyed
- moving->addTransition(this, SIGNAL(boatDestroyed()), destroyedState);
+ moving->addTransition(this, &Boat::boatDestroyed, destroyedState);
//Transition to final state when the destroyed animation is finished
- destroyedState->addTransition(destroyedState, SIGNAL(animationFinished()), final);
+ destroyedState->addTransition(destroyedState, &QAnimationState::animationFinished, final);
//The machine has finished to be executed, then the boat is dead
- connect(machine,SIGNAL(finished()), this, SIGNAL(boatExecutionFinished()));
+ connect(machine,&QState::finished, this, &Boat::boatExecutionFinished);
}
diff --git a/examples/widgets/animation/sub-attaq/boat_p.h b/examples/widgets/animation/sub-attaq/boat_p.h
index de11ff9555..8ebfeb27f5 100644
--- a/examples/widgets/animation/sub-attaq/boat_p.h
+++ b/examples/widgets/animation/sub-attaq/boat_p.h
@@ -146,7 +146,8 @@ private:
class MoveStateRight : public QState
{
public:
- explicit MoveStateRight(Boat *boat,QState *parent = 0) : QState(parent), boat(boat)
+ explicit MoveStateRight(Boat *boat, QState *parent = nullptr)
+ : QState(parent), boat(boat)
{
}
protected:
@@ -163,7 +164,8 @@ private:
class MoveStateLeft : public QState
{
public:
- explicit MoveStateLeft(Boat *boat,QState *parent = 0) : QState(parent), boat(boat)
+ explicit MoveStateLeft(Boat *boat, QState *parent = nullptr)
+ : QState(parent), boat(boat)
{
}
protected:
@@ -180,7 +182,8 @@ private:
class StopState : public QState
{
public:
- explicit StopState(Boat *boat,QState *parent = 0) : QState(parent), boat(boat)
+ explicit StopState(Boat *boat, QState *parent = nullptr)
+ : QState(parent), boat(boat)
{
}
protected:
@@ -198,13 +201,14 @@ private:
class LaunchStateRight : public QState
{
public:
- explicit LaunchStateRight(Boat *boat,QState *parent = 0) : QState(parent), boat(boat)
+ explicit LaunchStateRight(Boat *boat, QState *parent = nullptr)
+ : QState(parent), boat(boat)
{
}
protected:
void onEntry(QEvent *) override
{
- Bomb *b = new Bomb();
+ Bomb *b = new Bomb;
b->setPos(boat->x()+boat->size().width(),boat->y());
GraphicsScene *scene = static_cast<GraphicsScene *>(boat->scene());
scene->addItem(b);
@@ -219,13 +223,14 @@ private:
class LaunchStateLeft : public QState
{
public:
- explicit LaunchStateLeft(Boat *boat,QState *parent = 0) : QState(parent), boat(boat)
+ explicit LaunchStateLeft(Boat *boat, QState *parent = nullptr)
+ : QState(parent), boat(boat)
{
}
protected:
void onEntry(QEvent *) override
{
- Bomb *b = new Bomb();
+ Bomb *b = new Bomb;
b->setPos(boat->x() - b->size().width(), boat->y());
GraphicsScene *scene = static_cast<GraphicsScene *>(boat->scene());
scene->addItem(b);
diff --git a/examples/widgets/animation/sub-attaq/bomb.cpp b/examples/widgets/animation/sub-attaq/bomb.cpp
index a80d2d46c5..2b865137dd 100644
--- a/examples/widgets/animation/sub-attaq/bomb.cpp
+++ b/examples/widgets/animation/sub-attaq/bomb.cpp
@@ -83,8 +83,8 @@ void Bomb::launch(Bomb::Direction direction)
anim->setEndValue(QPointF(x() + delta*2,scene()->height()));
anim->setDuration(y()/2*60);
launchAnimation->addAnimation(anim);
- connect(anim,SIGNAL(valueChanged(QVariant)),this,SLOT(onAnimationLaunchValueChanged(QVariant)));
- connect(this, SIGNAL(bombExploded()), launchAnimation, SLOT(stop()));
+ connect(anim,&QVariantAnimation::valueChanged,this,&Bomb::onAnimationLaunchValueChanged);
+ connect(this, &Bomb::bombExploded, launchAnimation, &QAbstractAnimation::stop);
//We setup the state machine of the bomb
QStateMachine *machine = new QStateMachine(this);
@@ -98,13 +98,13 @@ void Bomb::launch(Bomb::Direction direction)
machine->setInitialState(launched);
//### Add a nice animation when the bomb is destroyed
- launched->addTransition(this, SIGNAL(bombExploded()),final);
+ launched->addTransition(this, &Bomb::bombExploded,final);
//If the animation is finished, then we move to the final state
- launched->addTransition(launched, SIGNAL(animationFinished()), final);
+ launched->addTransition(launched, &QAnimationState::animationFinished, final);
//The machine has finished to be executed, then the boat is dead
- connect(machine,SIGNAL(finished()),this, SIGNAL(bombExecutionFinished()));
+ connect(machine,&QState::finished,this, &Bomb::bombExecutionFinished);
machine->start();
@@ -112,7 +112,9 @@ void Bomb::launch(Bomb::Direction direction)
void Bomb::onAnimationLaunchValueChanged(const QVariant &)
{
- foreach (QGraphicsItem * item , collidingItems(Qt::IntersectsItemBoundingRect)) {
+ const QList<QGraphicsItem *> colItems =
+ collidingItems(Qt::IntersectsItemBoundingRect);
+ for (QGraphicsItem *item : colItems) {
if (item->type() == SubMarine::Type) {
SubMarine *s = static_cast<SubMarine *>(item);
destroy();
diff --git a/examples/widgets/animation/sub-attaq/graphicsscene.cpp b/examples/widgets/animation/sub-attaq/graphicsscene.cpp
index e0913f99f6..8f0dfc1357 100644
--- a/examples/widgets/animation/sub-attaq/graphicsscene.cpp
+++ b/examples/widgets/animation/sub-attaq/graphicsscene.cpp
@@ -191,15 +191,15 @@ void GraphicsScene::setupScene(QAction *newAction, QAction *quitAction)
lettersFadingState->setAnimation(lettersGroupFading);
//if new game then we fade out the welcome screen and start playing
- lettersMovingState->addTransition(newAction, SIGNAL(triggered()), lettersFadingState);
- lettersFadingState->addTransition(lettersFadingState, SIGNAL(animationFinished()), gameState);
+ lettersMovingState->addTransition(newAction, &QAction::triggered, lettersFadingState);
+ lettersFadingState->addTransition(lettersFadingState, &QAnimationState::animationFinished, gameState);
//New Game is triggered then player start playing
- gameState->addTransition(newAction, SIGNAL(triggered()), gameState);
+ gameState->addTransition(newAction, &QAction::triggered, gameState);
//Wanna quit, then connect to CTRL+Q
- gameState->addTransition(quitAction, SIGNAL(triggered()), final);
- lettersMovingState->addTransition(quitAction, SIGNAL(triggered()), final);
+ gameState->addTransition(quitAction, &QAction::triggered, final);
+ lettersMovingState->addTransition(quitAction, &QAction::triggered, final);
//Welcome screen is the initial state
machine->setInitialState(lettersMovingState);
@@ -207,27 +207,27 @@ void GraphicsScene::setupScene(QAction *newAction, QAction *quitAction)
machine->start();
//We reach the final state, then we quit
- connect(machine, SIGNAL(finished()), qApp, SLOT(quit()));
+ connect(machine, &QStateMachine::finished, qApp, &QApplication::quit);
}
void GraphicsScene::addItem(Bomb *bomb)
{
bombs.insert(bomb);
- connect(bomb,SIGNAL(bombExecutionFinished()),this, SLOT(onBombExecutionFinished()));
+ connect(bomb,&Bomb::bombExecutionFinished,this, &GraphicsScene::onBombExecutionFinished);
QGraphicsScene::addItem(bomb);
}
void GraphicsScene::addItem(Torpedo *torpedo)
{
torpedos.insert(torpedo);
- connect(torpedo,SIGNAL(torpedoExecutionFinished()),this, SLOT(onTorpedoExecutionFinished()));
+ connect(torpedo,&Torpedo::torpedoExecutionFinished,this, &GraphicsScene::onTorpedoExecutionFinished);
QGraphicsScene::addItem(torpedo);
}
void GraphicsScene::addItem(SubMarine *submarine)
{
submarines.insert(submarine);
- connect(submarine,SIGNAL(subMarineExecutionFinished()),this, SLOT(onSubMarineExecutionFinished()));
+ connect(submarine,&SubMarine::subMarineExecutionFinished,this, &GraphicsScene::onSubMarineExecutionFinished);
QGraphicsScene::addItem(submarine);
}
@@ -265,17 +265,17 @@ void GraphicsScene::onSubMarineExecutionFinished()
void GraphicsScene::clearScene()
{
- foreach (SubMarine *sub, submarines) {
+ for (SubMarine *sub : qAsConst(submarines)) {
sub->destroy();
sub->deleteLater();
}
- foreach (Torpedo *torpedo, torpedos) {
+ for (Torpedo *torpedo : qAsConst(torpedos)) {
torpedo->destroy();
torpedo->deleteLater();
}
- foreach (Bomb *bomb, bombs) {
+ for (Bomb *bomb : qAsConst(bombs)) {
bomb->destroy();
bomb->deleteLater();
}
diff --git a/examples/widgets/animation/sub-attaq/mainwindow.cpp b/examples/widgets/animation/sub-attaq/mainwindow.cpp
index b08a7d9f98..a4bb15b383 100644
--- a/examples/widgets/animation/sub-attaq/mainwindow.cpp
+++ b/examples/widgets/animation/sub-attaq/mainwindow.cpp
@@ -63,7 +63,8 @@
# include <QtOpenGL/QtOpenGL>
#endif
-MainWindow::MainWindow() : QMainWindow(0)
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
{
QMenu *file = menuBar()->addMenu(tr("&File"));
diff --git a/examples/widgets/animation/sub-attaq/mainwindow.h b/examples/widgets/animation/sub-attaq/mainwindow.h
index 8d3cc85cd1..c4fb9d324d 100644
--- a/examples/widgets/animation/sub-attaq/mainwindow.h
+++ b/examples/widgets/animation/sub-attaq/mainwindow.h
@@ -62,7 +62,7 @@ class MainWindow : public QMainWindow
{
Q_OBJECT
public:
- MainWindow();
+ MainWindow(QWidget *parent = nullptr);
private:
GraphicsScene *scene;
diff --git a/examples/widgets/animation/sub-attaq/pixmapitem.cpp b/examples/widgets/animation/sub-attaq/pixmapitem.cpp
index 0723cdfb5d..9475d5c3f8 100644
--- a/examples/widgets/animation/sub-attaq/pixmapitem.cpp
+++ b/examples/widgets/animation/sub-attaq/pixmapitem.cpp
@@ -54,7 +54,8 @@
//Qt
#include <QPainter>
-PixmapItem::PixmapItem(const QString &fileName,GraphicsScene::Mode mode, QGraphicsItem * parent) : QGraphicsObject(parent)
+PixmapItem::PixmapItem(const QString &fileName,GraphicsScene::Mode mode, QGraphicsItem * parent)
+ : QGraphicsObject(parent)
{
if (mode == GraphicsScene::Big)
pix = QPixmap(QStringLiteral(":/big/") + fileName);
diff --git a/examples/widgets/animation/sub-attaq/pixmapitem.h b/examples/widgets/animation/sub-attaq/pixmapitem.h
index de8ed67a38..ec5c01857f 100644
--- a/examples/widgets/animation/sub-attaq/pixmapitem.h
+++ b/examples/widgets/animation/sub-attaq/pixmapitem.h
@@ -60,7 +60,7 @@
class PixmapItem : public QGraphicsObject
{
public:
- PixmapItem(const QString &fileName, GraphicsScene::Mode mode, QGraphicsItem * parent = 0);
+ PixmapItem(const QString &fileName, GraphicsScene::Mode mode, QGraphicsItem *parent = nullptr);
PixmapItem(const QString &fileName, QGraphicsScene *scene);
QSizeF size() const;
QRectF boundingRect() const override;
diff --git a/examples/widgets/animation/sub-attaq/qanimationstate.cpp b/examples/widgets/animation/sub-attaq/qanimationstate.cpp
index ae24af6da3..ce99f9080d 100644
--- a/examples/widgets/animation/sub-attaq/qanimationstate.cpp
+++ b/examples/widgets/animation/sub-attaq/qanimationstate.cpp
@@ -73,7 +73,7 @@ QAnimationState *s = new QAnimationState(machine->rootState());
QPropertyAnimation *animation = new QPropertyAnimation(obj, "pos");
s->setAnimation(animation);
QState *s2 = new QState(machine->rootState());
-s->addTransition(s, SIGNAL(animationFinished()), s2);
+s->addTransition(s, &QAnimationState::animationFinished, s2);
machine.start();
\endcode
@@ -84,7 +84,7 @@ machine.start();
Constructs a new state with the given \a parent state.
*/
QAnimationState::QAnimationState(QState *parent)
- : QState(parent), m_animation(0)
+ : QState(parent), m_animation(nullptr)
{
}
@@ -107,18 +107,18 @@ void QAnimationState::setAnimation(QAbstractAnimation *animation)
//Disconnect from the previous animation if exist
if(m_animation)
- disconnect(m_animation, SIGNAL(finished()), this, SIGNAL(animationFinished()));
+ disconnect(m_animation, &QAbstractAnimation::finished, this, &QAnimationState::animationFinished);
m_animation = animation;
if (m_animation) {
//connect the new animation
- connect(m_animation, SIGNAL(finished()), this, SIGNAL(animationFinished()));
+ connect(m_animation, &QAbstractAnimation::finished, this, &QAnimationState::animationFinished);
}
}
/*!
- Returns the animation handle by this animation state, or 0 if there is no animation.
+ Returns the animation handle by this animation state, or \nullptr if there is no animation.
*/
QAbstractAnimation* QAnimationState::animation() const
{
diff --git a/examples/widgets/animation/sub-attaq/states.cpp b/examples/widgets/animation/sub-attaq/states.cpp
index e19704db7b..cda10ccdaf 100644
--- a/examples/widgets/animation/sub-attaq/states.cpp
+++ b/examples/widgets/animation/sub-attaq/states.cpp
@@ -67,11 +67,8 @@
#include <QtCore/QRandomGenerator>
PlayState::PlayState(GraphicsScene *scene, QState *parent)
- : QState(parent),
- scene(scene),
- machine(0),
- currentLevel(0),
- score(0)
+ : QState(parent), scene(scene), machine(nullptr),
+ currentLevel(0), score(0)
{
}
@@ -124,7 +121,7 @@ void PlayState::onEntry(QEvent *)
WinState *winState = new WinState(scene, this, machine);
//The boat has been destroyed then the game is finished
- levelState->addTransition(scene->boat, SIGNAL(boatExecutionFinished()),lostState);
+ levelState->addTransition(scene->boat, &Boat::boatExecutionFinished,lostState);
//This transition check if we won or not
WinTransition *winTransition = new WinTransition(scene, this, winState);
@@ -157,7 +154,7 @@ void PlayState::onEntry(QEvent *)
winState->addTransition(spaceTransition);
//We lost we should reach the final state
- lostState->addTransition(lostState, SIGNAL(finished()), final);
+ lostState->addTransition(lostState, &QState::finished, final);
machine->start();
}
@@ -291,8 +288,8 @@ UpdateScoreState::UpdateScoreState(QState *parent) : QState(parent)
/** Win transition */
UpdateScoreTransition::UpdateScoreTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target)
- : QSignalTransition(scene,SIGNAL(subMarineDestroyed(int))),
- game(game), scene(scene)
+ : QSignalTransition(scene, &GraphicsScene::subMarineDestroyed),
+ game(game), scene(scene)
{
setTargetState(target);
}
@@ -309,8 +306,8 @@ bool UpdateScoreTransition::eventTest(QEvent *event)
/** Win transition */
WinTransition::WinTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target)
- : QSignalTransition(scene,SIGNAL(allSubMarineDestroyed(int))),
- game(game), scene(scene)
+ : QSignalTransition(scene, &GraphicsScene::allSubMarineDestroyed),
+ game(game), scene(scene)
{
setTargetState(target);
}
diff --git a/examples/widgets/animation/sub-attaq/submarine.cpp b/examples/widgets/animation/sub-attaq/submarine.cpp
index a451185ce0..775e75ceed 100644
--- a/examples/widgets/animation/sub-attaq/submarine.cpp
+++ b/examples/widgets/animation/sub-attaq/submarine.cpp
@@ -106,7 +106,7 @@ SubMarine::SubMarine(int type, const QString &name, int points) : PixmapItem(QSt
//This is the initial state of the moving root state
moving->setInitialState(movement);
- movement->addTransition(this, SIGNAL(subMarineStateChanged()), moving);
+ movement->addTransition(this, &SubMarine::subMarineStateChanged, moving);
//This is the initial state of the machine
machine->setInitialState(moving);
@@ -115,23 +115,23 @@ SubMarine::SubMarine(int type, const QString &name, int points) : PixmapItem(QSt
QFinalState *final = new QFinalState(machine);
//If the moving animation is finished we move to the return state
- movement->addTransition(movement, SIGNAL(animationFinished()), rotation);
+ movement->addTransition(movement, &QAnimationState::animationFinished, rotation);
//If the return animation is finished we move to the moving state
- rotation->addTransition(rotation, SIGNAL(animationFinished()), movement);
+ rotation->addTransition(rotation, &QAnimationState::animationFinished, movement);
//This state play the destroyed animation
QAnimationState *destroyedState = new QAnimationState(machine);
destroyedState->setAnimation(setupDestroyAnimation(this));
//Play a nice animation when the submarine is destroyed
- moving->addTransition(this, SIGNAL(subMarineDestroyed()), destroyedState);
+ moving->addTransition(this, &SubMarine::subMarineDestroyed, destroyedState);
//Transition to final state when the destroyed animation is finished
- destroyedState->addTransition(destroyedState, SIGNAL(animationFinished()), final);
+ destroyedState->addTransition(destroyedState, &QAnimationState::animationFinished, final);
//The machine has finished to be executed, then the submarine is dead
- connect(machine,SIGNAL(finished()),this, SIGNAL(subMarineExecutionFinished()));
+ connect(machine,&QState::finished,this, &SubMarine::subMarineExecutionFinished);
machine->start();
}
diff --git a/examples/widgets/animation/sub-attaq/submarine_p.h b/examples/widgets/animation/sub-attaq/submarine_p.h
index 698b4b494f..1c2cb7ceac 100644
--- a/examples/widgets/animation/sub-attaq/submarine_p.h
+++ b/examples/widgets/animation/sub-attaq/submarine_p.h
@@ -80,7 +80,8 @@ public:
explicit MovementState(SubMarine *submarine, QState *parent = 0) : QAnimationState(parent)
{
movementAnimation = new QPropertyAnimation(submarine, "pos");
- connect(movementAnimation,SIGNAL(valueChanged(const QVariant &)),this,SLOT(onAnimationMovementValueChanged(const QVariant &)));
+ connect(movementAnimation, &QPropertyAnimation::valueChanged,
+ this, &MovementState::onAnimationMovementValueChanged);
setAnimation(movementAnimation);
AnimationManager::self()->registerAnimation(movementAnimation);
this->submarine = submarine;
diff --git a/examples/widgets/animation/sub-attaq/torpedo.cpp b/examples/widgets/animation/sub-attaq/torpedo.cpp
index 2e9d970326..92a3833452 100644
--- a/examples/widgets/animation/sub-attaq/torpedo.cpp
+++ b/examples/widgets/animation/sub-attaq/torpedo.cpp
@@ -73,8 +73,8 @@ void Torpedo::launch()
launchAnimation->setEndValue(QPointF(x(),qobject_cast<GraphicsScene *>(scene())->sealLevel() - 15));
launchAnimation->setEasingCurve(QEasingCurve::InQuad);
launchAnimation->setDuration(y()/currentSpeed*10);
- connect(launchAnimation,SIGNAL(valueChanged(QVariant)),this,SLOT(onAnimationLaunchValueChanged(QVariant)));
- connect(this,SIGNAL(torpedoExploded()), launchAnimation, SLOT(stop()));
+ connect(launchAnimation,&QVariantAnimation::valueChanged,this,&Torpedo::onAnimationLaunchValueChanged);
+ connect(this,&Torpedo::torpedoExploded, launchAnimation, &QAbstractAnimation::stop);
//We setup the state machine of the torpedo
QStateMachine *machine = new QStateMachine(this);
@@ -89,13 +89,13 @@ void Torpedo::launch()
machine->setInitialState(launched);
//### Add a nice animation when the torpedo is destroyed
- launched->addTransition(this, SIGNAL(torpedoExploded()),final);
+ launched->addTransition(this, &Torpedo::torpedoExploded,final);
//If the animation is finished, then we move to the final state
- launched->addTransition(launched, SIGNAL(animationFinished()), final);
+ launched->addTransition(launched, &QAnimationState::animationFinished, final);
//The machine has finished to be executed, then the boat is dead
- connect(machine,SIGNAL(finished()),this, SIGNAL(torpedoExecutionFinished()));
+ connect(machine,&QState::finished,this, &Torpedo::torpedoExecutionFinished);
machine->start();
}
@@ -111,7 +111,9 @@ void Torpedo::setCurrentSpeed(int speed)
void Torpedo::onAnimationLaunchValueChanged(const QVariant &)
{
- foreach (QGraphicsItem *item , collidingItems(Qt::IntersectsItemBoundingRect)) {
+ const QList<QGraphicsItem *> colItems =
+ collidingItems(Qt::IntersectsItemBoundingRect);
+ for (QGraphicsItem *item : colItems) {
if (Boat *b = qgraphicsitem_cast<Boat*>(item))
b->destroy();
}
diff --git a/examples/widgets/desktop/screenshot/screenshot.cpp b/examples/widgets/desktop/screenshot/screenshot.cpp
index 80f26ae282..715e6c780e 100644
--- a/examples/widgets/desktop/screenshot/screenshot.cpp
+++ b/examples/widgets/desktop/screenshot/screenshot.cpp
@@ -139,7 +139,8 @@ void Screenshot::saveScreenshot()
fileDialog.setFileMode(QFileDialog::AnyFile);
fileDialog.setDirectory(initialPath);
QStringList mimeTypes;
- foreach (const QByteArray &bf, QImageWriter::supportedMimeTypes())
+ const QList<QByteArray> baMimeTypes = QImageWriter::supportedMimeTypes();
+ for (const QByteArray &bf : baMimeTypes)
mimeTypes.append(QLatin1String(bf));
fileDialog.setMimeTypeFilters(mimeTypes);
fileDialog.selectMimeTypeFilter("image/" + format);
diff --git a/examples/widgets/desktop/systray/main.cpp b/examples/widgets/desktop/systray/main.cpp
index d981415b44..2d91e4ac36 100644
--- a/examples/widgets/desktop/systray/main.cpp
+++ b/examples/widgets/desktop/systray/main.cpp
@@ -64,7 +64,7 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
- QMessageBox::critical(0, QObject::tr("Systray"),
+ QMessageBox::critical(nullptr, QObject::tr("Systray"),
QObject::tr("I couldn't detect any system tray "
"on this system."));
return 1;
diff --git a/examples/widgets/desktop/systray/window.cpp b/examples/widgets/desktop/systray/window.cpp
index 05944c92a7..31fcd84821 100644
--- a/examples/widgets/desktop/systray/window.cpp
+++ b/examples/widgets/desktop/systray/window.cpp
@@ -176,7 +176,7 @@ void Window::showMessage()
//! [6]
void Window::messageClicked()
{
- QMessageBox::information(0, tr("Systray"),
+ QMessageBox::information(nullptr, tr("Systray"),
tr("Sorry, I already gave what help I could.\n"
"Maybe you should try asking a human?"));
}
diff --git a/examples/widgets/dialogs/classwizard/classwizard.cpp b/examples/widgets/dialogs/classwizard/classwizard.cpp
index 3eab2f5fb2..81adf85b0d 100644
--- a/examples/widgets/dialogs/classwizard/classwizard.cpp
+++ b/examples/widgets/dialogs/classwizard/classwizard.cpp
@@ -139,7 +139,7 @@ void ClassWizard::accept()
QFile headerFile(outputDir + '/' + header);
if (!headerFile.open(QFile::WriteOnly | QFile::Text)) {
- QMessageBox::warning(0, QObject::tr("Simple Wizard"),
+ QMessageBox::warning(nullptr, QObject::tr("Simple Wizard"),
QObject::tr("Cannot write file %1:\n%2")
.arg(headerFile.fileName())
.arg(headerFile.errorString()));
@@ -195,7 +195,7 @@ void ClassWizard::accept()
QFile implementationFile(outputDir + '/' + implementation);
if (!implementationFile.open(QFile::WriteOnly | QFile::Text)) {
- QMessageBox::warning(0, QObject::tr("Simple Wizard"),
+ QMessageBox::warning(nullptr, QObject::tr("Simple Wizard"),
QObject::tr("Cannot write file %1:\n%2")
.arg(implementationFile.fileName())
.arg(implementationFile.errorString()));
diff --git a/examples/widgets/dialogs/extension/finddialog.cpp b/examples/widgets/dialogs/extension/finddialog.cpp
index 1321155f00..10a4ae1ac0 100644
--- a/examples/widgets/dialogs/extension/finddialog.cpp
+++ b/examples/widgets/dialogs/extension/finddialog.cpp
@@ -91,7 +91,7 @@ FindDialog::FindDialog(QWidget *parent)
connect(moreButton, &QAbstractButton::toggled, extension, &QWidget::setVisible);
QVBoxLayout *extensionLayout = new QVBoxLayout;
- extensionLayout->setMargin(0);
+ extensionLayout->setContentsMargins(QMargins());
extensionLayout->addWidget(wholeWordsCheckBox);
extensionLayout->addWidget(backwardCheckBox);
extensionLayout->addWidget(searchSelectionCheckBox);
diff --git a/examples/widgets/dialogs/findfiles/window.cpp b/examples/widgets/dialogs/findfiles/window.cpp
index 1b16cdcd35..e1f7ccdcc4 100644
--- a/examples/widgets/dialogs/findfiles/window.cpp
+++ b/examples/widgets/dialogs/findfiles/window.cpp
@@ -182,7 +182,7 @@ QStringList Window::findFiles(const QStringList &files, const QString &text)
for (int i = 0; i < files.size(); ++i) {
progressDialog.setValue(i);
- progressDialog.setLabelText(tr("Searching file number %1 of %n...", 0, files.size()).arg(i));
+ progressDialog.setLabelText(tr("Searching file number %1 of %n...", nullptr, files.size()).arg(i));
QCoreApplication::processEvents();
//! [6]
@@ -237,7 +237,7 @@ void Window::showFiles(const QStringList &paths)
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, paths.size()));
+ filesFoundLabel->setText(tr("%n file(s) found (Double click on a file to open it)", nullptr, paths.size()));
filesFoundLabel->setWordWrap(true);
}
//! [8]
diff --git a/examples/widgets/dialogs/standarddialogs/dialog.cpp b/examples/widgets/dialogs/standarddialogs/dialog.cpp
index 74a4131b38..c91a594490 100644
--- a/examples/widgets/dialogs/standarddialogs/dialog.cpp
+++ b/examples/widgets/dialogs/standarddialogs/dialog.cpp
@@ -65,7 +65,7 @@
class DialogOptionsWidget : public QGroupBox
{
public:
- explicit DialogOptionsWidget(QWidget *parent = 0);
+ explicit DialogOptionsWidget(QWidget *parent = nullptr);
void addCheckBox(const QString &text, int value);
void addSpacer();
@@ -99,9 +99,10 @@ void DialogOptionsWidget::addSpacer()
int DialogOptionsWidget::value() const
{
int result = 0;
- foreach (const CheckBoxEntry &checkboxEntry, checkBoxEntries)
+ for (const CheckBoxEntry &checkboxEntry : qAsConst(checkBoxEntries)) {
if (checkboxEntry.first->isChecked())
result |= checkboxEntry.second;
+ }
return result;
}
@@ -286,7 +287,6 @@ Dialog::Dialog(QWidget *parent)
fileDialogOptionsWidget->addCheckBox(tr("Show directories only"), QFileDialog::ShowDirsOnly);
fileDialogOptionsWidget->addCheckBox(tr("Do not resolve symlinks"), QFileDialog::DontResolveSymlinks);
fileDialogOptionsWidget->addCheckBox(tr("Do not confirm overwrite"), QFileDialog::DontConfirmOverwrite);
- fileDialogOptionsWidget->addCheckBox(tr("Do not use sheet"), QFileDialog::DontUseSheet);
fileDialogOptionsWidget->addCheckBox(tr("Readonly"), QFileDialog::ReadOnly);
fileDialogOptionsWidget->addCheckBox(tr("Hide name filter details"), QFileDialog::HideNameFilterDetails);
fileDialogOptionsWidget->addCheckBox(tr("Do not use custom directory icons (Windows)"), QFileDialog::DontUseCustomDirectoryIcons);
@@ -492,7 +492,7 @@ void Dialog::questionMessage()
void Dialog::warningMessage()
{
QMessageBox msgBox(QMessageBox::Warning, tr("QMessageBox::warning()"),
- MESSAGE, 0, this);
+ MESSAGE, nullptr, this);
msgBox.setDetailedText(MESSAGE_DETAILS);
msgBox.addButton(tr("Save &Again"), QMessageBox::AcceptRole);
msgBox.addButton(tr("&Continue"), QMessageBox::RejectRole);
diff --git a/examples/widgets/doc/dropsite.qdoc b/examples/widgets/doc/dropsite.qdoc
index 32bcfe8916..af8766a308 100644
--- a/examples/widgets/doc/dropsite.qdoc
+++ b/examples/widgets/doc/dropsite.qdoc
@@ -202,13 +202,7 @@
\snippet draganddrop/dropsite/dropsitewindow.cpp updateFormatsTable() part1
Once we are sure that \c mimeData is valid, we iterate through its
- supported formats using the \l{The foreach Keyword}{foreach keyword}.
- This keyword has the following format:
-
- \include code/doc_src_examples_dropsite.qdoc 0
-
- In our example, \c format is the \a variable and the \a container is a
- QStringList, obtained from \c mimeData->formats().
+ supported formats.
\note The \l{QMimeData::formats()}{formats()} function returns a
QStringList object, containing all the formats supported by the
diff --git a/examples/widgets/doc/src/addressbook.qdoc b/examples/widgets/doc/src/addressbook.qdoc
index 1fa0bfa9d4..e5e7fe5c2c 100644
--- a/examples/widgets/doc/src/addressbook.qdoc
+++ b/examples/widgets/doc/src/addressbook.qdoc
@@ -90,8 +90,8 @@
\snippet itemviews/addressbook/tablemodel.h 0
Two constructors are used, a default constructor which uses
- \c TableModel's own \c {QList<Contact>} and one that takes
- \c {QList<Contact>} as an argument, for convenience.
+ \c TableModel's own \c {QVector<Contact>} and one that takes
+ \c {QVector<Contact>} as an argument, for convenience.
\section1 TableModel Class Implementation
@@ -108,9 +108,6 @@
\c columnCount()'s value is always 2 because we only need space
for the \b Name and \b Address columns.
- \note The \c Q_UNUSED() macro prevents the compiler from
- generating warnings regarding unused parameters.
-
\snippet itemviews/addressbook/tablemodel.cpp 1
The \c data() function returns either a \b Name or
@@ -164,7 +161,7 @@
them here so that we can reuse the model in other programs.
The last function in \c {TableModel}, \c getContacts() returns the
- QList<Contact> object that holds all the contacts in the address
+ QVector<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.
@@ -233,7 +230,7 @@
\image addressbook-signals.png Signals and Slots Connections
- We provide 2 \c addEntry() functions: 1 which is intended to be
+ We provide two \c addEntry() functions: One which is intended to be
used to accept user input, and the other which performs the actual
task of adding new entries to the address book. We divide the
responsibility of adding entries into two parts to allow
diff --git a/examples/widgets/doc/src/application.qdoc b/examples/widgets/doc/src/application.qdoc
index 040aa171b7..6c37fa67bb 100644
--- a/examples/widgets/doc/src/application.qdoc
+++ b/examples/widgets/doc/src/application.qdoc
@@ -327,9 +327,12 @@
\snippet mainwindows/application/mainwindow.cpp 44
\snippet mainwindows/application/mainwindow.cpp 45
- Saving a file is very similar to loading one. Here, the
- QFile::Text flag ensures that on Windows, "\\n" is converted into
- "\\r\\n" to conform to the Windows convension.
+ Saving a file is similar to loading one. We use QSaveFile to ensure
+ all data are safely written and existing files are not damaged
+ should writing fail.
+ We use the QFile::Text flag to make sure that on Windows, "\\n"
+ is converted into "\\r\\n" to conform to the Windows convention.
+
\snippet mainwindows/application/mainwindow.cpp 46
\snippet mainwindows/application/mainwindow.cpp 47
diff --git a/examples/widgets/doc/src/diagramscene.qdoc b/examples/widgets/doc/src/diagramscene.qdoc
index ca4876f2e8..860dcc5cb9 100644
--- a/examples/widgets/doc/src/diagramscene.qdoc
+++ b/examples/widgets/doc/src/diagramscene.qdoc
@@ -589,7 +589,7 @@
\snippet graphicsview/diagramscene/diagramscene.cpp 14
The scene has single selection, i.e., only one item can be
- selected at any given time. The foreach will then loop one time
+ selected at any given time. The for loop will then loop one time
with the selected item or none if no item is selected. \c
isItemChange() is used to check whether a selected item exists
and also is of the specified diagram \a type.
diff --git a/examples/widgets/doc/src/fetchmore.qdoc b/examples/widgets/doc/src/fetchmore.qdoc
index df0cf3b8ec..a27efaf071 100644
--- a/examples/widgets/doc/src/fetchmore.qdoc
+++ b/examples/widgets/doc/src/fetchmore.qdoc
@@ -29,7 +29,7 @@
\example itemviews/fetchmore
\title Fetch More Example
\ingroup examples-itemviews
- \brief The Fetch More example shows how two add items to an item view
+ \brief The Fetch More example shows how to add items to an item view
model on demand.
\image fetchmore-example.png
diff --git a/examples/widgets/doc/src/icons.qdoc b/examples/widgets/doc/src/icons.qdoc
index 60cb9062c2..7aae0491d6 100644
--- a/examples/widgets/doc/src/icons.qdoc
+++ b/examples/widgets/doc/src/icons.qdoc
@@ -262,12 +262,7 @@
provides arrays allowing to map from enumeration value to row/column
(by using QVector::indexOf()) and back by using the array index and lists
of the matching strings. Qt's containers can be easily populated by
- using C++ 11 initializer lists. If the compiler does not provide that feature,
- a pattern like
-
- \snippet widgets/icons/iconpreviewarea.cpp 43
-
- can be used.
+ using C++ 11 initializer lists.
We need two public functions to set the current icon and the
icon's size. In addition the class has three private functions: We
diff --git a/examples/widgets/doc/src/orderform.qdoc b/examples/widgets/doc/src/orderform.qdoc
index de59fc402d..5c63081a77 100644
--- a/examples/widgets/doc/src/orderform.qdoc
+++ b/examples/widgets/doc/src/orderform.qdoc
@@ -191,7 +191,7 @@
We then set the \c{cursor}'s position back to its last position in
\c topFrame and fill in the customer's name (provided by the constructor)
- and address - using a \c foreach loop to traverse the QString, \c address.
+ and address - using a range-based for loop to traverse the QString, \c address.
\snippet richtext/orderform/mainwindow.cpp 4
diff --git a/examples/widgets/doc/src/plugandpaint.qdoc b/examples/widgets/doc/src/plugandpaint.qdoc
index d3044860ab..b37176da0e 100644
--- a/examples/widgets/doc/src/plugandpaint.qdoc
+++ b/examples/widgets/doc/src/plugandpaint.qdoc
@@ -171,8 +171,8 @@
\snippet tools/plugandpaint/app/mainwindow.cpp 8
We use QDir::entryList() to get a list of all files in that
- directory. Then we iterate over the result using \l foreach and
- try to load the plugin using QPluginLoader.
+ directory. Then we iterate over the result using a range-based for loop
+ and try to load the plugin using QPluginLoader.
The QObject provided by the plugin is accessible through
QPluginLoader::instance(). If the dynamic library isn't a Qt
diff --git a/examples/widgets/doc/src/simpletreemodel.qdoc b/examples/widgets/doc/src/simpletreemodel.qdoc
index a50197b04d..f5fe93897c 100644
--- a/examples/widgets/doc/src/simpletreemodel.qdoc
+++ b/examples/widgets/doc/src/simpletreemodel.qdoc
@@ -170,9 +170,8 @@
\snippet itemviews/simpletreemodel/treeitem.cpp 5
- Column data is returned by the \c data() function, taking advantage of
- QList's ability to provide sensible default values if the column number
- is out of range:
+ Column data is returned by the \c data() function. The bounds are checked
+ before accessing the container with the data:
\snippet itemviews/simpletreemodel/treeitem.cpp 6
diff --git a/examples/widgets/doc/src/stardelegate.qdoc b/examples/widgets/doc/src/stardelegate.qdoc
index 44d17662ca..0b91723a51 100644
--- a/examples/widgets/doc/src/stardelegate.qdoc
+++ b/examples/widgets/doc/src/stardelegate.qdoc
@@ -42,11 +42,11 @@
editing takes place.
Delegates are subclasses of QAbstractItemDelegate. Qt provides
- QItemDelegate, which inherits QAbstractItemDelegate and handles
+ QStyledItemDelegate, which inherits QAbstractItemDelegate and handles
the most common data types (notably \c int and QString). If we
need to support custom data types, or want to customize the
rendering or the editing for existing data types, we can subclass
- QAbstractItemDelegate or QItemDelegate. See \l{Delegate Classes}
+ QAbstractItemDelegate or QStyledItemDelegate. See \l{Delegate Classes}
for more information about delegates, and \l{Model/View
Programming} if you need a high-level introduction to Qt's
model/view architecture (including delegates).
@@ -62,9 +62,9 @@
expressed as stars, such as "2 out of 5 stars" or "5 out of
6 stars".
- \li \c StarDelegate inherits QItemDelegate and provides support
+ \li \c StarDelegate inherits QStyledItemDelegate and provides support
for \c StarRating (in addition to the data types already
- handled by QItemDelegate).
+ handled by QStyledItemDelegate).
\li \c StarEditor inherits QWidget and is used by \c StarDelegate
to let the user edit a star rating using the mouse.
@@ -80,12 +80,12 @@
\snippet itemviews/stardelegate/stardelegate.h 0
All public functions are reimplemented virtual functions from
- QItemDelegate to provide custom rendering and editing.
+ QStyledItemDelegate to provide custom rendering and editing.
\section1 StarDelegate Class Implementation
The \l{QAbstractItemDelegate::}{paint()} function is
- reimplemented from QItemDelegate and is called whenever the view
+ reimplemented from QStyledItemDelegate and is called whenever the view
needs to repaint an item:
\snippet itemviews/stardelegate/stardelegate.cpp 0
@@ -93,7 +93,7 @@
The function is invoked once for each item, represented by a
QModelIndex object from the model. If the data stored in the item
is a \c StarRating, we paint it ourselves; otherwise, we let
- QItemDelegate paint it for us. This ensures that the \c
+ QStyledItemDelegate paint it for us. This ensures that the \c
StarDelegate can handle the most common data types.
If the item is a \c StarRating, we draw the background if the
diff --git a/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp b/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp
index 28a42ee614..2dae83bb22 100644
--- a/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp
+++ b/examples/widgets/draganddrop/dropsite/dropsitewindow.cpp
@@ -113,7 +113,8 @@ void DropSiteWindow::updateFormatsTable(const QMimeData *mimeData)
//! [updateFormatsTable() part1]
//! [updateFormatsTable() part2]
- for (const QString &format : mimeData->formats()) {
+ const QStringList formats = mimeData->formats();
+ for (const QString &format : formats) {
QTableWidgetItem *formatItem = new QTableWidgetItem(format);
formatItem->setFlags(Qt::ItemIsEnabled);
formatItem->setTextAlignment(Qt::AlignTop | Qt::AlignLeft);
diff --git a/examples/widgets/effects/fademessage/fademessage.cpp b/examples/widgets/effects/fademessage/fademessage.cpp
index 9943147bb7..4c3a70bb4f 100644
--- a/examples/widgets/effects/fademessage/fademessage.cpp
+++ b/examples/widgets/effects/fademessage/fademessage.cpp
@@ -131,7 +131,7 @@ void FadeMessage::setupScene()
QPushButton *press = new QPushButton;
press->setText(tr("Press me"));
- connect(press, SIGNAL(clicked()), SLOT(togglePopup()));
+ connect(press, &QAbstractButton::clicked, this, &FadeMessage::togglePopup);
m_scene.addWidget(press);
press->move(300, 500);
diff --git a/examples/widgets/gestures/imagegestures/imagewidget.cpp b/examples/widgets/gestures/imagegestures/imagewidget.cpp
index ca9affca70..0a6b963559 100644
--- a/examples/widgets/gestures/imagegestures/imagewidget.cpp
+++ b/examples/widgets/gestures/imagegestures/imagewidget.cpp
@@ -72,7 +72,7 @@ ImageWidget::ImageWidget(QWidget *parent)
void ImageWidget::grabGestures(const QList<Qt::GestureType> &gestures)
{
//! [enable gestures]
- foreach (Qt::GestureType gesture, gestures)
+ for (Qt::GestureType gesture : gestures)
grabGesture(gesture);
//! [enable gestures]
}
diff --git a/examples/widgets/graphicsview/boxes/glbuffers.cpp b/examples/widgets/graphicsview/boxes/glbuffers.cpp
index 851cd17796..b52b26c4ef 100644
--- a/examples/widgets/graphicsview/boxes/glbuffers.cpp
+++ b/examples/widgets/graphicsview/boxes/glbuffers.cpp
@@ -218,14 +218,14 @@ GLTextureCube::GLTextureCube(int size)
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
-GLTextureCube::GLTextureCube(const QStringList& fileNames, int size)
+GLTextureCube::GLTextureCube(const QStringList &fileNames, int size)
{
// TODO: Add error handling.
glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture);
int index = 0;
- foreach (QString file, fileNames) {
+ for (const QString &file : fileNames) {
QImage image(file);
if (image.isNull()) {
m_failed = true;
diff --git a/examples/widgets/graphicsview/boxes/glbuffers.h b/examples/widgets/graphicsview/boxes/glbuffers.h
index 03c24a91d3..e2363d561e 100644
--- a/examples/widgets/graphicsview/boxes/glbuffers.h
+++ b/examples/widgets/graphicsview/boxes/glbuffers.h
@@ -129,7 +129,7 @@ class GLTextureCube : public GLTexture
{
public:
GLTextureCube(int size);
- explicit GLTextureCube(const QStringList& fileNames, int size = 0);
+ explicit GLTextureCube(const QStringList &fileNames, int size = 0);
void load(int size, int face, QRgb *data);
void bind() override;
void unbind() override;
diff --git a/examples/widgets/graphicsview/boxes/qtbox.cpp b/examples/widgets/graphicsview/boxes/qtbox.cpp
index 3a184dd0b6..68d5c251f4 100644
--- a/examples/widgets/graphicsview/boxes/qtbox.cpp
+++ b/examples/widgets/graphicsview/boxes/qtbox.cpp
@@ -127,10 +127,8 @@ void ItemBase::duplicateSelectedItems(QGraphicsScene *scene)
if (!scene)
return;
- QList<QGraphicsItem *> selected;
- selected = scene->selectedItems();
-
- foreach (QGraphicsItem *item, selected) {
+ const QList<QGraphicsItem *> selected = scene->selectedItems();
+ for (QGraphicsItem *item : selected) {
ItemBase *itemBase = qgraphicsitem_cast<ItemBase *>(item);
if (itemBase)
scene->addItem(itemBase->createNew(itemBase->m_size, itemBase->pos().x() + itemBase->m_size, itemBase->pos().y()));
@@ -142,10 +140,8 @@ void ItemBase::deleteSelectedItems(QGraphicsScene *scene)
if (!scene)
return;
- QList<QGraphicsItem *> selected;
- selected = scene->selectedItems();
-
- foreach (QGraphicsItem *item, selected) {
+ const QList<QGraphicsItem *> selected = scene->selectedItems();
+ for (QGraphicsItem *item : selected) {
ItemBase *itemBase = qgraphicsitem_cast<ItemBase *>(item);
if (itemBase)
delete itemBase;
@@ -157,10 +153,8 @@ void ItemBase::growSelectedItems(QGraphicsScene *scene)
if (!scene)
return;
- QList<QGraphicsItem *> selected;
- selected = scene->selectedItems();
-
- foreach (QGraphicsItem *item, selected) {
+ const QList<QGraphicsItem *> selected = scene->selectedItems();
+ for (QGraphicsItem *item : selected) {
ItemBase *itemBase = qgraphicsitem_cast<ItemBase *>(item);
if (itemBase) {
itemBase->prepareGeometryChange();
@@ -176,10 +170,8 @@ void ItemBase::shrinkSelectedItems(QGraphicsScene *scene)
if (!scene)
return;
- QList<QGraphicsItem *> selected;
- selected = scene->selectedItems();
-
- foreach (QGraphicsItem *item, selected) {
+ const QList<QGraphicsItem *> selected = scene->selectedItems();
+ for (QGraphicsItem *item : selected) {
ItemBase *itemBase = qgraphicsitem_cast<ItemBase *>(item);
if (itemBase) {
itemBase->prepareGeometryChange();
diff --git a/examples/widgets/graphicsview/boxes/scene.cpp b/examples/widgets/graphicsview/boxes/scene.cpp
index 1637c1f781..d51124aed7 100644
--- a/examples/widgets/graphicsview/boxes/scene.cpp
+++ b/examples/widgets/graphicsview/boxes/scene.cpp
@@ -111,7 +111,7 @@ ColorEdit::ColorEdit(QRgb initialColor, int id)
m_button->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
layout->addWidget(m_button);
- connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(editDone()));
+ connect(m_lineEdit, &QLineEdit::editingFinished, this, &ColorEdit::editDone);
}
void ColorEdit::editDone()
@@ -166,7 +166,7 @@ FloatEdit::FloatEdit(float initialValue, int id)
m_lineEdit = new QLineEdit(QString::number(m_value));
layout->addWidget(m_lineEdit);
- connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(editDone()));
+ connect(m_lineEdit, &QLineEdit::editingFinished, this, &FloatEdit::editDone);
}
void FloatEdit::editDone()
@@ -252,7 +252,7 @@ void TwoSidedGraphicsWidget::animateFlip()
.translate(-r.width() / 2, -r.height() / 2));
if ((m_current == 0 && m_angle > 0) || (m_current == 1 && m_angle < 180))
- QTimer::singleShot(25, this, SLOT(animateFlip()));
+ QTimer::singleShot(25, this, &TwoSidedGraphicsWidget::animateFlip);
}
QVariant GraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value)
@@ -307,19 +307,17 @@ RenderOptionsDialog::RenderOptionsDialog()
check->setCheckState(Qt::Unchecked);
// Dynamic cube maps are only enabled when multi-texturing and render to texture are available.
check->setEnabled(glActiveTexture && glGenFramebuffersEXT);
- connect(check, SIGNAL(stateChanged(int)), this, SIGNAL(dynamicCubemapToggled(int)));
+ connect(check, &QCheckBox::stateChanged, this, &RenderOptionsDialog::dynamicCubemapToggled);
layout->addWidget(check, 0, 0, 1, 2);
++row;
- QPalette palette;
-
// Load all .par files
// .par files have a simple syntax for specifying user adjustable uniform variables.
- QSet<QByteArray> uniforms;
- QList<QString> filter = QStringList("*.par");
- QList<QFileInfo> files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable);
+ const QList<QFileInfo> files = QDir(QStringLiteral(":/res/boxes/"))
+ .entryInfoList({ QStringLiteral("*.par") },
+ QDir::Files | QDir::Readable);
- foreach (QFileInfo fileInfo, files) {
+ for (const QFileInfo &fileInfo : files) {
QFile file(fileInfo.absoluteFilePath());
if (file.open(QIODevice::ReadOnly)) {
while (!file.atEnd()) {
@@ -356,7 +354,7 @@ RenderOptionsDialog::RenderOptionsDialog()
ColorEdit *colorEdit = new ColorEdit(it->toUInt(&ok, 16), m_parameterNames.size() - 1);
m_parameterEdits << colorEdit;
layout->addWidget(colorEdit);
- connect(colorEdit, SIGNAL(colorChanged(QRgb,int)), this, SLOT(setColorParameter(QRgb,int)));
+ connect(colorEdit, &ColorEdit::colorChanged, this, &RenderOptionsDialog::setColorParameter);
++row;
} else if (type == "float") {
layout->addWidget(new QLabel(m_parameterNames.back()));
@@ -364,7 +362,7 @@ RenderOptionsDialog::RenderOptionsDialog()
FloatEdit *floatEdit = new FloatEdit(it->toFloat(&ok), m_parameterNames.size() - 1);
m_parameterEdits << floatEdit;
layout->addWidget(floatEdit);
- connect(floatEdit, SIGNAL(valueChanged(float,int)), this, SLOT(setFloatParameter(float,int)));
+ connect(floatEdit, &FloatEdit::valueChanged, this, &RenderOptionsDialog::setFloatParameter);
++row;
}
}
@@ -375,13 +373,15 @@ RenderOptionsDialog::RenderOptionsDialog()
layout->addWidget(new QLabel(tr("Texture:")));
m_textureCombo = new QComboBox;
- connect(m_textureCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(textureChanged(int)));
+ connect(m_textureCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &RenderOptionsDialog::textureChanged);
layout->addWidget(m_textureCombo);
++row;
layout->addWidget(new QLabel(tr("Shader:")));
m_shaderCombo = new QComboBox;
- connect(m_shaderCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(shaderChanged(int)));
+ connect(m_shaderCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &RenderOptionsDialog::shaderChanged);
layout->addWidget(m_shaderCombo);
++row;
@@ -402,7 +402,7 @@ int RenderOptionsDialog::addShader(const QString &name)
void RenderOptionsDialog::emitParameterChanged()
{
- foreach (ParameterEdit *edit, m_parameterEdits)
+ for (ParameterEdit *edit : qAsConst(m_parameterEdits))
edit->emitChange();
}
@@ -439,15 +439,15 @@ ItemDialog::ItemDialog()
button = new QPushButton(tr("Add Qt box"));
layout->addWidget(button);
- connect(button, SIGNAL(clicked()), this, SLOT(triggerNewQtBox()));
+ connect(button, &QAbstractButton::clicked, this, &ItemDialog::triggerNewQtBox);
button = new QPushButton(tr("Add circle"));
layout->addWidget(button);
- connect(button, SIGNAL(clicked()), this, SLOT(triggerNewCircleItem()));
+ connect(button, &QAbstractButton::clicked, this, &ItemDialog::triggerNewCircleItem);
button = new QPushButton(tr("Add square"));
layout->addWidget(button);
- connect(button, SIGNAL(clicked()), this, SLOT(triggerNewSquareItem()));
+ connect(button, &QAbstractButton::clicked, this, &ItemDialog::triggerNewSquareItem);
layout->addStretch(1);
}
@@ -506,21 +506,21 @@ Scene::Scene(int width, int height, int maxTextureSize)
m_renderOptions->move(20, 120);
m_renderOptions->resize(m_renderOptions->sizeHint());
- connect(m_renderOptions, SIGNAL(dynamicCubemapToggled(int)), this, SLOT(toggleDynamicCubemap(int)));
- connect(m_renderOptions, SIGNAL(colorParameterChanged(QString,QRgb)), this, SLOT(setColorParameter(QString,QRgb)));
- connect(m_renderOptions, SIGNAL(floatParameterChanged(QString,float)), this, SLOT(setFloatParameter(QString,float)));
- connect(m_renderOptions, SIGNAL(textureChanged(int)), this, SLOT(setTexture(int)));
- connect(m_renderOptions, SIGNAL(shaderChanged(int)), this, SLOT(setShader(int)));
+ connect(m_renderOptions, &RenderOptionsDialog::dynamicCubemapToggled, this, &Scene::toggleDynamicCubemap);
+ connect(m_renderOptions, &RenderOptionsDialog::colorParameterChanged, this, &Scene::setColorParameter);
+ connect(m_renderOptions, &RenderOptionsDialog::floatParameterChanged, this, &Scene::setFloatParameter);
+ connect(m_renderOptions, &RenderOptionsDialog::textureChanged, this, &Scene::setTexture);
+ connect(m_renderOptions, &RenderOptionsDialog::shaderChanged, this, &Scene::setShader);
m_itemDialog = new ItemDialog;
- connect(m_itemDialog, SIGNAL(newItemTriggered(ItemDialog::ItemType)), this, SLOT(newItem(ItemDialog::ItemType)));
+ connect(m_itemDialog, &ItemDialog::newItemTriggered, this, &Scene::newItem);
TwoSidedGraphicsWidget *twoSided = new TwoSidedGraphicsWidget(this);
twoSided->setWidget(0, m_renderOptions);
twoSided->setWidget(1, m_itemDialog);
- connect(m_renderOptions, SIGNAL(doubleClicked()), twoSided, SLOT(flip()));
- connect(m_itemDialog, SIGNAL(doubleClicked()), twoSided, SLOT(flip()));
+ connect(m_renderOptions, &RenderOptionsDialog::doubleClicked, twoSided, &TwoSidedGraphicsWidget::flip);
+ connect(m_itemDialog, &ItemDialog::doubleClicked, twoSided, &TwoSidedGraphicsWidget::flip);
addItem(new QtBox(64, width - 64, height - 64));
addItem(new QtBox(64, width - 64, 64));
@@ -531,32 +531,21 @@ Scene::Scene(int width, int height, int maxTextureSize)
m_timer = new QTimer(this);
m_timer->setInterval(20);
- connect(m_timer, SIGNAL(timeout()), this, SLOT(update()));
+ connect(m_timer, &QTimer::timeout, this, [this](){ update(); });
m_timer->start();
-
- m_time.start();
}
Scene::~Scene()
{
- if (m_box)
- delete m_box;
- foreach (GLTexture *texture, m_textures)
- if (texture) delete texture;
- if (m_mainCubemap)
- delete m_mainCubemap;
- foreach (QGLShaderProgram *program, m_programs)
- if (program) delete program;
- if (m_vertexShader)
- delete m_vertexShader;
- foreach (QGLShader *shader, m_fragmentShaders)
- if (shader) delete shader;
- foreach (GLRenderTargetCube *rt, m_cubemaps)
- if (rt) delete rt;
- if (m_environmentShader)
- delete m_environmentShader;
- if (m_environmentProgram)
- delete m_environmentProgram;
+ delete m_box;
+ qDeleteAll(m_textures);
+ delete m_mainCubemap;
+ qDeleteAll(m_programs);
+ delete m_vertexShader;
+ qDeleteAll(m_fragmentShaders);
+ qDeleteAll(m_cubemaps);
+ delete m_environmentShader;
+ delete m_environmentProgram;
}
void Scene::initGL()
@@ -601,15 +590,13 @@ void Scene::initGL()
m_mainCubemap = new GLRenderTargetCube(512);
- QStringList filter;
QList<QFileInfo> files;
// Load all .png files as textures
m_currentTexture = 0;
- filter = QStringList("*.png");
- files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable);
+ files = QDir(":/res/boxes/").entryInfoList({ QStringLiteral("*.png") }, QDir::Files | QDir::Readable);
- foreach (QFileInfo file, files) {
+ for (const QFileInfo &file : qAsConst(files)) {
GLTexture *texture = new GLTexture2D(file.absoluteFilePath(), qMin(256, m_maxTextureSize), qMin(256, m_maxTextureSize));
if (texture->failed()) {
delete texture;
@@ -624,9 +611,8 @@ void Scene::initGL()
// Load all .fsh files as fragment shaders
m_currentShader = 0;
- filter = QStringList("*.fsh");
- files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable);
- foreach (QFileInfo file, files) {
+ files = QDir(":/res/boxes/").entryInfoList({ QStringLiteral("*.fsh") }, QDir::Files | QDir::Readable);
+ for (const QFileInfo &file : qAsConst(files)) {
QGLShaderProgram *program = new QGLShaderProgram;
QGLShader* shader = new QGLShader(QGLShader::Fragment);
shader->compileSourceFile(file.absoluteFilePath());
@@ -662,7 +648,7 @@ void Scene::initGL()
m_renderOptions->emitParameterChanged();
}
-static void loadMatrix(const QMatrix4x4& m)
+static void loadMatrix(const QMatrix4x4 &m)
{
// static to prevent glLoadMatrixf to fail on certain drivers
static GLfloat mat[16];
@@ -1051,7 +1037,7 @@ void Scene::toggleDynamicCubemap(int state)
void Scene::setColorParameter(const QString &name, QRgb color)
{
// set the color in all programs
- foreach (QGLShaderProgram *program, m_programs) {
+ for (QGLShaderProgram *program : qAsConst(m_programs)) {
program->bind();
program->setUniformValue(program->uniformLocation(name), QColor(color));
program->release();
@@ -1061,7 +1047,7 @@ void Scene::setColorParameter(const QString &name, QRgb color)
void Scene::setFloatParameter(const QString &name, float value)
{
// set the color in all programs
- foreach (QGLShaderProgram *program, m_programs) {
+ for (QGLShaderProgram *program : qAsConst(m_programs)) {
program->bind();
program->setUniformValue(program->uniformLocation(name), value);
program->release();
diff --git a/examples/widgets/graphicsview/boxes/scene.h b/examples/widgets/graphicsview/boxes/scene.h
index ccb6f368cd..ffff01358f 100644
--- a/examples/widgets/graphicsview/boxes/scene.h
+++ b/examples/widgets/graphicsview/boxes/scene.h
@@ -220,7 +220,7 @@ private:
void initGL();
QPointF pixelPosToViewPos(const QPointF& p);
- QTime m_time;
+ QTime m_time; // ### Qt 6: remove (unused)
int m_lastTime;
int m_mouseEventTime;
int m_distExp;
diff --git a/examples/widgets/graphicsview/chip/chip.cpp b/examples/widgets/graphicsview/chip/chip.cpp
index 443994e121..3d2bbdfcef 100644
--- a/examples/widgets/graphicsview/chip/chip.cpp
+++ b/examples/widgets/graphicsview/chip/chip.cpp
@@ -79,9 +79,9 @@ void Chip::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
{
Q_UNUSED(widget);
- QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color;
+ QColor fillColor = (option->state & QStyle::State_Selected) ? color.darker(150) : color;
if (option->state & QStyle::State_MouseOver)
- fillColor = fillColor.light(125);
+ fillColor = fillColor.lighter(125);
const qreal lod = option->levelOfDetailFromTransform(painter->worldTransform());
if (lod < 0.2) {
@@ -105,7 +105,7 @@ void Chip::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
pen.setWidth(width);
QBrush b = painter->brush();
- painter->setBrush(QBrush(fillColor.dark(option->state & QStyle::State_Sunken ? 120 : 100)));
+ painter->setBrush(QBrush(fillColor.darker(option->state & QStyle::State_Sunken ? 120 : 100)));
painter->drawRect(QRect(14, 14, 79, 39));
painter->setBrush(b);
diff --git a/examples/widgets/graphicsview/chip/view.cpp b/examples/widgets/graphicsview/chip/view.cpp
index 491f1a54cf..9676c13ff7 100644
--- a/examples/widgets/graphicsview/chip/view.cpp
+++ b/examples/widgets/graphicsview/chip/view.cpp
@@ -190,22 +190,22 @@ View::View(const QString &name, QWidget *parent)
topLayout->addWidget(resetButton, 2, 1);
setLayout(topLayout);
- connect(resetButton, SIGNAL(clicked()), this, SLOT(resetView()));
- connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix()));
- connect(rotateSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix()));
- connect(graphicsView->verticalScrollBar(), SIGNAL(valueChanged(int)),
- this, SLOT(setResetButtonEnabled()));
- connect(graphicsView->horizontalScrollBar(), SIGNAL(valueChanged(int)),
- this, SLOT(setResetButtonEnabled()));
- connect(selectModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode()));
- connect(dragModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode()));
- connect(antialiasButton, SIGNAL(toggled(bool)), this, SLOT(toggleAntialiasing()));
- connect(openGlButton, SIGNAL(toggled(bool)), this, SLOT(toggleOpenGL()));
- connect(rotateLeftIcon, SIGNAL(clicked()), this, SLOT(rotateLeft()));
- connect(rotateRightIcon, SIGNAL(clicked()), this, SLOT(rotateRight()));
- connect(zoomInIcon, SIGNAL(clicked()), this, SLOT(zoomIn()));
- connect(zoomOutIcon, SIGNAL(clicked()), this, SLOT(zoomOut()));
- connect(printButton, SIGNAL(clicked()), this, SLOT(print()));
+ connect(resetButton, &QAbstractButton::clicked, this, &View::resetView);
+ connect(zoomSlider, &QAbstractSlider::valueChanged, this, &View::setupMatrix);
+ connect(rotateSlider, &QAbstractSlider::valueChanged, this, &View::setupMatrix);
+ connect(graphicsView->verticalScrollBar(), &QAbstractSlider::valueChanged,
+ this, &View::setResetButtonEnabled);
+ connect(graphicsView->horizontalScrollBar(), &QAbstractSlider::valueChanged,
+ this, &View::setResetButtonEnabled);
+ connect(selectModeButton, &QAbstractButton::toggled, this, &View::togglePointerMode);
+ connect(dragModeButton, &QAbstractButton::toggled, this, &View::togglePointerMode);
+ connect(antialiasButton, &QAbstractButton::toggled, this, &View::toggleAntialiasing);
+ connect(openGlButton, &QAbstractButton::toggled, this, &View::toggleOpenGL);
+ connect(rotateLeftIcon, &QAbstractButton::clicked, this, &View::rotateLeft);
+ connect(rotateRightIcon, &QAbstractButton::clicked, this, &View::rotateRight);
+ connect(zoomInIcon, &QAbstractButton::clicked, this, &View::zoomIn);
+ connect(zoomOutIcon, &QAbstractButton::clicked, this, &View::zoomOut);
+ connect(printButton, &QAbstractButton::clicked, this, &View::print);
setupMatrix();
}
diff --git a/examples/widgets/graphicsview/collidingmice/main.cpp b/examples/widgets/graphicsview/collidingmice/main.cpp
index 91aee70b86..dfb20815b9 100644
--- a/examples/widgets/graphicsview/collidingmice/main.cpp
+++ b/examples/widgets/graphicsview/collidingmice/main.cpp
@@ -92,7 +92,7 @@ int main(int argc, char **argv)
view.show();
QTimer timer;
- QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance()));
+ QObject::connect(&timer, &QTimer::timeout, &scene, &QGraphicsScene::advance);
timer.start(1000 / 33);
return app.exec();
diff --git a/examples/widgets/graphicsview/collidingmice/mouse.cpp b/examples/widgets/graphicsview/collidingmice/mouse.cpp
index 14f887f6e3..a8fcc05d76 100644
--- a/examples/widgets/graphicsview/collidingmice/mouse.cpp
+++ b/examples/widgets/graphicsview/collidingmice/mouse.cpp
@@ -160,11 +160,12 @@ void Mouse::advance(int step)
// Try not to crash with any other mice
//! [7]
- QList<QGraphicsItem *> dangerMice = scene()->items(QPolygonF()
- << mapToScene(0, 0)
- << mapToScene(-30, -50)
- << mapToScene(30, -50));
- foreach (QGraphicsItem *item, dangerMice) {
+ const QList<QGraphicsItem *> dangerMice = scene()->items(QPolygonF()
+ << mapToScene(0, 0)
+ << mapToScene(-30, -50)
+ << mapToScene(30, -50));
+
+ for (const QGraphicsItem *item : dangerMice) {
if (item == this)
continue;
diff --git a/examples/widgets/graphicsview/diagramscene/arrow.cpp b/examples/widgets/graphicsview/diagramscene/arrow.cpp
index 88160d9399..525e0b3fbb 100644
--- a/examples/widgets/graphicsview/diagramscene/arrow.cpp
+++ b/examples/widgets/graphicsview/diagramscene/arrow.cpp
@@ -113,15 +113,13 @@ void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
QLineF centerLine(myStartItem->pos(), myEndItem->pos());
QPolygonF endPolygon = myEndItem->polygon();
QPointF p1 = endPolygon.first() + myEndItem->pos();
- QPointF p2;
QPointF intersectPoint;
- QLineF polyLine;
for (int i = 1; i < endPolygon.count(); ++i) {
- p2 = endPolygon.at(i) + myEndItem->pos();
- polyLine = QLineF(p1, p2);
- QLineF::IntersectType intersectType =
- polyLine.intersect(centerLine, &intersectPoint);
- if (intersectType == QLineF::BoundedIntersection)
+ QPointF p2 = endPolygon.at(i) + myEndItem->pos();
+ QLineF polyLine = QLineF(p1, p2);
+ QLineF::IntersectionType intersectionType =
+ polyLine.intersects(centerLine, &intersectPoint);
+ if (intersectionType == QLineF::BoundedIntersection)
break;
p1 = p2;
}
diff --git a/examples/widgets/graphicsview/diagramscene/diagramitem.cpp b/examples/widgets/graphicsview/diagramscene/diagramitem.cpp
index db6dabee56..3aa685635e 100644
--- a/examples/widgets/graphicsview/diagramscene/diagramitem.cpp
+++ b/examples/widgets/graphicsview/diagramscene/diagramitem.cpp
@@ -111,7 +111,7 @@ void DiagramItem::removeArrow(Arrow *arrow)
//! [2]
void DiagramItem::removeArrows()
{
- foreach (Arrow *arrow, arrows) {
+ for (Arrow *arrow : qAsConst(arrows)) {
arrow->startItem()->removeArrow(arrow);
arrow->endItem()->removeArrow(arrow);
scene()->removeItem(arrow);
@@ -154,9 +154,8 @@ void DiagramItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
QVariant DiagramItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == QGraphicsItem::ItemPositionChange) {
- foreach (Arrow *arrow, arrows) {
+ for (Arrow *arrow : qAsConst(arrows))
arrow->updatePosition();
- }
}
return value;
diff --git a/examples/widgets/graphicsview/diagramscene/diagramscene.cpp b/examples/widgets/graphicsview/diagramscene/diagramscene.cpp
index bbbc512b55..40272834c3 100644
--- a/examples/widgets/graphicsview/diagramscene/diagramscene.cpp
+++ b/examples/widgets/graphicsview/diagramscene/diagramscene.cpp
@@ -169,10 +169,10 @@ void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
textItem->setFont(myFont);
textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
textItem->setZValue(1000.0);
- connect(textItem, SIGNAL(lostFocus(DiagramTextItem*)),
- this, SLOT(editorLostFocus(DiagramTextItem*)));
- connect(textItem, SIGNAL(selectedChange(QGraphicsItem*)),
- this, SIGNAL(itemSelected(QGraphicsItem*)));
+ connect(textItem, &DiagramTextItem::lostFocus,
+ this, &DiagramScene::editorLostFocus);
+ connect(textItem, &DiagramTextItem::selectedChange,
+ this, &DiagramScene::itemSelected);
addItem(textItem);
textItem->setDefaultTextColor(myTextColor);
textItem->setPos(mouseEvent->scenePos());
@@ -234,12 +234,10 @@ void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
//! [13]
//! [14]
-bool DiagramScene::isItemChange(int type)
+bool DiagramScene::isItemChange(int type) const
{
- foreach (QGraphicsItem *item, selectedItems()) {
- if (item->type() == type)
- return true;
- }
- return false;
+ const QList<QGraphicsItem *> items = selectedItems();
+ const auto cb = [type](const QGraphicsItem *item) { return item->type() == type; };
+ return std::find_if(items.begin(), items.end(), cb) != items.end();
}
//! [14]
diff --git a/examples/widgets/graphicsview/diagramscene/diagramscene.h b/examples/widgets/graphicsview/diagramscene/diagramscene.h
index 95f7f3c621..15063d58b7 100644
--- a/examples/widgets/graphicsview/diagramscene/diagramscene.h
+++ b/examples/widgets/graphicsview/diagramscene/diagramscene.h
@@ -100,7 +100,7 @@ protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
private:
- bool isItemChange(int type);
+ bool isItemChange(int type) const;
DiagramItem::DiagramType myItemType;
QMenu *myItemMenu;
diff --git a/examples/widgets/graphicsview/diagramscene/mainwindow.cpp b/examples/widgets/graphicsview/diagramscene/mainwindow.cpp
index 36353674ea..3327d4d5df 100644
--- a/examples/widgets/graphicsview/diagramscene/mainwindow.cpp
+++ b/examples/widgets/graphicsview/diagramscene/mainwindow.cpp
@@ -67,12 +67,12 @@ MainWindow::MainWindow()
scene = new DiagramScene(itemMenu, this);
scene->setSceneRect(QRectF(0, 0, 5000, 5000));
- connect(scene, SIGNAL(itemInserted(DiagramItem*)),
- this, SLOT(itemInserted(DiagramItem*)));
- connect(scene, SIGNAL(textInserted(QGraphicsTextItem*)),
- this, SLOT(textInserted(QGraphicsTextItem*)));
- connect(scene, SIGNAL(itemSelected(QGraphicsItem*)),
- this, SLOT(itemSelected(QGraphicsItem*)));
+ connect(scene, &DiagramScene::itemInserted,
+ this, &MainWindow::itemInserted);
+ connect(scene, &DiagramScene::textInserted,
+ this, &MainWindow::textInserted);
+ connect(scene, &DiagramScene::itemSelected,
+ this, &MainWindow::itemSelected);
createToolbars();
QHBoxLayout *layout = new QHBoxLayout;
@@ -92,8 +92,8 @@ MainWindow::MainWindow()
//! [1]
void MainWindow::backgroundButtonGroupClicked(QAbstractButton *button)
{
- QList<QAbstractButton *> buttons = backgroundButtonGroup->buttons();
- foreach (QAbstractButton *myButton, buttons) {
+ const QList<QAbstractButton *> buttons = backgroundButtonGroup->buttons();
+ for (QAbstractButton *myButton : buttons) {
if (myButton != button)
button->setChecked(false);
}
@@ -115,8 +115,8 @@ void MainWindow::backgroundButtonGroupClicked(QAbstractButton *button)
//! [2]
void MainWindow::buttonGroupClicked(int id)
{
- QList<QAbstractButton *> buttons = buttonGroup->buttons();
- foreach (QAbstractButton *button, buttons) {
+ const QList<QAbstractButton *> buttons = buttonGroup->buttons();
+ for (QAbstractButton *button : buttons) {
if (buttonGroup->button(id) != button)
button->setChecked(false);
}
@@ -132,7 +132,8 @@ void MainWindow::buttonGroupClicked(int id)
//! [3]
void MainWindow::deleteItem()
{
- foreach (QGraphicsItem *item, scene->selectedItems()) {
+ QList<QGraphicsItem *> selectedItems = scene->selectedItems();
+ for (QGraphicsItem *item : qAsConst(selectedItems)) {
if (item->type() == Arrow::Type) {
scene->removeItem(item);
Arrow *arrow = qgraphicsitem_cast<Arrow *>(item);
@@ -142,7 +143,8 @@ void MainWindow::deleteItem()
}
}
- foreach (QGraphicsItem *item, scene->selectedItems()) {
+ selectedItems = scene->selectedItems();
+ for (QGraphicsItem *item : qAsConst(selectedItems)) {
if (item->type() == DiagramItem::Type)
qgraphicsitem_cast<DiagramItem *>(item)->removeArrows();
scene->removeItem(item);
@@ -165,10 +167,10 @@ void MainWindow::bringToFront()
return;
QGraphicsItem *selectedItem = scene->selectedItems().first();
- QList<QGraphicsItem *> overlapItems = selectedItem->collidingItems();
+ const QList<QGraphicsItem *> overlapItems = selectedItem->collidingItems();
qreal zValue = 0;
- foreach (QGraphicsItem *item, overlapItems) {
+ for (const QGraphicsItem *item : overlapItems) {
if (item->zValue() >= zValue && item->type() == DiagramItem::Type)
zValue = item->zValue() + 0.1;
}
@@ -183,10 +185,10 @@ void MainWindow::sendToBack()
return;
QGraphicsItem *selectedItem = scene->selectedItems().first();
- QList<QGraphicsItem *> overlapItems = selectedItem->collidingItems();
+ const QList<QGraphicsItem *> overlapItems = selectedItem->collidingItems();
qreal zValue = 0;
- foreach (QGraphicsItem *item, overlapItems) {
+ for (const QGraphicsItem *item : overlapItems) {
if (item->zValue() <= zValue && item->type() == DiagramItem::Type)
zValue = item->zValue() - 0.1;
}
@@ -332,8 +334,8 @@ void MainWindow::createToolBox()
{
buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(false);
- connect(buttonGroup, SIGNAL(buttonClicked(int)),
- this, SLOT(buttonGroupClicked(int)));
+ connect(buttonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked),
+ this, &MainWindow::buttonGroupClicked);
QGridLayout *layout = new QGridLayout;
layout->addWidget(createCellWidget(tr("Conditional"), DiagramItem::Conditional), 0, 0);
layout->addWidget(createCellWidget(tr("Process"), DiagramItem::Step),0, 1);
@@ -359,8 +361,8 @@ void MainWindow::createToolBox()
itemWidget->setLayout(layout);
backgroundButtonGroup = new QButtonGroup(this);
- connect(backgroundButtonGroup, SIGNAL(buttonClicked(QAbstractButton*)),
- this, SLOT(backgroundButtonGroupClicked(QAbstractButton*)));
+ connect(backgroundButtonGroup, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
+ this, &MainWindow::backgroundButtonGroupClicked);
QGridLayout *backgroundLayout = new QGridLayout;
backgroundLayout->addWidget(createBackgroundCellWidget(tr("Blue Grid"),
@@ -395,44 +397,44 @@ void MainWindow::createActions()
tr("Bring to &Front"), this);
toFrontAction->setShortcut(tr("Ctrl+F"));
toFrontAction->setStatusTip(tr("Bring item to front"));
- connect(toFrontAction, SIGNAL(triggered()), this, SLOT(bringToFront()));
+ connect(toFrontAction, &QAction::triggered, this, &MainWindow::bringToFront);
//! [23]
sendBackAction = new QAction(QIcon(":/images/sendtoback.png"), tr("Send to &Back"), this);
sendBackAction->setShortcut(tr("Ctrl+T"));
sendBackAction->setStatusTip(tr("Send item to back"));
- connect(sendBackAction, SIGNAL(triggered()), this, SLOT(sendToBack()));
+ connect(sendBackAction, &QAction::triggered, this, &MainWindow::sendToBack);
deleteAction = new QAction(QIcon(":/images/delete.png"), tr("&Delete"), this);
deleteAction->setShortcut(tr("Delete"));
deleteAction->setStatusTip(tr("Delete item from diagram"));
- connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteItem()));
+ connect(deleteAction, &QAction::triggered, this, &MainWindow::deleteItem);
exitAction = new QAction(tr("E&xit"), this);
exitAction->setShortcuts(QKeySequence::Quit);
exitAction->setStatusTip(tr("Quit Scenediagram example"));
- connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
+ connect(exitAction, &QAction::triggered, this, &QWidget::close);
boldAction = new QAction(tr("Bold"), this);
boldAction->setCheckable(true);
QPixmap pixmap(":/images/bold.png");
boldAction->setIcon(QIcon(pixmap));
boldAction->setShortcut(tr("Ctrl+B"));
- connect(boldAction, SIGNAL(triggered()), this, SLOT(handleFontChange()));
+ connect(boldAction, &QAction::triggered, this, &MainWindow::handleFontChange);
italicAction = new QAction(QIcon(":/images/italic.png"), tr("Italic"), this);
italicAction->setCheckable(true);
italicAction->setShortcut(tr("Ctrl+I"));
- connect(italicAction, SIGNAL(triggered()), this, SLOT(handleFontChange()));
+ connect(italicAction, &QAction::triggered, this, &MainWindow::handleFontChange);
underlineAction = new QAction(QIcon(":/images/underline.png"), tr("Underline"), this);
underlineAction->setCheckable(true);
underlineAction->setShortcut(tr("Ctrl+U"));
- connect(underlineAction, SIGNAL(triggered()), this, SLOT(handleFontChange()));
+ connect(underlineAction, &QAction::triggered, this, &MainWindow::handleFontChange);
aboutAction = new QAction(tr("A&bout"), this);
aboutAction->setShortcut(tr("F1"));
- connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
+ connect(aboutAction, &QAction::triggered, this, &MainWindow::about);
}
//! [24]
@@ -462,8 +464,8 @@ void MainWindow::createToolbars()
editToolBar->addAction(sendBackAction);
fontCombo = new QFontComboBox();
- connect(fontCombo, SIGNAL(currentFontChanged(QFont)),
- this, SLOT(currentFontChanged(QFont)));
+ connect(fontCombo, &QFontComboBox::currentFontChanged,
+ this, &MainWindow::currentFontChanged);
fontSizeCombo = new QComboBox;
fontSizeCombo->setEditable(true);
@@ -471,8 +473,8 @@ void MainWindow::createToolbars()
fontSizeCombo->addItem(QString().setNum(i));
QIntValidator *validator = new QIntValidator(2, 64, this);
fontSizeCombo->setValidator(validator);
- connect(fontSizeCombo, SIGNAL(currentIndexChanged(QString)),
- this, SLOT(fontSizeChanged(QString)));
+ connect(fontSizeCombo, &QComboBox::currentTextChanged,
+ this, &MainWindow::fontSizeChanged);
fontColorToolButton = new QToolButton;
fontColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
@@ -480,8 +482,8 @@ void MainWindow::createToolbars()
textAction = fontColorToolButton->menu()->defaultAction();
fontColorToolButton->setIcon(createColorToolButtonIcon(":/images/textpointer.png", Qt::black));
fontColorToolButton->setAutoFillBackground(true);
- connect(fontColorToolButton, SIGNAL(clicked()),
- this, SLOT(textButtonTriggered()));
+ connect(fontColorToolButton, &QAbstractButton::clicked,
+ this, &MainWindow::textButtonTriggered);
//! [26]
fillColorToolButton = new QToolButton;
@@ -490,8 +492,8 @@ void MainWindow::createToolbars()
fillAction = fillColorToolButton->menu()->defaultAction();
fillColorToolButton->setIcon(createColorToolButtonIcon(
":/images/floodfill.png", Qt::white));
- connect(fillColorToolButton, SIGNAL(clicked()),
- this, SLOT(fillButtonTriggered()));
+ connect(fillColorToolButton, &QAbstractButton::clicked,
+ this, &MainWindow::fillButtonTriggered);
//! [26]
lineColorToolButton = new QToolButton;
@@ -500,8 +502,8 @@ void MainWindow::createToolbars()
lineAction = lineColorToolButton->menu()->defaultAction();
lineColorToolButton->setIcon(createColorToolButtonIcon(
":/images/linecolor.png", Qt::black));
- connect(lineColorToolButton, SIGNAL(clicked()),
- this, SLOT(lineButtonTriggered()));
+ connect(lineColorToolButton, &QAbstractButton::clicked,
+ this, &MainWindow::lineButtonTriggered);
textToolBar = addToolBar(tr("Font"));
textToolBar->addWidget(fontCombo);
@@ -526,16 +528,16 @@ void MainWindow::createToolbars()
pointerTypeGroup = new QButtonGroup(this);
pointerTypeGroup->addButton(pointerButton, int(DiagramScene::MoveItem));
pointerTypeGroup->addButton(linePointerButton, int(DiagramScene::InsertLine));
- connect(pointerTypeGroup, SIGNAL(buttonClicked(int)),
- this, SLOT(pointerGroupClicked(int)));
+ connect(pointerTypeGroup, QOverload<int>::of(&QButtonGroup::buttonClicked),
+ this, &MainWindow::pointerGroupClicked);
sceneScaleCombo = new QComboBox;
QStringList scales;
scales << tr("50%") << tr("75%") << tr("100%") << tr("125%") << tr("150%");
sceneScaleCombo->addItems(scales);
sceneScaleCombo->setCurrentIndex(2);
- connect(sceneScaleCombo, SIGNAL(currentIndexChanged(QString)),
- this, SLOT(sceneScaleChanged(QString)));
+ connect(sceneScaleCombo, &QComboBox::currentTextChanged,
+ this, &MainWindow::sceneScaleChanged);
pointerToolbar = addToolBar(tr("Pointer type"));
pointerToolbar->addWidget(pointerButton);
diff --git a/examples/widgets/graphicsview/dragdroprobot/robot.cpp b/examples/widgets/graphicsview/dragdroprobot/robot.cpp
index 38552747af..cc70366872 100644
--- a/examples/widgets/graphicsview/dragdroprobot/robot.cpp
+++ b/examples/widgets/graphicsview/dragdroprobot/robot.cpp
@@ -113,7 +113,7 @@ void RobotHead::paint(QPainter *painter,
Q_UNUSED(option);
Q_UNUSED(widget);
if (pixmap.isNull()) {
- painter->setBrush(dragOver ? color.light(130) : color);
+ painter->setBrush(dragOver ? color.lighter(130) : color);
painter->drawRoundedRect(-10, -30, 20, 30, 25, 25, Qt::RelativeSize);
painter->setBrush(Qt::white);
painter->drawEllipse(-7, -3 - 20, 7, 7);
@@ -173,7 +173,7 @@ void RobotTorso::paint(QPainter *painter,
Q_UNUSED(option);
Q_UNUSED(widget);
- painter->setBrush(dragOver ? color.light(130) : color);
+ painter->setBrush(dragOver ? color.lighter(130) : color);
painter->drawRoundedRect(-20, -20, 40, 60, 25, 25, Qt::RelativeSize);
painter->drawEllipse(-25, -20, 20, 20);
painter->drawEllipse(5, -20, 20, 20);
@@ -197,7 +197,7 @@ void RobotLimb::paint(QPainter *painter,
Q_UNUSED(option);
Q_UNUSED(widget);
- painter->setBrush(dragOver ? color.light(130) : color);
+ painter->setBrush(dragOver ? color.lighter(130) : color);
painter->drawRoundedRect(boundingRect(), 50, 50, Qt::RelativeSize);
painter->drawEllipse(-5, -5, 10, 10);
}
diff --git a/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp b/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp
index 81928a4ee1..6b817b2a21 100644
--- a/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp
+++ b/examples/widgets/graphicsview/elasticnodes/graphwidget.cpp
@@ -164,16 +164,17 @@ void GraphWidget::timerEvent(QTimerEvent *event)
Q_UNUSED(event);
QList<Node *> nodes;
- foreach (QGraphicsItem *item, scene()->items()) {
+ const QList<QGraphicsItem *> items = scene()->items();
+ for (QGraphicsItem *item : items) {
if (Node *node = qgraphicsitem_cast<Node *>(item))
nodes << node;
}
- foreach (Node *node, nodes)
+ for (Node *node : qAsConst(nodes))
node->calculateForces();
bool itemsMoved = false;
- foreach (Node *node, nodes) {
+ for (Node *node : qAsConst(nodes)) {
if (node->advancePosition())
itemsMoved = true;
}
@@ -246,7 +247,8 @@ void GraphWidget::scaleView(qreal scaleFactor)
void GraphWidget::shuffle()
{
- foreach (QGraphicsItem *item, scene()->items()) {
+ const QList<QGraphicsItem *> items = scene()->items();
+ for (QGraphicsItem *item : items) {
if (qgraphicsitem_cast<Node *>(item))
item->setPos(-150 + QRandomGenerator::global()->bounded(300), -150 + QRandomGenerator::global()->bounded(300));
}
diff --git a/examples/widgets/graphicsview/elasticnodes/node.cpp b/examples/widgets/graphicsview/elasticnodes/node.cpp
index 71737c984b..8d44a167fa 100644
--- a/examples/widgets/graphicsview/elasticnodes/node.cpp
+++ b/examples/widgets/graphicsview/elasticnodes/node.cpp
@@ -94,7 +94,8 @@ void Node::calculateForces()
// Sum up all forces pushing this item away
qreal xvel = 0;
qreal yvel = 0;
- foreach (QGraphicsItem *item, scene()->items()) {
+ const QList<QGraphicsItem *> items = scene()->items();
+ for (QGraphicsItem *item : items) {
Node *node = qgraphicsitem_cast<Node *>(item);
if (!node)
continue;
@@ -113,7 +114,7 @@ void Node::calculateForces()
//! [4]
// Now subtract all forces pulling items together
double weight = (edgeList.size() + 1) * 10;
- foreach (Edge *edge, edgeList) {
+ for (const Edge *edge : qAsConst(edgeList)) {
QPointF vec;
if (edge->sourceNode() == this)
vec = mapToItem(edge->destNode(), 0, 0);
@@ -176,8 +177,8 @@ void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
if (option->state & QStyle::State_Sunken) {
gradient.setCenter(3, 3);
gradient.setFocalPoint(3, 3);
- gradient.setColorAt(1, QColor(Qt::yellow).light(120));
- gradient.setColorAt(0, QColor(Qt::darkYellow).light(120));
+ gradient.setColorAt(1, QColor(Qt::yellow).lighter(120));
+ gradient.setColorAt(0, QColor(Qt::darkYellow).lighter(120));
} else {
gradient.setColorAt(0, Qt::yellow);
gradient.setColorAt(1, Qt::darkYellow);
@@ -194,7 +195,7 @@ QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
{
switch (change) {
case ItemPositionHasChanged:
- foreach (Edge *edge, edgeList)
+ for (Edge *edge : qAsConst(edgeList))
edge->adjust();
graph->itemMoved();
break;
diff --git a/examples/widgets/graphicsview/embeddeddialogs/customproxy.cpp b/examples/widgets/graphicsview/embeddeddialogs/customproxy.cpp
index 158c31d9c1..f510ebc07f 100644
--- a/examples/widgets/graphicsview/embeddeddialogs/customproxy.cpp
+++ b/examples/widgets/graphicsview/embeddeddialogs/customproxy.cpp
@@ -55,13 +55,13 @@
#include <QGraphicsScene>
CustomProxy::CustomProxy(QGraphicsItem *parent, Qt::WindowFlags wFlags)
- : QGraphicsProxyWidget(parent, wFlags), popupShown(false), currentPopup(0)
+ : QGraphicsProxyWidget(parent, wFlags), popupShown(false), currentPopup(nullptr)
{
timeLine = new QTimeLine(250, this);
- connect(timeLine, SIGNAL(valueChanged(qreal)),
- this, SLOT(updateStep(qreal)));
- connect(timeLine, SIGNAL(stateChanged(QTimeLine::State)),
- this, SLOT(stateChanged(QTimeLine::State)));
+ connect(timeLine, &QTimeLine::valueChanged,
+ this, &CustomProxy::updateStep);
+ connect(timeLine, &QTimeLine::stateChanged,
+ this, &CustomProxy::stateChanged);
}
QRectF CustomProxy::boundingRect() const
@@ -133,7 +133,7 @@ QVariant CustomProxy::itemChange(GraphicsItemChange change, const QVariant &valu
currentPopup->installSceneEventFilter(this);
} else if (scene()) {
currentPopup->removeSceneEventFilter(this);
- currentPopup = 0;
+ currentPopup = nullptr;
}
} else if (currentPopup && change == ItemSceneHasChanged) {
currentPopup->installSceneEventFilter(this);
diff --git a/examples/widgets/graphicsview/embeddeddialogs/embeddeddialog.cpp b/examples/widgets/graphicsview/embeddeddialogs/embeddeddialog.cpp
index 0c3ed86565..9fa24fcd17 100644
--- a/examples/widgets/graphicsview/embeddeddialogs/embeddeddialog.cpp
+++ b/examples/widgets/graphicsview/embeddeddialogs/embeddeddialog.cpp
@@ -60,7 +60,8 @@ EmbeddedDialog::EmbeddedDialog(QWidget *parent)
ui->setupUi(this);
ui->layoutDirection->setCurrentIndex(layoutDirection() != Qt::LeftToRight);
- foreach (QString styleName, QStyleFactory::keys()) {
+ const QStringList styleKeys = QStyleFactory::keys();
+ for (const QString &styleName : styleKeys) {
ui->style->addItem(styleName);
if (style()->objectName().toLower() == styleName.toLower())
ui->style->setCurrentIndex(ui->style->count() - 1);
@@ -72,7 +73,7 @@ EmbeddedDialog::EmbeddedDialog(QWidget *parent)
this, &EmbeddedDialog::spacingChanged);
connect(ui->fontComboBox, &QFontComboBox::currentFontChanged,
this, &EmbeddedDialog::fontChanged);
- connect(ui->style, QOverload<const QString &>::of(&QComboBox::activated),
+ connect(ui->style, &QComboBox::textActivated,
this, &EmbeddedDialog::styleChanged);
}
@@ -101,7 +102,8 @@ static void setStyleHelper(QWidget *widget, QStyle *style)
{
widget->setStyle(style);
widget->setPalette(style->standardPalette());
- foreach (QObject *child, widget->children()) {
+ const QObjectList children = widget->children();
+ for (QObject *child : children) {
if (QWidget *childWidget = qobject_cast<QWidget *>(child))
setStyleHelper(childWidget, style);
}
diff --git a/examples/widgets/graphicsview/embeddeddialogs/main.cpp b/examples/widgets/graphicsview/embeddeddialogs/main.cpp
index cbd5dd5890..501405e3ff 100644
--- a/examples/widgets/graphicsview/embeddeddialogs/main.cpp
+++ b/examples/widgets/graphicsview/embeddeddialogs/main.cpp
@@ -66,7 +66,7 @@ int main(int argc, char *argv[])
for (int y = 0; y < gridSize; ++y) {
for (int x = 0; x < gridSize; ++x) {
- CustomProxy *proxy = new CustomProxy(0, Qt::Window);
+ CustomProxy *proxy = new CustomProxy(nullptr, Qt::Window);
proxy->setWidget(new EmbeddedDialog);
QRectF rect = proxy->boundingRect();
diff --git a/examples/widgets/graphicsview/flowlayout/flowlayout.cpp b/examples/widgets/graphicsview/flowlayout/flowlayout.cpp
index 065c3e00ea..ab6bbb7aa4 100644
--- a/examples/widgets/graphicsview/flowlayout/flowlayout.cpp
+++ b/examples/widgets/graphicsview/flowlayout/flowlayout.cpp
@@ -154,8 +154,7 @@ QSizeF FlowLayout::minSize(const QSizeF &constraint) const
} else if (constraint.height() >= 0) { // width for height?
// not supported
} else {
- QGraphicsLayoutItem *item;
- foreach (item, m_items)
+ for (const QGraphicsLayoutItem *item : qAsConst(m_items))
size = size.expandedTo(item->effectiveSizeHint(Qt::MinimumSize));
size += QSize(left + right, top + bottom);
}
@@ -167,10 +166,9 @@ QSizeF FlowLayout::prefSize() const
qreal left, right;
getContentsMargins(&left, 0, &right, 0);
- QGraphicsLayoutItem *item;
qreal maxh = 0;
qreal totalWidth = 0;
- foreach (item, m_items) {
+ for (const QGraphicsLayoutItem *item : qAsConst(m_items)) {
if (totalWidth > 0)
totalWidth += spacing(Qt::Horizontal);
QSizeF pref = item->effectiveSizeHint(Qt::PreferredSize);
@@ -187,10 +185,9 @@ QSizeF FlowLayout::prefSize() const
QSizeF FlowLayout::maxSize() const
{
- QGraphicsLayoutItem *item;
qreal totalWidth = 0;
qreal totalHeight = 0;
- foreach (item, m_items) {
+ for (const QGraphicsLayoutItem *item : qAsConst(m_items)) {
if (totalWidth > 0)
totalWidth += spacing(Qt::Horizontal);
if (totalHeight > 0)
diff --git a/examples/widgets/graphicsview/padnavigator/roundrectitem.cpp b/examples/widgets/graphicsview/padnavigator/roundrectitem.cpp
index f629400a76..82205050ec 100644
--- a/examples/widgets/graphicsview/padnavigator/roundrectitem.cpp
+++ b/examples/widgets/graphicsview/padnavigator/roundrectitem.cpp
@@ -62,7 +62,7 @@ RoundRectItem::RoundRectItem(const QRectF &bounds, const QColor &color,
gradient.setStart(bounds.topLeft());
gradient.setFinalStop(bounds.bottomRight());
gradient.setColorAt(0, color);
- gradient.setColorAt(1, color.dark(200));
+ gradient.setColorAt(1, color.darker(200));
setCacheMode(ItemCoordinateCache);
}
//! [0]
@@ -94,7 +94,7 @@ void RoundRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
Q_UNUSED(widget);
painter->setPen(Qt::NoPen);
painter->setBrush(QColor(0, 0, 0, 64));
- painter->drawRoundRect(bounds.translated(2, 2));
+ painter->drawRoundedRect(bounds.translated(2, 2), 25, 25, Qt::RelativeSize);
//! [3]
//! [4]
if (fillRect)
@@ -102,7 +102,7 @@ void RoundRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
else
painter->setBrush(gradient);
painter->setPen(QPen(Qt::black, 1));
- painter->drawRoundRect(bounds);
+ painter->drawRoundedRect(bounds, 25,25, Qt::RelativeSize);
//! [4]
//! [5]
if (!pix.isNull()) {
diff --git a/examples/widgets/graphicsview/padnavigator/splashitem.cpp b/examples/widgets/graphicsview/padnavigator/splashitem.cpp
index 0c3a05dd9a..7c3dfba588 100644
--- a/examples/widgets/graphicsview/padnavigator/splashitem.cpp
+++ b/examples/widgets/graphicsview/padnavigator/splashitem.cpp
@@ -79,7 +79,7 @@ void SplashItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option
painter->setPen(QPen(Qt::black, 2));
painter->setBrush(QColor(245, 245, 255, 220));
painter->setClipRect(boundingRect());
- painter->drawRoundRect(3, -100 + 3, 400 - 6, 250 - 6);
+ painter->drawRoundedRect(3, -100 + 3, 400 - 6, 250 - 6, 25, 25, Qt::RelativeSize);
QRectF textRect = boundingRect().adjusted(10, 10, -10, -10);
int flags = Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap;
diff --git a/examples/widgets/itemviews/addressbook/adddialog.cpp b/examples/widgets/itemviews/addressbook/adddialog.cpp
index 1ce2d3110a..bf87307253 100644
--- a/examples/widgets/itemviews/addressbook/adddialog.cpp
+++ b/examples/widgets/itemviews/addressbook/adddialog.cpp
@@ -54,17 +54,16 @@
//! [0]
AddDialog::AddDialog(QWidget *parent)
- : QDialog(parent)
+ : QDialog(parent),
+ nameText(new QLineEdit),
+ addressText(new QTextEdit)
{
- nameLabel = new QLabel("Name");
- addressLabel = new QLabel("Address");
- okButton = new QPushButton("OK");
- cancelButton = new QPushButton("Cancel");
+ auto nameLabel = new QLabel(tr("Name"));
+ auto addressLabel = new QLabel(tr("Address"));
+ auto okButton = new QPushButton(tr("OK"));
+ auto cancelButton = new QPushButton(tr("Cancel"));
- nameText = new QLineEdit;
- addressText = new QTextEdit;
-
- QGridLayout *gLayout = new QGridLayout;
+ auto gLayout = new QGridLayout;
gLayout->setColumnStretch(1, 2);
gLayout->addWidget(nameLabel, 0, 0);
gLayout->addWidget(nameText, 0, 1);
@@ -72,13 +71,13 @@ AddDialog::AddDialog(QWidget *parent)
gLayout->addWidget(addressLabel, 1, 0, Qt::AlignLeft|Qt::AlignTop);
gLayout->addWidget(addressText, 1, 1, Qt::AlignLeft);
- QHBoxLayout *buttonLayout = new QHBoxLayout;
+ auto buttonLayout = new QHBoxLayout;
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
gLayout->addLayout(buttonLayout, 2, 1, Qt::AlignRight);
- QVBoxLayout *mainLayout = new QVBoxLayout;
+ auto mainLayout = new QVBoxLayout;
mainLayout->addLayout(gLayout);
setLayout(mainLayout);
@@ -87,4 +86,21 @@ AddDialog::AddDialog(QWidget *parent)
setWindowTitle(tr("Add a Contact"));
}
+
+QString AddDialog::name() const
+{
+ return nameText->text();
+}
+
+QString AddDialog::address() const
+{
+ return addressText->toPlainText();
+}
+
+void AddDialog::editAddress(const QString &name, const QString &address)
+{
+ nameText->setReadOnly(true);
+ nameText->setText(name);
+ addressText->setPlainText(address);
+}
//! [0]
diff --git a/examples/widgets/itemviews/addressbook/adddialog.h b/examples/widgets/itemviews/addressbook/adddialog.h
index 16fa7bc650..2867034122 100644
--- a/examples/widgets/itemviews/addressbook/adddialog.h
+++ b/examples/widgets/itemviews/addressbook/adddialog.h
@@ -66,15 +66,15 @@ class AddDialog : public QDialog
Q_OBJECT
public:
- AddDialog(QWidget *parent = 0);
- QLineEdit *nameText;
- QTextEdit *addressText;
+ AddDialog(QWidget *parent = nullptr);
+
+ QString name() const;
+ QString address() const;
+ void editAddress(const QString &name, const QString &address);
private:
- QLabel *nameLabel;
- QLabel *addressLabel;
- QPushButton *okButton;
- QPushButton *cancelButton;
+ QLineEdit *nameText;
+ QTextEdit *addressText;
};
//! [0]
diff --git a/examples/widgets/itemviews/addressbook/addresswidget.cpp b/examples/widgets/itemviews/addressbook/addresswidget.cpp
index 143f6266dd..b1b65174ee 100644
--- a/examples/widgets/itemviews/addressbook/addresswidget.cpp
+++ b/examples/widgets/itemviews/addressbook/addresswidget.cpp
@@ -48,21 +48,21 @@
**
****************************************************************************/
-#include "adddialog.h"
#include "addresswidget.h"
+#include "adddialog.h"
#include <QtWidgets>
//! [0]
AddressWidget::AddressWidget(QWidget *parent)
- : QTabWidget(parent)
+ : QTabWidget(parent),
+ table(new TableModel(this)),
+ newAddressTab(new NewAddressTab(this))
{
- table = new TableModel(this);
- newAddressTab = new NewAddressTab(this);
connect(newAddressTab, &NewAddressTab::sendDetails,
this, &AddressWidget::addEntry);
- addTab(newAddressTab, "Address Book");
+ addTab(newAddressTab, tr("Address Book"));
setupTabs();
}
@@ -73,17 +73,13 @@ void AddressWidget::showAddEntryDialog()
{
AddDialog aDialog;
- if (aDialog.exec()) {
- QString name = aDialog.nameText->text();
- QString address = aDialog.addressText->toPlainText();
-
- addEntry(name, address);
- }
+ if (aDialog.exec())
+ addEntry(aDialog.name(), aDialog.address());
}
//! [2]
//! [3]
-void AddressWidget::addEntry(QString name, QString address)
+void AddressWidget::addEntry(const QString &name, const QString &address)
{
if (!table->getContacts().contains({ name, address })) {
table->insertRows(0, 1, QModelIndex());
@@ -107,12 +103,12 @@ void AddressWidget::editEntry()
QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(temp->model());
QItemSelectionModel *selectionModel = temp->selectionModel();
- QModelIndexList indexes = selectionModel->selectedRows();
+ const QModelIndexList indexes = selectionModel->selectedRows();
QString name;
QString address;
int row = -1;
- foreach (QModelIndex index, indexes) {
+ for (const QModelIndex &index : indexes) {
row = proxy->mapToSource(index).row();
QModelIndex nameIndex = table->index(row, 0, QModelIndex());
QVariant varName = table->data(nameIndex, Qt::DisplayRole);
@@ -127,15 +123,12 @@ void AddressWidget::editEntry()
//! [4b]
AddDialog aDialog;
aDialog.setWindowTitle(tr("Edit a Contact"));
-
- aDialog.nameText->setReadOnly(true);
- aDialog.nameText->setText(name);
- aDialog.addressText->setText(address);
+ aDialog.editAddress(name, address);
if (aDialog.exec()) {
- QString newAddress = aDialog.addressText->toPlainText();
+ const QString newAddress = aDialog.address();
if (newAddress != address) {
- QModelIndex index = table->index(row, 1, QModelIndex());
+ const QModelIndex index = table->index(row, 1, QModelIndex());
table->setData(index, newAddress, Qt::EditRole);
}
}
@@ -149,52 +142,46 @@ void AddressWidget::removeEntry()
QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(temp->model());
QItemSelectionModel *selectionModel = temp->selectionModel();
- QModelIndexList indexes = selectionModel->selectedRows();
+ const QModelIndexList indexes = selectionModel->selectedRows();
- foreach (QModelIndex index, indexes) {
+ for (QModelIndex index : indexes) {
int row = proxy->mapToSource(index).row();
table->removeRows(row, 1, QModelIndex());
}
- if (table->rowCount(QModelIndex()) == 0) {
- insertTab(0, newAddressTab, "Address Book");
- }
+ if (table->rowCount(QModelIndex()) == 0)
+ insertTab(0, newAddressTab, tr("Address Book"));
}
//! [5]
//! [1]
void AddressWidget::setupTabs()
{
- QStringList groups;
- groups << "ABC" << "DEF" << "GHI" << "JKL" << "MNO" << "PQR" << "STU" << "VW" << "XYZ";
+ const auto groups = { "ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ" };
- for (int i = 0; i < groups.size(); ++i) {
- QString str = groups.at(i);
- QString regExp = QString("^[%1].*").arg(str);
+ for (const QString &str : groups) {
+ const auto regExp = QRegularExpression(QString("^[%1].*").arg(str),
+ QRegularExpression::CaseInsensitiveOption);
- proxyModel = new QSortFilterProxyModel(this);
+ auto proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(table);
- proxyModel->setFilterRegExp(QRegExp(regExp, Qt::CaseInsensitive));
+ proxyModel->setFilterRegularExpression(regExp);
proxyModel->setFilterKeyColumn(0);
QTableView *tableView = new QTableView;
tableView->setModel(proxyModel);
-
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
tableView->horizontalHeader()->setStretchLastSection(true);
tableView->verticalHeader()->hide();
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
-
tableView->setSortingEnabled(true);
- connect(tableView->selectionModel(),
- &QItemSelectionModel::selectionChanged,
- this, &AddressWidget::selectionChanged);
+ connect(tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
+ this, &AddressWidget::selectionChanged);
- connect(this, &QTabWidget::currentChanged, this, [this](int tabIndex) {
- auto *tableView = qobject_cast<QTableView *>(widget(tabIndex));
- if (tableView)
+ connect(this, &QTabWidget::currentChanged, this, [this, tableView](int tabIndex) {
+ if (widget(tabIndex) == tableView)
emit selectionChanged(tableView->selectionModel()->selection());
});
@@ -214,7 +201,7 @@ void AddressWidget::readFromFile(const QString &fileName)
return;
}
- QList<Contact> contacts;
+ QVector<Contact> contacts;
QDataStream in(&file);
in >> contacts;
diff --git a/examples/widgets/itemviews/addressbook/addresswidget.h b/examples/widgets/itemviews/addressbook/addresswidget.h
index de5a2da766..111ea98328 100644
--- a/examples/widgets/itemviews/addressbook/addresswidget.h
+++ b/examples/widgets/itemviews/addressbook/addresswidget.h
@@ -68,13 +68,13 @@ class AddressWidget : public QTabWidget
Q_OBJECT
public:
- AddressWidget(QWidget *parent = 0);
+ AddressWidget(QWidget *parent = nullptr);
void readFromFile(const QString &fileName);
void writeToFile(const QString &fileName);
public slots:
void showAddEntryDialog();
- void addEntry(QString name, QString address);
+ void addEntry(const QString &name, const QString &address);
void editEntry();
void removeEntry();
@@ -86,7 +86,6 @@ private:
TableModel *table;
NewAddressTab *newAddressTab;
- QSortFilterProxyModel *proxyModel;
};
//! [0]
diff --git a/examples/widgets/itemviews/addressbook/mainwindow.cpp b/examples/widgets/itemviews/addressbook/mainwindow.cpp
index 6d8b15b032..42966de375 100644
--- a/examples/widgets/itemviews/addressbook/mainwindow.cpp
+++ b/examples/widgets/itemviews/addressbook/mainwindow.cpp
@@ -56,8 +56,9 @@
//! [0]
MainWindow::MainWindow()
+ : QMainWindow(),
+ addressWidget(new AddressWidget)
{
- addressWidget = new AddressWidget;
setCentralWidget(addressWidget);
createMenus();
setWindowTitle(tr("Address Book"));
@@ -67,28 +68,29 @@ MainWindow::MainWindow()
//! [1a]
void MainWindow::createMenus()
{
- fileMenu = menuBar()->addMenu(tr("&File"));
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
- openAct = new QAction(tr("&Open..."), this);
+ QAction *openAct = new QAction(tr("&Open..."), this);
fileMenu->addAction(openAct);
connect(openAct, &QAction::triggered, this, &MainWindow::openFile);
//! [1a]
- saveAct = new QAction(tr("&Save As..."), this);
+ QAction *saveAct = new QAction(tr("&Save As..."), this);
fileMenu->addAction(saveAct);
connect(saveAct, &QAction::triggered, this, &MainWindow::saveFile);
fileMenu->addSeparator();
- exitAct = new QAction(tr("E&xit"), this);
+ QAction *exitAct = new QAction(tr("E&xit"), this);
fileMenu->addAction(exitAct);
connect(exitAct, &QAction::triggered, this, &QWidget::close);
- toolMenu = menuBar()->addMenu(tr("&Tools"));
+ QMenu *toolMenu = menuBar()->addMenu(tr("&Tools"));
- addAct = new QAction(tr("&Add Entry..."), this);
+ QAction *addAct = new QAction(tr("&Add Entry..."), this);
toolMenu->addAction(addAct);
- connect(addAct, &QAction::triggered, addressWidget, &AddressWidget::showAddEntryDialog);
+ connect(addAct, &QAction::triggered,
+ addressWidget, &AddressWidget::showAddEntryDialog);
//! [1b]
editAct = new QAction(tr("&Edit Entry..."), this);
diff --git a/examples/widgets/itemviews/addressbook/mainwindow.h b/examples/widgets/itemviews/addressbook/mainwindow.h
index 3d323e5799..fca5934e68 100644
--- a/examples/widgets/itemviews/addressbook/mainwindow.h
+++ b/examples/widgets/itemviews/addressbook/mainwindow.h
@@ -72,12 +72,6 @@ private:
void createMenus();
AddressWidget *addressWidget;
- QMenu *fileMenu;
- QMenu *toolMenu;
- QAction *openAct;
- QAction *saveAct;
- QAction *exitAct;
- QAction *addAct;
QAction *editAct;
QAction *removeAct;
};
diff --git a/examples/widgets/itemviews/addressbook/newaddresstab.cpp b/examples/widgets/itemviews/addressbook/newaddresstab.cpp
index f0a7369796..ef725d723f 100644
--- a/examples/widgets/itemviews/addressbook/newaddresstab.cpp
+++ b/examples/widgets/itemviews/addressbook/newaddresstab.cpp
@@ -48,24 +48,23 @@
**
****************************************************************************/
-#include "adddialog.h"
#include "newaddresstab.h"
+#include "adddialog.h"
#include <QtWidgets>
//! [0]
NewAddressTab::NewAddressTab(QWidget *parent)
+ : QWidget(parent)
{
- Q_UNUSED(parent);
+ auto descriptionLabel = new QLabel(tr("There are currently no contacts in your address book. "
+ "\nClick Add to add new contacts."));
- descriptionLabel = new QLabel(tr("There are currently no contacts in your address book. "
- "\nClick Add to add new contacts."));
-
- addButton = new QPushButton(tr("Add"));
+ auto addButton = new QPushButton(tr("Add"));
connect(addButton, &QAbstractButton::clicked, this, &NewAddressTab::addEntry);
- mainLayout = new QVBoxLayout;
+ auto mainLayout = new QVBoxLayout;
mainLayout->addWidget(descriptionLabel);
mainLayout->addWidget(addButton, 0, Qt::AlignCenter);
@@ -78,11 +77,7 @@ void NewAddressTab::addEntry()
{
AddDialog aDialog;
- if (aDialog.exec()) {
- QString name = aDialog.nameText->text();
- QString address = aDialog.addressText->toPlainText();
-
- emit sendDetails(name, address);
- }
+ if (aDialog.exec())
+ emit sendDetails(aDialog.name(), aDialog.address());
}
//! [1]
diff --git a/examples/widgets/itemviews/addressbook/newaddresstab.h b/examples/widgets/itemviews/addressbook/newaddresstab.h
index 05c7a8dada..6a147e3c7c 100644
--- a/examples/widgets/itemviews/addressbook/newaddresstab.h
+++ b/examples/widgets/itemviews/addressbook/newaddresstab.h
@@ -65,19 +65,13 @@ class NewAddressTab : public QWidget
Q_OBJECT
public:
- NewAddressTab(QWidget *parent = 0);
+ NewAddressTab(QWidget *parent = nullptr);
public slots:
void addEntry();
signals:
- void sendDetails(QString name, QString address);
-
-private:
- QLabel *descriptionLabel;
- QPushButton *addButton;
- QVBoxLayout *mainLayout;
-
+ void sendDetails(const QString &name, const QString &address);
};
//! [0]
diff --git a/examples/widgets/itemviews/addressbook/tablemodel.cpp b/examples/widgets/itemviews/addressbook/tablemodel.cpp
index b3704f857e..ddf79a3fa3 100644
--- a/examples/widgets/itemviews/addressbook/tablemodel.cpp
+++ b/examples/widgets/itemviews/addressbook/tablemodel.cpp
@@ -56,9 +56,9 @@ TableModel::TableModel(QObject *parent)
{
}
-TableModel::TableModel(QList<Contact> contacts, QObject *parent)
- : QAbstractTableModel(parent)
- , contacts(contacts)
+TableModel::TableModel(const QVector<Contact> &contacts, QObject *parent)
+ : QAbstractTableModel(parent),
+ contacts(contacts)
{
}
//! [0]
@@ -66,14 +66,12 @@ TableModel::TableModel(QList<Contact> contacts, QObject *parent)
//! [1]
int TableModel::rowCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
- return contacts.size();
+ return parent.isValid() ? 0 : contacts.size();
}
int TableModel::columnCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
- return 2;
+ return parent.isValid() ? 0 : 2;
}
//! [1]
@@ -89,10 +87,14 @@ QVariant TableModel::data(const QModelIndex &index, int role) const
if (role == Qt::DisplayRole) {
const auto &contact = contacts.at(index.row());
- if (index.column() == 0)
- return contact.name;
- else if (index.column() == 1)
- return contact.address;
+ switch (index.column()) {
+ case 0:
+ return contact.name;
+ case 1:
+ return contact.address;
+ default:
+ break;
+ }
}
return QVariant();
}
@@ -108,12 +110,10 @@ QVariant TableModel::headerData(int section, Qt::Orientation orientation, int ro
switch (section) {
case 0:
return tr("Name");
-
case 1:
return tr("Address");
-
default:
- return QVariant();
+ break;
}
}
return QVariant();
@@ -152,19 +152,21 @@ bool TableModel::removeRows(int position, int rows, const QModelIndex &index)
bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::EditRole) {
- int row = index.row();
-
+ const int row = index.row();
auto contact = contacts.value(row);
- if (index.column() == 0)
- contact.name = value.toString();
- else if (index.column() == 1)
- contact.address = value.toString();
- else
- return false;
-
+ switch (index.column()) {
+ case 0:
+ contact.name = value.toString();
+ break;
+ case 1:
+ contact.address = value.toString();
+ break;
+ default:
+ return false;
+ }
contacts.replace(row, contact);
- emit dataChanged(index, index, {role});
+ emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
return true;
}
@@ -184,7 +186,7 @@ Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
//! [7]
//! [8]
-QList<Contact> TableModel::getContacts() const
+const QVector<Contact> &TableModel::getContacts() const
{
return contacts;
}
diff --git a/examples/widgets/itemviews/addressbook/tablemodel.h b/examples/widgets/itemviews/addressbook/tablemodel.h
index 1004a35d31..e4025fc734 100644
--- a/examples/widgets/itemviews/addressbook/tablemodel.h
+++ b/examples/widgets/itemviews/addressbook/tablemodel.h
@@ -52,7 +52,7 @@
#define TABLEMODEL_H
#include <QAbstractTableModel>
-#include <QList>
+#include <QVector>
//! [0]
@@ -82,8 +82,8 @@ class TableModel : public QAbstractTableModel
Q_OBJECT
public:
- TableModel(QObject *parent = 0);
- TableModel(QList<Contact> contacts, QObject *parent = 0);
+ TableModel(QObject *parent = nullptr);
+ TableModel(const QVector<Contact> &contacts, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
@@ -93,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<Contact> getContacts() const;
+ const QVector<Contact> &getContacts() const;
private:
- QList<Contact> contacts;
+ QVector<Contact> contacts;
};
//! [0]
diff --git a/examples/widgets/itemviews/coloreditorfactory/colorlisteditor.cpp b/examples/widgets/itemviews/coloreditorfactory/colorlisteditor.cpp
index 75d809a44f..0b65c53477 100644
--- a/examples/widgets/itemviews/coloreditorfactory/colorlisteditor.cpp
+++ b/examples/widgets/itemviews/coloreditorfactory/colorlisteditor.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "colorlisteditor.h"
+#include <QtWidgets>
+
ColorListEditor::ColorListEditor(QWidget *widget) : QComboBox(widget)
{
populateList();
@@ -65,16 +65,16 @@ QColor ColorListEditor::color() const
//! [0]
//! [1]
-void ColorListEditor::setColor(QColor color)
+void ColorListEditor::setColor(const QColor &color)
{
- setCurrentIndex(findData(color, int(Qt::DecorationRole)));
+ setCurrentIndex(findData(color, Qt::DecorationRole));
}
//! [1]
//! [2]
void ColorListEditor::populateList()
{
- QStringList colorNames = QColor::colorNames();
+ const QStringList colorNames = QColor::colorNames();
for (int i = 0; i < colorNames.size(); ++i) {
QColor color(colorNames[i]);
diff --git a/examples/widgets/itemviews/coloreditorfactory/colorlisteditor.h b/examples/widgets/itemviews/coloreditorfactory/colorlisteditor.h
index f284c07c89..f9d736d298 100644
--- a/examples/widgets/itemviews/coloreditorfactory/colorlisteditor.h
+++ b/examples/widgets/itemviews/coloreditorfactory/colorlisteditor.h
@@ -65,11 +65,11 @@ class ColorListEditor : public QComboBox
Q_PROPERTY(QColor color READ color WRITE setColor USER true)
public:
- ColorListEditor(QWidget *widget = 0);
+ ColorListEditor(QWidget *widget = nullptr);
public:
QColor color() const;
- void setColor(QColor c);
+ void setColor(const QColor &color);
private:
void populateList();
diff --git a/examples/widgets/itemviews/coloreditorfactory/window.cpp b/examples/widgets/itemviews/coloreditorfactory/window.cpp
index f7ce821d31..e4a9379d8f 100644
--- a/examples/widgets/itemviews/coloreditorfactory/window.cpp
+++ b/examples/widgets/itemviews/coloreditorfactory/window.cpp
@@ -48,11 +48,11 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "window.h"
#include "colorlisteditor.h"
+#include <QtWidgets>
+
//! [0]
Window::Window()
{
@@ -71,19 +71,18 @@ Window::Window()
void Window::createGUI()
{
- QList<QPair<QString, QColor> > list;
- list << QPair<QString, QColor>(tr("Alice"), QColor("aliceblue")) <<
- QPair<QString, QColor>(tr("Neptun"), QColor("aquamarine")) <<
- QPair<QString, QColor>(tr("Ferdinand"), QColor("springgreen"));
+ const QVector<QPair<QString, QColor> > list =
+ {{ tr("Alice"), QColor("aliceblue") },
+ { tr("Neptun"), QColor("aquamarine") },
+ { tr("Ferdinand"), QColor("springgreen") }};
QTableWidget *table = new QTableWidget(3, 2);
- table->setHorizontalHeaderLabels(QStringList() << tr("Name")
- << tr("Hair Color"));
+ table->setHorizontalHeaderLabels({ tr("Name"), tr("Hair Color") });
table->verticalHeader()->setVisible(false);
table->resize(150, 50);
for (int i = 0; i < 3; ++i) {
- QPair<QString, QColor> pair = list.at(i);
+ const QPair<QString, QColor> &pair = list.at(i);
QTableWidgetItem *nameItem = new QTableWidgetItem(pair.first);
QTableWidgetItem *colorItem = new QTableWidgetItem;
diff --git a/examples/widgets/itemviews/customsortfiltermodel/filterwidget.cpp b/examples/widgets/itemviews/customsortfiltermodel/filterwidget.cpp
index 74d88caae6..302042a6b3 100644
--- a/examples/widgets/itemviews/customsortfiltermodel/filterwidget.cpp
+++ b/examples/widgets/itemviews/customsortfiltermodel/filterwidget.cpp
@@ -52,13 +52,11 @@
#include <QIcon>
#include <QPixmap>
-#include <QImage>
#include <QMenu>
#include <QAction>
#include <QActionGroup>
#include <QToolButton>
#include <QWidgetAction>
-#include <QDebug>
FilterWidget::FilterWidget(QWidget *parent)
: QLineEdit(parent)
@@ -127,7 +125,8 @@ QRegExp::PatternSyntax FilterWidget::patternSyntax() const
void FilterWidget::setPatternSyntax(QRegExp::PatternSyntax s)
{
- foreach (QAction *a, m_patternGroup->actions()) {
+ const QList<QAction*> actions = m_patternGroup->actions();
+ for (QAction *a : actions) {
if (patternSyntaxFromAction(a) == s) {
a->setChecked(true);
break;
diff --git a/examples/widgets/itemviews/customsortfiltermodel/filterwidget.h b/examples/widgets/itemviews/customsortfiltermodel/filterwidget.h
index ea12954e52..70214b862e 100644
--- a/examples/widgets/itemviews/customsortfiltermodel/filterwidget.h
+++ b/examples/widgets/itemviews/customsortfiltermodel/filterwidget.h
@@ -67,7 +67,7 @@ class FilterWidget : public QLineEdit
Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE setCaseSensitivity)
Q_PROPERTY(QRegExp::PatternSyntax patternSyntax READ patternSyntax WRITE setPatternSyntax)
public:
- explicit FilterWidget(QWidget *parent = 0);
+ explicit FilterWidget(QWidget *parent = nullptr);
Qt::CaseSensitivity caseSensitivity() const;
void setCaseSensitivity(Qt::CaseSensitivity);
diff --git a/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp b/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp
index 35426657d9..4753d04d9b 100644
--- a/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp
+++ b/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "mysortfilterproxymodel.h"
+#include <QtWidgets>
+
//! [0]
MySortFilterProxyModel::MySortFilterProxyModel(QObject *parent)
: QSortFilterProxyModel(parent)
@@ -77,7 +77,7 @@ void MySortFilterProxyModel::setFilterMaximumDate(const QDate &date)
//! [3]
bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow,
- const QModelIndex &sourceParent) const
+ const QModelIndex &sourceParent) const
{
QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent);
diff --git a/examples/widgets/itemviews/customsortfiltermodel/window.cpp b/examples/widgets/itemviews/customsortfiltermodel/window.cpp
index bfd2350da0..3356c971ad 100644
--- a/examples/widgets/itemviews/customsortfiltermodel/window.cpp
+++ b/examples/widgets/itemviews/customsortfiltermodel/window.cpp
@@ -48,12 +48,12 @@
**
****************************************************************************/
-#include <QtWidgets>
-
-#include "mysortfilterproxymodel.h"
#include "window.h"
+#include "mysortfilterproxymodel.h"
#include "filterwidget.h"
+#include <QtWidgets>
+
//! [0]
Window::Window()
{
@@ -75,7 +75,7 @@ Window::Window()
//! [3]
filterWidget = new FilterWidget;
- filterWidget->setText("Grace|Sports");
+ filterWidget->setText(tr("Grace|Sports"));
connect(filterWidget, &FilterWidget::filterChanged, this, &Window::textFilterChanged);
filterPatternLabel = new QLabel(tr("&Filter pattern:"));
@@ -137,6 +137,11 @@ void Window::setSourceModel(QAbstractItemModel *model)
{
proxyModel->setSourceModel(model);
sourceView->setModel(model);
+
+ for (int i = 0; i < proxyModel->columnCount(); ++i)
+ proxyView->resizeColumnToContents(i);
+ for (int i = 0; i < model->columnCount(); ++i)
+ sourceView->resizeColumnToContents(i);
}
//! [7]
diff --git a/examples/widgets/itemviews/editabletreemodel/main.cpp b/examples/widgets/itemviews/editabletreemodel/main.cpp
index 80f6842730..5e9ff214a3 100644
--- a/examples/widgets/itemviews/editabletreemodel/main.cpp
+++ b/examples/widgets/itemviews/editabletreemodel/main.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QApplication>
-
#include "mainwindow.h"
+#include <QApplication>
+
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(editabletreemodel);
diff --git a/examples/widgets/itemviews/editabletreemodel/mainwindow.cpp b/examples/widgets/itemviews/editabletreemodel/mainwindow.cpp
index 0c54d8930f..7faa325469 100644
--- a/examples/widgets/itemviews/editabletreemodel/mainwindow.cpp
+++ b/examples/widgets/itemviews/editabletreemodel/mainwindow.cpp
@@ -58,8 +58,7 @@ MainWindow::MainWindow(QWidget *parent)
{
setupUi(this);
- QStringList headers;
- headers << tr("Title") << tr("Description");
+ const QStringList headers({tr("Title"), tr("Description")});
QFile file(":/default.txt");
file.open(QIODevice::ReadOnly);
@@ -87,7 +86,7 @@ MainWindow::MainWindow(QWidget *parent)
void MainWindow::insertChild()
{
- QModelIndex index = view->selectionModel()->currentIndex();
+ const QModelIndex index = view->selectionModel()->currentIndex();
QAbstractItemModel *model = view->model();
if (model->columnCount(index) == 0) {
@@ -99,10 +98,10 @@ void MainWindow::insertChild()
return;
for (int column = 0; column < model->columnCount(index); ++column) {
- QModelIndex child = model->index(0, column, index);
- model->setData(child, QVariant("[No data]"), Qt::EditRole);
+ const QModelIndex child = model->index(0, column, index);
+ model->setData(child, QVariant(tr("[No data]")), Qt::EditRole);
if (!model->headerData(column, Qt::Horizontal).isValid())
- model->setHeaderData(column, Qt::Horizontal, QVariant("[No header]"), Qt::EditRole);
+ model->setHeaderData(column, Qt::Horizontal, QVariant(tr("[No header]")), Qt::EditRole);
}
view->selectionModel()->setCurrentIndex(model->index(0, 0, index),
@@ -127,7 +126,7 @@ bool MainWindow::insertColumn()
void MainWindow::insertRow()
{
- QModelIndex index = view->selectionModel()->currentIndex();
+ const QModelIndex index = view->selectionModel()->currentIndex();
QAbstractItemModel *model = view->model();
if (!model->insertRow(index.row()+1, index.parent()))
@@ -136,19 +135,18 @@ void MainWindow::insertRow()
updateActions();
for (int column = 0; column < model->columnCount(index.parent()); ++column) {
- QModelIndex child = model->index(index.row()+1, column, index.parent());
- model->setData(child, QVariant("[No data]"), Qt::EditRole);
+ const QModelIndex child = model->index(index.row() + 1, column, index.parent());
+ model->setData(child, QVariant(tr("[No data]")), Qt::EditRole);
}
}
bool MainWindow::removeColumn()
{
QAbstractItemModel *model = view->model();
- int column = view->selectionModel()->currentIndex().column();
+ const int column = view->selectionModel()->currentIndex().column();
// Insert columns in each child of the parent item.
- bool changed = model->removeColumn(column);
-
+ const bool changed = model->removeColumn(column);
if (changed)
updateActions();
@@ -157,7 +155,7 @@ bool MainWindow::removeColumn()
void MainWindow::removeRow()
{
- QModelIndex index = view->selectionModel()->currentIndex();
+ const QModelIndex index = view->selectionModel()->currentIndex();
QAbstractItemModel *model = view->model();
if (model->removeRow(index.row(), index.parent()))
updateActions();
@@ -165,19 +163,19 @@ void MainWindow::removeRow()
void MainWindow::updateActions()
{
- bool hasSelection = !view->selectionModel()->selection().isEmpty();
+ const bool hasSelection = !view->selectionModel()->selection().isEmpty();
removeRowAction->setEnabled(hasSelection);
removeColumnAction->setEnabled(hasSelection);
- bool hasCurrent = view->selectionModel()->currentIndex().isValid();
+ const bool hasCurrent = view->selectionModel()->currentIndex().isValid();
insertRowAction->setEnabled(hasCurrent);
insertColumnAction->setEnabled(hasCurrent);
if (hasCurrent) {
view->closePersistentEditor(view->selectionModel()->currentIndex());
- int row = view->selectionModel()->currentIndex().row();
- int column = view->selectionModel()->currentIndex().column();
+ const int row = view->selectionModel()->currentIndex().row();
+ const int column = view->selectionModel()->currentIndex().column();
if (view->selectionModel()->currentIndex().parent().isValid())
statusBar()->showMessage(tr("Position: (%1,%2)").arg(row).arg(column));
else
diff --git a/examples/widgets/itemviews/editabletreemodel/mainwindow.h b/examples/widgets/itemviews/editabletreemodel/mainwindow.h
index dbc745e25d..314b0cb1fa 100644
--- a/examples/widgets/itemviews/editabletreemodel/mainwindow.h
+++ b/examples/widgets/itemviews/editabletreemodel/mainwindow.h
@@ -54,14 +54,13 @@
#include "ui_mainwindow.h"
#include <QMainWindow>
-#include <QModelIndex>
class MainWindow : public QMainWindow, private Ui::MainWindow
{
Q_OBJECT
public:
- MainWindow(QWidget *parent = 0);
+ MainWindow(QWidget *parent = nullptr);
public slots:
void updateActions();
diff --git a/examples/widgets/itemviews/editabletreemodel/treeitem.cpp b/examples/widgets/itemviews/editabletreemodel/treeitem.cpp
index 8fbe86ad1e..027a5f8849 100644
--- a/examples/widgets/itemviews/editabletreemodel/treeitem.cpp
+++ b/examples/widgets/itemviews/editabletreemodel/treeitem.cpp
@@ -56,14 +56,11 @@
#include "treeitem.h"
-#include <QStringList>
-
//! [0]
TreeItem::TreeItem(const QVector<QVariant> &data, TreeItem *parent)
-{
- parentItem = parent;
- itemData = data;
-}
+ : itemData(data),
+ parentItem(parent)
+{}
//! [0]
//! [1]
@@ -76,7 +73,9 @@ TreeItem::~TreeItem()
//! [2]
TreeItem *TreeItem::child(int number)
{
- return childItems.value(number);
+ if (number < 0 || number >= childItems.size())
+ return nullptr;
+ return childItems.at(number);
}
//! [2]
@@ -92,7 +91,6 @@ int TreeItem::childNumber() const
{
if (parentItem)
return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
-
return 0;
}
//! [4]
@@ -107,7 +105,9 @@ int TreeItem::columnCount() const
//! [6]
QVariant TreeItem::data(int column) const
{
- return itemData.value(column);
+ if (column < 0 || column >= itemData.size())
+ return QVariant();
+ return itemData.at(column);
}
//! [6]
@@ -136,7 +136,7 @@ bool TreeItem::insertColumns(int position, int columns)
for (int column = 0; column < columns; ++column)
itemData.insert(position, QVariant());
- foreach (TreeItem *child, childItems)
+ for (TreeItem *child : qAsConst(childItems))
child->insertColumns(position, columns);
return true;
@@ -171,7 +171,7 @@ bool TreeItem::removeColumns(int position, int columns)
for (int column = 0; column < columns; ++column)
itemData.remove(position);
- foreach (TreeItem *child, childItems)
+ for (TreeItem *child : qAsConst(childItems))
child->removeColumns(position, columns);
return true;
diff --git a/examples/widgets/itemviews/editabletreemodel/treeitem.h b/examples/widgets/itemviews/editabletreemodel/treeitem.h
index fd65f12268..867be5f380 100644
--- a/examples/widgets/itemviews/editabletreemodel/treeitem.h
+++ b/examples/widgets/itemviews/editabletreemodel/treeitem.h
@@ -51,7 +51,6 @@
#ifndef TREEITEM_H
#define TREEITEM_H
-#include <QList>
#include <QVariant>
#include <QVector>
@@ -59,7 +58,7 @@
class TreeItem
{
public:
- explicit TreeItem(const QVector<QVariant> &data, TreeItem *parent = 0);
+ explicit TreeItem(const QVector<QVariant> &data, TreeItem *parent = nullptr);
~TreeItem();
TreeItem *child(int number);
@@ -75,7 +74,7 @@ public:
bool setData(int column, const QVariant &value);
private:
- QList<TreeItem*> childItems;
+ QVector<TreeItem*> childItems;
QVector<QVariant> itemData;
TreeItem *parentItem;
};
diff --git a/examples/widgets/itemviews/editabletreemodel/treemodel.cpp b/examples/widgets/itemviews/editabletreemodel/treemodel.cpp
index 72818372d7..836c2e8651 100644
--- a/examples/widgets/itemviews/editabletreemodel/treemodel.cpp
+++ b/examples/widgets/itemviews/editabletreemodel/treemodel.cpp
@@ -48,21 +48,21 @@
**
****************************************************************************/
-#include <QtWidgets>
-
-#include "treeitem.h"
#include "treemodel.h"
+#include "treeitem.h"
+
+#include <QtWidgets>
//! [0]
TreeModel::TreeModel(const QStringList &headers, const QString &data, QObject *parent)
: QAbstractItemModel(parent)
{
QVector<QVariant> rootData;
- foreach (QString header, headers)
+ for (const QString &header : headers)
rootData << header;
rootItem = new TreeItem(rootData);
- setupModelData(data.split(QString("\n")), rootItem);
+ setupModelData(data.split('\n'), rootItem);
}
//! [0]
@@ -74,8 +74,9 @@ TreeModel::~TreeModel()
//! [1]
//! [2]
-int TreeModel::columnCount(const QModelIndex & /* parent */) const
+int TreeModel::columnCount(const QModelIndex &parent) const
{
+ Q_UNUSED(parent);
return rootItem->columnCount();
}
//! [2]
@@ -97,7 +98,7 @@ QVariant TreeModel::data(const QModelIndex &index, int role) const
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
- return 0;
+ return Qt::NoItemFlags;
return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
}
@@ -133,21 +134,20 @@ QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) con
//! [6]
TreeItem *parentItem = getItem(parent);
+ if (!parentItem)
+ return QModelIndex();
TreeItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
- else
- return QModelIndex();
+ return QModelIndex();
}
//! [6]
bool TreeModel::insertColumns(int position, int columns, const QModelIndex &parent)
{
- bool success;
-
beginInsertColumns(parent, position, position + columns - 1);
- success = rootItem->insertColumns(position, columns);
+ const bool success = rootItem->insertColumns(position, columns);
endInsertColumns();
return success;
@@ -156,10 +156,13 @@ bool TreeModel::insertColumns(int position, int columns, const QModelIndex &pare
bool TreeModel::insertRows(int position, int rows, const QModelIndex &parent)
{
TreeItem *parentItem = getItem(parent);
- bool success;
+ if (!parentItem)
+ return false;
beginInsertRows(parent, position, position + rows - 1);
- success = parentItem->insertChildren(position, rows, rootItem->columnCount());
+ const bool success = parentItem->insertChildren(position,
+ rows,
+ rootItem->columnCount());
endInsertRows();
return success;
@@ -172,9 +175,9 @@ QModelIndex TreeModel::parent(const QModelIndex &index) const
return QModelIndex();
TreeItem *childItem = getItem(index);
- TreeItem *parentItem = childItem->parent();
+ TreeItem *parentItem = childItem ? childItem->parent() : nullptr;
- if (parentItem == rootItem)
+ if (parentItem == rootItem || !parentItem)
return QModelIndex();
return createIndex(parentItem->childNumber(), 0, parentItem);
@@ -183,10 +186,8 @@ QModelIndex TreeModel::parent(const QModelIndex &index) const
bool TreeModel::removeColumns(int position, int columns, const QModelIndex &parent)
{
- bool success;
-
beginRemoveColumns(parent, position, position + columns - 1);
- success = rootItem->removeColumns(position, columns);
+ const bool success = rootItem->removeColumns(position, columns);
endRemoveColumns();
if (rootItem->columnCount() == 0)
@@ -198,10 +199,11 @@ bool TreeModel::removeColumns(int position, int columns, const QModelIndex &pare
bool TreeModel::removeRows(int position, int rows, const QModelIndex &parent)
{
TreeItem *parentItem = getItem(parent);
- bool success = true;
+ if (!parentItem)
+ return false;
beginRemoveRows(parent, position, position + rows - 1);
- success = parentItem->removeChildren(position, rows);
+ const bool success = parentItem->removeChildren(position, rows);
endRemoveRows();
return success;
@@ -210,9 +212,9 @@ bool TreeModel::removeRows(int position, int rows, const QModelIndex &parent)
//! [8]
int TreeModel::rowCount(const QModelIndex &parent) const
{
- TreeItem *parentItem = getItem(parent);
+ const TreeItem *parentItem = getItem(parent);
- return parentItem->childCount();
+ return parentItem ? parentItem->childCount() : 0;
}
//! [8]
@@ -225,7 +227,7 @@ bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int rol
bool result = item->setData(index.column(), value);
if (result)
- emit dataChanged(index, index, {role});
+ emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
return result;
}
@@ -236,7 +238,7 @@ bool TreeModel::setHeaderData(int section, Qt::Orientation orientation,
if (role != Qt::EditRole || orientation != Qt::Horizontal)
return false;
- bool result = rootItem->setData(section, value);
+ const bool result = rootItem->setData(section, value);
if (result)
emit headerDataChanged(orientation, section, section);
@@ -246,8 +248,8 @@ bool TreeModel::setHeaderData(int section, Qt::Orientation orientation,
void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
{
- QList<TreeItem*> parents;
- QList<int> indentations;
+ QVector<TreeItem*> parents;
+ QVector<int> indentations;
parents << parent;
indentations << 0;
@@ -261,14 +263,15 @@ void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
++position;
}
- QString lineData = lines[number].mid(position).trimmed();
+ const QString lineData = lines[number].mid(position).trimmed();
if (!lineData.isEmpty()) {
// Read the column data from the rest of the line.
- QStringList columnStrings = lineData.split("\t", QString::SkipEmptyParts);
+ const QStringList columnStrings = lineData.split('\t', QString::SkipEmptyParts);
QVector<QVariant> columnData;
- for (int column = 0; column < columnStrings.count(); ++column)
- columnData << columnStrings[column];
+ columnData.reserve(columnStrings.size());
+ for (const QString &columnString : columnStrings)
+ columnData << columnString;
if (position > indentations.last()) {
// The last child of the current parent is now the new parent
@@ -291,7 +294,6 @@ void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
for (int column = 0; column < columnData.size(); ++column)
parent->child(parent->childCount() - 1)->setData(column, columnData[column]);
}
-
++number;
}
}
diff --git a/examples/widgets/itemviews/editabletreemodel/treemodel.h b/examples/widgets/itemviews/editabletreemodel/treemodel.h
index d76d138831..8419f9cb9d 100644
--- a/examples/widgets/itemviews/editabletreemodel/treemodel.h
+++ b/examples/widgets/itemviews/editabletreemodel/treemodel.h
@@ -64,7 +64,7 @@ class TreeModel : public QAbstractItemModel
public:
TreeModel(const QStringList &headers, const QString &data,
- QObject *parent = 0);
+ QObject *parent = nullptr);
~TreeModel();
//! [0] //! [1]
diff --git a/examples/widgets/itemviews/fetchmore/filelistmodel.cpp b/examples/widgets/itemviews/fetchmore/filelistmodel.cpp
index 086d45eca3..3ee80617c0 100644
--- a/examples/widgets/itemviews/fetchmore/filelistmodel.cpp
+++ b/examples/widgets/itemviews/fetchmore/filelistmodel.cpp
@@ -50,20 +50,18 @@
#include "filelistmodel.h"
-#include <QApplication>
-#include <QBrush>
+#include <QGuiApplication>
#include <QDir>
#include <QPalette>
FileListModel::FileListModel(QObject *parent)
- : QAbstractListModel(parent)
-{
-}
+ : QAbstractListModel(parent), fileCount(0)
+{}
//![4]
-int FileListModel::rowCount(const QModelIndex & /* parent */) const
+int FileListModel::rowCount(const QModelIndex &parent) const
{
- return fileCount;
+ return parent.isValid() ? 0 : fileCount;
}
QVariant FileListModel::data(const QModelIndex &index, int role) const
@@ -88,25 +86,26 @@ QVariant FileListModel::data(const QModelIndex &index, int role) const
//![4]
//![1]
-bool FileListModel::canFetchMore(const QModelIndex & /* index */) const
+bool FileListModel::canFetchMore(const QModelIndex &parent) const
{
- if (fileCount < fileList.size())
- return true;
- else
+ if (parent.isValid())
return false;
+ return (fileCount < fileList.size());
}
//![1]
//![2]
-void FileListModel::fetchMore(const QModelIndex & /* index */)
+void FileListModel::fetchMore(const QModelIndex &parent)
{
+ if (parent.isValid())
+ return;
int remainder = fileList.size() - fileCount;
int itemsToFetch = qMin(100, remainder);
if (itemsToFetch <= 0)
return;
- beginInsertRows(QModelIndex(), fileCount, fileCount+itemsToFetch-1);
+ beginInsertRows(QModelIndex(), fileCount, fileCount + itemsToFetch - 1);
fileCount += itemsToFetch;
diff --git a/examples/widgets/itemviews/fetchmore/filelistmodel.h b/examples/widgets/itemviews/fetchmore/filelistmodel.h
index 9251eaf959..35cf6f7b46 100644
--- a/examples/widgets/itemviews/fetchmore/filelistmodel.h
+++ b/examples/widgets/itemviews/fetchmore/filelistmodel.h
@@ -52,7 +52,6 @@
#define FILELISTMODEL_H
#include <QAbstractListModel>
-#include <QList>
#include <QStringList>
//![0]
@@ -61,7 +60,7 @@ class FileListModel : public QAbstractListModel
Q_OBJECT
public:
- FileListModel(QObject *parent = 0);
+ FileListModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
diff --git a/examples/widgets/itemviews/fetchmore/window.cpp b/examples/widgets/itemviews/fetchmore/window.cpp
index 886f76d6ab..d71ac7059d 100644
--- a/examples/widgets/itemviews/fetchmore/window.cpp
+++ b/examples/widgets/itemviews/fetchmore/window.cpp
@@ -48,8 +48,8 @@
**
****************************************************************************/
-#include "filelistmodel.h"
#include "window.h"
+#include "filelistmodel.h"
#include <QtWidgets>
@@ -66,7 +66,7 @@ Window::Window(QWidget *parent)
QListView *view = new QListView;
view->setModel(model);
- logViewer = new QTextBrowser;
+ logViewer = new QTextBrowser(this);
logViewer->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
connect(lineEdit, &QLineEdit::textChanged,
diff --git a/examples/widgets/itemviews/fetchmore/window.h b/examples/widgets/itemviews/fetchmore/window.h
index f234683785..61bcb94bde 100644
--- a/examples/widgets/itemviews/fetchmore/window.h
+++ b/examples/widgets/itemviews/fetchmore/window.h
@@ -62,7 +62,7 @@ class Window : public QWidget
Q_OBJECT
public:
- Window(QWidget *parent = 0);
+ Window(QWidget *parent = nullptr);
public slots:
void updateLog(int number);
diff --git a/examples/widgets/itemviews/interview/model.cpp b/examples/widgets/itemviews/interview/model.cpp
index a8f3a6f31e..feaf8bb98c 100644
--- a/examples/widgets/itemviews/interview/model.cpp
+++ b/examples/widgets/itemviews/interview/model.cpp
@@ -50,14 +50,13 @@
#include "model.h"
-#include <QIcon>
#include <QPixmap>
Model::Model(int rows, int columns, QObject *parent)
: QAbstractItemModel(parent),
services(QPixmap(":/images/services.png")),
rc(rows), cc(columns),
- tree(new QVector<Node>(rows, Node(0)))
+ tree(new QVector<Node>(rows, Node()))
{
}
diff --git a/examples/widgets/itemviews/interview/model.h b/examples/widgets/itemviews/interview/model.h
index 969cf693b2..132f1d01aa 100644
--- a/examples/widgets/itemviews/interview/model.h
+++ b/examples/widgets/itemviews/interview/model.h
@@ -61,7 +61,7 @@ class Model : public QAbstractItemModel
Q_OBJECT
public:
- Model(int rows, int columns, QObject *parent = 0);
+ Model(int rows, int columns, QObject *parent = nullptr);
~Model();
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
@@ -80,7 +80,7 @@ private:
struct Node
{
- Node(Node *parent = 0) : parent(parent), children(0) {}
+ Node(Node *parent = nullptr) : parent(parent), children(nullptr) {}
~Node() { delete children; }
Node *parent;
QVector<Node> *children;
diff --git a/examples/widgets/itemviews/pixelator/mainwindow.cpp b/examples/widgets/itemviews/pixelator/mainwindow.cpp
index 63617f0169..f6b67e4dba 100644
--- a/examples/widgets/itemviews/pixelator/mainwindow.cpp
+++ b/examples/widgets/itemviews/pixelator/mainwindow.cpp
@@ -48,8 +48,8 @@
**
****************************************************************************/
-#include "imagemodel.h"
#include "mainwindow.h"
+#include "imagemodel.h"
#include "pixeldelegate.h"
#include <QtWidgets>
diff --git a/examples/widgets/itemviews/pixelator/pixeldelegate.cpp b/examples/widgets/itemviews/pixelator/pixeldelegate.cpp
index ecf44c1224..dc8736c836 100644
--- a/examples/widgets/itemviews/pixelator/pixeldelegate.cpp
+++ b/examples/widgets/itemviews/pixelator/pixeldelegate.cpp
@@ -54,10 +54,8 @@
//! [0]
PixelDelegate::PixelDelegate(QObject *parent)
- : QAbstractItemDelegate(parent)
-{
- pixelSize = 12;
-}
+ : QAbstractItemDelegate(parent), pixelSize(12)
+{}
//! [0]
//! [1]
@@ -70,11 +68,11 @@ void PixelDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
//! [1]
//! [3]
- int size = qMin(option.rect.width(), option.rect.height());
+ const int size = qMin(option.rect.width(), option.rect.height());
//! [3] //! [4]
- int brightness = index.model()->data(index, Qt::DisplayRole).toInt();
- double radius = (size / 2.0) - (brightness / 255.0 * size / 2.0);
- if (radius == 0.0)
+ const int brightness = index.model()->data(index, Qt::DisplayRole).toInt();
+ const double radius = (size / 2.0) - (brightness / 255.0 * size / 2.0);
+ if (qFuzzyIsNull(radius))
return;
//! [4]
diff --git a/examples/widgets/itemviews/pixelator/pixeldelegate.h b/examples/widgets/itemviews/pixelator/pixeldelegate.h
index d968d9e8d2..9f52221a28 100644
--- a/examples/widgets/itemviews/pixelator/pixeldelegate.h
+++ b/examples/widgets/itemviews/pixelator/pixeldelegate.h
@@ -61,7 +61,7 @@ class QObject;
class QPainter;
QT_END_NAMESPACE
-static const int ItemSize = 256;
+static constexpr int ItemSize = 256;
//! [0]
class PixelDelegate : public QAbstractItemDelegate
@@ -69,13 +69,13 @@ class PixelDelegate : public QAbstractItemDelegate
Q_OBJECT
public:
- PixelDelegate(QObject *parent = 0);
+ PixelDelegate(QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option,
- const QModelIndex &index ) const override;
+ const QModelIndex &index) const override;
public slots:
void setPixelSize(int size);
diff --git a/examples/widgets/itemviews/puzzle/piecesmodel.cpp b/examples/widgets/itemviews/puzzle/piecesmodel.cpp
index 28b46836f4..a9c53ed2cd 100644
--- a/examples/widgets/itemviews/puzzle/piecesmodel.cpp
+++ b/examples/widgets/itemviews/puzzle/piecesmodel.cpp
@@ -134,7 +134,7 @@ QMimeData *PiecesModel::mimeData(const QModelIndexList &indexes) const
QDataStream stream(&encodedData, QIODevice::WriteOnly);
- foreach (QModelIndex index, indexes) {
+ for (const QModelIndex &index : indexes) {
if (index.isValid()) {
QPixmap pixmap = qvariant_cast<QPixmap>(data(index, Qt::UserRole));
QPoint location = data(index, Qt::UserRole+1).toPoint();
@@ -190,10 +190,7 @@ bool PiecesModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
int PiecesModel::rowCount(const QModelIndex &parent) const
{
- if (parent.isValid())
- return 0;
- else
- return pixmaps.size();
+ return parent.isValid() ? 0 : pixmaps.size();
}
Qt::DropActions PiecesModel::supportedDropActions() const
@@ -201,7 +198,7 @@ Qt::DropActions PiecesModel::supportedDropActions() const
return Qt::CopyAction | Qt::MoveAction;
}
-void PiecesModel::addPieces(const QPixmap& pixmap)
+void PiecesModel::addPieces(const QPixmap &pixmap)
{
if (!pixmaps.isEmpty()) {
beginRemoveRows(QModelIndex(), 0, pixmaps.size() - 1);
diff --git a/examples/widgets/itemviews/puzzle/piecesmodel.h b/examples/widgets/itemviews/puzzle/piecesmodel.h
index bd979f4c7e..2a96603707 100644
--- a/examples/widgets/itemviews/puzzle/piecesmodel.h
+++ b/examples/widgets/itemviews/puzzle/piecesmodel.h
@@ -52,10 +52,10 @@
#define PIECESLIST_H
#include <QAbstractListModel>
-#include <QList>
#include <QPixmap>
#include <QPoint>
#include <QStringList>
+#include <QVector>
QT_BEGIN_NAMESPACE
class QMimeData;
@@ -66,7 +66,7 @@ class PiecesModel : public QAbstractListModel
Q_OBJECT
public:
- explicit PiecesModel(int pieceSize, QObject *parent = 0);
+ explicit PiecesModel(int pieceSize, QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
@@ -80,11 +80,11 @@ public:
Qt::DropActions supportedDropActions() const override;
void addPiece(const QPixmap &pixmap, const QPoint &location);
- void addPieces(const QPixmap& pixmap);
+ void addPieces(const QPixmap &pixmap);
private:
- QList<QPoint> locations;
- QList<QPixmap> pixmaps;
+ QVector<QPoint> locations;
+ QVector<QPixmap> pixmaps;
int m_PieceSize;
};
diff --git a/examples/widgets/itemviews/puzzle/puzzlewidget.cpp b/examples/widgets/itemviews/puzzle/puzzlewidget.cpp
index 06968da80f..974a972306 100644
--- a/examples/widgets/itemviews/puzzle/puzzlewidget.cpp
+++ b/examples/widgets/itemviews/puzzle/puzzlewidget.cpp
@@ -169,7 +169,7 @@ void PuzzleWidget::mousePressEvent(QMouseEvent *event)
drag->setHotSpot(event->pos() - square.topLeft());
drag->setPixmap(piece.pixmap);
- if (drag->start(Qt::MoveAction) == Qt::IgnoreAction) {
+ if (drag->exec(Qt::MoveAction) == Qt::IgnoreAction) {
pieces.insert(found, piece);
update(targetSquare(event->pos()));
diff --git a/examples/widgets/itemviews/simpledommodel/domitem.cpp b/examples/widgets/itemviews/simpledommodel/domitem.cpp
index c8b35b2e0a..a2dc9530f0 100644
--- a/examples/widgets/itemviews/simpledommodel/domitem.cpp
+++ b/examples/widgets/itemviews/simpledommodel/domitem.cpp
@@ -53,23 +53,20 @@
#include <QtXml>
//! [0]
-DomItem::DomItem(QDomNode &node, int row, DomItem *parent)
-{
- domNode = node;
+DomItem::DomItem(const QDomNode &node, int row, DomItem *parent)
+ : domNode(node),
//! [0]
- // Record the item's location within its parent.
+ // Record the item's location within its parent.
//! [1]
- rowNumber = row;
- parentItem = parent;
-}
+ parentItem(parent),
+ rowNumber(row)
+{}
//! [1]
//! [2]
DomItem::~DomItem()
{
- QHash<int,DomItem*>::iterator it;
- for (it = childItems.begin(); it != childItems.end(); ++it)
- delete it.value();
+ qDeleteAll(childItems);
}
//! [2]
@@ -90,21 +87,22 @@ DomItem *DomItem::parent()
//! [5]
DomItem *DomItem::child(int i)
{
- if (childItems.contains(i))
- return childItems[i];
+ DomItem *childItem = childItems.value(i);
+ if (childItem)
+ return childItem;
+ // if child does not yet exist, create it
if (i >= 0 && i < domNode.childNodes().count()) {
QDomNode childNode = domNode.childNodes().item(i);
- DomItem *childItem = new DomItem(childNode, i, this);
+ childItem = new DomItem(childNode, i, this);
childItems[i] = childItem;
- return childItem;
}
- return 0;
+ return childItem;
}
//! [5]
//! [6]
-int DomItem::row()
+int DomItem::row() const
{
return rowNumber;
}
diff --git a/examples/widgets/itemviews/simpledommodel/domitem.h b/examples/widgets/itemviews/simpledommodel/domitem.h
index b5db16009c..4a74db5139 100644
--- a/examples/widgets/itemviews/simpledommodel/domitem.h
+++ b/examples/widgets/itemviews/simpledommodel/domitem.h
@@ -58,16 +58,16 @@
class DomItem
{
public:
- DomItem(QDomNode &node, int row, DomItem *parent = 0);
+ DomItem(const QDomNode &node, int row, DomItem *parent = nullptr);
~DomItem();
DomItem *child(int i);
DomItem *parent();
QDomNode node() const;
- int row();
+ int row() const;
private:
QDomNode domNode;
- QHash<int,DomItem*> childItems;
+ QHash<int, DomItem *> childItems;
DomItem *parentItem;
int rowNumber;
};
diff --git a/examples/widgets/itemviews/simpledommodel/dommodel.cpp b/examples/widgets/itemviews/simpledommodel/dommodel.cpp
index f9ba0b5801..8e15252ebb 100644
--- a/examples/widgets/itemviews/simpledommodel/dommodel.cpp
+++ b/examples/widgets/itemviews/simpledommodel/dommodel.cpp
@@ -48,16 +48,17 @@
**
****************************************************************************/
-#include "domitem.h"
#include "dommodel.h"
+#include "domitem.h"
#include <QtXml>
//! [0]
-DomModel::DomModel(QDomDocument document, QObject *parent)
- : QAbstractItemModel(parent), domDocument(document)
+DomModel::DomModel(const QDomDocument &document, QObject *parent)
+ : QAbstractItemModel(parent),
+ domDocument(document),
+ rootItem(new DomItem(domDocument, 0))
{
- rootItem = new DomItem(domDocument, 0);
}
//! [0]
@@ -69,8 +70,9 @@ DomModel::~DomModel()
//! [1]
//! [2]
-int DomModel::columnCount(const QModelIndex &/*parent*/) const
+int DomModel::columnCount(const QModelIndex &parent) const
{
+ Q_UNUSED(parent);
return 3;
}
//! [2]
@@ -84,28 +86,31 @@ QVariant DomModel::data(const QModelIndex &index, int role) const
if (role != Qt::DisplayRole)
return QVariant();
- DomItem *item = static_cast<DomItem*>(index.internalPointer());
+ const DomItem *item = static_cast<DomItem*>(index.internalPointer());
- QDomNode node = item->node();
+ const QDomNode node = item->node();
//! [3] //! [4]
- QStringList attributes;
- QDomNamedNodeMap attributeMap = node.attributes();
switch (index.column()) {
case 0:
return node.nodeName();
case 1:
+ {
+ const QDomNamedNodeMap attributeMap = node.attributes();
+ QStringList attributes;
for (int i = 0; i < attributeMap.count(); ++i) {
QDomNode attribute = attributeMap.item(i);
attributes << attribute.nodeName() + "=\""
- +attribute.nodeValue() + '"';
+ + attribute.nodeValue() + '"';
}
return attributes.join(' ');
+ }
case 2:
- return node.nodeValue().split("\n").join(' ');
+ return node.nodeValue().split('\n').join(' ');
default:
- return QVariant();
+ break;
}
+ return QVariant();
}
//! [4]
@@ -113,7 +118,7 @@ QVariant DomModel::data(const QModelIndex &index, int role) const
Qt::ItemFlags DomModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
- return 0;
+ return Qt::NoItemFlags;
return QAbstractItemModel::flags(index);
}
@@ -132,17 +137,15 @@ QVariant DomModel::headerData(int section, Qt::Orientation orientation,
case 2:
return tr("Value");
default:
- return QVariant();
+ break;
}
}
-
return QVariant();
}
//! [6]
//! [7]
-QModelIndex DomModel::index(int row, int column, const QModelIndex &parent)
- const
+QModelIndex DomModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
@@ -159,8 +162,7 @@ QModelIndex DomModel::index(int row, int column, const QModelIndex &parent)
DomItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
- else
- return QModelIndex();
+ return QModelIndex();
}
//! [8]
diff --git a/examples/widgets/itemviews/simpledommodel/dommodel.h b/examples/widgets/itemviews/simpledommodel/dommodel.h
index 411f58295c..a91bb33cf9 100644
--- a/examples/widgets/itemviews/simpledommodel/dommodel.h
+++ b/examples/widgets/itemviews/simpledommodel/dommodel.h
@@ -63,7 +63,7 @@ class DomModel : public QAbstractItemModel
Q_OBJECT
public:
- explicit DomModel(QDomDocument document, QObject *parent = 0);
+ explicit DomModel(const QDomDocument &document, QObject *parent = nullptr);
~DomModel();
QVariant data(const QModelIndex &index, int role) const override;
diff --git a/examples/widgets/itemviews/simpledommodel/mainwindow.cpp b/examples/widgets/itemviews/simpledommodel/mainwindow.cpp
index 7d43d0fc02..86543b07a6 100644
--- a/examples/widgets/itemviews/simpledommodel/mainwindow.cpp
+++ b/examples/widgets/itemviews/simpledommodel/mainwindow.cpp
@@ -48,22 +48,23 @@
**
****************************************************************************/
-#include "dommodel.h"
#include "mainwindow.h"
+#include "dommodel.h"
#include <QDomDocument>
#include <QTreeView>
#include <QMenuBar>
#include <QFileDialog>
-MainWindow::MainWindow() : QMainWindow(), model(0)
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent),
+ model(new DomModel(QDomDocument(), this)),
+ view(new QTreeView(this))
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(tr("&Open..."), this, &MainWindow::openFile, QKeySequence::Open);
fileMenu->addAction(tr("E&xit"), this, &QWidget::close, QKeySequence::Quit);
- model = new DomModel(QDomDocument(), this);
- view = new QTreeView(this);
view->setModel(model);
setCentralWidget(view);
diff --git a/examples/widgets/itemviews/simpledommodel/mainwindow.h b/examples/widgets/itemviews/simpledommodel/mainwindow.h
index 938a1c54c1..b3f8d77f35 100644
--- a/examples/widgets/itemviews/simpledommodel/mainwindow.h
+++ b/examples/widgets/itemviews/simpledommodel/mainwindow.h
@@ -65,7 +65,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
- MainWindow();
+ MainWindow(QWidget *parent = nullptr);
public slots:
void openFile();
diff --git a/examples/widgets/itemviews/simpletreemodel/treeitem.cpp b/examples/widgets/itemviews/simpletreemodel/treeitem.cpp
index e11639ff67..41fe24e737 100644
--- a/examples/widgets/itemviews/simpletreemodel/treeitem.cpp
+++ b/examples/widgets/itemviews/simpletreemodel/treeitem.cpp
@@ -54,16 +54,12 @@
A container for items of data supplied by the simple tree model.
*/
-#include <QStringList>
-
#include "treeitem.h"
//! [0]
-TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)
-{
- m_parentItem = parent;
- m_itemData = data;
-}
+TreeItem::TreeItem(const QVector<QVariant> &data, TreeItem *parent)
+ : m_itemData(data), m_parentItem(parent)
+{}
//! [0]
//! [1]
@@ -83,7 +79,9 @@ void TreeItem::appendChild(TreeItem *item)
//! [3]
TreeItem *TreeItem::child(int row)
{
- return m_childItems.value(row);
+ if (row < 0 || row >= m_childItems.size())
+ return nullptr;
+ return m_childItems.at(row);
}
//! [3]
@@ -104,7 +102,9 @@ int TreeItem::columnCount() const
//! [6]
QVariant TreeItem::data(int column) const
{
- return m_itemData.value(column);
+ if (column < 0 || column >= m_itemData.size())
+ return QVariant();
+ return m_itemData.at(column);
}
//! [6]
diff --git a/examples/widgets/itemviews/simpletreemodel/treeitem.h b/examples/widgets/itemviews/simpletreemodel/treeitem.h
index 8d0bb49627..390433597d 100644
--- a/examples/widgets/itemviews/simpletreemodel/treeitem.h
+++ b/examples/widgets/itemviews/simpletreemodel/treeitem.h
@@ -51,14 +51,14 @@
#ifndef TREEITEM_H
#define TREEITEM_H
-#include <QList>
#include <QVariant>
+#include <QVector>
//! [0]
class TreeItem
{
public:
- explicit TreeItem(const QList<QVariant> &data, TreeItem *parentItem = 0);
+ explicit TreeItem(const QVector<QVariant> &data, TreeItem *parentItem = nullptr);
~TreeItem();
void appendChild(TreeItem *child);
@@ -71,8 +71,8 @@ public:
TreeItem *parentItem();
private:
- QList<TreeItem*> m_childItems;
- QList<QVariant> m_itemData;
+ QVector<TreeItem*> m_childItems;
+ QVector<QVariant> m_itemData;
TreeItem *m_parentItem;
};
//! [0]
diff --git a/examples/widgets/itemviews/simpletreemodel/treemodel.cpp b/examples/widgets/itemviews/simpletreemodel/treemodel.cpp
index 1de970d398..cfa65846ed 100644
--- a/examples/widgets/itemviews/simpletreemodel/treemodel.cpp
+++ b/examples/widgets/itemviews/simpletreemodel/treemodel.cpp
@@ -55,8 +55,8 @@
models.
*/
-#include "treeitem.h"
#include "treemodel.h"
+#include "treeitem.h"
#include <QStringList>
@@ -64,10 +64,8 @@
TreeModel::TreeModel(const QString &data, QObject *parent)
: QAbstractItemModel(parent)
{
- QList<QVariant> rootData;
- rootData << "Title" << "Summary";
- rootItem = new TreeItem(rootData);
- setupModelData(data.split(QString("\n")), rootItem);
+ rootItem = new TreeItem({tr("Title"), tr("Summary")});
+ setupModelData(data.split('\n'), rootItem);
}
//! [0]
@@ -83,8 +81,7 @@ int TreeModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
- else
- return rootItem->columnCount();
+ return rootItem->columnCount();
}
//! [2]
@@ -107,7 +104,7 @@ QVariant TreeModel::data(const QModelIndex &index, int role) const
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
- return 0;
+ return Qt::NoItemFlags;
return QAbstractItemModel::flags(index);
}
@@ -125,8 +122,7 @@ QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
//! [5]
//! [6]
-QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
- const
+QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
@@ -141,8 +137,7 @@ QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
TreeItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
- else
- return QModelIndex();
+ return QModelIndex();
}
//! [6]
@@ -180,8 +175,8 @@ int TreeModel::rowCount(const QModelIndex &parent) const
void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
{
- QList<TreeItem*> parents;
- QList<int> indentations;
+ QVector<TreeItem*> parents;
+ QVector<int> indentations;
parents << parent;
indentations << 0;
@@ -195,14 +190,15 @@ void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
position++;
}
- QString lineData = lines[number].mid(position).trimmed();
+ const QString lineData = lines[number].mid(position).trimmed();
if (!lineData.isEmpty()) {
// Read the column data from the rest of the line.
- QStringList columnStrings = lineData.split("\t", QString::SkipEmptyParts);
- QList<QVariant> columnData;
- for (int column = 0; column < columnStrings.count(); ++column)
- columnData << columnStrings[column];
+ const QStringList columnStrings = lineData.split('\t', QString::SkipEmptyParts);
+ QVector<QVariant> columnData;
+ columnData.reserve(columnStrings.count());
+ for (const QString &columnString : columnStrings)
+ columnData << columnString;
if (position > indentations.last()) {
// The last child of the current parent is now the new parent
@@ -222,7 +218,6 @@ void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
// Append a new item to the current parent's list of children.
parents.last()->appendChild(new TreeItem(columnData, parents.last()));
}
-
++number;
}
}
diff --git a/examples/widgets/itemviews/simpletreemodel/treemodel.h b/examples/widgets/itemviews/simpletreemodel/treemodel.h
index 800728fb82..76fd03f112 100644
--- a/examples/widgets/itemviews/simpletreemodel/treemodel.h
+++ b/examples/widgets/itemviews/simpletreemodel/treemodel.h
@@ -63,7 +63,7 @@ class TreeModel : public QAbstractItemModel
Q_OBJECT
public:
- explicit TreeModel(const QString &data, QObject *parent = 0);
+ explicit TreeModel(const QString &data, QObject *parent = nullptr);
~TreeModel();
QVariant data(const QModelIndex &index, int role) const override;
diff --git a/examples/widgets/itemviews/simplewidgetmapper/window.h b/examples/widgets/itemviews/simplewidgetmapper/window.h
index baa087f8ae..d04b528e16 100644
--- a/examples/widgets/itemviews/simplewidgetmapper/window.h
+++ b/examples/widgets/itemviews/simplewidgetmapper/window.h
@@ -69,7 +69,7 @@ class Window : public QWidget
Q_OBJECT
public:
- Window(QWidget *parent = 0);
+ Window(QWidget *parent = nullptr);
private slots:
void updateButtons(int row);
diff --git a/examples/widgets/itemviews/spinboxdelegate/delegate.cpp b/examples/widgets/itemviews/spinboxdelegate/delegate.cpp
index e7e03688c3..f0fe524a60 100644
--- a/examples/widgets/itemviews/spinboxdelegate/delegate.cpp
+++ b/examples/widgets/itemviews/spinboxdelegate/delegate.cpp
@@ -68,8 +68,8 @@ SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
//! [1]
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
- const QStyleOptionViewItem &/* option */,
- const QModelIndex &/* index */) const
+ const QStyleOptionViewItem &/* option */,
+ const QModelIndex &/* index */) const
{
QSpinBox *editor = new QSpinBox(parent);
editor->setFrame(false);
@@ -105,7 +105,8 @@ void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
//! [4]
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
- const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
+ const QStyleOptionViewItem &option,
+ const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
diff --git a/examples/widgets/itemviews/spinboxdelegate/delegate.h b/examples/widgets/itemviews/spinboxdelegate/delegate.h
index 47ef1555f7..5dbdda9cd0 100644
--- a/examples/widgets/itemviews/spinboxdelegate/delegate.h
+++ b/examples/widgets/itemviews/spinboxdelegate/delegate.h
@@ -59,7 +59,7 @@ class SpinBoxDelegate : public QStyledItemDelegate
Q_OBJECT
public:
- SpinBoxDelegate(QObject *parent = 0);
+ SpinBoxDelegate(QObject *parent = nullptr);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
@@ -68,8 +68,8 @@ public:
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const override;
- void updateEditorGeometry(QWidget *editor,
- const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+ void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override;
};
//! [0]
diff --git a/examples/widgets/itemviews/spreadsheet/main.cpp b/examples/widgets/itemviews/spreadsheet/main.cpp
index 769edbdf03..548dc8d604 100644
--- a/examples/widgets/itemviews/spreadsheet/main.cpp
+++ b/examples/widgets/itemviews/spreadsheet/main.cpp
@@ -53,7 +53,8 @@
#include <QApplication>
#include <QLayout>
-int main(int argc, char** argv) {
+int main(int argc, char **argv)
+{
Q_INIT_RESOURCE(spreadsheet);
QApplication app(argc, argv);
SpreadSheet sheet(10, 6);
diff --git a/examples/widgets/itemviews/spreadsheet/printview.cpp b/examples/widgets/itemviews/spreadsheet/printview.cpp
index 31424e9070..7db1a6bad9 100644
--- a/examples/widgets/itemviews/spreadsheet/printview.cpp
+++ b/examples/widgets/itemviews/spreadsheet/printview.cpp
@@ -48,12 +48,11 @@
**
****************************************************************************/
+#include "printview.h"
+
#ifndef QT_NO_PRINTER
#include <QPrinter>
#endif
-#include <QStyleOptionViewItem>
-
-#include "printview.h"
PrintView::PrintView()
{
diff --git a/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp b/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp
index 621f655b02..fc7fbb872c 100644
--- a/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp
+++ b/examples/widgets/itemviews/spreadsheet/spreadsheet.cpp
@@ -48,36 +48,30 @@
**
****************************************************************************/
-#include <QtWidgets>
-#if defined(QT_PRINTSUPPORT_LIB)
-#include <QtPrintSupport/qtprintsupportglobal.h>
-#if QT_CONFIG(printdialog)
-#include <QPrinter>
-#include <QPrintDialog>
-#endif
-#if QT_CONFIG(printpreviewdialog)
-#include <QPrintPreviewDialog>
-#endif
-#endif
-
#include "spreadsheet.h"
#include "spreadsheetdelegate.h"
#include "spreadsheetitem.h"
#include "printview.h"
+#include <QtWidgets>
+#if defined(QT_PRINTSUPPORT_LIB)
+#include <QtPrintSupport>
+#endif
+
SpreadSheet::SpreadSheet(int rows, int cols, QWidget *parent)
- : QMainWindow(parent)
+ : QMainWindow(parent),
+ toolBar(new QToolBar(this)),
+ cellLabel(new QLabel(toolBar)),
+ table(new QTableWidget(rows, cols, this)),
+ formulaInput(new QLineEdit(this))
{
- addToolBar(toolBar = new QToolBar());
- formulaInput = new QLineEdit();
+ addToolBar(toolBar);
- cellLabel = new QLabel(toolBar);
cellLabel->setMinimumSize(80, 0);
toolBar->addWidget(cellLabel);
toolBar->addWidget(formulaInput);
- table = new QTableWidget(rows, cols, this);
table->setSizeAdjustPolicy(QTableWidget::AdjustToContents);
for (int c = 0; c < cols; ++c) {
QString character(QChar('A' + c));
@@ -88,7 +82,7 @@ SpreadSheet::SpreadSheet(int rows, int cols, QWidget *parent)
table->setItemDelegate(new SpreadSheetDelegate());
createActions();
- updateColor(0);
+ updateColor(nullptr);
setupMenuBar();
setupContents();
setupContextMenu();
@@ -103,7 +97,8 @@ SpreadSheet::SpreadSheet(int rows, int cols, QWidget *parent)
this, &SpreadSheet::updateLineEdit);
connect(table, &QTableWidget::itemChanged,
this, &SpreadSheet::updateStatus);
- connect(formulaInput, &QLineEdit::returnPressed, this, &SpreadSheet::returnPressed);
+ connect(formulaInput, &QLineEdit::returnPressed,
+ this, &SpreadSheet::returnPressed);
connect(table, &QTableWidget::itemChanged,
this, &SpreadSheet::updateLineEdit);
@@ -193,19 +188,19 @@ void SpreadSheet::updateColor(QTableWidgetItem *item)
QPixmap pix(16, 16);
QColor col;
if (item)
- col = item->backgroundColor();
+ col = item->background().color();
if (!col.isValid())
col = palette().base().color();
QPainter pt(&pix);
pt.fillRect(0, 0, 16, 16, col);
- QColor lighter = col.light();
+ QColor lighter = col.lighter();
pt.setPen(lighter);
QPoint lightFrame[] = { QPoint(0, 15), QPoint(0, 0), QPoint(15, 0) };
pt.drawPolyline(lightFrame, 3);
- pt.setPen(col.dark());
+ pt.setPen(col.darker());
QPoint darkFrame[] = { QPoint(1, 15), QPoint(15, 15), QPoint(15, 1) };
pt.drawPolyline(darkFrame, 3);
@@ -240,18 +235,18 @@ void SpreadSheet::returnPressed()
void SpreadSheet::selectColor()
{
QTableWidgetItem *item = table->currentItem();
- QColor col = item ? item->backgroundColor() : table->palette().base().color();
+ QColor col = item ? item->background().color() : table->palette().base().color();
col = QColorDialog::getColor(col, this);
if (!col.isValid())
return;
- QList<QTableWidgetItem*> selected = table->selectedItems();
- if (selected.count() == 0)
+ const QList<QTableWidgetItem *> selected = table->selectedItems();
+ if (selected.isEmpty())
return;
- foreach (QTableWidgetItem *i, selected) {
+ for (QTableWidgetItem *i : selected) {
if (i)
- i->setBackgroundColor(col);
+ i->setBackground(col);
}
updateColor(table->currentItem());
@@ -259,8 +254,8 @@ void SpreadSheet::selectColor()
void SpreadSheet::selectFont()
{
- QList<QTableWidgetItem*> selected = table->selectedItems();
- if (selected.count() == 0)
+ const QList<QTableWidgetItem *> selected = table->selectedItems();
+ if (selected.isEmpty())
return;
bool ok = false;
@@ -268,7 +263,7 @@ void SpreadSheet::selectFont()
if (!ok)
return;
- foreach (QTableWidgetItem *i, selected) {
+ for (QTableWidgetItem *i : selected) {
if (i)
i->setFont(fnt);
}
@@ -397,7 +392,7 @@ void SpreadSheet::actionSum()
int col_last = 0;
int col_cur = 0;
- QList<QTableWidgetItem*> selected = table->selectedItems();
+ const QList<QTableWidgetItem *> selected = table->selectedItems();
if (!selected.isEmpty()) {
QTableWidgetItem *first = selected.first();
@@ -408,7 +403,7 @@ void SpreadSheet::actionSum()
col_last = table->column(last);
}
- QTableWidgetItem *current = table->currentItem();
+ const QTableWidgetItem *current = table->currentItem();
if (current) {
row_cur = table->row(current);
@@ -435,7 +430,7 @@ void SpreadSheet::actionMath_helper(const QString &title, const QString &op)
QString cell2 = "C2";
QString out = "C3";
- QTableWidgetItem *current = table->currentItem();
+ const QTableWidgetItem *current = table->currentItem();
if (current)
out = encode_pos(table->currentRow(), table->currentColumn());
@@ -468,8 +463,9 @@ void SpreadSheet::actionDivide()
void SpreadSheet::clear()
{
- foreach (QTableWidgetItem *i, table->selectedItems())
- i->setText("");
+ const QList<QTableWidgetItem *> selectedItems = table->selectedItems();
+ for (QTableWidgetItem *i : selectedItems)
+ i->setText(QString());
}
void SpreadSheet::setupContextMenu()
@@ -489,13 +485,13 @@ void SpreadSheet::setupContextMenu()
void SpreadSheet::setupContents()
{
- QColor titleBackground(Qt::lightGray);
+ QBrush titleBackground(Qt::lightGray);
QFont titleFont = table->font();
titleFont.setBold(true);
// column 0
table->setItem(0, 0, new SpreadSheetItem("Item"));
- table->item(0, 0)->setBackgroundColor(titleBackground);
+ table->item(0, 0)->setBackground(titleBackground);
table->item(0, 0)->setToolTip("This column shows the purchased item/service");
table->item(0, 0)->setFont(titleFont);
@@ -510,11 +506,11 @@ void SpreadSheet::setupContents()
table->setItem(9, 0, new SpreadSheetItem("Total:"));
table->item(9, 0)->setFont(titleFont);
- table->item(9, 0)->setBackgroundColor(Qt::lightGray);
+ table->item(9, 0)->setBackground(titleBackground);
// column 1
table->setItem(0, 1, new SpreadSheetItem("Date"));
- table->item(0, 1)->setBackgroundColor(titleBackground);
+ table->item(0, 1)->setBackground(titleBackground);
table->item(0, 1)->setToolTip("This column shows the purchase date, double click to change");
table->item(0, 1)->setFont(titleFont);
@@ -528,11 +524,11 @@ void SpreadSheet::setupContents()
table->setItem(8, 1, new SpreadSheetItem("18/6/2006"));
table->setItem(9, 1, new SpreadSheetItem());
- table->item(9, 1)->setBackgroundColor(Qt::lightGray);
+ table->item(9, 1)->setBackground(titleBackground);
// column 2
table->setItem(0, 2, new SpreadSheetItem("Price"));
- table->item(0, 2)->setBackgroundColor(titleBackground);
+ table->item(0, 2)->setBackground(titleBackground);
table->item(0, 2)->setToolTip("This column shows the price of the purchase");
table->item(0, 2)->setFont(titleFont);
@@ -546,11 +542,11 @@ void SpreadSheet::setupContents()
table->setItem(8, 2, new SpreadSheetItem("1240"));
table->setItem(9, 2, new SpreadSheetItem());
- table->item(9, 2)->setBackgroundColor(Qt::lightGray);
+ table->item(9, 2)->setBackground(Qt::lightGray);
// column 3
table->setItem(0, 3, new SpreadSheetItem("Currency"));
- table->item(0, 3)->setBackgroundColor(titleBackground);
+ table->item(0, 3)->setBackground(titleBackground);
table->item(0, 3)->setToolTip("This column shows the currency");
table->item(0, 3)->setFont(titleFont);
@@ -564,11 +560,11 @@ void SpreadSheet::setupContents()
table->setItem(8, 3, new SpreadSheetItem("USD"));
table->setItem(9, 3, new SpreadSheetItem());
- table->item(9,3)->setBackgroundColor(Qt::lightGray);
+ table->item(9, 3)->setBackground(Qt::lightGray);
// column 4
table->setItem(0, 4, new SpreadSheetItem("Ex. Rate"));
- table->item(0, 4)->setBackgroundColor(titleBackground);
+ table->item(0, 4)->setBackground(titleBackground);
table->item(0, 4)->setToolTip("This column shows the exchange rate to NOK");
table->item(0, 4)->setFont(titleFont);
@@ -582,11 +578,11 @@ void SpreadSheet::setupContents()
table->setItem(8, 4, new SpreadSheetItem("7"));
table->setItem(9, 4, new SpreadSheetItem());
- table->item(9,4)->setBackgroundColor(Qt::lightGray);
+ table->item(9, 4)->setBackground(titleBackground);
// column 5
table->setItem(0, 5, new SpreadSheetItem("NOK"));
- table->item(0, 5)->setBackgroundColor(titleBackground);
+ table->item(0, 5)->setBackground(titleBackground);
table->item(0, 5)->setToolTip("This column shows the expenses in NOK");
table->item(0, 5)->setFont(titleFont);
@@ -600,7 +596,7 @@ void SpreadSheet::setupContents()
table->setItem(8, 5, new SpreadSheetItem("* C9 E9"));
table->setItem(9, 5, new SpreadSheetItem("sum F2 F9"));
- table->item(9,5)->setBackgroundColor(Qt::lightGray);
+ table->item(9, 5)->setBackground(titleBackground);
}
const char *htmlText =
diff --git a/examples/widgets/itemviews/spreadsheet/spreadsheet.h b/examples/widgets/itemviews/spreadsheet/spreadsheet.h
index a90d1d8c20..b36a377156 100644
--- a/examples/widgets/itemviews/spreadsheet/spreadsheet.h
+++ b/examples/widgets/itemviews/spreadsheet/spreadsheet.h
@@ -65,10 +65,8 @@ QT_END_NAMESPACE
class SpreadSheet : public QMainWindow
{
Q_OBJECT
-
public:
-
- SpreadSheet(int rows, int cols, QWidget *parent = 0);
+ SpreadSheet(int rows, int cols, QWidget *parent = nullptr);
public slots:
void updateStatus(QTableWidgetItem *item);
diff --git a/examples/widgets/itemviews/spreadsheet/spreadsheetdelegate.cpp b/examples/widgets/itemviews/spreadsheet/spreadsheetdelegate.cpp
index aaf8902af5..eadd5fadb8 100644
--- a/examples/widgets/itemviews/spreadsheet/spreadsheetdelegate.cpp
+++ b/examples/widgets/itemviews/spreadsheet/spreadsheetdelegate.cpp
@@ -53,11 +53,12 @@
#include <QtWidgets>
SpreadSheetDelegate::SpreadSheetDelegate(QObject *parent)
- : QItemDelegate(parent) {}
+ : QItemDelegate(parent)
+{}
QWidget *SpreadSheetDelegate::createEditor(QWidget *parent,
- const QStyleOptionViewItem &,
- const QModelIndex &index) const
+ const QStyleOptionViewItem &,
+ const QModelIndex &index) const
{
if (index.column() == 1) {
QDateTimeEdit *editor = new QDateTimeEdit(parent);
@@ -92,7 +93,7 @@ void SpreadSheetDelegate::commitAndCloseEditor()
}
void SpreadSheetDelegate::setEditorData(QWidget *editor,
- const QModelIndex &index) const
+ const QModelIndex &index) const
{
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
if (edit) {
@@ -109,7 +110,8 @@ void SpreadSheetDelegate::setEditorData(QWidget *editor,
}
void SpreadSheetDelegate::setModelData(QWidget *editor,
- QAbstractItemModel *model, const QModelIndex &index) const
+ QAbstractItemModel *model,
+ const QModelIndex &index) const
{
QLineEdit *edit = qobject_cast<QLineEdit *>(editor);
if (edit) {
diff --git a/examples/widgets/itemviews/spreadsheet/spreadsheetdelegate.h b/examples/widgets/itemviews/spreadsheet/spreadsheetdelegate.h
index 333467720f..c89459cadf 100644
--- a/examples/widgets/itemviews/spreadsheet/spreadsheetdelegate.h
+++ b/examples/widgets/itemviews/spreadsheet/spreadsheetdelegate.h
@@ -51,8 +51,6 @@
#ifndef SPREADSHEETDELEGATE_H
#define SPREADSHEETDELEGATE_H
-#include "spreadsheet.h"
-
#include <QItemDelegate>
class SpreadSheetDelegate : public QItemDelegate
@@ -60,7 +58,7 @@ class SpreadSheetDelegate : public QItemDelegate
Q_OBJECT
public:
- SpreadSheetDelegate(QObject *parent = 0);
+ SpreadSheetDelegate(QObject *parent = nullptr);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &,
const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
diff --git a/examples/widgets/itemviews/spreadsheet/spreadsheetitem.cpp b/examples/widgets/itemviews/spreadsheet/spreadsheetitem.cpp
index 4c18fa8251..62d3a6fdcd 100644
--- a/examples/widgets/itemviews/spreadsheet/spreadsheetitem.cpp
+++ b/examples/widgets/itemviews/spreadsheet/spreadsheetitem.cpp
@@ -50,19 +50,9 @@
#include "spreadsheetitem.h"
-SpreadSheetItem::SpreadSheetItem()
- : QTableWidgetItem(), isResolving(false)
-{
-}
-
-SpreadSheetItem::SpreadSheetItem(const QString &text)
- : QTableWidgetItem(text), isResolving(false)
-{
-}
-
QTableWidgetItem *SpreadSheetItem::clone() const
{
- SpreadSheetItem *item = new SpreadSheetItem();
+ SpreadSheetItem *item = new SpreadSheetItem;
*item = *this;
return item;
}
@@ -75,21 +65,20 @@ QVariant SpreadSheetItem::data(int role) const
if (role == Qt::DisplayRole)
return display();
- QString t = display().toString();
- bool isNumber = false;
- int number = t.toInt(&isNumber);
+ const QString t = display().toString();
- if (role == Qt::TextColorRole) {
- if (!isNumber)
- return QVariant::fromValue(QColor(Qt::black));
- else if (number < 0)
- return QVariant::fromValue(QColor(Qt::red));
- return QVariant::fromValue(QColor(Qt::blue));
+ if (role == Qt::ForegroundRole) {
+ bool isNumber = false;
+ const int number = t.toInt(&isNumber);
+ QColor color = Qt::black;
+ if (isNumber)
+ color = (number < 0) ? Qt::red : Qt::blue;
+ return QVariant::fromValue(color);
}
- if (role == Qt::TextAlignmentRole)
- if (!t.isEmpty() && (t.at(0).isNumber() || t.at(0) == '-'))
- return (int)(Qt::AlignRight | Qt::AlignVCenter);
+ if (role == Qt::TextAlignmentRole)
+ if (!t.isEmpty() && (t.at(0).isNumber() || t.at(0) == '-'))
+ return int(Qt::AlignRight | Qt::AlignVCenter);
return QTableWidgetItem::data(role);
}
diff --git a/examples/widgets/itemviews/spreadsheet/spreadsheetitem.h b/examples/widgets/itemviews/spreadsheet/spreadsheetitem.h
index 46460df527..159f4a7eea 100644
--- a/examples/widgets/itemviews/spreadsheet/spreadsheetitem.h
+++ b/examples/widgets/itemviews/spreadsheet/spreadsheetitem.h
@@ -58,8 +58,7 @@
class SpreadSheetItem : public QTableWidgetItem
{
public:
- SpreadSheetItem();
- SpreadSheetItem(const QString &text);
+ using QTableWidgetItem::QTableWidgetItem;
QTableWidgetItem *clone() const override;
@@ -74,10 +73,10 @@ public:
static QVariant computeFormula(const QString &formula,
const QTableWidget *widget,
- const QTableWidgetItem *self = 0);
+ const QTableWidgetItem *self = nullptr);
private:
- mutable bool isResolving;
+ mutable bool isResolving = false;
};
#endif // SPREADSHEETITEM_H
diff --git a/examples/widgets/itemviews/stardelegate/main.cpp b/examples/widgets/itemviews/stardelegate/main.cpp
index 51ca30c73a..452976bba0 100644
--- a/examples/widgets/itemviews/stardelegate/main.cpp
+++ b/examples/widgets/itemviews/stardelegate/main.cpp
@@ -101,10 +101,7 @@ int main(int argc, char *argv[])
tableWidget.setEditTriggers(QAbstractItemView::DoubleClicked
| QAbstractItemView::SelectedClicked);
tableWidget.setSelectionBehavior(QAbstractItemView::SelectRows);
-
- QStringList headerLabels;
- headerLabels << "Title" << "Genre" << "Artist" << "Rating";
- tableWidget.setHorizontalHeaderLabels(headerLabels);
+ tableWidget.setHorizontalHeaderLabels({"Title", "Genre", "Artist", "Rating"});
populateTableWidget(&tableWidget);
diff --git a/examples/widgets/itemviews/stardelegate/stardelegate.cpp b/examples/widgets/itemviews/stardelegate/stardelegate.cpp
index da5902a160..41ae5a920f 100644
--- a/examples/widgets/itemviews/stardelegate/stardelegate.cpp
+++ b/examples/widgets/itemviews/stardelegate/stardelegate.cpp
@@ -65,7 +65,7 @@ void StarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
painter->fillRect(option.rect, option.palette.highlight());
starRating.paint(painter, option.rect, option.palette,
- StarRating::ReadOnly);
+ StarRating::EditMode::ReadOnly);
} else {
QStyledItemDelegate::paint(painter, option, index);
}
@@ -79,9 +79,8 @@ QSize StarDelegate::sizeHint(const QStyleOptionViewItem &option,
if (index.data().canConvert<StarRating>()) {
StarRating starRating = qvariant_cast<StarRating>(index.data());
return starRating.sizeHint();
- } else {
- return QStyledItemDelegate::sizeHint(option, index);
}
+ return QStyledItemDelegate::sizeHint(option, index);
}
//! [1]
@@ -96,9 +95,8 @@ QWidget *StarDelegate::createEditor(QWidget *parent,
connect(editor, &StarEditor::editingFinished,
this, &StarDelegate::commitAndCloseEditor);
return editor;
- } else {
- return QStyledItemDelegate::createEditor(parent, option, index);
}
+ return QStyledItemDelegate::createEditor(parent, option, index);
}
//! [2]
diff --git a/examples/widgets/itemviews/stardelegate/stardelegate.h b/examples/widgets/itemviews/stardelegate/stardelegate.h
index ffc65fbedd..1fc31f8ee8 100644
--- a/examples/widgets/itemviews/stardelegate/stardelegate.h
+++ b/examples/widgets/itemviews/stardelegate/stardelegate.h
@@ -57,9 +57,8 @@
class StarDelegate : public QStyledItemDelegate
{
Q_OBJECT
-
public:
- StarDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {}
+ using QStyledItemDelegate::QStyledItemDelegate;
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
diff --git a/examples/widgets/itemviews/stardelegate/stareditor.cpp b/examples/widgets/itemviews/stardelegate/stareditor.cpp
index 19a4b54d9e..43706eeae0 100644
--- a/examples/widgets/itemviews/stardelegate/stareditor.cpp
+++ b/examples/widgets/itemviews/stardelegate/stareditor.cpp
@@ -48,11 +48,11 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "stareditor.h"
#include "starrating.h"
+#include <QtWidgets>
+
//! [0]
StarEditor::StarEditor(QWidget *parent)
: QWidget(parent)
@@ -71,35 +71,37 @@ QSize StarEditor::sizeHint() const
void StarEditor::paintEvent(QPaintEvent *)
{
QPainter painter(this);
- myStarRating.paint(&painter, rect(), this->palette(),
- StarRating::Editable);
+ myStarRating.paint(&painter, rect(), palette(),
+ StarRating::EditMode::Editable);
}
//! [1]
//! [2]
void StarEditor::mouseMoveEvent(QMouseEvent *event)
{
- int star = starAtPosition(event->x());
+ const int star = starAtPosition(event->x());
if (star != myStarRating.starCount() && star != -1) {
myStarRating.setStarCount(star);
update();
}
+ QWidget::mouseMoveEvent(event);
}
//! [2]
//! [3]
-void StarEditor::mouseReleaseEvent(QMouseEvent * /* event */)
+void StarEditor::mouseReleaseEvent(QMouseEvent *event)
{
emit editingFinished();
+ QWidget::mouseReleaseEvent(event);
}
//! [3]
//! [4]
-int StarEditor::starAtPosition(int x)
+int StarEditor::starAtPosition(int x) const
{
- int star = (x / (myStarRating.sizeHint().width()
- / myStarRating.maxStarCount())) + 1;
+ const int star = (x / (myStarRating.sizeHint().width()
+ / myStarRating.maxStarCount())) + 1;
if (star <= 0 || star > myStarRating.maxStarCount())
return -1;
diff --git a/examples/widgets/itemviews/stardelegate/stareditor.h b/examples/widgets/itemviews/stardelegate/stareditor.h
index 4a4c3a4954..8b1bf2efed 100644
--- a/examples/widgets/itemviews/stardelegate/stareditor.h
+++ b/examples/widgets/itemviews/stardelegate/stareditor.h
@@ -59,9 +59,8 @@
class StarEditor : public QWidget
{
Q_OBJECT
-
public:
- StarEditor(QWidget *parent = 0);
+ StarEditor(QWidget *parent = nullptr);
QSize sizeHint() const override;
void setStarRating(const StarRating &starRating) {
@@ -78,7 +77,7 @@ protected:
void mouseReleaseEvent(QMouseEvent *event) override;
private:
- int starAtPosition(int x);
+ int starAtPosition(int x) const;
StarRating myStarRating;
};
diff --git a/examples/widgets/itemviews/stardelegate/starrating.cpp b/examples/widgets/itemviews/stardelegate/starrating.cpp
index 845e474de9..75f0bd9cf7 100644
--- a/examples/widgets/itemviews/stardelegate/starrating.cpp
+++ b/examples/widgets/itemviews/stardelegate/starrating.cpp
@@ -48,19 +48,18 @@
**
****************************************************************************/
+#include "starrating.h"
+
#include <QtWidgets>
#include <cmath>
-#include "starrating.h"
-
-const int PaintingScaleFactor = 20;
+constexpr int PaintingScaleFactor = 20;
//! [0]
StarRating::StarRating(int starCount, int maxStarCount)
+ : myStarCount(starCount),
+ myMaxStarCount(maxStarCount)
{
- myStarCount = starCount;
- myMaxStarCount = maxStarCount;
-
starPolygon << QPointF(1.0, 0.5);
for (int i = 1; i < 5; ++i)
starPolygon << QPointF(0.5 + 0.5 * std::cos(0.8 * i * 3.14),
@@ -87,23 +86,19 @@ void StarRating::paint(QPainter *painter, const QRect &rect,
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setPen(Qt::NoPen);
+ painter->setBrush(mode == EditMode::Editable ?
+ palette.highlight() :
+ palette.windowText());
- if (mode == Editable) {
- painter->setBrush(palette.highlight());
- } else {
- painter->setBrush(palette.foreground());
- }
-
- int yOffset = (rect.height() - PaintingScaleFactor) / 2;
+ const int yOffset = (rect.height() - PaintingScaleFactor) / 2;
painter->translate(rect.x(), rect.y() + yOffset);
painter->scale(PaintingScaleFactor, PaintingScaleFactor);
for (int i = 0; i < myMaxStarCount; ++i) {
- if (i < myStarCount) {
+ if (i < myStarCount)
painter->drawPolygon(starPolygon, Qt::WindingFill);
- } else if (mode == Editable) {
+ else if (mode == EditMode::Editable)
painter->drawPolygon(diamondPolygon, Qt::WindingFill);
- }
painter->translate(1.0, 0.0);
}
diff --git a/examples/widgets/itemviews/stardelegate/starrating.h b/examples/widgets/itemviews/stardelegate/starrating.h
index fa77311914..fc3028db58 100644
--- a/examples/widgets/itemviews/stardelegate/starrating.h
+++ b/examples/widgets/itemviews/stardelegate/starrating.h
@@ -51,15 +51,15 @@
#ifndef STARRATING_H
#define STARRATING_H
-#include <QMetaType>
-#include <QPointF>
-#include <QVector>
+#include <QPainter>
+#include <QPolygonF>
+#include <QSize>
//! [0]
class StarRating
{
public:
- enum EditMode { Editable, ReadOnly };
+ enum class EditMode { Editable, ReadOnly };
explicit StarRating(int starCount = 1, int maxStarCount = 5);
diff --git a/examples/widgets/itemviews/storageview/main.cpp b/examples/widgets/itemviews/storageview/main.cpp
index f349e58fad..8f23a4820a 100644
--- a/examples/widgets/itemviews/storageview/main.cpp
+++ b/examples/widgets/itemviews/storageview/main.cpp
@@ -49,10 +49,9 @@
**
****************************************************************************/
-#include <QtWidgets/QApplication>
-#include <QtWidgets/QHeaderView>
-#include <QtWidgets/QShortcut>
-#include <QtWidgets/QTreeView>
+#include <QApplication>
+#include <QShortcut>
+#include <QTreeView>
#include "storagemodel.h"
diff --git a/examples/widgets/itemviews/storageview/storagemodel.cpp b/examples/widgets/itemviews/storageview/storagemodel.cpp
index 063f126d86..b98fc8445c 100644
--- a/examples/widgets/itemviews/storageview/storagemodel.cpp
+++ b/examples/widgets/itemviews/storageview/storagemodel.cpp
@@ -53,14 +53,6 @@
#include <QDir>
#include <QLocale>
-#include <qmath.h>
-#include <algorithm>
-#include <cmath>
-
-StorageModel::StorageModel(QObject *parent) :
- QAbstractTableModel(parent)
-{
-}
void StorageModel::refresh()
{
diff --git a/examples/widgets/itemviews/storageview/storagemodel.h b/examples/widgets/itemviews/storageview/storagemodel.h
index 787b2f04de..597218c220 100644
--- a/examples/widgets/itemviews/storageview/storagemodel.h
+++ b/examples/widgets/itemviews/storageview/storagemodel.h
@@ -74,7 +74,7 @@ public:
ColumnCount
};
- explicit StorageModel(QObject *parent = nullptr);
+ using QAbstractTableModel::QAbstractTableModel;
int columnCount(const QModelIndex &parent) const override;
int rowCount(const QModelIndex &parent) const override;
diff --git a/examples/widgets/layouts/basiclayouts/dialog.cpp b/examples/widgets/layouts/basiclayouts/dialog.cpp
index 7acbc50eb7..8376820545 100644
--- a/examples/widgets/layouts/basiclayouts/dialog.cpp
+++ b/examples/widgets/layouts/basiclayouts/dialog.cpp
@@ -69,8 +69,8 @@ Dialog::Dialog()
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
| QDialogButtonBox::Cancel);
- connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
- connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
//! [1]
//! [2]
@@ -99,7 +99,7 @@ void Dialog::createMenu()
exitAction = fileMenu->addAction(tr("E&xit"));
menuBar->addMenu(fileMenu);
- connect(exitAction, SIGNAL(triggered()), this, SLOT(accept()));
+ connect(exitAction, &QAction::triggered, this, &QDialog::accept);
}
//! [6]
diff --git a/examples/widgets/layouts/borderlayout/borderlayout.cpp b/examples/widgets/layouts/borderlayout/borderlayout.cpp
index 9b142584c9..b8ddd3af83 100644
--- a/examples/widgets/layouts/borderlayout/borderlayout.cpp
+++ b/examples/widgets/layouts/borderlayout/borderlayout.cpp
@@ -50,10 +50,10 @@
#include "borderlayout.h"
-BorderLayout::BorderLayout(QWidget *parent, int margin, int spacing)
+BorderLayout::BorderLayout(QWidget *parent, const QMargins &margins, int spacing)
: QLayout(parent)
{
- setMargin(margin);
+ setContentsMargins(margins);
setSpacing(spacing);
}
@@ -98,10 +98,7 @@ int BorderLayout::count() const
QLayoutItem *BorderLayout::itemAt(int index) const
{
ItemWrapper *wrapper = list.value(index);
- if (wrapper)
- return wrapper->item;
- else
- return 0;
+ return wrapper ? wrapper->item : nullptr;
}
QSize BorderLayout::minimumSize() const
@@ -111,7 +108,7 @@ QSize BorderLayout::minimumSize() const
void BorderLayout::setGeometry(const QRect &rect)
{
- ItemWrapper *center = 0;
+ ItemWrapper *center = nullptr;
int eastWidth = 0;
int westWidth = 0;
int northHeight = 0;
@@ -189,7 +186,7 @@ QLayoutItem *BorderLayout::takeAt(int index)
ItemWrapper *layoutStruct = list.takeAt(index);
return layoutStruct->item;
}
- return 0;
+ return nullptr;
}
void BorderLayout::add(QLayoutItem *item, Position position)
diff --git a/examples/widgets/layouts/borderlayout/borderlayout.h b/examples/widgets/layouts/borderlayout/borderlayout.h
index 4c0c01f90b..58d1aa394d 100644
--- a/examples/widgets/layouts/borderlayout/borderlayout.h
+++ b/examples/widgets/layouts/borderlayout/borderlayout.h
@@ -59,7 +59,7 @@ class BorderLayout : public QLayout
public:
enum Position { West, North, South, East, Center };
- explicit BorderLayout(QWidget *parent, int margin = 0, int spacing = -1);
+ explicit BorderLayout(QWidget *parent, const QMargins &margins = QMargins(), int spacing = -1);
BorderLayout(int spacing = -1);
~BorderLayout();
diff --git a/examples/widgets/layouts/dynamiclayouts/dialog.cpp b/examples/widgets/layouts/dynamiclayouts/dialog.cpp
index f46053372a..baf3b4cf1e 100644
--- a/examples/widgets/layouts/dynamiclayouts/dialog.cpp
+++ b/examples/widgets/layouts/dynamiclayouts/dialog.cpp
@@ -104,7 +104,7 @@ void Dialog::rotateWidgets()
{
Q_ASSERT(rotatableWidgets.count() % 2 == 0);
- foreach (QWidget *widget, rotatableWidgets)
+ for (QWidget *widget : qAsConst(rotatableWidgets))
rotatableLayout->removeWidget(widget);
rotatableWidgets.enqueue(rotatableWidgets.dequeue());
diff --git a/examples/widgets/layouts/flowlayout/flowlayout.cpp b/examples/widgets/layouts/flowlayout/flowlayout.cpp
index 9203da0ba1..5c59ae025c 100644
--- a/examples/widgets/layouts/flowlayout/flowlayout.cpp
+++ b/examples/widgets/layouts/flowlayout/flowlayout.cpp
@@ -116,8 +116,7 @@ QLayoutItem *FlowLayout::takeAt(int index)
{
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index);
- else
- return 0;
+ return nullptr;
}
//! [5]
@@ -156,11 +155,11 @@ QSize FlowLayout::sizeHint() const
QSize FlowLayout::minimumSize() const
{
QSize size;
- QLayoutItem *item;
- foreach (item, itemList)
+ for (const QLayoutItem *item : qAsConst(itemList))
size = size.expandedTo(item->minimumSize());
- size += QSize(2*margin(), 2*margin());
+ const QMargins margins = contentsMargins();
+ size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
return size;
}
//! [8]
@@ -177,9 +176,8 @@ int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
//! [9]
//! [10]
- QLayoutItem *item;
- foreach (item, itemList) {
- QWidget *wid = item->widget();
+ for (QLayoutItem *item : qAsConst(itemList)) {
+ const QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
@@ -215,7 +213,7 @@ int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
return -1;
} else if (parent->isWidgetType()) {
QWidget *pw = static_cast<QWidget *>(parent);
- return pw->style()->pixelMetric(pm, 0, pw);
+ return pw->style()->pixelMetric(pm, nullptr, pw);
} else {
return static_cast<QLayout *>(parent)->spacing();
}
diff --git a/examples/widgets/mainwindows/application/mainwindow.cpp b/examples/widgets/mainwindows/application/mainwindow.cpp
index dc93fe4eb2..7886c4afac 100644
--- a/examples/widgets/mainwindows/application/mainwindow.cpp
+++ b/examples/widgets/mainwindows/application/mainwindow.cpp
@@ -337,11 +337,11 @@ void MainWindow::loadFile(const QString &fileName)
QTextStream in(&file);
#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(Qt::WaitCursor);
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
#endif
textEdit->setPlainText(in.readAll());
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
setCurrentFile(fileName);
@@ -353,23 +353,27 @@ void MainWindow::loadFile(const QString &fileName)
bool MainWindow::saveFile(const QString &fileName)
//! [44] //! [45]
{
- QFile file(fileName);
- if (!file.open(QFile::WriteOnly | QFile::Text)) {
- QMessageBox::warning(this, tr("Application"),
- tr("Cannot write file %1:\n%2.")
- .arg(QDir::toNativeSeparators(fileName),
- file.errorString()));
- return false;
+ QString errorMessage;
+
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
+ QSaveFile file(fileName);
+ if (file.open(QFile::WriteOnly | QFile::Text)) {
+ QTextStream out(&file);
+ out << textEdit->toPlainText();
+ if (!file.commit()) {
+ errorMessage = tr("Cannot write file %1:\n%2.")
+ .arg(QDir::toNativeSeparators(fileName), file.errorString());
+ }
+ } else {
+ errorMessage = tr("Cannot open file %1 for writing:\n%2.")
+ .arg(QDir::toNativeSeparators(fileName), file.errorString());
}
+ QGuiApplication::restoreOverrideCursor();
- QTextStream out(&file);
-#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(Qt::WaitCursor);
-#endif
- out << textEdit->toPlainText();
-#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
-#endif
+ if (!errorMessage.isEmpty()) {
+ QMessageBox::warning(this, tr("Application"), errorMessage);
+ return false;
+ }
setCurrentFile(fileName);
statusBar()->showMessage(tr("File saved"), 2000);
diff --git a/examples/widgets/mainwindows/dockwidgets/mainwindow.cpp b/examples/widgets/mainwindows/dockwidgets/mainwindow.cpp
index 47a6e78265..a62765cdab 100644
--- a/examples/widgets/mainwindows/dockwidgets/mainwindow.cpp
+++ b/examples/widgets/mainwindows/dockwidgets/mainwindow.cpp
@@ -161,9 +161,9 @@ void MainWindow::save()
}
QTextStream out(&file);
- QApplication::setOverrideCursor(Qt::WaitCursor);
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
out << textEdit->toHtml();
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
statusBar()->showMessage(tr("Saved '%1'").arg(fileName), 2000);
}
diff --git a/examples/widgets/mainwindows/mainwindow/colorswatch.cpp b/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
index 720f9a2085..5662518ddc 100644
--- a/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
+++ b/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
@@ -86,7 +86,7 @@ QColor bgColorForName(const QString &name)
return QColor("#D8D8F1");
if (name == "Yellow")
return QColor("#F1F0D8");
- return QColor(name).light(110);
+ return QColor(name).lighter(110);
}
QColor fgColorForName(const QString &name)
@@ -454,8 +454,8 @@ void ColorSwatch::updateContextMenu()
tabMenu->clear();
splitHMenu->clear();
splitVMenu->clear();
- QList<ColorSwatch*> dock_list = mainWindow->findChildren<ColorSwatch*>();
- foreach (ColorSwatch *dock, dock_list) {
+ const QList<ColorSwatch *> dockList = mainWindow->findChildren<ColorSwatch*>();
+ for (const ColorSwatch *dock : dockList) {
tabMenu->addAction(dock->objectName());
splitHMenu->addAction(dock->objectName());
splitVMenu->addAction(dock->objectName());
@@ -464,7 +464,8 @@ void ColorSwatch::updateContextMenu()
static ColorSwatch *findByName(const QMainWindow *mainWindow, const QString &name)
{
- foreach (ColorSwatch *dock, mainWindow->findChildren<ColorSwatch*>()) {
+ const QList<ColorSwatch *> dockList = mainWindow->findChildren<ColorSwatch*>();
+ for (ColorSwatch *dock : dockList) {
if (name == dock->objectName())
return dock;
}
@@ -584,7 +585,7 @@ void ColorSwatch::changeVerticalTitleBar(bool on)
QSize BlueTitleBar::minimumSizeHint() const
{
QDockWidget *dw = qobject_cast<QDockWidget*>(parentWidget());
- Q_ASSERT(dw != 0);
+ Q_ASSERT(dw);
QSize result(leftPm.width() + rightPm.width(), centerPm.height());
if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar)
result.transpose();
@@ -605,7 +606,7 @@ void BlueTitleBar::paintEvent(QPaintEvent*)
QRect rect = this->rect();
QDockWidget *dw = qobject_cast<QDockWidget*>(parentWidget());
- Q_ASSERT(dw != 0);
+ Q_ASSERT(dw);
if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar) {
QSize s = rect.size();
@@ -632,7 +633,7 @@ void BlueTitleBar::mouseReleaseEvent(QMouseEvent *event)
QRect rect = this->rect();
QDockWidget *dw = qobject_cast<QDockWidget*>(parentWidget());
- Q_ASSERT(dw != 0);
+ Q_ASSERT(dw);
if (dw->features() & QDockWidget::DockWidgetVerticalTitleBar) {
QPoint p = pos;
@@ -676,7 +677,7 @@ void BlueTitleBar::mouseReleaseEvent(QMouseEvent *event)
void BlueTitleBar::updateMask()
{
QDockWidget *dw = qobject_cast<QDockWidget*>(parent());
- Q_ASSERT(dw != 0);
+ Q_ASSERT(dw);
QRect rect = dw->rect();
QPixmap bitmap(dw->size());
diff --git a/examples/widgets/mainwindows/mainwindow/toolbar.cpp b/examples/widgets/mainwindows/mainwindow/toolbar.cpp
index 7c96f5b1be..36d4108b1e 100644
--- a/examples/widgets/mainwindows/mainwindow/toolbar.cpp
+++ b/examples/widgets/mainwindows/mainwindow/toolbar.cpp
@@ -208,7 +208,7 @@ ToolBar::ToolBar(const QString &title, QWidget *parent)
void ToolBar::updateMenu()
{
QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
- Q_ASSERT(mainWindow != 0);
+ Q_ASSERT(mainWindow);
const Qt::ToolBarArea area = mainWindow->toolBarArea(this);
const Qt::ToolBarAreas areas = allowedAreas();
@@ -244,7 +244,8 @@ void ToolBar::order()
{
QList<QAction *> ordered;
QList<QAction *> actions1 = actions();
- foreach (QAction *action, findChildren<QAction *>()) {
+ const QList<QAction *> childActions = findChildren<QAction *>();
+ for (QAction *action : childActions) {
if (!actions1.contains(action))
continue;
actions1.removeAll(action);
@@ -313,7 +314,7 @@ void ToolBar::place(Qt::ToolBarArea area, bool p)
return;
QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
- Q_ASSERT(mainWindow != 0);
+ Q_ASSERT(mainWindow);
mainWindow->addToolBar(area, this);
@@ -355,7 +356,7 @@ void ToolBar::placeBottom(bool p)
void ToolBar::insertToolBarBreak()
{
QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget());
- Q_ASSERT(mainWindow != 0);
+ Q_ASSERT(mainWindow);
mainWindow->insertToolBarBreak(this);
}
diff --git a/examples/widgets/mainwindows/mdi/main.cpp b/examples/widgets/mainwindows/mdi/main.cpp
index e23f5f6e60..950244ad53 100644
--- a/examples/widgets/mainwindows/mdi/main.cpp
+++ b/examples/widgets/mainwindows/mdi/main.cpp
@@ -70,7 +70,8 @@ int main(int argc, char *argv[])
parser.process(app);
MainWindow mainWin;
- foreach (const QString &fileName, parser.positionalArguments())
+ const QStringList posArgs = parser.positionalArguments();
+ for (const QString &fileName : posArgs)
mainWin.openFile(fileName);
mainWin.show();
return app.exec();
diff --git a/examples/widgets/mainwindows/mdi/mainwindow.cpp b/examples/widgets/mainwindows/mdi/mainwindow.cpp
index 188de1893e..b952d19e2e 100644
--- a/examples/widgets/mainwindows/mdi/mainwindow.cpp
+++ b/examples/widgets/mainwindows/mdi/mainwindow.cpp
@@ -242,7 +242,7 @@ void MainWindow::about()
void MainWindow::updateMenus()
{
- bool hasMdiChild = (activeMdiChild() != 0);
+ bool hasMdiChild = (activeMdiChild() != nullptr);
saveAct->setEnabled(hasMdiChild);
saveAsAct->setEnabled(hasMdiChild);
#ifndef QT_NO_CLIPBOARD
@@ -483,19 +483,20 @@ MdiChild *MainWindow::activeMdiChild() const
{
if (QMdiSubWindow *activeSubWindow = mdiArea->activeSubWindow())
return qobject_cast<MdiChild *>(activeSubWindow->widget());
- return 0;
+ return nullptr;
}
QMdiSubWindow *MainWindow::findMdiChild(const QString &fileName) const
{
QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();
- foreach (QMdiSubWindow *window, mdiArea->subWindowList()) {
+ const QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
+ for (QMdiSubWindow *window : subWindows) {
MdiChild *mdiChild = qobject_cast<MdiChild *>(window->widget());
if (mdiChild->currentFile() == canonicalFilePath)
return window;
}
- return 0;
+ return nullptr;
}
void MainWindow::switchLayoutDirection()
diff --git a/examples/widgets/mainwindows/mdi/mdichild.cpp b/examples/widgets/mainwindows/mdi/mdichild.cpp
index 006c84574a..727d4f6cfd 100644
--- a/examples/widgets/mainwindows/mdi/mdichild.cpp
+++ b/examples/widgets/mainwindows/mdi/mdichild.cpp
@@ -82,9 +82,9 @@ bool MdiChild::loadFile(const QString &fileName)
}
QTextStream in(&file);
- QApplication::setOverrideCursor(Qt::WaitCursor);
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
setPlainText(in.readAll());
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
setCurrentFile(fileName);
@@ -115,18 +115,27 @@ bool MdiChild::saveAs()
bool MdiChild::saveFile(const QString &fileName)
{
- QFile file(fileName);
- if (!file.open(QFile::WriteOnly | QFile::Text)) {
- QMessageBox::warning(this, tr("MDI"),
- tr("Cannot write file %1:\n%2.")
- .arg(QDir::toNativeSeparators(fileName), file.errorString()));
- return false;
+ QString errorMessage;
+
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
+ QSaveFile file(fileName);
+ if (file.open(QFile::WriteOnly | QFile::Text)) {
+ QTextStream out(&file);
+ out << toPlainText();
+ if (!file.commit()) {
+ errorMessage = tr("Cannot write file %1:\n%2.")
+ .arg(QDir::toNativeSeparators(fileName), file.errorString());
+ }
+ } else {
+ errorMessage = tr("Cannot open file %1 for writing:\n%2.")
+ .arg(QDir::toNativeSeparators(fileName), file.errorString());
}
+ QGuiApplication::restoreOverrideCursor();
- QTextStream out(&file);
- QApplication::setOverrideCursor(Qt::WaitCursor);
- out << toPlainText();
- QApplication::restoreOverrideCursor();
+ if (!errorMessage.isEmpty()) {
+ QMessageBox::warning(this, tr("MDI"), errorMessage);
+ return false;
+ }
setCurrentFile(fileName);
return true;
diff --git a/examples/widgets/mainwindows/menus/mainwindow.cpp b/examples/widgets/mainwindows/menus/mainwindow.cpp
index 600b04fdb2..c6aba8be83 100644
--- a/examples/widgets/mainwindows/menus/mainwindow.cpp
+++ b/examples/widgets/mainwindows/menus/mainwindow.cpp
@@ -72,7 +72,7 @@ MainWindow::MainWindow()
bottomFiller->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QVBoxLayout *layout = new QVBoxLayout;
- layout->setMargin(5);
+ layout->setContentsMargins(5, 5, 5, 5);
layout->addWidget(topFiller);
layout->addWidget(infoLabel);
layout->addWidget(bottomFiller);
diff --git a/examples/widgets/mainwindows/sdi/main.cpp b/examples/widgets/mainwindows/sdi/main.cpp
index 6e29fafd6f..7a18c0c39c 100644
--- a/examples/widgets/mainwindows/sdi/main.cpp
+++ b/examples/widgets/mainwindows/sdi/main.cpp
@@ -68,7 +68,8 @@ int main(int argc, char *argv[])
parser.process(app);
MainWindow *mainWin = nullptr;
- foreach (const QString &file, parser.positionalArguments()) {
+ const QStringList posArgs = parser.positionalArguments();
+ for (const QString &file : posArgs) {
MainWindow *newWin = new MainWindow(file);
newWin->tile(mainWin);
newWin->show();
diff --git a/examples/widgets/mainwindows/sdi/mainwindow.cpp b/examples/widgets/mainwindows/sdi/mainwindow.cpp
index 301c85c144..a1fb42158e 100644
--- a/examples/widgets/mainwindows/sdi/mainwindow.cpp
+++ b/examples/widgets/mainwindows/sdi/mainwindow.cpp
@@ -338,9 +338,9 @@ void MainWindow::loadFile(const QString &fileName)
}
QTextStream in(&file);
- QApplication::setOverrideCursor(Qt::WaitCursor);
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
textEdit->setPlainText(in.readAll());
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
setCurrentFile(fileName);
statusBar()->showMessage(tr("File loaded"), 2000);
@@ -425,18 +425,27 @@ void MainWindow::openRecentFile()
bool MainWindow::saveFile(const QString &fileName)
{
- QFile file(fileName);
- if (!file.open(QFile::WriteOnly | QFile::Text)) {
- QMessageBox::warning(this, tr("SDI"),
- tr("Cannot write file %1:\n%2.")
- .arg(QDir::toNativeSeparators(fileName), file.errorString()));
- return false;
+ QString errorMessage;
+
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
+ QSaveFile file(fileName);
+ if (file.open(QFile::WriteOnly | QFile::Text)) {
+ QTextStream out(&file);
+ out << textEdit->toPlainText();
+ if (!file.commit()) {
+ errorMessage = tr("Cannot write file %1:\n%2.")
+ .arg(QDir::toNativeSeparators(fileName), file.errorString());
+ }
+ } else {
+ errorMessage = tr("Cannot open file %1 for writing:\n%2.")
+ .arg(QDir::toNativeSeparators(fileName), file.errorString());
}
+ QGuiApplication::restoreOverrideCursor();
- QTextStream out(&file);
- QApplication::setOverrideCursor(Qt::WaitCursor);
- out << textEdit->toPlainText();
- QApplication::restoreOverrideCursor();
+ if (!errorMessage.isEmpty()) {
+ QMessageBox::warning(this, tr("SDI"), errorMessage);
+ return false;
+ }
setCurrentFile(fileName);
statusBar()->showMessage(tr("File saved"), 2000);
@@ -472,11 +481,12 @@ MainWindow *MainWindow::findMainWindow(const QString &fileName) const
{
QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();
- foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ const QList<QWidget *> topLevelWidgets = QApplication::topLevelWidgets();
+ for (QWidget *widget : topLevelWidgets) {
MainWindow *mainWin = qobject_cast<MainWindow *>(widget);
if (mainWin && mainWin->curFile == canonicalFilePath)
return mainWin;
}
- return 0;
+ return nullptr;
}
diff --git a/examples/widgets/painting/affine/main.cpp b/examples/widgets/painting/affine/main.cpp
index a820c784f0..6ce8efe482 100644
--- a/examples/widgets/painting/affine/main.cpp
+++ b/examples/widgets/painting/affine/main.cpp
@@ -58,12 +58,12 @@ int main(int argc, char **argv)
QApplication app(argc, argv);
- XFormWidget xformWidget(0);
- QStyle *arthurStyle = new ArthurStyle();
+ XFormWidget xformWidget(nullptr);
+ QStyle *arthurStyle = new ArthurStyle;
xformWidget.setStyle(arthurStyle);
- QList<QWidget *> widgets = xformWidget.findChildren<QWidget *>();
- foreach (QWidget *w, widgets) {
+ const QList<QWidget *> widgets = xformWidget.findChildren<QWidget *>();
+ for (QWidget *w : widgets) {
w->setStyle(arthurStyle);
w->setAttribute(Qt::WA_AcceptTouchEvents);
}
diff --git a/examples/widgets/painting/affine/xform.cpp b/examples/widgets/painting/affine/xform.cpp
index dc01acf453..482e0f3268 100644
--- a/examples/widgets/painting/affine/xform.cpp
+++ b/examples/widgets/painting/affine/xform.cpp
@@ -160,10 +160,7 @@ void XFormView::updateCtrlPoints(const QPolygonF &points)
ctrlPoints = points;
QLineF line(ctrlPoints.at(0), ctrlPoints.at(1));
- m_rotation = line.angle(QLineF(0, 0, 1, 0));
- if (line.dy() < 0)
- m_rotation = 360 - m_rotation;
-
+ m_rotation = 360 - QLineF(0, 0, 1, 0).angleTo(line);
if (trans.isNull())
emit rotationChanged(int(m_rotation*10));
}
diff --git a/examples/widgets/painting/basicdrawing/window.cpp b/examples/widgets/painting/basicdrawing/window.cpp
index c80237e914..65f6971d13 100644
--- a/examples/widgets/painting/basicdrawing/window.cpp
+++ b/examples/widgets/painting/basicdrawing/window.cpp
@@ -157,22 +157,22 @@ Window::Window()
//! [7]
//! [8]
- connect(shapeComboBox, SIGNAL(activated(int)),
- this, SLOT(shapeChanged()));
- connect(penWidthSpinBox, SIGNAL(valueChanged(int)),
- this, SLOT(penChanged()));
- connect(penStyleComboBox, SIGNAL(activated(int)),
- this, SLOT(penChanged()));
- connect(penCapComboBox, SIGNAL(activated(int)),
- this, SLOT(penChanged()));
- connect(penJoinComboBox, SIGNAL(activated(int)),
- this, SLOT(penChanged()));
- connect(brushStyleComboBox, SIGNAL(activated(int)),
- this, SLOT(brushChanged()));
- connect(antialiasingCheckBox, SIGNAL(toggled(bool)),
- renderArea, SLOT(setAntialiased(bool)));
- connect(transformationsCheckBox, SIGNAL(toggled(bool)),
- renderArea, SLOT(setTransformed(bool)));
+ connect(shapeComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::shapeChanged);
+ connect(penWidthSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ this, &Window::penChanged);
+ connect(penStyleComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::penChanged);
+ connect(penCapComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::penChanged);
+ connect(penJoinComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::penChanged);
+ connect(brushStyleComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::brushChanged);
+ connect(antialiasingCheckBox, &QAbstractButton::toggled,
+ renderArea, &RenderArea::setAntialiased);
+ connect(transformationsCheckBox, &QAbstractButton::toggled,
+ renderArea, &RenderArea::setTransformed);
//! [8]
//! [9]
diff --git a/examples/widgets/painting/composition/composition.cpp b/examples/widgets/painting/composition/composition.cpp
index e0abc5875c..a220fb42fa 100644
--- a/examples/widgets/painting/composition/composition.cpp
+++ b/examples/widgets/painting/composition/composition.cpp
@@ -76,68 +76,68 @@ CompositionWidget::CompositionWidget(QWidget *parent)
modesGroup->setTitle(tr("Mode"));
rbClear = new QRadioButton(tr("Clear"), modesGroup);
- connect(rbClear, SIGNAL(clicked()), view, SLOT(setClearMode()));
+ connect(rbClear, &QAbstractButton::clicked, view, &CompositionRenderer::setClearMode);
rbSource = new QRadioButton(tr("Source"), modesGroup);
- connect(rbSource, SIGNAL(clicked()), view, SLOT(setSourceMode()));
+ connect(rbSource, &QAbstractButton::clicked, view, &CompositionRenderer::setSourceMode);
rbDest = new QRadioButton(tr("Destination"), modesGroup);
- connect(rbDest, SIGNAL(clicked()), view, SLOT(setDestMode()));
+ connect(rbDest, &QAbstractButton::clicked, view, &CompositionRenderer::setDestMode);
rbSourceOver = new QRadioButton(tr("Source Over"), modesGroup);
- connect(rbSourceOver, SIGNAL(clicked()), view, SLOT(setSourceOverMode()));
+ connect(rbSourceOver, &QAbstractButton::clicked, view, &CompositionRenderer::setSourceOverMode);
rbDestOver = new QRadioButton(tr("Destination Over"), modesGroup);
- connect(rbDestOver, SIGNAL(clicked()), view, SLOT(setDestOverMode()));
+ connect(rbDestOver, &QAbstractButton::clicked, view, &CompositionRenderer::setDestOverMode);
rbSourceIn = new QRadioButton(tr("Source In"), modesGroup);
- connect(rbSourceIn, SIGNAL(clicked()), view, SLOT(setSourceInMode()));
+ connect(rbSourceIn, &QAbstractButton::clicked, view, &CompositionRenderer::setSourceInMode);
rbDestIn = new QRadioButton(tr("Dest In"), modesGroup);
- connect(rbDestIn, SIGNAL(clicked()), view, SLOT(setDestInMode()));
+ connect(rbDestIn, &QAbstractButton::clicked, view, &CompositionRenderer::setDestInMode);
rbSourceOut = new QRadioButton(tr("Source Out"), modesGroup);
- connect(rbSourceOut, SIGNAL(clicked()), view, SLOT(setSourceOutMode()));
+ connect(rbSourceOut, &QAbstractButton::clicked, view, &CompositionRenderer::setSourceOutMode);
rbDestOut = new QRadioButton(tr("Dest Out"), modesGroup);
- connect(rbDestOut, SIGNAL(clicked()), view, SLOT(setDestOutMode()));
+ connect(rbDestOut, &QAbstractButton::clicked, view, &CompositionRenderer::setDestOutMode);
rbSourceAtop = new QRadioButton(tr("Source Atop"), modesGroup);
- connect(rbSourceAtop, SIGNAL(clicked()), view, SLOT(setSourceAtopMode()));
+ connect(rbSourceAtop, &QAbstractButton::clicked, view, &CompositionRenderer::setSourceAtopMode);
rbDestAtop = new QRadioButton(tr("Dest Atop"), modesGroup);
- connect(rbDestAtop, SIGNAL(clicked()), view, SLOT(setDestAtopMode()));
+ connect(rbDestAtop, &QAbstractButton::clicked, view, &CompositionRenderer::setDestAtopMode);
rbXor = new QRadioButton(tr("Xor"), modesGroup);
- connect(rbXor, SIGNAL(clicked()), view, SLOT(setXorMode()));
+ connect(rbXor, &QAbstractButton::clicked, view, &CompositionRenderer::setXorMode);
rbPlus = new QRadioButton(tr("Plus"), modesGroup);
- connect(rbPlus, SIGNAL(clicked()), view, SLOT(setPlusMode()));
+ connect(rbPlus, &QAbstractButton::clicked, view, &CompositionRenderer::setPlusMode);
rbMultiply = new QRadioButton(tr("Multiply"), modesGroup);
- connect(rbMultiply, SIGNAL(clicked()), view, SLOT(setMultiplyMode()));
+ connect(rbMultiply, &QAbstractButton::clicked, view, &CompositionRenderer::setMultiplyMode);
rbScreen = new QRadioButton(tr("Screen"), modesGroup);
- connect(rbScreen, SIGNAL(clicked()), view, SLOT(setScreenMode()));
+ connect(rbScreen, &QAbstractButton::clicked, view, &CompositionRenderer::setScreenMode);
rbOverlay = new QRadioButton(tr("Overlay"), modesGroup);
- connect(rbOverlay, SIGNAL(clicked()), view, SLOT(setOverlayMode()));
+ connect(rbOverlay, &QAbstractButton::clicked, view, &CompositionRenderer::setOverlayMode);
rbDarken = new QRadioButton(tr("Darken"), modesGroup);
- connect(rbDarken, SIGNAL(clicked()), view, SLOT(setDarkenMode()));
+ connect(rbDarken, &QAbstractButton::clicked, view, &CompositionRenderer::setDarkenMode);
rbLighten = new QRadioButton(tr("Lighten"), modesGroup);
- connect(rbLighten, SIGNAL(clicked()), view, SLOT(setLightenMode()));
+ connect(rbLighten, &QAbstractButton::clicked, view, &CompositionRenderer::setLightenMode);
rbColorDodge = new QRadioButton(tr("Color Dodge"), modesGroup);
- connect(rbColorDodge, SIGNAL(clicked()), view, SLOT(setColorDodgeMode()));
+ connect(rbColorDodge, &QAbstractButton::clicked, view, &CompositionRenderer::setColorDodgeMode);
rbColorBurn = new QRadioButton(tr("Color Burn"), modesGroup);
- connect(rbColorBurn, SIGNAL(clicked()), view, SLOT(setColorBurnMode()));
+ connect(rbColorBurn, &QAbstractButton::clicked, view, &CompositionRenderer::setColorBurnMode);
rbHardLight = new QRadioButton(tr("Hard Light"), modesGroup);
- connect(rbHardLight, SIGNAL(clicked()), view, SLOT(setHardLightMode()));
+ connect(rbHardLight, &QAbstractButton::clicked, view, &CompositionRenderer::setHardLightMode);
rbSoftLight = new QRadioButton(tr("Soft Light"), modesGroup);
- connect(rbSoftLight, SIGNAL(clicked()), view, SLOT(setSoftLightMode()));
+ connect(rbSoftLight, &QAbstractButton::clicked, view, &CompositionRenderer::setSoftLightMode);
rbDifference = new QRadioButton(tr("Difference"), modesGroup);
- connect(rbDifference, SIGNAL(clicked()), view, SLOT(setDifferenceMode()));
+ connect(rbDifference, &QAbstractButton::clicked, view, &CompositionRenderer::setDifferenceMode);
rbExclusion = new QRadioButton(tr("Exclusion"), modesGroup);
- connect(rbExclusion, SIGNAL(clicked()), view, SLOT(setExclusionMode()));
+ connect(rbExclusion, &QAbstractButton::clicked, view, &CompositionRenderer::setExclusionMode);
QGroupBox *circleColorGroup = new QGroupBox(mainGroup);
circleColorGroup->setTitle(tr("Circle color"));
QSlider *circleColorSlider = new QSlider(Qt::Horizontal, circleColorGroup);
circleColorSlider->setRange(0, 359);
circleColorSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
- connect(circleColorSlider, SIGNAL(valueChanged(int)), view, SLOT(setCircleColor(int)));
+ connect(circleColorSlider, &QAbstractSlider::valueChanged, view, &CompositionRenderer::setCircleColor);
QGroupBox *circleAlphaGroup = new QGroupBox(mainGroup);
circleAlphaGroup->setTitle(tr("Circle alpha"));
QSlider *circleAlphaSlider = new QSlider(Qt::Horizontal, circleAlphaGroup);
circleAlphaSlider->setRange(0, 255);
circleAlphaSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
- connect(circleAlphaSlider, SIGNAL(valueChanged(int)), view, SLOT(setCircleAlpha(int)));
+ connect(circleAlphaSlider, &QAbstractSlider::valueChanged, view, &CompositionRenderer::setCircleAlpha);
QPushButton *showSourceButton = new QPushButton(mainGroup);
showSourceButton->setText(tr("Show Source"));
@@ -209,13 +209,13 @@ CompositionWidget::CompositionWidget(QWidget *parent)
view->loadDescription(":res/composition/composition.html");
view->loadSourceFile(":res/composition/composition.cpp");
- connect(whatsThisButton, SIGNAL(clicked(bool)), view, SLOT(setDescriptionEnabled(bool)));
- connect(view, SIGNAL(descriptionEnabledChanged(bool)), whatsThisButton, SLOT(setChecked(bool)));
- connect(showSourceButton, SIGNAL(clicked()), view, SLOT(showSource()));
+ connect(whatsThisButton, &QAbstractButton::clicked, view, &ArthurFrame::setDescriptionEnabled);
+ connect(view, &ArthurFrame::descriptionEnabledChanged, whatsThisButton, &QAbstractButton::setChecked);
+ connect(showSourceButton, &QAbstractButton::clicked, view, &ArthurFrame::showSource);
#if QT_CONFIG(opengl)
- connect(enableOpenGLButton, SIGNAL(clicked(bool)), view, SLOT(enableOpenGL(bool)));
+ connect(enableOpenGLButton, &QAbstractButton::clicked, view, &ArthurFrame::enableOpenGL);
#endif
- connect(animateButton, SIGNAL(toggled(bool)), view, SLOT(setAnimationEnabled(bool)));
+ connect(animateButton, &QAbstractButton::toggled, view, &CompositionRenderer::setAnimationEnabled);
circleColorSlider->setValue(270);
circleAlphaSlider->setValue(200);
@@ -224,6 +224,10 @@ CompositionWidget::CompositionWidget(QWidget *parent)
setWindowTitle(tr("Composition Modes"));
}
+CompositionWidget::~CompositionWidget()
+{
+}
+
void CompositionWidget::nextMode()
{
@@ -265,6 +269,10 @@ CompositionRenderer::CompositionRenderer(QWidget *parent)
#endif
}
+CompositionRenderer::~CompositionRenderer()
+{
+}
+
QRectF rectangle_around(const QPointF &p, const QSizeF &size = QSize(250, 200))
{
QRectF rect(p, size);
@@ -341,9 +349,9 @@ void CompositionRenderer::drawSource(QPainter &p)
QRectF circle_rect = rectangle_around(m_circle_pos);
QColor color = QColor::fromHsvF(m_circle_hue / 360.0, 1, 1, m_circle_alpha / 255.0);
QLinearGradient circle_gradient(circle_rect.topLeft(), circle_rect.bottomRight());
- circle_gradient.setColorAt(0, color.light());
+ circle_gradient.setColorAt(0, color.lighter());
circle_gradient.setColorAt(0.5, color);
- circle_gradient.setColorAt(1, color.dark());
+ circle_gradient.setColorAt(1, color.darker());
p.setBrush(circle_gradient);
p.drawEllipse(circle_rect);
@@ -371,7 +379,7 @@ void CompositionRenderer::paint(QPainter *painter)
if (size() != m_previous_size) {
m_previous_size = size();
- QPainter p(m_fbo.data());
+ QPainter p(m_fbo.get());
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(QRect(QPoint(0, 0), size()), Qt::transparent);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
@@ -382,7 +390,7 @@ void CompositionRenderer::paint(QPainter *painter)
painter->beginNativePainting();
{
- QPainter p(m_fbo.data());
+ QPainter p(m_fbo.get());
p.beginNativePainting();
m_blitter.bind();
const QRect targetRect(QPoint(0, 0), m_fbo->size());
diff --git a/examples/widgets/painting/composition/composition.h b/examples/widgets/painting/composition/composition.h
index 19150e2024..52ca7919b0 100644
--- a/examples/widgets/painting/composition/composition.h
+++ b/examples/widgets/painting/composition/composition.h
@@ -61,6 +61,8 @@
#include <QPainter>
#include <QEvent>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QPushButton;
class QRadioButton;
@@ -71,7 +73,8 @@ class CompositionWidget : public QWidget
Q_OBJECT
public:
- CompositionWidget(QWidget *parent);
+ explicit CompositionWidget(QWidget *parent = nullptr);
+ ~CompositionWidget();
public slots:
void nextMode();
@@ -117,7 +120,8 @@ class CompositionRenderer : public ArthurFrame
Q_PROPERTY(bool animation READ animationEnabled WRITE setAnimationEnabled)
public:
- CompositionRenderer(QWidget *parent);
+ explicit CompositionRenderer(QWidget *parent = nullptr);
+ ~CompositionRenderer();
void paint(QPainter *) override;
@@ -188,7 +192,7 @@ private:
int m_animationTimer;
#if QT_CONFIG(opengl)
- QScopedPointer<QFboPaintDevice> m_fbo;
+ std::unique_ptr<QFboPaintDevice> m_fbo;
int m_pbuffer_size; // width==height==size of pbuffer
uint m_base_tex;
uint m_compositing_tex;
diff --git a/examples/widgets/painting/composition/main.cpp b/examples/widgets/painting/composition/main.cpp
index 1f4ead7165..1ffa29dddc 100644
--- a/examples/widgets/painting/composition/main.cpp
+++ b/examples/widgets/painting/composition/main.cpp
@@ -56,13 +56,13 @@ int main(int argc, char *argv[])
{
QApplication app(argc, argv);
+ QScopedPointer<QStyle> arthurStyle(new ArthurStyle());
CompositionWidget compWidget(nullptr);
- QStyle *arthurStyle = new ArthurStyle();
- compWidget.setStyle(arthurStyle);
+ compWidget.setStyle(arthurStyle.data());
- QList<QWidget *> widgets = compWidget.findChildren<QWidget *>();
- foreach (QWidget *w, widgets)
- w->setStyle(arthurStyle);
+ const QList<QWidget *> widgets = compWidget.findChildren<QWidget *>();
+ for (QWidget *w : widgets)
+ w->setStyle(arthurStyle.data());
compWidget.show();
return app.exec();
diff --git a/examples/widgets/painting/concentriccircles/window.cpp b/examples/widgets/painting/concentriccircles/window.cpp
index 0f65dc2285..45258e0bc4 100644
--- a/examples/widgets/painting/concentriccircles/window.cpp
+++ b/examples/widgets/painting/concentriccircles/window.cpp
@@ -77,8 +77,8 @@ Window::Window()
circleWidgets[i][j]->setAntialiased(j != 0);
circleWidgets[i][j]->setFloatBased(i != 0);
- connect(timer, SIGNAL(timeout()),
- circleWidgets[i][j], SLOT(nextAnimationFrame()));
+ connect(timer, &QTimer::timeout,
+ circleWidgets[i][j], &CircleWidget::nextAnimationFrame);
layout->addWidget(circleWidgets[i][j], i + 1, j + 1);
}
diff --git a/examples/widgets/painting/deform/main.cpp b/examples/widgets/painting/deform/main.cpp
index 85e83207c0..28e3d6823d 100644
--- a/examples/widgets/painting/deform/main.cpp
+++ b/examples/widgets/painting/deform/main.cpp
@@ -60,12 +60,12 @@ int main(int argc, char **argv)
bool smallScreen = QApplication::arguments().contains("-small-screen");
- PathDeformWidget deformWidget(0, smallScreen);
+ PathDeformWidget deformWidget(nullptr, smallScreen);
- QStyle *arthurStyle = new ArthurStyle();
+ QStyle *arthurStyle = new ArthurStyle;
deformWidget.setStyle(arthurStyle);
- QList<QWidget *> widgets = deformWidget.findChildren<QWidget *>();
- foreach (QWidget *w, widgets)
+ const QList<QWidget *> widgets = deformWidget.findChildren<QWidget *>();
+ for (QWidget *w : widgets)
w->setStyle(arthurStyle);
if (smallScreen)
diff --git a/examples/widgets/painting/deform/pathdeform.cpp b/examples/widgets/painting/deform/pathdeform.cpp
index 7c3fe45277..64e81f8cab 100644
--- a/examples/widgets/painting/deform/pathdeform.cpp
+++ b/examples/widgets/painting/deform/pathdeform.cpp
@@ -150,21 +150,21 @@ void PathDeformControls::layoutForDesktop()
QVBoxLayout * mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(mainGroup);
- mainLayout->setMargin(0);
+ mainLayout->setContentsMargins(QMargins());
- connect(radiusSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setRadius(int)));
- connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int)));
- connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int)));
- connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool)));
+ connect(radiusSlider, &QAbstractSlider::valueChanged, m_renderer, &PathDeformRenderer::setRadius);
+ connect(deformSlider, &QAbstractSlider::valueChanged, m_renderer, &PathDeformRenderer::setIntensity);
+ connect(fontSizeSlider, &QAbstractSlider::valueChanged, m_renderer, &PathDeformRenderer::setFontSize);
+ connect(animateButton, &QAbstractButton::clicked, m_renderer, &PathDeformRenderer::setAnimated);
#if QT_CONFIG(opengl)
- connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
+ connect(enableOpenGLButton, &QAbstractButton::clicked, m_renderer, &ArthurFrame::enableOpenGL);
#endif
- connect(textInput, SIGNAL(textChanged(QString)), m_renderer, SLOT(setText(QString)));
- connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)),
- whatsThisButton, SLOT(setChecked(bool)));
- connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool)));
- connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource()));
+ connect(textInput, &QLineEdit::textChanged, m_renderer, &PathDeformRenderer::setText);
+ connect(m_renderer, &ArthurFrame::descriptionEnabledChanged,
+ whatsThisButton, &QAbstractButton::setChecked);
+ connect(whatsThisButton, &QAbstractButton::clicked, m_renderer, &ArthurFrame::setDescriptionEnabled);
+ connect(showSourceButton, &QAbstractButton::clicked, m_renderer, &ArthurFrame::showSource);
animateButton->animateClick();
deformSlider->setValue(80);
@@ -211,7 +211,7 @@ void PathDeformControls::layoutForSmallScreen()
QGridLayout *mainGroupLayout = new QGridLayout(mainGroup);
- mainGroupLayout->setMargin(0);
+ mainGroupLayout->setContentsMargins(QMargins());
mainGroupLayout->addWidget(radiusLabel, 0, 0, Qt::AlignRight);
mainGroupLayout->addWidget(radiusSlider, 0, 1);
mainGroupLayout->addWidget(deformLabel, 1, 0, Qt::AlignRight);
@@ -229,14 +229,14 @@ void PathDeformControls::layoutForSmallScreen()
mainLayout->addWidget(okButton);
mainLayout->addWidget(quitButton);
- connect(quitButton, SIGNAL(clicked()), this, SIGNAL(quitPressed()));
- connect(okButton, SIGNAL(clicked()), this, SIGNAL(okPressed()));
- connect(radiusSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setRadius(int)));
- connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int)));
- connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int)));
- connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool)));
+ connect(quitButton, &QAbstractButton::clicked, this, &PathDeformControls::quitPressed);
+ connect(okButton, &QAbstractButton::clicked, this, &PathDeformControls::okPressed);
+ connect(radiusSlider, &QAbstractSlider::valueChanged, m_renderer, &PathDeformRenderer::setRadius);
+ connect(deformSlider, &QAbstractSlider::valueChanged, m_renderer, &PathDeformRenderer::setIntensity);
+ connect(fontSizeSlider, &QAbstractSlider::valueChanged, m_renderer, &PathDeformRenderer::setFontSize);
+ connect(animateButton, &QAbstractButton::clicked, m_renderer, &PathDeformRenderer::setAnimated);
#if QT_CONFIG(opengl)
- connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
+ connect(enableOpenGLButton, &QAbstractButton::clicked, m_renderer, &ArthurFrame::enableOpenGL);
#endif
@@ -272,9 +272,12 @@ PathDeformWidget::PathDeformWidget(QWidget *parent, bool smallScreen)
m_renderer->loadDescription(":res/deform/pathdeform.html");
m_renderer->setDescriptionEnabled(false);
- connect(m_renderer, SIGNAL(clicked()), this, SLOT(showControls()));
- connect(m_controls, SIGNAL(okPressed()), this, SLOT(hideControls()));
- connect(m_controls, SIGNAL(quitPressed()), QCoreApplication::instance(), SLOT(quit()));
+ connect(m_renderer, &PathDeformRenderer::clicked,
+ this, &PathDeformWidget::showControls);
+ connect(m_controls, &PathDeformControls::okPressed,
+ this, &PathDeformWidget::hideControls);
+ connect(m_controls, &PathDeformControls::quitPressed,
+ qApp, &QCoreApplication::quit);
}
@@ -288,16 +291,16 @@ void PathDeformWidget::hideControls()
m_controls->hide();
}
-void PathDeformWidget::setStyle( QStyle * style )
+void PathDeformWidget::setStyle(QStyle *style)
{
QWidget::setStyle(style);
- if (m_controls == 0)
+ if (!m_controls)
return;
m_controls->setStyle(style);
- QList<QWidget *> widgets = m_controls->findChildren<QWidget *>();
- foreach (QWidget *w, widgets)
+ const QList<QWidget *> widgets = m_controls->findChildren<QWidget *>();
+ for (QWidget *w : widgets)
w->setStyle(style);
}
diff --git a/examples/widgets/painting/deform/pathdeform.h b/examples/widgets/painting/deform/pathdeform.h
index 68908045b9..af869badc9 100644
--- a/examples/widgets/painting/deform/pathdeform.h
+++ b/examples/widgets/painting/deform/pathdeform.h
@@ -54,7 +54,7 @@
#include "arthurwidgets.h"
#include <QBasicTimer>
-#include <QDateTime>
+#include <QElapsedTimer>
#include <QPainterPath>
class PathDeformRenderer : public ArthurFrame
@@ -103,7 +103,7 @@ private:
QBasicTimer m_repaintTimer;
// QBasicTimer m_fpsTimer;
// int m_fpsCounter;
- QTime m_repaintTracker;
+ QElapsedTimer m_repaintTracker;
QVector<QPainterPath> m_paths;
QVector<QPointF> m_advances;
@@ -135,7 +135,7 @@ signals:
void okPressed();
void quitPressed();
private:
- PathDeformRenderer* m_renderer;
+ PathDeformRenderer *m_renderer;
void layoutForDesktop();
void layoutForSmallScreen();
};
@@ -145,7 +145,7 @@ class PathDeformWidget : public QWidget
Q_OBJECT
public:
PathDeformWidget(QWidget *parent, bool smallScreen);
- void setStyle (QStyle * style );
+ void setStyle(QStyle *style);
private:
PathDeformRenderer *m_renderer;
diff --git a/examples/widgets/painting/fontsampler/mainwindow.cpp b/examples/widgets/painting/fontsampler/mainwindow.cpp
index bd15438df9..b3304b4b6d 100644
--- a/examples/widgets/painting/fontsampler/mainwindow.cpp
+++ b/examples/widgets/painting/fontsampler/mainwindow.cpp
@@ -71,13 +71,14 @@ MainWindow::MainWindow(QWidget *parent)
markedCount = 0;
setupFontTree();
- connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
- connect(fontTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
- this, SLOT(showFont(QTreeWidgetItem*)));
- connect(fontTree, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
- this, SLOT(updateStyles(QTreeWidgetItem*,int)));
-
- fontTree->setItemSelected(fontTree->topLevelItem(0), true);
+ connect(quitAction, &QAction::triggered,
+ qApp, &QApplication::quit);
+ connect(fontTree, &QTreeWidget::currentItemChanged,
+ this, &MainWindow::showFont);
+ connect(fontTree, &QTreeWidget::itemChanged,
+ this, &MainWindow::updateStyles);
+
+ fontTree->topLevelItem(0)->setSelected(true);
showFont(fontTree->topLevelItem(0));
}
@@ -85,9 +86,10 @@ void MainWindow::setupFontTree()
{
QFontDatabase database;
fontTree->setColumnCount(1);
- fontTree->setHeaderLabels(QStringList() << tr("Font"));
+ fontTree->setHeaderLabels({ tr("Font") });
- foreach (QString family, database.families()) {
+ const QStringList fontFamilies = database.families();
+ for (const QString &family : fontFamilies) {
const QStringList styles = database.styles(family);
if (styles.isEmpty())
continue;
@@ -97,7 +99,7 @@ void MainWindow::setupFontTree()
familyItem->setCheckState(0, Qt::Unchecked);
familyItem->setFlags(familyItem->flags() | Qt::ItemIsAutoTristate);
- foreach (QString style, styles) {
+ for (const QString &style : styles) {
QTreeWidgetItem *styleItem = new QTreeWidgetItem(familyItem);
styleItem->setText(0, style);
styleItem->setCheckState(0, Qt::Unchecked);
@@ -109,10 +111,10 @@ void MainWindow::setupFontTree()
void MainWindow::on_clearAction_triggered()
{
- QTreeWidgetItem *currentItem = fontTree->currentItem();
- foreach (QTreeWidgetItem *item, fontTree->selectedItems())
- fontTree->setItemSelected(item, false);
- fontTree->setItemSelected(currentItem, true);
+ const QList<QTreeWidgetItem *> items = fontTree->selectedItems();
+ for (QTreeWidgetItem *item : items)
+ item->setSelected(false);
+ fontTree->currentItem()->setSelected(true);
}
void MainWindow::on_markAction_triggered()
@@ -127,8 +129,8 @@ void MainWindow::on_unmarkAction_triggered()
void MainWindow::markUnmarkFonts(Qt::CheckState state)
{
- QList<QTreeWidgetItem *> items = fontTree->selectedItems();
- foreach (QTreeWidgetItem *item, items) {
+ const QList<QTreeWidgetItem *> items = fontTree->selectedItems();
+ for (QTreeWidgetItem *item : items) {
if (item->checkState(0) != state)
item->setCheckState(0, state);
}
@@ -285,8 +287,8 @@ void MainWindow::on_printPreviewAction_triggered()
QPrinter printer(QPrinter::HighResolution);
QPrintPreviewDialog preview(&printer, this);
- connect(&preview, SIGNAL(paintRequested(QPrinter*)),
- this, SLOT(printDocument(QPrinter*)));
+ connect(&preview, &QPrintPreviewDialog::paintRequested,
+ this, &MainWindow::printDocument);
preview.exec();
#endif
}
@@ -294,19 +296,19 @@ void MainWindow::on_printPreviewAction_triggered()
void MainWindow::printPage(int index, QPainter *painter, QPrinter *printer)
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
- QString family = pageMap.keys()[index];
- StyleItems items = pageMap[family];
+ const QString family = (pageMap.begin() + index).key();
+ const StyleItems items = pageMap.value(family);
// Find the dimensions of the text on each page.
qreal width = 0.0;
qreal height = 0.0;
- foreach (QTreeWidgetItem *item, items) {
+ for (const QTreeWidgetItem *item : items) {
QString style = item->text(0);
int weight = item->data(0, Qt::UserRole).toInt();
bool italic = item->data(0, Qt::UserRole + 1).toBool();
// Calculate the maximum width and total height of the text.
- foreach (int size, sampleSizes) {
+ for (int size : qAsConst(sampleSizes)) {
QFont font(family, size, weight, italic);
font.setStyleName(style);
font = QFont(font, painter->device());
@@ -334,13 +336,13 @@ void MainWindow::printPage(int index, QPainter *painter, QPrinter *printer)
qreal x = -width / 2.0;
qreal y = -height / 2.0 - remainingHeight / 4.0 + spaceHeight;
- foreach (QTreeWidgetItem *item, items) {
+ for (const QTreeWidgetItem *item : items) {
QString style = item->text(0);
int weight = item->data(0, Qt::UserRole).toInt();
bool italic = item->data(0, Qt::UserRole + 1).toBool();
// Draw each line of text.
- foreach (int size, sampleSizes) {
+ for (int size : qAsConst(sampleSizes)) {
QFont font(family, size, weight, italic);
font.setStyleName(style);
font = QFont(font, painter->device());
diff --git a/examples/widgets/painting/gradients/gradients.cpp b/examples/widgets/painting/gradients/gradients.cpp
index 004f6710cd..a4528ce06f 100644
--- a/examples/widgets/painting/gradients/gradients.cpp
+++ b/examples/widgets/painting/gradients/gradients.cpp
@@ -72,7 +72,7 @@ ShadeWidget::ShadeWidget(ShadeType type, QWidget *parent)
setPalette(pal);
} else {
- setAttribute(Qt::WA_NoBackground);
+ setAttribute(Qt::WA_OpaquePaintEvent);
}
QPolygonF points;
@@ -180,7 +180,7 @@ GradientEditor::GradientEditor(QWidget *parent)
{
QVBoxLayout *vbox = new QVBoxLayout(this);
vbox->setSpacing(1);
- vbox->setMargin(1);
+ vbox->setContentsMargins(1, 1, 1, 1);
m_red_shade = new ShadeWidget(ShadeWidget::RedShade, this);
m_green_shade = new ShadeWidget(ShadeWidget::GreenShade, this);
@@ -421,7 +421,7 @@ GradientWidget::GradientWidget(QWidget *parent)
m_renderer->loadSourceFile(":res/gradients/gradients.cpp");
m_renderer->loadDescription(":res/gradients/gradients.html");
- QTimer::singleShot(50, this, SLOT(setDefault1()));
+ QTimer::singleShot(50, this, &GradientWidget::setDefault1);
}
void GradientWidget::setDefault(int config)
@@ -564,9 +564,7 @@ void GradientRenderer::paint(QPainter *p)
} else {
QLineF l(pts.at(0), pts.at(1));
- qreal angle = l.angle(QLineF(0, 0, 1, 0));
- if (l.dy() > 0)
- angle = 360 - angle;
+ qreal angle = QLineF(0, 0, 1, 0).angleTo(l);
g = QConicalGradient(pts.at(0), angle);
}
diff --git a/examples/widgets/painting/gradients/main.cpp b/examples/widgets/painting/gradients/main.cpp
index 6c5261fe6b..539d67e40e 100644
--- a/examples/widgets/painting/gradients/main.cpp
+++ b/examples/widgets/painting/gradients/main.cpp
@@ -61,8 +61,8 @@ int main(int argc, char *argv[])
GradientWidget gradientWidget(0);
QStyle *arthurStyle = new ArthurStyle();
gradientWidget.setStyle(arthurStyle);
- QList<QWidget *> widgets = gradientWidget.findChildren<QWidget *>();
- foreach (QWidget *w, widgets) {
+ const QList<QWidget *> widgets = gradientWidget.findChildren<QWidget *>();
+ for (QWidget *w : widgets) {
w->setStyle(arthurStyle);
w->setAttribute(Qt::WA_AcceptTouchEvents);
}
diff --git a/examples/widgets/painting/imagecomposition/imagecomposer.cpp b/examples/widgets/painting/imagecomposition/imagecomposer.cpp
index d53017b955..ffdc8f433c 100644
--- a/examples/widgets/painting/imagecomposition/imagecomposer.cpp
+++ b/examples/widgets/painting/imagecomposition/imagecomposer.cpp
@@ -100,9 +100,12 @@ ImageComposer::ImageComposer()
//! [2]
//! [3]
- connect(sourceButton, SIGNAL(clicked()), this, SLOT(chooseSource()));
- connect(operatorComboBox, SIGNAL(activated(int)), this, SLOT(recalculateResult()));
- connect(destinationButton, SIGNAL(clicked()), this, SLOT(chooseDestination()));
+ connect(sourceButton, &QAbstractButton::clicked,
+ this, &ImageComposer::chooseSource);
+ connect(operatorComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &ImageComposer::recalculateResult);
+ connect(destinationButton, &QAbstractButton::clicked,
+ this, &ImageComposer::chooseDestination);
//! [3]
//! [4]
diff --git a/examples/widgets/painting/painterpaths/window.cpp b/examples/widgets/painting/painterpaths/window.cpp
index a987937b39..6fb3218313 100644
--- a/examples/widgets/painting/painterpaths/window.cpp
+++ b/examples/widgets/painting/painterpaths/window.cpp
@@ -194,22 +194,30 @@ Window::Window()
//! [12]
//! [16]
- connect(fillRuleComboBox, SIGNAL(activated(int)), this, SLOT(fillRuleChanged()));
- connect(fillColor1ComboBox, SIGNAL(activated(int)), this, SLOT(fillGradientChanged()));
- connect(fillColor2ComboBox, SIGNAL(activated(int)), this, SLOT(fillGradientChanged()));
- connect(penColorComboBox, SIGNAL(activated(int)), this, SLOT(penColorChanged()));
-
- for(QList<RenderArea*>::iterator it = renderAreas.begin(); it != renderAreas.end(); it++) {
- connect(penWidthSpinBox, SIGNAL(valueChanged(int)), *it, SLOT(setPenWidth(int)));
- connect(rotationAngleSpinBox, SIGNAL(valueChanged(int)), *it, SLOT(setRotationAngle(int)));
+ connect(fillRuleComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::fillRuleChanged);
+ connect(fillColor1ComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::fillGradientChanged);
+ connect(fillColor2ComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::fillGradientChanged);
+ connect(penColorComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::penColorChanged);
+
+ for (RenderArea *area : qAsConst(renderAreas)) {
+ connect(penWidthSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ area, &RenderArea::setPenWidth);
+ connect(rotationAngleSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ area, &RenderArea::setRotationAngle);
}
//! [16] //! [17]
QGridLayout *topLayout = new QGridLayout;
- int i=0;
- for(QList<RenderArea*>::iterator it = renderAreas.begin(); it != renderAreas.end(); it++, i++)
- topLayout->addWidget(*it, i / 3, i % 3);
+ int i = 0;
+ for (RenderArea *area : qAsConst(renderAreas)) {
+ topLayout->addWidget(area, i / 3, i % 3);
+ ++i;
+ }
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addLayout(topLayout, 0, 0, 1, 4);
@@ -243,8 +251,8 @@ void Window::fillRuleChanged()
{
Qt::FillRule rule = (Qt::FillRule)currentItemData(fillRuleComboBox).toInt();
- for (QList<RenderArea*>::iterator it = renderAreas.begin(); it != renderAreas.end(); ++it)
- (*it)->setFillRule(rule);
+ for (RenderArea *area : qAsConst(renderAreas))
+ area->setFillRule(rule);
}
//! [19]
@@ -254,8 +262,8 @@ void Window::fillGradientChanged()
QColor color1 = qvariant_cast<QColor>(currentItemData(fillColor1ComboBox));
QColor color2 = qvariant_cast<QColor>(currentItemData(fillColor2ComboBox));
- for (QList<RenderArea*>::iterator it = renderAreas.begin(); it != renderAreas.end(); ++it)
- (*it)->setFillGradient(color1, color2);
+ for (RenderArea *area : qAsConst(renderAreas))
+ area->setFillGradient(color1, color2);
}
//! [20]
@@ -264,16 +272,16 @@ void Window::penColorChanged()
{
QColor color = qvariant_cast<QColor>(currentItemData(penColorComboBox));
- for (QList<RenderArea*>::iterator it = renderAreas.begin(); it != renderAreas.end(); ++it)
- (*it)->setPenColor(color);
+ for (RenderArea *area : qAsConst(renderAreas))
+ area->setPenColor(color);
}
//! [21]
//! [22]
void Window::populateWithColors(QComboBox *comboBox)
{
- QStringList colorNames = QColor::colorNames();
- foreach (QString name, colorNames)
+ const QStringList colorNames = QColor::colorNames();
+ for (const QString &name : colorNames)
comboBox->addItem(name, QColor(name));
}
//! [22]
diff --git a/examples/widgets/painting/pathstroke/main.cpp b/examples/widgets/painting/pathstroke/main.cpp
index 3a63203118..57c85d73a3 100644
--- a/examples/widgets/painting/pathstroke/main.cpp
+++ b/examples/widgets/painting/pathstroke/main.cpp
@@ -63,8 +63,8 @@ int main(int argc, char **argv)
PathStrokeWidget pathStrokeWidget(smallScreen);
QStyle *arthurStyle = new ArthurStyle();
pathStrokeWidget.setStyle(arthurStyle);
- QList<QWidget *> widgets = pathStrokeWidget.findChildren<QWidget *>();
- foreach (QWidget *w, widgets) {
+ const QList<QWidget *> widgets = pathStrokeWidget.findChildren<QWidget *>();
+ for (QWidget *w : widgets) {
w->setStyle(arthurStyle);
w->setAttribute(Qt::WA_AcceptTouchEvents);
}
diff --git a/examples/widgets/painting/pathstroke/pathstroke.cpp b/examples/widgets/painting/pathstroke/pathstroke.cpp
index b04998afac..e4009f0b1a 100644
--- a/examples/widgets/painting/pathstroke/pathstroke.cpp
+++ b/examples/widgets/painting/pathstroke/pathstroke.cpp
@@ -164,24 +164,24 @@ void PathStrokeControls::createCommonControls(QWidget* parent)
// Connections
- connect(flatCap, SIGNAL(clicked()), m_renderer, SLOT(setFlatCap()));
- connect(squareCap, SIGNAL(clicked()), m_renderer, SLOT(setSquareCap()));
- connect(roundCap, SIGNAL(clicked()), m_renderer, SLOT(setRoundCap()));
+ connect(flatCap, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setFlatCap);
+ connect(squareCap, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setSquareCap);
+ connect(roundCap, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setRoundCap);
- connect(bevelJoin, SIGNAL(clicked()), m_renderer, SLOT(setBevelJoin()));
- connect(miterJoin, SIGNAL(clicked()), m_renderer, SLOT(setMiterJoin()));
- connect(svgMiterJoin, SIGNAL(clicked()), m_renderer, SLOT(setSvgMiterJoin()));
- connect(roundJoin, SIGNAL(clicked()), m_renderer, SLOT(setRoundJoin()));
+ connect(bevelJoin, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setBevelJoin);
+ connect(miterJoin, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setMiterJoin);
+ connect(svgMiterJoin, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setSvgMiterJoin);
+ connect(roundJoin, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setRoundJoin);
- connect(curveMode, SIGNAL(clicked()), m_renderer, SLOT(setCurveMode()));
- connect(lineMode, SIGNAL(clicked()), m_renderer, SLOT(setLineMode()));
+ connect(curveMode, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setCurveMode);
+ connect(lineMode, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setLineMode);
- connect(solidLine, SIGNAL(clicked()), m_renderer, SLOT(setSolidLine()));
- connect(dashLine, SIGNAL(clicked()), m_renderer, SLOT(setDashLine()));
- connect(dotLine, SIGNAL(clicked()), m_renderer, SLOT(setDotLine()));
- connect(dashDotLine, SIGNAL(clicked()), m_renderer, SLOT(setDashDotLine()));
- connect(dashDotDotLine, SIGNAL(clicked()), m_renderer, SLOT(setDashDotDotLine()));
- connect(customDashLine, SIGNAL(clicked()), m_renderer, SLOT(setCustomDashLine()));
+ connect(solidLine, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setSolidLine);
+ connect(dashLine, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setDashLine);
+ connect(dotLine, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setDotLine);
+ connect(dashDotLine, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setDashDotLine);
+ connect(dashDotDotLine, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setDashDotDotLine);
+ connect(customDashLine, &QAbstractButton::clicked, m_renderer, &PathStrokeRenderer::setCustomDashLine);
// Set the defaults:
flatCap->setChecked(true);
@@ -227,11 +227,11 @@ void PathStrokeControls::layoutForDesktop()
penWidthLayout->addWidget(penWidth);
QVBoxLayout * mainLayout = new QVBoxLayout(this);
- mainLayout->setMargin(0);
+ mainLayout->setContentsMargins(QMargins());
mainLayout->addWidget(mainGroup);
QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup);
- mainGroupLayout->setMargin(3);
+ mainGroupLayout->setContentsMargins(3, 3, 3, 3);
mainGroupLayout->addWidget(m_capGroup);
mainGroupLayout->addWidget(m_joinGroup);
mainGroupLayout->addWidget(m_styleGroup);
@@ -247,17 +247,17 @@ void PathStrokeControls::layoutForDesktop()
// Set up connections
- connect(animated, SIGNAL(toggled(bool)), m_renderer, SLOT(setAnimation(bool)));
+ connect(animated, &QAbstractButton::toggled, m_renderer, &PathStrokeRenderer::setAnimation);
- connect(penWidth, SIGNAL(valueChanged(int)), m_renderer, SLOT(setPenWidth(int)));
+ connect(penWidth, &QAbstractSlider::valueChanged, m_renderer, &PathStrokeRenderer::setPenWidth);
- connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource()));
+ connect(showSourceButton, &QAbstractButton::clicked, m_renderer, &ArthurFrame::showSource);
#if QT_CONFIG(opengl)
- connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
+ connect(enableOpenGLButton, &QAbstractButton::clicked, m_renderer, &ArthurFrame::enableOpenGL);
#endif
- connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool)));
- connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)),
- whatsThisButton, SLOT(setChecked(bool)));
+ connect(whatsThisButton, &QAbstractButton::clicked, m_renderer, &ArthurFrame::setDescriptionEnabled);
+ connect(m_renderer, &ArthurFrame::descriptionEnabledChanged,
+ whatsThisButton, &QAbstractButton::setChecked);
// Set the defaults
@@ -270,10 +270,10 @@ void PathStrokeControls::layoutForSmallScreens()
{
createCommonControls(this);
- m_capGroup->layout()->setMargin(0);
- m_joinGroup->layout()->setMargin(0);
- m_styleGroup->layout()->setMargin(0);
- m_pathModeGroup->layout()->setMargin(0);
+ m_capGroup->layout()->setContentsMargins(QMargins());
+ m_joinGroup->layout()->setContentsMargins(QMargins());
+ m_styleGroup->layout()->setContentsMargins(QMargins());
+ m_pathModeGroup->layout()->setContentsMargins(QMargins());
QPushButton* okBtn = new QPushButton(tr("OK"), this);
okBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
@@ -313,7 +313,7 @@ void PathStrokeControls::layoutForSmallScreens()
rightLayout->addWidget(m_pathModeGroup);
QGridLayout *mainLayout = new QGridLayout(this);
- mainLayout->setMargin(0);
+ mainLayout->setContentsMargins(QMargins());
// Add spacers around the form items so we don't look stupid at higher resolutions
mainLayout->addItem(new QSpacerItem(0,0), 0, 0, 1, 4);
@@ -327,12 +327,12 @@ void PathStrokeControls::layoutForSmallScreens()
mainLayout->addWidget(okBtn, 2, 2, Qt::AlignHCenter | Qt::AlignTop);
#if QT_CONFIG(opengl)
- connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
+ connect(enableOpenGLButton, &QAbstractButton::clicked, m_renderer, &ArthurFrame::enableOpenGL);
#endif
- connect(penWidth, SIGNAL(valueChanged(int)), m_renderer, SLOT(setPenWidth(int)));
- connect(quitBtn, SIGNAL(clicked()), this, SLOT(emitQuitSignal()));
- connect(okBtn, SIGNAL(clicked()), this, SLOT(emitOkSignal()));
+ connect(penWidth, &QAbstractSlider::valueChanged, m_renderer, &PathStrokeRenderer::setPenWidth);
+ connect(quitBtn, &QAbstractButton::clicked, this, &PathStrokeControls::emitQuitSignal);
+ connect(okBtn, &QAbstractButton::clicked, this, &PathStrokeControls::emitOkSignal);
m_renderer->setAnimation(true);
penWidth->setValue(50);
@@ -368,8 +368,8 @@ PathStrokeWidget::PathStrokeWidget(bool smallScreen)
m_renderer->loadSourceFile(":res/pathstroke/pathstroke.cpp");
m_renderer->loadDescription(":res/pathstroke/pathstroke.html");
- connect(m_renderer, SIGNAL(clicked()), this, SLOT(showControls()));
- connect(m_controls, SIGNAL(okPressed()), this, SLOT(hideControls()));
+ connect(m_renderer, &PathStrokeRenderer::clicked, this, &PathStrokeWidget::showControls);
+ connect(m_controls, &PathStrokeControls::okPressed, this, &PathStrokeWidget::hideControls);
connect(m_controls, SIGNAL(quitPressed()), QApplication::instance(), SLOT(quit()));
}
@@ -390,8 +390,8 @@ void PathStrokeWidget::setStyle( QStyle * style )
{
m_controls->setStyle(style);
- QList<QWidget *> widgets = m_controls->findChildren<QWidget *>();
- foreach (QWidget *w, widgets)
+ const QList<QWidget *> widgets = m_controls->findChildren<QWidget *>();
+ for (QWidget *w : widgets)
w->setStyle(style);
}
}
@@ -605,13 +605,14 @@ bool PathStrokeRenderer::event(QEvent *e)
{
const QTouchEvent *const event = static_cast<const QTouchEvent*>(e);
const QList<QTouchEvent::TouchPoint> points = event->touchPoints();
- foreach (const QTouchEvent::TouchPoint &touchPoint, points) {
+ for (const QTouchEvent::TouchPoint &touchPoint : points) {
const int id = touchPoint.id();
switch (touchPoint.state()) {
case Qt::TouchPointPressed:
{
// find the point, move it
- QSet<int> activePoints = QSet<int>::fromList(m_fingerPointMapping.values());
+ const auto mappedPoints = m_fingerPointMapping.values();
+ QSet<int> activePoints = QSet<int>(mappedPoints.begin(), mappedPoints.end());
int activePoint = -1;
qreal distance = -1;
const int pointsCount = m_points.size();
diff --git a/examples/widgets/painting/shared/arthurstyle.cpp b/examples/widgets/painting/shared/arthurstyle.cpp
index f4fc76bda6..3fc461bbd2 100644
--- a/examples/widgets/painting/shared/arthurstyle.cpp
+++ b/examples/widgets/painting/shared/arthurstyle.cpp
@@ -61,10 +61,10 @@
QPixmap cached(const QString &img)
{
- if (QPixmap *p = QPixmapCache::find(img))
- return *p;
-
QPixmap pm;
+ if (QPixmapCache::find(img, &pm))
+ return pm;
+
pm = QPixmap::fromImage(QImage(img), Qt::OrderedDither | Qt::OrderedAlphaDither);
if (pm.isNull())
return QPixmap();
@@ -443,9 +443,9 @@ void ArthurStyle::polish(QWidget *widget)
if (widget->layout() && qobject_cast<QGroupBox *>(widget)) {
if (widget->findChildren<QGroupBox *>().size() == 0) {
widget->layout()->setSpacing(0);
- widget->layout()->setMargin(12);
+ widget->layout()->setContentsMargins(12, 12, 12, 12);
} else {
- widget->layout()->setMargin(13);
+ widget->layout()->setContentsMargins(13, 13, 13, 13);
}
}
diff --git a/examples/widgets/painting/shared/arthurwidgets.cpp b/examples/widgets/painting/shared/arthurwidgets.cpp
index 442fb69ac1..bdac5de13c 100644
--- a/examples/widgets/painting/shared/arthurwidgets.cpp
+++ b/examples/widgets/painting/shared/arthurwidgets.cpp
@@ -330,32 +330,40 @@ void ArthurFrame::showSource()
QString contents;
if (m_sourceFileName.isEmpty()) {
- contents = QString("No source for widget: '%1'").arg(objectName());
+ contents = tr("No source for widget: '%1'").arg(objectName());
} else {
QFile f(m_sourceFileName);
if (!f.open(QFile::ReadOnly))
- contents = QString("Could not open file: '%1'").arg(m_sourceFileName);
+ contents = tr("Could not open file: '%1'").arg(m_sourceFileName);
else
contents = f.readAll();
}
- contents.replace('&', "&amp;");
- contents.replace('<', "&lt;");
- contents.replace('>', "&gt;");
-
- QStringList keywords;
- keywords << "for " << "if " << "switch " << " int " << "#include " << "const"
- << "void " << "uint " << "case " << "double " << "#define " << "static"
- << "new" << "this";
-
- foreach (QString keyword, keywords)
+ contents.replace(QLatin1Char('&'), QStringLiteral("&amp;"));
+ contents.replace(QLatin1Char('<'), QStringLiteral("&lt;"));
+ contents.replace(QLatin1Char('>'), QStringLiteral("&gt;"));
+
+ static const QString keywords[] = {
+ QStringLiteral("for "), QStringLiteral("if "),
+ QStringLiteral("switch "), QStringLiteral(" int "),
+ QStringLiteral("#include "), QStringLiteral("const"),
+ QStringLiteral("void "), QStringLiteral("uint "),
+ QStringLiteral("case "), QStringLiteral("double "),
+ QStringLiteral("#define "), QStringLiteral("static"),
+ QStringLiteral("new"), QStringLiteral("this")
+ };
+
+ for (const QString &keyword : keywords)
contents.replace(keyword, QLatin1String("<font color=olive>") + keyword + QLatin1String("</font>"));
- contents.replace("(int ", "(<font color=olive><b>int </b></font>");
+ contents.replace(QStringLiteral("(int "), QStringLiteral("(<font color=olive><b>int </b></font>"));
- QStringList ppKeywords;
- ppKeywords << "#ifdef" << "#ifndef" << "#if" << "#endif" << "#else";
+ static const QString ppKeywords[] = {
+ QStringLiteral("#ifdef"), QStringLiteral("#ifndef"),
+ QStringLiteral("#if"), QStringLiteral("#endif"),
+ QStringLiteral("#else")
+ };
- foreach (QString keyword, ppKeywords)
+ for (const QString &keyword : ppKeywords)
contents.replace(keyword, QLatin1String("<font color=navy>") + keyword + QLatin1String("</font>"));
contents.replace(QRegularExpression("(\\d\\d?)"), QLatin1String("<font color=navy>\\1</font>"));
@@ -366,12 +374,10 @@ void ArthurFrame::showSource()
QRegularExpression stringLiteralRe("(\".+?\")");
contents.replace(stringLiteralRe, QLatin1String("<font color=green>\\1</font>"));
- QString html = contents;
- html.prepend("<html><pre>");
- html.append("</pre></html>");
+ const QString html = QStringLiteral("<html><pre>") + contents + QStringLiteral("</pre></html>");
QTextBrowser *sourceViewer = new QTextBrowser(0);
- sourceViewer->setWindowTitle("Source: " + m_sourceFileName.mid(5));
+ sourceViewer->setWindowTitle(tr("Source: %1").arg(m_sourceFileName.midRef(5)));
sourceViewer->setParent(this, Qt::Dialog);
sourceViewer->setAttribute(Qt::WA_DeleteOnClose);
sourceViewer->setLineWrapMode(QTextEdit::NoWrap);
diff --git a/examples/widgets/painting/shared/hoverpoints.cpp b/examples/widgets/painting/shared/hoverpoints.cpp
index 7cd8cc0b29..2032fb5a2c 100644
--- a/examples/widgets/painting/shared/hoverpoints.cpp
+++ b/examples/widgets/painting/shared/hoverpoints.cpp
@@ -73,8 +73,8 @@ HoverPoints::HoverPoints(QWidget *widget, PointShape shape)
m_editable = true;
m_enabled = true;
- connect(this, SIGNAL(pointsChanged(QPolygonF)),
- m_widget, SLOT(update()));
+ connect(this, &HoverPoints::pointsChanged,
+ m_widget, QOverload<>::of(&QWidget::update));
}
@@ -174,13 +174,14 @@ bool HoverPoints::eventFilter(QObject *object, QEvent *event)
const QTouchEvent *const touchEvent = static_cast<const QTouchEvent*>(event);
const QList<QTouchEvent::TouchPoint> points = touchEvent->touchPoints();
const qreal pointSize = qMax(m_pointSize.width(), m_pointSize.height());
- foreach (const QTouchEvent::TouchPoint &touchPoint, points) {
+ for (const QTouchEvent::TouchPoint &touchPoint : points) {
const int id = touchPoint.id();
switch (touchPoint.state()) {
case Qt::TouchPointPressed:
{
// find the point, move it
- QSet<int> activePoints = QSet<int>::fromList(m_fingerPointMapping.values());
+ const auto mappedPoints = m_fingerPointMapping.values();
+ QSet<int> activePoints = QSet<int>(mappedPoints.begin(), mappedPoints.end());
int activePoint = -1;
qreal distance = -1;
const int pointsCount = m_points.size();
diff --git a/examples/widgets/painting/transformations/window.cpp b/examples/widgets/painting/transformations/window.cpp
index d8babb2e00..8261c4e12e 100644
--- a/examples/widgets/painting/transformations/window.cpp
+++ b/examples/widgets/painting/transformations/window.cpp
@@ -79,8 +79,8 @@ Window::Window()
operationComboBoxes[i]->addItem(tr("Scale to 75%"));
operationComboBoxes[i]->addItem(tr("Translate by (50, 50)"));
- connect(operationComboBoxes[i], SIGNAL(activated(int)),
- this, SLOT(operationChanged()));
+ connect(operationComboBoxes[i], QOverload<int>::of(&QComboBox::activated),
+ this, &Window::operationChanged);
layout->addWidget(transformedRenderAreas[i], 0, i + 1);
layout->addWidget(operationComboBoxes[i], 1, i + 1);
@@ -159,7 +159,8 @@ void Window::setupShapes()
shapes.append(text);
shapes.append(truck);
- connect(shapeComboBox, SIGNAL(activated(int)), this, SLOT(shapeSelected(int)));
+ connect(shapeComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::shapeSelected);
}
//! [7]
diff --git a/examples/widgets/qnx/foreignwindows/collector.cpp b/examples/widgets/qnx/foreignwindows/collector.cpp
new file mode 100644
index 0000000000..4b9e774945
--- /dev/null
+++ b/examples/widgets/qnx/foreignwindows/collector.cpp
@@ -0,0 +1,176 @@
+/***************************************************************************
+**
+** Copyright (C) 2018 QNX Software Systems. All rights reserved.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QDebug>
+#include <QHBoxLayout>
+#include <QWindow>
+
+#include <algorithm>
+#include <screen/screen.h>
+
+#include "collector.h"
+
+constexpr int MANAGER_EVENT_NAME_SUGGESTION = 9999;
+
+Collector::Collector(QWidget *parent)
+ : QWidget(parent)
+{
+ QApplication::instance()->installNativeEventFilter(this);
+
+ QLayout *layout = new QHBoxLayout(this);
+ setLayout(layout);
+}
+
+Collector::~Collector()
+{
+ QApplication::instance()->removeNativeEventFilter(this);
+}
+
+bool Collector::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
+{
+ Q_UNUSED(result);
+
+ if (eventType == QByteArrayLiteral("screen_event_t"))
+ return filterQnxScreenEvent(static_cast<screen_event_t>(message));
+
+ return false;
+}
+
+bool Collector::filterQnxScreenEvent(screen_event_t event)
+{
+ int objectType = SCREEN_OBJECT_TYPE_CONTEXT;
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType);
+
+ if (objectType == SCREEN_OBJECT_TYPE_WINDOW)
+ return filterQnxScreenWindowEvent(event);
+
+ return false;
+}
+
+bool Collector::filterQnxScreenWindowEvent(screen_event_t event)
+{
+ int eventType = SCREEN_EVENT_NONE;
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &eventType);
+ screen_window_t window = nullptr;
+ screen_get_event_property_pv(event,
+ SCREEN_PROPERTY_WINDOW,
+ reinterpret_cast<void **>(&window));
+
+ if (eventType == SCREEN_EVENT_CREATE)
+ return filterQnxScreenWindowCreateEvent(window, event);
+ else if (eventType == SCREEN_EVENT_CLOSE)
+ return filterQnxScreenWindowCloseEvent(window, event);
+ else if (eventType == SCREEN_EVENT_MANAGER)
+ return filterQnxScreenWindowManagerEvent(window, event);
+
+ return false;
+}
+
+bool Collector::filterQnxScreenWindowCreateEvent(screen_window_t window, screen_event_t event)
+{
+ Q_UNUSED(event);
+ WId winId = reinterpret_cast<WId>(window);
+
+ QByteArray parentGroup(256, 0);
+ screen_get_window_property_cv(window,
+ SCREEN_PROPERTY_PARENT,
+ parentGroup.length(),
+ parentGroup.data());
+ parentGroup.resize(strlen(parentGroup.constData()));
+
+ QByteArray group(256, 0);
+ screen_get_window_property_cv(reinterpret_cast<screen_window_t>(windowHandle()->winId()),
+ SCREEN_PROPERTY_GROUP,
+ group.length(),
+ group.data());
+ group.resize(strlen(group.constData()));
+
+ if (parentGroup != group)
+ return false;
+
+ Collectible collectible;
+ collectible.window = QWindow::fromWinId(winId);
+ collectible.widget = QWidget::createWindowContainer(collectible.window, this);
+ layout()->addWidget(collectible.widget);
+ m_collectibles.append(collectible);
+
+ return false;
+}
+
+bool Collector::filterQnxScreenWindowCloseEvent(screen_window_t window, screen_event_t event)
+{
+ Q_UNUSED(event);
+ WId winId = reinterpret_cast<WId>(window);
+ auto it = std::find_if(m_collectibles.begin(), m_collectibles.end(),
+ [winId] (const Collectible &collectible) {
+ return collectible.window->winId() == winId;
+ });
+ if (it != m_collectibles.end()) {
+ delete it->widget;
+ // it->window is deleted by it->widget.
+ m_collectibles.erase(it);
+ }
+
+ return false;
+}
+
+bool Collector::filterQnxScreenWindowManagerEvent(screen_window_t window, screen_event_t event)
+{
+ int managerEventType = 0;
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_SUBTYPE, &managerEventType);
+
+ if (managerEventType == MANAGER_EVENT_NAME_SUGGESTION)
+ return filterQnxScreenWindowManagerNameEvent(window, event);
+
+ return false;
+}
+
+bool Collector::filterQnxScreenWindowManagerNameEvent(screen_window_t window, screen_event_t event)
+{
+ Q_UNUSED(window);
+ int dataSize = 0;
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_SIZE, &dataSize);
+ if (dataSize > 0) {
+ QByteArray data(dataSize, 0);
+ screen_get_event_property_cv(event, SCREEN_PROPERTY_USER_DATA, data.size(), data.data());
+ }
+
+ return false;
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientscreenobserver.h b/examples/widgets/qnx/foreignwindows/collector.h
index ad927319c1..2b1ed499ff 100644
--- a/src/plugins/platforms/mirclient/qmirclientscreenobserver.h
+++ b/examples/widgets/qnx/foreignwindows/collector.h
@@ -1,6 +1,6 @@
-/****************************************************************************
+/***************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2018 QNX Software Systems. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -37,42 +37,39 @@
**
****************************************************************************/
+#ifndef COLLECTOR_H_
+#define COLLECTOR_H_
-#ifndef QMIRCLIENTSCREENOBSERVER_H
-#define QMIRCLIENTSCREENOBSERVER_H
+#include <QAbstractNativeEventFilter>
+#include <QWidget>
+#include <QVector>
-#include <QObject>
+#include <screen/screen.h>
-#include <mir_toolkit/mir_connection.h>
-
-class QMirClientScreen;
-
-class QMirClientScreenObserver : public QObject
+class Collector : public QWidget, public QAbstractNativeEventFilter
{
- Q_OBJECT
-
public:
- QMirClientScreenObserver(MirConnection *connection);
-
- QList<QMirClientScreen*> screens() const { return mScreenList; }
- QMirClientScreen *findScreenWithId(int id);
+ explicit Collector(QWidget *parent = nullptr);
+ ~Collector() override;
- void handleScreenPropertiesChange(QMirClientScreen *screen, int dpi,
- MirFormFactor formFactor, float scale);
-
-Q_SIGNALS:
- void screenAdded(QMirClientScreen *screen);
- void screenRemoved(QMirClientScreen *screen);
-
-private Q_SLOTS:
- void update();
+ bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
private:
- QMirClientScreen *findScreenWithId(const QList<QMirClientScreen *> &list, int id);
- void removeScreen(QMirClientScreen *screen);
+ struct Collectible
+ {
+ QWindow *window;
+ QWidget *widget;
+ };
+ QVector<Collectible> m_collectibles;
- MirConnection *mMirConnection;
- QList<QMirClientScreen*> mScreenList;
+ bool filterQnxScreenEvent(screen_event_t event);
+ bool filterQnxScreenWindowEvent(screen_event_t event);
+ bool filterQnxScreenWindowCreateEvent(screen_window_t window, screen_event_t event);
+ bool filterQnxScreenWindowCloseEvent(screen_window_t window, screen_event_t event);
+ bool filterQnxScreenWindowManagerEvent(screen_window_t window, screen_event_t event);
+ bool filterQnxScreenWindowManagerNameEvent(screen_window_t window,
+ screen_event_t event);
};
-#endif // QMIRCLIENTSCREENOBSERVER_H
+
+#endif /* COLLECTOR_H_ */
diff --git a/examples/widgets/qnx/foreignwindows/foreignwindows.pro b/examples/widgets/qnx/foreignwindows/foreignwindows.pro
new file mode 100644
index 0000000000..09ff8633eb
--- /dev/null
+++ b/examples/widgets/qnx/foreignwindows/foreignwindows.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+HEADERS += collector.h
+SOURCES += main.cpp collector.cpp
+LIBS += -lscreen
+
+QT += widgets
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/widgets/qnx/foreignwindows
+INSTALLS += target
diff --git a/src/plugins/platforms/mirclient/qmirclientdesktopwindow.cpp b/examples/widgets/qnx/foreignwindows/main.cpp
index 123f805c25..128e93cf88 100644
--- a/src/plugins/platforms/mirclient/qmirclientdesktopwindow.cpp
+++ b/examples/widgets/qnx/foreignwindows/main.cpp
@@ -1,6 +1,6 @@
-/****************************************************************************
+/***************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2018 QNX Software Systems. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -37,14 +37,17 @@
**
****************************************************************************/
+#include <QApplication>
-#include "qmirclientdesktopwindow.h"
+#include "collector.h"
-// local
-#include "qmirclientlogging.h"
-
-QMirClientDesktopWindow::QMirClientDesktopWindow(QWindow *window)
- : QPlatformWindow(window)
+int main(int argc, char *argv[])
{
- qCDebug(mirclient, "QMirClientDesktopWindow(window=%p)", window);
+ QApplication app(argc, argv);
+
+ Collector collector;
+ collector.resize(640, 480);
+ collector.show();
+
+ return app.exec();
}
diff --git a/examples/widgets/richtext/calendar/mainwindow.cpp b/examples/widgets/richtext/calendar/mainwindow.cpp
index 38dc0e2849..3ddb1cf7ad 100644
--- a/examples/widgets/richtext/calendar/mainwindow.cpp
+++ b/examples/widgets/richtext/calendar/mainwindow.cpp
@@ -86,10 +86,12 @@ MainWindow::MainWindow()
//! [2]
//! [3]
- connect(monthCombo, SIGNAL(activated(int)), this, SLOT(setMonth(int)));
- connect(yearEdit, SIGNAL(dateChanged(QDate)), this, SLOT(setYear(QDate)));
- connect(fontSizeSpinBox, SIGNAL(valueChanged(int)),
- this, SLOT(setFontSize(int)));
+ connect(monthCombo, QOverload<int>::of(&QComboBox::activated),
+ this, &MainWindow::setMonth);
+ connect(yearEdit, &QDateTimeEdit::dateChanged,
+ this, &MainWindow::setYear);
+ connect(fontSizeSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ this, &MainWindow::setFontSize);
//! [3]
fontSizeSpinBox->setValue(10);
diff --git a/examples/widgets/richtext/orderform/mainwindow.cpp b/examples/widgets/richtext/orderform/mainwindow.cpp
index b207ee4dbc..0b6a2cac6c 100644
--- a/examples/widgets/richtext/orderform/mainwindow.cpp
+++ b/examples/widgets/richtext/orderform/mainwindow.cpp
@@ -66,7 +66,7 @@ MainWindow::MainWindow()
QMenu *fileMenu = new QMenu(tr("&File"), this);
QAction *newAction = fileMenu->addAction(tr("&New..."));
newAction->setShortcuts(QKeySequence::New);
- printAction = fileMenu->addAction(tr("&Print..."), this, SLOT(printFile()));
+ printAction = fileMenu->addAction(tr("&Print..."), this, &MainWindow::printFile);
printAction->setShortcuts(QKeySequence::Print);
printAction->setEnabled(false);
QAction *quitAction = fileMenu->addAction(tr("E&xit"));
@@ -126,8 +126,8 @@ void MainWindow::createLetter(const QString &name, const QString &address,
cursor.setPosition(topFrame->lastPosition());
cursor.insertText(name, textFormat);
- QString line;
- foreach (line, address.split("\n")) {
+ const QStringList lines = address.split('\n');
+ for (const QString &line : lines) {
cursor.insertBlock();
cursor.insertText(line);
}
diff --git a/examples/widgets/richtext/syntaxhighlighter/highlighter.cpp b/examples/widgets/richtext/syntaxhighlighter/highlighter.cpp
index 6c420c328a..0c10eed6cf 100644
--- a/examples/widgets/richtext/syntaxhighlighter/highlighter.cpp
+++ b/examples/widgets/richtext/syntaxhighlighter/highlighter.cpp
@@ -58,18 +58,19 @@ Highlighter::Highlighter(QTextDocument *parent)
keywordFormat.setForeground(Qt::darkBlue);
keywordFormat.setFontWeight(QFont::Bold);
- QStringList keywordPatterns;
- keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b"
- << "\\bdouble\\b" << "\\benum\\b" << "\\bexplicit\\b"
- << "\\bfriend\\b" << "\\binline\\b" << "\\bint\\b"
- << "\\blong\\b" << "\\bnamespace\\b" << "\\boperator\\b"
- << "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b"
- << "\\bshort\\b" << "\\bsignals\\b" << "\\bsigned\\b"
- << "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b"
- << "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b"
- << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b"
- << "\\bvoid\\b" << "\\bvolatile\\b" << "\\bbool\\b";
- foreach (const QString &pattern, keywordPatterns) {
+ const QString keywordPatterns[] = {
+ QStringLiteral("\\bchar\\b"), QStringLiteral("\\bclass\\b"), QStringLiteral("\\bconst\\b"),
+ QStringLiteral("\\bdouble\\b"), QStringLiteral("\\benum\\b"), QStringLiteral("\\bexplicit\\b"),
+ QStringLiteral("\\bfriend\\b"), QStringLiteral("\\binline\\b"), QStringLiteral("\\bint\\b"),
+ QStringLiteral("\\blong\\b"), QStringLiteral("\\bnamespace\\b"), QStringLiteral("\\boperator\\b"),
+ QStringLiteral("\\bprivate\\b"), QStringLiteral("\\bprotected\\b"), QStringLiteral("\\bpublic\\b"),
+ QStringLiteral("\\bshort\\b"), QStringLiteral("\\bsignals\\b"), QStringLiteral("\\bsigned\\b"),
+ QStringLiteral("\\bslots\\b"), QStringLiteral("\\bstatic\\b"), QStringLiteral("\\bstruct\\b"),
+ QStringLiteral("\\btemplate\\b"), QStringLiteral("\\btypedef\\b"), QStringLiteral("\\btypename\\b"),
+ QStringLiteral("\\bunion\\b"), QStringLiteral("\\bunsigned\\b"), QStringLiteral("\\bvirtual\\b"),
+ QStringLiteral("\\bvoid\\b"), QStringLiteral("\\bvolatile\\b"), QStringLiteral("\\bbool\\b")
+ };
+ for (const QString &pattern : keywordPatterns) {
rule.pattern = QRegularExpression(pattern);
rule.format = keywordFormat;
highlightingRules.append(rule);
@@ -80,14 +81,14 @@ Highlighter::Highlighter(QTextDocument *parent)
//! [2]
classFormat.setFontWeight(QFont::Bold);
classFormat.setForeground(Qt::darkMagenta);
- rule.pattern = QRegularExpression("\\bQ[A-Za-z]+\\b");
+ rule.pattern = QRegularExpression(QStringLiteral("\\bQ[A-Za-z]+\\b"));
rule.format = classFormat;
highlightingRules.append(rule);
//! [2]
//! [3]
singleLineCommentFormat.setForeground(Qt::red);
- rule.pattern = QRegularExpression("//[^\n]*");
+ rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*"));
rule.format = singleLineCommentFormat;
highlightingRules.append(rule);
@@ -96,7 +97,7 @@ Highlighter::Highlighter(QTextDocument *parent)
//! [4]
quotationFormat.setForeground(Qt::darkGreen);
- rule.pattern = QRegularExpression("\".*\"");
+ rule.pattern = QRegularExpression(QStringLiteral("\".*\""));
rule.format = quotationFormat;
highlightingRules.append(rule);
//! [4]
@@ -104,21 +105,21 @@ Highlighter::Highlighter(QTextDocument *parent)
//! [5]
functionFormat.setFontItalic(true);
functionFormat.setForeground(Qt::blue);
- rule.pattern = QRegularExpression("\\b[A-Za-z0-9_]+(?=\\()");
+ rule.pattern = QRegularExpression(QStringLiteral("\\b[A-Za-z0-9_]+(?=\\()"));
rule.format = functionFormat;
highlightingRules.append(rule);
//! [5]
//! [6]
- commentStartExpression = QRegularExpression("/\\*");
- commentEndExpression = QRegularExpression("\\*/");
+ commentStartExpression = QRegularExpression(QStringLiteral("/\\*"));
+ commentEndExpression = QRegularExpression(QStringLiteral("\\*/"));
}
//! [6]
//! [7]
void Highlighter::highlightBlock(const QString &text)
{
- foreach (const HighlightingRule &rule, highlightingRules) {
+ for (const HighlightingRule &rule : qAsConst(highlightingRules)) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
diff --git a/examples/widgets/richtext/syntaxhighlighter/mainwindow.cpp b/examples/widgets/richtext/syntaxhighlighter/mainwindow.cpp
index dd58f1f45b..2dba0ba73e 100644
--- a/examples/widgets/richtext/syntaxhighlighter/mainwindow.cpp
+++ b/examples/widgets/richtext/syntaxhighlighter/mainwindow.cpp
@@ -117,9 +117,12 @@ void MainWindow::setupFileMenu()
QMenu *fileMenu = new QMenu(tr("&File"), this);
menuBar()->addMenu(fileMenu);
- fileMenu->addAction(tr("&New"), this, SLOT(newFile()), QKeySequence::New);
- fileMenu->addAction(tr("&Open..."), this, SLOT(openFile()), QKeySequence::Open);
- fileMenu->addAction(tr("E&xit"), qApp, SLOT(quit()), QKeySequence::Quit);
+ fileMenu->addAction(tr("&New"), this,
+ &MainWindow::newFile, QKeySequence::New);
+ fileMenu->addAction(tr("&Open..."),
+ this, [this](){ openFile(); }, QKeySequence::Open);
+ fileMenu->addAction(tr("E&xit"), qApp,
+ &QApplication::quit, QKeySequence::Quit);
}
void MainWindow::setupHelpMenu()
@@ -127,6 +130,6 @@ void MainWindow::setupHelpMenu()
QMenu *helpMenu = new QMenu(tr("&Help"), this);
menuBar()->addMenu(helpMenu);
- helpMenu->addAction(tr("&About"), this, SLOT(about()));
- helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt()));
+ helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
}
diff --git a/examples/widgets/richtext/textedit/example.md b/examples/widgets/richtext/textedit/example.md
new file mode 100644
index 0000000000..a16a9197b4
--- /dev/null
+++ b/examples/widgets/richtext/textedit/example.md
@@ -0,0 +1,102 @@
+# QTextEdit
+
+The QTextEdit widget is an advanced editor that supports formatted rich text.
+It can be used to display HTML and other rich document formats. Internally,
+QTextEdit uses the QTextDocument class to describe both the high-level
+structure of each document and the low-level formatting of paragraphs.
+
+If you are viewing this document in the textedit example, you can edit this
+document to explore Qt's rich text editing features. We have included some
+comments in each of the following sections to encourage you to experiment.
+
+## Font and Paragraph Styles
+
+QTextEdit supports **bold**, *italic*, &amp; ~~strikethrough~~ font styles, and
+can display <span style="font-size:10pt; font-weight:600;
+color:#00007f;">multicolored</span> text. Font families such as <span
+style="font-family:Times New Roman">Times New Roman</span> and `Courier`
+can also be used directly. *If you place the cursor in a region of styled text,
+the controls in the tool bars will change to reflect the current style.*
+
+Paragraphs can be formatted so that the text is left-aligned, right-aligned,
+centered, or fully justified.
+
+*Try changing the alignment of some text and resize the editor to see how the
+text layout changes.*
+
+## Lists
+
+Different kinds of lists can be included in rich text documents. Standard
+bullet lists can be nested, using different symbols for each level of the list:
+
+- Disc symbols are typically used for top-level list items.
+ * Circle symbols can be used to distinguish between items in lower-level
+ lists.
+ + Square symbols provide a reasonable alternative to discs and circles.
+
+Ordered lists can be created that can be used for tables of contents. Different
+characters can be used to enumerate items, and we can use both Roman and Arabic
+numerals in the same list structure:
+
+1. Introduction
+2. Qt Tools
+ 1) Qt Assistant
+ 2) Qt Designer
+ 1. Form Editor
+ 2. Component Architecture
+ 3) Qt Linguist
+
+The list will automatically be renumbered if you add or remove items. *Try
+adding new sections to the above list or removing existing item to see the
+numbers change.*
+
+Task lists can be used to track progress on projects:
+
+- [ ] This is not yet done
+- This is just a bullet point
+- [x] This is done
+
+## Images
+
+Inline images are treated like ordinary ranges of characters in the text
+editor, so they flow with the surrounding text. Images can also be selected in
+the same way as text, making it easy to cut, copy, and paste them.
+
+![logo](images/logo32.png "logo") *Try to select this image by clicking and
+dragging over it with the mouse, or use the text cursor to select it by holding
+down Shift and using the arrow keys. You can then cut or copy it, and paste it
+into different parts of this document.*
+
+## Tables
+
+QTextEdit can arrange and format tables, supporting features such as row and
+column spans, text formatting within cells, and size constraints for columns.
+
+| | Development Tools | Programming Techniques | Graphical User Interfaces |
+| ------------: | ----------------- | ---------------------- | ------------------------- |
+| 9:00 - 11:00 | Introduction to Qt |||
+| 11:00 - 13:00 | Using qmake | Object-oriented Programming | Layouts in Qt |
+| 13:00 - 15:00 | Qt Designer Tutorial | Extreme Programming | Writing Custom Styles |
+| 15:00 - 17:00 | Qt Linguist and Internationalization | &nbsp; | &nbsp; |
+
+*Try adding text to the cells in the table and experiment with the alignment of
+the paragraphs.*
+
+## Hyperlinks
+
+QTextEdit is designed to support hyperlinks between documents, and this feature
+is used extensively in
+[Qt Assistant](http://doc.qt.io/qt-5/qtassistant-index.html). Hyperlinks are
+automatically created when an HTML file is imported into an editor. Since the
+rich text framework supports hyperlinks natively, they can also be created
+programatically.
+
+## Undo and Redo
+
+Full support for undo and redo operations is built into QTextEdit and the
+underlying rich text framework. Operations on a document can be packaged
+together to make editing a more comfortable experience for the user.
+
+*Try making changes to this document and press `Ctrl+Z` to undo them. You can
+always recover the original contents of the document.*
+
diff --git a/examples/widgets/richtext/textedit/images/mac/checkbox-checked.png b/examples/widgets/richtext/textedit/images/mac/checkbox-checked.png
new file mode 100644
index 0000000000..a072d7fb5c
--- /dev/null
+++ b/examples/widgets/richtext/textedit/images/mac/checkbox-checked.png
Binary files differ
diff --git a/examples/widgets/richtext/textedit/images/mac/checkbox.png b/examples/widgets/richtext/textedit/images/mac/checkbox.png
new file mode 100644
index 0000000000..4064909712
--- /dev/null
+++ b/examples/widgets/richtext/textedit/images/mac/checkbox.png
Binary files differ
diff --git a/examples/widgets/richtext/textedit/images/mac/format-indent-less.png b/examples/widgets/richtext/textedit/images/mac/format-indent-less.png
new file mode 100644
index 0000000000..e38074e78b
--- /dev/null
+++ b/examples/widgets/richtext/textedit/images/mac/format-indent-less.png
Binary files differ
diff --git a/examples/widgets/richtext/textedit/images/mac/format-indent-more.png b/examples/widgets/richtext/textedit/images/mac/format-indent-more.png
new file mode 100644
index 0000000000..1bdeabd354
--- /dev/null
+++ b/examples/widgets/richtext/textedit/images/mac/format-indent-more.png
Binary files differ
diff --git a/examples/widgets/richtext/textedit/images/win/checkbox-checked.png b/examples/widgets/richtext/textedit/images/win/checkbox-checked.png
new file mode 100644
index 0000000000..a072d7fb5c
--- /dev/null
+++ b/examples/widgets/richtext/textedit/images/win/checkbox-checked.png
Binary files differ
diff --git a/examples/widgets/richtext/textedit/images/win/checkbox.png b/examples/widgets/richtext/textedit/images/win/checkbox.png
new file mode 100644
index 0000000000..4064909712
--- /dev/null
+++ b/examples/widgets/richtext/textedit/images/win/checkbox.png
Binary files differ
diff --git a/examples/widgets/richtext/textedit/images/win/format-indent-less.png b/examples/widgets/richtext/textedit/images/win/format-indent-less.png
new file mode 100644
index 0000000000..e38074e78b
--- /dev/null
+++ b/examples/widgets/richtext/textedit/images/win/format-indent-less.png
Binary files differ
diff --git a/examples/widgets/richtext/textedit/images/win/format-indent-more.png b/examples/widgets/richtext/textedit/images/win/format-indent-more.png
new file mode 100644
index 0000000000..1bdeabd354
--- /dev/null
+++ b/examples/widgets/richtext/textedit/images/win/format-indent-more.png
Binary files differ
diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp
index 0d51ce61ad..996bb8e0a4 100644
--- a/examples/widgets/richtext/textedit/textedit.cpp
+++ b/examples/widgets/richtext/textedit/textedit.cpp
@@ -71,6 +71,7 @@
#include <QCloseEvent>
#include <QMessageBox>
#include <QMimeData>
+#include <QMimeDatabase>
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
#if QT_CONFIG(printer)
@@ -316,6 +317,14 @@ void TextEdit::setupTextActions()
actionAlignJustify->setShortcut(Qt::CTRL + Qt::Key_J);
actionAlignJustify->setCheckable(true);
actionAlignJustify->setPriority(QAction::LowPriority);
+ const QIcon indentMoreIcon = QIcon::fromTheme("format-indent-more", QIcon(rsrcPath + "/format-indent-more.png"));
+ actionIndentMore = menu->addAction(indentMoreIcon, tr("&Indent"), this, &TextEdit::indent);
+ actionIndentMore->setShortcut(Qt::CTRL + Qt::Key_BracketRight);
+ actionIndentMore->setPriority(QAction::LowPriority);
+ const QIcon indentLessIcon = QIcon::fromTheme("format-indent-less", QIcon(rsrcPath + "/format-indent-less.png"));
+ actionIndentLess = menu->addAction(indentLessIcon, tr("&Unindent"), this, &TextEdit::unindent);
+ actionIndentLess->setShortcut(Qt::CTRL + Qt::Key_BracketLeft);
+ actionIndentLess->setPriority(QAction::LowPriority);
// Make sure the alignLeft is always left of the alignRight
QActionGroup *alignGroup = new QActionGroup(this);
@@ -334,6 +343,10 @@ void TextEdit::setupTextActions()
tb->addActions(alignGroup->actions());
menu->addActions(alignGroup->actions());
+ tb->addAction(actionIndentMore);
+ tb->addAction(actionIndentLess);
+ menu->addAction(actionIndentMore);
+ menu->addAction(actionIndentLess);
menu->addSeparator();
@@ -342,6 +355,15 @@ void TextEdit::setupTextActions()
actionTextColor = menu->addAction(pix, tr("&Color..."), this, &TextEdit::textColor);
tb->addAction(actionTextColor);
+ menu->addSeparator();
+
+ const QIcon checkboxIcon = QIcon::fromTheme("status-checkbox-checked", QIcon(rsrcPath + "/checkbox-checked.png"));
+ actionToggleCheckState = menu->addAction(checkboxIcon, tr("Chec&ked"), this, &TextEdit::setChecked);
+ actionToggleCheckState->setShortcut(Qt::CTRL + Qt::Key_K);
+ actionToggleCheckState->setCheckable(true);
+ actionToggleCheckState->setPriority(QAction::LowPriority);
+ tb->addAction(actionToggleCheckState);
+
tb = addToolBar(tr("Format Actions"));
tb->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
addToolBarBreak(Qt::TopToolBarArea);
@@ -353,6 +375,8 @@ void TextEdit::setupTextActions()
comboStyle->addItem("Bullet List (Disc)");
comboStyle->addItem("Bullet List (Circle)");
comboStyle->addItem("Bullet List (Square)");
+ comboStyle->addItem("Task List (Unchecked)");
+ comboStyle->addItem("Task List (Checked)");
comboStyle->addItem("Ordered List (Decimal)");
comboStyle->addItem("Ordered List (Alpha lower)");
comboStyle->addItem("Ordered List (Alpha upper)");
@@ -369,7 +393,7 @@ void TextEdit::setupTextActions()
comboFont = new QFontComboBox(tb);
tb->addWidget(comboFont);
- connect(comboFont, QOverload<const QString &>::of(&QComboBox::activated), this, &TextEdit::textFamily);
+ connect(comboFont, &QComboBox::textActivated, this, &TextEdit::textFamily);
comboSize = new QComboBox(tb);
comboSize->setObjectName("comboSize");
@@ -377,11 +401,11 @@ void TextEdit::setupTextActions()
comboSize->setEditable(true);
const QList<int> standardSizes = QFontDatabase::standardSizes();
- foreach (int size, standardSizes)
+ for (int size : standardSizes)
comboSize->addItem(QString::number(size));
comboSize->setCurrentIndex(standardSizes.indexOf(QApplication::font().pointSize()));
- connect(comboSize, QOverload<const QString &>::of(&QComboBox::activated), this, &TextEdit::textSize);
+ connect(comboSize, &QComboBox::textActivated, this, &TextEdit::textSize);
}
bool TextEdit::load(const QString &f)
@@ -395,11 +419,18 @@ bool TextEdit::load(const QString &f)
QByteArray data = file.readAll();
QTextCodec *codec = Qt::codecForHtml(data);
QString str = codec->toUnicode(data);
+ QUrl baseUrl = (f.front() == QLatin1Char(':') ? QUrl(f) : QUrl::fromLocalFile(f)).adjusted(QUrl::RemoveFilename);
+ textEdit->document()->setBaseUrl(baseUrl);
if (Qt::mightBeRichText(str)) {
textEdit->setHtml(str);
} else {
- str = QString::fromLocal8Bit(data);
- textEdit->setPlainText(str);
+#if QT_CONFIG(textmarkdownreader)
+ QMimeDatabase db;
+ if (db.mimeTypeForFileNameAndData(f, data).name() == QLatin1String("text/markdown"))
+ textEdit->setMarkdown(str);
+ else
+#endif
+ textEdit->setPlainText(QString::fromLocal8Bit(data));
}
setCurrentFileName(f);
@@ -451,7 +482,15 @@ void TextEdit::fileOpen()
QFileDialog fileDialog(this, tr("Open File..."));
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
fileDialog.setFileMode(QFileDialog::ExistingFile);
- fileDialog.setMimeTypeFilters(QStringList() << "text/html" << "text/plain");
+ fileDialog.setMimeTypeFilters(QStringList()
+#if QT_CONFIG(texthtmlparser)
+ << "text/html"
+#endif
+#if QT_CONFIG(textmarkdownreader)
+
+ << "text/markdown"
+#endif
+ << "text/plain");
if (fileDialog.exec() != QDialog::Accepted)
return;
const QString fn = fileDialog.selectedFiles().first();
@@ -485,9 +524,18 @@ bool TextEdit::fileSaveAs()
QFileDialog fileDialog(this, tr("Save as..."));
fileDialog.setAcceptMode(QFileDialog::AcceptSave);
QStringList mimeTypes;
- mimeTypes << "application/vnd.oasis.opendocument.text" << "text/html" << "text/plain";
+ mimeTypes << "text/plain"
+#if QT_CONFIG(textodfwriter)
+ << "application/vnd.oasis.opendocument.text"
+#endif
+#if QT_CONFIG(textmarkdownwriter)
+ << "text/markdown"
+#endif
+ << "text/html";
fileDialog.setMimeTypeFilters(mimeTypes);
+#if QT_CONFIG(textodfwriter)
fileDialog.setDefaultSuffix("odt");
+#endif
if (fileDialog.exec() != QDialog::Accepted)
return false;
const QString fn = fileDialog.selectedFiles().first();
@@ -592,6 +640,7 @@ void TextEdit::textStyle(int styleIndex)
{
QTextCursor cursor = textEdit->textCursor();
QTextListFormat::Style style = QTextListFormat::ListStyleUndefined;
+ QTextBlockFormat::MarkerType marker = QTextBlockFormat::NoMarker;
switch (styleIndex) {
case 1:
@@ -604,18 +653,32 @@ void TextEdit::textStyle(int styleIndex)
style = QTextListFormat::ListSquare;
break;
case 4:
- style = QTextListFormat::ListDecimal;
+ if (cursor.currentList())
+ style = cursor.currentList()->format().style();
+ else
+ style = QTextListFormat::ListDisc;
+ marker = QTextBlockFormat::Unchecked;
break;
case 5:
- style = QTextListFormat::ListLowerAlpha;
+ if (cursor.currentList())
+ style = cursor.currentList()->format().style();
+ else
+ style = QTextListFormat::ListDisc;
+ marker = QTextBlockFormat::Checked;
break;
case 6:
- style = QTextListFormat::ListUpperAlpha;
+ style = QTextListFormat::ListDecimal;
break;
case 7:
- style = QTextListFormat::ListLowerRoman;
+ style = QTextListFormat::ListLowerAlpha;
break;
case 8:
+ style = QTextListFormat::ListUpperAlpha;
+ break;
+ case 9:
+ style = QTextListFormat::ListLowerRoman;
+ break;
+ case 10:
style = QTextListFormat::ListUpperRoman;
break;
default:
@@ -628,7 +691,7 @@ void TextEdit::textStyle(int styleIndex)
if (style == QTextListFormat::ListStyleUndefined) {
blockFmt.setObjectIndex(-1);
- int headingLevel = styleIndex >= 9 ? styleIndex - 9 + 1 : 0; // H1 to H6, or Standard
+ int headingLevel = styleIndex >= 11 ? styleIndex - 11 + 1 : 0; // H1 to H6, or Standard
blockFmt.setHeadingLevel(headingLevel);
cursor.setBlockFormat(blockFmt);
@@ -640,6 +703,8 @@ void TextEdit::textStyle(int styleIndex)
cursor.mergeCharFormat(fmt);
textEdit->mergeCurrentCharFormat(fmt);
} else {
+ blockFmt.setMarker(marker);
+ cursor.setBlockFormat(blockFmt);
QTextListFormat listFmt;
if (cursor.currentList()) {
listFmt = cursor.currentList()->format();
@@ -678,6 +743,45 @@ void TextEdit::textAlign(QAction *a)
textEdit->setAlignment(Qt::AlignJustify);
}
+void TextEdit::setChecked(bool checked)
+{
+ textStyle(checked ? 5 : 4);
+}
+
+void TextEdit::indent()
+{
+ modifyIndentation(1);
+}
+
+void TextEdit::unindent()
+{
+ modifyIndentation(-1);
+}
+
+void TextEdit::modifyIndentation(int amount)
+{
+ QTextCursor cursor = textEdit->textCursor();
+ cursor.beginEditBlock();
+ if (cursor.currentList()) {
+ QTextListFormat listFmt = cursor.currentList()->format();
+ // See whether the line above is the list we want to move this item into,
+ // or whether we need a new list.
+ QTextCursor above(cursor);
+ above.movePosition(QTextCursor::Up);
+ if (above.currentList() && listFmt.indent() + amount == above.currentList()->format().indent()) {
+ above.currentList()->add(cursor.block());
+ } else {
+ listFmt.setIndent(listFmt.indent() + amount);
+ cursor.createList(listFmt);
+ }
+ } else {
+ QTextBlockFormat blockFmt = cursor.blockFormat();
+ blockFmt.setIndent(blockFmt.indent() + amount);
+ cursor.setBlockFormat(blockFmt);
+ }
+ cursor.endEditBlock();
+}
+
void TextEdit::currentCharFormatChanged(const QTextCharFormat &format)
{
fontChanged(format.font());
@@ -700,27 +804,40 @@ void TextEdit::cursorPositionChanged()
comboStyle->setCurrentIndex(3);
break;
case QTextListFormat::ListDecimal:
- comboStyle->setCurrentIndex(4);
+ comboStyle->setCurrentIndex(6);
break;
case QTextListFormat::ListLowerAlpha:
- comboStyle->setCurrentIndex(5);
+ comboStyle->setCurrentIndex(7);
break;
case QTextListFormat::ListUpperAlpha:
- comboStyle->setCurrentIndex(6);
+ comboStyle->setCurrentIndex(8);
break;
case QTextListFormat::ListLowerRoman:
- comboStyle->setCurrentIndex(7);
+ comboStyle->setCurrentIndex(9);
break;
case QTextListFormat::ListUpperRoman:
- comboStyle->setCurrentIndex(8);
+ comboStyle->setCurrentIndex(10);
break;
default:
comboStyle->setCurrentIndex(-1);
break;
}
+ switch (textEdit->textCursor().block().blockFormat().marker()) {
+ case QTextBlockFormat::NoMarker:
+ actionToggleCheckState->setChecked(false);
+ break;
+ case QTextBlockFormat::Unchecked:
+ comboStyle->setCurrentIndex(4);
+ actionToggleCheckState->setChecked(false);
+ break;
+ case QTextBlockFormat::Checked:
+ comboStyle->setCurrentIndex(5);
+ actionToggleCheckState->setChecked(true);
+ break;
+ }
} else {
int headingLevel = textEdit->textCursor().blockFormat().headingLevel();
- comboStyle->setCurrentIndex(headingLevel ? headingLevel + 8 : 0);
+ comboStyle->setCurrentIndex(headingLevel ? headingLevel + 10 : 0);
}
}
diff --git a/examples/widgets/richtext/textedit/textedit.h b/examples/widgets/richtext/textedit/textedit.h
index ae0b13a4cc..9e50166c6f 100644
--- a/examples/widgets/richtext/textedit/textedit.h
+++ b/examples/widgets/richtext/textedit/textedit.h
@@ -96,6 +96,9 @@ private slots:
void textStyle(int styleIndex);
void textColor();
void textAlign(QAction *a);
+ void setChecked(bool checked);
+ void indent();
+ void unindent();
void currentCharFormatChanged(const QTextCharFormat &format);
void cursorPositionChanged();
@@ -110,6 +113,7 @@ private:
void setupTextActions();
bool maybeSave();
void setCurrentFileName(const QString &fileName);
+ void modifyIndentation(int amount);
void mergeFormatOnWordOrSelection(const QTextCharFormat &format);
void fontChanged(const QFont &f);
@@ -125,6 +129,9 @@ private:
QAction *actionAlignCenter;
QAction *actionAlignRight;
QAction *actionAlignJustify;
+ QAction *actionIndentLess;
+ QAction *actionIndentMore;
+ QAction *actionToggleCheckState;
QAction *actionUndo;
QAction *actionRedo;
#ifndef QT_NO_CLIPBOARD
diff --git a/examples/widgets/richtext/textedit/textedit.qrc b/examples/widgets/richtext/textedit/textedit.qrc
index 7d6efd7d67..1641acc207 100644
--- a/examples/widgets/richtext/textedit/textedit.qrc
+++ b/examples/widgets/richtext/textedit/textedit.qrc
@@ -1,6 +1,8 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>images/logo32.png</file>
+ <file>images/mac/checkbox.png</file>
+ <file>images/mac/checkbox-checked.png</file>
<file>images/mac/editcopy.png</file>
<file>images/mac/editcut.png</file>
<file>images/mac/editpaste.png</file>
@@ -11,6 +13,8 @@
<file>images/mac/fileopen.png</file>
<file>images/mac/fileprint.png</file>
<file>images/mac/filesave.png</file>
+ <file>images/mac/format-indent-less.png</file>
+ <file>images/mac/format-indent-more.png</file>
<file>images/mac/textbold.png</file>
<file>images/mac/textcenter.png</file>
<file>images/mac/textitalic.png</file>
@@ -20,6 +24,8 @@
<file>images/mac/textunder.png</file>
<file>images/mac/zoomin.png</file>
<file>images/mac/zoomout.png</file>
+ <file>images/win/checkbox.png</file>
+ <file>images/win/checkbox-checked.png</file>
<file>images/win/editcopy.png</file>
<file>images/win/editcut.png</file>
<file>images/win/editpaste.png</file>
@@ -30,6 +36,8 @@
<file>images/win/fileopen.png</file>
<file>images/win/fileprint.png</file>
<file>images/win/filesave.png</file>
+ <file>images/win/format-indent-less.png</file>
+ <file>images/win/format-indent-more.png</file>
<file>images/win/textbold.png</file>
<file>images/win/textcenter.png</file>
<file>images/win/textitalic.png</file>
diff --git a/examples/widgets/scroller/graphicsview/main.cpp b/examples/widgets/scroller/graphicsview/main.cpp
index c33a3091ed..d6b2956d50 100644
--- a/examples/widgets/scroller/graphicsview/main.cpp
+++ b/examples/widgets/scroller/graphicsview/main.cpp
@@ -117,7 +117,8 @@ public:
QRectF boundingRect() const override
{
QRectF rect;
- foreach (QGraphicsItem *item, childItems())
+ const auto items = childItems();
+ for (const QGraphicsItem *item : items)
rect |= item->boundingRect().translated(item->pos());
return rect;
}
diff --git a/examples/widgets/statemachine/factorial/main.cpp b/examples/widgets/statemachine/factorial/main.cpp
index f100aa0110..e9431596fe 100644
--- a/examples/widgets/statemachine/factorial/main.cpp
+++ b/examples/widgets/statemachine/factorial/main.cpp
@@ -49,7 +49,6 @@
****************************************************************************/
#include <QtCore>
-#include <stdio.h>
//! [0]
class Factorial : public QObject
@@ -100,7 +99,7 @@ class FactorialLoopTransition : public QSignalTransition
{
public:
FactorialLoopTransition(Factorial *fact)
- : QSignalTransition(fact, SIGNAL(xChanged(int))), m_fact(fact)
+ : QSignalTransition(fact, &Factorial::xChanged), m_fact(fact)
{}
bool eventTest(QEvent *e) override
@@ -130,7 +129,7 @@ class FactorialDoneTransition : public QSignalTransition
{
public:
FactorialDoneTransition(Factorial *fact)
- : QSignalTransition(fact, SIGNAL(xChanged(int))), m_fact(fact)
+ : QSignalTransition(fact, &Factorial::xChanged), m_fact(fact)
{}
bool eventTest(QEvent *e) override
@@ -143,7 +142,7 @@ public:
void onTransition(QEvent *) override
{
- fprintf(stdout, "%d\n", m_fact->property("fac").toInt());
+ qInfo() << m_fact->property("fac").toInt();
}
private:
diff --git a/examples/widgets/statemachine/rogue/window.cpp b/examples/widgets/statemachine/rogue/window.cpp
index 059fbf1003..a5363e2758 100644
--- a/examples/widgets/statemachine/rogue/window.cpp
+++ b/examples/widgets/statemachine/rogue/window.cpp
@@ -66,7 +66,8 @@ Window::Window()
font = QFont("Monospace");
}
else {
- foreach (QString family, database.families()) {
+ const QStringList fontFamilies = database.families();
+ for (const QString &family : fontFamilies ) {
if (database.isFixedPitch(family)) {
font = QFont(family);
break;
@@ -217,7 +218,8 @@ void Window::buildMachine()
//![5]
machine->setInitialState(inputState);
- connect(machine, SIGNAL(finished()), qApp, SLOT(quit()));
+ connect(machine, &QStateMachine::finished,
+ qApp, &QApplication::quit);
machine->start();
}
diff --git a/examples/widgets/statemachine/trafficlight/main.cpp b/examples/widgets/statemachine/trafficlight/main.cpp
index 21df91d8b0..1a7050c28d 100644
--- a/examples/widgets/statemachine/trafficlight/main.cpp
+++ b/examples/widgets/statemachine/trafficlight/main.cpp
@@ -132,11 +132,11 @@ QState *createLightState(LightWidget *light, int duration, QState *parent = 0)
timer->setInterval(duration);
timer->setSingleShot(true);
QState *timing = new QState(lightState);
- QObject::connect(timing, SIGNAL(entered()), light, SLOT(turnOn()));
- QObject::connect(timing, SIGNAL(entered()), timer, SLOT(start()));
- QObject::connect(timing, SIGNAL(exited()), light, SLOT(turnOff()));
+ QObject::connect(timing, &QAbstractState::entered, light, &LightWidget::turnOn);
+ QObject::connect(timing, &QAbstractState::entered, timer, QOverload<>::of(&QTimer::start));
+ QObject::connect(timing, &QAbstractState::exited, light, &LightWidget::turnOff);
QFinalState *done = new QFinalState(lightState);
- timing->addTransition(timer, SIGNAL(timeout()), done);
+ timing->addTransition(timer, &QTimer::timeout, done);
lightState->setInitialState(timing);
return lightState;
}
@@ -146,27 +146,27 @@ QState *createLightState(LightWidget *light, int duration, QState *parent = 0)
class TrafficLight : public QWidget
{
public:
- TrafficLight(QWidget *parent = 0)
+ TrafficLight(QWidget *parent = nullptr)
: QWidget(parent)
{
QVBoxLayout *vbox = new QVBoxLayout(this);
- TrafficLightWidget *widget = new TrafficLightWidget();
+ TrafficLightWidget *widget = new TrafficLightWidget;
vbox->addWidget(widget);
- vbox->setMargin(0);
+ vbox->setContentsMargins(QMargins());
QStateMachine *machine = new QStateMachine(this);
QState *redGoingYellow = createLightState(widget->redLight(), 3000);
redGoingYellow->setObjectName("redGoingYellow");
QState *yellowGoingGreen = createLightState(widget->yellowLight(), 1000);
yellowGoingGreen->setObjectName("yellowGoingGreen");
- redGoingYellow->addTransition(redGoingYellow, SIGNAL(finished()), yellowGoingGreen);
+ redGoingYellow->addTransition(redGoingYellow, &QState::finished, yellowGoingGreen);
QState *greenGoingYellow = createLightState(widget->greenLight(), 3000);
greenGoingYellow->setObjectName("greenGoingYellow");
- yellowGoingGreen->addTransition(yellowGoingGreen, SIGNAL(finished()), greenGoingYellow);
+ yellowGoingGreen->addTransition(yellowGoingGreen, &QState::finished, greenGoingYellow);
QState *yellowGoingRed = createLightState(widget->yellowLight(), 1000);
yellowGoingRed->setObjectName("yellowGoingRed");
- greenGoingYellow->addTransition(greenGoingYellow, SIGNAL(finished()), yellowGoingRed);
- yellowGoingRed->addTransition(yellowGoingRed, SIGNAL(finished()), redGoingYellow);
+ greenGoingYellow->addTransition(greenGoingYellow, &QState::finished, yellowGoingRed);
+ yellowGoingRed->addTransition(yellowGoingRed, &QState::finished, redGoingYellow);
machine->addState(redGoingYellow);
machine->addState(yellowGoingGreen);
diff --git a/examples/widgets/statemachine/twowaybutton/main.cpp b/examples/widgets/statemachine/twowaybutton/main.cpp
index 5c778aba70..3d4fef3bbe 100644
--- a/examples/widgets/statemachine/twowaybutton/main.cpp
+++ b/examples/widgets/statemachine/twowaybutton/main.cpp
@@ -69,8 +69,8 @@ int main(int argc, char **argv)
//! [1]
//! [2]
- off->addTransition(&button, SIGNAL(clicked()), on);
- on->addTransition(&button, SIGNAL(clicked()), off);
+ off->addTransition(&button, &QAbstractButton::clicked, on);
+ on->addTransition(&button, &QAbstractButton::clicked, off);
//! [2]
//! [3]
diff --git a/examples/widgets/tools/codecs/mainwindow.cpp b/examples/widgets/tools/codecs/mainwindow.cpp
index 229c2ccfd4..53db9fe61f 100644
--- a/examples/widgets/tools/codecs/mainwindow.cpp
+++ b/examples/widgets/tools/codecs/mainwindow.cpp
@@ -127,11 +127,10 @@ void MainWindow::about()
void MainWindow::aboutToShowSaveAsMenu()
{
- QString currentText = textEdit->toPlainText();
-
- foreach (QAction *action, saveAsActs) {
- QByteArray codecName = action->data().toByteArray();
- QTextCodec *codec = QTextCodec::codecForName(codecName);
+ const QString currentText = textEdit->toPlainText();
+ for (QAction *action : qAsConst(saveAsActs)) {
+ const QByteArray codecName = action->data().toByteArray();
+ const QTextCodec *codec = QTextCodec::codecForName(codecName);
action->setVisible(codec && codec->canEncode(currentText));
}
}
@@ -142,7 +141,8 @@ void MainWindow::findCodecs()
QRegularExpression iso8859RegExp("^ISO[- ]8859-([0-9]+).*$");
QRegularExpressionMatch match;
- foreach (int mib, QTextCodec::availableMibs()) {
+ const QList<int> mibs = QTextCodec::availableMibs();
+ for (int mib : mibs) {
QTextCodec *codec = QTextCodec::codecForMib(mib);
QString sortKey = codec->name().toUpper();
@@ -177,7 +177,7 @@ void MainWindow::createMenus()
QMenu *saveAsMenu = fileMenu->addMenu(tr("&Save As"));
connect(saveAsMenu, &QMenu::aboutToShow,
this, &MainWindow::aboutToShowSaveAsMenu);
- foreach (const QTextCodec *codec, codecs) {
+ for (const QTextCodec *codec : qAsConst(codecs)) {
const QByteArray name = codec->name();
QAction *action = saveAsMenu->addAction(tr("%1...").arg(QLatin1String(name)));
action->setData(QVariant(name));
diff --git a/examples/widgets/tools/codecs/previewform.cpp b/examples/widgets/tools/codecs/previewform.cpp
index d19b9c0833..206b5757cd 100644
--- a/examples/widgets/tools/codecs/previewform.cpp
+++ b/examples/widgets/tools/codecs/previewform.cpp
@@ -182,7 +182,7 @@ PreviewForm::PreviewForm(QWidget *parent)
void PreviewForm::setCodecList(const QList<QTextCodec *> &list)
{
encodingComboBox->clear();
- foreach (const QTextCodec *codec, list) {
+ for (const QTextCodec *codec : list) {
encodingComboBox->addItem(QLatin1String(codec->name()),
QVariant(codec->mibEnum()));
}
diff --git a/examples/widgets/tools/completer/mainwindow.cpp b/examples/widgets/tools/completer/mainwindow.cpp
index d63d523548..114ff0fd7c 100644
--- a/examples/widgets/tools/completer/mainwindow.cpp
+++ b/examples/widgets/tools/completer/mainwindow.cpp
@@ -102,10 +102,14 @@ MainWindow::MainWindow(QWidget *parent)
contentsLabel = new QLabel;
contentsLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- connect(modelCombo, SIGNAL(activated(int)), this, SLOT(changeModel()));
- connect(modeCombo, SIGNAL(activated(int)), this, SLOT(changeMode(int)));
- connect(caseCombo, SIGNAL(activated(int)), this, SLOT(changeCase(int)));
- connect(maxVisibleSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeMaxVisible(int)));
+ connect(modelCombo, QOverload<int>::of(&QComboBox::activated),
+ this, &MainWindow::changeModel);
+ connect(modeCombo, QOverload<int>::of(&QComboBox::activated),
+ this, &MainWindow::changeMode);
+ connect(caseCombo, QOverload<int>::of(&QComboBox::activated),
+ this, &MainWindow::changeCase);
+ connect(maxVisibleSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ this, &MainWindow::changeMaxVisible);
//! [2]
//! [3]
@@ -136,9 +140,9 @@ void MainWindow::createMenu()
QAction *aboutAct = new QAction(tr("About"), this);
QAction *aboutQtAct = new QAction(tr("About Qt"), this);
- connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ connect(exitAction, &QAction::triggered, qApp, &QApplication::quit);
+ connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
+ connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);
QMenu* fileMenu = menuBar()->addMenu(tr("File"));
fileMenu->addAction(exitAction);
@@ -159,7 +163,7 @@ QAbstractItemModel *MainWindow::modelFromFile(const QString& fileName)
//! [6]
#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+ QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
#endif
QStringList words;
@@ -170,7 +174,7 @@ QAbstractItemModel *MainWindow::modelFromFile(const QString& fileName)
}
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
//! [6]
@@ -271,7 +275,7 @@ void MainWindow::changeModel()
changeCase(caseCombo->currentIndex());
completer->setWrapAround(wrapCheckBox->isChecked());
lineEdit->setCompleter(completer);
- connect(wrapCheckBox, SIGNAL(clicked(bool)), completer, SLOT(setWrapAround(bool)));
+ connect(wrapCheckBox, &QAbstractButton::clicked, completer, &QCompleter::setWrapAround);
}
//! [14]
diff --git a/examples/widgets/tools/customcompleter/mainwindow.cpp b/examples/widgets/tools/customcompleter/mainwindow.cpp
index 26948d0c8e..39f5f39617 100644
--- a/examples/widgets/tools/customcompleter/mainwindow.cpp
+++ b/examples/widgets/tools/customcompleter/mainwindow.cpp
@@ -79,9 +79,9 @@ void MainWindow::createMenu()
QAction *aboutAct = new QAction(tr("About"), this);
QAction *aboutQtAct = new QAction(tr("About Qt"), this);
- connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ connect(exitAction, &QAction::triggered, qApp, &QApplication::quit);
+ connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
+ connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);
QMenu* fileMenu = menuBar()->addMenu(tr("File"));
fileMenu->addAction(exitAction);
@@ -100,7 +100,7 @@ QAbstractItemModel *MainWindow::modelFromFile(const QString& fileName)
return new QStringListModel(completer);
#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+ QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
#endif
QStringList words;
@@ -111,7 +111,7 @@ QAbstractItemModel *MainWindow::modelFromFile(const QString& fileName)
}
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
return new QStringListModel(words, completer);
}
diff --git a/examples/widgets/tools/customcompleter/textedit.cpp b/examples/widgets/tools/customcompleter/textedit.cpp
index 5512e72843..d42f7b38bb 100644
--- a/examples/widgets/tools/customcompleter/textedit.cpp
+++ b/examples/widgets/tools/customcompleter/textedit.cpp
@@ -88,8 +88,8 @@ void TextEdit::setCompleter(QCompleter *completer)
c->setWidget(this);
c->setCompletionMode(QCompleter::PopupCompletion);
c->setCaseSensitivity(Qt::CaseInsensitive);
- QObject::connect(c, SIGNAL(activated(QString)),
- this, SLOT(insertCompletion(QString)));
+ QObject::connect(c, QOverload<const QString &>::of(&QCompleter::activated),
+ this, &TextEdit::insertCompletion);
}
//! [2]
diff --git a/examples/widgets/tools/echoplugin/echowindow/echowindow.cpp b/examples/widgets/tools/echoplugin/echowindow/echowindow.cpp
index 64b59d506e..6886a4cd88 100644
--- a/examples/widgets/tools/echoplugin/echowindow/echowindow.cpp
+++ b/examples/widgets/tools/echoplugin/echowindow/echowindow.cpp
@@ -113,7 +113,8 @@ bool EchoWindow::loadPlugin()
}
#endif
pluginsDir.cd("plugins");
- foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
+ const QStringList entries = pluginsDir.entryList(QDir::Files);
+ for (const QString &fileName : entries) {
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = pluginLoader.instance();
if (plugin) {
diff --git a/examples/widgets/tools/i18n/languagechooser.cpp b/examples/widgets/tools/i18n/languagechooser.cpp
index 58cf9d4047..963165ff81 100644
--- a/examples/widgets/tools/i18n/languagechooser.cpp
+++ b/examples/widgets/tools/i18n/languagechooser.cpp
@@ -148,14 +148,14 @@ void LanguageChooser::checkBoxToggled()
void LanguageChooser::showAll()
{
- foreach (QCheckBox *checkBox, qmFileForCheckBoxMap.keys())
- checkBox->setChecked(true);
+ for (auto it = qmFileForCheckBoxMap.keyBegin(); it != qmFileForCheckBoxMap.keyEnd(); ++it)
+ (*it)->setChecked(true);
}
void LanguageChooser::hideAll()
{
- foreach (QCheckBox *checkBox, qmFileForCheckBoxMap.keys())
- checkBox->setChecked(false);
+ for (auto it = qmFileForCheckBoxMap.keyBegin(); it != qmFileForCheckBoxMap.keyEnd(); ++it)
+ (*it)->setChecked(false);
}
QStringList LanguageChooser::findQmFiles()
@@ -163,11 +163,8 @@ QStringList LanguageChooser::findQmFiles()
QDir dir(":/translations");
QStringList fileNames = dir.entryList(QStringList("*.qm"), QDir::Files,
QDir::Name);
- QMutableStringListIterator i(fileNames);
- while (i.hasNext()) {
- i.next();
- i.setValue(dir.filePath(i.value()));
- }
+ for (QString &fileName : fileNames)
+ fileName = dir.filePath(fileName);
return fileNames;
}
diff --git a/examples/widgets/tools/plugandpaint/app/interfaces.h b/examples/widgets/tools/plugandpaint/app/interfaces.h
index a1e91e13ff..705e578809 100644
--- a/examples/widgets/tools/plugandpaint/app/interfaces.h
+++ b/examples/widgets/tools/plugandpaint/app/interfaces.h
@@ -68,7 +68,7 @@ QT_END_NAMESPACE
class BrushInterface
{
public:
- virtual ~BrushInterface() {}
+ virtual ~BrushInterface() = default;
virtual QStringList brushes() const = 0;
virtual QRect mousePress(const QString &brush, QPainter &painter,
@@ -84,7 +84,7 @@ public:
class ShapeInterface
{
public:
- virtual ~ShapeInterface() {}
+ virtual ~ShapeInterface() = default;
virtual QStringList shapes() const = 0;
virtual QPainterPath generateShape(const QString &shape,
@@ -96,7 +96,7 @@ public:
class FilterInterface
{
public:
- virtual ~FilterInterface() {}
+ virtual ~FilterInterface() = default;
virtual QStringList filters() const = 0;
virtual QImage filterImage(const QString &filter, const QImage &image,
diff --git a/examples/widgets/tools/plugandpaint/app/paintarea.cpp b/examples/widgets/tools/plugandpaint/app/paintarea.cpp
index 4295e04cc0..e225d78398 100644
--- a/examples/widgets/tools/plugandpaint/app/paintarea.cpp
+++ b/examples/widgets/tools/plugandpaint/app/paintarea.cpp
@@ -59,7 +59,7 @@ PaintArea::PaintArea(QWidget *parent) :
QWidget(parent)
{
setAttribute(Qt::WA_StaticContents);
- setAttribute(Qt::WA_NoBackground);
+ setAttribute(Qt::WA_OpaquePaintEvent);
theImage.fill(qRgb(255, 255, 255));
}
diff --git a/examples/widgets/tools/plugandpaint/app/plugindialog.cpp b/examples/widgets/tools/plugandpaint/app/plugindialog.cpp
index af5828f67e..84bd364b41 100644
--- a/examples/widgets/tools/plugandpaint/app/plugindialog.cpp
+++ b/examples/widgets/tools/plugandpaint/app/plugindialog.cpp
@@ -125,7 +125,7 @@ void PluginDialog::populateTreeWidget(QObject *plugin, const QString &text)
{
auto pluginItem = new QTreeWidgetItem(treeWidget);
pluginItem->setText(0, text);
- treeWidget->setItemExpanded(pluginItem, true);
+ pluginItem->setExpanded(true);
QFont boldFont = pluginItem->font(0);
boldFont.setBold(true);
diff --git a/examples/widgets/tools/regexp/regexpdialog.cpp b/examples/widgets/tools/regexp/regexpdialog.cpp
index 7b3fee5794..bf61d09974 100644
--- a/examples/widgets/tools/regexp/regexpdialog.cpp
+++ b/examples/widgets/tools/regexp/regexpdialog.cpp
@@ -135,15 +135,15 @@ RegExpDialog::RegExpDialog(QWidget *parent)
}
setLayout(mainLayout);
- connect(patternComboBox, SIGNAL(editTextChanged(QString)),
- this, SLOT(refresh()));
- connect(textComboBox, SIGNAL(editTextChanged(QString)),
- this, SLOT(refresh()));
- connect(caseSensitiveCheckBox, SIGNAL(toggled(bool)),
- this, SLOT(refresh()));
- connect(minimalCheckBox, SIGNAL(toggled(bool)), this, SLOT(refresh()));
- connect(syntaxComboBox, SIGNAL(currentIndexChanged(int)),
- this, SLOT(refresh()));
+ connect(patternComboBox, &QComboBox::editTextChanged,
+ this, &RegExpDialog::refresh);
+ connect(textComboBox, &QComboBox::editTextChanged,
+ this, &RegExpDialog::refresh);
+ connect(caseSensitiveCheckBox, &QAbstractButton::toggled,
+ this, &RegExpDialog::refresh);
+ connect(minimalCheckBox, &QAbstractButton::toggled, this, &RegExpDialog::refresh);
+ connect(syntaxComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &RegExpDialog::refresh);
patternComboBox->addItem(tr("[A-Za-z_]+([A-Za-z_0-9]*)"));
textComboBox->addItem(tr("(10 + delta4) * 32"));
diff --git a/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp b/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp
index 8fbf143cbd..ea3cb00a02 100644
--- a/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp
+++ b/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp
@@ -376,7 +376,7 @@ QWidget *RegularExpressionDialog::setupLeftUi()
QFormLayout *layout = new QFormLayout(container);
layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
- layout->setMargin(0);
+ layout->setContentsMargins(QMargins());
QLabel *regexpAndSubjectLabel = new QLabel(tr("<h3>Regular expression and text input</h3>"));
layout->addRow(regexpAndSubjectLabel);
@@ -448,7 +448,7 @@ QWidget *RegularExpressionDialog::setupRightUi()
QFormLayout *layout = new QFormLayout(container);
layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
- layout->setMargin(0);
+ layout->setContentsMargins(QMargins());
QLabel *matchInfoLabel = new QLabel(tr("<h3>Match information</h3>"));
layout->addRow(matchInfoLabel);
diff --git a/examples/widgets/tools/settingseditor/settingstree.cpp b/examples/widgets/tools/settingseditor/settingstree.cpp
index 4ca843784e..8585792787 100644
--- a/examples/widgets/tools/settingseditor/settingstree.cpp
+++ b/examples/widgets/tools/settingseditor/settingstree.cpp
@@ -170,7 +170,8 @@ void SettingsTree::updateChildItems(QTreeWidgetItem *parent)
{
int dividerIndex = 0;
- foreach (QString group, settings->childGroups()) {
+ const QStringList childGroups = settings->childGroups();
+ for (const QString &group : childGroups) {
QTreeWidgetItem *child;
int childIndex = findChild(parent, group, dividerIndex);
if (childIndex != -1) {
@@ -190,7 +191,8 @@ void SettingsTree::updateChildItems(QTreeWidgetItem *parent)
settings->endGroup();
}
- foreach (const QString &key, settings->childKeys()) {
+ const QStringList childKeys = settings->childKeys();
+ for (const QString &key : childKeys) {
QTreeWidgetItem *child;
int childIndex = findChild(parent, key, 0);
diff --git a/examples/widgets/tools/treemodelcompleter/mainwindow.cpp b/examples/widgets/tools/treemodelcompleter/mainwindow.cpp
index a8b51c7aa0..dec3cb0496 100644
--- a/examples/widgets/tools/treemodelcompleter/mainwindow.cpp
+++ b/examples/widgets/tools/treemodelcompleter/mainwindow.cpp
@@ -61,8 +61,8 @@ MainWindow::MainWindow(QWidget *parent)
completer = new TreeModelCompleter(this);
completer->setModel(modelFromFile(":/resources/treemodel.txt"));
completer->setSeparator(QLatin1String("."));
- QObject::connect(completer, SIGNAL(highlighted(QModelIndex)),
- this, SLOT(highlight(QModelIndex)));
+ QObject::connect(completer, QOverload<const QModelIndex &>::of(&TreeModelCompleter::highlighted),
+ this, &MainWindow::highlight);
QWidget *centralWidget = new QWidget;
@@ -91,18 +91,18 @@ MainWindow::MainWindow(QWidget *parent)
QLineEdit *separatorLineEdit = new QLineEdit;
separatorLineEdit->setText(completer->separator());
- connect(separatorLineEdit, SIGNAL(textChanged(QString)),
- completer, SLOT(setSeparator(QString)));
+ connect(separatorLineEdit, &QLineEdit::textChanged,
+ completer, &TreeModelCompleter::setSeparator);
QCheckBox *wrapCheckBox = new QCheckBox;
wrapCheckBox->setText(tr("Wrap around completions"));
wrapCheckBox->setChecked(completer->wrapAround());
- connect(wrapCheckBox, SIGNAL(clicked(bool)), completer, SLOT(setWrapAround(bool)));
+ connect(wrapCheckBox, &QAbstractButton::clicked, completer, &QCompleter::setWrapAround);
contentsLabel = new QLabel;
contentsLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- connect(separatorLineEdit, SIGNAL(textChanged(QString)),
- this, SLOT(updateContentsLabel(QString)));
+ connect(separatorLineEdit, &QLineEdit::textChanged,
+ this, &MainWindow::updateContentsLabel);
treeView = new QTreeView;
treeView->setModel(completer->model());
@@ -111,8 +111,10 @@ MainWindow::MainWindow(QWidget *parent)
//! [1]
//! [2]
- connect(modeCombo, SIGNAL(activated(int)), this, SLOT(changeMode(int)));
- connect(caseCombo, SIGNAL(activated(int)), this, SLOT(changeCase(int)));
+ connect(modeCombo, QOverload<int>::of(&QComboBox::activated),
+ this, &MainWindow::changeMode);
+ connect(caseCombo, QOverload<int>::of(&QComboBox::activated),
+ this, &MainWindow::changeMode);
lineEdit = new QLineEdit;
lineEdit->setCompleter(completer);
@@ -145,9 +147,9 @@ void MainWindow::createMenu()
QAction *aboutAct = new QAction(tr("About"), this);
QAction *aboutQtAct = new QAction(tr("About Qt"), this);
- connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ connect(exitAction, &QAction::triggered, qApp, &QApplication::quit);
+ connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
+ connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);
QMenu* fileMenu = menuBar()->addMenu(tr("File"));
fileMenu->addAction(exitAction);
@@ -180,7 +182,7 @@ QAbstractItemModel *MainWindow::modelFromFile(const QString& fileName)
return new QStringListModel(completer);
#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+ QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
#endif
QStringList words;
@@ -218,7 +220,7 @@ QAbstractItemModel *MainWindow::modelFromFile(const QString& fileName)
}
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
return model;
diff --git a/examples/widgets/tools/undo/document.cpp b/examples/widgets/tools/undo/document.cpp
index 212656721e..8935f98a7a 100644
--- a/examples/widgets/tools/undo/document.cpp
+++ b/examples/widgets/tools/undo/document.cpp
@@ -338,9 +338,9 @@ static QGradient gradient(const QColor &color, const QRect &rect)
QColor c = color;
c.setAlpha(160);
QLinearGradient result(rect.topLeft(), rect.bottomRight());
- result.setColorAt(0, c.dark(150));
- result.setColorAt(0.5, c.light(200));
- result.setColorAt(1, c.dark(150));
+ result.setColorAt(0, c.darker(150));
+ result.setColorAt(0.5, c.lighter(200));
+ result.setColorAt(1, c.darker(150));
return result;
}
diff --git a/examples/widgets/tools/undo/mainwindow.cpp b/examples/widgets/tools/undo/mainwindow.cpp
index 5976163f3f..118d604742 100644
--- a/examples/widgets/tools/undo/mainwindow.cpp
+++ b/examples/widgets/tools/undo/mainwindow.cpp
@@ -68,25 +68,25 @@ MainWindow::MainWindow(QWidget *parent)
documentTabs->removeTab(0);
delete w;
- connect(actionOpen, SIGNAL(triggered()), this, SLOT(openDocument()));
- connect(actionClose, SIGNAL(triggered()), this, SLOT(closeDocument()));
- connect(actionNew, SIGNAL(triggered()), this, SLOT(newDocument()));
- connect(actionSave, SIGNAL(triggered()), this, SLOT(saveDocument()));
- connect(actionExit, SIGNAL(triggered()), this, SLOT(close()));
- connect(actionRed, SIGNAL(triggered()), this, SLOT(setShapeColor()));
- connect(actionGreen, SIGNAL(triggered()), this, SLOT(setShapeColor()));
- connect(actionBlue, SIGNAL(triggered()), this, SLOT(setShapeColor()));
- connect(actionAddCircle, SIGNAL(triggered()), this, SLOT(addShape()));
- connect(actionAddRectangle, SIGNAL(triggered()), this, SLOT(addShape()));
- connect(actionAddTriangle, SIGNAL(triggered()), this, SLOT(addShape()));
- connect(actionRemoveShape, SIGNAL(triggered()), this, SLOT(removeShape()));
- connect(actionAddRobot, SIGNAL(triggered()), this, SLOT(addRobot()));
- connect(actionAddSnowman, SIGNAL(triggered()), this, SLOT(addSnowman()));
- connect(actionAbout, SIGNAL(triggered()), this, SLOT(about()));
- connect(actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt()));
-
- connect(undoLimit, SIGNAL(valueChanged(int)), this, SLOT(updateActions()));
- connect(documentTabs, SIGNAL(currentChanged(int)), this, SLOT(updateActions()));
+ connect(actionOpen, &QAction::triggered, this, &MainWindow::openDocument);
+ connect(actionClose, &QAction::triggered, this, &MainWindow::closeDocument);
+ connect(actionNew, &QAction::triggered, this, &MainWindow::newDocument);
+ connect(actionSave, &QAction::triggered, this, &MainWindow::saveDocument);
+ connect(actionExit, &QAction::triggered, this, &QWidget::close);
+ connect(actionRed, &QAction::triggered, this, &MainWindow::setShapeColor);
+ connect(actionGreen, &QAction::triggered, this, &MainWindow::setShapeColor);
+ connect(actionBlue, &QAction::triggered, this, &MainWindow::setShapeColor);
+ connect(actionAddCircle, &QAction::triggered, this, &MainWindow::addShape);
+ connect(actionAddRectangle, &QAction::triggered, this, &MainWindow::addShape);
+ connect(actionAddTriangle, &QAction::triggered, this, &MainWindow::addShape);
+ connect(actionRemoveShape, &QAction::triggered, this, &MainWindow::removeShape);
+ connect(actionAddRobot, &QAction::triggered, this, &MainWindow::addRobot);
+ connect(actionAddSnowman, &QAction::triggered, this, &MainWindow::addSnowman);
+ connect(actionAbout, &QAction::triggered, this, &MainWindow::about);
+ connect(actionAboutQt, &QAction::triggered, this, &MainWindow::aboutQt);
+
+ connect(undoLimit, QOverload<int>::of(&QSpinBox::valueChanged), this, &MainWindow::updateActions);
+ connect(documentTabs, &QTabWidget::currentChanged, this, &MainWindow::updateActions);
actionOpen->setShortcut(QString("Ctrl+O"));
actionClose->setShortcut(QString("Ctrl+W"));
@@ -226,9 +226,9 @@ void MainWindow::addDocument(Document *doc)
return;
m_undoGroup->addStack(doc->undoStack());
documentTabs->addTab(doc, fixedWindowTitle(doc));
- connect(doc, SIGNAL(currentShapeChanged(QString)), this, SLOT(updateActions()));
- connect(doc->undoStack(), SIGNAL(indexChanged(int)), this, SLOT(updateActions()));
- connect(doc->undoStack(), SIGNAL(cleanChanged(bool)), this, SLOT(updateActions()));
+ connect(doc, &Document::currentShapeChanged, this, &MainWindow::updateActions);
+ connect(doc->undoStack(), &QUndoStack::indexChanged, this, &MainWindow::updateActions);
+ connect(doc->undoStack(), &QUndoStack::cleanChanged, this, &MainWindow::updateActions);
setCurrentDocument(doc);
}
@@ -251,9 +251,9 @@ void MainWindow::removeDocument(Document *doc)
documentTabs->removeTab(index);
m_undoGroup->removeStack(doc->undoStack());
- disconnect(doc, SIGNAL(currentShapeChanged(QString)), this, SLOT(updateActions()));
- disconnect(doc->undoStack(), SIGNAL(indexChanged(int)), this, SLOT(updateActions()));
- disconnect(doc->undoStack(), SIGNAL(cleanChanged(bool)), this, SLOT(updateActions()));
+ disconnect(doc, &Document::currentShapeChanged, this, &MainWindow::updateActions);
+ disconnect(doc->undoStack(), &QUndoStack::indexChanged, this, &MainWindow::updateActions);
+ disconnect(doc->undoStack(), &QUndoStack::cleanChanged, this, &MainWindow::updateActions);
if (documentTabs->count() == 0) {
newDocument();
diff --git a/examples/widgets/tools/undoframework/mainwindow.cpp b/examples/widgets/tools/undoframework/mainwindow.cpp
index b2f5405b73..e95d50d164 100644
--- a/examples/widgets/tools/undoframework/mainwindow.cpp
+++ b/examples/widgets/tools/undoframework/mainwindow.cpp
@@ -70,8 +70,8 @@ MainWindow::MainWindow()
diagramScene->setBackgroundBrush(pixmapBrush);
diagramScene->setSceneRect(QRect(0, 0, 500, 500));
- connect(diagramScene, SIGNAL(itemMoved(DiagramItem*,QPointF)),
- this, SLOT(itemMoved(DiagramItem*,QPointF)));
+ connect(diagramScene, &DiagramScene::itemMoved,
+ this, &MainWindow::itemMoved);
setWindowTitle("Undo Framework");
QGraphicsView *view = new QGraphicsView(diagramScene);
@@ -95,18 +95,18 @@ void MainWindow::createActions()
{
deleteAction = new QAction(tr("&Delete Item"), this);
deleteAction->setShortcut(tr("Del"));
- connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteItem()));
+ connect(deleteAction, &QAction::triggered, this, &MainWindow::deleteItem);
//! [2] //! [3]
//! [3] //! [4]
addBoxAction = new QAction(tr("Add &Box"), this);
//! [4]
addBoxAction->setShortcut(tr("Ctrl+O"));
- connect(addBoxAction, SIGNAL(triggered()), this, SLOT(addBox()));
+ connect(addBoxAction, &QAction::triggered, this, &MainWindow::addBox);
addTriangleAction = new QAction(tr("Add &Triangle"), this);
addTriangleAction->setShortcut(tr("Ctrl+T"));
- connect(addTriangleAction, SIGNAL(triggered()), this, SLOT(addTriangle()));
+ connect(addTriangleAction, &QAction::triggered, this, &MainWindow::addTriangle);
//! [5]
undoAction = undoStack->createUndoAction(this, tr("&Undo"));
@@ -118,13 +118,13 @@ void MainWindow::createActions()
exitAction = new QAction(tr("E&xit"), this);
exitAction->setShortcuts(QKeySequence::Quit);
- connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
+ connect(exitAction, &QAction::triggered, this, &QWidget::close);
aboutAction = new QAction(tr("&About"), this);
QList<QKeySequence> aboutShortcuts;
aboutShortcuts << tr("Ctrl+A") << tr("Ctrl+B");
aboutAction->setShortcuts(aboutShortcuts);
- connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
+ connect(aboutAction, &QAction::triggered, this, &MainWindow::about);
}
//! [6]
@@ -140,10 +140,10 @@ void MainWindow::createMenus()
editMenu->addAction(redoAction);
editMenu->addSeparator();
editMenu->addAction(deleteAction);
- connect(editMenu, SIGNAL(aboutToShow()),
- this, SLOT(itemMenuAboutToShow()));
- connect(editMenu, SIGNAL(aboutToHide()),
- this, SLOT(itemMenuAboutToHide()));
+ connect(editMenu, &QMenu::aboutToShow,
+ this, &MainWindow::itemMenuAboutToShow);
+ connect(editMenu, &QMenu::aboutToHide,
+ this, &MainWindow::itemMenuAboutToHide);
//! [7]
itemMenu = menuBar()->addMenu(tr("&Item"));
diff --git a/examples/widgets/touch/dials/main.cpp b/examples/widgets/touch/dials/main.cpp
index 071f485de3..059dfdc716 100644
--- a/examples/widgets/touch/dials/main.cpp
+++ b/examples/widgets/touch/dials/main.cpp
@@ -60,8 +60,8 @@ int main(int argc, char **argv)
QWidget window;
Ui::Dials dialsUi;
dialsUi.setupUi(&window);
- QList<QAbstractSlider *> sliders = window.findChildren<QAbstractSlider *>();
- foreach (QAbstractSlider *slider, sliders)
+ const QList<QAbstractSlider *> sliders = window.findChildren<QAbstractSlider *>();
+ for (QAbstractSlider *slider : sliders)
slider->setAttribute(Qt::WA_AcceptTouchEvents);
window.showMaximized();
return app.exec();
diff --git a/examples/widgets/touch/fingerpaint/mainwindow.cpp b/examples/widgets/touch/fingerpaint/mainwindow.cpp
index 0e45eea240..2f7ec38d1a 100644
--- a/examples/widgets/touch/fingerpaint/mainwindow.cpp
+++ b/examples/widgets/touch/fingerpaint/mainwindow.cpp
@@ -127,34 +127,35 @@ void MainWindow::createActions()
{
openAct = new QAction(tr("&Open..."), this);
openAct->setShortcut(tr("Ctrl+O"));
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
+ connect(openAct, &QAction::triggered, this, &MainWindow::open);
- foreach (QByteArray format, QImageWriter::supportedImageFormats()) {
+ const QList<QByteArray> imageFormats = QImageWriter::supportedImageFormats();
+ for (const QByteArray &format : imageFormats) {
QString text = tr("%1...").arg(QString(format).toUpper());
QAction *action = new QAction(text, this);
action->setData(format);
- connect(action, SIGNAL(triggered()), this, SLOT(save()));
+ connect(action, &QAction::triggered, this, &MainWindow::save);
saveAsActs.append(action);
}
printAct = new QAction(tr("&Print..."), this);
- connect(printAct, SIGNAL(triggered()), scribbleArea, SLOT(print()));
+ connect(printAct, &QAction::triggered, scribbleArea, &ScribbleArea::print);
exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcut(tr("Ctrl+Q"));
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
+ connect(exitAct, &QAction::triggered, this, &QWidget::close);
clearScreenAct = new QAction(tr("&Clear Screen"), this);
clearScreenAct->setShortcut(tr("Ctrl+L"));
- connect(clearScreenAct, SIGNAL(triggered()),
- scribbleArea, SLOT(clearImage()));
+ connect(clearScreenAct, &QAction::triggered,
+ scribbleArea, &ScribbleArea::clearImage);
aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
+ connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);
}
//! [14]
@@ -163,8 +164,7 @@ void MainWindow::createMenus()
//! [15] //! [16]
{
saveAsMenu = new QMenu(tr("&Save As"), this);
- foreach (QAction *action, saveAsActs)
- saveAsMenu->addAction(action);
+ saveAsMenu->addActions(saveAsActs);
fileMenu = new QMenu(tr("&File"), this);
fileMenu->addAction(openAct);
diff --git a/examples/widgets/touch/fingerpaint/scribblearea.cpp b/examples/widgets/touch/fingerpaint/scribblearea.cpp
index aa4e60c934..0b0c4476d9 100644
--- a/examples/widgets/touch/fingerpaint/scribblearea.cpp
+++ b/examples/widgets/touch/fingerpaint/scribblearea.cpp
@@ -195,9 +195,9 @@ bool ScribbleArea::event(QEvent *event)
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
{
- QTouchEvent *touch = static_cast<QTouchEvent *>(event);
- QList<QTouchEvent::TouchPoint> touchPoints = static_cast<QTouchEvent *>(event)->touchPoints();
- foreach (const QTouchEvent::TouchPoint &touchPoint, touchPoints) {
+ const QTouchEvent *touch = static_cast<QTouchEvent *>(event);
+ const QList<QTouchEvent::TouchPoint> touchPoints = static_cast<QTouchEvent *>(event)->touchPoints();
+ for (const QTouchEvent::TouchPoint &touchPoint : touchPoints) {
switch (touchPoint.state()) {
case Qt::TouchPointStationary:
case Qt::TouchPointReleased:
diff --git a/examples/widgets/touch/pinchzoom/mouse.cpp b/examples/widgets/touch/pinchzoom/mouse.cpp
index 1e6814be13..1dfd7d749c 100644
--- a/examples/widgets/touch/pinchzoom/mouse.cpp
+++ b/examples/widgets/touch/pinchzoom/mouse.cpp
@@ -163,7 +163,7 @@ void Mouse::timerEvent(QTimerEvent *)
<< mapToScene(0, 0)
<< mapToScene(-30, -50)
<< mapToScene(30, -50));
- foreach (QGraphicsItem *item, dangerMice) {
+ for (QGraphicsItem *item : dangerMice) {
if (item == this)
continue;
diff --git a/examples/widgets/tutorials/addressbook/part2/addressbook.cpp b/examples/widgets/tutorials/addressbook/part2/addressbook.cpp
index 34fa5d2060..d5ee394abd 100644
--- a/examples/widgets/tutorials/addressbook/part2/addressbook.cpp
+++ b/examples/widgets/tutorials/addressbook/part2/addressbook.cpp
@@ -74,9 +74,12 @@ AddressBook::AddressBook(QWidget *parent)
cancelButton->hide();
//! [pushbutton declaration]
//! [connecting signals and slots]
- connect(addButton, SIGNAL(clicked()), this, SLOT(addContact()));
- connect(submitButton, SIGNAL(clicked()), this, SLOT(submitContact()));
- connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
+ connect(addButton, &QPushButton::clicked,
+ this, &AddressBook::addContact);
+ connect(submitButton, &QPushButton::clicked,
+ this, &AddressBook::submitContact);
+ connect(cancelButton, &QPushButton::clicked,
+ this, &AddressBook::cancel);
//! [connecting signals and slots]
//! [vertical layout]
QVBoxLayout *buttonLayout1 = new QVBoxLayout;
diff --git a/examples/widgets/tutorials/addressbook/part3/addressbook.cpp b/examples/widgets/tutorials/addressbook/part3/addressbook.cpp
index caef83970a..b6d48f7a0d 100644
--- a/examples/widgets/tutorials/addressbook/part3/addressbook.cpp
+++ b/examples/widgets/tutorials/addressbook/part3/addressbook.cpp
@@ -74,13 +74,17 @@ AddressBook::AddressBook(QWidget *parent)
previousButton = new QPushButton(tr("&Previous"));
previousButton->setEnabled(false);
//! [navigation pushbuttons]
-
- connect(addButton, SIGNAL(clicked()), this, SLOT(addContact()));
- connect(submitButton, SIGNAL(clicked()), this, SLOT(submitContact()));
- connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
+ connect(addButton, &QPushButton::clicked,
+ this, &AddressBook::addContact);
+ connect(submitButton, &QPushButton::clicked,
+ this, &AddressBook::submitContact);
+ connect(cancelButton, &QPushButton::clicked,
+ this, &AddressBook::cancel);
//! [connecting navigation signals]
- connect(nextButton, SIGNAL(clicked()), this, SLOT(next()));
- connect(previousButton, SIGNAL(clicked()), this, SLOT(previous()));
+ connect(nextButton, &QPushButton::clicked,
+ this, &AddressBook::next);
+ connect(previousButton, &QPushButton::clicked,
+ this, &AddressBook::previous);
//! [connecting navigation signals]
QVBoxLayout *buttonLayout1 = new QVBoxLayout;
diff --git a/examples/widgets/tutorials/addressbook/part4/addressbook.cpp b/examples/widgets/tutorials/addressbook/part4/addressbook.cpp
index 92f0776727..77ce216c07 100644
--- a/examples/widgets/tutorials/addressbook/part4/addressbook.cpp
+++ b/examples/widgets/tutorials/addressbook/part4/addressbook.cpp
@@ -79,15 +79,22 @@ AddressBook::AddressBook(QWidget *parent)
previousButton = new QPushButton(tr("&Previous"));
previousButton->setEnabled(false);
- connect(addButton, SIGNAL(clicked()), this, SLOT(addContact()));
- connect(submitButton, SIGNAL(clicked()), this, SLOT(submitContact()));
+ connect(addButton, &QPushButton::clicked,
+ this, &AddressBook::addContact);
+ connect(submitButton, &QPushButton::clicked,
+ this, &AddressBook::submitContact);
//! [connecting edit and remove]
- connect(editButton, SIGNAL(clicked()), this, SLOT(editContact()));
- connect(removeButton, SIGNAL(clicked()), this, SLOT(removeContact()));
+ connect(editButton, &QPushButton::clicked,
+ this, &AddressBook::editContact);
+ connect(removeButton, &QPushButton::clicked,
+ this, &AddressBook::removeContact);
//! [connecting edit and remove]
- connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
- connect(nextButton, SIGNAL(clicked()), this, SLOT(next()));
- connect(previousButton, SIGNAL(clicked()), this, SLOT(previous()));
+ connect(cancelButton, &QPushButton::clicked,
+ this, &AddressBook::cancel);
+ connect(nextButton, &QPushButton::clicked,
+ this, &AddressBook::next);
+ connect(previousButton, &QPushButton::clicked,
+ this, &AddressBook::previous);
QVBoxLayout *buttonLayout1 = new QVBoxLayout;
buttonLayout1->addWidget(addButton);
diff --git a/examples/widgets/tutorials/addressbook/part5/addressbook.cpp b/examples/widgets/tutorials/addressbook/part5/addressbook.cpp
index 6e09ec287d..5505a0e35c 100644
--- a/examples/widgets/tutorials/addressbook/part5/addressbook.cpp
+++ b/examples/widgets/tutorials/addressbook/part5/addressbook.cpp
@@ -86,16 +86,24 @@ AddressBook::AddressBook(QWidget *parent)
dialog = new FindDialog(this);
//! [instantiating FindDialog]
- connect(addButton, SIGNAL(clicked()), this, SLOT(addContact()));
- connect(submitButton, SIGNAL(clicked()), this, SLOT(submitContact()));
- connect(editButton, SIGNAL(clicked()), this, SLOT(editContact()));
- connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
- connect(removeButton, SIGNAL(clicked()), this, SLOT(removeContact()));
+ connect(addButton, &QPushButton::clicked,
+ this, &AddressBook::addContact);
+ connect(submitButton, &QPushButton::clicked,
+ this, &AddressBook::submitContact);
+ connect(editButton, &QPushButton::clicked,
+ this, &AddressBook::editContact);
+ connect(removeButton, &QPushButton::clicked,
+ this, &AddressBook::removeContact);
+ connect(cancelButton, &QPushButton::clicked,
+ this, &AddressBook::cancel);
//! [signals and slots for find]
- connect(findButton, SIGNAL(clicked()), this, SLOT(findContact()));
+ connect(findButton, &QPushButton::clicked,
+ this, &AddressBook::findContact);
//! [signals and slots for find]
- connect(nextButton, SIGNAL(clicked()), this, SLOT(next()));
- connect(previousButton, SIGNAL(clicked()), this, SLOT(previous()));
+ connect(nextButton, &QPushButton::clicked,
+ this, &AddressBook::next);
+ connect(previousButton, &QPushButton::clicked,
+ this, &AddressBook::previous);
QVBoxLayout *buttonLayout1 = new QVBoxLayout;
buttonLayout1->addWidget(addButton);
diff --git a/examples/widgets/tutorials/addressbook/part5/finddialog.cpp b/examples/widgets/tutorials/addressbook/part5/finddialog.cpp
index b0d9a5e6e3..615b39d42f 100644
--- a/examples/widgets/tutorials/addressbook/part5/finddialog.cpp
+++ b/examples/widgets/tutorials/addressbook/part5/finddialog.cpp
@@ -68,8 +68,10 @@ FindDialog::FindDialog(QWidget *parent)
setLayout(layout);
setWindowTitle(tr("Find a Contact"));
- connect(findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
- connect(findButton, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(findButton, &QPushButton::clicked,
+ this, &FindDialog::findClicked);
+ connect(findButton, &QPushButton::clicked,
+ this, &FindDialog::accept);
}
//! [constructor]
//! [findClicked() function]
diff --git a/examples/widgets/tutorials/addressbook/part6/addressbook.cpp b/examples/widgets/tutorials/addressbook/part6/addressbook.cpp
index b2e361a45e..8e740cfffc 100644
--- a/examples/widgets/tutorials/addressbook/part6/addressbook.cpp
+++ b/examples/widgets/tutorials/addressbook/part6/addressbook.cpp
@@ -92,16 +92,26 @@ AddressBook::AddressBook(QWidget *parent)
dialog = new FindDialog(this);
- connect(addButton, SIGNAL(clicked()), this, SLOT(addContact()));
- connect(submitButton, SIGNAL(clicked()), this, SLOT(submitContact()));
- connect(editButton, SIGNAL(clicked()), this, SLOT(editContact()));
- connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
- connect(removeButton, SIGNAL(clicked()), this, SLOT(removeContact()));
- connect(findButton, SIGNAL(clicked()), this, SLOT(findContact()));
- connect(nextButton, SIGNAL(clicked()), this, SLOT(next()));
- connect(previousButton, SIGNAL(clicked()), this, SLOT(previous()));
- connect(loadButton, SIGNAL(clicked()), this, SLOT(loadFromFile()));
- connect(saveButton, SIGNAL(clicked()), this, SLOT(saveToFile()));
+ connect(addButton, &QPushButton::clicked,
+ this, &AddressBook::addContact);
+ connect(submitButton, &QPushButton::clicked,
+ this, &AddressBook::submitContact);
+ connect(editButton, &QPushButton::clicked,
+ this, &AddressBook::editContact);
+ connect(removeButton, &QPushButton::clicked,
+ this, &AddressBook::removeContact);
+ connect(cancelButton, &QPushButton::clicked,
+ this, &AddressBook::cancel);
+ connect(findButton, &QPushButton::clicked,
+ this, &AddressBook::findContact);
+ connect(nextButton, &QPushButton::clicked,
+ this, &AddressBook::next);
+ connect(previousButton, &QPushButton::clicked,
+ this, &AddressBook::previous);
+ connect(loadButton, &QPushButton::clicked,
+ this, &AddressBook::loadFromFile);
+ connect(saveButton, &QPushButton::clicked,
+ this, &AddressBook::saveToFile);
QVBoxLayout *buttonLayout1 = new QVBoxLayout;
buttonLayout1->addWidget(addButton);
diff --git a/examples/widgets/tutorials/addressbook/part6/finddialog.cpp b/examples/widgets/tutorials/addressbook/part6/finddialog.cpp
index 6a1e6b116f..c25cccd552 100644
--- a/examples/widgets/tutorials/addressbook/part6/finddialog.cpp
+++ b/examples/widgets/tutorials/addressbook/part6/finddialog.cpp
@@ -67,8 +67,10 @@ FindDialog::FindDialog(QWidget *parent)
setLayout(layout);
setWindowTitle(tr("Find a Contact"));
- connect(findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
- connect(findButton, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(findButton, &QPushButton::clicked,
+ this, &FindDialog::findClicked);
+ connect(findButton, &QPushButton::clicked,
+ this, &FindDialog::accept);
}
void FindDialog::findClicked()
diff --git a/examples/widgets/tutorials/addressbook/part7/addressbook.cpp b/examples/widgets/tutorials/addressbook/part7/addressbook.cpp
index e946c873e3..717d0882af 100644
--- a/examples/widgets/tutorials/addressbook/part7/addressbook.cpp
+++ b/examples/widgets/tutorials/addressbook/part7/addressbook.cpp
@@ -92,17 +92,28 @@ AddressBook::AddressBook(QWidget *parent)
dialog = new FindDialog(this);
- connect(addButton, SIGNAL(clicked()), this, SLOT(addContact()));
- connect(submitButton, SIGNAL(clicked()), this, SLOT(submitContact()));
- connect(editButton, SIGNAL(clicked()), this, SLOT(editContact()));
- connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
- connect(removeButton, SIGNAL(clicked()), this, SLOT(removeContact()));
- connect(findButton, SIGNAL(clicked()), this, SLOT(findContact()));
- connect(nextButton, SIGNAL(clicked()), this, SLOT(next()));
- connect(previousButton, SIGNAL(clicked()), this, SLOT(previous()));
- connect(loadButton, SIGNAL(clicked()), this, SLOT(loadFromFile()));
- connect(saveButton, SIGNAL(clicked()), this, SLOT(saveToFile()));
- connect(exportButton, SIGNAL(clicked()), this, SLOT(exportAsVCard()));
+ connect(addButton, &QPushButton::clicked,
+ this, &AddressBook::addContact);
+ connect(submitButton, &QPushButton::clicked,
+ this, &AddressBook::submitContact);
+ connect(editButton, &QPushButton::clicked,
+ this, &AddressBook::editContact);
+ connect(removeButton, &QPushButton::clicked,
+ this, &AddressBook::removeContact);
+ connect(cancelButton, &QPushButton::clicked,
+ this, &AddressBook::cancel);
+ connect(findButton, &QPushButton::clicked,
+ this, &AddressBook::findContact);
+ connect(nextButton, &QPushButton::clicked,
+ this, &AddressBook::next);
+ connect(previousButton, &QPushButton::clicked,
+ this, &AddressBook::previous);
+ connect(loadButton, &QPushButton::clicked,
+ this, &AddressBook::loadFromFile);
+ connect(saveButton, &QPushButton::clicked,
+ this, &AddressBook::saveToFile);
+ connect(exportButton, &QPushButton::clicked,
+ this, &AddressBook::exportAsVCard);
QVBoxLayout *buttonLayout1 = new QVBoxLayout;
buttonLayout1->addWidget(addButton);
diff --git a/examples/widgets/tutorials/addressbook/part7/finddialog.cpp b/examples/widgets/tutorials/addressbook/part7/finddialog.cpp
index 6a1e6b116f..c25cccd552 100644
--- a/examples/widgets/tutorials/addressbook/part7/finddialog.cpp
+++ b/examples/widgets/tutorials/addressbook/part7/finddialog.cpp
@@ -67,8 +67,10 @@ FindDialog::FindDialog(QWidget *parent)
setLayout(layout);
setWindowTitle(tr("Find a Contact"));
- connect(findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
- connect(findButton, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(findButton, &QPushButton::clicked,
+ this, &FindDialog::findClicked);
+ connect(findButton, &QPushButton::clicked,
+ this, &FindDialog::accept);
}
void FindDialog::findClicked()
diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part2/main.cpp b/examples/widgets/tutorials/gettingStarted/gsQt/part2/main.cpp
index 90f5f1a6b3..8bf83859a0 100644
--- a/examples/widgets/tutorials/gettingStarted/gsQt/part2/main.cpp
+++ b/examples/widgets/tutorials/gettingStarted/gsQt/part2/main.cpp
@@ -57,7 +57,8 @@ int main(int argc, char *argv[])
QTextEdit *textEdit = new QTextEdit;
QPushButton *quitButton = new QPushButton("&Quit");
- QObject::connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
+ QObject::connect(quitButton, &QPushButton::clicked,
+ qApp, &QApplication::quit);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(textEdit);
diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part3/main.cpp b/examples/widgets/tutorials/gettingStarted/gsQt/part3/main.cpp
index 0a60c1cf16..d4b43eb034 100644
--- a/examples/widgets/tutorials/gettingStarted/gsQt/part3/main.cpp
+++ b/examples/widgets/tutorials/gettingStarted/gsQt/part3/main.cpp
@@ -71,7 +71,8 @@ Notepad::Notepad()
textEdit = new QTextEdit;
quitButton = new QPushButton(tr("Quit"));
- connect(quitButton, SIGNAL(clicked()), this, SLOT(quit()));
+ connect(quitButton, &QPushButton::clicked,
+ this, &Notepad::quit);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(textEdit);
diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part4/main.cpp b/examples/widgets/tutorials/gettingStarted/gsQt/part4/main.cpp
index 6d9e96a3d4..8c5fbc70ca 100644
--- a/examples/widgets/tutorials/gettingStarted/gsQt/part4/main.cpp
+++ b/examples/widgets/tutorials/gettingStarted/gsQt/part4/main.cpp
@@ -73,14 +73,16 @@ private:
Notepad::Notepad()
{
-
loadAction = new QAction(tr("&Load"), this);
saveAction = new QAction(tr("&Save"), this);
exitAction = new QAction(tr("E&xit"), this);
- connect(loadAction, SIGNAL(triggered()), this, SLOT(load()));
- connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));
- connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ connect(loadAction, &QAction::triggered,
+ this, &Notepad::load);
+ connect(saveAction, &QAction::triggered,
+ this, &Notepad::save);
+ connect(exitAction, &QAction::triggered,
+ qApp, &QApplication::quit);
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(loadAction);
diff --git a/examples/widgets/tutorials/gettingStarted/gsQt/part5/main.cpp b/examples/widgets/tutorials/gettingStarted/gsQt/part5/main.cpp
index b2b4a73874..cc3e1a261c 100644
--- a/examples/widgets/tutorials/gettingStarted/gsQt/part5/main.cpp
+++ b/examples/widgets/tutorials/gettingStarted/gsQt/part5/main.cpp
@@ -73,14 +73,16 @@ private:
Notepad::Notepad()
{
-
openAction = new QAction(tr("&Load"), this);
saveAction = new QAction(tr("&Save"), this);
exitAction = new QAction(tr("E&xit"), this);
- connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
- connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));
- connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ connect(openAction, &QAction::triggered,
+ this, &Notepad::open);
+ connect(saveAction, &QAction::triggered,
+ this, &Notepad::save);
+ connect(exitAction, &QAction::triggered,
+ qApp, &QApplication::quit);
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);
diff --git a/examples/widgets/tutorials/widgets/nestedlayouts/main.cpp b/examples/widgets/tutorials/widgets/nestedlayouts/main.cpp
index 9acc74b469..8880dbe3d0 100644
--- a/examples/widgets/tutorials/widgets/nestedlayouts/main.cpp
+++ b/examples/widgets/tutorials/widgets/nestedlayouts/main.cpp
@@ -76,25 +76,26 @@ int main(int argc, char *argv[])
//! [set up the model]
QStandardItemModel model;
- model.setHorizontalHeaderLabels(
- QStringList() << QApplication::translate("nestedlayouts", "Name")
- << QApplication::translate("nestedlayouts", "Office"));
+ model.setHorizontalHeaderLabels({ QApplication::translate("nestedlayouts", "Name"),
+ QApplication::translate("nestedlayouts", "Office") });
- QList<QStringList> rows = QList<QStringList>()
- << (QStringList() << "Verne Nilsen" << "123")
- << (QStringList() << "Carlos Tang" << "77")
- << (QStringList() << "Bronwyn Hawcroft" << "119")
- << (QStringList() << "Alessandro Hanssen" << "32")
- << (QStringList() << "Andrew John Bakken" << "54")
- << (QStringList() << "Vanessa Weatherley" << "85")
- << (QStringList() << "Rebecca Dickens" << "17")
- << (QStringList() << "David Bradley" << "42")
- << (QStringList() << "Knut Walters" << "25")
- << (QStringList() << "Andrea Jones" << "34");
+ const QStringList rows[] = {
+ QStringList{ QStringLiteral("Verne Nilsen"), QStringLiteral("123") },
+ QStringList{ QStringLiteral("Carlos Tang"), QStringLiteral("77") },
+ QStringList{ QStringLiteral("Bronwyn Hawcroft"), QStringLiteral("119") },
+ QStringList{ QStringLiteral("Alessandro Hanssen"), QStringLiteral("32") },
+ QStringList{ QStringLiteral("Andrew John Bakken"), QStringLiteral("54") },
+ QStringList{ QStringLiteral("Vanessa Weatherley"), QStringLiteral("85") },
+ QStringList{ QStringLiteral("Rebecca Dickens"), QStringLiteral("17") },
+ QStringList{ QStringLiteral("David Bradley"), QStringLiteral("42") },
+ QStringList{ QStringLiteral("Knut Walters"), QStringLiteral("25") },
+ QStringList{ QStringLiteral("Andrea Jones"), QStringLiteral("34") }
+ };
- foreach (QStringList row, rows) {
- QList<QStandardItem *> items;
- foreach (QString text, row)
+ QList<QStandardItem *> items;
+ for (const QStringList &row : rows) {
+ items.clear();
+ for (const QString &text : row)
items.append(new QStandardItem(text));
model.appendRow(items);
}
diff --git a/examples/widgets/widgets/analogclock/analogclock.cpp b/examples/widgets/widgets/analogclock/analogclock.cpp
index 0dc2fbc708..c7b3f66cca 100644
--- a/examples/widgets/widgets/analogclock/analogclock.cpp
+++ b/examples/widgets/widgets/analogclock/analogclock.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "analogclock.h"
+#include <QtWidgets>
+
//! [0] //! [1]
AnalogClock::AnalogClock(QWidget *parent)
//! [0] //! [2]
@@ -61,7 +61,7 @@ AnalogClock::AnalogClock(QWidget *parent)
//! [3] //! [4]
QTimer *timer = new QTimer(this);
//! [4] //! [5]
- connect(timer, SIGNAL(timeout()), this, SLOT(update()));
+ connect(timer, &QTimer::timeout, this, QOverload<>::of(&AnalogClock::update));
//! [5] //! [6]
timer->start(1000);
//! [6]
diff --git a/examples/widgets/widgets/analogclock/analogclock.h b/examples/widgets/widgets/analogclock/analogclock.h
index 19e580d1ac..e2486a915f 100644
--- a/examples/widgets/widgets/analogclock/analogclock.h
+++ b/examples/widgets/widgets/analogclock/analogclock.h
@@ -59,7 +59,7 @@ class AnalogClock : public QWidget
Q_OBJECT
public:
- AnalogClock(QWidget *parent = 0);
+ AnalogClock(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event) override;
diff --git a/examples/widgets/widgets/calculator/button.cpp b/examples/widgets/widgets/calculator/button.cpp
index 0d622b1781..a1ce0bf428 100644
--- a/examples/widgets/widgets/calculator/button.cpp
+++ b/examples/widgets/widgets/calculator/button.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "button.h"
+#include <QtWidgets>
+
//! [0]
Button::Button(const QString &text, QWidget *parent)
: QToolButton(parent)
diff --git a/examples/widgets/widgets/calculator/button.h b/examples/widgets/widgets/calculator/button.h
index 057640700f..7c6f26867f 100644
--- a/examples/widgets/widgets/calculator/button.h
+++ b/examples/widgets/widgets/calculator/button.h
@@ -59,7 +59,7 @@ class Button : public QToolButton
Q_OBJECT
public:
- explicit Button(const QString &text, QWidget *parent = 0);
+ explicit Button(const QString &text, QWidget *parent = nullptr);
QSize sizeHint() const override;
};
diff --git a/examples/widgets/widgets/calculator/calculator.cpp b/examples/widgets/widgets/calculator/calculator.cpp
index cbcc29b2a8..dd908cf40a 100644
--- a/examples/widgets/widgets/calculator/calculator.cpp
+++ b/examples/widgets/widgets/calculator/calculator.cpp
@@ -48,13 +48,13 @@
**
****************************************************************************/
+#include "button.h"
+#include "calculator.h"
+
#include <QtWidgets>
#include <cmath>
-#include "button.h"
-#include "calculator.h"
-
//! [0]
Calculator::Calculator(QWidget *parent)
: QWidget(parent)
diff --git a/examples/widgets/widgets/calculator/calculator.h b/examples/widgets/widgets/calculator/calculator.h
index 6d7e336347..937de185e7 100644
--- a/examples/widgets/widgets/calculator/calculator.h
+++ b/examples/widgets/widgets/calculator/calculator.h
@@ -64,7 +64,7 @@ class Calculator : public QWidget
Q_OBJECT
public:
- Calculator(QWidget *parent = 0);
+ Calculator(QWidget *parent = nullptr);
private slots:
void digitClicked();
diff --git a/examples/widgets/widgets/calendarwidget/window.cpp b/examples/widgets/widgets/calendarwidget/window.cpp
index c3a0e1e3f7..64047aaac9 100644
--- a/examples/widgets/widgets/calendarwidget/window.cpp
+++ b/examples/widgets/widgets/calendarwidget/window.cpp
@@ -53,7 +53,8 @@
#include "window.h"
//! [0]
-Window::Window()
+Window::Window(QWidget *parent)
+ : QWidget(parent)
{
createPreviewGroupBox();
createGeneralOptionsGroupBox();
@@ -220,8 +221,8 @@ void Window::createPreviewGroupBox()
calendar->setMaximumDate(QDate(3000, 1, 1));
calendar->setGridVisible(true);
- connect(calendar, SIGNAL(currentPageChanged(int,int)),
- this, SLOT(reformatCalendarPage()));
+ connect(calendar, &QCalendarWidget::currentPageChanged,
+ this, &Window::reformatCalendarPage);
previewLayout = new QGridLayout;
previewLayout->addWidget(calendar, 0, 0, Qt::AlignCenter);
@@ -305,20 +306,20 @@ void Window::createGeneralOptionsGroupBox()
verticalHeaderLabel->setBuddy(verticalHeaderCombo);
//! [11]
- connect(localeCombo, SIGNAL(currentIndexChanged(int)),
- this, SLOT(localeChanged(int)));
- connect(firstDayCombo, SIGNAL(currentIndexChanged(int)),
- this, SLOT(firstDayChanged(int)));
- connect(selectionModeCombo, SIGNAL(currentIndexChanged(int)),
- this, SLOT(selectionModeChanged(int)));
- connect(gridCheckBox, SIGNAL(toggled(bool)),
- calendar, SLOT(setGridVisible(bool)));
- connect(navigationCheckBox, SIGNAL(toggled(bool)),
- calendar, SLOT(setNavigationBarVisible(bool)));
- connect(horizontalHeaderCombo, SIGNAL(currentIndexChanged(int)),
- this, SLOT(horizontalHeaderChanged(int)));
- connect(verticalHeaderCombo, SIGNAL(currentIndexChanged(int)),
- this, SLOT(verticalHeaderChanged(int)));
+ connect(localeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &Window::localeChanged);
+ connect(firstDayCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &Window::firstDayChanged);
+ connect(selectionModeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &Window::selectionModeChanged);
+ connect(gridCheckBox, &QCheckBox::toggled,
+ calendar, &QCalendarWidget::setGridVisible);
+ connect(navigationCheckBox, &QCheckBox::toggled,
+ calendar, &QCalendarWidget::setNavigationBarVisible);
+ connect(horizontalHeaderCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &Window::horizontalHeaderChanged);
+ connect(verticalHeaderCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &Window::verticalHeaderChanged);
//! [11]
QHBoxLayout *checkBoxLayout = new QHBoxLayout;
@@ -381,14 +382,14 @@ void Window::createDatesGroupBox()
maximumDateLabel->setBuddy(maximumDateEdit);
//! [13] //! [14]
- connect(currentDateEdit, SIGNAL(dateChanged(QDate)),
- calendar, SLOT(setSelectedDate(QDate)));
- connect(calendar, SIGNAL(selectionChanged()),
- this, SLOT(selectedDateChanged()));
- connect(minimumDateEdit, SIGNAL(dateChanged(QDate)),
- this, SLOT(minimumDateChanged(QDate)));
- connect(maximumDateEdit, SIGNAL(dateChanged(QDate)),
- this, SLOT(maximumDateChanged(QDate)));
+ connect(currentDateEdit, &QDateEdit::dateChanged,
+ calendar, &QCalendarWidget::setSelectedDate);
+ connect(calendar, &QCalendarWidget::selectionChanged,
+ this, &Window::selectedDateChanged);
+ connect(minimumDateEdit, &QDateEdit::dateChanged,
+ this, &Window::minimumDateChanged);
+ connect(maximumDateEdit, &QDateEdit::dateChanged,
+ this, &Window::maximumDateChanged);
//! [14]
QGridLayout *dateBoxLayout = new QGridLayout;
@@ -438,20 +439,20 @@ void Window::createTextFormatsGroupBox()
mayFirstCheckBox = new QCheckBox(tr("May &1 in red"));
//! [17] //! [18]
- connect(weekdayColorCombo, SIGNAL(currentIndexChanged(int)),
- this, SLOT(weekdayFormatChanged()));
- connect(weekdayColorCombo, SIGNAL(currentIndexChanged(int)),
- this, SLOT(reformatCalendarPage()));
- connect(weekendColorCombo, SIGNAL(currentIndexChanged(int)),
- this, SLOT(weekendFormatChanged()));
- connect(weekendColorCombo, SIGNAL(currentIndexChanged(int)),
- this, SLOT(reformatCalendarPage()));
- connect(headerTextFormatCombo, SIGNAL(currentIndexChanged(QString)),
- this, SLOT(reformatHeaders()));
- connect(firstFridayCheckBox, SIGNAL(toggled(bool)),
- this, SLOT(reformatCalendarPage()));
- connect(mayFirstCheckBox, SIGNAL(toggled(bool)),
- this, SLOT(reformatCalendarPage()));
+ connect(weekdayColorCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &Window::weekdayFormatChanged);
+ connect(weekdayColorCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &Window::reformatCalendarPage);
+ connect(weekendColorCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &Window::weekendFormatChanged);
+ connect(weekendColorCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &Window::reformatCalendarPage);
+ connect(headerTextFormatCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &Window::reformatHeaders);
+ connect(firstFridayCheckBox, &QCheckBox::toggled,
+ this, &Window::reformatCalendarPage);
+ connect(mayFirstCheckBox, &QCheckBox::toggled,
+ this, &Window::reformatCalendarPage);
//! [18]
QHBoxLayout *checkBoxLayout = new QHBoxLayout;
diff --git a/examples/widgets/widgets/calendarwidget/window.h b/examples/widgets/widgets/calendarwidget/window.h
index fa01fc4db6..83ea494fc2 100644
--- a/examples/widgets/widgets/calendarwidget/window.h
+++ b/examples/widgets/widgets/calendarwidget/window.h
@@ -70,7 +70,7 @@ class Window : public QWidget
Q_OBJECT
public:
- Window();
+ Window(QWidget *parent = nullptr);
private slots:
void localeChanged(int index);
diff --git a/examples/widgets/widgets/charactermap/characterwidget.cpp b/examples/widgets/widgets/charactermap/characterwidget.cpp
index 5bab921516..061c0164b0 100644
--- a/examples/widgets/widgets/charactermap/characterwidget.cpp
+++ b/examples/widgets/widgets/charactermap/characterwidget.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "characterwidget.h"
+#include <QtWidgets>
+
//! [0]
CharacterWidget::CharacterWidget(QWidget *parent)
: QWidget(parent), columns(16), lastKey(-1)
diff --git a/examples/widgets/widgets/charactermap/characterwidget.h b/examples/widgets/widgets/charactermap/characterwidget.h
index 53add51e6f..d12a46aa15 100644
--- a/examples/widgets/widgets/charactermap/characterwidget.h
+++ b/examples/widgets/widgets/charactermap/characterwidget.h
@@ -52,7 +52,6 @@
#define CHARACTERWIDGET_H
#include <QFont>
-#include <QPoint>
#include <QSize>
#include <QString>
#include <QWidget>
@@ -68,7 +67,7 @@ class CharacterWidget : public QWidget
Q_OBJECT
public:
- CharacterWidget(QWidget *parent = 0);
+ CharacterWidget(QWidget *parent = nullptr);
QSize sizeHint() const override;
public slots:
diff --git a/examples/widgets/widgets/charactermap/mainwindow.cpp b/examples/widgets/widgets/charactermap/mainwindow.cpp
index d3ac55483c..77aad145e7 100644
--- a/examples/widgets/widgets/charactermap/mainwindow.cpp
+++ b/examples/widgets/widgets/charactermap/mainwindow.cpp
@@ -57,7 +57,8 @@
Q_DECLARE_METATYPE(QFontComboBox::FontFilter)
-MainWindow::MainWindow()
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
{
QMenu *fileMenu = menuBar()->addMenu(tr("File"));
fileMenu->addAction(tr("Quit"), this, &QWidget::close);
@@ -113,9 +114,9 @@ MainWindow::MainWindow()
this, &MainWindow::findSizes);
connect(fontCombo, &QFontComboBox::currentFontChanged,
characterWidget, &CharacterWidget::updateFont);
- connect(sizeCombo, QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
+ connect(sizeCombo, &QComboBox::currentTextChanged,
characterWidget, &CharacterWidget::updateSize);
- connect(styleCombo, QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
+ connect(styleCombo, &QComboBox::currentTextChanged,
characterWidget, &CharacterWidget::updateStyle);
//! [4] //! [5]
connect(characterWidget, &CharacterWidget::characterSelected,
@@ -169,8 +170,8 @@ void MainWindow::findStyles(const QFont &font)
//! [7]
//! [8]
- QString style;
- foreach (style, fontDatabase.styles(font.family()))
+ const QStringList styles = fontDatabase.styles(font.family());
+ for (const QString &style : styles)
styleCombo->addItem(style);
int styleIndex = styleCombo->findText(currentItem);
@@ -187,7 +188,7 @@ void MainWindow::filterChanged(int f)
const QFontComboBox::FontFilter filter =
filterCombo->itemData(f).value<QFontComboBox::FontFilter>();
fontCombo->setFontFilters(filter);
- statusBar()->showMessage(tr("%n font(s) found", 0, fontCombo->count()));
+ statusBar()->showMessage(tr("%n font(s) found", nullptr, fontCombo->count()));
}
void MainWindow::findSizes(const QFont &font)
@@ -200,15 +201,16 @@ void MainWindow::findSizes(const QFont &font)
// sizeCombo signals are now blocked until end of scope
sizeCombo->clear();
- int size;
if (fontDatabase.isSmoothlyScalable(font.family(), fontDatabase.styleString(font))) {
- foreach (size, QFontDatabase::standardSizes()) {
+ const QList<int> sizes = QFontDatabase::standardSizes();
+ for (const int size : sizes) {
sizeCombo->addItem(QVariant(size).toString());
sizeCombo->setEditable(true);
}
} else {
- foreach (size, fontDatabase.smoothSizes(font.family(), fontDatabase.styleString(font))) {
+ const QList<int> sizes = fontDatabase.smoothSizes(font.family(), fontDatabase.styleString(font));
+ for (const int size : sizes ) {
sizeCombo->addItem(QVariant(size).toString());
sizeCombo->setEditable(false);
}
diff --git a/examples/widgets/widgets/charactermap/mainwindow.h b/examples/widgets/widgets/charactermap/mainwindow.h
index eac16b35fa..79fe9f9cc8 100644
--- a/examples/widgets/widgets/charactermap/mainwindow.h
+++ b/examples/widgets/widgets/charactermap/mainwindow.h
@@ -70,7 +70,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
- MainWindow();
+ MainWindow(QWidget *parent = nullptr);
public slots:
void filterChanged(int);
diff --git a/examples/widgets/widgets/codeeditor/codeeditor.cpp b/examples/widgets/widgets/codeeditor/codeeditor.cpp
index 7e56a75294..8e29860669 100644
--- a/examples/widgets/widgets/codeeditor/codeeditor.cpp
+++ b/examples/widgets/widgets/codeeditor/codeeditor.cpp
@@ -58,9 +58,9 @@ CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent)
{
lineNumberArea = new LineNumberArea(this);
- connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
- connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
- connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
+ connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
+ connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
+ connect(this, &CodeEditor::cursorPositionChanged, this, &CodeEditor::highlightCurrentLine);
updateLineNumberAreaWidth(0);
highlightCurrentLine();
diff --git a/examples/widgets/widgets/codeeditor/codeeditor.h b/examples/widgets/widgets/codeeditor/codeeditor.h
index 65be76d81d..5a48abafc4 100644
--- a/examples/widgets/widgets/codeeditor/codeeditor.h
+++ b/examples/widgets/widgets/codeeditor/codeeditor.h
@@ -52,7 +52,6 @@
#define CODEEDITOR_H
#include <QPlainTextEdit>
-#include <QObject>
QT_BEGIN_NAMESPACE
class QPaintEvent;
@@ -70,7 +69,7 @@ class CodeEditor : public QPlainTextEdit
Q_OBJECT
public:
- CodeEditor(QWidget *parent = 0);
+ CodeEditor(QWidget *parent = nullptr);
void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberAreaWidth();
diff --git a/examples/widgets/widgets/digitalclock/digitalclock.cpp b/examples/widgets/widgets/digitalclock/digitalclock.cpp
index dec7e64fc3..000334f33b 100644
--- a/examples/widgets/widgets/digitalclock/digitalclock.cpp
+++ b/examples/widgets/widgets/digitalclock/digitalclock.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "digitalclock.h"
+#include <QtWidgets>
+
//! [0]
DigitalClock::DigitalClock(QWidget *parent)
: QLCDNumber(parent)
diff --git a/examples/widgets/widgets/digitalclock/digitalclock.h b/examples/widgets/widgets/digitalclock/digitalclock.h
index 4365b965bf..31c12f39ab 100644
--- a/examples/widgets/widgets/digitalclock/digitalclock.h
+++ b/examples/widgets/widgets/digitalclock/digitalclock.h
@@ -59,7 +59,7 @@ class DigitalClock : public QLCDNumber
Q_OBJECT
public:
- DigitalClock(QWidget *parent = 0);
+ DigitalClock(QWidget *parent = nullptr);
private slots:
void showTime();
diff --git a/examples/widgets/widgets/elidedlabel/elidedlabel.cpp b/examples/widgets/widgets/elidedlabel/elidedlabel.cpp
index b12bf118f6..e80f7a9894 100644
--- a/examples/widgets/widgets/elidedlabel/elidedlabel.cpp
+++ b/examples/widgets/widgets/elidedlabel/elidedlabel.cpp
@@ -51,8 +51,8 @@
#include "elidedlabel.h"
#include <QPainter>
+#include <QSizePolicy>
#include <QTextLayout>
-#include <QDebug>
//! [0]
ElidedLabel::ElidedLabel(const QString &text, QWidget *parent)
diff --git a/examples/widgets/widgets/elidedlabel/elidedlabel.h b/examples/widgets/widgets/elidedlabel/elidedlabel.h
index 8a2a40f49a..0c8d96834e 100644
--- a/examples/widgets/widgets/elidedlabel/elidedlabel.h
+++ b/examples/widgets/widgets/elidedlabel/elidedlabel.h
@@ -51,11 +51,8 @@
#ifndef ELIDEDLABEL_H
#define ELIDEDLABEL_H
-#include <QtWidgets/QFrame>
-#include <QtCore/QRect>
-#include <QtGui/QResizeEvent>
-#include <QtCore/QString>
-#include <QtWidgets/QWidget>
+#include <QFrame>
+#include <QString>
//! [0]
class ElidedLabel : public QFrame
@@ -65,7 +62,7 @@ class ElidedLabel : public QFrame
Q_PROPERTY(bool isElided READ isElided)
public:
- explicit ElidedLabel(const QString &text, QWidget *parent = 0);
+ explicit ElidedLabel(const QString &text, QWidget *parent = nullptr);
void setText(const QString &text);
const QString & text() const { return content; }
diff --git a/examples/widgets/widgets/elidedlabel/main.cpp b/examples/widgets/widgets/elidedlabel/main.cpp
index f692db0efc..1c620c1d41 100644
--- a/examples/widgets/widgets/elidedlabel/main.cpp
+++ b/examples/widgets/widgets/elidedlabel/main.cpp
@@ -50,7 +50,7 @@
#include "testwidget.h"
-#include <QtWidgets/QApplication>
+#include <QApplication>
//! [0]
int main( int argc, char *argv[] )
diff --git a/examples/widgets/widgets/elidedlabel/testwidget.cpp b/examples/widgets/widgets/elidedlabel/testwidget.cpp
index 6392a4b4fa..4e013cc5de 100644
--- a/examples/widgets/widgets/elidedlabel/testwidget.cpp
+++ b/examples/widgets/widgets/elidedlabel/testwidget.cpp
@@ -51,14 +51,13 @@
#include "testwidget.h"
#include "elidedlabel.h"
-#include <QtWidgets/QLabel>
-#include <QtWidgets/QPushButton>
-#include <QtWidgets/QSizePolicy>
-#include <QtWidgets/QGridLayout>
+#include <QGridLayout>
+#include <QLabel>
+#include <QPushButton>
//! [0]
-TestWidget::TestWidget(QWidget *parent):
- QWidget(parent)
+TestWidget::TestWidget(QWidget *parent)
+ : QWidget(parent)
{
const QString romeo = tr(
"But soft, what light through yonder window breaks? / "
@@ -116,7 +115,7 @@ TestWidget::TestWidget(QWidget *parent):
//! [3]
//! [4]
- QGridLayout *layout = new QGridLayout();
+ QGridLayout *layout = new QGridLayout;
layout->addWidget(label, 0, 1, Qt::AlignCenter);
layout->addWidget(switchButton, 0, 2);
layout->addWidget(exitButton, 0, 3);
diff --git a/examples/widgets/widgets/elidedlabel/testwidget.h b/examples/widgets/widgets/elidedlabel/testwidget.h
index 840bc98b40..bcb2f33044 100644
--- a/examples/widgets/widgets/elidedlabel/testwidget.h
+++ b/examples/widgets/widgets/elidedlabel/testwidget.h
@@ -51,10 +51,9 @@
#ifndef TESTWIDGET_H
#define TESTWIDGET_H
-#include <QtWidgets/QWidget>
-#include <QtCore/QStringList>
-#include <QtWidgets/QSlider>
-#include <QtWidgets/QComboBox>
+#include <QSlider>
+#include <QStringList>
+#include <QWidget>
class ElidedLabel;
@@ -64,7 +63,7 @@ class TestWidget : public QWidget
Q_OBJECT
public:
- TestWidget(QWidget *parent = 0);
+ TestWidget(QWidget *parent = nullptr);
protected:
void resizeEvent(QResizeEvent *event) override;
diff --git a/examples/widgets/widgets/groupbox/window.h b/examples/widgets/widgets/groupbox/window.h
index 566fafa151..1f041fd003 100644
--- a/examples/widgets/widgets/groupbox/window.h
+++ b/examples/widgets/widgets/groupbox/window.h
@@ -63,7 +63,7 @@ class Window : public QWidget
Q_OBJECT
public:
- Window(QWidget *parent = 0);
+ Window(QWidget *parent = nullptr);
private:
QGroupBox *createFirstExclusiveGroup();
diff --git a/examples/widgets/widgets/icons/iconpreviewarea.cpp b/examples/widgets/widgets/icons/iconpreviewarea.cpp
index 9cb54c47f6..7a73a137cd 100644
--- a/examples/widgets/widgets/icons/iconpreviewarea.cpp
+++ b/examples/widgets/widgets/icons/iconpreviewarea.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "iconpreviewarea.h"
+#include <QtWidgets>
+
//! [0]
IconPreviewArea::IconPreviewArea(QWidget *parent)
: QWidget(parent)
@@ -79,8 +79,6 @@ IconPreviewArea::IconPreviewArea(QWidget *parent)
}
//! [0]
-#ifdef Q_COMPILER_INITIALIZER_LISTS
-
//! [42]
QVector<QIcon::Mode> IconPreviewArea::iconModes()
{
@@ -107,44 +105,6 @@ QStringList IconPreviewArea::iconStateNames()
}
//! [42]
-#else // Q_COMPILER_INITIALIZER_LISTS
-
-//! [43]
-QVector<QIcon::Mode> IconPreviewArea::iconModes()
-{
- static QVector<QIcon::Mode> result;
- if (result.isEmpty())
- result << QIcon::Normal << QIcon::Active << QIcon::Disabled << QIcon::Selected;
- return result;
-}
-//! [43]
-
-QVector<QIcon::State> IconPreviewArea::iconStates()
-{
- static QVector<QIcon::State> result;
- if (result.isEmpty())
- result << QIcon::Off << QIcon::On;
- return result;
-}
-
-QStringList IconPreviewArea::iconModeNames()
-{
- static QStringList result;
- if (result.isEmpty())
- result << tr("Normal") << tr("Active") << tr("Disabled") << tr("Selected");
- return result;
-}
-
-QStringList IconPreviewArea::iconStateNames()
-{
- static QStringList result;
- if (result.isEmpty())
- result << tr("Off") << tr("On");
- return result;
-}
-
-#endif // !Q_COMPILER_INITIALIZER_LISTS
-
//! [1]
void IconPreviewArea::setIcon(const QIcon &icon)
{
diff --git a/examples/widgets/widgets/icons/iconsizespinbox.cpp b/examples/widgets/widgets/icons/iconsizespinbox.cpp
index 4c6a850858..e94d943993 100644
--- a/examples/widgets/widgets/icons/iconsizespinbox.cpp
+++ b/examples/widgets/widgets/icons/iconsizespinbox.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "iconsizespinbox.h"
+#include <QtWidgets>
+
//! [0]
IconSizeSpinBox::IconSizeSpinBox(QWidget *parent)
: QSpinBox(parent)
diff --git a/examples/widgets/widgets/icons/imagedelegate.cpp b/examples/widgets/widgets/icons/imagedelegate.cpp
index 3c873f1e24..786194bae7 100644
--- a/examples/widgets/widgets/icons/imagedelegate.cpp
+++ b/examples/widgets/widgets/icons/imagedelegate.cpp
@@ -48,11 +48,11 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "imagedelegate.h"
#include "iconpreviewarea.h"
+#include <QtWidgets>
+
//! [0]
ImageDelegate::ImageDelegate(QObject *parent)
: QItemDelegate(parent)
diff --git a/examples/widgets/widgets/icons/mainwindow.cpp b/examples/widgets/widgets/icons/mainwindow.cpp
index f704b8306f..91e98ff896 100644
--- a/examples/widgets/widgets/icons/mainwindow.cpp
+++ b/examples/widgets/widgets/icons/mainwindow.cpp
@@ -55,12 +55,15 @@
#include "imagedelegate.h"
#include "mainwindow.h"
+#include <memory>
+
//! [40]
enum { OtherSize = QStyle::PM_CustomBase };
//! [40]
//! [0]
-MainWindow::MainWindow()
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
{
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
@@ -121,7 +124,8 @@ void MainWindow::changeStyle(bool checked)
Q_ASSERT(style);
QApplication::setStyle(style);
- foreach (QAbstractButton *button, sizeButtonGroup->buttons()) {
+ const QList<QAbstractButton*> buttons = sizeButtonGroup->buttons();
+ for (QAbstractButton *button : buttons) {
const QStyle::PixelMetric metric = static_cast<QStyle::PixelMetric>(sizeButtonGroup->id(button));
const int value = style->pixelMetric(metric);
switch (metric) {
@@ -229,7 +233,8 @@ void MainWindow::addImages(const QString &directory)
{
QFileDialog fileDialog(this, tr("Open Images"), directory);
QStringList mimeTypeFilters;
- foreach (const QByteArray &mimeTypeName, QImageReader::supportedMimeTypes())
+ const QList<QByteArray> mimeTypes = QImageReader::supportedMimeTypes();
+ for (const QByteArray &mimeTypeName : mimeTypes)
mimeTypeFilters.append(mimeTypeName);
mimeTypeFilters.sort();
fileDialog.setMimeTypeFilters(mimeTypeFilters);
@@ -245,7 +250,7 @@ void MainWindow::addImages(const QString &directory)
void MainWindow::loadImages(const QStringList &fileNames)
{
- foreach (const QString &fileName, fileNames) {
+ for (const QString &fileName : fileNames) {
const int row = imagesTable->rowCount();
imagesTable->setRowCount(row + 1);
//! [13]
@@ -468,7 +473,8 @@ void MainWindow::createActions()
QMenu *viewMenu = menuBar()->addMenu(tr("&View"));
styleActionGroup = new QActionGroup(this);
- foreach (const QString &styleName, QStyleFactory::keys()) {
+ const QStringList styleKeys = QStyleFactory::keys();
+ for (const QString &styleName : styleKeys) {
QAction *action = new QAction(tr("%1 Style").arg(styleName), styleActionGroup);
action->setData(styleName);
action->setCheckable(true);
@@ -507,10 +513,11 @@ void MainWindow::createContextMenu()
//! [31]
void MainWindow::checkCurrentStyle()
{
- foreach (QAction *action, styleActionGroup->actions()) {
- QString styleName = action->data().toString();
- QScopedPointer<QStyle> candidate(QStyleFactory::create(styleName));
- Q_ASSERT(!candidate.isNull());
+ const QList<QAction *> actions = styleActionGroup->actions();
+ for (QAction *action : actions) {
+ const QString styleName = action->data().toString();
+ const std::unique_ptr<QStyle> candidate{QStyleFactory::create(styleName)};
+ Q_ASSERT(candidate);
if (candidate->metaObject()->className()
== QApplication::style()->metaObject()->className()) {
action->trigger();
diff --git a/examples/widgets/widgets/icons/mainwindow.h b/examples/widgets/widgets/icons/mainwindow.h
index e3888e5fb1..c67d828cab 100644
--- a/examples/widgets/widgets/icons/mainwindow.h
+++ b/examples/widgets/widgets/icons/mainwindow.h
@@ -60,8 +60,6 @@ QT_BEGIN_NAMESPACE
class QAction;
class QActionGroup;
class QLabel;
-class QMenu;
-class QRadioButton;
class QButtonGroup;
class QTableWidget;
QT_END_NAMESPACE
@@ -74,7 +72,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
- MainWindow();
+ MainWindow(QWidget *parent = nullptr);
void loadImages(const QStringList &fileNames);
diff --git a/examples/widgets/widgets/imageviewer/imageviewer.cpp b/examples/widgets/widgets/imageviewer/imageviewer.cpp
index 327abf7e43..2fc8ff63de 100644
--- a/examples/widgets/widgets/imageviewer/imageviewer.cpp
+++ b/examples/widgets/widgets/imageviewer/imageviewer.cpp
@@ -48,6 +48,8 @@
**
****************************************************************************/
+#include "imageviewer.h"
+
#include <QtWidgets>
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
@@ -56,13 +58,10 @@
#endif
#endif
-#include "imageviewer.h"
-
//! [0]
-ImageViewer::ImageViewer()
- : imageLabel(new QLabel)
- , scrollArea(new QScrollArea)
- , scaleFactor(1)
+ImageViewer::ImageViewer(QWidget *parent)
+ : QMainWindow(parent), imageLabel(new QLabel),
+ scrollArea(new QScrollArea), scaleFactor(1)
{
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
@@ -107,6 +106,8 @@ bool ImageViewer::loadFile(const QString &fileName)
void ImageViewer::setImage(const QImage &newImage)
{
image = newImage;
+ if (image.colorSpace().isValid())
+ image.convertToColorSpace(QColorSpace::SRgb);
imageLabel->setPixmap(QPixmap::fromImage(image));
//! [4]
scaleFactor = 1.0;
@@ -152,7 +153,7 @@ static void initializeImageFileDialog(QFileDialog &dialog, QFileDialog::AcceptMo
QStringList mimeTypeFilters;
const QByteArrayList supportedMimeTypes = acceptMode == QFileDialog::AcceptOpen
? QImageReader::supportedMimeTypes() : QImageWriter::supportedMimeTypes();
- foreach (const QByteArray &mimeTypeName, supportedMimeTypes)
+ for (const QByteArray &mimeTypeName : supportedMimeTypes)
mimeTypeFilters.append(mimeTypeName);
mimeTypeFilters.sort();
dialog.setMimeTypeFilters(mimeTypeFilters);
diff --git a/examples/widgets/widgets/imageviewer/imageviewer.h b/examples/widgets/widgets/imageviewer/imageviewer.h
index f4a62cafe9..7e53105b33 100644
--- a/examples/widgets/widgets/imageviewer/imageviewer.h
+++ b/examples/widgets/widgets/imageviewer/imageviewer.h
@@ -71,7 +71,7 @@ class ImageViewer : public QMainWindow
Q_OBJECT
public:
- ImageViewer();
+ ImageViewer(QWidget *parent = nullptr);
bool loadFile(const QString &);
private slots:
diff --git a/examples/widgets/widgets/lineedits/window.cpp b/examples/widgets/widgets/lineedits/window.cpp
index ffb1edc5ce..33f09d544d 100644
--- a/examples/widgets/widgets/lineedits/window.cpp
+++ b/examples/widgets/widgets/lineedits/window.cpp
@@ -53,7 +53,8 @@
#include "window.h"
//! [0]
-Window::Window()
+Window::Window(QWidget *parent)
+ : QWidget(parent)
{
QGroupBox *echoGroup = new QGroupBox(tr("Echo"));
@@ -122,16 +123,16 @@ Window::Window()
//! [4]
//! [5]
- connect(echoComboBox, SIGNAL(activated(int)),
- this, SLOT(echoChanged(int)));
- connect(validatorComboBox, SIGNAL(activated(int)),
- this, SLOT(validatorChanged(int)));
- connect(alignmentComboBox, SIGNAL(activated(int)),
- this, SLOT(alignmentChanged(int)));
- connect(inputMaskComboBox, SIGNAL(activated(int)),
- this, SLOT(inputMaskChanged(int)));
- connect(accessComboBox, SIGNAL(activated(int)),
- this, SLOT(accessChanged(int)));
+ connect(echoComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::echoChanged);
+ connect(validatorComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::validatorChanged);
+ connect(alignmentComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::alignmentChanged);
+ connect(inputMaskComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::inputMaskChanged);
+ connect(accessComboBox, QOverload<int>::of(&QComboBox::activated),
+ this, &Window::accessChanged);
//! [5]
//! [6]
@@ -205,7 +206,7 @@ void Window::validatorChanged(int index)
{
switch (index) {
case 0:
- validatorLineEdit->setValidator(0);
+ validatorLineEdit->setValidator(nullptr);
break;
case 1:
validatorLineEdit->setValidator(new QIntValidator(
diff --git a/examples/widgets/widgets/lineedits/window.h b/examples/widgets/widgets/lineedits/window.h
index 2070b3b84c..a31634f3a3 100644
--- a/examples/widgets/widgets/lineedits/window.h
+++ b/examples/widgets/widgets/lineedits/window.h
@@ -54,7 +54,6 @@
#include <QWidget>
QT_BEGIN_NAMESPACE
-class QComboBox;
class QLineEdit;
QT_END_NAMESPACE
@@ -64,7 +63,7 @@ class Window : public QWidget
Q_OBJECT
public:
- Window();
+ Window(QWidget *parent = nullptr);
public slots:
void echoChanged(int);
diff --git a/examples/widgets/widgets/mousebuttons/buttontester.h b/examples/widgets/widgets/mousebuttons/buttontester.h
index d99dcceb18..231733bd44 100644
--- a/examples/widgets/widgets/mousebuttons/buttontester.h
+++ b/examples/widgets/widgets/mousebuttons/buttontester.h
@@ -59,13 +59,14 @@
class ButtonTester : public QTextEdit
{
Q_OBJECT
-
+public:
+ using QTextEdit::QTextEdit;
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
#if QT_CONFIG(wheelevent)
- void wheelEvent(QWheelEvent * event) override;
+ void wheelEvent(QWheelEvent *event) override;
#endif
int buttonByNumber(const Qt::MouseButton button);
QString enumNameFromValue(const Qt::MouseButton button);
diff --git a/examples/widgets/widgets/mousebuttons/main.cpp b/examples/widgets/widgets/mousebuttons/main.cpp
index 28be0ffddf..e35a442181 100644
--- a/examples/widgets/widgets/mousebuttons/main.cpp
+++ b/examples/widgets/widgets/mousebuttons/main.cpp
@@ -68,7 +68,7 @@ int main(int argv, char **args)
testArea->setText("To test your mouse with Qt, press buttons in this area.\nYou may also scroll or tilt your mouse wheel.");
QPushButton *quitButton = new QPushButton("Quit");
- QObject::connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
+ QObject::connect(quitButton, &QPushButton::clicked, qApp, &QCoreApplication::quit);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(testArea);
diff --git a/examples/widgets/widgets/movie/movieplayer.cpp b/examples/widgets/widgets/movie/movieplayer.cpp
index 61e85537a3..182b258a82 100644
--- a/examples/widgets/widgets/movie/movieplayer.cpp
+++ b/examples/widgets/widgets/movie/movieplayer.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "movieplayer.h"
+#include <QtWidgets>
+
MoviePlayer::MoviePlayer(QWidget *parent)
: QWidget(parent)
{
@@ -69,13 +69,12 @@ MoviePlayer::MoviePlayer(QWidget *parent)
createControls();
createButtons();
- connect(movie, SIGNAL(frameChanged(int)), this, SLOT(updateFrameSlider()));
- connect(movie, SIGNAL(stateChanged(QMovie::MovieState)),
- this, SLOT(updateButtons()));
- connect(fitCheckBox, SIGNAL(clicked()), this, SLOT(fitToWindow()));
- connect(frameSlider, SIGNAL(valueChanged(int)), this, SLOT(goToFrame(int)));
- connect(speedSpinBox, SIGNAL(valueChanged(int)),
- movie, SLOT(setSpeed(int)));
+ connect(movie, &QMovie::frameChanged, this, &MoviePlayer::updateFrameSlider);
+ connect(movie, &QMovie::stateChanged, this, &MoviePlayer::updateButtons);
+ connect(fitCheckBox, &QCheckBox::clicked, this, &MoviePlayer::fitToWindow);
+ connect(frameSlider, &QSlider::valueChanged, this, &MoviePlayer::goToFrame);
+ connect(speedSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ movie, &QMovie::setSpeed);
mainLayout = new QVBoxLayout;
mainLayout->addWidget(movieLabel);
@@ -182,32 +181,32 @@ void MoviePlayer::createButtons()
openButton->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton));
openButton->setIconSize(iconSize);
openButton->setToolTip(tr("Open File"));
- connect(openButton, SIGNAL(clicked()), this, SLOT(open()));
+ connect(openButton, &QToolButton::clicked, this, &MoviePlayer::open);
playButton = new QToolButton;
playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
playButton->setIconSize(iconSize);
playButton->setToolTip(tr("Play"));
- connect(playButton, SIGNAL(clicked()), movie, SLOT(start()));
+ connect(playButton, &QToolButton::clicked, movie, &QMovie::start);
pauseButton = new QToolButton;
pauseButton->setCheckable(true);
pauseButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
pauseButton->setIconSize(iconSize);
pauseButton->setToolTip(tr("Pause"));
- connect(pauseButton, SIGNAL(clicked(bool)), movie, SLOT(setPaused(bool)));
+ connect(pauseButton, &QToolButton::clicked, movie, &QMovie::setPaused);
stopButton = new QToolButton;
stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop));
stopButton->setIconSize(iconSize);
stopButton->setToolTip(tr("Stop"));
- connect(stopButton, SIGNAL(clicked()), movie, SLOT(stop()));
+ connect(stopButton, &QToolButton::clicked, movie, &QMovie::stop);
quitButton = new QToolButton;
quitButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton));
quitButton->setIconSize(iconSize);
quitButton->setToolTip(tr("Quit"));
- connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
+ connect(quitButton, &QToolButton::clicked, this, &MoviePlayer::close);
buttonsLayout = new QHBoxLayout;
buttonsLayout->addStretch();
diff --git a/examples/widgets/widgets/movie/movieplayer.h b/examples/widgets/widgets/movie/movieplayer.h
index 9fa9604025..7d143bd37c 100644
--- a/examples/widgets/widgets/movie/movieplayer.h
+++ b/examples/widgets/widgets/movie/movieplayer.h
@@ -70,7 +70,7 @@ class MoviePlayer : public QWidget
Q_OBJECT
public:
- MoviePlayer(QWidget *parent = 0);
+ MoviePlayer(QWidget *parent = nullptr);
void openFile(const QString &fileName);
private slots:
diff --git a/examples/widgets/widgets/scribble/mainwindow.cpp b/examples/widgets/widgets/scribble/mainwindow.cpp
index d54e5ce0f9..44afa64b94 100644
--- a/examples/widgets/widgets/scribble/mainwindow.cpp
+++ b/examples/widgets/widgets/scribble/mainwindow.cpp
@@ -54,9 +54,9 @@
#include "scribblearea.h"
//! [0]
-MainWindow::MainWindow()
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent), scribbleArea(new ScribbleArea(this))
{
- scribbleArea = new ScribbleArea;
setCentralWidget(scribbleArea);
createActions();
@@ -151,40 +151,41 @@ void MainWindow::createActions()
{
openAct = new QAction(tr("&Open..."), this);
openAct->setShortcuts(QKeySequence::Open);
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
+ connect(openAct, &QAction::triggered, this, &MainWindow::open);
- foreach (QByteArray format, QImageWriter::supportedImageFormats()) {
- QString text = tr("%1...").arg(QString(format).toUpper());
+ const QList<QByteArray> imageFormats = QImageWriter::supportedImageFormats();
+ for (const QByteArray &format : imageFormats) {
+ QString text = tr("%1...").arg(QString::fromLatin1(format).toUpper());
QAction *action = new QAction(text, this);
action->setData(format);
- connect(action, SIGNAL(triggered()), this, SLOT(save()));
+ connect(action, &QAction::triggered, this, &MainWindow::save);
saveAsActs.append(action);
}
printAct = new QAction(tr("&Print..."), this);
- connect(printAct, SIGNAL(triggered()), scribbleArea, SLOT(print()));
+ connect(printAct, &QAction::triggered, scribbleArea, &ScribbleArea::print);
exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcuts(QKeySequence::Quit);
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
+ connect(exitAct, &QAction::triggered, this, &MainWindow::close);
penColorAct = new QAction(tr("&Pen Color..."), this);
- connect(penColorAct, SIGNAL(triggered()), this, SLOT(penColor()));
+ connect(penColorAct, &QAction::triggered, this, &MainWindow::penColor);
penWidthAct = new QAction(tr("Pen &Width..."), this);
- connect(penWidthAct, SIGNAL(triggered()), this, SLOT(penWidth()));
+ connect(penWidthAct, &QAction::triggered, this, &MainWindow::penWidth);
clearScreenAct = new QAction(tr("&Clear Screen"), this);
clearScreenAct->setShortcut(tr("Ctrl+L"));
- connect(clearScreenAct, SIGNAL(triggered()),
- scribbleArea, SLOT(clearImage()));
+ connect(clearScreenAct, &QAction::triggered,
+ scribbleArea, &ScribbleArea::clearImage);
aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
+ connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);
}
//! [14]
@@ -193,7 +194,7 @@ void MainWindow::createMenus()
//! [15] //! [16]
{
saveAsMenu = new QMenu(tr("&Save As"), this);
- foreach (QAction *action, saveAsActs)
+ for (QAction *action : qAsConst(saveAsActs))
saveAsMenu->addAction(action);
fileMenu = new QMenu(tr("&File"), this);
diff --git a/examples/widgets/widgets/scribble/mainwindow.h b/examples/widgets/widgets/scribble/mainwindow.h
index 9e0ddaff71..e57ff065ac 100644
--- a/examples/widgets/widgets/scribble/mainwindow.h
+++ b/examples/widgets/widgets/scribble/mainwindow.h
@@ -62,7 +62,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
- MainWindow();
+ MainWindow(QWidget *parent = nullptr);
protected:
void closeEvent(QCloseEvent *event) override;
diff --git a/examples/widgets/widgets/scribble/scribblearea.cpp b/examples/widgets/widgets/scribble/scribblearea.cpp
index d32a29697b..13e46f6e1d 100644
--- a/examples/widgets/widgets/scribble/scribblearea.cpp
+++ b/examples/widgets/widgets/scribble/scribblearea.cpp
@@ -48,6 +48,8 @@
**
****************************************************************************/
+#include "scribblearea.h"
+
#include <QtWidgets>
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
@@ -57,8 +59,6 @@
#endif
#endif
-#include "scribblearea.h"
-
//! [0]
ScribbleArea::ScribbleArea(QWidget *parent)
: QWidget(parent)
diff --git a/examples/widgets/widgets/scribble/scribblearea.h b/examples/widgets/widgets/scribble/scribblearea.h
index 7729fb5b89..100c45e133 100644
--- a/examples/widgets/widgets/scribble/scribblearea.h
+++ b/examples/widgets/widgets/scribble/scribblearea.h
@@ -62,7 +62,7 @@ class ScribbleArea : public QWidget
Q_OBJECT
public:
- ScribbleArea(QWidget *parent = 0);
+ ScribbleArea(QWidget *parent = nullptr);
bool openImage(const QString &fileName);
bool saveImage(const QString &fileName, const char *fileFormat);
diff --git a/examples/widgets/widgets/shapedclock/shapedclock.cpp b/examples/widgets/widgets/shapedclock/shapedclock.cpp
index af0cd01be5..8e7d831938 100644
--- a/examples/widgets/widgets/shapedclock/shapedclock.cpp
+++ b/examples/widgets/widgets/shapedclock/shapedclock.cpp
@@ -57,12 +57,12 @@ ShapedClock::ShapedClock(QWidget *parent)
: QWidget(parent, Qt::FramelessWindowHint | Qt::WindowSystemMenuHint)
{
QTimer *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(update()));
+ connect(timer, &QTimer::timeout, this, QOverload<>::of(&ShapedClock::update));
timer->start(1000);
QAction *quitAction = new QAction(tr("E&xit"), this);
quitAction->setShortcut(tr("Ctrl+Q"));
- connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
addAction(quitAction);
setContextMenuPolicy(Qt::ActionsContextMenu);
diff --git a/examples/widgets/widgets/shapedclock/shapedclock.h b/examples/widgets/widgets/shapedclock/shapedclock.h
index 6468d21618..a854d956b3 100644
--- a/examples/widgets/widgets/shapedclock/shapedclock.h
+++ b/examples/widgets/widgets/shapedclock/shapedclock.h
@@ -59,7 +59,7 @@ class ShapedClock : public QWidget
Q_OBJECT
public:
- ShapedClock(QWidget *parent = 0);
+ ShapedClock(QWidget *parent = nullptr);
QSize sizeHint() const override;
protected:
diff --git a/examples/widgets/widgets/sliders/slidersgroup.cpp b/examples/widgets/widgets/sliders/slidersgroup.cpp
index 365a003047..b4eaf9bb3d 100644
--- a/examples/widgets/widgets/sliders/slidersgroup.cpp
+++ b/examples/widgets/widgets/sliders/slidersgroup.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "slidersgroup.h"
+#include <QtWidgets>
+
//! [0]
SlidersGroup::SlidersGroup(Qt::Orientation orientation, const QString &title,
QWidget *parent)
@@ -69,11 +69,11 @@ SlidersGroup::SlidersGroup(Qt::Orientation orientation, const QString &title,
dial = new QDial;
dial->setFocusPolicy(Qt::StrongFocus);
- connect(slider, SIGNAL(valueChanged(int)), scrollBar, SLOT(setValue(int)));
- connect(scrollBar, SIGNAL(valueChanged(int)), dial, SLOT(setValue(int)));
- connect(dial, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
+ connect(slider, &QSlider::valueChanged, scrollBar, &QScrollBar::setValue);
+ connect(scrollBar, &QScrollBar::valueChanged, dial, &QDial::setValue);
+ connect(dial, &QDial::valueChanged, slider, &QSlider::setValue);
//! [0] //! [1]
- connect(dial, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int)));
+ connect(dial, &QDial::valueChanged, this, &SlidersGroup::valueChanged);
//! [1] //! [2]
//! [2] //! [3]
diff --git a/examples/widgets/widgets/sliders/slidersgroup.h b/examples/widgets/widgets/sliders/slidersgroup.h
index 76dcbee0d8..7be8a3b4f8 100644
--- a/examples/widgets/widgets/sliders/slidersgroup.h
+++ b/examples/widgets/widgets/sliders/slidersgroup.h
@@ -66,7 +66,7 @@ class SlidersGroup : public QGroupBox
public:
SlidersGroup(Qt::Orientation orientation, const QString &title,
- QWidget *parent = 0);
+ QWidget *parent = nullptr);
signals:
void valueChanged(int value);
diff --git a/examples/widgets/widgets/sliders/window.cpp b/examples/widgets/widgets/sliders/window.cpp
index 16b60dde49..d73fafec10 100644
--- a/examples/widgets/widgets/sliders/window.cpp
+++ b/examples/widgets/widgets/sliders/window.cpp
@@ -54,7 +54,8 @@
#include "window.h"
//! [0]
-Window::Window()
+Window::Window(QWidget *parent)
+ : QWidget(parent)
{
horizontalSliders = new SlidersGroup(Qt::Horizontal, tr("Horizontal"));
verticalSliders = new SlidersGroup(Qt::Vertical, tr("Vertical"));
@@ -67,13 +68,13 @@ Window::Window()
//! [0]
//! [1]
- connect(horizontalSliders, SIGNAL(valueChanged(int)),
+ connect(horizontalSliders, &SlidersGroup::valueChanged,
//! [1] //! [2]
- verticalSliders, SLOT(setValue(int)));
- connect(verticalSliders, SIGNAL(valueChanged(int)),
- valueSpinBox, SLOT(setValue(int)));
- connect(valueSpinBox, SIGNAL(valueChanged(int)),
- horizontalSliders, SLOT(setValue(int)));
+ verticalSliders, &SlidersGroup::setValue);
+ connect(verticalSliders, &SlidersGroup::valueChanged,
+ valueSpinBox, &QSpinBox::setValue);
+ connect(valueSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ horizontalSliders, &SlidersGroup::setValue);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(controlsGroup);
@@ -120,25 +121,25 @@ void Window::createControls(const QString &title)
orientationCombo->addItem(tr("Vertical slider-like widgets"));
//! [6] //! [7]
- connect(orientationCombo, SIGNAL(activated(int)),
+ connect(orientationCombo, QOverload<int>::of(&QComboBox::activated),
//! [7] //! [8]
- stackedWidget, SLOT(setCurrentIndex(int)));
- connect(minimumSpinBox, SIGNAL(valueChanged(int)),
- horizontalSliders, SLOT(setMinimum(int)));
- connect(minimumSpinBox, SIGNAL(valueChanged(int)),
- verticalSliders, SLOT(setMinimum(int)));
- connect(maximumSpinBox, SIGNAL(valueChanged(int)),
- horizontalSliders, SLOT(setMaximum(int)));
- connect(maximumSpinBox, SIGNAL(valueChanged(int)),
- verticalSliders, SLOT(setMaximum(int)));
- connect(invertedAppearance, SIGNAL(toggled(bool)),
- horizontalSliders, SLOT(invertAppearance(bool)));
- connect(invertedAppearance, SIGNAL(toggled(bool)),
- verticalSliders, SLOT(invertAppearance(bool)));
- connect(invertedKeyBindings, SIGNAL(toggled(bool)),
- horizontalSliders, SLOT(invertKeyBindings(bool)));
- connect(invertedKeyBindings, SIGNAL(toggled(bool)),
- verticalSliders, SLOT(invertKeyBindings(bool)));
+ stackedWidget, &QStackedWidget::setCurrentIndex);
+ connect(minimumSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ horizontalSliders, &SlidersGroup::setMinimum);
+ connect(minimumSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ verticalSliders, &SlidersGroup::setMinimum);
+ connect(maximumSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ horizontalSliders, &SlidersGroup::setMaximum);
+ connect(maximumSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
+ verticalSliders, &SlidersGroup::setMaximum);
+ connect(invertedAppearance, &QCheckBox::toggled,
+ horizontalSliders, &SlidersGroup::invertAppearance);
+ connect(invertedAppearance, &QCheckBox::toggled,
+ verticalSliders, &SlidersGroup::invertAppearance);
+ connect(invertedKeyBindings, &QCheckBox::toggled,
+ horizontalSliders, &SlidersGroup::invertKeyBindings);
+ connect(invertedKeyBindings, &QCheckBox::toggled,
+ verticalSliders, &SlidersGroup::invertKeyBindings);
QGridLayout *controlsLayout = new QGridLayout;
controlsLayout->addWidget(minimumLabel, 0, 0);
diff --git a/examples/widgets/widgets/sliders/window.h b/examples/widgets/widgets/sliders/window.h
index 9c4c14fa37..4894781ac2 100644
--- a/examples/widgets/widgets/sliders/window.h
+++ b/examples/widgets/widgets/sliders/window.h
@@ -69,7 +69,7 @@ class Window : public QWidget
Q_OBJECT
public:
- Window();
+ Window(QWidget *parent = nullptr);
private:
void createControls(const QString &title);
diff --git a/examples/widgets/widgets/spinboxes/window.cpp b/examples/widgets/widgets/spinboxes/window.cpp
index 54604e35aa..82e19527a7 100644
--- a/examples/widgets/widgets/spinboxes/window.cpp
+++ b/examples/widgets/widgets/spinboxes/window.cpp
@@ -53,7 +53,8 @@
#include "window.h"
//! [0]
-Window::Window()
+Window::Window(QWidget *parent)
+ : QWidget(parent)
{
createSpinBoxes();
createDateTimeEdits();
@@ -175,8 +176,8 @@ void Window::createDateTimeEdits()
formatComboBox->addItem("hh:mm ap");
//! [9] //! [10]
- connect(formatComboBox, SIGNAL(activated(QString)),
- this, SLOT(setFormatString(QString)));
+ connect(formatComboBox, &QComboBox::textActivated,
+ this, &Window::setFormatString);
//! [10]
setFormatString(formatComboBox->currentText());
@@ -255,9 +256,9 @@ void Window::createDoubleSpinBoxes()
priceSpinBox->setPrefix("$");
priceSpinBox->setValue(99.99);
- connect(precisionSpinBox, SIGNAL(valueChanged(int)),
+ connect(precisionSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
//! [17]
- this, SLOT(changePrecision(int)));
+ this, &Window::changePrecision);
groupSeparatorSpinBox_d = new QDoubleSpinBox;
groupSeparatorSpinBox_d->setRange(-99999999, 99999999);
diff --git a/examples/widgets/widgets/spinboxes/window.h b/examples/widgets/widgets/spinboxes/window.h
index 97e9ac1083..138773a5aa 100644
--- a/examples/widgets/widgets/spinboxes/window.h
+++ b/examples/widgets/widgets/spinboxes/window.h
@@ -67,7 +67,7 @@ class Window : public QWidget
Q_OBJECT
public:
- Window();
+ Window(QWidget *parent = nullptr);
public slots:
void changePrecision(int decimals);
diff --git a/examples/widgets/widgets/styles/norwegianwoodstyle.cpp b/examples/widgets/widgets/styles/norwegianwoodstyle.cpp
index 8aca91a686..1d7ef2637b 100644
--- a/examples/widgets/widgets/styles/norwegianwoodstyle.cpp
+++ b/examples/widgets/widgets/styles/norwegianwoodstyle.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "norwegianwoodstyle.h"
+#include <QtWidgets>
+
NorwegianWoodStyle::NorwegianWoodStyle() :
QProxyStyle(QStyleFactory::create("windows"))
{
@@ -85,8 +85,8 @@ void NorwegianWoodStyle::polish(QPalette &palette)
setTexture(palette, QPalette::Mid, midImage);
setTexture(palette, QPalette::Window, backgroundImage);
- QBrush brush = palette.background();
- brush.setColor(brush.color().dark());
+ QBrush brush = palette.window();
+ brush.setColor(brush.color().darker());
palette.setBrush(QPalette::Disabled, QPalette::WindowText, brush);
palette.setBrush(QPalette::Disabled, QPalette::Text, brush);
@@ -185,7 +185,7 @@ void NorwegianWoodStyle::drawPrimitive(PrimitiveElement element,
qstyleoption_cast<const QStyleOptionButton *>(option);
if (buttonOption
&& (buttonOption->features & QStyleOptionButton::Flat)) {
- brush = option->palette.background();
+ brush = option->palette.window();
darker = (option->state & (State_Sunken | State_On));
} else {
if (option->state & (State_Sunken | State_On)) {
@@ -261,7 +261,7 @@ void NorwegianWoodStyle::drawPrimitive(PrimitiveElement element,
painter->setPen(bottomPen);
painter->drawPath(roundRect);
- painter->setPen(option->palette.foreground().color());
+ painter->setPen(option->palette.windowText().color());
painter->setClipping(false);
painter->drawPath(roundRect);
diff --git a/examples/widgets/widgets/styles/widgetgallery.cpp b/examples/widgets/widgets/styles/widgetgallery.cpp
index d44547d905..34c010df74 100644
--- a/examples/widgets/widgets/styles/widgetgallery.cpp
+++ b/examples/widgets/widgets/styles/widgetgallery.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
-#include "norwegianwoodstyle.h"
#include "widgetgallery.h"
+#include "norwegianwoodstyle.h"
+
+#include <QtWidgets>
//! [0]
WidgetGallery::WidgetGallery(QWidget *parent)
@@ -79,19 +79,19 @@ WidgetGallery::WidgetGallery(QWidget *parent)
//! [0]
//! [1]
- connect(styleComboBox, SIGNAL(activated(QString)),
+ connect(styleComboBox, &QComboBox::textActivated,
//! [1] //! [2]
- this, SLOT(changeStyle(QString)));
- connect(useStylePaletteCheckBox, SIGNAL(toggled(bool)),
- this, SLOT(changePalette()));
- connect(disableWidgetsCheckBox, SIGNAL(toggled(bool)),
- topLeftGroupBox, SLOT(setDisabled(bool)));
- connect(disableWidgetsCheckBox, SIGNAL(toggled(bool)),
- topRightGroupBox, SLOT(setDisabled(bool)));
- connect(disableWidgetsCheckBox, SIGNAL(toggled(bool)),
- bottomLeftTabWidget, SLOT(setDisabled(bool)));
- connect(disableWidgetsCheckBox, SIGNAL(toggled(bool)),
- bottomRightGroupBox, SLOT(setDisabled(bool)));
+ this, &WidgetGallery::changeStyle);
+ connect(useStylePaletteCheckBox, &QCheckBox::toggled,
+ this, &WidgetGallery::changePalette);
+ connect(disableWidgetsCheckBox, &QCheckBox::toggled,
+ topLeftGroupBox, &QGroupBox::setDisabled);
+ connect(disableWidgetsCheckBox, &QCheckBox::toggled,
+ topRightGroupBox, &QGroupBox::setDisabled);
+ connect(disableWidgetsCheckBox, &QCheckBox::toggled,
+ bottomLeftTabWidget, &QGroupBox::setDisabled);
+ connect(disableWidgetsCheckBox, &QCheckBox::toggled,
+ bottomRightGroupBox, &QGroupBox::setDisabled);
//! [2]
//! [3]
@@ -212,7 +212,7 @@ void WidgetGallery::createBottomLeftTabWidget()
tableWidget = new QTableWidget(10, 10);
QHBoxLayout *tab1hbox = new QHBoxLayout;
- tab1hbox->setMargin(5);
+ tab1hbox->setContentsMargins(5,5, 5, 5);
tab1hbox->addWidget(tableWidget);
tab1->setLayout(tab1hbox);
@@ -227,7 +227,7 @@ void WidgetGallery::createBottomLeftTabWidget()
"How I wonder what you are!\n"));
QHBoxLayout *tab2hbox = new QHBoxLayout;
- tab2hbox->setMargin(5);
+ tab2hbox->setContentsMargins(5, 5, 5, 5);
tab2hbox->addWidget(textEdit);
tab2->setLayout(tab2hbox);
@@ -279,7 +279,7 @@ void WidgetGallery::createProgressBar()
progressBar->setValue(0);
QTimer *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(advanceProgressBar()));
+ connect(timer, &QTimer::timeout, this, &WidgetGallery::advanceProgressBar);
timer->start(1000);
}
//! [13]
diff --git a/examples/widgets/widgets/styles/widgetgallery.h b/examples/widgets/widgets/styles/widgetgallery.h
index ec6edff536..9ee65c21c4 100644
--- a/examples/widgets/widgets/styles/widgetgallery.h
+++ b/examples/widgets/widgets/styles/widgetgallery.h
@@ -78,7 +78,7 @@ class WidgetGallery : public QDialog
Q_OBJECT
public:
- WidgetGallery(QWidget *parent = 0);
+ WidgetGallery(QWidget *parent = nullptr);
private slots:
void changeStyle(const QString &styleName);
diff --git a/examples/widgets/widgets/stylesheet/mainwindow.cpp b/examples/widgets/widgets/stylesheet/mainwindow.cpp
index 9acd90658a..f187c007dd 100644
--- a/examples/widgets/widgets/stylesheet/mainwindow.cpp
+++ b/examples/widgets/widgets/stylesheet/mainwindow.cpp
@@ -53,7 +53,8 @@
#include "mainwindow.h"
#include "stylesheeteditor.h"
-MainWindow::MainWindow()
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
{
ui.setupUi(this);
@@ -63,8 +64,8 @@ MainWindow::MainWindow()
statusBar()->addWidget(new QLabel(tr("Ready")));
- connect(ui.exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
- connect(ui.aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ connect(ui.exitAction, &QAction::triggered, qApp, &QApplication::quit);
+ connect(ui.aboutQtAction, &QAction::triggered, qApp, &QApplication::aboutQt);
}
void MainWindow::on_editStyleAction_triggered()
diff --git a/examples/widgets/widgets/stylesheet/mainwindow.h b/examples/widgets/widgets/stylesheet/mainwindow.h
index 46d3ecbb93..8af4c01da0 100644
--- a/examples/widgets/widgets/stylesheet/mainwindow.h
+++ b/examples/widgets/widgets/stylesheet/mainwindow.h
@@ -62,7 +62,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
- MainWindow();
+ MainWindow(QWidget *parent = nullptr);
private slots:
void on_editStyleAction_triggered();
diff --git a/examples/widgets/widgets/stylesheet/stylesheeteditor.cpp b/examples/widgets/widgets/stylesheet/stylesheeteditor.cpp
index 3247fa774d..0874cc3554 100644
--- a/examples/widgets/widgets/stylesheet/stylesheeteditor.cpp
+++ b/examples/widgets/widgets/stylesheet/stylesheeteditor.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "stylesheeteditor.h"
+#include <QtWidgets>
+
StyleSheetEditor::StyleSheetEditor(QWidget *parent)
: QDialog(parent)
{
diff --git a/examples/widgets/widgets/stylesheet/stylesheeteditor.h b/examples/widgets/widgets/stylesheet/stylesheeteditor.h
index 65a3018adb..f51af7877c 100644
--- a/examples/widgets/widgets/stylesheet/stylesheeteditor.h
+++ b/examples/widgets/widgets/stylesheet/stylesheeteditor.h
@@ -60,7 +60,7 @@ class StyleSheetEditor : public QDialog
Q_OBJECT
public:
- StyleSheetEditor(QWidget *parent = 0);
+ StyleSheetEditor(QWidget *parent = nullptr);
private slots:
void on_styleCombo_activated(const QString &styleName);
diff --git a/examples/widgets/widgets/tablet/tabletapplication.cpp b/examples/widgets/widgets/tablet/tabletapplication.cpp
index 2e5ac07c95..37be018276 100644
--- a/examples/widgets/widgets/tablet/tabletapplication.cpp
+++ b/examples/widgets/widgets/tablet/tabletapplication.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "tabletapplication.h"
+#include <QtWidgets>
+
//! [0]
bool TabletApplication::event(QEvent *event)
{
diff --git a/examples/widgets/widgets/tablet/tabletapplication.h b/examples/widgets/widgets/tablet/tabletapplication.h
index 6b3b2a1730..9b4a4f1886 100644
--- a/examples/widgets/widgets/tablet/tabletapplication.h
+++ b/examples/widgets/widgets/tablet/tabletapplication.h
@@ -61,15 +61,14 @@ class TabletApplication : public QApplication
Q_OBJECT
public:
- TabletApplication(int &argv, char **args)
- : QApplication(argv, args) {}
+ using QApplication::QApplication;
bool event(QEvent *event) override;
void setCanvas(TabletCanvas *canvas)
{ m_canvas = canvas; }
private:
- TabletCanvas *m_canvas;
+ TabletCanvas *m_canvas = nullptr;
};
//! [0]
diff --git a/examples/widgets/widgets/tetrix/main.cpp b/examples/widgets/widgets/tetrix/main.cpp
index 2698190e76..92f245ca14 100644
--- a/examples/widgets/widgets/tetrix/main.cpp
+++ b/examples/widgets/widgets/tetrix/main.cpp
@@ -48,12 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
-#include <stdlib.h>
-
#include "tetrixwindow.h"
+#include <QApplication>
+
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
diff --git a/examples/widgets/widgets/tetrix/tetrixboard.cpp b/examples/widgets/widgets/tetrix/tetrixboard.cpp
index 222ab1fb4d..ef3ac4fc38 100644
--- a/examples/widgets/widgets/tetrix/tetrixboard.cpp
+++ b/examples/widgets/widgets/tetrix/tetrixboard.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "tetrixboard.h"
+#include <QtWidgets>
+
//! [0]
TetrixBoard::TetrixBoard(QWidget *parent)
: QFrame(parent)
@@ -358,7 +358,7 @@ void TetrixBoard::showNextPiece()
QPixmap pixmap(dx * squareWidth(), dy * squareHeight());
QPainter painter(&pixmap);
- painter.fillRect(pixmap.rect(), nextPieceLabel->palette().background());
+ painter.fillRect(pixmap.rect(), nextPieceLabel->palette().window());
for (int i = 0; i < 4; ++i) {
int x = nextPiece.x(i) - nextPiece.minX();
@@ -405,11 +405,11 @@ void TetrixBoard::drawSquare(QPainter &painter, int x, int y, TetrixShape shape)
painter.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2,
color);
- painter.setPen(color.light());
+ painter.setPen(color.lighter());
painter.drawLine(x, y + squareHeight() - 1, x, y);
painter.drawLine(x, y, x + squareWidth() - 1, y);
- painter.setPen(color.dark());
+ painter.setPen(color.darker());
painter.drawLine(x + 1, y + squareHeight() - 1,
x + squareWidth() - 1, y + squareHeight() - 1);
painter.drawLine(x + squareWidth() - 1, y + squareHeight() - 1,
diff --git a/examples/widgets/widgets/tetrix/tetrixboard.h b/examples/widgets/widgets/tetrix/tetrixboard.h
index 7c6871dfbd..86bcfa4d6e 100644
--- a/examples/widgets/widgets/tetrix/tetrixboard.h
+++ b/examples/widgets/widgets/tetrix/tetrixboard.h
@@ -67,7 +67,7 @@ class TetrixBoard : public QFrame
Q_OBJECT
public:
- TetrixBoard(QWidget *parent = 0);
+ TetrixBoard(QWidget *parent = nullptr);
void setNextPieceLabel(QLabel *label);
QSize sizeHint() const override;
diff --git a/examples/widgets/widgets/tetrix/tetrixpiece.cpp b/examples/widgets/widgets/tetrix/tetrixpiece.cpp
index 3d8fa86860..b1b3ca9a99 100644
--- a/examples/widgets/widgets/tetrix/tetrixpiece.cpp
+++ b/examples/widgets/widgets/tetrix/tetrixpiece.cpp
@@ -48,12 +48,10 @@
**
****************************************************************************/
-#include <QtCore>
-
-#include <stdlib.h>
-
#include "tetrixpiece.h"
+#include <QtCore>
+
//! [0]
void TetrixPiece::setRandomShape()
{
diff --git a/examples/widgets/widgets/tetrix/tetrixwindow.cpp b/examples/widgets/widgets/tetrix/tetrixwindow.cpp
index 7e951aceb8..970a38c1dc 100644
--- a/examples/widgets/widgets/tetrix/tetrixwindow.cpp
+++ b/examples/widgets/widgets/tetrix/tetrixwindow.cpp
@@ -54,7 +54,8 @@
#include "tetrixwindow.h"
//! [0]
-TetrixWindow::TetrixWindow()
+TetrixWindow::TetrixWindow(QWidget *parent)
+ : QWidget(parent)
{
board = new TetrixBoard;
//! [0]
diff --git a/examples/widgets/widgets/tetrix/tetrixwindow.h b/examples/widgets/widgets/tetrix/tetrixwindow.h
index a21cef2ecf..3743d6cd2a 100644
--- a/examples/widgets/widgets/tetrix/tetrixwindow.h
+++ b/examples/widgets/widgets/tetrix/tetrixwindow.h
@@ -51,7 +51,6 @@
#ifndef TETRIXWINDOW_H
#define TETRIXWINDOW_H
-#include <QFrame>
#include <QWidget>
QT_BEGIN_NAMESPACE
@@ -67,7 +66,7 @@ class TetrixWindow : public QWidget
Q_OBJECT
public:
- TetrixWindow();
+ TetrixWindow(QWidget *parent = nullptr);
private:
QLabel *createLabel(const QString &text);
diff --git a/examples/widgets/widgets/tooltips/shapeitem.cpp b/examples/widgets/widgets/tooltips/shapeitem.cpp
index 70c1cc03dc..68cc744b84 100644
--- a/examples/widgets/widgets/tooltips/shapeitem.cpp
+++ b/examples/widgets/widgets/tooltips/shapeitem.cpp
@@ -48,8 +48,6 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "shapeitem.h"
//! [0]
diff --git a/examples/widgets/widgets/tooltips/sortingbox.cpp b/examples/widgets/widgets/tooltips/sortingbox.cpp
index 4769a30c64..685eaa7d1d 100644
--- a/examples/widgets/widgets/tooltips/sortingbox.cpp
+++ b/examples/widgets/widgets/tooltips/sortingbox.cpp
@@ -48,14 +48,13 @@
**
****************************************************************************/
-#include <QtWidgets>
-
-#include <stdlib.h>
-
#include "sortingbox.h"
+#include <QtWidgets>
+
//! [0]
-SortingBox::SortingBox()
+SortingBox::SortingBox(QWidget *parent)
+ : QWidget(parent)
{
//! [0] //! [1]
setMouseTracking(true);
@@ -63,7 +62,7 @@ SortingBox::SortingBox()
setBackgroundRole(QPalette::Base);
//! [2]
- itemInMotion = 0;
+ itemInMotion = nullptr;
//! [3]
newCircleButton = createToolButton(tr("New Circle"),
@@ -139,7 +138,7 @@ void SortingBox::paintEvent(QPaintEvent * /* event */)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
- foreach (ShapeItem shapeItem, shapeItems) {
+ for (const ShapeItem &shapeItem : qAsConst(shapeItems)) {
//! [8] //! [9]
painter.translate(shapeItem.position());
//! [9] //! [10]
@@ -178,7 +177,7 @@ void SortingBox::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && itemInMotion) {
moveItemTo(event->pos());
- itemInMotion = 0;
+ itemInMotion = nullptr;
}
}
//! [13]
diff --git a/examples/widgets/widgets/tooltips/sortingbox.h b/examples/widgets/widgets/tooltips/sortingbox.h
index 2ac27614a5..3d0cecea2b 100644
--- a/examples/widgets/widgets/tooltips/sortingbox.h
+++ b/examples/widgets/widgets/tooltips/sortingbox.h
@@ -51,10 +51,10 @@
#ifndef SORTINGBOX_H
#define SORTINGBOX_H
-#include <QWidget>
-
#include "shapeitem.h"
+#include <QWidget>
+
QT_BEGIN_NAMESPACE
class QAction;
class QPoint;
@@ -67,7 +67,7 @@ class SortingBox : public QWidget
Q_OBJECT
public:
- SortingBox();
+ SortingBox(QWidget *parent = nullptr);
protected:
bool event(QEvent *event) override;
diff --git a/examples/widgets/widgets/validators/ledwidget.cpp b/examples/widgets/widgets/validators/ledwidget.cpp
index 65248741b5..462f416c86 100644
--- a/examples/widgets/widgets/validators/ledwidget.cpp
+++ b/examples/widgets/widgets/validators/ledwidget.cpp
@@ -56,7 +56,7 @@ LEDWidget::LEDWidget(QWidget *parent)
setPixmap(offPixmap);
flashTimer.setInterval(200);
flashTimer.setSingleShot(true);
- connect(&flashTimer, SIGNAL(timeout()), this, SLOT(extinguish()));
+ connect(&flashTimer, &QTimer::timeout, this, &LEDWidget::extinguish);
};
void LEDWidget::extinguish()
diff --git a/examples/widgets/widgets/validators/ledwidget.h b/examples/widgets/widgets/validators/ledwidget.h
index dcbfb176c2..c4b406db23 100644
--- a/examples/widgets/widgets/validators/ledwidget.h
+++ b/examples/widgets/widgets/validators/ledwidget.h
@@ -59,7 +59,7 @@ class LEDWidget : public QLabel
{
Q_OBJECT
public:
- LEDWidget(QWidget *parent = 0);
+ LEDWidget(QWidget *parent = nullptr);
public slots:
void flash();
diff --git a/examples/widgets/widgets/validators/localeselector.cpp b/examples/widgets/widgets/validators/localeselector.cpp
index 2f702c9753..1382da0cc9 100644
--- a/examples/widgets/widgets/validators/localeselector.cpp
+++ b/examples/widgets/widgets/validators/localeselector.cpp
@@ -59,7 +59,9 @@ LocaleSelector::LocaleSelector(QWidget *parent)
int index = 0;
for (int _lang = QLocale::C; _lang <= QLocale::LastLanguage; ++_lang) {
QLocale::Language lang = static_cast<QLocale::Language>(_lang);
- foreach (const QLocale &l, QLocale::matchingLocales(lang, QLocale::AnyScript, QLocale::AnyCountry)) {
+ const QList<QLocale> locales =
+ QLocale::matchingLocales(lang, QLocale::AnyScript, QLocale::AnyCountry);
+ for (const QLocale &l : locales) {
QString label = QLocale::languageToString(l.language());
label += QLatin1Char('/');
label += QLocale::countryToString(l.country());
@@ -79,7 +81,8 @@ LocaleSelector::LocaleSelector(QWidget *parent)
if (curIndex != -1)
setCurrentIndex(curIndex);
- connect(this, SIGNAL(activated(int)), this, SLOT(emitLocaleSelected(int)));
+ connect(this, QOverload<int>::of(&LocaleSelector::activated),
+ this, &LocaleSelector::emitLocaleSelected);
}
void LocaleSelector::emitLocaleSelected(int index)
diff --git a/examples/widgets/widgets/validators/localeselector.h b/examples/widgets/widgets/validators/localeselector.h
index 05290eae81..611e2da66e 100644
--- a/examples/widgets/widgets/validators/localeselector.h
+++ b/examples/widgets/widgets/validators/localeselector.h
@@ -58,7 +58,7 @@ class LocaleSelector : public QComboBox
Q_OBJECT
public:
- LocaleSelector(QWidget *parent = 0);
+ LocaleSelector(QWidget *parent = nullptr);
signals:
void localeSelected(const QLocale &locale);
diff --git a/examples/widgets/widgets/validators/main.cpp b/examples/widgets/widgets/validators/main.cpp
index d8ba2943d0..1fbf12410d 100644
--- a/examples/widgets/widgets/validators/main.cpp
+++ b/examples/widgets/widgets/validators/main.cpp
@@ -48,88 +48,9 @@
**
****************************************************************************/
-#include <qdebug.h>
-#include <QApplication>
-#include <QLineEdit>
-#include <QValidator>
-
-#include "ui_validators.h"
-
-class ValidatorWidget : public QWidget, public Ui::ValidatorsForm
-{
- Q_OBJECT
-public:
- ValidatorWidget(QWidget *parent = 0);
-
-private slots:
- void updateValidator();
- void updateDoubleValidator();
- void _setLocale(const QLocale &l) { setLocale(l); updateValidator(); updateDoubleValidator(); }
-
-private:
- QIntValidator *validator;
- QDoubleValidator *doubleValidator;
-};
-
-ValidatorWidget::ValidatorWidget(QWidget *parent)
- : QWidget(parent)
-{
- setupUi(this);
-
- connect(localeSelector, SIGNAL(localeSelected(QLocale)), this, SLOT(_setLocale(QLocale)));
-
- connect(minVal, SIGNAL(editingFinished()), this, SLOT(updateValidator()));
- connect(maxVal, SIGNAL(editingFinished()), this, SLOT(updateValidator()));
- connect(editor, SIGNAL(editingFinished()), ledWidget, SLOT(flash()));
-
- connect(doubleMaxVal, SIGNAL(editingFinished()), this, SLOT(updateDoubleValidator()));
- connect(doubleMinVal, SIGNAL(editingFinished()), this, SLOT(updateDoubleValidator()));
- connect(doubleDecimals, SIGNAL(valueChanged(int)), this, SLOT(updateDoubleValidator()));
- connect(doubleFormat, SIGNAL(activated(int)), this, SLOT(updateDoubleValidator()));
- connect(doubleEditor, SIGNAL(editingFinished()), doubleLedWidget, SLOT(flash()));
+#include "validatorwidget.h"
- validator = 0;
- doubleValidator = 0;
- updateValidator();
- updateDoubleValidator();
-};
-
-void ValidatorWidget::updateValidator()
-{
- QIntValidator *v = new QIntValidator(minVal->value(), maxVal->value(), this);
- v->setLocale(locale());
- editor->setValidator(v);
- delete validator;
- validator = v;
-
- QString s = editor->text();
- int i = 0;
- if (validator->validate(s, i) == QValidator::Invalid) {
- editor->clear();
- } else {
- editor->setText(s);
- }
-}
-
-void ValidatorWidget::updateDoubleValidator()
-{
- QDoubleValidator *v
- = new QDoubleValidator(doubleMinVal->value(), doubleMaxVal->value(),
- doubleDecimals->value(), this);
- v->setNotation(static_cast<QDoubleValidator::Notation>(doubleFormat->currentIndex()));
- v->setLocale(locale());
- doubleEditor->setValidator(v);
- delete doubleValidator;
- doubleValidator = v;
-
- QString s = doubleEditor->text();
- int i = 0;
- if (doubleValidator->validate(s, i) == QValidator::Invalid) {
- doubleEditor->clear();
- } else {
- doubleEditor->setText(s);
- }
-}
+#include <QApplication>
int main(int argc, char **argv)
{
@@ -142,5 +63,3 @@ int main(int argc, char **argv)
return app.exec();
}
-
-#include "main.moc"
diff --git a/examples/widgets/widgets/validators/validators.pro b/examples/widgets/widgets/validators/validators.pro
index ab1eb7809b..029cf95aca 100644
--- a/examples/widgets/widgets/validators/validators.pro
+++ b/examples/widgets/widgets/validators/validators.pro
@@ -4,8 +4,8 @@ requires(qtConfig(combobox))
FORMS += validators.ui
RESOURCES += validators.qrc
-SOURCES += main.cpp ledwidget.cpp localeselector.cpp
-HEADERS += ledwidget.h localeselector.h
+SOURCES += main.cpp ledwidget.cpp localeselector.cpp validatorwidget.cpp
+HEADERS += ledwidget.h localeselector.h validatorwidget.h
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/validators
diff --git a/examples/widgets/widgets/validators/validatorwidget.cpp b/examples/widgets/widgets/validators/validatorwidget.cpp
new file mode 100644
index 0000000000..fa0a55aa52
--- /dev/null
+++ b/examples/widgets/widgets/validators/validatorwidget.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "validatorwidget.h"
+
+#include <QtWidgets>
+
+ValidatorWidget::ValidatorWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ setupUi(this);
+
+ connect(localeSelector, &LocaleSelector::localeSelected,
+ this, &ValidatorWidget::setLocale);
+ connect(localeSelector, &LocaleSelector::localeSelected,
+ this, &ValidatorWidget::updateValidator);
+ connect(localeSelector, &LocaleSelector::localeSelected,
+ this, &ValidatorWidget::updateDoubleValidator);
+
+ connect(minVal, &QSpinBox::editingFinished,
+ this, &ValidatorWidget::updateValidator);
+ connect(maxVal, &QSpinBox::editingFinished,
+ this, &ValidatorWidget::updateValidator);
+ connect(editor, &QLineEdit::editingFinished,
+ ledWidget, &LEDWidget::flash);
+
+ connect(doubleMaxVal, &QDoubleSpinBox::editingFinished,
+ this, &ValidatorWidget::updateDoubleValidator);
+ connect(doubleMinVal, &QDoubleSpinBox::editingFinished,
+ this, &ValidatorWidget::updateDoubleValidator);
+ connect(doubleDecimals, QOverload<int>::of(&QSpinBox::valueChanged),
+ this, &ValidatorWidget::updateDoubleValidator);
+ connect(doubleFormat, QOverload<int>::of(&QComboBox::activated),
+ this, &ValidatorWidget::updateDoubleValidator);
+ connect(doubleEditor, &QLineEdit::editingFinished,
+ doubleLedWidget, &LEDWidget::flash);
+
+ updateValidator();
+ updateDoubleValidator();
+}
+
+void ValidatorWidget::updateValidator()
+{
+ QIntValidator *v = new QIntValidator(minVal->value(), maxVal->value(), this);
+ v->setLocale(locale());
+ delete editor->validator();
+ editor->setValidator(v);
+
+ QString s = editor->text();
+ int i = 0;
+ if (v->validate(s, i) == QValidator::Invalid) {
+ editor->clear();
+ } else {
+ editor->setText(s);
+ }
+}
+
+void ValidatorWidget::updateDoubleValidator()
+{
+ QDoubleValidator *v
+ = new QDoubleValidator(doubleMinVal->value(), doubleMaxVal->value(),
+ doubleDecimals->value(), this);
+ v->setNotation(static_cast<QDoubleValidator::Notation>(doubleFormat->currentIndex()));
+ v->setLocale(locale());
+ delete doubleEditor->validator();
+ doubleEditor->setValidator(v);
+
+ QString s = doubleEditor->text();
+ int i = 0;
+ if (v->validate(s, i) == QValidator::Invalid) {
+ doubleEditor->clear();
+ } else {
+ doubleEditor->setText(s);
+ }
+}
diff --git a/src/widgets/doc/snippets/code/doc_src_examples_dropsite.qdoc b/examples/widgets/widgets/validators/validatorwidget.h
index a91933cdce..bcc4a9b91e 100644
--- a/src/widgets/doc/snippets/code/doc_src_examples_dropsite.qdoc
+++ b/examples/widgets/widgets/validators/validatorwidget.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the documentation of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
@@ -48,8 +48,17 @@
**
****************************************************************************/
-//! [0]
-\code
-foreach(variable, container)
-\endcode
-//! [0]
+#include <QWidget>
+
+#include "ui_validators.h"
+
+class ValidatorWidget : public QWidget, public Ui::ValidatorsForm
+{
+ Q_OBJECT
+public:
+ ValidatorWidget(QWidget *parent = nullptr);
+
+private slots:
+ void updateValidator();
+ void updateDoubleValidator();
+};
diff --git a/examples/widgets/widgets/wiggly/dialog.cpp b/examples/widgets/widgets/wiggly/dialog.cpp
index 010648eda6..a7a72b3570 100644
--- a/examples/widgets/widgets/wiggly/dialog.cpp
+++ b/examples/widgets/widgets/wiggly/dialog.cpp
@@ -48,12 +48,12 @@
**
****************************************************************************/
-#include <QLineEdit>
-#include <QVBoxLayout>
-
#include "dialog.h"
#include "wigglywidget.h"
+#include <QLineEdit>
+#include <QVBoxLayout>
+
//! [0]
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
diff --git a/examples/widgets/widgets/wiggly/dialog.h b/examples/widgets/widgets/wiggly/dialog.h
index a0981dc6b6..357b6354b5 100644
--- a/examples/widgets/widgets/wiggly/dialog.h
+++ b/examples/widgets/widgets/wiggly/dialog.h
@@ -59,7 +59,7 @@ class Dialog : public QDialog
Q_OBJECT
public:
- explicit Dialog(QWidget *parent = 0);
+ explicit Dialog(QWidget *parent = nullptr);
};
//! [0]
diff --git a/examples/widgets/widgets/wiggly/main.cpp b/examples/widgets/widgets/wiggly/main.cpp
index bd2a50a8eb..cd888c4084 100644
--- a/examples/widgets/widgets/wiggly/main.cpp
+++ b/examples/widgets/widgets/wiggly/main.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QApplication>
-
#include "dialog.h"
+#include <QApplication>
+
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
diff --git a/examples/widgets/widgets/wiggly/wigglywidget.cpp b/examples/widgets/widgets/wiggly/wigglywidget.cpp
index 1b8f3cffad..0399fe9056 100644
--- a/examples/widgets/widgets/wiggly/wigglywidget.cpp
+++ b/examples/widgets/widgets/wiggly/wigglywidget.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "wigglywidget.h"
+#include <QtWidgets>
+
//! [0]
WigglyWidget::WigglyWidget(QWidget *parent)
: QWidget(parent)
diff --git a/examples/widgets/widgets/wiggly/wigglywidget.h b/examples/widgets/widgets/wiggly/wigglywidget.h
index 58a7d045e1..1d909c34da 100644
--- a/examples/widgets/widgets/wiggly/wigglywidget.h
+++ b/examples/widgets/widgets/wiggly/wigglywidget.h
@@ -60,7 +60,7 @@ class WigglyWidget : public QWidget
Q_OBJECT
public:
- WigglyWidget(QWidget *parent = 0);
+ WigglyWidget(QWidget *parent = nullptr);
public slots:
void setText(const QString &newText) { text = newText; }
diff --git a/examples/widgets/widgets/windowflags/controllerwindow.cpp b/examples/widgets/widgets/windowflags/controllerwindow.cpp
index 78323810ed..e2abad89f4 100644
--- a/examples/widgets/widgets/windowflags/controllerwindow.cpp
+++ b/examples/widgets/widgets/windowflags/controllerwindow.cpp
@@ -53,7 +53,8 @@
#include "controllerwindow.h"
//! [0]
-ControllerWindow::ControllerWindow()
+ControllerWindow::ControllerWindow(QWidget *parent)
+ : QWidget(parent)
{
previewWindow = new PreviewWindow(this);
@@ -61,7 +62,8 @@ ControllerWindow::ControllerWindow()
createHintsGroupBox();
quitButton = new QPushButton(tr("&Quit"));
- connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
+ connect(quitButton, &QPushButton::clicked,
+ qApp, &QApplication::quit);
QHBoxLayout *bottomLayout = new QHBoxLayout;
bottomLayout->addStretch();
@@ -219,7 +221,8 @@ void ControllerWindow::createHintsGroupBox()
QCheckBox *ControllerWindow::createCheckBox(const QString &text)
{
QCheckBox *checkBox = new QCheckBox(text);
- connect(checkBox, SIGNAL(clicked()), this, SLOT(updatePreview()));
+ connect(checkBox, &QCheckBox::clicked,
+ this, &ControllerWindow::updatePreview);
return checkBox;
}
//! [7]
@@ -228,7 +231,8 @@ QCheckBox *ControllerWindow::createCheckBox(const QString &text)
QRadioButton *ControllerWindow::createRadioButton(const QString &text)
{
QRadioButton *button = new QRadioButton(text);
- connect(button, SIGNAL(clicked()), this, SLOT(updatePreview()));
+ connect(button, &QRadioButton::clicked,
+ this, &ControllerWindow::updatePreview);
return button;
}
//! [8]
diff --git a/examples/widgets/widgets/windowflags/controllerwindow.h b/examples/widgets/widgets/windowflags/controllerwindow.h
index cfb88ed20f..43ec67e27f 100644
--- a/examples/widgets/widgets/windowflags/controllerwindow.h
+++ b/examples/widgets/widgets/windowflags/controllerwindow.h
@@ -69,7 +69,7 @@ class ControllerWindow : public QWidget
Q_OBJECT
public:
- ControllerWindow();
+ ControllerWindow(QWidget *parent = nullptr);
private slots:
void updatePreview();
diff --git a/examples/widgets/widgets/windowflags/previewwindow.cpp b/examples/widgets/widgets/windowflags/previewwindow.cpp
index 725a134daf..8773dccb05 100644
--- a/examples/widgets/widgets/windowflags/previewwindow.cpp
+++ b/examples/widgets/widgets/windowflags/previewwindow.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QtWidgets>
-
#include "previewwindow.h"
+#include <QtWidgets>
+
//! [0]
PreviewWindow::PreviewWindow(QWidget *parent)
: QWidget(parent)
@@ -61,7 +61,8 @@ PreviewWindow::PreviewWindow(QWidget *parent)
textEdit->setLineWrapMode(QTextEdit::NoWrap);
closeButton = new QPushButton(tr("&Close"));
- connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
+ connect(closeButton, &QPushButton::clicked,
+ this, &PreviewWindow::close);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(textEdit);
diff --git a/examples/widgets/widgets/windowflags/previewwindow.h b/examples/widgets/widgets/windowflags/previewwindow.h
index e9efd09507..9bb487e8ab 100644
--- a/examples/widgets/widgets/windowflags/previewwindow.h
+++ b/examples/widgets/widgets/windowflags/previewwindow.h
@@ -64,7 +64,7 @@ class PreviewWindow : public QWidget
Q_OBJECT
public:
- PreviewWindow(QWidget *parent = 0);
+ PreviewWindow(QWidget *parent = nullptr);
void setWindowFlags(Qt::WindowFlags flags);
diff --git a/examples/xml/dombookmarks/xbeltree.cpp b/examples/xml/dombookmarks/xbeltree.cpp
index f7ff1de638..d90cdc03b4 100644
--- a/examples/xml/dombookmarks/xbeltree.cpp
+++ b/examples/xml/dombookmarks/xbeltree.cpp
@@ -184,7 +184,7 @@ void XbelTree::parseFolderElement(const QDomElement &element,
item->setText(0, title);
bool folded = (element.attribute(foldedAttribute()) != QLatin1String("no"));
- setItemExpanded(item, !folded);
+ item->setExpanded(!folded);
QDomElement child = element.firstChildElement();
while (!child.isNull()) {
diff --git a/examples/xml/htmlinfo/main.cpp b/examples/xml/htmlinfo/main.cpp
index 6591c3ac91..bc19ae4a82 100644
--- a/examples/xml/htmlinfo/main.cpp
+++ b/examples/xml/htmlinfo/main.cpp
@@ -50,13 +50,14 @@
#include <QtCore>
-void parseHtmlFile(QTextStream &out, const QString &fileName) {
+void parseHtmlFile(QTextStream &out, const QString &fileName)
+{
QFile file(fileName);
- out << "Analysis of HTML file: " << fileName << endl;
+ out << "Analysis of HTML file: " << fileName << Qt::endl;
if (!file.open(QIODevice::ReadOnly)) {
- out << " Couldn't open the file." << endl << endl << endl;
+ out << " Couldn't open the file." << Qt::endl << Qt::endl << Qt::endl;
return;
}
@@ -71,11 +72,11 @@ void parseHtmlFile(QTextStream &out, const QString &fileName) {
while (!reader.atEnd()) {
reader.readNext();
if (reader.isStartElement()) {
- if (reader.name() == "title")
+ if (reader.name() == QLatin1String("title"))
title = reader.readElementText();
- else if(reader.name() == "a")
- links.append(reader.attributes().value("href").toString());
- else if(reader.name() == "p")
+ else if (reader.name() == QLatin1String("a"))
+ links.append(reader.attributes().value(QLatin1String("href")).toString());
+ else if (reader.name() == QLatin1String("p"))
++paragraphCount;
}
}
@@ -84,22 +85,22 @@ void parseHtmlFile(QTextStream &out, const QString &fileName) {
//! [2]
if (reader.hasError()) {
out << " The HTML file isn't well-formed: " << reader.errorString()
- << endl << endl << endl;
+ << Qt::endl << Qt::endl << Qt::endl;
return;
}
//! [2]
- out << " Title: \"" << title << '"' << endl
- << " Number of paragraphs: " << paragraphCount << endl
- << " Number of links: " << links.size() << endl
- << " Showing first few links:" << endl;
+ out << " Title: \"" << title << '"' << Qt::endl
+ << " Number of paragraphs: " << paragraphCount << Qt::endl
+ << " Number of links: " << links.size() << Qt::endl
+ << " Showing first few links:" << Qt::endl;
- while(links.size() > 5)
+ while (links.size() > 5)
links.removeLast();
- foreach(QString link, links)
- out << " " << link << endl;
- out << endl << endl;
+ for (const QString &link : qAsConst(links))
+ out << " " << link << Qt::endl;
+ out << Qt::endl << Qt::endl;
}
int main(int argc, char **argv)
@@ -108,11 +109,10 @@ int main(int argc, char **argv)
QCoreApplication app(argc, argv);
// get a list of all html files in the current directory
- QStringList filter;
- filter << "*.htm";
- filter << "*.html";
+ const QStringList filter = { QStringLiteral("*.htm"),
+ QStringLiteral("*.html") };
- QStringList htmlFiles = QDir(":/").entryList(filter, QDir::Files);
+ const QStringList htmlFiles = QDir(QStringLiteral(":/")).entryList(filter, QDir::Files);
QTextStream out(stdout);
@@ -122,8 +122,8 @@ int main(int argc, char **argv)
}
// parse each html file and write the result to file/stream
- foreach(QString file, htmlFiles)
- parseHtmlFile(out, ":/" + file);
+ for (const QString &file : htmlFiles)
+ parseHtmlFile(out, QStringLiteral(":/") + file);
return 0;
}
diff --git a/examples/xml/saxbookmarks/xbelgenerator.cpp b/examples/xml/saxbookmarks/xbelgenerator.cpp
index ee6f113f9c..77cb6748fe 100644
--- a/examples/xml/saxbookmarks/xbelgenerator.cpp
+++ b/examples/xml/saxbookmarks/xbelgenerator.cpp
@@ -100,7 +100,7 @@ void XbelGenerator::generateItem(const QTreeWidgetItem *item, int depth)
{
QString tagName = item->data(0, Qt::UserRole).toString();
if (tagName == QLatin1String("folder")) {
- bool folded = !treeWidget->isItemExpanded(item);
+ bool folded = !item->isExpanded();
out << indent(depth) << "<folder folded=\"" << (folded ? "yes" : "no")
<< "\">\n"
<< indent(depth + 1) << "<title>" << escapedText(item->text(0))
diff --git a/examples/xml/saxbookmarks/xbelhandler.cpp b/examples/xml/saxbookmarks/xbelhandler.cpp
index 7e2a9db3c2..62dfbf9482 100644
--- a/examples/xml/saxbookmarks/xbelhandler.cpp
+++ b/examples/xml/saxbookmarks/xbelhandler.cpp
@@ -94,7 +94,7 @@ bool XbelHandler::startElement(const QString & /* namespaceURI */,
item->setIcon(0, folderIcon);
item->setText(0, QObject::tr("Folder"));
bool folded = (attributes.value(foldedAttribute()) != QLatin1String("no"));
- treeWidget->setItemExpanded(item, !folded);
+ item->setExpanded(!folded);
} else if (qName == QLatin1String("bookmark")) {
item = createChildItem(qName);
item->setFlags(item->flags() | Qt::ItemIsEditable);
diff --git a/examples/xml/streambookmarks/xbelreader.cpp b/examples/xml/streambookmarks/xbelreader.cpp
index 099985d91e..bd187038bc 100644
--- a/examples/xml/streambookmarks/xbelreader.cpp
+++ b/examples/xml/streambookmarks/xbelreader.cpp
@@ -140,7 +140,7 @@ void XbelReader::readFolder(QTreeWidgetItem *item)
QTreeWidgetItem *folder = createChildItem(item);
bool folded = (xml.attributes().value(foldedAttribute()) != QLatin1String("no"));
- treeWidget->setItemExpanded(folder, !folded);
+ folder->setExpanded(!folded);
while (xml.readNextStartElement()) {
if (xml.name() == QLatin1String("title"))
diff --git a/examples/xml/streambookmarks/xbelwriter.cpp b/examples/xml/streambookmarks/xbelwriter.cpp
index 2959680678..7cc16494e2 100644
--- a/examples/xml/streambookmarks/xbelwriter.cpp
+++ b/examples/xml/streambookmarks/xbelwriter.cpp
@@ -87,7 +87,7 @@ void XbelWriter::writeItem(const QTreeWidgetItem *item)
{
QString tagName = item->data(0, Qt::UserRole).toString();
if (tagName == QLatin1String("folder")) {
- bool folded = !treeWidget->isItemExpanded(item);
+ bool folded = !item->isExpanded();
xml.writeStartElement(tagName);
xml.writeAttribute(XbelReader::foldedAttribute(), folded ? yesValue() : noValue());
xml.writeTextElement(titleElement(), item->text(0));
diff --git a/mkspecs/android-clang/qmake.conf b/mkspecs/android-clang/qmake.conf
index 975d43779d..8569c08348 100644
--- a/mkspecs/android-clang/qmake.conf
+++ b/mkspecs/android-clang/qmake.conf
@@ -24,10 +24,6 @@ else: equals(ANDROID_TARGET_ARCH, x86): \
QMAKE_CFLAGS += -target i686-none-linux-android -mstackrealign
else: equals(ANDROID_TARGET_ARCH, x86_64): \
QMAKE_CFLAGS += -target x86_64-none-linux-android
-else: equals(ANDROID_TARGET_ARCH, mips): \
- QMAKE_CFLAGS += -target mipsel-none-linux-android
-else: equals(ANDROID_TARGET_ARCH, mips64): \
- QMAKE_CFLAGS += -target mips64el-none-linux-android
QMAKE_CFLAGS += -gcc-toolchain $$NDK_TOOLCHAIN_PATH -fno-limit-debug-info
@@ -51,6 +47,4 @@ exists($$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++.so): \
else: \
ANDROID_CXX_STL_LIBS = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++.so.$$replace(ANDROID_PLATFORM, "android-", "")
-QMAKE_CFLAGS_OPTIMIZE_SIZE = -Oz
-
include(../common/android-base-tail.conf)
diff --git a/mkspecs/common/android-base-head.conf b/mkspecs/common/android-base-head.conf
index a43fc7f23e..ba90ad5f17 100644
--- a/mkspecs/common/android-base-head.conf
+++ b/mkspecs/common/android-base-head.conf
@@ -19,8 +19,6 @@ NDK_TOOLCHAIN_PREFIX = $$(ANDROID_NDK_TOOLCHAIN_PREFIX)
isEmpty(NDK_TOOLCHAIN_PREFIX) {
equals(ANDROID_TARGET_ARCH, x86): NDK_TOOLCHAIN_PREFIX = x86
else: equals(ANDROID_TARGET_ARCH, x86_64): NDK_TOOLCHAIN_PREFIX = x86_64
- else: equals(ANDROID_TARGET_ARCH, mips): NDK_TOOLCHAIN_PREFIX = mipsel-linux-android
- else: equals(ANDROID_TARGET_ARCH, mips64): NDK_TOOLCHAIN_PREFIX = mips64el-linux-android
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): NDK_TOOLCHAIN_PREFIX = aarch64-linux-android
else: NDK_TOOLCHAIN_PREFIX = arm-linux-androideabi
}
@@ -29,8 +27,6 @@ NDK_TOOLS_PREFIX = $$(ANDROID_NDK_TOOLS_PREFIX)
isEmpty(NDK_TOOLS_PREFIX) {
equals(ANDROID_TARGET_ARCH, x86): NDK_TOOLS_PREFIX = i686-linux-android
else: equals(ANDROID_TARGET_ARCH, x86_64): NDK_TOOLS_PREFIX = x86_64-linux-android
- else: equals(ANDROID_TARGET_ARCH, mips): NDK_TOOLS_PREFIX = mipsel-linux-android
- else: equals(ANDROID_TARGET_ARCH, mips64): NDK_TOOLS_PREFIX = mips64el-linux-android
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): NDK_TOOLS_PREFIX = aarch64-linux-android
else: NDK_TOOLS_PREFIX = arm-linux-androideabi
}
@@ -40,8 +36,6 @@ isEmpty(NDK_TOOLCHAIN_VERSION): NDK_TOOLCHAIN_VERSION = $$DEFAULT_ANDROID_NDK_TO
equals(ANDROID_TARGET_ARCH, x86): ANDROID_ARCHITECTURE = x86
else: equals(ANDROID_TARGET_ARCH, x86_64): ANDROID_ARCHITECTURE = x86_64
-else: equals(ANDROID_TARGET_ARCH, mips): ANDROID_ARCHITECTURE = mips
-else: equals(ANDROID_TARGET_ARCH, mips64): ANDROID_ARCHITECTURE = mips64
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): ANDROID_ARCHITECTURE = arm64
else: ANDROID_ARCHITECTURE = arm
diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf
index 5800aaa5b4..aead581478 100644
--- a/mkspecs/common/clang.conf
+++ b/mkspecs/common/clang.conf
@@ -16,10 +16,13 @@ QMAKE_LINK_SHLIB = $$QMAKE_CXX
CONFIG += clang_pch_style
QMAKE_PCH_OUTPUT_EXT = .pch
+QMAKE_CFLAGS_OPTIMIZE_SIZE = -Oz
+
QMAKE_CFLAGS_ISYSTEM = -isystem
QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CFLAGS_USE_PRECOMPILE = -Xclang -include-pch -Xclang ${QMAKE_PCH_OUTPUT}
-QMAKE_CFLAGS_LTCG = -flto
+QMAKE_CFLAGS_LTCG = -flto=thin
+QMAKE_CFLAGS_LTCG_FATOBJECTS = -flto
QMAKE_CFLAGS_DISABLE_LTCG = -fno-lto
QMAKE_CFLAGS_GNUC99 = -std=gnu99
QMAKE_CFLAGS_GNUC11 = -std=gnu11
@@ -27,13 +30,16 @@ QMAKE_CFLAGS_GNUC11 = -std=gnu11
QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
+QMAKE_CXXFLAGS_LTCG_FATOBJECTS = $$QMAKE_CFLAGS_LTCG_FATOBJECTS
QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++1y
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
+QMAKE_CXXFLAGS_CXX2A = -std=c++2a
QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++1y
QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
+QMAKE_CXXFLAGS_GNUCXX2A = -std=gnu++2a
QMAKE_LFLAGS_CXX11 =
QMAKE_LFLAGS_CXX14 =
@@ -44,3 +50,7 @@ QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
QMAKE_AR_LTCG = llvm-ar cqs
QMAKE_NM_LTCG = llvm-nm -P
QMAKE_RANLIB_LTCG = true # No need to run, since llvm-ar has "s"
+
+QMAKE_CFLAGS_COVERAGE_TRACE_PC_GUARD = -fsanitize-coverage=trace-pc-guard
+QMAKE_CXXFLAGS_COVERAGE_TRACE_PC_GUARD = -fsanitize-coverage=trace-pc-guard
+QMAKE_LFLAGS_COVERAGE_TRACE_PC_GUARD = -fsanitize-coverage=trace-pc-guard
diff --git a/mkspecs/common/g++-base.conf b/mkspecs/common/g++-base.conf
index fa0f0c391d..8053feb876 100644
--- a/mkspecs/common/g++-base.conf
+++ b/mkspecs/common/g++-base.conf
@@ -32,9 +32,11 @@ QMAKE_CFLAGS_GNUC11 = -std=gnu11
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++1y
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
+QMAKE_CXXFLAGS_CXX2A = -std=c++2a
QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++1y
QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
+QMAKE_CXXFLAGS_GNUCXX2A = -std=gnu++2a
QMAKE_LFLAGS_CXX11 =
QMAKE_LFLAGS_CXX14 =
QMAKE_LFLAGS_CXX1Z =
diff --git a/mkspecs/common/g++-win32.conf b/mkspecs/common/g++-win32.conf
index f0df324b64..c3a1f3a373 100644
--- a/mkspecs/common/g++-win32.conf
+++ b/mkspecs/common/g++-win32.conf
@@ -31,8 +31,6 @@ QMAKE_YACCFLAGS = -d
QMAKE_CFLAGS_SSE2 += -mstackrealign
-QMAKE_CXXFLAGS_RTTI_ON = -frtti
-QMAKE_CXXFLAGS_RTTI_OFF = -fno-rtti
QMAKE_CXXFLAGS_EXCEPTIONS_ON = -fexceptions -mthreads
QMAKE_INCDIR =
diff --git a/mkspecs/common/gcc-base-unix.conf b/mkspecs/common/gcc-base-unix.conf
index 700f228c36..a456c8f3eb 100644
--- a/mkspecs/common/gcc-base-unix.conf
+++ b/mkspecs/common/gcc-base-unix.conf
@@ -20,7 +20,9 @@ QMAKE_LFLAGS_RPATH = -Wl,-rpath,
QMAKE_LFLAGS_RPATHLINK = -Wl,-rpath-link,
QMAKE_LFLAGS_NEW_DTAGS = -Wl,--enable-new-dtags
QMAKE_LFLAGS_GDB_INDEX = -Wl,--gdb-index
+QMAKE_LFLAGS_USE_BFD = -fuse-ld=bfd
QMAKE_LFLAGS_USE_GOLD = -fuse-ld=gold
+QMAKE_LFLAGS_USE_LLD = -fuse-ld=lld
# -Bsymbolic-functions (ld) support
QMAKE_LFLAGS_BSYMBOLIC_FUNC = -Wl,-Bsymbolic-functions
diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf
index c2669e4833..4d82321cba 100644
--- a/mkspecs/common/gcc-base.conf
+++ b/mkspecs/common/gcc-base.conf
@@ -38,7 +38,7 @@ QMAKE_CFLAGS_OPTIMIZE_SIZE = -Os
!equals(QMAKE_HOST.os, Windows): QMAKE_CFLAGS += -pipe
QMAKE_CFLAGS_DEPS += -M
-QMAKE_CFLAGS_WARN_ON += -Wall -W
+QMAKE_CFLAGS_WARN_ON += -Wall -Wextra
QMAKE_CFLAGS_WARN_OFF += -w
QMAKE_CFLAGS_RELEASE += $$QMAKE_CFLAGS_OPTIMIZE
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -g
@@ -68,6 +68,8 @@ QMAKE_CXXFLAGS_APP += $$QMAKE_CFLAGS_APP
QMAKE_CXXFLAGS_YACC += $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden
QMAKE_CXXFLAGS_EXCEPTIONS_OFF += $$QMAKE_CFLAGS_EXCEPTIONS_OFF
+QMAKE_CXXFLAGS_RTTI_ON = -frtti
+QMAKE_CXXFLAGS_RTTI_OFF = -fno-rtti
QMAKE_CXXFLAGS_SPLIT_SECTIONS += $$QMAKE_CFLAGS_SPLIT_SECTIONS
QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
QMAKE_CXXFLAGS_LTCG_FATOBJECTS = $$QMAKE_CFLAGS_LTCG_FATOBJECTS
diff --git a/mkspecs/common/msvc-desktop.conf b/mkspecs/common/msvc-desktop.conf
index c0d4bd2acc..0b94e5a3f5 100644
--- a/mkspecs/common/msvc-desktop.conf
+++ b/mkspecs/common/msvc-desktop.conf
@@ -115,4 +115,5 @@ VCSOLUTION_EXTENSION = .sln
VCPROJ_KEYWORD = Qt4VSv1.0
include(angle.conf)
+include(windows-desktop.conf)
include(windows-vulkan.conf)
diff --git a/mkspecs/common/msvc-version.conf b/mkspecs/common/msvc-version.conf
index 06af6abf13..af33132077 100644
--- a/mkspecs/common/msvc-version.conf
+++ b/mkspecs/common/msvc-version.conf
@@ -116,6 +116,8 @@ greaterThan(QMAKE_MSC_VER, 1910) {
greaterThan(QMAKE_MSC_VER, 1919) {
# Visual Studio 2019 (16.0) / Visual C++ 19.20 and up
MSVC_VER = 16.0
+ QMAKE_CXXFLAGS_CXX2A = -std:c++latest
+
}
!isEmpty(COMPAT_MKSPEC):!$$COMPAT_MKSPEC: CONFIG += $$COMPAT_MKSPEC
diff --git a/mkspecs/common/rtems-base.conf b/mkspecs/common/rtems-base.conf
new file mode 100644
index 0000000000..0a015c3173
--- /dev/null
+++ b/mkspecs/common/rtems-base.conf
@@ -0,0 +1,73 @@
+#
+# Base qmake configuration for GCC on RTEMS
+#
+#
+#
+MAKEFILE_GENERATOR = UNIX
+
+QMAKE_PLATFORM = rtems
+
+include(unix.conf)
+include(gcc-base-unix.conf)
+include(g++-unix.conf)
+
+rtems_bsp = $$(RTEMS_BSP)
+isEmpty(rtems_bsp) {
+ error("This qmakespec requires $RTEMS_BSP to be set")
+}
+
+rtems_compiler = $$(RTEMS_COMPILER)
+isEmpty(rtems_compiler) {
+ error("This qmakespec requires $RTEMS_COMPILER to be set")
+}
+
+isEmpty(RTEMS_CPU_FLAGS) {
+ error("The qmakespec is expected to set \$\$RTEMS_CPU_FLAGS")
+}
+
+RTEMS_FLAGS = \
+ -B$$rtems_bsp \
+ -specs bsp_specs \
+ -qrtems \
+ $$RTEMS_CPU_FLAGS
+
+QMAKE_CFLAGS_OPTIMIZE_FULL = $$QMAKE_CFLAGS_OPTIMIZE
+QMAKE_CFLAGS_OPTIMIZE_DEBUG = -O0 -g
+
+QMAKE_CFLAGS_DEBUG = $$QMAKE_CFLAGS_OPTIMIZE_DEBUG
+QMAKE_CFLAGS_WARN_ON = -Wall
+QMAKE_CFLAGS_PIC =
+QMAKE_CFLAGS_SHLIB =
+QMAKE_CFLAGS_STATIC_LIB =
+QMAKE_CFLAGS_APP =
+QMAKE_CFLAGS += $$RTEMS_FLAGS
+
+QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
+QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
+QMAKE_CXXFLAGS_SHLIB =
+QMAKE_CXXFLAGS_STATIC_LIB =
+QMAKE_CXXFLAGS_APP =
+QMAKE_CXXFLAGS += $$RTEMS_FLAGS
+
+QMAKE_CXXFLAGS_CXX11 =
+QMAKE_CXXFLAGS_CXX14 =
+QMAKE_CXXFLAGS_CXX1Z =
+
+QMAKE_LFLAGS_GCSECTIONS = -Wl,--gc-sections
+QMAKE_LFLAGS += $$RTEMS_FLAGS $$QMAKE_LFLAGS_GCSECTIONS
+
+QMAKE_CC = $${rtems_compiler}-gcc
+QMAKE_CXX = $${rtems_compiler}-g++
+QMAKE_AR = $${rtems_compiler}-ar cqs
+QMAKE_OBJCOPY = $${rtems_compiler}-objcopy
+QMAKE_NM = $${rtems_compiler}-nm -P
+QMAKE_RANLIB = $${rtems_compiler}-ranlib
+QMAKE_STRIP = $${rtems_compiler}-strip
+
+QMAKE_LINK_C = $$QMAKE_CC
+QMAKE_LINK_C_SHLIB =
+
+QMAKE_LINK = $$QMAKE_CXX
+QMAKE_LINK_SHLIB =
+
+load(qt_config)
diff --git a/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h b/mkspecs/common/rtems/qplatformdefs.h
index 5abd3262dc..1baa7c7d74 100644
--- a/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h
+++ b/mkspecs/common/rtems/qplatformdefs.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2018 The Qt Company. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the qmake spec of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,25 +37,34 @@
**
****************************************************************************/
+#ifndef Q_RTEMS_PLATFORMDEFS_H
+#define Q_RTEMS_PLATFORMDEFS_H
-#ifndef QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
-#define QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
+// Get Qt defines/settings
-#include <QEvent>
-#include "qmirclientlogging.h"
+#include "qglobal.h"
-class OrientationChangeEvent : public QEvent {
-public:
- enum Orientation { TopUp, LeftUp, TopDown, RightUp };
+#include <pthread.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/select.h>
- OrientationChangeEvent(QEvent::Type type, Orientation orientation)
- : QEvent(type)
- , mOrientation(orientation)
- {
- }
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
- static const QEvent::Type mType;
- Orientation mOrientation;
-};
+#include <pwd.h>
+#include <grp.h>
-#endif // QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
+#include "../posix/qplatformdefs.h"
+
+
+#ifdef __STRICT_ANSI__
+#undef __STRICT_ANSI__
+#endif
+
+#undef QT_OPEN_LARGEFILE
+#define QT_OPEN_LARGEFILE 0
+
+#endif // Q_RTEMS_PLATFORMDEFS_H
diff --git a/mkspecs/common/windows-desktop.conf b/mkspecs/common/windows-desktop.conf
new file mode 100644
index 0000000000..c1f2955e1b
--- /dev/null
+++ b/mkspecs/common/windows-desktop.conf
@@ -0,0 +1,5 @@
+# This file contains initializations for Windows Desktop platforms (non-UWP)
+
+WINDOWS_TARGET_PLATFORM_VERSION = $$(WindowsSDKVersion)
+# The version number might have a trailing backslash due to a VS bug.
+WINDOWS_TARGET_PLATFORM_VERSION ~= s/\\\\$//
diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf
index 375e084127..03fb96f2c5 100644
--- a/mkspecs/common/winrt_winphone/qmake.conf
+++ b/mkspecs/common/winrt_winphone/qmake.conf
@@ -97,6 +97,8 @@ WINRT_ASSETS_PATH = $$PWD/assets
WINRT_MANIFEST.capabilities = defaults
WINRT_MANIFEST.capabilities_device = defaults
+WINDOWS_TARGET_PLATFORM_VERSION = $$(UCRTVERSION)
+
include(../angle.conf)
load(qt_config)
diff --git a/mkspecs/features/android/android.prf b/mkspecs/features/android/android.prf
index 1dc8f87313..0e6f4a4592 100644
--- a/mkspecs/features/android/android.prf
+++ b/mkspecs/features/android/android.prf
@@ -1,3 +1,21 @@
+APK_PATH = $$shell_path($$OUT_PWD/android-build/$${TARGET}.apk)
+!contains(TEMPLATE, subdirs): {
+ apk_install_target.target = apk_install_target
+ apk_install_target.depends = first
+ apk_install_target.commands = $(MAKE) -f $(MAKEFILE) INSTALL_ROOT=$$OUT_PWD/android-build install
+
+ apk.target = apk
+ apk.depends = apk_install_target
+ qtPrepareTool(ANDROIDDEPLOYQT, androiddeployqt)
+ isEmpty(ANDROID_DEPLOYMENT_SETTINGS_FILE): ANDROID_DEPLOYMENT_SETTINGS_FILE = $$OUT_PWD/android-$$TARGET-deployment-settings.json
+ contains(QMAKE_HOST.os, Windows): extension = .exe
+ apk.commands = $$ANDROIDDEPLOYQT --input $$ANDROID_DEPLOYMENT_SETTINGS_FILE --output $$OUT_PWD/android-build --apk $$APK_PATH
+} else {
+ prepareRecursiveTarget(apk)
+ prepareRecursiveTarget(apk_install_target)
+}
+QMAKE_EXTRA_TARGETS *= apk apk_install_target
+
contains(TEMPLATE, ".*app") {
!android_app {
!contains(TARGET, ".so"): TARGET = lib$${TARGET}.so
diff --git a/mkspecs/features/android/android_deployment_settings.prf b/mkspecs/features/android/android_deployment_settings.prf
index ad826bdad3..48943fa0f4 100644
--- a/mkspecs/features/android/android_deployment_settings.prf
+++ b/mkspecs/features/android/android_deployment_settings.prf
@@ -25,8 +25,6 @@ contains(TEMPLATE, ".*app"):!build_pass:!android-embedded {
isEmpty(NDK_TOOLCHAIN_PREFIX) {
equals(ANDROID_TARGET_ARCH, x86): NDK_TOOLCHAIN_PREFIX = x86
else: equals(ANDROID_TARGET_ARCH, x86_64): NDK_TOOLCHAIN_PREFIX = x86_64
- else: equals(ANDROID_TARGET_ARCH, mips): NDK_TOOLCHAIN_PREFIX = mipsel-linux-android
- else: equals(ANDROID_TARGET_ARCH, mips64): NDK_TOOLCHAIN_PREFIX = mips64el-linux-android
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): NDK_TOOLCHAIN_PREFIX = aarch64-linux-android
else: NDK_TOOLCHAIN_PREFIX = arm-linux-androideabi
}
diff --git a/mkspecs/features/android/sdk.prf b/mkspecs/features/android/sdk.prf
index eee7ac2d5d..fe7b9a27bd 100644
--- a/mkspecs/features/android/sdk.prf
+++ b/mkspecs/features/android/sdk.prf
@@ -1,6 +1,6 @@
API_VERSION_TO_USE = $$(ANDROID_API_VERSION)
isEmpty(API_VERSION_TO_USE): API_VERSION_TO_USE = $$API_VERSION
-isEmpty(API_VERSION_TO_USE): API_VERSION_TO_USE = android-16
+isEmpty(API_VERSION_TO_USE): API_VERSION_TO_USE = android-21
ANDROID_JAR_FILE = $$ANDROID_SDK_ROOT/platforms/$$API_VERSION_TO_USE/android.jar
!exists($$ANDROID_JAR_FILE) {
diff --git a/mkspecs/features/coverage.prf b/mkspecs/features/coverage.prf
new file mode 100644
index 0000000000..b8b37e1b80
--- /dev/null
+++ b/mkspecs/features/coverage.prf
@@ -0,0 +1,7 @@
+# Coverage flags
+
+coverage_trace_pc_guard {
+ QMAKE_CFLAGS += $$QMAKE_CFLAGS_COVERAGE_TRACE_PC_GUARD
+ QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_COVERAGE_TRACE_PC_GUARD
+ QMAKE_LFLAGS += $$QMAKE_LFLAGS_COVERAGE_TRACE_PC_GUARD
+}
diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
index c729892889..1c4994c30f 100644
--- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
+++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
@@ -48,6 +48,69 @@ but not all the files it references.
endif()
endmacro()
+!!IF !isEmpty(CMAKE_STATIC_TYPE)
+function(_qt5_$${CMAKE_MODULE_NAME}_process_prl_file prl_file_location Configuration lib_deps link_flags)
+ set(_lib_deps)
+ set(_link_flags)
+
+ get_filename_component(_qt5_install_libs \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/lib\" ABSOLUTE)
+
+ if(EXISTS \"${prl_file_location}\")
+ file(STRINGS \"${prl_file_location}\" _prl_strings REGEX \"QMAKE_PRL_LIBS[ \\t]*=\")
+ string(REGEX REPLACE \"QMAKE_PRL_LIBS[ \\t]*=[ \\t]*([^\\n]*)\" \"\\\\1\" _static_depends ${_prl_strings})
+ string(REGEX REPLACE \"[ \\t]+\" \";\" _static_depends ${_static_depends})
+ string(REGEX REPLACE \"[ \\t]+\" \";\" _standard_libraries ${CMAKE_CXX_STANDARD_LIBRARIES})
+ set(_search_paths)
+ string(REPLACE \"\\$\\$[QT_INSTALL_LIBS]\" \"${_qt5_install_libs}\" _static_depends \"${_static_depends}\")
+ foreach(_flag ${_static_depends})
+ string(REPLACE \"\\\"\" \"\" _flag ${_flag})
+ if(_flag MATCHES \"^-l(.*)$\")
+ # Handle normal libraries passed as -lfoo
+ set(_lib \"${CMAKE_MATCH_1}\")
+ foreach(_standard_library ${_standard_libraries})
+ if(_standard_library MATCHES \"^${_lib}(\\.lib)?$\")
+ set(_lib_is_default_linked TRUE)
+ break()
+ endif()
+ endforeach()
+ if (_lib_is_default_linked)
+ unset(_lib_is_default_linked)
+ elseif(_lib MATCHES \"^pthread$\")
+ find_package(Threads REQUIRED)
+ list(APPEND _lib_deps Threads::Threads)
+ else()
+ if(_search_paths)
+ find_library(_Qt5$${CMAKE_MODULE_NAME}_${Configuration}_${_lib}_PATH ${_lib} HINTS ${_search_paths} NO_DEFAULT_PATH)
+ endif()
+ find_library(_Qt5$${CMAKE_MODULE_NAME}_${Configuration}_${_lib}_PATH ${_lib})
+ mark_as_advanced(_Qt5$${CMAKE_MODULE_NAME}_${Configuration}_${_lib}_PATH)
+ if(_Qt5$${CMAKE_MODULE_NAME}_${Configuration}_${_lib}_PATH)
+ list(APPEND _lib_deps
+ ${_Qt5$${CMAKE_MODULE_NAME}_${Configuration}_${_lib}_PATH}
+ )
+ else()
+ message(FATAL_ERROR \"Library not found: ${_lib}\")
+ endif()
+ endif()
+ elseif(EXISTS \"${_flag}\")
+ # The flag is an absolute path to an existing library
+ list(APPEND _lib_deps \"${_flag}\")
+ elseif(_flag MATCHES \"^-L(.*)$\")
+ # Handle -Lfoo flags by putting their paths in the search path used by find_library above
+ list(APPEND _search_paths \"${CMAKE_MATCH_1}\")
+ else()
+ # Handle all remaining flags by simply passing them to the linker
+ list(APPEND _link_flags ${_flag})
+ endif()
+ endforeach()
+ endif()
+
+ string(REPLACE \";\" \" \" _link_flags \"${_link_flags}\")
+ set(${lib_deps} ${_lib_deps} PARENT_SCOPE)
+ set(${link_flags} \"SHELL:${_link_flags}\" PARENT_SCOPE)
+endfunction()
+!!ENDIF
+
!!IF !equals(TEMPLATE, aux)
macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATION IMPLIB_LOCATION)
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${Configuration})
@@ -58,15 +121,29 @@ macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATI
set(imported_location \"$${CMAKE_DLL_DIR}${LIB_LOCATION}\")
!!ENDIF
_qt5_$${CMAKE_MODULE_NAME}_check_file_exists(${imported_location})
+ set(_deps
+ ${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}
+!!IF !isEmpty(CMAKE_STATIC_TYPE)
+ ${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${Configuration}_LIB_DEPENDENCIES}
+!!ENDIF
+ )
set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES
- \"INTERFACE_LINK_LIBRARIES\" \"${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\"
+ \"INTERFACE_LINK_LIBRARIES\" \"${_deps}\"
\"IMPORTED_LOCATION_${Configuration}\" ${imported_location}
!!IF !isEmpty(CMAKE_LIB_SONAME)
\"IMPORTED_SONAME_${Configuration}\" \"$${CMAKE_LIB_SONAME}\"
!!ENDIF
# For backward compatibility with CMake < 2.8.12
- \"IMPORTED_LINK_INTERFACE_LIBRARIES_${Configuration}\" \"${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\"
+ \"IMPORTED_LINK_INTERFACE_LIBRARIES_${Configuration}\" \"${_deps}\"
)
+!!IF !isEmpty(CMAKE_STATIC_TYPE)
+
+ if(NOT CMAKE_VERSION VERSION_LESS \"3.13\")
+ set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES
+ \"INTERFACE_LINK_OPTIONS\" \"${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${Configuration}_LINK_FLAGS}\"
+ )
+ endif()
+!!ENDIF
!!IF !isEmpty(CMAKE_WINDOWS_BUILD)
!!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
@@ -215,6 +292,40 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
!!ENDIF
!!IF !isEmpty(CMAKE_STATIC_TYPE)
+ if(NOT Qt5_EXCLUDE_STATIC_DEPENDENCIES)
+!!IF !isEmpty(CMAKE_DEBUG_TYPE)
+!!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
+ _qt5_$${CMAKE_MODULE_NAME}_process_prl_file(
+ \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_PRL_FILE_LOCATION_DEBUG}\" DEBUG
+ _Qt5$${CMAKE_MODULE_NAME}_STATIC_DEBUG_LIB_DEPENDENCIES
+ _Qt5$${CMAKE_MODULE_NAME}_STATIC_DEBUG_LINK_FLAGS
+ )
+!!ELSE
+ _qt5_$${CMAKE_MODULE_NAME}_process_prl_file(
+ \"$${CMAKE_LIB_DIR}$${CMAKE_PRL_FILE_LOCATION_DEBUG}\" DEBUG
+ _Qt5$${CMAKE_MODULE_NAME}_STATIC_DEBUG_LIB_DEPENDENCIES
+ _Qt5$${CMAKE_MODULE_NAME}_STATIC_DEBUG_LINK_FLAGS
+ )
+!!ENDIF
+!!ENDIF
+
+!!IF !isEmpty(CMAKE_RELEASE_TYPE)
+!!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
+ _qt5_$${CMAKE_MODULE_NAME}_process_prl_file(
+ \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_PRL_FILE_LOCATION_RELEASE}\" RELEASE
+ _Qt5$${CMAKE_MODULE_NAME}_STATIC_RELEASE_LIB_DEPENDENCIES
+ _Qt5$${CMAKE_MODULE_NAME}_STATIC_RELEASE_LINK_FLAGS
+ )
+!!ELSE
+ _qt5_$${CMAKE_MODULE_NAME}_process_prl_file(
+ \"$${CMAKE_LIB_DIR}$${CMAKE_PRL_FILE_LOCATION_RELEASE}\" RELEASE
+ _Qt5$${CMAKE_MODULE_NAME}_STATIC_RELEASE_LIB_DEPENDENCIES
+ _Qt5$${CMAKE_MODULE_NAME}_STATIC_RELEASE_LINK_FLAGS
+ )
+!!ENDIF
+!!ENDIF
+ endif()
+
add_library(Qt5::$${CMAKE_MODULE_NAME} STATIC IMPORTED)
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY IMPORTED_LINK_INTERFACE_LANGUAGES "CXX")
!!ELSE
diff --git a/mkspecs/features/data/testserver/Dockerfile b/mkspecs/features/data/testserver/Dockerfile
new file mode 100644
index 0000000000..8fb664a1d2
--- /dev/null
+++ b/mkspecs/features/data/testserver/Dockerfile
@@ -0,0 +1,27 @@
+# This Dockerfile is used to provision the shared scripts (e.g. startup.sh) and configurations. It
+# relies on the arguments passed by docker-compose file to build additional images for each service.
+# To lean more how it works, please check the topic "Use multi-stage builds".
+# https://docs.docker.com/develop/develop-images/multistage-build/
+
+ARG provisioningImage
+FROM $provisioningImage as testserver_tier2
+
+# Add and merge the testdata into service folder
+ARG serviceDir
+ARG shareDir=$serviceDir
+COPY $serviceDir $shareDir service/
+
+# create the shared script of testserver
+RUN echo "#!/usr/bin/env bash\n" \
+ "set -ex\n" \
+ "for RUN_CMD; do \$RUN_CMD; done\n" \
+ "service dbus restart\n" \
+ "service avahi-daemon restart\n" \
+ "sleep infinity\n" > startup.sh
+RUN chmod +x startup.sh
+
+# rewrite the default configurations of avahi-daemon
+ARG test_domain
+RUN sed -i -e "s,#domain-name=local,domain-name=${test_domain:-test-net.qt.local}," \
+ -e "s,#publish-aaaa-on-ipv4=yes,publish-aaaa-on-ipv4=no," \
+ /etc/avahi/avahi-daemon.conf
diff --git a/mkspecs/features/default_post.prf b/mkspecs/features/default_post.prf
index fbf1f3b8df..0e41b825ec 100644
--- a/mkspecs/features/default_post.prf
+++ b/mkspecs/features/default_post.prf
@@ -78,7 +78,9 @@ stack_protector_strong {
# disable special linker flags for host builds (no proper test for host support yet)
!host_build|!cross_compile {
+ use_bfd_linker: QMAKE_LFLAGS += $$QMAKE_LFLAGS_USE_BFD
use_gold_linker: QMAKE_LFLAGS += $$QMAKE_LFLAGS_USE_GOLD
+ use_lld_linker: QMAKE_LFLAGS += $$QMAKE_LFLAGS_USE_LLD
enable_new_dtags: QMAKE_LFLAGS += $$QMAKE_LFLAGS_NEW_DTAGS
enable_gdb_index: QMAKE_LFLAGS += $$QMAKE_LFLAGS_GDB_INDEX
}
@@ -90,6 +92,10 @@ staticlib:unix {
QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_STATIC_LIB
}
+defined(WINDOWS_TARGET_PLATFORM_VERSION, var):isEmpty(WINDOWS_TARGET_PLATFORM_MIN_VERSION) {
+ WINDOWS_TARGET_PLATFORM_MIN_VERSION = $$WINDOWS_TARGET_PLATFORM_VERSION
+}
+
incredibuild_xge {
CONFIG -= incredibuild_xge
CONFIG = incredibuild_xge $$CONFIG
@@ -114,16 +120,18 @@ breakpad {
}
c++17: CONFIG += c++1z
+c++latest: CONFIG *= c++2a c++1z c++14 c++11
-!c++11:!c++14:!c++1z {
+!c++11:!c++14:!c++1z:!c++2a {
# Qt requires C++11 since 5.7, check if we need to force a compiler option
QT_COMPILER_STDCXX_no_L = $$replace(QT_COMPILER_STDCXX, "L$", "")
!greaterThan(QT_COMPILER_STDCXX_no_L, 199711): CONFIG += c++11
}
-c++11|c++14|c++1z {
+c++11|c++14|c++1z|c++2a {
# Disable special compiler flags for host builds
!host_build|!cross_compile {
- c++1z: cxxstd = CXX1Z
+ c++2a: cxxstd = CXX2A
+ else: c++1z: cxxstd = CXX1Z
else: c++14: cxxstd = CXX14
else: cxxstd = CXX11
} else {
diff --git a/mkspecs/features/exclusive_builds.prf b/mkspecs/features/exclusive_builds.prf
index 1ff9a04d42..b28e74146a 100644
--- a/mkspecs/features/exclusive_builds.prf
+++ b/mkspecs/features/exclusive_builds.prf
@@ -38,5 +38,5 @@ defineTest(addExclusiveBuilds) {
}
# Default directories to process
-QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR QMLCACHE_DIR LRELEASE_DIR
-QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR LRELEASE_DIR
+QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR LRELEASE_DIR LEX_DIR YACC_DIR
+QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR DESTDIR $$QMAKE_DIR_REPLACE_SANE
diff --git a/mkspecs/features/lex.prf b/mkspecs/features/lex.prf
index 7d8325bedb..ee06215103 100644
--- a/mkspecs/features/lex.prf
+++ b/mkspecs/features/lex.prf
@@ -2,37 +2,49 @@
# Lex extra-compiler for handling files specified in the LEXSOURCES variable
#
-{
- lex.name = Lex ${QMAKE_FILE_IN}
- lex.input = LEXSOURCES
- lex.dependency_type = TYPE_C
- lex_included {
- lex.CONFIG += no_link
- } else {
- lex.variable_out = GENERATED_SOURCES
- }
+isEmpty(LEX_DIR): LEX_DIR = .
- isEmpty(QMAKE_LEXFLAGS_MANGLE):QMAKE_LEXFLAGS_MANGLE = -P${QMAKE_FILE_BASE}
+defineReplace(lexCommands) {
+ input = $$relative_path($$absolute_path($$1, $$OUT_PWD), $$OUT_PWD/$$LEX_DIR)
+ output = $$basename(2)
+ input_base = $$basename(1)
+ input_base ~= s/\.[^.]*$//
+
+ isEmpty(QMAKE_LEXFLAGS_MANGLE): QMAKE_LEXFLAGS_MANGLE = -P$${input_base}
QMAKE_LEXEXTRAFLAGS = $$QMAKE_LEXFLAGS
- !yacc_no_name_mangle:QMAKE_LEXEXTRAFLAGS += $$QMAKE_LEXFLAGS_MANGLE
+ !yacc_no_name_mangle: QMAKE_LEXEXTRAFLAGS += $$QMAKE_LEXFLAGS_MANGLE
contains(QMAKE_LEX, .*flex) {
# GNU flex, we can use -o outfile
- lex.commands = $$QMAKE_LEX $$QMAKE_LEXEXTRAFLAGS --nounistd -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
+ commands = $$QMAKE_LEX $$QMAKE_LEXEXTRAFLAGS --nounistd -o $$output $$input
} else {
# stupid POSIX lex, it only generates a file called lex.yy.c
# or lex.prefix.c if the -P<prefix> option is active
intermediate_file = lex.yy.c
QMAKE_LEXEXTRAFLAGS = $$QMAKE_LEXFLAGS $$QMAKE_LEXFLAGS_MANGLE
- lex.commands = \
- -$(DEL_FILE) ${QMAKE_FILE_OUT}$$escape_expand(\\n\\t) \
- $$QMAKE_LEX $$QMAKE_LEXEXTRAFLAGS ${QMAKE_FILE_IN}$$escape_expand(\\n\\t) \
- $(MOVE) $$intermediate_file ${QMAKE_FILE_OUT} $$escape_expand(\\n\\t)
- unset(intermediate_file)
+ commands = \
+ -$(DEL_FILE) $${output}$$escape_expand(\\n\\t) \
+ $$QMAKE_LEX $$QMAKE_LEXEXTRAFLAGS $${input}$$escape_expand(\\n\\t) \
+ $(MOVE) $$intermediate_file $$output $$escape_expand(\\n\\t)
+ }
+ !equals(LEX_DIR, .): \
+ commands = cd $$LEX_DIR && $$commands
+ silent: commands = @echo Lex $$1 && $$commands
+ return($$commands)
+}
+
+{
+ lex.name = Lex ${QMAKE_FILE_IN}
+ lex.input = LEXSOURCES
+ lex.dependency_type = TYPE_C
+ lex_included {
+ lex.CONFIG += no_link
+ } else {
+ lex.variable_out = GENERATED_SOURCES
}
- lex.output = $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_LEX}$${first(QMAKE_EXT_CPP)}
- silent:lex.commands = @echo Lex ${QMAKE_FILE_IN} && $$lex.commands
+ lex.commands = ${QMAKE_FUNC_lexCommands}
+ lex.output = $$LEX_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_LEX}$${first(QMAKE_EXT_CPP)}
QMAKE_EXTRA_COMPILERS += lex
}
diff --git a/mkspecs/features/ltcg.prf b/mkspecs/features/ltcg.prf
index f2dbc6fa9e..43ba482954 100644
--- a/mkspecs/features/ltcg.prf
+++ b/mkspecs/features/ltcg.prf
@@ -2,7 +2,7 @@ CONFIG(release, debug|release) {
# We need fat object files when creating static libraries on some platforms
# so the linker will know to load a particular object from the library
# in the first place. On others, we have special ar and nm to create the symbol
- # tables so the linker will know better. For other compilers, we disable LTCG
+ # tables so the linker will know better. For other compilers, we disable LTCG
# for static libraries.
msvc {
# Nothing to do
diff --git a/mkspecs/features/qml_plugin.prf b/mkspecs/features/qml_plugin.prf
index ad8ecdf5f1..02068ae766 100644
--- a/mkspecs/features/qml_plugin.prf
+++ b/mkspecs/features/qml_plugin.prf
@@ -94,7 +94,7 @@ load(qt_common)
}
load(resolve_target)
- TARGETPATHBASE = $$replace(TARGETPATH, \\.\\d+\$, )
+ isEmpty(IMPORT_NAME): IMPORT_NAME = $$replace(TARGETPATH, \\.\\d+\$, )
!qml1_target {
isEmpty(QMAKE_PLUGINDUMP_DEPENDENCIES_FILE):exists($$_PRO_FILE_PWD_/dependencies.json): \
@@ -104,7 +104,7 @@ load(qt_common)
}
qmltypes.target = qmltypes
- qmltypes.commands = $$QMLPLUGINDUMP -nonrelocatable $$QMAKE_QMLPLUGINDUMP_FLAGS $$replace(TARGETPATHBASE, /, .) $$IMPORT_VERSION > $$QMLTYPEFILE
+ qmltypes.commands = $$QMLPLUGINDUMP -nonrelocatable $$QMAKE_QMLPLUGINDUMP_FLAGS $$replace(IMPORT_NAME, /, .) $$IMPORT_VERSION > $$QMLTYPEFILE
qmltypes.depends = $$QMAKE_RESOLVED_TARGET
} else {
qmltypes.CONFIG += recursive
diff --git a/mkspecs/features/qmltestcase.prf b/mkspecs/features/qmltestcase.prf
index b4b1224781..ae4ebef513 100644
--- a/mkspecs/features/qmltestcase.prf
+++ b/mkspecs/features/qmltestcase.prf
@@ -1,8 +1,14 @@
!isEmpty(SOURCES) {
QT += qml qmltest
load(testcase)
- contains(TEMPLATE, vc.*): DEFINES += QUICK_TEST_SOURCE_DIR=\"$$_PRO_FILE_PWD_\"
- else: DEFINES += QUICK_TEST_SOURCE_DIR=$$shell_quote(\"$$_PRO_FILE_PWD_\")
+ !android {
+ contains(TEMPLATE, vc.*): DEFINES += QUICK_TEST_SOURCE_DIR=\"$$_PRO_FILE_PWD_\"
+ else: DEFINES += QUICK_TEST_SOURCE_DIR=$$shell_quote(\"$$_PRO_FILE_PWD_\")
+ } else {
+ !isEmpty(RESOURCES): warning("The RESOURCES qmake variable is empty, the test will probably fail to run")
+ DEFINES += QUICK_TEST_SOURCE_DIR=\":/\"
+ }
+
} else {
# Allow a project to run tests without a CPP stub
TEMPLATE = aux
diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf
index 89f4946c50..3a71376029 100644
--- a/mkspecs/features/qt.prf
+++ b/mkspecs/features/qt.prf
@@ -2,7 +2,7 @@
# due to required Qt modules being missing.
!isEmpty(QMAKE_FAILED_REQUIREMENTS): return()
-CONFIG *= thread
+qtConfig(thread): CONFIG *= thread
#handle defines
win32 {
diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf
index caecb68a84..c24f2c6062 100644
--- a/mkspecs/features/qt_common.prf
+++ b/mkspecs/features/qt_common.prf
@@ -17,6 +17,7 @@ DEFINES *= QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
qtConfig(c++11): CONFIG += c++11 strict_c++
qtConfig(c++14): CONFIG += c++14
qtConfig(c++1z): CONFIG += c++1z
+qtConfig(c++2a): CONFIG += c++2a
qtConfig(c99): CONFIG += c99
qtConfig(c11): CONFIG += c11
qtConfig(stack-protector-strong): CONFIG += stack_protector_strong
@@ -99,14 +100,8 @@ clang {
greaterThan(QT_GCC_MAJOR_VERSION, 5): QMAKE_CXXFLAGS_WARN_ON += -Wshift-overflow=2 -Wduplicated-cond
# GCC 7 has a lot of false positives relating to this, so disable completely
greaterThan(QT_GCC_MAJOR_VERSION, 6): QMAKE_CXXFLAGS_WARN_ON += -Wno-stringop-overflow
- # GCC 9 has a lot of false positives relating to this, so disable completely
- greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-deprecated-copy
- # GCC 9 introduced this
- greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-redundant-move
- # GCC 9 introduced this
+ # GCC 9 introduced -Wformat-overflow in -Wall, but it is buggy:
greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-format-overflow
- # GCC 9 introduced this
- greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-init-list-lifetime
}
warnings_are_errors:warning_clean {
@@ -115,10 +110,10 @@ warnings_are_errors:warning_clean {
# compiler.
clang {
# Apple clang 4.0-4.2,5.0-5.1,6.0-6.4,7.0-7.3,8.0-8.3,9.0-9.2
- # Regular clang 3.x-6.0
+ # Regular clang 3.x-7.0
apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}
reg_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
- contains(apple_ver, "4\\.[012]|5\\.[01]|6\\.[01234]|7\\.[0123]|8\\.[0123]|9\\.[012]")|contains(reg_ver, "[345]\\.|6\\.0") {
+ contains(apple_ver, "4\\.[012]|5\\.[01]|6\\.[01234]|7\\.[0123]|8\\.[0123]|9\\.[012]")|contains(reg_ver, "[345]\\.|[67]\\.0") {
QMAKE_CXXFLAGS_WARN_ON += -Werror -Wno-error=\\$${LITERAL_HASH}warnings -Wno-error=deprecated-declarations $$WERROR
}
} else:intel_icc:linux {
@@ -146,20 +141,19 @@ warnings_are_errors:warning_clean {
# GCC 7 includes -Wimplicit-fallthrough in -Wextra, but Qt is not yet free of implicit fallthroughs.
greaterThan(QT_GCC_MAJOR_VERSION, 6): QMAKE_CXXFLAGS_WARN_ON += -Wno-error=implicit-fallthrough
- # GCC 9 has a lot of false positives relating to this, so disable completely
- greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-deprecated-copy
+ # GCC 9 introduced -Wdeprecated-copy in -Wextra, but we are not clean for it.
+ greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-error=deprecated-copy
# GCC 9 introduced this
- greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-redundant-move
+ greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-error=redundant-move
# GCC 9 introduced this
- greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-format-overflow
- # GCC 9 introduced this
- greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-init-list-lifetime
+ greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-error=init-list-lifetime
+
# Work-around for bug https://code.google.com/p/android/issues/detail?id=58135
android: QMAKE_CXXFLAGS_WARN_ON += -Wno-error=literal-suffix
}
} else:msvc:!intel_icl {
- # enable for MSVC 2012, MSVC 2013, MSVC 2015
- contains(MSVC_VER, "1[124].0"): QMAKE_CXXFLAGS_WARN_ON += -WX
+ # enable for MSVC 2015, MSVC 2017
+ contains(MSVC_VER, "1[45].0"): QMAKE_CXXFLAGS_WARN_ON += -WX
}
unset(ver)
}
diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf
index 242544d41b..2ac9de266f 100644
--- a/mkspecs/features/qt_configure.prf
+++ b/mkspecs/features/qt_configure.prf
@@ -61,6 +61,13 @@ defineTest(qtConfCommandlineSetInput) {
val = $${2}
!isEmpty($${currentConfig}.commandline.options.$${arg}.name): \
arg = $$eval($${currentConfig}.commandline.options.$${arg}.name)
+ !isEmpty(config.input.$$arg) {
+ oldval = $$eval(config.input.$$arg)
+ equals(oldval, $$val): \
+ qtConfAddNote("Option '$$arg' with value '$$val' was specified twice")
+ else: \
+ qtConfAddNote("Overriding option '$$arg' with '$$val' (was: '$$oldval')")
+ }
config.input.$$arg = $$val
export(config.input.$$arg)
@@ -380,8 +387,12 @@ defineTest(qtConfTest_compilerSupportsFlag) {
defineTest(qtConfTest_linkerSupportsFlag) {
flag = $$eval($${1}.flag)
+ use_bfd_linker: \
+ LFLAGS = -fuse-ld=bfd
use_gold_linker: \
LFLAGS = -fuse-ld=gold
+ use_lld_linker: \
+ LFLAGS = -fuse-ld=lld
return($$qtConfToolchainSupportsFlag($$LFLAGS "-Wl,$$flag"))
}
@@ -1262,8 +1273,12 @@ defineTest(qtConfTest_compile) {
else: \
qmake_configs = "static"
+ use_bfd_linker: \
+ qmake_configs += "use_bfd_linker"
use_gold_linker: \
qmake_configs += "use_gold_linker"
+ use_lld_linker: \
+ qmake_configs += "use_lld_linker"
# disable warnings from the builds, since they're just noise at this point.
qmake_configs += "warn_off"
diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf
index 18060cd490..cb3707cf8c 100644
--- a/mkspecs/features/qt_module.prf
+++ b/mkspecs/features/qt_module.prf
@@ -269,7 +269,7 @@ load(qt_installs)
load(qt_targets)
# this builds on top of qt_common
-!internal_module:if(unix|mingw) {
+!internal_module:if(unix|mingw):!if(darwin:debug_and_release:CONFIG(debug, debug|release)) {
CONFIG += create_pc
QMAKE_PKGCONFIG_DESTDIR = pkgconfig
host_build: \
@@ -282,11 +282,13 @@ load(qt_targets)
} else {
QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS/raw]
QMAKE_PKGCONFIG_CFLAGS = -D$$MODULE_DEFINE -I${includedir}/$$MODULE_INCNAME
+ for(inc, MODULE_AUX_INCLUDES): \
+ QMAKE_PKGCONFIG_CFLAGS += -I${includedir}/$$section(inc, /, 1, 1)
}
QMAKE_PKGCONFIG_NAME = $$replace(TARGET, ^Qt, "Qt$$QT_MAJOR_VERSION ")
- QMAKE_PKGCONFIG_FILE = $$replace(TARGET, ^Qt, Qt$$QT_MAJOR_VERSION)
+ QMAKE_PKGCONFIG_FILE = $$replace(TARGET, ^Qt, Qt$$QT_MAJOR_VERSION)$$qtPlatformTargetSuffix()
for(i, MODULE_DEPENDS): \
- QMAKE_PKGCONFIG_REQUIRES += $$replace(QT.$${i}.name, ^Qt, Qt$$section(QT.$${i}.VERSION, ., 0, 0))
+ QMAKE_PKGCONFIG_REQUIRES += $$replace(QT.$${i}.name, ^Qt, Qt$$section(QT.$${i}.VERSION, ., 0, 0))$$qtPlatformTargetSuffix()
isEmpty(QMAKE_PKGCONFIG_DESCRIPTION): \
QMAKE_PKGCONFIG_DESCRIPTION = $$replace(TARGET, ^Qt, "Qt ") module
pclib_replace.match = $$lib_replace.match
@@ -322,5 +324,6 @@ win32 {
# On other platforms, Qt's own compilation goes needs to compile the Qt 5.0 API
DEFINES *= QT_DISABLE_DEPRECATED_BEFORE=0x050000
}
+DEFINES *= QT_DEPRECATED_WARNINGS_SINCE=0x060000
TARGET = $$qt5LibraryTarget($$TARGET$$QT_LIBINFIX) # Do this towards the end
diff --git a/mkspecs/features/qt_plugin.prf b/mkspecs/features/qt_plugin.prf
index 40528a65e2..6e7388c352 100644
--- a/mkspecs/features/qt_plugin.prf
+++ b/mkspecs/features/qt_plugin.prf
@@ -91,6 +91,7 @@ CONFIG(static, static|shared)|prefix_build {
target.path = $$[QT_INSTALL_PLUGINS]/$$PLUGIN_TYPE
INSTALLS += target
+qt_libinfix_plugins: TARGET = $$TARGET$$QT_LIBINFIX
TARGET = $$qt5LibraryTarget($$TARGET)
CONFIG += create_cmake
diff --git a/mkspecs/features/win32/rtti.prf b/mkspecs/features/rtti.prf
index 6d720d2438..6d720d2438 100644
--- a/mkspecs/features/win32/rtti.prf
+++ b/mkspecs/features/rtti.prf
diff --git a/mkspecs/features/win32/rtti_off.prf b/mkspecs/features/rtti_off.prf
index b520bfa8b7..b520bfa8b7 100644
--- a/mkspecs/features/win32/rtti_off.prf
+++ b/mkspecs/features/rtti_off.prf
diff --git a/mkspecs/features/sanitizer.prf b/mkspecs/features/sanitizer.prf
index 9e7ff0218a..c7d72aec80 100644
--- a/mkspecs/features/sanitizer.prf
+++ b/mkspecs/features/sanitizer.prf
@@ -1,10 +1,33 @@
# Sanitizer flags
-
sanitize_address {
QMAKE_CFLAGS += $$QMAKE_SANITIZE_ADDRESS_CFLAGS
QMAKE_CXXFLAGS += $$QMAKE_SANITIZE_ADDRESS_CXXFLAGS
QMAKE_LFLAGS += $$QMAKE_SANITIZE_ADDRESS_LFLAGS
+ android {
+ # ARM 32 (armeabi-v7a & arm5) are not supported because Qt must be rebuilt with -marm
+ equals(ANDROID_TARGET_ARCH, arm64-v8a): ANDROID_LIBCLANG_RT_FILE = "libclang_rt.asan-aarch64-android.so"
+ else: equals(ANDROID_TARGET_ARCH, x86): ANDROID_LIBCLANG_RT_FILE = "libclang_rt.asan-i686-android.so"
+ else: equals(ANDROID_TARGET_ARCH, x86_64): ANDROID_LIBCLANG_RT_FILE = "libclang_rt.asan-x86_64-android.so"
+ else: error("ASAN: Unsupported platform $${ANDROID_TARGET_ARCH}")
+
+ ANDROID_LIBCLANG_RT_PATH = $${NDK_LLVM_PATH}/lib64/clang
+ ANDROID_CLANG_RT_VERSIONS = $$files($$ANDROID_LIBCLANG_RT_PATH/*)
+ for (VERSION, ANDROID_CLANG_RT_VERSIONS) {
+ greaterThan(VERSION, $$ANDROID_LIBCLANG_RT_PATH): ANDROID_LIBCLANG_RT_PATH = $$VERSION
+ }
+ ANDROID_LIBCLANG_RT_PATH = "$${ANDROID_LIBCLANG_RT_PATH}/lib/linux/"
+ ANDROID_WRAP_SH_CONTENT = "$$LITERAL_HASH!/system/bin/sh"
+ ANDROID_WRAP_SH_CONTENT += "HERE=\"$(cd \"$(dirname \"$0\")\" && pwd)\""
+ isEmpty(ANDROID_ASAN_OPTIONS): ANDROID_ASAN_OPTIONS = "log_to_syslog=false,allow_user_segv_handler=1"
+ ANDROID_WRAP_SH_CONTENT += "export ASAN_OPTIONS=$${ANDROID_ASAN_OPTIONS}"
+ ANDROID_WRAP_SH_CONTENT += "export LD_PRELOAD=$HERE/$${ANDROID_LIBCLANG_RT_FILE}"
+ ANDROID_WRAP_SH_CONTENT += "exec \"$@\""
+ write_file($$OUT_PWD/android-build/resources/lib/$${ANDROID_TARGET_ARCH}/wrap.sh, ANDROID_WRAP_SH_CONTENT) | error()
+ libclang_rt.path = /libs/$$ANDROID_TARGET_ARCH/
+ libclang_rt.files = "$${ANDROID_LIBCLANG_RT_PATH}/$${ANDROID_LIBCLANG_RT_FILE}"
+ INSTALLS += libclang_rt
+ }
}
sanitize_memory {
diff --git a/mkspecs/features/testcase.prf b/mkspecs/features/testcase.prf
index b8102c26b5..d4f08835f1 100644
--- a/mkspecs/features/testcase.prf
+++ b/mkspecs/features/testcase.prf
@@ -52,14 +52,26 @@ debug_and_release:debug_and_release_target {
}
# Allow for a custom test runner script
-$${type}.commands += $(TESTRUNNER)
+
+android: isEmpty($(TESTRUNNER)) {
+ APK_PATH = $$shell_path($$OUT_PWD/android-build/$${TARGET}.apk)
+ qtPrepareTool(ANDROIDTESTRUNNER, androidtestrunner)
+ qtPrepareTool(ANDROIDDEPLOYQT, androiddeployqt)
+ isEmpty(ANDROID_DEPLOYMENT_SETTINGS_FILE): ANDROID_DEPLOYMENT_SETTINGS_FILE = $$OUT_PWD/android-$$TARGET-deployment-settings.json
+ contains(QMAKE_HOST.os, Windows): extension = .exe
+ $${type}.commands = $$ANDROIDTESTRUNNER --androiddeployqt \"$$ANDROIDDEPLOYQT --input $$ANDROID_DEPLOYMENT_SETTINGS_FILE\"
+ $${type}.commands += --path \"$$OUT_PWD/android-build\"
+ $${type}.commands += --adb \"$$shell_path($${ANDROID_SDK_ROOT}$${QMAKE_DIR_SEP}platform-tools$${QMAKE_DIR_SEP}adb$${extension})\"
+ $${type}.commands += --make \"$(MAKE) -f $(MAKEFILE)\"
+ $${type}.commands += --apk $$APK_PATH
+} else: $${type}.commands += $(TESTRUNNER)
unix {
isEmpty(TEST_TARGET_DIR): TEST_TARGET_DIR = .
app_bundle: \
$${type}.commands += $${TEST_TARGET_DIR}/$(QMAKE_TARGET).app/Contents/MacOS/$(QMAKE_TARGET)
- else: \
+ else: !android: \
$${type}.commands += $${TEST_TARGET_DIR}/$(QMAKE_TARGET)
} else {
# Windows
diff --git a/mkspecs/features/unsupported/testserver.prf b/mkspecs/features/unsupported/testserver.prf
new file mode 100644
index 0000000000..6507a360c5
--- /dev/null
+++ b/mkspecs/features/unsupported/testserver.prf
@@ -0,0 +1,221 @@
+# Integrating docker-based test servers into Qt Test framework
+#
+# This file adds support for docker-based test servers built by testcase
+# projects that need them. To enable this feature, any automated test can
+# include testserver.pri in its project file. This instructs qmake to insert
+# additional targets into the generated Makefile. The 'check' target then brings
+# up test servers before running the testcase, and shuts them down afterwards.
+#
+# TESTSERVER_COMPOSE_FILE
+# - Contains the path of docker-compose file
+# This configuration file defines the services used for autotests. It tells the
+# docker engine how to build up the docker images and containers. In qtbase, a
+# shared docker-compose file is located in the tests folder.
+# Example: TESTSERVER_COMPOSE_FILE = \
+# $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml
+#
+# The user must run the provisioning scripts in advance before attempting to
+# build the test servers. The docker_testserver.sh script is used to build up
+# the docker images into the docker-cache. It handles the immutable parts of the
+# server installation that rarely need adjustment, such as downloading packages.
+# Example: qt5/coin/provisioning/.../testserver/docker_testserver.sh
+#
+# QT_TEST_SERVER_LIST
+# - A list of test servers to bring up for this testcase
+# These test servers should be defined in $$TESTSERVER_COMPOSE_FILE. Each
+# testcase can define the test servers it depends on.
+# Example: QT_TEST_SERVER_LIST = apache2 squid vsftpd ftp-proxy danted
+#
+# Pre-processor defines needed for the application:
+# QT_TEST_SERVER
+# - A preprocessor macro used for testcase to change testing parameters at
+# compile time
+# This macro is predefined for docker-based test servers and is passed as a
+# compiler option (-DQT_TEST_SERVER). The testcase can then check whether
+# docker-based servers are in use and change the testing parameters, such as
+# host name or port number, at compile time. An example can be found in
+# network-settings.h.
+#
+# Example:
+# #if defined(QT_TEST_SERVER)
+# Change the testing parameters at compile time
+# #endif
+#
+# QT_TEST_SERVER_DOMAIN
+# - A preprocessor macro that holds the server domain name
+# Provided for the helper functions in network-settings.h. Use function
+# serverDomainName() in your application instead.
+#
+# Additional make targets:
+# 1. check_network - A renamed target from the check target of testcase feature.
+# 2. testserver_clean - Clean up server containers/images and tidy away related
+# files.
+
+# The docker test server should only be integrated in the leaf Makefile.
+# If debug_and_release option is in use, skip the meta-Makefile except for
+# Makefile.Debug and Makefile.Release.
+debug_and_release:!build_pass: return()
+
+DOCKER_ENABLED = 1
+
+equals(QMAKE_HOST.os, Darwin) | equals(QMAKE_HOST.os, Windows) {
+ DOCKER_ENABLED = 0
+ message("Not using docker network test server on macOS and Windows, see QTQAINFRA-2717 and QTQAINFRA-2750")
+}
+
+TESTSERVER_VERSION = ""
+
+equals(DOCKER_ENABLED, 1) {
+ TESTSERVER_VERSION = $$system(docker-compose --version)
+}
+
+isEmpty(TESTSERVER_VERSION) {
+ # Make check with server "qt-test-server.qt-test-net" as a fallback
+} else {
+ # Make check with docker test servers
+ equals(QMAKE_HOST.os, Linux) {
+ # For the platform supporting docker bridge network, each container is
+ # assigned a unique hostname and connected to the same network domain
+ # to communicate with the others.
+ DEFINES += QT_TEST_SERVER_NAME
+ DNSDOMAIN = test-net.qt.local
+ } else {
+ # For the others, the containers are deployed into a virtual machine
+ # using the host network. All the containers share the same hostname of
+ # the virtual machine, and they are connected to the same network domain.
+ # NOTE: In Windows, Apple Bonjour only works within a single local domain.
+ DNSDOMAIN = local
+ }
+
+ equals(QMAKE_HOST.os, Darwin) {
+ # There is no docker bridge on macOS. It is impossible to ping a container.
+ # Docker docs recommends using port mapping to connect to a container;
+ # but it causes a port conflict if the user is running a service that
+ # binds the same port on the host. An alternative solution is to deploy
+ # the docker environment into VirtualBox using docker-machine.
+ isEmpty(TESTSERVER_COMPOSE_FILE): TESTSERVER_COMPOSE_FILE = \
+ $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose-for-macOS.yml
+
+ # The connection configuration for the target machine
+ MACHINE_CONFIG = $(shell docker-machine config qt-test-server)
+
+ # The environment variables passed to the docker-compose file
+ TEST_ENV = 'MACHINE_IP=$(shell docker-machine ip qt-test-server)'
+ TEST_ENV += 'TEST_DOMAIN=$$DNSDOMAIN'
+ TEST_ENV += 'SHARED_DATA=$$PWD/../data/testserver'
+ TEST_CMD = env
+ } else:equals(QMAKE_HOST.os, Windows) {
+ # There is no docker bridge on Windows. It is impossible to ping a container.
+ # Use docker-machine to deploy the docker environment into VirtualBox.
+ isEmpty(TESTSERVER_COMPOSE_FILE): TESTSERVER_COMPOSE_FILE = \
+ $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose-for-windows.yml
+
+ # The connection configuration for the target machine
+ MACHINE_CONFIG = (docker-machine config qt-test-server)
+
+ # The environment variables passed to the docker-compose file
+ TEST_ENV = '\$\$env:MACHINE_IP = docker-machine ip qt-test-server;'
+ TEST_ENV += '\$\$env:TEST_DOMAIN = $$shell_quote(\"$$DNSDOMAIN\");'
+ TEST_ENV += '\$\$env:SHARED_DATA = $$shell_quote(\"$$PWD/../data/testserver\");'
+
+ # Docker-compose CLI environment variables:
+ # Enable path conversion from Windows-style to Unix-style in volume definitions.
+ TEST_ENV += '\$\$env:COMPOSE_CONVERT_WINDOWS_PATHS = $$shell_quote(\"true\");'
+
+ TEST_CMD = 'PowerShell -noprofile'
+ CONFIG += PowerShell
+ } else {
+ isEmpty(TESTSERVER_COMPOSE_FILE): TESTSERVER_COMPOSE_FILE = \
+ $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml
+ # The environment variables passed to the docker-compose file
+ TEST_ENV = 'TEST_DOMAIN=$$DNSDOMAIN'
+ TEST_ENV += 'SHARED_DATA=$$PWD/../data/testserver'
+ TEST_CMD = env
+ }
+ !exists($$TESTSERVER_COMPOSE_FILE): error("Invalid TESTSERVER_COMPOSE_FILE specified")
+
+
+ # The domain name is relevant to https keycert (qnetworkreply/crts/qt-test-net-cacert.pem).
+ DEFINES += QT_TEST_SERVER QT_TEST_SERVER_DOMAIN=$$shell_quote(\"$${DNSDOMAIN}\")
+
+ # Ensure that the docker-compose file is provided. It is a configuration
+ # file which is mandatory for all docker-compose commands. You can get more
+ # detail from the description of TESTSERVER_COMPOSE_FILE above. There is
+ # also an example showing how to configure it manually.
+ FILE_PRETEST_MSG = "Project variable 'TESTSERVER_COMPOSE_FILE' is not set"
+ PowerShell {
+ testserver_pretest.commands = echo $$TESTSERVER_VERSION &&
+ testserver_pretest.commands += \
+ $$TEST_CMD if ([String]::IsNullOrEmpty($$shell_quote(\"$$TESTSERVER_COMPOSE_FILE\"))) \
+ {Write-Error $$shell_quote(\"$$FILE_PRETEST_MSG\")} &&
+ } else {
+ testserver_pretest.commands = $(info "testserver:" $$TESTSERVER_VERSION)
+ testserver_pretest.commands += $(if $$TESTSERVER_COMPOSE_FILE,,$(error $$FILE_PRETEST_MSG))
+ }
+
+ # Make sure docker-machine is both created and running. The docker_machine
+ # script is used to deploy the docker environment into VirtualBox.
+ # Example: qt5/coin/provisioning/common/shared/testserver/docker_machine.sh
+ !isEmpty(MACHINE_CONFIG) {
+ MACHINE_LIST_CMD = docker-machine ls -q --filter "Name=^qt-test-server\$\$"
+ MACHINE_LIST_MSG = "Docker machine qt-test-server not found"
+ PowerShell {
+ testserver_pretest.commands += $$TEST_CMD if (!($$MACHINE_LIST_CMD)) \
+ {Write-Error $$shell_quote(\"$$MACHINE_LIST_MSG\")} &&
+ } else {
+ testserver_pretest.commands += \
+ $(if $(shell $$MACHINE_LIST_CMD),,$(error $$MACHINE_LIST_MSG))
+ }
+
+ MACHINE_STATE_CMD = \
+ docker-machine ls -q --filter "State=Running" --filter "Name=^qt-test-server\$\$"
+ MACHINE_START_CMD = docker-machine start qt-test-server
+ MACHINE_RECERT = docker-machine regenerate-certs -f qt-test-server
+ PowerShell {
+ testserver_pretest.commands += \
+ $$TEST_CMD if (!($$MACHINE_STATE_CMD)) {$$MACHINE_START_CMD; $$MACHINE_RECERT} &&
+ } else {
+ testserver_pretest.commands += \
+ $(if $(shell $$MACHINE_STATE_CMD),,\
+ $(shell $$MACHINE_START_CMD > /dev/null && $$MACHINE_RECERT > /dev/null))
+ }
+ }
+
+ # Before starting the test servers, it requires the user to run the setup
+ # script (coin/provisioning/.../testserver/docker_testserver.sh) in advance.
+ IMAGE_PRETEST_CMD = docker $$MACHINE_CONFIG images -aq "qt-test-server-*"
+ IMAGE_PRETEST_MSG = "Docker image qt-test-server-* not found"
+ PowerShell {
+ testserver_pretest.commands += $$TEST_CMD if (!($$IMAGE_PRETEST_CMD)) \
+ {Write-Error $$shell_quote(\"$$IMAGE_PRETEST_MSG\")}
+ } else {
+ testserver_pretest.commands += \
+ $(if $(shell $$IMAGE_PRETEST_CMD),,$(error $$IMAGE_PRETEST_MSG))
+ }
+
+ # Rename the check target of testcase feature
+ check.target = check_network
+ testserver_test.target = check
+
+ # Pretesting test servers environment
+ testserver_test.depends = testserver_pretest
+
+ # Bring up test servers and make sure the services are ready.
+ !isEmpty(TEST_CMD): testserver_test.commands = $$TEST_CMD $$TEST_ENV
+ testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE up \
+ --build -d --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} &&
+
+ # Check test cases with docker-based test servers.
+ testserver_test.commands += $(MAKE) -f $(MAKEFILE) check_network &&
+
+ # Stop and remove test servers after testing.
+ !isEmpty(TEST_CMD): testserver_test.commands += $$TEST_CMD $$TEST_ENV
+ testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE down \
+ --timeout 1
+
+ # Destroy test servers and tidy away related files.
+ testserver_clean.commands = docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE down \
+ --rmi all
+
+ QMAKE_EXTRA_TARGETS += testserver_pretest testserver_test testserver_clean
+}
diff --git a/mkspecs/features/wasm/wasm.prf b/mkspecs/features/wasm/wasm.prf
index 13ac43443d..54d351bfd5 100644
--- a/mkspecs/features/wasm/wasm.prf
+++ b/mkspecs/features/wasm/wasm.prf
@@ -2,6 +2,39 @@
# DESTDIR will be empty if not set in the app .pro file; make sure it has a value
isEmpty(DESTDIR): DESTDIR = $$OUT_PWD
+exists($$QMAKE_QT_CONFIG) {
+ qtConfig(thread) {
+
+ EMCC_THREAD_LFLAGS += -s USE_PTHREADS=1
+ # Hardcode wasm memory size. Emscripten does not currently support memory growth
+ # (ALLOW_MEMORY_GROWTH) in pthreads mode, and requires specifying the memory size
+ # at build time. Further, browsers limit the maximum initial memory size to 1GB.
+ TOTAL_MEMORY = 1GB
+ !isEmpty(QMAKE_WASM_TOTAL_MEMORY) {
+ TOTAL_MEMORY = $$QMAKE_WASM_TOTAL_MEMORY
+ }
+
+ message("Setting TOTAL_MEMORY to" $$TOTAL_MEMORY)
+ EMCC_THREAD_LFLAGS += -s TOTAL_MEMORY=$$TOTAL_MEMORY
+
+ # Create worker threads at startup. This is supposed to be an optimization,
+ # however exceeding the pool size has been obesverved to hang the application.
+ POOL_SIZE = 4
+ !isEmpty(QMAKE_WASM_PTHREAD_POOL_SIZE) {
+ POOL_SIZE = $$QMAKE_WASM_PTHREAD_POOL_SIZE
+ }
+
+ message("Setting PTHREAD_POOL_SIZE to" $$POOL_SIZE)
+ EMCC_THREAD_LFLAGS += -s PTHREAD_POOL_SIZE=$$POOL_SIZE
+ } else {
+ EMCC_THREAD_LFLAGS += -s ALLOW_MEMORY_GROWTH=1
+ }
+ QMAKE_LFLAGS += $$EMCC_THREAD_LFLAGS
+ QMAKE_LFLAGS_DEBUG += $$EMCC_THREAD_LFLAGS
+ QMAKE_CFLAGS += $$EMCC_THREAD_LFLAGS
+ QMAKE_CXXFLAGS += $$EMCC_THREAD_LFLAGS
+}
+
# Create js and wasm files for applications
contains(TEMPLATE, .*app) {
TARGET_BASE = $${TARGET}
@@ -34,7 +67,7 @@ contains(TEMPLATE, .*app) {
# replacing the app name placeholder with the actual app name.
apphtml.name = application main html file
apphtml.output = $$DESTDIR/$$TARGET_HTML
- apphtml.commands = sed -e s/APPNAME/$$TARGET_BASE/g $$WASM_PLUGIN_PATH/wasm_shell.html > $$DESTDIR/$$TARGET_HTML
+ apphtml.commands = sed -e s/@APPNAME@/$$TARGET_BASE/g $$WASM_PLUGIN_PATH/wasm_shell.html > $$DESTDIR/$$TARGET_HTML
apphtml.input = $$WASM_PLUGIN_PATH/wasm_shell.html
apphtml.depends = $$apphtml.input
QMAKE_EXTRA_COMPILERS += apphtml
@@ -72,6 +105,13 @@ contains(TEMPLATE, .*app) {
}
}
+# Pass --source-map-base on the linker line. This informs the
+# browser where to find the source files when debugging.
+WASM_SOURCE_MAP_BASE = http://localhost:8000/
+!isEmpty(QMAKE_WASM_SOURCE_MAP_BASE):\
+ WASM_SOURCE_MAP_BASE = $$QMAKE_WASM_SOURCE_MAP_BASE
+CONFIG(debug): QMAKE_LFLAGS += --source-map-base $$WASM_SOURCE_MAP_BASE
+
# Creates the stand-alone version of the library from bitcode
!static:contains(TEMPLATE, .*lib): {
load(resolve_target)
diff --git a/mkspecs/features/wayland-scanner.prf b/mkspecs/features/wayland-scanner.prf
index 2360917a3b..79bf02f25b 100644
--- a/mkspecs/features/wayland-scanner.prf
+++ b/mkspecs/features/wayland-scanner.prf
@@ -22,7 +22,7 @@ wayland_server_header.name = wayland ${QMAKE_FILE_BASE}
wayland_server_header.input = WAYLANDSERVERSOURCES WAYLANDSERVERSOURCES_SYSTEM
wayland_server_header.variable_out = HEADERS
wayland_server_header.output = wayland-${QMAKE_FILE_BASE}-server-protocol$${first(QMAKE_EXT_H)}
-wayland_server_header.commands = $$QMAKE_WAYLAND_SCANNER server-header < ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
+wayland_server_header.commands = $$QMAKE_WAYLAND_SCANNER --include-core-only server-header < ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
silent:wayland_server_header.commands = @echo Wayland server header ${QMAKE_FILE_IN} && $$wayland_server_header.commands
QMAKE_EXTRA_COMPILERS += wayland_server_header
@@ -30,7 +30,7 @@ wayland_client_header.name = wayland ${QMAKE_FILE_BASE}
wayland_client_header.input = WAYLANDCLIENTSOURCES WAYLANDCLIENTSOURCES_SYSTEM
wayland_client_header.variable_out = HEADERS
wayland_client_header.output = wayland-${QMAKE_FILE_BASE}-client-protocol$${first(QMAKE_EXT_H)}
-wayland_client_header.commands = $$QMAKE_WAYLAND_SCANNER client-header < ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
+wayland_client_header.commands = $$QMAKE_WAYLAND_SCANNER --include-core-only client-header < ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
silent:wayland_client_header.commands = @echo Wayland client header ${QMAKE_FILE_IN} && $$wayland_client_header.commands
QMAKE_EXTRA_COMPILERS += wayland_client_header
@@ -38,7 +38,7 @@ wayland_code.name = wayland ${QMAKE_FILE_BASE}
wayland_code.input = WAYLANDCLIENTSOURCES WAYLANDSERVERSOURCES
wayland_code.variable_out = SOURCES
wayland_code.output = wayland-${QMAKE_FILE_BASE}-protocol.c
-wayland_code.commands = $$QMAKE_WAYLAND_SCANNER code < ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
+wayland_code.commands = $$QMAKE_WAYLAND_SCANNER --include-core-only code < ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
silent:wayland_code.commands = @echo Wayland code header ${QMAKE_FILE_IN} && $$wayland_code.commands
QMAKE_EXTRA_COMPILERS += wayland_code
diff --git a/mkspecs/features/winrt/package_manifest.prf b/mkspecs/features/winrt/package_manifest.prf
index 143b884dbf..969343cfd7 100644
--- a/mkspecs/features/winrt/package_manifest.prf
+++ b/mkspecs/features/winrt/package_manifest.prf
@@ -69,9 +69,10 @@
isEmpty(WINRT_MANIFEST.foreground): WINRT_MANIFEST.foreground = light
isEmpty(WINRT_MANIFEST.default_language): WINRT_MANIFEST.default_language = en
*-msvc2015|*-msvc2017 {
- isEmpty(WINRT_MANIFEST.minVersion): WINRT_MANIFEST.minVersion = $$(UCRTVersion)
- isEmpty(WINRT_MANIFEST.minVersion): error("No UCRTVersion found in environment."))
- isEmpty(WINRT_MANIFEST.maxVersionTested): WINRT_MANIFEST.maxVersionTested = $$WINRT_MANIFEST.minVersion
+ isEmpty(WINRT_MANIFEST.minVersion): \
+ WINRT_MANIFEST.minVersion = $$WINDOWS_TARGET_PLATFORM_VERSION
+ isEmpty(WINRT_MANIFEST.maxVersionTested): \
+ WINRT_MANIFEST.maxVersionTested = $$WINDOWS_TARGET_PLATFORM_MIN_VERSION
}
INDENT = "$$escape_expand(\\r\\n) "
diff --git a/mkspecs/features/yacc.prf b/mkspecs/features/yacc.prf
index 618f0668c2..0c7ff7321e 100644
--- a/mkspecs/features/yacc.prf
+++ b/mkspecs/features/yacc.prf
@@ -2,32 +2,49 @@
# Yacc extra-compiler for handling files specified in the YACCSOURCES variable
#
-{
- yacc_decl.name = Yacc header
- yacc_decl.input = YACCSOURCES
- yacc_decl.variable_out = GENERATED_FILES
+isEmpty(YACC_DIR): YACC_DIR = .
+defineReplace(yaccCommands) {
+ input = $$relative_path($$absolute_path($$1, $$OUT_PWD), $$OUT_PWD/$$YACC_DIR)
+ input_base = $$basename(1)
+ input_base ~= s/\.[^.]*$//
+ hpp_output = $$2
+ cpp_output = $$hpp_output
+ cpp_output ~= s/$$re_escape($$first(QMAKE_EXT_H))$/$$first(QMAKE_EXT_CPP)/
isEmpty(QMAKE_YACCFLAGS_MANGLE) {
- QMAKE_YACCFLAGS_MANGLE = -p ${QMAKE_FILE_BASE} -b ${QMAKE_FILE_BASE}
- QMAKE_YACC_HEADER = ${QMAKE_FILE_BASE}.tab.h
- QMAKE_YACC_SOURCE = ${QMAKE_FILE_BASE}.tab.c
+ QMAKE_YACCFLAGS_MANGLE = -p $${input_base} -b $${input_base}
+ QMAKE_YACC_HEADER = $${input_base}.tab.h
+ QMAKE_YACC_SOURCE = $${input_base}.tab.c
} else {
- QMAKE_YACCFLAGS_MANGLE ~= s/\\$base/${QMAKE_FILE_BASE}/g #backwards compat
- QMAKE_YACC_HEADER ~= s/\\$base/${QMAKE_FILE_BASE}/g
- QMAKE_YACC_SOURCE ~= s/\\$base/${QMAKE_FILE_BASE}/g
+ QMAKE_YACCFLAGS_MANGLE ~= s/\\$base/$${input_base}/g #backwards compat
+ QMAKE_YACC_HEADER ~= s/\\$base/$${input_base}/g
+ QMAKE_YACC_SOURCE ~= s/\\$base/$${input_base}/g
}
QMAKE_YACCDECLFLAGS = $$QMAKE_YACCFLAGS
- !yacc_no_name_mangle:QMAKE_YACCDECLFLAGS += $$QMAKE_YACCFLAGS_MANGLE
+ !yacc_no_name_mangle: QMAKE_YACCDECLFLAGS += $$QMAKE_YACCFLAGS_MANGLE
- yacc_decl.commands = \
- -$(DEL_FILE) $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_H)} $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_CPP)}$$escape_expand(\\n\\t) \
- $$QMAKE_YACC $$QMAKE_YACCDECLFLAGS ${QMAKE_FILE_IN}$$escape_expand(\\n\\t) \
- $(MOVE) $${QMAKE_YACC_HEADER} $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_H)}$$escape_expand(\\n\\t) \
- $(MOVE) $${QMAKE_YACC_SOURCE} $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_CPP)}$$escape_expand(\\n\\t)
- yacc_decl.output = $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_H)}
+ !equals(YACC_DIR, .): yacc_call = cd $$YACC_DIR &&
+ yacc_call += $$QMAKE_YACC $$QMAKE_YACCDECLFLAGS $${input}
+
+ commands = \
+ -$(DEL_FILE) $${hpp_output} $${cpp_output}$$escape_expand(\\n\\t) \
+ $${yacc_call}$$escape_expand(\\n\\t) \
+ $(MOVE) $${YACC_DIR}/$${QMAKE_YACC_HEADER} $${hpp_output}$$escape_expand(\\n\\t) \
+ $(MOVE) $${YACC_DIR}/$${QMAKE_YACC_SOURCE} $${cpp_output}$$escape_expand(\\n\\t)
+
+ silent: commands = @echo Yacc $$1 && $$commands
+ return($$commands)
+}
- silent:yacc_decl.commands = @echo Yacc ${QMAKE_FILE_IN} && $$yacc_decl.commands
+yacc_output_base = $${YACC_DIR}/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}
+
+{
+ yacc_decl.name = Yacc header
+ yacc_decl.input = YACCSOURCES
+ yacc_decl.variable_out = GENERATED_FILES
+ yacc_decl.commands = ${QMAKE_FUNC_yaccCommands}
+ yacc_decl.output = $${yacc_output_base}$$first(QMAKE_EXT_H)
QMAKE_EXTRA_COMPILERS += yacc_decl
}
@@ -37,7 +54,9 @@
yacc_impl.variable_out = GENERATED_SOURCES
yacc_impl.dependency_type = TYPE_C
yacc_impl.commands = $$escape_expand(\\n) # We don't want any commands where, but if command is empty no rules are created
- yacc_impl.depends += $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_H)} # Make sure we depend on the step above
- yacc_impl.output = $${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_MOD_YACC}$${first(QMAKE_EXT_CPP)} # Faked output from this step, output really created in step above
+ yacc_impl.depends += $${yacc_output_base}$$first(QMAKE_EXT_H) # Make sure we depend on the step above
+ yacc_impl.output = $${yacc_output_base}$$first(QMAKE_EXT_CPP) # Faked output from this step, output really created in step above
QMAKE_EXTRA_COMPILERS += yacc_impl
}
+
+unset(yacc_output_base)
diff --git a/mkspecs/linux-clang-32/qmake.conf b/mkspecs/linux-clang-32/qmake.conf
new file mode 100644
index 0000000000..de872e7431
--- /dev/null
+++ b/mkspecs/linux-clang-32/qmake.conf
@@ -0,0 +1,20 @@
+#
+# qmake configuration for linux-clang
+#
+
+MAKEFILE_GENERATOR = UNIX
+CONFIG += incremental
+
+QMAKE_INCREMENTAL_STYLE = sublib
+
+include(../common/linux.conf)
+
+QMAKE_CFLAGS = -m32
+QMAKE_LFLAGS = -m32
+
+include(../common/gcc-base-unix.conf)
+include(../common/clang.conf)
+
+QMAKE_LFLAGS += -ccc-gcc-name g++
+
+load(qt_config)
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_dummy.cpp b/mkspecs/linux-clang-32/qplatformdefs.h
index 78b289ea49..8f5ce17858 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration_dummy.cpp
+++ b/mkspecs/linux-clang-32/qplatformdefs.h
@@ -3,7 +3,7 @@
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the qmake spec of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,9 +37,4 @@
**
****************************************************************************/
-#include "qoffscreenintegration.h"
-
-QOffscreenIntegration *QOffscreenIntegration::createOffscreenIntegration()
-{
- return new QOffscreenIntegration;
-}
+#include "../linux-clang/qplatformdefs.h"
diff --git a/mkspecs/linux-clang-libc++-32/qmake.conf b/mkspecs/linux-clang-libc++-32/qmake.conf
new file mode 100644
index 0000000000..f4c006d383
--- /dev/null
+++ b/mkspecs/linux-clang-libc++-32/qmake.conf
@@ -0,0 +1,10 @@
+#
+# qmake configuration for linux-clang and libc++
+#
+
+include(../linux-clang-32/qmake.conf)
+
+QMAKE_CXXFLAGS += -stdlib=libc++
+QMAKE_LFLAGS += -stdlib=libc++
+
+load(qt_config)
diff --git a/src/plugins/platforms/mirclient/qmirclientdesktopwindow.h b/mkspecs/linux-clang-libc++-32/qplatformdefs.h
index 3ba54db826..8f5ce17858 100644
--- a/src/plugins/platforms/mirclient/qmirclientdesktopwindow.h
+++ b/mkspecs/linux-clang-libc++-32/qplatformdefs.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the qmake spec of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,17 +37,4 @@
**
****************************************************************************/
-
-#ifndef QMIRCLIENTDESKTOPWINDOW_H
-#define QMIRCLIENTDESKTOPWINDOW_H
-
-#include <qpa/qplatformwindow.h>
-
-// TODO Implement it. For now it's just an empty, dummy class.
-class QMirClientDesktopWindow : public QPlatformWindow
-{
-public:
- QMirClientDesktopWindow(QWindow*);
-};
-
-#endif // QMIRCLIENTDESKTOPWINDOW_H
+#include "../linux-clang/qplatformdefs.h"
diff --git a/mkspecs/wasm-emscripten/qmake.conf b/mkspecs/wasm-emscripten/qmake.conf
index e7b45d312d..c6c3af3622 100644
--- a/mkspecs/wasm-emscripten/qmake.conf
+++ b/mkspecs/wasm-emscripten/qmake.conf
@@ -5,6 +5,17 @@ QMAKE_PLATFORM = wasm unix
include(../common/gcc-base.conf)
include(../common/clang.conf)
+load(device_config)
+
+# Support setting WASM_OBJECT_FILES with -device-option WASM_OBJECT_FILES=1
+!isEmpty(WASM_OBJECT_FILES): {
+ !equals(WASM_OBJECT_FILES, 1):!equals(WASM_OBJECT_FILES, 0): \
+ message(Error: The value for WASM_OBJECT_FILES must be 0 or 1)
+ QMAKE_CFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES
+ QMAKE_CXXFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES
+ QMAKE_LFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES
+}
+
EMTERP_FLAGS = \
-s EMTERPRETIFY=1 \
-s EMTERPRETIFY_ASYNC=1 \
@@ -15,7 +26,6 @@ EMTERP_FLAGS = \
EMCC_COMMON_LFLAGS = \
-s WASM=1 \
-s FULL_ES2=1 \
- -s ALLOW_MEMORY_GROWTH=1 \
-s USE_WEBGL2=1 \
-s NO_EXIT_RUNTIME=0 \
-s ERROR_ON_UNDEFINED_SYMBOLS=1 \
@@ -34,28 +44,40 @@ EMCC_COMMON_LFLAGS_DEBUG = \
# -s SOCKET_DEBUG \ #print out socket,network data transfer
-s GL_DEBUG=1
+# Set up debug/optimization flags
+QMAKE_CXXFLAGS_RELEASE -= -O2
+QMAKE_CFLAGS_RELEASE -= -O2
+equals(WASM_OBJECT_FILES, 1) {
+ QMAKE_LFLAGS_DEBUG += -g
+
+ QMAKE_CXXFLAGS_RELEASE += -O3
+ QMAKE_CFLAGS_RELEASE += -O3
+ QMAKE_LFLAGS_RELEASE += -O3
+ QMAKE_CFLAGS_OPTIMIZE += -O3
+ QMAKE_CFLAGS_OPTIMIZE_FULL += -Oz
+} else {
+ # Practical debugging setup:
+ # "-g4" preserves function names for stack traces
+ # "-Os" produces reasonably sized binaries
+ QMAKE_CFLAGS_DEBUG -= -g
+ QMAKE_CXXFLAGS_DEBUG -= -g
+ QMAKE_CFLAGS_DEBUG += -Os -g4
+ QMAKE_CXXFLAGS_DEBUG += -Os -g4
+ QMAKE_LFLAGS_DEBUG += -Os -g4
+
+ QMAKE_CXXFLAGS_RELEASE += -O3
+ QMAKE_CFLAGS_RELEASE += -O3
+ QMAKE_LFLAGS_RELEASE += -O3
+ QMAKE_CFLAGS_OPTIMIZE += -O3
+ QMAKE_CFLAGS_OPTIMIZE_FULL += -Oz
+}
+
+
QMAKE_COMPILER += emscripten
QMAKE_CC = emcc
QMAKE_CXX = em++
-# Practical debugging setup:
-# "-g4" preserves function names for stack traces
-# "-Os" produces reasonably sized binaries
-QMAKE_CFLAGS_DEBUG -= -g
-QMAKE_CXXFLAGS_DEBUG -= -g
-QMAKE_CFLAGS_DEBUG += -Os -g4
-QMAKE_CXXFLAGS_DEBUG += -Os -g4
-QMAKE_LFLAGS_DEBUG += -Os -g4
-
-QMAKE_CXXFLAGS_RELEASE -= -O2
-QMAKE_CXXFLAGS_RELEASE += -O3
-QMAKE_CFLAGS_RELEASE -= -O2
-QMAKE_CFLAGS_RELEASE += -O3
-QMAKE_LFLAGS_RELEASE += -O3
-QMAKE_CFLAGS_OPTIMIZE += -O3
-QMAKE_CFLAGS_OPTIMIZE_FULL += -Oz
-
QMAKE_LINK = $$QMAKE_CXX
QMAKE_LINK_SHLIB = $$QMAKE_CXX
QMAKE_LINK_C = $$QMAKE_CC
@@ -72,6 +94,12 @@ QMAKE_PREFIX_STATICLIB = lib
QMAKE_EXTENSION_STATICLIB = a # llvm bitcode
QMAKE_AR = emar cqs
+equals(QMAKE_HOST.os, Windows) {
+ QMAKE_AR_CMD = \
+ "$(file >$(OBJECTS_DIR)/$(TARGET).rsp, $(subst \\,/,$(OBJECTS)))$$escape_expand(\\n\\t)" \
+ "$(AR) $(DESTDIR)$(TARGET) @$(OBJECTS_DIR)/$(TARGET).rsp"
+}
+
QMAKE_DISTCLEAN += *.html *.js *.wasm
load(qt_config)
diff --git a/mkspecs/win32-clang-g++/qmake.conf b/mkspecs/win32-clang-g++/qmake.conf
index 4630ec4602..59d42176f0 100644
--- a/mkspecs/win32-clang-g++/qmake.conf
+++ b/mkspecs/win32-clang-g++/qmake.conf
@@ -24,4 +24,12 @@ QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
QMAKE_LINK = $${CROSS_COMPILE}clang++
QMAKE_LINK_C = $${CROSS_COMPILE}clang
+QMAKE_CFLAGS_LTCG = -flto=thin
+QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
+QMAKE_CFLAGS_LTCG_FATOBJECTS = -flto
+QMAKE_CXXFLAGS_LTCG_FATOBJECTS = $$QMAKE_CFLAGS_LTCG_FATOBJECTS
+QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
+
+QMAKE_CFLAGS_OPTIMIZE_SIZE = -Oz
+
load(qt_config)
diff --git a/mkspecs/win32-clang-msvc/qmake.conf b/mkspecs/win32-clang-msvc/qmake.conf
index 4b9cac3e22..5da7e2d1b2 100644
--- a/mkspecs/win32-clang-msvc/qmake.conf
+++ b/mkspecs/win32-clang-msvc/qmake.conf
@@ -39,12 +39,16 @@ QMAKE_CXXFLAGS += -Wno-microsoft-enum-value
QMAKE_LINK = lld-link
QMAKE_LIB = llvm-lib /NOLOGO
-QMAKE_CFLAGS_LTCG = -flto
+QMAKE_CFLAGS_LTCG = -flto=thin
QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
+QMAKE_CFLAGS_LTCG_FATOBJECTS = -flto
+QMAKE_CXXFLAGS_LTCG_FATOBJECTS = $$QMAKE_CFLAGS_LTCG_FATOBJECTS
# Leave QMAKE_LFLAGS_LTCG empty because lld-link doesn't need any additional parameters
QMAKE_LFLAGS_LTCG =
-# Precompiled headers are not supported yet by clang
-CONFIG -= precompile_header
+QMAKE_CFLAGS_OPTIMIZE_SIZE = /clang:-Oz
+QMAKE_CFLAGS_OPTIMIZE_FULL = /clang:-O3
+
+QMAKE_LFLAGS_RELEASE += /OPT:REF,ICF,LBR
load(qt_config)
diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf
index 5e9923357f..5de482f23b 100644
--- a/mkspecs/win32-g++/qmake.conf
+++ b/mkspecs/win32-g++/qmake.conf
@@ -8,6 +8,7 @@
#
include(../common/g++-win32.conf)
+include(../common/windows-desktop.conf)
# modifications to g++-win32.conf
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix
index 0f69b6b487..069cb0f12d 100644
--- a/qmake/Makefile.unix
+++ b/qmake/Makefile.unix
@@ -28,9 +28,9 @@ QOBJS = \
qmetatype.o qsystemerror.o qvariant.o \
quuid.o \
qarraydata.o qbitarray.o qbytearray.o qbytearraymatcher.o \
- qcryptographichash.o qdatetime.o qhash.o qlinkedlist.o qlist.o \
+ qcryptographichash.o qdatetime.o qhash.o qlist.o \
qlocale.o qlocale_tools.o qmap.o qregexp.o qringbuffer.o \
- qstringbuilder.o qstring_compat.o qstring.o qstringlist.o qversionnumber.o \
+ qstringbuilder.o qstring.o qstringlist.o qversionnumber.o \
qvsnprintf.o qxmlstream.o qxmlutils.o \
$(QTOBJS) $(QTOBJS2)
# QTOBJS and QTOBJS2 are populated by Makefile.unix.* as for QTSRC (see below).
@@ -105,14 +105,13 @@ DEPEND_SRC = \
$(SOURCE_PATH)/src/corelib/serialization/qtextstream.cpp \
$(SOURCE_PATH)/src/corelib/serialization/qxmlstream.cpp \
$(SOURCE_PATH)/src/corelib/serialization/qxmlutils.cpp \
+ $(SOURCE_PATH)/src/corelib/time/qdatetime.cpp \
$(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp \
$(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp \
$(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\
$(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \
$(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp \
$(SOURCE_PATH)/src/corelib/tools/qhash.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlist.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlocale.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp \
@@ -120,7 +119,6 @@ DEPEND_SRC = \
$(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \
$(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \
$(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \
$(SOURCE_PATH)/src/corelib/tools/qstring.cpp \
$(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp \
$(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp \
@@ -343,9 +341,6 @@ qutfcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp
qstring.o: $(SOURCE_PATH)/src/corelib/tools/qstring.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
-qstring_compat.o: $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $<
-
qstringbuilder.o: $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
@@ -430,7 +425,7 @@ quuid.o: $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp
qfileinfo.o: $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
-qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp
+qdatetime.o: $(SOURCE_PATH)/src/corelib/time/qdatetime.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp
@@ -442,9 +437,6 @@ qmap.o: $(SOURCE_PATH)/src/corelib/tools/qmap.cpp
qhash.o: $(SOURCE_PATH)/src/corelib/tools/qhash.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
-qlinkedlist.o: $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $<
-
qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32
index 506e9deb19..d300e49215 100644
--- a/qmake/Makefile.win32
+++ b/qmake/Makefile.win32
@@ -24,10 +24,8 @@ LINKER = link
CFLAGS_EXTRA = /MP /wd4577 $(CFLAGS_CRT)
!endif # !win32-icc
-!if "$(QMAKESPEC)" != "win32-clang-msvc"
CFLAGS_PCH = -Yuqmake_pch.h -FIqmake_pch.h -Fpqmake_pch.pch
PCH_OBJECT = qmake_pch.obj
-!endif
CFLAGS_BARE = -c -Fo./ -Fdqmake.pdb \
-W2 -nologo -O2 \
@@ -90,7 +88,6 @@ QTOBJS= \
qringbuffer.obj \
qdebug.obj \
qlist.obj \
- qlinkedlist.obj \
qlocale.obj \
qlocale_tools.obj \
qlocale_win.obj \
@@ -102,7 +99,6 @@ QTOBJS= \
qregexp.obj \
qutfcodec.obj \
qstring.obj \
- qstring_compat.obj \
qstringlist.obj \
qstringbuilder.obj \
qsystemerror.obj \
@@ -200,13 +196,13 @@ qmake_pch.obj:
{$(SOURCE_PATH)\src\corelib\serialization}.cpp{}.obj::
$(CXX) $(CXXFLAGS) $<
-{$(SOURCE_PATH)\src\corelib\tools}.cpp{}.obj::
+{$(SOURCE_PATH)\src\corelib\time}.cpp{}.obj::
$(CXX) $(CXXFLAGS) $<
-# Make sure qstring_compat.obj and qlibraryinfo.obj aren't compiled with PCH enabled
-qstring_compat.obj: $(SOURCE_PATH)\src\corelib\tools\qstring_compat.cpp
- $(CXX) -c $(CXXFLAGS_BARE) $(SOURCE_PATH)\src\corelib\tools\qstring_compat.cpp
+{$(SOURCE_PATH)\src\corelib\tools}.cpp{}.obj::
+ $(CXX) $(CXXFLAGS) $<
+# Make sure qlibraryinfo.obj isn't compiled with PCH enabled
qlibraryinfo.obj: $(SOURCE_PATH)\src\corelib\global\qlibraryinfo.cpp
$(CXX) $(CXXFLAGS_BARE) -DQT_BUILD_QMAKE_BOOTSTRAP $(SOURCE_PATH)\src\corelib\global\qlibraryinfo.cpp
diff --git a/qmake/doc/qmake.qdocconf b/qmake/doc/qmake.qdocconf
index 3493a697f4..cf8f911372 100644
--- a/qmake/doc/qmake.qdocconf
+++ b/qmake/doc/qmake.qdocconf
@@ -25,6 +25,8 @@ sources = src/qmake-manual.qdoc
imagedirs = images
exampledirs = snippets
+tagfile = qmake.tags
+
depends += \
activeqt \
qt3d \
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index d3148a1e62..b271abcee3 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -974,6 +974,12 @@
the compiler does not support C++17, or can't select the C++ standard.
By default, support is disabled.
\row \li c++17 \li Same as c++1z.
+ \row \li c++2a \li C++2a support is enabled. This option has no effect if
+ the compiler does not support C++2a, or can't select the C++ standard.
+ By default, support is disabled.
+ \row \li c++latest \li Support for the latest C++ language standard is
+ enabled that is supported by the compiler. By default, this option is
+ disabled.
\row \li strict_c++ \li Disables support for C++ compiler extensions.
By default, they are enabled.
\row \li depend_includepath \li Appending the value of INCLUDEPATH to
@@ -1148,8 +1154,9 @@
\target DEPENDPATH
\section1 DEPENDPATH
- Specifies a list of all directories to look in to resolve dependencies. This
- variable is used when crawling through \c included files.
+ Specifies a list of directories for qmake to scan, to resolve dependencies.
+ This variable is used when qmake crawls through the header files that you
+ \c{#include} in your source code.
\target DESTDIR
\section1 DESTDIR
@@ -1277,6 +1284,41 @@
\snippet code/doc_src_qmake-manual.pro 36
+ \c INSTALLS has a \c{.CONFIG} member that can take several values:
+
+ \table
+ \header
+ \li Value
+ \li Description
+ \row
+ \li no_check_exists
+ \li If not set, qmake looks to see if the files to install actually
+ exist. If these files don't exist, qmake doesn’t create the
+ install rule. Use this config value if you need to install
+ files that are generated as part of your build process, like
+ HTML files created by qdoc.
+ \row
+ \li nostrip
+ \li If set, the typical Unix strip functionality is turned off and
+ the debug information will remain in the binary.
+ \row
+ \li executable
+ \li On Unix, this sets the executable flag.
+ \row
+ \li no_build
+ \li When you do a \c{make install}, and you don't have a build of
+ the project yet, the project is first built, and then installed.
+ If you don't want this behavior, set this config value to ensure
+ that the build target is not added as a dependency to the install
+ target.
+ \row
+ \li no_default_install
+ \li A project has a top-level project target where, when you do a
+ \c{make install}, everything is installed. But, if you have an
+ install target with this config value set, it's not installed by
+ default. You then have to explicitly say \c{make install_<file>}.
+ \endtable
+
For more information, see \l{Installing Files}.
This variable is also used to specify which additional files will be
@@ -2820,6 +2862,26 @@
See also \l{#DEPENDPATH}{DEPENDPATH}.
+ \target WINDOWS_TARGET_PLATFORM_VERSION
+ \section1 WINDOWS_TARGET_PLATFORM_VERSION
+
+ Specifies the targeted Windows version; this corresponds to the tag
+ \c{WindowsTargetPlatformVersion} in vcxproj files.
+
+ On desktop Windows, the default value is the value of the environment
+ variable \c{WindowsSDKVersion}.
+
+ On WinRT, the default value is the value of the environment variable
+ \c{UCRTVERSION}.
+
+ \target WINDOWS_TARGET_PLATFORM_MIN_VERSION
+ \section1 WINDOWS_TARGET_PLATFORM_MIN_VERSION
+
+ Specifies the minimum version of the Windows target platform; this
+ corresponds to the tag \c{WindowsTargetPlatformMinVersion} in vcxproj files.
+
+ Defaults to \c{WINDOWS_TARGET_PLATFORM_VERSION}.
+
\target WINRT_MANIFEST
\section1 WINRT_MANIFEST
@@ -2953,10 +3015,12 @@
\li The version number of the package. Defaults to \c{1.0.0.0}.
\row
\li minVersion
- \li The minimum required Windows version to run the package. Defaults to the environment variable \c UCRTVersion.
+ \li The minimum required Windows version to run the package.
+ Defaults to \c{WINDOWS_TARGET_PLATFORM_VERSION}.
\row
\li maxVersionTested
- \li The maximum Windows version the package has been tested against. Defaults to \c WINRT_MANIFEST.minVersion
+ \li The maximum Windows version the package has been tested against.
+ Defaults to \c{WINDOWS_TARGET_PLATFORM_MIN_VERSION}.
\endtable
@@ -4514,7 +4578,10 @@
\c QMAKEFEATURES environment variable)
\li \c $$QMAKEFEATURES/myfeatures.prf (for each directory listed in the
\c QMAKEFEATURES property variable)
- \li \c myfeatures.prf (in the project's root directory)
+ \li \c myfeatures.prf (in the project's root directory). The project root
+ is determined by the top-level \c{.pro} file. However, if you place the
+ \c{.qmake.cache} file in a sub-directory or the directory of a
+ sub-project, then the project root becomes the sub-directory itself.
\li \c $QMAKEPATH/mkspecs/features/unix/myfeatures.prf and
\c $QMAKEPATH/mkspecs/features/myfeatures.prf (for each directory
listed in the \c QMAKEPATH environment variable)
@@ -4819,6 +4886,7 @@
\li Unix
\list
\li GCC 3.4 and above
+ \li clang
\endlist
\endlist
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index d5994639b3..28cf02344d 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -60,11 +60,6 @@ static QString qtSha1(const QByteArray &src)
return QString::fromLatin1(digest.toHex());
}
-ProjectBuilderMakefileGenerator::ProjectBuilderMakefileGenerator() : UnixMakefileGenerator()
-{
-
-}
-
bool
ProjectBuilderMakefileGenerator::writeMakefile(QTextStream &t)
{
@@ -540,7 +535,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData());
QTextStream mkt(&mkf);
writeHeader(mkt);
- mkt << "QMAKE = " << var("QMAKE_QMAKE") << endl;
+ mkt << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl;
project->values("QMAKE_MAKE_QMAKE_EXTRA_COMMANDS")
<< "@echo 'warning: Xcode project has been regenerated, custom settings have been lost. " \
"Use CONFIG+=no_autoqmake to prevent this behavior in the future, " \
@@ -738,15 +733,15 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData());
QTextStream mkt(&mkf);
writeHeader(mkt);
- mkt << "MOC = " << var("QMAKE_MOC") << endl;
- mkt << "UIC = " << var("QMAKE_UIC") << endl;
- mkt << "LEX = " << var("QMAKE_LEX") << endl;
- mkt << "LEXFLAGS = " << var("QMAKE_LEXFLAGS") << endl;
- mkt << "YACC = " << var("QMAKE_YACC") << endl;
- mkt << "YACCFLAGS = " << var("QMAKE_YACCFLAGS") << endl;
+ mkt << "MOC = " << var("QMAKE_MOC") << Qt::endl;
+ mkt << "UIC = " << var("QMAKE_UIC") << Qt::endl;
+ mkt << "LEX = " << var("QMAKE_LEX") << Qt::endl;
+ mkt << "LEXFLAGS = " << var("QMAKE_LEXFLAGS") << Qt::endl;
+ mkt << "YACC = " << var("QMAKE_YACC") << Qt::endl;
+ mkt << "YACCFLAGS = " << var("QMAKE_YACCFLAGS") << Qt::endl;
mkt << "DEFINES = "
<< varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
- << varGlue("DEFINES","-D"," -D","") << endl;
+ << varGlue("DEFINES","-D"," -D","") << Qt::endl;
mkt << "INCPATH =";
{
const ProStringList &incs = project->values("INCLUDEPATH");
@@ -755,9 +750,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
}
if(!project->isEmpty("QMAKE_FRAMEWORKPATH_FLAGS"))
mkt << " " << var("QMAKE_FRAMEWORKPATH_FLAGS");
- mkt << endl;
- mkt << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
- mkt << "MOVE = " << var("QMAKE_MOVE") << endl << endl;
+ mkt << Qt::endl;
+ mkt << "DEL_FILE = " << var("QMAKE_DEL_FILE") << Qt::endl;
+ mkt << "MOVE = " << var("QMAKE_MOVE") << Qt::endl << Qt::endl;
mkt << "preprocess: compilers\n";
mkt << "clean preprocess_clean: compiler_clean\n\n";
writeExtraTargets(mkt);
@@ -787,7 +782,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
}
}
}
- mkt << endl;
+ mkt << Qt::endl;
writeExtraCompilerTargets(mkt);
writingUnixMakefileGenerator = false;
}
@@ -992,12 +987,12 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
tmp = project->values("SUBLIBS");
for(int i = 0; i < tmp.count(); i++)
t << escapeFilePath("tmp/lib" + tmp[i] + ".a") << ' ';
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
mkt << "sublibs: $(SUBLIBS)\n\n";
tmp = project->values("SUBLIBS");
for(int i = 0; i < tmp.count(); i++)
t << escapeFilePath("tmp/lib" + tmp[i] + ".a") + ":\n\t"
- << var(ProKey("MAKELIB" + tmp[i])) << endl << endl;
+ << var(ProKey("MAKELIB" + tmp[i])) << Qt::endl << Qt::endl;
mkt.flush();
mkf.close();
writingUnixMakefileGenerator = false;
@@ -1234,9 +1229,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n"
<< "\t\t};\n";
- QMapIterator<ProString, ProStringList> it(embedded_plugins);
- while (it.hasNext()) {
- it.next();
+ for (auto it = embedded_plugins.cbegin(), end = embedded_plugins.cend(); it != end; ++it) {
QString suffix = !it.key().isEmpty() ? (" (" + it.key() + ")") : QString();
QString grp3("Embed PlugIns" + suffix), key3 = keyFor(grp3);
project->values("QMAKE_PBX_BUILDPHASES").append(key3);
@@ -1472,7 +1465,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("name", "Qt Test") << ";\n"
<< "\t\t};\n";
- QLatin1Literal testTargetID("TestTargetID");
+ QLatin1String testTargetID("TestTargetID");
project->values(ProKey("QMAKE_PBX_TARGET_ATTRIBUTES_" + testTargetKey + "_" + testTargetID)).append(keyFor(pbx_dir + "QMAKE_PBX_TARGET"));
project->values(ProKey("QMAKE_PBX_TARGET_ATTRIBUTES_" + testTargetKey)).append(ProKey(testTargetID));
}
diff --git a/qmake/generators/mac/pbuilder_pbx.h b/qmake/generators/mac/pbuilder_pbx.h
index f15c814cb4..ac0d63606d 100644
--- a/qmake/generators/mac/pbuilder_pbx.h
+++ b/qmake/generators/mac/pbuilder_pbx.h
@@ -61,19 +61,12 @@ class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator
QString writeSettings(const QString &var, const ProStringList &vals, int flags=0, int indent_level=0);
public:
- ProjectBuilderMakefileGenerator();
- ~ProjectBuilderMakefileGenerator();
-
bool supportsMetaBuild() override { return false; }
bool openOutput(QFile &, const QString &) const override;
protected:
bool doPrecompiledHeaders() const override { return false; }
bool doDepends() const override { return writingUnixMakefileGenerator && UnixMakefileGenerator::doDepends(); }
};
-
-inline ProjectBuilderMakefileGenerator::~ProjectBuilderMakefileGenerator()
-{ }
-
QT_END_NAMESPACE
#endif // PBUILDER_PBX_H
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index bc59eaaea2..aa1b50f2ef 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -94,13 +94,6 @@ bool MakefileGenerator::mkdir(const QString &in_path) const
return QDir().mkpath(path);
}
-// ** base makefile generator
-MakefileGenerator::MakefileGenerator() :
- no_io(false), project(nullptr)
-{
-}
-
-
void
MakefileGenerator::verifyCompilers()
{
@@ -206,7 +199,6 @@ MakefileGenerator::initOutPaths()
ProStringList &inputs = project->values((*it2).toKey());
for (ProStringList::Iterator input = inputs.begin(); input != inputs.end(); ++input) {
QString finp = fileFixify((*input).toQString(), FileFixifyFromOutdir);
- *input = ProString(finp);
QString path = replaceExtraCompilerVariables(tmp_out, finp, QString(), NoShell);
path = Option::normalizePath(path);
int slash = path.lastIndexOf('/');
@@ -627,7 +619,7 @@ MakefileGenerator::init()
compiler.flags |= Compiler::CompilerNoCheckDeps;
compilers.append(compiler);
}
- for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
+ for (ProStringList::ConstIterator it = quc.cbegin(); it != quc.cend(); ++it) {
const ProStringList &inputs = v[ProKey(*it + ".input")];
for(x = 0; x < inputs.size(); ++x) {
Compiler compiler;
@@ -994,25 +986,25 @@ MakefileGenerator::writePrlFile(QTextStream &t)
QString bdir = Option::output_dir;
if(bdir.isEmpty())
bdir = qmake_getpwd();
- t << "QMAKE_PRL_BUILD_DIR =" << qv(bdir) << endl;
+ t << "QMAKE_PRL_BUILD_DIR =" << qv(bdir) << Qt::endl;
- t << "QMAKE_PRO_INPUT =" << qv(project->projectFile().section('/', -1)) << endl;
+ t << "QMAKE_PRO_INPUT =" << qv(project->projectFile().section('/', -1)) << Qt::endl;
if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
- t << "QMAKE_PRL_SOURCE_DIR =" << qv(project->first("QMAKE_ABSOLUTE_SOURCE_PATH")) << endl;
- t << "QMAKE_PRL_TARGET =" << qv(project->first("LIB_TARGET")) << endl;
+ t << "QMAKE_PRL_SOURCE_DIR =" << qv(project->first("QMAKE_ABSOLUTE_SOURCE_PATH")) << Qt::endl;
+ t << "QMAKE_PRL_TARGET =" << qv(project->first("LIB_TARGET")) << Qt::endl;
if(!project->isEmpty("PRL_EXPORT_DEFINES"))
- t << "QMAKE_PRL_DEFINES =" << qv(project->values("PRL_EXPORT_DEFINES")) << endl;
+ t << "QMAKE_PRL_DEFINES =" << qv(project->values("PRL_EXPORT_DEFINES")) << Qt::endl;
if(!project->isEmpty("PRL_EXPORT_CFLAGS"))
- t << "QMAKE_PRL_CFLAGS =" << qv(project->values("PRL_EXPORT_CFLAGS")) << endl;
+ t << "QMAKE_PRL_CFLAGS =" << qv(project->values("PRL_EXPORT_CFLAGS")) << Qt::endl;
if(!project->isEmpty("PRL_EXPORT_CXXFLAGS"))
- t << "QMAKE_PRL_CXXFLAGS =" << qv(project->values("PRL_EXPORT_CXXFLAGS")) << endl;
+ t << "QMAKE_PRL_CXXFLAGS =" << qv(project->values("PRL_EXPORT_CXXFLAGS")) << Qt::endl;
if(!project->isEmpty("CONFIG"))
- t << "QMAKE_PRL_CONFIG =" << qv(project->values("CONFIG")) << endl;
+ t << "QMAKE_PRL_CONFIG =" << qv(project->values("CONFIG")) << Qt::endl;
if(!project->isEmpty("TARGET_VERSION_EXT"))
- t << "QMAKE_PRL_VERSION = " << project->first("TARGET_VERSION_EXT") << endl;
+ t << "QMAKE_PRL_VERSION = " << project->first("TARGET_VERSION_EXT") << Qt::endl;
else if(!project->isEmpty("VERSION"))
- t << "QMAKE_PRL_VERSION = " << project->first("VERSION") << endl;
+ t << "QMAKE_PRL_VERSION = " << project->first("VERSION") << Qt::endl;
if(project->isActiveConfig("staticlib") || project->isActiveConfig("explicitlib")) {
ProStringList libs;
if (!project->isActiveConfig("staticlib"))
@@ -1022,7 +1014,7 @@ MakefileGenerator::writePrlFile(QTextStream &t)
t << "QMAKE_PRL_LIBS =";
for (ProStringList::Iterator it = libs.begin(); it != libs.end(); ++it)
t << qv(project->values((*it).toKey()));
- t << endl;
+ t << Qt::endl;
}
}
@@ -1053,17 +1045,17 @@ MakefileGenerator::writeProjectMakefile()
//install
t << "install: ";
- for(it = targets.begin(); it != targets.end(); ++it)
- t << (*it)->target << "-install ";
- t << endl;
+ for (SubTarget *s : qAsConst(targets))
+ t << s->target << '-';
+ t << "install " << Qt::endl;
//uninstall
t << "uninstall: ";
for(it = targets.begin(); it != targets.end(); ++it)
t << (*it)->target << "-uninstall ";
- t << endl;
+ t << Qt::endl;
} else {
- t << "first: " << targets.first()->target << endl
+ t << "first: " << targets.first()->target << Qt::endl
<< "install: " << targets.first()->target << "-install\n"
<< "uninstall: " << targets.first()->target << "-uninstall\n";
}
@@ -1072,7 +1064,7 @@ MakefileGenerator::writeProjectMakefile()
if(!project->isActiveConfig("no_autoqmake")) {
QString mkf = escapeDependencyPath(fileFixify(Option::output.fileName()));
for(QList<SubTarget*>::Iterator it = targets.begin(); it != targets.end(); ++it)
- t << escapeDependencyPath((*it)->makefile) << ": " << mkf << endl;
+ t << escapeDependencyPath((*it)->makefile) << ": " << mkf << Qt::endl;
}
qDeleteAll(targets);
return true;
@@ -1187,7 +1179,7 @@ MakefileGenerator::writeObj(QTextStream &t, const char *src)
p.replace(stringObj, escapeFilePath(dstf));
t << "\n\t" << p;
}
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
}
}
@@ -1302,9 +1294,9 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild)
dst_file += fi.fileName();
QString cmd;
if (is_target || (!fi.isDir() && fi.isExecutable()))
- cmd = QLatin1String("-$(QINSTALL_PROGRAM)");
+ cmd = QLatin1String("$(QINSTALL_PROGRAM)");
else
- cmd = QLatin1String("-$(QINSTALL)");
+ cmd = QLatin1String("$(QINSTALL)");
cmd += " " + escapeFilePath(wild) + " " + escapeFilePath(dst_file);
inst << cmd;
if (!noStrip && !project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip") &&
@@ -1324,9 +1316,9 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild)
dst_file += filestr;
QString cmd;
if (installConfigValues.contains("executable"))
- cmd = QLatin1String("-$(QINSTALL_PROGRAM)");
+ cmd = QLatin1String("$(QINSTALL_PROGRAM)");
else
- cmd = QLatin1String("-$(QINSTALL)");
+ cmd = QLatin1String("$(QINSTALL)");
cmd += " " + escapeFilePath(wild) + " " + escapeFilePath(dst_file);
inst << cmd;
uninst.append(rm_dir_contents + " " + escapeFilePath(filePrefixRoot(root, fileFixify(dst_dir + filestr, FileFixifyAbsolute, false))));
@@ -1339,7 +1331,7 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild)
if (!dst_file.endsWith(Option::dir_sep))
dst_file += Option::dir_sep;
dst_file += fi.fileName();
- QString cmd = QLatin1String("-$(QINSTALL) ") +
+ QString cmd = QLatin1String("$(QINSTALL) ") +
escapeFilePath(dirstr + file) + " " + escapeFilePath(dst_file);
inst << cmd;
if (!noStrip && !project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip") &&
@@ -1381,14 +1373,14 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild)
QString tmp_dst = fileFixify((*pit).toQString(), FileFixifyAbsolute, false);
t << mkdir_p_asstring(filePrefixRoot(root, tmp_dst)) << "\n\t";
}
- t << target << endl << endl;
+ t << target << Qt::endl << Qt::endl;
if(!uninst.isEmpty()) {
t << "uninstall_" << (*it) << ": FORCE";
for (int i = uninst.size(); --i >= 0; )
t << "\n\t" << uninst.at(i);
t << "\n\t-$(DEL_DIR) " << escapeFilePath(filePrefixRoot(root, dst)) << " \n\n";
}
- t << endl;
+ t << Qt::endl;
if (installConfigValues.indexOf("no_default_install") == -1) {
all_installs += QString("install_") + (*it) + " ";
@@ -1825,7 +1817,7 @@ MakefileGenerator::writeExtraTargets(QTextStream &t)
t << escapeDependencyPath(targ) << ":" << deps;
if(!cmd.isEmpty())
t << "\n\t" << cmd;
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
}
}
@@ -1870,6 +1862,55 @@ QString MakefileGenerator::resolveDependency(const QDir &outDir, const QString &
return {};
}
+void MakefileGenerator::callExtraCompilerDependCommand(const ProString &extraCompiler,
+ const QString &dep_cd_cmd,
+ const QString &tmp_dep_cmd,
+ const QString &inpf,
+ const QString &tmp_out,
+ bool dep_lines,
+ QStringList *deps)
+{
+ char buff[256];
+ QString dep_cmd = replaceExtraCompilerVariables(tmp_dep_cmd, inpf, tmp_out, LocalShell);
+ dep_cmd = dep_cd_cmd + fixEnvVariables(dep_cmd);
+ if (FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), QT_POPEN_READ)) {
+ QByteArray depData;
+ while (int read_in = feof(proc) ? 0 : (int)fread(buff, 1, 255, proc))
+ depData.append(buff, read_in);
+ QT_PCLOSE(proc);
+ const QString indeps = QString::fromLocal8Bit(depData);
+ if (indeps.isEmpty())
+ return;
+ QDir outDir(Option::output_dir);
+ QStringList dep_cmd_deps = splitDeps(indeps, dep_lines);
+ for (int i = 0; i < dep_cmd_deps.count(); ++i) {
+ QString &file = dep_cmd_deps[i];
+ const QString absFile = outDir.absoluteFilePath(file);
+ if (absFile == file) {
+ // already absolute; don't do any checks.
+ } else if (exists(absFile)) {
+ file = absFile;
+ } else {
+ const QString localFile = resolveDependency(outDir, file);
+ if (localFile.isEmpty()) {
+ if (exists(file)) {
+ warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"
+ " prints paths relative to source directory",
+ extraCompiler.toLatin1().constData());
+ } else {
+ file = absFile; // fallback for generated resources
+ }
+ } else {
+ file = localFile;
+ }
+ }
+ if (!file.isEmpty())
+ file = fileFixify(file);
+ }
+ deps->append(dep_cmd_deps);
+ }
+}
+
void
MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
{
@@ -1911,13 +1952,13 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
replaceExtraCompilerVariables(tmp_out, input, QString(), NoShell),
FileFixifyFromOutdir));
} else {
- for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
+ for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) {
t << ' ' << escapeDependencyPath(fileFixify(
replaceExtraCompilerVariables(tmp_out, (*input).toQString(), QString(), NoShell),
FileFixifyFromOutdir));
}
}
- t << endl;
+ t << Qt::endl;
if (config.indexOf("no_clean") == -1) {
QStringList raw_clean = project->values(ProKey(*it + ".clean")).toQStringList();
@@ -1946,7 +1987,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
const QString del_statement("-$(DEL_FILE)");
if(!wrote_clean) {
QStringList dels;
- for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
+ for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) {
QString tinp = (*input).toQString();
QString out = replaceExtraCompilerVariables(tmp_out, tinp, QString(), NoShell);
for (const QString &rc : qAsConst(raw_clean)) {
@@ -1975,14 +2016,14 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
if(!cleans.isEmpty())
t << valGlue(cleans, "\n\t" + del_statement, "\n\t" + del_statement, "");
if(!wrote_clean_cmds) {
- for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
+ for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) {
QString tinp = (*input).toQString();
t << "\n\t" << replaceExtraCompilerVariables(tmp_clean_cmds, tinp,
replaceExtraCompilerVariables(tmp_out, tinp, QString(), NoShell), TargetShell);
}
}
}
- t << endl;
+ t << Qt::endl;
}
QStringList tmp_dep = project->values(ProKey(*it + ".depends")).toQStringList();
if (config.indexOf("combine") != -1) {
@@ -1994,49 +2035,13 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
QStringList deps, inputs;
if(!tmp_dep.isEmpty())
deps += fileFixify(tmp_dep, FileFixifyFromOutdir);
- for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
+ for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) {
QString inpf = (*input).toQString();
deps += findDependencies(inpf);
inputs += Option::fixPathToTargetOS(inpf, false);
if(!tmp_dep_cmd.isEmpty() && doDepends()) {
- char buff[256];
- QString dep_cmd = replaceExtraCompilerVariables(tmp_dep_cmd, inpf, tmp_out, LocalShell);
- dep_cmd = dep_cd_cmd + fixEnvVariables(dep_cmd);
- if (FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), QT_POPEN_READ)) {
- QByteArray depData;
- while (int read_in = feof(proc) ? 0 : (int)fread(buff, 1, 255, proc))
- depData.append(buff, read_in);
- QT_PCLOSE(proc);
- const QString indeps = QString::fromLocal8Bit(depData);
- if(!indeps.isEmpty()) {
- QDir outDir(Option::output_dir);
- QStringList dep_cmd_deps = splitDeps(indeps, dep_lines);
- for(int i = 0; i < dep_cmd_deps.count(); ++i) {
- QString &file = dep_cmd_deps[i];
- QString absFile = outDir.absoluteFilePath(file);
- if (absFile == file) {
- // already absolute; don't do any checks.
- } else if (exists(absFile)) {
- file = absFile;
- } else {
- QString localFile = resolveDependency(outDir, file);
- if (localFile.isEmpty()) {
- if (exists(file))
- warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"
- " prints paths relative to source directory",
- (*it).toLatin1().constData());
- else
- file = absFile; // fallback for generated resources
- } else {
- file = localFile;
- }
- }
- if(!file.isEmpty())
- file = fileFixify(file);
- }
- deps += dep_cmd_deps;
- }
- }
+ callExtraCompilerDependCommand(*it, dep_cd_cmd, tmp_dep_cmd, inpf,
+ tmp_out, dep_lines, &deps);
}
}
for(int i = 0; i < inputs.size(); ) {
@@ -2063,10 +2068,10 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
} else {
t << " " << valList(escapeDependencyPaths(inputs)) << " " << valList(finalizeDependencyPaths(deps));
}
- t << "\n\t" << cmd << endl << endl;
+ t << "\n\t" << cmd << Qt::endl << Qt::endl;
continue;
}
- for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
+ for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) {
QString inpf = (*input).toQString();
QStringList deps;
deps << fileFixify(inpf, FileFixifyFromOutdir);
@@ -2084,44 +2089,8 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
for (ProStringList::ConstIterator it3 = vars.constBegin(); it3 != vars.constEnd(); ++it3)
cmd.replace("$(" + (*it3) + ")", "$(QMAKE_COMP_" + (*it3)+")");
if(!tmp_dep_cmd.isEmpty() && doDepends()) {
- char buff[256];
- QString dep_cmd = replaceExtraCompilerVariables(tmp_dep_cmd, inpf, out, LocalShell);
- dep_cmd = dep_cd_cmd + fixEnvVariables(dep_cmd);
- if (FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), QT_POPEN_READ)) {
- QByteArray depData;
- while (int read_in = feof(proc) ? 0 : (int)fread(buff, 1, 255, proc))
- depData.append(buff, read_in);
- QT_PCLOSE(proc);
- const QString indeps = QString::fromLocal8Bit(depData);
- if(!indeps.isEmpty()) {
- QDir outDir(Option::output_dir);
- QStringList dep_cmd_deps = splitDeps(indeps, dep_lines);
- for(int i = 0; i < dep_cmd_deps.count(); ++i) {
- QString &file = dep_cmd_deps[i];
- QString absFile = outDir.absoluteFilePath(file);
- if (absFile == file) {
- // already absolute; don't do any checks.
- } else if (exists(absFile)) {
- file = absFile;
- } else {
- QString localFile = resolveDependency(outDir, file);
- if (localFile.isEmpty()) {
- if (exists(file))
- warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"
- " prints paths relative to source directory",
- (*it).toLatin1().constData());
- else
- file = absFile; // fallback for generated resources
- } else {
- file = localFile;
- }
- }
- if(!file.isEmpty())
- file = fileFixify(file);
- }
- deps += dep_cmd_deps;
- }
- }
+ callExtraCompilerDependCommand(*it, dep_cd_cmd, tmp_dep_cmd, inpf,
+ tmp_out, dep_lines, &deps);
//use the depend system to find includes of these included files
QStringList inc_deps;
for(int i = 0; i < deps.size(); ++i) {
@@ -2172,10 +2141,10 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
++i;
}
t << escapeDependencyPath(out) << ": " << valList(finalizeDependencyPaths(deps)) << "\n\t"
- << cmd << endl << endl;
+ << cmd << Qt::endl << Qt::endl;
}
}
- t << "compiler_clean: " << clean_targets << endl << endl;
+ t << "compiler_clean: " << clean_targets << Qt::endl << Qt::endl;
}
void
@@ -2191,17 +2160,17 @@ MakefileGenerator::writeExtraCompilerVariables(QTextStream &t)
first = false;
}
t << "QMAKE_COMP_" << (*varit) << " = "
- << valList(project->values((*varit).toKey())) << endl;
+ << valList(project->values((*varit).toKey())) << Qt::endl;
}
}
if(!first)
- t << endl;
+ t << Qt::endl;
}
void
MakefileGenerator::writeExtraVariables(QTextStream &t)
{
- t << endl;
+ t << Qt::endl;
ProStringList outlist;
const ProValueMap &vars = project->variables();
@@ -2215,7 +2184,7 @@ MakefileGenerator::writeExtraVariables(QTextStream &t)
}
if (!outlist.isEmpty()) {
t << "####### Custom Variables\n";
- t << outlist.join('\n') << endl << endl;
+ t << outlist.join('\n') << Qt::endl << Qt::endl;
}
}
@@ -2231,11 +2200,11 @@ MakefileGenerator::writeExportedVariables(QTextStream &t)
const ProString &name = project->first(ProKey(exp + ".name"));
const ProString &value = project->first(ProKey(exp + ".value"));
if (!value.isEmpty())
- t << name << " = " << value << endl;
+ t << name << " = " << value << Qt::endl;
else
t << name << " =\n";
}
- t << endl;
+ t << Qt::endl;
}
bool
@@ -2243,7 +2212,7 @@ MakefileGenerator::writeDummyMakefile(QTextStream &t)
{
if (project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty())
return false;
- t << "QMAKE = " << var("QMAKE_QMAKE") << endl;
+ t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl;
const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
t << *it << " ";
@@ -2259,7 +2228,7 @@ MakefileGenerator::writeDummyMakefile(QTextStream &t)
bool
MakefileGenerator::writeStubMakefile(QTextStream &t)
{
- t << "QMAKE = " << var("QMAKE_QMAKE") << endl;
+ t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl;
const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
t << *it << " ";
@@ -2288,22 +2257,22 @@ MakefileGenerator::writeMakefile(QTextStream &t)
void
MakefileGenerator::writeDefaultVariables(QTextStream &t)
{
- t << "QMAKE = " << var("QMAKE_QMAKE") << endl;
- t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
- t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl;
- t << "MKDIR = " << var("QMAKE_MKDIR") << endl;
- t << "COPY = " << var("QMAKE_COPY") << endl;
- t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << endl;
- t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl;
- t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl;
- t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl;
- t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl;
- t << "QINSTALL = " << var("QMAKE_QMAKE") << " -install qinstall" << endl;
- t << "QINSTALL_PROGRAM = " << var("QMAKE_QMAKE") << " -install qinstall -exe" << endl;
- t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
- t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << endl;
- t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl;
- t << "MOVE = " << var("QMAKE_MOVE") << endl;
+ t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl;
+ t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << Qt::endl;
+ t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << Qt::endl;
+ t << "MKDIR = " << var("QMAKE_MKDIR") << Qt::endl;
+ t << "COPY = " << var("QMAKE_COPY") << Qt::endl;
+ t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << Qt::endl;
+ t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << Qt::endl;
+ t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << Qt::endl;
+ t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << Qt::endl;
+ t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << Qt::endl;
+ t << "QINSTALL = " << var("QMAKE_QMAKE") << " -install qinstall" << Qt::endl;
+ t << "QINSTALL_PROGRAM = " << var("QMAKE_QMAKE") << " -install qinstall -exe" << Qt::endl;
+ t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << Qt::endl;
+ t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << Qt::endl;
+ t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << Qt::endl;
+ t << "MOVE = " << var("QMAKE_MOVE") << Qt::endl;
}
QString MakefileGenerator::buildArgs(bool withExtra)
@@ -2344,18 +2313,18 @@ void
MakefileGenerator::writeHeader(QTextStream &t)
{
t << "#############################################################################\n";
- t << "# Makefile for building: " << escapeFilePath(var("TARGET")) << endl;
+ t << "# Makefile for building: " << escapeFilePath(var("TARGET")) << Qt::endl;
t << "# Generated by qmake (" QMAKE_VERSION_STR ") (Qt " QT_VERSION_STR ")\n";
- t << "# Project: " << fileFixify(project->projectFile()) << endl;
- t << "# Template: " << var("TEMPLATE") << endl;
+ t << "# Project: " << fileFixify(project->projectFile()) << Qt::endl;
+ t << "# Template: " << var("TEMPLATE") << Qt::endl;
if(!project->isActiveConfig("build_pass"))
- t << "# Command: " << build_args().replace(QLatin1String("$(QMAKE)"), var("QMAKE_QMAKE")) << endl;
+ t << "# Command: " << build_args().replace(QLatin1String("$(QMAKE)"), var("QMAKE_QMAKE")) << Qt::endl;
t << "#############################################################################\n";
- t << endl;
+ t << Qt::endl;
QString ofile = Option::fixPathToTargetOS(Option::output.fileName());
if (ofile.lastIndexOf(Option::dir_sep) != -1)
ofile.remove(0, ofile.lastIndexOf(Option::dir_sep) +1);
- t << "MAKEFILE = " << escapeFilePath(ofile) << endl << endl;
+ t << "MAKEFILE = " << escapeFilePath(ofile) << Qt::endl << Qt::endl;
t << "EQ = =\n\n";
}
@@ -2494,7 +2463,7 @@ MakefileGenerator::writeSubDirs(QTextStream &t)
void MakefileGenerator::writeSubMakeCall(QTextStream &t, const QString &callPrefix,
const QString &makeArguments)
{
- t << callPrefix << "$(MAKE)" << makeArguments << endl;
+ t << callPrefix << "$(MAKE)" << makeArguments << Qt::endl;
}
void
@@ -2513,20 +2482,30 @@ MakefileGenerator::writeSubTargetCall(QTextStream &t,
writeSubMakeCall(t, out_directory_cdin + pfx, makefilein);
}
+static void chopEndLines(QString *s)
+{
+ while (!s->isEmpty()) {
+ const ushort c = s->at(s->size() - 1).unicode();
+ if (c != '\n' && c != '\r')
+ break;
+ s->chop(1);
+ }
+}
+
void
MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubTarget*> targets, int flags)
{
// blasted includes
const ProStringList &qeui = project->values("QMAKE_EXTRA_INCLUDES");
for (ProStringList::ConstIterator qeui_it = qeui.begin(); qeui_it != qeui.end(); ++qeui_it)
- t << "include " << (*qeui_it) << endl;
+ t << "include " << (*qeui_it) << Qt::endl;
if (!(flags & SubTargetSkipDefaultVariables)) {
writeDefaultVariables(t);
t << "SUBTARGETS = "; // subtargets are sub-directory
for(int target = 0; target < targets.size(); ++target)
t << " \\\n\t\t" << targets.at(target)->target;
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
}
writeExtraVariables(t);
@@ -2538,6 +2517,14 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
<< QString((flags & SubTargetInstalls) ? "uninstall_subtargets" : "uninstall");
}
+ struct SequentialInstallData
+ {
+ QString targetPrefix;
+ QString commands;
+ QTextStream commandsStream;
+ SequentialInstallData() : commandsStream(&commands) {}
+ };
+ std::unique_ptr<SequentialInstallData> sequentialInstallData;
bool dont_recurse = project->isActiveConfig("dont_recurse");
// generate target rules
@@ -2582,7 +2569,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
if (!dont_recurse)
writeSubMakeCall(t, out_directory_cdin, makefilein + " qmake_all");
else
- t << endl;
+ t << Qt::endl;
}
{ //actually compile
@@ -2606,6 +2593,16 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
else if(s == "make_first")
s = QString();
+ if (project->isActiveConfig("build_all") && s == "install") {
+ if (!sequentialInstallData)
+ sequentialInstallData.reset(new SequentialInstallData);
+ sequentialInstallData->targetPrefix += subtarget->target + '-';
+ writeSubTargetCall(sequentialInstallData->commandsStream, in_directory, in,
+ out_directory, out, out_directory_cdin,
+ makefilein + " " + s);
+ chopEndLines(&sequentialInstallData->commands);
+ }
+
if(flags & SubTargetOrdered) {
t << subtarget->target << "-" << targetSuffixes.at(suffix) << "-ordered:";
if(target)
@@ -2623,7 +2620,12 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
out_directory_cdin, makefilein + " " + s);
}
}
- t << endl;
+ t << Qt::endl;
+
+ if (sequentialInstallData) {
+ t << sequentialInstallData->targetPrefix << "install: FORCE"
+ << sequentialInstallData->commands << Qt::endl << Qt::endl;
+ }
if (!(flags & SubTargetSkipDefaultTargets)) {
writeMakeQmake(t, true);
@@ -2672,7 +2674,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
} else if(suffix == "distclean") {
QString ofile = fileFixify(Option::output.fileName());
if(!ofile.isEmpty())
- t << "\t-$(DEL_FILE) " << escapeFilePath(ofile) << endl;
+ t << "\t-$(DEL_FILE) " << escapeFilePath(ofile) << Qt::endl;
t << fixFileVarGlue("QMAKE_DISTCLEAN", "\t-$(DEL_FILE) ", " ", "\n");
}
}
@@ -2685,7 +2687,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
cmd = var(ProKey(*qut_it + ".commands")), deps;
if(targ.isEmpty())
targ = (*qut_it).toQString();
- t << endl;
+ t << Qt::endl;
const ProStringList &deplist = project->values(ProKey(*qut_it + ".depends"));
for (ProStringList::ConstIterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) {
@@ -2698,7 +2700,8 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
QSet<QString> recurse;
const ProKey rkey(*qut_it + ".recurse");
if (project->isSet(rkey)) {
- recurse = project->values(rkey).toQStringList().toSet();
+ const QStringList values = project->values(rkey).toQStringList();
+ recurse = QSet<QString>(values.begin(), values.end());
} else {
for(int target = 0; target < targets.size(); ++target)
recurse.insert(targets.at(target)->name);
@@ -2760,7 +2763,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
deps += " FORCE";
t << escapeDependencyPath(Option::fixPathToTargetOS(targ, false)) << ":" << deps << "\n";
if(!cmd.isEmpty())
- t << "\t" << cmd << endl;
+ t << "\t" << cmd << Qt::endl;
}
if(flags & SubTargetInstalls) {
@@ -2778,7 +2781,7 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll)
if(project->isEmpty("QMAKE_FAILED_REQUIREMENTS") && !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) {
QStringList files = escapeFilePaths(fileFixify(Option::mkfile::project_files));
t << escapeDependencyPath(project->first("QMAKE_INTERNAL_PRL_FILE").toQString()) << ": \n\t"
- << "@$(QMAKE) -prl " << files.join(' ') << ' ' << buildArgs(true) << endl;
+ << "@$(QMAKE) -prl " << files.join(' ') << ' ' << buildArgs(true) << Qt::endl;
}
QString qmake = build_args();
@@ -2797,10 +2800,10 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll)
}
const ProStringList &included = escapeDependencyPaths(project->values("QMAKE_INTERNAL_INCLUDED_FILES"));
t << included.join(QString(" \\\n\t\t")) << "\n\t"
- << qmake << endl;
+ << qmake << Qt::endl;
const ProStringList &extraCommands = project->values("QMAKE_MAKE_QMAKE_EXTRA_COMMANDS");
if (!extraCommands.isEmpty())
- t << "\t" << extraCommands.join(QString("\n\t")) << endl;
+ t << "\t" << extraCommands.join(QString("\n\t")) << Qt::endl;
for(int include = 0; include < included.size(); ++include) {
const ProString &i = included.at(include);
if(!i.isEmpty())
@@ -2808,7 +2811,7 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll)
}
}
if(project->first("QMAKE_ORIG_TARGET") != "qmake") {
- t << "qmake: FORCE\n\t@" << qmake << endl << endl;
+ t << "qmake: FORCE\n\t@" << qmake << Qt::endl << Qt::endl;
if (!noDummyQmakeAll)
t << "qmake_all: FORCE\n\n";
}
@@ -3300,11 +3303,11 @@ MakefileGenerator::writePkgConfigFile()
if(includeDir.isEmpty())
includeDir = prefix + "/include";
- t << "prefix=" << prefix << endl;
+ t << "prefix=" << prefix << Qt::endl;
t << "exec_prefix=${prefix}\n"
<< "libdir=" << pkgConfigFixPath(libDir) << "\n"
- << "includedir=" << pkgConfigFixPath(includeDir) << endl;
- t << endl;
+ << "includedir=" << pkgConfigFixPath(includeDir) << Qt::endl;
+ t << Qt::endl;
//extra PKGCONFIG variables
const ProStringList &pkgconfig_vars = project->values("QMAKE_PKGCONFIG_VARIABLES");
@@ -3325,17 +3328,17 @@ MakefileGenerator::writePkgConfigFile()
}
}
if (!val.isEmpty())
- t << var << "=" << val << endl;
+ t << var << "=" << val << Qt::endl;
}
- t << endl;
+ t << Qt::endl;
QString name = project->first("QMAKE_PKGCONFIG_NAME").toQString();
if(name.isEmpty()) {
name = project->first("QMAKE_ORIG_TARGET").toQString().toLower();
name.replace(0, 1, name[0].toUpper());
}
- t << "Name: " << name << endl;
+ t << "Name: " << name << Qt::endl;
QString desc = project->values("QMAKE_PKGCONFIG_DESCRIPTION").join(' ');
if(desc.isEmpty()) {
if(name.isEmpty()) {
@@ -3353,12 +3356,12 @@ MakefileGenerator::writePkgConfigFile()
desc += " Application";
}
}
- t << "Description: " << desc << endl;
+ t << "Description: " << desc << Qt::endl;
ProString version = project->first("QMAKE_PKGCONFIG_VERSION");
if (version.isEmpty())
version = project->first("VERSION");
if (!version.isEmpty())
- t << "Version: " << version << endl;
+ t << "Version: " << version << Qt::endl;
if (project->first("TEMPLATE") == "lib") {
// libs
@@ -3394,9 +3397,9 @@ MakefileGenerator::writePkgConfigFile()
libs << "QMAKE_LIBS_PRIVATE";
libs << "QMAKE_LFLAGS_THREAD"; //not sure about this one, but what about things like -pthread?
t << "Libs.private:";
- for (ProStringList::ConstIterator it = libs.begin(); it != libs.end(); ++it)
+ for (ProStringList::ConstIterator it = libs.cbegin(); it != libs.cend(); ++it)
t << ' ' << fixLibFlags((*it).toKey()).join(' ');
- t << endl;
+ t << Qt::endl;
}
}
@@ -3415,15 +3418,15 @@ MakefileGenerator::writePkgConfigFile()
&& libDir != QLatin1String("/Library/Frameworks")) {
t << " -F${libdir}";
}
- t << endl;
+ t << Qt::endl;
// requires
const QString requires = project->values("QMAKE_PKGCONFIG_REQUIRES").join(' ');
if (!requires.isEmpty()) {
- t << "Requires: " << requires << endl;
+ t << "Requires: " << requires << Qt::endl;
}
- t << endl;
+ t << Qt::endl;
}
static QString windowsifyPath(const QString &str)
diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h
index 350ebd377a..c7b2bee0b4 100644
--- a/qmake/generators/makefile.h
+++ b/qmake/generators/makefile.h
@@ -54,7 +54,7 @@ struct ReplaceExtraCompilerCacheKey;
class MakefileGenerator : protected QMakeSourceFileInfo
{
QString spec;
- bool no_io;
+ bool no_io = false;
bool resolveDependenciesInFrameworks = false;
QHash<QString, bool> init_compiler_already;
QString makedir, chkexists;
@@ -84,6 +84,9 @@ protected:
void writeExtraVariables(QTextStream &t);
void writeExtraTargets(QTextStream &t);
QString resolveDependency(const QDir &outDir, const QString &file);
+ void callExtraCompilerDependCommand(const ProString &extraCompiler, const QString &dep_cd_cmd,
+ const QString &tmp_dep_cmd, const QString &inpf,
+ const QString &tmp_out, bool dep_lines, QStringList *deps);
void writeExtraCompilerTargets(QTextStream &t);
void writeExtraCompilerVariables(QTextStream &t);
bool writeDummyMakefile(QTextStream &t);
@@ -131,7 +134,7 @@ protected:
QMakeLocalFileName fixPathForFile(const QMakeLocalFileName &, bool) override;
QMakeLocalFileName findFileForDep(const QMakeLocalFileName &, const QMakeLocalFileName &) override;
QFileInfo findFileInfo(const QMakeLocalFileName &) override;
- QMakeProject *project;
+ QMakeProject *project = nullptr;
//escape
virtual QString escapeFilePath(const QString &path) const = 0;
@@ -256,8 +259,6 @@ protected:
const QString &fixedFile);
public:
- MakefileGenerator();
- ~MakefileGenerator();
QMakeProject *projectFile() const;
void setProjectFile(QMakeProject *p);
@@ -295,9 +296,6 @@ inline QString MakefileGenerator::installRoot() const
inline bool MakefileGenerator::findLibraries(bool, bool)
{ return true; }
-inline MakefileGenerator::~MakefileGenerator()
-{ }
-
struct ReplaceExtraCompilerCacheKey
{
mutable uint hash;
diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp
index 8ebd0c61ce..f9159ccd75 100644
--- a/qmake/generators/metamakefile.cpp
+++ b/qmake/generators/metamakefile.cpp
@@ -27,7 +27,6 @@
****************************************************************************/
#include "metamakefile.h"
-#include "qregexp.h"
#include "qdir.h"
#include "qdebug.h"
#include "makefile.h"
diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp
index f45a90b851..119dd652b3 100644
--- a/qmake/generators/projectgenerator.cpp
+++ b/qmake/generators/projectgenerator.cpp
@@ -50,10 +50,6 @@ QString project_builtin_regx() //calculate the builtin regular expression..
return ret;
}
-ProjectGenerator::ProjectGenerator() : MakefileGenerator()
-{
-}
-
void
ProjectGenerator::init()
{
@@ -324,14 +320,14 @@ ProjectGenerator::init()
bool
ProjectGenerator::writeMakefile(QTextStream &t)
{
- t << "######################################################################" << endl;
- t << "# Automatically generated by qmake (" QMAKE_VERSION_STR ") " << QDateTime::currentDateTime().toString() << endl;
- t << "######################################################################" << endl << endl;
+ t << "######################################################################" << Qt::endl;
+ t << "# Automatically generated by qmake (" QMAKE_VERSION_STR ") " << QDateTime::currentDateTime().toString() << Qt::endl;
+ t << "######################################################################" << Qt::endl << Qt::endl;
if (!Option::globals->extra_cmds[QMakeEvalBefore].isEmpty())
- t << Option::globals->extra_cmds[QMakeEvalBefore] << endl;
+ t << Option::globals->extra_cmds[QMakeEvalBefore] << Qt::endl;
t << getWritableVar("TEMPLATE_ASSIGN", false);
if(project->first("TEMPLATE_ASSIGN") == "subdirs") {
- t << endl << "# Directories" << "\n"
+ t << Qt::endl << "# Directories" << "\n"
<< getWritableVar("SUBDIRS");
} else {
//figure out target
@@ -343,16 +339,12 @@ ProjectGenerator::writeMakefile(QTextStream &t)
t << getWritableVar("TARGET_ASSIGN")
<< getWritableVar("CONFIG", false)
<< getWritableVar("CONFIG_REMOVE", false)
- << getWritableVar("INCLUDEPATH") << endl;
+ << getWritableVar("INCLUDEPATH") << Qt::endl;
- t << "# The following define makes your compiler warn you if you use any\n"
- "# feature of Qt which has been marked as deprecated (the exact warnings\n"
- "# depend on your compiler). Please consult the documentation of the\n"
- "# deprecated API in order to know how to port your code away from it.\n"
- "DEFINES += QT_DEPRECATED_WARNINGS\n"
- "\n"
- "# You can also make your code fail to compile if you use deprecated APIs.\n"
+ t << "# You can make your code fail to compile if you use deprecated APIs.\n"
"# In order to do so, uncomment the following line.\n"
+ "# Please consult the documentation of the deprecated API in order to know\n"
+ "# how to port your code away from it.\n"
"# You can also select to disable deprecated APIs only up to a certain version of Qt.\n"
"#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0\n\n";
@@ -366,7 +358,7 @@ ProjectGenerator::writeMakefile(QTextStream &t)
<< getWritableVar("TRANSLATIONS");
}
if (!Option::globals->extra_cmds[QMakeEvalAfter].isEmpty())
- t << Option::globals->extra_cmds[QMakeEvalAfter] << endl;
+ t << Option::globals->extra_cmds[QMakeEvalAfter] << Qt::endl;
return true;
}
diff --git a/qmake/generators/projectgenerator.h b/qmake/generators/projectgenerator.h
index 02a331bd4f..374bad98c7 100644
--- a/qmake/generators/projectgenerator.h
+++ b/qmake/generators/projectgenerator.h
@@ -46,15 +46,10 @@ protected:
QString escapeFilePath(const QString &) const override { Q_ASSERT(false); return QString(); }
public:
- ProjectGenerator();
- ~ProjectGenerator();
bool supportsMetaBuild() override { return false; }
bool openOutput(QFile &, const QString &) const override;
};
-inline ProjectGenerator::~ProjectGenerator()
-{ }
-
QT_END_NAMESPACE
#endif // PROJECTGENERATOR_H
diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp
index b809bb6c19..ef55af365c 100644
--- a/qmake/generators/unix/unixmake.cpp
+++ b/qmake/generators/unix/unixmake.cpp
@@ -28,7 +28,6 @@
#include "unixmake.h"
#include "option.h"
-#include <qregexp.h>
#include <qfile.h>
#include <qhash.h>
#include <qdir.h>
@@ -605,7 +604,7 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
dst = escapeFilePath(filePrefixRoot(root, targetdir + src.section('/', -1)));
if(!ret.isEmpty())
ret += "\n\t";
- ret += "-$(QINSTALL) " + escapeFilePath(Option::fixPathToTargetOS(src, false)) + ' ' + dst;
+ ret += "$(QINSTALL) " + escapeFilePath(Option::fixPathToTargetOS(src, false)) + ' ' + dst;
if(!uninst.isEmpty())
uninst.append("\n\t");
uninst.append("-$(DEL_FILE) " + dst);
@@ -641,16 +640,16 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
QString copy_cmd;
if (bundle == SolidBundle) {
- copy_cmd += "-$(QINSTALL) " + src_targ + ' ' + plain_targ;
+ copy_cmd += "$(QINSTALL) " + src_targ + ' ' + plain_targ;
} else if (project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) {
- copy_cmd += "-$(QINSTALL) " + src_targ + ' ' + dst_targ;
+ copy_cmd += "$(QINSTALL) " + src_targ + ' ' + dst_targ;
} else if (!isAux) {
if (bundle == SlicedBundle) {
if (!ret.isEmpty())
ret += "\n\t";
ret += mkdir_p_asstring("\"`dirname " + dst_targ + "`\"", false);
}
- copy_cmd += "-$(QINSTALL_PROGRAM) " + src_targ + ' ' + dst_targ;
+ copy_cmd += "$(QINSTALL_PROGRAM) " + src_targ + ' ' + dst_targ;
}
if(project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib")
&& project->values(ProKey(t + ".CONFIG")).indexOf("fix_rpath") != -1) {
@@ -703,7 +702,7 @@ UnixMakefileGenerator::defaultInstall(const QString &t)
ret += "\n\t";
ret += mkdir_p_asstring("\"`dirname " + dst + "`\"", false) + "\n\t";
ret += "-$(DEL_FILE) " + dst + "\n\t"; // Can't overwrite symlinks to directories
- ret += "-$(QINSTALL) " + escapeFilePath(src) + " " + dst;
+ ret += "$(QINSTALL) " + escapeFilePath(src) + " " + dst;
if (!uninst.isEmpty())
uninst.append("\n\t");
uninst.append("-$(DEL_FILE) " + dst);
diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h
index 5b0766855b..901419d3cc 100644
--- a/qmake/generators/unix/unixmake.h
+++ b/qmake/generators/unix/unixmake.h
@@ -35,15 +35,11 @@ QT_BEGIN_NAMESPACE
class UnixMakefileGenerator : public MakefileGenerator
{
- bool include_deps;
+ bool include_deps = false;
QString libtoolFileName(bool fixify=true);
void writeLibtoolFile(); // for libtool
void writePrlFile(QTextStream &) override;
-public:
- UnixMakefileGenerator();
- ~UnixMakefileGenerator();
-
protected:
virtual bool doPrecompiledHeaders() const { return project->isActiveConfig("precompile_header"); }
bool doDepends() const override { return !Option::mkfile::do_stub_makefile && MakefileGenerator::doDepends(); }
@@ -69,9 +65,6 @@ private:
ProStringList libdirToFlags(const ProKey &key);
};
-inline UnixMakefileGenerator::~UnixMakefileGenerator()
-{ }
-
QT_END_NAMESPACE
#endif // UNIXMAKE_H
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index d9bcccf2e2..c8efd0680b 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -39,11 +39,6 @@
QT_BEGIN_NAMESPACE
-UnixMakefileGenerator::UnixMakefileGenerator() : MakefileGenerator(), include_deps(false)
-{
-
-}
-
void
UnixMakefileGenerator::writePrlFile(QTextStream &t)
{
@@ -86,8 +81,8 @@ void
UnixMakefileGenerator::writeDefaultVariables(QTextStream &t)
{
MakefileGenerator::writeDefaultVariables(t);
- t << "TAR = " << var("QMAKE_TAR") << endl;
- t << "COMPRESS = " << var("QMAKE_GZIP") << endl;
+ t << "TAR = " << var("QMAKE_TAR") << Qt::endl;
+ t << "COMPRESS = " << var("QMAKE_GZIP") << Qt::endl;
if (project->isEmpty("QMAKE_DISTNAME")) {
ProString distname = project->first("QMAKE_ORIG_TARGET");
@@ -95,13 +90,13 @@ UnixMakefileGenerator::writeDefaultVariables(QTextStream &t)
distname += project->first("VERSION");
project->values("QMAKE_DISTNAME") = distname;
}
- t << "DISTNAME = " << fileVar("QMAKE_DISTNAME") << endl;
+ t << "DISTNAME = " << fileVar("QMAKE_DISTNAME") << Qt::endl;
if (project->isEmpty("QMAKE_DISTDIR"))
project->values("QMAKE_DISTDIR") = project->first("QMAKE_DISTNAME");
t << "DISTDIR = " << escapeFilePath(fileFixify(
(project->isEmpty("OBJECTS_DIR") ? ProString(".tmp/") : project->first("OBJECTS_DIR")) + project->first("QMAKE_DISTDIR"),
- FileFixifyFromOutdir | FileFixifyAbsolute)) << endl;
+ FileFixifyFromOutdir | FileFixifyAbsolute)) << Qt::endl;
}
void
@@ -109,10 +104,10 @@ UnixMakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::
{
MakefileGenerator::writeSubTargets(t, targets, flags);
- t << "dist: distdir FORCE" << endl;
+ t << "dist: distdir FORCE" << Qt::endl;
t << "\t(cd `dirname $(DISTDIR)` && $(TAR) $(DISTNAME).tar $(DISTNAME) && $(COMPRESS) $(DISTNAME).tar)"
" && $(MOVE) `dirname $(DISTDIR)`/$(DISTNAME).tar.gz . && $(DEL_FILE) -r $(DISTDIR)";
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
t << "distdir:";
for (int target = 0; target < targets.size(); ++target) {
@@ -121,7 +116,7 @@ UnixMakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::
}
t << " FORCE\n\t"
<< mkdir_p_asstring("$(DISTDIR)", false) << "\n\t"
- << "$(COPY_FILE) --parents " << fileVar("DISTFILES") << " $(DISTDIR)" << Option::dir_sep << endl << endl;
+ << "$(COPY_FILE) --parents " << fileVar("DISTFILES") << " $(DISTDIR)" << Option::dir_sep << Qt::endl << Qt::endl;
const QString abs_source_path = project->first("QMAKE_ABSOLUTE_SOURCE_PATH").toQString();
for (int target = 0; target < targets.size(); ++target) {
@@ -154,7 +149,7 @@ UnixMakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::
t << subtarget->target << "-distdir: FORCE";
writeSubTargetCall(t, in_directory, in, out_directory, escapeFilePath(out),
out_directory_cdin, makefilein);
- t << endl;
+ t << Qt::endl;
}
}
@@ -172,6 +167,16 @@ static QString rfc1034Identifier(const QString &str)
return s;
}
+static QString escapeDir(const QString &dir)
+{
+ // When building on non-MSys MinGW, the path ends with a backslash, which
+ // GNU make will interpret that as a line continuation. Doubling the backslash
+ // avoids the problem, at the cost of the variable containing *both* backslashes.
+ if (dir.endsWith('\\'))
+ return dir + '\\';
+ return dir;
+}
+
void
UnixMakefileGenerator::writeMakeParts(QTextStream &t)
{
@@ -186,11 +191,11 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
writeExportedVariables(t);
t << "####### Compiler, tools and options\n\n";
- t << "CC = " << var("QMAKE_CC") << endl;
- t << "CXX = " << var("QMAKE_CXX") << endl;
+ t << "CC = " << var("QMAKE_CC") << Qt::endl;
+ t << "CXX = " << var("QMAKE_CXX") << Qt::endl;
t << "DEFINES = "
<< varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
- << varGlue("DEFINES","-D"," -D","") << endl;
+ << varGlue("DEFINES","-D"," -D","") << Qt::endl;
t << "CFLAGS = " << var("QMAKE_CFLAGS") << " $(DEFINES)\n";
t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " $(DEFINES)\n";
t << "INCPATH =";
@@ -211,38 +216,38 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
}
if(!project->isEmpty("QMAKE_FRAMEWORKPATH_FLAGS"))
t << " " << var("QMAKE_FRAMEWORKPATH_FLAGS");
- t << endl;
+ t << Qt::endl;
writeDefaultVariables(t);
if(!project->isActiveConfig("staticlib")) {
- t << "LINK = " << var("QMAKE_LINK") << endl;
- t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
+ t << "LINK = " << var("QMAKE_LINK") << Qt::endl;
+ t << "LFLAGS = " << var("QMAKE_LFLAGS") << Qt::endl;
t << "LIBS = $(SUBLIBS) " << fixLibFlags("LIBS").join(' ') << ' '
<< fixLibFlags("LIBS_PRIVATE").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS").join(' ') << ' '
- << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl;
+ << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << Qt::endl;
}
- t << "AR = " << var("QMAKE_AR") << endl;
- t << "RANLIB = " << var("QMAKE_RANLIB") << endl;
- t << "SED = " << var("QMAKE_STREAM_EDITOR") << endl;
- t << "STRIP = " << var("QMAKE_STRIP") << endl;
+ t << "AR = " << var("QMAKE_AR") << Qt::endl;
+ t << "RANLIB = " << var("QMAKE_RANLIB") << Qt::endl;
+ t << "SED = " << var("QMAKE_STREAM_EDITOR") << Qt::endl;
+ t << "STRIP = " << var("QMAKE_STRIP") << Qt::endl;
- t << endl;
+ t << Qt::endl;
t << "####### Output directory\n\n";
// This is used in commands by some .prf files.
if (! project->values("OBJECTS_DIR").isEmpty())
- t << "OBJECTS_DIR = " << fileVar("OBJECTS_DIR") << endl;
+ t << "OBJECTS_DIR = " << escapeDir(fileVar("OBJECTS_DIR")) << Qt::endl;
else
t << "OBJECTS_DIR = ./\n";
- t << endl;
+ t << Qt::endl;
/* files */
t << "####### Files\n\n";
// This is used by the dist target.
- t << "SOURCES = " << fileVarList("SOURCES") << ' ' << fileVarList("GENERATED_SOURCES") << endl;
+ t << "SOURCES = " << fileVarList("SOURCES") << ' ' << fileVarList("GENERATED_SOURCES") << Qt::endl;
if(do_incremental) {
const ProStringList &objs = project->values("OBJECTS");
const ProStringList &incrs = project->values("QMAKE_INCREMENTAL");
@@ -262,59 +267,53 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\\\n\t\t" << (*objit);
}
if(incrs_out.count() == objs.count()) { //we just switched places, no real incrementals to be done!
- t << escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << endl;
+ t << escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << Qt::endl;
} else if(!incrs_out.count()) {
- t << endl;
+ t << Qt::endl;
} else {
src_incremental = true;
- t << endl;
+ t << Qt::endl;
t << "INCREMENTAL_OBJECTS = "
- << escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << endl;
+ << escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << Qt::endl;
}
} else {
// Used all over the place in both deps and commands.
- t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << endl;
+ t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << Qt::endl;
}
if(do_incremental && !src_incremental)
do_incremental = false;
t << "DIST = " << valList(fileFixify(project->values("DISTFILES").toQStringList())) << " "
- << fileVarList("HEADERS") << ' ' << fileVarList("SOURCES") << endl;
- t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << endl;
- QString destd = fileVar("DESTDIR");
- // When building on non-MSys MinGW, the path ends with a backslash, which
- // GNU make will interpret that as a line continuation. Doubling the backslash
- // avoids the problem, at the cost of the variable containing *both* backslashes.
- if (destd.endsWith('\\'))
- destd += '\\';
- t << "DESTDIR = " << destd << endl;
- t << "TARGET = " << fileVar("TARGET") << endl;
+ << fileVarList("HEADERS") << ' ' << fileVarList("SOURCES") << Qt::endl;
+ t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << Qt::endl;
+ t << "DESTDIR = " << escapeDir(fileVar("DESTDIR")) << Qt::endl;
+ t << "TARGET = " << fileVar("TARGET") << Qt::endl;
if(project->isActiveConfig("plugin")) {
- t << "TARGETD = " << fileVar("TARGET") << endl;
+ t << "TARGETD = " << fileVar("TARGET") << Qt::endl;
} else if(!project->isActiveConfig("staticlib") && project->values("QMAKE_APP_FLAG").isEmpty()) {
- t << "TARGETA = " << fileVar("TARGETA") << endl;
+ t << "TARGETA = " << fileVar("TARGETA") << Qt::endl;
if(!project->isEmpty("QMAKE_BUNDLE")) {
- t << "TARGETD = " << fileVar("TARGET_x.y") << endl;
- t << "TARGET0 = " << fileVar("TARGET_") << endl;
+ t << "TARGETD = " << fileVar("TARGET_x.y") << Qt::endl;
+ t << "TARGET0 = " << fileVar("TARGET_") << Qt::endl;
} else if (!project->isActiveConfig("unversioned_libname")) {
- t << "TARGET0 = " << fileVar("TARGET_") << endl;
+ t << "TARGET0 = " << fileVar("TARGET_") << Qt::endl;
if (project->isEmpty("QMAKE_HPUX_SHLIB")) {
- t << "TARGETD = " << fileVar("TARGET_x.y.z") << endl;
- t << "TARGET1 = " << fileVar("TARGET_x") << endl;
- t << "TARGET2 = " << fileVar("TARGET_x.y") << endl;
+ t << "TARGETD = " << fileVar("TARGET_x.y.z") << Qt::endl;
+ t << "TARGET1 = " << fileVar("TARGET_x") << Qt::endl;
+ t << "TARGET2 = " << fileVar("TARGET_x.y") << Qt::endl;
} else {
- t << "TARGETD = " << fileVar("TARGET_x") << endl;
+ t << "TARGETD = " << fileVar("TARGET_x") << Qt::endl;
}
}
}
writeExtraCompilerVariables(t);
writeExtraVariables(t);
- t << endl;
+ t << Qt::endl;
// blasted includes
const ProStringList &qeui = project->values("QMAKE_EXTRA_INCLUDES");
ProStringList::ConstIterator it;
for(it = qeui.begin(); it != qeui.end(); ++it)
- t << "include " << escapeDependencyPath(*it) << endl;
+ t << "include " << escapeDependencyPath(*it) << Qt::endl;
/* rules */
t << "first:" << (!project->isActiveConfig("no_default_goal_deps") ? " all" : "") << "\n";
@@ -324,7 +323,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
ProStringList objects = project->values("OBJECTS");
for (ProStringList::Iterator it = objects.begin(); it != objects.end(); ++it) {
QString d_file = (*it).toQString().replace(QRegExp(Option::obj_ext + "$"), ".d");
- t << "-include " << escapeDependencyPath(d_file) << endl;
+ t << "-include " << escapeDependencyPath(d_file) << Qt::endl;
project->values("QMAKE_DISTCLEAN") << d_file;
}
} else {
@@ -382,8 +381,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
QStringList deps = findDependencies((*it).toQString()).filter(QRegExp(
"((^|/)" + Option::h_moc_mod + "|" + Option::cpp_moc_ext + "$)"));
if(!deps.isEmpty())
- t << d_file_d << ": " << finalizeDependencyPaths(deps).join(' ') << endl;
- t << "-include " << d_file_d << endl;
+ t << d_file_d << ": " << finalizeDependencyPaths(deps).join(' ') << Qt::endl;
+ t << "-include " << d_file_d << Qt::endl;
project->values("QMAKE_DISTCLEAN") += d_file;
}
}
@@ -402,7 +401,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
for (ProStringList::ConstIterator it = l.begin(); it != l.end(); ++it)
t << escapeFilePath(libdir + project->first("QMAKE_PREFIX_STATICLIB") + (*it) + '.'
+ project->first("QMAKE_EXTENSION_STATICLIB")) << ' ';
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
}
QString target_deps;
if ((project->isActiveConfig("depend_prl") || project->isActiveConfig("fast_depend_prl"))
@@ -507,7 +506,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "$(LINK) $(LFLAGS) " << var("QMAKE_LINK_O_FLAG") << "$(TARGET) " << incr_deps << " " << incr_objs << " $(OBJCOMP) $(LIBS)";
if(!project->isEmpty("QMAKE_POST_LINK"))
t << "\n\t" << var("QMAKE_POST_LINK");
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
} else {
t << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) "
<< target_deps << ' ' << depVar("POST_TARGETDEPS") << "\n\t";
@@ -520,7 +519,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
if (!project->isEmpty("QMAKE_POST_LINK"))
t << "\n\t" << var("QMAKE_POST_LINK");
}
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
}
allDeps = ' ' + depVar("TARGET");
} else if(!project->isActiveConfig("staticlib")) {
@@ -551,7 +550,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
//actual target
const QString link_deps = "$(OBJECTS) ";
t << incr_target_dir_d << ": " << link_deps << "\n\t"
- << "ld -r -o " << incr_target_dir_f << ' ' << link_deps << endl;
+ << "ld -r -o " << incr_target_dir_f << ' ' << link_deps << Qt::endl;
//communicated below
ProStringList &cmd = project->values("QMAKE_LINK_SHLIB_CMD");
cmd[0] = cmd.at(0).toQString().replace(QLatin1String("$(OBJECTS) "), QLatin1String("$(INCREMENTAL_OBJECTS)")); //ick
@@ -609,7 +608,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
<< "-$(MOVE) $(TARGET) " << destdir << "$(TARGET)";
if(!project->isEmpty("QMAKE_POST_LINK"))
t << "\n\t" << var("QMAKE_POST_LINK");
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
} else if(!project->isEmpty("QMAKE_BUNDLE")) {
bundledFiles << destdir_r + var("TARGET");
t << "\n\t"
@@ -623,7 +622,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
" Versions/Current/$(TARGET) $(DESTDIR)$(TARGET0)") << "\n\t";
if(!project->isEmpty("QMAKE_POST_LINK"))
t << "\n\t" << var("QMAKE_POST_LINK");
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
} else if(project->isEmpty("QMAKE_HPUX_SHLIB")) {
t << "\n\t";
@@ -657,7 +656,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
}
if(!project->isEmpty("QMAKE_POST_LINK"))
t << "\n\t" << var("QMAKE_POST_LINK");
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
} else {
t << "\n\t"
<< "-$(DEL_FILE) $(TARGET) $(TARGET0)\n\t"
@@ -671,9 +670,9 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
<< "-$(MOVE) $(TARGET0) " << destdir << "$(TARGET0)\n\t";
if(!project->isEmpty("QMAKE_POST_LINK"))
t << "\n\t" << var("QMAKE_POST_LINK");
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
}
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
if (! project->isActiveConfig("plugin")) {
t << "staticlib: " << depVar("TARGETA") << "\n\n";
@@ -691,7 +690,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\n\t" << var("QMAKE_POST_LINK");
if(!project->isEmpty("QMAKE_RANLIB"))
t << "\n\t$(RANLIB) $(TARGETA)";
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
}
} else {
QString destdir_r = project->first("DESTDIR").toQString();
@@ -711,7 +710,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\t" << var("QMAKE_POST_LINK") << "\n";
if (!project->isEmpty("QMAKE_RANLIB"))
t << "\t$(RANLIB) " << destdir << "$(TARGET)\n";
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
}
writeMakeQmake(t);
@@ -725,7 +724,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
}
if(!meta_files.isEmpty())
t << escapeDependencyPaths(meta_files).join(" ") << ": \n\t"
- << "@$(QMAKE) -prl " << escapeFilePath(project->projectFile()) << ' ' << buildArgs(true) << endl;
+ << "@$(QMAKE) -prl " << escapeFilePath(project->projectFile()) << ' ' << buildArgs(true) << Qt::endl;
}
if (!project->isEmpty("QMAKE_BUNDLE")) {
@@ -746,7 +745,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
<< "@echo \"APPL"
<< (project->isEmpty("QMAKE_PKGINFO_TYPEINFO")
? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4))
- << "\" > " << pkginfo_f << endl;
+ << "\" > " << pkginfo_f << Qt::endl;
}
if (!project->first("QMAKE_BUNDLE_RESOURCE_FILE").isEmpty()) {
ProString resources = project->first("QMAKE_BUNDLE_RESOURCE_FILE");
@@ -855,7 +854,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
<< "-e \"s,\\$${EXECUTABLE_NAME}," << (app_bundle_name.isEmpty() ? app_bundle_name : plugin_bundle_name) << ",g\" "
<< "-e \"s,@TYPEINFO@,"<< typeInfo << ",g\" "
<< "-e \"s,\\$${QMAKE_PKGINFO_TYPEINFO},"<< typeInfo << ",g\" "
- << "" << info_plist << " >" << info_plist_out << endl;
+ << "" << info_plist << " >" << info_plist_out << Qt::endl;
//copy the icon
if (!project->isEmpty("ICON")) {
QString dir = bundle_dir + "Contents/Resources/";
@@ -866,7 +865,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << escapeDependencyPath(icon_path) << ": " << escapeDependencyPath(icon) << "\n\t"
<< mkdir_p_asstring(dir) << "\n\t"
<< "@$(DEL_FILE) " << icon_path_f << "\n\t"
- << "@$(COPY_FILE) " << escapeFilePath(icon) << ' ' << icon_path_f << endl;
+ << "@$(COPY_FILE) " << escapeFilePath(icon) << ' ' << icon_path_f << Qt::endl;
}
} else {
ProString lib_bundle_name = var("QMAKE_FRAMEWORK_BUNDLE_NAME");
@@ -883,7 +882,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
<< "-e \"s,\\$${EXECUTABLE_NAME}," << lib_bundle_name << ",g\" "
<< "-e \"s,@TYPEINFO@," << typeInfo << ",g\" "
<< "-e \"s,\\$${QMAKE_PKGINFO_TYPEINFO}," << typeInfo << ",g\" "
- << "" << info_plist << " >" << info_plist_out << endl;
+ << "" << info_plist << " >" << info_plist_out << Qt::endl;
}
break;
} // project->isActiveConfig("no_plist")
@@ -927,10 +926,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
QFileInfo fi(fileInfo(fn));
if(fi.isDir())
t << "@$(DEL_FILE) -r " << dst << "\n\t"
- << "@$(COPY_DIR) " << src << " " << dst << endl;
+ << "@$(COPY_DIR) " << src << " " << dst << Qt::endl;
else
t << "@$(DEL_FILE) " << dst << "\n\t"
- << "@$(COPY_FILE) " << src << " " << dst << endl;
+ << "@$(COPY_FILE) " << src << " " << dst << Qt::endl;
}
}
}
@@ -943,7 +942,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
alldeps << symIt.key();
t << escapeDependencyPath(symIt.key()) << ":\n\t"
<< mkdir_p_asstring(bundle_dir) << "\n\t"
- << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << endl;
+ << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << Qt::endl;
}
if (!project->isActiveConfig("shallow_bundle")) {
@@ -955,24 +954,24 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
<< mkdir_p_asstring(bundle_dir + "Versions") << "\n\t"
<< "@-$(DEL_FILE) " << currentLink_f << "\n\t"
<< "@$(SYMLINK) " << project->first("QMAKE_FRAMEWORK_VERSION")
- << ' ' << currentLink_f << endl;
+ << ' ' << currentLink_f << Qt::endl;
}
}
}
- t << endl << "all: " << deps
+ t << Qt::endl << "all: " << deps
<< valGlue(escapeDependencyPaths(project->values("ALL_DEPS")), " \\\n\t\t", " \\\n\t\t", "")
- << allDeps << endl << endl;
+ << allDeps << Qt::endl << Qt::endl;
t << "dist: distdir FORCE\n\t";
t << "(cd `dirname $(DISTDIR)` && $(TAR) $(DISTNAME).tar $(DISTNAME) && $(COMPRESS) $(DISTNAME).tar)"
" && $(MOVE) `dirname $(DISTDIR)`" << Option::dir_sep << "$(DISTNAME).tar.gz ."
" && $(DEL_FILE) -r $(DISTDIR)";
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
t << "distdir: FORCE\n\t"
<< mkdir_p_asstring("$(DISTDIR)", false) << "\n\t"
- << "$(COPY_FILE) --parents $(DIST) $(DISTDIR)" << Option::dir_sep << endl;
+ << "$(COPY_FILE) --parents $(DIST) $(DISTDIR)" << Option::dir_sep << Qt::endl;
if(!project->isEmpty("QMAKE_EXTRA_COMPILERS")) {
const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
@@ -982,20 +981,20 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
if(val.isEmpty())
continue;
t << "\t$(COPY_FILE) --parents " << escapeFilePaths(val).join(' ')
- << " $(DISTDIR)" << Option::dir_sep << endl;
+ << " $(DISTDIR)" << Option::dir_sep << Qt::endl;
}
}
}
if(!project->isEmpty("TRANSLATIONS"))
- t << "\t$(COPY_FILE) --parents " << fileVar("TRANSLATIONS") << " $(DISTDIR)" << Option::dir_sep << endl;
- t << endl << endl;
+ t << "\t$(COPY_FILE) --parents " << fileVar("TRANSLATIONS") << " $(DISTDIR)" << Option::dir_sep << Qt::endl;
+ t << Qt::endl << Qt::endl;
QString clean_targets = " compiler_clean " + depVar("CLEAN_DEPS");
if(do_incremental) {
t << "incrclean:\n";
if(src_incremental)
t << "\t-$(DEL_FILE) $(INCREMENTAL_OBJECTS)\n";
- t << endl;
+ t << Qt::endl;
}
t << "clean:" << clean_targets << "\n\t";
@@ -1063,7 +1062,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "-$(DEL_FILE) $(INCREMENTAL_OBJECTS)\n\t";
t << fileVarGlue("QMAKE_CLEAN","-$(DEL_FILE) "," ","\n\t")
<< "-$(DEL_FILE) *~ core *.core\n"
- << fileVarGlue("CLEAN_FILES","\t-$(DEL_FILE) "," ","") << endl << endl;
+ << fileVarGlue("CLEAN_FILES","\t-$(DEL_FILE) "," ","") << Qt::endl << Qt::endl;
ProString destdir = project->first("DESTDIR");
if (!destdir.isEmpty() && !destdir.endsWith(Option::dir_sep))
@@ -1071,7 +1070,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "distclean: clean " << depVar("DISTCLEAN_DEPS") << '\n';
if(!project->isEmpty("QMAKE_BUNDLE")) {
QString bundlePath = escapeFilePath(destdir + project->first("QMAKE_BUNDLE"));
- t << "\t-$(DEL_FILE) -r " << bundlePath << endl;
+ t << "\t-$(DEL_FILE) -r " << bundlePath << Qt::endl;
} else if (project->isActiveConfig("staticlib") || project->isActiveConfig("plugin")) {
t << "\t-$(DEL_FILE) " << escapeFilePath(destdir) << "$(TARGET) \n";
} else if (project->values("QMAKE_APP_FLAG").isEmpty()) {
@@ -1090,9 +1089,9 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
{
QString ofile = fileFixify(Option::output.fileName());
if(!ofile.isEmpty())
- t << "\t-$(DEL_FILE) " << escapeFilePath(ofile) << endl;
+ t << "\t-$(DEL_FILE) " << escapeFilePath(ofile) << Qt::endl;
}
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
t << "####### Sub-libraries\n\n";
if (!project->values("SUBLIBS").isEmpty()) {
@@ -1103,7 +1102,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
for (it = l.begin(); it != l.end(); ++it)
t << escapeDependencyPath(libdir + project->first("QMAKE_PREFIX_STATICLIB") + (*it) + '.'
+ project->first("QMAKE_EXTENSION_STATICLIB")) << ":\n\t"
- << var(ProKey("MAKELIB" + *it)) << endl << endl;
+ << var(ProKey("MAKELIB" + *it)) << Qt::endl << Qt::endl;
}
if(doPrecompiledHeaders() && !project->isEmpty("PRECOMPILED_HEADER")) {
@@ -1187,7 +1186,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
compilerExecutable = "$(CXX)";
// compile command
- t << "\n\t" << compilerExecutable << cflags << " $(INCPATH) " << pchArchFlags << endl << endl;
+ t << "\n\t" << compilerExecutable << cflags << " $(INCPATH) " << pchArchFlags << Qt::endl << Qt::endl;
}
}
}
@@ -1491,7 +1490,7 @@ UnixMakefileGenerator::writeLibtoolFile()
ProStringList libs;
libs << "LIBS" << "QMAKE_LIBS";
t << "dependency_libs='";
- for (ProStringList::ConstIterator it = libs.begin(); it != libs.end(); ++it)
+ for (ProStringList::ConstIterator it = libs.cbegin(); it != libs.cend(); ++it)
t << fixLibFlags((*it).toKey()).join(' ') << ' ';
t << "'\n\n";
diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp
index de7363e51b..325823e1d9 100644
--- a/qmake/generators/win32/mingw_make.cpp
+++ b/qmake/generators/win32/mingw_make.cpp
@@ -38,10 +38,6 @@
QT_BEGIN_NAMESPACE
-MingwMakefileGenerator::MingwMakefileGenerator() : Win32MakefileGenerator()
-{
-}
-
QString MingwMakefileGenerator::escapeDependencyPath(const QString &path) const
{
QString ret = path;
@@ -99,7 +95,7 @@ bool MingwMakefileGenerator::writeMakefile(QTextStream &t)
writePkgConfigFile();
if(Option::mkfile::do_stub_makefile) {
- t << "QMAKE = " << var("QMAKE_QMAKE") << endl;
+ t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl;
const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
t << escapeDependencyPath(*it) << ' ';
@@ -148,7 +144,7 @@ void createLdResponseFile(const QString &fileName, const ProStringList &objList)
.replace(QLatin1Char('\t'), QLatin1String("\\\t"))
.replace(QLatin1Char('"'), QLatin1String("\\\""))
.replace(QLatin1Char('\''), QLatin1String("\\'"));
- t << path << endl;
+ t << path << Qt::endl;
}
t.flush();
file.close();
@@ -162,9 +158,9 @@ void createArObjectScriptFile(const QString &fileName, const QString &target, co
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream t(&file);
// ### quoting?
- t << "CREATE " << target << endl;
+ t << "CREATE " << target << Qt::endl;
for (ProStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) {
- t << "ADDMOD " << *it << endl;
+ t << "ADDMOD " << *it << Qt::endl;
}
t << "SAVE\n";
t.flush();
@@ -183,13 +179,13 @@ void MingwMakefileGenerator::writeMingwParts(QTextStream &t)
<< finalizeDependencyPaths(findDependencies(header)).join(" \\\n\t\t")
<< "\n\t" << mkdir_p_asstring(preCompHeaderOut)
<< "\n\t$(CC) -x c-header -c $(CFLAGS) $(INCPATH) -o " << escapeFilePath(cHeader)
- << ' ' << escapeFilePath(header) << endl << endl;
+ << ' ' << escapeFilePath(header) << Qt::endl << Qt::endl;
QString cppHeader = preCompHeaderOut + Option::dir_sep + "c++";
t << escapeDependencyPath(cppHeader) << ": " << escapeDependencyPath(header) << " "
<< finalizeDependencyPaths(findDependencies(header)).join(" \\\n\t\t")
<< "\n\t" << mkdir_p_asstring(preCompHeaderOut)
<< "\n\t$(CXX) -x c++-header -c $(CXXFLAGS) $(INCPATH) -o " << escapeFilePath(cppHeader)
- << ' ' << escapeFilePath(header) << endl << endl;
+ << ' ' << escapeFilePath(header) << Qt::endl << Qt::endl;
}
}
@@ -274,21 +270,21 @@ void MingwMakefileGenerator::writeIncPart(QTextStream &t)
t << "-I";
t << escapeFilePath(inc) << ' ';
}
- t << endl;
+ t << Qt::endl;
}
void MingwMakefileGenerator::writeLibsPart(QTextStream &t)
{
if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") {
- t << "LIB = " << var("QMAKE_LIB") << endl;
+ t << "LIB = " << var("QMAKE_LIB") << Qt::endl;
} else {
- t << "LINKER = " << var("QMAKE_LINK") << endl;
- t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
+ t << "LINKER = " << var("QMAKE_LINK") << Qt::endl;
+ t << "LFLAGS = " << var("QMAKE_LFLAGS") << Qt::endl;
t << "LIBS = "
<< fixLibFlags("LIBS").join(' ') << ' '
<< fixLibFlags("LIBS_PRIVATE").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS").join(' ') << ' '
- << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl;
+ << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << Qt::endl;
}
}
@@ -350,7 +346,7 @@ void MingwMakefileGenerator::writeBuildRulesPart(QTextStream &t)
}
if(!project->isEmpty("QMAKE_POST_LINK"))
t << "\n\t" <<var("QMAKE_POST_LINK");
- t << endl;
+ t << Qt::endl;
}
void MingwMakefileGenerator::writeRcFilePart(QTextStream &t)
diff --git a/qmake/generators/win32/mingw_make.h b/qmake/generators/win32/mingw_make.h
index 5da5b24088..8cae28a78b 100644
--- a/qmake/generators/win32/mingw_make.h
+++ b/qmake/generators/win32/mingw_make.h
@@ -35,9 +35,6 @@ QT_BEGIN_NAMESPACE
class MingwMakefileGenerator : public Win32MakefileGenerator
{
-public:
- MingwMakefileGenerator();
- ~MingwMakefileGenerator();
protected:
using MakefileGenerator::escapeDependencyPath;
QString escapeDependencyPath(const QString &path) const override;
@@ -65,9 +62,6 @@ private:
QString objectsLinkLine;
};
-inline MingwMakefileGenerator::~MingwMakefileGenerator()
-{ }
-
QT_END_NAMESPACE
#endif // MINGW_MAKE_H
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index 87cd560552..3116238aa0 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -34,7 +34,7 @@
#include <qscopedpointer.h>
#include <qstringlist.h>
#include <qfileinfo.h>
-#include <qversionnumber.h>
+#include <qregexp.h>
QT_BEGIN_NAMESPACE
@@ -626,31 +626,17 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
<< tagValue("RootNamespace", tool.Name)
<< tagValue("Keyword", tool.Keyword);
- QString windowsTargetPlatformVersion;
if (isWinRT) {
xml << tagValue("MinimumVisualStudioVersion", tool.Version)
<< tagValue("DefaultLanguage", "en")
<< tagValue("AppContainerApplication", "true")
<< tagValue("ApplicationType", "Windows Store")
<< tagValue("ApplicationTypeRevision", tool.SdkVersion);
- if (tool.SdkVersion == "10.0")
- windowsTargetPlatformVersion = qgetenv("UCRTVERSION");
- } else {
- QByteArray winSDKVersionStr = qgetenv("WindowsSDKVersion").trimmed();
-
- // This environment variable might end with a backslash due to a VS bug.
- if (winSDKVersionStr.endsWith('\\'))
- winSDKVersionStr.chop(1);
-
- QVersionNumber winSDKVersion = QVersionNumber::fromString(
- QString::fromLocal8Bit(winSDKVersionStr));
- if (!winSDKVersion.isNull())
- windowsTargetPlatformVersion = winSDKVersionStr;
- }
- if (!windowsTargetPlatformVersion.isEmpty()) {
- xml << tagValue("WindowsTargetPlatformVersion", windowsTargetPlatformVersion)
- << tagValue("WindowsTargetPlatformMinVersion", windowsTargetPlatformVersion);
}
+ if (!tool.WindowsTargetPlatformVersion.isEmpty())
+ xml << tagValue("WindowsTargetPlatformVersion", tool.WindowsTargetPlatformVersion);
+ if (!tool.WindowsTargetPlatformMinVersion.isEmpty())
+ xml << tagValue("WindowsTargetPlatformMinVersion", tool.WindowsTargetPlatformMinVersion);
xml << closetag();
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index f295705e2e..1f6223f01d 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -38,11 +38,6 @@
QT_BEGIN_NAMESPACE
-NmakeMakefileGenerator::NmakeMakefileGenerator() : usePCH(false), usePCHC(false)
-{
-
-}
-
bool
NmakeMakefileGenerator::writeMakefile(QTextStream &t)
{
@@ -143,7 +138,7 @@ void NmakeMakefileGenerator::writeNmakeParts(QTextStream &t)
t << escapeDependencyPath(precompObj) << ": " << escapeDependencyPath(precompH) << ' '
<< finalizeDependencyPaths(findDependencies(precompH)).join(" \\\n\t\t")
<< "\n\t$(CXX) " + precompRule +" $(CXXFLAGS) $(INCPATH) -TP "
- << escapeFilePath(precompH) << endl << endl;
+ << escapeFilePath(precompH) << Qt::endl << Qt::endl;
}
if (usePCHC) {
QString precompRuleC = QString("-c -Yc -Fp%1 -Fo%2")
@@ -151,7 +146,7 @@ void NmakeMakefileGenerator::writeNmakeParts(QTextStream &t)
t << escapeDependencyPath(precompObjC) << ": " << escapeDependencyPath(precompH) << ' '
<< finalizeDependencyPaths(findDependencies(precompH)).join(" \\\n\t\t")
<< "\n\t$(CC) " + precompRuleC +" $(CFLAGS) $(INCPATH) -TC "
- << escapeFilePath(precompH) << endl << endl;
+ << escapeFilePath(precompH) << Qt::endl << Qt::endl;
}
}
@@ -165,21 +160,17 @@ QString NmakeMakefileGenerator::var(const ProKey &value) const
|| value == "QMAKE_RUN_CXX_IMP"
|| value == "QMAKE_RUN_CXX");
if ((isRunCpp && usePCH) || (isRunC && usePCHC)) {
- QFileInfo precompHInfo(fileInfo(precompH));
- QString precompH_f = escapeFilePath(precompHInfo.fileName());
+ QString precompH_f = escapeFilePath(fileFixify(precompH, FileFixifyBackwards));
QString precompRule = QString("-c -FI%1 -Yu%2 -Fp%3")
.arg(precompH_f, precompH_f, escapeFilePath(isRunC ? precompPchC : precompPch));
+ // ### For clang_cl 8 we force inline methods to be compiled here instead
+ // linking them from a pch.o file. We do this by pretending we are also doing
+ // the pch.o generation step.
+ if (project->isActiveConfig("clang_cl"))
+ precompRule += QString(" -Xclang -building-pch-with-obj");
QString p = MakefileGenerator::var(value);
p.replace(QLatin1String("-c"), precompRule);
- // Cannot use -Gm with -FI & -Yu, as this gives an
- // internal compiler error, on the newer compilers
- // ### work-around for a VS 2003 bug. Move to some prf file or remove completely.
- p.remove("-Gm");
return p;
- } else if (value == "QMAKE_CXXFLAGS") {
- // Remove internal compiler error option
- // ### work-around for a VS 2003 bug. Move to some prf file or remove completely.
- return MakefileGenerator::var(value).remove("-Gm");
}
}
@@ -238,7 +229,10 @@ void NmakeMakefileGenerator::init()
precompObj = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch" + Option::obj_ext;
precompPch = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch.pch";
// Add linking of precompObj (required for whole precompiled classes)
- project->values("OBJECTS") += precompObj;
+ // ### For clang_cl we currently let inline methods be generated in the normal objects,
+ // since the PCH object is buggy (as of clang 8.0.0)
+ if (!project->isActiveConfig("clang_cl"))
+ project->values("OBJECTS") += precompObj;
// Add pch file to cleanup
project->values("QMAKE_CLEAN") += precompPch;
// Return to variable pool
@@ -248,7 +242,8 @@ void NmakeMakefileGenerator::init()
if (usePCHC) {
precompObjC = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch_c" + Option::obj_ext;
precompPchC = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch_c.pch";
- project->values("OBJECTS") += precompObjC;
+ if (!project->isActiveConfig("clang_cl"))
+ project->values("OBJECTS") += precompObjC;
project->values("QMAKE_CLEAN") += precompPchC;
project->values("PRECOMPILED_OBJECT_C") = ProStringList(precompObjC);
project->values("PRECOMPILED_PCH_C") = ProStringList(precompPchC);
@@ -314,7 +309,7 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t)
t << " " << (*cit);
for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit)
t << " " << (*cppit);
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
bool useInferenceRules = !project->isActiveConfig("no_batch");
QSet<QString> source_directories;
@@ -346,7 +341,7 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t)
QHash<QString, QString> fileNames;
bool duplicatesFound = false;
const QStringList sourceFilesFilter = sourceFilesForImplicitRulesFilter();
- QStringList fixifiedSourceDirs = fileFixify(source_directories.toList(), FileFixifyAbsolute);
+ QStringList fixifiedSourceDirs = fileFixify(QList<QString>(source_directories.constBegin(), source_directories.constEnd()), FileFixifyAbsolute);
fixifiedSourceDirs.removeDuplicates();
for (const QString &sourceDir : qAsConst(fixifiedSourceDirs)) {
QDirIterator dit(sourceDir, sourceFilesFilter, QDir::Files | QDir::NoDotAndDotDot);
@@ -393,9 +388,9 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t)
}
} else {
for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit)
- t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl;
+ t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << Qt::endl << Qt::endl;
for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit)
- t << (*cit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl;
+ t << (*cit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << Qt::endl << Qt::endl;
}
}
@@ -498,7 +493,7 @@ void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t)
if(!project->isEmpty("QMAKE_POST_LINK")) {
t << "\n\t" << var("QMAKE_POST_LINK");
}
- t << endl;
+ t << Qt::endl;
}
void NmakeMakefileGenerator::writeLinkCommand(QTextStream &t, const QString &extraFlags, const QString &extraInlineFileContent)
diff --git a/qmake/generators/win32/msvc_nmake.h b/qmake/generators/win32/msvc_nmake.h
index 5bfdba2bbc..3064f06521 100644
--- a/qmake/generators/win32/msvc_nmake.h
+++ b/qmake/generators/win32/msvc_nmake.h
@@ -54,17 +54,10 @@ protected:
QString var(const ProKey &value) const override;
QString precompH, precompObj, precompPch;
QString precompObjC, precompPchC;
- bool usePCH, usePCHC;
-
-public:
- NmakeMakefileGenerator();
- ~NmakeMakefileGenerator();
-
+ bool usePCH = false;
+ bool usePCHC = false;
};
-inline NmakeMakefileGenerator::~NmakeMakefileGenerator()
-{ }
-
QT_END_NAMESPACE
#endif // MSVC_NMAKE_H
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp
index 68f62c8dda..b6fe683d2c 100644
--- a/qmake/generators/win32/msvc_objectmodel.cpp
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -34,6 +34,7 @@
#include <qscopedpointer.h>
#include <qfileinfo.h>
+#include <qregexp.h>
using namespace QMakeInternal;
@@ -2223,8 +2224,49 @@ void VCFilter::addFiles(const ProStringList& fileList)
void VCFilter::modifyPCHstage(QString str)
{
- bool autogenSourceFile = Project->autogenPrecompCPP;
- bool pchThroughSourceFile = !Project->precompCPP.isEmpty();
+ const bool isHFile = (str == Project->precompH);
+ const bool pchThroughSourceFile = !Project->precompSource.isEmpty();
+ if (isHFile && pchThroughSourceFile && Project->autogenPrecompSource) {
+ useCustomBuildTool = true;
+ QString toFile(Project->precompSource);
+ CustomBuildTool.Description = "Generating precompiled header source file '" + toFile + "' ...";
+ CustomBuildTool.Outputs += toFile;
+
+ QStringList lines;
+ CustomBuildTool.CommandLine +=
+ "echo /*-------------------------------------------------------------------- >" + toFile;
+ lines << "* Precompiled header source file used by Visual Studio.NET to generate";
+ lines << "* the .pch file.";
+ lines << "*";
+ lines << "* Due to issues with the dependencies checker within the IDE, it";
+ lines << "* sometimes fails to recompile the PCH file, if we force the IDE to";
+ lines << "* create the PCH file directly from the header file.";
+ lines << "*";
+ lines << "* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was";
+ lines << "* specified, and is used as the common stdafx.cpp. The file is only";
+ lines << QLatin1String("* generated when creating ")
+ + (Config->CompilerVersion < NET2010 ? ".vcproj" : ".vcxproj")
+ + " project files, and is not used for";
+ lines << "* command line compilations by nmake.";
+ lines << "*";
+ lines << "* WARNING: All changes made in this file will be lost.";
+ lines << "--------------------------------------------------------------------*/";
+ lines << "#include \"" + Project->precompHFilename + "\"";
+ for (const QString &line : qAsConst(lines))
+ CustomBuildTool.CommandLine += "echo " + line + ">>" + toFile;
+ return;
+ }
+
+ useCompilerTool = true;
+ const bool isPrecompSource = pchThroughSourceFile && (str == Project->precompSource);
+ if (isPrecompSource) {
+ CompilerTool.UsePrecompiledHeader = pchCreateUsingSpecific;
+ if (Project->autogenPrecompSource)
+ CompilerTool.PrecompiledHeaderThrough = Project->precompHFilename;
+ CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)");
+ return;
+ }
+
bool isCFile = false;
for (QStringList::Iterator it = Option::c_ext.begin(); it != Option::c_ext.end(); ++it) {
if (str.endsWith(*it)) {
@@ -2232,53 +2274,13 @@ void VCFilter::modifyPCHstage(QString str)
break;
}
}
- const bool isHFile = (str == Project->precompH);
- bool isCPPFile = pchThroughSourceFile && (str == Project->precompCPP);
-
- if(!isCFile && !isHFile && !isCPPFile)
- return;
-
- if(isHFile && pchThroughSourceFile) {
- if (autogenSourceFile) {
- useCustomBuildTool = true;
- QString toFile(Project->precompCPP);
- CustomBuildTool.Description = "Generating precompiled header source file '" + toFile + "' ...";
- CustomBuildTool.Outputs += toFile;
-
- QStringList lines;
- CustomBuildTool.CommandLine +=
- "echo /*-------------------------------------------------------------------- >" + toFile;
- lines << "* Precompiled header source file used by Visual Studio.NET to generate";
- lines << "* the .pch file.";
- lines << "*";
- lines << "* Due to issues with the dependencies checker within the IDE, it";
- lines << "* sometimes fails to recompile the PCH file, if we force the IDE to";
- lines << "* create the PCH file directly from the header file.";
- lines << "*";
- lines << "* This file is auto-generated by qmake since no PRECOMPILED_SOURCE was";
- lines << "* specified, and is used as the common stdafx.cpp. The file is only";
- lines << QLatin1String("* generated when creating ")
- + (Config->CompilerVersion < NET2010 ? ".vcproj" : ".vcxproj")
- + " project files, and is not used for";
- lines << "* command line compilations by nmake.";
- lines << "*";
- lines << "* WARNING: All changes made in this file will be lost.";
- lines << "--------------------------------------------------------------------*/";
- lines << "#include \"" + Project->precompHFilename + "\"";
- for (const QString &line : qAsConst(lines))
- CustomBuildTool.CommandLine += "echo " + line + ">>" + toFile;
- }
- return;
- }
- useCompilerTool = true;
- // Setup PCH options
- CompilerTool.UsePrecompiledHeader = (isCFile ? pchNone : pchCreateUsingSpecific);
- if (isCFile)
+ bool pchCompatible = (isCFile == Project->pchIsCFile);
+ if (!pchCompatible) {
+ CompilerTool.UsePrecompiledHeader = pchNone;
CompilerTool.PrecompiledHeaderThrough = QLatin1String("$(NOINHERIT)");
- else if (autogenSourceFile)
- CompilerTool.PrecompiledHeaderThrough = Project->precompHFilename;
- CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)");
+ CompilerTool.ForcedIncludeFiles = QStringList("$(NOINHERIT)");
+ }
}
VCFilterFile VCFilter::findFile(const QString &filePath, bool *found) const
diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h
index f6d1fc8023..33eff0d914 100644
--- a/qmake/generators/win32/msvc_objectmodel.h
+++ b/qmake/generators/win32/msvc_objectmodel.h
@@ -923,7 +923,7 @@ struct VCFilterFile
inline QDebug operator<<(QDebug dbg, const VCFilterFile &p)
{
dbg.nospace() << "VCFilterFile(file(" << p.file
- << ") excludeFromBuild(" << p.excludeFromBuild << "))" << endl;
+ << ") excludeFromBuild(" << p.excludeFromBuild << "))" << Qt::endl;
return dbg.space();
}
#endif
@@ -1125,6 +1125,8 @@ public:
QString SccLocalPath;
QString PlatformName;
QString SdkVersion;
+ QString WindowsTargetPlatformVersion;
+ QString WindowsTargetPlatformMinVersion;
// Single projects
QList<VCProjectSingleConfig> SingleProjects;
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index 0115dc1313..b6f7f20564 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -193,6 +193,10 @@ bool VcprojGenerator::writeProjectMakefile()
mergedProject.SccProjectName = mergedProjects.at(0)->vcProject.SccProjectName;
mergedProject.SccLocalPath = mergedProjects.at(0)->vcProject.SccLocalPath;
mergedProject.PlatformName = mergedProjects.at(0)->vcProject.PlatformName;
+ mergedProject.WindowsTargetPlatformVersion =
+ project->first("WINDOWS_TARGET_PLATFORM_VERSION").toQString();
+ mergedProject.WindowsTargetPlatformMinVersion =
+ project->first("WINDOWS_TARGET_PLATFORM_MIN_VERSION").toQString();
XmlOutput xmlOut(t);
projectWriter->write(xmlOut, mergedProject);
@@ -477,8 +481,8 @@ ProStringList VcprojGenerator::collectDependencies(QMakeProject *proj, QHash<QSt
// Add all unknown libs to the deps
QStringList where = QStringList() << "LIBS" << "LIBS_PRIVATE"
<< "QMAKE_LIBS" << "QMAKE_LIBS_PRIVATE";
- for (QStringList::ConstIterator wit = where.begin();
- wit != where.end(); ++wit) {
+ for (QStringList::ConstIterator wit = where.cbegin();
+ wit != where.cend(); ++wit) {
const ProStringList &l = tmp_proj.values(ProKey(*wit));
for (ProStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
const QString opt = fixLibFlag(*it).toQString();
@@ -778,8 +782,9 @@ void VcprojGenerator::init()
// Setup PCH variables
precompH = project->first("PRECOMPILED_HEADER").toQString();
- precompCPP = project->first("PRECOMPILED_SOURCE").toQString();
- usePCH = !precompH.isEmpty() && project->isActiveConfig("precompile_header");
+ precompSource = project->first("PRECOMPILED_SOURCE").toQString();
+ pchIsCFile = project->isActiveConfig("precompile_header_c");
+ usePCH = !precompH.isEmpty() && (pchIsCFile || project->isActiveConfig("precompile_header"));
if (usePCH) {
precompHFilename = fileInfo(precompH).fileName();
// Created files
@@ -793,13 +798,15 @@ void VcprojGenerator::init()
project->values("PRECOMPILED_OBJECT") = ProStringList(precompObj);
project->values("PRECOMPILED_PCH") = ProStringList(precompPch);
- autogenPrecompCPP = precompCPP.isEmpty() && project->isActiveConfig("autogen_precompile_source");
- if (autogenPrecompCPP) {
- precompCPP = precompH
- + (Option::cpp_ext.count() ? Option::cpp_ext.at(0) : QLatin1String(".cpp"));
- project->values("GENERATED_SOURCES") += precompCPP;
- } else if (!precompCPP.isEmpty()) {
- project->values("SOURCES") += precompCPP;
+ autogenPrecompSource = precompSource.isEmpty() && project->isActiveConfig("autogen_precompile_source");
+ if (autogenPrecompSource) {
+ precompSource = precompH
+ + (pchIsCFile
+ ? (Option::c_ext.count() ? Option::c_ext.at(0) : QLatin1String(".c"))
+ : (Option::cpp_ext.count() ? Option::cpp_ext.at(0) : QLatin1String(".cpp")));
+ project->values("GENERATED_SOURCES") += precompSource;
+ } else if (!precompSource.isEmpty()) {
+ project->values("SOURCES") += precompSource;
}
}
@@ -1056,16 +1063,6 @@ void VcprojGenerator::initCompilerTool()
conf.compiler.PrecompiledHeaderFile = "$(IntDir)\\" + precompPch;
conf.compiler.PrecompiledHeaderThrough = project->first("PRECOMPILED_HEADER").toQString();
conf.compiler.ForcedIncludeFiles = project->values("PRECOMPILED_HEADER").toQStringList();
-
- if (conf.CompilerVersion <= NET2003) {
- // Minimal build option triggers an Internal Compiler Error
- // when used in conjunction with /FI and /Yu, so remove it
- // ### work-around for a VS 2003 bug. Move to some prf file or remove completely.
- project->values("QMAKE_CFLAGS_DEBUG").removeAll("-Gm");
- project->values("QMAKE_CFLAGS_DEBUG").removeAll("/Gm");
- project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("-Gm");
- project->values("QMAKE_CXXFLAGS_DEBUG").removeAll("/Gm");
- }
}
conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS"));
diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h
index e87eb733fc..8f38252274 100644
--- a/qmake/generators/win32/msvc_vcproj.h
+++ b/qmake/generators/win32/msvc_vcproj.h
@@ -57,15 +57,16 @@ public:
~VcprojGenerator();
QString defaultMakefile() const;
- QString precompH, precompHFilename, precompCPP,
+ QString precompH, precompHFilename, precompSource,
precompObj, precompPch;
- bool autogenPrecompCPP;
+ bool autogenPrecompSource;
static bool hasBuiltinCompiler(const QString &file);
QHash<QString, QStringList> extraCompilerSources;
QHash<QString, QString> extraCompilerOutputs;
const QString customBuildToolFilterFileSuffix;
bool usePCH;
+ bool pchIsCFile = false;
VCProjectWriter *projectWriter;
protected:
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
index cc612921f7..b79fd8f250 100644
--- a/qmake/generators/win32/winmakefile.cpp
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -40,10 +40,6 @@
QT_BEGIN_NAMESPACE
-Win32MakefileGenerator::Win32MakefileGenerator() : MakefileGenerator()
-{
-}
-
ProString Win32MakefileGenerator::fixLibFlag(const ProString &lib)
{
if (lib.startsWith("-l")) // Fallback for unresolved -l libs.
@@ -116,8 +112,8 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
goto found;
}
QString libBase = (*dir_it).local() + '/' + lib + verovr;
- for (ProStringList::ConstIterator extit = impexts.begin();
- extit != impexts.end(); ++extit) {
+ for (ProStringList::ConstIterator extit = impexts.cbegin();
+ extit != impexts.cend(); ++extit) {
if (exists(libBase + '.' + *extit)) {
(*it) = cand + verovr + '.' + *extit;
goto found;
@@ -320,11 +316,11 @@ void Win32MakefileGenerator::processRcFileVar()
int rcCodePage = project->intValue("RC_CODEPAGE", 1200); // default: Unicode
ts << "#include <windows.h>\n";
- ts << endl;
+ ts << Qt::endl;
if (!rcIcons.isEmpty()) {
for (int i = 0; i < rcIcons.size(); ++i)
- ts << QString("IDI_ICON%1\tICON\tDISCARDABLE\t%2").arg(i + 1).arg(cQuoted(rcIcons[i])) << endl;
- ts << endl;
+ ts << QString("IDI_ICON%1\tICON\tDISCARDABLE\t%2").arg(i + 1).arg(cQuoted(rcIcons[i])) << Qt::endl;
+ ts << Qt::endl;
}
if (!manifestFile.isEmpty()) {
QString manifestResourceId;
@@ -335,8 +331,8 @@ void Win32MakefileGenerator::processRcFileVar()
ts << manifestResourceId << " RT_MANIFEST \"" << manifestFile << "\"\n";
}
ts << "VS_VERSION_INFO VERSIONINFO\n";
- ts << "\tFILEVERSION " << QString(versionString).replace(".", ",") << endl;
- ts << "\tPRODUCTVERSION " << QString(versionString).replace(".", ",") << endl;
+ ts << "\tFILEVERSION " << QString(versionString).replace(".", ",") << Qt::endl;
+ ts << "\tPRODUCTVERSION " << QString(versionString).replace(".", ",") << Qt::endl;
ts << "\tFILEFLAGSMASK 0x3fL\n";
ts << "#ifdef _DEBUG\n";
ts << "\tFILEFLAGS VS_FF_DEBUG\n";
@@ -369,11 +365,11 @@ void Win32MakefileGenerator::processRcFileVar()
ts << "\t\tBEGIN\n";
ts << "\t\t\tVALUE \"Translation\", "
<< QString("0x%1").arg(rcLang, 4, 16, QLatin1Char('0'))
- << ", " << QString("%1").arg(rcCodePage, 4) << endl;
+ << ", " << QString("%1").arg(rcCodePage, 4) << Qt::endl;
ts << "\t\tEND\n";
ts << "\tEND\n";
ts << "/* End of Version info */\n";
- ts << endl;
+ ts << Qt::endl;
ts.flush();
@@ -470,7 +466,7 @@ void Win32MakefileGenerator::writeCleanParts(QTextStream &t)
}
}
}
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
t << "distclean: clean " << depVar("DISTCLEAN_DEPS");
{
@@ -503,9 +499,9 @@ void Win32MakefileGenerator::writeCleanParts(QTextStream &t)
{
QString ofile = fileFixify(Option::output.fileName());
if(!ofile.isEmpty())
- t << "\t-$(DEL_FILE) " << escapeFilePath(ofile) << endl;
+ t << "\t-$(DEL_FILE) " << escapeFilePath(ofile) << Qt::endl;
}
- t << endl;
+ t << Qt::endl;
}
void Win32MakefileGenerator::writeIncPart(QTextStream &t)
@@ -519,7 +515,7 @@ void Win32MakefileGenerator::writeIncPart(QTextStream &t)
if(!inc.isEmpty())
t << "-I" << escapeFilePath(inc) << ' ';
}
- t << endl;
+ t << Qt::endl;
}
void Win32MakefileGenerator::writeStandardParts(QTextStream &t)
@@ -527,51 +523,29 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t)
writeExportedVariables(t);
t << "####### Compiler, tools and options\n\n";
- t << "CC = " << var("QMAKE_CC") << endl;
- t << "CXX = " << var("QMAKE_CXX") << endl;
+ t << "CC = " << var("QMAKE_CC") << Qt::endl;
+ t << "CXX = " << var("QMAKE_CXX") << Qt::endl;
t << "DEFINES = "
<< varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
- << varGlue("DEFINES","-D"," -D","") << endl;
+ << varGlue("DEFINES","-D"," -D","") << Qt::endl;
t << "CFLAGS = " << var("QMAKE_CFLAGS") << " $(DEFINES)\n";
t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " $(DEFINES)\n";
writeIncPart(t);
writeLibsPart(t);
-
- t << "QMAKE = " << var("QMAKE_QMAKE") << endl;
- t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") : var("QMAKE_IDC"))
- << endl;
- t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") : var("QMAKE_IDL"))
- << endl;
- t << "ZIP = " << var("QMAKE_ZIP") << endl;
- t << "DEF_FILE = " << fileVar("DEF_FILE") << endl;
- t << "RES_FILE = " << fileVar("RES_FILE") << endl; // Not on mingw, can't see why not though...
- t << "COPY = " << var("QMAKE_COPY") << endl;
- t << "SED = " << var("QMAKE_STREAM_EDITOR") << endl;
- t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << endl;
- t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl;
- t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
- t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl;
- t << "MOVE = " << var("QMAKE_MOVE") << endl;
- t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl;
- t << "MKDIR = " << var("QMAKE_MKDIR") << endl;
- t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl;
- t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl;
- t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl;
- t << "QINSTALL = " << var("QMAKE_QMAKE") << " -install qinstall" << endl;
- t << "QINSTALL_PROGRAM = " << var("QMAKE_QMAKE") << " -install qinstall -exe" << endl;
- t << endl;
+ writeDefaultVariables(t);
+ t << Qt::endl;
t << "####### Output directory\n\n";
if(!project->values("OBJECTS_DIR").isEmpty())
- t << "OBJECTS_DIR = " << escapeFilePath(var("OBJECTS_DIR").remove(QRegExp("\\\\$"))) << endl;
+ t << "OBJECTS_DIR = " << escapeFilePath(var("OBJECTS_DIR").remove(QRegExp("\\\\$"))) << Qt::endl;
else
t << "OBJECTS_DIR = . \n";
- t << endl;
+ t << Qt::endl;
t << "####### Files\n\n";
t << "SOURCES = " << valList(escapeFilePaths(project->values("SOURCES")))
- << " " << valList(escapeFilePaths(project->values("GENERATED_SOURCES"))) << endl;
+ << " " << valList(escapeFilePaths(project->values("GENERATED_SOURCES"))) << Qt::endl;
// do this here so we can set DEST_TARGET to be the complete path to the final target if it is needed.
QString orgDestDir = var("DESTDIR");
@@ -587,14 +561,14 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t)
writeExtraVariables(t);
t << "DIST = " << fileVarList("DISTFILES") << ' '
- << fileVarList("HEADERS") << ' ' << fileVarList("SOURCES") << endl;
- t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << endl; // unused
+ << fileVarList("HEADERS") << ' ' << fileVarList("SOURCES") << Qt::endl;
+ t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << Qt::endl; // unused
// The comment is important to maintain variable compatibility with Unix
// Makefiles, while not interpreting a trailing-slash as a linebreak
t << "DESTDIR = " << escapeFilePath(destDir) << " #avoid trailing-slash linebreak\n";
- t << "TARGET = " << escapeFilePath(target) << endl;
- t << "DESTDIR_TARGET = " << fileVar("DEST_TARGET") << endl;
- t << endl;
+ t << "TARGET = " << escapeFilePath(target) << Qt::endl;
+ t << "DESTDIR_TARGET = " << fileVar("DEST_TARGET") << Qt::endl;
+ t << Qt::endl;
writeImplicitRulesPart(t);
@@ -606,10 +580,10 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t)
const ProStringList &dlldirs = project->values("DLLDESTDIR");
for (ProStringList::ConstIterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir) {
t << "\t-$(COPY_FILE) $(DESTDIR_TARGET) "
- << escapeFilePath(Option::fixPathToTargetOS((*dlldir).toQString(), false)) << endl;
+ << escapeFilePath(Option::fixPathToTargetOS((*dlldir).toQString(), false)) << Qt::endl;
}
}
- t << endl;
+ t << Qt::endl;
writeRcFilePart(t);
}
@@ -642,33 +616,33 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t)
}
}
}
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
writeCleanParts(t);
writeExtraTargets(t);
writeExtraCompilerTargets(t);
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
}
void Win32MakefileGenerator::writeLibsPart(QTextStream &t)
{
if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") {
- t << "LIBAPP = " << var("QMAKE_LIB") << endl;
- t << "LIBFLAGS = " << var("QMAKE_LIBFLAGS") << endl;
+ t << "LIBAPP = " << var("QMAKE_LIB") << Qt::endl;
+ t << "LIBFLAGS = " << var("QMAKE_LIBFLAGS") << Qt::endl;
} else {
- t << "LINKER = " << var("QMAKE_LINK") << endl;
- t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
+ t << "LINKER = " << var("QMAKE_LINK") << Qt::endl;
+ t << "LFLAGS = " << var("QMAKE_LFLAGS") << Qt::endl;
t << "LIBS = " << fixLibFlags("LIBS").join(' ') << ' '
<< fixLibFlags("LIBS_PRIVATE").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS").join(' ') << ' '
- << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl;
+ << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << Qt::endl;
}
}
void Win32MakefileGenerator::writeObjectsPart(QTextStream &t)
{
// Used in both deps and commands.
- t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << endl;
+ t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << Qt::endl;
}
void Win32MakefileGenerator::writeImplicitRulesPart(QTextStream &)
@@ -710,7 +684,7 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t)
<< var("QMAKE_RC") << (project->isActiveConfig("debug") ? " -D_DEBUG" : "")
<< defines << incPathStr << " -fo " << escapeFilePath(res_file)
<< ' ' << escapeFilePath(rc_file);
- t << endl << endl;
+ t << Qt::endl << Qt::endl;
}
}
@@ -789,6 +763,20 @@ QString Win32MakefileGenerator::defaultInstall(const QString &t)
return ret;
}
+void Win32MakefileGenerator::writeDefaultVariables(QTextStream &t)
+{
+ MakefileGenerator::writeDefaultVariables(t);
+ t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") : var("QMAKE_IDC"))
+ << Qt::endl;
+ t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") : var("QMAKE_IDL"))
+ << Qt::endl;
+ t << "ZIP = " << var("QMAKE_ZIP") << Qt::endl;
+ t << "DEF_FILE = " << fileVar("DEF_FILE") << Qt::endl;
+ t << "RES_FILE = " << fileVar("RES_FILE") << Qt::endl; // Not on mingw, can't see why not though...
+ t << "SED = " << var("QMAKE_STREAM_EDITOR") << Qt::endl;
+ t << "MOVE = " << var("QMAKE_MOVE") << Qt::endl;
+}
+
QString Win32MakefileGenerator::escapeFilePath(const QString &path) const
{
QString ret = path;
diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h
index 4416951a09..8eb633fdfa 100644
--- a/qmake/generators/win32/winmakefile.h
+++ b/qmake/generators/win32/winmakefile.h
@@ -35,11 +35,9 @@ QT_BEGIN_NAMESPACE
class Win32MakefileGenerator : public MakefileGenerator
{
-public:
- Win32MakefileGenerator();
- ~Win32MakefileGenerator();
protected:
QString defaultInstall(const QString &) override;
+ void writeDefaultVariables(QTextStream &t) override;
virtual void writeCleanParts(QTextStream &t);
virtual void writeStandardParts(QTextStream &t);
virtual void writeIncPart(QTextStream &t);
@@ -68,9 +66,6 @@ protected:
virtual QString getManifestFileForRcFile() const;
};
-inline Win32MakefileGenerator::~Win32MakefileGenerator()
-{ }
-
QT_END_NAMESPACE
#endif // WINMAKEFILE_H
diff --git a/qmake/generators/xmloutput.cpp b/qmake/generators/xmloutput.cpp
index e92749a126..2f48763550 100644
--- a/qmake/generators/xmloutput.cpp
+++ b/qmake/generators/xmloutput.cpp
@@ -237,7 +237,7 @@ void XmlOutput::newTagOpen(const QString &tag)
closeOpen();
if (format == NewLine)
- xmlFile << endl << currentIndent;
+ xmlFile << Qt::endl << currentIndent;
xmlFile << '<' << doConversion(tag);
currentState = Attribute;
tagStack.append(tag);
@@ -271,7 +271,7 @@ void XmlOutput::closeTag()
case Tag:
decreaseIndent(); // <--- Pre-decrease indent
if (format == NewLine)
- xmlFile << endl << currentIndent;
+ xmlFile << Qt::endl << currentIndent;
xmlFile << "</" << doConversion(tagStack.last()) << '>';
tagStack.pop_back();
break;
@@ -343,7 +343,7 @@ void XmlOutput::addAttribute(const QString &attribute, const QString &value)
break;
}
if (format == NewLine)
- xmlFile << endl;
+ xmlFile << Qt::endl;
xmlFile << currentIndent << doConversion(attribute) << "=\"" << doConversion(value) << "\"";
}
diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp
index 3e49a99cd5..d2171274d8 100644
--- a/qmake/library/ioutils.cpp
+++ b/qmake/library/ioutils.cpp
@@ -30,6 +30,7 @@
#include <qdir.h>
#include <qfile.h>
+#include <qregexp.h>
#ifdef Q_OS_WIN
# include <windows.h>
diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h
index 71e5e05367..6882f2802f 100644
--- a/qmake/library/proitems.h
+++ b/qmake/library/proitems.h
@@ -429,7 +429,7 @@ class ProFunctionDef {
public:
ProFunctionDef(ProFile *pro, int offset) : m_pro(pro), m_offset(offset) { m_pro->ref(); }
ProFunctionDef(const ProFunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); }
- ProFunctionDef(ProFunctionDef &&other) Q_DECL_NOTHROW
+ ProFunctionDef(ProFunctionDef &&other) noexcept
: m_pro(other.m_pro), m_offset(other.m_offset) { other.m_pro = nullptr; }
~ProFunctionDef() { m_pro->deref(); }
ProFunctionDef &operator=(const ProFunctionDef &o)
@@ -442,13 +442,13 @@ public:
}
return *this;
}
- ProFunctionDef &operator=(ProFunctionDef &&other) Q_DECL_NOTHROW
+ ProFunctionDef &operator=(ProFunctionDef &&other) noexcept
{
ProFunctionDef moved(std::move(other));
swap(moved);
return *this;
}
- void swap(ProFunctionDef &other) Q_DECL_NOTHROW
+ void swap(ProFunctionDef &other) noexcept
{
qSwap(m_pro, other.m_pro);
qSwap(m_offset, other.m_offset);
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index dd7766c8e0..866915bdfd 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -882,8 +882,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
ret += values(map(args.at(0)));
break;
case E_LIST: {
- QString tmp;
- tmp.sprintf(".QMAKE_INTERNAL_TMP_variableName_%d", m_listCount++);
+ QString tmp(QString::asprintf(".QMAKE_INTERNAL_TMP_variableName_%d", m_listCount++));
ret = ProStringList(ProString(tmp));
ProStringList lst;
for (const ProString &arg : args)
@@ -1458,15 +1457,15 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
case T_EXPORT: {
const ProKey &var = map(args.at(0));
- for (ProValueMapStack::Iterator vmi = m_valuemapStack.end();
+ for (ProValueMapStack::iterator vmi = m_valuemapStack.end();
--vmi != m_valuemapStack.begin(); ) {
ProValueMap::Iterator it = (*vmi).find(var);
if (it != (*vmi).end()) {
if (it->constBegin() == statics.fakeValue.constBegin()) {
// This is stupid, but qmake doesn't propagate deletions
- m_valuemapStack.first()[var] = ProStringList();
+ m_valuemapStack.front()[var] = ProStringList();
} else {
- m_valuemapStack.first()[var] = *it;
+ m_valuemapStack.front()[var] = *it;
}
(*vmi).erase(it);
while (--vmi != m_valuemapStack.begin())
@@ -1477,7 +1476,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnTrue;
}
case T_DISCARD_FROM: {
- if (m_valuemapStack.count() != 1) {
+ if (m_valuemapStack.size() != 1) {
evalError(fL1S("discard_from() cannot be called from functions."));
return ReturnFalse;
}
@@ -1487,7 +1486,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
int pro = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly);
if (!pro)
return ReturnFalse;
- ProValueMap &vmap = m_valuemapStack.first();
+ ProValueMap &vmap = m_valuemapStack.front();
for (auto vit = vmap.begin(); vit != vmap.end(); ) {
if (!vit->isEmpty()) {
auto isFrom = [pro](const ProString &s) {
@@ -1515,7 +1514,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
else
++fit;
}
- ProStringList &iif = m_valuemapStack.first()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")];
+ ProStringList &iif = m_valuemapStack.front()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")];
int idx = iif.indexOf(ProString(fn));
if (idx >= 0)
iif.removeAt(idx);
diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp
index 09c1f80222..ba617932ce 100644
--- a/qmake/library/qmakeevaluator.cpp
+++ b/qmake/library/qmakeevaluator.cpp
@@ -601,14 +601,16 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
case TokBypassNesting:
blockLen = getBlockLen(tokPtr);
if ((m_cumulative || okey != or_op) && blockLen) {
- ProValueMapStack savedValuemapStack = m_valuemapStack;
+ ProValueMapStack savedValuemapStack = std::move(m_valuemapStack);
m_valuemapStack.clear();
- m_valuemapStack.append(savedValuemapStack.takeFirst());
+ m_valuemapStack.splice(m_valuemapStack.end(),
+ savedValuemapStack, savedValuemapStack.begin());
traceMsg("visiting nesting-bypassing block");
ret = visitProBlock(tokPtr);
traceMsg("visited nesting-bypassing block");
- savedValuemapStack.prepend(m_valuemapStack.first());
- m_valuemapStack = savedValuemapStack;
+ savedValuemapStack.splice(savedValuemapStack.begin(),
+ m_valuemapStack, m_valuemapStack.begin());
+ m_valuemapStack = std::move(savedValuemapStack);
} else {
traceMsg("skipped nesting-bypassing block");
ret = ReturnTrue;
@@ -1203,7 +1205,7 @@ bool QMakeEvaluator::loadSpecInternal()
# ifdef Q_OS_UNIX
if (m_qmakespec.endsWith(QLatin1String("/default-host"))
|| m_qmakespec.endsWith(QLatin1String("/default"))) {
- QString rspec = QFileInfo(m_qmakespec).readLink();
+ QString rspec = QFileInfo(m_qmakespec).symLinkTarget();
if (!rspec.isEmpty())
m_qmakespec = QDir::cleanPath(QDir(m_qmakespec).absoluteFilePath(rspec));
}
@@ -1452,7 +1454,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
for (ProValueMap::ConstIterator it = m_extraVars.constBegin();
it != m_extraVars.constEnd(); ++it)
- m_valuemapStack.first().insert(it.key(), it.value());
+ m_valuemapStack.front().insert(it.key(), it.value());
// In case default_pre needs to make decisions based on the current
// build pass configuration.
@@ -1720,9 +1722,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFunction(
{
VisitReturn vr;
- if (m_valuemapStack.count() >= 100) {
+ if (m_valuemapStack.size() >= 100) {
evalError(fL1S("Ran into infinite recursion (depth > 100)."));
- vr = ReturnFalse;
+ vr = ReturnError;
} else {
m_valuemapStack.push(ProValueMap());
m_locationStack.push(m_current);
@@ -1872,7 +1874,7 @@ static bool isFunctParam(const ProKey &variableName)
ProValueMap *QMakeEvaluator::findValues(const ProKey &variableName, ProValueMap::Iterator *rit)
{
- ProValueMapStack::Iterator vmi = m_valuemapStack.end();
+ ProValueMapStack::iterator vmi = m_valuemapStack.end();
for (bool first = true; ; first = false) {
--vmi;
ProValueMap::Iterator it = (*vmi).find(variableName);
@@ -1899,7 +1901,7 @@ ProStringList &QMakeEvaluator::valuesRef(const ProKey &variableName)
return *it;
}
if (!isFunctParam(variableName)) {
- ProValueMapStack::Iterator vmi = m_valuemapStack.end();
+ ProValueMapStack::iterator vmi = m_valuemapStack.end();
if (--vmi != m_valuemapStack.begin()) {
do {
--vmi;
@@ -1918,7 +1920,7 @@ ProStringList &QMakeEvaluator::valuesRef(const ProKey &variableName)
ProStringList QMakeEvaluator::values(const ProKey &variableName) const
{
- ProValueMapStack::ConstIterator vmi = m_valuemapStack.constEnd();
+ ProValueMapStack::const_iterator vmi = m_valuemapStack.cend();
for (bool first = true; ; first = false) {
--vmi;
ProValueMap::ConstIterator it = (*vmi).constFind(variableName);
@@ -1927,7 +1929,7 @@ ProStringList QMakeEvaluator::values(const ProKey &variableName) const
break;
return *it;
}
- if (vmi == m_valuemapStack.constBegin())
+ if (vmi == m_valuemapStack.cbegin())
break;
if (first && isFunctParam(variableName))
break;
@@ -1955,7 +1957,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFile(
m_current = m_locationStack.pop();
pro->deref();
if (ok == ReturnTrue && !(flags & LoadHidden)) {
- ProStringList &iif = m_valuemapStack.first()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")];
+ ProStringList &iif = m_valuemapStack.front()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")];
ProString ifn(fileName);
if (!iif.contains(ifn))
iif << ifn;
@@ -2084,7 +2086,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFileInto(
return ret;
*values = visitor.m_valuemapStack.top();
ProKey qiif("QMAKE_INTERNAL_INCLUDED_FILES");
- ProStringList &iif = m_valuemapStack.first()[qiif];
+ ProStringList &iif = m_valuemapStack.front()[qiif];
const auto ifns = values->value(qiif);
for (const ProString &ifn : ifns)
if (!iif.contains(ifn))
diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h
index f617681cbb..9f702b9182 100644
--- a/qmake/library/qmakeevaluator.h
+++ b/qmake/library/qmakeevaluator.h
@@ -38,7 +38,6 @@
#include "ioutils.h"
#include <qlist.h>
-#include <qlinkedlist.h>
#include <qmap.h>
#include <qset.h>
#include <qstack.h>
@@ -54,6 +53,8 @@
# include <qmutex.h>
#endif
+#include <list>
+
QT_BEGIN_NAMESPACE
class QMakeGlobals;
@@ -94,15 +95,15 @@ public:
#endif
};
-// We use a QLinkedList based stack instead of a QVector based one (QStack), so that
+// We use a list-based stack instead of a vector-based one, so that
// the addresses of value maps stay constant. The qmake generators rely on that.
-class QMAKE_EXPORT ProValueMapStack : public QLinkedList<ProValueMap>
+class QMAKE_EXPORT ProValueMapStack : public std::list<ProValueMap>
{
public:
- inline void push(const ProValueMap &t) { append(t); }
- inline ProValueMap pop() { return takeLast(); }
- ProValueMap &top() { return last(); }
- const ProValueMap &top() const { return last(); }
+ inline void push(const ProValueMap &t) { push_back(t); }
+ inline ProValueMap pop() { auto r = std::move(back()); pop_back(); return r; }
+ ProValueMap &top() { return back(); }
+ const ProValueMap &top() const { return back(); }
};
namespace QMakeInternal { struct QMakeBuiltin; }
diff --git a/qmake/library/qmakeevaluator_p.h b/qmake/library/qmakeevaluator_p.h
index f888bc5765..da83ff0de2 100644
--- a/qmake/library/qmakeevaluator_p.h
+++ b/qmake/library/qmakeevaluator_p.h
@@ -31,8 +31,6 @@
#include "proitems.h"
-#include <qregexp.h>
-
#define debugMsg if (!m_debugLevel) {} else debugMsgInternal
#define traceMsg if (!m_debugLevel) {} else traceMsgInternal
#ifdef PROEVALUATOR_DEBUG
diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp
index daf4707779..1d76cecc45 100644
--- a/qmake/library/qmakeglobals.cpp
+++ b/qmake/library/qmakeglobals.cpp
@@ -38,7 +38,6 @@
#include <qfile.h>
#include <qfileinfo.h>
#include <qlist.h>
-#include <qregexp.h>
#include <qset.h>
#include <qstack.h>
#include <qstring.h>
diff --git a/qmake/project.cpp b/qmake/project.cpp
index 1bc9b352b5..931a337b71 100644
--- a/qmake/project.cpp
+++ b/qmake/project.cpp
@@ -143,15 +143,15 @@ ProString QMakeProject::expand(const QString &expr, const QString &where, int li
bool QMakeProject::isEmpty(const ProKey &v) const
{
- ProValueMap::ConstIterator it = m_valuemapStack.first().constFind(v);
- return it == m_valuemapStack.first().constEnd() || it->isEmpty();
+ ProValueMap::ConstIterator it = m_valuemapStack.front().constFind(v);
+ return it == m_valuemapStack.front().constEnd() || it->isEmpty();
}
void QMakeProject::dump() const
{
QStringList out;
- for (ProValueMap::ConstIterator it = m_valuemapStack.first().begin();
- it != m_valuemapStack.first().end(); ++it) {
+ for (ProValueMap::ConstIterator it = m_valuemapStack.front().begin();
+ it != m_valuemapStack.front().end(); ++it) {
if (!it.key().startsWith('.')) {
QString str = it.key() + " =";
for (const ProString &v : it.value())
diff --git a/qmake/project.h b/qmake/project.h
index d7a5852bed..071b62424f 100644
--- a/qmake/project.h
+++ b/qmake/project.h
@@ -58,12 +58,12 @@ public:
{ m_current.clear(); return evaluateConditional(QStringRef(&v), file, line) == ReturnTrue; }
bool test(const ProKey &func, const QList<ProStringList> &args);
- bool isSet(const ProKey &v) const { return m_valuemapStack.first().contains(v); }
+ bool isSet(const ProKey &v) const { return m_valuemapStack.front().contains(v); }
bool isEmpty(const ProKey &v) const;
ProStringList &values(const ProKey &v) { return valuesRef(v); }
int intValue(const ProKey &v, int defaultValue = 0) const;
- const ProValueMap &variables() const { return m_valuemapStack.first(); }
- ProValueMap &variables() { return m_valuemapStack.first(); }
+ const ProValueMap &variables() const { return m_valuemapStack.front(); }
+ ProValueMap &variables() { return m_valuemapStack.front(); }
bool isActiveConfig(const QString &config, bool regex = false)
{ return QMakeEvaluator::isActiveConfig(QStringRef(&config), regex); }
diff --git a/qmake/property.cpp b/qmake/property.cpp
index c0a3ec0dab..432ff55664 100644
--- a/qmake/property.cpp
+++ b/qmake/property.cpp
@@ -178,8 +178,8 @@ QMakeProperty::exec()
}
return true;
}
- for(QStringList::ConstIterator it = Option::prop::properties.begin();
- it != Option::prop::properties.end(); it++) {
+ for (QStringList::ConstIterator it = Option::prop::properties.cbegin();
+ it != Option::prop::properties.cend(); it++) {
if(Option::prop::properties.count() > 1)
fprintf(stdout, "%s:", (*it).toLatin1().constData());
const ProKey pkey(*it);
@@ -191,11 +191,11 @@ QMakeProperty::exec()
}
}
} else if(Option::qmake_mode == Option::QMAKE_SET_PROPERTY) {
- for(QStringList::ConstIterator it = Option::prop::properties.begin();
- it != Option::prop::properties.end(); it++) {
+ for (QStringList::ConstIterator it = Option::prop::properties.cbegin();
+ it != Option::prop::properties.cend(); it++) {
QString var = (*it);
it++;
- if(it == Option::prop::properties.end()) {
+ if (it == Option::prop::properties.cend()) {
ret = false;
break;
}
@@ -203,8 +203,8 @@ QMakeProperty::exec()
setValue(var, (*it));
}
} else if(Option::qmake_mode == Option::QMAKE_UNSET_PROPERTY) {
- for(QStringList::ConstIterator it = Option::prop::properties.begin();
- it != Option::prop::properties.end(); it++) {
+ for (QStringList::ConstIterator it = Option::prop::properties.cbegin();
+ it != Option::prop::properties.cend(); it++) {
QString var = (*it);
if(!var.startsWith("."))
remove(var);
diff --git a/qmake/qmake.pro b/qmake/qmake.pro
index 5399e8c298..4681fbf764 100644
--- a/qmake/qmake.pro
+++ b/qmake/qmake.pro
@@ -96,7 +96,7 @@ HEADERS += \
bp = $$shadowed(..)
INCLUDEPATH += \
$$bp/include $$bp/include/QtCore \
- $$bp/include/QtCore/$$QT_VERSION $$bp/include/QtCore/$$QT_VERSION/QtCore
+ $$bp/include/QtCore/$$QT_VERSION $$bp/include/QtCore/$$QT_VERSION/QtCore \
$$bp/src/corelib/global
VPATH += \
@@ -136,7 +136,6 @@ SOURCES += \
qjsonparser.cpp \
qjsonvalue.cpp \
qlibraryinfo.cpp \
- qlinkedlist.cpp \
qlist.cpp \
qlocale.cpp \
qlocale_tools.cpp \
@@ -148,7 +147,6 @@ SOURCES += \
qregexp.cpp \
qsettings.cpp \
qstring.cpp \
- qstring_compat.cpp \
qstringlist.cpp \
qsystemerror.cpp \
qtemporaryfile.cpp \
@@ -182,18 +180,16 @@ HEADERS += \
qglobal.h \
qhash.h \
qiodevice.h \
- qjson.h \
+ qjson_p.h \
qjsonarray.h \
qjsondocument.h \
qjsonobject.h \
- qjsonparser.h \
+ qjsonparser_p.h \
qjsonvalue.h \
- qjsonwriter.h \
- qlinkedlist.h \
+ qjsonwriter_p.h \
qlist.h \
qlocale.h \
qlocale_tools_p.h \
- qmalloc.h \
qmap.h \
qmetatype.h \
qnumeric.h \
@@ -204,12 +200,12 @@ HEADERS += \
qsystemerror_p.h \
qtemporaryfile.h \
qtextstream.h \
- qutfcodec.h \
+ qutfcodec_p.h \
quuid.h \
qvector.h \
qversionnumber.h \
qxmlstream.h \
- qxmlutils.h
+ qxmlutils_p.h
unix {
SOURCES += \
diff --git a/src/3rdparty/VulkanMemoryAllocator.pri b/src/3rdparty/VulkanMemoryAllocator.pri
new file mode 100644
index 0000000000..7466200dfc
--- /dev/null
+++ b/src/3rdparty/VulkanMemoryAllocator.pri
@@ -0,0 +1 @@
+INCLUDEPATH += $$PWD/VulkanMemoryAllocator
diff --git a/src/3rdparty/VulkanMemoryAllocator/LICENSE.txt b/src/3rdparty/VulkanMemoryAllocator/LICENSE.txt
new file mode 100644
index 0000000000..dbfe253391
--- /dev/null
+++ b/src/3rdparty/VulkanMemoryAllocator/LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2017-2018 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/src/3rdparty/VulkanMemoryAllocator/patches/0001-Avoid-compiler-warnings.patch b/src/3rdparty/VulkanMemoryAllocator/patches/0001-Avoid-compiler-warnings.patch
new file mode 100644
index 0000000000..f459db6c7a
--- /dev/null
+++ b/src/3rdparty/VulkanMemoryAllocator/patches/0001-Avoid-compiler-warnings.patch
@@ -0,0 +1,402 @@
+diff --git a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
+index a2f7a1b..fbe6f9e 100644
+--- a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
++++ b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
+@@ -3661,7 +3661,7 @@ static void VmaWriteMagicValue(void* pData, VkDeviceSize offset)
+ {
+ uint32_t* pDst = (uint32_t*)((char*)pData + offset);
+ const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);
+- for(size_t i = 0; i < numberCount; ++i, ++pDst)
++ for(size_t i = 0; i != numberCount; ++i, ++pDst)
+ {
+ *pDst = VMA_CORRUPTION_DETECTION_MAGIC_VALUE;
+ }
+@@ -3671,7 +3671,7 @@ static bool VmaValidateMagicValue(const void* pData, VkDeviceSize offset)
+ {
+ const uint32_t* pSrc = (const uint32_t*)((const char*)pData + offset);
+ const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);
+- for(size_t i = 0; i < numberCount; ++i, ++pSrc)
++ for(size_t i = 0; i != numberCount; ++i, ++pSrc)
+ {
+ if(*pSrc != VMA_CORRUPTION_DETECTION_MAGIC_VALUE)
+ {
+@@ -3866,7 +3866,7 @@ public:
+ template<typename U> VmaStlAllocator(const VmaStlAllocator<U>& src) : m_pCallbacks(src.m_pCallbacks) { }
+
+ T* allocate(size_t n) { return VmaAllocateArray<T>(m_pCallbacks, n); }
+- void deallocate(T* p, size_t n) { VmaFree(m_pCallbacks, p); }
++ void deallocate(T* p, size_t /*n*/) { VmaFree(m_pCallbacks, p); }
+
+ template<typename U>
+ bool operator==(const VmaStlAllocator<U>& rhs) const
+@@ -5214,7 +5214,7 @@ public:
+ virtual void FreeAtOffset(VkDeviceSize offset) = 0;
+
+ // Tries to resize (grow or shrink) space for given allocation, in place.
+- virtual bool ResizeAllocation(const VmaAllocation alloc, VkDeviceSize newSize) { return false; }
++ virtual bool ResizeAllocation(const VmaAllocation /*alloc*/, VkDeviceSize /*newSize*/) { return false; }
+
+ protected:
+ const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; }
+@@ -5574,7 +5574,7 @@ public:
+
+ virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+- virtual VkResult CheckCorruption(const void* pBlockData) { return VK_ERROR_FEATURE_NOT_PRESENT; }
++ virtual VkResult CheckCorruption(const void* /*pBlockData*/) { return VK_ERROR_FEATURE_NOT_PRESENT; }
+
+ virtual void Alloc(
+ const VmaAllocationRequest& request,
+@@ -6133,7 +6133,7 @@ public:
+ bool overlappingMoveSupported);
+ virtual ~VmaDefragmentationAlgorithm_Fast();
+
+- virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) { ++m_AllocationCount; }
++ virtual void AddAllocation(VmaAllocation /*hAlloc*/, VkBool32* /*pChanged*/) { ++m_AllocationCount; }
+ virtual void AddAll() { m_AllAllocations = true; }
+
+ virtual VkResult Defragment(
+@@ -6318,7 +6318,7 @@ private:
+ // Redundant, for convenience not to fetch from m_hCustomPool->m_BlockVector or m_hAllocator->m_pBlockVectors.
+ VmaBlockVector* const m_pBlockVector;
+ const uint32_t m_CurrFrameIndex;
+- const uint32_t m_AlgorithmFlags;
++ /*const uint32_t m_AlgorithmFlags;*/
+ // Owner of this object.
+ VmaDefragmentationAlgorithm* m_pAlgorithm;
+
+@@ -7073,6 +7073,7 @@ void VmaJsonWriter::BeginValue(bool isString)
+ if(currItem.type == COLLECTION_TYPE_OBJECT &&
+ currItem.valueCount % 2 == 0)
+ {
++ (void) isString;
+ VMA_ASSERT(isString);
+ }
+
+@@ -7660,7 +7661,9 @@ bool VmaBlockMetadata_Generic::Validate() const
+ }
+
+ // Margin required between allocations - every free space must be at least that large.
++#if VMA_DEBUG_MARGIN
+ VMA_VALIDATE(subAlloc.size >= VMA_DEBUG_MARGIN);
++#endif
+ }
+ else
+ {
+@@ -7806,6 +7809,7 @@ bool VmaBlockMetadata_Generic::CreateAllocationRequest(
+ {
+ VMA_ASSERT(allocSize > 0);
+ VMA_ASSERT(!upperAddress);
++ (void) upperAddress;
+ VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(pAllocationRequest != VMA_NULL);
+ VMA_HEAVY_ASSERT(Validate());
+@@ -8033,6 +8037,7 @@ void VmaBlockMetadata_Generic::Alloc(
+ VmaAllocation hAllocation)
+ {
+ VMA_ASSERT(!upperAddress);
++ (void) upperAddress;
+ VMA_ASSERT(request.item != m_Suballocations.end());
+ VmaSuballocation& suballoc = *request.item;
+ // Given suballocation is a free block.
+@@ -9609,7 +9614,7 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest(
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+- uint32_t strategy,
++ uint32_t /*strategy*/,
+ VmaAllocationRequest* pAllocationRequest)
+ {
+ VMA_ASSERT(allocSize > 0);
+@@ -9651,10 +9656,12 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest(
+ // Apply VMA_DEBUG_MARGIN at the end.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
++#if VMA_DEBUG_MARGIN
+ if(resultOffset < VMA_DEBUG_MARGIN)
+ {
+ return false;
+ }
++#endif
+ resultOffset -= VMA_DEBUG_MARGIN;
+ }
+
+@@ -10542,18 +10549,19 @@ void VmaBlockMetadata_Buddy::PrintDetailedMap(class VmaJsonWriter& json) const
+ #endif // #if VMA_STATS_STRING_ENABLED
+
+ bool VmaBlockMetadata_Buddy::CreateAllocationRequest(
+- uint32_t currentFrameIndex,
+- uint32_t frameInUseCount,
++ uint32_t /*currentFrameIndex*/,
++ uint32_t /*frameInUseCount*/,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+- bool canMakeOtherLost,
+- uint32_t strategy,
++ bool /*canMakeOtherLost*/,
++ uint32_t /*strategy*/,
+ VmaAllocationRequest* pAllocationRequest)
+ {
+ VMA_ASSERT(!upperAddress && "VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm.");
++ (void) upperAddress;
+
+ // Simple way to respect bufferImageGranularity. May be optimized some day.
+ // Whenever it might be an OPTIMAL image...
+@@ -10593,8 +10601,8 @@ bool VmaBlockMetadata_Buddy::CreateAllocationRequest(
+ }
+
+ bool VmaBlockMetadata_Buddy::MakeRequestedAllocationsLost(
+- uint32_t currentFrameIndex,
+- uint32_t frameInUseCount,
++ uint32_t /*currentFrameIndex*/,
++ uint32_t /*frameInUseCount*/,
+ VmaAllocationRequest* pAllocationRequest)
+ {
+ /*
+@@ -10604,7 +10612,7 @@ bool VmaBlockMetadata_Buddy::MakeRequestedAllocationsLost(
+ return pAllocationRequest->itemsToMakeLostCount == 0;
+ }
+
+-uint32_t VmaBlockMetadata_Buddy::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
++uint32_t VmaBlockMetadata_Buddy::MakeAllocationsLost(uint32_t /*currentFrameIndex*/, uint32_t /*frameInUseCount*/)
+ {
+ /*
+ Lost allocations are not supported in buddy allocator at the moment.
+@@ -10615,9 +10623,9 @@ uint32_t VmaBlockMetadata_Buddy::MakeAllocationsLost(uint32_t currentFrameIndex,
+
+ void VmaBlockMetadata_Buddy::Alloc(
+ const VmaAllocationRequest& request,
+- VmaSuballocationType type,
++ VmaSuballocationType /*type*/,
+ VkDeviceSize allocSize,
+- bool upperAddress,
++ bool /*upperAddress*/,
+ VmaAllocation hAllocation)
+ {
+ const uint32_t targetLevel = AllocSizeToLevel(allocSize);
+@@ -10941,7 +10949,7 @@ void VmaBlockMetadata_Buddy::PrintDetailedMapNode(class VmaJsonWriter& json, con
+ ////////////////////////////////////////////////////////////////////////////////
+ // class VmaDeviceMemoryBlock
+
+-VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) :
++VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator /*hAllocator*/) :
+ m_pMetadata(VMA_NULL),
+ m_MemoryTypeIndex(UINT32_MAX),
+ m_Id(0),
+@@ -11691,6 +11699,7 @@ VkResult VmaBlockVector::AllocatePage(
+ if(IsCorruptionDetectionEnabled())
+ {
+ VkResult res = pBestRequestBlock->WriteMagicValueAroundAllocation(m_hAllocator, bestRequest.offset, size);
++ (void) res;
+ VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
+ }
+ return VK_SUCCESS;
+@@ -11729,6 +11738,7 @@ void VmaBlockVector::Free(
+ if(IsCorruptionDetectionEnabled())
+ {
+ VkResult res = pBlock->ValidateMagicValueAroundAllocation(m_hAllocator, hAllocation->GetOffset(), hAllocation->GetSize());
++ (void) res;
+ VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to validate magic value.");
+ }
+
+@@ -11894,6 +11904,7 @@ VkResult VmaBlockVector::AllocateFromBlock(
+ if(IsCorruptionDetectionEnabled())
+ {
+ VkResult res = pBlock->WriteMagicValueAroundAllocation(m_hAllocator, currRequest.offset, size);
++ (void) res;
+ VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
+ }
+ return VK_SUCCESS;
+@@ -11903,7 +11914,8 @@ VkResult VmaBlockVector::AllocateFromBlock(
+
+ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex)
+ {
+- VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
++ VkMemoryAllocateInfo allocInfo = {};
++ allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocInfo.memoryTypeIndex = m_MemoryTypeIndex;
+ allocInfo.allocationSize = blockSize;
+ VkDeviceMemory mem = VK_NULL_HANDLE;
+@@ -11991,7 +12003,8 @@ void VmaBlockVector::ApplyDefragmentationMovesCpu(
+ if(pDefragCtx->res == VK_SUCCESS)
+ {
+ const VkDeviceSize nonCoherentAtomSize = m_hAllocator->m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
+- VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
++ VkMappedMemoryRange memRange = {};
++ memRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+
+ for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ {
+@@ -12076,7 +12089,8 @@ void VmaBlockVector::ApplyDefragmentationMovesGpu(
+
+ // Go over all blocks. Create and bind buffer for whole block if necessary.
+ {
+- VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
++ VkBufferCreateInfo bufCreateInfo = {};
++ bufCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+@@ -12101,8 +12115,9 @@ void VmaBlockVector::ApplyDefragmentationMovesGpu(
+ // Go over all moves. Post data transfer commands to command buffer.
+ if(pDefragCtx->res == VK_SUCCESS)
+ {
+- const VkDeviceSize nonCoherentAtomSize = m_hAllocator->m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
+- VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
++ /*const VkDeviceSize nonCoherentAtomSize = m_hAllocator->m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
++ VkMappedMemoryRange memRange = {};
++ memRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;*/
+
+ for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ {
+@@ -12435,10 +12450,10 @@ VmaDefragmentationAlgorithm_Generic::VmaDefragmentationAlgorithm_Generic(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex,
+- bool overlappingMoveSupported) :
++ bool /*overlappingMoveSupported*/) :
+ VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
+- m_AllAllocations(false),
+ m_AllocationCount(0),
++ m_AllAllocations(false),
+ m_BytesMoved(0),
+ m_AllocationsMoved(0),
+ m_Blocks(VmaStlAllocator<BlockInfo*>(hAllocator->GetAllocationCallbacks()))
+@@ -12813,7 +12828,7 @@ VkResult VmaDefragmentationAlgorithm_Fast::Defragment(
+ size_t freeSpaceOrigBlockIndex = m_BlockInfos[freeSpaceInfoIndex].origBlockIndex;
+ VmaDeviceMemoryBlock* pFreeSpaceBlock = m_pBlockVector->GetBlock(freeSpaceOrigBlockIndex);
+ VmaBlockMetadata_Generic* pFreeSpaceMetadata = (VmaBlockMetadata_Generic*)pFreeSpaceBlock->m_pMetadata;
+- VkDeviceSize freeSpaceBlockSize = pFreeSpaceMetadata->GetSize();
++ /*VkDeviceSize freeSpaceBlockSize = pFreeSpaceMetadata->GetSize();*/
+
+ // Same block
+ if(freeSpaceInfoIndex == srcBlockInfoIndex)
+@@ -13098,7 +13113,7 @@ VmaBlockVectorDefragmentationContext::VmaBlockVectorDefragmentationContext(
+ VmaPool hCustomPool,
+ VmaBlockVector* pBlockVector,
+ uint32_t currFrameIndex,
+- uint32_t algorithmFlags) :
++ uint32_t /*algorithmFlags*/) :
+ res(VK_SUCCESS),
+ mutexLocked(false),
+ blockContexts(VmaStlAllocator<VmaBlockDefragmentationContext>(hAllocator->GetAllocationCallbacks())),
+@@ -13106,7 +13121,7 @@ VmaBlockVectorDefragmentationContext::VmaBlockVectorDefragmentationContext(
+ m_hCustomPool(hCustomPool),
+ m_pBlockVector(pBlockVector),
+ m_CurrFrameIndex(currFrameIndex),
+- m_AlgorithmFlags(algorithmFlags),
++ /*m_AlgorithmFlags(algorithmFlags),*/
+ m_pAlgorithm(VMA_NULL),
+ m_Allocations(VmaStlAllocator<AllocInfo>(hAllocator->GetAllocationCallbacks())),
+ m_AllAllocations(false)
+@@ -14311,19 +14326,21 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory(
+ bool map,
+ bool isUserDataString,
+ void* pUserData,
+- VkBuffer dedicatedBuffer,
+- VkImage dedicatedImage,
++ VkBuffer /*dedicatedBuffer*/,
++ VkImage /*dedicatedImage*/,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+ {
+ VMA_ASSERT(allocationCount > 0 && pAllocations);
+
+- VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
++ VkMemoryAllocateInfo allocInfo = {};
++ allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocInfo.memoryTypeIndex = memTypeIndex;
+ allocInfo.allocationSize = size;
+
+ #if VMA_DEDICATED_ALLOCATION
+- VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR };
++ VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = {};
++ dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
+ if(m_UseKhrDedicatedAllocation)
+ {
+ if(dedicatedBuffer != VK_NULL_HANDLE)
+@@ -14341,7 +14358,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory(
+ #endif // #if VMA_DEDICATED_ALLOCATION
+
+ size_t allocIndex;
+- VkResult res;
++ VkResult res = VK_SUCCESS;
+ for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+ {
+ res = AllocateDedicatedMemoryPage(
+@@ -14460,12 +14477,15 @@ void VmaAllocator_T::GetBufferMemoryRequirements(
+ #if VMA_DEDICATED_ALLOCATION
+ if(m_UseKhrDedicatedAllocation)
+ {
+- VkBufferMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR };
++ VkBufferMemoryRequirementsInfo2KHR memReqInfo = {};
++ memReqInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR;
+ memReqInfo.buffer = hBuffer;
+
+- VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };
++ VkMemoryDedicatedRequirementsKHR memDedicatedReq = {};
++ memDedicatedReq.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR;
+
+- VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
++ VkMemoryRequirements2KHR memReq2 = {};
++ memReq2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR;
+ memReq2.pNext = &memDedicatedReq;
+
+ (*m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2);
+@@ -14492,12 +14512,15 @@ void VmaAllocator_T::GetImageMemoryRequirements(
+ #if VMA_DEDICATED_ALLOCATION
+ if(m_UseKhrDedicatedAllocation)
+ {
+- VkImageMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR };
++ VkImageMemoryRequirementsInfo2KHR memReqInfo = {};
++ memReqInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR;
+ memReqInfo.image = hImage;
+
+- VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };
++ VkMemoryDedicatedRequirementsKHR memDedicatedReq = {};
++ memDedicatedReq.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR;
+
+- VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
++ VkMemoryRequirements2KHR memReq2 = {};
++ memReq2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR;
+ memReq2.pNext = &memDedicatedReq;
+
+ (*m_VulkanFunctions.vkGetImageMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2);
+@@ -14734,7 +14757,7 @@ VkResult VmaAllocator_T::ResizeAllocation(
+ }
+ else
+ {
+- return VK_ERROR_OUT_OF_POOL_MEMORY;
++ return VkResult(-1000069000); // VK_ERROR_OUT_OF_POOL_MEMORY
+ }
+ default:
+ VMA_ASSERT(0);
+@@ -15000,6 +15023,7 @@ void VmaAllocator_T::DestroyPool(VmaPool pool)
+ {
+ VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);
+ bool success = VmaVectorRemoveSorted<VmaPointerLess>(m_Pools, pool);
++ (void) success;
+ VMA_ASSERT(success && "Pool not found in Allocator.");
+ }
+
+@@ -15248,7 +15272,8 @@ void VmaAllocator_T::FlushOrInvalidateAllocation(
+
+ const VkDeviceSize nonCoherentAtomSize = m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
+
+- VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
++ VkMappedMemoryRange memRange = {};
++ memRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+ memRange.memory = hAllocation->GetMemory();
+
+ switch(hAllocation->GetType())
+@@ -15321,6 +15346,7 @@ void VmaAllocator_T::FreeDedicatedMemory(VmaAllocation allocation)
+ AllocationVectorType* const pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex];
+ VMA_ASSERT(pDedicatedAllocations);
+ bool success = VmaVectorRemoveSorted<VmaPointerLess>(*pDedicatedAllocations, allocation);
++ (void) success;
+ VMA_ASSERT(success);
+ }
+
diff --git a/src/3rdparty/VulkanMemoryAllocator/patches/0002-Fix-gcc8-warning.patch b/src/3rdparty/VulkanMemoryAllocator/patches/0002-Fix-gcc8-warning.patch
new file mode 100644
index 0000000000..57a2f1a0f1
--- /dev/null
+++ b/src/3rdparty/VulkanMemoryAllocator/patches/0002-Fix-gcc8-warning.patch
@@ -0,0 +1,14 @@
+diff --git a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
+index fbe6f9e3e8..f043bdc289 100644
+--- a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
++++ b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
+@@ -12074,7 +12074,8 @@ void VmaBlockVector::ApplyDefragmentationMovesGpu(
+ const size_t blockCount = m_Blocks.size();
+
+ pDefragCtx->blockContexts.resize(blockCount);
+- memset(pDefragCtx->blockContexts.data(), 0, blockCount * sizeof(VmaBlockDefragmentationContext));
++ for (size_t i = 0; i < blockCount; ++i)
++ pDefragCtx->blockContexts[i] = VmaBlockDefragmentationContext();
+
+ // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.
+ const size_t moveCount = moves.size();
diff --git a/src/3rdparty/VulkanMemoryAllocator/patches/0003-Disable-srwlock-for-mingw.patch b/src/3rdparty/VulkanMemoryAllocator/patches/0003-Disable-srwlock-for-mingw.patch
new file mode 100644
index 0000000000..ab7acfe40b
--- /dev/null
+++ b/src/3rdparty/VulkanMemoryAllocator/patches/0003-Disable-srwlock-for-mingw.patch
@@ -0,0 +1,13 @@
+diff --git a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
+index f043bdc289..2355de091f 100644
+--- a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
++++ b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
+@@ -3298,7 +3298,7 @@ void *aligned_alloc(size_t alignment, size_t size)
+ std::shared_mutex m_Mutex;
+ };
+ #define VMA_RW_MUTEX VmaRWMutex
+- #elif defined(_WIN32)
++ #elif defined(_WIN32) && !defined(__MINGW32__)
+ // Use SRWLOCK from WinAPI.
+ class VmaRWMutex
+ {
diff --git a/src/3rdparty/VulkanMemoryAllocator/qt_attribution.json b/src/3rdparty/VulkanMemoryAllocator/qt_attribution.json
new file mode 100644
index 0000000000..2548856ca7
--- /dev/null
+++ b/src/3rdparty/VulkanMemoryAllocator/qt_attribution.json
@@ -0,0 +1,16 @@
+[
+ {
+ "Id": "VulkanMemoryAllocator",
+ "Name": "Vulkan Memory Allocator",
+ "QDocModule": "qtrhi",
+ "Description": "Vulkan Memory Allocator",
+ "QtUsage": "Memory management for the Vulkan backend of QRhi.",
+
+ "Homepage": "https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator",
+ "Version": "2.2.0",
+ "License": "MIT License",
+ "LicenseId": "MIT",
+ "LicenseFile": "LICENSE.txt",
+ "Copyright": "Copyright (c) 2017-2018 Advanced Micro Devices, Inc. All rights reserved."
+ }
+]
diff --git a/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
new file mode 100644
index 0000000000..2355de091f
--- /dev/null
+++ b/src/3rdparty/VulkanMemoryAllocator/vk_mem_alloc.h
@@ -0,0 +1,16790 @@
+//
+// Copyright (c) 2017-2018 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#ifndef AMD_VULKAN_MEMORY_ALLOCATOR_H
+#define AMD_VULKAN_MEMORY_ALLOCATOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \mainpage Vulkan Memory Allocator
+
+<b>Version 2.2.0</b> (2018-12-13)
+
+Copyright (c) 2017-2018 Advanced Micro Devices, Inc. All rights reserved. \n
+License: MIT
+
+Documentation of all members: vk_mem_alloc.h
+
+\section main_table_of_contents Table of contents
+
+- <b>User guide</b>
+ - \subpage quick_start
+ - [Project setup](@ref quick_start_project_setup)
+ - [Initialization](@ref quick_start_initialization)
+ - [Resource allocation](@ref quick_start_resource_allocation)
+ - \subpage choosing_memory_type
+ - [Usage](@ref choosing_memory_type_usage)
+ - [Required and preferred flags](@ref choosing_memory_type_required_preferred_flags)
+ - [Explicit memory types](@ref choosing_memory_type_explicit_memory_types)
+ - [Custom memory pools](@ref choosing_memory_type_custom_memory_pools)
+ - \subpage memory_mapping
+ - [Mapping functions](@ref memory_mapping_mapping_functions)
+ - [Persistently mapped memory](@ref memory_mapping_persistently_mapped_memory)
+ - [Cache control](@ref memory_mapping_cache_control)
+ - [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable)
+ - \subpage custom_memory_pools
+ - [Choosing memory type index](@ref custom_memory_pools_MemTypeIndex)
+ - [Linear allocation algorithm](@ref linear_algorithm)
+ - [Free-at-once](@ref linear_algorithm_free_at_once)
+ - [Stack](@ref linear_algorithm_stack)
+ - [Double stack](@ref linear_algorithm_double_stack)
+ - [Ring buffer](@ref linear_algorithm_ring_buffer)
+ - [Buddy allocation algorithm](@ref buddy_algorithm)
+ - \subpage defragmentation
+ - [Defragmenting CPU memory](@ref defragmentation_cpu)
+ - [Defragmenting GPU memory](@ref defragmentation_gpu)
+ - [Additional notes](@ref defragmentation_additional_notes)
+ - [Writing custom allocation algorithm](@ref defragmentation_custom_algorithm)
+ - \subpage lost_allocations
+ - \subpage statistics
+ - [Numeric statistics](@ref statistics_numeric_statistics)
+ - [JSON dump](@ref statistics_json_dump)
+ - \subpage allocation_annotation
+ - [Allocation user data](@ref allocation_user_data)
+ - [Allocation names](@ref allocation_names)
+ - \subpage debugging_memory_usage
+ - [Memory initialization](@ref debugging_memory_usage_initialization)
+ - [Margins](@ref debugging_memory_usage_margins)
+ - [Corruption detection](@ref debugging_memory_usage_corruption_detection)
+ - \subpage record_and_replay
+- \subpage usage_patterns
+ - [Simple patterns](@ref usage_patterns_simple)
+ - [Advanced patterns](@ref usage_patterns_advanced)
+- \subpage configuration
+ - [Pointers to Vulkan functions](@ref config_Vulkan_functions)
+ - [Custom host memory allocator](@ref custom_memory_allocator)
+ - [Device memory allocation callbacks](@ref allocation_callbacks)
+ - [Device heap memory limit](@ref heap_memory_limit)
+ - \subpage vk_khr_dedicated_allocation
+- \subpage general_considerations
+ - [Thread safety](@ref general_considerations_thread_safety)
+ - [Validation layer warnings](@ref general_considerations_validation_layer_warnings)
+ - [Allocation algorithm](@ref general_considerations_allocation_algorithm)
+ - [Features not supported](@ref general_considerations_features_not_supported)
+
+\section main_see_also See also
+
+- [Product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/)
+- [Source repository on GitHub](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
+
+
+
+
+\page quick_start Quick start
+
+\section quick_start_project_setup Project setup
+
+Vulkan Memory Allocator comes in form of a single header file.
+You don't need to build it as a separate library project.
+You can add this file directly to your project and submit it to code repository next to your other source files.
+
+"Single header" doesn't mean that everything is contained in C/C++ declarations,
+like it tends to be in case of inline functions or C++ templates.
+It means that implementation is bundled with interface in a single file and needs to be extracted using preprocessor macro.
+If you don't do it properly, you will get linker errors.
+
+To do it properly:
+
+-# Include "vk_mem_alloc.h" file in each CPP file where you want to use the library.
+ This includes declarations of all members of the library.
+-# In exacly one CPP file define following macro before this include.
+ It enables also internal definitions.
+
+\code
+#define VMA_IMPLEMENTATION
+#include "vk_mem_alloc.h"
+\endcode
+
+It may be a good idea to create dedicated CPP file just for this purpose.
+
+Note on language: This library is written in C++, but has C-compatible interface.
+Thus you can include and use vk_mem_alloc.h in C or C++ code, but full
+implementation with `VMA_IMPLEMENTATION` macro must be compiled as C++, NOT as C.
+
+Please note that this library includes header `<vulkan/vulkan.h>`, which in turn
+includes `<windows.h>` on Windows. If you need some specific macros defined
+before including these headers (like `WIN32_LEAN_AND_MEAN` or
+`WINVER` for Windows, `VK_USE_PLATFORM_WIN32_KHR` for Vulkan), you must define
+them before every `#include` of this library.
+
+
+\section quick_start_initialization Initialization
+
+At program startup:
+
+-# Initialize Vulkan to have `VkPhysicalDevice` and `VkDevice` object.
+-# Fill VmaAllocatorCreateInfo structure and create #VmaAllocator object by
+ calling vmaCreateAllocator().
+
+\code
+VmaAllocatorCreateInfo allocatorInfo = {};
+allocatorInfo.physicalDevice = physicalDevice;
+allocatorInfo.device = device;
+
+VmaAllocator allocator;
+vmaCreateAllocator(&allocatorInfo, &allocator);
+\endcode
+
+\section quick_start_resource_allocation Resource allocation
+
+When you want to create a buffer or image:
+
+-# Fill `VkBufferCreateInfo` / `VkImageCreateInfo` structure.
+-# Fill VmaAllocationCreateInfo structure.
+-# Call vmaCreateBuffer() / vmaCreateImage() to get `VkBuffer`/`VkImage` with memory
+ already allocated and bound to it.
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufferInfo.size = 65536;
+bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+Don't forget to destroy your objects when no longer needed:
+
+\code
+vmaDestroyBuffer(allocator, buffer, allocation);
+vmaDestroyAllocator(allocator);
+\endcode
+
+
+\page choosing_memory_type Choosing memory type
+
+Physical devices in Vulkan support various combinations of memory heaps and
+types. Help with choosing correct and optimal memory type for your specific
+resource is one of the key features of this library. You can use it by filling
+appropriate members of VmaAllocationCreateInfo structure, as described below.
+You can also combine multiple methods.
+
+-# If you just want to find memory type index that meets your requirements, you
+ can use function vmaFindMemoryTypeIndex().
+-# If you want to allocate a region of device memory without association with any
+ specific image or buffer, you can use function vmaAllocateMemory(). Usage of
+ this function is not recommended and usually not needed.
+-# If you already have a buffer or an image created, you want to allocate memory
+ for it and then you will bind it yourself, you can use function
+ vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage().
+ For binding you should use functions: vmaBindBufferMemory(), vmaBindImageMemory().
+-# If you want to create a buffer or an image, allocate memory for it and bind
+ them together, all in one call, you can use function vmaCreateBuffer(),
+ vmaCreateImage(). This is the recommended way to use this library.
+
+When using 3. or 4., the library internally queries Vulkan for memory types
+supported for that buffer or image (function `vkGetBufferMemoryRequirements()`)
+and uses only one of these types.
+
+If no memory type can be found that meets all the requirements, these functions
+return `VK_ERROR_FEATURE_NOT_PRESENT`.
+
+You can leave VmaAllocationCreateInfo structure completely filled with zeros.
+It means no requirements are specified for memory type.
+It is valid, although not very useful.
+
+\section choosing_memory_type_usage Usage
+
+The easiest way to specify memory requirements is to fill member
+VmaAllocationCreateInfo::usage using one of the values of enum #VmaMemoryUsage.
+It defines high level, common usage types.
+For more details, see description of this enum.
+
+For example, if you want to create a uniform buffer that will be filled using
+transfer only once or infrequently and used for rendering every frame, you can
+do it using following code:
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufferInfo.size = 65536;
+bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+\section choosing_memory_type_required_preferred_flags Required and preferred flags
+
+You can specify more detailed requirements by filling members
+VmaAllocationCreateInfo::requiredFlags and VmaAllocationCreateInfo::preferredFlags
+with a combination of bits from enum `VkMemoryPropertyFlags`. For example,
+if you want to create a buffer that will be persistently mapped on host (so it
+must be `HOST_VISIBLE`) and preferably will also be `HOST_COHERENT` and `HOST_CACHED`,
+use following code:
+
+\code
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+allocInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+A memory type is chosen that has all the required flags and as many preferred
+flags set as possible.
+
+If you use VmaAllocationCreateInfo::usage, it is just internally converted to
+a set of required and preferred flags.
+
+\section choosing_memory_type_explicit_memory_types Explicit memory types
+
+If you inspected memory types available on the physical device and you have
+a preference for memory types that you want to use, you can fill member
+VmaAllocationCreateInfo::memoryTypeBits. It is a bit mask, where each bit set
+means that a memory type with that index is allowed to be used for the
+allocation. Special value 0, just like `UINT32_MAX`, means there are no
+restrictions to memory type index.
+
+Please note that this member is NOT just a memory type index.
+Still you can use it to choose just one, specific memory type.
+For example, if you already determined that your buffer should be created in
+memory type 2, use following code:
+
+\code
+uint32_t memoryTypeIndex = 2;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.memoryTypeBits = 1u << memoryTypeIndex;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+\section choosing_memory_type_custom_memory_pools Custom memory pools
+
+If you allocate from custom memory pool, all the ways of specifying memory
+requirements described above are not applicable and the aforementioned members
+of VmaAllocationCreateInfo structure are ignored. Memory type is selected
+explicitly when creating the pool and then used to make all the allocations from
+that pool. For further details, see \ref custom_memory_pools.
+
+
+\page memory_mapping Memory mapping
+
+To "map memory" in Vulkan means to obtain a CPU pointer to `VkDeviceMemory`,
+to be able to read from it or write to it in CPU code.
+Mapping is possible only of memory allocated from a memory type that has
+`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag.
+Functions `vkMapMemory()`, `vkUnmapMemory()` are designed for this purpose.
+You can use them directly with memory allocated by this library,
+but it is not recommended because of following issue:
+Mapping the same `VkDeviceMemory` block multiple times is illegal - only one mapping at a time is allowed.
+This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan.
+Because of this, Vulkan Memory Allocator provides following facilities:
+
+\section memory_mapping_mapping_functions Mapping functions
+
+The library provides following functions for mapping of a specific #VmaAllocation: vmaMapMemory(), vmaUnmapMemory().
+They are safer and more convenient to use than standard Vulkan functions.
+You can map an allocation multiple times simultaneously - mapping is reference-counted internally.
+You can also map different allocations simultaneously regardless of whether they use the same `VkDeviceMemory` block.
+The way it's implemented is that the library always maps entire memory block, not just region of the allocation.
+For further details, see description of vmaMapMemory() function.
+Example:
+
+\code
+// Having these objects initialized:
+
+struct ConstantBuffer
+{
+ ...
+};
+ConstantBuffer constantBufferData;
+
+VmaAllocator allocator;
+VkBuffer constantBuffer;
+VmaAllocation constantBufferAllocation;
+
+// You can map and fill your buffer using following code:
+
+void* mappedData;
+vmaMapMemory(allocator, constantBufferAllocation, &mappedData);
+memcpy(mappedData, &constantBufferData, sizeof(constantBufferData));
+vmaUnmapMemory(allocator, constantBufferAllocation);
+\endcode
+
+When mapping, you may see a warning from Vulkan validation layer similar to this one:
+
+<i>Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.</i>
+
+It happens because the library maps entire `VkDeviceMemory` block, where different
+types of images and buffers may end up together, especially on GPUs with unified memory like Intel.
+You can safely ignore it if you are sure you access only memory of the intended
+object that you wanted to map.
+
+
+\section memory_mapping_persistently_mapped_memory Persistently mapped memory
+
+Kepping your memory persistently mapped is generally OK in Vulkan.
+You don't need to unmap it before using its data on the GPU.
+The library provides a special feature designed for that:
+Allocations made with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag set in
+VmaAllocationCreateInfo::flags stay mapped all the time,
+so you can just access CPU pointer to it any time
+without a need to call any "map" or "unmap" function.
+Example:
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = sizeof(ConstantBuffer);
+bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+// Buffer is already mapped. You can access its memory.
+memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
+\endcode
+
+There are some exceptions though, when you should consider mapping memory only for a short period of time:
+
+- When operating system is Windows 7 or 8.x (Windows 10 is not affected because it uses WDDM2),
+ device is discrete AMD GPU,
+ and memory type is the special 256 MiB pool of `DEVICE_LOCAL + HOST_VISIBLE` memory
+ (selected when you use #VMA_MEMORY_USAGE_CPU_TO_GPU),
+ then whenever a memory block allocated from this memory type stays mapped
+ for the time of any call to `vkQueueSubmit()` or `vkQueuePresentKHR()`, this
+ block is migrated by WDDM to system RAM, which degrades performance. It doesn't
+ matter if that particular memory block is actually used by the command buffer
+ being submitted.
+- On Mac/MoltenVK there is a known bug - [Issue #175](https://github.com/KhronosGroup/MoltenVK/issues/175)
+ which requires unmapping before GPU can see updated texture.
+- Keeping many large memory blocks mapped may impact performance or stability of some debugging tools.
+
+\section memory_mapping_cache_control Cache control
+
+Memory in Vulkan doesn't need to be unmapped before using it on GPU,
+but unless a memory types has `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag set,
+you need to manually invalidate cache before reading of mapped pointer
+and flush cache after writing to mapped pointer.
+Vulkan provides following functions for this purpose `vkFlushMappedMemoryRanges()`,
+`vkInvalidateMappedMemoryRanges()`, but this library provides more convenient
+functions that refer to given allocation object: vmaFlushAllocation(),
+vmaInvalidateAllocation().
+
+Regions of memory specified for flush/invalidate must be aligned to
+`VkPhysicalDeviceLimits::nonCoherentAtomSize`. This is automatically ensured by the library.
+In any memory type that is `HOST_VISIBLE` but not `HOST_COHERENT`, all allocations
+within blocks are aligned to this value, so their offsets are always multiply of
+`nonCoherentAtomSize` and two different allocations never share same "line" of this size.
+
+Please note that memory allocated with #VMA_MEMORY_USAGE_CPU_ONLY is guaranteed to be `HOST_COHERENT`.
+
+Also, Windows drivers from all 3 PC GPU vendors (AMD, Intel, NVIDIA)
+currently provide `HOST_COHERENT` flag on all memory types that are
+`HOST_VISIBLE`, so on this platform you may not need to bother.
+
+\section memory_mapping_finding_if_memory_mappable Finding out if memory is mappable
+
+It may happen that your allocation ends up in memory that is `HOST_VISIBLE` (available for mapping)
+despite it wasn't explicitly requested.
+For example, application may work on integrated graphics with unified memory (like Intel) or
+allocation from video memory might have failed, so the library chose system memory as fallback.
+
+You can detect this case and map such allocation to access its memory on CPU directly,
+instead of launching a transfer operation.
+In order to do that: inspect `allocInfo.memoryType`, call vmaGetMemoryTypeProperties(),
+and look for `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag in properties of that memory type.
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = sizeof(ConstantBuffer);
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+VkMemoryPropertyFlags memFlags;
+vmaGetMemoryTypeProperties(allocator, allocInfo.memoryType, &memFlags);
+if((memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+{
+ // Allocation ended up in mappable memory. You can map it and access it directly.
+ void* mappedData;
+ vmaMapMemory(allocator, alloc, &mappedData);
+ memcpy(mappedData, &constantBufferData, sizeof(constantBufferData));
+ vmaUnmapMemory(allocator, alloc);
+}
+else
+{
+ // Allocation ended up in non-mappable memory.
+ // You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.
+}
+\endcode
+
+You can even use #VMA_ALLOCATION_CREATE_MAPPED_BIT flag while creating allocations
+that are not necessarily `HOST_VISIBLE` (e.g. using #VMA_MEMORY_USAGE_GPU_ONLY).
+If the allocation ends up in memory type that is `HOST_VISIBLE`, it will be persistently mapped and you can use it directly.
+If not, the flag is just ignored.
+Example:
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = sizeof(ConstantBuffer);
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+if(allocInfo.pUserData != nullptr)
+{
+ // Allocation ended up in mappable memory.
+ // It's persistently mapped. You can access it directly.
+ memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
+}
+else
+{
+ // Allocation ended up in non-mappable memory.
+ // You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.
+}
+\endcode
+
+
+\page custom_memory_pools Custom memory pools
+
+A memory pool contains a number of `VkDeviceMemory` blocks.
+The library automatically creates and manages default pool for each memory type available on the device.
+Default memory pool automatically grows in size.
+Size of allocated blocks is also variable and managed automatically.
+
+You can create custom pool and allocate memory out of it.
+It can be useful if you want to:
+
+- Keep certain kind of allocations separate from others.
+- Enforce particular, fixed size of Vulkan memory blocks.
+- Limit maximum amount of Vulkan memory allocated for that pool.
+- Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool.
+
+To use custom memory pools:
+
+-# Fill VmaPoolCreateInfo structure.
+-# Call vmaCreatePool() to obtain #VmaPool handle.
+-# When making an allocation, set VmaAllocationCreateInfo::pool to this handle.
+ You don't need to specify any other parameters of this structure, like `usage`.
+
+Example:
+
+\code
+// Create a pool that can have at most 2 blocks, 128 MiB each.
+VmaPoolCreateInfo poolCreateInfo = {};
+poolCreateInfo.memoryTypeIndex = ...
+poolCreateInfo.blockSize = 128ull * 1024 * 1024;
+poolCreateInfo.maxBlockCount = 2;
+
+VmaPool pool;
+vmaCreatePool(allocator, &poolCreateInfo, &pool);
+
+// Allocate a buffer out of it.
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = 1024;
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.pool = pool;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+\endcode
+
+You have to free all allocations made from this pool before destroying it.
+
+\code
+vmaDestroyBuffer(allocator, buf, alloc);
+vmaDestroyPool(allocator, pool);
+\endcode
+
+\section custom_memory_pools_MemTypeIndex Choosing memory type index
+
+When creating a pool, you must explicitly specify memory type index.
+To find the one suitable for your buffers or images, you can use helper functions
+vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo().
+You need to provide structures with example parameters of buffers or images
+that you are going to create in that pool.
+
+\code
+VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+exampleBufCreateInfo.size = 1024; // Whatever.
+exampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; // Change if needed.
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; // Change if needed.
+
+uint32_t memTypeIndex;
+vmaFindMemoryTypeIndexForBufferInfo(allocator, &exampleBufCreateInfo, &allocCreateInfo, &memTypeIndex);
+
+VmaPoolCreateInfo poolCreateInfo = {};
+poolCreateInfo.memoryTypeIndex = memTypeIndex;
+// ...
+\endcode
+
+When creating buffers/images allocated in that pool, provide following parameters:
+
+- `VkBufferCreateInfo`: Prefer to pass same parameters as above.
+ Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior.
+ Using different `VK_BUFFER_USAGE_` flags may work, but you shouldn't create images in a pool intended for buffers
+ or the other way around.
+- VmaAllocationCreateInfo: You don't need to pass same parameters. Fill only `pool` member.
+ Other members are ignored anyway.
+
+\section linear_algorithm Linear allocation algorithm
+
+Each Vulkan memory block managed by this library has accompanying metadata that
+keeps track of used and unused regions. By default, the metadata structure and
+algorithm tries to find best place for new allocations among free regions to
+optimize memory usage. This way you can allocate and free objects in any order.
+
+![Default allocation algorithm](../gfx/Linear_allocator_1_algo_default.png)
+
+Sometimes there is a need to use simpler, linear allocation algorithm. You can
+create custom pool that uses such algorithm by adding flag
+#VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating
+#VmaPool object. Then an alternative metadata management is used. It always
+creates new allocations after last one and doesn't reuse free regions after
+allocations freed in the middle. It results in better allocation performance and
+less memory consumed by metadata.
+
+![Linear allocation algorithm](../gfx/Linear_allocator_2_algo_linear.png)
+
+With this one flag, you can create a custom pool that can be used in many ways:
+free-at-once, stack, double stack, and ring buffer. See below for details.
+
+\subsection linear_algorithm_free_at_once Free-at-once
+
+In a pool that uses linear algorithm, you still need to free all the allocations
+individually, e.g. by using vmaFreeMemory() or vmaDestroyBuffer(). You can free
+them in any order. New allocations are always made after last one - free space
+in the middle is not reused. However, when you release all the allocation and
+the pool becomes empty, allocation starts from the beginning again. This way you
+can use linear algorithm to speed up creation of allocations that you are going
+to release all at once.
+
+![Free-at-once](../gfx/Linear_allocator_3_free_at_once.png)
+
+This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount
+value that allows multiple memory blocks.
+
+\subsection linear_algorithm_stack Stack
+
+When you free an allocation that was created last, its space can be reused.
+Thanks to this, if you always release allocations in the order opposite to their
+creation (LIFO - Last In First Out), you can achieve behavior of a stack.
+
+![Stack](../gfx/Linear_allocator_4_stack.png)
+
+This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount
+value that allows multiple memory blocks.
+
+\subsection linear_algorithm_double_stack Double stack
+
+The space reserved by a custom pool with linear algorithm may be used by two
+stacks:
+
+- First, default one, growing up from offset 0.
+- Second, "upper" one, growing down from the end towards lower offsets.
+
+To make allocation from upper stack, add flag #VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT
+to VmaAllocationCreateInfo::flags.
+
+![Double stack](../gfx/Linear_allocator_7_double_stack.png)
+
+Double stack is available only in pools with one memory block -
+VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.
+
+When the two stacks' ends meet so there is not enough space between them for a
+new allocation, such allocation fails with usual
+`VK_ERROR_OUT_OF_DEVICE_MEMORY` error.
+
+\subsection linear_algorithm_ring_buffer Ring buffer
+
+When you free some allocations from the beginning and there is not enough free space
+for a new one at the end of a pool, allocator's "cursor" wraps around to the
+beginning and starts allocation there. Thanks to this, if you always release
+allocations in the same order as you created them (FIFO - First In First Out),
+you can achieve behavior of a ring buffer / queue.
+
+![Ring buffer](../gfx/Linear_allocator_5_ring_buffer.png)
+
+Pools with linear algorithm support [lost allocations](@ref lost_allocations) when used as ring buffer.
+If there is not enough free space for a new allocation, but existing allocations
+from the front of the queue can become lost, they become lost and the allocation
+succeeds.
+
+![Ring buffer with lost allocations](../gfx/Linear_allocator_6_ring_buffer_lost.png)
+
+Ring buffer is available only in pools with one memory block -
+VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.
+
+\section buddy_algorithm Buddy allocation algorithm
+
+There is another allocation algorithm that can be used with custom pools, called
+"buddy". Its internal data structure is based on a tree of blocks, each having
+size that is a power of two and a half of its parent's size. When you want to
+allocate memory of certain size, a free node in the tree is located. If it's too
+large, it is recursively split into two halves (called "buddies"). However, if
+requested allocation size is not a power of two, the size of a tree node is
+aligned up to the nearest power of two and the remaining space is wasted. When
+two buddy nodes become free, they are merged back into one larger node.
+
+![Buddy allocator](../gfx/Buddy_allocator.png)
+
+The advantage of buddy allocation algorithm over default algorithm is faster
+allocation and deallocation, as well as smaller external fragmentation. The
+disadvantage is more wasted space (internal fragmentation).
+
+For more information, please read ["Buddy memory allocation" on Wikipedia](https://en.wikipedia.org/wiki/Buddy_memory_allocation)
+or other sources that describe this concept in general.
+
+To use buddy allocation algorithm with a custom pool, add flag
+#VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating
+#VmaPool object.
+
+Several limitations apply to pools that use buddy algorithm:
+
+- It is recommended to use VmaPoolCreateInfo::blockSize that is a power of two.
+ Otherwise, only largest power of two smaller than the size is used for
+ allocations. The remaining space always stays unused.
+- [Margins](@ref debugging_memory_usage_margins) and
+ [corruption detection](@ref debugging_memory_usage_corruption_detection)
+ don't work in such pools.
+- [Lost allocations](@ref lost_allocations) don't work in such pools. You can
+ use them, but they never become lost. Support may be added in the future.
+- [Defragmentation](@ref defragmentation) doesn't work with allocations made from
+ such pool.
+
+\page defragmentation Defragmentation
+
+Interleaved allocations and deallocations of many objects of varying size can
+cause fragmentation over time, which can lead to a situation where the library is unable
+to find a continuous range of free memory for a new allocation despite there is
+enough free space, just scattered across many small free ranges between existing
+allocations.
+
+To mitigate this problem, you can use defragmentation feature:
+structure #VmaDefragmentationInfo2, function vmaDefragmentationBegin(), vmaDefragmentationEnd().
+Given set of allocations,
+this function can move them to compact used memory, ensure more continuous free
+space and possibly also free some `VkDeviceMemory` blocks.
+
+What the defragmentation does is:
+
+- Updates #VmaAllocation objects to point to new `VkDeviceMemory` and offset.
+ After allocation has been moved, its VmaAllocationInfo::deviceMemory and/or
+ VmaAllocationInfo::offset changes. You must query them again using
+ vmaGetAllocationInfo() if you need them.
+- Moves actual data in memory.
+
+What it doesn't do, so you need to do it yourself:
+
+- Recreate buffers and images that were bound to allocations that were defragmented and
+ bind them with their new places in memory.
+ You must use `vkDestroyBuffer()`, `vkDestroyImage()`,
+ `vkCreateBuffer()`, `vkCreateImage()` for that purpose and NOT vmaDestroyBuffer(),
+ vmaDestroyImage(), vmaCreateBuffer(), vmaCreateImage(), because you don't need to
+ destroy or create allocation objects!
+- Recreate views and update descriptors that point to these buffers and images.
+
+\section defragmentation_cpu Defragmenting CPU memory
+
+Following example demonstrates how you can run defragmentation on CPU.
+Only allocations created in memory types that are `HOST_VISIBLE` can be defragmented.
+Others are ignored.
+
+The way it works is:
+
+- It temporarily maps entire memory blocks when necessary.
+- It moves data using `memmove()` function.
+
+\code
+// Given following variables already initialized:
+VkDevice device;
+VmaAllocator allocator;
+std::vector<VkBuffer> buffers;
+std::vector<VmaAllocation> allocations;
+
+
+const uint32_t allocCount = (uint32_t)allocations.size();
+std::vector<VkBool32> allocationsChanged(allocCount);
+
+VmaDefragmentationInfo2 defragInfo = {};
+defragInfo.allocationCount = allocCount;
+defragInfo.pAllocations = allocations.data();
+defragInfo.pAllocationsChanged = allocationsChanged.data();
+defragInfo.maxCpuBytesToMove = VK_WHOLE_SIZE; // No limit.
+defragInfo.maxCpuAllocationsToMove = UINT32_MAX; // No limit.
+
+VmaDefragmentationContext defragCtx;
+vmaDefragmentationBegin(allocator, &defragInfo, nullptr, &defragCtx);
+vmaDefragmentationEnd(allocator, defragCtx);
+
+for(uint32_t i = 0; i < allocCount; ++i)
+{
+ if(allocationsChanged[i])
+ {
+ // Destroy buffer that is immutably bound to memory region which is no longer valid.
+ vkDestroyBuffer(device, buffers[i], nullptr);
+
+ // Create new buffer with same parameters.
+ VkBufferCreateInfo bufferInfo = ...;
+ vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]);
+
+ // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.
+
+ // Bind new buffer to new memory region. Data contained in it is already moved.
+ VmaAllocationInfo allocInfo;
+ vmaGetAllocationInfo(allocator, allocations[i], &allocInfo);
+ vkBindBufferMemory(device, buffers[i], allocInfo.deviceMemory, allocInfo.offset);
+ }
+}
+\endcode
+
+Setting VmaDefragmentationInfo2::pAllocationsChanged is optional.
+This output array tells whether particular allocation in VmaDefragmentationInfo2::pAllocations at the same index
+has been modified during defragmentation.
+You can pass null, but you then need to query every allocation passed to defragmentation
+for new parameters using vmaGetAllocationInfo() if you might need to recreate and rebind a buffer or image associated with it.
+
+If you use [Custom memory pools](@ref choosing_memory_type_custom_memory_pools),
+you can fill VmaDefragmentationInfo2::poolCount and VmaDefragmentationInfo2::pPools
+instead of VmaDefragmentationInfo2::allocationCount and VmaDefragmentationInfo2::pAllocations
+to defragment all allocations in given pools.
+You cannot use VmaDefragmentationInfo2::pAllocationsChanged in that case.
+You can also combine both methods.
+
+\section defragmentation_gpu Defragmenting GPU memory
+
+It is also possible to defragment allocations created in memory types that are not `HOST_VISIBLE`.
+To do that, you need to pass a command buffer that meets requirements as described in
+VmaDefragmentationInfo2::commandBuffer. The way it works is:
+
+- It creates temporary buffers and binds them to entire memory blocks when necessary.
+- It issues `vkCmdCopyBuffer()` to passed command buffer.
+
+Example:
+
+\code
+// Given following variables already initialized:
+VkDevice device;
+VmaAllocator allocator;
+VkCommandBuffer commandBuffer;
+std::vector<VkBuffer> buffers;
+std::vector<VmaAllocation> allocations;
+
+
+const uint32_t allocCount = (uint32_t)allocations.size();
+std::vector<VkBool32> allocationsChanged(allocCount);
+
+VkCommandBufferBeginInfo cmdBufBeginInfo = ...;
+vkBeginCommandBuffer(commandBuffer, &cmdBufBeginInfo);
+
+VmaDefragmentationInfo2 defragInfo = {};
+defragInfo.allocationCount = allocCount;
+defragInfo.pAllocations = allocations.data();
+defragInfo.pAllocationsChanged = allocationsChanged.data();
+defragInfo.maxGpuBytesToMove = VK_WHOLE_SIZE; // Notice it's "GPU" this time.
+defragInfo.maxGpuAllocationsToMove = UINT32_MAX; // Notice it's "GPU" this time.
+defragInfo.commandBuffer = commandBuffer;
+
+VmaDefragmentationContext defragCtx;
+vmaDefragmentationBegin(allocator, &defragInfo, nullptr, &defragCtx);
+
+vkEndCommandBuffer(commandBuffer);
+
+// Submit commandBuffer.
+// Wait for a fence that ensures commandBuffer execution finished.
+
+vmaDefragmentationEnd(allocator, defragCtx);
+
+for(uint32_t i = 0; i < allocCount; ++i)
+{
+ if(allocationsChanged[i])
+ {
+ // Destroy buffer that is immutably bound to memory region which is no longer valid.
+ vkDestroyBuffer(device, buffers[i], nullptr);
+
+ // Create new buffer with same parameters.
+ VkBufferCreateInfo bufferInfo = ...;
+ vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]);
+
+ // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.
+
+ // Bind new buffer to new memory region. Data contained in it is already moved.
+ VmaAllocationInfo allocInfo;
+ vmaGetAllocationInfo(allocator, allocations[i], &allocInfo);
+ vkBindBufferMemory(device, buffers[i], allocInfo.deviceMemory, allocInfo.offset);
+ }
+}
+\endcode
+
+You can combine these two methods by specifying non-zero `maxGpu*` as well as `maxCpu*` parameters.
+The library automatically chooses best method to defragment each memory pool.
+
+You may try not to block your entire program to wait until defragmentation finishes,
+but do it in the background, as long as you carefully fullfill requirements described
+in function vmaDefragmentationBegin().
+
+\section defragmentation_additional_notes Additional notes
+
+While using defragmentation, you may experience validation layer warnings, which you just need to ignore.
+See [Validation layer warnings](@ref general_considerations_validation_layer_warnings).
+
+If you defragment allocations bound to images, these images should be created with
+`VK_IMAGE_CREATE_ALIAS_BIT` flag, to make sure that new image created with same
+parameters and pointing to data copied to another memory region will interpret
+its contents consistently. Otherwise you may experience corrupted data on some
+implementations, e.g. due to different pixel swizzling used internally by the graphics driver.
+
+If you defragment allocations bound to images, new images to be bound to new
+memory region after defragmentation should be created with `VK_IMAGE_LAYOUT_PREINITIALIZED`
+and then transitioned to their original layout from before defragmentation using
+an image memory barrier.
+
+Please don't expect memory to be fully compacted after defragmentation.
+Algorithms inside are based on some heuristics that try to maximize number of Vulkan
+memory blocks to make totally empty to release them, as well as to maximimze continuous
+empty space inside remaining blocks, while minimizing the number and size of allocations that
+need to be moved. Some fragmentation may still remain - this is normal.
+
+\section defragmentation_custom_algorithm Writing custom defragmentation algorithm
+
+If you want to implement your own, custom defragmentation algorithm,
+there is infrastructure prepared for that,
+but it is not exposed through the library API - you need to hack its source code.
+Here are steps needed to do this:
+
+-# Main thing you need to do is to define your own class derived from base abstract
+ class `VmaDefragmentationAlgorithm` and implement your version of its pure virtual methods.
+ See definition and comments of this class for details.
+-# Your code needs to interact with device memory block metadata.
+ If you need more access to its data than it's provided by its public interface,
+ declare your new class as a friend class e.g. in class `VmaBlockMetadata_Generic`.
+-# If you want to create a flag that would enable your algorithm or pass some additional
+ flags to configure it, add them to `VmaDefragmentationFlagBits` and use them in
+ VmaDefragmentationInfo2::flags.
+-# Modify function `VmaBlockVectorDefragmentationContext::Begin` to create object
+ of your new class whenever needed.
+
+
+\page lost_allocations Lost allocations
+
+If your game oversubscribes video memory, if may work OK in previous-generation
+graphics APIs (DirectX 9, 10, 11, OpenGL) because resources are automatically
+paged to system RAM. In Vulkan you can't do it because when you run out of
+memory, an allocation just fails. If you have more data (e.g. textures) that can
+fit into VRAM and you don't need it all at once, you may want to upload them to
+GPU on demand and "push out" ones that are not used for a long time to make room
+for the new ones, effectively using VRAM (or a cartain memory pool) as a form of
+cache. Vulkan Memory Allocator can help you with that by supporting a concept of
+"lost allocations".
+
+To create an allocation that can become lost, include #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT
+flag in VmaAllocationCreateInfo::flags. Before using a buffer or image bound to
+such allocation in every new frame, you need to query it if it's not lost.
+To check it, call vmaTouchAllocation().
+If the allocation is lost, you should not use it or buffer/image bound to it.
+You mustn't forget to destroy this allocation and this buffer/image.
+vmaGetAllocationInfo() can also be used for checking status of the allocation.
+Allocation is lost when returned VmaAllocationInfo::deviceMemory == `VK_NULL_HANDLE`.
+
+To create an allocation that can make some other allocations lost to make room
+for it, use #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag. You will
+usually use both flags #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT and
+#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT at the same time.
+
+Warning! Current implementation uses quite naive, brute force algorithm,
+which can make allocation calls that use #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT
+flag quite slow. A new, more optimal algorithm and data structure to speed this
+up is planned for the future.
+
+<b>Q: When interleaving creation of new allocations with usage of existing ones,
+how do you make sure that an allocation won't become lost while it's used in the
+current frame?</b>
+
+It is ensured because vmaTouchAllocation() / vmaGetAllocationInfo() not only returns allocation
+status/parameters and checks whether it's not lost, but when it's not, it also
+atomically marks it as used in the current frame, which makes it impossible to
+become lost in that frame. It uses lockless algorithm, so it works fast and
+doesn't involve locking any internal mutex.
+
+<b>Q: What if my allocation may still be in use by the GPU when it's rendering a
+previous frame while I already submit new frame on the CPU?</b>
+
+You can make sure that allocations "touched" by vmaTouchAllocation() / vmaGetAllocationInfo() will not
+become lost for a number of additional frames back from the current one by
+specifying this number as VmaAllocatorCreateInfo::frameInUseCount (for default
+memory pool) and VmaPoolCreateInfo::frameInUseCount (for custom pool).
+
+<b>Q: How do you inform the library when new frame starts?</b>
+
+You need to call function vmaSetCurrentFrameIndex().
+
+Example code:
+
+\code
+struct MyBuffer
+{
+ VkBuffer m_Buf = nullptr;
+ VmaAllocation m_Alloc = nullptr;
+
+ // Called when the buffer is really needed in the current frame.
+ void EnsureBuffer();
+};
+
+void MyBuffer::EnsureBuffer()
+{
+ // Buffer has been created.
+ if(m_Buf != VK_NULL_HANDLE)
+ {
+ // Check if its allocation is not lost + mark it as used in current frame.
+ if(vmaTouchAllocation(allocator, m_Alloc))
+ {
+ // It's all OK - safe to use m_Buf.
+ return;
+ }
+ }
+
+ // Buffer not yet exists or lost - destroy and recreate it.
+
+ vmaDestroyBuffer(allocator, m_Buf, m_Alloc);
+
+ VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+ bufCreateInfo.size = 1024;
+ bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+ VmaAllocationCreateInfo allocCreateInfo = {};
+ allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+ allocCreateInfo.flags = VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT |
+ VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
+
+ vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &m_Buf, &m_Alloc, nullptr);
+}
+\endcode
+
+When using lost allocations, you may see some Vulkan validation layer warnings
+about overlapping regions of memory bound to different kinds of buffers and
+images. This is still valid as long as you implement proper handling of lost
+allocations (like in the example above) and don't use them.
+
+You can create an allocation that is already in lost state from the beginning using function
+vmaCreateLostAllocation(). It may be useful if you need a "dummy" allocation that is not null.
+
+You can call function vmaMakePoolAllocationsLost() to set all eligible allocations
+in a specified custom pool to lost state.
+Allocations that have been "touched" in current frame or VmaPoolCreateInfo::frameInUseCount frames back
+cannot become lost.
+
+<b>Q: Can I touch allocation that cannot become lost?</b>
+
+Yes, although it has no visible effect.
+Calls to vmaGetAllocationInfo() and vmaTouchAllocation() update last use frame index
+also for allocations that cannot become lost, but the only way to observe it is to dump
+internal allocator state using vmaBuildStatsString().
+You can use this feature for debugging purposes to explicitly mark allocations that you use
+in current frame and then analyze JSON dump to see for how long each allocation stays unused.
+
+
+\page statistics Statistics
+
+This library contains functions that return information about its internal state,
+especially the amount of memory allocated from Vulkan.
+Please keep in mind that these functions need to traverse all internal data structures
+to gather these information, so they may be quite time-consuming.
+Don't call them too often.
+
+\section statistics_numeric_statistics Numeric statistics
+
+You can query for overall statistics of the allocator using function vmaCalculateStats().
+Information are returned using structure #VmaStats.
+It contains #VmaStatInfo - number of allocated blocks, number of allocations
+(occupied ranges in these blocks), number of unused (free) ranges in these blocks,
+number of bytes used and unused (but still allocated from Vulkan) and other information.
+They are summed across memory heaps, memory types and total for whole allocator.
+
+You can query for statistics of a custom pool using function vmaGetPoolStats().
+Information are returned using structure #VmaPoolStats.
+
+You can query for information about specific allocation using function vmaGetAllocationInfo().
+It fill structure #VmaAllocationInfo.
+
+\section statistics_json_dump JSON dump
+
+You can dump internal state of the allocator to a string in JSON format using function vmaBuildStatsString().
+The result is guaranteed to be correct JSON.
+It uses ANSI encoding.
+Any strings provided by user (see [Allocation names](@ref allocation_names))
+are copied as-is and properly escaped for JSON, so if they use UTF-8, ISO-8859-2 or any other encoding,
+this JSON string can be treated as using this encoding.
+It must be freed using function vmaFreeStatsString().
+
+The format of this JSON string is not part of official documentation of the library,
+but it will not change in backward-incompatible way without increasing library major version number
+and appropriate mention in changelog.
+
+The JSON string contains all the data that can be obtained using vmaCalculateStats().
+It can also contain detailed map of allocated memory blocks and their regions -
+free and occupied by allocations.
+This allows e.g. to visualize the memory or assess fragmentation.
+
+
+\page allocation_annotation Allocation names and user data
+
+\section allocation_user_data Allocation user data
+
+You can annotate allocations with your own information, e.g. for debugging purposes.
+To do that, fill VmaAllocationCreateInfo::pUserData field when creating
+an allocation. It's an opaque `void*` pointer. You can use it e.g. as a pointer,
+some handle, index, key, ordinal number or any other value that would associate
+the allocation with your custom metadata.
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+// Fill bufferInfo...
+
+MyBufferMetadata* pMetadata = CreateBufferMetadata();
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.pUserData = pMetadata;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, nullptr);
+\endcode
+
+The pointer may be later retrieved as VmaAllocationInfo::pUserData:
+
+\code
+VmaAllocationInfo allocInfo;
+vmaGetAllocationInfo(allocator, allocation, &allocInfo);
+MyBufferMetadata* pMetadata = (MyBufferMetadata*)allocInfo.pUserData;
+\endcode
+
+It can also be changed using function vmaSetAllocationUserData().
+
+Values of (non-zero) allocations' `pUserData` are printed in JSON report created by
+vmaBuildStatsString(), in hexadecimal form.
+
+\section allocation_names Allocation names
+
+There is alternative mode available where `pUserData` pointer is used to point to
+a null-terminated string, giving a name to the allocation. To use this mode,
+set #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT flag in VmaAllocationCreateInfo::flags.
+Then `pUserData` passed as VmaAllocationCreateInfo::pUserData or argument to
+vmaSetAllocationUserData() must be either null or pointer to a null-terminated string.
+The library creates internal copy of the string, so the pointer you pass doesn't need
+to be valid for whole lifetime of the allocation. You can free it after the call.
+
+\code
+VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+// Fill imageInfo...
+
+std::string imageName = "Texture: ";
+imageName += fileName;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
+allocCreateInfo.pUserData = imageName.c_str();
+
+VkImage image;
+VmaAllocation allocation;
+vmaCreateImage(allocator, &imageInfo, &allocCreateInfo, &image, &allocation, nullptr);
+\endcode
+
+The value of `pUserData` pointer of the allocation will be different than the one
+you passed when setting allocation's name - pointing to a buffer managed
+internally that holds copy of the string.
+
+\code
+VmaAllocationInfo allocInfo;
+vmaGetAllocationInfo(allocator, allocation, &allocInfo);
+const char* imageName = (const char*)allocInfo.pUserData;
+printf("Image name: %s\n", imageName);
+\endcode
+
+That string is also printed in JSON report created by vmaBuildStatsString().
+
+
+\page debugging_memory_usage Debugging incorrect memory usage
+
+If you suspect a bug with memory usage, like usage of uninitialized memory or
+memory being overwritten out of bounds of an allocation,
+you can use debug features of this library to verify this.
+
+\section debugging_memory_usage_initialization Memory initialization
+
+If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used,
+you can enable automatic memory initialization to verify this.
+To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1.
+
+\code
+#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1
+#include "vk_mem_alloc.h"
+\endcode
+
+It makes memory of all new allocations initialized to bit pattern `0xDCDCDCDC`.
+Before an allocation is destroyed, its memory is filled with bit pattern `0xEFEFEFEF`.
+Memory is automatically mapped and unmapped if necessary.
+
+If you find these values while debugging your program, good chances are that you incorrectly
+read Vulkan memory that is allocated but not initialized, or already freed, respectively.
+
+Memory initialization works only with memory types that are `HOST_VISIBLE`.
+It works also with dedicated allocations.
+It doesn't work with allocations created with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
+as they cannot be mapped.
+
+\section debugging_memory_usage_margins Margins
+
+By default, allocations are laid out in memory blocks next to each other if possible
+(considering required alignment, `bufferImageGranularity`, and `nonCoherentAtomSize`).
+
+![Allocations without margin](../gfx/Margins_1.png)
+
+Define macro `VMA_DEBUG_MARGIN` to some non-zero value (e.g. 16) to enforce specified
+number of bytes as a margin before and after every allocation.
+
+\code
+#define VMA_DEBUG_MARGIN 16
+#include "vk_mem_alloc.h"
+\endcode
+
+![Allocations with margin](../gfx/Margins_2.png)
+
+If your bug goes away after enabling margins, it means it may be caused by memory
+being overwritten outside of allocation boundaries. It is not 100% certain though.
+Change in application behavior may also be caused by different order and distribution
+of allocations across memory blocks after margins are applied.
+
+The margin is applied also before first and after last allocation in a block.
+It may occur only once between two adjacent allocations.
+
+Margins work with all types of memory.
+
+Margin is applied only to allocations made out of memory blocks and not to dedicated
+allocations, which have their own memory block of specific size.
+It is thus not applied to allocations made using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag
+or those automatically decided to put into dedicated allocations, e.g. due to its
+large size or recommended by VK_KHR_dedicated_allocation extension.
+Margins are also not active in custom pools created with #VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag.
+
+Margins appear in [JSON dump](@ref statistics_json_dump) as part of free space.
+
+Note that enabling margins increases memory usage and fragmentation.
+
+\section debugging_memory_usage_corruption_detection Corruption detection
+
+You can additionally define macro `VMA_DEBUG_DETECT_CORRUPTION` to 1 to enable validation
+of contents of the margins.
+
+\code
+#define VMA_DEBUG_MARGIN 16
+#define VMA_DEBUG_DETECT_CORRUPTION 1
+#include "vk_mem_alloc.h"
+\endcode
+
+When this feature is enabled, number of bytes specified as `VMA_DEBUG_MARGIN`
+(it must be multiply of 4) before and after every allocation is filled with a magic number.
+This idea is also know as "canary".
+Memory is automatically mapped and unmapped if necessary.
+
+This number is validated automatically when the allocation is destroyed.
+If it's not equal to the expected value, `VMA_ASSERT()` is executed.
+It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation,
+which indicates a serious bug.
+
+You can also explicitly request checking margins of all allocations in all memory blocks
+that belong to specified memory types by using function vmaCheckCorruption(),
+or in memory blocks that belong to specified custom pool, by using function
+vmaCheckPoolCorruption().
+
+Margin validation (corruption detection) works only for memory types that are
+`HOST_VISIBLE` and `HOST_COHERENT`.
+
+
+\page record_and_replay Record and replay
+
+\section record_and_replay_introduction Introduction
+
+While using the library, sequence of calls to its functions together with their
+parameters can be recorded to a file and later replayed using standalone player
+application. It can be useful to:
+
+- Test correctness - check if same sequence of calls will not cause crash or
+ failures on a target platform.
+- Gather statistics - see number of allocations, peak memory usage, number of
+ calls etc.
+- Benchmark performance - see how much time it takes to replay the whole
+ sequence.
+
+\section record_and_replay_usage Usage
+
+<b>To record sequence of calls to a file:</b> Fill in
+VmaAllocatorCreateInfo::pRecordSettings member while creating #VmaAllocator
+object. File is opened and written during whole lifetime of the allocator.
+
+<b>To replay file:</b> Use VmaReplay - standalone command-line program.
+Precompiled binary can be found in "bin" directory.
+Its source can be found in "src/VmaReplay" directory.
+Its project is generated by Premake.
+Command line syntax is printed when the program is launched without parameters.
+Basic usage:
+
+ VmaReplay.exe MyRecording.csv
+
+<b>Documentation of file format</b> can be found in file: "docs/Recording file format.md".
+It's a human-readable, text file in CSV format (Comma Separated Values).
+
+\section record_and_replay_additional_considerations Additional considerations
+
+- Replaying file that was recorded on a different GPU (with different parameters
+ like `bufferImageGranularity`, `nonCoherentAtomSize`, and especially different
+ set of memory heaps and types) may give different performance and memory usage
+ results, as well as issue some warnings and errors.
+- Current implementation of recording in VMA, as well as VmaReplay application, is
+ coded and tested only on Windows. Inclusion of recording code is driven by
+ `VMA_RECORDING_ENABLED` macro. Support for other platforms should be easy to
+ add. Contributions are welcomed.
+- Currently calls to vmaDefragment() function are not recorded.
+
+
+\page usage_patterns Recommended usage patterns
+
+See also slides from talk:
+[Sawicki, Adam. Advanced Graphics Techniques Tutorial: Memory management in Vulkan and DX12. Game Developers Conference, 2018](https://www.gdcvault.com/play/1025458/Advanced-Graphics-Techniques-Tutorial-New)
+
+
+\section usage_patterns_simple Simple patterns
+
+\subsection usage_patterns_simple_render_targets Render targets
+
+<b>When:</b>
+Any resources that you frequently write and read on GPU,
+e.g. images used as color attachments (aka "render targets"), depth-stencil attachments,
+images/buffers used as storage image/buffer (aka "Unordered Access View (UAV)").
+
+<b>What to do:</b>
+Create them in video memory that is fastest to access from GPU using
+#VMA_MEMORY_USAGE_GPU_ONLY.
+
+Consider using [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension
+and/or manually creating them as dedicated allocations using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
+especially if they are large or if you plan to destroy and recreate them e.g. when
+display resolution changes.
+Prefer to create such resources first and all other GPU resources (like textures and vertex buffers) later.
+
+\subsection usage_patterns_simple_immutable_resources Immutable resources
+
+<b>When:</b>
+Any resources that you fill on CPU only once (aka "immutable") or infrequently
+and then read frequently on GPU,
+e.g. textures, vertex and index buffers, constant buffers that don't change often.
+
+<b>What to do:</b>
+Create them in video memory that is fastest to access from GPU using
+#VMA_MEMORY_USAGE_GPU_ONLY.
+
+To initialize content of such resource, create a CPU-side (aka "staging") copy of it
+in system memory - #VMA_MEMORY_USAGE_CPU_ONLY, map it, fill it,
+and submit a transfer from it to the GPU resource.
+You can keep the staging copy if you need it for another upload transfer in the future.
+If you don't, you can destroy it or reuse this buffer for uploading different resource
+after the transfer finishes.
+
+Prefer to create just buffers in system memory rather than images, even for uploading textures.
+Use `vkCmdCopyBufferToImage()`.
+Dont use images with `VK_IMAGE_TILING_LINEAR`.
+
+\subsection usage_patterns_dynamic_resources Dynamic resources
+
+<b>When:</b>
+Any resources that change frequently (aka "dynamic"), e.g. every frame or every draw call,
+written on CPU, read on GPU.
+
+<b>What to do:</b>
+Create them using #VMA_MEMORY_USAGE_CPU_TO_GPU.
+You can map it and write to it directly on CPU, as well as read from it on GPU.
+
+This is a more complex situation. Different solutions are possible,
+and the best one depends on specific GPU type, but you can use this simple approach for the start.
+Prefer to write to such resource sequentially (e.g. using `memcpy`).
+Don't perform random access or any reads from it on CPU, as it may be very slow.
+
+\subsection usage_patterns_readback Readback
+
+<b>When:</b>
+Resources that contain data written by GPU that you want to read back on CPU,
+e.g. results of some computations.
+
+<b>What to do:</b>
+Create them using #VMA_MEMORY_USAGE_GPU_TO_CPU.
+You can write to them directly on GPU, as well as map and read them on CPU.
+
+\section usage_patterns_advanced Advanced patterns
+
+\subsection usage_patterns_integrated_graphics Detecting integrated graphics
+
+You can support integrated graphics (like Intel HD Graphics, AMD APU) better
+by detecting it in Vulkan.
+To do it, call `vkGetPhysicalDeviceProperties()`, inspect
+`VkPhysicalDeviceProperties::deviceType` and look for `VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU`.
+When you find it, you can assume that memory is unified and all memory types are comparably fast
+to access from GPU, regardless of `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.
+
+You can then sum up sizes of all available memory heaps and treat them as useful for
+your GPU resources, instead of only `DEVICE_LOCAL` ones.
+You can also prefer to create your resources in memory types that are `HOST_VISIBLE` to map them
+directly instead of submitting explicit transfer (see below).
+
+\subsection usage_patterns_direct_vs_transfer Direct access versus transfer
+
+For resources that you frequently write on CPU and read on GPU, many solutions are possible:
+
+-# Create one copy in video memory using #VMA_MEMORY_USAGE_GPU_ONLY,
+ second copy in system memory using #VMA_MEMORY_USAGE_CPU_ONLY and submit explicit tranfer each time.
+-# Create just single copy using #VMA_MEMORY_USAGE_CPU_TO_GPU, map it and fill it on CPU,
+ read it directly on GPU.
+-# Create just single copy using #VMA_MEMORY_USAGE_CPU_ONLY, map it and fill it on CPU,
+ read it directly on GPU.
+
+Which solution is the most efficient depends on your resource and especially on the GPU.
+It is best to measure it and then make the decision.
+Some general recommendations:
+
+- On integrated graphics use (2) or (3) to avoid unnecesary time and memory overhead
+ related to using a second copy and making transfer.
+- For small resources (e.g. constant buffers) use (2).
+ Discrete AMD cards have special 256 MiB pool of video memory that is directly mappable.
+ Even if the resource ends up in system memory, its data may be cached on GPU after first
+ fetch over PCIe bus.
+- For larger resources (e.g. textures), decide between (1) and (2).
+ You may want to differentiate NVIDIA and AMD, e.g. by looking for memory type that is
+ both `DEVICE_LOCAL` and `HOST_VISIBLE`. When you find it, use (2), otherwise use (1).
+
+Similarly, for resources that you frequently write on GPU and read on CPU, multiple
+solutions are possible:
+
+-# Create one copy in video memory using #VMA_MEMORY_USAGE_GPU_ONLY,
+ second copy in system memory using #VMA_MEMORY_USAGE_GPU_TO_CPU and submit explicit tranfer each time.
+-# Create just single copy using #VMA_MEMORY_USAGE_GPU_TO_CPU, write to it directly on GPU,
+ map it and read it on CPU.
+
+You should take some measurements to decide which option is faster in case of your specific
+resource.
+
+If you don't want to specialize your code for specific types of GPUs, you can still make
+an simple optimization for cases when your resource ends up in mappable memory to use it
+directly in this case instead of creating CPU-side staging copy.
+For details see [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable).
+
+
+\page configuration Configuration
+
+Please check "CONFIGURATION SECTION" in the code to find macros that you can define
+before each include of this file or change directly in this file to provide
+your own implementation of basic facilities like assert, `min()` and `max()` functions,
+mutex, atomic etc.
+The library uses its own implementation of containers by default, but you can switch to using
+STL containers instead.
+
+\section config_Vulkan_functions Pointers to Vulkan functions
+
+The library uses Vulkan functions straight from the `vulkan.h` header by default.
+If you want to provide your own pointers to these functions, e.g. fetched using
+`vkGetInstanceProcAddr()` and `vkGetDeviceProcAddr()`:
+
+-# Define `VMA_STATIC_VULKAN_FUNCTIONS 0`.
+-# Provide valid pointers through VmaAllocatorCreateInfo::pVulkanFunctions.
+
+\section custom_memory_allocator Custom host memory allocator
+
+If you use custom allocator for CPU memory rather than default operator `new`
+and `delete` from C++, you can make this library using your allocator as well
+by filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These
+functions will be passed to Vulkan, as well as used by the library itself to
+make any CPU-side allocations.
+
+\section allocation_callbacks Device memory allocation callbacks
+
+The library makes calls to `vkAllocateMemory()` and `vkFreeMemory()` internally.
+You can setup callbacks to be informed about these calls, e.g. for the purpose
+of gathering some statistics. To do it, fill optional member
+VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
+
+\section heap_memory_limit Device heap memory limit
+
+If you want to test how your program behaves with limited amount of Vulkan device
+memory available without switching your graphics card to one that really has
+smaller VRAM, you can use a feature of this library intended for this purpose.
+To do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit.
+
+
+
+\page vk_khr_dedicated_allocation VK_KHR_dedicated_allocation
+
+VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve
+performance on some GPUs. It augments Vulkan API with possibility to query
+driver whether it prefers particular buffer or image to have its own, dedicated
+allocation (separate `VkDeviceMemory` block) for better efficiency - to be able
+to do some internal optimizations.
+
+The extension is supported by this library. It will be used automatically when
+enabled. To enable it:
+
+1 . When creating Vulkan device, check if following 2 device extensions are
+supported (call `vkEnumerateDeviceExtensionProperties()`).
+If yes, enable them (fill `VkDeviceCreateInfo::ppEnabledExtensionNames`).
+
+- VK_KHR_get_memory_requirements2
+- VK_KHR_dedicated_allocation
+
+If you enabled these extensions:
+
+2 . Use #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag when creating
+your #VmaAllocator`to inform the library that you enabled required extensions
+and you want the library to use them.
+
+\code
+allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
+
+vmaCreateAllocator(&allocatorInfo, &allocator);
+\endcode
+
+That's all. The extension will be automatically used whenever you create a
+buffer using vmaCreateBuffer() or image using vmaCreateImage().
+
+When using the extension together with Vulkan Validation Layer, you will receive
+warnings like this:
+
+ vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer.
+
+It is OK, you should just ignore it. It happens because you use function
+`vkGetBufferMemoryRequirements2KHR()` instead of standard
+`vkGetBufferMemoryRequirements()`, while the validation layer seems to be
+unaware of it.
+
+To learn more about this extension, see:
+
+- [VK_KHR_dedicated_allocation in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VK_KHR_dedicated_allocation)
+- [VK_KHR_dedicated_allocation unofficial manual](http://asawicki.info/articles/VK_KHR_dedicated_allocation.php5)
+
+
+
+\page general_considerations General considerations
+
+\section general_considerations_thread_safety Thread safety
+
+- The library has no global state, so separate #VmaAllocator objects can be used
+ independently.
+ There should be no need to create multiple such objects though - one per `VkDevice` is enough.
+- By default, all calls to functions that take #VmaAllocator as first parameter
+ are safe to call from multiple threads simultaneously because they are
+ synchronized internally when needed.
+- When the allocator is created with #VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT
+ flag, calls to functions that take such #VmaAllocator object must be
+ synchronized externally.
+- Access to a #VmaAllocation object must be externally synchronized. For example,
+ you must not call vmaGetAllocationInfo() and vmaMapMemory() from different
+ threads at the same time if you pass the same #VmaAllocation object to these
+ functions.
+
+\section general_considerations_validation_layer_warnings Validation layer warnings
+
+When using this library, you can meet following types of warnings issued by
+Vulkan validation layer. They don't necessarily indicate a bug, so you may need
+to just ignore them.
+
+- *vkBindBufferMemory(): Binding memory to buffer 0xeb8e4 but vkGetBufferMemoryRequirements() has not been called on that buffer.*
+ - It happens when VK_KHR_dedicated_allocation extension is enabled.
+ `vkGetBufferMemoryRequirements2KHR` function is used instead, while validation layer seems to be unaware of it.
+- *Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.*
+ - It happens when you map a buffer or image, because the library maps entire
+ `VkDeviceMemory` block, where different types of images and buffers may end
+ up together, especially on GPUs with unified memory like Intel.
+- *Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug.*
+ - It happens when you use lost allocations, and a new image or buffer is
+ created in place of an existing object that bacame lost.
+ - It may happen also when you use [defragmentation](@ref defragmentation).
+
+\section general_considerations_allocation_algorithm Allocation algorithm
+
+The library uses following algorithm for allocation, in order:
+
+-# Try to find free range of memory in existing blocks.
+-# If failed, try to create a new block of `VkDeviceMemory`, with preferred block size.
+-# If failed, try to create such block with size/2, size/4, size/8.
+-# If failed and #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag was
+ specified, try to find space in existing blocks, possilby making some other
+ allocations lost.
+-# If failed, try to allocate separate `VkDeviceMemory` for this allocation,
+ just like when you use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+-# If failed, choose other memory type that meets the requirements specified in
+ VmaAllocationCreateInfo and go to point 1.
+-# If failed, return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+
+\section general_considerations_features_not_supported Features not supported
+
+Features deliberately excluded from the scope of this library:
+
+- Data transfer. Uploading (straming) and downloading data of buffers and images
+ between CPU and GPU memory and related synchronization is responsibility of the user.
+- Allocations for imported/exported external memory. They tend to require
+ explicit memory type index and dedicated allocation anyway, so they don't
+ interact with main features of this library. Such special purpose allocations
+ should be made manually, using `vkCreateBuffer()` and `vkAllocateMemory()`.
+- Recreation of buffers and images. Although the library has functions for
+ buffer and image creation (vmaCreateBuffer(), vmaCreateImage()), you need to
+ recreate these objects yourself after defragmentation. That's because the big
+ structures `VkBufferCreateInfo`, `VkImageCreateInfo` are not stored in
+ #VmaAllocation object.
+- Handling CPU memory allocation failures. When dynamically creating small C++
+ objects in CPU memory (not Vulkan memory), allocation failures are not checked
+ and handled gracefully, because that would complicate code significantly and
+ is usually not needed in desktop PC applications anyway.
+- Code free of any compiler warnings. Maintaining the library to compile and
+ work correctly on so many different platforms is hard enough. Being free of
+ any warnings, on any version of any compiler, is simply not feasible.
+- This is a C++ library with C interface.
+ Bindings or ports to any other programming languages are welcomed as external projects and
+ are not going to be included into this repository.
+
+*/
+
+/*
+Define this macro to 0/1 to disable/enable support for recording functionality,
+available through VmaAllocatorCreateInfo::pRecordSettings.
+*/
+#ifndef VMA_RECORDING_ENABLED
+ #ifdef _WIN32
+ #define VMA_RECORDING_ENABLED 1
+ #else
+ #define VMA_RECORDING_ENABLED 0
+ #endif
+#endif
+
+#ifndef NOMINMAX
+ #define NOMINMAX // For windows.h
+#endif
+
+#ifndef VULKAN_H_
+ #include <vulkan/vulkan.h>
+#endif
+
+#if VMA_RECORDING_ENABLED
+ #include <windows.h>
+#endif
+
+#if !defined(VMA_DEDICATED_ALLOCATION)
+ #if VK_KHR_get_memory_requirements2 && VK_KHR_dedicated_allocation
+ #define VMA_DEDICATED_ALLOCATION 1
+ #else
+ #define VMA_DEDICATED_ALLOCATION 0
+ #endif
+#endif
+
+/** \struct VmaAllocator
+\brief Represents main object of this library initialized.
+
+Fill structure #VmaAllocatorCreateInfo and call function vmaCreateAllocator() to create it.
+Call function vmaDestroyAllocator() to destroy it.
+
+It is recommended to create just one object of this type per `VkDevice` object,
+right after Vulkan is initialized and keep it alive until before Vulkan device is destroyed.
+*/
+VK_DEFINE_HANDLE(VmaAllocator)
+
+/// Callback function called after successful vkAllocateMemory.
+typedef void (VKAPI_PTR *PFN_vmaAllocateDeviceMemoryFunction)(
+ VmaAllocator allocator,
+ uint32_t memoryType,
+ VkDeviceMemory memory,
+ VkDeviceSize size);
+/// Callback function called before vkFreeMemory.
+typedef void (VKAPI_PTR *PFN_vmaFreeDeviceMemoryFunction)(
+ VmaAllocator allocator,
+ uint32_t memoryType,
+ VkDeviceMemory memory,
+ VkDeviceSize size);
+
+/** \brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`.
+
+Provided for informative purpose, e.g. to gather statistics about number of
+allocations or total amount of memory allocated in Vulkan.
+
+Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
+*/
+typedef struct VmaDeviceMemoryCallbacks {
+ /// Optional, can be null.
+ PFN_vmaAllocateDeviceMemoryFunction pfnAllocate;
+ /// Optional, can be null.
+ PFN_vmaFreeDeviceMemoryFunction pfnFree;
+} VmaDeviceMemoryCallbacks;
+
+/// Flags for created #VmaAllocator.
+typedef enum VmaAllocatorCreateFlagBits {
+ /** \brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you.
+
+ Using this flag may increase performance because internal mutexes are not used.
+ */
+ VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001,
+ /** \brief Enables usage of VK_KHR_dedicated_allocation extension.
+
+ Using this extenion will automatically allocate dedicated blocks of memory for
+ some buffers and images instead of suballocating place for them out of bigger
+ memory blocks (as if you explicitly used #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT
+ flag) when it is recommended by the driver. It may improve performance on some
+ GPUs.
+
+ You may set this flag only if you found out that following device extensions are
+ supported, you enabled them while creating Vulkan device passed as
+ VmaAllocatorCreateInfo::device, and you want them to be used internally by this
+ library:
+
+ - VK_KHR_get_memory_requirements2
+ - VK_KHR_dedicated_allocation
+
+When this flag is set, you can experience following warnings reported by Vulkan
+validation layer. You can ignore them.
+
+> vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer.
+ */
+ VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT = 0x00000002,
+
+ VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaAllocatorCreateFlagBits;
+typedef VkFlags VmaAllocatorCreateFlags;
+
+/** \brief Pointers to some Vulkan functions - a subset used by the library.
+
+Used in VmaAllocatorCreateInfo::pVulkanFunctions.
+*/
+typedef struct VmaVulkanFunctions {
+ PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
+ PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
+ PFN_vkAllocateMemory vkAllocateMemory;
+ PFN_vkFreeMemory vkFreeMemory;
+ PFN_vkMapMemory vkMapMemory;
+ PFN_vkUnmapMemory vkUnmapMemory;
+ PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;
+ PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges;
+ PFN_vkBindBufferMemory vkBindBufferMemory;
+ PFN_vkBindImageMemory vkBindImageMemory;
+ PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
+ PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
+ PFN_vkCreateBuffer vkCreateBuffer;
+ PFN_vkDestroyBuffer vkDestroyBuffer;
+ PFN_vkCreateImage vkCreateImage;
+ PFN_vkDestroyImage vkDestroyImage;
+ PFN_vkCmdCopyBuffer vkCmdCopyBuffer;
+#if VMA_DEDICATED_ALLOCATION
+ PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;
+ PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;
+#endif
+} VmaVulkanFunctions;
+
+/// Flags to be used in VmaRecordSettings::flags.
+typedef enum VmaRecordFlagBits {
+ /** \brief Enables flush after recording every function call.
+
+ Enable it if you expect your application to crash, which may leave recording file truncated.
+ It may degrade performance though.
+ */
+ VMA_RECORD_FLUSH_AFTER_CALL_BIT = 0x00000001,
+
+ VMA_RECORD_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaRecordFlagBits;
+typedef VkFlags VmaRecordFlags;
+
+/// Parameters for recording calls to VMA functions. To be used in VmaAllocatorCreateInfo::pRecordSettings.
+typedef struct VmaRecordSettings
+{
+ /// Flags for recording. Use #VmaRecordFlagBits enum.
+ VmaRecordFlags flags;
+ /** \brief Path to the file that should be written by the recording.
+
+ Suggested extension: "csv".
+ If the file already exists, it will be overwritten.
+ It will be opened for the whole time #VmaAllocator object is alive.
+ If opening this file fails, creation of the whole allocator object fails.
+ */
+ const char* pFilePath;
+} VmaRecordSettings;
+
+/// Description of a Allocator to be created.
+typedef struct VmaAllocatorCreateInfo
+{
+ /// Flags for created allocator. Use #VmaAllocatorCreateFlagBits enum.
+ VmaAllocatorCreateFlags flags;
+ /// Vulkan physical device.
+ /** It must be valid throughout whole lifetime of created allocator. */
+ VkPhysicalDevice physicalDevice;
+ /// Vulkan device.
+ /** It must be valid throughout whole lifetime of created allocator. */
+ VkDevice device;
+ /// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB. Optional.
+ /** Set to 0 to use default, which is currently 256 MiB. */
+ VkDeviceSize preferredLargeHeapBlockSize;
+ /// Custom CPU memory allocation callbacks. Optional.
+ /** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */
+ const VkAllocationCallbacks* pAllocationCallbacks;
+ /// Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional.
+ /** Optional, can be null. */
+ const VmaDeviceMemoryCallbacks* pDeviceMemoryCallbacks;
+ /** \brief Maximum number of additional frames that are in use at the same time as current frame.
+
+ This value is used only when you make allocations with
+ VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocation cannot become
+ lost if allocation.lastUseFrameIndex >= allocator.currentFrameIndex - frameInUseCount.
+
+ For example, if you double-buffer your command buffers, so resources used for
+ rendering in previous frame may still be in use by the GPU at the moment you
+ allocate resources needed for the current frame, set this value to 1.
+
+ If you want to allow any allocations other than used in the current frame to
+ become lost, set this value to 0.
+ */
+ uint32_t frameInUseCount;
+ /** \brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap.
+
+ If not NULL, it must be a pointer to an array of
+ `VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on
+ maximum number of bytes that can be allocated out of particular Vulkan memory
+ heap.
+
+ Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that
+ heap. This is also the default in case of `pHeapSizeLimit` = NULL.
+
+ If there is a limit defined for a heap:
+
+ - If user tries to allocate more memory from that heap using this allocator,
+ the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+ - If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the
+ value of this limit will be reported instead when using vmaGetMemoryProperties().
+
+ Warning! Using this feature may not be equivalent to installing a GPU with
+ smaller amount of memory, because graphics driver doesn't necessary fail new
+ allocations with `VK_ERROR_OUT_OF_DEVICE_MEMORY` result when memory capacity is
+ exceeded. It may return success and just silently migrate some device memory
+ blocks to system RAM. This driver behavior can also be controlled using
+ VK_AMD_memory_overallocation_behavior extension.
+ */
+ const VkDeviceSize* pHeapSizeLimit;
+ /** \brief Pointers to Vulkan functions. Can be null if you leave define `VMA_STATIC_VULKAN_FUNCTIONS 1`.
+
+ If you leave define `VMA_STATIC_VULKAN_FUNCTIONS 1` in configuration section,
+ you can pass null as this member, because the library will fetch pointers to
+ Vulkan functions internally in a static way, like:
+
+ vulkanFunctions.vkAllocateMemory = &vkAllocateMemory;
+
+ Fill this member if you want to provide your own pointers to Vulkan functions,
+ e.g. fetched using `vkGetInstanceProcAddr()` and `vkGetDeviceProcAddr()`.
+ */
+ const VmaVulkanFunctions* pVulkanFunctions;
+ /** \brief Parameters for recording of VMA calls. Can be null.
+
+ If not null, it enables recording of calls to VMA functions to a file.
+ If support for recording is not enabled using `VMA_RECORDING_ENABLED` macro,
+ creation of the allocator object fails with `VK_ERROR_FEATURE_NOT_PRESENT`.
+ */
+ const VmaRecordSettings* pRecordSettings;
+} VmaAllocatorCreateInfo;
+
+/// Creates Allocator object.
+VkResult vmaCreateAllocator(
+ const VmaAllocatorCreateInfo* pCreateInfo,
+ VmaAllocator* pAllocator);
+
+/// Destroys allocator object.
+void vmaDestroyAllocator(
+ VmaAllocator allocator);
+
+/**
+PhysicalDeviceProperties are fetched from physicalDevice by the allocator.
+You can access it here, without fetching it again on your own.
+*/
+void vmaGetPhysicalDeviceProperties(
+ VmaAllocator allocator,
+ const VkPhysicalDeviceProperties** ppPhysicalDeviceProperties);
+
+/**
+PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator.
+You can access it here, without fetching it again on your own.
+*/
+void vmaGetMemoryProperties(
+ VmaAllocator allocator,
+ const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties);
+
+/**
+\brief Given Memory Type Index, returns Property Flags of this memory type.
+
+This is just a convenience function. Same information can be obtained using
+vmaGetMemoryProperties().
+*/
+void vmaGetMemoryTypeProperties(
+ VmaAllocator allocator,
+ uint32_t memoryTypeIndex,
+ VkMemoryPropertyFlags* pFlags);
+
+/** \brief Sets index of the current frame.
+
+This function must be used if you make allocations with
+#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT and
+#VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flags to inform the allocator
+when a new frame begins. Allocations queried using vmaGetAllocationInfo() cannot
+become lost in the current frame.
+*/
+void vmaSetCurrentFrameIndex(
+ VmaAllocator allocator,
+ uint32_t frameIndex);
+
+/** \brief Calculated statistics of memory usage in entire allocator.
+*/
+typedef struct VmaStatInfo
+{
+ /// Number of `VkDeviceMemory` Vulkan memory blocks allocated.
+ uint32_t blockCount;
+ /// Number of #VmaAllocation allocation objects allocated.
+ uint32_t allocationCount;
+ /// Number of free ranges of memory between allocations.
+ uint32_t unusedRangeCount;
+ /// Total number of bytes occupied by all allocations.
+ VkDeviceSize usedBytes;
+ /// Total number of bytes occupied by unused ranges.
+ VkDeviceSize unusedBytes;
+ VkDeviceSize allocationSizeMin, allocationSizeAvg, allocationSizeMax;
+ VkDeviceSize unusedRangeSizeMin, unusedRangeSizeAvg, unusedRangeSizeMax;
+} VmaStatInfo;
+
+/// General statistics from current state of Allocator.
+typedef struct VmaStats
+{
+ VmaStatInfo memoryType[VK_MAX_MEMORY_TYPES];
+ VmaStatInfo memoryHeap[VK_MAX_MEMORY_HEAPS];
+ VmaStatInfo total;
+} VmaStats;
+
+/// Retrieves statistics from current state of the Allocator.
+void vmaCalculateStats(
+ VmaAllocator allocator,
+ VmaStats* pStats);
+
+#define VMA_STATS_STRING_ENABLED 1
+
+#if VMA_STATS_STRING_ENABLED
+
+/// Builds and returns statistics as string in JSON format.
+/** @param[out] ppStatsString Must be freed using vmaFreeStatsString() function.
+*/
+void vmaBuildStatsString(
+ VmaAllocator allocator,
+ char** ppStatsString,
+ VkBool32 detailedMap);
+
+void vmaFreeStatsString(
+ VmaAllocator allocator,
+ char* pStatsString);
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+/** \struct VmaPool
+\brief Represents custom memory pool
+
+Fill structure VmaPoolCreateInfo and call function vmaCreatePool() to create it.
+Call function vmaDestroyPool() to destroy it.
+
+For more information see [Custom memory pools](@ref choosing_memory_type_custom_memory_pools).
+*/
+VK_DEFINE_HANDLE(VmaPool)
+
+typedef enum VmaMemoryUsage
+{
+ /** No intended memory usage specified.
+ Use other members of VmaAllocationCreateInfo to specify your requirements.
+ */
+ VMA_MEMORY_USAGE_UNKNOWN = 0,
+ /** Memory will be used on device only, so fast access from the device is preferred.
+ It usually means device-local GPU (video) memory.
+ No need to be mappable on host.
+ It is roughly equivalent of `D3D12_HEAP_TYPE_DEFAULT`.
+
+ Usage:
+
+ - Resources written and read by device, e.g. images used as attachments.
+ - Resources transferred from host once (immutable) or infrequently and read by
+ device multiple times, e.g. textures to be sampled, vertex buffers, uniform
+ (constant) buffers, and majority of other types of resources used on GPU.
+
+ Allocation may still end up in `HOST_VISIBLE` memory on some implementations.
+ In such case, you are free to map it.
+ You can use #VMA_ALLOCATION_CREATE_MAPPED_BIT with this usage type.
+ */
+ VMA_MEMORY_USAGE_GPU_ONLY = 1,
+ /** Memory will be mappable on host.
+ It usually means CPU (system) memory.
+ Guarantees to be `HOST_VISIBLE` and `HOST_COHERENT`.
+ CPU access is typically uncached. Writes may be write-combined.
+ Resources created in this pool may still be accessible to the device, but access to them can be slow.
+ It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`.
+
+ Usage: Staging copy of resources used as transfer source.
+ */
+ VMA_MEMORY_USAGE_CPU_ONLY = 2,
+ /**
+ Memory that is both mappable on host (guarantees to be `HOST_VISIBLE`) and preferably fast to access by GPU.
+ CPU access is typically uncached. Writes may be write-combined.
+
+ Usage: Resources written frequently by host (dynamic), read by device. E.g. textures, vertex buffers, uniform buffers updated every frame or every draw call.
+ */
+ VMA_MEMORY_USAGE_CPU_TO_GPU = 3,
+ /** Memory mappable on host (guarantees to be `HOST_VISIBLE`) and cached.
+ It is roughly equivalent of `D3D12_HEAP_TYPE_READBACK`.
+
+ Usage:
+
+ - Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping.
+ - Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection.
+ */
+ VMA_MEMORY_USAGE_GPU_TO_CPU = 4,
+ VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF
+} VmaMemoryUsage;
+
+/// Flags to be passed as VmaAllocationCreateInfo::flags.
+typedef enum VmaAllocationCreateFlagBits {
+ /** \brief Set this flag if the allocation should have its own memory block.
+
+ Use it for special, big resources, like fullscreen images used as attachments.
+
+ This flag must also be used for host visible resources that you want to map
+ simultaneously because otherwise they might end up as regions of the same
+ `VkDeviceMemory`, while mapping same `VkDeviceMemory` multiple times
+ simultaneously is illegal.
+
+ You should not use this flag if VmaAllocationCreateInfo::pool is not null.
+ */
+ VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001,
+
+ /** \brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block.
+
+ If new allocation cannot be placed in any of the existing blocks, allocation
+ fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error.
+
+ You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and
+ #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense.
+
+ If VmaAllocationCreateInfo::pool is not null, this flag is implied and ignored. */
+ VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002,
+ /** \brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.
+
+ Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData.
+
+ Is it valid to use this flag for allocation made from memory type that is not
+ `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is
+ useful if you need an allocation that is efficient to use on GPU
+ (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that
+ support it (e.g. Intel GPU).
+
+ You should not use this flag together with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT.
+ */
+ VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004,
+ /** Allocation created with this flag can become lost as a result of another
+ allocation with #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag, so you
+ must check it before use.
+
+ To check if allocation is not lost, call vmaGetAllocationInfo() and check if
+ VmaAllocationInfo::deviceMemory is not `VK_NULL_HANDLE`.
+
+ For details about supporting lost allocations, see Lost Allocations
+ chapter of User Guide on Main Page.
+
+ You should not use this flag together with #VMA_ALLOCATION_CREATE_MAPPED_BIT.
+ */
+ VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT = 0x00000008,
+ /** While creating allocation using this flag, other allocations that were
+ created with flag #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT can become lost.
+
+ For details about supporting lost allocations, see Lost Allocations
+ chapter of User Guide on Main Page.
+ */
+ VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT = 0x00000010,
+ /** Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a
+ null-terminated string. Instead of copying pointer value, a local copy of the
+ string is made and stored in allocation's `pUserData`. The string is automatically
+ freed together with the allocation. It is also used in vmaBuildStatsString().
+ */
+ VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020,
+ /** Allocation will be created from upper stack in a double stack pool.
+
+ This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag.
+ */
+ VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040,
+
+ /** Allocation strategy that chooses smallest possible free range for the
+ allocation.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT = 0x00010000,
+ /** Allocation strategy that chooses biggest possible free range for the
+ allocation.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT = 0x00020000,
+ /** Allocation strategy that chooses first suitable free range for the
+ allocation.
+
+ "First" doesn't necessarily means the one with smallest offset in memory,
+ but rather the one that is easiest and fastest to find.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = 0x00040000,
+
+ /** Allocation strategy that tries to minimize memory usage.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT,
+ /** Allocation strategy that tries to minimize allocation time.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT,
+ /** Allocation strategy that tries to minimize memory fragmentation.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT = VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT,
+
+ /** A bit mask to extract only `STRATEGY` bits from entire set of flags.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MASK =
+ VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT |
+ VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT |
+ VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT,
+
+ VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaAllocationCreateFlagBits;
+typedef VkFlags VmaAllocationCreateFlags;
+
+typedef struct VmaAllocationCreateInfo
+{
+ /// Use #VmaAllocationCreateFlagBits enum.
+ VmaAllocationCreateFlags flags;
+ /** \brief Intended usage of memory.
+
+ You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n
+ If `pool` is not null, this member is ignored.
+ */
+ VmaMemoryUsage usage;
+ /** \brief Flags that must be set in a Memory Type chosen for an allocation.
+
+ Leave 0 if you specify memory requirements in other way. \n
+ If `pool` is not null, this member is ignored.*/
+ VkMemoryPropertyFlags requiredFlags;
+ /** \brief Flags that preferably should be set in a memory type chosen for an allocation.
+
+ Set to 0 if no additional flags are prefered. \n
+ If `pool` is not null, this member is ignored. */
+ VkMemoryPropertyFlags preferredFlags;
+ /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation.
+
+ Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if
+ it meets other requirements specified by this structure, with no further
+ restrictions on memory type index. \n
+ If `pool` is not null, this member is ignored.
+ */
+ uint32_t memoryTypeBits;
+ /** \brief Pool that this allocation should be created in.
+
+ Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members:
+ `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored.
+ */
+ VmaPool pool;
+ /** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().
+
+ If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either
+ null or pointer to a null-terminated string. The string will be then copied to
+ internal buffer, so it doesn't need to be valid after allocation call.
+ */
+ void* pUserData;
+} VmaAllocationCreateInfo;
+
+/**
+\brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo.
+
+This algorithm tries to find a memory type that:
+
+- Is allowed by memoryTypeBits.
+- Contains all the flags from pAllocationCreateInfo->requiredFlags.
+- Matches intended usage.
+- Has as many flags from pAllocationCreateInfo->preferredFlags as possible.
+
+\return Returns VK_ERROR_FEATURE_NOT_PRESENT if not found. Receiving such result
+from this function or any other allocating function probably means that your
+device doesn't support any memory type with requested features for the specific
+type of resource you want to use it for. Please check parameters of your
+resource, like image layout (OPTIMAL versus LINEAR) or mip level count.
+*/
+VkResult vmaFindMemoryTypeIndex(
+ VmaAllocator allocator,
+ uint32_t memoryTypeBits,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex);
+
+/**
+\brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo.
+
+It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex.
+It internally creates a temporary, dummy buffer that never has memory bound.
+It is just a convenience function, equivalent to calling:
+
+- `vkCreateBuffer`
+- `vkGetBufferMemoryRequirements`
+- `vmaFindMemoryTypeIndex`
+- `vkDestroyBuffer`
+*/
+VkResult vmaFindMemoryTypeIndexForBufferInfo(
+ VmaAllocator allocator,
+ const VkBufferCreateInfo* pBufferCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex);
+
+/**
+\brief Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo.
+
+It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex.
+It internally creates a temporary, dummy image that never has memory bound.
+It is just a convenience function, equivalent to calling:
+
+- `vkCreateImage`
+- `vkGetImageMemoryRequirements`
+- `vmaFindMemoryTypeIndex`
+- `vkDestroyImage`
+*/
+VkResult vmaFindMemoryTypeIndexForImageInfo(
+ VmaAllocator allocator,
+ const VkImageCreateInfo* pImageCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex);
+
+/// Flags to be passed as VmaPoolCreateInfo::flags.
+typedef enum VmaPoolCreateFlagBits {
+ /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored.
+
+ This is an optional optimization flag.
+
+ If you always allocate using vmaCreateBuffer(), vmaCreateImage(),
+ vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator
+ knows exact type of your allocations so it can handle Buffer-Image Granularity
+ in the optimal way.
+
+ If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(),
+ exact type of such allocations is not known, so allocator must be conservative
+ in handling Buffer-Image Granularity, which can lead to suboptimal allocation
+ (wasted memory). In that case, if you can make sure you always allocate only
+ buffers and linear images or only optimal images out of this pool, use this flag
+ to make allocator disregard Buffer-Image Granularity and so make allocations
+ faster and more optimal.
+ */
+ VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002,
+
+ /** \brief Enables alternative, linear allocation algorithm in this pool.
+
+ Specify this flag to enable linear allocation algorithm, which always creates
+ new allocations after last one and doesn't reuse space from allocations freed in
+ between. It trades memory consumption for simplified algorithm and data
+ structure, which has better performance and uses less memory for metadata.
+
+ By using this flag, you can achieve behavior of free-at-once, stack,
+ ring buffer, and double stack. For details, see documentation chapter
+ \ref linear_algorithm.
+
+ When using this flag, you must specify VmaPoolCreateInfo::maxBlockCount == 1 (or 0 for default).
+
+ For more details, see [Linear allocation algorithm](@ref linear_algorithm).
+ */
+ VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004,
+
+ /** \brief Enables alternative, buddy allocation algorithm in this pool.
+
+ It operates on a tree of blocks, each having size that is a power of two and
+ a half of its parent's size. Comparing to default algorithm, this one provides
+ faster allocation and deallocation and decreased external fragmentation,
+ at the expense of more memory wasted (internal fragmentation).
+
+ For more details, see [Buddy allocation algorithm](@ref buddy_algorithm).
+ */
+ VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT = 0x00000008,
+
+ /** Bit mask to extract only `ALGORITHM` bits from entire set of flags.
+ */
+ VMA_POOL_CREATE_ALGORITHM_MASK =
+ VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT |
+ VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT,
+
+ VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaPoolCreateFlagBits;
+typedef VkFlags VmaPoolCreateFlags;
+
+/** \brief Describes parameter of created #VmaPool.
+*/
+typedef struct VmaPoolCreateInfo {
+ /** \brief Vulkan memory type index to allocate this pool from.
+ */
+ uint32_t memoryTypeIndex;
+ /** \brief Use combination of #VmaPoolCreateFlagBits.
+ */
+ VmaPoolCreateFlags flags;
+ /** \brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional.
+
+ Specify nonzero to set explicit, constant size of memory blocks used by this
+ pool.
+
+ Leave 0 to use default and let the library manage block sizes automatically.
+ Sizes of particular blocks may vary.
+ */
+ VkDeviceSize blockSize;
+ /** \brief Minimum number of blocks to be always allocated in this pool, even if they stay empty.
+
+ Set to 0 to have no preallocated blocks and allow the pool be completely empty.
+ */
+ size_t minBlockCount;
+ /** \brief Maximum number of blocks that can be allocated in this pool. Optional.
+
+ Set to 0 to use default, which is `SIZE_MAX`, which means no limit.
+
+ Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated
+ throughout whole lifetime of this pool.
+ */
+ size_t maxBlockCount;
+ /** \brief Maximum number of additional frames that are in use at the same time as current frame.
+
+ This value is used only when you make allocations with
+ #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocation cannot become
+ lost if allocation.lastUseFrameIndex >= allocator.currentFrameIndex - frameInUseCount.
+
+ For example, if you double-buffer your command buffers, so resources used for
+ rendering in previous frame may still be in use by the GPU at the moment you
+ allocate resources needed for the current frame, set this value to 1.
+
+ If you want to allow any allocations other than used in the current frame to
+ become lost, set this value to 0.
+ */
+ uint32_t frameInUseCount;
+} VmaPoolCreateInfo;
+
+/** \brief Describes parameter of existing #VmaPool.
+*/
+typedef struct VmaPoolStats {
+ /** \brief Total amount of `VkDeviceMemory` allocated from Vulkan for this pool, in bytes.
+ */
+ VkDeviceSize size;
+ /** \brief Total number of bytes in the pool not used by any #VmaAllocation.
+ */
+ VkDeviceSize unusedSize;
+ /** \brief Number of #VmaAllocation objects created from this pool that were not destroyed or lost.
+ */
+ size_t allocationCount;
+ /** \brief Number of continuous memory ranges in the pool not used by any #VmaAllocation.
+ */
+ size_t unusedRangeCount;
+ /** \brief Size of the largest continuous free memory region available for new allocation.
+
+ Making a new allocation of that size is not guaranteed to succeed because of
+ possible additional margin required to respect alignment and buffer/image
+ granularity.
+ */
+ VkDeviceSize unusedRangeSizeMax;
+ /** \brief Number of `VkDeviceMemory` blocks allocated for this pool.
+ */
+ size_t blockCount;
+} VmaPoolStats;
+
+/** \brief Allocates Vulkan device memory and creates #VmaPool object.
+
+@param allocator Allocator object.
+@param pCreateInfo Parameters of pool to create.
+@param[out] pPool Handle to created pool.
+*/
+VkResult vmaCreatePool(
+ VmaAllocator allocator,
+ const VmaPoolCreateInfo* pCreateInfo,
+ VmaPool* pPool);
+
+/** \brief Destroys #VmaPool object and frees Vulkan device memory.
+*/
+void vmaDestroyPool(
+ VmaAllocator allocator,
+ VmaPool pool);
+
+/** \brief Retrieves statistics of existing #VmaPool object.
+
+@param allocator Allocator object.
+@param pool Pool object.
+@param[out] pPoolStats Statistics of specified pool.
+*/
+void vmaGetPoolStats(
+ VmaAllocator allocator,
+ VmaPool pool,
+ VmaPoolStats* pPoolStats);
+
+/** \brief Marks all allocations in given pool as lost if they are not used in current frame or VmaPoolCreateInfo::frameInUseCount back from now.
+
+@param allocator Allocator object.
+@param pool Pool.
+@param[out] pLostAllocationCount Number of allocations marked as lost. Optional - pass null if you don't need this information.
+*/
+void vmaMakePoolAllocationsLost(
+ VmaAllocator allocator,
+ VmaPool pool,
+ size_t* pLostAllocationCount);
+
+/** \brief Checks magic number in margins around all allocations in given memory pool in search for corruptions.
+
+Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,
+`VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is
+`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection).
+
+Possible return values:
+
+- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool.
+- `VK_SUCCESS` - corruption detection has been performed and succeeded.
+- `VK_ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations.
+ `VMA_ASSERT` is also fired in that case.
+- Other value: Error returned by Vulkan, e.g. memory mapping failure.
+*/
+VkResult vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool);
+
+/** \struct VmaAllocation
+\brief Represents single memory allocation.
+
+It may be either dedicated block of `VkDeviceMemory` or a specific region of a bigger block of this type
+plus unique offset.
+
+There are multiple ways to create such object.
+You need to fill structure VmaAllocationCreateInfo.
+For more information see [Choosing memory type](@ref choosing_memory_type).
+
+Although the library provides convenience functions that create Vulkan buffer or image,
+allocate memory for it and bind them together,
+binding of the allocation to a buffer or an image is out of scope of the allocation itself.
+Allocation object can exist without buffer/image bound,
+binding can be done manually by the user, and destruction of it can be done
+independently of destruction of the allocation.
+
+The object also remembers its size and some other information.
+To retrieve this information, use function vmaGetAllocationInfo() and inspect
+returned structure VmaAllocationInfo.
+
+Some kinds allocations can be in lost state.
+For more information, see [Lost allocations](@ref lost_allocations).
+*/
+VK_DEFINE_HANDLE(VmaAllocation)
+
+/** \brief Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().
+*/
+typedef struct VmaAllocationInfo {
+ /** \brief Memory type index that this allocation was allocated from.
+
+ It never changes.
+ */
+ uint32_t memoryType;
+ /** \brief Handle to Vulkan memory object.
+
+ Same memory object can be shared by multiple allocations.
+
+ It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost.
+
+ If the allocation is lost, it is equal to `VK_NULL_HANDLE`.
+ */
+ VkDeviceMemory deviceMemory;
+ /** \brief Offset into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory, offset) pair is unique to this allocation.
+
+ It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost.
+ */
+ VkDeviceSize offset;
+ /** \brief Size of this allocation, in bytes.
+
+ It never changes, unless allocation is lost.
+ */
+ VkDeviceSize size;
+ /** \brief Pointer to the beginning of this allocation as mapped data.
+
+ If the allocation hasn't been mapped using vmaMapMemory() and hasn't been
+ created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value null.
+
+ It can change after call to vmaMapMemory(), vmaUnmapMemory().
+ It can also change after call to vmaDefragment() if this allocation is passed to the function.
+ */
+ void* pMappedData;
+ /** \brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData().
+
+ It can change after call to vmaSetAllocationUserData() for this allocation.
+ */
+ void* pUserData;
+} VmaAllocationInfo;
+
+/** \brief General purpose memory allocation.
+
+@param[out] pAllocation Handle to allocated memory.
+@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+
+You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages().
+
+It is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(),
+vmaCreateBuffer(), vmaCreateImage() instead whenever possible.
+*/
+VkResult vmaAllocateMemory(
+ VmaAllocator allocator,
+ const VkMemoryRequirements* pVkMemoryRequirements,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief General purpose memory allocation for multiple allocation objects at once.
+
+@param allocator Allocator object.
+@param pVkMemoryRequirements Memory requirements for each allocation.
+@param pCreateInfo Creation parameters for each alloction.
+@param allocationCount Number of allocations to make.
+@param[out] pAllocations Pointer to array that will be filled with handles to created allocations.
+@param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations.
+
+You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages().
+
+Word "pages" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding.
+It is just a general purpose allocation function able to make multiple allocations at once.
+It may be internally optimized to be more efficient than calling vmaAllocateMemory() `allocationCount` times.
+
+All allocations are made using same parameters. All of them are created out of the same memory pool and type.
+If any allocation fails, all allocations already made within this function call are also freed, so that when
+returned result is not `VK_SUCCESS`, `pAllocation` array is always entirely filled with `VK_NULL_HANDLE`.
+*/
+VkResult vmaAllocateMemoryPages(
+ VmaAllocator allocator,
+ const VkMemoryRequirements* pVkMemoryRequirements,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ size_t allocationCount,
+ VmaAllocation* pAllocations,
+ VmaAllocationInfo* pAllocationInfo);
+
+/**
+@param[out] pAllocation Handle to allocated memory.
+@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+
+You should free the memory using vmaFreeMemory().
+*/
+VkResult vmaAllocateMemoryForBuffer(
+ VmaAllocator allocator,
+ VkBuffer buffer,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/// Function similar to vmaAllocateMemoryForBuffer().
+VkResult vmaAllocateMemoryForImage(
+ VmaAllocator allocator,
+ VkImage image,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage().
+
+Passing `VK_NULL_HANDLE` as `allocation` is valid. Such function call is just skipped.
+*/
+void vmaFreeMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation);
+
+/** \brief Frees memory and destroys multiple allocations.
+
+Word "pages" is just a suggestion to use this function to free pieces of memory used for sparse binding.
+It is just a general purpose function to free memory and destroy allocations made using e.g. vmaAllocateMemory(),
+vmaAllocateMemoryPages() and other functions.
+It may be internally optimized to be more efficient than calling vmaFreeMemory() `allocationCount` times.
+
+Allocations in `pAllocations` array can come from any memory pools and types.
+Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entries are just skipped.
+*/
+void vmaFreeMemoryPages(
+ VmaAllocator allocator,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+/** \brief Tries to resize an allocation in place, if there is enough free memory after it.
+
+Tries to change allocation's size without moving or reallocating it.
+You can both shrink and grow allocation size.
+When growing, it succeeds only when the allocation belongs to a memory block with enough
+free space after it.
+
+Returns `VK_SUCCESS` if allocation's size has been successfully changed.
+Returns `VK_ERROR_OUT_OF_POOL_MEMORY` if allocation's size could not be changed.
+
+After successful call to this function, VmaAllocationInfo::size of this allocation changes.
+All other parameters stay the same: memory pool and type, alignment, offset, mapped pointer.
+
+- Calling this function on allocation that is in lost state fails with result `VK_ERROR_VALIDATION_FAILED_EXT`.
+- Calling this function with `newSize` same as current allocation size does nothing and returns `VK_SUCCESS`.
+- Resizing dedicated allocations, as well as allocations created in pools that use linear
+ or buddy algorithm, is not supported.
+ The function returns `VK_ERROR_FEATURE_NOT_PRESENT` in such cases.
+ Support may be added in the future.
+*/
+VkResult vmaResizeAllocation(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkDeviceSize newSize);
+
+/** \brief Returns current information about specified allocation and atomically marks it as used in current frame.
+
+Current paramters of given allocation are returned in `pAllocationInfo`.
+
+This function also atomically "touches" allocation - marks it as used in current frame,
+just like vmaTouchAllocation().
+If the allocation is in lost state, `pAllocationInfo->deviceMemory == VK_NULL_HANDLE`.
+
+Although this function uses atomics and doesn't lock any mutex, so it should be quite efficient,
+you can avoid calling it too often.
+
+- You can retrieve same VmaAllocationInfo structure while creating your resource, from function
+ vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change
+ (e.g. due to defragmentation or allocation becoming lost).
+- If you just want to check if allocation is not lost, vmaTouchAllocation() will work faster.
+*/
+void vmaGetAllocationInfo(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Returns `VK_TRUE` if allocation is not lost and atomically marks it as used in current frame.
+
+If the allocation has been created with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
+this function returns `VK_TRUE` if it's not in lost state, so it can still be used.
+It then also atomically "touches" the allocation - marks it as used in current frame,
+so that you can be sure it won't become lost in current frame or next `frameInUseCount` frames.
+
+If the allocation is in lost state, the function returns `VK_FALSE`.
+Memory of such allocation, as well as buffer or image bound to it, should not be used.
+Lost allocation and the buffer/image still need to be destroyed.
+
+If the allocation has been created without #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
+this function always returns `VK_TRUE`.
+*/
+VkBool32 vmaTouchAllocation(
+ VmaAllocator allocator,
+ VmaAllocation allocation);
+
+/** \brief Sets pUserData in given allocation to new value.
+
+If the allocation was created with VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT,
+pUserData must be either null, or pointer to a null-terminated string. The function
+makes local copy of the string and sets it as allocation's `pUserData`. String
+passed as pUserData doesn't need to be valid for whole lifetime of the allocation -
+you can free it after this call. String previously pointed by allocation's
+pUserData is freed from memory.
+
+If the flag was not used, the value of pointer `pUserData` is just copied to
+allocation's `pUserData`. It is opaque, so you can use it however you want - e.g.
+as a pointer, ordinal number or some handle to you own data.
+*/
+void vmaSetAllocationUserData(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ void* pUserData);
+
+/** \brief Creates new allocation that is in lost state from the beginning.
+
+It can be useful if you need a dummy, non-null allocation.
+
+You still need to destroy created object using vmaFreeMemory().
+
+Returned allocation is not tied to any specific memory pool or memory type and
+not bound to any image or buffer. It has size = 0. It cannot be turned into
+a real, non-empty allocation.
+*/
+void vmaCreateLostAllocation(
+ VmaAllocator allocator,
+ VmaAllocation* pAllocation);
+
+/** \brief Maps memory represented by given allocation and returns pointer to it.
+
+Maps memory represented by given allocation to make it accessible to CPU code.
+When succeeded, `*ppData` contains pointer to first byte of this memory.
+If the allocation is part of bigger `VkDeviceMemory` block, the pointer is
+correctly offseted to the beginning of region assigned to this particular
+allocation.
+
+Mapping is internally reference-counted and synchronized, so despite raw Vulkan
+function `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory`
+multiple times simultaneously, it is safe to call this function on allocations
+assigned to the same memory block. Actual Vulkan memory will be mapped on first
+mapping and unmapped on last unmapping.
+
+If the function succeeded, you must call vmaUnmapMemory() to unmap the
+allocation when mapping is no longer needed or before freeing the allocation, at
+the latest.
+
+It also safe to call this function multiple times on the same allocation. You
+must call vmaUnmapMemory() same number of times as you called vmaMapMemory().
+
+It is also safe to call this function on allocation created with
+#VMA_ALLOCATION_CREATE_MAPPED_BIT flag. Its memory stays mapped all the time.
+You must still call vmaUnmapMemory() same number of times as you called
+vmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the
+"0-th" mapping made automatically due to #VMA_ALLOCATION_CREATE_MAPPED_BIT flag.
+
+This function fails when used on allocation made in memory type that is not
+`HOST_VISIBLE`.
+
+This function always fails when called for allocation that was created with
+#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocations cannot be
+mapped.
+*/
+VkResult vmaMapMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ void** ppData);
+
+/** \brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().
+
+For details, see description of vmaMapMemory().
+*/
+void vmaUnmapMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation);
+
+/** \brief Flushes memory of given allocation.
+
+Calls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation.
+
+- `offset` must be relative to the beginning of allocation.
+- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.
+- `offset` and `size` don't have to be aligned.
+ They are internally rounded down/up to multiply of `nonCoherentAtomSize`.
+- If `size` is 0, this call is ignored.
+- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,
+ this call is ignored.
+*/
+void vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+
+/** \brief Invalidates memory of given allocation.
+
+Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation.
+
+- `offset` must be relative to the beginning of allocation.
+- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.
+- `offset` and `size` don't have to be aligned.
+ They are internally rounded down/up to multiply of `nonCoherentAtomSize`.
+- If `size` is 0, this call is ignored.
+- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,
+ this call is ignored.
+*/
+void vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+
+/** \brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions.
+
+@param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked.
+
+Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,
+`VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are
+`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection).
+
+Possible return values:
+
+- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types.
+- `VK_SUCCESS` - corruption detection has been performed and succeeded.
+- `VK_ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations.
+ `VMA_ASSERT` is also fired in that case.
+- Other value: Error returned by Vulkan, e.g. memory mapping failure.
+*/
+VkResult vmaCheckCorruption(VmaAllocator allocator, uint32_t memoryTypeBits);
+
+/** \struct VmaDefragmentationContext
+\brief Represents Opaque object that represents started defragmentation process.
+
+Fill structure #VmaDefragmentationInfo2 and call function vmaDefragmentationBegin() to create it.
+Call function vmaDefragmentationEnd() to destroy it.
+*/
+VK_DEFINE_HANDLE(VmaDefragmentationContext)
+
+/// Flags to be used in vmaDefragmentationBegin(). None at the moment. Reserved for future use.
+typedef enum VmaDefragmentationFlagBits {
+ VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaDefragmentationFlagBits;
+typedef VkFlags VmaDefragmentationFlags;
+
+/** \brief Parameters for defragmentation.
+
+To be used with function vmaDefragmentationBegin().
+*/
+typedef struct VmaDefragmentationInfo2 {
+ /** \brief Reserved for future use. Should be 0.
+ */
+ VmaDefragmentationFlags flags;
+ /** \brief Number of allocations in `pAllocations` array.
+ */
+ uint32_t allocationCount;
+ /** \brief Pointer to array of allocations that can be defragmented.
+
+ The array should have `allocationCount` elements.
+ The array should not contain nulls.
+ Elements in the array should be unique - same allocation cannot occur twice.
+ It is safe to pass allocations that are in the lost state - they are ignored.
+ All allocations not present in this array are considered non-moveable during this defragmentation.
+ */
+ VmaAllocation* pAllocations;
+ /** \brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation.
+
+ The array should have `allocationCount` elements.
+ You can pass null if you are not interested in this information.
+ */
+ VkBool32* pAllocationsChanged;
+ /** \brief Numer of pools in `pPools` array.
+ */
+ uint32_t poolCount;
+ /** \brief Either null or pointer to array of pools to be defragmented.
+
+ All the allocations in the specified pools can be moved during defragmentation
+ and there is no way to check if they were really moved as in `pAllocationsChanged`,
+ so you must query all the allocations in all these pools for new `VkDeviceMemory`
+ and offset using vmaGetAllocationInfo() if you might need to recreate buffers
+ and images bound to them.
+
+ The array should have `poolCount` elements.
+ The array should not contain nulls.
+ Elements in the array should be unique - same pool cannot occur twice.
+
+ Using this array is equivalent to specifying all allocations from the pools in `pAllocations`.
+ It might be more efficient.
+ */
+ VmaPool* pPools;
+ /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`.
+
+ `VK_WHOLE_SIZE` means no limit.
+ */
+ VkDeviceSize maxCpuBytesToMove;
+ /** \brief Maximum number of allocations that can be moved to a different place using transfers on CPU side, like `memcpy()`, `memmove()`.
+
+ `UINT32_MAX` means no limit.
+ */
+ uint32_t maxCpuAllocationsToMove;
+ /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to `commandBuffer`.
+
+ `VK_WHOLE_SIZE` means no limit.
+ */
+ VkDeviceSize maxGpuBytesToMove;
+ /** \brief Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to `commandBuffer`.
+
+ `UINT32_MAX` means no limit.
+ */
+ uint32_t maxGpuAllocationsToMove;
+ /** \brief Optional. Command buffer where GPU copy commands will be posted.
+
+ If not null, it must be a valid command buffer handle that supports Transfer queue type.
+ It must be in the recording state and outside of a render pass instance.
+ You need to submit it and make sure it finished execution before calling vmaDefragmentationEnd().
+
+ Passing null means that only CPU defragmentation will be performed.
+ */
+ VkCommandBuffer commandBuffer;
+} VmaDefragmentationInfo2;
+
+/** \brief Deprecated. Optional configuration parameters to be passed to function vmaDefragment().
+
+\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead.
+*/
+typedef struct VmaDefragmentationInfo {
+ /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places.
+
+ Default is `VK_WHOLE_SIZE`, which means no limit.
+ */
+ VkDeviceSize maxBytesToMove;
+ /** \brief Maximum number of allocations that can be moved to different place.
+
+ Default is `UINT32_MAX`, which means no limit.
+ */
+ uint32_t maxAllocationsToMove;
+} VmaDefragmentationInfo;
+
+/** \brief Statistics returned by function vmaDefragment(). */
+typedef struct VmaDefragmentationStats {
+ /// Total number of bytes that have been copied while moving allocations to different places.
+ VkDeviceSize bytesMoved;
+ /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects.
+ VkDeviceSize bytesFreed;
+ /// Number of allocations that have been moved to different places.
+ uint32_t allocationsMoved;
+ /// Number of empty `VkDeviceMemory` objects that have been released to the system.
+ uint32_t deviceMemoryBlocksFreed;
+} VmaDefragmentationStats;
+
+/** \brief Begins defragmentation process.
+
+@param allocator Allocator object.
+@param pInfo Structure filled with parameters of defragmentation.
+@param[out] pStats Optional. Statistics of defragmentation. You can pass null if you are not interested in this information.
+@param[out] pContext Context object that must be passed to vmaDefragmentationEnd() to finish defragmentation.
+@return `VK_SUCCESS` and `*pContext == null` if defragmentation finished within this function call. `VK_NOT_READY` and `*pContext != null` if defragmentation has been started and you need to call vmaDefragmentationEnd() to finish it. Negative value in case of error.
+
+Use this function instead of old, deprecated vmaDefragment().
+
+Warning! Between the call to vmaDefragmentationBegin() and vmaDefragmentationEnd():
+
+- You should not use any of allocations passed as `pInfo->pAllocations` or
+ any allocations that belong to pools passed as `pInfo->pPools`,
+ including calling vmaGetAllocationInfo(), vmaTouchAllocation(), or access
+ their data.
+- Some mutexes protecting internal data structures may be locked, so trying to
+ make or free any allocations, bind buffers or images, map memory, or launch
+ another simultaneous defragmentation in between may cause stall (when done on
+ another thread) or deadlock (when done on the same thread), unless you are
+ 100% sure that defragmented allocations are in different pools.
+- Information returned via `pStats` and `pInfo->pAllocationsChanged` are undefined.
+ They become valid after call to vmaDefragmentationEnd().
+- If `pInfo->commandBuffer` is not null, you must submit that command buffer
+ and make sure it finished execution before calling vmaDefragmentationEnd().
+*/
+VkResult vmaDefragmentationBegin(
+ VmaAllocator allocator,
+ const VmaDefragmentationInfo2* pInfo,
+ VmaDefragmentationStats* pStats,
+ VmaDefragmentationContext *pContext);
+
+/** \brief Ends defragmentation process.
+
+Use this function to finish defragmentation started by vmaDefragmentationBegin().
+It is safe to pass `context == null`. The function then does nothing.
+*/
+VkResult vmaDefragmentationEnd(
+ VmaAllocator allocator,
+ VmaDefragmentationContext context);
+
+/** \brief Deprecated. Compacts memory by moving allocations.
+
+@param pAllocations Array of allocations that can be moved during this compation.
+@param allocationCount Number of elements in pAllocations and pAllocationsChanged arrays.
+@param[out] pAllocationsChanged Array of boolean values that will indicate whether matching allocation in pAllocations array has been moved. This parameter is optional. Pass null if you don't need this information.
+@param pDefragmentationInfo Configuration parameters. Optional - pass null to use default values.
+@param[out] pDefragmentationStats Statistics returned by the function. Optional - pass null if you don't need this information.
+@return `VK_SUCCESS` if completed, negative error code in case of error.
+
+\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead.
+
+This function works by moving allocations to different places (different
+`VkDeviceMemory` objects and/or different offsets) in order to optimize memory
+usage. Only allocations that are in `pAllocations` array can be moved. All other
+allocations are considered nonmovable in this call. Basic rules:
+
+- Only allocations made in memory types that have
+ `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`
+ flags can be compacted. You may pass other allocations but it makes no sense -
+ these will never be moved.
+- Custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT or
+ #VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag are not defragmented. Allocations
+ passed to this function that come from such pools are ignored.
+- Allocations created with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT or
+ created as dedicated allocations for any other reason are also ignored.
+- Both allocations made with or without #VMA_ALLOCATION_CREATE_MAPPED_BIT
+ flag can be compacted. If not persistently mapped, memory will be mapped
+ temporarily inside this function if needed.
+- You must not pass same #VmaAllocation object multiple times in `pAllocations` array.
+
+The function also frees empty `VkDeviceMemory` blocks.
+
+Warning: This function may be time-consuming, so you shouldn't call it too often
+(like after every resource creation/destruction).
+You can call it on special occasions (like when reloading a game level or
+when you just destroyed a lot of objects). Calling it every frame may be OK, but
+you should measure that on your platform.
+
+For more information, see [Defragmentation](@ref defragmentation) chapter.
+*/
+VkResult vmaDefragment(
+ VmaAllocator allocator,
+ VmaAllocation* pAllocations,
+ size_t allocationCount,
+ VkBool32* pAllocationsChanged,
+ const VmaDefragmentationInfo *pDefragmentationInfo,
+ VmaDefragmentationStats* pDefragmentationStats);
+
+/** \brief Binds buffer to allocation.
+
+Binds specified buffer to region of memory represented by specified allocation.
+Gets `VkDeviceMemory` handle and offset from the allocation.
+If you want to create a buffer, allocate memory for it and bind them together separately,
+you should use this function for binding instead of standard `vkBindBufferMemory()`,
+because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple
+allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously
+(which is illegal in Vulkan).
+
+It is recommended to use function vmaCreateBuffer() instead of this one.
+*/
+VkResult vmaBindBufferMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkBuffer buffer);
+
+/** \brief Binds image to allocation.
+
+Binds specified image to region of memory represented by specified allocation.
+Gets `VkDeviceMemory` handle and offset from the allocation.
+If you want to create an image, allocate memory for it and bind them together separately,
+you should use this function for binding instead of standard `vkBindImageMemory()`,
+because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple
+allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously
+(which is illegal in Vulkan).
+
+It is recommended to use function vmaCreateImage() instead of this one.
+*/
+VkResult vmaBindImageMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkImage image);
+
+/**
+@param[out] pBuffer Buffer that was created.
+@param[out] pAllocation Allocation that was created.
+@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+
+This function automatically:
+
+-# Creates buffer.
+-# Allocates appropriate memory for it.
+-# Binds the buffer with the memory.
+
+If any of these operations fail, buffer and allocation are not created,
+returned value is negative error code, *pBuffer and *pAllocation are null.
+
+If the function succeeded, you must destroy both buffer and allocation when you
+no longer need them using either convenience function vmaDestroyBuffer() or
+separately, using `vkDestroyBuffer()` and vmaFreeMemory().
+
+If VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used,
+VK_KHR_dedicated_allocation extension is used internally to query driver whether
+it requires or prefers the new buffer to have dedicated allocation. If yes,
+and if dedicated allocation is possible (VmaAllocationCreateInfo::pool is null
+and VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated
+allocation for this buffer, just like when using
+VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+*/
+VkResult vmaCreateBuffer(
+ VmaAllocator allocator,
+ const VkBufferCreateInfo* pBufferCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkBuffer* pBuffer,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Destroys Vulkan buffer and frees allocated memory.
+
+This is just a convenience function equivalent to:
+
+\code
+vkDestroyBuffer(device, buffer, allocationCallbacks);
+vmaFreeMemory(allocator, allocation);
+\endcode
+
+It it safe to pass null as buffer and/or allocation.
+*/
+void vmaDestroyBuffer(
+ VmaAllocator allocator,
+ VkBuffer buffer,
+ VmaAllocation allocation);
+
+/// Function similar to vmaCreateBuffer().
+VkResult vmaCreateImage(
+ VmaAllocator allocator,
+ const VkImageCreateInfo* pImageCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkImage* pImage,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Destroys Vulkan image and frees allocated memory.
+
+This is just a convenience function equivalent to:
+
+\code
+vkDestroyImage(device, image, allocationCallbacks);
+vmaFreeMemory(allocator, allocation);
+\endcode
+
+It it safe to pass null as image and/or allocation.
+*/
+void vmaDestroyImage(
+ VmaAllocator allocator,
+ VkImage image,
+ VmaAllocation allocation);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AMD_VULKAN_MEMORY_ALLOCATOR_H
+
+// For Visual Studio IntelliSense.
+#if defined(__cplusplus) && defined(__INTELLISENSE__)
+#define VMA_IMPLEMENTATION
+#endif
+
+#ifdef VMA_IMPLEMENTATION
+#undef VMA_IMPLEMENTATION
+
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+
+/*******************************************************************************
+CONFIGURATION SECTION
+
+Define some of these macros before each #include of this header or change them
+here if you need other then default behavior depending on your environment.
+*/
+
+/*
+Define this macro to 1 to make the library fetch pointers to Vulkan functions
+internally, like:
+
+ vulkanFunctions.vkAllocateMemory = &vkAllocateMemory;
+
+Define to 0 if you are going to provide you own pointers to Vulkan functions via
+VmaAllocatorCreateInfo::pVulkanFunctions.
+*/
+#if !defined(VMA_STATIC_VULKAN_FUNCTIONS) && !defined(VK_NO_PROTOTYPES)
+#define VMA_STATIC_VULKAN_FUNCTIONS 1
+#endif
+
+// Define this macro to 1 to make the library use STL containers instead of its own implementation.
+//#define VMA_USE_STL_CONTAINERS 1
+
+/* Set this macro to 1 to make the library including and using STL containers:
+std::pair, std::vector, std::list, std::unordered_map.
+
+Set it to 0 or undefined to make the library using its own implementation of
+the containers.
+*/
+#if VMA_USE_STL_CONTAINERS
+ #define VMA_USE_STL_VECTOR 1
+ #define VMA_USE_STL_UNORDERED_MAP 1
+ #define VMA_USE_STL_LIST 1
+#endif
+
+#ifndef VMA_USE_STL_SHARED_MUTEX
+ // Minimum Visual Studio 2015 Update 2
+ #if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918
+ #define VMA_USE_STL_SHARED_MUTEX 1
+ #endif
+#endif
+
+#if VMA_USE_STL_VECTOR
+ #include <vector>
+#endif
+
+#if VMA_USE_STL_UNORDERED_MAP
+ #include <unordered_map>
+#endif
+
+#if VMA_USE_STL_LIST
+ #include <list>
+#endif
+
+/*
+Following headers are used in this CONFIGURATION section only, so feel free to
+remove them if not needed.
+*/
+#include <cassert> // for assert
+#include <algorithm> // for min, max
+#include <mutex>
+#include <atomic> // for std::atomic
+
+#ifndef VMA_NULL
+ // Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.
+ #define VMA_NULL nullptr
+#endif
+
+#if defined(__ANDROID_API__) && (__ANDROID_API__ < 16)
+#include <cstdlib>
+void *aligned_alloc(size_t alignment, size_t size)
+{
+ // alignment must be >= sizeof(void*)
+ if(alignment < sizeof(void*))
+ {
+ alignment = sizeof(void*);
+ }
+
+ return memalign(alignment, size);
+}
+#elif defined(__APPLE__) || defined(__ANDROID__)
+#include <cstdlib>
+void *aligned_alloc(size_t alignment, size_t size)
+{
+ // alignment must be >= sizeof(void*)
+ if(alignment < sizeof(void*))
+ {
+ alignment = sizeof(void*);
+ }
+
+ void *pointer;
+ if(posix_memalign(&pointer, alignment, size) == 0)
+ return pointer;
+ return VMA_NULL;
+}
+#endif
+
+// If your compiler is not compatible with C++11 and definition of
+// aligned_alloc() function is missing, uncommeting following line may help:
+
+//#include <malloc.h>
+
+// Normal assert to check for programmer's errors, especially in Debug configuration.
+#ifndef VMA_ASSERT
+ #ifdef _DEBUG
+ #define VMA_ASSERT(expr) assert(expr)
+ #else
+ #define VMA_ASSERT(expr)
+ #endif
+#endif
+
+// Assert that will be called very often, like inside data structures e.g. operator[].
+// Making it non-empty can make program slow.
+#ifndef VMA_HEAVY_ASSERT
+ #ifdef _DEBUG
+ #define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr)
+ #else
+ #define VMA_HEAVY_ASSERT(expr)
+ #endif
+#endif
+
+#ifndef VMA_ALIGN_OF
+ #define VMA_ALIGN_OF(type) (__alignof(type))
+#endif
+
+#ifndef VMA_SYSTEM_ALIGNED_MALLOC
+ #if defined(_WIN32)
+ #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (_aligned_malloc((size), (alignment)))
+ #else
+ #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (aligned_alloc((alignment), (size) ))
+ #endif
+#endif
+
+#ifndef VMA_SYSTEM_FREE
+ #if defined(_WIN32)
+ #define VMA_SYSTEM_FREE(ptr) _aligned_free(ptr)
+ #else
+ #define VMA_SYSTEM_FREE(ptr) free(ptr)
+ #endif
+#endif
+
+#ifndef VMA_MIN
+ #define VMA_MIN(v1, v2) (std::min((v1), (v2)))
+#endif
+
+#ifndef VMA_MAX
+ #define VMA_MAX(v1, v2) (std::max((v1), (v2)))
+#endif
+
+#ifndef VMA_SWAP
+ #define VMA_SWAP(v1, v2) std::swap((v1), (v2))
+#endif
+
+#ifndef VMA_SORT
+ #define VMA_SORT(beg, end, cmp) std::sort(beg, end, cmp)
+#endif
+
+#ifndef VMA_DEBUG_LOG
+ #define VMA_DEBUG_LOG(format, ...)
+ /*
+ #define VMA_DEBUG_LOG(format, ...) do { \
+ printf(format, __VA_ARGS__); \
+ printf("\n"); \
+ } while(false)
+ */
+#endif
+
+// Define this macro to 1 to enable functions: vmaBuildStatsString, vmaFreeStatsString.
+#if VMA_STATS_STRING_ENABLED
+ static inline void VmaUint32ToStr(char* outStr, size_t strLen, uint32_t num)
+ {
+ snprintf(outStr, strLen, "%u", static_cast<unsigned int>(num));
+ }
+ static inline void VmaUint64ToStr(char* outStr, size_t strLen, uint64_t num)
+ {
+ snprintf(outStr, strLen, "%llu", static_cast<unsigned long long>(num));
+ }
+ static inline void VmaPtrToStr(char* outStr, size_t strLen, const void* ptr)
+ {
+ snprintf(outStr, strLen, "%p", ptr);
+ }
+#endif
+
+#ifndef VMA_MUTEX
+ class VmaMutex
+ {
+ public:
+ void Lock() { m_Mutex.lock(); }
+ void Unlock() { m_Mutex.unlock(); }
+ private:
+ std::mutex m_Mutex;
+ };
+ #define VMA_MUTEX VmaMutex
+#endif
+
+// Read-write mutex, where "read" is shared access, "write" is exclusive access.
+#ifndef VMA_RW_MUTEX
+ #if VMA_USE_STL_SHARED_MUTEX
+ // Use std::shared_mutex from C++17.
+ #include <shared_mutex>
+ class VmaRWMutex
+ {
+ public:
+ void LockRead() { m_Mutex.lock_shared(); }
+ void UnlockRead() { m_Mutex.unlock_shared(); }
+ void LockWrite() { m_Mutex.lock(); }
+ void UnlockWrite() { m_Mutex.unlock(); }
+ private:
+ std::shared_mutex m_Mutex;
+ };
+ #define VMA_RW_MUTEX VmaRWMutex
+ #elif defined(_WIN32) && !defined(__MINGW32__)
+ // Use SRWLOCK from WinAPI.
+ class VmaRWMutex
+ {
+ public:
+ VmaRWMutex() { InitializeSRWLock(&m_Lock); }
+ void LockRead() { AcquireSRWLockShared(&m_Lock); }
+ void UnlockRead() { ReleaseSRWLockShared(&m_Lock); }
+ void LockWrite() { AcquireSRWLockExclusive(&m_Lock); }
+ void UnlockWrite() { ReleaseSRWLockExclusive(&m_Lock); }
+ private:
+ SRWLOCK m_Lock;
+ };
+ #define VMA_RW_MUTEX VmaRWMutex
+ #else
+ // Less efficient fallback: Use normal mutex.
+ class VmaRWMutex
+ {
+ public:
+ void LockRead() { m_Mutex.Lock(); }
+ void UnlockRead() { m_Mutex.Unlock(); }
+ void LockWrite() { m_Mutex.Lock(); }
+ void UnlockWrite() { m_Mutex.Unlock(); }
+ private:
+ VMA_MUTEX m_Mutex;
+ };
+ #define VMA_RW_MUTEX VmaRWMutex
+ #endif // #if VMA_USE_STL_SHARED_MUTEX
+#endif // #ifndef VMA_RW_MUTEX
+
+/*
+If providing your own implementation, you need to implement a subset of std::atomic:
+
+- Constructor(uint32_t desired)
+- uint32_t load() const
+- void store(uint32_t desired)
+- bool compare_exchange_weak(uint32_t& expected, uint32_t desired)
+*/
+#ifndef VMA_ATOMIC_UINT32
+ #define VMA_ATOMIC_UINT32 std::atomic<uint32_t>
+#endif
+
+#ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY
+ /**
+ Every allocation will have its own memory block.
+ Define to 1 for debugging purposes only.
+ */
+ #define VMA_DEBUG_ALWAYS_DEDICATED_MEMORY (0)
+#endif
+
+#ifndef VMA_DEBUG_ALIGNMENT
+ /**
+ Minimum alignment of all allocations, in bytes.
+ Set to more than 1 for debugging purposes only. Must be power of two.
+ */
+ #define VMA_DEBUG_ALIGNMENT (1)
+#endif
+
+#ifndef VMA_DEBUG_MARGIN
+ /**
+ Minimum margin before and after every allocation, in bytes.
+ Set nonzero for debugging purposes only.
+ */
+ #define VMA_DEBUG_MARGIN (0)
+#endif
+
+#ifndef VMA_DEBUG_INITIALIZE_ALLOCATIONS
+ /**
+ Define this macro to 1 to automatically fill new allocations and destroyed
+ allocations with some bit pattern.
+ */
+ #define VMA_DEBUG_INITIALIZE_ALLOCATIONS (0)
+#endif
+
+#ifndef VMA_DEBUG_DETECT_CORRUPTION
+ /**
+ Define this macro to 1 together with non-zero value of VMA_DEBUG_MARGIN to
+ enable writing magic value to the margin before and after every allocation and
+ validating it, so that memory corruptions (out-of-bounds writes) are detected.
+ */
+ #define VMA_DEBUG_DETECT_CORRUPTION (0)
+#endif
+
+#ifndef VMA_DEBUG_GLOBAL_MUTEX
+ /**
+ Set this to 1 for debugging purposes only, to enable single mutex protecting all
+ entry calls to the library. Can be useful for debugging multithreading issues.
+ */
+ #define VMA_DEBUG_GLOBAL_MUTEX (0)
+#endif
+
+#ifndef VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY
+ /**
+ Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity.
+ Set to more than 1 for debugging purposes only. Must be power of two.
+ */
+ #define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1)
+#endif
+
+#ifndef VMA_SMALL_HEAP_MAX_SIZE
+ /// Maximum size of a memory heap in Vulkan to consider it "small".
+ #define VMA_SMALL_HEAP_MAX_SIZE (1024ull * 1024 * 1024)
+#endif
+
+#ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE
+ /// Default size of a block allocated as single VkDeviceMemory from a "large" heap.
+ #define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ull * 1024 * 1024)
+#endif
+
+#ifndef VMA_CLASS_NO_COPY
+ #define VMA_CLASS_NO_COPY(className) \
+ private: \
+ className(const className&) = delete; \
+ className& operator=(const className&) = delete;
+#endif
+
+static const uint32_t VMA_FRAME_INDEX_LOST = UINT32_MAX;
+
+// Decimal 2139416166, float NaN, little-endian binary 66 E6 84 7F.
+static const uint32_t VMA_CORRUPTION_DETECTION_MAGIC_VALUE = 0x7F84E666;
+
+static const uint8_t VMA_ALLOCATION_FILL_PATTERN_CREATED = 0xDC;
+static const uint8_t VMA_ALLOCATION_FILL_PATTERN_DESTROYED = 0xEF;
+
+/*******************************************************************************
+END OF CONFIGURATION
+*/
+
+static const uint32_t VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET = 0x10000000u;
+
+static VkAllocationCallbacks VmaEmptyAllocationCallbacks = {
+ VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL };
+
+// Returns number of bits set to 1 in (v).
+static inline uint32_t VmaCountBitsSet(uint32_t v)
+{
+ uint32_t c = v - ((v >> 1) & 0x55555555);
+ c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
+ c = ((c >> 4) + c) & 0x0F0F0F0F;
+ c = ((c >> 8) + c) & 0x00FF00FF;
+ c = ((c >> 16) + c) & 0x0000FFFF;
+ return c;
+}
+
+// Aligns given value up to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 16.
+// Use types like uint32_t, uint64_t as T.
+template <typename T>
+static inline T VmaAlignUp(T val, T align)
+{
+ return (val + align - 1) / align * align;
+}
+// Aligns given value down to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 8.
+// Use types like uint32_t, uint64_t as T.
+template <typename T>
+static inline T VmaAlignDown(T val, T align)
+{
+ return val / align * align;
+}
+
+// Division with mathematical rounding to nearest number.
+template <typename T>
+static inline T VmaRoundDiv(T x, T y)
+{
+ return (x + (y / (T)2)) / y;
+}
+
+/*
+Returns true if given number is a power of two.
+T must be unsigned integer number or signed integer but always nonnegative.
+For 0 returns true.
+*/
+template <typename T>
+inline bool VmaIsPow2(T x)
+{
+ return (x & (x-1)) == 0;
+}
+
+// Returns smallest power of 2 greater or equal to v.
+static inline uint32_t VmaNextPow2(uint32_t v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+ return v;
+}
+static inline uint64_t VmaNextPow2(uint64_t v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v |= v >> 32;
+ v++;
+ return v;
+}
+
+// Returns largest power of 2 less or equal to v.
+static inline uint32_t VmaPrevPow2(uint32_t v)
+{
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v = v ^ (v >> 1);
+ return v;
+}
+static inline uint64_t VmaPrevPow2(uint64_t v)
+{
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v |= v >> 32;
+ v = v ^ (v >> 1);
+ return v;
+}
+
+static inline bool VmaStrIsEmpty(const char* pStr)
+{
+ return pStr == VMA_NULL || *pStr == '\0';
+}
+
+static const char* VmaAlgorithmToStr(uint32_t algorithm)
+{
+ switch(algorithm)
+ {
+ case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
+ return "Linear";
+ case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT:
+ return "Buddy";
+ case 0:
+ return "Default";
+ default:
+ VMA_ASSERT(0);
+ return "";
+ }
+}
+
+#ifndef VMA_SORT
+
+template<typename Iterator, typename Compare>
+Iterator VmaQuickSortPartition(Iterator beg, Iterator end, Compare cmp)
+{
+ Iterator centerValue = end; --centerValue;
+ Iterator insertIndex = beg;
+ for(Iterator memTypeIndex = beg; memTypeIndex < centerValue; ++memTypeIndex)
+ {
+ if(cmp(*memTypeIndex, *centerValue))
+ {
+ if(insertIndex != memTypeIndex)
+ {
+ VMA_SWAP(*memTypeIndex, *insertIndex);
+ }
+ ++insertIndex;
+ }
+ }
+ if(insertIndex != centerValue)
+ {
+ VMA_SWAP(*insertIndex, *centerValue);
+ }
+ return insertIndex;
+}
+
+template<typename Iterator, typename Compare>
+void VmaQuickSort(Iterator beg, Iterator end, Compare cmp)
+{
+ if(beg < end)
+ {
+ Iterator it = VmaQuickSortPartition<Iterator, Compare>(beg, end, cmp);
+ VmaQuickSort<Iterator, Compare>(beg, it, cmp);
+ VmaQuickSort<Iterator, Compare>(it + 1, end, cmp);
+ }
+}
+
+#define VMA_SORT(beg, end, cmp) VmaQuickSort(beg, end, cmp)
+
+#endif // #ifndef VMA_SORT
+
+/*
+Returns true if two memory blocks occupy overlapping pages.
+ResourceA must be in less memory offset than ResourceB.
+
+Algorithm is based on "Vulkan 1.0.39 - A Specification (with all registered Vulkan extensions)"
+chapter 11.6 "Resource Memory Association", paragraph "Buffer-Image Granularity".
+*/
+static inline bool VmaBlocksOnSamePage(
+ VkDeviceSize resourceAOffset,
+ VkDeviceSize resourceASize,
+ VkDeviceSize resourceBOffset,
+ VkDeviceSize pageSize)
+{
+ VMA_ASSERT(resourceAOffset + resourceASize <= resourceBOffset && resourceASize > 0 && pageSize > 0);
+ VkDeviceSize resourceAEnd = resourceAOffset + resourceASize - 1;
+ VkDeviceSize resourceAEndPage = resourceAEnd & ~(pageSize - 1);
+ VkDeviceSize resourceBStart = resourceBOffset;
+ VkDeviceSize resourceBStartPage = resourceBStart & ~(pageSize - 1);
+ return resourceAEndPage == resourceBStartPage;
+}
+
+enum VmaSuballocationType
+{
+ VMA_SUBALLOCATION_TYPE_FREE = 0,
+ VMA_SUBALLOCATION_TYPE_UNKNOWN = 1,
+ VMA_SUBALLOCATION_TYPE_BUFFER = 2,
+ VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3,
+ VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4,
+ VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5,
+ VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF
+};
+
+/*
+Returns true if given suballocation types could conflict and must respect
+VkPhysicalDeviceLimits::bufferImageGranularity. They conflict if one is buffer
+or linear image and another one is optimal image. If type is unknown, behave
+conservatively.
+*/
+static inline bool VmaIsBufferImageGranularityConflict(
+ VmaSuballocationType suballocType1,
+ VmaSuballocationType suballocType2)
+{
+ if(suballocType1 > suballocType2)
+ {
+ VMA_SWAP(suballocType1, suballocType2);
+ }
+
+ switch(suballocType1)
+ {
+ case VMA_SUBALLOCATION_TYPE_FREE:
+ return false;
+ case VMA_SUBALLOCATION_TYPE_UNKNOWN:
+ return true;
+ case VMA_SUBALLOCATION_TYPE_BUFFER:
+ return
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;
+ case VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN:
+ return
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR ||
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;
+ case VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR:
+ return
+ suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;
+ case VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL:
+ return false;
+ default:
+ VMA_ASSERT(0);
+ return true;
+ }
+}
+
+static void VmaWriteMagicValue(void* pData, VkDeviceSize offset)
+{
+ uint32_t* pDst = (uint32_t*)((char*)pData + offset);
+ const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);
+ for(size_t i = 0; i != numberCount; ++i, ++pDst)
+ {
+ *pDst = VMA_CORRUPTION_DETECTION_MAGIC_VALUE;
+ }
+}
+
+static bool VmaValidateMagicValue(const void* pData, VkDeviceSize offset)
+{
+ const uint32_t* pSrc = (const uint32_t*)((const char*)pData + offset);
+ const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);
+ for(size_t i = 0; i != numberCount; ++i, ++pSrc)
+ {
+ if(*pSrc != VMA_CORRUPTION_DETECTION_MAGIC_VALUE)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope).
+struct VmaMutexLock
+{
+ VMA_CLASS_NO_COPY(VmaMutexLock)
+public:
+ VmaMutexLock(VMA_MUTEX& mutex, bool useMutex) :
+ m_pMutex(useMutex ? &mutex : VMA_NULL)
+ { if(m_pMutex) { m_pMutex->Lock(); } }
+ ~VmaMutexLock()
+ { if(m_pMutex) { m_pMutex->Unlock(); } }
+private:
+ VMA_MUTEX* m_pMutex;
+};
+
+// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading.
+struct VmaMutexLockRead
+{
+ VMA_CLASS_NO_COPY(VmaMutexLockRead)
+public:
+ VmaMutexLockRead(VMA_RW_MUTEX& mutex, bool useMutex) :
+ m_pMutex(useMutex ? &mutex : VMA_NULL)
+ { if(m_pMutex) { m_pMutex->LockRead(); } }
+ ~VmaMutexLockRead() { if(m_pMutex) { m_pMutex->UnlockRead(); } }
+private:
+ VMA_RW_MUTEX* m_pMutex;
+};
+
+// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing.
+struct VmaMutexLockWrite
+{
+ VMA_CLASS_NO_COPY(VmaMutexLockWrite)
+public:
+ VmaMutexLockWrite(VMA_RW_MUTEX& mutex, bool useMutex) :
+ m_pMutex(useMutex ? &mutex : VMA_NULL)
+ { if(m_pMutex) { m_pMutex->LockWrite(); } }
+ ~VmaMutexLockWrite() { if(m_pMutex) { m_pMutex->UnlockWrite(); } }
+private:
+ VMA_RW_MUTEX* m_pMutex;
+};
+
+#if VMA_DEBUG_GLOBAL_MUTEX
+ static VMA_MUTEX gDebugGlobalMutex;
+ #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true);
+#else
+ #define VMA_DEBUG_GLOBAL_MUTEX_LOCK
+#endif
+
+// Minimum size of a free suballocation to register it in the free suballocation collection.
+static const VkDeviceSize VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER = 16;
+
+/*
+Performs binary search and returns iterator to first element that is greater or
+equal to (key), according to comparison (cmp).
+
+Cmp should return true if first argument is less than second argument.
+
+Returned value is the found element, if present in the collection or place where
+new element with value (key) should be inserted.
+*/
+template <typename CmpLess, typename IterT, typename KeyT>
+static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT &key, CmpLess cmp)
+{
+ size_t down = 0, up = (end - beg);
+ while(down < up)
+ {
+ const size_t mid = (down + up) / 2;
+ if(cmp(*(beg+mid), key))
+ {
+ down = mid + 1;
+ }
+ else
+ {
+ up = mid;
+ }
+ }
+ return beg + down;
+}
+
+/*
+Returns true if all pointers in the array are not-null and unique.
+Warning! O(n^2) complexity. Use only inside VMA_HEAVY_ASSERT.
+T must be pointer type, e.g. VmaAllocation, VmaPool.
+*/
+template<typename T>
+static bool VmaValidatePointerArray(uint32_t count, const T* arr)
+{
+ for(uint32_t i = 0; i < count; ++i)
+ {
+ const T iPtr = arr[i];
+ if(iPtr == VMA_NULL)
+ {
+ return false;
+ }
+ for(uint32_t j = i + 1; j < count; ++j)
+ {
+ if(iPtr == arr[j])
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Memory allocation
+
+static void* VmaMalloc(const VkAllocationCallbacks* pAllocationCallbacks, size_t size, size_t alignment)
+{
+ if((pAllocationCallbacks != VMA_NULL) &&
+ (pAllocationCallbacks->pfnAllocation != VMA_NULL))
+ {
+ return (*pAllocationCallbacks->pfnAllocation)(
+ pAllocationCallbacks->pUserData,
+ size,
+ alignment,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ }
+ else
+ {
+ return VMA_SYSTEM_ALIGNED_MALLOC(size, alignment);
+ }
+}
+
+static void VmaFree(const VkAllocationCallbacks* pAllocationCallbacks, void* ptr)
+{
+ if((pAllocationCallbacks != VMA_NULL) &&
+ (pAllocationCallbacks->pfnFree != VMA_NULL))
+ {
+ (*pAllocationCallbacks->pfnFree)(pAllocationCallbacks->pUserData, ptr);
+ }
+ else
+ {
+ VMA_SYSTEM_FREE(ptr);
+ }
+}
+
+template<typename T>
+static T* VmaAllocate(const VkAllocationCallbacks* pAllocationCallbacks)
+{
+ return (T*)VmaMalloc(pAllocationCallbacks, sizeof(T), VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static T* VmaAllocateArray(const VkAllocationCallbacks* pAllocationCallbacks, size_t count)
+{
+ return (T*)VmaMalloc(pAllocationCallbacks, sizeof(T) * count, VMA_ALIGN_OF(T));
+}
+
+#define vma_new(allocator, type) new(VmaAllocate<type>(allocator))(type)
+
+#define vma_new_array(allocator, type, count) new(VmaAllocateArray<type>((allocator), (count)))(type)
+
+template<typename T>
+static void vma_delete(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr)
+{
+ ptr->~T();
+ VmaFree(pAllocationCallbacks, ptr);
+}
+
+template<typename T>
+static void vma_delete_array(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr, size_t count)
+{
+ if(ptr != VMA_NULL)
+ {
+ for(size_t i = count; i--; )
+ {
+ ptr[i].~T();
+ }
+ VmaFree(pAllocationCallbacks, ptr);
+ }
+}
+
+// STL-compatible allocator.
+template<typename T>
+class VmaStlAllocator
+{
+public:
+ const VkAllocationCallbacks* const m_pCallbacks;
+ typedef T value_type;
+
+ VmaStlAllocator(const VkAllocationCallbacks* pCallbacks) : m_pCallbacks(pCallbacks) { }
+ template<typename U> VmaStlAllocator(const VmaStlAllocator<U>& src) : m_pCallbacks(src.m_pCallbacks) { }
+
+ T* allocate(size_t n) { return VmaAllocateArray<T>(m_pCallbacks, n); }
+ void deallocate(T* p, size_t /*n*/) { VmaFree(m_pCallbacks, p); }
+
+ template<typename U>
+ bool operator==(const VmaStlAllocator<U>& rhs) const
+ {
+ return m_pCallbacks == rhs.m_pCallbacks;
+ }
+ template<typename U>
+ bool operator!=(const VmaStlAllocator<U>& rhs) const
+ {
+ return m_pCallbacks != rhs.m_pCallbacks;
+ }
+
+ VmaStlAllocator& operator=(const VmaStlAllocator& x) = delete;
+};
+
+#if VMA_USE_STL_VECTOR
+
+#define VmaVector std::vector
+
+template<typename T, typename allocatorT>
+static void VmaVectorInsert(std::vector<T, allocatorT>& vec, size_t index, const T& item)
+{
+ vec.insert(vec.begin() + index, item);
+}
+
+template<typename T, typename allocatorT>
+static void VmaVectorRemove(std::vector<T, allocatorT>& vec, size_t index)
+{
+ vec.erase(vec.begin() + index);
+}
+
+#else // #if VMA_USE_STL_VECTOR
+
+/* Class with interface compatible with subset of std::vector.
+T must be POD because constructors and destructors are not called and memcpy is
+used for these objects. */
+template<typename T, typename AllocatorT>
+class VmaVector
+{
+public:
+ typedef T value_type;
+
+ VmaVector(const AllocatorT& allocator) :
+ m_Allocator(allocator),
+ m_pArray(VMA_NULL),
+ m_Count(0),
+ m_Capacity(0)
+ {
+ }
+
+ VmaVector(size_t count, const AllocatorT& allocator) :
+ m_Allocator(allocator),
+ m_pArray(count ? (T*)VmaAllocateArray<T>(allocator.m_pCallbacks, count) : VMA_NULL),
+ m_Count(count),
+ m_Capacity(count)
+ {
+ }
+
+ VmaVector(const VmaVector<T, AllocatorT>& src) :
+ m_Allocator(src.m_Allocator),
+ m_pArray(src.m_Count ? (T*)VmaAllocateArray<T>(src.m_Allocator.m_pCallbacks, src.m_Count) : VMA_NULL),
+ m_Count(src.m_Count),
+ m_Capacity(src.m_Count)
+ {
+ if(m_Count != 0)
+ {
+ memcpy(m_pArray, src.m_pArray, m_Count * sizeof(T));
+ }
+ }
+
+ ~VmaVector()
+ {
+ VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+ }
+
+ VmaVector& operator=(const VmaVector<T, AllocatorT>& rhs)
+ {
+ if(&rhs != this)
+ {
+ resize(rhs.m_Count);
+ if(m_Count != 0)
+ {
+ memcpy(m_pArray, rhs.m_pArray, m_Count * sizeof(T));
+ }
+ }
+ return *this;
+ }
+
+ bool empty() const { return m_Count == 0; }
+ size_t size() const { return m_Count; }
+ T* data() { return m_pArray; }
+ const T* data() const { return m_pArray; }
+
+ T& operator[](size_t index)
+ {
+ VMA_HEAVY_ASSERT(index < m_Count);
+ return m_pArray[index];
+ }
+ const T& operator[](size_t index) const
+ {
+ VMA_HEAVY_ASSERT(index < m_Count);
+ return m_pArray[index];
+ }
+
+ T& front()
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ return m_pArray[0];
+ }
+ const T& front() const
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ return m_pArray[0];
+ }
+ T& back()
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ return m_pArray[m_Count - 1];
+ }
+ const T& back() const
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ return m_pArray[m_Count - 1];
+ }
+
+ void reserve(size_t newCapacity, bool freeMemory = false)
+ {
+ newCapacity = VMA_MAX(newCapacity, m_Count);
+
+ if((newCapacity < m_Capacity) && !freeMemory)
+ {
+ newCapacity = m_Capacity;
+ }
+
+ if(newCapacity != m_Capacity)
+ {
+ T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator, newCapacity) : VMA_NULL;
+ if(m_Count != 0)
+ {
+ memcpy(newArray, m_pArray, m_Count * sizeof(T));
+ }
+ VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+ m_Capacity = newCapacity;
+ m_pArray = newArray;
+ }
+ }
+
+ void resize(size_t newCount, bool freeMemory = false)
+ {
+ size_t newCapacity = m_Capacity;
+ if(newCount > m_Capacity)
+ {
+ newCapacity = VMA_MAX(newCount, VMA_MAX(m_Capacity * 3 / 2, (size_t)8));
+ }
+ else if(freeMemory)
+ {
+ newCapacity = newCount;
+ }
+
+ if(newCapacity != m_Capacity)
+ {
+ T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator.m_pCallbacks, newCapacity) : VMA_NULL;
+ const size_t elementsToCopy = VMA_MIN(m_Count, newCount);
+ if(elementsToCopy != 0)
+ {
+ memcpy(newArray, m_pArray, elementsToCopy * sizeof(T));
+ }
+ VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+ m_Capacity = newCapacity;
+ m_pArray = newArray;
+ }
+
+ m_Count = newCount;
+ }
+
+ void clear(bool freeMemory = false)
+ {
+ resize(0, freeMemory);
+ }
+
+ void insert(size_t index, const T& src)
+ {
+ VMA_HEAVY_ASSERT(index <= m_Count);
+ const size_t oldCount = size();
+ resize(oldCount + 1);
+ if(index < oldCount)
+ {
+ memmove(m_pArray + (index + 1), m_pArray + index, (oldCount - index) * sizeof(T));
+ }
+ m_pArray[index] = src;
+ }
+
+ void remove(size_t index)
+ {
+ VMA_HEAVY_ASSERT(index < m_Count);
+ const size_t oldCount = size();
+ if(index < oldCount - 1)
+ {
+ memmove(m_pArray + index, m_pArray + (index + 1), (oldCount - index - 1) * sizeof(T));
+ }
+ resize(oldCount - 1);
+ }
+
+ void push_back(const T& src)
+ {
+ const size_t newIndex = size();
+ resize(newIndex + 1);
+ m_pArray[newIndex] = src;
+ }
+
+ void pop_back()
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ resize(size() - 1);
+ }
+
+ void push_front(const T& src)
+ {
+ insert(0, src);
+ }
+
+ void pop_front()
+ {
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ remove(0);
+ }
+
+ typedef T* iterator;
+
+ iterator begin() { return m_pArray; }
+ iterator end() { return m_pArray + m_Count; }
+
+private:
+ AllocatorT m_Allocator;
+ T* m_pArray;
+ size_t m_Count;
+ size_t m_Capacity;
+};
+
+template<typename T, typename allocatorT>
+static void VmaVectorInsert(VmaVector<T, allocatorT>& vec, size_t index, const T& item)
+{
+ vec.insert(index, item);
+}
+
+template<typename T, typename allocatorT>
+static void VmaVectorRemove(VmaVector<T, allocatorT>& vec, size_t index)
+{
+ vec.remove(index);
+}
+
+#endif // #if VMA_USE_STL_VECTOR
+
+template<typename CmpLess, typename VectorT>
+size_t VmaVectorInsertSorted(VectorT& vector, const typename VectorT::value_type& value)
+{
+ const size_t indexToInsert = VmaBinaryFindFirstNotLess(
+ vector.data(),
+ vector.data() + vector.size(),
+ value,
+ CmpLess()) - vector.data();
+ VmaVectorInsert(vector, indexToInsert, value);
+ return indexToInsert;
+}
+
+template<typename CmpLess, typename VectorT>
+bool VmaVectorRemoveSorted(VectorT& vector, const typename VectorT::value_type& value)
+{
+ CmpLess comparator;
+ typename VectorT::iterator it = VmaBinaryFindFirstNotLess(
+ vector.begin(),
+ vector.end(),
+ value,
+ comparator);
+ if((it != vector.end()) && !comparator(*it, value) && !comparator(value, *it))
+ {
+ size_t indexToRemove = it - vector.begin();
+ VmaVectorRemove(vector, indexToRemove);
+ return true;
+ }
+ return false;
+}
+
+template<typename CmpLess, typename IterT, typename KeyT>
+IterT VmaVectorFindSorted(const IterT& beg, const IterT& end, const KeyT& value)
+{
+ CmpLess comparator;
+ IterT it = VmaBinaryFindFirstNotLess<CmpLess, IterT, KeyT>(
+ beg, end, value, comparator);
+ if(it == end ||
+ (!comparator(*it, value) && !comparator(value, *it)))
+ {
+ return it;
+ }
+ return end;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaPoolAllocator
+
+/*
+Allocator for objects of type T using a list of arrays (pools) to speed up
+allocation. Number of elements that can be allocated is not bounded because
+allocator can create multiple blocks.
+*/
+template<typename T>
+class VmaPoolAllocator
+{
+ VMA_CLASS_NO_COPY(VmaPoolAllocator)
+public:
+ VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, size_t itemsPerBlock);
+ ~VmaPoolAllocator();
+ void Clear();
+ T* Alloc();
+ void Free(T* ptr);
+
+private:
+ union Item
+ {
+ uint32_t NextFreeIndex;
+ T Value;
+ };
+
+ struct ItemBlock
+ {
+ Item* pItems;
+ uint32_t FirstFreeIndex;
+ };
+
+ const VkAllocationCallbacks* m_pAllocationCallbacks;
+ size_t m_ItemsPerBlock;
+ VmaVector< ItemBlock, VmaStlAllocator<ItemBlock> > m_ItemBlocks;
+
+ ItemBlock& CreateNewBlock();
+};
+
+template<typename T>
+VmaPoolAllocator<T>::VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, size_t itemsPerBlock) :
+ m_pAllocationCallbacks(pAllocationCallbacks),
+ m_ItemsPerBlock(itemsPerBlock),
+ m_ItemBlocks(VmaStlAllocator<ItemBlock>(pAllocationCallbacks))
+{
+ VMA_ASSERT(itemsPerBlock > 0);
+}
+
+template<typename T>
+VmaPoolAllocator<T>::~VmaPoolAllocator()
+{
+ Clear();
+}
+
+template<typename T>
+void VmaPoolAllocator<T>::Clear()
+{
+ for(size_t i = m_ItemBlocks.size(); i--; )
+ vma_delete_array(m_pAllocationCallbacks, m_ItemBlocks[i].pItems, m_ItemsPerBlock);
+ m_ItemBlocks.clear();
+}
+
+template<typename T>
+T* VmaPoolAllocator<T>::Alloc()
+{
+ for(size_t i = m_ItemBlocks.size(); i--; )
+ {
+ ItemBlock& block = m_ItemBlocks[i];
+ // This block has some free items: Use first one.
+ if(block.FirstFreeIndex != UINT32_MAX)
+ {
+ Item* const pItem = &block.pItems[block.FirstFreeIndex];
+ block.FirstFreeIndex = pItem->NextFreeIndex;
+ return &pItem->Value;
+ }
+ }
+
+ // No block has free item: Create new one and use it.
+ ItemBlock& newBlock = CreateNewBlock();
+ Item* const pItem = &newBlock.pItems[0];
+ newBlock.FirstFreeIndex = pItem->NextFreeIndex;
+ return &pItem->Value;
+}
+
+template<typename T>
+void VmaPoolAllocator<T>::Free(T* ptr)
+{
+ // Search all memory blocks to find ptr.
+ for(size_t i = 0; i < m_ItemBlocks.size(); ++i)
+ {
+ ItemBlock& block = m_ItemBlocks[i];
+
+ // Casting to union.
+ Item* pItemPtr;
+ memcpy(&pItemPtr, &ptr, sizeof(pItemPtr));
+
+ // Check if pItemPtr is in address range of this block.
+ if((pItemPtr >= block.pItems) && (pItemPtr < block.pItems + m_ItemsPerBlock))
+ {
+ const uint32_t index = static_cast<uint32_t>(pItemPtr - block.pItems);
+ pItemPtr->NextFreeIndex = block.FirstFreeIndex;
+ block.FirstFreeIndex = index;
+ return;
+ }
+ }
+ VMA_ASSERT(0 && "Pointer doesn't belong to this memory pool.");
+}
+
+template<typename T>
+typename VmaPoolAllocator<T>::ItemBlock& VmaPoolAllocator<T>::CreateNewBlock()
+{
+ ItemBlock newBlock = {
+ vma_new_array(m_pAllocationCallbacks, Item, m_ItemsPerBlock), 0 };
+
+ m_ItemBlocks.push_back(newBlock);
+
+ // Setup singly-linked list of all free items in this block.
+ for(uint32_t i = 0; i < m_ItemsPerBlock - 1; ++i)
+ newBlock.pItems[i].NextFreeIndex = i + 1;
+ newBlock.pItems[m_ItemsPerBlock - 1].NextFreeIndex = UINT32_MAX;
+ return m_ItemBlocks.back();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaRawList, VmaList
+
+#if VMA_USE_STL_LIST
+
+#define VmaList std::list
+
+#else // #if VMA_USE_STL_LIST
+
+template<typename T>
+struct VmaListItem
+{
+ VmaListItem* pPrev;
+ VmaListItem* pNext;
+ T Value;
+};
+
+// Doubly linked list.
+template<typename T>
+class VmaRawList
+{
+ VMA_CLASS_NO_COPY(VmaRawList)
+public:
+ typedef VmaListItem<T> ItemType;
+
+ VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks);
+ ~VmaRawList();
+ void Clear();
+
+ size_t GetCount() const { return m_Count; }
+ bool IsEmpty() const { return m_Count == 0; }
+
+ ItemType* Front() { return m_pFront; }
+ const ItemType* Front() const { return m_pFront; }
+ ItemType* Back() { return m_pBack; }
+ const ItemType* Back() const { return m_pBack; }
+
+ ItemType* PushBack();
+ ItemType* PushFront();
+ ItemType* PushBack(const T& value);
+ ItemType* PushFront(const T& value);
+ void PopBack();
+ void PopFront();
+
+ // Item can be null - it means PushBack.
+ ItemType* InsertBefore(ItemType* pItem);
+ // Item can be null - it means PushFront.
+ ItemType* InsertAfter(ItemType* pItem);
+
+ ItemType* InsertBefore(ItemType* pItem, const T& value);
+ ItemType* InsertAfter(ItemType* pItem, const T& value);
+
+ void Remove(ItemType* pItem);
+
+private:
+ const VkAllocationCallbacks* const m_pAllocationCallbacks;
+ VmaPoolAllocator<ItemType> m_ItemAllocator;
+ ItemType* m_pFront;
+ ItemType* m_pBack;
+ size_t m_Count;
+};
+
+template<typename T>
+VmaRawList<T>::VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks) :
+ m_pAllocationCallbacks(pAllocationCallbacks),
+ m_ItemAllocator(pAllocationCallbacks, 128),
+ m_pFront(VMA_NULL),
+ m_pBack(VMA_NULL),
+ m_Count(0)
+{
+}
+
+template<typename T>
+VmaRawList<T>::~VmaRawList()
+{
+ // Intentionally not calling Clear, because that would be unnecessary
+ // computations to return all items to m_ItemAllocator as free.
+}
+
+template<typename T>
+void VmaRawList<T>::Clear()
+{
+ if(IsEmpty() == false)
+ {
+ ItemType* pItem = m_pBack;
+ while(pItem != VMA_NULL)
+ {
+ ItemType* const pPrevItem = pItem->pPrev;
+ m_ItemAllocator.Free(pItem);
+ pItem = pPrevItem;
+ }
+ m_pFront = VMA_NULL;
+ m_pBack = VMA_NULL;
+ m_Count = 0;
+ }
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushBack()
+{
+ ItemType* const pNewItem = m_ItemAllocator.Alloc();
+ pNewItem->pNext = VMA_NULL;
+ if(IsEmpty())
+ {
+ pNewItem->pPrev = VMA_NULL;
+ m_pFront = pNewItem;
+ m_pBack = pNewItem;
+ m_Count = 1;
+ }
+ else
+ {
+ pNewItem->pPrev = m_pBack;
+ m_pBack->pNext = pNewItem;
+ m_pBack = pNewItem;
+ ++m_Count;
+ }
+ return pNewItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushFront()
+{
+ ItemType* const pNewItem = m_ItemAllocator.Alloc();
+ pNewItem->pPrev = VMA_NULL;
+ if(IsEmpty())
+ {
+ pNewItem->pNext = VMA_NULL;
+ m_pFront = pNewItem;
+ m_pBack = pNewItem;
+ m_Count = 1;
+ }
+ else
+ {
+ pNewItem->pNext = m_pFront;
+ m_pFront->pPrev = pNewItem;
+ m_pFront = pNewItem;
+ ++m_Count;
+ }
+ return pNewItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushBack(const T& value)
+{
+ ItemType* const pNewItem = PushBack();
+ pNewItem->Value = value;
+ return pNewItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushFront(const T& value)
+{
+ ItemType* const pNewItem = PushFront();
+ pNewItem->Value = value;
+ return pNewItem;
+}
+
+template<typename T>
+void VmaRawList<T>::PopBack()
+{
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ ItemType* const pBackItem = m_pBack;
+ ItemType* const pPrevItem = pBackItem->pPrev;
+ if(pPrevItem != VMA_NULL)
+ {
+ pPrevItem->pNext = VMA_NULL;
+ }
+ m_pBack = pPrevItem;
+ m_ItemAllocator.Free(pBackItem);
+ --m_Count;
+}
+
+template<typename T>
+void VmaRawList<T>::PopFront()
+{
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ ItemType* const pFrontItem = m_pFront;
+ ItemType* const pNextItem = pFrontItem->pNext;
+ if(pNextItem != VMA_NULL)
+ {
+ pNextItem->pPrev = VMA_NULL;
+ }
+ m_pFront = pNextItem;
+ m_ItemAllocator.Free(pFrontItem);
+ --m_Count;
+}
+
+template<typename T>
+void VmaRawList<T>::Remove(ItemType* pItem)
+{
+ VMA_HEAVY_ASSERT(pItem != VMA_NULL);
+ VMA_HEAVY_ASSERT(m_Count > 0);
+
+ if(pItem->pPrev != VMA_NULL)
+ {
+ pItem->pPrev->pNext = pItem->pNext;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(m_pFront == pItem);
+ m_pFront = pItem->pNext;
+ }
+
+ if(pItem->pNext != VMA_NULL)
+ {
+ pItem->pNext->pPrev = pItem->pPrev;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(m_pBack == pItem);
+ m_pBack = pItem->pPrev;
+ }
+
+ m_ItemAllocator.Free(pItem);
+ --m_Count;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertBefore(ItemType* pItem)
+{
+ if(pItem != VMA_NULL)
+ {
+ ItemType* const prevItem = pItem->pPrev;
+ ItemType* const newItem = m_ItemAllocator.Alloc();
+ newItem->pPrev = prevItem;
+ newItem->pNext = pItem;
+ pItem->pPrev = newItem;
+ if(prevItem != VMA_NULL)
+ {
+ prevItem->pNext = newItem;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(m_pFront == pItem);
+ m_pFront = newItem;
+ }
+ ++m_Count;
+ return newItem;
+ }
+ else
+ return PushBack();
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertAfter(ItemType* pItem)
+{
+ if(pItem != VMA_NULL)
+ {
+ ItemType* const nextItem = pItem->pNext;
+ ItemType* const newItem = m_ItemAllocator.Alloc();
+ newItem->pNext = nextItem;
+ newItem->pPrev = pItem;
+ pItem->pNext = newItem;
+ if(nextItem != VMA_NULL)
+ {
+ nextItem->pPrev = newItem;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(m_pBack == pItem);
+ m_pBack = newItem;
+ }
+ ++m_Count;
+ return newItem;
+ }
+ else
+ return PushFront();
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertBefore(ItemType* pItem, const T& value)
+{
+ ItemType* const newItem = InsertBefore(pItem);
+ newItem->Value = value;
+ return newItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertAfter(ItemType* pItem, const T& value)
+{
+ ItemType* const newItem = InsertAfter(pItem);
+ newItem->Value = value;
+ return newItem;
+}
+
+template<typename T, typename AllocatorT>
+class VmaList
+{
+ VMA_CLASS_NO_COPY(VmaList)
+public:
+ class iterator
+ {
+ public:
+ iterator() :
+ m_pList(VMA_NULL),
+ m_pItem(VMA_NULL)
+ {
+ }
+
+ T& operator*() const
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ return m_pItem->Value;
+ }
+ T* operator->() const
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ return &m_pItem->Value;
+ }
+
+ iterator& operator++()
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ m_pItem = m_pItem->pNext;
+ return *this;
+ }
+ iterator& operator--()
+ {
+ if(m_pItem != VMA_NULL)
+ {
+ m_pItem = m_pItem->pPrev;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
+ m_pItem = m_pList->Back();
+ }
+ return *this;
+ }
+
+ iterator operator++(int)
+ {
+ iterator result = *this;
+ ++*this;
+ return result;
+ }
+ iterator operator--(int)
+ {
+ iterator result = *this;
+ --*this;
+ return result;
+ }
+
+ bool operator==(const iterator& rhs) const
+ {
+ VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+ return m_pItem == rhs.m_pItem;
+ }
+ bool operator!=(const iterator& rhs) const
+ {
+ VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+ return m_pItem != rhs.m_pItem;
+ }
+
+ private:
+ VmaRawList<T>* m_pList;
+ VmaListItem<T>* m_pItem;
+
+ iterator(VmaRawList<T>* pList, VmaListItem<T>* pItem) :
+ m_pList(pList),
+ m_pItem(pItem)
+ {
+ }
+
+ friend class VmaList<T, AllocatorT>;
+ };
+
+ class const_iterator
+ {
+ public:
+ const_iterator() :
+ m_pList(VMA_NULL),
+ m_pItem(VMA_NULL)
+ {
+ }
+
+ const_iterator(const iterator& src) :
+ m_pList(src.m_pList),
+ m_pItem(src.m_pItem)
+ {
+ }
+
+ const T& operator*() const
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ return m_pItem->Value;
+ }
+ const T* operator->() const
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ return &m_pItem->Value;
+ }
+
+ const_iterator& operator++()
+ {
+ VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+ m_pItem = m_pItem->pNext;
+ return *this;
+ }
+ const_iterator& operator--()
+ {
+ if(m_pItem != VMA_NULL)
+ {
+ m_pItem = m_pItem->pPrev;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
+ m_pItem = m_pList->Back();
+ }
+ return *this;
+ }
+
+ const_iterator operator++(int)
+ {
+ const_iterator result = *this;
+ ++*this;
+ return result;
+ }
+ const_iterator operator--(int)
+ {
+ const_iterator result = *this;
+ --*this;
+ return result;
+ }
+
+ bool operator==(const const_iterator& rhs) const
+ {
+ VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+ return m_pItem == rhs.m_pItem;
+ }
+ bool operator!=(const const_iterator& rhs) const
+ {
+ VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+ return m_pItem != rhs.m_pItem;
+ }
+
+ private:
+ const_iterator(const VmaRawList<T>* pList, const VmaListItem<T>* pItem) :
+ m_pList(pList),
+ m_pItem(pItem)
+ {
+ }
+
+ const VmaRawList<T>* m_pList;
+ const VmaListItem<T>* m_pItem;
+
+ friend class VmaList<T, AllocatorT>;
+ };
+
+ VmaList(const AllocatorT& allocator) : m_RawList(allocator.m_pCallbacks) { }
+
+ bool empty() const { return m_RawList.IsEmpty(); }
+ size_t size() const { return m_RawList.GetCount(); }
+
+ iterator begin() { return iterator(&m_RawList, m_RawList.Front()); }
+ iterator end() { return iterator(&m_RawList, VMA_NULL); }
+
+ const_iterator cbegin() const { return const_iterator(&m_RawList, m_RawList.Front()); }
+ const_iterator cend() const { return const_iterator(&m_RawList, VMA_NULL); }
+
+ void clear() { m_RawList.Clear(); }
+ void push_back(const T& value) { m_RawList.PushBack(value); }
+ void erase(iterator it) { m_RawList.Remove(it.m_pItem); }
+ iterator insert(iterator it, const T& value) { return iterator(&m_RawList, m_RawList.InsertBefore(it.m_pItem, value)); }
+
+private:
+ VmaRawList<T> m_RawList;
+};
+
+#endif // #if VMA_USE_STL_LIST
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaMap
+
+// Unused in this version.
+#if 0
+
+#if VMA_USE_STL_UNORDERED_MAP
+
+#define VmaPair std::pair
+
+#define VMA_MAP_TYPE(KeyT, ValueT) \
+ std::unordered_map< KeyT, ValueT, std::hash<KeyT>, std::equal_to<KeyT>, VmaStlAllocator< std::pair<KeyT, ValueT> > >
+
+#else // #if VMA_USE_STL_UNORDERED_MAP
+
+template<typename T1, typename T2>
+struct VmaPair
+{
+ T1 first;
+ T2 second;
+
+ VmaPair() : first(), second() { }
+ VmaPair(const T1& firstSrc, const T2& secondSrc) : first(firstSrc), second(secondSrc) { }
+};
+
+/* Class compatible with subset of interface of std::unordered_map.
+KeyT, ValueT must be POD because they will be stored in VmaVector.
+*/
+template<typename KeyT, typename ValueT>
+class VmaMap
+{
+public:
+ typedef VmaPair<KeyT, ValueT> PairType;
+ typedef PairType* iterator;
+
+ VmaMap(const VmaStlAllocator<PairType>& allocator) : m_Vector(allocator) { }
+
+ iterator begin() { return m_Vector.begin(); }
+ iterator end() { return m_Vector.end(); }
+
+ void insert(const PairType& pair);
+ iterator find(const KeyT& key);
+ void erase(iterator it);
+
+private:
+ VmaVector< PairType, VmaStlAllocator<PairType> > m_Vector;
+};
+
+#define VMA_MAP_TYPE(KeyT, ValueT) VmaMap<KeyT, ValueT>
+
+template<typename FirstT, typename SecondT>
+struct VmaPairFirstLess
+{
+ bool operator()(const VmaPair<FirstT, SecondT>& lhs, const VmaPair<FirstT, SecondT>& rhs) const
+ {
+ return lhs.first < rhs.first;
+ }
+ bool operator()(const VmaPair<FirstT, SecondT>& lhs, const FirstT& rhsFirst) const
+ {
+ return lhs.first < rhsFirst;
+ }
+};
+
+template<typename KeyT, typename ValueT>
+void VmaMap<KeyT, ValueT>::insert(const PairType& pair)
+{
+ const size_t indexToInsert = VmaBinaryFindFirstNotLess(
+ m_Vector.data(),
+ m_Vector.data() + m_Vector.size(),
+ pair,
+ VmaPairFirstLess<KeyT, ValueT>()) - m_Vector.data();
+ VmaVectorInsert(m_Vector, indexToInsert, pair);
+}
+
+template<typename KeyT, typename ValueT>
+VmaPair<KeyT, ValueT>* VmaMap<KeyT, ValueT>::find(const KeyT& key)
+{
+ PairType* it = VmaBinaryFindFirstNotLess(
+ m_Vector.data(),
+ m_Vector.data() + m_Vector.size(),
+ key,
+ VmaPairFirstLess<KeyT, ValueT>());
+ if((it != m_Vector.end()) && (it->first == key))
+ {
+ return it;
+ }
+ else
+ {
+ return m_Vector.end();
+ }
+}
+
+template<typename KeyT, typename ValueT>
+void VmaMap<KeyT, ValueT>::erase(iterator it)
+{
+ VmaVectorRemove(m_Vector, it - m_Vector.begin());
+}
+
+#endif // #if VMA_USE_STL_UNORDERED_MAP
+
+#endif // #if 0
+
+////////////////////////////////////////////////////////////////////////////////
+
+class VmaDeviceMemoryBlock;
+
+enum VMA_CACHE_OPERATION { VMA_CACHE_FLUSH, VMA_CACHE_INVALIDATE };
+
+struct VmaAllocation_T
+{
+ VMA_CLASS_NO_COPY(VmaAllocation_T)
+private:
+ static const uint8_t MAP_COUNT_FLAG_PERSISTENT_MAP = 0x80;
+
+ enum FLAGS
+ {
+ FLAG_USER_DATA_STRING = 0x01,
+ };
+
+public:
+ enum ALLOCATION_TYPE
+ {
+ ALLOCATION_TYPE_NONE,
+ ALLOCATION_TYPE_BLOCK,
+ ALLOCATION_TYPE_DEDICATED,
+ };
+
+ VmaAllocation_T(uint32_t currentFrameIndex, bool userDataString) :
+ m_Alignment(1),
+ m_Size(0),
+ m_pUserData(VMA_NULL),
+ m_LastUseFrameIndex(currentFrameIndex),
+ m_Type((uint8_t)ALLOCATION_TYPE_NONE),
+ m_SuballocationType((uint8_t)VMA_SUBALLOCATION_TYPE_UNKNOWN),
+ m_MapCount(0),
+ m_Flags(userDataString ? (uint8_t)FLAG_USER_DATA_STRING : 0)
+ {
+#if VMA_STATS_STRING_ENABLED
+ m_CreationFrameIndex = currentFrameIndex;
+ m_BufferImageUsage = 0;
+#endif
+ }
+
+ ~VmaAllocation_T()
+ {
+ VMA_ASSERT((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) == 0 && "Allocation was not unmapped before destruction.");
+
+ // Check if owned string was freed.
+ VMA_ASSERT(m_pUserData == VMA_NULL);
+ }
+
+ void InitBlockAllocation(
+ VmaPool hPool,
+ VmaDeviceMemoryBlock* block,
+ VkDeviceSize offset,
+ VkDeviceSize alignment,
+ VkDeviceSize size,
+ VmaSuballocationType suballocationType,
+ bool mapped,
+ bool canBecomeLost)
+ {
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+ VMA_ASSERT(block != VMA_NULL);
+ m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;
+ m_Alignment = alignment;
+ m_Size = size;
+ m_MapCount = mapped ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0;
+ m_SuballocationType = (uint8_t)suballocationType;
+ m_BlockAllocation.m_hPool = hPool;
+ m_BlockAllocation.m_Block = block;
+ m_BlockAllocation.m_Offset = offset;
+ m_BlockAllocation.m_CanBecomeLost = canBecomeLost;
+ }
+
+ void InitLost()
+ {
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+ VMA_ASSERT(m_LastUseFrameIndex.load() == VMA_FRAME_INDEX_LOST);
+ m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;
+ m_BlockAllocation.m_hPool = VK_NULL_HANDLE;
+ m_BlockAllocation.m_Block = VMA_NULL;
+ m_BlockAllocation.m_Offset = 0;
+ m_BlockAllocation.m_CanBecomeLost = true;
+ }
+
+ void ChangeBlockAllocation(
+ VmaAllocator hAllocator,
+ VmaDeviceMemoryBlock* block,
+ VkDeviceSize offset);
+
+ void ChangeSize(VkDeviceSize newSize);
+ void ChangeOffset(VkDeviceSize newOffset);
+
+ // pMappedData not null means allocation is created with MAPPED flag.
+ void InitDedicatedAllocation(
+ uint32_t memoryTypeIndex,
+ VkDeviceMemory hMemory,
+ VmaSuballocationType suballocationType,
+ void* pMappedData,
+ VkDeviceSize size)
+ {
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+ VMA_ASSERT(hMemory != VK_NULL_HANDLE);
+ m_Type = (uint8_t)ALLOCATION_TYPE_DEDICATED;
+ m_Alignment = 0;
+ m_Size = size;
+ m_SuballocationType = (uint8_t)suballocationType;
+ m_MapCount = (pMappedData != VMA_NULL) ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0;
+ m_DedicatedAllocation.m_MemoryTypeIndex = memoryTypeIndex;
+ m_DedicatedAllocation.m_hMemory = hMemory;
+ m_DedicatedAllocation.m_pMappedData = pMappedData;
+ }
+
+ ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }
+ VkDeviceSize GetAlignment() const { return m_Alignment; }
+ VkDeviceSize GetSize() const { return m_Size; }
+ bool IsUserDataString() const { return (m_Flags & FLAG_USER_DATA_STRING) != 0; }
+ void* GetUserData() const { return m_pUserData; }
+ void SetUserData(VmaAllocator hAllocator, void* pUserData);
+ VmaSuballocationType GetSuballocationType() const { return (VmaSuballocationType)m_SuballocationType; }
+
+ VmaDeviceMemoryBlock* GetBlock() const
+ {
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+ return m_BlockAllocation.m_Block;
+ }
+ VkDeviceSize GetOffset() const;
+ VkDeviceMemory GetMemory() const;
+ uint32_t GetMemoryTypeIndex() const;
+ bool IsPersistentMap() const { return (m_MapCount & MAP_COUNT_FLAG_PERSISTENT_MAP) != 0; }
+ void* GetMappedData() const;
+ bool CanBecomeLost() const;
+ VmaPool GetPool() const;
+
+ uint32_t GetLastUseFrameIndex() const
+ {
+ return m_LastUseFrameIndex.load();
+ }
+ bool CompareExchangeLastUseFrameIndex(uint32_t& expected, uint32_t desired)
+ {
+ return m_LastUseFrameIndex.compare_exchange_weak(expected, desired);
+ }
+ /*
+ - If hAllocation.LastUseFrameIndex + frameInUseCount < allocator.CurrentFrameIndex,
+ makes it lost by setting LastUseFrameIndex = VMA_FRAME_INDEX_LOST and returns true.
+ - Else, returns false.
+
+ If hAllocation is already lost, assert - you should not call it then.
+ If hAllocation was not created with CAN_BECOME_LOST_BIT, assert.
+ */
+ bool MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+ void DedicatedAllocCalcStatsInfo(VmaStatInfo& outInfo)
+ {
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_DEDICATED);
+ outInfo.blockCount = 1;
+ outInfo.allocationCount = 1;
+ outInfo.unusedRangeCount = 0;
+ outInfo.usedBytes = m_Size;
+ outInfo.unusedBytes = 0;
+ outInfo.allocationSizeMin = outInfo.allocationSizeMax = m_Size;
+ outInfo.unusedRangeSizeMin = UINT64_MAX;
+ outInfo.unusedRangeSizeMax = 0;
+ }
+
+ void BlockAllocMap();
+ void BlockAllocUnmap();
+ VkResult DedicatedAllocMap(VmaAllocator hAllocator, void** ppData);
+ void DedicatedAllocUnmap(VmaAllocator hAllocator);
+
+#if VMA_STATS_STRING_ENABLED
+ uint32_t GetCreationFrameIndex() const { return m_CreationFrameIndex; }
+ uint32_t GetBufferImageUsage() const { return m_BufferImageUsage; }
+
+ void InitBufferImageUsage(uint32_t bufferImageUsage)
+ {
+ VMA_ASSERT(m_BufferImageUsage == 0);
+ m_BufferImageUsage = bufferImageUsage;
+ }
+
+ void PrintParameters(class VmaJsonWriter& json) const;
+#endif
+
+private:
+ VkDeviceSize m_Alignment;
+ VkDeviceSize m_Size;
+ void* m_pUserData;
+ VMA_ATOMIC_UINT32 m_LastUseFrameIndex;
+ uint8_t m_Type; // ALLOCATION_TYPE
+ uint8_t m_SuballocationType; // VmaSuballocationType
+ // Bit 0x80 is set when allocation was created with VMA_ALLOCATION_CREATE_MAPPED_BIT.
+ // Bits with mask 0x7F are reference counter for vmaMapMemory()/vmaUnmapMemory().
+ uint8_t m_MapCount;
+ uint8_t m_Flags; // enum FLAGS
+
+ // Allocation out of VmaDeviceMemoryBlock.
+ struct BlockAllocation
+ {
+ VmaPool m_hPool; // Null if belongs to general memory.
+ VmaDeviceMemoryBlock* m_Block;
+ VkDeviceSize m_Offset;
+ bool m_CanBecomeLost;
+ };
+
+ // Allocation for an object that has its own private VkDeviceMemory.
+ struct DedicatedAllocation
+ {
+ uint32_t m_MemoryTypeIndex;
+ VkDeviceMemory m_hMemory;
+ void* m_pMappedData; // Not null means memory is mapped.
+ };
+
+ union
+ {
+ // Allocation out of VmaDeviceMemoryBlock.
+ BlockAllocation m_BlockAllocation;
+ // Allocation for an object that has its own private VkDeviceMemory.
+ DedicatedAllocation m_DedicatedAllocation;
+ };
+
+#if VMA_STATS_STRING_ENABLED
+ uint32_t m_CreationFrameIndex;
+ uint32_t m_BufferImageUsage; // 0 if unknown.
+#endif
+
+ void FreeUserDataString(VmaAllocator hAllocator);
+};
+
+/*
+Represents a region of VmaDeviceMemoryBlock that is either assigned and returned as
+allocated memory block or free.
+*/
+struct VmaSuballocation
+{
+ VkDeviceSize offset;
+ VkDeviceSize size;
+ VmaAllocation hAllocation;
+ VmaSuballocationType type;
+};
+
+// Comparator for offsets.
+struct VmaSuballocationOffsetLess
+{
+ bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const
+ {
+ return lhs.offset < rhs.offset;
+ }
+};
+struct VmaSuballocationOffsetGreater
+{
+ bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const
+ {
+ return lhs.offset > rhs.offset;
+ }
+};
+
+typedef VmaList< VmaSuballocation, VmaStlAllocator<VmaSuballocation> > VmaSuballocationList;
+
+// Cost of one additional allocation lost, as equivalent in bytes.
+static const VkDeviceSize VMA_LOST_ALLOCATION_COST = 1048576;
+
+/*
+Parameters of planned allocation inside a VmaDeviceMemoryBlock.
+
+If canMakeOtherLost was false:
+- item points to a FREE suballocation.
+- itemsToMakeLostCount is 0.
+
+If canMakeOtherLost was true:
+- item points to first of sequence of suballocations, which are either FREE,
+ or point to VmaAllocations that can become lost.
+- itemsToMakeLostCount is the number of VmaAllocations that need to be made lost for
+ the requested allocation to succeed.
+*/
+struct VmaAllocationRequest
+{
+ VkDeviceSize offset;
+ VkDeviceSize sumFreeSize; // Sum size of free items that overlap with proposed allocation.
+ VkDeviceSize sumItemSize; // Sum size of items to make lost that overlap with proposed allocation.
+ VmaSuballocationList::iterator item;
+ size_t itemsToMakeLostCount;
+ void* customData;
+
+ VkDeviceSize CalcCost() const
+ {
+ return sumItemSize + itemsToMakeLostCount * VMA_LOST_ALLOCATION_COST;
+ }
+};
+
+/*
+Data structure used for bookkeeping of allocations and unused ranges of memory
+in a single VkDeviceMemory block.
+*/
+class VmaBlockMetadata
+{
+public:
+ VmaBlockMetadata(VmaAllocator hAllocator);
+ virtual ~VmaBlockMetadata() { }
+ virtual void Init(VkDeviceSize size) { m_Size = size; }
+
+ // Validates all data structures inside this object. If not valid, returns false.
+ virtual bool Validate() const = 0;
+ VkDeviceSize GetSize() const { return m_Size; }
+ virtual size_t GetAllocationCount() const = 0;
+ virtual VkDeviceSize GetSumFreeSize() const = 0;
+ virtual VkDeviceSize GetUnusedRangeSizeMax() const = 0;
+ // Returns true if this block is empty - contains only single free suballocation.
+ virtual bool IsEmpty() const = 0;
+
+ virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const = 0;
+ // Shouldn't modify blockCount.
+ virtual void AddPoolStats(VmaPoolStats& inoutStats) const = 0;
+
+#if VMA_STATS_STRING_ENABLED
+ virtual void PrintDetailedMap(class VmaJsonWriter& json) const = 0;
+#endif
+
+ // Tries to find a place for suballocation with given parameters inside this block.
+ // If succeeded, fills pAllocationRequest and returns true.
+ // If failed, returns false.
+ virtual bool CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ // Always one of VMA_ALLOCATION_CREATE_STRATEGY_* or VMA_ALLOCATION_INTERNAL_STRATEGY_* flags.
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest) = 0;
+
+ virtual bool MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest) = 0;
+
+ virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) = 0;
+
+ virtual VkResult CheckCorruption(const void* pBlockData) = 0;
+
+ // Makes actual allocation based on request. Request must already be checked and valid.
+ virtual void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ bool upperAddress,
+ VmaAllocation hAllocation) = 0;
+
+ // Frees suballocation assigned to given memory region.
+ virtual void Free(const VmaAllocation allocation) = 0;
+ virtual void FreeAtOffset(VkDeviceSize offset) = 0;
+
+ // Tries to resize (grow or shrink) space for given allocation, in place.
+ virtual bool ResizeAllocation(const VmaAllocation /*alloc*/, VkDeviceSize /*newSize*/) { return false; }
+
+protected:
+ const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; }
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap_Begin(class VmaJsonWriter& json,
+ VkDeviceSize unusedBytes,
+ size_t allocationCount,
+ size_t unusedRangeCount) const;
+ void PrintDetailedMap_Allocation(class VmaJsonWriter& json,
+ VkDeviceSize offset,
+ VmaAllocation hAllocation) const;
+ void PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,
+ VkDeviceSize offset,
+ VkDeviceSize size) const;
+ void PrintDetailedMap_End(class VmaJsonWriter& json) const;
+#endif
+
+private:
+ VkDeviceSize m_Size;
+ const VkAllocationCallbacks* m_pAllocationCallbacks;
+};
+
+#define VMA_VALIDATE(cond) do { if(!(cond)) { \
+ VMA_ASSERT(0 && "Validation failed: " #cond); \
+ return false; \
+ } } while(false)
+
+class VmaBlockMetadata_Generic : public VmaBlockMetadata
+{
+ VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic)
+public:
+ VmaBlockMetadata_Generic(VmaAllocator hAllocator);
+ virtual ~VmaBlockMetadata_Generic();
+ virtual void Init(VkDeviceSize size);
+
+ virtual bool Validate() const;
+ virtual size_t GetAllocationCount() const { return m_Suballocations.size() - m_FreeCount; }
+ virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; }
+ virtual VkDeviceSize GetUnusedRangeSizeMax() const;
+ virtual bool IsEmpty() const;
+
+ virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
+ virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
+
+#if VMA_STATS_STRING_ENABLED
+ virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
+#endif
+
+ virtual bool CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual bool MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+ virtual VkResult CheckCorruption(const void* pBlockData);
+
+ virtual void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ bool upperAddress,
+ VmaAllocation hAllocation);
+
+ virtual void Free(const VmaAllocation allocation);
+ virtual void FreeAtOffset(VkDeviceSize offset);
+
+ virtual bool ResizeAllocation(const VmaAllocation alloc, VkDeviceSize newSize);
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // For defragmentation
+
+ bool IsBufferImageGranularityConflictPossible(
+ VkDeviceSize bufferImageGranularity,
+ VmaSuballocationType& inOutPrevSuballocType) const;
+
+private:
+ friend class VmaDefragmentationAlgorithm_Generic;
+ friend class VmaDefragmentationAlgorithm_Fast;
+
+ uint32_t m_FreeCount;
+ VkDeviceSize m_SumFreeSize;
+ VmaSuballocationList m_Suballocations;
+ // Suballocations that are free and have size greater than certain threshold.
+ // Sorted by size, ascending.
+ VmaVector< VmaSuballocationList::iterator, VmaStlAllocator< VmaSuballocationList::iterator > > m_FreeSuballocationsBySize;
+
+ bool ValidateFreeSuballocationList() const;
+
+ // Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem.
+ // If yes, fills pOffset and returns true. If no, returns false.
+ bool CheckAllocation(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ VmaSuballocationList::const_iterator suballocItem,
+ bool canMakeOtherLost,
+ VkDeviceSize* pOffset,
+ size_t* itemsToMakeLostCount,
+ VkDeviceSize* pSumFreeSize,
+ VkDeviceSize* pSumItemSize) const;
+ // Given free suballocation, it merges it with following one, which must also be free.
+ void MergeFreeWithNext(VmaSuballocationList::iterator item);
+ // Releases given suballocation, making it free.
+ // Merges it with adjacent free suballocations if applicable.
+ // Returns iterator to new free suballocation at this place.
+ VmaSuballocationList::iterator FreeSuballocation(VmaSuballocationList::iterator suballocItem);
+ // Given free suballocation, it inserts it into sorted list of
+ // m_FreeSuballocationsBySize if it's suitable.
+ void RegisterFreeSuballocation(VmaSuballocationList::iterator item);
+ // Given free suballocation, it removes it from sorted list of
+ // m_FreeSuballocationsBySize if it's suitable.
+ void UnregisterFreeSuballocation(VmaSuballocationList::iterator item);
+};
+
+/*
+Allocations and their references in internal data structure look like this:
+
+if(m_2ndVectorMode == SECOND_VECTOR_EMPTY):
+
+ 0 +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount]
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount + 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 1st[1st.size() - 1]
+ +-------+
+ | |
+ | |
+ | |
+GetSize() +-------+
+
+if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER):
+
+ 0 +-------+
+ | Alloc | 2nd[0]
+ +-------+
+ | Alloc | 2nd[1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 2nd[2nd.size() - 1]
+ +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount]
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount + 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 1st[1st.size() - 1]
+ +-------+
+ | |
+GetSize() +-------+
+
+if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK):
+
+ 0 +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount]
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount + 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 1st[1st.size() - 1]
+ +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 2nd[2nd.size() - 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 2nd[1]
+ +-------+
+ | Alloc | 2nd[0]
+GetSize() +-------+
+
+*/
+class VmaBlockMetadata_Linear : public VmaBlockMetadata
+{
+ VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear)
+public:
+ VmaBlockMetadata_Linear(VmaAllocator hAllocator);
+ virtual ~VmaBlockMetadata_Linear();
+ virtual void Init(VkDeviceSize size);
+
+ virtual bool Validate() const;
+ virtual size_t GetAllocationCount() const;
+ virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; }
+ virtual VkDeviceSize GetUnusedRangeSizeMax() const;
+ virtual bool IsEmpty() const { return GetAllocationCount() == 0; }
+
+ virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
+ virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
+
+#if VMA_STATS_STRING_ENABLED
+ virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
+#endif
+
+ virtual bool CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual bool MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+ virtual VkResult CheckCorruption(const void* pBlockData);
+
+ virtual void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ bool upperAddress,
+ VmaAllocation hAllocation);
+
+ virtual void Free(const VmaAllocation allocation);
+ virtual void FreeAtOffset(VkDeviceSize offset);
+
+private:
+ /*
+ There are two suballocation vectors, used in ping-pong way.
+ The one with index m_1stVectorIndex is called 1st.
+ The one with index (m_1stVectorIndex ^ 1) is called 2nd.
+ 2nd can be non-empty only when 1st is not empty.
+ When 2nd is not empty, m_2ndVectorMode indicates its mode of operation.
+ */
+ typedef VmaVector< VmaSuballocation, VmaStlAllocator<VmaSuballocation> > SuballocationVectorType;
+
+ enum SECOND_VECTOR_MODE
+ {
+ SECOND_VECTOR_EMPTY,
+ /*
+ Suballocations in 2nd vector are created later than the ones in 1st, but they
+ all have smaller offset.
+ */
+ SECOND_VECTOR_RING_BUFFER,
+ /*
+ Suballocations in 2nd vector are upper side of double stack.
+ They all have offsets higher than those in 1st vector.
+ Top of this stack means smaller offsets, but higher indices in this vector.
+ */
+ SECOND_VECTOR_DOUBLE_STACK,
+ };
+
+ VkDeviceSize m_SumFreeSize;
+ SuballocationVectorType m_Suballocations0, m_Suballocations1;
+ uint32_t m_1stVectorIndex;
+ SECOND_VECTOR_MODE m_2ndVectorMode;
+
+ SuballocationVectorType& AccessSuballocations1st() { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }
+ SuballocationVectorType& AccessSuballocations2nd() { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }
+ const SuballocationVectorType& AccessSuballocations1st() const { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }
+ const SuballocationVectorType& AccessSuballocations2nd() const { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }
+
+ // Number of items in 1st vector with hAllocation = null at the beginning.
+ size_t m_1stNullItemsBeginCount;
+ // Number of other items in 1st vector with hAllocation = null somewhere in the middle.
+ size_t m_1stNullItemsMiddleCount;
+ // Number of items in 2nd vector with hAllocation = null.
+ size_t m_2ndNullItemsCount;
+
+ bool ShouldCompact1st() const;
+ void CleanupAfterFree();
+};
+
+/*
+- GetSize() is the original size of allocated memory block.
+- m_UsableSize is this size aligned down to a power of two.
+ All allocations and calculations happen relative to m_UsableSize.
+- GetUnusableSize() is the difference between them.
+ It is repoted as separate, unused range, not available for allocations.
+
+Node at level 0 has size = m_UsableSize.
+Each next level contains nodes with size 2 times smaller than current level.
+m_LevelCount is the maximum number of levels to use in the current object.
+*/
+class VmaBlockMetadata_Buddy : public VmaBlockMetadata
+{
+ VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy)
+public:
+ VmaBlockMetadata_Buddy(VmaAllocator hAllocator);
+ virtual ~VmaBlockMetadata_Buddy();
+ virtual void Init(VkDeviceSize size);
+
+ virtual bool Validate() const;
+ virtual size_t GetAllocationCount() const { return m_AllocationCount; }
+ virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize + GetUnusableSize(); }
+ virtual VkDeviceSize GetUnusedRangeSizeMax() const;
+ virtual bool IsEmpty() const { return m_Root->type == Node::TYPE_FREE; }
+
+ virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
+ virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
+
+#if VMA_STATS_STRING_ENABLED
+ virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
+#endif
+
+ virtual bool CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual bool MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest);
+
+ virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+ virtual VkResult CheckCorruption(const void* /*pBlockData*/) { return VK_ERROR_FEATURE_NOT_PRESENT; }
+
+ virtual void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ bool upperAddress,
+ VmaAllocation hAllocation);
+
+ virtual void Free(const VmaAllocation allocation) { FreeAtOffset(allocation, allocation->GetOffset()); }
+ virtual void FreeAtOffset(VkDeviceSize offset) { FreeAtOffset(VMA_NULL, offset); }
+
+private:
+ static const VkDeviceSize MIN_NODE_SIZE = 32;
+ static const size_t MAX_LEVELS = 30;
+
+ struct ValidationContext
+ {
+ size_t calculatedAllocationCount;
+ size_t calculatedFreeCount;
+ VkDeviceSize calculatedSumFreeSize;
+
+ ValidationContext() :
+ calculatedAllocationCount(0),
+ calculatedFreeCount(0),
+ calculatedSumFreeSize(0) { }
+ };
+
+ struct Node
+ {
+ VkDeviceSize offset;
+ enum TYPE
+ {
+ TYPE_FREE,
+ TYPE_ALLOCATION,
+ TYPE_SPLIT,
+ TYPE_COUNT
+ } type;
+ Node* parent;
+ Node* buddy;
+
+ union
+ {
+ struct
+ {
+ Node* prev;
+ Node* next;
+ } free;
+ struct
+ {
+ VmaAllocation alloc;
+ } allocation;
+ struct
+ {
+ Node* leftChild;
+ } split;
+ };
+ };
+
+ // Size of the memory block aligned down to a power of two.
+ VkDeviceSize m_UsableSize;
+ uint32_t m_LevelCount;
+
+ Node* m_Root;
+ struct {
+ Node* front;
+ Node* back;
+ } m_FreeList[MAX_LEVELS];
+ // Number of nodes in the tree with type == TYPE_ALLOCATION.
+ size_t m_AllocationCount;
+ // Number of nodes in the tree with type == TYPE_FREE.
+ size_t m_FreeCount;
+ // This includes space wasted due to internal fragmentation. Doesn't include unusable size.
+ VkDeviceSize m_SumFreeSize;
+
+ VkDeviceSize GetUnusableSize() const { return GetSize() - m_UsableSize; }
+ void DeleteNode(Node* node);
+ bool ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const;
+ uint32_t AllocSizeToLevel(VkDeviceSize allocSize) const;
+ inline VkDeviceSize LevelToNodeSize(uint32_t level) const { return m_UsableSize >> level; }
+ // Alloc passed just for validation. Can be null.
+ void FreeAtOffset(VmaAllocation alloc, VkDeviceSize offset);
+ void CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const;
+ // Adds node to the front of FreeList at given level.
+ // node->type must be FREE.
+ // node->free.prev, next can be undefined.
+ void AddToFreeListFront(uint32_t level, Node* node);
+ // Removes node from FreeList at given level.
+ // node->type must be FREE.
+ // node->free.prev, next stay untouched.
+ void RemoveFromFreeList(uint32_t level, Node* node);
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const;
+#endif
+};
+
+/*
+Represents a single block of device memory (`VkDeviceMemory`) with all the
+data about its regions (aka suballocations, #VmaAllocation), assigned and free.
+
+Thread-safety: This class must be externally synchronized.
+*/
+class VmaDeviceMemoryBlock
+{
+ VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock)
+public:
+ VmaBlockMetadata* m_pMetadata;
+
+ VmaDeviceMemoryBlock(VmaAllocator hAllocator);
+
+ ~VmaDeviceMemoryBlock()
+ {
+ VMA_ASSERT(m_MapCount == 0 && "VkDeviceMemory block is being destroyed while it is still mapped.");
+ VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
+ }
+
+ // Always call after construction.
+ void Init(
+ VmaAllocator hAllocator,
+ uint32_t newMemoryTypeIndex,
+ VkDeviceMemory newMemory,
+ VkDeviceSize newSize,
+ uint32_t id,
+ uint32_t algorithm);
+ // Always call before destruction.
+ void Destroy(VmaAllocator allocator);
+
+ VkDeviceMemory GetDeviceMemory() const { return m_hMemory; }
+ uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+ uint32_t GetId() const { return m_Id; }
+ void* GetMappedData() const { return m_pMappedData; }
+
+ // Validates all data structures inside this object. If not valid, returns false.
+ bool Validate() const;
+
+ VkResult CheckCorruption(VmaAllocator hAllocator);
+
+ // ppData can be null.
+ VkResult Map(VmaAllocator hAllocator, uint32_t count, void** ppData);
+ void Unmap(VmaAllocator hAllocator, uint32_t count);
+
+ VkResult WriteMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);
+ VkResult ValidateMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);
+
+ VkResult BindBufferMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkBuffer hBuffer);
+ VkResult BindImageMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkImage hImage);
+
+private:
+ uint32_t m_MemoryTypeIndex;
+ uint32_t m_Id;
+ VkDeviceMemory m_hMemory;
+
+ /*
+ Protects access to m_hMemory so it's not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.
+ Also protects m_MapCount, m_pMappedData.
+ Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex.
+ */
+ VMA_MUTEX m_Mutex;
+ uint32_t m_MapCount;
+ void* m_pMappedData;
+};
+
+struct VmaPointerLess
+{
+ bool operator()(const void* lhs, const void* rhs) const
+ {
+ return lhs < rhs;
+ }
+};
+
+struct VmaDefragmentationMove
+{
+ size_t srcBlockIndex;
+ size_t dstBlockIndex;
+ VkDeviceSize srcOffset;
+ VkDeviceSize dstOffset;
+ VkDeviceSize size;
+};
+
+class VmaDefragmentationAlgorithm;
+
+/*
+Sequence of VmaDeviceMemoryBlock. Represents memory blocks allocated for a specific
+Vulkan memory type.
+
+Synchronized internally with a mutex.
+*/
+struct VmaBlockVector
+{
+ VMA_CLASS_NO_COPY(VmaBlockVector)
+public:
+ VmaBlockVector(
+ VmaAllocator hAllocator,
+ uint32_t memoryTypeIndex,
+ VkDeviceSize preferredBlockSize,
+ size_t minBlockCount,
+ size_t maxBlockCount,
+ VkDeviceSize bufferImageGranularity,
+ uint32_t frameInUseCount,
+ bool isCustomPool,
+ bool explicitBlockSize,
+ uint32_t algorithm);
+ ~VmaBlockVector();
+
+ VkResult CreateMinBlocks();
+
+ uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+ VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; }
+ VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; }
+ uint32_t GetFrameInUseCount() const { return m_FrameInUseCount; }
+ uint32_t GetAlgorithm() const { return m_Algorithm; }
+
+ void GetPoolStats(VmaPoolStats* pStats);
+
+ bool IsEmpty() const { return m_Blocks.empty(); }
+ bool IsCorruptionDetectionEnabled() const;
+
+ VkResult Allocate(
+ VmaPool hCurrentPool,
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ void Free(
+ VmaAllocation hAllocation);
+
+ // Adds statistics of this BlockVector to pStats.
+ void AddStats(VmaStats* pStats);
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap(class VmaJsonWriter& json);
+#endif
+
+ void MakePoolAllocationsLost(
+ uint32_t currentFrameIndex,
+ size_t* pLostAllocationCount);
+ VkResult CheckCorruption();
+
+ // Saves results in pCtx->res.
+ void Defragment(
+ class VmaBlockVectorDefragmentationContext* pCtx,
+ VmaDefragmentationStats* pStats,
+ VkDeviceSize& maxCpuBytesToMove, uint32_t& maxCpuAllocationsToMove,
+ VkDeviceSize& maxGpuBytesToMove, uint32_t& maxGpuAllocationsToMove,
+ VkCommandBuffer commandBuffer);
+ void DefragmentationEnd(
+ class VmaBlockVectorDefragmentationContext* pCtx,
+ VmaDefragmentationStats* pStats);
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // To be used only while the m_Mutex is locked. Used during defragmentation.
+
+ size_t GetBlockCount() const { return m_Blocks.size(); }
+ VmaDeviceMemoryBlock* GetBlock(size_t index) const { return m_Blocks[index]; }
+ size_t CalcAllocationCount() const;
+ bool IsBufferImageGranularityConflictPossible() const;
+
+private:
+ friend class VmaDefragmentationAlgorithm_Generic;
+
+ const VmaAllocator m_hAllocator;
+ const uint32_t m_MemoryTypeIndex;
+ const VkDeviceSize m_PreferredBlockSize;
+ const size_t m_MinBlockCount;
+ const size_t m_MaxBlockCount;
+ const VkDeviceSize m_BufferImageGranularity;
+ const uint32_t m_FrameInUseCount;
+ const bool m_IsCustomPool;
+ const bool m_ExplicitBlockSize;
+ const uint32_t m_Algorithm;
+ /* There can be at most one allocation that is completely empty - a
+ hysteresis to avoid pessimistic case of alternating creation and destruction
+ of a VkDeviceMemory. */
+ bool m_HasEmptyBlock;
+ VMA_RW_MUTEX m_Mutex;
+ // Incrementally sorted by sumFreeSize, ascending.
+ VmaVector< VmaDeviceMemoryBlock*, VmaStlAllocator<VmaDeviceMemoryBlock*> > m_Blocks;
+ uint32_t m_NextBlockId;
+
+ VkDeviceSize CalcMaxBlockSize() const;
+
+ // Finds and removes given block from vector.
+ void Remove(VmaDeviceMemoryBlock* pBlock);
+
+ // Performs single step in sorting m_Blocks. They may not be fully sorted
+ // after this call.
+ void IncrementallySortBlocks();
+
+ VkResult AllocatePage(
+ VmaPool hCurrentPool,
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ VmaAllocation* pAllocation);
+
+ // To be used only without CAN_MAKE_OTHER_LOST flag.
+ VkResult AllocateFromBlock(
+ VmaDeviceMemoryBlock* pBlock,
+ VmaPool hCurrentPool,
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ VmaAllocationCreateFlags allocFlags,
+ void* pUserData,
+ VmaSuballocationType suballocType,
+ uint32_t strategy,
+ VmaAllocation* pAllocation);
+
+ VkResult CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex);
+
+ // Saves result to pCtx->res.
+ void ApplyDefragmentationMovesCpu(
+ class VmaBlockVectorDefragmentationContext* pDefragCtx,
+ const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves);
+ // Saves result to pCtx->res.
+ void ApplyDefragmentationMovesGpu(
+ class VmaBlockVectorDefragmentationContext* pDefragCtx,
+ const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkCommandBuffer commandBuffer);
+
+ /*
+ Used during defragmentation. pDefragmentationStats is optional. It's in/out
+ - updated with new data.
+ */
+ void FreeEmptyBlocks(VmaDefragmentationStats* pDefragmentationStats);
+};
+
+struct VmaPool_T
+{
+ VMA_CLASS_NO_COPY(VmaPool_T)
+public:
+ VmaBlockVector m_BlockVector;
+
+ VmaPool_T(
+ VmaAllocator hAllocator,
+ const VmaPoolCreateInfo& createInfo,
+ VkDeviceSize preferredBlockSize);
+ ~VmaPool_T();
+
+ uint32_t GetId() const { return m_Id; }
+ void SetId(uint32_t id) { VMA_ASSERT(m_Id == 0); m_Id = id; }
+
+#if VMA_STATS_STRING_ENABLED
+ //void PrintDetailedMap(class VmaStringBuilder& sb);
+#endif
+
+private:
+ uint32_t m_Id;
+};
+
+/*
+Performs defragmentation:
+
+- Updates `pBlockVector->m_pMetadata`.
+- Updates allocations by calling ChangeBlockAllocation() or ChangeOffset().
+- Does not move actual data, only returns requested moves as `moves`.
+*/
+class VmaDefragmentationAlgorithm
+{
+ VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm)
+public:
+ VmaDefragmentationAlgorithm(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex) :
+ m_hAllocator(hAllocator),
+ m_pBlockVector(pBlockVector),
+ m_CurrentFrameIndex(currentFrameIndex)
+ {
+ }
+ virtual ~VmaDefragmentationAlgorithm()
+ {
+ }
+
+ virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) = 0;
+ virtual void AddAll() = 0;
+
+ virtual VkResult Defragment(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove) = 0;
+
+ virtual VkDeviceSize GetBytesMoved() const = 0;
+ virtual uint32_t GetAllocationsMoved() const = 0;
+
+protected:
+ VmaAllocator const m_hAllocator;
+ VmaBlockVector* const m_pBlockVector;
+ const uint32_t m_CurrentFrameIndex;
+
+ struct AllocationInfo
+ {
+ VmaAllocation m_hAllocation;
+ VkBool32* m_pChanged;
+
+ AllocationInfo() :
+ m_hAllocation(VK_NULL_HANDLE),
+ m_pChanged(VMA_NULL)
+ {
+ }
+ AllocationInfo(VmaAllocation hAlloc, VkBool32* pChanged) :
+ m_hAllocation(hAlloc),
+ m_pChanged(pChanged)
+ {
+ }
+ };
+};
+
+class VmaDefragmentationAlgorithm_Generic : public VmaDefragmentationAlgorithm
+{
+ VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Generic)
+public:
+ VmaDefragmentationAlgorithm_Generic(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex,
+ bool overlappingMoveSupported);
+ virtual ~VmaDefragmentationAlgorithm_Generic();
+
+ virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
+ virtual void AddAll() { m_AllAllocations = true; }
+
+ virtual VkResult Defragment(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove);
+
+ virtual VkDeviceSize GetBytesMoved() const { return m_BytesMoved; }
+ virtual uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; }
+
+private:
+ uint32_t m_AllocationCount;
+ bool m_AllAllocations;
+
+ VkDeviceSize m_BytesMoved;
+ uint32_t m_AllocationsMoved;
+
+ struct AllocationInfoSizeGreater
+ {
+ bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const
+ {
+ return lhs.m_hAllocation->GetSize() > rhs.m_hAllocation->GetSize();
+ }
+ };
+
+ struct AllocationInfoOffsetGreater
+ {
+ bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const
+ {
+ return lhs.m_hAllocation->GetOffset() > rhs.m_hAllocation->GetOffset();
+ }
+ };
+
+ struct BlockInfo
+ {
+ size_t m_OriginalBlockIndex;
+ VmaDeviceMemoryBlock* m_pBlock;
+ bool m_HasNonMovableAllocations;
+ VmaVector< AllocationInfo, VmaStlAllocator<AllocationInfo> > m_Allocations;
+
+ BlockInfo(const VkAllocationCallbacks* pAllocationCallbacks) :
+ m_OriginalBlockIndex(SIZE_MAX),
+ m_pBlock(VMA_NULL),
+ m_HasNonMovableAllocations(true),
+ m_Allocations(pAllocationCallbacks)
+ {
+ }
+
+ void CalcHasNonMovableAllocations()
+ {
+ const size_t blockAllocCount = m_pBlock->m_pMetadata->GetAllocationCount();
+ const size_t defragmentAllocCount = m_Allocations.size();
+ m_HasNonMovableAllocations = blockAllocCount != defragmentAllocCount;
+ }
+
+ void SortAllocationsBySizeDescending()
+ {
+ VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoSizeGreater());
+ }
+
+ void SortAllocationsByOffsetDescending()
+ {
+ VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoOffsetGreater());
+ }
+ };
+
+ struct BlockPointerLess
+ {
+ bool operator()(const BlockInfo* pLhsBlockInfo, const VmaDeviceMemoryBlock* pRhsBlock) const
+ {
+ return pLhsBlockInfo->m_pBlock < pRhsBlock;
+ }
+ bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const
+ {
+ return pLhsBlockInfo->m_pBlock < pRhsBlockInfo->m_pBlock;
+ }
+ };
+
+ // 1. Blocks with some non-movable allocations go first.
+ // 2. Blocks with smaller sumFreeSize go first.
+ struct BlockInfoCompareMoveDestination
+ {
+ bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const
+ {
+ if(pLhsBlockInfo->m_HasNonMovableAllocations && !pRhsBlockInfo->m_HasNonMovableAllocations)
+ {
+ return true;
+ }
+ if(!pLhsBlockInfo->m_HasNonMovableAllocations && pRhsBlockInfo->m_HasNonMovableAllocations)
+ {
+ return false;
+ }
+ if(pLhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize() < pRhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize())
+ {
+ return true;
+ }
+ return false;
+ }
+ };
+
+ typedef VmaVector< BlockInfo*, VmaStlAllocator<BlockInfo*> > BlockInfoVector;
+ BlockInfoVector m_Blocks;
+
+ VkResult DefragmentRound(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove);
+
+ size_t CalcBlocksWithNonMovableCount() const;
+
+ static bool MoveMakesSense(
+ size_t dstBlockIndex, VkDeviceSize dstOffset,
+ size_t srcBlockIndex, VkDeviceSize srcOffset);
+};
+
+class VmaDefragmentationAlgorithm_Fast : public VmaDefragmentationAlgorithm
+{
+ VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Fast)
+public:
+ VmaDefragmentationAlgorithm_Fast(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex,
+ bool overlappingMoveSupported);
+ virtual ~VmaDefragmentationAlgorithm_Fast();
+
+ virtual void AddAllocation(VmaAllocation /*hAlloc*/, VkBool32* /*pChanged*/) { ++m_AllocationCount; }
+ virtual void AddAll() { m_AllAllocations = true; }
+
+ virtual VkResult Defragment(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove);
+
+ virtual VkDeviceSize GetBytesMoved() const { return m_BytesMoved; }
+ virtual uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; }
+
+private:
+ struct BlockInfo
+ {
+ size_t origBlockIndex;
+ };
+
+ class FreeSpaceDatabase
+ {
+ public:
+ FreeSpaceDatabase()
+ {
+ FreeSpace s = {};
+ s.blockInfoIndex = SIZE_MAX;
+ for(size_t i = 0; i < MAX_COUNT; ++i)
+ {
+ m_FreeSpaces[i] = s;
+ }
+ }
+
+ void Register(size_t blockInfoIndex, VkDeviceSize offset, VkDeviceSize size)
+ {
+ if(size < VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ return;
+ }
+
+ // Find first invalid or the smallest structure.
+ size_t bestIndex = SIZE_MAX;
+ for(size_t i = 0; i < MAX_COUNT; ++i)
+ {
+ // Empty structure.
+ if(m_FreeSpaces[i].blockInfoIndex == SIZE_MAX)
+ {
+ bestIndex = i;
+ break;
+ }
+ if(m_FreeSpaces[i].size < size &&
+ (bestIndex == SIZE_MAX || m_FreeSpaces[bestIndex].size > m_FreeSpaces[i].size))
+ {
+ bestIndex = i;
+ }
+ }
+
+ if(bestIndex != SIZE_MAX)
+ {
+ m_FreeSpaces[bestIndex].blockInfoIndex = blockInfoIndex;
+ m_FreeSpaces[bestIndex].offset = offset;
+ m_FreeSpaces[bestIndex].size = size;
+ }
+ }
+
+ bool Fetch(VkDeviceSize alignment, VkDeviceSize size,
+ size_t& outBlockInfoIndex, VkDeviceSize& outDstOffset)
+ {
+ size_t bestIndex = SIZE_MAX;
+ VkDeviceSize bestFreeSpaceAfter = 0;
+ for(size_t i = 0; i < MAX_COUNT; ++i)
+ {
+ // Structure is valid.
+ if(m_FreeSpaces[i].blockInfoIndex != SIZE_MAX)
+ {
+ const VkDeviceSize dstOffset = VmaAlignUp(m_FreeSpaces[i].offset, alignment);
+ // Allocation fits into this structure.
+ if(dstOffset + size <= m_FreeSpaces[i].offset + m_FreeSpaces[i].size)
+ {
+ const VkDeviceSize freeSpaceAfter = (m_FreeSpaces[i].offset + m_FreeSpaces[i].size) -
+ (dstOffset + size);
+ if(bestIndex == SIZE_MAX || freeSpaceAfter > bestFreeSpaceAfter)
+ {
+ bestIndex = i;
+ bestFreeSpaceAfter = freeSpaceAfter;
+ }
+ }
+ }
+ }
+
+ if(bestIndex != SIZE_MAX)
+ {
+ outBlockInfoIndex = m_FreeSpaces[bestIndex].blockInfoIndex;
+ outDstOffset = VmaAlignUp(m_FreeSpaces[bestIndex].offset, alignment);
+
+ if(bestFreeSpaceAfter >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ // Leave this structure for remaining empty space.
+ const VkDeviceSize alignmentPlusSize = (outDstOffset - m_FreeSpaces[bestIndex].offset) + size;
+ m_FreeSpaces[bestIndex].offset += alignmentPlusSize;
+ m_FreeSpaces[bestIndex].size -= alignmentPlusSize;
+ }
+ else
+ {
+ // This structure becomes invalid.
+ m_FreeSpaces[bestIndex].blockInfoIndex = SIZE_MAX;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private:
+ static const size_t MAX_COUNT = 4;
+
+ struct FreeSpace
+ {
+ size_t blockInfoIndex; // SIZE_MAX means this structure is invalid.
+ VkDeviceSize offset;
+ VkDeviceSize size;
+ } m_FreeSpaces[MAX_COUNT];
+ };
+
+ const bool m_OverlappingMoveSupported;
+
+ uint32_t m_AllocationCount;
+ bool m_AllAllocations;
+
+ VkDeviceSize m_BytesMoved;
+ uint32_t m_AllocationsMoved;
+
+ VmaVector< BlockInfo, VmaStlAllocator<BlockInfo> > m_BlockInfos;
+
+ void PreprocessMetadata();
+ void PostprocessMetadata();
+ void InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, const VmaSuballocation& suballoc);
+};
+
+struct VmaBlockDefragmentationContext
+{
+ enum BLOCK_FLAG
+ {
+ BLOCK_FLAG_USED = 0x00000001,
+ };
+ uint32_t flags;
+ VkBuffer hBuffer;
+
+ VmaBlockDefragmentationContext() :
+ flags(0),
+ hBuffer(VK_NULL_HANDLE)
+ {
+ }
+};
+
+class VmaBlockVectorDefragmentationContext
+{
+ VMA_CLASS_NO_COPY(VmaBlockVectorDefragmentationContext)
+public:
+ VkResult res;
+ bool mutexLocked;
+ VmaVector< VmaBlockDefragmentationContext, VmaStlAllocator<VmaBlockDefragmentationContext> > blockContexts;
+
+ VmaBlockVectorDefragmentationContext(
+ VmaAllocator hAllocator,
+ VmaPool hCustomPool, // Optional.
+ VmaBlockVector* pBlockVector,
+ uint32_t currFrameIndex,
+ uint32_t flags);
+ ~VmaBlockVectorDefragmentationContext();
+
+ VmaPool GetCustomPool() const { return m_hCustomPool; }
+ VmaBlockVector* GetBlockVector() const { return m_pBlockVector; }
+ VmaDefragmentationAlgorithm* GetAlgorithm() const { return m_pAlgorithm; }
+
+ void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
+ void AddAll() { m_AllAllocations = true; }
+
+ void Begin(bool overlappingMoveSupported);
+
+private:
+ const VmaAllocator m_hAllocator;
+ // Null if not from custom pool.
+ const VmaPool m_hCustomPool;
+ // Redundant, for convenience not to fetch from m_hCustomPool->m_BlockVector or m_hAllocator->m_pBlockVectors.
+ VmaBlockVector* const m_pBlockVector;
+ const uint32_t m_CurrFrameIndex;
+ /*const uint32_t m_AlgorithmFlags;*/
+ // Owner of this object.
+ VmaDefragmentationAlgorithm* m_pAlgorithm;
+
+ struct AllocInfo
+ {
+ VmaAllocation hAlloc;
+ VkBool32* pChanged;
+ };
+ // Used between constructor and Begin.
+ VmaVector< AllocInfo, VmaStlAllocator<AllocInfo> > m_Allocations;
+ bool m_AllAllocations;
+};
+
+struct VmaDefragmentationContext_T
+{
+private:
+ VMA_CLASS_NO_COPY(VmaDefragmentationContext_T)
+public:
+ VmaDefragmentationContext_T(
+ VmaAllocator hAllocator,
+ uint32_t currFrameIndex,
+ uint32_t flags,
+ VmaDefragmentationStats* pStats);
+ ~VmaDefragmentationContext_T();
+
+ void AddPools(uint32_t poolCount, VmaPool* pPools);
+ void AddAllocations(
+ uint32_t allocationCount,
+ VmaAllocation* pAllocations,
+ VkBool32* pAllocationsChanged);
+
+ /*
+ Returns:
+ - `VK_SUCCESS` if succeeded and object can be destroyed immediately.
+ - `VK_NOT_READY` if succeeded but the object must remain alive until vmaDefragmentationEnd().
+ - Negative value if error occured and object can be destroyed immediately.
+ */
+ VkResult Defragment(
+ VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove,
+ VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove,
+ VkCommandBuffer commandBuffer, VmaDefragmentationStats* pStats);
+
+private:
+ const VmaAllocator m_hAllocator;
+ const uint32_t m_CurrFrameIndex;
+ const uint32_t m_Flags;
+ VmaDefragmentationStats* const m_pStats;
+ // Owner of these objects.
+ VmaBlockVectorDefragmentationContext* m_DefaultPoolContexts[VK_MAX_MEMORY_TYPES];
+ // Owner of these objects.
+ VmaVector< VmaBlockVectorDefragmentationContext*, VmaStlAllocator<VmaBlockVectorDefragmentationContext*> > m_CustomPoolContexts;
+};
+
+#if VMA_RECORDING_ENABLED
+
+class VmaRecorder
+{
+public:
+ VmaRecorder();
+ VkResult Init(const VmaRecordSettings& settings, bool useMutex);
+ void WriteConfiguration(
+ const VkPhysicalDeviceProperties& devProps,
+ const VkPhysicalDeviceMemoryProperties& memProps,
+ bool dedicatedAllocationExtensionEnabled);
+ ~VmaRecorder();
+
+ void RecordCreateAllocator(uint32_t frameIndex);
+ void RecordDestroyAllocator(uint32_t frameIndex);
+ void RecordCreatePool(uint32_t frameIndex,
+ const VmaPoolCreateInfo& createInfo,
+ VmaPool pool);
+ void RecordDestroyPool(uint32_t frameIndex, VmaPool pool);
+ void RecordAllocateMemory(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation);
+ void RecordAllocateMemoryPages(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ const VmaAllocationCreateInfo& createInfo,
+ uint64_t allocationCount,
+ const VmaAllocation* pAllocations);
+ void RecordAllocateMemoryForBuffer(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation);
+ void RecordAllocateMemoryForImage(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation);
+ void RecordFreeMemory(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordFreeMemoryPages(uint32_t frameIndex,
+ uint64_t allocationCount,
+ const VmaAllocation* pAllocations);
+ void RecordResizeAllocation(
+ uint32_t frameIndex,
+ VmaAllocation allocation,
+ VkDeviceSize newSize);
+ void RecordSetAllocationUserData(uint32_t frameIndex,
+ VmaAllocation allocation,
+ const void* pUserData);
+ void RecordCreateLostAllocation(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordMapMemory(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordUnmapMemory(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordFlushAllocation(uint32_t frameIndex,
+ VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+ void RecordInvalidateAllocation(uint32_t frameIndex,
+ VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+ void RecordCreateBuffer(uint32_t frameIndex,
+ const VkBufferCreateInfo& bufCreateInfo,
+ const VmaAllocationCreateInfo& allocCreateInfo,
+ VmaAllocation allocation);
+ void RecordCreateImage(uint32_t frameIndex,
+ const VkImageCreateInfo& imageCreateInfo,
+ const VmaAllocationCreateInfo& allocCreateInfo,
+ VmaAllocation allocation);
+ void RecordDestroyBuffer(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordDestroyImage(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordTouchAllocation(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordGetAllocationInfo(uint32_t frameIndex,
+ VmaAllocation allocation);
+ void RecordMakePoolAllocationsLost(uint32_t frameIndex,
+ VmaPool pool);
+ void RecordDefragmentationBegin(uint32_t frameIndex,
+ const VmaDefragmentationInfo2& info,
+ VmaDefragmentationContext ctx);
+ void RecordDefragmentationEnd(uint32_t frameIndex,
+ VmaDefragmentationContext ctx);
+
+private:
+ struct CallParams
+ {
+ uint32_t threadId;
+ double time;
+ };
+
+ class UserDataString
+ {
+ public:
+ UserDataString(VmaAllocationCreateFlags allocFlags, const void* pUserData);
+ const char* GetString() const { return m_Str; }
+
+ private:
+ char m_PtrStr[17];
+ const char* m_Str;
+ };
+
+ bool m_UseMutex;
+ VmaRecordFlags m_Flags;
+ FILE* m_File;
+ VMA_MUTEX m_FileMutex;
+ int64_t m_Freq;
+ int64_t m_StartCounter;
+
+ void GetBasicParams(CallParams& outParams);
+
+ // T must be a pointer type, e.g. VmaAllocation, VmaPool.
+ template<typename T>
+ void PrintPointerList(uint64_t count, const T* pItems)
+ {
+ if(count)
+ {
+ fprintf(m_File, "%p", pItems[0]);
+ for(uint64_t i = 1; i < count; ++i)
+ {
+ fprintf(m_File, " %p", pItems[i]);
+ }
+ }
+ }
+
+ void PrintPointerList(uint64_t count, const VmaAllocation* pItems);
+ void Flush();
+};
+
+#endif // #if VMA_RECORDING_ENABLED
+
+// Main allocator object.
+struct VmaAllocator_T
+{
+ VMA_CLASS_NO_COPY(VmaAllocator_T)
+public:
+ bool m_UseMutex;
+ bool m_UseKhrDedicatedAllocation;
+ VkDevice m_hDevice;
+ bool m_AllocationCallbacksSpecified;
+ VkAllocationCallbacks m_AllocationCallbacks;
+ VmaDeviceMemoryCallbacks m_DeviceMemoryCallbacks;
+
+ // Number of bytes free out of limit, or VK_WHOLE_SIZE if no limit for that heap.
+ VkDeviceSize m_HeapSizeLimit[VK_MAX_MEMORY_HEAPS];
+ VMA_MUTEX m_HeapSizeLimitMutex;
+
+ VkPhysicalDeviceProperties m_PhysicalDeviceProperties;
+ VkPhysicalDeviceMemoryProperties m_MemProps;
+
+ // Default pools.
+ VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES];
+
+ // Each vector is sorted by memory (handle value).
+ typedef VmaVector< VmaAllocation, VmaStlAllocator<VmaAllocation> > AllocationVectorType;
+ AllocationVectorType* m_pDedicatedAllocations[VK_MAX_MEMORY_TYPES];
+ VMA_RW_MUTEX m_DedicatedAllocationsMutex[VK_MAX_MEMORY_TYPES];
+
+ VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo);
+ VkResult Init(const VmaAllocatorCreateInfo* pCreateInfo);
+ ~VmaAllocator_T();
+
+ const VkAllocationCallbacks* GetAllocationCallbacks() const
+ {
+ return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : 0;
+ }
+ const VmaVulkanFunctions& GetVulkanFunctions() const
+ {
+ return m_VulkanFunctions;
+ }
+
+ VkDeviceSize GetBufferImageGranularity() const
+ {
+ return VMA_MAX(
+ static_cast<VkDeviceSize>(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY),
+ m_PhysicalDeviceProperties.limits.bufferImageGranularity);
+ }
+
+ uint32_t GetMemoryHeapCount() const { return m_MemProps.memoryHeapCount; }
+ uint32_t GetMemoryTypeCount() const { return m_MemProps.memoryTypeCount; }
+
+ uint32_t MemoryTypeIndexToHeapIndex(uint32_t memTypeIndex) const
+ {
+ VMA_ASSERT(memTypeIndex < m_MemProps.memoryTypeCount);
+ return m_MemProps.memoryTypes[memTypeIndex].heapIndex;
+ }
+ // True when specific memory type is HOST_VISIBLE but not HOST_COHERENT.
+ bool IsMemoryTypeNonCoherent(uint32_t memTypeIndex) const
+ {
+ return (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ }
+ // Minimum alignment for all allocations in specific memory type.
+ VkDeviceSize GetMemoryTypeMinAlignment(uint32_t memTypeIndex) const
+ {
+ return IsMemoryTypeNonCoherent(memTypeIndex) ?
+ VMA_MAX((VkDeviceSize)VMA_DEBUG_ALIGNMENT, m_PhysicalDeviceProperties.limits.nonCoherentAtomSize) :
+ (VkDeviceSize)VMA_DEBUG_ALIGNMENT;
+ }
+
+ bool IsIntegratedGpu() const
+ {
+ return m_PhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
+ }
+
+#if VMA_RECORDING_ENABLED
+ VmaRecorder* GetRecorder() const { return m_pRecorder; }
+#endif
+
+ void GetBufferMemoryRequirements(
+ VkBuffer hBuffer,
+ VkMemoryRequirements& memReq,
+ bool& requiresDedicatedAllocation,
+ bool& prefersDedicatedAllocation) const;
+ void GetImageMemoryRequirements(
+ VkImage hImage,
+ VkMemoryRequirements& memReq,
+ bool& requiresDedicatedAllocation,
+ bool& prefersDedicatedAllocation) const;
+
+ // Main allocation function.
+ VkResult AllocateMemory(
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ // Main deallocation function.
+ void FreeMemory(
+ size_t allocationCount,
+ const VmaAllocation* pAllocations);
+
+ VkResult ResizeAllocation(
+ const VmaAllocation alloc,
+ VkDeviceSize newSize);
+
+ void CalculateStats(VmaStats* pStats);
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap(class VmaJsonWriter& json);
+#endif
+
+ VkResult DefragmentationBegin(
+ const VmaDefragmentationInfo2& info,
+ VmaDefragmentationStats* pStats,
+ VmaDefragmentationContext* pContext);
+ VkResult DefragmentationEnd(
+ VmaDefragmentationContext context);
+
+ void GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo);
+ bool TouchAllocation(VmaAllocation hAllocation);
+
+ VkResult CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool);
+ void DestroyPool(VmaPool pool);
+ void GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats);
+
+ void SetCurrentFrameIndex(uint32_t frameIndex);
+ uint32_t GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); }
+
+ void MakePoolAllocationsLost(
+ VmaPool hPool,
+ size_t* pLostAllocationCount);
+ VkResult CheckPoolCorruption(VmaPool hPool);
+ VkResult CheckCorruption(uint32_t memoryTypeBits);
+
+ void CreateLostAllocation(VmaAllocation* pAllocation);
+
+ VkResult AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory);
+ void FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory);
+
+ VkResult Map(VmaAllocation hAllocation, void** ppData);
+ void Unmap(VmaAllocation hAllocation);
+
+ VkResult BindBufferMemory(VmaAllocation hAllocation, VkBuffer hBuffer);
+ VkResult BindImageMemory(VmaAllocation hAllocation, VkImage hImage);
+
+ void FlushOrInvalidateAllocation(
+ VmaAllocation hAllocation,
+ VkDeviceSize offset, VkDeviceSize size,
+ VMA_CACHE_OPERATION op);
+
+ void FillAllocation(const VmaAllocation hAllocation, uint8_t pattern);
+
+private:
+ VkDeviceSize m_PreferredLargeHeapBlockSize;
+
+ VkPhysicalDevice m_PhysicalDevice;
+ VMA_ATOMIC_UINT32 m_CurrentFrameIndex;
+
+ VMA_RW_MUTEX m_PoolsMutex;
+ // Protected by m_PoolsMutex. Sorted by pointer value.
+ VmaVector<VmaPool, VmaStlAllocator<VmaPool> > m_Pools;
+ uint32_t m_NextPoolId;
+
+ VmaVulkanFunctions m_VulkanFunctions;
+
+#if VMA_RECORDING_ENABLED
+ VmaRecorder* m_pRecorder;
+#endif
+
+ void ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions);
+
+ VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);
+
+ VkResult AllocateMemoryOfType(
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ bool dedicatedAllocation,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ const VmaAllocationCreateInfo& createInfo,
+ uint32_t memTypeIndex,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ // Helper function only to be used inside AllocateDedicatedMemory.
+ VkResult AllocateDedicatedMemoryPage(
+ VkDeviceSize size,
+ VmaSuballocationType suballocType,
+ uint32_t memTypeIndex,
+ const VkMemoryAllocateInfo& allocInfo,
+ bool map,
+ bool isUserDataString,
+ void* pUserData,
+ VmaAllocation* pAllocation);
+
+ // Allocates and registers new VkDeviceMemory specifically for dedicated allocations.
+ VkResult AllocateDedicatedMemory(
+ VkDeviceSize size,
+ VmaSuballocationType suballocType,
+ uint32_t memTypeIndex,
+ bool map,
+ bool isUserDataString,
+ void* pUserData,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ // Tries to free pMemory as Dedicated Memory. Returns true if found and freed.
+ void FreeDedicatedMemory(VmaAllocation allocation);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Memory allocation #2 after VmaAllocator_T definition
+
+static void* VmaMalloc(VmaAllocator hAllocator, size_t size, size_t alignment)
+{
+ return VmaMalloc(&hAllocator->m_AllocationCallbacks, size, alignment);
+}
+
+static void VmaFree(VmaAllocator hAllocator, void* ptr)
+{
+ VmaFree(&hAllocator->m_AllocationCallbacks, ptr);
+}
+
+template<typename T>
+static T* VmaAllocate(VmaAllocator hAllocator)
+{
+ return (T*)VmaMalloc(hAllocator, sizeof(T), VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static T* VmaAllocateArray(VmaAllocator hAllocator, size_t count)
+{
+ return (T*)VmaMalloc(hAllocator, sizeof(T) * count, VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static void vma_delete(VmaAllocator hAllocator, T* ptr)
+{
+ if(ptr != VMA_NULL)
+ {
+ ptr->~T();
+ VmaFree(hAllocator, ptr);
+ }
+}
+
+template<typename T>
+static void vma_delete_array(VmaAllocator hAllocator, T* ptr, size_t count)
+{
+ if(ptr != VMA_NULL)
+ {
+ for(size_t i = count; i--; )
+ ptr[i].~T();
+ VmaFree(hAllocator, ptr);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaStringBuilder
+
+#if VMA_STATS_STRING_ENABLED
+
+class VmaStringBuilder
+{
+public:
+ VmaStringBuilder(VmaAllocator alloc) : m_Data(VmaStlAllocator<char>(alloc->GetAllocationCallbacks())) { }
+ size_t GetLength() const { return m_Data.size(); }
+ const char* GetData() const { return m_Data.data(); }
+
+ void Add(char ch) { m_Data.push_back(ch); }
+ void Add(const char* pStr);
+ void AddNewLine() { Add('\n'); }
+ void AddNumber(uint32_t num);
+ void AddNumber(uint64_t num);
+ void AddPointer(const void* ptr);
+
+private:
+ VmaVector< char, VmaStlAllocator<char> > m_Data;
+};
+
+void VmaStringBuilder::Add(const char* pStr)
+{
+ const size_t strLen = strlen(pStr);
+ if(strLen > 0)
+ {
+ const size_t oldCount = m_Data.size();
+ m_Data.resize(oldCount + strLen);
+ memcpy(m_Data.data() + oldCount, pStr, strLen);
+ }
+}
+
+void VmaStringBuilder::AddNumber(uint32_t num)
+{
+ char buf[11];
+ VmaUint32ToStr(buf, sizeof(buf), num);
+ Add(buf);
+}
+
+void VmaStringBuilder::AddNumber(uint64_t num)
+{
+ char buf[21];
+ VmaUint64ToStr(buf, sizeof(buf), num);
+ Add(buf);
+}
+
+void VmaStringBuilder::AddPointer(const void* ptr)
+{
+ char buf[21];
+ VmaPtrToStr(buf, sizeof(buf), ptr);
+ Add(buf);
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaJsonWriter
+
+#if VMA_STATS_STRING_ENABLED
+
+class VmaJsonWriter
+{
+ VMA_CLASS_NO_COPY(VmaJsonWriter)
+public:
+ VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb);
+ ~VmaJsonWriter();
+
+ void BeginObject(bool singleLine = false);
+ void EndObject();
+
+ void BeginArray(bool singleLine = false);
+ void EndArray();
+
+ void WriteString(const char* pStr);
+ void BeginString(const char* pStr = VMA_NULL);
+ void ContinueString(const char* pStr);
+ void ContinueString(uint32_t n);
+ void ContinueString(uint64_t n);
+ void ContinueString_Pointer(const void* ptr);
+ void EndString(const char* pStr = VMA_NULL);
+
+ void WriteNumber(uint32_t n);
+ void WriteNumber(uint64_t n);
+ void WriteBool(bool b);
+ void WriteNull();
+
+private:
+ static const char* const INDENT;
+
+ enum COLLECTION_TYPE
+ {
+ COLLECTION_TYPE_OBJECT,
+ COLLECTION_TYPE_ARRAY,
+ };
+ struct StackItem
+ {
+ COLLECTION_TYPE type;
+ uint32_t valueCount;
+ bool singleLineMode;
+ };
+
+ VmaStringBuilder& m_SB;
+ VmaVector< StackItem, VmaStlAllocator<StackItem> > m_Stack;
+ bool m_InsideString;
+
+ void BeginValue(bool isString);
+ void WriteIndent(bool oneLess = false);
+};
+
+const char* const VmaJsonWriter::INDENT = " ";
+
+VmaJsonWriter::VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb) :
+ m_SB(sb),
+ m_Stack(VmaStlAllocator<StackItem>(pAllocationCallbacks)),
+ m_InsideString(false)
+{
+}
+
+VmaJsonWriter::~VmaJsonWriter()
+{
+ VMA_ASSERT(!m_InsideString);
+ VMA_ASSERT(m_Stack.empty());
+}
+
+void VmaJsonWriter::BeginObject(bool singleLine)
+{
+ VMA_ASSERT(!m_InsideString);
+
+ BeginValue(false);
+ m_SB.Add('{');
+
+ StackItem item;
+ item.type = COLLECTION_TYPE_OBJECT;
+ item.valueCount = 0;
+ item.singleLineMode = singleLine;
+ m_Stack.push_back(item);
+}
+
+void VmaJsonWriter::EndObject()
+{
+ VMA_ASSERT(!m_InsideString);
+
+ WriteIndent(true);
+ m_SB.Add('}');
+
+ VMA_ASSERT(!m_Stack.empty() && m_Stack.back().type == COLLECTION_TYPE_OBJECT);
+ m_Stack.pop_back();
+}
+
+void VmaJsonWriter::BeginArray(bool singleLine)
+{
+ VMA_ASSERT(!m_InsideString);
+
+ BeginValue(false);
+ m_SB.Add('[');
+
+ StackItem item;
+ item.type = COLLECTION_TYPE_ARRAY;
+ item.valueCount = 0;
+ item.singleLineMode = singleLine;
+ m_Stack.push_back(item);
+}
+
+void VmaJsonWriter::EndArray()
+{
+ VMA_ASSERT(!m_InsideString);
+
+ WriteIndent(true);
+ m_SB.Add(']');
+
+ VMA_ASSERT(!m_Stack.empty() && m_Stack.back().type == COLLECTION_TYPE_ARRAY);
+ m_Stack.pop_back();
+}
+
+void VmaJsonWriter::WriteString(const char* pStr)
+{
+ BeginString(pStr);
+ EndString();
+}
+
+void VmaJsonWriter::BeginString(const char* pStr)
+{
+ VMA_ASSERT(!m_InsideString);
+
+ BeginValue(true);
+ m_SB.Add('"');
+ m_InsideString = true;
+ if(pStr != VMA_NULL && pStr[0] != '\0')
+ {
+ ContinueString(pStr);
+ }
+}
+
+void VmaJsonWriter::ContinueString(const char* pStr)
+{
+ VMA_ASSERT(m_InsideString);
+
+ const size_t strLen = strlen(pStr);
+ for(size_t i = 0; i < strLen; ++i)
+ {
+ char ch = pStr[i];
+ if(ch == '\\')
+ {
+ m_SB.Add("\\\\");
+ }
+ else if(ch == '"')
+ {
+ m_SB.Add("\\\"");
+ }
+ else if(ch >= 32)
+ {
+ m_SB.Add(ch);
+ }
+ else switch(ch)
+ {
+ case '\b':
+ m_SB.Add("\\b");
+ break;
+ case '\f':
+ m_SB.Add("\\f");
+ break;
+ case '\n':
+ m_SB.Add("\\n");
+ break;
+ case '\r':
+ m_SB.Add("\\r");
+ break;
+ case '\t':
+ m_SB.Add("\\t");
+ break;
+ default:
+ VMA_ASSERT(0 && "Character not currently supported.");
+ break;
+ }
+ }
+}
+
+void VmaJsonWriter::ContinueString(uint32_t n)
+{
+ VMA_ASSERT(m_InsideString);
+ m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::ContinueString(uint64_t n)
+{
+ VMA_ASSERT(m_InsideString);
+ m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::ContinueString_Pointer(const void* ptr)
+{
+ VMA_ASSERT(m_InsideString);
+ m_SB.AddPointer(ptr);
+}
+
+void VmaJsonWriter::EndString(const char* pStr)
+{
+ VMA_ASSERT(m_InsideString);
+ if(pStr != VMA_NULL && pStr[0] != '\0')
+ {
+ ContinueString(pStr);
+ }
+ m_SB.Add('"');
+ m_InsideString = false;
+}
+
+void VmaJsonWriter::WriteNumber(uint32_t n)
+{
+ VMA_ASSERT(!m_InsideString);
+ BeginValue(false);
+ m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::WriteNumber(uint64_t n)
+{
+ VMA_ASSERT(!m_InsideString);
+ BeginValue(false);
+ m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::WriteBool(bool b)
+{
+ VMA_ASSERT(!m_InsideString);
+ BeginValue(false);
+ m_SB.Add(b ? "true" : "false");
+}
+
+void VmaJsonWriter::WriteNull()
+{
+ VMA_ASSERT(!m_InsideString);
+ BeginValue(false);
+ m_SB.Add("null");
+}
+
+void VmaJsonWriter::BeginValue(bool isString)
+{
+ if(!m_Stack.empty())
+ {
+ StackItem& currItem = m_Stack.back();
+ if(currItem.type == COLLECTION_TYPE_OBJECT &&
+ currItem.valueCount % 2 == 0)
+ {
+ (void) isString;
+ VMA_ASSERT(isString);
+ }
+
+ if(currItem.type == COLLECTION_TYPE_OBJECT &&
+ currItem.valueCount % 2 != 0)
+ {
+ m_SB.Add(": ");
+ }
+ else if(currItem.valueCount > 0)
+ {
+ m_SB.Add(", ");
+ WriteIndent();
+ }
+ else
+ {
+ WriteIndent();
+ }
+ ++currItem.valueCount;
+ }
+}
+
+void VmaJsonWriter::WriteIndent(bool oneLess)
+{
+ if(!m_Stack.empty() && !m_Stack.back().singleLineMode)
+ {
+ m_SB.AddNewLine();
+
+ size_t count = m_Stack.size();
+ if(count > 0 && oneLess)
+ {
+ --count;
+ }
+ for(size_t i = 0; i < count; ++i)
+ {
+ m_SB.Add(INDENT);
+ }
+ }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+
+void VmaAllocation_T::SetUserData(VmaAllocator hAllocator, void* pUserData)
+{
+ if(IsUserDataString())
+ {
+ VMA_ASSERT(pUserData == VMA_NULL || pUserData != m_pUserData);
+
+ FreeUserDataString(hAllocator);
+
+ if(pUserData != VMA_NULL)
+ {
+ const char* const newStrSrc = (char*)pUserData;
+ const size_t newStrLen = strlen(newStrSrc);
+ char* const newStrDst = vma_new_array(hAllocator, char, newStrLen + 1);
+ memcpy(newStrDst, newStrSrc, newStrLen + 1);
+ m_pUserData = newStrDst;
+ }
+ }
+ else
+ {
+ m_pUserData = pUserData;
+ }
+}
+
+void VmaAllocation_T::ChangeBlockAllocation(
+ VmaAllocator hAllocator,
+ VmaDeviceMemoryBlock* block,
+ VkDeviceSize offset)
+{
+ VMA_ASSERT(block != VMA_NULL);
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+
+ // Move mapping reference counter from old block to new block.
+ if(block != m_BlockAllocation.m_Block)
+ {
+ uint32_t mapRefCount = m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP;
+ if(IsPersistentMap())
+ ++mapRefCount;
+ m_BlockAllocation.m_Block->Unmap(hAllocator, mapRefCount);
+ block->Map(hAllocator, mapRefCount, VMA_NULL);
+ }
+
+ m_BlockAllocation.m_Block = block;
+ m_BlockAllocation.m_Offset = offset;
+}
+
+void VmaAllocation_T::ChangeSize(VkDeviceSize newSize)
+{
+ VMA_ASSERT(newSize > 0);
+ m_Size = newSize;
+}
+
+void VmaAllocation_T::ChangeOffset(VkDeviceSize newOffset)
+{
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+ m_BlockAllocation.m_Offset = newOffset;
+}
+
+VkDeviceSize VmaAllocation_T::GetOffset() const
+{
+ switch(m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_Offset;
+ case ALLOCATION_TYPE_DEDICATED:
+ return 0;
+ default:
+ VMA_ASSERT(0);
+ return 0;
+ }
+}
+
+VkDeviceMemory VmaAllocation_T::GetMemory() const
+{
+ switch(m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_Block->GetDeviceMemory();
+ case ALLOCATION_TYPE_DEDICATED:
+ return m_DedicatedAllocation.m_hMemory;
+ default:
+ VMA_ASSERT(0);
+ return VK_NULL_HANDLE;
+ }
+}
+
+uint32_t VmaAllocation_T::GetMemoryTypeIndex() const
+{
+ switch(m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_Block->GetMemoryTypeIndex();
+ case ALLOCATION_TYPE_DEDICATED:
+ return m_DedicatedAllocation.m_MemoryTypeIndex;
+ default:
+ VMA_ASSERT(0);
+ return UINT32_MAX;
+ }
+}
+
+void* VmaAllocation_T::GetMappedData() const
+{
+ switch(m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ if(m_MapCount != 0)
+ {
+ void* pBlockData = m_BlockAllocation.m_Block->GetMappedData();
+ VMA_ASSERT(pBlockData != VMA_NULL);
+ return (char*)pBlockData + m_BlockAllocation.m_Offset;
+ }
+ else
+ {
+ return VMA_NULL;
+ }
+ break;
+ case ALLOCATION_TYPE_DEDICATED:
+ VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0));
+ return m_DedicatedAllocation.m_pMappedData;
+ default:
+ VMA_ASSERT(0);
+ return VMA_NULL;
+ }
+}
+
+bool VmaAllocation_T::CanBecomeLost() const
+{
+ switch(m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_CanBecomeLost;
+ case ALLOCATION_TYPE_DEDICATED:
+ return false;
+ default:
+ VMA_ASSERT(0);
+ return false;
+ }
+}
+
+VmaPool VmaAllocation_T::GetPool() const
+{
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+ return m_BlockAllocation.m_hPool;
+}
+
+bool VmaAllocation_T::MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+ VMA_ASSERT(CanBecomeLost());
+
+ /*
+ Warning: This is a carefully designed algorithm.
+ Do not modify unless you really know what you're doing :)
+ */
+ uint32_t localLastUseFrameIndex = GetLastUseFrameIndex();
+ for(;;)
+ {
+ if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
+ {
+ VMA_ASSERT(0);
+ return false;
+ }
+ else if(localLastUseFrameIndex + frameInUseCount >= currentFrameIndex)
+ {
+ return false;
+ }
+ else // Last use time earlier than current time.
+ {
+ if(CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, VMA_FRAME_INDEX_LOST))
+ {
+ // Setting hAllocation.LastUseFrameIndex atomic to VMA_FRAME_INDEX_LOST is enough to mark it as LOST.
+ // Calling code just needs to unregister this allocation in owning VmaDeviceMemoryBlock.
+ return true;
+ }
+ }
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+// Correspond to values of enum VmaSuballocationType.
+static const char* VMA_SUBALLOCATION_TYPE_NAMES[] = {
+ "FREE",
+ "UNKNOWN",
+ "BUFFER",
+ "IMAGE_UNKNOWN",
+ "IMAGE_LINEAR",
+ "IMAGE_OPTIMAL",
+};
+
+void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const
+{
+ json.WriteString("Type");
+ json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[m_SuballocationType]);
+
+ json.WriteString("Size");
+ json.WriteNumber(m_Size);
+
+ if(m_pUserData != VMA_NULL)
+ {
+ json.WriteString("UserData");
+ if(IsUserDataString())
+ {
+ json.WriteString((const char*)m_pUserData);
+ }
+ else
+ {
+ json.BeginString();
+ json.ContinueString_Pointer(m_pUserData);
+ json.EndString();
+ }
+ }
+
+ json.WriteString("CreationFrameIndex");
+ json.WriteNumber(m_CreationFrameIndex);
+
+ json.WriteString("LastUseFrameIndex");
+ json.WriteNumber(GetLastUseFrameIndex());
+
+ if(m_BufferImageUsage != 0)
+ {
+ json.WriteString("Usage");
+ json.WriteNumber(m_BufferImageUsage);
+ }
+}
+
+#endif
+
+void VmaAllocation_T::FreeUserDataString(VmaAllocator hAllocator)
+{
+ VMA_ASSERT(IsUserDataString());
+ if(m_pUserData != VMA_NULL)
+ {
+ char* const oldStr = (char*)m_pUserData;
+ const size_t oldStrLen = strlen(oldStr);
+ vma_delete_array(hAllocator, oldStr, oldStrLen + 1);
+ m_pUserData = VMA_NULL;
+ }
+}
+
+void VmaAllocation_T::BlockAllocMap()
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);
+
+ if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F)
+ {
+ ++m_MapCount;
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Allocation mapped too many times simultaneously.");
+ }
+}
+
+void VmaAllocation_T::BlockAllocUnmap()
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);
+
+ if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0)
+ {
+ --m_MapCount;
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Unmapping allocation not previously mapped.");
+ }
+}
+
+VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppData)
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
+
+ if(m_MapCount != 0)
+ {
+ if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F)
+ {
+ VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);
+ *ppData = m_DedicatedAllocation.m_pMappedData;
+ ++m_MapCount;
+ return VK_SUCCESS;
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Dedicated allocation mapped too many times simultaneously.");
+ return VK_ERROR_MEMORY_MAP_FAILED;
+ }
+ }
+ else
+ {
+ VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)(
+ hAllocator->m_hDevice,
+ m_DedicatedAllocation.m_hMemory,
+ 0, // offset
+ VK_WHOLE_SIZE,
+ 0, // flags
+ ppData);
+ if(result == VK_SUCCESS)
+ {
+ m_DedicatedAllocation.m_pMappedData = *ppData;
+ m_MapCount = 1;
+ }
+ return result;
+ }
+}
+
+void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator)
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
+
+ if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0)
+ {
+ --m_MapCount;
+ if(m_MapCount == 0)
+ {
+ m_DedicatedAllocation.m_pMappedData = VMA_NULL;
+ (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(
+ hAllocator->m_hDevice,
+ m_DedicatedAllocation.m_hMemory);
+ }
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Unmapping dedicated allocation not previously mapped.");
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+static void VmaPrintStatInfo(VmaJsonWriter& json, const VmaStatInfo& stat)
+{
+ json.BeginObject();
+
+ json.WriteString("Blocks");
+ json.WriteNumber(stat.blockCount);
+
+ json.WriteString("Allocations");
+ json.WriteNumber(stat.allocationCount);
+
+ json.WriteString("UnusedRanges");
+ json.WriteNumber(stat.unusedRangeCount);
+
+ json.WriteString("UsedBytes");
+ json.WriteNumber(stat.usedBytes);
+
+ json.WriteString("UnusedBytes");
+ json.WriteNumber(stat.unusedBytes);
+
+ if(stat.allocationCount > 1)
+ {
+ json.WriteString("AllocationSize");
+ json.BeginObject(true);
+ json.WriteString("Min");
+ json.WriteNumber(stat.allocationSizeMin);
+ json.WriteString("Avg");
+ json.WriteNumber(stat.allocationSizeAvg);
+ json.WriteString("Max");
+ json.WriteNumber(stat.allocationSizeMax);
+ json.EndObject();
+ }
+
+ if(stat.unusedRangeCount > 1)
+ {
+ json.WriteString("UnusedRangeSize");
+ json.BeginObject(true);
+ json.WriteString("Min");
+ json.WriteNumber(stat.unusedRangeSizeMin);
+ json.WriteString("Avg");
+ json.WriteNumber(stat.unusedRangeSizeAvg);
+ json.WriteString("Max");
+ json.WriteNumber(stat.unusedRangeSizeMax);
+ json.EndObject();
+ }
+
+ json.EndObject();
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+struct VmaSuballocationItemSizeLess
+{
+ bool operator()(
+ const VmaSuballocationList::iterator lhs,
+ const VmaSuballocationList::iterator rhs) const
+ {
+ return lhs->size < rhs->size;
+ }
+ bool operator()(
+ const VmaSuballocationList::iterator lhs,
+ VkDeviceSize rhsSize) const
+ {
+ return lhs->size < rhsSize;
+ }
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata
+
+VmaBlockMetadata::VmaBlockMetadata(VmaAllocator hAllocator) :
+ m_Size(0),
+ m_pAllocationCallbacks(hAllocator->GetAllocationCallbacks())
+{
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockMetadata::PrintDetailedMap_Begin(class VmaJsonWriter& json,
+ VkDeviceSize unusedBytes,
+ size_t allocationCount,
+ size_t unusedRangeCount) const
+{
+ json.BeginObject();
+
+ json.WriteString("TotalBytes");
+ json.WriteNumber(GetSize());
+
+ json.WriteString("UnusedBytes");
+ json.WriteNumber(unusedBytes);
+
+ json.WriteString("Allocations");
+ json.WriteNumber((uint64_t)allocationCount);
+
+ json.WriteString("UnusedRanges");
+ json.WriteNumber((uint64_t)unusedRangeCount);
+
+ json.WriteString("Suballocations");
+ json.BeginArray();
+}
+
+void VmaBlockMetadata::PrintDetailedMap_Allocation(class VmaJsonWriter& json,
+ VkDeviceSize offset,
+ VmaAllocation hAllocation) const
+{
+ json.BeginObject(true);
+
+ json.WriteString("Offset");
+ json.WriteNumber(offset);
+
+ hAllocation->PrintParameters(json);
+
+ json.EndObject();
+}
+
+void VmaBlockMetadata::PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,
+ VkDeviceSize offset,
+ VkDeviceSize size) const
+{
+ json.BeginObject(true);
+
+ json.WriteString("Offset");
+ json.WriteNumber(offset);
+
+ json.WriteString("Type");
+ json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[VMA_SUBALLOCATION_TYPE_FREE]);
+
+ json.WriteString("Size");
+ json.WriteNumber(size);
+
+ json.EndObject();
+}
+
+void VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json) const
+{
+ json.EndArray();
+ json.EndObject();
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata_Generic
+
+VmaBlockMetadata_Generic::VmaBlockMetadata_Generic(VmaAllocator hAllocator) :
+ VmaBlockMetadata(hAllocator),
+ m_FreeCount(0),
+ m_SumFreeSize(0),
+ m_Suballocations(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
+ m_FreeSuballocationsBySize(VmaStlAllocator<VmaSuballocationList::iterator>(hAllocator->GetAllocationCallbacks()))
+{
+}
+
+VmaBlockMetadata_Generic::~VmaBlockMetadata_Generic()
+{
+}
+
+void VmaBlockMetadata_Generic::Init(VkDeviceSize size)
+{
+ VmaBlockMetadata::Init(size);
+
+ m_FreeCount = 1;
+ m_SumFreeSize = size;
+
+ VmaSuballocation suballoc = {};
+ suballoc.offset = 0;
+ suballoc.size = size;
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ suballoc.hAllocation = VK_NULL_HANDLE;
+
+ VMA_ASSERT(size > VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
+ m_Suballocations.push_back(suballoc);
+ VmaSuballocationList::iterator suballocItem = m_Suballocations.end();
+ --suballocItem;
+ m_FreeSuballocationsBySize.push_back(suballocItem);
+}
+
+bool VmaBlockMetadata_Generic::Validate() const
+{
+ VMA_VALIDATE(!m_Suballocations.empty());
+
+ // Expected offset of new suballocation as calculated from previous ones.
+ VkDeviceSize calculatedOffset = 0;
+ // Expected number of free suballocations as calculated from traversing their list.
+ uint32_t calculatedFreeCount = 0;
+ // Expected sum size of free suballocations as calculated from traversing their list.
+ VkDeviceSize calculatedSumFreeSize = 0;
+ // Expected number of free suballocations that should be registered in
+ // m_FreeSuballocationsBySize calculated from traversing their list.
+ size_t freeSuballocationsToRegister = 0;
+ // True if previous visited suballocation was free.
+ bool prevFree = false;
+
+ for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();
+ suballocItem != m_Suballocations.cend();
+ ++suballocItem)
+ {
+ const VmaSuballocation& subAlloc = *suballocItem;
+
+ // Actual offset of this suballocation doesn't match expected one.
+ VMA_VALIDATE(subAlloc.offset == calculatedOffset);
+
+ const bool currFree = (subAlloc.type == VMA_SUBALLOCATION_TYPE_FREE);
+ // Two adjacent free suballocations are invalid. They should be merged.
+ VMA_VALIDATE(!prevFree || !currFree);
+
+ VMA_VALIDATE(currFree == (subAlloc.hAllocation == VK_NULL_HANDLE));
+
+ if(currFree)
+ {
+ calculatedSumFreeSize += subAlloc.size;
+ ++calculatedFreeCount;
+ if(subAlloc.size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ ++freeSuballocationsToRegister;
+ }
+
+ // Margin required between allocations - every free space must be at least that large.
+#if VMA_DEBUG_MARGIN
+ VMA_VALIDATE(subAlloc.size >= VMA_DEBUG_MARGIN);
+#endif
+ }
+ else
+ {
+ VMA_VALIDATE(subAlloc.hAllocation->GetOffset() == subAlloc.offset);
+ VMA_VALIDATE(subAlloc.hAllocation->GetSize() == subAlloc.size);
+
+ // Margin required between allocations - previous allocation must be free.
+ VMA_VALIDATE(VMA_DEBUG_MARGIN == 0 || prevFree);
+ }
+
+ calculatedOffset += subAlloc.size;
+ prevFree = currFree;
+ }
+
+ // Number of free suballocations registered in m_FreeSuballocationsBySize doesn't
+ // match expected one.
+ VMA_VALIDATE(m_FreeSuballocationsBySize.size() == freeSuballocationsToRegister);
+
+ VkDeviceSize lastSize = 0;
+ for(size_t i = 0; i < m_FreeSuballocationsBySize.size(); ++i)
+ {
+ VmaSuballocationList::iterator suballocItem = m_FreeSuballocationsBySize[i];
+
+ // Only free suballocations can be registered in m_FreeSuballocationsBySize.
+ VMA_VALIDATE(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE);
+ // They must be sorted by size ascending.
+ VMA_VALIDATE(suballocItem->size >= lastSize);
+
+ lastSize = suballocItem->size;
+ }
+
+ // Check if totals match calculacted values.
+ VMA_VALIDATE(ValidateFreeSuballocationList());
+ VMA_VALIDATE(calculatedOffset == GetSize());
+ VMA_VALIDATE(calculatedSumFreeSize == m_SumFreeSize);
+ VMA_VALIDATE(calculatedFreeCount == m_FreeCount);
+
+ return true;
+}
+
+VkDeviceSize VmaBlockMetadata_Generic::GetUnusedRangeSizeMax() const
+{
+ if(!m_FreeSuballocationsBySize.empty())
+ {
+ return m_FreeSuballocationsBySize.back()->size;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+bool VmaBlockMetadata_Generic::IsEmpty() const
+{
+ return (m_Suballocations.size() == 1) && (m_FreeCount == 1);
+}
+
+void VmaBlockMetadata_Generic::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
+{
+ outInfo.blockCount = 1;
+
+ const uint32_t rangeCount = (uint32_t)m_Suballocations.size();
+ outInfo.allocationCount = rangeCount - m_FreeCount;
+ outInfo.unusedRangeCount = m_FreeCount;
+
+ outInfo.unusedBytes = m_SumFreeSize;
+ outInfo.usedBytes = GetSize() - outInfo.unusedBytes;
+
+ outInfo.allocationSizeMin = UINT64_MAX;
+ outInfo.allocationSizeMax = 0;
+ outInfo.unusedRangeSizeMin = UINT64_MAX;
+ outInfo.unusedRangeSizeMax = 0;
+
+ for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();
+ suballocItem != m_Suballocations.cend();
+ ++suballocItem)
+ {
+ const VmaSuballocation& suballoc = *suballocItem;
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+ outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, suballoc.size);
+ }
+ else
+ {
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, suballoc.size);
+ outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, suballoc.size);
+ }
+ }
+}
+
+void VmaBlockMetadata_Generic::AddPoolStats(VmaPoolStats& inoutStats) const
+{
+ const uint32_t rangeCount = (uint32_t)m_Suballocations.size();
+
+ inoutStats.size += GetSize();
+ inoutStats.unusedSize += m_SumFreeSize;
+ inoutStats.allocationCount += rangeCount - m_FreeCount;
+ inoutStats.unusedRangeCount += m_FreeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, GetUnusedRangeSizeMax());
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockMetadata_Generic::PrintDetailedMap(class VmaJsonWriter& json) const
+{
+ PrintDetailedMap_Begin(json,
+ m_SumFreeSize, // unusedBytes
+ m_Suballocations.size() - (size_t)m_FreeCount, // allocationCount
+ m_FreeCount); // unusedRangeCount
+
+ size_t i = 0;
+ for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();
+ suballocItem != m_Suballocations.cend();
+ ++suballocItem, ++i)
+ {
+ if(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ PrintDetailedMap_UnusedRange(json, suballocItem->offset, suballocItem->size);
+ }
+ else
+ {
+ PrintDetailedMap_Allocation(json, suballocItem->offset, suballocItem->hAllocation);
+ }
+ }
+
+ PrintDetailedMap_End(json);
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+bool VmaBlockMetadata_Generic::CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ VMA_ASSERT(allocSize > 0);
+ VMA_ASSERT(!upperAddress);
+ (void) upperAddress;
+ VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(pAllocationRequest != VMA_NULL);
+ VMA_HEAVY_ASSERT(Validate());
+
+ // There is not enough total free space in this block to fullfill the request: Early return.
+ if(canMakeOtherLost == false &&
+ m_SumFreeSize < allocSize + 2 * VMA_DEBUG_MARGIN)
+ {
+ return false;
+ }
+
+ // New algorithm, efficiently searching freeSuballocationsBySize.
+ const size_t freeSuballocCount = m_FreeSuballocationsBySize.size();
+ if(freeSuballocCount > 0)
+ {
+ if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+ {
+ // Find first free suballocation with size not less than allocSize + 2 * VMA_DEBUG_MARGIN.
+ VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(
+ m_FreeSuballocationsBySize.data(),
+ m_FreeSuballocationsBySize.data() + freeSuballocCount,
+ allocSize + 2 * VMA_DEBUG_MARGIN,
+ VmaSuballocationItemSizeLess());
+ size_t index = it - m_FreeSuballocationsBySize.data();
+ for(; index < freeSuballocCount; ++index)
+ {
+ if(CheckAllocation(
+ currentFrameIndex,
+ frameInUseCount,
+ bufferImageGranularity,
+ allocSize,
+ allocAlignment,
+ allocType,
+ m_FreeSuballocationsBySize[index],
+ false, // canMakeOtherLost
+ &pAllocationRequest->offset,
+ &pAllocationRequest->itemsToMakeLostCount,
+ &pAllocationRequest->sumFreeSize,
+ &pAllocationRequest->sumItemSize))
+ {
+ pAllocationRequest->item = m_FreeSuballocationsBySize[index];
+ return true;
+ }
+ }
+ }
+ else if(strategy == VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET)
+ {
+ for(VmaSuballocationList::iterator it = m_Suballocations.begin();
+ it != m_Suballocations.end();
+ ++it)
+ {
+ if(it->type == VMA_SUBALLOCATION_TYPE_FREE && CheckAllocation(
+ currentFrameIndex,
+ frameInUseCount,
+ bufferImageGranularity,
+ allocSize,
+ allocAlignment,
+ allocType,
+ it,
+ false, // canMakeOtherLost
+ &pAllocationRequest->offset,
+ &pAllocationRequest->itemsToMakeLostCount,
+ &pAllocationRequest->sumFreeSize,
+ &pAllocationRequest->sumItemSize))
+ {
+ pAllocationRequest->item = it;
+ return true;
+ }
+ }
+ }
+ else // WORST_FIT, FIRST_FIT
+ {
+ // Search staring from biggest suballocations.
+ for(size_t index = freeSuballocCount; index--; )
+ {
+ if(CheckAllocation(
+ currentFrameIndex,
+ frameInUseCount,
+ bufferImageGranularity,
+ allocSize,
+ allocAlignment,
+ allocType,
+ m_FreeSuballocationsBySize[index],
+ false, // canMakeOtherLost
+ &pAllocationRequest->offset,
+ &pAllocationRequest->itemsToMakeLostCount,
+ &pAllocationRequest->sumFreeSize,
+ &pAllocationRequest->sumItemSize))
+ {
+ pAllocationRequest->item = m_FreeSuballocationsBySize[index];
+ return true;
+ }
+ }
+ }
+ }
+
+ if(canMakeOtherLost)
+ {
+ // Brute-force algorithm. TODO: Come up with something better.
+
+ pAllocationRequest->sumFreeSize = VK_WHOLE_SIZE;
+ pAllocationRequest->sumItemSize = VK_WHOLE_SIZE;
+
+ VmaAllocationRequest tmpAllocRequest = {};
+ for(VmaSuballocationList::iterator suballocIt = m_Suballocations.begin();
+ suballocIt != m_Suballocations.end();
+ ++suballocIt)
+ {
+ if(suballocIt->type == VMA_SUBALLOCATION_TYPE_FREE ||
+ suballocIt->hAllocation->CanBecomeLost())
+ {
+ if(CheckAllocation(
+ currentFrameIndex,
+ frameInUseCount,
+ bufferImageGranularity,
+ allocSize,
+ allocAlignment,
+ allocType,
+ suballocIt,
+ canMakeOtherLost,
+ &tmpAllocRequest.offset,
+ &tmpAllocRequest.itemsToMakeLostCount,
+ &tmpAllocRequest.sumFreeSize,
+ &tmpAllocRequest.sumItemSize))
+ {
+ tmpAllocRequest.item = suballocIt;
+
+ if(tmpAllocRequest.CalcCost() < pAllocationRequest->CalcCost() ||
+ strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
+ {
+ *pAllocationRequest = tmpAllocRequest;
+ }
+ }
+ }
+ }
+
+ if(pAllocationRequest->sumItemSize != VK_WHOLE_SIZE)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool VmaBlockMetadata_Generic::MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ while(pAllocationRequest->itemsToMakeLostCount > 0)
+ {
+ if(pAllocationRequest->item->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ ++pAllocationRequest->item;
+ }
+ VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end());
+ VMA_ASSERT(pAllocationRequest->item->hAllocation != VK_NULL_HANDLE);
+ VMA_ASSERT(pAllocationRequest->item->hAllocation->CanBecomeLost());
+ if(pAllocationRequest->item->hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ {
+ pAllocationRequest->item = FreeSuballocation(pAllocationRequest->item);
+ --pAllocationRequest->itemsToMakeLostCount;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ VMA_HEAVY_ASSERT(Validate());
+ VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end());
+ VMA_ASSERT(pAllocationRequest->item->type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ return true;
+}
+
+uint32_t VmaBlockMetadata_Generic::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+ uint32_t lostAllocationCount = 0;
+ for(VmaSuballocationList::iterator it = m_Suballocations.begin();
+ it != m_Suballocations.end();
+ ++it)
+ {
+ if(it->type != VMA_SUBALLOCATION_TYPE_FREE &&
+ it->hAllocation->CanBecomeLost() &&
+ it->hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ {
+ it = FreeSuballocation(it);
+ ++lostAllocationCount;
+ }
+ }
+ return lostAllocationCount;
+}
+
+VkResult VmaBlockMetadata_Generic::CheckCorruption(const void* pBlockData)
+{
+ for(VmaSuballocationList::iterator it = m_Suballocations.begin();
+ it != m_Suballocations.end();
+ ++it)
+ {
+ if(it->type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ if(!VmaValidateMagicValue(pBlockData, it->offset - VMA_DEBUG_MARGIN))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ if(!VmaValidateMagicValue(pBlockData, it->offset + it->size))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaBlockMetadata_Generic::Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ bool upperAddress,
+ VmaAllocation hAllocation)
+{
+ VMA_ASSERT(!upperAddress);
+ (void) upperAddress;
+ VMA_ASSERT(request.item != m_Suballocations.end());
+ VmaSuballocation& suballoc = *request.item;
+ // Given suballocation is a free block.
+ VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+ // Given offset is inside this suballocation.
+ VMA_ASSERT(request.offset >= suballoc.offset);
+ const VkDeviceSize paddingBegin = request.offset - suballoc.offset;
+ VMA_ASSERT(suballoc.size >= paddingBegin + allocSize);
+ const VkDeviceSize paddingEnd = suballoc.size - paddingBegin - allocSize;
+
+ // Unregister this free suballocation from m_FreeSuballocationsBySize and update
+ // it to become used.
+ UnregisterFreeSuballocation(request.item);
+
+ suballoc.offset = request.offset;
+ suballoc.size = allocSize;
+ suballoc.type = type;
+ suballoc.hAllocation = hAllocation;
+
+ // If there are any free bytes remaining at the end, insert new free suballocation after current one.
+ if(paddingEnd)
+ {
+ VmaSuballocation paddingSuballoc = {};
+ paddingSuballoc.offset = request.offset + allocSize;
+ paddingSuballoc.size = paddingEnd;
+ paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ VmaSuballocationList::iterator next = request.item;
+ ++next;
+ const VmaSuballocationList::iterator paddingEndItem =
+ m_Suballocations.insert(next, paddingSuballoc);
+ RegisterFreeSuballocation(paddingEndItem);
+ }
+
+ // If there are any free bytes remaining at the beginning, insert new free suballocation before current one.
+ if(paddingBegin)
+ {
+ VmaSuballocation paddingSuballoc = {};
+ paddingSuballoc.offset = request.offset - paddingBegin;
+ paddingSuballoc.size = paddingBegin;
+ paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ const VmaSuballocationList::iterator paddingBeginItem =
+ m_Suballocations.insert(request.item, paddingSuballoc);
+ RegisterFreeSuballocation(paddingBeginItem);
+ }
+
+ // Update totals.
+ m_FreeCount = m_FreeCount - 1;
+ if(paddingBegin > 0)
+ {
+ ++m_FreeCount;
+ }
+ if(paddingEnd > 0)
+ {
+ ++m_FreeCount;
+ }
+ m_SumFreeSize -= allocSize;
+}
+
+void VmaBlockMetadata_Generic::Free(const VmaAllocation allocation)
+{
+ for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
+ suballocItem != m_Suballocations.end();
+ ++suballocItem)
+ {
+ VmaSuballocation& suballoc = *suballocItem;
+ if(suballoc.hAllocation == allocation)
+ {
+ FreeSuballocation(suballocItem);
+ VMA_HEAVY_ASSERT(Validate());
+ return;
+ }
+ }
+ VMA_ASSERT(0 && "Not found!");
+}
+
+void VmaBlockMetadata_Generic::FreeAtOffset(VkDeviceSize offset)
+{
+ for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
+ suballocItem != m_Suballocations.end();
+ ++suballocItem)
+ {
+ VmaSuballocation& suballoc = *suballocItem;
+ if(suballoc.offset == offset)
+ {
+ FreeSuballocation(suballocItem);
+ return;
+ }
+ }
+ VMA_ASSERT(0 && "Not found!");
+}
+
+bool VmaBlockMetadata_Generic::ResizeAllocation(const VmaAllocation alloc, VkDeviceSize newSize)
+{
+ typedef VmaSuballocationList::iterator iter_type;
+ for(iter_type suballocItem = m_Suballocations.begin();
+ suballocItem != m_Suballocations.end();
+ ++suballocItem)
+ {
+ VmaSuballocation& suballoc = *suballocItem;
+ if(suballoc.hAllocation == alloc)
+ {
+ iter_type nextItem = suballocItem;
+ ++nextItem;
+
+ // Should have been ensured on higher level.
+ VMA_ASSERT(newSize != alloc->GetSize() && newSize > 0);
+
+ // Shrinking.
+ if(newSize < alloc->GetSize())
+ {
+ const VkDeviceSize sizeDiff = suballoc.size - newSize;
+
+ // There is next item.
+ if(nextItem != m_Suballocations.end())
+ {
+ // Next item is free.
+ if(nextItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ // Grow this next item backward.
+ UnregisterFreeSuballocation(nextItem);
+ nextItem->offset -= sizeDiff;
+ nextItem->size += sizeDiff;
+ RegisterFreeSuballocation(nextItem);
+ }
+ // Next item is not free.
+ else
+ {
+ // Create free item after current one.
+ VmaSuballocation newFreeSuballoc;
+ newFreeSuballoc.hAllocation = VK_NULL_HANDLE;
+ newFreeSuballoc.offset = suballoc.offset + newSize;
+ newFreeSuballoc.size = sizeDiff;
+ newFreeSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ iter_type newFreeSuballocIt = m_Suballocations.insert(nextItem, newFreeSuballoc);
+ RegisterFreeSuballocation(newFreeSuballocIt);
+
+ ++m_FreeCount;
+ }
+ }
+ // This is the last item.
+ else
+ {
+ // Create free item at the end.
+ VmaSuballocation newFreeSuballoc;
+ newFreeSuballoc.hAllocation = VK_NULL_HANDLE;
+ newFreeSuballoc.offset = suballoc.offset + newSize;
+ newFreeSuballoc.size = sizeDiff;
+ newFreeSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ m_Suballocations.push_back(newFreeSuballoc);
+
+ iter_type newFreeSuballocIt = m_Suballocations.end();
+ RegisterFreeSuballocation(--newFreeSuballocIt);
+
+ ++m_FreeCount;
+ }
+
+ suballoc.size = newSize;
+ m_SumFreeSize += sizeDiff;
+ }
+ // Growing.
+ else
+ {
+ const VkDeviceSize sizeDiff = newSize - suballoc.size;
+
+ // There is next item.
+ if(nextItem != m_Suballocations.end())
+ {
+ // Next item is free.
+ if(nextItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ // There is not enough free space, including margin.
+ if(nextItem->size < sizeDiff + VMA_DEBUG_MARGIN)
+ {
+ return false;
+ }
+
+ // There is more free space than required.
+ if(nextItem->size > sizeDiff)
+ {
+ // Move and shrink this next item.
+ UnregisterFreeSuballocation(nextItem);
+ nextItem->offset += sizeDiff;
+ nextItem->size -= sizeDiff;
+ RegisterFreeSuballocation(nextItem);
+ }
+ // There is exactly the amount of free space required.
+ else
+ {
+ // Remove this next free item.
+ UnregisterFreeSuballocation(nextItem);
+ m_Suballocations.erase(nextItem);
+ --m_FreeCount;
+ }
+ }
+ // Next item is not free - there is no space to grow.
+ else
+ {
+ return false;
+ }
+ }
+ // This is the last item - there is no space to grow.
+ else
+ {
+ return false;
+ }
+
+ suballoc.size = newSize;
+ m_SumFreeSize -= sizeDiff;
+ }
+
+ // We cannot call Validate() here because alloc object is updated to new size outside of this call.
+ return true;
+ }
+ }
+ VMA_ASSERT(0 && "Not found!");
+ return false;
+}
+
+bool VmaBlockMetadata_Generic::ValidateFreeSuballocationList() const
+{
+ VkDeviceSize lastSize = 0;
+ for(size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i)
+ {
+ const VmaSuballocationList::iterator it = m_FreeSuballocationsBySize[i];
+
+ VMA_VALIDATE(it->type == VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_VALIDATE(it->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
+ VMA_VALIDATE(it->size >= lastSize);
+ lastSize = it->size;
+ }
+ return true;
+}
+
+bool VmaBlockMetadata_Generic::CheckAllocation(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ VmaSuballocationList::const_iterator suballocItem,
+ bool canMakeOtherLost,
+ VkDeviceSize* pOffset,
+ size_t* itemsToMakeLostCount,
+ VkDeviceSize* pSumFreeSize,
+ VkDeviceSize* pSumItemSize) const
+{
+ VMA_ASSERT(allocSize > 0);
+ VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(suballocItem != m_Suballocations.cend());
+ VMA_ASSERT(pOffset != VMA_NULL);
+
+ *itemsToMakeLostCount = 0;
+ *pSumFreeSize = 0;
+ *pSumItemSize = 0;
+
+ if(canMakeOtherLost)
+ {
+ if(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ *pSumFreeSize = suballocItem->size;
+ }
+ else
+ {
+ if(suballocItem->hAllocation->CanBecomeLost() &&
+ suballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+ {
+ ++*itemsToMakeLostCount;
+ *pSumItemSize = suballocItem->size;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Remaining size is too small for this request: Early return.
+ if(GetSize() - suballocItem->offset < allocSize)
+ {
+ return false;
+ }
+
+ // Start from offset equal to beginning of this suballocation.
+ *pOffset = suballocItem->offset;
+
+ // Apply VMA_DEBUG_MARGIN at the beginning.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
+ *pOffset += VMA_DEBUG_MARGIN;
+ }
+
+ // Apply alignment.
+ *pOffset = VmaAlignUp(*pOffset, allocAlignment);
+
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if(bufferImageGranularity > 1)
+ {
+ bool bufferImageGranularityConflict = false;
+ VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
+ while(prevSuballocItem != m_Suballocations.cbegin())
+ {
+ --prevSuballocItem;
+ const VmaSuballocation& prevSuballoc = *prevSuballocItem;
+ if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
+ }
+ else
+ // Already on previous page.
+ break;
+ }
+ if(bufferImageGranularityConflict)
+ {
+ *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity);
+ }
+ }
+
+ // Now that we have final *pOffset, check if we are past suballocItem.
+ // If yes, return false - this function should be called for another suballocItem as starting point.
+ if(*pOffset >= suballocItem->offset + suballocItem->size)
+ {
+ return false;
+ }
+
+ // Calculate padding at the beginning based on current offset.
+ const VkDeviceSize paddingBegin = *pOffset - suballocItem->offset;
+
+ // Calculate required margin at the end.
+ const VkDeviceSize requiredEndMargin = VMA_DEBUG_MARGIN;
+
+ const VkDeviceSize totalSize = paddingBegin + allocSize + requiredEndMargin;
+ // Another early return check.
+ if(suballocItem->offset + totalSize > GetSize())
+ {
+ return false;
+ }
+
+ // Advance lastSuballocItem until desired size is reached.
+ // Update itemsToMakeLostCount.
+ VmaSuballocationList::const_iterator lastSuballocItem = suballocItem;
+ if(totalSize > suballocItem->size)
+ {
+ VkDeviceSize remainingSize = totalSize - suballocItem->size;
+ while(remainingSize > 0)
+ {
+ ++lastSuballocItem;
+ if(lastSuballocItem == m_Suballocations.cend())
+ {
+ return false;
+ }
+ if(lastSuballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ *pSumFreeSize += lastSuballocItem->size;
+ }
+ else
+ {
+ VMA_ASSERT(lastSuballocItem->hAllocation != VK_NULL_HANDLE);
+ if(lastSuballocItem->hAllocation->CanBecomeLost() &&
+ lastSuballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+ {
+ ++*itemsToMakeLostCount;
+ *pSumItemSize += lastSuballocItem->size;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ remainingSize = (lastSuballocItem->size < remainingSize) ?
+ remainingSize - lastSuballocItem->size : 0;
+ }
+ }
+
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, we must mark more allocations lost or fail.
+ if(bufferImageGranularity > 1)
+ {
+ VmaSuballocationList::const_iterator nextSuballocItem = lastSuballocItem;
+ ++nextSuballocItem;
+ while(nextSuballocItem != m_Suballocations.cend())
+ {
+ const VmaSuballocation& nextSuballoc = *nextSuballocItem;
+ if(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+ {
+ VMA_ASSERT(nextSuballoc.hAllocation != VK_NULL_HANDLE);
+ if(nextSuballoc.hAllocation->CanBecomeLost() &&
+ nextSuballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+ {
+ ++*itemsToMakeLostCount;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
+ ++nextSuballocItem;
+ }
+ }
+ }
+ else
+ {
+ const VmaSuballocation& suballoc = *suballocItem;
+ VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ *pSumFreeSize = suballoc.size;
+
+ // Size of this suballocation is too small for this request: Early return.
+ if(suballoc.size < allocSize)
+ {
+ return false;
+ }
+
+ // Start from offset equal to beginning of this suballocation.
+ *pOffset = suballoc.offset;
+
+ // Apply VMA_DEBUG_MARGIN at the beginning.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
+ *pOffset += VMA_DEBUG_MARGIN;
+ }
+
+ // Apply alignment.
+ *pOffset = VmaAlignUp(*pOffset, allocAlignment);
+
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if(bufferImageGranularity > 1)
+ {
+ bool bufferImageGranularityConflict = false;
+ VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
+ while(prevSuballocItem != m_Suballocations.cbegin())
+ {
+ --prevSuballocItem;
+ const VmaSuballocation& prevSuballoc = *prevSuballocItem;
+ if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
+ }
+ else
+ // Already on previous page.
+ break;
+ }
+ if(bufferImageGranularityConflict)
+ {
+ *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity);
+ }
+ }
+
+ // Calculate padding at the beginning based on current offset.
+ const VkDeviceSize paddingBegin = *pOffset - suballoc.offset;
+
+ // Calculate required margin at the end.
+ const VkDeviceSize requiredEndMargin = VMA_DEBUG_MARGIN;
+
+ // Fail if requested size plus margin before and after is bigger than size of this suballocation.
+ if(paddingBegin + allocSize + requiredEndMargin > suballoc.size)
+ {
+ return false;
+ }
+
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, allocation cannot be made here.
+ if(bufferImageGranularity > 1)
+ {
+ VmaSuballocationList::const_iterator nextSuballocItem = suballocItem;
+ ++nextSuballocItem;
+ while(nextSuballocItem != m_Suballocations.cend())
+ {
+ const VmaSuballocation& nextSuballoc = *nextSuballocItem;
+ if(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
+ ++nextSuballocItem;
+ }
+ }
+ }
+
+ // All tests passed: Success. pOffset is already filled.
+ return true;
+}
+
+void VmaBlockMetadata_Generic::MergeFreeWithNext(VmaSuballocationList::iterator item)
+{
+ VMA_ASSERT(item != m_Suballocations.end());
+ VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ VmaSuballocationList::iterator nextItem = item;
+ ++nextItem;
+ VMA_ASSERT(nextItem != m_Suballocations.end());
+ VMA_ASSERT(nextItem->type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ item->size += nextItem->size;
+ --m_FreeCount;
+ m_Suballocations.erase(nextItem);
+}
+
+VmaSuballocationList::iterator VmaBlockMetadata_Generic::FreeSuballocation(VmaSuballocationList::iterator suballocItem)
+{
+ // Change this suballocation to be marked as free.
+ VmaSuballocation& suballoc = *suballocItem;
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ suballoc.hAllocation = VK_NULL_HANDLE;
+
+ // Update totals.
+ ++m_FreeCount;
+ m_SumFreeSize += suballoc.size;
+
+ // Merge with previous and/or next suballocation if it's also free.
+ bool mergeWithNext = false;
+ bool mergeWithPrev = false;
+
+ VmaSuballocationList::iterator nextItem = suballocItem;
+ ++nextItem;
+ if((nextItem != m_Suballocations.end()) && (nextItem->type == VMA_SUBALLOCATION_TYPE_FREE))
+ {
+ mergeWithNext = true;
+ }
+
+ VmaSuballocationList::iterator prevItem = suballocItem;
+ if(suballocItem != m_Suballocations.begin())
+ {
+ --prevItem;
+ if(prevItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ mergeWithPrev = true;
+ }
+ }
+
+ if(mergeWithNext)
+ {
+ UnregisterFreeSuballocation(nextItem);
+ MergeFreeWithNext(suballocItem);
+ }
+
+ if(mergeWithPrev)
+ {
+ UnregisterFreeSuballocation(prevItem);
+ MergeFreeWithNext(prevItem);
+ RegisterFreeSuballocation(prevItem);
+ return prevItem;
+ }
+ else
+ {
+ RegisterFreeSuballocation(suballocItem);
+ return suballocItem;
+ }
+}
+
+void VmaBlockMetadata_Generic::RegisterFreeSuballocation(VmaSuballocationList::iterator item)
+{
+ VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(item->size > 0);
+
+ // You may want to enable this validation at the beginning or at the end of
+ // this function, depending on what do you want to check.
+ VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+
+ if(item->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ if(m_FreeSuballocationsBySize.empty())
+ {
+ m_FreeSuballocationsBySize.push_back(item);
+ }
+ else
+ {
+ VmaVectorInsertSorted<VmaSuballocationItemSizeLess>(m_FreeSuballocationsBySize, item);
+ }
+ }
+
+ //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+}
+
+
+void VmaBlockMetadata_Generic::UnregisterFreeSuballocation(VmaSuballocationList::iterator item)
+{
+ VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(item->size > 0);
+
+ // You may want to enable this validation at the beginning or at the end of
+ // this function, depending on what do you want to check.
+ VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+
+ if(item->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(
+ m_FreeSuballocationsBySize.data(),
+ m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(),
+ item,
+ VmaSuballocationItemSizeLess());
+ for(size_t index = it - m_FreeSuballocationsBySize.data();
+ index < m_FreeSuballocationsBySize.size();
+ ++index)
+ {
+ if(m_FreeSuballocationsBySize[index] == item)
+ {
+ VmaVectorRemove(m_FreeSuballocationsBySize, index);
+ return;
+ }
+ VMA_ASSERT((m_FreeSuballocationsBySize[index]->size == item->size) && "Not found.");
+ }
+ VMA_ASSERT(0 && "Not found.");
+ }
+
+ //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+}
+
+bool VmaBlockMetadata_Generic::IsBufferImageGranularityConflictPossible(
+ VkDeviceSize bufferImageGranularity,
+ VmaSuballocationType& inOutPrevSuballocType) const
+{
+ if(bufferImageGranularity == 1 || IsEmpty())
+ {
+ return false;
+ }
+
+ VkDeviceSize minAlignment = VK_WHOLE_SIZE;
+ bool typeConflictFound = false;
+ for(VmaSuballocationList::const_iterator it = m_Suballocations.cbegin();
+ it != m_Suballocations.cend();
+ ++it)
+ {
+ const VmaSuballocationType suballocType = it->type;
+ if(suballocType != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ minAlignment = VMA_MIN(minAlignment, it->hAllocation->GetAlignment());
+ if(VmaIsBufferImageGranularityConflict(inOutPrevSuballocType, suballocType))
+ {
+ typeConflictFound = true;
+ }
+ inOutPrevSuballocType = suballocType;
+ }
+ }
+
+ return typeConflictFound || minAlignment >= bufferImageGranularity;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata_Linear
+
+VmaBlockMetadata_Linear::VmaBlockMetadata_Linear(VmaAllocator hAllocator) :
+ VmaBlockMetadata(hAllocator),
+ m_SumFreeSize(0),
+ m_Suballocations0(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
+ m_Suballocations1(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
+ m_1stVectorIndex(0),
+ m_2ndVectorMode(SECOND_VECTOR_EMPTY),
+ m_1stNullItemsBeginCount(0),
+ m_1stNullItemsMiddleCount(0),
+ m_2ndNullItemsCount(0)
+{
+}
+
+VmaBlockMetadata_Linear::~VmaBlockMetadata_Linear()
+{
+}
+
+void VmaBlockMetadata_Linear::Init(VkDeviceSize size)
+{
+ VmaBlockMetadata::Init(size);
+ m_SumFreeSize = size;
+}
+
+bool VmaBlockMetadata_Linear::Validate() const
+{
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ VMA_VALIDATE(suballocations2nd.empty() == (m_2ndVectorMode == SECOND_VECTOR_EMPTY));
+ VMA_VALIDATE(!suballocations1st.empty() ||
+ suballocations2nd.empty() ||
+ m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER);
+
+ if(!suballocations1st.empty())
+ {
+ // Null item at the beginning should be accounted into m_1stNullItemsBeginCount.
+ VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].hAllocation != VK_NULL_HANDLE);
+ // Null item at the end should be just pop_back().
+ VMA_VALIDATE(suballocations1st.back().hAllocation != VK_NULL_HANDLE);
+ }
+ if(!suballocations2nd.empty())
+ {
+ // Null item at the end should be just pop_back().
+ VMA_VALIDATE(suballocations2nd.back().hAllocation != VK_NULL_HANDLE);
+ }
+
+ VMA_VALIDATE(m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount <= suballocations1st.size());
+ VMA_VALIDATE(m_2ndNullItemsCount <= suballocations2nd.size());
+
+ VkDeviceSize sumUsedSize = 0;
+ const size_t suballoc1stCount = suballocations1st.size();
+ VkDeviceSize offset = VMA_DEBUG_MARGIN;
+
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ const size_t suballoc2ndCount = suballocations2nd.size();
+ size_t nullItem2ndCount = 0;
+ for(size_t i = 0; i < suballoc2ndCount; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[i];
+ const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+ VMA_VALIDATE(suballoc.offset >= offset);
+
+ if(!currFree)
+ {
+ VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
+ VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+ sumUsedSize += suballoc.size;
+ }
+ else
+ {
+ ++nullItem2ndCount;
+ }
+
+ offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+ }
+
+ VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);
+ }
+
+ for(size_t i = 0; i < m_1stNullItemsBeginCount; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[i];
+ VMA_VALIDATE(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE &&
+ suballoc.hAllocation == VK_NULL_HANDLE);
+ }
+
+ size_t nullItem1stCount = m_1stNullItemsBeginCount;
+
+ for(size_t i = m_1stNullItemsBeginCount; i < suballoc1stCount; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[i];
+ const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+ VMA_VALIDATE(suballoc.offset >= offset);
+ VMA_VALIDATE(i >= m_1stNullItemsBeginCount || currFree);
+
+ if(!currFree)
+ {
+ VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
+ VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+ sumUsedSize += suballoc.size;
+ }
+ else
+ {
+ ++nullItem1stCount;
+ }
+
+ offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+ }
+ VMA_VALIDATE(nullItem1stCount == m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount);
+
+ if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ const size_t suballoc2ndCount = suballocations2nd.size();
+ size_t nullItem2ndCount = 0;
+ for(size_t i = suballoc2ndCount; i--; )
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[i];
+ const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+ VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+ VMA_VALIDATE(suballoc.offset >= offset);
+
+ if(!currFree)
+ {
+ VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
+ VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+ sumUsedSize += suballoc.size;
+ }
+ else
+ {
+ ++nullItem2ndCount;
+ }
+
+ offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+ }
+
+ VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);
+ }
+
+ VMA_VALIDATE(offset <= GetSize());
+ VMA_VALIDATE(m_SumFreeSize == GetSize() - sumUsedSize);
+
+ return true;
+}
+
+size_t VmaBlockMetadata_Linear::GetAllocationCount() const
+{
+ return AccessSuballocations1st().size() - (m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount) +
+ AccessSuballocations2nd().size() - m_2ndNullItemsCount;
+}
+
+VkDeviceSize VmaBlockMetadata_Linear::GetUnusedRangeSizeMax() const
+{
+ const VkDeviceSize size = GetSize();
+
+ /*
+ We don't consider gaps inside allocation vectors with freed allocations because
+ they are not suitable for reuse in linear allocator. We consider only space that
+ is available for new allocations.
+ */
+ if(IsEmpty())
+ {
+ return size;
+ }
+
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+
+ switch(m_2ndVectorMode)
+ {
+ case SECOND_VECTOR_EMPTY:
+ /*
+ Available space is after end of 1st, as well as before beginning of 1st (which
+ whould make it a ring buffer).
+ */
+ {
+ const size_t suballocations1stCount = suballocations1st.size();
+ VMA_ASSERT(suballocations1stCount > m_1stNullItemsBeginCount);
+ const VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];
+ const VmaSuballocation& lastSuballoc = suballocations1st[suballocations1stCount - 1];
+ return VMA_MAX(
+ firstSuballoc.offset,
+ size - (lastSuballoc.offset + lastSuballoc.size));
+ }
+ break;
+
+ case SECOND_VECTOR_RING_BUFFER:
+ /*
+ Available space is only between end of 2nd and beginning of 1st.
+ */
+ {
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ const VmaSuballocation& lastSuballoc2nd = suballocations2nd.back();
+ const VmaSuballocation& firstSuballoc1st = suballocations1st[m_1stNullItemsBeginCount];
+ return firstSuballoc1st.offset - (lastSuballoc2nd.offset + lastSuballoc2nd.size);
+ }
+ break;
+
+ case SECOND_VECTOR_DOUBLE_STACK:
+ /*
+ Available space is only between end of 1st and top of 2nd.
+ */
+ {
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ const VmaSuballocation& topSuballoc2nd = suballocations2nd.back();
+ const VmaSuballocation& lastSuballoc1st = suballocations1st.back();
+ return topSuballoc2nd.offset - (lastSuballoc1st.offset + lastSuballoc1st.size);
+ }
+ break;
+
+ default:
+ VMA_ASSERT(0);
+ return 0;
+ }
+}
+
+void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
+{
+ const VkDeviceSize size = GetSize();
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ const size_t suballoc1stCount = suballocations1st.size();
+ const size_t suballoc2ndCount = suballocations2nd.size();
+
+ outInfo.blockCount = 1;
+ outInfo.allocationCount = (uint32_t)GetAllocationCount();
+ outInfo.unusedRangeCount = 0;
+ outInfo.usedBytes = 0;
+ outInfo.allocationSizeMin = UINT64_MAX;
+ outInfo.allocationSizeMax = 0;
+ outInfo.unusedRangeSizeMin = UINT64_MAX;
+ outInfo.unusedRangeSizeMax = 0;
+
+ VkDeviceSize lastOffset = 0;
+
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+ size_t nextAlloc2ndIndex = 0;
+ while(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex < suballoc2ndCount)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ outInfo.usedBytes += suballoc.size;
+ outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+ outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+ if(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace2ndTo1stEnd;
+ }
+ }
+ }
+
+ size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
+ const VkDeviceSize freeSpace1stTo2ndEnd =
+ m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
+ while(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc1stIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc1stIndex < suballoc1stCount)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ outInfo.usedBytes += suballoc.size;
+ outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+ outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc1stIndex;
+ }
+ // We are at the end.
+ else
+ {
+ // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+ if(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace1stTo2ndEnd;
+ }
+ }
+
+ if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+ while(lastOffset < size)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ --nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex != SIZE_MAX)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ outInfo.usedBytes += suballoc.size;
+ outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+ outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ --nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ // There is free space from lastOffset to size.
+ if(lastOffset < size)
+ {
+ const VkDeviceSize unusedRangeSize = size - lastOffset;
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = size;
+ }
+ }
+ }
+
+ outInfo.unusedBytes = size - outInfo.usedBytes;
+}
+
+void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const
+{
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ const VkDeviceSize size = GetSize();
+ const size_t suballoc1stCount = suballocations1st.size();
+ const size_t suballoc2ndCount = suballocations2nd.size();
+
+ inoutStats.size += size;
+
+ VkDeviceSize lastOffset = 0;
+
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+ size_t nextAlloc2ndIndex = m_1stNullItemsBeginCount;
+ while(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex < suballoc2ndCount)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++inoutStats.allocationCount;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+ const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace2ndTo1stEnd;
+ }
+ }
+ }
+
+ size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
+ const VkDeviceSize freeSpace1stTo2ndEnd =
+ m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
+ while(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc1stIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc1stIndex < suballoc1stCount)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++inoutStats.allocationCount;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc1stIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+ const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace1stTo2ndEnd;
+ }
+ }
+
+ if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+ while(lastOffset < size)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ --nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex != SIZE_MAX)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++inoutStats.allocationCount;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ --nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < size)
+ {
+ // There is free space from lastOffset to size.
+ const VkDeviceSize unusedRangeSize = size - lastOffset;
+ inoutStats.unusedSize += unusedRangeSize;
+ ++inoutStats.unusedRangeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = size;
+ }
+ }
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
+{
+ const VkDeviceSize size = GetSize();
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ const size_t suballoc1stCount = suballocations1st.size();
+ const size_t suballoc2ndCount = suballocations2nd.size();
+
+ // FIRST PASS
+
+ size_t unusedRangeCount = 0;
+ VkDeviceSize usedBytes = 0;
+
+ VkDeviceSize lastOffset = 0;
+
+ size_t alloc2ndCount = 0;
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+ size_t nextAlloc2ndIndex = 0;
+ while(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex < suballoc2ndCount)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ ++unusedRangeCount;
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++alloc2ndCount;
+ usedBytes += suballoc.size;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+ ++unusedRangeCount;
+ }
+
+ // End of loop.
+ lastOffset = freeSpace2ndTo1stEnd;
+ }
+ }
+ }
+
+ size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
+ size_t alloc1stCount = 0;
+ const VkDeviceSize freeSpace1stTo2ndEnd =
+ m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
+ while(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc1stIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc1stIndex < suballoc1stCount)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ ++unusedRangeCount;
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++alloc1stCount;
+ usedBytes += suballoc.size;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc1stIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < size)
+ {
+ // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+ ++unusedRangeCount;
+ }
+
+ // End of loop.
+ lastOffset = freeSpace1stTo2ndEnd;
+ }
+ }
+
+ if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+ while(lastOffset < size)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ --nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex != SIZE_MAX)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ ++unusedRangeCount;
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ ++alloc2ndCount;
+ usedBytes += suballoc.size;
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ --nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < size)
+ {
+ // There is free space from lastOffset to size.
+ ++unusedRangeCount;
+ }
+
+ // End of loop.
+ lastOffset = size;
+ }
+ }
+ }
+
+ const VkDeviceSize unusedBytes = size - usedBytes;
+ PrintDetailedMap_Begin(json, unusedBytes, alloc1stCount + alloc2ndCount, unusedRangeCount);
+
+ // SECOND PASS
+ lastOffset = 0;
+
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+ size_t nextAlloc2ndIndex = 0;
+ while(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex < suballoc2ndCount)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < freeSpace2ndTo1stEnd)
+ {
+ // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+ const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace2ndTo1stEnd;
+ }
+ }
+ }
+
+ nextAlloc1stIndex = m_1stNullItemsBeginCount;
+ while(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // Find next non-null allocation or move nextAllocIndex to the end.
+ while(nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++nextAlloc1stIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc1stIndex < suballoc1stCount)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ ++nextAlloc1stIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < freeSpace1stTo2ndEnd)
+ {
+ // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+ const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = freeSpace1stTo2ndEnd;
+ }
+ }
+
+ if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+ while(lastOffset < size)
+ {
+ // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+ while(nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ --nextAlloc2ndIndex;
+ }
+
+ // Found non-null allocation.
+ if(nextAlloc2ndIndex != SIZE_MAX)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+
+ // 1. Process free space before this allocation.
+ if(lastOffset < suballoc.offset)
+ {
+ // There is free space from lastOffset to suballoc.offset.
+ const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // 2. Process this allocation.
+ // There is allocation with suballoc.offset, suballoc.size.
+ PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+
+ // 3. Prepare for next iteration.
+ lastOffset = suballoc.offset + suballoc.size;
+ --nextAlloc2ndIndex;
+ }
+ // We are at the end.
+ else
+ {
+ if(lastOffset < size)
+ {
+ // There is free space from lastOffset to size.
+ const VkDeviceSize unusedRangeSize = size - lastOffset;
+ PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+ }
+
+ // End of loop.
+ lastOffset = size;
+ }
+ }
+ }
+
+ PrintDetailedMap_End(json);
+}
+#endif // #if VMA_STATS_STRING_ENABLED
+
+bool VmaBlockMetadata_Linear::CreateAllocationRequest(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool canMakeOtherLost,
+ uint32_t /*strategy*/,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ VMA_ASSERT(allocSize > 0);
+ VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(pAllocationRequest != VMA_NULL);
+ VMA_HEAVY_ASSERT(Validate());
+
+ const VkDeviceSize size = GetSize();
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ if(upperAddress)
+ {
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ VMA_ASSERT(0 && "Trying to use pool with linear algorithm as double stack, while it is already being used as ring buffer.");
+ return false;
+ }
+
+ // Try to allocate before 2nd.back(), or end of block if 2nd.empty().
+ if(allocSize > size)
+ {
+ return false;
+ }
+ VkDeviceSize resultBaseOffset = size - allocSize;
+ if(!suballocations2nd.empty())
+ {
+ const VmaSuballocation& lastSuballoc = suballocations2nd.back();
+ resultBaseOffset = lastSuballoc.offset - allocSize;
+ if(allocSize > lastSuballoc.offset)
+ {
+ return false;
+ }
+ }
+
+ // Start from offset equal to end of free space.
+ VkDeviceSize resultOffset = resultBaseOffset;
+
+ // Apply VMA_DEBUG_MARGIN at the end.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
+#if VMA_DEBUG_MARGIN
+ if(resultOffset < VMA_DEBUG_MARGIN)
+ {
+ return false;
+ }
+#endif
+ resultOffset -= VMA_DEBUG_MARGIN;
+ }
+
+ // Apply alignment.
+ resultOffset = VmaAlignDown(resultOffset, allocAlignment);
+
+ // Check next suballocations from 2nd for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if(bufferImageGranularity > 1 && !suballocations2nd.empty())
+ {
+ bool bufferImageGranularityConflict = false;
+ for(size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )
+ {
+ const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];
+ if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(nextSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
+ }
+ else
+ // Already on previous page.
+ break;
+ }
+ if(bufferImageGranularityConflict)
+ {
+ resultOffset = VmaAlignDown(resultOffset, bufferImageGranularity);
+ }
+ }
+
+ // There is enough free space.
+ const VkDeviceSize endOf1st = !suballocations1st.empty() ?
+ suballocations1st.back().offset + suballocations1st.back().size :
+ 0;
+ if(endOf1st + VMA_DEBUG_MARGIN <= resultOffset)
+ {
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, allocation cannot be made here.
+ if(bufferImageGranularity > 1)
+ {
+ for(size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )
+ {
+ const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];
+ if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(allocType, prevSuballoc.type))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
+ }
+ }
+
+ // All tests passed: Success.
+ pAllocationRequest->offset = resultOffset;
+ pAllocationRequest->sumFreeSize = resultBaseOffset + allocSize - endOf1st;
+ pAllocationRequest->sumItemSize = 0;
+ // pAllocationRequest->item unused.
+ pAllocationRequest->itemsToMakeLostCount = 0;
+ return true;
+ }
+ }
+ else // !upperAddress
+ {
+ if(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ // Try to allocate at the end of 1st vector.
+
+ VkDeviceSize resultBaseOffset = 0;
+ if(!suballocations1st.empty())
+ {
+ const VmaSuballocation& lastSuballoc = suballocations1st.back();
+ resultBaseOffset = lastSuballoc.offset + lastSuballoc.size;
+ }
+
+ // Start from offset equal to beginning of free space.
+ VkDeviceSize resultOffset = resultBaseOffset;
+
+ // Apply VMA_DEBUG_MARGIN at the beginning.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
+ resultOffset += VMA_DEBUG_MARGIN;
+ }
+
+ // Apply alignment.
+ resultOffset = VmaAlignUp(resultOffset, allocAlignment);
+
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if(bufferImageGranularity > 1 && !suballocations1st.empty())
+ {
+ bool bufferImageGranularityConflict = false;
+ for(size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )
+ {
+ const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];
+ if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
+ }
+ else
+ // Already on previous page.
+ break;
+ }
+ if(bufferImageGranularityConflict)
+ {
+ resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);
+ }
+ }
+
+ const VkDeviceSize freeSpaceEnd = m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ?
+ suballocations2nd.back().offset : size;
+
+ // There is enough free space at the end after alignment.
+ if(resultOffset + allocSize + VMA_DEBUG_MARGIN <= freeSpaceEnd)
+ {
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, allocation cannot be made here.
+ if(bufferImageGranularity > 1 && m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ for(size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )
+ {
+ const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];
+ if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Already on previous page.
+ break;
+ }
+ }
+ }
+
+ // All tests passed: Success.
+ pAllocationRequest->offset = resultOffset;
+ pAllocationRequest->sumFreeSize = freeSpaceEnd - resultBaseOffset;
+ pAllocationRequest->sumItemSize = 0;
+ // pAllocationRequest->item unused.
+ pAllocationRequest->itemsToMakeLostCount = 0;
+ return true;
+ }
+ }
+
+ // Wrap-around to end of 2nd vector. Try to allocate there, watching for the
+ // beginning of 1st vector as the end of free space.
+ if(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ VMA_ASSERT(!suballocations1st.empty());
+
+ VkDeviceSize resultBaseOffset = 0;
+ if(!suballocations2nd.empty())
+ {
+ const VmaSuballocation& lastSuballoc = suballocations2nd.back();
+ resultBaseOffset = lastSuballoc.offset + lastSuballoc.size;
+ }
+
+ // Start from offset equal to beginning of free space.
+ VkDeviceSize resultOffset = resultBaseOffset;
+
+ // Apply VMA_DEBUG_MARGIN at the beginning.
+ if(VMA_DEBUG_MARGIN > 0)
+ {
+ resultOffset += VMA_DEBUG_MARGIN;
+ }
+
+ // Apply alignment.
+ resultOffset = VmaAlignUp(resultOffset, allocAlignment);
+
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if(bufferImageGranularity > 1 && !suballocations2nd.empty())
+ {
+ bool bufferImageGranularityConflict = false;
+ for(size_t prevSuballocIndex = suballocations2nd.size(); prevSuballocIndex--; )
+ {
+ const VmaSuballocation& prevSuballoc = suballocations2nd[prevSuballocIndex];
+ if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
+ }
+ else
+ // Already on previous page.
+ break;
+ }
+ if(bufferImageGranularityConflict)
+ {
+ resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);
+ }
+ }
+
+ pAllocationRequest->itemsToMakeLostCount = 0;
+ pAllocationRequest->sumItemSize = 0;
+ size_t index1st = m_1stNullItemsBeginCount;
+
+ if(canMakeOtherLost)
+ {
+ while(index1st < suballocations1st.size() &&
+ resultOffset + allocSize + VMA_DEBUG_MARGIN > suballocations1st[index1st].offset)
+ {
+ // Next colliding allocation at the beginning of 1st vector found. Try to make it lost.
+ const VmaSuballocation& suballoc = suballocations1st[index1st];
+ if(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ // No problem.
+ }
+ else
+ {
+ VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE);
+ if(suballoc.hAllocation->CanBecomeLost() &&
+ suballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+ {
+ ++pAllocationRequest->itemsToMakeLostCount;
+ pAllocationRequest->sumItemSize += suballoc.size;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ ++index1st;
+ }
+
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, we must mark more allocations lost or fail.
+ if(bufferImageGranularity > 1)
+ {
+ while(index1st < suballocations1st.size())
+ {
+ const VmaSuballocation& suballoc = suballocations1st[index1st];
+ if(VmaBlocksOnSamePage(resultOffset, allocSize, suballoc.offset, bufferImageGranularity))
+ {
+ if(suballoc.hAllocation != VK_NULL_HANDLE)
+ {
+ // Not checking actual VmaIsBufferImageGranularityConflict(allocType, suballoc.type).
+ if(suballoc.hAllocation->CanBecomeLost() &&
+ suballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+ {
+ ++pAllocationRequest->itemsToMakeLostCount;
+ pAllocationRequest->sumItemSize += suballoc.size;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
+ ++index1st;
+ }
+ }
+ }
+
+ // There is enough free space at the end after alignment.
+ if((index1st == suballocations1st.size() && resultOffset + allocSize + VMA_DEBUG_MARGIN < size) ||
+ (index1st < suballocations1st.size() && resultOffset + allocSize + VMA_DEBUG_MARGIN <= suballocations1st[index1st].offset))
+ {
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, allocation cannot be made here.
+ if(bufferImageGranularity > 1)
+ {
+ for(size_t nextSuballocIndex = index1st;
+ nextSuballocIndex < suballocations1st.size();
+ nextSuballocIndex++)
+ {
+ const VmaSuballocation& nextSuballoc = suballocations1st[nextSuballocIndex];
+ if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ {
+ if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
+ }
+ }
+
+ // All tests passed: Success.
+ pAllocationRequest->offset = resultOffset;
+ pAllocationRequest->sumFreeSize =
+ (index1st < suballocations1st.size() ? suballocations1st[index1st].offset : size)
+ - resultBaseOffset
+ - pAllocationRequest->sumItemSize;
+ // pAllocationRequest->item unused.
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool VmaBlockMetadata_Linear::MakeRequestedAllocationsLost(
+ uint32_t currentFrameIndex,
+ uint32_t frameInUseCount,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ if(pAllocationRequest->itemsToMakeLostCount == 0)
+ {
+ return true;
+ }
+
+ VMA_ASSERT(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER);
+
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ size_t index1st = m_1stNullItemsBeginCount;
+ size_t madeLostCount = 0;
+ while(madeLostCount < pAllocationRequest->itemsToMakeLostCount)
+ {
+ VMA_ASSERT(index1st < suballocations1st.size());
+ VmaSuballocation& suballoc = suballocations1st[index1st];
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE);
+ VMA_ASSERT(suballoc.hAllocation->CanBecomeLost());
+ if(suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ {
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ suballoc.hAllocation = VK_NULL_HANDLE;
+ m_SumFreeSize += suballoc.size;
+ ++m_1stNullItemsMiddleCount;
+ ++madeLostCount;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ ++index1st;
+ }
+
+ CleanupAfterFree();
+ //VMA_HEAVY_ASSERT(Validate()); // Already called by ClanupAfterFree().
+
+ return true;
+}
+
+uint32_t VmaBlockMetadata_Linear::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+ uint32_t lostAllocationCount = 0;
+
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ for(size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i)
+ {
+ VmaSuballocation& suballoc = suballocations1st[i];
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE &&
+ suballoc.hAllocation->CanBecomeLost() &&
+ suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ {
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ suballoc.hAllocation = VK_NULL_HANDLE;
+ ++m_1stNullItemsMiddleCount;
+ m_SumFreeSize += suballoc.size;
+ ++lostAllocationCount;
+ }
+ }
+
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ for(size_t i = 0, count = suballocations2nd.size(); i < count; ++i)
+ {
+ VmaSuballocation& suballoc = suballocations2nd[i];
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE &&
+ suballoc.hAllocation->CanBecomeLost() &&
+ suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ {
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ suballoc.hAllocation = VK_NULL_HANDLE;
+ ++m_2ndNullItemsCount;
+ ++lostAllocationCount;
+ }
+ }
+
+ if(lostAllocationCount)
+ {
+ CleanupAfterFree();
+ }
+
+ return lostAllocationCount;
+}
+
+VkResult VmaBlockMetadata_Linear::CheckCorruption(const void* pBlockData)
+{
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ for(size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[i];
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ if(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ if(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ }
+ }
+
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ for(size_t i = 0, count = suballocations2nd.size(); i < count; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[i];
+ if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ if(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ if(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaBlockMetadata_Linear::Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ VkDeviceSize allocSize,
+ bool upperAddress,
+ VmaAllocation hAllocation)
+{
+ const VmaSuballocation newSuballoc = { request.offset, allocSize, hAllocation, type };
+
+ if(upperAddress)
+ {
+ VMA_ASSERT(m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER &&
+ "CRITICAL ERROR: Trying to use linear allocator as double stack while it was already used as ring buffer.");
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ suballocations2nd.push_back(newSuballoc);
+ m_2ndVectorMode = SECOND_VECTOR_DOUBLE_STACK;
+ }
+ else
+ {
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+
+ // First allocation.
+ if(suballocations1st.empty())
+ {
+ suballocations1st.push_back(newSuballoc);
+ }
+ else
+ {
+ // New allocation at the end of 1st vector.
+ if(request.offset >= suballocations1st.back().offset + suballocations1st.back().size)
+ {
+ // Check if it fits before the end of the block.
+ VMA_ASSERT(request.offset + allocSize <= GetSize());
+ suballocations1st.push_back(newSuballoc);
+ }
+ // New allocation at the end of 2-part ring buffer, so before first allocation from 1st vector.
+ else if(request.offset + allocSize <= suballocations1st[m_1stNullItemsBeginCount].offset)
+ {
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ switch(m_2ndVectorMode)
+ {
+ case SECOND_VECTOR_EMPTY:
+ // First allocation from second part ring buffer.
+ VMA_ASSERT(suballocations2nd.empty());
+ m_2ndVectorMode = SECOND_VECTOR_RING_BUFFER;
+ break;
+ case SECOND_VECTOR_RING_BUFFER:
+ // 2-part ring buffer is already started.
+ VMA_ASSERT(!suballocations2nd.empty());
+ break;
+ case SECOND_VECTOR_DOUBLE_STACK:
+ VMA_ASSERT(0 && "CRITICAL ERROR: Trying to use linear allocator as ring buffer while it was already used as double stack.");
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+
+ suballocations2nd.push_back(newSuballoc);
+ }
+ else
+ {
+ VMA_ASSERT(0 && "CRITICAL INTERNAL ERROR.");
+ }
+ }
+ }
+
+ m_SumFreeSize -= newSuballoc.size;
+}
+
+void VmaBlockMetadata_Linear::Free(const VmaAllocation allocation)
+{
+ FreeAtOffset(allocation->GetOffset());
+}
+
+void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset)
+{
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ if(!suballocations1st.empty())
+ {
+ // First allocation: Mark it as next empty at the beginning.
+ VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];
+ if(firstSuballoc.offset == offset)
+ {
+ firstSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ firstSuballoc.hAllocation = VK_NULL_HANDLE;
+ m_SumFreeSize += firstSuballoc.size;
+ ++m_1stNullItemsBeginCount;
+ CleanupAfterFree();
+ return;
+ }
+ }
+
+ // Last allocation in 2-part ring buffer or top of upper stack (same logic).
+ if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ||
+ m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ VmaSuballocation& lastSuballoc = suballocations2nd.back();
+ if(lastSuballoc.offset == offset)
+ {
+ m_SumFreeSize += lastSuballoc.size;
+ suballocations2nd.pop_back();
+ CleanupAfterFree();
+ return;
+ }
+ }
+ // Last allocation in 1st vector.
+ else if(m_2ndVectorMode == SECOND_VECTOR_EMPTY)
+ {
+ VmaSuballocation& lastSuballoc = suballocations1st.back();
+ if(lastSuballoc.offset == offset)
+ {
+ m_SumFreeSize += lastSuballoc.size;
+ suballocations1st.pop_back();
+ CleanupAfterFree();
+ return;
+ }
+ }
+
+ // Item from the middle of 1st vector.
+ {
+ VmaSuballocation refSuballoc;
+ refSuballoc.offset = offset;
+ // Rest of members stays uninitialized intentionally for better performance.
+ SuballocationVectorType::iterator it = VmaVectorFindSorted<VmaSuballocationOffsetLess>(
+ suballocations1st.begin() + m_1stNullItemsBeginCount,
+ suballocations1st.end(),
+ refSuballoc);
+ if(it != suballocations1st.end())
+ {
+ it->type = VMA_SUBALLOCATION_TYPE_FREE;
+ it->hAllocation = VK_NULL_HANDLE;
+ ++m_1stNullItemsMiddleCount;
+ m_SumFreeSize += it->size;
+ CleanupAfterFree();
+ return;
+ }
+ }
+
+ if(m_2ndVectorMode != SECOND_VECTOR_EMPTY)
+ {
+ // Item from the middle of 2nd vector.
+ VmaSuballocation refSuballoc;
+ refSuballoc.offset = offset;
+ // Rest of members stays uninitialized intentionally for better performance.
+ SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?
+ VmaVectorFindSorted<VmaSuballocationOffsetLess>(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc) :
+ VmaVectorFindSorted<VmaSuballocationOffsetGreater>(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc);
+ if(it != suballocations2nd.end())
+ {
+ it->type = VMA_SUBALLOCATION_TYPE_FREE;
+ it->hAllocation = VK_NULL_HANDLE;
+ ++m_2ndNullItemsCount;
+ m_SumFreeSize += it->size;
+ CleanupAfterFree();
+ return;
+ }
+ }
+
+ VMA_ASSERT(0 && "Allocation to free not found in linear allocator!");
+}
+
+bool VmaBlockMetadata_Linear::ShouldCompact1st() const
+{
+ const size_t nullItemCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;
+ const size_t suballocCount = AccessSuballocations1st().size();
+ return suballocCount > 32 && nullItemCount * 2 >= (suballocCount - nullItemCount) * 3;
+}
+
+void VmaBlockMetadata_Linear::CleanupAfterFree()
+{
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ if(IsEmpty())
+ {
+ suballocations1st.clear();
+ suballocations2nd.clear();
+ m_1stNullItemsBeginCount = 0;
+ m_1stNullItemsMiddleCount = 0;
+ m_2ndNullItemsCount = 0;
+ m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+ }
+ else
+ {
+ const size_t suballoc1stCount = suballocations1st.size();
+ const size_t nullItem1stCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;
+ VMA_ASSERT(nullItem1stCount <= suballoc1stCount);
+
+ // Find more null items at the beginning of 1st vector.
+ while(m_1stNullItemsBeginCount < suballoc1stCount &&
+ suballocations1st[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE)
+ {
+ ++m_1stNullItemsBeginCount;
+ --m_1stNullItemsMiddleCount;
+ }
+
+ // Find more null items at the end of 1st vector.
+ while(m_1stNullItemsMiddleCount > 0 &&
+ suballocations1st.back().hAllocation == VK_NULL_HANDLE)
+ {
+ --m_1stNullItemsMiddleCount;
+ suballocations1st.pop_back();
+ }
+
+ // Find more null items at the end of 2nd vector.
+ while(m_2ndNullItemsCount > 0 &&
+ suballocations2nd.back().hAllocation == VK_NULL_HANDLE)
+ {
+ --m_2ndNullItemsCount;
+ suballocations2nd.pop_back();
+ }
+
+ if(ShouldCompact1st())
+ {
+ const size_t nonNullItemCount = suballoc1stCount - nullItem1stCount;
+ size_t srcIndex = m_1stNullItemsBeginCount;
+ for(size_t dstIndex = 0; dstIndex < nonNullItemCount; ++dstIndex)
+ {
+ while(suballocations1st[srcIndex].hAllocation == VK_NULL_HANDLE)
+ {
+ ++srcIndex;
+ }
+ if(dstIndex != srcIndex)
+ {
+ suballocations1st[dstIndex] = suballocations1st[srcIndex];
+ }
+ ++srcIndex;
+ }
+ suballocations1st.resize(nonNullItemCount);
+ m_1stNullItemsBeginCount = 0;
+ m_1stNullItemsMiddleCount = 0;
+ }
+
+ // 2nd vector became empty.
+ if(suballocations2nd.empty())
+ {
+ m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+ }
+
+ // 1st vector became empty.
+ if(suballocations1st.size() - m_1stNullItemsBeginCount == 0)
+ {
+ suballocations1st.clear();
+ m_1stNullItemsBeginCount = 0;
+
+ if(!suballocations2nd.empty() && m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ // Swap 1st with 2nd. Now 2nd is empty.
+ m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+ m_1stNullItemsMiddleCount = m_2ndNullItemsCount;
+ while(m_1stNullItemsBeginCount < suballocations2nd.size() &&
+ suballocations2nd[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE)
+ {
+ ++m_1stNullItemsBeginCount;
+ --m_1stNullItemsMiddleCount;
+ }
+ m_2ndNullItemsCount = 0;
+ m_1stVectorIndex ^= 1;
+ }
+ }
+ }
+
+ VMA_HEAVY_ASSERT(Validate());
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata_Buddy
+
+VmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(VmaAllocator hAllocator) :
+ VmaBlockMetadata(hAllocator),
+ m_Root(VMA_NULL),
+ m_AllocationCount(0),
+ m_FreeCount(1),
+ m_SumFreeSize(0)
+{
+ memset(m_FreeList, 0, sizeof(m_FreeList));
+}
+
+VmaBlockMetadata_Buddy::~VmaBlockMetadata_Buddy()
+{
+ DeleteNode(m_Root);
+}
+
+void VmaBlockMetadata_Buddy::Init(VkDeviceSize size)
+{
+ VmaBlockMetadata::Init(size);
+
+ m_UsableSize = VmaPrevPow2(size);
+ m_SumFreeSize = m_UsableSize;
+
+ // Calculate m_LevelCount.
+ m_LevelCount = 1;
+ while(m_LevelCount < MAX_LEVELS &&
+ LevelToNodeSize(m_LevelCount) >= MIN_NODE_SIZE)
+ {
+ ++m_LevelCount;
+ }
+
+ Node* rootNode = vma_new(GetAllocationCallbacks(), Node)();
+ rootNode->offset = 0;
+ rootNode->type = Node::TYPE_FREE;
+ rootNode->parent = VMA_NULL;
+ rootNode->buddy = VMA_NULL;
+
+ m_Root = rootNode;
+ AddToFreeListFront(0, rootNode);
+}
+
+bool VmaBlockMetadata_Buddy::Validate() const
+{
+ // Validate tree.
+ ValidationContext ctx;
+ if(!ValidateNode(ctx, VMA_NULL, m_Root, 0, LevelToNodeSize(0)))
+ {
+ VMA_VALIDATE(false && "ValidateNode failed.");
+ }
+ VMA_VALIDATE(m_AllocationCount == ctx.calculatedAllocationCount);
+ VMA_VALIDATE(m_SumFreeSize == ctx.calculatedSumFreeSize);
+
+ // Validate free node lists.
+ for(uint32_t level = 0; level < m_LevelCount; ++level)
+ {
+ VMA_VALIDATE(m_FreeList[level].front == VMA_NULL ||
+ m_FreeList[level].front->free.prev == VMA_NULL);
+
+ for(Node* node = m_FreeList[level].front;
+ node != VMA_NULL;
+ node = node->free.next)
+ {
+ VMA_VALIDATE(node->type == Node::TYPE_FREE);
+
+ if(node->free.next == VMA_NULL)
+ {
+ VMA_VALIDATE(m_FreeList[level].back == node);
+ }
+ else
+ {
+ VMA_VALIDATE(node->free.next->free.prev == node);
+ }
+ }
+ }
+
+ // Validate that free lists ar higher levels are empty.
+ for(uint32_t level = m_LevelCount; level < MAX_LEVELS; ++level)
+ {
+ VMA_VALIDATE(m_FreeList[level].front == VMA_NULL && m_FreeList[level].back == VMA_NULL);
+ }
+
+ return true;
+}
+
+VkDeviceSize VmaBlockMetadata_Buddy::GetUnusedRangeSizeMax() const
+{
+ for(uint32_t level = 0; level < m_LevelCount; ++level)
+ {
+ if(m_FreeList[level].front != VMA_NULL)
+ {
+ return LevelToNodeSize(level);
+ }
+ }
+ return 0;
+}
+
+void VmaBlockMetadata_Buddy::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
+{
+ const VkDeviceSize unusableSize = GetUnusableSize();
+
+ outInfo.blockCount = 1;
+
+ outInfo.allocationCount = outInfo.unusedRangeCount = 0;
+ outInfo.usedBytes = outInfo.unusedBytes = 0;
+
+ outInfo.allocationSizeMax = outInfo.unusedRangeSizeMax = 0;
+ outInfo.allocationSizeMin = outInfo.unusedRangeSizeMin = UINT64_MAX;
+ outInfo.allocationSizeAvg = outInfo.unusedRangeSizeAvg = 0; // Unused.
+
+ CalcAllocationStatInfoNode(outInfo, m_Root, LevelToNodeSize(0));
+
+ if(unusableSize > 0)
+ {
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusableSize;
+ outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusableSize);
+ outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusableSize);
+ }
+}
+
+void VmaBlockMetadata_Buddy::AddPoolStats(VmaPoolStats& inoutStats) const
+{
+ const VkDeviceSize unusableSize = GetUnusableSize();
+
+ inoutStats.size += GetSize();
+ inoutStats.unusedSize += m_SumFreeSize + unusableSize;
+ inoutStats.allocationCount += m_AllocationCount;
+ inoutStats.unusedRangeCount += m_FreeCount;
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, GetUnusedRangeSizeMax());
+
+ if(unusableSize > 0)
+ {
+ ++inoutStats.unusedRangeCount;
+ // Not updating inoutStats.unusedRangeSizeMax with unusableSize because this space is not available for allocations.
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockMetadata_Buddy::PrintDetailedMap(class VmaJsonWriter& json) const
+{
+ // TODO optimize
+ VmaStatInfo stat;
+ CalcAllocationStatInfo(stat);
+
+ PrintDetailedMap_Begin(
+ json,
+ stat.unusedBytes,
+ stat.allocationCount,
+ stat.unusedRangeCount);
+
+ PrintDetailedMapNode(json, m_Root, LevelToNodeSize(0));
+
+ const VkDeviceSize unusableSize = GetUnusableSize();
+ if(unusableSize > 0)
+ {
+ PrintDetailedMap_UnusedRange(json,
+ m_UsableSize, // offset
+ unusableSize); // size
+ }
+
+ PrintDetailedMap_End(json);
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+bool VmaBlockMetadata_Buddy::CreateAllocationRequest(
+ uint32_t /*currentFrameIndex*/,
+ uint32_t /*frameInUseCount*/,
+ VkDeviceSize bufferImageGranularity,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ bool /*canMakeOtherLost*/,
+ uint32_t /*strategy*/,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ VMA_ASSERT(!upperAddress && "VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm.");
+ (void) upperAddress;
+
+ // Simple way to respect bufferImageGranularity. May be optimized some day.
+ // Whenever it might be an OPTIMAL image...
+ if(allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN ||
+ allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
+ allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL)
+ {
+ allocAlignment = VMA_MAX(allocAlignment, bufferImageGranularity);
+ allocSize = VMA_MAX(allocSize, bufferImageGranularity);
+ }
+
+ if(allocSize > m_UsableSize)
+ {
+ return false;
+ }
+
+ const uint32_t targetLevel = AllocSizeToLevel(allocSize);
+ for(uint32_t level = targetLevel + 1; level--; )
+ {
+ for(Node* freeNode = m_FreeList[level].front;
+ freeNode != VMA_NULL;
+ freeNode = freeNode->free.next)
+ {
+ if(freeNode->offset % allocAlignment == 0)
+ {
+ pAllocationRequest->offset = freeNode->offset;
+ pAllocationRequest->sumFreeSize = LevelToNodeSize(level);
+ pAllocationRequest->sumItemSize = 0;
+ pAllocationRequest->itemsToMakeLostCount = 0;
+ pAllocationRequest->customData = (void*)(uintptr_t)level;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool VmaBlockMetadata_Buddy::MakeRequestedAllocationsLost(
+ uint32_t /*currentFrameIndex*/,
+ uint32_t /*frameInUseCount*/,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ /*
+ Lost allocations are not supported in buddy allocator at the moment.
+ Support might be added in the future.
+ */
+ return pAllocationRequest->itemsToMakeLostCount == 0;
+}
+
+uint32_t VmaBlockMetadata_Buddy::MakeAllocationsLost(uint32_t /*currentFrameIndex*/, uint32_t /*frameInUseCount*/)
+{
+ /*
+ Lost allocations are not supported in buddy allocator at the moment.
+ Support might be added in the future.
+ */
+ return 0;
+}
+
+void VmaBlockMetadata_Buddy::Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType /*type*/,
+ VkDeviceSize allocSize,
+ bool /*upperAddress*/,
+ VmaAllocation hAllocation)
+{
+ const uint32_t targetLevel = AllocSizeToLevel(allocSize);
+ uint32_t currLevel = (uint32_t)(uintptr_t)request.customData;
+
+ Node* currNode = m_FreeList[currLevel].front;
+ VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
+ while(currNode->offset != request.offset)
+ {
+ currNode = currNode->free.next;
+ VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
+ }
+
+ // Go down, splitting free nodes.
+ while(currLevel < targetLevel)
+ {
+ // currNode is already first free node at currLevel.
+ // Remove it from list of free nodes at this currLevel.
+ RemoveFromFreeList(currLevel, currNode);
+
+ const uint32_t childrenLevel = currLevel + 1;
+
+ // Create two free sub-nodes.
+ Node* leftChild = vma_new(GetAllocationCallbacks(), Node)();
+ Node* rightChild = vma_new(GetAllocationCallbacks(), Node)();
+
+ leftChild->offset = currNode->offset;
+ leftChild->type = Node::TYPE_FREE;
+ leftChild->parent = currNode;
+ leftChild->buddy = rightChild;
+
+ rightChild->offset = currNode->offset + LevelToNodeSize(childrenLevel);
+ rightChild->type = Node::TYPE_FREE;
+ rightChild->parent = currNode;
+ rightChild->buddy = leftChild;
+
+ // Convert current currNode to split type.
+ currNode->type = Node::TYPE_SPLIT;
+ currNode->split.leftChild = leftChild;
+
+ // Add child nodes to free list. Order is important!
+ AddToFreeListFront(childrenLevel, rightChild);
+ AddToFreeListFront(childrenLevel, leftChild);
+
+ ++m_FreeCount;
+ //m_SumFreeSize -= LevelToNodeSize(currLevel) % 2; // Useful only when level node sizes can be non power of 2.
+ ++currLevel;
+ currNode = m_FreeList[currLevel].front;
+
+ /*
+ We can be sure that currNode, as left child of node previously split,
+ also fullfills the alignment requirement.
+ */
+ }
+
+ // Remove from free list.
+ VMA_ASSERT(currLevel == targetLevel &&
+ currNode != VMA_NULL &&
+ currNode->type == Node::TYPE_FREE);
+ RemoveFromFreeList(currLevel, currNode);
+
+ // Convert to allocation node.
+ currNode->type = Node::TYPE_ALLOCATION;
+ currNode->allocation.alloc = hAllocation;
+
+ ++m_AllocationCount;
+ --m_FreeCount;
+ m_SumFreeSize -= allocSize;
+}
+
+void VmaBlockMetadata_Buddy::DeleteNode(Node* node)
+{
+ if(node->type == Node::TYPE_SPLIT)
+ {
+ DeleteNode(node->split.leftChild->buddy);
+ DeleteNode(node->split.leftChild);
+ }
+
+ vma_delete(GetAllocationCallbacks(), node);
+}
+
+bool VmaBlockMetadata_Buddy::ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const
+{
+ VMA_VALIDATE(level < m_LevelCount);
+ VMA_VALIDATE(curr->parent == parent);
+ VMA_VALIDATE((curr->buddy == VMA_NULL) == (parent == VMA_NULL));
+ VMA_VALIDATE(curr->buddy == VMA_NULL || curr->buddy->buddy == curr);
+ switch(curr->type)
+ {
+ case Node::TYPE_FREE:
+ // curr->free.prev, next are validated separately.
+ ctx.calculatedSumFreeSize += levelNodeSize;
+ ++ctx.calculatedFreeCount;
+ break;
+ case Node::TYPE_ALLOCATION:
+ ++ctx.calculatedAllocationCount;
+ ctx.calculatedSumFreeSize += levelNodeSize - curr->allocation.alloc->GetSize();
+ VMA_VALIDATE(curr->allocation.alloc != VK_NULL_HANDLE);
+ break;
+ case Node::TYPE_SPLIT:
+ {
+ const uint32_t childrenLevel = level + 1;
+ const VkDeviceSize childrenLevelNodeSize = levelNodeSize / 2;
+ const Node* const leftChild = curr->split.leftChild;
+ VMA_VALIDATE(leftChild != VMA_NULL);
+ VMA_VALIDATE(leftChild->offset == curr->offset);
+ if(!ValidateNode(ctx, curr, leftChild, childrenLevel, childrenLevelNodeSize))
+ {
+ VMA_VALIDATE(false && "ValidateNode for left child failed.");
+ }
+ const Node* const rightChild = leftChild->buddy;
+ VMA_VALIDATE(rightChild->offset == curr->offset + childrenLevelNodeSize);
+ if(!ValidateNode(ctx, curr, rightChild, childrenLevel, childrenLevelNodeSize))
+ {
+ VMA_VALIDATE(false && "ValidateNode for right child failed.");
+ }
+ }
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+uint32_t VmaBlockMetadata_Buddy::AllocSizeToLevel(VkDeviceSize allocSize) const
+{
+ // I know this could be optimized somehow e.g. by using std::log2p1 from C++20.
+ uint32_t level = 0;
+ VkDeviceSize currLevelNodeSize = m_UsableSize;
+ VkDeviceSize nextLevelNodeSize = currLevelNodeSize >> 1;
+ while(allocSize <= nextLevelNodeSize && level + 1 < m_LevelCount)
+ {
+ ++level;
+ currLevelNodeSize = nextLevelNodeSize;
+ nextLevelNodeSize = currLevelNodeSize >> 1;
+ }
+ return level;
+}
+
+void VmaBlockMetadata_Buddy::FreeAtOffset(VmaAllocation alloc, VkDeviceSize offset)
+{
+ // Find node and level.
+ Node* node = m_Root;
+ VkDeviceSize nodeOffset = 0;
+ uint32_t level = 0;
+ VkDeviceSize levelNodeSize = LevelToNodeSize(0);
+ while(node->type == Node::TYPE_SPLIT)
+ {
+ const VkDeviceSize nextLevelSize = levelNodeSize >> 1;
+ if(offset < nodeOffset + nextLevelSize)
+ {
+ node = node->split.leftChild;
+ }
+ else
+ {
+ node = node->split.leftChild->buddy;
+ nodeOffset += nextLevelSize;
+ }
+ ++level;
+ levelNodeSize = nextLevelSize;
+ }
+
+ VMA_ASSERT(node != VMA_NULL && node->type == Node::TYPE_ALLOCATION);
+ VMA_ASSERT(alloc == VK_NULL_HANDLE || node->allocation.alloc == alloc);
+
+ ++m_FreeCount;
+ --m_AllocationCount;
+ m_SumFreeSize += alloc->GetSize();
+
+ node->type = Node::TYPE_FREE;
+
+ // Join free nodes if possible.
+ while(level > 0 && node->buddy->type == Node::TYPE_FREE)
+ {
+ RemoveFromFreeList(level, node->buddy);
+ Node* const parent = node->parent;
+
+ vma_delete(GetAllocationCallbacks(), node->buddy);
+ vma_delete(GetAllocationCallbacks(), node);
+ parent->type = Node::TYPE_FREE;
+
+ node = parent;
+ --level;
+ //m_SumFreeSize += LevelToNodeSize(level) % 2; // Useful only when level node sizes can be non power of 2.
+ --m_FreeCount;
+ }
+
+ AddToFreeListFront(level, node);
+}
+
+void VmaBlockMetadata_Buddy::CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const
+{
+ switch(node->type)
+ {
+ case Node::TYPE_FREE:
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += levelNodeSize;
+ outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, levelNodeSize);
+ outInfo.unusedRangeSizeMin = VMA_MAX(outInfo.unusedRangeSizeMin, levelNodeSize);
+ break;
+ case Node::TYPE_ALLOCATION:
+ {
+ const VkDeviceSize allocSize = node->allocation.alloc->GetSize();
+ ++outInfo.allocationCount;
+ outInfo.usedBytes += allocSize;
+ outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, allocSize);
+ outInfo.allocationSizeMin = VMA_MAX(outInfo.allocationSizeMin, allocSize);
+
+ const VkDeviceSize unusedRangeSize = levelNodeSize - allocSize;
+ if(unusedRangeSize > 0)
+ {
+ ++outInfo.unusedRangeCount;
+ outInfo.unusedBytes += unusedRangeSize;
+ outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ outInfo.unusedRangeSizeMin = VMA_MAX(outInfo.unusedRangeSizeMin, unusedRangeSize);
+ }
+ }
+ break;
+ case Node::TYPE_SPLIT:
+ {
+ const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
+ const Node* const leftChild = node->split.leftChild;
+ CalcAllocationStatInfoNode(outInfo, leftChild, childrenNodeSize);
+ const Node* const rightChild = leftChild->buddy;
+ CalcAllocationStatInfoNode(outInfo, rightChild, childrenNodeSize);
+ }
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+}
+
+void VmaBlockMetadata_Buddy::AddToFreeListFront(uint32_t level, Node* node)
+{
+ VMA_ASSERT(node->type == Node::TYPE_FREE);
+
+ // List is empty.
+ Node* const frontNode = m_FreeList[level].front;
+ if(frontNode == VMA_NULL)
+ {
+ VMA_ASSERT(m_FreeList[level].back == VMA_NULL);
+ node->free.prev = node->free.next = VMA_NULL;
+ m_FreeList[level].front = m_FreeList[level].back = node;
+ }
+ else
+ {
+ VMA_ASSERT(frontNode->free.prev == VMA_NULL);
+ node->free.prev = VMA_NULL;
+ node->free.next = frontNode;
+ frontNode->free.prev = node;
+ m_FreeList[level].front = node;
+ }
+}
+
+void VmaBlockMetadata_Buddy::RemoveFromFreeList(uint32_t level, Node* node)
+{
+ VMA_ASSERT(m_FreeList[level].front != VMA_NULL);
+
+ // It is at the front.
+ if(node->free.prev == VMA_NULL)
+ {
+ VMA_ASSERT(m_FreeList[level].front == node);
+ m_FreeList[level].front = node->free.next;
+ }
+ else
+ {
+ Node* const prevFreeNode = node->free.prev;
+ VMA_ASSERT(prevFreeNode->free.next == node);
+ prevFreeNode->free.next = node->free.next;
+ }
+
+ // It is at the back.
+ if(node->free.next == VMA_NULL)
+ {
+ VMA_ASSERT(m_FreeList[level].back == node);
+ m_FreeList[level].back = node->free.prev;
+ }
+ else
+ {
+ Node* const nextFreeNode = node->free.next;
+ VMA_ASSERT(nextFreeNode->free.prev == node);
+ nextFreeNode->free.prev = node->free.prev;
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+void VmaBlockMetadata_Buddy::PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const
+{
+ switch(node->type)
+ {
+ case Node::TYPE_FREE:
+ PrintDetailedMap_UnusedRange(json, node->offset, levelNodeSize);
+ break;
+ case Node::TYPE_ALLOCATION:
+ {
+ PrintDetailedMap_Allocation(json, node->offset, node->allocation.alloc);
+ const VkDeviceSize allocSize = node->allocation.alloc->GetSize();
+ if(allocSize < levelNodeSize)
+ {
+ PrintDetailedMap_UnusedRange(json, node->offset + allocSize, levelNodeSize - allocSize);
+ }
+ }
+ break;
+ case Node::TYPE_SPLIT:
+ {
+ const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
+ const Node* const leftChild = node->split.leftChild;
+ PrintDetailedMapNode(json, leftChild, childrenNodeSize);
+ const Node* const rightChild = leftChild->buddy;
+ PrintDetailedMapNode(json, rightChild, childrenNodeSize);
+ }
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+}
+#endif // #if VMA_STATS_STRING_ENABLED
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaDeviceMemoryBlock
+
+VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator /*hAllocator*/) :
+ m_pMetadata(VMA_NULL),
+ m_MemoryTypeIndex(UINT32_MAX),
+ m_Id(0),
+ m_hMemory(VK_NULL_HANDLE),
+ m_MapCount(0),
+ m_pMappedData(VMA_NULL)
+{
+}
+
+void VmaDeviceMemoryBlock::Init(
+ VmaAllocator hAllocator,
+ uint32_t newMemoryTypeIndex,
+ VkDeviceMemory newMemory,
+ VkDeviceSize newSize,
+ uint32_t id,
+ uint32_t algorithm)
+{
+ VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
+
+ m_MemoryTypeIndex = newMemoryTypeIndex;
+ m_Id = id;
+ m_hMemory = newMemory;
+
+ switch(algorithm)
+ {
+ case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
+ m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator);
+ break;
+ case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT:
+ m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Buddy)(hAllocator);
+ break;
+ default:
+ VMA_ASSERT(0);
+ // Fall-through.
+ case 0:
+ m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Generic)(hAllocator);
+ }
+ m_pMetadata->Init(newSize);
+}
+
+void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator)
+{
+ // This is the most important assert in the entire library.
+ // Hitting it means you have some memory leak - unreleased VmaAllocation objects.
+ VMA_ASSERT(m_pMetadata->IsEmpty() && "Some allocations were not freed before destruction of this memory block!");
+
+ VMA_ASSERT(m_hMemory != VK_NULL_HANDLE);
+ allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory);
+ m_hMemory = VK_NULL_HANDLE;
+
+ vma_delete(allocator, m_pMetadata);
+ m_pMetadata = VMA_NULL;
+}
+
+bool VmaDeviceMemoryBlock::Validate() const
+{
+ VMA_VALIDATE((m_hMemory != VK_NULL_HANDLE) &&
+ (m_pMetadata->GetSize() != 0));
+
+ return m_pMetadata->Validate();
+}
+
+VkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator)
+{
+ void* pData = nullptr;
+ VkResult res = Map(hAllocator, 1, &pData);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+
+ res = m_pMetadata->CheckCorruption(pData);
+
+ Unmap(hAllocator, 1);
+
+ return res;
+}
+
+VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void** ppData)
+{
+ if(count == 0)
+ {
+ return VK_SUCCESS;
+ }
+
+ VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ if(m_MapCount != 0)
+ {
+ m_MapCount += count;
+ VMA_ASSERT(m_pMappedData != VMA_NULL);
+ if(ppData != VMA_NULL)
+ {
+ *ppData = m_pMappedData;
+ }
+ return VK_SUCCESS;
+ }
+ else
+ {
+ VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)(
+ hAllocator->m_hDevice,
+ m_hMemory,
+ 0, // offset
+ VK_WHOLE_SIZE,
+ 0, // flags
+ &m_pMappedData);
+ if(result == VK_SUCCESS)
+ {
+ if(ppData != VMA_NULL)
+ {
+ *ppData = m_pMappedData;
+ }
+ m_MapCount = count;
+ }
+ return result;
+ }
+}
+
+void VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator, uint32_t count)
+{
+ if(count == 0)
+ {
+ return;
+ }
+
+ VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ if(m_MapCount >= count)
+ {
+ m_MapCount -= count;
+ if(m_MapCount == 0)
+ {
+ m_pMappedData = VMA_NULL;
+ (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);
+ }
+ }
+ else
+ {
+ VMA_ASSERT(0 && "VkDeviceMemory block is being unmapped while it was not previously mapped.");
+ }
+}
+
+VkResult VmaDeviceMemoryBlock::WriteMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)
+{
+ VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION);
+ VMA_ASSERT(allocOffset >= VMA_DEBUG_MARGIN);
+
+ void* pData;
+ VkResult res = Map(hAllocator, 1, &pData);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+
+ VmaWriteMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN);
+ VmaWriteMagicValue(pData, allocOffset + allocSize);
+
+ Unmap(hAllocator, 1);
+
+ return VK_SUCCESS;
+}
+
+VkResult VmaDeviceMemoryBlock::ValidateMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)
+{
+ VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION);
+ VMA_ASSERT(allocOffset >= VMA_DEBUG_MARGIN);
+
+ void* pData;
+ VkResult res = Map(hAllocator, 1, &pData);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+
+ if(!VmaValidateMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE FREED ALLOCATION!");
+ }
+ else if(!VmaValidateMagicValue(pData, allocOffset + allocSize))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER FREED ALLOCATION!");
+ }
+
+ Unmap(hAllocator, 1);
+
+ return VK_SUCCESS;
+}
+
+VkResult VmaDeviceMemoryBlock::BindBufferMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkBuffer hBuffer)
+{
+ VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &&
+ hAllocation->GetBlock() == this);
+ // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.
+ VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ return hAllocator->GetVulkanFunctions().vkBindBufferMemory(
+ hAllocator->m_hDevice,
+ hBuffer,
+ m_hMemory,
+ hAllocation->GetOffset());
+}
+
+VkResult VmaDeviceMemoryBlock::BindImageMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkImage hImage)
+{
+ VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &&
+ hAllocation->GetBlock() == this);
+ // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.
+ VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ return hAllocator->GetVulkanFunctions().vkBindImageMemory(
+ hAllocator->m_hDevice,
+ hImage,
+ m_hMemory,
+ hAllocation->GetOffset());
+}
+
+static void InitStatInfo(VmaStatInfo& outInfo)
+{
+ memset(&outInfo, 0, sizeof(outInfo));
+ outInfo.allocationSizeMin = UINT64_MAX;
+ outInfo.unusedRangeSizeMin = UINT64_MAX;
+}
+
+// Adds statistics srcInfo into inoutInfo, like: inoutInfo += srcInfo.
+static void VmaAddStatInfo(VmaStatInfo& inoutInfo, const VmaStatInfo& srcInfo)
+{
+ inoutInfo.blockCount += srcInfo.blockCount;
+ inoutInfo.allocationCount += srcInfo.allocationCount;
+ inoutInfo.unusedRangeCount += srcInfo.unusedRangeCount;
+ inoutInfo.usedBytes += srcInfo.usedBytes;
+ inoutInfo.unusedBytes += srcInfo.unusedBytes;
+ inoutInfo.allocationSizeMin = VMA_MIN(inoutInfo.allocationSizeMin, srcInfo.allocationSizeMin);
+ inoutInfo.allocationSizeMax = VMA_MAX(inoutInfo.allocationSizeMax, srcInfo.allocationSizeMax);
+ inoutInfo.unusedRangeSizeMin = VMA_MIN(inoutInfo.unusedRangeSizeMin, srcInfo.unusedRangeSizeMin);
+ inoutInfo.unusedRangeSizeMax = VMA_MAX(inoutInfo.unusedRangeSizeMax, srcInfo.unusedRangeSizeMax);
+}
+
+static void VmaPostprocessCalcStatInfo(VmaStatInfo& inoutInfo)
+{
+ inoutInfo.allocationSizeAvg = (inoutInfo.allocationCount > 0) ?
+ VmaRoundDiv<VkDeviceSize>(inoutInfo.usedBytes, inoutInfo.allocationCount) : 0;
+ inoutInfo.unusedRangeSizeAvg = (inoutInfo.unusedRangeCount > 0) ?
+ VmaRoundDiv<VkDeviceSize>(inoutInfo.unusedBytes, inoutInfo.unusedRangeCount) : 0;
+}
+
+VmaPool_T::VmaPool_T(
+ VmaAllocator hAllocator,
+ const VmaPoolCreateInfo& createInfo,
+ VkDeviceSize preferredBlockSize) :
+ m_BlockVector(
+ hAllocator,
+ createInfo.memoryTypeIndex,
+ createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize,
+ createInfo.minBlockCount,
+ createInfo.maxBlockCount,
+ (createInfo.flags & VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
+ createInfo.frameInUseCount,
+ true, // isCustomPool
+ createInfo.blockSize != 0, // explicitBlockSize
+ createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK), // algorithm
+ m_Id(0)
+{
+}
+
+VmaPool_T::~VmaPool_T()
+{
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+VmaBlockVector::VmaBlockVector(
+ VmaAllocator hAllocator,
+ uint32_t memoryTypeIndex,
+ VkDeviceSize preferredBlockSize,
+ size_t minBlockCount,
+ size_t maxBlockCount,
+ VkDeviceSize bufferImageGranularity,
+ uint32_t frameInUseCount,
+ bool isCustomPool,
+ bool explicitBlockSize,
+ uint32_t algorithm) :
+ m_hAllocator(hAllocator),
+ m_MemoryTypeIndex(memoryTypeIndex),
+ m_PreferredBlockSize(preferredBlockSize),
+ m_MinBlockCount(minBlockCount),
+ m_MaxBlockCount(maxBlockCount),
+ m_BufferImageGranularity(bufferImageGranularity),
+ m_FrameInUseCount(frameInUseCount),
+ m_IsCustomPool(isCustomPool),
+ m_ExplicitBlockSize(explicitBlockSize),
+ m_Algorithm(algorithm),
+ m_HasEmptyBlock(false),
+ m_Blocks(VmaStlAllocator<VmaDeviceMemoryBlock*>(hAllocator->GetAllocationCallbacks())),
+ m_NextBlockId(0)
+{
+}
+
+VmaBlockVector::~VmaBlockVector()
+{
+ for(size_t i = m_Blocks.size(); i--; )
+ {
+ m_Blocks[i]->Destroy(m_hAllocator);
+ vma_delete(m_hAllocator, m_Blocks[i]);
+ }
+}
+
+VkResult VmaBlockVector::CreateMinBlocks()
+{
+ for(size_t i = 0; i < m_MinBlockCount; ++i)
+ {
+ VkResult res = CreateBlock(m_PreferredBlockSize, VMA_NULL);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+ }
+ return VK_SUCCESS;
+}
+
+void VmaBlockVector::GetPoolStats(VmaPoolStats* pStats)
+{
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+ const size_t blockCount = m_Blocks.size();
+
+ pStats->size = 0;
+ pStats->unusedSize = 0;
+ pStats->allocationCount = 0;
+ pStats->unusedRangeCount = 0;
+ pStats->unusedRangeSizeMax = 0;
+ pStats->blockCount = blockCount;
+
+ for(uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pBlock);
+ VMA_HEAVY_ASSERT(pBlock->Validate());
+ pBlock->m_pMetadata->AddPoolStats(*pStats);
+ }
+}
+
+bool VmaBlockVector::IsCorruptionDetectionEnabled() const
+{
+ const uint32_t requiredMemFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ return (VMA_DEBUG_DETECT_CORRUPTION != 0) &&
+ (VMA_DEBUG_MARGIN > 0) &&
+ (m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & requiredMemFlags) == requiredMemFlags;
+}
+
+static const uint32_t VMA_ALLOCATION_TRY_COUNT = 32;
+
+VkResult VmaBlockVector::Allocate(
+ VmaPool hCurrentPool,
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ size_t allocIndex;
+ VkResult res = VK_SUCCESS;
+
+ {
+ VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+ for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+ {
+ res = AllocatePage(
+ hCurrentPool,
+ currentFrameIndex,
+ size,
+ alignment,
+ createInfo,
+ suballocType,
+ pAllocations + allocIndex);
+ if(res != VK_SUCCESS)
+ {
+ break;
+ }
+ }
+ }
+
+ if(res != VK_SUCCESS)
+ {
+ // Free all already created allocations.
+ while(allocIndex--)
+ {
+ Free(pAllocations[allocIndex]);
+ }
+ memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+ }
+
+ return res;
+}
+
+VkResult VmaBlockVector::AllocatePage(
+ VmaPool hCurrentPool,
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ VmaAllocation* pAllocation)
+{
+ const bool isUpperAddress = (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0;
+ bool canMakeOtherLost = (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT) != 0;
+ const bool mapped = (createInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
+ const bool isUserDataString = (createInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0;
+ const bool canCreateNewBlock =
+ ((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0) &&
+ (m_Blocks.size() < m_MaxBlockCount);
+ uint32_t strategy = createInfo.flags & VMA_ALLOCATION_CREATE_STRATEGY_MASK;
+
+ // If linearAlgorithm is used, canMakeOtherLost is available only when used as ring buffer.
+ // Which in turn is available only when maxBlockCount = 1.
+ if(m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT && m_MaxBlockCount > 1)
+ {
+ canMakeOtherLost = false;
+ }
+
+ // Upper address can only be used with linear allocator and within single memory block.
+ if(isUpperAddress &&
+ (m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT || m_MaxBlockCount > 1))
+ {
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+ }
+
+ // Validate strategy.
+ switch(strategy)
+ {
+ case 0:
+ strategy = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT;
+ break;
+ case VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT:
+ case VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT:
+ case VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT:
+ break;
+ default:
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+ }
+
+ // Early reject: requested allocation size is larger that maximum block size for this block vector.
+ if(size + 2 * VMA_DEBUG_MARGIN > m_PreferredBlockSize)
+ {
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+
+ /*
+ Under certain condition, this whole section can be skipped for optimization, so
+ we move on directly to trying to allocate with canMakeOtherLost. That's the case
+ e.g. for custom pools with linear algorithm.
+ */
+ if(!canMakeOtherLost || canCreateNewBlock)
+ {
+ // 1. Search existing allocations. Try to allocate without making other allocations lost.
+ VmaAllocationCreateFlags allocFlagsCopy = createInfo.flags;
+ allocFlagsCopy &= ~VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
+
+ if(m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
+ {
+ // Use only last block.
+ if(!m_Blocks.empty())
+ {
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks.back();
+ VMA_ASSERT(pCurrBlock);
+ VkResult res = AllocateFromBlock(
+ pCurrBlock,
+ hCurrentPool,
+ currentFrameIndex,
+ size,
+ alignment,
+ allocFlagsCopy,
+ createInfo.pUserData,
+ suballocType,
+ strategy,
+ pAllocation);
+ if(res == VK_SUCCESS)
+ {
+ VMA_DEBUG_LOG(" Returned from last block #%u", (uint32_t)(m_Blocks.size() - 1));
+ return VK_SUCCESS;
+ }
+ }
+ }
+ else
+ {
+ if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+ {
+ // Forward order in m_Blocks - prefer blocks with smallest amount of free space.
+ for(size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex )
+ {
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pCurrBlock);
+ VkResult res = AllocateFromBlock(
+ pCurrBlock,
+ hCurrentPool,
+ currentFrameIndex,
+ size,
+ alignment,
+ allocFlagsCopy,
+ createInfo.pUserData,
+ suballocType,
+ strategy,
+ pAllocation);
+ if(res == VK_SUCCESS)
+ {
+ VMA_DEBUG_LOG(" Returned from existing block #%u", (uint32_t)blockIndex);
+ return VK_SUCCESS;
+ }
+ }
+ }
+ else // WORST_FIT, FIRST_FIT
+ {
+ // Backward order in m_Blocks - prefer blocks with largest amount of free space.
+ for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+ {
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pCurrBlock);
+ VkResult res = AllocateFromBlock(
+ pCurrBlock,
+ hCurrentPool,
+ currentFrameIndex,
+ size,
+ alignment,
+ allocFlagsCopy,
+ createInfo.pUserData,
+ suballocType,
+ strategy,
+ pAllocation);
+ if(res == VK_SUCCESS)
+ {
+ VMA_DEBUG_LOG(" Returned from existing block #%u", (uint32_t)blockIndex);
+ return VK_SUCCESS;
+ }
+ }
+ }
+ }
+
+ // 2. Try to create new block.
+ if(canCreateNewBlock)
+ {
+ // Calculate optimal size for new block.
+ VkDeviceSize newBlockSize = m_PreferredBlockSize;
+ uint32_t newBlockSizeShift = 0;
+ const uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3;
+
+ if(!m_ExplicitBlockSize)
+ {
+ // Allocate 1/8, 1/4, 1/2 as first blocks.
+ const VkDeviceSize maxExistingBlockSize = CalcMaxBlockSize();
+ for(uint32_t i = 0; i < NEW_BLOCK_SIZE_SHIFT_MAX; ++i)
+ {
+ const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
+ if(smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= size * 2)
+ {
+ newBlockSize = smallerNewBlockSize;
+ ++newBlockSizeShift;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ size_t newBlockIndex = 0;
+ VkResult res = CreateBlock(newBlockSize, &newBlockIndex);
+ // Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize.
+ if(!m_ExplicitBlockSize)
+ {
+ while(res < 0 && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX)
+ {
+ const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
+ if(smallerNewBlockSize >= size)
+ {
+ newBlockSize = smallerNewBlockSize;
+ ++newBlockSizeShift;
+ res = CreateBlock(newBlockSize, &newBlockIndex);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ if(res == VK_SUCCESS)
+ {
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex];
+ VMA_ASSERT(pBlock->m_pMetadata->GetSize() >= size);
+
+ res = AllocateFromBlock(
+ pBlock,
+ hCurrentPool,
+ currentFrameIndex,
+ size,
+ alignment,
+ allocFlagsCopy,
+ createInfo.pUserData,
+ suballocType,
+ strategy,
+ pAllocation);
+ if(res == VK_SUCCESS)
+ {
+ VMA_DEBUG_LOG(" Created new block Size=%llu", newBlockSize);
+ return VK_SUCCESS;
+ }
+ else
+ {
+ // Allocation from new block failed, possibly due to VMA_DEBUG_MARGIN or alignment.
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ }
+ }
+ }
+
+ // 3. Try to allocate from existing blocks with making other allocations lost.
+ if(canMakeOtherLost)
+ {
+ uint32_t tryIndex = 0;
+ for(; tryIndex < VMA_ALLOCATION_TRY_COUNT; ++tryIndex)
+ {
+ VmaDeviceMemoryBlock* pBestRequestBlock = VMA_NULL;
+ VmaAllocationRequest bestRequest = {};
+ VkDeviceSize bestRequestCost = VK_WHOLE_SIZE;
+
+ // 1. Search existing allocations.
+ if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+ {
+ // Forward order in m_Blocks - prefer blocks with smallest amount of free space.
+ for(size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex )
+ {
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pCurrBlock);
+ VmaAllocationRequest currRequest = {};
+ if(pCurrBlock->m_pMetadata->CreateAllocationRequest(
+ currentFrameIndex,
+ m_FrameInUseCount,
+ m_BufferImageGranularity,
+ size,
+ alignment,
+ (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0,
+ suballocType,
+ canMakeOtherLost,
+ strategy,
+ &currRequest))
+ {
+ const VkDeviceSize currRequestCost = currRequest.CalcCost();
+ if(pBestRequestBlock == VMA_NULL ||
+ currRequestCost < bestRequestCost)
+ {
+ pBestRequestBlock = pCurrBlock;
+ bestRequest = currRequest;
+ bestRequestCost = currRequestCost;
+
+ if(bestRequestCost == 0)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ else // WORST_FIT, FIRST_FIT
+ {
+ // Backward order in m_Blocks - prefer blocks with largest amount of free space.
+ for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+ {
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pCurrBlock);
+ VmaAllocationRequest currRequest = {};
+ if(pCurrBlock->m_pMetadata->CreateAllocationRequest(
+ currentFrameIndex,
+ m_FrameInUseCount,
+ m_BufferImageGranularity,
+ size,
+ alignment,
+ (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0,
+ suballocType,
+ canMakeOtherLost,
+ strategy,
+ &currRequest))
+ {
+ const VkDeviceSize currRequestCost = currRequest.CalcCost();
+ if(pBestRequestBlock == VMA_NULL ||
+ currRequestCost < bestRequestCost ||
+ strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
+ {
+ pBestRequestBlock = pCurrBlock;
+ bestRequest = currRequest;
+ bestRequestCost = currRequestCost;
+
+ if(bestRequestCost == 0 ||
+ strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if(pBestRequestBlock != VMA_NULL)
+ {
+ if(mapped)
+ {
+ VkResult res = pBestRequestBlock->Map(m_hAllocator, 1, VMA_NULL);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+ }
+
+ if(pBestRequestBlock->m_pMetadata->MakeRequestedAllocationsLost(
+ currentFrameIndex,
+ m_FrameInUseCount,
+ &bestRequest))
+ {
+ // We no longer have an empty Allocation.
+ if(pBestRequestBlock->m_pMetadata->IsEmpty())
+ {
+ m_HasEmptyBlock = false;
+ }
+ // Allocate from this pBlock.
+ *pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString);
+ pBestRequestBlock->m_pMetadata->Alloc(bestRequest, suballocType, size, isUpperAddress, *pAllocation);
+ (*pAllocation)->InitBlockAllocation(
+ hCurrentPool,
+ pBestRequestBlock,
+ bestRequest.offset,
+ alignment,
+ size,
+ suballocType,
+ mapped,
+ (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
+ VMA_HEAVY_ASSERT(pBestRequestBlock->Validate());
+ VMA_DEBUG_LOG(" Returned from existing allocation #%u", (uint32_t)blockIndex);
+ (*pAllocation)->SetUserData(m_hAllocator, createInfo.pUserData);
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+ {
+ m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
+ }
+ if(IsCorruptionDetectionEnabled())
+ {
+ VkResult res = pBestRequestBlock->WriteMagicValueAroundAllocation(m_hAllocator, bestRequest.offset, size);
+ (void) res;
+ VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
+ }
+ return VK_SUCCESS;
+ }
+ // else: Some allocations must have been touched while we are here. Next try.
+ }
+ else
+ {
+ // Could not find place in any of the blocks - break outer loop.
+ break;
+ }
+ }
+ /* Maximum number of tries exceeded - a very unlike event when many other
+ threads are simultaneously touching allocations making it impossible to make
+ lost at the same time as we try to allocate. */
+ if(tryIndex == VMA_ALLOCATION_TRY_COUNT)
+ {
+ return VK_ERROR_TOO_MANY_OBJECTS;
+ }
+ }
+
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+}
+
+void VmaBlockVector::Free(
+ VmaAllocation hAllocation)
+{
+ VmaDeviceMemoryBlock* pBlockToDelete = VMA_NULL;
+
+ // Scope for lock.
+ {
+ VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+ VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();
+
+ if(IsCorruptionDetectionEnabled())
+ {
+ VkResult res = pBlock->ValidateMagicValueAroundAllocation(m_hAllocator, hAllocation->GetOffset(), hAllocation->GetSize());
+ (void) res;
+ VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to validate magic value.");
+ }
+
+ if(hAllocation->IsPersistentMap())
+ {
+ pBlock->Unmap(m_hAllocator, 1);
+ }
+
+ pBlock->m_pMetadata->Free(hAllocation);
+ VMA_HEAVY_ASSERT(pBlock->Validate());
+
+ VMA_DEBUG_LOG(" Freed from MemoryTypeIndex=%u", memTypeIndex);
+
+ // pBlock became empty after this deallocation.
+ if(pBlock->m_pMetadata->IsEmpty())
+ {
+ // Already has empty Allocation. We don't want to have two, so delete this one.
+ if(m_HasEmptyBlock && m_Blocks.size() > m_MinBlockCount)
+ {
+ pBlockToDelete = pBlock;
+ Remove(pBlock);
+ }
+ // We now have first empty block.
+ else
+ {
+ m_HasEmptyBlock = true;
+ }
+ }
+ // pBlock didn't become empty, but we have another empty block - find and free that one.
+ // (This is optional, heuristics.)
+ else if(m_HasEmptyBlock)
+ {
+ VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back();
+ if(pLastBlock->m_pMetadata->IsEmpty() && m_Blocks.size() > m_MinBlockCount)
+ {
+ pBlockToDelete = pLastBlock;
+ m_Blocks.pop_back();
+ m_HasEmptyBlock = false;
+ }
+ }
+
+ IncrementallySortBlocks();
+ }
+
+ // Destruction of a free Allocation. Deferred until this point, outside of mutex
+ // lock, for performance reason.
+ if(pBlockToDelete != VMA_NULL)
+ {
+ VMA_DEBUG_LOG(" Deleted empty allocation");
+ pBlockToDelete->Destroy(m_hAllocator);
+ vma_delete(m_hAllocator, pBlockToDelete);
+ }
+}
+
+VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const
+{
+ VkDeviceSize result = 0;
+ for(size_t i = m_Blocks.size(); i--; )
+ {
+ result = VMA_MAX(result, m_Blocks[i]->m_pMetadata->GetSize());
+ if(result >= m_PreferredBlockSize)
+ {
+ break;
+ }
+ }
+ return result;
+}
+
+void VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock)
+{
+ for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+ {
+ if(m_Blocks[blockIndex] == pBlock)
+ {
+ VmaVectorRemove(m_Blocks, blockIndex);
+ return;
+ }
+ }
+ VMA_ASSERT(0);
+}
+
+void VmaBlockVector::IncrementallySortBlocks()
+{
+ if(m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
+ {
+ // Bubble sort only until first swap.
+ for(size_t i = 1; i < m_Blocks.size(); ++i)
+ {
+ if(m_Blocks[i - 1]->m_pMetadata->GetSumFreeSize() > m_Blocks[i]->m_pMetadata->GetSumFreeSize())
+ {
+ VMA_SWAP(m_Blocks[i - 1], m_Blocks[i]);
+ return;
+ }
+ }
+ }
+}
+
+VkResult VmaBlockVector::AllocateFromBlock(
+ VmaDeviceMemoryBlock* pBlock,
+ VmaPool hCurrentPool,
+ uint32_t currentFrameIndex,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ VmaAllocationCreateFlags allocFlags,
+ void* pUserData,
+ VmaSuballocationType suballocType,
+ uint32_t strategy,
+ VmaAllocation* pAllocation)
+{
+ VMA_ASSERT((allocFlags & VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT) == 0);
+ const bool isUpperAddress = (allocFlags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0;
+ const bool mapped = (allocFlags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
+ const bool isUserDataString = (allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0;
+
+ VmaAllocationRequest currRequest = {};
+ if(pBlock->m_pMetadata->CreateAllocationRequest(
+ currentFrameIndex,
+ m_FrameInUseCount,
+ m_BufferImageGranularity,
+ size,
+ alignment,
+ isUpperAddress,
+ suballocType,
+ false, // canMakeOtherLost
+ strategy,
+ &currRequest))
+ {
+ // Allocate from pCurrBlock.
+ VMA_ASSERT(currRequest.itemsToMakeLostCount == 0);
+
+ if(mapped)
+ {
+ VkResult res = pBlock->Map(m_hAllocator, 1, VMA_NULL);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+ }
+
+ // We no longer have an empty Allocation.
+ if(pBlock->m_pMetadata->IsEmpty())
+ {
+ m_HasEmptyBlock = false;
+ }
+
+ *pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString);
+ pBlock->m_pMetadata->Alloc(currRequest, suballocType, size, isUpperAddress, *pAllocation);
+ (*pAllocation)->InitBlockAllocation(
+ hCurrentPool,
+ pBlock,
+ currRequest.offset,
+ alignment,
+ size,
+ suballocType,
+ mapped,
+ (allocFlags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
+ VMA_HEAVY_ASSERT(pBlock->Validate());
+ (*pAllocation)->SetUserData(m_hAllocator, pUserData);
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+ {
+ m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
+ }
+ if(IsCorruptionDetectionEnabled())
+ {
+ VkResult res = pBlock->WriteMagicValueAroundAllocation(m_hAllocator, currRequest.offset, size);
+ (void) res;
+ VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
+ }
+ return VK_SUCCESS;
+ }
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+}
+
+VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex)
+{
+ VkMemoryAllocateInfo allocInfo = {};
+ allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocInfo.memoryTypeIndex = m_MemoryTypeIndex;
+ allocInfo.allocationSize = blockSize;
+ VkDeviceMemory mem = VK_NULL_HANDLE;
+ VkResult res = m_hAllocator->AllocateVulkanMemory(&allocInfo, &mem);
+ if(res < 0)
+ {
+ return res;
+ }
+
+ // New VkDeviceMemory successfully created.
+
+ // Create new Allocation for it.
+ VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator);
+ pBlock->Init(
+ m_hAllocator,
+ m_MemoryTypeIndex,
+ mem,
+ allocInfo.allocationSize,
+ m_NextBlockId++,
+ m_Algorithm);
+
+ m_Blocks.push_back(pBlock);
+ if(pNewBlockIndex != VMA_NULL)
+ {
+ *pNewBlockIndex = m_Blocks.size() - 1;
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaBlockVector::ApplyDefragmentationMovesCpu(
+ class VmaBlockVectorDefragmentationContext* pDefragCtx,
+ const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves)
+{
+ const size_t blockCount = m_Blocks.size();
+ const bool isNonCoherent = m_hAllocator->IsMemoryTypeNonCoherent(m_MemoryTypeIndex);
+
+ enum BLOCK_FLAG
+ {
+ BLOCK_FLAG_USED = 0x00000001,
+ BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION = 0x00000002,
+ };
+
+ struct BlockInfo
+ {
+ uint32_t flags;
+ void* pMappedData;
+ };
+ VmaVector< BlockInfo, VmaStlAllocator<BlockInfo> >
+ blockInfo(blockCount, VmaStlAllocator<BlockInfo>(m_hAllocator->GetAllocationCallbacks()));
+ memset(blockInfo.data(), 0, blockCount * sizeof(BlockInfo));
+
+ // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.
+ const size_t moveCount = moves.size();
+ for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ {
+ const VmaDefragmentationMove& move = moves[moveIndex];
+ blockInfo[move.srcBlockIndex].flags |= BLOCK_FLAG_USED;
+ blockInfo[move.dstBlockIndex].flags |= BLOCK_FLAG_USED;
+ }
+
+ VMA_ASSERT(pDefragCtx->res == VK_SUCCESS);
+
+ // Go over all blocks. Get mapped pointer or map if necessary.
+ for(size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex)
+ {
+ BlockInfo& currBlockInfo = blockInfo[blockIndex];
+ VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+ if((currBlockInfo.flags & BLOCK_FLAG_USED) != 0)
+ {
+ currBlockInfo.pMappedData = pBlock->GetMappedData();
+ // It is not originally mapped - map it.
+ if(currBlockInfo.pMappedData == VMA_NULL)
+ {
+ pDefragCtx->res = pBlock->Map(m_hAllocator, 1, &currBlockInfo.pMappedData);
+ if(pDefragCtx->res == VK_SUCCESS)
+ {
+ currBlockInfo.flags |= BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION;
+ }
+ }
+ }
+ }
+
+ // Go over all moves. Do actual data transfer.
+ if(pDefragCtx->res == VK_SUCCESS)
+ {
+ const VkDeviceSize nonCoherentAtomSize = m_hAllocator->m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
+ VkMappedMemoryRange memRange = {};
+ memRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+
+ for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ {
+ const VmaDefragmentationMove& move = moves[moveIndex];
+
+ const BlockInfo& srcBlockInfo = blockInfo[move.srcBlockIndex];
+ const BlockInfo& dstBlockInfo = blockInfo[move.dstBlockIndex];
+
+ VMA_ASSERT(srcBlockInfo.pMappedData && dstBlockInfo.pMappedData);
+
+ // Invalidate source.
+ if(isNonCoherent)
+ {
+ VmaDeviceMemoryBlock* const pSrcBlock = m_Blocks[move.srcBlockIndex];
+ memRange.memory = pSrcBlock->GetDeviceMemory();
+ memRange.offset = VmaAlignDown(move.srcOffset, nonCoherentAtomSize);
+ memRange.size = VMA_MIN(
+ VmaAlignUp(move.size + (move.srcOffset - memRange.offset), nonCoherentAtomSize),
+ pSrcBlock->m_pMetadata->GetSize() - memRange.offset);
+ (*m_hAllocator->GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hAllocator->m_hDevice, 1, &memRange);
+ }
+
+ // THE PLACE WHERE ACTUAL DATA COPY HAPPENS.
+ memmove(
+ reinterpret_cast<char*>(dstBlockInfo.pMappedData) + move.dstOffset,
+ reinterpret_cast<char*>(srcBlockInfo.pMappedData) + move.srcOffset,
+ static_cast<size_t>(move.size));
+
+ if(IsCorruptionDetectionEnabled())
+ {
+ VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset - VMA_DEBUG_MARGIN);
+ VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset + move.size);
+ }
+
+ // Flush destination.
+ if(isNonCoherent)
+ {
+ VmaDeviceMemoryBlock* const pDstBlock = m_Blocks[move.dstBlockIndex];
+ memRange.memory = pDstBlock->GetDeviceMemory();
+ memRange.offset = VmaAlignDown(move.dstOffset, nonCoherentAtomSize);
+ memRange.size = VMA_MIN(
+ VmaAlignUp(move.size + (move.dstOffset - memRange.offset), nonCoherentAtomSize),
+ pDstBlock->m_pMetadata->GetSize() - memRange.offset);
+ (*m_hAllocator->GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hAllocator->m_hDevice, 1, &memRange);
+ }
+ }
+ }
+
+ // Go over all blocks in reverse order. Unmap those that were mapped just for defragmentation.
+ // Regardless of pCtx->res == VK_SUCCESS.
+ for(size_t blockIndex = blockCount; blockIndex--; )
+ {
+ const BlockInfo& currBlockInfo = blockInfo[blockIndex];
+ if((currBlockInfo.flags & BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION) != 0)
+ {
+ VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+ pBlock->Unmap(m_hAllocator, 1);
+ }
+ }
+}
+
+void VmaBlockVector::ApplyDefragmentationMovesGpu(
+ class VmaBlockVectorDefragmentationContext* pDefragCtx,
+ const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkCommandBuffer commandBuffer)
+{
+ const size_t blockCount = m_Blocks.size();
+
+ pDefragCtx->blockContexts.resize(blockCount);
+ for (size_t i = 0; i < blockCount; ++i)
+ pDefragCtx->blockContexts[i] = VmaBlockDefragmentationContext();
+
+ // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.
+ const size_t moveCount = moves.size();
+ for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ {
+ const VmaDefragmentationMove& move = moves[moveIndex];
+ pDefragCtx->blockContexts[move.srcBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED;
+ pDefragCtx->blockContexts[move.dstBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED;
+ }
+
+ VMA_ASSERT(pDefragCtx->res == VK_SUCCESS);
+
+ // Go over all blocks. Create and bind buffer for whole block if necessary.
+ {
+ VkBufferCreateInfo bufCreateInfo = {};
+ bufCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+ for(size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex)
+ {
+ VmaBlockDefragmentationContext& currBlockCtx = pDefragCtx->blockContexts[blockIndex];
+ VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+ if((currBlockCtx.flags & VmaBlockDefragmentationContext::BLOCK_FLAG_USED) != 0)
+ {
+ bufCreateInfo.size = pBlock->m_pMetadata->GetSize();
+ pDefragCtx->res = (*m_hAllocator->GetVulkanFunctions().vkCreateBuffer)(
+ m_hAllocator->m_hDevice, &bufCreateInfo, m_hAllocator->GetAllocationCallbacks(), &currBlockCtx.hBuffer);
+ if(pDefragCtx->res == VK_SUCCESS)
+ {
+ pDefragCtx->res = (*m_hAllocator->GetVulkanFunctions().vkBindBufferMemory)(
+ m_hAllocator->m_hDevice, currBlockCtx.hBuffer, pBlock->GetDeviceMemory(), 0);
+ }
+ }
+ }
+ }
+
+ // Go over all moves. Post data transfer commands to command buffer.
+ if(pDefragCtx->res == VK_SUCCESS)
+ {
+ /*const VkDeviceSize nonCoherentAtomSize = m_hAllocator->m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
+ VkMappedMemoryRange memRange = {};
+ memRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;*/
+
+ for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ {
+ const VmaDefragmentationMove& move = moves[moveIndex];
+
+ const VmaBlockDefragmentationContext& srcBlockCtx = pDefragCtx->blockContexts[move.srcBlockIndex];
+ const VmaBlockDefragmentationContext& dstBlockCtx = pDefragCtx->blockContexts[move.dstBlockIndex];
+
+ VMA_ASSERT(srcBlockCtx.hBuffer && dstBlockCtx.hBuffer);
+
+ VkBufferCopy region = {
+ move.srcOffset,
+ move.dstOffset,
+ move.size };
+ (*m_hAllocator->GetVulkanFunctions().vkCmdCopyBuffer)(
+ commandBuffer, srcBlockCtx.hBuffer, dstBlockCtx.hBuffer, 1, &region);
+ }
+ }
+
+ // Save buffers to defrag context for later destruction.
+ if(pDefragCtx->res == VK_SUCCESS && moveCount > 0)
+ {
+ pDefragCtx->res = VK_NOT_READY;
+ }
+}
+
+void VmaBlockVector::FreeEmptyBlocks(VmaDefragmentationStats* pDefragmentationStats)
+{
+ m_HasEmptyBlock = false;
+ for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+ {
+ VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+ if(pBlock->m_pMetadata->IsEmpty())
+ {
+ if(m_Blocks.size() > m_MinBlockCount)
+ {
+ if(pDefragmentationStats != VMA_NULL)
+ {
+ ++pDefragmentationStats->deviceMemoryBlocksFreed;
+ pDefragmentationStats->bytesFreed += pBlock->m_pMetadata->GetSize();
+ }
+
+ VmaVectorRemove(m_Blocks, blockIndex);
+ pBlock->Destroy(m_hAllocator);
+ vma_delete(m_hAllocator, pBlock);
+ }
+ else
+ {
+ m_HasEmptyBlock = true;
+ }
+ }
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json)
+{
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+ json.BeginObject();
+
+ if(m_IsCustomPool)
+ {
+ json.WriteString("MemoryTypeIndex");
+ json.WriteNumber(m_MemoryTypeIndex);
+
+ json.WriteString("BlockSize");
+ json.WriteNumber(m_PreferredBlockSize);
+
+ json.WriteString("BlockCount");
+ json.BeginObject(true);
+ if(m_MinBlockCount > 0)
+ {
+ json.WriteString("Min");
+ json.WriteNumber((uint64_t)m_MinBlockCount);
+ }
+ if(m_MaxBlockCount < SIZE_MAX)
+ {
+ json.WriteString("Max");
+ json.WriteNumber((uint64_t)m_MaxBlockCount);
+ }
+ json.WriteString("Cur");
+ json.WriteNumber((uint64_t)m_Blocks.size());
+ json.EndObject();
+
+ if(m_FrameInUseCount > 0)
+ {
+ json.WriteString("FrameInUseCount");
+ json.WriteNumber(m_FrameInUseCount);
+ }
+
+ if(m_Algorithm != 0)
+ {
+ json.WriteString("Algorithm");
+ json.WriteString(VmaAlgorithmToStr(m_Algorithm));
+ }
+ }
+ else
+ {
+ json.WriteString("PreferredBlockSize");
+ json.WriteNumber(m_PreferredBlockSize);
+ }
+
+ json.WriteString("Blocks");
+ json.BeginObject();
+ for(size_t i = 0; i < m_Blocks.size(); ++i)
+ {
+ json.BeginString();
+ json.ContinueString(m_Blocks[i]->GetId());
+ json.EndString();
+
+ m_Blocks[i]->m_pMetadata->PrintDetailedMap(json);
+ }
+ json.EndObject();
+
+ json.EndObject();
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+void VmaBlockVector::Defragment(
+ class VmaBlockVectorDefragmentationContext* pCtx,
+ VmaDefragmentationStats* pStats,
+ VkDeviceSize& maxCpuBytesToMove, uint32_t& maxCpuAllocationsToMove,
+ VkDeviceSize& maxGpuBytesToMove, uint32_t& maxGpuAllocationsToMove,
+ VkCommandBuffer commandBuffer)
+{
+ pCtx->res = VK_SUCCESS;
+
+ const VkMemoryPropertyFlags memPropFlags =
+ m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags;
+ const bool isHostVisible = (memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
+ const bool isHostCoherent = (memPropFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
+
+ const bool canDefragmentOnCpu = maxCpuBytesToMove > 0 && maxCpuAllocationsToMove > 0 &&
+ isHostVisible;
+ const bool canDefragmentOnGpu = maxGpuBytesToMove > 0 && maxGpuAllocationsToMove > 0 &&
+ (VMA_DEBUG_DETECT_CORRUPTION == 0 || !(isHostVisible && isHostCoherent));
+
+ // There are options to defragment this memory type.
+ if(canDefragmentOnCpu || canDefragmentOnGpu)
+ {
+ bool defragmentOnGpu;
+ // There is only one option to defragment this memory type.
+ if(canDefragmentOnGpu != canDefragmentOnCpu)
+ {
+ defragmentOnGpu = canDefragmentOnGpu;
+ }
+ // Both options are available: Heuristics to choose the best one.
+ else
+ {
+ defragmentOnGpu = (memPropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0 ||
+ m_hAllocator->IsIntegratedGpu();
+ }
+
+ bool overlappingMoveSupported = !defragmentOnGpu;
+
+ if(m_hAllocator->m_UseMutex)
+ {
+ m_Mutex.LockWrite();
+ pCtx->mutexLocked = true;
+ }
+
+ pCtx->Begin(overlappingMoveSupported);
+
+ // Defragment.
+
+ const VkDeviceSize maxBytesToMove = defragmentOnGpu ? maxGpuBytesToMove : maxCpuBytesToMove;
+ const uint32_t maxAllocationsToMove = defragmentOnGpu ? maxGpuAllocationsToMove : maxCpuAllocationsToMove;
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> > moves =
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >(VmaStlAllocator<VmaDefragmentationMove>(m_hAllocator->GetAllocationCallbacks()));
+ pCtx->res = pCtx->GetAlgorithm()->Defragment(moves, maxBytesToMove, maxAllocationsToMove);
+
+ // Accumulate statistics.
+ if(pStats != VMA_NULL)
+ {
+ const VkDeviceSize bytesMoved = pCtx->GetAlgorithm()->GetBytesMoved();
+ const uint32_t allocationsMoved = pCtx->GetAlgorithm()->GetAllocationsMoved();
+ pStats->bytesMoved += bytesMoved;
+ pStats->allocationsMoved += allocationsMoved;
+ VMA_ASSERT(bytesMoved <= maxBytesToMove);
+ VMA_ASSERT(allocationsMoved <= maxAllocationsToMove);
+ if(defragmentOnGpu)
+ {
+ maxGpuBytesToMove -= bytesMoved;
+ maxGpuAllocationsToMove -= allocationsMoved;
+ }
+ else
+ {
+ maxCpuBytesToMove -= bytesMoved;
+ maxCpuAllocationsToMove -= allocationsMoved;
+ }
+ }
+
+ if(pCtx->res >= VK_SUCCESS)
+ {
+ if(defragmentOnGpu)
+ {
+ ApplyDefragmentationMovesGpu(pCtx, moves, commandBuffer);
+ }
+ else
+ {
+ ApplyDefragmentationMovesCpu(pCtx, moves);
+ }
+ }
+ }
+}
+
+void VmaBlockVector::DefragmentationEnd(
+ class VmaBlockVectorDefragmentationContext* pCtx,
+ VmaDefragmentationStats* pStats)
+{
+ // Destroy buffers.
+ for(size_t blockIndex = pCtx->blockContexts.size(); blockIndex--; )
+ {
+ VmaBlockDefragmentationContext& blockCtx = pCtx->blockContexts[blockIndex];
+ if(blockCtx.hBuffer)
+ {
+ (*m_hAllocator->GetVulkanFunctions().vkDestroyBuffer)(
+ m_hAllocator->m_hDevice, blockCtx.hBuffer, m_hAllocator->GetAllocationCallbacks());
+ }
+ }
+
+ if(pCtx->res >= VK_SUCCESS)
+ {
+ FreeEmptyBlocks(pStats);
+ }
+
+ if(pCtx->mutexLocked)
+ {
+ VMA_ASSERT(m_hAllocator->m_UseMutex);
+ m_Mutex.UnlockWrite();
+ }
+}
+
+size_t VmaBlockVector::CalcAllocationCount() const
+{
+ size_t result = 0;
+ for(size_t i = 0; i < m_Blocks.size(); ++i)
+ {
+ result += m_Blocks[i]->m_pMetadata->GetAllocationCount();
+ }
+ return result;
+}
+
+bool VmaBlockVector::IsBufferImageGranularityConflictPossible() const
+{
+ if(m_BufferImageGranularity == 1)
+ {
+ return false;
+ }
+ VmaSuballocationType lastSuballocType = VMA_SUBALLOCATION_TYPE_FREE;
+ for(size_t i = 0, count = m_Blocks.size(); i < count; ++i)
+ {
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[i];
+ VMA_ASSERT(m_Algorithm == 0);
+ VmaBlockMetadata_Generic* const pMetadata = (VmaBlockMetadata_Generic*)pBlock->m_pMetadata;
+ if(pMetadata->IsBufferImageGranularityConflictPossible(m_BufferImageGranularity, lastSuballocType))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void VmaBlockVector::MakePoolAllocationsLost(
+ uint32_t currentFrameIndex,
+ size_t* pLostAllocationCount)
+{
+ VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+ size_t lostAllocationCount = 0;
+ for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+ {
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pBlock);
+ lostAllocationCount += pBlock->m_pMetadata->MakeAllocationsLost(currentFrameIndex, m_FrameInUseCount);
+ }
+ if(pLostAllocationCount != VMA_NULL)
+ {
+ *pLostAllocationCount = lostAllocationCount;
+ }
+}
+
+VkResult VmaBlockVector::CheckCorruption()
+{
+ if(!IsCorruptionDetectionEnabled())
+ {
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+ }
+
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+ for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+ {
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pBlock);
+ VkResult res = pBlock->CheckCorruption(m_hAllocator);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+ }
+ return VK_SUCCESS;
+}
+
+void VmaBlockVector::AddStats(VmaStats* pStats)
+{
+ const uint32_t memTypeIndex = m_MemoryTypeIndex;
+ const uint32_t memHeapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(memTypeIndex);
+
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+ for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+ {
+ const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pBlock);
+ VMA_HEAVY_ASSERT(pBlock->Validate());
+ VmaStatInfo allocationStatInfo;
+ pBlock->m_pMetadata->CalcAllocationStatInfo(allocationStatInfo);
+ VmaAddStatInfo(pStats->total, allocationStatInfo);
+ VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo);
+ VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaDefragmentationAlgorithm_Generic members definition
+
+VmaDefragmentationAlgorithm_Generic::VmaDefragmentationAlgorithm_Generic(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex,
+ bool /*overlappingMoveSupported*/) :
+ VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
+ m_AllocationCount(0),
+ m_AllAllocations(false),
+ m_BytesMoved(0),
+ m_AllocationsMoved(0),
+ m_Blocks(VmaStlAllocator<BlockInfo*>(hAllocator->GetAllocationCallbacks()))
+{
+ // Create block info for each block.
+ const size_t blockCount = m_pBlockVector->m_Blocks.size();
+ for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ BlockInfo* pBlockInfo = vma_new(m_hAllocator, BlockInfo)(m_hAllocator->GetAllocationCallbacks());
+ pBlockInfo->m_OriginalBlockIndex = blockIndex;
+ pBlockInfo->m_pBlock = m_pBlockVector->m_Blocks[blockIndex];
+ m_Blocks.push_back(pBlockInfo);
+ }
+
+ // Sort them by m_pBlock pointer value.
+ VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockPointerLess());
+}
+
+VmaDefragmentationAlgorithm_Generic::~VmaDefragmentationAlgorithm_Generic()
+{
+ for(size_t i = m_Blocks.size(); i--; )
+ {
+ vma_delete(m_hAllocator, m_Blocks[i]);
+ }
+}
+
+void VmaDefragmentationAlgorithm_Generic::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged)
+{
+ // Now as we are inside VmaBlockVector::m_Mutex, we can make final check if this allocation was not lost.
+ if(hAlloc->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST)
+ {
+ VmaDeviceMemoryBlock* pBlock = hAlloc->GetBlock();
+ BlockInfoVector::iterator it = VmaBinaryFindFirstNotLess(m_Blocks.begin(), m_Blocks.end(), pBlock, BlockPointerLess());
+ if(it != m_Blocks.end() && (*it)->m_pBlock == pBlock)
+ {
+ AllocationInfo allocInfo = AllocationInfo(hAlloc, pChanged);
+ (*it)->m_Allocations.push_back(allocInfo);
+ }
+ else
+ {
+ VMA_ASSERT(0);
+ }
+
+ ++m_AllocationCount;
+ }
+}
+
+VkResult VmaDefragmentationAlgorithm_Generic::DefragmentRound(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove)
+{
+ if(m_Blocks.empty())
+ {
+ return VK_SUCCESS;
+ }
+
+ // This is a choice based on research.
+ // Option 1:
+ uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT;
+ // Option 2:
+ //uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT;
+ // Option 3:
+ //uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT;
+
+ size_t srcBlockMinIndex = 0;
+ // When FAST_ALGORITHM, move allocations from only last out of blocks that contain non-movable allocations.
+ /*
+ if(m_AlgorithmFlags & VMA_DEFRAGMENTATION_FAST_ALGORITHM_BIT)
+ {
+ const size_t blocksWithNonMovableCount = CalcBlocksWithNonMovableCount();
+ if(blocksWithNonMovableCount > 0)
+ {
+ srcBlockMinIndex = blocksWithNonMovableCount - 1;
+ }
+ }
+ */
+
+ size_t srcBlockIndex = m_Blocks.size() - 1;
+ size_t srcAllocIndex = SIZE_MAX;
+ for(;;)
+ {
+ // 1. Find next allocation to move.
+ // 1.1. Start from last to first m_Blocks - they are sorted from most "destination" to most "source".
+ // 1.2. Then start from last to first m_Allocations.
+ while(srcAllocIndex >= m_Blocks[srcBlockIndex]->m_Allocations.size())
+ {
+ if(m_Blocks[srcBlockIndex]->m_Allocations.empty())
+ {
+ // Finished: no more allocations to process.
+ if(srcBlockIndex == srcBlockMinIndex)
+ {
+ return VK_SUCCESS;
+ }
+ else
+ {
+ --srcBlockIndex;
+ srcAllocIndex = SIZE_MAX;
+ }
+ }
+ else
+ {
+ srcAllocIndex = m_Blocks[srcBlockIndex]->m_Allocations.size() - 1;
+ }
+ }
+
+ BlockInfo* pSrcBlockInfo = m_Blocks[srcBlockIndex];
+ AllocationInfo& allocInfo = pSrcBlockInfo->m_Allocations[srcAllocIndex];
+
+ const VkDeviceSize size = allocInfo.m_hAllocation->GetSize();
+ const VkDeviceSize srcOffset = allocInfo.m_hAllocation->GetOffset();
+ const VkDeviceSize alignment = allocInfo.m_hAllocation->GetAlignment();
+ const VmaSuballocationType suballocType = allocInfo.m_hAllocation->GetSuballocationType();
+
+ // 2. Try to find new place for this allocation in preceding or current block.
+ for(size_t dstBlockIndex = 0; dstBlockIndex <= srcBlockIndex; ++dstBlockIndex)
+ {
+ BlockInfo* pDstBlockInfo = m_Blocks[dstBlockIndex];
+ VmaAllocationRequest dstAllocRequest;
+ if(pDstBlockInfo->m_pBlock->m_pMetadata->CreateAllocationRequest(
+ m_CurrentFrameIndex,
+ m_pBlockVector->GetFrameInUseCount(),
+ m_pBlockVector->GetBufferImageGranularity(),
+ size,
+ alignment,
+ false, // upperAddress
+ suballocType,
+ false, // canMakeOtherLost
+ strategy,
+ &dstAllocRequest) &&
+ MoveMakesSense(
+ dstBlockIndex, dstAllocRequest.offset, srcBlockIndex, srcOffset))
+ {
+ VMA_ASSERT(dstAllocRequest.itemsToMakeLostCount == 0);
+
+ // Reached limit on number of allocations or bytes to move.
+ if((m_AllocationsMoved + 1 > maxAllocationsToMove) ||
+ (m_BytesMoved + size > maxBytesToMove))
+ {
+ return VK_SUCCESS;
+ }
+
+ VmaDefragmentationMove move;
+ move.srcBlockIndex = pSrcBlockInfo->m_OriginalBlockIndex;
+ move.dstBlockIndex = pDstBlockInfo->m_OriginalBlockIndex;
+ move.srcOffset = srcOffset;
+ move.dstOffset = dstAllocRequest.offset;
+ move.size = size;
+ moves.push_back(move);
+
+ pDstBlockInfo->m_pBlock->m_pMetadata->Alloc(
+ dstAllocRequest,
+ suballocType,
+ size,
+ false, // upperAddress
+ allocInfo.m_hAllocation);
+ pSrcBlockInfo->m_pBlock->m_pMetadata->FreeAtOffset(srcOffset);
+
+ allocInfo.m_hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlockInfo->m_pBlock, dstAllocRequest.offset);
+
+ if(allocInfo.m_pChanged != VMA_NULL)
+ {
+ *allocInfo.m_pChanged = VK_TRUE;
+ }
+
+ ++m_AllocationsMoved;
+ m_BytesMoved += size;
+
+ VmaVectorRemove(pSrcBlockInfo->m_Allocations, srcAllocIndex);
+
+ break;
+ }
+ }
+
+ // If not processed, this allocInfo remains in pBlockInfo->m_Allocations for next round.
+
+ if(srcAllocIndex > 0)
+ {
+ --srcAllocIndex;
+ }
+ else
+ {
+ if(srcBlockIndex > 0)
+ {
+ --srcBlockIndex;
+ srcAllocIndex = SIZE_MAX;
+ }
+ else
+ {
+ return VK_SUCCESS;
+ }
+ }
+ }
+}
+
+size_t VmaDefragmentationAlgorithm_Generic::CalcBlocksWithNonMovableCount() const
+{
+ size_t result = 0;
+ for(size_t i = 0; i < m_Blocks.size(); ++i)
+ {
+ if(m_Blocks[i]->m_HasNonMovableAllocations)
+ {
+ ++result;
+ }
+ }
+ return result;
+}
+
+VkResult VmaDefragmentationAlgorithm_Generic::Defragment(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove)
+{
+ if(!m_AllAllocations && m_AllocationCount == 0)
+ {
+ return VK_SUCCESS;
+ }
+
+ const size_t blockCount = m_Blocks.size();
+ for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ BlockInfo* pBlockInfo = m_Blocks[blockIndex];
+
+ if(m_AllAllocations)
+ {
+ VmaBlockMetadata_Generic* pMetadata = (VmaBlockMetadata_Generic*)pBlockInfo->m_pBlock->m_pMetadata;
+ for(VmaSuballocationList::const_iterator it = pMetadata->m_Suballocations.begin();
+ it != pMetadata->m_Suballocations.end();
+ ++it)
+ {
+ if(it->type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ AllocationInfo allocInfo = AllocationInfo(it->hAllocation, VMA_NULL);
+ pBlockInfo->m_Allocations.push_back(allocInfo);
+ }
+ }
+ }
+
+ pBlockInfo->CalcHasNonMovableAllocations();
+
+ // This is a choice based on research.
+ // Option 1:
+ pBlockInfo->SortAllocationsByOffsetDescending();
+ // Option 2:
+ //pBlockInfo->SortAllocationsBySizeDescending();
+ }
+
+ // Sort m_Blocks this time by the main criterium, from most "destination" to most "source" blocks.
+ VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockInfoCompareMoveDestination());
+
+ // This is a choice based on research.
+ const uint32_t roundCount = 2;
+
+ // Execute defragmentation rounds (the main part).
+ VkResult result = VK_SUCCESS;
+ for(uint32_t round = 0; (round < roundCount) && (result == VK_SUCCESS); ++round)
+ {
+ result = DefragmentRound(moves, maxBytesToMove, maxAllocationsToMove);
+ }
+
+ return result;
+}
+
+bool VmaDefragmentationAlgorithm_Generic::MoveMakesSense(
+ size_t dstBlockIndex, VkDeviceSize dstOffset,
+ size_t srcBlockIndex, VkDeviceSize srcOffset)
+{
+ if(dstBlockIndex < srcBlockIndex)
+ {
+ return true;
+ }
+ if(dstBlockIndex > srcBlockIndex)
+ {
+ return false;
+ }
+ if(dstOffset < srcOffset)
+ {
+ return true;
+ }
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaDefragmentationAlgorithm_Fast
+
+VmaDefragmentationAlgorithm_Fast::VmaDefragmentationAlgorithm_Fast(
+ VmaAllocator hAllocator,
+ VmaBlockVector* pBlockVector,
+ uint32_t currentFrameIndex,
+ bool overlappingMoveSupported) :
+ VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
+ m_OverlappingMoveSupported(overlappingMoveSupported),
+ m_AllocationCount(0),
+ m_AllAllocations(false),
+ m_BytesMoved(0),
+ m_AllocationsMoved(0),
+ m_BlockInfos(VmaStlAllocator<BlockInfo>(hAllocator->GetAllocationCallbacks()))
+{
+ VMA_ASSERT(VMA_DEBUG_MARGIN == 0);
+
+}
+
+VmaDefragmentationAlgorithm_Fast::~VmaDefragmentationAlgorithm_Fast()
+{
+}
+
+VkResult VmaDefragmentationAlgorithm_Fast::Defragment(
+ VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+ VkDeviceSize maxBytesToMove,
+ uint32_t maxAllocationsToMove)
+{
+ VMA_ASSERT(m_AllAllocations || m_pBlockVector->CalcAllocationCount() == m_AllocationCount);
+
+ const size_t blockCount = m_pBlockVector->GetBlockCount();
+ if(blockCount == 0 || maxBytesToMove == 0 || maxAllocationsToMove == 0)
+ {
+ return VK_SUCCESS;
+ }
+
+ PreprocessMetadata();
+
+ // Sort blocks in order from most destination.
+
+ m_BlockInfos.resize(blockCount);
+ for(size_t i = 0; i < blockCount; ++i)
+ {
+ m_BlockInfos[i].origBlockIndex = i;
+ }
+
+ VMA_SORT(m_BlockInfos.begin(), m_BlockInfos.end(), [this](const BlockInfo& lhs, const BlockInfo& rhs) -> bool {
+ return m_pBlockVector->GetBlock(lhs.origBlockIndex)->m_pMetadata->GetSumFreeSize() <
+ m_pBlockVector->GetBlock(rhs.origBlockIndex)->m_pMetadata->GetSumFreeSize();
+ });
+
+ // THE MAIN ALGORITHM
+
+ FreeSpaceDatabase freeSpaceDb;
+
+ size_t dstBlockInfoIndex = 0;
+ size_t dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex;
+ VmaDeviceMemoryBlock* pDstBlock = m_pBlockVector->GetBlock(dstOrigBlockIndex);
+ VmaBlockMetadata_Generic* pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock->m_pMetadata;
+ VkDeviceSize dstBlockSize = pDstMetadata->GetSize();
+ VkDeviceSize dstOffset = 0;
+
+ bool end = false;
+ for(size_t srcBlockInfoIndex = 0; !end && srcBlockInfoIndex < blockCount; ++srcBlockInfoIndex)
+ {
+ const size_t srcOrigBlockIndex = m_BlockInfos[srcBlockInfoIndex].origBlockIndex;
+ VmaDeviceMemoryBlock* const pSrcBlock = m_pBlockVector->GetBlock(srcOrigBlockIndex);
+ VmaBlockMetadata_Generic* const pSrcMetadata = (VmaBlockMetadata_Generic*)pSrcBlock->m_pMetadata;
+ for(VmaSuballocationList::iterator srcSuballocIt = pSrcMetadata->m_Suballocations.begin();
+ !end && srcSuballocIt != pSrcMetadata->m_Suballocations.end(); )
+ {
+ VmaAllocation_T* const pAlloc = srcSuballocIt->hAllocation;
+ const VkDeviceSize srcAllocAlignment = pAlloc->GetAlignment();
+ const VkDeviceSize srcAllocSize = srcSuballocIt->size;
+ if(m_AllocationsMoved == maxAllocationsToMove ||
+ m_BytesMoved + srcAllocSize > maxBytesToMove)
+ {
+ end = true;
+ break;
+ }
+ const VkDeviceSize srcAllocOffset = srcSuballocIt->offset;
+
+ // Try to place it in one of free spaces from the database.
+ size_t freeSpaceInfoIndex;
+ VkDeviceSize dstAllocOffset;
+ if(freeSpaceDb.Fetch(srcAllocAlignment, srcAllocSize,
+ freeSpaceInfoIndex, dstAllocOffset))
+ {
+ size_t freeSpaceOrigBlockIndex = m_BlockInfos[freeSpaceInfoIndex].origBlockIndex;
+ VmaDeviceMemoryBlock* pFreeSpaceBlock = m_pBlockVector->GetBlock(freeSpaceOrigBlockIndex);
+ VmaBlockMetadata_Generic* pFreeSpaceMetadata = (VmaBlockMetadata_Generic*)pFreeSpaceBlock->m_pMetadata;
+ /*VkDeviceSize freeSpaceBlockSize = pFreeSpaceMetadata->GetSize();*/
+
+ // Same block
+ if(freeSpaceInfoIndex == srcBlockInfoIndex)
+ {
+ VMA_ASSERT(dstAllocOffset <= srcAllocOffset);
+
+ // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
+
+ VmaSuballocation suballoc = *srcSuballocIt;
+ suballoc.offset = dstAllocOffset;
+ suballoc.hAllocation->ChangeOffset(dstAllocOffset);
+ m_BytesMoved += srcAllocSize;
+ ++m_AllocationsMoved;
+
+ VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
+ ++nextSuballocIt;
+ pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
+ srcSuballocIt = nextSuballocIt;
+
+ InsertSuballoc(pFreeSpaceMetadata, suballoc);
+
+ VmaDefragmentationMove move = {
+ srcOrigBlockIndex, freeSpaceOrigBlockIndex,
+ srcAllocOffset, dstAllocOffset,
+ srcAllocSize };
+ moves.push_back(move);
+ }
+ // Different block
+ else
+ {
+ // MOVE OPTION 2: Move the allocation to a different block.
+
+ VMA_ASSERT(freeSpaceInfoIndex < srcBlockInfoIndex);
+
+ VmaSuballocation suballoc = *srcSuballocIt;
+ suballoc.offset = dstAllocOffset;
+ suballoc.hAllocation->ChangeBlockAllocation(m_hAllocator, pFreeSpaceBlock, dstAllocOffset);
+ m_BytesMoved += srcAllocSize;
+ ++m_AllocationsMoved;
+
+ VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
+ ++nextSuballocIt;
+ pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
+ srcSuballocIt = nextSuballocIt;
+
+ InsertSuballoc(pFreeSpaceMetadata, suballoc);
+
+ VmaDefragmentationMove move = {
+ srcOrigBlockIndex, freeSpaceOrigBlockIndex,
+ srcAllocOffset, dstAllocOffset,
+ srcAllocSize };
+ moves.push_back(move);
+ }
+ }
+ else
+ {
+ dstAllocOffset = VmaAlignUp(dstOffset, srcAllocAlignment);
+
+ // If the allocation doesn't fit before the end of dstBlock, forward to next block.
+ while(dstBlockInfoIndex < srcBlockInfoIndex &&
+ dstAllocOffset + srcAllocSize > dstBlockSize)
+ {
+ // But before that, register remaining free space at the end of dst block.
+ freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, dstBlockSize - dstOffset);
+
+ ++dstBlockInfoIndex;
+ dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex;
+ pDstBlock = m_pBlockVector->GetBlock(dstOrigBlockIndex);
+ pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock->m_pMetadata;
+ dstBlockSize = pDstMetadata->GetSize();
+ dstOffset = 0;
+ dstAllocOffset = 0;
+ }
+
+ // Same block
+ if(dstBlockInfoIndex == srcBlockInfoIndex)
+ {
+ VMA_ASSERT(dstAllocOffset <= srcAllocOffset);
+
+ const bool overlap = dstAllocOffset + srcAllocSize > srcAllocOffset;
+
+ bool skipOver = overlap;
+ if(overlap && m_OverlappingMoveSupported && dstAllocOffset < srcAllocOffset)
+ {
+ // If destination and source place overlap, skip if it would move it
+ // by only < 1/64 of its size.
+ skipOver = (srcAllocOffset - dstAllocOffset) * 64 < srcAllocSize;
+ }
+
+ if(skipOver)
+ {
+ freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, srcAllocOffset - dstOffset);
+
+ dstOffset = srcAllocOffset + srcAllocSize;
+ ++srcSuballocIt;
+ }
+ // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
+ else
+ {
+ srcSuballocIt->offset = dstAllocOffset;
+ srcSuballocIt->hAllocation->ChangeOffset(dstAllocOffset);
+ dstOffset = dstAllocOffset + srcAllocSize;
+ m_BytesMoved += srcAllocSize;
+ ++m_AllocationsMoved;
+ ++srcSuballocIt;
+ VmaDefragmentationMove move = {
+ srcOrigBlockIndex, dstOrigBlockIndex,
+ srcAllocOffset, dstAllocOffset,
+ srcAllocSize };
+ moves.push_back(move);
+ }
+ }
+ // Different block
+ else
+ {
+ // MOVE OPTION 2: Move the allocation to a different block.
+
+ VMA_ASSERT(dstBlockInfoIndex < srcBlockInfoIndex);
+ VMA_ASSERT(dstAllocOffset + srcAllocSize <= dstBlockSize);
+
+ VmaSuballocation suballoc = *srcSuballocIt;
+ suballoc.offset = dstAllocOffset;
+ suballoc.hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlock, dstAllocOffset);
+ dstOffset = dstAllocOffset + srcAllocSize;
+ m_BytesMoved += srcAllocSize;
+ ++m_AllocationsMoved;
+
+ VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
+ ++nextSuballocIt;
+ pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
+ srcSuballocIt = nextSuballocIt;
+
+ pDstMetadata->m_Suballocations.push_back(suballoc);
+
+ VmaDefragmentationMove move = {
+ srcOrigBlockIndex, dstOrigBlockIndex,
+ srcAllocOffset, dstAllocOffset,
+ srcAllocSize };
+ moves.push_back(move);
+ }
+ }
+ }
+ }
+
+ m_BlockInfos.clear();
+
+ PostprocessMetadata();
+
+ return VK_SUCCESS;
+}
+
+void VmaDefragmentationAlgorithm_Fast::PreprocessMetadata()
+{
+ const size_t blockCount = m_pBlockVector->GetBlockCount();
+ for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ VmaBlockMetadata_Generic* const pMetadata =
+ (VmaBlockMetadata_Generic*)m_pBlockVector->GetBlock(blockIndex)->m_pMetadata;
+ pMetadata->m_FreeCount = 0;
+ pMetadata->m_SumFreeSize = pMetadata->GetSize();
+ pMetadata->m_FreeSuballocationsBySize.clear();
+ for(VmaSuballocationList::iterator it = pMetadata->m_Suballocations.begin();
+ it != pMetadata->m_Suballocations.end(); )
+ {
+ if(it->type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ VmaSuballocationList::iterator nextIt = it;
+ ++nextIt;
+ pMetadata->m_Suballocations.erase(it);
+ it = nextIt;
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ }
+}
+
+void VmaDefragmentationAlgorithm_Fast::PostprocessMetadata()
+{
+ const size_t blockCount = m_pBlockVector->GetBlockCount();
+ for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ VmaBlockMetadata_Generic* const pMetadata =
+ (VmaBlockMetadata_Generic*)m_pBlockVector->GetBlock(blockIndex)->m_pMetadata;
+ const VkDeviceSize blockSize = pMetadata->GetSize();
+
+ // No allocations in this block - entire area is free.
+ if(pMetadata->m_Suballocations.empty())
+ {
+ pMetadata->m_FreeCount = 1;
+ //pMetadata->m_SumFreeSize is already set to blockSize.
+ VmaSuballocation suballoc = {
+ 0, // offset
+ blockSize, // size
+ VMA_NULL, // hAllocation
+ VMA_SUBALLOCATION_TYPE_FREE };
+ pMetadata->m_Suballocations.push_back(suballoc);
+ pMetadata->RegisterFreeSuballocation(pMetadata->m_Suballocations.begin());
+ }
+ // There are some allocations in this block.
+ else
+ {
+ VkDeviceSize offset = 0;
+ VmaSuballocationList::iterator it;
+ for(it = pMetadata->m_Suballocations.begin();
+ it != pMetadata->m_Suballocations.end();
+ ++it)
+ {
+ VMA_ASSERT(it->type != VMA_SUBALLOCATION_TYPE_FREE);
+ VMA_ASSERT(it->offset >= offset);
+
+ // Need to insert preceding free space.
+ if(it->offset > offset)
+ {
+ ++pMetadata->m_FreeCount;
+ const VkDeviceSize freeSize = it->offset - offset;
+ VmaSuballocation suballoc = {
+ offset, // offset
+ freeSize, // size
+ VMA_NULL, // hAllocation
+ VMA_SUBALLOCATION_TYPE_FREE };
+ VmaSuballocationList::iterator precedingFreeIt = pMetadata->m_Suballocations.insert(it, suballoc);
+ if(freeSize >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ pMetadata->m_FreeSuballocationsBySize.push_back(precedingFreeIt);
+ }
+ }
+
+ pMetadata->m_SumFreeSize -= it->size;
+ offset = it->offset + it->size;
+ }
+
+ // Need to insert trailing free space.
+ if(offset < blockSize)
+ {
+ ++pMetadata->m_FreeCount;
+ const VkDeviceSize freeSize = blockSize - offset;
+ VmaSuballocation suballoc = {
+ offset, // offset
+ freeSize, // size
+ VMA_NULL, // hAllocation
+ VMA_SUBALLOCATION_TYPE_FREE };
+ VMA_ASSERT(it == pMetadata->m_Suballocations.end());
+ VmaSuballocationList::iterator trailingFreeIt = pMetadata->m_Suballocations.insert(it, suballoc);
+ if(freeSize > VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ {
+ pMetadata->m_FreeSuballocationsBySize.push_back(trailingFreeIt);
+ }
+ }
+
+ VMA_SORT(
+ pMetadata->m_FreeSuballocationsBySize.begin(),
+ pMetadata->m_FreeSuballocationsBySize.end(),
+ VmaSuballocationItemSizeLess());
+ }
+
+ VMA_HEAVY_ASSERT(pMetadata->Validate());
+ }
+}
+
+void VmaDefragmentationAlgorithm_Fast::InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, const VmaSuballocation& suballoc)
+{
+ // TODO: Optimize somehow. Remember iterator instead of searching for it linearly.
+ VmaSuballocationList::iterator it = pMetadata->m_Suballocations.begin();
+ while(it != pMetadata->m_Suballocations.end())
+ {
+ if(it->offset < suballoc.offset)
+ {
+ ++it;
+ }
+ }
+ pMetadata->m_Suballocations.insert(it, suballoc);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaBlockVectorDefragmentationContext
+
+VmaBlockVectorDefragmentationContext::VmaBlockVectorDefragmentationContext(
+ VmaAllocator hAllocator,
+ VmaPool hCustomPool,
+ VmaBlockVector* pBlockVector,
+ uint32_t currFrameIndex,
+ uint32_t /*algorithmFlags*/) :
+ res(VK_SUCCESS),
+ mutexLocked(false),
+ blockContexts(VmaStlAllocator<VmaBlockDefragmentationContext>(hAllocator->GetAllocationCallbacks())),
+ m_hAllocator(hAllocator),
+ m_hCustomPool(hCustomPool),
+ m_pBlockVector(pBlockVector),
+ m_CurrFrameIndex(currFrameIndex),
+ /*m_AlgorithmFlags(algorithmFlags),*/
+ m_pAlgorithm(VMA_NULL),
+ m_Allocations(VmaStlAllocator<AllocInfo>(hAllocator->GetAllocationCallbacks())),
+ m_AllAllocations(false)
+{
+}
+
+VmaBlockVectorDefragmentationContext::~VmaBlockVectorDefragmentationContext()
+{
+ vma_delete(m_hAllocator, m_pAlgorithm);
+}
+
+void VmaBlockVectorDefragmentationContext::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged)
+{
+ AllocInfo info = { hAlloc, pChanged };
+ m_Allocations.push_back(info);
+}
+
+void VmaBlockVectorDefragmentationContext::Begin(bool overlappingMoveSupported)
+{
+ const bool allAllocations = m_AllAllocations ||
+ m_Allocations.size() == m_pBlockVector->CalcAllocationCount();
+
+ /********************************
+ HERE IS THE CHOICE OF DEFRAGMENTATION ALGORITHM.
+ ********************************/
+
+ /*
+ Fast algorithm is supported only when certain criteria are met:
+ - VMA_DEBUG_MARGIN is 0.
+ - All allocations in this block vector are moveable.
+ - There is no possibility of image/buffer granularity conflict.
+ */
+ if(VMA_DEBUG_MARGIN == 0 &&
+ allAllocations &&
+ !m_pBlockVector->IsBufferImageGranularityConflictPossible())
+ {
+ m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Fast)(
+ m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);
+ }
+ else
+ {
+ m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Generic)(
+ m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);
+ }
+
+ if(allAllocations)
+ {
+ m_pAlgorithm->AddAll();
+ }
+ else
+ {
+ for(size_t i = 0, count = m_Allocations.size(); i < count; ++i)
+ {
+ m_pAlgorithm->AddAllocation(m_Allocations[i].hAlloc, m_Allocations[i].pChanged);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaDefragmentationContext
+
+VmaDefragmentationContext_T::VmaDefragmentationContext_T(
+ VmaAllocator hAllocator,
+ uint32_t currFrameIndex,
+ uint32_t flags,
+ VmaDefragmentationStats* pStats) :
+ m_hAllocator(hAllocator),
+ m_CurrFrameIndex(currFrameIndex),
+ m_Flags(flags),
+ m_pStats(pStats),
+ m_CustomPoolContexts(VmaStlAllocator<VmaBlockVectorDefragmentationContext*>(hAllocator->GetAllocationCallbacks()))
+{
+ memset(m_DefaultPoolContexts, 0, sizeof(m_DefaultPoolContexts));
+}
+
+VmaDefragmentationContext_T::~VmaDefragmentationContext_T()
+{
+ for(size_t i = m_CustomPoolContexts.size(); i--; )
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[i];
+ pBlockVectorCtx->GetBlockVector()->DefragmentationEnd(pBlockVectorCtx, m_pStats);
+ vma_delete(m_hAllocator, pBlockVectorCtx);
+ }
+ for(size_t i = m_hAllocator->m_MemProps.memoryTypeCount; i--; )
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[i];
+ if(pBlockVectorCtx)
+ {
+ pBlockVectorCtx->GetBlockVector()->DefragmentationEnd(pBlockVectorCtx, m_pStats);
+ vma_delete(m_hAllocator, pBlockVectorCtx);
+ }
+ }
+}
+
+void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, VmaPool* pPools)
+{
+ for(uint32_t poolIndex = 0; poolIndex < poolCount; ++poolIndex)
+ {
+ VmaPool pool = pPools[poolIndex];
+ VMA_ASSERT(pool);
+ // Pools with algorithm other than default are not defragmented.
+ if(pool->m_BlockVector.GetAlgorithm() == 0)
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
+
+ for(size_t i = m_CustomPoolContexts.size(); i--; )
+ {
+ if(m_CustomPoolContexts[i]->GetCustomPool() == pool)
+ {
+ pBlockVectorDefragCtx = m_CustomPoolContexts[i];
+ break;
+ }
+ }
+
+ if(!pBlockVectorDefragCtx)
+ {
+ pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
+ m_hAllocator,
+ pool,
+ &pool->m_BlockVector,
+ m_CurrFrameIndex,
+ m_Flags);
+ m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
+ }
+
+ pBlockVectorDefragCtx->AddAll();
+ }
+ }
+}
+
+void VmaDefragmentationContext_T::AddAllocations(
+ uint32_t allocationCount,
+ VmaAllocation* pAllocations,
+ VkBool32* pAllocationsChanged)
+{
+ // Dispatch pAllocations among defragmentators. Create them when necessary.
+ for(uint32_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+ {
+ const VmaAllocation hAlloc = pAllocations[allocIndex];
+ VMA_ASSERT(hAlloc);
+ // DedicatedAlloc cannot be defragmented.
+ if((hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK) &&
+ // Lost allocation cannot be defragmented.
+ (hAlloc->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST))
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
+
+ const VmaPool hAllocPool = hAlloc->GetPool();
+ // This allocation belongs to custom pool.
+ if(hAllocPool != VK_NULL_HANDLE)
+ {
+ // Pools with algorithm other than default are not defragmented.
+ if(hAllocPool->m_BlockVector.GetAlgorithm() == 0)
+ {
+ for(size_t i = m_CustomPoolContexts.size(); i--; )
+ {
+ if(m_CustomPoolContexts[i]->GetCustomPool() == hAllocPool)
+ {
+ pBlockVectorDefragCtx = m_CustomPoolContexts[i];
+ break;
+ }
+ }
+ if(!pBlockVectorDefragCtx)
+ {
+ pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
+ m_hAllocator,
+ hAllocPool,
+ &hAllocPool->m_BlockVector,
+ m_CurrFrameIndex,
+ m_Flags);
+ m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
+ }
+ }
+ }
+ // This allocation belongs to default pool.
+ else
+ {
+ const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex();
+ pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex];
+ if(!pBlockVectorDefragCtx)
+ {
+ pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
+ m_hAllocator,
+ VMA_NULL, // hCustomPool
+ m_hAllocator->m_pBlockVectors[memTypeIndex],
+ m_CurrFrameIndex,
+ m_Flags);
+ m_DefaultPoolContexts[memTypeIndex] = pBlockVectorDefragCtx;
+ }
+ }
+
+ if(pBlockVectorDefragCtx)
+ {
+ VkBool32* const pChanged = (pAllocationsChanged != VMA_NULL) ?
+ &pAllocationsChanged[allocIndex] : VMA_NULL;
+ pBlockVectorDefragCtx->AddAllocation(hAlloc, pChanged);
+ }
+ }
+ }
+}
+
+VkResult VmaDefragmentationContext_T::Defragment(
+ VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove,
+ VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove,
+ VkCommandBuffer commandBuffer, VmaDefragmentationStats* pStats)
+{
+ if(pStats)
+ {
+ memset(pStats, 0, sizeof(VmaDefragmentationStats));
+ }
+
+ if(commandBuffer == VK_NULL_HANDLE)
+ {
+ maxGpuBytesToMove = 0;
+ maxGpuAllocationsToMove = 0;
+ }
+
+ VkResult res = VK_SUCCESS;
+
+ // Process default pools.
+ for(uint32_t memTypeIndex = 0;
+ memTypeIndex < m_hAllocator->GetMemoryTypeCount() && res >= VK_SUCCESS;
+ ++memTypeIndex)
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];
+ if(pBlockVectorCtx)
+ {
+ VMA_ASSERT(pBlockVectorCtx->GetBlockVector());
+ pBlockVectorCtx->GetBlockVector()->Defragment(
+ pBlockVectorCtx,
+ pStats,
+ maxCpuBytesToMove, maxCpuAllocationsToMove,
+ maxGpuBytesToMove, maxGpuAllocationsToMove,
+ commandBuffer);
+ if(pBlockVectorCtx->res != VK_SUCCESS)
+ {
+ res = pBlockVectorCtx->res;
+ }
+ }
+ }
+
+ // Process custom pools.
+ for(size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();
+ customCtxIndex < customCtxCount && res >= VK_SUCCESS;
+ ++customCtxIndex)
+ {
+ VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];
+ VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector());
+ pBlockVectorCtx->GetBlockVector()->Defragment(
+ pBlockVectorCtx,
+ pStats,
+ maxCpuBytesToMove, maxCpuAllocationsToMove,
+ maxGpuBytesToMove, maxGpuAllocationsToMove,
+ commandBuffer);
+ if(pBlockVectorCtx->res != VK_SUCCESS)
+ {
+ res = pBlockVectorCtx->res;
+ }
+ }
+
+ return res;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaRecorder
+
+#if VMA_RECORDING_ENABLED
+
+VmaRecorder::VmaRecorder() :
+ m_UseMutex(true),
+ m_Flags(0),
+ m_File(VMA_NULL),
+ m_Freq(INT64_MAX),
+ m_StartCounter(INT64_MAX)
+{
+}
+
+VkResult VmaRecorder::Init(const VmaRecordSettings& settings, bool useMutex)
+{
+ m_UseMutex = useMutex;
+ m_Flags = settings.flags;
+
+ QueryPerformanceFrequency((LARGE_INTEGER*)&m_Freq);
+ QueryPerformanceCounter((LARGE_INTEGER*)&m_StartCounter);
+
+ // Open file for writing.
+ errno_t err = fopen_s(&m_File, settings.pFilePath, "wb");
+ if(err != 0)
+ {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ // Write header.
+ fprintf(m_File, "%s\n", "Vulkan Memory Allocator,Calls recording");
+ fprintf(m_File, "%s\n", "1,5");
+
+ return VK_SUCCESS;
+}
+
+VmaRecorder::~VmaRecorder()
+{
+ if(m_File != VMA_NULL)
+ {
+ fclose(m_File);
+ }
+}
+
+void VmaRecorder::RecordCreateAllocator(uint32_t frameIndex)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaCreateAllocator\n", callParams.threadId, callParams.time, frameIndex);
+ Flush();
+}
+
+void VmaRecorder::RecordDestroyAllocator(uint32_t frameIndex)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDestroyAllocator\n", callParams.threadId, callParams.time, frameIndex);
+ Flush();
+}
+
+void VmaRecorder::RecordCreatePool(uint32_t frameIndex, const VmaPoolCreateInfo& createInfo, VmaPool pool)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaCreatePool,%u,%u,%llu,%llu,%llu,%u,%p\n", callParams.threadId, callParams.time, frameIndex,
+ createInfo.memoryTypeIndex,
+ createInfo.flags,
+ createInfo.blockSize,
+ (uint64_t)createInfo.minBlockCount,
+ (uint64_t)createInfo.maxBlockCount,
+ createInfo.frameInUseCount,
+ pool);
+ Flush();
+}
+
+void VmaRecorder::RecordDestroyPool(uint32_t frameIndex, VmaPool pool)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDestroyPool,%p\n", callParams.threadId, callParams.time, frameIndex,
+ pool);
+ Flush();
+}
+
+void VmaRecorder::RecordAllocateMemory(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemory,%llu,%llu,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ vkMemReq.size,
+ vkMemReq.alignment,
+ vkMemReq.memoryTypeBits,
+ createInfo.flags,
+ createInfo.usage,
+ createInfo.requiredFlags,
+ createInfo.preferredFlags,
+ createInfo.memoryTypeBits,
+ createInfo.pool,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordAllocateMemoryPages(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ const VmaAllocationCreateInfo& createInfo,
+ uint64_t allocationCount,
+ const VmaAllocation* pAllocations)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryPages,%llu,%llu,%u,%u,%u,%u,%u,%u,%p,", callParams.threadId, callParams.time, frameIndex,
+ vkMemReq.size,
+ vkMemReq.alignment,
+ vkMemReq.memoryTypeBits,
+ createInfo.flags,
+ createInfo.usage,
+ createInfo.requiredFlags,
+ createInfo.preferredFlags,
+ createInfo.memoryTypeBits,
+ createInfo.pool);
+ PrintPointerList(allocationCount, pAllocations);
+ fprintf(m_File, ",%s\n", userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordAllocateMemoryForBuffer(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryForBuffer,%llu,%llu,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ vkMemReq.size,
+ vkMemReq.alignment,
+ vkMemReq.memoryTypeBits,
+ requiresDedicatedAllocation ? 1 : 0,
+ prefersDedicatedAllocation ? 1 : 0,
+ createInfo.flags,
+ createInfo.usage,
+ createInfo.requiredFlags,
+ createInfo.preferredFlags,
+ createInfo.memoryTypeBits,
+ createInfo.pool,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordAllocateMemoryForImage(uint32_t frameIndex,
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryForImage,%llu,%llu,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ vkMemReq.size,
+ vkMemReq.alignment,
+ vkMemReq.memoryTypeBits,
+ requiresDedicatedAllocation ? 1 : 0,
+ prefersDedicatedAllocation ? 1 : 0,
+ createInfo.flags,
+ createInfo.usage,
+ createInfo.requiredFlags,
+ createInfo.preferredFlags,
+ createInfo.memoryTypeBits,
+ createInfo.pool,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordFreeMemory(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaFreeMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordFreeMemoryPages(uint32_t frameIndex,
+ uint64_t allocationCount,
+ const VmaAllocation* pAllocations)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaFreeMemoryPages,", callParams.threadId, callParams.time, frameIndex);
+ PrintPointerList(allocationCount, pAllocations);
+ fprintf(m_File, "\n");
+ Flush();
+}
+
+void VmaRecorder::RecordResizeAllocation(
+ uint32_t frameIndex,
+ VmaAllocation allocation,
+ VkDeviceSize newSize)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaResizeAllocation,%p,%llu\n", callParams.threadId, callParams.time, frameIndex,
+ allocation, newSize);
+ Flush();
+}
+
+void VmaRecorder::RecordSetAllocationUserData(uint32_t frameIndex,
+ VmaAllocation allocation,
+ const void* pUserData)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(
+ allocation->IsUserDataString() ? VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT : 0,
+ pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaSetAllocationUserData,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordCreateLostAllocation(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaCreateLostAllocation,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordMapMemory(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaMapMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordUnmapMemory(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaUnmapMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordFlushAllocation(uint32_t frameIndex,
+ VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaFlushAllocation,%p,%llu,%llu\n", callParams.threadId, callParams.time, frameIndex,
+ allocation,
+ offset,
+ size);
+ Flush();
+}
+
+void VmaRecorder::RecordInvalidateAllocation(uint32_t frameIndex,
+ VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaInvalidateAllocation,%p,%llu,%llu\n", callParams.threadId, callParams.time, frameIndex,
+ allocation,
+ offset,
+ size);
+ Flush();
+}
+
+void VmaRecorder::RecordCreateBuffer(uint32_t frameIndex,
+ const VkBufferCreateInfo& bufCreateInfo,
+ const VmaAllocationCreateInfo& allocCreateInfo,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(allocCreateInfo.flags, allocCreateInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaCreateBuffer,%u,%llu,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ bufCreateInfo.flags,
+ bufCreateInfo.size,
+ bufCreateInfo.usage,
+ bufCreateInfo.sharingMode,
+ allocCreateInfo.flags,
+ allocCreateInfo.usage,
+ allocCreateInfo.requiredFlags,
+ allocCreateInfo.preferredFlags,
+ allocCreateInfo.memoryTypeBits,
+ allocCreateInfo.pool,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordCreateImage(uint32_t frameIndex,
+ const VkImageCreateInfo& imageCreateInfo,
+ const VmaAllocationCreateInfo& allocCreateInfo,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ UserDataString userDataStr(allocCreateInfo.flags, allocCreateInfo.pUserData);
+ fprintf(m_File, "%u,%.3f,%u,vmaCreateImage,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+ imageCreateInfo.flags,
+ imageCreateInfo.imageType,
+ imageCreateInfo.format,
+ imageCreateInfo.extent.width,
+ imageCreateInfo.extent.height,
+ imageCreateInfo.extent.depth,
+ imageCreateInfo.mipLevels,
+ imageCreateInfo.arrayLayers,
+ imageCreateInfo.samples,
+ imageCreateInfo.tiling,
+ imageCreateInfo.usage,
+ imageCreateInfo.sharingMode,
+ imageCreateInfo.initialLayout,
+ allocCreateInfo.flags,
+ allocCreateInfo.usage,
+ allocCreateInfo.requiredFlags,
+ allocCreateInfo.preferredFlags,
+ allocCreateInfo.memoryTypeBits,
+ allocCreateInfo.pool,
+ allocation,
+ userDataStr.GetString());
+ Flush();
+}
+
+void VmaRecorder::RecordDestroyBuffer(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDestroyBuffer,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordDestroyImage(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDestroyImage,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordTouchAllocation(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaTouchAllocation,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordGetAllocationInfo(uint32_t frameIndex,
+ VmaAllocation allocation)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaGetAllocationInfo,%p\n", callParams.threadId, callParams.time, frameIndex,
+ allocation);
+ Flush();
+}
+
+void VmaRecorder::RecordMakePoolAllocationsLost(uint32_t frameIndex,
+ VmaPool pool)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaMakePoolAllocationsLost,%p\n", callParams.threadId, callParams.time, frameIndex,
+ pool);
+ Flush();
+}
+
+void VmaRecorder::RecordDefragmentationBegin(uint32_t frameIndex,
+ const VmaDefragmentationInfo2& info,
+ VmaDefragmentationContext ctx)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDefragmentationBegin,%u,", callParams.threadId, callParams.time, frameIndex,
+ info.flags);
+ PrintPointerList(info.allocationCount, info.pAllocations);
+ fprintf(m_File, ",");
+ PrintPointerList(info.poolCount, info.pPools);
+ fprintf(m_File, ",%llu,%u,%llu,%u,%p,%p\n",
+ info.maxCpuBytesToMove,
+ info.maxCpuAllocationsToMove,
+ info.maxGpuBytesToMove,
+ info.maxGpuAllocationsToMove,
+ info.commandBuffer,
+ ctx);
+ Flush();
+}
+
+void VmaRecorder::RecordDefragmentationEnd(uint32_t frameIndex,
+ VmaDefragmentationContext ctx)
+{
+ CallParams callParams;
+ GetBasicParams(callParams);
+
+ VmaMutexLock lock(m_FileMutex, m_UseMutex);
+ fprintf(m_File, "%u,%.3f,%u,vmaDefragmentationEnd,%p\n", callParams.threadId, callParams.time, frameIndex,
+ ctx);
+ Flush();
+}
+
+VmaRecorder::UserDataString::UserDataString(VmaAllocationCreateFlags allocFlags, const void* pUserData)
+{
+ if(pUserData != VMA_NULL)
+ {
+ if((allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0)
+ {
+ m_Str = (const char*)pUserData;
+ }
+ else
+ {
+ sprintf_s(m_PtrStr, "%p", pUserData);
+ m_Str = m_PtrStr;
+ }
+ }
+ else
+ {
+ m_Str = "";
+ }
+}
+
+void VmaRecorder::WriteConfiguration(
+ const VkPhysicalDeviceProperties& devProps,
+ const VkPhysicalDeviceMemoryProperties& memProps,
+ bool dedicatedAllocationExtensionEnabled)
+{
+ fprintf(m_File, "Config,Begin\n");
+
+ fprintf(m_File, "PhysicalDevice,apiVersion,%u\n", devProps.apiVersion);
+ fprintf(m_File, "PhysicalDevice,driverVersion,%u\n", devProps.driverVersion);
+ fprintf(m_File, "PhysicalDevice,vendorID,%u\n", devProps.vendorID);
+ fprintf(m_File, "PhysicalDevice,deviceID,%u\n", devProps.deviceID);
+ fprintf(m_File, "PhysicalDevice,deviceType,%u\n", devProps.deviceType);
+ fprintf(m_File, "PhysicalDevice,deviceName,%s\n", devProps.deviceName);
+
+ fprintf(m_File, "PhysicalDeviceLimits,maxMemoryAllocationCount,%u\n", devProps.limits.maxMemoryAllocationCount);
+ fprintf(m_File, "PhysicalDeviceLimits,bufferImageGranularity,%llu\n", devProps.limits.bufferImageGranularity);
+ fprintf(m_File, "PhysicalDeviceLimits,nonCoherentAtomSize,%llu\n", devProps.limits.nonCoherentAtomSize);
+
+ fprintf(m_File, "PhysicalDeviceMemory,HeapCount,%u\n", memProps.memoryHeapCount);
+ for(uint32_t i = 0; i < memProps.memoryHeapCount; ++i)
+ {
+ fprintf(m_File, "PhysicalDeviceMemory,Heap,%u,size,%llu\n", i, memProps.memoryHeaps[i].size);
+ fprintf(m_File, "PhysicalDeviceMemory,Heap,%u,flags,%u\n", i, memProps.memoryHeaps[i].flags);
+ }
+ fprintf(m_File, "PhysicalDeviceMemory,TypeCount,%u\n", memProps.memoryTypeCount);
+ for(uint32_t i = 0; i < memProps.memoryTypeCount; ++i)
+ {
+ fprintf(m_File, "PhysicalDeviceMemory,Type,%u,heapIndex,%u\n", i, memProps.memoryTypes[i].heapIndex);
+ fprintf(m_File, "PhysicalDeviceMemory,Type,%u,propertyFlags,%u\n", i, memProps.memoryTypes[i].propertyFlags);
+ }
+
+ fprintf(m_File, "Extension,VK_KHR_dedicated_allocation,%u\n", dedicatedAllocationExtensionEnabled ? 1 : 0);
+
+ fprintf(m_File, "Macro,VMA_DEBUG_ALWAYS_DEDICATED_MEMORY,%u\n", VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ? 1 : 0);
+ fprintf(m_File, "Macro,VMA_DEBUG_ALIGNMENT,%llu\n", (VkDeviceSize)VMA_DEBUG_ALIGNMENT);
+ fprintf(m_File, "Macro,VMA_DEBUG_MARGIN,%llu\n", (VkDeviceSize)VMA_DEBUG_MARGIN);
+ fprintf(m_File, "Macro,VMA_DEBUG_INITIALIZE_ALLOCATIONS,%u\n", VMA_DEBUG_INITIALIZE_ALLOCATIONS ? 1 : 0);
+ fprintf(m_File, "Macro,VMA_DEBUG_DETECT_CORRUPTION,%u\n", VMA_DEBUG_DETECT_CORRUPTION ? 1 : 0);
+ fprintf(m_File, "Macro,VMA_DEBUG_GLOBAL_MUTEX,%u\n", VMA_DEBUG_GLOBAL_MUTEX ? 1 : 0);
+ fprintf(m_File, "Macro,VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY,%llu\n", (VkDeviceSize)VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY);
+ fprintf(m_File, "Macro,VMA_SMALL_HEAP_MAX_SIZE,%llu\n", (VkDeviceSize)VMA_SMALL_HEAP_MAX_SIZE);
+ fprintf(m_File, "Macro,VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE,%llu\n", (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);
+
+ fprintf(m_File, "Config,End\n");
+}
+
+void VmaRecorder::GetBasicParams(CallParams& outParams)
+{
+ outParams.threadId = GetCurrentThreadId();
+
+ LARGE_INTEGER counter;
+ QueryPerformanceCounter(&counter);
+ outParams.time = (double)(counter.QuadPart - m_StartCounter) / (double)m_Freq;
+}
+
+void VmaRecorder::PrintPointerList(uint64_t count, const VmaAllocation* pItems)
+{
+ if(count)
+ {
+ fprintf(m_File, "%p", pItems[0]);
+ for(uint64_t i = 1; i < count; ++i)
+ {
+ fprintf(m_File, " %p", pItems[i]);
+ }
+ }
+}
+
+void VmaRecorder::Flush()
+{
+ if((m_Flags & VMA_RECORD_FLUSH_AFTER_CALL_BIT) != 0)
+ {
+ fflush(m_File);
+ }
+}
+
+#endif // #if VMA_RECORDING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaAllocator_T
+
+VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
+ m_UseMutex((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) == 0),
+ m_UseKhrDedicatedAllocation((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0),
+ m_hDevice(pCreateInfo->device),
+ m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL),
+ m_AllocationCallbacks(pCreateInfo->pAllocationCallbacks ?
+ *pCreateInfo->pAllocationCallbacks : VmaEmptyAllocationCallbacks),
+ m_PreferredLargeHeapBlockSize(0),
+ m_PhysicalDevice(pCreateInfo->physicalDevice),
+ m_CurrentFrameIndex(0),
+ m_Pools(VmaStlAllocator<VmaPool>(GetAllocationCallbacks())),
+ m_NextPoolId(0)
+#if VMA_RECORDING_ENABLED
+ ,m_pRecorder(VMA_NULL)
+#endif
+{
+ if(VMA_DEBUG_DETECT_CORRUPTION)
+ {
+ // Needs to be multiply of uint32_t size because we are going to write VMA_CORRUPTION_DETECTION_MAGIC_VALUE to it.
+ VMA_ASSERT(VMA_DEBUG_MARGIN % sizeof(uint32_t) == 0);
+ }
+
+ VMA_ASSERT(pCreateInfo->physicalDevice && pCreateInfo->device);
+
+#if !(VMA_DEDICATED_ALLOCATION)
+ if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT set but required extensions are disabled by preprocessor macros.");
+ }
+#endif
+
+ memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks));
+ memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties));
+ memset(&m_MemProps, 0, sizeof(m_MemProps));
+
+ memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors));
+ memset(&m_pDedicatedAllocations, 0, sizeof(m_pDedicatedAllocations));
+
+ for(uint32_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i)
+ {
+ m_HeapSizeLimit[i] = VK_WHOLE_SIZE;
+ }
+
+ if(pCreateInfo->pDeviceMemoryCallbacks != VMA_NULL)
+ {
+ m_DeviceMemoryCallbacks.pfnAllocate = pCreateInfo->pDeviceMemoryCallbacks->pfnAllocate;
+ m_DeviceMemoryCallbacks.pfnFree = pCreateInfo->pDeviceMemoryCallbacks->pfnFree;
+ }
+
+ ImportVulkanFunctions(pCreateInfo->pVulkanFunctions);
+
+ (*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties);
+ (*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps);
+
+ VMA_ASSERT(VmaIsPow2(VMA_DEBUG_ALIGNMENT));
+ VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY));
+ VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.bufferImageGranularity));
+ VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.nonCoherentAtomSize));
+
+ m_PreferredLargeHeapBlockSize = (pCreateInfo->preferredLargeHeapBlockSize != 0) ?
+ pCreateInfo->preferredLargeHeapBlockSize : static_cast<VkDeviceSize>(VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);
+
+ if(pCreateInfo->pHeapSizeLimit != VMA_NULL)
+ {
+ for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex)
+ {
+ const VkDeviceSize limit = pCreateInfo->pHeapSizeLimit[heapIndex];
+ if(limit != VK_WHOLE_SIZE)
+ {
+ m_HeapSizeLimit[heapIndex] = limit;
+ if(limit < m_MemProps.memoryHeaps[heapIndex].size)
+ {
+ m_MemProps.memoryHeaps[heapIndex].size = limit;
+ }
+ }
+ }
+ }
+
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex);
+
+ m_pBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)(
+ this,
+ memTypeIndex,
+ preferredBlockSize,
+ 0,
+ SIZE_MAX,
+ GetBufferImageGranularity(),
+ pCreateInfo->frameInUseCount,
+ false, // isCustomPool
+ false, // explicitBlockSize
+ false); // linearAlgorithm
+ // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here,
+ // becase minBlockCount is 0.
+ m_pDedicatedAllocations[memTypeIndex] = vma_new(this, AllocationVectorType)(VmaStlAllocator<VmaAllocation>(GetAllocationCallbacks()));
+
+ }
+}
+
+VkResult VmaAllocator_T::Init(const VmaAllocatorCreateInfo* pCreateInfo)
+{
+ VkResult res = VK_SUCCESS;
+
+ if(pCreateInfo->pRecordSettings != VMA_NULL &&
+ !VmaStrIsEmpty(pCreateInfo->pRecordSettings->pFilePath))
+ {
+#if VMA_RECORDING_ENABLED
+ m_pRecorder = vma_new(this, VmaRecorder)();
+ res = m_pRecorder->Init(*pCreateInfo->pRecordSettings, m_UseMutex);
+ if(res != VK_SUCCESS)
+ {
+ return res;
+ }
+ m_pRecorder->WriteConfiguration(
+ m_PhysicalDeviceProperties,
+ m_MemProps,
+ m_UseKhrDedicatedAllocation);
+ m_pRecorder->RecordCreateAllocator(GetCurrentFrameIndex());
+#else
+ VMA_ASSERT(0 && "VmaAllocatorCreateInfo::pRecordSettings used, but not supported due to VMA_RECORDING_ENABLED not defined to 1.");
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+#endif
+ }
+
+ return res;
+}
+
+VmaAllocator_T::~VmaAllocator_T()
+{
+#if VMA_RECORDING_ENABLED
+ if(m_pRecorder != VMA_NULL)
+ {
+ m_pRecorder->RecordDestroyAllocator(GetCurrentFrameIndex());
+ vma_delete(this, m_pRecorder);
+ }
+#endif
+
+ VMA_ASSERT(m_Pools.empty());
+
+ for(size_t i = GetMemoryTypeCount(); i--; )
+ {
+ vma_delete(this, m_pDedicatedAllocations[i]);
+ vma_delete(this, m_pBlockVectors[i]);
+ }
+}
+
+void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions)
+{
+#if VMA_STATIC_VULKAN_FUNCTIONS == 1
+ m_VulkanFunctions.vkGetPhysicalDeviceProperties = &vkGetPhysicalDeviceProperties;
+ m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties = &vkGetPhysicalDeviceMemoryProperties;
+ m_VulkanFunctions.vkAllocateMemory = &vkAllocateMemory;
+ m_VulkanFunctions.vkFreeMemory = &vkFreeMemory;
+ m_VulkanFunctions.vkMapMemory = &vkMapMemory;
+ m_VulkanFunctions.vkUnmapMemory = &vkUnmapMemory;
+ m_VulkanFunctions.vkFlushMappedMemoryRanges = &vkFlushMappedMemoryRanges;
+ m_VulkanFunctions.vkInvalidateMappedMemoryRanges = &vkInvalidateMappedMemoryRanges;
+ m_VulkanFunctions.vkBindBufferMemory = &vkBindBufferMemory;
+ m_VulkanFunctions.vkBindImageMemory = &vkBindImageMemory;
+ m_VulkanFunctions.vkGetBufferMemoryRequirements = &vkGetBufferMemoryRequirements;
+ m_VulkanFunctions.vkGetImageMemoryRequirements = &vkGetImageMemoryRequirements;
+ m_VulkanFunctions.vkCreateBuffer = &vkCreateBuffer;
+ m_VulkanFunctions.vkDestroyBuffer = &vkDestroyBuffer;
+ m_VulkanFunctions.vkCreateImage = &vkCreateImage;
+ m_VulkanFunctions.vkDestroyImage = &vkDestroyImage;
+ m_VulkanFunctions.vkCmdCopyBuffer = &vkCmdCopyBuffer;
+#if VMA_DEDICATED_ALLOCATION
+ if(m_UseKhrDedicatedAllocation)
+ {
+ m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR =
+ (PFN_vkGetBufferMemoryRequirements2KHR)vkGetDeviceProcAddr(m_hDevice, "vkGetBufferMemoryRequirements2KHR");
+ m_VulkanFunctions.vkGetImageMemoryRequirements2KHR =
+ (PFN_vkGetImageMemoryRequirements2KHR)vkGetDeviceProcAddr(m_hDevice, "vkGetImageMemoryRequirements2KHR");
+ }
+#endif // #if VMA_DEDICATED_ALLOCATION
+#endif // #if VMA_STATIC_VULKAN_FUNCTIONS == 1
+
+#define VMA_COPY_IF_NOT_NULL(funcName) \
+ if(pVulkanFunctions->funcName != VMA_NULL) m_VulkanFunctions.funcName = pVulkanFunctions->funcName;
+
+ if(pVulkanFunctions != VMA_NULL)
+ {
+ VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties);
+ VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties);
+ VMA_COPY_IF_NOT_NULL(vkAllocateMemory);
+ VMA_COPY_IF_NOT_NULL(vkFreeMemory);
+ VMA_COPY_IF_NOT_NULL(vkMapMemory);
+ VMA_COPY_IF_NOT_NULL(vkUnmapMemory);
+ VMA_COPY_IF_NOT_NULL(vkFlushMappedMemoryRanges);
+ VMA_COPY_IF_NOT_NULL(vkInvalidateMappedMemoryRanges);
+ VMA_COPY_IF_NOT_NULL(vkBindBufferMemory);
+ VMA_COPY_IF_NOT_NULL(vkBindImageMemory);
+ VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements);
+ VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements);
+ VMA_COPY_IF_NOT_NULL(vkCreateBuffer);
+ VMA_COPY_IF_NOT_NULL(vkDestroyBuffer);
+ VMA_COPY_IF_NOT_NULL(vkCreateImage);
+ VMA_COPY_IF_NOT_NULL(vkDestroyImage);
+ VMA_COPY_IF_NOT_NULL(vkCmdCopyBuffer);
+#if VMA_DEDICATED_ALLOCATION
+ VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements2KHR);
+ VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements2KHR);
+#endif
+ }
+
+#undef VMA_COPY_IF_NOT_NULL
+
+ // If these asserts are hit, you must either #define VMA_STATIC_VULKAN_FUNCTIONS 1
+ // or pass valid pointers as VmaAllocatorCreateInfo::pVulkanFunctions.
+ VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceProperties != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkAllocateMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkFreeMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkMapMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkUnmapMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkFlushMappedMemoryRanges != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkInvalidateMappedMemoryRanges != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkCreateBuffer != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkDestroyBuffer != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkCreateImage != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkDestroyImage != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkCmdCopyBuffer != VMA_NULL);
+#if VMA_DEDICATED_ALLOCATION
+ if(m_UseKhrDedicatedAllocation)
+ {
+ VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements2KHR != VMA_NULL);
+ }
+#endif
+}
+
+VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)
+{
+ const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
+ const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;
+ const bool isSmallHeap = heapSize <= VMA_SMALL_HEAP_MAX_SIZE;
+ return isSmallHeap ? (heapSize / 8) : m_PreferredLargeHeapBlockSize;
+}
+
+VkResult VmaAllocator_T::AllocateMemoryOfType(
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ bool dedicatedAllocation,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ const VmaAllocationCreateInfo& createInfo,
+ uint32_t memTypeIndex,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ VMA_ASSERT(pAllocations != VMA_NULL);
+ VMA_DEBUG_LOG(" AllocateMemory: MemoryTypeIndex=%u, AllocationCount=%zu, Size=%llu", memTypeIndex, allocationCount, vkMemReq.size);
+
+ VmaAllocationCreateInfo finalCreateInfo = createInfo;
+
+ // If memory type is not HOST_VISIBLE, disable MAPPED.
+ if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
+ (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ {
+ finalCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT;
+ }
+
+ VmaBlockVector* const blockVector = m_pBlockVectors[memTypeIndex];
+ VMA_ASSERT(blockVector);
+
+ const VkDeviceSize preferredBlockSize = blockVector->GetPreferredBlockSize();
+ bool preferDedicatedMemory =
+ VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ||
+ dedicatedAllocation ||
+ // Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size.
+ size > preferredBlockSize / 2;
+
+ if(preferDedicatedMemory &&
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 &&
+ finalCreateInfo.pool == VK_NULL_HANDLE)
+ {
+ finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+ }
+
+ if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)
+ {
+ if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ {
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ else
+ {
+ return AllocateDedicatedMemory(
+ size,
+ suballocType,
+ memTypeIndex,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
+ finalCreateInfo.pUserData,
+ dedicatedBuffer,
+ dedicatedImage,
+ allocationCount,
+ pAllocations);
+ }
+ }
+ else
+ {
+ VkResult res = blockVector->Allocate(
+ VK_NULL_HANDLE, // hCurrentPool
+ m_CurrentFrameIndex.load(),
+ size,
+ alignment,
+ finalCreateInfo,
+ suballocType,
+ allocationCount,
+ pAllocations);
+ if(res == VK_SUCCESS)
+ {
+ return res;
+ }
+
+ // 5. Try dedicated memory.
+ if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ {
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ else
+ {
+ res = AllocateDedicatedMemory(
+ size,
+ suballocType,
+ memTypeIndex,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
+ finalCreateInfo.pUserData,
+ dedicatedBuffer,
+ dedicatedImage,
+ allocationCount,
+ pAllocations);
+ if(res == VK_SUCCESS)
+ {
+ // Succeeded: AllocateDedicatedMemory function already filld pMemory, nothing more to do here.
+ VMA_DEBUG_LOG(" Allocated as DedicatedMemory");
+ return VK_SUCCESS;
+ }
+ else
+ {
+ // Everything failed: Return error code.
+ VMA_DEBUG_LOG(" vkAllocateMemory FAILED");
+ return res;
+ }
+ }
+ }
+}
+
+VkResult VmaAllocator_T::AllocateDedicatedMemory(
+ VkDeviceSize size,
+ VmaSuballocationType suballocType,
+ uint32_t memTypeIndex,
+ bool map,
+ bool isUserDataString,
+ void* pUserData,
+ VkBuffer /*dedicatedBuffer*/,
+ VkImage /*dedicatedImage*/,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ VMA_ASSERT(allocationCount > 0 && pAllocations);
+
+ VkMemoryAllocateInfo allocInfo = {};
+ allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocInfo.memoryTypeIndex = memTypeIndex;
+ allocInfo.allocationSize = size;
+
+#if VMA_DEDICATED_ALLOCATION
+ VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = {};
+ dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
+ if(m_UseKhrDedicatedAllocation)
+ {
+ if(dedicatedBuffer != VK_NULL_HANDLE)
+ {
+ VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE);
+ dedicatedAllocInfo.buffer = dedicatedBuffer;
+ allocInfo.pNext = &dedicatedAllocInfo;
+ }
+ else if(dedicatedImage != VK_NULL_HANDLE)
+ {
+ dedicatedAllocInfo.image = dedicatedImage;
+ allocInfo.pNext = &dedicatedAllocInfo;
+ }
+ }
+#endif // #if VMA_DEDICATED_ALLOCATION
+
+ size_t allocIndex;
+ VkResult res = VK_SUCCESS;
+ for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+ {
+ res = AllocateDedicatedMemoryPage(
+ size,
+ suballocType,
+ memTypeIndex,
+ allocInfo,
+ map,
+ isUserDataString,
+ pUserData,
+ pAllocations + allocIndex);
+ if(res != VK_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ if(res == VK_SUCCESS)
+ {
+ // Register them in m_pDedicatedAllocations.
+ {
+ VmaMutexLockWrite lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+ AllocationVectorType* pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex];
+ VMA_ASSERT(pDedicatedAllocations);
+ for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+ {
+ VmaVectorInsertSorted<VmaPointerLess>(*pDedicatedAllocations, pAllocations[allocIndex]);
+ }
+ }
+
+ VMA_DEBUG_LOG(" Allocated DedicatedMemory Count=%zu, MemoryTypeIndex=#%u", allocationCount, memTypeIndex);
+ }
+ else
+ {
+ // Free all already created allocations.
+ while(allocIndex--)
+ {
+ VmaAllocation currAlloc = pAllocations[allocIndex];
+ VkDeviceMemory hMemory = currAlloc->GetMemory();
+
+ /*
+ There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory
+ before vkFreeMemory.
+
+ if(currAlloc->GetMappedData() != VMA_NULL)
+ {
+ (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory);
+ }
+ */
+
+ FreeVulkanMemory(memTypeIndex, currAlloc->GetSize(), hMemory);
+
+ currAlloc->SetUserData(this, VMA_NULL);
+ vma_delete(this, currAlloc);
+ }
+
+ memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+ }
+
+ return res;
+}
+
+VkResult VmaAllocator_T::AllocateDedicatedMemoryPage(
+ VkDeviceSize size,
+ VmaSuballocationType suballocType,
+ uint32_t memTypeIndex,
+ const VkMemoryAllocateInfo& allocInfo,
+ bool map,
+ bool isUserDataString,
+ void* pUserData,
+ VmaAllocation* pAllocation)
+{
+ VkDeviceMemory hMemory = VK_NULL_HANDLE;
+ VkResult res = AllocateVulkanMemory(&allocInfo, &hMemory);
+ if(res < 0)
+ {
+ VMA_DEBUG_LOG(" vkAllocateMemory FAILED");
+ return res;
+ }
+
+ void* pMappedData = VMA_NULL;
+ if(map)
+ {
+ res = (*m_VulkanFunctions.vkMapMemory)(
+ m_hDevice,
+ hMemory,
+ 0,
+ VK_WHOLE_SIZE,
+ 0,
+ &pMappedData);
+ if(res < 0)
+ {
+ VMA_DEBUG_LOG(" vkMapMemory FAILED");
+ FreeVulkanMemory(memTypeIndex, size, hMemory);
+ return res;
+ }
+ }
+
+ *pAllocation = vma_new(this, VmaAllocation_T)(m_CurrentFrameIndex.load(), isUserDataString);
+ (*pAllocation)->InitDedicatedAllocation(memTypeIndex, hMemory, suballocType, pMappedData, size);
+ (*pAllocation)->SetUserData(this, pUserData);
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+ {
+ FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaAllocator_T::GetBufferMemoryRequirements(
+ VkBuffer hBuffer,
+ VkMemoryRequirements& memReq,
+ bool& requiresDedicatedAllocation,
+ bool& prefersDedicatedAllocation) const
+{
+#if VMA_DEDICATED_ALLOCATION
+ if(m_UseKhrDedicatedAllocation)
+ {
+ VkBufferMemoryRequirementsInfo2KHR memReqInfo = {};
+ memReqInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR;
+ memReqInfo.buffer = hBuffer;
+
+ VkMemoryDedicatedRequirementsKHR memDedicatedReq = {};
+ memDedicatedReq.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR;
+
+ VkMemoryRequirements2KHR memReq2 = {};
+ memReq2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR;
+ memReq2.pNext = &memDedicatedReq;
+
+ (*m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2);
+
+ memReq = memReq2.memoryRequirements;
+ requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE);
+ prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE);
+ }
+ else
+#endif // #if VMA_DEDICATED_ALLOCATION
+ {
+ (*m_VulkanFunctions.vkGetBufferMemoryRequirements)(m_hDevice, hBuffer, &memReq);
+ requiresDedicatedAllocation = false;
+ prefersDedicatedAllocation = false;
+ }
+}
+
+void VmaAllocator_T::GetImageMemoryRequirements(
+ VkImage hImage,
+ VkMemoryRequirements& memReq,
+ bool& requiresDedicatedAllocation,
+ bool& prefersDedicatedAllocation) const
+{
+#if VMA_DEDICATED_ALLOCATION
+ if(m_UseKhrDedicatedAllocation)
+ {
+ VkImageMemoryRequirementsInfo2KHR memReqInfo = {};
+ memReqInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR;
+ memReqInfo.image = hImage;
+
+ VkMemoryDedicatedRequirementsKHR memDedicatedReq = {};
+ memDedicatedReq.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR;
+
+ VkMemoryRequirements2KHR memReq2 = {};
+ memReq2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR;
+ memReq2.pNext = &memDedicatedReq;
+
+ (*m_VulkanFunctions.vkGetImageMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2);
+
+ memReq = memReq2.memoryRequirements;
+ requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE);
+ prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE);
+ }
+ else
+#endif // #if VMA_DEDICATED_ALLOCATION
+ {
+ (*m_VulkanFunctions.vkGetImageMemoryRequirements)(m_hDevice, hImage, &memReq);
+ requiresDedicatedAllocation = false;
+ prefersDedicatedAllocation = false;
+ }
+}
+
+VkResult VmaAllocator_T::AllocateMemory(
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+
+ VMA_ASSERT(VmaIsPow2(vkMemReq.alignment));
+
+ if(vkMemReq.size == 0)
+ {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ if((createInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&
+ (createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense.");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ if((createInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
+ (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_MAPPED_BIT together with VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT is invalid.");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ if(requiresDedicatedAllocation)
+ {
+ if((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT specified while dedicated allocation is required.");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ if(createInfo.pool != VK_NULL_HANDLE)
+ {
+ VMA_ASSERT(0 && "Pool specified while dedicated allocation is required.");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ }
+ if((createInfo.pool != VK_NULL_HANDLE) &&
+ ((createInfo.flags & (VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT)) != 0))
+ {
+ VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT when pool != null is invalid.");
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+
+ if(createInfo.pool != VK_NULL_HANDLE)
+ {
+ const VkDeviceSize alignmentForPool = VMA_MAX(
+ vkMemReq.alignment,
+ GetMemoryTypeMinAlignment(createInfo.pool->m_BlockVector.GetMemoryTypeIndex()));
+ return createInfo.pool->m_BlockVector.Allocate(
+ createInfo.pool,
+ m_CurrentFrameIndex.load(),
+ vkMemReq.size,
+ alignmentForPool,
+ createInfo,
+ suballocType,
+ allocationCount,
+ pAllocations);
+ }
+ else
+ {
+ // Bit mask of memory Vulkan types acceptable for this allocation.
+ uint32_t memoryTypeBits = vkMemReq.memoryTypeBits;
+ uint32_t memTypeIndex = UINT32_MAX;
+ VkResult res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex);
+ if(res == VK_SUCCESS)
+ {
+ VkDeviceSize alignmentForMemType = VMA_MAX(
+ vkMemReq.alignment,
+ GetMemoryTypeMinAlignment(memTypeIndex));
+
+ res = AllocateMemoryOfType(
+ vkMemReq.size,
+ alignmentForMemType,
+ requiresDedicatedAllocation || prefersDedicatedAllocation,
+ dedicatedBuffer,
+ dedicatedImage,
+ createInfo,
+ memTypeIndex,
+ suballocType,
+ allocationCount,
+ pAllocations);
+ // Succeeded on first try.
+ if(res == VK_SUCCESS)
+ {
+ return res;
+ }
+ // Allocation from this memory type failed. Try other compatible memory types.
+ else
+ {
+ for(;;)
+ {
+ // Remove old memTypeIndex from list of possibilities.
+ memoryTypeBits &= ~(1u << memTypeIndex);
+ // Find alternative memTypeIndex.
+ res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex);
+ if(res == VK_SUCCESS)
+ {
+ alignmentForMemType = VMA_MAX(
+ vkMemReq.alignment,
+ GetMemoryTypeMinAlignment(memTypeIndex));
+
+ res = AllocateMemoryOfType(
+ vkMemReq.size,
+ alignmentForMemType,
+ requiresDedicatedAllocation || prefersDedicatedAllocation,
+ dedicatedBuffer,
+ dedicatedImage,
+ createInfo,
+ memTypeIndex,
+ suballocType,
+ allocationCount,
+ pAllocations);
+ // Allocation from this alternative memory type succeeded.
+ if(res == VK_SUCCESS)
+ {
+ return res;
+ }
+ // else: Allocation from this memory type failed. Try next one - next loop iteration.
+ }
+ // No other matching memory type index could be found.
+ else
+ {
+ // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ }
+ }
+ }
+ // Can't find any single memory type maching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.
+ else
+ return res;
+ }
+}
+
+void VmaAllocator_T::FreeMemory(
+ size_t allocationCount,
+ const VmaAllocation* pAllocations)
+{
+ VMA_ASSERT(pAllocations);
+
+ for(size_t allocIndex = allocationCount; allocIndex--; )
+ {
+ VmaAllocation allocation = pAllocations[allocIndex];
+
+ if(allocation != VK_NULL_HANDLE)
+ {
+ if(TouchAllocation(allocation))
+ {
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+ {
+ FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);
+ }
+
+ switch(allocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaBlockVector* pBlockVector = VMA_NULL;
+ VmaPool hPool = allocation->GetPool();
+ if(hPool != VK_NULL_HANDLE)
+ {
+ pBlockVector = &hPool->m_BlockVector;
+ }
+ else
+ {
+ const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
+ pBlockVector = m_pBlockVectors[memTypeIndex];
+ }
+ pBlockVector->Free(allocation);
+ }
+ break;
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ FreeDedicatedMemory(allocation);
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+ }
+
+ allocation->SetUserData(this, VMA_NULL);
+ vma_delete(this, allocation);
+ }
+ }
+}
+
+VkResult VmaAllocator_T::ResizeAllocation(
+ const VmaAllocation alloc,
+ VkDeviceSize newSize)
+{
+ if(newSize == 0 || alloc->GetLastUseFrameIndex() == VMA_FRAME_INDEX_LOST)
+ {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ if(newSize == alloc->GetSize())
+ {
+ return VK_SUCCESS;
+ }
+
+ switch(alloc->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ if(alloc->GetBlock()->m_pMetadata->ResizeAllocation(alloc, newSize))
+ {
+ alloc->ChangeSize(newSize);
+ VMA_HEAVY_ASSERT(alloc->GetBlock()->m_pMetadata->Validate());
+ return VK_SUCCESS;
+ }
+ else
+ {
+ return VkResult(-1000069000); // VK_ERROR_OUT_OF_POOL_MEMORY
+ }
+ default:
+ VMA_ASSERT(0);
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+}
+
+void VmaAllocator_T::CalculateStats(VmaStats* pStats)
+{
+ // Initialize.
+ InitStatInfo(pStats->total);
+ for(size_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i)
+ InitStatInfo(pStats->memoryType[i]);
+ for(size_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i)
+ InitStatInfo(pStats->memoryHeap[i]);
+
+ // Process default pools.
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];
+ VMA_ASSERT(pBlockVector);
+ pBlockVector->AddStats(pStats);
+ }
+
+ // Process custom pools.
+ {
+ VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
+ for(size_t poolIndex = 0, poolCount = m_Pools.size(); poolIndex < poolCount; ++poolIndex)
+ {
+ m_Pools[poolIndex]->m_BlockVector.AddStats(pStats);
+ }
+ }
+
+ // Process dedicated allocations.
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
+ VmaMutexLockRead dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+ AllocationVectorType* const pDedicatedAllocVector = m_pDedicatedAllocations[memTypeIndex];
+ VMA_ASSERT(pDedicatedAllocVector);
+ for(size_t allocIndex = 0, allocCount = pDedicatedAllocVector->size(); allocIndex < allocCount; ++allocIndex)
+ {
+ VmaStatInfo allocationStatInfo;
+ (*pDedicatedAllocVector)[allocIndex]->DedicatedAllocCalcStatsInfo(allocationStatInfo);
+ VmaAddStatInfo(pStats->total, allocationStatInfo);
+ VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo);
+ VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo);
+ }
+ }
+
+ // Postprocess.
+ VmaPostprocessCalcStatInfo(pStats->total);
+ for(size_t i = 0; i < GetMemoryTypeCount(); ++i)
+ VmaPostprocessCalcStatInfo(pStats->memoryType[i]);
+ for(size_t i = 0; i < GetMemoryHeapCount(); ++i)
+ VmaPostprocessCalcStatInfo(pStats->memoryHeap[i]);
+}
+
+static const uint32_t VMA_VENDOR_ID_AMD = 4098;
+
+VkResult VmaAllocator_T::DefragmentationBegin(
+ const VmaDefragmentationInfo2& info,
+ VmaDefragmentationStats* pStats,
+ VmaDefragmentationContext* pContext)
+{
+ if(info.pAllocationsChanged != VMA_NULL)
+ {
+ memset(info.pAllocationsChanged, 0, info.allocationCount * sizeof(VkBool32));
+ }
+
+ *pContext = vma_new(this, VmaDefragmentationContext_T)(
+ this, m_CurrentFrameIndex.load(), info.flags, pStats);
+
+ (*pContext)->AddPools(info.poolCount, info.pPools);
+ (*pContext)->AddAllocations(
+ info.allocationCount, info.pAllocations, info.pAllocationsChanged);
+
+ VkResult res = (*pContext)->Defragment(
+ info.maxCpuBytesToMove, info.maxCpuAllocationsToMove,
+ info.maxGpuBytesToMove, info.maxGpuAllocationsToMove,
+ info.commandBuffer, pStats);
+
+ if(res != VK_NOT_READY)
+ {
+ vma_delete(this, *pContext);
+ *pContext = VMA_NULL;
+ }
+
+ return res;
+}
+
+VkResult VmaAllocator_T::DefragmentationEnd(
+ VmaDefragmentationContext context)
+{
+ vma_delete(this, context);
+ return VK_SUCCESS;
+}
+
+void VmaAllocator_T::GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo)
+{
+ if(hAllocation->CanBecomeLost())
+ {
+ /*
+ Warning: This is a carefully designed algorithm.
+ Do not modify unless you really know what you're doing :)
+ */
+ const uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+ uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+ for(;;)
+ {
+ if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
+ {
+ pAllocationInfo->memoryType = UINT32_MAX;
+ pAllocationInfo->deviceMemory = VK_NULL_HANDLE;
+ pAllocationInfo->offset = 0;
+ pAllocationInfo->size = hAllocation->GetSize();
+ pAllocationInfo->pMappedData = VMA_NULL;
+ pAllocationInfo->pUserData = hAllocation->GetUserData();
+ return;
+ }
+ else if(localLastUseFrameIndex == localCurrFrameIndex)
+ {
+ pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex();
+ pAllocationInfo->deviceMemory = hAllocation->GetMemory();
+ pAllocationInfo->offset = hAllocation->GetOffset();
+ pAllocationInfo->size = hAllocation->GetSize();
+ pAllocationInfo->pMappedData = VMA_NULL;
+ pAllocationInfo->pUserData = hAllocation->GetUserData();
+ return;
+ }
+ else // Last use time earlier than current time.
+ {
+ if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+ {
+ localLastUseFrameIndex = localCurrFrameIndex;
+ }
+ }
+ }
+ }
+ else
+ {
+#if VMA_STATS_STRING_ENABLED
+ uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+ uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+ for(;;)
+ {
+ VMA_ASSERT(localLastUseFrameIndex != VMA_FRAME_INDEX_LOST);
+ if(localLastUseFrameIndex == localCurrFrameIndex)
+ {
+ break;
+ }
+ else // Last use time earlier than current time.
+ {
+ if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+ {
+ localLastUseFrameIndex = localCurrFrameIndex;
+ }
+ }
+ }
+#endif
+
+ pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex();
+ pAllocationInfo->deviceMemory = hAllocation->GetMemory();
+ pAllocationInfo->offset = hAllocation->GetOffset();
+ pAllocationInfo->size = hAllocation->GetSize();
+ pAllocationInfo->pMappedData = hAllocation->GetMappedData();
+ pAllocationInfo->pUserData = hAllocation->GetUserData();
+ }
+}
+
+bool VmaAllocator_T::TouchAllocation(VmaAllocation hAllocation)
+{
+ // This is a stripped-down version of VmaAllocator_T::GetAllocationInfo.
+ if(hAllocation->CanBecomeLost())
+ {
+ uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+ uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+ for(;;)
+ {
+ if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
+ {
+ return false;
+ }
+ else if(localLastUseFrameIndex == localCurrFrameIndex)
+ {
+ return true;
+ }
+ else // Last use time earlier than current time.
+ {
+ if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+ {
+ localLastUseFrameIndex = localCurrFrameIndex;
+ }
+ }
+ }
+ }
+ else
+ {
+#if VMA_STATS_STRING_ENABLED
+ uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+ uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+ for(;;)
+ {
+ VMA_ASSERT(localLastUseFrameIndex != VMA_FRAME_INDEX_LOST);
+ if(localLastUseFrameIndex == localCurrFrameIndex)
+ {
+ break;
+ }
+ else // Last use time earlier than current time.
+ {
+ if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+ {
+ localLastUseFrameIndex = localCurrFrameIndex;
+ }
+ }
+ }
+#endif
+
+ return true;
+ }
+}
+
+VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool)
+{
+ VMA_DEBUG_LOG(" CreatePool: MemoryTypeIndex=%u, flags=%u", pCreateInfo->memoryTypeIndex, pCreateInfo->flags);
+
+ VmaPoolCreateInfo newCreateInfo = *pCreateInfo;
+
+ if(newCreateInfo.maxBlockCount == 0)
+ {
+ newCreateInfo.maxBlockCount = SIZE_MAX;
+ }
+ if(newCreateInfo.minBlockCount > newCreateInfo.maxBlockCount)
+ {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex);
+
+ *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize);
+
+ VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks();
+ if(res != VK_SUCCESS)
+ {
+ vma_delete(this, *pPool);
+ *pPool = VMA_NULL;
+ return res;
+ }
+
+ // Add to m_Pools.
+ {
+ VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);
+ (*pPool)->SetId(m_NextPoolId++);
+ VmaVectorInsertSorted<VmaPointerLess>(m_Pools, *pPool);
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaAllocator_T::DestroyPool(VmaPool pool)
+{
+ // Remove from m_Pools.
+ {
+ VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);
+ bool success = VmaVectorRemoveSorted<VmaPointerLess>(m_Pools, pool);
+ (void) success;
+ VMA_ASSERT(success && "Pool not found in Allocator.");
+ }
+
+ vma_delete(this, pool);
+}
+
+void VmaAllocator_T::GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats)
+{
+ pool->m_BlockVector.GetPoolStats(pPoolStats);
+}
+
+void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)
+{
+ m_CurrentFrameIndex.store(frameIndex);
+}
+
+void VmaAllocator_T::MakePoolAllocationsLost(
+ VmaPool hPool,
+ size_t* pLostAllocationCount)
+{
+ hPool->m_BlockVector.MakePoolAllocationsLost(
+ m_CurrentFrameIndex.load(),
+ pLostAllocationCount);
+}
+
+VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool)
+{
+ return hPool->m_BlockVector.CheckCorruption();
+}
+
+VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)
+{
+ VkResult finalRes = VK_ERROR_FEATURE_NOT_PRESENT;
+
+ // Process default pools.
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ if(((1u << memTypeIndex) & memoryTypeBits) != 0)
+ {
+ VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];
+ VMA_ASSERT(pBlockVector);
+ VkResult localRes = pBlockVector->CheckCorruption();
+ switch(localRes)
+ {
+ case VK_ERROR_FEATURE_NOT_PRESENT:
+ break;
+ case VK_SUCCESS:
+ finalRes = VK_SUCCESS;
+ break;
+ default:
+ return localRes;
+ }
+ }
+ }
+
+ // Process custom pools.
+ {
+ VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
+ for(size_t poolIndex = 0, poolCount = m_Pools.size(); poolIndex < poolCount; ++poolIndex)
+ {
+ if(((1u << m_Pools[poolIndex]->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0)
+ {
+ VkResult localRes = m_Pools[poolIndex]->m_BlockVector.CheckCorruption();
+ switch(localRes)
+ {
+ case VK_ERROR_FEATURE_NOT_PRESENT:
+ break;
+ case VK_SUCCESS:
+ finalRes = VK_SUCCESS;
+ break;
+ default:
+ return localRes;
+ }
+ }
+ }
+ }
+
+ return finalRes;
+}
+
+void VmaAllocator_T::CreateLostAllocation(VmaAllocation* pAllocation)
+{
+ *pAllocation = vma_new(this, VmaAllocation_T)(VMA_FRAME_INDEX_LOST, false);
+ (*pAllocation)->InitLost();
+}
+
+VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory)
+{
+ const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(pAllocateInfo->memoryTypeIndex);
+
+ VkResult res;
+ if(m_HeapSizeLimit[heapIndex] != VK_WHOLE_SIZE)
+ {
+ VmaMutexLock lock(m_HeapSizeLimitMutex, m_UseMutex);
+ if(m_HeapSizeLimit[heapIndex] >= pAllocateInfo->allocationSize)
+ {
+ res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory);
+ if(res == VK_SUCCESS)
+ {
+ m_HeapSizeLimit[heapIndex] -= pAllocateInfo->allocationSize;
+ }
+ }
+ else
+ {
+ res = VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+ }
+ else
+ {
+ res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory);
+ }
+
+ if(res == VK_SUCCESS && m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL)
+ {
+ (*m_DeviceMemoryCallbacks.pfnAllocate)(this, pAllocateInfo->memoryTypeIndex, *pMemory, pAllocateInfo->allocationSize);
+ }
+
+ return res;
+}
+
+void VmaAllocator_T::FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory)
+{
+ if(m_DeviceMemoryCallbacks.pfnFree != VMA_NULL)
+ {
+ (*m_DeviceMemoryCallbacks.pfnFree)(this, memoryType, hMemory, size);
+ }
+
+ (*m_VulkanFunctions.vkFreeMemory)(m_hDevice, hMemory, GetAllocationCallbacks());
+
+ const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memoryType);
+ if(m_HeapSizeLimit[heapIndex] != VK_WHOLE_SIZE)
+ {
+ VmaMutexLock lock(m_HeapSizeLimitMutex, m_UseMutex);
+ m_HeapSizeLimit[heapIndex] += size;
+ }
+}
+
+VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData)
+{
+ if(hAllocation->CanBecomeLost())
+ {
+ return VK_ERROR_MEMORY_MAP_FAILED;
+ }
+
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();
+ char *pBytes = VMA_NULL;
+ VkResult res = pBlock->Map(this, 1, (void**)&pBytes);
+ if(res == VK_SUCCESS)
+ {
+ *ppData = pBytes + (ptrdiff_t)hAllocation->GetOffset();
+ hAllocation->BlockAllocMap();
+ }
+ return res;
+ }
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ return hAllocation->DedicatedAllocMap(this, ppData);
+ default:
+ VMA_ASSERT(0);
+ return VK_ERROR_MEMORY_MAP_FAILED;
+ }
+}
+
+void VmaAllocator_T::Unmap(VmaAllocation hAllocation)
+{
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();
+ hAllocation->BlockAllocUnmap();
+ pBlock->Unmap(this, 1);
+ }
+ break;
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ hAllocation->DedicatedAllocUnmap(this);
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+}
+
+VkResult VmaAllocator_T::BindBufferMemory(VmaAllocation hAllocation, VkBuffer hBuffer)
+{
+ VkResult res = VK_SUCCESS;
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ res = GetVulkanFunctions().vkBindBufferMemory(
+ m_hDevice,
+ hBuffer,
+ hAllocation->GetMemory(),
+ 0); //memoryOffset
+ break;
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();
+ VMA_ASSERT(pBlock && "Binding buffer to allocation that doesn't belong to any block. Is the allocation lost?");
+ res = pBlock->BindBufferMemory(this, hAllocation, hBuffer);
+ break;
+ }
+ default:
+ VMA_ASSERT(0);
+ }
+ return res;
+}
+
+VkResult VmaAllocator_T::BindImageMemory(VmaAllocation hAllocation, VkImage hImage)
+{
+ VkResult res = VK_SUCCESS;
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ res = GetVulkanFunctions().vkBindImageMemory(
+ m_hDevice,
+ hImage,
+ hAllocation->GetMemory(),
+ 0); //memoryOffset
+ break;
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();
+ VMA_ASSERT(pBlock && "Binding image to allocation that doesn't belong to any block. Is the allocation lost?");
+ res = pBlock->BindImageMemory(this, hAllocation, hImage);
+ break;
+ }
+ default:
+ VMA_ASSERT(0);
+ }
+ return res;
+}
+
+void VmaAllocator_T::FlushOrInvalidateAllocation(
+ VmaAllocation hAllocation,
+ VkDeviceSize offset, VkDeviceSize size,
+ VMA_CACHE_OPERATION op)
+{
+ const uint32_t memTypeIndex = hAllocation->GetMemoryTypeIndex();
+ if(size > 0 && IsMemoryTypeNonCoherent(memTypeIndex))
+ {
+ const VkDeviceSize allocationSize = hAllocation->GetSize();
+ VMA_ASSERT(offset <= allocationSize);
+
+ const VkDeviceSize nonCoherentAtomSize = m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
+
+ VkMappedMemoryRange memRange = {};
+ memRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+ memRange.memory = hAllocation->GetMemory();
+
+ switch(hAllocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ memRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);
+ if(size == VK_WHOLE_SIZE)
+ {
+ memRange.size = allocationSize - memRange.offset;
+ }
+ else
+ {
+ VMA_ASSERT(offset + size <= allocationSize);
+ memRange.size = VMA_MIN(
+ VmaAlignUp(size + (offset - memRange.offset), nonCoherentAtomSize),
+ allocationSize - memRange.offset);
+ }
+ break;
+
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ {
+ // 1. Still within this allocation.
+ memRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);
+ if(size == VK_WHOLE_SIZE)
+ {
+ size = allocationSize - offset;
+ }
+ else
+ {
+ VMA_ASSERT(offset + size <= allocationSize);
+ }
+ memRange.size = VmaAlignUp(size + (offset - memRange.offset), nonCoherentAtomSize);
+
+ // 2. Adjust to whole block.
+ const VkDeviceSize allocationOffset = hAllocation->GetOffset();
+ VMA_ASSERT(allocationOffset % nonCoherentAtomSize == 0);
+ const VkDeviceSize blockSize = hAllocation->GetBlock()->m_pMetadata->GetSize();
+ memRange.offset += allocationOffset;
+ memRange.size = VMA_MIN(memRange.size, blockSize - memRange.offset);
+
+ break;
+ }
+
+ default:
+ VMA_ASSERT(0);
+ }
+
+ switch(op)
+ {
+ case VMA_CACHE_FLUSH:
+ (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, 1, &memRange);
+ break;
+ case VMA_CACHE_INVALIDATE:
+ (*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, 1, &memRange);
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+ }
+ // else: Just ignore this call.
+}
+
+void VmaAllocator_T::FreeDedicatedMemory(VmaAllocation allocation)
+{
+ VMA_ASSERT(allocation && allocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
+
+ const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
+ {
+ VmaMutexLockWrite lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+ AllocationVectorType* const pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex];
+ VMA_ASSERT(pDedicatedAllocations);
+ bool success = VmaVectorRemoveSorted<VmaPointerLess>(*pDedicatedAllocations, allocation);
+ (void) success;
+ VMA_ASSERT(success);
+ }
+
+ VkDeviceMemory hMemory = allocation->GetMemory();
+
+ /*
+ There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory
+ before vkFreeMemory.
+
+ if(allocation->GetMappedData() != VMA_NULL)
+ {
+ (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory);
+ }
+ */
+
+ FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);
+
+ VMA_DEBUG_LOG(" Freed DedicatedMemory MemoryTypeIndex=%u", memTypeIndex);
+}
+
+void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern)
+{
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS &&
+ !hAllocation->CanBecomeLost() &&
+ (m_MemProps.memoryTypes[hAllocation->GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
+ {
+ void* pData = VMA_NULL;
+ VkResult res = Map(hAllocation, &pData);
+ if(res == VK_SUCCESS)
+ {
+ memset(pData, (int)pattern, (size_t)hAllocation->GetSize());
+ FlushOrInvalidateAllocation(hAllocation, 0, VK_WHOLE_SIZE, VMA_CACHE_FLUSH);
+ Unmap(hAllocation);
+ }
+ else
+ {
+ VMA_ASSERT(0 && "VMA_DEBUG_INITIALIZE_ALLOCATIONS is enabled, but couldn't map memory to fill allocation.");
+ }
+ }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
+{
+ bool dedicatedAllocationsStarted = false;
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ VmaMutexLockRead dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+ AllocationVectorType* const pDedicatedAllocVector = m_pDedicatedAllocations[memTypeIndex];
+ VMA_ASSERT(pDedicatedAllocVector);
+ if(pDedicatedAllocVector->empty() == false)
+ {
+ if(dedicatedAllocationsStarted == false)
+ {
+ dedicatedAllocationsStarted = true;
+ json.WriteString("DedicatedAllocations");
+ json.BeginObject();
+ }
+
+ json.BeginString("Type ");
+ json.ContinueString(memTypeIndex);
+ json.EndString();
+
+ json.BeginArray();
+
+ for(size_t i = 0; i < pDedicatedAllocVector->size(); ++i)
+ {
+ json.BeginObject(true);
+ const VmaAllocation hAlloc = (*pDedicatedAllocVector)[i];
+ hAlloc->PrintParameters(json);
+ json.EndObject();
+ }
+
+ json.EndArray();
+ }
+ }
+ if(dedicatedAllocationsStarted)
+ {
+ json.EndObject();
+ }
+
+ {
+ bool allocationsStarted = false;
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ if(m_pBlockVectors[memTypeIndex]->IsEmpty() == false)
+ {
+ if(allocationsStarted == false)
+ {
+ allocationsStarted = true;
+ json.WriteString("DefaultPools");
+ json.BeginObject();
+ }
+
+ json.BeginString("Type ");
+ json.ContinueString(memTypeIndex);
+ json.EndString();
+
+ m_pBlockVectors[memTypeIndex]->PrintDetailedMap(json);
+ }
+ }
+ if(allocationsStarted)
+ {
+ json.EndObject();
+ }
+ }
+
+ // Custom pools
+ {
+ VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
+ const size_t poolCount = m_Pools.size();
+ if(poolCount > 0)
+ {
+ json.WriteString("Pools");
+ json.BeginObject();
+ for(size_t poolIndex = 0; poolIndex < poolCount; ++poolIndex)
+ {
+ json.BeginString();
+ json.ContinueString(m_Pools[poolIndex]->GetId());
+ json.EndString();
+
+ m_Pools[poolIndex]->m_BlockVector.PrintDetailedMap(json);
+ }
+ json.EndObject();
+ }
+ }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// Public interface
+
+VkResult vmaCreateAllocator(
+ const VmaAllocatorCreateInfo* pCreateInfo,
+ VmaAllocator* pAllocator)
+{
+ VMA_ASSERT(pCreateInfo && pAllocator);
+ VMA_DEBUG_LOG("vmaCreateAllocator");
+ *pAllocator = vma_new(pCreateInfo->pAllocationCallbacks, VmaAllocator_T)(pCreateInfo);
+ return (*pAllocator)->Init(pCreateInfo);
+}
+
+void vmaDestroyAllocator(
+ VmaAllocator allocator)
+{
+ if(allocator != VK_NULL_HANDLE)
+ {
+ VMA_DEBUG_LOG("vmaDestroyAllocator");
+ VkAllocationCallbacks allocationCallbacks = allocator->m_AllocationCallbacks;
+ vma_delete(&allocationCallbacks, allocator);
+ }
+}
+
+void vmaGetPhysicalDeviceProperties(
+ VmaAllocator allocator,
+ const VkPhysicalDeviceProperties **ppPhysicalDeviceProperties)
+{
+ VMA_ASSERT(allocator && ppPhysicalDeviceProperties);
+ *ppPhysicalDeviceProperties = &allocator->m_PhysicalDeviceProperties;
+}
+
+void vmaGetMemoryProperties(
+ VmaAllocator allocator,
+ const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties)
+{
+ VMA_ASSERT(allocator && ppPhysicalDeviceMemoryProperties);
+ *ppPhysicalDeviceMemoryProperties = &allocator->m_MemProps;
+}
+
+void vmaGetMemoryTypeProperties(
+ VmaAllocator allocator,
+ uint32_t memoryTypeIndex,
+ VkMemoryPropertyFlags* pFlags)
+{
+ VMA_ASSERT(allocator && pFlags);
+ VMA_ASSERT(memoryTypeIndex < allocator->GetMemoryTypeCount());
+ *pFlags = allocator->m_MemProps.memoryTypes[memoryTypeIndex].propertyFlags;
+}
+
+void vmaSetCurrentFrameIndex(
+ VmaAllocator allocator,
+ uint32_t frameIndex)
+{
+ VMA_ASSERT(allocator);
+ VMA_ASSERT(frameIndex != VMA_FRAME_INDEX_LOST);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ allocator->SetCurrentFrameIndex(frameIndex);
+}
+
+void vmaCalculateStats(
+ VmaAllocator allocator,
+ VmaStats* pStats)
+{
+ VMA_ASSERT(allocator && pStats);
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+ allocator->CalculateStats(pStats);
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void vmaBuildStatsString(
+ VmaAllocator allocator,
+ char** ppStatsString,
+ VkBool32 detailedMap)
+{
+ VMA_ASSERT(allocator && ppStatsString);
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VmaStringBuilder sb(allocator);
+ {
+ VmaJsonWriter json(allocator->GetAllocationCallbacks(), sb);
+ json.BeginObject();
+
+ VmaStats stats;
+ allocator->CalculateStats(&stats);
+
+ json.WriteString("Total");
+ VmaPrintStatInfo(json, stats.total);
+
+ for(uint32_t heapIndex = 0; heapIndex < allocator->GetMemoryHeapCount(); ++heapIndex)
+ {
+ json.BeginString("Heap ");
+ json.ContinueString(heapIndex);
+ json.EndString();
+ json.BeginObject();
+
+ json.WriteString("Size");
+ json.WriteNumber(allocator->m_MemProps.memoryHeaps[heapIndex].size);
+
+ json.WriteString("Flags");
+ json.BeginArray(true);
+ if((allocator->m_MemProps.memoryHeaps[heapIndex].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
+ {
+ json.WriteString("DEVICE_LOCAL");
+ }
+ json.EndArray();
+
+ if(stats.memoryHeap[heapIndex].blockCount > 0)
+ {
+ json.WriteString("Stats");
+ VmaPrintStatInfo(json, stats.memoryHeap[heapIndex]);
+ }
+
+ for(uint32_t typeIndex = 0; typeIndex < allocator->GetMemoryTypeCount(); ++typeIndex)
+ {
+ if(allocator->MemoryTypeIndexToHeapIndex(typeIndex) == heapIndex)
+ {
+ json.BeginString("Type ");
+ json.ContinueString(typeIndex);
+ json.EndString();
+
+ json.BeginObject();
+
+ json.WriteString("Flags");
+ json.BeginArray(true);
+ VkMemoryPropertyFlags flags = allocator->m_MemProps.memoryTypes[typeIndex].propertyFlags;
+ if((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
+ {
+ json.WriteString("DEVICE_LOCAL");
+ }
+ if((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
+ {
+ json.WriteString("HOST_VISIBLE");
+ }
+ if((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0)
+ {
+ json.WriteString("HOST_COHERENT");
+ }
+ if((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0)
+ {
+ json.WriteString("HOST_CACHED");
+ }
+ if((flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0)
+ {
+ json.WriteString("LAZILY_ALLOCATED");
+ }
+ json.EndArray();
+
+ if(stats.memoryType[typeIndex].blockCount > 0)
+ {
+ json.WriteString("Stats");
+ VmaPrintStatInfo(json, stats.memoryType[typeIndex]);
+ }
+
+ json.EndObject();
+ }
+ }
+
+ json.EndObject();
+ }
+ if(detailedMap == VK_TRUE)
+ {
+ allocator->PrintDetailedMap(json);
+ }
+
+ json.EndObject();
+ }
+
+ const size_t len = sb.GetLength();
+ char* const pChars = vma_new_array(allocator, char, len + 1);
+ if(len > 0)
+ {
+ memcpy(pChars, sb.GetData(), len);
+ }
+ pChars[len] = '\0';
+ *ppStatsString = pChars;
+}
+
+void vmaFreeStatsString(
+ VmaAllocator allocator,
+ char* pStatsString)
+{
+ if(pStatsString != VMA_NULL)
+ {
+ VMA_ASSERT(allocator);
+ size_t len = strlen(pStatsString);
+ vma_delete_array(allocator, pStatsString, len + 1);
+ }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+/*
+This function is not protected by any mutex because it just reads immutable data.
+*/
+VkResult vmaFindMemoryTypeIndex(
+ VmaAllocator allocator,
+ uint32_t memoryTypeBits,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex)
+{
+ VMA_ASSERT(allocator != VK_NULL_HANDLE);
+ VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);
+ VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
+
+ if(pAllocationCreateInfo->memoryTypeBits != 0)
+ {
+ memoryTypeBits &= pAllocationCreateInfo->memoryTypeBits;
+ }
+
+ uint32_t requiredFlags = pAllocationCreateInfo->requiredFlags;
+ uint32_t preferredFlags = pAllocationCreateInfo->preferredFlags;
+
+ const bool mapped = (pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
+ if(mapped)
+ {
+ preferredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ }
+
+ // Convert usage to requiredFlags and preferredFlags.
+ switch(pAllocationCreateInfo->usage)
+ {
+ case VMA_MEMORY_USAGE_UNKNOWN:
+ break;
+ case VMA_MEMORY_USAGE_GPU_ONLY:
+ if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ {
+ preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ break;
+ case VMA_MEMORY_USAGE_CPU_ONLY:
+ requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ break;
+ case VMA_MEMORY_USAGE_CPU_TO_GPU:
+ requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ {
+ preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ break;
+ case VMA_MEMORY_USAGE_GPU_TO_CPU:
+ requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ preferredFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ break;
+ default:
+ break;
+ }
+
+ *pMemoryTypeIndex = UINT32_MAX;
+ uint32_t minCost = UINT32_MAX;
+ for(uint32_t memTypeIndex = 0, memTypeBit = 1;
+ memTypeIndex < allocator->GetMemoryTypeCount();
+ ++memTypeIndex, memTypeBit <<= 1)
+ {
+ // This memory type is acceptable according to memoryTypeBits bitmask.
+ if((memTypeBit & memoryTypeBits) != 0)
+ {
+ const VkMemoryPropertyFlags currFlags =
+ allocator->m_MemProps.memoryTypes[memTypeIndex].propertyFlags;
+ // This memory type contains requiredFlags.
+ if((requiredFlags & ~currFlags) == 0)
+ {
+ // Calculate cost as number of bits from preferredFlags not present in this memory type.
+ uint32_t currCost = VmaCountBitsSet(preferredFlags & ~currFlags);
+ // Remember memory type with lowest cost.
+ if(currCost < minCost)
+ {
+ *pMemoryTypeIndex = memTypeIndex;
+ if(currCost == 0)
+ {
+ return VK_SUCCESS;
+ }
+ minCost = currCost;
+ }
+ }
+ }
+ }
+ return (*pMemoryTypeIndex != UINT32_MAX) ? VK_SUCCESS : VK_ERROR_FEATURE_NOT_PRESENT;
+}
+
+VkResult vmaFindMemoryTypeIndexForBufferInfo(
+ VmaAllocator allocator,
+ const VkBufferCreateInfo* pBufferCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex)
+{
+ VMA_ASSERT(allocator != VK_NULL_HANDLE);
+ VMA_ASSERT(pBufferCreateInfo != VMA_NULL);
+ VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);
+ VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
+
+ const VkDevice hDev = allocator->m_hDevice;
+ VkBuffer hBuffer = VK_NULL_HANDLE;
+ VkResult res = allocator->GetVulkanFunctions().vkCreateBuffer(
+ hDev, pBufferCreateInfo, allocator->GetAllocationCallbacks(), &hBuffer);
+ if(res == VK_SUCCESS)
+ {
+ VkMemoryRequirements memReq = {};
+ allocator->GetVulkanFunctions().vkGetBufferMemoryRequirements(
+ hDev, hBuffer, &memReq);
+
+ res = vmaFindMemoryTypeIndex(
+ allocator,
+ memReq.memoryTypeBits,
+ pAllocationCreateInfo,
+ pMemoryTypeIndex);
+
+ allocator->GetVulkanFunctions().vkDestroyBuffer(
+ hDev, hBuffer, allocator->GetAllocationCallbacks());
+ }
+ return res;
+}
+
+VkResult vmaFindMemoryTypeIndexForImageInfo(
+ VmaAllocator allocator,
+ const VkImageCreateInfo* pImageCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ uint32_t* pMemoryTypeIndex)
+{
+ VMA_ASSERT(allocator != VK_NULL_HANDLE);
+ VMA_ASSERT(pImageCreateInfo != VMA_NULL);
+ VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);
+ VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
+
+ const VkDevice hDev = allocator->m_hDevice;
+ VkImage hImage = VK_NULL_HANDLE;
+ VkResult res = allocator->GetVulkanFunctions().vkCreateImage(
+ hDev, pImageCreateInfo, allocator->GetAllocationCallbacks(), &hImage);
+ if(res == VK_SUCCESS)
+ {
+ VkMemoryRequirements memReq = {};
+ allocator->GetVulkanFunctions().vkGetImageMemoryRequirements(
+ hDev, hImage, &memReq);
+
+ res = vmaFindMemoryTypeIndex(
+ allocator,
+ memReq.memoryTypeBits,
+ pAllocationCreateInfo,
+ pMemoryTypeIndex);
+
+ allocator->GetVulkanFunctions().vkDestroyImage(
+ hDev, hImage, allocator->GetAllocationCallbacks());
+ }
+ return res;
+}
+
+VkResult vmaCreatePool(
+ VmaAllocator allocator,
+ const VmaPoolCreateInfo* pCreateInfo,
+ VmaPool* pPool)
+{
+ VMA_ASSERT(allocator && pCreateInfo && pPool);
+
+ VMA_DEBUG_LOG("vmaCreatePool");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkResult res = allocator->CreatePool(pCreateInfo, pPool);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordCreatePool(allocator->GetCurrentFrameIndex(), *pCreateInfo, *pPool);
+ }
+#endif
+
+ return res;
+}
+
+void vmaDestroyPool(
+ VmaAllocator allocator,
+ VmaPool pool)
+{
+ VMA_ASSERT(allocator);
+
+ if(pool == VK_NULL_HANDLE)
+ {
+ return;
+ }
+
+ VMA_DEBUG_LOG("vmaDestroyPool");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordDestroyPool(allocator->GetCurrentFrameIndex(), pool);
+ }
+#endif
+
+ allocator->DestroyPool(pool);
+}
+
+void vmaGetPoolStats(
+ VmaAllocator allocator,
+ VmaPool pool,
+ VmaPoolStats* pPoolStats)
+{
+ VMA_ASSERT(allocator && pool && pPoolStats);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ allocator->GetPoolStats(pool, pPoolStats);
+}
+
+void vmaMakePoolAllocationsLost(
+ VmaAllocator allocator,
+ VmaPool pool,
+ size_t* pLostAllocationCount)
+{
+ VMA_ASSERT(allocator && pool);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordMakePoolAllocationsLost(allocator->GetCurrentFrameIndex(), pool);
+ }
+#endif
+
+ allocator->MakePoolAllocationsLost(pool, pLostAllocationCount);
+}
+
+VkResult vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool)
+{
+ VMA_ASSERT(allocator && pool);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VMA_DEBUG_LOG("vmaCheckPoolCorruption");
+
+ return allocator->CheckPoolCorruption(pool);
+}
+
+VkResult vmaAllocateMemory(
+ VmaAllocator allocator,
+ const VkMemoryRequirements* pVkMemoryRequirements,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocation);
+
+ VMA_DEBUG_LOG("vmaAllocateMemory");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkResult result = allocator->AllocateMemory(
+ *pVkMemoryRequirements,
+ false, // requiresDedicatedAllocation
+ false, // prefersDedicatedAllocation
+ VK_NULL_HANDLE, // dedicatedBuffer
+ VK_NULL_HANDLE, // dedicatedImage
+ *pCreateInfo,
+ VMA_SUBALLOCATION_TYPE_UNKNOWN,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordAllocateMemory(
+ allocator->GetCurrentFrameIndex(),
+ *pVkMemoryRequirements,
+ *pCreateInfo,
+ *pAllocation);
+ }
+#endif
+
+ if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return result;
+}
+
+VkResult vmaAllocateMemoryPages(
+ VmaAllocator allocator,
+ const VkMemoryRequirements* pVkMemoryRequirements,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ size_t allocationCount,
+ VmaAllocation* pAllocations,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ if(allocationCount == 0)
+ {
+ return VK_SUCCESS;
+ }
+
+ VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocations);
+
+ VMA_DEBUG_LOG("vmaAllocateMemoryPages");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkResult result = allocator->AllocateMemory(
+ *pVkMemoryRequirements,
+ false, // requiresDedicatedAllocation
+ false, // prefersDedicatedAllocation
+ VK_NULL_HANDLE, // dedicatedBuffer
+ VK_NULL_HANDLE, // dedicatedImage
+ *pCreateInfo,
+ VMA_SUBALLOCATION_TYPE_UNKNOWN,
+ allocationCount,
+ pAllocations);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordAllocateMemoryPages(
+ allocator->GetCurrentFrameIndex(),
+ *pVkMemoryRequirements,
+ *pCreateInfo,
+ (uint64_t)allocationCount,
+ pAllocations);
+ }
+#endif
+
+ if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS)
+ {
+ for(size_t i = 0; i < allocationCount; ++i)
+ {
+ allocator->GetAllocationInfo(pAllocations[i], pAllocationInfo + i);
+ }
+ }
+
+ return result;
+}
+
+VkResult vmaAllocateMemoryForBuffer(
+ VmaAllocator allocator,
+ VkBuffer buffer,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && buffer != VK_NULL_HANDLE && pCreateInfo && pAllocation);
+
+ VMA_DEBUG_LOG("vmaAllocateMemoryForBuffer");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkMemoryRequirements vkMemReq = {};
+ bool requiresDedicatedAllocation = false;
+ bool prefersDedicatedAllocation = false;
+ allocator->GetBufferMemoryRequirements(buffer, vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation);
+
+ VkResult result = allocator->AllocateMemory(
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ buffer, // dedicatedBuffer
+ VK_NULL_HANDLE, // dedicatedImage
+ *pCreateInfo,
+ VMA_SUBALLOCATION_TYPE_BUFFER,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordAllocateMemoryForBuffer(
+ allocator->GetCurrentFrameIndex(),
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ *pCreateInfo,
+ *pAllocation);
+ }
+#endif
+
+ if(pAllocationInfo && result == VK_SUCCESS)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return result;
+}
+
+VkResult vmaAllocateMemoryForImage(
+ VmaAllocator allocator,
+ VkImage image,
+ const VmaAllocationCreateInfo* pCreateInfo,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && image != VK_NULL_HANDLE && pCreateInfo && pAllocation);
+
+ VMA_DEBUG_LOG("vmaAllocateMemoryForImage");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkMemoryRequirements vkMemReq = {};
+ bool requiresDedicatedAllocation = false;
+ bool prefersDedicatedAllocation = false;
+ allocator->GetImageMemoryRequirements(image, vkMemReq,
+ requiresDedicatedAllocation, prefersDedicatedAllocation);
+
+ VkResult result = allocator->AllocateMemory(
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ VK_NULL_HANDLE, // dedicatedBuffer
+ image, // dedicatedImage
+ *pCreateInfo,
+ VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordAllocateMemoryForImage(
+ allocator->GetCurrentFrameIndex(),
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ *pCreateInfo,
+ *pAllocation);
+ }
+#endif
+
+ if(pAllocationInfo && result == VK_SUCCESS)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return result;
+}
+
+void vmaFreeMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator);
+
+ if(allocation == VK_NULL_HANDLE)
+ {
+ return;
+ }
+
+ VMA_DEBUG_LOG("vmaFreeMemory");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordFreeMemory(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ allocator->FreeMemory(
+ 1, // allocationCount
+ &allocation);
+}
+
+void vmaFreeMemoryPages(
+ VmaAllocator allocator,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ if(allocationCount == 0)
+ {
+ return;
+ }
+
+ VMA_ASSERT(allocator);
+
+ VMA_DEBUG_LOG("vmaFreeMemoryPages");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordFreeMemoryPages(
+ allocator->GetCurrentFrameIndex(),
+ (uint64_t)allocationCount,
+ pAllocations);
+ }
+#endif
+
+ allocator->FreeMemory(allocationCount, pAllocations);
+}
+
+VkResult vmaResizeAllocation(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkDeviceSize newSize)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_LOG("vmaResizeAllocation");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordResizeAllocation(
+ allocator->GetCurrentFrameIndex(),
+ allocation,
+ newSize);
+ }
+#endif
+
+ return allocator->ResizeAllocation(allocation, newSize);
+}
+
+void vmaGetAllocationInfo(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && allocation && pAllocationInfo);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordGetAllocationInfo(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ allocator->GetAllocationInfo(allocation, pAllocationInfo);
+}
+
+VkBool32 vmaTouchAllocation(
+ VmaAllocator allocator,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordTouchAllocation(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ return allocator->TouchAllocation(allocation);
+}
+
+void vmaSetAllocationUserData(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ void* pUserData)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ allocation->SetUserData(allocator, pUserData);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordSetAllocationUserData(
+ allocator->GetCurrentFrameIndex(),
+ allocation,
+ pUserData);
+ }
+#endif
+}
+
+void vmaCreateLostAllocation(
+ VmaAllocator allocator,
+ VmaAllocation* pAllocation)
+{
+ VMA_ASSERT(allocator && pAllocation);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+
+ allocator->CreateLostAllocation(pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordCreateLostAllocation(
+ allocator->GetCurrentFrameIndex(),
+ *pAllocation);
+ }
+#endif
+}
+
+VkResult vmaMapMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ void** ppData)
+{
+ VMA_ASSERT(allocator && allocation && ppData);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkResult res = allocator->Map(allocation, ppData);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordMapMemory(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ return res;
+}
+
+void vmaUnmapMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordUnmapMemory(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ allocator->Unmap(allocation);
+}
+
+void vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_LOG("vmaFlushAllocation");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordFlushAllocation(
+ allocator->GetCurrentFrameIndex(),
+ allocation, offset, size);
+ }
+#endif
+}
+
+void vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+ VMA_ASSERT(allocator && allocation);
+
+ VMA_DEBUG_LOG("vmaInvalidateAllocation");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordInvalidateAllocation(
+ allocator->GetCurrentFrameIndex(),
+ allocation, offset, size);
+ }
+#endif
+}
+
+VkResult vmaCheckCorruption(VmaAllocator allocator, uint32_t memoryTypeBits)
+{
+ VMA_ASSERT(allocator);
+
+ VMA_DEBUG_LOG("vmaCheckCorruption");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ return allocator->CheckCorruption(memoryTypeBits);
+}
+
+VkResult vmaDefragment(
+ VmaAllocator allocator,
+ VmaAllocation* pAllocations,
+ size_t allocationCount,
+ VkBool32* pAllocationsChanged,
+ const VmaDefragmentationInfo *pDefragmentationInfo,
+ VmaDefragmentationStats* pDefragmentationStats)
+{
+ // Deprecated interface, reimplemented using new one.
+
+ VmaDefragmentationInfo2 info2 = {};
+ info2.allocationCount = (uint32_t)allocationCount;
+ info2.pAllocations = pAllocations;
+ info2.pAllocationsChanged = pAllocationsChanged;
+ if(pDefragmentationInfo != VMA_NULL)
+ {
+ info2.maxCpuAllocationsToMove = pDefragmentationInfo->maxAllocationsToMove;
+ info2.maxCpuBytesToMove = pDefragmentationInfo->maxBytesToMove;
+ }
+ else
+ {
+ info2.maxCpuAllocationsToMove = UINT32_MAX;
+ info2.maxCpuBytesToMove = VK_WHOLE_SIZE;
+ }
+ // info2.flags, maxGpuAllocationsToMove, maxGpuBytesToMove, commandBuffer deliberately left zero.
+
+ VmaDefragmentationContext ctx;
+ VkResult res = vmaDefragmentationBegin(allocator, &info2, pDefragmentationStats, &ctx);
+ if(res == VK_NOT_READY)
+ {
+ res = vmaDefragmentationEnd( allocator, ctx);
+ }
+ return res;
+}
+
+VkResult vmaDefragmentationBegin(
+ VmaAllocator allocator,
+ const VmaDefragmentationInfo2* pInfo,
+ VmaDefragmentationStats* pStats,
+ VmaDefragmentationContext *pContext)
+{
+ VMA_ASSERT(allocator && pInfo && pContext);
+
+ // Degenerate case: Nothing to defragment.
+ if(pInfo->allocationCount == 0 && pInfo->poolCount == 0)
+ {
+ return VK_SUCCESS;
+ }
+
+ VMA_ASSERT(pInfo->allocationCount == 0 || pInfo->pAllocations != VMA_NULL);
+ VMA_ASSERT(pInfo->poolCount == 0 || pInfo->pPools != VMA_NULL);
+ VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->allocationCount, pInfo->pAllocations));
+ VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->poolCount, pInfo->pPools));
+
+ VMA_DEBUG_LOG("vmaDefragmentationBegin");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ VkResult res = allocator->DefragmentationBegin(*pInfo, pStats, pContext);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordDefragmentationBegin(
+ allocator->GetCurrentFrameIndex(), *pInfo, *pContext);
+ }
+#endif
+
+ return res;
+}
+
+VkResult vmaDefragmentationEnd(
+ VmaAllocator allocator,
+ VmaDefragmentationContext context)
+{
+ VMA_ASSERT(allocator);
+
+ VMA_DEBUG_LOG("vmaDefragmentationEnd");
+
+ if(context != VK_NULL_HANDLE)
+ {
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordDefragmentationEnd(
+ allocator->GetCurrentFrameIndex(), context);
+ }
+#endif
+
+ return allocator->DefragmentationEnd(context);
+ }
+ else
+ {
+ return VK_SUCCESS;
+ }
+}
+
+VkResult vmaBindBufferMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkBuffer buffer)
+{
+ VMA_ASSERT(allocator && allocation && buffer);
+
+ VMA_DEBUG_LOG("vmaBindBufferMemory");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ return allocator->BindBufferMemory(allocation, buffer);
+}
+
+VkResult vmaBindImageMemory(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkImage image)
+{
+ VMA_ASSERT(allocator && allocation && image);
+
+ VMA_DEBUG_LOG("vmaBindImageMemory");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ return allocator->BindImageMemory(allocation, image);
+}
+
+VkResult vmaCreateBuffer(
+ VmaAllocator allocator,
+ const VkBufferCreateInfo* pBufferCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkBuffer* pBuffer,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && pBuffer && pAllocation);
+
+ if(pBufferCreateInfo->size == 0)
+ {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+
+ VMA_DEBUG_LOG("vmaCreateBuffer");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ *pBuffer = VK_NULL_HANDLE;
+ *pAllocation = VK_NULL_HANDLE;
+
+ // 1. Create VkBuffer.
+ VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)(
+ allocator->m_hDevice,
+ pBufferCreateInfo,
+ allocator->GetAllocationCallbacks(),
+ pBuffer);
+ if(res >= 0)
+ {
+ // 2. vkGetBufferMemoryRequirements.
+ VkMemoryRequirements vkMemReq = {};
+ bool requiresDedicatedAllocation = false;
+ bool prefersDedicatedAllocation = false;
+ allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq,
+ requiresDedicatedAllocation, prefersDedicatedAllocation);
+
+ // Make sure alignment requirements for specific buffer usages reported
+ // in Physical Device Properties are included in alignment reported by memory requirements.
+ if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) != 0)
+ {
+ VMA_ASSERT(vkMemReq.alignment %
+ allocator->m_PhysicalDeviceProperties.limits.minTexelBufferOffsetAlignment == 0);
+ }
+ if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) != 0)
+ {
+ VMA_ASSERT(vkMemReq.alignment %
+ allocator->m_PhysicalDeviceProperties.limits.minUniformBufferOffsetAlignment == 0);
+ }
+ if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) != 0)
+ {
+ VMA_ASSERT(vkMemReq.alignment %
+ allocator->m_PhysicalDeviceProperties.limits.minStorageBufferOffsetAlignment == 0);
+ }
+
+ // 3. Allocate memory using allocator.
+ res = allocator->AllocateMemory(
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ *pBuffer, // dedicatedBuffer
+ VK_NULL_HANDLE, // dedicatedImage
+ *pAllocationCreateInfo,
+ VMA_SUBALLOCATION_TYPE_BUFFER,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordCreateBuffer(
+ allocator->GetCurrentFrameIndex(),
+ *pBufferCreateInfo,
+ *pAllocationCreateInfo,
+ *pAllocation);
+ }
+#endif
+
+ if(res >= 0)
+ {
+ // 3. Bind buffer with memory.
+ res = allocator->BindBufferMemory(*pAllocation, *pBuffer);
+ if(res >= 0)
+ {
+ // All steps succeeded.
+ #if VMA_STATS_STRING_ENABLED
+ (*pAllocation)->InitBufferImageUsage(pBufferCreateInfo->usage);
+ #endif
+ if(pAllocationInfo != VMA_NULL)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return VK_SUCCESS;
+ }
+ allocator->FreeMemory(
+ 1, // allocationCount
+ pAllocation);
+ *pAllocation = VK_NULL_HANDLE;
+ (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());
+ *pBuffer = VK_NULL_HANDLE;
+ return res;
+ }
+ (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());
+ *pBuffer = VK_NULL_HANDLE;
+ return res;
+ }
+ return res;
+}
+
+void vmaDestroyBuffer(
+ VmaAllocator allocator,
+ VkBuffer buffer,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator);
+
+ if(buffer == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE)
+ {
+ return;
+ }
+
+ VMA_DEBUG_LOG("vmaDestroyBuffer");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordDestroyBuffer(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ if(buffer != VK_NULL_HANDLE)
+ {
+ (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, buffer, allocator->GetAllocationCallbacks());
+ }
+
+ if(allocation != VK_NULL_HANDLE)
+ {
+ allocator->FreeMemory(
+ 1, // allocationCount
+ &allocation);
+ }
+}
+
+VkResult vmaCreateImage(
+ VmaAllocator allocator,
+ const VkImageCreateInfo* pImageCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkImage* pImage,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && pImageCreateInfo && pAllocationCreateInfo && pImage && pAllocation);
+
+ if(pImageCreateInfo->extent.width == 0 ||
+ pImageCreateInfo->extent.height == 0 ||
+ pImageCreateInfo->extent.depth == 0 ||
+ pImageCreateInfo->mipLevels == 0 ||
+ pImageCreateInfo->arrayLayers == 0)
+ {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+
+ VMA_DEBUG_LOG("vmaCreateImage");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ *pImage = VK_NULL_HANDLE;
+ *pAllocation = VK_NULL_HANDLE;
+
+ // 1. Create VkImage.
+ VkResult res = (*allocator->GetVulkanFunctions().vkCreateImage)(
+ allocator->m_hDevice,
+ pImageCreateInfo,
+ allocator->GetAllocationCallbacks(),
+ pImage);
+ if(res >= 0)
+ {
+ VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ?
+ VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL :
+ VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR;
+
+ // 2. Allocate memory using allocator.
+ VkMemoryRequirements vkMemReq = {};
+ bool requiresDedicatedAllocation = false;
+ bool prefersDedicatedAllocation = false;
+ allocator->GetImageMemoryRequirements(*pImage, vkMemReq,
+ requiresDedicatedAllocation, prefersDedicatedAllocation);
+
+ res = allocator->AllocateMemory(
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ VK_NULL_HANDLE, // dedicatedBuffer
+ *pImage, // dedicatedImage
+ *pAllocationCreateInfo,
+ suballocType,
+ 1, // allocationCount
+ pAllocation);
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordCreateImage(
+ allocator->GetCurrentFrameIndex(),
+ *pImageCreateInfo,
+ *pAllocationCreateInfo,
+ *pAllocation);
+ }
+#endif
+
+ if(res >= 0)
+ {
+ // 3. Bind image with memory.
+ res = allocator->BindImageMemory(*pAllocation, *pImage);
+ if(res >= 0)
+ {
+ // All steps succeeded.
+ #if VMA_STATS_STRING_ENABLED
+ (*pAllocation)->InitBufferImageUsage(pImageCreateInfo->usage);
+ #endif
+ if(pAllocationInfo != VMA_NULL)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return VK_SUCCESS;
+ }
+ allocator->FreeMemory(
+ 1, // allocationCount
+ pAllocation);
+ *pAllocation = VK_NULL_HANDLE;
+ (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks());
+ *pImage = VK_NULL_HANDLE;
+ return res;
+ }
+ (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks());
+ *pImage = VK_NULL_HANDLE;
+ return res;
+ }
+ return res;
+}
+
+void vmaDestroyImage(
+ VmaAllocator allocator,
+ VkImage image,
+ VmaAllocation allocation)
+{
+ VMA_ASSERT(allocator);
+
+ if(image == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE)
+ {
+ return;
+ }
+
+ VMA_DEBUG_LOG("vmaDestroyImage");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+ if(allocator->GetRecorder() != VMA_NULL)
+ {
+ allocator->GetRecorder()->RecordDestroyImage(
+ allocator->GetCurrentFrameIndex(),
+ allocation);
+ }
+#endif
+
+ if(image != VK_NULL_HANDLE)
+ {
+ (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, image, allocator->GetAllocationCallbacks());
+ }
+ if(allocation != VK_NULL_HANDLE)
+ {
+ allocator->FreeMemory(
+ 1, // allocationCount
+ &allocation);
+ }
+}
+
+#endif // #ifdef VMA_IMPLEMENTATION
diff --git a/src/3rdparty/angle/src/libANGLE/validationES.cpp b/src/3rdparty/angle/src/libANGLE/validationES.cpp
index ae564b7412..069ca045f8 100644
--- a/src/3rdparty/angle/src/libANGLE/validationES.cpp
+++ b/src/3rdparty/angle/src/libANGLE/validationES.cpp
@@ -3525,7 +3525,7 @@ bool ValidateGetBufferPointervBase(Context *context,
if (context->getGLState().getTargetBuffer(target) == nullptr)
{
context->handleError(InvalidOperation()
- << "Can not get pointer for reserved buffer name zero.");
+ << "Cannot get pointer for reserved buffer name zero.");
return false;
}
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp
index 704ea9774a..de3bcb2bbf 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp
@@ -1471,7 +1471,7 @@ static bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool inv
while (finalOrder[toMove].form && fixed < len-1) {
IDEBUG(" fixed = %d, toMove=%d, moving form %d with pos %d", fixed, toMove, finalOrder[toMove].form, finalOrder[toMove].position);
for (i = fixed; i < len; i++) {
-// IDEBUG() << " i=" << i << "uc=" << hex << uc[i] << "form=" << form(uc[i])
+// IDEBUG() << " i=" << i << "uc=" << Qt::hex << uc[i] << "form=" << form(uc[i])
// << "position=" << position[i];
if (form(uc[i]) == finalOrder[toMove].form &&
position[i] == finalOrder[toMove].position) {
diff --git a/src/3rdparty/harfbuzz/tests/shaping/main.cpp b/src/3rdparty/harfbuzz/tests/shaping/main.cpp
index 10818c565c..16f469029b 100644
--- a/src/3rdparty/harfbuzz/tests/shaping/main.cpp
+++ b/src/3rdparty/harfbuzz/tests/shaping/main.cpp
@@ -370,7 +370,7 @@ void tst_QScriptEngine::greek()
QString str;
str.append(uc);
if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) {
- //qDebug() << "skipping" << hex << uc;
+ //qDebug() << "skipping" << Qt::hex << uc;
continue;
}
if (uc == 0x1fc1 || uc == 0x1fed)
@@ -389,7 +389,7 @@ void tst_QScriptEngine::greek()
QString str;
str.append(uc);
if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) {
- //qDebug() << "skipping" << hex << uc;
+ //qDebug() << "skipping" << Qt::hex << uc;
continue;
}
if (uc == 0x1fc1 || uc == 0x1fed)
diff --git a/src/3rdparty/libjpeg/LICENSE b/src/3rdparty/libjpeg/LICENSE
index 0f6ec4b30a..5ca512b34d 100644
--- a/src/3rdparty/libjpeg/LICENSE
+++ b/src/3rdparty/libjpeg/LICENSE
@@ -14,7 +14,7 @@ libjpeg-turbo is covered by three compatible BSD-style open source licenses:
This license covers the TurboJPEG API library and associated programs, as
well as the build system.
-- The zlib License, which is listed below
+- The [zlib License](https://opensource.org/licenses/Zlib)
This license is a subset of the other two, and it covers the libjpeg-turbo
SIMD extensions.
@@ -66,7 +66,7 @@ best of our understanding.
2. If your binary distribution includes or uses the TurboJPEG API, then
your product documentation must include the text of the Modified BSD
- License.
+ License (see below.)
**Origin**
- Clause 2 of the Modified BSD License
@@ -91,7 +91,8 @@ best of our understanding.
The Modified (3-clause) BSD License
===================================
-Copyright (C)\<YEAR\> \<AUTHOR\>. All Rights Reserved.
+Copyright (C)2009-2019 D. R. Commander. All Rights Reserved.
+Copyright (C)2015 Viktor Szathmáry. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -118,28 +119,6 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-The zlib License
-================
-
-Copyright (C) \<YEAR\>, \<AUTHOR\>.
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
-
Why Three Licenses?
===================
diff --git a/src/3rdparty/libjpeg/jconfig.h b/src/3rdparty/libjpeg/jconfig.h
index bcfef5f0b6..3f6a7f6b3c 100644
--- a/src/3rdparty/libjpeg/jconfig.h
+++ b/src/3rdparty/libjpeg/jconfig.h
@@ -2,22 +2,22 @@
#define JPEG_LIB_VERSION 80
-#define LIBJPEG_TURBO_VERSION 2.0.0
+#define LIBJPEG_TURBO_VERSION 2.0.2
-#define LIBJPEG_TURBO_VERSION_NUMBER 2000000
+#define LIBJPEG_TURBO_VERSION_NUMBER 2000002
-#define C_ARITH_CODING_SUPPORTED
+#define C_ARITH_CODING_SUPPORTED 1
-#define D_ARITH_CODING_SUPPORTED
+#define D_ARITH_CODING_SUPPORTED 1
-#define MEM_SRCDST_SUPPORTED
+#define MEM_SRCDST_SUPPORTED 1
#define BITS_IN_JSAMPLE 8
-#define HAVE_STDDEF_H
+#define HAVE_STDDEF_H 1
-#define HAVE_STDLIB_H
+#define HAVE_STDLIB_H 1
-#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_CHAR 1
-#define HAVE_UNSIGNED_SHORT
+#define HAVE_UNSIGNED_SHORT 1
diff --git a/src/3rdparty/libjpeg/qt_attribution.json b/src/3rdparty/libjpeg/qt_attribution.json
index 8fbdfdb9b7..d1497bc20f 100644
--- a/src/3rdparty/libjpeg/qt_attribution.json
+++ b/src/3rdparty/libjpeg/qt_attribution.json
@@ -6,11 +6,11 @@
"Description": "The Independent JPEG Group's JPEG software",
"Homepage": "http://libjpeg-turbo.virtualgl.org/",
- "Version": "2.0.0",
+ "Version": "2.0.2",
"License": "Independent JPEG Group License",
"LicenseId": "IJG",
"LicenseFile": "LICENSE",
- "Copyright": "Copyright (C) 2009-2018 D. R. Commander
+ "Copyright": "Copyright (C) 2009-2019 D. R. Commander
Copyright (C) 2011-2016 Siarhei Siamashka
Copyright (C) 2015-2016, 2018 Matthieu Darbois
Copyright (C) 2015 Intel Corporation
diff --git a/src/3rdparty/libjpeg/src/ChangeLog.md b/src/3rdparty/libjpeg/src/ChangeLog.md
index 8f0d11b1a6..7cf92c30fd 100644
--- a/src/3rdparty/libjpeg/src/ChangeLog.md
+++ b/src/3rdparty/libjpeg/src/ChangeLog.md
@@ -1,3 +1,73 @@
+2.0.2
+=====
+
+### Significant changes relative to 2.0.1:
+
+1. Fixed a regression introduced by 2.0.1[5] that prevented a runtime search
+path (rpath) from being embedded in the libjpeg-turbo shared libraries and
+executables for macOS and iOS. This caused a fatal error of the form
+"dyld: Library not loaded" when attempting to use one of the executables,
+unless `DYLD_LIBRARY_PATH` was explicitly set to the location of the
+libjpeg-turbo shared libraries.
+
+2. Fixed an integer overflow and subsequent segfault (CVE-2018-20330) that
+occurred when attempting to load a BMP file with more than 1 billion pixels
+using the `tjLoadImage()` function.
+
+3. Fixed a buffer overrun (CVE-2018-19664) that occurred when attempting to
+decompress a specially-crafted malformed JPEG image to a 256-color BMP using
+djpeg.
+
+4. Fixed a floating point exception that occurred when attempting to
+decompress a specially-crafted malformed JPEG image with a specified image
+width or height of 0 using the C version of TJBench.
+
+5. The TurboJPEG API will now decompress 4:4:4 JPEG images with 2x1, 1x2, 3x1,
+or 1x3 luminance and chrominance sampling factors. This is a non-standard way
+of specifying 1x subsampling (normally 4:4:4 JPEGs have 1x1 luminance and
+chrominance sampling factors), but the JPEG format and the libjpeg API both
+allow it.
+
+6. Fixed a regression introduced by 2.0 beta1[7] that caused djpeg to generate
+incorrect PPM images when used with the `-colors` option.
+
+7. Fixed an issue whereby a static build of libjpeg-turbo (a build in which
+`ENABLE_SHARED` is `0`) could not be installed using the Visual Studio IDE.
+
+8. Fixed a severe performance issue in the Loongson MMI SIMD extensions that
+occurred when compressing RGB images whose image rows were not 64-bit-aligned.
+
+
+2.0.1
+=====
+
+### Significant changes relative to 2.0.0:
+
+1. Fixed a regression introduced with the new CMake-based Un*x build system,
+whereby jconfig.h could cause compiler warnings of the form
+`"HAVE_*_H" redefined` if it was included by downstream Autotools-based
+projects that used `AC_CHECK_HEADERS()` to check for the existence of locale.h,
+stddef.h, or stdlib.h.
+
+2. The `jsimd_quantize_float_dspr2()` and `jsimd_convsamp_float_dspr2()`
+functions in the MIPS DSPr2 SIMD extensions are now disabled at compile time
+if the soft float ABI is enabled. Those functions use instructions that are
+incompatible with the soft float ABI.
+
+3. Fixed a regression in the SIMD feature detection code, introduced by
+the AVX2 SIMD extensions (2.0 beta1[1]), that caused libjpeg-turbo to crash on
+Windows 7 if Service Pack 1 was not installed.
+
+4. Fixed out-of-bounds read in cjpeg that occurred when attempting to compress
+a specially-crafted malformed color-index (8-bit-per-sample) Targa file in
+which some of the samples (color indices) exceeded the bounds of the Targa
+file's color table.
+
+5. Fixed an issue whereby installing a fully static build of libjpeg-turbo
+(a build in which `CFLAGS` contains `-static` and `ENABLE_SHARED` is `0`) would
+fail with "No valid ELF RPATH or RUNPATH entry exists in the file."
+
+
2.0.0
=====
diff --git a/src/3rdparty/libjpeg/src/jconfig.h.in b/src/3rdparty/libjpeg/src/jconfig.h.in
index 28427548e8..18a69a4814 100644
--- a/src/3rdparty/libjpeg/src/jconfig.h.in
+++ b/src/3rdparty/libjpeg/src/jconfig.h.in
@@ -10,16 +10,16 @@
#define LIBJPEG_TURBO_VERSION_NUMBER @LIBJPEG_TURBO_VERSION_NUMBER@
/* Support arithmetic encoding */
-#cmakedefine C_ARITH_CODING_SUPPORTED
+#cmakedefine C_ARITH_CODING_SUPPORTED 1
/* Support arithmetic decoding */
-#cmakedefine D_ARITH_CODING_SUPPORTED
+#cmakedefine D_ARITH_CODING_SUPPORTED 1
/* Support in-memory source/destination managers */
-#cmakedefine MEM_SRCDST_SUPPORTED
+#cmakedefine MEM_SRCDST_SUPPORTED 1
/* Use accelerated SIMD routines. */
-#cmakedefine WITH_SIMD
+#cmakedefine WITH_SIMD 1
/*
* Define BITS_IN_JSAMPLE as either
@@ -33,37 +33,37 @@
#define BITS_IN_JSAMPLE @BITS_IN_JSAMPLE@ /* use 8 or 12 */
/* Define to 1 if you have the <locale.h> header file. */
-#cmakedefine HAVE_LOCALE_H
+#cmakedefine HAVE_LOCALE_H 1
/* Define to 1 if you have the <stddef.h> header file. */
-#cmakedefine HAVE_STDDEF_H
+#cmakedefine HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
-#cmakedefine HAVE_STDLIB_H
+#cmakedefine HAVE_STDLIB_H 1
/* Define if you need to include <sys/types.h> to get size_t. */
-#cmakedefine NEED_SYS_TYPES_H
+#cmakedefine NEED_SYS_TYPES_H 1
/* Define if you have BSD-like bzero and bcopy in <strings.h> rather than
memset/memcpy in <string.h>. */
-#cmakedefine NEED_BSD_STRINGS
+#cmakedefine NEED_BSD_STRINGS 1
/* Define to 1 if the system has the type `unsigned char'. */
-#cmakedefine HAVE_UNSIGNED_CHAR
+#cmakedefine HAVE_UNSIGNED_CHAR 1
/* Define to 1 if the system has the type `unsigned short'. */
-#cmakedefine HAVE_UNSIGNED_SHORT
+#cmakedefine HAVE_UNSIGNED_SHORT 1
/* Compiler does not support pointers to undefined structures. */
-#cmakedefine INCOMPLETE_TYPES_BROKEN
+#cmakedefine INCOMPLETE_TYPES_BROKEN 1
/* Define if your (broken) compiler shifts signed values as if they were
unsigned. */
-#cmakedefine RIGHT_SHIFT_IS_UNSIGNED
+#cmakedefine RIGHT_SHIFT_IS_UNSIGNED 1
/* Define to 1 if type `char' is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
- #cmakedefine __CHAR_UNSIGNED__
+ #cmakedefine __CHAR_UNSIGNED__ 1
#endif
/* Define to empty if `const' does not conform to ANSI C. */
diff --git a/src/3rdparty/libjpeg/src/jdcolor.c b/src/3rdparty/libjpeg/src/jdcolor.c
index fd7f661d5a..dc0e3b6c0e 100644
--- a/src/3rdparty/libjpeg/src/jdcolor.c
+++ b/src/3rdparty/libjpeg/src/jdcolor.c
@@ -592,7 +592,7 @@ ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
/* Declarations for ordered dithering
*
* We use a 4x4 ordered dither array packed into 32 bits. This array is
- * sufficent for dithering RGB888 to RGB565.
+ * sufficient for dithering RGB888 to RGB565.
*/
#define DITHER_MASK 0x3
diff --git a/src/3rdparty/libjpeg/src/jdmerge.c b/src/3rdparty/libjpeg/src/jdmerge.c
index d67faec036..b3fec04f71 100644
--- a/src/3rdparty/libjpeg/src/jdmerge.c
+++ b/src/3rdparty/libjpeg/src/jdmerge.c
@@ -448,7 +448,7 @@ h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
/* Declarations for ordered dithering
*
* We use a 4x4 ordered dither array packed into 32 bits. This array is
- * sufficent for dithering RGB888 to RGB565.
+ * sufficient for dithering RGB888 to RGB565.
*/
#define DITHER_MASK 0x3
diff --git a/src/3rdparty/libjpeg/src/jquant1.c b/src/3rdparty/libjpeg/src/jquant1.c
index a336abdbbb..40bbb28cc7 100644
--- a/src/3rdparty/libjpeg/src/jquant1.c
+++ b/src/3rdparty/libjpeg/src/jquant1.c
@@ -154,7 +154,7 @@ typedef struct {
*/
boolean is_padded; /* is the colorindex padded for odither? */
- int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */
+ int Ncolors[MAX_Q_COMPS]; /* # of values allocated to each component */
/* Variables for ordered dithering */
int row_index; /* cur row's vertical index in dither matrix */
diff --git a/src/3rdparty/libjpeg/src/jversion.h b/src/3rdparty/libjpeg/src/jversion.h
index 2039f44c3a..191fb6bb54 100644
--- a/src/3rdparty/libjpeg/src/jversion.h
+++ b/src/3rdparty/libjpeg/src/jversion.h
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010, 2012-2018, D. R. Commander.
+ * Copyright (C) 2010, 2012-2019, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -36,7 +36,7 @@
*/
#define JCOPYRIGHT \
- "Copyright (C) 2009-2018 D. R. Commander\n" \
+ "Copyright (C) 2009-2019 D. R. Commander\n" \
"Copyright (C) 2011-2016 Siarhei Siamashka\n" \
"Copyright (C) 2015-2016, 2018 Matthieu Darbois\n" \
"Copyright (C) 2015 Intel Corporation\n" \
@@ -49,4 +49,4 @@
"Copyright (C) 1991-2016 Thomas G. Lane, Guido Vollbeding"
#define JCOPYRIGHT_SHORT \
- "Copyright (C) 1991-2018 The libjpeg-turbo Project and many others"
+ "Copyright (C) 1991-2019 The libjpeg-turbo Project and many others"
diff --git a/src/3rdparty/md4c.pri b/src/3rdparty/md4c.pri
new file mode 100644
index 0000000000..e0150dc6ed
--- /dev/null
+++ b/src/3rdparty/md4c.pri
@@ -0,0 +1,3 @@
+INCLUDEPATH += $$PWD/md4c
+HEADERS += $$PWD/md4c/md4c.h
+SOURCES += $$PWD/md4c/md4c.c
diff --git a/src/3rdparty/md4c/LICENSE.md b/src/3rdparty/md4c/LICENSE.md
new file mode 100644
index 0000000000..d58ef9341d
--- /dev/null
+++ b/src/3rdparty/md4c/LICENSE.md
@@ -0,0 +1,22 @@
+
+# The MIT License (MIT)
+
+Copyright © 2016-2019 Martin Mitáš
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the “Softwareâ€),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
diff --git a/src/3rdparty/md4c/md4c.c b/src/3rdparty/md4c/md4c.c
new file mode 100644
index 0000000000..01e63a5fd2
--- /dev/null
+++ b/src/3rdparty/md4c/md4c.c
@@ -0,0 +1,6109 @@
+/*
+ * MD4C: Markdown parser for C
+ * (http://github.com/mity/md4c)
+ *
+ * Copyright (c) 2016-2019 Martin Mitas
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "md4c.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/*****************************
+ *** Miscellaneous Stuff ***
+ *****************************/
+
+#ifdef _MSC_VER
+ /* MSVC does not understand "inline" when building as pure C (not C++).
+ * However it understands "__inline" */
+ #ifndef __cplusplus
+ #define inline __inline
+ #endif
+#endif
+
+#ifdef _T
+ #undef _T
+#endif
+#if defined MD4C_USE_UTF16
+ #define _T(x) L##x
+#else
+ #define _T(x) x
+#endif
+
+/* Misc. macros. */
+#define SIZEOF_ARRAY(a) (sizeof(a) / sizeof(a[0]))
+
+#define STRINGIZE_(x) #x
+#define STRINGIZE(x) STRINGIZE_(x)
+
+#ifndef TRUE
+ #define TRUE 1
+ #define FALSE 0
+#endif
+
+
+/************************
+ *** Internal Types ***
+ ************************/
+
+/* These are omnipresent so lets save some typing. */
+#define CHAR MD_CHAR
+#define SZ MD_SIZE
+#define OFF MD_OFFSET
+
+typedef struct MD_MARK_tag MD_MARK;
+typedef struct MD_BLOCK_tag MD_BLOCK;
+typedef struct MD_CONTAINER_tag MD_CONTAINER;
+typedef struct MD_REF_DEF_tag MD_REF_DEF;
+
+
+/* During analyzes of inline marks, we need to manage some "mark chains",
+ * of (yet unresolved) openers. This structure holds start/end of the chain.
+ * The chain internals are then realized through MD_MARK::prev and ::next.
+ */
+typedef struct MD_MARKCHAIN_tag MD_MARKCHAIN;
+struct MD_MARKCHAIN_tag {
+ int head; /* Index of first mark in the chain, or -1 if empty. */
+ int tail; /* Index of last mark in the chain, or -1 if empty. */
+};
+
+/* Context propagated through all the parsing. */
+typedef struct MD_CTX_tag MD_CTX;
+struct MD_CTX_tag {
+ /* Immutable stuff (parameters of md_parse()). */
+ const CHAR* text;
+ SZ size;
+ MD_PARSER parser;
+ void* userdata;
+
+ /* When this is true, it allows some optimizations. */
+ int doc_ends_with_newline;
+
+ /* Helper temporary growing buffer. */
+ CHAR* buffer;
+ unsigned alloc_buffer;
+
+ /* Reference definitions. */
+ MD_REF_DEF* ref_defs;
+ int n_ref_defs;
+ int alloc_ref_defs;
+ void** ref_def_hashtable;
+ int ref_def_hashtable_size;
+
+ /* Stack of inline/span markers.
+ * This is only used for parsing a single block contents but by storing it
+ * here we may reuse the stack for subsequent blocks; i.e. we have fewer
+ * (re)allocations. */
+ MD_MARK* marks;
+ int n_marks;
+ int alloc_marks;
+
+#if defined MD4C_USE_UTF16
+ char mark_char_map[128];
+#else
+ char mark_char_map[256];
+#endif
+
+ /* For resolving of inline spans. */
+ MD_MARKCHAIN mark_chains[11];
+#define PTR_CHAIN ctx->mark_chains[0]
+#define TABLECELLBOUNDARIES ctx->mark_chains[1]
+#define ASTERISK_OPENERS_extraword_mod3_0 ctx->mark_chains[2]
+#define ASTERISK_OPENERS_extraword_mod3_1 ctx->mark_chains[3]
+#define ASTERISK_OPENERS_extraword_mod3_2 ctx->mark_chains[4]
+#define ASTERISK_OPENERS_intraword_mod3_0 ctx->mark_chains[5]
+#define ASTERISK_OPENERS_intraword_mod3_1 ctx->mark_chains[6]
+#define ASTERISK_OPENERS_intraword_mod3_2 ctx->mark_chains[7]
+#define UNDERSCORE_OPENERS ctx->mark_chains[8]
+#define TILDE_OPENERS ctx->mark_chains[9]
+#define BRACKET_OPENERS ctx->mark_chains[10]
+#define OPENERS_CHAIN_FIRST 2
+#define OPENERS_CHAIN_LAST 10
+
+ int n_table_cell_boundaries;
+
+ /* For resolving links. */
+ int unresolved_link_head;
+ int unresolved_link_tail;
+
+ /* For resolving raw HTML. */
+ OFF html_comment_horizon;
+ OFF html_proc_instr_horizon;
+ OFF html_decl_horizon;
+ OFF html_cdata_horizon;
+
+ /* For block analysis.
+ * Notes:
+ * -- It holds MD_BLOCK as well as MD_LINE structures. After each
+ * MD_BLOCK, its (multiple) MD_LINE(s) follow.
+ * -- For MD_BLOCK_HTML and MD_BLOCK_CODE, MD_VERBATIMLINE(s) are used
+ * instead of MD_LINE(s).
+ */
+ void* block_bytes;
+ MD_BLOCK* current_block;
+ int n_block_bytes;
+ int alloc_block_bytes;
+
+ /* For container block analysis. */
+ MD_CONTAINER* containers;
+ int n_containers;
+ int alloc_containers;
+
+ /* Minimal indentation to call the block "indented code block". */
+ unsigned code_indent_offset;
+
+ /* Contextual info for line analysis. */
+ SZ code_fence_length; /* For checking closing fence length. */
+ int html_block_type; /* For checking closing raw HTML condition. */
+ int last_line_has_list_loosening_effect;
+ int last_list_item_starts_with_two_blank_lines;
+};
+
+enum MD_LINETYPE_tag {
+ MD_LINE_BLANK,
+ MD_LINE_HR,
+ MD_LINE_ATXHEADER,
+ MD_LINE_SETEXTHEADER,
+ MD_LINE_SETEXTUNDERLINE,
+ MD_LINE_INDENTEDCODE,
+ MD_LINE_FENCEDCODE,
+ MD_LINE_HTML,
+ MD_LINE_TEXT,
+ MD_LINE_TABLE,
+ MD_LINE_TABLEUNDERLINE
+};
+typedef enum MD_LINETYPE_tag MD_LINETYPE;
+
+typedef struct MD_LINE_ANALYSIS_tag MD_LINE_ANALYSIS;
+struct MD_LINE_ANALYSIS_tag {
+ MD_LINETYPE type : 16;
+ unsigned data : 16;
+ OFF beg;
+ OFF end;
+ unsigned indent; /* Indentation level. */
+};
+
+typedef struct MD_LINE_tag MD_LINE;
+struct MD_LINE_tag {
+ OFF beg;
+ OFF end;
+};
+
+typedef struct MD_VERBATIMLINE_tag MD_VERBATIMLINE;
+struct MD_VERBATIMLINE_tag {
+ OFF beg;
+ OFF end;
+ OFF indent;
+};
+
+
+/*******************
+ *** Debugging ***
+ *******************/
+
+#define MD_LOG(msg) \
+ do { \
+ if(ctx->parser.debug_log != NULL) \
+ ctx->parser.debug_log((msg), ctx->userdata); \
+ } while(0)
+
+#ifdef DEBUG
+ #define MD_ASSERT(cond) \
+ do { \
+ if(!(cond)) { \
+ MD_LOG(__FILE__ ":" STRINGIZE(__LINE__) ": " \
+ "Assertion '" STRINGIZE(cond) "' failed."); \
+ exit(1); \
+ } \
+ } while(0)
+
+ #define MD_UNREACHABLE() MD_ASSERT(1 == 0)
+#else
+ #ifdef __GNUC__
+ #define MD_ASSERT(cond) do { if(!(cond)) __builtin_unreachable(); } while(0)
+ #define MD_UNREACHABLE() do { __builtin_unreachable(); } while(0)
+ #elif defined _MSC_VER && _MSC_VER > 120
+ #define MD_ASSERT(cond) do { __assume(cond); } while(0)
+ #define MD_UNREACHABLE() do { __assume(0); } while(0)
+ #else
+ #define MD_ASSERT(cond) do {} while(0)
+ #define MD_UNREACHABLE() do {} while(0)
+ #endif
+#endif
+
+
+/*****************
+ *** Helpers ***
+ *****************/
+
+/* Character accessors. */
+#define CH(off) (ctx->text[(off)])
+#define STR(off) (ctx->text + (off))
+
+/* Character classification.
+ * Note we assume ASCII compatibility of code points < 128 here. */
+#define ISIN_(ch, ch_min, ch_max) ((ch_min) <= (unsigned)(ch) && (unsigned)(ch) <= (ch_max))
+#define ISANYOF_(ch, palette) (md_strchr((palette), (ch)) != NULL)
+#define ISANYOF2_(ch, ch1, ch2) ((ch) == (ch1) || (ch) == (ch2))
+#define ISANYOF3_(ch, ch1, ch2, ch3) ((ch) == (ch1) || (ch) == (ch2) || (ch) == (ch3))
+#define ISASCII_(ch) ((unsigned)(ch) <= 127)
+#define ISBLANK_(ch) (ISANYOF2_((ch), _T(' '), _T('\t')))
+#define ISNEWLINE_(ch) (ISANYOF2_((ch), _T('\r'), _T('\n')))
+#define ISWHITESPACE_(ch) (ISBLANK_(ch) || ISANYOF2_((ch), _T('\v'), _T('\f')))
+#define ISCNTRL_(ch) ((unsigned)(ch) <= 31 || (unsigned)(ch) == 127)
+#define ISPUNCT_(ch) (ISIN_(ch, 33, 47) || ISIN_(ch, 58, 64) || ISIN_(ch, 91, 96) || ISIN_(ch, 123, 126))
+#define ISUPPER_(ch) (ISIN_(ch, _T('A'), _T('Z')))
+#define ISLOWER_(ch) (ISIN_(ch, _T('a'), _T('z')))
+#define ISALPHA_(ch) (ISUPPER_(ch) || ISLOWER_(ch))
+#define ISDIGIT_(ch) (ISIN_(ch, _T('0'), _T('9')))
+#define ISXDIGIT_(ch) (ISDIGIT_(ch) || ISIN_(ch, _T('A'), _T('F')) || ISIN_(ch, _T('a'), _T('f')))
+#define ISALNUM_(ch) (ISALPHA_(ch) || ISDIGIT_(ch))
+
+#define ISANYOF(off, palette) ISANYOF_(CH(off), (palette))
+#define ISANYOF2(off, ch1, ch2) ISANYOF2_(CH(off), (ch1), (ch2))
+#define ISANYOF3(off, ch1, ch2, ch3) ISANYOF3_(CH(off), (ch1), (ch2), (ch3))
+#define ISASCII(off) ISASCII_(CH(off))
+#define ISBLANK(off) ISBLANK_(CH(off))
+#define ISNEWLINE(off) ISNEWLINE_(CH(off))
+#define ISWHITESPACE(off) ISWHITESPACE_(CH(off))
+#define ISCNTRL(off) ISCNTRL_(CH(off))
+#define ISPUNCT(off) ISPUNCT_(CH(off))
+#define ISUPPER(off) ISUPPER_(CH(off))
+#define ISLOWER(off) ISLOWER_(CH(off))
+#define ISALPHA(off) ISALPHA_(CH(off))
+#define ISDIGIT(off) ISDIGIT_(CH(off))
+#define ISXDIGIT(off) ISXDIGIT_(CH(off))
+#define ISALNUM(off) ISALNUM_(CH(off))
+static inline const CHAR*
+md_strchr(const CHAR* str, CHAR ch)
+{
+ OFF i;
+ for(i = 0; str[i] != _T('\0'); i++) {
+ if(ch == str[i])
+ return (str + i);
+ }
+ return NULL;
+}
+
+/* Case insensitive check of string equality. */
+static inline int
+md_ascii_case_eq(const CHAR* s1, const CHAR* s2, SZ n)
+{
+ OFF i;
+ for(i = 0; i < n; i++) {
+ CHAR ch1 = s1[i];
+ CHAR ch2 = s2[i];
+
+ if(ISLOWER_(ch1))
+ ch1 += ('A'-'a');
+ if(ISLOWER_(ch2))
+ ch2 += ('A'-'a');
+ if(ch1 != ch2)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static inline int
+md_ascii_eq(const CHAR* s1, const CHAR* s2, SZ n)
+{
+ return memcmp(s1, s2, n * sizeof(CHAR)) == 0;
+}
+
+static int
+md_text_with_null_replacement(MD_CTX* ctx, MD_TEXTTYPE type, const CHAR* str, SZ size)
+{
+ OFF off = 0;
+ int ret = 0;
+
+ while(1) {
+ while(off < size && str[off] != _T('\0'))
+ off++;
+
+ if(off > 0) {
+ ret = ctx->parser.text(type, str, off, ctx->userdata);
+ if(ret != 0)
+ return ret;
+
+ str += off;
+ size -= off;
+ off = 0;
+ }
+
+ if(off >= size)
+ return 0;
+
+ ret = ctx->parser.text(MD_TEXT_NULLCHAR, _T(""), 1, ctx->userdata);
+ if(ret != 0)
+ return ret;
+ off++;
+ }
+}
+
+
+#define MD_CHECK(func) \
+ do { \
+ ret = (func); \
+ if(ret < 0) \
+ goto abort; \
+ } while(0)
+
+
+#define MD_TEMP_BUFFER(sz) \
+ do { \
+ if(sz > ctx->alloc_buffer) { \
+ CHAR* new_buffer; \
+ SZ new_size = ((sz) + (sz) / 2 + 128) & ~127; \
+ \
+ new_buffer = realloc(ctx->buffer, new_size); \
+ if(new_buffer == NULL) { \
+ MD_LOG("realloc() failed."); \
+ ret = -1; \
+ goto abort; \
+ } \
+ \
+ ctx->buffer = new_buffer; \
+ ctx->alloc_buffer = new_size; \
+ } \
+ } while(0)
+
+
+#define MD_ENTER_BLOCK(type, arg) \
+ do { \
+ ret = ctx->parser.enter_block((type), (arg), ctx->userdata); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from enter_block() callback."); \
+ goto abort; \
+ } \
+ } while(0)
+
+#define MD_LEAVE_BLOCK(type, arg) \
+ do { \
+ ret = ctx->parser.leave_block((type), (arg), ctx->userdata); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from leave_block() callback."); \
+ goto abort; \
+ } \
+ } while(0)
+
+#define MD_ENTER_SPAN(type, arg) \
+ do { \
+ ret = ctx->parser.enter_span((type), (arg), ctx->userdata); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from enter_span() callback."); \
+ goto abort; \
+ } \
+ } while(0)
+
+#define MD_LEAVE_SPAN(type, arg) \
+ do { \
+ ret = ctx->parser.leave_span((type), (arg), ctx->userdata); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from leave_span() callback."); \
+ goto abort; \
+ } \
+ } while(0)
+
+#define MD_TEXT(type, str, size) \
+ do { \
+ if(size > 0) { \
+ ret = ctx->parser.text((type), (str), (size), ctx->userdata); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from text() callback."); \
+ goto abort; \
+ } \
+ } \
+ } while(0)
+
+#define MD_TEXT_INSECURE(type, str, size) \
+ do { \
+ if(size > 0) { \
+ ret = md_text_with_null_replacement(ctx, type, str, size); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from text() callback."); \
+ goto abort; \
+ } \
+ } \
+ } while(0)
+
+
+
+/*************************
+ *** Unicode Support ***
+ *************************/
+
+typedef struct MD_UNICODE_FOLD_INFO_tag MD_UNICODE_FOLD_INFO;
+struct MD_UNICODE_FOLD_INFO_tag {
+ unsigned codepoints[3];
+ int n_codepoints;
+};
+
+
+#if defined MD4C_USE_UTF16 || defined MD4C_USE_UTF8
+ /* Binary search over sorted "map" of codepoints. Consecutive sequences
+ * of codepoints may be encoded in the map by just using the
+ * (MIN_CODEPOINT | 0x40000000) and (MAX_CODEPOINT | 0x80000000).
+ *
+ * Returns index of the found record in the map (in the case of ranges,
+ * the minimal value is used); or -1 on failure. */
+ static int
+ md_unicode_bsearch__(unsigned codepoint, const unsigned* map, size_t map_size)
+ {
+ int beg, end;
+ int pivot_beg, pivot_end;
+
+ beg = 0;
+ end = (int) map_size-1;
+ while(beg <= end) {
+ /* Pivot may be a range, not just a single value. */
+ pivot_beg = pivot_end = (beg + end) / 2;
+ if(map[pivot_end] & 0x40000000)
+ pivot_end++;
+ if(map[pivot_beg] & 0x80000000)
+ pivot_beg--;
+
+ if(codepoint < (map[pivot_beg] & 0x00ffffff))
+ end = pivot_beg - 1;
+ else if(codepoint > (map[pivot_end] & 0x00ffffff))
+ beg = pivot_end + 1;
+ else
+ return pivot_beg;
+ }
+
+ return -1;
+ }
+
+ static int
+ md_is_unicode_whitespace__(unsigned codepoint)
+ {
+#define R(cp_min, cp_max) ((cp_min) | 0x40000000), ((cp_max) | 0x80000000)
+#define S(cp) (cp)
+ /* Unicode "Zs" category.
+ * (generated by scripts/build_whitespace_map.py) */
+ static const unsigned WHITESPACE_MAP[] = {
+ S(0x0020), S(0x00a0), S(0x1680), R(0x2000,0x200a), S(0x202f), S(0x205f), S(0x3000)
+ };
+#undef R
+#undef S
+
+ /* The ASCII ones are the most frequently used ones, also CommonMark
+ * specification requests few more in this range. */
+ if(codepoint <= 0x7f)
+ return ISWHITESPACE_(codepoint);
+
+ return (md_unicode_bsearch__(codepoint, WHITESPACE_MAP, SIZEOF_ARRAY(WHITESPACE_MAP)) >= 0);
+ }
+
+ static int
+ md_is_unicode_punct__(unsigned codepoint)
+ {
+#define R(cp_min, cp_max) ((cp_min) | 0x40000000), ((cp_max) | 0x80000000)
+#define S(cp) (cp)
+ /* Unicode "Pc", "Pd", "Pe", "Pf", "Pi", "Po", "Ps" categories.
+ * (generated by scripts/build_punct_map.py) */
+ static const unsigned PUNCT_MAP[] = {
+ R(0x0021,0x0023), R(0x0025,0x002a), R(0x002c,0x002f), R(0x003a,0x003b), R(0x003f,0x0040),
+ R(0x005b,0x005d), S(0x005f), S(0x007b), S(0x007d), S(0x00a1), S(0x00a7), S(0x00ab), R(0x00b6,0x00b7),
+ S(0x00bb), S(0x00bf), S(0x037e), S(0x0387), R(0x055a,0x055f), R(0x0589,0x058a), S(0x05be), S(0x05c0),
+ S(0x05c3), S(0x05c6), R(0x05f3,0x05f4), R(0x0609,0x060a), R(0x060c,0x060d), S(0x061b), R(0x061e,0x061f),
+ R(0x066a,0x066d), S(0x06d4), R(0x0700,0x070d), R(0x07f7,0x07f9), R(0x0830,0x083e), S(0x085e),
+ R(0x0964,0x0965), S(0x0970), S(0x09fd), S(0x0a76), S(0x0af0), S(0x0c77), S(0x0c84), S(0x0df4), S(0x0e4f),
+ R(0x0e5a,0x0e5b), R(0x0f04,0x0f12), S(0x0f14), R(0x0f3a,0x0f3d), S(0x0f85), R(0x0fd0,0x0fd4),
+ R(0x0fd9,0x0fda), R(0x104a,0x104f), S(0x10fb), R(0x1360,0x1368), S(0x1400), S(0x166e), R(0x169b,0x169c),
+ R(0x16eb,0x16ed), R(0x1735,0x1736), R(0x17d4,0x17d6), R(0x17d8,0x17da), R(0x1800,0x180a),
+ R(0x1944,0x1945), R(0x1a1e,0x1a1f), R(0x1aa0,0x1aa6), R(0x1aa8,0x1aad), R(0x1b5a,0x1b60),
+ R(0x1bfc,0x1bff), R(0x1c3b,0x1c3f), R(0x1c7e,0x1c7f), R(0x1cc0,0x1cc7), S(0x1cd3), R(0x2010,0x2027),
+ R(0x2030,0x2043), R(0x2045,0x2051), R(0x2053,0x205e), R(0x207d,0x207e), R(0x208d,0x208e),
+ R(0x2308,0x230b), R(0x2329,0x232a), R(0x2768,0x2775), R(0x27c5,0x27c6), R(0x27e6,0x27ef),
+ R(0x2983,0x2998), R(0x29d8,0x29db), R(0x29fc,0x29fd), R(0x2cf9,0x2cfc), R(0x2cfe,0x2cff), S(0x2d70),
+ R(0x2e00,0x2e2e), R(0x2e30,0x2e4f), R(0x3001,0x3003), R(0x3008,0x3011), R(0x3014,0x301f), S(0x3030),
+ S(0x303d), S(0x30a0), S(0x30fb), R(0xa4fe,0xa4ff), R(0xa60d,0xa60f), S(0xa673), S(0xa67e),
+ R(0xa6f2,0xa6f7), R(0xa874,0xa877), R(0xa8ce,0xa8cf), R(0xa8f8,0xa8fa), S(0xa8fc), R(0xa92e,0xa92f),
+ S(0xa95f), R(0xa9c1,0xa9cd), R(0xa9de,0xa9df), R(0xaa5c,0xaa5f), R(0xaade,0xaadf), R(0xaaf0,0xaaf1),
+ S(0xabeb), R(0xfd3e,0xfd3f), R(0xfe10,0xfe19), R(0xfe30,0xfe52), R(0xfe54,0xfe61), S(0xfe63), S(0xfe68),
+ R(0xfe6a,0xfe6b), R(0xff01,0xff03), R(0xff05,0xff0a), R(0xff0c,0xff0f), R(0xff1a,0xff1b),
+ R(0xff1f,0xff20), R(0xff3b,0xff3d), S(0xff3f), S(0xff5b), S(0xff5d), R(0xff5f,0xff65), R(0x10100,0x10102),
+ S(0x1039f), S(0x103d0), S(0x1056f), S(0x10857), S(0x1091f), S(0x1093f), R(0x10a50,0x10a58), S(0x10a7f),
+ R(0x10af0,0x10af6), R(0x10b39,0x10b3f), R(0x10b99,0x10b9c), R(0x10f55,0x10f59), R(0x11047,0x1104d),
+ R(0x110bb,0x110bc), R(0x110be,0x110c1), R(0x11140,0x11143), R(0x11174,0x11175), R(0x111c5,0x111c8),
+ S(0x111cd), S(0x111db), R(0x111dd,0x111df), R(0x11238,0x1123d), S(0x112a9), R(0x1144b,0x1144f),
+ S(0x1145b), S(0x1145d), S(0x114c6), R(0x115c1,0x115d7), R(0x11641,0x11643), R(0x11660,0x1166c),
+ R(0x1173c,0x1173e), S(0x1183b), S(0x119e2), R(0x11a3f,0x11a46), R(0x11a9a,0x11a9c), R(0x11a9e,0x11aa2),
+ R(0x11c41,0x11c45), R(0x11c70,0x11c71), R(0x11ef7,0x11ef8), S(0x11fff), R(0x12470,0x12474),
+ R(0x16a6e,0x16a6f), S(0x16af5), R(0x16b37,0x16b3b), S(0x16b44), R(0x16e97,0x16e9a), S(0x16fe2),
+ S(0x1bc9f), R(0x1da87,0x1da8b), R(0x1e95e,0x1e95f)
+ };
+#undef R
+#undef S
+
+ /* The ASCII ones are the most frequently used ones, also CommonMark
+ * specification requests few more in this range. */
+ if(codepoint <= 0x7f)
+ return ISPUNCT_(codepoint);
+
+ return (md_unicode_bsearch__(codepoint, PUNCT_MAP, SIZEOF_ARRAY(PUNCT_MAP)) >= 0);
+ }
+
+ static void
+ md_get_unicode_fold_info(unsigned codepoint, MD_UNICODE_FOLD_INFO* info)
+ {
+#define R(cp_min, cp_max) ((cp_min) | 0x40000000), ((cp_max) | 0x80000000)
+#define S(cp) (cp)
+ /* Unicode "Pc", "Pd", "Pe", "Pf", "Pi", "Po", "Ps" categories.
+ * (generated by scripts/build_punct_map.py) */
+ static const unsigned FOLD_MAP_1[] = {
+ R(0x0041,0x005a), S(0x00b5), R(0x00c0,0x00d6), R(0x00d8,0x00de), R(0x0100,0x012e), R(0x0132,0x0136),
+ R(0x0139,0x0147), R(0x014a,0x0176), S(0x0178), R(0x0179,0x017d), S(0x017f), S(0x0181), S(0x0182),
+ S(0x0186), S(0x0187), S(0x0189), S(0x018b), S(0x018e), S(0x018f), S(0x0190), S(0x0191), S(0x0193),
+ S(0x0194), S(0x0196), S(0x0197), S(0x0198), S(0x019c), S(0x019d), S(0x019f), R(0x01a0,0x01a4), S(0x01a6),
+ S(0x01a7), S(0x01a9), S(0x01ac), S(0x01ae), S(0x01af), S(0x01b1), S(0x01b3), S(0x01b7), S(0x01b8),
+ S(0x01bc), S(0x01c4), S(0x01c5), S(0x01c7), S(0x01c8), S(0x01ca), R(0x01cb,0x01db), R(0x01de,0x01ee),
+ S(0x01f1), S(0x01f2), S(0x01f6), S(0x01f7), R(0x01f8,0x021e), S(0x0220), R(0x0222,0x0232), S(0x023a),
+ S(0x023b), S(0x023d), S(0x023e), S(0x0241), S(0x0243), S(0x0244), S(0x0245), R(0x0246,0x024e), S(0x0345),
+ S(0x0370), S(0x0376), S(0x037f), S(0x0386), R(0x0388,0x038a), S(0x038c), S(0x038e), R(0x0391,0x03a1),
+ R(0x03a3,0x03ab), S(0x03c2), S(0x03cf), S(0x03d0), S(0x03d1), S(0x03d5), S(0x03d6), R(0x03d8,0x03ee),
+ S(0x03f0), S(0x03f1), S(0x03f4), S(0x03f5), S(0x03f7), S(0x03f9), S(0x03fa), R(0x03fd,0x03ff),
+ R(0x0400,0x040f), R(0x0410,0x042f), R(0x0460,0x0480), R(0x048a,0x04be), S(0x04c0), R(0x04c1,0x04cd),
+ R(0x04d0,0x052e), R(0x0531,0x0556), R(0x10a0,0x10c5), S(0x10c7), S(0x10cd), R(0x13f8,0x13fd), S(0x1c80),
+ S(0x1c81), S(0x1c82), S(0x1c83), S(0x1c85), S(0x1c86), S(0x1c87), S(0x1c88), R(0x1c90,0x1cba),
+ R(0x1cbd,0x1cbf), R(0x1e00,0x1e94), S(0x1e9b), R(0x1ea0,0x1efe), R(0x1f08,0x1f0f), R(0x1f18,0x1f1d),
+ R(0x1f28,0x1f2f), R(0x1f38,0x1f3f), R(0x1f48,0x1f4d), S(0x1f59), S(0x1f5b), S(0x1f5d), S(0x1f5f),
+ R(0x1f68,0x1f6f), S(0x1fb8), S(0x1fba), S(0x1fbe), R(0x1fc8,0x1fcb), S(0x1fd8), S(0x1fda), S(0x1fe8),
+ S(0x1fea), S(0x1fec), S(0x1ff8), S(0x1ffa), S(0x2126), S(0x212a), S(0x212b), S(0x2132), R(0x2160,0x216f),
+ S(0x2183), R(0x24b6,0x24cf), R(0x2c00,0x2c2e), S(0x2c60), S(0x2c62), S(0x2c63), S(0x2c64),
+ R(0x2c67,0x2c6b), S(0x2c6d), S(0x2c6e), S(0x2c6f), S(0x2c70), S(0x2c72), S(0x2c75), S(0x2c7e),
+ R(0x2c80,0x2ce2), S(0x2ceb), S(0x2cf2), R(0xa640,0xa66c), R(0xa680,0xa69a), R(0xa722,0xa72e),
+ R(0xa732,0xa76e), S(0xa779), S(0xa77d), R(0xa77e,0xa786), S(0xa78b), S(0xa78d), S(0xa790),
+ R(0xa796,0xa7a8), S(0xa7aa), S(0xa7ab), S(0xa7ac), S(0xa7ad), S(0xa7ae), S(0xa7b0), S(0xa7b1), S(0xa7b2),
+ S(0xa7b3), R(0xa7b4,0xa7be), S(0xa7c2), S(0xa7c4), S(0xa7c5), S(0xa7c6), R(0xab70,0xabbf),
+ R(0xff21,0xff3a), R(0x10400,0x10427), R(0x104b0,0x104d3), R(0x10c80,0x10cb2), R(0x118a0,0x118bf),
+ R(0x16e40,0x16e5f), R(0x1e900,0x1e921)
+ };
+ static const unsigned FOLD_MAP_1_DATA[] = {
+ 0x0061, 0x007a, 0x03bc, 0x00e0, 0x00f6, 0x00f8, 0x00fe, 0x0101, 0x012f, 0x0133, 0x0137, 0x013a, 0x0148,
+ 0x014b, 0x0177, 0x00ff, 0x017a, 0x017e, 0x0073, 0x0253, 0x0183, 0x0254, 0x0188, 0x0256, 0x018c, 0x01dd,
+ 0x0259, 0x025b, 0x0192, 0x0260, 0x0263, 0x0269, 0x0268, 0x0199, 0x026f, 0x0272, 0x0275, 0x01a1, 0x01a5,
+ 0x0280, 0x01a8, 0x0283, 0x01ad, 0x0288, 0x01b0, 0x028a, 0x01b4, 0x0292, 0x01b9, 0x01bd, 0x01c6, 0x01c6,
+ 0x01c9, 0x01c9, 0x01cc, 0x01cc, 0x01dc, 0x01df, 0x01ef, 0x01f3, 0x01f3, 0x0195, 0x01bf, 0x01f9, 0x021f,
+ 0x019e, 0x0223, 0x0233, 0x2c65, 0x023c, 0x019a, 0x2c66, 0x0242, 0x0180, 0x0289, 0x028c, 0x0247, 0x024f,
+ 0x03b9, 0x0371, 0x0377, 0x03f3, 0x03ac, 0x03ad, 0x03af, 0x03cc, 0x03cd, 0x03b1, 0x03c1, 0x03c3, 0x03cb,
+ 0x03c3, 0x03d7, 0x03b2, 0x03b8, 0x03c6, 0x03c0, 0x03d9, 0x03ef, 0x03ba, 0x03c1, 0x03b8, 0x03b5, 0x03f8,
+ 0x03f2, 0x03fb, 0x037b, 0x037d, 0x0450, 0x045f, 0x0430, 0x044f, 0x0461, 0x0481, 0x048b, 0x04bf, 0x04cf,
+ 0x04c2, 0x04ce, 0x04d1, 0x052f, 0x0561, 0x0586, 0x2d00, 0x2d25, 0x2d27, 0x2d2d, 0x13f0, 0x13f5, 0x0432,
+ 0x0434, 0x043e, 0x0441, 0x0442, 0x044a, 0x0463, 0xa64b, 0x10d0, 0x10fa, 0x10fd, 0x10ff, 0x1e01, 0x1e95,
+ 0x1e61, 0x1ea1, 0x1eff, 0x1f00, 0x1f07, 0x1f10, 0x1f15, 0x1f20, 0x1f27, 0x1f30, 0x1f37, 0x1f40, 0x1f45,
+ 0x1f51, 0x1f53, 0x1f55, 0x1f57, 0x1f60, 0x1f67, 0x1fb0, 0x1f70, 0x03b9, 0x1f72, 0x1f75, 0x1fd0, 0x1f76,
+ 0x1fe0, 0x1f7a, 0x1fe5, 0x1f78, 0x1f7c, 0x03c9, 0x006b, 0x00e5, 0x214e, 0x2170, 0x217f, 0x2184, 0x24d0,
+ 0x24e9, 0x2c30, 0x2c5e, 0x2c61, 0x026b, 0x1d7d, 0x027d, 0x2c68, 0x2c6c, 0x0251, 0x0271, 0x0250, 0x0252,
+ 0x2c73, 0x2c76, 0x023f, 0x2c81, 0x2ce3, 0x2cec, 0x2cf3, 0xa641, 0xa66d, 0xa681, 0xa69b, 0xa723, 0xa72f,
+ 0xa733, 0xa76f, 0xa77a, 0x1d79, 0xa77f, 0xa787, 0xa78c, 0x0265, 0xa791, 0xa797, 0xa7a9, 0x0266, 0x025c,
+ 0x0261, 0x026c, 0x026a, 0x029e, 0x0287, 0x029d, 0xab53, 0xa7b5, 0xa7bf, 0xa7c3, 0xa794, 0x0282, 0x1d8e,
+ 0x13a0, 0x13ef, 0xff41, 0xff5a, 0x10428, 0x1044f, 0x104d8, 0x104fb, 0x10cc0, 0x10cf2, 0x118c0, 0x118df,
+ 0x16e60, 0x16e7f, 0x1e922, 0x1e943
+ };
+ static const unsigned FOLD_MAP_2[] = {
+ S(0x00df), S(0x0130), S(0x0149), S(0x01f0), S(0x0587), S(0x1e96), S(0x1e97), S(0x1e98), S(0x1e99),
+ S(0x1e9a), S(0x1e9e), S(0x1f50), R(0x1f80,0x1f87), R(0x1f88,0x1f8f), R(0x1f90,0x1f97), R(0x1f98,0x1f9f),
+ R(0x1fa0,0x1fa7), R(0x1fa8,0x1faf), S(0x1fb2), S(0x1fb3), S(0x1fb4), S(0x1fb6), S(0x1fbc), S(0x1fc2),
+ S(0x1fc3), S(0x1fc4), S(0x1fc6), S(0x1fcc), S(0x1fd6), S(0x1fe4), S(0x1fe6), S(0x1ff2), S(0x1ff3),
+ S(0x1ff4), S(0x1ff6), S(0x1ffc), S(0xfb00), S(0xfb01), S(0xfb02), S(0xfb05), S(0xfb06), S(0xfb13),
+ S(0xfb14), S(0xfb15), S(0xfb16), S(0xfb17)
+ };
+ static const unsigned FOLD_MAP_2_DATA[] = {
+ 0x0073,0x0073, 0x0069,0x0307, 0x02bc,0x006e, 0x006a,0x030c, 0x0565,0x0582, 0x0068,0x0331, 0x0074,0x0308,
+ 0x0077,0x030a, 0x0079,0x030a, 0x0061,0x02be, 0x0073,0x0073, 0x03c5,0x0313, 0x1f00,0x03b9, 0x1f07,0x03b9,
+ 0x1f00,0x03b9, 0x1f07,0x03b9, 0x1f20,0x03b9, 0x1f27,0x03b9, 0x1f20,0x03b9, 0x1f27,0x03b9, 0x1f60,0x03b9,
+ 0x1f67,0x03b9, 0x1f60,0x03b9, 0x1f67,0x03b9, 0x1f70,0x03b9, 0x03b1,0x03b9, 0x03ac,0x03b9, 0x03b1,0x0342,
+ 0x03b1,0x03b9, 0x1f74,0x03b9, 0x03b7,0x03b9, 0x03ae,0x03b9, 0x03b7,0x0342, 0x03b7,0x03b9, 0x03b9,0x0342,
+ 0x03c1,0x0313, 0x03c5,0x0342, 0x1f7c,0x03b9, 0x03c9,0x03b9, 0x03ce,0x03b9, 0x03c9,0x0342, 0x03c9,0x03b9,
+ 0x0066,0x0066, 0x0066,0x0069, 0x0066,0x006c, 0x0073,0x0074, 0x0073,0x0074, 0x0574,0x0576, 0x0574,0x0565,
+ 0x0574,0x056b, 0x057e,0x0576, 0x0574,0x056d
+ };
+ static const unsigned FOLD_MAP_3[] = {
+ S(0x0390), S(0x03b0), S(0x1f52), S(0x1f54), S(0x1f56), S(0x1fb7), S(0x1fc7), S(0x1fd2), S(0x1fd3),
+ S(0x1fd7), S(0x1fe2), S(0x1fe3), S(0x1fe7), S(0x1ff7), S(0xfb03), S(0xfb04)
+ };
+ static const unsigned FOLD_MAP_3_DATA[] = {
+ 0x03b9,0x0308,0x0301, 0x03c5,0x0308,0x0301, 0x03c5,0x0313,0x0300, 0x03c5,0x0313,0x0301,
+ 0x03c5,0x0313,0x0342, 0x03b1,0x0342,0x03b9, 0x03b7,0x0342,0x03b9, 0x03b9,0x0308,0x0300,
+ 0x03b9,0x0308,0x0301, 0x03b9,0x0308,0x0342, 0x03c5,0x0308,0x0300, 0x03c5,0x0308,0x0301,
+ 0x03c5,0x0308,0x0342, 0x03c9,0x0342,0x03b9, 0x0066,0x0066,0x0069, 0x0066,0x0066,0x006c
+ };
+#undef R
+#undef S
+ static const struct {
+ const unsigned* map;
+ const unsigned* data;
+ size_t map_size;
+ int n_codepoints;
+ } FOLD_MAP_LIST[] = {
+ { FOLD_MAP_1, FOLD_MAP_1_DATA, SIZEOF_ARRAY(FOLD_MAP_1), 1 },
+ { FOLD_MAP_2, FOLD_MAP_2_DATA, SIZEOF_ARRAY(FOLD_MAP_2), 2 },
+ { FOLD_MAP_3, FOLD_MAP_3_DATA, SIZEOF_ARRAY(FOLD_MAP_3), 3 }
+ };
+
+ int i;
+
+ /* Fast path for ASCII characters. */
+ if(codepoint <= 0x7f) {
+ info->codepoints[0] = codepoint;
+ if(ISUPPER_(codepoint))
+ info->codepoints[0] += 'a' - 'A';
+ info->n_codepoints = 1;
+ return;
+ }
+
+ /* Try to locate the codepoint in any of the maps. */
+ for(i = 0; i < (int) SIZEOF_ARRAY(FOLD_MAP_LIST); i++) {
+ int index;
+
+ index = md_unicode_bsearch__(codepoint, FOLD_MAP_LIST[i].map, FOLD_MAP_LIST[i].map_size);
+ if(index >= 0) {
+ /* Found the mapping. */
+ int n_codepoints = FOLD_MAP_LIST[i].n_codepoints;
+ const unsigned* map = FOLD_MAP_LIST[i].map;
+ const unsigned* codepoints = FOLD_MAP_LIST[i].data + (index * n_codepoints);
+
+ memcpy(info->codepoints, codepoints, sizeof(unsigned) * n_codepoints);
+ info->n_codepoints = n_codepoints;
+
+ if(FOLD_MAP_LIST[i].map[index] != codepoint) {
+ /* The found mapping maps whole range of codepoints,
+ * i.e. we have to offset info->codepoints[0] accordingly. */
+ if((map[index] & 0x00ffffff)+1 == codepoints[0]) {
+ /* Alternating type of the range. */
+ info->codepoints[0] = codepoint + ((codepoint & 0x1) == (map[index] & 0x1) ? 1 : 0);
+ } else {
+ /* Range to range kind of mapping. */
+ info->codepoints[0] += (codepoint - (map[index] & 0x00ffffff));
+ }
+ }
+
+ return;
+ }
+ }
+
+ /* No mapping found. Map the codepoint to itself. */
+ info->codepoints[0] = codepoint;
+ info->n_codepoints = 1;
+ }
+#endif
+
+
+#if defined MD4C_USE_UTF16
+ #define IS_UTF16_SURROGATE_HI(word) (((WORD)(word) & 0xfc00) == 0xd800)
+ #define IS_UTF16_SURROGATE_LO(word) (((WORD)(word) & 0xfc00) == 0xdc00)
+ #define UTF16_DECODE_SURROGATE(hi, lo) (0x10000 + ((((unsigned)(hi) & 0x3ff) << 10) | (((unsigned)(lo) & 0x3ff) << 0)))
+
+ static unsigned
+ md_decode_utf16le__(const CHAR* str, SZ str_size, SZ* p_size)
+ {
+ if(IS_UTF16_SURROGATE_HI(str[0])) {
+ if(1 < str_size && IS_UTF16_SURROGATE_LO(str[1])) {
+ if(p_size != NULL)
+ *p_size = 2;
+ return UTF16_DECODE_SURROGATE(str[0], str[1]);
+ }
+ }
+
+ if(p_size != NULL)
+ *p_size = 1;
+ return str[0];
+ }
+
+ static unsigned
+ md_decode_utf16le_before__(MD_CTX* ctx, OFF off)
+ {
+ if(off > 2 && IS_UTF16_SURROGATE_HI(CH(off-2)) && IS_UTF16_SURROGATE_LO(CH(off-1)))
+ return UTF16_DECODE_SURROGATE(CH(off-2), CH(off-1));
+
+ return CH(off);
+ }
+
+ /* No whitespace uses surrogates, so no decoding needed here. */
+ #define ISUNICODEWHITESPACE_(codepoint) md_is_unicode_whitespace__(codepoint)
+ #define ISUNICODEWHITESPACE(off) md_is_unicode_whitespace__(CH(off))
+ #define ISUNICODEWHITESPACEBEFORE(off) md_is_unicode_whitespace__(CH((off)-1))
+
+ #define ISUNICODEPUNCT(off) md_is_unicode_punct__(md_decode_utf16le__(STR(off), ctx->size - (off), NULL))
+ #define ISUNICODEPUNCTBEFORE(off) md_is_unicode_punct__(md_decode_utf16le_before__(ctx, off))
+
+ static inline int
+ md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_char_size)
+ {
+ return md_decode_utf16le__(str+off, str_size-off, p_char_size);
+ }
+#elif defined MD4C_USE_UTF8
+ #define IS_UTF8_LEAD1(byte) ((unsigned char)(byte) <= 0x7f)
+ #define IS_UTF8_LEAD2(byte) (((unsigned char)(byte) & 0xe0) == 0xc0)
+ #define IS_UTF8_LEAD3(byte) (((unsigned char)(byte) & 0xf0) == 0xe0)
+ #define IS_UTF8_LEAD4(byte) (((unsigned char)(byte) & 0xf8) == 0xf0)
+ #define IS_UTF8_TAIL(byte) (((unsigned char)(byte) & 0xc0) == 0x80)
+
+ static unsigned
+ md_decode_utf8__(const CHAR* str, SZ str_size, SZ* p_size)
+ {
+ if(!IS_UTF8_LEAD1(str[0])) {
+ if(IS_UTF8_LEAD2(str[0])) {
+ if(1 < str_size && IS_UTF8_TAIL(str[1])) {
+ if(p_size != NULL)
+ *p_size = 2;
+
+ return (((unsigned int)str[0] & 0x1f) << 6) |
+ (((unsigned int)str[1] & 0x3f) << 0);
+ }
+ } else if(IS_UTF8_LEAD3(str[0])) {
+ if(2 < str_size && IS_UTF8_TAIL(str[1]) && IS_UTF8_TAIL(str[2])) {
+ if(p_size != NULL)
+ *p_size = 3;
+
+ return (((unsigned int)str[0] & 0x0f) << 12) |
+ (((unsigned int)str[1] & 0x3f) << 6) |
+ (((unsigned int)str[2] & 0x3f) << 0);
+ }
+ } else if(IS_UTF8_LEAD4(str[0])) {
+ if(3 < str_size && IS_UTF8_TAIL(str[1]) && IS_UTF8_TAIL(str[2]) && IS_UTF8_TAIL(str[3])) {
+ if(p_size != NULL)
+ *p_size = 4;
+
+ return (((unsigned int)str[0] & 0x07) << 18) |
+ (((unsigned int)str[1] & 0x3f) << 12) |
+ (((unsigned int)str[2] & 0x3f) << 6) |
+ (((unsigned int)str[3] & 0x3f) << 0);
+ }
+ }
+ }
+
+ if(p_size != NULL)
+ *p_size = 1;
+ return (unsigned) str[0];
+ }
+
+ static unsigned
+ md_decode_utf8_before__(MD_CTX* ctx, OFF off)
+ {
+ if(!IS_UTF8_LEAD1(CH(off-1))) {
+ if(off > 1 && IS_UTF8_LEAD2(CH(off-2)) && IS_UTF8_TAIL(CH(off-1)))
+ return (((unsigned int)CH(off-2) & 0x1f) << 6) |
+ (((unsigned int)CH(off-1) & 0x3f) << 0);
+
+ if(off > 2 && IS_UTF8_LEAD3(CH(off-3)) && IS_UTF8_TAIL(CH(off-2)) && IS_UTF8_TAIL(CH(off-1)))
+ return (((unsigned int)CH(off-3) & 0x0f) << 12) |
+ (((unsigned int)CH(off-2) & 0x3f) << 6) |
+ (((unsigned int)CH(off-1) & 0x3f) << 0);
+
+ if(off > 3 && IS_UTF8_LEAD4(CH(off-4)) && IS_UTF8_TAIL(CH(off-3)) && IS_UTF8_TAIL(CH(off-2)) && IS_UTF8_TAIL(CH(off-1)))
+ return (((unsigned int)CH(off-4) & 0x07) << 18) |
+ (((unsigned int)CH(off-3) & 0x3f) << 12) |
+ (((unsigned int)CH(off-2) & 0x3f) << 6) |
+ (((unsigned int)CH(off-1) & 0x3f) << 0);
+ }
+
+ return (unsigned) CH(off-1);
+ }
+
+ #define ISUNICODEWHITESPACE_(codepoint) md_is_unicode_whitespace__(codepoint)
+ #define ISUNICODEWHITESPACE(off) md_is_unicode_whitespace__(md_decode_utf8__(STR(off), ctx->size - (off), NULL))
+ #define ISUNICODEWHITESPACEBEFORE(off) md_is_unicode_whitespace__(md_decode_utf8_before__(ctx, off))
+
+ #define ISUNICODEPUNCT(off) md_is_unicode_punct__(md_decode_utf8__(STR(off), ctx->size - (off), NULL))
+ #define ISUNICODEPUNCTBEFORE(off) md_is_unicode_punct__(md_decode_utf8_before__(ctx, off))
+
+ static inline unsigned
+ md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_char_size)
+ {
+ return md_decode_utf8__(str+off, str_size-off, p_char_size);
+ }
+#else
+ #define ISUNICODEWHITESPACE_(codepoint) ISWHITESPACE_(codepoint)
+ #define ISUNICODEWHITESPACE(off) ISWHITESPACE(off)
+ #define ISUNICODEWHITESPACEBEFORE(off) ISWHITESPACE((off)-1)
+
+ #define ISUNICODEPUNCT(off) ISPUNCT(off)
+ #define ISUNICODEPUNCTBEFORE(off) ISPUNCT((off)-1)
+
+ static inline void
+ md_get_unicode_fold_info(unsigned codepoint, MD_UNICODE_FOLD_INFO* info)
+ {
+ info->codepoints[0] = codepoint;
+ if(ISUPPER_(codepoint))
+ info->codepoints[0] += 'a' - 'A';
+ info->n_codepoints = 1;
+ }
+
+ static inline unsigned
+ md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_size)
+ {
+ *p_size = 1;
+ return (unsigned) str[off];
+ }
+#endif
+
+
+/*************************************
+ *** Helper string manipulations ***
+ *************************************/
+
+/* Fill buffer with copy of the string between 'beg' and 'end' but replace any
+ * line breaks with given replacement character.
+ *
+ * NOTE: Caller is responsible to make sure the buffer is large enough.
+ * (Given the output is always shorter then input, (end - beg) is good idea
+ * what the caller should allocate.)
+ */
+static void
+md_merge_lines(MD_CTX* ctx, OFF beg, OFF end, const MD_LINE* lines, int n_lines,
+ CHAR line_break_replacement_char, CHAR* buffer, SZ* p_size)
+{
+ CHAR* ptr = buffer;
+ int line_index = 0;
+ OFF off = beg;
+
+ while(1) {
+ const MD_LINE* line = &lines[line_index];
+ OFF line_end = line->end;
+ if(end < line_end)
+ line_end = end;
+
+ while(off < line_end) {
+ *ptr = CH(off);
+ ptr++;
+ off++;
+ }
+
+ if(off >= end) {
+ *p_size = ptr - buffer;
+ return;
+ }
+
+ *ptr = line_break_replacement_char;
+ ptr++;
+
+ line_index++;
+ off = lines[line_index].beg;
+ }
+}
+
+/* Wrapper of md_merge_lines() which allocates new buffer for the output string.
+ */
+static int
+md_merge_lines_alloc(MD_CTX* ctx, OFF beg, OFF end, const MD_LINE* lines, int n_lines,
+ CHAR line_break_replacement_char, CHAR** p_str, SZ* p_size)
+{
+ CHAR* buffer;
+
+ buffer = (CHAR*) malloc(sizeof(CHAR) * (end - beg));
+ if(buffer == NULL) {
+ MD_LOG("malloc() failed.");
+ return -1;
+ }
+
+ md_merge_lines(ctx, beg, end, lines, n_lines,
+ line_break_replacement_char, buffer, p_size);
+
+ *p_str = buffer;
+ return 0;
+}
+
+static OFF
+md_skip_unicode_whitespace(const CHAR* label, OFF off, SZ size)
+{
+ SZ char_size;
+ unsigned codepoint;
+
+ while(off < size) {
+ codepoint = md_decode_unicode(label, off, size, &char_size);
+ if(!ISUNICODEWHITESPACE_(codepoint) && !ISNEWLINE_(label[off]))
+ break;
+ off += char_size;
+ }
+
+ return off;
+}
+
+
+/******************************
+ *** Recognizing raw HTML ***
+ ******************************/
+
+/* md_is_html_tag() may be called when processing inlines (inline raw HTML)
+ * or when breaking document to blocks (checking for start of HTML block type 7).
+ *
+ * When breaking document to blocks, we do not yet know line boundaries, but
+ * in that case the whole tag has to live on a single line. We distinguish this
+ * by n_lines == 0.
+ */
+static int
+md_is_html_tag(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end)
+{
+ int attr_state;
+ OFF off = beg;
+ OFF line_end = (n_lines > 0) ? lines[0].end : ctx->size;
+ int i = 0;
+
+ MD_ASSERT(CH(beg) == _T('<'));
+
+ if(off + 1 >= line_end)
+ return FALSE;
+ off++;
+
+ /* For parsing attributes, we need a little state automaton below.
+ * State -1: no attributes are allowed.
+ * State 0: attribute could follow after some whitespace.
+ * State 1: after a whitespace (attribute name may follow).
+ * State 2: after attribute name ('=' MAY follow).
+ * State 3: after '=' (value specification MUST follow).
+ * State 41: in middle of unquoted attribute value.
+ * State 42: in middle of single-quoted attribute value.
+ * State 43: in middle of double-quoted attribute value.
+ */
+ attr_state = 0;
+
+ if(CH(off) == _T('/')) {
+ /* Closer tag "</ ... >". No attributes may be present. */
+ attr_state = -1;
+ off++;
+ }
+
+ /* Tag name */
+ if(off >= line_end || !ISALPHA(off))
+ return FALSE;
+ off++;
+ while(off < line_end && (ISALNUM(off) || CH(off) == _T('-')))
+ off++;
+
+ /* (Optional) attributes (if not closer), (optional) '/' (if not closer)
+ * and final '>'. */
+ while(1) {
+ while(off < line_end && !ISNEWLINE(off)) {
+ if(attr_state > 40) {
+ if(attr_state == 41 && (ISBLANK(off) || ISANYOF(off, _T("\"'=<>`")))) {
+ attr_state = 0;
+ off--; /* Put the char back for re-inspection in the new state. */
+ } else if(attr_state == 42 && CH(off) == _T('\'')) {
+ attr_state = 0;
+ } else if(attr_state == 43 && CH(off) == _T('"')) {
+ attr_state = 0;
+ }
+ off++;
+ } else if(ISWHITESPACE(off)) {
+ if(attr_state == 0)
+ attr_state = 1;
+ off++;
+ } else if(attr_state <= 2 && CH(off) == _T('>')) {
+ /* End. */
+ goto done;
+ } else if(attr_state <= 2 && CH(off) == _T('/') && off+1 < line_end && CH(off+1) == _T('>')) {
+ /* End with digraph '/>' */
+ off++;
+ goto done;
+ } else if((attr_state == 1 || attr_state == 2) && (ISALPHA(off) || CH(off) == _T('_') || CH(off) == _T(':'))) {
+ off++;
+ /* Attribute name */
+ while(off < line_end && (ISALNUM(off) || ISANYOF(off, _T("_.:-"))))
+ off++;
+ attr_state = 2;
+ } else if(attr_state == 2 && CH(off) == _T('=')) {
+ /* Attribute assignment sign */
+ off++;
+ attr_state = 3;
+ } else if(attr_state == 3) {
+ /* Expecting start of attribute value. */
+ if(CH(off) == _T('"'))
+ attr_state = 43;
+ else if(CH(off) == _T('\''))
+ attr_state = 42;
+ else if(!ISANYOF(off, _T("\"'=<>`")) && !ISNEWLINE(off))
+ attr_state = 41;
+ else
+ return FALSE;
+ off++;
+ } else {
+ /* Anything unexpected. */
+ return FALSE;
+ }
+ }
+
+ /* We have to be on a single line. See definition of start condition
+ * of HTML block, type 7. */
+ if(n_lines == 0)
+ return FALSE;
+
+ i++;
+ if(i >= n_lines)
+ return FALSE;
+
+ off = lines[i].beg;
+ line_end = lines[i].end;
+
+ if(attr_state == 0 || attr_state == 41)
+ attr_state = 1;
+
+ if(off >= max_end)
+ return FALSE;
+ }
+
+done:
+ if(off >= max_end)
+ return FALSE;
+
+ *p_end = off+1;
+ return TRUE;
+}
+
+static int
+md_scan_for_html_closer(MD_CTX* ctx, const MD_CHAR* str, MD_SIZE len,
+ const MD_LINE* lines, int n_lines,
+ OFF beg, OFF max_end, OFF* p_end,
+ OFF* p_scan_horizon)
+{
+ OFF off = beg;
+ int i = 0;
+
+ if(off < *p_scan_horizon && *p_scan_horizon >= max_end - len) {
+ /* We have already scanned the range up to the max_end so we know
+ * there is nothing to see. */
+ return FALSE;
+ }
+
+ while(TRUE) {
+ while(off + len <= lines[i].end && off + len <= max_end) {
+ if(md_ascii_eq(STR(off), str, len)) {
+ /* Success. */
+ *p_end = off + len;
+ return TRUE;
+ }
+ off++;
+ }
+
+ i++;
+ if(off >= max_end || i >= n_lines) {
+ /* Failure. */
+ *p_scan_horizon = off;
+ return FALSE;
+ }
+
+ off = lines[i].beg;
+ }
+}
+
+static int
+md_is_html_comment(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end)
+{
+ OFF off = beg;
+
+ MD_ASSERT(CH(beg) == _T('<'));
+
+ if(off + 4 >= lines[0].end)
+ return FALSE;
+ if(CH(off+1) != _T('!') || CH(off+2) != _T('-') || CH(off+3) != _T('-'))
+ return FALSE;
+ off += 4;
+
+ /* ">" and "->" must not follow the opening. */
+ if(off < lines[0].end && CH(off) == _T('>'))
+ return FALSE;
+ if(off+1 < lines[0].end && CH(off) == _T('-') && CH(off+1) == _T('>'))
+ return FALSE;
+
+ /* HTML comment must not contyain "--", so we scan just for "--" instead
+ * of "-->" and verify manually that '>' follows. */
+ if(md_scan_for_html_closer(ctx, _T("--"), 2,
+ lines, n_lines, off, max_end, p_end, &ctx->html_comment_horizon))
+ {
+ if(*p_end < max_end && CH(*p_end) == _T('>')) {
+ *p_end = *p_end + 1;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static int
+md_is_html_processing_instruction(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end)
+{
+ OFF off = beg;
+
+ if(off + 2 >= lines[0].end)
+ return FALSE;
+ if(CH(off+1) != _T('?'))
+ return FALSE;
+ off += 2;
+
+ return md_scan_for_html_closer(ctx, _T("?>"), 2,
+ lines, n_lines, off, max_end, p_end, &ctx->html_proc_instr_horizon);
+}
+
+static int
+md_is_html_declaration(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end)
+{
+ OFF off = beg;
+
+ if(off + 2 >= lines[0].end)
+ return FALSE;
+ if(CH(off+1) != _T('!'))
+ return FALSE;
+ off += 2;
+
+ /* Declaration name. */
+ if(off >= lines[0].end || !ISALPHA(off))
+ return FALSE;
+ off++;
+ while(off < lines[0].end && ISALPHA(off))
+ off++;
+ if(off < lines[0].end && !ISWHITESPACE(off))
+ return FALSE;
+
+ return md_scan_for_html_closer(ctx, _T(">"), 1,
+ lines, n_lines, off, max_end, p_end, &ctx->html_decl_horizon);
+}
+
+static int
+md_is_html_cdata(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end)
+{
+ static const CHAR open_str[] = _T("<![CDATA[");
+ static const SZ open_size = SIZEOF_ARRAY(open_str) - 1;
+
+ OFF off = beg;
+
+ if(off + open_size >= lines[0].end)
+ return FALSE;
+ if(memcmp(STR(off), open_str, open_size) != 0)
+ return FALSE;
+ off += open_size;
+
+ if(lines[n_lines-1].end < max_end)
+ max_end = lines[n_lines-1].end - 2;
+
+ return md_scan_for_html_closer(ctx, _T("]]>"), 3,
+ lines, n_lines, off, max_end, p_end, &ctx->html_cdata_horizon);
+}
+
+static int
+md_is_html_any(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end)
+{
+ MD_ASSERT(CH(beg) == _T('<'));
+ return (md_is_html_tag(ctx, lines, n_lines, beg, max_end, p_end) ||
+ md_is_html_comment(ctx, lines, n_lines, beg, max_end, p_end) ||
+ md_is_html_processing_instruction(ctx, lines, n_lines, beg, max_end, p_end) ||
+ md_is_html_declaration(ctx, lines, n_lines, beg, max_end, p_end) ||
+ md_is_html_cdata(ctx, lines, n_lines, beg, max_end, p_end));
+}
+
+
+/****************************
+ *** Recognizing Entity ***
+ ****************************/
+
+static int
+md_is_hex_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end)
+{
+ OFF off = beg;
+
+ while(off < max_end && ISXDIGIT_(text[off]) && off - beg <= 8)
+ off++;
+
+ if(1 <= off - beg && off - beg <= 6) {
+ *p_end = off;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static int
+md_is_dec_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end)
+{
+ OFF off = beg;
+
+ while(off < max_end && ISDIGIT_(text[off]) && off - beg <= 8)
+ off++;
+
+ if(1 <= off - beg && off - beg <= 7) {
+ *p_end = off;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static int
+md_is_named_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end)
+{
+ OFF off = beg;
+
+ if(off < max_end && ISALPHA_(text[off]))
+ off++;
+ else
+ return FALSE;
+
+ while(off < max_end && ISALNUM_(text[off]) && off - beg <= 48)
+ off++;
+
+ if(2 <= off - beg && off - beg <= 48) {
+ *p_end = off;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static int
+md_is_entity_str(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end)
+{
+ int is_contents;
+ OFF off = beg;
+
+ MD_ASSERT(text[off] == _T('&'));
+ off++;
+
+ if(off+2 < max_end && text[off] == _T('#') && (text[off+1] == _T('x') || text[off+1] == _T('X')))
+ is_contents = md_is_hex_entity_contents(ctx, text, off+2, max_end, &off);
+ else if(off+1 < max_end && text[off] == _T('#'))
+ is_contents = md_is_dec_entity_contents(ctx, text, off+1, max_end, &off);
+ else
+ is_contents = md_is_named_entity_contents(ctx, text, off, max_end, &off);
+
+ if(is_contents && off < max_end && text[off] == _T(';')) {
+ *p_end = off+1;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static inline int
+md_is_entity(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end)
+{
+ return md_is_entity_str(ctx, ctx->text, beg, max_end, p_end);
+}
+
+
+/******************************
+ *** Attribute Management ***
+ ******************************/
+
+typedef struct MD_ATTRIBUTE_BUILD_tag MD_ATTRIBUTE_BUILD;
+struct MD_ATTRIBUTE_BUILD_tag {
+ CHAR* text;
+ MD_TEXTTYPE* substr_types;
+ OFF* substr_offsets;
+ int substr_count;
+ int substr_alloc;
+ MD_TEXTTYPE trivial_types[1];
+ OFF trivial_offsets[2];
+};
+
+
+#define MD_BUILD_ATTR_NO_ESCAPES 0x0001
+
+static int
+md_build_attr_append_substr(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build,
+ MD_TEXTTYPE type, OFF off)
+{
+ if(build->substr_count >= build->substr_alloc) {
+ MD_TEXTTYPE* new_substr_types;
+ OFF* new_substr_offsets;
+
+ build->substr_alloc = (build->substr_alloc == 0 ? 8 : build->substr_alloc * 2);
+
+ new_substr_types = (MD_TEXTTYPE*) realloc(build->substr_types,
+ build->substr_alloc * sizeof(MD_TEXTTYPE));
+ if(new_substr_types == NULL) {
+ MD_LOG("realloc() failed.");
+ return -1;
+ }
+ /* Note +1 to reserve space for final offset (== raw_size). */
+ new_substr_offsets = (OFF*) realloc(build->substr_offsets,
+ (build->substr_alloc+1) * sizeof(OFF));
+ if(new_substr_offsets == NULL) {
+ MD_LOG("realloc() failed.");
+ free(new_substr_types);
+ return -1;
+ }
+
+ build->substr_types = new_substr_types;
+ build->substr_offsets = new_substr_offsets;
+ }
+
+ build->substr_types[build->substr_count] = type;
+ build->substr_offsets[build->substr_count] = off;
+ build->substr_count++;
+ return 0;
+}
+
+static void
+md_free_attribute(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build)
+{
+ if(build->substr_alloc > 0) {
+ free(build->text);
+ free(build->substr_types);
+ free(build->substr_offsets);
+ }
+}
+
+static int
+md_build_attribute(MD_CTX* ctx, const CHAR* raw_text, SZ raw_size,
+ unsigned flags, MD_ATTRIBUTE* attr, MD_ATTRIBUTE_BUILD* build)
+{
+ OFF raw_off, off;
+ int is_trivial;
+ int ret = 0;
+
+ memset(build, 0, sizeof(MD_ATTRIBUTE_BUILD));
+
+ /* If there is no backslash and no ampersand, build trivial attribute
+ * without any malloc(). */
+ is_trivial = TRUE;
+ for(raw_off = 0; raw_off < raw_size; raw_off++) {
+ if(ISANYOF3_(raw_text[raw_off], _T('\\'), _T('&'), _T('\0'))) {
+ is_trivial = FALSE;
+ break;
+ }
+ }
+
+ if(is_trivial) {
+ build->text = (CHAR*) (raw_size ? raw_text : NULL);
+ build->substr_types = build->trivial_types;
+ build->substr_offsets = build->trivial_offsets;
+ build->substr_count = 1;
+ build->substr_alloc = 0;
+ build->trivial_types[0] = MD_TEXT_NORMAL;
+ build->trivial_offsets[0] = 0;
+ build->trivial_offsets[1] = raw_size;
+ off = raw_size;
+ } else {
+ build->text = (CHAR*) malloc(raw_size * sizeof(CHAR));
+ if(build->text == NULL) {
+ MD_LOG("malloc() failed.");
+ goto abort;
+ }
+
+ raw_off = 0;
+ off = 0;
+
+ while(raw_off < raw_size) {
+ if(raw_text[raw_off] == _T('\0')) {
+ MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_NULLCHAR, off));
+ memcpy(build->text + off, raw_text + raw_off, 1);
+ off++;
+ raw_off++;
+ continue;
+ }
+
+ if(raw_text[raw_off] == _T('&')) {
+ OFF ent_end;
+
+ if(md_is_entity_str(ctx, raw_text, raw_off, raw_size, &ent_end)) {
+ MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_ENTITY, off));
+ memcpy(build->text + off, raw_text + raw_off, ent_end - raw_off);
+ off += ent_end - raw_off;
+ raw_off = ent_end;
+ continue;
+ }
+ }
+
+ if(build->substr_count == 0 || build->substr_types[build->substr_count-1] != MD_TEXT_NORMAL)
+ MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_NORMAL, off));
+
+ if(!(flags & MD_BUILD_ATTR_NO_ESCAPES) &&
+ raw_text[raw_off] == _T('\\') && raw_off+1 < raw_size &&
+ (ISPUNCT_(raw_text[raw_off+1]) || ISNEWLINE_(raw_text[raw_off+1])))
+ raw_off++;
+
+ build->text[off++] = raw_text[raw_off++];
+ }
+ build->substr_offsets[build->substr_count] = off;
+ }
+
+ attr->text = build->text;
+ attr->size = off;
+ attr->substr_offsets = build->substr_offsets;
+ attr->substr_types = build->substr_types;
+ return 0;
+
+abort:
+ md_free_attribute(ctx, build);
+ return -1;
+}
+
+
+/*********************************************
+ *** Dictionary of Reference Definitions ***
+ *********************************************/
+
+#define MD_FNV1A_BASE 2166136261
+#define MD_FNV1A_PRIME 16777619
+
+static inline unsigned
+md_fnv1a(unsigned base, const void* data, size_t n)
+{
+ const unsigned char* buf = (const unsigned char*) data;
+ unsigned hash = base;
+ size_t i;
+
+ for(i = 0; i < n; i++) {
+ hash ^= buf[i];
+ hash *= MD_FNV1A_PRIME;
+ }
+
+ return hash;
+}
+
+
+struct MD_REF_DEF_tag {
+ CHAR* label;
+ CHAR* title;
+ unsigned hash;
+ SZ label_size : 24;
+ unsigned label_needs_free : 1;
+ unsigned title_needs_free : 1;
+ SZ title_size;
+ OFF dest_beg;
+ OFF dest_end;
+};
+
+/* Label equivalence is quite complicated with regards to whitespace and case
+ * folding. This complicates computing a hash of it as well as direct comparison
+ * of two labels. */
+
+static unsigned
+md_link_label_hash(const CHAR* label, SZ size)
+{
+ unsigned hash = MD_FNV1A_BASE;
+ OFF off;
+ unsigned codepoint;
+ int is_whitespace = FALSE;
+
+ off = md_skip_unicode_whitespace(label, 0, size);
+ while(off < size) {
+ SZ char_size;
+
+ codepoint = md_decode_unicode(label, off, size, &char_size);
+ is_whitespace = ISUNICODEWHITESPACE_(codepoint) || ISNEWLINE_(label[off]);
+
+ if(is_whitespace) {
+ codepoint = ' ';
+ hash = md_fnv1a(hash, &codepoint, sizeof(unsigned));
+ off = md_skip_unicode_whitespace(label, off, size);
+ } else {
+ MD_UNICODE_FOLD_INFO fold_info;
+
+ md_get_unicode_fold_info(codepoint, &fold_info);
+ hash = md_fnv1a(hash, fold_info.codepoints, fold_info.n_codepoints * sizeof(unsigned));
+ off += char_size;
+ }
+ }
+
+ return hash;
+}
+
+static OFF
+md_link_label_cmp_load_fold_info(const CHAR* label, OFF off, SZ size,
+ MD_UNICODE_FOLD_INFO* fold_info)
+{
+ unsigned codepoint;
+ SZ char_size;
+
+ if(off >= size) {
+ /* Treat end of link label as a whitespace. */
+ goto whitespace;
+ }
+
+ if(ISNEWLINE_(label[off])) {
+ /* Treat new lines as a whitespace. */
+ off++;
+ goto whitespace;
+ }
+
+ codepoint = md_decode_unicode(label, off, size, &char_size);
+ off += char_size;
+ if(ISUNICODEWHITESPACE_(codepoint)) {
+ /* Treat all whitespace as equivalent */
+ goto whitespace;
+ }
+
+ /* Get real folding info. */
+ md_get_unicode_fold_info(codepoint, fold_info);
+ return off;
+
+whitespace:
+ fold_info->codepoints[0] = _T(' ');
+ fold_info->n_codepoints = 1;
+ return off;
+}
+
+static int
+md_link_label_cmp(const CHAR* a_label, SZ a_size, const CHAR* b_label, SZ b_size)
+{
+ OFF a_off;
+ OFF b_off;
+ int a_reached_end = FALSE;
+ int b_reached_end = FALSE;
+ MD_UNICODE_FOLD_INFO a_fi = { 0 };
+ MD_UNICODE_FOLD_INFO b_fi = { 0 };
+ OFF a_fi_off = 0;
+ OFF b_fi_off = 0;
+ int cmp;
+
+ a_off = md_skip_unicode_whitespace(a_label, 0, a_size);
+ b_off = md_skip_unicode_whitespace(b_label, 0, b_size);
+ while(!a_reached_end && !b_reached_end) {
+ /* If needed, load fold info for next char. */
+ if(a_fi_off >= a_fi.n_codepoints) {
+ a_fi_off = 0;
+ a_off = md_link_label_cmp_load_fold_info(a_label, a_off, a_size, &a_fi);
+ a_reached_end = (a_off >= a_size);
+ }
+ if(b_fi_off >= b_fi.n_codepoints) {
+ b_fi_off = 0;
+ b_off = md_link_label_cmp_load_fold_info(b_label, b_off, b_size, &b_fi);
+ b_reached_end = (b_off >= b_size);
+ }
+
+ cmp = b_fi.codepoints[b_fi_off] - a_fi.codepoints[a_fi_off];
+ if(cmp != 0)
+ return cmp;
+
+ a_fi_off++;
+ b_fi_off++;
+ }
+
+ return 0;
+}
+
+typedef struct MD_REF_DEF_LIST_tag MD_REF_DEF_LIST;
+struct MD_REF_DEF_LIST_tag {
+ int n_ref_defs;
+ int alloc_ref_defs;
+ MD_REF_DEF* ref_defs[]; /* Valid items always point into ctx->ref_defs[] */
+};
+
+static int
+md_ref_def_cmp(const void* a, const void* b)
+{
+ const MD_REF_DEF* a_ref = *(const MD_REF_DEF**)a;
+ const MD_REF_DEF* b_ref = *(const MD_REF_DEF**)b;
+
+ if(a_ref->hash < b_ref->hash)
+ return -1;
+ else if(a_ref->hash > b_ref->hash)
+ return +1;
+ else
+ return md_link_label_cmp(a_ref->label, a_ref->label_size, b_ref->label, b_ref->label_size);
+}
+
+static int
+md_ref_def_cmp_stable(const void* a, const void* b)
+{
+ int cmp;
+
+ cmp = md_ref_def_cmp(a, b);
+
+ /* Ensure stability of the sorting. */
+ if(cmp == 0) {
+ const MD_REF_DEF* a_ref = *(const MD_REF_DEF**)a;
+ const MD_REF_DEF* b_ref = *(const MD_REF_DEF**)b;
+
+ if(a_ref < b_ref)
+ cmp = -1;
+ else if(a_ref > b_ref)
+ cmp = +1;
+ else
+ cmp = 0;
+ }
+
+ return cmp;
+}
+
+static int
+md_build_ref_def_hashtable(MD_CTX* ctx)
+{
+ int i, j;
+
+ if(ctx->n_ref_defs == 0)
+ return 0;
+
+ ctx->ref_def_hashtable_size = (ctx->n_ref_defs * 5) / 4;
+ ctx->ref_def_hashtable = malloc(ctx->ref_def_hashtable_size * sizeof(void*));
+ if(ctx->ref_def_hashtable == NULL) {
+ MD_LOG("malloc() failed.");
+ goto abort;
+ }
+ memset(ctx->ref_def_hashtable, 0, ctx->ref_def_hashtable_size * sizeof(void*));
+
+ /* Each member of ctx->ref_def_hashtable[] can be:
+ * -- NULL,
+ * -- pointer to the MD_REF_DEF in ctx->ref_defs[], or
+ * -- pointer to a MD_REF_DEF_LIST, which holds multiple pointers to
+ * such MD_REF_DEFs.
+ */
+ for(i = 0; i < ctx->n_ref_defs; i++) {
+ MD_REF_DEF* def = &ctx->ref_defs[i];
+ void* bucket;
+ MD_REF_DEF_LIST* list;
+
+ def->hash = md_link_label_hash(def->label, def->label_size);
+ bucket = ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size];
+
+ if(bucket == NULL) {
+ ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = def;
+ continue;
+ }
+
+ if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs) {
+ /* The bucket already contains one ref. def. Lets see whether it
+ * is the same label (ref. def. duplicate) or different one
+ * (hash conflict). */
+ MD_REF_DEF* old_def = (MD_REF_DEF*) bucket;
+
+ if(md_link_label_cmp(def->label, def->label_size, old_def->label, old_def->label_size) == 0) {
+ /* Ignore this ref. def. */
+ continue;
+ }
+
+ /* Make the bucket capable of holding more ref. defs. */
+ list = (MD_REF_DEF_LIST*) malloc(sizeof(MD_REF_DEF_LIST) + 4 * sizeof(MD_REF_DEF));
+ if(list == NULL) {
+ MD_LOG("malloc() failed.");
+ goto abort;
+ }
+ list->ref_defs[0] = old_def;
+ list->ref_defs[1] = def;
+ list->n_ref_defs = 2;
+ list->alloc_ref_defs = 4;
+ ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = list;
+ continue;
+ }
+
+ /* Append the def to the bucket list. */
+ list = (MD_REF_DEF_LIST*) bucket;
+ if(list->n_ref_defs >= list->alloc_ref_defs) {
+ MD_REF_DEF_LIST* list_tmp = (MD_REF_DEF_LIST*) realloc(list,
+ sizeof(MD_REF_DEF_LIST) + 2 * list->alloc_ref_defs * sizeof(MD_REF_DEF));
+ if(list_tmp == NULL) {
+ MD_LOG("realloc() failed.");
+ goto abort;
+ }
+ list = list_tmp;
+ list->alloc_ref_defs *= 2;
+ ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = list;
+ }
+
+ list->ref_defs[list->n_ref_defs] = def;
+ list->n_ref_defs++;
+ }
+
+ /* Sort the complex buckets so we can use bsearch() with them. */
+ for(i = 0; i < ctx->ref_def_hashtable_size; i++) {
+ void* bucket = ctx->ref_def_hashtable[i];
+ MD_REF_DEF_LIST* list;
+
+ if(bucket == NULL)
+ continue;
+ if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs)
+ continue;
+
+ list = (MD_REF_DEF_LIST*) bucket;
+ qsort(list->ref_defs, list->n_ref_defs, sizeof(MD_REF_DEF*), md_ref_def_cmp_stable);
+
+ /* Disable duplicates. */
+ for(j = 1; j < list->n_ref_defs; j++) {
+ if(md_ref_def_cmp(&list->ref_defs[j-1], &list->ref_defs[j]) == 0)
+ list->ref_defs[j] = list->ref_defs[j-1];
+ }
+ }
+
+ return 0;
+
+abort:
+ return -1;
+}
+
+static void
+md_free_ref_def_hashtable(MD_CTX* ctx)
+{
+ if(ctx->ref_def_hashtable != NULL) {
+ int i;
+
+ for(i = 0; i < ctx->ref_def_hashtable_size; i++) {
+ void* bucket = ctx->ref_def_hashtable[i];
+ if(bucket == NULL)
+ continue;
+ if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs)
+ continue;
+ free(bucket);
+ }
+
+ free(ctx->ref_def_hashtable);
+ }
+}
+
+static const MD_REF_DEF*
+md_lookup_ref_def(MD_CTX* ctx, const CHAR* label, SZ label_size)
+{
+ unsigned hash;
+ void* bucket;
+
+ if(ctx->ref_def_hashtable_size == 0)
+ return NULL;
+
+ hash = md_link_label_hash(label, label_size);
+ bucket = ctx->ref_def_hashtable[hash % ctx->ref_def_hashtable_size];
+
+ if(bucket == NULL) {
+ return NULL;
+ } else if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs) {
+ const MD_REF_DEF* def = (MD_REF_DEF*) bucket;
+
+ if(md_link_label_cmp(def->label, def->label_size, label, label_size) == 0)
+ return def;
+ else
+ return NULL;
+ } else {
+ MD_REF_DEF_LIST* list = (MD_REF_DEF_LIST*) bucket;
+ MD_REF_DEF key_buf;
+ const MD_REF_DEF* key = &key_buf;
+ const MD_REF_DEF** ret;
+
+ key_buf.label = (CHAR*) label;
+ key_buf.label_size = label_size;
+ key_buf.hash = md_link_label_hash(key_buf.label, key_buf.label_size);
+
+ ret = (const MD_REF_DEF**) bsearch(&key, list->ref_defs,
+ list->n_ref_defs, sizeof(MD_REF_DEF*), md_ref_def_cmp);
+ if(ret != NULL)
+ return *ret;
+ else
+ return NULL;
+ }
+}
+
+
+/***************************
+ *** Recognizing Links ***
+ ***************************/
+
+/* Note this code is partially shared between processing inlines and blocks
+ * as reference definitions and links share some helper parser functions.
+ */
+
+typedef struct MD_LINK_ATTR_tag MD_LINK_ATTR;
+struct MD_LINK_ATTR_tag {
+ OFF dest_beg;
+ OFF dest_end;
+
+ CHAR* title;
+ SZ title_size;
+ int title_needs_free;
+};
+
+
+static int
+md_is_link_label(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg,
+ OFF* p_end, int* p_beg_line_index, int* p_end_line_index,
+ OFF* p_contents_beg, OFF* p_contents_end)
+{
+ OFF off = beg;
+ OFF contents_beg = 0;
+ OFF contents_end = 0;
+ int line_index = 0;
+ int len = 0;
+
+ if(CH(off) != _T('['))
+ return FALSE;
+ off++;
+
+ while(1) {
+ OFF line_end = lines[line_index].end;
+
+ while(off < line_end) {
+ if(CH(off) == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) {
+ if(contents_end == 0) {
+ contents_beg = off;
+ *p_beg_line_index = line_index;
+ }
+ contents_end = off + 2;
+ off += 2;
+ } else if(CH(off) == _T('[')) {
+ return FALSE;
+ } else if(CH(off) == _T(']')) {
+ if(contents_beg < contents_end) {
+ /* Success. */
+ *p_contents_beg = contents_beg;
+ *p_contents_end = contents_end;
+ *p_end = off+1;
+ *p_end_line_index = line_index;
+ return TRUE;
+ } else {
+ /* Link label must have some non-whitespace contents. */
+ return FALSE;
+ }
+ } else {
+ unsigned codepoint;
+ SZ char_size;
+
+ codepoint = md_decode_unicode(ctx->text, off, ctx->size, &char_size);
+ if(!ISUNICODEWHITESPACE_(codepoint)) {
+ if(contents_end == 0) {
+ contents_beg = off;
+ *p_beg_line_index = line_index;
+ }
+ contents_end = off + char_size;
+ }
+
+ off += char_size;
+ }
+
+ len++;
+ if(len > 999)
+ return FALSE;
+ }
+
+ line_index++;
+ len++;
+ if(line_index < n_lines)
+ off = lines[line_index].beg;
+ else
+ break;
+ }
+
+ return FALSE;
+}
+
+static int
+md_is_link_destination_A(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end,
+ OFF* p_contents_beg, OFF* p_contents_end)
+{
+ OFF off = beg;
+
+ if(off >= max_end || CH(off) != _T('<'))
+ return FALSE;
+ off++;
+
+ while(off < max_end) {
+ if(CH(off) == _T('\\') && off+1 < max_end && ISPUNCT(off+1)) {
+ off += 2;
+ continue;
+ }
+
+ if(ISNEWLINE(off) || CH(off) == _T('<'))
+ return FALSE;
+
+ if(CH(off) == _T('>')) {
+ /* Success. */
+ *p_contents_beg = beg+1;
+ *p_contents_end = off;
+ *p_end = off+1;
+ return TRUE;
+ }
+
+ off++;
+ }
+
+ return FALSE;
+}
+
+static int
+md_is_link_destination_B(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end,
+ OFF* p_contents_beg, OFF* p_contents_end)
+{
+ OFF off = beg;
+ int parenthesis_level = 0;
+
+ while(off < max_end) {
+ if(CH(off) == _T('\\') && off+1 < max_end && ISPUNCT(off+1)) {
+ off += 2;
+ continue;
+ }
+
+ if(ISWHITESPACE(off) || ISCNTRL(off))
+ break;
+
+ /* Link destination may include balanced pairs of unescaped '(' ')'.
+ * Note we limit the maximal nesting level by 32 to protect us from
+ * https://github.com/jgm/cmark/issues/214 */
+ if(CH(off) == _T('(')) {
+ parenthesis_level++;
+ if(parenthesis_level > 32)
+ return FALSE;
+ } else if(CH(off) == _T(')')) {
+ if(parenthesis_level == 0)
+ break;
+ parenthesis_level--;
+ }
+
+ off++;
+ }
+
+ if(parenthesis_level != 0 || off == beg)
+ return FALSE;
+
+ /* Success. */
+ *p_contents_beg = beg;
+ *p_contents_end = off;
+ *p_end = off;
+ return TRUE;
+}
+
+static inline int
+md_is_link_destination(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end,
+ OFF* p_contents_beg, OFF* p_contents_end)
+{
+ if(CH(beg) == _T('<'))
+ return md_is_link_destination_A(ctx, beg, max_end, p_end, p_contents_beg, p_contents_end);
+ else
+ return md_is_link_destination_B(ctx, beg, max_end, p_end, p_contents_beg, p_contents_end);
+}
+
+static int
+md_is_link_title(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg,
+ OFF* p_end, int* p_beg_line_index, int* p_end_line_index,
+ OFF* p_contents_beg, OFF* p_contents_end)
+{
+ OFF off = beg;
+ CHAR closer_char;
+ int line_index = 0;
+
+ /* White space with up to one line break. */
+ while(off < lines[line_index].end && ISWHITESPACE(off))
+ off++;
+ if(off >= lines[line_index].end) {
+ line_index++;
+ if(line_index >= n_lines)
+ return FALSE;
+ off = lines[line_index].beg;
+ }
+ if(off == beg)
+ return FALSE;
+
+ *p_beg_line_index = line_index;
+
+ /* First char determines how to detect end of it. */
+ switch(CH(off)) {
+ case _T('"'): closer_char = _T('"'); break;
+ case _T('\''): closer_char = _T('\''); break;
+ case _T('('): closer_char = _T(')'); break;
+ default: return FALSE;
+ }
+ off++;
+
+ *p_contents_beg = off;
+
+ while(line_index < n_lines) {
+ OFF line_end = lines[line_index].end;
+
+ while(off < line_end) {
+ if(CH(off) == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) {
+ off++;
+ } else if(CH(off) == closer_char) {
+ /* Success. */
+ *p_contents_end = off;
+ *p_end = off+1;
+ *p_end_line_index = line_index;
+ return TRUE;
+ } else if(closer_char == _T(')') && CH(off) == _T('(')) {
+ /* ()-style title cannot contain (unescaped '(')) */
+ return FALSE;
+ }
+
+ off++;
+ }
+
+ line_index++;
+ }
+
+ return FALSE;
+}
+
+/* Returns 0 if it is not a reference definition.
+ *
+ * Returns N > 0 if it is a reference definition. N then corresponds to the
+ * number of lines forming it). In this case the definition is stored for
+ * resolving any links referring to it.
+ *
+ * Returns -1 in case of an error (out of memory).
+ */
+static int
+md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
+{
+ OFF label_contents_beg;
+ OFF label_contents_end;
+ int label_contents_line_index = -1;
+ int label_is_multiline;
+ CHAR* label;
+ SZ label_size;
+ int label_needs_free = FALSE;
+ OFF dest_contents_beg;
+ OFF dest_contents_end;
+ OFF title_contents_beg;
+ OFF title_contents_end;
+ int title_contents_line_index;
+ int title_is_multiline;
+ OFF off;
+ int line_index = 0;
+ int tmp_line_index;
+ MD_REF_DEF* def;
+ int ret;
+
+ /* Link label. */
+ if(!md_is_link_label(ctx, lines, n_lines, lines[0].beg,
+ &off, &label_contents_line_index, &line_index,
+ &label_contents_beg, &label_contents_end))
+ return FALSE;
+ label_is_multiline = (label_contents_line_index != line_index);
+
+ /* Colon. */
+ if(off >= lines[line_index].end || CH(off) != _T(':'))
+ return FALSE;
+ off++;
+
+ /* Optional white space with up to one line break. */
+ while(off < lines[line_index].end && ISWHITESPACE(off))
+ off++;
+ if(off >= lines[line_index].end) {
+ line_index++;
+ if(line_index >= n_lines)
+ return FALSE;
+ off = lines[line_index].beg;
+ }
+
+ /* Link destination. */
+ if(!md_is_link_destination(ctx, off, lines[line_index].end,
+ &off, &dest_contents_beg, &dest_contents_end))
+ return FALSE;
+
+ /* (Optional) title. Note we interpret it as an title only if nothing
+ * more follows on its last line. */
+ if(md_is_link_title(ctx, lines + line_index, n_lines - line_index, off,
+ &off, &title_contents_line_index, &tmp_line_index,
+ &title_contents_beg, &title_contents_end)
+ && off >= lines[line_index + tmp_line_index].end)
+ {
+ title_is_multiline = (tmp_line_index != title_contents_line_index);
+ title_contents_line_index += line_index;
+ line_index += tmp_line_index;
+ } else {
+ /* Not a title. */
+ title_is_multiline = FALSE;
+ title_contents_beg = off;
+ title_contents_end = off;
+ title_contents_line_index = 0;
+ }
+
+ /* Nothing more can follow on the last line. */
+ if(off < lines[line_index].end)
+ return FALSE;
+
+ /* Construct label. */
+ if(!label_is_multiline) {
+ label = (CHAR*) STR(label_contents_beg);
+ label_size = label_contents_end - label_contents_beg;
+ label_needs_free = FALSE;
+ } else {
+ MD_CHECK(md_merge_lines_alloc(ctx, label_contents_beg, label_contents_end,
+ lines + label_contents_line_index, n_lines - label_contents_line_index,
+ _T(' '), &label, &label_size));
+ label_needs_free = TRUE;
+ }
+
+ /* Store the reference definition. */
+ if(ctx->n_ref_defs >= ctx->alloc_ref_defs) {
+ MD_REF_DEF* new_defs;
+
+ ctx->alloc_ref_defs = (ctx->alloc_ref_defs > 0 ? ctx->alloc_ref_defs * 2 : 16);
+ new_defs = (MD_REF_DEF*) realloc(ctx->ref_defs, ctx->alloc_ref_defs * sizeof(MD_REF_DEF));
+ if(new_defs == NULL) {
+ MD_LOG("realloc() failed.");
+ ret = -1;
+ goto abort;
+ }
+
+ ctx->ref_defs = new_defs;
+ }
+
+ def = &ctx->ref_defs[ctx->n_ref_defs];
+ memset(def, 0, sizeof(MD_REF_DEF));
+
+ def->label = label;
+ def->label_size = label_size;
+ def->label_needs_free = label_needs_free;
+
+ def->dest_beg = dest_contents_beg;
+ def->dest_end = dest_contents_end;
+
+ if(title_contents_beg >= title_contents_end) {
+ def->title = NULL;
+ def->title_size = 0;
+ } else if(!title_is_multiline) {
+ def->title = (CHAR*) STR(title_contents_beg);
+ def->title_size = title_contents_end - title_contents_beg;
+ } else {
+ MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end,
+ lines + title_contents_line_index, n_lines - title_contents_line_index,
+ _T('\n'), &def->title, &def->title_size));
+ def->title_needs_free = TRUE;
+ }
+
+ /* Success. */
+ ctx->n_ref_defs++;
+ return line_index + 1;
+
+abort:
+ /* Failure. */
+ if(label_needs_free)
+ free(label);
+ return -1;
+}
+
+static int
+md_is_link_reference(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
+ OFF beg, OFF end, MD_LINK_ATTR* attr)
+{
+ const MD_REF_DEF* def;
+ const MD_LINE* beg_line;
+ const MD_LINE* end_line;
+ CHAR* label;
+ SZ label_size;
+ int ret;
+
+ MD_ASSERT(CH(beg) == _T('[') || CH(beg) == _T('!'));
+ MD_ASSERT(CH(end-1) == _T(']'));
+
+ beg += (CH(beg) == _T('!') ? 2 : 1);
+ end--;
+
+ /* Find lines corresponding to the beg and end positions. */
+ MD_ASSERT(lines[0].beg <= beg);
+ beg_line = lines;
+ while(beg >= beg_line->end)
+ beg_line++;
+
+ MD_ASSERT(end <= lines[n_lines-1].end);
+ end_line = beg_line;
+ while(end >= end_line->end)
+ end_line++;
+
+ if(beg_line != end_line) {
+ MD_CHECK(md_merge_lines_alloc(ctx, beg, end, beg_line,
+ n_lines - (beg_line - lines), _T(' '), &label, &label_size));
+ } else {
+ label = (CHAR*) STR(beg);
+ label_size = end - beg;
+ }
+
+ def = md_lookup_ref_def(ctx, label, label_size);
+ if(def != NULL) {
+ attr->dest_beg = def->dest_beg;
+ attr->dest_end = def->dest_end;
+ attr->title = def->title;
+ attr->title_size = def->title_size;
+ attr->title_needs_free = FALSE;
+ }
+
+ if(beg_line != end_line)
+ free(label);
+
+ ret = (def != NULL);
+
+abort:
+ return ret;
+}
+
+static int
+md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
+ OFF beg, OFF* p_end, MD_LINK_ATTR* attr)
+{
+ int line_index = 0;
+ int tmp_line_index;
+ OFF title_contents_beg;
+ OFF title_contents_end;
+ int title_contents_line_index;
+ int title_is_multiline;
+ OFF off = beg;
+ int ret = FALSE;
+
+ while(off >= lines[line_index].end)
+ line_index++;
+
+ MD_ASSERT(CH(off) == _T('('));
+ off++;
+
+ /* Optional white space with up to one line break. */
+ while(off < lines[line_index].end && ISWHITESPACE(off))
+ off++;
+ if(off >= lines[line_index].end && ISNEWLINE(off)) {
+ line_index++;
+ if(line_index >= n_lines)
+ return FALSE;
+ off = lines[line_index].beg;
+ }
+
+ /* Link destination may be omitted, but only when not also having a title. */
+ if(off < ctx->size && CH(off) == _T(')')) {
+ attr->dest_beg = off;
+ attr->dest_end = off;
+ attr->title = NULL;
+ attr->title_size = 0;
+ attr->title_needs_free = FALSE;
+ off++;
+ *p_end = off;
+ return TRUE;
+ }
+
+ /* Link destination. */
+ if(!md_is_link_destination(ctx, off, lines[line_index].end,
+ &off, &attr->dest_beg, &attr->dest_end))
+ return FALSE;
+
+ /* (Optional) title. */
+ if(md_is_link_title(ctx, lines + line_index, n_lines - line_index, off,
+ &off, &title_contents_line_index, &tmp_line_index,
+ &title_contents_beg, &title_contents_end))
+ {
+ title_is_multiline = (tmp_line_index != title_contents_line_index);
+ title_contents_line_index += line_index;
+ line_index += tmp_line_index;
+ } else {
+ /* Not a title. */
+ title_is_multiline = FALSE;
+ title_contents_beg = off;
+ title_contents_end = off;
+ title_contents_line_index = 0;
+ }
+
+ /* Optional whitespace followed with final ')'. */
+ while(off < lines[line_index].end && ISWHITESPACE(off))
+ off++;
+ if(off >= lines[line_index].end && ISNEWLINE(off)) {
+ line_index++;
+ if(line_index >= n_lines)
+ return FALSE;
+ off = lines[line_index].beg;
+ }
+ if(CH(off) != _T(')'))
+ goto abort;
+ off++;
+
+ if(title_contents_beg >= title_contents_end) {
+ attr->title = NULL;
+ attr->title_size = 0;
+ attr->title_needs_free = FALSE;
+ } else if(!title_is_multiline) {
+ attr->title = (CHAR*) STR(title_contents_beg);
+ attr->title_size = title_contents_end - title_contents_beg;
+ attr->title_needs_free = FALSE;
+ } else {
+ MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end,
+ lines + title_contents_line_index, n_lines - title_contents_line_index,
+ _T('\n'), &attr->title, &attr->title_size));
+ attr->title_needs_free = TRUE;
+ }
+
+ *p_end = off;
+ ret = TRUE;
+
+abort:
+ return ret;
+}
+
+static void
+md_free_ref_defs(MD_CTX* ctx)
+{
+ int i;
+
+ for(i = 0; i < ctx->n_ref_defs; i++) {
+ MD_REF_DEF* def = &ctx->ref_defs[i];
+
+ if(def->label_needs_free)
+ free(def->label);
+ if(def->title_needs_free)
+ free(def->title);
+ }
+
+ free(ctx->ref_defs);
+}
+
+
+/******************************************
+ *** Processing Inlines (a.k.a Spans) ***
+ ******************************************/
+
+/* We process inlines in few phases:
+ *
+ * (1) We go through the block text and collect all significant characters
+ * which may start/end a span or some other significant position into
+ * ctx->marks[]. Core of this is what md_collect_marks() does.
+ *
+ * We also do some very brief preliminary context-less analysis, whether
+ * it might be opener or closer (e.g. of an emphasis span).
+ *
+ * This speeds the other steps as we do not need to re-iterate over all
+ * characters anymore.
+ *
+ * (2) We analyze each potential mark types, in order by their precedence.
+ *
+ * In each md_analyze_XXX() function, we re-iterate list of the marks,
+ * skipping already resolved regions (in preceding precedences) and try to
+ * resolve them.
+ *
+ * (2.1) For trivial marks, which are single (e.g. HTML entity), we just mark
+ * them as resolved.
+ *
+ * (2.2) For range-type marks, we analyze whether the mark could be closer
+ * and, if yes, whether there is some preceding opener it could satisfy.
+ *
+ * If not we check whether it could be really an opener and if yes, we
+ * remember it so subsequent closers may resolve it.
+ *
+ * (3) Finally, when all marks were analyzed, we render the block contents
+ * by calling MD_RENDERER::text() callback, interrupting by ::enter_span()
+ * or ::close_span() whenever we reach a resolved mark.
+ */
+
+
+/* The mark structure.
+ *
+ * '\\': Maybe escape sequence.
+ * '\0': NULL char.
+ * '*': Maybe (strong) emphasis start/end.
+ * '_': Maybe (strong) emphasis start/end.
+ * '~': Maybe strikethrough start/end (needs MD_FLAG_STRIKETHROUGH).
+ * '`': Maybe code span start/end.
+ * '&': Maybe start of entity.
+ * ';': Maybe end of entity.
+ * '<': Maybe start of raw HTML or autolink.
+ * '>': Maybe end of raw HTML or autolink.
+ * '[': Maybe start of link label or link text.
+ * '!': Equivalent of '[' for image.
+ * ']': Maybe end of link label or link text.
+ * '@': Maybe permissive e-mail auto-link (needs MD_FLAG_PERMISSIVEEMAILAUTOLINKS).
+ * ':': Maybe permissive URL auto-link (needs MD_FLAG_PERMISSIVEURLAUTOLINKS).
+ * '.': Maybe permissive WWW auto-link (needs MD_FLAG_PERMISSIVEWWWAUTOLINKS).
+ * 'D': Dummy mark, it reserves a space for splitting a previous mark
+ * (e.g. emphasis) or to make more space for storing some special data
+ * related to the preceding mark (e.g. link).
+ *
+ * Note that not all instances of these chars in the text imply creation of the
+ * structure. Only those which have (or may have, after we see more context)
+ * the special meaning.
+ *
+ * (Keep this struct as small as possible to fit as much of them into CPU
+ * cache line.)
+ */
+struct MD_MARK_tag {
+ OFF beg;
+ OFF end;
+
+ /* For unresolved openers, 'prev' and 'next' form the chain of open openers
+ * of given type 'ch'.
+ *
+ * During resolving, we disconnect from the chain and point to the
+ * corresponding counterpart so opener points to its closer and vice versa.
+ */
+ int prev;
+ int next;
+ CHAR ch;
+ unsigned char flags;
+};
+
+/* Mark flags (these apply to ALL mark types). */
+#define MD_MARK_POTENTIAL_OPENER 0x01 /* Maybe opener. */
+#define MD_MARK_POTENTIAL_CLOSER 0x02 /* Maybe closer. */
+#define MD_MARK_OPENER 0x04 /* Definitely opener. */
+#define MD_MARK_CLOSER 0x08 /* Definitely closer. */
+#define MD_MARK_RESOLVED 0x10 /* Resolved in any definite way. */
+
+/* Mark flags specific for various mark types (so they can share bits). */
+#define MD_MARK_EMPH_INTRAWORD 0x20 /* Helper for the "rule of 3". */
+#define MD_MARK_EMPH_MOD3_0 0x40
+#define MD_MARK_EMPH_MOD3_1 0x80
+#define MD_MARK_EMPH_MOD3_2 (0x40 | 0x80)
+#define MD_MARK_EMPH_MOD3_MASK (0x40 | 0x80)
+#define MD_MARK_AUTOLINK 0x20 /* Distinguisher for '<', '>'. */
+#define MD_MARK_VALIDPERMISSIVEAUTOLINK 0x20 /* For permissive autolinks. */
+
+static MD_MARKCHAIN*
+md_asterisk_chain(MD_CTX* ctx, unsigned flags)
+{
+ switch(flags & (MD_MARK_EMPH_INTRAWORD | MD_MARK_EMPH_MOD3_MASK)) {
+ case MD_MARK_EMPH_INTRAWORD | MD_MARK_EMPH_MOD3_0: return &ASTERISK_OPENERS_intraword_mod3_0;
+ case MD_MARK_EMPH_INTRAWORD | MD_MARK_EMPH_MOD3_1: return &ASTERISK_OPENERS_intraword_mod3_1;
+ case MD_MARK_EMPH_INTRAWORD | MD_MARK_EMPH_MOD3_2: return &ASTERISK_OPENERS_intraword_mod3_2;
+ case MD_MARK_EMPH_MOD3_0: return &ASTERISK_OPENERS_extraword_mod3_0;
+ case MD_MARK_EMPH_MOD3_1: return &ASTERISK_OPENERS_extraword_mod3_1;
+ case MD_MARK_EMPH_MOD3_2: return &ASTERISK_OPENERS_extraword_mod3_2;
+ default: MD_UNREACHABLE();
+ }
+ return NULL;
+}
+
+static MD_MARKCHAIN*
+md_mark_chain(MD_CTX* ctx, int mark_index)
+{
+ MD_MARK* mark = &ctx->marks[mark_index];
+
+ switch(mark->ch) {
+ case _T('*'): return md_asterisk_chain(ctx, mark->flags);
+ case _T('_'): return &UNDERSCORE_OPENERS;
+ case _T('~'): return &TILDE_OPENERS;
+ case _T('['): return &BRACKET_OPENERS;
+ case _T('|'): return &TABLECELLBOUNDARIES;
+ default: return NULL;
+ }
+}
+
+static MD_MARK*
+md_push_mark(MD_CTX* ctx)
+{
+ if(ctx->n_marks >= ctx->alloc_marks) {
+ MD_MARK* new_marks;
+
+ ctx->alloc_marks = (ctx->alloc_marks > 0 ? ctx->alloc_marks * 2 : 64);
+ new_marks = realloc(ctx->marks, ctx->alloc_marks * sizeof(MD_MARK));
+ if(new_marks == NULL) {
+ MD_LOG("realloc() failed.");
+ return NULL;
+ }
+
+ ctx->marks = new_marks;
+ }
+
+ return &ctx->marks[ctx->n_marks++];
+}
+
+#define PUSH_MARK_() \
+ do { \
+ mark = md_push_mark(ctx); \
+ if(mark == NULL) { \
+ ret = -1; \
+ goto abort; \
+ } \
+ } while(0)
+
+#define PUSH_MARK(ch_, beg_, end_, flags_) \
+ do { \
+ PUSH_MARK_(); \
+ mark->beg = (beg_); \
+ mark->end = (end_); \
+ mark->prev = -1; \
+ mark->next = -1; \
+ mark->ch = (char)(ch_); \
+ mark->flags = (flags_); \
+ } while(0)
+
+
+static void
+md_mark_chain_append(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index)
+{
+ if(chain->tail >= 0)
+ ctx->marks[chain->tail].next = mark_index;
+ else
+ chain->head = mark_index;
+
+ ctx->marks[mark_index].prev = chain->tail;
+ chain->tail = mark_index;
+}
+
+/* Sometimes, we need to store a pointer into the mark. It is quite rare
+ * so we do not bother to make MD_MARK use union, and it can only happen
+ * for dummy marks. */
+static inline void
+md_mark_store_ptr(MD_CTX* ctx, int mark_index, void* ptr)
+{
+ MD_MARK* mark = &ctx->marks[mark_index];
+ MD_ASSERT(mark->ch == 'D');
+
+ /* Check only members beg and end are misused for this. */
+ MD_ASSERT(sizeof(void*) <= 2 * sizeof(OFF));
+ memcpy(mark, &ptr, sizeof(void*));
+}
+
+static inline void*
+md_mark_get_ptr(MD_CTX* ctx, int mark_index)
+{
+ void* ptr;
+ MD_MARK* mark = &ctx->marks[mark_index];
+ MD_ASSERT(mark->ch == 'D');
+ memcpy(&ptr, mark, sizeof(void*));
+ return ptr;
+}
+
+static void
+md_resolve_range(MD_CTX* ctx, MD_MARKCHAIN* chain, int opener_index, int closer_index)
+{
+ MD_MARK* opener = &ctx->marks[opener_index];
+ MD_MARK* closer = &ctx->marks[closer_index];
+
+ /* Remove opener from the list of openers. */
+ if(chain != NULL) {
+ if(opener->prev >= 0)
+ ctx->marks[opener->prev].next = opener->next;
+ else
+ chain->head = opener->next;
+
+ if(opener->next >= 0)
+ ctx->marks[opener->next].prev = opener->prev;
+ else
+ chain->tail = opener->prev;
+ }
+
+ /* Interconnect opener and closer and mark both as resolved. */
+ opener->next = closer_index;
+ opener->flags |= MD_MARK_OPENER | MD_MARK_RESOLVED;
+ closer->prev = opener_index;
+ closer->flags |= MD_MARK_CLOSER | MD_MARK_RESOLVED;
+}
+
+
+#define MD_ROLLBACK_ALL 0
+#define MD_ROLLBACK_CROSSING 1
+
+/* In the range ctx->marks[opener_index] ... [closer_index], undo some or all
+ * resolvings accordingly to these rules:
+ *
+ * (1) All openers BEFORE the range corresponding to any closer inside the
+ * range are un-resolved and they are re-added to their respective chains
+ * of unresolved openers. This ensures we can reuse the opener for closers
+ * AFTER the range.
+ *
+ * (2) If 'how' is MD_ROLLBACK_ALL, then ALL resolved marks inside the range
+ * are discarded.
+ *
+ * (3) If 'how' is MD_ROLLBACK_CROSSING, only closers with openers handled
+ * in (1) are discarded. I.e. pairs of openers and closers which are both
+ * inside the range are retained as well as any unpaired marks.
+ */
+static void
+md_rollback(MD_CTX* ctx, int opener_index, int closer_index, int how)
+{
+ int i;
+ int mark_index;
+
+ /* Cut all unresolved openers at the mark index. */
+ for(i = OPENERS_CHAIN_FIRST; i < OPENERS_CHAIN_LAST+1; i++) {
+ MD_MARKCHAIN* chain = &ctx->mark_chains[i];
+
+ while(chain->tail >= opener_index)
+ chain->tail = ctx->marks[chain->tail].prev;
+
+ if(chain->tail >= 0)
+ ctx->marks[chain->tail].next = -1;
+ else
+ chain->head = -1;
+ }
+
+ /* Go backwards so that un-resolved openers are re-added into their
+ * respective chains, in the right order. */
+ mark_index = closer_index - 1;
+ while(mark_index > opener_index) {
+ MD_MARK* mark = &ctx->marks[mark_index];
+ int mark_flags = mark->flags;
+ int discard_flag = (how == MD_ROLLBACK_ALL);
+
+ if(mark->flags & MD_MARK_CLOSER) {
+ int mark_opener_index = mark->prev;
+
+ /* Undo opener BEFORE the range. */
+ if(mark_opener_index < opener_index) {
+ MD_MARK* mark_opener = &ctx->marks[mark_opener_index];
+ MD_MARKCHAIN* chain;
+
+ mark_opener->flags &= ~(MD_MARK_OPENER | MD_MARK_CLOSER | MD_MARK_RESOLVED);
+ chain = md_mark_chain(ctx, opener_index);
+ if(chain != NULL) {
+ md_mark_chain_append(ctx, chain, mark_opener_index);
+ discard_flag = 1;
+ }
+ }
+ }
+
+ /* And reset our flags. */
+ if(discard_flag)
+ mark->flags &= ~(MD_MARK_OPENER | MD_MARK_CLOSER | MD_MARK_RESOLVED);
+
+ /* Jump as far as we can over unresolved or non-interesting marks. */
+ switch(how) {
+ case MD_ROLLBACK_CROSSING:
+ if((mark_flags & MD_MARK_CLOSER) && mark->prev > opener_index) {
+ /* If we are closer with opener INSIDE the range, there may
+ * not be any other crosser inside the subrange. */
+ mark_index = mark->prev;
+ break;
+ }
+ /* Pass through. */
+ default:
+ mark_index--;
+ break;
+ }
+ }
+}
+
+static void
+md_build_mark_char_map(MD_CTX* ctx)
+{
+ memset(ctx->mark_char_map, 0, sizeof(ctx->mark_char_map));
+
+ ctx->mark_char_map['\\'] = 1;
+ ctx->mark_char_map['*'] = 1;
+ ctx->mark_char_map['_'] = 1;
+ ctx->mark_char_map['`'] = 1;
+ ctx->mark_char_map['&'] = 1;
+ ctx->mark_char_map[';'] = 1;
+ ctx->mark_char_map['<'] = 1;
+ ctx->mark_char_map['>'] = 1;
+ ctx->mark_char_map['['] = 1;
+ ctx->mark_char_map['!'] = 1;
+ ctx->mark_char_map[']'] = 1;
+ ctx->mark_char_map['\0'] = 1;
+
+ if(ctx->parser.flags & MD_FLAG_STRIKETHROUGH)
+ ctx->mark_char_map['~'] = 1;
+
+ if(ctx->parser.flags & MD_FLAG_PERMISSIVEEMAILAUTOLINKS)
+ ctx->mark_char_map['@'] = 1;
+
+ if(ctx->parser.flags & MD_FLAG_PERMISSIVEURLAUTOLINKS)
+ ctx->mark_char_map[':'] = 1;
+
+ if(ctx->parser.flags & MD_FLAG_PERMISSIVEWWWAUTOLINKS)
+ ctx->mark_char_map['.'] = 1;
+
+ if(ctx->parser.flags & MD_FLAG_TABLES)
+ ctx->mark_char_map['|'] = 1;
+
+ if(ctx->parser.flags & MD_FLAG_COLLAPSEWHITESPACE) {
+ int i;
+
+ for(i = 0; i < (int) sizeof(ctx->mark_char_map); i++) {
+ if(ISWHITESPACE_(i))
+ ctx->mark_char_map[i] = 1;
+ }
+ }
+}
+
+/* We limit code span marks to lower then 32 backticks. This solves the
+ * pathologic case of too many openers, each of different length: Their
+ * resolving would be then O(n^2). */
+#define CODESPAN_MARK_MAXLEN 32
+
+static int
+md_is_code_span(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg,
+ OFF* p_opener_beg, OFF* p_opener_end,
+ OFF* p_closer_beg, OFF* p_closer_end,
+ OFF last_potential_closers[CODESPAN_MARK_MAXLEN],
+ int* p_reached_paragraph_end)
+{
+ OFF opener_beg = beg;
+ OFF opener_end;
+ OFF closer_beg;
+ OFF closer_end;
+ SZ mark_len;
+ OFF line_end;
+ int has_space_after_opener = FALSE;
+ int has_eol_after_opener = FALSE;
+ int has_space_before_closer = FALSE;
+ int has_eol_before_closer = FALSE;
+ int has_only_space = TRUE;
+ int line_index = 0;
+
+ line_end = lines[0].end;
+ opener_end = opener_beg;
+ while(opener_end < line_end && CH(opener_end) == _T('`'))
+ opener_end++;
+ has_space_after_opener = (opener_end < line_end && CH(opener_end) == _T(' '));
+ has_eol_after_opener = (opener_end == line_end);
+
+ /* The caller needs to know end of the opening mark even if we fail. */
+ *p_opener_end = opener_end;
+
+ mark_len = opener_end - opener_beg;
+ if(mark_len > CODESPAN_MARK_MAXLEN)
+ return FALSE;
+
+ /* Check whether we already know there is no closer of this length.
+ * If so, re-scan does no sense. This fixes issue #59. */
+ if(last_potential_closers[mark_len-1] >= lines[n_lines-1].end ||
+ (*p_reached_paragraph_end && last_potential_closers[mark_len-1] < opener_end))
+ return FALSE;
+
+ closer_beg = opener_end;
+ closer_end = opener_end;
+
+ /* Find closer mark. */
+ while(TRUE) {
+ while(closer_beg < line_end && CH(closer_beg) != _T('`')) {
+ if(CH(closer_beg) != _T(' '))
+ has_only_space = FALSE;
+ closer_beg++;
+ }
+ closer_end = closer_beg;
+ while(closer_end < line_end && CH(closer_end) == _T('`'))
+ closer_end++;
+
+ if(closer_end - closer_beg == mark_len) {
+ /* Success. */
+ has_space_before_closer = (closer_beg > lines[line_index].beg && CH(closer_beg-1) == _T(' '));
+ has_eol_before_closer = (closer_beg == lines[line_index].beg);
+ break;
+ }
+
+ if(closer_end - closer_beg > 0) {
+ /* We have found a back-tick which is not part of the closer. */
+ has_only_space = FALSE;
+
+ /* But if we eventually fail, remember it as a potential closer
+ * of its own length for future attempts. This mitigates needs for
+ * rescans. */
+ if(closer_end - closer_beg < CODESPAN_MARK_MAXLEN) {
+ if(closer_beg > last_potential_closers[closer_end - closer_beg - 1])
+ last_potential_closers[closer_end - closer_beg - 1] = closer_beg;
+ }
+ }
+
+ if(closer_end >= line_end) {
+ line_index++;
+ if(line_index >= n_lines) {
+ /* Reached end of the paragraph and still nothing. */
+ *p_reached_paragraph_end = TRUE;
+ return FALSE;
+ }
+ /* Try on the next line. */
+ line_end = lines[line_index].end;
+ closer_beg = lines[line_index].beg;
+ } else {
+ closer_beg = closer_end;
+ }
+ }
+
+ /* If there is a space or a new line both after and before the opener
+ * (and if the code span is not made of spaces only), consume one initial
+ * and one trailing space as part of the marks. */
+ if(!has_only_space &&
+ (has_space_after_opener || has_eol_after_opener) &&
+ (has_space_before_closer || has_eol_before_closer))
+ {
+ if(has_space_after_opener)
+ opener_end++;
+ else
+ opener_end = lines[1].beg;
+
+ if(has_space_before_closer)
+ closer_beg--;
+ else {
+ closer_beg = lines[line_index-1].end;
+ /* We need to eat the preceding "\r\n" but not any line trailing
+ * spaces. */
+ while(closer_beg < ctx->size && ISBLANK(closer_beg))
+ closer_beg++;
+ }
+ }
+
+ *p_opener_beg = opener_beg;
+ *p_opener_end = opener_end;
+ *p_closer_beg = closer_beg;
+ *p_closer_end = closer_end;
+ return TRUE;
+}
+
+static int
+md_is_autolink_uri(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end)
+{
+ OFF off = beg+1;
+
+ MD_ASSERT(CH(beg) == _T('<'));
+
+ /* Check for scheme. */
+ if(off >= max_end || !ISASCII(off))
+ return FALSE;
+ off++;
+ while(1) {
+ if(off >= max_end)
+ return FALSE;
+ if(off - beg > 32)
+ return FALSE;
+ if(CH(off) == _T(':') && off - beg >= 3)
+ break;
+ if(!ISALNUM(off) && CH(off) != _T('+') && CH(off) != _T('-') && CH(off) != _T('.'))
+ return FALSE;
+ off++;
+ }
+
+ /* Check the path after the scheme. */
+ while(off < max_end && CH(off) != _T('>')) {
+ if(ISWHITESPACE(off) || ISCNTRL(off) || CH(off) == _T('<'))
+ return FALSE;
+ off++;
+ }
+
+ if(off >= max_end)
+ return FALSE;
+
+ MD_ASSERT(CH(off) == _T('>'));
+ *p_end = off+1;
+ return TRUE;
+}
+
+static int
+md_is_autolink_email(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end)
+{
+ OFF off = beg + 1;
+ int label_len;
+
+ MD_ASSERT(CH(beg) == _T('<'));
+
+ /* The code should correspond to this regexp:
+ /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+
+ @[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
+ (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
+ */
+
+ /* Username (before '@'). */
+ while(off < max_end && (ISALNUM(off) || ISANYOF(off, _T(".!#$%&'*+/=?^_`{|}~-"))))
+ off++;
+ if(off <= beg+1)
+ return FALSE;
+
+ /* '@' */
+ if(off >= max_end || CH(off) != _T('@'))
+ return FALSE;
+ off++;
+
+ /* Labels delimited with '.'; each label is sequence of 1 - 62 alnum
+ * characters or '-', but '-' is not allowed as first or last char. */
+ label_len = 0;
+ while(off < max_end) {
+ if(ISALNUM(off))
+ label_len++;
+ else if(CH(off) == _T('-') && label_len > 0)
+ label_len++;
+ else if(CH(off) == _T('.') && label_len > 0 && CH(off-1) != _T('-'))
+ label_len = 0;
+ else
+ break;
+
+ if(label_len > 62)
+ return FALSE;
+
+ off++;
+ }
+
+ if(label_len <= 0 || off >= max_end || CH(off) != _T('>') || CH(off-1) == _T('-'))
+ return FALSE;
+
+ *p_end = off+1;
+ return TRUE;
+}
+
+static int
+md_is_autolink(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, int* p_missing_mailto)
+{
+ if(md_is_autolink_uri(ctx, beg, max_end, p_end)) {
+ *p_missing_mailto = FALSE;
+ return TRUE;
+ }
+
+ if(md_is_autolink_email(ctx, beg, max_end, p_end)) {
+ *p_missing_mailto = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int
+md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode)
+{
+ int i;
+ int ret = 0;
+ MD_MARK* mark;
+ OFF codespan_last_potential_closers[CODESPAN_MARK_MAXLEN] = { 0 };
+ int codespan_scanned_till_paragraph_end = FALSE;
+
+ for(i = 0; i < n_lines; i++) {
+ const MD_LINE* line = &lines[i];
+ OFF off = line->beg;
+ OFF line_end = line->end;
+
+ while(TRUE) {
+ CHAR ch;
+
+#ifdef MD4C_USE_UTF16
+ /* For UTF-16, mark_char_map[] covers only ASCII. */
+ #define IS_MARK_CHAR(off) ((CH(off) < SIZEOF_ARRAY(ctx->mark_char_map)) && \
+ (ctx->mark_char_map[(unsigned char) CH(off)]))
+#else
+ /* For 8-bit encodings, mark_char_map[] covers all 256 elements. */
+ #define IS_MARK_CHAR(off) (ctx->mark_char_map[(unsigned char) CH(off)])
+#endif
+
+ /* Optimization: Use some loop unrolling. */
+ while(off + 3 < line_end && !IS_MARK_CHAR(off+0) && !IS_MARK_CHAR(off+1)
+ && !IS_MARK_CHAR(off+2) && !IS_MARK_CHAR(off+3))
+ off += 4;
+ while(off < line_end && !IS_MARK_CHAR(off+0))
+ off++;
+
+ if(off >= line_end)
+ break;
+
+ ch = CH(off);
+
+ /* A backslash escape.
+ * It can go beyond line->end as it may involve escaped new
+ * line to form a hard break. */
+ if(ch == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) {
+ /* Hard-break cannot be on the last line of the block. */
+ if(!ISNEWLINE(off+1) || i+1 < n_lines)
+ PUSH_MARK(ch, off, off+2, MD_MARK_RESOLVED);
+ off += 2;
+ continue;
+ }
+
+ /* A potential (string) emphasis start/end. */
+ if(ch == _T('*') || ch == _T('_')) {
+ OFF tmp = off+1;
+ int left_level; /* What precedes: 0 = whitespace; 1 = punctuation; 2 = other char. */
+ int right_level; /* What follows: 0 = whitespace; 1 = punctuation; 2 = other char. */
+
+ while(tmp < line_end && CH(tmp) == ch)
+ tmp++;
+
+ if(off == line->beg || ISUNICODEWHITESPACEBEFORE(off))
+ left_level = 0;
+ else if(ISUNICODEPUNCTBEFORE(off))
+ left_level = 1;
+ else
+ left_level = 2;
+
+ if(tmp == line_end || ISUNICODEWHITESPACE(tmp))
+ right_level = 0;
+ else if(ISUNICODEPUNCT(tmp))
+ right_level = 1;
+ else
+ right_level = 2;
+
+ /* Intra-word underscore doesn't have special meaning. */
+ if(ch == _T('_') && left_level == 2 && right_level == 2) {
+ left_level = 0;
+ right_level = 0;
+ }
+
+ if(left_level != 0 || right_level != 0) {
+ unsigned flags = 0;
+
+ if(left_level > 0 && left_level >= right_level)
+ flags |= MD_MARK_POTENTIAL_CLOSER;
+ if(right_level > 0 && right_level >= left_level)
+ flags |= MD_MARK_POTENTIAL_OPENER;
+ if(left_level == 2 && right_level == 2)
+ flags |= MD_MARK_EMPH_INTRAWORD;
+
+ /* For "the rule of three" we need to remember the original
+ * size of the mark (modulo three), before we potentially
+ * split the mark when being later resolved partially by some
+ * shorter closer. */
+ switch((tmp - off) % 3) {
+ case 0: flags |= MD_MARK_EMPH_MOD3_0; break;
+ case 1: flags |= MD_MARK_EMPH_MOD3_1; break;
+ case 2: flags |= MD_MARK_EMPH_MOD3_2; break;
+ }
+
+ PUSH_MARK(ch, off, tmp, flags);
+
+ /* During resolving, multiple asterisks may have to be
+ * split into independent span start/ends. Consider e.g.
+ * "**foo* bar*". Therefore we push also some empty dummy
+ * marks to have enough space for that. */
+ off++;
+ while(off < tmp) {
+ PUSH_MARK('D', off, off, 0);
+ off++;
+ }
+ continue;
+ }
+
+ off = tmp;
+ continue;
+ }
+
+ /* A potential code span start/end. */
+ if(ch == _T('`')) {
+ OFF opener_beg, opener_end;
+ OFF closer_beg, closer_end;
+ int is_code_span;
+
+ is_code_span = md_is_code_span(ctx, lines + i, n_lines - i, off,
+ &opener_beg, &opener_end, &closer_beg, &closer_end,
+ codespan_last_potential_closers,
+ &codespan_scanned_till_paragraph_end);
+ if(is_code_span) {
+ PUSH_MARK(_T('`'), opener_beg, opener_end, MD_MARK_OPENER | MD_MARK_RESOLVED);
+ PUSH_MARK(_T('`'), closer_beg, closer_end, MD_MARK_CLOSER | MD_MARK_RESOLVED);
+ ctx->marks[ctx->n_marks-2].next = ctx->n_marks-1;
+ ctx->marks[ctx->n_marks-1].prev = ctx->n_marks-2;
+
+ off = closer_end;
+
+ /* Advance the current line accordingly. */
+ while(off > line_end) {
+ i++;
+ line++;
+ line_end = line->end;
+ }
+ continue;
+ }
+
+ off = opener_end;
+ continue;
+ }
+
+ /* A potential entity start. */
+ if(ch == _T('&')) {
+ PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_OPENER);
+ off++;
+ continue;
+ }
+
+ /* A potential entity end. */
+ if(ch == _T(';')) {
+ /* We surely cannot be entity unless the previous mark is '&'. */
+ if(ctx->n_marks > 0 && ctx->marks[ctx->n_marks-1].ch == _T('&'))
+ PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_CLOSER);
+
+ off++;
+ continue;
+ }
+
+ /* A potential autolink or raw HTML start/end. */
+ if(ch == _T('<')) {
+ int is_autolink;
+ OFF autolink_end;
+ int missing_mailto;
+
+ if(!(ctx->parser.flags & MD_FLAG_NOHTMLSPANS)) {
+ int is_html;
+ OFF html_end;
+
+ /* Given the nature of the raw HTML, we have to recognize
+ * it here. Doing so later in md_analyze_lt_gt() could
+ * open can of worms of quadratic complexity. */
+ is_html = md_is_html_any(ctx, lines + i, n_lines - i, off,
+ lines[n_lines-1].end, &html_end);
+ if(is_html) {
+ PUSH_MARK(_T('<'), off, off, MD_MARK_OPENER | MD_MARK_RESOLVED);
+ PUSH_MARK(_T('>'), html_end, html_end, MD_MARK_CLOSER | MD_MARK_RESOLVED);
+ ctx->marks[ctx->n_marks-2].next = ctx->n_marks-1;
+ ctx->marks[ctx->n_marks-1].prev = ctx->n_marks-2;
+ off = html_end;
+
+ /* Advance the current line accordingly. */
+ while(off > line_end) {
+ i++;
+ line++;
+ line_end = line->end;
+ }
+ continue;
+ }
+ }
+
+ is_autolink = md_is_autolink(ctx, off, lines[n_lines-1].end,
+ &autolink_end, &missing_mailto);
+ if(is_autolink) {
+ PUSH_MARK((missing_mailto ? _T('@') : _T('<')), off, off+1,
+ MD_MARK_OPENER | MD_MARK_RESOLVED | MD_MARK_AUTOLINK);
+ PUSH_MARK(_T('>'), autolink_end-1, autolink_end,
+ MD_MARK_CLOSER | MD_MARK_RESOLVED | MD_MARK_AUTOLINK);
+ ctx->marks[ctx->n_marks-2].next = ctx->n_marks-1;
+ ctx->marks[ctx->n_marks-1].prev = ctx->n_marks-2;
+ off = autolink_end;
+ continue;
+ }
+
+ off++;
+ continue;
+ }
+
+ /* A potential link or its part. */
+ if(ch == _T('[') || (ch == _T('!') && off+1 < line_end && CH(off+1) == _T('['))) {
+ OFF tmp = (ch == _T('[') ? off+1 : off+2);
+ PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER);
+ off = tmp;
+ /* Two dummies to make enough place for data we need if it is
+ * a link. */
+ PUSH_MARK('D', off, off, 0);
+ PUSH_MARK('D', off, off, 0);
+ continue;
+ }
+ if(ch == _T(']')) {
+ PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_CLOSER);
+ off++;
+ continue;
+ }
+
+ /* A potential permissive e-mail autolink. */
+ if(ch == _T('@')) {
+ if(line->beg + 1 <= off && ISALNUM(off-1) &&
+ off + 3 < line->end && ISALNUM(off+1))
+ {
+ PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_OPENER);
+ /* Push a dummy as a reserve for a closer. */
+ PUSH_MARK('D', off, off, 0);
+ }
+
+ off++;
+ continue;
+ }
+
+ /* A potential permissive URL autolink. */
+ if(ch == _T(':')) {
+ static struct {
+ const CHAR* scheme;
+ SZ scheme_size;
+ const CHAR* suffix;
+ SZ suffix_size;
+ } scheme_map[] = {
+ /* In the order from the most frequently used, arguably. */
+ { _T("http"), 4, _T("//"), 2 },
+ { _T("https"), 5, _T("//"), 2 },
+ { _T("ftp"), 3, _T("//"), 2 }
+ };
+ int scheme_index;
+
+ for(scheme_index = 0; scheme_index < (int) SIZEOF_ARRAY(scheme_map); scheme_index++) {
+ const CHAR* scheme = scheme_map[scheme_index].scheme;
+ const SZ scheme_size = scheme_map[scheme_index].scheme_size;
+ const CHAR* suffix = scheme_map[scheme_index].suffix;
+ const SZ suffix_size = scheme_map[scheme_index].suffix_size;
+
+ if(line->beg + scheme_size <= off && md_ascii_eq(STR(off-scheme_size), scheme, scheme_size) &&
+ (line->beg + scheme_size == off || ISWHITESPACE(off-scheme_size-1) || ISANYOF(off-scheme_size-1, _T("*_~(["))) &&
+ off + 1 + suffix_size < line->end && md_ascii_eq(STR(off+1), suffix, suffix_size))
+ {
+ PUSH_MARK(ch, off-scheme_size, off+1+suffix_size, MD_MARK_POTENTIAL_OPENER);
+ /* Push a dummy as a reserve for a closer. */
+ PUSH_MARK('D', off, off, 0);
+ off += 1 + suffix_size;
+ continue;
+ }
+ }
+
+ off++;
+ continue;
+ }
+
+ /* A potential permissive WWW autolink. */
+ if(ch == _T('.')) {
+ if(line->beg + 3 <= off && md_ascii_eq(STR(off-3), _T("www"), 3) &&
+ (line->beg + 3 == off || ISWHITESPACE(off-4) || ISANYOF(off-4, _T("*_~(["))) &&
+ off + 1 < line_end)
+ {
+ PUSH_MARK(ch, off-3, off+1, MD_MARK_POTENTIAL_OPENER);
+ /* Push a dummy as a reserve for a closer. */
+ PUSH_MARK('D', off, off, 0);
+ off++;
+ continue;
+ }
+
+ off++;
+ continue;
+ }
+
+ /* A potential table cell boundary. */
+ if(table_mode && ch == _T('|')) {
+ PUSH_MARK(ch, off, off+1, 0);
+ off++;
+ continue;
+ }
+
+ /* A potential strikethrough start/end. */
+ if(ch == _T('~')) {
+ OFF tmp = off+1;
+
+ while(tmp < line_end && CH(tmp) == _T('~'))
+ tmp++;
+
+ PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER);
+ off = tmp;
+ continue;
+ }
+
+ /* Turn non-trivial whitespace into single space. */
+ if(ISWHITESPACE_(ch)) {
+ OFF tmp = off+1;
+
+ while(tmp < line_end && ISWHITESPACE(tmp))
+ tmp++;
+
+ if(tmp - off > 1 || ch != _T(' '))
+ PUSH_MARK(ch, off, tmp, MD_MARK_RESOLVED);
+
+ off = tmp;
+ continue;
+ }
+
+ /* NULL character. */
+ if(ch == _T('\0')) {
+ PUSH_MARK(ch, off, off+1, MD_MARK_RESOLVED);
+ off++;
+ continue;
+ }
+
+ off++;
+ }
+ }
+
+ /* Add a dummy mark at the end of the mark vector to simplify
+ * process_inlines(). */
+ PUSH_MARK(127, ctx->size, ctx->size, MD_MARK_RESOLVED);
+
+abort:
+ return ret;
+}
+
+static void
+md_analyze_bracket(MD_CTX* ctx, int mark_index)
+{
+ /* We cannot really resolve links here as for that we would need
+ * more context. E.g. a following pair of brackets (reference link),
+ * or enclosing pair of brackets (if the inner is the link, the outer
+ * one cannot be.)
+ *
+ * Therefore we here only construct a list of resolved '[' ']' pairs
+ * ordered by position of the closer. This allows ur to analyze what is
+ * or is not link in the right order, from inside to outside in case
+ * of nested brackets.
+ *
+ * The resolving itself is deferred into md_resolve_links().
+ */
+
+ MD_MARK* mark = &ctx->marks[mark_index];
+
+ if(mark->flags & MD_MARK_POTENTIAL_OPENER) {
+ md_mark_chain_append(ctx, &BRACKET_OPENERS, mark_index);
+ return;
+ }
+
+ if(BRACKET_OPENERS.tail >= 0) {
+ /* Pop the opener from the chain. */
+ int opener_index = BRACKET_OPENERS.tail;
+ MD_MARK* opener = &ctx->marks[opener_index];
+ if(opener->prev >= 0)
+ ctx->marks[opener->prev].next = -1;
+ else
+ BRACKET_OPENERS.head = -1;
+ BRACKET_OPENERS.tail = opener->prev;
+
+ /* Interconnect the opener and closer. */
+ opener->next = mark_index;
+ mark->prev = opener_index;
+
+ /* Add the pair into chain of potential links for md_resolve_links().
+ * Note we misuse opener->prev for this as opener->next points to its
+ * closer. */
+ if(ctx->unresolved_link_tail >= 0)
+ ctx->marks[ctx->unresolved_link_tail].prev = opener_index;
+ else
+ ctx->unresolved_link_head = opener_index;
+ ctx->unresolved_link_tail = opener_index;
+ opener->prev = -1;
+ }
+}
+
+/* Forward declaration. */
+static void md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
+ int mark_beg, int mark_end);
+
+static int
+md_resolve_links(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
+{
+ int opener_index = ctx->unresolved_link_head;
+ OFF last_link_beg = 0;
+ OFF last_link_end = 0;
+ OFF last_img_beg = 0;
+ OFF last_img_end = 0;
+
+ while(opener_index >= 0) {
+ MD_MARK* opener = &ctx->marks[opener_index];
+ int closer_index = opener->next;
+ MD_MARK* closer = &ctx->marks[closer_index];
+ int next_index = opener->prev;
+ MD_MARK* next_opener;
+ MD_MARK* next_closer;
+ MD_LINK_ATTR attr;
+ int is_link = FALSE;
+
+ if(next_index >= 0) {
+ next_opener = &ctx->marks[next_index];
+ next_closer = &ctx->marks[next_opener->next];
+ } else {
+ next_opener = NULL;
+ next_closer = NULL;
+ }
+
+ /* If nested ("[ [ ] ]"), we need to make sure that:
+ * - The outer does not end inside of (...) belonging to the inner.
+ * - The outer cannot be link if the inner is link (i.e. not image).
+ *
+ * (Note we here analyze from inner to outer as the marks are ordered
+ * by closer->beg.)
+ */
+ if((opener->beg < last_link_beg && closer->end < last_link_end) ||
+ (opener->beg < last_img_beg && closer->end < last_img_end) ||
+ (opener->beg < last_link_end && opener->ch == '['))
+ {
+ opener_index = next_index;
+ continue;
+ }
+
+ if(next_opener != NULL && next_opener->beg == closer->end) {
+ if(next_closer->beg > closer->end + 1) {
+ /* Might be full reference link. */
+ is_link = md_is_link_reference(ctx, lines, n_lines, next_opener->beg, next_closer->end, &attr);
+ } else {
+ /* Might be shortcut reference link. */
+ is_link = md_is_link_reference(ctx, lines, n_lines, opener->beg, closer->end, &attr);
+ }
+
+ if(is_link < 0)
+ return -1;
+
+ if(is_link) {
+ /* Eat the 2nd "[...]". */
+ closer->end = next_closer->end;
+ }
+ } else {
+ if(closer->end < ctx->size && CH(closer->end) == _T('(')) {
+ /* Might be inline link. */
+ OFF inline_link_end = UINT_MAX;
+
+ is_link = md_is_inline_link_spec(ctx, lines, n_lines, closer->end, &inline_link_end, &attr);
+ if(is_link < 0)
+ return -1;
+
+ /* Check the closing ')' is not inside an already resolved range
+ * (i.e. a range with a higher priority), e.g. a code span. */
+ if(is_link) {
+ int i = closer_index + 1;
+
+ while(i < ctx->n_marks) {
+ MD_MARK* mark = &ctx->marks[i];
+
+ if(mark->beg >= inline_link_end)
+ break;
+ if((mark->flags & (MD_MARK_OPENER | MD_MARK_RESOLVED)) == (MD_MARK_OPENER | MD_MARK_RESOLVED)) {
+ if(ctx->marks[mark->next].beg >= inline_link_end) {
+ /* Cancel the link status. */
+ if(attr.title_needs_free)
+ free(attr.title);
+ is_link = FALSE;
+ break;
+ }
+
+ i = mark->next + 1;
+ } else {
+ i++;
+ }
+ }
+ }
+
+ if(is_link) {
+ /* Eat the "(...)" */
+ closer->end = inline_link_end;
+ }
+ }
+
+ if(!is_link) {
+ /* Might be collapsed reference link. */
+ is_link = md_is_link_reference(ctx, lines, n_lines, opener->beg, closer->end, &attr);
+ if(is_link < 0)
+ return -1;
+ }
+ }
+
+ if(is_link) {
+ /* Resolve the brackets as a link. */
+ opener->flags |= MD_MARK_OPENER | MD_MARK_RESOLVED;
+ closer->flags |= MD_MARK_CLOSER | MD_MARK_RESOLVED;
+
+ /* If it is a link, we store the destination and title in the two
+ * dummy marks after the opener. */
+ MD_ASSERT(ctx->marks[opener_index+1].ch == 'D');
+ ctx->marks[opener_index+1].beg = attr.dest_beg;
+ ctx->marks[opener_index+1].end = attr.dest_end;
+
+ MD_ASSERT(ctx->marks[opener_index+2].ch == 'D');
+ md_mark_store_ptr(ctx, opener_index+2, attr.title);
+ if(attr.title_needs_free)
+ md_mark_chain_append(ctx, &PTR_CHAIN, opener_index+2);
+ ctx->marks[opener_index+2].prev = attr.title_size;
+
+ if(opener->ch == '[') {
+ last_link_beg = opener->beg;
+ last_link_end = closer->end;
+ } else {
+ last_img_beg = opener->beg;
+ last_img_end = closer->end;
+ }
+
+ md_analyze_link_contents(ctx, lines, n_lines, opener_index+1, closer_index);
+ }
+
+ opener_index = next_index;
+ }
+
+ return 0;
+}
+
+/* Analyze whether the mark '&' starts a HTML entity.
+ * If so, update its flags as well as flags of corresponding closer ';'. */
+static void
+md_analyze_entity(MD_CTX* ctx, int mark_index)
+{
+ MD_MARK* opener = &ctx->marks[mark_index];
+ MD_MARK* closer;
+ OFF off;
+
+ /* Cannot be entity if there is no closer as the next mark.
+ * (Any other mark between would mean strange character which cannot be
+ * part of the entity.
+ *
+ * So we can do all the work on '&' and do not call this later for the
+ * closing mark ';'.
+ */
+ if(mark_index + 1 >= ctx->n_marks)
+ return;
+ closer = &ctx->marks[mark_index+1];
+ if(closer->ch != ';')
+ return;
+
+ if(md_is_entity(ctx, opener->beg, closer->end, &off)) {
+ MD_ASSERT(off == closer->end);
+
+ md_resolve_range(ctx, NULL, mark_index, mark_index+1);
+ opener->end = closer->end;
+ }
+}
+
+static void
+md_analyze_table_cell_boundary(MD_CTX* ctx, int mark_index)
+{
+ MD_MARK* mark = &ctx->marks[mark_index];
+ mark->flags |= MD_MARK_RESOLVED;
+
+ md_mark_chain_append(ctx, &TABLECELLBOUNDARIES, mark_index);
+ ctx->n_table_cell_boundaries++;
+}
+
+/* Split a longer mark into two. The new mark takes the given count of
+ * characters. May only be called if an adequate number of dummy 'D' marks
+ * follows.
+ */
+static int
+md_split_emph_mark(MD_CTX* ctx, int mark_index, SZ n)
+{
+ MD_MARK* mark = &ctx->marks[mark_index];
+ int new_mark_index = mark_index + (mark->end - mark->beg - n);
+ MD_MARK* dummy = &ctx->marks[new_mark_index];
+
+ MD_ASSERT(mark->end - mark->beg > n);
+ MD_ASSERT(dummy->ch == 'D');
+
+ memcpy(dummy, mark, sizeof(MD_MARK));
+ mark->end -= n;
+ dummy->beg = mark->end;
+
+ return new_mark_index;
+}
+
+static void
+md_analyze_emph(MD_CTX* ctx, int mark_index)
+{
+ MD_MARK* mark = &ctx->marks[mark_index];
+ MD_MARKCHAIN* chain = md_mark_chain(ctx, mark_index);
+
+ /* If we can be a closer, try to resolve with the preceding opener. */
+ if(mark->flags & MD_MARK_POTENTIAL_CLOSER) {
+ MD_MARK* opener = NULL;
+ int opener_index;
+
+ if(mark->ch == _T('*')) {
+ MD_MARKCHAIN* opener_chains[6];
+ int i, n_opener_chains;
+ unsigned flags = mark->flags;
+
+ /* Apply "rule of three". (This is why we break asterisk opener
+ * marks into multiple chains.) */
+ n_opener_chains = 0;
+ opener_chains[n_opener_chains++] = &ASTERISK_OPENERS_intraword_mod3_0;
+ if((flags & MD_MARK_EMPH_MOD3_MASK) != MD_MARK_EMPH_MOD3_2)
+ opener_chains[n_opener_chains++] = &ASTERISK_OPENERS_intraword_mod3_1;
+ if((flags & MD_MARK_EMPH_MOD3_MASK) != MD_MARK_EMPH_MOD3_1)
+ opener_chains[n_opener_chains++] = &ASTERISK_OPENERS_intraword_mod3_2;
+ opener_chains[n_opener_chains++] = &ASTERISK_OPENERS_extraword_mod3_0;
+ if(!(flags & MD_MARK_EMPH_INTRAWORD) || (flags & MD_MARK_EMPH_MOD3_MASK) != MD_MARK_EMPH_MOD3_2)
+ opener_chains[n_opener_chains++] = &ASTERISK_OPENERS_extraword_mod3_1;
+ if(!(flags & MD_MARK_EMPH_INTRAWORD) || (flags & MD_MARK_EMPH_MOD3_MASK) != MD_MARK_EMPH_MOD3_1)
+ opener_chains[n_opener_chains++] = &ASTERISK_OPENERS_extraword_mod3_2;
+
+ /* Opener is the most recent mark from the allowed chains. */
+ for(i = 0; i < n_opener_chains; i++) {
+ if(opener_chains[i]->tail >= 0) {
+ int tmp_index = opener_chains[i]->tail;
+ MD_MARK* tmp_mark = &ctx->marks[tmp_index];
+ if(opener == NULL || tmp_mark->end > opener->end) {
+ opener_index = tmp_index;
+ opener = tmp_mark;
+ }
+ }
+ }
+ } else {
+ /* Simple emph. mark */
+ if(chain->tail >= 0) {
+ opener_index = chain->tail;
+ opener = &ctx->marks[opener_index];
+ }
+ }
+
+ /* Resolve, if we have found matching opener. */
+ if(opener != NULL) {
+ SZ opener_size = opener->end - opener->beg;
+ SZ closer_size = mark->end - mark->beg;
+
+ if(opener_size > closer_size) {
+ opener_index = md_split_emph_mark(ctx, opener_index, closer_size);
+ md_mark_chain_append(ctx, md_mark_chain(ctx, opener_index), opener_index);
+ } else if(opener_size < closer_size) {
+ md_split_emph_mark(ctx, mark_index, closer_size - opener_size);
+ }
+
+ md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_CROSSING);
+ md_resolve_range(ctx, chain, opener_index, mark_index);
+ return;
+ }
+ }
+
+ /* If we could not resolve as closer, we may be yet be an opener. */
+ if(mark->flags & MD_MARK_POTENTIAL_OPENER)
+ md_mark_chain_append(ctx, chain, mark_index);
+}
+
+static void
+md_analyze_tilde(MD_CTX* ctx, int mark_index)
+{
+ /* We attempt to be Github Flavored Markdown compatible here. GFM says
+ * that length of the tilde sequence is not important at all. Note that
+ * implies the TILDE_OPENERS chain can have at most one item. */
+
+ if(TILDE_OPENERS.head >= 0) {
+ /* The chain already contains an opener, so we may resolve the span. */
+ int opener_index = TILDE_OPENERS.head;
+
+ md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_CROSSING);
+ md_resolve_range(ctx, &TILDE_OPENERS, opener_index, mark_index);
+ } else {
+ /* We can only be opener. */
+ md_mark_chain_append(ctx, &TILDE_OPENERS, mark_index);
+ }
+}
+
+static void
+md_analyze_permissive_url_autolink(MD_CTX* ctx, int mark_index)
+{
+ MD_MARK* opener = &ctx->marks[mark_index];
+ int closer_index = mark_index + 1;
+ MD_MARK* closer = &ctx->marks[closer_index];
+ MD_MARK* next_resolved_mark;
+ OFF off = opener->end;
+ int n_dots = FALSE;
+ int has_underscore_in_last_seg = FALSE;
+ int has_underscore_in_next_to_last_seg = FALSE;
+ int n_opened_parenthesis = 0;
+
+ /* Check for domain. */
+ while(off < ctx->size) {
+ if(ISALNUM(off) || CH(off) == _T('-')) {
+ off++;
+ } else if(CH(off) == _T('.')) {
+ /* We must see at least one period. */
+ n_dots++;
+ has_underscore_in_next_to_last_seg = has_underscore_in_last_seg;
+ has_underscore_in_last_seg = FALSE;
+ off++;
+ } else if(CH(off) == _T('_')) {
+ /* No underscore may be present in the last two domain segments. */
+ has_underscore_in_last_seg = TRUE;
+ off++;
+ } else {
+ break;
+ }
+ }
+ if(off > opener->end && CH(off-1) == _T('.')) {
+ off--;
+ n_dots--;
+ }
+ if(off <= opener->end || n_dots == 0 || has_underscore_in_next_to_last_seg || has_underscore_in_last_seg)
+ return;
+
+ /* Check for path. */
+ next_resolved_mark = closer + 1;
+ while(next_resolved_mark->ch == 'D' || !(next_resolved_mark->flags & MD_MARK_RESOLVED))
+ next_resolved_mark++;
+ while(off < next_resolved_mark->beg && CH(off) != _T('<') && !ISWHITESPACE(off) && !ISNEWLINE(off)) {
+ /* Parenthesis must be balanced. */
+ if(CH(off) == _T('(')) {
+ n_opened_parenthesis++;
+ } else if(CH(off) == _T(')')) {
+ if(n_opened_parenthesis > 0)
+ n_opened_parenthesis--;
+ else
+ break;
+ }
+
+ off++;
+ }
+ /* These cannot be last char In such case they are more likely normal
+ * punctuation. */
+ if(ISANYOF(off-1, _T("?!.,:*_~")))
+ off--;
+
+ /* Ok. Lets call it auto-link. Adapt opener and create closer to zero
+ * length so all the contents becomes the link text. */
+ MD_ASSERT(closer->ch == 'D');
+ opener->end = opener->beg;
+ closer->ch = opener->ch;
+ closer->beg = off;
+ closer->end = off;
+ md_resolve_range(ctx, NULL, mark_index, closer_index);
+}
+
+/* The permissive autolinks do not have to be enclosed in '<' '>' but we
+ * instead impose stricter rules what is understood as an e-mail address
+ * here. Actually any non-alphanumeric characters with exception of '.'
+ * are prohibited both in username and after '@'. */
+static void
+md_analyze_permissive_email_autolink(MD_CTX* ctx, int mark_index)
+{
+ MD_MARK* opener = &ctx->marks[mark_index];
+ int closer_index;
+ MD_MARK* closer;
+ OFF beg = opener->beg;
+ OFF end = opener->end;
+ int dot_count = 0;
+
+ MD_ASSERT(CH(beg) == _T('@'));
+
+ /* Scan for name before '@'. */
+ while(beg > 0 && (ISALNUM(beg-1) || ISANYOF(beg-1, _T(".-_+"))))
+ beg--;
+
+ /* Scan for domain after '@'. */
+ while(end < ctx->size && (ISALNUM(end) || ISANYOF(end, _T(".-_")))) {
+ if(CH(end) == _T('.'))
+ dot_count++;
+ end++;
+ }
+ if(CH(end-1) == _T('.')) { /* Final '.' not part of it. */
+ dot_count--;
+ end--;
+ }
+ else if(ISANYOF2(end-1, _T('-'), _T('_'))) /* These are forbidden at the end. */
+ return;
+ if(CH(end-1) == _T('@') || dot_count == 0)
+ return;
+
+ /* Ok. Lets call it auto-link. Adapt opener and create closer to zero
+ * length so all the contents becomes the link text. */
+ closer_index = mark_index + 1;
+ closer = &ctx->marks[closer_index];
+ MD_ASSERT(closer->ch == 'D');
+
+ opener->beg = beg;
+ opener->end = beg;
+ closer->ch = opener->ch;
+ closer->beg = end;
+ closer->end = end;
+ md_resolve_range(ctx, NULL, mark_index, closer_index);
+}
+
+static inline void
+md_analyze_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
+ int mark_beg, int mark_end, const CHAR* mark_chars)
+{
+ int i = mark_beg;
+
+ while(i < mark_end) {
+ MD_MARK* mark = &ctx->marks[i];
+
+ /* Skip resolved spans. */
+ if(mark->flags & MD_MARK_RESOLVED) {
+ if(mark->flags & MD_MARK_OPENER) {
+ MD_ASSERT(i < mark->next);
+ i = mark->next + 1;
+ } else {
+ i++;
+ }
+ continue;
+ }
+
+ /* Skip marks we do not want to deal with. */
+ if(!ISANYOF_(mark->ch, mark_chars)) {
+ i++;
+ continue;
+ }
+
+ /* Analyze the mark. */
+ switch(mark->ch) {
+ case '[': /* Pass through. */
+ case '!': /* Pass through. */
+ case ']': md_analyze_bracket(ctx, i); break;
+ case '&': md_analyze_entity(ctx, i); break;
+ case '|': md_analyze_table_cell_boundary(ctx, i); break;
+ case '_': /* Pass through. */
+ case '*': md_analyze_emph(ctx, i); break;
+ case '~': md_analyze_tilde(ctx, i); break;
+ case '.': /* Pass through. */
+ case ':': md_analyze_permissive_url_autolink(ctx, i); break;
+ case '@': md_analyze_permissive_email_autolink(ctx, i); break;
+ }
+
+ i++;
+ }
+}
+
+/* Analyze marks (build ctx->marks). */
+static int
+md_analyze_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode)
+{
+ int ret;
+
+ /* Reset the previously collected stack of marks. */
+ ctx->n_marks = 0;
+
+ /* Collect all marks. */
+ MD_CHECK(md_collect_marks(ctx, lines, n_lines, table_mode));
+
+ /* We analyze marks in few groups to handle their precedence. */
+ /* (1) Entities; code spans; autolinks; raw HTML. */
+ md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("&"));
+
+ if(table_mode) {
+ /* (2) Analyze table cell boundaries.
+ * Note we reset TABLECELLBOUNDARIES chain prior to the call md_analyze_marks(),
+ * not after, because caller may need it. */
+ MD_ASSERT(n_lines == 1);
+ TABLECELLBOUNDARIES.head = -1;
+ TABLECELLBOUNDARIES.tail = -1;
+ ctx->n_table_cell_boundaries = 0;
+ md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("|"));
+ return ret;
+ }
+
+ /* (3) Links. */
+ md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("[]!"));
+ MD_CHECK(md_resolve_links(ctx, lines, n_lines));
+ BRACKET_OPENERS.head = -1;
+ BRACKET_OPENERS.tail = -1;
+ ctx->unresolved_link_head = -1;
+ ctx->unresolved_link_tail = -1;
+
+ /* (4) Emphasis and strong emphasis; permissive autolinks. */
+ md_analyze_link_contents(ctx, lines, n_lines, 0, ctx->n_marks);
+
+abort:
+ return ret;
+}
+
+static void
+md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
+ int mark_beg, int mark_end)
+{
+ md_analyze_marks(ctx, lines, n_lines, mark_beg, mark_end, _T("*_~@:."));
+ ASTERISK_OPENERS_extraword_mod3_0.head = -1;
+ ASTERISK_OPENERS_extraword_mod3_0.tail = -1;
+ ASTERISK_OPENERS_extraword_mod3_1.head = -1;
+ ASTERISK_OPENERS_extraword_mod3_1.tail = -1;
+ ASTERISK_OPENERS_extraword_mod3_2.head = -1;
+ ASTERISK_OPENERS_extraword_mod3_2.tail = -1;
+ ASTERISK_OPENERS_intraword_mod3_0.head = -1;
+ ASTERISK_OPENERS_intraword_mod3_0.tail = -1;
+ ASTERISK_OPENERS_intraword_mod3_1.head = -1;
+ ASTERISK_OPENERS_intraword_mod3_1.tail = -1;
+ ASTERISK_OPENERS_intraword_mod3_2.head = -1;
+ ASTERISK_OPENERS_intraword_mod3_2.tail = -1;
+ UNDERSCORE_OPENERS.head = -1;
+ UNDERSCORE_OPENERS.tail = -1;
+ TILDE_OPENERS.head = -1;
+ TILDE_OPENERS.tail = -1;
+}
+
+static int
+md_enter_leave_span_a(MD_CTX* ctx, int enter, MD_SPANTYPE type,
+ const CHAR* dest, SZ dest_size, int prohibit_escapes_in_dest,
+ const CHAR* title, SZ title_size)
+{
+ MD_ATTRIBUTE_BUILD href_build = { 0 };
+ MD_ATTRIBUTE_BUILD title_build = { 0 };
+ MD_SPAN_A_DETAIL det;
+ int ret = 0;
+
+ /* Note we here rely on fact that MD_SPAN_A_DETAIL and
+ * MD_SPAN_IMG_DETAIL are binary-compatible. */
+ memset(&det, 0, sizeof(MD_SPAN_A_DETAIL));
+ MD_CHECK(md_build_attribute(ctx, dest, dest_size,
+ (prohibit_escapes_in_dest ? MD_BUILD_ATTR_NO_ESCAPES : 0),
+ &det.href, &href_build));
+ MD_CHECK(md_build_attribute(ctx, title, title_size, 0, &det.title, &title_build));
+
+ if(enter)
+ MD_ENTER_SPAN(type, &det);
+ else
+ MD_LEAVE_SPAN(type, &det);
+
+abort:
+ md_free_attribute(ctx, &href_build);
+ md_free_attribute(ctx, &title_build);
+ return ret;
+}
+
+/* Render the output, accordingly to the analyzed ctx->marks. */
+static int
+md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
+{
+ MD_TEXTTYPE text_type;
+ const MD_LINE* line = lines;
+ MD_MARK* prev_mark = NULL;
+ MD_MARK* mark;
+ OFF off = lines[0].beg;
+ OFF end = lines[n_lines-1].end;
+ int enforce_hardbreak = 0;
+ int ret = 0;
+
+ /* Find first resolved mark. Note there is always at least one resolved
+ * mark, the dummy last one after the end of the latest line we actually
+ * never really reach. This saves us of a lot of special checks and cases
+ * in this function. */
+ mark = ctx->marks;
+ while(!(mark->flags & MD_MARK_RESOLVED))
+ mark++;
+
+ text_type = MD_TEXT_NORMAL;
+
+ while(1) {
+ /* Process the text up to the next mark or end-of-line. */
+ OFF tmp = (line->end < mark->beg ? line->end : mark->beg);
+ if(tmp > off) {
+ MD_TEXT(text_type, STR(off), tmp - off);
+ off = tmp;
+ }
+
+ /* If reached the mark, process it and move to next one. */
+ if(off >= mark->beg) {
+ switch(mark->ch) {
+ case '\\': /* Backslash escape. */
+ if(ISNEWLINE(mark->beg+1))
+ enforce_hardbreak = 1;
+ else
+ MD_TEXT(text_type, STR(mark->beg+1), 1);
+ break;
+
+ case ' ': /* Non-trivial space. */
+ MD_TEXT(text_type, _T(" "), 1);
+ break;
+
+ case '`': /* Code span. */
+ if(mark->flags & MD_MARK_OPENER) {
+ MD_ENTER_SPAN(MD_SPAN_CODE, NULL);
+ text_type = MD_TEXT_CODE;
+ } else {
+ MD_LEAVE_SPAN(MD_SPAN_CODE, NULL);
+ text_type = MD_TEXT_NORMAL;
+ }
+ break;
+
+ case '_':
+ case '*': /* Emphasis, strong emphasis. */
+ if(mark->flags & MD_MARK_OPENER) {
+ if((mark->end - off) % 2) {
+ MD_ENTER_SPAN(MD_SPAN_EM, NULL);
+ off++;
+ }
+ while(off + 1 < mark->end) {
+ MD_ENTER_SPAN(MD_SPAN_STRONG, NULL);
+ off += 2;
+ }
+ } else {
+ while(off + 1 < mark->end) {
+ MD_LEAVE_SPAN(MD_SPAN_STRONG, NULL);
+ off += 2;
+ }
+ if((mark->end - off) % 2) {
+ MD_LEAVE_SPAN(MD_SPAN_EM, NULL);
+ off++;
+ }
+ }
+ break;
+
+ case '~':
+ if(mark->flags & MD_MARK_OPENER)
+ MD_ENTER_SPAN(MD_SPAN_DEL, NULL);
+ else
+ MD_LEAVE_SPAN(MD_SPAN_DEL, NULL);
+ break;
+
+ case '[': /* Link, image. */
+ case '!':
+ case ']':
+ {
+ const MD_MARK* opener = (mark->ch != ']' ? mark : &ctx->marks[mark->prev]);
+ const MD_MARK* dest_mark = opener+1;
+ const MD_MARK* title_mark = opener+2;
+
+ MD_ASSERT(dest_mark->ch == 'D');
+ MD_ASSERT(title_mark->ch == 'D');
+
+ MD_CHECK(md_enter_leave_span_a(ctx, (mark->ch != ']'),
+ (opener->ch == '!' ? MD_SPAN_IMG : MD_SPAN_A),
+ STR(dest_mark->beg), dest_mark->end - dest_mark->beg, FALSE,
+ md_mark_get_ptr(ctx, title_mark - ctx->marks), title_mark->prev));
+
+ /* link/image closer may span multiple lines. */
+ if(mark->ch == ']') {
+ while(mark->end > line->end)
+ line++;
+ }
+
+ break;
+ }
+
+ case '<':
+ case '>': /* Autolink or raw HTML. */
+ if(!(mark->flags & MD_MARK_AUTOLINK)) {
+ /* Raw HTML. */
+ if(mark->flags & MD_MARK_OPENER)
+ text_type = MD_TEXT_HTML;
+ else
+ text_type = MD_TEXT_NORMAL;
+ break;
+ }
+ /* Pass through, if auto-link. */
+
+ case '@': /* Permissive e-mail autolink. */
+ case ':': /* Permissive URL autolink. */
+ case '.': /* Permissive WWW autolink. */
+ {
+ MD_MARK* opener = ((mark->flags & MD_MARK_OPENER) ? mark : &ctx->marks[mark->prev]);
+ MD_MARK* closer = &ctx->marks[opener->next];
+ const CHAR* dest = STR(opener->end);
+ SZ dest_size = closer->beg - opener->end;
+
+ /* For permissive auto-links we do not know closer mark
+ * position at the time of md_collect_marks(), therefore
+ * it can be out-of-order in ctx->marks[].
+ *
+ * With this flag, we make sure that we output the closer
+ * only if we processed the opener. */
+ if(mark->flags & MD_MARK_OPENER)
+ closer->flags |= MD_MARK_VALIDPERMISSIVEAUTOLINK;
+
+ if(opener->ch == '@' || opener->ch == '.') {
+ dest_size += 7;
+ MD_TEMP_BUFFER(dest_size * sizeof(CHAR));
+ memcpy(ctx->buffer,
+ (opener->ch == '@' ? _T("mailto:") : _T("http://")),
+ 7 * sizeof(CHAR));
+ memcpy(ctx->buffer + 7, dest, (dest_size-7) * sizeof(CHAR));
+ dest = ctx->buffer;
+ }
+
+ if(closer->flags & MD_MARK_VALIDPERMISSIVEAUTOLINK)
+ MD_CHECK(md_enter_leave_span_a(ctx, (mark->flags & MD_MARK_OPENER),
+ MD_SPAN_A, dest, dest_size, TRUE, NULL, 0));
+ break;
+ }
+
+ case '&': /* Entity. */
+ MD_TEXT(MD_TEXT_ENTITY, STR(mark->beg), mark->end - mark->beg);
+ break;
+
+ case '\0':
+ MD_TEXT(MD_TEXT_NULLCHAR, _T(""), 1);
+ break;
+
+ case 127:
+ goto abort;
+ }
+
+ off = mark->end;
+
+ /* Move to next resolved mark. */
+ prev_mark = mark;
+ mark++;
+ while(!(mark->flags & MD_MARK_RESOLVED) || mark->beg < off)
+ mark++;
+ }
+
+ /* If reached end of line, move to next one. */
+ if(off >= line->end) {
+ /* If it is the last line, we are done. */
+ if(off >= end)
+ break;
+
+ if(text_type == MD_TEXT_CODE) {
+ OFF tmp;
+
+ MD_ASSERT(prev_mark != NULL);
+ MD_ASSERT(prev_mark->ch == '`' && (prev_mark->flags & MD_MARK_OPENER));
+ MD_ASSERT(mark->ch == '`' && (mark->flags & MD_MARK_CLOSER));
+
+ /* Inside a code span, trailing line whitespace has to be
+ * outputted. */
+ tmp = off;
+ while(off < ctx->size && ISBLANK(off))
+ off++;
+ if(off > tmp)
+ MD_TEXT(MD_TEXT_CODE, STR(tmp), off-tmp);
+
+ /* and new lines are transformed into single spaces. */
+ if(prev_mark->end < off && off < mark->beg)
+ MD_TEXT(MD_TEXT_CODE, _T(" "), 1);
+
+ } else if(text_type == MD_TEXT_HTML) {
+ /* Inside raw HTML, we output the new line verbatim, including
+ * any trailing spaces. */
+ OFF tmp = off;
+
+ while(tmp < end && ISBLANK(tmp))
+ tmp++;
+ if(tmp > off)
+ MD_TEXT(MD_TEXT_HTML, STR(off), tmp - off);
+ MD_TEXT(MD_TEXT_HTML, _T("\n"), 1);
+ } else {
+ /* Output soft or hard line break. */
+ MD_TEXTTYPE break_type = MD_TEXT_SOFTBR;
+
+ if(text_type == MD_TEXT_NORMAL) {
+ if(enforce_hardbreak)
+ break_type = MD_TEXT_BR;
+ else if((CH(line->end) == _T(' ') && CH(line->end+1) == _T(' ')))
+ break_type = MD_TEXT_BR;
+ }
+
+ MD_TEXT(break_type, _T("\n"), 1);
+ }
+
+ /* Move to the next line. */
+ line++;
+ off = line->beg;
+
+ enforce_hardbreak = 0;
+ }
+ }
+
+abort:
+ return ret;
+}
+
+
+/***************************
+ *** Processing Tables ***
+ ***************************/
+
+static void
+md_analyze_table_alignment(MD_CTX* ctx, OFF beg, OFF end, MD_ALIGN* align, int n_align)
+{
+ static const MD_ALIGN align_map[] = { MD_ALIGN_DEFAULT, MD_ALIGN_LEFT, MD_ALIGN_RIGHT, MD_ALIGN_CENTER };
+ OFF off = beg;
+
+ while(n_align > 0) {
+ int index = 0; /* index into align_map[] */
+
+ while(CH(off) != _T('-'))
+ off++;
+ if(off > beg && CH(off-1) == _T(':'))
+ index |= 1;
+ while(off < end && CH(off) == _T('-'))
+ off++;
+ if(off < end && CH(off) == _T(':'))
+ index |= 2;
+
+ *align = align_map[index];
+ align++;
+ n_align--;
+ }
+
+}
+
+/* Forward declaration. */
+static int md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines);
+
+static int
+md_process_table_cell(MD_CTX* ctx, MD_BLOCKTYPE cell_type, MD_ALIGN align, OFF beg, OFF end)
+{
+ MD_LINE line;
+ MD_BLOCK_TD_DETAIL det;
+ int ret = 0;
+
+ while(beg < end && ISWHITESPACE(beg))
+ beg++;
+ while(end > beg && ISWHITESPACE(end-1))
+ end--;
+
+ det.align = align;
+ line.beg = beg;
+ line.end = end;
+
+ MD_ENTER_BLOCK(cell_type, &det);
+ MD_CHECK(md_process_normal_block_contents(ctx, &line, 1));
+ MD_LEAVE_BLOCK(cell_type, &det);
+
+abort:
+ return ret;
+}
+
+static int
+md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end,
+ const MD_ALIGN* align, int col_count)
+{
+ MD_LINE line;
+ OFF* pipe_offs = NULL;
+ int i, j, n;
+ int ret = 0;
+
+ line.beg = beg;
+ line.end = end;
+
+ /* Break the line into table cells by identifying pipe characters who
+ * form the cell boundary. */
+ MD_CHECK(md_analyze_inlines(ctx, &line, 1, TRUE));
+
+ /* We have to remember the cell boundaries in local buffer because
+ * ctx->marks[] shall be reused during cell contents processing. */
+ n = ctx->n_table_cell_boundaries;
+ pipe_offs = (OFF*) malloc(n * sizeof(OFF));
+ if(pipe_offs == NULL) {
+ MD_LOG("malloc() failed.");
+ ret = -1;
+ goto abort;
+ }
+ for(i = TABLECELLBOUNDARIES.head, j = 0; i >= 0; i = ctx->marks[i].next) {
+ MD_MARK* mark = &ctx->marks[i];
+ pipe_offs[j++] = mark->beg;
+ }
+
+ /* Process cells. */
+ MD_ENTER_BLOCK(MD_BLOCK_TR, NULL);
+ j = 0;
+ if(beg < pipe_offs[0] && j < col_count)
+ MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], beg, pipe_offs[0]));
+ for(i = 0; i < n-1 && j < col_count; i++)
+ MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], pipe_offs[i]+1, pipe_offs[i+1]));
+ if(pipe_offs[n-1] < end-1 && j < col_count)
+ MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], pipe_offs[n-1]+1, end));
+ /* Make sure we call enough table cells even if the current table contains
+ * too few of them. */
+ while(j < col_count)
+ MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], 0, 0));
+
+ MD_LEAVE_BLOCK(MD_BLOCK_TR, NULL);
+
+abort:
+ free(pipe_offs);
+
+ /* Free any temporary memory blocks stored within some dummy marks. */
+ for(i = PTR_CHAIN.head; i >= 0; i = ctx->marks[i].next)
+ free(md_mark_get_ptr(ctx, i));
+ PTR_CHAIN.head = -1;
+ PTR_CHAIN.tail = -1;
+
+ return ret;
+}
+
+static int
+md_process_table_block_contents(MD_CTX* ctx, int col_count, const MD_LINE* lines, int n_lines)
+{
+ MD_ALIGN* align;
+ int i;
+ int ret = 0;
+
+ /* At least two lines have to be present: The column headers and the line
+ * with the underlines. */
+ MD_ASSERT(n_lines >= 2);
+
+ align = malloc(col_count * sizeof(MD_ALIGN));
+ if(align == NULL) {
+ MD_LOG("malloc() failed.");
+ ret = -1;
+ goto abort;
+ }
+
+ md_analyze_table_alignment(ctx, lines[1].beg, lines[1].end, align, col_count);
+
+ MD_ENTER_BLOCK(MD_BLOCK_THEAD, NULL);
+ MD_CHECK(md_process_table_row(ctx, MD_BLOCK_TH,
+ lines[0].beg, lines[0].end, align, col_count));
+ MD_LEAVE_BLOCK(MD_BLOCK_THEAD, NULL);
+
+ MD_ENTER_BLOCK(MD_BLOCK_TBODY, NULL);
+ for(i = 2; i < n_lines; i++) {
+ MD_CHECK(md_process_table_row(ctx, MD_BLOCK_TD,
+ lines[i].beg, lines[i].end, align, col_count));
+ }
+ MD_LEAVE_BLOCK(MD_BLOCK_TBODY, NULL);
+
+abort:
+ free(align);
+ return ret;
+}
+
+static int
+md_is_table_row(MD_CTX* ctx, OFF beg, OFF* p_end)
+{
+ MD_LINE line;
+ int i;
+ int ret = FALSE;
+
+ line.beg = beg;
+ line.end = beg;
+
+ /* Find end of line. */
+ while(line.end < ctx->size && !ISNEWLINE(line.end))
+ line.end++;
+
+ MD_CHECK(md_analyze_inlines(ctx, &line, 1, TRUE));
+
+ if(TABLECELLBOUNDARIES.head >= 0) {
+ if(p_end != NULL)
+ *p_end = line.end;
+ ret = TRUE;
+ }
+
+abort:
+ /* Free any temporary memory blocks stored within some dummy marks. */
+ for(i = PTR_CHAIN.head; i >= 0; i = ctx->marks[i].next)
+ free(md_mark_get_ptr(ctx, i));
+ PTR_CHAIN.head = -1;
+ PTR_CHAIN.tail = -1;
+
+ return ret;
+}
+
+
+/**************************
+ *** Processing Block ***
+ **************************/
+
+#define MD_BLOCK_CONTAINER_OPENER 0x01
+#define MD_BLOCK_CONTAINER_CLOSER 0x02
+#define MD_BLOCK_CONTAINER (MD_BLOCK_CONTAINER_OPENER | MD_BLOCK_CONTAINER_CLOSER)
+#define MD_BLOCK_LOOSE_LIST 0x04
+#define MD_BLOCK_SETEXT_HEADER 0x08
+
+struct MD_BLOCK_tag {
+ MD_BLOCKTYPE type : 8;
+ unsigned flags : 8;
+
+ /* MD_BLOCK_H: Header level (1 - 6)
+ * MD_BLOCK_CODE: Non-zero if fenced, zero if indented.
+ * MD_BLOCK_LI: Task mark character (0 if not task list item, 'x', 'X' or ' ').
+ * MD_BLOCK_TABLE: Column count (as determined by the table underline).
+ */
+ unsigned data : 16;
+
+ /* Leaf blocks: Count of lines (MD_LINE or MD_VERBATIMLINE) on the block.
+ * MD_BLOCK_LI: Task mark offset in the input doc.
+ * MD_BLOCK_OL: Start item number.
+ */
+ unsigned n_lines;
+};
+
+struct MD_CONTAINER_tag {
+ CHAR ch;
+ unsigned is_loose : 8;
+ unsigned is_task : 8;
+ unsigned start;
+ unsigned mark_indent;
+ unsigned contents_indent;
+ OFF block_byte_off;
+ OFF task_mark_off;
+};
+
+
+static int
+md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
+{
+ int i;
+ int ret;
+
+ MD_CHECK(md_analyze_inlines(ctx, lines, n_lines, FALSE));
+ MD_CHECK(md_process_inlines(ctx, lines, n_lines));
+
+abort:
+ /* Free any temporary memory blocks stored within some dummy marks. */
+ for(i = PTR_CHAIN.head; i >= 0; i = ctx->marks[i].next)
+ free(md_mark_get_ptr(ctx, i));
+ PTR_CHAIN.head = -1;
+ PTR_CHAIN.tail = -1;
+
+ return ret;
+}
+
+static int
+md_process_verbatim_block_contents(MD_CTX* ctx, MD_TEXTTYPE text_type, const MD_VERBATIMLINE* lines, int n_lines)
+{
+ static const CHAR indent_chunk_str[] = _T(" ");
+ static const SZ indent_chunk_size = SIZEOF_ARRAY(indent_chunk_str) - 1;
+
+ int i;
+ int ret = 0;
+
+ for(i = 0; i < n_lines; i++) {
+ const MD_VERBATIMLINE* line = &lines[i];
+ int indent = line->indent;
+
+ MD_ASSERT(indent >= 0);
+
+ /* Output code indentation. */
+ while(indent > (int) SIZEOF_ARRAY(indent_chunk_str)) {
+ MD_TEXT(text_type, indent_chunk_str, indent_chunk_size);
+ indent -= SIZEOF_ARRAY(indent_chunk_str);
+ }
+ if(indent > 0)
+ MD_TEXT(text_type, indent_chunk_str, indent);
+
+ /* Output the code line itself. */
+ MD_TEXT_INSECURE(text_type, STR(line->beg), line->end - line->beg);
+
+ /* Enforce end-of-line. */
+ MD_TEXT(text_type, _T("\n"), 1);
+ }
+
+abort:
+ return ret;
+}
+
+static int
+md_process_code_block_contents(MD_CTX* ctx, int is_fenced, const MD_VERBATIMLINE* lines, int n_lines)
+{
+ if(is_fenced) {
+ /* Skip the first line in case of fenced code: It is the fence.
+ * (Only the starting fence is present due to logic in md_analyze_line().) */
+ lines++;
+ n_lines--;
+ } else {
+ /* Ignore blank lines at start/end of indented code block. */
+ while(n_lines > 0 && lines[0].beg == lines[0].end) {
+ lines++;
+ n_lines--;
+ }
+ while(n_lines > 0 && lines[n_lines-1].beg == lines[n_lines-1].end) {
+ n_lines--;
+ }
+ }
+
+ if(n_lines == 0)
+ return 0;
+
+ return md_process_verbatim_block_contents(ctx, MD_TEXT_CODE, lines, n_lines);
+}
+
+static int
+md_setup_fenced_code_detail(MD_CTX* ctx, const MD_BLOCK* block, MD_BLOCK_CODE_DETAIL* det,
+ MD_ATTRIBUTE_BUILD* info_build, MD_ATTRIBUTE_BUILD* lang_build)
+{
+ const MD_VERBATIMLINE* fence_line = (const MD_VERBATIMLINE*)(block + 1);
+ OFF beg = fence_line->beg;
+ OFF end = fence_line->end;
+ OFF lang_end;
+ CHAR fence_ch = CH(fence_line->beg);
+ int ret = 0;
+
+ /* Skip the fence itself. */
+ while(beg < ctx->size && CH(beg) == fence_ch)
+ beg++;
+ /* Trim initial spaces. */
+ while(beg < ctx->size && CH(beg) == _T(' '))
+ beg++;
+
+ /* Trim trailing spaces. */
+ while(end > beg && CH(end-1) == _T(' '))
+ end--;
+
+ /* Build info string attribute. */
+ MD_CHECK(md_build_attribute(ctx, STR(beg), end - beg, 0, &det->info, info_build));
+
+ /* Build info string attribute. */
+ lang_end = beg;
+ while(lang_end < end && !ISWHITESPACE(lang_end))
+ lang_end++;
+ MD_CHECK(md_build_attribute(ctx, STR(beg), lang_end - beg, 0, &det->lang, lang_build));
+
+ det->fence_char = fence_ch;
+
+abort:
+ return ret;
+}
+
+static int
+md_process_leaf_block(MD_CTX* ctx, const MD_BLOCK* block)
+{
+ union {
+ MD_BLOCK_H_DETAIL header;
+ MD_BLOCK_CODE_DETAIL code;
+ } det;
+ MD_ATTRIBUTE_BUILD info_build;
+ MD_ATTRIBUTE_BUILD lang_build;
+ int is_in_tight_list;
+ int clean_fence_code_detail = FALSE;
+ int ret = 0;
+
+ memset(&det, 0, sizeof(det));
+
+ if(ctx->n_containers == 0)
+ is_in_tight_list = FALSE;
+ else
+ is_in_tight_list = !ctx->containers[ctx->n_containers-1].is_loose;
+
+ switch(block->type) {
+ case MD_BLOCK_H:
+ det.header.level = block->data;
+ break;
+
+ case MD_BLOCK_CODE:
+ /* For fenced code block, we may need to set the info string. */
+ if(block->data != 0) {
+ memset(&det.code, 0, sizeof(MD_BLOCK_CODE_DETAIL));
+ clean_fence_code_detail = TRUE;
+ MD_CHECK(md_setup_fenced_code_detail(ctx, block, &det.code, &info_build, &lang_build));
+ }
+ break;
+
+ default:
+ /* Noop. */
+ break;
+ }
+
+ if(!is_in_tight_list || block->type != MD_BLOCK_P)
+ MD_ENTER_BLOCK(block->type, (void*) &det);
+
+ /* Process the block contents accordingly to is type. */
+ switch(block->type) {
+ case MD_BLOCK_HR:
+ /* noop */
+ break;
+
+ case MD_BLOCK_CODE:
+ MD_CHECK(md_process_code_block_contents(ctx, (block->data != 0),
+ (const MD_VERBATIMLINE*)(block + 1), block->n_lines));
+ break;
+
+ case MD_BLOCK_HTML:
+ MD_CHECK(md_process_verbatim_block_contents(ctx, MD_TEXT_HTML,
+ (const MD_VERBATIMLINE*)(block + 1), block->n_lines));
+ break;
+
+ case MD_BLOCK_TABLE:
+ MD_CHECK(md_process_table_block_contents(ctx, block->data,
+ (const MD_LINE*)(block + 1), block->n_lines));
+ break;
+
+ default:
+ MD_CHECK(md_process_normal_block_contents(ctx,
+ (const MD_LINE*)(block + 1), block->n_lines));
+ break;
+ }
+
+ if(!is_in_tight_list || block->type != MD_BLOCK_P)
+ MD_LEAVE_BLOCK(block->type, (void*) &det);
+
+abort:
+ if(clean_fence_code_detail) {
+ md_free_attribute(ctx, &info_build);
+ md_free_attribute(ctx, &lang_build);
+ }
+ return ret;
+}
+
+static int
+md_process_all_blocks(MD_CTX* ctx)
+{
+ int byte_off = 0;
+ int ret = 0;
+
+ /* ctx->containers now is not needed for detection of lists and list items
+ * so we reuse it for tracking what lists are loose or tight. We rely
+ * on the fact the vector is large enough to hold the deepest nesting
+ * level of lists. */
+ ctx->n_containers = 0;
+
+ while(byte_off < ctx->n_block_bytes) {
+ MD_BLOCK* block = (MD_BLOCK*)((char*)ctx->block_bytes + byte_off);
+ union {
+ MD_BLOCK_UL_DETAIL ul;
+ MD_BLOCK_OL_DETAIL ol;
+ MD_BLOCK_LI_DETAIL li;
+ } det;
+
+ switch(block->type) {
+ case MD_BLOCK_UL:
+ det.ul.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? FALSE : TRUE;
+ det.ul.mark = (CHAR) block->data;
+ break;
+
+ case MD_BLOCK_OL:
+ det.ol.start = block->n_lines;
+ det.ol.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? FALSE : TRUE;
+ det.ol.mark_delimiter = (CHAR) block->data;
+ break;
+
+ case MD_BLOCK_LI:
+ det.li.is_task = (block->data != 0);
+ det.li.task_mark = (CHAR) block->data;
+ det.li.task_mark_offset = (OFF) block->n_lines;
+ break;
+
+ default:
+ /* noop */
+ break;
+ }
+
+ if(block->flags & MD_BLOCK_CONTAINER) {
+ if(block->flags & MD_BLOCK_CONTAINER_CLOSER) {
+ MD_LEAVE_BLOCK(block->type, &det);
+
+ if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL || block->type == MD_BLOCK_QUOTE)
+ ctx->n_containers--;
+ }
+
+ if(block->flags & MD_BLOCK_CONTAINER_OPENER) {
+ MD_ENTER_BLOCK(block->type, &det);
+
+ if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL) {
+ ctx->containers[ctx->n_containers].is_loose = (block->flags & MD_BLOCK_LOOSE_LIST);
+ ctx->n_containers++;
+ } else if(block->type == MD_BLOCK_QUOTE) {
+ /* This causes that any text in a block quote, even if
+ * nested inside a tight list item, is wrapped with
+ * <p>...</p>. */
+ ctx->containers[ctx->n_containers].is_loose = TRUE;
+ ctx->n_containers++;
+ }
+ }
+ } else {
+ MD_CHECK(md_process_leaf_block(ctx, block));
+
+ if(block->type == MD_BLOCK_CODE || block->type == MD_BLOCK_HTML)
+ byte_off += block->n_lines * sizeof(MD_VERBATIMLINE);
+ else
+ byte_off += block->n_lines * sizeof(MD_LINE);
+ }
+
+ byte_off += sizeof(MD_BLOCK);
+ }
+
+ ctx->n_block_bytes = 0;
+
+abort:
+ return ret;
+}
+
+
+/************************************
+ *** Grouping Lines into Blocks ***
+ ************************************/
+
+static void*
+md_push_block_bytes(MD_CTX* ctx, int n_bytes)
+{
+ void* ptr;
+
+ if(ctx->n_block_bytes + n_bytes > ctx->alloc_block_bytes) {
+ void* new_block_bytes;
+
+ ctx->alloc_block_bytes = (ctx->alloc_block_bytes > 0 ? ctx->alloc_block_bytes * 2 : 512);
+ new_block_bytes = realloc(ctx->block_bytes, ctx->alloc_block_bytes);
+ if(new_block_bytes == NULL) {
+ MD_LOG("realloc() failed.");
+ return NULL;
+ }
+
+ /* Fix the ->current_block after the reallocation. */
+ if(ctx->current_block != NULL) {
+ OFF off_current_block = (char*) ctx->current_block - (char*) ctx->block_bytes;
+ ctx->current_block = (MD_BLOCK*) ((char*) new_block_bytes + off_current_block);
+ }
+
+ ctx->block_bytes = new_block_bytes;
+ }
+
+ ptr = (char*)ctx->block_bytes + ctx->n_block_bytes;
+ ctx->n_block_bytes += n_bytes;
+ return ptr;
+}
+
+static int
+md_start_new_block(MD_CTX* ctx, const MD_LINE_ANALYSIS* line)
+{
+ MD_BLOCK* block;
+
+ MD_ASSERT(ctx->current_block == NULL);
+
+ block = (MD_BLOCK*) md_push_block_bytes(ctx, sizeof(MD_BLOCK));
+ if(block == NULL)
+ return -1;
+
+ switch(line->type) {
+ case MD_LINE_HR:
+ block->type = MD_BLOCK_HR;
+ break;
+
+ case MD_LINE_ATXHEADER:
+ case MD_LINE_SETEXTHEADER:
+ block->type = MD_BLOCK_H;
+ break;
+
+ case MD_LINE_FENCEDCODE:
+ case MD_LINE_INDENTEDCODE:
+ block->type = MD_BLOCK_CODE;
+ break;
+
+ case MD_LINE_TEXT:
+ block->type = MD_BLOCK_P;
+ break;
+
+ case MD_LINE_HTML:
+ block->type = MD_BLOCK_HTML;
+ break;
+
+ case MD_LINE_BLANK:
+ case MD_LINE_SETEXTUNDERLINE:
+ case MD_LINE_TABLEUNDERLINE:
+ default:
+ MD_UNREACHABLE();
+ break;
+ }
+
+ block->flags = 0;
+ block->data = line->data;
+ block->n_lines = 0;
+
+ ctx->current_block = block;
+ return 0;
+}
+
+/* Eat from start of current (textual) block any reference definitions and
+ * remember them so we can resolve any links referring to them.
+ *
+ * (Reference definitions can only be at start of it as they cannot break
+ * a paragraph.)
+ */
+static int
+md_consume_link_reference_definitions(MD_CTX* ctx)
+{
+ MD_LINE* lines = (MD_LINE*) (ctx->current_block + 1);
+ int n_lines = ctx->current_block->n_lines;
+ int n = 0;
+
+ /* Compute how many lines at the start of the block form one or more
+ * reference definitions. */
+ while(n < n_lines) {
+ int n_link_ref_lines;
+
+ n_link_ref_lines = md_is_link_reference_definition(ctx,
+ lines + n, n_lines - n);
+ /* Not a reference definition? */
+ if(n_link_ref_lines == 0)
+ break;
+
+ /* We fail if it is the ref. def. but it could not be stored due
+ * a memory allocation error. */
+ if(n_link_ref_lines < 0)
+ return -1;
+
+ n += n_link_ref_lines;
+ }
+
+ /* If there was at least one reference definition, we need to remove
+ * its lines from the block, or perhaps even the whole block. */
+ if(n > 0) {
+ if(n == n_lines) {
+ /* Remove complete block. */
+ ctx->n_block_bytes -= n * sizeof(MD_LINE);
+ ctx->n_block_bytes -= sizeof(MD_BLOCK);
+ ctx->current_block = NULL;
+ } else {
+ /* Remove just some initial lines from the block. */
+ memmove(lines, lines + n, (n_lines - n) * sizeof(MD_LINE));
+ ctx->current_block->n_lines -= n;
+ ctx->n_block_bytes -= n * sizeof(MD_LINE);
+ }
+ }
+
+ return 0;
+}
+
+static int
+md_end_current_block(MD_CTX* ctx)
+{
+ int ret = 0;
+
+ if(ctx->current_block == NULL)
+ return ret;
+
+ /* Check whether there is a reference definition. (We do this here instead
+ * of in md_analyze_line() because reference definition can take multiple
+ * lines.) */
+ if(ctx->current_block->type == MD_BLOCK_P ||
+ (ctx->current_block->type == MD_BLOCK_H && (ctx->current_block->flags & MD_BLOCK_SETEXT_HEADER)))
+ {
+ MD_LINE* lines = (MD_LINE*) (ctx->current_block + 1);
+ if(CH(lines[0].beg) == _T('[')) {
+ MD_CHECK(md_consume_link_reference_definitions(ctx));
+ if(ctx->current_block == NULL)
+ return ret;
+ }
+ }
+
+ if(ctx->current_block->type == MD_BLOCK_H && (ctx->current_block->flags & MD_BLOCK_SETEXT_HEADER)) {
+ int n_lines = ctx->current_block->n_lines;
+
+ if(n_lines > 1) {
+ /* Get rid of the underline. */
+ ctx->current_block->n_lines--;
+ ctx->n_block_bytes -= sizeof(MD_LINE);
+ } else {
+ /* Only the underline has left after eating the ref. defs.
+ * Keep the line as beginning of a new ordinary paragraph. */
+ ctx->current_block->type = MD_BLOCK_P;
+ return 0;
+ }
+ }
+
+ /* Mark we are not building any block anymore. */
+ ctx->current_block = NULL;
+
+abort:
+ return ret;
+}
+
+static int
+md_add_line_into_current_block(MD_CTX* ctx, const MD_LINE_ANALYSIS* analysis)
+{
+ MD_ASSERT(ctx->current_block != NULL);
+
+ if(ctx->current_block->type == MD_BLOCK_CODE || ctx->current_block->type == MD_BLOCK_HTML) {
+ MD_VERBATIMLINE* line;
+
+ line = (MD_VERBATIMLINE*) md_push_block_bytes(ctx, sizeof(MD_VERBATIMLINE));
+ if(line == NULL)
+ return -1;
+
+ line->indent = analysis->indent;
+ line->beg = analysis->beg;
+ line->end = analysis->end;
+ } else {
+ MD_LINE* line;
+
+ line = (MD_LINE*) md_push_block_bytes(ctx, sizeof(MD_LINE));
+ if(line == NULL)
+ return -1;
+
+ line->beg = analysis->beg;
+ line->end = analysis->end;
+ }
+ ctx->current_block->n_lines++;
+
+ return 0;
+}
+
+static int
+md_push_container_bytes(MD_CTX* ctx, MD_BLOCKTYPE type, unsigned start,
+ unsigned data, unsigned flags)
+{
+ MD_BLOCK* block;
+ int ret = 0;
+
+ MD_CHECK(md_end_current_block(ctx));
+
+ block = (MD_BLOCK*) md_push_block_bytes(ctx, sizeof(MD_BLOCK));
+ if(block == NULL)
+ return -1;
+
+ block->type = type;
+ block->flags = flags;
+ block->data = data;
+ block->n_lines = start;
+
+abort:
+ return ret;
+}
+
+
+
+/***********************
+ *** Line Analysis ***
+ ***********************/
+
+static int
+md_is_hr_line(MD_CTX* ctx, OFF beg, OFF* p_end, OFF* p_killer)
+{
+ OFF off = beg + 1;
+ int n = 1;
+
+ while(off < ctx->size && (CH(off) == CH(beg) || CH(off) == _T(' ') || CH(off) == _T('\t'))) {
+ if(CH(off) == CH(beg))
+ n++;
+ off++;
+ }
+
+ if(n < 3) {
+ *p_killer = off;
+ return FALSE;
+ }
+
+ /* Nothing else can be present on the line. */
+ if(off < ctx->size && !ISNEWLINE(off)) {
+ *p_killer = off;
+ return FALSE;
+ }
+
+ *p_end = off;
+ return TRUE;
+}
+
+static int
+md_is_atxheader_line(MD_CTX* ctx, OFF beg, OFF* p_beg, OFF* p_end, unsigned* p_level)
+{
+ int n;
+ OFF off = beg + 1;
+
+ while(off < ctx->size && CH(off) == _T('#') && off - beg < 7)
+ off++;
+ n = off - beg;
+
+ if(n > 6)
+ return FALSE;
+ *p_level = n;
+
+ if(!(ctx->parser.flags & MD_FLAG_PERMISSIVEATXHEADERS) && off < ctx->size &&
+ CH(off) != _T(' ') && CH(off) != _T('\t') && !ISNEWLINE(off))
+ return FALSE;
+
+ while(off < ctx->size && CH(off) == _T(' '))
+ off++;
+ *p_beg = off;
+ *p_end = off;
+ return TRUE;
+}
+
+static int
+md_is_setext_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_level)
+{
+ OFF off = beg + 1;
+
+ while(off < ctx->size && CH(off) == CH(beg))
+ off++;
+
+ /* Optionally, space(s) can follow. */
+ while(off < ctx->size && CH(off) == _T(' '))
+ off++;
+
+ /* But nothing more is allowed on the line. */
+ if(off < ctx->size && !ISNEWLINE(off))
+ return FALSE;
+
+ *p_level = (CH(beg) == _T('=') ? 1 : 2);
+ *p_end = off;
+ return TRUE;
+}
+
+static int
+md_is_table_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_col_count)
+{
+ OFF off = beg;
+ int found_pipe = FALSE;
+ unsigned col_count = 0;
+
+ if(off < ctx->size && CH(off) == _T('|')) {
+ found_pipe = TRUE;
+ off++;
+ while(off < ctx->size && ISWHITESPACE(off))
+ off++;
+ }
+
+ while(1) {
+ OFF cell_beg;
+ int delimited = FALSE;
+
+ /* Cell underline ("-----", ":----", "----:" or ":----:") */
+ cell_beg = off;
+ if(off < ctx->size && CH(off) == _T(':'))
+ off++;
+ while(off < ctx->size && CH(off) == _T('-'))
+ off++;
+ if(off < ctx->size && CH(off) == _T(':'))
+ off++;
+ if(off - cell_beg < 3)
+ return FALSE;
+
+ col_count++;
+
+ /* Pipe delimiter (optional at the end of line). */
+ while(off < ctx->size && ISWHITESPACE(off))
+ off++;
+ if(off < ctx->size && CH(off) == _T('|')) {
+ delimited = TRUE;
+ found_pipe = TRUE;
+ off++;
+ while(off < ctx->size && ISWHITESPACE(off))
+ off++;
+ }
+
+ /* Success, if we reach end of line. */
+ if(off >= ctx->size || ISNEWLINE(off))
+ break;
+
+ if(!delimited)
+ return FALSE;
+ }
+
+ if(!found_pipe)
+ return FALSE;
+
+ *p_end = off;
+ *p_col_count = col_count;
+ return TRUE;
+}
+
+static int
+md_is_opening_code_fence(MD_CTX* ctx, OFF beg, OFF* p_end)
+{
+ OFF off = beg;
+
+ while(off < ctx->size && CH(off) == CH(beg))
+ off++;
+
+ /* Fence must have at least three characters. */
+ if(off - beg < 3)
+ return FALSE;
+
+ ctx->code_fence_length = off - beg;
+
+ /* Optionally, space(s) can follow. */
+ while(off < ctx->size && CH(off) == _T(' '))
+ off++;
+
+ /* Optionally, an info string can follow. */
+ while(off < ctx->size && !ISNEWLINE(off)) {
+ /* Backtick-based fence must not contain '`' in the info string. */
+ if(CH(beg) == _T('`') && CH(off) == _T('`'))
+ return FALSE;
+ off++;
+ }
+
+ *p_end = off;
+ return TRUE;
+}
+
+static int
+md_is_closing_code_fence(MD_CTX* ctx, CHAR ch, OFF beg, OFF* p_end)
+{
+ OFF off = beg;
+ int ret = FALSE;
+
+ /* Closing fence must have at least the same length and use same char as
+ * opening one. */
+ while(off < ctx->size && CH(off) == ch)
+ off++;
+ if(off - beg < ctx->code_fence_length)
+ goto out;
+
+ /* Optionally, space(s) can follow */
+ while(off < ctx->size && CH(off) == _T(' '))
+ off++;
+
+ /* But nothing more is allowed on the line. */
+ if(off < ctx->size && !ISNEWLINE(off))
+ goto out;
+
+ ret = TRUE;
+
+out:
+ /* Note we set *p_end even on failure: If we are not closing fence, caller
+ * would eat the line anyway without any parsing. */
+ *p_end = off;
+ return ret;
+}
+
+/* Returns type of the raw HTML block, or FALSE if it is not HTML block.
+ * (Refer to CommonMark specification for details about the types.)
+ */
+static int
+md_is_html_block_start_condition(MD_CTX* ctx, OFF beg)
+{
+ typedef struct TAG_tag TAG;
+ struct TAG_tag {
+ const CHAR* name;
+ unsigned len : 8;
+ };
+
+ /* Type 6 is started by a long list of allowed tags. We use two-level
+ * tree to speed-up the search. */
+#ifdef X
+ #undef X
+#endif
+#define X(name) { _T(name), sizeof(name)-1 }
+#define Xend { NULL, 0 }
+ static const TAG t1[] = { X("script"), X("pre"), X("style"), Xend };
+
+ static const TAG a6[] = { X("address"), X("article"), X("aside"), Xend };
+ static const TAG b6[] = { X("base"), X("basefont"), X("blockquote"), X("body"), Xend };
+ static const TAG c6[] = { X("caption"), X("center"), X("col"), X("colgroup"), Xend };
+ static const TAG d6[] = { X("dd"), X("details"), X("dialog"), X("dir"),
+ X("div"), X("dl"), X("dt"), Xend };
+ static const TAG f6[] = { X("fieldset"), X("figcaption"), X("figure"), X("footer"),
+ X("form"), X("frame"), X("frameset"), Xend };
+ static const TAG h6[] = { X("h1"), X("head"), X("header"), X("hr"), X("html"), Xend };
+ static const TAG i6[] = { X("iframe"), Xend };
+ static const TAG l6[] = { X("legend"), X("li"), X("link"), Xend };
+ static const TAG m6[] = { X("main"), X("menu"), X("menuitem"), Xend };
+ static const TAG n6[] = { X("nav"), X("noframes"), Xend };
+ static const TAG o6[] = { X("ol"), X("optgroup"), X("option"), Xend };
+ static const TAG p6[] = { X("p"), X("param"), Xend };
+ static const TAG s6[] = { X("section"), X("source"), X("summary"), Xend };
+ static const TAG t6[] = { X("table"), X("tbody"), X("td"), X("tfoot"), X("th"),
+ X("thead"), X("title"), X("tr"), X("track"), Xend };
+ static const TAG u6[] = { X("ul"), Xend };
+ static const TAG xx[] = { Xend };
+#undef X
+
+ static const TAG* map6[26] = {
+ a6, b6, c6, d6, xx, f6, xx, h6, i6, xx, xx, l6, m6,
+ n6, o6, p6, xx, xx, s6, t6, u6, xx, xx, xx, xx, xx
+ };
+ OFF off = beg + 1;
+ int i;
+
+ /* Check for type 1: <script, <pre, or <style */
+ for(i = 0; t1[i].name != NULL; i++) {
+ if(off + t1[i].len <= ctx->size) {
+ if(md_ascii_case_eq(STR(off), t1[i].name, t1[i].len))
+ return 1;
+ }
+ }
+
+ /* Check for type 2: <!-- */
+ if(off + 3 < ctx->size && CH(off) == _T('!') && CH(off+1) == _T('-') && CH(off+2) == _T('-'))
+ return 2;
+
+ /* Check for type 3: <? */
+ if(off < ctx->size && CH(off) == _T('?'))
+ return 3;
+
+ /* Check for type 4 or 5: <! */
+ if(off < ctx->size && CH(off) == _T('!')) {
+ /* Check for type 4: <! followed by uppercase letter. */
+ if(off + 1 < ctx->size && ISUPPER(off+1))
+ return 4;
+
+ /* Check for type 5: <![CDATA[ */
+ if(off + 8 < ctx->size) {
+ if(md_ascii_eq(STR(off), _T("![CDATA["), 8 * sizeof(CHAR)))
+ return 5;
+ }
+ }
+
+ /* Check for type 6: Many possible starting tags listed above. */
+ if(off + 1 < ctx->size && (ISALPHA(off) || (CH(off) == _T('/') && ISALPHA(off+1)))) {
+ int slot;
+ const TAG* tags;
+
+ if(CH(off) == _T('/'))
+ off++;
+
+ slot = (ISUPPER(off) ? CH(off) - 'A' : CH(off) - 'a');
+ tags = map6[slot];
+
+ for(i = 0; tags[i].name != NULL; i++) {
+ if(off + tags[i].len <= ctx->size) {
+ if(md_ascii_case_eq(STR(off), tags[i].name, tags[i].len)) {
+ OFF tmp = off + tags[i].len;
+ if(tmp >= ctx->size)
+ return 6;
+ if(ISBLANK(tmp) || ISNEWLINE(tmp) || CH(tmp) == _T('>'))
+ return 6;
+ if(tmp+1 < ctx->size && CH(tmp) == _T('/') && CH(tmp+1) == _T('>'))
+ return 6;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Check for type 7: any COMPLETE other opening or closing tag. */
+ if(off + 1 < ctx->size) {
+ OFF end;
+
+ if(md_is_html_tag(ctx, NULL, 0, beg, ctx->size, &end)) {
+ /* Only optional whitespace and new line may follow. */
+ while(end < ctx->size && ISWHITESPACE(end))
+ end++;
+ if(end >= ctx->size || ISNEWLINE(end))
+ return 7;
+ }
+ }
+
+ return FALSE;
+}
+
+/* Case sensitive check whether there is a substring 'what' between 'beg'
+ * and end of line. */
+static int
+md_line_contains(MD_CTX* ctx, OFF beg, const CHAR* what, SZ what_len, OFF* p_end)
+{
+ OFF i;
+ for(i = beg; i + what_len < ctx->size; i++) {
+ if(ISNEWLINE(i))
+ break;
+ if(memcmp(STR(i), what, what_len * sizeof(CHAR)) == 0) {
+ *p_end = i + what_len;
+ return TRUE;
+ }
+ }
+
+ *p_end = i;
+ return FALSE;
+}
+
+/* Returns type of HTML block end condition or FALSE if not an end condition.
+ *
+ * Note it fills p_end even when it is not end condition as the caller
+ * does not need to analyze contents of a raw HTML block.
+ */
+static int
+md_is_html_block_end_condition(MD_CTX* ctx, OFF beg, OFF* p_end)
+{
+ switch(ctx->html_block_type) {
+ case 1:
+ {
+ OFF off = beg;
+
+ while(off < ctx->size && !ISNEWLINE(off)) {
+ if(CH(off) == _T('<')) {
+ if(md_ascii_case_eq(STR(off), _T("</script>"), 9)) {
+ *p_end = off + 9;
+ return TRUE;
+ }
+
+ if(md_ascii_case_eq(STR(off), _T("</style>"), 8)) {
+ *p_end = off + 8;
+ return TRUE;
+ }
+
+ if(md_ascii_case_eq(STR(off), _T("</pre>"), 6)) {
+ *p_end = off + 6;
+ return TRUE;
+ }
+ }
+
+ off++;
+ }
+ *p_end = off;
+ return FALSE;
+ }
+
+ case 2:
+ return (md_line_contains(ctx, beg, _T("-->"), 3, p_end) ? 2 : FALSE);
+
+ case 3:
+ return (md_line_contains(ctx, beg, _T("?>"), 2, p_end) ? 3 : FALSE);
+
+ case 4:
+ return (md_line_contains(ctx, beg, _T(">"), 1, p_end) ? 4 : FALSE);
+
+ case 5:
+ return (md_line_contains(ctx, beg, _T("]]>"), 3, p_end) ? 5 : FALSE);
+
+ case 6: /* Pass through */
+ case 7:
+ *p_end = beg;
+ return (ISNEWLINE(beg) ? ctx->html_block_type : FALSE);
+
+ default:
+ MD_UNREACHABLE();
+ }
+ return FALSE;
+}
+
+
+static int
+md_is_container_compatible(const MD_CONTAINER* pivot, const MD_CONTAINER* container)
+{
+ /* Block quote has no "items" like lists. */
+ if(container->ch == _T('>'))
+ return FALSE;
+
+ if(container->ch != pivot->ch)
+ return FALSE;
+ if(container->mark_indent > pivot->contents_indent)
+ return FALSE;
+
+ return TRUE;
+}
+
+static int
+md_push_container(MD_CTX* ctx, const MD_CONTAINER* container)
+{
+ if(ctx->n_containers >= ctx->alloc_containers) {
+ MD_CONTAINER* new_containers;
+
+ ctx->alloc_containers = (ctx->alloc_containers > 0 ? ctx->alloc_containers * 2 : 16);
+ new_containers = realloc(ctx->containers, ctx->alloc_containers * sizeof(MD_CONTAINER));
+ if(new_containers == NULL) {
+ MD_LOG("realloc() failed.");
+ return -1;
+ }
+
+ ctx->containers = new_containers;
+ }
+
+ memcpy(&ctx->containers[ctx->n_containers++], container, sizeof(MD_CONTAINER));
+ return 0;
+}
+
+static int
+md_enter_child_containers(MD_CTX* ctx, int n_children, unsigned data)
+{
+ int i;
+ int ret = 0;
+
+ for(i = ctx->n_containers - n_children; i < ctx->n_containers; i++) {
+ MD_CONTAINER* c = &ctx->containers[i];
+ int is_ordered_list = FALSE;
+
+ switch(c->ch) {
+ case _T(')'):
+ case _T('.'):
+ is_ordered_list = TRUE;
+ /* Pass through */
+
+ case _T('-'):
+ case _T('+'):
+ case _T('*'):
+ /* Remember offset in ctx->block_bytes so we can revisit the
+ * block if we detect it is a loose list. */
+ md_end_current_block(ctx);
+ c->block_byte_off = ctx->n_block_bytes;
+
+ MD_CHECK(md_push_container_bytes(ctx,
+ (is_ordered_list ? MD_BLOCK_OL : MD_BLOCK_UL),
+ c->start, data, MD_BLOCK_CONTAINER_OPENER));
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI,
+ c->task_mark_off,
+ (c->is_task ? CH(c->task_mark_off) : 0),
+ MD_BLOCK_CONTAINER_OPENER));
+ break;
+
+ case _T('>'):
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, 0, 0, MD_BLOCK_CONTAINER_OPENER));
+ break;
+
+ default:
+ MD_UNREACHABLE();
+ break;
+ }
+ }
+
+abort:
+ return ret;
+}
+
+static int
+md_leave_child_containers(MD_CTX* ctx, int n_keep)
+{
+ int ret = 0;
+
+ while(ctx->n_containers > n_keep) {
+ MD_CONTAINER* c = &ctx->containers[ctx->n_containers-1];
+ int is_ordered_list = FALSE;
+
+ switch(c->ch) {
+ case _T(')'):
+ case _T('.'):
+ is_ordered_list = TRUE;
+ /* Pass through */
+
+ case _T('-'):
+ case _T('+'):
+ case _T('*'):
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI,
+ c->task_mark_off, (c->is_task ? CH(c->task_mark_off) : 0),
+ MD_BLOCK_CONTAINER_CLOSER));
+ MD_CHECK(md_push_container_bytes(ctx,
+ (is_ordered_list ? MD_BLOCK_OL : MD_BLOCK_UL), 0,
+ c->ch, MD_BLOCK_CONTAINER_CLOSER));
+ break;
+
+ case _T('>'):
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, 0,
+ 0, MD_BLOCK_CONTAINER_CLOSER));
+ break;
+
+ default:
+ MD_UNREACHABLE();
+ break;
+ }
+
+ ctx->n_containers--;
+ }
+
+abort:
+ return ret;
+}
+
+static int
+md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTAINER* p_container)
+{
+ OFF off = beg;
+ OFF max_end;
+
+ if(indent >= ctx->code_indent_offset)
+ return FALSE;
+
+ /* Check for block quote mark. */
+ if(off < ctx->size && CH(off) == _T('>')) {
+ off++;
+ p_container->ch = _T('>');
+ p_container->is_loose = FALSE;
+ p_container->is_task = FALSE;
+ p_container->mark_indent = indent;
+ p_container->contents_indent = indent + 1;
+ *p_end = off;
+ return TRUE;
+ }
+
+ /* Check for list item bullet mark. */
+ if(off+1 < ctx->size && ISANYOF(off, _T("-+*")) && (ISBLANK(off+1) || ISNEWLINE(off+1))) {
+ p_container->ch = CH(off);
+ p_container->is_loose = FALSE;
+ p_container->is_task = FALSE;
+ p_container->mark_indent = indent;
+ p_container->contents_indent = indent + 1;
+ *p_end = off + 1;
+ return TRUE;
+ }
+
+ /* Check for ordered list item marks. */
+ max_end = off + 9;
+ if(max_end > ctx->size)
+ max_end = ctx->size;
+ p_container->start = 0;
+ while(off < max_end && ISDIGIT(off)) {
+ p_container->start = p_container->start * 10 + CH(off) - _T('0');
+ off++;
+ }
+ if(off+1 < ctx->size && (CH(off) == _T('.') || CH(off) == _T(')')) && (ISBLANK(off+1) || ISNEWLINE(off+1))) {
+ p_container->ch = CH(off);
+ p_container->is_loose = FALSE;
+ p_container->is_task = FALSE;
+ p_container->mark_indent = indent;
+ p_container->contents_indent = indent + off - beg + 1;
+ *p_end = off + 1;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static unsigned
+md_line_indentation(MD_CTX* ctx, unsigned total_indent, OFF beg, OFF* p_end)
+{
+ OFF off = beg;
+ unsigned indent = total_indent;
+
+ while(off < ctx->size && ISBLANK(off)) {
+ if(CH(off) == _T('\t'))
+ indent = (indent + 4) & ~3;
+ else
+ indent++;
+ off++;
+ }
+
+ *p_end = off;
+ return indent - total_indent;
+}
+
+static const MD_LINE_ANALYSIS md_dummy_blank_line = { MD_LINE_BLANK, 0 };
+
+/* Analyze type of the line and find some its properties. This serves as a
+ * main input for determining type and boundaries of a block. */
+static int
+md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end,
+ const MD_LINE_ANALYSIS* pivot_line, MD_LINE_ANALYSIS* line)
+{
+ unsigned total_indent = 0;
+ int n_parents = 0;
+ int n_brothers = 0;
+ int n_children = 0;
+ MD_CONTAINER container = { 0 };
+ int prev_line_has_list_loosening_effect = ctx->last_line_has_list_loosening_effect;
+ OFF off = beg;
+ OFF hr_killer = 0;
+ int ret = 0;
+
+ line->indent = md_line_indentation(ctx, total_indent, off, &off);
+ total_indent += line->indent;
+ line->beg = off;
+
+ /* Given the indentation and block quote marks '>', determine how many of
+ * the current containers are our parents. */
+ while(n_parents < ctx->n_containers) {
+ MD_CONTAINER* c = &ctx->containers[n_parents];
+
+ if(c->ch == _T('>') && line->indent < ctx->code_indent_offset &&
+ off < ctx->size && CH(off) == _T('>'))
+ {
+ /* Block quote mark. */
+ off++;
+ total_indent++;
+ line->indent = md_line_indentation(ctx, total_indent, off, &off);
+ total_indent += line->indent;
+
+ /* The optional 1st space after '>' is part of the block quote mark. */
+ if(line->indent > 0)
+ line->indent--;
+
+ line->beg = off;
+ } else if(c->ch != _T('>') && line->indent >= c->contents_indent) {
+ /* List. */
+ line->indent -= c->contents_indent;
+ } else {
+ break;
+ }
+
+ n_parents++;
+ }
+
+ if(off >= ctx->size || ISNEWLINE(off)) {
+ /* Blank line does not need any real indentation to be nested inside
+ * a list. */
+ if(n_brothers + n_children == 0) {
+ while(n_parents < ctx->n_containers && ctx->containers[n_parents].ch != _T('>'))
+ n_parents++;
+ }
+ }
+
+ while(TRUE) {
+ /* Check whether we are fenced code continuation. */
+ if(pivot_line->type == MD_LINE_FENCEDCODE) {
+ line->beg = off;
+
+ /* We are another MD_LINE_FENCEDCODE unless we are closing fence
+ * which we transform into MD_LINE_BLANK. */
+ if(line->indent < ctx->code_indent_offset) {
+ if(md_is_closing_code_fence(ctx, CH(pivot_line->beg), off, &off)) {
+ line->type = MD_LINE_BLANK;
+ ctx->last_line_has_list_loosening_effect = FALSE;
+ break;
+ }
+ }
+
+ /* Change indentation accordingly to the initial code fence. */
+ if(n_parents == ctx->n_containers) {
+ if(line->indent > pivot_line->indent)
+ line->indent -= pivot_line->indent;
+ else
+ line->indent = 0;
+
+ line->type = MD_LINE_FENCEDCODE;
+ break;
+ }
+ }
+
+ /* Check whether we are HTML block continuation. */
+ if(pivot_line->type == MD_LINE_HTML && ctx->html_block_type > 0) {
+ int html_block_type;
+
+ html_block_type = md_is_html_block_end_condition(ctx, off, &off);
+ if(html_block_type > 0) {
+ MD_ASSERT(html_block_type == ctx->html_block_type);
+
+ /* Make sure this is the last line of the block. */
+ ctx->html_block_type = 0;
+
+ /* Some end conditions serve as blank lines at the same time. */
+ if(html_block_type == 6 || html_block_type == 7) {
+ line->type = MD_LINE_BLANK;
+ line->indent = 0;
+ break;
+ }
+ }
+
+ if(n_parents == ctx->n_containers) {
+ line->type = MD_LINE_HTML;
+ break;
+ }
+ }
+
+ /* Check for blank line. */
+ if(off >= ctx->size || ISNEWLINE(off)) {
+ if(pivot_line->type == MD_LINE_INDENTEDCODE && n_parents == ctx->n_containers) {
+ line->type = MD_LINE_INDENTEDCODE;
+ if(line->indent > ctx->code_indent_offset)
+ line->indent -= ctx->code_indent_offset;
+ else
+ line->indent = 0;
+ ctx->last_line_has_list_loosening_effect = FALSE;
+ } else {
+ line->type = MD_LINE_BLANK;
+ ctx->last_line_has_list_loosening_effect = (n_parents > 0 &&
+ n_brothers + n_children == 0 &&
+ ctx->containers[n_parents-1].ch != _T('>'));
+
+ #if 1
+ /* See https://github.com/mity/md4c/issues/6
+ *
+ * This ugly checking tests we are in (yet empty) list item but not
+ * its very first line (with the list item mark).
+ *
+ * If we are such blank line, then any following non-blank line
+ * which would be part of this list item actually ends the list
+ * because "a list item can begin with at most one blank line."
+ */
+ if(n_parents > 0 && ctx->containers[n_parents-1].ch != _T('>') &&
+ n_brothers + n_children == 0 && ctx->current_block == NULL &&
+ ctx->n_block_bytes > (int) sizeof(MD_BLOCK))
+ {
+ MD_BLOCK* top_block = (MD_BLOCK*) ((char*)ctx->block_bytes + ctx->n_block_bytes - sizeof(MD_BLOCK));
+ if(top_block->type == MD_BLOCK_LI)
+ ctx->last_list_item_starts_with_two_blank_lines = TRUE;
+ }
+ #endif
+ }
+ break;
+ } else {
+ #if 1
+ /* This is 2nd half of the hack. If the flag is set (that is there
+ * were 2nd blank line at the start of the list item) and we would also
+ * belonging to such list item, then interrupt the list. */
+ ctx->last_line_has_list_loosening_effect = FALSE;
+ if(ctx->last_list_item_starts_with_two_blank_lines) {
+ if(n_parents > 0 && ctx->containers[n_parents-1].ch != _T('>') &&
+ n_brothers + n_children == 0 && ctx->current_block == NULL &&
+ ctx->n_block_bytes > (int) sizeof(MD_BLOCK))
+ {
+ MD_BLOCK* top_block = (MD_BLOCK*) ((char*)ctx->block_bytes + ctx->n_block_bytes - sizeof(MD_BLOCK));
+ if(top_block->type == MD_BLOCK_LI)
+ n_parents--;
+ }
+
+ ctx->last_list_item_starts_with_two_blank_lines = FALSE;
+ }
+ #endif
+ }
+
+ /* Check whether we are Setext underline. */
+ if(line->indent < ctx->code_indent_offset && pivot_line->type == MD_LINE_TEXT
+ && (CH(off) == _T('=') || CH(off) == _T('-'))
+ && (n_parents == ctx->n_containers))
+ {
+ unsigned level;
+
+ if(md_is_setext_underline(ctx, off, &off, &level)) {
+ line->type = MD_LINE_SETEXTUNDERLINE;
+ line->data = level;
+ break;
+ }
+ }
+
+ /* Check for thematic break line. */
+ if(line->indent < ctx->code_indent_offset && ISANYOF(off, _T("-_*")) && off >= hr_killer) {
+ if(md_is_hr_line(ctx, off, &off, &hr_killer)) {
+ line->type = MD_LINE_HR;
+ break;
+ }
+ }
+
+ /* Check for "brother" container. I.e. whether we are another list item
+ * in already started list. */
+ if(n_parents < ctx->n_containers && n_brothers + n_children == 0) {
+ OFF tmp;
+
+ if(md_is_container_mark(ctx, line->indent, off, &tmp, &container) &&
+ md_is_container_compatible(&ctx->containers[n_parents], &container))
+ {
+ pivot_line = &md_dummy_blank_line;
+
+ off = tmp;
+
+ total_indent += container.contents_indent - container.mark_indent;
+ line->indent = md_line_indentation(ctx, total_indent, off, &off);
+ total_indent += line->indent;
+ line->beg = off;
+
+ /* Some of the following whitespace actually still belongs to the mark. */
+ if(off >= ctx->size || ISNEWLINE(off)) {
+ container.contents_indent++;
+ } else if(line->indent <= ctx->code_indent_offset) {
+ container.contents_indent += line->indent;
+ line->indent = 0;
+ } else {
+ container.contents_indent += 1;
+ line->indent--;
+ }
+
+ ctx->containers[n_parents].mark_indent = container.mark_indent;
+ ctx->containers[n_parents].contents_indent = container.contents_indent;
+
+ n_brothers++;
+ continue;
+ }
+ }
+
+ /* Check for indented code.
+ * Note indented code block cannot interrupt a paragraph. */
+ if(line->indent >= ctx->code_indent_offset &&
+ (pivot_line->type == MD_LINE_BLANK || pivot_line->type == MD_LINE_INDENTEDCODE))
+ {
+ line->type = MD_LINE_INDENTEDCODE;
+ MD_ASSERT(line->indent >= ctx->code_indent_offset);
+ line->indent -= ctx->code_indent_offset;
+ line->data = 0;
+ break;
+ }
+
+ /* Check for start of a new container block. */
+ if(line->indent < ctx->code_indent_offset &&
+ md_is_container_mark(ctx, line->indent, off, &off, &container))
+ {
+ if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers &&
+ (off >= ctx->size || ISNEWLINE(off)))
+ {
+ /* Noop. List mark followed by a blank line cannot interrupt a paragraph. */
+ } else if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers &&
+ (container.ch == _T('.') || container.ch == _T(')')) && container.start != 1)
+ {
+ /* Noop. Ordered list cannot interrupt a paragraph unless the start index is 1. */
+ } else {
+ total_indent += container.contents_indent - container.mark_indent;
+ line->indent = md_line_indentation(ctx, total_indent, off, &off);
+ total_indent += line->indent;
+
+ line->beg = off;
+ line->data = container.ch;
+
+ /* Some of the following whitespace actually still belongs to the mark. */
+ if(off >= ctx->size || ISNEWLINE(off)) {
+ container.contents_indent++;
+ } else if(line->indent <= ctx->code_indent_offset) {
+ container.contents_indent += line->indent;
+ line->indent = 0;
+ } else {
+ container.contents_indent += 1;
+ line->indent--;
+ }
+
+ if(n_brothers + n_children == 0)
+ pivot_line = &md_dummy_blank_line;
+
+ if(n_children == 0)
+ MD_CHECK(md_leave_child_containers(ctx, n_parents + n_brothers));
+
+ n_children++;
+ MD_CHECK(md_push_container(ctx, &container));
+ continue;
+ }
+ }
+
+ /* Check whether we are table continuation. */
+ if(pivot_line->type == MD_LINE_TABLE && md_is_table_row(ctx, off, &off) &&
+ n_parents == ctx->n_containers)
+ {
+ line->type = MD_LINE_TABLE;
+ break;
+ }
+
+ /* Check for ATX header. */
+ if(line->indent < ctx->code_indent_offset && CH(off) == _T('#')) {
+ unsigned level;
+
+ if(md_is_atxheader_line(ctx, off, &line->beg, &off, &level)) {
+ line->type = MD_LINE_ATXHEADER;
+ line->data = level;
+ break;
+ }
+ }
+
+ /* Check whether we are starting code fence. */
+ if(CH(off) == _T('`') || CH(off) == _T('~')) {
+ if(md_is_opening_code_fence(ctx, off, &off)) {
+ line->type = MD_LINE_FENCEDCODE;
+ line->data = 1;
+ break;
+ }
+ }
+
+ /* Check for start of raw HTML block. */
+ if(CH(off) == _T('<') && !(ctx->parser.flags & MD_FLAG_NOHTMLBLOCKS))
+ {
+ ctx->html_block_type = md_is_html_block_start_condition(ctx, off);
+
+ /* HTML block type 7 cannot interrupt paragraph. */
+ if(ctx->html_block_type == 7 && pivot_line->type == MD_LINE_TEXT)
+ ctx->html_block_type = 0;
+
+ if(ctx->html_block_type > 0) {
+ /* The line itself also may immediately close the block. */
+ if(md_is_html_block_end_condition(ctx, off, &off) == ctx->html_block_type) {
+ /* Make sure this is the last line of the block. */
+ ctx->html_block_type = 0;
+ }
+
+ line->type = MD_LINE_HTML;
+ break;
+ }
+ }
+
+ /* Check for table underline. */
+ if((ctx->parser.flags & MD_FLAG_TABLES) && pivot_line->type == MD_LINE_TEXT &&
+ (CH(off) == _T('|') || CH(off) == _T('-') || CH(off) == _T(':')) &&
+ n_parents == ctx->n_containers)
+ {
+ unsigned col_count;
+
+ if(ctx->current_block != NULL && ctx->current_block->n_lines == 1 &&
+ md_is_table_underline(ctx, off, &off, &col_count) &&
+ md_is_table_row(ctx, pivot_line->beg, NULL))
+ {
+ line->data = col_count;
+ line->type = MD_LINE_TABLEUNDERLINE;
+ break;
+ }
+ }
+
+ /* By default, we are normal text line. */
+ line->type = MD_LINE_TEXT;
+ if(pivot_line->type == MD_LINE_TEXT && n_brothers + n_children == 0) {
+ /* Lazy continuation. */
+ n_parents = ctx->n_containers;
+ }
+
+ /* Check for task mark. */
+ if((ctx->parser.flags & MD_FLAG_TASKLISTS) && n_brothers + n_children > 0 &&
+ ISANYOF_(ctx->containers[ctx->n_containers-1].ch, _T("-+*.)")))
+ {
+ OFF tmp = off;
+
+ while(tmp < ctx->size && tmp < off + 3 && ISBLANK(tmp))
+ tmp++;
+ if(tmp + 2 < ctx->size && CH(tmp) == _T('[') &&
+ ISANYOF(tmp+1, _T("xX ")) && CH(tmp+2) == _T(']') &&
+ (tmp + 3 == ctx->size || ISBLANK(tmp+3) || ISNEWLINE(tmp+3)))
+ {
+ MD_CONTAINER* task_container = (n_children > 0 ? &ctx->containers[ctx->n_containers-1] : &container);
+ task_container->is_task = TRUE;
+ task_container->task_mark_off = tmp + 1;
+ off = tmp + 3;
+ while(ISWHITESPACE(off))
+ off++;
+ line->beg = off;
+ }
+ }
+
+ break;
+ }
+
+ /* Scan for end of the line.
+ *
+ * Note this is quite a bottleneck of the parsing as we here iterate almost
+ * over compete document.
+ */
+#if defined __linux__ && !defined MD4C_USE_UTF16
+ /* Recent glibc versions have superbly optimized strcspn(), even using
+ * vectorization if available. */
+ if(ctx->doc_ends_with_newline && off < ctx->size) {
+ while(TRUE) {
+ off += (OFF) strcspn(STR(off), "\r\n");
+
+ /* strcspn() can stop on zero terminator; but that can appear
+ * anywhere in the Markfown input... */
+ if(CH(off) == _T('\0'))
+ off++;
+ else
+ break;
+ }
+ } else
+#endif
+ {
+ /* Optimization: Use some loop unrolling. */
+ while(off + 3 < ctx->size && !ISNEWLINE(off+0) && !ISNEWLINE(off+1)
+ && !ISNEWLINE(off+2) && !ISNEWLINE(off+3))
+ off += 4;
+ while(off < ctx->size && !ISNEWLINE(off))
+ off++;
+ }
+
+ /* Set end of the line. */
+ line->end = off;
+
+ /* But for ATX header, we should exclude the optional trailing mark. */
+ if(line->type == MD_LINE_ATXHEADER) {
+ OFF tmp = line->end;
+ while(tmp > line->beg && CH(tmp-1) == _T(' '))
+ tmp--;
+ while(tmp > line->beg && CH(tmp-1) == _T('#'))
+ tmp--;
+ if(tmp == line->beg || CH(tmp-1) == _T(' ') || (ctx->parser.flags & MD_FLAG_PERMISSIVEATXHEADERS))
+ line->end = tmp;
+ }
+
+ /* Trim trailing spaces. */
+ if(line->type != MD_LINE_INDENTEDCODE && line->type != MD_LINE_FENCEDCODE) {
+ while(line->end > line->beg && CH(line->end-1) == _T(' '))
+ line->end--;
+ }
+
+ /* Eat also the new line. */
+ if(off < ctx->size && CH(off) == _T('\r'))
+ off++;
+ if(off < ctx->size && CH(off) == _T('\n'))
+ off++;
+
+ *p_end = off;
+
+ /* If we belong to a list after seeing a blank line, the list is loose. */
+ if(prev_line_has_list_loosening_effect && line->type != MD_LINE_BLANK && n_parents + n_brothers > 0) {
+ MD_CONTAINER* c = &ctx->containers[n_parents + n_brothers - 1];
+ if(c->ch != _T('>')) {
+ MD_BLOCK* block = (MD_BLOCK*) (((char*)ctx->block_bytes) + c->block_byte_off);
+ block->flags |= MD_BLOCK_LOOSE_LIST;
+ }
+ }
+
+ /* Leave any containers we are not part of anymore. */
+ if(n_children == 0 && n_parents + n_brothers < ctx->n_containers)
+ MD_CHECK(md_leave_child_containers(ctx, n_parents + n_brothers));
+
+ /* Enter any container we found a mark for. */
+ if(n_brothers > 0) {
+ MD_ASSERT(n_brothers == 1);
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI,
+ ctx->containers[n_parents].task_mark_off,
+ (ctx->containers[n_parents].is_task ? CH(ctx->containers[n_parents].task_mark_off) : 0),
+ MD_BLOCK_CONTAINER_CLOSER));
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI,
+ container.task_mark_off,
+ (container.is_task ? CH(container.task_mark_off) : 0),
+ MD_BLOCK_CONTAINER_OPENER));
+ ctx->containers[n_parents].is_task = container.is_task;
+ ctx->containers[n_parents].task_mark_off = container.task_mark_off;
+ }
+
+ if(n_children > 0)
+ MD_CHECK(md_enter_child_containers(ctx, n_children, line->data));
+
+abort:
+ return ret;
+}
+
+static int
+md_process_line(MD_CTX* ctx, const MD_LINE_ANALYSIS** p_pivot_line, MD_LINE_ANALYSIS* line)
+{
+ const MD_LINE_ANALYSIS* pivot_line = *p_pivot_line;
+ int ret = 0;
+
+ /* Blank line ends current leaf block. */
+ if(line->type == MD_LINE_BLANK) {
+ MD_CHECK(md_end_current_block(ctx));
+ *p_pivot_line = &md_dummy_blank_line;
+ return 0;
+ }
+
+ /* Some line types form block on their own. */
+ if(line->type == MD_LINE_HR || line->type == MD_LINE_ATXHEADER) {
+ MD_CHECK(md_end_current_block(ctx));
+
+ /* Add our single-line block. */
+ MD_CHECK(md_start_new_block(ctx, line));
+ MD_CHECK(md_add_line_into_current_block(ctx, line));
+ MD_CHECK(md_end_current_block(ctx));
+ *p_pivot_line = &md_dummy_blank_line;
+ return 0;
+ }
+
+ /* MD_LINE_SETEXTUNDERLINE changes meaning of the current block and ends it. */
+ if(line->type == MD_LINE_SETEXTUNDERLINE) {
+ MD_ASSERT(ctx->current_block != NULL);
+ ctx->current_block->type = MD_BLOCK_H;
+ ctx->current_block->data = line->data;
+ ctx->current_block->flags |= MD_BLOCK_SETEXT_HEADER;
+ MD_CHECK(md_add_line_into_current_block(ctx, line));
+ MD_CHECK(md_end_current_block(ctx));
+ if(ctx->current_block == NULL) {
+ *p_pivot_line = &md_dummy_blank_line;
+ } else {
+ /* This happens if we have consumed all the body as link ref. defs.
+ * and downgraded the underline into start of a new paragraph block. */
+ line->type = MD_LINE_TEXT;
+ *p_pivot_line = line;
+ }
+ return 0;
+ }
+
+ /* MD_LINE_TABLEUNDERLINE changes meaning of the current block. */
+ if(line->type == MD_LINE_TABLEUNDERLINE) {
+ MD_ASSERT(ctx->current_block != NULL);
+ MD_ASSERT(ctx->current_block->n_lines == 1);
+ ctx->current_block->type = MD_BLOCK_TABLE;
+ ctx->current_block->data = line->data;
+ MD_ASSERT(pivot_line != &md_dummy_blank_line);
+ ((MD_LINE_ANALYSIS*)pivot_line)->type = MD_LINE_TABLE;
+ MD_CHECK(md_add_line_into_current_block(ctx, line));
+ return 0;
+ }
+
+ /* The current block also ends if the line has different type. */
+ if(line->type != pivot_line->type)
+ MD_CHECK(md_end_current_block(ctx));
+
+ /* The current line may start a new block. */
+ if(ctx->current_block == NULL) {
+ MD_CHECK(md_start_new_block(ctx, line));
+ *p_pivot_line = line;
+ }
+
+ /* In all other cases the line is just a continuation of the current block. */
+ MD_CHECK(md_add_line_into_current_block(ctx, line));
+
+abort:
+ return ret;
+}
+
+static int
+md_process_doc(MD_CTX *ctx)
+{
+ const MD_LINE_ANALYSIS* pivot_line = &md_dummy_blank_line;
+ MD_LINE_ANALYSIS line_buf[2];
+ MD_LINE_ANALYSIS* line = &line_buf[0];
+ OFF off = 0;
+ int ret = 0;
+
+ MD_ENTER_BLOCK(MD_BLOCK_DOC, NULL);
+
+ while(off < ctx->size) {
+ if(line == pivot_line)
+ line = (line == &line_buf[0] ? &line_buf[1] : &line_buf[0]);
+
+ MD_CHECK(md_analyze_line(ctx, off, &off, pivot_line, line));
+ MD_CHECK(md_process_line(ctx, &pivot_line, line));
+ }
+
+ md_end_current_block(ctx);
+
+ MD_CHECK(md_build_ref_def_hashtable(ctx));
+
+ /* Process all blocks. */
+ MD_CHECK(md_leave_child_containers(ctx, 0));
+ MD_CHECK(md_process_all_blocks(ctx));
+
+ MD_LEAVE_BLOCK(MD_BLOCK_DOC, NULL);
+
+abort:
+
+#if 0
+ /* Output some memory consumption statistics. */
+ {
+ char buffer[256];
+ sprintf(buffer, "Alloced %u bytes for block buffer.",
+ (unsigned)(ctx->alloc_block_bytes));
+ MD_LOG(buffer);
+
+ sprintf(buffer, "Alloced %u bytes for containers buffer.",
+ (unsigned)(ctx->alloc_containers * sizeof(MD_CONTAINER)));
+ MD_LOG(buffer);
+
+ sprintf(buffer, "Alloced %u bytes for marks buffer.",
+ (unsigned)(ctx->alloc_marks * sizeof(MD_MARK)));
+ MD_LOG(buffer);
+
+ sprintf(buffer, "Alloced %u bytes for aux. buffer.",
+ (unsigned)(ctx->alloc_buffer * sizeof(MD_CHAR)));
+ MD_LOG(buffer);
+ }
+#endif
+
+ return ret;
+}
+
+
+/********************
+ *** Public API ***
+ ********************/
+
+int
+md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userdata)
+{
+ MD_CTX ctx;
+ int i;
+ int ret;
+
+ if(parser->abi_version != 0) {
+ if(parser->debug_log != NULL)
+ parser->debug_log("Unsupported abi_version.", userdata);
+ return -1;
+ }
+
+ /* Setup context structure. */
+ memset(&ctx, 0, sizeof(MD_CTX));
+ ctx.text = text;
+ ctx.size = size;
+ memcpy(&ctx.parser, parser, sizeof(MD_PARSER));
+ ctx.userdata = userdata;
+ ctx.code_indent_offset = (ctx.parser.flags & MD_FLAG_NOINDENTEDCODEBLOCKS) ? (OFF)(-1) : 4;
+ md_build_mark_char_map(&ctx);
+ ctx.doc_ends_with_newline = (size > 0 && ISNEWLINE_(text[size-1]));
+
+ /* Reset all unresolved opener mark chains. */
+ for(i = 0; i < (int) SIZEOF_ARRAY(ctx.mark_chains); i++) {
+ ctx.mark_chains[i].head = -1;
+ ctx.mark_chains[i].tail = -1;
+ }
+ ctx.unresolved_link_head = -1;
+ ctx.unresolved_link_tail = -1;
+
+ /* All the work. */
+ ret = md_process_doc(&ctx);
+
+ /* Clean-up. */
+ md_free_ref_defs(&ctx);
+ md_free_ref_def_hashtable(&ctx);
+ free(ctx.buffer);
+ free(ctx.marks);
+ free(ctx.block_bytes);
+ free(ctx.containers);
+
+ return ret;
+}
diff --git a/src/3rdparty/md4c/md4c.h b/src/3rdparty/md4c/md4c.h
new file mode 100644
index 0000000000..dcdadad88d
--- /dev/null
+++ b/src/3rdparty/md4c/md4c.h
@@ -0,0 +1,362 @@
+/*
+ * MD4C: Markdown parser for C
+ * (http://github.com/mity/md4c)
+ *
+ * Copyright (c) 2016-2019 Martin Mitas
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef MD4C_MARKDOWN_H
+#define MD4C_MARKDOWN_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#if defined MD4C_USE_UTF16
+ /* Magic to support UTF-16. Not that in order to use it, you have to define
+ * the macro MD4C_USE_UTF16 both when building MD4C as well as when
+ * including this header in your code. */
+ #ifdef _WIN32
+ #include <windows.h>
+ typedef WCHAR MD_CHAR;
+ #else
+ #error MD4C_USE_UTF16 is only supported on Windows.
+ #endif
+#else
+ typedef char MD_CHAR;
+#endif
+
+typedef unsigned MD_SIZE;
+typedef unsigned MD_OFFSET;
+
+
+/* Block represents a part of document hierarchy structure like a paragraph
+ * or list item.
+ */
+typedef enum MD_BLOCKTYPE {
+ /* <body>...</body> */
+ MD_BLOCK_DOC = 0,
+
+ /* <blockquote>...</blockquote> */
+ MD_BLOCK_QUOTE,
+
+ /* <ul>...</ul>
+ * Detail: Structure MD_BLOCK_UL_DETAIL. */
+ MD_BLOCK_UL,
+
+ /* <ol>...</ol>
+ * Detail: Structure MD_BLOCK_OL_DETAIL. */
+ MD_BLOCK_OL,
+
+ /* <li>...</li>
+ * Detail: Structure MD_BLOCK_LI_DETAIL. */
+ MD_BLOCK_LI,
+
+ /* <hr> */
+ MD_BLOCK_HR,
+
+ /* <h1>...</h1> (for levels up to 6)
+ * Detail: Structure MD_BLOCK_H_DETAIL. */
+ MD_BLOCK_H,
+
+ /* <pre><code>...</code></pre>
+ * Note the text lines within code blocks are terminated with '\n'
+ * instead of explicit MD_TEXT_BR. */
+ MD_BLOCK_CODE,
+
+ /* Raw HTML block. This itself does not correspond to any particular HTML
+ * tag. The contents of it _is_ raw HTML source intended to be put
+ * in verbatim form to the HTML output. */
+ MD_BLOCK_HTML,
+
+ /* <p>...</p> */
+ MD_BLOCK_P,
+
+ /* <table>...</table> and its contents.
+ * Detail: Structure MD_BLOCK_TD_DETAIL (used with MD_BLOCK_TH and MD_BLOCK_TD)
+ * Note all of these are used only if extension MD_FLAG_TABLES is enabled. */
+ MD_BLOCK_TABLE,
+ MD_BLOCK_THEAD,
+ MD_BLOCK_TBODY,
+ MD_BLOCK_TR,
+ MD_BLOCK_TH,
+ MD_BLOCK_TD
+} MD_BLOCKTYPE;
+
+/* Span represents an in-line piece of a document which should be rendered with
+ * the same font, color and other attributes. A sequence of spans forms a block
+ * like paragraph or list item. */
+typedef enum MD_SPANTYPE {
+ /* <em>...</em> */
+ MD_SPAN_EM,
+
+ /* <strong>...</strong> */
+ MD_SPAN_STRONG,
+
+ /* <a href="xxx">...</a>
+ * Detail: Structure MD_SPAN_A_DETAIL. */
+ MD_SPAN_A,
+
+ /* <img src="xxx">...</a>
+ * Detail: Structure MD_SPAN_IMG_DETAIL.
+ * Note: Image text can contain nested spans and even nested images.
+ * If rendered into ALT attribute of HTML <IMG> tag, it's responsibility
+ * of the renderer to deal with it.
+ */
+ MD_SPAN_IMG,
+
+ /* <code>...</code> */
+ MD_SPAN_CODE,
+
+ /* <del>...</del>
+ * Note: Recognized only when MD_FLAG_STRIKETHROUGH is enabled.
+ */
+ MD_SPAN_DEL
+} MD_SPANTYPE;
+
+/* Text is the actual textual contents of span. */
+typedef enum MD_TEXTTYPE {
+ /* Normal text. */
+ MD_TEXT_NORMAL = 0,
+
+ /* NULL character. CommonMark requires replacing NULL character with
+ * the replacement char U+FFFD, so this allows caller to do that easily. */
+ MD_TEXT_NULLCHAR,
+
+ /* Line breaks.
+ * Note these are not sent from blocks with verbatim output (MD_BLOCK_CODE
+ * or MD_BLOCK_HTML). In such cases, '\n' is part of the text itself. */
+ MD_TEXT_BR, /* <br> (hard break) */
+ MD_TEXT_SOFTBR, /* '\n' in source text where it is not semantically meaningful (soft break) */
+
+ /* Entity.
+ * (a) Named entity, e.g. &nbsp;
+ * (Note MD4C does not have a list of known entities.
+ * Anything matching the regexp /&[A-Za-z][A-Za-z0-9]{1,47};/ is
+ * treated as a named entity.)
+ * (b) Numerical entity, e.g. &#1234;
+ * (c) Hexadecimal entity, e.g. &#x12AB;
+ *
+ * As MD4C is mostly encoding agnostic, application gets the verbatim
+ * entity text into the MD_RENDERER::text_callback(). */
+ MD_TEXT_ENTITY,
+
+ /* Text in a code block (inside MD_BLOCK_CODE) or inlined code (`code`).
+ * If it is inside MD_BLOCK_CODE, it includes spaces for indentation and
+ * '\n' for new lines. MD_TEXT_BR and MD_TEXT_SOFTBR are not sent for this
+ * kind of text. */
+ MD_TEXT_CODE,
+
+ /* Text is a raw HTML. If it is contents of a raw HTML block (i.e. not
+ * an inline raw HTML), then MD_TEXT_BR and MD_TEXT_SOFTBR are not used.
+ * The text contains verbatim '\n' for the new lines. */
+ MD_TEXT_HTML
+} MD_TEXTTYPE;
+
+
+/* Alignment enumeration. */
+typedef enum MD_ALIGN {
+ MD_ALIGN_DEFAULT = 0, /* When unspecified. */
+ MD_ALIGN_LEFT,
+ MD_ALIGN_CENTER,
+ MD_ALIGN_RIGHT
+} MD_ALIGN;
+
+
+/* String attribute.
+ *
+ * This wraps strings which are outside of a normal text flow and which are
+ * propagated within various detailed structures, but which still may contain
+ * string portions of different types like e.g. entities.
+ *
+ * So, for example, lets consider an image has a title attribute string
+ * set to "foo &quot; bar". (Note the string size is 14.)
+ *
+ * Then the attribute MD_SPAN_IMG_DETAIL::title shall provide the following:
+ * -- [0]: "foo " (substr_types[0] == MD_TEXT_NORMAL; substr_offsets[0] == 0)
+ * -- [1]: "&quot;" (substr_types[1] == MD_TEXT_ENTITY; substr_offsets[1] == 4)
+ * -- [2]: " bar" (substr_types[2] == MD_TEXT_NORMAL; substr_offsets[2] == 10)
+ * -- [3]: (n/a) (n/a ; substr_offsets[3] == 14)
+ *
+ * Note that these conditions are guaranteed:
+ * -- substr_offsets[0] == 0
+ * -- substr_offsets[LAST+1] == size
+ * -- Only MD_TEXT_NORMAL, MD_TEXT_ENTITY, MD_TEXT_NULLCHAR substrings can appear.
+ */
+typedef struct MD_ATTRIBUTE {
+ const MD_CHAR* text;
+ MD_SIZE size;
+ const MD_TEXTTYPE* substr_types;
+ const MD_OFFSET* substr_offsets;
+} MD_ATTRIBUTE;
+
+
+/* Detailed info for MD_BLOCK_UL. */
+typedef struct MD_BLOCK_UL_DETAIL {
+ int is_tight; /* Non-zero if tight list, zero if loose. */
+ MD_CHAR mark; /* Item bullet character in MarkDown source of the list, e.g. '-', '+', '*'. */
+} MD_BLOCK_UL_DETAIL;
+
+/* Detailed info for MD_BLOCK_OL. */
+typedef struct MD_BLOCK_OL_DETAIL {
+ unsigned start; /* Start index of the ordered list. */
+ int is_tight; /* Non-zero if tight list, zero if loose. */
+ MD_CHAR mark_delimiter; /* Character delimiting the item marks in MarkDown source, e.g. '.' or ')' */
+} MD_BLOCK_OL_DETAIL;
+
+/* Detailed info for MD_BLOCK_LI. */
+typedef struct MD_BLOCK_LI_DETAIL {
+ int is_task; /* Can be non-zero only with MD_FLAG_TASKLISTS */
+ MD_CHAR task_mark; /* If is_task, then one of 'x', 'X' or ' '. Undefined otherwise. */
+ MD_OFFSET task_mark_offset; /* If is_task, then offset in the input of the char between '[' and ']'. */
+} MD_BLOCK_LI_DETAIL;
+
+/* Detailed info for MD_BLOCK_H. */
+typedef struct MD_BLOCK_H_DETAIL {
+ unsigned level; /* Header level (1 - 6) */
+} MD_BLOCK_H_DETAIL;
+
+/* Detailed info for MD_BLOCK_CODE. */
+typedef struct MD_BLOCK_CODE_DETAIL {
+ MD_ATTRIBUTE info;
+ MD_ATTRIBUTE lang;
+ MD_CHAR fence_char; /* The character used for fenced code block; or zero for indented code block. */
+} MD_BLOCK_CODE_DETAIL;
+
+/* Detailed info for MD_BLOCK_TH and MD_BLOCK_TD. */
+typedef struct MD_BLOCK_TD_DETAIL {
+ MD_ALIGN align;
+} MD_BLOCK_TD_DETAIL;
+
+/* Detailed info for MD_SPAN_A. */
+typedef struct MD_SPAN_A_DETAIL {
+ MD_ATTRIBUTE href;
+ MD_ATTRIBUTE title;
+} MD_SPAN_A_DETAIL;
+
+/* Detailed info for MD_SPAN_IMG. */
+typedef struct MD_SPAN_IMG_DETAIL {
+ MD_ATTRIBUTE src;
+ MD_ATTRIBUTE title;
+} MD_SPAN_IMG_DETAIL;
+
+
+/* Flags specifying extensions/deviations from CommonMark specification.
+ *
+ * By default (when MD_RENDERER::flags == 0), we follow CommonMark specification.
+ * The following flags may allow some extensions or deviations from it.
+ */
+#define MD_FLAG_COLLAPSEWHITESPACE 0x0001 /* In MD_TEXT_NORMAL, collapse non-trivial whitespace into single ' ' */
+#define MD_FLAG_PERMISSIVEATXHEADERS 0x0002 /* Do not require space in ATX headers ( ###header ) */
+#define MD_FLAG_PERMISSIVEURLAUTOLINKS 0x0004 /* Recognize URLs as autolinks even without '<', '>' */
+#define MD_FLAG_PERMISSIVEEMAILAUTOLINKS 0x0008 /* Recognize e-mails as autolinks even without '<', '>' and 'mailto:' */
+#define MD_FLAG_NOINDENTEDCODEBLOCKS 0x0010 /* Disable indented code blocks. (Only fenced code works.) */
+#define MD_FLAG_NOHTMLBLOCKS 0x0020 /* Disable raw HTML blocks. */
+#define MD_FLAG_NOHTMLSPANS 0x0040 /* Disable raw HTML (inline). */
+#define MD_FLAG_TABLES 0x0100 /* Enable tables extension. */
+#define MD_FLAG_STRIKETHROUGH 0x0200 /* Enable strikethrough extension. */
+#define MD_FLAG_PERMISSIVEWWWAUTOLINKS 0x0400 /* Enable WWW autolinks (even without any scheme prefix, if they begin with 'www.') */
+#define MD_FLAG_TASKLISTS 0x0800 /* Enable task list extension. */
+
+#define MD_FLAG_PERMISSIVEAUTOLINKS (MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS)
+#define MD_FLAG_NOHTML (MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS)
+
+/* Convenient sets of flags corresponding to well-known Markdown dialects.
+ *
+ * Note we may only support subset of features of the referred dialect.
+ * The constant just enables those extensions which bring us as close as
+ * possible given what features we implement.
+ *
+ * ABI compatibility note: Meaning of these can change in time as new
+ * extensions, bringing the dialect closer to the original, are implemented.
+ */
+#define MD_DIALECT_COMMONMARK 0
+#define MD_DIALECT_GITHUB (MD_FLAG_PERMISSIVEAUTOLINKS | MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH | MD_FLAG_TASKLISTS)
+
+/* Renderer structure.
+ */
+typedef struct MD_PARSER {
+ /* Reserved. Set to zero.
+ */
+ unsigned abi_version;
+
+ /* Dialect options. Bitmask of MD_FLAG_xxxx values.
+ */
+ unsigned flags;
+
+ /* Caller-provided rendering callbacks.
+ *
+ * For some block/span types, more detailed information is provided in a
+ * type-specific structure pointed by the argument 'detail'.
+ *
+ * The last argument of all callbacks, 'userdata', is just propagated from
+ * md_parse() and is available for any use by the application.
+ *
+ * Note any strings provided to the callbacks as their arguments or as
+ * members of any detail structure are generally not zero-terminated.
+ * Application has take the respective size information into account.
+ *
+ * Callbacks may abort further parsing of the document by returning non-zero.
+ */
+ int (*enter_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
+ int (*leave_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
+
+ int (*enter_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
+ int (*leave_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
+
+ int (*text)(MD_TEXTTYPE /*type*/, const MD_CHAR* /*text*/, MD_SIZE /*size*/, void* /*userdata*/);
+
+ /* Debug callback. Optional (may be NULL).
+ *
+ * If provided and something goes wrong, this function gets called.
+ * This is intended for debugging and problem diagnosis for developers;
+ * it is not intended to provide any errors suitable for displaying to an
+ * end user.
+ */
+ void (*debug_log)(const char* /*msg*/, void* /*userdata*/);
+
+ /* Reserved. Set to NULL.
+ */
+ void (*syntax)(void);
+} MD_PARSER;
+
+
+/* For backward compatibility. Do not use in new code. */
+typedef MD_PARSER MD_RENDERER;
+
+
+/* Parse the Markdown document stored in the string 'text' of size 'size'.
+ * The renderer provides callbacks to be called during the parsing so the
+ * caller can render the document on the screen or convert the Markdown
+ * to another format.
+ *
+ * Zero is returned on success. If a runtime error occurs (e.g. a memory
+ * fails), -1 is returned. If the processing is aborted due any callback
+ * returning non-zero, md_parse() the return value of the callback is returned.
+ */
+int md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userdata);
+
+
+#ifdef __cplusplus
+ } /* extern "C" { */
+#endif
+
+#endif /* MD4C_MARKDOWN_H */
diff --git a/src/3rdparty/md4c/qt_attribution.json b/src/3rdparty/md4c/qt_attribution.json
new file mode 100644
index 0000000000..fa0fd18853
--- /dev/null
+++ b/src/3rdparty/md4c/qt_attribution.json
@@ -0,0 +1,15 @@
+{
+ "Id": "md4c",
+ "Name": "MD4C",
+ "QDocModule": "qtgui",
+ "QtUsage": "Optionally used in QTextDocument if configured with textmarkdownreader.",
+
+ "Description": "A CommonMark-compliant Markdown parser.",
+ "Homepage": "https://github.com/mity/md4c",
+ "License": "MIT License",
+ "LicenseId": "MIT",
+ "LicenseFile": "LICENSE.md",
+ "Version": "0.3.3",
+ "DownloadLocation": "https://github.com/mity/md4c/releases/tag/release-0.3.3",
+ "Copyright": "Copyright © 2016-2019 Martin Mitáš"
+}
diff --git a/src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch b/src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch
new file mode 100644
index 0000000000..074b39df85
--- /dev/null
+++ b/src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch
@@ -0,0 +1,28 @@
+From ac10063196685fe6124055feb1275e13a78f562e Mon Sep 17 00:00:00 2001
+From: Mikhail Svetkin <mikhail.svetkin@qt.io>
+Date: Tue, 20 Mar 2018 14:03:54 +0100
+Subject: [PATCH] rtems: Fix pcre2 build (madvise undefined)
+
+RTEMS does not have madvise. We can use only posix_madvise
+
+Change-Id: Ia18b7cd2d7f9db84331f7e2350d060b9e85b30c8
+---
+ src/3rdparty/pcre2/src/sljit/sljitUtils.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/3rdparty/pcre2/src/sljit/sljitUtils.c b/src/3rdparty/pcre2/src/sljit/sljitUtils.c
+index 5c2a838932..2ead044b1b 100644
+--- a/src/3rdparty/pcre2/src/sljit/sljitUtils.c
++++ b/src/3rdparty/pcre2/src/sljit/sljitUtils.c
+@@ -315,7 +315,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st
+ aligned_new_start = (sljit_uw)new_start & ~sljit_page_align;
+ aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align;
+ /* If madvise is available, we release the unnecessary space. */
+-#if defined(MADV_DONTNEED)
++#if defined(MADV_DONTNEED) && !defined(__rtems__)
+ if (aligned_new_start > aligned_old_start)
+ madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED);
+ #elif defined(POSIX_MADV_DONTNEED)
+--
+2.21.0
+
diff --git a/src/3rdparty/pcre2/src/sljit/sljitUtils.c b/src/3rdparty/pcre2/src/sljit/sljitUtils.c
index 5c2a838932..2ead044b1b 100644
--- a/src/3rdparty/pcre2/src/sljit/sljitUtils.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitUtils.c
@@ -315,7 +315,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st
aligned_new_start = (sljit_uw)new_start & ~sljit_page_align;
aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align;
/* If madvise is available, we release the unnecessary space. */
-#if defined(MADV_DONTNEED)
+#if defined(MADV_DONTNEED) && !defined(__rtems__)
if (aligned_new_start > aligned_old_start)
madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED);
#elif defined(POSIX_MADV_DONTNEED)
diff --git a/src/3rdparty/sqlite.pri b/src/3rdparty/sqlite.pri
index cb8b888a6a..6405beb3d0 100644
--- a/src/3rdparty/sqlite.pri
+++ b/src/3rdparty/sqlite.pri
@@ -1,5 +1,6 @@
CONFIG(release, debug|release):DEFINES *= NDEBUG
-DEFINES += SQLITE_ENABLE_COLUMN_METADATA SQLITE_OMIT_LOAD_EXTENSION SQLITE_OMIT_COMPLETE SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_FTS5 SQLITE_ENABLE_RTREE
+QT_FOR_CONFIG += core-private
+DEFINES += SQLITE_ENABLE_COLUMN_METADATA SQLITE_OMIT_COMPLETE SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_FTS5 SQLITE_ENABLE_RTREE SQLITE_ENABLE_JSON1
!contains(CONFIG, largefile):DEFINES += SQLITE_DISABLE_LFS
qtConfig(posix_fallocate): DEFINES += HAVE_POSIX_FALLOCATE=1
winrt {
@@ -8,6 +9,7 @@ winrt {
}
qnx: DEFINES += _QNX_SOURCE
!win32:!winrt:!winphone: DEFINES += HAVE_USLEEP=1
+qtConfig(dlopen): QMAKE_USE += libdl
integrity: QMAKE_CFLAGS += -include qplatformdefs.h
INCLUDEPATH += $$PWD/sqlite
SOURCES += $$PWD/sqlite/sqlite3.c
diff --git a/src/3rdparty/wasm/DejaVuSansMono.ttf b/src/3rdparty/wasm/DejaVuSansMono.ttf
new file mode 100644
index 0000000000..029fcac35f
--- /dev/null
+++ b/src/3rdparty/wasm/DejaVuSansMono.ttf
Binary files differ
diff --git a/src/3rdparty/wasm/qt_attribution.json b/src/3rdparty/wasm/qt_attribution.json
index d569fdc167..75c5c6c49f 100644
--- a/src/3rdparty/wasm/qt_attribution.json
+++ b/src/3rdparty/wasm/qt_attribution.json
@@ -20,7 +20,7 @@
"Name": "DejaVu Fonts",
"QDocModule": "qtgui",
"QtUsage": "Used for WebAssembly platform.",
- "Files": "DejaVuSans.ttf",
+ "Files": "DejaVuSans.ttf, DejaVuSansMono.ttf",
"Description": "The DejaVu fonts are a font family based on the Vera Fonts.",
"Homepage": "https://dejavu-fonts.github.io/",
diff --git a/src/android/jar/jar.pro b/src/android/jar/jar.pro
index bda15a0a00..ac6fc79968 100644
--- a/src/android/jar/jar.pro
+++ b/src/android/jar/jar.pro
@@ -2,7 +2,6 @@ TARGET = QtAndroid
CONFIG += java
DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar
-API_VERSION = android-16
PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/
diff --git a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
index 3f74383a82..e6de354ac4 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
@@ -89,8 +89,6 @@ import android.view.inputmethod.EditorInfo;
public class ExtractStyle {
- native static int[] extractChunkInfo(byte[] chunkData);
- native static int[] extractNativeChunkInfo(int nativeChunk);
native static int[] extractChunkInfo20(byte[] chunkData);
native static int[] extractNativeChunkInfo20(long nativeChunk);
@@ -345,10 +343,7 @@ public class ExtractStyle {
}
public void drawPatch(Bitmap bmp, byte[] chunks, RectF dst, Paint paint) {
- if (Build.VERSION.SDK_INT > 19)
- chunkData = extractChunkInfo20(chunks);
- else
- chunkData = extractChunkInfo(chunks);
+ chunkData = extractChunkInfo20(chunks);
}
}
@@ -698,10 +693,6 @@ public class ExtractStyle {
json.put("thicknessRatio",gradientStateClass.getField("mThicknessRatio").getFloat(obj));
json.put("innerRadius",gradientStateClass.getField("mInnerRadius").getInt(obj));
json.put("thickness",gradientStateClass.getField("mThickness").getInt(obj));
- if (Build.VERSION.SDK_INT < 20) {
- json.put("solidColor",gradientStateClass.getField("mSolidColor").getInt(obj));
- json.put("strokeColor",gradientStateClass.getField("mStrokeColor").getInt(obj));
- }
} catch (Exception e) {
e.printStackTrace();
}
@@ -802,14 +793,7 @@ public class ExtractStyle {
Object state = getAccessibleField(NinePatchDrawable.class, "mNinePatchState").get(d);
np = (NinePatch) getAccessibleField(state.getClass(), "mNinePatch").get(state);
}
- if (Build.VERSION.SDK_INT < 19)
- return getJsonChunkInfo(extractChunkInfo((byte[]) getAccessibleField(np.getClass(), "mChunk").get(np)));
- else
- {
- if (Build.VERSION.SDK_INT > 19)
- return getJsonChunkInfo(extractNativeChunkInfo20(getAccessibleField(np.getClass(), "mNativeChunk").getLong(np)));
- return getJsonChunkInfo(extractNativeChunkInfo(getAccessibleField(np.getClass(), "mNativeChunk").getInt(np)));
- }
+ return getJsonChunkInfo(extractNativeChunkInfo20(getAccessibleField(np.getClass(), "mNativeChunk").getLong(np)));
}
class DrawableCache
@@ -1016,16 +1000,12 @@ public class ExtractStyle {
json.put("gravity", bitmapDrawable.getGravity());
json.put("tileModeX", bitmapDrawable.getTileModeX());
json.put("tileModeY", bitmapDrawable.getTileModeY());
- if (Build.VERSION.SDK_INT >= 18) {
- json.put("antialias", (Boolean) BitmapDrawable.class.getMethod("hasAntiAlias").invoke(bitmapDrawable));
- json.put("mipMap", (Boolean) BitmapDrawable.class.getMethod("hasMipMap").invoke(bitmapDrawable));
- }
- if (Build.VERSION.SDK_INT >= 21) {
- json.put("tintMode", (PorterDuff.Mode) BitmapDrawable.class.getMethod("getTintMode").invoke(bitmapDrawable));
- ColorStateList tintList = (ColorStateList) BitmapDrawable.class.getMethod("getTint").invoke(bitmapDrawable);
- if (tintList != null)
- json.put("tintList", getColorStateList(tintList));
- }
+ json.put("antialias", (Boolean) BitmapDrawable.class.getMethod("hasAntiAlias").invoke(bitmapDrawable));
+ json.put("mipMap", (Boolean) BitmapDrawable.class.getMethod("hasMipMap").invoke(bitmapDrawable));
+ json.put("tintMode", (PorterDuff.Mode) BitmapDrawable.class.getMethod("getTintMode").invoke(bitmapDrawable));
+ ColorStateList tintList = (ColorStateList) BitmapDrawable.class.getMethod("getTint").invoke(bitmapDrawable);
+ if (tintList != null)
+ json.put("tintList", getColorStateList(tintList));
} catch (Exception e) {
e.printStackTrace();
}
@@ -1758,10 +1738,8 @@ public class ExtractStyle {
json.put("Switch_switchPadding", a.getDimensionPixelSize(getField(styleableClass, "Switch_switchPadding"), 0));
json.put("Switch_thumbTextPadding", a.getDimensionPixelSize(getField(styleableClass, "Switch_thumbTextPadding"), 0));
- if (Build.VERSION.SDK_INT >= 21) {
- json.put("Switch_showText", a.getBoolean(getField(styleableClass, "Switch_showText"), true));
- json.put("Switch_splitTrack", a.getBoolean(getField(styleableClass, "Switch_splitTrack"), false));
- }
+ json.put("Switch_showText", a.getBoolean(getField(styleableClass, "Switch_showText"), true));
+ json.put("Switch_splitTrack", a.getBoolean(getField(styleableClass, "Switch_splitTrack"), false));
a.recycle();
jsonWriter.name(styleName).value(json);
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index f776888652..2df2ed9a1d 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -82,6 +82,7 @@ import android.view.inputmethod.InputMethodManager;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.PopupMenu;
+import android.hardware.display.DisplayManager;
import java.io.BufferedReader;
import java.io.DataOutputStream;
@@ -161,15 +162,13 @@ public class QtActivityDelegate
m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
try {
- if (Build.VERSION.SDK_INT >= 19) {
- int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
- flags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
- flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
- flags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
- flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
- flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY").getInt(null);
- m_activity.getWindow().getDecorView().setSystemUiVisibility(flags | View.INVISIBLE);
- }
+ int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ flags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+ flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ flags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
+ flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY").getInt(null);
+ m_activity.getWindow().getDecorView().setSystemUiVisibility(flags | View.INVISIBLE);
} catch (Exception e) {
e.printStackTrace();
}
@@ -661,6 +660,28 @@ public class QtActivityDelegate
} catch (Exception e) {
e.printStackTrace();
}
+
+ DisplayManager.DisplayListener displayListener = new DisplayManager.DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) { }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ m_currentRotation = m_activity.getWindowManager().getDefaultDisplay().getRotation();
+ QtNative.handleOrientationChanged(m_currentRotation, m_nativeOrientation);
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) { }
+ };
+
+ try {
+ DisplayManager displayManager = (DisplayManager) m_activity.getSystemService(Context.DISPLAY_SERVICE);
+ displayManager.registerDisplayListener(displayListener, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
m_mainLib = QtNative.loadMainLibrary(m_mainLib, nativeLibsDir);
return m_mainLib != null;
}
@@ -857,13 +878,6 @@ public class QtActivityDelegate
} catch (Exception e) {
e.printStackTrace();
}
-
- int rotation = m_activity.getWindowManager().getDefaultDisplay().getRotation();
- if (rotation != m_currentRotation) {
- QtNative.handleOrientationChanged(rotation, m_nativeOrientation);
- }
-
- m_currentRotation = rotation;
}
public void onDestroy()
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index 1d2b70ab5f..9679fd40f4 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -41,6 +41,7 @@
package org.qtproject.qt5.android;
import java.io.File;
+import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.concurrent.Semaphore;
@@ -59,6 +60,7 @@ import android.os.Looper;
import android.content.ClipboardManager;
import android.content.ClipboardManager.OnPrimaryClipChangedListener;
import android.content.ClipData;
+import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
@@ -168,6 +170,17 @@ public class QtNative
return ok;
}
+ public static int openFdForContentUrl(Context context, String contentUrl, String openMode)
+ {
+ try {
+ ContentResolver resolver = context.getContentResolver();
+ ParcelFileDescriptor fdDesc = resolver.openFileDescriptor(Uri.parse(contentUrl), openMode);
+ return fdDesc.detachFd();
+ } catch (FileNotFoundException e) {
+ return -1;
+ }
+ }
+
// this method loads full path libs
public static void loadQtLibraries(final ArrayList<String> libraries)
{
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java
index 759daf4393..6beb5e3161 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java
@@ -132,7 +132,7 @@ public class QtActivityLoader extends QtLoader {
return;
}
- if (Build.VERSION.SDK_INT < 16) {
+ if (Build.VERSION.SDK_INT < 21) {
// fatal error, show the error and quit
AlertDialog errorDialog = new AlertDialog.Builder(m_activity).create();
if (m_contextInfo.metaData.containsKey("android.app.unsupported_android_version"))
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
index 9d5578ed6d..d3b0600b2f 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
@@ -159,6 +159,9 @@ public abstract class QtLoader {
protected ComponentInfo m_contextInfo;
private Class<?> m_delegateClass;
+ private static ArrayList<FileOutputStream> m_fileOutputStreams = new ArrayList<FileOutputStream>();
+ // List of open file streams associated with files copied during installation.
+
QtLoader(ContextWrapper context, Class<?> clazz) {
m_context = context;
m_delegateClass = clazz;
@@ -357,7 +360,7 @@ public abstract class QtLoader {
AssetManager assetsManager = m_context.getAssets();
InputStream inputStream = null;
- OutputStream outputStream = null;
+ FileOutputStream outputStream = null;
try {
inputStream = assetsManager.open(source);
outputStream = new FileOutputStream(destinationFile);
@@ -369,8 +372,12 @@ public abstract class QtLoader {
inputStream.close();
if (outputStream != null)
- outputStream.close();
+ // Ensure that the buffered data is flushed to the OS for writing.
+ outputStream.flush();
}
+ // Mark the output stream as still needing to be written to physical disk.
+ // The output stream will be closed after this sync completes.
+ m_fileOutputStreams.add(outputStream);
}
private static void createBundledBinary(String source, String destination)
@@ -388,7 +395,7 @@ public abstract class QtLoader {
destinationFile.createNewFile();
InputStream inputStream = null;
- OutputStream outputStream = null;
+ FileOutputStream outputStream = null;
try {
inputStream = new FileInputStream(source);
outputStream = new FileOutputStream(destinationFile);
@@ -400,8 +407,12 @@ public abstract class QtLoader {
inputStream.close();
if (outputStream != null)
- outputStream.close();
+ // Ensure that the buffered data is flushed to the OS for writing.
+ outputStream.flush();
}
+ // Mark the output stream as still needing to be written to physical disk.
+ // The output stream will be closed after this sync completes.
+ m_fileOutputStreams.add(outputStream);
}
private boolean cleanCacheIfNecessary(String pluginsPrefix, long packageVersion)
@@ -450,27 +461,6 @@ public abstract class QtLoader {
return;
{
- File versionFile = new File(pluginsPrefix + "cache.version");
-
- File parentDirectory = versionFile.getParentFile();
- if (!parentDirectory.exists())
- parentDirectory.mkdirs();
-
- versionFile.createNewFile();
-
- DataOutputStream outputStream = null;
- try {
- outputStream = new DataOutputStream(new FileOutputStream(versionFile));
- outputStream.writeLong(packageVersion);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (outputStream != null)
- outputStream.close();
- }
- }
-
- {
// why can't we load the plugins directly from libs ?!?!
String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY;
if (m_contextInfo.metaData.containsKey(key)) {
@@ -499,6 +489,66 @@ public abstract class QtLoader {
}
}
+
+ // The Java compiler must be assured that variables belonging to this parent thread will not
+ // go out of scope during the runtime of the spawned thread (since in general spawned
+ // threads can outlive their parent threads). Copy variables and declare as 'final' before
+ // passing into the spawned thread.
+ final String pluginsPrefixFinal = pluginsPrefix;
+ final long packageVersionFinal = packageVersion;
+
+ // Spawn a worker thread to write all installed files to physical disk and indicate
+ // successful installation by creating the 'cache.version' file.
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ finalizeInstallation(pluginsPrefixFinal, packageVersionFinal);
+ } catch (Exception e) {
+ Log.e(QtApplication.QtTAG, e.getMessage());
+ e.printStackTrace();
+ return;
+ }
+ }
+ }).start();
+ }
+
+ private void finalizeInstallation(String pluginsPrefix, long packageVersion)
+ throws IOException
+ {
+ {
+ // Write all installed files to physical disk and close each output stream
+ for (FileOutputStream fileOutputStream : m_fileOutputStreams) {
+ fileOutputStream.getFD().sync();
+ fileOutputStream.close();
+ }
+
+ m_fileOutputStreams.clear();
+ }
+
+ {
+ // Create 'cache.version' file
+
+ File versionFile = new File(pluginsPrefix + "cache.version");
+
+ File parentDirectory = versionFile.getParentFile();
+ if (!parentDirectory.exists())
+ parentDirectory.mkdirs();
+
+ versionFile.createNewFile();
+
+ DataOutputStream outputStream = null;
+ try {
+ outputStream = new DataOutputStream(new FileOutputStream(versionFile));
+ outputStream.writeLong(packageVersion);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (outputStream != null)
+ outputStream.close();
+ }
+ }
+
}
private void deleteRecursively(File directory)
diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml
index b5b26758d9..aed8a3c888 100644
--- a/src/android/templates/AndroidManifest.xml
+++ b/src/android/templates/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:installLocation="auto">
- <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="28"/>
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
diff --git a/src/android/templates/build.gradle b/src/android/templates/build.gradle
index 989d0792cf..5754c82708 100644
--- a/src/android/templates/build.gradle
+++ b/src/android/templates/build.gradle
@@ -44,7 +44,7 @@ android {
java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qt5AndroidDir + '/res', 'res']
- resources.srcDirs = ['src']
+ resources.srcDirs = ['resources']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri
index 5c521281a6..cafae0e742 100644
--- a/src/angle/src/config.pri
+++ b/src/angle/src/config.pri
@@ -79,10 +79,9 @@ msvc {
# /Oy: Omits frame pointer (x86 only).
# /Gy: Enables function-level linking.
# /GS: Buffers security check.
- # /Gm-: Disable minimal rebuild.
# /RTC1: Run time error checking
- QMAKE_CFLAGS_RELEASE += -Oy- -Gy -GS -Gm-
- QMAKE_CFLAGS_DEBUG += -Oy- -Gy -GS -Gm- -RTC1
+ QMAKE_CFLAGS_RELEASE += -Oy- -Gy -GS
+ QMAKE_CFLAGS_DEBUG += -Oy- -Gy -GS -RTC1
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -Zi $$QMAKE_CFLAGS_RELEASE
QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
diff --git a/src/concurrent/qtconcurrentcompilertest.h b/src/concurrent/qtconcurrentcompilertest.h
index cddfd06ca1..72cf1670a0 100644
--- a/src/concurrent/qtconcurrentcompilertest.h
+++ b/src/concurrent/qtconcurrentcompilertest.h
@@ -52,7 +52,7 @@ template<class T>
class HasResultType {
typedef char Yes;
typedef void *No;
- template<typename U> static Yes test(int, const typename U::result_type * = 0);
+ template<typename U> static Yes test(int, const typename U::result_type * = nullptr);
template<typename U> static No test(double);
public:
enum { Value = (sizeof(test<T>(0)) == sizeof(Yes)) };
diff --git a/src/concurrent/qtconcurrentfilterkernel.h b/src/concurrent/qtconcurrentfilterkernel.h
index 9cbea2e671..e921a3d51a 100644
--- a/src/concurrent/qtconcurrentfilterkernel.h
+++ b/src/concurrent/qtconcurrentfilterkernel.h
@@ -266,7 +266,7 @@ public:
if (keep(*it))
this->reportResult(&(*it), index);
else
- this->reportResult(0, index);
+ this->reportResult(nullptr, index);
return false;
}
diff --git a/src/concurrent/qtconcurrentfunctionwrappers.h b/src/concurrent/qtconcurrentfunctionwrappers.h
index 734bb29df1..7ba6720e03 100644
--- a/src/concurrent/qtconcurrentfunctionwrappers.h
+++ b/src/concurrent/qtconcurrentfunctionwrappers.h
@@ -225,13 +225,11 @@ struct PushBackWrapper
return c.push_back(u);
}
-#ifdef Q_COMPILER_RVALUE_REFS
template <class C, class U>
inline void operator()(C &c, U &&u) const
{
return c.push_back(u);
}
-#endif
};
template <typename Functor, bool foo = HasResultType<Functor>::Value>
diff --git a/src/concurrent/qtconcurrentiteratekernel.h b/src/concurrent/qtconcurrentiteratekernel.h
index 89fd3d2592..3095c9ff52 100644
--- a/src/concurrent/qtconcurrentiteratekernel.h
+++ b/src/concurrent/qtconcurrentiteratekernel.h
@@ -206,9 +206,9 @@ public:
bool shouldStartThread() override
{
if (forIteration)
- return (currentIndex.load() < iterationCount) && !this->shouldThrottleThread();
+ return (currentIndex.loadRelaxed() < iterationCount) && !this->shouldThrottleThread();
else // whileIteration
- return (iteratorThreads.load() == 0);
+ return (iteratorThreads.loadRelaxed() == 0);
}
ThreadFunctionResult threadFunction() override
@@ -230,7 +230,7 @@ public:
const int currentBlockSize = blockSizeManager.blockSize();
- if (currentIndex.load() >= iterationCount)
+ if (currentIndex.loadRelaxed() >= iterationCount)
break;
// Atomically reserve a block of iterationCount for this thread.
@@ -261,7 +261,7 @@ public:
// Report progress if progress reporting enabled.
if (progressReportingEnabled) {
completed.fetchAndAddAcquire(finalBlockSize);
- this->setProgressValue(this->completed.load());
+ this->setProgressValue(this->completed.loadRelaxed());
}
if (this->shouldThrottleThread())
diff --git a/src/concurrent/qtconcurrentmapkernel.h b/src/concurrent/qtconcurrentmapkernel.h
index 3424124118..87fcf30cf9 100644
--- a/src/concurrent/qtconcurrentmapkernel.h
+++ b/src/concurrent/qtconcurrentmapkernel.h
@@ -74,7 +74,7 @@ public:
Iterator it = sequenceBeginIterator;
std::advance(it, beginIndex);
for (int i = beginIndex; i < endIndex; ++i) {
- runIteration(it, i, 0);
+ runIteration(it, i, nullptr);
std::advance(it, 1);
}
diff --git a/src/concurrent/qtconcurrentrun.h b/src/concurrent/qtconcurrentrun.h
index 6001010a78..22dae70460 100644
--- a/src/concurrent/qtconcurrentrun.h
+++ b/src/concurrent/qtconcurrentrun.h
@@ -99,8 +99,6 @@ QFuture<T> run(T (*functionPointer)(Param1, Param2, Param3, Param4, Param5), con
return (new StoredFunctorCall5<T, T (*)(Param1, Param2, Param3, Param4, Param5), Arg1, Arg2, Arg3, Arg4, Arg5>(functionPointer, arg1, arg2, arg3, arg4, arg5))->start();
}
-#if defined(Q_COMPILER_DECLTYPE) && defined(Q_COMPILER_AUTO_FUNCTION)
-
template <typename Functor>
auto run(Functor functor) -> typename std::enable_if<!QtPrivate::HasResultType<Functor>::Value, QFuture<decltype(functor())>>::type
{
@@ -148,8 +146,6 @@ auto run(Functor functor, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3,
return (new StoredFunctorCall5<result_type, Functor, Arg1, Arg2, Arg3, Arg4, Arg5>(functor, arg1, arg2, arg3, arg4, arg5))->start();
}
-#endif
-
template <typename FunctionObject>
QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject)
{
@@ -370,8 +366,6 @@ QFuture<T> run(QThreadPool *pool, T (*functionPointer)(Param1, Param2, Param3, P
return (new StoredFunctorCall5<T, T (*)(Param1, Param2, Param3, Param4, Param5), Arg1, Arg2, Arg3, Arg4, Arg5>(functionPointer, arg1, arg2, arg3, arg4, arg5))->start(pool);
}
-#if defined(Q_COMPILER_DECLTYPE) && defined(Q_COMPILER_AUTO_FUNCTION)
-
template <typename Functor>
auto run(QThreadPool *pool, Functor functor) -> typename std::enable_if<!QtPrivate::HasResultType<Functor>::Value, QFuture<decltype(functor())>>::type
{
@@ -419,8 +413,6 @@ auto run(QThreadPool *pool, Functor functor, const Arg1 &arg1, const Arg2 &arg2,
return (new StoredFunctorCall5<result_type, Functor, Arg1, Arg2, Arg3, Arg4, Arg5>(functor, arg1, arg2, arg3, arg4, arg5))->start(pool);
}
-#endif
-
template <typename FunctionObject>
QFuture<typename FunctionObject::result_type> run(QThreadPool *pool, FunctionObject functionObject)
{
diff --git a/src/concurrent/qtconcurrentthreadengine.cpp b/src/concurrent/qtconcurrentthreadengine.cpp
index 968720cbbe..7f91a2ba68 100644
--- a/src/concurrent/qtconcurrentthreadengine.cpp
+++ b/src/concurrent/qtconcurrentthreadengine.cpp
@@ -91,7 +91,7 @@ ThreadEngineBarrier::ThreadEngineBarrier()
void ThreadEngineBarrier::acquire()
{
forever {
- int localCount = count.load();
+ int localCount = count.loadRelaxed();
if (localCount < 0) {
if (count.testAndSetOrdered(localCount, localCount -1))
return;
@@ -105,7 +105,7 @@ void ThreadEngineBarrier::acquire()
int ThreadEngineBarrier::release()
{
forever {
- int localCount = count.load();
+ int localCount = count.loadRelaxed();
if (localCount == -1) {
if (count.testAndSetOrdered(-1, 0)) {
semaphore.release();
@@ -125,7 +125,7 @@ int ThreadEngineBarrier::release()
void ThreadEngineBarrier::wait()
{
forever {
- int localCount = count.load();
+ int localCount = count.loadRelaxed();
if (localCount == 0)
return;
@@ -139,7 +139,7 @@ void ThreadEngineBarrier::wait()
int ThreadEngineBarrier::currentCount()
{
- return count.load();
+ return count.loadRelaxed();
}
// releases a thread, unless this is the last thread.
@@ -147,7 +147,7 @@ int ThreadEngineBarrier::currentCount()
bool ThreadEngineBarrier::releaseUnlessLast()
{
forever {
- int localCount = count.load();
+ int localCount = count.loadRelaxed();
if (qAbs(localCount) == 1) {
return false;
} else if (localCount < 0) {
diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake
index 3a60b8e0d2..0f006fe1e3 100644
--- a/src/corelib/Qt5CoreMacros.cmake
+++ b/src/corelib/Qt5CoreMacros.cmake
@@ -375,7 +375,7 @@ if (NOT CMAKE_VERSION VERSION_LESS 2.8.9)
if (NOT Qt5${_module}_FOUND)
find_package(Qt5${_module} PATHS "${_Qt5_COMPONENT_PATH}" NO_DEFAULT_PATH)
if (NOT Qt5${_module}_FOUND)
- message(FATAL_ERROR "Can not use \"${_module}\" module which has not yet been found.")
+ message(FATAL_ERROR "Cannot use \"${_module}\" module which has not yet been found.")
endif()
endif()
target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES})
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index 42308b78fb..46b01449d4 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -152,6 +152,7 @@
#include <QtCore/qthreadstorage.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qpointer.h>
+#include <QtCore/qscopedvaluerollback.h>
#define DEFAULT_TIMER_INTERVAL 16
#define PAUSE_TIMER_COARSE_THRESHOLD 2000
@@ -315,14 +316,13 @@ void QUnifiedTimer::updateAnimationTimers(qint64 currentTick)
//* it might happen in some cases that the delta is negative because the animation driver
// advances faster than time.elapsed()
if (delta > 0) {
- insideTick = true;
+ QScopedValueRollback<bool> guard(insideTick, true);
if (profilerCallback)
profilerCallback(delta);
for (currentAnimationIdx = 0; currentAnimationIdx < animationTimers.count(); ++currentAnimationIdx) {
QAbstractAnimationTimer *animation = animationTimers.at(currentAnimationIdx);
animation->updateAnimationsTime(delta);
}
- insideTick = false;
currentAnimationIdx = 0;
}
}
@@ -361,10 +361,11 @@ void QUnifiedTimer::localRestart()
void QUnifiedTimer::restart()
{
- insideRestart = true;
- for (int i = 0; i < animationTimers.count(); ++i)
- animationTimers.at(i)->restartAnimationTimer();
- insideRestart = false;
+ {
+ QScopedValueRollback<bool> guard(insideRestart, true);
+ for (int i = 0; i < animationTimers.count(); ++i)
+ animationTimers.at(i)->restartAnimationTimer();
+ }
localRestart();
}
@@ -599,14 +600,13 @@ void QAnimationTimer::updateAnimationsTime(qint64 delta)
//it might happen in some cases that the time doesn't change because events are delayed
//when the CPU load is high
if (delta) {
- insideTick = true;
+ QScopedValueRollback<bool> guard(insideTick, true);
for (currentAnimationIdx = 0; currentAnimationIdx < animations.count(); ++currentAnimationIdx) {
QAbstractAnimation *animation = animations.at(currentAnimationIdx);
int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
+ (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
animation->setCurrentTime(elapsed);
}
- insideTick = false;
currentAnimationIdx = 0;
}
}
@@ -773,6 +773,7 @@ QAnimationDriver::~QAnimationDriver()
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
Sets the time at which an animation driver should start at.
@@ -799,6 +800,7 @@ qint64 QAnimationDriver::startTime() const
{
return 0;
}
+#endif
/*!
@@ -1065,6 +1067,8 @@ QAbstractAnimation::~QAbstractAnimation()
if (oldState == QAbstractAnimation::Running)
QAnimationTimer::unregisterAnimation(this);
}
+ if (d->group)
+ d->group->removeAnimation(this);
}
/*!
diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h
index 25b5726d56..7f2577d7f7 100644
--- a/src/corelib/animation/qabstractanimation.h
+++ b/src/corelib/animation/qabstractanimation.h
@@ -147,9 +147,10 @@ public:
virtual qint64 elapsed() const;
- // ### Qt6: Remove these two functions
- void setStartTime(qint64 startTime);
- qint64 startTime() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED void setStartTime(qint64 startTime);
+ QT_DEPRECATED qint64 startTime() const;
+#endif
Q_SIGNALS:
void started();
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
index 3b6e8d6cc4..037d3be74f 100644
--- a/src/corelib/animation/qabstractanimation_p.h
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -78,7 +78,7 @@ public:
hasRegisteredTimer(false),
isPause(false),
isGroup(false),
- group(0)
+ group(nullptr)
{
}
diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp
index f47d99eb68..ed40817222 100644
--- a/src/corelib/animation/qanimationgroup.cpp
+++ b/src/corelib/animation/qanimationgroup.cpp
@@ -113,6 +113,11 @@ QAnimationGroup::QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent)
*/
QAnimationGroup::~QAnimationGroup()
{
+ Q_D(QAnimationGroup);
+ // We need to clear the animations now while we are still a valid QAnimationGroup.
+ // If we wait until ~QObject() the QAbstractAnimation's pointer back to us would
+ // point to a QObject, not a valid QAnimationGroup.
+ d->clear(true);
}
/*!
@@ -256,7 +261,7 @@ QAbstractAnimation *QAnimationGroup::takeAnimation(int index)
void QAnimationGroup::clear()
{
Q_D(QAnimationGroup);
- qDeleteAll(d->animations);
+ d->clear(false);
}
/*!
@@ -284,6 +289,24 @@ bool QAnimationGroup::event(QEvent *event)
return QAbstractAnimation::event(event);
}
+void QAnimationGroupPrivate::clear(bool onDestruction)
+{
+ const QList<QAbstractAnimation *> animationsCopy = animations; // taking a copy
+ animations.clear();
+ // Clearing backwards so the indices doesn't change while we remove animations.
+ for (int i = animationsCopy.count() - 1; i >= 0; --i) {
+ QAbstractAnimation *animation = animationsCopy.at(i);
+ animation->setParent(nullptr);
+ QAbstractAnimationPrivate::get(animation)->group = nullptr;
+ // If we are in ~QAnimationGroup() it is not safe to called the virtual
+ // animationRemoved method, which can still be a method in a
+ // QAnimationGroupPrivate derived class that assumes q_ptr is still
+ // a valid derived class of QAnimationGroup.
+ if (!onDestruction)
+ animationRemoved(i, animation);
+ delete animation;
+ }
+}
void QAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *)
{
diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h
index ff759d11fd..4d1d690e69 100644
--- a/src/corelib/animation/qanimationgroup_p.h
+++ b/src/corelib/animation/qanimationgroup_p.h
@@ -73,10 +73,12 @@ public:
virtual void animationInsertedAt(int) { }
virtual void animationRemoved(int, QAbstractAnimation *);
+ void clear(bool onDestruction);
+
void disconnectUncontrolledAnimation(QAbstractAnimation *anim)
{
//0 for the signal here because we might be called from the animation destructor
- QObject::disconnect(anim, 0, q_func(), SLOT(_q_uncontrolledAnimationFinished()));
+ QObject::disconnect(anim, nullptr, q_func(), SLOT(_q_uncontrolledAnimationFinished()));
}
void connectUncontrolledAnimation(QAbstractAnimation *anim)
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
index 28c03553c5..a1baa112fc 100644
--- a/src/corelib/animation/qpropertyanimation.cpp
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -277,15 +277,20 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState,
if (oldState == Stopped) {
d->setDefaultStartEndValue(d->targetValue->property(d->propertyName.constData()));
//let's check if we have a start value and an end value
+ const char *what = nullptr;
if (!startValue().isValid() && (d->direction == Backward || !d->defaultStartEndValue.isValid())) {
- qWarning("QPropertyAnimation::updateState (%s, %s, %s): starting an animation without start value",
- d->propertyName.constData(), d->target.data()->metaObject()->className(),
- qPrintable(d->target.data()->objectName()));
+ what = "start";
}
if (!endValue().isValid() && (d->direction == Forward || !d->defaultStartEndValue.isValid())) {
- qWarning("QPropertyAnimation::updateState (%s, %s, %s): starting an animation without end value",
+ if (what)
+ what = "start and end";
+ else
+ what = "end";
+ }
+ if (Q_UNLIKELY(what)) {
+ qWarning("QPropertyAnimation::updateState (%s, %s, %ls): starting an animation without %s value",
d->propertyName.constData(), d->target.data()->metaObject()->className(),
- qPrintable(d->target.data()->objectName()));
+ qUtf16Printable(d->target.data()->objectName()), what);
}
}
} else if (hash.value(key) == this) {
@@ -303,6 +308,6 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState,
}
}
-#include "moc_qpropertyanimation.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qpropertyanimation.cpp"
diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h
index 479762f573..cbd3ce287d 100644
--- a/src/corelib/animation/qpropertyanimation_p.h
+++ b/src/corelib/animation/qpropertyanimation_p.h
@@ -64,7 +64,7 @@ class QPropertyAnimationPrivate : public QVariantAnimationPrivate
Q_DECLARE_PUBLIC(QPropertyAnimation)
public:
QPropertyAnimationPrivate()
- : targetValue(0), propertyType(0), propertyIndex(-1)
+ : targetValue(nullptr), propertyType(0), propertyIndex(-1)
{
}
diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp
index 150e74d7d6..66e346a2fe 100644
--- a/src/corelib/animation/qsequentialanimationgroup.cpp
+++ b/src/corelib/animation/qsequentialanimationgroup.cpp
@@ -532,7 +532,8 @@ void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnim
Q_Q(QSequentialAnimationGroup);
QAnimationGroupPrivate::animationRemoved(index, anim);
- Q_ASSERT(currentAnimation); // currentAnimation should always be set
+ if (!currentAnimation)
+ return;
if (actualDuration.size() > index)
actualDuration.removeAt(index);
diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h
index 88dac4f566..c082d6b524 100644
--- a/src/corelib/animation/qsequentialanimationgroup_p.h
+++ b/src/corelib/animation/qsequentialanimationgroup_p.h
@@ -63,7 +63,7 @@ class QSequentialAnimationGroupPrivate : public QAnimationGroupPrivate
Q_DECLARE_PUBLIC(QSequentialAnimationGroup)
public:
QSequentialAnimationGroupPrivate()
- : currentAnimation(0), currentAnimationIndex(-1), lastLoop(0)
+ : currentAnimation(nullptr), currentAnimationIndex(-1), lastLoop(0)
{ }
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index e935ac711e..01a699c5dc 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -283,11 +283,11 @@ void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress)
qSwap(currentValue, ret);
q->updateCurrentValue(currentValue);
static QBasicAtomicInt changedSignalIndex = Q_BASIC_ATOMIC_INITIALIZER(0);
- if (!changedSignalIndex.load()) {
+ if (!changedSignalIndex.loadRelaxed()) {
//we keep the mask so that we emit valueChanged only when needed (for performance reasons)
changedSignalIndex.testAndSetRelaxed(0, signalIndex("valueChanged(QVariant)"));
}
- if (isSignalConnected(changedSignalIndex.load()) && currentValue != ret) {
+ if (isSignalConnected(changedSignalIndex.loadRelaxed()) && currentValue != ret) {
//the value has changed
emit q->valueChanged(currentValue);
}
@@ -399,7 +399,7 @@ static QBasicMutex registeredInterpolatorsMutex;
Registers a custom interpolator \a func for the template type \c{T}.
The interpolator has to be registered before the animation is constructed.
- To unregister (and use the default interpolator) set \a func to 0.
+ To unregister (and use the default interpolator) set \a func to \nullptr.
*/
/*!
@@ -416,7 +416,7 @@ static QBasicMutex registeredInterpolatorsMutex;
* \internal
* Registers a custom interpolator \a func for the specific \a interpolationType.
* The interpolator has to be registered before the animation is constructed.
- * To unregister (and use the default interpolator) set \a func to 0.
+ * To unregister (and use the default interpolator) set \a func to \nullptr.
*/
void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator func, int interpolationType)
{
diff --git a/src/corelib/codecs/qbig5codec_p.h b/src/corelib/codecs/qbig5codec_p.h
index 2db8377ee3..c17afae1c4 100644
--- a/src/corelib/codecs/qbig5codec_p.h
+++ b/src/corelib/codecs/qbig5codec_p.h
@@ -69,12 +69,12 @@ public:
static QList<QByteArray> _aliases();
static int _mibEnum();
- QByteArray name() const { return _name(); }
- QList<QByteArray> aliases() const { return _aliases(); }
- int mibEnum() const { return _mibEnum(); }
+ QByteArray name() const override { return _name(); }
+ QList<QByteArray> aliases() const override { return _aliases(); }
+ int mibEnum() const override { return _mibEnum(); }
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
};
class QBig5hkscsCodec : public QTextCodec {
@@ -83,12 +83,12 @@ public:
static QList<QByteArray> _aliases() { return QList<QByteArray>(); }
static int _mibEnum();
- QByteArray name() const { return _name(); }
- QList<QByteArray> aliases() const { return _aliases(); }
- int mibEnum() const { return _mibEnum(); }
+ QByteArray name() const override { return _name(); }
+ QList<QByteArray> aliases() const override { return _aliases(); }
+ int mibEnum() const override { return _mibEnum(); }
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
};
QT_END_NAMESPACE
diff --git a/src/corelib/codecs/qlatincodec.cpp b/src/corelib/codecs/qlatincodec.cpp
index 1b53d26ef4..463c5a56ae 100644
--- a/src/corelib/codecs/qlatincodec.cpp
+++ b/src/corelib/codecs/qlatincodec.cpp
@@ -48,7 +48,7 @@ QLatin1Codec::~QLatin1Codec()
QString QLatin1Codec::convertToUnicode(const char *chars, int len, ConverterState *) const
{
- if (chars == 0)
+ if (chars == nullptr)
return QString();
return QString::fromLatin1(chars, len);
@@ -104,7 +104,7 @@ QLatin15Codec::~QLatin15Codec()
QString QLatin15Codec::convertToUnicode(const char* chars, int len, ConverterState *) const
{
- if (chars == 0)
+ if (chars == nullptr)
return QString();
QString str = QString::fromLatin1(chars, len);
diff --git a/src/corelib/codecs/qsimplecodec.cpp b/src/corelib/codecs/qsimplecodec.cpp
index 9ab545d783..16a9b8a7c3 100644
--- a/src/corelib/codecs/qsimplecodec.cpp
+++ b/src/corelib/codecs/qsimplecodec.cpp
@@ -610,7 +610,7 @@ QSimpleTextCodec::QSimpleTextCodec(int i) : forwardIndex(i), reverseMap(0)
QSimpleTextCodec::~QSimpleTextCodec()
{
- delete reverseMap.load();
+ delete reverseMap.loadAcquire();
}
static QByteArray *buildReverseMap(int forwardIndex)
@@ -662,12 +662,12 @@ QByteArray QSimpleTextCodec::convertFromUnicode(const QChar *in, int length, Con
const char replacement = (state && state->flags & ConvertInvalidToNull) ? 0 : '?';
int invalid = 0;
- QByteArray *rmap = reverseMap.load();
+ QByteArray *rmap = reverseMap.loadAcquire();
if (!rmap){
rmap = buildReverseMap(this->forwardIndex);
if (!reverseMap.testAndSetRelease(0, rmap)) {
delete rmap;
- rmap = reverseMap.load();
+ rmap = reverseMap.loadAcquire();
}
}
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index eb05446beb..85cfcdbf48 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -159,7 +159,7 @@ static QTextCodec *setupLocaleMapper()
{
QCoreGlobalData *globalData = QCoreGlobalData::instance();
- QTextCodec *locale = 0;
+ QTextCodec *locale = nullptr;
{
QMutexLocker locker(textCodecsMutex());
@@ -208,7 +208,7 @@ static QTextCodec *setupLocaleMapper()
// First part is getting that locale name. First try setlocale() which
// definitely knows it, but since we cannot fully trust it, get ready
// to fall back to environment variables.
- const QByteArray ctype = setlocale(LC_CTYPE, 0);
+ const QByteArray ctype = setlocale(LC_CTYPE, nullptr);
// Get the first nonempty value from $LC_ALL, $LC_CTYPE, and $LANG
// environment variables.
@@ -505,9 +505,9 @@ QTextCodec::~QTextCodec()
globalData->allCodecs.removeOne(this);
- auto it = globalData->codecCache.cbegin();
+ auto it = globalData->codecCache.begin();
- while (it != globalData->codecCache.cend()) {
+ while (it != globalData->codecCache.end()) {
if (it.value() == this)
it = globalData->codecCache.erase(it);
else
@@ -532,13 +532,13 @@ QTextCodec::~QTextCodec()
QTextCodec *QTextCodec::codecForName(const QByteArray &name)
{
if (name.isEmpty())
- return 0;
+ return nullptr;
QMutexLocker locker(textCodecsMutex());
QCoreGlobalData *globalData = QCoreGlobalData::instance();
if (!globalData)
- return 0;
+ return nullptr;
setup();
#if !QT_CONFIG(icu)
@@ -567,7 +567,7 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name)
}
}
- return 0;
+ return nullptr;
#else
return QIcuCodec::codecForNameUnlocked(name);
#endif
@@ -585,7 +585,7 @@ QTextCodec* QTextCodec::codecForMib(int mib)
QCoreGlobalData *globalData = QCoreGlobalData::instance();
if (!globalData)
- return 0;
+ return nullptr;
if (globalData->allCodecs.isEmpty())
setup();
@@ -611,7 +611,7 @@ QTextCodec* QTextCodec::codecForMib(int mib)
#if QT_CONFIG(icu)
return QIcuCodec::codecForMibUnlocked(mib);
#else
- return 0;
+ return nullptr;
#endif
}
@@ -678,7 +678,7 @@ QList<int> QTextCodec::availableMibs()
\nonreentrant
Set the codec to \a c; this will be returned by
- codecForLocale(). If \a c is a null pointer, the codec is reset to
+ codecForLocale(). If \a c is \nullptr, the codec is reset to
the default.
This might be needed for some applications that want to use their
@@ -695,18 +695,16 @@ void QTextCodec::setCodecForLocale(QTextCodec *c)
\threadsafe
Returns a pointer to the codec most suitable for this locale.
- On Windows, the codec will be based on a system locale. On Unix
- systems, the codec will might fall back to using the \e iconv
- library if no builtin codec for the locale can be found.
-
- Note that in these cases the codec's name will be "System".
+ The codec will be retrieved from ICU where that backend is in use, otherwise
+ it may be obtained from an OS-specific API. In the latter case, the codec's
+ name may be "System".
*/
QTextCodec* QTextCodec::codecForLocale()
{
QCoreGlobalData *globalData = QCoreGlobalData::instance();
if (!globalData)
- return 0;
+ return nullptr;
QTextCodec *codec = globalData->codecForLocale.loadAcquire();
if (!codec) {
@@ -766,7 +764,7 @@ QList<QByteArray> QTextCodec::aliases() const
encoding of the subclass to Unicode, and returns the result in a
QString.
- \a state can be 0, in which case the conversion is stateless and
+ \a state can be \nullptr, in which case the conversion is stateless and
default conversion rules should be used. If state is not 0, the
codec should save the state after the conversion in \a state, and
adjust the \c remainingChars and \c invalidChars members of the struct.
@@ -782,7 +780,7 @@ QList<QByteArray> QTextCodec::aliases() const
from Unicode to the encoding of the subclass, and returns the result
in a QByteArray.
- \a state can be 0 in which case the conversion is stateless and
+ \a state can be \nullptr in which case the conversion is stateless and
default conversion rules should be used. If state is not 0, the
codec should save the state after the conversion in \a state, and
adjust the \c remainingChars and \c invalidChars members of the struct.
@@ -832,7 +830,7 @@ QTextEncoder* QTextCodec::makeEncoder(QTextCodec::ConversionFlags flags) const
*/
QByteArray QTextCodec::fromUnicode(const QString& str) const
{
- return convertFromUnicode(str.constData(), str.length(), 0);
+ return convertFromUnicode(str.constData(), str.length(), nullptr);
}
#endif
@@ -865,7 +863,7 @@ QByteArray QTextCodec::fromUnicode(QStringView str) const
*/
QString QTextCodec::toUnicode(const QByteArray& a) const
{
- return convertToUnicode(a.constData(), a.length(), 0);
+ return convertToUnicode(a.constData(), a.length(), nullptr);
}
/*!
@@ -917,7 +915,7 @@ bool QTextCodec::canEncode(QStringView s) const
QString QTextCodec::toUnicode(const char *chars) const
{
int len = qstrlen(chars);
- return convertToUnicode(chars, len, 0);
+ return convertToUnicode(chars, len, nullptr);
}
@@ -1063,7 +1061,7 @@ QString QTextDecoder::toUnicode(const char *chars, int len)
}
// in qstring.cpp:
-void qt_from_latin1(ushort *dst, const char *str, size_t size) Q_DECL_NOTHROW;
+void qt_from_latin1(ushort *dst, const char *str, size_t size) noexcept;
/*! \overload
@@ -1112,7 +1110,7 @@ QString QTextDecoder::toUnicode(const QByteArray &ba)
QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec)
{
// determine charset
- QTextCodec *c = QTextCodec::codecForUtfText(ba, 0);
+ QTextCodec *c = QTextCodec::codecForUtfText(ba, nullptr);
if (!c) {
static Q_RELAXED_CONSTEXPR auto matcher = qMakeStaticByteArrayMatcher("meta ");
QByteArray header = ba.left(1024).toLower();
diff --git a/src/corelib/codecs/qtextcodec_p.h b/src/corelib/codecs/qtextcodec_p.h
index 0e449d994c..7fcf6df984 100644
--- a/src/corelib/codecs/qtextcodec_p.h
+++ b/src/corelib/codecs/qtextcodec_p.h
@@ -98,7 +98,7 @@ public:
struct ConverterState {
ConverterState(ConversionFlags f = DefaultConversion)
- : flags(f), remainingChars(0), invalidChars(0), d(0) { state_data[0] = state_data[1] = state_data[2] = 0; }
+ : flags(f), remainingChars(0), invalidChars(0), d(nullptr) { state_data[0] = state_data[1] = state_data[2] = 0; }
~ConverterState() { }
ConversionFlags flags;
int remainingChars;
diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp
index 643c8ee475..85736fdf02 100644
--- a/src/corelib/codecs/qutfcodec.cpp
+++ b/src/corelib/codecs/qutfcodec.cpp
@@ -54,7 +54,7 @@ static const uchar utf8bom[] = { 0xef, 0xbb, 0xbf };
#if (defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSE2)) \
|| (defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64))
-static Q_ALWAYS_INLINE uint qBitScanReverse(unsigned v) Q_DECL_NOTHROW
+static Q_ALWAYS_INLINE uint qBitScanReverse(unsigned v) noexcept
{
uint result = qCountLeadingZeroBits(v);
// Now Invert the result: clz will count *down* from the msb to the lsb, so the msb index is 31
@@ -504,7 +504,7 @@ QString QUtf8::convertToUnicode(const char *chars, int len)
This function never throws.
*/
-QChar *QUtf8::convertToUnicode(QChar *buffer, const char *chars, int len) Q_DECL_NOTHROW
+QChar *QUtf8::convertToUnicode(QChar *buffer, const char *chars, int len) noexcept
{
ushort *dst = reinterpret_cast<ushort *>(buffer);
const uchar *src = reinterpret_cast<const uchar *>(chars);
diff --git a/src/corelib/codecs/qutfcodec_p.h b/src/corelib/codecs/qutfcodec_p.h
index b24283ac5e..083e16317a 100644
--- a/src/corelib/codecs/qutfcodec_p.h
+++ b/src/corelib/codecs/qutfcodec_p.h
@@ -291,7 +291,7 @@ enum DataEndianness
struct QUtf8
{
- static QChar *convertToUnicode(QChar *, const char *, int) Q_DECL_NOTHROW;
+ static QChar *convertToUnicode(QChar *, const char *, int) noexcept;
static QString convertToUnicode(const char *, int);
static QString convertToUnicode(const char *, int, QTextCodec::ConverterState *);
static QByteArray convertFromUnicode(const QChar *, int);
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
index 5f5a00a64f..88c7bbfbed 100644
--- a/src/corelib/configure.json
+++ b/src/corelib/configure.json
@@ -11,7 +11,8 @@
"icu": "boolean",
"inotify": "boolean",
"journald": "boolean",
- "pcre": { "type": "enum", "values": [ "qt", "system" ] },
+ "mimetype-database": "boolean",
+ "pcre": { "type": "enum", "values": [ "no", "qt", "system" ] },
"posix-ipc": { "type": "boolean", "name": "ipc_posix" },
"pps": { "type": "boolean", "name": "qqnx_pps" },
"slog2": "boolean",
@@ -234,6 +235,66 @@
"sources": [
"-lslog2"
]
+ },
+ "advapi32": {
+ "label": "advapi32",
+ "sources": [
+ "-ladvapi32"
+ ]
+ },
+ "gdi32": {
+ "label": "gdi32",
+ "sources": [
+ "-lgdi32"
+ ]
+ },
+ "kernel32": {
+ "label": "kernel32",
+ "sources": [
+ "-lkernel32"
+ ]
+ },
+ "netapi32": {
+ "label": "netapi32",
+ "sources": [
+ "-lnetapi32"
+ ]
+ },
+ "ole32": {
+ "label": "ole32",
+ "sources": [
+ "-lole32"
+ ]
+ },
+ "shell32": {
+ "label": "shell32",
+ "sources": [
+ "-lshell32"
+ ]
+ },
+ "uuid": {
+ "label": "uuid",
+ "sources": [
+ "-luuid"
+ ]
+ },
+ "user32": {
+ "label": "user32",
+ "sources": [
+ "-luser32"
+ ]
+ },
+ "winmm": {
+ "label": "winmm",
+ "sources": [
+ "-lwinmm"
+ ]
+ },
+ "ws2_32": {
+ "label": "ws2_32",
+ "sources": [
+ "-lws2_32"
+ ]
}
},
@@ -678,15 +739,23 @@
"condition": "features.textcodec",
"output": [ "publicFeature", "feature" ]
},
+ "mimetype-database": {
+ "label": "Built-in copy of the MIME database",
+ "condition": "features.mimetype",
+ "output": [ "privateFeature" ]
+ },
+ "pcre2": {
+ "label": "PCRE2",
+ "disable": "input.pcre == 'no' || input.pcre == 'system'",
+ "enable": "input.pcre == 'qt'",
+ "output": [ "privateConfig" ]
+ },
"system-pcre2": {
- "label": "Using system PCRE2",
- "disable": "input.pcre == 'qt'",
+ "label": " Using system PCRE2",
+ "disable": "input.pcre == 'no' || input.pcre == 'qt'",
"enable": "input.pcre == 'system'",
"condition": "libs.pcre2",
- "output": [
- "privateFeature",
- { "type": "privateConfig", "negative": true, "name": "pcre2" }
- ]
+ "output": [ "privateFeature" ]
},
"poll_ppoll": {
"label": "Native ppoll()",
@@ -765,6 +834,7 @@
"label": "QRegularExpression",
"purpose": "Provides an API to Perl-compatible regular expressions.",
"section": "Kernel",
+ "condition": "features.system-pcre2 || features.pcre2",
"output": [ "publicFeature", "feature" ]
},
"sharedmemory": {
@@ -781,7 +851,7 @@
"purpose": "Provides a general counting system semaphore.",
"section": "Kernel",
"condition": [
- "!config.integrity && !config.vxworks",
+ "!config.integrity && !config.vxworks && !config.rtems",
"config.android || config.win32 || tests.ipc_sysv || tests.ipc_posix"
],
"output": [ "publicFeature", "feature" ]
@@ -823,14 +893,14 @@
"label": "QProcess",
"purpose": "Supports external process invocation.",
"section": "File I/O",
- "condition": "features.processenvironment && !config.winrt && !config.uikit && !config.integrity && !config.vxworks",
+ "condition": "features.processenvironment && !config.winrt && !config.uikit && !config.integrity && !config.vxworks && !config.rtems",
"output": [ "publicFeature", "feature" ]
},
"processenvironment": {
"label": "QProcessEnvironment",
"purpose": "Provides a higher-level abstraction of environment variables.",
"section": "File I/O",
- "condition": "!config.winrt && !config.integrity",
+ "condition": "!config.winrt && !config.integrity && !config.rtems",
"output": [ "publicFeature" ]
},
"temporaryfile": {
@@ -892,6 +962,20 @@
"condition": "features.proxymodel",
"output": [ "publicFeature", "feature" ]
},
+ "transposeproxymodel": {
+ "label": "QTransposeProxyModel",
+ "purpose": "Provides a proxy to swap rows and columns of a model.",
+ "section": "ItemViews",
+ "condition": "features.proxymodel",
+ "output": [ "publicFeature", "feature" ]
+ },
+ "concatenatetablesproxymodel": {
+ "label": "QConcatenateTablesProxyModel",
+ "purpose": "Supports concatenating source models.",
+ "section": "ItemViews",
+ "condition": "features.proxymodel",
+ "output": [ "publicFeature", "feature" ]
+ },
"stringlistmodel": {
"label": "QStringListModel",
"purpose": "Provides a model that supplies strings to views.",
@@ -993,6 +1077,10 @@ If enabled, a binary dump of the Public Suffix List (http://www.publicsuffix.org
Mozilla License) is included. The data is then also used in QNetworkCookieJar::validateCookie.",
"section": "Utilities",
"output": [ "publicFeature" ]
+ },
+ "win32_system_libs": {
+ "label": "Windows System Libraries",
+ "condition": "config.win32 && libs.advapi32 && libs.gdi32 && libs.kernel32 && libs.netapi32 && libs.ole32 && libs.shell32 && libs.uuid && libs.user32 && libs.winmm && libs.ws2_32"
}
},
@@ -1034,6 +1122,7 @@ Please apply the patch corresponding to your Standard Library vendor, found in
"glib",
"iconv",
"icu",
+ "mimetype-database",
{
"message": "Tracing backend",
"type": "firstAvailableFeature",
@@ -1050,6 +1139,7 @@ Please apply the patch corresponding to your Standard Library vendor, found in
"args": "qqnx_pps",
"condition": "config.qnx"
},
+ "pcre2",
"system-pcre2"
]
}
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 181780c475..521f840292 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -36,6 +36,7 @@ qtConfig(animation): include(animation/animation.pri)
include(global/global.pri)
include(thread/thread.pri)
include(tools/tools.pri)
+include(time/time.pri)
include(io/io.pri)
include(itemmodels/itemmodels.pri)
include(plugin/plugin.pri)
@@ -44,12 +45,11 @@ include(codecs/codecs.pri)
include(serialization/serialization.pri)
include(statemachine/statemachine.pri)
include(mimetypes/mimetypes.pri)
+include(platform/platform.pri)
win32 {
- LIBS_PRIVATE += -lws2_32
- !winrt {
- LIBS_PRIVATE += -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lwinmm
- }
+ QMAKE_USE_PRIVATE += ws2_32
+ !winrt: QMAKE_USE_PRIVATE += advapi32 kernel32 ole32 shell32 uuid user32 winmm
}
darwin {
@@ -67,8 +67,6 @@ integrity {
QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtCore.dynlist
-contains(DEFINES,QT_EVAL):include(eval.pri)
-
HOST_BINS = $$[QT_HOST_BINS]
host_bins.name = host_bins
host_bins.variable = HOST_BINS
diff --git a/src/corelib/doc/snippets/code/doc_src_qset.cpp b/src/corelib/doc/snippets/code/doc_src_qset.cpp
index 4cd84d7330..7f7cec8b45 100644
--- a/src/corelib/doc/snippets/code/doc_src_qset.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qset.cpp
@@ -133,7 +133,7 @@ QSet<QString> set;
...
QSet<QString>::iterator it = qFind(set.begin(), set.end(), "Jeanette");
if (it != set.end())
- cout << "Found Jeanette" << endl;
+ cout << "Found Jeanette" << Qt::endl;
//! [10]
@@ -152,7 +152,7 @@ QSet<QString> set;
...
QSet<QString>::iterator it = qFind(set.begin(), set.end(), "Jeanette");
if (it != set.constEnd())
- cout << "Found Jeanette" << endl;
+ cout << "Found Jeanette" << Qt::endl;
//! [12]
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
index 03904659f5..eb75a29ca2 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
@@ -773,16 +773,16 @@ bool readConfiguration(const QFile &file)
//! [qdecloverride]
// generate error if this doesn't actually override anything:
- virtual void MyWidget::paintEvent(QPaintEvent*) Q_DECL_OVERRIDE;
+ virtual void MyWidget::paintEvent(QPaintEvent*) override;
//! [qdecloverride]
//! [qdeclfinal-1]
// more-derived classes no longer permitted to override this:
- virtual void MyWidget::paintEvent(QPaintEvent*) Q_DECL_FINAL;
+ virtual void MyWidget::paintEvent(QPaintEvent*) final;
//! [qdeclfinal-1]
//! [qdeclfinal-2]
- class QRect Q_DECL_FINAL { // cannot be derived from
+ class QRect final { // cannot be derived from
// ...
};
//! [qdeclfinal-2]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp
index 625c1cf9bc..c30f13df5a 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp
@@ -124,12 +124,12 @@ in >> ch1 >> ch2 >> ch3;
//! [8]
QTextStream out(stdout);
-out << "Qt rocks!" << endl;
+out << "Qt rocks!" << Qt::endl;
//! [8]
//! [9]
-stream << '\n' << flush;
+stream << '\n' << Qt::flush;
//! [9]
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp
index 382b08fdb7..dfa9b670e7 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp
@@ -53,7 +53,7 @@ QFuture<QString> future = ...;
QFuture<QString>::const_iterator i;
for (i = future.constBegin(); i != future.constEnd(); ++i)
- cout << *i << endl;
+ cout << *i << Qt::endl;
//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
index 32fccbefbf..11ab50687d 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
@@ -71,7 +71,7 @@ ba[4] = 0xca;
//! [2]
for (int i = 0; i < ba.size(); ++i) {
if (ba.at(i) >= 'a' && ba.at(i) <= 'f')
- cout << "Found character in range [a-f]" << endl;
+ cout << "Found character in range [a-f]" << Qt::endl;
}
//! [2]
@@ -88,7 +88,7 @@ x.replace(5, 3, "&"); // x == "rock & roll"
QByteArray ba("We must be <b>bold</b>, very <b>bold</b>");
int j = 0;
while ((j = ba.indexOf("<b>", j)) != -1) {
- cout << "Found <b> tag at index position " << j << endl;
+ cout << "Found <b> tag at index position " << j << Qt::endl;
++j;
}
//! [4]
@@ -126,17 +126,17 @@ QByteArray("abc").isEmpty(); // returns false
QByteArray ba("Hello world");
char *data = ba.data();
while (*data) {
- cout << "[" << *data << "]" << endl;
+ cout << "[" << *data << "]" << Qt::endl;
++data;
}
//! [8]
//! [9]
-QByteArray ba;
-for (int i = 0; i < 10; ++i)
- ba[i] = 'A' + i;
-// ba == "ABCDEFGHIJ"
+QByteArray ba("Hello, world");
+cout << ba[0]; // prints H
+ba[7] = 'W';
+// ba == "Hello, World"
//! [9]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp
index 3ecb67a48f..a477e91548 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp
@@ -128,7 +128,7 @@ qDebug("Time elapsed: %d ms", t.elapsed());
//! [11]
QDateTime now = QDateTime::currentDateTime();
-QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0));
+QDateTime xmas(QDate(now.date().year(), 12, 25).startOfDay());
qDebug("There are %d seconds to Christmas", now.secsTo(xmas));
//! [11]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
index a3d2dd7f9e..9813cc98d5 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
@@ -89,7 +89,7 @@ QHash<int, QWidget *> hash;
...
for (int i = 0; i < 1000; ++i) {
if (hash[i] == okButton)
- cout << "Found button at index " << i << endl;
+ cout << "Found button at index " << i << Qt::endl;
}
//! [6]
@@ -98,7 +98,7 @@ for (int i = 0; i < 1000; ++i) {
QHashIterator<QString, int> i(hash);
while (i.hasNext()) {
i.next();
- cout << i.key() << ": " << i.value() << endl;
+ cout << i.key() << ": " << i.value() << Qt::endl;
}
//! [7]
@@ -106,7 +106,7 @@ while (i.hasNext()) {
//! [8]
QHash<QString, int>::const_iterator i = hash.constBegin();
while (i != hash.constEnd()) {
- cout << i.key() << ": " << i.value() << endl;
+ cout << i.key() << ": " << i.value() << Qt::endl;
++i;
}
//! [8]
@@ -122,14 +122,14 @@ hash.insert("plenty", 2000);
//! [10]
QList<int> values = hash.values("plenty");
for (int i = 0; i < values.size(); ++i)
- cout << values.at(i) << endl;
+ cout << values.at(i) << Qt::endl;
//! [10]
//! [11]
QHash<QString, int>::iterator i = hash.find("plenty");
while (i != hash.end() && i.key() == "plenty") {
- cout << i.value() << endl;
+ cout << i.value() << Qt::endl;
++i;
}
//! [11]
@@ -139,7 +139,7 @@ while (i != hash.end() && i.key() == "plenty") {
QHash<QString, int> hash;
...
foreach (int value, hash)
- cout << value << endl;
+ cout << value << Qt::endl;
//! [12]
@@ -201,7 +201,7 @@ QHash<QString, int> hash;
...
QHash<QString, int>::const_iterator i = hash.find("HDR");
while (i != hash.end() && i.key() == "HDR") {
- cout << i.value() << endl;
+ cout << i.value() << Qt::endl;
++i;
}
//! [16]
@@ -216,7 +216,7 @@ hash.insert("December", 12);
QHash<QString, int>::iterator i;
for (i = hash.begin(); i != hash.end(); ++i)
- cout << i.key() << ": " << i.value() << endl;
+ cout << i.key() << ": " << i.value() << Qt::endl;
//! [17]
@@ -274,7 +274,7 @@ hash.insert("December", 12);
QHash<QString, int>::const_iterator i;
for (i = hash.constBegin(); i != hash.constEnd(); ++i)
- cout << i.key() << ": " << i.value() << endl;
+ cout << i.key() << ": " << i.value() << Qt::endl;
//! [23]
@@ -296,23 +296,23 @@ hash3 = hash1 + hash2;
//! [25]
QList<int> values = hash.values("plenty");
for (int i = 0; i < values.size(); ++i)
- cout << values.at(i) << endl;
+ cout << values.at(i) << Qt::endl;
//! [25]
//! [26]
QMultiHash<QString, int>::iterator i = hash.find("plenty");
while (i != hash.end() && i.key() == "plenty") {
- cout << i.value() << endl;
+ cout << i.value() << Qt::endl;
++i;
}
//! [26]
//! [27]
for (QHash<int, QString>::const_iterator it = hash.cbegin(), end = hash.cend(); it != end; ++it) {
- cout << "The key: " << it.key() << endl
- cout << "The value: " << it.value() << endl;
- cout << "Also the value: " << (*it) << endl;
+ cout << "The key: " << it.key() << Qt::endl
+ cout << "The value: " << it.value() << Qt::endl;
+ cout << "Also the value: " << (*it) << Qt::endl;
}
//! [27]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp
index 7f743bbd25..e0d3c71dc5 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp
@@ -112,7 +112,7 @@ list.append("December");
QLinkedList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
- cout << *i << endl;
+ cout << *i << Qt::endl;
//! [7]
@@ -122,7 +122,7 @@ QLinkedList<QString> list;
QLinkedList<QString>::iterator it = qFind(list.begin(),
list.end(), "Joel");
if (it != list.end())
- cout << "Found Joel" << endl;
+ cout << "Found Joel" << Qt::endl;
//! [8]
@@ -182,7 +182,7 @@ list.append("December");
QLinkedList<QString>::const_iterator i;
for (i = list.constBegin(); i != list.constEnd(); ++i)
- cout << *i << endl;
+ cout << *i << Qt::endl;
//! [14]
@@ -192,7 +192,7 @@ QLinkedList<QString> list;
QLinkedList<QString>::iterator it = qFind(list.constBegin(),
list.constEnd(), "Joel");
if (it != list.constEnd())
- cout << "Found Joel" << endl;
+ cout << "Found Joel" << Qt::endl;
//! [15]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp
index cc3f689710..a24e599f2f 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp
@@ -73,7 +73,7 @@ if (list[0] == "Bob")
//! [3]
for (int i = 0; i < list.size(); ++i) {
if (list.at(i) == "Jane")
- cout << "Found Jane at position " << i << endl;
+ cout << "Found Jane at position " << i << Qt::endl;
}
//! [3]
@@ -89,7 +89,7 @@ while (!list.isEmpty())
//! [5]
int i = list.indexOf("Jane");
if (i != -1)
- cout << "First occurrence of Jane is at position " << i << endl;
+ cout << "First occurrence of Jane is at position " << i << Qt::endl;
//! [5]
@@ -146,7 +146,7 @@ list.move(1, 4);
//! [12]
QList<QString> list;
list << "A" << "B" << "C" << "D" << "E" << "F";
-list.swap(1, 4);
+list.swapItemsAt(1, 4);
// list: ["A", "E", "C", "D", "B", "F"]
//! [12]
@@ -180,7 +180,7 @@ list.append("December");
QList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
- cout << *i << endl;
+ cout << *i << Qt::endl;
//! [15]
@@ -213,7 +213,7 @@ list.append("December");
QList<QString>::const_iterator i;
for (i = list.constBegin(); i != list.constEnd(); ++i)
- cout << *i << endl;
+ cout << *i << Qt::endl;
//! [19]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp
index bd59758f71..506022f082 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp
@@ -89,7 +89,7 @@ QMap<int, QWidget *> map;
...
for (int i = 0; i < 1000; ++i) {
if (map[i] == okButton)
- cout << "Found button at index " << i << endl;
+ cout << "Found button at index " << i << Qt::endl;
}
//! [6]
@@ -98,7 +98,7 @@ for (int i = 0; i < 1000; ++i) {
QMapIterator<QString, int> i(map);
while (i.hasNext()) {
i.next();
- cout << i.key() << ": " << i.value() << endl;
+ cout << i.key() << ": " << i.value() << Qt::endl;
}
//! [7]
@@ -106,7 +106,7 @@ while (i.hasNext()) {
//! [8]
QMap<QString, int>::const_iterator i = map.constBegin();
while (i != map.constEnd()) {
- cout << i.key() << ": " << i.value() << endl;
+ cout << i.key() << ": " << i.value() << Qt::endl;
++i;
}
//! [8]
@@ -122,14 +122,14 @@ map.insert("plenty", 2000);
//! [10]
QList<int> values = map.values("plenty");
for (int i = 0; i < values.size(); ++i)
- cout << values.at(i) << endl;
+ cout << values.at(i) << Qt::endl;
//! [10]
//! [11]
QMap<QString, int>::iterator i = map.find("plenty");
while (i != map.end() && i.key() == "plenty") {
- cout << i.value() << endl;
+ cout << i.value() << Qt::endl;
++i;
}
//! [11]
@@ -139,7 +139,7 @@ while (i != map.end() && i.key() == "plenty") {
QMap<QString, int> map;
...
foreach (int value, map)
- cout << value << endl;
+ cout << value << Qt::endl;
//! [12]
@@ -175,7 +175,7 @@ QMap<QString, int> map;
...
QMap<QString, int>::const_iterator i = map.find("HDR");
while (i != map.end() && i.key() == "HDR") {
- cout << i.value() << endl;
+ cout << i.value() << Qt::endl;
++i;
}
//! [14]
@@ -201,7 +201,7 @@ QMap<QString, int> map;
QMap<QString, int>::const_iterator i = map.lowerBound("HDR");
QMap<QString, int>::const_iterator upperBound = map.upperBound("HDR");
while (i != upperBound) {
- cout << i.value() << endl;
+ cout << i.value() << Qt::endl;
++i;
}
//! [16]
@@ -230,7 +230,7 @@ map.insert("December", 12);
QMap<QString, int>::iterator i;
for (i = map.begin(); i != map.end(); ++i)
- cout << i.key() << ": " << i.value() << endl;
+ cout << i.key() << ": " << i.value() << Qt::endl;
//! [18]
@@ -288,7 +288,7 @@ map.insert("December", 12);
QMap<QString, int>::const_iterator i;
for (i = map.constBegin(); i != map.constEnd(); ++i)
- cout << i.key() << ": " << i.value() << endl;
+ cout << i.key() << ": " << i.value() << Qt::endl;
//! [24]
@@ -310,23 +310,23 @@ map3 = map1 + map2;
//! [26]
QList<int> values = map.values("plenty");
for (int i = 0; i < values.size(); ++i)
- cout << values.at(i) << endl;
+ cout << values.at(i) << Qt::endl;
//! [26]
//! [27]
QMultiMap<QString, int>::iterator i = map.find("plenty");
while (i != map.end() && i.key() == "plenty") {
- cout << i.value() << endl;
+ cout << i.value() << Qt::endl;
++i;
}
//! [27]
//! [keyiterator1]
for (QMap<int, QString>::const_iterator it = map.cbegin(), end = map.cend(); it != end; ++it) {
- cout << "The key: " << it.key() << endl
- cout << "The value: " << it.value() << endl;
- cout << "Also the value: " << (*it) << endl;
+ cout << "The key: " << it.key() << Qt::endl
+ cout << "The value: " << it.value() << Qt::endl;
+ cout << "Also the value: " << (*it) << Qt::endl;
}
//! [keyiterator1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp
index b74ac31933..6046c73b0f 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp
@@ -54,5 +54,5 @@ queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
while (!queue.isEmpty())
- cout << queue.dequeue() << endl;
+ cout << queue.dequeue() << Qt::endl;
//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp
index afdd9c3d25..99cd4ea7a2 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp
@@ -286,15 +286,11 @@ if (!invalidRe.isValid()) {
{
//! [24]
-QRegularExpression re("^this pattern must match exactly$");
-//! [24]
-}
-
-{
-//! [25]
QString p("a .*|pattern");
-QRegularExpression re("\\A(?:" + p + ")\\z"); // re matches exactly the pattern string p
-//! [25]
+
+// re matches exactly the pattern string p
+QRegularExpression re(QRegularExpression::anchoredPattern(p));
+//! [24]
}
{
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp
index 7a2b4812ef..eb09fb99e2 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp
@@ -72,9 +72,9 @@ while (i.hasNext())
{
//! [2]
QStringIterator i(u"ð„ž is the G clef");
-qDebug() << hex << i.next(); // will print 1d11e (U+1D11E, MUSICAL SYMBOL G CLEF)
-qDebug() << hex << i.next(); // will print 20 (U+0020, SPACE)
-qDebug() << hex << i.next(); // will print 69 (U+0069, LATIN SMALL LETTER I)
+qDebug() << Qt::hex << i.next(); // will print 1d11e (U+1D11E, MUSICAL SYMBOL G CLEF)
+qDebug() << Qt::hex << i.next(); // will print 20 (U+0020, SPACE)
+qDebug() << Qt::hex << i.next(); // will print 69 (U+0069, LATIN SMALL LETTER I)
//! [2]
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp
index 1f2af4a408..a05233049f 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp
@@ -73,7 +73,7 @@ if (vector[0] == "Liz")
//! [4]
for (int i = 0; i < vector.size(); ++i) {
if (vector.at(i) == "Alfonso")
- cout << "Found Alfonso at position " << i << endl;
+ cout << "Found Alfonso at position " << i << Qt::endl;
}
//! [4]
@@ -81,7 +81,7 @@ for (int i = 0; i < vector.size(); ++i) {
//! [5]
int i = vector.indexOf("Harumi");
if (i != -1)
- cout << "First occurrence of Harumi is at position " << i << endl;
+ cout << "First occurrence of Harumi is at position " << i << Qt::endl;
//! [5]
diff --git a/src/corelib/doc/snippets/qstack/main.cpp b/src/corelib/doc/snippets/qstack/main.cpp
index af6b960e57..66823bcb59 100644
--- a/src/corelib/doc/snippets/qstack/main.cpp
+++ b/src/corelib/doc/snippets/qstack/main.cpp
@@ -60,6 +60,6 @@ int main(int argc, char *argv[])
stack.push(2);
stack.push(3);
while (!stack.isEmpty())
- cout << stack.pop() << endl;
+ cout << stack.pop() << Qt::endl;
//! [0]
}
diff --git a/src/corelib/doc/snippets/qstringlist/main.cpp b/src/corelib/doc/snippets/qstringlist/main.cpp
index 55c60650fe..80788ccd76 100644
--- a/src/corelib/doc/snippets/qstringlist/main.cpp
+++ b/src/corelib/doc/snippets/qstringlist/main.cpp
@@ -71,20 +71,20 @@ Widget::Widget(QWidget *parent)
//! [1]
for (int i = 0; i < fonts.size(); ++i)
- cout << fonts.at(i).toLocal8Bit().constData() << endl;
+ cout << fonts.at(i).toLocal8Bit().constData() << Qt::endl;
//! [1]
//! [2]
QStringListIterator javaStyleIterator(fonts);
while (javaStyleIterator.hasNext())
- cout << javaStyleIterator.next().toLocal8Bit().constData() << endl;
+ cout << javaStyleIterator.next().toLocal8Bit().constData() << Qt::endl;
//! [2]
//! [3]
QStringList::const_iterator constIterator;
for (constIterator = fonts.constBegin(); constIterator != fonts.constEnd();
++constIterator)
- cout << (*constIterator).toLocal8Bit().constData() << endl;
+ cout << (*constIterator).toLocal8Bit().constData() << Qt::endl;
//! [3]
//! [4]
diff --git a/src/corelib/doc/snippets/resource-system/mainwindow.cpp b/src/corelib/doc/snippets/resource-system/mainwindow.cpp
index bbeeec64ac..86e93aaa62 100644
--- a/src/corelib/doc/snippets/resource-system/mainwindow.cpp
+++ b/src/corelib/doc/snippets/resource-system/mainwindow.cpp
@@ -338,11 +338,11 @@ void MainWindow::loadFile(const QString &fileName)
QTextStream in(&file);
#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(Qt::WaitCursor);
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
#endif
textEdit->setPlainText(in.readAll());
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
setCurrentFile(fileName);
@@ -365,11 +365,11 @@ bool MainWindow::saveFile(const QString &fileName)
QTextStream out(&file);
#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(Qt::WaitCursor);
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
#endif
out << textEdit->toPlainText();
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
setCurrentFile(fileName);
diff --git a/src/corelib/doc/src/containers.qdoc b/src/corelib/doc/src/containers.qdoc
index a1c32bb007..e6c95129db 100644
--- a/src/corelib/doc/src/containers.qdoc
+++ b/src/corelib/doc/src/containers.qdoc
@@ -171,8 +171,9 @@
The values stored in the various containers can be of any
\e{assignable data type}. To qualify, a type must provide a
- default constructor, a copy constructor, and an assignment
- operator. This covers most data types you are likely to want to
+ copy constructor, and an assignment operator. For some
+ operations a default constructor is also required. This
+ covers most data types you are likely to want to
store in a container, including basic types such as \c int and \c
double, pointer types, and Qt data types such as QString, QDate,
and QTime, but it doesn't cover QObject or any QObject subclass
diff --git a/src/corelib/doc/src/datastreamformat.qdoc b/src/corelib/doc/src/datastreamformat.qdoc
index 73ca51974d..d6b60f10ce 100644
--- a/src/corelib/doc/src/datastreamformat.qdoc
+++ b/src/corelib/doc/src/datastreamformat.qdoc
@@ -28,357 +28,71 @@
/*!
\page datastreamformat.html
\title Serializing Qt Data Types
- \brief Representations of data types that can be serialized by QDataStream.
+ \brief List of data types that can be serialized by QDataStream.
- The \l QDataStream allows you to serialize some of the Qt data types.
- The table below lists the data types that QDataStream can serialize
- and how they are represented. The format described below is
- \l{QDataStream::setVersion()}{version 13}.
+ The \l QDataStream class allows you to serialize the Qt data types
+ listed in this section as of \l{QDataStream::setVersion()}{version 18}.
It is always best to cast integers to a Qt integer type, such as
- qint16 or quint32, when reading and writing. This ensures that
+ \l{qint16} or \l{quint32}, when reading and writing. This ensures that
you always know exactly what size integers you are reading and
writing, no matter what the underlying platform and architecture
the application happens to be running on.
- \table
- \row \li bool
- \li \list
- \li boolean
- \endlist
- \row \li qint8
- \li \list
- \li signed byte
- \endlist
- \row \li qint16
- \li \list
- \li signed 16-bit integer
- \endlist
- \row \li qint32
- \li \list
- \li signed 32-bit integer
- \endlist
- \row \li qint64
- \li \list
- \li signed 64-bit integer
- \endlist
- \row \li quint8
- \li \list
- \li unsigned byte
- \endlist
- \row \li quint16
- \li \list
- \li unsigned 16-bit integer
- \endlist
- \row \li quint32
- \li \list
- \li unsigned 32-bit integer
- \endlist
- \row \li quint64
- \li \list
- \li unsigned 64-bit integer
- \endlist
- \row \li \c float
- \li \list
- \li 32-bit floating point number using the standard IEEE 754 format
- \endlist
- \row \li \c double
- \li \list
- \li 64-bit floating point number using the standard IEEE 754 format
- \endlist
- \row \li \c {const char *}
- \li \list
- \li The string length (quint32)
- \li The string bytes, excluding the terminating 0
- \endlist
- \row \li QBitArray
- \li \list
- \li The array size (quint32)
- \li The array bits, i.e. (size + 7)/8 bytes
- \endlist
- \row \li QBrush
- \li \list
- \li The brush style (quint8)
- \li The brush color (QColor)
- \li If style is CustomPattern, the brush pixmap (QPixmap)
- \endlist
- \row \li QByteArray
- \li \list
- \li If the byte array is null: 0xFFFFFFFF (quint32)
- \li Otherwise: the array size (quint32) followed by the array bytes, i.e. size bytes
- \endlist
- \row \li \l QColor
- \li \list
- \li Color spec (qint8)
- \li Alpha value (quint16)
- \li Red value (quint16)
- \li Green value (quint16)
- \li Blue value (quint16)
- \li Pad value (quint16)
- \endlist
- \row \li QCursor
- \li \list
- \li Shape ID (qint16)
- \li If shape is BitmapCursor: The bitmap (QPixmap), mask (QPixmap), and hot spot (QPoint)
- \endlist
- \row \li QDate
- \li \list
- \li Julian day (quint32)
- \endlist
- \row \li QDateTime
- \li \list
- \li Date (QDate)
- \li Time (QTime)
- \li The \l{Qt::TimeSpec}{time spec}
- offsetFromUtc (qint32) if Qt::TimeSpec is offsetFromUtc
- TimeZone(QTimeZone) if Qt::TimeSpec is TimeZone
- \endlist
- \row \li QEasingCurve
- \li \list
- \li type (quint8)
- \li func (quint64)
- \li hasConfig (bool)
- \li If hasConfig is true then these fields follow:
- \li list
- \li period (double)
- \li amplitude (double)
- \li overshoot (double)
- \endlist
- \row \li QFont
- \li \list
- \li The family (QString)
- \li The style name (QString)
- \li The point size (double)
- \li The pixel size (qint32)
- \li The style hint (quint8)
- \li The style strategy (quint16)
- \li The char set (quint8)
- \li The weight (quint8)
- \li The font bits (quint8)
- \li The font stretch (quint16)
- \li The extended font bits (quint8)
- \li The letter spacing (double)
- \li The word spacing (double)
- \li The hinting preference (quint8)
- \endlist
- \row \li QHash<Key, T>
- \li \list
- \li The number of items (quint32)
- \li For all items, the key (Key) and value (T)
- \endlist
- \row \li QIcon
- \li \list
- \li The number of pixmap entries (quint32)
- \li For all pixmap entries:
- \list
- \li The pixmap (QPixmap)
- \li The file name (QString)
- \li The pixmap size (QSize)
- \li The \l{QIcon::Mode}{mode} (quint32)
- \li The \l{QIcon::State}{state} (quint32)
- \endlist
- \endlist
- \row \li QImage
- \li \list
- \li If the image is null a "null image" marker is saved;
- otherwise the image is saved in PNG or BMP format (depending
- on the stream version). If you want control of the format,
- stream the image into a QBuffer (using QImageIOHandler/QImageIOPlugin) and stream
- that.
- \endlist
- \row \li QKeySequence
- \li \list
- \li A QList<int>, where each integer is a key in the key sequence
- \endlist
- \row \li QLinkedList<T>
- \li \list
- \li The number of items (quint32)
- \li The items (T)
- \endlist
- \row \li QList<T>
- \li \list
- \li The number of items (quint32)
- \li The items (T)
- \endlist
- \row \li QMap<Key, T>
- \li \list
- \li The number of items (quint32)
- \li For all items, the key (Key) and value (T)
- \endlist
- \row \li QMargins
- \li \list
- \li left (int)
- \li top (int)
- \li right (int)
- \li bottom (int)
- \endlist
- \row \li QMatrix
- \li \list
- \li m11 (double)
- \li m12 (double)
- \li m21 (double)
- \li m22 (double)
- \li dx (double)
- \li dy (double)
- \endlist
- \row \li QMatrix4x4
- \li \list
- \li m11 (float)
- \li m12 (float)
- \li m13 (float)
- \li m14 (float)
- \li m21 (float)
- \li m22 (float)
- \li m23 (float)
- \li m24 (float)
- \li m31 (float)
- \li m32 (float)
- \li m33 (float)
- \li m34 (float)
- \li m41 (float)
- \li m42 (float)
- \li m43 (float)
- \li m44 (float)
- \endlist
- \row \li QPair<T1, T2>
- \li \list
- \li first (T1)
- \li second (T2)
- \endlist
- \row \li QPalette
- \li The disabled, active, and inactive color groups, each of which consists
- of the following:
- \list
- \li foreground (QBrush)
- \li button (QBrush)
- \li light (QBrush)
- \li midlight (QBrush)
- \li dark (QBrush)
- \li mid (QBrush)
- \li text (QBrush)
- \li brightText (QBrush)
- \li buttonText (QBrush)
- \li base (QBrush)
- \li background (QBrush)
- \li shadow (QBrush)
- \li highlight (QBrush)
- \li highlightedText (QBrush)
- \li link (QBrush)
- \li linkVisited (QBrush)
- \endlist
- \row \li QPen
- \li \list
- \li The pen styles (quint8)
- \li The pen width (quint16)
- \li The pen color (QColor)
- \endlist
- \row \li QPicture
- \li \list
- \li The size of the picture data (quint32)
- \li The raw bytes of picture data (char)
- \endlist
- \row \li QPixmap
- \li \list
- \li Save it as a PNG image.
- \endlist
- \row \li QPoint
- \li \list
- \li The x coordinate (qint32)
- \li The y coordinate (qint32)
- \endlist
- \row \li QQuaternion
- \li \list
- \li The scalar component (float)
- \li The x coordinate (float)
- \li The y coordinate (float)
- \li The z coordinate (float)
- \endlist
- \row \li QRect
- \li \list
- \li left (qint32)
- \li top (qint32)
- \li right (qint32)
- \li bottom (qint32)
- \endlist
- \row \li QRegExp
- \li \list
- \li The regexp pattern (QString)
- \li Case sensitivity (quint8)
- \li Regular expression syntax (quint8)
- \li Minimal matching (quint8)
- \endlist
- \row \li QRegularExpression
- \li \list
- \li The regular expression pattern (QString)
- \li The pattern options (quint32)
- \endlist
- \row \li QRegion
- \li \list
- \li The size of the data, i.e. 8 + 16 * (number of rectangles) (quint32)
- \li 10 (qint32)
- \li The number of rectangles (quint32)
- \li The rectangles in sequential order (QRect)
- \endlist
- \row \li QSize
- \li \list
- \li width (qint32)
- \li height (qint32)
- \endlist
- \row \li QString
- \li \list
- \li If the string is null: 0xFFFFFFFF (quint32)
- \li Otherwise: The string length in bytes (quint32) followed by the data in UTF-16
- \endlist
- \row \li QTime
- \li \list
- \li Milliseconds since midnight (quint32)
- \endlist
- \row \li QTransform
- \li \list
- \li m11 (double)
- \li m12 (double)
- \li m13 (double)
- \li m21 (double)
- \li m22 (double)
- \li m23 (double)
- \li m31 (double)
- \li m32 (double)
- \li m33 (double)
- \endlist
- \row \li QUrl
- \li \list
- \li Holds an URL (QString)
- \endlist
- \row \li QVariant
- \li \list
- \li The type of the data (quint32)
- \li The null flag (qint8)
- \li The data of the specified type
- \endlist
- \row \li QVector2D
- \li \list
- \li the x coordinate (float)
- \li the y coordinate (float)
- \endlist
- \row \li QVector3D
- \li \list
- \li the x coordinate (float)
- \li the y coordinate (float)
- \li the z coordinate (float)
- \endlist
- \row \li QVector4D
- \li \list
- \li the x coordinate (float)
- \li the y coordinate (float)
- \li the z coordinate (float)
- \li the w coordinate (float)
- \endlist
- \row \li QVector<T>
- \li \list
- \li The number of items (quint32)
- \li The items (T)
- \endlist
- \endtable
+ \list
+ \li bool
+ \li \l{qint8}
+ \li \l{qint16}
+ \li \l{qint32}
+ \li \l{qint64}
+ \li \l{quint8}
+ \li \l{quint16}
+ \li \l{quint32}
+ \li \l{quint64}
+ \li \c float
+ \li \c double
+ \li \c {const char *}
+ \li QBitArray
+ \li QBrush
+ \li QByteArray
+ \li QColor
+ \li QCursor
+ \li QDate
+ \li QDateTime
+ \li QEasingCurve
+ \li QFont
+ \li QGenericMatrix
+ \li QHash<Key, T>
+ \li QIcon
+ \li QImage
+ \li QKeySequence
+ \li QLinkedList<T>
+ \li QList<T>
+ \li QMap<Key, T>
+ \li QMargins
+ \li QMatrix4x4
+ \li QPair<T1, T2>
+ \li QPalette
+ \li QPen
+ \li QPicture
+ \li QPixmap
+ \li QPoint
+ \li QQuaternion
+ \li QRect
+ \li QRegExp
+ \li QRegularExpression
+ \li QRegion
+ \li QSize
+ \li QString
+ \li QTime
+ \li QTransform
+ \li QUrl
+ \li QVariant
+ \li QVector2D
+ \li QVector3D
+ \li QVector4D
+ \li QVector<T>
+ \endlist
\sa {JSON Support in Qt}
*/
diff --git a/src/corelib/doc/src/dontdocument.qdoc b/src/corelib/doc/src/dontdocument.qdoc
new file mode 100644
index 0000000000..19ca7db299
--- /dev/null
+++ b/src/corelib/doc/src/dontdocument.qdoc
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+/*!
+ \dontdocument (QMacAutoReleasePool QIncompatibleFlag QGenericAtomicOps QAtomicTraits
+ QAtomicOps QBasicAtomicInteger QBasicAtomicPointer QBasicMutex QInternal
+ QArgument QReturnArgument QArrayData QTypedArrayData QStaticByteArrayData
+ QByteRef QStaticStringData QListSpecialMethods QListData QScopedPointerDeleter
+ QScopedPointerArrayDeleter QScopedPointerPodDeleter QScopedPointerObjectDeleteLater
+ QMetaTypeId2 QObjectData QObjectUserData QMapNodeBase QMapNode QMapDataBase
+ QMapData QHashData QHashNode QArrayDataPointer QTextStreamManipulator
+ QContiguousCacheData QContiguousCacheTypedData QNoDebug QUrlTwoFlags
+ QCborValueRef qfloat16 QDeferredDeleteEvent QSpecialInteger QLittleEndianStorageType
+ QBigEndianStorageType QFactoryInterface QFutureWatcherBase QJsonValuePtr
+ QJsonValueRefPtr QLinkedListNode QAbstractConcatenable QStringBuilderCommon
+ QTextCodec::ConverterState QThreadStorageData)
+*/
diff --git a/src/corelib/doc/src/objectmodel/metaobjects.qdoc b/src/corelib/doc/src/objectmodel/metaobjects.qdoc
index 5b3d8f9863..53b34fe120 100644
--- a/src/corelib/doc/src/objectmodel/metaobjects.qdoc
+++ b/src/corelib/doc/src/objectmodel/metaobjects.qdoc
@@ -86,7 +86,7 @@
that it doesn't require RTTI support and it works across dynamic
library boundaries. It attempts to cast its argument to the pointer
type specified in angle-brackets, returning a non-zero pointer if the
- object is of the correct type (determined at run-time), or 0
+ object is of the correct type (determined at run-time), or \nullptr
if the object's type is incompatible.
For example, let's assume \c MyWidget inherits from QWidget and
diff --git a/src/corelib/doc/src/resource-system.qdoc b/src/corelib/doc/src/resource-system.qdoc
index 9b6b613f79..69ec5e556b 100644
--- a/src/corelib/doc/src/resource-system.qdoc
+++ b/src/corelib/doc/src/resource-system.qdoc
@@ -100,6 +100,9 @@
See the QLocale documentation for a description of the format to use
for locale strings.
+ See QFileSelector for an additional mechanism to select locale-specific
+ resources, in addition to the ability to select OS-specific and other
+ features.
\section2 External Binary Resources
@@ -143,24 +146,70 @@
\section1 Compression
- Resources are compressed by default (in the \c ZIP format). It is
- possible to turn off compression. This can be useful if your
- resources already contain a compressed format, such as \c .png
- files. You do this by giving the \c {-no-compress} command line
- argument.
+ \c rcc attempts to compress the content to optimize disk space usage in the
+ final binaries. By default, it will perform a heuristic check to determine
+ whether compressing is worth it and will store the content uncompressed if
+ it fails to sufficiently compress. To control the threshold, you can use
+ the \c {-threshold} option, which tells \c rcc the percentage of the
+ original file size that must be gained for it to store the file in
+ compressed form.
+
+ \code
+ rcc -threshold 25 myresources.qrc
+ \endcode
+
+ The default value is "70", indicating that the compressed file must be 70%
+ smaller than the original (no more than 30% of the original file size).
+
+ It is possible to turn off compression, if desired. This can be useful if
+ your resources already contain a compressed format, such as \c .png files,
+ and you do not want to incur the CPU cost at build time to confirm that it
+ can't be compressed. Another reason is if disk usage is not a problem and
+ the application would prefer to keep the content as clean memory pages at
+ runtime. You do this by giving the \c {-no-compress} command line argument.
\code
rcc -no-compress myresources.qrc
\endcode
- \c rcc also gives you some control over the compression. You can
- specify the compression level and the threshold level to consider
- while compressing files, for example:
+ \c rcc also gives you some control over the compression level and
+ compression algorithm, for example:
\code
- rcc -compress 2 -threshold 3 myresources.qrc
+ rcc -compress 2 -compress-algo zlib myresources.qrc
\endcode
+ \c rcc supports the following compression algorithms and compression
+ levels:
+
+ \list
+ \li \c{best}: use the best algorithm among the ones below, at its highest
+ compression level, to achieve the most compression at the expense of
+ using a lot of CPU time during compilation. This value is useful in the
+ XML file to indicate a file should be most compressed, regardless of
+ which algorithms \c rcc supports.
+
+ \li \c{zstd}: use the \l{Zstandard}{https://zstd.net} library to compress
+ contents. Valid compression levels range from 1 to 19, 1 is least
+ compression (least CPU time) and 19 is the most compression (most CPU
+ time). The default level is 14. A special value of 0 tells the \c{zstd}
+ library to choose an implementation-defined default.
+
+ \li \c{zlib}: use the \l{zlib}{https://zlib.net} library to compress
+ contents. Valid compression levels range from 1 to 9, with 1the least
+ compression (least CPU time) and 9 the most compression (most CPU time).
+ The special value 0 means "no compression" and should not be used. The
+ default is implementation-defined, but usually is level 6.
+
+ \li \c{none}: no compression. This is the same as the \c{-no-compress}
+ option.
+ \endlist
+
+ Support for both Zstandard and zlib are optional. If a given library was
+ not detected at compile time, attempting to pass \c {-compress-algo} for
+ that library will result in an error. The default compression algorithm is
+ \c zstd if it is enabled, \c zlib if not.
+
\section1 Using Resources in the Application
In the application, resource paths can be used in most places
diff --git a/src/corelib/eval.pri b/src/corelib/eval.pri
deleted file mode 100644
index efda56b16a..0000000000
--- a/src/corelib/eval.pri
+++ /dev/null
@@ -1,4 +0,0 @@
-SOURCES += \
- $$QT_SOURCE_TREE/src/corelib/kernel/qtcore_eval.cpp
-INCLUDEPATH += \
- $$QT_BUILD_TREE/src/corelib/global
diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp
index 66a5e074f6..1d00b7f5a5 100644
--- a/src/corelib/global/archdetect.cpp
+++ b/src/corelib/global/archdetect.cpp
@@ -67,6 +67,10 @@
# define ARCH_PROCESSOR "power"
#elif defined(Q_PROCESSOR_POWER_64)
# define ARCH_PROCESSOR "power64"
+#elif defined(Q_PROCESSOR_RISCV_32)
+# define ARCH_PROCESSOR "riscv32"
+#elif defined(Q_PROCESSOR_RISCV_64)
+# define ARCH_PROCESSOR "riscv64"
#elif defined(Q_PROCESSOR_S390_X)
# define ARCH_PROCESSOR "s390x"
#elif defined(Q_PROCESSOR_S390)
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index 029357ff43..1da69aba9b 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -7,12 +7,12 @@ HEADERS += \
global/qsystemdetection.h \
global/qcompilerdetection.h \
global/qprocessordetection.h \
+ global/qmemory_p.h \
global/qnamespace.h \
global/qendian.h \
global/qendian_p.h \
global/qnumeric_p.h \
global/qnumeric.h \
- global/qfloat16_p.h \
global/qfloat16.h \
global/qglobalstatic.h \
global/qlibraryinfo.h \
@@ -40,6 +40,10 @@ SOURCES += \
global/qrandom.cpp \
global/qhooks.cpp
+# To get listed in IDEs
+false: SOURCES += \
+ global/qfloat16tables.cpp
+
# Only add global/qfloat16_f16c.c if qfloat16.cpp can't #include it.
# Any compiler: if it is already generating F16C code, let qfloat16.cpp do it
# Clang: ICE if not generating F16C code, so use qfloat16_f16c.c
@@ -124,14 +128,3 @@ gcc:ltcg {
} else {
SOURCES += $$VERSIONTAGGING_SOURCES
}
-
-QMAKE_QFLOAT16_TABLES_GENERATE = global/qfloat16.h
-
-qtPrepareTool(QMAKE_QFLOAT16_TABLES, qfloat16-tables)
-
-qfloat16_tables.commands = $$QMAKE_QFLOAT16_TABLES ${QMAKE_FILE_OUT}
-qfloat16_tables.output = global/qfloat16tables.cpp
-qfloat16_tables.depends = $$QMAKE_QFLOAT16_TABLES_EXE
-qfloat16_tables.input = QMAKE_QFLOAT16_TABLES_GENERATE
-qfloat16_tables.variable_out = SOURCES
-QMAKE_EXTRA_COMPILERS += qfloat16_tables
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 345ab9e8ad..e47f284a42 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -110,12 +110,6 @@
# define Q_CC_INTEL __INTEL_COMPILER
# endif
-/* only defined for MSVC since that's the only compiler that actually optimizes for this */
-/* might get overridden further down when Q_COMPILER_NOEXCEPT is detected */
-# ifdef __cplusplus
-# define Q_DECL_NOTHROW throw()
-# endif
-
#elif defined(__BORLANDC__) || defined(__TURBOC__)
# define Q_CC_BOR
# define Q_INLINE_TEMPLATE
@@ -1128,16 +1122,11 @@
#ifdef Q_COMPILER_NOEXCEPT
# define Q_DECL_NOEXCEPT noexcept
# define Q_DECL_NOEXCEPT_EXPR(x) noexcept(x)
-# ifdef Q_DECL_NOTHROW
-# undef Q_DECL_NOTHROW /* override with C++11 noexcept if available */
-# endif
#else
# define Q_DECL_NOEXCEPT
# define Q_DECL_NOEXCEPT_EXPR(x)
#endif
-#ifndef Q_DECL_NOTHROW
-# define Q_DECL_NOTHROW Q_DECL_NOEXCEPT
-#endif
+#define Q_DECL_NOTHROW Q_DECL_NOEXCEPT
#if defined(Q_COMPILER_ALIGNOF)
# undef Q_ALIGNOF
diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h
index dfcc3c9c7f..10458e41d7 100644
--- a/src/corelib/global/qconfig-bootstrapped.h
+++ b/src/corelib/global/qconfig-bootstrapped.h
@@ -122,6 +122,11 @@
#define QT_NO_TRANSLATION
#define QT_FEATURE_translation -1
+// rcc.pro will DEFINES+= this
+#ifndef QT_FEATURE_zstd
+#define QT_FEATURE_zstd -1
+#endif
+
#ifdef QT_BUILD_QMAKE
#define QT_FEATURE_commandlineparser -1
#define QT_NO_COMPRESS
diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h
index e9fee5f23e..bd3c219968 100644
--- a/src/corelib/global/qflags.h
+++ b/src/corelib/global/qflags.h
@@ -42,9 +42,7 @@
#ifndef QFLAGS_H
#define QFLAGS_H
-#ifdef Q_COMPILER_INITIALIZER_LISTS
#include <initializer_list>
-#endif
QT_BEGIN_NAMESPACE
@@ -54,21 +52,21 @@ class QFlag
{
int i;
public:
- Q_DECL_CONSTEXPR inline QFlag(int value) Q_DECL_NOTHROW : i(value) {}
- Q_DECL_CONSTEXPR inline operator int() const Q_DECL_NOTHROW { return i; }
+ Q_DECL_CONSTEXPR inline QFlag(int value) noexcept : i(value) {}
+ Q_DECL_CONSTEXPR inline operator int() const noexcept { return i; }
#if !defined(Q_CC_MSVC)
// Microsoft Visual Studio has buggy behavior when it comes to
// unsigned enums: even if the enum is unsigned, the enum tags are
// always signed
# if !defined(__LP64__) && !defined(Q_CLANG_QDOC)
- Q_DECL_CONSTEXPR inline QFlag(long value) Q_DECL_NOTHROW : i(int(value)) {}
- Q_DECL_CONSTEXPR inline QFlag(ulong value) Q_DECL_NOTHROW : i(int(long(value))) {}
+ Q_DECL_CONSTEXPR inline QFlag(long value) noexcept : i(int(value)) {}
+ Q_DECL_CONSTEXPR inline QFlag(ulong value) noexcept : i(int(long(value))) {}
# endif
- Q_DECL_CONSTEXPR inline QFlag(uint value) Q_DECL_NOTHROW : i(int(value)) {}
- Q_DECL_CONSTEXPR inline QFlag(short value) Q_DECL_NOTHROW : i(int(value)) {}
- Q_DECL_CONSTEXPR inline QFlag(ushort value) Q_DECL_NOTHROW : i(int(uint(value))) {}
- Q_DECL_CONSTEXPR inline operator uint() const Q_DECL_NOTHROW { return uint(i); }
+ Q_DECL_CONSTEXPR inline QFlag(uint value) noexcept : i(int(value)) {}
+ Q_DECL_CONSTEXPR inline QFlag(short value) noexcept : i(int(value)) {}
+ Q_DECL_CONSTEXPR inline QFlag(ushort value) noexcept : i(int(uint(value))) {}
+ Q_DECL_CONSTEXPR inline operator uint() const noexcept { return uint(i); }
#endif
};
Q_DECLARE_TYPEINFO(QFlag, Q_PRIMITIVE_TYPE);
@@ -77,12 +75,12 @@ class QIncompatibleFlag
{
int i;
public:
- Q_DECL_CONSTEXPR inline explicit QIncompatibleFlag(int i) Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline operator int() const Q_DECL_NOTHROW { return i; }
+ Q_DECL_CONSTEXPR inline explicit QIncompatibleFlag(int i) noexcept;
+ Q_DECL_CONSTEXPR inline operator int() const noexcept { return i; }
};
Q_DECLARE_TYPEINFO(QIncompatibleFlag, Q_PRIMITIVE_TYPE);
-Q_DECL_CONSTEXPR inline QIncompatibleFlag::QIncompatibleFlag(int value) Q_DECL_NOTHROW : i(value) {}
+Q_DECL_CONSTEXPR inline QIncompatibleFlag::QIncompatibleFlag(int value) noexcept : i(value) {}
#ifndef Q_NO_TYPESAFE_FLAGS
@@ -117,51 +115,47 @@ public:
Q_DECL_CONSTEXPR inline QFlags(const QFlags &other);
Q_DECL_CONSTEXPR inline QFlags &operator=(const QFlags &other);
#endif
- Q_DECL_CONSTEXPR inline QFlags(Enum flags) Q_DECL_NOTHROW : i(Int(flags)) {}
- Q_DECL_CONSTEXPR inline QFlags(Zero = Q_NULLPTR) Q_DECL_NOTHROW : i(0) {}
- Q_DECL_CONSTEXPR inline QFlags(QFlag flag) Q_DECL_NOTHROW : i(flag) {}
+ Q_DECL_CONSTEXPR inline QFlags(Enum flags) noexcept : i(Int(flags)) {}
+ Q_DECL_CONSTEXPR inline QFlags(Zero = nullptr) noexcept : i(0) {}
+ Q_DECL_CONSTEXPR inline QFlags(QFlag flag) noexcept : i(flag) {}
-#ifdef Q_COMPILER_INITIALIZER_LISTS
- Q_DECL_CONSTEXPR inline QFlags(std::initializer_list<Enum> flags) Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR inline QFlags(std::initializer_list<Enum> flags) noexcept
: i(initializer_list_helper(flags.begin(), flags.end())) {}
-#endif
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(int mask) Q_DECL_NOTHROW { i &= mask; return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(uint mask) Q_DECL_NOTHROW { i &= mask; return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(Enum mask) Q_DECL_NOTHROW { i &= Int(mask); return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator|=(QFlags other) Q_DECL_NOTHROW { i |= other.i; return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator|=(Enum other) Q_DECL_NOTHROW { i |= Int(other); return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator^=(QFlags other) Q_DECL_NOTHROW { i ^= other.i; return *this; }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator^=(Enum other) Q_DECL_NOTHROW { i ^= Int(other); return *this; }
-
- Q_DECL_CONSTEXPR inline operator Int() const Q_DECL_NOTHROW { return i; }
-
- Q_DECL_CONSTEXPR inline QFlags operator|(QFlags other) const Q_DECL_NOTHROW { return QFlags(QFlag(i | other.i)); }
- Q_DECL_CONSTEXPR inline QFlags operator|(Enum other) const Q_DECL_NOTHROW { return QFlags(QFlag(i | Int(other))); }
- Q_DECL_CONSTEXPR inline QFlags operator^(QFlags other) const Q_DECL_NOTHROW { return QFlags(QFlag(i ^ other.i)); }
- Q_DECL_CONSTEXPR inline QFlags operator^(Enum other) const Q_DECL_NOTHROW { return QFlags(QFlag(i ^ Int(other))); }
- Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const Q_DECL_NOTHROW { return QFlags(QFlag(i & mask)); }
- Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const Q_DECL_NOTHROW { return QFlags(QFlag(i & mask)); }
- Q_DECL_CONSTEXPR inline QFlags operator&(Enum other) const Q_DECL_NOTHROW { return QFlags(QFlag(i & Int(other))); }
- Q_DECL_CONSTEXPR inline QFlags operator~() const Q_DECL_NOTHROW { return QFlags(QFlag(~i)); }
-
- Q_DECL_CONSTEXPR inline bool operator!() const Q_DECL_NOTHROW { return !i; }
-
- Q_DECL_CONSTEXPR inline bool testFlag(Enum flag) const Q_DECL_NOTHROW { return (i & Int(flag)) == Int(flag) && (Int(flag) != 0 || i == Int(flag) ); }
- Q_DECL_RELAXED_CONSTEXPR inline QFlags &setFlag(Enum flag, bool on = true) Q_DECL_NOTHROW
+ Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(int mask) noexcept { i &= mask; return *this; }
+ Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(uint mask) noexcept { i &= mask; return *this; }
+ Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(Enum mask) noexcept { i &= Int(mask); return *this; }
+ Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator|=(QFlags other) noexcept { i |= other.i; return *this; }
+ Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator|=(Enum other) noexcept { i |= Int(other); return *this; }
+ Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator^=(QFlags other) noexcept { i ^= other.i; return *this; }
+ Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator^=(Enum other) noexcept { i ^= Int(other); return *this; }
+
+ Q_DECL_CONSTEXPR inline operator Int() const noexcept { return i; }
+
+ Q_DECL_CONSTEXPR inline QFlags operator|(QFlags other) const noexcept { return QFlags(QFlag(i | other.i)); }
+ Q_DECL_CONSTEXPR inline QFlags operator|(Enum other) const noexcept { return QFlags(QFlag(i | Int(other))); }
+ Q_DECL_CONSTEXPR inline QFlags operator^(QFlags other) const noexcept { return QFlags(QFlag(i ^ other.i)); }
+ Q_DECL_CONSTEXPR inline QFlags operator^(Enum other) const noexcept { return QFlags(QFlag(i ^ Int(other))); }
+ Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const noexcept { return QFlags(QFlag(i & mask)); }
+ Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const noexcept { return QFlags(QFlag(i & mask)); }
+ Q_DECL_CONSTEXPR inline QFlags operator&(Enum other) const noexcept { return QFlags(QFlag(i & Int(other))); }
+ Q_DECL_CONSTEXPR inline QFlags operator~() const noexcept { return QFlags(QFlag(~i)); }
+
+ Q_DECL_CONSTEXPR inline bool operator!() const noexcept { return !i; }
+
+ Q_DECL_CONSTEXPR inline bool testFlag(Enum flag) const noexcept { return (i & Int(flag)) == Int(flag) && (Int(flag) != 0 || i == Int(flag) ); }
+ Q_DECL_RELAXED_CONSTEXPR inline QFlags &setFlag(Enum flag, bool on = true) noexcept
{
return on ? (*this |= flag) : (*this &= ~Int(flag));
}
private:
-#ifdef Q_COMPILER_INITIALIZER_LISTS
Q_DECL_CONSTEXPR static inline Int initializer_list_helper(typename std::initializer_list<Enum>::const_iterator it,
typename std::initializer_list<Enum>::const_iterator end)
- Q_DECL_NOTHROW
+ noexcept
{
return (it == end ? Int(0) : (Int(*it) | initializer_list_helper(it + 1, end)));
}
-#endif
Int i;
};
@@ -172,13 +166,13 @@ typedef QFlags<Enum> Flags;
#endif
#define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) \
-Q_DECL_CONSTEXPR inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) Q_DECL_NOTHROW \
+Q_DECL_CONSTEXPR inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) noexcept \
{ return QIncompatibleFlag(int(f1) | f2); }
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
-Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) Q_DECL_NOTHROW \
+Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept \
{ return QFlags<Flags::enum_type>(f1) | f2; } \
-Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) Q_DECL_NOTHROW \
+Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
{ return f2 | f1; } Q_DECLARE_INCOMPATIBLE_FLAGS(Flags)
diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp
index 87ff796368..ff2997b73a 100644
--- a/src/corelib/global/qfloat16.cpp
+++ b/src/corelib/global/qfloat16.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 by Southwest Research Institute (R)
** Contact: http://www.qt-project.org/legal
**
@@ -37,8 +38,9 @@
**
****************************************************************************/
-#include "qfloat16_p.h"
+#include "qfloat16.h"
#include "private/qsimd_p.h"
+#include <cmath> // for fpclassify()'s return values
QT_BEGIN_NAMESPACE
@@ -78,28 +80,42 @@ QT_BEGIN_NAMESPACE
*/
/*!
- Returns true if the \c qfloat16 \a {f} is equivalent to infinity.
+ \fn bool qIsInf(qfloat16 f)
\relates <QFloat16>
+ Returns true if the \c qfloat16 \a {f} is equivalent to infinity.
+
\sa qIsInf
*/
-Q_REQUIRED_RESULT bool qIsInf(qfloat16 f) Q_DECL_NOTHROW { return qt_is_inf(f); }
/*!
- Returns true if the \c qfloat16 \a {f} is not a number (NaN).
+ \fn bool qIsNaN(qfloat16 f)
\relates <QFloat16>
+ Returns true if the \c qfloat16 \a {f} is not a number (NaN).
+
\sa qIsNaN
*/
-Q_REQUIRED_RESULT bool qIsNaN(qfloat16 f) Q_DECL_NOTHROW { return qt_is_nan(f); }
/*!
- Returns true if the \c qfloat16 \a {f} is a finite number.
+ \fn bool qIsFinite(qfloat16 f)
\relates <QFloat16>
+ Returns true if the \c qfloat16 \a {f} is a finite number.
+
\sa qIsFinite
*/
-Q_REQUIRED_RESULT bool qIsFinite(qfloat16 f) Q_DECL_NOTHROW { return qt_is_finite(f); }
+
+/*!
+ \internal
+ Implements qFpClassify() for qfloat16.
+ */
+
+int qfloat16::fpClassify() const noexcept
+{
+ return isInf() ? FP_INFINITE : isNaN() ? FP_NAN
+ : !b16 ? FP_ZERO : isNormal() ? FP_NORMAL : FP_SUBNORMAL;
+}
/*! \fn int qRound(qfloat16 value)
\relates <QFloat16>
@@ -142,8 +158,8 @@ extern "C" {
# define f16cextern extern
#endif
-f16cextern void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_NOTHROW;
-f16cextern void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) Q_DECL_NOTHROW;
+f16cextern void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) noexcept;
+f16cextern void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) noexcept;
#undef f16cextern
}
@@ -154,7 +170,7 @@ static inline bool hasFastF16()
return true;
}
-static void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_NOTHROW
+static void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) noexcept
{
__fp16 *out_f16 = reinterpret_cast<__fp16 *>(out);
qsizetype i = 0;
@@ -164,7 +180,7 @@ static void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q
out_f16[i] = __fp16(in[i]);
}
-static void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) Q_DECL_NOTHROW
+static void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) noexcept
{
const __fp16 *in_f16 = reinterpret_cast<const __fp16 *>(in);
qsizetype i = 0;
@@ -179,12 +195,12 @@ static inline bool hasFastF16()
return false;
}
-static void qFloatToFloat16_fast(quint16 *, const float *, qsizetype) Q_DECL_NOTHROW
+static void qFloatToFloat16_fast(quint16 *, const float *, qsizetype) noexcept
{
Q_UNREACHABLE();
}
-static void qFloatFromFloat16_fast(float *, const quint16 *, qsizetype) Q_DECL_NOTHROW
+static void qFloatFromFloat16_fast(float *, const quint16 *, qsizetype) noexcept
{
Q_UNREACHABLE();
}
@@ -196,7 +212,7 @@ static void qFloatFromFloat16_fast(float *, const quint16 *, qsizetype) Q_DECL_N
Converts \a len floats from \a in to qfloat16 and stores them in \a out.
Both \a in and \a out must have \a len allocated entries.
*/
-Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len) Q_DECL_NOTHROW
+Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len) noexcept
{
if (hasFastF16())
return qFloatToFloat16_fast(reinterpret_cast<quint16 *>(out), in, len);
@@ -212,7 +228,7 @@ Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len
Converts \a len qfloat16 from \a in to floats and stores them in \a out.
Both \a in and \a out must have \a len allocated entries.
*/
-Q_CORE_EXPORT void qFloatFromFloat16(float *out, const qfloat16 *in, qsizetype len) Q_DECL_NOTHROW
+Q_CORE_EXPORT void qFloatFromFloat16(float *out, const qfloat16 *in, qsizetype len) noexcept
{
if (hasFastF16())
return qFloatFromFloat16_fast(out, reinterpret_cast<const quint16 *>(in), len);
@@ -223,6 +239,7 @@ Q_CORE_EXPORT void qFloatFromFloat16(float *out, const qfloat16 *in, qsizetype l
QT_END_NAMESPACE
+#include "qfloat16tables.cpp"
#ifdef QFLOAT16_INCLUDE_FAST
# include "qfloat16_f16c.c"
#endif
diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h
index b76d2b9616..4d1aa91349 100644
--- a/src/corelib/global/qfloat16.h
+++ b/src/corelib/global/qfloat16.h
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 by Southwest Research Institute (R)
** Contact: http://www.qt-project.org/legal
**
@@ -66,15 +67,37 @@ QT_BEGIN_NAMESPACE
class qfloat16
{
+ struct Wrap
+ {
+ // To let our private constructor work, without other code seeing
+ // ambiguity when constructing from int, double &c.
+ quint16 b16;
+ constexpr inline explicit Wrap(int value) : b16(value) {}
+ };
public:
-#ifndef Q_QDOC
- Q_DECL_CONSTEXPR inline qfloat16() Q_DECL_NOTHROW : b16(0) { }
- inline qfloat16(float f) Q_DECL_NOTHROW;
- inline operator float() const Q_DECL_NOTHROW;
-#endif
-
+ constexpr inline qfloat16() noexcept : b16(0) {}
+ inline qfloat16(float f) noexcept;
+ inline operator float() const noexcept;
+
+ // Support for qIs{Inf,NaN,Finite}:
+ bool isInf() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7c; }
+ bool isNaN() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7e; }
+ bool isFinite() const noexcept { return ((b16 >> 8) & 0x7c) != 0x7c; }
+ Q_CORE_EXPORT int fpClassify() const noexcept;
+ // Support for std::numeric_limits<qfloat16>
+ static constexpr qfloat16 _limit_epsilon() noexcept { return qfloat16(Wrap(0x1400)); }
+ static constexpr qfloat16 _limit_min() noexcept { return qfloat16(Wrap(0x400)); }
+ static constexpr qfloat16 _limit_denorm_min() noexcept { return qfloat16(Wrap(1)); }
+ static constexpr qfloat16 _limit_max() noexcept { return qfloat16(Wrap(0x7bff)); }
+ static constexpr qfloat16 _limit_lowest() noexcept { return qfloat16(Wrap(0xfbff)); }
+ static constexpr qfloat16 _limit_infinity() noexcept { return qfloat16(Wrap(0x7c00)); }
+ static constexpr qfloat16 _limit_quiet_NaN() noexcept { return qfloat16(Wrap(0x7e00)); }
+ // Signalling NaN is 0x7f00
+ inline constexpr bool isNormal() const noexcept
+ { return b16 == 0 || ((b16 & 0x7c00) && (b16 & 0x7c00) != 0x7c00); }
private:
quint16 b16;
+ constexpr inline explicit qfloat16(Wrap nibble) noexcept : b16(nibble.b16) {}
Q_CORE_EXPORT static const quint32 mantissatable[];
Q_CORE_EXPORT static const quint32 exponenttable[];
@@ -82,29 +105,32 @@ private:
Q_CORE_EXPORT static const quint32 basetable[];
Q_CORE_EXPORT static const quint32 shifttable[];
- friend bool qIsNull(qfloat16 f) Q_DECL_NOTHROW;
+ friend bool qIsNull(qfloat16 f) noexcept;
#if !defined(QT_NO_FLOAT16_OPERATORS)
- friend qfloat16 operator-(qfloat16 a) Q_DECL_NOTHROW;
+ friend qfloat16 operator-(qfloat16 a) noexcept;
#endif
};
Q_DECLARE_TYPEINFO(qfloat16, Q_PRIMITIVE_TYPE);
-Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *, const float *, qsizetype length) Q_DECL_NOTHROW;
-Q_CORE_EXPORT void qFloatFromFloat16(float *, const qfloat16 *, qsizetype length) Q_DECL_NOTHROW;
+Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *, const float *, qsizetype length) noexcept;
+Q_CORE_EXPORT void qFloatFromFloat16(float *, const qfloat16 *, qsizetype length) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT bool qIsInf(qfloat16 f) Q_DECL_NOTHROW; // complements qnumeric.h
-Q_REQUIRED_RESULT Q_CORE_EXPORT bool qIsNaN(qfloat16 f) Q_DECL_NOTHROW; // complements qnumeric.h
-Q_REQUIRED_RESULT Q_CORE_EXPORT bool qIsFinite(qfloat16 f) Q_DECL_NOTHROW; // complements qnumeric.h
+// Complement qnumeric.h:
+Q_REQUIRED_RESULT inline bool qIsInf(qfloat16 f) noexcept { return f.isInf(); }
+Q_REQUIRED_RESULT inline bool qIsNaN(qfloat16 f) noexcept { return f.isNaN(); }
+Q_REQUIRED_RESULT inline bool qIsFinite(qfloat16 f) noexcept { return f.isFinite(); }
+Q_REQUIRED_RESULT inline int qFpClassify(qfloat16 f) noexcept { return f.fpClassify(); }
+// Q_REQUIRED_RESULT quint32 qFloatDistance(qfloat16 a, qfloat16 b);
// The remainder of these utility functions complement qglobal.h
-Q_REQUIRED_RESULT inline int qRound(qfloat16 d) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline int qRound(qfloat16 d) noexcept
{ return qRound(static_cast<float>(d)); }
-Q_REQUIRED_RESULT inline qint64 qRound64(qfloat16 d) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline qint64 qRound64(qfloat16 d) noexcept
{ return qRound64(static_cast<float>(d)); }
-Q_REQUIRED_RESULT inline bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
{
float f1 = static_cast<float>(p1);
float f2 = static_cast<float>(p2);
@@ -117,19 +143,19 @@ Q_REQUIRED_RESULT inline bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) Q_DECL_NOT
return (qAbs(f1 - f2) * 102.5f <= qMin(qAbs(f1), qAbs(f2)));
}
-Q_REQUIRED_RESULT inline bool qIsNull(qfloat16 f) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline bool qIsNull(qfloat16 f) noexcept
{
return (f.b16 & static_cast<quint16>(0x7fff)) == 0;
}
-inline int qIntCast(qfloat16 f) Q_DECL_NOTHROW
+inline int qIntCast(qfloat16 f) noexcept
{ return int(static_cast<float>(f)); }
#ifndef Q_QDOC
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wc99-extensions")
QT_WARNING_DISABLE_GCC("-Wold-style-cast")
-inline qfloat16::qfloat16(float f) Q_DECL_NOTHROW
+inline qfloat16::qfloat16(float f) noexcept
{
#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)
__m128 packsingle = _mm_set_ss(f);
@@ -147,7 +173,7 @@ inline qfloat16::qfloat16(float f) Q_DECL_NOTHROW
}
QT_WARNING_POP
-inline qfloat16::operator float() const Q_DECL_NOTHROW
+inline qfloat16::operator float() const noexcept
{
#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)
__m128i packhalf = _mm_cvtsi32_si128(b16);
@@ -168,23 +194,23 @@ inline qfloat16::operator float() const Q_DECL_NOTHROW
#endif
#if !defined(QT_NO_FLOAT16_OPERATORS)
-inline qfloat16 operator-(qfloat16 a) Q_DECL_NOTHROW
+inline qfloat16 operator-(qfloat16 a) noexcept
{
qfloat16 f;
f.b16 = a.b16 ^ quint16(0x8000);
return f;
}
-inline qfloat16 operator+(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return qfloat16(static_cast<float>(a) + static_cast<float>(b)); }
-inline qfloat16 operator-(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return qfloat16(static_cast<float>(a) - static_cast<float>(b)); }
-inline qfloat16 operator*(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return qfloat16(static_cast<float>(a) * static_cast<float>(b)); }
-inline qfloat16 operator/(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return qfloat16(static_cast<float>(a) / static_cast<float>(b)); }
+inline qfloat16 operator+(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<float>(a) + static_cast<float>(b)); }
+inline qfloat16 operator-(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<float>(a) - static_cast<float>(b)); }
+inline qfloat16 operator*(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<float>(a) * static_cast<float>(b)); }
+inline qfloat16 operator/(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<float>(a) / static_cast<float>(b)); }
#define QF16_MAKE_ARITH_OP_FP(FP, OP) \
- inline FP operator OP(qfloat16 lhs, FP rhs) Q_DECL_NOTHROW { return static_cast<FP>(lhs) OP rhs; } \
- inline FP operator OP(FP lhs, qfloat16 rhs) Q_DECL_NOTHROW { return lhs OP static_cast<FP>(rhs); }
+ inline FP operator OP(qfloat16 lhs, FP rhs) noexcept { return static_cast<FP>(lhs) OP rhs; } \
+ inline FP operator OP(FP lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<FP>(rhs); }
#define QF16_MAKE_ARITH_OP_EQ_FP(FP, OP_EQ, OP) \
- inline qfloat16& operator OP_EQ(qfloat16& lhs, FP rhs) Q_DECL_NOTHROW \
+ inline qfloat16& operator OP_EQ(qfloat16& lhs, FP rhs) noexcept \
{ lhs = qfloat16(float(static_cast<FP>(lhs) OP rhs)); return lhs; }
#define QF16_MAKE_ARITH_OP(FP) \
QF16_MAKE_ARITH_OP_FP(FP, +) \
@@ -202,8 +228,8 @@ QF16_MAKE_ARITH_OP(float)
#undef QF16_MAKE_ARITH_OP_FP
#define QF16_MAKE_ARITH_OP_INT(OP) \
- inline double operator OP(qfloat16 lhs, int rhs) Q_DECL_NOTHROW { return static_cast<double>(lhs) OP rhs; } \
- inline double operator OP(int lhs, qfloat16 rhs) Q_DECL_NOTHROW { return lhs OP static_cast<double>(rhs); }
+ inline double operator OP(qfloat16 lhs, int rhs) noexcept { return static_cast<double>(lhs) OP rhs; } \
+ inline double operator OP(int lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<double>(rhs); }
QF16_MAKE_ARITH_OP_INT(+)
QF16_MAKE_ARITH_OP_INT(-)
QF16_MAKE_ARITH_OP_INT(*)
@@ -214,16 +240,16 @@ QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal")
-inline bool operator>(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return static_cast<float>(a) > static_cast<float>(b); }
-inline bool operator<(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return static_cast<float>(a) < static_cast<float>(b); }
-inline bool operator>=(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return static_cast<float>(a) >= static_cast<float>(b); }
-inline bool operator<=(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return static_cast<float>(a) <= static_cast<float>(b); }
-inline bool operator==(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return static_cast<float>(a) == static_cast<float>(b); }
-inline bool operator!=(qfloat16 a, qfloat16 b) Q_DECL_NOTHROW { return static_cast<float>(a) != static_cast<float>(b); }
+inline bool operator>(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) > static_cast<float>(b); }
+inline bool operator<(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) < static_cast<float>(b); }
+inline bool operator>=(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) >= static_cast<float>(b); }
+inline bool operator<=(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) <= static_cast<float>(b); }
+inline bool operator==(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) == static_cast<float>(b); }
+inline bool operator!=(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) != static_cast<float>(b); }
#define QF16_MAKE_BOOL_OP_FP(FP, OP) \
- inline bool operator OP(qfloat16 lhs, FP rhs) Q_DECL_NOTHROW { return static_cast<FP>(lhs) OP rhs; } \
- inline bool operator OP(FP lhs, qfloat16 rhs) Q_DECL_NOTHROW { return lhs OP static_cast<FP>(rhs); }
+ inline bool operator OP(qfloat16 lhs, FP rhs) noexcept { return static_cast<FP>(lhs) OP rhs; } \
+ inline bool operator OP(FP lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<FP>(rhs); }
#define QF16_MAKE_BOOL_OP(FP) \
QF16_MAKE_BOOL_OP_FP(FP, <) \
QF16_MAKE_BOOL_OP_FP(FP, >) \
@@ -238,8 +264,8 @@ QF16_MAKE_BOOL_OP(float)
#undef QF16_MAKE_BOOL_OP_FP
#define QF16_MAKE_BOOL_OP_INT(OP) \
- inline bool operator OP(qfloat16 a, int b) Q_DECL_NOTHROW { return static_cast<float>(a) OP b; } \
- inline bool operator OP(int a, qfloat16 b) Q_DECL_NOTHROW { return a OP static_cast<float>(b); }
+ inline bool operator OP(qfloat16 a, int b) noexcept { return static_cast<float>(a) OP b; } \
+ inline bool operator OP(int a, qfloat16 b) noexcept { return a OP static_cast<float>(b); }
QF16_MAKE_BOOL_OP_INT(>)
QF16_MAKE_BOOL_OP_INT(<)
QF16_MAKE_BOOL_OP_INT(>=)
@@ -254,7 +280,7 @@ QT_WARNING_POP
/*!
\internal
*/
-Q_REQUIRED_RESULT inline bool qFuzzyIsNull(qfloat16 f) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline bool qFuzzyIsNull(qfloat16 f) noexcept
{
return qAbs(static_cast<float>(f)) <= 0.001f;
}
@@ -263,4 +289,55 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(qfloat16)
+namespace std {
+template<>
+class numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> : public numeric_limits<float>
+{
+public:
+ /*
+ Treat quint16 b16 as if it were:
+ uint S: 1; // b16 >> 15 (sign)
+ uint E: 5; // (b16 >> 10) & 0x1f (offset exponent)
+ uint M: 10; // b16 & 0x3ff (adjusted mantissa)
+
+ for E == 0: magnitude is M / 2.^{24}
+ for 0 < E < 31: magnitude is (1. + M / 2.^{10}) * 2.^{E - 15)
+ for E == 31: not finite
+ */
+ static constexpr int digits = 11;
+ static constexpr int min_exponent = -13;
+ static constexpr int max_exponent = 16;
+
+ static constexpr int digits10 = 3;
+ static constexpr int max_digits10 = 5;
+ static constexpr int min_exponent10 = -4;
+ static constexpr int max_exponent10 = 4;
+
+ static constexpr QT_PREPEND_NAMESPACE(qfloat16) epsilon()
+ { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_epsilon(); }
+ static constexpr QT_PREPEND_NAMESPACE(qfloat16) (min)()
+ { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_min(); }
+ static constexpr QT_PREPEND_NAMESPACE(qfloat16) denorm_min()
+ { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_denorm_min(); }
+ static constexpr QT_PREPEND_NAMESPACE(qfloat16) (max)()
+ { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_max(); }
+ static constexpr QT_PREPEND_NAMESPACE(qfloat16) lowest()
+ { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_lowest(); }
+ static constexpr QT_PREPEND_NAMESPACE(qfloat16) infinity()
+ { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_infinity(); }
+ static constexpr QT_PREPEND_NAMESPACE(qfloat16) quiet_NaN()
+ { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_quiet_NaN(); }
+};
+
+template<> class numeric_limits<const QT_PREPEND_NAMESPACE(qfloat16)>
+ : public numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> {};
+template<> class numeric_limits<volatile QT_PREPEND_NAMESPACE(qfloat16)>
+ : public numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> {};
+template<> class numeric_limits<const volatile QT_PREPEND_NAMESPACE(qfloat16)>
+ : public numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> {};
+
+// Adding overloads to std isn't allowed, so we can't extend this to support
+// for fpclassify(), isnormal() &c. (which, furthermore, are macros on MinGW).
+} // namespace std
+
#endif // QFLOAT16_H
diff --git a/src/corelib/global/qfloat16_f16c.c b/src/corelib/global/qfloat16_f16c.c
index a7eadc71b7..ba1e16f481 100644
--- a/src/corelib/global/qfloat16_f16c.c
+++ b/src/corelib/global/qfloat16_f16c.c
@@ -54,7 +54,7 @@ extern "C" {
#endif
QT_FUNCTION_TARGET(F16C)
-void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_NOTHROW
+void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_NOEXCEPT
{
qsizetype i = 0;
int epilog_i;
@@ -70,7 +70,7 @@ void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_N
}
QT_FUNCTION_TARGET(F16C)
-void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) Q_DECL_NOTHROW
+void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) Q_DECL_NOEXCEPT
{
qsizetype i = 0;
int epilog_i;
diff --git a/src/corelib/global/qfloat16tables.cpp b/src/corelib/global/qfloat16tables.cpp
new file mode 100644
index 0000000000..3d764937d7
--- /dev/null
+++ b/src/corelib/global/qfloat16tables.cpp
@@ -0,0 +1,3266 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 by Southwest Research Institute (R)
+** Copyright (C) 2019 Intel Corporation.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* This file was generated by gen_qfloat16_tables.cpp */
+
+#include <QtCore/qfloat16.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(__F16C__) && !defined(__ARM_FP16_FORMAT_IEEE)
+
+const quint32 qfloat16::mantissatable[2048] = {
+0,
+0x33800000U,
+0x34000000U,
+0x34400000U,
+0x34800000U,
+0x34A00000U,
+0x34C00000U,
+0x34E00000U,
+0x35000000U,
+0x35100000U,
+0x35200000U,
+0x35300000U,
+0x35400000U,
+0x35500000U,
+0x35600000U,
+0x35700000U,
+0x35800000U,
+0x35880000U,
+0x35900000U,
+0x35980000U,
+0x35A00000U,
+0x35A80000U,
+0x35B00000U,
+0x35B80000U,
+0x35C00000U,
+0x35C80000U,
+0x35D00000U,
+0x35D80000U,
+0x35E00000U,
+0x35E80000U,
+0x35F00000U,
+0x35F80000U,
+0x36000000U,
+0x36040000U,
+0x36080000U,
+0x360C0000U,
+0x36100000U,
+0x36140000U,
+0x36180000U,
+0x361C0000U,
+0x36200000U,
+0x36240000U,
+0x36280000U,
+0x362C0000U,
+0x36300000U,
+0x36340000U,
+0x36380000U,
+0x363C0000U,
+0x36400000U,
+0x36440000U,
+0x36480000U,
+0x364C0000U,
+0x36500000U,
+0x36540000U,
+0x36580000U,
+0x365C0000U,
+0x36600000U,
+0x36640000U,
+0x36680000U,
+0x366C0000U,
+0x36700000U,
+0x36740000U,
+0x36780000U,
+0x367C0000U,
+0x36800000U,
+0x36820000U,
+0x36840000U,
+0x36860000U,
+0x36880000U,
+0x368A0000U,
+0x368C0000U,
+0x368E0000U,
+0x36900000U,
+0x36920000U,
+0x36940000U,
+0x36960000U,
+0x36980000U,
+0x369A0000U,
+0x369C0000U,
+0x369E0000U,
+0x36A00000U,
+0x36A20000U,
+0x36A40000U,
+0x36A60000U,
+0x36A80000U,
+0x36AA0000U,
+0x36AC0000U,
+0x36AE0000U,
+0x36B00000U,
+0x36B20000U,
+0x36B40000U,
+0x36B60000U,
+0x36B80000U,
+0x36BA0000U,
+0x36BC0000U,
+0x36BE0000U,
+0x36C00000U,
+0x36C20000U,
+0x36C40000U,
+0x36C60000U,
+0x36C80000U,
+0x36CA0000U,
+0x36CC0000U,
+0x36CE0000U,
+0x36D00000U,
+0x36D20000U,
+0x36D40000U,
+0x36D60000U,
+0x36D80000U,
+0x36DA0000U,
+0x36DC0000U,
+0x36DE0000U,
+0x36E00000U,
+0x36E20000U,
+0x36E40000U,
+0x36E60000U,
+0x36E80000U,
+0x36EA0000U,
+0x36EC0000U,
+0x36EE0000U,
+0x36F00000U,
+0x36F20000U,
+0x36F40000U,
+0x36F60000U,
+0x36F80000U,
+0x36FA0000U,
+0x36FC0000U,
+0x36FE0000U,
+0x37000000U,
+0x37010000U,
+0x37020000U,
+0x37030000U,
+0x37040000U,
+0x37050000U,
+0x37060000U,
+0x37070000U,
+0x37080000U,
+0x37090000U,
+0x370A0000U,
+0x370B0000U,
+0x370C0000U,
+0x370D0000U,
+0x370E0000U,
+0x370F0000U,
+0x37100000U,
+0x37110000U,
+0x37120000U,
+0x37130000U,
+0x37140000U,
+0x37150000U,
+0x37160000U,
+0x37170000U,
+0x37180000U,
+0x37190000U,
+0x371A0000U,
+0x371B0000U,
+0x371C0000U,
+0x371D0000U,
+0x371E0000U,
+0x371F0000U,
+0x37200000U,
+0x37210000U,
+0x37220000U,
+0x37230000U,
+0x37240000U,
+0x37250000U,
+0x37260000U,
+0x37270000U,
+0x37280000U,
+0x37290000U,
+0x372A0000U,
+0x372B0000U,
+0x372C0000U,
+0x372D0000U,
+0x372E0000U,
+0x372F0000U,
+0x37300000U,
+0x37310000U,
+0x37320000U,
+0x37330000U,
+0x37340000U,
+0x37350000U,
+0x37360000U,
+0x37370000U,
+0x37380000U,
+0x37390000U,
+0x373A0000U,
+0x373B0000U,
+0x373C0000U,
+0x373D0000U,
+0x373E0000U,
+0x373F0000U,
+0x37400000U,
+0x37410000U,
+0x37420000U,
+0x37430000U,
+0x37440000U,
+0x37450000U,
+0x37460000U,
+0x37470000U,
+0x37480000U,
+0x37490000U,
+0x374A0000U,
+0x374B0000U,
+0x374C0000U,
+0x374D0000U,
+0x374E0000U,
+0x374F0000U,
+0x37500000U,
+0x37510000U,
+0x37520000U,
+0x37530000U,
+0x37540000U,
+0x37550000U,
+0x37560000U,
+0x37570000U,
+0x37580000U,
+0x37590000U,
+0x375A0000U,
+0x375B0000U,
+0x375C0000U,
+0x375D0000U,
+0x375E0000U,
+0x375F0000U,
+0x37600000U,
+0x37610000U,
+0x37620000U,
+0x37630000U,
+0x37640000U,
+0x37650000U,
+0x37660000U,
+0x37670000U,
+0x37680000U,
+0x37690000U,
+0x376A0000U,
+0x376B0000U,
+0x376C0000U,
+0x376D0000U,
+0x376E0000U,
+0x376F0000U,
+0x37700000U,
+0x37710000U,
+0x37720000U,
+0x37730000U,
+0x37740000U,
+0x37750000U,
+0x37760000U,
+0x37770000U,
+0x37780000U,
+0x37790000U,
+0x377A0000U,
+0x377B0000U,
+0x377C0000U,
+0x377D0000U,
+0x377E0000U,
+0x377F0000U,
+0x37800000U,
+0x37808000U,
+0x37810000U,
+0x37818000U,
+0x37820000U,
+0x37828000U,
+0x37830000U,
+0x37838000U,
+0x37840000U,
+0x37848000U,
+0x37850000U,
+0x37858000U,
+0x37860000U,
+0x37868000U,
+0x37870000U,
+0x37878000U,
+0x37880000U,
+0x37888000U,
+0x37890000U,
+0x37898000U,
+0x378A0000U,
+0x378A8000U,
+0x378B0000U,
+0x378B8000U,
+0x378C0000U,
+0x378C8000U,
+0x378D0000U,
+0x378D8000U,
+0x378E0000U,
+0x378E8000U,
+0x378F0000U,
+0x378F8000U,
+0x37900000U,
+0x37908000U,
+0x37910000U,
+0x37918000U,
+0x37920000U,
+0x37928000U,
+0x37930000U,
+0x37938000U,
+0x37940000U,
+0x37948000U,
+0x37950000U,
+0x37958000U,
+0x37960000U,
+0x37968000U,
+0x37970000U,
+0x37978000U,
+0x37980000U,
+0x37988000U,
+0x37990000U,
+0x37998000U,
+0x379A0000U,
+0x379A8000U,
+0x379B0000U,
+0x379B8000U,
+0x379C0000U,
+0x379C8000U,
+0x379D0000U,
+0x379D8000U,
+0x379E0000U,
+0x379E8000U,
+0x379F0000U,
+0x379F8000U,
+0x37A00000U,
+0x37A08000U,
+0x37A10000U,
+0x37A18000U,
+0x37A20000U,
+0x37A28000U,
+0x37A30000U,
+0x37A38000U,
+0x37A40000U,
+0x37A48000U,
+0x37A50000U,
+0x37A58000U,
+0x37A60000U,
+0x37A68000U,
+0x37A70000U,
+0x37A78000U,
+0x37A80000U,
+0x37A88000U,
+0x37A90000U,
+0x37A98000U,
+0x37AA0000U,
+0x37AA8000U,
+0x37AB0000U,
+0x37AB8000U,
+0x37AC0000U,
+0x37AC8000U,
+0x37AD0000U,
+0x37AD8000U,
+0x37AE0000U,
+0x37AE8000U,
+0x37AF0000U,
+0x37AF8000U,
+0x37B00000U,
+0x37B08000U,
+0x37B10000U,
+0x37B18000U,
+0x37B20000U,
+0x37B28000U,
+0x37B30000U,
+0x37B38000U,
+0x37B40000U,
+0x37B48000U,
+0x37B50000U,
+0x37B58000U,
+0x37B60000U,
+0x37B68000U,
+0x37B70000U,
+0x37B78000U,
+0x37B80000U,
+0x37B88000U,
+0x37B90000U,
+0x37B98000U,
+0x37BA0000U,
+0x37BA8000U,
+0x37BB0000U,
+0x37BB8000U,
+0x37BC0000U,
+0x37BC8000U,
+0x37BD0000U,
+0x37BD8000U,
+0x37BE0000U,
+0x37BE8000U,
+0x37BF0000U,
+0x37BF8000U,
+0x37C00000U,
+0x37C08000U,
+0x37C10000U,
+0x37C18000U,
+0x37C20000U,
+0x37C28000U,
+0x37C30000U,
+0x37C38000U,
+0x37C40000U,
+0x37C48000U,
+0x37C50000U,
+0x37C58000U,
+0x37C60000U,
+0x37C68000U,
+0x37C70000U,
+0x37C78000U,
+0x37C80000U,
+0x37C88000U,
+0x37C90000U,
+0x37C98000U,
+0x37CA0000U,
+0x37CA8000U,
+0x37CB0000U,
+0x37CB8000U,
+0x37CC0000U,
+0x37CC8000U,
+0x37CD0000U,
+0x37CD8000U,
+0x37CE0000U,
+0x37CE8000U,
+0x37CF0000U,
+0x37CF8000U,
+0x37D00000U,
+0x37D08000U,
+0x37D10000U,
+0x37D18000U,
+0x37D20000U,
+0x37D28000U,
+0x37D30000U,
+0x37D38000U,
+0x37D40000U,
+0x37D48000U,
+0x37D50000U,
+0x37D58000U,
+0x37D60000U,
+0x37D68000U,
+0x37D70000U,
+0x37D78000U,
+0x37D80000U,
+0x37D88000U,
+0x37D90000U,
+0x37D98000U,
+0x37DA0000U,
+0x37DA8000U,
+0x37DB0000U,
+0x37DB8000U,
+0x37DC0000U,
+0x37DC8000U,
+0x37DD0000U,
+0x37DD8000U,
+0x37DE0000U,
+0x37DE8000U,
+0x37DF0000U,
+0x37DF8000U,
+0x37E00000U,
+0x37E08000U,
+0x37E10000U,
+0x37E18000U,
+0x37E20000U,
+0x37E28000U,
+0x37E30000U,
+0x37E38000U,
+0x37E40000U,
+0x37E48000U,
+0x37E50000U,
+0x37E58000U,
+0x37E60000U,
+0x37E68000U,
+0x37E70000U,
+0x37E78000U,
+0x37E80000U,
+0x37E88000U,
+0x37E90000U,
+0x37E98000U,
+0x37EA0000U,
+0x37EA8000U,
+0x37EB0000U,
+0x37EB8000U,
+0x37EC0000U,
+0x37EC8000U,
+0x37ED0000U,
+0x37ED8000U,
+0x37EE0000U,
+0x37EE8000U,
+0x37EF0000U,
+0x37EF8000U,
+0x37F00000U,
+0x37F08000U,
+0x37F10000U,
+0x37F18000U,
+0x37F20000U,
+0x37F28000U,
+0x37F30000U,
+0x37F38000U,
+0x37F40000U,
+0x37F48000U,
+0x37F50000U,
+0x37F58000U,
+0x37F60000U,
+0x37F68000U,
+0x37F70000U,
+0x37F78000U,
+0x37F80000U,
+0x37F88000U,
+0x37F90000U,
+0x37F98000U,
+0x37FA0000U,
+0x37FA8000U,
+0x37FB0000U,
+0x37FB8000U,
+0x37FC0000U,
+0x37FC8000U,
+0x37FD0000U,
+0x37FD8000U,
+0x37FE0000U,
+0x37FE8000U,
+0x37FF0000U,
+0x37FF8000U,
+0x38000000U,
+0x38004000U,
+0x38008000U,
+0x3800C000U,
+0x38010000U,
+0x38014000U,
+0x38018000U,
+0x3801C000U,
+0x38020000U,
+0x38024000U,
+0x38028000U,
+0x3802C000U,
+0x38030000U,
+0x38034000U,
+0x38038000U,
+0x3803C000U,
+0x38040000U,
+0x38044000U,
+0x38048000U,
+0x3804C000U,
+0x38050000U,
+0x38054000U,
+0x38058000U,
+0x3805C000U,
+0x38060000U,
+0x38064000U,
+0x38068000U,
+0x3806C000U,
+0x38070000U,
+0x38074000U,
+0x38078000U,
+0x3807C000U,
+0x38080000U,
+0x38084000U,
+0x38088000U,
+0x3808C000U,
+0x38090000U,
+0x38094000U,
+0x38098000U,
+0x3809C000U,
+0x380A0000U,
+0x380A4000U,
+0x380A8000U,
+0x380AC000U,
+0x380B0000U,
+0x380B4000U,
+0x380B8000U,
+0x380BC000U,
+0x380C0000U,
+0x380C4000U,
+0x380C8000U,
+0x380CC000U,
+0x380D0000U,
+0x380D4000U,
+0x380D8000U,
+0x380DC000U,
+0x380E0000U,
+0x380E4000U,
+0x380E8000U,
+0x380EC000U,
+0x380F0000U,
+0x380F4000U,
+0x380F8000U,
+0x380FC000U,
+0x38100000U,
+0x38104000U,
+0x38108000U,
+0x3810C000U,
+0x38110000U,
+0x38114000U,
+0x38118000U,
+0x3811C000U,
+0x38120000U,
+0x38124000U,
+0x38128000U,
+0x3812C000U,
+0x38130000U,
+0x38134000U,
+0x38138000U,
+0x3813C000U,
+0x38140000U,
+0x38144000U,
+0x38148000U,
+0x3814C000U,
+0x38150000U,
+0x38154000U,
+0x38158000U,
+0x3815C000U,
+0x38160000U,
+0x38164000U,
+0x38168000U,
+0x3816C000U,
+0x38170000U,
+0x38174000U,
+0x38178000U,
+0x3817C000U,
+0x38180000U,
+0x38184000U,
+0x38188000U,
+0x3818C000U,
+0x38190000U,
+0x38194000U,
+0x38198000U,
+0x3819C000U,
+0x381A0000U,
+0x381A4000U,
+0x381A8000U,
+0x381AC000U,
+0x381B0000U,
+0x381B4000U,
+0x381B8000U,
+0x381BC000U,
+0x381C0000U,
+0x381C4000U,
+0x381C8000U,
+0x381CC000U,
+0x381D0000U,
+0x381D4000U,
+0x381D8000U,
+0x381DC000U,
+0x381E0000U,
+0x381E4000U,
+0x381E8000U,
+0x381EC000U,
+0x381F0000U,
+0x381F4000U,
+0x381F8000U,
+0x381FC000U,
+0x38200000U,
+0x38204000U,
+0x38208000U,
+0x3820C000U,
+0x38210000U,
+0x38214000U,
+0x38218000U,
+0x3821C000U,
+0x38220000U,
+0x38224000U,
+0x38228000U,
+0x3822C000U,
+0x38230000U,
+0x38234000U,
+0x38238000U,
+0x3823C000U,
+0x38240000U,
+0x38244000U,
+0x38248000U,
+0x3824C000U,
+0x38250000U,
+0x38254000U,
+0x38258000U,
+0x3825C000U,
+0x38260000U,
+0x38264000U,
+0x38268000U,
+0x3826C000U,
+0x38270000U,
+0x38274000U,
+0x38278000U,
+0x3827C000U,
+0x38280000U,
+0x38284000U,
+0x38288000U,
+0x3828C000U,
+0x38290000U,
+0x38294000U,
+0x38298000U,
+0x3829C000U,
+0x382A0000U,
+0x382A4000U,
+0x382A8000U,
+0x382AC000U,
+0x382B0000U,
+0x382B4000U,
+0x382B8000U,
+0x382BC000U,
+0x382C0000U,
+0x382C4000U,
+0x382C8000U,
+0x382CC000U,
+0x382D0000U,
+0x382D4000U,
+0x382D8000U,
+0x382DC000U,
+0x382E0000U,
+0x382E4000U,
+0x382E8000U,
+0x382EC000U,
+0x382F0000U,
+0x382F4000U,
+0x382F8000U,
+0x382FC000U,
+0x38300000U,
+0x38304000U,
+0x38308000U,
+0x3830C000U,
+0x38310000U,
+0x38314000U,
+0x38318000U,
+0x3831C000U,
+0x38320000U,
+0x38324000U,
+0x38328000U,
+0x3832C000U,
+0x38330000U,
+0x38334000U,
+0x38338000U,
+0x3833C000U,
+0x38340000U,
+0x38344000U,
+0x38348000U,
+0x3834C000U,
+0x38350000U,
+0x38354000U,
+0x38358000U,
+0x3835C000U,
+0x38360000U,
+0x38364000U,
+0x38368000U,
+0x3836C000U,
+0x38370000U,
+0x38374000U,
+0x38378000U,
+0x3837C000U,
+0x38380000U,
+0x38384000U,
+0x38388000U,
+0x3838C000U,
+0x38390000U,
+0x38394000U,
+0x38398000U,
+0x3839C000U,
+0x383A0000U,
+0x383A4000U,
+0x383A8000U,
+0x383AC000U,
+0x383B0000U,
+0x383B4000U,
+0x383B8000U,
+0x383BC000U,
+0x383C0000U,
+0x383C4000U,
+0x383C8000U,
+0x383CC000U,
+0x383D0000U,
+0x383D4000U,
+0x383D8000U,
+0x383DC000U,
+0x383E0000U,
+0x383E4000U,
+0x383E8000U,
+0x383EC000U,
+0x383F0000U,
+0x383F4000U,
+0x383F8000U,
+0x383FC000U,
+0x38400000U,
+0x38404000U,
+0x38408000U,
+0x3840C000U,
+0x38410000U,
+0x38414000U,
+0x38418000U,
+0x3841C000U,
+0x38420000U,
+0x38424000U,
+0x38428000U,
+0x3842C000U,
+0x38430000U,
+0x38434000U,
+0x38438000U,
+0x3843C000U,
+0x38440000U,
+0x38444000U,
+0x38448000U,
+0x3844C000U,
+0x38450000U,
+0x38454000U,
+0x38458000U,
+0x3845C000U,
+0x38460000U,
+0x38464000U,
+0x38468000U,
+0x3846C000U,
+0x38470000U,
+0x38474000U,
+0x38478000U,
+0x3847C000U,
+0x38480000U,
+0x38484000U,
+0x38488000U,
+0x3848C000U,
+0x38490000U,
+0x38494000U,
+0x38498000U,
+0x3849C000U,
+0x384A0000U,
+0x384A4000U,
+0x384A8000U,
+0x384AC000U,
+0x384B0000U,
+0x384B4000U,
+0x384B8000U,
+0x384BC000U,
+0x384C0000U,
+0x384C4000U,
+0x384C8000U,
+0x384CC000U,
+0x384D0000U,
+0x384D4000U,
+0x384D8000U,
+0x384DC000U,
+0x384E0000U,
+0x384E4000U,
+0x384E8000U,
+0x384EC000U,
+0x384F0000U,
+0x384F4000U,
+0x384F8000U,
+0x384FC000U,
+0x38500000U,
+0x38504000U,
+0x38508000U,
+0x3850C000U,
+0x38510000U,
+0x38514000U,
+0x38518000U,
+0x3851C000U,
+0x38520000U,
+0x38524000U,
+0x38528000U,
+0x3852C000U,
+0x38530000U,
+0x38534000U,
+0x38538000U,
+0x3853C000U,
+0x38540000U,
+0x38544000U,
+0x38548000U,
+0x3854C000U,
+0x38550000U,
+0x38554000U,
+0x38558000U,
+0x3855C000U,
+0x38560000U,
+0x38564000U,
+0x38568000U,
+0x3856C000U,
+0x38570000U,
+0x38574000U,
+0x38578000U,
+0x3857C000U,
+0x38580000U,
+0x38584000U,
+0x38588000U,
+0x3858C000U,
+0x38590000U,
+0x38594000U,
+0x38598000U,
+0x3859C000U,
+0x385A0000U,
+0x385A4000U,
+0x385A8000U,
+0x385AC000U,
+0x385B0000U,
+0x385B4000U,
+0x385B8000U,
+0x385BC000U,
+0x385C0000U,
+0x385C4000U,
+0x385C8000U,
+0x385CC000U,
+0x385D0000U,
+0x385D4000U,
+0x385D8000U,
+0x385DC000U,
+0x385E0000U,
+0x385E4000U,
+0x385E8000U,
+0x385EC000U,
+0x385F0000U,
+0x385F4000U,
+0x385F8000U,
+0x385FC000U,
+0x38600000U,
+0x38604000U,
+0x38608000U,
+0x3860C000U,
+0x38610000U,
+0x38614000U,
+0x38618000U,
+0x3861C000U,
+0x38620000U,
+0x38624000U,
+0x38628000U,
+0x3862C000U,
+0x38630000U,
+0x38634000U,
+0x38638000U,
+0x3863C000U,
+0x38640000U,
+0x38644000U,
+0x38648000U,
+0x3864C000U,
+0x38650000U,
+0x38654000U,
+0x38658000U,
+0x3865C000U,
+0x38660000U,
+0x38664000U,
+0x38668000U,
+0x3866C000U,
+0x38670000U,
+0x38674000U,
+0x38678000U,
+0x3867C000U,
+0x38680000U,
+0x38684000U,
+0x38688000U,
+0x3868C000U,
+0x38690000U,
+0x38694000U,
+0x38698000U,
+0x3869C000U,
+0x386A0000U,
+0x386A4000U,
+0x386A8000U,
+0x386AC000U,
+0x386B0000U,
+0x386B4000U,
+0x386B8000U,
+0x386BC000U,
+0x386C0000U,
+0x386C4000U,
+0x386C8000U,
+0x386CC000U,
+0x386D0000U,
+0x386D4000U,
+0x386D8000U,
+0x386DC000U,
+0x386E0000U,
+0x386E4000U,
+0x386E8000U,
+0x386EC000U,
+0x386F0000U,
+0x386F4000U,
+0x386F8000U,
+0x386FC000U,
+0x38700000U,
+0x38704000U,
+0x38708000U,
+0x3870C000U,
+0x38710000U,
+0x38714000U,
+0x38718000U,
+0x3871C000U,
+0x38720000U,
+0x38724000U,
+0x38728000U,
+0x3872C000U,
+0x38730000U,
+0x38734000U,
+0x38738000U,
+0x3873C000U,
+0x38740000U,
+0x38744000U,
+0x38748000U,
+0x3874C000U,
+0x38750000U,
+0x38754000U,
+0x38758000U,
+0x3875C000U,
+0x38760000U,
+0x38764000U,
+0x38768000U,
+0x3876C000U,
+0x38770000U,
+0x38774000U,
+0x38778000U,
+0x3877C000U,
+0x38780000U,
+0x38784000U,
+0x38788000U,
+0x3878C000U,
+0x38790000U,
+0x38794000U,
+0x38798000U,
+0x3879C000U,
+0x387A0000U,
+0x387A4000U,
+0x387A8000U,
+0x387AC000U,
+0x387B0000U,
+0x387B4000U,
+0x387B8000U,
+0x387BC000U,
+0x387C0000U,
+0x387C4000U,
+0x387C8000U,
+0x387CC000U,
+0x387D0000U,
+0x387D4000U,
+0x387D8000U,
+0x387DC000U,
+0x387E0000U,
+0x387E4000U,
+0x387E8000U,
+0x387EC000U,
+0x387F0000U,
+0x387F4000U,
+0x387F8000U,
+0x387FC000U,
+0x38000000U,
+0x38002000U,
+0x38004000U,
+0x38006000U,
+0x38008000U,
+0x3800A000U,
+0x3800C000U,
+0x3800E000U,
+0x38010000U,
+0x38012000U,
+0x38014000U,
+0x38016000U,
+0x38018000U,
+0x3801A000U,
+0x3801C000U,
+0x3801E000U,
+0x38020000U,
+0x38022000U,
+0x38024000U,
+0x38026000U,
+0x38028000U,
+0x3802A000U,
+0x3802C000U,
+0x3802E000U,
+0x38030000U,
+0x38032000U,
+0x38034000U,
+0x38036000U,
+0x38038000U,
+0x3803A000U,
+0x3803C000U,
+0x3803E000U,
+0x38040000U,
+0x38042000U,
+0x38044000U,
+0x38046000U,
+0x38048000U,
+0x3804A000U,
+0x3804C000U,
+0x3804E000U,
+0x38050000U,
+0x38052000U,
+0x38054000U,
+0x38056000U,
+0x38058000U,
+0x3805A000U,
+0x3805C000U,
+0x3805E000U,
+0x38060000U,
+0x38062000U,
+0x38064000U,
+0x38066000U,
+0x38068000U,
+0x3806A000U,
+0x3806C000U,
+0x3806E000U,
+0x38070000U,
+0x38072000U,
+0x38074000U,
+0x38076000U,
+0x38078000U,
+0x3807A000U,
+0x3807C000U,
+0x3807E000U,
+0x38080000U,
+0x38082000U,
+0x38084000U,
+0x38086000U,
+0x38088000U,
+0x3808A000U,
+0x3808C000U,
+0x3808E000U,
+0x38090000U,
+0x38092000U,
+0x38094000U,
+0x38096000U,
+0x38098000U,
+0x3809A000U,
+0x3809C000U,
+0x3809E000U,
+0x380A0000U,
+0x380A2000U,
+0x380A4000U,
+0x380A6000U,
+0x380A8000U,
+0x380AA000U,
+0x380AC000U,
+0x380AE000U,
+0x380B0000U,
+0x380B2000U,
+0x380B4000U,
+0x380B6000U,
+0x380B8000U,
+0x380BA000U,
+0x380BC000U,
+0x380BE000U,
+0x380C0000U,
+0x380C2000U,
+0x380C4000U,
+0x380C6000U,
+0x380C8000U,
+0x380CA000U,
+0x380CC000U,
+0x380CE000U,
+0x380D0000U,
+0x380D2000U,
+0x380D4000U,
+0x380D6000U,
+0x380D8000U,
+0x380DA000U,
+0x380DC000U,
+0x380DE000U,
+0x380E0000U,
+0x380E2000U,
+0x380E4000U,
+0x380E6000U,
+0x380E8000U,
+0x380EA000U,
+0x380EC000U,
+0x380EE000U,
+0x380F0000U,
+0x380F2000U,
+0x380F4000U,
+0x380F6000U,
+0x380F8000U,
+0x380FA000U,
+0x380FC000U,
+0x380FE000U,
+0x38100000U,
+0x38102000U,
+0x38104000U,
+0x38106000U,
+0x38108000U,
+0x3810A000U,
+0x3810C000U,
+0x3810E000U,
+0x38110000U,
+0x38112000U,
+0x38114000U,
+0x38116000U,
+0x38118000U,
+0x3811A000U,
+0x3811C000U,
+0x3811E000U,
+0x38120000U,
+0x38122000U,
+0x38124000U,
+0x38126000U,
+0x38128000U,
+0x3812A000U,
+0x3812C000U,
+0x3812E000U,
+0x38130000U,
+0x38132000U,
+0x38134000U,
+0x38136000U,
+0x38138000U,
+0x3813A000U,
+0x3813C000U,
+0x3813E000U,
+0x38140000U,
+0x38142000U,
+0x38144000U,
+0x38146000U,
+0x38148000U,
+0x3814A000U,
+0x3814C000U,
+0x3814E000U,
+0x38150000U,
+0x38152000U,
+0x38154000U,
+0x38156000U,
+0x38158000U,
+0x3815A000U,
+0x3815C000U,
+0x3815E000U,
+0x38160000U,
+0x38162000U,
+0x38164000U,
+0x38166000U,
+0x38168000U,
+0x3816A000U,
+0x3816C000U,
+0x3816E000U,
+0x38170000U,
+0x38172000U,
+0x38174000U,
+0x38176000U,
+0x38178000U,
+0x3817A000U,
+0x3817C000U,
+0x3817E000U,
+0x38180000U,
+0x38182000U,
+0x38184000U,
+0x38186000U,
+0x38188000U,
+0x3818A000U,
+0x3818C000U,
+0x3818E000U,
+0x38190000U,
+0x38192000U,
+0x38194000U,
+0x38196000U,
+0x38198000U,
+0x3819A000U,
+0x3819C000U,
+0x3819E000U,
+0x381A0000U,
+0x381A2000U,
+0x381A4000U,
+0x381A6000U,
+0x381A8000U,
+0x381AA000U,
+0x381AC000U,
+0x381AE000U,
+0x381B0000U,
+0x381B2000U,
+0x381B4000U,
+0x381B6000U,
+0x381B8000U,
+0x381BA000U,
+0x381BC000U,
+0x381BE000U,
+0x381C0000U,
+0x381C2000U,
+0x381C4000U,
+0x381C6000U,
+0x381C8000U,
+0x381CA000U,
+0x381CC000U,
+0x381CE000U,
+0x381D0000U,
+0x381D2000U,
+0x381D4000U,
+0x381D6000U,
+0x381D8000U,
+0x381DA000U,
+0x381DC000U,
+0x381DE000U,
+0x381E0000U,
+0x381E2000U,
+0x381E4000U,
+0x381E6000U,
+0x381E8000U,
+0x381EA000U,
+0x381EC000U,
+0x381EE000U,
+0x381F0000U,
+0x381F2000U,
+0x381F4000U,
+0x381F6000U,
+0x381F8000U,
+0x381FA000U,
+0x381FC000U,
+0x381FE000U,
+0x38200000U,
+0x38202000U,
+0x38204000U,
+0x38206000U,
+0x38208000U,
+0x3820A000U,
+0x3820C000U,
+0x3820E000U,
+0x38210000U,
+0x38212000U,
+0x38214000U,
+0x38216000U,
+0x38218000U,
+0x3821A000U,
+0x3821C000U,
+0x3821E000U,
+0x38220000U,
+0x38222000U,
+0x38224000U,
+0x38226000U,
+0x38228000U,
+0x3822A000U,
+0x3822C000U,
+0x3822E000U,
+0x38230000U,
+0x38232000U,
+0x38234000U,
+0x38236000U,
+0x38238000U,
+0x3823A000U,
+0x3823C000U,
+0x3823E000U,
+0x38240000U,
+0x38242000U,
+0x38244000U,
+0x38246000U,
+0x38248000U,
+0x3824A000U,
+0x3824C000U,
+0x3824E000U,
+0x38250000U,
+0x38252000U,
+0x38254000U,
+0x38256000U,
+0x38258000U,
+0x3825A000U,
+0x3825C000U,
+0x3825E000U,
+0x38260000U,
+0x38262000U,
+0x38264000U,
+0x38266000U,
+0x38268000U,
+0x3826A000U,
+0x3826C000U,
+0x3826E000U,
+0x38270000U,
+0x38272000U,
+0x38274000U,
+0x38276000U,
+0x38278000U,
+0x3827A000U,
+0x3827C000U,
+0x3827E000U,
+0x38280000U,
+0x38282000U,
+0x38284000U,
+0x38286000U,
+0x38288000U,
+0x3828A000U,
+0x3828C000U,
+0x3828E000U,
+0x38290000U,
+0x38292000U,
+0x38294000U,
+0x38296000U,
+0x38298000U,
+0x3829A000U,
+0x3829C000U,
+0x3829E000U,
+0x382A0000U,
+0x382A2000U,
+0x382A4000U,
+0x382A6000U,
+0x382A8000U,
+0x382AA000U,
+0x382AC000U,
+0x382AE000U,
+0x382B0000U,
+0x382B2000U,
+0x382B4000U,
+0x382B6000U,
+0x382B8000U,
+0x382BA000U,
+0x382BC000U,
+0x382BE000U,
+0x382C0000U,
+0x382C2000U,
+0x382C4000U,
+0x382C6000U,
+0x382C8000U,
+0x382CA000U,
+0x382CC000U,
+0x382CE000U,
+0x382D0000U,
+0x382D2000U,
+0x382D4000U,
+0x382D6000U,
+0x382D8000U,
+0x382DA000U,
+0x382DC000U,
+0x382DE000U,
+0x382E0000U,
+0x382E2000U,
+0x382E4000U,
+0x382E6000U,
+0x382E8000U,
+0x382EA000U,
+0x382EC000U,
+0x382EE000U,
+0x382F0000U,
+0x382F2000U,
+0x382F4000U,
+0x382F6000U,
+0x382F8000U,
+0x382FA000U,
+0x382FC000U,
+0x382FE000U,
+0x38300000U,
+0x38302000U,
+0x38304000U,
+0x38306000U,
+0x38308000U,
+0x3830A000U,
+0x3830C000U,
+0x3830E000U,
+0x38310000U,
+0x38312000U,
+0x38314000U,
+0x38316000U,
+0x38318000U,
+0x3831A000U,
+0x3831C000U,
+0x3831E000U,
+0x38320000U,
+0x38322000U,
+0x38324000U,
+0x38326000U,
+0x38328000U,
+0x3832A000U,
+0x3832C000U,
+0x3832E000U,
+0x38330000U,
+0x38332000U,
+0x38334000U,
+0x38336000U,
+0x38338000U,
+0x3833A000U,
+0x3833C000U,
+0x3833E000U,
+0x38340000U,
+0x38342000U,
+0x38344000U,
+0x38346000U,
+0x38348000U,
+0x3834A000U,
+0x3834C000U,
+0x3834E000U,
+0x38350000U,
+0x38352000U,
+0x38354000U,
+0x38356000U,
+0x38358000U,
+0x3835A000U,
+0x3835C000U,
+0x3835E000U,
+0x38360000U,
+0x38362000U,
+0x38364000U,
+0x38366000U,
+0x38368000U,
+0x3836A000U,
+0x3836C000U,
+0x3836E000U,
+0x38370000U,
+0x38372000U,
+0x38374000U,
+0x38376000U,
+0x38378000U,
+0x3837A000U,
+0x3837C000U,
+0x3837E000U,
+0x38380000U,
+0x38382000U,
+0x38384000U,
+0x38386000U,
+0x38388000U,
+0x3838A000U,
+0x3838C000U,
+0x3838E000U,
+0x38390000U,
+0x38392000U,
+0x38394000U,
+0x38396000U,
+0x38398000U,
+0x3839A000U,
+0x3839C000U,
+0x3839E000U,
+0x383A0000U,
+0x383A2000U,
+0x383A4000U,
+0x383A6000U,
+0x383A8000U,
+0x383AA000U,
+0x383AC000U,
+0x383AE000U,
+0x383B0000U,
+0x383B2000U,
+0x383B4000U,
+0x383B6000U,
+0x383B8000U,
+0x383BA000U,
+0x383BC000U,
+0x383BE000U,
+0x383C0000U,
+0x383C2000U,
+0x383C4000U,
+0x383C6000U,
+0x383C8000U,
+0x383CA000U,
+0x383CC000U,
+0x383CE000U,
+0x383D0000U,
+0x383D2000U,
+0x383D4000U,
+0x383D6000U,
+0x383D8000U,
+0x383DA000U,
+0x383DC000U,
+0x383DE000U,
+0x383E0000U,
+0x383E2000U,
+0x383E4000U,
+0x383E6000U,
+0x383E8000U,
+0x383EA000U,
+0x383EC000U,
+0x383EE000U,
+0x383F0000U,
+0x383F2000U,
+0x383F4000U,
+0x383F6000U,
+0x383F8000U,
+0x383FA000U,
+0x383FC000U,
+0x383FE000U,
+0x38400000U,
+0x38402000U,
+0x38404000U,
+0x38406000U,
+0x38408000U,
+0x3840A000U,
+0x3840C000U,
+0x3840E000U,
+0x38410000U,
+0x38412000U,
+0x38414000U,
+0x38416000U,
+0x38418000U,
+0x3841A000U,
+0x3841C000U,
+0x3841E000U,
+0x38420000U,
+0x38422000U,
+0x38424000U,
+0x38426000U,
+0x38428000U,
+0x3842A000U,
+0x3842C000U,
+0x3842E000U,
+0x38430000U,
+0x38432000U,
+0x38434000U,
+0x38436000U,
+0x38438000U,
+0x3843A000U,
+0x3843C000U,
+0x3843E000U,
+0x38440000U,
+0x38442000U,
+0x38444000U,
+0x38446000U,
+0x38448000U,
+0x3844A000U,
+0x3844C000U,
+0x3844E000U,
+0x38450000U,
+0x38452000U,
+0x38454000U,
+0x38456000U,
+0x38458000U,
+0x3845A000U,
+0x3845C000U,
+0x3845E000U,
+0x38460000U,
+0x38462000U,
+0x38464000U,
+0x38466000U,
+0x38468000U,
+0x3846A000U,
+0x3846C000U,
+0x3846E000U,
+0x38470000U,
+0x38472000U,
+0x38474000U,
+0x38476000U,
+0x38478000U,
+0x3847A000U,
+0x3847C000U,
+0x3847E000U,
+0x38480000U,
+0x38482000U,
+0x38484000U,
+0x38486000U,
+0x38488000U,
+0x3848A000U,
+0x3848C000U,
+0x3848E000U,
+0x38490000U,
+0x38492000U,
+0x38494000U,
+0x38496000U,
+0x38498000U,
+0x3849A000U,
+0x3849C000U,
+0x3849E000U,
+0x384A0000U,
+0x384A2000U,
+0x384A4000U,
+0x384A6000U,
+0x384A8000U,
+0x384AA000U,
+0x384AC000U,
+0x384AE000U,
+0x384B0000U,
+0x384B2000U,
+0x384B4000U,
+0x384B6000U,
+0x384B8000U,
+0x384BA000U,
+0x384BC000U,
+0x384BE000U,
+0x384C0000U,
+0x384C2000U,
+0x384C4000U,
+0x384C6000U,
+0x384C8000U,
+0x384CA000U,
+0x384CC000U,
+0x384CE000U,
+0x384D0000U,
+0x384D2000U,
+0x384D4000U,
+0x384D6000U,
+0x384D8000U,
+0x384DA000U,
+0x384DC000U,
+0x384DE000U,
+0x384E0000U,
+0x384E2000U,
+0x384E4000U,
+0x384E6000U,
+0x384E8000U,
+0x384EA000U,
+0x384EC000U,
+0x384EE000U,
+0x384F0000U,
+0x384F2000U,
+0x384F4000U,
+0x384F6000U,
+0x384F8000U,
+0x384FA000U,
+0x384FC000U,
+0x384FE000U,
+0x38500000U,
+0x38502000U,
+0x38504000U,
+0x38506000U,
+0x38508000U,
+0x3850A000U,
+0x3850C000U,
+0x3850E000U,
+0x38510000U,
+0x38512000U,
+0x38514000U,
+0x38516000U,
+0x38518000U,
+0x3851A000U,
+0x3851C000U,
+0x3851E000U,
+0x38520000U,
+0x38522000U,
+0x38524000U,
+0x38526000U,
+0x38528000U,
+0x3852A000U,
+0x3852C000U,
+0x3852E000U,
+0x38530000U,
+0x38532000U,
+0x38534000U,
+0x38536000U,
+0x38538000U,
+0x3853A000U,
+0x3853C000U,
+0x3853E000U,
+0x38540000U,
+0x38542000U,
+0x38544000U,
+0x38546000U,
+0x38548000U,
+0x3854A000U,
+0x3854C000U,
+0x3854E000U,
+0x38550000U,
+0x38552000U,
+0x38554000U,
+0x38556000U,
+0x38558000U,
+0x3855A000U,
+0x3855C000U,
+0x3855E000U,
+0x38560000U,
+0x38562000U,
+0x38564000U,
+0x38566000U,
+0x38568000U,
+0x3856A000U,
+0x3856C000U,
+0x3856E000U,
+0x38570000U,
+0x38572000U,
+0x38574000U,
+0x38576000U,
+0x38578000U,
+0x3857A000U,
+0x3857C000U,
+0x3857E000U,
+0x38580000U,
+0x38582000U,
+0x38584000U,
+0x38586000U,
+0x38588000U,
+0x3858A000U,
+0x3858C000U,
+0x3858E000U,
+0x38590000U,
+0x38592000U,
+0x38594000U,
+0x38596000U,
+0x38598000U,
+0x3859A000U,
+0x3859C000U,
+0x3859E000U,
+0x385A0000U,
+0x385A2000U,
+0x385A4000U,
+0x385A6000U,
+0x385A8000U,
+0x385AA000U,
+0x385AC000U,
+0x385AE000U,
+0x385B0000U,
+0x385B2000U,
+0x385B4000U,
+0x385B6000U,
+0x385B8000U,
+0x385BA000U,
+0x385BC000U,
+0x385BE000U,
+0x385C0000U,
+0x385C2000U,
+0x385C4000U,
+0x385C6000U,
+0x385C8000U,
+0x385CA000U,
+0x385CC000U,
+0x385CE000U,
+0x385D0000U,
+0x385D2000U,
+0x385D4000U,
+0x385D6000U,
+0x385D8000U,
+0x385DA000U,
+0x385DC000U,
+0x385DE000U,
+0x385E0000U,
+0x385E2000U,
+0x385E4000U,
+0x385E6000U,
+0x385E8000U,
+0x385EA000U,
+0x385EC000U,
+0x385EE000U,
+0x385F0000U,
+0x385F2000U,
+0x385F4000U,
+0x385F6000U,
+0x385F8000U,
+0x385FA000U,
+0x385FC000U,
+0x385FE000U,
+0x38600000U,
+0x38602000U,
+0x38604000U,
+0x38606000U,
+0x38608000U,
+0x3860A000U,
+0x3860C000U,
+0x3860E000U,
+0x38610000U,
+0x38612000U,
+0x38614000U,
+0x38616000U,
+0x38618000U,
+0x3861A000U,
+0x3861C000U,
+0x3861E000U,
+0x38620000U,
+0x38622000U,
+0x38624000U,
+0x38626000U,
+0x38628000U,
+0x3862A000U,
+0x3862C000U,
+0x3862E000U,
+0x38630000U,
+0x38632000U,
+0x38634000U,
+0x38636000U,
+0x38638000U,
+0x3863A000U,
+0x3863C000U,
+0x3863E000U,
+0x38640000U,
+0x38642000U,
+0x38644000U,
+0x38646000U,
+0x38648000U,
+0x3864A000U,
+0x3864C000U,
+0x3864E000U,
+0x38650000U,
+0x38652000U,
+0x38654000U,
+0x38656000U,
+0x38658000U,
+0x3865A000U,
+0x3865C000U,
+0x3865E000U,
+0x38660000U,
+0x38662000U,
+0x38664000U,
+0x38666000U,
+0x38668000U,
+0x3866A000U,
+0x3866C000U,
+0x3866E000U,
+0x38670000U,
+0x38672000U,
+0x38674000U,
+0x38676000U,
+0x38678000U,
+0x3867A000U,
+0x3867C000U,
+0x3867E000U,
+0x38680000U,
+0x38682000U,
+0x38684000U,
+0x38686000U,
+0x38688000U,
+0x3868A000U,
+0x3868C000U,
+0x3868E000U,
+0x38690000U,
+0x38692000U,
+0x38694000U,
+0x38696000U,
+0x38698000U,
+0x3869A000U,
+0x3869C000U,
+0x3869E000U,
+0x386A0000U,
+0x386A2000U,
+0x386A4000U,
+0x386A6000U,
+0x386A8000U,
+0x386AA000U,
+0x386AC000U,
+0x386AE000U,
+0x386B0000U,
+0x386B2000U,
+0x386B4000U,
+0x386B6000U,
+0x386B8000U,
+0x386BA000U,
+0x386BC000U,
+0x386BE000U,
+0x386C0000U,
+0x386C2000U,
+0x386C4000U,
+0x386C6000U,
+0x386C8000U,
+0x386CA000U,
+0x386CC000U,
+0x386CE000U,
+0x386D0000U,
+0x386D2000U,
+0x386D4000U,
+0x386D6000U,
+0x386D8000U,
+0x386DA000U,
+0x386DC000U,
+0x386DE000U,
+0x386E0000U,
+0x386E2000U,
+0x386E4000U,
+0x386E6000U,
+0x386E8000U,
+0x386EA000U,
+0x386EC000U,
+0x386EE000U,
+0x386F0000U,
+0x386F2000U,
+0x386F4000U,
+0x386F6000U,
+0x386F8000U,
+0x386FA000U,
+0x386FC000U,
+0x386FE000U,
+0x38700000U,
+0x38702000U,
+0x38704000U,
+0x38706000U,
+0x38708000U,
+0x3870A000U,
+0x3870C000U,
+0x3870E000U,
+0x38710000U,
+0x38712000U,
+0x38714000U,
+0x38716000U,
+0x38718000U,
+0x3871A000U,
+0x3871C000U,
+0x3871E000U,
+0x38720000U,
+0x38722000U,
+0x38724000U,
+0x38726000U,
+0x38728000U,
+0x3872A000U,
+0x3872C000U,
+0x3872E000U,
+0x38730000U,
+0x38732000U,
+0x38734000U,
+0x38736000U,
+0x38738000U,
+0x3873A000U,
+0x3873C000U,
+0x3873E000U,
+0x38740000U,
+0x38742000U,
+0x38744000U,
+0x38746000U,
+0x38748000U,
+0x3874A000U,
+0x3874C000U,
+0x3874E000U,
+0x38750000U,
+0x38752000U,
+0x38754000U,
+0x38756000U,
+0x38758000U,
+0x3875A000U,
+0x3875C000U,
+0x3875E000U,
+0x38760000U,
+0x38762000U,
+0x38764000U,
+0x38766000U,
+0x38768000U,
+0x3876A000U,
+0x3876C000U,
+0x3876E000U,
+0x38770000U,
+0x38772000U,
+0x38774000U,
+0x38776000U,
+0x38778000U,
+0x3877A000U,
+0x3877C000U,
+0x3877E000U,
+0x38780000U,
+0x38782000U,
+0x38784000U,
+0x38786000U,
+0x38788000U,
+0x3878A000U,
+0x3878C000U,
+0x3878E000U,
+0x38790000U,
+0x38792000U,
+0x38794000U,
+0x38796000U,
+0x38798000U,
+0x3879A000U,
+0x3879C000U,
+0x3879E000U,
+0x387A0000U,
+0x387A2000U,
+0x387A4000U,
+0x387A6000U,
+0x387A8000U,
+0x387AA000U,
+0x387AC000U,
+0x387AE000U,
+0x387B0000U,
+0x387B2000U,
+0x387B4000U,
+0x387B6000U,
+0x387B8000U,
+0x387BA000U,
+0x387BC000U,
+0x387BE000U,
+0x387C0000U,
+0x387C2000U,
+0x387C4000U,
+0x387C6000U,
+0x387C8000U,
+0x387CA000U,
+0x387CC000U,
+0x387CE000U,
+0x387D0000U,
+0x387D2000U,
+0x387D4000U,
+0x387D6000U,
+0x387D8000U,
+0x387DA000U,
+0x387DC000U,
+0x387DE000U,
+0x387E0000U,
+0x387E2000U,
+0x387E4000U,
+0x387E6000U,
+0x387E8000U,
+0x387EA000U,
+0x387EC000U,
+0x387EE000U,
+0x387F0000U,
+0x387F2000U,
+0x387F4000U,
+0x387F6000U,
+0x387F8000U,
+0x387FA000U,
+0x387FC000U,
+0x387FE000U,
+};
+
+const quint32 qfloat16::exponenttable[64] = {
+0,
+0x800000U,
+0x1000000U,
+0x1800000U,
+0x2000000U,
+0x2800000U,
+0x3000000U,
+0x3800000U,
+0x4000000U,
+0x4800000U,
+0x5000000U,
+0x5800000U,
+0x6000000U,
+0x6800000U,
+0x7000000U,
+0x7800000U,
+0x8000000U,
+0x8800000U,
+0x9000000U,
+0x9800000U,
+0xA000000U,
+0xA800000U,
+0xB000000U,
+0xB800000U,
+0xC000000U,
+0xC800000U,
+0xD000000U,
+0xD800000U,
+0xE000000U,
+0xE800000U,
+0xF000000U,
+0x47800000U,
+0x80000000U,
+0x80800000U,
+0x81000000U,
+0x81800000U,
+0x82000000U,
+0x82800000U,
+0x83000000U,
+0x83800000U,
+0x84000000U,
+0x84800000U,
+0x85000000U,
+0x85800000U,
+0x86000000U,
+0x86800000U,
+0x87000000U,
+0x87800000U,
+0x88000000U,
+0x88800000U,
+0x89000000U,
+0x89800000U,
+0x8A000000U,
+0x8A800000U,
+0x8B000000U,
+0x8B800000U,
+0x8C000000U,
+0x8C800000U,
+0x8D000000U,
+0x8D800000U,
+0x8E000000U,
+0x8E800000U,
+0x8F000000U,
+0xC7800000U,
+};
+
+const quint32 qfloat16::offsettable[64] = {
+0,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+0,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+1024U,
+};
+
+const quint32 qfloat16::basetable[512] = {
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x0U,
+0x1U,
+0x2U,
+0x4U,
+0x8U,
+0x10U,
+0x20U,
+0x40U,
+0x80U,
+0x100U,
+0x200U,
+0x400U,
+0x800U,
+0xC00U,
+0x1000U,
+0x1400U,
+0x1800U,
+0x1C00U,
+0x2000U,
+0x2400U,
+0x2800U,
+0x2C00U,
+0x3000U,
+0x3400U,
+0x3800U,
+0x3C00U,
+0x4000U,
+0x4400U,
+0x4800U,
+0x4C00U,
+0x5000U,
+0x5400U,
+0x5800U,
+0x5C00U,
+0x6000U,
+0x6400U,
+0x6800U,
+0x6C00U,
+0x7000U,
+0x7400U,
+0x7800U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x7C00U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8000U,
+0x8001U,
+0x8002U,
+0x8004U,
+0x8008U,
+0x8010U,
+0x8020U,
+0x8040U,
+0x8080U,
+0x8100U,
+0x8200U,
+0x8400U,
+0x8800U,
+0x8C00U,
+0x9000U,
+0x9400U,
+0x9800U,
+0x9C00U,
+0xA000U,
+0xA400U,
+0xA800U,
+0xAC00U,
+0xB000U,
+0xB400U,
+0xB800U,
+0xBC00U,
+0xC000U,
+0xC400U,
+0xC800U,
+0xCC00U,
+0xD000U,
+0xD400U,
+0xD800U,
+0xDC00U,
+0xE000U,
+0xE400U,
+0xE800U,
+0xEC00U,
+0xF000U,
+0xF400U,
+0xF800U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+0xFC00U,
+};
+
+const quint32 qfloat16::shifttable[512] = {
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x17U,
+0x16U,
+0x15U,
+0x14U,
+0x13U,
+0x12U,
+0x11U,
+0x10U,
+0xFU,
+0xEU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0xDU,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x17U,
+0x16U,
+0x15U,
+0x14U,
+0x13U,
+0x12U,
+0x11U,
+0x10U,
+0xFU,
+0xEU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0xDU,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0x18U,
+0xDU,
+};
+
+#endif // !__F16C__ && !__ARM_FP16_FORMAT_IEEE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 555b04dcd5..a8ed8ca6fd 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -525,6 +525,31 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value));
made private. In that case, no error would be reported, but your
application would probably crash when you called a member function
of \c{w}.
+
+ \sa Q_DISABLE_COPY_MOVE, Q_DISABLE_MOVE
+*/
+
+/*!
+ \macro Q_DISABLE_MOVE(Class)
+ \relates QObject
+
+ Disables the use of move constructors and move assignment operators
+ for the given \a Class.
+
+ \sa Q_DISABLE_COPY, Q_DISABLE_COPY_MOVE
+ \since 5.13
+*/
+
+/*!
+ \macro Q_DISABLE_COPY_MOVE(Class)
+ \relates QObject
+
+ A convenience macro that disables the use of copy constructors, assignment
+ operators, move constructors and move assignment operators for the given
+ \a Class, combining Q_DISABLE_COPY and Q_DISABLE_MOVE.
+
+ \sa Q_DISABLE_COPY, Q_DISABLE_MOVE
+ \since 5.13
*/
/*!
@@ -1122,12 +1147,12 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value));
\sa QT_VERSION_STR, QLibraryInfo::version()
*/
-const char *qVersion() Q_DECL_NOTHROW
+const char *qVersion() noexcept
{
return QT_VERSION_STR;
}
-bool qSharedBuild() Q_DECL_NOTHROW
+bool qSharedBuild() noexcept
{
#ifdef QT_SHARED
return true;
@@ -1528,6 +1553,13 @@ bool qSharedBuild() Q_DECL_NOTHROW
*/
/*!
+ \macro Q_OS_WASM
+ \relates <QtGlobal>
+
+ Defined on Web Assembly.
+*/
+
+/*!
\macro Q_CC_SYM
\relates <QtGlobal>
@@ -1866,6 +1898,42 @@ bool qSharedBuild() Q_DECL_NOTHROW
*/
/*!
+ \macro Q_PROCESSOR_RISCV
+ \relates <QtGlobal>
+ \since 5.13
+
+ Defined if the application is compiled for RISC-V processors. Qt currently
+ supports two RISC-V variants: \l Q_PROCESSOR_RISCV_32 and \l
+ Q_PROCESSOR_RISCV_64.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_RISCV_32
+ \relates <QtGlobal>
+ \since 5.13
+
+ Defined if the application is compiled for 32-bit RISC-V processors. The \l
+ Q_PROCESSOR_RISCV macro is also defined when Q_PROCESSOR_RISCV_32 is
+ defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
+ \macro Q_PROCESSOR_RISCV_64
+ \relates <QtGlobal>
+ \since 5.13
+
+ Defined if the application is compiled for 64-bit RISC-V processors. The \l
+ Q_PROCESSOR_RISCV macro is also defined when Q_PROCESSOR_RISCV_64 is
+ defined.
+
+ \sa QSysInfo::buildCpuArchitecture()
+*/
+
+/*!
\macro Q_PROCESSOR_S390
\relates <QtGlobal>
@@ -1961,11 +2029,11 @@ bool qSharedBuild() Q_DECL_NOTHROW
a specified version of Qt or any earlier version. The default version number is 5.0,
meaning that functions deprecated in or before Qt 5.0 will not be included.
- Examples:
- When using a future release of Qt 5, set QT_DISABLE_DEPRECATED_BEFORE=0x050100 to
- disable functions deprecated in Qt 5.1 and earlier. In any release, set
- QT_DISABLE_DEPRECATED_BEFORE=0x000000 to enable any functions, including the ones
- deprecated in Qt 5.0
+ For instance, when using a future release of Qt 5, set
+ \c{QT_DISABLE_DEPRECATED_BEFORE=0x050100} to disable functions deprecated in
+ Qt 5.1 and earlier. In any release, set
+ \c{QT_DISABLE_DEPRECATED_BEFORE=0x000000} to enable all functions, including
+ the ones deprecated in Qt 5.0.
\sa QT_DEPRECATED_WARNINGS
*/
@@ -1975,12 +2043,24 @@ bool qSharedBuild() Q_DECL_NOTHROW
\macro QT_DEPRECATED_WARNINGS
\relates <QtGlobal>
- If this macro is defined, the compiler will generate warnings if API declared as
+ Since Qt 5.13, this macro has no effect. In Qt 5.12 and before, if this macro
+ is defined, the compiler will generate warnings if any API declared as
deprecated by Qt is used.
- \sa QT_DISABLE_DEPRECATED_BEFORE
+ \sa QT_DISABLE_DEPRECATED_BEFORE, QT_NO_DEPRECATED_WARNINGS
*/
+/*!
+ \macro QT_NO_DEPRECATED_WARNINGS
+ \relates <QtGlobal>
+ \since 5.13
+
+ This macro can be used to suppress deprecation warnings that would otherwise
+ be generated when using deprecated APIs.
+
+ \sa QT_DISABLE_DEPRECATED_BEFORE
+*/
+
#if defined(QT_BUILD_QMAKE)
// needed to bootstrap qmake
static const unsigned int qt_one = 1;
@@ -2151,11 +2231,20 @@ struct QUnixOSVersion
static QString unquote(const char *begin, const char *end)
{
+ // man os-release says:
+ // Variable assignment values must be enclosed in double
+ // or single quotes if they include spaces, semicolons or
+ // other special characters outside of A–Z, a–z, 0–9. Shell
+ // special characters ("$", quotes, backslash, backtick)
+ // must be escaped with backslashes, following shell style.
+ // All strings should be in UTF-8 format, and non-printable
+ // characters should not be used. It is not supported to
+ // concatenate multiple individually quoted strings.
if (*begin == '"') {
Q_ASSERT(end[-1] == '"');
- return QString::fromLatin1(begin + 1, end - begin - 2);
+ return QString::fromUtf8(begin + 1, end - begin - 2);
}
- return QString::fromLatin1(begin, end - begin);
+ return QString::fromUtf8(begin, end - begin);
}
static QByteArray getEtcFileContent(const char *filename)
{
@@ -2863,6 +2952,7 @@ QString QSysInfo::machineHostName()
struct utsname u;
if (uname(&u) == 0)
return QString::fromLocal8Bit(u.nodename);
+ return QString();
#else
# ifdef Q_OS_WIN
// Important: QtNetwork depends on machineHostName() initializing ws2_32.dll
@@ -2875,7 +2965,6 @@ QString QSysInfo::machineHostName()
hostName[sizeof(hostName) - 1] = '\0';
return QString::fromLocal8Bit(hostName);
#endif
- return QString();
}
#endif // QT_BOOTSTRAPPED
@@ -3167,7 +3256,7 @@ QByteArray QSysInfo::bootUniqueId()
The Q_CHECK_PTR macro calls this function if an allocation check
fails.
*/
-void qt_check_pointer(const char *n, int l) Q_DECL_NOTHROW
+void qt_check_pointer(const char *n, int l) noexcept
{
// make separate printing calls so that the first one may flush;
// the second one could want to allocate memory (fputs prints a
@@ -3194,7 +3283,7 @@ void qBadAlloc()
Allows you to call std::terminate() without including <exception>.
Called internally from QT_TERMINATE_ON_EXCEPTION
*/
-Q_NORETURN void qTerminate() Q_DECL_NOTHROW
+Q_NORETURN void qTerminate() noexcept
{
std::terminate();
}
@@ -3203,7 +3292,7 @@ Q_NORETURN void qTerminate() Q_DECL_NOTHROW
/*
The Q_ASSERT macro calls this function when the test fails.
*/
-void qt_assert(const char *assertion, const char *file, int line) Q_DECL_NOTHROW
+void qt_assert(const char *assertion, const char *file, int line) noexcept
{
QMessageLogger(file, line, nullptr).fatal("ASSERT: \"%s\" in file %s, line %d", assertion, file, line);
}
@@ -3211,7 +3300,7 @@ void qt_assert(const char *assertion, const char *file, int line) Q_DECL_NOTHROW
/*
The Q_ASSERT_X macro calls this function when the test fails.
*/
-void qt_assert_x(const char *where, const char *what, const char *file, int line) Q_DECL_NOTHROW
+void qt_assert_x(const char *where, const char *what, const char *file, int line) noexcept
{
QMessageLogger(file, line, nullptr).fatal("ASSERT failure in %s: \"%s\", file %s, line %d", where, what, file, line);
}
@@ -3252,6 +3341,34 @@ void *qMemSet(void *dest, int c, size_t n) { return memset(dest, c, n); }
// add thread-safety for the Qt wrappers.
static QBasicMutex environmentMutex;
+/*
+ Wraps tzset(), which accesses the environment, so should only be called while
+ we hold the lock on the environment mutex.
+*/
+void qTzSet()
+{
+ QMutexLocker locker(&environmentMutex);
+#if defined(Q_OS_WIN)
+ _tzset();
+#else
+ tzset();
+#endif // Q_OS_WIN
+}
+
+/*
+ Wrap mktime(), which is specified to behave as if it called tzset(), hence
+ shares its implicit environment-dependence.
+*/
+time_t qMkTime(struct tm *when)
+{
+ QMutexLocker locker(&environmentMutex);
+ return mktime(when);
+}
+
+// Also specified to behave as if they call tzset():
+// localtime() -- but not localtime_r(), which we use when threaded
+// strftime() -- not used (except in tests)
+
/*!
\relates <QtGlobal>
\threadsafe
@@ -3390,7 +3507,7 @@ QString qEnvironmentVariable(const char *varName)
\sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet()
*/
-bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT
+bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
{
QMutexLocker locker(&environmentMutex);
#ifdef Q_CC_MSVC
@@ -3425,7 +3542,7 @@ bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT
\sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet()
*/
-int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT
+int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept
{
static const int NumBinaryDigitsPerOctalDigit = 3;
static const int MaxDigitsForOctalInt =
@@ -3494,7 +3611,7 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT
\sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsEmpty()
*/
-bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT
+bool qEnvironmentVariableIsSet(const char *varName) noexcept
{
QMutexLocker locker(&environmentMutex);
#ifdef Q_CC_MSVC
@@ -3502,7 +3619,7 @@ bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT
(void)getenv_s(&requiredSize, 0, 0, varName);
return requiredSize != 0;
#else
- return ::getenv(varName) != 0;
+ return ::getenv(varName) != nullptr;
#endif
}
@@ -3696,6 +3813,56 @@ bool qunsetenv(const char *varName)
*/
/*!
+ \fn template <typename T, typename U = T> T qExchange(T &obj, U &&newValue)
+ \relates <QtGlobal>
+ \since 5.14
+
+ Replaces the value of \a obj with \a newValue and returns the old value of \a obj.
+
+ This is Qt's implementation of std::exchange(). It differs from std::exchange()
+ only in that it is \c constexpr already in C++14, and available on all supported
+ compilers.
+
+ Here is how to use qExchange() to implement move constructors:
+ \code
+ MyClass(MyClass &&other)
+ : m_pointer{qExchange(other.m_pointer, nullptr)},
+ m_int{qExchange(other.m_int, 0)},
+ m_vector{std::move(other.m_vector)},
+ ...
+ \endcode
+
+ For members of class type, we can use std::move(), as their move-constructor will
+ do the right thing. But for scalar types such as raw pointers or integer type, move
+ is the same as copy, which, particularly for pointers, is not what we expect. So, we
+ cannot use std::move() for such types, but we can use std::exchange()/qExchange() to
+ make sure the source object's member is already reset by the time we get to the
+ initialization of our next data member, which might come in handy if the constructor
+ exits with an exception.
+
+ Here is how to use qExchange() to write a loop that consumes the collection it
+ iterates over:
+ \code
+ for (auto &e : qExchange(collection, {})
+ doSomethingWith(e);
+ \endcode
+
+ Which is equivalent to the following, much more verbose code:
+ \code
+ {
+ auto tmp = std::move(collection);
+ collection = {}; // or collection.clear()
+ for (auto &e : tmp)
+ doSomethingWith(e);
+ } // destroys 'tmp'
+ \endcode
+
+ This is perfectly safe, as the for-loop keeps the result of qExchange() alive for as
+ long as the loop runs, saving the declaration of a temporary variable. Be aware, though,
+ that qExchange() returns a non-const object, so Qt containers may detach.
+*/
+
+/*!
\macro QT_TR_NOOP(sourceText)
\relates <QtGlobal>
@@ -4050,6 +4217,13 @@ bool qunsetenv(const char *varName)
Example of a movable type:
\snippet code/src_corelib_global_qglobal.cpp 39
+
+ Qt will try to detect the class of a type using std::is_trivial or
+ std::is_trivially_copyable. Use this macro to tune the behavior.
+ For instance many types would be candidates for Q_MOVABLE_TYPE despite
+ not being trivially-copyable. For binary compatibility reasons, QList
+ optimizations are only enabled if there is an explicit
+ Q_DECLARE_TYPEINFO even for trivially-copyable types.
*/
/*!
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index ccab228804..15f4621cc0 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -287,7 +287,7 @@ typedef double qreal;
# undef QT_DEPRECATED_X
# undef QT_DEPRECATED_VARIABLE
# undef QT_DEPRECATED_CONSTRUCTOR
-#elif defined(QT_DEPRECATED_WARNINGS)
+#elif !defined(QT_NO_DEPRECATED_WARNINGS)
# undef QT_DEPRECATED
# define QT_DEPRECATED Q_DECL_DEPRECATED
# undef QT_DEPRECATED_X
@@ -307,6 +307,14 @@ typedef double qreal;
# define QT_DEPRECATED_CONSTRUCTOR
#endif
+#ifndef QT_DEPRECATED_WARNINGS_SINCE
+# ifdef QT_DISABLE_DEPRECATED_BEFORE
+# define QT_DEPRECATED_WARNINGS_SINCE QT_DISABLE_DEPRECATED_BEFORE
+# else
+# define QT_DEPRECATED_WARNINGS_SINCE QT_VERSION
+# endif
+#endif
+
#ifndef QT_DISABLE_DEPRECATED_BEFORE
#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(5, 0, 0)
#endif
@@ -330,6 +338,51 @@ typedef double qreal;
#endif
/*
+ QT_DEPRECATED_VERSION(major, minor) and QT_DEPRECATED_VERSION_X(major, minor, text)
+ outputs a deprecation warning if QT_DEPRECATED_WARNINGS_SINCE is equal or greater
+ than the version specified as major, minor. This makes it possible to deprecate a
+ function without annoying a user who needs to stick at a specified minimum version
+ and therefore can't use the new function.
+*/
+#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 12, 0)
+# define QT_DEPRECATED_VERSION_X_5_12(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_5_12 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_5_12(text)
+# define QT_DEPRECATED_VERSION_5_12
+#endif
+
+#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 13, 0)
+# define QT_DEPRECATED_VERSION_X_5_13(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_5_13 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_5_13(text)
+# define QT_DEPRECATED_VERSION_5_13
+#endif
+
+#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 14, 0)
+# define QT_DEPRECATED_VERSION_X_5_14(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_5_14 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_5_14(text)
+# define QT_DEPRECATED_VERSION_5_14
+#endif
+
+#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 15, 0)
+# define QT_DEPRECATED_VERSION_X_5_15(text) QT_DEPRECATED_X(text)
+# define QT_DEPRECATED_VERSION_5_15 QT_DEPRECATED
+#else
+# define QT_DEPRECATED_VERSION_X_5_15(text)
+# define QT_DEPRECATED_VERSION_5_15
+#endif
+
+#define QT_DEPRECATED_VERSION_X_5(minor, text) QT_DEPRECATED_VERSION_X_5_##minor(text)
+#define QT_DEPRECATED_VERSION_X(major, minor, text) QT_DEPRECATED_VERSION_X_##major(minor, text)
+
+#define QT_DEPRECATED_VERSION_5(minor) QT_DEPRECATED_VERSION_5_##minor
+#define QT_DEPRECATED_VERSION(major, minor) QT_DEPRECATED_VERSION_##major(minor)
+
+/*
The Qt modules' export macros.
The options are:
- defined(QT_STATIC): Qt was built or is being built in static mode
@@ -369,8 +422,16 @@ typedef double qreal;
operator to disable copying (the compiler gives an error message).
*/
#define Q_DISABLE_COPY(Class) \
- Class(const Class &) Q_DECL_EQ_DELETE;\
- Class &operator=(const Class &) Q_DECL_EQ_DELETE;
+ Class(const Class &) = delete;\
+ Class &operator=(const Class &) = delete;
+
+#define Q_DISABLE_MOVE(Class) \
+ Class(Class &&) = delete; \
+ Class &operator=(Class &&) = delete;
+
+#define Q_DISABLE_COPY_MOVE(Class) \
+ Q_DISABLE_COPY(Class) \
+ Q_DISABLE_MOVE(Class)
/*
No, this is not an evil backdoor. QT_BUILD_INTERNAL just exports more symbols
@@ -403,7 +464,7 @@ typedef double qreal;
#if !defined(QT_NAMESPACE) && defined(__cplusplus) && !defined(Q_QDOC)
extern "C"
#endif
-Q_CORE_EXPORT Q_DECL_CONST_FUNCTION const char *qVersion(void) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION const char *qVersion(void) Q_DECL_NOEXCEPT;
#if defined(__cplusplus)
@@ -448,11 +509,8 @@ namespace QtPrivate {
template <class T> struct AlignOf : AlignOf_Default<T> { };
template <class T> struct AlignOf<T &> : AlignOf<T> {};
- template <size_t N, class T> struct AlignOf<T[N]> : AlignOf<T> {};
-
-#ifdef Q_COMPILER_RVALUE_REFS
template <class T> struct AlignOf<T &&> : AlignOf<T> {};
-#endif
+ template <size_t N, class T> struct AlignOf<T[N]> : AlignOf<T> {};
#if defined(Q_PROCESSOR_X86_32) && !defined(Q_OS_WIN)
template <class T> struct AlignOf_WorkaroundForI386Abi { enum { Value = sizeof(T) }; };
@@ -591,11 +649,11 @@ Q_DECL_CONSTEXPR inline qint64 qRound64(float d)
{ return d >= 0.0f ? qint64(d + 0.5f) : qint64(d - float(qint64(d-1)) + 0.5f) + qint64(d-1); }
template <typename T>
-Q_DECL_CONSTEXPR inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; }
+constexpr inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; }
template <typename T>
-Q_DECL_CONSTEXPR inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; }
+constexpr inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; }
template <typename T>
-Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max)
+constexpr inline const T &qBound(const T &min, const T &val, const T &max)
{ return qMax(min, qMin(max, val)); }
#ifndef Q_FORWARD_DECLARE_OBJC_CLASS
@@ -722,7 +780,7 @@ inline void qt_noop(void) {}
# define QT_CATCH(A) catch (A)
# define QT_THROW(A) throw A
# define QT_RETHROW throw
-Q_NORETURN Q_DECL_COLD_FUNCTION Q_CORE_EXPORT void qTerminate() Q_DECL_NOTHROW;
+Q_NORETURN Q_DECL_COLD_FUNCTION Q_CORE_EXPORT void qTerminate() noexcept;
# ifdef Q_COMPILER_NOEXCEPT
# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false)
# else
@@ -730,7 +788,7 @@ Q_NORETURN Q_DECL_COLD_FUNCTION Q_CORE_EXPORT void qTerminate() Q_DECL_NOTHROW;
# endif
#endif
-Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qSharedBuild() Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qSharedBuild() noexcept;
#ifndef Q_OUTOFLINE_TEMPLATE
# define Q_OUTOFLINE_TEMPLATE
@@ -773,7 +831,7 @@ Q_CORE_EXPORT QString qt_error_string(int errorCode = -1);
Q_NORETURN
#endif
Q_DECL_COLD_FUNCTION
-Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line) Q_DECL_NOTHROW;
+Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line) noexcept;
#if !defined(Q_ASSERT)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
@@ -791,7 +849,7 @@ Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line)
Q_NORETURN
#endif
Q_DECL_COLD_FUNCTION
-Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *file, int line) Q_DECL_NOTHROW;
+Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *file, int line) noexcept;
#if !defined(Q_ASSERT_X)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
@@ -801,7 +859,7 @@ Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *
# endif
#endif
-Q_NORETURN Q_CORE_EXPORT void qt_check_pointer(const char *, int) Q_DECL_NOTHROW;
+Q_NORETURN Q_CORE_EXPORT void qt_check_pointer(const char *, int) noexcept;
Q_DECL_COLD_FUNCTION
Q_CORE_EXPORT void qBadAlloc();
@@ -844,38 +902,23 @@ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qFuzzyIsNul
return qAbs(f) <= 0.00001f;
}
-/*
- This function tests a double for a null value. It doesn't
- check whether the actual value is 0 or close to 0, but whether
- it is binary 0, disregarding sign.
-*/
-Q_REQUIRED_RESULT static inline Q_DECL_UNUSED bool qIsNull(double d)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
+QT_WARNING_DISABLE_GCC("-Wfloat-equal")
+QT_WARNING_DISABLE_INTEL(1572)
+
+Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qIsNull(double d) noexcept
{
- union U {
- double d;
- quint64 u;
- };
- U val;
- val.d = d;
- return (val.u & Q_UINT64_C(0x7fffffffffffffff)) == 0;
+ return d == 0.0;
}
-/*
- This function tests a float for a null value. It doesn't
- check whether the actual value is 0 or close to 0, but whether
- it is binary 0, disregarding sign.
-*/
-Q_REQUIRED_RESULT static inline Q_DECL_UNUSED bool qIsNull(float f)
+Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qIsNull(float f) noexcept
{
- union U {
- float f;
- quint32 u;
- };
- U val;
- val.f = f;
- return (val.u & 0x7fffffff) == 0;
+ return f == 0.0f;
}
+QT_WARNING_POP
+
/*
Compilers which follow outdated template instantiation rules
require a class to have a comparison operator to exist when
@@ -902,14 +945,14 @@ namespace SwapExceptionTester { // insulate users from the "using std::swap" bel
using std::swap; // import std::swap
template <typename T>
void checkSwap(T &t)
- Q_DECL_NOEXCEPT_EXPR(noexcept(swap(t, t)));
+ noexcept(noexcept(swap(t, t)));
// declared, but not implemented (only to be used in unevaluated contexts (noexcept operator))
}
} // namespace QtPrivate
template <typename T>
inline void qSwap(T &value1, T &value2)
- Q_DECL_NOEXCEPT_EXPR(noexcept(QtPrivate::SwapExceptionTester::checkSwap(value1)))
+ noexcept(noexcept(QtPrivate::SwapExceptionTester::checkSwap(value1)))
{
using std::swap;
swap(value1, value2);
@@ -960,10 +1003,19 @@ QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantic
// this adds const to non-const objects (like std::as_const)
template <typename T>
-Q_DECL_CONSTEXPR typename std::add_const<T>::type &qAsConst(T &t) Q_DECL_NOTHROW { return t; }
+Q_DECL_CONSTEXPR typename std::add_const<T>::type &qAsConst(T &t) noexcept { return t; }
// prevent rvalue arguments:
template <typename T>
-void qAsConst(const T &&) Q_DECL_EQ_DELETE;
+void qAsConst(const T &&) = delete;
+
+// like std::exchange
+template <typename T, typename U = T>
+Q_DECL_RELAXED_CONSTEXPR T qExchange(T &t, U &&newValue)
+{
+ T old = std::move(t);
+ t = std::forward<U>(newValue);
+ return old;
+}
#ifndef QT_NO_FOREACH
@@ -1005,6 +1057,15 @@ QForeachContainer<typename std::decay<T>::type> qMakeForeachContainer(T &&t)
}
}
+
+#if __cplusplus >= 201703L
+// Use C++17 if statement with initializer. User's code ends up in a else so
+// scoping of different ifs is not broken
+#define Q_FOREACH(variable, container) \
+for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \
+ _container_.i != _container_.e; ++_container_.i) \
+ if (variable = *_container_.i; false) {} else
+#else
// Explanation of the control word:
// - it's initialized to 1
// - that means both the inner and outer loops start
@@ -1019,7 +1080,7 @@ for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \
_container_.control && _container_.i != _container_.e; \
++_container_.i, _container_.control ^= 1) \
for (variable = *_container_.i; _container_.control; _container_.control = 0)
-
+#endif
#endif // QT_NO_FOREACH
#define Q_FOREVER for(;;)
@@ -1035,7 +1096,7 @@ for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \
#endif
template <typename T> inline T *qGetPtrHelper(T *ptr) { return ptr; }
-template <typename Ptr> inline auto qGetPtrHelper(const Ptr &ptr) -> decltype(ptr.operator->()) { return ptr.operator->(); }
+template <typename Ptr> inline auto qGetPtrHelper(Ptr &ptr) -> decltype(ptr.operator->()) { return ptr.operator->(); }
// The body must be a statement:
#define Q_CAST_IGNORE_ALIGN(body) QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wcast-align") body QT_WARNING_POP
@@ -1113,11 +1174,11 @@ template <typename... Args>
struct QNonConstOverload
{
template <typename R, typename T>
- Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr)
+ Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const noexcept -> decltype(ptr)
{ return ptr; }
template <typename R, typename T>
- static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr)
+ static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) noexcept -> decltype(ptr)
{ return ptr; }
};
@@ -1125,11 +1186,11 @@ template <typename... Args>
struct QConstOverload
{
template <typename R, typename T>
- Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr)
+ Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const noexcept -> decltype(ptr)
{ return ptr; }
template <typename R, typename T>
- static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr)
+ static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) noexcept -> decltype(ptr)
{ return ptr; }
};
@@ -1142,11 +1203,11 @@ struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...>
using QNonConstOverload<Args...>::operator();
template <typename R>
- Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr)
+ Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const noexcept -> decltype(ptr)
{ return ptr; }
template <typename R>
- static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr)
+ static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) noexcept -> decltype(ptr)
{ return ptr; }
};
@@ -1167,9 +1228,9 @@ Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName, const QString &d
Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray& value);
Q_CORE_EXPORT bool qunsetenv(const char *varName);
-Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT;
-Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT;
-Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) Q_DECL_NOEXCEPT;
+Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept;
+Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept;
+Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept;
inline int qIntCast(double f) { return int(f); }
inline int qIntCast(float f) { return int(f); }
@@ -1192,9 +1253,6 @@ namespace QtPrivate {
//like std::enable_if
template <bool B, typename T = void> struct QEnableIf;
template <typename T> struct QEnableIf<true, T> { typedef T Type; };
-
-template <bool B, typename T, typename F> struct QConditional { typedef T Type; };
-template <typename T, typename F> struct QConditional<false, T, F> { typedef F Type; };
}
QT_END_NAMESPACE
diff --git a/src/corelib/global/qglobal_p.h b/src/corelib/global/qglobal_p.h
index 0f092e9006..58bc8b7bf3 100644
--- a/src/corelib/global/qglobal_p.h
+++ b/src/corelib/global/qglobal_p.h
@@ -61,6 +61,19 @@
#endif
#if defined(__cplusplus)
+#ifdef Q_CC_MINGW
+# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
+#endif
+#include <time.h>
+
+QT_BEGIN_NAMESPACE
+
+// These behave as if they consult the environment, so need to share its locking:
+Q_CORE_EXPORT void qTzSet();
+Q_CORE_EXPORT time_t qMkTime(struct tm *when);
+
+QT_END_NAMESPACE
+
#if !QT_HAS_BUILTIN(__builtin_available)
#include <initializer_list>
#include <QtCore/qoperatingsystemversion.h>
diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h
index 555bdf04c1..7a7d65ed76 100644
--- a/src/corelib/global/qglobalstatic.h
+++ b/src/corelib/global/qglobalstatic.h
@@ -79,16 +79,16 @@ enum GuardValues {
Q_GLOBAL_STATIC_INTERNAL_DECORATION Type *innerFunction() \
{ \
struct HolderBase { \
- ~HolderBase() Q_DECL_NOTHROW \
- { if (guard.load() == QtGlobalStatic::Initialized) \
- guard.store(QtGlobalStatic::Destroyed); } \
+ ~HolderBase() noexcept \
+ { if (guard.loadRelaxed() == QtGlobalStatic::Initialized) \
+ guard.storeRelaxed(QtGlobalStatic::Destroyed); } \
}; \
static struct Holder : public HolderBase { \
Type value; \
Holder() \
- Q_DECL_NOEXCEPT_EXPR(noexcept(Type ARGS)) \
+ noexcept(noexcept(Type ARGS)) \
: value ARGS \
- { guard.store(QtGlobalStatic::Initialized); } \
+ { guard.storeRelaxed(QtGlobalStatic::Initialized); } \
} holder; \
return &holder.value; \
}
@@ -108,12 +108,12 @@ QT_BEGIN_NAMESPACE
int x = guard.loadAcquire(); \
if (Q_UNLIKELY(x >= QtGlobalStatic::Uninitialized)) { \
QMutexLocker locker(&mutex); \
- if (guard.load() == QtGlobalStatic::Uninitialized) { \
+ if (guard.loadRelaxed() == QtGlobalStatic::Uninitialized) { \
d = new Type ARGS; \
static struct Cleanup { \
~Cleanup() { \
delete d; \
- guard.store(QtGlobalStatic::Destroyed); \
+ guard.storeRelaxed(QtGlobalStatic::Destroyed); \
} \
} cleanup; \
guard.storeRelease(QtGlobalStatic::Initialized); \
@@ -129,10 +129,10 @@ struct QGlobalStatic
{
typedef T Type;
- bool isDestroyed() const { return guard.load() <= QtGlobalStatic::Destroyed; }
- bool exists() const { return guard.load() == QtGlobalStatic::Initialized; }
- operator Type *() { if (isDestroyed()) return 0; return innerFunction(); }
- Type *operator()() { if (isDestroyed()) return 0; return innerFunction(); }
+ bool isDestroyed() const { return guard.loadRelaxed() <= QtGlobalStatic::Destroyed; }
+ bool exists() const { return guard.loadRelaxed() == QtGlobalStatic::Initialized; }
+ operator Type *() { if (isDestroyed()) return nullptr; return innerFunction(); }
+ Type *operator()() { if (isDestroyed()) return nullptr; return innerFunction(); }
Type *operator->()
{
Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed");
diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp
index bbddb1cbf1..020dee3710 100644
--- a/src/corelib/global/qhooks.cpp
+++ b/src/corelib/global/qhooks.cpp
@@ -67,7 +67,7 @@ quintptr Q_CORE_EXPORT qtHookData[] = {
// The required sizes and offsets are tested in tests/auto/other/toolsupport.
// When this fails and the change was intentional, adjust the test and
// adjust this value here.
- 16
+ 17
};
Q_STATIC_ASSERT(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0]));
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index d19e54154e..e82939dcd9 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -350,7 +350,7 @@ QLibraryInfo::buildDate()
\since 5.3
*/
-const char *QLibraryInfo::build() Q_DECL_NOTHROW
+const char *QLibraryInfo::build() noexcept
{
return QT_BUILD_STR;
}
@@ -377,7 +377,7 @@ QLibraryInfo::isDebugBuild()
\sa qVersion()
*/
-QVersionNumber QLibraryInfo::version() Q_DECL_NOTHROW
+QVersionNumber QLibraryInfo::version() noexcept
{
return QVersionNumber(QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH);
}
@@ -726,11 +726,6 @@ void qt_core_boilerplate()
QT_PREPEND_NAMESPACE(qDumpCPUFeatures)();
-#ifdef QT_EVAL
- extern void qt_core_eval_init(QCoreApplicationPrivate::Type);
- qt_core_eval_init(QCoreApplicationPrivate::Tty);
-#endif
-
exit(0);
}
diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h
index 9414af9b7d..ed60b170a5 100644
--- a/src/corelib/global/qlibraryinfo.h
+++ b/src/corelib/global/qlibraryinfo.h
@@ -62,12 +62,12 @@ public:
#endif // QT_DEPRECATED_SINCE(5, 5)
#endif // datestring
- static const char * build() Q_DECL_NOTHROW;
+ static const char * build() noexcept;
static bool isDebugBuild();
#ifndef QT_BOOTSTRAPPED
- static QVersionNumber version() Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ static QVersionNumber version() noexcept Q_DECL_CONST_FUNCTION;
#endif
enum LibraryLocation
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 30232170fb..621b6d7d13 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -44,6 +44,7 @@
#include "qlogging_p.h"
#include "qlist.h"
#include "qbytearray.h"
+#include "qscopeguard.h"
#include "qstring.h"
#include "qvarlengtharray.h"
#include "qdebug.h"
@@ -158,6 +159,9 @@ static QT_PREPEND_NAMESPACE(qint64) qt_gettid()
#endif // !QT_BOOTSTRAPPED
#include <cstdlib>
+#include <algorithm>
+#include <memory>
+#include <vector>
#include <stdio.h>
@@ -194,7 +198,7 @@ static bool isFatal(QtMsgType msgType)
// it's fatal if the current value is exactly 1,
// otherwise decrement if it's non-zero
- return fatalCriticals.load() && fatalCriticals.fetchAndAddRelaxed(-1) == 1;
+ return fatalCriticals.loadRelaxed() && fatalCriticals.fetchAndAddRelaxed(-1) == 1;
}
if (msgType == QtWarningMsg || msgType == QtCriticalMsg) {
@@ -202,7 +206,7 @@ static bool isFatal(QtMsgType msgType)
// it's fatal if the current value is exactly 1,
// otherwise decrement if it's non-zero
- return fatalWarnings.load() && fatalWarnings.fetchAndAddRelaxed(-1) == 1;
+ return fatalWarnings.loadRelaxed() && fatalWarnings.fetchAndAddRelaxed(-1) == 1;
}
return false;
@@ -240,7 +244,7 @@ static bool systemHasStderr()
\note Qt Creator does not implement a pseudo TTY, nor does it launch apps with
the override environment variable set, but it will read stderr and print it to
- the user, so in effect this function can not be used to conclude that stderr
+ the user, so in effect this function cannot be used to conclude that stderr
output will _not_ be visible to the user, as even if this function returns false,
the output might still end up visible to the user. For this reason, we don't guard
the stderr output in the default message handler with stderrHasConsoleAttached().
@@ -347,7 +351,7 @@ using namespace QtPrivate;
*/
#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
-static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const char *s) Q_DECL_NOEXCEPT
+static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const char *s) noexcept
{
size_t len = qstrlen(s);
if (len + 1 > space) {
@@ -439,7 +443,7 @@ void QMessageLogger::debug(const QLoggingCategory &cat, const char *msg, ...) co
return;
QMessageLogContext ctxt;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
va_list ap;
@@ -466,7 +470,7 @@ void QMessageLogger::debug(QMessageLogger::CategoryFunction catFunc,
return;
QMessageLogContext ctxt;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
va_list ap;
@@ -489,7 +493,7 @@ QDebug QMessageLogger::debug() const
{
QDebug dbg = QDebug(QtDebugMsg);
QMessageLogContext &ctxt = dbg.stream->context;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
return dbg;
}
@@ -506,7 +510,7 @@ QDebug QMessageLogger::debug(const QLoggingCategory &cat) const
dbg.stream->message_output = false;
QMessageLogContext &ctxt = dbg.stream->context;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
return dbg;
@@ -530,7 +534,7 @@ QDebug QMessageLogger::debug(QMessageLogger::CategoryFunction catFunc) const
\sa QNoDebug, qDebug()
*/
-QNoDebug QMessageLogger::noDebug() const Q_DECL_NOTHROW
+QNoDebug QMessageLogger::noDebug() const noexcept
{
return QNoDebug();
}
@@ -550,7 +554,7 @@ void QMessageLogger::info(const QLoggingCategory &cat, const char *msg, ...) con
return;
QMessageLogContext ctxt;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
va_list ap;
@@ -577,7 +581,7 @@ void QMessageLogger::info(QMessageLogger::CategoryFunction catFunc,
return;
QMessageLogContext ctxt;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
va_list ap;
@@ -601,7 +605,7 @@ QDebug QMessageLogger::info() const
{
QDebug dbg = QDebug(QtInfoMsg);
QMessageLogContext &ctxt = dbg.stream->context;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
return dbg;
}
@@ -618,7 +622,7 @@ QDebug QMessageLogger::info(const QLoggingCategory &cat) const
dbg.stream->message_output = false;
QMessageLogContext &ctxt = dbg.stream->context;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
return dbg;
@@ -668,7 +672,7 @@ void QMessageLogger::warning(const QLoggingCategory &cat, const char *msg, ...)
return;
QMessageLogContext ctxt;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
va_list ap;
@@ -695,7 +699,7 @@ void QMessageLogger::warning(QMessageLogger::CategoryFunction catFunc,
return;
QMessageLogContext ctxt;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
va_list ap;
@@ -717,7 +721,7 @@ QDebug QMessageLogger::warning() const
{
QDebug dbg = QDebug(QtWarningMsg);
QMessageLogContext &ctxt = dbg.stream->context;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
return dbg;
}
@@ -733,7 +737,7 @@ QDebug QMessageLogger::warning(const QLoggingCategory &cat) const
dbg.stream->message_output = false;
QMessageLogContext &ctxt = dbg.stream->context;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
return dbg;
@@ -784,7 +788,7 @@ void QMessageLogger::critical(const QLoggingCategory &cat, const char *msg, ...)
return;
QMessageLogContext ctxt;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
va_list ap;
@@ -811,7 +815,7 @@ void QMessageLogger::critical(QMessageLogger::CategoryFunction catFunc,
return;
QMessageLogContext ctxt;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
va_list ap;
@@ -833,7 +837,7 @@ QDebug QMessageLogger::critical() const
{
QDebug dbg = QDebug(QtCriticalMsg);
QMessageLogContext &ctxt = dbg.stream->context;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
return dbg;
}
@@ -850,7 +854,7 @@ QDebug QMessageLogger::critical(const QLoggingCategory &cat) const
dbg.stream->message_output = false;
QMessageLogContext &ctxt = dbg.stream->context;
- ctxt.copy(context);
+ ctxt.copyContextFrom(context);
ctxt.category = cat.categoryName();
return dbg;
@@ -876,7 +880,7 @@ QDebug QMessageLogger::critical(QMessageLogger::CategoryFunction catFunc) const
\sa qFatal()
*/
-void QMessageLogger::fatal(const char *msg, ...) const Q_DECL_NOTHROW
+void QMessageLogger::fatal(const char *msg, ...) const noexcept
{
QString message;
@@ -1076,8 +1080,8 @@ struct QMessagePattern {
void setPattern(const QString &pattern);
// 0 terminated arrays of literal tokens / literal or placeholder tokens
- const char **literals;
- const char **tokens;
+ std::unique_ptr<std::unique_ptr<const char[]>[]> literals;
+ std::unique_ptr<const char*[]> tokens;
QList<QString> timeArgs; // timeFormats in sequence of %{time
#ifndef QT_BOOTSTRAPPED
QElapsedTimer timer;
@@ -1100,9 +1104,6 @@ Q_DECLARE_TYPEINFO(QMessagePattern::BacktraceParams, Q_MOVABLE_TYPE);
QBasicMutex QMessagePattern::mutex;
QMessagePattern::QMessagePattern()
- : literals(0)
- , tokens(0)
- , fromEnvironment(false)
{
#ifndef QT_BOOTSTRAPPED
timer.start();
@@ -1110,6 +1111,7 @@ QMessagePattern::QMessagePattern()
const QString envPattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN"));
if (envPattern.isEmpty()) {
setPattern(QLatin1String(defaultPattern));
+ fromEnvironment = false;
} else {
setPattern(envPattern);
fromEnvironment = true;
@@ -1117,23 +1119,10 @@ QMessagePattern::QMessagePattern()
}
QMessagePattern::~QMessagePattern()
-{
- for (int i = 0; literals[i]; ++i)
- delete [] literals[i];
- delete [] literals;
- literals = 0;
- delete [] tokens;
- tokens = 0;
-}
+ = default;
void QMessagePattern::setPattern(const QString &pattern)
{
- if (literals) {
- for (int i = 0; literals[i]; ++i)
- delete [] literals[i];
- delete [] literals;
- }
- delete [] tokens;
timeArgs.clear();
#ifdef QLOGGING_HAVE_BACKTRACE
backtraceArgs.clear();
@@ -1171,9 +1160,9 @@ void QMessagePattern::setPattern(const QString &pattern)
lexemes.append(lexeme);
// tokenizer
- QVarLengthArray<const char*> literalsVar;
- tokens = new const char*[lexemes.size() + 1];
- tokens[lexemes.size()] = 0;
+ std::vector<std::unique_ptr<const char[]>> literalsVar;
+ tokens.reset(new const char*[lexemes.size() + 1]);
+ tokens[lexemes.size()] = nullptr;
bool nestedIfError = false;
bool inIf = false;
@@ -1267,7 +1256,7 @@ void QMessagePattern::setPattern(const QString &pattern)
char *literal = new char[lexeme.size() + 1];
strncpy(literal, lexeme.toLatin1().constData(), lexeme.size());
literal[lexeme.size()] = '\0';
- literalsVar.append(literal);
+ literalsVar.emplace_back(literal);
tokens[i] = literal;
}
}
@@ -1279,9 +1268,8 @@ void QMessagePattern::setPattern(const QString &pattern)
if (!error.isEmpty())
qt_message_print(error);
- literals = new const char*[literalsVar.size() + 1];
- literals[literalsVar.size()] = 0;
- memcpy(literals, literalsVar.constData(), literalsVar.size() * sizeof(const char*));
+ literals.reset(new std::unique_ptr<const char[]>[literalsVar.size() + 1]);
+ std::move(literalsVar.begin(), literalsVar.end(), &literals[0]);
}
#if defined(QLOGGING_HAVE_BACKTRACE) && !defined(QT_BOOTSTRAPPED)
@@ -1406,7 +1394,7 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con
#endif
// we do not convert file, function, line literals to local encoding due to overhead
- for (int i = 0; pattern->tokens[i] != 0; ++i) {
+ for (int i = 0; pattern->tokens[i]; ++i) {
const char *token = pattern->tokens[i];
if (token == endifTokenC) {
skip = false;
@@ -1512,9 +1500,9 @@ static void qDefaultMsgHandler(QtMsgType type, const char *buf);
static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &buf);
// pointer to QtMsgHandler debug handler (without context)
-static QBasicAtomicPointer<void (QtMsgType, const char*)> msgHandler = Q_BASIC_ATOMIC_INITIALIZER(qDefaultMsgHandler);
+static QBasicAtomicPointer<void (QtMsgType, const char*)> msgHandler = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
// pointer to QtMessageHandler debug handler (with context)
-static QBasicAtomicPointer<void (QtMsgType, const QMessageLogContext &, const QString &)> messageHandler = Q_BASIC_ATOMIC_INITIALIZER(qDefaultMessageHandler);
+static QBasicAtomicPointer<void (QtMsgType, const QMessageLogContext &, const QString &)> messageHandler = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
// ------------------------ Alternate logging sinks -------------------------
@@ -1826,14 +1814,15 @@ static void qt_message_print(QtMsgType msgType, const QMessageLogContext &contex
// prevent recursion in case the message handler generates messages
// itself, e.g. by using Qt API
if (grabMessageHandler()) {
+ const auto ungrab = qScopeGuard([]{ ungrabMessageHandler(); });
+ auto oldStyle = msgHandler.loadAcquire();
+ auto newStye = messageHandler.loadAcquire();
// prefer new message handler over the old one
- if (msgHandler.load() == qDefaultMsgHandler
- || messageHandler.load() != qDefaultMessageHandler) {
- (*messageHandler.load())(msgType, context, message);
+ if (newStye || !oldStyle) {
+ (newStye ? newStye : qDefaultMessageHandler)(msgType, context, message);
} else {
- (*msgHandler.load())(msgType, message.toLocal8Bit().constData());
+ (oldStyle ? oldStyle : qDefaultMsgHandler)(msgType, message.toLocal8Bit().constData());
}
- ungrabMessageHandler();
} else {
fprintf(stderr, "%s\n", message.toLocal8Bit().constData());
}
@@ -2084,18 +2073,20 @@ void qErrnoWarning(int code, const char *msg, ...)
QtMessageHandler qInstallMessageHandler(QtMessageHandler h)
{
- if (!h)
- h = qDefaultMessageHandler;
- //set 'h' and return old message handler
- return messageHandler.fetchAndStoreRelaxed(h);
+ const auto old = messageHandler.fetchAndStoreOrdered(h);
+ if (old)
+ return old;
+ else
+ return qDefaultMessageHandler;
}
QtMsgHandler qInstallMsgHandler(QtMsgHandler h)
{
- if (!h)
- h = qDefaultMsgHandler;
- //set 'h' and return old message handler
- return msgHandler.fetchAndStoreRelaxed(h);
+ const auto old = msgHandler.fetchAndStoreOrdered(h);
+ if (old)
+ return old;
+ else
+ return qDefaultMsgHandler;
}
void qSetMessagePattern(const QString &pattern)
@@ -2108,15 +2099,20 @@ void qSetMessagePattern(const QString &pattern)
/*!
- Copies context information from \a logContext into this QMessageLogContext
+ Copies context information from \a logContext into this QMessageLogContext.
+ Returns a reference to this object.
+
+ Note that the version is \b not copied, only the context information.
+
\internal
*/
-void QMessageLogContext::copy(const QMessageLogContext &logContext)
+QMessageLogContext &QMessageLogContext::copyContextFrom(const QMessageLogContext &logContext) noexcept
{
this->category = logContext.category;
this->file = logContext.file;
this->line = logContext.line;
this->function = logContext.function;
+ return *this;
}
/*!
diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h
index 16e01183bd..4a528a2973 100644
--- a/src/corelib/global/qlogging.h
+++ b/src/corelib/global/qlogging.h
@@ -63,20 +63,19 @@ class QMessageLogContext
{
Q_DISABLE_COPY(QMessageLogContext)
public:
- Q_DECL_CONSTEXPR QMessageLogContext()
- : version(2), line(0), file(nullptr), function(nullptr), category(nullptr) {}
- Q_DECL_CONSTEXPR QMessageLogContext(const char *fileName, int lineNumber, const char *functionName, const char *categoryName)
- : version(2), line(lineNumber), file(fileName), function(functionName), category(categoryName) {}
+ Q_DECL_CONSTEXPR QMessageLogContext() noexcept = default;
+ Q_DECL_CONSTEXPR QMessageLogContext(const char *fileName, int lineNumber, const char *functionName, const char *categoryName) noexcept
+ : line(lineNumber), file(fileName), function(functionName), category(categoryName) {}
- void copy(const QMessageLogContext &logContext);
-
- int version;
- int line;
- const char *file;
- const char *function;
- const char *category;
+ int version = 2;
+ int line = 0;
+ const char *file = nullptr;
+ const char *function = nullptr;
+ const char *category = nullptr;
private:
+ QMessageLogContext &copyContextFrom(const QMessageLogContext &logContext) noexcept;
+
friend class QMessageLogger;
friend class QDebug;
};
@@ -121,7 +120,7 @@ public:
Q_NORETURN
#endif
Q_DECL_COLD_FUNCTION
- void fatal(const char *msg, ...) const Q_DECL_NOTHROW Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
+ void fatal(const char *msg, ...) const noexcept Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
#ifndef QT_NO_DEBUG_STREAM
QDebug debug() const;
@@ -137,7 +136,7 @@ public:
QDebug critical(const QLoggingCategory &cat) const;
QDebug critical(CategoryFunction catFunc) const;
- QNoDebug noDebug() const Q_DECL_NOTHROW;
+ QNoDebug noDebug() const noexcept;
#endif // QT_NO_DEBUG_STREAM
private:
@@ -153,9 +152,9 @@ private:
#endif
#ifdef QT_MESSAGELOGCONTEXT
- #define QT_MESSAGELOG_FILE __FILE__
+ #define QT_MESSAGELOG_FILE static_cast<const char *>(__FILE__)
#define QT_MESSAGELOG_LINE __LINE__
- #define QT_MESSAGELOG_FUNC Q_FUNC_INFO
+ #define QT_MESSAGELOG_FUNC static_cast<const char *>(Q_FUNC_INFO)
#else
#define QT_MESSAGELOG_FILE nullptr
#define QT_MESSAGELOG_LINE 0
diff --git a/src/corelib/global/qmalloc.cpp b/src/corelib/global/qmalloc.cpp
index 05676a0da2..b071c1df62 100644
--- a/src/corelib/global/qmalloc.cpp
+++ b/src/corelib/global/qmalloc.cpp
@@ -74,18 +74,18 @@ void *qRealloc(void *ptr, size_t size)
void *qMallocAligned(size_t size, size_t alignment)
{
- return qReallocAligned(0, size, 0, alignment);
+ return qReallocAligned(nullptr, size, 0, alignment);
}
void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t alignment)
{
// fake an aligned allocation
- void *actualptr = oldptr ? static_cast<void **>(oldptr)[-1] : 0;
+ void *actualptr = oldptr ? static_cast<void **>(oldptr)[-1] : nullptr;
if (alignment <= sizeof(void*)) {
// special, fast case
void **newptr = static_cast<void **>(realloc(actualptr, newsize + sizeof(void*)));
if (!newptr)
- return 0;
+ return nullptr;
if (newptr == actualptr) {
// realloc succeeded without reallocating
return oldptr;
@@ -105,7 +105,7 @@ void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t align
void *real = realloc(actualptr, newsize + alignment);
if (!real)
- return 0;
+ return nullptr;
quintptr faked = reinterpret_cast<quintptr>(real) + alignment;
faked &= ~(alignment - 1);
diff --git a/src/corelib/global/qfloat16_p.h b/src/corelib/global/qmemory_p.h
index f3fc96e119..ac791385bd 100644
--- a/src/corelib/global/qfloat16_p.h
+++ b/src/corelib/global/qmemory_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 by Southwest Research Institute (R)
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
@@ -36,9 +36,8 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
-#ifndef QFLOAT16_P_H
-#define QFLOAT16_P_H
+#ifndef QMEMORY_P_H
+#define QMEMORY_P_H
//
// W A R N I N G
@@ -51,45 +50,22 @@
// We mean it.
//
-#include <QtCore/qfloat16.h>
-#include <QtCore/qsysinfo.h>
-
-QT_BEGIN_NAMESPACE
+#include <QtCore/qglobal.h>
-static inline bool qt_is_inf(qfloat16 d) Q_DECL_NOTHROW
-{
- bool is_inf;
- uchar *ch = (uchar *)&d;
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
- is_inf = (ch[0] & 0x7c) == 0x7c && (ch[0] & 0x02) == 0;
- else
- is_inf = (ch[1] & 0x7c) == 0x7c && (ch[1] & 0x02) == 0;
- return is_inf;
-}
+#include <memory>
+#include <type_traits>
+#include <utility>
-static inline bool qt_is_nan(qfloat16 d) Q_DECL_NOTHROW
-{
- bool is_nan;
- uchar *ch = (uchar *)&d;
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
- is_nan = (ch[0] & 0x7c) == 0x7c && (ch[0] & 0x02) != 0;
- else
- is_nan = (ch[1] & 0x7c) == 0x7c && (ch[1] & 0x02) != 0;
- return is_nan;
-}
+QT_BEGIN_NAMESPACE
-static inline bool qt_is_finite(qfloat16 d) Q_DECL_NOTHROW
+// Like std::make_unique, but less ambitious, so keep as private API, for use in Qt itself:
+template <typename T, typename... Args>
+typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
+qt_make_unique(Args &&...args)
{
- bool is_finite;
- uchar *ch = (uchar *)&d;
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
- is_finite = (ch[0] & 0x7c) != 0x7c;
- else
- is_finite = (ch[1] & 0x7c) != 0x7c;
- return is_finite;
+ return std::unique_ptr<T>{new T(std::forward<Args>(args)...)};
}
-
QT_END_NAMESPACE
-#endif // QFLOAT16_P_H
+#endif /* QMEMORY_P_H */
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index dec2c44637..f5f7176670 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -50,10 +50,10 @@ QT_BEGIN_NAMESPACE
#if !defined(Q_QDOC) && !defined(Q_MOC_RUN)
struct QMetaObject;
-const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT; // defined in qobject.h (which can't be included here)
+const QMetaObject *qt_getQtMetaObject() noexcept; // defined in qobject.h (which can't be included here)
#define QT_Q_ENUM(ENUM) \
- inline const QMetaObject *qt_getEnumMetaObject(ENUM) Q_DECL_NOEXCEPT { return qt_getQtMetaObject(); } \
- inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) Q_DECL_NOEXCEPT { return #ENUM; }
+ inline const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return qt_getQtMetaObject(); } \
+ inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
#define QT_Q_FLAG(ENUM) QT_Q_ENUM(ENUM)
#else
#define QT_Q_ENUM Q_ENUM
@@ -194,6 +194,13 @@ public:
DescendingOrder
};
+ enum SplitBehaviorFlags {
+ KeepEmptyParts = 0,
+ SkipEmptyParts = 0x1,
+ };
+ Q_DECLARE_FLAGS(SplitBehavior, SplitBehaviorFlags)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(SplitBehavior)
+
enum TileRule {
StretchTile,
RepeatTile,
@@ -351,14 +358,18 @@ public:
WA_MouseTracking = 2,
WA_ContentsPropagated = 3, // ## deprecated
WA_OpaquePaintEvent = 4,
- WA_NoBackground = WA_OpaquePaintEvent, // ## deprecated
+#if QT_DEPRECATED_SINCE(5, 14)
+ WA_NoBackground Q_DECL_ENUMERATOR_DEPRECATED = WA_OpaquePaintEvent,
+#endif
WA_StaticContents = 5,
WA_LaidOut = 7,
WA_PaintOnScreen = 8,
WA_NoSystemBackground = 9,
WA_UpdatesDisabled = 10,
WA_Mapped = 11,
- WA_MacNoClickThrough = 12, // Mac only
+#if QT_DEPRECATED_SINCE(5, 14)
+ WA_MacNoClickThrough Q_DECL_ENUMERATOR_DEPRECATED = 12,
+#endif
WA_InputMethodEnabled = 14,
WA_WState_Visible = 15,
WA_WState_Hidden = 16,
@@ -376,8 +387,10 @@ public:
WA_Moved = 43,
WA_PendingUpdate = 44,
WA_InvalidSize = 45,
- WA_MacBrushedMetal = 46, // Mac only
- WA_MacMetalStyle = WA_MacBrushedMetal, // obsolete
+#if QT_DEPRECATED_SINCE(5, 14)
+ WA_MacBrushedMetal Q_DECL_ENUMERATOR_DEPRECATED = 46,
+ WA_MacMetalStyle Q_DECL_ENUMERATOR_DEPRECATED = 46,
+#endif
WA_CustomWhatsThis = 47,
WA_LayoutOnEntireRect = 48,
WA_OutsideWSRange = 49,
@@ -434,7 +447,9 @@ public:
WA_LayoutUsesWidgetRect = 92,
WA_StyledBackground = 93, // internal
- WA_MSWindowsUseDirect3D = 94, // Win only
+#if QT_DEPRECATED_SINCE(5, 14)
+ WA_MSWindowsUseDirect3D Q_DECL_ENUMERATOR_DEPRECATED = 94,
+#endif
WA_CanHostQMdiSubWindowTitleBar = 95, // Internal
WA_MacAlwaysShowToolWindow = 96, // Mac only
@@ -466,9 +481,9 @@ public:
WA_X11NetWmWindowTypeNotification = 114,
WA_X11NetWmWindowTypeCombo = 115,
WA_X11NetWmWindowTypeDND = 116,
-
- WA_MacFrameworkScaled = 117,
-
+#if QT_DEPRECATED_SINCE(5, 14)
+ WA_MacFrameworkScaled Q_DECL_ENUMERATOR_DEPRECATED = 117,
+#endif
WA_SetWindowModality = 118,
WA_WState_WindowOpacitySet = 119, // internal
WA_TranslucentBackground = 120,
@@ -495,16 +510,22 @@ public:
enum ApplicationAttribute
{
AA_ImmediateWidgetCreation = 0,
- AA_MSWindowsUseDirect3DByDefault = 1, // Win only
+#if QT_DEPRECATED_SINCE(5, 14)
+ AA_MSWindowsUseDirect3DByDefault Q_DECL_ENUMERATOR_DEPRECATED = 1,
+#endif
AA_DontShowIconsInMenus = 2,
AA_NativeWindows = 3,
AA_DontCreateNativeWidgetSiblings = 4,
AA_PluginApplication = 5,
- AA_MacPluginApplication = AA_PluginApplication, // ### Qt 6: remove me
+#if QT_DEPRECATED_SINCE(5, 13) // ### Qt 6: remove me
+ AA_MacPluginApplication Q_DECL_ENUMERATOR_DEPRECATED = AA_PluginApplication,
+#endif
AA_DontUseNativeMenuBar = 6,
AA_MacDontSwapCtrlAndMeta = 7,
AA_Use96Dpi = 8,
- AA_X11InitThreads = 10,
+#if QT_DEPRECATED_SINCE(5, 14)
+ AA_X11InitThreads Q_DECL_ENUMERATOR_DEPRECATED = 10,
+#endif
AA_SynthesizeTouchForUnhandledMouseEvents = 11,
AA_SynthesizeMouseForUnhandledTouchEvents = 12,
AA_UseHighDpiPixmaps = 13,
@@ -516,7 +537,7 @@ public:
AA_SetPalette = 19,
AA_EnableHighDpiScaling = 20,
AA_DisableHighDpiScaling = 21,
- AA_UseStyleSheetPropagationInWidgetStyles = 22, // ### Qt 6: remove me
+ AA_UseStyleSheetPropagationInWidgetStyles = 22,
AA_DontUseNativeDialogs = 23,
AA_SynthesizeMouseForUnhandledTabletEvents = 24,
AA_CompressHighFrequencyEvents = 25,
@@ -525,6 +546,7 @@ public:
AA_DontShowShortcutsInContextMenus = 28,
AA_CompressTabletEvents = 29,
AA_DisableWindowContextHelpButton = 30, // ### Qt 6: remove me
+ AA_DisableSessionManager = 31,
// Add new attributes before this line
AA_AttributeCount
@@ -1196,7 +1218,8 @@ public:
enum TextFormat {
PlainText,
RichText,
- AutoText
+ AutoText,
+ MarkdownText
};
enum AspectRatioMode {
@@ -1377,7 +1400,9 @@ public:
enum InputMethodQuery {
ImEnabled = 0x1,
ImCursorRectangle = 0x2,
- ImMicroFocus = 0x2, // deprecated
+#if QT_DEPRECATED_SINCE(5, 14)
+ ImMicroFocus Q_DECL_ENUMERATOR_DEPRECATED = 0x2,
+#endif
ImFont = 0x4,
ImCursorPosition = 0x8,
ImSurroundingText = 0x10,
@@ -1504,10 +1529,12 @@ public:
// Metadata
FontRole = 6,
TextAlignmentRole = 7,
- BackgroundColorRole = 8,
BackgroundRole = 8,
- TextColorRole = 9,
ForegroundRole = 9,
+#if QT_DEPRECATED_SINCE(5, 13) // ### Qt 6: remove me
+ BackgroundColorRole Q_DECL_ENUMERATOR_DEPRECATED = BackgroundRole,
+ TextColorRole Q_DECL_ENUMERATOR_DEPRECATED = ForegroundRole,
+#endif
CheckStateRole = 10,
// Accessibility
AccessibleTextRole = 11,
@@ -1610,7 +1637,7 @@ public:
TitleBarArea // For move
};
-#if defined(Q_COMPILER_CLASS_ENUM) && defined(Q_COMPILER_CONSTEXPR)
+#if defined(Q_COMPILER_CONSTEXPR)
enum class Initialization {
Uninitialized
};
@@ -1753,6 +1780,7 @@ public:
QT_Q_FLAG(Alignment)
QT_Q_ENUM(TextFlag)
QT_Q_FLAG(Orientations)
+ QT_Q_FLAG(SplitBehavior)
QT_Q_FLAG(DropActions)
QT_Q_FLAG(Edges)
QT_Q_FLAG(DockWidgetAreas)
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 5bba8c5fe5..45d79902c7 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -286,6 +286,13 @@
This value was added in Qt 5.10. In Qt 6, WindowContextHelpButtonHint
will not be set by default.
+ \value AA_DisableSessionManager Disables the QSessionManager.
+ By default Qt will connect to a running session manager for a GUI
+ application on supported platforms, use of a session manager may be
+ redundant for system services.
+ This attribute must be set before QGuiApplication is constructed.
+ This value was added in 5.13
+
The following values are deprecated or obsolete:
\value AA_ImmediateWidgetCreation This attribute is no longer fully
@@ -2362,6 +2369,19 @@
*/
/*!
+ \enum Qt::SplitBehavior
+ \since 5.14
+
+ This enum specifies how the split() functions should behave with
+ respect to empty strings.
+
+ \value KeepEmptyParts If a field is empty, keep it in the result.
+ \value SkipEmptyParts If a field is empty, don't include it in the result.
+
+ \sa QString::split()
+*/
+
+/*!
\enum Qt::ClipOperation
\value NoClip This operation turns clipping off.
@@ -2464,6 +2484,9 @@
\value AutoText The text string is interpreted as for
Qt::RichText if Qt::mightBeRichText() returns \c true, otherwise
as Qt::PlainText.
+
+ \value MarkdownText The text string is interpreted as Markdown-formatted text.
+ This enum value was added in Qt 5.14.
*/
/*!
diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp
index fc2b052edf..11440f40a4 100644
--- a/src/corelib/global/qnumeric.cpp
+++ b/src/corelib/global/qnumeric.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE
/*!
Returns \c true if the double \a {d} is equivalent to infinity.
\relates <QtGlobal>
+ \sa qInf()
*/
Q_CORE_EXPORT bool qIsInf(double d) { return qt_is_inf(d); }
@@ -64,6 +65,7 @@ Q_CORE_EXPORT bool qIsFinite(double d) { return qt_is_finite(d); }
/*!
Returns \c true if the float \a {f} is equivalent to infinity.
\relates <QtGlobal>
+ \sa qInf()
*/
Q_CORE_EXPORT bool qIsInf(float f) { return qt_is_inf(f); }
@@ -88,15 +90,37 @@ Q_CORE_EXPORT double qSNaN() { return qt_snan(); }
/*!
Returns the bit pattern of a quiet NaN as a double.
\relates <QtGlobal>
+ \sa qIsNaN()
*/
Q_CORE_EXPORT double qQNaN() { return qt_qnan(); }
/*!
Returns the bit pattern for an infinite number as a double.
\relates <QtGlobal>
+ \sa qIsInf()
*/
Q_CORE_EXPORT double qInf() { return qt_inf(); }
+/*!
+ \relates <QtGlobal>
+ Classifies a floating-point value.
+
+ The return values are defined in \c{<cmath>}: returns one of the following,
+ determined by the floating-point class of \a val:
+ \list
+ \li FP_NAN not a number
+ \li FP_INFINITE infinities (positive or negative)
+ \li FP_ZERO zero (positive or negative)
+ \li FP_NORMAL finite with a full mantissa
+ \li FP_SUBNORMAL finite with a reduced mantissa
+ \endlist
+*/
+Q_CORE_EXPORT int qFpClassify(double val) { return qt_fpclassify(val); }
+
+/*!
+ \overload
+*/
+Q_CORE_EXPORT int qFpClassify(float val) { return qt_fpclassify(val); }
/*!
diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h
index 535a96aaec..6a0c64712f 100644
--- a/src/corelib/global/qnumeric.h
+++ b/src/corelib/global/qnumeric.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -48,9 +48,11 @@ QT_BEGIN_NAMESPACE
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(double d);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(double d);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(double d);
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(double val);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(float f);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(float f);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(float f);
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(float val);
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qSNaN();
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN();
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qInf();
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
index 4a225b2599..21f9cfbef0 100644
--- a/src/corelib/global/qnumeric_p.h
+++ b/src/corelib/global/qnumeric_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -85,9 +85,11 @@ namespace qnumeric_std_wrapper {
Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(double d) { using namespace std; return isnan(d); }
Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(double d) { using namespace std; return isinf(d); }
Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(double d) { using namespace std; return isfinite(d); }
+Q_DECL_CONST_FUNCTION static inline int math_h_fpclassify(double d) { using namespace std; return fpclassify(d); }
Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(float f) { using namespace std; return isnan(f); }
Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(float f) { using namespace std; return isinf(f); }
Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(float f) { using namespace std; return isfinite(f); }
+Q_DECL_CONST_FUNCTION static inline int math_h_fpclassify(float f) { using namespace std; return fpclassify(f); }
}
QT_END_NAMESPACE
// These macros from math.h conflict with the real functions in the std namespace.
@@ -95,6 +97,7 @@ QT_END_NAMESPACE
# undef isnan
# undef isinf
# undef isfinite
+# undef fpclassify
# endif // defined(isnan)
#endif
@@ -106,20 +109,24 @@ namespace qnumeric_std_wrapper {
Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return math_h_isnan(d); }
Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return math_h_isinf(d); }
Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return math_h_isfinite(d); }
+Q_DECL_CONST_FUNCTION static inline int fpclassify(double d) { return math_h_fpclassify(d); }
Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return math_h_isnan(f); }
Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return math_h_isinf(f); }
Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return math_h_isfinite(f); }
+Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return math_h_fpclassify(f); }
#else
Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return std::isnan(d); }
Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return std::isinf(d); }
Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return std::isfinite(d); }
+Q_DECL_CONST_FUNCTION static inline int fpclassify(double d) { return std::fpclassify(d); }
Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return std::isnan(f); }
Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return std::isinf(f); }
Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return std::isfinite(f); }
+Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return std::fpclassify(f); }
#endif
}
-Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_inf() Q_DECL_NOEXCEPT
+Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_inf() noexcept
{
Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_infinity,
"platform has no definition for infinity for type double");
@@ -127,7 +134,7 @@ Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_inf() Q_DECL_NOEX
}
// Signaling NaN
-Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_snan() Q_DECL_NOEXCEPT
+Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_snan() noexcept
{
Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_signaling_NaN,
"platform has no definition for signaling NaN for type double");
@@ -135,7 +142,7 @@ Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_snan() Q_DECL_NOE
}
// Quiet NaN
-Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_qnan() Q_DECL_NOEXCEPT
+Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_qnan() noexcept
{
Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_quiet_NaN,
"platform has no definition for quiet NaN for type double");
@@ -157,6 +164,11 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(double d)
return qnumeric_std_wrapper::isfinite(d);
}
+Q_DECL_CONST_FUNCTION static inline int qt_fpclassify(double d)
+{
+ return qnumeric_std_wrapper::fpclassify(d);
+}
+
Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(float f)
{
return qnumeric_std_wrapper::isinf(f);
@@ -172,6 +184,11 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f)
return qnumeric_std_wrapper::isfinite(f);
}
+Q_DECL_CONST_FUNCTION static inline int qt_fpclassify(float f)
+{
+ return qnumeric_std_wrapper::fpclassify(f);
+}
+
#ifndef Q_CLANG_QDOC
namespace {
/*!
diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp
index 94dc261b41..42a1275621 100644
--- a/src/corelib/global/qoperatingsystemversion.cpp
+++ b/src/corelib/global/qoperatingsystemversion.cpp
@@ -340,7 +340,6 @@ QString QOperatingSystemVersion::name() const
}
}
-#ifdef Q_COMPILER_INITIALIZER_LISTS
/*!
\fn bool QOperatingSystemVersion::isAnyOfType(std::initializer_list<OSType> types) const
@@ -355,7 +354,6 @@ bool QOperatingSystemVersion::isAnyOfType(std::initializer_list<OSType> types) c
}
return false;
}
-#endif
/*!
\variable QOperatingSystemVersion::Windows7
diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h
index df01e5438a..e99e4f8997 100644
--- a/src/corelib/global/qoperatingsystemversion.h
+++ b/src/corelib/global/qoperatingsystemversion.h
@@ -119,9 +119,7 @@ public:
Q_DECL_CONSTEXPR int segmentCount() const
{ return m_micro >= 0 ? 3 : m_minor >= 0 ? 2 : m_major >= 0 ? 1 : 0; }
-#ifdef Q_COMPILER_INITIALIZER_LISTS
bool isAnyOfType(std::initializer_list<OSType> types) const;
-#endif
Q_DECL_CONSTEXPR OSType type() const { return m_os; }
QString name() const;
diff --git a/src/corelib/global/qoperatingsystemversion_win.cpp b/src/corelib/global/qoperatingsystemversion_win.cpp
index 2da190da48..798d985a76 100644
--- a/src/corelib/global/qoperatingsystemversion_win.cpp
+++ b/src/corelib/global/qoperatingsystemversion_win.cpp
@@ -84,7 +84,6 @@ static inline OSVERSIONINFOEX determineWinOsVersion()
#define pGetModuleHandle GetModuleHandleW
#endif
-#ifndef Q_OS_WINCE
HMODULE ntdll = pGetModuleHandle(L"ntdll.dll");
if (Q_UNLIKELY(!ntdll))
return result;
@@ -104,9 +103,6 @@ static inline OSVERSIONINFOEX determineWinOsVersion()
// GetVersionEx() has been deprecated in Windows 8.1 and will return
// only Windows 8 from that version on, so use the kernel API function.
pRtlGetVersion(reinterpret_cast<LPOSVERSIONINFO>(&result)); // always returns STATUS_SUCCESS
-#else // !Q_OS_WINCE
- GetVersionEx(&result);
-#endif
return result;
}
diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h
index 77b3ba36b0..8d65720850 100644
--- a/src/corelib/global/qprocessordetection.h
+++ b/src/corelib/global/qprocessordetection.h
@@ -282,6 +282,20 @@
// Q_BYTE_ORDER not defined, use endianness auto-detection
/*
+ RISC-V family, known variants: 32- and 64-bit
+
+ RISC-V is little-endian.
+*/
+#elif defined(__riscv)
+# define Q_PROCESSOR_RISCV
+# if __riscv_xlen == 64
+# define Q_PROCESSOR_RISCV_64
+# else
+# define Q_PROCESSOR_RISCV_32
+# endif
+# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
+
+/*
S390 family, known variant: S390X (64-bit)
S390 is big-endian.
@@ -324,7 +338,6 @@
// -- Web Assembly --
#elif defined(__EMSCRIPTEN__)
# define Q_PROCESSOR_WASM
-# define Q_PROCESSOR_X86 6 // enables SIMD support
# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
# define Q_PROCESSOR_WORDSIZE 8
#endif
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
index 90df8653a7..84cf960f2d 100644
--- a/src/corelib/global/qrandom.cpp
+++ b/src/corelib/global/qrandom.cpp
@@ -91,7 +91,7 @@ DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG Rando
QT_BEGIN_NAMESPACE
#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND)
-static qsizetype qt_random_cpu(void *buffer, qsizetype count) Q_DECL_NOTHROW;
+static qsizetype qt_random_cpu(void *buffer, qsizetype count) noexcept;
# ifdef Q_PROCESSOR_X86_64
# define _rdrandXX_step _rdrand64_step
@@ -99,7 +99,7 @@ static qsizetype qt_random_cpu(void *buffer, qsizetype count) Q_DECL_NOTHROW;
# define _rdrandXX_step _rdrand32_step
# endif
-static QT_FUNCTION_TARGET(RDRND) qsizetype qt_random_cpu(void *buffer, qsizetype count) Q_DECL_NOTHROW
+static QT_FUNCTION_TARGET(RDRND) qsizetype qt_random_cpu(void *buffer, qsizetype count) noexcept
{
unsigned *ptr = reinterpret_cast<unsigned *>(buffer);
unsigned *end = ptr + count;
@@ -134,7 +134,7 @@ enum {
struct QRandomGenerator::SystemGenerator
{
#if QT_CONFIG(getentropy)
- static qsizetype fillBuffer(void *buffer, qsizetype count) Q_DECL_NOTHROW
+ static qsizetype fillBuffer(void *buffer, qsizetype count) noexcept
{
// getentropy can read at most 256 bytes, so break the reading
qsizetype read = 0;
@@ -186,7 +186,7 @@ struct QRandomGenerator::SystemGenerator
#endif
static void closeDevice()
{
- int fd = self().fdp1.load() - 1;
+ int fd = self().fdp1.loadRelaxed() - 1;
if (fd >= 0)
qt_safe_close(fd);
}
@@ -204,13 +204,13 @@ struct QRandomGenerator::SystemGenerator
}
#elif defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
- qsizetype fillBuffer(void *buffer, qsizetype count) Q_DECL_NOTHROW
+ qsizetype fillBuffer(void *buffer, qsizetype count) noexcept
{
auto RtlGenRandom = SystemFunction036;
return RtlGenRandom(buffer, ULONG(count)) ? count: 0;
}
#elif defined(Q_OS_WINRT)
- qsizetype fillBuffer(void *, qsizetype) Q_DECL_NOTHROW
+ qsizetype fillBuffer(void *, qsizetype) noexcept
{
// always use the fallback
return 0;
@@ -219,7 +219,7 @@ struct QRandomGenerator::SystemGenerator
static SystemGenerator &self();
typedef quint32 result_type;
- void generate(quint32 *begin, quint32 *end) Q_DECL_NOEXCEPT_EXPR(FillBufferNoexcept);
+ void generate(quint32 *begin, quint32 *end) noexcept(FillBufferNoexcept);
// For std::mersenne_twister_engine implementations that use something
// other than quint32 (unsigned int) to fill their buffers.
@@ -242,7 +242,7 @@ struct QRandomGenerator::SystemGenerator
#if defined(Q_OS_WIN)
static void fallback_update_seed(unsigned) {}
-static void fallback_fill(quint32 *ptr, qsizetype left) Q_DECL_NOTHROW
+static void fallback_fill(quint32 *ptr, qsizetype left) noexcept
{
// on Windows, rand_s is a high-quality random number generator
// and it requires no seeding
@@ -254,14 +254,14 @@ static void fallback_fill(quint32 *ptr, qsizetype left) Q_DECL_NOTHROW
}
#elif QT_CONFIG(getentropy)
static void fallback_update_seed(unsigned) {}
-static void fallback_fill(quint32 *, qsizetype) Q_DECL_NOTHROW
+static void fallback_fill(quint32 *, qsizetype) noexcept
{
// no fallback necessary, getentropy cannot fail under normal circumstances
Q_UNREACHABLE();
}
#elif defined(Q_OS_BSD4) && !defined(__GLIBC__)
static void fallback_update_seed(unsigned) {}
-static void fallback_fill(quint32 *ptr, qsizetype left) Q_DECL_NOTHROW
+static void fallback_fill(quint32 *ptr, qsizetype left) noexcept
{
// BSDs have arc4random(4) and these work even in chroot(2)
arc4random_buf(ptr, left * sizeof(*ptr));
@@ -280,7 +280,7 @@ Q_NEVER_INLINE
#ifdef Q_CC_GNU
__attribute__((cold)) // this function is pretty big, so optimize for size
#endif
-static void fallback_fill(quint32 *ptr, qsizetype left) Q_DECL_NOTHROW
+static void fallback_fill(quint32 *ptr, qsizetype left) noexcept
{
quint32 scratch[12]; // see element count below
quint32 *end = scratch;
@@ -310,7 +310,7 @@ static void fallback_fill(quint32 *ptr, qsizetype left) Q_DECL_NOTHROW
*end++ = quint32(nsecs); // 5
#endif
- if (quint32 v = seed.load())
+ if (quint32 v = seed.loadRelaxed())
*end++ = v; // 6
#if QT_CONFIG(getauxval)
@@ -354,7 +354,7 @@ static void fallback_fill(quint32 *ptr, qsizetype left) Q_DECL_NOTHROW
#endif
Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin, quint32 *end)
- Q_DECL_NOEXCEPT_EXPR(FillBufferNoexcept)
+ noexcept(FillBufferNoexcept)
{
quint32 *buffer = begin;
qsizetype count = end - begin;
@@ -1167,7 +1167,7 @@ QRandomGenerator &QRandomGenerator::operator=(const QRandomGenerator &other)
return *this;
}
-QRandomGenerator::QRandomGenerator(std::seed_seq &sseq) Q_DECL_NOTHROW
+QRandomGenerator::QRandomGenerator(std::seed_seq &sseq) noexcept
: type(MersenneTwister)
{
Q_ASSERT(this != system());
diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h
index 46d3e0e152..2f72528266 100644
--- a/src/corelib/global/qrandom.h
+++ b/src/corelib/global/qrandom.h
@@ -68,7 +68,7 @@ public:
QRandomGenerator(const quint32 *seedBuffer, qsizetype len)
: QRandomGenerator(seedBuffer, seedBuffer + len)
{}
- Q_CORE_EXPORT QRandomGenerator(std::seed_seq &sseq) Q_DECL_NOTHROW;
+ Q_CORE_EXPORT QRandomGenerator(std::seed_seq &sseq) noexcept;
Q_CORE_EXPORT QRandomGenerator(const quint32 *begin, const quint32 *end);
// copy constructor & assignment operator (move unnecessary)
@@ -165,7 +165,7 @@ public:
typedef quint32 result_type;
result_type operator()() { return generate(); }
void seed(quint32 s = 1) { *this = { s }; }
- void seed(std::seed_seq &sseq) Q_DECL_NOTHROW { *this = { sseq }; }
+ void seed(std::seed_seq &sseq) noexcept { *this = { sseq }; }
Q_CORE_EXPORT void discard(unsigned long long z);
static Q_DECL_CONSTEXPR result_type min() { return std::numeric_limits<result_type>::min(); }
static Q_DECL_CONSTEXPR result_type max() { return std::numeric_limits<result_type>::max(); }
@@ -228,7 +228,7 @@ public:
QRandomGenerator64(const quint32 *seedBuffer, qsizetype len)
: QRandomGenerator(seedBuffer, len)
{}
- QRandomGenerator64(std::seed_seq &sseq) Q_DECL_NOTHROW
+ QRandomGenerator64(std::seed_seq &sseq) noexcept
: QRandomGenerator(sseq)
{}
QRandomGenerator64(const quint32 *begin, const quint32 *end)
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index a2e51fa330..02e2f77c6b 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -166,6 +166,8 @@
# define Q_OS_QNX
#elif defined(__INTEGRITY)
# define Q_OS_INTEGRITY
+#elif defined(__rtems__)
+# define Q_OS_RTEMS
#elif defined(VXWORKS) /* there is no "real" VxWorks define - this has to be set in the mkspec! */
# define Q_OS_VXWORKS
#elif defined(__HAIKU__)
diff --git a/src/corelib/global/qt_pch.h b/src/corelib/global/qt_pch.h
index 76e46374c3..3972991618 100644
--- a/src/corelib/global/qt_pch.h
+++ b/src/corelib/global/qt_pch.h
@@ -60,12 +60,18 @@
# undef _POSIX_
#endif
#include <qcoreapplication.h>
+#include <qcoreevent.h>
+#include <qiodevice.h>
#include <qlist.h>
#include <qvariant.h> /* All moc genereated code has this include */
#include <qobject.h>
#include <qregexp.h>
+#include <qscopedpointer.h>
+#include <qshareddata.h>
#include <qstring.h>
#include <qstringlist.h>
+#include <qtimer.h>
+#include <qvector.h>
#if QT_CONFIG(textcodec)
#include <qtextcodec.h>
#endif
diff --git a/src/corelib/global/qtrace_p.h b/src/corelib/global/qtrace_p.h
index 4cef126bb6..d9011c6066 100644
--- a/src/corelib/global/qtrace_p.h
+++ b/src/corelib/global/qtrace_p.h
@@ -122,6 +122,7 @@
QT_BEGIN_NAMESPACE
#if defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED)
+# define Q_HAS_TRACEPOINTS 1
# define Q_TRACE(x, ...) QtPrivate::trace_ ## x(__VA_ARGS__)
# define Q_TRACE_EXIT(x, ...) \
const auto qTraceExit_ ## x ## __COUNTER__ = qScopeGuard([&]() { Q_TRACE(x, __VA_ARGS__); });
@@ -131,6 +132,7 @@ QT_BEGIN_NAMESPACE
# define Q_UNCONDITIONAL_TRACE(x, ...) QtPrivate::do_trace_ ## x(__VA_ARGS__)
# define Q_TRACE_ENABLED(x) QtPrivate::trace_ ## x ## _enabled()
#else
+# define Q_HAS_TRACEPOINTS 0
# define Q_TRACE(x, ...)
# define Q_TRACE_EXIT(x, ...)
# define Q_TRACE_SCOPE(x, ...)
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 4f79c48c51..30be47296e 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -49,6 +49,26 @@ QT_BEGIN_NAMESPACE
QTypeInfo - type trait functionality
*/
+template <typename T>
+static constexpr bool qIsRelocatable()
+{
+#if defined(Q_CC_CLANG) || !defined(Q_CC_GNU) || Q_CC_GNU >= 501
+ return std::is_trivially_copyable<T>::value && std::is_trivially_destructible<T>::value;
+#else
+ return std::is_enum<T>::value || std::is_integral<T>::value;
+#endif
+}
+
+template <typename T>
+static constexpr bool qIsTrivial()
+{
+#if defined(Q_CC_CLANG) || !defined(Q_CC_GNU) || Q_CC_GNU >= 501
+ return std::is_trivial<T>::value;
+#else
+ return std::is_enum<T>::value || std::is_integral<T>::value;
+#endif
+}
+
/*
The catch-all template.
*/
@@ -61,9 +81,9 @@ public:
isSpecialized = std::is_enum<T>::value, // don't require every enum to be marked manually
isPointer = false,
isIntegral = std::is_integral<T>::value,
- isComplex = !isIntegral && !std::is_enum<T>::value,
+ isComplex = !qIsTrivial<T>(),
isStatic = true,
- isRelocatable = std::is_enum<T>::value,
+ isRelocatable = qIsRelocatable<T>(),
isLarge = (sizeof(T)>sizeof(void*)),
isDummy = false, //### Qt6: remove
sizeOf = sizeof(T)
@@ -193,7 +213,6 @@ Q_DECLARE_MOVABLE_CONTAINER(QList);
Q_DECLARE_MOVABLE_CONTAINER(QVector);
Q_DECLARE_MOVABLE_CONTAINER(QQueue);
Q_DECLARE_MOVABLE_CONTAINER(QStack);
-Q_DECLARE_MOVABLE_CONTAINER(QLinkedList);
Q_DECLARE_MOVABLE_CONTAINER(QSet);
#undef Q_DECLARE_MOVABLE_CONTAINER
@@ -248,9 +267,9 @@ class QTypeInfo<TYPE > \
public: \
enum { \
isSpecialized = true, \
- isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0), \
+ isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && !qIsTrivial<TYPE>(), \
isStatic = (((FLAGS) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), \
- isRelocatable = !isStatic || ((FLAGS) & Q_RELOCATABLE_TYPE), \
+ isRelocatable = !isStatic || ((FLAGS) & Q_RELOCATABLE_TYPE) || qIsRelocatable<TYPE>(), \
isLarge = (sizeof(TYPE)>sizeof(void*)), \
isPointer = false, \
isIntegral = std::is_integral< TYPE >::value, \
@@ -288,7 +307,7 @@ Q_DECLARE_TYPEINFO_BODY(QFlags<T>, Q_PRIMITIVE_TYPE);
#define Q_DECLARE_SHARED_IMPL(TYPE, FLAGS) \
Q_DECLARE_TYPEINFO(TYPE, FLAGS); \
inline void swap(TYPE &value1, TYPE &value2) \
- Q_DECL_NOEXCEPT_EXPR(noexcept(value1.swap(value2))) \
+ noexcept(noexcept(value1.swap(value2))) \
{ value1.swap(value2); }
#define Q_DECLARE_SHARED(TYPE) Q_DECLARE_SHARED_IMPL(TYPE, Q_MOVABLE_TYPE)
#define Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(TYPE) \
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index 086d642c26..fe81689932 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -79,6 +79,8 @@ SOURCES += \
io/qloggingcategory.cpp \
io/qloggingregistry.cpp
+qtConfig(zstd): QMAKE_USE_PRIVATE += zstd
+
qtConfig(filesystemwatcher) {
HEADERS += \
io/qfilesystemwatcher.h \
@@ -156,7 +158,8 @@ win32 {
io/qwindowspipereader.cpp \
io/qwindowspipewriter.cpp
- LIBS += -lmpr -lnetapi32 -luserenv
+ LIBS += -lmpr -luserenv
+ QMAKE_USE_PRIVATE += netapi32
} else {
SOURCES += \
io/qstandardpaths_winrt.cpp \
@@ -169,7 +172,7 @@ win32 {
io/qlockfile_unix.cpp \
io/qfilesystemiterator_unix.cpp
- !integrity:!uikit {
+ !integrity:!uikit:!rtems {
SOURCES += io/forkfd_qt.cpp
HEADERS += \
../3rdparty/forkfd/forkfd.h
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index f2a895bbb8..8a1679c5af 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -159,7 +159,7 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
*/
QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path)
{
- QAbstractFileEngine *engine = 0;
+ QAbstractFileEngine *engine = nullptr;
if (qt_file_engine_handlers_in_use) {
QReadLocker locker(fileEngineHandlerMutex());
@@ -658,7 +658,7 @@ QStringList QAbstractFileEngine::entryList(QDir::Filters filters, const QStringL
QAbstractFileEngine::FileFlags QAbstractFileEngine::fileFlags(FileFlags type) const
{
Q_UNUSED(type);
- return 0;
+ return nullptr;
}
/*!
@@ -838,7 +838,7 @@ uchar *QAbstractFileEngine::map(qint64 offset, qint64 size, QFile::MemoryMapFlag
option.flags = flags;
MapExtensionReturn r;
if (!extension(MapExtension, &option, &r))
- return 0;
+ return nullptr;
return r.address;
}
@@ -1118,7 +1118,7 @@ QAbstractFileEngine::Iterator *QAbstractFileEngine::beginEntryList(QDir::Filters
{
Q_UNUSED(filters);
Q_UNUSED(filterNames);
- return 0;
+ return nullptr;
}
/*!
@@ -1126,7 +1126,7 @@ QAbstractFileEngine::Iterator *QAbstractFileEngine::beginEntryList(QDir::Filters
*/
QAbstractFileEngine::Iterator *QAbstractFileEngine::endEntryList()
{
- return 0;
+ return nullptr;
}
/*!
diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h
index 00c415b521..c88b66c7ce 100644
--- a/src/corelib/io/qabstractfileengine_p.h
+++ b/src/corelib/io/qabstractfileengine_p.h
@@ -193,7 +193,7 @@ public:
uchar *address;
};
- virtual bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
+ virtual bool extension(Extension extension, const ExtensionOption *option = nullptr, ExtensionReturn *output = nullptr);
virtual bool supportsExtension(Extension extension) const;
// Factory
@@ -208,7 +208,7 @@ protected:
QScopedPointer<QAbstractFileEnginePrivate> d_ptr;
private:
Q_DECLARE_PRIVATE(QAbstractFileEngine)
- Q_DISABLE_COPY(QAbstractFileEngine)
+ Q_DISABLE_COPY_MOVE(QAbstractFileEngine)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractFileEngine::FileFlags)
@@ -245,7 +245,7 @@ protected:
virtual QVariant entryInfo(EntryInfoType type) const;
private:
- Q_DISABLE_COPY(QAbstractFileEngineIterator)
+ Q_DISABLE_COPY_MOVE(QAbstractFileEngineIterator)
friend class QDirIterator;
friend class QDirIteratorPrivate;
void setPath(const QString &path);
diff --git a/src/corelib/io/qbuffer.cpp b/src/corelib/io/qbuffer.cpp
index e0b9c41323..8e980733de 100644
--- a/src/corelib/io/qbuffer.cpp
+++ b/src/corelib/io/qbuffer.cpp
@@ -50,7 +50,7 @@ class QBufferPrivate : public QIODevicePrivate
public:
QBufferPrivate()
- : buf(0)
+ : buf(nullptr)
#ifndef QT_NO_QOBJECT
, writtenSinceLastEmit(0), signalConnectionCount(0), signalsEmitted(false)
#endif
@@ -60,8 +60,8 @@ public:
QByteArray *buf;
QByteArray defaultBuf;
- virtual qint64 peek(char *data, qint64 maxSize) override;
- virtual QByteArray peek(qint64 maxSize) override;
+ qint64 peek(char *data, qint64 maxSize) override;
+ QByteArray peek(qint64 maxSize) override;
#ifndef QT_NO_QOBJECT
// private slots
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index 4d56d1a179..d13e94e096 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -147,7 +147,7 @@ using QtMiscUtils::fromHex;
// Has been defined in the header / inlined before Qt 5.4
QDebug::~QDebug()
{
- if (!--stream->ref) {
+ if (stream && !--stream->ref) {
if (stream->space && stream->buffer.endsWith(QLatin1Char(' ')))
stream->buffer.chop(1);
if (stream->message_output) {
@@ -166,7 +166,7 @@ void QDebug::putUcs4(uint ucs4)
{
maybeQuote('\'');
if (ucs4 < 0x20) {
- stream->ts << "\\x" << hex << ucs4 << reset;
+ stream->ts << "\\x" << Qt::hex << ucs4 << Qt::reset;
} else if (ucs4 < 0x80) {
stream->ts << char(ucs4);
} else {
@@ -174,7 +174,7 @@ void QDebug::putUcs4(uint ucs4)
stream->ts << "\\u" << qSetFieldWidth(4);
else
stream->ts << "\\U" << qSetFieldWidth(8);
- stream->ts << hex << qSetPadChar(QLatin1Char('0')) << ucs4 << reset;
+ stream->ts << Qt::hex << qSetPadChar(QLatin1Char('0')) << ucs4 << Qt::reset;
}
maybeQuote('\'');
}
@@ -356,7 +356,7 @@ QDebug &QDebug::resetFormat()
stream->space = true;
if (stream->context.version > 1)
stream->flags = 0;
- stream->setVerbosity(Stream::DefaultVerbosity);
+ stream->setVerbosity(DefaultVerbosity);
return *this;
}
@@ -461,7 +461,7 @@ QDebug &QDebug::resetFormat()
The allowed range is from 0 to 7. The default value is 2.
- \sa setVerbosity()
+ \sa setVerbosity(), VerbosityLevel
*/
/*!
@@ -472,7 +472,31 @@ QDebug &QDebug::resetFormat()
The allowed range is from 0 to 7. The default value is 2.
- \sa verbosity()
+ \sa verbosity(), VerbosityLevel
+*/
+
+/*!
+ \fn QDebug &QDebug::verbosity(int verbosityLevel)
+ \since 5.13
+
+ Sets the verbosity of the stream to \a verbosityLevel and returns a reference to the stream.
+
+ The allowed range is from 0 to 7. The default value is 2.
+
+ \sa verbosity(), setVerbosity(), VerbosityLevel
+*/
+
+/*!
+ \enum QDebug::VerbosityLevel
+ \since 5.13
+
+ This enum describes the range of verbosity levels.
+
+ \value MinimumVerbosity
+ \value DefaultVerbosity
+ \value MaximumVerbosity
+
+ \sa verbosity(), setVerbosity()
*/
/*!
@@ -810,7 +834,7 @@ QDebug &QDebug::resetFormat()
that QDebugStateSaver stores for the duration of the current block.
The settings of the internal QTextStream are also saved and restored,
- so that using << hex in a QDebug operator doesn't affect other QDebug
+ so that using << Qt::hex in a QDebug operator doesn't affect other QDebug
operators.
\since 5.1
@@ -819,36 +843,34 @@ QDebug &QDebug::resetFormat()
class QDebugStateSaverPrivate
{
public:
- QDebugStateSaverPrivate(QDebug &dbg)
- : m_dbg(dbg),
- m_spaces(dbg.autoInsertSpaces()),
- m_flags(0),
- m_streamParams(dbg.stream->ts.d_ptr->params)
+ QDebugStateSaverPrivate(QDebug::Stream *stream)
+ : m_stream(stream),
+ m_spaces(stream->space),
+ m_flags(stream->context.version > 1 ? stream->flags : 0),
+ m_streamParams(stream->ts.d_ptr->params)
{
- if (m_dbg.stream->context.version > 1)
- m_flags = m_dbg.stream->flags;
}
void restoreState()
{
- const bool currentSpaces = m_dbg.autoInsertSpaces();
+ const bool currentSpaces = m_stream->space;
if (currentSpaces && !m_spaces)
- if (m_dbg.stream->buffer.endsWith(QLatin1Char(' ')))
- m_dbg.stream->buffer.chop(1);
+ if (m_stream->buffer.endsWith(QLatin1Char(' ')))
+ m_stream->buffer.chop(1);
- m_dbg.setAutoInsertSpaces(m_spaces);
- m_dbg.stream->ts.d_ptr->params = m_streamParams;
- if (m_dbg.stream->context.version > 1)
- m_dbg.stream->flags = m_flags;
+ m_stream->space = m_spaces;
+ m_stream->ts.d_ptr->params = m_streamParams;
+ if (m_stream->context.version > 1)
+ m_stream->flags = m_flags;
if (!currentSpaces && m_spaces)
- m_dbg.stream->ts << ' ';
+ m_stream->ts << ' ';
}
- QDebug &m_dbg;
+ QDebug::Stream *m_stream;
// QDebug state
const bool m_spaces;
- int m_flags;
+ const int m_flags;
// QTextStream state
const QTextStreamPrivate::Params m_streamParams;
@@ -862,7 +884,7 @@ public:
\sa QDebug::setAutoInsertSpaces(), QDebug::autoInsertSpaces()
*/
QDebugStateSaver::QDebugStateSaver(QDebug &dbg)
- : d(new QDebugStateSaverPrivate(dbg))
+ : d(new QDebugStateSaverPrivate(dbg.stream))
{
}
@@ -892,37 +914,127 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value)
#ifndef QT_NO_QOBJECT
/*!
+ \fn QDebug qt_QMetaEnum_debugOperator(QDebug &, int value, const QMetaObject *, const char *name)
\internal
+
+ Formats the given enum \a value for debug output.
+
+ The supported verbosity are:
+
+ 0: Just the key, or value with enum name if no key is found:
+
+ MyEnum2
+ MyEnum(123)
+ MyScopedEnum::Enum3
+ MyScopedEnum(456)
+
+ 1: Same as 0, but treating all enums as scoped:
+
+ MyEnum::MyEnum2
+ MyEnum(123)
+ MyScopedEnum::Enum3
+ MyScopedEnum(456)
+
+ 2: The QDebug default. Same as 0, and includes class/namespace scope:
+
+ MyNamespace::MyClass::MyEnum2
+ MyNamespace::MyClass::MyEnum(123)
+ MyNamespace::MyClass::MyScopedEnum::Enum3
+ MyNamespace::MyClass::MyScopedEnum(456)
+
+ 3: Same as 2, but treating all enums as scoped:
+
+ MyNamespace::MyClass::MyEnum::MyEnum2
+ MyNamespace::MyClass::MyEnum(123)
+ MyNamespace::MyClass::MyScopedEnum::Enum3
+ MyNamespace::MyClass::MyScopedEnum(456)
*/
QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, int value, const QMetaObject *meta, const char *name)
{
QDebugStateSaver saver(dbg);
dbg.nospace();
QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
- const char *key = me.valueToKey(value);
- if (key) {
+
+ const int verbosity = dbg.verbosity();
+ if (verbosity >= QDebug::DefaultVerbosity) {
if (const char *scope = me.scope())
dbg << scope << "::";
- if (me.isScoped())
- dbg << me.enumName() << "::";
- dbg << key;
- } else {
- dbg << meta->className() << "::" << name << "(" << value << ")";
}
+
+ const char *key = me.valueToKey(value);
+ const bool scoped = me.isScoped() || verbosity & 1;
+ if (scoped || !key)
+ dbg << me.enumName() << (!key ? "(" : "::");
+
+ if (key)
+ dbg << key;
+ else
+ dbg << value << ")";
+
return dbg;
}
+/*!
+ \fn QDebug qt_QMetaEnum_flagDebugOperator(QDebug &, quint64 value, const QMetaObject *, const char *name)
+ \internal
+
+ Formats the given flag \a value for debug output.
+
+ The supported verbosity are:
+
+ 0: Just the key(s):
+
+ MyFlag1
+ MyFlag2|MyFlag3
+ MyScopedFlag(MyFlag2)
+ MyScopedFlag(MyFlag2|MyFlag3)
+
+ 1: Same as 0, but treating all flags as scoped:
+
+ MyFlag(MyFlag1)
+ MyFlag(MyFlag2|MyFlag3)
+ MyScopedFlag(MyFlag2)
+ MyScopedFlag(MyFlag2|MyFlag3)
+
+ 2: The QDebug default. Same as 1, and includes class/namespace scope:
+
+ QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1)
+ QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)
+ QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)
+ QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3)
+ */
QDebug qt_QMetaEnum_flagDebugOperator(QDebug &debug, quint64 value, const QMetaObject *meta, const char *name)
{
+ const int verbosity = debug.verbosity();
+
QDebugStateSaver saver(debug);
debug.resetFormat();
debug.noquote();
debug.nospace();
- debug << "QFlags<";
+
const QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
- if (const char *scope = me.scope())
- debug << scope << "::";
- debug << me.enumName() << ">(" << me.valueToKeys(value) << ')';
+
+ const bool classScope = verbosity >= QDebug::DefaultVerbosity;
+ if (classScope) {
+ debug << "QFlags<";
+
+ if (const char *scope = me.scope())
+ debug << scope << "::";
+ }
+
+ const bool enumScope = me.isScoped() || verbosity > QDebug::MinimumVerbosity;
+ if (enumScope) {
+ debug << me.enumName();
+ if (classScope)
+ debug << ">";
+ debug << "(";
+ }
+
+ debug << me.valueToKeys(value);
+
+ if (enumScope)
+ debug << ')';
+
return debug;
}
#endif // !QT_NO_QOBJECT
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 9d1ce51da5..421c5d933b 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -65,9 +65,10 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QDebug
{
friend class QMessageLogger;
+ friend class QDebugStateSaver;
friend class QDebugStateSaverPrivate;
struct Stream {
- enum { DefaultVerbosity = 2, VerbosityShift = 29, VerbosityMask = 0x7 };
+ enum { VerbosityShift = 29, VerbosityMask = 0x7 };
Stream(QIODevice *device) : ts(device), ref(1), type(QtDebugMsg),
space(true), message_output(false), flags(DefaultVerbosity << VerbosityShift) {}
@@ -92,7 +93,7 @@ class Q_CORE_EXPORT QDebug
void setFlag(FormatFlag flag) { if (context.version > 1) { flags |= flag; } }
void unsetFlag(FormatFlag flag) { if (context.version > 1) { flags &= ~flag; } }
int verbosity() const
- { return context.version > 1 ? (flags >> VerbosityShift) & VerbosityMask : int(Stream::DefaultVerbosity); }
+ { return context.version > 1 ? (flags >> VerbosityShift) & VerbosityMask : int(DefaultVerbosity); }
void setVerbosity(int v)
{
if (context.version > 1) {
@@ -114,17 +115,22 @@ public:
inline QDebug(QString *string) : stream(new Stream(string)) {}
inline QDebug(QtMsgType t) : stream(new Stream(t)) {}
inline QDebug(const QDebug &o):stream(o.stream) { ++stream->ref; }
+ QDebug(QDebug &&other) noexcept : stream{qExchange(other.stream, nullptr)} {}
inline QDebug &operator=(const QDebug &other);
+ QDebug &operator=(QDebug &&other) noexcept
+ { QDebug{std::move(other)}.swap(*this); return *this; }
~QDebug();
- inline void swap(QDebug &other) Q_DECL_NOTHROW { qSwap(stream, other.stream); }
+ inline void swap(QDebug &other) noexcept { qSwap(stream, other.stream); }
QDebug &resetFormat();
inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; }
inline QDebug &nospace() { stream->space = false; return *this; }
inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
+ inline QDebug &verbosity(int verbosityLevel) { setVerbosity(verbosityLevel); return *this; }
int verbosity() const { return stream->verbosity(); }
void setVerbosity(int verbosityLevel) { stream->setVerbosity(verbosityLevel); }
+ enum VerbosityLevel { MinimumVerbosity = 0, DefaultVerbosity = 2, MaximumVerbosity = 7 };
bool autoInsertSpaces() const { return stream->space; }
void setAutoInsertSpaces(bool b) { stream->space = b; }
@@ -159,9 +165,7 @@ public:
inline QDebug &operator<<(QLatin1String t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
inline QDebug &operator<<(const QByteArray & t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
-#ifdef Q_COMPILER_NULLPTR
inline QDebug &operator<<(std::nullptr_t) { stream->ts << "(nullptr)"; return maybeSpace(); }
-#endif
inline QDebug &operator<<(QTextStreamFunction f) {
stream->ts << f;
return *this;
@@ -195,6 +199,7 @@ public:
inline QNoDebug &quote() { return *this; }
inline QNoDebug &noquote() { return *this; }
inline QNoDebug &maybeQuote(const char = '"') { return *this; }
+ inline QNoDebug &verbosity(int) { return *this; }
template<typename T>
inline QNoDebug &operator<<(const T &) { return *this; }
@@ -202,10 +207,7 @@ public:
inline QDebug &QDebug::operator=(const QDebug &other)
{
- if (this != &other) {
- QDebug copy(other);
- qSwap(stream, copy.stream);
- }
+ QDebug{other}.swap(*this);
return *this;
}
@@ -349,7 +351,7 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
{
const QDebugStateSaver saver(debug);
debug.resetFormat();
- debug.nospace() << "QFlags(" << hex << showbase;
+ debug.nospace() << "QFlags(" << Qt::hex << Qt::showbase;
bool needSeparator = false;
for (uint i = 0; i < sizeofT * 8; ++i) {
if (value & (Int(1) << i)) {
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index f7778943c9..62dae3577c 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -1069,6 +1069,7 @@ void QDir::setNameFilters(const QStringList &nameFilters)
d->nameFilters = nameFilters;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -1083,11 +1084,15 @@ void QDir::setNameFilters(const QStringList &nameFilters)
void QDir::addResourceSearchPath(const QString &path)
{
#ifdef QT_BUILD_CORE_LIB
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QResource::addSearchPath(path);
+QT_WARNING_POP
#else
Q_UNUSED(path)
#endif
}
+#endif
#ifdef QT_BUILD_CORE_LIB
/*!
@@ -1426,7 +1431,7 @@ QStringList QDir::entryList(const QStringList &nameFilters, Filters filters,
l.append(it.fileInfo());
}
QStringList ret;
- d->sortFileList(sort, l, &ret, 0);
+ d->sortFileList(sort, l, &ret, nullptr);
return ret;
}
@@ -1468,7 +1473,7 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter
l.append(it.fileInfo());
}
QFileInfoList ret;
- d->sortFileList(sort, l, 0, &ret);
+ d->sortFileList(sort, l, nullptr, &ret);
return ret;
}
@@ -1815,6 +1820,7 @@ QDir &QDir::operator=(const QDir &dir)
return *this;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\overload
\obsolete
@@ -1828,6 +1834,7 @@ QDir &QDir::operator=(const QString &path)
d_ptr->setPath(path);
return *this;
}
+#endif
/*!
\fn void QDir::swap(QDir &other)
diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h
index 45c59d9e1d..45a40995f8 100644
--- a/src/corelib/io/qdir.h
+++ b/src/corelib/io/qdir.h
@@ -105,12 +105,13 @@ public:
~QDir();
QDir &operator=(const QDir &);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QDir::setPath() instead")
QDir &operator=(const QString &path);
-#ifdef Q_COMPILER_RVALUE_REFS
- QDir &operator=(QDir &&other) Q_DECL_NOTHROW { swap(other); return *this; }
#endif
+ QDir &operator=(QDir &&other) noexcept { swap(other); return *this; }
- void swap(QDir &other) Q_DECL_NOTHROW
+ void swap(QDir &other) noexcept
{ qSwap(d_ptr, other.d_ptr); }
void setPath(const QString &path);
@@ -118,7 +119,10 @@ public:
QString absolutePath() const;
QString canonicalPath() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QDir::addSearchPath() instead")
static void addResourceSearchPath(const QString &path);
+#endif
static void setSearchPaths(const QString &prefix, const QStringList &searchPaths);
static void addSearchPath(const QString &prefix, const QString &path);
@@ -184,7 +188,7 @@ public:
static QFileInfoList drives();
- Q_DECL_CONSTEXPR static inline QChar listSeparator() Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR static inline QChar listSeparator() noexcept
{
#if defined(Q_OS_WIN)
return QLatin1Char(';');
diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp
index ccde9745bf..21214ee273 100644
--- a/src/corelib/io/qdiriterator.cpp
+++ b/src/corelib/io/qdiriterator.cpp
@@ -93,6 +93,7 @@
#include "qdir_p.h"
#include "qabstractfileengine_p.h"
+#include <QtCore/qregexp.h>
#include <QtCore/qset.h>
#include <QtCore/qstack.h>
#include <QtCore/qvariant.h>
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 1fb9af576c..9f9a9e3040 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -61,6 +61,13 @@
QT_BEGIN_NAMESPACE
+Q_DECL_COLD_FUNCTION
+static bool file_already_open(QFile &file, const char *where = nullptr)
+{
+ qWarning("QFile::%s: File (%ls) already open", where ? where : "open", qUtf16Printable(file.fileName()));
+ return false;
+}
+
//************* QFilePrivate
QFilePrivate::QFilePrivate()
{
@@ -79,7 +86,7 @@ QFilePrivate::openExternalFile(int flags, int fd, QFile::FileHandleFlags handleF
return false;
#else
delete fileEngine;
- fileEngine = 0;
+ fileEngine = nullptr;
QFSFileEngine *fe = new QFSFileEngine;
fileEngine = fe;
return fe->open(QIODevice::OpenMode(flags), fd, handleFlags);
@@ -95,7 +102,7 @@ QFilePrivate::openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handl
return false;
#else
delete fileEngine;
- fileEngine = 0;
+ fileEngine = nullptr;
QFSFileEngine *fe = new QFSFileEngine;
fileEngine = fe;
return fe->open(QIODevice::OpenMode(flags), fh, handleFlags);
@@ -324,13 +331,12 @@ QFile::setFileName(const QString &name)
{
Q_D(QFile);
if (isOpen()) {
- qWarning("QFile::setFileName: File (%s) is already opened",
- qPrintable(fileName()));
+ file_already_open(*this, "setFileName");
close();
}
if(d->fileEngine) { //get a new file engine later
delete d->fileEngine;
- d->fileEngine = 0;
+ d->fileEngine = nullptr;
}
d->fileName = name;
}
@@ -454,7 +460,13 @@ QFile::exists(const QString &fileName)
\sa fileName(), setFileName()
*/
+QString QFile::symLinkTarget() const
+{
+ Q_D(const QFile);
+ return d->engine()->fileName(QAbstractFileEngine::LinkName);
+}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -463,9 +475,9 @@ QFile::exists(const QString &fileName)
QString
QFile::readLink() const
{
- Q_D(const QFile);
- return d->engine()->fileName(QAbstractFileEngine::LinkName);
+ return symLinkTarget();
}
+#endif
/*!
\fn static QString QFile::symLinkTarget(const QString &fileName)
@@ -478,7 +490,12 @@ QFile::readLink() const
This name may not represent an existing file; it is only a string.
QFile::exists() returns \c true if the symlink points to an existing file.
*/
+QString QFile::symLinkTarget(const QString &fileName)
+{
+ return QFileInfo(fileName).symLinkTarget();
+}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -487,8 +504,9 @@ QFile::readLink() const
QString
QFile::readLink(const QString &fileName)
{
- return QFileInfo(fileName).readLink();
+ return symLinkTarget(fileName);
}
+#endif
/*!
Removes the file specified by fileName(). Returns \c true if successful;
@@ -792,7 +810,7 @@ QFile::copy(const QString &newName)
error = true;
d->setError(QFile::CopyError, tr("Cannot open %1 for input").arg(d->fileName));
} else {
- QString fileTemplate = QLatin1String("%1/qt_temp.XXXXXX");
+ const auto fileTemplate = QLatin1String("%1/qt_temp.XXXXXX");
#ifdef QT_NO_TEMPORARYFILE
QFile out(fileTemplate.arg(QFileInfo(newName).path()));
if (!out.open(QIODevice::ReadWrite))
@@ -808,7 +826,7 @@ QFile::copy(const QString &newName)
if (error) {
out.close();
close();
- d->setError(QFile::CopyError, tr("Cannot open for output"));
+ d->setError(QFile::CopyError, tr("Cannot open for output: %1").arg(out.errorString()));
} else {
if (!d->engine()->cloneTo(out.d_func()->engine())) {
char block[4096];
@@ -898,10 +916,8 @@ QFile::copy(const QString &fileName, const QString &newName)
bool QFile::open(OpenMode mode)
{
Q_D(QFile);
- if (isOpen()) {
- qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
- return false;
- }
+ if (isOpen())
+ return file_already_open(*this);
// Either Append or NewOnly implies WriteOnly
if (mode & (Append | NewOnly))
mode |= WriteOnly;
@@ -970,10 +986,8 @@ bool QFile::open(OpenMode mode)
bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
{
Q_D(QFile);
- if (isOpen()) {
- qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
- return false;
- }
+ if (isOpen())
+ return file_already_open(*this);
// Either Append or NewOnly implies WriteOnly
if (mode & (Append | NewOnly))
mode |= WriteOnly;
@@ -1029,10 +1043,8 @@ bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
{
Q_D(QFile);
- if (isOpen()) {
- qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
- return false;
- }
+ if (isOpen())
+ return file_already_open(*this);
// Either Append or NewOnly implies WriteOnly
if (mode & (Append | NewOnly))
mode |= WriteOnly;
diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h
index e6f3d942fe..cf1465ec70 100644
--- a/src/corelib/io/qfile.h
+++ b/src/corelib/io/qfile.h
@@ -107,10 +107,14 @@ public:
bool exists() const;
static bool exists(const QString &fileName);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QFile::symLinkTarget() instead")
QString readLink() const;
+ QT_DEPRECATED_X("Use QFile::symLinkTarget(QString) instead")
static QString readLink(const QString &fileName);
- inline QString symLinkTarget() const { return readLink(); }
- inline static QString symLinkTarget(const QString &fileName) { return readLink(fileName); }
+#endif
+ QString symLinkTarget() const;
+ static QString symLinkTarget(const QString &fileName);
bool remove();
static bool remove(const QString &fileName);
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
index 2f99775c65..2f74547054 100644
--- a/src/corelib/io/qfiledevice.cpp
+++ b/src/corelib/io/qfiledevice.cpp
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
#endif
QFileDevicePrivate::QFileDevicePrivate()
- : fileEngine(0),
+ : fileEngine(nullptr),
cachedSize(0),
error(QFile::NoError), lastWasWrite(false)
{
@@ -63,7 +63,7 @@ QFileDevicePrivate::QFileDevicePrivate()
QFileDevicePrivate::~QFileDevicePrivate()
{
delete fileEngine;
- fileEngine = 0;
+ fileEngine = nullptr;
}
QAbstractFileEngine * QFileDevicePrivate::engine() const
@@ -700,7 +700,7 @@ bool QFileDevice::setPermissions(Permissions permissions)
Any mapping options can be passed through \a flags.
- Returns a pointer to the memory or 0 if there is an error.
+ Returns a pointer to the memory or \nullptr if there is an error.
\sa unmap()
*/
@@ -711,11 +711,11 @@ uchar *QFileDevice::map(qint64 offset, qint64 size, MemoryMapFlags flags)
&& d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) {
unsetError();
uchar *address = d->fileEngine->map(offset, size, flags);
- if (address == 0)
+ if (address == nullptr)
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
return address;
}
- return 0;
+ return nullptr;
}
/*!
diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h
index af41bec2f6..2d524193c5 100644
--- a/src/corelib/io/qfiledevice.h
+++ b/src/corelib/io/qfiledevice.h
@@ -100,7 +100,7 @@ public:
FileError error() const;
void unsetError();
- virtual void close() override;
+ void close() override;
bool isSequential() const override;
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 185e061d8f..f5b398feae 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -52,7 +52,7 @@ QString QFileInfoPrivate::getFileName(QAbstractFileEngine::FileName name) const
return fileNames[(int)name];
QString ret;
- if (fileEngine == 0) { // local file; use the QFileSystemEngine directly
+ if (fileEngine == nullptr) { // local file; use the QFileSystemEngine directly
switch (name) {
case QAbstractFileEngine::CanonicalName:
case QAbstractFileEngine::CanonicalPathName: {
@@ -103,7 +103,7 @@ QString QFileInfoPrivate::getFileOwner(QAbstractFileEngine::FileOwner own) const
if (cache_enabled && !fileOwners[(int)own].isNull())
return fileOwners[(int)own];
QString ret;
- if (fileEngine == 0) {
+ if (fileEngine == nullptr) {
switch (own) {
case QAbstractFileEngine::OwnerUser:
ret = QFileSystemEngine::resolveUserName(fileEntry, metaData);
@@ -134,7 +134,7 @@ uint QFileInfoPrivate::getFileFlags(QAbstractFileEngine::FileFlags request) cons
// extra syscall. Bundle detecton on Mac can be slow, expecially on network
// paths, so we separate out that as well.
- QAbstractFileEngine::FileFlags req = 0;
+ QAbstractFileEngine::FileFlags req = nullptr;
uint cachedFlags = 0;
if (request & (QAbstractFileEngine::FlagsMask | QAbstractFileEngine::TypesMask)) {
@@ -434,7 +434,7 @@ bool QFileInfo::operator==(const QFileInfo &fileinfo) const
return true;
Qt::CaseSensitivity sensitive;
- if (d->fileEngine == 0 || fileinfo.d_ptr->fileEngine == 0) {
+ if (d->fileEngine == nullptr || fileinfo.d_ptr->fileEngine == nullptr) {
if (d->fileEngine != fileinfo.d_ptr->fileEngine) // one is native, the other is a custom file-engine
return false;
@@ -649,7 +649,7 @@ bool QFileInfo::isRelative() const
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
return true;
- if (d->fileEngine == 0)
+ if (d->fileEngine == nullptr)
return d->fileEntry.isRelative();
return d->fileEngine->isRelativePath();
}
@@ -682,7 +682,7 @@ bool QFileInfo::exists() const
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
return false;
- if (d->fileEngine == 0) {
+ if (d->fileEngine == nullptr) {
if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::ExistsAttribute))
QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::ExistsAttribute);
return d->metaData.exists();
@@ -982,7 +982,7 @@ bool QFileInfo::isNativePath() const
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
return false;
- if (d->fileEngine == 0)
+ if (d->fileEngine == nullptr)
return true;
return d->getFileFlags(QAbstractFileEngine::LocalDiskFlag);
}
@@ -1075,7 +1075,7 @@ bool QFileInfo::isRoot() const
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
return false;
- if (d->fileEngine == 0) {
+ if (d->fileEngine == nullptr) {
if (d->fileEntry.isRoot()) {
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
//the path is a drive root, but the drive may not exist
@@ -1107,6 +1107,7 @@ bool QFileInfo::isRoot() const
\sa exists(), isSymLink(), isDir(), isFile()
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -1114,6 +1115,12 @@ bool QFileInfo::isRoot() const
*/
QString QFileInfo::readLink() const
{
+ return symLinkTarget();
+}
+#endif
+
+QString QFileInfo::symLinkTarget() const
+{
Q_D(const QFileInfo);
if (d->isDefaultConstructed)
return QLatin1String("");
diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h
index f295a86015..111517325d 100644
--- a/src/corelib/io/qfileinfo.h
+++ b/src/corelib/io/qfileinfo.h
@@ -67,11 +67,9 @@ public:
~QFileInfo();
QFileInfo &operator=(const QFileInfo &fileinfo);
-#ifdef Q_COMPILER_RVALUE_REFS
- QFileInfo &operator=(QFileInfo &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QFileInfo &operator=(QFileInfo &&other) noexcept { swap(other); return *this; }
- void swap(QFileInfo &other) Q_DECL_NOTHROW
+ void swap(QFileInfo &other) noexcept
{ qSwap(d_ptr, other.d_ptr); }
bool operator==(const QFileInfo &fileinfo) const;
@@ -116,8 +114,11 @@ public:
bool isRoot() const;
bool isBundle() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QFileInfo::symLinkTarget() instead")
QString readLink() const;
- inline QString symLinkTarget() const { return readLink(); }
+#endif
+ QString symLinkTarget() const;
QString owner() const;
uint ownerId() const;
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
index e4b28f4519..36f440812f 100644
--- a/src/corelib/io/qfileinfo_p.h
+++ b/src/corelib/io/qfileinfo_p.h
@@ -80,7 +80,7 @@ public:
};
inline QFileInfoPrivate()
- : QSharedData(), fileEngine(0),
+ : QSharedData(), fileEngine(nullptr),
cachedFlags(0),
isDefaultConstructed(true),
cache_enabled(true), fileFlags(0), fileSize(0)
diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp
index 7abdf90bf5..21847c2a7c 100644
--- a/src/corelib/io/qfilesystemengine.cpp
+++ b/src/corelib/io/qfilesystemengine.cpp
@@ -124,7 +124,7 @@ static inline bool _q_checkEntry(QAbstractFileEngine *&engine, bool resolvingEnt
if (resolvingEntry) {
if (!(engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) {
delete engine;
- engine = 0;
+ engine = nullptr;
return false;
}
}
@@ -191,7 +191,7 @@ static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &ent
QAbstractFileEngine *QFileSystemEngine::resolveEntryAndCreateLegacyEngine(
QFileSystemEntry &entry, QFileSystemMetaData &data) {
QFileSystemEntry copy = entry;
- QAbstractFileEngine *engine = 0;
+ QAbstractFileEngine *engine = nullptr;
if (_q_resolveEntryAndCreateLegacyEngine_recursive(copy, data, engine))
// Reset entry to resolved copy.
diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h
index 09ec2d6a10..e44837747c 100644
--- a/src/corelib/io/qfilesystemengine_p.h
+++ b/src/corelib/io/qfilesystemengine_p.h
@@ -130,7 +130,7 @@ public:
static bool removeFile(const QFileSystemEntry &entry, QSystemError &error);
static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error,
- QFileSystemMetaData *data = 0);
+ QFileSystemMetaData *data = nullptr);
// unused, therefore not implemented
static bool setFileTime(const QFileSystemEntry &entry, const QDateTime &newDate,
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 5bab897d43..066a7c3f01 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -695,52 +695,36 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
Q_UNUSED(data);
return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
#else
- char *ret = 0;
-# if defined(Q_OS_DARWIN)
- ret = (char*)malloc(PATH_MAX + 1);
- if (ret && realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
- const int savedErrno = errno; // errno is checked below, and free() might change it
- free(ret);
- errno = savedErrno;
- ret = 0;
- }
-# elif defined(Q_OS_ANDROID)
- // On some Android versions, realpath() will return a path even if it does not exist
- // To work around this, we check existence in advance.
+ char stack_result[PATH_MAX+1];
+ char *resolved_name = nullptr;
+# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID)
+ // On some Android and macOS versions, realpath() will return a path even if
+ // it does not exist. To work around this, we check existence in advance.
if (!data.hasFlags(QFileSystemMetaData::ExistsAttribute))
fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute);
if (!data.exists()) {
- ret = 0;
errno = ENOENT;
} else {
- ret = (char*)malloc(PATH_MAX + 1);
- if (realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
- const int savedErrno = errno; // errno is checked below, and free() might change it
- free(ret);
- errno = savedErrno;
- ret = 0;
- }
+ resolved_name = stack_result;
}
-
+ if (resolved_name && realpath(entry.nativeFilePath().constData(), resolved_name) == nullptr)
+ resolved_name = nullptr;
# else
-# if _POSIX_VERSION >= 200801L
- ret = realpath(entry.nativeFilePath().constData(), (char*)0);
+# if _POSIX_VERSION >= 200801L // ask realpath to allocate memory
+ resolved_name = realpath(entry.nativeFilePath().constData(), nullptr);
# else
- ret = (char*)malloc(PATH_MAX + 1);
- if (realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
- const int savedErrno = errno; // errno is checked below, and free() might change it
- free(ret);
- errno = savedErrno;
- ret = 0;
- }
+ resolved_name = stack_result;
+ if (realpath(entry.nativeFilePath().constData(), resolved_name) == nullptr)
+ resolved_name = nullptr;
# endif
# endif
- if (ret) {
+ if (resolved_name) {
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
- QString canonicalPath = QDir::cleanPath(QFile::decodeName(ret));
- free(ret);
+ QString canonicalPath = QDir::cleanPath(QFile::decodeName(resolved_name));
+ if (resolved_name != stack_result)
+ free(resolved_name);
return QFileSystemEntry(canonicalPath);
} else if (errno == ENOENT || errno == ENOTDIR) { // file doesn't exist
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
@@ -829,7 +813,7 @@ QString QFileSystemEngine::resolveUserName(uint userId)
#endif
#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_WASM)
- struct passwd *pw = 0;
+ struct passwd *pw = nullptr;
#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS)
struct passwd entry;
getpwuid_r(userId, &entry, buf.data(), buf.size(), &pw);
@@ -853,7 +837,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId)
#endif
#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_WASM)
- struct group *gr = 0;
+ struct group *gr = nullptr;
#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID) && (__ANDROID_API__ >= 24))
size_max = sysconf(_SC_GETGR_R_SIZE_MAX);
if (size_max == -1)
diff --git a/src/corelib/io/qfilesystemiterator_p.h b/src/corelib/io/qfilesystemiterator_p.h
index 081487e66e..5e4e424e69 100644
--- a/src/corelib/io/qfilesystemiterator_p.h
+++ b/src/corelib/io/qfilesystemiterator_p.h
@@ -96,7 +96,7 @@ private:
int lastError;
#endif
- Q_DISABLE_COPY(QFileSystemIterator)
+ Q_DISABLE_COPY_MOVE(QFileSystemIterator)
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp
index a9acf542d4..5ac7e13a2e 100644
--- a/src/corelib/io/qfilesystemiterator_unix.cpp
+++ b/src/corelib/io/qfilesystemiterator_unix.cpp
@@ -50,15 +50,15 @@ QT_BEGIN_NAMESPACE
QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
const QStringList &nameFilters, QDirIterator::IteratorFlags flags)
: nativePath(entry.nativeFilePath())
- , dir(0)
- , dirEntry(0)
+ , dir(nullptr)
+ , dirEntry(nullptr)
, lastError(0)
{
Q_UNUSED(filters)
Q_UNUSED(nameFilters)
Q_UNUSED(flags)
- if ((dir = QT_OPENDIR(nativePath.constData())) == 0) {
+ if ((dir = QT_OPENDIR(nativePath.constData())) == nullptr) {
lastError = errno;
} else {
if (!nativePath.endsWith('/'))
diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h
index 4d2a5acb9b..81f4b3ba13 100644
--- a/src/corelib/io/qfilesystemmetadata_p.h
+++ b/src/corelib/io/qfilesystemmetadata_p.h
@@ -76,7 +76,7 @@ class Q_AUTOTEST_EXPORT QFileSystemMetaData
{
public:
QFileSystemMetaData()
- : knownFlagsMask(0),
+ : knownFlagsMask(nullptr),
size_(-1)
{
}
@@ -184,7 +184,7 @@ public:
void clear()
{
- knownFlagsMask = 0;
+ knownFlagsMask = nullptr;
}
void clearFlags(MetaDataFlags flags = AllMetaDataFlags)
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index f40e166d9f..e3e4433a6b 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -311,6 +311,17 @@ bool QFileSystemWatcher::addPath(const QString &path)
return paths.isEmpty();
}
+static QStringList empty_paths_pruned(const QStringList &paths)
+{
+ QStringList p;
+ p.reserve(paths.size());
+ const auto isEmpty = [](const QString &s) { return s.isEmpty(); };
+ std::remove_copy_if(paths.begin(), paths.end(),
+ std::back_inserter(p),
+ isEmpty);
+ return p;
+}
+
/*!
Adds each path in \a paths to the file system watcher. Paths are
not added if they not exist, or if they are already being
@@ -338,47 +349,41 @@ QStringList QFileSystemWatcher::addPaths(const QStringList &paths)
{
Q_D(QFileSystemWatcher);
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
-
- while (it.hasNext()) {
- const QString &path = it.next();
- if (path.isEmpty())
- it.remove();
- }
+ QStringList p = empty_paths_pruned(paths);
if (p.isEmpty()) {
qWarning("QFileSystemWatcher::addPaths: list is empty");
- return QStringList();
+ return p;
}
- QFileSystemWatcherEngine *engine = 0;
-
- const QString on = objectName();
-
- if (!on.startsWith(QLatin1String("_qt_autotest_force_engine_"))) {
+ const auto selectEngine = [this, d]() -> QFileSystemWatcherEngine* {
+#ifdef QT_BUILD_INTERNAL
+ const QString on = objectName();
+
+ if (Q_UNLIKELY(on.startsWith(QLatin1String("_qt_autotest_force_engine_")))) {
+ // Autotest override case - use the explicitly selected engine only
+ const QStringRef forceName = on.midRef(26);
+ if (forceName == QLatin1String("poller")) {
+ qDebug("QFileSystemWatcher: skipping native engine, using only polling engine");
+ d_func()->initPollerEngine();
+ return d->poller;
+ } else if (forceName == QLatin1String("native")) {
+ qDebug("QFileSystemWatcher: skipping polling engine, using only native engine");
+ return d->native;
+ }
+ return nullptr;
+ }
+#endif
// Normal runtime case - search intelligently for best engine
if(d->native) {
- engine = d->native;
+ return d->native;
} else {
d_func()->initPollerEngine();
- engine = d->poller;
- }
-
- } else {
- // Autotest override case - use the explicitly selected engine only
- const QStringRef forceName = on.midRef(26);
- if(forceName == QLatin1String("poller")) {
- qDebug("QFileSystemWatcher: skipping native engine, using only polling engine");
- d_func()->initPollerEngine();
- engine = d->poller;
- } else if(forceName == QLatin1String("native")) {
- qDebug("QFileSystemWatcher: skipping polling engine, using only native engine");
- engine = d->native;
+ return d->poller;
}
- }
+ };
- if(engine)
+ if (auto engine = selectEngine())
p = engine->addPaths(p, &d->files, &d->directories);
return p;
@@ -420,18 +425,11 @@ QStringList QFileSystemWatcher::removePaths(const QStringList &paths)
{
Q_D(QFileSystemWatcher);
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
-
- while (it.hasNext()) {
- const QString &path = it.next();
- if (path.isEmpty())
- it.remove();
- }
+ QStringList p = empty_paths_pruned(paths);
if (p.isEmpty()) {
qWarning("QFileSystemWatcher::removePaths: list is empty");
- return QStringList();
+ return p;
}
if (d->native)
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm
index f594fad803..fb3b6f86fd 100644
--- a/src/corelib/io/qfilesystemwatcher_fsevents.mm
+++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm
@@ -407,7 +407,7 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
stopStream();
if (!startStream()) {
// ok, something went wrong, let's try to restore the previous state
- watchingState = qMove(oldState);
+ watchingState = std::move(oldState);
// and because we don't know which path caused the issue (if any), fail on all of them
p = paths;
@@ -474,7 +474,7 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
if (needsRestart) {
if (!restartStream()) {
- watchingState = qMove(oldState);
+ watchingState = std::move(oldState);
startStream();
}
}
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp
index a5e629b646..5fb5685f42 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -46,6 +46,7 @@
#include <qdebug.h>
#include <qfile.h>
#include <qfileinfo.h>
+#include <qscopeguard.h>
#include <qsocketnotifier.h>
#include <qvarlengtharray.h>
@@ -268,12 +269,11 @@ QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
+ QStringList unhandled;
+ for (const QString &path : paths) {
QFileInfo fi(path);
bool isDir = fi.isDir();
+ auto sg = qScopeGuard([&]{ unhandled.push_back(path); });
if (isDir) {
if (directories->contains(path))
continue;
@@ -305,7 +305,7 @@ QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths,
continue;
}
- it.remove();
+ sg.dismiss();
int id = isDir ? -wd : wd;
if (id < 0) {
@@ -318,19 +318,19 @@ QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths,
idToPath.insert(id, path);
}
- return p;
+ return unhandled;
}
QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
+ QStringList unhandled;
+ for (const QString &path : paths) {
int id = pathToID.take(path);
+ auto sg = qScopeGuard([&]{ unhandled.push_back(path); });
+
// Multiple paths could be associated to the same watch descriptor
// when a file is moved and added with the new name.
// So we should find and delete the correct one by using
@@ -349,7 +349,8 @@ QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &path
inotify_rm_watch(inotifyFd, wd);
}
- it.remove();
+ sg.dismiss();
+
if (id < 0) {
directories->removeAll(path);
} else {
@@ -357,7 +358,7 @@ QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &path
}
}
- return p;
+ return unhandled;
}
void QInotifyFileSystemWatcherEngine::readFromInotify()
@@ -388,7 +389,7 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
const inotify_event &event = **it;
++it;
- // qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask;
+ // qDebug() << "inotify event, wd" << event.wd << "mask" << Qt::hex << event.mask;
int id = event.wd;
QString path = getPathFromID(id);
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
index 423b88cb7f..c2028e3641 100644
--- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp
+++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
@@ -45,6 +45,7 @@
#include <qdebug.h>
#include <qfile.h>
+#include <qscopeguard.h>
#include <qsocketnotifier.h>
#include <qvarlengtharray.h>
@@ -94,10 +95,9 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
+ QStringList unhandled;
+ for (const QString &path : paths) {
+ auto sg = qScopeGuard([&]{unhandled.push_back(path);});
int fd;
#if defined(O_EVTONLY)
fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY);
@@ -149,7 +149,8 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
continue;
}
- it.remove();
+ sg.dismiss();
+
if (id < 0) {
DEBUG() << "QKqueueFileSystemWatcherEngine: added directory path" << path;
directories->append(path);
@@ -162,20 +163,19 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
idToPath.insert(id, path);
}
- return p;
+ return unhandled;
}
QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
- QStringList p = paths;
if (pathToID.isEmpty())
- return p;
+ return paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
+ QStringList unhandled;
+ for (const QString &path : paths) {
+ auto sg = qScopeGuard([&]{unhandled.push_back(path);});
int id = pathToID.take(path);
QString x = idToPath.take(id);
if (x.isEmpty() || x != path)
@@ -183,14 +183,15 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths
::close(id < 0 ? -id : id);
- it.remove();
+ sg.dismiss();
+
if (id < 0)
directories->removeAll(path);
else
files->removeAll(path);
}
- return p;
+ return unhandled;
}
void QKqueueFileSystemWatcherEngine::readFromKqueue()
diff --git a/src/corelib/io/qfilesystemwatcher_polling.cpp b/src/corelib/io/qfilesystemwatcher_polling.cpp
index 903c15f4a9..e07b02f7c2 100644
--- a/src/corelib/io/qfilesystemwatcher_polling.cpp
+++ b/src/corelib/io/qfilesystemwatcher_polling.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qfilesystemwatcher_polling_p.h"
+#include <QtCore/qscopeguard.h>
#include <QtCore/qtimer.h>
QT_BEGIN_NAMESPACE
@@ -53,10 +54,9 @@ QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
+ QStringList unhandled;
+ for (const QString &path : paths) {
+ auto sg = qScopeGuard([&]{ unhandled.push_back(path); });
QFileInfo fi(path);
if (!fi.exists())
continue;
@@ -73,7 +73,7 @@ QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
files->append(path);
this->files.insert(path, fi);
}
- it.remove();
+ sg.dismiss();
}
if ((!this->files.isEmpty() ||
@@ -82,23 +82,21 @@ QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
timer.start(PollingInterval);
}
- return p;
+ return unhandled;
}
QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
+ QStringList unhandled;
+ for (const QString &path : paths) {
if (this->directories.remove(path)) {
directories->removeAll(path);
- it.remove();
} else if (this->files.remove(path)) {
files->removeAll(path);
- it.remove();
+ } else {
+ unhandled.push_back(path);
}
}
@@ -107,38 +105,37 @@ QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &path
timer.stop();
}
- return p;
+ return unhandled;
}
void QPollingFileSystemWatcherEngine::timeout()
{
- QMutableHashIterator<QString, FileInfo> fit(files);
- while (fit.hasNext()) {
- QHash<QString, FileInfo>::iterator x = fit.next();
+ for (auto it = files.begin(), end = files.end(); it != end; /*erasing*/) {
+ auto x = it++;
QString path = x.key();
QFileInfo fi(path);
if (!fi.exists()) {
- fit.remove();
+ files.erase(x);
emit fileChanged(path, true);
} else if (x.value() != fi) {
x.value() = fi;
emit fileChanged(path, false);
}
}
- QMutableHashIterator<QString, FileInfo> dit(directories);
- while (dit.hasNext()) {
- QHash<QString, FileInfo>::iterator x = dit.next();
+
+ for (auto it = directories.begin(), end = directories.end(); it != end; /*erasing*/) {
+ auto x = it++;
QString path = x.key();
QFileInfo fi(path);
if (!path.endsWith(QLatin1Char('/')))
fi = QFileInfo(path + QLatin1Char('/'));
if (!fi.exists()) {
- dit.remove();
+ directories.erase(x);
emit directoryChanged(path, true);
} else if (x.value() != fi) {
fi.refresh();
if (!fi.exists()) {
- dit.remove();
+ directories.erase(x);
emit directoryChanged(path, true);
} else {
x.value() = fi;
diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp
index 66985f8982..c22a003931 100644
--- a/src/corelib/io/qfilesystemwatcher_win.cpp
+++ b/src/corelib/io/qfilesystemwatcher_win.cpp
@@ -44,6 +44,7 @@
#include <qfileinfo.h>
#include <qstringlist.h>
#include <qset.h>
+#include <qscopeguard.h>
#include <qdatetime.h>
#include <qdir.h>
#include <qtextstream.h>
@@ -79,7 +80,7 @@ static Qt::HANDLE createChangeNotification(const QString &path, uint flags)
nativePath.append(QLatin1Char('\\'));
const HANDLE result = FindFirstChangeNotification(reinterpret_cast<const wchar_t *>(nativePath.utf16()),
FALSE, flags);
- DEBUG() << __FUNCTION__ << nativePath << hex <<showbase << flags << "returns" << result;
+ DEBUG() << __FUNCTION__ << nativePath << Qt::hex <<showbase << flags << "returns" << result;
return result;
}
@@ -108,7 +109,11 @@ public:
// Call from QFileSystemWatcher::addPaths() to set up notifications on drives
void addPath(const QString &path);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool nativeEventFilter(const QByteArray &, void *messageIn, qintptr *) override;
+#else
bool nativeEventFilter(const QByteArray &, void *messageIn, long *) override;
+#endif
signals:
void driveAdded();
@@ -255,7 +260,11 @@ inline void QWindowsRemovableDriveListener::handleDbtDriveArrivalRemoval(const M
}
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QWindowsRemovableDriveListener::nativeEventFilter(const QByteArray &, void *messageIn, qintptr *)
+#else
bool QWindowsRemovableDriveListener::nativeEventFilter(const QByteArray &, void *messageIn, long *)
+#endif
{
const MSG *msg = reinterpret_cast<const MSG *>(messageIn);
if (msg->message == WM_DEVICECHANGE) {
@@ -297,8 +306,7 @@ void QWindowsRemovableDriveListener::addPath(const QString &p)
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, // Volume requires BACKUP_SEMANTICS
0);
if (volumeHandle == INVALID_HANDLE_VALUE) {
- qErrnoWarning("CreateFile %s failed.",
- qPrintable(QString::fromWCharArray(devicePath)));
+ qErrnoWarning("CreateFile %ls failed.", devicePath);
return;
}
@@ -315,8 +323,7 @@ void QWindowsRemovableDriveListener::addPath(const QString &p)
// closed. Do it here to avoid having to close/reopen in lock message handling.
CloseHandle(volumeHandle);
if (!re.devNotify) {
- qErrnoWarning("RegisterDeviceNotification %s failed.",
- qPrintable(QString::fromWCharArray(devicePath)));
+ qErrnoWarning("RegisterDeviceNotification %ls failed.", devicePath);
return;
}
@@ -369,10 +376,9 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList *directories)
{
DEBUG() << "Adding" << paths.count() << "to existing" << (files->count() + directories->count()) << "watchers";
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
+ QStringList unhandled;
+ for (const QString &path : paths) {
+ auto sg = qScopeGuard([&] { unhandled.push_back(path); });
QString normalPath = path;
if ((normalPath.endsWith(QLatin1Char('/')) && !normalPath.endsWith(QLatin1String(":/")))
|| (normalPath.endsWith(QLatin1Char('\\')) && !normalPath.endsWith(QLatin1String(":\\")))) {
@@ -424,7 +430,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
// Requesting to add a file whose directory has been added previously.
// Recreate the notification handle to add the missing notification attributes
// for files (FILE_NOTIFY_CHANGE_ATTRIBUTES...)
- DEBUG() << "recreating" << absolutePath << hex << showbase << hit.value().flags
+ DEBUG() << "recreating" << absolutePath << Qt::hex << Qt::showbase << hit.value().flags
<< "->" << flags;
const Qt::HANDLE fileHandle = createChangeNotification(absolutePath, flags);
if (fileHandle != INVALID_HANDLE_VALUE) {
@@ -455,7 +461,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
else
files->append(path);
}
- it.remove();
+ sg.dismiss();
thread->wakeup();
break;
}
@@ -485,7 +491,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
else
files->append(path);
- it.remove();
+ sg.dismiss();
found = true;
thread->wakeup();
break;
@@ -511,7 +517,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
thread->msg = '@';
thread->start();
threads.append(thread);
- it.remove();
+ sg.dismiss();
}
}
}
@@ -519,12 +525,12 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
#ifndef Q_OS_WINRT
if (Q_LIKELY(m_driveListener)) {
for (const QString &path : paths) {
- if (!p.contains(path))
+ if (!unhandled.contains(path))
m_driveListener->addPath(path);
}
}
#endif // !Q_OS_WINRT
- return p;
+ return unhandled;
}
QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &paths,
@@ -532,10 +538,9 @@ QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &path
QStringList *directories)
{
DEBUG() << "removePaths" << paths;
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
+ QStringList unhandled;
+ for (const QString &path : paths) {
+ auto sg = qScopeGuard([&] { unhandled.push_back(path); });
QString normalPath = path;
if (normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\')))
normalPath.chop(1);
@@ -564,7 +569,7 @@ QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &path
// ###
files->removeAll(path);
directories->removeAll(path);
- it.remove();
+ sg.dismiss();
if (h.isEmpty()) {
DEBUG() << "Closing handle" << handle.handle;
@@ -605,7 +610,7 @@ QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &path
}
threads.removeAll(0);
- return p;
+ return unhandled;
}
///////////
@@ -634,15 +639,15 @@ QWindowsFileSystemWatcherEngineThread::~QWindowsFileSystemWatcherEngineThread()
}
}
-static inline QString msgFindNextFailed(const QWindowsFileSystemWatcherEngineThread::PathInfoHash &pathInfos)
+Q_DECL_COLD_FUNCTION
+static QString msgFindNextFailed(const QWindowsFileSystemWatcherEngineThread::PathInfoHash &pathInfos)
{
- QString result;
- QTextStream str(&result);
- str << "QFileSystemWatcher: FindNextChangeNotification failed for";
+ QString str;
+ str += QLatin1String("QFileSystemWatcher: FindNextChangeNotification failed for");
for (const QWindowsFileSystemWatcherEngine::PathInfo &pathInfo : pathInfos)
- str << " \"" << QDir::toNativeSeparators(pathInfo.absolutePath) << '"';
- str << ' ';
- return result;
+ str += QLatin1String(" \"") + QDir::toNativeSeparators(pathInfo.absolutePath) + QLatin1Char('"');
+ str += QLatin1Char(' ');
+ return str;
}
void QWindowsFileSystemWatcherEngineThread::run()
@@ -688,11 +693,10 @@ void QWindowsFileSystemWatcherEngineThread::run()
fakeRemove = true;
}
- qErrnoWarning(error, "%s", qPrintable(msgFindNextFailed(h)));
+ qErrnoWarning(error, "%ls", qUtf16Printable(msgFindNextFailed(h)));
}
- QMutableHashIterator<QFileSystemWatcherPathKey, QWindowsFileSystemWatcherEngine::PathInfo> it(h);
- while (it.hasNext()) {
- QWindowsFileSystemWatcherEngineThread::PathInfoHash::iterator x = it.next();
+ for (auto it = h.begin(), end = h.end(); it != end; /*erasing*/ ) {
+ auto x = it++;
QString absolutePath = x.value().absolutePath;
QFileInfo fileInfo(x.value().path);
DEBUG() << "checking" << x.key();
@@ -718,6 +722,7 @@ void QWindowsFileSystemWatcherEngineThread::run()
handleForDir.remove(QFileSystemWatcherPathKey(absolutePath));
// h is now invalid
+ break;
}
} else if (x.value().isDir) {
DEBUG() << x.key() << "directory changed!";
diff --git a/src/corelib/io/qfilesystemwatcher_win_p.h b/src/corelib/io/qfilesystemwatcher_win_p.h
index 1d3224614c..272591ce7a 100644
--- a/src/corelib/io/qfilesystemwatcher_win_p.h
+++ b/src/corelib/io/qfilesystemwatcher_win_p.h
@@ -77,8 +77,8 @@ public:
explicit QWindowsFileSystemWatcherEngine(QObject *parent);
~QWindowsFileSystemWatcherEngine();
- QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
- QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
+ QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories) override;
+ QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories) override;
class Handle
{
@@ -154,7 +154,7 @@ public:
QWindowsFileSystemWatcherEngineThread();
~QWindowsFileSystemWatcherEngineThread();
- void run();
+ void run() override;
void stop();
void wakeup();
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 387990ed79..0db27f3e25 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -127,7 +127,7 @@ void QFSFileEnginePrivate::init()
is_link = 0;
openMode = QIODevice::NotOpen;
fd = -1;
- fh = 0;
+ fh = nullptr;
lastIOCommand = IOFlushCommand;
lastFlushFailed = false;
closeFileHandle = false;
@@ -240,7 +240,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode)
d->openMode = openMode;
d->lastFlushFailed = false;
d->tried_stat = 0;
- d->fh = 0;
+ d->fh = nullptr;
d->fd = -1;
return d->nativeOpen(openMode);
@@ -299,7 +299,7 @@ bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
QSystemError::stdString());
this->openMode = QIODevice::NotOpen;
- this->fh = 0;
+ this->fh = nullptr;
return false;
}
@@ -328,7 +328,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandle
d->lastFlushFailed = false;
d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
d->fileEntry.clear();
- d->fh = 0;
+ d->fh = nullptr;
d->fd = -1;
d->tried_stat = 0;
@@ -344,7 +344,7 @@ bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode, int fd)
{
Q_Q(QFSFileEngine);
this->fd = fd;
- fh = 0;
+ fh = nullptr;
// Seek to the end when in Append mode.
if (openMode & QFile::Append) {
@@ -405,7 +405,7 @@ bool QFSFileEnginePrivate::closeFdFh()
// We must reset these guys regardless; calling close again after a
// failed close causes crashes on some systems.
- fh = 0;
+ fh = nullptr;
fd = -1;
closed = (ret == 0);
}
@@ -822,7 +822,7 @@ QAbstractFileEngine::Iterator *QFSFileEngine::beginEntryList(QDir::Filters filte
*/
QAbstractFileEngine::Iterator *QFSFileEngine::endEntryList()
{
- return 0;
+ return nullptr;
}
#endif // QT_NO_FILESYSTEMITERATOR
@@ -870,7 +870,7 @@ bool QFSFileEngine::extension(Extension extension, const ExtensionOption *option
const MapExtensionOption *options = (const MapExtensionOption*)(option);
MapExtensionReturn *returnValue = static_cast<MapExtensionReturn*>(output);
returnValue->address = d->map(options->offset, options->size, options->flags);
- return (returnValue->address != 0);
+ return (returnValue->address != nullptr);
}
if (extension == UnMapExtension) {
const UnMapExtensionOption *options = (const UnMapExtensionOption*)option;
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 6b091a8eef..0f416f4886 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -115,7 +115,7 @@ public:
virtual bool isUnnamedFile() const
{ return false; }
- bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) override;
+ bool extension(Extension extension, const ExtensionOption *option = nullptr, ExtensionReturn *output = nullptr) override;
bool supportsExtension(Extension extension) const override;
//FS only!!
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 90ad0126d6..d4983c72af 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -153,7 +153,7 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
}
}
- fh = 0;
+ fh = nullptr;
}
closeFileHandle = true;
@@ -451,14 +451,14 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
if (type & Refresh)
d->metaData.clear();
- QAbstractFileEngine::FileFlags ret = 0;
+ QAbstractFileEngine::FileFlags ret = { };
if (type & FlagsMask)
ret |= LocalDiskFlag;
bool exists;
{
- QFileSystemMetaData::MetaDataFlags queryFlags = 0;
+ QFileSystemMetaData::MetaDataFlags queryFlags = { };
queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type))
& QFileSystemMetaData::Permissions;
@@ -590,9 +590,9 @@ bool QFSFileEngine::setPermissions(uint perms)
QSystemError error;
bool ok;
if (d->fd != -1)
- ok = QFileSystemEngine::setPermissions(d->fd, QFile::Permissions(perms), error, 0);
+ ok = QFileSystemEngine::setPermissions(d->fd, QFile::Permissions(perms), error);
else
- ok = QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error, 0);
+ ok = QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error);
if (!ok) {
setError(QFile::PermissionsError, error.toString());
return false;
@@ -651,13 +651,13 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
Q_Q(QFSFileEngine);
if (openMode == QIODevice::NotOpen) {
q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
- return 0;
+ return nullptr;
}
if (offset < 0 || offset > maxFileOffset
|| size < 0 || quint64(size) > quint64(size_t(-1))) {
q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
- return 0;
+ return nullptr;
}
// If we know the mapping will extend beyond EOF, fail early to avoid
@@ -685,14 +685,14 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
if (quint64(size + extra) > quint64((size_t)-1)) {
q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
- return 0;
+ return nullptr;
}
size_t realSize = (size_t)size + extra;
QT_OFF_T realOffset = QT_OFF_T(offset);
realOffset &= ~(QT_OFF_T(pageSize - 1));
- void *mapAddress = QT_MMAP((void*)0, realSize,
+ void *mapAddress = QT_MMAP((void*)nullptr, realSize,
access, sharemode, nativeHandle(), realOffset);
if (MAP_FAILED != mapAddress) {
uchar *address = extra + static_cast<uchar*>(mapAddress);
@@ -714,7 +714,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
q->setError(QFile::UnspecifiedError, qt_error_string(int(errno)));
break;
}
- return 0;
+ return nullptr;
}
bool QFSFileEnginePrivate::unmap(uchar *ptr)
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 86e21f0a66..e26508e631 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -169,7 +169,7 @@ QIODevicePrivate::QIODevicePrivate()
, baseReadLineDataCalled(false)
, accessMode(Unset)
#ifdef QT_NO_QOBJECT
- , q_ptr(0)
+ , q_ptr(nullptr)
#endif
{
}
@@ -194,7 +194,7 @@ QIODevicePrivate::~QIODevicePrivate()
QIODevice provides both a common implementation and an abstract
interface for devices that support reading and writing of blocks
of data, such as QFile, QBuffer and QTcpSocket. QIODevice is
- abstract and can not be instantiated, but it is common to use the
+ abstract and cannot be instantiated, but it is common to use the
interface it defines to provide device-independent I/O features.
For example, Qt's XML classes operate on a QIODevice pointer,
allowing them to be used with various devices (such as files and
diff --git a/src/corelib/io/qipaddress.cpp b/src/corelib/io/qipaddress.cpp
index 039e291b43..b3421fca8f 100644
--- a/src/corelib/io/qipaddress.cpp
+++ b/src/corelib/io/qipaddress.cpp
@@ -67,7 +67,7 @@ static const QChar *checkedToAscii(Buffer &buffer, const QChar *begin, const QCh
*dst++ = *src++;
}
*dst = '\0';
- return 0;
+ return nullptr;
}
static bool parseIp4Internal(IPv4Address &address, const char *ptr, bool acceptLeadingZero);
@@ -175,7 +175,7 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end
memset(address, 0, sizeof address);
if (colonCount == 2 && end - begin == 2) // "::"
- return 0;
+ return nullptr;
// if there's a double colon ("::"), this is how many zeroes it means
int zeroWordsToFill;
@@ -236,7 +236,7 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end
address[13] = ip4 >> 16;
address[14] = ip4 >> 8;
address[15] = ip4;
- return 0;
+ return nullptr;
}
address[pos++] = x >> 8;
@@ -248,15 +248,15 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end
return begin + (endptr - buffer.data());
ptr = endptr + 1;
}
- return pos == 16 ? 0 : end;
+ return pos == 16 ? nullptr : end;
}
static inline QChar toHex(uchar c)
{
- return QtMiscUtils::toHexLower(c);
+ return QChar::fromLatin1(QtMiscUtils::toHexLower(c));
}
-void toString(QString &appendTo, IPv6Address address)
+void toString(QString &appendTo, const IPv6Address address)
{
// the longest IPv6 address possible is:
// "1111:2222:3333:4444:5555:6666:255.255.255.255"
diff --git a/src/corelib/io/qipaddress_p.h b/src/corelib/io/qipaddress_p.h
index d95cccb3bd..ea31e5883d 100644
--- a/src/corelib/io/qipaddress_p.h
+++ b/src/corelib/io/qipaddress_p.h
@@ -64,7 +64,7 @@ typedef quint8 IPv6Address[16];
Q_CORE_EXPORT bool parseIp4(IPv4Address &address, const QChar *begin, const QChar *end);
Q_CORE_EXPORT const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end);
Q_CORE_EXPORT void toString(QString &appendTo, IPv4Address address);
-Q_CORE_EXPORT void toString(QString &appendTo, IPv6Address address);
+Q_CORE_EXPORT void toString(QString &appendTo, const IPv6Address address);
} // namespace
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index 418b7d22ba..b2bf77c0da 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -58,6 +58,11 @@
#include <sys/file.h> // flock
#endif
+#if defined(Q_OS_RTEMS)
+# undef LOCK_EX
+# undef LOCK_NB
+#endif
+
#include <sys/types.h> // kill
#include <signal.h> // kill
#include <unistd.h> // gethostname
@@ -169,7 +174,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) {
qt_safe_close(fd);
if (!QFile::remove(fileName))
- qWarning("QLockFile: Could not remove our own lock file %s.", qPrintable(fileName));
+ qWarning("QLockFile: Could not remove our own lock file %ls.", qUtf16Printable(fileName));
return QLockFile::UnknownError; // partition full
}
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 33253429a2..f6ff56c83c 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -214,8 +214,8 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
Note that \a category must be kept valid during the lifetime of this object.
*/
QLoggingCategory::QLoggingCategory(const char *category)
- : d(0),
- name(0)
+ : d(nullptr),
+ name(nullptr)
{
init(category, QtDebugMsg);
}
@@ -231,15 +231,15 @@ QLoggingCategory::QLoggingCategory(const char *category)
\since 5.4
*/
QLoggingCategory::QLoggingCategory(const char *category, QtMsgType enableForLevel)
- : d(0),
- name(0)
+ : d(nullptr),
+ name(nullptr)
{
init(category, enableForLevel);
}
void QLoggingCategory::init(const char *category, QtMsgType severityLevel)
{
- enabled.store(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true;
+ enabled.storeRelaxed(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true;
if (category)
name = category;
@@ -342,10 +342,10 @@ void QLoggingCategory::setEnabled(QtMsgType type, bool enable)
{
switch (type) {
#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
- case QtDebugMsg: bools.enabledDebug.store(enable); break;
- case QtInfoMsg: bools.enabledInfo.store(enable); break;
- case QtWarningMsg: bools.enabledWarning.store(enable); break;
- case QtCriticalMsg: bools.enabledCritical.store(enable); break;
+ case QtDebugMsg: bools.enabledDebug.storeRelaxed(enable); break;
+ case QtInfoMsg: bools.enabledInfo.storeRelaxed(enable); break;
+ case QtWarningMsg: bools.enabledWarning.storeRelaxed(enable); break;
+ case QtCriticalMsg: bools.enabledCritical.storeRelaxed(enable); break;
#else
case QtDebugMsg: setBoolLane(&enabled, enable, DebugShift); break;
case QtInfoMsg: setBoolLane(&enabled, enable, InfoShift); break;
diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h
index 91e3144300..1c3e10b493 100644
--- a/src/corelib/io/qloggingcategory.h
+++ b/src/corelib/io/qloggingcategory.h
@@ -58,15 +58,15 @@ public:
void setEnabled(QtMsgType type, bool enable);
#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
- bool isDebugEnabled() const { return bools.enabledDebug.load(); }
- bool isInfoEnabled() const { return bools.enabledInfo.load(); }
- bool isWarningEnabled() const { return bools.enabledWarning.load(); }
- bool isCriticalEnabled() const { return bools.enabledCritical.load(); }
+ bool isDebugEnabled() const { return bools.enabledDebug.loadRelaxed(); }
+ bool isInfoEnabled() const { return bools.enabledInfo.loadRelaxed(); }
+ bool isWarningEnabled() const { return bools.enabledWarning.loadRelaxed(); }
+ bool isCriticalEnabled() const { return bools.enabledCritical.loadRelaxed(); }
#else
- bool isDebugEnabled() const { return enabled.load() >> DebugShift & 1; }
- bool isInfoEnabled() const { return enabled.load() >> InfoShift & 1; }
- bool isWarningEnabled() const { return enabled.load() >> WarningShift & 1; }
- bool isCriticalEnabled() const { return enabled.load() >> CriticalShift & 1; }
+ bool isDebugEnabled() const { return enabled.loadRelaxed() >> DebugShift & 1; }
+ bool isInfoEnabled() const { return enabled.loadRelaxed() >> InfoShift & 1; }
+ bool isWarningEnabled() const { return enabled.loadRelaxed() >> WarningShift & 1; }
+ bool isCriticalEnabled() const { return enabled.loadRelaxed() >> CriticalShift & 1; }
#endif
const char *categoryName() const { return name; }
@@ -111,8 +111,6 @@ private:
#define Q_DECLARE_LOGGING_CATEGORY(name) \
extern const QLoggingCategory &name();
-#if defined(Q_COMPILER_VARIADIC_MACROS) || defined(Q_MOC_RUN)
-
#define Q_LOGGING_CATEGORY(name, ...) \
const QLoggingCategory &name() \
{ \
@@ -148,39 +146,6 @@ private:
for (bool qt_category_enabled = category().isCriticalEnabled(); qt_category_enabled; qt_category_enabled = false) \
QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, category().categoryName()).critical(__VA_ARGS__)
-#else // defined(Q_COMPILER_VARIADIC_MACROS) || defined(Q_MOC_RUN)
-
-// Optional msgType argument not supported
-#define Q_LOGGING_CATEGORY(name, string) \
- const QLoggingCategory &name() \
- { \
- static const QLoggingCategory category(string); \
- return category; \
- }
-
-// check for enabled category inside QMessageLogger.
-#if !defined(QT_NO_DEBUG_OUTPUT)
-# define qCDebug qDebug
-#else
-# define qCDebug(category) QT_NO_QDEBUG_MACRO()
-#endif
-
-#if !defined(QT_NO_INFO_OUTPUT)
-# define qCInfo qInfo
-#else
-# define qCInfo(category) QT_NO_QDEBUG_MACRO()
-#endif
-
-#if !defined(QT_NO_WARNING_OUTPUT)
-# define qCWarning qWarning
-#else
-# define qCWarning(category) QT_NO_QDEBUG_MACRO()
-#endif
-
-#define qCCritical qCritical
-
-#endif // Q_COMPILER_VARIADIC_MACROS || defined(Q_MOC_RUN)
-
QT_END_NAMESPACE
#endif // QLOGGINGCATEGORY_H
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index 9792d956cc..7849dfd14c 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -165,7 +165,7 @@ void QLoggingRule::parse(const QStringRef &pattern)
p = QStringRef(p.string(), p.position() + 1, p.length() - 1);
}
if (p.contains(QLatin1Char('*'))) // '*' only supported at start/end
- flags = 0;
+ flags = PatternFlags();
}
category = p.toString();
@@ -415,7 +415,7 @@ QLoggingRegistry::installFilter(QLoggingCategory::CategoryFilter filter)
{
QMutexLocker locker(&registryMutex);
- if (filter == 0)
+ if (!filter)
filter = defaultCategoryFilter;
QLoggingCategory::CategoryFilter old = categoryFilter;
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
index beca6ccbf7..d1806aa12b 100644
--- a/src/corelib/io/qnoncontiguousbytedevice.cpp
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -534,7 +534,7 @@ QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QSharedPointer
*/
QSharedPointer<QNonContiguousByteDevice> QNonContiguousByteDeviceFactory::createShared(QSharedPointer<QRingBuffer> ringBuffer)
{
- return QSharedPointer<QNonContiguousByteDeviceRingBufferImpl>::create(qMove(ringBuffer));
+ return QSharedPointer<QNonContiguousByteDeviceRingBufferImpl>::create(std::move(ringBuffer));
}
/*!
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
index ebed1120db..bbc4ea5ae2 100644
--- a/src/corelib/io/qnoncontiguousbytedevice_p.h
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -179,13 +179,13 @@ class QByteDeviceWrappingIoDevice : public QIODevice
public:
QByteDeviceWrappingIoDevice (QNonContiguousByteDevice *bd);
~QByteDeviceWrappingIoDevice ();
- virtual bool isSequential () const override;
- virtual bool atEnd () const override;
- virtual bool reset () override;
- virtual qint64 size () const override;
+ bool isSequential() const override;
+ bool atEnd() const override;
+ bool reset() override;
+ qint64 size() const override;
protected:
- virtual qint64 readData ( char * data, qint64 maxSize ) override;
- virtual qint64 writeData ( const char * data, qint64 maxSize ) override;
+ qint64 readData(char *data, qint64 maxSize) override;
+ qint64 writeData(const char *data, qint64 maxSize) override;
QNonContiguousByteDevice *byteDevice;
};
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 7b2de02d1d..0b964e6a21 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -42,6 +42,7 @@
#include <qdebug.h>
#include <qdir.h>
+#include <qscopedvaluerollback.h>
#if defined(Q_OS_WIN)
#include <qtimer.h>
#endif
@@ -814,6 +815,7 @@ void QProcessPrivate::Channel::clear()
\a newState argument is the state QProcess changed to.
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\fn void QProcess::finished(int exitCode)
\obsolete
@@ -821,6 +823,7 @@ void QProcessPrivate::Channel::clear()
Use finished(int exitCode, QProcess::ExitStatus status) instead.
*/
+#endif
/*!
\fn void QProcess::finished(int exitCode, QProcess::ExitStatus exitStatus)
@@ -996,7 +999,12 @@ void QProcessPrivate::setErrorAndEmit(QProcess::ProcessError error, const QStrin
Q_ASSERT(error != QProcess::UnknownError);
setError(error, description);
emit q->errorOccurred(processError);
+#if QT_DEPRECATED_SINCE(5, 6)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
emit q->error(processError);
+QT_WARNING_POP
+#endif
}
/*!
@@ -1061,9 +1069,8 @@ bool QProcessPrivate::tryReadFromChannel(Channel *channel)
if (currentReadChannel == channelIdx) {
didRead = true;
if (!emittedReadyRead) {
- emittedReadyRead = true;
+ QScopedValueRollback<bool> guard(emittedReadyRead, true);
emit q->readyRead();
- emittedReadyRead = false;
}
}
emit q->channelReadyRead(int(channelIdx));
@@ -1173,7 +1180,12 @@ bool QProcessPrivate::_q_processDied()
//emit q->standardOutputClosed();
//emit q->standardErrorClosed();
+#if QT_DEPRECATED_SINCE(5, 13)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
emit q->finished(exitCode);
+QT_WARNING_POP
+#endif
emit q->finished(exitCode, exitStatus);
}
#if defined QPROCESS_DEBUG
@@ -1265,6 +1277,7 @@ QProcess::~QProcess()
d->cleanup();
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
Returns the read channel mode of the QProcess. This function is
@@ -1288,6 +1301,7 @@ void QProcess::setReadChannelMode(ProcessChannelMode mode)
{
setProcessChannelMode(mode);
}
+#endif
/*!
\since 4.2
@@ -2474,7 +2488,7 @@ QProcess::ExitStatus QProcess::exitStatus() const
int QProcess::execute(const QString &program, const QStringList &arguments)
{
QProcess process;
- process.setReadChannelMode(ForwardedChannels);
+ process.setProcessChannelMode(ForwardedChannels);
process.start(program, arguments);
if (!process.waitForFinished(-1) || process.error() == FailedToStart)
return -2;
@@ -2497,7 +2511,7 @@ int QProcess::execute(const QString &program, const QStringList &arguments)
int QProcess::execute(const QString &command)
{
QProcess process;
- process.setReadChannelMode(ForwardedChannels);
+ process.setProcessChannelMode(ForwardedChannels);
process.start(command);
if (!process.waitForFinished(-1) || process.error() == FailedToStart)
return -2;
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index 474fc87de8..9fda5fba11 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -48,34 +48,34 @@
QT_REQUIRE_CONFIG(processenvironment);
-QT_BEGIN_NAMESPACE
-
-class QProcessPrivate;
-
-#if !defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
-typedef qint64 Q_PID;
-#else
-QT_END_NAMESPACE
+#ifdef Q_OS_WIN
typedef struct _PROCESS_INFORMATION *Q_PID;
+#endif
+
+#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
typedef struct _SECURITY_ATTRIBUTES Q_SECURITY_ATTRIBUTES;
typedef struct _STARTUPINFOW Q_STARTUPINFO;
-QT_BEGIN_NAMESPACE
#endif
+QT_BEGIN_NAMESPACE
+
+class QProcessPrivate;
class QProcessEnvironmentPrivate;
+#ifndef Q_OS_WIN
+typedef qint64 Q_PID;
+#endif
+
class Q_CORE_EXPORT QProcessEnvironment
{
public:
QProcessEnvironment();
QProcessEnvironment(const QProcessEnvironment &other);
~QProcessEnvironment();
-#ifdef Q_COMPILER_RVALUE_REFS
- QProcessEnvironment &operator=(QProcessEnvironment && other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QProcessEnvironment &operator=(QProcessEnvironment && other) noexcept { swap(other); return *this; }
QProcessEnvironment &operator=(const QProcessEnvironment &other);
- void swap(QProcessEnvironment &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QProcessEnvironment &other) noexcept { qSwap(d, other.d); }
bool operator==(const QProcessEnvironment &other) const;
inline bool operator!=(const QProcessEnvironment &other) const
@@ -172,8 +172,12 @@ public:
QStringList arguments() const;
void setArguments(const QStringList & arguments);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QProcess::processChannelMode() instead")
ProcessChannelMode readChannelMode() const;
+ QT_DEPRECATED_X("Use QProcess::setProcessChannelMode() instead")
void setReadChannelMode(ProcessChannelMode mode);
+#endif
ProcessChannelMode processChannelMode() const;
void setProcessChannelMode(ProcessChannelMode mode);
InputChannelMode inputChannelMode() const;
@@ -269,7 +273,10 @@ public Q_SLOTS:
Q_SIGNALS:
void started(QPrivateSignal);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QProcess::finished(int, QProcess::ExitStatus) instead")
void finished(int exitCode); // ### Qt 6: merge the two signals with a default value
+#endif
void finished(int exitCode, QProcess::ExitStatus exitStatus);
#if QT_DEPRECATED_SINCE(5,6)
void error(QProcess::ProcessError error);
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index aa7ecbe91d..d02e87837c 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -108,8 +108,7 @@ using QProcEnvKey = QByteArray;
class QProcEnvValue
{
public:
- QProcEnvValue() {}
- QProcEnvValue(const QProcEnvValue &other) { *this = other; }
+ QProcEnvValue() = default;
explicit QProcEnvValue(const QString &value) : stringValue(value) {}
explicit QProcEnvValue(const QByteArray &value) : byteValue(value) {}
bool operator==(const QProcEnvValue &other) const
@@ -221,7 +220,7 @@ public:
template<> Q_INLINE_TEMPLATE void QSharedDataPointer<QProcessEnvironmentPrivate>::detach()
{
- if (d && d->ref.load() == 1)
+ if (d && d->ref.loadRelaxed() == 1)
return;
QProcessEnvironmentPrivate *x = (d ? new QProcessEnvironmentPrivate(*d)
: new QProcessEnvironmentPrivate);
@@ -247,7 +246,7 @@ public:
// if you add "= 4" here, increase the number of bits below
};
- Channel() : process(0), notifier(0), type(Normal), closed(false), append(false)
+ Channel() : process(nullptr), notifier(nullptr), type(Normal), closed(false), append(false)
{
pipe[0] = INVALID_Q_PIPE;
pipe[1] = INVALID_Q_PIPE;
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 7a2daa2a57..3a29a0d842 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -202,8 +202,7 @@ static int qt_create_pipe(int *pipe)
qt_safe_close(pipe[1]);
int pipe_ret = qt_safe_pipe(pipe);
if (pipe_ret != 0) {
- qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s",
- pipe, qPrintable(qt_error_string(errno)));
+ qErrnoWarning("QProcessPrivate::createPipe: Cannot create pipe %p", pipe);
}
return pipe_ret;
}
@@ -473,7 +472,7 @@ void QProcessPrivate::startProcess()
if (forkfd == -1) {
// Cleanup, report error and return
#if defined (QPROCESS_DEBUG)
- qDebug("fork failed: %s", qPrintable(qt_error_string(lastForkErrno)));
+ qDebug("fork failed: %ls", qUtf16Printable(qt_error_string(lastForkErrno)));
#endif
q->setProcessState(QProcess::NotRunning);
setErrorAndEmit(QProcess::FailedToStart,
@@ -652,7 +651,7 @@ bool QProcessPrivate::writeToStdin()
qDebug("QProcessPrivate::writeToStdin(), write(%p \"%s\", %lld) == %lld",
data, qt_prettyDebug(data, bytesToWrite, 16).constData(), bytesToWrite, written);
if (written == -1)
- qDebug("QProcessPrivate::writeToStdin(), failed to write (%s)", qPrintable(qt_error_string(errno)));
+ qDebug("QProcessPrivate::writeToStdin(), failed to write (%ls)", qUtf16Printable(qt_error_string(errno)));
#endif
if (written == -1) {
// If the O_NONBLOCK flag is set and If some data can be written without blocking
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 564a3e5f51..d143f7fda3 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -56,16 +57,46 @@
#include "private/qabstractfileengine_p.h"
#include "private/qnumeric_p.h"
#include "private/qsimd_p.h"
+#include "private/qtools_p.h"
#include "private/qsystemerror_p.h"
+#if QT_CONFIG(zstd)
+# include <zstd.h>
+#endif
+
#ifdef Q_OS_UNIX
# include "private/qcore_unix_p.h"
#endif
+#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
+# define QT_USE_MMAP
+# include <sys/mman.h>
+#endif
+
//#define DEBUG_RESOURCE_MATCH
QT_BEGIN_NAMESPACE
+// Symbols used by code generated by RCC.
+// They cause compilation errors if the RCC content couldn't
+// be interpreted by this QtCore version.
+#if defined(__ELF__) || defined(__APPLE__) // same as RCC generates
+# define RCC_FEATURE_SYMBOL(feature) \
+ extern Q_CORE_EXPORT const quint8 qt_resourceFeature ## feature; \
+ const quint8 qt_resourceFeature ## feature = 0;
+#else
+# define RCC_FEATURE_SYMBOL(feature) \
+ Q_CORE_EXPORT quint8 qResourceFeature ## feature() { return 0; }
+#endif
+
+#ifndef QT_NO_COMPRESS
+RCC_FEATURE_SYMBOL(Zlib)
+#endif
+#if QT_CONFIG(zstd)
+RCC_FEATURE_SYMBOL(Zstd)
+#endif
+
+#undef RCC_FEATURE_SYMBOL
class QStringSplitter
{
@@ -98,11 +129,15 @@ public:
//resource glue
class QResourceRoot
{
+public:
enum Flags
{
+ // must match rcc.h
Compressed = 0x01,
- Directory = 0x02
+ Directory = 0x02,
+ CompressedZstd = 0x04
};
+private:
const uchar *tree, *names, *payloads;
int version;
inline int findOffset(int node) const { return node * (14 + (version >= 0x02 ? 8 : 0)); } //sizeof each tree element
@@ -112,17 +147,25 @@ class QResourceRoot
public:
mutable QAtomicInt ref;
- inline QResourceRoot(): tree(0), names(0), payloads(0), version(0) {}
+ inline QResourceRoot(): tree(nullptr), names(nullptr), payloads(nullptr), version(0) {}
inline QResourceRoot(int version, const uchar *t, const uchar *n, const uchar *d) { setSource(version, t, n, d); }
virtual ~QResourceRoot() { }
int findNode(const QString &path, const QLocale &locale=QLocale()) const;
inline bool isContainer(int node) const { return flags(node) & Directory; }
- inline bool isCompressed(int node) const { return flags(node) & Compressed; }
+ QResource::Compression compressionAlgo(int node)
+ {
+ uint compressionFlags = flags(node) & (Compressed | CompressedZstd);
+ if (compressionFlags == Compressed)
+ return QResource::ZlibCompression;
+ if (compressionFlags == CompressedZstd)
+ return QResource::ZstdCompression;
+ return QResource::NoCompression;
+ }
const uchar *data(int node, qint64 *size) const;
quint64 lastModified(int node) const;
QStringList children(int node) const;
virtual QString mappingRoot() const { return QString(); }
- bool mappingRootSubdir(const QString &path, QString *match=0) const;
+ bool mappingRootSubdir(const QString &path, QString *match = nullptr) const;
inline bool operator==(const QResourceRoot &other) const
{ return tree == other.tree && names == other.names && payloads == other.payloads && version == other.version; }
inline bool operator!=(const QResourceRoot &other) const
@@ -229,6 +272,23 @@ static inline QStringList *resourceSearchPaths()
\sa {The Qt Resource System}, QFile, QDir, QFileInfo
*/
+/*!
+ \enum QResource::Compression
+ \since 5.13
+
+ This enum is used by compressionAlgorithm() to indicate which algorithm the
+ RCC tool used to compress the payload.
+
+ \value NoCompression Contents are not compressed (isCompressed() is false).
+ \value ZlibCompression Contents are compressed using \l{zlib}{https://zlib.net} and can
+ be decompressed using the qUncompress() function.
+ \value ZstdCompression Contents are compressed using \l{zstd}{https://zstd.net}. To
+ decompress, use the \c{ZSTD_decompress} function from the zstd
+ library.
+
+ \sa compressionAlgorithm(), isCompressed()
+*/
+
class QResourcePrivate {
public:
inline QResourcePrivate(QResource *_q) : q_ptr(_q) { clear(); }
@@ -243,12 +303,13 @@ public:
QLocale locale;
QString fileName, absoluteFilePath;
QList<QResourceRoot*> related;
- uint container : 1;
- mutable uint compressed : 1;
mutable qint64 size;
+ mutable quint64 lastModified;
mutable const uchar *data;
mutable QStringList children;
- mutable quint64 lastModified;
+ mutable quint8 compressionAlgo;
+ bool container;
+ /* 2 or 6 padding bytes */
QResource *q_ptr;
Q_DECLARE_PUBLIC(QResource)
@@ -258,8 +319,8 @@ void
QResourcePrivate::clear()
{
absoluteFilePath.clear();
- compressed = 0;
- data = 0;
+ compressionAlgo = QResource::NoCompression;
+ data = nullptr;
size = 0;
children.clear();
lastModified = 0;
@@ -287,11 +348,11 @@ QResourcePrivate::load(const QString &file)
container = res->isContainer(node);
if(!container) {
data = res->data(node, &size);
- compressed = res->isCompressed(node);
+ compressionAlgo = res->compressionAlgo(node);
} else {
- data = 0;
+ data = nullptr;
size = 0;
- compressed = 0;
+ compressionAlgo = QResource::NoCompression;
}
lastModified = res->lastModified(node);
} else if(res->isContainer(node) != container) {
@@ -301,9 +362,9 @@ QResourcePrivate::load(const QString &file)
related.append(res);
} else if(res->mappingRootSubdir(file)) {
container = true;
- data = 0;
+ data = nullptr;
size = 0;
- compressed = 0;
+ compressionAlgo = QResource::NoCompression;
lastModified = 0;
res->ref.ref();
related.append(res);
@@ -493,16 +554,41 @@ bool QResource::isValid() const
/*!
Returns \c true if the resource represents a file and the data backing it
- is in a compressed format, false otherwise.
+ is in a compressed format, false otherwise. If the data is compressed,
+ check compressionAlgorithm() to verify what algorithm to use to decompress
+ the data.
- \sa data(), isFile()
+ \sa data(), compressionAlgorithm(), isFile()
*/
bool QResource::isCompressed() const
{
+ return compressionAlgorithm() != NoCompression;
+}
+
+/*!
+ \since 5.13
+
+ Returns the compression type that this resource is compressed with, if any.
+ If it is not compressed, this function returns QResource::NoCompression.
+
+ If this function returns QResource::ZlibCompression, you may decompress the
+ data using the qUncompress() function. Up until Qt 5.13, this was the only
+ possible compression algorithm.
+
+ If this function returns QResource::ZstdCompression, you need to use the
+ Zstandard library functios (\c{<zstd.h> header). Qt does not provide a
+ wrapper.
+
+ See \l{http://facebook.github.io/zstd/zstd_manual.html}{Zstandard manual}.
+
+ \sa isCompressed(), data(), isFile()
+*/
+QResource::Compression QResource::compressionAlgorithm() const
+{
Q_D(const QResource);
d->ensureInitialized();
- return d->compressed;
+ return Compression(d->compressionAlgo);
}
/*!
@@ -522,7 +608,7 @@ qint64 QResource::size() const
Returns direct access to a read only segment of data that this resource
represents. If the resource is compressed the data returns is
compressed and qUncompress() must be used to access the data. If the
- resource is a directory 0 is returned.
+ resource is a directory \nullptr is returned.
\sa size(), isCompressed(), isFile()
*/
@@ -573,6 +659,7 @@ QStringList QResource::children() const
return d->children;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -614,6 +701,7 @@ QResource::searchPaths()
QMutexLocker lock(resourceMutex());
return *resourceSearchPaths();
}
+#endif
inline uint QResourceRoot::hash(int node) const
{
@@ -776,7 +864,7 @@ const uchar *QResourceRoot::data(int node, qint64 *size) const
{
if(node == -1) {
*size = 0;
- return 0;
+ return nullptr;
}
int offset = findOffset(node) + 4; //jump past name
@@ -793,7 +881,7 @@ const uchar *QResourceRoot::data(int node, qint64 *size) const
return ret;
}
*size = 0;
- return 0;
+ return nullptr;
}
quint64 QResourceRoot::lastModified(int node) const
@@ -853,7 +941,7 @@ Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
const unsigned char *name, const unsigned char *data)
{
QMutexLocker lock(resourceMutex());
- if ((version == 0x01 || version == 0x2) && resourceList()) {
+ if (version >= 0x01 && version <= 0x3 && resourceList()) {
bool found = false;
QResourceRoot res(version, tree, name, data);
for(int i = 0; i < resourceList()->size(); ++i) {
@@ -879,7 +967,7 @@ Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tre
return false;
QMutexLocker lock(resourceMutex());
- if ((version == 0x01 || version == 0x02) && resourceList()) {
+ if (version >= 0x01 && version <= 0x3 && resourceList()) {
QResourceRoot res(version, tree, name, data);
for(int i = 0; i < resourceList()->size(); ) {
if(*resourceList()->at(i) == res) {
@@ -903,14 +991,14 @@ class QDynamicBufferResourceRoot: public QResourceRoot
const uchar *buffer;
public:
- inline QDynamicBufferResourceRoot(const QString &_root) : root(_root), buffer(0) { }
+ inline QDynamicBufferResourceRoot(const QString &_root) : root(_root), buffer(nullptr) { }
inline ~QDynamicBufferResourceRoot() { }
inline const uchar *mappingBuffer() const { return buffer; }
- virtual QString mappingRoot() const override { return root; }
- virtual ResourceRootType type() const override { return Resource_Buffer; }
+ QString mappingRoot() const override { return root; }
+ ResourceRootType type() const override { return Resource_Buffer; }
// size == -1 means "unknown"
- bool registerSelf(const uchar *b, int size)
+ bool registerSelf(const uchar *b, qsizetype size)
{
// 5 int "pointers"
if (size >= 0 && size < 20)
@@ -938,11 +1026,27 @@ public:
const int name_offset = qFromBigEndian<qint32>(b + offset);
offset += 4;
+ quint32 file_flags = 0;
+ if (version >= 3) {
+ file_flags = qFromBigEndian<qint32>(b + offset);
+ offset += 4;
+ }
+
// Some sanity checking for sizes. This is _not_ a security measure.
if (size >= 0 && (tree_offset >= size || data_offset >= size || name_offset >= size))
return false;
- if (version == 0x01 || version == 0x02) {
+ // And some sanity checking for features
+ quint32 acceptableFlags = 0;
+#ifndef QT_NO_COMPRESS
+ acceptableFlags |= Compressed;
+#endif
+ if (QT_CONFIG(zstd))
+ acceptableFlags |= CompressedZstd;
+ if (file_flags & ~acceptableFlags)
+ return false;
+
+ if (version >= 0x01 && version <= 0x03) {
buffer = b;
setSource(version, b+tree_offset, b+name_offset, b+data_offset);
return true;
@@ -951,36 +1055,22 @@ public:
}
};
-#if defined(Q_OS_UNIX) && !defined (Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
-#define QT_USE_MMAP
-#endif
-
-// most of the headers below are already included in qplatformdefs.h
-// also this lacks Large File support but that's probably irrelevant
-#if defined(QT_USE_MMAP)
-// for mmap
-QT_BEGIN_INCLUDE_NAMESPACE
-#include <sys/mman.h>
-#include <errno.h>
-QT_END_INCLUDE_NAMESPACE
-#endif
-
-
-
class QDynamicFileResourceRoot: public QDynamicBufferResourceRoot
{
QString fileName;
// for mmap'ed files, this is what needs to be unmapped.
uchar *unmapPointer;
- unsigned int unmapLength;
+ qsizetype unmapLength;
public:
- inline QDynamicFileResourceRoot(const QString &_root) : QDynamicBufferResourceRoot(_root), unmapPointer(0), unmapLength(0) { }
+ QDynamicFileResourceRoot(const QString &_root)
+ : QDynamicBufferResourceRoot(_root), unmapPointer(nullptr), unmapLength(0)
+ { }
~QDynamicFileResourceRoot() {
#if defined(QT_USE_MMAP)
if (unmapPointer) {
munmap((char*)unmapPointer, unmapLength);
- unmapPointer = 0;
+ unmapPointer = nullptr;
unmapLength = 0;
} else
#endif
@@ -989,76 +1079,78 @@ public:
}
}
QString mappingFile() const { return fileName; }
- virtual ResourceRootType type() const override { return Resource_File; }
+ ResourceRootType type() const override { return Resource_File; }
- bool registerSelf(const QString &f) {
- bool fromMM = false;
- uchar *data = 0;
- unsigned int data_len = 0;
-
-#ifdef QT_USE_MMAP
+ bool registerSelf(const QString &f);
+};
#ifndef MAP_FILE
-#define MAP_FILE 0
+# define MAP_FILE 0
#endif
#ifndef MAP_FAILED
-#define MAP_FAILED -1
+# define MAP_FAILED reinterpret_cast<void *>(-1)
#endif
- int fd = QT_OPEN(QFile::encodeName(f), O_RDONLY,
+bool QDynamicFileResourceRoot::registerSelf(const QString &f)
+{
+ bool fromMM = false;
+ uchar *data = nullptr;
+ qsizetype data_len = 0;
+
+#ifdef QT_USE_MMAP
+ int fd = QT_OPEN(QFile::encodeName(f), O_RDONLY,
#if defined(Q_OS_WIN)
- _S_IREAD | _S_IWRITE
+ _S_IREAD | _S_IWRITE
#else
- 0666
+ 0666
#endif
- );
- if (fd >= 0) {
- QT_STATBUF st;
- if (!QT_FSTAT(fd, &st)) {
- uchar *ptr;
- ptr = reinterpret_cast<uchar *>(
- mmap(0, st.st_size, // any address, whole file
- PROT_READ, // read-only memory
- MAP_FILE | MAP_PRIVATE, // swap-backed map from file
- fd, 0)); // from offset 0 of fd
- if (ptr && ptr != reinterpret_cast<uchar *>(MAP_FAILED)) {
- data = ptr;
- data_len = st.st_size;
- fromMM = true;
- }
+ );
+ if (fd >= 0) {
+ QT_STATBUF st;
+ if (!QT_FSTAT(fd, &st) && st.st_size <= std::numeric_limits<qsizetype>::max()) {
+ int protection = PROT_READ; // read-only memory
+ int flags = MAP_FILE | MAP_PRIVATE; // swap-backed map from file
+ void *ptr = QT_MMAP(nullptr, st.st_size, // any address, whole file
+ protection, flags,
+ fd, 0); // from offset 0 of fd
+ if (ptr != MAP_FAILED) {
+ data = static_cast<uchar *>(ptr);
+ data_len = st.st_size;
+ fromMM = true;
}
- ::close(fd);
}
+ QT_CLOSE(fd);
+ }
#endif // QT_USE_MMAP
- if(!data) {
- QFile file(f);
- if (!file.exists())
- return false;
- data_len = file.size();
- data = new uchar[data_len];
-
- bool ok = false;
- if (file.open(QIODevice::ReadOnly))
- ok = (data_len == (uint)file.read((char*)data, data_len));
- if (!ok) {
- delete [] data;
- data = 0;
- data_len = 0;
- return false;
+ if (!data) {
+ QFile file(f);
+ bool ok = false;
+ if (file.open(QIODevice::ReadOnly)) {
+ qint64 fsize = file.size();
+ if (fsize <= std::numeric_limits<qsizetype>::max()) {
+ data_len = file.size();
+ data = new uchar[data_len];
+ ok = (data_len == file.read((char*)data, data_len));
}
- fromMM = false;
}
- if (data && QDynamicBufferResourceRoot::registerSelf(data, data_len)) {
- if(fromMM) {
- unmapPointer = data;
- unmapLength = data_len;
- }
- fileName = f;
- return true;
+ if (!ok) {
+ delete [] data;
+ data = nullptr;
+ data_len = 0;
+ return false;
}
- return false;
+ fromMM = false;
}
-};
+ if (data && QDynamicBufferResourceRoot::registerSelf(data, data_len)) {
+ if (fromMM) {
+ unmapPointer = data;
+ unmapLength = data_len;
+ }
+ fileName = f;
+ return true;
+ }
+ return false;
+}
static QString qt_resource_fixResourceRoot(QString r) {
if(!r.isEmpty()) {
@@ -1531,12 +1623,40 @@ bool QResourceFileEnginePrivate::unmap(uchar *ptr)
void QResourceFileEnginePrivate::uncompress() const
{
- if (resource.isCompressed() && uncompressed.isEmpty() && resource.size()) {
+ if (uncompressed.isEmpty() && resource.size()) {
+ quint64 size;
+ switch (resource.compressionAlgorithm()) {
+ case QResource::NoCompression:
+ return; // nothing to do
+
+ case QResource::ZlibCompression:
#ifndef QT_NO_COMPRESS
- uncompressed = qUncompress(resource.data(), resource.size());
+ uncompressed = qUncompress(resource.data(), resource.size());
+#else
+ Q_ASSERT(!"QResourceFileEngine::open: Qt built without support for Zlib compression");
+#endif
+ break;
+
+ case QResource::ZstdCompression:
+#if QT_CONFIG(zstd)
+ size = ZSTD_getFrameContentSize(resource.data(), resource.size());
+ if (!ZSTD_isError(size)) {
+ if (size >= MaxAllocSize) {
+ qWarning("QResourceFileEngine::open: content bigger than memory (size %lld)", size);
+ } else {
+ uncompressed = QByteArray(size, Qt::Uninitialized);
+ size = ZSTD_decompress(const_cast<char *>(uncompressed.data()), size,
+ resource.data(), resource.size());
+ }
+ }
+ if (ZSTD_isError(size))
+ qWarning("QResourceFileEngine::open: error decoding: %s", ZSTD_getErrorName(size));
#else
- Q_ASSERT(!"QResourceFileEngine::open: Qt built without support for compression");
+ Q_UNUSED(size);
+ Q_ASSERT(!"QResourceFileEngine::open: Qt built without support for Zstd compression");
#endif
+ break;
+ }
}
}
diff --git a/src/corelib/io/qresource.h b/src/corelib/io/qresource.h
index 895cf0456e..5e798de436 100644
--- a/src/corelib/io/qresource.h
+++ b/src/corelib/io/qresource.h
@@ -54,6 +54,12 @@ class QResourcePrivate;
class Q_CORE_EXPORT QResource
{
public:
+ enum Compression {
+ NoCompression,
+ ZlibCompression,
+ ZstdCompression
+ };
+
QResource(const QString &file=QString(), const QLocale &locale=QLocale());
~QResource();
@@ -67,12 +73,17 @@ public:
bool isValid() const;
bool isCompressed() const;
+ Compression compressionAlgorithm() const;
qint64 size() const;
const uchar *data() const;
QDateTime lastModified() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QDir::addSearchPath() instead")
static void addSearchPath(const QString &path);
+ QT_DEPRECATED_X("Use QDir::searchPaths() instead")
static QStringList searchPaths();
+#endif
static bool registerResource(const QString &rccFilename, const QString &resourceRoot=QString());
static bool unregisterResource(const QString &rccFilename, const QString &resourceRoot=QString());
diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h
index dcfe46704c..fedf95bb33 100644
--- a/src/corelib/io/qresource_p.h
+++ b/src/corelib/io/qresource_p.h
@@ -64,51 +64,51 @@ public:
explicit QResourceFileEngine(const QString &path);
~QResourceFileEngine();
- virtual void setFileName(const QString &file) override;
+ void setFileName(const QString &file) override;
- virtual bool open(QIODevice::OpenMode flags) override ;
- virtual bool close() override;
- virtual bool flush() override;
- virtual qint64 size() const override;
- virtual qint64 pos() const override;
+ bool open(QIODevice::OpenMode flags) override;
+ bool close() override;
+ bool flush() override;
+ qint64 size() const override;
+ qint64 pos() const override;
virtual bool atEnd() const;
- virtual bool seek(qint64) override;
- virtual qint64 read(char *data, qint64 maxlen) override;
- virtual qint64 write(const char *data, qint64 len) override;
+ bool seek(qint64) override;
+ qint64 read(char *data, qint64 maxlen) override;
+ qint64 write(const char *data, qint64 len) override;
- virtual bool remove() override;
- virtual bool copy(const QString &newName) override;
- virtual bool rename(const QString &newName) override;
- virtual bool link(const QString &newName) override;
+ bool remove() override;
+ bool copy(const QString &newName) override;
+ bool rename(const QString &newName) override;
+ bool link(const QString &newName) override;
- virtual bool isSequential() const override;
+ bool isSequential() const override;
- virtual bool isRelativePath() const override;
+ bool isRelativePath() const override;
- virtual bool mkdir(const QString &dirName, bool createParentDirectories) const override;
- virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const override;
+ bool mkdir(const QString &dirName, bool createParentDirectories) const override;
+ bool rmdir(const QString &dirName, bool recurseParentDirectories) const override;
- virtual bool setSize(qint64 size) override;
+ bool setSize(qint64 size) override;
- virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
+ QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
- virtual bool caseSensitive() const override;
+ bool caseSensitive() const override;
- virtual FileFlags fileFlags(FileFlags type) const override;
+ FileFlags fileFlags(FileFlags type) const override;
- virtual bool setPermissions(uint perms) override;
+ bool setPermissions(uint perms) override;
- virtual QString fileName(QAbstractFileEngine::FileName file) const override;
+ QString fileName(QAbstractFileEngine::FileName file) const override;
- virtual uint ownerId(FileOwner) const override;
- virtual QString owner(FileOwner) const override;
+ uint ownerId(FileOwner) const override;
+ QString owner(FileOwner) const override;
- virtual QDateTime fileTime(FileTime time) const override;
+ QDateTime fileTime(FileTime time) const override;
- virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override;
- virtual Iterator *endEntryList() override;
+ Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override;
+ Iterator *endEntryList() override;
- bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) override;
+ bool extension(Extension extension, const ExtensionOption *option = nullptr, ExtensionReturn *output = nullptr) override;
bool supportsExtension(Extension extension) const override;
};
diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp
index 0cbc8c2234..915d0a0a00 100644
--- a/src/corelib/io/qsavefile.cpp
+++ b/src/corelib/io/qsavefile.cpp
@@ -151,7 +151,7 @@ QSaveFile::~QSaveFile()
if (d->fileEngine) {
d->fileEngine->remove();
delete d->fileEngine;
- d->fileEngine = 0;
+ d->fileEngine = nullptr;
}
}
@@ -193,7 +193,7 @@ bool QSaveFile::open(OpenMode mode)
{
Q_D(QSaveFile);
if (isOpen()) {
- qWarning("QSaveFile::open: File (%s) already open", qPrintable(fileName()));
+ qWarning("QSaveFile::open: File (%ls) already open", qUtf16Printable(fileName()));
return false;
}
unsetError();
@@ -252,7 +252,7 @@ bool QSaveFile::open(OpenMode mode)
return true;
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
delete d->fileEngine;
- d->fileEngine = 0;
+ d->fileEngine = nullptr;
} else {
QString msg =
QSaveFile::tr("QSaveFile cannot open '%1' without direct write fallback "
@@ -285,7 +285,7 @@ bool QSaveFile::open(OpenMode mode)
err = QFileDevice::OpenError;
d->setError(err, d->fileEngine->errorString());
delete d->fileEngine;
- d->fileEngine = 0;
+ d->fileEngine = nullptr;
return false;
}
@@ -326,7 +326,7 @@ bool QSaveFile::commit()
return false;
if (!isOpen()) {
- qWarning("QSaveFile::commit: File (%s) is not open", qPrintable(fileName()));
+ qWarning("QSaveFile::commit: File (%ls) is not open", qUtf16Printable(fileName()));
return false;
}
QFileDevice::close(); // calls flush()
@@ -339,7 +339,7 @@ bool QSaveFile::commit()
d->fileEngine->remove();
d->writeError = QFileDevice::NoError;
delete d->fileEngine;
- d->fileEngine = 0;
+ d->fileEngine = nullptr;
return false;
}
// atomically replace old file with new file
@@ -349,12 +349,12 @@ bool QSaveFile::commit()
d->setError(d->fileEngine->error(), d->fileEngine->errorString());
d->fileEngine->remove();
delete d->fileEngine;
- d->fileEngine = 0;
+ d->fileEngine = nullptr;
return false;
}
}
delete d->fileEngine;
- d->fileEngine = 0;
+ d->fileEngine = nullptr;
return true;
}
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index ed61c4aca0..9234a23f3a 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -62,8 +62,8 @@
#include "qrect.h"
#endif // !QT_NO_GEOM_VARIANT
-#ifndef QT_NO_QOBJECT
-#include "qcoreapplication.h"
+#ifndef QT_BUILD_QMAKE
+# include "qcoreapplication.h"
#endif
#ifndef QT_BOOTSTRAPPED
@@ -2667,9 +2667,10 @@ QSettings::QSettings(const QString &fileName, Format format, QObject *parent)
called, the QSettings object will not be able to read or write
any settings, and status() will return AccessError.
- On \macos and iOS, if both a name and an Internet domain are specified
- for the organization, the domain is preferred over the name. On
- other platforms, the name is preferred over the domain.
+ You should supply both the domain (used by default on \macos and iOS) and
+ the name (used by default elsewhere), although the code will cope if you
+ supply only one, which will then be used (on all platforms), at odds with
+ the usual naming of the file on platforms for which it isn't the default.
\sa QCoreApplication::setOrganizationName(),
QCoreApplication::setOrganizationDomain(),
@@ -2677,8 +2678,21 @@ QSettings::QSettings(const QString &fileName, Format format, QObject *parent)
setDefaultFormat()
*/
QSettings::QSettings(QObject *parent)
- : QObject(*QSettingsPrivate::create(globalDefaultFormat, UserScope,
-#ifdef Q_OS_MAC
+ : QSettings(UserScope, parent)
+{
+}
+
+/*!
+ \since 5.13
+
+ Constructs a QSettings object in the same way as
+ QSettings(QObject *parent) but with the given \a scope.
+
+ \sa QSettings(QObject *parent)
+*/
+QSettings::QSettings(Scope scope, QObject *parent)
+ : QObject(*QSettingsPrivate::create(globalDefaultFormat, scope,
+#ifdef Q_OS_DARWIN
QCoreApplication::organizationDomain().isEmpty()
? QCoreApplication::organizationName()
: QCoreApplication::organizationDomain()
@@ -2717,6 +2731,25 @@ QSettings::QSettings(const QString &fileName, Format format)
{
d_ptr->q_ptr = this;
}
+
+# ifndef QT_BUILD_QMAKE
+QSettings::QSettings(Scope scope)
+ : d_ptr(QSettingsPrivate::create(globalDefaultFormat, scope,
+# ifdef Q_OS_DARWIN
+ QCoreApplication::organizationDomain().isEmpty()
+ ? QCoreApplication::organizationName()
+ : QCoreApplication::organizationDomain()
+# else
+ QCoreApplication::organizationName().isEmpty()
+ ? QCoreApplication::organizationDomain()
+ : QCoreApplication::organizationName()
+# endif
+ , QCoreApplication::applicationName())
+ )
+{
+ d_ptr->q_ptr = this;
+}
+# endif
#endif
/*!
@@ -2886,7 +2919,7 @@ void QSettings::setIniCodec(const char *codecName)
\since 4.5
Returns the codec that is used for accessing INI files. By default,
- no codec is used, so a null pointer is returned.
+ no codec is used, so \nullptr is returned.
*/
QTextCodec *QSettings::iniCodec() const
@@ -3417,6 +3450,7 @@ QSettings::Format QSettings::defaultFormat()
return globalDefaultFormat;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -3450,7 +3484,7 @@ void QSettings::setUserIniPath(const QString &dir)
setPath(NativeFormat, UserScope, dir);
#endif
}
-
+#endif
/*!
\since 4.1
diff --git a/src/corelib/io/qsettings.h b/src/corelib/io/qsettings.h
index 7a9eebe11b..07c746d043 100644
--- a/src/corelib/io/qsettings.h
+++ b/src/corelib/io/qsettings.h
@@ -129,6 +129,7 @@ public:
const QString &application = QString(), QObject *parent = nullptr);
QSettings(const QString &fileName, Format format, QObject *parent = nullptr);
explicit QSettings(QObject *parent = nullptr);
+ explicit QSettings(Scope scope, QObject *parent = nullptr);
#else
explicit QSettings(const QString &organization,
const QString &application = QString());
@@ -137,6 +138,9 @@ public:
QSettings(Format format, Scope scope, const QString &organization,
const QString &application = QString());
QSettings(const QString &fileName, Format format);
+# ifndef QT_BUILD_QMAKE
+ explicit QSettings(Scope scope = UserScope);
+# endif
#endif
~QSettings();
@@ -183,8 +187,12 @@ public:
static void setDefaultFormat(Format format);
static Format defaultFormat();
- static void setSystemIniPath(const QString &dir); // ### Qt 6: remove (use setPath() instead)
- static void setUserIniPath(const QString &dir); // ### Qt 6: remove (use setPath() instead)
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QSettings::setPath() instead")
+ static void setSystemIniPath(const QString &dir);
+ QT_DEPRECATED_X("Use QSettings::setPath() instead")
+ static void setUserIniPath(const QString &dir);
+#endif
static void setPath(Format format, Scope scope, const QString &path);
typedef QMap<QString, QVariant> SettingsMap;
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
index dd3468e1f8..679212ea21 100644
--- a/src/corelib/io/qsettings_win.cpp
+++ b/src/corelib/io/qsettings_win.cpp
@@ -166,8 +166,8 @@ static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSub
if (res == ERROR_SUCCESS)
return resultHandle;
- //qWarning("QSettings: Failed to create subkey \"%s\": %s",
- // qPrintable(rSubKey), qPrintable(qt_error_string(int(res))));
+ //qErrnoWarning(int(res), "QSettings: Failed to create subkey \"%ls\"",
+ // qUtf16Printable(rSubKey));
return 0;
}
@@ -207,7 +207,7 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS
&numKeys, &maxKeySize, 0, 0, 0);
if (res != ERROR_SUCCESS) {
- qWarning("QSettings: RegQueryInfoKey() failed: %s", qPrintable(qt_error_string(int(res))));
+ qErrnoWarning(int(res), "QSettings: RegQueryInfoKey() failed");
return result;
}
@@ -241,7 +241,7 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS
item = QString::fromWCharArray((const wchar_t *)buff.constData(), l);
if (res != ERROR_SUCCESS) {
- qWarning("QSettings: RegEnumValue failed: %s", qPrintable(qt_error_string(int(res))));
+ qErrnoWarning(int(res), "QSettings: RegEnumValue failed");
continue;
}
if (item.isEmpty())
@@ -295,8 +295,8 @@ static void deleteChildGroups(HKEY parentHandle, REGSAM access = 0)
// delete group itself
LONG res = RegDeleteKey(parentHandle, reinterpret_cast<const wchar_t *>(group.utf16()));
if (res != ERROR_SUCCESS) {
- qWarning("QSettings: RegDeleteKey failed on subkey \"%s\": %s",
- qPrintable(group), qPrintable(qt_error_string(int(res))));
+ qErrnoWarning(int(res), "QSettings: RegDeleteKey failed on subkey \"%ls\"",
+ qUtf16Printable(group));
return;
}
}
@@ -596,8 +596,8 @@ QWinSettingsPrivate::~QWinSettingsPrivate()
QString emptyKey;
DWORD res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(emptyKey.utf16()));
if (res != ERROR_SUCCESS) {
- qWarning("QSettings: Failed to delete key \"%s\": %s",
- qPrintable(regList.at(0).key()), qPrintable(qt_error_string(int(res))));
+ qErrnoWarning(int(res), "QSettings: Failed to delete key \"%ls\"",
+ qUtf16Printable(regList.constFirst().key()));
}
}
@@ -633,16 +633,16 @@ void QWinSettingsPrivate::remove(const QString &uKey)
for (const QString &group : childKeys) {
LONG res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(group.utf16()));
if (res != ERROR_SUCCESS) {
- qWarning("QSettings: RegDeleteValue failed on subkey \"%s\": %s",
- qPrintable(group), qPrintable(qt_error_string(int(res))));
+ qErrnoWarning(int(res), "QSettings: RegDeleteValue failed on subkey \"%ls\"",
+ qUtf16Printable(group));
}
}
} else {
res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(rKey.utf16()));
if (res != ERROR_SUCCESS) {
- qWarning("QSettings: RegDeleteKey failed on key \"%s\": %s",
- qPrintable(rKey), qPrintable(qt_error_string(int(res))));
+ qErrnoWarning(int(res), "QSettings: RegDeleteKey failed on key \"%ls\"",
+ qUtf16Printable(rKey));
}
}
RegCloseKey(handle);
@@ -739,8 +739,8 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
if (res == ERROR_SUCCESS) {
deleteWriteHandleOnExit = false;
} else {
- qWarning("QSettings: failed to set subkey \"%s\": %s",
- qPrintable(rKey), qPrintable(qt_error_string(int(res))));
+ qErrnoWarning(int(res), "QSettings: failed to set subkey \"%ls\"",
+ qUtf16Printable(rKey));
setStatus(QSettings::AccessError);
}
diff --git a/src/corelib/io/qstandardpaths_android.cpp b/src/corelib/io/qstandardpaths_android.cpp
index 0667d170c7..1f4e0de1e7 100644
--- a/src/corelib/io/qstandardpaths_android.cpp
+++ b/src/corelib/io/qstandardpaths_android.cpp
@@ -136,7 +136,7 @@ static QString getExternalStoragePublicDirectory(const char *directoryField)
*/
static QString getExternalFilesDir(const char *directoryField = 0)
{
- QString &path = (*androidDirCache)[QString(QLatin1String("APPNAME_%1")).arg(QLatin1String(directoryField))];
+ QString &path = (*androidDirCache)[QLatin1String("APPNAME_%1").arg(QLatin1String(directoryField))];
if (!path.isEmpty())
return path;
@@ -239,10 +239,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case QStandardPaths::PicturesLocation:
return getExternalStoragePublicDirectory("DIRECTORY_PICTURES");
case QStandardPaths::DocumentsLocation:
- if (QtAndroidPrivate::androidSdkVersion() > 18)
- return getExternalStoragePublicDirectory("DIRECTORY_DOCUMENTS");
- else
- return getExternalStorageDirectory() + QLatin1String("/Documents");
+ return getExternalStoragePublicDirectory("DIRECTORY_DOCUMENTS");
case QStandardPaths::DownloadLocation:
return getExternalStoragePublicDirectory("DIRECTORY_DOWNLOADS");
case QStandardPaths::GenericConfigLocation:
@@ -295,13 +292,8 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
}
if (type == DocumentsLocation) {
- if (QtAndroidPrivate::androidSdkVersion() > 18) {
- return QStringList() << writableLocation(type)
- << getExternalFilesDir("DIRECTORY_DOCUMENTS");
- } else {
- return QStringList() << writableLocation(type)
- << getExternalFilesDir() + QLatin1String("/Documents");
- }
+ return QStringList() << writableLocation(type)
+ << getExternalFilesDir("DIRECTORY_DOCUMENTS");
}
if (type == DownloadLocation) {
diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp
index 748ce67dac..f4f8787968 100644
--- a/src/corelib/io/qstandardpaths_unix.cpp
+++ b/src/corelib/io/qstandardpaths_unix.cpp
@@ -130,27 +130,31 @@ QString QStandardPaths::writableLocation(StandardLocation type)
fileInfo.setFile(xdgRuntimeDir);
if (!fileInfo.isDir()) {
if (!QDir().mkdir(xdgRuntimeDir)) {
- qWarning("QStandardPaths: error creating runtime directory %s: %s", qPrintable(xdgRuntimeDir), qPrintable(qt_error_string(errno)));
+ qErrnoWarning("QStandardPaths: error creating runtime directory %ls",
+ qUtf16Printable(xdgRuntimeDir));
return QString();
}
}
- qWarning("QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '%s'", qPrintable(xdgRuntimeDir));
+#ifndef Q_OS_WASM
+ qWarning("QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '%ls'", qUtf16Printable(xdgRuntimeDir));
+#endif
} else {
fileInfo.setFile(xdgRuntimeDir);
if (!fileInfo.exists()) {
- qWarning("QStandardPaths: XDG_RUNTIME_DIR points to non-existing path '%s', "
- "please create it with 0700 permissions.", qPrintable(xdgRuntimeDir));
+ qWarning("QStandardPaths: XDG_RUNTIME_DIR points to non-existing path '%ls', "
+ "please create it with 0700 permissions.", qUtf16Printable(xdgRuntimeDir));
return QString();
}
if (!fileInfo.isDir()) {
- qWarning("QStandardPaths: XDG_RUNTIME_DIR points to '%s' which is not a directory",
- qPrintable(xdgRuntimeDir));
+ qWarning("QStandardPaths: XDG_RUNTIME_DIR points to '%ls' which is not a directory",
+ qUtf16Printable(xdgRuntimeDir));
return QString();
}
}
// "The directory MUST be owned by the user"
if (fileInfo.ownerId() != myUid) {
- qWarning("QStandardPaths: wrong ownership on runtime directory %s, %d instead of %d", qPrintable(xdgRuntimeDir),
+ qWarning("QStandardPaths: wrong ownership on runtime directory %ls, %d instead of %d",
+ qUtf16Printable(xdgRuntimeDir),
fileInfo.ownerId(), myUid);
return QString();
}
@@ -161,8 +165,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
if (fileInfo.permissions() != wantedPerms) {
QFile file(xdgRuntimeDir);
if (!file.setPermissions(wantedPerms)) {
- qWarning("QStandardPaths: could not set correct permissions on runtime directory %s: %s",
- qPrintable(xdgRuntimeDir), qPrintable(file.errorString()));
+ qWarning("QStandardPaths: could not set correct permissions on runtime directory %ls: %ls",
+ qUtf16Printable(xdgRuntimeDir), qUtf16Printable(file.errorString()));
return QString();
}
}
@@ -282,16 +286,12 @@ static QStringList xdgDataDirs()
dirs.append(QString::fromLatin1("/usr/local/share"));
dirs.append(QString::fromLatin1("/usr/share"));
} else {
- dirs = xdgDataDirsEnv.split(QLatin1Char(':'), QString::SkipEmptyParts);
+ const auto parts = xdgDataDirsEnv.splitRef(QLatin1Char(':'), QString::SkipEmptyParts);
// Normalize paths, skip relative paths
- QMutableListIterator<QString> it(dirs);
- while (it.hasNext()) {
- const QString dir = it.next();
- if (!dir.startsWith(QLatin1Char('/')))
- it.remove();
- else
- it.setValue(QDir::cleanPath(dir));
+ for (const QStringRef &dir : parts) {
+ if (dir.startsWith(QLatin1Char('/')))
+ dirs.push_back(QDir::cleanPath(dir.toString()));
}
// Remove duplicates from the list, there's no use for duplicated
diff --git a/src/corelib/io/qstorageinfo.h b/src/corelib/io/qstorageinfo.h
index 4ab7a353ef..237e68d2a1 100644
--- a/src/corelib/io/qstorageinfo.h
+++ b/src/corelib/io/qstorageinfo.h
@@ -62,11 +62,9 @@ public:
~QStorageInfo();
QStorageInfo &operator=(const QStorageInfo &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QStorageInfo &operator=(QStorageInfo &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QStorageInfo &operator=(QStorageInfo &&other) noexcept { swap(other); return *this; }
- inline void swap(QStorageInfo &other) Q_DECL_NOTHROW
+ inline void swap(QStorageInfo &other) noexcept
{ qSwap(d, other.d); }
void setPath(const QString &path);
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index 11b5af069a..b6413d7902 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -812,7 +812,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
valid = true;
ready = true;
-#if defined(Q_OS_INTEGRITY) || (defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD))
+#if defined(Q_OS_INTEGRITY) || (defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)) || defined(Q_OS_RTEMS)
bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
@@ -822,7 +822,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
#endif
blockSize = statfs_buf.f_bsize;
-#if defined(Q_OS_ANDROID) || defined(Q_OS_BSD4) || defined(Q_OS_INTEGRITY)
+#if defined(Q_OS_ANDROID) || defined(Q_OS_BSD4) || defined(Q_OS_INTEGRITY) || defined(Q_OS_RTEMS)
#if defined(_STATFS_F_FLAGS)
readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
#endif
diff --git a/src/corelib/io/qt_attribution.json b/src/corelib/io/qt_attribution.json
index e9eb9c85e4..9b7dcc6b54 100644
--- a/src/corelib/io/qt_attribution.json
+++ b/src/corelib/io/qt_attribution.json
@@ -2,7 +2,7 @@
"Id": "psl",
"Name": "The Public Suffix List",
"QDocModule": "qtcore",
- "Description": "The Public Suffix List is an initiative of the Mozilla Project,
+ "Description": "The Public Suffix List is an initiative of Mozilla,
but is maintained as a community resource. It is available for use in any software,
but was originally created to meet the needs of browser manufacturers.
It allows browsers to, for example:
@@ -14,11 +14,13 @@ It allows browsers to, for example:
- Accurately sort history entries by site",
"Files": "qurltlds_p.h",
- "QtUsage": "Used in Qt Core to avoid \"supercookies\" being set in the cookie jar
+ "QtUsage": "See util/corelib/qurl-generateTLDs/ for code-generator",
+ "QtUsage": "Used in Qt Core to avoid setting \"supercookies\" in the cookie jar
supported by Qt (by the QNetworkCookieJar class).",
+ "Homepage": "Consult https://github.com/publicsuffix/list for the sha1 but download from ...",
"Homepage": "http://publicsuffix.org/",
- "Version": "Generated on 2018-01-04",
+ "Version": "d6331e2b65fffbe9fe299dae1689db8de8fd6190, fetched on 2019-02-20",
"License": "Mozilla Public License 2.0",
"LicenseFile": "PSL-LICENSE.txt",
"LicenseId": "MPL-2.0",
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index ced08a9a87..c89ad06a1f 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -327,7 +327,7 @@ bool QTemporaryFileEngine::isReallyOpen() const
{
Q_D(const QFSFileEngine);
- if (!((0 == d->fh) && (-1 == d->fd)
+ if (!((nullptr == d->fh) && (-1 == d->fd)
#if defined Q_OS_WIN
&& (INVALID_HANDLE_VALUE == d->fileHandle)
#endif
@@ -902,7 +902,7 @@ QTemporaryFile *QTemporaryFile::createNativeFile(QFile &file)
{
if (QAbstractFileEngine *engine = file.d_func()->engine()) {
if(engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)
- return 0; //native already
+ return nullptr; // native already
//cache
bool wasOpen = file.isOpen();
qint64 old_off = 0;
@@ -934,7 +934,7 @@ QTemporaryFile *QTemporaryFile::createNativeFile(QFile &file)
//done
return ret;
}
- return 0;
+ return nullptr;
}
/*!
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 6d82981fd6..d9ebc6c750 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -421,6 +421,7 @@
#include "private/qipaddress_p.h"
#include "qurlquery.h"
#include "private/qdir_p.h"
+#include <private/qmemory_p.h>
QT_BEGIN_NAMESPACE
@@ -520,10 +521,10 @@ public:
bool isEmpty() const
{ return sectionIsPresent == 0 && port == -1 && path.isEmpty(); }
- Error *cloneError() const;
+ std::unique_ptr<Error> cloneError() const;
void clearError();
void setError(ErrorCode errorCode, const QString &source, int supplement = -1);
- ErrorCode validityError(QString *source = 0, int *position = 0) const;
+ ErrorCode validityError(QString *source = nullptr, int *position = nullptr) const;
bool validateComponent(Section section, const QString &input, int begin, int end);
bool validateComponent(Section section, const QString &input)
{ return validateComponent(section, input, 0, uint(input.length())); }
@@ -576,7 +577,7 @@ public:
QString query;
QString fragment;
- Error *error;
+ std::unique_ptr<Error> error;
// not used for:
// - Port (port == -1 means absence)
@@ -591,7 +592,6 @@ public:
inline QUrlPrivate::QUrlPrivate()
: ref(1), port(-1),
- error(0),
sectionIsPresent(0),
flags(0)
{
@@ -613,19 +613,16 @@ inline QUrlPrivate::QUrlPrivate(const QUrlPrivate &copy)
}
inline QUrlPrivate::~QUrlPrivate()
-{
- delete error;
-}
+ = default;
-inline QUrlPrivate::Error *QUrlPrivate::cloneError() const
+std::unique_ptr<QUrlPrivate::Error> QUrlPrivate::cloneError() const
{
- return error ? new Error(*error) : 0;
+ return error ? qt_make_unique<Error>(*error) : nullptr;
}
inline void QUrlPrivate::clearError()
{
- delete error;
- error = 0;
+ error.reset();
}
inline void QUrlPrivate::setError(ErrorCode errorCode, const QString &source, int supplement)
@@ -634,7 +631,7 @@ inline void QUrlPrivate::setError(ErrorCode errorCode, const QString &source, in
// don't overwrite an error set in a previous section during parsing
return;
}
- error = new Error;
+ error = qt_make_unique<Error>();
error->code = errorCode;
error->source = source;
error->position = supplement;
@@ -826,7 +823,7 @@ recodeFromUser(const QString &input, const ushort *actions, int from, int to)
QString output;
const QChar *begin = input.constData() + from;
const QChar *end = input.constData() + to;
- if (qt_urlRecode(output, begin, end, 0, actions))
+ if (qt_urlRecode(output, begin, end, nullptr, actions))
return output;
return input.mid(from, to - from);
@@ -954,7 +951,7 @@ inline void QUrlPrivate::appendFragment(QString &appendTo, QUrl::FormattingOptio
{
appendToUser(appendTo, fragment, options,
options & QUrl::EncodeDelimiters ? fragmentInUrl :
- appendingTo == FullUrl ? 0 : fragmentInIsolation);
+ appendingTo == FullUrl ? nullptr : fragmentInIsolation);
}
inline void QUrlPrivate::appendQuery(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const
@@ -1179,7 +1176,7 @@ inline void QUrlPrivate::appendHost(QString &appendTo, QUrl::FormattingOptions o
if (host.at(0).unicode() == '[') {
// IPv6 addresses might contain a zone-id which needs to be recoded
if (options != 0)
- if (qt_urlRecode(appendTo, host.constBegin(), host.constEnd(), options, 0))
+ if (qt_urlRecode(appendTo, host.constBegin(), host.constEnd(), options, nullptr))
return;
appendTo += host;
} else {
@@ -1221,7 +1218,7 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
--end;
QString decoded;
- if (mode == QUrl::TolerantMode && qt_urlRecode(decoded, begin, end, QUrl::FullyDecoded, 0)) {
+ if (mode == QUrl::TolerantMode && qt_urlRecode(decoded, begin, end, QUrl::FullyDecoded, nullptr)) {
begin = decoded.constBegin();
end = decoded.constEnd();
}
@@ -1233,13 +1230,13 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
host += *begin;
else if (begin->unicode() >= '0' && begin->unicode() <= '9')
host += *begin;
- else if (begin->unicode() < 0x80 && strchr(acceptable, begin->unicode()) != 0)
+ else if (begin->unicode() < 0x80 && strchr(acceptable, begin->unicode()) != nullptr)
host += *begin;
else
return decoded.isEmpty() ? begin : &origBegin[2];
}
host += QLatin1Char(']');
- return 0;
+ return nullptr;
}
return &origBegin[2];
}
@@ -1286,7 +1283,7 @@ static const QChar *parseIp6(QString &host, const QChar *begin, const QChar *end
host += zoneId;
}
host += QLatin1Char(']');
- return 0;
+ return nullptr;
}
inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl::ParsingMode mode)
@@ -1352,7 +1349,7 @@ inline bool QUrlPrivate::setHost(const QString &value, int from, int iend, QUrl:
// check for percent-encoding first
QString s;
- if (mode == QUrl::TolerantMode && qt_urlRecode(s, begin, end, 0, 0)) {
+ if (mode == QUrl::TolerantMode && qt_urlRecode(s, begin, end, { }, nullptr)) {
// something was decoded
// anything encoded left?
int pos = s.indexOf(QChar(0x25)); // '%'
@@ -1837,7 +1834,7 @@ inline void QUrlPrivate::validate() const
\sa setUrl(), fromEncoded(), TolerantMode
*/
-QUrl::QUrl(const QString &url, ParsingMode parsingMode) : d(0)
+QUrl::QUrl(const QString &url, ParsingMode parsingMode) : d(nullptr)
{
setUrl(url, parsingMode);
}
@@ -1845,7 +1842,7 @@ QUrl::QUrl(const QString &url, ParsingMode parsingMode) : d(0)
/*!
Constructs an empty QUrl object.
*/
-QUrl::QUrl() : d(0)
+QUrl::QUrl() : d(nullptr)
{
}
@@ -1879,7 +1876,7 @@ QUrl::~QUrl()
bool QUrl::isValid() const
{
if (isEmpty()) {
- // also catches d == 0
+ // also catches d == nullptr
return false;
}
return d->validityError() == QUrlPrivate::NoError;
@@ -1907,7 +1904,7 @@ void QUrl::clear()
{
if (d && !d->ref.deref())
delete d;
- d = 0;
+ d = nullptr;
}
/*!
@@ -3266,10 +3263,10 @@ QUrl QUrl::resolved(const QUrl &relative) const
removeDotsFromPath(&t.d->path);
#if defined(QURL_DEBUG)
- qDebug("QUrl(\"%s\").resolved(\"%s\") = \"%s\"",
- qPrintable(url()),
- qPrintable(relative.url()),
- qPrintable(t.url()));
+ qDebug("QUrl(\"%ls\").resolved(\"%ls\") = \"%ls\"",
+ qUtf16Printable(url()),
+ qUtf16Printable(relative.url()),
+ qUtf16Printable(t.url()));
#endif
return t;
}
@@ -3805,7 +3802,7 @@ void QUrl::detach()
*/
bool QUrl::isDetached() const
{
- return !d || d->ref.load() == 1;
+ return !d || d->ref.loadRelaxed() == 1;
}
@@ -3994,21 +3991,21 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
return QString();
case QUrlPrivate::InvalidSchemeError: {
- QString msg = QStringLiteral("Invalid scheme (character '%1' not permitted)");
+ auto msg = QLatin1String("Invalid scheme (character '%1' not permitted)");
return msg.arg(c);
}
case QUrlPrivate::InvalidUserNameError:
- return QString(QStringLiteral("Invalid user name (character '%1' not permitted)"))
+ return QLatin1String("Invalid user name (character '%1' not permitted)")
.arg(c);
case QUrlPrivate::InvalidPasswordError:
- return QString(QStringLiteral("Invalid password (character '%1' not permitted)"))
+ return QLatin1String("Invalid password (character '%1' not permitted)")
.arg(c);
case QUrlPrivate::InvalidRegNameError:
if (errorPosition != -1)
- return QString(QStringLiteral("Invalid hostname (character '%1' not permitted)"))
+ return QLatin1String("Invalid hostname (character '%1' not permitted)")
.arg(c);
else
return QStringLiteral("Invalid hostname (contains invalid characters)");
@@ -4017,9 +4014,9 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
case QUrlPrivate::InvalidIPv6AddressError:
return QStringLiteral("Invalid IPv6 address");
case QUrlPrivate::InvalidCharacterInIPv6Error:
- return QStringLiteral("Invalid IPv6 address (character '%1' not permitted)").arg(c);
+ return QLatin1String("Invalid IPv6 address (character '%1' not permitted)").arg(c);
case QUrlPrivate::InvalidIPvFutureError:
- return QStringLiteral("Invalid IPvFuture address (character '%1' not permitted)").arg(c);
+ return QLatin1String("Invalid IPvFuture address (character '%1' not permitted)").arg(c);
case QUrlPrivate::HostMissingEndBracket:
return QStringLiteral("Expected ']' to match '[' in hostname");
@@ -4029,15 +4026,15 @@ static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &err
return QStringLiteral("Port field was empty");
case QUrlPrivate::InvalidPathError:
- return QString(QStringLiteral("Invalid path (character '%1' not permitted)"))
+ return QLatin1String("Invalid path (character '%1' not permitted)")
.arg(c);
case QUrlPrivate::InvalidQueryError:
- return QString(QStringLiteral("Invalid query (character '%1' not permitted)"))
+ return QLatin1String("Invalid query (character '%1' not permitted)")
.arg(c);
case QUrlPrivate::InvalidFragmentError:
- return QString(QStringLiteral("Invalid fragment (character '%1' not permitted)"))
+ return QLatin1String("Invalid fragment (character '%1' not permitted)")
.arg(c);
case QUrlPrivate::AuthorityPresentAndPathIsRelative:
@@ -4159,7 +4156,7 @@ QList<QUrl> QUrl::fromStringList(const QStringList &urls, ParsingMode mode)
\relates QHash
\since 5.0
*/
-uint qHash(const QUrl &url, uint seed) Q_DECL_NOTHROW
+uint qHash(const QUrl &url, uint seed) noexcept
{
if (!url.d)
return qHash(-1, seed); // the hash of an unset port (-1)
@@ -4187,7 +4184,7 @@ static QUrl adjustFtpPath(QUrl url)
static bool isIp6(const QString &text)
{
QIPAddressUtils::IPv6Address address;
- return !text.isEmpty() && QIPAddressUtils::parseIp6(address, text.begin(), text.end()) == 0;
+ return !text.isEmpty() && QIPAddressUtils::parseIp6(address, text.begin(), text.end()) == nullptr;
}
/*!
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index 5062ef7905..94269e4369 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -119,7 +119,7 @@ class QTypeInfo<QUrlTwoFlags<E1, E2> > : public QTypeInfoMerger<QUrlTwoFlags<E1,
class QUrl;
// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
-Q_CORE_EXPORT uint qHash(const QUrl &url, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT uint qHash(const QUrl &url, uint seed = 0) noexcept;
class Q_CORE_EXPORT QUrl
{
@@ -182,15 +182,13 @@ public:
QUrl(const QString &url, ParsingMode mode = TolerantMode);
QUrl &operator=(const QString &url);
#endif
-#ifdef Q_COMPILER_RVALUE_REFS
- QUrl(QUrl &&other) Q_DECL_NOTHROW : d(other.d)
+ QUrl(QUrl &&other) noexcept : d(other.d)
{ other.d = nullptr; }
- inline QUrl &operator=(QUrl &&other) Q_DECL_NOTHROW
+ inline QUrl &operator=(QUrl &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
~QUrl();
- inline void swap(QUrl &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ inline void swap(QUrl &other) noexcept { qSwap(d, other.d); }
void setUrl(const QString &url, ParsingMode mode = TolerantMode);
QString url(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
@@ -361,7 +359,7 @@ public:
static QList<QUrl> fromStringList(const QStringList &uris, ParsingMode mode = TolerantMode);
static void setIdnWhitelist(const QStringList &);
- friend Q_CORE_EXPORT uint qHash(const QUrl &url, uint seed) Q_DECL_NOTHROW;
+ friend Q_CORE_EXPORT uint qHash(const QUrl &url, uint seed) noexcept;
private:
QUrlPrivate *d;
diff --git a/src/corelib/io/qurl_p.h b/src/corelib/io/qurl_p.h
index 1b9237e58a..e75de32e03 100644
--- a/src/corelib/io/qurl_p.h
+++ b/src/corelib/io/qurl_p.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
// in qurlrecode.cpp
extern Q_AUTOTEST_EXPORT int qt_urlRecode(QString &appendTo, const QChar *begin, const QChar *end,
- QUrl::ComponentFormattingOptions encoding, const ushort *tableModifications = 0);
+ QUrl::ComponentFormattingOptions encoding, const ushort *tableModifications = nullptr);
// in qurlidna.cpp
enum AceLeadingDot { AllowLeadingDot, ForbidLeadingDot };
diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp
index 2305e66407..2f89d22660 100644
--- a/src/corelib/io/qurlidna.cpp
+++ b/src/corelib/io/qurlidna.cpp
@@ -1444,7 +1444,7 @@ static void mapToLowerCase(QString *str, int from)
{
int N = sizeof(NameprepCaseFolding) / sizeof(NameprepCaseFolding[0]);
- ushort *d = 0;
+ ushort *d = nullptr;
for (int i = from; i < str->size(); ++i) {
uint uc = str->at(i).unicode();
if (uc < 0x80) {
@@ -1474,7 +1474,7 @@ static void mapToLowerCase(QString *str, int from)
else
str->replace(--i, 2, reinterpret_cast<const QChar *>(&entry->mapping[0]), l);
i += l - 1;
- d = 0;
+ d = nullptr;
} else {
if (!d)
d = reinterpret_cast<ushort *>(str->data());
@@ -2404,7 +2404,7 @@ static const char * const idn_whitelist[] = {
};
static const size_t idn_whitelist_size = sizeof idn_whitelist / sizeof *idn_whitelist;
-static QStringList *user_idn_whitelist = 0;
+static QStringList *user_idn_whitelist = nullptr;
static bool lessThan(const QChar *a, int l, const char *c)
{
diff --git a/src/corelib/io/qurlquery.cpp b/src/corelib/io/qurlquery.cpp
index 97e7b8a4eb..36a2880bf1 100644
--- a/src/corelib/io/qurlquery.cpp
+++ b/src/corelib/io/qurlquery.cpp
@@ -145,6 +145,14 @@ QT_BEGIN_NAMESPACE
\since 5.2
*/
+/*!
+ \fn QUrlQuery(std::initializer_list<QPair<QString, QString>> list)
+
+ \since 5.13
+
+ Constructs a QUrlQuery object from the \a list of key/value pair.
+*/
+
typedef QList<QPair<QString, QString> > Map;
class QUrlQueryPrivate : public QSharedData
@@ -181,7 +189,7 @@ public:
template<> void QSharedDataPointer<QUrlQueryPrivate>::detach()
{
- if (d && d->ref.load() == 1)
+ if (d && d->ref.loadRelaxed() == 1)
return;
QUrlQueryPrivate *x = (d ? new QUrlQueryPrivate(*d)
: new QUrlQueryPrivate);
@@ -254,7 +262,7 @@ inline QString QUrlQueryPrivate::recodeToUser(const QString &input, QUrl::Compon
if (!(encoding & QUrl::EncodeDelimiters)) {
QString output;
if (qt_urlRecode(output, input.constData(), input.constData() + input.length(),
- encoding, 0))
+ encoding, nullptr))
return output;
return input;
}
@@ -282,7 +290,7 @@ void QUrlQueryPrivate::setQuery(const QString &query)
const QChar *const end = pos + query.size();
while (pos != end) {
const QChar *begin = pos;
- const QChar *delimiter = 0;
+ const QChar *delimiter = nullptr;
while (pos != end) {
// scan for the component parts of this pair
if (!delimiter && pos->unicode() == valueDelimiter)
@@ -337,7 +345,7 @@ QSharedDataPointer<QUrlQueryPrivate>::clone()
\sa setQuery(), addQueryItem()
*/
QUrlQuery::QUrlQuery()
- : d(0)
+ : d(nullptr)
{
}
@@ -348,7 +356,7 @@ QUrlQuery::QUrlQuery()
set the query with setQuery().
*/
QUrlQuery::QUrlQuery(const QString &queryString)
- : d(queryString.isEmpty() ? 0 : new QUrlQueryPrivate(queryString))
+ : d(queryString.isEmpty() ? nullptr : new QUrlQueryPrivate(queryString))
{
}
@@ -361,7 +369,7 @@ QUrlQuery::QUrlQuery(const QString &queryString)
\sa QUrl::query()
*/
QUrlQuery::QUrlQuery(const QUrl &url)
- : d(0)
+ : d(nullptr)
{
// use internals to avoid unnecessary recoding
// ### FIXME: actually do it
@@ -426,7 +434,7 @@ bool QUrlQuery::operator ==(const QUrlQuery &other) const
Returns the hash value for \a key,
using \a seed to seed the calculation.
*/
-uint qHash(const QUrlQuery &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QUrlQuery &key, uint seed) noexcept
{
if (const QUrlQueryPrivate *d = key.d) {
QtPrivate::QHashCombine hash;
@@ -454,7 +462,7 @@ bool QUrlQuery::isEmpty() const
*/
bool QUrlQuery::isDetached() const
{
- return d && d->ref.load() == 1;
+ return d && d->ref.loadRelaxed() == 1;
}
/*!
diff --git a/src/corelib/io/qurlquery.h b/src/corelib/io/qurlquery.h
index 092d002543..89d0f88059 100644
--- a/src/corelib/io/qurlquery.h
+++ b/src/corelib/io/qurlquery.h
@@ -48,9 +48,11 @@
#include <QtCore/qstringlist.h>
#endif
+#include <initializer_list>
+
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT uint qHash(const QUrlQuery &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT uint qHash(const QUrlQuery &key, uint seed = 0) noexcept;
class QUrlQueryPrivate;
class Q_CORE_EXPORT QUrlQuery
@@ -59,18 +61,23 @@ public:
QUrlQuery();
explicit QUrlQuery(const QUrl &url);
explicit QUrlQuery(const QString &queryString);
+ QUrlQuery(std::initializer_list<QPair<QString, QString>> list)
+ : QUrlQuery()
+ {
+ for (const QPair<QString, QString> &item : list)
+ addQueryItem(item.first, item.second);
+ }
+
QUrlQuery(const QUrlQuery &other);
QUrlQuery &operator=(const QUrlQuery &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QUrlQuery &operator=(QUrlQuery &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QUrlQuery &operator=(QUrlQuery &&other) noexcept { swap(other); return *this; }
~QUrlQuery();
bool operator==(const QUrlQuery &other) const;
bool operator!=(const QUrlQuery &other) const
{ return !(*this == other); }
- void swap(QUrlQuery &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QUrlQuery &other) noexcept { qSwap(d, other.d); }
bool isEmpty() const;
bool isDetached() const;
@@ -102,7 +109,7 @@ public:
private:
friend class QUrl;
- friend Q_CORE_EXPORT uint qHash(const QUrlQuery &key, uint seed) Q_DECL_NOTHROW;
+ friend Q_CORE_EXPORT uint qHash(const QUrlQuery &key, uint seed) noexcept;
QSharedDataPointer<QUrlQueryPrivate> d;
public:
typedef QSharedDataPointer<QUrlQueryPrivate> DataPtr;
diff --git a/src/corelib/io/qurlrecode.cpp b/src/corelib/io/qurlrecode.cpp
index 443ae18b21..35ede8d078 100644
--- a/src/corelib/io/qurlrecode.cpp
+++ b/src/corelib/io/qurlrecode.cpp
@@ -377,7 +377,7 @@ static int recode(QString &result, const ushort *begin, const ushort *end, QUrl:
{
const int origSize = result.size();
const ushort *input = begin;
- ushort *output = 0;
+ ushort *output = nullptr;
EncodingAction action = EncodeCharacter;
for ( ; input != end; ++input) {
@@ -692,7 +692,7 @@ qt_urlRecode(QString &appendTo, const QChar *begin, const QChar *end,
}
// qstring.cpp
-bool qt_is_ascii(const char *&ptr, const char *end) Q_DECL_NOTHROW;
+bool qt_is_ascii(const char *&ptr, const char *end) noexcept;
/*!
\internal
diff --git a/src/corelib/io/qurltlds_p.h b/src/corelib/io/qurltlds_p.h
index 5453644225..043e84e5ab 100644
--- a/src/corelib/io/qurltlds_p.h
+++ b/src/corelib/io/qurltlds_p.h
@@ -1,7 +1,7 @@
-// Version: MPL 1.1/GPL 2.0/LGPL 2.1
+// License: MPL 2.0/GPL 2.0/LGPL 3
//
// The contents of this file are subject to the Mozilla Public License Version
-// 1.1 (the "License"); you may not use this file except in compliance with
+// 2.0 (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
// http://www.mozilla.org/MPL/
//
@@ -59,14106 +59,14139 @@ QT_BEGIN_NAMESPACE
// note to maintainer:
// this file should be updated before each release ->
// for instructions see the program at
-// util/corelib/qurl-generateTLDs
+// util/corelib/qurl-generateTLDs/
-static const quint16 tldCount = 8621;
+static const quint16 tldCount = 8666;
static const quint32 tldIndices[] = {
0,
-0,
-26,
-26,
-26,
-26,
-40,
-40,
-54,
-54,
-54,
-59,
+7,
+24,
+31,
+58,
65,
-75,
-75,
-109,
-117,
-132,
-149,
-149,
-149,
-159,
-166,
-193,
-193,
-235,
-235,
-235,
-241,
-276,
-282,
-287,
-309,
-339,
-349,
-349,
-390,
-402,
-420,
-452,
-468,
-489,
-489,
-503,
-508,
-531,
-551,
-551,
-574,
-605,
-605,
-605,
-615,
-615,
-615,
-633,
-655,
-661,
-661,
-684,
-702,
-714,
-736,
+79,
+103,
+137,
+137,
+158,
+194,
+220,
+255,
+255,
+298,
+298,
+298,
+298,
+298,
+311,
+311,
+311,
+311,
+323,
+359,
+383,
+383,
+400,
+400,
+421,
+421,
+441,
+441,
+448,
+490,
+490,
+497,
+502,
+520,
+542,
+549,
+597,
+611,
+611,
+635,
+642,
+649,
+668,
+683,
+683,
+683,
+700,
+705,
+712,
+724,
+724,
+740,
765,
765,
776,
-794,
-826,
-847,
-866,
-866,
-882,
-895,
-901,
-960,
-994,
-994,
-1012,
-1012,
-1012,
-1032,
-1048,
-1048,
-1068,
-1090,
-1090,
-1090,
-1101,
-1114,
-1114,
-1133,
-1133,
-1140,
-1140,
-1147,
-1147,
-1156,
-1163,
-1163,
-1163,
-1173,
-1185,
-1185,
-1201,
-1201,
-1208,
-1225,
-1230,
-1285,
-1316,
-1374,
-1394,
-1417,
-1417,
-1417,
-1424,
-1438,
-1476,
-1532,
-1549,
-1556,
-1563,
-1570,
-1590,
-1590,
-1597,
-1604,
-1617,
-1617,
-1629,
-1629,
-1641,
-1648,
-1662,
-1662,
-1680,
-1706,
-1722,
+787,
+802,
+810,
+820,
+841,
+848,
+848,
+858,
+858,
+864,
+871,
+871,
+871,
+881,
+898,
+930,
+958,
+972,
+985,
+999,
+1006,
+1013,
+1030,
+1056,
+1063,
+1086,
+1086,
+1086,
+1093,
+1100,
+1107,
+1117,
+1117,
+1117,
+1117,
+1128,
+1153,
+1153,
+1180,
+1186,
+1186,
+1193,
+1221,
+1239,
+1239,
+1252,
+1279,
+1286,
+1286,
+1293,
+1307,
+1325,
+1348,
+1348,
+1348,
+1355,
+1355,
+1355,
+1355,
+1373,
+1395,
+1395,
+1413,
+1440,
+1440,
+1440,
+1440,
+1447,
+1457,
+1464,
+1498,
+1498,
+1498,
+1572,
+1606,
+1613,
+1613,
+1613,
+1620,
+1625,
+1632,
+1651,
+1658,
+1672,
+1688,
+1704,
+1712,
+1712,
1729,
-1745,
-1745,
+1751,
1757,
-1779,
-1779,
-1786,
-1835,
-1848,
+1771,
+1787,
+1831,
+1831,
+1831,
+1831,
1848,
-1875,
-1895,
-1895,
-1923,
-1943,
-1943,
-1950,
-2004,
-2023,
-2023,
-2030,
-2051,
-2068,
-2083,
-2100,
+1919,
+1926,
+1926,
+1926,
+1949,
+1961,
+1961,
+1981,
+2001,
+2001,
+2001,
+2009,
+2028,
+2028,
+2035,
+2054,
+2054,
+2077,
2107,
-2142,
-2155,
-2155,
-2155,
-2162,
-2174,
-2174,
-2174,
+2121,
+2137,
+2157,
2196,
2196,
-2218,
-2254,
-2281,
-2287,
-2303,
-2313,
-2313,
-2313,
-2333,
-2354,
-2367,
-2367,
-2367,
-2420,
-2442,
-2460,
-2483,
-2494,
-2513,
-2521,
-2521,
-2538,
-2545,
-2555,
-2583,
-2610,
-2610,
-2617,
-2631,
-2638,
+2217,
+2235,
+2235,
+2243,
+2243,
+2259,
+2259,
+2283,
+2290,
+2290,
+2316,
+2329,
+2356,
+2356,
+2356,
+2356,
+2356,
+2393,
+2414,
+2428,
+2428,
+2440,
+2481,
+2487,
+2487,
+2487,
+2507,
+2507,
+2507,
+2546,
+2562,
+2562,
+2580,
+2607,
+2614,
+2626,
+2649,
2649,
-2661,
-2661,
-2668,
-2699,
-2705,
-2705,
-2705,
-2712,
+2665,
+2675,
+2682,
2721,
+2731,
2737,
-2749,
-2768,
-2775,
-2792,
-2815,
-2825,
-2841,
-2841,
-2868,
-2868,
-2905,
-2905,
-2934,
-2957,
-2957,
-2975,
-3005,
-3012,
-3037,
-3046,
-3046,
-3053,
-3053,
-3066,
-3073,
-3083,
-3083,
-3105,
-3123,
-3123,
-3181,
-3226,
-3245,
-3245,
-3301,
-3323,
-3332,
-3360,
-3370,
-3370,
-3370,
-3380,
-3380,
-3387,
-3387,
-3394,
-3394,
-3394,
-3402,
-3409,
-3416,
-3431,
-3448,
+2765,
+2770,
+2770,
+2803,
+2803,
+2813,
+2833,
+2855,
+2855,
+2855,
+2863,
+2863,
+2863,
+2880,
+2888,
+2896,
+2896,
+2903,
+2903,
+2910,
+2910,
+2928,
+2928,
+2935,
+2999,
+2999,
+3031,
+3031,
+3050,
+3100,
+3141,
+3141,
+3141,
+3147,
+3185,
+3185,
+3197,
+3197,
+3234,
+3241,
+3248,
+3257,
+3272,
+3272,
+3272,
+3309,
+3328,
+3328,
+3346,
+3356,
+3356,
+3356,
+3356,
+3364,
+3392,
+3392,
+3413,
+3441,
+3465,
+3465,
+3465,
+3465,
+3482,
+3482,
+3487,
+3487,
+3487,
+3487,
+3487,
+3497,
+3497,
+3510,
+3510,
+3519,
+3519,
3519,
-3543,
-3569,
-3607,
-3607,
-3613,
-3625,
-3625,
-3682,
-3689,
-3696,
-3734,
-3750,
-3750,
-3760,
-3760,
-3769,
-3786,
-3786,
-3786,
-3793,
-3809,
-3816,
-3822,
-3829,
-3829,
-3836,
-3852,
-3852,
-3867,
-3874,
-3892,
-3892,
-3902,
-3935,
-3960,
-3980,
-4005,
-4019,
-4032,
-4059,
-4089,
-4089,
-4122,
-4122,
-4151,
-4151,
-4151,
-4151,
-4158,
-4158,
-4158,
-4158,
-4158,
-4158,
-4158,
-4173,
-4191,
-4200,
-4200,
-4224,
-4232,
-4265,
-4281,
-4288,
-4309,
-4348,
-4370,
-4377,
-4396,
-4396,
-4403,
-4403,
-4419,
-4439,
-4446,
-4462,
-4469,
-4469,
-4469,
-4476,
-4483,
-4511,
-4518,
+3519,
+3519,
+3519,
+3530,
+3530,
+3541,
+3568,
+3568,
+3568,
+3586,
+3586,
+3606,
+3627,
+3637,
+3637,
+3645,
+3667,
+3667,
+3708,
+3721,
+3740,
+3762,
+3762,
+3762,
+3762,
+3762,
+3762,
+3775,
+3775,
+3790,
+3812,
+3812,
+3818,
+3818,
+3834,
+3845,
+3881,
+3904,
+3904,
+3910,
+3937,
+3937,
+3937,
+3943,
+3950,
+3950,
+3969,
+3999,
+4017,
+4017,
+4017,
+4017,
+4033,
+4033,
+4033,
+4033,
+4098,
+4135,
+4159,
+4159,
+4159,
+4159,
+4159,
+4169,
+4189,
+4205,
+4239,
+4261,
+4261,
+4261,
+4261,
+4261,
+4261,
+4278,
+4278,
+4293,
+4308,
+4317,
+4336,
+4343,
+4371,
+4371,
+4376,
+4376,
+4376,
+4399,
+4409,
+4424,
+4451,
+4473,
+4473,
+4473,
+4489,
+4489,
+4526,
+4532,
+4532,
4538,
-4563,
-4580,
-4580,
-4587,
-4608,
-4608,
-4624,
-4640,
-4664,
-4664,
-4664,
-4680,
-4690,
-4699,
-4707,
-4707,
-4707,
-4717,
-4717,
-4741,
-4741,
-4741,
-4741,
-4766,
-4778,
-4778,
-4794,
-4801,
-4834,
-4854,
-4867,
-4874,
-4874,
-4888,
-4888,
-4888,
-4936,
-4942,
-4963,
-5001,
-5008,
-5008,
-5008,
-5008,
-5008,
-5017,
-5024,
-5062,
-5069,
-5074,
-5095,
-5139,
-5146,
-5156,
-5175,
-5182,
-5193,
+4570,
+4570,
+4570,
+4613,
+4632,
+4643,
+4688,
+4688,
+4726,
+4771,
+4783,
+4799,
+4799,
+4865,
+4865,
+4865,
+4885,
+4909,
+4909,
+4926,
+4926,
+4956,
+4994,
+5010,
+5010,
+5020,
+5041,
+5056,
+5075,
+5092,
+5122,
+5122,
+5122,
+5122,
+5130,
+5157,
+5164,
+5177,
+5194,
5200,
-5212,
-5225,
-5238,
-5261,
-5268,
-5298,
-5298,
-5305,
-5305,
-5315,
-5315,
-5329,
-5329,
-5349,
-5363,
-5363,
-5399,
-5399,
-5418,
-5445,
-5466,
+5200,
+5211,
+5224,
+5241,
+5241,
+5273,
+5273,
+5273,
+5294,
+5294,
+5294,
+5343,
+5343,
+5350,
+5386,
+5396,
+5403,
+5417,
+5449,
+5463,
+5463,
+5480,
5490,
-5505,
-5505,
-5505,
-5530,
-5530,
-5546,
-5546,
-5582,
-5610,
-5610,
-5634,
-5676,
-5676,
-5722,
-5735,
-5774,
-5774,
-5828,
-5828,
-5828,
-5828,
-5851,
-5881,
-5894,
-5894,
-5901,
-5901,
-5906,
-5906,
-5937,
+5541,
+5591,
+5597,
+5604,
+5604,
+5625,
+5639,
+5649,
+5649,
+5649,
+5666,
+5685,
+5705,
+5705,
+5705,
+5723,
+5772,
+5783,
+5790,
+5804,
+5837,
+5878,
+5915,
+5915,
+5915,
5937,
-5950,
-5950,
-5950,
-5956,
-5956,
-5956,
-5998,
-5998,
-6030,
-6055,
-6074,
-6090,
-6090,
-6103,
-6103,
-6155,
-6177,
+5984,
+5989,
+5989,
+5989,
+6006,
+6051,
+6051,
+6073,
+6080,
+6080,
+6089,
+6100,
+6149,
+6164,
+6169,
6207,
-6207,
-6214,
6214,
-6226,
-6244,
-6266,
-6303,
+6242,
+6278,
+6284,
+6290,
6303,
-6330,
-6330,
-6344,
-6360,
-6387,
-6410,
-6410,
-6410,
-6410,
-6438,
-6451,
-6451,
-6451,
-6465,
-6477,
-6477,
+6326,
+6383,
+6399,
+6416,
+6416,
+6437,
+6444,
+6457,
+6463,
+6463,
6477,
-6484,
-6500,
-6500,
-6519,
-6519,
-6530,
-6548,
-6567,
-6567,
-6567,
-6586,
-6604,
+6520,
+6535,
+6555,
+6555,
+6555,
+6555,
+6603,
6652,
6652,
-6672,
-6683,
-6716,
-6716,
-6727,
-6727,
-6727,
-6727,
-6727,
-6747,
-6747,
-6781,
-6781,
-6791,
-6821,
-6821,
-6827,
-6827,
-6843,
+6670,
+6691,
+6698,
+6698,
+6712,
+6712,
+6719,
+6719,
+6726,
+6739,
+6778,
+6778,
+6797,
+6797,
+6807,
+6807,
+6830,
+6830,
+6842,
+6865,
+6865,
+6865,
6869,
-6877,
-6877,
-6877,
-6877,
-6896,
-6896,
-6903,
-6919,
-6919,
-6919,
-6935,
-6935,
-6935,
-6935,
-6935,
-6935,
-6935,
-6966,
-6983,
-6983,
-6999,
-6999,
-6999,
-7013,
-7022,
-7022,
-7022,
-7022,
-7022,
-7022,
-7070,
-7085,
-7105,
-7105,
-7122,
-7139,
-7148,
-7162,
-7162,
-7172,
-7172,
-7210,
-7210,
-7230,
-7242,
-7242,
-7249,
-7259,
-7259,
-7279,
-7279,
-7294,
-7311,
-7317,
-7353,
-7369,
-7375,
-7395,
-7395,
-7431,
-7496,
-7496,
-7505,
-7505,
-7505,
-7505,
-7511,
-7539,
-7551,
+6875,
+6888,
+6888,
+6888,
+6910,
+6926,
+6933,
+6944,
+6964,
+6980,
+6980,
+7024,
+7024,
+7024,
+7024,
+7036,
+7058,
+7068,
+7068,
+7083,
+7087,
+7109,
+7117,
+7124,
+7143,
+7159,
+7194,
+7194,
+7194,
+7201,
+7208,
+7224,
+7231,
+7262,
+7309,
+7323,
+7352,
+7352,
+7359,
+7366,
+7366,
+7381,
+7381,
+7412,
+7412,
+7449,
+7459,
+7459,
+7487,
+7487,
+7487,
+7487,
+7527,
+7545,
+7559,
+7559,
+7559,
+7559,
+7559,
+7564,
7564,
-7583,
-7595,
-7595,
7595,
-7628,
-7628,
-7628,
-7665,
-7674,
-7686,
-7711,
-7737,
-7755,
-7755,
-7794,
-7805,
-7811,
-7811,
-7831,
-7831,
-7850,
-7850,
-7858,
-7874,
-7879,
-7903,
-7923,
-7958,
-7958,
-7972,
-7987,
-7987,
-7998,
-8008,
-8008,
-8042,
-8042,
-8059,
-8059,
-8076,
-8096,
-8096,
-8096,
-8114,
-8114,
-8132,
-8132,
-8148,
-8163,
-8175,
-8194,
-8194,
-8205,
-8214,
-8218,
-8246,
-8246,
-8246,
-8286,
-8286,
-8286,
-8286,
-8286,
+7602,
+7626,
+7643,
+7655,
+7655,
+7682,
+7701,
+7725,
+7736,
+7751,
+7765,
+7832,
+7852,
+7906,
+7965,
+7965,
+7976,
+7976,
+8024,
+8041,
+8058,
+8071,
+8084,
+8105,
+8105,
+8115,
+8144,
+8160,
+8182,
+8210,
+8216,
+8229,
+8229,
+8234,
+8282,
+8282,
+8282,
+8289,
8305,
8312,
8312,
8312,
8312,
-8335,
-8357,
-8357,
-8366,
-8382,
-8390,
-8394,
-8394,
-8407,
-8414,
-8446,
-8453,
-8466,
-8466,
-8500,
-8500,
-8522,
+8319,
+8363,
+8401,
+8408,
+8415,
+8415,
+8425,
+8454,
+8464,
+8464,
+8482,
+8505,
8542,
-8554,
-8577,
-8588,
-8608,
-8614,
-8621,
-8652,
-8675,
-8675,
-8687,
-8687,
-8712,
-8712,
-8734,
-8744,
-8798,
-8808,
-8827,
-8827,
-8827,
+8542,
+8557,
+8603,
+8629,
+8629,
+8643,
+8643,
+8667,
+8690,
+8690,
+8714,
+8721,
+8721,
+8726,
+8746,
+8766,
+8783,
+8790,
+8804,
+8833,
8840,
-8855,
-8855,
-8880,
-8880,
-8897,
-8897,
-8897,
-8930,
-8968,
-8968,
-8968,
-8968,
-8992,
-9055,
+8863,
+8870,
+8884,
+8934,
+8956,
+8956,
+8956,
+8956,
+8965,
+8991,
+8991,
+8997,
+9007,
+9007,
+9013,
+9031,
+9031,
+9038,
+9059,
+9066,
9073,
-9085,
-9094,
-9116,
+9090,
+9105,
+9109,
9116,
-9145,
-9164,
-9175,
-9187,
-9214,
-9214,
-9226,
-9242,
-9272,
-9291,
-9305,
-9324,
-9324,
-9324,
-9324,
-9331,
-9368,
-9374,
-9393,
-9415,
-9415,
-9415,
-9428,
-9428,
-9434,
-9451,
-9451,
-9451,
-9486,
-9486,
-9486,
-9486,
-9503,
-9503,
-9503,
-9509,
-9509,
-9541,
-9548,
-9548,
-9548,
-9597,
-9597,
-9604,
-9619,
-9646,
-9657,
-9664,
-9701,
-9730,
-9737,
-9743,
-9755,
-9774,
-9795,
-9802,
-9816,
-9816,
-9824,
-9847,
-9865,
-9865,
+9120,
+9120,
+9178,
+9233,
+9241,
+9259,
+9275,
+9275,
+9275,
+9292,
+9299,
+9299,
+9318,
+9332,
+9351,
+9358,
+9400,
+9422,
+9497,
+9513,
+9517,
+9517,
+9530,
+9537,
+9552,
+9592,
+9592,
+9608,
+9627,
+9643,
+9643,
+9643,
+9653,
+9653,
+9683,
+9691,
+9723,
+9733,
+9758,
+9762,
+9762,
+9762,
+9842,
+9842,
+9871,
+9871,
9890,
9904,
9911,
-9931,
-9955,
+9918,
+9932,
+9949,
9969,
-10008,
-10015,
-10032,
-10032,
-10039,
-10046,
-10065,
-10065,
-10113,
-10120,
-10128,
-10135,
-10142,
-10142,
-10167,
-10178,
-10198,
-10232,
-10251,
-10307,
-10325,
-10325,
-10325,
-10332,
-10338,
-10360,
-10372,
-10379,
-10412,
-10443,
-10443,
-10460,
-10468,
-10490,
-10490,
-10500,
-10519,
-10534,
-10541,
-10574,
-10598,
-10633,
-10653,
-10673,
-10694,
-10694,
-10694,
+10000,
+10024,
+10024,
+10055,
+10055,
+10082,
+10098,
+10098,
+10126,
+10126,
+10138,
+10138,
+10147,
+10174,
+10174,
+10174,
+10174,
+10196,
+10203,
+10210,
+10210,
+10210,
+10233,
+10245,
+10252,
+10252,
+10282,
+10289,
+10300,
+10346,
+10369,
+10375,
+10402,
+10402,
+10402,
+10402,
+10423,
+10444,
+10453,
+10473,
+10497,
+10503,
+10513,
+10531,
+10579,
+10595,
+10602,
+10602,
+10602,
+10627,
+10648,
+10659,
+10659,
+10674,
+10674,
+10681,
10706,
10706,
-10715,
-10725,
-10725,
-10736,
-10743,
-10750,
-10782,
-10798,
-10814,
-10833,
-10833,
-10848,
-10858,
-10858,
-10858,
-10863,
+10722,
+10760,
+10760,
+10772,
+10785,
+10785,
+10785,
+10796,
+10815,
+10836,
+10836,
+10844,
10875,
-10900,
-10907,
-10930,
-10961,
-10989,
-11020,
-11068,
-11075,
-11082,
-11114,
-11131,
-11156,
-11176,
-11184,
-11212,
-11218,
-11235,
-11235,
-11247,
-11247,
-11254,
-11265,
-11269,
-11304,
-11311,
-11340,
-11340,
-11354,
-11384,
-11384,
-11409,
-11409,
-11422,
-11439,
-11449,
-11449,
-11462,
-11469,
-11469,
-11477,
-11488,
-11488,
-11502,
-11522,
-11589,
-11628,
-11657,
-11670,
-11670,
+10875,
+10875,
+10875,
+10885,
+10885,
+10892,
+10892,
+10892,
+10892,
+10920,
+10920,
+10963,
+10963,
+10963,
+10970,
+10977,
+11007,
+11007,
+11007,
+11007,
+11007,
+11031,
+11041,
+11051,
+11070,
+11078,
+11078,
+11078,
+11091,
+11101,
+11101,
+11123,
+11129,
+11139,
+11155,
+11191,
+11233,
+11233,
+11233,
+11244,
+11244,
+11256,
+11262,
+11262,
+11262,
+11262,
+11278,
+11285,
+11285,
+11314,
+11335,
+11341,
+11359,
+11359,
+11387,
+11401,
+11408,
+11442,
+11442,
+11463,
+11463,
+11470,
+11492,
+11492,
+11492,
+11492,
+11503,
+11537,
+11547,
+11572,
+11572,
+11591,
+11610,
+11610,
+11618,
+11636,
+11652,
+11652,
+11652,
+11675,
+11675,
+11675,
+11675,
11699,
-11706,
-11723,
-11723,
-11763,
-11763,
-11763,
-11790,
-11825,
-11844,
-11875,
-11875,
-11891,
-11891,
-11898,
-11898,
-11898,
-11898,
-11898,
-11911,
-11911,
-11932,
-11939,
-11939,
-11946,
-11946,
-11957,
-11957,
-11964,
-11988,
-11995,
-12047,
-12110,
-12117,
-12124,
-12131,
-12131,
-12147,
-12173,
-12192,
-12228,
-12235,
-12252,
-12252,
-12284,
-12284,
-12299,
-12299,
-12312,
-12336,
-12343,
-12367,
-12374,
-12400,
-12417,
-12417,
-12437,
-12437,
-12444,
-12479,
-12513,
-12527,
-12541,
-12541,
-12564,
-12607,
-12614,
-12625,
-12632,
-12670,
-12698,
-12739,
-12753,
-12760,
-12791,
-12791,
-12791,
-12791,
-12818,
-12818,
-12818,
-12839,
-12851,
-12851,
-12851,
-12861,
+11710,
+11710,
+11738,
+11748,
+11748,
+11748,
+11768,
+11768,
+11768,
+11768,
+11768,
+11778,
+11778,
+11788,
+11812,
+11820,
+11820,
+11835,
+11852,
+11872,
+11872,
+11929,
+11929,
+11933,
+11952,
+11962,
+11962,
+11979,
+11979,
+11979,
+11992,
+11999,
+12014,
+12014,
+12023,
+12023,
+12023,
+12023,
+12023,
+12023,
+12041,
+12041,
+12066,
+12066,
+12076,
+12076,
+12076,
+12076,
+12087,
+12099,
+12114,
+12137,
+12137,
+12146,
+12166,
+12175,
+12185,
+12201,
+12220,
+12239,
+12253,
+12291,
+12304,
+12304,
+12315,
+12323,
+12342,
+12342,
+12351,
+12357,
+12361,
+12381,
+12381,
+12397,
+12424,
+12452,
+12475,
+12481,
+12481,
+12481,
+12485,
+12502,
+12535,
+12535,
+12552,
+12566,
+12570,
+12601,
+12605,
+12605,
+12611,
+12623,
+12633,
+12633,
+12642,
+12642,
+12642,
+12642,
+12646,
+12656,
+12656,
+12656,
+12656,
+12677,
+12677,
+12714,
+12720,
+12734,
+12734,
+12734,
+12751,
+12774,
+12794,
+12806,
+12806,
+12819,
+12819,
+12819,
+12819,
+12836,
+12836,
+12877,
+12877,
12877,
-12899,
-12899,
-12906,
-12906,
-12918,
-12925,
-12925,
-12925,
-12925,
-12945,
-12949,
-12968,
-12968,
-12980,
-12996,
-12996,
-13003,
-13030,
-13037,
-13044,
-13080,
-13084,
-13137,
-13156,
-13175,
-13197,
-13213,
-13220,
-13227,
-13227,
-13245,
-13245,
-13245,
-13262,
-13277,
-13304,
-13311,
-13311,
-13319,
-13319,
-13319,
-13324,
-13324,
-13324,
-13324,
-13335,
-13342,
-13342,
-13347,
-13378,
-13390,
-13408,
-13413,
-13413,
-13413,
-13420,
+12893,
+12909,
+12936,
+12936,
+12936,
+12936,
+12950,
+12950,
+12950,
+12950,
+12969,
+12974,
+13000,
+13000,
+13028,
+13034,
+13051,
+13051,
+13051,
+13051,
+13051,
+13067,
+13067,
+13071,
+13071,
+13087,
+13113,
+13164,
+13204,
+13204,
+13211,
+13226,
+13226,
+13230,
+13230,
+13260,
+13276,
+13301,
+13332,
+13340,
+13357,
+13357,
+13357,
+13374,
+13397,
+13410,
13433,
-13440,
-13447,
-13466,
-13511,
-13525,
-13537,
-13555,
-13600,
-13600,
-13618,
-13629,
-13636,
-13636,
-13679,
-13686,
-13725,
-13757,
-13757,
-13800,
-13826,
-13836,
-13847,
-13867,
-13867,
-13882,
-13911,
-13925,
-13925,
-13942,
-13954,
-13991,
-14001,
-14016,
-14057,
-14073,
-14095,
-14095,
-14104,
-14118,
-14124,
-14124,
-14130,
-14156,
-14156,
-14179,
-14201,
-14201,
+13445,
+13481,
+13503,
+13532,
+13532,
+13584,
+13602,
+13622,
+13650,
+13675,
+13682,
+13682,
+13701,
+13710,
+13721,
+13721,
+13735,
+13735,
+13771,
+13777,
+13797,
+13817,
+13817,
+13817,
+13837,
+13837,
+13842,
+13861,
+13892,
+13892,
+13937,
+13955,
+13994,
+13994,
+13994,
+14023,
+14035,
+14042,
+14052,
+14052,
+14052,
+14074,
+14074,
+14074,
+14074,
+14074,
+14082,
+14116,
+14123,
+14160,
+14174,
+14191,
+14197,
+14197,
14205,
14205,
-14209,
-14216,
-14224,
-14231,
-14249,
-14253,
+14205,
+14205,
+14205,
+14243,
+14256,
+14256,
+14256,
+14256,
+14256,
+14291,
+14291,
14291,
-14338,
-14366,
+14302,
+14302,
+14316,
+14330,
+14330,
14370,
-14375,
-14407,
-14427,
-14427,
-14434,
-14447,
-14463,
-14473,
-14473,
-14484,
-14484,
-14501,
-14501,
-14501,
-14510,
-14529,
-14543,
-14543,
-14555,
-14559,
-14585,
-14585,
-14601,
-14614,
-14618,
+14370,
+14370,
+14370,
+14387,
+14399,
+14433,
+14441,
+14458,
+14458,
+14458,
+14458,
+14458,
+14458,
+14476,
+14514,
+14527,
+14527,
+14537,
+14560,
+14590,
+14590,
+14590,
+14590,
14622,
-14642,
-14711,
-14711,
-14730,
-14730,
-14730,
-14730,
-14743,
-14764,
-14764,
-14782,
-14817,
-14829,
-14829,
-14829,
-14835,
-14839,
-14839,
-14839,
-14839,
-14851,
-14859,
-14859,
-14888,
-14888,
-14888,
+14622,
+14648,
+14648,
+14648,
+14656,
+14667,
+14687,
+14705,
+14705,
+14705,
+14705,
+14718,
+14733,
+14759,
+14766,
+14795,
+14795,
+14795,
+14795,
+14801,
+14801,
+14824,
+14832,
+14832,
+14832,
+14832,
+14832,
+14848,
+14860,
+14870,
14888,
-14927,
-14939,
-14951,
-14951,
-14971,
+14934,
+14952,
+14959,
+14977,
+14977,
+14994,
+14994,
15007,
15007,
-15018,
-15034,
-15034,
-15045,
+15007,
+15007,
+15017,
15045,
-15067,
-15106,
-15106,
-15141,
-15147,
-15163,
-15195,
-15195,
-15209,
-15209,
-15216,
-15216,
-15224,
-15224,
-15224,
-15243,
-15243,
-15243,
-15253,
-15285,
-15285,
-15306,
-15324,
-15382,
-15403,
-15403,
-15407,
-15407,
-15435,
-15435,
-15468,
-15472,
-15499,
-15516,
-15516,
+15052,
+15062,
+15072,
+15094,
+15101,
+15101,
+15125,
+15125,
+15133,
+15140,
+15164,
+15183,
+15201,
+15201,
+15207,
+15211,
+15228,
+15228,
+15242,
+15251,
+15260,
+15260,
+15266,
+15266,
+15266,
+15290,
+15290,
+15290,
+15290,
+15303,
+15317,
+15317,
+15317,
+15323,
+15323,
+15330,
+15343,
+15383,
+15390,
+15390,
+15397,
+15397,
+15397,
+15412,
+15420,
+15427,
+15451,
+15467,
+15467,
+15503,
+15509,
15528,
-15533,
-15533,
-15538,
-15538,
-15550,
-15568,
-15579,
-15603,
+15528,
+15537,
+15537,
+15537,
+15542,
+15542,
+15542,
+15558,
+15558,
+15558,
+15580,
+15580,
+15580,
15603,
-15611,
-15621,
-15621,
-15621,
-15621,
-15631,
-15647,
-15655,
-15655,
-15655,
-15655,
-15655,
-15707,
-15707,
-15713,
-15713,
-15733,
-15774,
-15774,
-15784,
-15784,
-15784,
-15784,
-15784,
-15795,
-15795,
-15800,
-15800,
-15800,
-15825,
-15825,
-15825,
-15857,
-15884,
-15884,
-15884,
-15884,
-15884,
-15903,
-15922,
-15937,
-15937,
+15615,
+15615,
+15615,
+15657,
+15690,
+15712,
+15741,
+15741,
+15757,
+15757,
+15792,
+15792,
+15819,
+15819,
+15839,
+15860,
+15867,
+15874,
+15888,
+15888,
+15900,
+15913,
+15927,
+15938,
+15938,
+15956,
+15971,
+15993,
+15993,
+15993,
+15993,
15997,
-16004,
-16019,
-16065,
-16065,
-16065,
-16086,
-16100,
-16112,
-16112,
-16129,
-16138,
-16138,
-16138,
-16153,
-16169,
+16020,
+16020,
+16033,
+16033,
+16033,
+16069,
+16069,
+16097,
+16109,
+16109,
+16109,
+16145,
+16145,
+16145,
16186,
-16186,
-16228,
-16228,
-16228,
-16259,
-16270,
-16306,
-16316,
-16322,
-16322,
-16383,
-16393,
-16393,
-16423,
-16423,
-16423,
-16433,
-16448,
-16448,
-16472,
-16472,
-16477,
-16487,
-16528,
-16537,
-16547,
-16552,
-16574,
+16230,
+16250,
+16269,
+16276,
+16283,
+16295,
+16329,
+16359,
+16391,
+16404,
+16404,
+16453,
+16470,
+16480,
+16480,
+16480,
+16499,
+16512,
+16530,
+16530,
+16541,
+16541,
+16563,
16579,
+16586,
16596,
-16603,
-16651,
-16686,
-16686,
-16686,
-16703,
-16703,
-16753,
-16753,
-16753,
-16767,
-16767,
+16618,
+16633,
+16665,
+16665,
+16690,
+16721,
+16733,
+16733,
+16740,
+16762,
+16762,
+16762,
+16762,
+16762,
+16762,
+16762,
+16762,
+16777,
+16777,
16784,
-16825,
-16832,
-16843,
-16843,
+16812,
+16830,
16851,
-16862,
-16879,
-16898,
-16898,
-16917,
-16917,
-16924,
-16932,
-16970,
-17008,
-17016,
-17034,
-17034,
-17034,
-17034,
-17063,
-17098,
-17127,
-17142,
-17142,
-17160,
-17160,
-17160,
-17160,
-17186,
-17213,
-17240,
-17254,
-17259,
-17259,
-17259,
+16870,
+16870,
+16901,
+16908,
+16908,
+16908,
+16929,
+16953,
+16953,
+16959,
+16959,
+16986,
+16986,
+16986,
+16996,
+16996,
+16996,
+16996,
+17010,
+17030,
+17050,
+17057,
+17057,
+17057,
+17057,
+17066,
+17076,
+17093,
+17093,
+17122,
+17122,
+17138,
+17138,
+17157,
+17164,
+17179,
+17179,
+17198,
+17198,
+17218,
+17236,
+17236,
+17266,
+17283,
+17294,
17294,
-17350,
-17376,
-17414,
-17443,
-17459,
-17459,
-17477,
-17482,
-17495,
-17508,
-17508,
-17515,
-17521,
-17544,
-17544,
-17544,
-17544,
-17550,
-17573,
-17580,
-17587,
-17631,
-17673,
-17673,
-17691,
-17733,
-17743,
-17762,
-17762,
-17771,
-17771,
-17771,
-17780,
-17807,
-17807,
-17840,
-17847,
-17847,
-17855,
-17867,
-17883,
-17900,
-17900,
-17924,
-17964,
-17964,
-17970,
-17970,
-17998,
-18006,
-18006,
-18006,
-18006,
-18006,
-18035,
-18084,
-18110,
-18110,
-18127,
-18135,
-18167,
-18167,
-18203,
-18203,
-18208,
-18208,
-18238,
-18238,
-18255,
-18267,
-18267,
-18298,
-18314,
-18344,
-18344,
-18352,
-18352,
-18352,
-18352,
-18392,
-18398,
-18437,
-18437,
-18449,
-18463,
-18497,
-18497,
-18546,
-18553,
-18566,
-18616,
-18647,
-18647,
-18663,
-18663,
-18663,
-18696,
-18730,
-18749,
-18749,
-18759,
-18771,
-18771,
+17294,
+17311,
+17321,
+17336,
+17336,
+17336,
+17336,
+17336,
+17347,
+17353,
+17353,
+17353,
+17353,
+17361,
+17361,
+17361,
+17361,
+17374,
+17374,
+17374,
+17388,
+17388,
+17388,
+17395,
+17411,
+17411,
+17411,
+17428,
+17440,
+17457,
+17471,
+17492,
+17492,
+17529,
+17533,
+17546,
+17546,
+17558,
+17566,
+17566,
+17566,
+17578,
+17604,
+17620,
+17650,
+17650,
+17669,
+17695,
+17695,
+17741,
+17741,
+17741,
+17769,
+17774,
+17774,
+17779,
+17785,
+17795,
+17795,
+17803,
+17819,
+17859,
+17859,
+17916,
+17916,
+17955,
+17963,
+17977,
+17977,
+18009,
+18009,
+18021,
+18044,
+18044,
+18044,
+18044,
+18044,
+18044,
+18064,
+18079,
+18079,
+18096,
+18096,
+18132,
+18138,
+18138,
+18171,
+18171,
+18171,
+18171,
+18177,
+18200,
+18220,
+18220,
+18220,
+18234,
+18234,
+18234,
+18270,
+18286,
+18332,
+18343,
+18343,
+18348,
+18367,
+18409,
+18464,
+18486,
+18493,
+18544,
+18544,
+18544,
+18550,
+18575,
+18580,
+18634,
+18646,
+18672,
+18695,
+18695,
+18695,
+18713,
+18744,
+18762,
+18762,
+18770,
+18770,
+18777,
+18781,
18785,
18785,
18785,
18785,
-18803,
-18803,
-18803,
-18803,
-18803,
-18826,
-18832,
-18832,
-18861,
-18861,
-18870,
-18887,
-18897,
+18791,
+18839,
+18850,
+18864,
+18864,
+18881,
+18881,
18897,
-18903,
+18912,
+18919,
18926,
-18933,
-18933,
-18941,
-18957,
-18983,
-19025,
-19034,
-19034,
-19055,
-19122,
-19122,
-19152,
+18944,
+18944,
+18944,
+18951,
+18951,
+18958,
+18969,
+18994,
+19010,
+19054,
+19054,
+19086,
+19097,
+19115,
+19129,
+19129,
19152,
-19163,
-19163,
-19198,
-19198,
-19198,
-19198,
-19198,
-19210,
-19218,
-19238,
-19238,
+19183,
+19189,
+19226,
+19226,
+19226,
+19226,
+19236,
+19260,
19266,
-19274,
-19303,
-19317,
-19317,
-19329,
-19329,
-19329,
-19329,
-19355,
-19355,
-19410,
-19410,
-19410,
-19433,
-19450,
-19450,
-19450,
-19463,
-19463,
-19490,
-19524,
-19531,
-19558,
-19597,
-19609,
-19609,
+19273,
+19291,
+19298,
+19298,
+19298,
+19335,
+19352,
+19352,
+19363,
+19383,
+19383,
+19399,
+19409,
+19430,
+19430,
+19447,
+19469,
+19485,
+19485,
+19493,
+19499,
+19499,
+19506,
+19506,
+19516,
+19537,
+19549,
+19588,
+19588,
19633,
-19642,
-19642,
-19642,
-19642,
-19658,
-19671,
-19703,
-19710,
-19710,
-19727,
-19741,
-19741,
-19748,
-19748,
-19748,
-19755,
-19791,
-19808,
-19827,
-19835,
-19859,
-19869,
-19869,
+19655,
+19676,
+19676,
+19720,
+19723,
+19739,
+19742,
+19745,
+19768,
+19768,
+19771,
+19788,
+19795,
+19823,
+19843,
+19850,
19869,
-19886,
-19900,
+19893,
19919,
-19931,
-19940,
-19960,
-19974,
-19983,
-20002,
-20002,
-20002,
-20002,
-20011,
-20011,
-20011,
-20018,
-20031,
-20049,
-20049,
-20049,
-20065,
+19936,
+19939,
+19942,
+19963,
+19966,
+19982,
+19995,
+20004,
+20010,
+20010,
+20045,
+20048,
+20062,
+20071,
+20071,
+20074,
20084,
-20139,
-20152,
-20159,
-20177,
-20191,
-20202,
-20202,
-20229,
-20248,
-20248,
-20254,
-20254,
-20265,
-20265,
-20275,
-20275,
-20295,
-20322,
-20322,
-20347,
-20377,
-20377,
-20377,
-20401,
-20412,
-20412,
-20419,
-20419,
-20419,
+20090,
+20108,
+20108,
+20114,
+20120,
+20147,
+20153,
+20156,
+20166,
+20169,
+20184,
+20187,
+20195,
+20210,
+20221,
+20246,
+20246,
+20246,
+20273,
+20293,
+20296,
+20313,
+20331,
+20337,
+20346,
+20362,
+20395,
+20395,
+20423,
+20423,
+20429,
+20429,
20432,
-20455,
-20462,
-20514,
-20514,
-20514,
-20582,
-20588,
-20603,
-20603,
-20603,
-20615,
-20657,
+20443,
+20465,
+20465,
+20468,
+20479,
+20479,
+20497,
+20537,
+20546,
+20558,
+20614,
+20621,
+20639,
+20639,
+20658,
+20661,
+20671,
20674,
-20691,
+20674,
+20674,
+20674,
+20677,
+20677,
+20677,
+20696,
+20699,
+20699,
+20702,
+20702,
20705,
20711,
-20711,
-20711,
+20724,
20727,
-20727,
-20727,
-20747,
-20769,
-20775,
-20775,
-20790,
-20790,
-20807,
-20826,
-20834,
-20843,
-20856,
-20859,
-20862,
-20873,
-20903,
-20926,
-20926,
-20929,
-20948,
-20982,
-21012,
-21012,
-21018,
-21024,
-21046,
-21062,
-21087,
-21117,
-21151,
-21157,
-21160,
-21166,
-21182,
-21193,
+20730,
+20753,
+20763,
+20766,
+20783,
+20783,
+20783,
+20806,
+20809,
+20819,
+20819,
+20822,
+20911,
+20944,
+20961,
+20992,
+21004,
+21014,
+21017,
+21033,
+21036,
+21036,
+21067,
+21074,
+21094,
+21119,
+21162,
+21179,
21204,
-21207,
-21223,
-21223,
-21283,
-21304,
-21310,
-21316,
-21316,
-21358,
-21364,
-21371,
-21377,
-21386,
-21386,
-21389,
-21427,
-21490,
-21493,
-21493,
-21517,
-21539,
-21545,
-21545,
+21230,
+21239,
+21250,
+21256,
+21290,
+21297,
+21297,
+21297,
+21333,
+21333,
+21349,
+21352,
+21378,
+21393,
+21411,
+21414,
+21424,
+21435,
+21438,
+21461,
+21461,
+21489,
+21504,
+21511,
+21511,
+21511,
+21511,
+21516,
+21516,
+21526,
+21529,
+21538,
+21538,
21551,
-21554,
-21592,
-21608,
-21611,
-21617,
-21636,
-21636,
-21646,
-21650,
+21606,
+21609,
+21609,
+21612,
+21634,
21662,
-21688,
-21700,
-21736,
-21739,
-21766,
+21737,
+21737,
+21756,
+21759,
21787,
-21805,
+21808,
+21811,
21814,
-21831,
-21852,
-21871,
-21884,
-21901,
-21901,
-21924,
-21932,
-21932,
-21964,
-21964,
-21967,
-21970,
-21973,
-21973,
-21973,
-22007,
-22026,
-22039,
-22056,
-22063,
-22076,
-22115,
-22152,
-22152,
-22155,
-22179,
-22179,
-22182,
-22185,
-22201,
-22204,
-22237,
-22240,
-22257,
-22257,
+21820,
+21841,
+21860,
+21860,
+21867,
+21875,
+21894,
+21900,
+21921,
+21936,
+21936,
+21945,
+21945,
+21945,
+21986,
+22001,
+22021,
+22027,
+22033,
+22059,
+22080,
+22105,
+22127,
+22130,
+22146,
+22171,
+22174,
+22202,
+22222,
+22244,
+22253,
22285,
-22288,
-22306,
-22306,
-22309,
-22322,
22325,
-22328,
-22331,
-22334,
-22334,
+22347,
22359,
-22366,
-22386,
-22399,
-22414,
-22437,
-22440,
-22450,
-22459,
-22475,
-22485,
-22488,
-22495,
+22371,
+22395,
+22401,
+22404,
+22433,
+22465,
+22465,
+22468,
+22468,
22507,
-22513,
-22513,
-22513,
-22513,
-22518,
-22518,
-22530,
-22533,
-22536,
-22539,
-22556,
-22587,
-22590,
-22605,
-22620,
-22641,
-22644,
-22644,
-22644,
-22674,
-22674,
-22685,
-22716,
-22732,
-22748,
-22748,
-22764,
+22522,
+22546,
+22546,
+22580,
+22580,
+22612,
+22615,
+22622,
+22622,
+22622,
+22634,
+22655,
+22655,
+22687,
+22699,
+22711,
+22711,
+22731,
+22734,
+22740,
22767,
-22783,
-22799,
-22799,
-22799,
-22813,
-22825,
-22838,
-22851,
-22854,
-22854,
-22854,
-22899,
-22918,
-22921,
-22921,
-22924,
-22927,
-22975,
-22978,
-22988,
-22988,
+22795,
+22798,
+22801,
+22822,
+22845,
+22883,
+22883,
+22886,
+22916,
+22919,
+22938,
+22947,
+22947,
+22962,
22994,
22997,
-23004,
-23010,
+23000,
23013,
-23016,
-23016,
-23024,
-23024,
-23035,
-23070,
-23073,
+23026,
+23029,
+23029,
+23032,
+23042,
+23042,
+23069,
+23076,
23087,
-23104,
-23119,
-23150,
-23153,
-23156,
-23173,
-23198,
-23225,
-23241,
-23256,
-23256,
-23259,
-23284,
-23324,
-23340,
-23374,
-23380,
-23383,
-23389,
-23415,
-23421,
-23429,
-23450,
-23453,
-23453,
-23456,
-23456,
-23456,
-23468,
-23485,
-23498,
-23517,
-23529,
-23536,
-23539,
-23553,
-23565,
-23571,
-23571,
-23589,
-23611,
-23611,
-23631,
-23647,
-23670,
-23670,
-23673,
-23700,
-23700,
-23706,
-23709,
-23712,
-23712,
-23715,
-23732,
-23743,
-23746,
-23761,
-23774,
-23777,
-23783,
-23783,
-23800,
-23803,
-23806,
+23094,
+23107,
+23124,
+23142,
+23149,
+23149,
+23152,
+23159,
+23159,
+23181,
+23181,
+23212,
+23219,
+23233,
+23233,
+23255,
+23265,
+23265,
+23279,
+23307,
+23339,
+23349,
+23376,
+23401,
+23451,
+23514,
+23524,
+23552,
+23555,
+23575,
+23591,
+23601,
+23604,
+23620,
+23627,
+23630,
+23640,
+23659,
+23674,
+23714,
+23747,
+23776,
+23786,
+23802,
+23809,
+23812,
23827,
-23827,
-23837,
-23844,
+23863,
+23882,
23882,
-23891,
-23907,
-23914,
-23938,
-23948,
-23948,
-23948,
-23948,
-23948,
-23948,
-23963,
-23963,
-23980,
-23989,
-24003,
-24012,
-24030,
-24036,
-24065,
+23892,
+23917,
+23949,
+23974,
+23974,
+24009,
+24039,
+24039,
+24052,
+24060,
24081,
-24102,
-24102,
-24134,
-24134,
-24137,
-24158,
-24185,
-24255,
+24100,
+24131,
+24131,
+24138,
+24138,
+24148,
+24169,
+24175,
+24233,
+24262,
+24262,
+24265,
+24272,
24278,
-24287,
-24320,
-24333,
-24350,
-24357,
-24399,
-24425,
-24464,
-24467,
-24470,
-24470,
-24470,
-24488,
-24491,
-24497,
-24500,
-24506,
-24529,
-24535,
-24563,
-24576,
-24579,
-24582,
+24300,
+24321,
+24332,
+24339,
+24349,
+24349,
+24349,
+24353,
+24370,
+24370,
+24370,
+24373,
+24376,
+24405,
+24405,
+24414,
+24454,
+24461,
+24461,
+24461,
+24461,
+24484,
+24504,
+24511,
+24543,
+24558,
+24558,
+24558,
+24571,
+24584,
24591,
-24594,
-24614,
-24614,
-24617,
-24620,
-24620,
-24623,
-24629,
-24647,
-24669,
-24669,
-24669,
-24711,
-24734,
-24753,
-24758,
-24781,
-24781,
-24805,
-24828,
-24871,
-24895,
-24895,
-24911,
-24911,
-24942,
-24952,
-24984,
-25004,
-25016,
-25029,
-25036,
-25039,
-25039,
-25039,
-25061,
-25061,
-25067,
-25094,
-25118,
-25121,
-25121,
-25121,
-25126,
-25126,
+24619,
+24626,
+24626,
+24678,
+24703,
+24714,
+24729,
+24757,
+24765,
+24769,
+24794,
+24794,
+24827,
+24827,
+24827,
+24834,
+24834,
+24834,
+24834,
+24834,
+24834,
+24852,
+24894,
+24912,
+24919,
+24919,
+24919,
+24922,
+24932,
+24966,
+24982,
+25019,
+25044,
+25059,
+25081,
+25096,
25145,
25145,
-25145,
-25145,
-25145,
-25176,
-25196,
+25162,
+25168,
+25188,
+25188,
+25188,
+25200,
+25200,
25218,
-25259,
-25259,
-25259,
-25259,
-25259,
-25269,
-25306,
-25306,
-25306,
-25313,
-25313,
-25336,
-25346,
-25356,
-25366,
-25366,
-25386,
-25386,
-25397,
-25397,
-25411,
-25439,
-25439,
-25439,
-25439,
+25226,
+25226,
+25233,
+25250,
+25250,
+25250,
+25250,
+25264,
+25264,
+25293,
+25300,
+25311,
+25333,
+25347,
+25347,
+25347,
+25364,
+25403,
+25414,
+25443,
+25460,
+25477,
+25494,
25511,
-25515,
-25515,
-25521,
-25521,
-25521,
-25521,
-25536,
-25539,
-25549,
-25549,
-25573,
-25608,
-25608,
-25608,
-25608,
-25643,
-25646,
-25646,
-25646,
-25656,
-25656,
-25656,
-25672,
-25672,
-25692,
-25709,
-25729,
-25729,
-25746,
-25766,
-25766,
-25766,
-25793,
-25793,
-25806,
-25806,
-25817,
-25847,
-25847,
-25873,
-25873,
-25884,
-25892,
-25892,
-25892,
-25892,
-25902,
-25909,
-25917,
-25917,
-25949,
-25949,
-25949,
-25953,
-25953,
-25959,
-25959,
-25974,
-25974,
-25974,
-25985,
-25992,
-26003,
-26003,
-26003,
-26003,
-26003,
-26003,
-26003,
-26019,
-26025,
-26033,
-26041,
-26053,
-26053,
-26067,
+25511,
+25522,
+25555,
+25576,
+25583,
+25623,
+25630,
+25630,
+25630,
+25630,
+25630,
+25645,
+25652,
+25659,
+25666,
+25693,
+25723,
+25763,
+25780,
+25788,
+25801,
+25801,
+25821,
+25828,
+25828,
+25835,
+25852,
+25852,
+25859,
+25859,
+25878,
+25896,
+25920,
+25937,
+25969,
+25998,
+26012,
+26049,
+26070,
26076,
-26092,
-26105,
-26105,
-26105,
-26105,
-26138,
-26163,
-26163,
-26169,
-26182,
-26200,
-26200,
-26205,
-26215,
+26088,
+26088,
+26088,
+26088,
+26088,
+26101,
+26128,
+26149,
+26158,
+26177,
+26183,
26219,
-26231,
-26231,
-26231,
-26256,
-26277,
-26277,
-26295,
-26295,
-26299,
-26329,
-26336,
-26342,
-26342,
-26366,
-26413,
-26413,
-26413,
-26434,
-26455,
-26455,
-26472,
-26472,
-26483,
-26497,
-26497,
-26497,
-26508,
-26508,
-26512,
-26532,
-26532,
-26532,
-26536,
-26536,
-26545,
-26545,
-26565,
-26565,
-26565,
-26576,
-26586,
-26595,
-26595,
-26608,
-26612,
-26612,
-26639,
-26639,
-26639,
-26639,
-26655,
-26655,
-26676,
-26676,
-26692,
-26707,
-26707,
-26707,
-26707,
-26722,
-26722,
-26730,
-26739,
-26739,
-26739,
-26739,
-26759,
-26759,
-26759,
-26769,
-26769,
-26769,
-26781,
-26796,
-26815,
-26815,
-26815,
-26826,
-26839,
-26839,
-26869,
-26873,
-26914,
-26921,
-26933,
-26950,
-26975,
-26980,
-27007,
-27007,
-27007,
-27042,
-27042,
-27042,
-27046,
-27046,
-27062,
-27070,
-27086,
-27086,
-27086,
-27098,
-27098,
-27105,
-27105,
-27133,
-27133,
-27138,
-27147,
-27147,
-27154,
-27154,
-27154,
-27154,
-27170,
-27170,
-27192,
-27269,
-27269,
-27269,
-27312,
-27312,
-27319,
-27332,
-27345,
-27393,
-27410,
-27410,
-27432,
-27452,
-27452,
-27452,
-27452,
-27452,
-27479,
-27479,
-27507,
-27507,
-27513,
-27513,
-27530,
-27535,
-27535,
-27535,
-27535,
-27535,
-27548,
-27563,
-27579,
-27601,
-27601,
-27611,
-27611,
-27624,
-27624,
-27624,
-27629,
-27648,
-27648,
-27648,
-27656,
-27656,
-27666,
-27683,
-27683,
-27683,
-27704,
-27723,
-27729,
-27729,
-27762,
-27798,
-27798,
+26236,
+26243,
+26253,
+26261,
+26268,
+26278,
+26278,
+26296,
+26307,
+26307,
+26307,
+26315,
+26378,
+26385,
+26402,
+26409,
+26439,
+26459,
+26466,
+26485,
+26485,
+26492,
+26499,
+26499,
+26511,
+26556,
+26572,
+26596,
+26621,
+26621,
+26621,
+26621,
+26659,
+26659,
+26675,
+26700,
+26716,
+26741,
+26755,
+26755,
+26755,
+26785,
+26785,
+26785,
+26825,
+26825,
+26846,
+26864,
+26891,
+26898,
+26936,
+26936,
+26951,
+26951,
+26971,
+26978,
+27008,
+27054,
+27068,
+27075,
+27089,
+27089,
+27120,
+27127,
+27127,
+27127,
+27144,
+27151,
+27169,
+27176,
+27183,
+27208,
+27225,
+27272,
+27272,
+27279,
+27308,
+27354,
+27358,
+27358,
+27374,
+27388,
+27388,
+27388,
+27395,
+27419,
+27426,
+27430,
+27465,
+27472,
+27508,
+27515,
+27529,
+27558,
+27580,
+27590,
+27590,
+27590,
+27605,
+27605,
+27615,
+27615,
+27625,
+27625,
+27625,
+27631,
+27681,
+27681,
+27688,
+27688,
+27707,
+27711,
+27742,
+27749,
+27749,
+27765,
+27793,
+27839,
+27839,
+27839,
+27849,
+27849,
27864,
27864,
-27877,
-27907,
-27946,
-27972,
-27972,
-27972,
-27983,
-27983,
-27983,
-27991,
-27998,
-28014,
+27871,
+27871,
+27871,
+27871,
+27871,
+27871,
+27884,
+27903,
+27928,
+27949,
+27949,
+27963,
+27963,
+27975,
+27982,
+27982,
+27982,
+27982,
+27982,
+28019,
+28019,
28040,
28040,
-28064,
-28064,
-28080,
-28092,
-28101,
-28101,
-28123,
-28141,
-28161,
-28168,
-28185,
-28196,
-28209,
-28238,
-28259,
-28259,
-28286,
-28304,
-28304,
-28331,
-28348,
-28348,
-28366,
-28379,
-28389,
-28398,
-28398,
-28398,
-28423,
-28449,
-28472,
-28514,
-28523,
-28523,
-28542,
-28542,
-28551,
-28551,
-28565,
-28579,
-28579,
-28589,
-28597,
-28601,
-28633,
-28633,
-28651,
-28679,
-28696,
-28759,
-28759,
-28759,
-28759,
-28759,
-28778,
-28793,
-28836,
-28842,
-28852,
-28859,
-28859,
-28885,
-28885,
-28915,
-28915,
-28915,
-28919,
-28923,
-28971,
-28971,
-28978,
-28982,
-28987,
-28991,
+28040,
+28040,
+28108,
+28134,
+28134,
+28134,
+28174,
+28183,
+28197,
+28197,
+28197,
+28220,
+28230,
+28241,
+28241,
+28257,
+28257,
+28263,
+28290,
+28290,
+28361,
+28368,
+28368,
+28368,
+28373,
+28397,
+28421,
+28433,
+28440,
+28440,
+28450,
+28450,
+28466,
+28481,
+28481,
+28490,
+28532,
+28532,
+28539,
+28548,
+28555,
+28573,
+28573,
+28603,
+28627,
+28645,
+28645,
+28658,
+28684,
+28684,
+28722,
+28749,
+28767,
+28774,
+28774,
+28788,
+28801,
+28844,
+28844,
+28844,
+28850,
+28870,
+28870,
+28877,
+28883,
+28893,
+28893,
+28893,
+28918,
+28918,
+28931,
+28931,
+28931,
+28959,
+28973,
+28973,
28991,
-29008,
-29031,
-29041,
-29081,
-29081,
-29081,
-29081,
-29088,
-29088,
-29088,
-29100,
-29110,
-29124,
-29147,
-29147,
-29147,
-29153,
-29153,
-29153,
-29175,
-29185,
-29190,
-29214,
-29231,
-29231,
-29231,
-29231,
-29237,
-29265,
+29010,
+29029,
+29038,
+29048,
+29099,
+29099,
+29109,
+29109,
+29109,
+29109,
+29109,
+29109,
+29128,
+29139,
+29162,
+29162,
+29176,
+29176,
+29194,
+29194,
+29194,
+29205,
+29205,
+29227,
+29227,
+29227,
+29227,
+29248,
+29254,
+29270,
+29270,
29302,
-29333,
-29333,
-29374,
-29421,
-29446,
-29446,
-29456,
-29456,
-29473,
-29489,
-29497,
-29497,
-29530,
-29538,
-29571,
-29602,
-29623,
-29631,
-29631,
-29642,
-29655,
-29702,
-29702,
-29702,
-29702,
-29720,
-29720,
-29731,
-29753,
-29753,
-29753,
-29765,
+29309,
+29326,
+29343,
+29359,
+29369,
+29369,
+29386,
+29411,
+29411,
+29411,
+29411,
+29452,
+29463,
+29463,
+29468,
+29468,
+29492,
+29492,
+29523,
+29535,
+29535,
+29539,
+29539,
+29546,
+29557,
+29557,
+29564,
+29570,
+29579,
+29595,
+29601,
+29608,
+29608,
+29608,
+29664,
+29683,
+29698,
+29698,
+29698,
+29698,
+29706,
+29706,
+29721,
+29746,
+29775,
29793,
-29800,
-29849,
-29884,
-29884,
-29884,
-29894,
-29919,
-29940,
-29973,
-30037,
-30037,
-30054,
-30054,
-30054,
-30054,
-30054,
-30066,
-30090,
-30103,
-30144,
-30144,
-30144,
-30165,
-30189,
-30189,
-30189,
-30189,
-30189,
-30208,
-30222,
+29813,
+29831,
+29831,
+29852,
+29852,
+29897,
+29916,
+29955,
+29971,
+29971,
+30000,
+30040,
+30040,
+30055,
+30064,
+30071,
+30071,
+30071,
+30071,
+30071,
+30088,
+30088,
+30118,
+30118,
+30130,
+30130,
+30141,
+30164,
+30171,
+30178,
+30194,
+30194,
+30204,
+30223,
30231,
-30241,
-30241,
-30259,
30269,
-30276,
-30298,
-30298,
-30298,
-30304,
-30304,
-30314,
-30314,
-30314,
-30314,
-30314,
-30314,
-30321,
-30321,
-30321,
-30321,
-30327,
-30327,
-30334,
-30340,
-30340,
-30362,
-30378,
-30385,
-30385,
-30385,
-30385,
+30308,
+30308,
+30308,
+30352,
+30374,
+30394,
+30394,
+30406,
30406,
-30412,
-30424,
-30464,
+30406,
+30414,
+30431,
+30431,
+30437,
+30443,
+30461,
+30483,
30483,
30483,
-30492,
-30498,
-30522,
-30529,
-30554,
-30554,
-30554,
-30554,
-30572,
-30572,
-30584,
-30584,
-30606,
-30626,
-30665,
-30678,
-30678,
-30697,
-30725,
+30514,
+30519,
+30553,
+30553,
+30558,
+30563,
+30563,
+30604,
+30604,
+30610,
+30610,
+30610,
+30631,
+30642,
+30646,
+30646,
+30646,
+30650,
+30650,
+30681,
+30681,
+30681,
+30698,
+30714,
+30714,
+30714,
+30714,
+30714,
+30721,
+30732,
+30732,
+30732,
+30745,
+30745,
+30751,
30765,
-30771,
-30771,
-30771,
-30791,
-30791,
-30824,
-30840,
-30844,
-30872,
-30896,
-30896,
-30922,
-30946,
-30946,
-30970,
+30782,
+30805,
+30805,
+30821,
+30821,
+30842,
+30855,
+30881,
+30881,
+30903,
+30903,
+30912,
+30965,
+30965,
+30980,
+30980,
+30980,
+30987,
30998,
-30998,
-31028,
-31047,
-31070,
-31070,
-31070,
-31076,
-31113,
-31134,
-31140,
-31151,
-31158,
+31002,
+31064,
+31075,
+31087,
+31103,
+31109,
+31109,
+31109,
+31122,
+31122,
+31122,
+31135,
+31150,
+31150,
+31165,
31165,
-31185,
-31185,
-31185,
-31203,
-31218,
-31233,
-31233,
-31233,
-31256,
-31263,
-31263,
-31287,
-31287,
-31287,
-31297,
-31309,
-31317,
-31327,
-31343,
-31353,
-31353,
-31389,
-31389,
-31389,
-31406,
-31406,
-31406,
-31423,
-31439,
-31439,
-31459,
-31469,
-31476,
-31493,
-31499,
-31515,
-31515,
-31534,
-31534,
+31175,
+31175,
+31175,
+31189,
+31220,
+31220,
+31230,
+31240,
+31274,
+31281,
+31307,
+31307,
+31313,
+31342,
+31349,
+31372,
+31413,
+31413,
+31429,
+31435,
+31435,
+31435,
+31447,
+31454,
+31454,
+31454,
+31461,
+31461,
+31488,
+31488,
+31488,
+31488,
+31488,
+31507,
+31537,
+31546,
+31546,
+31546,
31566,
-31585,
-31608,
-31608,
-31626,
-31641,
-31648,
+31590,
+31602,
+31602,
+31602,
+31622,
+31622,
31648,
-31665,
-31665,
-31665,
-31665,
-31681,
-31705,
-31746,
-31768,
-31841,
-31851,
-31927,
-31927,
-31934,
-31962,
-31986,
-31992,
-32008,
-32021,
-32021,
-32021,
-32021,
-32027,
-32027,
-32053,
-32053,
-32057,
-32088,
-32088,
-32098,
-32098,
-32098,
-32129,
-32172,
-32193,
-32208,
-32208,
-32228,
-32228,
-32248,
-32254,
-32274,
-32274,
-32287,
-32309,
-32319,
-32350,
-32355,
-32391,
-32397,
-32397,
-32412,
-32412,
-32419,
-32461,
-32468,
-32468,
-32468,
-32485,
-32485,
-32510,
-32553,
-32565,
-32578,
-32586,
-32591,
-32591,
-32595,
-32608,
-32608,
-32636,
-32636,
-32636,
-32658,
-32676,
+31677,
+31692,
+31701,
+31717,
+31728,
+31728,
+31744,
+31744,
+31754,
+31783,
+31816,
+31827,
+31827,
+31834,
+31834,
+31863,
+31884,
+31884,
+31898,
+31954,
+32001,
+32023,
+32023,
+32041,
+32054,
+32076,
+32086,
+32121,
+32128,
+32135,
+32135,
+32158,
+32188,
+32203,
+32203,
+32255,
+32255,
+32255,
+32279,
+32308,
+32346,
+32374,
+32394,
+32394,
+32394,
+32394,
+32414,
+32431,
+32431,
+32447,
+32447,
+32447,
+32462,
+32462,
+32462,
+32462,
+32505,
+32522,
+32522,
+32522,
+32539,
+32544,
+32569,
+32569,
+32569,
+32598,
+32614,
+32633,
+32633,
+32633,
+32648,
+32648,
+32659,
32680,
32680,
-32695,
-32695,
-32695,
-32695,
-32695,
+32720,
+32720,
+32726,
+32726,
32726,
32726,
-32768,
-32779,
-32804,
-32821,
-32835,
-32835,
-32835,
-32851,
-32866,
-32881,
-32881,
-32886,
-32886,
-32886,
-32893,
-32893,
-32912,
-32924,
-32935,
-32935,
-32955,
-32975,
-32993,
+32769,
+32803,
+32803,
+32803,
+32803,
+32803,
+32819,
+32819,
+32836,
+32836,
+32836,
+32856,
+32856,
+32871,
+32871,
+32889,
+32913,
+32919,
+32919,
+32919,
+32919,
+32942,
+32942,
+32942,
+32942,
+32942,
+32963,
+32984,
33012,
-33020,
-33038,
-33046,
-33069,
-33069,
-33118,
-33131,
-33131,
-33157,
-33157,
-33172,
-33177,
-33182,
-33197,
-33204,
+33018,
+33018,
+33018,
+33018,
+33034,
+33060,
+33060,
+33077,
+33110,
+33110,
+33120,
+33120,
+33144,
+33181,
+33195,
+33195,
+33195,
+33212,
+33225,
33238,
-33254,
-33281,
-33294,
-33309,
-33320,
-33360,
-33360,
-33364,
-33379,
-33379,
-33397,
-33415,
-33415,
-33415,
-33415,
-33415,
-33415,
-33441,
-33465,
+33248,
+33248,
+33248,
+33248,
+33259,
+33259,
+33259,
+33273,
+33273,
+33273,
+33273,
+33273,
+33273,
+33273,
+33273,
+33273,
+33273,
+33293,
+33303,
+33303,
+33313,
+33325,
+33325,
+33325,
+33336,
+33342,
+33347,
+33347,
+33357,
+33370,
+33403,
+33442,
+33467,
+33477,
+33477,
+33491,
+33491,
33508,
33508,
-33508,
-33525,
-33531,
-33558,
-33572,
-33572,
-33579,
-33579,
-33607,
-33636,
-33642,
-33642,
-33663,
-33663,
-33663,
-33663,
-33670,
-33670,
-33670,
-33670,
-33677,
-33677,
-33677,
-33688,
-33688,
-33688,
-33709,
-33723,
-33741,
-33741,
-33741,
-33741,
-33741,
-33741,
-33752,
-33752,
-33752,
-33771,
-33771,
-33771,
-33790,
+33560,
+33569,
+33569,
+33569,
+33589,
+33628,
+33654,
+33665,
+33681,
+33700,
+33719,
+33719,
+33742,
+33760,
+33760,
+33760,
+33760,
+33760,
+33788,
+33788,
+33804,
33804,
-33824,
-33864,
-33875,
-33886,
-33903,
-33903,
-33916,
-33928,
-33948,
-33961,
-34011,
-34048,
-34065,
-34097,
-34112,
-34112,
-34112,
-34112,
-34130,
-34148,
-34148,
-34148,
-34178,
-34191,
-34223,
-34228,
-34228,
-34260,
-34260,
-34260,
-34260,
-34282,
-34305,
-34315,
-34315,
-34336,
-34356,
-34373,
-34373,
-34379,
-34401,
-34419,
-34419,
-34419,
-34419,
-34432,
-34432,
-34438,
-34460,
-34489,
-34508,
-34515,
-34515,
-34515,
-34515,
-34537,
-34546,
-34546,
-34546,
-34546,
-34546,
-34562,
-34573,
-34573,
-34583,
-34621,
+33804,
+33830,
+33854,
+33854,
+33854,
+33860,
+33860,
+33878,
+33898,
+33898,
+33898,
+33898,
+33898,
+33941,
+33941,
+33955,
+33982,
+33982,
+34002,
+34002,
+34017,
+34030,
+34090,
+34104,
+34104,
+34140,
+34180,
+34195,
+34214,
+34214,
+34214,
+34244,
+34244,
+34263,
+34263,
+34263,
+34263,
+34263,
+34263,
+34263,
+34263,
+34279,
+34312,
+34341,
+34345,
+34351,
+34374,
+34386,
+34407,
+34407,
+34407,
+34417,
+34437,
+34437,
+34449,
+34459,
+34465,
+34484,
+34484,
+34494,
+34534,
+34556,
+34556,
+34556,
+34566,
+34576,
+34576,
+34582,
+34607,
+34607,
+34628,
34634,
-34644,
-34664,
-34664,
-34695,
-34719,
-34719,
-34762,
-34762,
-34762,
-34805,
-34811,
-34832,
-34836,
-34836,
-34836,
-34836,
-34865,
+34646,
+34646,
+34655,
+34673,
+34673,
+34686,
+34686,
+34697,
+34697,
+34714,
+34714,
+34714,
+34714,
+34714,
+34731,
+34731,
+34731,
+34731,
+34731,
+34741,
+34767,
+34767,
+34767,
+34783,
+34783,
+34792,
+34792,
+34847,
+34862,
+34876,
+34876,
+34891,
34891,
-34911,
-34916,
-34916,
-34916,
-34916,
-34933,
-34963,
-34979,
-34979,
-35021,
-35035,
-35035,
-35044,
-35055,
-35092,
-35120,
-35120,
-35120,
-35120,
-35120,
-35139,
-35179,
-35208,
-35218,
+34902,
+34919,
+34919,
+34939,
+34939,
+34939,
+34954,
+34954,
+34954,
+34954,
+34971,
+34971,
+34988,
+34988,
+34998,
+35006,
+35006,
+35006,
+35017,
+35023,
+35023,
+35028,
+35028,
+35047,
+35066,
+35066,
+35076,
+35128,
+35137,
+35158,
+35174,
+35174,
+35181,
+35181,
+35223,
35233,
-35249,
-35249,
-35298,
-35309,
-35325,
+35248,
+35258,
+35277,
+35277,
+35282,
+35300,
+35316,
+35335,
+35335,
35344,
-35344,
-35358,
-35358,
-35395,
-35410,
-35410,
-35419,
-35419,
-35419,
-35419,
+35378,
+35400,
35419,
-35451,
-35470,
-35470,
-35494,
-35523,
-35523,
-35573,
-35573,
-35597,
-35609,
-35644,
-35662,
-35662,
-35676,
-35680,
-35680,
-35680,
-35680,
-35685,
-35694,
-35694,
-35694,
-35729,
-35747,
-35747,
-35754,
-35761,
-35761,
-35771,
-35793,
-35802,
-35837,
-35889,
-35889,
-35889,
-35889,
-35899,
-35915,
-35947,
-35947,
-35947,
-35957,
-35957,
-35980,
-35986,
-35986,
-35986,
-36002,
-36050,
-36050,
-36074,
-36084,
-36092,
-36092,
-36117,
-36117,
+35433,
+35433,
+35448,
+35461,
+35477,
+35498,
+35522,
+35533,
+35554,
+35569,
+35569,
+35586,
+35595,
+35608,
+35608,
+35608,
+35618,
+35623,
+35635,
+35645,
+35645,
+35645,
+35682,
+35682,
+35682,
+35682,
+35687,
+35701,
+35705,
+35705,
+35705,
+35715,
+35715,
+35715,
+35753,
+35766,
+35808,
+35821,
+35825,
+35835,
+35857,
+35877,
+35877,
+35877,
+35888,
+35888,
+35905,
+35967,
+35967,
+35974,
+35974,
+36001,
+36027,
+36027,
+36038,
+36038,
+36054,
+36064,
+36064,
+36064,
+36083,
+36111,
+36133,
36133,
36156,
-36171,
-36184,
-36227,
-36247,
-36288,
-36288,
-36317,
-36325,
-36342,
-36342,
-36342,
-36349,
-36349,
-36369,
-36378,
-36397,
-36410,
-36410,
-36449,
-36473,
-36473,
-36488,
-36488,
-36500,
-36527,
-36538,
-36538,
-36578,
-36610,
-36632,
-36651,
-36651,
-36651,
-36651,
-36664,
-36664,
-36682,
-36682,
-36682,
-36713,
-36732,
-36732,
-36732,
-36732,
-36732,
-36745,
-36745,
-36751,
-36751,
-36770,
+36178,
+36198,
+36198,
+36198,
+36202,
+36255,
+36276,
+36282,
+36290,
+36290,
+36313,
+36334,
+36334,
+36334,
+36345,
+36411,
+36424,
+36450,
+36472,
+36472,
+36472,
+36479,
+36495,
+36511,
+36575,
+36575,
+36593,
+36593,
+36593,
+36593,
+36602,
+36616,
+36628,
+36628,
+36656,
+36672,
+36719,
+36719,
+36719,
+36719,
+36719,
+36737,
+36737,
+36737,
+36750,
+36750,
+36750,
+36758,
36770,
36770,
-36776,
-36807,
-36827,
-36827,
-36844,
-36844,
-36853,
-36863,
-36873,
-36873,
-36880,
-36880,
-36880,
-36884,
-36897,
-36928,
-36928,
-36950,
-36968,
-36973,
-36973,
-36989,
-37055,
-37055,
-37073,
-37085,
-37094,
-37106,
-37157,
-37163,
+36778,
+36778,
+36778,
+36778,
+36826,
+36835,
+36835,
+36835,
+36850,
+36850,
+36855,
+36872,
+36872,
+36903,
+36919,
+36934,
+36939,
+36939,
+36954,
+36954,
+36986,
+37016,
+37043,
+37051,
+37062,
+37062,
+37062,
+37069,
+37069,
+37069,
+37069,
+37069,
+37069,
+37069,
+37069,
+37096,
+37096,
+37115,
+37115,
+37149,
+37177,
37193,
-37232,
+37214,
+37228,
+37228,
+37228,
+37228,
+37228,
37241,
-37265,
-37265,
-37272,
-37281,
-37324,
-37359,
-37391,
-37415,
-37429,
-37429,
-37457,
-37457,
-37463,
-37463,
-37469,
-37469,
-37498,
-37498,
-37498,
-37498,
-37498,
-37498,
-37498,
-37498,
-37498,
-37515,
-37526,
-37541,
-37559,
-37597,
-37617,
-37627,
-37634,
-37668,
-37668,
-37668,
-37668,
-37699,
-37706,
-37706,
-37706,
+37245,
+37245,
+37245,
+37250,
+37250,
+37268,
+37294,
+37299,
+37314,
+37328,
+37335,
+37335,
+37372,
+37380,
+37396,
+37410,
+37416,
+37428,
+37468,
+37490,
+37511,
+37516,
+37516,
+37528,
+37528,
+37528,
+37528,
+37534,
+37534,
+37562,
+37589,
+37589,
+37589,
+37611,
+37611,
+37611,
+37625,
+37631,
+37654,
+37654,
+37654,
+37658,
+37685,
+37685,
37706,
-37715,
-37724,
-37733,
-37751,
-37767,
-37767,
+37717,
+37717,
+37717,
+37732,
+37732,
+37732,
+37758,
37783,
-37783,
-37793,
-37793,
-37793,
-37806,
-37806,
-37828,
-37841,
-37841,
-37841,
-37841,
-37866,
-37879,
-37879,
-37896,
-37903,
-37910,
-37910,
+37803,
+37822,
+37840,
+37840,
+37840,
+37840,
+37863,
+37881,
+37894,
37926,
-37971,
-37971,
-37981,
-38033,
-38082,
-38113,
-38122,
-38122,
-38122,
-38122,
-38144,
-38144,
-38144,
-38169,
-38210,
-38244,
-38284,
+37949,
+37949,
+37949,
+37970,
+37970,
+37991,
+37991,
+37991,
+37991,
+38025,
+38025,
+38025,
+38025,
+38045,
+38058,
+38058,
+38080,
+38080,
+38095,
+38095,
+38142,
+38179,
+38187,
+38211,
+38218,
+38225,
+38232,
+38277,
+38298,
+38298,
38328,
-38339,
-38339,
-38377,
-38402,
-38412,
-38429,
-38429,
-38452,
-38474,
-38481,
-38488,
-38488,
-38488,
-38488,
-38511,
-38525,
-38568,
-38568,
-38575,
-38592,
-38613,
-38629,
-38629,
-38654,
-38684,
-38684,
-38703,
-38710,
-38710,
-38735,
-38748,
-38755,
-38762,
-38776,
-38776,
-38776,
-38776,
-38776,
-38812,
-38819,
-38834,
-38847,
-38854,
-38861,
-38868,
-38868,
-38888,
-38888,
-38908,
-38908,
+38352,
+38352,
+38371,
+38371,
+38378,
+38407,
+38428,
+38448,
+38448,
+38458,
+38458,
+38458,
+38489,
+38489,
+38489,
+38489,
+38499,
+38515,
+38532,
+38532,
+38578,
+38578,
+38586,
+38606,
+38606,
+38624,
+38624,
+38624,
+38642,
+38647,
+38647,
+38658,
+38665,
+38682,
+38723,
+38767,
+38767,
+38795,
+38795,
+38801,
+38801,
+38801,
+38837,
+38837,
+38856,
+38856,
+38894,
38915,
-38926,
-38942,
-38949,
-38956,
-38956,
-38956,
-38963,
-38980,
-38980,
-39003,
-39009,
+38941,
+38965,
+38965,
+38965,
+38965,
+38992,
+39015,
39039,
-39052,
-39059,
-39077,
-39084,
-39084,
-39091,
-39091,
-39108,
-39115,
-39115,
-39150,
-39150,
-39179,
-39184,
-39184,
-39240,
-39240,
-39277,
-39284,
-39284,
-39284,
-39309,
-39351,
+39045,
+39045,
+39053,
+39058,
+39058,
+39088,
+39088,
+39118,
+39118,
+39129,
+39129,
+39129,
+39147,
+39155,
+39155,
+39178,
+39182,
+39222,
+39222,
+39230,
+39230,
+39230,
+39230,
+39238,
+39238,
+39260,
+39260,
+39260,
+39281,
+39295,
+39310,
+39328,
+39335,
+39342,
39358,
-39363,
-39395,
-39408,
-39421,
-39421,
-39427,
-39427,
-39440,
-39453,
-39461,
-39461,
-39473,
-39473,
-39473,
-39490,
-39497,
-39510,
-39510,
-39516,
-39516,
-39523,
-39523,
-39535,
-39544,
-39551,
-39561,
-39561,
-39568,
+39371,
+39386,
+39386,
+39415,
+39415,
+39422,
+39454,
+39471,
+39471,
+39471,
+39478,
+39520,
+39520,
+39534,
+39541,
+39541,
+39548,
+39548,
+39548,
39568,
-39585,
-39585,
-39592,
-39592,
-39599,
-39622,
-39622,
-39637,
-39677,
-39715,
-39736,
-39765,
-39765,
-39775,
-39793,
-39793,
-39814,
-39850,
-39864,
-39889,
-39893,
-39917,
-39927,
-39934,
-39934,
-39952,
-39959,
-39977,
-39984,
-39991,
-40009,
-40009,
-40013,
-40013,
-40032,
-40032,
-40032,
-40032,
-40032,
-40032,
-40047,
-40062,
-40078,
-40078,
-40095,
-40131,
-40137,
-40151,
-40186,
-40201,
-40208,
-40227,
-40236,
-40236,
-40243,
-40250,
-40250,
-40359,
-40366,
-40373,
+39581,
+39605,
+39613,
+39627,
+39634,
+39672,
+39699,
+39705,
+39712,
+39728,
+39741,
+39748,
+39755,
+39762,
+39799,
+39843,
+39884,
+39891,
+39905,
+39922,
+39922,
+39929,
+39936,
+39943,
+39970,
+39970,
+39970,
+39988,
+40002,
+40022,
+40026,
+40026,
+40043,
+40073,
+40097,
+40107,
+40107,
+40166,
+40178,
+40184,
+40211,
+40234,
+40260,
+40260,
+40285,
+40310,
+40310,
+40331,
+40348,
+40348,
+40362,
40380,
-40404,
-40404,
-40415,
-40422,
-40434,
-40458,
-40465,
-40472,
-40472,
-40472,
+40380,
+40394,
+40414,
+40414,
+40421,
+40421,
+40460,
40472,
+40483,
+40490,
40497,
-40502,
-40509,
-40527,
+40512,
40527,
-40540,
-40547,
-40562,
-40569,
-40584,
-40591,
-40591,
-40598,
-40605,
-40605,
-40612,
-40619,
-40630,
-40660,
-40667,
-40674,
-40690,
-40714,
-40721,
-40748,
-40763,
-40770,
-40784,
-40795,
-40827,
-40827,
-40841,
-40841,
-40870,
-40870,
-40889,
-40889,
-40889,
+40546,
+40587,
+40587,
+40587,
+40587,
+40607,
+40614,
+40614,
+40614,
+40614,
+40614,
+40635,
+40635,
+40635,
+40653,
+40673,
+40673,
+40673,
+40673,
+40673,
+40680,
+40680,
+40694,
+40708,
+40731,
+40731,
+40738,
+40757,
+40757,
+40764,
+40803,
+40812,
+40825,
+40825,
+40832,
+40838,
+40869,
+40922,
40936,
-40942,
-40952,
-40982,
-40991,
-41001,
-41017,
-41033,
-41040,
-41060,
-41073,
-41104,
-41114,
-41114,
-41149,
-41149,
-41149,
-41149,
-41149,
-41156,
-41221,
-41244,
-41266,
-41292,
-41292,
-41309,
-41309,
+40955,
+40990,
+40997,
+41010,
+41053,
+41071,
+41101,
+41107,
+41119,
+41194,
+41208,
+41208,
+41208,
+41215,
+41233,
+41265,
+41285,
+41295,
41318,
-41325,
-41361,
-41389,
-41415,
-41415,
-41442,
-41457,
-41471,
-41478,
-41478,
-41478,
-41487,
-41487,
-41502,
-41518,
-41553,
-41553,
-41575,
-41575,
-41575,
-41596,
-41596,
-41596,
-41596,
-41603,
-41603,
-41603,
-41603,
-41617,
-41625,
-41638,
-41671,
-41704,
-41721,
-41752,
-41788,
-41810,
-41828,
-41842,
-41849,
-41849,
-41859,
-41874,
-41881,
-41881,
-41881,
-41881,
-41881,
-41906,
-41919,
-41935,
-41942,
-41942,
-41959,
-41959,
-41966,
-41973,
-41980,
-41980,
-41987,
-42017,
-42024,
-42031,
-42031,
-42038,
-42045,
-42055,
-42092,
-42125,
-42144,
-42151,
-42162,
-42181,
-42192,
-42215,
-42215,
-42241,
-42255,
-42255,
-42255,
-42255,
-42255,
-42279,
+41318,
+41336,
+41356,
+41356,
+41363,
+41379,
+41407,
+41439,
+41469,
+41500,
+41500,
+41524,
+41524,
+41524,
+41524,
+41529,
+41578,
+41616,
+41616,
+41631,
+41672,
+41677,
+41711,
+41726,
+41787,
+41787,
+41787,
+41818,
+41845,
+41845,
+41845,
+41900,
+41930,
+41937,
+41937,
+41937,
+41937,
+41986,
+42025,
+42037,
+42059,
+42073,
+42080,
+42148,
+42148,
+42163,
+42179,
+42186,
+42197,
+42219,
+42226,
+42240,
+42240,
+42240,
+42259,
+42264,
+42280,
42290,
-42297,
-42315,
-42315,
-42315,
-42356,
-42356,
-42356,
-42382,
-42382,
-42389,
-42398,
-42398,
-42398,
-42408,
-42426,
-42426,
-42437,
-42443,
-42448,
-42448,
-42448,
-42470,
-42470,
-42478,
-42520,
-42546,
+42313,
+42313,
+42328,
+42346,
+42373,
+42380,
+42399,
+42406,
+42406,
+42413,
+42427,
+42476,
+42494,
+42533,
+42533,
+42540,
+42540,
42556,
-42571,
-42588,
-42594,
-42645,
-42656,
-42656,
-42656,
-42656,
-42673,
-42680,
-42680,
-42680,
-42688,
-42688,
-42719,
-42758,
-42758,
-42758,
-42768,
-42794,
-42794,
-42794,
-42806,
-42822,
-42846,
-42865,
-42865,
-42874,
-42874,
-42887,
-42887,
-42894,
-42920,
-42932,
-42932,
-42966,
-42987,
-42987,
-42987,
-43015,
-43030,
-43041,
-43041,
-43049,
-43069,
-43082,
-43082,
-43082,
-43082,
-43108,
-43125,
-43147,
-43155,
-43174,
-43180,
-43193,
-43193,
-43193,
-43193,
-43193,
-43193,
-43220,
-43232,
-43232,
-43232,
-43246,
-43262,
-43270,
-43278,
-43278,
-43278,
-43278,
-43301,
-43301,
-43320,
-43320,
-43366,
-43370,
-43388,
-43388,
-43388,
-43433,
+42567,
+42587,
+42601,
+42615,
+42622,
+42643,
+42664,
+42664,
+42664,
+42702,
+42718,
+42718,
+42734,
+42746,
+42761,
+42781,
+42793,
+42810,
+42815,
+42841,
+42890,
+42897,
+42905,
+42917,
+42924,
+42931,
+42936,
+42941,
+42951,
+42967,
+42988,
+42988,
+43012,
+43028,
+43054,
+43070,
+43123,
+43127,
+43144,
+43175,
+43199,
+43199,
+43236,
+43244,
+43244,
+43273,
+43280,
+43287,
+43302,
+43318,
+43318,
+43318,
+43331,
+43353,
+43373,
+43373,
+43390,
+43390,
+43390,
+43390,
+43425,
+43437,
+43437,
43447,
-43462,
-43462,
-43462,
-43462,
-43462,
-43495,
-43495,
-43521,
-43528,
-43528,
-43552,
-43612,
-43612,
-43632,
-43648,
-43659,
-43666,
-43693,
-43710,
-43723,
-43728,
-43757,
-43768,
-43780,
-43797,
-43797,
-43797,
-43809,
-43816,
-43821,
-43849,
-43871,
-43890,
-43923,
-43923,
-43932,
-43940,
-43940,
-43958,
-43979,
-43979,
-43979,
-43979,
-44002,
-44002,
-44002,
-44002,
-44058,
-44077,
-44099,
-44129,
-44140,
-44146,
-44146,
-44146,
-44165,
-44178,
-44178,
-44202,
-44202,
-44220,
-44238,
-44255,
-44255,
-44263,
+43464,
+43504,
+43504,
+43504,
+43504,
+43504,
+43504,
+43512,
+43587,
+43587,
+43613,
+43620,
+43620,
+43669,
+43684,
+43698,
+43711,
+43732,
+43752,
+43766,
+43773,
+43796,
+43811,
+43820,
+43840,
+43840,
+43856,
+43876,
+43891,
+43922,
+43922,
+43945,
+43970,
+43984,
+44011,
+44024,
+44024,
+44048,
+44055,
+44055,
+44060,
+44067,
+44074,
+44094,
+44094,
+44106,
+44126,
+44136,
+44149,
+44149,
+44149,
+44190,
+44232,
+44232,
+44250,
+44264,
+44264,
+44264,
44280,
-44298,
-44302,
-44302,
-44330,
-44351,
-44351,
-44363,
-44363,
-44363,
-44378,
-44385,
-44406,
+44280,
+44280,
+44303,
+44335,
+44361,
+44361,
+44398,
44406,
-44434,
-44444,
-44472,
-44472,
-44472,
-44488,
-44492,
-44523,
-44561,
-44592,
-44611,
-44611,
-44632,
-44644,
-44644,
-44651,
-44651,
-44651,
+44425,
+44425,
+44452,
+44459,
+44459,
+44459,
+44459,
+44466,
+44481,
+44516,
+44550,
+44556,
+44576,
+44576,
+44583,
+44583,
+44599,
+44621,
+44642,
44651,
-44651,
-44684,
-44684,
-44690,
-44706,
-44725,
-44731,
-44731,
-44731,
-44731,
-44746,
-44746,
-44757,
-44757,
-44757,
-44757,
-44787,
-44787,
-44787,
-44787,
-44787,
-44799,
-44812,
-44812,
-44827,
-44847,
-44856,
-44856,
-44856,
-44856,
-44884,
+44661,
+44661,
+44661,
+44679,
+44679,
+44710,
+44728,
+44740,
+44747,
+44761,
+44772,
+44795,
+44804,
+44804,
+44804,
+44804,
+44804,
+44808,
+44814,
+44814,
+44814,
+44832,
+44832,
+44832,
+44844,
+44872,
44899,
-44911,
-44911,
-44911,
-44928,
-44958,
-44958,
-44981,
-44981,
-44990,
-45012,
-45037,
-45037,
-45046,
-45046,
-45073,
-45073,
-45085,
-45096,
-45096,
-45100,
-45113,
-45123,
-45158,
+44924,
+44931,
+44931,
+44939,
+44983,
+44988,
+44988,
+44998,
+45008,
+45015,
+45015,
+45028,
+45028,
+45045,
+45045,
+45074,
+45091,
+45091,
+45091,
+45091,
+45095,
+45141,
+45141,
+45155,
+45155,
+45155,
45173,
-45206,
-45214,
-45230,
-45230,
-45258,
-45268,
-45295,
-45307,
-45307,
-45307,
-45307,
-45307,
-45307,
-45338,
-45338,
-45355,
-45372,
-45372,
-45393,
-45393,
-45393,
-45403,
-45403,
-45403,
-45414,
-45455,
-45455,
-45455,
-45455,
+45196,
+45209,
+45226,
+45238,
+45266,
+45266,
+45266,
+45266,
+45302,
+45308,
+45312,
+45312,
+45333,
+45365,
+45377,
+45386,
+45409,
+45409,
+45409,
+45409,
+45445,
45455,
-45463,
-45463,
45478,
-45497,
-45514,
-45514,
-45524,
-45540,
-45540,
-45540,
-45558,
-45558,
-45558,
-45558,
-45574,
-45574,
-45574,
-45590,
-45654,
-45674,
-45686,
-45686,
-45686,
-45705,
-45705,
-45711,
-45721,
-45732,
-45732,
-45732,
-45732,
-45732,
-45738,
-45748,
-45748,
-45769,
-45789,
-45789,
-45800,
-45837,
-45856,
-45868,
-45876,
-45885,
-45902,
-45908,
-45918,
-45918,
-45918,
-45948,
-45976,
+45478,
+45494,
+45511,
+45511,
+45511,
+45523,
+45523,
+45538,
+45538,
+45553,
+45553,
+45589,
+45589,
+45600,
+45610,
+45629,
+45657,
+45720,
+45725,
+45725,
+45755,
+45777,
+45777,
+45791,
+45814,
+45840,
+45890,
+45890,
+45890,
+45927,
+45927,
+45934,
+45934,
+45954,
+45954,
45976,
45976,
45976,
-45981,
-46009,
+45998,
+46007,
+46016,
46016,
-46027,
-46027,
-46027,
46034,
-46050,
-46090,
-46108,
-46108,
-46112,
-46119,
-46126,
-46149,
-46149,
-46149,
-46149,
+46034,
+46066,
+46081,
+46102,
+46117,
+46146,
+46146,
+46162,
+46162,
46169,
-46193,
-46193,
-46193,
-46204,
-46213,
-46222,
-46222,
-46238,
-46245,
-46257,
-46257,
-46301,
-46301,
-46322,
-46322,
-46322,
-46327,
-46345,
-46359,
+46174,
+46215,
+46215,
+46234,
+46239,
+46286,
+46286,
+46300,
+46313,
+46370,
+46370,
+46370,
46374,
-46384,
-46417,
-46417,
-46428,
-46458,
-46458,
-46458,
-46493,
-46493,
-46500,
-46505,
-46555,
-46567,
-46567,
-46580,
-46580,
-46580,
-46595,
-46595,
-46595,
-46595,
-46628,
-46628,
-46652,
-46652,
-46669,
-46669,
-46698,
-46718,
-46718,
-46718,
-46738,
-46753,
-46761,
-46776,
-46776,
-46776,
+46379,
+46393,
+46401,
+46416,
+46416,
+46446,
+46467,
+46482,
+46482,
+46496,
+46538,
+46538,
+46581,
+46581,
+46629,
+46629,
+46629,
+46640,
+46644,
+46649,
+46649,
+46659,
+46659,
+46673,
+46700,
+46731,
+46731,
+46731,
+46741,
+46766,
+46766,
+46771,
+46771,
+46782,
46794,
46794,
-46802,
-46816,
-46846,
-46863,
-46899,
-46899,
-46899,
-46907,
-46907,
-46917,
-46930,
-46957,
-46957,
-46961,
-46961,
-46969,
-46975,
-46975,
-46975,
-46991,
-46999,
-46999,
-47012,
-47018,
-47018,
-47048,
-47058,
-47076,
-47145,
-47145,
-47162,
-47183,
-47228,
-47244,
-47267,
-47267,
-47295,
-47295,
-47295,
-47316,
-47316,
-47316,
-47353,
-47361,
-47385,
-47385,
-47415,
-47419,
-47430,
-47450,
-47465,
-47470,
-47470,
-47470,
-47470,
-47479,
-47501,
-47521,
-47529,
-47536,
-47554,
-47572,
-47572,
-47597,
-47606,
-47614,
-47614,
-47614,
-47623,
-47623,
-47660,
-47660,
-47669,
-47681,
-47694,
-47694,
-47694,
-47698,
-47702,
-47720,
-47720,
-47730,
-47749,
-47767,
-47790,
-47808,
-47824,
-47824,
-47824,
-47830,
-47830,
-47836,
-47869,
-47869,
-47875,
-47898,
-47898,
-47958,
-47962,
-47978,
-47978,
-47985,
-48019,
-48023,
-48023,
-48023,
-48023,
-48043,
-48043,
-48058,
-48058,
-48058,
-48058,
+46812,
+46812,
+46828,
+46851,
+46851,
+46851,
+46851,
+46851,
+46855,
+46868,
+46875,
+46875,
+46886,
+46890,
+46925,
+46925,
+46925,
+46936,
+46954,
+46972,
+46972,
+46972,
+46998,
+47068,
+47068,
+47068,
+47098,
+47107,
+47122,
+47128,
+47151,
+47156,
+47156,
+47170,
+47177,
+47182,
+47193,
+47200,
+47226,
+47226,
+47253,
+47273,
+47283,
+47283,
+47290,
+47303,
+47303,
+47303,
+47320,
+47327,
+47327,
+47335,
+47335,
+47344,
+47344,
+47356,
+47356,
+47360,
+47360,
+47369,
+47394,
+47425,
+47425,
+47425,
+47443,
+47466,
+47466,
+47481,
+47495,
+47513,
+47513,
+47532,
+47532,
+47543,
+47590,
+47603,
+47613,
+47618,
+47618,
+47635,
+47641,
+47641,
+47679,
+47727,
+47740,
+47753,
+47769,
+47779,
+47801,
+47809,
+47829,
+47859,
+47859,
+47878,
+47885,
+47906,
+47906,
+47906,
+47940,
+47950,
+47950,
+47950,
+47950,
+47984,
+47991,
+47991,
+47991,
+47991,
+48029,
+48029,
+48029,
+48038,
+48038,
+48038,
+48055,
+48055,
48065,
-48070,
-48101,
-48101,
-48116,
-48127,
-48127,
-48139,
-48139,
-48163,
-48163,
-48177,
-48177,
-48204,
-48218,
-48246,
-48262,
-48262,
-48262,
-48283,
-48283,
-48306,
-48306,
-48312,
-48312,
-48317,
-48331,
-48347,
-48354,
-48364,
-48364,
-48364,
-48394,
-48447,
-48452,
-48452,
-48476,
-48476,
-48476,
-48542,
-48572,
-48582,
-48622,
-48658,
-48669,
-48669,
-48669,
-48686,
-48686,
-48686,
-48693,
-48693,
-48699,
-48724,
-48741,
+48065,
+48065,
+48065,
+48105,
+48105,
+48123,
+48138,
+48164,
+48179,
+48179,
+48179,
+48205,
+48211,
+48250,
+48310,
+48343,
+48368,
+48368,
+48374,
+48381,
+48397,
+48397,
+48397,
+48406,
+48426,
+48426,
+48439,
+48458,
+48458,
+48485,
+48485,
+48494,
+48520,
+48532,
+48578,
+48595,
+48608,
+48608,
+48608,
+48623,
+48636,
+48636,
+48636,
+48636,
+48648,
+48687,
+48703,
+48711,
+48727,
48741,
-48752,
-48764,
-48784,
-48784,
-48794,
-48799,
-48799,
-48799,
-48799,
-48820,
-48830,
-48866,
-48884,
-48894,
-48913,
-48913,
-48913,
-48913,
-48925,
-48966,
-48975,
+48746,
+48746,
+48746,
+48746,
+48746,
+48746,
+48771,
+48771,
+48771,
+48806,
+48847,
+48847,
+48847,
+48847,
+48847,
+48886,
+48886,
+48886,
+48886,
+48886,
+48886,
+48899,
+48933,
+48933,
+48933,
48975,
-48975,
-48980,
-48987,
-49020,
-49028,
-49054,
-49060,
-49060,
-49086,
-49110,
-49110,
-49121,
-49121,
-49121,
-49134,
-49134,
-49134,
-49141,
+48979,
+48986,
+48986,
+49019,
+49019,
+49019,
+49040,
+49040,
+49040,
+49059,
+49076,
+49103,
+49103,
+49132,
+49132,
+49132,
+49132,
+49132,
+49132,
+49154,
49171,
-49185,
-49197,
-49228,
-49254,
-49254,
-49286,
-49302,
-49315,
-49315,
-49353,
-49362,
+49191,
+49216,
+49226,
+49264,
+49264,
+49278,
+49278,
+49301,
+49340,
+49340,
+49360,
+49370,
+49370,
49374,
-49385,
-49412,
+49381,
+49381,
+49399,
+49406,
49419,
-49447,
-49447,
-49489,
-49514,
-49526,
-49526,
-49559,
-49559,
-49603,
-49615,
-49655,
-49667,
-49667,
-49682,
-49699,
-49743,
-49743,
-49755,
+49428,
+49428,
+49464,
+49464,
+49497,
+49497,
+49497,
+49497,
+49501,
+49501,
+49501,
+49518,
+49548,
+49548,
+49579,
+49594,
+49619,
+49619,
+49639,
+49665,
+49665,
+49665,
+49665,
+49671,
+49671,
+49671,
+49686,
+49686,
+49686,
+49701,
+49701,
+49701,
+49724,
+49738,
49755,
49755,
-49768,
-49778,
-49799,
-49816,
-49816,
-49816,
-49822,
-49822,
-49835,
-49854,
-49872,
-49872,
-49872,
-49882,
-49882,
-49945,
-49969,
-49978,
-49993,
-49993,
+49765,
+49785,
+49795,
+49807,
+49807,
+49842,
+49862,
+49862,
+49876,
+49899,
+49899,
+49899,
+49929,
+49929,
+49929,
+49959,
+49959,
+49959,
+49990,
+49994,
+50012,
50028,
-50044,
-50054,
-50076,
-50083,
-50108,
-50108,
-50120,
-50120,
-50143,
-50143,
-50202,
-50202,
-50214,
+50071,
+50071,
+50081,
+50081,
+50081,
+50091,
+50099,
+50139,
+50139,
+50139,
+50139,
+50156,
+50184,
+50209,
+50209,
+50209,
+50216,
+50216,
+50223,
+50231,
+50231,
+50231,
+50231,
+50251,
50265,
-50279,
-50279,
-50291,
-50291,
-50316,
-50366,
-50366,
-50387,
-50387,
-50387,
-50387,
-50387,
-50405,
-50405,
-50425,
-50425,
-50432,
-50432,
-50432,
-50439,
-50439,
-50463,
-50470,
-50470,
-50470,
-50470,
-50474,
-50486,
-50495,
-50495,
-50518,
-50518,
-50518,
-50533,
-50558,
-50579,
-50579,
-50601,
-50611,
-50645,
-50674,
-50674,
-50692,
-50729,
-50748,
-50784,
-50784,
-50801,
-50814,
-50831,
-50831,
-50831,
-50831,
-50844,
+50273,
+50295,
+50311,
+50311,
+50330,
+50330,
+50339,
+50348,
+50373,
+50373,
+50406,
+50406,
+50406,
+50422,
+50422,
+50433,
+50494,
+50526,
+50542,
+50542,
+50542,
+50542,
+50542,
+50552,
+50552,
+50586,
+50586,
+50586,
+50612,
+50619,
+50619,
+50644,
+50659,
+50659,
+50676,
+50676,
+50676,
+50676,
+50676,
+50723,
+50736,
+50736,
+50736,
+50736,
+50755,
+50778,
+50778,
+50778,
+50785,
+50785,
+50793,
+50815,
+50856,
50856,
-50860,
-50872,
+50874,
+50886,
50909,
-50921,
-50921,
-50964,
-50964,
-50986,
-51006,
-51006,
-51006,
-51021,
-51021,
-51029,
-51035,
-51047,
-51058,
-51058,
-51062,
-51089,
-51089,
-51120,
-51120,
-51120,
-51126,
-51126,
-51139,
-51139,
-51153,
-51153,
-51153,
-51153,
-51165,
-51186,
-51186,
-51208,
-51247,
-51247,
-51247,
-51261,
-51273,
-51273,
-51298,
-51298,
-51298,
-51321,
-51321,
-51321,
-51338,
-51343,
-51371,
-51395,
-51417,
-51417,
-51417,
-51426,
-51426,
-51426,
-51445,
-51455,
-51469,
-51469,
-51488,
-51492,
-51492,
-51511,
-51529,
-51529,
-51549,
-51549,
-51564,
-51583,
-51611,
-51622,
-51644,
-51644,
-51644,
-51656,
-51674,
-51674,
+50918,
+50973,
+50998,
+51014,
+51030,
+51030,
+51030,
+51036,
+51036,
+51046,
+51072,
+51072,
+51078,
+51118,
+51118,
+51118,
+51118,
+51134,
+51182,
+51203,
+51219,
+51219,
+51230,
+51240,
+51240,
+51260,
+51260,
+51260,
+51260,
+51260,
+51260,
+51260,
+51275,
+51275,
+51301,
+51358,
+51374,
+51386,
+51393,
+51402,
+51402,
+51402,
+51441,
+51471,
+51507,
+51507,
+51531,
+51547,
+51547,
+51571,
+51571,
+51571,
+51571,
+51571,
+51571,
+51587,
+51612,
+51626,
+51642,
+51665,
+51681,
+51681,
+51681,
+51681,
51700,
-51733,
-51741,
-51768,
-51822,
-51829,
-51850,
-51850,
-51857,
-51857,
+51713,
+51734,
+51742,
+51746,
+51746,
+51746,
+51759,
+51759,
+51799,
+51799,
+51811,
+51811,
+51816,
+51816,
+51851,
+51851,
51867,
-51874,
-51874,
-51874,
-51874,
-51888,
-51910,
-51938,
-51945,
-51958,
-51976,
-51990,
-51990,
+51879,
+51879,
+51885,
+51902,
+51918,
+51940,
+51940,
+51946,
+51966,
+51997,
52007,
-52033,
-52043,
-52055,
-52055,
-52095,
-52111,
-52123,
-52128,
-52128,
-52147,
-52153,
-52175,
-52199,
-52223,
-52223,
-52223,
-52223,
-52223,
-52223,
-52262,
-52283,
-52324,
-52346,
-52346,
-52380,
-52380,
+52018,
+52018,
+52049,
+52049,
+52049,
+52064,
+52064,
+52084,
+52104,
+52130,
+52168,
+52204,
+52236,
+52249,
+52249,
+52276,
+52276,
+52309,
+52328,
+52328,
+52338,
+52364,
+52364,
+52377,
52395,
-52395,
-52407,
-52407,
-52419,
-52426,
-52439,
-52483,
-52495,
-52495,
-52514,
-52514,
-52523,
-52523,
-52535,
-52559,
-52559,
-52563,
-52563,
-52582,
-52594,
-52644,
-52661,
-52661,
-52720,
-52732,
-52740,
-52740,
-52740,
-52740,
-52759,
-52782,
-52809,
-52809,
-52821,
-52833,
-52853,
-52853,
-52853,
-52887,
-52899,
-52903,
-52930,
-52930,
-52942,
-52942,
-52972,
-53012,
-53012,
-53054,
-53066,
+52402,
+52418,
+52441,
+52441,
+52485,
+52524,
+52524,
+52567,
+52567,
+52567,
+52567,
+52614,
+52628,
+52628,
+52642,
+52654,
+52680,
+52699,
+52760,
+52765,
+52765,
+52765,
+52785,
+52785,
+52785,
+52785,
+52806,
+52832,
+52832,
+52871,
+52871,
+52885,
+52885,
+52892,
+52911,
+52935,
+52958,
+52976,
+52996,
+53005,
+53005,
+53022,
+53022,
+53022,
53066,
-53066,
-53092,
-53106,
-53124,
+53081,
+53088,
+53102,
+53109,
+53109,
+53120,
53124,
-53131,
-53171,
-53176,
-53176,
-53176,
-53176,
-53186,
-53186,
-53210,
-53230,
-53230,
-53230,
-53240,
-53277,
-53291,
-53291,
-53291,
-53302,
-53320,
-53320,
-53347,
-53347,
-53364,
-53378,
-53382,
-53399,
-53424,
-53437,
-53437,
-53437,
-53470,
-53470,
-53470,
-53477,
-53477,
-53484,
-53484,
-53484,
-53499,
-53499,
-53499,
-53504,
-53510,
-53528,
-53528,
-53528,
-53537,
-53537,
-53537,
-53542,
+53158,
+53174,
+53174,
+53185,
+53185,
+53221,
+53249,
+53256,
+53256,
+53285,
+53290,
+53309,
+53309,
+53309,
+53317,
+53322,
+53322,
+53322,
+53360,
+53369,
+53369,
+53369,
+53386,
+53405,
+53405,
+53405,
+53412,
+53432,
+53444,
+53464,
+53472,
+53494,
+53494,
+53494,
+53531,
53547,
-53570,
-53576,
-53601,
-53601,
-53606,
+53547,
+53547,
+53547,
+53556,
+53556,
+53556,
+53556,
+53556,
+53564,
+53587,
53606,
-53625,
-53625,
-53643,
-53650,
-53686,
-53686,
-53693,
-53724,
-53743,
-53759,
-53764,
-53764,
-53774,
+53610,
+53628,
+53651,
+53651,
+53667,
+53667,
+53674,
+53674,
+53681,
+53697,
+53701,
+53701,
+53722,
+53722,
+53729,
+53741,
+53749,
+53749,
+53749,
+53749,
+53765,
53774,
-53794,
-53800,
-53835,
-53851,
-53851,
-53871,
-53892,
-53917,
-53917,
-53925,
-53925,
-53925,
-53973,
-53973,
-53977,
+53785,
+53799,
+53799,
+53821,
+53831,
+53847,
+53902,
+53902,
+53902,
+53902,
+53941,
+53962,
+53972,
+53972,
53998,
-54018,
-54036,
-54054,
-54062,
-54123,
-54123,
-54123,
-54142,
-54194,
-54194,
-54208,
+54016,
+54033,
+54049,
+54066,
+54066,
+54079,
+54089,
+54089,
+54089,
+54096,
+54118,
+54139,
+54163,
+54179,
+54184,
+54210,
54232,
-54242,
-54259,
-54259,
-54268,
-54275,
-54282,
-54305,
-54312,
-54335,
-54348,
-54355,
-54369,
-54369,
-54369,
-54382,
-54382,
-54382,
-54410,
-54436,
-54456,
-54456,
-54456,
-54463,
-54463,
-54472,
-54497,
-54537,
+54254,
+54278,
+54278,
+54292,
+54325,
+54337,
+54371,
+54396,
+54421,
+54434,
+54455,
+54462,
+54495,
+54507,
+54507,
+54523,
+54542,
+54552,
+54552,
+54552,
+54552,
+54552,
+54559,
+54559,
54569,
-54591,
-54591,
-54591,
-54591,
-54617,
-54617,
-54664,
-54664,
-54664,
-54664,
-54693,
-54700,
-54700,
-54736,
-54746,
-54771,
-54782,
-54804,
-54850,
-54868,
-54901,
-54901,
-54921,
-54921,
-54921,
-54960,
-54987,
-54993,
-55000,
-55000,
-55028,
+54620,
+54692,
+54710,
+54721,
+54721,
+54759,
+54773,
+54787,
+54787,
+54803,
+54808,
+54834,
+54834,
+54848,
+54848,
+54848,
+54855,
+54855,
+54879,
+54891,
+54891,
+54891,
+54891,
+54900,
+54910,
+54949,
+54962,
+54978,
+54978,
+54985,
+55005,
+55018,
+55037,
55037,
+55044,
+55049,
+55049,
+55056,
55066,
-55118,
-55133,
-55133,
-55133,
-55138,
-55138,
-55138,
-55138,
-55138,
-55159,
-55191,
-55191,
-55191,
-55226,
-55232,
-55232,
-55242,
-55257,
-55257,
-55270,
-55270,
-55270,
-55298,
-55317,
-55317,
-55317,
-55317,
-55317,
-55317,
-55331,
-55350,
-55350,
-55350,
+55073,
+55081,
+55143,
+55151,
+55161,
+55168,
+55190,
+55196,
+55213,
+55213,
+55230,
+55237,
+55247,
+55267,
+55272,
+55279,
+55279,
+55286,
+55306,
+55334,
+55341,
+55348,
+55354,
55363,
-55387,
-55387,
-55411,
-55411,
-55422,
-55435,
-55481,
-55490,
-55502,
-55502,
+55363,
+55378,
+55386,
+55395,
+55432,
+55432,
+55437,
+55446,
+55458,
+55479,
55502,
-55520,
+55512,
+55512,
55532,
-55554,
-55563,
-55570,
-55585,
-55585,
-55603,
-55610,
-55610,
-55662,
-55662,
-55684,
-55700,
-55707,
-55707,
-55749,
-55765,
-55784,
-55784,
-55784,
-55791,
-55791,
-55791,
-55816,
-55823,
-55852,
-55852,
-55906,
-55941,
-55971,
-55971,
-55978,
-55978,
-55978,
-55987,
-56011,
-56018,
-56024,
-56024,
-56024,
-56055,
-56071,
-56071,
-56078,
-56078,
-56085,
-56092,
-56122,
-56141,
-56141,
-56141,
-56141,
-56146,
-56146,
-56155,
-56178,
-56209,
-56238,
-56257,
-56257,
-56257,
-56262,
-56275,
-56275,
-56275,
-56275,
-56290,
-56307,
-56323,
-56341,
-56341,
-56347,
-56366,
-56375,
-56375,
-56375,
-56375,
-56413,
-56445,
-56450,
-56450,
-56450,
-56454,
+55543,
+55565,
+55573,
+55580,
+55580,
+55618,
+55638,
+55645,
+55657,
+55657,
+55657,
+55691,
+55708,
+55708,
+55708,
+55708,
+55729,
+55735,
+55758,
+55758,
+55767,
+55772,
+55820,
+55830,
+55830,
+55854,
+55854,
+55866,
+55886,
+55886,
+55886,
+55886,
+55910,
+55910,
+55914,
+55929,
+55939,
+55965,
+56006,
+56025,
+56037,
+56037,
+56037,
+56064,
+56115,
+56115,
+56128,
+56133,
+56133,
+56133,
+56133,
+56133,
+56140,
+56140,
+56140,
+56151,
+56177,
+56205,
+56205,
+56219,
+56219,
+56219,
+56236,
+56250,
+56250,
+56250,
+56260,
+56264,
+56271,
+56271,
+56283,
+56292,
+56312,
+56329,
+56338,
+56338,
+56338,
+56364,
+56371,
+56382,
+56382,
+56389,
+56389,
+56389,
+56417,
+56417,
+56417,
+56417,
+56417,
+56437,
+56437,
+56444,
+56460,
56460,
-56467,
-56490,
-56510,
-56517,
-56527,
-56534,
-56534,
-56534,
-56565,
-56577,
-56577,
-56584,
-56608,
-56608,
-56615,
-56615,
-56640,
-56658,
-56658,
-56658,
-56677,
-56677,
-56701,
-56701,
-56722,
-56750,
-56757,
-56757,
-56802,
-56802,
-56802,
-56821,
-56839,
-56863,
-56863,
+56474,
+56503,
+56511,
+56524,
+56594,
+56599,
+56659,
+56685,
+56700,
+56707,
+56707,
+56738,
+56761,
+56774,
+56785,
+56792,
+56805,
+56829,
+56829,
+56840,
+56868,
+56868,
+56868,
+56868,
56874,
56874,
-56905,
-56941,
-56976,
-57006,
-57006,
-57025,
-57032,
-57037,
-57037,
-57061,
-57061,
-57067,
-57067,
-57074,
-57093,
-57131,
-57138,
+56874,
+56874,
+56881,
+56881,
+56893,
+56922,
+56934,
+56934,
+56944,
+56944,
+56944,
+56944,
+56965,
+56973,
+57005,
+57081,
+57126,
57138,
-57158,
-57158,
-57158,
-57169,
-57169,
-57177,
-57191,
-57191,
-57191,
-57191,
-57226,
-57248,
-57261,
-57278,
-57306,
-57306,
-57329,
-57329,
-57349,
-57349,
-57356,
-57356,
-57409,
-57416,
-57422,
-57422,
-57446,
-57463,
-57463,
-57463,
-57487,
-57507,
-57507,
-57507,
-57528,
-57528,
-57528,
-57535,
-57542,
-57542,
-57578,
-57578,
-57592,
-57592,
-57598,
-57598,
-57645,
+57159,
+57175,
+57199,
+57216,
+57216,
+57222,
+57222,
+57222,
+57237,
+57259,
+57282,
+57282,
+57296,
+57312,
+57312,
+57341,
+57397,
+57405,
+57442,
+57442,
+57442,
+57456,
+57466,
+57482,
+57500,
+57512,
+57537,
+57537,
+57575,
+57575,
+57575,
+57582,
+57609,
+57633,
57651,
-57665,
-57665,
-57684,
-57684,
-57692,
-57692,
-57692,
-57709,
-57724,
-57724,
-57766,
-57766,
-57773,
-57773,
-57780,
-57780,
-57797,
-57842,
-57842,
-57842,
-57842,
-57852,
-57852,
-57852,
+57688,
+57714,
+57767,
+57775,
+57783,
+57783,
+57810,
+57849,
+57856,
57869,
-57882,
-57899,
-57899,
-57936,
-57943,
-57943,
-57973,
-57989,
-58001,
-58001,
-58001,
-58001,
-58024,
-58024,
-58024,
-58024,
-58051,
-58051,
-58051,
-58082,
-58091,
-58091,
-58091,
-58097,
-58097,
-58097,
-58130,
-58130,
-58130,
-58130,
-58130,
-58150,
-58150,
-58166,
-58166,
-58171,
-58171,
-58203,
-58209,
-58216,
-58229,
-58235,
-58242,
-58249,
-58260,
-58267,
-58322,
-58332,
-58372,
-58372,
-58384,
-58384,
-58384,
-58405,
-58430,
-58449,
-58476,
-58492,
-58492,
-58499,
-58506,
-58520,
-58554,
-58560,
-58579,
-58595,
-58627,
-58651,
-58651,
-58651,
+57889,
+57916,
+57941,
+57941,
+57941,
+57948,
+57956,
+57974,
+57996,
+58017,
+58048,
+58048,
+58048,
+58048,
+58070,
+58070,
+58094,
+58151,
+58192,
+58224,
+58224,
+58224,
+58224,
+58263,
+58263,
+58273,
+58283,
+58314,
+58356,
+58356,
+58363,
+58363,
+58363,
+58380,
+58396,
+58396,
+58417,
+58417,
+58417,
+58423,
+58423,
+58450,
+58461,
+58461,
+58470,
+58470,
+58514,
+58514,
+58537,
+58544,
+58557,
+58557,
+58557,
+58557,
+58557,
+58591,
+58615,
+58636,
+58636,
58658,
58679,
58686,
58686,
58686,
-58714,
-58714,
-58728,
-58735,
-58753,
-58753,
-58770,
-58777,
-58842,
-58842,
-58859,
-58879,
-58886,
-58886,
-58940,
-58940,
-58964,
-58964,
-58982,
-58988,
-59002,
-59032,
-59056,
-59067,
-59083,
-59112,
-59112,
-59121,
-59152,
-59152,
+58700,
+58717,
+58732,
+58739,
+58739,
+58745,
+58752,
+58762,
+58784,
+58811,
+58825,
+58832,
+58839,
+58863,
+58899,
+58905,
+58912,
+58912,
+58912,
+58939,
+58939,
+58939,
+58960,
+58973,
+58973,
+58973,
+58973,
+58973,
+58980,
+58980,
+58987,
+58994,
+59012,
+59012,
+59019,
+59055,
+59110,
+59110,
+59110,
+59110,
+59135,
+59153,
+59153,
59180,
-59185,
-59192,
-59192,
-59192,
-59219,
-59229,
-59229,
-59229,
-59229,
-59229,
-59239,
-59239,
-59250,
-59265,
-59288,
-59306,
-59306,
-59318,
-59329,
-59329,
-59350,
-59368,
-59377,
-59394,
-59417,
+59186,
+59196,
+59210,
+59236,
+59244,
+59244,
+59244,
+59276,
+59282,
+59300,
+59300,
+59342,
+59351,
+59372,
+59390,
+59402,
+59418,
+59444,
+59444,
59444,
-59465,
-59465,
-59472,
-59472,
-59472,
-59479,
-59479,
-59479,
-59497,
-59514,
-59514,
-59514,
-59528,
-59528,
-59554,
-59554,
-59592,
-59597,
-59628,
-59669,
-59676,
-59683,
-59690,
-59690,
-59719,
-59757,
-59757,
-59764,
+59444,
+59482,
+59495,
+59495,
+59525,
+59545,
+59568,
+59578,
+59584,
+59584,
+59596,
+59596,
+59596,
+59596,
+59615,
+59625,
+59663,
+59663,
+59670,
+59711,
+59731,
+59731,
+59761,
59782,
-59793,
-59819,
-59823,
-59835,
-59850,
-59879,
-59886,
-59893,
-59903,
-59903,
-59918,
-59918,
-59935,
-59963,
-59963,
-60006,
-60030,
-60034,
-60041,
-60041,
-60060,
-60060,
-60074,
-60074,
-60103,
-60103,
-60110,
-60124,
-60138,
-60138,
-60138,
-60152,
-60162,
-60171,
-60186,
-60186,
-60192,
-60240,
-60260,
-60298,
-60298,
-60298,
-60340,
-60354,
-60361,
-60390,
-60390,
-60408,
-60446,
-60452,
-60452,
-60475,
-60482,
-60489,
-60509,
-60509,
-60509,
-60524,
-60531,
-60531,
-60557,
-60564,
-60581,
-60586,
-60629,
-60629,
-60629,
-60629,
-60629,
-60636,
-60663,
-60675,
-60675,
-60682,
-60704,
-60704,
-60724,
-60776,
-60809,
-60832,
-60849,
-60870,
-60877,
-60907,
-60956,
-60956,
-60989,
+59837,
+59837,
+59862,
+59904,
+59931,
+59931,
+59931,
+59931,
+59946,
+59958,
+59958,
+59958,
+59958,
+59958,
+59981,
+60003,
+60003,
+60003,
+60012,
+60012,
+60012,
+60039,
+60047,
+60088,
+60116,
+60161,
+60195,
+60195,
+60227,
+60238,
+60256,
+60283,
+60292,
+60296,
+60301,
+60325,
+60325,
+60325,
+60335,
+60335,
+60368,
+60368,
+60368,
+60399,
+60440,
+60449,
+60470,
+60485,
+60499,
+60535,
+60535,
+60542,
+60550,
+60550,
+60562,
+60562,
+60569,
+60614,
+60614,
+60614,
+60634,
+60634,
+60648,
+60648,
+60648,
+60669,
+60669,
+60690,
+60698,
+60698,
+60723,
+60752,
+60772,
+60772,
+60772,
+60788,
+60788,
+60810,
+60821,
+60846,
+60869,
+60899,
+60916,
+60916,
+60916,
+60916,
+60925,
+60931,
+60931,
+60931,
+60931,
+60938,
+60972,
+60972,
+60972,
+60985,
+60985,
+61003,
+61003,
+61003,
+61003,
+61003,
+61003,
61003,
-61024,
-61048,
-61062,
-61069,
-61101,
-61101,
-61101,
-61101,
-61125,
-61138,
-61155,
-61162,
-61162,
-61184,
-61184,
-61184,
-61184,
-61184,
-61184,
-61216,
-61242,
-61296,
-61296,
-61296,
-61303,
-61303,
-61303,
-61334,
-61360,
-61360,
-61397,
-61416,
-61423,
-61448,
-61476,
-61483,
-61483,
+61003,
+61003,
+61031,
+61031,
+61044,
+61056,
+61072,
+61108,
+61146,
+61146,
+61146,
+61146,
+61207,
+61231,
+61231,
+61250,
+61257,
+61257,
+61288,
+61288,
+61322,
+61322,
+61338,
+61338,
+61343,
+61352,
+61352,
+61373,
+61383,
+61389,
+61436,
+61443,
+61449,
+61503,
+61520,
+61520,
+61520,
+61520,
61532,
-61539,
-61560,
-61578,
-61578,
-61578,
-61617,
-61624,
+61544,
+61557,
+61557,
+61557,
+61557,
+61563,
+61563,
+61591,
+61610,
+61631,
61631,
-61681,
-61706,
-61721,
-61721,
-61729,
-61729,
-61764,
-61776,
-61776,
-61776,
-61808,
-61831,
-61831,
-61837,
-61846,
-61846,
+61631,
+61651,
+61659,
+61691,
+61726,
+61744,
+61744,
+61748,
+61758,
+61794,
+61829,
+61836,
+61856,
+61856,
61864,
-61883,
-61890,
-61910,
-61910,
-61910,
-61917,
-61917,
-61954,
-61954,
-61954,
-61961,
-61968,
-61978,
-62000,
-62007,
-62014,
-62028,
-62042,
-62077,
-62102,
-62109,
-62109,
-62116,
-62116,
-62123,
-62156,
-62163,
-62197,
-62197,
-62197,
-62218,
-62218,
-62232,
-62250,
-62257,
-62286,
-62286,
-62293,
-62300,
-62320,
-62382,
-62430,
-62437,
-62484,
-62484,
-62498,
-62540,
-62552,
-62559,
-62559,
-62559,
-62573,
-62583,
-62592,
-62592,
-62596,
-62628,
-62649,
-62674,
-62674,
-62694,
-62699,
-62699,
-62734,
+61897,
+61924,
+61924,
+61924,
+61924,
+61924,
+61946,
+61946,
+61962,
+61977,
+62005,
+62015,
+62015,
+62033,
+62033,
+62033,
+62065,
+62075,
+62075,
+62087,
+62104,
+62104,
+62104,
+62104,
+62138,
+62138,
+62165,
+62165,
+62193,
+62220,
+62235,
+62235,
+62255,
+62262,
+62269,
+62269,
+62269,
+62269,
+62269,
+62282,
+62282,
+62291,
+62307,
+62307,
+62307,
+62316,
+62316,
+62333,
+62333,
+62344,
+62370,
+62392,
+62392,
+62392,
+62396,
+62411,
+62411,
+62411,
+62418,
+62422,
+62463,
+62463,
+62486,
+62500,
+62504,
+62512,
+62512,
+62522,
+62539,
+62544,
+62557,
+62567,
+62567,
+62567,
+62571,
+62571,
+62571,
+62575,
+62575,
+62575,
+62575,
+62591,
+62591,
+62632,
+62638,
+62638,
+62638,
+62648,
+62675,
+62675,
+62675,
+62675,
+62696,
+62696,
+62715,
+62715,
+62732,
62745,
-62752,
-62759,
-62773,
-62773,
-62804,
-62821,
-62821,
-62825,
-62836,
-62874,
+62801,
+62828,
+62853,
+62853,
+62863,
+62863,
+62879,
62884,
-62911,
-62923,
-62923,
-62935,
-62941,
-62963,
-62987,
-63002,
-63002,
-63027,
-63027,
-63027,
-63027,
+62884,
+62893,
+62929,
+62949,
+62949,
+62961,
+62980,
+62998,
+63007,
+63017,
63027,
-63045,
-63045,
-63057,
-63064,
-63064,
-63108,
-63121,
-63136,
-63136,
-63136,
-63136,
-63136,
-63136,
-63143,
-63143,
-63178,
-63178,
-63178,
-63215,
-63238,
-63264,
-63279,
-63315,
-63337,
-63337,
-63360,
-63360,
-63364,
-63378,
-63378,
-63426,
-63440,
-63460,
-63460,
-63460,
-63460,
+63034,
+63034,
+63050,
+63050,
+63050,
+63050,
+63088,
+63111,
+63111,
+63111,
+63111,
+63111,
+63111,
+63111,
+63111,
+63142,
+63155,
+63155,
+63165,
+63165,
+63165,
+63172,
+63172,
+63172,
+63172,
+63172,
+63172,
+63172,
+63191,
+63191,
+63201,
+63221,
+63230,
+63230,
+63230,
+63230,
+63249,
+63254,
+63254,
+63266,
+63266,
+63287,
+63287,
+63313,
+63327,
+63327,
+63327,
+63327,
+63346,
+63377,
+63377,
+63377,
+63392,
+63392,
+63392,
+63392,
+63392,
+63412,
+63412,
+63431,
+63437,
+63437,
63464,
-63468,
-63491,
-63517,
-63517,
-63535,
-63548,
-63548,
-63601,
-63624,
-63643,
-63660,
-63660,
-63702,
-63714,
-63714,
-63714,
-63723,
-63742,
-63742,
-63742,
-63761,
-63779,
-63790,
-63805,
-63805,
-63805,
+63473,
+63479,
+63494,
+63509,
+63509,
+63520,
+63520,
+63520,
+63520,
+63520,
+63547,
+63547,
+63547,
+63547,
+63547,
+63582,
+63614,
+63632,
+63632,
+63640,
+63640,
+63664,
+63664,
+63664,
+63677,
+63690,
+63690,
+63713,
+63738,
+63738,
+63771,
+63788,
+63788,
+63811,
+63811,
+63818,
+63818,
+63818,
+63818,
+63830,
63852,
-63858,
-63880,
-63910,
-63927,
-63938,
-63938,
-63985,
-63985,
-64010,
-64010,
-64010,
-64017,
-64017,
-64049,
-64049,
-64065,
-64083,
-64083,
-64102,
-64102,
-64102,
-64110,
-64110,
-64122,
-64122,
-64156,
-64186,
-64186,
+63863,
+63863,
+63883,
+63883,
+63887,
+63887,
+63920,
+63931,
+63956,
+63956,
+63956,
+63975,
+64026,
+64030,
+64067,
+64067,
+64067,
+64080,
+64080,
+64097,
+64124,
+64124,
+64139,
+64139,
+64139,
+64139,
+64148,
+64148,
+64148,
+64148,
+64173,
64193,
-64232,
-64249,
-64269,
-64287,
-64287,
-64330,
-64361,
-64379,
-64407,
-64412,
-64412,
-64431,
-64453,
-64461,
-64498,
-64512,
-64512,
-64512,
-64553,
-64558,
-64558,
-64614,
+64200,
+64217,
+64231,
+64235,
+64241,
+64241,
+64279,
+64313,
+64332,
+64345,
+64368,
+64424,
+64430,
+64448,
+64479,
+64496,
+64514,
+64574,
+64574,
+64595,
+64599,
+64618,
+64643,
64657,
-64657,
-64657,
-64694,
-64694,
-64694,
-64710,
-64710,
-64717,
-64735,
-64735,
-64745,
-64755,
-64763,
-64782,
-64782,
-64782,
-64782,
-64782,
-64796,
-64796,
-64796,
-64822,
-64822,
-64839,
-64839,
-64855,
-64866,
+64672,
+64691,
+64691,
+64691,
+64691,
+64728,
+64742,
+64760,
+64760,
+64787,
+64819,
+64819,
+64837,
+64844,
+64860,
64874,
-64889,
-64906,
-64934,
-64963,
-64963,
-64963,
-64963,
-64969,
-64982,
-64982,
-64982,
-64996,
-64996,
-64996,
-65008,
-65033,
-65045,
-65045,
-65045,
-65060,
-65075,
-65075,
-65075,
-65075,
-65100,
-65121,
-65121,
-65126,
+64885,
+64885,
+64891,
+64901,
+64953,
+64953,
+64953,
+64967,
+64997,
+64997,
+64997,
+65020,
+65027,
+65044,
+65051,
+65062,
+65078,
+65099,
+65099,
+65099,
65126,
-65126,
-65150,
-65159,
-65159,
-65184,
-65184,
-65206,
-65206,
-65222,
-65228,
-65247,
-65256,
-65263,
-65275,
-65275,
-65294,
-65308,
+65133,
+65162,
+65209,
+65217,
+65234,
+65265,
+65265,
+65265,
+65285,
+65285,
+65291,
+65291,
+65291,
65308,
-65359,
-65359,
-65359,
-65381,
-65381,
-65397,
-65415,
-65465,
-65476,
-65482,
-65490,
-65490,
+65328,
+65335,
+65341,
+65353,
+65366,
+65390,
+65408,
+65418,
+65429,
+65440,
+65440,
+65457,
+65466,
65496,
-65532,
-65559,
-65603,
+65502,
+65508,
+65508,
+65517,
+65535,
+65554,
+65558,
+65564,
+65564,
+65570,
+65581,
65607,
-65607,
-65633,
-65643,
-65715,
-65721,
-65782,
-65782,
-65782,
-65810,
-65825,
-65825,
-65831,
-65831,
-65831,
-65831,
-65845,
-65850,
-65863,
-65873,
-65882,
-65882,
-65886,
-65904,
-65923,
-65923,
-65939,
-65983,
-65995,
-65995,
-66004,
-66035,
-66061,
-66092,
-66112,
-66112,
-66121,
-66150,
-66162,
-66166,
-66166,
-66175,
-66175,
-66200,
-66230,
-66249,
-66275,
-66292,
-66313,
-66317,
-66317,
-66337,
-66344,
-66344,
-66351,
+65627,
+65635,
+65635,
+65635,
+65635,
+65647,
+65685,
+65693,
+65712,
+65729,
+65729,
+65734,
+65734,
+65734,
+65755,
+65776,
+65776,
+65793,
+65808,
+65828,
+65842,
+65878,
+65891,
+65891,
+65891,
+65982,
+65989,
+66003,
+66003,
+66003,
+66023,
+66057,
+66088,
+66101,
+66132,
+66139,
+66146,
+66146,
+66159,
+66159,
+66182,
+66182,
+66182,
+66189,
+66217,
+66259,
+66271,
+66271,
+66285,
+66297,
+66332,
+66349,
+66349,
66364,
66364,
-66381,
-66391,
-66391,
-66391,
-66400,
-66400,
-66411,
-66411,
-66416,
-66416,
-66436,
-66448,
-66455,
-66469,
-66478,
-66478,
-66478,
-66482,
-66482,
-66482,
-66482,
-66492,
-66492,
-66501,
-66511,
-66518,
-66531,
-66541,
-66541,
-66561,
-66561,
-66561,
-66576,
-66576,
-66576,
-66576,
-66576,
-66576,
-66602,
-66602,
-66614,
-66619,
-66619,
-66619,
-66680,
-66685,
-66685,
-66685,
-66707,
-66716,
-66716,
-66716,
-66716,
-66716,
-66729,
-66748,
-66748,
-66804,
-66814,
-66814,
-66814,
-66822,
-66832,
-66876,
-66876,
-66895,
-66895,
-66905,
-66914,
-66933,
-66942,
-66967,
-66987,
-66987,
-66998,
+66421,
+66449,
+66463,
+66503,
+66535,
+66548,
+66555,
+66555,
+66570,
+66570,
+66580,
+66580,
+66587,
+66587,
+66587,
+66603,
+66631,
+66631,
+66650,
+66650,
+66675,
+66695,
+66702,
+66702,
+66702,
+66702,
+66709,
+66709,
+66739,
+66755,
+66762,
+66762,
+66775,
+66805,
+66823,
+66835,
+66841,
+66841,
+66841,
+66841,
+66841,
+66841,
+66861,
+66907,
+66907,
+66907,
+66907,
+66907,
+66922,
+66940,
+66940,
+66940,
+66940,
+66975,
+66975,
+66975,
+67002,
67016,
-67024,
-67034,
-67034,
-67043,
-67043,
-67043,
-67062,
-67103,
-67103,
-67112,
-67145,
-67145,
-67160,
-67168,
-67168,
-67168,
-67176,
-67205,
-67242,
-67242,
-67242,
-67256,
-67276,
-67276,
-67276,
-67276,
-67297,
-67345,
-67345,
-67345,
-67345,
-67345,
-67358,
-67362,
-67382,
-67382,
-67382,
-67388,
-67422,
-67422,
-67454,
-67454,
-67472,
-67488,
-67506,
-67506,
-67506,
-67506,
-67525,
-67525,
-67544,
-67560,
-67578,
-67578,
-67578,
-67583,
-67600,
-67614,
-67641,
-67659,
-67675,
-67706,
+67032,
+67032,
+67039,
+67069,
+67075,
+67086,
+67119,
+67146,
+67146,
+67151,
+67167,
+67197,
+67197,
+67214,
+67214,
+67221,
+67236,
+67236,
+67249,
+67265,
+67279,
+67306,
+67313,
+67336,
+67353,
+67404,
+67420,
+67420,
+67420,
+67420,
+67420,
+67420,
+67429,
+67429,
+67446,
+67446,
+67462,
+67462,
+67473,
+67480,
+67490,
+67511,
+67511,
+67568,
+67605,
+67639,
+67646,
+67682,
+67689,
+67696,
+67702,
+67720,
67744,
-67761,
-67801,
-67801,
-67837,
-67837,
-67844,
-67844,
-67844,
-67844,
-67844,
-67854,
-67873,
-67907,
-67907,
-67922,
-67922,
-67929,
-67947,
-67947,
-67977,
-67984,
-67994,
-67994,
-67994,
-68022,
-68038,
-68038,
-68046,
-68087,
-68098,
-68104,
-68104,
-68120,
-68120,
-68120,
-68126,
-68126,
-68138,
-68143,
-68169,
-68169,
-68199,
-68241,
-68256,
-68279,
-68279,
-68279,
+67763,
+67763,
+67782,
+67806,
+67806,
+67806,
+67810,
+67817,
+67817,
+67827,
+67840,
+67840,
+67840,
+67840,
+67840,
+67847,
+67867,
+67874,
+67874,
+67886,
+67886,
+67920,
+67927,
+67932,
+67960,
+67967,
+67974,
+67992,
+67992,
+68004,
+68004,
+68031,
+68031,
+68063,
+68088,
+68095,
+68112,
+68112,
+68112,
+68127,
+68135,
+68146,
+68176,
+68193,
+68200,
+68221,
+68228,
+68245,
+68245,
+68280,
+68280,
68320,
-68330,
-68330,
-68335,
-68335,
-68356,
-68390,
-68390,
-68407,
-68434,
-68434,
+68345,
+68352,
+68383,
+68425,
+68445,
+68445,
68452,
-68475,
-68484,
-68514,
-68524,
-68524,
-68524,
-68524,
-68524,
-68532,
-68532,
-68532,
-68556,
-68572,
-68587,
-68587,
-68594,
-68594,
-68604,
-68604,
-68621,
-68693,
-68703,
-68737,
-68759,
-68784,
-68784,
-68808,
-68808,
-68808,
-68822,
-68822,
-68881,
-68881,
-68881,
-68919,
-68919,
+68479,
+68503,
+68510,
+68517,
+68576,
+68583,
+68628,
+68642,
+68646,
+68662,
+68701,
+68717,
+68724,
+68724,
+68733,
+68740,
+68756,
+68777,
+68777,
+68777,
+68777,
+68791,
+68803,
+68803,
+68825,
+68843,
+68857,
+68879,
+68907,
+68907,
+68907,
68919,
-68934,
-68934,
-68934,
-68951,
-68969,
-68991,
-69022,
-69022,
-69022,
-69022,
-69043,
-69052,
-69052,
-69123,
-69141,
-69141,
-69155,
-69177,
-69194,
-69194,
-69194,
-69212,
-69223,
-69223,
-69241,
-69257,
-69271,
-69300,
-69300,
-69300,
-69300,
-69332,
-69367,
-69377,
-69377,
-69381,
-69427,
-69427,
-69427,
-69459,
-69476,
-69524,
-69543,
-69573,
-69573,
-69585,
-69585,
-69585,
+68959,
+68994,
+69006,
+69023,
+69023,
+69040,
+69055,
+69055,
+69076,
+69102,
+69102,
+69140,
+69149,
+69165,
+69183,
+69221,
+69228,
+69235,
+69256,
+69256,
+69256,
+69268,
+69292,
+69326,
+69363,
+69380,
+69380,
+69380,
+69380,
+69405,
+69417,
+69445,
+69445,
+69464,
+69464,
+69464,
+69464,
+69464,
+69480,
+69508,
+69544,
+69544,
+69557,
+69557,
+69557,
+69587,
69607,
-69683,
-69698,
-69698,
-69698,
-69698,
-69756,
-69778,
-69792,
-69818,
-69828,
-69853,
-69853,
-69876,
+69628,
+69655,
+69725,
+69749,
+69760,
+69796,
+69803,
+69847,
+69872,
+69872,
69893,
-69916,
-69916,
-69916,
-69916,
-69931,
-69944,
-69952,
-69952,
-69982,
-69982,
-69987,
-70026,
-70042,
-70042,
-70059,
-70078,
-70078,
-70135,
-70143,
-70143,
-70158,
-70167,
-70167,
-70167,
-70188,
-70224,
-70260,
-70260,
-70260,
-70287,
-70298,
-70298,
-70314,
-70323,
-70351,
-70382,
-70382,
-70393,
-70402,
-70440,
-70440,
-70440,
-70440,
-70440,
-70448,
-70448,
-70448,
-70472,
-70472,
-70472,
-70472,
-70503,
-70503,
-70503,
+69893,
+69893,
+69893,
+69893,
+69902,
+69926,
+69941,
+69948,
+69948,
+69965,
+69979,
+69986,
+69993,
+70000,
+70005,
+70030,
+70050,
+70057,
+70064,
+70091,
+70117,
+70163,
+70163,
+70170,
+70180,
+70211,
+70218,
+70264,
+70264,
+70278,
+70285,
+70285,
+70332,
+70332,
+70337,
+70337,
+70337,
+70361,
+70368,
+70385,
+70392,
+70410,
+70429,
+70435,
+70435,
+70435,
+70435,
+70442,
+70442,
+70456,
+70485,
70503,
-70551,
-70551,
-70564,
-70564,
-70564,
-70564,
-70564,
+70512,
+70521,
+70521,
+70525,
+70525,
+70563,
+70575,
+70586,
+70586,
+70586,
+70603,
70609,
-70609,
-70620,
-70620,
-70627,
-70634,
-70651,
-70651,
-70657,
-70663,
-70663,
-70681,
-70687,
-70694,
-70694,
-70701,
-70714,
-70724,
-70724,
-70724,
-70755,
-70755,
-70755,
-70755,
-70755,
-70755,
-70755,
-70755,
-70786,
-70786,
-70808,
-70808,
-70826,
-70826,
-70826,
-70852,
-70852,
-70852,
-70852,
-70852,
-70852,
-70852,
-70852,
-70860,
-70908,
-70918,
-70926,
-70943,
-70943,
-71014,
-71014,
-71014,
-71023,
-71031,
-71049,
-71049,
-71073,
-71073,
-71094,
-71094,
-71103,
-71103,
-71132,
-71149,
-71149,
-71167,
+70640,
+70656,
+70664,
+70664,
+70670,
+70685,
+70692,
+70710,
+70731,
+70750,
+70767,
+70785,
+70816,
+70823,
+70839,
+70839,
+70853,
+70853,
+70853,
+70871,
+70889,
+70889,
+70889,
+70907,
+70916,
+70955,
+70955,
+70970,
+70970,
+70990,
+70998,
+70998,
+70998,
+71024,
+71045,
+71051,
+71058,
+71058,
+71058,
+71058,
+71058,
+71058,
+71058,
+71074,
+71096,
+71096,
+71105,
+71105,
+71112,
+71112,
+71119,
+71135,
+71135,
+71152,
+71152,
+71152,
+71152,
+71170,
71177,
-71195,
-71204,
-71204,
-71224,
-71248,
-71248,
-71252,
-71273,
-71279,
-71279,
-71279,
-71313,
-71319,
-71319,
-71319,
-71319,
-71336,
-71336,
-71336,
-71336,
-71336,
-71357,
-71367,
-71367,
-71391,
-71457,
-71457,
-71465,
-71465,
-71469,
+71199,
+71199,
+71199,
+71210,
+71210,
+71238,
+71238,
+71238,
+71238,
+71243,
+71243,
+71243,
+71261,
+71288,
+71302,
+71318,
+71361,
+71361,
+71361,
+71389,
+71389,
+71389,
+71410,
+71422,
+71439,
+71439,
+71439,
+71439,
+71439,
+71449,
+71449,
+71449,
71469,
-71487,
-71521,
-71521,
-71559,
-71559,
-71559,
-71559,
-71559,
-71591,
-71618,
-71618,
-71624,
-71650,
-71650,
-71650,
-71680,
-71680,
-71680,
-71680,
-71708,
-71720,
+71483,
+71490,
+71490,
+71494,
+71506,
+71544,
+71544,
+71571,
+71580,
+71580,
+71580,
+71580,
+71593,
+71611,
+71626,
+71626,
+71640,
+71653,
+71653,
+71653,
+71665,
+71684,
+71700,
+71729,
+71729,
+71729,
71729,
-71752,
-71752,
-71752,
-71752,
-71757,
-71757,
-71793,
-71805,
-71805,
-71805,
-71805,
-71805,
-71805,
-71805,
-71810,
-71810,
-71820,
-71840,
-71888,
-71911,
-71911,
-71921,
-71932,
-71968,
-71992,
-71992,
-72002,
-72002,
-72002,
-72013,
-72013,
+71741,
+71741,
+71748,
+71809,
+71818,
+71818,
+71836,
+71876,
+71926,
+71946,
+71946,
+71946,
+71946,
+71946,
+71971,
+71984,
+71984,
+71994,
+72010,
+72010,
+72010,
+72010,
+72010,
+72010,
72035,
-72046,
-72074,
-72099,
-72099,
-72135,
-72135,
-72135,
-72145,
-72202,
-72202,
-72202,
-72227,
-72234,
+72079,
+72079,
+72102,
+72129,
+72138,
+72151,
+72151,
+72151,
+72151,
+72162,
+72162,
+72166,
+72166,
+72166,
+72175,
+72175,
+72175,
+72191,
+72191,
+72191,
+72191,
+72191,
+72191,
72242,
-72247,
-72255,
-72255,
-72255,
-72277,
-72277,
-72277,
-72284,
-72284,
-72329,
+72242,
+72242,
+72248,
+72264,
+72282,
+72290,
+72308,
+72324,
+72345,
+72345,
+72345,
72345,
-72382,
-72382,
-72382,
-72393,
+72351,
+72370,
+72370,
+72401,
+72401,
72407,
72407,
-72428,
-72436,
-72436,
-72467,
-72495,
-72495,
-72504,
-72504,
-72504,
-72526,
-72553,
+72407,
+72407,
+72435,
+72453,
+72453,
+72453,
+72468,
+72486,
+72506,
+72512,
+72512,
+72537,
+72537,
+72556,
+72567,
72579,
-72585,
72601,
-72640,
-72650,
-72656,
-72661,
-72661,
-72669,
-72688,
-72688,
-72688,
-72730,
-72743,
-72743,
-72764,
-72779,
-72803,
-72813,
-72813,
-72813,
-72825,
-72825,
-72857,
-72866,
-72895,
-72895,
-72934,
-72969,
-72969,
-72969,
-72969,
-73020,
-73020,
-73033,
-73046,
-73057,
-73057,
-73057,
-73069,
-73078,
-73082,
-73082,
-73109,
-73129,
-73174,
-73180,
-73180,
-73180,
-73186,
-73186,
-73196,
-73196,
-73196,
-73212,
-73230,
-73230,
-73254,
-73260,
-73260,
-73274,
-73281,
-73311,
-73311,
-73311,
-73337,
-73368,
-73381,
+72613,
+72619,
+72625,
+72625,
+72631,
+72637,
+72667,
+72680,
+72692,
+72692,
+72692,
+72710,
+72720,
+72720,
+72733,
+72733,
+72741,
+72741,
+72752,
+72765,
+72771,
+72771,
+72771,
+72771,
+72785,
+72785,
+72807,
+72807,
+72827,
+72834,
+72843,
+72878,
+72878,
+72892,
+72901,
+72901,
+72901,
+72906,
+72916,
+72916,
+72916,
+72927,
+72927,
+72927,
+72927,
+72963,
+72963,
+72963,
+72963,
+72963,
+72963,
+72985,
+73029,
+73044,
+73064,
+73064,
+73064,
+73064,
+73064,
+73064,
+73073,
+73073,
+73093,
+73120,
+73126,
+73144,
+73144,
+73159,
+73159,
+73165,
+73165,
+73203,
+73213,
+73238,
+73258,
+73273,
+73273,
+73273,
+73273,
+73273,
+73287,
+73303,
+73335,
+73359,
+73365,
+73387,
+73402,
73402,
-73435,
-73456,
-73456,
-73456,
-73456,
-73472,
-73472,
-73488,
-73488,
-73488,
-73488,
-73488,
-73488,
+73402,
+73413,
+73413,
+73413,
+73423,
+73442,
+73468,
+73485,
+73485,
73503,
-73522,
-73522,
-73522,
-73530,
-73530,
-73559,
-73616,
-73637,
-73662,
-73685,
-73700,
-73700,
-73711,
-73745,
-73755,
-73790,
-73815,
-73815,
-73815,
-73815,
-73821,
-73844,
-73867,
-73883,
-73907,
-73907,
-73942,
-73974,
-73974,
-73974,
-74007,
-74026,
-74043,
-74043,
-74057,
-74063,
-74079,
-74079,
-74102,
-74102,
-74102,
-74125,
-74136,
-74136,
-74136,
-74136,
-74158,
-74164,
-74164,
-74164,
-74172,
-74188,
-74188,
-74210,
-74246,
-74256,
-74256,
-74256,
-74264,
-74300,
-74312,
-74320,
-74328,
-74360,
-74360,
+73537,
+73575,
+73575,
+73610,
+73629,
+73635,
+73635,
+73635,
+73635,
+73658,
+73658,
+73681,
+73687,
+73687,
+73712,
+73736,
+73753,
+73780,
+73797,
+73816,
+73838,
+73850,
+73850,
+73863,
+73909,
+73918,
+73930,
+73946,
+73976,
+73986,
+73986,
+73986,
+73986,
+73990,
+74017,
+74017,
+74017,
+74025,
+74025,
+74025,
+74025,
+74055,
+74073,
+74073,
+74073,
+74084,
+74095,
+74095,
+74095,
+74123,
+74150,
+74150,
+74155,
+74155,
+74155,
+74155,
+74161,
+74170,
+74176,
+74193,
+74216,
+74224,
+74266,
+74266,
+74277,
+74277,
+74289,
+74289,
+74295,
+74330,
+74330,
+74342,
+74348,
74383,
-74389,
-74401,
-74413,
-74430,
-74430,
-74430,
-74460,
-74486,
-74486,
-74486,
-74486,
-74486,
-74510,
-74531,
-74531,
-74561,
-74601,
-74620,
-74631,
-74631,
-74674,
-74674,
-74684,
-74684,
-74695,
-74710,
-74710,
-74719,
-74748,
-74773,
-74781,
-74789,
-74789,
-74809,
-74809,
-74809,
-74825,
-74845,
-74845,
-74857,
-74891,
-74891,
-74891,
-74891,
-74891,
-74925,
+74420,
+74420,
+74426,
+74426,
+74451,
+74469,
+74483,
+74500,
+74500,
+74515,
+74520,
+74520,
+74537,
+74547,
+74547,
+74547,
+74558,
+74558,
+74571,
+74578,
+74590,
+74590,
+74603,
+74619,
+74628,
+74628,
+74634,
+74634,
+74634,
+74655,
+74667,
+74691,
+74702,
+74725,
+74725,
+74725,
+74725,
+74730,
+74730,
+74730,
+74730,
+74736,
+74758,
+74764,
+74764,
+74764,
+74764,
+74784,
+74803,
+74803,
+74832,
+74832,
+74856,
+74867,
+74867,
+74885,
+74890,
+74890,
+74910,
74925,
74925,
-74943,
-74988,
-75011,
-75011,
-75011,
-75011,
-75011,
-75021,
-75021,
-75037,
-75037,
-75064,
-75097,
-75102,
-75102,
-75140,
-75140,
-75158,
-75158,
-75172,
-75172,
-75193,
-75193,
-75212,
-75227,
-75245,
-75256,
-75272,
+74939,
+74939,
+74954,
+74963,
+74989,
+74996,
+74996,
+75013,
+75013,
+75013,
+75042,
+75059,
+75067,
+75108,
+75128,
+75136,
+75155,
+75160,
+75160,
+75173,
+75173,
+75173,
+75173,
+75179,
+75179,
+75190,
+75213,
+75217,
+75236,
+75236,
+75265,
+75265,
75283,
-75293,
-75308,
-75315,
-75315,
-75341,
-75356,
-75367,
-75397,
-75397,
-75453,
-75471,
-75471,
-75471,
-75485,
-75534,
-75534,
-75534,
-75545,
-75551,
-75551,
-75551,
-75564,
-75576,
-75609,
-75621,
-75638,
-75671,
-75681,
-75696,
-75702,
-75702,
-75714,
-75714,
-75721,
-75736,
-75736,
-75743,
+75294,
+75311,
+75311,
+75317,
+75317,
+75325,
+75345,
+75370,
+75370,
+75382,
+75382,
+75382,
+75411,
+75417,
+75434,
+75443,
+75449,
+75455,
+75478,
+75484,
+75517,
+75542,
+75548,
+75561,
+75561,
+75567,
+75573,
+75573,
+75579,
+75579,
+75593,
+75593,
+75593,
+75593,
+75599,
+75615,
+75651,
+75685,
+75692,
+75713,
+75719,
+75725,
+75737,
+75746,
+75750,
+75750,
75761,
-75770,
-75778,
-75778,
-75778,
-75778,
-75778,
-75805,
-75805,
-75823,
-75834,
-75840,
-75857,
-75893,
-75893,
-75893,
-75893,
-75893,
+75783,
+75789,
+75804,
+75814,
+75814,
+75814,
+75833,
+75833,
+75867,
+75867,
+75867,
+75867,
75904,
+75909,
+75928,
+75928,
+75928,
+75928,
+75928,
75945,
-75945,
-75958,
-75958,
-75958,
-75977,
-76016,
-76031,
-76037,
-76037,
-76051,
-76051,
-76079,
-76084,
-76084,
-76102,
-76120,
+75959,
+75973,
+75973,
+75995,
+76066,
+76066,
+76066,
+76082,
+76082,
+76082,
+76098,
+76109,
76120,
76120,
76120,
-76134,
-76166,
-76175,
-76205,
-76216,
-76216,
-76227,
-76244,
-76275,
-76284,
-76318,
-76337,
-76343,
-76389,
-76389,
-76389,
-76389,
-76402,
-76416,
-76416,
-76434,
-76434,
-76444,
-76497,
-76497,
-76509,
-76519,
-76566,
-76604,
-76611,
-76611,
-76611,
-76640,
-76654,
-76654,
-76654,
-76654,
-76671,
-76671,
-76676,
-76676,
-76697,
-76697,
-76697,
-76697,
-76707,
-76751,
-76751,
-76751,
-76774,
-76778,
-76807,
-76807,
-76807,
-76830,
-76830,
-76848,
+76129,
+76149,
+76170,
+76170,
+76170,
+76170,
+76170,
+76186,
+76199,
+76199,
+76199,
+76218,
+76235,
+76249,
+76261,
+76300,
+76305,
+76328,
+76342,
+76366,
+76366,
+76399,
+76413,
+76413,
+76413,
+76431,
+76437,
+76459,
+76459,
+76475,
+76475,
+76475,
+76475,
+76475,
+76475,
+76482,
+76493,
+76493,
+76501,
+76501,
+76515,
+76532,
+76532,
+76544,
+76544,
+76578,
+76603,
+76603,
+76612,
+76628,
+76644,
+76657,
+76666,
+76705,
+76705,
+76730,
+76730,
+76740,
+76740,
+76757,
+76804,
+76816,
+76832,
+76832,
+76832,
+76832,
+76847,
76864,
-76897,
-76913,
-76932,
-76932,
-76944,
-76970,
-76986,
-76986,
-77002,
-77017,
-77022,
-77039,
-77049,
-77049,
-77049,
-77067,
-77067,
-77067,
-77081,
-77081,
-77081,
-77089,
-77089,
-77105,
-77121,
-77121,
-77156,
-77156,
-77156,
-77156,
-77156,
-77165,
-77173,
-77173,
-77173,
-77173,
-77191,
-77211,
-77211,
-77211,
-77218,
-77242,
+76871,
+76881,
+76881,
+76917,
+76929,
+76929,
+76938,
+76938,
+76938,
+76938,
+76960,
+76979,
+77000,
+77041,
+77058,
+77058,
+77066,
+77084,
+77084,
+77084,
+77106,
+77122,
+77122,
+77122,
+77122,
+77143,
+77152,
+77152,
+77152,
+77158,
+77158,
+77158,
+77158,
+77158,
+77158,
+77171,
+77183,
+77183,
+77188,
+77188,
+77188,
+77188,
+77188,
+77204,
+77204,
+77227,
+77251,
+77251,
+77251,
+77270,
+77290,
+77290,
+77290,
77290,
-77308,
-77308,
-77325,
-77343,
-77343,
-77376,
-77376,
-77376,
-77376,
-77386,
-77386,
-77386,
-77386,
+77311,
+77327,
+77327,
+77341,
+77341,
+77358,
+77358,
+77358,
77393,
-77399,
-77419,
-77428,
-77450,
+77393,
+77400,
+77407,
+77407,
+77436,
77450,
+77464,
+77464,
77492,
77492,
-77492,
-77492,
-77529,
-77529,
-77529,
-77540,
-77540,
-77540,
-77557,
-77570,
-77570,
-77570,
-77570,
-77570,
-77570,
-77587,
-77597,
+77508,
+77508,
+77533,
+77545,
+77545,
+77556,
+77578,
+77593,
+77610,
77620,
-77640,
-77640,
-77640,
-77661,
-77680,
-77680,
-77680,
-77680,
-77680,
-77680,
-77712,
-77732,
-77739,
-77739,
-77739,
-77748,
-77765,
-77824,
-77824,
-77834,
-77850,
-77860,
-77860,
-77872,
-77872,
-77889,
-77889,
-77889,
-77902,
-77920,
-77934,
-77962,
-77982,
-77982,
-77982,
-77982,
-78000,
-78000,
-78000,
-78009,
-78025,
-78036,
-78036,
-78043,
-78043,
-78062,
-78072,
-78123,
-78153,
-78167,
-78189,
-78211,
-78211,
-78211,
-78222,
-78222,
-78222,
-78230,
-78230,
-78236,
-78236,
-78236,
-78236,
-78254,
-78254,
-78254,
-78254,
-78254,
-78272,
-78296,
-78313,
-78332,
-78368,
-78384,
-78394,
-78404,
-78411,
-78423,
-78444,
-78451,
-78464,
-78485,
-78501,
-78501,
-78514,
-78514,
-78514,
-78514,
-78523,
-78532,
-78544,
-78544,
-78544,
-78544,
-78544,
-78544,
-78555,
-78575,
-78612,
-78612,
-78641,
-78672,
-78678,
-78678,
-78705,
-78705,
-78720,
-78737,
-78737,
-78753,
-78753,
-78757,
-78778,
-78778,
-78778,
-78819,
-78837,
-78837,
-78837,
-78843,
-78843,
-78853,
-78869,
-78869,
-78908,
-78908,
-78908,
-78908,
-78908,
-78913,
-78958,
-78958,
-78958,
-78969,
-78990,
-79019,
-79019,
-79025,
-79025,
-79025,
-79059,
-79079,
-79079,
-79079,
-79086,
-79086,
-79102,
-79102,
-79102,
-79109,
-79109,
-79109,
-79109,
-79109,
-79109,
-79109,
-79109,
-79109,
-79123,
-79136,
-79155,
+77657,
+77657,
+77693,
+77693,
+77693,
+77693,
+77705,
+77705,
+77705,
+77718,
+77718,
+77734,
+77742,
+77742,
+77781,
+77789,
+77819,
+77830,
+77830,
+77830,
+77830,
+77830,
+77847,
+77870,
+77870,
+77904,
+77904,
+77916,
+77916,
+77942,
+77958,
+77958,
+77958,
+77972,
+77972,
+77972,
+77988,
+77988,
+77994,
+78017,
+78031,
+78044,
+78089,
+78099,
+78129,
+78129,
+78129,
+78129,
+78135,
+78140,
+78155,
+78176,
+78214,
+78235,
+78243,
+78277,
+78277,
+78277,
+78285,
+78312,
+78312,
+78328,
+78339,
+78357,
+78373,
+78389,
+78389,
+78414,
+78432,
+78439,
+78455,
+78484,
+78492,
+78500,
+78536,
+78556,
+78582,
+78582,
+78615,
+78624,
+78664,
+78664,
+78675,
+78675,
+78694,
+78694,
+78709,
+78715,
+78715,
+78724,
+78724,
+78733,
+78733,
+78766,
+78766,
+78780,
+78791,
+78812,
+78812,
+78812,
+78821,
+78865,
+78865,
+78865,
+78865,
+78890,
+78890,
+78890,
+78890,
+78911,
+78911,
+78911,
+78933,
+78943,
+78943,
+78943,
+78943,
+78943,
+78978,
+78986,
+78986,
+78997,
+79027,
+79047,
+79047,
+79078,
+79078,
+79093,
+79093,
+79093,
+79093,
+79093,
+79131,
+79131,
+79152,
+79152,
+79152,
79180,
79180,
-79187,
-79187,
-79187,
-79187,
-79217,
-79217,
-79249,
-79249,
-79266,
+79180,
+79180,
+79202,
+79202,
+79202,
+79221,
+79221,
+79227,
+79233,
+79241,
+79260,
+79260,
+79260,
79266,
-79278,
+79274,
+79274,
79288,
-79288,
-79302,
-79311,
-79311,
-79341,
-79357,
-79357,
-79364,
-79382,
-79395,
-79395,
-79395,
-79395,
-79408,
-79427,
-79444,
-79444,
-79464,
-79484,
-79484,
-79491,
+79303,
+79319,
+79351,
+79374,
+79374,
+79380,
+79390,
+79390,
+79390,
+79396,
+79416,
+79416,
+79426,
+79426,
+79426,
+79443,
+79453,
+79453,
+79472,
+79503,
+79503,
+79508,
79514,
-79526,
-79526,
-79539,
-79571,
-79571,
-79591,
-79626,
-79626,
-79626,
-79656,
-79656,
-79671,
-79671,
-79671,
-79685,
-79685,
-79697,
-79705,
-79722,
-79748,
-79773,
-79773,
-79802,
-79802,
-79802,
-79808,
-79808,
-79818,
-79818,
-79841,
-79841,
-79841,
-79850,
+79530,
+79540,
+79540,
+79548,
+79563,
+79584,
+79636,
+79645,
+79675,
+79682,
+79682,
+79715,
+79725,
+79754,
+79754,
+79774,
+79793,
+79793,
+79816,
+79816,
+79816,
+79831,
+79831,
79850,
-79850,
-79850,
-79850,
-79859,
-79859,
-79876,
-79876,
-79906,
-79927,
-79952,
-79963,
-79974,
-79980,
-79996,
-79996,
-79996,
-79996,
-80014,
-80014,
+79867,
+79867,
+79867,
+79867,
+79875,
+79896,
+79896,
+79896,
+79896,
+79922,
+79922,
+79922,
+79934,
+79934,
+79947,
+79964,
+79964,
+80000,
80014,
80014,
-80014,
-80014,
-80014,
-80044,
-80067,
-80074,
-80090,
-80090,
-80090,
-80090,
-80090,
-80090,
-80123,
-80132,
-80137,
-80152,
-80152,
-80177,
-80194,
-80211,
-80211,
-80231,
-80248,
-80269,
+80025,
+80025,
+80037,
+80071,
+80105,
+80105,
+80111,
+80161,
+80171,
+80181,
+80197,
+80217,
+80227,
+80227,
+80227,
+80252,
+80264,
80276,
-80276,
-80283,
80293,
-80310,
-80310,
-80315,
-80332,
-80352,
-80352,
-80404,
-80415,
-80432,
-80464,
-80492,
-80524,
-80534,
-80541,
-80581,
-80581,
-80588,
-80588,
-80601,
-80618,
-80618,
-80634,
-80652,
-80675,
-80675,
-80682,
-80682,
-80682,
-80682,
-80682,
-80682,
-80704,
-80733,
-80733,
-80749,
-80796,
-80796,
-80812,
-80812,
-80819,
-80819,
-80829,
-80862,
-80885,
-80909,
-80917,
-80917,
+80293,
+80293,
+80293,
+80293,
+80333,
+80339,
+80353,
+80380,
+80421,
+80484,
+80484,
+80484,
+80498,
+80543,
+80543,
+80569,
+80569,
+80578,
+80578,
+80595,
+80616,
+80616,
+80623,
+80631,
+80631,
+80631,
+80649,
+80649,
+80649,
+80649,
+80659,
+80686,
+80703,
+80710,
+80726,
+80741,
+80741,
+80764,
+80764,
+80764,
+80783,
+80799,
+80799,
+80799,
+80833,
+80833,
+80872,
+80872,
+80872,
+80899,
+80916,
+80916,
+80937,
80937,
-80951,
-80951,
-80974,
-80992,
-81014,
-81032,
-81032,
-81032,
-81032,
-81061,
-81069,
-81106,
-81106,
-81111,
-81111,
-81167,
-81201,
-81219,
-81219,
-81219,
-81266,
-81266,
-81280,
-81280,
-81280,
-81287,
-81308,
-81314,
-81336,
-81354,
-81360,
-81360,
-81360,
-81389,
-81410,
-81410,
-81410,
-81410,
-81418,
-81437,
+80937,
+80937,
+80937,
+80947,
+80947,
+80965,
+80965,
+80977,
+80977,
+80986,
+80986,
+80986,
+81006,
+81013,
+81013,
+81023,
+81048,
+81066,
+81066,
+81097,
+81107,
+81118,
+81118,
+81118,
+81140,
+81175,
+81187,
+81187,
+81187,
+81192,
+81192,
+81192,
+81212,
+81240,
+81240,
+81298,
+81298,
+81298,
+81298,
+81310,
+81316,
+81316,
+81327,
+81335,
+81335,
+81342,
+81359,
+81359,
+81359,
+81359,
+81370,
+81370,
+81370,
+81381,
+81395,
+81405,
+81413,
+81447,
+81447,
81460,
81460,
-81485,
-81497,
-81513,
-81525,
-81525,
-81532,
-81543,
-81543,
-81558,
+81471,
+81471,
+81476,
+81495,
+81510,
+81510,
+81526,
+81526,
+81553,
+81571,
+81587,
+81587,
81592,
-81592,
-81613,
-81613,
-81630,
-81637,
-81680,
-81727,
-81727,
-81727,
-81727,
-81732,
-81732,
-81732,
-81732,
+81611,
+81638,
+81638,
+81664,
+81690,
+81696,
+81696,
+81696,
+81721,
+81721,
+81739,
81739,
81739,
-81751,
-81758,
-81758,
-81778,
-81778,
-81785,
-81785,
-81808,
-81830,
-81830,
-81838,
+81749,
+81766,
+81773,
+81773,
+81773,
+81791,
+81791,
+81815,
+81839,
+81846,
81855,
-81868,
-81885,
-81885,
-81892,
-81892,
-81905,
-81905,
-81921,
-81934,
-81959,
-81959,
-81966,
-82004,
+81855,
+81855,
+81879,
+81903,
+81915,
+81939,
+81939,
+81965,
+81985,
82004,
82004,
82021,
-82021,
-82048,
-82048,
-82048,
-82070,
-82093,
-82114,
-82114,
-82114,
-82136,
-82160,
-82182,
-82182,
-82191,
-82198,
-82198,
-82211,
-82245,
-82280,
-82287,
-82287,
-82287,
-82287,
-82308,
-82308,
-82308,
-82315,
-82336,
-82336,
-82336,
-82336,
-82365,
-82375,
-82375,
-82375,
-82375,
-82382,
-82382,
-82417,
-82433,
-82440,
-82474,
-82488,
-82531,
-82531,
-82552,
-82563,
-82581,
-82597,
-82597,
-82613,
-82634,
-82648,
-82654,
-82661,
-82661,
-82661,
-82668,
-82675,
-82690,
-82696,
+82037,
+82082,
+82082,
+82115,
+82154,
+82161,
+82169,
+82169,
+82207,
+82223,
+82233,
+82233,
+82233,
+82233,
+82249,
+82249,
+82249,
+82264,
+82270,
+82283,
+82309,
+82340,
+82353,
+82380,
+82380,
+82400,
+82425,
+82456,
+82462,
+82462,
+82481,
+82481,
+82499,
+82499,
+82499,
+82499,
+82499,
+82499,
+82499,
+82512,
+82547,
+82564,
+82607,
+82607,
+82607,
+82620,
+82629,
+82629,
+82629,
+82640,
+82640,
+82664,
+82664,
+82664,
+82664,
+82664,
+82674,
+82689,
+82689,
+82689,
+82689,
+82703,
82703,
-82717,
+82703,
+82719,
82724,
-82752,
-82752,
-82772,
-82788,
-82795,
-82802,
-82814,
-82837,
-82858,
-82865,
-82888,
-82895,
-82929,
-82948,
-82960,
-82967,
-82981,
-82981,
-82996,
-83015,
-83031,
-83038,
-83045,
-83081,
-83100,
-83149,
-83182,
-83182,
-83206,
-83213,
-83236,
-83236,
-83243,
-83243,
-83249,
-83261,
-83268,
-83268,
+82741,
+82750,
+82750,
+82757,
+82809,
+82821,
+82821,
+82821,
+82821,
+82833,
+82833,
+82863,
+82863,
+82879,
+82898,
+82906,
+82906,
+82923,
+82923,
+82942,
+82942,
+82966,
+83020,
+83020,
+83044,
+83044,
+83067,
+83067,
+83105,
+83105,
+83122,
+83143,
+83161,
+83178,
+83194,
+83210,
+83210,
+83210,
+83210,
+83210,
+83232,
83292,
-83306,
-83328,
-83328,
-83354,
-83361,
-83395,
-83401,
-83415,
-83425,
-83448,
-83454,
-83481,
-83510,
-83558,
-83565,
+83309,
+83323,
+83357,
+83357,
+83406,
+83406,
+83406,
+83406,
+83453,
+83468,
+83487,
+83513,
+83513,
+83513,
+83519,
+83567,
+83580,
83591,
-83607,
-83617,
-83645,
-83658,
-83665,
-83682,
-83682,
-83682,
-83699,
-83733,
-83743,
-83797,
-83813,
-83829,
+83606,
+83616,
+83653,
+83653,
+83670,
+83684,
+83684,
+83684,
+83684,
+83684,
+83695,
+83714,
+83714,
+83714,
+83759,
+83759,
+83759,
+83759,
+83759,
+83759,
+83791,
+83791,
+83791,
+83791,
+83791,
+83791,
+83791,
+83799,
+83799,
+83812,
+83812,
+83822,
+83822,
+83837,
+83837,
+83837,
+83837,
+83843,
83843,
-83855,
-83859,
-83873,
-83873,
-83873,
-83889,
-83904,
-83945,
-83974,
-84021,
-84021,
-84081,
-84092,
-84106,
-84123,
-84140,
-84212,
-84212,
-84212,
-84212,
-84241,
-84248,
-84255,
-84255,
-84262,
-84282,
-84308,
-84308,
-84308,
-84317,
-84317,
-84331,
-84360,
-84384,
-84401,
+83861,
+83861,
+83861,
+83874,
+83888,
+83936,
+83936,
+83950,
+83950,
+83950,
+83963,
+83963,
+83970,
+83995,
+83995,
+84018,
+84040,
+84040,
+84040,
+84040,
+84053,
+84053,
+84074,
+84105,
+84115,
+84154,
+84177,
+84194,
+84211,
+84211,
+84211,
+84211,
+84229,
+84229,
+84245,
+84266,
+84278,
+84285,
+84285,
+84285,
+84285,
+84285,
+84285,
+84285,
+84323,
+84348,
+84368,
+84368,
+84368,
+84368,
+84388,
+84388,
+84388,
+84388,
+84388,
+84388,
84408,
-84455,
-84488,
-84488,
-84530,
-84551,
-84577,
-84577,
-84586,
-84593,
-84612,
-84619,
-84619,
-84666,
+84421,
+84426,
+84433,
+84433,
+84433,
+84433,
+84433,
+84449,
+84472,
+84472,
+84472,
+84472,
+84492,
+84492,
+84499,
+84499,
+84506,
+84506,
+84524,
+84567,
+84585,
+84585,
+84585,
+84585,
+84585,
+84585,
+84608,
+84608,
+84618,
+84618,
+84618,
+84650,
+84670,
+84670,
84682,
-84697,
-84714,
-84766,
-84766,
-84766,
-84766,
-84778,
-84792,
-84799,
-84799,
-84799,
-84805,
-84817,
-84842,
-84842,
-84842,
-84849,
-84864,
-84876,
-84930,
-84936,
-84936,
-84948,
-84960,
-84960,
-84960,
-84983,
-84996,
-85003,
-85011,
-85046,
-85066,
-85111,
-85127,
-85149,
-85165,
-85210,
-85229,
-85229,
-85229,
-85235,
-85235,
-85253,
-85266,
-85285,
-85299,
-85329,
-85343,
-85361,
-85379,
-85413,
-85413,
-85446,
-85453,
-85482,
-85492,
-85514,
-85521,
-85521,
-85521,
-85561,
-85568,
-85585,
-85599,
-85654,
-85671,
-85685,
-85699,
-85699,
-85699,
-85699,
-85699,
-85709,
-85734,
-85734,
-85748,
-85748,
-85771,
-85787,
-85787,
-85820,
-85830,
-85830,
-85837,
-85837,
-85837,
-85860,
-85921,
-85944,
-85944,
-85962,
-85968,
-85982,
-86007,
-86014,
-86019,
-86034,
-86054,
-86061,
-86074,
-86112,
-86119,
-86125,
-86144,
-86163,
-86163,
-86170,
-86202,
-86253,
-86310,
-86310,
-86337,
-86344,
-86361,
-86376,
-86410,
-86428,
-86428,
-86444,
-86456,
-86456,
-86456,
-86474,
-86492,
-86500,
-86500,
-86528,
-86528,
-86541,
-86541,
-86562,
-86582,
-86602,
-86615,
-86615,
+84682,
+84689,
+84699,
+84699,
+84709,
+84709,
+84709,
+84709,
+84709,
+84709,
+84709,
+84724,
+84733,
+84733,
+84741,
+84741,
+84776,
+84776,
+84776,
+84795,
+84825,
+84834,
+84834,
+84841,
+84851,
+84861,
+84871,
+84871,
+84882,
+84882,
+84892,
+84927,
+84932,
+84966,
+84984,
+84984,
+85015,
+85039,
+85051,
+85088,
+85088,
+85088,
+85088,
+85108,
+85134,
+85163,
+85163,
+85163,
+85174,
+85180,
+85198,
+85198,
+85198,
+85198,
+85230,
+85257,
+85257,
+85278,
+85278,
+85278,
+85278,
+85324,
+85365,
+85377,
+85414,
+85420,
+85436,
+85465,
+85490,
+85490,
+85501,
+85501,
+85529,
+85553,
+85553,
+85560,
+85560,
+85571,
+85571,
+85571,
+85571,
+85571,
+85571,
+85598,
+85598,
+85598,
+85620,
+85649,
+85649,
+85664,
+85664,
+85675,
+85687,
+85687,
+85687,
+85687,
+85687,
+85687,
+85705,
+85705,
+85717,
+85755,
+85755,
+85765,
+85765,
+85784,
+85784,
+85784,
+85818,
+85848,
+85873,
+85904,
+85954,
+85954,
+85967,
+85974,
+85983,
+86022,
+86030,
+86050,
+86050,
+86050,
+86050,
+86087,
+86087,
+86087,
+86099,
+86099,
+86109,
+86127,
+86150,
+86161,
+86187,
+86187,
+86205,
+86217,
+86236,
+86243,
+86254,
+86254,
+86254,
+86270,
+86270,
+86282,
+86295,
+86304,
+86332,
+86332,
+86332,
+86332,
+86343,
+86343,
+86343,
+86343,
+86343,
+86354,
+86354,
+86354,
+86354,
+86354,
+86354,
+86372,
+86377,
+86398,
+86398,
+86421,
+86427,
+86427,
+86427,
+86427,
+86432,
+86454,
+86468,
+86468,
+86482,
+86482,
+86487,
+86498,
+86512,
+86512,
+86535,
+86544,
+86577,
86615,
-86645,
-86645,
-86666,
-86692,
-86720,
-86727,
-86734,
+86651,
+86672,
+86672,
+86672,
+86698,
+86698,
+86721,
+86721,
86757,
-86781,
-86801,
-86801,
-86801,
-86823,
-86853,
-86853,
-86870,
-86889,
-86895,
-86895,
+86757,
+86757,
+86778,
+86789,
+86789,
+86789,
+86809,
+86833,
+86833,
+86845,
+86867,
+86867,
+86867,
86895,
86920,
-86927,
-86939,
-86957,
-86981,
-86988,
-87009,
-87044,
-87044,
-87075,
-87108,
-87129,
-87146,
-87158,
-87176,
-87183,
-87213,
-87266,
-87284,
-87284,
-87291,
-87307,
-87307,
-87312,
-87339,
-87339,
-87346,
-87353,
-87385,
-87419,
-87419,
+86920,
+86920,
+86920,
+86982,
+86982,
+87000,
+87006,
+87067,
+87067,
+87067,
+87067,
+87077,
+87077,
+87085,
+87090,
+87106,
+87106,
+87112,
+87112,
+87112,
+87118,
+87127,
+87127,
+87127,
+87143,
+87143,
+87143,
+87143,
+87155,
+87155,
+87168,
+87168,
+87182,
+87182,
+87188,
+87188,
+87188,
+87188,
+87188,
+87204,
+87215,
+87236,
+87236,
+87236,
+87248,
+87257,
+87274,
+87282,
+87297,
+87297,
+87297,
+87297,
+87302,
+87321,
+87341,
+87341,
+87367,
+87367,
+87373,
+87379,
+87387,
+87406,
+87406,
+87406,
+87412,
+87426,
+87441,
+87441,
87441,
-87448,
-87470,
-87503,
-87503,
-87509,
-87509,
-87537,
-87561,
-87580,
-87580,
-87625,
-87632,
-87644,
-87656,
-87656,
-87656,
-87656,
-87656,
-87696,
-87713,
-87713,
-87713,
-87713,
-87713,
-87713,
+87449,
+87458,
+87458,
+87458,
+87467,
+87476,
+87541,
+87541,
+87541,
+87541,
+87577,
+87583,
+87583,
+87612,
+87612,
+87620,
+87626,
+87639,
+87639,
+87639,
+87661,
+87671,
+87686,
+87707,
+87707,
+87707,
87738,
-87746,
-87753,
-87753,
-87785,
-87800,
-87811,
-87823,
-87833,
+87738,
+87759,
+87770,
+87780,
+87797,
+87797,
+87810,
+87810,
+87819,
87833,
-87844,
-87844,
-87859,
-87878,
-87878,
-87889,
-87920,
-87925,
-87945,
-87945,
-87945,
-87964,
-87974,
-87974,
-87974,
-87980,
-87996,
-87996,
-87996,
-87996,
-88015,
-88015,
-88037,
-88037,
-88042,
-88054,
-88063,
-88070,
-88084,
-88084,
-88116,
-88125,
+87841,
+87869,
+87869,
+87869,
+87869,
+87885,
+87885,
+87899,
+87912,
+87929,
+87941,
+87955,
+87970,
+87984,
+87984,
+88000,
+88026,
+88026,
+88026,
+88026,
+88036,
+88051,
+88061,
+88104,
+88114,
+88114,
88125,
88125,
88125,
-88164,
-88164,
-88179,
-88179,
-88193,
-88193,
-88237,
-88237,
-88237,
-88237,
-88237,
-88237,
-88261,
-88270,
-88282,
-88293,
-88293,
-88310,
-88323,
-88345,
-88365,
-88385,
-88385,
-88385,
-88385,
-88385,
-88403,
-88403,
-88418,
-88418,
-88418,
-88453,
-88473,
-88483,
-88498,
-88508,
-88508,
-88529,
-88539,
-88550,
-88550,
-88550,
-88558,
-88581,
-88596,
-88596,
-88596,
-88596,
-88596,
-88596,
-88596,
+88132,
+88161,
+88166,
+88178,
+88178,
+88178,
+88178,
+88208,
+88213,
+88213,
+88220,
+88227,
+88227,
+88244,
+88260,
+88260,
+88266,
+88291,
+88297,
+88297,
+88297,
+88334,
+88334,
+88366,
+88398,
+88415,
+88432,
+88442,
+88456,
+88478,
+88520,
+88520,
+88520,
+88569,
88617,
-88641,
-88650,
-88678,
-88678,
-88678,
-88700,
-88700,
-88714,
-88756,
-88762,
-88773,
-88828,
-88855,
-88861,
-88861,
-88892,
-88952,
-88962,
-88962,
-88962,
-88968,
-88993,
-88993,
-89003,
-89033,
-89033,
-89078,
-89086,
-89091,
-89102,
-89102,
-89127,
-89138,
-89138,
-89155,
-89166,
-89188,
-89188,
-89205,
-89211,
-89211,
-89211,
-89221,
-89221,
-89268,
+88626,
+88632,
+88632,
+88649,
+88661,
+88661,
+88693,
+88705,
+88705,
+88705,
+88705,
+88705,
+88712,
+88734,
+88779,
+88779,
+88779,
+88785,
+88785,
+88800,
+88817,
+88817,
+88824,
+88824,
+88868,
+88868,
+88868,
+88868,
+88868,
+88913,
+88936,
+88977,
+88990,
+89019,
+89025,
+89044,
+89068,
+89068,
+89085,
+89085,
+89085,
+89085,
+89131,
+89143,
+89143,
+89158,
+89168,
+89197,
+89202,
+89202,
+89207,
+89278,
89290,
-89303,
-89316,
+89309,
+89319,
89324,
-89383,
+89324,
+89344,
+89354,
+89354,
+89386,
89393,
-89404,
-89421,
-89437,
-89466,
-89466,
-89502,
-89502,
-89515,
+89405,
+89430,
+89430,
+89430,
+89438,
+89438,
+89489,
+89496,
+89511,
+89529,
89545,
-89580,
-89586,
-89586,
-89586,
-89591,
-89591,
-89620,
-89633,
-89649,
-89654,
-89694,
-89694,
-89706,
-89706,
-89706,
-89721,
-89721,
-89727,
-89727,
-89727,
-89756,
-89756,
-89756,
-89763,
-89782,
+89563,
+89569,
+89569,
+89569,
+89592,
+89598,
+89598,
+89598,
+89653,
+89659,
+89659,
+89669,
+89669,
+89690,
+89714,
+89722,
+89732,
+89776,
+89776,
+89776,
89782,
-89804,
-89804,
-89826,
-89826,
-89831,
-89840,
-89847,
+89795,
+89795,
+89795,
+89795,
+89813,
+89824,
+89824,
+89841,
+89848,
+89848,
+89848,
89858,
-89885,
-89885,
-89885,
-89920,
-89942,
-89949,
-89949,
-89949,
-89959,
-89971,
-89978,
-89984,
-89984,
-89999,
-90035,
-90053,
-90064,
-90075,
-90083,
-90083,
-90083,
-90101,
-90101,
-90116,
-90116,
-90150,
-90157,
-90157,
-90157,
-90168,
-90205,
-90205,
-90212,
-90212,
-90242,
-90274,
-90280,
-90292,
-90302,
-90302,
-90302,
-90309,
-90309,
-90321,
-90327,
-90343,
-90399,
-90426,
-90435,
-90435,
-90453,
-90459,
-90459,
-90476,
-90476,
-90482,
-90502,
-90502,
+89858,
+89891,
+89891,
+89918,
+89928,
+89928,
+89947,
+89977,
+89977,
+89977,
+89977,
+89998,
+90025,
+90025,
+90065,
+90071,
+90086,
+90086,
+90086,
+90104,
+90104,
+90136,
+90163,
+90163,
+90163,
+90163,
+90169,
+90194,
+90194,
+90194,
+90194,
+90207,
+90224,
+90247,
+90256,
+90256,
+90262,
+90275,
+90275,
+90293,
+90303,
+90303,
+90303,
+90361,
+90376,
+90417,
+90428,
+90452,
+90491,
90502,
-90522,
-90522,
-90536,
-90563,
-90563,
-90583,
-90583,
-90583,
-90604,
-90604,
-90610,
-90610,
-90610,
-90610,
-90629,
-90629,
-90654,
-90663,
-90669,
-90690,
-90699,
-90699,
-90699,
-90729,
-90752,
-90752,
-90758,
-90758,
-90774,
-90780,
-90825,
-90845,
-90857,
-90857,
-90857,
-90857,
-90873,
-90905,
-90905,
-90905,
-90920,
-90920,
-90920,
-90963,
-90969,
-90987,
-90987,
+90509,
+90515,
+90538,
+90564,
+90594,
+90638,
+90638,
+90638,
+90638,
+90659,
+90668,
+90683,
+90691,
+90698,
+90706,
+90724,
+90735,
+90770,
+90770,
+90778,
+90778,
+90795,
+90795,
+90795,
+90795,
+90831,
+90831,
+90869,
+90883,
+90901,
+90907,
+90913,
+90929,
+90929,
+90959,
+90977,
90987,
-91004,
-91023,
-91029,
-91029,
-91061,
-91061,
-91061,
-91067,
-91073,
-91093,
-91093,
-91093,
-91101,
-91126,
-91126,
-91126,
-91126,
-91131,
-91178,
-91185,
-91195,
-91216,
+91007,
+91019,
+91033,
+91039,
+91104,
+91104,
+91110,
+91110,
+91110,
+91124,
+91130,
+91136,
+91157,
+91163,
+91163,
+91169,
+91209,
+91209,
+91225,
+91225,
+91225,
+91225,
91241,
-91268,
-91268,
-91268,
-91278,
-91288,
-91297,
-91297,
-91297,
-91314,
-91320,
-91320,
-91320,
-91328,
-91328,
-91345,
-91365,
-91365,
-91365,
-91365,
-91386,
-91422,
-91449,
-91458,
-91495,
-91533,
-91551,
-91579,
-91579,
-91579,
-91624,
-91631,
-91631,
-91631,
-91639,
-91657,
-91688,
-91709,
-91709,
-91709,
-91709,
-91709,
-91709,
-91709,
-91715,
-91743,
-91777,
-91777,
-91800,
-91817,
-91817,
-91848,
-91848,
-91858,
-91858,
-91867,
-91884,
-91884,
-91900,
-91900,
-91900,
-91913,
-91919,
-91926,
-91934,
-91947,
-91947,
-91947,
-91965,
-91965,
-91965,
-91972,
-91982,
-92009,
-92036,
+91241,
+91253,
+91273,
+91273,
+91283,
+91304,
+91310,
+91337,
+91354,
+91354,
+91354,
+91354,
+91368,
+91381,
+91381,
+91416,
+91435,
+91441,
+91441,
+91441,
+91441,
+91441,
+91463,
+91489,
+91504,
+91504,
+91520,
+91520,
+91520,
+91566,
+91566,
+91576,
+91576,
+91594,
+91599,
+91599,
+91610,
+91610,
+91619,
+91635,
+91641,
+91675,
+91683,
+91683,
+91683,
+91683,
+91683,
+91683,
+91683,
+91683,
+91749,
+91749,
+91749,
+91749,
+91760,
+91809,
+91814,
+91814,
+91814,
+91824,
+91824,
+91835,
+91847,
+91865,
+91879,
+91891,
+91935,
+91935,
+91955,
+91986,
+91996,
+91996,
+91996,
+92023,
+92057,
92057,
-92068,
-92068,
-92093,
-92107,
-92114,
-92120,
-92206,
-92218,
-92218,
-92218,
-92218,
-92233,
-92233,
-92290,
-92303,
-92303,
-92315,
-92315,
-92315,
-92326,
-92339,
-92360,
-92360,
-92372,
-92372,
-92387,
-92387,
-92387,
-92407,
-92431,
-92453,
-92453,
-92453,
-92471,
-92494,
-92494,
-92515,
-92539,
-92557,
-92557,
-92562,
-92573,
-92573,
-92595,
-92601,
-92633,
-92633,
-92633,
-92675,
-92706,
-92706,
-92723,
-92729,
-92729,
-92745,
-92745,
-92760,
-92760,
-92806,
-92831,
-92844,
-92844,
-92850,
-92850,
-92856,
-92856,
-92881,
-92913,
+92062,
+92103,
+92111,
+92117,
+92117,
+92117,
+92117,
+92117,
+92117,
+92117,
+92136,
+92157,
+92192,
+92203,
+92203,
+92223,
+92223,
+92241,
+92241,
+92241,
+92241,
+92241,
+92281,
+92319,
+92329,
+92329,
+92351,
+92358,
+92358,
+92358,
+92371,
+92390,
+92404,
+92410,
+92410,
+92423,
+92423,
+92449,
+92491,
+92532,
+92532,
+92540,
+92546,
+92552,
+92572,
+92572,
+92572,
+92592,
+92603,
+92603,
+92603,
+92626,
+92658,
+92666,
+92666,
+92666,
+92672,
+92714,
+92714,
+92724,
+92744,
+92776,
+92776,
+92797,
+92797,
+92828,
+92828,
+92847,
+92847,
+92874,
+92874,
+92874,
+92892,
+92900,
+92900,
+92900,
92930,
-92941,
-92956,
-92967,
-92967,
+92930,
+92936,
+92936,
+92944,
+92962,
+92977,
92977,
-93000,
-93006,
-93025,
-93051,
-93066,
-93079,
-93091,
-93091,
-93097,
-93103,
-93103,
-93133,
-93133,
-93133,
-93139,
-93139,
-93139,
-93158,
-93164,
-93191,
-93191,
-93191,
+92983,
+93027,
+93033,
+93033,
+93050,
+93082,
+93107,
+93125,
+93125,
+93125,
+93143,
+93143,
+93157,
+93157,
+93157,
+93157,
+93187,
+93187,
+93194,
+93194,
93206,
-93220,
-93235,
-93251,
-93251,
-93251,
-93257,
-93265,
-93265,
-93271,
-93323,
-93341,
-93358,
-93373,
-93390,
-93390,
-93390,
-93398,
-93398,
-93398,
-93407,
-93413,
-93422,
-93428,
-93428,
-93452,
-93477,
-93500,
-93508,
-93529,
-93535,
-93535,
-93561,
-93561,
-93561,
-93594,
-93601,
-93617,
-93617,
-93625,
-93642,
-93659,
-93669,
-93669,
-93675,
-93675,
-93691,
-93691,
-93703,
-93718,
-93718,
-93725,
-93725,
-93725,
-93725,
-93733,
-93733,
-93733,
-93733,
-93749,
-93772,
-93799,
-93814,
-93814,
-93839,
-93861,
-93861,
-93861,
-93861,
-93861,
-93883,
-93883,
-93883,
+93206,
+93212,
+93229,
+93258,
+93285,
+93297,
+93297,
+93297,
+93297,
+93343,
+93343,
+93343,
+93370,
+93387,
+93387,
+93387,
+93387,
+93387,
+93412,
+93417,
+93430,
+93430,
+93430,
+93430,
+93430,
+93430,
+93430,
+93436,
+93455,
+93464,
+93483,
+93496,
+93496,
+93513,
+93513,
+93513,
+93554,
+93584,
+93584,
+93584,
+93584,
+93592,
+93602,
+93607,
+93631,
+93657,
+93664,
+93672,
+93744,
+93753,
+93753,
+93761,
+93776,
+93776,
+93776,
+93776,
+93776,
+93776,
+93810,
+93822,
+93822,
+93852,
+93871,
+93884,
93897,
-93910,
-93917,
-93917,
-93940,
-93940,
-93956,
-93956,
-93968,
-93985,
-94005,
-94005,
-94005,
-94011,
-94035,
-94035,
-94066,
-94089,
-94089,
-94089,
-94108,
-94132,
-94157,
-94175,
-94175,
-94183,
-94212,
-94218,
+93914,
+93926,
+93939,
+93939,
+93954,
+93954,
+93954,
+93954,
+93969,
+93977,
+93977,
+93977,
+93990,
+93990,
+94031,
+94062,
+94068,
+94068,
+94068,
+94099,
+94123,
+94141,
+94191,
+94209,
+94209,
+94209,
94228,
-94234,
-94257,
-94270,
-94270,
-94270,
-94270,
-94292,
-94308,
-94314,
-94314,
-94331,
-94331,
-94355,
-94380,
-94424,
-94445,
-94445,
-94445,
-94445,
-94467,
-94473,
-94488,
-94497,
-94515,
-94524,
-94531,
-94571,
-94571,
-94587,
-94610,
-94620,
-94620,
-94627,
-94633,
-94643,
-94643,
-94643,
-94661,
-94661,
-94661,
-94661,
-94668,
-94668,
-94668,
-94668,
-94696,
-94696,
-94696,
-94696,
-94711,
+94263,
+94263,
+94298,
+94307,
+94321,
+94321,
+94327,
+94327,
+94358,
+94358,
+94358,
+94370,
+94370,
+94370,
+94370,
+94377,
+94410,
+94464,
+94496,
+94513,
+94542,
+94548,
+94548,
+94563,
+94569,
+94575,
+94593,
+94593,
+94593,
+94593,
+94613,
+94613,
+94618,
+94618,
+94618,
+94625,
+94637,
+94644,
+94650,
+94663,
+94682,
+94695,
+94728,
+94728,
+94734,
94734,
-94756,
-94756,
-94794,
-94807,
-94820,
-94837,
-94857,
-94857,
-94868,
-94878,
-94884,
-94884,
-94884,
-94915,
-94935,
-94935,
-94994,
-95020,
-95020,
-95028,
-95028,
-95028,
-95028,
-95042,
-95052,
-95062,
-95076,
-95099,
-95120,
-95126,
-95156,
-95165,
-95218,
-95218,
-95230,
-95230,
-95230,
-95230,
-95242,
-95284,
+94759,
+94789,
+94814,
+94826,
+94826,
+94826,
+94840,
+94840,
+94840,
+94871,
+94877,
+94877,
+94885,
+94885,
+94885,
+94892,
+94892,
+94904,
+94904,
+94904,
+94904,
+94904,
+94904,
+94904,
+94920,
+94920,
+94941,
+94959,
+94959,
+94959,
+94959,
+94959,
+94971,
+95005,
+95034,
+95034,
+95068,
+95073,
+95098,
+95098,
+95098,
+95115,
+95144,
+95153,
+95170,
+95170,
+95207,
+95227,
+95227,
+95250,
+95264,
+95264,
+95264,
+95280,
95303,
-95316,
-95329,
-95329,
-95329,
-95361,
-95398,
-95411,
-95411,
-95427,
-95427,
-95462,
-95481,
-95496,
-95496,
-95508,
-95540,
-95540,
-95558,
-95558,
-95585,
-95585,
-95597,
-95607,
-95643,
-95674,
-95688,
-95688,
-95688,
-95718,
-95718,
-95731,
-95750,
-95750,
-95750,
-95768,
-95768,
-95776,
-95776,
-95776,
-95776,
-95776,
-95776,
-95776,
-95804,
-95804,
-95822,
-95829,
-95836,
-95836,
-95836,
-95836,
-95849,
-95849,
-95861,
-95861,
-95861,
-95886,
-95886,
-95886,
-95893,
-95893,
-95911,
+95303,
+95303,
+95319,
+95319,
+95319,
+95342,
+95364,
+95407,
+95420,
+95420,
+95435,
+95435,
+95452,
+95452,
+95452,
+95470,
+95476,
+95505,
+95536,
+95536,
+95536,
+95536,
+95536,
+95536,
+95568,
+95568,
+95587,
+95629,
+95629,
+95640,
+95647,
+95660,
+95705,
+95742,
+95754,
+95825,
+95831,
+95848,
+95848,
+95848,
+95868,
+95888,
95911,
-95918,
-95918,
-95951,
-95951,
-95951,
-95961,
-95998,
-95998,
-95998,
-95998,
-96013,
-96013,
-96013,
-96013,
-96027,
-96057,
-96065,
-96065,
-96076,
-96076,
-96076,
-96076,
-96108,
-96120,
-96120,
-96120,
-96129,
-96156,
-96156,
+95936,
+95936,
+95979,
+96003,
+96016,
+96047,
+96047,
+96059,
+96082,
+96107,
+96107,
+96119,
+96133,
+96157,
+96169,
+96169,
+96169,
96177,
-96189,
-96201,
-96211,
-96211,
-96211,
-96211,
-96232,
-96232,
-96244,
-96263,
-96280,
-96280,
-96301,
-96301,
-96301,
-96321,
-96321,
-96321,
-96333,
-96351,
-96363,
-96363,
-96381,
-96387,
-96394,
-96394,
-96399,
-96399,
-96428,
-96441,
-96441,
-96441,
-96454,
-96463,
-96471,
-96471,
-96481,
-96521,
-96521,
-96534,
-96534,
-96544,
-96566,
-96566,
-96566,
-96566,
-96596,
-96596,
-96596,
-96596,
-96611,
-96611,
-96611,
-96611,
-96629,
-96629,
-96642,
+96177,
+96203,
+96234,
+96234,
+96234,
+96247,
+96268,
+96274,
+96274,
+96315,
+96354,
+96372,
+96372,
+96372,
+96392,
+96407,
+96444,
+96444,
+96470,
+96510,
+96527,
+96562,
+96583,
+96583,
+96599,
+96599,
+96599,
96642,
-96662,
-96662,
-96676,
-96689,
-96689,
-96699,
-96714,
-96725,
-96725,
-96741,
-96769,
-96769,
-96775,
-96775,
-96783,
-96783,
-96783,
-96801,
-96817,
-96834,
-96834,
-96834,
-96834,
-96844,
-96860,
-96889,
-96929,
-96929,
-96945,
-96945,
-96975,
-96985,
-97002,
+96657,
+96657,
+96657,
+96698,
+96720,
+96735,
+96735,
+96761,
+96802,
+96802,
+96814,
+96826,
+96826,
+96843,
+96855,
+96866,
+96884,
+96896,
+96896,
+96905,
+96905,
+96905,
+96905,
+96905,
+96933,
+96933,
+96933,
+96933,
+96950,
+96950,
+96950,
+96950,
+96965,
+96974,
+96992,
+96992,
+97012,
+97041,
97047,
-97062,
-97062,
-97069,
-97069,
-97082,
-97082,
-97093,
-97126,
-97150,
-97150,
-97150,
-97150,
-97150,
-97175,
-97175,
-97175,
-97175,
-97175,
-97175,
-97196,
-97196,
-97196,
+97091,
+97091,
+97091,
+97098,
+97098,
+97120,
+97138,
+97138,
97196,
-97213,
-97232,
-97249,
-97249,
-97276,
-97289,
-97296,
-97307,
-97307,
-97314,
-97338,
-97338,
-97338,
-97358,
-97375,
-97387,
-97408,
-97408,
-97408,
-97408,
-97425,
-97461,
-97483,
-97502,
-97502,
-97509,
-97509,
-97509,
-97518,
-97540,
-97553,
-97553,
-97553,
+97227,
+97227,
+97255,
+97267,
+97267,
+97292,
+97331,
+97355,
+97365,
+97373,
+97457,
+97457,
+97457,
+97519,
+97519,
+97534,
+97548,
+97548,
97570,
-97576,
-97576,
-97576,
-97610,
-97610,
-97618,
-97624,
-97630,
-97640,
-97674,
-97699,
-97699,
-97709,
-97709,
-97709,
-97709,
-97720,
-97740,
-97740,
-97740,
-97759,
-97759,
-97759,
-97769,
-97776,
-97829,
-97829,
-97829,
-97863,
-97863,
-97887,
-97904,
-97914,
-97914,
+97593,
+97613,
+97631,
+97661,
+97667,
+97689,
+97717,
+97717,
+97717,
+97735,
+97735,
+97735,
+97745,
+97771,
+97786,
+97798,
+97798,
+97839,
+97839,
+97839,
+97848,
+97848,
+97867,
+97918,
+97918,
+97918,
97927,
-97937,
-97947,
-97947,
-97947,
-97959,
-97959,
-97959,
-97977,
-98002,
-98016,
-98044,
-98044,
-98062,
-98062,
-98072,
-98072,
-98072,
-98072,
-98086,
-98105,
-98124,
-98132,
-98132,
-98148,
-98173,
-98185,
-98206,
-98240,
-98240,
-98259,
-98294,
-98320,
+97942,
+97942,
+97942,
+97942,
+97942,
+97967,
+97979,
+98012,
+98012,
+98054,
+98054,
+98078,
+98078,
+98106,
+98106,
+98115,
+98130,
+98130,
+98130,
+98130,
+98137,
+98137,
+98137,
+98144,
+98168,
+98188,
+98188,
+98202,
+98202,
+98220,
+98234,
+98266,
+98273,
+98292,
+98317,
+98328,
+98328,
98346,
98346,
98346,
-98379,
-98387,
-98415,
-98442,
-98469,
+98357,
+98357,
+98357,
+98365,
+98400,
+98412,
+98431,
+98438,
98477,
-98490,
-98528,
-98528,
-98528,
-98553,
-98562,
-98593,
-98608,
-98622,
-98630,
-98630,
-98637,
-98647,
+98488,
+98504,
+98504,
+98511,
+98540,
+98559,
+98566,
+98595,
+98601,
+98607,
+98615,
+98638,
+98651,
+98651,
+98651,
+98667,
+98667,
+98686,
98703,
-98733,
-98733,
-98733,
-98749,
-98749,
-98754,
-98759,
-98783,
-98783,
-98808,
-98827,
-98827,
+98703,
+98716,
+98728,
+98762,
+98762,
+98762,
+98779,
+98804,
98827,
-98853,
-98888,
-98888,
-98906,
-98906,
-98926,
-98954,
-98963,
-98963,
-98963,
-98973,
-98991,
-98997,
-98997,
-98997,
-98997,
-99014,
-99014,
-99014,
-99014,
-99022,
-99036,
-99036,
-99080,
-99096,
-99101,
-99101,
-99115,
-99125,
-99135,
-99135,
-99135,
-99163,
-99163,
-99163,
-99203,
-99203,
-99222,
-99222,
-99253,
-99253,
-99285,
-99308,
-99308,
-99308,
-99308,
-99333,
-99360,
-99394,
-99394,
-99408,
-99408,
-99414,
-99420,
-99420,
-99420,
-99469,
-99476,
-99476,
-99476,
-99498,
-99498,
-99498,
-99528,
-99528,
+98833,
+98847,
+98865,
+98865,
+98865,
+98865,
+98876,
+98876,
+98876,
+98895,
+98905,
+98905,
+98946,
+98946,
+98946,
+98946,
+98977,
+99002,
+99019,
+99026,
+99026,
+99038,
+99051,
+99078,
+99106,
+99113,
+99126,
+99144,
+99164,
+99164,
+99189,
+99238,
+99245,
+99257,
+99288,
+99306,
+99306,
+99334,
+99355,
+99383,
+99437,
+99437,
+99458,
+99485,
+99505,
+99517,
99528,
-99546,
-99552,
-99558,
-99576,
-99576,
-99576,
-99600,
-99611,
-99611,
-99621,
-99636,
-99636,
-99636,
-99636,
-99636,
-99636,
-99636,
-99687,
-99687,
-99721,
-99728,
+99553,
+99560,
+99573,
+99590,
+99602,
+99624,
+99624,
+99631,
+99638,
+99657,
+99688,
+99701,
+99708,
99747,
-99753,
-99753,
-99753,
-99796,
-99801,
-99817,
-99826,
-99858,
-99858,
-99873,
-99873,
-99873,
-99912,
-99912,
-99912,
-99912,
-99939,
-99939,
-99939,
-99939,
-99953,
-99963,
-100010,
-100045,
-100056,
-100056,
-100078,
-100078,
-100078,
-100093,
-100098,
-100098,
-100098,
-100106,
-100113,
-100126,
-100126,
-100126,
-100126,
-100126,
-100126,
-100131,
-100156,
-100156,
-100166,
-100166,
-100166,
-100186,
-100186,
-100186,
-100186,
-100219,
-100236,
-100236,
-100236,
-100236,
-100287,
-100305,
-100313,
-100313,
-100328,
-100328,
-100328,
-100328,
-100352,
-100352,
-100352,
-100352,
-100363,
-100399,
-100399,
-100399,
-100417,
-100433,
-100446,
-100446,
-100464,
-100464,
-100464,
-100521,
-100530,
-100539,
-100565,
-100583,
-100591,
-100601,
-100612,
-100612,
-100612,
-100612,
-100612,
-100618,
-100644,
-100644,
-100652,
-100685,
-100695,
-100695,
-100706,
-100712,
-100749,
-100766,
-100811,
-100834,
-100834,
-100860,
-100869,
-100869,
-100869,
-100889,
-100907,
-100907,
-100913,
-100932,
-100932,
-100932,
-100932,
-100932,
-100932,
+99759,
+99781,
+99781,
+99804,
+99822,
+99841,
+99841,
+99859,
+99859,
+99859,
+99877,
+99890,
+99913,
+99930,
+99944,
+99976,
+100005,
+100005,
+100018,
+100025,
+100025,
+100032,
+100032,
+100048,
+100059,
+100059,
+100086,
+100095,
+100111,
+100138,
+100153,
+100169,
+100214,
+100222,
+100230,
+100267,
+100274,
+100284,
+100293,
+100293,
+100329,
+100347,
+100357,
+100377,
+100387,
+100387,
+100397,
+100397,
+100409,
+100425,
+100425,
+100425,
+100441,
+100455,
+100472,
+100472,
+100479,
+100508,
+100508,
+100517,
+100549,
+100549,
+100568,
+100578,
+100603,
+100603,
+100610,
+100610,
+100641,
+100682,
+100690,
+100705,
+100723,
+100743,
+100743,
+100750,
+100763,
+100763,
+100822,
+100844,
+100865,
+100877,
+100877,
+100877,
+100884,
+100891,
+100903,
+100926,
100950,
100950,
-100963,
-100963,
-101015,
-101026,
+100968,
+100968,
+100987,
+101007,
+101027,
+101027,
+101027,
+101034,
+101034,
+101041,
101048,
-101048,
-101084,
-101090,
-101103,
-101119,
-101119,
-101119,
-101137,
-101160,
-101171,
-101180,
-101186,
-101194,
-101194,
-101212,
-101237,
-101260,
-101260,
-101260};
+101055,
+101105,
+101126,
+101142,
+101149,
+101156,
+101163,
+101163,
+101205,
+101205,
+101228,
+101228,
+101228,
+101228,
+101228,
+101228,
+101250,
+101275,
+101282,
+101282,
+101310,
+101316,
+101316,
+101316,
+101323,
+101344,
+101366,
+101392,
+101399,
+101424,
+101441,
+101441,
+101441,
+101441,
+101464,
+101500,
+101520,
+101537,
+101544,
+101552,
+101552,
+101580,
+101580,
+101610,
+101620,
+101627,
+101634,
+101649,
+101656,
+101663,
+101670,
+101670,
+101686,
+101686,
+101693,
+101720,
+101720,
+101748,
+101765,
+101786,
+101802,
+101809,
+101828};
static const char *tldData[] = {
-"ac.lk\0lu.eu.org\0me.eu.org\0"
-"hazu.aichi.jp\0"
-"ac.ma\0auto.pl\0"
-"meme\0"
-"ac.me\0"
-"kuokgroup\0"
-"trentinsu\xcc\x88""d-tirol.it\0holtalen.no\0"
-"alibaba\0"
-"\xd9\x85\xd9\x88\xd8\xa8\xd8\xa7\xd9\x8a\xd9\x84\xd9\x8a\0"
-"k12.ct.us\0hu.com\0"
-"lib.ar.us\0"
-"bbs.tr\0"
-"arao.kumamoto.jp\0no-ip.biz\0"
-"js.cn\0s3-fips-us-gov-west-1.amazonaws.com\0"
-"ac.mu\0"
-"bato.tochigi.jp\0agriculture.museum\0"
-"ac.mw\0"
-"h.se\0"
-"ac.ni\0home.dyndns.org\0"
-"umi.fukuoka.jp\0ac.mz\0varoy.no\0"
-"lv.eu.org\0"
-"slg.br\0bando.ibaraki.jp\0community.museum\0"
-"s\xc3\xb8rfold.no\0"
-"nysa.pl\0travelers\0"
-"krokstadelva.no\0is-a-lawyer.com\0"
-"baseball.museum\0"
-"southcarolina.museum\0"
-"menu\0verisign\0"
-"kddi\0"
-"fc.it\0docs\0nfshost.com\0"
-"outsystemscloud.com\0"
-"larsson.museum\0med.pro\0"
-"forli\xcc\x80""cesena.it\0arts.nf\0ac.nz\0"
-"\xe3\x82\xb9\xe3\x83\x88\xe3\x82\xa2\0"
-"tsuruta.aomori.jp\0"
-"sp.it\0ac.pa\0fhapp.xyz\0"
-"study\0"
-"misato.akita.jp\0rocher\0"
-"us-1.evennode.com\0"
-"ralingen.no\0"
-"nesna.no\0ddnsfree.com\0"
-"urakawa.hokkaido.jp\0tychy.pl\0"
-"webhop.org\0"
-"artgallery.museum\0"
-"saigawa.fukuoka.jp\0state.museum\0"
-"contagem.br\0snasa.no\0"
-"museum\0doomdns.org\0"
-"tone.ibaraki.jp\0"
-"bashkiria.ru\0"
-"ac.pr\0"
-"uchiko.ehime.jp\0sue.fukuoka.jp\0toyosato.shiga.jp\0es.leg.br\0"
-"asahi.nagano.jp\0es.kr\0from-wa.com\0"
-"ooshika.nagano.jp\0"
-"kasukabe.saitama.jp\0"
-"sumita.iwate.jp\0"
-"nannestad.no\0\xe5\x81\xa5\xe5\xba\xb7\0"
-"teshikaga.hokkaido.jp\0"
-"slattum.no\0"
-"bashkiria.su\0"
-"trentinos-tirol.it\0"
-"laz.it\0"
-"edu.ac\0"
-"memorial\0"
-"edu.af\0"
-"k12.id.us\0"
-"from-la.net\0"
-"edu.al\0feedback\0"
-"vik.no\0"
-"ketrzyn.pl\0ac.rs\0"
-"doha\0"
-"edu.ba\0okaya.nagano.jp\0ac.ru\0ac.se\0cloudcontrolled.com\0"
-"edu.ar\0edu.bb\0kunisaki.oita.jp\0"
-"ac.rw\0s3.dualstack.eu-central-1.amazonaws.com\0from-al.com\0"
-"kouzushima.tokyo.jp\0"
-"edu.au\0is-a-knight.org\0"
-"edu.bh\0"
-"edu.bi\0inc.hk\0"
-"edu.az\0yamashina.kyoto.jp\0time.museum\0"
-"ishikawa.fukushima.jp\0naruto.tokushima.jp\0myravendb.com\0"
-"stage.nodeart.io\0"
-"edu.bm\0"
-"edu.bn\0"
-"edu.bo\0"
-"lplfinancial\0ltd.ua\0"
-"edu.br\0"
-"edu.bs\0"
-"edu.bt\0ac.th\0"
-"ac.sz\0ac.tj\0"
-"taki.mie.jp\0"
-"edu.ci\0"
-"edu.bz\0ltd.uk\0"
-"github.io\0""32-b.it\0"
-"hidaka.hokkaido.jp\0school\0"
-"edu.cn\0acct.pro\0"
-"edu.co\0"
-"windmill.museum\0"
-"nittedal.no\0"
-"r\xc3\xb8st.no\0ac.ug\0unicom\0"
-"edu.cu\0"
-"latina.it\0oristano.it\0shakotan.hokkaido.jp\0ac.tz\0"
-"edu.cw\0ac.uk\0"
-"anan.nagano.jp\0notteroy.no\0"
-"miyawaka.fukuoka.jp\0"
-"accident-investigation.aero\0"
-"edu.dm\0gifu.gifu.jp\0"
-"edu.do\0"
-"kokubunji.tokyo.jp\0kawanishi.yamagata.jp\0thruhere.net\0"
-"zentsuji.kagawa.jp\0"
-"edu.ec\0"
-"\xc3\xa5seral.no\0mincom.tn\0"
-"edu.ee\0marine.ru\0"
-"equipment.aero\0"
-"edu.eg\0kr.eu.org\0"
-"arq.br\0"
-"tabuse.yamaguchi.jp\0hamburg.museum\0"
-"edu.dz\0ac.vn\0"
-"emr.it\0"
-"from-mi.com\0"
-"christiansburg.museum\0"
-"edu.es\0kami.miyagi.jp\0"
-"edu.et\0fitness\0*.kunden.ortsinfo.at\0"
-"tokoname.aichi.jp\0daegu.kr\0"
-"ck.ua\0"
-"mobara.chiba.jp\0"
-"hsbc\0icbc\0"
-"\xe5\xa5\x88\xe8\x89\xaf.jp\0k12.mt.us\0"
-"ven.it\0virgin\0yachts\0"
-"bjerkreim.no\0"
-"idv.hk\0namikata.ehime.jp\0tamatsukuri.ibaraki.jp\0luxe\0"
-"macerata.it\0microsoft\0"
-"minano.saitama.jp\0"
-"f.bg\0oseto.nagasaki.jp\0"
-"protection\0"
-"edu.ge\0from-ak.com\0"
-"aaa.pro\0"
-"edu.gh\0novara.it\0"
-"edu.gi\0"
-"maceio.br\0"
-"av.it\0turystyka.pl\0download\0"
-"edu.gl\0ringsaker.no\0africa\0"
-"edu.gn\0"
-"movimiento.bo\0"
-"edu.gp\0"
-"camdvr.org\0"
-"edu.gr\0skin\0"
-"edu.gt\0"
-"edu.gu\0usdecorativearts.museum\0"
-"pc.it\0"
-"edu.gy\0"
-"flora.no\0"
-"edu.hk\0perso.sn\0"
-"moskenes.no\0"
-"sk\xc3\xa5nland.no\0ac.za\0"
-"edu.hn\0"
-"annefrank.museum\0"
-"higashikurume.tokyo.jp\0"
-"powiat.pl\0"
-"sandnessjoen.no\0"
-"edu.ht\0yamagata.ibaraki.jp\0"
-"inzai.chiba.jp\0koto.shiga.jp\0godaddy\0"
-"niihama.ehime.jp\0flesberg.no\0"
-"ac.zm\0community\0viajes\0"
-"perso.tn\0observer\0"
-"cesenaforli.it\0cloudfront.net\0"
-"secure\0"
-"edu.in\0zamami.okinawa.jp\0"
-"volda.no\0"
-"edu.iq\0"
-"edu.is\0ac.zw\0"
-"edu.it\0"
-"fitjar.no\0"
-"sukagawa.fukushima.jp\0"
-"versailles.museum\0"
-"satsumasendai.kagoshima.jp\0educational.museum\0myphotos.cc\0"
-"shingu.fukuoka.jp\0shibata.miyagi.jp\0hemne.no\0"
-"oyamazaki.kyoto.jp\0"
-"nationalheritage.museum\0north-kazakhstan.su\0dscloud.biz\0"
-"edu.jo\0diskstation.me\0"
-"feira.br\0"
-"\xe0\xb2\xad\xe0\xb2\xbe\xe0\xb2\xb0\xe0\xb2\xa4\0vladikavkaz.ru\0"
-"tranby.no\0"
-"lib.ca.us\0"
-"edu.kg\0"
-"edu.ki\0"
-"windows\0"
-"edu.km\0"
-"edu.kn\0"
-"diskstation.eu\0"
-"edu.kp\0lib.pr.us\0"
-"kyonan.chiba.jp\0munakata.fukuoka.jp\0edu.la\0andasuolo.no\0vladikavkaz.su\0"
-"edu.lb\0schaeffler\0tushu\0"
-"takatsuki.shiga.jp\0edu.lc\0"
-"slz.br\0koya.wakayama.jp\0meeres.museum\0"
-"aetna\0"
-"edu.kw\0game\0"
-"hanamaki.iwate.jp\0kuroiso.tochigi.jp\0edu.ky\0dscloud.mobi\0"
-"edu.kz\0"
-"edu.lk\0"
-"in-addr.arpa\0soja.okayama.jp\0hamar.no\0"
-"mito.ibaraki.jp\0"
-"ic.gov.pl\0"
-"cc.ga.us\0"
-"edu.lr\0bindal.no\0"
-"edu.me\0"
-"edu.lv\0naroy.no\0"
-"edu.mg\0"
-"ts.it\0"
-"edu.ly\0"
-"edu.mk\0"
-"edu.ml\0cc.tn.us\0"
-"edu.mn\0cruises\0"
-"edu.mo\0"
-"hasuda.saitama.jp\0"
-"um.gov.pl\0"
-"edu.ms\0sande.m\xc3\xb8re-og-romsdal.no\0"
-"kitagawa.kochi.jp\0edu.mt\0"
-"spy.museum\0stryn.no\0"
-"kamijima.ehime.jp\0edu.mv\0"
-"edu.mw\0edu.ng\0"
-"edu.mx\0house\0"
-"saga.saga.jp\0edu.my\0edu.ni\0"
-"edu.mz\0boldlygoingnowhere.org\0"
-"yoshioka.gunma.jp\0lajolla.museum\0"
-"pc.pl\0pagespeedmobilizer.com\0"
-"edu.nr\0"
-"minoh.osaka.jp\0"
-"masuda.shimane.jp\0"
-"commbank\0"
-"oiso.kanagawa.jp\0edu.om\0"
-"banamex\0"
-"sobetsu.hokkaido.jp\0trust.museum\0"
-"nesoddtangen.no\0"
-"edu.pa\0"
-"chesapeakebay.museum\0"
-"trentino-su\xcc\x88""d-tirol.it\0pacific.museum\0"
-"dyn.home-webserver.de\0"
+"edu.mt\0"
+"off.ai\0k12.dc.us\0"
+"edu.mv\0"
+"edu.mw\0edu.ng\0berlev\xc3\xa5g.no\0"
+"edu.mx\0"
+"edu.my\0edu.ni\0"
+"edu.mz\0fastpanel.direct\0"
+"suzuki\0s3-eu-west-1.amazonaws.com\0"
+"livinghistory.museum\0"
+"trentinoalto-adige.it\0dontexist.net\0"
+"hamburg.museum\0muos\xc3\xa1t.no\0"
+"cn-northwest-1.eb.amazonaws.com.cn\0"
+"edu.nr\0\xe0\xb8\x98\xe0\xb8\xb8\xe0\xb8\xa3\xe0\xb8\x81\xe0\xb8\xb4\xe0\xb8\x88.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0direct\0"
+"fl.us\0agency\0"
+"from-ok.com\0"
+"nishiizu.shizuoka.jp\0komae.tokyo.jp\0"
+"edu.om\0team\0doomdns.com\0"
+"vestre-slidre.no\0"
+"sweden.museum\0edu.pa\0"
+"newhampshire.museum\0"
"edu.pe\0"
-"edu.pf\0duckdns.org\0"
+"pro.az\0ar.it\0nishihara.kumamoto.jp\0edu.pf\0"
"edu.ph\0"
-"\xe6\xa0\x83\xe6\x9c\xa8.jp\0mk.ua\0"
-"edu.pk\0myiphost.com\0"
+"page\0"
+"hikimi.shimane.jp\0"
+"santafe.museum\0edu.pk\0"
"edu.pl\0"
-"jdf.br\0\xd8\xb9\xd8\xb1\xd8\xa7\xd9\x82\0"
-"edu.pn\0"
+"s3-ap-southeast-1.amazonaws.com\0home.dyndns.org\0"
+"pro.br\0edu.pn\0"
+"kasai.hyogo.jp\0clan.rip\0"
"edu.qa\0"
"edu.pr\0"
-"kunneppu.hokkaido.jp\0edu.ps\0"
-"edu.pt\0"
-"yabuki.fukushima.jp\0"
-"kr\xc3\xb8""dsherad.no\0mel\xc3\xb8y.no\0"
-"plurinacional.bo\0"
+"edu.ps\0mordovia.ru\0"
+"nysa.pl\0edu.pt\0"
+"\xe7\xbd\x91\xe7\xbb\x9c.hk\0ing.pa\0"
+"tech\0"
"edu.py\0"
-"shikokuchuo.ehime.jp\0"
-"kiyose.tokyo.jp\0"
-"miho.ibaraki.jp\0"
-"bolzano.it\0versicherung\0"
-"shisui.chiba.jp\0"
-"us.gov.pl\0"
-"cc.la.us\0"
-"aure.no\0"
-"\xe9\xb3\xa5\xe5\x8f\x96.jp\0"
-"kawanishi.nara.jp\0av.tr\0"
-"government.aero\0jampa.br\0"
-"sortland.no\0"
-"mymailer.com.tw\0"
-"edu.sa\0"
-"aerobatic.aero\0edu.sb\0defense.tn\0"
-"in.na\0edu.rs\0edu.sc\0"
-"sn.cn\0edu.sd\0"
+"ugim.gov.pl\0"
+"kameyama.mie.jp\0"
+"madrid.museum\0gjesdal.no\0"
+"elverum.no\0"
+"saotome.st\0"
+"sveio.no\0iveco\0"
+"gifu.jp\0"
+"k12.me.us\0"
+"samsclub\0now-dns.top\0"
+"pro.cy\0"
+"solund.no\0"
+"store\0"
+"nym.gr\0"
+"gjovik.no\0"
+"miyoshi.aichi.jp\0"
+"pro.ec\0convent.museum\0hopto.org\0"
+"ichikawamisato.yamanashi.jp\0"
+"edu.sa\0nym.gy\0"
+"edu.sb\0lamer\0"
+"edu.rs\0edu.sc\0"
+"edu.sd\0"
"edu.ru\0"
-"edu.rw\0edu.sg\0"
-"okuizumo.shimane.jp\0sykkylven.no\0weatherchannel\0"
-"in.ni\0"
-"edu.sl\0idv.tw\0review\0"
-"higashitsuno.kochi.jp\0channelsdvr.net\0"
+"map.fastlylb.net\0"
+"langevag.no\0edu.rw\0edu.sg\0"
+"bmd.br\0"
+"brasil.museum\0cc.ar.us\0"
+"edu.sl\0"
+"nym.ie\0"
"edu.sn\0"
-"selje.no\0"
-"edu.st\0"
-"kawanishi.hyogo.jp\0\xe0\xae\x87\xe0\xae\xb2\xe0\xae\x99\xe0\xaf\x8d\xe0\xae\x95\xe0\xaf\x88\0"
-"edu.sv\0"
-"free\0"
-"b\xc3\xa5""d\xc3\xa5""ddj\xc3\xa5.no\0azure\0"
-"kembuchi.hokkaido.jp\0edu.sy\0dev.static.land\0"
-"edu.tj\0"
-"k12.az.us\0"
-"sells-for-less.com\0"
-"edu.tm\0"
-"cloud66.ws\0"
+"muosat.no\0"
+"usa.museum\0"
+"oguni.kumamoto.jp\0edu.st\0"
+"friuli-ve-giulia.it\0edu.sv\0"
+"lg.ua\0"
+"edu.sy\0"
+"shiwa.iwate.jp\0edu.tj\0cheap\0"
+"tysfjord.no\0miami\0"
+"edu.tm\0apple\0"
+"kunimi.fukushima.jp\0iwi.nz\0"
"edu.to\0"
-"surnadal.no\0"
-"edu.ua\0dn.ua\0"
-"hi.cn\0edu.tr\0"
-"fukushima.fukushima.jp\0"
-"edu.tt\0"
-"kunstsammlung.museum\0bargains\0"
+"edu.ua\0"
+"cim.br\0edu.tr\0"
+"bindal.no\0arts.ve\0"
+"ikaruga.nara.jp\0edu.tt\0"
"edu.tw\0"
-"lib.ma.us\0"
-"yabu.hyogo.jp\0"
-"nagatoro.saitama.jp\0"
-"y.bg\0marriott\0"
-"associates\0builders\0diskstation.org\0"
-"okegawa.saitama.jp\0"
-"kikonai.hokkaido.jp\0edu.vc\0"
-"fujikawa.shizuoka.jp\0"
-"usculture.museum\0edu.ve\0"
-"ci.it\0bomlo.no\0"
-"omura.nagasaki.jp\0edu.uy\0"
-"hashima.gifu.jp\0"
-"casadelamoneda.museum\0hasura-app.io\0"
-"bulsan-su\xcc\x88""dtirol.it\0edu.vn\0"
-"friulivenezia-giulia.it\0"
-"pv.it\0childrensgarden.museum\0stj\xc3\xb8rdal.no\0"
-"shintoku.hokkaido.jp\0gs.va.no\0forgot.his.name\0"
-"familyds.com\0"
-"es.gov.br\0garden.museum\0edu.vu\0weather\0"
-"kudamatsu.yamaguchi.jp\0is-a-democrat.com\0crafting.xyz\0"
-"wa.gov.au\0taku.saga.jp\0"
-"mitane.akita.jp\0taka.hyogo.jp\0"
-"paris.museum\0"
-"\xd5\xb0\xd5\xa1\xd5\xb5\0"
-"f.se\0"
-"komoro.nagano.jp\0edu.ws\0george\0"
-"pmn.it\0in.rs\0"
-"aa.no\0"
-"kamisu.ibaraki.jp\0arai.shizuoka.jp\0iki.fi\0"
-"tokai.ibaraki.jp\0shiwa.iwate.jp\0"
-"telekommunikation.museum\0"
-"rokunohe.aomori.jp\0"
-"bounty-full.com\0"
-"cyber.museum\0"
-"chichibu.saitama.jp\0vantaa.museum\0jgora.pl\0hdfcbank\0"
-"is-a-conservative.com\0"
-"\xe9\xa6\x99\xe5\xb7\x9d.jp\0v\xc3\xa5gs\xc3\xb8y.no\0flights\0"
-"emp.br\0"
-"in.th\0movie\0"
-"mediocampidano.it\0"
-"frontdoor\0gbiz\0zappos\0"
-"fie.ee\0military.museum\0ovre-eiker.no\0"
-"shimosuwa.nagano.jp\0kep.tr\0"
-"edu.za\0\xe5\xae\xb6\xe9\x9b\xbb\0"
-"tajiri.osaka.jp\0"
-"abashiri.hokkaido.jp\0in.ua\0"
-"ikaruga.nara.jp\0\xc3\xa5s.no\0"
-"ribeirao.br\0aya.miyazaki.jp\0"
-"tokushima.jp\0"
-"assisi.museum\0"
-"edu.zm\0bofa\0"
-"sch.ae\0"
-"corvette.museum\0"
-"mikasa.hokkaido.jp\0"
-"in.us\0work\0"
-"iwata.shizuoka.jp\0"
-"amami.kagoshima.jp\0"
-"miyoshi.saitama.jp\0"
"eu-4.evennode.com\0"
-"flekkefjord.no\0kvalsund.no\0*.spectrum.myjino.ru\0"
-"ohtawara.tochigi.jp\0"
-"poltava.ua\0"
-"ikusaka.nagano.jp\0ikeda.osaka.jp\0"
-"\xd8\xa7\xd9\x84\xd9\x8a\xd9\x85\xd9\x86\0"
-"cc.va.us\0net.eu.org\0"
-"film.hu\0moscow.museum\0from-nh.com\0"
-"ris\xc3\xb8r.no\0"
-"nagahama.shiga.jp\0kv.ua\0trade\0"
-"e4.cz\0"
-"*.statics.cloud\0"
-"mitsue.nara.jp\0properties\0"
-"osen.no\0"
-"yoichi.hokkaido.jp\0"
-"fam.pk\0"
-"finearts.museum\0"
-"berkeley.museum\0"
-"furudono.fukushima.jp\0gs.ol.no\0"
-"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd9\x87\0"
-"monzabrianza.it\0"
-"dontexist.com\0"
-"penza.su\0"
-"takasu.hokkaido.jp\0gyeongbuk.kr\0cc.wy.us\0spb.ru\0"
-"motosu.gifu.jp\0"
-"imakane.hokkaido.jp\0"
-"servesarcasm.com\0"
-"yashiro.hyogo.jp\0"
-"naklo.pl\0"
-"kicks-ass.net\0"
-"equipment\0"
-"moroyama.saitama.jp\0eu-3.evennode.com\0"
-"avoues.fr\0lib.wa.us\0"
-"poa.br\0zara\0"
-"spb.su\0"
-"tozsde.hu\0"
-"homesecuritymac.com\0"
-"bitballoon.com\0"
-"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd8\xa9\0"
-"tools\0"
-"aizumisato.fukushima.jp\0dvrcam.info\0"
-"nikaho.akita.jp\0"
-"mi.it\0"
-"is-a-linux-user.org\0"
-"semboku.akita.jp\0iwanai.hokkaido.jp\0"
-"himeshima.oita.jp\0house.museum\0vf.no\0unj\xc3\xa1rga.no\0cc.md.us\0gallup\0"
-"attorney\0"
-"gd.cn\0"
-"audible\0richardli\0gdynia.pl\0"
-"k\xc3\xa5""fjord.no\0"
-"depot.museum\0"
-"ashoro.hokkaido.jp\0"
-"homeftp.org\0"
-"friulivegiulia.it\0sakae.chiba.jp\0"
+"shirahama.wakayama.jp\0"
+"yoshioka.gunma.jp\0"
+"stuttgart.museum\0sn\xc3\xa5sa.no\0"
+"edu.vc\0"
+"sicily.it\0"
+"edu.ve\0"
+"sakahogi.gifu.jp\0daigo.ibaraki.jp\0"
+"indianapolis.museum\0edu.uy\0s3.dualstack.eu-central-1.amazonaws.com\0nym.la\0"
+"iwamizawa.hokkaido.jp\0buzz\0piaget\0"
+"nym.lc\0"
+"edu.vn\0"
+"o.bg\0"
+"pro.ht\0"
+"skanland.no\0nym.li\0"
+"nym.kz\0"
+"riik.ee\0audio\0"
+"adachi.tokyo.jp\0"
+"edu.vu\0exnet.su\0"
+"iselect\0"
+"sanjo.niigata.jp\0"
+"jamison.museum\0abbvie\0"
+"za.bz\0"
+"sor-aurdal.no\0"
+"adult.ht\0nym.lt\0"
+"miners.museum\0is-an-actor.com\0nym.lu\0nym.me\0"
+"*.cns.joyent.com\0"
+"sv.it\0mukawa.hokkaido.jp\0oshu.iwate.jp\0kawanehon.shizuoka.jp\0krakow.pl\0"
+"edu.ws\0"
+"asahi.toyama.jp\0nym.mn\0"
+"from-ak.com\0"
+"preservation.museum\0"
+"rec.br\0oga.akita.jp\0"
+"okinawa\0"
+"chikuho.fukuoka.jp\0"
+"nym.mx\0"
+"levanger.no\0living\0"
+"8.bg\0space-to-rent.com\0"
+"tokushima.jp\0wanouchi.gifu.jp\0"
+"lifeinsurance\0"
+"\xe7\xa6\x8f\xe5\xb3\xb6.jp\0jetzt\0"
+"rec.co\0bible.museum\0"
+"ibaraki.jp\0usui.fukuoka.jp\0chungbuk.kr\0"
+"takamori.kumamoto.jp\0"
+"eu-3.evennode.com\0"
+"arts.ro\0"
+"is-a-lawyer.com\0"
+"edu.za\0is-a-student.com\0"
+"nym.nz\0"
+"nishikatsura.yamanashi.jp\0"
+"app.lmpm.com\0"
+"po.it\0nishigo.fukushima.jp\0"
"s3.dualstack.us-east-2.amazonaws.com\0"
-"d.bg\0aaa\0"
-"limanowa.pl\0"
-"kimitsu.chiba.jp\0digital\0"
-"cust.testing.thingdust.io\0"
-"chuo.yamanashi.jp\0"
-"vic.edu.au\0dellogliastra.it\0war.museum\0"
-"mitsubishi\0"
-"at.it\0"
-"hashikami.aomori.jp\0"
-"geometre-expert.fr\0"
-"ferrari\0"
-"sch.id\0graphics\0"
-"bond\0"
-"nagareyama.chiba.jp\0abb\0"
-"b\xc3\xb8.nordland.no\0abc\0"
-"pa.it\0kanuma.tochigi.jp\0webhop.net\0"
-"webhosting.be\0"
-"tomi.nagano.jp\0"
-"g\xc3\xa1ls\xc3\xa1.no\0"
-"lib.ak.us\0"
-"vibovalentia.it\0eu-2.evennode.com\0"
-"sch.ir\0fujixerox\0"
-"kamioka.akita.jp\0"
-"saskatchewan.museum\0"
-"kamikawa.hyogo.jp\0"
-"asahi.yamagata.jp\0"
-"harstad.no\0book\0"
-"aisho.shiga.jp\0"
-"dali.museum\0"
-"sch.jo\0from-ks.com\0"
-"lebesby.no\0"
-"sampa.br\0"
-"aco\0"
-"cagliari.it\0olbia-tempio.it\0"
-"obihiro.hokkaido.jp\0r\xc3\xb8ros.no\0kozow.com\0"
-"kyotanabe.kyoto.jp\0"
-"int.ar\0"
-"ri.it\0imabari.ehime.jp\0"
-"nakaniikawa.toyama.jp\0"
-"vanguard\0"
-"int.az\0""4lima.de\0"
-"rost.no\0"
-"ads\0"
-"homeunix.net\0"
-"int.bo\0"
-"sch.lk\0snoasa.no\0aeg\0memset.net\0"
-"bharti\0"
-"batsfjord.no\0"
-"katsuura.chiba.jp\0kashiba.nara.jp\0"
-"niiza.saitama.jp\0y.se\0"
-"hagebostad.no\0za.bz\0"
-"flight.aero\0"
-"int.ci\0dyndns-work.com\0"
-"revista.bo\0"
-"solund.no\0daplie.me\0"
-"ubank\0"
-"\xe7\xbd\x91\xe5\x9d\x80\0"
-"sch.ly\0marburg.museum\0odesa.ua\0"
-"int.co\0meguro.tokyo.jp\0"
-"hi.us\0video\0"
-"online.museum\0dvrdns.org\0"
-"afl\0eu-1.evennode.com\0"
-"nt.edu.au\0"
-"wios.gov.pl\0beats\0ftpaccess.cc\0global.prod.fastly.net\0"
-"\xe6\x96\xb0\xe6\xbd\x9f.jp\0"
-"rindal.no\0""4lima.at\0"
-"nl.ca\0sch.ng\0"
-"blogspot.co.at\0"
-"niigata.jp\0sydney.museum\0"
-"pesaro-urbino.it\0"
-"shizuoka.shizuoka.jp\0nerdpol.ovh\0"
-"\xe5\x8d\x83\xe8\x91\x89.jp\0hemsedal.no\0sandvikcoromant\0"
-"barreau.bj\0ohi.fukui.jp\0"
-"viking.museum\0\xd8\xa7\xd9\x84\xd9\x85\xd8\xba\xd8\xb1\xd8\xa8\0from-wy.com\0synology-diskstation.de\0"
-"shinjo.okayama.jp\0"
-"from-co.net\0"
-"4lima.ch\0"
-"pharmacy.museum\0actor\0"
-"muenster.museum\0embaixada.st\0"
-"association.museum\0"
-"dyndns.org\0"
-"jessheim.no\0"
-"\xd0\xbe\xd0\xb4.\xd1\x81\xd1\x80\xd0\xb1\0ieee\0\xe6\xb7\xa1\xe9\xa9\xac\xe9\x94\xa1\0"
-"gyeonggi.kr\0"
-"consultant.aero\0"
-"s3-eu-central-1.amazonaws.com\0"
-"bulsan-sudtirol.it\0"
-"museet.museum\0"
-"ecn.br\0brindisi.it\0"
-"studio\0"
-"ami.ibaraki.jp\0h\xc3\xa1mm\xc3\xa1rfeasta.no\0aig\0"
-"cisco\0"
-"ebetsu.hokkaido.jp\0"
-"denmark.museum\0kr.com\0"
-"sch.qa\0promo\0"
-"mi.th\0"
-"tomiya.miyagi.jp\0"
-"vao.it\0kawasaki.miyagi.jp\0cc.vt.us\0"
-"hekinan.aichi.jp\0"
-"bd.se\0"
-"nagaokakyo.kyoto.jp\0bill.museum\0"
-"kinder\0"
-"org.ac\0lib.ut.us\0accountant\0allstate\0from-ne.com\0"
-"org.ae\0"
-"org.af\0asso.fr\0"
-"org.ag\0kakinoki.shimane.jp\0"
-"wiw.gov.pl\0"
-"org.ai\0"
-"loyalist.museum\0gloppen.no\0fresenius\0"
-"guam.gu\0miyoshi.hiroshima.jp\0"
-"org.al\0"
-"mi.us\0"
-"aarborte.no\0"
-"shimonita.gunma.jp\0"
-"sch.sa\0\xe8\x87\xba\xe7\x81\xa3\0\xe7\x82\xb9\xe7\x9c\x8b\0"
-"org.ba\0"
-"org.ar\0org.bb\0"
-"asso.gp\0"
-"org.au\0sannan.hyogo.jp\0"
-"miyama.fukuoka.jp\0"
-"org.bh\0kosai.shizuoka.jp\0"
-"org.bi\0etc.br\0"
-"org.az\0"
-"nakatsugawa.gifu.jp\0"
-"futsu.nagasaki.jp\0paris\0"
-"org.bm\0int.is\0"
-"org.bn\0s3-ap-southeast-2.amazonaws.com\0"
-"org.bo\0"
-"minokamo.gifu.jp\0"
-"org.br\0"
-"org.bs\0"
-"org.bt\0for-the.biz\0"
-"karasuyama.tochigi.jp\0plants.museum\0static.land\0"
-"org.bw\0"
-"asso.ht\0"
-"org.ci\0"
-"org.bz\0"
-"union.aero\0*.platform.sh\0"
-"erotica.hu\0"
-"org.cn\0ino.kochi.jp\0"
-"org.co\0randaberg.no\0vindafjord.no\0"
-"hiraizumi.iwate.jp\0"
-"railway.museum\0swidnica.pl\0\xe0\xb8\xad\xe0\xb8\x87\xe0\xb8\x84\xe0\xb9\x8c\xe0\xb8\x81\xe0\xb8\xa3.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0"
-"friuli-vgiulia.it\0"
-"org.cu\0"
-"pa.us\0"
-"org.cw\0blogspot.co.id\0"
-"accountants\0"
-"org.cy\0"
-"kamimine.saga.jp\0naumburg.museum\0"
-"int.la\0stor-elvdal.no\0property\0"
-"org.dm\0statebank\0"
-"asso.bj\0"
-"org.do\0blogspot.co.il\0"
-"d\xc3\xb8nna.no\0"
-"misato.wakayama.jp\0"
-"org.ec\0saga.jp\0"
-"isa.us\0"
-"org.ee\0int.lk\0rade.no\0bukhara.su\0"
-"\xe6\xbb\x8b\xe8\xb3\x80.jp\0herokuapp.com\0"
-"org.eg\0experts-comptables.fr\0lease\0"
-"takarazuka.hyogo.jp\0"
-"niyodogawa.kochi.jp\0"
-"org.dz\0yasu.shiga.jp\0"
-"asso.ci\0anz\0"
-"w.bg\0aol\0"
-"amsterdam\0"
-"unjarga.no\0"
-"org.es\0"
-"org.et\0"
-"s3.ap-northeast-2.amazonaws.com\0"
-"gojome.akita.jp\0"
-"nerima.tokyo.jp\0"
-"\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4\xe0\xa4\xae\xe0\xa5\x8d\0"
-"val-d-aosta.it\0"
-"jp.eu.org\0"
-"sncf\0"
-"ri.us\0dodge\0"
-"mima.tokushima.jp\0int.mv\0"
-"int.mw\0"
-"pt.it\0southwest.museum\0"
-"int.ni\0s\xc3\xb8r-fron.no\0app\0kindle\0"
-"nishihara.okinawa.jp\0yandex\0"
-"org.ge\0pisa.it\0doesntexist.com\0"
-"watari.miyagi.jp\0yono.saitama.jp\0kosei.shiga.jp\0"
-"org.gg\0"
-"org.gh\0"
-"org.gi\0zhitomir.ua\0karaganda.su\0"
-"satte.saitama.jp\0"
-"mitaka.tokyo.jp\0frogn.no\0"
-"org.gl\0h\xc3\xb8yanger.no\0"
-"systems\0"
-"asso.dz\0org.gn\0sarpsborg.no\0"
-"swiss\0"
-"org.gp\0\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0\0"
-"org.gr\0d.se\0"
-"org.gt\0"
-"org.gu\0bar\0"
-"bbc\0"
-"tempio-olbia.it\0tobishima.aichi.jp\0"
-"elk.pl\0"
-"org.gy\0trentinoalto-adige.it\0"
-"aju.br\0org.hk\0"
-"tanabe.wakayama.jp\0apartments\0"
-"org.hn\0suginami.tokyo.jp\0"
-"pimienta.org\0"
-"fortworth.museum\0"
-"\xe7\x9f\xb3\xe5\xb7\x9d.jp\0"
-"org.ht\0nl.no\0"
-"org.hu\0"
-"art\0bbt\0"
-"barsy.info\0"
-"bcg\0education\0"
-"itoigawa.niigata.jp\0"
-"org.il\0hakusan.ishikawa.jp\0yamato.kanagawa.jp\0ina.nagano.jp\0sch.zm\0"
-"org.im\0ap-south-1.elasticbeanstalk.com\0"
-"org.in\0int.pt\0turen.tn\0chase\0"
-"l\xc3\xa4ns.museum\0"
-"org.iq\0valle\xcc\x81""edaoste.it\0bcn\0"
-"org.ir\0"
-"org.is\0byen.site\0"
-"org.je\0environmentalconservation.museum\0"
-"watchandclock.museum\0intel\0"
-"minamidaito.okinawa.jp\0bonn.museum\0"
-"doshi.yamanashi.jp\0"
-"daito.osaka.jp\0katano.osaka.jp\0"
-"taiwa.miyagi.jp\0"
-"org.jo\0"
-"a\xc3\xa9roport.ci\0"
-"miyake.nara.jp\0il.us\0"
-"org.kg\0"
-"org.ki\0"
-"q-a.eu.org\0"
-"org.km\0"
-"org.kn\0nuernberg.museum\0"
-"int.ru\0"
-"yamanashi.jp\0org.kp\0\xe0\xb8\x97\xe0\xb8\xab\xe0\xb8\xb2\xe0\xb8\xa3.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0pictures\0"
-"ueno.gunma.jp\0chiyoda.tokyo.jp\0org.la\0int.rw\0wi.us\0lamborghini\0"
-"org.lb\0"
-"org.lc\0"
-"eu.com\0"
-"sakura.chiba.jp\0"
-"org.kw\0bet\0virtualuser.de\0"
-"saroma.hokkaido.jp\0"
-"org.ky\0cincinnati.museum\0ybo.review\0"
-"org.kz\0"
-"org.lk\0gdansk.pl\0"
-"design.museum\0vlaanderen.museum\0"
-"society.museum\0"
-"org.ma\0smart\0"
-"org.lr\0australia.museum\0"
-"org.ls\0"
-"int.tj\0is-very-nice.org\0"
-"org.me\0"
-"marumori.miyagi.jp\0org.lv\0"
-"org.mg\0dnsup.net\0"
-"org.ly\0ddnsgeek.com\0"
-"org.mk\0"
-"org.ml\0\xd8\xa7\xd9\x8a\xd8\xb1\xd8\xa7\xd9\x86\0parts\0\xd8\xa8\xd8\xa7\xd8\xb2\xd8\xa7\xd8\xb1\0"
-"\xe5\x92\x8c\xe6\xad\x8c\xe5\xb1\xb1.jp\0omotego.fukushima.jp\0"
-"org.mn\0int.tt\0"
-"org.mo\0center\0"
-"freiburg.museum\0org.na\0"
-"journalist.aero\0chuo.tokyo.jp\0estate\0party\0"
-"org.ms\0"
-"org.mt\0axa\0"
-"org.mu\0"
-"calabria.it\0org.mv\0aws\0googleapis.com\0"
-"miners.museum\0org.mw\0org.ng\0"
-"niimi.okayama.jp\0toyama.toyama.jp\0org.mx\0"
-"org.my\0org.ni\0"
-"org.mz\0"
-"val-daosta.it\0oumu.hokkaido.jp\0"
-"naganohara.gunma.jp\0int.ve\0"
-"l\xc3\xb8renskog.no\0org.nr\0"
-"ens.tn\0\xd0\xb1\xd0\xb3\0"
-"\xe6\x9d\xb1\xe4\xba\xac.jp\0"
-"principe.st\0bid\0"
-"shiso.hyogo.jp\0int.vn\0"
-"org.nz\0"
-"olayangroup\0"
-"org.om\0"
-"org.pa\0\xd8\xa7\xd9\x85\xd8\xa7\xd8\xb1\xd8\xa7\xd8\xaa\0"
-"bio\0"
-"musashino.tokyo.jp\0"
-"org.pe\0cafe\0"
-"org.pf\0mytis.ru\0"
-"org.ph\0"
-"village.museum\0from-pr.com\0"
-"\xe6\x9c\xba\xe6\x9e\x84\0"
-"org.pk\0"
-"name.hr\0org.pl\0browsersafetymark.io\0"
-"biz\0"
-"ogose.saitama.jp\0org.pn\0kicks-ass.org\0blogspot.co.uk\0"
-"okagaki.fukuoka.jp\0"
-"nayoro.hokkaido.jp\0"
-"openair.museum\0org.qa\0"
-"org.pr\0istanbul\0"
-"org.ps\0"
-"org.pt\0"
-"bibai.hokkaido.jp\0"
-"org.py\0k12.nh.us\0"
-"tsuno.kochi.jp\0"
-"tokamachi.niigata.jp\0wales\0"
-"cng.br\0"
-"name.et\0"
-"b.bg\0"
-"karpacz.pl\0"
-"otsuka\0"
-"mini\0"
-"ar.it\0hikawa.shimane.jp\0\xe5\x95\x86\xe5\x9f\x8e\0"
-"homeftp.net\0"
-"video.hu\0gs.fm.no\0"
-"b.br\0"
-"org.ro\0"
-"rennes\xc3\xb8y.no\0"
-"org.sa\0"
-"org.sb\0"
-"org.rs\0org.sc\0mint\0"
-"sayama.osaka.jp\0nirasaki.yamanashi.jp\0org.sd\0"
-"org.se\0org.ru\0"
-"gjerstad.no\0"
-"kommune.no\0org.sg\0"
-"takashima.shiga.jp\0fhs.no\0org.sh\0from-mn.com\0"
-"bsb.br\0\xc3\xb8rskog.no\0"
-"jfk.museum\0"
-"org.sl\0"
-"iwatsuki.saitama.jp\0nanto.toyama.jp\0org.sn\0"
-"org.so\0"
-"kurashiki.okayama.jp\0\xc3\xa5""fjord.no\0\xd2\x9b\xd0\xb0\xd0\xb7\0"
-"civilaviation.aero\0clock.museum\0"
-"name.cy\0traniandriabarletta.it\0pruszkow.pl\0"
-"org.st\0fastvps-server.com\0"
-"lib.mn.us\0"
-"org.sv\0bms\0"
-"mashiki.kumamoto.jp\0"
-"asso.re\0org.sy\0"
-"sogndal.no\0org.sz\0org.tj\0bmw\0"
-"balestrand.no\0"
-"org.tm\0insurance\0"
-"org.tn\0\xd0\xb5\xd1\x8e\0"
-"otofuke.hokkaido.jp\0org.to\0bnl\0citic\0"
-"\xc3\xa5rdal.no\0"
-"name.eg\0org.ua\0"
-"cz.it\0toyohashi.aichi.jp\0skaun.no\0org.tr\0"
-"mihama.aichi.jp\0"
-"jewelry.museum\0org.tt\0"
-"cc.de.us\0"
-"org.tw\0org.ug\0"
-"lupin\0"
-"shoes\0"
-"org.uk\0here-for-more.info\0"
-"rg.it\0matta-varjjat.no\0"
-"\xe5\x95\x86\xe6\xa5\xad.tw\0wedeploy.sh\0"
-"bom\0"
-"boo\0"
-"org.vc\0"
-"name.az\0"
-"org.ve\0"
-"tateyama.chiba.jp\0"
-"bot\0"
-"chungnam.kr\0blogspot.co.ke\0nhlfan.net\0"
-"kanie.aichi.jp\0miura.kanagawa.jp\0org.uy\0org.vi\0"
-"ishinomaki.miyagi.jp\0org.uz\0"
-"box\0"
-"call\0"
-"national.museum\0stavern.no\0w.se\0"
-"org.vn\0lima-city.de\0"
-"aip.ee\0"
-"kani.gifu.jp\0"
-"wake.okayama.jp\0"
-"\xe5\xbe\xb3\xe5\xb3\xb6.jp\0"
-"org.vu\0cab\0"
-"soeda.fukuoka.jp\0"
-"terni.it\0"
-"fr.it\0homeunix.org\0"
-"\xd0\xbe\xd0\xb1\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0"
-"from-sd.com\0"
-"cal\0"
-"cam\0camp\0blackbaudcdn.net\0"
-"hidaka.kochi.jp\0"
-"ut.us\0org.ws\0"
-"cba\0"
-"car\0"
-"to.it\0servebeer.com\0"
-"cat\0fukusaki.hyogo.jp\0takanezawa.tochigi.jp\0asso.nc\0*.ex.ortsinfo.at\0"
-"klabu.no\0k12.ga.us\0"
-"lima-city.at\0"
-"higashiyama.kyoto.jp\0"
-"shikatsu.aichi.jp\0"
-"gorizia.it\0cbn\0*.hosting.myjino.ru\0"
-"gjerdrum.no\0"
-"ikano\0"
-"cbs\0"
-"wakayama.jp\0"
-"mobi.gp\0"
-"hasvik.no\0sosnowiec.pl\0apple\0"
-"kaita.hiroshima.jp\0org.za\0lima-city.ch\0"
-"eidsvoll.no\0"
-"siracusa.it\0"
+"fj.cn\0tome.miyagi.jp\0"
+"edu.zm\0nym.pe\0"
+"v-info.info\0"
+"tomakomai.hokkaido.jp\0hosting-cluster.nl\0"
+"click\0"
"miharu.fukushima.jp\0"
-"palmsprings.museum\0teaches-yoga.com\0"
-"ibestad.no\0"
-"kagami.kochi.jp\0"
-"avocat.pro\0"
-"org.zm\0blogspot.co.nz\0"
-"foundation.museum\0style\0dattorelay.com\0"
-"air-surveillance.aero\0for-more.biz\0"
-"toray\0"
-"zaporizhzhia.ua\0"
-"sande.more-og-romsdal.no\0\xe7\xbd\x91\xe7\xab\x99\0"
-"lib.gu.us\0ceb\0"
-"org.zw\0"
-"jeju.kr\0"
-"haebaru.okinawa.jp\0"
-"police.uk\0"
-"nomi.ishikawa.jp\0is-a-green.com\0"
-"divttasvuotna.no\0ceo\0"
-"tree.museum\0zt.ua\0"
-"yugawara.kanagawa.jp\0v\xc3\xa5gan.no\0cfa\0engineering\0""001www.com\0"
-"choshi.chiba.jp\0care\0"
-"cfd\0"
-"usa.oita.jp\0lowicz.pl\0gifts\0"
-"uscountryestate.museum\0is.eu.org\0"
-"buy\0"
-"kr.it\0missoula.museum\0sohu\0"
-"iide.yamagata.jp\0"
-"from-sc.com\0"
-"casa\0"
-"cars\0"
-"per.la\0case\0"
-"soma.fukushima.jp\0"
-"romskog.no\0"
-"izumisano.osaka.jp\0cash\0"
-"booking\0"
-"k12.la.us\0"
-"\xe4\xbd\x90\xe8\xb3\x80.jp\0"
-"ibigawa.gifu.jp\0"
-"asso.km\0"
-"muni.il\0karatsu.saga.jp\0science-fiction.museum\0xbox\0"
+"r\xc3\xb8st.no\0s3.eu-central-1.amazonaws.com\0"
+"midori.chiba.jp\0"
+"moriyama.shiga.jp\0"
+"natuurwetenschappen.museum\0"
+"nym.pt\0"
+"pro.na\0moto\0"
+"aero.tt\0map.fastly.net\0"
+"hidaka.kochi.jp\0"
+"crew.aero\0"
+"pro.mv\0"
+"histoire.museum\0krokstadelva.no\0giving\0"
+"microsoft\0"
"ar.us\0"
-"valle\xcc\x81""e-d-aoste.it\0"
-"kozagawa.wakayama.jp\0it.eu.org\0myvnc.com\0"
-"cog.mi.us\0"
-"folldal.no\0"
-"\xd1\x80\xd1\x84\0"
-"honjo.saitama.jp\0asso.mc\0"
-"cultural.museum\0per.nf\0cc.ne.us\0"
-"tvedestrand.no\0wedeploy.me\0"
-"he.cn\0spydeberg.no\0"
-"kommunalforbund.se\0"
-"rifu.miyagi.jp\0"
-"inuyama.aichi.jp\0nishio.aichi.jp\0akagi.shimane.jp\0k12.ny.us\0"
-"mormon\0"
-"gs.svalbard.no\0"
-"jevnaker.no\0lib.me.us\0office\0myshopblocks.com\0"
-"shibecha.hokkaido.jp\0"
-"tj\xc3\xb8me.no\0bzh\0"
-"u.bg\0\xe9\xa3\x9f\xe5\x93\x81\0"
-"takatori.nara.jp\0"
-"czest.pl\0"
-"modelling.aero\0"
-"hammarfeasta.no\0"
-"ce.it\0gausdal.no\0"
-"\xd7\x99\xd7\xa8\xd7\x95\xd7\xa9\xd7\x9c\xd7\x99\xd7\x9d.museum\0square7.net\0edu.krd\0"
-"shinjo.nara.jp\0is-very-bad.org\0"
-"potenza.it\0"
-"jelenia-gora.pl\0localhost.daplie.me\0"
-"9guacu.br\0"
-"audio\0"
-"naples.it\0pr.it\0furano.hokkaido.jp\0kamikawa.hokkaido.jp\0song\0"
-"ask\xc3\xb8y.no\0"
-"orange\0telecity\0serveblog.net\0"
-"orland.no\0"
-"ikata.ehime.jp\0"
-"name.vn\0mozilla-iot.org\0"
-"fund\0"
-"in.eu.org\0"
-"matsushima.miyagi.jp\0c66.me\0dattoweb.com\0"
-"realm.cz\0"
-"\xe5\xba\x83\xe5\xb3\xb6.jp\0"
-"b.se\0"
-"myactivedirectory.com\0"
-"sony\0"
-"ookuwa.nagano.jp\0"
-"berlin\0"
-"xj.cn\0barletta-trani-andria.it\0is-a-painter.com\0"
-"annaka.gunma.jp\0tsukui.kanagawa.jp\0"
-"towada.aomori.jp\0"
-"deporte.bo\0fukuyama.hiroshima.jp\0gent\0does-it.net\0"
-"bieszczady.pl\0"
-"b\xc3\xa1hccavuotna.no\0"
-"kikuchi.kumamoto.jp\0surrey.museum\0piaget\0"
-"tos.it\0"
-"barsy.club\0"
-"name.tj\0"
-"republican\0"
-"aquarelle\0dunlop\0"
-"nakagawa.nagano.jp\0"
-"environment.museum\0"
-"per.sg\0"
-"name.tr\0"
-"verm\xc3\xb6gensberatung\0customer.enonic.io\0"
-"samukawa.kanagawa.jp\0name.tt\0ericsson\0"
-"compare\0"
-"katagami.akita.jp\0"
-"elburg.museum\0blogspot.co.za\0"
-"mashiko.tochigi.jp\0imizu.toyama.jp\0"
-"seika.kyoto.jp\0gildesk\xc3\xa5l.no\0"
-"station.museum\0"
-"elvendrell.museum\0"
-"kitashiobara.fukushima.jp\0"
-"nic.in\0iglesiascarbonia.it\0"
-"sunagawa.hokkaido.jp\0bu.no\0"
-"com\0\xe9\x9d\x92\xe6\xa3\xae.jp\0"
-"ollo\0"
-"kashiwa.chiba.jp\0otobe.hokkaido.jp\0"
-"shibuya.tokyo.jp\0halsa.no\0\xd0\xbc\xd0\xbe\xd1\x81\xd0\xba\xd0\xb2\xd0\xb0\0*.cns.joyent.com\0"
-"catering.aero\0dyn-ip24.de\0"
-"s3.dualstack.ap-south-1.amazonaws.com\0"
-"\xe7\xbd\x91\xe7\xb5\xa1.hk\0okoppe.hokkaido.jp\0"
-"chosei.chiba.jp\0"
-"agdenes.no\0\xe5\x85\xab\xe5\x8d\xa6\0"
-"vana\0"
-"riobranco.br\0"
-"cam.it\0canon\0"
-"airtel\0"
-"vb.it\0"
-"higashinaruse.akita.jp\0"
-"pizza\0"
-"fjell.no\0dad\0myjino.ru\0"
-"career\0"
-"\xe5\x8f\xb0\xe6\xb9\xbe\0"
-"kitaakita.akita.jp\0kr.ua\0*.quipelements.com\0"
-"nanmoku.gunma.jp\0musashimurayama.tokyo.jp\0"
-"joetsu.niigata.jp\0"
-"s3.dualstack.ap-southeast-1.amazonaws.com\0"
-"k12.va.us\0"
-"macapa.br\0ehime.jp\0"
+"sc.cn\0higashiosaka.osaka.jp\0"
+"pars\0"
+"philadelphia.museum\0lima-city.de\0"
+"lib.nv.us\0"
+"nakagawa.fukuoka.jp\0"
+"\xe4\xb8\xaa\xe4\xba\xba.hk\0nordkapp.no\0"
+"aero.mv\0"
+"baltimore.museum\0"
+"arts.nf\0"
+"shiksha\0"
+"nym.ro\0"
+"pro.om\0"
+"eu-2.evennode.com\0"
+"google\0"
+"nisshin.aichi.jp\0oyamazaki.kyoto.jp\0higashimatsuyama.saitama.jp\0"
+"vallee-d-aoste.it\0serveblog.net\0"
+"agro.pl\0agrinet.tn\0"
+"\xe3\x82\xb0\xe3\x83\xbc\xe3\x82\xb0\xe3\x83\xab\0verm\xc3\xb6gensberatung\0loginto.me\0nym.sk\0"
+"kiyokawa.kanagawa.jp\0kagamino.okayama.jp\0"
+"zt.ua\0"
+"barletta-trani-andria.it\0lima-city.at\0"
+"aeroport.fr\0"
+"kikonai.hokkaido.jp\0shell\0boomla.net\0"
+"nym.su\0"
+"pro.pr\0"
"yokohama\0"
-"radoy.no\0"
-"kiyama.saga.jp\0j\xc3\xb8lster.no\0"
-"estate.museum\0serveminecraft.net\0"
-"reg.dk\0"
-"name.qa\0"
-"name.pr\0day\0"
-"yoshino.nara.jp\0"
-"fedorapeople.org\0"
-"gunma.jp\0vestv\xc3\xa5g\xc3\xb8y.no\0"
-"lombardy.it\0gamo.shiga.jp\0my-gateway.de\0"
-"mango\0"
-"reisen\0is-an-accountant.com\0"
-"crs\0csc\0"
-"name.na\0fedorainfracloud.org\0"
-"nagara.chiba.jp\0utashinai.hokkaido.jp\0creditcard\0"
-"joyo.kyoto.jp\0katowice.pl\0"
-"s3.amazonaws.com\0"
-"name.mv\0"
-"mihama.fukui.jp\0name.ng\0support\0"
-"!city.kitakyushu.jp\0name.my\0company\0"
-"8.bg\0"
-"vix.br\0computerhistory.museum\0"
-"fujimi.nagano.jp\0"
-"contractors\0"
-"nakai.kanagawa.jp\0\xd9\x85\xd9\x84\xd9\x8a\xd8\xb3\xd9\x8a\xd8\xa7\0"
-"miyako.iwate.jp\0"
-"okawa.fukuoka.jp\0gujo.gifu.jp\0"
-"kids.us\0"
-"campidano-medio.it\0mishima.fukushima.jp\0"
-"nj.us\0"
-"karuizawa.nagano.jp\0dds\0groks-the.info\0"
-"lu.it\0me.it\0"
-"dyndns-ip.com\0"
-"campinagrande.br\0education.museum\0"
-"trentin-su\xcc\x88""dtirol.it\0sekigahara.gifu.jp\0moss.no\0"
-"makeup\0"
-"bible.museum\0"
-"parachuting.aero\0chikugo.fukuoka.jp\0chernivtsi.ua\0"
-"us-west-2.elasticbeanstalk.com\0"
-"ballooning.aero\0"
-"galsa.no\0gok.pk\0cbre\0wedeploy.io\0"
-"bjark\xc3\xb8y.no\0\xe3\x82\xbb\xe3\x83\xbc\xe3\x83\xab\0from-tx.com\0"
-"sumoto.kumamoto.jp\0"
-"me.ke\0dev\0"
-"grosseto.it\0"
-"sevastopol.ua\0"
-"yakage.okayama.jp\0"
-"abiko.chiba.jp\0name.mk\0"
+"jobs.tt\0nym.sx\0"
+"club.aero\0journalism.museum\0symantec\0"
+"takamori.nagano.jp\0"
+"kamigori.hyogo.jp\0"
+"github.io\0"
+"reviews\0"
+"ariake.saga.jp\0lima-city.ch\0"
+"trentinos\xc3\xbc""dtirol.it\0"
+"mysecuritycamera.org\0nym.tw\0"
+"inzai.chiba.jp\0verisign\0"
+"nakagyo.kyoto.jp\0"
+"surf\0"
+"k12.tn.us\0"
+"apps.lair.io\0"
+"risor.no\0"
+"finn\xc3\xb8y.no\0"
+"kafjord.no\0"
+"ujitawara.kyoto.jp\0""64-b.it\0"
+"eu-1.evennode.com\0"
+"hamburg\0dvrcam.info\0"
+"minamiaiki.nagano.jp\0"
+"mt.eu.org\0"
+"abogado\0"
+"shimokawa.hokkaido.jp\0"
+"ninomiya.kanagawa.jp\0hatogaya.saitama.jp\0"
+"batsfjord.no\0"
+"kamikoani.akita.jp\0"
+"\xd9\x85\xd9\x84\xd9\x8a\xd8\xb3\xd9\x8a\xd8\xa7\0lenug.su\0"
+"samnanger.no\0"
+"gs.ol.no\0glade\0"
+"pro.tt\0\xd9\xbe\xd8\xa7\xd9\x83\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\0"
+"hn.cn\0"
+"mihama.chiba.jp\0"
+"stavern.no\0"
+"bs.it\0kuji.iwate.jp\0kisosaki.mie.jp\0"
+"tydal.no\0\xe5\x85\xac\xe5\x8f\xb8.\xe9\xa6\x99\xe6\xb8\xaf\0"
+"cv.ua\0"
+"sakado.saitama.jp\0hospital\0"
+"sc.ke\0"
+"rec.nf\0"
+"takatsuki.shiga.jp\0"
+"\xe7\xb5\x84\xe7\xb9\x94.\xe9\xa6\x99\xe6\xb8\xaf\0teva\0square7.de\0"
+"yuasa.wakayama.jp\0"
+"choshi.chiba.jp\0"
+"shiroishi.miyagi.jp\0tottori.tottori.jp\0sc.kr\0pro.vn\0thruhere.net\0"
+"balashov.su\0cust.disrec.thingdust.io\0"
+"tw.cn\0yawara.ibaraki.jp\0"
+"lib.pr.us\0"
+"kitamoto.saitama.jp\0"
+"hurdal.no\0sling\0"
+"chonan.chiba.jp\0endofinternet.net\0"
+"githubusercontent.com\0"
+"sc.ls\0sogndal.no\0"
+"judaica.museum\0"
+"heguri.nara.jp\0"
+"cc.sc.us\0"
+"wajima.ishikawa.jp\0"
+"sec.ps\0"
+"masaki.ehime.jp\0augustow.pl\0"
+"imdb\0"
+"\xd1\x83\xd0\xbf\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0hdfcbank\0"
+"landrover\0"
+"costume.museum\0"
+"*.compute.amazonaws.com.cn\0"
+"history.museum\0alsace\0"
+"karatsu.saga.jp\0"
+"fukushima.fukushima.jp\0nabari.mie.jp\0"
+"skype\0"
+"cc.na\0"
+"le.it\0rifu.miyagi.jp\0square7.ch\0"
+"fla.no\0watches\0backplaneapp.io\0definima.io\0"
+"mikasa.hokkaido.jp\0"
+"nyc.museum\0"
+"seranishi.hiroshima.jp\0nakatane.kagoshima.jp\0"
+"aya.miyazaki.jp\0custom.metacentrum.cz\0"
+"its.me\0harvestcelebration.museum\0abo.pa\0o.se\0"
+"limanowa.pl\0"
+"corvette.museum\0"
+"artsandcrafts.museum\0watchandclock.museum\0pors\xc3\xa1\xc5\x8bgu.no\0vard\xc3\xb8.no\0"
+"naruto.tokushima.jp\0"
+"devices.resinstaging.io\0"
+"rec.ro\0accenture\0"
+"boston.museum\0sciences.museum\0"
+"takayama.gifu.jp\0abashiri.hokkaido.jp\0"
+"dyndns-wiki.com\0"
+"solutions\0"
+"minamata.kumamoto.jp\0"
+"s\xc3\xb8r-aurdal.no\0"
+"ibaraki.ibaraki.jp\0"
+"fantasyleague.cc\0"
+"vet.br\0\xe5\xb2\xa9\xe6\x89\x8b.jp\0inabe.mie.jp\0"
+"pila.pl\0"
+"balestrand.no\0hornindal.no\0"
+"virgin\0"
+"hepforge.org\0"
+"ukiha.fukuoka.jp\0"
+"ol.no\0"
+"ufcfan.org\0"
+"ino.kochi.jp\0"
+"farmstead.museum\0"
+"community.museum\0land-4-sale.us\0"
+"kaneyama.yamagata.jp\0"
+"topology.museum\0\xc3\xa1laheadju.no\0aurskog-h\xc3\xb8land.no\0"
+"tec.ve\0"
+"kumakogen.ehime.jp\0ujiie.tochigi.jp\0"
+"idrett.no\0"
+"esp.br\0"
+"is-a-guru.com\0"
+"ikawa.akita.jp\0kamitsue.oita.jp\0"
+"\xe7\xb6\xb2\xe7\xb5\xa1.\xe9\xa6\x99\xe6\xb8\xaf\0"
+"alt.za\0xnbay.com\0"
+"ragusa.it\0"
+"scienceandindustry.museum\0holmestrand.no\0lib.wi.us\0"
+"minokamo.gifu.jp\0chikusei.ibaraki.jp\0definima.net\0"
+"uz.ua\0"
+"cal.it\0"
+"trento.it\0twmail.net\0"
+"aero\0halsa.no\0"
+"\xe5\xae\xae\xe5\xb4\x8e.jp\0"
+"rec.ve\0nohost.me\0"
+"mifune.kumamoto.jp\0"
+"skj\xc3\xa5k.no\0my.eu.org\0"
+"kuzumaki.iwate.jp\0"
+"net.ac\0academia.bo\0s3-ca-central-1.amazonaws.com\0"
+"dnsking.ch\0"
+"net.ae\0"
+"net.af\0umb.it\0"
+"net.ag\0alaheadju.no\0hobol.no\0aaa\0"
+"ojiya.niigata.jp\0yamanakako.yamanashi.jp\0"
+"net.ai\0communication.museum\0grong.no\0"
+"net.al\0imb.br\0cartier\0"
+"juif.museum\0bardu.no\0surnadal.no\0accesscam.org\0"
+"read\0"
+"net.ba\0kaluga.su\0"
+"net.ar\0net.bb\0aquila.it\0kuriyama.hokkaido.jp\0"
+"inazawa.aichi.jp\0chat\0"
+"net.au\0"
+"hemne.no\0"
+"net.bh\0abb\0"
+"windmill.museum\0spydeberg.no\0abc\0ditchyourip.com\0"
+"net.az\0citadel\0"
+"pccw\0"
+"okagaki.fukuoka.jp\0ginowan.okinawa.jp\0"
+"net.bm\0"
+"net.bn\0takazaki.miyazaki.jp\0"
+"net.bo\0askim.no\0l\xc3\xb8renskog.no\0sc.ug\0"
"ap.it\0"
-"tm.cy\0center.museum\0belau.pw\0"
-"cc.ak.us\0"
+"deals\0"
+"net.br\0sc.tz\0"
+"net.bs\0k12.al.us\0cc.ua\0"
+"net.bt\0tainai.niigata.jp\0kakinoki.shimane.jp\0pcloud.host\0"
+"stuff-4-sale.us\0"
"gobo.wakayama.jp\0"
-"ma.gov.br\0"
-"pr.us\0"
-"oshima.tokyo.jp\0no.com\0"
-"\xe5\x9c\xa8\xe7\xba\xbf\0"
-"taxi.br\0"
-"columbus.museum\0"
-"hamura.tokyo.jp\0utsira.no\0"
-"minami.fukuoka.jp\0swinoujscie.pl\0cc.oh.us\0"
-"bjugn.no\0"
-"is-a-libertarian.com\0"
-"name.jo\0s3-website-eu-west-1.amazonaws.com\0dattolocal.net\0sopot.pl\0"
-"noboribetsu.hokkaido.jp\0we.bs\0"
-"enebakk.no\0"
-"soka.saitama.jp\0mobi.tt\0dhl\0\xeb\x8b\xb7\xec\xbb\xb4\0"
-"krager\xc3\xb8.no\0"
-"mobi.tz\0"
-"minamiboso.chiba.jp\0"
-"taa.it\0omihachiman.shiga.jp\0"
-"flowers\0"
-"\xe5\xae\xae\xe5\xb4\x8e.jp\0nakijin.okinawa.jp\0"
-"kamo.kyoto.jp\0"
-"londrina.br\0"
-"tm.fr\0\xe9\xb9\xbf\xe5\x85\x90\xe5\xb3\xb6.jp\0\xe5\xa8\xb1\xe4\xb9\x90\0"
-"kosuge.yamanashi.jp\0eng.pro\0naturbruksgymn.se\0cc.dc.us\0"
-"oceanographique.museum\0"
-"myhome-server.de\0"
-"re.it\0nic.tj\0"
-"toki.gifu.jp\0hapmir.no\0diy\0"
-"akabira.hokkaido.jp\0\xe5\x85\xac\xe5\x8f\xb8\0\xe6\x97\xb6\xe5\xb0\x9a\0"
-"uk.com\0"
-"\xe3\x81\xbf\xe3\x82\x93\xe3\x81\xaa\0is-a-blogger.com\0"
-"yamagata.gifu.jp\0tosa.kochi.jp\0fusa.no\0"
-"psse.gov.pl\0"
-"valleaosta.it\0ma.leg.br\0"
-"stord.no\0"
-"settlers.museum\0"
-"gaivuotna.no\0"
-"u.se\0s3-eu-west-2.amazonaws.com\0"
-"nhs.uk\0"
-"cesenaforli\xcc\x80.it\0"
-"wolterskluwer\0"
-"events\0"
-"church\0"
-"tm.hu\0ushiku.ibaraki.jp\0glas.museum\0"
-"kafjord.no\0gu.us\0"
-"aejrie.no\0computer\0"
-"iselect\0"
-"como.it\0re.kr\0komvux.se\0"
-"utazas.hu\0"
-"kurobe.toyama.jp\0"
-"engineer.aero\0"
-"duck\0travelchannel\0"
-"from-ia.com\0"
-"*.s5y.io\0"
-"franziskaner.museum\0"
-"omasvuotna.no\0"
-"baseball\0"
-"tawaramoto.nara.jp\0"
-"lecce.it\0"
-"pub.sa\0"
-"mobi.na\0spot\0"
-"midtre-gauldal.no\0"
-"toyono.osaka.jp\0"
-"k12.tn.us\0catering\0"
-"asakawa.fukushima.jp\0pharmaciens.km\0nyc.museum\0mobi.ng\0"
-"freeboxos.fr\0"
-"realty\0"
-"yakumo.shimane.jp\0"
-"oshu.iwate.jp\0"
-"usa.museum\0"
-"trolley.museum\0skanland.no\0"
+"takikawa.hokkaido.jp\0"
+"net.ci\0"
+"net.bz\0my.id\0"
+"sc.us\0"
+"net.cm\0energy\0"
+"net.cn\0konan.aichi.jp\0biratori.hokkaido.jp\0"
+"net.co\0coupons\0"
+"ownip.net\0gotdns.ch\0"
+"gonohe.aomori.jp\0inawashiro.fukushima.jp\0jp.net\0"
+"net.cu\0coloradoplateau.museum\0giessen.museum\0aco\0"
+"act.edu.au\0net.cw\0"
+"shimodate.ibaraki.jp\0"
+"net.cy\0"
+"hjelmeland.no\0"
+"net.dm\0"
+"net.do\0"
+"joinville.br\0"
+"unj\xc3\xa1rga.no\0immo\0\xe5\xa4\xa7\xe6\x8b\xbf\0dyndns-web.com\0"
+"net.ec\0rennesoy.no\0"
+"komvux.se\0"
+"net.eg\0memorial.museum\0"
+"ads\0science\0"
+"net.dz\0minato.tokyo.jp\0"
+"aeg\0"
+"quest\0"
+"cymru.museum\0"
+"trentin-s\xc3\xbc""d-tirol.it\0"
+"muenchen.museum\0"
+"net.et\0"
+"h\xc3\xa1""bmer.no\0"
+"yonabaru.okinawa.jp\0"
+"loyalist.museum\0"
+"galsa.no\0s3-website-sa-east-1.amazonaws.com\0"
+"from-nv.com\0"
+"trentino-s\xc3\xbc""dtirol.it\0"
+"nl.eu.org\0"
+"england.museum\0"
+"afl\0"
+"comunica\xc3\xa7\xc3\xb5""es.museum\0"
+"theater\0"
+"net.ge\0"
+"yamaga.kumamoto.jp\0"
+"urn.arpa\0net.gg\0"
+"bozen-suedtirol.it\0honjyo.akita.jp\0"
+"vik.no\0"
+"net.gl\0"
+"rindal.no\0glass\0"
+"net.gn\0"
+"tvedestrand.no\0internet-dns.de\0"
+"net.gp\0kozaki.chiba.jp\0rzgw.gov.pl\0ravendb.run\0"
+"dontexist.org\0"
+"net.gr\0nishimera.miyazaki.jp\0"
+"net.gt\0"
+"net.gu\0"
+"alabama.museum\0"
+"net.gy\0asso.eu.org\0freeddns.us\0"
+"net.hk\0gs.st.no\0fairwinds\0africa.com\0"
+"morena.br\0"
+"net.hn\0minamimaki.nagano.jp\0"
+"tagami.niigata.jp\0nakagawa.tokushima.jp\0"
+"name\0my-router.de\0"
+"net.ht\0net.id\0"
+"m.bg\0"
+"eu-west-1.elasticbeanstalk.com\0"
+"net.il\0"
+"net.im\0stathelle.no\0aig\0"
+"net.in\0modena.it\0"
+"from-wv.com\0"
+"net.iq\0\xc3\xa5lg\xc3\xa5rd.no\0hoteles\0"
+"net.ir\0williamhill\0"
+"net.is\0newspaper.museum\0"
+"niteroi.br\0"
+"net.je\0jewelry\0"
+"chuo.osaka.jp\0"
+"ap-southeast-1.elasticbeanstalk.com\0us-west-1.elasticbeanstalk.com\0"
+"hirono.fukushima.jp\0"
+"uri.arpa\0guernsey.museum\0lancashire.museum\0sn\xc3\xa5""ase.no\0"
+"soma.fukushima.jp\0onomichi.hiroshima.jp\0urausu.hokkaido.jp\0"
+"barreau.bj\0"
+"fujioka.gunma.jp\0komatsushima.tokushima.jp\0reit\0"
+"net.jo\0police.uk\0"
+"niiza.saitama.jp\0"
+"isa-geek.org\0"
+"la-spezia.it\0"
+"sm\xc3\xb8la.no\0barsy.info\0"
+"travelers\0"
+"ct.it\0kitagata.gifu.jp\0crown\0"
+"net.kg\0valle.no\0"
+"samegawa.fukushima.jp\0"
+"net.ki\0is-an-accountant.com\0"
+"nowtv\0"
+"in-addr.arpa\0"
+"6.bg\0"
+"oamishirasato.chiba.jp\0tarama.okinawa.jp\0net.kn\0"
+"net.la\0"
+"lucca.it\0net.lb\0"
+"net.lc\0"
+"net.kw\0"
+"midori.gunma.jp\0sayama.saitama.jp\0mincom.tn\0"
+"net.ky\0encyclopedic.museum\0*.0emm.com\0"
+"net.kz\0"
+"net.lk\0"
+"dgca.aero\0"
+"shirataka.yamagata.jp\0kinder\0"
+"ng.eu.org\0"
+"net.ma\0air.museum\0"
+"ogawa.nagano.jp\0net.lr\0"
+"net.ls\0is-a-socialist.com\0co.network\0"
+"net.me\0courses\0"
+"ichinomiya.chiba.jp\0kishiwada.osaka.jp\0net.lv\0"
+"sa.au\0fortmissoula.museum\0"
+"emb.kw\0net.ly\0"
+"net.mk\0lib.as.us\0luxury\0"
+"osaki.miyagi.jp\0net.ml\0"
+"hamura.tokyo.jp\0capital\0"
+"net.mo\0"
+"info\0"
+"oishida.yamagata.jp\0"
+"net.ms\0eigersund.no\0"
+"biella.it\0net.mt\0"
+"net.mu\0"
+"net.mv\0net.nf\0"
+"virtual.museum\0net.mw\0net.ng\0"
+"net.mx\0"
+"net.my\0net.ni\0cc.ct.us\0"
+"net.mz\0"
+"torino.museum\0"
+"uruma.okinawa.jp\0stalowa-wola.pl\0azure-mobile.net\0"
+"aarborte.no\0dnsfor.me\0"
+"odesa.ua\0"
+"nanbu.yamanashi.jp\0net.nr\0"
+"sa.cr\0"
+"lib.oh.us\0"
+"st.no\0"
+"taiji.wakayama.jp\0"
+"net.nz\0"
+"couchpotatofries.org\0"
+"search\0"
+"net.om\0"
+"pinb.gov.pl\0rent\0"
+"game-server.cc\0"
+"anz\0"
+"net.pa\0"
+"aol\0"
+"friuli-veneziagiulia.it\0oiso.kanagawa.jp\0muika.niigata.jp\0"
+"artgallery.museum\0handson.museum\0net.pe\0on-aptible.com\0"
+"enna.it\0"
+"honefoss.no\0press\0"
+"net.ph\0etisalat\0"
+"s\xc3\xb8rum.no\0net.pk\0"
+"net.pl\0"
+"wios.gov.pl\0net.pn\0"
+"servepics.com\0"
+"marugame.kagawa.jp\0"
+"net.qa\0"
+"joso.ibaraki.jp\0tsubame.niigata.jp\0net.pr\0"
+"net.ps\0myfirewall.org\0"
+"bergamo.it\0rishirifuji.hokkaido.jp\0ina.nagano.jp\0kokubunji.tokyo.jp\0net.pt\0"
+"sweetpepper.org\0"
+"app\0"
+"benevento.it\0"
+"net.py\0"
+"akita.akita.jp\0"
+"s3-website-ap-northeast-1.amazonaws.com\0"
+"forgot.her.name\0"
"shinshiro.aichi.jp\0"
-"tm.km\0"
-"vistaprint\0"
+"scotland.museum\0"
+"\xe5\x85\xb5\xe5\xba\xab.jp\0"
+"sassari.it\0okuma.fukushima.jp\0"
+"mypi.co\0"
+"numazu.shizuoka.jp\0\xe7\xbb\x84\xe7\xbb\x87\xe6\x9c\xba\xe6\x9e\x84\0"
+"ris\xc3\xb8r.no\0"
+"fuefuki.yamanashi.jp\0bar\0"
+"bbc\0"
+"toscana.it\0atsugi.kanagawa.jp\0settsu.osaka.jp\0kusatsu.shiga.jp\0yamada.toyama.jp\0"
+"\xe0\xb8\xa3\xe0\xb8\xb1\xe0\xb8\x90\xe0\xb8\x9a\xe0\xb8\xb2\xe0\xb8\xa5.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0"
+"omitama.ibaraki.jp\0"
+"net.sa\0kindle\0"
+"net.sb\0"
+"net.sc\0"
+"net.sd\0dunlop\0"
+"net.ru\0myftp.org\0"
+"sekikawa.niigata.jp\0"
+"hemsedal.no\0net.rw\0net.sg\0navy\0"
+"niimi.okayama.jp\0net.sh\0"
+"kamifurano.hokkaido.jp\0art\0bbt\0"
+"kumejima.okinawa.jp\0net.sl\0"
+"broker.aero\0bcg\0"
+"fet.no\0net.so\0nsupdate.info\0"
+"dagestan.ru\0"
+"property\0"
+"iki.nagasaki.jp\0net.st\0bcn\0"
+"prof.pr\0net.th\0walter\0"
+"net.sy\0"
+"net.tj\0"
+"sor-varanger.no\0net.tm\0"
+"net.tn\0rest\0"
+"net.to\0"
+"unjarga.no\0net.ua\0dagestan.su\0"
+"net.tr\0"
+"cargo.aero\0"
+"aizubange.fukushima.jp\0kamo.niigata.jp\0net.tt\0"
+"society.museum\0ebiz.tw\0"
+"sa.it\0"
+"net.tw\0localhost.daplie.me\0"
+"net.uk\0cards\0organic\0"
+"hl.cn\0\xd0\xba\xd0\xbe\xd0\xbc\0""32-b.it\0"
+"diamonds\0"
+"naganohara.gunma.jp\0"
+"vennesla.no\0blogdns.org\0"
+"ca.it\0"
+"lib.co.us\0"
+"kyotango.kyoto.jp\0"
+"safety.aero\0net.vc\0\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4\xe0\xa4\xae\xe0\xa5\x8d\0cyon.link\0"
+"sandvikcoromant\0"
+"net.ve\0"
+"koge.tottori.jp\0guardian\0"
+"hof.no\0net.uy\0net.vi\0"
+"net.uz\0bet\0"
+"sakae.chiba.jp\0"
+"net.vn\0"
+"ekloges.cy\0bryne.no\0kpmg\0"
+"dyndns-home.com\0"
+"\xe5\xa4\xa7\xe5\x88\x86.jp\0higashimatsushima.miyagi.jp\0"
+"gmbh\0\xe7\xa7\xbb\xe5\x8a\xa8\0"
+"ct.us\0net.vu\0"
+"wsa.gov.pl\0"
+"gemological.museum\0"
+"pistoia.it\0travel.pl\0"
+"realtor\0"
+"vindafjord.no\0k12.mn.us\0viajes\0"
"tysnes.no\0"
-"pp.az\0pors\xc3\xa1\xc5\x8bgu.no\0"
-"even\xc3\xa1\xc5\xa1\xc5\xa1i.no\0dnp\0tickets\0"
-"datsun\0home-webserver.de\0"
-"valer.ostfold.no\0blogsite.xyz\0"
-"murmansk.su\0brasilia.me\0"
-"dog\0schule\0"
-"vic.au\0"
-"space.museum\0"
-"takata.fukuoka.jp\0zero\0"
-"sel.no\0"
-"shimokitayama.nara.jp\0tm.mc\0brandywinevalley.museum\0"
-"nuremberg.museum\0homegoods\0kiwi\0ap-northeast-2.elasticbeanstalk.com\0"
-"tm.mg\0"
-"bergamo.it\0dot\0"
-"from-tn.com\0"
-"yatomi.aichi.jp\0narita.chiba.jp\0drobak.no\0"
-"transport.museum\0"
-"carrara-massa.it\0"
-"me.tz\0wanggou\0"
-"me.uk\0"
-"gs.jan-mayen.no\0"
-"ichinomiya.chiba.jp\0"
-"uenohara.yamanashi.jp\0"
-"me.us\0"
-"ushuaia.museum\0"
-"bizen.okayama.jp\0"
-"koori.fukushima.jp\0"
-"ac\0aarp\0"
-"ad\0tm.no\0"
-"ae\0orskog.no\0"
+"net.ws\0"
+"axa\0place\0visa\0isa-geek.com\0"
+"civilisation.museum\0aws\0u2-local.xnbay.com\0"
+"ppg.br\0"
+"\xe5\x95\x86\xe5\xba\x97\0"
+"kami.kochi.jp\0sado.niigata.jp\0"
+"cc.ca.us\0kerrylogistics\0"
+"puglia.it\0"
+"siljan.no\0"
+"toyohashi.aichi.jp\0"
+"xfinity\0"
+"lomza.pl\0bid\0"
+"evenes.no\0"
+"monmouth.museum\0ca.na\0"
+"lc.it\0"
+"lib.nm.us\0"
+"cloudaccess.net\0"
+"gs.hl.no\0lv.ua\0net.za\0""1337.pictures\0"
+"iwafune.tochigi.jp\0tokushima.tokushima.jp\0"
+"bio\0inc.hk\0"
+"m.se\0online\0"
+"seven\0"
+"sukumo.kochi.jp\0"
+"net.zm\0"
+"rochester.museum\0dynserv.org\0"
+"biz\0watari.miyagi.jp\0"
+"tokyo\0"
+"yasuoka.nagano.jp\0"
+"koshigaya.saitama.jp\0tjmaxx\0"
+"democracia.bo\0"
+"tur.ar\0"
+"stavanger.no\0theatre\0viva\0myds.me\0"
+"bilbao.museum\0webcam\0"
+"tienda\0"
+"hashimoto.wakayama.jp\0"
+"cosenza.it\0"
+"louvre.museum\0askoy.no\0boxfuse.io\0"
+"travel.tt\0"
+"\xd0\xb1\xd0\xb3\0is-a-celticsfan.org\0"
+"vivo\0cleverapps.io\0"
+"riopreto.br\0tur.br\0"
+"walmart\0"
+"manchester.museum\0"
+"asahi.nagano.jp\0"
+"valer.hedmark.no\0fh.se\0"
+"wiki.bo\0cc.ks.us\0\xe8\xb4\xad\xe7\x89\xa9\0"
+"homeip.net\0"
+"wiki.br\0imakane.hokkaido.jp\0"
+"snoasa.no\0"
+"kumagaya.saitama.jp\0"
+"tromsa.no\0"
+"hob\xc3\xb8l.no\0"
+"ecn.br\0koza.wakayama.jp\0"
+"krym.ua\0"
+"filegear-de.me\0"
+"toyama.toyama.jp\0"
+"rygge.no\0istmein.de\0"
+"jewish.museum\0usgarden.museum\0raisa.no\0endofinternet.org\0"
+"bms\0"
+"ryokami.saitama.jp\0"
+"\xe0\xb8\x84\xe0\xb8\xad\xe0\xb8\xa1\0"
+"haugesund.no\0bmw\0"
+"homeunix.net\0"
+"asn.au\0"
+"messina.it\0bnl\0"
+"lazio.it\0"
+"*.in.futurecms.at\0"
+"val-d-aosta.it\0pa.leg.br\0"
+"\xe9\xa3\x9e\xe5\x88\xa9\xe6\xb5\xa6\0"
+"gorlice.pl\0"
+"assn.lk\0bom\0"
+"kanna.gunma.jp\0"
+"timekeeping.museum\0boo\0"
+"ardal.no\0"
+"monza.it\0fukuoka.jp\0"
+"tksat.bo\0"
+"an.it\0bot\0"
+"sandnessjoen.no\0"
+"calvinklein\0report\0"
+"hl.no\0\xe9\x9b\xbb\xe8\xa8\x8a\xe7\x9b\x88\xe7\xa7\x91\0"
+"genova.it\0box\0"
+"epilepsy.museum\0geology.museum\0casino\0"
+"pordenone.it\0"
+"ostroda.pl\0"
+"tana.no\0"
+"tochigi.tochigi.jp\0"
+"opole.pl\0"
+"sucks\0"
+"cab\0"
+"artanddesign.museum\0"
+"webredirect.org\0"
+"kashiwa.chiba.jp\0pb.leg.br\0"
+"tele.amune.org\0dnsalias.com\0"
+"kiwi.nz\0\xd0\xb5\xd1\x8e\0honeywell\0"
+"ca.us\0"
+"cal\0"
+"space.museum\0cam\0"
+"rankoshi.hokkaido.jp\0rawa-maz.pl\0"
+"zama.kanagawa.jp\0"
+"k12.mi.us\0cba\0"
+"car\0"
+"journalist.aero\0synology-ds.de\0"
+"cat\0"
+"rehab\0"
+"r\xc3\xb8mskog.no\0"
+"dynv6.net\0"
+"tychy.pl\0"
+"cbn\0"
+"\xe3\x82\xbb\xe3\x83\xbc\xe3\x83\xab\0"
+"cbs\0stuff-4-sale.org\0"
+"shell.museum\0cloud.fedoraproject.org\0"
+"sport\0"
+"rsc.cdn77.org\0"
+"omachi.nagano.jp\0"
+"biev\xc3\xa1t.no\0tennis\0tiaa\0"
+"ichinoseki.iwate.jp\0"
+"time.museum\0"
+"trading.aero\0"
+"citi\0from-ma.com\0"
+"ks.ua\0twmail.org\0synology-diskstation.de\0"
+"anani.br\0dupont\0"
+"\xd0\xb8\xd0\xba\xd0\xbe\xd0\xbc.museum\0"
+"jpmorgan\0router.management\0"
+"lincoln\0lixil\0"
+"valle-aosta.it\0ceb\0"
+"city\0"
+"nuoro.it\0iheya.okinawa.jp\0"
+"saitama.jp\0kamimine.saga.jp\0"
+"ks.us\0"
+"nakano.nagano.jp\0"
+"patria.bo\0md.ci\0"
+"ceo\0"
+"cfa\0from-pa.com\0"
+"tono.iwate.jp\0r.cdn77.net\0"
+"artdeco.museum\0civilization.museum\0bodo.no\0kiev.ua\0"
+"fujisato.akita.jp\0obama.nagasaki.jp\0cfd\0"
+"int.ar\0"
+"klabu.no\0radio\0"
+"buy\0"
+"ddnsgeek.com\0servesarcasm.com\0"
+"olbia-tempio.it\0"
+"k.bg\0\xc3\xb8rsta.no\0skodje.no\0"
+"int.az\0otsuki.kochi.jp\0""16-b.it\0"
+"mine.nu\0"
+"naie.hokkaido.jp\0"
+"int.bo\0algard.no\0"
+"trentino-s\xc3\xbc""d-tirol.it\0"
+"khakassia.su\0"
+"kure.hiroshima.jp\0land\0"
+"s\xc3\xb8rfold.no\0"
+"kaisei.kanagawa.jp\0ohira.tochigi.jp\0"
+"grane.no\0codespot.com\0"
+"shikabe.hokkaido.jp\0targi.pl\0"
+"takayama.nagano.jp\0itoigawa.niigata.jp\0zachpomor.pl\0"
+"empresa.bo\0int.ci\0"
+"mochizuki.nagano.jp\0"
+"is-very-good.org\0webhop.org\0"
+"fortal.br\0sr.it\0\xda\x80\xd8\xa7\xd8\xb1\xd8\xaa\0"
+"per.la\0"
+"int.co\0gjerdrum.no\0"
+"vanguard\0"
+"saltdal.no\0"
+"magazine.aero\0"
+"sciencesnaturelles.museum\0\xc3\xa5snes.no\0"
+"cr.it\0"
+"bievat.no\0lib.fl.us\0"
+"obihiro.hokkaido.jp\0"
+"ringebu.no\0cc.wi.us\0"
+"4.bg\0"
+"higashi.fukuoka.jp\0"
+"l\xc3\xb8""dingen.no\0est-le-patron.com\0"
+"mod.gi\0naturalhistorymuseum.museum\0hemnes.no\0"
+"tadotsu.kagawa.jp\0"
+"missoula.museum\0supply\0cable-modem.org\0"
+"schmidt\0dynu.net\0nerdpol.ovh\0"
+"getmyip.com\0"
+"asn.lv\0"
+"zapto.org\0"
+"kyowa.akita.jp\0now.sh\0"
+"lancome\0"
+"odo.br\0shunan.yamaguchi.jp\0per.nf\0"
+"nsn.us\0"
+"salvador.br\0omaezaki.shizuoka.jp\0bzh\0"
+"circus.museum\0"
+"unnan.shimane.jp\0"
+"gripe\0"
+"shriram\0"
+"cnt.br\0nikaho.akita.jp\0meiwa.gunma.jp\0"
+"omega\0otsuka\0"
+"toyoake.aichi.jp\0omura.nagasaki.jp\0"
+"extraspace\0"
+"game-host.org\0"
+"udine.it\0\xd1\x80\xd1\x84\0"
+"bulsan-suedtirol.it\0iglesiascarbonia.it\0"
+"niki.hokkaido.jp\0"
+"from-va.com\0"
+"noshiro.akita.jp\0agano.niigata.jp\0"
+"vega.no\0"
+"lt.it\0suwalki.pl\0"
+"yahiko.niigata.jp\0"
+"usarts.museum\0hoyanger.no\0from-wa.com\0"
+"oita.oita.jp\0"
+"\xe3\x81\xbf\xe3\x82\x93\xe3\x81\xaa\0"
+"childrensgarden.museum\0"
+"tarnobrzeg.pl\0\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe\0"
+"tajiri.osaka.jp\0toyono.osaka.jp\0"
+"auto.pl\0cloudycluster.net\0"
+"compare\0"
+"barsy.club\0"
+"r\xc3\xb8yrvik.no\0kids.us\0"
+"trentinoaadige.it\0"
+"saga.saga.jp\0"
+"gs.vf.no\0zp.ua\0"
+"tokyo.jp\0stargard.pl\0kred\0"
+"int.is\0"
+"nx.cn\0molise.it\0isa-geek.net\0"
+"im.it\0"
+"hyogo.jp\0toei.aichi.jp\0"
+"vaga.no\0"
+"jelenia-gora.pl\0"
+"kvalsund.no\0"
+"pi.leg.br\0"
+"pilot.aero\0per.sg\0"
+"trieste.it\0shimizu.hokkaido.jp\0seika.kyoto.jp\0"
+"television.museum\0"
+"coupon\0"
+"bykle.no\0cc.md.us\0"
+"com\0dscloud.mobi\0"
+"dattoweb.com\0"
+"tr.eu.org\0"
+"tamba.hyogo.jp\0dynalias.net\0"
+"int.la\0"
+"teramo.it\0"
+"lyngen.no\0"
+"shimotsuke.tochigi.jp\0"
+"secure\0"
+"americanantiques.museum\0"
+"cooking\0"
+"\xd0\xbc\xd0\xba\xd0\xb4\0"
+"int.lk\0ambulance.museum\0"
+"takashima.shiga.jp\0"
+"unusualperson.com\0"
+"tushu\0"
+"dad\0"
+"2000.hu\0luroy.no\0"
+"iamallama.com\0"
+"radio.br\0"
+"romsa.no\0"
+"wi.us\0"
+"noheji.aomori.jp\0nowruz\0"
+"ozu.ehime.jp\0"
+"arna.no\0ro.im\0"
+"xj.cn\0"
+"ato.br\0"
+"vagan.no\0day\0"
+"ro.it\0int.mv\0construction\0freebox-os.fr\0"
+"int.mw\0"
+"int.ni\0"
+"gz.cn\0capetown\0"
+"company\0"
+"qsl.br\0"
+"alfaromeo\0crs\0csc\0video\0"
+"sp.gov.br\0bo.it\0"
+"anamizu.ishikawa.jp\0sakae.nagano.jp\0"
+"cr.ua\0"
+"cloudfunctions.net\0"
+"siena.it\0"
+"tips\0"
+"ashiya.hyogo.jp\0"
+"myactivedirectory.com\0"
+"kaminoyama.yamagata.jp\0"
+"from-ca.com\0"
+"tobe.ehime.jp\0nikko.tochigi.jp\0sko.gov.pl\0"
+"otago.museum\0washingtondc.museum\0"
+"shiranuka.hokkaido.jp\0"
+"oceanographic.museum\0rana.no\0"
+"divtasvuodna.no\0"
+"vf.no\0meloy.no\0k12.mt.us\0insurance\0"
+"koebenhavn.museum\0aigo\0dds\0"
+"oyer.no\0netlify.com\0"
+"shakotan.hokkaido.jp\0"
+"\xd0\xbc\xd0\xbe\xd0\xbd\0"
+"int.pt\0"
+"\xe6\x95\x99\xe8\x82\xb2.\xe9\xa6\x99\xe6\xb8\xaf\0"
+"from-ia.com\0"
+"hita.oita.jp\0"
+"\xd0\xbe\xd0\xb1\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0"
+"\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86\0"
+"seihi.nagasaki.jp\0"
+"geekgalaxy.com\0"
+"taketa.oita.jp\0mutual\0"
+"dev\0"
+"research.aero\0mytis.ru\0"
+"gratangen.no\0"
+"mihara.kochi.jp\0gyokuto.kumamoto.jp\0"
+"takaishi.osaka.jp\0so.gov.pl\0"
+"from-ga.com\0"
+"furubira.hokkaido.jp\0ayabe.kyoto.jp\0"
+"lt.ua\0s3-website.eu-west-3.amazonaws.com\0"
+"tateyama.chiba.jp\0ohira.miyagi.jp\0pe.leg.br\0"
+"larvik.no\0verdal.no\0"
+"geometre-expert.fr\0"
+"int.ru\0"
+"biz.bb\0"
+"int.rw\0k.se\0"
+"hakata.fukuoka.jp\0czest.pl\0biz.at\0"
+"wildlife.museum\0spreadbetting\0"
+"otaki.chiba.jp\0suzu.ishikawa.jp\0"
+"mydobiss.com\0"
+"stpetersburg.museum\0cc.oh.us\0zone\0diskstation.me\0"
+"biz.az\0miasta.pl\0"
+"ask\xc3\xb8y.no\0"
+"yoshimi.saitama.jp\0"
+"md.us\0physio\0"
+"maebashi.gunma.jp\0"
+"ferrara.it\0"
+"dhl\0scrapper-site.net\0"
+"ann-arbor.mi.us\0"
+"int.tj\0"
+"lifestyle\0"
+"ishikawa.fukushima.jp\0"
+"diskstation.eu\0"
+"toyooka.hyogo.jp\0oi.kanagawa.jp\0"
+"maringa.br\0\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86.ir\0"
+"kragero.no\0vinnica.ua\0co.place\0"
+"blogdns.net\0"
+"int.tt\0"
+"baidar.no\0\xd0\xbe\xd0\xb4.\xd1\x81\xd1\x80\xd0\xb1\0"
+"biz.cy\0law.pro\0"
+"biz.dk\0"
+"fuchu.tokyo.jp\0for-some.biz\0"
+"*.sch.uk\0cc.la.us\0"
+"shintoku.hokkaido.jp\0"
+"airport.aero\0study\0"
+"int.ve\0diy\0grocery\0certmgr.org\0"
+"hiphop\0"
+"booking\0homeunix.org\0"
+"matsushige.tokushima.jp\0"
+"ts.it\0"
+"wajiki.tokushima.jp\0int.vn\0"
+"ltd.co.im\0"
+"hawaii.museum\0"
+"chikuzen.fukuoka.jp\0"
+"est-a-la-masion.com\0"
+"biz.et\0"
+"marriott\0"
+"apigee.io\0"
+"yuu.yamaguchi.jp\0"
+"natal.br\0hachinohe.aomori.jp\0"
+"sayama.osaka.jp\0"
+"9guacu.br\0budapest\0"
+"camera\0"
+"showa.gunma.jp\0"
+"eating-organic.net\0"
+"hirata.fukushima.jp\0"
+"wales\0dnsdojo.org\0"
+"snasa.no\0stream\0dontexist.com\0"
+"kuokgroup\0\xd8\xb9\xd8\xb1\xd8\xa8\0"
+"m\xc3\xa5s\xc3\xb8y.no\0"
+"nishi.fukuoka.jp\0"
+"ddnss.org\0"
+"ritto.shiga.jp\0"
+"n\xc3\xa6r\xc3\xb8y.no\0"
+"al.it\0"
+"isla.pr\0"
+"ide.kyoto.jp\0"
+"tecnologia.bo\0"
+"biz.id\0"
+"zaporizhzhia.ua\0"
+"kppsp.gov.pl\0dnp\0"
+"birkenes.no\0"
+"omuta.fukuoka.jp\0"
+"\xe6\x94\xbf\xe5\xba\x9c.\xe9\xa6\x99\xe6\xb8\xaf\0"
+"carbonia-iglesias.it\0"
+"arai.shizuoka.jp\0hokuto.yamanashi.jp\0"
+"dog\0"
+"nara.nara.jp\0"
+"swidnica.pl\0"
+"storage\0"
+"from-ny.net\0"
+"brussel.museum\0stordal.no\0"
+"mitane.akita.jp\0"
+"botanicgarden.museum\0asker.no\0"
+"judygarland.museum\0"
+"ne.jp\0yono.saitama.jp\0dot\0"
+"hiji.oita.jp\0oshima.tokyo.jp\0futurehosting.at\0"
+"pri.ee\0ne.ke\0atlanta.museum\0"
+"gold\0"
+"golf\0"
+"oh.us\0"
+"sr.gov.pl\0"
+"como.it\0"
+"biz.ki\0cc.al.us\0"
+"sarufutsu.hokkaido.jp\0arida.wakayama.jp\0"
+"mashiko.tochigi.jp\0chizu.tottori.jp\0bosch\0global\0beep.pl\0"
+"izumizaki.fukushima.jp\0ne.kr\0pr.leg.br\0"
+"samsung\0"
+"realestate.pl\0"
+"daito.osaka.jp\0asaka.saitama.jp\0"
+"kiho.mie.jp\0"
+"gloppen.no\0porsangu.no\0"
+"snaase.no\0uk.eu.org\0"
+"bologna.it\0eat\0"
+"yaita.tochigi.jp\0"
+"kawagoe.mie.jp\0kalisz.pl\0tourism.tn\0"
+"al.no\0"
+"biz.ls\0cc.ne.us\0is-a-liberal.com\0"
+"mb.ca\0"
+"higashikurume.tokyo.jp\0"
+"kv\xc3\xa6nangen.no\0la.us\0"
+"ginan.gifu.jp\0"
+"*.hosting.myjino.ru\0lima-city.rocks\0"
+"!city.nagoya.jp\0"
+"k12.vi.us\0ap-northeast-2.elasticbeanstalk.com\0"
+"legnica.pl\0"
+"rich\0"
+"goog\0*.transurl.be\0"
+"oketo.hokkaido.jp\0biz.mv\0starostwo.gov.pl\0"
+"biz.mw\0vegarshei.no\0eco\0is-very-sweet.org\0blogsyte.com\0"
+"fujikawa.yamanashi.jp\0"
+"biz.ni\0"
+"lig.it\0napoli.it\0aioi.hyogo.jp\0okuizumo.shimane.jp\0"
+"gallo\0"
+"tohma.hokkaido.jp\0rep.kp\0"
+"i.bg\0"
+"taishin.fukushima.jp\0sumita.iwate.jp\0hamatama.saga.jp\0"
+"yk.ca\0reise\0"
+"iwaki.fukushima.jp\0biz.nr\0"
+"andebu.no\0karaganda.su\0"
+"hamada.shimane.jp\0"
+"finland.museum\0helsinki.museum\0"
+"onagawa.miyagi.jp\0"
+"zone.id\0"
+"gob.ar\0"
+"edu\0"
+"dtv\0"
+"sp.it\0"
+"lib.tn.us\0s3-eu-west-3.amazonaws.com\0""001www.com\0"
+"immobilien\0"
+"gwiddle.co.uk\0"
+"parachuting.aero\0"
+"ip6.arpa\0gob.bo\0"
+"chita.aichi.jp\0"
+"biz.pk\0"
+"biz.pl\0"
+"lindas.no\0avianca\0"
+"cri.br\0"
+"biz.pr\0"
+"2.bg\0ne.pw\0"
+"musashimurayama.tokyo.jp\0"
+"is-a-doctor.com\0"
+"gob.cl\0bari.it\0tsuwano.shimane.jp\0ug.gov.pl\0"
+"annaka.gunma.jp\0in-the-band.net\0"
+"ski.museum\0"
+"joyo.kyoto.jp\0dvr\0"
+"indian.museum\0"
+"servecounterstrike.com\0"
+"date.hokkaido.jp\0zao.miyagi.jp\0"
+"trade\0"
+"bozen-s\xc3\xbc""dtirol.it\0warabi.saitama.jp\0"
+"\xe4\xbd\x90\xe8\xb3\x80.jp\0"
+"nesset.no\0*.transurl.eu\0"
+"pi.it\0"
+"no.com\0"
+"yusuhara.kochi.jp\0"
+"gob.do\0"
+"yoshinogari.saga.jp\0johana.toyama.jp\0"
+"gob.ec\0grozny.su\0"
+"mad.museum\0"
+"online.th\0a.run.app\0"
+"nanto.toyama.jp\0"
+"d\xc3\xb8nna.no\0"
+"nhlfan.net\0myftp.biz\0"
+"aguni.okinawa.jp\0"
+"bergbau.museum\0rogers\0"
+"oyabe.toyama.jp\0"
+"univ.sn\0"
+"prime\0"
+"gob.es\0"
+"gamvik.no\0"
+"\xe7\xa6\x8f\xe4\xba\x95.jp\0memset.net\0"
+"indigena.bo\0"
+"okegawa.saitama.jp\0shimizu.shizuoka.jp\0"
+"vix.br\0kyowa.hokkaido.jp\0nagaokakyo.kyoto.jp\0"
+"al.us\0no-ip.org\0oy.lc\0"
+"kunitomi.miyazaki.jp\0"
+"balsan-suedtirol.it\0wakuya.miyagi.jp\0gb.net\0"
+"ac\0"
+"ad\0mb.it\0biz.tj\0"
+"ae\0"
"af\0"
-"ag\0"
-"perugia.it\0"
-"ai\0lewismiller.museum\0monster\0"
-"izumizaki.fukushima.jp\0"
-"al\0"
-"am\0karasjok.no\0eat\0"
-"tas.edu.au\0ferrero\0dyn-o-saur.com\0"
-"ao\0kiyokawa.kanagawa.jp\0cheap\0"
-"aq\0ba\0"
-"ar\0bb\0"
-"as\0dupont\0from-wi.com\0"
-"at\0leirfjord.no\0"
-"au\0be\0sh.cn\0kunst.museum\0"
-"bf\0shiojiri.nagano.jp\0mobi.ke\0"
-"asn.au\0aw\0bg\0wakkanai.hokkaido.jp\0"
-"ax\0bh\0"
-"bi\0"
+"ag\0yahoo\0dnsupdater.de\0"
+"ai\0"
+"tonami.toyama.jp\0"
+"biz.ua\0"
+"al\0kanuma.tochigi.jp\0biz.tr\0"
+"am\0seljord.no\0ne.ug\0"
+"biz.tt\0"
+"ao\0creation.museum\0"
+"otaru.hokkaido.jp\0ne.tz\0"
+"aq\0ba\0stj\xc3\xb8rdalshalsen.no\0"
+"ar\0bb\0schaeffler\0"
+"as\0"
+"at\0"
+"au\0be\0jewelry.museum\0"
+"bf\0"
+"aw\0bg\0grozny.ru\0"
+"ax\0bh\0gob.gt\0"
+"bi\0ne.us\0"
"az\0bj\0"
-"forli-cesena.it\0"
-"air.museum\0"
-"bm\0jewelry\0"
-"bn\0"
-"bo\0lorenskog.no\0"
-"ca\0kuroishi.aomori.jp\0hirono.fukushima.jp\0tm.pl\0credit\0ggee\0"
-"br\0yawara.ibaraki.jp\0"
+"*.yokohama.jp\0matsumae.hokkaido.jp\0"
+"bm\0"
+"bn\0webhop.net\0"
+"bo\0of.by\0"
+"ca\0"
+"br\0gob.hn\0"
"bs\0cc\0"
-"bt\0cd\0"
-"bv\0cf\0artsandcrafts.museum\0kosher\0neustar\0"
+"bt\0cd\0szczytno.pl\0"
+"bv\0cf\0"
"bw\0cg\0"
-"ch\0eco\0"
+"ch\0vall\xc3\xa9""e-aoste.it\0biz.vn\0"
"by\0ci\0"
-"bz\0total\0"
+"bz\0"
+"k12.gu.us\0"
"cl\0"
-"media.aero\0cm\0cc.ms.us\0cc.nc.us\0hyatt\0"
-"trading.aero\0cn\0isen.kagoshima.jp\0wegrow.pl\0northwesternmutual\0"
-"co\0"
-"mino.gifu.jp\0nflfan.org\0"
-"cr\0assabu.hokkaido.jp\0"
-"gs.cn\0"
-"cu\0de\0"
-"cv\0"
-"cw\0s3-website-us-west-1.amazonaws.com\0"
-"cx\0servebbs.net\0"
-"cy\0"
+"cm\0c.cdn77.org\0"
+"cn\0"
+"co\0java\0"
+"tempioolbia.it\0"
+"alesund.no\0"
+"cr\0fukuyama.hiroshima.jp\0"
+"cu\0de\0farmequipment.museum\0"
+"cv\0iruma.saitama.jp\0"
+"cw\0"
+"cx\0seto.aichi.jp\0"
+"cy\0ushuaia.museum\0"
"cz\0dj\0"
-"dk\0portland.museum\0"
-"fst.br\0dm\0"
-"edu\0"
-"s.bg\0do\0dtv\0"
-"hurum.no\0paroch.k12.ma.us\0"
-"casacam.net\0"
-"chihayaakasaka.osaka.jp\0cechire.com\0"
+"dk\0games\0"
+"mobara.chiba.jp\0"
+"dm\0gjerstad.no\0naamesjevuemie.no\0"
+"do\0lur\xc3\xb8y.no\0is-a-green.com\0"
+"tools\0"
"ec\0"
-"cargo.aero\0tm.ro\0mypsx.net\0"
-"ee\0historical.museum\0"
-"uonuma.niigata.jp\0"
-"eg\0bs.it\0"
-"misawa.aomori.jp\0"
-"\xe6\x95\x8e\xe8\x82\xb2.hk\0gs.oslo.no\0"
-"dz\0nagano.jp\0tm.se\0"
-"scrapping.cc\0"
-"nankoku.kochi.jp\0"
-"higashiyoshino.nara.jp\0"
-"kiev.ua\0"
-"miyazaki.jp\0kushiro.hokkaido.jp\0"
+"okinawa.jp\0"
+"ee\0vefsn.no\0k12.tx.us\0"
+"eg\0"
+"tourism.pl\0"
+"dz\0kin.okinawa.jp\0"
+"museumcenter.museum\0valley.museum\0bingo\0"
+"baseball\0"
+"noticias.bo\0"
+"inagawa.hyogo.jp\0abu.yamaguchi.jp\0global.ssl.fastly.net\0"
+"co.com\0"
+"takahama.aichi.jp\0"
+"kayabe.hokkaido.jp\0"
"es\0"
-"et\0"
+"et\0school\0"
"eu\0"
-"higashiizumo.shimane.jp\0lib.az.us\0"
-"fi\0is-uberleet.com\0"
-"intuit\0volvo\0"
-"dvr\0*.advisor.ws\0"
-"nagoya\0"
-"fm\0\xc3\xa5snes.no\0"
-"andriatranibarletta.it\0nes.akershus.no\0"
-"fo\0botany.museum\0alesund.no\0grane.no\0"
+"fi\0"
+"aikawa.kanagawa.jp\0"
+"fm\0"
+"fo\0"
"ga\0"
-"fr\0gb\0california.museum\0"
+"fr\0gb\0"
+"dep.no\0media\0"
"gd\0"
"ge\0"
-"gf\0mx.na\0\xe9\xa4\x90\xe5\x8e\x85\0"
-"gg\0"
-"gh\0sanagochi.tokushima.jp\0active\0"
-"gi\0"
-"zama.kanagawa.jp\0"
-"gl\0namegawa.saitama.jp\0duns\0"
+"gf\0rm.it\0*.transurl.nl\0"
+"gg\0biz.zm\0"
+"gh\0"
+"gi\0i.ng\0gs.of.no\0"
+"gx.cn\0gl\0ouchi.saga.jp\0"
"gm\0"
-"gn\0florida.museum\0"
+"adm.br\0gn\0"
"gp\0"
-"gq\0pt.eu.org\0"
-"gr\0"
-"gs\0"
-"gt\0"
-"gu\0"
-"gw\0\xe4\xb8\xaa\xe4\xba\xba.hk\0winb.gov.pl\0"
-"fed.us\0"
-"gy\0iwama.ibaraki.jp\0"
-"tr\xc3\xb8gstad.no\0"
-"riopreto.br\0hk\0"
-"student.aero\0lancaster\0"
-"hm\0"
-"hn\0madrid\0"
-"cc.sc.us\0"
-"futtsu.chiba.jp\0"
-"sicily.it\0"
-"hr\0"
-"\xe5\x98\x89\xe9\x87\x8c\0"
-"ht\0id\0cc.na\0"
+"recreation.aero\0gq\0lib.dc.us\0fitness\0s3.dualstack.ap-northeast-1.amazonaws.com\0mypets.ws\0"
+"gr\0saga.jp\0matsubushi.saitama.jp\0"
+"gs\0\xe5\x80\x8b\xe4\xba\xba.\xe9\xa6\x99\xe6\xb8\xaf\0"
+"gt\0trentino-aadige.it\0lukow.pl\0"
+"gu\0cc.ut.us\0"
+"to.gov.br\0"
+"gw\0"
+"miyazu.kyoto.jp\0"
+"gy\0"
+"hk\0elvendrell.museum\0mel\xc3\xb8y.no\0"
+"gob.mx\0"
+"hm\0gob.ni\0hadsel.no\0"
+"hn\0aridagawa.wakayama.jp\0"
+"ubank\0s3.dualstack.eu-west-3.amazonaws.com\0"
+"kep.tr\0coach\0fan\0"
+"wpdevcloud.com\0cyon.site\0"
+"hr\0saarland\0dynathome.net\0"
+"andoy.no\0"
+"ht\0id\0akdn\0"
"hu\0ie\0"
-"talk\0"
-"economia.bo\0"
-"il\0"
+"oarai.ibaraki.jp\0futuremailing.at\0"
+"bnr.la\0"
+"higashi.okinawa.jp\0i.ph\0winb.gov.pl\0"
+"il\0for-more.biz\0"
"im\0"
-"in\0"
-"io\0togo.aichi.jp\0"
-"noda.chiba.jp\0augustow.pl\0dvag\0"
+"in\0matsumoto.kagoshima.jp\0"
+"io\0from-al.com\0"
+"naka.hiroshima.jp\0"
"iq\0"
-"ir\0cody.museum\0"
-"is\0flakstad.no\0"
-"it\0misato.shimane.jp\0"
-"je\0"
-"aver\xc3\xb8y.no\0prochowice.pl\0able\0"
-"lucania.it\0"
-"fortmissoula.museum\0gleeze.com\0"
-"khmelnytskyi.ua\0"
-"hichiso.gifu.jp\0"
-"jo\0glass.museum\0"
+"ir\0cri.nz\0"
+"is\0oldnavy\0"
+"it\0"
+"je\0gob.pa\0togliatti.su\0"
+"varoy.no\0is-a-bruinsfan.org\0"
+"watarai.mie.jp\0"
+"gob.pe\0"
+"news\0"
+"jo\0gob.pk\0"
"jp\0"
-"chino.nagano.jp\0"
-"internet-dns.de\0"
-"ke\0opoczno.pl\0"
-"griw.gov.pl\0"
-"kg\0k12.il.us\0"
-"rakkestad.no\0"
-"ki\0"
-"kikugawa.shizuoka.jp\0nasushiobara.tochigi.jp\0"
-"km\0misconfused.org\0"
-"kn\0"
+"floro.no\0"
+"radoy.no\0esq\0"
+"treviso.it\0katori.chiba.jp\0toga.toyama.jp\0freeboxos.fr\0"
+"ke\0"
+"kg\0"
+"furudono.fukushima.jp\0"
+"ki\0tree.museum\0dynalias.org\0"
+"mobi.gp\0trentinoa-adige.it\0toba.mie.jp\0ooshika.nagano.jp\0nagai.yamagata.jp\0"
+"koshu.yamanashi.jp\0"
+"km\0"
+"kn\0club\0next\0blogspot.co.at\0"
+"folldal.no\0lib.ma.us\0"
"kp\0"
"la\0"
-"shimodate.ibaraki.jp\0nagasaki.nagasaki.jp\0kr\0lb\0"
-"lc\0"
-"tromso.no\0"
-"tm.za\0"
-"kw\0"
-"\xe5\x85\xac\xe7\x9b\x8a\0"
+"kr\0lb\0"
+"lc\0naturbruksgymn.se\0"
+"shonai.yamagata.jp\0"
+"\xe6\xbe\xb3\xe9\x96\x80\0"
+"kw\0i.se\0"
+"haboro.hokkaido.jp\0"
"ky\0li\0"
-"kz\0"
-"lk\0"
-"realtor\0"
-"storj.farm\0"
-"!city.yokohama.jp\0is-a-student.com\0"
-"ma\0"
-"lr\0elverum.no\0"
-"ls\0mc\0norddal.no\0"
-"lt\0md\0gs.of.no\0"
-"minamifurano.hokkaido.jp\0lu\0me\0"
-"lv\0"
-"mg\0"
-"asn.lv\0mh\0hughes\0"
-"tokorozawa.saitama.jp\0ly\0"
-"ainan.ehime.jp\0mydrobo.com\0"
-"airport.aero\0mk\0"
-"ml\0mordovia.su\0"
-"mn\0"
-"kobayashi.miyazaki.jp\0mo\0"
-"trainer.aero\0mp\0click\0technology\0\xe9\x9b\x86\xe5\x9b\xa2\0"
-"milano.it\0mq\0na\0"
-"workinggroup.aero\0mr\0togliatti.su\0"
-"ms\0nc\0"
-"mt\0"
-"mu\0ne\0"
-"togitsu.nagasaki.jp\0mv\0nf\0"
+"chikuma.nagano.jp\0kz\0"
+"lk\0motorcycles\0"
+"cc.nv.us\0"
+"kawamata.fukushima.jp\0nagasu.kumamoto.jp\0"
+"ma\0protonet.io\0"
+"friulivgiulia.it\0lr\0"
+"ls\0mc\0"
+"lt\0md\0"
+"lu\0me\0\xc4\x8d\xc3\xa1hcesuolo.no\0eus\0"
+"hachioji.tokyo.jp\0lv\0"
+"mg\0alpha-myqnapcloud.com\0"
+"takasu.hokkaido.jp\0mh\0"
+"ly\0"
+"soccer\0stcgroup\0"
+"mk\0flakstad.no\0k12.vt.us\0"
+"ml\0"
+"ssl.origin.cdn77-secure.org\0"
+"cesena-forl\xc3\xac.it\0mn\0"
+"mo\0eidfjord.no\0\xd0\xbe\xd1\x80\xd0\xb3\0"
+"mp\0dabur\0"
+"mq\0na\0edu.eu.org\0tselinograd.su\0"
+"anpachi.gifu.jp\0kamakura.kanagawa.jp\0mr\0"
+"ms\0nc\0myqnapcloud.com\0"
+"fermo.it\0mt\0"
+"mu\0ne\0of.no\0"
+"ranzan.saitama.jp\0mv\0nf\0"
"mw\0ng\0"
-"6.bg\0mx\0"
-"my\0ni\0rana.no\0\xe5\xb9\xbf\xe4\xb8\x9c\0"
-"mz\0"
+"mx\0"
+"z.bg\0my\0ni\0is-into-anime.com\0"
+"asahikawa.hokkaido.jp\0mz\0gob.sv\0"
"nl\0"
-"no\0helsinki\0"
-"uwajima.ehime.jp\0"
-"dnsalias.net\0"
-"tahara.aichi.jp\0nr\0"
-"pp.se\0pp.ru\0"
-"\xe5\x8f\xb0\xe7\x81\xa3\0"
+"miyama.fukuoka.jp\0yanaizu.fukushima.jp\0"
+"no\0from-il.com\0"
+"nagano.nagano.jp\0makeup\0"
+"aizumi.tokushima.jp\0nr\0nextdirect\0"
+"yokawa.hyogo.jp\0yoshino.nara.jp\0"
"nu\0"
-"realestate.pl\0"
-"medicina.bo\0"
-"nh.us\0"
-"awaji.hyogo.jp\0nz\0"
-"mc.it\0kiyosu.aichi.jp\0"
-"om\0is-a-teacher.com\0"
-"sumida.tokyo.jp\0"
-"sakai.osaka.jp\0avianca\0"
+"tos.it\0"
+"from-fl.com\0"
+"nz\0trafficplex.cloud\0"
+"sardegna.it\0oshima.yamaguchi.jp\0"
+"masoy.no\0om\0"
+"dnsdojo.net\0"
+"takahagi.ibaraki.jp\0"
"pa\0"
-"tsubata.ishikawa.jp\0""4u.com\0"
-"cc.ua\0"
+"jl.cn\0"
+"national.museum\0bygland.no\0"
+"shimoichi.nara.jp\0lebork.pl\0"
"pe\0"
"pf\0"
-"ph\0"
-"myoko.niigata.jp\0"
-"brescia.it\0"
+"fosnes.no\0syno-ds.de\0"
+"chitose.hokkaido.jp\0ph\0"
+"quebec.museum\0aurland.no\0gob.ve\0money\0"
"pk\0"
-"pl\0mordovia.ru\0"
-"\xe7\xbd\x91\xe7\xbb\x9c.cn\0pm\0"
-"pn\0"
-"pp.ua\0"
-"ouchi.saga.jp\0qa\0"
-"pr\0"
+"koya.wakayama.jp\0pl\0financial\0"
+"pm\0"
+"shoo.okayama.jp\0pn\0"
+"sogne.no\0"
+"qa\0ut.us\0we.bs\0"
+"taiki.mie.jp\0taiwa.miyagi.jp\0pr\0"
"ps\0"
-"takasago.hyogo.jp\0pt\0"
-"\xe8\xaf\xba\xe5\x9f\xba\xe4\xba\x9a\0"
-"pw\0fan\0"
-"hachinohe.aomori.jp\0tsugaru.aomori.jp\0"
-"an.it\0py\0"
-"muenchen.museum\0"
-"teo.br\0"
-"tsurugashima.saitama.jp\0"
-"\xe9\x9d\x99\xe5\xb2\xa1.jp\0"
-"bristol.museum\0"
-"miki.hyogo.jp\0re\0"
-"security\0"
-"lebtimnetz.de\0"
-"cc.nv.us\0"
-"flt.cloud.muni.cz\0"
-"yahoo\0"
-"floripa.br\0lezajsk.pl\0luxury\0"
-"adachi.tokyo.jp\0"
-"niikappu.hokkaido.jp\0"
-"nara.nara.jp\0hattfjelldal.no\0ro\0"
-"sa\0"
-"mg.gov.br\0sb\0netflix\0"
-"takamori.kumamoto.jp\0rs\0sc\0"
-"la-spezia.it\0nishiokoppe.hokkaido.jp\0barcelona.museum\0\xc3\xb8ygarden.no\0sd\0"
-"togura.nagano.jp\0ru\0se\0"
-"donna.no\0"
-"shiraoi.hokkaido.jp\0rw\0sg\0abbott\0"
-"sn\xc3\xa5sa.no\0sh\0"
-"si\0cleverapps.io\0"
-"sj\0esq\0"
-"usgarden.museum\0sk\0servecounterstrike.com\0"
-"tank.museum\0v\xc3\xa6r\xc3\xb8y.no\0sl\0"
-"tomigusuku.okinawa.jp\0sm\0azerbaijan.su\0"
-"sn\0"
+"pt\0"
+"basel.museum\0"
+"ulsan.kr\0fit\0"
+"pw\0"
+"py\0"
+"\xe6\x9d\xb1\xe4\xba\xac.jp\0"
+"shinto.gunma.jp\0gwangju.kr\0"
+"org.ac\0"
+"wif.gov.pl\0"
+"org.ae\0"
+"org.af\0pz.it\0"
+"org.ag\0lib.sd.us\0"
+"yaizu.shizuoka.jp\0"
+"org.ai\0"
+"re\0"
+"org.al\0"
+"kaminokawa.tochigi.jp\0"
+"kyotamba.kyoto.jp\0fastlylb.net\0"
+"org.ba\0"
+"org.ar\0org.bb\0"
+"\xe6\xbe\xb3\xe9\x97\xa8\0blogspot.co.id\0"
+"org.au\0ro\0"
+"tysv\xc3\xa6r.no\0sa\0"
+"org.bh\0ashiya.fukuoka.jp\0sb\0"
+"org.bi\0kopervik.no\0rs\0sc\0beauty\0"
+"org.az\0sd\0"
+"ru\0se\0fastly-terrarium.com\0"
+"balsan.it\0blogspot.co.il\0"
+"org.bm\0archaeological.museum\0trustee.museum\0rw\0sg\0"
+"org.bn\0toki.gifu.jp\0kahoku.ishikawa.jp\0yoshikawa.saitama.jp\0sh\0"
+"org.bo\0si\0"
+"kaszuby.pl\0sj\0on-the-web.tv\0"
+"sk\0"
+"org.br\0mielno.pl\0sl\0"
+"org.bs\0sm\0black\0"
+"org.bt\0sn\0"
"so\0"
-"british.museum\0sr\0"
-"tc\0"
-"st\0td\0"
-"su\0"
-"sv\0tf\0"
-"architecture.museum\0tg\0"
-"sx\0th\0"
-"pup.gov.pl\0sy\0*.transurl.be\0"
-"sz\0tj\0vuelos\0"
-"tk\0"
+"df.gov.br\0sn.cn\0"
+"org.bw\0"
+"sr\0"
+"org.ci\0tc\0"
+"org.bz\0ms.it\0st\0td\0"
+"b\xc3\xa1jddar.no\0su\0"
+"\xd8\xa7\xd9\x8a\xd8\xb1\xd8\xa7\xd9\x86.ir\0asakuchi.okayama.jp\0sv\0tf\0"
+"karmoy.no\0lier.no\0tg\0redumbrella\0"
+"org.cn\0forl\xc3\xac""cesena.it\0sx\0th\0"
+"org.co\0sy\0"
+"slupsk.pl\0sz\0tj\0"
+"tk\0fly\0"
"tl\0"
-"rc.it\0tm\0"
-"tn\0"
-"westfalen.museum\0to\0"
-"ua\0"
-"tr\0"
-"tt\0"
-"yk.ca\0"
-"tv\0is-a-nurse.com\0"
-"tw\0ug\0taxi\0boxfuse.io\0"
-"\xe7\xbd\x91\xe7\xbb\x9c.hk\0arboretum.museum\0tz\0williamhill\0"
-"oishida.yamagata.jp\0uk\0"
-"profesional.bo\0eus\0"
-"s.se\0"
-"cooking\0cookingchannel\0"
-"arita.saga.jp\0lahppi.no\0"
-"riodejaneiro.museum\0va\0"
-"hiraya.nagano.jp\0cinema.museum\0nyny.museum\0"
-"kyotango.kyoto.jp\0us\0vc\0"
-"pordenone.it\0ve\0"
-"ontario.museum\0vg\0hepforge.org\0"
-"zapto.xyz\0"
-"fribourg.museum\0uy\0vi\0mg.leg.br\0"
-"beauxarts.museum\0uz\0"
-"no-ip.co.uk\0"
-"frosinone.it\0"
-"plc.ly\0"
-"vn\0"
-"trentino-suedtirol.it\0"
-"nf.ca\0"
-"nature.museum\0\xe9\x9b\xbb\xe8\xa8\x8a\xe7\x9b\x88\xe7\xa7\x91\0"
-"sciencecenter.museum\0vu\0"
-"wf\0"
-"qpon\0"
-"is-a-anarchist.com\0"
-"us-east-1.elasticbeanstalk.com\0"
-"tingvoll.no\0careers\0"
-"*.nom.br\0essex.museum\0"
-"kibichuo.okayama.jp\0birthplace.museum\0ws\0"
-"rovigo.it\0"
-"kagoshima.kagoshima.jp\0*.transurl.eu\0"
-"its.me\0"
-"oharu.aichi.jp\0brother\0"
-"reklam.hu\0"
-"rollag.no\0"
-"afjord.no\0"
-"yawatahama.ehime.jp\0"
-"vpnplus.to\0"
-"hino.tokyo.jp\0"
-"kamiichi.toyama.jp\0cc.ia.us\0"
-"leasing.aero\0yamato.fukushima.jp\0fuchu.toyama.jp\0media.museum\0logoip.de\0"
-"fit\0"
-"vs.it\0"
-"valledaosta.it\0"
-"yt\0"
-"lib.hi.us\0"
-"fuji.shizuoka.jp\0co.com\0"
-"mutsuzawa.chiba.jp\0gotpantheon.com\0"
-"showa.gunma.jp\0shimizu.shizuoka.jp\0"
-"zm\0"
-"teramo.it\0"
-"arezzo.it\0zp.ua\0"
-"aizumi.tokushima.jp\0"
-"br\xc3\xb8nn\xc3\xb8ysund.no\0"
-"nakagyo.kyoto.jp\0zw\0"
-"r\xc3\xa1hkker\xc3\xa1vju.no\0"
-"odawara.kanagawa.jp\0"
-"insurance.aero\0from-ut.com\0"
-"cloudapp.net\0"
-"l\xc3\xa6rdal.no\0"
-"aland.fi\0hachirogata.akita.jp\0"
-"yazu.tottori.jp\0wielun.pl\0"
-"bajddar.no\0"
-"website\0"
-"casino.hu\0"
-"vda.it\0"
-"lanxess\0"
-"federation.aero\0koga.fukuoka.jp\0"
-"fly\0"
-"legal\0"
-"ikawa.akita.jp\0"
-"etnedal.no\0"
-"gb.net\0"
-"uzs.gov.pl\0"
-"doesntexist.org\0"
-"ok.us\0"
-"starhub\0"
-"frogans\0"
-"linz.museum\0"
-"mydissent.net\0"
-"busan.kr\0"
-"nakano.tokyo.jp\0"
-"u2.xnbay.com\0"
-"stj\xc3\xb8rdalshalsen.no\0cv.ua\0plc.uk\0"
-"ha.cn\0hidaka.wakayama.jp\0"
-"dy.fi\0"
-"h\xc3\xb8nefoss.no\0"
-"endofinternet.net\0"
-"adac\0"
-"lib.mi.us\0"
+"tm\0brasilia.me\0"
+"ven.it\0shinagawa.tokyo.jp\0atm.pl\0tn\0"
+"org.cu\0to\0boutique\0"
+"org.cw\0ua\0"
+"shiga.jp\0gose.nara.jp\0tr\0"
+"org.cy\0is-a-personaltrainer.com\0"
+"tt\0olayan\0for-better.biz\0"
+"hakodate.hokkaido.jp\0jeonbuk.kr\0tv\0"
+"org.dm\0tw\0ug\0fedorapeople.org\0"
+"org.do\0nv.us\0"
+"tz\0hair\0"
+"losangeles.museum\0uk\0"
+"shimoji.okinawa.jp\0"
+"org.ec\0berg.no\0b\xc3\xb8.nordland.no\0"
+"org.ee\0"
+"org.eg\0va\0"
+"oto.fukuoka.jp\0ms.kr\0"
+"us\0vc\0"
+"org.dz\0sardinia.it\0trentins\xc3\xbc""dtirol.it\0kyotanabe.kyoto.jp\0"
+"ve\0whoswho\0home-webserver.de\0"
+"vg\0"
+"sos.pl\0"
+"uy\0vi\0"
+"uz\0freetls.fastly.net\0"
+"mysecuritycamera.com\0"
+"ptplus.fit\0"
+"org.es\0"
+"org.et\0vn\0"
"foo\0"
-"nagasaki.jp\0"
-"q.bg\0kannami.shizuoka.jp\0"
-"chungbuk.kr\0dyroy.no\0"
-"*.platformsh.site\0"
-"fox\0"
-"ohira.miyagi.jp\0onthewifi.com\0"
-"\xe9\xa6\x99\xe6\xb8\xaf\0"
-"ca.it\0"
-"museumvereniging.museum\0"
-"democracia.bo\0*.sendai.jp\0tachiarai.fukuoka.jp\0"
-"beta.bounty-full.com\0"
-"bauhaus\0apps.lair.io\0"
-"meldal.no\0\xe8\x81\x94\xe9\x80\x9a\0"
-"pn.it\0raid\0"
-"*.transurl.nl\0"
-"square7.de\0"
-"gal\0"
-"isehara.kanagawa.jp\0"
+"kasugai.aichi.jp\0"
+"vu\0"
+"wf\0"
+"cc.ms.us\0cc.nc.us\0mypep.link\0"
+"smola.no\0"
+"minamiawaji.hyogo.jp\0kami.miyagi.jp\0fox\0"
+"fie.ee\0"
+"org.ge\0mymailer.com.tw\0"
+"niyodogawa.kochi.jp\0"
+"org.gg\0"
+"org.gh\0anan.nagano.jp\0ac.leg.br\0"
+"org.gi\0ws\0lego\0"
+"org.gl\0cloud\0"
+"\xe9\xa6\x99\xe6\xa0\xbc\xe9\x87\x8c\xe6\x8b\x89\0"
+"org.gn\0"
+"bjerkreim.no\0filegear-au.me\0"
+"org.gp\0"
+"org.gr\0ge.it\0shikaoi.hokkaido.jp\0mitsuke.niigata.jp\0"
+"l\xc3\xb8ten.no\0readthedocs.io\0"
+"org.gt\0gal\0"
+"org.gu\0bar.pro\0"
+"mie.jp\0kunneppu.hokkaido.jp\0"
+"holiday\0"
"gap\0"
-"tydal.no\0"
-"yugawa.fukushima.jp\0"
-"uber.space\0"
-"sirdal.no\0"
-"shopping\0"
-"ddnsking.com\0"
-"frl\0"
-"\xe7\xb5\x84\xe7\xbb\x87.hk\0stuff-4-sale.org\0"
-"otsuki.kochi.jp\0"
-"couchpotatofries.org\0"
-"*.vps.myjino.ru\0"
-"asago.hyogo.jp\0"
-"damnserver.com\0"
-"zone.id\0"
-"symantec\0"
-"higashiomi.shiga.jp\0"
-"lib.ct.us\0"
-"ca.na\0if.ua\0"
-"kin.okinawa.jp\0"
-"cloudfunctions.net\0"
-"square7.ch\0"
-"gulen.no\0gdn\0"
-"lib.ri.us\0is-a-republican.com\0"
-"gea\0"
-"otaki.chiba.jp\0hole.no\0ftr\0dynathome.net\0"
-"\xe7\xbd\x91\xe7\xbb\x9c\0"
-"skiptvet.no\0"
-"nakano.nagano.jp\0"
-"warmia.pl\0bananarepublic\0"
-"gift\0"
-"ouda.nara.jp\0jur.pro\0tours\0"
-"shiroishi.miyagi.jp\0ritto.shiga.jp\0"
-"fun\0"
-"cards\0goldpoint\0"
-"port.fr\0"
-"joso.ibaraki.jp\0"
-"nesodden.no\0"
-"rec.br\0"
-"otaki.nagano.jp\0bahn.museum\0"
-"cern\0"
-"engineer\0"
-"lom.it\0"
-"sowa.ibaraki.jp\0"
-"rec.co\0umaji.kochi.jp\0"
-"varese.it\0sosa.chiba.jp\0minnesota.museum\0posts-and-telecommunications.museum\0"
-"modalen.no\0s3-ap-southeast-1.amazonaws.com\0"
-"rnu.tn\0"
-"asahi.mie.jp\0"
-"dynalias.com\0"
-"kamo.niigata.jp\0betainabox.com\0is-certified.com\0"
-"hanno.saitama.jp\0"
-"aridagawa.wakayama.jp\0"
-"kamikawa.saitama.jp\0"
-"trentinosuedtirol.it\0vegas\0"
-"katashina.gunma.jp\0gs.nt.no\0"
-"sf.no\0"
-"miyada.nagano.jp\0"
-"open\0"
-"servebbs.org\0"
-"otoyo.kochi.jp\0"
-"cologne\0toshiba\0"
-"hiratsuka.kanagawa.jp\0"
-"lib.id.us\0"
-"fyi\0hospital\0"
-"4.bg\0"
-"chikujo.fukuoka.jp\0"
-"origins\0"
-"lib.wi.us\0"
-"is-very-good.org\0"
-"biratori.hokkaido.jp\0"
-"aukra.no\0lindas.no\0"
-"ha.no\0"
-"yamatokoriyama.nara.jp\0ddnss.org\0"
-"suzu.ishikawa.jp\0yamagata.nagano.jp\0"
-"tokai.aichi.jp\0saikai.nagasaki.jp\0americana.museum\0bearalvahki.no\0"
-"plaza.museum\0"
-"nemuro.hokkaido.jp\0klodzko.pl\0"
-"itakura.gunma.jp\0nishihara.kumamoto.jp\0"
-"maniwa.okayama.jp\0de.cool\0"
-"salerno.it\0"
-"android\0"
-"lom.no\0"
-"misaki.osaka.jp\0"
-"nishinoomote.kagoshima.jp\0"
-"hammerfest.no\0k12.nj.us\0"
-"nago.okinawa.jp\0"
-"sandcats.io\0"
-"kutno.pl\0"
-"stange.no\0vladimir.su\0"
-"shika.ishikawa.jp\0"
-"gle\0dyndns-free.com\0"
-"k12.ec\0"
-"s\xc3\xb8r-varanger.no\0"
-"pointto.us\0"
-"id.au\0\xd0\xba\xd0\xbe\xd0\xbc\0"
-"kawaminami.miyazaki.jp\0ca.us\0"
-"kawaue.gifu.jp\0deals\0"
-"al.it\0tosashimizu.kochi.jp\0"
-"kumatori.osaka.jp\0"
-"iizuka.fukuoka.jp\0services\0"
-"discovery.museum\0"
-"ato.br\0twmail.net\0"
-"wa.au\0hol.no\0"
-"e164.arpa\0"
-"ddnss.de\0"
-"yokoshibahikari.chiba.jp\0"
-"uruma.okinawa.jp\0gs.st.no\0"
-"express.aero\0k12.as.us\0"
-"sasaguri.fukuoka.jp\0kushimoto.wakayama.jp\0"
-"rauma.no\0"
-"suwa.nagano.jp\0gmo\0"
-"wlocl.pl\0"
-"cahcesuolo.no\0"
-"masfjorden.no\0"
-"k12.or.us\0"
-"latrobe\0"
+"g.bg\0org.gy\0priv.hu\0pics\0"
+"org.hk\0computer.museum\0crimea.ua\0"
+"org.hn\0"
+"org.ht\0frl\0uk.net\0"
+"org.hu\0arboretum.museum\0is-a-rockstar.com\0"
+"sites.static.land\0"
+"eun.eg\0"
+"yt\0"
+"\xe5\xa4\xa9\xe4\xb8\xbb\xe6\x95\x99\0"
+"org.il\0tateshina.nagano.jp\0intuit\0"
+"org.im\0naroy.no\0"
+"org.in\0yawatahama.ehime.jp\0ms.leg.br\0"
+"aeroclub.aero\0qld.gov.au\0"
+"umi.fukuoka.jp\0"
+"org.iq\0nordre-land.no\0"
+"org.ir\0support\0"
+"org.is\0kunst.museum\0zm\0cust.testing.thingdust.io\0"
+"org.je\0ee.eu.org\0"
+"cn.it\0"
+"l\xc3\xa4ns.museum\0\xe4\xbd\x9b\xe5\xb1\xb1\0"
+"ribeirao.br\0"
+"miyako.fukuoka.jp\0"
+"0.bg\0zw\0"
+"org.jo\0"
+"shibuya.tokyo.jp\0"
+"saiki.oita.jp\0"
+"monza-e-della-brianza.it\0gdn\0"
+"org.kg\0"
+"ketrzyn.pl\0"
+"org.ki\0skedsmo.no\0gea\0"
+"\xe9\xab\x98\xe7\x9f\xa5.jp\0ftr\0"
+"org.km\0amsterdam\0"
+"alessandria.it\0org.kn\0church\0mt.leg.br\0"
+"cuisinella\0"
+"pg.it\0hannan.osaka.jp\0org.kp\0"
+"org.la\0lib.ri.us\0"
+"org.lb\0no-ip.net\0"
+"org.lc\0k12.ny.us\0"
+"nomi.ishikawa.jp\0"
+"waw.pl\0fun\0"
+"org.kw\0anthro.museum\0from-mo.com\0"
+"omihachiman.shiga.jp\0"
+"org.ky\0"
+"nahari.kochi.jp\0nagiso.nagano.jp\0org.kz\0"
+"org.lk\0"
+"chofu.tokyo.jp\0"
+"org.ma\0"
+"org.lr\0"
+"org.ls\0"
+"gen.in\0nobeoka.miyazaki.jp\0"
+"org.me\0naumburg.museum\0gos.pk\0"
+"belluno.it\0ashibetsu.hokkaido.jp\0org.lv\0"
+"org.mg\0\xe5\x95\x86\xe6\xa5\xad.tw\0"
+"priv.at\0"
+"org.ly\0gives\0"
+"org.mk\0field.museum\0"
+"org.ml\0"
+"org.mn\0"
+"org.mo\0lenvik.no\0"
+"org.na\0"
+"org.ms\0arts.museum\0"
+"caserta.it\0org.mt\0"
+"org.mu\0museum\0lib.mn.us\0"
+"\xe8\x8c\xa8\xe5\x9f\x8e.jp\0org.mv\0"
+"humanities.museum\0org.mw\0org.ng\0"
+"takko.aomori.jp\0org.mx\0nc.tr\0"
+"org.my\0org.ni\0"
+"mihama.wakayama.jp\0org.mz\0gniezno.pl\0"
+"nt.au\0blogspot.co.uk\0"
+"earth\0"
+"z.se\0iki.fi\0"
+"org.nr\0epost\0"
+"s3.eu-west-3.amazonaws.com\0"
+"trentins\xc3\xbc""d-tirol.it\0"
+"frana.no\0"
+"takatsuki.osaka.jp\0"
+"nt.ca\0"
+"kashihara.nara.jp\0verm\xc3\xb6gensberater\0"
+"ms.us\0nc.us\0itau\0"
+"org.nz\0"
+"hareid.no\0"
+"from.hr\0"
+"org.om\0"
+"miyagi.jp\0"
+"saito.miyazaki.jp\0"
+"org.pa\0fyi\0"
+"mobi.tt\0"
+"civilwar.museum\0rissa.no\0org.pe\0security\0\xd9\x85\xd9\x88\xd9\x82\xd8\xb9\0remotewd.com\0"
+"org.pf\0"
+"filatelia.museum\0"
+"org.ph\0"
+"dolls.museum\0rodoy.no\0tinn.no\0"
+"mobi.tz\0creditunion\0"
+"org.pk\0"
+"org.pl\0vapor.cloud\0"
+"org.pn\0"
+"ski.no\0"
+"org.qa\0haus\0"
+"kumenan.okayama.jp\0yatsuka.shimane.jp\0org.pr\0"
+"gulen.no\0org.ps\0"
+"misawa.aomori.jp\0org.pt\0"
+"ally\0bugatti\0filegear.me\0"
+"usculture.museum\0org.py\0keymachine.de\0"
+"military.museum\0"
+"koto.shiga.jp\0restaurant\0"
+"nt.edu.au\0volvo\0"
+"sannan.hyogo.jp\0other.nf\0"
+"swiss\0youtube\0"
+"vb.it\0aizumisato.fukushima.jp\0"
+"s3-website.ap-northeast-2.amazonaws.com\0"
+"sch.ae\0panama.museum\0"
+"hyuga.miyazaki.jp\0"
+"s3-us-west-1.amazonaws.com\0"
+"agr.br\0"
+"s3-website.ca-central-1.amazonaws.com\0"
+"gv.ao\0gle\0ping\0"
+"org.ro\0pimienta.org\0"
+"gen.nz\0"
+"org.sa\0lexus\0pink\0nfshost.com\0"
+"gv.at\0hiroshima.jp\0kawajima.saitama.jp\0org.sb\0"
+"org.rs\0org.sc\0"
+"org.sd\0"
+"org.se\0org.ru\0"
+"omaha.museum\0org.sg\0nflfan.org\0"
+"org.sh\0"
+"sandnessj\xc3\xb8""en.no\0"
+"org.sl\0"
+"sande.vestfold.no\0"
+"org.sn\0"
+"org.so\0"
+"nakatombetsu.hokkaido.jp\0"
+"nesna.no\0country\0"
+"ancona.it\0kiryu.gunma.jp\0hitachiota.ibaraki.jp\0"
+"org.st\0"
+"karasjohka.no\0blogspot.co.ke\0"
+"kitagawa.miyazaki.jp\0hasuda.saitama.jp\0org.sv\0"
+"gmo\0"
+"gs.nt.no\0org.sy\0"
+"org.sz\0org.tj\0"
+"org.tm\0"
+"yorii.saitama.jp\0org.tn\0"
+"org.to\0"
"gmx\0"
-"lib.mt.us\0lib.nd.us\0from-nm.com\0"
-"tsuno.miyazaki.jp\0"
-"kawanehon.shizuoka.jp\0rv.ua\0"
-"artcenter.museum\0"
-"yamakita.kanagawa.jp\0ternopil.ua\0homeunix.com\0fantasyleague.cc\0"
-"tur.ar\0vladimir.ru\0"
-"hara.nagano.jp\0"
-"psi.br\0miyama.mie.jp\0katsuragi.wakayama.jp\0"
-"ct.it\0"
-"buzz\0star\0"
-"the.br\0"
-"abu.yamaguchi.jp\0cc.co.us\0"
-"s3.ca-central-1.amazonaws.com\0"
-"goo\0"
+"mobi.na\0and\xc3\xb8y.no\0org.ua\0lib.de.us\0"
+"org.tr\0"
+"entomology.museum\0moskenes.no\0cn.ua\0"
+"org.tt\0"
+"modern.museum\0"
+"\xe6\x96\xb0\xe6\xbd\x9f.jp\0hioki.kagoshima.jp\0"
+"mobi.ng\0org.tw\0org.ug\0"
+"olkusz.pl\0"
+"org.uk\0tickets\0"
+"1kapp.com\0"
+"lardal.no\0"
+"fedex\0"
+"moareke.no\0org.vc\0ap-south-1.elasticbeanstalk.com\0"
+"org.ve\0"
+"goo\0hobby-site.com\0"
"gop\0"
-"ra.it\0matsumoto.kagoshima.jp\0shibata.niigata.jp\0"
-"tur.br\0"
-"got\0"
-"mobi\0"
-"gov\0"
-"isleofman.museum\0"
-"yamanashi.yamanashi.jp\0"
-"osasco.br\0"
-"aomori.aomori.jp\0sor-varanger.no\0\xe6\xb8\xb8\xe6\x88\x8f\0"
-"k12.il\0"
-"enterprises\0"
-"is.gov.pl\0"
-"\xc3\xa1laheadju.no\0"
-"tranibarlettaandria.it\0"
-"al.no\0"
-"rec.nf\0americanfamily\0"
-"slupsk.pl\0"
-"moda\0"
-"luzern.museum\0fairwinds\0"
-"is-a-liberal.com\0"
-"crown\0"
-"museum.tt\0is-into-games.com\0"
-"bio.br\0nakagawa.hokkaido.jp\0ilawa.pl\0"
-"gliding.aero\0portlligat.museum\0"
-"nishikatsura.yamanashi.jp\0seaport.museum\0"
-"kasuya.fukuoka.jp\0hirado.nagasaki.jp\0barsy.net\0"
-"higashiyodogawa.osaka.jp\0"
-"lebork.pl\0"
-"official.academy\0"
-"mer\xc3\xa5ker.no\0hbo\0"
-"aca.pro\0"
-"aircraft.aero\0chattanooga.museum\0"
-"nara.jp\0"
-"\xe6\x94\xbf\xe5\xba\x9c.hk\0alaheadju.no\0\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\x9f\0"
-"issmarterthanyou.com\0al.eu.org\0"
-"*.nagoya.jp\0capetown\0"
-"rentals\0"
-"budejju.no\0"
-"construction\0"
-"lib.sd.us\0dnsalias.org\0from-mt.com\0from-nd.com\0"
-"tomisato.chiba.jp\0"
-"liguria.it\0"
-"tomakomai.hokkaido.jp\0"
-"cloudns.biz\0"
-"id.ir\0shinichi.hiroshima.jp\0"
-"hiphop\0"
-"showa.yamanashi.jp\0royrvik.no\0url.tw\0pcloud.host\0"
-"iris.arpa\0ferrara.it\0oxford.museum\0"
-"larvik.no\0"
-"konan.shiga.jp\0school.na\0"
-"yamanobe.yamagata.jp\0"
-"lucca.it\0handson.museum\0dedyn.io\0"
-"trentinsued-tirol.it\0kawaguchi.saitama.jp\0wv.us\0ann-arbor.mi.us\0"
-"yuu.yamaguchi.jp\0"
-"sor-odal.no\0"
-"eu.int\0astronomy.museum\0"
-"obu.aichi.jp\0"
-"muroto.kochi.jp\0newspaper.museum\0amli.no\0"
-"oum.gov.pl\0gotdns.ch\0"
-"koryo.nara.jp\0lyngen.no\0"
-"judygarland.museum\0"
-"rec.ro\0aramco\0"
-"olawa.pl\0"
-"school.nz\0"
-"oguni.yamagata.jp\0"
-"rimini.it\0"
-"now.sh\0"
-"torsken.no\0mmafan.biz\0"
-"ma.us\0"
-"pgfog.com\0"
-"gratis\0"
-"id.lv\0"
-"\xeb\x8b\xb7\xeb\x84\xb7\0"
-"id.ly\0"
-"k12.ks.us\0merseine.nu\0"
-"wazuka.kyoto.jp\0"
-"tattoo\0"
-"trentino-sudtirol.it\0"
-"sd.cn\0"
-"tonsberg.no\0"
-"tsunan.niigata.jp\0pl.eu.org\0protonet.io\0"
-"midatlantic.museum\0"
-"business\0"
-"al.us\0"
-"from-ms.com\0from-nc.com\0"
-"iwi.nz\0"
-"satosho.okayama.jp\0tires\0"
-"tanohata.iwate.jp\0"
-"is-leet.com\0"
-"monmouth.museum\0ny.us\0"
-"est-a-la-masion.com\0"
-"indian.museum\0settlement.museum\0""2ix.at\0"
-"mt.it\0rec.ve\0"
-"nagaoka.niigata.jp\0"
-"komforb.se\0linkitools.space\0"
-"shishikui.tokushima.jp\0cc.mo.us\0farmers\0"
-"go.ci\0"
-"toyota.yamaguchi.jp\0"
-"higashimatsushima.miyagi.jp\0page\0"
-"aogaki.hyogo.jp\0"
+"minnesota.museum\0org.uy\0org.vi\0"
+"org.uz\0"
+"got\0wedeploy.sh\0"
+"plantation.museum\0k12.nh.us\0"
+"gov\0fukui.fukui.jp\0matsuda.kanagawa.jp\0org.vn\0"
+"rad\xc3\xb8y.no\0"
+"readmyblog.org\0"
+"org.vu\0"
+"vic.au\0edeka\0"
+"sekigahara.gifu.jp\0"
+"telekommunikation.museum\0"
+"kembuchi.hokkaido.jp\0"
+"agakhan\0irish\0"
+"piedmont.it\0"
+"org.ws\0"
+"shima.mie.jp\0ogose.saitama.jp\0gen.tr\0"
+"qh.cn\0blogspot.co.nz\0"
+"yokosuka.kanagawa.jp\0minamisanriku.miyagi.jp\0katano.osaka.jp\0swatch\0"
+"overhalla.no\0baidu\0\xe9\x80\x9a\xe8\xb2\xa9\0"
+"kamikitayama.nara.jp\0kimino.wakayama.jp\0"
+"donna.no\0"
+"ah.cn\0kitchen\0"
+"berlin.museum\0g.se\0hbo\0"
+"al.leg.br\0"
+"int.eu.org\0"
+"american.museum\0"
+"toray\0"
+"haibara.shizuoka.jp\0""2ix.at\0"
+"aosta-valley.it\0oki.fukuoka.jp\0kitashiobara.fukushima.jp\0misugi.mie.jp\0"
+"org.za\0"
+"amex\0"
+"mobi.ke\0herad.no\0aramco\0"
+"sch.id\0bando.ibaraki.jp\0"
+"glug.org.uk\0"
+"madrid\0"
+"szkola.pl\0"
+"imizu.toyama.jp\0"
+"osen.no\0org.zm\0"
+"\xd8\xb4\xd8\xa8\xd9\x83\xd8\xa9\0"
+"trentin-sudtirol.it\0uenohara.yamanashi.jp\0"
+"2ix.ch\0"
+"fidelity\0"
+"sch.ir\0"
+"frog.museum\0nt.no\0"
+"org.zw\0cbg.ru\0stufftoread.com\0"
+"urasoe.okinawa.jp\0mopar\0"
+"council.aero\0x.bg\0"
+"soundcast.me\0"
+"savona.it\0kyuragi.saga.jp\0"
+"miyakonojo.miyazaki.jp\0cookingchannel\0"
+"is-an-anarchist.com\0""2ix.de\0"
+"kurate.fukuoka.jp\0"
+"sch.jo\0"
+"theworkpc.com\0"
+"lplfinancial\0"
+"karate.museum\0kommunalforbund.se\0cn.eu.org\0"
+"zj.cn\0"
+"hoylandet.no\0law.za\0"
+"family\0"
+"to.it\0"
+"lib.va.us\0"
+"shinshinotsu.hokkaido.jp\0"
+"ando.nara.jp\0"
+"cranbrook.museum\0r\xc3\xa5holt.no\0"
+"vald-aosta.it\0"
+"erimo.hokkaido.jp\0"
+"gs.ah.no\0k12.ca.us\0"
+"hitachi.ibaraki.jp\0"
+"cc.wv.us\0"
+"rj.gov.br\0"
+"sch.lk\0s3-website.eu-west-2.amazonaws.com\0hopto.me\0"
+"lerdal.no\0"
+"customer.enonic.io\0"
+"trapani.it\0"
+"vic.gov.au\0investments\0"
+"gc.ca\0domains\0"
+"sch.ly\0cloud66.ws\0"
+"volkswagen\0"
+"assedic.fr\0psp.gov.pl\0"
+"fujishiro.ibaraki.jp\0"
+"nt.ro\0"
+"toyone.aichi.jp\0"
+"nemuro.hokkaido.jp\0broke-it.net\0"
+"sch.ng\0"
+"okawa.fukuoka.jp\0"
+"guovdageaidnu.no\0"
+"kaho.fukuoka.jp\0"
+"fage\0vote\0"
+"wellbeingzone.eu\0"
+"valle-d-aosta.it\0priv.pl\0"
+"asaminami.hiroshima.jp\0notogawa.shiga.jp\0"
+"karm\xc3\xb8y.no\0"
+"voto\0"
+"kerryhotels\0wedeploy.me\0"
+"baghdad.museum\0amfam\0ro.eu.org\0"
+"wakayama.jp\0"
"hiv\0"
-"salvadordali.museum\0lapy.pl\0"
-"go.cr\0k12.ok.us\0gallery\0"
-"higashikagura.hokkaido.jp\0"
-"cnt.br\0itako.ibaraki.jp\0"
-"vestby.no\0\xe5\xa4\xa7\xe6\x8b\xbf\0""2ix.ch\0"
-"piemonte.it\0washtenaw.mi.us\0"
-"o.bg\0r\xc3\xb8mskog.no\0vestvagoy.no\0"
-"marugame.kagawa.jp\0"
-"kuchinotsu.nagasaki.jp\0"
-"ct.us\0"
-"pol.dz\0museum.mv\0dev-myqnapcloud.com\0"
-"museum.mw\0pomorze.pl\0"
-"bo.it\0"
-"dr\xc3\xb8""bak.no\0"
-"2ix.de\0"
-"\xe7\xbd\x91\xe5\xba\x97\0"
-"lugansk.ua\0cc.az.us\0"
-"museum.no\0bestbuy\0"
-"culture.museum\0"
-"quicksytes.com\0"
-"shingu.wakayama.jp\0hkt\0"
-"k12.tr\0"
-"kisofukushima.nagano.jp\0"
-"ancona.it\0"
-"rennesoy.no\0"
-"2038.io\0"
-"museum.om\0"
-"onna.okinawa.jp\0"
-"hvaler.no\0"
-"seihi.nagasaki.jp\0linkyard-cloud.ch\0"
-"publishproxy.com\0"
-"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xdb\x8c\xd8\xa9\0"
-"servehumour.com\0"
-"fosnes.no\0\xe4\xb8\xad\xe6\x96\x87\xe7\xbd\x91\0"
-"and\xc3\xb8y.no\0"
-"k12.vi\0"
-"traeumtgerade.de\0"
-"fl.us\0"
-"koga.ibaraki.jp\0"
-"moriyoshi.akita.jp\0"
-"toyota.aichi.jp\0bahccavuotna.no\0"
-"uchinomi.kagawa.jp\0"
-"\xd9\xbe\xd8\xa7\xda\xa9\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\0spiegel\0"
-"moriya.ibaraki.jp\0"
-"tempioolbia.it\0"
-"villas\0"
-"soo.kagoshima.jp\0"
-"naka.ibaraki.jp\0"
-"pol.ht\0murata.miyagi.jp\0"
-"cherkasy.ua\0\xe0\xb8\xa3\xe0\xb8\xb1\xe0\xb8\x90\xe0\xb8\x9a\xe0\xb8\xb2\xe0\xb8\xa5.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0"
-"kusatsu.gunma.jp\0team\0"
-"tenei.fukushima.jp\0misugi.mie.jp\0s3-website-ap-southeast-1.amazonaws.com\0"
-"barsy.pro\0"
-"tsukigata.hokkaido.jp\0misato.miyagi.jp\0s3.dualstack.eu-west-3.amazonaws.com\0"
-"prd.fr\0"
-"ru.com\0is-not-certified.com\0"
-"matsushige.tokushima.jp\0"
-"go.id\0"
-"wakasa.fukui.jp\0"
-"vinnytsia.ua\0"
-"og.ao\0"
-"beppu.oita.jp\0town.museum\0"
-"hot\0"
-"eu-west-3.elasticbeanstalk.com\0"
-"id.us\0how\0"
-"go.it\0minamiyamashiro.kyoto.jp\0"
-"lodi.it\0shizuoka.jp\0cadaques.museum\0\xec\x82\xbc\xec\x84\xb1\0"
-"namerikawa.toyama.jp\0"
-"sa.edu.au\0tech\0"
-"bandai.fukushima.jp\0"
-"isahaya.nagasaki.jp\0"
-"wa.us\0"
-"hanawa.fukushima.jp\0"
-"homelink.one\0"
-"airtraffic.aero\0go.jp\0"
-"barsy.pub\0"
-"louvre.museum\0oystre-slidre.no\0"
-"aero\0"
-"sorocaba.br\0lakas.hu\0sydney\0i234.me\0"
-"go.ke\0"
-"oto.fukuoka.jp\0"
-"hu.net\0"
-"s3.dualstack.ap-northeast-1.amazonaws.com\0"
+"lel.br\0"
+"forsand.no\0"
+"\xd1\x80\xd1\x83\xd1\x81\0"
+"na.it\0"
+"bradesco\0"
+"ureshino.mie.jp\0"
+"od.ua\0"
"sic.it\0"
-"iheya.okinawa.jp\0"
-"hamatonbetsu.hokkaido.jp\0"
-"news.hu\0nakanoto.ishikawa.jp\0rns.tn\0za.com\0"
-"go.kr\0tirol\0"
-"uji.kyoto.jp\0"
-"organic\0"
-"moto\0"
-"ibm\0"
-"tara.saga.jp\0"
-"yurihonjo.akita.jp\0frana.no\0"
-"kerrylogistics\0locker\0"
-"chikuma.nagano.jp\0"
-"ice\0"
-"collegefan.org\0"
-"trentinsudtirol.it\0navuotna.no\0"
-"dnipropetrovsk.ua\0lilly\0endofinternet.org\0"
-"tran\xc3\xb8y.no\0"
-"forlicesena.it\0bievat.no\0"
-"kijo.miyazaki.jp\0"
-"prd.km\0nowruz\0"
-"film.museum\0icu\0"
-"kawagoe.mie.jp\0"
-"birdart.museum\0"
-"2.bg\0"
-"pvt.ge\0"
-"qld.au\0bridgestone\0"
-"ecologia.bo\0"
-"moareke.no\0"
-"fujimino.saitama.jp\0"
-"hikari.yamaguchi.jp\0"
-"tohma.hokkaido.jp\0"
-"numata.hokkaido.jp\0"
-"city.hu\0"
-"fujisato.akita.jp\0"
-"govt.nz\0"
-"vinnica.ua\0mt.us\0nd.us\0"
-"arte.bo\0kaisei.kanagawa.jp\0higashine.yamagata.jp\0"
-"lo.it\0prd.mg\0"
-"*.compute-1.amazonaws.com\0"
-"kanna.gunma.jp\0"
-"chat\0"
-"pars\0"
-"kongsvinger.no\0"
-"physio\0"
-"urayasu.chiba.jp\0echizen.fukui.jp\0"
-"fj.cn\0\xe6\x84\x9b\xe5\xaa\x9b.jp\0"
-"science\0dyndns-at-home.com\0"
-"kviteseid.no\0"
-"\xd8\xa7\xd8\xaa\xd8\xb5\xd8\xa7\xd9\x84\xd8\xa7\xd8\xaa\0"
-"varggat.no\0"
-"raisa.no\0temasek\0ae.org\0in-the-band.net\0"
-"ifm\0"
-"amot.no\0imamat\0"
-"oji.nara.jp\0pl.ua\0"
-"naka.hiroshima.jp\0"
-"kawakami.nara.jp\0esurance\0"
-"m\xc4\x81ori.nz\0imdb\0clan.rip\0"
-"gonohe.aomori.jp\0kariwa.niigata.jp\0jpn.com\0"
-"matsuno.ehime.jp\0"
-"go.pw\0"
-"s3-us-west-1.amazonaws.com\0"
-"snillfjord.no\0"
-"\xd0\xbc\xd0\xba\xd0\xb4\0"
-"alaska.museum\0isteingeek.de\0"
-"transporte.bo\0boleslawiec.pl\0"
-"og.it\0"
-"iwate.jp\0ybo.science\0"
-"n4t.co\0"
-"\xe5\x95\x86\xe5\xba\x97\0"
-"skedsmo.no\0"
-"kitagawa.miyazaki.jp\0"
-"yoka.hyogo.jp\0"
-"tohnosho.chiba.jp\0"
-"eidskog.no\0"
-"kahoku.ishikawa.jp\0"
-"cr.it\0otago.museum\0"
-"homelinux.com\0"
-"gs.hm.no\0capitalone\0"
-"hirogawa.wakayama.jp\0is-a-therapist.com\0"
-"\xd8\xb3\xd9\x88\xd8\xaf\xd8\xa7\xd9\x86\0"
-"ravenna.it\0"
-"biei.hokkaido.jp\0"
-"sd.us\0moscow\0"
-"curitiba.br\0"
-"arteducation.museum\0"
-"go.th\0pol.tr\0"
-"esan.hokkaido.jp\0hannan.osaka.jp\0gotsu.shimane.jp\0"
-"toyone.aichi.jp\0ostre-toten.no\0go.tj\0"
-"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xdb\x8c\xdb\x83\0"
-"kanmaki.nara.jp\0undersea.museum\0"
-"academy.museum\0"
-"sayama.saitama.jp\0"
-"fermo.it\0maori.nz\0"
-"iglesias-carbonia.it\0bryne.no\0"
-"ogliastra.it\0"
-"ando.nara.jp\0yao.osaka.jp\0go.ug\0"
-"o.se\0"
-"go.tz\0is-a-financialadvisor.com\0"
-"kawamata.fukushima.jp\0"
-"honjyo.akita.jp\0dealer\0"
-"orkdal.no\0"
-"lindesnes.no\0wedding\0"
-"trentinosudtirol.it\0"
-"namsos.no\0\xd0\xbc\xd0\xbe\xd0\xbd\0"
-"nokia\0"
-"onomichi.hiroshima.jp\0"
-"tagawa.fukuoka.jp\0"
-"blogspot.com\0"
-"nb.ca\0"
-"is-a-photographer.com\0"
-"qsl.br\0tarumizu.kagoshima.jp\0"
-"volkenkunde.museum\0"
-"fin.ec\0"
-"tuscany.it\0vicenza.it\0"
-"akita.jp\0"
-"brussels.museum\0"
-"jab.br\0inc\0"
-"k12.tx.us\0"
-"s3-website.eu-central-1.amazonaws.com\0"
-"ing\0barsy.me\0"
-"no.eu.org\0"
-"uchihara.ibaraki.jp\0"
-"fuso.aichi.jp\0v\xc3\xa1rgg\xc3\xa1t.no\0ink\0"
-"chuo.chiba.jp\0barsy.org\0"
-"oamishirasato.chiba.jp\0hokuryu.hokkaido.jp\0"
-"oz.au\0ogawa.saitama.jp\0oshino.yamanashi.jp\0"
-"bosch\0"
-"kamiizumi.saitama.jp\0"
-"int\0"
-"histoire.museum\0yolasite.com\0"
-"\xe7\xa6\x8f\xe5\xb3\xb6.jp\0lea\xc5\x8bgaviika.no\0"
-"schlesisches.museum\0"
-"surf\0"
-"smile\0pgafan.net\0"
-"toda.saitama.jp\0babia-gora.pl\0"
-"stuff-4-sale.us\0"
-"k12.ia.us\0apps.fbsbx.com\0flynnhosting.net\0"
-"sund.no\0phone\0"
-"skjak.no\0"
-"\xc3\xb8rland.no\0"
-"blanco\0whoswho\0alpha.bounty-full.com\0"
-"lombardia.it\0whaling.museum\0"
-"tomari.hokkaido.jp\0"
-"naturalhistorymuseum.museum\0from-fl.com\0"
-"brasil.museum\0sibenik.museum\0"
-"lib.tn.us\0"
-"castres.museum\0"
-"consulting.aero\0"
-"countryestate.museum\0olecko.pl\0immo\0appchizi.com\0"
-"twmail.org\0"
-"ohda.shimane.jp\0"
-"shimoji.okinawa.jp\0"
-"mus.br\0expert\0"
-"tatsuno.nagano.jp\0kawazu.shizuoka.jp\0"
-"santafe.museum\0"
-"lighting\0"
-"valleedaoste.it\0kazuno.akita.jp\0"
-"is-a-bulls-fan.com\0"
-"nishiawakura.okayama.jp\0"
-"livinghistory.museum\0bar.pro\0"
-"shirakawa.gifu.jp\0sanuki.kagawa.jp\0carrier.museum\0"
-"k12.ky.us\0\xe6\x94\xbf\xe5\xba\x9c.\xe9\xa6\x99\xe6\xb8\xaf\0"
-"now-dns.net\0"
-"cn-northwest-1.eb.amazonaws.com.cn\0"
-"tsuiki.fukuoka.jp\0"
-"fylkesbibl.no\0"
-"jcb\0"
-"teva\0"
-"tksat.bo\0"
-"saijo.ehime.jp\0kawajima.saitama.jp\0"
-"oguni.kumamoto.jp\0"
-"grp.lk\0"
-"hk.org\0"
-"bingo\0jcp\0"
-"narusawa.yamanashi.jp\0"
-"balat.no\0"
-"ujitawara.kyoto.jp\0\xc3\xb8stre-toten.no\0"
-"urbino-pesaro.it\0hamada.shimane.jp\0mo-i-rana.no\0ist\0"
-"nz.eu.org\0"
-"is-an-actor.com\0"
-"asker.no\0extraspace\0from-ri.com\0"
-"gaular.no\0"
-"aizubange.fukushima.jp\0"
-"cr.ua\0"
-"ashiya.hyogo.jp\0"
-"athleta\0s3.dualstack.ca-central-1.amazonaws.com\0"
-"akkeshi.hokkaido.jp\0itv\0"
-"solutions\0"
-"rome.it\0"
-"sagae.yamagata.jp\0atm.pl\0"
-"tanabe.kyoto.jp\0"
-"m.bg\0azurewebsites.net\0"
-"georgia.museum\0"
-"salem.museum\0"
-"shiranuka.hokkaido.jp\0yoshikawa.saitama.jp\0"
-"kumagaya.saitama.jp\0"
-"\xe7\xbe\xa4\xe9\xa6\xac.jp\0s3-us-gov-west-1.amazonaws.com\0"
-"rankoshi.hokkaido.jp\0hosting\0"
-"hotmail\0"
-"stockholm.museum\0"
-"flickr\0"
-"is-with-theband.com\0"
-"catholic\0"
-"snaase.no\0barsy.uk\0"
-"london\0photo\0"
-"minowa.nagano.jp\0skole.museum\0trana.no\0"
-"kiryu.gunma.jp\0orsta.no\0"
-"science.museum\0"
-"rendalen.no\0"
-"nozawaonsen.nagano.jp\0pccw\0"
+"interactive.museum\0norfolk.museum\0\xd7\x99\xd7\xa8\xd7\x95\xd7\xa9\xd7\x9c\xd7\x99\xd7\x9d.museum\0"
+"reggio-calabria.it\0"
+"gs.svalbard.no\0"
+"alibaba\0"
+"priv.no\0sch.qa\0"
+"sobetsu.hokkaido.jp\0fail\0"
+"dominic.ua\0cy.eu.org\0goip.de\0"
+"iz.hr\0square7.net\0"
+"pe.ca\0masfjorden.no\0"
+"tamayu.shimane.jp\0"
+"padua.it\0static.land\0"
+"marumori.miyagi.jp\0kamitonda.wakayama.jp\0hkt\0"
+"aure.no\0onyourside\0"
+"*.kobe.jp\0chihayaakasaka.osaka.jp\0lgbt\0"
+"misconfused.org\0"
+"canada.museum\0blogspot.co.za\0"
+"itoman.okinawa.jp\0nakaniikawa.toyama.jp\0"
+"avocat.fr\0jeep\0"
+"trana.no\0"
+"rel.ht\0"
+"meraker.no\0km.ua\0"
+"academy.museum\0miniserver.com\0"
+"jevnaker.no\0"
+"harstad.no\0"
+"abruzzo.it\0hashbang.sh\0"
+"sch.sa\0"
+"nic.in\0"
+"ah.no\0cz.eu.org\0"
+"tranby.no\0"
+"kunitachi.tokyo.jp\0"
+"priv.me\0"
+"kibichuo.okayama.jp\0mugi.tokushima.jp\0"
+"si.eu.org\0app.os.stg.fedoraproject.org\0"
+"minamiechizen.fukui.jp\0tsubetsu.hokkaido.jp\0"
+"ostre-toten.no\0orange\0"
+"nakatsugawa.gifu.jp\0"
+"vs.it\0smart\0"
+"cologne\0"
+"tsuruga.fukui.jp\0"
+"ln.cn\0"
+"loans\0"
+"fukusaki.hyogo.jp\0"
+"lavagis.no\0cloudns.eu\0"
+"itami.hyogo.jp\0wroclaw.pl\0cool\0"
+"nico\0"
+"udi.br\0tsuno.kochi.jp\0nowaruda.pl\0"
+"coop\0"
+"e.bg\0"
+"eu-west-2.elasticbeanstalk.com\0dk.eu.org\0"
+"wv.us\0"
+"namerikawa.toyama.jp\0"
"lyngdal.no\0"
-"pa.gov.br\0frosta.no\0vaga.no\0wskr.gov.pl\0"
-"shirosato.ibaraki.jp\0os\xc3\xb8yro.no\0"
-"rikubetsu.hokkaido.jp\0"
-"mihama.wakayama.jp\0"
-"porsgrunn.no\0"
-"unzen.nagasaki.jp\0"
-"*.yokohama.jp\0etne.no\0zgora.pl\0"
-"archaeology.museum\0"
-"agrigento.it\0"
-"watch\0"
-"hasami.nagasaki.jp\0"
-"mr.no\0"
-"kashiwara.osaka.jp\0rhcloud.com\0"
-"\xe7\xb6\xb2\xe7\xb5\xa1.\xe9\xa6\x99\xe6\xb8\xaf\0koeln\0"
-"orkanger.no\0read\0"
-"infiniti\0"
-"pb.gov.br\0"
-"horten.no\0"
-"us.org\0"
-"jio\0"
-"dlugoleka.pl\0"
-"osaki.miyagi.jp\0synology-ds.de\0"
-"industries\0gotdns.org\0"
-"pittsburgh.museum\0"
-"info\0"
-"kuki.saitama.jp\0"
-"trentinosued-tirol.it\0yokaichiba.chiba.jp\0nagano.nagano.jp\0taobao\0"
-"aeroport.fr\0linde\0"
-"dsmynas.org\0"
-"showtime\0"
-"farm.museum\0"
-"zj.cn\0osakikamijima.hiroshima.jp\0shari.hokkaido.jp\0"
-"solar\0"
-"ishigaki.okinawa.jp\0pa.leg.br\0"
-"mad.museum\0name\0degree\0myqnapcloud.com\0"
-"\xd0\xb4\xd0\xb5\xd1\x82\xd0\xb8\0"
-"avellino.it\0c.cdn77.org\0"
-"coupon\0"
-"saarland\0"
-"ranzan.saitama.jp\0biev\xc3\xa1t.no\0freebox-os.fr\0"
-"itami.hyogo.jp\0hokuto.yamanashi.jp\0"
-"saka.hiroshima.jp\0palace.museum\0"
-"khmelnitskiy.ua\0capital\0"
-"kuji.iwate.jp\0"
-"koshimizu.hokkaido.jp\0green\0"
-"nu.ca\0"
-"ah.cn\0"
-"ofunato.iwate.jp\0jlc\0qa2.com\0"
-"jll\0familyds.net\0"
-"donetsk.ua\0"
-"\xd8\xa7\xd9\x84\xd8\xac\xd8\xb2\xd8\xa7\xd8\xa6\xd8\xb1\0"
-"\xe7\xb6\xb2\xe7\xb5\xa1.cn\0samsung\0"
-"k12.vi.us\0verm\xc3\xb6gensberater\0pb.leg.br\0"
-"otsuki.yamanashi.jp\0"
-"biella.it\0"
-"fin.tn\0"
-"hirakata.osaka.jp\0database.museum\0"
-"airguard.museum\0loseyourip.com\0"
-"jor.br\0"
-"ip6.arpa\0"
-"genoa.it\0"
-"luroy.no\0"
-"usarts.museum\0jmp\0"
-"g\xc3\xa1\xc5\x8bgaviika.no\0"
-"domains\0""16-b.it\0"
-"b\xc3\xa6rum.no\0"
-"servebbs.com\0"
-"kamagaya.chiba.jp\0jnj\0"
-"my-router.de\0"
-"yaizu.shizuoka.jp\0walter\0"
-"hyllestad.no\0"
-"kai.yamanashi.jp\0"
-"beauty\0"
-"msk.ru\0"
-"0.bg\0vpndns.net\0"
-"tomioka.gunma.jp\0botanical.museum\0gjemnes.no\0"
-"\xe9\xa3\x9e\xe5\x88\xa9\xe6\xb5\xa6\0"
-"aisai.aichi.jp\0ayagawa.kagawa.jp\0mosjoen.no\0schmidt\0"
-"noshiro.akita.jp\0kunimi.fukushima.jp\0witd.gov.pl\0"
-"chieti.it\0fujisawa.kanagawa.jp\0"
-"cityeats\0"
-"naturalhistory.museum\0"
-"kobierzyce.pl\0jot\0msk.su\0"
-"yoshimi.saitama.jp\0giize.com\0forumz.info\0"
-"montreal.museum\0sherbrooke.museum\0"
-"kawahara.tottori.jp\0intelligence.museum\0"
-"rishirifuji.hokkaido.jp\0bern.museum\0statoil\0"
-"gov.ac\0joy\0"
-"gov.ae\0porsangu.no\0gmbh\0homelinux.net\0"
-"gov.af\0ilovecollege.info\0"
-"school.za\0"
-"iruma.saitama.jp\0"
-"hembygdsforbund.museum\0"
-"yufu.oita.jp\0zarow.pl\0"
-"gov.al\0"
-"rio.br\0"
-"gov.ba\0guernsey.museum\0"
-"gov.ar\0gov.bb\0"
-"aerodrome.aero\0gov.as\0beeldengeluid.museum\0"
-"gov.au\0"
-"gov.bf\0\xe7\xb6\xb2\xe7\xb5\xa1.hk\0"
-"matsumae.hokkaido.jp\0"
-"gov.bh\0\xd1\x81\xd0\xb0\xd0\xb9\xd1\x82\0"
-"gov.az\0azurecontainer.io\0"
-"takaoka.toyama.jp\0calvinklein\0"
-"gov.bm\0pinb.gov.pl\0"
-"gov.bn\0"
-"reit\0wellbeingzone.co.uk\0"
-"\xe7\xa5\x9e\xe5\xa5\x88\xe5\xb7\x9d.jp\0"
-"gov.br\0"
-"gov.bs\0"
-"gov.bt\0gov.cd\0"
-"gov.by\0children.museum\0gorge.museum\0"
-"gov.bz\0"
-"scientist.aero\0"
-"gov.cl\0nu.it\0"
-"gov.cm\0"
-"gov.cn\0"
-"gov.co\0"
-"cloudcontrolapp.com\0"
-"legnica.pl\0barsy.bg\0"
-"gov.cu\0"
-"karacol.su\0"
-"aviation.museum\0"
-"gov.cx\0"
-"gov.cy\0"
-"ski.no\0"
-"gov.dm\0lib.nh.us\0"
-"gov.do\0oizumi.gunma.jp\0"
-"sb.ua\0"
-"kawagoe.saitama.jp\0seljord.no\0"
-"wloclawek.pl\0"
-"gov.ec\0"
-"yokoze.saitama.jp\0"
-"gov.ee\0"
-"gov.eg\0"
-"black\0armenia.su\0"
-"gov.dz\0"
-"kyowa.hokkaido.jp\0kurotaki.nara.jp\0"
-"kadogawa.miyazaki.jp\0network\0"
-"navy\0"
-"yokkaichi.mie.jp\0kounosu.saitama.jp\0mup.gov.pl\0barsy.de\0"
-"kihoku.ehime.jp\0takahata.yamagata.jp\0"
-"gov.et\0"
-"andria-trani-barletta.it\0"
-"botanicalgarden.museum\0askim.no\0k12.co.us\0"
-"leg.br\0"
-"kpmg\0"
-"automotive.museum\0hb.cldmail.ru\0"
-"catanzaro.it\0"
-"audnedaln.no\0"
-"jx.cn\0"
-"shima.mie.jp\0"
-"kfh\0ddns.net\0"
-"staples\0"
-"gov.ge\0m.se\0"
-"gov.gh\0umbria.it\0"
-"gov.gi\0"
-"blogsite.org\0"
-"ah.no\0"
-"gov.gn\0"
-"bas.it\0rent\0"
-"barsy.eu\0"
-"gov.gr\0"
-"pi.gov.br\0"
-"gov.gu\0"
+"hot\0"
+"how\0"
+"us-west-2.elasticbeanstalk.com\0"
"oyama.tochigi.jp\0"
-"gov.gy\0"
-"gov.hk\0"
-"eng.br\0mp.br\0krakow.pl\0"
-"te.it\0merckmsd\0"
-"yamada.fukuoka.jp\0iwamizawa.hokkaido.jp\0"
-"miyazu.kyoto.jp\0bungoono.oita.jp\0citi\0"
-"kouyama.kagoshima.jp\0"
-"evje-og-hornnes.no\0mt.eu.org\0"
-"aseral.no\0"
-"gov.ie\0utwente.io\0"
-"ryugasaki.ibaraki.jp\0"
-"togane.chiba.jp\0hirata.fukushima.jp\0"
-"sayo.hyogo.jp\0"
-"iki.nagasaki.jp\0pharmacy\0"
-"kia\0"
-"gov.il\0ambulance.museum\0"
-"\xe7\xbb\x84\xe7\xbb\x87.hk\0"
-"gov.in\0"
-"wales.museum\0city\0"
-"gov.iq\0"
-"gov.ir\0ise.mie.jp\0"
-"gov.is\0"
-"gov.it\0"
-"otaru.hokkaido.jp\0"
-"kim\0"
-"sklep.pl\0szkola.pl\0"
-"gov.jo\0gifu.jp\0"
-"farmers.museum\0"
-"kadoma.osaka.jp\0"
-"semine.miyagi.jp\0"
-"akiruno.tokyo.jp\0eating-organic.net\0"
-"glade\0"
-"anjo.aichi.jp\0"
-"piacenza.it\0gov.kg\0cable-modem.org\0"
-"kiso.nagano.jp\0"
-"gov.ki\0"
-"pi.leg.br\0barsy.in\0"
-"barsy.io\0"
-"gov.km\0"
-"gov.kn\0"
-"yaita.tochigi.jp\0tokushima.tokushima.jp\0gov.kp\0jan-mayen.no\0ap-northeast-1.elasticbeanstalk.com\0mytuleap.com\0"
-"gov.la\0"
-"gov.lb\0"
-"gov.lc\0"
-"\xe5\xb2\xa9\xe6\x89\x8b.jp\0landes.museum\0"
-"tourism.tn\0"
-"gov.kw\0"
-"v-info.info\0"
-"maizuru.kyoto.jp\0gov.ky\0"
-"gov.kz\0"
-"gov.lk\0"
-"barrel-of-knowledge.info\0"
-"rest\0"
-"gov.ma\0"
-"gov.lr\0finn\xc3\xb8y.no\0"
-"gov.lt\0baidu\0"
-"gov.me\0"
-"gov.lv\0tana.no\0"
-"gov.mg\0"
-"judaica.museum\0"
-"gov.ly\0"
-"gov.mk\0"
-"gov.ml\0"
-"gov.mn\0"
-"gov.mo\0"
-"ski.museum\0"
-"politica.bo\0tagami.niigata.jp\0"
-"gov.mr\0"
-"gov.ms\0"
-"ascolipiceno.it\0"
-"ujiie.tochigi.jp\0gov.mu\0"
-"gov.mv\0"
-"force.museum\0gov.mw\0gov.ng\0"
-"ogata.akita.jp\0"
-"gov.my\0"
-"gov.mz\0\xd0\xbe\xd1\x80\xd0\xb3\0"
-"sassari.it\0"
-"off.ai\0pueblo.bo\0dnsiskinky.com\0"
-"\xd1\x83\xd0\xbf\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0"
-"hellas.museum\0virtual.museum\0"
-"york.museum\0gov.nr\0"
-"s3-ap-northeast-1.amazonaws.com\0redirectme.net\0"
-"amfam\0"
-"toyama.jp\0"
-"baidar.no\0roan.no\0doomdns.com\0"
-"broadway\0"
-"aomori.jp\0"
-"carraramassa.it\0"
-"building.museum\0"
-"gov.om\0"
-"kumejima.okinawa.jp\0"
-"dolls.museum\0"
-"yamagata.yamagata.jp\0evenes.no\0"
-"k12.al.us\0"
-"pe.gov.br\0minami-alps.yamanashi.jp\0"
-"gov.ph\0"
-"shimada.shizuoka.jp\0nachikatsuura.wakayama.jp\0interactive.museum\0"
-"kamifurano.hokkaido.jp\0"
-"gov.pk\0coupons\0report\0"
-"gov.pl\0k12.mo.us\0exchange\0"
-"tysvar.no\0gov.pn\0"
-"frontier\0"
-"gov.qa\0"
-"misaki.okayama.jp\0gov.pr\0mlbfan.org\0"
-"shop.ht\0kvinesdal.no\0gov.ps\0"
-"k.bg\0shop.hu\0gov.pt\0fh.se\0"
-"tsukuba.ibaraki.jp\0lier.no\0"
-"brussel.museum\0"
-"\xe5\xa4\xa7\xe5\x88\x86.jp\0kpn\0"
-"gov.py\0"
-"lutsk.ua\0"
-"*.uberspace.de\0"
-"barsycenter.com\0"
-"mukawa.hokkaido.jp\0stalbans.museum\0"
-"okinoshima.shimane.jp\0"
+"bellevue.museum\0"
+"nyc.mn\0"
+"fans\0style\0"
+"\xd9\x81\xd9\x84\xd8\xb3\xd8\xb7\xd9\x8a\xd9\x86\0"
+"cl.it\0"
+"sevastopol.ua\0"
+"okutama.tokyo.jp\0"
+"stateofdelaware.museum\0"
+"dyndns-work.com\0"
+"sel.no\0co.technology\0"
+"kwpsp.gov.pl\0"
+"engine.aero\0design.museum\0"
+"sorreisa.no\0sk.eu.org\0"
+"vardo.no\0"
+"karumai.iwate.jp\0akishima.tokyo.jp\0itabashi.tokyo.jp\0"
+"sue.fukuoka.jp\0"
+"\xe6\x94\xbf\xe5\x8a\xa1\0"
+"cloudns.in\0"
+"ibm\0"
+"ba.gov.br\0cesena-forli.it\0hekinan.aichi.jp\0moriyoshi.akita.jp\0"
+"inderoy.no\0"
+"brindisi.it\0"
+"dyndns.ddnss.de\0"
+"pe.it\0"
+"dyroy.no\0ice\0"
+"\xe0\xa6\xad\xe0\xa6\xbe\xe0\xa6\xb0\xe0\xa6\xa4\0"
+"filegear-ie.me\0"
+"simple-url.com\0"
+"de.eu.org\0"
+"hazu.aichi.jp\0"
+"riodejaneiro.museum\0cloudns.cc\0"
+"beardu.no\0"
+"bulsan.it\0"
+"arendal.no\0icu\0dynamisches-dns.de\0"
+"rel.pl\0"
+"sa.gov.au\0barsycenter.com\0"
+"codes\0"
+"takayama.gunma.jp\0olsztyn.pl\0"
+"za.com\0"
+"mamurogawa.yamagata.jp\0"
+"intelligence.museum\0\xc3\xb8stre-toten.no\0farm\0"
+"\xc3\xa1k\xc5\x8boluokta.no\0"
+"pe.kr\0"
+"mer\xc3\xa5ker.no\0"
+"dental\0"
+"sch.zm\0"
+"yosemite.museum\0dyndns.org\0"
+"katsuyama.fukui.jp\0"
+"x.se\0afamilycompany\0vacations\0"
+"rieti.it\0"
+"ru.eu.org\0se.eu.org\0"
+"kounosu.saitama.jp\0fast\0"
+"bill.museum\0"
+"akabira.hokkaido.jp\0"
+"matsuno.ehime.jp\0fbxos.fr\0"
+"\xe6\x95\x8e\xe8\x82\xb2.hk\0\xd1\x81\xd1\x80\xd0\xb1\0wedeploy.io\0"
+"achi.nagano.jp\0"
+"ifm\0nike\0"
+"happou.akita.jp\0"
+"gleeze.com\0"
+"airforce\0hk.org\0"
+"k12.wy.us\0"
+"rr.gov.br\0tawaramoto.nara.jp\0"
+"mansion.museum\0ulvik.no\0tunk.org\0"
+"venezia.it\0"
+"tel.tr\0"
+"iwata.shizuoka.jp\0incheon.kr\0"
+"castle.museum\0bostik\0"
+"fhs.no\0h\xc3\xa5.no\0"
+"nishiawakura.okayama.jp\0tabuse.yamaguchi.jp\0wskr.gov.pl\0"
+"\xe0\xb6\xbd\xe0\xb6\x82\xe0\xb6\x9a\xe0\xb7\x8f\0*.compute.amazonaws.com\0webhop.me\0"
+"karasuyama.tochigi.jp\0"
+"zushi.kanagawa.jp\0"
+"homeunix.com\0"
+"trentino-sud-tirol.it\0"
+"christmas\0"
+"val-daosta.it\0iwakuni.yamaguchi.jp\0"
+"joburg\0"
+"nic.tj\0"
+"jab.br\0*.kitakyushu.jp\0"
+"donostia.museum\0kvinnherad.no\0"
+"\xd0\xba\xd0\xb0\xd1\x82\xd0\xbe\xd0\xbb\xd0\xb8\xd0\xba\0"
+"eti.br\0aizuwakamatsu.fukushima.jp\0kitakami.iwate.jp\0"
+"belau.pw\0philips\0sa.com\0"
+"cuiaba.br\0kamiichi.toyama.jp\0"
+"her\xc3\xb8y.m\xc3\xb8re-og-romsdal.no\0vaksdal.no\0"
+"rs.gov.br\0sc.gov.br\0asti.it\0"
+"historisches.museum\0"
+"nhs.uk\0flynnhub.com\0"
+"soo.kagoshima.jp\0"
+"pesarourbino.it\0"
+"flekkefjord.no\0"
+"americana.museum\0leangaviika.no\0torsken.no\0"
+"zp.gov.pl\0center\0"
+"myhome-server.de\0"
+"rmit\0"
+"hdfc\0\xe4\xb8\xad\xe4\xbf\xa1\0familyds.com\0"
+"srv.br\0milan.it\0tosu.saga.jp\0"
+"forgot.his.name\0"
+"am.gov.br\0turen.tn\0"
+"groks-the.info\0"
+"h\xc3\xa1pmir.no\0"
+"fujikawa.shizuoka.jp\0"
+"tsukuba.ibaraki.jp\0kitadaito.okinawa.jp\0"
+"ri.it\0"
+"*.nom.br\0okazaki.aichi.jp\0izumo.shimane.jp\0"
+"airline.aero\0ca.eu.org\0logoip.com\0"
+"bi.it\0museum.tt\0"
+"natori.miyagi.jp\0"
+"namsskogan.no\0macys\0"
+"sondre-land.no\0"
+"historisch.museum\0"
+"imari.saga.jp\0homedepot\0"
+"shoes\0"
+"kharkov.ua\0from-nj.com\0"
"kawakita.ishikawa.jp\0"
-"udi.br\0"
-"gwiddle.co.uk\0"
-"krd\0lat\0"
-"barsy.online\0"
-"hasama.oita.jp\0koebenhavn.museum\0"
-"higashiosaka.osaka.jp\0gov.sa\0law\0"
-"gov.sb\0my.eu.org\0"
-"sanjo.niigata.jp\0gov.rs\0gov.sc\0"
-"susaki.kochi.jp\0porsanger.no\0gov.sd\0"
-"aga.niigata.jp\0gov.ru\0"
-"obira.hokkaido.jp\0"
-"gov.rw\0gov.sg\0"
-"gov.sh\0"
-"pe.leg.br\0"
-"aichi.jp\0te.ua\0"
-"gov.sl\0"
-"okinawa.okinawa.jp\0coach\0"
-"tjeldsund.no\0"
-"shoo.okayama.jp\0"
-"gov.st\0"
-"valle\xcc\x81""eaoste.it\0"
-"gov.sx\0"
-"gov.sy\0"
-"gov.tj\0"
-"gov.tl\0"
-"laspezia.it\0kragero.no\0gov.tm\0"
-"gov.tn\0"
-"gov.to\0"
-"gov.ua\0"
-"gov.tr\0"
-"k12.fl.us\0"
-"davvenj\xc3\xa1rga.no\0konskowola.pl\0gov.tt\0"
-"fukushima.hokkaido.jp\0boomla.net\0"
+"fedorainfracloud.org\0"
+"osasco.br\0friuli-vgiulia.it\0"
+"cymru\0"
+"washtenaw.mi.us\0"
+"tsuyama.okayama.jp\0boston\0"
+"tokai.ibaraki.jp\0"
+"sherbrooke.museum\0virtuel.museum\0"
+"tm.cy\0inc\0"
+"scholarships\0bryansk.su\0"
+"komoro.nagano.jp\0kunigami.okinawa.jp\0"
+"lib.al.us\0ing\0"
+"uryu.hokkaido.jp\0"
+"cc.ri.us\0ink\0"
+"turystyka.pl\0"
+"directory\0"
+"cloudns.us\0"
+"rn.gov.br\0int\0"
+"kutchan.hokkaido.jp\0"
+"verran.no\0"
+"lib.me.us\0"
+"oristano.it\0"
+"bolivia.bo\0"
+"group\0"
+"play\0"
+"e.se\0erni\0"
+"ome.tokyo.jp\0"
+"chicago.museum\0steiermark.museum\0"
+"tm.fr\0yachimata.chiba.jp\0beppu.oita.jp\0"
+"camdvr.org\0hb.cldmail.ru\0"
+"ap.gov.br\0"
+"omi.nagano.jp\0"
+"eiheiji.fukui.jp\0"
+"ro.gov.br\0seirou.niigata.jp\0nishinoshima.shimane.jp\0"
+"somna.no\0"
+"setouchi.okayama.jp\0"
+"iris.arpa\0ravendb.community\0uklugs.org\0"
+"fuji.shizuoka.jp\0gmina.pl\0"
+"dvrdns.org\0"
+"joboji.iwate.jp\0"
+"gs.tm.no\0cd.eu.org\0"
+"kawazu.shizuoka.jp\0"
+"mo.cn\0chiyoda.tokyo.jp\0"
+"dh.bytemark.co.uk\0"
+"asahi.ibaraki.jp\0tsu.mie.jp\0"
+"ap.gov.pl\0total\0"
+"v.bg\0bus.museum\0namsos.no\0"
+"nanmoku.gunma.jp\0bel.tr\0"
+"tm.hu\0"
+"drobak.no\0mex.com\0"
+"hikone.shiga.jp\0jcb\0"
+"malvik.no\0agric.za\0wang\0fastvps-server.com\0"
+"is-a-chef.org\0"
+"prato.it\0*.cryptonomic.net\0"
+"!city.kitakyushu.jp\0"
+"\xd9\x85\xd9\x88\xd8\xa8\xd8\xa7\xd9\x8a\xd9\x84\xd9\x8a\0"
+"mayfirst.org\0"
+"shirosato.ibaraki.jp\0izumisano.osaka.jp\0kiyose.tokyo.jp\0jcp\0"
+"omasvuotna.no\0"
+"schokoladen.museum\0official.academy\0"
+"togane.chiba.jp\0yotsukaido.chiba.jp\0ist\0"
+"wa.au\0clothing\0"
+"hongo.hiroshima.jp\0"
+"services.aero\0tas.au\0rivne.ua\0"
"her\xc3\xb8y.nordland.no\0"
-"gov.tw\0"
-"mywire.org\0"
+"conference.aero\0"
+"andriatranibarletta.it\0museum.mv\0"
+"museum.mw\0is-a-therapist.com\0"
+"itv\0"
+"tm.km\0"
+"pomorskie.pl\0dyndns.tv\0"
+"bonn.museum\0"
+"kiyosato.hokkaido.jp\0"
+"museum.no\0"
+"nagato.yamaguchi.jp\0"
+"casacam.net\0"
+"bamble.no\0"
+"pv.it\0"
"is-a-candidate.org\0"
-"boehringer\0"
-"uto.kumamoto.jp\0gov.uk\0"
-"ena.gifu.jp\0pa.gov.pl\0lds\0"
-"kv\xc3\xa6nangen.no\0"
-"kvafjord.no\0gov.vc\0visa\0"
-"loginto.me\0"
-"gov.ve\0"
-"zoological.museum\0"
-"trentin-sud-tirol.it\0sandoy.no\0panasonic\0"
-"salat.no\0futuremailing.at\0"
-"gov.vn\0"
-"bardu.no\0"
-"scjohnson\0"
-"inabe.mie.jp\0aigo\0"
-"ibaraki.jp\0"
-"ns.ca\0"
-"land\0"
-"mandal.no\0now-dns.org\0"
-"bokn.no\0"
-"\xe7\xa7\xbb\xe5\x8a\xa8\0s3-website-sa-east-1.amazonaws.com\0"
-"fukumitsu.toyama.jp\0stada\0"
-"recht.pro\0"
-"asahi.chiba.jp\0"
-"vibo-valentia.it\0"
-"kh.ua\0"
-"nasu.tochigi.jp\0leka.no\0sorfold.no\0gov.ws\0yombo.me\0"
-"tourism.pl\0"
-"h\xc3\xa1""bmer.no\0onion\0"
-"abbvie\0"
-"yamaxun\0"
-"tra.kp\0gs.aa.no\0net-freaks.com\0"
-"kujukuri.chiba.jp\0fukagawa.hokkaido.jp\0"
-"nl.eu.org\0"
-"takaharu.miyazaki.jp\0viva\0"
-"mydatto.com\0"
-"is.it\0lifestyle\0"
-"yamanakako.yamanashi.jp\0"
-"itano.tokushima.jp\0"
-"cc.in.us\0"
-"zgorzelec.pl\0"
-"br.com\0"
-"far.br\0lib.ee\0notodden.no\0"
-"gov.za\0vivo\0"
-"act.au\0pr.gov.br\0nanbu.tottori.jp\0"
-"moseushi.hokkaido.jp\0"
-"padua.it\0susono.shizuoka.jp\0"
-"ciscofreak.com\0"
-"karm\xc3\xb8y.no\0"
-"vang.no\0"
-"haibara.shizuoka.jp\0"
-"gov.zm\0lotte\0"
-"kiho.mie.jp\0valley.museum\0"
-"cambridge.museum\0"
-"mol.it\0vagan.no\0glass\0"
-"info.gu\0"
-"takayama.nagano.jp\0"
-"ox.rs\0"
-"gov.zw\0lotto\0"
-"zlg.br\0bungotakada.oita.jp\0"
-"dabur\0kyoto\0"
-"hawaii.museum\0"
-"ninohe.iwate.jp\0"
-"info.ht\0"
-"info.hu\0"
-"makinohara.shizuoka.jp\0"
-"dazaifu.fukuoka.jp\0"
-"bellevue.museum\0nativeamerican.museum\0theater\0"
-"llc\0"
-"k12.md.us\0courses\0"
-"tas.gov.au\0shiki.saitama.jp\0eu.meteorapp.com\0"
-"educator.aero\0"
-"info.et\0sakura\0"
-"egersund.no\0homelinux.org\0js.org\0"
-"is-a-techie.com\0pr.leg.br\0"
-"mobile\0"
-"field.museum\0hamaroy.no\0"
-"production.aero\0takamatsu.kagawa.jp\0wallonie.museum\0philips\0"
-"ostroda.pl\0tgory.pl\0"
-"\xd0\xb8\xd0\xba\xd0\xbe\xd0\xbc.museum\0"
-"basketball\0"
-"emb.kw\0"
-"idf.il\0securitytactics.com\0"
-"manaus.br\0hof.no\0"
-"austrheim.no\0"
-"kred\0"
-"noheji.aomori.jp\0my-vigor.de\0"
-"firenze.it\0"
-"dnsdojo.com\0"
-"giehtavuoatna.no\0"
-"inder\xc3\xb8y.no\0"
-"mobily\0"
-"tiaa\0"
-"azumino.nagano.jp\0nesset.no\0"
-"ng.eu.org\0dsmynas.net\0"
-"hn.cn\0\xe0\xac\xad\xe0\xac\xbe\xe0\xac\xb0\xe0\xac\xa4\0"
-"\xe7\xa6\x8f\xe4\xba\x95.jp\0kashiwazaki.niigata.jp\0"
-"no-ip.ca\0"
-"info.cx\0"
-"hakata.fukuoka.jp\0"
-"m\xc3\xa5s\xc3\xb8y.no\0lib.nj.us\0"
-"trentinosu\xcc\x88""d-tirol.it\0"
-"info.ec\0higashimurayama.tokyo.jp\0stateofdelaware.museum\0"
-"yachiyo.ibaraki.jp\0"
-"tamakawa.fukushima.jp\0"
-"parma.it\0firewall-gateway.com\0"
-"psc.br\0lol\0"
-"cn.it\0"
-"cloud\0servemp3.com\0"
-"\xe7\xbb\x84\xe7\xbb\x87\xe6\x9c\xba\xe6\x9e\x84\0"
-"nsn.us\0azure-mobile.net\0"
-"aurskog-holand.no\0"
-"eniwa.hokkaido.jp\0"
-"info.bb\0parti.se\0"
-"info.at\0"
-"info.au\0gs.vf.no\0"
-"bari.it\0k12.de.us\0"
-"lpl\0"
-"palermo.it\0farmstead.museum\0"
-"info.az\0familyds.org\0"
-"engerdal.no\0"
-"info.bo\0inf.br\0"
-"\xd8\xb9\xd8\xb1\xd8\xa8\0"
-"nakadomari.aomori.jp\0"
-"minamiechizen.fukui.jp\0k.se\0"
-"lib.or.us\0"
-"north.museum\0rahkkeravju.no\0"
-"mallorca.museum\0"
-"man\0"
-"chonan.chiba.jp\0bo.nordland.no\0"
-"hayashima.okayama.jp\0map\0paris.eu.org\0"
-"lavagis.no\0\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe\0mba\0"
-"bifuka.hokkaido.jp\0"
-"info.co\0meiwa.mie.jp\0"
-"b\xc3\xa1id\xc3\xa1r.no\0"
-"inf.cu\0"
-"ozu.ehime.jp\0storage\0from-oh.com\0"
-"tx.us\0"
-"lima-city.rocks\0"
-"nagasu.kumamoto.jp\0"
-"ss.it\0"
-"okawa.kochi.jp\0"
-"trapani.it\0"
-"izumi.kagoshima.jp\0svelvik.no\0"
-"rightathome\0"
-"storfjord.no\0"
-"tajimi.gifu.jp\0"
-"otari.nagano.jp\0ltd\0"
-"lubin.pl\0"
-"yahaba.iwate.jp\0uzhgorod.ua\0"
-"davvenjarga.no\0"
-"engine.aero\0"
-"is-a-caterer.com\0"
-"huissier-justice.fr\0fjaler.no\0"
-"kasumigaura.ibaraki.jp\0"
-"cc.hi.us\0"
-"reggiocalabria.it\0med\0"
-"shimonoseki.yamaguchi.jp\0"
-"rygge.no\0"
-"press.cy\0static-access.net\0"
-"from-md.com\0"
-"mantova.it\0"
-"men\0"
-"l\xc3\xb8""dingen.no\0"
-"lib.ga.us\0"
-"valle\xcc\x81""e-aoste.it\0childrens.museum\0"
-"uozu.toyama.jp\0"
-"matsumoto.nagano.jp\0oita.oita.jp\0"
-"shop.ro\0"
-"dyndns-home.com\0"
-"balsan-suedtirol.it\0hyundai\0"
-"k12.vt.us\0"
-"natuurwetenschappen.museum\0"
-"kvits\xc3\xb8y.no\0"
-"sekikawa.niigata.jp\0piw.gov.pl\0"
-"stockholm\0tkmaxx\0"
-"santacruz.museum\0"
-"realestate\0dd-dns.de\0"
-"\xe7\xb6\xb2\xe7\xbb\x9c.hk\0"
-"sdn.gov.pl\0"
-"nowaruda.pl\0nat.tn\0cartier\0mangyshlak.su\0"
-"shop.pl\0"
-"emergency.aero\0"
-"shonai.yamagata.jp\0"
-"sakai.ibaraki.jp\0"
-"shangrila\0"
-"development.run\0"
-"office-on-the.net\0"
-"tenkawa.nara.jp\0"
-"sweetpepper.org\0"
-"yomitan.okinawa.jp\0bus.museum\0philadelphiaarea.museum\0po.gov.pl\0"
-"\xe5\xb1\xb1\xe5\x8f\xa3.jp\0bamble.no\0"
-"from-ca.com\0"
-"friuli-vegiulia.it\0"
-"tv.bb\0"
-"aquila.it\0"
-"art.br\0mil\0"
-"mn.it\0"
-"ponpes.id\0"
-"mit\0fastpanel.direct\0"
-"cc.mi.us\0vlaanderen\0"
-"tv.bo\0gold\0"
-"is-a-hard-worker.com\0pantheonsite.io\0"
-"zao.miyagi.jp\0golf\0"
-"tv.br\0cn.ua\0"
-"leclerc\0"
-"\xd8\xb4\xd8\xa8\xd9\x83\xd8\xa9\0"
-"johana.toyama.jp\0"
-"lipsy\0"
-"k12.ne.us\0"
-"roma.it\0jaworzno.pl\0lib.la.us\0"
-"kusu.oita.jp\0fuchu.tokyo.jp\0"
-"i.bg\0"
-"\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa7\0clinique\0beep.pl\0"
-"art.do\0"
-"\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa9\0"
-"inf.mk\0"
-"pesarourbino.it\0"
-"bi.it\0kitayama.wakayama.jp\0baths.museum\0"
-"saotome.st\0\xe4\xbd\x9b\xe5\xb1\xb1\0"
-"mlb\0"
-"jus.br\0"
-"art.dz\0"
-"trentino-sued-tirol.it\0"
-"coal.museum\0myds.me\0"
-"happou.akita.jp\0info.ve\0"
-"tysv\xc3\xa6r.no\0"
-"cc.pa.us\0"
-"greta.fr\0"
-"stargard.pl\0mma\0"
-"aid.pl\0"
-"info.vn\0mls\0"
-"friuli-veneziagiulia.it\0shunan.yamaguchi.jp\0"
-"elasticbeanstalk.com\0"
-"goog\0"
-"lib.ny.us\0pioneer\0"
-"chuo.osaka.jp\0"
-"ariake.saga.jp\0"
-"xnbay.com\0"
-"trentino-stirol.it\0usuki.oita.jp\0"
-"istmein.de\0"
-"shiraoka.saitama.jp\0olkusz.pl\0"
-"s3-website.us-east-2.amazonaws.com\0"
-"rep.kp\0"
-"tips\0"
-"ora.gunma.jp\0timekeeping.museum\0isa-hockeynut.com\0"
-"uvic.museum\0"
-"nord-odal.no\0"
-"ayabe.kyoto.jp\0"
-"rn.it\0gokase.miyazaki.jp\0info.tn\0"
-"folkebibl.no\0moe\0own.pm\0"
-"info.tr\0cc.ri.us\0"
-"caltanissetta.it\0info.tt\0moi\0"
-"shikabe.hokkaido.jp\0"
-"mom\0dyndns.ddnss.de\0"
-"art.ht\0intl.tn\0"
-"info.tz\0"
-"trustee.museum\0"
-"wakasa.tottori.jp\0"
-"theatre\0"
-"mov\0statefarm\0"
-"higashihiroshima.hiroshima.jp\0"
-"agano.niigata.jp\0"
-"hiranai.aomori.jp\0opencraft.hosting\0"
-"shiksha\0"
-"\xc3\xa1lt\xc3\xa1.no\0"
-"kolobrzeg.pl\0"
-"cci.fr\0fujieda.shizuoka.jp\0"
-"nab\0"
-"info.ro\0"
-"tv.im\0"
-"presidio.museum\0"
-"info.sd\0"
-"berlev\xc3\xa5g.no\0"
-"tv.it\0"
-"britishcolumbia.museum\0\xd1\x80\xd1\x83\xd1\x81\0"
-"ybo.party\0"
-"passagens\0trading\0"
-"date.fukushima.jp\0futaba.fukushima.jp\0tokashiki.okinawa.jp\0iveco\0nba\0"
-"alstom\0barcelona\0"
-"kamikitayama.nara.jp\0"
-"groundhandling.aero\0fujiyoshida.yamanashi.jp\0"
-"hikone.shiga.jp\0"
-"ushistory.museum\0rugby\0"
-"ssl.origin.cdn77-secure.org\0"
-"modern.museum\0energy\0"
-"mihama.chiba.jp\0tsuruoka.yamagata.jp\0"
-"info.pk\0"
-"info.pl\0forgot.her.name\0"
-"suli.hu\0sologne.museum\0inf.ua\0"
-"msd\0"
-"niteroi.br\0"
-"shimoda.shizuoka.jp\0"
-"abo.pa\0info.pr\0"
-"akdn\0"
-"gs.nl.no\0"
-"izunokuni.shizuoka.jp\0"
-"olsztyn.pl\0cc.il.us\0"
-"conf.au\0"
-"bmd.br\0"
-"iwade.wakayama.jp\0"
-"misasa.tottori.jp\0"
-"county.museum\0logoip.com\0"
-"agric.za\0"
-"info.na\0"
-"cc.wi.us\0"
-"belluno.it\0info.mv\0info.nf\0lib.il.us\0"
-"radom.pl\0"
-"info.ni\0mtn\0"
-"journal.aero\0"
-"mtr\0"
-"nec\0"
-"nanyo.yamagata.jp\0"
-"lib.va.us\0"
-"arendal.no\0info.nr\0"
-"hachioji.tokyo.jp\0"
-"machida.tokyo.jp\0tv.na\0"
-"kurogi.fukuoka.jp\0"
-"\xc4\x8d\xc3\xa1hcesuolo.no\0"
-"nadex\0"
-"mn.us\0"
-"trentino-su\xcc\x88""dtirol.it\0glogow.pl\0"
-"li.it\0"
-"net\0u2-local.xnbay.com\0"
-"ac.gov.br\0puglia.it\0gushikami.okinawa.jp\0info.la\0iveland.no\0"
-"new\0"
-"is-a-soxfan.org\0"
-"odo.br\0"
-"kitahiroshima.hokkaido.jp\0finance\0"
-"nfl\0"
-"preservation.museum\0"
-"meiwa.gunma.jp\0"
-"art.pl\0"
-"i.ng\0"
-"cn-north-1.eb.amazonaws.com.cn\0"
-"detroit.museum\0"
-"karelia.su\0"
-"nordkapp.no\0"
-"ichinomiya.aichi.jp\0ngo\0"
-"namsskogan.no\0"
-"massacarrara.it\0suwalki.pl\0"
-"living.museum\0"
-"tozawa.yamagata.jp\0press.se\0"
-"microlight.aero\0"
-"nsw.edu.au\0verona.it\0"
-"nhk\0from-in.com\0eu.org\0"
-"ad.jp\0"
-"club\0"
-"ullensaker.no\0"
-"kisosaki.mie.jp\0"
-"\xe8\xb4\xad\xe7\x89\xa9\0"
-"mw.gov.pl\0"
-"hl.cn\0cesena-forli\xcc\x80.it\0jetzt\0"
-"ishikari.hokkaido.jp\0java\0\xd9\x85\xd9\x88\xd9\x82\xd8\xb9\0serveexchange.com\0"
-"i.ph\0"
-"info.ke\0asmatart.museum\0"
-"seirou.niigata.jp\0scienceandindustry.museum\0wiih.gov.pl\0ac.leg.br\0"
-"udine.it\0info.ki\0stadt.museum\0"
-"\xe5\x9f\xbc\xe7\x8e\x89.jp\0"
-"s3-website-ap-southeast-2.amazonaws.com\0"
-"minamiuonuma.niigata.jp\0blogspot.vn\0"
-"barsy.shop\0"
-"kitagata.gifu.jp\0"
-"art.sn\0"
-"cl.it\0"
-"higashiagatsuma.gunma.jp\0"
-"isernia.it\0tv.sd\0"
-"abruzzo.it\0"
-"roma.museum\0"
-"mihara.hiroshima.jp\0"
-"ntdll.top\0"
-"zone\0"
-"bolzano-altoadige.it\0"
-"k12.dc.us\0"
-"ms.gov.br\0chofu.tokyo.jp\0b\xc3\xa1l\xc3\xa1t.no\0"
-"seki.gifu.jp\0rich\0"
-"lib.as.us\0"
-"ichikai.tochigi.jp\0"
-"asso.eu.org\0"
-"ind.br\0nichinan.miyazaki.jp\0balsfjord.no\0"
-"reliance\0"
-"i.se\0"
-"cri.br\0"
-"naturhistorisches.museum\0grue.no\0"
-"zuerich\0"
-"hakui.ishikawa.jp\0tcp4.me\0"
-"tv.tr\0"
-"siena.it\0kodaira.tokyo.jp\0"
-"joinville.br\0caserta.it\0"
-"kharkiv.ua\0"
-"mie.jp\0tv.tz\0"
-"co.krd\0"
-"s\xc3\xb8r-aurdal.no\0service.gov.uk\0"
-"austin.museum\0"
-"blogspot.re\0"
-"mt.gov.br\0etajima.hiroshima.jp\0"
-"hachijo.tokyo.jp\0konin.pl\0"
-"london.museum\0cloudycluster.net\0"
-"chuo.fukuoka.jp\0"
-"ta.it\0\xd1\x81\xd1\x80\xd0\xb1\0"
-"shobara.hiroshima.jp\0sandnessj\xc3\xb8""en.no\0"
-"press.ma\0"
-"blogspot.ro\0"
-"goiania.br\0"
-"sport.hu\0notogawa.shiga.jp\0"
-"bel.tr\0"
-"haga.tochigi.jp\0blogspot.rs\0"
-"!city.kawasaki.jp\0blogspot.ru\0blogspot.se\0"
-"kmpsp.gov.pl\0from-wv.com\0"
-"blogspot.sg\0"
-"blogspot.si\0mysecuritycamera.net\0"
-"hanamigawa.chiba.jp\0blogspot.sk\0freeddns.us\0"
-"hjartdal.no\0"
-"miyako.fukuoka.jp\0zhytomyr.ua\0ms.leg.br\0"
-"blogspot.sn\0"
-"ueda.nagano.jp\0"
-"iwakura.aichi.jp\0"
-"nishiarita.saga.jp\0stat.no\0tr.eu.org\0ras.ru\0"
-"blogspot.td\0"
-"shiftedit.io\0"
-"hurdal.no\0"
-"matsuura.nagasaki.jp\0"
-"kasahara.gifu.jp\0"
-"amica\0"
-"myeffect.net\0"
-"kazimierz-dolny.pl\0"
-"hidaka.saitama.jp\0"
-"vi.it\0now\0"
-"takahashi.okayama.jp\0fujikawa.yamanashi.jp\0is-a-bookkeeper.com\0"
-"blogspot.tw\0blogspot.ug\0"
-"cc.ut.us\0"
-"game-server.cc\0"
-"sumoto.hyogo.jp\0tsuyama.okayama.jp\0"
-"midori.chiba.jp\0"
-"mt.leg.br\0"
-"trentinosu\xcc\x88""dtirol.it\0"
-"uk.net\0"
-"ind.gt\0heroy.nordland.no\0"
-"blogspot.mr\0"
-"hjelmeland.no\0tokke.no\0"
-"yoro.gifu.jp\0artanddesign.museum\0muncie.museum\0abkhazia.su\0"
-"blogspot.mx\0"
-"castle.museum\0monticello.museum\0soccer\0blogspot.my\0"
-"iamallama.com\0"
-"blogspot.nl\0"
-"lunner.no\0nra\0university\0"
-"pistoia.it\0mombetsu.hokkaido.jp\0ky.us\0blogspot.no\0"
-"hadsel.no\0swiftcover\0"
-"berlin.museum\0obi\0"
-"ashikaga.tochigi.jp\0"
-"ind.in\0"
-"pictet\0"
-"yuasa.wakayama.jp\0earth\0"
-"\xe1\x83\x92\xe1\x83\x94\0"
-"nrw\0"
-"blogspot.pe\0"
-"\xda\x80\xd8\xa7\xd8\xb1\xd8\xaa\0"
-"fauske.no\0serveftp.net\0"
-"likescandy.com\0"
-"international\0syno-ds.de\0"
-"lillehammer.no\0nikon\0"
-"health-carereform.com\0"
-"show.aero\0"
-"matsuzaki.shizuoka.jp\0blogspot.qa\0"
-"kawai.iwate.jp\0otsu.shiga.jp\0"
-"hl.no\0blogspot.pt\0"
-"s3.dualstack.eu-west-1.amazonaws.com\0"
-"shinagawa.tokyo.jp\0"
-"s3-website.ap-south-1.amazonaws.com\0"
+"k12.or.us\0"
+"shibetsu.hokkaido.jp\0shiojiri.nagano.jp\0"
+"surrey.museum\0forsale\0"
+"\xe5\xa4\xa7\xe9\x98\xaa.jp\0"
+"museum.om\0"
+"tm.mc\0"
+"tajimi.gifu.jp\0edunet.tn\0"
+"izumozaki.niigata.jp\0"
+"tm.mg\0"
+"hokkaido.jp\0"
+"bozen.it\0"
+"dyndns-remote.com\0"
+"ri.us\0hotels\0"
+"agdenes.no\0"
+"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd9\x87\0"
+"itakura.gunma.jp\0"
+"dyndns.ws\0"
+"mo.it\0toyoura.hokkaido.jp\0"
+"tm.no\0k12.la.us\0"
+"woodside\0"
+"delaware.museum\0h\xc3\xa1mm\xc3\xa1rfeasta.no\0lamborghini\0reliance\0"
+"cancerresearch\0"
+"is-a-chef.com\0"
+"arkhangelsk.su\0"
+"s\xc3\xa1l\xc3\xa1t.no\0"
+"hiraya.nagano.jp\0"
+"yamato.fukushima.jp\0"
+"webspace.rocks\0"
+"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd8\xa9\0"
+"jio\0u2.xnbay.com\0"
+"gen.mi.us\0"
+"brother\0"
+"cloudns.pw\0"
+"tm.pl\0"
+"town\0"
+"kawanishi.hyogo.jp\0"
+"charter.aero\0vegas\0"
+"k12.id.us\0"
+"sanuki.kagawa.jp\0agematsu.nagano.jp\0haga.tochigi.jp\0"
+"holdings\0"
+"higashi.fukushima.jp\0"
+"nes.akershus.no\0"
+"\xe6\x9b\xb8\xe7\xb1\x8d\0"
+"profesional.bo\0lviv.ua\0homesecuritypc.com\0"
+"dnsup.net\0"
+"vossevangen.no\0"
+"m\xc4\x81ori.nz\0"
+"cc.mo.us\0pgfog.com\0"
+"guge\0"
+"kanonji.kagawa.jp\0"
+"nebraska.museum\0"
+"kawagoe.saitama.jp\0"
+"download\0"
+"southcarolina.museum\0bremanger.no\0"
+"grosseto.it\0\xe0\xa4\x95\xe0\xa5\x89\xe0\xa4\xae\0"
+"evje-og-hornnes.no\0"
+"oyodo.nara.jp\0"
+"hasama.oita.jp\0"
+"chernigov.ua\0"
+"sumoto.hyogo.jp\0"
+"insurance.aero\0tm.ro\0"
+"makurazaki.kagoshima.jp\0"
+"\xd9\x87\xd9\x85\xd8\xb1\xd8\xa7\xd9\x87\0"
+"aomori.aomori.jp\0jll\0"
+"homegoods\0toys\0"
+"tm.se\0cupcake.is\0"
+"seoul.kr\0"
+"neues.museum\0"
+"se.gov.br\0"
+"c.bg\0"
+"upow.gov.pl\0"
+"\xe6\xb7\xa1\xe9\xa9\xac\xe9\x94\xa1\0"
+"tsuruoka.yamagata.jp\0goodyear\0pictet\0"
+"lidl\0"
+"jdevcloud.com\0"
+"jmp\0"
+"s\xc3\xa1lat.no\0"
+"tahara.aichi.jp\0nakagusuku.okinawa.jp\0"
+"steinkjer.no\0"
+"yokoshibahikari.chiba.jp\0nanjo.okinawa.jp\0"
+"press.museum\0"
+"jnj\0"
+"lpages.co\0"
+"higashine.yamagata.jp\0"
+"illustration.museum\0"
+"mragowo.pl\0"
+"bz.it\0mmafan.biz\0"
+"amusement.aero\0s3.dualstack.ca-central-1.amazonaws.com\0cya.gg\0"
+"villas\0"
+"hyllestad.no\0cc.wa.us\0life\0"
+"tatsuno.hyogo.jp\0maori.nz\0"
+"kwp.gov.pl\0"
+"uto.kumamoto.jp\0"
+"dyr\xc3\xb8y.no\0"
+"atsuma.hokkaido.jp\0"
+"nsw.au\0inder\xc3\xb8y.no\0cc.ga.us\0"
+"sabae.fukui.jp\0design\0"
+"sasebo.nagasaki.jp\0jot\0"
+"gucci\0*.alces.network\0"
+"kannami.shizuoka.jp\0"
+"joy\0"
+"nanao.ishikawa.jp\0akagi.shimane.jp\0*.bzz.dapps.earth\0"
+"iraq.museum\0esurance\0"
+"pc.it\0"
+"guam.gu\0"
+"cust.prod.thingdust.io\0"
+"horonobe.hokkaido.jp\0"
+"ibestad.no\0"
+"abc.br\0novara.it\0nichinan.tottori.jp\0fujikawaguchiko.yamanashi.jp\0"
+"wales.museum\0"
+"shikokuchuo.ehime.jp\0help\0"
+"textile.museum\0c66.me\0"
+"\xd1\x83\xd0\xba\xd1\x80\0"
+"dyndns-free.com\0"
+"uki.kumamoto.jp\0"
+"anthropology.museum\0botanicalgarden.museum\0raholt.no\0gjemnes.no\0"
+"us-4.evennode.com\0"
+"deloitte\0"
+"mydissent.net\0"
+"kustanai.ru\0"
+"veg\xc3\xa5rshei.no\0leitungsen.de\0"
+"valleedaoste.it\0"
+"settlers.museum\0sa-east-1.elasticbeanstalk.com\0"
+"sa.gov.pl\0clubmed\0"
+"paleo.museum\0"
+"rnrt.tn\0"
+"kustanai.su\0"
+"kyiv.ua\0"
+"control.aero\0tm.za\0data\0lundbeck\0dattolocal.com\0"
+"chiba.jp\0"
+"rollag.no\0date\0"
+"plus\0"
"maibara.shiga.jp\0"
-"control.aero\0"
-"ascoli-piceno.it\0"
-"*.sapporo.jp\0"
+"trani-andria-barletta.it\0epson\0"
+"ruovat.no\0mo.us\0"
+"ueda.nagano.jp\0"
+"like\0"
+"birdart.museum\0"
+"gateway.museum\0pagefrontapp.com\0"
+"higashihiroshima.hiroshima.jp\0"
+"fribourg.museum\0etnedal.no\0"
+"port.fr\0"
+"union.aero\0"
+"aju.br\0"
+"higashichichibu.saitama.jp\0"
+"furano.hokkaido.jp\0"
+"yamanouchi.nagano.jp\0\xe0\xaa\xad\xe0\xaa\xbe\xe0\xaa\xb0\xe0\xaa\xa4\0"
+"stange.no\0us-3.evennode.com\0"
+"toda.saitama.jp\0"
+"newport.museum\0locus\0"
+"nose.osaka.jp\0"
+"north.museum\0"
+"kfh\0"
+"here\0"
+"bukhara.su\0ras.ru\0"
+"nishinoomote.kagoshima.jp\0"
+"c.la\0"
+"oe.yamagata.jp\0"
+"limo\0*.s5y.io\0"
+"rocher\0"
+"godo.gifu.jp\0shikama.miyagi.jp\0pc.pl\0"
+"jur.pro\0"
+"miasa.nagano.jp\0"
+"n\xc3\xb8tter\xc3\xb8y.no\0"
+"en.it\0"
"design.aero\0"
-"ntt\0"
-"upow.gov.pl\0"
-"ichihara.chiba.jp\0ind.kw\0blogspot.is\0"
-"blogspot.it\0"
-"shimizu.hokkaido.jp\0uslivinghistory.museum\0"
-"bedzin.pl\0webhop.info\0"
-"k12.ms.us\0k12.nc.us\0"
-"lib.ks.us\0news\0"
-"politie\0"
-"codes\0"
-"blogspot.jp\0"
-"g.bg\0gripe\0"
-"off\0"
-"philately.museum\0dnsfor.me\0"
-"ochi.kochi.jp\0democrat\0winners\0"
-"bg.it\0"
-"broke-it.net\0"
-"cc.ar.us\0next\0"
-"bale.museum\0"
-"\xc3\xb8yer.no\0blogspot.kr\0"
-"ot.it\0pd.it\0gitlab.io\0"
-"godo.gifu.jp\0iwanuma.miyagi.jp\0hangout\0"
-"toon.ehime.jp\0"
-"blogspot.li\0"
-"shinshinotsu.hokkaido.jp\0"
-"sakaiminato.tottori.jp\0"
-"omachi.nagano.jp\0"
-"hair\0"
-"al.gov.br\0toyokawa.aichi.jp\0"
-"blogspot.lt\0blogspot.md\0"
-"lib.ok.us\0blogspot.lu\0"
-"turin.it\0"
-"cri.nz\0blogspot.mk\0"
-"ragusa.it\0"
-"alto-adige.it\0"
-"info.zm\0restaurant\0"
-"nyc\0"
-"niigata.niigata.jp\0"
-"gallo\0filegear.me\0"
-"qld.edu.au\0hobol.no\0"
-"knx-server.net\0"
-"yamaga.kumamoto.jp\0"
-"epilepsy.museum\0blogspot.fi\0"
-"kherson.ua\0"
-"nishimera.miyazaki.jp\0"
-"blackfriday\0"
-"usantiques.museum\0"
-"umb.it\0aogashima.tokyo.jp\0"
-"media.hu\0rawa-maz.pl\0blogspot.fr\0"
-"geek.nz\0"
-"nom.ad\0trentin-sudtirol.it\0"
-"uhren.museum\0bykle.no\0nom.ae\0customer.speedpartner.de\0"
+"takinoue.hokkaido.jp\0shinjo.yamagata.jp\0"
+"barcelona.museum\0guru\0"
+"bas.it\0kita.kyoto.jp\0"
+"link\0"
+"nyny.museum\0"
+"wa.us\0"
+"show.aero\0usantiques.museum\0"
+"asago.hyogo.jp\0wiih.gov.pl\0"
+"heimatunduhren.museum\0"
+"ikoma.nara.jp\0"
+"ga.us\0"
+"gyeongbuk.kr\0ybo.faith\0"
+"kia\0"
+"rg.it\0shizukuishi.iwate.jp\0"
+"shobara.hiroshima.jp\0"
+"uber.space\0"
+"hb.cn\0store.nf\0"
+"bushey.museum\0ashgabad.su\0"
+"bg.it\0mimata.miyazaki.jp\0"
+"kim\0promo\0ch.eu.org\0"
+"matsubara.osaka.jp\0"
+"us-2.evennode.com\0"
+"logistics.aero\0windows\0"
+"minano.saitama.jp\0"
+"salem.museum\0"
+"cremona.it\0higashiyama.kyoto.jp\0"
+"watch-and-clock.museum\0"
+"shibecha.hokkaido.jp\0"
+"funagata.yamagata.jp\0"
+"motosu.gifu.jp\0kuroiso.tochigi.jp\0"
+"yoshida.shizuoka.jp\0"
+"paris.eu.org\0"
+"davvenj\xc3\xa1rga.no\0amica\0"
+"western.museum\0"
+"environmentalconservation.museum\0schule\0own.pm\0"
+"noto.ishikawa.jp\0iwatsuki.saitama.jp\0"
+"info.gu\0"
+"nom.ad\0yuza.yamagata.jp\0"
+"nom.ae\0"
"nom.af\0"
-"nom.ag\0kita.tokyo.jp\0"
-"nom.ai\0"
-"k12.sc.us\0"
-"nom.al\0"
-"aeroclub.aero\0"
-"biz.bb\0history.museum\0"
-"takino.hyogo.jp\0blogspot.gr\0"
-"biz.at\0"
-"altoadige.it\0"
-"author.aero\0rocks\0"
-"freesite.host\0"
-"ab.ca\0malbork.pl\0"
-"biz.az\0grandrapids.museum\0"
-"al.leg.br\0"
-"blogspot.hk\0"
-"s3-website-ap-northeast-1.amazonaws.com\0"
-"shingu.hyogo.jp\0"
-"tt.im\0space\0"
-"ally\0"
-"webcam\0blogspot.hr\0"
-"vi.us\0"
-"kaminokawa.tochigi.jp\0"
-"blogspot.hu\0blogspot.ie\0"
-"ud.it\0homeoffice.gov.uk\0"
-"yonago.tottori.jp\0mayfirst.info\0nom.cl\0"
-"yukuhashi.fukuoka.jp\0"
-"kitahata.saga.jp\0vennesla.no\0blogspot.in\0"
-"nom.co\0\xe6\xbe\xb3\xe9\x96\x80\0tiffany\0"
-"shimokawa.hokkaido.jp\0blogspot.ba\0"
-"homebuilt.aero\0"
-"blogspot.be\0"
-"blogspot.bg\0"
-"biz.cy\0"
-"bydgoszcz.pl\0"
-"unazuki.toyama.jp\0ind.tn\0biz.dk\0blogspot.bj\0"
-"ashgabad.su\0"
-"sakata.yamagata.jp\0"
-"plumbing\0"
-"blogspot.ca\0"
-"kushima.miyazaki.jp\0one\0"
-"ong\0"
-"tmp.br\0blogspot.cf\0"
-"zakopane.pl\0"
-"rl.no\0s3-ap-northeast-2.amazonaws.com\0blogspot.ch\0"
-"soni.nara.jp\0onl\0"
-"amsterdam.museum\0archaeological.museum\0edeka\0jdevcloud.com\0"
-"blogspot.cl\0"
-"conf.lv\0"
-"hongo.hiroshima.jp\0"
-"maryland.museum\0juegos\0"
-"nom.es\0biz.et\0for-some.biz\0"
-"blogspot.de\0"
-"blogspot.cv\0"
-"*.bd\0tele.amune.org\0"
-"oi.kanagawa.jp\0\xe4\xb8\xad\xe4\xbf\xa1\0blogspot.cz\0"
-"blogspot.dk\0"
-"ooo\0"
-"campinas.br\0miniserver.com\0"
-"lodingen.no\0"
-"valleeaoste.it\0mitake.gifu.jp\0"
-"nom.fr\0mizunami.gifu.jp\0kristiansund.no\0"
-"gs.bu.no\0broker\0freetls.fastly.net\0nom.gd\0"
-"lego\0nom.ge\0"
-"bihoro.hokkaido.jp\0gub.uy\0"
-"tobe.ehime.jp\0"
-"bozen-sudtirol.it\0"
+"nom.ag\0"
+"isumi.chiba.jp\0shirakawa.gifu.jp\0witd.gov.pl\0"
+"square.museum\0nom.ai\0"
+"astronomy.museum\0vinnytsia.ua\0"
+"kasahara.gifu.jp\0nom.al\0"
+"funabashi.chiba.jp\0"
+"\xe4\xb8\x96\xe7\x95\x8c\0"
+"nature.museum\0bo.nordland.no\0"
+"info.ht\0ono.fukui.jp\0"
+"info.hu\0tank.museum\0"
+"bloomberg\0"
+"kofu.yamanashi.jp\0co.education\0"
+"sp.leg.br\0"
+"freiburg.museum\0"
+"machida.tokyo.jp\0"
+"obu.aichi.jp\0gifu.gifu.jp\0ashikaga.tochigi.jp\0"
+"info.et\0"
+"arte.bo\0homeftp.org\0"
+"us-1.evennode.com\0"
+"shika.ishikawa.jp\0"
+"c.se\0"
+"erotica.hu\0"
+"nom.cl\0"
+"is-very-nice.org\0"
+"tagawa.fukuoka.jp\0shishikui.tokushima.jp\0"
+"air-traffic-control.aero\0nom.co\0from-ne.com\0"
+"colonialwilliamsburg.museum\0"
+"homes\0"
+"bifuka.hokkaido.jp\0ogawa.saitama.jp\0"
+"yamashina.kyoto.jp\0"
+"matsushima.miyagi.jp\0kodaira.tokyo.jp\0"
+"imageandsound.museum\0"
+"tado.mie.jp\0is-a-chef.net\0"
+"live\0\xe5\x95\x86\xe6\xa0\x87\0murmansk.su\0"
+"fr\xc3\xa6na.no\0nore-og-uvdal.no\0"
+"kasumigaura.ibaraki.jp\0"
+"niepce.museum\0s\xc3\xb8gne.no\0"
+"gr.it\0"
+"info.cx\0"
+"room\0"
+"nexus\0us-east-1.amazonaws.com\0"
+"t.bg\0is-found.org\0forumz.info\0"
+"ivanovo.su\0"
+"campinas.br\0gr.jp\0"
+"info.ec\0"
+"nom.es\0ulm.museum\0baby\0"
+"kpn\0"
+"barsy.me\0serveexchange.com\0homelink.one\0"
+"game.tw\0"
+"voss.no\0"
+"store.ve\0applinzi.com\0"
+"info.bb\0frosinone.it\0"
+"moscow.museum\0"
+"nom.fr\0info.at\0"
+"info.au\0at.eu.org\0"
+"nom.gd\0"
+"nom.ge\0"
+"!city.sendai.jp\0"
+"nannestad.no\0"
+"info.az\0social\0"
+"tsuchiura.ibaraki.jp\0krd\0lat\0"
"nom.gl\0"
-"trentino-s-tirol.it\0minami.tokushima.jp\0"
-"*.ck\0"
-"uk.eu.org\0"
-"yaese.okinawa.jp\0nom.gt\0"
-"iitate.fukushima.jp\0"
-"directory\0"
-"lg.jp\0kimobetsu.hokkaido.jp\0media.pl\0"
-"cdn77-ssl.net\0"
-"tatamotors\0"
-"bryansk.su\0nom.hn\0"
-"s3.eu-west-3.amazonaws.com\0"
-"monza-brianza.it\0"
-"biz.id\0shouji\0"
-"org\0"
-"urawa.saitama.jp\0"
-"minamiaiki.nagano.jp\0pay\0"
-"e12.ve\0games\0"
-"ppg.br\0higashisumiyoshi.osaka.jp\0"
-"nom.im\0"
-"\xed\x95\x9c\xea\xb5\xad\0"
-"fussa.tokyo.jp\0"
-"*.er\0"
-"no.it\0"
-"\xe6\xbe\xb3\xe9\x97\xa8\0barsy.site\0"
-"cc.nj.us\0"
-"*.fj\0"
-"*.fk\0"
-"flatanger.no\0f\xc3\xb8rde.no\0"
-"gz.cn\0"
-"labour.museum\0skierva.no\0"
-"haus\0"
-"blogspot.ae\0nom.ke\0"
-"\xc3\xb8ystre-slidre.no\0"
-"biz.ki\0"
-"nishiazai.shiga.jp\0cranbrook.museum\0"
-"pro.az\0"
-"z.bg\0celtic.museum\0blogspot.al\0"
-"nom.km\0blogspot.am\0"
-"virginia.museum\0"
-"amex\0"
-"ott\0rodeo\0"
-"airline.aero\0pro.br\0"
-"bz.it\0"
-"fukudomi.saga.jp\0tendo.yamagata.jp\0"
-"komaki.aichi.jp\0"
-"indiana.museum\0itau\0"
-"b\xc3\xa5tsfjord.no\0nom.li\0"
-"rockart.museum\0ybo.trade\0"
-"citadel\0"
-"m\xc3\xa1tta-v\xc3\xa1rjjat.no\0privatizehealthinsurance.net\0"
-"pet\0"
-"juif.museum\0football\0"
-"viterbo.it\0cc.pr.us\0"
-"choyo.kumamoto.jp\0"
-"krodsherad.no\0ovh\0"
-"szex.hu\0"
-"morioka.iwate.jp\0nom.mg\0s3.dualstack.us-east-1.amazonaws.com\0"
-"pro.cy\0gets-it.net\0"
-"tynset.no\0s3-website-us-east-1.amazonaws.com\0nom.mk\0"
-"gsm.pl\0nym.by\0"
-"frankfurt.museum\0nym.bz\0"
-"g.se\0pics\0"
-"group.aero\0epost\0"
-"stcgroup\0"
-"nom.nc\0"
-"pro.ec\0"
-"biz.mv\0\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x8b\xe0\xa4\xa4\0"
-"biz.mw\0"
-"goshiki.hyogo.jp\0poker\0"
-"biz.ni\0lamer\0"
-"nom.ni\0"
-"sebastopol.ua\0"
-"yamaguchi.jp\0"
-"friuliveneziagiulia.it\0*.jm\0"
-"norfolk.museum\0biz.nr\0phd\0"
-"historisches.museum\0"
-"nom.nu\0"
-"redstone\0"
-"so.it\0kumenan.okayama.jp\0"
-"takamori.nagano.jp\0funagata.yamagata.jp\0"
-"natural.bo\0campobasso.it\0\xd1\x83\xd0\xba\xd1\x80\0"
-"ojiya.niigata.jp\0*.kh\0"
-"hirosaki.aomori.jp\0waw.pl\0"
-"nagato.yamaguchi.jp\0nom.pa\0americanexpress\0pid\0"
-"kr\xc3\xa5""anghke.no\0nom.pe\0agakhan\0"
-"giving\0"
-"tsuchiura.ibaraki.jp\0ina.saitama.jp\0"
-"club.aero\0"
-"historisch.museum\0biz.pk\0"
-"biz.pl\0pin\0"
-"pb.ao\0smola.no\0nom.pl\0"
-"matsuyama.ehime.jp\0ikeda.fukui.jp\0mydatto.net\0"
-"ikeda.hokkaido.jp\0"
-"university.museum\0user.party.eus\0"
-"or.at\0biz.pr\0nom.qa\0"
-"omitama.ibaraki.jp\0kanegasaki.iwate.jp\0"
-"higashichichibu.saitama.jp\0"
-"or.bi\0"
-"nom.pw\0"
-"kartuzy.pl\0dynamic-dns.info\0"
-"cc.gu.us\0"
-"lincoln.museum\0veg\xc3\xa5rshei.no\0"
-"sasebo.nagasaki.jp\0mysecuritycamera.org\0bloxcms.com\0"
-"achi.nagano.jp\0"
-"*.mm\0"
-"pro.ht\0sos.pl\0nom.re\0"
-"or.ci\0shimane.shimane.jp\0nym.gr\0"
-"nishiaizu.fukushima.jp\0tashkent.su\0"
-"lg.ua\0"
-"institute\0"
-"64-b.it\0nym.gy\0"
-"or.cr\0nom.ro\0"
-"verbania.it\0cloudaccess.net\0"
-"*.np\0travel\0nom.rs\0"
-"nym.ie\0nom.si\0"
-"wajima.ishikawa.jp\0"
-"mayfirst.org\0"
-"research.aero\0spdns.org\0"
-"nuoro.it\0pavia.it\0cymru\0"
-"toscana.it\0"
-"skjerv\xc3\xb8y.no\0"
-"yoshida.shizuoka.jp\0osaka\0\xd8\xa7\xd8\xa8\xd9\x88\xd8\xb8\xd8\xa8\xd9\x8a\0nom.st\0"
-"skien.no\0"
-"indigena.bo\0"
-"erotika.hu\0biz.tj\0"
-"*.pg\0nom.tj\0"
-"from.hr\0ikoma.nara.jp\0"
-"ulsan.kr\0"
-"nom.tm\0"
-"sabae.fukui.jp\0"
-"sci.eg\0pnc\0biz.ua\0"
-"biz.tr\0"
-"ozu.kumamoto.jp\0fujikawaguchiko.yamanashi.jp\0biz.tt\0"
-"chikushino.fukuoka.jp\0"
-"railroad.museum\0"
-"nom.ug\0"
-"nishinoshima.shimane.jp\0setagaya.tokyo.jp\0"
-"geisei.kochi.jp\0"
-"katsuyama.fukui.jp\0"
-"pug.it\0"
-"historicalsociety.museum\0"
-"natura\0"
-"tanagura.fukushima.jp\0nom.vc\0"
-"surgeonshall.museum\0bjarkoy.no\0nym.la\0virtual-user.de\0"
-"kameyama.mie.jp\0ryokami.saitama.jp\0"
-"grocery\0youtube\0nym.lc\0nom.vg\0"
-"nom.uy\0"
-"cc.me.us\0"
-"biz.vn\0dynns.com\0nym.li\0"
-"nym.kz\0"
-"tatar\0"
-"kasaoka.okayama.jp\0pro.na\0fage\0"
-"dyndns-wiki.com\0"
-"gop.pk\0"
-"pro.mv\0"
-"nym.lt\0"
-"kaho.fukuoka.jp\0nym.lu\0nym.me\0"
-"wa.edu.au\0ipiranga\0"
-"e.bg\0"
-"monza.it\0"
-"or.id\0dielddanuorri.no\0"
-"rel.ht\0iijima.nagano.jp\0nym.mn\0"
-"minamitane.kagoshima.jp\0ping\0"
-"\xd8\xa8\xda\xbe\xd8\xa7\xd8\xb1\xd8\xaa\0lasalle\0"
-"pink\0"
-"samnanger.no\0"
-"oldnavy\0nym.mx\0"
-"inazawa.aichi.jp\0"
-"bozen.it\0pro.om\0"
-"losangeles.museum\0"
-"or.it\0"
-"nango.fukushima.jp\0"
-"gs.tm.no\0"
-"americanantiques.museum\0wzmiuw.gov.pl\0"
-"certification.aero\0aki.kochi.jp\0"
-"fail\0"
-"pro\0"
-"or.jp\0"
-"nym.nz\0"
-"k12.pa.us\0\xe0\xb6\xbd\xe0\xb6\x82\xe0\xb6\x9a\xe0\xb7\x8f\0"
-"*.landing.myjino.ru\0"
-"nom.za\0"
-"or.ke\0pru\0"
-"pro.pr\0"
-"cool\0is-a-doctor.com\0half.host\0"
-"satx.museum\0"
-"nym.pe\0"
-"coop\0ostrowiec.pl\0fedex\0"
-"biz.zm\0"
-"naval.museum\0balashov.su\0"
-"or.kr\0stjordal.no\0"
-"is-a-socialist.com\0"
-"chippubetsu.hokkaido.jp\0"
-"minamimaki.nagano.jp\0"
-"historichouses.museum\0vista\0"
-"nym.pt\0"
-"kokonoe.oita.jp\0ringerike.no\0backplaneapp.io\0"
-"medio-campidano.it\0"
-"nogata.fukuoka.jp\0"
-"embetsu.hokkaido.jp\0pub\0"
-"dyndns1.de\0"
-"\xe0\xaa\xad\xe0\xaa\xbe\xe0\xaa\xb0\xe0\xaa\xa4\0a.prod.fastly.net\0"
-"agematsu.nagano.jp\0iizuna.nagano.jp\0"
-"takayama.gunma.jp\0paderborn.museum\0"
-"ichiba.tokushima.jp\0myftp.org\0"
-"toyako.hokkaido.jp\0"
-"doctor\0"
-"z.se\0"
-"homedns.org\0synology.me\0"
-"or.na\0"
-"tec.ve\0"
-"ulm.museum\0goip.de\0"
-"or.mu\0localhistory.museum\0playstation\0"
-"nym.ro\0"
-"hirokawa.fukuoka.jp\0"
-"ge.it\0*.ye\0"
-"bentley\0"
-"fhv.se\0\xe6\x94\xbf\xe5\x8a\xa1\0"
-"higashimatsuyama.saitama.jp\0nym.sk\0"
-"urasoe.okinawa.jp\0pwc\0"
-"ddnslive.com\0"
-"iiyama.nagano.jp\0"
-"tr.it\0shimotsuma.ibaraki.jp\0"
-"kozaki.chiba.jp\0pro.tt\0"
-"trentinsud-tirol.it\0"
-"nym.su\0"
-"harima.hyogo.jp\0serveftp.org\0cloud.fedoraproject.org\0"
-"nym.sx\0"
-"nm.cn\0"
-"ogaki.gifu.jp\0\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0"
-"\xc3\xa5lg\xc3\xa5rd.no\0fans\0"
-"ddr.museum\0is-slick.com\0"
-"froland.no\0sochi.su\0"
-"fukuchiyama.kyoto.jp\0"
-"rel.pl\0"
-"nym.tw\0"
-"trentino-a-adige.it\0moka.tochigi.jp\0"
-"eco.br\0pro.vn\0"
-"im.it\0"
-"owariasahi.aichi.jp\0jeep\0jp.net\0operaunite.com\0"
-"or.pw\0"
-"suisse.museum\0"
-"r\xc3\xb8""d\xc3\xb8y.no\0markets\0"
-"blog.bo\0"
-"blog.br\0lundbeck\0"
-"servequake.com\0"
-"yusui.kagoshima.jp\0k12.in.us\0\xd8\xa7\xd9\x84\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x86\0"
-"gen.in\0"
-"chanel\0"
-"dreamhosters.com\0"
-"mizuho.tokyo.jp\0os.hordaland.no\0freeddns.org\0"
-"k12.wy.us\0"
-"jondal.no\0alipay\0"
-"ine.kyoto.jp\0"
-"hamatama.saga.jp\0"
-"kamiamakusa.kumamoto.jp\0rackmaze.com\0"
-"gr.com\0"
-"tonami.toyama.jp\0kraanghke.no\0"
-"laakesvuemie.no\0"
-"hokkaido.jp\0"
-"le.it\0farm\0lgbt\0vision\0"
-"kanazawa.ishikawa.jp\0tr.no\0"
-"est-le-patron.com\0for-our.info\0"
-"targi.pl\0"
-"or.th\0"
-"yawata.kyoto.jp\0nagawa.nagano.jp\0"
-"wajiki.tokushima.jp\0"
-"conference.aero\0"
-"fast\0"
-"shonai.fukuoka.jp\0theworkpc.com\0"
-"or.ug\0"
+"info.bo\0law\0applicationcloud.io\0"
+"nankoku.kochi.jp\0"
"com.ac\0"
-"aparecida.br\0"
-"or.tz\0"
-"com.af\0"
+"ebetsu.hokkaido.jp\0*.elb.amazonaws.com.cn\0"
+"com.af\0nom.gt\0"
"com.ag\0"
-"jeonbuk.kr\0"
"com.ai\0"
-"heguri.nara.jp\0tochigi.tochigi.jp\0imageandsound.museum\0"
-"balsan.it\0"
-"com.al\0yamagata.jp\0andebu.no\0czeladz.pl\0"
-"or.us\0ninja\0"
-"com.ba\0nabari.mie.jp\0"
-"com.ar\0com.bb\0leirvik.no\0"
-"schoenbrunn.museum\0"
-"yamazoe.nara.jp\0stranda.no\0"
-"com.au\0cc.nh.us\0"
-"com.aw\0"
+"com.al\0aparecida.br\0"
+"ddnslive.com\0"
+"chippubetsu.hokkaido.jp\0"
+"info.co\0"
+"monash\0nom.hn\0"
+"com.ba\0"
+"com.ar\0com.bb\0art.br\0pesaro-urbino.it\0"
+"r\xc3\xa1hkker\xc3\xa1vju.no\0hisamitsu\0"
+"pt.it\0"
+"com.au\0"
+"kashima.saga.jp\0"
+"com.aw\0tours\0"
"com.bh\0"
-"com.bi\0suzuki\0"
-"com.az\0minamiashigara.kanagawa.jp\0"
-"gx.cn\0"
-"kumakogen.ehime.jp\0"
-"com.bm\0kochi.jp\0"
-"com.bn\0cust.disrec.thingdust.io\0"
-"com.bo\0shingo.aomori.jp\0"
+"com.bi\0"
+"com.az\0"
+"s3.dualstack.eu-west-1.amazonaws.com\0"
+"fukushima.hokkaido.jp\0tokorozawa.saitama.jp\0"
+"com.bm\0oregontrail.museum\0read-books.org\0"
+"com.bn\0"
+"com.bo\0nom.im\0"
+"ogano.saitama.jp\0"
"com.br\0"
-"com.bs\0bauern.museum\0"
+"com.bs\0"
"com.bt\0"
-"x.bg\0isla.pr\0map.fastly.net\0"
+"software.aero\0pubol.museum\0"
+"abira.hokkaido.jp\0"
"com.by\0com.ci\0"
-"com.bz\0"
-"gj\xc3\xb8vik.no\0gen.nz\0"
-"com.cm\0ee.eu.org\0"
-"com.cn\0"
-"com.co\0ch.it\0saku.nagano.jp\0s3.dualstack.sa-east-1.amazonaws.com\0"
-"association.aero\0"
-"philadelphia.museum\0"
-"safety\0"
-"com.cu\0chigasaki.kanagawa.jp\0com.de\0virtueeldomein.nl\0"
-"com.cw\0sakahogi.gifu.jp\0"
-"com.cy\0selfip.net\0"
-"pu.it\0"
-"keymachine.de\0"
-"hatogaya.saitama.jp\0jambyl.su\0"
-"com.dm\0massa-carrara.it\0"
-"agrinet.tn\0"
-"com.do\0dovre.no\0"
-"isumi.chiba.jp\0lifeinsurance\0"
-"lesja.no\0"
-"com.ec\0kamishihoro.hokkaido.jp\0"
-"com.ee\0hakodate.hokkaido.jp\0"
-"nico\0"
-"com.eg\0"
-"com.dz\0e.se\0dattolocal.com\0"
-"hisamitsu\0"
-"\xe7\xb5\x84\xe7\xb9\x94.tw\0"
-"messina.it\0"
-"com.es\0lancome\0"
-"com.et\0vestre-toten.no\0"
-"yuzawa.niigata.jp\0"
-"warszawa.pl\0"
-"shimane.jp\0"
-"murayama.yamagata.jp\0"
-"championship.aero\0"
-"meloy.no\0"
-"kusatsu.shiga.jp\0"
-"hemnes.no\0nord-fron.no\0"
-"pvt.k12.ma.us\0isa-geek.org\0"
-"botanicgarden.museum\0"
+"com.bz\0ad.jp\0flickr\0"
+"lds\0"
+"com.cm\0plc.co.im\0"
+"com.cn\0traniandriabarletta.it\0"
+"pueblo.bo\0com.co\0art.do\0"
+"\xe5\x85\xac\xe5\x8f\xb8.cn\0"
+"tohnosho.chiba.jp\0kawanabe.kagoshima.jp\0nakagawa.nagano.jp\0"
+"politica.bo\0"
+"sh.cn\0"
+"com.cu\0tr\xc3\xb8gstad.no\0com.de\0"
+"sanagochi.tokushima.jp\0"
+"com.cw\0karasjok.no\0nom.ke\0"
+"com.cy\0tolga.no\0store.ro\0"
+"art.dz\0lom.it\0mantova.it\0"
+"nakadomari.aomori.jp\0"
+"com.dm\0\xe5\x85\xac\xe5\x8f\xb8.hk\0"
+"com.do\0nom.km\0"
+"\xe6\xbb\x8b\xe8\xb3\x80.jp\0weather\0"
+"koka.shiga.jp\0"
+"com.ec\0bashkiria.ru\0"
+"com.ee\0"
+"com.eg\0settlement.museum\0herokussl.com\0"
+"gets-it.net\0"
+"works.aero\0"
+"com.dz\0"
+"nom.li\0"
+"omachi.saga.jp\0"
+"bearalvahki.no\0"
+"\xe7\xa7\x8b\xe7\x94\xb0.jp\0store.st\0"
+"mandal.no\0north-kazakhstan.su\0obninsk.su\0"
+"com.es\0bashkiria.su\0"
+"com.et\0"
+"nom.mg\0mein-iserv.de\0"
+"choyo.kumamoto.jp\0"
+"music.museum\0nom.mk\0"
"com.fr\0"
-"com.ge\0"
-"com.gh\0kaszuby.pl\0"
-"com.gi\0lib.co.us\0"
-"sld.do\0com.gl\0"
-"com.gn\0naoshima.kagawa.jp\0"
-"com.gp\0tsuruga.fukui.jp\0likes-pie.com\0"
-"hdfc\0"
-"med.br\0com.gr\0furniture.museum\0"
-"oyodo.nara.jp\0takaishi.osaka.jp\0woodside\0"
-"com.gt\0"
-"com.gu\0"
-"\xe4\xb8\x96\xe7\x95\x8c\0"
-"nakama.fukuoka.jp\0gangwon.kr\0"
-"com.gy\0aremark.no\0knightpoint.systems\0"
-"com.hk\0"
-"kashihara.nara.jp\0"
-"rennebu.no\0"
-"bc.ca\0com.hn\0hiji.oita.jp\0"
-"red\0"
-"uppo.gov.pl\0"
-"nishi.osaka.jp\0"
-"com.hr\0himeji.hyogo.jp\0adult\0"
-"gen.tr\0"
-"com.ht\0"
-"oksnes.no\0"
-"kyowa.akita.jp\0"
-"wodzislaw.pl\0ren\0"
-"nrw.museum\0stuttgart.museum\0"
-"ve.it\0fuefuki.yamanashi.jp\0scotland.museum\0"
-"com.im\0goto.nagasaki.jp\0"
-"qvc\0"
-"com.io\0"
-"com.iq\0honefoss.no\0"
-"med.ec\0com.is\0"
-"fnd.br\0med.ee\0arkhangelsk.su\0"
-"ass.km\0"
-"ardal.no\0vote\0"
-"is-a-guru.com\0"
-"vaporcloud.io\0"
-"lib.tx.us\0"
-"movistar\0"
-"com.jo\0country\0"
-"gives\0"
-"kamogawa.chiba.jp\0yokawa.hyogo.jp\0slask.pl\0voto\0"
-"tokigawa.saitama.jp\0"
-"yatsuka.shimane.jp\0erni\0tuxfamily.org\0"
-"sakaki.nagano.jp\0com.kg\0is-a-musician.com\0"
-"freeboxos.com\0"
+"anjo.aichi.jp\0"
+"com.ge\0nom.nc\0"
+"palmas.br\0\xd8\xa7\xd8\xb1\xd8\xa7\xd9\x85\xd9\x83\xd9\x88\0"
+"com.gh\0"
+"economia.bo\0com.gi\0"
+"nom.ni\0"
+"com.gl\0kawara.fukuoka.jp\0tenri.nara.jp\0"
+"barsy.uk\0"
+"com.gn\0email\0"
+"com.gp\0"
+"delta\0"
+"com.gr\0nagara.chiba.jp\0florist\0"
+"dovre.no\0porsanger.no\0s3-us-gov-west-1.amazonaws.com\0"
+"com.gt\0art.ht\0"
+"com.gu\0from-de.com\0"
+"towada.aomori.jp\0takata.fukuoka.jp\0"
+"nom.nu\0"
+"chambagri.fr\0"
+"com.gy\0ap-northeast-1.elasticbeanstalk.com\0"
+"iwanuma.miyagi.jp\0"
+"catering.aero\0com.hk\0roros.no\0"
+"watch\0"
+"vladimir.su\0"
+"com.hn\0semboku.akita.jp\0hanamigawa.chiba.jp\0chiyoda.gunma.jp\0kuwana.mie.jp\0"
+"cinema.museum\0"
+"com.hr\0"
+"nom.pa\0lug.org.uk\0"
+"com.ht\0higashishirakawa.gifu.jp\0"
+"lom.no\0vestvagoy.no\0"
+"ce.gov.br\0"
+"a.bg\0romskog.no\0nom.pe\0"
+"is-into-games.com\0"
+"inatsuki.fukuoka.jp\0"
+"tra.kp\0"
+"com.im\0abudhabi\0"
+"kudoyama.wakayama.jp\0nom.pl\0"
+"com.io\0aejrie.no\0davvenjarga.no\0"
+"nango.fukushima.jp\0band\0forex\0"
+"com.iq\0nationalfirearms.museum\0"
+"com.is\0bergen.no\0nom.qa\0"
+"bank\0"
+"kurashiki.okayama.jp\0musashino.tokyo.jp\0hotel.tz\0"
+"botany.museum\0newmexico.museum\0nom.pw\0"
+"llc\0university\0"
+"higashinaruse.akita.jp\0fujimi.saitama.jp\0"
+"dclk\0"
+"bunkyo.tokyo.jp\0office-on-the.net\0"
+"com.jo\0mycd.eu\0"
+"kawatana.nagasaki.jp\0satosho.okayama.jp\0kawaguchi.saitama.jp\0"
+"honda\0barrel-of-knowledge.info\0"
+"ch.it\0kanazawa.ishikawa.jp\0"
+"com.kg\0matta-varjjat.no\0nom.re\0mckinsey\0ciscofreak.com\0"
+"*.bd\0higashiagatsuma.gunma.jp\0"
"com.ki\0"
-"sciencehistory.museum\0\xe3\x82\xb3\xe3\x83\xa0\0"
-"naamesjevuemie.no\0"
-"mitou.yamaguchi.jp\0com.km\0sorreisa.no\0"
-"miami\0"
-"masaki.ehime.jp\0com.kp\0"
-"com.la\0"
+"com.km\0schoenbrunn.museum\0vladimir.ru\0ybo.review\0"
+"ichinomiya.aichi.jp\0numata.hokkaido.jp\0"
+"lans.museum\0"
+"mitake.gifu.jp\0com.kp\0"
+"com.la\0nom.ro\0"
"com.lb\0"
-"com.lc\0consulado.st\0"
-"seiyo.ehime.jp\0"
+"veterinaire.km\0com.lc\0uzhgorod.ua\0is-a-musician.com\0freedesktop.org\0"
+"info.ve\0nom.rs\0"
+"tanabe.kyoto.jp\0"
"com.kw\0"
-"com.ky\0ivano-frankivsk.ua\0"
+"pgafan.net\0"
+"com.ky\0missile.museum\0"
"com.kz\0"
-"com.lk\0beiarn.no\0"
-"nike\0"
-"\xe7\x86\x8a\xe6\x9c\xac.jp\0fukui.fukui.jp\0shinjuku.tokyo.jp\0"
-"com.lr\0"
-"discover\0router.management\0"
-"pokrovsk.su\0"
-"com.lv\0"
-"com.mg\0inderoy.no\0ril\0"
-"com.ly\0kv\xc3\xa6""fjord.no\0"
-"trader.aero\0kawanabe.kagoshima.jp\0saiki.oita.jp\0rio\0"
-"com.mk\0coastaldefence.museum\0rip\0"
-"kosaka.akita.jp\0com.ml\0"
-"jewishart.museum\0"
-"goodhands\0bplaced.de\0"
-"com.mo\0"
-"gc.ca\0tainai.niigata.jp\0nm.us\0"
-"kanonji.kagawa.jp\0com.na\0nore-og-uvdal.no\0est.pr\0"
-"ito.shizuoka.jp\0com.ms\0verdal.no\0"
-"med.ht\0com.mt\0"
-"com.mu\0family.museum\0"
-"com.mv\0com.nf\0cyon.link\0"
+"com.lk\0nom.si\0"
+"pa.it\0info.vn\0arab\0"
+"*.ck\0"
+"miyako.iwate.jp\0"
+"k12.ok.us\0"
+"com.lr\0wlocl.pl\0\xe5\xb7\xa5\xe8\xa1\x8c\0"
+"\xd9\xbe\xd8\xa7\xda\xa9\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\0"
+"isa-hockeynut.com\0"
+"com.lv\0ostrowiec.pl\0nom.st\0"
+"com.mg\0"
+"kawasaki.miyagi.jp\0"
+"com.ly\0"
+"com.mk\0"
+"com.ml\0nom.tj\0"
+"historyofscience.museum\0midtre-gauldal.no\0bir.ru\0"
+"minami.fukuoka.jp\0"
+"com.mo\0southwest.museum\0nom.tm\0drud.io\0"
+"com.na\0"
+"com.ms\0showtime\0"
+"com.mt\0lol\0"
+"com.mu\0plaza.museum\0"
+"com.mv\0com.nf\0"
"com.mw\0com.ng\0"
"com.mx\0"
-"kitakami.iwate.jp\0com.my\0com.ni\0"
-"iwate.iwate.jp\0maserati\0"
-"is-saved.org\0"
-"ogimi.okinawa.jp\0"
-"gon.pk\0"
-"com.nr\0\xd8\xa7\xd9\x84\xd8\xb9\xd9\x84\xd9\x8a\xd8\xa7\xd9\x86\0"
-"karate.museum\0dyndns-remote.com\0"
-"c.bg\0iwakuni.yamaguchi.jp\0"
-"hamamatsu.shizuoka.jp\0dinosaur.museum\0freedesktop.org\0"
+"com.my\0com.ni\0nom.ug\0"
+"yonezawa.yamagata.jp\0"
+"production.aero\0sciencecenters.museum\0"
+"lodi.it\0info.tn\0"
+"chiryu.aichi.jp\0"
+"blogdns.com\0"
+"com.nr\0info.tr\0"
+"lib.mt.us\0lib.nd.us\0"
+"info.tt\0lpl\0"
+"ooguy.com\0nom.vc\0"
+"*.er\0"
+"sande.m\xc3\xb8re-og-romsdal.no\0"
+"veterinaire.fr\0rikuzentakata.iwate.jp\0jeonnam.kr\0"
+"nom.vg\0"
+"info.tz\0"
+"t.se\0nom.uy\0"
+"art.pl\0"
"com.om\0"
-"campidanomedio.it\0tosu.saga.jp\0"
-"kashima.ibaraki.jp\0com.pa\0"
-"fukaya.saitama.jp\0numazu.shizuoka.jp\0"
-"kainan.wakayama.jp\0"
-"com.pe\0"
-"inami.wakayama.jp\0com.pf\0"
-"inagawa.hyogo.jp\0draydns.de\0"
-"com.ph\0"
-"reggioemilia.it\0yuki.ibaraki.jp\0starostwo.gov.pl\0"
-"com.pk\0"
-"com.pl\0\xe7\xb5\x84\xe7\xb9\x94.\xe9\xa6\x99\xe6\xb8\xaf\0"
-"sakado.saitama.jp\0"
-"exeter.museum\0s\xc3\xb8ndre-land.no\0cc.ok.us\0"
-"com.qa\0"
+"*.fj\0"
+"*.fk\0"
+"\xe4\xb8\x89\xe9\x87\x8d.jp\0"
+"com.pa\0cc.pa.us\0"
+"nishinomiya.hyogo.jp\0"
+"tsurugashima.saitama.jp\0"
+"aukra.no\0com.pe\0"
+"hara.nagano.jp\0com.pf\0man\0"
+"pharmacy.museum\0"
+"piemonte.it\0trentinosudtirol.it\0com.ph\0map\0zapto.xyz\0"
+"mba\0"
+"izena.okinawa.jp\0"
+"museumvereniging.museum\0com.pk\0"
+"tomioka.gunma.jp\0com.pl\0"
+"takasaki.gunma.jp\0hiraizumi.iwate.jp\0"
+"info.ro\0"
+"historichouses.museum\0com.qa\0"
"com.pr\0"
-"culturalcenter.museum\0sandefjord.no\0com.ps\0agency\0"
-"halloffame.museum\0com.pt\0"
-"leangaviika.no\0"
-"x443.pw\0"
-"nyuzen.toyama.jp\0com.py\0barsy.menu\0"
-"piedmont.it\0"
-"decorativearts.museum\0lib.mo.us\0"
-"gniezno.pl\0dyndns.info\0"
-"sm.ua\0"
-"risor.no\0"
-"sasayama.hyogo.jp\0"
-"saitama.saitama.jp\0"
-"com.re\0"
-"kanoya.kagoshima.jp\0"
-"med.ly\0"
-"hitachiota.ibaraki.jp\0atlanta.museum\0"
-"sld.pa\0"
+"com.ps\0"
+"com.pt\0info.sd\0"
+"g\xc3\xa1\xc5\x8bgaviika.no\0"
+"hida.gifu.jp\0"
+"hotel.lk\0com.py\0paris\0"
+"\xe5\xb1\xb1\xe5\x8f\xa3.jp\0fujixerox\0"
+"yachiyo.chiba.jp\0"
+"trentinosued-tirol.it\0\xe0\xa6\xad\xe0\xa6\xbe\xe0\xa7\xb0\xe0\xa6\xa4\0"
+"holtalen.no\0"
+"\xe7\xb5\x84\xe7\xb9\x94.tw\0"
+"soeda.fukuoka.jp\0"
+"gorge.museum\0com.re\0au.eu.org\0be.eu.org\0"
+"info.pk\0"
+"trentinosuedtirol.it\0tokamachi.niigata.jp\0gushikami.okinawa.jp\0info.pl\0ltd\0"
+"miyoshi.saitama.jp\0art.sn\0"
"com.ro\0"
-"yodobashi\0"
-"com.sa\0land-4-sale.us\0"
-"com.sb\0"
-"com.sc\0"
-"com.sd\0direct\0"
-"com.se\0com.ru\0"
-"s3-website-us-west-2.amazonaws.com\0"
-"h\xc3\xa1pmir.no\0com.rw\0com.sg\0"
+"denmark.museum\0uhren.museum\0com.sa\0servegame.com\0"
+"info.pr\0com.sb\0"
+"com.sc\0nom.za\0"
+"hs.kr\0com.sd\0"
+"\xc3\xa5l.no\0com.se\0com.ru\0"
+"mashiki.kumamoto.jp\0"
+"com.rw\0com.sg\0"
"com.sh\0"
-"\xe5\x95\x86\xe6\xa0\x87\0"
-"com.sl\0"
-"nishinomiya.hyogo.jp\0kustanai.ru\0"
-"com.sn\0"
-"passenger-association.aero\0com.so\0"
-"tsushima.nagasaki.jp\0"
-"com.st\0uy.com\0"
-"x.se\0isa-geek.com\0"
-"com.sv\0"
-"\xe8\x8c\xa8\xe5\x9f\x8e.jp\0otama.fukushima.jp\0"
-"com.sy\0"
+"rade.no\0americanfamily\0"
+"valledaosta.it\0"
+"froya.no\0"
+"store.bb\0com.sl\0med\0"
+"com.sn\0ericsson\0"
+"com.so\0git-repos.de\0"
+"ryuoh.shiga.jp\0"
+"*.jm\0info.na\0is-a-democrat.com\0"
+"britishcolumbia.museum\0"
+"motobu.okinawa.jp\0com.st\0"
+"myravendb.com\0"
+"info.mv\0info.nf\0com.sv\0men\0"
+"trainer.aero\0"
+"info.ni\0com.sy\0barsy.bg\0"
"com.tj\0"
-"crimea.ua\0ybo.faith\0"
-"jinsekikogen.hiroshima.jp\0nishikawa.yamagata.jp\0sor-aurdal.no\0"
-"\xc3\xa5mli.no\0t\xc3\xb8nsberg.no\0med.om\0com.tm\0kustanai.su\0"
+"*.kh\0"
+"com.tm\0"
"com.tn\0"
-"hatoyama.saitama.jp\0museumcenter.museum\0com.to\0"
-"med.pa\0com.ua\0"
-"charter.aero\0pvh.br\0com.tr\0simple-url.com\0"
-"salvador.br\0"
-"com.tt\0"
-"com.tw\0com.ug\0"
-"marche.it\0"
-"goodyear\0"
-"sap\0"
-"dyndns-office.com\0hzc.io\0med.pl\0"
-"kvitsoy.no\0cn.eu.org\0"
-"saobernardo.br\0tp.it\0sas\0"
-"carboniaiglesias.it\0"
-"rmit\0"
-"boavista.br\0kawaba.gunma.jp\0com.vc\0"
-"photos\0sbi\0"
-"com.ve\0"
-"vgs.no\0"
-"bialowieza.pl\0"
-"hakuba.nagano.jp\0com.uy\0com.vi\0"
-"l\xc3\xb8ten.no\0com.uz\0"
-"sca\0"
-"mod.gi\0scb\0"
-"aizuwakamatsu.fukushima.jp\0com.vn\0sbs\0"
-"\xe5\x85\xb5\xe5\xba\xab.jp\0"
-"tinn.no\0dynamisches-dns.de\0"
-"from-vt.com\0"
-"from-az.net\0"
-"delta\0"
-"lucerne.museum\0com.vu\0"
-"minamisanriku.miyagi.jp\0"
-"oki.fukuoka.jp\0"
-"hita.oita.jp\0fyresdal.no\0"
-"saito.miyazaki.jp\0"
-"ingatlan.hu\0"
-"med.sa\0"
-"com.ws\0s3.dualstack.eu-west-2.amazonaws.com\0"
-"qc.ca\0med.sd\0"
-"olbiatempio.it\0"
-"\xe6\x9b\xb8\xe7\xb1\x8d\0"
-"chirurgiens-dentistes-en-france.fr\0"
-"firestone\0*.compute.amazonaws.com.cn\0"
-"pilot.aero\0m\xc3\xa5lselv.no\0"
-"barrell-of-knowledge.info\0"
-"guge\0play\0c.la\0"
-"\xe7\xb5\x84\xe7\xb9\x94.hk\0iwaki.fukushima.jp\0law.za\0"
-"is-an-entertainer.com\0"
-"mamurogawa.yamagata.jp\0"
-"run\0"
-"se.net\0ru.net\0"
-"scienceandhistory.museum\0investments\0ravendb.me\0"
-"anthro.museum\0"
-"izu.shizuoka.jp\0ses\0"
-"sew\0"
-"sex\0"
-"coloradoplateau.museum\0"
-"lc.it\0\xe5\xae\xae\xe5\x9f\x8e.jp\0stokke.no\0"
-"kurume.fukuoka.jp\0"
-"gratangen.no\0"
-"kotohira.kagawa.jp\0ohkura.yamagata.jp\0gateway.museum\0"
-"canada.museum\0exnet.su\0"
-"shinonsen.hyogo.jp\0"
-"sk.ca\0com.zm\0sfr\0"
-"kitaura.miyazaki.jp\0githubusercontent.com\0"
-"oita.jp\0rwe\0"
-"dynu.net\0"
-"otake.hiroshima.jp\0"
-"kinko.kagoshima.jp\0"
-"pippu.hokkaido.jp\0"
-"gv.ao\0data\0"
-"skydiving.aero\0"
-"tsushima.aichi.jp\0date\0cy.eu.org\0servehttp.com\0"
-"gv.at\0"
-"nakatane.kagoshima.jp\0"
-"sakurai.nara.jp\0as.us\0academy\0"
-"tadaoka.osaka.jp\0"
-"steigen.no\0"
-"recreation.aero\0omachi.saga.jp\0aquarium.museum\0"
-"gouv.fr\0nanjo.okinawa.jp\0"
-"za.net\0"
-"etisalat\0dynalias.net\0sp.leg.br\0"
-"memorial.museum\0"
-"motobu.okinawa.jp\0"
-"gs.sf.no\0ro.eu.org\0"
-"lincoln\0"
-"selfip.info\0"
-"mielno.pl\0us-east-1.amazonaws.com\0"
-"kazo.saitama.jp\0on-the-web.tv\0"
-"sar.it\0"
-"omaezaki.shizuoka.jp\0is-into-anime.com\0"
-"newjersey.museum\0"
-"edunet.tn\0cz.eu.org\0"
-"ayase.kanagawa.jp\0"
-"kitanakagusuku.okinawa.jp\0rad\xc3\xb8y.no\0maison\0"
-"trentinoa-adige.it\0scrysec.com\0"
-"kamigori.hyogo.jp\0"
-"kashima.saga.jp\0notaires.km\0"
-"v.bg\0"
-"furukawa.miyagi.jp\0"
-"shirahama.wakayama.jp\0"
-"gouv.ht\0"
-"sodegaura.chiba.jp\0plantation.museum\0"
-"taifun-dns.de\0"
-"fujinomiya.shizuoka.jp\0luxembourg.museum\0"
-"help\0"
-"lans.museum\0askvoll.no\0cc.ca.us\0racing\0map.fastlylb.net\0"
-"koriyama.fukushima.jp\0communication.museum\0"
-"copenhagen.museum\0western.museum\0ski\0"
-"konsulat.gov.pl\0"
-"comsec\0"
-"ravendb.community\0"
-"savona.it\0"
-"dk.eu.org\0"
-"gouv.bj\0"
-"aurskog-h\xc3\xb8land.no\0"
-"skodje.no\0sky\0"
-"koshigaya.saitama.jp\0c.se\0"
-"monzaebrianza.it\0"
-"inami.toyama.jp\0"
-"ptplus.fit\0"
-"gouv.ci\0"
-"geekgalaxy.com\0"
-"pagefrontapp.com\0"
-"overhalla.no\0lidl\0si.eu.org\0"
-"sugito.saitama.jp\0grajewo.pl\0"
-"en.it\0"
-"cloudns.club\0"
-"crafts.museum\0"
-"axis.museum\0"
-"nakatombetsu.hokkaido.jp\0"
-"kumamoto.jp\0"
-"virtuel.museum\0"
-"convent.museum\0"
-"figueres.museum\0ustka.pl\0"
-"vardo.no\0blogdns.org\0"
-"life\0"
-"eastcoast.museum\0dep.no\0"
-"firmdale\0"
-"sunndal.no\0servepics.com\0"
-"durham.museum\0contact\0"
-"settsu.osaka.jp\0"
-"bv.nl\0"
-"akune.kagoshima.jp\0"
-"chiba.jp\0"
-"nid.io\0"
-"\xc3\xa5lesund.no\0"
-"komagane.nagano.jp\0"
-"tenri.nara.jp\0"
-"kasama.ibaraki.jp\0ullensvang.no\0\xd8\xb9\xd9\x85\xd8\xa7\xd9\x86\0de.eu.org\0"
-"tondabayashi.osaka.jp\0"
-"aso.kumamoto.jp\0"
-"br\xc3\xb8nn\xc3\xb8y.no\0here\0"
-"kuromatsunai.hokkaido.jp\0everbank\0soy\0from-nv.com\0"
-"drammen.no\0"
-"on.ca\0"
-"univ.sn\0"
-"vc.it\0"
-"contemporary.museum\0farsund.no\0wang\0"
-,
-
-"obama.nagasaki.jp\0supplies\0"
-"s3-eu-west-1.amazonaws.com\0bci.dnstrace.pro\0"
-"tab\0"
-"krym.ua\0usr.cloud.muni.cz\0"
-"sk.eu.org\0"
-"\xe0\xb8\x98\xe0\xb8\xb8\xe0\xb8\xa3\xe0\xb8\x81\xe0\xb8\xb4\xe0\xb8\x88.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0fujitsu\0s3-ap-south-1.amazonaws.com\0cn.com\0"
-"ks.ua\0"
-"asahi.toyama.jp\0other.nf\0guru\0us-east-2.elasticbeanstalk.com\0"
-"nordre-land.no\0rackmaze.net\0"
-"kanan.osaka.jp\0"
-"autos\0"
-"gangaviika.no\0"
-"baby\0"
-"shell.museum\0"
-"melhus.no\0"
-"\xc3\xa5mot.no\0"
-"tax\0"
-"ugim.gov.pl\0ks.us\0"
-"hioki.kagoshima.jp\0"
-"srl\0from-va.com\0"
-"epson\0s3-website.ca-central-1.amazonaws.com\0"
-"dsmynas.com\0"
-"natal.br\0"
-"friulive-giulia.it\0photography\0"
-"\xe5\xaf\x8c\xe5\xb1\xb1.jp\0sano.tochigi.jp\0"
-"tselinograd.su\0lcube-server.de\0"
-"bunkyo.tokyo.jp\0srt\0"
-"grainger\0"
-"genkai.saga.jp\0meteorapp.com\0"
-"certmgr.org\0"
-"tci\0"
-"cc.wv.us\0"
-"mansion.museum\0lib.ia.us\0"
-"oppeg\xc3\xa5rd.no\0oster\xc3\xb8y.no\0like\0"
-"corporation.museum\0"
-"foz.br\0yamato.kumamoto.jp\0"
-"naie.hokkaido.jp\0"
-"9.bg\0yame.fukuoka.jp\0"
-"stc\0"
-"matsuda.kanagawa.jp\0"
-"gol.no\0"
-"\xe9\x80\x9a\xe8\xb2\xa9\0"
-"drayddns.com\0"
-"us.na\0caseih\0tdk\0"
-"narvik.no\0"
-"jpmorgan\0"
-"selfip.org\0"
-"town\0"
-"ru.eu.org\0se.eu.org\0"
-"langevag.no\0"
-"market\0"
-"su\xcc\x88""dtirol.it\0"
-"cc.ma.us\0"
-"tel\0"
-"bulsan.it\0"
-"masoy.no\0"
-"k12.nm.us\0"
-"sanofi\0"
-"cloudns.info\0"
-"lib.ky.us\0"
-"obama.fukui.jp\0limo\0"
-"a.bg\0r\xc3\xa1isa.no\0"
-"cymru.museum\0isa-geek.net\0"
-"aq.it\0ba.it\0"
-"link\0"
-"bozen-suedtirol.it\0minamiminowa.nagano.jp\0cc.al.us\0lima.zone\0"
-"toys\0"
-"sciencecenters.museum\0"
-"guardian\0"
-"kongsberg.no\0"
-"cc.ny.us\0ca.eu.org\0"
-"trentino-alto-adige.it\0kitaaiki.nagano.jp\0lib.al.us\0thd\0"
-"halden.no\0"
-"fashion\0"
-"myftp.biz\0"
-"moriyama.shiga.jp\0rsc.cdn77.org\0from-ky.com\0"
-"\xe4\xb8\x89\xe9\x87\x8d.jp\0fidelity\0"
-"\xe5\xb1\xb1\xe6\xa2\xa8.jp\0"
-"somna.no\0"
-"productions\0voting\0"
-"forde.no\0"
-"chikuzen.fukuoka.jp\0plus\0"
-"mashike.hokkaido.jp\0"
-"leksvik.no\0"
-"hagi.yamaguchi.jp\0"
-"publ.pt\0"
-"1kapp.com\0"
-"\xd8\xaa\xd9\x88\xd9\x86\xd8\xb3\0"
-"showa.fukushima.jp\0"
-"yamatsuri.fukushima.jp\0is-a-designer.com\0"
-"cc.ct.us\0"
-"takikawa.hokkaido.jp\0*.stolos.io\0"
-"cpa.pro\0garden\0"
-"wiki.bo\0"
-"wiki.br\0"
-"itayanagi.aomori.jp\0store.nf\0"
-"asahikawa.hokkaido.jp\0fudai.iwate.jp\0"
-"dallas.museum\0"
-"is-an-anarchist.com\0"
-"sakegawa.yamagata.jp\0"
-"kanagawa.jp\0yamatotakada.nara.jp\0alabama.museum\0"
-"\xd0\xbe\xd0\xbd\xd0\xbb\xd0\xb0\xd0\xb9\xd0\xbd\0"
-"tjx\0"
-"est-a-la-maison.com\0"
-"yn.cn\0"
-"funahashi.toyama.jp\0torino.museum\0"
-"eiheiji.fukui.jp\0coldwar.museum\0"
-"podhale.pl\0airbus\0"
-"yamada.iwate.jp\0"
-"walmart\0on-web.fr\0"
-"friuli-v-giulia.it\0"
-"hareid.no\0cc.fl.us\0"
-"valled-aosta.it\0"
-"shiroishi.saga.jp\0"
-"band\0"
-"karumai.iwate.jp\0"
-"tn.it\0gouv.rw\0"
-"spjelkavik.no\0zachpomor.pl\0"
-"iwaizumi.iwate.jp\0"
-"turek.pl\0\xe5\xb7\xa5\xe8\xa1\x8c\0"
-"exhibition.museum\0serveftp.com\0"
-"otaki.saitama.jp\0m\xc3\xa1latvuopmi.no\0bank\0"
-"lib.fl.us\0social\0"
-"bronnoy.no\0hoyanger.no\0gouv.sn\0software\0"
-"stalowa-wola.pl\0consulting\0spdns.eu\0"
-"kaufen\0"
-"tromsa.no\0"
-"takatsuki.osaka.jp\0"
-"kagamiishi.fukushima.jp\0cd.eu.org\0"
-"sondre-land.no\0"
-"tennis\0"
-"ginoza.okinawa.jp\0"
-"s3.eu-central-1.amazonaws.com\0"
-"ngo.lk\0"
-"beardu.no\0"
-"rikuzentakata.iwate.jp\0live\0"
-"rotorcraft.aero\0"
-"frei.no\0"
-"sk\xc3\xa1nit.no\0mazowsze.pl\0cc.id.us\0tunk.org\0"
-"laquila.it\0"
-"ricoh\0"
-"nagi.okayama.jp\0"
-"vv.it\0"
-"shacknet.nu\0"
-"arab\0"
-"matsusaka.mie.jp\0cc.wa.us\0"
-"daiwa.hiroshima.jp\0dnsking.ch\0"
-"sardinia.it\0mihara.kochi.jp\0lanbib.se\0top\0"
-"prato.it\0lixil\0"
-"nosegawa.nara.jp\0lv.ua\0"
-"namegata.ibaraki.jp\0wolomin.pl\0christmas\0"
-"sp.gov.br\0"
-"dclk\0"
-"nesseby.no\0lib.vi.us\0"
-"trentinsuedtirol.it\0herokussl.com\0"
-"ham-radio-op.net\0"
-"shiogama.miyagi.jp\0jobs.tt\0"
-"kawara.fukuoka.jp\0"
-"nsw.au\0divtasvuodna.no\0"
-"res.aero\0"
-"kagamino.okayama.jp\0alvdal.no\0"
-"enonic.io\0"
-"mex.com\0"
-"devices.resinstaging.io\0"
-"nebraska.museum\0"
-"jamison.museum\0"
-"esp.br\0"
-"muosat.no\0"
-"chiyoda.gunma.jp\0"
-"monza-e-della-brianza.it\0okutama.tokyo.jp\0sn\xc3\xa5""ase.no\0s\xc3\xb8rreisa.no\0email\0"
-"cuiaba.br\0"
-"yasugi.shimane.jp\0ngo.ph\0store.ve\0"
-"shimabara.nagasaki.jp\0"
-"friuli-venezia-giulia.it\0"
-"zaporizhzhe.ua\0mortgage\0"
-"brunel.museum\0"
-"my.id\0kita.kyoto.jp\0kawatana.nagasaki.jp\0mugi.tokushima.jp\0"
-"ubs\0kalmykia.su\0cust.dev.thingdust.io\0"
-"newholland\0trv\0"
-"assn.lk\0spdns.de\0"
-"embroidery.museum\0"
-"shiriuchi.hokkaido.jp\0"
-"utah.museum\0forsand.no\0mycd.eu\0"
-"fukuoka.jp\0so.gov.pl\0"
-"romsa.no\0"
-"odate.akita.jp\0anamizu.ishikawa.jp\0tateyama.toyama.jp\0bodo.no\0holdings\0"
-"cc.mt.us\0cc.nd.us\0"
-"go.dyndns.org\0"
-"\xd8\xa7\xd9\x8a\xd8\xb1\xd8\xa7\xd9\x86.ir\0alta.no\0"
-"ukiha.fukuoka.jp\0"
-"sites.static.land\0"
-"stordal.no\0"
-"katsuragi.nara.jp\0"
-"katori.chiba.jp\0"
-"firm.ht\0sener\0"
-"lib.md.us\0from-nj.com\0za.org\0"
-"tokyo.jp\0higashiizu.shizuoka.jp\0"
-"t.bg\0shimotsuke.tochigi.jp\0gouv.km\0"
-"verran.no\0"
-"tui\0"
-"uri.arpa\0firm.in\0ureshino.mie.jp\0flynnhub.com\0"
-"notaires.fr\0*.elb.amazonaws.com\0"
-"bt.it\0gjesdal.no\0"
-"*.kitakyushu.jp\0shijonawate.osaka.jp\0cloud.goog\0"
-"aikawa.kanagawa.jp\0"
-"edogawa.tokyo.jp\0\xe5\xa4\xa7\xe4\xbc\x97\xe6\xb1\xbd\xe8\xbd\xa6\0"
-"kalmykia.ru\0"
-"enna.it\0leitungsen.de\0"
-"morotsuka.miyazaki.jp\0nichinan.tottori.jp\0burghof.museum\0\xe3\x83\x95\xe3\x82\xa1\xe3\x83\x83\xe3\x82\xb7\xe3\x83\xa7\xe3\x83\xb3\0"
-"ryuoh.shiga.jp\0"
-"fortal.br\0!city.nagoya.jp\0kamoenai.hokkaido.jp\0int.eu.org\0"
-"floro.no\0holt\xc3\xa5len.no\0"
-"condos\0stream\0"
-"supply\0bmoattachments.org\0"
-"to.leg.br\0"
-"kanzaki.saga.jp\0store.ro\0"
-"jl.cn\0taiki.mie.jp\0tvs\0"
-"jerusalem.museum\0"
-"gouv.ml\0""3utilities.com\0"
-"a.se\0pramerica\0"
-"money.museum\0"
-"firm.co\0"
-"ono.fukushima.jp\0nordreisa.no\0"
-"room\0"
-"paragliding.aero\0pri.ee\0hobby-site.com\0"
-"pasadena.museum\0"
-"newmexico.museum\0"
-"bremanger.no\0ga.us\0"
-"ostroleka.pl\0store.st\0s3-website.eu-west-3.amazonaws.com\0"
-"firm.dk\0"
-"fineart.museum\0"
-"osaka.jp\0"
-"trentinsu\xcc\x88""dtirol.it\0"
-"torahime.shiga.jp\0unusualperson.com\0"
-"priv.hu\0tn.us\0alpha-myqnapcloud.com\0"
-"si.it\0miyashiro.saitama.jp\0"
-"*.awdev.ca\0"
-"tsukumi.oita.jp\0"
-"cc.sd.us\0"
-"md.ci\0kaneyama.fukushima.jp\0"
-"kakamigahara.gifu.jp\0lib.dc.us\0"
-"vologda.su\0"
-"\xd8\xa8\xd8\xa7\xd8\xb1\xd8\xaa\0"
-"yotsukaido.chiba.jp\0motorcycle.museum\0"
-"bugatti\0"
-"ogawa.nagano.jp\0dentist\0"
-"chitose.hokkaido.jp\0debian.net\0"
-"chicago.museum\0newhampshire.museum\0stavanger.no\0"
-"n\xc3\xa1vuotna.no\0"
-"can.museum\0oceanographic.museum\0definima.net\0"
-"telefonica\0"
-"chrome\0"
-"cal.it\0"
-"living\0cyon.site\0"
-"va.it\0"
-"trust\0"
-"kakogawa.hyogo.jp\0"
-"group\0"
-"ngo.za\0"
-"ong.br\0"
-"\xe0\xa8\xad\xe0\xa8\xbe\xe0\xa8\xb0\xe0\xa8\xa4\0"
-"morena.br\0"
-"s3.cn-north-1.amazonaws.com.cn\0"
-"yura.wakayama.jp\0dnsupdater.de\0"
-"shirataka.yamagata.jp\0"
-"army\0dynalias.org\0"
-"fukuroi.shizuoka.jp\0la.us\0"
-"priv.at\0"
-"kira.aichi.jp\0nagai.yamagata.jp\0kristiansand.no\0"
-"sr.gov.pl\0"
-"abogado\0"
-"asahi.ibaraki.jp\0"
-"\xe7\xa7\x8b\xe7\x94\xb0.jp\0yakumo.hokkaido.jp\0higashikagawa.kagawa.jp\0dnepropetrovsk.ua\0"
-"askoy.no\0"
-"fishing\0"
+"depot.museum\0com.to\0"
+"com.ua\0safe\0"
+"info.nr\0com.tr\0pohl\0"
+"tysvar.no\0"
+"re.it\0com.tt\0"
+"muncie.museum\0com.tw\0cherkassy.ua\0com.ug\0"
+"geisei.kochi.jp\0izumi.osaka.jp\0swidnik.pl\0"
+"tomobe.ibaraki.jp\0"
+"exeter.museum\0"
+"monzabrianza.it\0"
+"info.la\0bitballoon.com\0"
+"\xe0\xb8\x97\xe0\xb8\xab\xe0\xb8\xb2\xe0\xb8\xa3.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0istanbul\0"
+"hotel.hu\0com.vc\0barcelona\0"
+"com.ve\0realestate\0store.dk\0bg.eu.org\0"
+"flog.br\0"
+"\xe7\xbb\x84\xe7\xb9\x94.hk\0barsy.de\0"
+"com.uy\0com.vi\0ddnsking.com\0"
+"com.uz\0"
+"com.vn\0"
+"bronnoysund.no\0"
+"toya.hokkaido.jp\0ebina.kanagawa.jp\0"
+"*.mm\0zoological.museum\0lind\xc3\xa5s.no\0"
+"re.kr\0"
+"info.ls\0no-ip.co.uk\0"
+"com.vu\0"
+"finearts.museum\0"
+"hiratsuka.kanagawa.jp\0"
+"media.hu\0iron.museum\0"
+"jampa.br\0"
+"k12.nj.us\0"
"tamano.okayama.jp\0"
-"arpa\0*.sensiosite.cloud\0"
-"birkenes.no\0sejny.pl\0"
-"7.bg\0uno\0"
-"hisayama.fukuoka.jp\0delivery\0"
-"adm.br\0skanit.no\0"
-"praxi\0getmyip.com\0"
-"lib.vt.us\0"
-"friuliv-giulia.it\0"
-"agrar.hu\0"
-"williamsburg.museum\0"
-"minamioguni.kumamoto.jp\0"
-"uol\0"
-"beskidy.pl\0df.leg.br\0"
-"archi\0"
-"2000.hu\0kyoto.jp\0mitoyo.kagawa.jp\0"
-"lt.it\0"
-"cosenza.it\0va.no\0"
-"musica.ar\0cuisinella\0"
-"mus.mi.us\0"
-"chiryu.aichi.jp\0kyiv.ua\0"
-"services.aero\0takahama.fukui.jp\0yanagawa.fukuoka.jp\0kautokeino.no\0"
-"fl\xc3\xa5.no\0"
-"ups\0"
-"tonosho.kagawa.jp\0"
-"forum.hu\0is-a-personaltrainer.com\0"
-"musica.bo\0otsuchi.iwate.jp\0adygeya.su\0"
-"broker.aero\0yonabaru.okinawa.jp\0"
-"s3-us-east-2.amazonaws.com\0"
-"ao.it\0"
-"firm.ve\0*.ex.futurecms.at\0"
-"shiiba.miyazaki.jp\0management\0"
-"ichinohe.iwate.jp\0lardal.no\0"
-"blogdns.net\0"
-"lazio.it\0"
-"trentinoaadige.it\0asda\0"
+"misaki.okayama.jp\0cloudns.club\0"
+"heroy.nordland.no\0"
+"homeftp.net\0"
+"com.ws\0"
+"mil\0*.np\0hgtv\0"
+"varggat.no\0"
+"vlog.br\0oharu.aichi.jp\0"
+"barsy.eu\0"
+"mit\0"
+"pa.us\0"
+"friulivegiulia.it\0"
+"town.museum\0"
+"\xe5\xb1\xb1\xe5\xbd\xa2.jp\0hidaka.saitama.jp\0"
+"ab.ca\0info.ke\0forum\0us.com\0"
+"chuo.fukuoka.jp\0sklep.pl\0"
+"qld.au\0"
+"info.ki\0"
+"jinsekikogen.hiroshima.jp\0yashio.saitama.jp\0"
+"*.pg\0"
+"lib.mi.us\0"
+"to.leg.br\0"
+"comsec\0"
+"jan-mayen.no\0"
+"loten.no\0drud.us\0"
+"a.se\0army\0east-kazakhstan.su\0"
+"tomiya.miyagi.jp\0"
+"mlb\0"
+"s3-website.ap-south-1.amazonaws.com\0kurgan.su\0"
+"sld.do\0com.zm\0"
+"campidanomedio.it\0"
+"luxembourg.museum\0sale\0"
+"ouda.nara.jp\0"
+"dynamic-dns.info\0"
+"griw.gov.pl\0"
+"s3-external-1.amazonaws.com\0"
+"karikatur.museum\0project.museum\0mma\0"
+"kg.kr\0"
+"mls\0"
+"arpa\0michigan.museum\0"
+"nanporo.hokkaido.jp\0uppo.gov.pl\0"
+"flesberg.no\0"
+"barsy.in\0"
+"it.ao\0time.no\0barsy.io\0"
+"freemasonry.museum\0africa\0hr.eu.org\0"
+"ntdll.top\0"
+"r.bg\0skierva.no\0qc.com\0"
+"r\xc3\xa1isa.no\0parts\0"
+"omiya.saitama.jp\0"
+"roma.museum\0"
+"res.aero\0party\0"
+"rockart.museum\0"
+"mj\xc3\xb8ndalen.no\0contractors\0passagens\0"
+"hamaroy.no\0"
+"go.gov.br\0"
+"educational.museum\0"
+"amagasaki.hyogo.jp\0frontier\0"
+"\xe7\xae\x87\xe4\xba\xba.hk\0ddr.museum\0s3.dualstack.ap-southeast-2.amazonaws.com\0"
+"weir\0"
+"feira.br\0asakawa.fukushima.jp\0"
+"fl\xc3\xa5.no\0k12.sc.us\0moe\0"
+"oregon.museum\0"
+"vercelli.it\0basketball\0"
+"aip.ee\0nedre-eiker.no\0moi\0"
+"togakushi.nagano.jp\0final\0barsy.support\0no-ip.biz\0"
+"consulting\0mom\0tires\0lcube-server.de\0"
+"voting\0"
+"is-a-landscaper.com\0"
+"conf.au\0suisse.museum\0"
+"kamikawa.hyogo.jp\0mov\0"
+"frogn.no\0"
+"media.pl\0"
+"bsb.br\0swiftcover\0"
+"koori.fukushima.jp\0porn\0noho.st\0"
+"b\xc3\xa5""d\xc3\xa5""ddj\xc3\xa5.no\0"
+"honbetsu.hokkaido.jp\0"
+"pacific.museum\0"
+"fm.br\0makinohara.shizuoka.jp\0"
+"nab\0myfritz.net\0"
+"co.krd\0"
+"asda\0"
+"pr.it\0kakamigahara.gifu.jp\0\xd8\xb9\xd9\x85\xd8\xa7\xd9\x86\0deal\0"
+"aogashima.tokyo.jp\0"
"arte\0"
-"bulsan-suedtirol.it\0egyptian.museum\0"
-"kerryhotels\0"
-"hgtv\0"
-"\xe0\xb8\x84\xe0\xb8\xad\xe0\xb8\xa1\0"
-"lib.ms.us\0lib.nc.us\0"
-"valle-d-aosta.it\0komatsu.ishikawa.jp\0ringebu.no\0"
-"sagamihara.kanagawa.jp\0"
-"ug.gov.pl\0"
-"taranto.it\0"
-"ap-southeast-2.elasticbeanstalk.com\0"
-"ogi.saga.jp\0mill.museum\0"
-"health.nz\0"
-"adygeya.ru\0"
-"gru.br\0dyn.cosidns.de\0"
-"bbva\0tmall\0"
-"oshima.yamaguchi.jp\0sumy.ua\0"
-"shiga.jp\0sakawa.kochi.jp\0"
-"drive\0s3-ca-central-1.amazonaws.com\0"
-"mielec.pl\0"
-"minamiawaji.hyogo.jp\0okayama.okayama.jp\0baltimore.museum\0"
-"paleo.museum\0eidsberg.no\0"
-"hotels\0"
-"aero.tt\0"
-"deal\0"
-"drud.io\0"
-"alstahaug.no\0uconnect\0"
-"ryukyu\0"
-"suzuka.mie.jp\0ch.eu.org\0firewall-gateway.net\0"
-"naha.okinawa.jp\0"
-"entertainment.aero\0store.bb\0t.se\0vet\0"
+"reggioemilia.it\0ehime.jp\0teshikaga.hokkaido.jp\0"
+"santamaria.br\0"
+"cyber.museum\0"
+"nakagawa.hokkaido.jp\0yamato.kanagawa.jp\0ogimi.okinawa.jp\0"
+"nba\0"
+"post\0"
+"cahcesuolo.no\0"
+"android\0"
+"\xd9\x83\xd8\xa7\xd8\xab\xd9\x88\xd9\x84\xd9\x8a\xd9\x83\0"
+"s3-eu-central-1.amazonaws.com\0"
+"kawai.nara.jp\0\xe8\xb0\xb7\xe6\xad\x8c\0"
+"withgoogle.com\0"
+"nh-serv.co.uk\0"
+"iizuka.fukuoka.jp\0meiwa.mie.jp\0lezajsk.pl\0"
+"minamiboso.chiba.jp\0hashima.gifu.jp\0imamat\0"
+"manaus.br\0urbino-pesaro.it\0kariya.aichi.jp\0sarl\0"
+"vpnplus.to\0"
+"msd\0"
+"bbva\0"
+"meldal.no\0"
+"*.triton.zone\0"
+"crotone.it\0toho.fukuoka.jp\0"
+"portal.museum\0tr\xc3\xa6na.no\0\xd9\x82\xd8\xb7\xd8\xb1\0"
+"allfinanz\0"
+"heroy.more-og-romsdal.no\0"
+"*.ye\0"
+"nrw.museum\0"
+"does-it.net\0"
+"ginoza.okinawa.jp\0"
+"yahaba.iwate.jp\0"
+"cc.pr.us\0azerbaijan.su\0"
+"mtn\0"
+"cloudns.info\0"
+"abarth\0"
+"\xe1\x83\x92\xe1\x83\x94\0mtr\0"
+"nec\0"
+"yokote.akita.jp\0sodegaura.chiba.jp\0"
"l\xc3\xa1hppi.no\0"
-"brumunddal.no\0"
-"aero.mv\0kwpsp.gov.pl\0"
-"firm.ro\0"
-"eu-west-1.elasticbeanstalk.com\0"
-"keisen.fukuoka.jp\0dynv6.net\0"
-"klepp.no\0"
-"matsubushi.saitama.jp\0"
-"takazaki.miyazaki.jp\0irish\0"
-"taishi.hyogo.jp\0luster.no\0"
-"ol.no\0"
-"vallee-aoste.it\0"
-"sannohe.aomori.jp\0kumamoto.kumamoto.jp\0"
-"vacations\0"
-"va.us\0"
+"kitagawa.kochi.jp\0"
+"workinggroup.aero\0"
+"padova.it\0onga.fukuoka.jp\0"
+"stjordal.no\0us-east-1.elasticbeanstalk.com\0s3-sa-east-1.amazonaws.com\0"
+"\xe5\xbe\xb3\xe5\xb3\xb6.jp\0komatsu.ishikawa.jp\0"
+"gs.fm.no\0"
+"saobernardo.br\0"
+"globo\0"
+"okinawa.okinawa.jp\0net\0"
"asia\0"
-"hamburg\0"
-"agents.aero\0\xd9\x82\xd8\xb7\xd8\xb1\0"
-"sula.no\0\xe0\xae\x9a\xe0\xae\xbf\xe0\xae\x99\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xaa\xe0\xaf\x8d\xe0\xae\xaa\xe0\xaf\x82\xe0\xae\xb0\xe0\xaf\x8d\0"
-"benevento.it\0"
-"yonezawa.yamagata.jp\0"
-"giessen.museum\0"
-"venezia.it\0serveirc.com\0"
-"dyr\xc3\xb8y.no\0"
-"toba.mie.jp\0"
-"higashi.fukushima.jp\0skoczow.pl\0"
-"store.dk\0"
-"esashi.hokkaido.jp\0lib.sc.us\0"
-"komae.tokyo.jp\0sells-it.net\0nalchik.ru\0"
-"daigo.ibaraki.jp\0kirkenes.no\0nowtv\0"
-"shiroi.chiba.jp\0kakegawa.shizuoka.jp\0mining.museum\0"
-"vig\0\xd8\xa8\xd9\x8a\xd8\xaa\xd9\x83\0"
-"myddns.rocks\0"
-"muos\xc3\xa1t.no\0"
-"oygarden.no\0"
-"gs.mr.no\0"
-"vin\0"
-"florence.it\0vip\0nalchik.su\0"
-"saitama.jp\0asnes.no\0"
-"tateshina.nagano.jp\0kamitsue.oita.jp\0firm.nf\0"
-"wy.us\0"
-"vt.it\0"
-"lerdal.no\0"
-"groks-this.info\0"
-"fujisawa.iwate.jp\0"
-"tas.au\0ibara.okayama.jp\0"
-"lt.ua\0"
-"health.museum\0"
-"pfizer\0"
-"toride.ibaraki.jp\0salangen.no\0"
-"toyonaka.osaka.jp\0charity\0"
-"izena.okinawa.jp\0school.museum\0"
-"l-o-g-i-n.de\0"
-"health.vn\0dyndns.biz\0"
-"friuli-ve-giulia.it\0vegarshei.no\0"
-"nahari.kochi.jp\0pohl\0"
-"dyndns-blog.com\0"
-"suldal.no\0md.us\0"
-"nord-aurdal.no\0"
-"higashi.fukuoka.jp\0"
-"gran.no\0"
-"app.os.stg.fedoraproject.org\0"
-"katsushika.tokyo.jp\0nanbu.yamanashi.jp\0anquan\0cloudns.eu\0"
-"honbetsu.hokkaido.jp\0"
-"salzburg.museum\0sorum.no\0"
-"asaminami.hiroshima.jp\0"
-"is-a-llama.com\0"
-"selfip.biz\0"
-"malatvuopmi.no\0rivne.ua\0lib.in.us\0"
-"\xe5\xb1\xb1\xe5\xbd\xa2.jp\0"
-"shikaoi.hokkaido.jp\0buyshouses.net\0"
-"lind\xc3\xa5s.no\0tarnobrzeg.pl\0"
-"forex\0"
-"andriabarlettatrani.it\0"
-"\xe0\xb9\x80\xe0\xb8\x99\xe0\xb9\x87\xe0\xb8\x95.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0"
-"toho.fukuoka.jp\0"
-"nationalfirearms.museum\0"
-"aioi.hyogo.jp\0at.eu.org\0georgia.su\0"
-"toei.aichi.jp\0onagawa.miyagi.jp\0"
-"to.gov.br\0\xe5\x80\x8b\xe4\xba\xba.hk\0blogsyte.com\0"
-"software.aero\0safe\0"
-"is-a-patsfan.org\0"
-"worse-than.tv\0"
-"gucci\0"
-"svizzera.museum\0"
-"cust.prod.thingdust.io\0"
-"contemporaryart.museum\0"
-"\xc3\xb8ksnes.no\0"
-"communications.museum\0"
-"hb.cn\0"
-"noho.st\0"
-"k12.oh.us\0today\0"
-"hayakawa.yamanashi.jp\0"
-"heroy.more-og-romsdal.no\0grondar.za\0"
-"vard\xc3\xb8.no\0"
-"kvam.no\0"
-"r.bg\0tcm.museum\0levanger.no\0cricket\0"
-"hashbang.sh\0"
-"holiday\0"
-"priv.pl\0"
-"miyazaki.miyazaki.jp\0cloudns.in\0"
-"habikino.osaka.jp\0dell\0"
-"weber\0"
-"br.it\0cb.it\0"
-"creditunion\0"
-"shitara.aichi.jp\0"
-"matsukawa.nagano.jp\0\xe0\xa4\x95\xe0\xa5\x89\xe0\xa4\xae\0"
-"madrid.museum\0redumbrella\0"
-"po.it\0ozora.hokkaido.jp\0"
-"trentinosud-tirol.it\0"
-"chernigov.ua\0k12.ca.us\0\xe4\xb8\xad\xe5\x9b\xbd\0"
-"taketomi.okinawa.jp\0mine.nu\0dray-dns.de\0"
-"kunitachi.tokyo.jp\0"
-"cloudns.cc\0"
-"nakamura.kochi.jp\0valer.hedmark.no\0drud.us\0"
-"fr\xc3\xb8ya.no\0"
-"wsa.gov.pl\0"
-"veterinaire.km\0"
-"abudhabi\0"
-"komono.mie.jp\0*.futurecms.at\0"
-"rebun.hokkaido.jp\0\xe4\xb8\xad\xe5\x9c\x8b\0"
-"fhsk.se\0"
-"priv.no\0"
-"mjondalen.no\0in.net\0"
-"computer.museum\0"
-"iraq.museum\0lund.no\0"
-"vercelli.it\0"
-"\xe3\x83\x9d\xe3\x82\xa4\xe3\x83\xb3\xe3\x83\x88\0mysecuritycamera.com\0"
-"monzaedellabrianza.it\0dnsdojo.org\0"
-"tarama.okinawa.jp\0"
-"toyoake.aichi.jp\0ichikawamisato.yamanashi.jp\0"
-"mb.ca\0francaise.museum\0"
-"fbx-os.fr\0"
-"topology.museum\0"
-"miyoshi.aichi.jp\0lib.de.us\0"
-"medizinhistorisches.museum\0salon\0"
-"sale\0"
-"ashibetsu.hokkaido.jp\0\xc3\xa5l.no\0brand.se\0"
-"shioya.tochigi.jp\0"
-"pilots.museum\0"
-"priv.me\0haugesund.no\0"
-"time.no\0healthcare\0"
-"gallery.museum\0"
-"tadotsu.kagawa.jp\0"
-"durban\0wed\0"
-"antiques.museum\0"
-"sandnes.no\0"
-"royken.no\0"
-"veterinaire.fr\0"
-"bnr.la\0"
-"am.br\0training\0edu.eu.org\0"
-"asuke.aichi.jp\0"
-"gr.it\0porn\0"
-"prof.pr\0mckinsey\0\xe9\xa6\x99\xe6\xa0\xbc\xe9\x87\x8c\xe6\x8b\x89\0"
-"act.edu.au\0atsugi.kanagawa.jp\0ventures\0at-band-camp.net\0"
-"kasamatsu.gifu.jp\0"
-"basilicata.it\0"
-"tatsuno.hyogo.jp\0kunohe.iwate.jp\0vt.us\0ownip.net\0"
-"siellak.no\0"
-"gr.jp\0"
-"trondheim.no\0"
-"svalbard.no\0"
-"niki.hokkaido.jp\0delaware.museum\0"
-"mosj\xc3\xb8""en.no\0"
-"yuza.yamagata.jp\0"
-"dental\0sharp\0*.magentosite.cloud\0"
-"dgca.aero\0"
-"df.gov.br\0post\0"
-"iz.hr\0"
-"abc.br\0desi\0"
-"dni.us\0"
-"aoki.nagano.jp\0"
-"bir.ru\0"
-"sakura.tochigi.jp\0"
-"gs.ah.no\0"
-"college\0"
-"her\xc3\xb8y.m\xc3\xb8re-og-romsdal.no\0"
-"abira.hokkaido.jp\0"
-"karlsoy.no\0"
-"dance\0"
-"sakuho.nagano.jp\0"
-"!city.sendai.jp\0chijiwa.nagasaki.jp\0"
-"empresa.bo\0"
-"nishigo.fukushima.jp\0anthropology.museum\0"
-"git-repos.de\0"
-"americanart.museum\0"
-"s3.us-east-2.amazonaws.com\0wmflabs.org\0"
-"for-better.biz\0"
-"final\0"
-"test-iserv.de\0"
-"colonialwilliamsburg.museum\0"
-"5.bg\0"
-"stjohn.museum\0win\0"
-"r\xc3\xa5holt.no\0insure\0"
-"spreadbetting\0"
-"yamada.toyama.jp\0on-aptible.com\0"
-"cipriani\0"
-"srv.br\0from-de.com\0gotdns.com\0"
-"selfip.com\0"
-"nationwide\0"
-"bruxelles.museum\0"
-"okuma.fukushima.jp\0silk.museum\0"
-"opole.pl\0"
-"fm.br\0s3-external-1.amazonaws.com\0"
-"tamaki.mie.jp\0sarl\0"
-"mb.it\0"
-"tarui.gifu.jp\0fujiidera.osaka.jp\0t3l3p0rt.net\0"
-"\xd8\xa7\xd8\xb1\xd8\xa7\xd9\x85\xd9\x83\xd9\x88\0"
-"karasjohka.no\0"
-"shikama.miyagi.jp\0"
-"gen.mi.us\0"
-"amagasaki.hyogo.jp\0togakushi.nagano.jp\0kirovograd.ua\0"
-"sor-fron.no\0"
-"k12.ma.us\0"
-"\xe7\xbb\x84\xe7\xb9\x94.hk\0wassamu.hokkaido.jp\0arakawa.tokyo.jp\0"
-"onojo.fukuoka.jp\0horonobe.hokkaido.jp\0"
-"g12.br\0"
-"honai.ehime.jp\0bilbao.museum\0"
-"tj.cn\0oyer.no\0"
-"reggio-emilia.it\0"
-"weir\0"
-"miasta.pl\0cloudns.us\0"
-"rj.leg.br\0"
-"zushi.kanagawa.jp\0chiropractic.museum\0forum\0"
-"rzgw.gov.pl\0cistron.nl\0"
-"wme\0"
-"shirako.chiba.jp\0spacekit.io\0"
-"\xc3\xa5krehamn.no\0averoy.no\0"
-"resistance.museum\0"
-"firebaseapp.com\0"
-"hanyu.saitama.jp\0sandiego.museum\0"
-"workshop.museum\0"
-"homesecuritypc.com\0"
-"from-or.com\0"
-"honeywell\0sells-for-u.com\0"
-"\xe0\xb4\xad\xe0\xb4\xbe\xe0\xb4\xb0\xe0\xb4\xa4\xe0\xb4\x82\0"
-"hirono.iwate.jp\0"
-"chita.aichi.jp\0"
+"melhus.no\0new\0"
+"vao.it\0"
"save\0"
-"toyooka.hyogo.jp\0"
-"lib.ne.us\0"
-"ichikawa.chiba.jp\0"
-"imari.saga.jp\0"
-"oslo.no\0"
-"hinode.tokyo.jp\0"
-"deloitte\0\xe6\x89\x8b\xe8\xa1\xa8\0"
-"n\xc3\xb8tter\xc3\xb8y.no\0is-into-cartoons.com\0"
-"kepno.pl\0"
-"rexroth\0"
-"cheltenham.museum\0"
-"au.eu.org\0be.eu.org\0"
-"lel.br\0"
-"hitachiomiya.ibaraki.jp\0"
-"alessandria.it\0tsu.mie.jp\0wow\0xenapponazure.com\0"
-"warabi.saitama.jp\0"
-"a.ssl.fastly.net\0"
-"nakanojo.gunma.jp\0"
-"mitsuke.niigata.jp\0tama.tokyo.jp\0"
-"r.se\0saxo\0"
-"google\0"
-"xz.cn\0"
-"civilization.museum\0"
-"*.sch.uk\0"
-"livorno.it\0medecin.km\0"
-"s3.dualstack.ap-southeast-2.amazonaws.com\0"
-"fm.it\0owani.aomori.jp\0kasai.hyogo.jp\0"
-"midsund.no\0"
-"kaga.ishikawa.jp\0"
-"eigersund.no\0"
-"izumo.shimane.jp\0"
-"fr\xc3\xa6na.no\0"
-"taishi.osaka.jp\0quebec\0"
-"illustration.museum\0"
-"takinoue.hokkaido.jp\0"
-"vald-aosta.it\0audi\0"
-"barlettatraniandria.it\0samsclub\0"
-"marshalls\0no-ip.org\0"
-"\xe6\x85\x88\xe5\x96\x84\0"
-"froya.no\0"
-"ube.yamaguchi.jp\0"
-"kota.aichi.jp\0hitachi.ibaraki.jp\0wildlife.museum\0s\xc3\xb8mna.no\0"
-"bg.eu.org\0"
-"wtc\0dagestan.ru\0"
-"\xe6\x84\x9b\xe7\x9f\xa5.jp\0"
-"clubmed\0wtf\0"
-"tagajo.miyagi.jp\0"
-"krasnodar.su\0"
-"basel.museum\0beer\0"
-"niepce.museum\0"
-"amber.museum\0england.museum\0"
-"rishiri.hokkaido.jp\0"
-"vr.it\0dagestan.su\0"
-"bod\xc3\xb8.no\0"
-"b\xc3\xa1hcavuotna.no\0"
-"crotone.it\0"
-"viking\0"
-"tsuru.yamanashi.jp\0"
-"ba.leg.br\0"
-"kizu.kyoto.jp\0kvanangen.no\0trysil.no\0\xe5\x80\x8b\xe4\xba\xba.\xe9\xa6\x99\xe6\xb8\xaf\0"
-"midori.gunma.jp\0jewish.museum\0"
-"\xd0\xbe\xd1\x80\xd0\xb3.\xd1\x81\xd1\x80\xd0\xb1\0"
-"k12.wa.us\0bplaced.com\0"
-"shimamaki.hokkaido.jp\0"
-"barsy.mobi\0"
-"liaison\0"
+"defense.tn\0"
+"lefrak\0"
+"kawanishi.yamagata.jp\0nfl\0"
+"katsushika.tokyo.jp\0lawyer\0"
+"\xe7\xb5\x84\xe7\xb9\x94.hk\0pramerica\0"
+"df.leg.br\0"
+"airtel\0"
+"rakkestad.no\0"
+"tsuga.tochigi.jp\0"
+"sld.pa\0"
+"med.pro\0"
+"gs.sf.no\0"
+"ecologia.bo\0"
+"ngo\0"
+"everbank\0"
+"fm.it\0nishiazai.shiga.jp\0"
+"v\xc3\xa5gan.no\0is-into-cartoons.com\0"
+"def.br\0\xd8\xb3\xd9\x88\xd8\xaf\xd8\xa7\xd9\x86\0"
+"public.museum\0software\0"
+"seaport.museum\0"
+"hino.tokyo.jp\0"
+"austin.museum\0nhk\0"
+"writesthisblog.com\0"
+"mlbfan.org\0"
+"\xe7\xb6\xb2\xe7\xb5\xa1.cn\0abr.it\0varese.it\0hirokawa.fukuoka.jp\0"
+"kvanangen.no\0"
+"maceio.br\0"
+"saxo\0"
+"furniture.museum\0"
+"tirol\0"
+"saka.hiroshima.jp\0*.magentosite.cloud\0"
+"brunel.museum\0tingvoll.no\0eaton.mi.us\0daplie.me\0"
+"s\xc3\xbc""dtirol.it\0"
+"stadt.museum\0"
+"yamada.iwate.jp\0"
+"lib.tx.us\0"
+"ravenna.it\0cistron.nl\0"
+"bestbuy\0"
+"kamisato.saitama.jp\0"
+"\xc3\xa5seral.no\0drive\0drayddns.com\0"
+"corporation.museum\0"
+"adv.br\0"
+"jorpeland.no\0info.zm\0"
+"abeno.osaka.jp\0showa.yamanashi.jp\0"
+"k12.ar.us\0"
+"idv.hk\0medizinhistorisches.museum\0"
+"locker\0"
+"sampa.br\0tsumagoi.gunma.jp\0wiw.gov.pl\0"
+"allstate\0"
+"miyota.nagano.jp\0"
+"\xe9\x9d\x99\xe5\xb2\xa1.jp\0"
+"mihama.fukui.jp\0nishiokoppe.hokkaido.jp\0"
+"tsuiki.fukuoka.jp\0"
+"even\xc3\xa1\xc5\xa1\xc5\xa1i.no\0"
+"higashisumiyoshi.osaka.jp\0"
+"acct.pro\0movie\0"
+"nichinan.miyazaki.jp\0dell\0"
+"pizza\0"
+"trentinsud-tirol.it\0\xe0\xae\x87\xe0\xae\xb2\xe0\xae\x99\xe0\xaf\x8d\xe0\xae\x95\xe0\xaf\x88\0"
+"r\xc3\xb8""d\xc3\xb8y.no\0vikna.no\0s3-website-ap-southeast-1.amazonaws.com\0"
+"tone.ibaraki.jp\0cloudaccess.host\0"
+"touch.museum\0nesodden.no\0"
"fm.no\0"
-"hiroo.hokkaido.jp\0"
-"motegi.tochigi.jp\0"
-"kakuda.miyagi.jp\0\xe6\x89\x8b\xe6\x9c\xba\0"
-"ogano.saitama.jp\0"
-"fuchu.hiroshima.jp\0"
-"amusement.aero\0kaneyama.yamagata.jp\0"
-"ownprovider.com\0"
-"siljan.no\0"
-"mosvik.no\0"
-"red.sv\0"
-"tananger.no\0"
-"yamanouchi.nagano.jp\0"
+"\xe3\x82\xb3\xe3\x83\xa0\0"
+"khmelnytskyi.ua\0"
+"jgora.pl\0"
+"is-with-theband.com\0"
+"gok.pk\0pr.us\0"
+"kotoura.tottori.jp\0"
+"minamiashigara.kanagawa.jp\0"
+"kyoto.jp\0"
+"satx.museum\0brumunddal.no\0"
+"curitiba.br\0"
+"bc.ca\0\xe7\xb6\xb2\xe7\xb5\xa1.hk\0uscountryestate.museum\0hockey\0"
+"kawakami.nara.jp\0"
+"ringsaker.no\0"
+"suwa.nagano.jp\0"
+"t\xc3\xb8nsberg.no\0"
+"sf.no\0mk.ua\0"
+"komagane.nagano.jp\0murakami.niigata.jp\0"
+"fjell.no\0events\0"
+"pioneer\0"
+"dyndns-mail.com\0"
+"hizen.saga.jp\0"
+"r.se\0"
+"health.museum\0no-ip.info\0"
+"elblag.pl\0eurovision\0international\0"
+"nl.ca\0user.party.eus\0is-a-bookkeeper.com\0"
+"\xe9\xb3\xa5\xe5\x8f\x96.jp\0ogasawara.tokyo.jp\0\xe8\xaf\xba\xe5\x9f\xba\xe4\xba\x9a\0"
+"\xd8\xa7\xd8\xa8\xd9\x88\xd8\xb8\xd8\xa8\xd9\x8a\0"
+"capebreton.museum\0s\xc3\xb8ndre-land.no\0"
+"niigata.jp\0!city.kawasaki.jp\0\xd8\xa7\xd9\x84\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x86\0"
+"now\0"
+"london\0"
+"ishikawa.jp\0samukawa.kanagawa.jp\0"
+"kunstsammlung.museum\0"
+"yamato.kumamoto.jp\0"
+"australia.museum\0"
+"rome.it\0tsuru.yamanashi.jp\0"
+"wake.okayama.jp\0wloclawek.pl\0"
+"chigasaki.kanagawa.jp\0"
+"ngrok.io\0noip.us\0"
+"etc.br\0seki.gifu.jp\0"
+"lincoln.museum\0il.eu.org\0"
+"\xe5\xba\x83\xe5\xb3\xb6.jp\0"
+"eastcoast.museum\0sor-fron.no\0ipiranga\0"
+"nra\0twmail.cc\0"
+"\xc3\xa5krehamn.no\0lib.vt.us\0"
+"anan.tokushima.jp\0yamanobe.yamagata.jp\0"
+"ichiba.tokushima.jp\0"
+"f\xc3\xb8rde.no\0"
+"obi\0"
+"garden\0"
+"inami.wakayama.jp\0"
+"photos\0"
+"crafting.xyz\0"
+"parti.se\0"
+"svizzera.museum\0firewall-gateway.de\0"
+"pharmaciens.km\0chernihiv.ua\0desi\0"
+"nrw\0"
+"shiki.saitama.jp\0"
+"caa.aero\0sor-odal.no\0cc.ia.us\0"
+"norddal.no\0hu.eu.org\0ie.eu.org\0"
+"sakai.fukui.jp\0"
+"balsfjord.no\0bloxcms.com\0"
+"\xe7\x8f\xa0\xe5\xae\x9d\0shiftedit.io\0"
+"kitanakagusuku.okinawa.jp\0"
+"rc.it\0"
+"gs.nl.no\0rv.ua\0"
+"kanie.aichi.jp\0"
+"dnipropetrovsk.ua\0tube\0"
+"fuso.aichi.jp\0"
+"loppa.no\0tiffany\0"
+"reklam.hu\0"
+"numata.gunma.jp\0ntt\0"
+"sa.edu.au\0"
+"verbania.it\0"
+"shimabara.nagasaki.jp\0dnsalias.net\0"
+"nesseby.no\0plumbing\0"
+"servehttp.com\0"
+"onjuku.chiba.jp\0adv.mz\0"
+"kids.museum\0motorcycle.museum\0"
+"kamioka.akita.jp\0ine.kyoto.jp\0"
+"nationalheritage.museum\0gratis\0"
+"off\0"
+"gausdal.no\0condos\0"
+"daisen.akita.jp\0"
+"openair.museum\0gaular.no\0\xc3\xb8ystre-slidre.no\0"
+"lib.or.us\0"
+"uw.gov.pl\0"
+"ismaili\0"
+"furukawa.miyagi.jp\0kitakata.miyazaki.jp\0"
+"nagawa.nagano.jp\0"
+"s\xc3\xb8mna.no\0lpusercontent.com\0"
+"pp.az\0yomitan.okinawa.jp\0"
+"idv.tw\0"
+"estate\0"
+"caravan\0"
+"yamagata.ibaraki.jp\0"
+"b\xc3\xa5tsfjord.no\0"
+"nara.jp\0"
+"gliding.aero\0cc.as.us\0"
+"yamazoe.nara.jp\0"
+"\xe7\x9f\xb3\xe5\xb7\x9d.jp\0democrat\0"
+"iwate.jp\0"
+"skien.no\0"
+"taxi.br\0takagi.nagano.jp\0"
+"embetsu.hokkaido.jp\0kuju.oita.jp\0"
+"servehumour.com\0"
+"dr\xc3\xb8""bak.no\0"
+"minamiminowa.nagano.jp\0yamatotakada.nara.jp\0toshima.tokyo.jp\0"
+"fineart.museum\0storfjord.no\0nyc\0"
+"vall\xc3\xa9""eaoste.it\0"
+"statebank\0"
+"is-a-nascarfan.com\0""3utilities.com\0"
+"nachikatsuura.wakayama.jp\0"
+"fin.ec\0"
+"dali.museum\0songdalen.no\0"
+"obama.fukui.jp\0"
+"imabari.ehime.jp\0"
+"trysil.no\0s3.dualstack.us-east-1.amazonaws.com\0"
+"\xe0\xb2\xad\xe0\xb2\xbe\xe0\xb2\xb0\xe0\xb2\xa4\0"
+"ashoro.hokkaido.jp\0"
+"hembygdsforbund.museum\0"
+"\xe6\x89\x8b\xe8\xa1\xa8\0"
+"conf.lv\0"
+"nl.no\0feedback\0shouji\0"
+"iglesias-carbonia.it\0hashikami.aomori.jp\0"
+"sakura.tochigi.jp\0"
+"p.bg\0emerck\0"
+"sakaiminato.tottori.jp\0"
+"cleaning\0"
+"shijonawate.osaka.jp\0hino.tottori.jp\0nanyo.yamagata.jp\0"
+"\xe6\x95\x99\xe8\x82\xb2.hk\0indiana.museum\0"
+"izu.shizuoka.jp\0"
+"is-a-techie.com\0"
+"adult\0"
+"equipment\0"
+"discovery.museum\0pharmacy\0"
+"ia.us\0"
+"nishihara.okinawa.jp\0izumiotsu.osaka.jp\0"
+"nasu.tochigi.jp\0"
+"lib.vi.us\0servegame.org\0noip.me\0pantheonsite.io\0"
+"sakegawa.yamagata.jp\0"
+"ass.km\0skaun.no\0"
+"armenia.su\0"
+"half.host\0"
+"tsubata.ishikawa.jp\0"
+"servequake.com\0"
+"9.bg\0v\xc3\xa6r\xc3\xb8y.no\0gr.eu.org\0"
+"yachiyo.ibaraki.jp\0fujisawa.kanagawa.jp\0urawa.saitama.jp\0"
+"maryland.museum\0"
+"taki.mie.jp\0"
"\xe6\x96\xb0\xe9\x97\xbb\0"
-"remotewd.com\0"
-"flor\xc3\xb8.no\0cloudns.pw\0"
-"ditchyourip.com\0"
-"hida.gifu.jp\0"
-"sogne.no\0"
-"hopto.me\0"
-"now-dns.top\0"
-"vestnes.no\0"
-"yoshinogari.saga.jp\0"
-"reggio-calabria.it\0cartoonart.museum\0"
-"shinto.gunma.jp\0scholarships\0"
-"mansions.museum\0readmyblog.org\0"
-"media\0"
-"yosemite.museum\0no-ip.info\0"
-"newport.museum\0"
-"kitagata.saga.jp\0"
-"american.museum\0"
-"xin\0"
-"tatebayashi.gunma.jp\0"
-"jefferson.museum\0casino\0\xd9\x83\xd9\x88\xd9\x85\0hr.eu.org\0"
-"tsumagoi.gunma.jp\0"
-"ne.jp\0"
-"k12.nv.us\0"
-"withyoutube.com\0"
-"aguni.okinawa.jp\0ne.ke\0civilwar.museum\0"
-"p.bg\0"
-"santoandre.br\0yahiko.niigata.jp\0songdalen.no\0"
-"fiat\0homes\0"
-"schweiz.museum\0de.us\0"
-"yasuoka.nagano.jp\0nextdirect\0"
-"ne.kr\0"
-"shimofusa.chiba.jp\0project.museum\0"
-"nobeoka.miyazaki.jp\0"
-"\xe7\x8f\xa0\xe5\xae\x9d\0"
-"mutsu.aomori.jp\0"
-"voyage\0"
-"is-a-geek.com\0"
-"lillesand.no\0"
-"tottori.tottori.jp\0"
-"wada.nagano.jp\0rr.leg.br\0"
-"mat.br\0"
-"chernihiv.ua\0cloudaccess.host\0"
-"planetarium.museum\0is-a-cpa.com\0"
-"www.ro\0grozny.su\0"
-"nikolaev.ua\0"
-"am.leg.br\0"
-"fido\0softbank\0"
-"tjome.no\0"
-"kuzumaki.iwate.jp\0appspot.com\0"
-"loppa.no\0clinic\0"
-"\xe6\x8b\x9b\xe8\x81\x98\0"
-"kamaishi.iwate.jp\0"
-"\xe3\x82\xaf\xe3\x83\xa9\xe3\x82\xa6\xe3\x83\x89\0"
+"ilawa.pl\0"
+"fundacio.museum\0one\0travelersinsurance\0"
+"wada.nagano.jp\0\xd8\xa7\xd9\x84\xd8\xb9\xd9\x84\xd9\x8a\xd8\xa7\xd9\x86\0"
+"ong\0*.elb.amazonaws.com\0from-ks.com\0"
+"nord-aurdal.no\0\xd8\xaa\xd9\x88\xd9\x86\xd8\xb3\0"
+"ninohe.iwate.jp\0"
+"otsuki.yamanashi.jp\0onl\0"
+"meguro.tokyo.jp\0"
+"trust.museum\0zhytomyr.ua\0"
+"tarui.gifu.jp\0"
+"ballooning.aero\0"
+"miyazaki.jp\0vpndns.net\0"
+"railroad.museum\0"
+"blog.bo\0capitalone\0"
+"aki.kochi.jp\0"
+"chintai\0rackmaze.com\0"
+"blog.br\0"
+"ooo\0"
+"bialystok.pl\0"
+"manno.kagawa.jp\0shichikashuku.miyagi.jp\0"
+"med.br\0scor\0"
+"scot\0"
+"fvg.it\0toyako.hokkaido.jp\0discover\0"
+"miho.ibaraki.jp\0"
+"oppegard.no\0"
+"as.us\0"
+"sd.cn\0malbork.pl\0"
+"virginia.museum\0"
+"higashitsuno.kochi.jp\0"
+"mi.it\0"
+"oksnes.no\0shangrila\0"
+"gyeongnam.kr\0limited\0rj.leg.br\0"
+"k12.ks.us\0"
+"brescia.it\0"
+"jeju.kr\0management\0podzone.net\0"
+"vads\xc3\xb8.no\0audi\0"
+"outsystemscloud.com\0"
+"funahashi.toyama.jp\0"
+"autos\0wellbeingzone.co.uk\0"
+"forlicesena.it\0olawa.pl\0ostrowwlkp.pl\0"
+"vanylven.no\0from-ms.com\0from-nc.com\0"
+"asuke.aichi.jp\0flynnhosting.net\0"
"r\xc3\xa6lingen.no\0"
-"narashino.chiba.jp\0"
-"takayama.gifu.jp\0"
-"indianmarket.museum\0"
-"rs.leg.br\0sc.leg.br\0"
-"tienda\0"
-"zagan.pl\0mein-iserv.de\0"
-"dnsdojo.net\0"
-"texas.museum\0"
-"miyagi.jp\0artdeco.museum\0global\0"
-"blockbuster\0guitars\0"
-"kasuga.hyogo.jp\0tube\0servegame.com\0"
-"gemological.museum\0fuossko.no\0"
-"taito.tokyo.jp\0"
-"kami.kochi.jp\0"
-"myfritz.net\0"
-"tula.su\0"
-"wanouchi.gifu.jp\0"
-"ibaraki.ibaraki.jp\0ar.com\0"
-"from-ny.net\0neat-url.com\0"
-"kayabe.hokkaido.jp\0grozny.ru\0"
-"ne.pw\0"
-"s\xc3\xa1lat.no\0"
-"onyourside\0from-id.com\0"
-"anani.br\0"
-"cc.tx.us\0"
-"k\xc3\xa1r\xc3\xa1\xc5\xa1johka.no\0"
-"emilia-romagna.it\0frog.museum\0"
-"phoenix.museum\0km.ua\0"
-"nx.cn\0tsuwano.shimane.jp\0"
-"art.museum\0"
-"*.0emm.com\0"
-"lexus\0"
+"med.ec\0org\0delivery\0n4t.co\0"
+"vic.edu.au\0med.ee\0pay\0golffan.us\0"
+"kinko.kagoshima.jp\0"
+"marche.it\0"
+"*.compute-1.amazonaws.com\0"
+"porsgrunn.no\0"
+"tochio.niigata.jp\0"
+"unicom\0"
+"konsulat.gov.pl\0"
+"lakas.hu\0dyndns-ip.com\0"
+"heritage.museum\0starnberg.museum\0dscloud.me\0"
+"yamatsuri.fukushima.jp\0beer\0barsy.shop\0"
+"\xe5\xb1\xb1\xe6\xa2\xa8.jp\0komaki.aichi.jp\0myoko.niigata.jp\0"
+"veneto.it\0tobetsu.hokkaido.jp\0semine.miyagi.jp\0"
+"movimiento.bo\0"
+"hammerfest.no\0"
+"zakopane.pl\0"
+"quebec\0fuettertdasnetz.de\0"
+"nishiwaki.hyogo.jp\0"
+"brandywinevalley.museum\0s3.dualstack.eu-west-2.amazonaws.com\0"
+"fiat\0"
+"granvin.no\0cc.mi.us\0"
+"grp.lk\0pvt.k12.ma.us\0"
+"name.hr\0sugito.saitama.jp\0"
+"mishima.fukushima.jp\0joetsu.niigata.jp\0"
+"suzuka.mie.jp\0"
+"\xe6\x85\x88\xe5\x96\x84\0"
+"is-an-engineer.com\0"
+"minami.tokushima.jp\0ott\0"
+"nationwide\0from-sc.com\0"
+"potenza.it\0career\0"
+"\xe6\x94\xbf\xe5\xba\x9c.hk\0panasonic\0"
+"\xd1\x81\xd0\xb0\xd0\xb9\xd1\x82\0"
+"goshiki.hyogo.jp\0"
+"delmenhorst.museum\0zoology.museum\0lib.gu.us\0"
+"name.et\0\xe6\x89\x8b\xe6\x9c\xba\0"
+"\xd9\x83\xd9\x88\xd9\x85\0"
+"*.platform.sh\0"
+"yachts\0"
+"svelvik.no\0"
+"pet\0"
+"naturalsciences.museum\0jolster.no\0"
+"massacarrara.it\0"
+"med.ht\0ovh\0"
+"trentinsuedtirol.it\0wazuka.kyoto.jp\0"
+"county.museum\0oxford.museum\0"
+"inf.br\0"
+"ushiku.ibaraki.jp\0accountant\0"
+"fido\0"
+"kuroishi.aomori.jp\0"
+"metlife\0"
+"rsvp\0"
+"narvik.no\0mytuleap.com\0freebox-os.com\0"
+"barefoot\0"
+"bronnoy.no\0smile\0"
+"trentino-stirol.it\0"
+"inf.cu\0"
+"bt.it\0tamaki.mie.jp\0"
+"pp.se\0pp.ru\0"
+"takarazuka.hyogo.jp\0"
+"name.cy\0"
+"misasa.tottori.jp\0phd\0"
+"correios-e-telecomunica\xc3\xa7\xc3\xb5""es.museum\0"
+"kazuno.akita.jp\0"
+"pavia.it\0"
+"name.eg\0"
+"kawaminami.miyazaki.jp\0"
+"photography.museum\0"
+"pid\0"
+"california.museum\0"
+"kudamatsu.yamaguchi.jp\0"
+"sakurai.nara.jp\0"
+"fin.tn\0"
+"travel\0"
+"k12.mo.us\0pp.ua\0"
+"pin\0"
+"szczecin.pl\0zagan.pl\0"
+"\xe6\x8b\x9b\xe8\x81\x98\0"
+"is-lost.org\0"
+"name.az\0"
+"yazu.tottori.jp\0"
+"cc.sd.us\0"
+"catania.it\0"
+"aknoluokta.no\0"
+"med.ly\0fredrikstad.no\0"
+"um.gov.pl\0"
+"montreal.museum\0"
+"sosa.chiba.jp\0matsumoto.nagano.jp\0loan\0instantcloud.cn\0"
+"hokuto.hokkaido.jp\0odawara.kanagawa.jp\0"
+"is-a-hard-worker.com\0"
+"\xe5\xb2\xa1\xe5\xb1\xb1.jp\0"
+"chikuhoku.nagano.jp\0mi.th\0"
+"cartoonart.museum\0"
+"nieruchomosci.pl\0"
+"hammarfeasta.no\0"
+"seiro.niigata.jp\0"
+"ohi.fukui.jp\0"
+"lib.nh.us\0"
+"expert\0"
+"ddnsfree.com\0yombo.me\0"
+"trentin-suedtirol.it\0"
+"newjersey.museum\0\xe4\xb8\xad\xe5\x9b\xbd\0"
+"nerima.tokyo.jp\0"
+"p.se\0"
+"vda.it\0aoste.it\0ic.gov.pl\0"
+"koeln.museum\0r\xc3\xa5""de.no\0"
+"muko.kyoto.jp\0govt.nz\0"
+"tcm.museum\0austrheim.no\0"
+"vaporcloud.io\0"
+"toon.ehime.jp\0moriguchi.osaka.jp\0"
+"rightathome\0"
+"torahime.shiga.jp\0gmail\0ba.leg.br\0"
+"med.om\0institute\0systems\0"
+"moroyama.saitama.jp\0prod\0"
+"mi.us\0\xe4\xb8\xad\xe5\x9c\x8b\0"
+"hinode.tokyo.jp\0prof\0"
+"med.pa\0"
+"yasuda.kochi.jp\0hakuba.nagano.jp\0"
+"from-dc.com\0"
+"vestre-toten.no\0"
+"shinonsen.hyogo.jp\0"
+"k12.wa.us\0"
+"med.pl\0"
+"barsy.net\0"
+"usdecorativearts.museum\0osteroy.no\0pnc\0dray-dns.de\0"
+"tsushima.aichi.jp\0yukuhashi.fukuoka.jp\0kiso.nagano.jp\0fukaya.saitama.jp\0"
+"club.tw\0k12.ga.us\0"
+"taranto.it\0"
+"calabria.it\0uchinomi.kagawa.jp\0red.sv\0"
+"kr\xc3\xa5""anghke.no\0"
+"miki.hyogo.jp\0"
"oguchi.aichi.jp\0"
-"television.museum\0"
-"mil.ac\0best\0dyndns-server.com\0"
-"naturalsciences.museum\0"
-"mil.ae\0"
-"obuse.nagano.jp\0"
-"mil.al\0heritage.museum\0skj\xc3\xa5k.no\0"
-"bytom.pl\0"
-"auto\0"
-"ama.shimane.jp\0"
-"mil.ba\0steiermark.museum\0"
-"mil.ar\0ap.leg.br\0"
-"eisenbahn.museum\0"
-"murakami.niigata.jp\0"
-"vestre-slidre.no\0"
-"balsan-su\xcc\x88""dtirol.it\0"
-"nis.za\0"
+"film\0"
+"narita.chiba.jp\0us.gov.pl\0"
+"wolterskluwer\0"
+"mil.ac\0"
+"mil.ae\0association.aero\0"
+"pruszkow.pl\0"
+"\xd0\xb4\xd0\xb5\xd1\x82\xd0\xb8\0"
+"\xe7\xb6\xb2\xe8\xb7\xaf.tw\0"
+"mil.al\0higashiizumo.shimane.jp\0run.app\0"
+"trondheim.no\0"
+"scjohnson\0solar\0"
+"cam.it\0"
+"mil.ba\0kviteseid.no\0"
+"mil.ar\0js.cn\0"
+"americanart.museum\0"
+"med.sa\0"
+"loft\0"
+"med.sd\0"
+"k12.ct.us\0"
"mil.az\0"
-"rj.gov.br\0"
-"fot.br\0landrover\0"
-"3.bg\0"
-"crew.aero\0mil.bo\0"
-"kainan.tokushima.jp\0"
-"mil.br\0sauherad.no\0ne.ug\0prudential\0dyndns-mail.com\0"
-"medecin.fr\0"
-"is-very-evil.org\0"
-"ne.tz\0blogspot.com.cy\0rn.leg.br\0"
-"sera.hiroshima.jp\0accenture\0"
-"fujimi.saitama.jp\0malopolska.pl\0"
-"gamvik.no\0"
+"sund.no\0"
+"emiliaromagna.it\0yashiro.hyogo.jp\0kaizuka.osaka.jp\0skoczow.pl\0"
+"alta.no\0"
+"\xe5\xa5\x88\xe8\x89\xaf.jp\0"
+"mil.bo\0"
+"foz.br\0tomi.nagano.jp\0"
+"guide\0"
+"mil.br\0arezzo.it\0"
+"minowa.nagano.jp\0"
+"inf.mk\0"
+"rr.leg.br\0"
+"mosvik.no\0termez.su\0"
+"best\0"
"mil.by\0"
-"kurate.fukuoka.jp\0omi.niigata.jp\0hockey\0"
-"mil.cl\0"
-"mil.cn\0ne.us\0"
-"mil.co\0\xe5\xb2\x90\xe9\x98\x9c.jp\0"
-"blogspot.com.ee\0"
-"gildeskal.no\0film\0"
-"\xd9\x85\xd8\xb5\xd8\xb1\0blogspot.com.eg\0"
-"fet.no\0"
-"nissan\0wpdevcloud.com\0"
-"east-kazakhstan.su\0hopto.org\0"
-"blogspot.com.ar\0"
-"mil.do\0nakasatsunai.hokkaido.jp\0missile.museum\0"
-"blogspot.com.au\0"
+"\xd9\x85\xd8\xb5\xd8\xb1\0"
+"mil.cl\0\xd0\xbc\xd0\xbe\xd1\x81\xd0\xba\xd0\xb2\xd0\xb0\0"
+"collection.museum\0fitjar.no\0"
+"mil.cn\0"
+"mil.co\0"
+"ra.it\0"
+"scapp.io\0"
+"auto\0lima.zone\0"
+"asso.fr\0"
+"catering\0"
+"mitsue.nara.jp\0kushimoto.wakayama.jp\0"
+"seat\0"
+"barclays\0"
+"aq.it\0ba.it\0"
+"egersund.no\0tokke.no\0"
+"\xe0\xb9\x80\xe0\xb8\x99\xe0\xb9\x87\xe0\xb8\x95.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0"
+"k12.ak.us\0"
+"mil.do\0pro\0cc.tx.us\0"
+"bss.design\0"
+"christiansburg.museum\0"
+"asso.gp\0"
"mil.ec\0"
-"ro.leg.br\0"
-"sx.cn\0trentino.it\0nissay\0noip.us\0"
-"mil.eg\0cesena-forli.it\0"
-"inawashiro.fukushima.jp\0"
-"auspost\0"
-"vevelstad.no\0nyc.mn\0"
-"is-a-geek.org\0"
-"design\0blogspot.com.br\0"
-"sellsyourhome.org\0"
-"\xe0\xae\x87\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xbe\0"
-"collection.museum\0"
-"blogspot.com.by\0soundcast.me\0"
-"surgery\0"
-"shichinohe.aomori.jp\0*.alces.network\0"
-"scor\0"
-"scot\0s3-website.eu-west-2.amazonaws.com\0blogspot.com.co\0"
-"ca-central-1.elasticbeanstalk.com\0"
-"gliwice.pl\0gda.pl\0"
-"lig.it\0miyoshi.tokushima.jp\0kahoku.yamagata.jp\0"
-"mein-vigor.de\0"
-"mil.ge\0"
-"\xc3\xb8rsta.no\0mragowo.pl\0"
-"honda\0"
-"mil.gh\0vossevangen.no\0"
-"\xe5\x85\xac\xe5\x8f\xb8.cn\0xfinity\0"
-"globo\0"
-"xxx\0app.os.fedoraproject.org\0"
-"yokosuka.kanagawa.jp\0"
-"corsica\0"
-"s\xc3\xb8r-odal.no\0omega\0"
-"mil.gt\0is-a-hunter.com\0"
-"\xe5\x85\xac\xe5\x8f\xb8.hk\0honjo.akita.jp\0"
-"chimkent.su\0"
-"cs.it\0twmail.cc\0"
-"academia.bo\0"
-"select\0"
-"loan\0place\0"
-"mil.hn\0tuva.su\0"
-"j\xc3\xb8rpeland.no\0xyz\0blogspot.com.es\0"
-"oppdal.no\0rzeszow.pl\0"
-"sko.gov.pl\0press\0"
-"mil.id\0"
-"taishin.fukushima.jp\0tokuyama.yamaguchi.jp\0"
-"napoli.it\0correios-e-telecomunica\xc3\xa7\xc3\xb5""es.museum\0"
+"sd.us\0pru\0s3-ap-south-1.amazonaws.com\0"
+"rs.leg.br\0sc.leg.br\0"
+"mil.eg\0"
+"ena.gifu.jp\0"
+"passenger-association.aero\0racing\0"
+"shirako.chiba.jp\0"
+"miyoshi.tokushima.jp\0"
+"dance\0"
+"sakyo.kyoto.jp\0nome.pt\0"
+"\xd8\xa8\xd8\xa7\xd8\xb1\xd8\xaa\0"
"fire\0"
+"asso.ht\0yoshida.saitama.jp\0hotmail\0servebbs.net\0"
+"wa.gov.au\0"
+"nuremberg.museum\0fam.pk\0"
+"ingatlan.hu\0"
+"aibetsu.hokkaido.jp\0"
+"kumano.mie.jp\0am.leg.br\0"
+"pub\0"
+"cooperativa.bo\0"
+"verona.it\0"
+"mil.ge\0association.museum\0"
+"niikappu.hokkaido.jp\0kawahara.tottori.jp\0"
+"bmoattachments.org\0"
+"mil.gh\0fish\0"
+"s3-eu-west-2.amazonaws.com\0"
+"asso.bj\0nagano.jp\0shinyoshitomi.fukuoka.jp\0starhub\0"
+"kagoshima.jp\0"
+"seek\0"
+"mil.gt\0"
+"vaapste.no\0"
+"yakage.okayama.jp\0name.vn\0"
+"eastafrica.museum\0averoy.no\0"
+"asso.ci\0kv.ua\0"
+"es.gov.br\0mil.hn\0"
+"freeboxos.com\0"
+"venice.it\0"
+"pwc\0"
+"mil.id\0"
+"uda.nara.jp\0"
+"cc.nj.us\0"
+"kouzushima.tokyo.jp\0"
+"web.bo\0meland.no\0"
+"radom.pl\0"
+"planetarium.museum\0fed.us\0"
"mil.in\0"
-"eaton.mi.us\0"
+"steigen.no\0"
"mil.iq\0"
-"badajoz.museum\0p.se\0"
-"lawyer\0"
-"mibu.tochigi.jp\0\xe8\xb0\xb7\xe6\xad\x8c\0"
-"otoineppu.hokkaido.jp\0"
-"lacaixa\0"
-"fujioka.gunma.jp\0"
-"applinzi.com\0"
-"fish\0bplaced.net\0"
-"mil.jo\0"
-"xs4all.space\0"
-"onjuku.chiba.jp\0"
-"przeworsk.pl\0"
-"mo\xc3\xa5reke.no\0pomorskie.pl\0"
+"yokaichiba.chiba.jp\0name.tj\0"
+"web.co\0yolasite.com\0"
+"inf.ua\0"
+"asso.dz\0name.tr\0"
+"name.tt\0faith\0"
+"mil.jo\0nativeamerican.museum\0"
+"wroc.pl\0"
+"gildeskal.no\0"
+"shichinohe.aomori.jp\0kanoya.kagoshima.jp\0privatizehealthinsurance.net\0"
+"n.bg\0"
+"kanegasaki.iwate.jp\0ogawara.miyagi.jp\0\xe0\xae\x87\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xbe\0"
+"website\0dedyn.io\0ddnss.de\0"
+"ruhr\0rn.leg.br\0"
"mil.kg\0"
-"ba.gov.br\0jogasz.hu\0nanao.ishikawa.jp\0"
-"isesaki.gunma.jp\0"
-"mochizuki.nagano.jp\0mil.km\0"
-"himi.toyama.jp\0camera\0"
-"fuel.aero\0servep2p.com\0"
-"mil.kr\0ostrowwlkp.pl\0"
-"morimachi.shizuoka.jp\0"
-"*.compute.amazonaws.com\0"
-"iron.museum\0il.eu.org\0"
-"haram.no\0"
+"web.do\0hellas.museum\0fr\xc3\xb8ya.no\0"
+"nakamichi.yamanashi.jp\0"
+"dnsalias.org\0"
+"kartuzy.pl\0"
+"mil.km\0"
+"kmpsp.gov.pl\0"
+"pixolino.com\0telebit.io\0"
+"barsy.site\0"
+"matsuura.nagasaki.jp\0mil.kr\0"
+"te.it\0"
"mil.kz\0"
-"austevoll.no\0"
-"eu-central-1.elasticbeanstalk.com\0"
-"tonaki.okinawa.jp\0karikatur.museum\0"
-"family\0"
-"nonoichi.ishikawa.jp\0"
-"mil.lv\0"
-"mil.mg\0tolga.no\0rsvp\0"
-"tamamura.gunma.jp\0osteroy.no\0"
-"no-ip.net\0"
-"net.ac\0"
-"net.ae\0miyakonojo.miyazaki.jp\0loft\0"
-"net.af\0belem.br\0"
-"net.ag\0"
-"guovdageaidnu.no\0workisboring.com\0"
-"net.ai\0mil.mv\0"
-"mil.ng\0knowsitall.info\0hu.eu.org\0ie.eu.org\0"
-"net.al\0mil.my\0mil.ni\0"
-"mil.mz\0you\0"
-"yusuhara.kochi.jp\0"
-"bearalv\xc3\xa1hki.no\0"
-"net.ba\0yalta.ua\0"
-"net.ar\0net.bb\0mil.no\0"
-"bushey.museum\0"
-"money\0"
-"net.au\0"
-"net.bh\0"
-"\xd7\xa7\xd7\x95\xd7\x9d\0"
-"net.az\0coop.ht\0"
-"hs.kr\0"
-"nov.ru\0"
-"net.bm\0mil.nz\0"
-"net.bn\0"
-"net.bo\0saves-the-whales.com\0"
-"sa.gov.au\0ladbrokes\0"
-"net.br\0sanok.pl\0"
-"net.bs\0"
-"net.bt\0"
-"ravendb.run\0"
-"yasuda.kochi.jp\0\xe4\xbf\xa1\xe6\x81\xaf\0"
-"jaguar\0myasustor.com\0"
+"oirm.gov.pl\0"
+"deporte.bo\0temasek\0barsy.pro\0"
+"target\0wien\0"
+"ap.leg.br\0"
+"yamagata.yamagata.jp\0"
+"moss.no\0"
+"ama.shimane.jp\0mil.lv\0ro.leg.br\0"
+"7.bg\0mil.mg\0jondal.no\0s3.dualstack.sa-east-1.amazonaws.com\0is-a-patsfan.org\0"
+"turin.it\0dazaifu.fukuoka.jp\0miyada.nagano.jp\0"
+"ternopil.ua\0"
+"miyoshi.hiroshima.jp\0"
+"tx.us\0marshalls\0"
+"higashikawa.hokkaido.jp\0"
+"eisenbahn.museum\0"
+"horse\0"
+"cloudfront.net\0"
+"culturalcenter.museum\0"
+"kawachinagano.osaka.jp\0"
+"mil.mv\0gda.pl\0"
+"mil.ng\0forde.no\0"
+"mil.my\0mil.ni\0lillehammer.no\0"
+"pn.it\0yamakita.kanagawa.jp\0nozawaonsen.nagano.jp\0mil.mz\0"
+"name.qa\0"
+"ntr.br\0tomigusuku.okinawa.jp\0name.pr\0"
+"web.gu\0mil.no\0"
+"barsy.pub\0"
+"undersea.museum\0"
+"fujisawa.iwate.jp\0"
+"\xd0\xb0\xd0\xba.\xd1\x81\xd1\x80\xd0\xb1\0"
+"fi.cr\0susono.shizuoka.jp\0"
+"murata.miyagi.jp\0cloud.metacentrum.cz\0"
+"voyage\0"
+"bulsan-s\xc3\xbc""dtirol.it\0mil.nz\0"
+"name.na\0nes.buskerud.no\0"
+"shinjo.okayama.jp\0"
+"whaling.museum\0podzone.org\0fr.eu.org\0"
+"web.id\0aichi.jp\0health.nz\0"
+"sunndal.no\0lancia\0s3-website-us-west-1.amazonaws.com\0"
+"name.mv\0"
+"name.ng\0"
+"name.my\0vestby.no\0cc.de.us\0"
+"azumino.nagano.jp\0nagasaki.nagasaki.jp\0"
"mil.pe\0"
-"net.ci\0yokote.akita.jp\0"
-"net.bz\0"
-"\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86.ir\0mil.ph\0prod\0noip.me\0"
-"mykolaiv.ua\0nov.su\0"
-"net.cm\0prof\0"
-"net.cn\0"
-"net.co\0mil.pl\0"
-"kochi.kochi.jp\0"
-"presse.km\0discount\0"
-"blogspot.com.mt\0"
-"mil.qa\0"
-"net.cu\0"
-"takahagi.ibaraki.jp\0blogspot.com.ng\0"
-"net.cw\0tysfjord.no\0"
-"coop.br\0humanities.museum\0\xe0\xa6\xad\xe0\xa6\xbe\xe0\xa6\xb0\xe0\xa6\xa4\0se.leg.br\0"
-"net.cy\0geelvinck.museum\0volyn.ua\0"
-"sc.cn\0kumiyama.kyoto.jp\0"
-"mil.py\0"
-"net.dm\0ikeda.nagano.jp\0"
-"net.do\0"
-"ak.us\0"
-"ipifony.net\0"
-"net.ec\0"
-"h\xc3\xb8ylandet.no\0pulawy.pl\0"
-"seto.aichi.jp\0"
-"net.eg\0\xc3\xb8vre-eiker.no\0"
-"venice.it\0is-a-player.com\0"
-"net.dz\0"
-"sciencesnaturelles.museum\0sandvik\0"
-"oh.us\0"
-"kumano.mie.jp\0"
-"rr.gov.br\0"
-"ms.it\0nieruchomosci.pl\0"
-"xerox\0"
-"trd.br\0\xe6\x95\x99\xe8\x82\xb2.hk\0presse.ml\0"
-"ogori.fukuoka.jp\0hokksund.no\0"
-"trentino-aadige.it\0tsurugi.ishikawa.jp\0cc.mn.us\0"
-"net.et\0"
-"nanae.hokkaido.jp\0caravan\0"
-"\xe0\xa4\xb8\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xa0\xe0\xa4\xa8\0"
-"gjovik.no\0"
-"mil.ru\0endoftheinternet.org\0"
-"council.aero\0"
-"mil.rw\0"
-"am.gov.br\0mil.sh\0"
-"bolt.hu\0hotel.tz\0"
-"tsukiyono.gunma.jp\0bahcavuotna.no\0"
-"deatnu.no\0"
-"maringa.br\0usui.fukuoka.jp\0bnpparibas\0blogspot.com.tr\0"
-"dyndns-pics.com\0"
-"nogi.tochigi.jp\0"
-"tono.iwate.jp\0"
-"n.bg\0net.ge\0"
-"yun\0"
-"net.gg\0mil.st\0"
-"lur\xc3\xb8y.no\0dc.us\0"
-"taketa.oita.jp\0"
-"net.gl\0mil.sy\0s3-eu-west-3.amazonaws.com\0"
-"bn.it\0ms.kr\0malvik.no\0mil.tj\0"
-"rs.gov.br\0sc.gov.br\0net.gn\0nakagawa.fukuoka.jp\0"
-"net.gp\0oirase.aomori.jp\0oketo.hokkaido.jp\0mil.tm\0ivanovo.su\0"
-"eurovision\0"
-"net.gr\0mil.to\0"
-"rochester.museum\0"
-"net.gt\0tec.mi.us\0"
-"net.gu\0sardegna.it\0koshu.yamanashi.jp\0yorkshire.museum\0tr\xc3\xa6na.no\0mil.tr\0"
-"net.gy\0trentino-altoadige.it\0"
+"ostroleka.pl\0"
+"*.landing.myjino.ru\0"
+"munakata.fukuoka.jp\0mil.ph\0"
+"revista.bo\0mining.museum\0"
+"mil.pl\0"
+"latrobe\0"
+"katsuura.chiba.jp\0"
+"engerdal.no\0lib.ny.us\0"
+"wakayama.wakayama.jp\0"
+"sandefjord.no\0mil.qa\0k12.ky.us\0"
+"\xe5\x80\x8b\xe4\xba\xba.hk\0from-mn.com\0"
+"entertainment.aero\0love\0"
+"balsan-s\xc3\xbc""dtirol.it\0ina.ibaraki.jp\0okinoshima.shimane.jp\0"
+"westfalen.museum\0stryn.no\0mil.py\0hosting\0"
+"shisui.chiba.jp\0sowa.ibaraki.jp\0"
+"tanagura.fukushima.jp\0nanbu.tottori.jp\0"
+"gov.nc.tr\0"
+"stockholm\0"
+"kitami.hokkaido.jp\0lubartow.pl\0"
+"r\xc3\xb8ros.no\0nj.us\0industries\0hobby-site.org\0"
+"ru.com\0"
+"ono.fukushima.jp\0"
+"wiki\0georgia.su\0"
+"bauern.museum\0taipei\0"
+"lupin\0"
+"gojome.akita.jp\0boehringer\0"
+"pointto.us\0"
+"\xd8\xa8\xd9\x8a\xd8\xaa\xd9\x83\0"
+"web.lk\0name.mk\0mil.ru\0k12.il.us\0spacekit.io\0"
+"mil.rw\0dyndns-blog.com\0"
+"mil.sh\0"
+"nordreisa.no\0"
+"hichiso.gifu.jp\0shinjuku.tokyo.jp\0"
+"bahn.museum\0ybo.science\0"
+"trentinoaltoadige.it\0"
+"minamiizu.shizuoka.jp\0"
+"properties\0us.eu.org\0"
+"mil.st\0"
+"elburg.museum\0"
+"at-band-camp.net\0"
+"name.jo\0mil.sy\0"
+"mil.tj\0"
+"vi.it\0"
+"mil.tm\0"
+"on-web.fr\0"
+"mil.to\0is-a-nurse.com\0"
+"yonaguni.okinawa.jp\0web.nf\0"
+"spjelkavik.no\0"
+"mil.tr\0"
+"web.ni\0"
+"mitoyo.kagawa.jp\0yandex\0"
+"j\xc3\xb8rpeland.no\0wine\0is-a-painter.com\0"
+"fi.it\0"
"mil.tw\0"
-"net.hk\0"
-"mil.tz\0"
-"industria.bo\0net.hn\0"
-"bozen-su\xcc\x88""dtirol.it\0faith\0"
-"urn.arpa\0"
-"net.ht\0net.id\0"
-"emiliaromagna.it\0moma.museum\0"
-"matsudo.chiba.jp\0mil.vc\0"
-"nishi.fukuoka.jp\0"
+"futaba.fukushima.jp\0mil.tz\0"
+"saves-the-whales.com\0"
+"yufu.oita.jp\0"
+"mil.vc\0"
"mil.ve\0"
-"kitamoto.saitama.jp\0chizu.tottori.jp\0s\xc3\xb8rum.no\0"
-"mizumaki.fukuoka.jp\0bounceme.net\0"
-"net.il\0delmenhorst.museum\0ulvik.no\0mil.uy\0"
-"net.im\0mihama.mie.jp\0"
-"net.in\0odda.no\0s\xc3\xa1l\xc3\xa1t.no\0"
-"barclays\0"
-"net.iq\0"
-"net.ir\0naustdal.no\0"
-"net.is\0"
-"net.je\0s3-website.ap-northeast-2.amazonaws.com\0"
-"kyuragi.saga.jp\0"
-"medical.museum\0"
-"yoita.niigata.jp\0"
-"tachikawa.tokyo.jp\0kvinnherad.no\0is-an-engineer.com\0"
-"badaddja.no\0"
-"aktyubinsk.su\0"
-"net.jo\0"
-"quest\0"
-"trogstad.no\0"
-"hofu.yamaguchi.jp\0tel.tr\0"
-"net.kg\0"
-"okinawa.jp\0zip\0"
-"net.ki\0diet\0"
-"manno.kagawa.jp\0omiya.saitama.jp\0vaapste.no\0gr.eu.org\0"
-"ln.cn\0"
-"saogonca.br\0"
-"net.kn\0seat\0"
-"uki.kumamoto.jp\0net.la\0"
-"sc.ke\0net.lb\0"
-"net.lc\0"
-"recipes\0"
-"harvestcelebration.museum\0chrysler\0"
-"santabarbara.museum\0"
-"chikusei.ibaraki.jp\0itoman.okinawa.jp\0net.kw\0"
-"blogspot.com.uy\0"
-"net.ky\0googlecode.com\0"
-"net.kz\0selbu.no\0"
-"ap.gov.br\0ishikawa.okinawa.jp\0net.lk\0law.pro\0"
-"dyndns-at-work.com\0"
-"sc.kr\0"
-"net.ma\0cupcake.is\0"
-"net.lr\0boats\0"
-"kamikoani.akita.jp\0"
-"mil.za\0oracle\0"
-"net.me\0vadso.no\0game-host.org\0"
-"not.br\0net.lv\0"
-"scrapper-site.net\0"
-"capebreton.museum\0"
-"ichinoseki.iwate.jp\0net.ly\0online\0"
-"santamaria.br\0net.mk\0from-ma.com\0"
-"net.ml\0"
-"hadano.kanagawa.jp\0k12.gu.us\0"
-"rn.gov.br\0"
-"of.by\0hotel.lk\0net.mo\0"
-"mil.zm\0"
-"accident-prevention.aero\0net.ms\0rnrt.tn\0"
-"net.mt\0"
-"net.mu\0ap.gov.pl\0"
-"net.mv\0net.nf\0"
-"muika.niigata.jp\0net.mw\0net.ng\0foundation\0feste-ip.net\0"
-"net.mx\0k12.ut.us\0"
-"net.my\0net.ni\0"
-"net.mz\0mil.zw\0"
-"avocat.fr\0"
-"gyeongnam.kr\0lavangen.no\0"
-"net.nr\0tjmaxx\0"
-"radio.br\0accesscam.org\0"
-"incheon.kr\0seek\0"
-"maritimo.museum\0abarth\0kurgan.su\0"
-"molise.it\0"
-"net.nz\0"
-"b\xc3\xb8.telemark.no\0net.om\0"
-"ro.gov.br\0valle-daosta.it\0est-mon-blogueur.com\0nh-serv.co.uk\0"
-"claims\0\xe5\x98\x89\xe9\x87\x8c\xe5\xa4\xa7\xe9\x85\x92\xe5\xba\x97\0"
-"granvin.no\0net.pa\0"
-"cq.cn\0"
-"nsupdate.info\0"
-"daisen.akita.jp\0barum.no\0"
-"net.pe\0"
-"love\0"
-"oe.yamagata.jp\0"
-"drangedal.no\0net.ph\0"
-"mar.it\0"
-"\xd9\x81\xd9\x84\xd8\xb3\xd8\xb7\xd9\x8a\xd9\x86\0"
-"shinjo.yamagata.jp\0oppegard.no\0net.pk\0"
-"net.pl\0"
-"nc.tr\0"
-"1.bg\0fvg.it\0net.pn\0"
-"ogasawara.tokyo.jp\0"
-"net.qa\0"
-"ako.hyogo.jp\0net.pr\0from-me.org\0"
-"fujishiro.ibaraki.jp\0higashiyamato.tokyo.jp\0net.ps\0"
-"kitadaito.okinawa.jp\0fundacio.museum\0net.pt\0\xe3\x82\xb0\xe3\x83\xbc\xe3\x82\xb0\xe3\x83\xab\0"
-"assassination.museum\0loans\0"
-"qc.com\0"
-"kui.hiroshima.jp\0"
-"net.py\0ddns.me\0"
-"sennan.osaka.jp\0kofu.yamanashi.jp\0"
-"juedisches.museum\0"
-"andoy.no\0rogers\0"
-"ms.us\0nc.us\0"
-"akishima.tokyo.jp\0"
-"kyotamba.kyoto.jp\0"
-"arna.no\0"
-"freight.aero\0cc.ky.us\0shell\0"
-"hoylandet.no\0"
-"hotel.hu\0barclaycard\0"
-"b\xc3\xa1jddar.no\0juniper\0"
-"n\xc3\xa5\xc3\xa5mesjevuemie.no\0"
-"!www.ck\0ruhr\0"
-"fi.cr\0panama.museum\0k12.me.us\0"
-"net.sa\0\xe5\x85\xac\xe5\x8f\xb8.\xe9\xa6\x99\xe6\xb8\xaf\0"
-"hokuto.hokkaido.jp\0net.sb\0"
-"\xe5\xb2\xa1\xe5\xb1\xb1.jp\0saltdal.no\0net.sc\0"
-"net.sd\0"
-"net.ru\0"
-"exposed\0resindevice.io\0"
-"net.rw\0net.sg\0nohost.me\0"
-"net.sh\0app.lmpm.com\0"
-"horokanai.hokkaido.jp\0"
-"akrehamn.no\0meraker.no\0net.sl\0"
-"asaka.saitama.jp\0"
-"ishikawa.jp\0net.so\0"
-"ws.na\0"
-"namdalseid.no\0dscloud.me\0"
-"net.st\0"
-"szczytno.pl\0"
-"sigdal.no\0metlife\0"
-"wif.gov.pl\0pixolino.com\0"
-"net.th\0"
-"tako.chiba.jp\0net.sy\0"
-"noto.ishikawa.jp\0net.tj\0immobilien\0"
-"isa.kagoshima.jp\0is-a-geek.net\0"
-"taira.toyama.jp\0net.tm\0k12.ar.us\0"
-"net.tn\0is-a-chef.org\0"
-"net.to\0melbourne\0"
-"from-ok.com\0"
-"net.ua\0mypep.link\0"
-"net.tr\0"
-"kishiwada.osaka.jp\0bygland.no\0"
-"assedic.fr\0omuta.fukuoka.jp\0hyuga.miyazaki.jp\0net.tt\0"
-"is-a-rockstar.com\0"
-"net.tw\0"
-"columbia.museum\0"
+"ind.br\0"
+"barsyonline.co.uk\0"
+"mil.uy\0"
+"\xe5\x8d\x83\xe8\x91\x89.jp\0kitahiroshima.hokkaido.jp\0"
+"can.museum\0yorkshire.museum\0bjugn.no\0vm.bytemark.co.uk\0"
+"sande.more-og-romsdal.no\0"
+"akaiwa.okayama.jp\0"
+"sejny.pl\0health.vn\0contact\0"
+"te.ua\0"
+"tv.bb\0red\0"
+"web.pk\0\xd7\xa7\xd7\x95\xd7\x9d\0"
+"\xe0\xb8\xa8\xe0\xb8\xb6\xe0\xb8\x81\xe0\xb8\xa9\xe0\xb8\xb2.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0"
+"asso.re\0"
+"br.it\0cb.it\0shimoda.shizuoka.jp\0"
+"archi\0"
+"tanohata.iwate.jp\0"
+"kamishihoro.hokkaido.jp\0diet\0ren\0cnpy.gdn\0"
+"cc.vi.us\0"
+"omotego.fukushima.jp\0"
+"tv.bo\0sandcats.io\0"
+"blockbuster\0"
+"qvc\0from-tn.com\0"
+"fnd.br\0tv.br\0rackmaze.net\0"
+"mihara.hiroshima.jp\0azurewebsites.net\0"
+"stada\0hu.com\0"
+"mulhouse.museum\0school.museum\0"
+"shimada.shizuoka.jp\0"
+"pagespeedmobilizer.com\0"
+"bedzin.pl\0"
+"de.us\0"
+"manx.museum\0"
+"lease\0serveirc.com\0"
+"se.leg.br\0"
+"copenhagen.museum\0lanbib.se\0k12.ne.us\0"
+"studio\0"
+"friuliveneziagiulia.it\0ikeda.hokkaido.jp\0"
+"notaires.km\0leka.no\0"
+"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xdb\x8c\xd8\xa9\0*.advisor.ws\0"
+"fukagawa.hokkaido.jp\0"
+"hanggliding.aero\0s3.dualstack.ap-south-1.amazonaws.com\0"
+"resistance.museum\0mil.za\0"
+"yamagata.jp\0kamikawa.saitama.jp\0wielun.pl\0"
+"beiarn.no\0is-into-cars.com\0"
+"film.hu\0eu.com\0"
+"for-the.biz\0"
+"mil.zm\0*.vps.myjino.ru\0"
+"morimachi.shizuoka.jp\0"
+"maserati\0"
+"nagareyama.chiba.jp\0web.tj\0"
+"asso.nc\0"
+"takehara.hiroshima.jp\0yamagata.nagano.jp\0"
+"oppdal.no\0\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa7\0mil.zw\0"
+"ind.gt\0!city.yokohama.jp\0fujimino.saitama.jp\0"
+"lib.nj.us\0\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa9\0xs4all.space\0"
+"gs.hm.no\0netbank\0wanggou\0de.com\0"
+"web.tr\0ril\0"
+"leasing.aero\0sexy\0"
+"hirono.iwate.jp\0debian.net\0"
+"jobs\0rio\0"
+"rip\0"
+"n.se\0"
+"ggf.br\0urayasu.chiba.jp\0"
+"barsy.org\0"
+"cc.ok.us\0is-leet.com\0dsmynas.org\0"
+"ochi.kochi.jp\0satte.saitama.jp\0"
+"m\xc3\xa5lselv.no\0is-a-teacher.com\0synology.me\0"
+"zarow.pl\0"
+"firewall-gateway.com\0"
+"okawa.kochi.jp\0"
+"web.ve\0latino\0"
+"kusatsu.gunma.jp\0saikai.nagasaki.jp\0"
+"ind.in\0"
+"corsica\0"
+"oster\xc3\xb8y.no\0"
+"pub.sa\0"
+"\xe9\x95\xb7\xe9\x87\x8e.jp\0niigata.niigata.jp\0nago.okinawa.jp\0"
+"est-a-la-maison.com\0"
+"namdalseid.no\0"
+"nishikata.tochigi.jp\0"
+"kumamoto.jp\0ustka.pl\0"
+"tuva.su\0"
+"accident-prevention.aero\0"
+"roma.it\0mombetsu.hokkaido.jp\0"
+"odda.no\0barsy.co.uk\0"
+"\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x8b\xe0\xa4\xa4\0"
+"oita.jp\0moonscale.net\0"
+"gotdns.org\0"
+"higashimurayama.tokyo.jp\0"
+"tv.im\0publishproxy.com\0"
+"shimogo.fukushima.jp\0sanok.pl\0"
+"!www.ck\0sport.hu\0"
+"catholic\0"
+"tv.it\0"
+"eco.br\0"
+"ind.kw\0transport.museum\0homesense\0"
+"soni.nara.jp\0"
+"hinohara.tokyo.jp\0"
+"nombre.bo\0versailles.museum\0"
+"vi.us\0web.za\0"
+"now-dns.net\0"
+"is-very-bad.org\0"
+"otoineppu.hokkaido.jp\0freesite.host\0"
+"asso.km\0gallery.museum\0rahkkeravju.no\0"
+"posts-and-telecommunications.museum\0station.museum\0community\0"
+"minamiuonuma.niigata.jp\0"
+"hirosaki.aomori.jp\0"
+"dating\0"
+"horten.no\0endoftheinternet.org\0"
+"ethnology.museum\0giske.no\0charity\0"
+"sb.ua\0k12.pa.us\0"
"cyou\0"
-"gov.nc.tr\0net.uk\0alfaromeo\0"
-"de.com\0"
-"emerck\0"
-"obninsk.su\0townnews-staging.com\0"
-"soundandvision.museum\0grimstad.no\0"
-"sakuragawa.ibaraki.jp\0"
-"net.vc\0"
-"sciences.museum\0sc.ug\0"
-"izumi.osaka.jp\0troms\xc3\xb8.no\0net.ve\0"
-"sc.tz\0"
-"net.uy\0net.vi\0servegame.org\0"
-"gs.hl.no\0coop.tt\0net.uz\0"
-"yoshida.saitama.jp\0"
-"kamisunagawa.hokkaido.jp\0v\xc3\xa5g\xc3\xa5.no\0termez.su\0"
-"net.vn\0"
-"vapor.cloud\0"
-"sc.us\0store\0"
-"sakae.nagano.jp\0ibaraki.osaka.jp\0net.vu\0"
-"chocolate.museum\0"
-"coop.mv\0b.ssl.fastly.net\0"
-"coop.mw\0"
-"swatch\0"
-"works.aero\0minamata.kumamoto.jp\0"
-"jobs\0tranoy.no\0"
-"webhop.biz\0"
-"n.se\0net.ws\0"
-"lib.pa.us\0"
-"aurland.no\0"
-"dyndns-web.com\0"
-"kitami.hokkaido.jp\0"
-"tottori.jp\0"
-"forli\xcc\x80-cesena.it\0youth.museum\0"
-"dish\0"
-"touch.museum\0\xe4\xbc\x81\xe4\xb8\x9a\0"
-"fi.it\0fastlylb.net\0"
-"homesense\0"
-"of.no\0"
-"loten.no\0olayan\0"
-"mifune.kumamoto.jp\0"
-"sv.it\0joboji.iwate.jp\0"
-"wien\0"
-"wuoz.gov.pl\0"
-"hyogo.jp\0"
-"net.za\0"
-"swiebodzin.pl\0"
-"ogawara.miyagi.jp\0is-a-chef.com\0"
-"sveio.no\0"
-"vet.br\0schokoladen.museum\0dnsalias.com\0"
-"yaotsu.gifu.jp\0"
-"def.br\0net.zm\0"
-"atsuma.hokkaido.jp\0ohira.tochigi.jp\0coop.py\0"
-"shichikashuku.miyagi.jp\0"
-"sauda.no\0"
-"szczecin.pl\0"
-"press.aero\0"
-"loabat.no\0mattel\0"
-"ota.gunma.jp\0"
-"odessa.ua\0netlify.com\0"
-"asakuchi.okayama.jp\0"
-"se.gov.br\0presse.ci\0"
-"saintlouis.museum\0"
-"tome.miyagi.jp\0"
-"us-gov-west-1.elasticbeanstalk.com\0"
-"fuoisku.no\0cc.vi.us\0"
-"financial\0"
-"vipsinaapp.com\0"
-"ltd.co.im\0"
-"ed.ao\0myfirewall.org\0"
-"raholt.no\0"
-"jeonnam.kr\0"
-"coop.km\0"
-"boston.museum\0clothing\0"
-"abeno.osaka.jp\0"
-"kudoyama.wakayama.jp\0"
-"entomology.museum\0mopar\0"
-"ngrok.io\0"
-"sa.au\0samegawa.fukushima.jp\0"
-"recife.br\0poivron.org\0"
-"hizen.saga.jp\0"
-"sango.nara.jp\0minato.tokyo.jp\0lugs.org.uk\0"
-"sling\0"
-"fetsund.no\0"
-"ed.ci\0numata.gunma.jp\0seranishi.hiroshima.jp\0vagsoy.no\0"
-"s3-us-west-2.amazonaws.com\0"
-"zippo\0"
-"ogawa.ibaraki.jp\0omi.nagano.jp\0"
-"trentin-sued-tirol.it\0tomobe.ibaraki.jp\0setouchi.okayama.jp\0"
-"\xe9\xab\x98\xe7\x9f\xa5.jp\0"
-"ed.cr\0"
-"gob.ar\0shimoichi.nara.jp\0"
-"osoyro.no\0"
-"aibetsu.hokkaido.jp\0ce.leg.br\0"
-"presse.fr\0tsubame.niigata.jp\0michigan.museum\0"
-"hoteles\0"
-"wiki\0"
-"sand\xc3\xb8y.no\0"
-"sa.cr\0is-a-bruinsfan.org\0"
-"kharkov.ua\0"
-"gob.bo\0lib.wy.us\0"
-"hasura.app\0"
-"utsunomiya.tochigi.jp\0"
-"maintenance.aero\0"
-"skype\0"
-"kaluga.su\0"
-"nishitosa.kochi.jp\0obanazawa.yamagata.jp\0nv.us\0"
-"manx.museum\0\xe6\x96\xb0\xe5\x8a\xa0\xe5\x9d\xa1\0"
-"ome.tokyo.jp\0"
-"gob.cl\0na.it\0"
-"kiwi.nz\0"
-"buzen.fukuoka.jp\0gs.rl.no\0read-books.org\0servehalflife.com\0"
-"k12.ak.us\0"
-"uklugs.org\0"
-"skedsmokorset.no\0"
-"kerryproperties\0"
-"kinokawa.wakayama.jp\0forsale\0"
-"marnardal.no\0psp.gov.pl\0\xd0\xb0\xd0\xba.\xd1\x81\xd1\x80\xd0\xb1\0"
-"kppsp.gov.pl\0"
-"seoul.kr\0sa.gov.pl\0cieszyn.pl\0"
-"kimino.wakayama.jp\0macys\0marketing\0"
-"gmail\0"
-"\xce\xb5\xce\xbb\0"
-"gob.do\0heimatunduhren.museum\0"
-"it.ao\0alsace\0"
-"research.museum\0"
-"l.bg\0"
-"gob.ec\0kanra.gunma.jp\0vega.no\0zp.gov.pl\0"
-"agr.br\0wine\0"
-"\xd0\xba\xd0\xb0\xd1\x82\xd0\xbe\xd0\xbb\xd0\xb8\xd0\xba\0"
-"bl.it\0"
-"encyclopedic.museum\0boutique\0"
+"lubin.pl\0"
+"tachiarai.fukuoka.jp\0"
+"tj\xc3\xb8me.no\0"
+"ao.it\0"
+"asso.mc\0ontario.museum\0chernovtsy.ua\0lib.ca.us\0"
+"mus.br\0"
+"hm.no\0"
+"dellogliastra.it\0yoita.niigata.jp\0kainan.tokushima.jp\0"
+"myshopblocks.com\0"
+"from-in.com\0"
+"dscloud.biz\0"
+"mo-i-rana.no\0"
+"tv.na\0"
+"author.aero\0nesoddtangen.no\0"
+"showa.fukushima.jp\0"
+"folkebibl.no\0athleta\0"
+"nagatoro.saitama.jp\0"
+"bokn.no\0"
+"moka.tochigi.jp\0nogi.tochigi.jp\0"
+"mesaverde.museum\0technology.museum\0"
+"kamisu.ibaraki.jp\0"
+"sap\0"
+"k12.md.us\0"
+"hikari.yamaguchi.jp\0\xe0\xa4\xb8\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xa0\xe0\xa4\xa8\0"
+"casadelamoneda.museum\0sas\0shopping\0"
+"jus.br\0"
+"groundhandling.aero\0"
+"wedding\0"
+"urbinopesaro.it\0podlasie.pl\0maif\0"
+"konyvelo.hu\0sbi\0adygeya.su\0"
+"morotsuka.miyazaki.jp\0"
+"naha.okinawa.jp\0"
+"aver\xc3\xb8y.no\0sca\0"
+"rokunohe.aomori.jp\0dish\0scb\0"
+"ok.us\0sbs\0"
+"\xc3\xa5mot.no\0flora.no\0"
+"sondrio.it\0takahata.yamagata.jp\0"
+"royken.no\0"
+"salangen.no\0"
+"oirase.aomori.jp\0"
+"pescara.it\0kuchinotsu.nagasaki.jp\0"
+"shiraoi.hokkaido.jp\0vision\0"
+"tottori.jp\0onojo.fukuoka.jp\0"
+"maritimo.museum\0\xc3\xb8ksnes.no\0"
+"iida.nagano.jp\0"
+"yabuki.fukushima.jp\0"
+"gub.uy\0"
"res.in\0"
-"stjordalshalsen.no\0"
-"gob.es\0\xe6\xb2\x96\xe7\xb8\x84.jp\0sexy\0"
-"pi.it\0onga.fukuoka.jp\0"
-"maif\0"
-"barefoot\0"
-"alt.za\0"
-"pescara.it\0"
+"h\xc3\xb8nefoss.no\0"
+"cc.nh.us\0"
+"susaki.kochi.jp\0"
+"haram.no\0"
+"\xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xdb\x8c\xdb\x83\0"
+"adygeya.ru\0"
+"bhz.br\0iwanai.hokkaido.jp\0"
+"mx.na\0gs.jan-mayen.no\0"
+"run\0"
+"culture.museum\0"
+"ind.tn\0"
+"ses\0"
+"bandai.fukushima.jp\0etajima.hiroshima.jp\0"
+"campinagrande.br\0tv.sd\0"
+"lib.id.us\0sew\0"
+"sex\0"
+"fhsk.se\0"
+"tranoy.no\0"
+"kakuda.miyagi.jp\0"
+"l.bg\0"
+"walbrzych.pl\0"
+"\xe7\xb6\xb2\xe7\xbb\x9c.hk\0"
+"sfr\0"
+"rwe\0"
+"salzburg.museum\0"
+"press.aero\0railway.museum\0net-freaks.com\0"
+"yn.cn\0"
+"dynns.com\0"
+"ss.it\0hachirogata.akita.jp\0"
+"tv.tr\0redirectme.net\0"
+"shingu.wakayama.jp\0"
+"bungoono.oita.jp\0"
+"servebbs.org\0"
+"cs.it\0mediocampidano.it\0esashi.hokkaido.jp\0cloudapp.net\0"
"s3.eu-west-2.amazonaws.com\0"
-"yasaka.nagano.jp\0hinohara.tokyo.jp\0"
-"motorcycles\0my-wan.de\0"
-"dating\0"
-"k12.pr.us\0"
-"kopervik.no\0"
-"abr.it\0"
-"tunes\0"
-"iida.nagano.jp\0"
-"sarufutsu.hokkaido.jp\0parliament.nz\0"
-"omaha.museum\0flir\0"
-"barueri.br\0"
-"daejeon.kr\0"
-"desa.id\0"
-"s\xc3\xb8gne.no\0pila.pl\0"
-"baghdad.museum\0"
-"gob.gt\0shizukuishi.iwate.jp\0oy.lc\0"
-"health\0"
-"\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86\0"
-"qld.gov.au\0eidfjord.no\0\xe6\x95\x99\xe8\x82\xb2.\xe9\xa6\x99\xe6\xb8\xaf\0"
-"sex.hu\0"
-"from-ar.com\0barsyonline.co.uk\0"
-"gob.hn\0sa.it\0kotoura.tottori.jp\0"
-"ed.jp\0"
-"podzone.net\0"
-"sytes.net\0"
-"bayern\0"
-"umig.gov.pl\0"
-"radio\0"
-"herad.no\0lancia\0"
-"shinyoshitomi.fukuoka.jp\0jorpeland.no\0trafficplex.cloud\0"
-"salud.bo\0atami.shizuoka.jp\0"
-"is-by.us\0"
-"mypets.ws\0mypi.co\0"
-"dubai\0"
-"suzaka.nagano.jp\0"
-"vn.ua\0"
-"yonaguni.okinawa.jp\0"
-"washingtondc.museum\0"
-"nt.au\0express\0"
-"r\xc3\xa5""de.no\0ia.us\0definima.io\0"
+"kahoku.yamagata.jp\0tv.tz\0"
+"fhapp.xyz\0"
+"kihoku.ehime.jp\0"
+"5.bg\0"
+"press.cy\0"
+"koga.ibaraki.jp\0hakusan.ishikawa.jp\0"
+"saskatchewan.museum\0"
+"trogstad.no\0"
+"hakone.kanagawa.jp\0"
+"xenapponazure.com\0"
+"bytom.pl\0"
+"analytics\0"
+"toyama.jp\0"
+"\xe4\xbf\xa1\xe6\x81\xaf\0"
+"kristiansund.no\0"
+"aquarelle\0mango\0is-a-photographer.com\0"
+"minamidaito.okinawa.jp\0"
+"\xe7\xa5\x9e\xe5\xa5\x88\xe5\xb7\x9d.jp\0chuo.yamanashi.jp\0"
+"leikanger.no\0"
+"lib.ar.us\0"
+"za.net\0"
+"ambulance.aero\0ski\0"
+"voagat.no\0"
+"namegawa.saitama.jp\0"
+"cc.dc.us\0"
+"*.quipelements.com\0"
+"flir\0"
+"nagasaki.jp\0"
+"wakkanai.hokkaido.jp\0"
+"lu.it\0me.it\0*.telebit.xyz\0"
+"lib.ok.us\0sky\0"
+"v\xc3\xa5ler.\xc3\xb8stfold.no\0"
+"himeji.hyogo.jp\0alwaysdata.net\0"
+"science.museum\0"
+"higashiura.aichi.jp\0"
+"hadano.kanagawa.jp\0"
+"me.ke\0"
+"dyndns.info\0dnsiskinky.com\0"
+"gunma.jp\0"
+"nh.us\0"
+"ikeda.fukui.jp\0"
+"googleapis.com\0"
+"farsund.no\0"
+"okoppe.hokkaido.jp\0publ.pt\0"
+"paderborn.museum\0dyndns-server.com\0"
+"*.sapporo.jp\0shibata.niigata.jp\0"
+"halloffame.museum\0"
+"farmers\0"
+"eidsberg.no\0doomdns.org\0"
+"asahi.mie.jp\0"
+"neat-url.com\0"
+"oceanographique.museum\0"
+"shinkamigoto.nagasaki.jp\0"
+"friuliv-giulia.it\0kanra.gunma.jp\0"
+"cc.me.us\0""2038.io\0"
+"lillesand.no\0es.eu.org\0"
+"url.tw\0"
+"evenassi.no\0"
+"utashinai.hokkaido.jp\0"
+"ravendb.me\0"
+"tromso.no\0lib.wy.us\0"
+"soy\0"
+"beauxarts.museum\0bounty-full.com\0"
+"uzs.gov.pl\0"
+"kvam.no\0giehtavuoatna.no\0"
+"fg.it\0familyds.net\0"
+"alaska.museum\0lib.hi.us\0s3.us-east-2.amazonaws.com\0"
+"tab\0"
+"naturhistorisches.museum\0hjartdal.no\0"
+"ora.gunma.jp\0"
+"oumu.hokkaido.jp\0"
+"paragliding.aero\0halden.no\0"
+"badajoz.museum\0"
+"cc.in.us\0"
+"modelling.aero\0mc.eu.org\0"
+"ishikawa.okinawa.jp\0"
+"www.ro\0"
+"niihama.ehime.jp\0"
+"kautokeino.no\0"
+"tax\0"
+"in.na\0"
+"shaw\0est-mon-blogueur.com\0from-ky.com\0"
+"daiwa.hiroshima.jp\0rzeszow.pl\0srl\0"
+"eidsvoll.no\0ryukyu\0"
+"taku.saga.jp\0"
+"family.museum\0bargains\0"
+"hk.cn\0notaires.fr\0bolzano-altoadige.it\0isesaki.gunma.jp\0"
+"in.ni\0"
+"kurume.fukuoka.jp\0"
+"chattanooga.museum\0lodingen.no\0"
+"przeworsk.pl\0srt\0"
+"ed.ao\0from-mi.com\0"
+"greta.fr\0amami.kagoshima.jp\0chuo.tokyo.jp\0yonago.tottori.jp\0"
+"rnu.tn\0cdn77-ssl.net\0"
+"tci\0"
+"kitaaiki.nagano.jp\0"
+"app.os.fedoraproject.org\0"
+"miyama.mie.jp\0"
+"theater.museum\0"
+"katashina.gunma.jp\0"
+"tsuno.miyazaki.jp\0fujiidera.osaka.jp\0"
+"stc\0lt.eu.org\0"
+"takasago.hyogo.jp\0"
+"ponpes.id\0ham-radio-op.net\0"
+"sells-for-u.com\0ownprovider.com\0"
+"dc.us\0duckdns.org\0"
+"mormon\0"
+"nikolaev.ua\0tdk\0"
+"usuki.oita.jp\0"
+"apartments\0"
+"ed.ci\0"
+"ce.leg.br\0"
+"oystre-slidre.no\0pl.ua\0k12.ms.us\0k12.nc.us\0softbank\0"
+"ikeda.gifu.jp\0"
+"flight.aero\0k12.ec\0\xc3\xb8rskog.no\0"
+"ed.cr\0fujimi.nagano.jp\0"
+"nagoya\0"
+"kui.hiroshima.jp\0"
+"pvt.ge\0"
+"g12.br\0tel\0"
+"khmelnitskiy.ua\0"
+"kamiizumi.saitama.jp\0"
+"s3-us-east-2.amazonaws.com\0"
+"futbol\0"
+"v\xc3\xa5gs\xc3\xb8y.no\0valer.ostfold.no\0"
+"osaka.jp\0hidaka.wakayama.jp\0mail.pl\0podhale.pl\0"
+"ddns.me\0"
+"goto.nagasaki.jp\0"
+"cincinnati.museum\0myddns.rocks\0"
"minobu.yamanashi.jp\0"
-"takanabe.miyazaki.jp\0"
-"rehab\0"
-"nt.ca\0leikanger.no\0"
-"co.ae\0shibukawa.gunma.jp\0"
-"aoste.it\0"
-"co.ag\0"
-"davvesiida.no\0bostik\0"
-"airforce\0"
-"motoyama.kochi.jp\0potager.org\0"
-"fukui.jp\0oregon.museum\0"
+"am.br\0"
+"amsterdam.museum\0"
+"trentino-s-tirol.it\0"
+"4u.com\0"
+"kr.it\0"
+"graz.museum\0"
+"yoro.gifu.jp\0"
+"cruise\0teaches-yoga.com\0"
+"minakami.gunma.jp\0"
+"orkdal.no\0"
+"imperia.it\0"
+"*.awdev.ca\0"
+"in.rs\0l.se\0dubai\0"
+"aosta.it\0"
+"alstom\0is-a-cubicle-slave.com\0"
+"me.tz\0"
+"me.uk\0"
+"cc.ny.us\0"
+,
+
+"ichikawa.hyogo.jp\0"
+"\xe3\x83\x95\xe3\x82\xa1\xe3\x83\x83\xe3\x82\xb7\xe3\x83\xa7\xe3\x83\xb3\0"
+"thd\0"
+"nf.ca\0"
+"me.us\0"
+"pup.gov.pl\0"
+"klepp.no\0bike\0mydatto.com\0"
+"trentino-a-adige.it\0"
+"sandvik\0"
+"from-ri.com\0"
+"*.kawasaki.jp\0nakama.fukuoka.jp\0in.th\0"
+"i234.me\0"
+"toyotsu.fukuoka.jp\0"
+"broadcast.museum\0"
+"shia\0"
+"kouyama.kagoshima.jp\0"
+"coldwar.museum\0in.ua\0"
+"gov.ac\0v\xc3\xa5g\xc3\xa5.no\0"
+"aga.niigata.jp\0"
+"gov.ae\0kvinesdal.no\0"
+"gov.af\0k12.il\0"
+"jprs\0eu-west-3.elasticbeanstalk.com\0"
+"sells-it.net\0"
+"hitra.no\0s3-website-ap-southeast-2.amazonaws.com\0*.otap.co\0from-wy.com\0net.eu.org\0""4lima.de\0"
+"gov.al\0"
+"landes.museum\0"
+"chijiwa.nagasaki.jp\0"
+"gov.ba\0tt.im\0beeldengeluid.museum\0"
+"gov.ar\0gov.bb\0edogawa.tokyo.jp\0"
+"gov.as\0in.us\0"
+"s3.cn-north-1.amazonaws.com.cn\0"
+"gov.au\0"
+"gov.bf\0"
+"gov.bh\0ud.it\0"
+"gov.az\0kiyosu.aichi.jp\0"
+"gov.bm\0"
+"gov.bn\0miyashiro.saitama.jp\0"
+"jerusalem.museum\0sydney\0servehalflife.com\0"
+"tjx\0yamaxun\0"
+"gov.br\0emr.it\0"
+"gov.bs\0bing\0"
+"gov.bt\0gov.cd\0fukuchiyama.kyoto.jp\0"
+"cn.com\0fi.eu.org\0"
+"press.se\0house\0"
+"gov.by\0cpa.pro\0s3.ca-central-1.amazonaws.com\0from-wi.com\0"
+"gov.bz\0florence.it\0""4lima.at\0"
+"viking.museum\0"
+"gov.cl\0forl\xc3\xac-cesena.it\0kagami.kochi.jp\0"
+"gov.cm\0isleofman.museum\0rentals\0"
+"gov.cn\0ed.jp\0"
+"gov.co\0"
+"chtr.k12.ma.us\0"
+"\xe6\x96\xb0\xe5\x8a\xa0\xe5\x9d\xa1\0"
+"gov.cu\0"
+"gov.cx\0perso.ht\0"
+"gov.cy\0pilots.museum\0hughes\0"
+"dyndns-at-work.com\0"
+"gov.dm\0lib.sc.us\0flowers\0"
+"bielawa.pl\0""4lima.ch\0"
+"gov.do\0"
+"gov.ec\0"
+"gov.ee\0bern.museum\0sk\xc3\xa1nit.no\0"
+"kyonan.chiba.jp\0"
+"gov.eg\0"
+"h\xc3\xb8yanger.no\0"
+"gov.dz\0tamatsukuri.ibaraki.jp\0"
+"asnes.no\0molde.no\0"
+"dsmynas.net\0"
+"phone\0"
+"salvadordali.museum\0"
+"gov.et\0sakuragawa.ibaraki.jp\0fukudomi.saga.jp\0"
+"kr\xc3\xb8""dsherad.no\0"
+"pippu.hokkaido.jp\0"
+"mima.tokushima.jp\0ube.yamaguchi.jp\0"
+"firebaseapp.com\0barsy.menu\0"
+"basilicata.it\0"
+"government.aero\0"
+"gov.ge\0"
+"cq.cn\0naples.it\0toyo.kochi.jp\0"
+"oz.au\0"
+"gov.gh\0top\0"
+"express.aero\0gov.gi\0force.museum\0"
+"aostavalley.it\0gyeonggi.kr\0"
+"shop\0"
+"fujitsu\0recipes\0"
+"gov.gn\0kashiwazaki.niigata.jp\0"
+"buzen.fukuoka.jp\0"
+"gov.gr\0"
+"fresenius\0show\0"
+"gov.gu\0ny.us\0"
+"*.statics.cloud\0"
+"isteingeek.de\0"
+"caxias.br\0suzaka.nagano.jp\0"
+"gov.gy\0"
+"shirakawa.fukushima.jp\0"
+"gov.hk\0habmer.no\0"
+"otama.fukushima.jp\0koryo.nara.jp\0kumatori.osaka.jp\0"
+"\xe0\xb0\xad\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\xa4\xe0\xb1\x8d\0"
+"press.ma\0"
+"gov.ie\0lib.la.us\0"
+"kr.ua\0k12.ia.us\0"
+"eidskog.no\0"
+"\xe4\xbc\x81\xe4\xb8\x9a\0"
+"mk.eu.org\0"
+"gov.il\0kizu.kyoto.jp\0"
+"gov.in\0mito.ibaraki.jp\0kita.osaka.jp\0\xe6\x94\xbf\xe5\xba\x9c\0blogsite.xyz\0"
+"m\xc3\xa1latvuopmi.no\0beta.bounty-full.com\0"
+"kamagaya.chiba.jp\0aso.kumamoto.jp\0"
+"gov.iq\0"
+"the.br\0gov.ir\0kaneyama.fukushima.jp\0"
+"gov.is\0"
+"gov.it\0"
+"ed.pw\0"
+"kasuya.fukuoka.jp\0"
+"lugs.org.uk\0now-dns.org\0"
+"matsuyama.ehime.jp\0"
+"doshi.yamanashi.jp\0"
+"tran\xc3\xb8y.no\0ubs\0navoi.su\0"
+"trv\0"
+"gov.jo\0"
+"k12.ut.us\0"
+"feste-ip.net\0"
+"gov.kg\0"
+"vicenza.it\0uconnect\0"
+"gov.ki\0"
+"from-hi.com\0"
+"tas.edu.au\0gov.km\0aquarium.museum\0"
+"gov.kn\0"
+"j.bg\0"
+"hayashima.okayama.jp\0gov.kp\0"
+"gov.la\0"
+"gov.lb\0"
+"gov.lc\0g\xc3\xa1ls\xc3\xa1.no\0"
+"cloudns.pro\0"
+"gov.kw\0center.museum\0photo\0"
+"gov.ky\0stokke.no\0vladikavkaz.ru\0"
+"iwade.wakayama.jp\0gov.kz\0"
+"gov.lk\0"
+"ma.gov.br\0k12.tr\0"
+"volyn.ua\0rugby\0"
+"schwarz\0"
+"gov.ma\0tui\0"
+"ta.it\0yamagata.gifu.jp\0gov.lr\0"
+"gov.ls\0\xc3\xa5rdal.no\0"
+"gov.lt\0"
+"gov.me\0palace.museum\0"
+"gov.lv\0"
+"gov.mg\0orskog.no\0"
+"gov.ly\0for-our.info\0vladikavkaz.su\0"
+"gov.mk\0lu.eu.org\0me.eu.org\0servemp3.com\0"
+"hiranai.aomori.jp\0gov.ml\0"
+"plo.ps\0"
+"kisofukushima.nagano.jp\0gov.mn\0"
+"gov.mo\0us-gov-west-1.elasticbeanstalk.com\0"
+"uchihara.ibaraki.jp\0"
+"gov.mr\0"
+"3.bg\0gov.ms\0lund.no\0k12.vi\0"
+"friulivenezia-giulia.it\0"
+"gov.mu\0"
+"gov.mv\0"
+"chiropractic.museum\0gov.mw\0gov.ng\0j\xc3\xb8lster.no\0is-slick.com\0"
+"gsm.pl\0"
+"midatlantic.museum\0gov.my\0is-a-bulls-fan.com\0"
+"gov.mz\0durban\0"
+"tvs\0"
+"valled-aosta.it\0"
+"santabarbara.museum\0naustdal.no\0za.org\0"
+"mizuho.tokyo.jp\0"
+"nov.ru\0"
+"brand.se\0"
+"gov.nr\0"
+"columbia.museum\0"
+"kamoenai.hokkaido.jp\0"
+"konskowola.pl\0"
+"progressive\0"
+"hokksund.no\0lv.eu.org\0"
+"nakamura.kochi.jp\0"
+"soc.lk\0gov.om\0"
+"tondabayashi.osaka.jp\0"
+"nov.su\0*.spectrum.myjino.ru\0"
+"laz.it\0host\0"
+"b\xc3\xa1hccavuotna.no\0helsinki\0homelinux.com\0"
+"tmp.br\0siracusa.it\0vibovalentia.it\0"
+"skjervoy.no\0"
+"togura.nagano.jp\0"
+"gov.ph\0go.leg.br\0"
+"\xc3\xb8vre-eiker.no\0"
+"ullensaker.no\0gov.pk\0"
+"otake.hiroshima.jp\0gov.pl\0"
+"bolzano.it\0fukuroi.shizuoka.jp\0gov.pn\0"
+"exchange\0"
+"futtsu.chiba.jp\0"
+"gs.oslo.no\0gov.qa\0"
+"kimobetsu.hokkaido.jp\0gov.pr\0merckmsd\0"
+"gov.ps\0"
+"gov.pt\0"
+"sauda.no\0cherkasy.ua\0"
+"from-la.net\0"
+"bruxelles.museum\0gov.py\0"
+"mc.it\0iwate.iwate.jp\0ota.tokyo.jp\0"
+"og.ao\0bajddar.no\0e12.ve\0leadpages.co\0"
+"tagajo.miyagi.jp\0"
+"aoki.nagano.jp\0leczna.pl\0"
+"webhop.info\0"
+"latina.it\0virtueeldomein.nl\0"
+"tobishima.aichi.jp\0"
+"pasadena.museum\0"
+"contagem.br\0chosei.chiba.jp\0"
+"homesecuritymac.com\0diskstation.org\0"
+"naval.museum\0"
+"fujinomiya.shizuoka.jp\0tkmaxx\0"
+"holt\xc3\xa5len.no\0gov.sa\0"
+"gov.sb\0kicks-ass.net\0"
+"paris.museum\0gov.rs\0gov.sc\0"
+"trentino-suedtirol.it\0itano.tokushima.jp\0obanazawa.yamagata.jp\0gov.sd\0"
+"frankfurt.museum\0gov.ru\0"
+"\xd8\xa7\xd9\x84\xd9\x8a\xd9\x85\xd9\x86\0"
+"gov.rw\0gov.sg\0health-carereform.com\0"
+"gov.sh\0"
+"assisi.museum\0cadaques.museum\0herokuapp.com\0"
+"kamisunagawa.hokkaido.jp\0"
+"kota.aichi.jp\0gov.sl\0"
+"supplies\0"
+"noboribetsu.hokkaido.jp\0"
+"*.uberspace.de\0"
+"gov.st\0"
+"!city.sapporo.jp\0"
+"yalta.ua\0silk\0"
+"gov.sx\0"
+"gov.sy\0"
+"gov.tj\0"
+"ltda\0"
+"ichinohe.iwate.jp\0gov.tl\0"
+"oppeg\xc3\xa5rd.no\0gov.tm\0"
+"gov.tn\0"
+"gov.to\0"
+"kamo.kyoto.jp\0wodzislaw.pl\0"
+"volkenkunde.museum\0gov.ua\0"
+"honjo.akita.jp\0kamiamakusa.kumamoto.jp\0gov.tr\0"
+"gov.tt\0"
+"skanit.no\0"
+"kisarazu.chiba.jp\0ono.hyogo.jp\0"
+"gov.tw\0"
+"ve.it\0kosaka.akita.jp\0matsusaka.mie.jp\0pfizer\0"
+"swiebodzin.pl\0"
+"gov.uk\0"
+"art.museum\0vestv\xc3\xa5g\xc3\xb8y.no\0sina\0virtual-user.de\0"
+"yoga\0"
+"fe.it\0miura.kanagawa.jp\0"
+"gov.vc\0"
+"yasaka.nagano.jp\0"
+"gov.ve\0"
+"uonuma.niigata.jp\0"
+"florida.museum\0uno\0"
+"intel\0"
+"market\0"
+"gov.vn\0maison\0"
+"kristiansand.no\0blogspot.com\0"
+"misato.saitama.jp\0"
+"cc.il.us\0"
+"perso.sn\0"
+"uol\0"
+"chanel\0cn-north-1.eb.amazonaws.com.cn\0"
+"cody.museum\0"
+"czeladz.pl\0"
+"sakura\0kr.eu.org\0"
+"rn.it\0"
+"maritime.museum\0vipsinaapp.com\0"
+"harima.hyogo.jp\0"
+"staples\0"
+"boats\0"
+"hi.cn\0perso.tn\0"
+"gov.ws\0"
+"dell-ogliastra.it\0"
+"browsersafetymark.io\0"
+"bn.it\0dlugoleka.pl\0"
+"annefrank.museum\0"
+"hagi.yamaguchi.jp\0"
+"k12.az.us\0space\0loseyourip.com\0"
+"rns.tn\0"
+"mill.museum\0ups\0"
+"go.dyndns.org\0"
+"bozen-sudtirol.it\0"
+"dyndns-office.com\0"
+"hofu.yamaguchi.jp\0"
+"no-ip.ca\0"
+"togitsu.nagasaki.jp\0misato.wakayama.jp\0"
+"better-than.tv\0"
+"emp.br\0kani.gifu.jp\0"
+"oslo.no\0"
+"foggia.it\0mibu.tochigi.jp\0"
+"orsta.no\0is-gone.com\0"
+"og.it\0"
+"gov.za\0"
+"tenkawa.nara.jp\0"
+"communications.museum\0"
+"builders\0"
+"gov.zm\0"
+"juegos\0"
+"minami.kyoto.jp\0"
+"blackbaudcdn.net\0"
+"auction\0mypsx.net\0"
+"gov.zw\0"
+"monzaedellabrianza.it\0"
+"q-a.eu.org\0"
+"federation.aero\0cloudns.org\0"
+"site\0"
+"zamami.okinawa.jp\0"
+"emergency.aero\0from-md.com\0"
+"not.br\0repair\0"
+"airtraffic.aero\0"
+"satsumasendai.kagoshima.jp\0\xe0\xb4\xad\xe0\xb4\xbe\xe0\xb4\xb0\xe0\xb4\xa4\xe0\xb4\x82\0"
+"lajolla.museum\0familyds.org\0"
+"trentino-sudtirol.it\0"
+"mosj\xc3\xb8""en.no\0"
+"takatori.nara.jp\0"
+"recht.pro\0"
+"inashiki.ibaraki.jp\0"
+"durham.museum\0"
+"\xe5\xbe\xae\xe5\x8d\x9a\0"
+"vet\0"
+"co.business\0"
+"andria-barletta-trani.it\0suedtirol.it\0"
+"konin.pl\0linkyard-cloud.ch\0"
+"gs.tr.no\0"
+"labor.museum\0"
+"ayagawa.kagawa.jp\0"
+"zaporizhzhe.ua\0"
+"ovre-eiker.no\0"
+"yao.osaka.jp\0"
+"my-vigor.de\0"
+"northwesternmutual\0"
+"stalbans.museum\0"
+"hokuryu.hokkaido.jp\0football\0"
+"*.nagoya.jp\0"
+"teo.br\0"
+"presidio.museum\0b\xc3\xb8mlo.no\0kharkiv.ua\0from-mt.com\0from-nd.com\0"
+"lecco.it\0"
+"asahi.yamagata.jp\0"
+"salud.bo\0contemporaryart.museum\0aca.pro\0"
+"soja.okayama.jp\0tokigawa.saitama.jp\0prochowice.pl\0"
+"il.us\0is-a-geek.com\0"
+"tr.it\0gokase.miyazaki.jp\0"
+"dyn.ddnss.de\0"
+"ladbrokes\0"
+"uchiko.ehime.jp\0"
+"toyosato.shiga.jp\0ens.tn\0"
+"berkeley.museum\0s3.ap-south-1.amazonaws.com\0"
+"media.aero\0aaa.pro\0vig\0"
+"rimini.it\0itako.ibaraki.jp\0"
+"cc.wy.us\0"
+"gujo.gifu.jp\0"
+"fot.br\0vin\0"
+"vip\0"
+"cc.hi.us\0"
+"taishi.hyogo.jp\0"
+"neyagawa.osaka.jp\0genkai.saga.jp\0wakasa.tottori.jp\0"
+"co.ae\0"
+"development.run\0"
+"co.ag\0from-sd.com\0"
+"neustar\0"
+"birthplace.museum\0"
+"cesenaforl\xc3\xac.it\0"
+"amot.no\0skjerv\xc3\xb8y.no\0"
"co.ao\0"
-"creation.museum\0"
-"co.bb\0"
-"chirurgiens-dentistes.fr\0toyoura.hokkaido.jp\0"
-"co.at\0""1337.pictures\0"
-"noticias.bo\0"
-"co.bi\0kagawa.jp\0"
-"unnan.shimane.jp\0freebox-os.com\0"
-"handa.aichi.jp\0"
-"makurazaki.kagoshima.jp\0fuettertdasnetz.de\0"
-"co.ca\0"
-"lancashire.museum\0"
-"kasugai.aichi.jp\0"
-"rieti.it\0\xe7\xb6\xb2\xe8\xb7\xaf.tw\0"
-"co.bw\0"
-"co.ci\0komatsushima.tokushima.jp\0"
+"arakawa.saitama.jp\0"
+"co.bb\0trani-barletta-andria.it\0"
+"co.at\0"
+"suifu.ibaraki.jp\0oum.gov.pl\0"
+"co.bi\0kvafjord.no\0"
+"odate.akita.jp\0"
+"embroidery.museum\0"
+"takamatsu.kagawa.jp\0"
+"nokia\0"
+"civilaviation.aero\0co.ca\0"
+"sells-for-less.com\0"
+"creditcard\0"
+"from-ut.com\0"
+"rikubetsu.hokkaido.jp\0"
+"co.bw\0dr.na\0"
+"mt.it\0"
+"co.ci\0"
+"tr.no\0"
"co.cl\0"
-"co.cm\0"
-"kutchan.hokkaido.jp\0"
-"watches\0"
-"co.cr\0fukuchi.fukuoka.jp\0"
-"bike\0"
-"chambagri.fr\0toya.hokkaido.jp\0gob.mx\0allfinanz\0"
-"gob.ni\0"
-"fr.eu.org\0"
-"sanda.hyogo.jp\0co.cz\0"
-"matsubara.osaka.jp\0co.dk\0"
-"moriguchi.osaka.jp\0lviv.ua\0"
-"webhop.me\0"
-"algard.no\0"
-"demon.nl\0"
-"oarai.ibaraki.jp\0"
-"ed.pw\0"
-"asti.it\0"
-"ethnology.museum\0"
-"mishima.shizuoka.jp\0"
-"carbonia-iglesias.it\0"
-"maebashi.gunma.jp\0gob.pa\0golffan.us\0"
-"amakusa.kumamoto.jp\0sex.pl\0"
-"milan.it\0"
-"magazine.aero\0kaminoyama.yamagata.jp\0"
-"ntr.br\0\xe9\x95\xb7\xe5\xb4\x8e.jp\0kuwana.mie.jp\0gob.pe\0"
-"takasaki.gunma.jp\0"
-"adult.ht\0vikna.no\0poznan.pl\0"
-"kagoshima.jp\0takehara.hiroshima.jp\0voagat.no\0"
-"gob.pk\0"
-"auction\0"
-"arida.wakayama.jp\0"
-"evenassi.no\0writesthisblog.com\0"
-"kiyosato.hokkaido.jp\0"
+"co.cm\0philadelphiaarea.museum\0"
+"bounceme.net\0"
+"from-vt.com\0"
+"co.cr\0playstation\0"
+"hvaler.no\0"
+"servebbs.com\0"
+"guitars\0"
+"storj.farm\0"
+"poa.br\0co.cz\0"
+"co.dk\0"
+"dallas.museum\0"
+"leirfjord.no\0cc.ak.us\0"
+"localhistory.museum\0"
+"\xeb\x8b\xb7\xec\xbb\xb4\0"
+"attorney\0"
+"awaji.hyogo.jp\0higashiomi.shiga.jp\0"
+"homelinux.net\0"
+"business\0"
+"meet\0"
+"lib.ks.us\0"
+"krasnik.pl\0"
+"isshiki.aichi.jp\0okayama.okayama.jp\0"
+"koriyama.fukushima.jp\0"
+"horology.museum\0cc.mt.us\0cc.nd.us\0ybo.trade\0"
+"valleeaoste.it\0"
+"williamsburg.museum\0"
+"\xc3\xa5mli.no\0"
+"is-a-linux-user.org\0"
+"vv.it\0kozagawa.wakayama.jp\0"
"co.gg\0"
-"holmestrand.no\0bing\0kitchen\0"
-"urbinopesaro.it\0misato.saitama.jp\0"
-"ag.it\0kalisz.pl\0boston\0"
-"vic.gov.au\0co.gl\0"
-"utazu.kagawa.jp\0better-than.tv\0"
-"foggia.it\0"
-"nodum.co\0"
-"lierne.no\0joburg\0"
-"sado.niigata.jp\0"
-"stathelle.no\0"
-"co.gy\0"
-"monash\0"
-"komatsu\0"
-"ono.hyogo.jp\0"
-"journalism.museum\0"
-"sa.com\0"
-"hicam.net\0"
-"co.id\0\xe9\x95\xb7\xe9\x87\x8e.jp\0dominic.ua\0"
-"co.hu\0dontexist.net\0cya.gg\0"
-"uchinada.ishikawa.jp\0"
-"n\xc3\xa6r\xc3\xb8y.no\0"
-"modena.it\0afamilycompany\0"
-"is-a-chef.net\0"
-"sjc.br\0"
-"co.il\0"
-"co.im\0seiro.niigata.jp\0ap-southeast-1.elasticbeanstalk.com\0s3-sa-east-1.amazonaws.com\0"
-"co.in\0guide\0"
-"co.ir\0nodum.io\0"
-"trentinoaltoadige.it\0co.it\0yachiyo.chiba.jp\0polkowice.pl\0"
-"co.je\0gob.sv\0"
-"graz.museum\0"
-"wroclaw.pl\0"
-"iyo.ehime.jp\0"
-"osakasayama.osaka.jp\0"
-"campania.it\0"
-"co.jp\0diamonds\0"
-"stpetersburg.museum\0"
-"bronnoysund.no\0lomza.pl\0"
-"takko.aomori.jp\0co.ke\0"
-"kisarazu.chiba.jp\0"
-"ota.tokyo.jp\0rybnik.pl\0"
-"sm\xc3\xb8la.no\0vaksdal.no\0"
-"*.kawasaki.jp\0us.eu.org\0"
-"is-an-actress.com\0"
-"l.se\0"
-"loab\xc3\xa1t.no\0"
-"co.kr\0donostia.museum\0"
-"co.lc\0"
-"zoology.museum\0gob.ve\0go.leg.br\0"
-"s3.dualstack.ap-northeast-2.amazonaws.com\0"
-"eu-west-2.elasticbeanstalk.com\0"
-"omigawa.chiba.jp\0"
-"build\0"
-"fg.it\0ruovat.no\0"
-"point2this.com\0"
-"kunitomi.miyazaki.jp\0co.ma\0nt.no\0ballangen.no\0"
-"trani-barletta-andria.it\0"
-"bhz.br\0co.ls\0"
-"co.me\0"
-"co.mg\0"
-"hatsukaichi.hiroshima.jp\0"
-"kameoka.kyoto.jp\0fredrikstad.no\0"
-"isshiki.aichi.jp\0"
-"bologna.it\0"
-"theater.museum\0"
-"ekloges.cy\0"
-"padova.it\0"
-"gosen.niigata.jp\0co.na\0"
-"mo.cn\0"
-"is-a-nascarfan.com\0"
-"\xe0\xb8\xa8\xe0\xb8\xb6\xe0\xb8\x81\xe0\xb8\xa9\xe0\xb8\xb2.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0"
-"co.mu\0hitra.no\0"
-"gose.nara.jp\0"
-"co.mw\0prime\0"
-"co.ni\0"
-"co.mz\0"
-"higashikawa.hokkaido.jp\0co.nl\0"
-"co.no\0"
-"higashi.okinawa.jp\0"
-"seven\0"
-"oirm.gov.pl\0\xd9\xbe\xd8\xa7\xd9\x83\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\0"
-"h\xc3\xa6gebostad.no\0"
-"mj\xc3\xb8ndalen.no\0"
-"sakai.fukui.jp\0"
-"ce.gov.br\0co.nz\0"
+"tokoname.aichi.jp\0"
+"mg.gov.br\0food\0"
+"co.gl\0"
+"wassamu.hokkaido.jp\0hakui.ishikawa.jp\0"
+"orland.no\0"
+"friuli-venezia-giulia.it\0"
+"sanfrancisco.museum\0"
+"omi.niigata.jp\0"
+"h.bg\0infiniti\0"
+"kokonoe.oita.jp\0"
+"co.gy\0meeres.museum\0merseine.nu\0"
+"ebino.miyazaki.jp\0tatar\0"
+"wy.us\0"
+"trentino-altoadige.it\0"
+"malatvuopmi.no\0"
+"\xd8\xa7\xd9\x8a\xd8\xb1\xd8\xa7\xd9\x86\0"
+"melbourne\0"
+"co.id\0valdaosta.it\0"
+"co.hu\0hi.us\0is-a-geek.org\0"
+"xz.cn\0prudential\0"
+"yasugi.shimane.jp\0"
+"games.hu\0from-ct.com\0scrapping.cc\0"
+"so.it\0iwakura.aichi.jp\0saijo.ehime.jp\0"
+"co.il\0friulive-giulia.it\0mielec.pl\0"
+"co.im\0ikano\0msk.ru\0"
+"co.in\0"
+"co.ir\0kurotaki.nara.jp\0"
+"co.it\0ogawa.ibaraki.jp\0"
+"co.je\0"
+"foundation.museum\0clinic\0"
+"kamogawa.chiba.jp\0dr.tr\0"
+"santacruz.museum\0"
+"tsukigata.hokkaido.jp\0ford\0"
+"1.bg\0kalmykia.su\0"
+"shimofusa.chiba.jp\0"
+"bananarepublic\0msk.su\0"
+"umig.gov.pl\0"
+"co.jp\0warman\0"
+"luzern.museum\0s3-ap-northeast-1.amazonaws.com\0"
+"cuneo.it\0"
+"tananger.no\0"
+"vallee-aoste.it\0"
+"co.ke\0lindesnes.no\0cloud.goog\0"
+"milano.it\0"
+"wed\0"
+"wa.edu.au\0is-a-caterer.com\0"
+"edu.krd\0"
+"\xe5\xb2\x90\xe9\x98\x9c.jp\0co.kr\0legal\0rexroth\0"
+"co.lc\0*.stolos.io\0"
+"selfip.net\0"
+"slattum.no\0"
+"kawakami.nagano.jp\0computer\0"
+"stor-elvdal.no\0from-id.com\0"
+"meme\0"
+"co.ma\0"
+"akita.jp\0"
+"co.ls\0"
+"sakai.ibaraki.jp\0"
+"co.me\0royrvik.no\0rocks\0"
+"geek.nz\0"
+"co.mg\0school.na\0cc.co.us\0s3.amazonaws.com\0"
+"kommune.no\0"
+"kalmykia.ru\0"
+"ak.us\0"
+"aogaki.hyogo.jp\0kashima.ibaraki.jp\0"
+"shizuoka.jp\0"
+"co.na\0"
+"tako.chiba.jp\0kamikawa.hokkaido.jp\0"
+"media.museum\0lib.mo.us\0kicks-ass.org\0"
+"co.mu\0"
+"certification.aero\0co.mw\0"
+"nakanojo.gunma.jp\0"
+"suli.hu\0co.ni\0"
+"sicilia.it\0co.mz\0"
+"movistar\0co.nl\0"
+"menu\0"
+"co.no\0utwente.io\0"
+"school.nz\0"
+"vologda.su\0"
+"nu.ca\0george\0"
+"xihuan\0"
+"mt.us\0nd.us\0"
+"drangedal.no\0"
+"\xe5\xaf\x8c\xe5\xb1\xb1.jp\0co.nz\0"
+"rauma.no\0"
"co.om\0"
-"flog.br\0"
-"bj.cn\0"
-"miasa.nagano.jp\0nishikata.tochigi.jp\0bergbau.museum\0"
-"trentinostirol.it\0"
-"okazaki.aichi.jp\0"
-"nedre-eiker.no\0"
-"uryu.hokkaido.jp\0"
-"shriram\0"
-"brussels\0"
+"nakanoto.ishikawa.jp\0"
+"poivron.org\0"
+"cesenaforli.it\0discount\0"
+"loab\xc3\xa1t.no\0"
+"nakijin.okinawa.jp\0win\0"
+"skin\0"
"co.pl\0"
-"valle.no\0"
+"soundandvision.museum\0"
"co.pn\0"
-"vanylven.no\0jprs\0\xe6\x94\xbf\xe5\xba\x9c\0"
-"hakone.kanagawa.jp\0nt.ro\0"
-"portal.museum\0gmina.pl\0"
-"schwarz\0"
-"wakayama.wakayama.jp\0"
-"locus\0"
-"caa.aero\0co.pw\0volkswagen\0"
-"exchange.aero\0shimamoto.osaka.jp\0"
-"coffee\0"
-"nes.buskerud.no\0"
-"vlog.br\0"
-"*.compute.estate\0"
-"filatelia.museum\0"
-"*.otap.co\0"
-"st.no\0"
-"aosta-valley.it\0"
-"r\xc3\xb8yrvik.no\0"
-"alwaysdata.net\0"
-"sec.ps\0"
-"wroc.pl\0"
-"sukumo.kochi.jp\0"
-"bielawa.pl\0co.rs\0od.ua\0"
-"minamiise.mie.jp\0dst.mi.us\0"
-"cancerresearch\0"
-"urausu.hokkaido.jp\0co.rw\0"
-"tabayama.yamanashi.jp\0"
-"kg.kr\0mulhouse.museum\0"
-"g\xc3\xa1ivuotna.no\0"
-"hiroshima.jp\0"
-"lefrak\0"
-"co.st\0futurehosting.at\0"
-"maritime.museum\0"
-"mo.it\0co.th\0"
-"koza.wakayama.jp\0"
-"co.sz\0co.tj\0club.tw\0"
-"co.tm\0"
-"broadcast.museum\0latino\0"
-"muko.kyoto.jp\0berlevag.no\0shaw\0"
-"mutual\0co.ua\0dynvpn.de\0"
-"co.tt\0codespot.com\0"
-"anpachi.gifu.jp\0florist\0"
-"starachowice.pl\0lenug.su\0"
-"co.ug\0from-ga.com\0"
-"hitachi\0"
-"watch-and-clock.museum\0co.tz\0"
+"kasukabe.saitama.jp\0"
+"vgs.no\0notodden.no\0"
+"surgeonshall.museum\0cc.ma.us\0"
+"university.museum\0co.pw\0"
+"klodzko.pl\0"
+"static-access.net\0"
+"kddi\0"
+"volda.no\0troitsk.su\0"
+"kawai.iwate.jp\0"
+"coop.ht\0vc.it\0"
+"ikata.ehime.jp\0"
+"gs.rl.no\0"
+"catanzaro.it\0ogliastra.it\0"
+"\xc3\xa5s.no\0"
+"dreamhosters.com\0"
+"fc.it\0sagamihara.kanagawa.jp\0"
+"skedsmokorset.no\0"
+"lapy.pl\0"
+"figueres.museum\0midsund.no\0tuxfamily.org\0"
+"kushiro.hokkaido.jp\0"
+"x443.pw\0"
+"yamamoto.miyagi.jp\0"
+"blog\0"
+"co.rs\0active\0"
+"co.rw\0"
+"sorfold.no\0"
+"trentino-sued-tirol.it\0"
+"wme\0"
+"shimonita.gunma.jp\0"
+"coop.br\0kadogawa.miyazaki.jp\0"
+"shari.hokkaido.jp\0"
+"avocat.pro\0"
+"massa-carrara.it\0"
+"co.st\0"
+"shop.ht\0"
+"shop.hu\0productions\0"
+"yamaguchi.jp\0es.kr\0co.th\0"
+"co.sz\0co.tj\0"
+"francaise.museum\0co.tm\0ox.rs\0"
+"bl.it\0"
+"e164.arpa\0fhv.se\0"
+"genoa.it\0"
+"co.ua\0"
+"build\0"
+"langev\xc3\xa5g.no\0loabat.no\0"
+"co.tt\0"
+"skydiving.aero\0is-a-designer.com\0"
+"psi.br\0oseto.nagasaki.jp\0"
+"co.ug\0"
+"uji.kyoto.jp\0"
+"co.tz\0"
"co.uk\0"
-"b\xc3\xb8mlo.no\0"
-"tw.cn\0"
-"j.bg\0dell-ogliastra.it\0"
-"cherkassy.ua\0"
-"co.us\0stufftoread.com\0"
-"navigation.aero\0"
-"co.ve\0"
-"nisshin.aichi.jp\0"
-"ebino.miyazaki.jp\0co.vi\0"
-"toyotsu.fukuoka.jp\0co.uz\0"
-"is-a-cubicle-slave.com\0cloud.metacentrum.cz\0"
-"shibetsu.hokkaido.jp\0"
-"minamiizu.shizuoka.jp\0"
-"pg.it\0"
-"cooperativa.bo\0"
-"gs.tr.no\0"
-"vallee-d-aoste.it\0"
-"cc.or.us\0"
-"eun.eg\0"
-"vads\xc3\xb8.no\0travelersinsurance\0dnshome.de\0"
-"helsinki.museum\0"
-"inagi.tokyo.jp\0sola.no\0"
-"dyndns.tv\0"
-"imb.br\0"
-"weibo\0"
-"nombre.bo\0"
-"lib.nv.us\0okinawa\0"
-"soc.lk\0"
-"ninomiya.kanagawa.jp\0ing.pa\0"
-"finland.museum\0"
-"kariya.aichi.jp\0cbg.ru\0"
-"aostavalley.it\0taipei\0"
-"trieste.it\0koganei.tokyo.jp\0bloomberg\0"
-"circle\0ro.im\0"
-"ono.fukui.jp\0"
-"kaizuka.osaka.jp\0"
-"indianapolis.museum\0"
-"ufcfan.org\0"
-"finnoy.no\0"
-"ro.it\0"
-"sa-east-1.elasticbeanstalk.com\0"
-"panerai\0from-mo.com\0"
-"shirakawa.fukushima.jp\0historyofscience.museum\0kids.museum\0"
-"gotemba.shizuoka.jp\0co.za\0"
-"agro.bo\0"
-"parliament.cy\0"
-"dyndns.ws\0"
-"marker.no\0"
-"moonscale.net\0"
-"nakamichi.yamanashi.jp\0"
-"nakayama.yamagata.jp\0"
+"us.na\0"
+"transporte.bo\0"
+"co.us\0"
+"ito.shizuoka.jp\0"
+"osoyro.no\0co.ve\0knightpoint.systems\0"
+"pmn.it\0arita.saga.jp\0sosnowiec.pl\0"
+"sci.eg\0"
+"nu.it\0swinoujscie.pl\0"
+"co.vi\0"
+"co.uz\0"
+"nissedal.no\0"
+"grainger\0"
+"wow\0"
+"associates\0"
+"narusawa.yamanashi.jp\0"
+"rodeo\0"
+"kiyama.saga.jp\0"
+"lib.ak.us\0"
+"medio-campidano.it\0"
+"chikushino.fukuoka.jp\0mazowsze.pl\0"
+"ogori.fukuoka.jp\0kitaura.miyazaki.jp\0"
+"luxe\0"
+"assabu.hokkaido.jp\0"
+"geelvinck.museum\0"
+"malopolska.pl\0"
+"living.museum\0"
+"farmers.museum\0coffee\0"
+"fukushima.jp\0shingo.aomori.jp\0sasaguri.fukuoka.jp\0toyotomi.hokkaido.jp\0"
+"b\xc3\xa1hcavuotna.no\0"
+"tempio-olbia.it\0"
+"rl.no\0blue\0"
+"perugia.it\0"
+"commbank\0"
+"chichibu.saitama.jp\0"
+"hattfjelldal.no\0h.se\0"
+"inami.toyama.jp\0"
+"ftpaccess.cc\0"
+"yurihonjo.akita.jp\0"
+"nb.ca\0draydns.de\0"
+"mymediapc.net\0"
+"ma.us\0co.za\0"
+"kitaakita.akita.jp\0kosuge.yamanashi.jp\0"
+"docs\0"
+"tranibarlettaandria.it\0"
+"sydney.museum\0"
+"tamamura.gunma.jp\0onion\0"
+"taketomi.okinawa.jp\0myeffect.net\0"
+"k12.wi.us\0wtc\0"
+"noda.iwate.jp\0wtf\0"
"co.zm\0"
-"shinanomachi.nagano.jp\0xihuan\0"
-"rissa.no\0"
-"trentino-sud-tirol.it\0funabashi.chiba.jp\0podlasie.pl\0"
-"podzone.org\0"
-"safety.aero\0"
-"neyagawa.osaka.jp\0marylhurst.museum\0co.zw\0"
-"haboro.hokkaido.jp\0"
-"fukushima.jp\0"
-"channel\0shia\0"
-"kita.osaka.jp\0v\xc3\xa5ler.hedmark.no\0"
-"higashiura.aichi.jp\0chintai\0navoi.su\0"
-"\xe5\x8c\x97\xe6\xb5\xb7\xe9\x81\x93.jp\0"
-"\xe0\xb0\xad\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\xa4\xe0\xb1\x8d\0"
-"chikuhoku.nagano.jp\0toga.toyama.jp\0"
-"balsan-sudtirol.it\0"
-"ismaili\0\xe5\xbe\xae\xe5\x8d\x9a\0"
-"sinaapp.com\0"
-"trentin-su\xcc\x88""d-tirol.it\0lecco.it\0"
-"itabashi.tokyo.jp\0"
-"farmequipment.museum\0dr.na\0"
-"host\0gb.com\0"
-"\xe4\xba\xac\xe9\x83\xbd.jp\0"
-"akita.akita.jp\0shimogo.fukushima.jp\0"
-"furubira.hokkaido.jp\0idrett.no\0"
-"ginan.gifu.jp\0"
-"minato.osaka.jp\0pyatigorsk.ru\0"
-"\xe0\xa6\xad\xe0\xa6\xbe\xe0\xa7\xb0\xe0\xa6\xa4\0"
-"web.bo\0from-ct.com\0"
-"erimo.hokkaido.jp\0"
-"test.tj\0"
-"games.hu\0kawakami.nagano.jp\0"
-"technology.museum\0"
-"target\0"
-"web.co\0"
-"repbody.aero\0"
-"\xd0\xbf\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0"
-"sondrio.it\0circus.museum\0"
-"plo.ps\0"
-"savannahga.museum\0"
-"web.do\0"
-"ide.kyoto.jp\0civilisation.museum\0"
-"caxias.br\0"
-"valle-aosta.it\0global.ssl.fastly.net\0"
-"geology.museum\0"
-"sweden.museum\0"
-"yashio.saitama.jp\0mo.us\0vodka\0"
-"test.ru\0"
-"troitsk.su\0"
-"hirara.okinawa.jp\0mymediapc.net\0"
-"glug.org.uk\0"
-"modum.no\0"
-"eti.br\0game.tw\0from-pa.com\0"
-"kamakura.kanagawa.jp\0"
-"blogdns.com\0"
-"foodnetwork\0"
-"k12.mi.us\0"
-"toyotomi.hokkaido.jp\0"
-"r.cdn77.net\0"
-"yachimata.chiba.jp\0"
-"is-into-cars.com\0"
-"trentin-suedtirol.it\0"
-"tecnologia.bo\0az.us\0"
-"tado.mie.jp\0"
-"suedtirol.it\0shop\0"
-"from-dc.com\0"
-"matsue.shimane.jp\0"
-"horse\0"
-"web.gu\0"
-"show\0"
-"kawachinagano.osaka.jp\0reise\0"
-"neues.museum\0"
-"steam.museum\0"
-"cc.nm.us\0"
-"genting\0"
-"go.gov.br\0"
-"higashishirakawa.gifu.jp\0clinton.museum\0"
-"web.id\0dr.tr\0"
-"genova.it\0"
-"dynserv.org\0zapto.org\0"
-"lib.nm.us\0\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4\0ath.cx\0"
-"bo.telemark.no\0"
-"gamagori.aichi.jp\0"
-"dyn.ddnss.de\0"
-"muroran.hokkaido.jp\0"
+"horokanai.hokkaido.jp\0"
+"ikeda.nagano.jp\0"
+"jor.br\0"
+"y.bg\0co.zw\0"
+"news.hu\0"
"xen.prgmr.com\0"
-"svn-repos.de\0"
-"\xe7\xa6\x8f\xe5\xb2\xa1.jp\0"
-"\xd9\x83\xd8\xa7\xd8\xab\xd9\x88\xd9\x84\xd9\x8a\xd9\x83\0"
-"tochigi.jp\0"
+"otaki.saitama.jp\0"
+"ipifony.net\0"
+"minamitane.kagoshima.jp\0olecko.pl\0"
+"jpn.com\0workisboring.com\0"
+"tjome.no\0"
+"forli-cesena.it\0"
+"os.hordaland.no\0"
+"ako.hyogo.jp\0"
+"video.hu\0"
+"huissier-justice.fr\0kotohira.kagawa.jp\0"
+"tp.it\0ichikai.tochigi.jp\0"
+"gdansk.pl\0"
+"maizuru.kyoto.jp\0"
+"hsbc\0icbc\0lanxess\0singles\0elasticbeanstalk.com\0"
+"katowice.pl\0"
+"consulting.aero\0"
+"detroit.museum\0"
+"yaese.okinawa.jp\0"
+"office\0"
+"umbria.it\0"
+"toyota.aichi.jp\0gotemba.shizuoka.jp\0"
+"selfip.info\0"
+"vadso.no\0"
+"mo\xc3\xa5reke.no\0doha\0work\0"
+"ohkura.yamagata.jp\0"
+"pictures\0myphotos.cc\0"
+"eu.int\0shonai.fukuoka.jp\0sennan.osaka.jp\0"
+"philately.museum\0"
+"gallery\0"
+"misato.shimane.jp\0"
+"aerobatic.aero\0review\0"
+"yatomi.aichi.jp\0"
+"tosashimizu.kochi.jp\0"
+"gs.mr.no\0"
+"gd.cn\0"
+"polkowice.pl\0"
+"bale.museum\0"
+"zara\0"
+"mutsu.aomori.jp\0"
+"jaworzno.pl\0doctor\0xin\0"
+"chimkent.su\0sinaapp.com\0"
+"nishiarita.saga.jp\0"
+"cloudcontrolled.com\0"
+"chrome\0aktyubinsk.su\0"
+"muroto.kochi.jp\0"
+"tama.tokyo.jp\0"
+"hanyu.saitama.jp\0"
+"s3-website.us-east-2.amazonaws.com\0"
+"\xe8\x87\xba\xe7\x81\xa3\0"
+"\xe7\xbd\x91\xe5\x9d\x80\0"
+"\xe0\xb8\xad\xe0\xb8\x87\xe0\xb8\x84\xe0\xb9\x8c\xe0\xb8\x81\xe0\xb8\xa3.\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0"
+"homelinux.org\0"
+"noda.chiba.jp\0"
+"ama.aichi.jp\0ami.ibaraki.jp\0"
+"misato.akita.jp\0"
+"cci.fr\0kawanishi.nara.jp\0"
+"cechire.com\0"
+"\xd8\xa8\xd8\xa7\xd8\xb2\xd8\xa7\xd8\xb1\0"
+"newholland\0vistaprint\0"
+"lucerne.museum\0"
+"vibo-valentia.it\0"
+"jp.eu.org\0"
+"haebaru.okinawa.jp\0suginami.tokyo.jp\0"
+"otofuke.hokkaido.jp\0kasuga.hyogo.jp\0"
+"mydatto.net\0"
+"marnardal.no\0"
+"blogspot.com.cy\0"
+"monster\0"
+"shimane.jp\0chikugo.fukuoka.jp\0zgora.pl\0"
+"komatsu\0"
+"trentino.it\0yakumo.shimane.jp\0"
+"tatamotors\0"
+"morioka.iwate.jp\0"
+"\xe9\xa3\x9f\xe5\x93\x81\0blogspot.com.ee\0"
+"kherson.ua\0blogspot.com.eg\0nid.io\0"
+"rendalen.no\0"
+"is-a-financialadvisor.com\0"
"kouhoku.saga.jp\0"
-"s3.ap-south-1.amazonaws.com\0"
-"pz.it\0"
-"voss.no\0"
-"tochio.niigata.jp\0"
-"akashi.hyogo.jp\0"
-"yorii.saitama.jp\0"
-"palmas.br\0"
-"lenvik.no\0sport\0"
-"v\xc3\xa5ler.\xc3\xb8stfold.no\0es.eu.org\0"
-"molde.no\0strand.no\0k12.ri.us\0homeip.net\0"
-"horology.museum\0"
-"trento.it\0toyota\0khakassia.su\0"
-"travel.pl\0"
-"ggf.br\0karmoy.no\0"
-"mimata.miyazaki.jp\0fedje.no\0ltda\0cloudns.pro\0"
-"costume.museum\0"
-"web.lk\0"
-"hornindal.no\0"
+"myasustor.com\0"
+"blogspot.com.ar\0"
+"vt.it\0"
+"alipay\0blogspot.com.au\0"
+"is-a-geek.net\0"
+"youth.museum\0"
+"kasuga.fukuoka.jp\0arao.kumamoto.jp\0is.gov.pl\0"
+"kozow.com\0"
+"daegu.kr\0*.kunden.ortsinfo.at\0"
+"weber\0"
+"game\0"
+"umaji.kochi.jp\0"
+"mr.no\0service.gov.uk\0"
+"hamamatsu.shizuoka.jp\0blogspot.com.br\0"
+"russia.museum\0spb.ru\0"
+"coop.tt\0"
+"f.bg\0is-uberleet.com\0krasnodar.su\0"
+"liaison\0"
+"karlsoy.no\0blogspot.com.by\0"
+"sandiego.museum\0"
+"republican\0"
+"v\xc3\xa5ler.hedmark.no\0"
+"obuse.nagano.jp\0"
+"blogspot.com.co\0"
+"historicalsociety.museum\0"
+"masuda.shimane.jp\0"
+"spb.su\0"
+"oizumi.gunma.jp\0"
+"wallonie.museum\0versicherung\0"
+"coop.mv\0"
+"coop.mw\0"
+"naka.ibaraki.jp\0isahaya.nagasaki.jp\0"
+"lierne.no\0utsira.no\0"
+"onna.okinawa.jp\0es.leg.br\0"
+"bydgoszcz.pl\0\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4\0jaguar\0"
+"sochi.su\0"
+"biei.hokkaido.jp\0konan.shiga.jp\0shop.th\0"
+"gliwice.pl\0"
+"trentinos-tirol.it\0"
+"uozu.toyama.jp\0"
+"dp.ua\0"
+"cc.vt.us\0"
+"bomlo.no\0"
+"grondar.za\0dyn.home-webserver.de\0"
+"gangaviika.no\0"
"okayama.jp\0"
-"!city.kobe.jp\0chikuho.fukuoka.jp\0"
-"fe.it\0is-very-sweet.org\0"
-"air-traffic-control.aero\0"
-"sr.it\0konan.aichi.jp\0"
-"natori.miyagi.jp\0"
-"ginowan.okinawa.jp\0"
-"date.hokkaido.jp\0"
-"konyvelo.hu\0newyork.museum\0"
-"pubol.museum\0"
-"web.nf\0"
-"cremona.it\0"
-"web.ni\0"
-"treviso.it\0temp-dns.com\0"
-"kumano.hiroshima.jp\0"
-"bergen.no\0hermes\0"
-"narviika.no\0"
-"kuriyama.hokkaido.jp\0"
-"kwp.gov.pl\0sucks\0"
-"hino.tottori.jp\0firewall-gateway.de\0"
-"custom.metacentrum.cz\0"
-"photography.museum\0"
-"search\0"
-"partners\0"
-"nakagusuku.okinawa.jp\0"
-"koeln.museum\0"
-"friulivgiulia.it\0"
-"pe.ca\0"
-"riik.ee\0nagiso.nagano.jp\0giske.no\0"
-"ivgu.no\0"
-"works\0"
-"world\0"
-"matera.it\0"
-"cim.br\0web.pk\0is-a-celticsfan.org\0"
-"taiji.wakayama.jp\0cruise\0"
-"travel.tt\0"
-"sokndal.no\0"
-"k12.wi.us\0mc.eu.org\0"
-"nishiwaki.hyogo.jp\0"
-"hob\xc3\xb8l.no\0"
-"repair\0"
-"miyota.nagano.jp\0mesaverde.museum\0oregontrail.museum\0"
-"hitachinaka.ibaraki.jp\0and.museum\0"
-"patria.bo\0koka.shiga.jp\0"
-"starnberg.museum\0"
-"ooguy.com\0"
-"udono.mie.jp\0"
-"\xe5\xa4\xa9\xe4\xb8\xbb\xe6\x95\x99\0"
-"\xe5\xb3\xb6\xe6\xa0\xb9.jp\0"
-"is-gone.com\0"
-"kadena.okinawa.jp\0"
-"trani-andria-barletta.it\0"
+"townnews-staging.com\0"
+"parma.it\0"
+"agents.aero\0doesntexist.com\0blogspot.com.es\0"
+"student.aero\0engineering\0"
+"college\0cloudns.asia\0"
+"tgory.pl\0embaixada.st\0"
+"mus.mi.us\0"
+"katsuragi.wakayama.jp\0kolobrzeg.pl\0"
+"shop.ro\0"
+"tas.gov.au\0"
+"pharmacien.fr\0sakura.chiba.jp\0"
+"coop.py\0zhitomir.ua\0"
+"jefferson.museum\0mangyshlak.su\0"
+"georgia.museum\0"
+"reggiocalabria.it\0muroran.hokkaido.jp\0"
+"pomorze.pl\0lancaster\0"
+"dinosaur.museum\0fyresdal.no\0"
+"kvitsoy.no\0dyndns1.de\0"
+"tsukiyono.gunma.jp\0"
+"lo.it\0"
+"zippo\0"
+"shop.pl\0"
+"genting\0mitsubishi\0"
+"bj.cn\0"
+"frei.no\0"
+"hurum.no\0y.se\0"
+"linkyard.cloud\0"
+"antiques.museum\0"
+"kimitsu.chiba.jp\0aisho.shiga.jp\0"
+"coop.km\0dattorelay.com\0"
+"lilly\0"
+"wegrow.pl\0"
+"ns.ca\0"
+"fujieda.shizuoka.jp\0"
+"\xe4\xba\xac\xe9\x83\xbd.jp\0"
+"dielddanuorri.no\0"
+"\xe9\xa6\x99\xe5\xb7\x9d.jp\0"
+"kasaoka.okayama.jp\0"
+"gs.va.no\0alpha.bounty-full.com\0"
+"free\0"
+"hyatt\0"
+"mansions.museum\0"
+"\xe6\xb2\x96\xe7\xb8\x84.jp\0"
+"hangout\0"
+"larsson.museum\0"
+"osakasayama.osaka.jp\0"
+"fortworth.museum\0googlecode.com\0securitytactics.com\0"
+"kochi.jp\0"
+"nuernberg.museum\0br\xc3\xb8nn\xc3\xb8y.no\0"
+"elk.pl\0"
+"caltanissetta.it\0owani.aomori.jp\0"
+"\xe7\xbb\x84\xe7\xbb\x87.hk\0"
+"tateyama.toyama.jp\0fbx-os.fr\0"
+"hanawa.fukushima.jp\0"
+"berlevag.no\0eid.no\0"
+"audnedaln.no\0gitlab.io\0"
+"kosei.shiga.jp\0"
+"namie.fukushima.jp\0"
+"firestone\0insure\0"
+"stat.no\0"
+"va.it\0fudai.iwate.jp\0"
+"nishikawa.yamagata.jp\0xxx\0"
+"uvic.museum\0"
+"dynalias.com\0"
+"yokkaichi.mie.jp\0"
+"mutsuzawa.chiba.jp\0uwajima.ehime.jp\0"
+"kirovograd.ua\0"
+"selfip.org\0"
+"nittedal.no\0"
+"lucania.it\0higashiizu.shizuoka.jp\0"
+"asmatart.museum\0exhibition.museum\0"
+"vt.us\0"
+"riobranco.br\0xyz\0*.ex.ortsinfo.at\0blogspot.com.mt\0"
+"aseral.no\0"
+"warmia.pl\0"
+"blogspot.com.ng\0"
+"mizumaki.fukuoka.jp\0"
+"sandoy.no\0"
+"hatsukaichi.hiroshima.jp\0"
+"pokrovsk.su\0"
+"laspezia.it\0"
+"is-certified.com\0"
+"motegi.tochigi.jp\0hayakawa.yamanashi.jp\0"
+"sm.ua\0"
+"babia-gora.pl\0"
+"bo.telemark.no\0narviika.no\0"
+"he.cn\0esan.hokkaido.jp\0unzen.nagasaki.jp\0"
+"vevelstad.no\0s3-fips-us-gov-west-1.amazonaws.com\0test-iserv.de\0"
+"valleaosta.it\0"
+"ciencia.bo\0fuossko.no\0s\xc3\xb8rreisa.no\0lib.ct.us\0"
+"dyn-ip24.de\0hasura-app.io\0"
+"cc.va.us\0"
+"k\xc3\xa1r\xc3\xa1\xc5\xa1johka.no\0"
+"nagi.okayama.jp\0gbiz\0"
+"aid.pl\0"
+"hole.no\0"
+"nakai.kanagawa.jp\0"
+"chieti.it\0"
+"flatanger.no\0krodsherad.no\0"
+"reggio-emilia.it\0"
+"us.org\0"
+"blogspot.com.tr\0"
+"is-a-llama.com\0"
+"enebakk.no\0scrysec.com\0"
+"*.sensiosite.cloud\0"
+"va.no\0k12.nm.us\0"
+"kurogi.fukuoka.jp\0shingu.hyogo.jp\0"
+"carrara-massa.it\0tamakawa.fukushima.jp\0"
+"s3-us-west-2.amazonaws.com\0"
+"kurobe.toyama.jp\0"
+"shizuoka.shizuoka.jp\0"
+"go-vip.co\0"
+"saintlouis.museum\0"
+"appspot.com\0"
+"cc.az.us\0"
+"hisayama.fukuoka.jp\0"
+"claims\0"
+"cog.mi.us\0"
+"sorocaba.br\0siteleaf.net\0"
+"historical.museum\0"
+"us-east-2.elasticbeanstalk.com\0"
+"torino.it\0"
+"iveland.no\0"
+"tokuyama.yamaguchi.jp\0"
+"clinton.museum\0you\0groks-this.info\0"
+"kiwa.mie.jp\0"
+"f.se\0"
+"mishima.shizuoka.jp\0"
+"lutsk.ua\0here-for-more.info\0"
+"s3.dualstack.ap-northeast-2.amazonaws.com\0barsyonline.com\0"
+"kirkenes.no\0"
+"mp.br\0"
+"mup.gov.pl\0"
+"flights\0"
+"\xe7\x82\xb9\xe7\x9c\x8b\0"
+"kunisaki.oita.jp\0"
+"sdn.gov.pl\0"
+"siellak.no\0"
+"otsu.shiga.jp\0"
+"is.eu.org\0"
+"netflix\0"
+"bahcavuotna.no\0\xe5\x81\xa5\xe5\xba\xb7\0potager.org\0"
+"kongsberg.no\0"
+"telefonica\0"
+"w.bg\0"
+"hasami.nagasaki.jp\0"
+"homebuilt.aero\0"
+"blogspot.com.uy\0"
+"school.za\0stage.nodeart.io\0"
+"bibai.hokkaido.jp\0"
+"city.hu\0lacaixa\0"
+"bofa\0"
+"izumi.kagoshima.jp\0"
+"monticello.museum\0cityeats\0"
+"essex.museum\0tjeldsund.no\0"
+"kakegawa.shizuoka.jp\0sncf\0"
+"gifts\0"
+"tn.it\0saitama.saitama.jp\0"
+"katagami.akita.jp\0"
+"it.eu.org\0"
+"monza-brianza.it\0"
+"js.org\0"
+"yamada.fukuoka.jp\0"
+"kagamiishi.fukushima.jp\0"
+"bjark\xc3\xb8y.no\0bplaced.com\0"
+"trd.br\0"
+"aland.fi\0"
+"ogi.saga.jp\0chungnam.kr\0"
+"deatnu.no\0likes-pie.com\0"
+"avellino.it\0"
+"va.us\0moscow\0barsy.mobi\0"
+"gildesk\xc3\xa5l.no\0mydrobo.com\0"
+"akkeshi.hokkaido.jp\0"
+"alvdal.no\0cc.gu.us\0"
+"is-an-artist.com\0"
+"shiroi.chiba.jp\0"
+"h\xc3\xa6gebostad.no\0firmdale\0uy.com\0webhosting.be\0"
+"americanexpress\0traeumtgerade.de\0"
+"nishitosa.kochi.jp\0sakawa.kochi.jp\0yun\0"
+"\xec\x82\xbc\xec\x84\xb1\0"
+"pisz.pl\0"
+"monzaebrianza.it\0yugawara.kanagawa.jp\0"
+"gotpantheon.com\0"
+"goldpoint\0"
+"koga.fukuoka.jp\0"
+"likescandy.com\0"
+"ag.it\0"
+"\xc3\xb8ygarden.no\0"
+"ogata.akita.jp\0gangwon.kr\0"
+"workshop.museum\0filegear-jp.me\0"
+"consulado.st\0"
+"l\xc3\xa6rdal.no\0cc.tn.us\0\xe7\xbd\x91\xe7\xab\x99\0"
+"\xe7\xb5\x84\xe7\xbb\x87.hk\0marketing\0"
+"fujiyoshida.yamanashi.jp\0"
+"repbody.aero\0sk.ca\0ralingen.no\0"
+"trust\0"
+"bulsan-sudtirol.it\0"
+"sasayama.hyogo.jp\0"
+"lib.ee\0az.us\0"
+"ofunato.iwate.jp\0shibata.miyagi.jp\0"
+"\xe5\xae\xb6\xe9\x9b\xbb\0in.eu.org\0"
+"andria-trani-barletta.it\0katsuragi.nara.jp\0"
+"freeddns.org\0"
+"belem.br\0"
+"lebesby.no\0"
+"consultant.aero\0amli.no\0"
+"\xe5\x9f\xbc\xe7\x8e\x89.jp\0"
+"ivgu.no\0viking\0"
+"sebastopol.ua\0"
+"author\0ddns.net\0"
+"ieee\0"
+"mat.br\0\xe5\xae\xae\xe5\x9f\x8e.jp\0"
+"services\0"
+"\xd0\xb1\xd0\xb5\xd0\xbb\0"
+"sayo.hyogo.jp\0shiiba.miyazaki.jp\0zip\0buyshouses.net\0"
+"wmflabs.org\0"
+"from-or.com\0"
+"moma.museum\0homeoffice.gov.uk\0"
+"children.museum\0"
+"balsan-sudtirol.it\0"
+"winners\0"
+"is-very-evil.org\0"
+"\xe9\xa4\x90\xe5\x8e\x85\0from-pr.com\0"
+"gj\xc3\xb8vik.no\0appchizi.com\0"
+"miyazaki.miyazaki.jp\0shiroishi.saga.jp\0anquan\0channel\0"
+"prd.fr\0koganei.tokyo.jp\0"
+"boleslawiec.pl\0exposed\0"
+"nishi.osaka.jp\0sagae.yamagata.jp\0bond\0"
+"iwama.ibaraki.jp\0"
+"surgery\0servep2p.com\0"
+"ayase.kanagawa.jp\0"
+"maintenance.aero\0"
+"yawata.kyoto.jp\0"
+"skjak.no\0vuelos\0"
+"vr.it\0kunohe.iwate.jp\0"
+"brussels.museum\0os.hedmark.no\0sk\xc3\xa5nland.no\0eu.meteorapp.com\0"
+"minamiise.mie.jp\0"
+"hagebostad.no\0"
+"rishiri.hokkaido.jp\0wzmiuw.gov.pl\0"
+"floripa.br\0namegata.ibaraki.jp\0xerox\0from-co.net\0"
+"fr.it\0higashikagura.hokkaido.jp\0saku.nagano.jp\0"
+"lib.il.us\0book\0"
+"saigawa.fukuoka.jp\0"
+"sirdal.no\0linde\0myjino.ru\0"
+"poker\0"
+"d.bg\0is-an-entertainer.com\0is-not-certified.com\0"
+"serveftp.net\0"
+"medecin.km\0"
+"yaotsu.gifu.jp\0"
+"vagsoy.no\0"
+"campidano-medio.it\0kamijima.ehime.jp\0"
+"gotsu.shimane.jp\0"
+"onthewifi.com\0"
+"\xd8\xa8\xda\xbe\xd8\xa7\xd8\xb1\xd8\xaa\0"
+"gu.us\0\xd0\xbe\xd0\xbd\xd0\xbb\xd0\xb0\xd0\xb9\xd0\xbd\0"
+"trentinosud-tirol.it\0firenze.it\0\xe3\x83\x9d\xe3\x82\xa4\xe3\x83\xb3\xe3\x83\x88\0"
+"yamanashi.yamanashi.jp\0realm.cz\0"
+"cruises\0"
+"dn.ua\0bharti\0"
+"tynset.no\0"
+"\xd8\xa7\xd9\x84\xd8\xac\xd8\xb2\xd8\xa7\xd8\xa6\xd8\xb1\0"
+"tn.us\0"
+"prd.km\0r\xc3\xb8yken.no\0"
+"t3l3p0rt.net\0"
+"plants.museum\0"
+"vall\xc3\xa9""e-d-aoste.it\0nagaoka.niigata.jp\0rybnik.pl\0"
+"yasu.shiga.jp\0"
+"randaberg.no\0"
+"\xeb\x8b\xb7\xeb\x84\xb7\0"
+"ot.it\0pd.it\0\xe5\x92\x8c\xe6\xad\x8c\xe5\xb1\xb1.jp\0"
+"hitachinaka.ibaraki.jp\0"
+"b\xc3\xa1id\xc3\xa1r.no\0k12.oh.us\0"
+"alstahaug.no\0"
+"\xd5\xb0\xd5\xa1\xd5\xb5\0\xd0\xbe\xd1\x80\xd0\xb3.\xd1\x81\xd1\x80\xd0\xb1\0"
+"yamatokoriyama.nara.jp\0dentist\0"
+"lib.az.us\0"
+"taiki.hokkaido.jp\0kitayama.wakayama.jp\0"
+"prd.mg\0bahccavuotna.no\0"
+"a.ssl.fastly.net\0"
+"ushistory.museum\0"
+"is-an-actress.com\0"
+"fedje.no\0gop.pk\0"
+"kikugawa.shizuoka.jp\0"
+"kvits\xc3\xb8y.no\0"
+"slz.br\0"
+"castres.museum\0training\0lebtimnetz.de\0"
+"shimonoseki.yamaguchi.jp\0"
+"architecture.museum\0"
+"lib.ms.us\0lib.nc.us\0"
+"dev-myqnapcloud.com\0"
+"\xe0\xa8\xad\xe0\xa8\xbe\xe0\xa8\xb0\xe0\xa8\xa4\0"
+"w.se\0"
+"broker\0"
+"database.museum\0"
+"soka.saitama.jp\0norton\0"
+"kushima.miyazaki.jp\0"
+"\xe9\x9b\x86\xe5\x9b\xa2\0"
+"sjc.br\0"
+"emilia-romagna.it\0"
+"spy.museum\0s3-ap-northeast-2.amazonaws.com\0"
+"kasamatsu.gifu.jp\0"
+"kagoshima.kagoshima.jp\0"
+"pa.gov.br\0"
+"s3-ap-southeast-2.amazonaws.com\0"
+"xbox\0*.futurecms.at\0"
+"*.sendai.jp\0"
+"abbott\0"
+"fjaler.no\0"
+"b\xc3\xa6rum.no\0"
+"minoh.osaka.jp\0"
+"agrar.hu\0"
+"markets\0"
+"computerhistory.museum\0notteroy.no\0"
+"kaita.hiroshima.jp\0"
+"indianmarket.museum\0lib.wa.us\0"
+"naklo.pl\0"
+"taa.it\0"
+"luster.no\0"
+"pb.gov.br\0"
+"ybo.party\0"
+"sand\xc3\xb8y.no\0"
+"lib.ga.us\0"
+"vall\xc3\xa9""edaoste.it\0ichikawa.chiba.jp\0"
+"mini\0"
+"yusui.kagoshima.jp\0schokokeks.net\0"
+"automotive.museum\0"
+"kunstunddesign.museum\0barum.no\0"
+"nasushiobara.tochigi.jp\0"
+"from-ar.com\0"
+"amakusa.kumamoto.jp\0kai.yamanashi.jp\0"
+"miyake.nara.jp\0mint\0"
+"aviation.museum\0fauske.no\0"
+"zlg.br\0shiriuchi.hokkaido.jp\0"
+"askvoll.no\0"
+"tmall\0"
+"ngo.lk\0poltava.ua\0"
+"s3.ap-northeast-2.amazonaws.com\0"
+"tenei.fukushima.jp\0spiegel\0"
+"kinokawa.wakayama.jp\0"
+"gs.cn\0experts-comptables.fr\0toride.ibaraki.jp\0"
+"jewishart.museum\0ivano-frankivsk.ua\0sohu\0"
+"wuoz.gov.pl\0"
+"palmsprings.museum\0dnepropetrovsk.ua\0"
+"koeln\0"
+"mallorca.museum\0"
+"nirasaki.yamanashi.jp\0bayern\0"
+"m\xc3\xa1tta-v\xc3\xa1rjjat.no\0ck.ua\0"
+"fetsund.no\0"
+"medical.museum\0blogsite.org\0"
+"komono.mie.jp\0powiat.pl\0"
+"ath.cx\0"
+"piw.gov.pl\0"
+"\xe5\xb3\xb6\xe6\xa0\xb9.jp\0glogow.pl\0nat.tn\0"
+"natural.bo\0mosjoen.no\0"
+"akiruno.tokyo.jp\0bplaced.net\0"
+"taito.tokyo.jp\0"
+"beskidy.pl\0"
+"film.museum\0"
+"sellsyourhome.org\0"
+"foodnetwork\0"
+"boavista.br\0saogonca.br\0yabu.hyogo.jp\0"
+"aomori.jp\0"
+"sakata.yamagata.jp\0"
+"\xe0\xae\x9a\xe0\xae\xbf\xe0\xae\x99\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xaa\xe0\xaf\x8d\xe0\xae\xaa\xe0\xaf\x82\xe0\xae\xb0\xe0\xaf\x8d\0"
+"sera.hiroshima.jp\0psse.gov.pl\0"
+"safety\0*.platformsh.site\0"
+"\xe7\xa6\x8f\xe5\xb2\xa1.jp\0ngo.ph\0travelchannel\0"
+"express\0s3.dualstack.ap-southeast-1.amazonaws.com\0"
+"kv\xc3\xa6""fjord.no\0"
+"slg.br\0"
+"ventures\0"
+"sakuho.nagano.jp\0utsunomiya.tochigi.jp\0"
+"audible\0"
+"yanagawa.fukuoka.jp\0"
+"kashiwara.osaka.jp\0a.prod.fastly.net\0"
+"homedns.org\0"
+"lib.md.us\0"
+"*.ex.futurecms.at\0"
+"gaivuotna.no\0k12.in.us\0"
+"protection\0"
+"engineer.aero\0lavangen.no\0"
+"opencraft.hosting\0"
+"olayangroup\0"
+"celtic.museum\0d.se\0"
+"\xe6\x9c\xba\xe6\x9e\x84\0"
+"and.museum\0"
+"kanzaki.saga.jp\0"
+"principe.st\0"
+"politie\0song\0"
+"\xd8\xb9\xd8\xb1\xd8\xa7\xd9\x82\0"
+"cheltenham.museum\0marker.no\0"
+"\xc3\xa5""fjord.no\0"
+"daejeon.kr\0"
+"mizusawa.iwate.jp\0"
+"sony\0"
+"gru.br\0tosa.kochi.jp\0"
+"barlettatraniandria.it\0"
+"if.ua\0"
+"u.bg\0"
+"shimamaki.hokkaido.jp\0"
+"h\xc3\xb8ylandet.no\0"
+"bible\0ferrari\0"
+"vana\0"
+"medecin.fr\0"
+"pyatigorsk.ru\0"
+"\xe9\xa6\x99\xe6\xb8\xaf\0statefarm\0today\0"
+"kutno.pl\0"
+"education.museum\0is-a-player.com\0"
+"!city.kobe.jp\0bialowieza.pl\0frontdoor\0"
+"ap-southeast-2.elasticbeanstalk.com\0"
+"firewall-gateway.net\0"
+"presse.km\0mozilla-iot.org\0"
+"airguard.museum\0hzc.io\0"
+"arteducation.museum\0research.museum\0"
+"tsushima.nagasaki.jp\0"
+"karacol.su\0"
+"ishigaki.okinawa.jp\0"
+"freight.aero\0\xc3\xb8rland.no\0"
+"dnsdojo.com\0"
+"selfip.biz\0hasura.app\0"
+"tozsde.hu\0vlaanderen.museum\0"
+"nakasatsunai.hokkaido.jp\0"
+"\xe6\x84\x9b\xe7\x9f\xa5.jp\0mihama.aichi.jp\0matsudo.chiba.jp\0tachikawa.tokyo.jp\0"
+"toyonaka.osaka.jp\0"
+"ws.na\0"
+"tomisato.chiba.jp\0takahashi.okayama.jp\0matsuzaki.shizuoka.jp\0"
+"presse.ml\0"
+"gouv.fr\0"
+"cafe\0"
+"ascolipiceno.it\0"
+"pu.it\0"
+"osaka\0"
+"demon.nl\0"
+"lotte\0pt.eu.org\0"
+"sortland.no\0"
+"nord-odal.no\0"
+"servebeer.com\0"
+"lotto\0"
+"kazo.saitama.jp\0"
+"nalchik.ru\0"
+"pi.gov.br\0vlaanderen\0"
+"dsmynas.com\0"
+"kepno.pl\0"
+"childrens.museum\0"
+"gouv.ht\0"
+"api.stdlib.com\0"
+"\xce\xb5\xce\xbb\0"
+"mn.it\0\xe5\x8c\x97\xe6\xb5\xb7\xe9\x81\x93.jp\0"
+"pb.ao\0fylkesbibl.no\0"
+"fusa.no\0ngo.za\0nalchik.su\0"
+"dodge\0"
+"or.at\0"
+"grue.no\0"
+"kazimierz-dolny.pl\0"
+"or.bi\0"
+"se.net\0ru.net\0"
+"scientist.aero\0"
+"gouv.bj\0"
+"selje.no\0"
+"sopot.pl\0"
+"spdns.eu\0"
+"shimotsuma.ibaraki.jp\0tanabe.wakayama.jp\0intl.tn\0dev.static.land\0"
+"taka.hyogo.jp\0shimokitayama.nara.jp\0"
+"or.ci\0"
+"szex.hu\0chesapeakebay.museum\0"
+"gouv.ci\0"
+"sener\0"
+"kraanghke.no\0"
+"or.cr\0nakano.tokyo.jp\0"
+"lib.ky.us\0"
+"\xd8\xa7\xd8\xaa\xd8\xb5\xd8\xa7\xd9\x84\xd8\xa7\xd8\xaa\0"
+"microlight.aero\0ollo\0"
+"ota.gunma.jp\0himeshima.oita.jp\0"
+"tokashiki.okinawa.jp\0"
+"nsw.edu.au\0"
+"\xe7\x86\x8a\xe6\x9c\xac.jp\0"
+"botanical.museum\0"
+"house.museum\0"
+"cc.mn.us\0"
+"ogaki.gifu.jp\0"
+"gran.no\0"
+"shinichi.hiroshima.jp\0nadex\0"
+"ibigawa.gifu.jp\0"
"koto.tokyo.jp\0"
-"dontexist.org\0*.triton.zone\0"
-"sande.vestfold.no\0"
-"lt.eu.org\0"
-"cloudeity.net\0"
+"steam.museum\0"
+"arakawa.tokyo.jp\0"
+"medicina.bo\0"
+"turek.pl\0call\0"
+"apps.fbsbx.com\0"
+"*.dapps.earth\0"
+"utazu.kagawa.jp\0"
+"assassination.museum\0zero\0"
+"\xe7\xbd\x91\xe7\xb5\xa1.hk\0"
+"himi.toyama.jp\0"
+"k12.fl.us\0"
+"sar.it\0ichihara.chiba.jp\0unazuki.toyama.jp\0"
+"furniture\0"
+"id.au\0b.bg\0"
+"nissan\0"
+"bjarkoy.no\0azurecontainer.io\0"
+"camp\0"
+"mykolaiv.ua\0"
+"online.museum\0is-a-hunter.com\0"
+"b.br\0"
+"far.br\0"
+"nissay\0"
+"wpcomstaging.com\0"
+"starachowice.pl\0"
+"si.it\0"
+"erotika.hu\0garden.museum\0"
+"nikon\0"
+"cultural.museum\0issmarterthanyou.com\0"
+"egyptian.museum\0\xe5\x98\x89\xe9\x87\x8c\xe5\xa4\xa7\xe9\x85\x92\xe5\xba\x97\0"
+"misato.miyagi.jp\0weatherchannel\0"
+"br\xc3\xb8nn\xc3\xb8ysund.no\0"
+"ci.it\0karpacz.pl\0"
+"dynvpn.de\0"
+"togo.aichi.jp\0"
+"trader.aero\0k12.as.us\0"
+"sannohe.aomori.jp\0mizunami.gifu.jp\0hu.net\0"
+"cambridge.museum\0lewismiller.museum\0svn-repos.de\0"
+"pe.gov.br\0nosegawa.nara.jp\0cieszyn.pl\0hicam.net\0"
+"spdns.de\0"
+"or.id\0"
+"otsuchi.iwate.jp\0"
+"jessheim.no\0"
+"chernivtsi.ua\0kyoto\0from-nm.com\0"
+"macerata.it\0"
+"kr.com\0"
+"takanezawa.tochigi.jp\0"
+"london.museum\0bod\xc3\xb8.no\0is-a-conservative.com\0"
+"or.it\0"
+"desa.id\0mar.it\0"
+"k12.nv.us\0nis.za\0"
+"zappos\0"
+"aurskog-holand.no\0skiptvet.no\0my-gateway.de\0"
+"or.jp\0shiogama.miyagi.jp\0bungotakada.oita.jp\0"
+"clock.museum\0strand.no\0"
+"higashiyamato.tokyo.jp\0oguni.yamagata.jp\0"
+"andasuolo.no\0"
+"musica.ar\0shimamoto.osaka.jp\0"
+"or.ke\0"
"mikawa.yamagata.jp\0"
-"izumiotsu.osaka.jp\0"
-"reviews\0"
-"adv.br\0vefsn.no\0"
-"oyabe.toyama.jp\0roros.no\0"
-"nissedal.no\0"
-"izumozaki.niigata.jp\0"
-"kure.hiroshima.jp\0koge.tottori.jp\0"
-"yamamoto.miyagi.jp\0"
-"kitakata.fukushima.jp\0press.museum\0"
-"noda.iwate.jp\0skierv\xc3\xa1.no\0"
-"hm.no\0eid.no\0cloudns.asia\0"
-"\xe7\xae\x87\xe4\xba\xba.hk\0r\xc3\xb8yken.no\0from-il.com\0"
-"pisz.pl\0"
-"nishiizu.shizuoka.jp\0web.tj\0"
-"kamitonda.wakayama.jp\0silk\0"
-"inatsuki.fukuoka.jp\0futbol\0"
-"ebiz.tw\0"
-"valdaosta.it\0"
-"hashimoto.wakayama.jp\0my-firewall.org\0"
-"mizusawa.iwate.jp\0web.tr\0"
-"bradesco\0"
-"us-west-1.elasticbeanstalk.com\0"
-"hobby-site.org\0"
-"os.hedmark.no\0"
-"agro.pl\0"
-"gos.pk\0"
-"k12.mn.us\0"
-"arts.co\0freemasonry.museum\0troandin.no\0is-an-artist.com\0"
-"kasuga.fukuoka.jp\0barsy.co.uk\0"
-"minami.kyoto.jp\0"
-"sina\0"
-"h.bg\0"
-"budapest\0schokokeks.net\0"
-"tamayu.shimane.jp\0web.ve\0"
-"iwafune.tochigi.jp\0"
-"chtr.k12.ma.us\0dyn-vpn.de\0"
-"yanaizu.fukushima.jp\0barsy.support\0"
-"*.cryptonomic.net\0"
-"catania.it\0cc.as.us\0"
-"kunstunddesign.museum\0tokyo\0"
-"cleaning\0"
-"elblag.pl\0"
-"takahama.aichi.jp\0"
-"pe.it\0"
-"hanggliding.aero\0"
-"limited\0"
-"toyo.kochi.jp\0"
-"comunica\xc3\xa7\xc3\xb5""es.museum\0is-lost.org\0fi.eu.org\0"
-"webredirect.org\0"
-"food\0"
-"pharmacien.fr\0"
-"homedepot\0"
-"lib.oh.us\0"
-"wakuya.miyagi.jp\0jolster.no\0"
-"kunigami.okinawa.jp\0sanfrancisco.museum\0"
-"namie.fukushima.jp\0"
-"ama.aichi.jp\0ashiya.fukuoka.jp\0"
-"takagi.nagano.jp\0webspace.rocks\0"
-"suifu.ibaraki.jp\0pe.kr\0"
-"andria-barletta-trani.it\0"
-"fbxos.fr\0*.in.futurecms.at\0"
-"nose.osaka.jp\0grong.no\0malselv.no\0"
-"aknoluokta.no\0"
-"ac.ae\0"
-"rm.it\0"
-"ciencia.bo\0ebina.kanagawa.jp\0web.za\0is-found.org\0"
-"fla.no\0"
-"nakagawa.tokushima.jp\0"
-"textile.museum\0linkyard.cloud\0"
-"taiki.hokkaido.jp\0"
+"sumy.ua\0care\0selfip.com\0"
+"gon.pk\0dst.mi.us\0"
+"sokndal.no\0s3-website-us-east-1.amazonaws.com\0"
+"from-az.net\0"
+"ikeda.osaka.jp\0"
+"musica.bo\0"
+"takaoka.toyama.jp\0or.kr\0fund\0"
+"casa\0"
+"cars\0"
+"nishiaizu.fukushima.jp\0kusu.oita.jp\0minato.osaka.jp\0bieszczady.pl\0spot\0"
+"case\0gr.com\0"
+"nayoro.hokkaido.jp\0"
+"lib.ne.us\0"
+"cash\0"
+"owariasahi.aichi.jp\0"
+"utazas.hu\0"
+"decorativearts.museum\0sigdal.no\0"
+"mattel\0"
+"u.se\0gb.com\0"
+"shiraoka.saitama.jp\0gent\0"
+"bauhaus\0"
+"artcenter.museum\0cc.or.us\0serveftp.org\0shacknet.nu\0"
+"jdf.br\0"
+"collegefan.org\0"
+"isen.kagoshima.jp\0"
+"b\xc3\xb8.telemark.no\0"
+"tsuruta.aomori.jp\0"
+"mn.us\0"
+"higashiyoshino.nara.jp\0"
+"or.na\0"
+"tochigi.jp\0osakikamijima.hiroshima.jp\0kitagata.saga.jp\0"
+"or.mu\0"
+"enonic.io\0"
+"texas.museum\0leclerc\0"
+"id.ir\0habikino.osaka.jp\0"
+"qa2.com\0"
+"pa.gov.pl\0"
+"air-surveillance.aero\0axis.museum\0marine.ru\0"
+"ricoh\0"
+"ballangen.no\0"
+"odessa.ua\0careers\0"
+"palermo.it\0"
+"kitahata.saga.jp\0"
+"br.com\0"
+"\xe9\x95\xb7\xe5\xb4\x8e.jp\0"
+"campania.it\0hirogawa.wakayama.jp\0"
+"macapa.br\0yura.wakayama.jp\0"
+"my-wan.de\0"
+"k\xc3\xa5""fjord.no\0ar.com\0"
+"aisai.aichi.jp\0sanda.hyogo.jp\0"
+"trentin-s\xc3\xbc""dtirol.it\0"
+"estate.museum\0ringerike.no\0"
+"dyndns-at-home.com\0is-a-libertarian.com\0"
+"jx.cn\0"
+"newyork.museum\0"
+"yuzawa.niigata.jp\0"
+"hitachiomiya.ibaraki.jp\0test.tj\0"
+"k12.co.us\0linkitools.space\0"
+"or.pw\0"
+"fukui.jp\0mitaka.tokyo.jp\0"
+"\xe0\xac\xad\xe0\xac\xbe\xe0\xac\xb0\xe0\xac\xa4\0"
+"is-a-blogger.com\0"
+"kijo.miyazaki.jp\0id.lv\0"
+"cc.id.us\0"
+"id.ly\0"
+"altoadige.it\0"
+"hirara.okinawa.jp\0"
+"hapmir.no\0"
+"obira.hokkaido.jp\0kochi.kochi.jp\0higashiyodogawa.osaka.jp\0"
+"damnserver.com\0"
+"yame.fukuoka.jp\0ina.saitama.jp\0lowicz.pl\0"
+"war.museum\0"
+"omigawa.chiba.jp\0datsun\0"
+"modalen.no\0k12.pr.us\0tattoo\0karelia.su\0"
+"grajewo.pl\0"
+"sanofi\0"
+"ha.cn\0"
+"academy\0filegear-gb.me\0"
+"pr.gov.br\0tsukumi.oita.jp\0"
+"stjordalshalsen.no\0komforb.se\0"
+"av.it\0sunagawa.hokkaido.jp\0iijima.nagano.jp\0"
+"ishinomaki.miyagi.jp\0"
+"stord.no\0"
+"sakai.osaka.jp\0"
+"gouv.rw\0"
+"psc.br\0"
+"test.ru\0"
+"kakogawa.hyogo.jp\0"
+"budejju.no\0"
+"kariwa.niigata.jp\0iide.yamagata.jp\0"
+"gouv.sn\0"
+"kameoka.kyoto.jp\0"
+"uchinada.ishikawa.jp\0or.th\0observer\0"
+"tj.cn\0handa.aichi.jp\0kaga.ishikawa.jp\0"
+"snillfjord.no\0"
+"idf.il\0tuscany.it\0"
+"azure\0"
+"no.it\0"
+"ac.ae\0lib.pa.us\0"
+"presse.ci\0k12.ma.us\0\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\x9f\0"
+"kasama.ibaraki.jp\0"
+"tec.mi.us\0"
+"karuizawa.nagano.jp\0"
+"photography\0"
+"reisen\0\xe5\x95\x86\xe5\x9f\x8e\0"
+"or.ug\0"
+"hamatonbetsu.hokkaido.jp\0tomari.hokkaido.jp\0kita.tokyo.jp\0select\0"
+"or.tz\0"
+"mayfirst.info\0"
"ac.at\0"
"ac.be\0"
-"minakami.gunma.jp\0"
-"torino.it\0ikeda.gifu.jp\0"
-"uz.ua\0ford\0"
-"kl\xc3\xa6""bu.no\0"
-"withgoogle.com\0"
-"kitakata.miyazaki.jp\0nikko.tochigi.jp\0bialystok.pl\0"
-"veneto.it\0*.kobe.jp\0kawai.nara.jp\0"
-"hk.com\0"
-"h\xc3\xa5.no\0cloudns.org\0"
-"ac.ci\0"
-"ltd.cy\0plc.co.im\0hikimi.shimane.jp\0comcast\0"
-"site\0"
-"ac.cn\0\xe5\xa4\xa7\xe9\x98\xaa.jp\0"
-"aosta.it\0"
-"ambulance.aero\0!city.sapporo.jp\0"
-"ac.cr\0cuneo.it\0"
-"bolivia.bo\0meland.no\0us-4.evennode.com\0"
-"ac.cy\0tsubetsu.hokkaido.jp\0"
-"public.museum\0"
-"habmer.no\0"
-"sakyo.kyoto.jp\0eastafrica.museum\0square.museum\0"
-"shintomi.miyazaki.jp\0russia.museum\0"
-"gorlice.pl\0"
-"tamba.hyogo.jp\0norton\0"
-"tomika.gifu.jp\0"
-"blog\0"
-"12hp.de\0"
-"\xd0\xb1\xd0\xb5\xd0\xbb\0"
-"music.museum\0"
-"yoga\0"
-"nanporo.hokkaido.jp\0meet\0"
-"mazury.pl\0"
-"inashiki.ibaraki.jp\0"
-"ltd.gi\0adv.mz\0hosting-cluster.nl\0"
-"tsuga.tochigi.jp\0"
-"suita.osaka.jp\0ap-northeast-3.elasticbeanstalk.com\0"
-"qh.cn\0kiwa.mie.jp\0"
-"nome.pt\0"
-"perso.ht\0nexus\0"
-"arts.ve\0netbank\0""12hp.at\0"
-"sicilia.it\0"
-"ac.gn\0quebec.museum\0rovno.ua\0ltd.hk\0"
-"anan.tokushima.jp\0"
-"nantan.kyoto.jp\0"
-"walbrzych.pl\0"
-"us-3.evennode.com\0"
-"ina.ibaraki.jp\0labor.museum\0skjervoy.no\0wellbeingzone.eu\0"
-"rodoy.no\0"
-"cc.ks.us\0"
-"berg.no\0singles\0mk.eu.org\0"
-"akaiwa.okayama.jp\0"
+"rovigo.it\0ise.mie.jp\0"
+"qc.ca\0"
+"or.us\0"
+"laquila.it\0gamagori.aichi.jp\0foundation\0"
+"taira.toyama.jp\0"
+"valle-daosta.it\0"
+"barclaycard\0"
+"cloudcontrolapp.com\0"
+"hasvik.no\0"
+"takaharu.miyazaki.jp\0"
+"cisco\0"
+"hatoyama.saitama.jp\0credit\0"
+"ac.ci\0malselv.no\0"
+"ullensvang.no\0"
+"ac.cn\0gallup\0"
+"\xe9\x9d\x92\xe6\xa3\xae.jp\0minami-alps.yamanashi.jp\0"
+"g\xc3\xa1ivuotna.no\0b.se\0"
+"ac.cr\0"
+"baths.museum\0balat.no\0"
+"liguria.it\0kanan.osaka.jp\0"
+"ac.cy\0forum.hu\0"
+"is-a-knight.org\0"
+"pol.dz\0kitakata.fukushima.jp\0iizuna.nagano.jp\0"
+"presse.fr\0"
+"tsugaru.aomori.jp\0"
+"talk\0"
+"sandnes.no\0"
+"graphics\0"
+"carraramassa.it\0"
+"lipsy\0"
+"iiyama.nagano.jp\0nyuzen.toyama.jp\0"
+"network\0"
+"s.bg\0chocolate.museum\0labour.museum\0marburg.museum\0kongsvinger.no\0"
+"bnpparibas\0"
+"kashiba.nara.jp\0parliament.nz\0chrysler\0poznan.pl\0"
+"kiwi\0"
+"gdynia.pl\0"
+"barueri.br\0"
+"\xd0\xbf\xd1\x80.\xd1\x81\xd1\x80\xd0\xb1\0"
+"kamaishi.iwate.jp\0"
+"id.us\0lasalle\0"
+"warszawa.pl\0"
+"sciencecenter.museum\0yodobashi\0myiphost.com\0"
+"is-a-republican.com\0"
+"chikujo.fukuoka.jp\0usa.oita.jp\0"
+"lib.ut.us\0"
+"gorizia.it\0ozu.kumamoto.jp\0"
+"franziskaner.museum\0mein-vigor.de\0"
+"cbre\0"
+"ac.gn\0friuli-v-giulia.it\0kuki.saitama.jp\0"
+"bentley\0"
+"cz.it\0"
+"gouv.km\0froland.no\0"
+"pol.ht\0worse-than.tv\0"
+"s3-website-eu-west-1.amazonaws.com\0"
+"salerno.it\0"
+"mino.gifu.jp\0\xe8\x81\x94\xe9\x80\x9a\0"
+"atami.shizuoka.jp\0"
+"building.museum\0flanders.museum\0""12hp.de\0"
+"ac.id\0kira.aichi.jp\0flt.cloud.muni.cz\0"
+"suldal.no\0"
+"british.museum\0reg.dk\0"
+"\xe6\x97\xb6\xe5\xb0\x9a\0"
+"journal.aero\0"
+"ac.il\0poniatowa.pl\0"
+"ac.im\0vang.no\0"
+"ac.in\0"
+"\xd8\xa7\xd9\x84\xd9\x85\xd8\xba\xd8\xb1\xd8\xa8\0"
+"ac.ir\0kagawa.jp\0\xe6\x84\x9b\xe5\xaa\x9b.jp\0"
+"coal.museum\0davvesiida.no\0knowsitall.info\0"
+"\xe7\xbe\xa4\xe9\xa6\xac.jp\0asahi.chiba.jp\0bato.tochigi.jp\0"
+"gouv.ml\0"
+"ha.no\0"
+"av.tr\0"
+"n\xc3\xa5\xc3\xa5mesjevuemie.no\0"
+"mashike.hokkaido.jp\0"
+"fuoisku.no\0"
+"ac.jp\0isa.kagoshima.jp\0"
+"portland.museum\0doesntexist.org\0"
+"12hp.at\0"
+"ac.ke\0"
+"mol.it\0saroma.hokkaido.jp\0ohda.shimane.jp\0"
+"\xe6\xa0\x83\xe6\x9c\xa8.jp\0"
+"schweiz.museum\0duck\0"
+"leg.br\0kuromatsunai.hokkaido.jp\0"
+"ryugasaki.ibaraki.jp\0"
+"ainan.ehime.jp\0wakasa.fukui.jp\0"
+"sumoto.kumamoto.jp\0"
+"murayama.yamagata.jp\0ac.kr\0"
+"portlligat.museum\0"
"12hp.ch\0"
-"analytics\0"
-"gwangju.kr\0"
-"ac.id\0"
-"arakawa.saitama.jp\0us.com\0"
-"mail.pl\0"
-"tobetsu.hokkaido.jp\0kuju.oita.jp\0"
-"furniture\0"
-"lug.org.uk\0"
-"ac.il\0"
-"ac.im\0watarai.mie.jp\0flanders.museum\0"
-"ac.in\0africa.com\0"
-"logistics.aero\0progressive\0space-to-rent.com\0"
-"*.elb.amazonaws.com.cn\0"
-"ac.ir\0is-a-landscaper.com\0"
-"lukow.pl\0"
-"kamisato.saitama.jp\0"
-"manchester.museum\0"
-"bible\0"
-"arts.museum\0author\0"
-"ac.jp\0uda.nara.jp\0"
-"langev\xc3\xa5g.no\0"
-"ichikawa.hyogo.jp\0gyokuto.kumamoto.jp\0chernovtsy.ua\0"
-"ac.ke\0blue\0"
-"uw.gov.pl\0from-hi.com\0"
-"toshima.tokyo.jp\0steinkjer.no\0dp.ua\0"
-"hk.cn\0"
-"oga.akita.jp\0"
-"\xc3\xa1k\xc5\x8boluokta.no\0"
-"imperia.it\0ltd.lk\0"
+"aircraft.aero\0navigation.aero\0"
+"ac.lk\0"
+"finance\0"
+"usr.cloud.muni.cz\0"
+"betainabox.com\0"
+"ac.ma\0"
+"trentino-alto-adige.it\0nonoichi.ishikawa.jp\0"
+"ac.ls\0"
+"ac.me\0mywire.org\0"
+"yuki.ibaraki.jp\0nantan.kyoto.jp\0"
+"stjohn.museum\0bplaced.de\0"
+"hanamaki.iwate.jp\0"
+"pittsburgh.museum\0"
+"educator.aero\0"
+"muenster.museum\0taifun-dns.de\0"
+"blanco\0"
+"ac.mu\0kh.ua\0"
+"ac.mw\0"
+"ascoli-piceno.it\0"
+"uslivinghistory.museum\0ac.ni\0"
+"trentin-sud-tirol.it\0ac.mz\0"
+"svalbard.no\0"
+"giize.com\0customer.speedpartner.de\0dyn-vpn.de\0"
+"inuyama.aichi.jp\0po.gov.pl\0"
+"mortgage\0toshiba\0"
+"cagliari.it\0sharp\0\xe7\xbd\x91\xe7\xbb\x9c\0"
+"ggee\0"
+"pug.it\0ac.nz\0"
+"ac.pa\0"
+"shibukawa.gunma.jp\0"
+"sorum.no\0"
+"fukuchi.fukuoka.jp\0"
+"sarpsborg.no\0"
+"vestnes.no\0chase\0"
+"tarumizu.kagoshima.jp\0shimane.shimane.jp\0"
+"farm.museum\0ilovecollege.info\0"
+"hitachi\0"
+"education\0"
+"taxi\0"
+"date.fukushima.jp\0ac.pr\0"
+"barrell-of-knowledge.info\0"
+"dealer\0"
+"fishing\0"
+"trentin-sued-tirol.it\0nanae.hokkaido.jp\0akashi.hyogo.jp\0sumida.tokyo.jp\0"
+"selbu.no\0"
+"rost.no\0"
+"tomika.gifu.jp\0"
+"ookuwa.nagano.jp\0hachijo.tokyo.jp\0"
+"silk.museum\0"
+"mjondalen.no\0k12.ri.us\0uk.com\0"
+"hidaka.hokkaido.jp\0"
+"austevoll.no\0"
+"iyo.ehime.jp\0"
+"plurinacional.bo\0"
+"kanagawa.jp\0"
+"is-a-cpa.com\0"
+"aerodrome.aero\0"
+"operaunite.com\0"
+"zuerich\0"
+"hol.no\0ac.rs\0"
+"nord-fron.no\0ac.ru\0ac.se\0lighting\0eu.org\0"
+"kujukuri.chiba.jp\0tara.saga.jp\0"
+"ac.rw\0"
+"yugawa.fukushima.jp\0dyndns.biz\0"
+"sauherad.no\0accountants\0"
+"eniwa.hokkaido.jp\0"
+"gol.no\0bridgestone\0dyndns-pics.com\0point2this.com\0"
+"takahama.fukui.jp\0"
+"skierv\xc3\xa1.no\0\xd2\x9b\xd0\xb0\xd0\xb7\0"
+"iitate.fukushima.jp\0otoyo.kochi.jp\0"
+"tatsuno.nagano.jp\0ibaraki.osaka.jp\0"
+"clinique\0"
+"pol.tr\0kosher\0"
+"ac.th\0"
+"mazury.pl\0slask.pl\0ac.sz\0ac.tj\0"
+"rhcloud.com\0"
+"natura\0"
+"okaya.nagano.jp\0b.ssl.fastly.net\0"
+"lunner.no\0aetna\0s3-website.eu-central-1.amazonaws.com\0"
+"fuchu.toyama.jp\0salon\0ma.leg.br\0"
+"divttasvuotna.no\0"
+"campobasso.it\0inagi.tokyo.jp\0"
+"ac.ug\0"
+"bristol.museum\0"
+"ac.tz\0"
+"ac.uk\0"
+"matsue.shimane.jp\0"
+"abiko.chiba.jp\0qpon\0"
+"aarp\0"
+"mobile\0"
+"oji.nara.jp\0"
+"ae.org\0"
+"li.it\0"
+"glass.museum\0"
+"serveminecraft.net\0"
+"amber.museum\0"
+"hirado.nagasaki.jp\0\xe5\x8f\xb0\xe6\xb9\xbe\0in.net\0"
+"ac.vn\0"
+"fussa.tokyo.jp\0\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0\0"
+"ltd.cy\0money.museum\0s.se\0duns\0"
+"minamifurano.hokkaido.jp\0"
+"glas.museum\0"
+"mihama.mie.jp\0"
+"degree\0mobily\0\xe5\x9c\xa8\xe7\xba\xbf\0logoip.de\0"
+"e4.cz\0"
+"fashion\0"
+"realty\0"
+"from-nh.com\0"
+"recife.br\0nm.cn\0"
+"rio.br\0ueno.gunma.jp\0"
+"citic\0from-oh.com\0"
+"blogspot.vn\0"
+"ca-central-1.elasticbeanstalk.com\0"
+"viterbo.it\0shingu.fukuoka.jp\0"
+"chuo.chiba.jp\0urakawa.hokkaido.jp\0"
+"dvag\0"
+"fst.br\0tsunan.niigata.jp\0"
+"stockholm.museum\0"
+"kobayashi.miyazaki.jp\0\xe5\xa8\xb1\xe4\xb9\x90\0"
+"cc.ky.us\0"
+"bizen.okayama.jp\0"
+"koshimizu.hokkaido.jp\0shinjo.nara.jp\0"
+"trading\0from-tx.com\0"
+"ltd.gi\0ac.za\0al.eu.org\0"
+"gamo.shiga.jp\0"
+"rovno.ua\0hk.com\0"
"yatsushiro.kumamoto.jp\0"
-"\xd9\x87\xd9\x85\xd8\xb1\xd8\xa7\xd9\x87\0"
-"cnpy.gdn\0"
-"ac.kr\0"
-"arts.ro\0"
-"us-2.evennode.com\0"
-"shinkamigoto.nagasaki.jp\0"
-"warman\0barsyonline.com\0"
+"vn.ua\0richardli\0"
+"taishi.osaka.jp\0kaufen\0"
+"bearalv\xc3\xa1hki.no\0ac.zm\0"
+"chirurgiens-dentistes.fr\0rebun.hokkaido.jp\0"
+"state.museum\0"
+"equipment.aero\0"
+"k12.de.us\0ltd.hk\0"
+"setagaya.tokyo.jp\0"
+"ac.zw\0"
+"pvh.br\0firm.ht\0bbs.tr\0\xe5\x85\xab\xe5\x8d\xa6\0"
+"grandrapids.museum\0enterprises\0"
+"a\xc3\xa9roport.ci\0\xe4\xb8\xad\xe6\x96\x87\xe7\xbd\x91\0nodum.co\0"
+"bolt.hu\0technology\0"
+"firm.in\0hiroo.hokkaido.jp\0kadoma.osaka.jp\0"
+"isernia.it\0"
+"act.au\0"
+"agrigento.it\0"
+"drammen.no\0troandin.no\0pl.eu.org\0blogspot.re\0"
+"shioya.tochigi.jp\0mitou.yamaguchi.jp\0"
+"badaddja.no\0"
+"nogata.fukuoka.jp\0tonosho.kagawa.jp\0minamioguni.kumamoto.jp\0opoczno.pl\0"
+"go.ci\0"
+"shitara.aichi.jp\0"
+"beats\0meteorapp.com\0"
+"kumano.hiroshima.jp\0"
+"leksvik.no\0blogspot.ro\0"
+"maniwa.okayama.jp\0health\0"
+"londrina.br\0go.cr\0at.it\0yoichi.hokkaido.jp\0"
+"oygarden.no\0blogspot.rs\0"
+"zgorzelec.pl\0"
+"airbus\0blogspot.ru\0blogspot.se\0"
+"blogspot.sg\0"
+"andriabarlettatrani.it\0"
+"stj\xc3\xb8rdal.no\0blogspot.si\0"
+"blogspot.sk\0"
+"alto-adige.it\0"
+"filegear-sg.me\0nodum.io\0"
+"blogspot.sn\0"
+"firm.co\0"
+"kerryproperties\0dd-dns.de\0"
+"fuchu.hiroshima.jp\0blogspot.td\0"
+"temp-dns.com\0"
+"sx.cn\0tokai.aichi.jp\0"
+"ninja\0"
+"marylhurst.museum\0science-fiction.museum\0"
+"tozawa.yamagata.jp\0oshino.yamanashi.jp\0"
+"casino.hu\0firm.dk\0"
+"ac.gov.br\0mw.gov.pl\0"
+"ltd.lk\0hyundai\0"
+"kosai.shizuoka.jp\0kainan.wakayama.jp\0"
+"shintomi.miyazaki.jp\0raid\0"
+"lorenskog.no\0able\0cust.dev.thingdust.io\0"
+"hanno.saitama.jp\0"
+"rennebu.no\0blogspot.tw\0blogspot.ug\0"
+"nakayama.yamagata.jp\0"
+"nishio.aichi.jp\0"
+"origins\0dyn.cosidns.de\0abkhazia.su\0tula.su\0"
+"dattolocal.net\0"
+"baseball.museum\0vantaa.museum\0os\xc3\xb8yro.no\0"
+"\xe3\x82\xb9\xe3\x83\x88\xe3\x82\xa2\0blogspot.mr\0"
+"quicksytes.com\0"
+"sex.hu\0agriculture.museum\0"
+"muni.il\0kikuchi.kumamoto.jp\0\xe5\xa4\xa7\xe4\xbc\x97\xe6\xb1\xbd\xe8\xbd\xa6\0"
+"blogspot.mx\0"
+"blogspot.my\0"
+"bci.dnstrace.pro\0"
+"blogspot.nl\0"
+"qld.edu.au\0"
+"ikusaka.nagano.jp\0"
+"blogspot.no\0"
+"\xc3\xb8yer.no\0"
+"ms.gov.br\0otobe.hokkaido.jp\0"
+"sakaki.nagano.jp\0"
+"knx-server.net\0"
+"cc.nm.us\0"
+"moriya.ibaraki.jp\0"
+"miyawaka.fukuoka.jp\0"
+"sciencehistory.museum\0circle\0"
+"go.id\0"
+"burghof.museum\0donetsk.ua\0ky.us\0blogspot.pe\0"
+"bio.br\0"
+"izunokuni.shizuoka.jp\0"
+"frogans\0spdns.org\0"
+"york.museum\0k12.va.us\0ap-northeast-3.elasticbeanstalk.com\0"
+"takanabe.miyazaki.jp\0\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0"
+"isehara.kanagawa.jp\0auspost\0"
+"blogspot.qa\0"
+"scienceandhistory.museum\0"
+"trentinsued-tirol.it\0go.it\0blogspot.pt\0"
+"parliament.cy\0lib.ia.us\0"
+"mt.gov.br\0"
+"etne.no\0"
+"trentinos\xc3\xbc""d-tirol.it\0trentinsudtirol.it\0olbiatempio.it\0fukumitsu.toyama.jp\0juniper\0"
+"q.bg\0naturalhistory.museum\0s3-website-us-west-2.amazonaws.com\0"
+"sologne.museum\0"
+"santoandre.br\0"
+"go.jp\0kawaba.gunma.jp\0"
+"flor\xc3\xb8.no\0l-o-g-i-n.de\0"
+"ohtawara.tochigi.jp\0"
+"weibo\0blogspot.is\0"
+"lecce.it\0memorial\0blogspot.it\0"
+"go.ke\0"
+"tabayama.yamanashi.jp\0"
+"accident-investigation.aero\0"
+"kadena.okinawa.jp\0"
+"frosta.no\0"
+"toyokawa.aichi.jp\0banamex\0"
+"sibenik.museum\0"
+"blogspot.jp\0"
+"go.kr\0chirurgiens-dentistes-en-france.fr\0"
+"hamar.no\0"
+"environment.museum\0"
+"higashikagawa.kagawa.jp\0matsukawa.nagano.jp\0\xe5\x85\xac\xe5\x8f\xb8\0"
+"gs.aa.no\0"
+"honai.ehime.jp\0"
+"skole.museum\0utah.museum\0"
+"blogspot.kr\0"
+"trolley.museum\0bd.se\0from-me.org\0"
+"carrier.museum\0salat.no\0brussels\0cipriani\0"
+"grimstad.no\0krager\xc3\xb8.no\0"
+"lea\xc5\x8bgaviika.no\0blogspot.li\0"
+"is-by.us\0"
+"shiso.hyogo.jp\0"
+"arq.br\0"
+"\xed\x95\x9c\xea\xb5\xad\0"
+"blogspot.lt\0blogspot.md\0"
+"roan.no\0blogspot.lu\0"
+"dni.us\0ltd.ua\0"
+"championship.aero\0"
+"kobierzyce.pl\0"
+"schlesisches.museum\0blogspot.mk\0"
+"sex.pl\0"
+"archaeology.museum\0"
+"tonaki.okinawa.jp\0est.pr\0"
+"gotdns.com\0"
+"ltd.uk\0healthcare\0"
+"webhop.biz\0"
+"firm.ve\0"
+"itayanagi.aomori.jp\0suita.osaka.jp\0"
+"blogspot.fi\0"
+"narashino.chiba.jp\0"
+"\xe7\xbd\x91\xe5\xba\x97\0"
+"tsukui.kanagawa.jp\0shimosuwa.nagano.jp\0"
+"troms\xc3\xb8.no\0"
+"otaki.nagano.jp\0"
+"\xe5\xb9\xbf\xe4\xb8\x9c\0"
+"jfk.museum\0kl\xc3\xa6""bu.no\0ferrero\0"
+"berlin\0blogspot.fr\0"
+"oracle\0"
+"sukagawa.fukushima.jp\0\xe5\x98\x89\xe9\x87\x8c\0"
+"works\0"
+"world\0"
+"tcp4.me\0"
+"kumiyama.kyoto.jp\0open\0"
+"is-saved.org\0"
+"channelsdvr.net\0"
+"friuli-vegiulia.it\0"
+"taobao\0co.events\0"
+"\xe3\x82\xaf\xe3\x83\xa9\xe3\x82\xa6\xe3\x83\x89\0"
+"blogspot.gr\0"
+"praxi\0barsy.online\0resindevice.io\0"
+"tadaoka.osaka.jp\0"
+"go.pw\0is-a-anarchist.com\0"
+"trentinostirol.it\0star\0"
+"on.ca\0"
+"cloudeity.net\0"
+"nm.us\0blogspot.hk\0"
+"leirvik.no\0"
+"ong.br\0blogspot.hr\0"
+"lahppi.no\0"
+"*.compute.estate\0blogspot.hu\0blogspot.ie\0"
+"edu.ac\0\xc3\xa5lesund.no\0blackfriday\0"
+"is.it\0zentsuji.kagawa.jp\0"
+"paroch.k12.ma.us\0"
+"edu.af\0"
+"blogspot.in\0"
+"rennes\xc3\xb8y.no\0"
+"ozora.hokkaido.jp\0busan.kr\0"
+"blogspot.ba\0withyoutube.com\0"
+"edu.al\0"
+"sykkylven.no\0"
+"hirakata.osaka.jp\0"
+"eng.pro\0blogspot.be\0"
+"edu.ba\0aa.no\0blogspot.bg\0"
+"edu.ar\0edu.bb\0matera.it\0ibara.okayama.jp\0de.cool\0"
+"plc.ly\0"
+"blogspot.bj\0"
+"edu.au\0godaddy\0is-a-soxfan.org\0"
+"keisen.fukuoka.jp\0"
+"edu.bh\0moseushi.hokkaido.jp\0"
+"edu.bi\0crafts.museum\0"
+"edu.az\0kumamoto.kumamoto.jp\0"
+"firm.ro\0eu-central-1.elasticbeanstalk.com\0blogspot.ca\0"
+"exchange.aero\0edu.bm\0"
+"edu.bn\0tsurugi.ishikawa.jp\0"
+"edu.bo\0s\xc3\xb8r-odal.no\0"
+"blogspot.cf\0"
+"aremark.no\0"
+"edu.br\0go.th\0blogspot.ch\0"
+"edu.bs\0"
+"edu.bt\0go.tj\0"
+"s\xc3\xb8r-varanger.no\0"
+"blogspot.cl\0"
+"jogasz.hu\0orkanger.no\0"
+"edu.ci\0"
+"edu.bz\0"
+"gs.bu.no\0jambyl.su\0"
+"lublin.pl\0mysecuritycamera.net\0"
+"v\xc3\xa1rgg\xc3\xa1t.no\0"
+"edu.cn\0"
+"edu.co\0contemporary.museum\0blogspot.de\0"
+"blogspot.cv\0"
+"laakesvuemie.no\0go.ug\0"
+"boldlygoingnowhere.org\0"
+"go.tz\0blogspot.cz\0"
+"edu.cu\0blogspot.dk\0"
+"edu.cw\0stranda.no\0"
+"hikawa.shimane.jp\0"
+"serveftp.com\0"
+"shinanomachi.nagano.jp\0"
+"edu.dm\0finnoy.no\0"
+"yoka.hyogo.jp\0"
+"edu.do\0museet.museum\0b\xc3\xa1l\xc3\xa1t.no\0"
+"sano.tochigi.jp\0\xd8\xa7\xd9\x85\xd8\xa7\xd8\xb1\xd8\xa7\xd8\xaa\0"
+"\xe9\xb9\xbf\xe5\x85\x90\xe5\xb3\xb6.jp\0"
+"edu.ec\0"
+"edu.ee\0"
+"edu.eg\0broadway\0"
+"livorno.it\0"
+"edu.dz\0carboniaiglesias.it\0"
+"lesja.no\0"
+"ce.it\0sytes.net\0"
+"linz.museum\0virtualuser.de\0"
+"seiyo.ehime.jp\0"
+"my-firewall.org\0"
+"kanmaki.nara.jp\0tendo.yamagata.jp\0wolomin.pl\0"
+"sula.no\0"
+"firm.nf\0"
+"edu.es\0savannahga.museum\0tonsberg.no\0"
+"edu.et\0"
+"myvnc.com\0"
+"engineer\0"
+"avoues.fr\0bihoro.hokkaido.jp\0caseih\0"
+"juedisches.museum\0"
+"al.gov.br\0"
+"group.aero\0cc.fl.us\0"
+"mg.leg.br\0"
+"pulawy.pl\0"
+"eng.br\0gift\0"
+"columbus.museum\0"
+"otari.nagano.jp\0"
+"edu.ge\0hermes\0"
+"honjo.saitama.jp\0"
+"edu.gh\0"
+"edu.gi\0coastaldefence.museum\0"
+"partners\0"
+"edu.gl\0minamiyamashiro.kyoto.jp\0"
+"edu.gn\0cloudns.biz\0"
+"no.eu.org\0"
+"edu.gp\0namikata.ehime.jp\0"
+"edu.gr\0"
+"cng.br\0edu.gt\0gosen.niigata.jp\0"
+"agro.bo\0edu.gu\0phoenix.museum\0lugansk.ua\0"
+"digital\0"
+"dyn-o-saur.com\0"
+"motoyama.kochi.jp\0"
+"industria.bo\0edu.gy\0"
+"edu.hk\0"
+"lombardia.it\0"
+"edu.hn\0iwaizumi.iwate.jp\0chino.nagano.jp\0futsu.nagasaki.jp\0"
+"fuel.aero\0blogspot.ae\0"
+"ishikari.hokkaido.jp\0"
+"akrehamn.no\0"
+"edu.ht\0"
+"toyota\0"
+"blogspot.al\0"
+"mobi\0tunes\0blogspot.am\0"
+"goiania.br\0co.financial\0"
+"yokoze.saitama.jp\0"
+"naoshima.kagawa.jp\0"
+"sola.no\0adac\0\xe6\xb8\xb8\xe6\x88\x8f\0"
+"edu.in\0yamanashi.jp\0"
+"edu.iq\0"
+"edu.is\0"
+"edu.it\0"
+"plc.uk\0"
+"piacenza.it\0terni.it\0lg.jp\0echizen.fukui.jp\0actor\0"
+"bu.no\0modum.no\0dy.fi\0"
+"takino.hyogo.jp\0"
+"\xe5\x8f\xb0\xe7\x81\xa3\0"
+"\xe5\x85\xac\xe7\x9b\x8a\0"
+"isa.us\0"
+"arts.co\0village.museum\0s\xc3\xb8r-fron.no\0vodka\0"
+"edu.jo\0moda\0dnshome.de\0"
+"tashkent.su\0byen.site\0"
+"akune.kagoshima.jp\0canon\0"
+"edu.kg\0"
+"edu.ki\0countryestate.museum\0"
+"green\0"
+"edu.km\0"
+"sango.nara.jp\0edu.kn\0"
+"navuotna.no\0lib.in.us\0"
+"yakumo.hokkaido.jp\0edu.kp\0"
+"edu.la\0"
+"nagahama.shiga.jp\0edu.lb\0"
+"edu.lc\0afjord.no\0"
+"rotorcraft.aero\0edu.kw\0"
+"udono.mie.jp\0global.prod.fastly.net\0"
+"edu.ky\0n\xc3\xa1vuotna.no\0"
+"\xe7\xbd\x91\xe7\xbb\x9c.cn\0edu.kz\0"
+"edu.lk\0"
+"pisa.it\0"
+"toyota.yamaguchi.jp\0comcast\0"
+"lombardy.it\0shikatsu.aichi.jp\0"
+"\xc3\xa1lt\xc3\xa1.no\0"
+"edu.lr\0"
+"edu.ls\0"
+"kawaue.gifu.jp\0"
+"edu.me\0"
+"edu.lv\0"
+"edu.mg\0"
+"edu.ly\0penza.su\0"
+"edu.mk\0"
+"edu.ml\0cricket\0telebit.app\0"
+"misaki.osaka.jp\0edu.mn\0cern\0"
+"edu.mo\0nz.eu.org\0"
+"tatebayashi.gunma.jp\0"
+"redstone\0nym.by\0"
+"nym.bz\0"
+"edu.ms\0mordovia.su\0"
};
static const quint16 tldChunkCount = 2;
-static const quint32 tldChunks[] = {65532, 101260};
+static const quint32 tldChunks[] = {65517, 101828};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 15c9f52cf3..1f03ac5d5a 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -40,6 +40,7 @@
#include "qwindowspipereader_p.h"
#include "qiodevice_p.h"
#include <qelapsedtimer.h>
+#include <qscopedvaluerollback.h>
QT_BEGIN_NAMESPACE
@@ -301,9 +302,8 @@ void QWindowsPipeReader::emitPendingReadyRead()
{
if (readyReadPending) {
readyReadPending = false;
- inReadyRead = true;
+ QScopedValueRollback<bool> guard(inReadyRead, true);
emit readyRead();
- inReadyRead = false;
}
}
diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h
index e52aa4c33d..c757753c9c 100644
--- a/src/corelib/io/qwindowspipereader_p.h
+++ b/src/corelib/io/qwindowspipereader_p.h
@@ -97,7 +97,7 @@ private:
class Overlapped : public OVERLAPPED
{
- Q_DISABLE_COPY(Overlapped)
+ Q_DISABLE_COPY_MOVE(Overlapped)
public:
explicit Overlapped(QWindowsPipeReader *reader);
void clear();
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index 92e8b6db52..32536f495b 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -39,6 +39,7 @@
#include "qwindowspipewriter_p.h"
#include "qiodevice_p.h"
+#include <qscopedvaluerollback.h>
QT_BEGIN_NAMESPACE
@@ -111,9 +112,8 @@ void QWindowsPipeWriter::emitPendingBytesWrittenValue()
emit canWrite();
if (!inBytesWritten) {
- inBytesWritten = true;
+ QScopedValueRollback<bool> guard(inBytesWritten, true);
emit bytesWritten(bytes);
- inBytesWritten = false;
}
}
}
diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h
index d6671c3f27..6c269e86b7 100644
--- a/src/corelib/io/qwindowspipewriter_p.h
+++ b/src/corelib/io/qwindowspipewriter_p.h
@@ -134,7 +134,7 @@ private:
class Overlapped : public OVERLAPPED
{
- Q_DISABLE_COPY(Overlapped)
+ Q_DISABLE_COPY_MOVE(Overlapped)
public:
explicit Overlapped(QWindowsPipeWriter *pipeWriter);
void clear();
diff --git a/src/corelib/itemmodels/itemmodels.pri b/src/corelib/itemmodels/itemmodels.pri
index 068a8c4b3a..ebeac6e211 100644
--- a/src/corelib/itemmodels/itemmodels.pri
+++ b/src/corelib/itemmodels/itemmodels.pri
@@ -20,6 +20,14 @@ qtConfig(proxymodel) {
SOURCES += \
itemmodels/qabstractproxymodel.cpp
+ qtConfig(concatenatetablesproxymodel) {
+ HEADERS += \
+ itemmodels/qconcatenatetablesproxymodel.h
+
+ SOURCES += \
+ itemmodels/qconcatenatetablesproxymodel.cpp
+ }
+
qtConfig(identityproxymodel) {
HEADERS += \
itemmodels/qidentityproxymodel.h
@@ -35,6 +43,15 @@ qtConfig(proxymodel) {
SOURCES += \
itemmodels/qsortfilterproxymodel.cpp
}
+
+ qtConfig(transposeproxymodel) {
+ HEADERS += \
+ itemmodels/qtransposeproxymodel.h \
+ itemmodels/qtransposeproxymodel_p.h
+
+ SOURCES += \
+ itemmodels/qtransposeproxymodel.cpp
+ }
}
qtConfig(stringlistmodel) {
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 83dcf68314..3e74e5a0c8 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -45,6 +45,7 @@
#include <qmimedata.h>
#include <qdebug.h>
#include <qvector.h>
+#include <qregexp.h>
#include <qstack.h>
#include <qbitarray.h>
#include <qdatetime.h>
@@ -76,8 +77,8 @@ QPersistentModelIndexData *QPersistentModelIndexData::create(const QModelIndex &
void QPersistentModelIndexData::destroy(QPersistentModelIndexData *data)
{
Q_ASSERT(data);
- Q_ASSERT(data->ref.load() == 0);
- QAbstractItemModel *model = const_cast<QAbstractItemModel *>(data->model);
+ Q_ASSERT(data->ref.loadRelaxed() == 0);
+ QAbstractItemModel *model = const_cast<QAbstractItemModel *>(data->index.model());
// a valid persistent model index with a null model pointer can only happen if the model was destroyed
if (model) {
QAbstractItemModelPrivate *p = model->d_func();
@@ -512,10 +513,8 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
void QAbstractItemModelPrivate::invalidatePersistentIndexes()
{
- for (QPersistentModelIndexData *data : qAsConst(persistent.indexes)) {
+ for (QPersistentModelIndexData *data : qAsConst(persistent.indexes))
data->index = QModelIndex();
- data->model = 0;
- }
persistent.indexes.clear();
}
@@ -530,7 +529,6 @@ void QAbstractItemModelPrivate::invalidatePersistentIndex(const QModelIndex &ind
QPersistentModelIndexData *data = *it;
persistent.indexes.erase(it);
data->index = QModelIndex();
- data->model = 0;
}
}
@@ -863,7 +861,6 @@ void QAbstractItemModelPrivate::rowsRemoved(const QModelIndex &parent,
QPersistentModelIndexData *data = *it;
persistent.indexes.erase(persistent.indexes.constFind(data->index));
data->index = QModelIndex();
- data->model = 0;
}
}
@@ -958,7 +955,6 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent,
QPersistentModelIndexData *data = *it;
persistent.indexes.erase(persistent.indexes.constFind(data->index));
data->index = QModelIndex();
- data->model = 0;
}
}
@@ -2334,7 +2330,7 @@ QModelIndex QAbstractItemModel::buddy(const QModelIndex &index) const
The way the search is performed is defined by the \a flags given. The list
that is returned may be empty. Note also that the order of results in the
list may not correspond to the order in the model, if for example a proxy
- model is used. The order of the results can not be relied upon.
+ model is used. The order of the results cannot be relied upon.
The search begins from the \a start index, and continues until the number
of matching data items equals \a hits, the search reaches the last row, or
@@ -2912,7 +2908,7 @@ bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int star
Note that other rows may be displaced accordingly. Note also that when moving
items within the same parent you should not attempt invalid or no-op moves. In
- the above example, item 2 is at row 2 before the move, so it can not be moved
+ the above example, item 2 is at row 2 before the move, so it cannot be moved
to row 2 (where it is already) or row 3 (no-op as row 3 means above row 3, where
it is already)
@@ -3298,8 +3294,6 @@ void QAbstractItemModel::changePersistentIndex(const QModelIndex &from, const QM
data->index = to;
if (to.isValid())
d->persistent.insertMultiAtEnd(to, data);
- else
- data->model = 0;
}
}
@@ -3332,8 +3326,6 @@ void QAbstractItemModel::changePersistentIndexList(const QModelIndexList &from,
data->index = to.at(i);
if (data->index.isValid())
toBeReinserted << data;
- else
- data->model = 0;
}
}
@@ -3627,7 +3619,7 @@ QModelIndex QAbstractTableModel::sibling(int row, int column, const QModelIndex
bool QAbstractTableModel::hasChildren(const QModelIndex &parent) const
{
- if (parent.model() == this || !parent.isValid())
+ if (!parent.isValid())
return rowCount(parent) > 0 && columnCount(parent) > 0;
return false;
}
@@ -3963,7 +3955,7 @@ bool QAbstractListModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
/*!
\internal
- QHash::insertMulti insert the value before the old value. and find() return the new value.
+ QMultiHash::insert inserts the value before the old value. and find() return the new value.
We need insertMultiAtEnd because we don't want to overwrite the old one, which should be removed later
There should be only one instance QPersistentModelIndexData per index, but in some intermediate state there may be
@@ -3973,9 +3965,9 @@ bool QAbstractListModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
*/
void QAbstractItemModelPrivate::Persistent::insertMultiAtEnd(const QModelIndex& key, QPersistentModelIndexData *data)
{
- QHash<QModelIndex,QPersistentModelIndexData *>::iterator newIt =
- indexes.insertMulti(key, data);
- QHash<QModelIndex,QPersistentModelIndexData *>::iterator it = newIt + 1;
+ QHash<QModelIndex,QPersistentModelIndexData *>::iterator newIt = indexes.insert(key, data);
+ QHash<QModelIndex,QPersistentModelIndexData *>::iterator it = newIt;
+ ++it;
while (it != indexes.end() && it.key() == key) {
qSwap(*newIt,*it);
newIt = it;
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h
index bec71b0606..43649cf79b 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.h
+++ b/src/corelib/itemmodels/qabstractitemmodel.h
@@ -57,12 +57,12 @@ class Q_CORE_EXPORT QModelIndex
{
friend class QAbstractItemModel;
public:
- Q_DECL_CONSTEXPR inline QModelIndex() Q_DECL_NOTHROW : r(-1), c(-1), i(0), m(nullptr) {}
+ Q_DECL_CONSTEXPR inline QModelIndex() noexcept : r(-1), c(-1), i(0), m(nullptr) {}
// compiler-generated copy/move ctors/assignment operators are fine!
- Q_DECL_CONSTEXPR inline int row() const Q_DECL_NOTHROW { return r; }
- Q_DECL_CONSTEXPR inline int column() const Q_DECL_NOTHROW { return c; }
- Q_DECL_CONSTEXPR inline quintptr internalId() const Q_DECL_NOTHROW { return i; }
- inline void *internalPointer() const Q_DECL_NOTHROW { return reinterpret_cast<void*>(i); }
+ Q_DECL_CONSTEXPR inline int row() const noexcept { return r; }
+ Q_DECL_CONSTEXPR inline int column() const noexcept { return c; }
+ Q_DECL_CONSTEXPR inline quintptr internalId() const noexcept { return i; }
+ inline void *internalPointer() const noexcept { return reinterpret_cast<void*>(i); }
inline QModelIndex parent() const;
inline QModelIndex sibling(int row, int column) const;
inline QModelIndex siblingAtColumn(int column) const;
@@ -72,13 +72,13 @@ public:
#endif
inline QVariant data(int role = Qt::DisplayRole) const;
inline Qt::ItemFlags flags() const;
- Q_DECL_CONSTEXPR inline const QAbstractItemModel *model() const Q_DECL_NOTHROW { return m; }
- Q_DECL_CONSTEXPR inline bool isValid() const Q_DECL_NOTHROW { return (r >= 0) && (c >= 0) && (m != nullptr); }
- Q_DECL_CONSTEXPR inline bool operator==(const QModelIndex &other) const Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR inline const QAbstractItemModel *model() const noexcept { return m; }
+ Q_DECL_CONSTEXPR inline bool isValid() const noexcept { return (r >= 0) && (c >= 0) && (m != nullptr); }
+ Q_DECL_CONSTEXPR inline bool operator==(const QModelIndex &other) const noexcept
{ return (other.r == r) && (other.i == i) && (other.c == c) && (other.m == m); }
- Q_DECL_CONSTEXPR inline bool operator!=(const QModelIndex &other) const Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR inline bool operator!=(const QModelIndex &other) const noexcept
{ return !(*this == other); }
- Q_DECL_CONSTEXPR inline bool operator<(const QModelIndex &other) const Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR inline bool operator<(const QModelIndex &other) const noexcept
{
return r < other.r
|| (r == other.r && (c < other.c
@@ -86,9 +86,9 @@ public:
|| (i == other.i && std::less<const QAbstractItemModel *>()(m, other.m))))));
}
private:
- inline QModelIndex(int arow, int acolumn, void *ptr, const QAbstractItemModel *amodel) Q_DECL_NOTHROW
+ inline QModelIndex(int arow, int acolumn, void *ptr, const QAbstractItemModel *amodel) noexcept
: r(arow), c(acolumn), i(reinterpret_cast<quintptr>(ptr)), m(amodel) {}
- Q_DECL_CONSTEXPR inline QModelIndex(int arow, int acolumn, quintptr id, const QAbstractItemModel *amodel) Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR inline QModelIndex(int arow, int acolumn, quintptr id, const QAbstractItemModel *amodel) noexcept
: r(arow), c(acolumn), i(id), m(amodel) {}
int r, c;
quintptr i;
@@ -103,7 +103,7 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QModelIndex &);
class QPersistentModelIndexData;
// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
-uint qHash(const QPersistentModelIndex &index, uint seed = 0) Q_DECL_NOTHROW;
+uint qHash(const QPersistentModelIndex &index, uint seed = 0) noexcept;
class Q_CORE_EXPORT QPersistentModelIndex
{
@@ -117,13 +117,11 @@ public:
inline bool operator!=(const QPersistentModelIndex &other) const
{ return !operator==(other); }
QPersistentModelIndex &operator=(const QPersistentModelIndex &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QPersistentModelIndex(QPersistentModelIndex &&other) Q_DECL_NOTHROW
+ inline QPersistentModelIndex(QPersistentModelIndex &&other) noexcept
: d(other.d) { other.d = nullptr; }
- inline QPersistentModelIndex &operator=(QPersistentModelIndex &&other) Q_DECL_NOTHROW
+ inline QPersistentModelIndex &operator=(QPersistentModelIndex &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- inline void swap(QPersistentModelIndex &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ inline void swap(QPersistentModelIndex &other) noexcept { qSwap(d, other.d); }
bool operator==(const QModelIndex &other) const;
bool operator!=(const QModelIndex &other) const;
QPersistentModelIndex &operator=(const QModelIndex &other);
@@ -143,14 +141,14 @@ public:
bool isValid() const;
private:
QPersistentModelIndexData *d;
- friend uint qHash(const QPersistentModelIndex &, uint seed) Q_DECL_NOTHROW;
+ friend uint qHash(const QPersistentModelIndex &, uint seed) noexcept;
#ifndef QT_NO_DEBUG_STREAM
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &);
#endif
};
Q_DECLARE_SHARED(QPersistentModelIndex)
-inline uint qHash(const QPersistentModelIndex &index, uint seed) Q_DECL_NOTHROW
+inline uint qHash(const QPersistentModelIndex &index, uint seed) noexcept
{ return qHash(index.d, seed); }
@@ -163,6 +161,7 @@ typedef QList<QModelIndex> QModelIndexList;
class QMimeData;
class QAbstractItemModelPrivate;
+class QTransposeProxyModelPrivate;
template <class Key, class T> class QMap;
@@ -173,6 +172,7 @@ class Q_CORE_EXPORT QAbstractItemModel : public QObject
friend class QPersistentModelIndexData;
friend class QAbstractItemViewPrivate;
friend class QIdentityProxyModel;
+ friend class QTransposeProxyModelPrivate;
public:
explicit QAbstractItemModel(QObject *parent = nullptr);
@@ -300,7 +300,9 @@ public Q_SLOTS:
virtual void revert();
protected Q_SLOTS:
- // Qt 6: Make virtual
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ virtual
+#endif
void resetInternalData();
protected:
@@ -460,7 +462,7 @@ inline QVariant QModelIndex::data(int arole) const
inline Qt::ItemFlags QModelIndex::flags() const
{ return m ? m->flags(*this) : Qt::ItemFlags(); }
-inline uint qHash(const QModelIndex &index) Q_DECL_NOTHROW
+inline uint qHash(const QModelIndex &index) noexcept
{ return uint((uint(index.row()) << 4) + index.column() + index.internalId()); }
QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qabstractitemmodel_p.h b/src/corelib/itemmodels/qabstractitemmodel_p.h
index 12fd93d217..92a440a125 100644
--- a/src/corelib/itemmodels/qabstractitemmodel_p.h
+++ b/src/corelib/itemmodels/qabstractitemmodel_p.h
@@ -65,11 +65,10 @@ QT_REQUIRE_CONFIG(itemmodel);
class QPersistentModelIndexData
{
public:
- QPersistentModelIndexData() : model(0) {}
- QPersistentModelIndexData(const QModelIndex &idx) : index(idx), model(idx.model()) {}
+ QPersistentModelIndexData() {}
+ QPersistentModelIndexData(const QModelIndex &idx) : index(idx) {}
QModelIndex index;
QAtomicInt ref;
- const QAbstractItemModel *model;
static QPersistentModelIndexData *create(const QModelIndex &index);
static void destroy(QPersistentModelIndexData *data);
};
@@ -99,7 +98,7 @@ public:
void itemsMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation);
bool allowMove(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation);
- inline QModelIndex createIndex(int row, int column, void *data = 0) const {
+ inline QModelIndex createIndex(int row, int column, void *data = nullptr) const {
return q_func()->createIndex(row, column, data);
}
@@ -142,7 +141,7 @@ public:
struct Persistent {
Persistent() {}
- QHash<QModelIndex, QPersistentModelIndexData *> indexes;
+ QMultiHash<QModelIndex, QPersistentModelIndexData *> indexes;
QStack<QVector<QPersistentModelIndexData *> > moved;
QStack<QVector<QPersistentModelIndexData *> > invalidated;
void insertMultiAtEnd(const QModelIndex& key, QPersistentModelIndexData *data);
diff --git a/src/corelib/itemmodels/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp
index 62b3ee85b9..c863406afd 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.cpp
+++ b/src/corelib/itemmodels/qabstractproxymodel.cpp
@@ -313,6 +313,18 @@ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation
return d->model->setHeaderData(sourceSection, orientation, value, role);
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \reimp
+ \since 6.0
+ */
+bool QAbstractProxyModel::clearItemData(const QModelIndex &index)
+{
+ Q_D(QAbstractProxyModel);
+ return d->model->clearItemData(mapToSource(index));
+}
+#endif
+
/*!
\reimp
*/
diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h
index 08ecf9d15f..c9a73b6a31 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.h
+++ b/src/corelib/itemmodels/qabstractproxymodel.h
@@ -78,6 +78,9 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
bool setItemData(const QModelIndex& index, const QMap<int, QVariant> &roles) override;
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool clearItemData(const QModelIndex &index) override;
+#endif
QModelIndex buddy(const QModelIndex &index) const override;
bool canFetchMore(const QModelIndex &parent) const override;
diff --git a/src/corelib/itemmodels/qabstractproxymodel_p.h b/src/corelib/itemmodels/qabstractproxymodel_p.h
index f7bd5cc691..a95687c970 100644
--- a/src/corelib/itemmodels/qabstractproxymodel_p.h
+++ b/src/corelib/itemmodels/qabstractproxymodel_p.h
@@ -62,7 +62,7 @@ class Q_CORE_EXPORT QAbstractProxyModelPrivate : public QAbstractItemModelPrivat
{
Q_DECLARE_PUBLIC(QAbstractProxyModel)
public:
- QAbstractProxyModelPrivate() : QAbstractItemModelPrivate(), model(0) {}
+ QAbstractProxyModelPrivate() : QAbstractItemModelPrivate(), model(nullptr) {}
QAbstractItemModel *model;
virtual void _q_sourceModelDestroyed();
void mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent,
diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp
new file mode 100644
index 0000000000..0319d215a1
--- /dev/null
+++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp
@@ -0,0 +1,750 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qconcatenatetablesproxymodel.h"
+#include <private/qabstractitemmodel_p.h>
+#include "qsize.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+class QConcatenateTablesProxyModelPrivate : public QAbstractItemModelPrivate
+{
+ Q_DECLARE_PUBLIC(QConcatenateTablesProxyModel);
+
+public:
+ QConcatenateTablesProxyModelPrivate();
+
+ int computeRowsPrior(const QAbstractItemModel *sourceModel) const;
+
+ struct SourceModelForRowResult
+ {
+ SourceModelForRowResult() : sourceModel(nullptr), sourceRow(-1) {}
+ QAbstractItemModel *sourceModel;
+ int sourceRow;
+ };
+ SourceModelForRowResult sourceModelForRow(int row) const;
+
+ void _q_slotRowsAboutToBeInserted(const QModelIndex &, int start, int end);
+ void _q_slotRowsInserted(const QModelIndex &, int start, int end);
+ void _q_slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end);
+ void _q_slotRowsRemoved(const QModelIndex &, int start, int end);
+ void _q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end);
+ void _q_slotColumnsInserted(const QModelIndex &parent, int, int);
+ void _q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void _q_slotColumnsRemoved(const QModelIndex &parent, int, int);
+ void _q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QVector<int> &roles);
+ void _q_slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
+ void _q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
+ void _q_slotModelAboutToBeReset();
+ void _q_slotModelReset();
+ int columnCountAfterChange(const QAbstractItemModel *model, int newCount) const;
+ int calculatedColumnCount() const;
+ void updateColumnCount();
+ bool mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent,
+ int *sourceRow, int *sourceColumn, QModelIndex *sourceParent, QAbstractItemModel **sourceModel) const;
+
+ QVector<QAbstractItemModel *> m_models;
+ int m_rowCount; // have to maintain it here since we can't compute during model destruction
+ int m_columnCount;
+
+ // for columns{AboutToBe,}{Inserted,Removed}
+ int m_newColumnCount;
+
+ // for layoutAboutToBeChanged/layoutChanged
+ QVector<QPersistentModelIndex> layoutChangePersistentIndexes;
+ QVector<QModelIndex> layoutChangeProxyIndexes;
+};
+
+QConcatenateTablesProxyModelPrivate::QConcatenateTablesProxyModelPrivate()
+ : m_rowCount(0),
+ m_columnCount(0),
+ m_newColumnCount(0)
+{
+}
+
+/*!
+ \since 5.13
+ \class QConcatenateTablesProxyModel
+ \inmodule QtCore
+ \brief The QConcatenateTablesProxyModel class proxies multiple source models, concatenating their rows.
+
+ \ingroup model-view
+
+ QConcatenateTablesProxyModel takes multiple source models and concatenates their rows.
+
+ In other words, the proxy will have all rows of the first source model,
+ followed by all rows of the second source model, and so on.
+
+ If the source models don't have the same number of columns, the proxy will only
+ have as many columns as the source model with the smallest number of columns.
+ Additional columns in other source models will simply be ignored.
+
+ Source models can be added and removed at runtime, and the column count is adjusted accordingly.
+
+ This proxy does not inherit from QAbstractProxyModel because it uses multiple source
+ models, rather than a single one.
+
+ Only flat models (lists and tables) are supported, tree models are not.
+
+ \sa QAbstractProxyModel, {Model/View Programming}, QIdentityProxyModel, QAbstractItemModel
+ */
+
+
+/*!
+ Constructs a concatenate-rows proxy model with the given \a parent.
+*/
+QConcatenateTablesProxyModel::QConcatenateTablesProxyModel(QObject *parent)
+ : QAbstractItemModel(*new QConcatenateTablesProxyModelPrivate, parent)
+{
+}
+
+/*!
+ Destroys this proxy model.
+*/
+QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel()
+{
+}
+
+/*!
+ Returns the proxy index for a given \a sourceIndex, which can be from any of the source models.
+*/
+QModelIndex QConcatenateTablesProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ if (!sourceIndex.isValid())
+ return QModelIndex();
+ const QAbstractItemModel *sourceModel = sourceIndex.model();
+ if (!d->m_models.contains(const_cast<QAbstractItemModel *>(sourceModel))) {
+ qWarning("QConcatenateTablesProxyModel: index from wrong model passed to mapFromSource");
+ Q_ASSERT(!"QConcatenateTablesProxyModel: index from wrong model passed to mapFromSource");
+ return QModelIndex();
+ }
+ if (sourceIndex.column() >= d->m_columnCount)
+ return QModelIndex();
+ int rowsPrior = d_func()->computeRowsPrior(sourceModel);
+ return createIndex(rowsPrior + sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer());
+}
+
+/*!
+ Returns the source index for a given \a proxyIndex.
+*/
+QModelIndex QConcatenateTablesProxyModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ Q_ASSERT(checkIndex(proxyIndex));
+ if (!proxyIndex.isValid())
+ return QModelIndex();
+ if (proxyIndex.model() != this) {
+ qWarning("QConcatenateTablesProxyModel: index from wrong model passed to mapToSource");
+ Q_ASSERT(!"QConcatenateTablesProxyModel: index from wrong model passed to mapToSource");
+ return QModelIndex();
+ }
+ const int row = proxyIndex.row();
+ const auto result = d->sourceModelForRow(row);
+ if (!result.sourceModel)
+ return QModelIndex();
+ return result.sourceModel->index(result.sourceRow, proxyIndex.column());
+}
+
+/*!
+ \reimp
+*/
+QVariant QConcatenateTablesProxyModel::data(const QModelIndex &index, int role) const
+{
+ const QModelIndex sourceIndex = mapToSource(index);
+ Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
+ if (!sourceIndex.isValid())
+ return QVariant();
+ return sourceIndex.data(role);
+}
+
+/*!
+ \reimp
+*/
+bool QConcatenateTablesProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid));
+ const QModelIndex sourceIndex = mapToSource(index);
+ Q_ASSERT(sourceIndex.isValid());
+ const auto sourceModel = const_cast<QAbstractItemModel *>(sourceIndex.model());
+ return sourceModel->setData(sourceIndex, value, role);
+}
+
+/*!
+ \reimp
+*/
+QMap<int, QVariant> QConcatenateTablesProxyModel::itemData(const QModelIndex &proxyIndex) const
+{
+ Q_ASSERT(checkIndex(proxyIndex));
+ const QModelIndex sourceIndex = mapToSource(proxyIndex);
+ Q_ASSERT(sourceIndex.isValid());
+ return sourceIndex.model()->itemData(sourceIndex);
+}
+
+/*!
+ \reimp
+*/
+bool QConcatenateTablesProxyModel::setItemData(const QModelIndex &proxyIndex, const QMap<int, QVariant> &roles)
+{
+ Q_ASSERT(checkIndex(proxyIndex));
+ const QModelIndex sourceIndex = mapToSource(proxyIndex);
+ Q_ASSERT(sourceIndex.isValid());
+ const auto sourceModel = const_cast<QAbstractItemModel *>(sourceIndex.model());
+ return sourceModel->setItemData(sourceIndex, roles);
+}
+
+/*!
+ Returns the flags for the given index.
+ If the \a index is valid, the flags come from the source model for this \a index.
+ If the \a index is invalid (as used to determine if dropping onto an empty area
+ in the view is allowed, for instance), the flags from the first model are returned.
+*/
+Qt::ItemFlags QConcatenateTablesProxyModel::flags(const QModelIndex &index) const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ if (d->m_models.isEmpty())
+ return Qt::NoItemFlags;
+ Q_ASSERT(checkIndex(index));
+ if (!index.isValid())
+ return d->m_models.at(0)->flags(index);
+ const QModelIndex sourceIndex = mapToSource(index);
+ Q_ASSERT(sourceIndex.isValid());
+ return sourceIndex.model()->flags(sourceIndex);
+}
+
+/*!
+ This method returns the horizontal header data for the first source model,
+ and the vertical header data for the source model corresponding to each row.
+ \reimp
+*/
+QVariant QConcatenateTablesProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ if (d->m_models.isEmpty())
+ return QVariant();
+ switch (orientation) {
+ case Qt::Horizontal:
+ return d->m_models.at(0)->headerData(section, orientation, role);
+ case Qt::Vertical: {
+ const auto result = d->sourceModelForRow(section);
+ Q_ASSERT(result.sourceModel);
+ return result.sourceModel->headerData(result.sourceRow, orientation, role);
+ }
+ }
+ return QVariant();
+}
+
+/*!
+ This method returns the column count of the source model with the smallest number of columns.
+ \reimp
+*/
+int QConcatenateTablesProxyModel::columnCount(const QModelIndex &parent) const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ if (parent.isValid())
+ return 0; // flat model
+ return d->m_columnCount;
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QConcatenateTablesProxyModel::index(int row, int column, const QModelIndex &parent) const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ Q_ASSERT(hasIndex(row, column, parent));
+ if (!hasIndex(row, column, parent))
+ return QModelIndex();
+ Q_ASSERT(checkIndex(parent, QAbstractItemModel::CheckIndexOption::ParentIsInvalid)); // flat model
+ const auto result = d->sourceModelForRow(row);
+ Q_ASSERT(result.sourceModel);
+ return mapFromSource(result.sourceModel->index(result.sourceRow, column));
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QConcatenateTablesProxyModel::parent(const QModelIndex &index) const
+{
+ Q_UNUSED(index);
+ return QModelIndex(); // flat model, no hierarchy
+}
+
+/*!
+ \reimp
+*/
+int QConcatenateTablesProxyModel::rowCount(const QModelIndex &parent) const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ Q_ASSERT(checkIndex(parent, QAbstractItemModel::CheckIndexOption::ParentIsInvalid)); // flat model
+ Q_UNUSED(parent);
+ return d->m_rowCount;
+}
+
+/*!
+ This method returns the mime types for the first source model.
+ \reimp
+*/
+QStringList QConcatenateTablesProxyModel::mimeTypes() const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ if (d->m_models.isEmpty())
+ return QStringList();
+ return d->m_models.at(0)->mimeTypes();
+}
+
+/*!
+ The call is forwarded to the source model of the first index in the list of \a indexes.
+
+ Important: please note that this proxy only supports dragging a single row.
+ It will assert if called with indexes from multiple rows, because dragging rows that
+ might come from different source models cannot be implemented generically by this proxy model.
+ Each piece of data in the QMimeData needs to be merged, which is data-type-specific.
+ Reimplement this method in a subclass if you want to support dragging multiple rows.
+
+ \reimp
+*/
+QMimeData *QConcatenateTablesProxyModel::mimeData(const QModelIndexList &indexes) const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ if (indexes.isEmpty())
+ return nullptr;
+ const QModelIndex firstIndex = indexes.first();
+ Q_ASSERT(checkIndex(firstIndex, CheckIndexOption::IndexIsValid));
+ const auto result = d->sourceModelForRow(firstIndex.row());
+ QModelIndexList sourceIndexes;
+ sourceIndexes.reserve(indexes.count());
+ for (const QModelIndex &index : indexes) {
+ const QModelIndex sourceIndex = mapToSource(index);
+ Q_ASSERT(sourceIndex.model() == result.sourceModel); // see documentation above
+ sourceIndexes.append(sourceIndex);
+ }
+ return result.sourceModel->mimeData(sourceIndexes);
+}
+
+
+bool QConcatenateTablesProxyModelPrivate::mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent,
+ int *sourceRow, int *sourceColumn, QModelIndex *sourceParent, QAbstractItemModel **sourceModel) const
+{
+ Q_Q(const QConcatenateTablesProxyModel);
+ *sourceColumn = column;
+ if (!parent.isValid()) {
+ // Drop after the last item
+ if (row == -1 || row == m_rowCount) {
+ *sourceRow = -1;
+ *sourceModel = m_models.constLast();
+ return true;
+ }
+ // Drop between toplevel items
+ const auto result = sourceModelForRow(row);
+ Q_ASSERT(result.sourceModel);
+ *sourceRow = result.sourceRow;
+ *sourceModel = result.sourceModel;
+ return true;
+ } else {
+ if (row > -1)
+ return false; // flat model, no dropping as new children of items
+ // Drop onto item
+ const int targetRow = parent.row();
+ const auto result = sourceModelForRow(targetRow);
+ Q_ASSERT(result.sourceModel);
+ const QModelIndex sourceIndex = q->mapToSource(parent);
+ *sourceRow = -1;
+ *sourceParent = sourceIndex;
+ *sourceModel = result.sourceModel;
+ return true;
+ }
+}
+
+/*!
+ \reimp
+*/
+bool QConcatenateTablesProxyModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ if (d->m_models.isEmpty())
+ return false;
+
+ int sourceRow, sourceColumn;
+ QModelIndex sourceParent;
+ QAbstractItemModel *sourceModel;
+ if (!d->mapDropCoordinatesToSource(row, column, parent, &sourceRow, &sourceColumn, &sourceParent, &sourceModel))
+ return false;
+ return sourceModel->canDropMimeData(data, action, sourceRow, sourceColumn, sourceParent);
+}
+
+/*!
+ QConcatenateTablesProxyModel handles dropping onto an item, between items, and after the last item.
+ In all cases the call is forwarded to the underlying source model.
+ When dropping onto an item, the source model for this item is called.
+ When dropping between items, the source model immediately below the drop position is called.
+ When dropping after the last item, the last source model is called.
+
+ \reimp
+*/
+bool QConcatenateTablesProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ if (d->m_models.isEmpty())
+ return false;
+ int sourceRow, sourceColumn;
+ QModelIndex sourceParent;
+ QAbstractItemModel *sourceModel;
+ if (!d->mapDropCoordinatesToSource(row, column, parent, &sourceRow, &sourceColumn, &sourceParent, &sourceModel))
+ return false;
+
+ return sourceModel->dropMimeData(data, action, sourceRow, sourceColumn, sourceParent);
+}
+
+/*!
+ \reimp
+*/
+QSize QConcatenateTablesProxyModel::span(const QModelIndex &index) const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ Q_ASSERT(checkIndex(index));
+ if (d->m_models.isEmpty() || !index.isValid())
+ return QSize();
+ const QModelIndex sourceIndex = mapToSource(index);
+ Q_ASSERT(sourceIndex.isValid());
+ return sourceIndex.model()->span(sourceIndex);
+}
+
+/*!
+ Adds a source model \a sourceModel, below all previously added source models.
+
+ The ownership of \a sourceModel is not affected by this.
+
+ The same source model cannot be added more than once.
+ */
+void QConcatenateTablesProxyModel::addSourceModel(QAbstractItemModel *sourceModel)
+{
+ Q_D(QConcatenateTablesProxyModel);
+ Q_ASSERT(sourceModel);
+ Q_ASSERT(!d->m_models.contains(sourceModel));
+ connect(sourceModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), this, SLOT(_q_slotDataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ connect(sourceModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(_q_slotRowsInserted(QModelIndex,int,int)));
+ connect(sourceModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(_q_slotRowsRemoved(QModelIndex,int,int)));
+ connect(sourceModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(_q_slotRowsAboutToBeInserted(QModelIndex,int,int)));
+ connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(_q_slotRowsAboutToBeRemoved(QModelIndex,int,int)));
+
+ connect(sourceModel, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(_q_slotColumnsInserted(QModelIndex,int,int)));
+ connect(sourceModel, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(_q_slotColumnsRemoved(QModelIndex,int,int)));
+ connect(sourceModel, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(_q_slotColumnsAboutToBeInserted(QModelIndex,int,int)));
+ connect(sourceModel, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(_q_slotColumnsAboutToBeRemoved(QModelIndex,int,int)));
+
+ connect(sourceModel, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)),
+ this, SLOT(_q_slotSourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)));
+ connect(sourceModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)),
+ this, SLOT(_q_slotSourceLayoutChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)));
+ connect(sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_slotModelAboutToBeReset()));
+ connect(sourceModel, SIGNAL(modelReset()), this, SLOT(_q_slotModelReset()));
+
+ const int newRows = sourceModel->rowCount();
+ if (newRows > 0)
+ beginInsertRows(QModelIndex(), d->m_rowCount, d->m_rowCount + newRows - 1);
+ d->m_rowCount += newRows;
+ d->m_models.append(sourceModel);
+ if (newRows > 0)
+ endInsertRows();
+
+ d->updateColumnCount();
+}
+
+/*!
+ Removes the source model \a sourceModel, which was previously added to this proxy.
+
+ The ownership of \a sourceModel is not affected by this.
+*/
+void QConcatenateTablesProxyModel::removeSourceModel(QAbstractItemModel *sourceModel)
+{
+ Q_D(QConcatenateTablesProxyModel);
+ Q_ASSERT(d->m_models.contains(sourceModel));
+ disconnect(sourceModel, 0, this, 0);
+
+ const int rowsRemoved = sourceModel->rowCount();
+ const int rowsPrior = d->computeRowsPrior(sourceModel); // location of removed section
+
+ if (rowsRemoved > 0)
+ beginRemoveRows(QModelIndex(), rowsPrior, rowsPrior + rowsRemoved - 1);
+ d->m_models.removeOne(sourceModel);
+ d->m_rowCount -= rowsRemoved;
+ if (rowsRemoved > 0)
+ endRemoveRows();
+
+ d->updateColumnCount();
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ if (parent.isValid()) // not supported, the proxy is a flat model
+ return;
+ const QAbstractItemModel * const model = static_cast<QAbstractItemModel *>(q->sender());
+ const int rowsPrior = computeRowsPrior(model);
+ q->beginInsertRows(QModelIndex(), rowsPrior + start, rowsPrior + end);
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotRowsInserted(const QModelIndex &parent, int start, int end)
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ if (parent.isValid()) // flat model
+ return;
+ m_rowCount += end - start + 1;
+ q->endInsertRows();
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ if (parent.isValid()) // flat model
+ return;
+ const QAbstractItemModel * const model = static_cast<QAbstractItemModel *>(q->sender());
+ const int rowsPrior = computeRowsPrior(model);
+ q->beginRemoveRows(QModelIndex(), rowsPrior + start, rowsPrior + end);
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotRowsRemoved(const QModelIndex &parent, int start, int end)
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ if (parent.isValid()) // flat model
+ return;
+ m_rowCount -= end - start + 1;
+ q->endRemoveRows();
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ if (parent.isValid()) // flat model
+ return;
+ const QAbstractItemModel * const model = static_cast<QAbstractItemModel *>(q->sender());
+ const int oldColCount = model->columnCount();
+ const int newColCount = columnCountAfterChange(model, oldColCount + end - start + 1);
+ Q_ASSERT(newColCount >= oldColCount);
+ if (newColCount > oldColCount)
+ // If the underlying models have a different number of columns (example: 2 and 3), inserting 2 columns in
+ // the first model leads to inserting only one column in the proxy, since qMin(2+2,3) == 3.
+ q->beginInsertColumns(QModelIndex(), start, qMin(end, start + newColCount - oldColCount - 1));
+ m_newColumnCount = newColCount;
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotColumnsInserted(const QModelIndex &parent, int start, int end)
+{
+ Q_UNUSED(start);
+ Q_UNUSED(end);
+ Q_Q(QConcatenateTablesProxyModel);
+ if (parent.isValid()) // flat model
+ return;
+ if (m_newColumnCount != m_columnCount) {
+ m_columnCount = m_newColumnCount;
+ q->endInsertColumns();
+ }
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ if (parent.isValid()) // flat model
+ return;
+ const QAbstractItemModel * const model = static_cast<QAbstractItemModel *>(q->sender());
+ const int oldColCount = model->columnCount();
+ const int newColCount = columnCountAfterChange(model, oldColCount - (end - start + 1));
+ Q_ASSERT(newColCount <= oldColCount);
+ if (newColCount < oldColCount)
+ q->beginRemoveColumns(QModelIndex(), start, qMax(end, start + oldColCount - newColCount - 1));
+ m_newColumnCount = newColCount;
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotColumnsRemoved(const QModelIndex &parent, int start, int end)
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ Q_UNUSED(start);
+ Q_UNUSED(end);
+ if (parent.isValid()) // flat model
+ return;
+ if (m_newColumnCount != m_columnCount) {
+ m_columnCount = m_newColumnCount;
+ q->endRemoveColumns();
+ }
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QVector<int> &roles)
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ Q_ASSERT(from.isValid());
+ Q_ASSERT(to.isValid());
+ const QModelIndex myFrom = q->mapFromSource(from);
+ Q_ASSERT(q->checkIndex(myFrom, QAbstractItemModel::CheckIndexOption::IndexIsValid));
+ const QModelIndex myTo = q->mapFromSource(to);
+ Q_ASSERT(q->checkIndex(myTo, QAbstractItemModel::CheckIndexOption::IndexIsValid));
+ emit q->dataChanged(myFrom, myTo, roles);
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
+{
+ Q_Q(QConcatenateTablesProxyModel);
+
+ if (!sourceParents.isEmpty() && !sourceParents.contains(QModelIndex()))
+ return;
+
+ emit q->layoutAboutToBeChanged({}, hint);
+
+ const QModelIndexList persistentIndexList = q->persistentIndexList();
+ layoutChangePersistentIndexes.reserve(persistentIndexList.size());
+ layoutChangeProxyIndexes.reserve(persistentIndexList.size());
+
+ for (const QPersistentModelIndex &proxyPersistentIndex : persistentIndexList) {
+ layoutChangeProxyIndexes.append(proxyPersistentIndex);
+ Q_ASSERT(proxyPersistentIndex.isValid());
+ const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
+ Q_ASSERT(srcPersistentIndex.isValid());
+ layoutChangePersistentIndexes << srcPersistentIndex;
+ }
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ if (!sourceParents.isEmpty() && !sourceParents.contains(QModelIndex()))
+ return;
+ for (int i = 0; i < layoutChangeProxyIndexes.size(); ++i) {
+ const QModelIndex proxyIdx = layoutChangeProxyIndexes.at(i);
+ const QModelIndex newProxyIdx = q->mapFromSource(layoutChangePersistentIndexes.at(i));
+ q->changePersistentIndex(proxyIdx, newProxyIdx);
+ }
+
+ layoutChangePersistentIndexes.clear();
+ layoutChangeProxyIndexes.clear();
+
+ emit q->layoutChanged({}, hint);
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotModelAboutToBeReset()
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ Q_ASSERT(m_models.contains(const_cast<QAbstractItemModel *>(static_cast<const QAbstractItemModel *>(q->sender()))));
+ q->beginResetModel();
+ // A reset might reduce both rowCount and columnCount, and we can't notify of both at the same time,
+ // and notifying of one after the other leaves an intermediary invalid situation.
+ // So the only safe choice is to forward it as a full reset.
+}
+
+void QConcatenateTablesProxyModelPrivate::_q_slotModelReset()
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ Q_ASSERT(m_models.contains(const_cast<QAbstractItemModel *>(static_cast<const QAbstractItemModel *>(q->sender()))));
+ m_columnCount = calculatedColumnCount();
+ m_rowCount = computeRowsPrior(nullptr);
+ q->endResetModel();
+}
+
+int QConcatenateTablesProxyModelPrivate::calculatedColumnCount() const
+{
+ if (m_models.isEmpty())
+ return 0;
+
+ const auto it = std::min_element(m_models.begin(), m_models.end(), [](const QAbstractItemModel* model1, const QAbstractItemModel* model2) {
+ return model1->columnCount() < model2->columnCount();
+ });
+ return (*it)->columnCount();
+}
+
+void QConcatenateTablesProxyModelPrivate::updateColumnCount()
+{
+ Q_Q(QConcatenateTablesProxyModel);
+ const int newColumnCount = calculatedColumnCount();
+ const int columnDiff = newColumnCount - m_columnCount;
+ if (columnDiff > 0) {
+ q->beginInsertColumns(QModelIndex(), m_columnCount, m_columnCount + columnDiff - 1);
+ m_columnCount = newColumnCount;
+ q->endInsertColumns();
+ } else if (columnDiff < 0) {
+ const int lastColumn = m_columnCount - 1;
+ q->beginRemoveColumns(QModelIndex(), lastColumn + columnDiff + 1, lastColumn);
+ m_columnCount = newColumnCount;
+ q->endRemoveColumns();
+ }
+}
+
+int QConcatenateTablesProxyModelPrivate::columnCountAfterChange(const QAbstractItemModel *model, int newCount) const
+{
+ int newColumnCount = 0;
+ for (int i = 0; i < m_models.count(); ++i) {
+ const QAbstractItemModel *mod = m_models.at(i);
+ const int colCount = mod == model ? newCount : mod->columnCount();
+ if (i == 0)
+ newColumnCount = colCount;
+ else
+ newColumnCount = qMin(colCount, newColumnCount);
+ }
+ return newColumnCount;
+}
+
+int QConcatenateTablesProxyModelPrivate::computeRowsPrior(const QAbstractItemModel *sourceModel) const
+{
+ int rowsPrior = 0;
+ for (const QAbstractItemModel *model : m_models) {
+ if (model == sourceModel)
+ break;
+ rowsPrior += model->rowCount();
+ }
+ return rowsPrior;
+}
+
+QConcatenateTablesProxyModelPrivate::SourceModelForRowResult QConcatenateTablesProxyModelPrivate::sourceModelForRow(int row) const
+{
+ QConcatenateTablesProxyModelPrivate::SourceModelForRowResult result;
+ int rowCount = 0;
+ for (QAbstractItemModel *model : m_models) {
+ const int subRowCount = model->rowCount();
+ if (rowCount + subRowCount > row) {
+ result.sourceModel = model;
+ break;
+ }
+ rowCount += subRowCount;
+ }
+ result.sourceRow = row - rowCount;
+ return result;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qconcatenatetablesproxymodel.cpp"
diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.h b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h
new file mode 100644
index 0000000000..69b3a2ba09
--- /dev/null
+++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCONCATENATEROWSPROXYMODEL_H
+#define QCONCATENATEROWSPROXYMODEL_H
+
+#include <QtCore/qabstractitemmodel.h>
+
+QT_REQUIRE_CONFIG(concatenatetablesproxymodel);
+
+QT_BEGIN_NAMESPACE
+
+class QConcatenateTablesProxyModelPrivate;
+
+class Q_CORE_EXPORT QConcatenateTablesProxyModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ explicit QConcatenateTablesProxyModel(QObject *parent = nullptr);
+ ~QConcatenateTablesProxyModel();
+
+ Q_SCRIPTABLE void addSourceModel(QAbstractItemModel *sourceModel);
+ Q_SCRIPTABLE void removeSourceModel(QAbstractItemModel *sourceModel);
+
+ QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+ QMap<int, QVariant> itemData(const QModelIndex &proxyIndex) const override;
+ bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
+ QModelIndex parent(const QModelIndex &index) const override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ QStringList mimeTypes() const override;
+ QMimeData *mimeData(const QModelIndexList &indexes) const override;
+ bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
+ QSize span(const QModelIndex &index) const override;
+
+private:
+ Q_DECLARE_PRIVATE(QConcatenateTablesProxyModel)
+ Q_DISABLE_COPY(QConcatenateTablesProxyModel)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_slotRowsAboutToBeInserted(const QModelIndex &, int start, int end))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotRowsInserted(const QModelIndex &, int start, int end))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotRowsRemoved(const QModelIndex &, int start, int end))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsInserted(const QModelIndex &parent, int, int))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsRemoved(const QModelIndex &parent, int, int))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QVector<int> &roles))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotSourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint))
+ Q_PRIVATE_SLOT(d_func(), void _q_slotModelAboutToBeReset())
+ Q_PRIVATE_SLOT(d_func(), void _q_slotModelReset())
+};
+
+QT_END_NAMESPACE
+
+#endif // QCONCATENATEROWSPROXYMODEL_H
diff --git a/src/corelib/itemmodels/qidentityproxymodel.cpp b/src/corelib/itemmodels/qidentityproxymodel.cpp
index f869601d3f..39992eccd3 100644
--- a/src/corelib/itemmodels/qidentityproxymodel.cpp
+++ b/src/corelib/itemmodels/qidentityproxymodel.cpp
@@ -95,7 +95,7 @@ class QIdentityProxyModelPrivate : public QAbstractProxyModelPrivate
need to implement all data handling in the same class that creates the structure of the model, and can also be used to create
re-usable components.
- This also provides a way to change the data in the case where a source model is supplied by a third party which can not be modified.
+ This also provides a way to change the data in the case where a source model is supplied by a third party which cannot be modified.
\snippet code/src_gui_itemviews_qidentityproxymodel.cpp 0
@@ -480,13 +480,13 @@ void QIdentityProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &topLeft
Q_ASSERT(topLeft.isValid() ? topLeft.model() == model : true);
Q_ASSERT(bottomRight.isValid() ? bottomRight.model() == model : true);
Q_Q(QIdentityProxyModel);
- q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight), roles);
+ emit q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight), roles);
}
void QIdentityProxyModelPrivate::_q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last)
{
Q_Q(QIdentityProxyModel);
- q->headerDataChanged(orientation, first, last);
+ emit q->headerDataChanged(orientation, first, last);
}
void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
@@ -505,7 +505,7 @@ void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<QPe
parents << mappedParent;
}
- q->layoutAboutToBeChanged(parents, hint);
+ emit q->layoutAboutToBeChanged(parents, hint);
const auto proxyPersistentIndexes = q->persistentIndexList();
for (const QPersistentModelIndex &proxyPersistentIndex : proxyPersistentIndexes) {
@@ -540,7 +540,7 @@ void QIdentityProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersistentM
parents << mappedParent;
}
- q->layoutChanged(parents, hint);
+ emit q->layoutChanged(parents, hint);
}
void QIdentityProxyModelPrivate::_q_sourceModelAboutToBeReset()
diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp
index 1bacb63b17..c93a4d15b9 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.cpp
+++ b/src/corelib/itemmodels/qitemselectionmodel.cpp
@@ -1273,10 +1273,10 @@ struct IsNotValid {
typedef bool result_type;
struct is_transparent : std::true_type {};
template <typename T>
- Q_DECL_CONSTEXPR bool operator()(T &t) const Q_DECL_NOEXCEPT_EXPR(noexcept(t.isValid()))
+ Q_DECL_CONSTEXPR bool operator()(T &t) const noexcept(noexcept(t.isValid()))
{ return !t.isValid(); }
template <typename T>
- Q_DECL_CONSTEXPR bool operator()(T *t) const Q_DECL_NOEXCEPT_EXPR(noexcept(t->isValid()))
+ Q_DECL_CONSTEXPR bool operator()(T *t) const noexcept(noexcept(t->isValid()))
{ return !t->isValid(); }
};
}
diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h
index 1c924053a5..3c3f9fb1ac 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.h
+++ b/src/corelib/itemmodels/qitemselectionmodel.h
@@ -60,19 +60,17 @@ public:
// ### Qt 6: remove them all, the compiler-generated ones are fine
inline QItemSelectionRange(const QItemSelectionRange &other)
: tl(other.tl), br(other.br) {}
-# ifdef Q_COMPILER_RVALUE_REFS
- QItemSelectionRange(QItemSelectionRange &&other) Q_DECL_NOTHROW
+ QItemSelectionRange(QItemSelectionRange &&other) noexcept
: tl(std::move(other.tl)), br(std::move(other.br)) {}
- QItemSelectionRange &operator=(QItemSelectionRange &&other) Q_DECL_NOTHROW
+ QItemSelectionRange &operator=(QItemSelectionRange &&other) noexcept
{ tl = std::move(other.tl); br = std::move(other.br); return *this; }
-# endif
QItemSelectionRange &operator=(const QItemSelectionRange &other)
{ tl = other.tl; br = other.br; return *this; }
#endif // Qt < 6
QItemSelectionRange(const QModelIndex &topL, const QModelIndex &bottomR) : tl(topL), br(bottomR) {}
explicit QItemSelectionRange(const QModelIndex &index) : tl(index), br(tl) {}
- void swap(QItemSelectionRange &other) Q_DECL_NOTHROW
+ void swap(QItemSelectionRange &other) noexcept
{
qSwap(tl, other.tl);
qSwap(br, other.br);
@@ -249,7 +247,7 @@ Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QList<QItemSelectionRange>;
class Q_CORE_EXPORT QItemSelection : public QList<QItemSelectionRange>
{
public:
- QItemSelection() Q_DECL_NOTHROW : QList<QItemSelectionRange>() {}
+ QItemSelection() noexcept : QList<QItemSelectionRange>() {}
QItemSelection(const QModelIndex &topLeft, const QModelIndex &bottomRight);
// reusing QList::swap() here is OK!
diff --git a/src/corelib/itemmodels/qitemselectionmodel_p.h b/src/corelib/itemmodels/qitemselectionmodel_p.h
index e12a0c2928..ba85f22be3 100644
--- a/src/corelib/itemmodels/qitemselectionmodel_p.h
+++ b/src/corelib/itemmodels/qitemselectionmodel_p.h
@@ -62,7 +62,7 @@ class QItemSelectionModelPrivate: public QObjectPrivate
Q_DECLARE_PUBLIC(QItemSelectionModel)
public:
QItemSelectionModelPrivate()
- : model(0),
+ : model(nullptr),
currentCommand(QItemSelectionModel::NoUpdate),
tableSelected(false), tableColCount(0), tableRowCount(0) {}
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 87960b0863..d13e6199db 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -424,7 +424,7 @@ public:
void updateChildrenMapping(const QModelIndex &source_parent, Mapping *parent_mapping,
Qt::Orientation orient, int start, int end, int delta_item_count, bool remove);
- virtual void _q_sourceModelDestroyed() override;
+ void _q_sourceModelDestroyed() override;
bool needsReorder(const QVector<int> &source_rows, const QModelIndex &source_parent) const;
diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp
index f92a0d6676..a248cdcd38 100644
--- a/src/corelib/itemmodels/qstringlistmodel.cpp
+++ b/src/corelib/itemmodels/qstringlistmodel.cpp
@@ -136,6 +136,42 @@ QModelIndex QStringListModel::sibling(int row, int column, const QModelIndex &id
}
/*!
+ \reimp
+ \since 5.13
+*/
+QMap<int, QVariant> QStringListModel::itemData(const QModelIndex &index) const
+{
+ if (!checkIndex(index, CheckIndexOption::IndexIsValid | CheckIndexOption::ParentIsInvalid))
+ return QMap<int, QVariant>{};
+ const QVariant displayData = lst.at(index.row());
+ return QMap<int, QVariant>{{
+ std::make_pair<int>(Qt::DisplayRole, displayData),
+ std::make_pair<int>(Qt::EditRole, displayData)
+ }};
+}
+
+/*!
+ \reimp
+ \since 5.13
+ If \a roles contains both Qt::DisplayRole and Qt::EditRole, the latter will take precedence
+*/
+bool QStringListModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
+{
+ if (roles.isEmpty())
+ return false;
+ if (std::any_of(roles.keyBegin(), roles.keyEnd(), [](int role) -> bool {
+ return role != Qt::DisplayRole && role != Qt::EditRole;
+ })) {
+ return false;
+ }
+ auto roleIter = roles.constFind(Qt::EditRole);
+ if (roleIter == roles.constEnd())
+ roleIter = roles.constFind(Qt::DisplayRole);
+ Q_ASSERT(roleIter != roles.constEnd());
+ return setData(index, roleIter.value(), roleIter.key());
+}
+
+/*!
Returns data for the specified \a role, from the item with the
given \a index.
@@ -188,18 +224,23 @@ bool QStringListModel::setData(const QModelIndex &index, const QVariant &value,
if (lst.at(index.row()) == valueString)
return true;
lst.replace(index.row(), valueString);
- QVector<int> roles;
- roles.reserve(2);
- roles.append(Qt::DisplayRole);
- roles.append(Qt::EditRole);
- emit dataChanged(index, index, roles);
- // once Q_COMPILER_UNIFORM_INIT can be used, change to:
- // emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
+ emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
return true;
}
return false;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \reimp
+ \since 6.0
+ */
+bool QStringListModel::clearItemData(const QModelIndex &index)
+{
+ return setData(index, QVariant(), Qt::EditRole);
+}
+#endif
+
/*!
Inserts \a count rows into the model, beginning at the given \a row.
@@ -252,6 +293,38 @@ bool QStringListModel::removeRows(int row, int count, const QModelIndex &parent)
return true;
}
+/*!
+ \since 5.13
+ \reimp
+*/
+bool QStringListModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
+{
+ if (sourceRow < 0
+ || sourceRow + count - 1 >= rowCount(sourceParent)
+ || destinationChild <= 0
+ || destinationChild > rowCount(destinationParent)
+ || sourceRow == destinationChild - 1
+ || count <= 0) {
+ return false;
+ }
+ if (!beginMoveRows(QModelIndex(), sourceRow, sourceRow + count - 1, QModelIndex(), destinationChild))
+ return false;
+ /*
+ QList::move assumes that the second argument is the index where the item will end up to
+ i.e. the valid range for that argument is from 0 to QList::size()-1
+ QAbstractItemModel::moveRows when source and destinations have the same parent assumes that
+ the item will end up being in the row BEFORE the one indicated by destinationChild
+ i.e. the valid range for that argument is from 1 to QList::size()
+ For this reason we remove 1 from destinationChild when using it inside QList
+ */
+ destinationChild--;
+ const int fromRow = destinationChild < sourceRow ? (sourceRow + count - 1) : sourceRow;
+ while (count--)
+ lst.move(fromRow, destinationChild);
+ endMoveRows();
+ return true;
+}
+
static bool ascendingLessThan(const QPair<QString, int> &s1, const QPair<QString, int> &s2)
{
return s1.first < s2.first;
diff --git a/src/corelib/itemmodels/qstringlistmodel.h b/src/corelib/itemmodels/qstringlistmodel.h
index 53376285c6..86725ea80b 100644
--- a/src/corelib/itemmodels/qstringlistmodel.h
+++ b/src/corelib/itemmodels/qstringlistmodel.h
@@ -59,11 +59,18 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool clearItemData(const QModelIndex &index) override;
+#endif
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
+ bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
+
+ QMap<int, QVariant> itemData(const QModelIndex &index) const override;
+ bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override;
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
diff --git a/src/corelib/itemmodels/qtransposeproxymodel.cpp b/src/corelib/itemmodels/qtransposeproxymodel.cpp
new file mode 100644
index 0000000000..d4f379bc64
--- /dev/null
+++ b/src/corelib/itemmodels/qtransposeproxymodel.cpp
@@ -0,0 +1,447 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtransposeproxymodel.h"
+#include <private/qtransposeproxymodel_p.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+QModelIndex QTransposeProxyModelPrivate::uncheckedMapToSource(const QModelIndex &proxyIndex) const
+{
+ if (!model || !proxyIndex.isValid())
+ return QModelIndex();
+ if (proxyIndex.internalPointer())
+ return model->createIndex(proxyIndex.column(), proxyIndex.row(), proxyIndex.internalPointer());
+ return model->index(proxyIndex.column(), proxyIndex.row());
+}
+
+QModelIndex QTransposeProxyModelPrivate::uncheckedMapFromSource(const QModelIndex &sourceIndex) const
+{
+ if (!model || !sourceIndex.isValid())
+ return QModelIndex();
+ Q_Q(const QTransposeProxyModel);
+ return q->createIndex(sourceIndex.column(), sourceIndex.row(), sourceIndex.internalPointer());
+}
+
+void QTransposeProxyModelPrivate::onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
+{
+ Q_Q(QTransposeProxyModel);
+ QModelIndexList toList;
+ toList.reserve(layoutChangePersistentIndexes.size());
+ for (const QPersistentModelIndex &persistIdx : qAsConst(layoutChangePersistentIndexes))
+ toList << q->mapFromSource(persistIdx);
+ q->changePersistentIndexList(layoutChangeProxyIndexes, toList);
+ layoutChangeProxyIndexes.clear();
+ layoutChangePersistentIndexes.clear();
+ QList<QPersistentModelIndex> proxyParents;
+ proxyParents.reserve(parents.size());
+ for (const QPersistentModelIndex &srcParent : parents)
+ proxyParents << q->mapFromSource(srcParent);
+ QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint;
+ if (hint == QAbstractItemModel::VerticalSortHint)
+ proxyHint = QAbstractItemModel::HorizontalSortHint;
+ else if (hint == QAbstractItemModel::HorizontalSortHint)
+ proxyHint = QAbstractItemModel::VerticalSortHint;
+ emit q->layoutChanged(proxyParents, proxyHint);
+}
+
+void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
+{
+ Q_Q(QTransposeProxyModel);
+ const QModelIndexList proxyPersistentIndexes = q->persistentIndexList();
+ layoutChangeProxyIndexes.clear();
+ layoutChangePersistentIndexes.clear();
+ layoutChangeProxyIndexes.reserve(proxyPersistentIndexes.size());
+ layoutChangePersistentIndexes.reserve(proxyPersistentIndexes.size());
+ for (const QPersistentModelIndex &proxyPersistentIndex : proxyPersistentIndexes) {
+ layoutChangeProxyIndexes << proxyPersistentIndex;
+ Q_ASSERT(proxyPersistentIndex.isValid());
+ const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
+ Q_ASSERT(srcPersistentIndex.isValid());
+ layoutChangePersistentIndexes << srcPersistentIndex;
+ }
+ QList<QPersistentModelIndex> proxyParents;
+ proxyParents.reserve(parents.size());
+ for (auto& srcParent : parents)
+ proxyParents << q->mapFromSource(srcParent);
+ QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint;
+ if (hint == QAbstractItemModel::VerticalSortHint)
+ proxyHint = QAbstractItemModel::HorizontalSortHint;
+ else if (hint == QAbstractItemModel::HorizontalSortHint)
+ proxyHint = QAbstractItemModel::VerticalSortHint;
+ emit q->layoutAboutToBeChanged(proxyParents, proxyHint);
+}
+
+void QTransposeProxyModelPrivate::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
+{
+ Q_Q(QTransposeProxyModel);
+ emit q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight), roles);
+}
+
+void QTransposeProxyModelPrivate::onHeaderDataChanged(Qt::Orientation orientation, int first, int last)
+{
+ Q_Q(QTransposeProxyModel);
+ emit q->headerDataChanged(orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, first, last);
+}
+
+void QTransposeProxyModelPrivate::onColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginInsertRows(q->mapFromSource(parent), first, last);
+}
+
+void QTransposeProxyModelPrivate::onColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginRemoveRows(q->mapFromSource(parent), first, last);
+}
+
+void QTransposeProxyModelPrivate::onColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginMoveRows(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destinationParent), destinationColumn);
+}
+
+void QTransposeProxyModelPrivate::onRowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginInsertColumns(q->mapFromSource(parent), first, last);
+}
+
+void QTransposeProxyModelPrivate::onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginRemoveColumns(q->mapFromSource(parent), first, last);
+}
+
+void QTransposeProxyModelPrivate::onRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginMoveColumns(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destinationParent), destinationRow);
+}
+
+/*!
+ \since 5.13
+ \class QTransposeProxyModel
+ \brief This proxy transposes the source model.
+
+ This model will make the rows of the source model become columns of the proxy model and vice-versa.
+
+ If the model is a tree, the parents will be transposed as well. For example, if an index in the source model had parent `index(2,0)`, it will have parent `index(0,2)` in the proxy.
+*/
+
+/*!
+ Constructs a new proxy model with the given \a parent.
+*/
+QTransposeProxyModel::QTransposeProxyModel(QObject* parent)
+ : QAbstractProxyModel(*new QTransposeProxyModelPrivate, parent)
+{}
+
+/*!
+ Destructs the proxy model.
+*/
+QTransposeProxyModel::~QTransposeProxyModel() = default;
+
+/*!
+ \internal
+*/
+QTransposeProxyModel::QTransposeProxyModel(QTransposeProxyModelPrivate &dd, QObject *parent)
+ : QAbstractProxyModel(dd, parent)
+{}
+
+/*!
+ \reimp
+*/
+void QTransposeProxyModel::setSourceModel(QAbstractItemModel* newSourceModel)
+{
+ Q_D(QTransposeProxyModel);
+ if (newSourceModel == d->model)
+ return;
+ beginResetModel();
+ if (d->model) {
+ for (const QMetaObject::Connection& discIter : qAsConst(d->sourceConnections))
+ disconnect(discIter);
+ }
+ d->sourceConnections.clear();
+ QAbstractProxyModel::setSourceModel(newSourceModel);
+ if (d->model) {
+ using namespace std::placeholders;
+ d->sourceConnections = QVector<QMetaObject::Connection>{
+ connect(d->model, &QAbstractItemModel::modelAboutToBeReset, this, &QTransposeProxyModel::beginResetModel),
+ connect(d->model, &QAbstractItemModel::modelReset, this, &QTransposeProxyModel::endResetModel),
+ connect(d->model, &QAbstractItemModel::dataChanged, this, std::bind(&QTransposeProxyModelPrivate::onDataChanged, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::headerDataChanged, this, std::bind(&QTransposeProxyModelPrivate::onHeaderDataChanged, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::columnsAboutToBeInserted, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeInserted, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::columnsAboutToBeMoved, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeMoved, d, _1, _2, _3, _4, _5)),
+ connect(d->model, &QAbstractItemModel::columnsAboutToBeRemoved, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeRemoved, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::columnsInserted, this, &QTransposeProxyModel::endInsertRows),
+ connect(d->model, &QAbstractItemModel::columnsRemoved, this, &QTransposeProxyModel::endRemoveRows),
+ connect(d->model, &QAbstractItemModel::columnsMoved, this, &QTransposeProxyModel::endMoveRows),
+ connect(d->model, &QAbstractItemModel::rowsAboutToBeInserted, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeInserted, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::rowsAboutToBeMoved, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeMoved, d, _1, _2, _3, _4, _5)),
+ connect(d->model, &QAbstractItemModel::rowsAboutToBeRemoved, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeRemoved, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::rowsInserted, this, &QTransposeProxyModel::endInsertColumns),
+ connect(d->model, &QAbstractItemModel::rowsRemoved, this, &QTransposeProxyModel::endRemoveColumns),
+ connect(d->model, &QAbstractItemModel::rowsMoved, this, &QTransposeProxyModel::endMoveColumns),
+ connect(d->model, &QAbstractItemModel::layoutAboutToBeChanged, this, std::bind(&QTransposeProxyModelPrivate::onLayoutAboutToBeChanged, d, _1, _2)),
+ connect(d->model, &QAbstractItemModel::layoutChanged, this, std::bind(&QTransposeProxyModelPrivate::onLayoutChanged, d, _1, _2))
+ };
+ }
+ endResetModel();
+}
+
+/*!
+ \reimp
+*/
+int QTransposeProxyModel::rowCount(const QModelIndex &parent) const
+{
+ Q_D(const QTransposeProxyModel);
+ if (!d->model)
+ return 0;
+ Q_ASSERT(checkIndex(parent));
+ return d->model->columnCount(mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+int QTransposeProxyModel::columnCount(const QModelIndex &parent) const
+{
+ Q_D(const QTransposeProxyModel);
+ if (!d->model)
+ return 0;
+ Q_ASSERT(checkIndex(parent));
+ return d->model->rowCount(mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+QVariant QTransposeProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ Q_D(const QTransposeProxyModel);
+ if (!d->model)
+ return QVariant();
+ return d->model->headerData(section, orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, role);
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
+{
+ Q_D(QTransposeProxyModel);
+ if (!d->model)
+ return false;
+ return d->model->setHeaderData(section, orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, value, role);
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(index));
+ if (!d->model || !index.isValid())
+ return false;
+ return d->model->setItemData(mapToSource(index), roles);
+}
+
+/*!
+ \reimp
+*/
+QSize QTransposeProxyModel::span(const QModelIndex &index) const
+{
+ Q_D(const QTransposeProxyModel);
+ Q_ASSERT(checkIndex(index));
+ if (!d->model || !index.isValid())
+ return QSize();
+ return d->model->span(mapToSource(index)).transposed();
+}
+
+/*!
+ \reimp
+*/
+QMap<int, QVariant> QTransposeProxyModel::itemData(const QModelIndex &index) const
+{
+ Q_D(const QTransposeProxyModel);
+ if (!d->model)
+ return QMap<int, QVariant>();
+ Q_ASSERT(checkIndex(index));
+ return d->model->itemData(mapToSource(index));
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QTransposeProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ Q_D(const QTransposeProxyModel);
+ if (!d->model || !sourceIndex.isValid())
+ return QModelIndex();
+ Q_ASSERT(d->model->checkIndex(sourceIndex));
+ return d->uncheckedMapFromSource(sourceIndex);
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QTransposeProxyModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ Q_D(const QTransposeProxyModel);
+ Q_ASSERT(checkIndex(proxyIndex));
+ if (!d->model || !proxyIndex.isValid())
+ return QModelIndex();
+ return d->uncheckedMapToSource(proxyIndex);
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QTransposeProxyModel::parent(const QModelIndex &index) const
+{
+ Q_D(const QTransposeProxyModel);
+ Q_ASSERT(checkIndex(index, CheckIndexOption::DoNotUseParent));
+ if (!d->model || !index.isValid())
+ return QModelIndex();
+ return d->uncheckedMapFromSource(d->uncheckedMapToSource(index).parent());
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QTransposeProxyModel::index(int row, int column, const QModelIndex &parent) const
+{
+ Q_D(const QTransposeProxyModel);
+ Q_ASSERT(checkIndex(parent));
+ if (!d->model)
+ return QModelIndex();
+ return mapFromSource(d->model->index(column, row, mapToSource(parent)));
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::insertRows(int row, int count, const QModelIndex &parent)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(parent));
+ if (!d->model)
+ return false;
+ return d->model->insertColumns(row, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(parent));
+ if (!d->model)
+ return false;
+ return d->model->removeColumns(row, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(sourceParent));
+ Q_ASSERT(checkIndex(destinationParent));
+ if (!d->model)
+ return false;
+ return d->model->moveColumns(mapToSource(sourceParent), sourceRow, count, mapToSource(destinationParent), destinationChild);
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::insertColumns(int column, int count, const QModelIndex &parent)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(parent));
+ if (!d->model)
+ return false;
+ return d->model->insertRows(column, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::removeColumns(int column, int count, const QModelIndex &parent)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(parent));
+ if (!d->model)
+ return false;
+ return d->model->removeRows(column, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::moveColumns(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(sourceParent));
+ Q_ASSERT(checkIndex(destinationParent));
+ if (!d->model)
+ return false;
+ return d->model->moveRows(mapToSource(sourceParent), sourceRow, count, mapToSource(destinationParent), destinationChild);
+}
+
+/*!
+ \reimp
+ This method will perform no action. Use a QSortFilterProxyModel on top of this one if you require sorting.
+*/
+void QTransposeProxyModel::sort(int column, Qt::SortOrder order)
+{
+ Q_UNUSED(column)
+ Q_UNUSED(order)
+ return;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qtransposeproxymodel.h b/src/corelib/itemmodels/qtransposeproxymodel.h
new file mode 100644
index 0000000000..854a547fd4
--- /dev/null
+++ b/src/corelib/itemmodels/qtransposeproxymodel.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTRANSPOSEPROXYMODEL_H
+#define QTRANSPOSEPROXYMODEL_H
+
+#include <QtCore/qabstractproxymodel.h>
+#include <QtCore/qscopedpointer.h>
+
+QT_REQUIRE_CONFIG(transposeproxymodel);
+
+QT_BEGIN_NAMESPACE
+
+class QTransposeProxyModelPrivate;
+
+class Q_CORE_EXPORT QTransposeProxyModel : public QAbstractProxyModel
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QTransposeProxyModel)
+ Q_DECLARE_PRIVATE(QTransposeProxyModel)
+public:
+ explicit QTransposeProxyModel(QObject* parent = nullptr);
+ ~QTransposeProxyModel();
+ void setSourceModel(QAbstractItemModel* newSourceModel) override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+ bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override;
+ bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override;
+ QSize span(const QModelIndex &index) const override;
+ QMap<int, QVariant> itemData(const QModelIndex &index) const override;
+ QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
+ QModelIndex parent(const QModelIndex &index) const override;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
+ bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
+ bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
+ bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
+ bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
+ bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) override;
+ void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
+protected:
+ QTransposeProxyModel(QTransposeProxyModelPrivate &, QObject *parent);
+};
+
+QT_END_NAMESPACE
+
+#endif // QTRANSPOSEPROXYMODEL_H
diff --git a/src/corelib/itemmodels/qtransposeproxymodel_p.h b/src/corelib/itemmodels/qtransposeproxymodel_p.h
new file mode 100644
index 0000000000..fb5ce5c117
--- /dev/null
+++ b/src/corelib/itemmodels/qtransposeproxymodel_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTRANSPOSEPROXYMODEL_P_H
+#define QTRANSPOSEPROXYMODEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtransposeproxymodel.h"
+#include <private/qabstractproxymodel_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTransposeProxyModelPrivate : public QAbstractProxyModelPrivate
+{
+ Q_DECLARE_PUBLIC(QTransposeProxyModel)
+ Q_DISABLE_COPY(QTransposeProxyModelPrivate)
+private:
+ QTransposeProxyModelPrivate() = default;
+ QVector<QMetaObject::Connection> sourceConnections;
+ QVector<QPersistentModelIndex> layoutChangePersistentIndexes;
+ QModelIndexList layoutChangeProxyIndexes;
+ QModelIndex uncheckedMapToSource(const QModelIndex &proxyIndex) const;
+ QModelIndex uncheckedMapFromSource(const QModelIndex &sourceIndex) const;
+ void onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint);
+ void onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint);
+ void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles);
+ void onHeaderDataChanged(Qt::Orientation orientation, int first, int last);
+ void onColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void onColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void onColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn);
+ void onRowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void onRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow);
+};
+
+QT_END_NAMESPACE
+
+#endif //QTRANSPOSEPROXYMODEL_P_H
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 3f7bf3cd47..789bcb7927 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -7,7 +7,7 @@ HEADERS += \
kernel/qdeadlinetimer.h \
kernel/qdeadlinetimer_p.h \
kernel/qelapsedtimer.h \
- kernel/qeventloop.h\
+ kernel/qeventloop.h \
kernel/qpointer.h \
kernel/qcorecmdlineargs_p.h \
kernel/qcoreapplication.h \
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index ea08ff571f..7215b3f2bd 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -170,7 +170,7 @@ QAbstractEventDispatcher::~QAbstractEventDispatcher()
QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
{
QThreadData *data = thread ? QThreadData::get2(thread) : QThreadData::current();
- return data->eventDispatcher.load();
+ return data->eventDispatcher.loadRelaxed();
}
/*!
@@ -470,7 +470,11 @@ void QAbstractEventDispatcher::removeNativeEventFilter(QAbstractNativeEventFilte
\sa installNativeEventFilter(), QAbstractNativeEventFilter::nativeEventFilter()
\since 5.0
*/
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result)
+#else
bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, long *result)
+#endif
{
Q_D(QAbstractEventDispatcher);
if (!d->eventFilters.isEmpty()) {
diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h
index bd8da5c35d..4ef9c068df 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.h
+++ b/src/corelib/kernel/qabstracteventdispatcher.h
@@ -110,7 +110,11 @@ public:
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj);
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result);
+#else
bool filterNativeEvent(const QByteArray &eventType, void *message, long *result);
+#endif
#if QT_DEPRECATED_SINCE(5, 0)
QT_DEPRECATED bool filterEvent(void *message)
{ return filterNativeEvent("", message, nullptr); }
diff --git a/src/corelib/kernel/qabstractnativeeventfilter.cpp b/src/corelib/kernel/qabstractnativeeventfilter.cpp
index dcbb92f044..eaadea4c12 100644
--- a/src/corelib/kernel/qabstractnativeeventfilter.cpp
+++ b/src/corelib/kernel/qabstractnativeeventfilter.cpp
@@ -74,6 +74,7 @@ QAbstractNativeEventFilter::~QAbstractNativeEventFilter()
eventDispatcher->removeNativeEventFilter(this);
}
+// ### fixme Qt 6: result will be qintptr *
/*!
\fn bool QAbstractNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
diff --git a/src/corelib/kernel/qabstractnativeeventfilter.h b/src/corelib/kernel/qabstractnativeeventfilter.h
index d7baa42513..a468bffd61 100644
--- a/src/corelib/kernel/qabstractnativeeventfilter.h
+++ b/src/corelib/kernel/qabstractnativeeventfilter.h
@@ -52,7 +52,11 @@ public:
QAbstractNativeEventFilter();
virtual ~QAbstractNativeEventFilter();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ virtual bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) = 0;
+#else
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) = 0;
+#endif
private:
Q_DISABLE_COPY(QAbstractNativeEventFilter)
diff --git a/src/corelib/kernel/qbasictimer.cpp b/src/corelib/kernel/qbasictimer.cpp
index 637c98cd40..ea8f8e2c77 100644
--- a/src/corelib/kernel/qbasictimer.cpp
+++ b/src/corelib/kernel/qbasictimer.cpp
@@ -65,6 +65,10 @@ QT_BEGIN_NAMESPACE
has not been stopped. The timer's ID can be retrieved using
timerId().
+ Objects of this class cannot be copied, but can be moved, so you
+ can maintain a list of basic timers by holding them in container
+ that supports move-only types, e.g. std::vector.
+
The \l{widgets/wiggly}{Wiggly} example uses QBasicTimer to repaint
a widget at regular intervals.
@@ -79,6 +83,51 @@ QT_BEGIN_NAMESPACE
\sa start()
*/
+
+/*!
+ \fn QBasicTimer::QBasicTimer(QBasicTimer &&other)
+ \since 5.14
+
+ Move-constructs a basic timer from \a other, which is left
+ \l{isActive()}{inactive}.
+
+ \sa isActive(), swap()
+*/
+
+/*!
+ \fn QBasicTimer &QBasicTimer::operator=(QBasicTimer &&other)
+ \since 5.14
+
+ Move-assigns \a other to this basic timer. The timer
+ previously represented by this basic timer is stopped.
+ \a other is left as \l{isActive()}{inactive}.
+
+ \sa stop(), isActive(), swap()
+*/
+
+#if QT_DEPRECATED_SINCE(5, 14)
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \internal
+*/
+QBasicTimer::QBasicTimer(const QBasicTimer &other)
+ : id{other.id}
+{
+ qWarning("QBasicTimer can't be copied");
+}
+
+/*!
+ \internal
+*/
+QBasicTimer &QBasicTimer::operator=(const QBasicTimer &other)
+{
+ id = other.id;
+ qWarning("QBasicTimer can't be assigned to");
+ return *this;
+}
+#endif
+#endif
+
/*!
\fn QBasicTimer::~QBasicTimer()
@@ -95,6 +144,15 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QBasicTimer::swap(QBasicTimer &other)
+ \fn swap(QBasicTimer &lhs, QBasicTimer &rhs)
+ \since 5.14
+
+ Swaps string \a other with this string, or \a lhs with \a rhs.
+ This operation is very fast and never fails.
+*/
+
+/*!
\fn int QBasicTimer::timerId() const
Returns the timer's ID.
@@ -115,24 +173,7 @@ QT_BEGIN_NAMESPACE
*/
void QBasicTimer::start(int msec, QObject *obj)
{
- QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
- if (Q_UNLIKELY(!eventDispatcher)) {
- qWarning("QBasicTimer::start: QBasicTimer can only be used with threads started with QThread");
- return;
- }
- if (Q_UNLIKELY(obj && obj->thread() != eventDispatcher->thread())) {
- qWarning("QBasicTimer::start: Timers cannot be started from another thread");
- return;
- }
- if (id) {
- if (Q_LIKELY(eventDispatcher->unregisterTimer(id)))
- QAbstractEventDispatcherPrivate::releaseTimerId(id);
- else
- qWarning("QBasicTimer::start: Stopping previous timer failed. Possibly trying to stop from a different thread");
- }
- id = 0;
- if (obj)
- id = eventDispatcher->registerTimer(msec, Qt::CoarseTimer, obj);
+ start(msec, Qt::CoarseTimer, obj);
}
/*!
@@ -161,13 +202,7 @@ void QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj)
qWarning("QBasicTimer::start: Timers cannot be started from another thread");
return;
}
- if (id) {
- if (Q_LIKELY(eventDispatcher->unregisterTimer(id)))
- QAbstractEventDispatcherPrivate::releaseTimerId(id);
- else
- qWarning("QBasicTimer::start: Stopping previous timer failed. Possibly trying to stop from a different thread");
- }
- id = 0;
+ stop();
if (obj)
id = eventDispatcher->registerTimer(msec, timerType, obj);
}
diff --git a/src/corelib/kernel/qbasictimer.h b/src/corelib/kernel/qbasictimer.h
index bfd6ffd125..769898f835 100644
--- a/src/corelib/kernel/qbasictimer.h
+++ b/src/corelib/kernel/qbasictimer.h
@@ -51,12 +51,35 @@ class QObject;
class Q_CORE_EXPORT QBasicTimer
{
int id;
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+ Q_DISABLE_COPY(QBasicTimer)
+#elif QT_DEPRECATED_SINCE(5, 14)
public:
- inline QBasicTimer() : id(0) {}
+ // Just here to preserve BC, we can't remove them yet
+ QT_DEPRECATED_X("copy-construction is unsupported; use move-construction instead")
+ QBasicTimer(const QBasicTimer &);
+ QT_DEPRECATED_X("copy-assignment is unsupported; use move-assignment instead")
+ QBasicTimer &operator=(const QBasicTimer &);
+#endif
+
+public:
+ constexpr QBasicTimer() noexcept : id{0} {}
inline ~QBasicTimer() { if (id) stop(); }
- inline bool isActive() const { return id != 0; }
- inline int timerId() const { return id; }
+ QBasicTimer(QBasicTimer &&other) noexcept
+ : id{qExchange(other.id, 0)}
+ {}
+
+ QBasicTimer& operator=(QBasicTimer &&other) noexcept
+ {
+ QBasicTimer{std::move(other)}.swap(*this);
+ return *this;
+ }
+
+ void swap(QBasicTimer &other) noexcept { qSwap(id, other.id); }
+
+ bool isActive() const noexcept { return id != 0; }
+ int timerId() const noexcept { return id; }
void start(int msec, QObject *obj);
void start(int msec, Qt::TimerType timerType, QObject *obj);
@@ -64,6 +87,8 @@ public:
};
Q_DECLARE_TYPEINFO(QBasicTimer, Q_MOVABLE_TYPE);
+inline void swap(QBasicTimer &lhs, QBasicTimer &rhs) noexcept { lhs.swap(rhs); }
+
QT_END_NAMESPACE
#endif // QBASICTIMER_H
diff --git a/src/corelib/kernel/qcore_foundation.mm b/src/corelib/kernel/qcore_foundation.mm
index 56eabc4b8c..623d462749 100644
--- a/src/corelib/kernel/qcore_foundation.mm
+++ b/src/corelib/kernel/qcore_foundation.mm
@@ -501,7 +501,7 @@ NSTimeZone *QTimeZone::toNSTimeZone() const
\sa QRectF::fromCGRect()
*/
-CGRect QRect::toCGRect() const Q_DECL_NOTHROW
+CGRect QRect::toCGRect() const noexcept
{
return CGRectMake(x(), y(), width(), height());
}
@@ -513,7 +513,7 @@ CGRect QRect::toCGRect() const Q_DECL_NOTHROW
\sa fromCGRect()
*/
-CGRect QRectF::toCGRect() const Q_DECL_NOTHROW
+CGRect QRectF::toCGRect() const noexcept
{
return CGRectMake(x(), y(), width(), height());
}
@@ -525,7 +525,7 @@ CGRect QRectF::toCGRect() const Q_DECL_NOTHROW
\sa toCGRect()
*/
-QRectF QRectF::fromCGRect(CGRect rect) Q_DECL_NOTHROW
+QRectF QRectF::fromCGRect(CGRect rect) noexcept
{
return QRectF(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
}
@@ -539,7 +539,7 @@ QRectF QRectF::fromCGRect(CGRect rect) Q_DECL_NOTHROW
\sa QPointF::fromCGPoint()
*/
-CGPoint QPoint::toCGPoint() const Q_DECL_NOTHROW
+CGPoint QPoint::toCGPoint() const noexcept
{
return CGPointMake(x(), y());
}
@@ -551,7 +551,7 @@ CGPoint QPoint::toCGPoint() const Q_DECL_NOTHROW
\sa fromCGPoint()
*/
-CGPoint QPointF::toCGPoint() const Q_DECL_NOTHROW
+CGPoint QPointF::toCGPoint() const noexcept
{
return CGPointMake(x(), y());
}
@@ -563,7 +563,7 @@ CGPoint QPointF::toCGPoint() const Q_DECL_NOTHROW
\sa toCGPoint()
*/
-QPointF QPointF::fromCGPoint(CGPoint point) Q_DECL_NOTHROW
+QPointF QPointF::fromCGPoint(CGPoint point) noexcept
{
return QPointF(point.x, point.y);
}
@@ -577,7 +577,7 @@ QPointF QPointF::fromCGPoint(CGPoint point) Q_DECL_NOTHROW
\sa QSizeF::fromCGSize()
*/
-CGSize QSize::toCGSize() const Q_DECL_NOTHROW
+CGSize QSize::toCGSize() const noexcept
{
return CGSizeMake(width(), height());
}
@@ -589,7 +589,7 @@ CGSize QSize::toCGSize() const Q_DECL_NOTHROW
\sa fromCGSize()
*/
-CGSize QSizeF::toCGSize() const Q_DECL_NOTHROW
+CGSize QSizeF::toCGSize() const noexcept
{
return CGSizeMake(width(), height());
}
@@ -601,7 +601,7 @@ CGSize QSizeF::toCGSize() const Q_DECL_NOTHROW
\sa toCGSize()
*/
-QSizeF QSizeF::fromCGSize(CGSize size) Q_DECL_NOTHROW
+QSizeF QSizeF::fromCGSize(CGSize size) noexcept
{
return QSizeF(size.width, size.height);
}
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 9139b372a8..15b69acbd4 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -371,7 +371,7 @@ bool operator<(const KeyPair &entry, const Qt::Key &key)
struct qtKey2CocoaKeySortLessThan
{
typedef bool result_type;
- Q_DECL_CONSTEXPR result_type operator()(const KeyPair &entry1, const KeyPair &entry2) const Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR result_type operator()(const KeyPair &entry1, const KeyPair &entry2) const noexcept
{
return entry1.qtKey < entry2.qtKey;
}
@@ -501,7 +501,7 @@ void qt_apple_check_os_version()
if (!applicationName)
applicationName = NSProcessInfo.processInfo.processName;
- fprintf(stderr, "Sorry, \"%s\" can not be run on this version of %s. "
+ fprintf(stderr, "Sorry, \"%s\" cannot be run on this version of %s. "
"Qt requires %s %ld.%ld.%ld or later, you have %s %ld.%ld.%ld.\n",
applicationName.UTF8String, os,
os, long(required.majorVersion), long(required.minorVersion), long(required.patchVersion),
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index 8f4c96bbd6..0e1a5fe345 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -91,7 +91,7 @@ public:
QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); }
~QAppleRefCounted() { if (value) ReleaseFunction(value); }
operator T() const { return value; }
- void swap(QAppleRefCounted &other) Q_DECL_NOEXCEPT_EXPR(noexcept(qSwap(value, other.value)))
+ void swap(QAppleRefCounted &other) noexcept(noexcept(qSwap(value, other.value)))
{ qSwap(value, other.value); }
QAppleRefCounted &operator=(const QAppleRefCounted &other)
{ QAppleRefCounted copy(other); swap(copy); return *this; }
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 5a2a29a327..b56c2b9732 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -164,15 +164,15 @@ inline void qt_ignore_sigpipe()
{
// Set to ignore SIGPIPE once only.
static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
- if (!atom.load()) {
+ if (!atom.loadRelaxed()) {
// More than one thread could turn off SIGPIPE at the same time
// But that's acceptable because they all would be doing the same
// action
struct sigaction noaction;
memset(&noaction, 0, sizeof(noaction));
noaction.sa_handler = SIG_IGN;
- ::sigaction(SIGPIPE, &noaction, 0);
- atom.store(1);
+ ::sigaction(SIGPIPE, &noaction, nullptr);
+ atom.storeRelaxed(1);
}
}
@@ -347,7 +347,7 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
#endif
// in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
-timespec qt_gettime() Q_DECL_NOTHROW;
+timespec qt_gettime() noexcept;
void qt_nanosleep(timespec amount);
QByteArray qt_readlink(const char *path);
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index db6546028a..5d300a0488 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -120,6 +120,7 @@
#ifdef Q_OS_WASM
#include <emscripten.h>
+#include <emscripten/val.h>
#endif
#ifdef QT_BOOTSTRAPPED
@@ -216,16 +217,23 @@ QString QCoreApplicationPrivate::appVersion() const
}
#endif
-QString *QCoreApplicationPrivate::cachedApplicationFilePath = 0;
+QString *QCoreApplicationPrivate::cachedApplicationFilePath = nullptr;
bool QCoreApplicationPrivate::checkInstance(const char *function)
{
- bool b = (QCoreApplication::self != 0);
+ bool b = (QCoreApplication::self != nullptr);
if (!b)
qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
return b;
}
+void QCoreApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
+{
+ options->append(QCommandLineOption(QStringLiteral("qmljsdebugger"),
+ QStringLiteral("Activates the QML/JS debugger with a specified port. The value must be of format port:1234[,block]. \"block\" makes the application wait for a connection."),
+ QStringLiteral("value")));
+}
+
void QCoreApplicationPrivate::processCommandLineArguments()
{
int j = argc ? 1 : 0;
@@ -250,22 +258,13 @@ void QCoreApplicationPrivate::processCommandLineArguments()
}
if (j < argc) {
- argv[j] = 0;
+ argv[j] = nullptr;
argc = j;
}
}
// Support for introspection
-#ifndef QT_NO_QOBJECT
-QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set = { 0, 0, 0, 0 };
-
-void qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set)
-{
- qt_signal_spy_callback_set = callback_set;
-}
-#endif
-
extern "C" void Q_CORE_EXPORT qt_startup_hook()
{
}
@@ -369,17 +368,17 @@ Q_CORE_EXPORT uint qGlobalPostedEventsCount()
return currentThreadData->postEventList.size() - currentThreadData->postEventList.startOffset;
}
-QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = 0;
+QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = nullptr;
#endif // QT_NO_QOBJECT
-QCoreApplication *QCoreApplication::self = 0;
+QCoreApplication *QCoreApplication::self = nullptr;
uint QCoreApplicationPrivate::attribs =
(1 << Qt::AA_SynthesizeMouseForUnhandledTouchEvents) |
(1 << Qt::AA_SynthesizeMouseForUnhandledTabletEvents);
struct QCoreApplicationData {
- QCoreApplicationData() Q_DECL_NOTHROW {
+ QCoreApplicationData() noexcept {
applicationNameSet = false;
applicationVersionSet = false;
}
@@ -457,12 +456,12 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
, aboutToQuitEmitted(false)
, threadData_clean(false)
#else
- , q_ptr(0)
+ , q_ptr(nullptr)
#endif
{
app_compile_version = flags & 0xffffff;
static const char *const empty = "";
- if (argc == 0 || argv == 0) {
+ if (argc == 0 || argv == nullptr) {
argc = 0;
argv = const_cast<char **>(&empty);
}
@@ -553,8 +552,8 @@ void QCoreApplicationPrivate::eventDispatcherReady()
QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(0);
QThread *QCoreApplicationPrivate::mainThread()
{
- Q_ASSERT(theMainThread.load() != 0);
- return theMainThread.load();
+ Q_ASSERT(theMainThread.loadRelaxed() != 0);
+ return theMainThread.loadRelaxed();
}
bool QCoreApplicationPrivate::threadRequiresCoreApplication()
@@ -700,7 +699,7 @@ void QCoreApplicationPrivate::initLocale()
Returns a pointer to the application's QCoreApplication (or
QGuiApplication/QApplication) instance.
- If no instance has been allocated, \c null is returned.
+ If no instance has been allocated, \nullptr is returned.
*/
/*!
@@ -801,6 +800,10 @@ void QCoreApplicationPrivate::init()
Module.print(err);
});
);
+
+#if QT_CONFIG(thread)
+ QThreadPrivate::idealThreadCount = emscripten::val::global("navigator")["hardwareConcurrency"].as<int>();
+#endif
#endif
// Store app name/version (so they're still available after QCoreApplication is destroyed)
@@ -851,7 +854,7 @@ void QCoreApplicationPrivate::init()
#ifndef QT_NO_QOBJECT
// use the event dispatcher created by the app programmer (if any)
Q_ASSERT(!eventDispatcher);
- eventDispatcher = threadData->eventDispatcher.load();
+ eventDispatcher = threadData->eventDispatcher.loadRelaxed();
// otherwise we create one
if (!eventDispatcher)
@@ -867,11 +870,6 @@ void QCoreApplicationPrivate::init()
eventDispatcherReady();
#endif
-#ifdef QT_EVAL
- extern void qt_core_eval_init(QCoreApplicationPrivate::Type);
- qt_core_eval_init(application_type);
-#endif
-
processCommandLineArguments();
qt_call_pre_routines();
@@ -893,7 +891,7 @@ QCoreApplication::~QCoreApplication()
{
qt_call_post_routines();
- self = 0;
+ self = nullptr;
#ifndef QT_NO_QOBJECT
QCoreApplicationPrivate::is_app_closing = true;
QCoreApplicationPrivate::is_app_running = false;
@@ -901,7 +899,7 @@ QCoreApplication::~QCoreApplication()
#if QT_CONFIG(thread)
// Synchronize and stop the global thread pool threads.
- QThreadPool *globalThreadPool = 0;
+ QThreadPool *globalThreadPool = nullptr;
QT_TRY {
globalThreadPool = QThreadPool::globalInstance();
} QT_CATCH (...) {
@@ -912,10 +910,10 @@ QCoreApplication::~QCoreApplication()
#endif
#ifndef QT_NO_QOBJECT
- d_func()->threadData->eventDispatcher = 0;
+ d_func()->threadData->eventDispatcher = nullptr;
if (QCoreApplicationPrivate::eventDispatcher)
QCoreApplicationPrivate::eventDispatcher->closingDown();
- QCoreApplicationPrivate::eventDispatcher = 0;
+ QCoreApplicationPrivate::eventDispatcher = nullptr;
#endif
#if QT_CONFIG(library)
@@ -1043,6 +1041,7 @@ void QCoreApplication::setQuitLockEnabled(bool enabled)
quitLockRefEnabled = enabled;
}
+#if QT_DEPRECATED_SINCE(5, 6)
/*!
\internal
\deprecated
@@ -1054,6 +1053,7 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
{
return notifyInternal2(receiver, event);
}
+#endif
/*!
\internal
@@ -1291,7 +1291,11 @@ bool QCoreApplication::closingDown()
\l{QCoreApplication::sendPostedEvents()}{sendPostedEvents()} from
within that local loop.
- Calling this function processes events only for the calling thread.
+ Calling this function processes events only for the calling thread,
+ and returns after all available events have been processed. Available
+ events are events queued before the function call. This means that
+ events that are posted while the function runs will be queued until
+ a later round of event processing.
\threadsafe
@@ -1302,13 +1306,13 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
QThreadData *data = QThreadData::current();
if (!data->hasEventDispatcher())
return;
- data->eventDispatcher.load()->processEvents(flags);
+ data->eventDispatcher.loadRelaxed()->processEvents(flags);
}
/*!
\overload processEvents()
- Processes pending events for the calling thread for \a maxtime
+ Processes pending events for the calling thread for \a ms
milliseconds or until there are no more events to process,
whichever is shorter.
@@ -1317,11 +1321,14 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
Calling this function processes events only for the calling thread.
+ \note Unlike the \l{QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)}{processEvents()}
+ overload, this function also processes events that are posted while the function runs.
+
\threadsafe
\sa exec(), QTimer, QEventLoop::processEvents()
*/
-void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)
+void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int ms)
{
// ### Qt 6: consider splitting this method into a public and a private
// one, so that a user-invoked processEvents can be detected
@@ -1331,8 +1338,8 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int m
return;
QElapsedTimer start;
start.start();
- while (data->eventDispatcher.load()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
- if (start.elapsed() > maxtime)
+ while (data->eventDispatcher.loadRelaxed()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
+ if (start.elapsed() > ms)
break;
}
}
@@ -1655,14 +1662,15 @@ bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEven
/*!
Immediately dispatches all events which have been previously queued
- with QCoreApplication::postEvent() and which are for the object \a receiver
- and have the event type \a event_type.
+ with QCoreApplication::postEvent() and which are for the object \a
+ receiver and have the event type \a event_type.
Events from the window system are \e not dispatched by this
function, but by processEvents().
- If \a receiver is null, the events of \a event_type are sent for all
- objects. If \a event_type is 0, all the events are sent for \a receiver.
+ If \a receiver is \nullptr, the events of \a event_type are sent for
+ all objects. If \a event_type is 0, all the events are sent for
+ \a receiver.
\note This method must be called from the thread in which its QObject
parameter, \a receiver, lives.
@@ -1734,7 +1742,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
--data->postEventList.recursion;
if (!data->postEventList.recursion && !data->canWait && data->hasEventDispatcher())
- data->eventDispatcher.load()->wakeUp();
+ data->eventDispatcher.loadRelaxed()->wakeUp();
// clear the global list, i.e. remove everything that was
// delivered.
@@ -1843,10 +1851,10 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
call it, be aware that killing events may cause \a receiver to
break one or more invariants.
- If \a receiver is null, the events of \a eventType are removed for
- all objects. If \a eventType is 0, all the events are removed for
- \a receiver. You should never call this function with \a eventType
- of 0.
+ If \a receiver is \nullptr, the events of \a eventType are removed
+ for all objects. If \a eventType is 0, all the events are removed
+ for \a receiver. You should never call this function with \a
+ eventType of 0.
\threadsafe
*/
@@ -1985,7 +1993,7 @@ void QCoreApplicationPrivate::deref()
void QCoreApplicationPrivate::maybeQuit()
{
- if (quitLockRef.load() == 0 && in_exec && quitLockRefEnabled && shouldQuit())
+ if (quitLockRef.loadRelaxed() == 0 && in_exec && quitLockRefEnabled && shouldQuit())
QCoreApplication::postEvent(QCoreApplication::instance(), new QEvent(QEvent::Quit));
}
@@ -2159,7 +2167,7 @@ static void replacePercentN(QString *result, int n)
\a disambiguation is an identifying string, for when the same \a
sourceText is used in different roles within the same context. By
- default, it is null.
+ default, it is \nullptr.
See the \l QTranslator and \l QObject::tr() documentation for
more information about contexts, disambiguations and comments.
@@ -2954,7 +2962,7 @@ bool QCoreApplication::hasPendingEvents()
QAbstractEventDispatcher *QCoreApplication::eventDispatcher()
{
if (QCoreApplicationPrivate::theMainThread)
- return QCoreApplicationPrivate::theMainThread.load()->eventDispatcher();
+ return QCoreApplicationPrivate::theMainThread.loadRelaxed()->eventDispatcher();
return 0;
}
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index 3581970765..b7df004736 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -227,6 +227,7 @@ private:
#endif
friend Q_CORE_EXPORT QString qAppName();
friend class QClassFactory;
+ friend class QCommandLineParserPrivate;
};
#ifdef QT_NO_DEPRECATED
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index b3479414ab..0b9029b5fe 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -52,6 +52,7 @@
//
#include "QtCore/qcoreapplication.h"
+#include "QtCore/qcommandlineoption.h"
#include "QtCore/qtranslator.h"
#if QT_CONFIG(settings)
#include "QtCore/qsettings.h"
@@ -84,6 +85,11 @@ public:
};
QCoreApplicationPrivate(int &aargc, char **aargv, uint flags);
+
+ // If not inheriting from QObjectPrivate: force this class to be polymorphic
+#ifdef QT_NO_QOBJECT
+ virtual
+#endif
~QCoreApplicationPrivate();
void init();
@@ -99,6 +105,8 @@ public:
static bool checkInstance(const char *method);
+ virtual void addQtOptions(QList<QCommandLineOption> *options);
+
#ifndef QT_NO_QOBJECT
bool sendThroughApplicationEventFilters(QObject *, QEvent *);
static bool sendThroughObjectEventFilters(QObject *, QEvent *);
@@ -149,7 +157,7 @@ public:
QString cachedApplicationDirPath;
static QString *cachedApplicationFilePath;
static void setApplicationFilePath(const QString &path);
- static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = 0; }
+ static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = nullptr; }
#ifndef QT_NO_QOBJECT
void execCleanup();
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 4f4a29b41b..822b68cf62 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -64,8 +64,6 @@ using namespace Microsoft::WRL::Wrappers;
QT_BEGIN_NAMESPACE
-int appCmdShow = 0;
-
Q_CORE_EXPORT QString qAppFileName() // get application file name
{
/*
@@ -175,16 +173,12 @@ Q_CORE_EXPORT HINSTANCE qWinAppPrevInst() // get Windows prev app
Q_CORE_EXPORT int qWinAppCmdShow() // get main window show command
{
-#if defined(Q_OS_WINCE)
- return appCmdShow;
-#else
STARTUPINFO startupInfo;
GetStartupInfo(&startupInfo);
return (startupInfo.dwFlags & STARTF_USESHOWWINDOW)
? startupInfo.wShowWindow
: SW_SHOWDEFAULT;
-#endif
}
#endif
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index cacbb1e495..4cfc749386 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -421,10 +421,10 @@ struct QBasicAtomicBitField {
QBasicAtomicInteger<uint> next;
QBasicAtomicInteger<uint> data[NumInts];
- bool allocateSpecific(int which) Q_DECL_NOTHROW
+ bool allocateSpecific(int which) noexcept
{
QBasicAtomicInteger<uint> &entry = data[which / BitsPerInt];
- const uint old = entry.load();
+ const uint old = entry.loadRelaxed();
const uint bit = 1U << (which % BitsPerInt);
return !(old & bit) // wasn't taken
&& entry.testAndSetRelaxed(old, old | bit); // still wasn't taken
@@ -437,7 +437,7 @@ struct QBasicAtomicBitField {
// loop.
}
- int allocateNext() Q_DECL_NOTHROW
+ int allocateNext() noexcept
{
// Unroll loop to iterate over ints, then bits? Would save
// potentially a lot of cmpxchgs, because we can scan the
@@ -445,10 +445,10 @@ struct QBasicAtomicBitField {
// Then again, this should never execute many iterations, so
// leave like this for now:
- for (uint i = next.load(); i < NumBits; ++i) {
+ for (uint i = next.loadRelaxed(); i < NumBits; ++i) {
if (allocateSpecific(i)) {
// remember next (possibly) free id:
- const uint oldNext = next.load();
+ const uint oldNext = next.loadRelaxed();
next.testAndSetRelaxed(oldNext, qMax(i + 1, oldNext));
return i;
}
@@ -463,7 +463,7 @@ typedef QBasicAtomicBitField<QEvent::MaxUser - QEvent::User + 1> UserEventTypeRe
static UserEventTypeRegistry userEventTypeRegistry;
-static inline int registerEventTypeZeroBased(int id) Q_DECL_NOTHROW
+static inline int registerEventTypeZeroBased(int id) noexcept
{
// if the type hint hasn't been registered yet, take it:
if (id < UserEventTypeRegistry::NumBits && id >= 0 && userEventTypeRegistry.allocateSpecific(id))
@@ -486,7 +486,7 @@ static inline int registerEventTypeZeroBased(int id) Q_DECL_NOTHROW
Returns -1 if all available values are already taken or the
program is shutting down.
*/
-int QEvent::registerEventType(int hint) Q_DECL_NOTHROW
+int QEvent::registerEventType(int hint) noexcept
{
const int result = registerEventTypeZeroBased(QEvent::MaxUser - hint);
return result < 0 ? -1 : QEvent::MaxUser - result ;
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index ac974ba411..05af1a6132 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -307,7 +307,7 @@ public:
inline void accept() { m_accept = true; }
inline void ignore() { m_accept = false; }
- static int registerEventType(int hint = -1) Q_DECL_NOTHROW;
+ static int registerEventType(int hint = -1) noexcept;
protected:
QEventPrivate *d;
diff --git a/src/corelib/kernel/qcoreglobaldata.cpp b/src/corelib/kernel/qcoreglobaldata.cpp
index 104be1b87b..7ff222f170 100644
--- a/src/corelib/kernel/qcoreglobaldata.cpp
+++ b/src/corelib/kernel/qcoreglobaldata.cpp
@@ -48,7 +48,7 @@ Q_GLOBAL_STATIC(QCoreGlobalData, globalInstance)
QCoreGlobalData::QCoreGlobalData()
#if QT_CONFIG(textcodec)
- : codecForLocale(0)
+ : codecForLocale(nullptr)
#endif
{
}
@@ -56,7 +56,7 @@ QCoreGlobalData::QCoreGlobalData()
QCoreGlobalData::~QCoreGlobalData()
{
#if QT_CONFIG(textcodec)
- codecForLocale = 0;
+ codecForLocale = nullptr;
QList<QTextCodec *> tmp = allCodecs;
allCodecs.clear();
codecCache.clear();
diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp
index 49874b94b4..06b56bb09b 100644
--- a/src/corelib/kernel/qdeadlinetimer.cpp
+++ b/src/corelib/kernel/qdeadlinetimer.cpp
@@ -464,7 +464,7 @@ inline bool TimeReference::toNanoseconds(qint64 *result) const
\sa hasExpired(), isForever(), remainingTime(), setRemainingTime()
*/
-QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) Q_DECL_NOTHROW
+QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) noexcept
: t2(0)
{
setRemainingTime(msecs, type);
@@ -536,7 +536,7 @@ QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) Q_DECL_NOTHROW
\sa setPreciseRemainingTime(), hasExpired(), isForever(), remainingTime()
*/
-void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) Q_DECL_NOTHROW
+void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) noexcept
{
if (msecs == -1) {
*this = QDeadlineTimer(Forever, timerType);
@@ -562,7 +562,7 @@ void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) Q_D
\sa setRemainingTime(), hasExpired(), isForever(), remainingTime()
*/
-void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::TimerType timerType) Q_DECL_NOTHROW
+void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::TimerType timerType) noexcept
{
if (secs == -1) {
*this = QDeadlineTimer(Forever, timerType);
@@ -619,7 +619,7 @@ void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::Time
\sa isForever(), remainingTime()
*/
-bool QDeadlineTimer::hasExpired() const Q_DECL_NOTHROW
+bool QDeadlineTimer::hasExpired() const noexcept
{
if (isForever())
return false;
@@ -666,7 +666,7 @@ void QDeadlineTimer::setTimerType(Qt::TimerType timerType)
\sa remainingTimeNSecs(), isForever(), hasExpired()
*/
-qint64 QDeadlineTimer::remainingTime() const Q_DECL_NOTHROW
+qint64 QDeadlineTimer::remainingTime() const noexcept
{
if (isForever())
return -1;
@@ -694,7 +694,7 @@ qint64 QDeadlineTimer::remainingTime() const Q_DECL_NOTHROW
\sa remainingTime(), isForever(), hasExpired()
*/
-qint64 QDeadlineTimer::remainingTimeNSecs() const Q_DECL_NOTHROW
+qint64 QDeadlineTimer::remainingTimeNSecs() const noexcept
{
if (isForever())
return -1;
@@ -708,7 +708,7 @@ qint64 QDeadlineTimer::remainingTimeNSecs() const Q_DECL_NOTHROW
not deal with Forever. In case of underflow the result is saturated to
the minimum possible value, on overflow - the maximum possible value.
*/
-qint64 QDeadlineTimer::rawRemainingTimeNSecs() const Q_DECL_NOTHROW
+qint64 QDeadlineTimer::rawRemainingTimeNSecs() const noexcept
{
QDeadlineTimer now = current(timerType());
TimeReference ref(t1, t2);
@@ -744,7 +744,7 @@ qint64 QDeadlineTimer::rawRemainingTimeNSecs() const Q_DECL_NOTHROW
\sa remainingTime(), deadlineNSecs(), setDeadline()
*/
-qint64 QDeadlineTimer::deadline() const Q_DECL_NOTHROW
+qint64 QDeadlineTimer::deadline() const noexcept
{
if (isForever())
return TimeReference::Max;
@@ -777,7 +777,7 @@ qint64 QDeadlineTimer::deadline() const Q_DECL_NOTHROW
\sa remainingTime(), deadlineNSecs()
*/
-qint64 QDeadlineTimer::deadlineNSecs() const Q_DECL_NOTHROW
+qint64 QDeadlineTimer::deadlineNSecs() const noexcept
{
if (isForever())
return TimeReference::Max;
@@ -802,7 +802,7 @@ qint64 QDeadlineTimer::deadlineNSecs() const Q_DECL_NOTHROW
\sa setPreciseDeadline(), deadline(), deadlineNSecs(), setRemainingTime()
*/
-void QDeadlineTimer::setDeadline(qint64 msecs, Qt::TimerType timerType) Q_DECL_NOTHROW
+void QDeadlineTimer::setDeadline(qint64 msecs, Qt::TimerType timerType) noexcept
{
if (msecs == TimeReference::Max) {
*this = QDeadlineTimer(Forever, timerType);
@@ -829,7 +829,7 @@ void QDeadlineTimer::setDeadline(qint64 msecs, Qt::TimerType timerType) Q_DECL_N
\sa setDeadline(), deadline(), deadlineNSecs(), setRemainingTime()
*/
-void QDeadlineTimer::setPreciseDeadline(qint64 secs, qint64 nsecs, Qt::TimerType timerType) Q_DECL_NOTHROW
+void QDeadlineTimer::setPreciseDeadline(qint64 secs, qint64 nsecs, Qt::TimerType timerType) noexcept
{
type = timerType;
@@ -849,7 +849,7 @@ void QDeadlineTimer::setPreciseDeadline(qint64 secs, qint64 nsecs, Qt::TimerType
\note if \a dt was created as expired, its deadline is indeterminate and
adding an amount of time may or may not cause it to become unexpired.
*/
-QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_NOTHROW
+QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcept
{
if (dt.isForever())
return dt;
diff --git a/src/corelib/kernel/qdeadlinetimer.h b/src/corelib/kernel/qdeadlinetimer.h
index f9ad4063e5..9dd92481d2 100644
--- a/src/corelib/kernel/qdeadlinetimer.h
+++ b/src/corelib/kernel/qdeadlinetimer.h
@@ -63,49 +63,49 @@ class Q_CORE_EXPORT QDeadlineTimer
public:
enum ForeverConstant { Forever };
- Q_DECL_CONSTEXPR QDeadlineTimer(Qt::TimerType type_ = Qt::CoarseTimer) Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR QDeadlineTimer(Qt::TimerType type_ = Qt::CoarseTimer) noexcept
: t1(0), t2(0), type(type_) {}
- Q_DECL_CONSTEXPR QDeadlineTimer(ForeverConstant, Qt::TimerType type_ = Qt::CoarseTimer) Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR QDeadlineTimer(ForeverConstant, Qt::TimerType type_ = Qt::CoarseTimer) noexcept
: t1(std::numeric_limits<qint64>::max()), t2(0), type(type_) {}
- explicit QDeadlineTimer(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW;
+ explicit QDeadlineTimer(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) noexcept;
- void swap(QDeadlineTimer &other) Q_DECL_NOTHROW
+ void swap(QDeadlineTimer &other) noexcept
{ qSwap(t1, other.t1); qSwap(t2, other.t2); qSwap(type, other.type); }
- Q_DECL_CONSTEXPR bool isForever() const Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR bool isForever() const noexcept
{ return t1 == (std::numeric_limits<qint64>::max)(); }
- bool hasExpired() const Q_DECL_NOTHROW;
+ bool hasExpired() const noexcept;
- Qt::TimerType timerType() const Q_DECL_NOTHROW
+ Qt::TimerType timerType() const noexcept
{ return Qt::TimerType(type & 0xff); }
void setTimerType(Qt::TimerType type);
- qint64 remainingTime() const Q_DECL_NOTHROW;
- qint64 remainingTimeNSecs() const Q_DECL_NOTHROW;
- void setRemainingTime(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW;
+ qint64 remainingTime() const noexcept;
+ qint64 remainingTimeNSecs() const noexcept;
+ void setRemainingTime(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) noexcept;
void setPreciseRemainingTime(qint64 secs, qint64 nsecs = 0,
- Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW;
+ Qt::TimerType type = Qt::CoarseTimer) noexcept;
- qint64 deadline() const Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION;
- qint64 deadlineNSecs() const Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION;
- void setDeadline(qint64 msecs, Qt::TimerType timerType = Qt::CoarseTimer) Q_DECL_NOTHROW;
+ qint64 deadline() const noexcept Q_DECL_PURE_FUNCTION;
+ qint64 deadlineNSecs() const noexcept Q_DECL_PURE_FUNCTION;
+ void setDeadline(qint64 msecs, Qt::TimerType timerType = Qt::CoarseTimer) noexcept;
void setPreciseDeadline(qint64 secs, qint64 nsecs = 0,
- Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW;
+ Qt::TimerType type = Qt::CoarseTimer) noexcept;
- static QDeadlineTimer addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION;
- static QDeadlineTimer current(Qt::TimerType timerType = Qt::CoarseTimer) Q_DECL_NOTHROW;
+ static QDeadlineTimer addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcept Q_DECL_PURE_FUNCTION;
+ static QDeadlineTimer current(Qt::TimerType timerType = Qt::CoarseTimer) noexcept;
- friend bool operator==(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW
+ friend bool operator==(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
{ return d1.t1 == d2.t1 && d1.t2 == d2.t2; }
- friend bool operator!=(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW
+ friend bool operator!=(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
{ return !(d1 == d2); }
- friend bool operator<(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW
+ friend bool operator<(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
{ return d1.t1 < d2.t1 || (d1.t1 == d2.t1 && d1.t2 < d2.t2); }
- friend bool operator<=(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW
+ friend bool operator<=(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
{ return d1 == d2 || d1 < d2; }
- friend bool operator>(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW
+ friend bool operator>(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
{ return d2 < d1; }
- friend bool operator>=(QDeadlineTimer d1, QDeadlineTimer d2) Q_DECL_NOTHROW
+ friend bool operator>=(QDeadlineTimer d1, QDeadlineTimer d2) noexcept
{ return !(d1 < d2); }
friend Q_CORE_EXPORT QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs);
@@ -159,7 +159,7 @@ public:
setPreciseRemainingTime(0, std::chrono::nanoseconds(remaining).count(), type_);
}
- std::chrono::nanoseconds remainingTimeAsDuration() const Q_DECL_NOTHROW
+ std::chrono::nanoseconds remainingTimeAsDuration() const noexcept
{
if (isForever())
return std::chrono::nanoseconds::max();
@@ -185,7 +185,7 @@ private:
unsigned t2;
unsigned type;
- qint64 rawRemainingTimeNSecs() const Q_DECL_NOTHROW;
+ qint64 rawRemainingTimeNSecs() const noexcept;
public:
// This is not a public function, it's here only for Qt's internal convenience...
diff --git a/src/corelib/kernel/qelapsedtimer.cpp b/src/corelib/kernel/qelapsedtimer.cpp
index e578b5b8b3..57825583dd 100644
--- a/src/corelib/kernel/qelapsedtimer.cpp
+++ b/src/corelib/kernel/qelapsedtimer.cpp
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
\snippet qelapsedtimer/main.cpp 0
In this example, the timer is started by a call to start() and the
- elapsed timer is calculated by the elapsed() function.
+ elapsed time is calculated by the elapsed() function.
The time elapsed can also be used to recalculate the time available for
another operation, after the first one is complete. This is useful when
@@ -236,7 +236,7 @@ static const qint64 invalidData = Q_INT64_C(0x8000000000000000);
\sa isValid(), start(), restart()
*/
-void QElapsedTimer::invalidate() Q_DECL_NOTHROW
+void QElapsedTimer::invalidate() noexcept
{
t1 = t2 = invalidData;
}
@@ -247,7 +247,7 @@ void QElapsedTimer::invalidate() Q_DECL_NOTHROW
\sa invalidate(), start(), restart()
*/
-bool QElapsedTimer::isValid() const Q_DECL_NOTHROW
+bool QElapsedTimer::isValid() const noexcept
{
return t1 != invalidData && t2 != invalidData;
}
@@ -260,7 +260,7 @@ bool QElapsedTimer::isValid() const Q_DECL_NOTHROW
\sa elapsed(), QDeadlineTimer
*/
-bool QElapsedTimer::hasExpired(qint64 timeout) const Q_DECL_NOTHROW
+bool QElapsedTimer::hasExpired(qint64 timeout) const noexcept
{
// if timeout is -1, quint64(timeout) is LLINT_MAX, so this will be
// considered as never expired
diff --git a/src/corelib/kernel/qelapsedtimer.h b/src/corelib/kernel/qelapsedtimer.h
index 7954b41bf4..873847f6b6 100644
--- a/src/corelib/kernel/qelapsedtimer.h
+++ b/src/corelib/kernel/qelapsedtimer.h
@@ -62,28 +62,28 @@ public:
{
}
- static ClockType clockType() Q_DECL_NOTHROW;
- static bool isMonotonic() Q_DECL_NOTHROW;
+ static ClockType clockType() noexcept;
+ static bool isMonotonic() noexcept;
- void start() Q_DECL_NOTHROW;
- qint64 restart() Q_DECL_NOTHROW;
- void invalidate() Q_DECL_NOTHROW;
- bool isValid() const Q_DECL_NOTHROW;
+ void start() noexcept;
+ qint64 restart() noexcept;
+ void invalidate() noexcept;
+ bool isValid() const noexcept;
- qint64 nsecsElapsed() const Q_DECL_NOTHROW;
- qint64 elapsed() const Q_DECL_NOTHROW;
- bool hasExpired(qint64 timeout) const Q_DECL_NOTHROW;
+ qint64 nsecsElapsed() const noexcept;
+ qint64 elapsed() const noexcept;
+ bool hasExpired(qint64 timeout) const noexcept;
- qint64 msecsSinceReference() const Q_DECL_NOTHROW;
- qint64 msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW;
- qint64 secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW;
+ qint64 msecsSinceReference() const noexcept;
+ qint64 msecsTo(const QElapsedTimer &other) const noexcept;
+ qint64 secsTo(const QElapsedTimer &other) const noexcept;
- bool operator==(const QElapsedTimer &other) const Q_DECL_NOTHROW
+ bool operator==(const QElapsedTimer &other) const noexcept
{ return t1 == other.t1 && t2 == other.t2; }
- bool operator!=(const QElapsedTimer &other) const Q_DECL_NOTHROW
+ bool operator!=(const QElapsedTimer &other) const noexcept
{ return !(*this == other); }
- friend bool Q_CORE_EXPORT operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW;
+ friend bool Q_CORE_EXPORT operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept;
private:
qint64 t1;
diff --git a/src/corelib/kernel/qelapsedtimer_generic.cpp b/src/corelib/kernel/qelapsedtimer_generic.cpp
index fdeb385188..fe959e3c94 100644
--- a/src/corelib/kernel/qelapsedtimer_generic.cpp
+++ b/src/corelib/kernel/qelapsedtimer_generic.cpp
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
\sa isMonotonic()
*/
-QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
+QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
{
return SystemTime;
}
@@ -60,7 +60,7 @@ QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
\sa clockType(), QElapsedTimer::ClockType
*/
-bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW
+bool QElapsedTimer::isMonotonic() noexcept
{
return false;
}
@@ -75,7 +75,7 @@ bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW
\sa restart(), invalidate(), elapsed()
*/
-void QElapsedTimer::start() Q_DECL_NOTHROW
+void QElapsedTimer::start() noexcept
{
restart();
}
@@ -97,7 +97,7 @@ void QElapsedTimer::start() Q_DECL_NOTHROW
\sa start(), invalidate(), elapsed(), isValid()
*/
-qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
+qint64 QElapsedTimer::restart() noexcept
{
qint64 old = t1;
t1 = QDateTime::currentMSecsSinceEpoch();
@@ -118,7 +118,7 @@ qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
\sa start(), restart(), hasExpired(), invalidate()
*/
-qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::nsecsElapsed() const noexcept
{
return elapsed() * 1000000;
}
@@ -132,7 +132,7 @@ qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW
\sa start(), restart(), hasExpired(), isValid(), invalidate()
*/
-qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::elapsed() const noexcept
{
return QDateTime::currentMSecsSinceEpoch() - t1;
}
@@ -152,7 +152,7 @@ qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW
\sa clockType(), elapsed()
*/
-qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::msecsSinceReference() const noexcept
{
return t1;
}
@@ -167,7 +167,7 @@ qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW
\sa secsTo(), elapsed()
*/
-qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
{
qint64 diff = other.t1 - t1;
return diff;
@@ -183,7 +183,7 @@ qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
\sa msecsTo(), elapsed()
*/
-qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
{
return msecsTo(other) / 1000;
}
@@ -197,12 +197,12 @@ qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
and the other isn't. However, two invalid timers are equal and thus this
function will return false.
*/
-bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept
{
return v1.t1 < v2.t1;
}
-QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW
+QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
{
QDeadlineTimer result;
result.t1 = QDateTime::currentMSecsSinceEpoch() * 1000 * 1000;
diff --git a/src/corelib/kernel/qelapsedtimer_mac.cpp b/src/corelib/kernel/qelapsedtimer_mac.cpp
index 7490693991..5370cf7b3d 100644
--- a/src/corelib/kernel/qelapsedtimer_mac.cpp
+++ b/src/corelib/kernel/qelapsedtimer_mac.cpp
@@ -58,12 +58,12 @@ typedef __int128_t LargeInt;
typedef qint64 LargeInt;
#endif
-QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
+QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
{
return MachAbsoluteTime;
}
-bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW
+bool QElapsedTimer::isMonotonic() noexcept
{
return true;
}
@@ -87,7 +87,7 @@ static qint64 absoluteToMSecs(qint64 cpuTime)
return absoluteToNSecs(cpuTime) / 1000000;
}
-timespec qt_gettime() Q_DECL_NOTHROW
+timespec qt_gettime() noexcept
{
timespec tv;
@@ -107,13 +107,13 @@ void qt_nanosleep(timespec amount)
EINTR_LOOP(r, nanosleep(&amount, &amount));
}
-void QElapsedTimer::start() Q_DECL_NOTHROW
+void QElapsedTimer::start() noexcept
{
t1 = mach_absolute_time();
t2 = 0;
}
-qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
+qint64 QElapsedTimer::restart() noexcept
{
qint64 old = t1;
t1 = mach_absolute_time();
@@ -122,39 +122,39 @@ qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
return absoluteToMSecs(t1 - old);
}
-qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::nsecsElapsed() const noexcept
{
uint64_t cpu_time = mach_absolute_time();
return absoluteToNSecs(cpu_time - t1);
}
-qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::elapsed() const noexcept
{
uint64_t cpu_time = mach_absolute_time();
return absoluteToMSecs(cpu_time - t1);
}
-qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::msecsSinceReference() const noexcept
{
return absoluteToMSecs(t1);
}
-qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
{
return absoluteToMSecs(other.t1 - t1);
}
-qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
{
return msecsTo(other) / 1000;
}
-bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept
{
return v1.t1 < v2.t1;
}
-QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW
+QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
{
Q_STATIC_ASSERT(!QDeadlineTimerNanosecondsInT2);
QDeadlineTimer result;
diff --git a/src/corelib/kernel/qelapsedtimer_unix.cpp b/src/corelib/kernel/qelapsedtimer_unix.cpp
index e166d4e3d2..ccc2eeafa3 100644
--- a/src/corelib/kernel/qelapsedtimer_unix.cpp
+++ b/src/corelib/kernel/qelapsedtimer_unix.cpp
@@ -150,12 +150,12 @@ static int unixCheckClockType()
#endif
}
-bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW
+bool QElapsedTimer::isMonotonic() noexcept
{
return clockType() == MonotonicClock;
}
-QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
+QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
{
return unixCheckClockType() == CLOCK_REALTIME ? SystemTime : MonotonicClock;
}
@@ -169,7 +169,7 @@ static inline void do_gettime(qint64 *sec, qint64 *frac)
}
// used in qcore_unix.cpp and qeventdispatcher_unix.cpp
-struct timespec qt_gettime() Q_DECL_NOTHROW
+struct timespec qt_gettime() noexcept
{
qint64 sec, frac;
do_gettime(&sec, &frac);
@@ -204,17 +204,17 @@ static qint64 elapsedAndRestart(qint64 sec, qint64 frac,
return (sec * Q_INT64_C(1000000000) + frac) / Q_INT64_C(1000000);
}
-void QElapsedTimer::start() Q_DECL_NOTHROW
+void QElapsedTimer::start() noexcept
{
do_gettime(&t1, &t2);
}
-qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
+qint64 QElapsedTimer::restart() noexcept
{
return elapsedAndRestart(t1, t2, &t1, &t2);
}
-qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::nsecsElapsed() const noexcept
{
qint64 sec, frac;
do_gettime(&sec, &frac);
@@ -223,34 +223,34 @@ qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW
return sec * Q_INT64_C(1000000000) + frac;
}
-qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::elapsed() const noexcept
{
return nsecsElapsed() / Q_INT64_C(1000000);
}
-qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::msecsSinceReference() const noexcept
{
return t1 * Q_INT64_C(1000) + t2 / Q_INT64_C(1000000);
}
-qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
{
qint64 secs = other.t1 - t1;
qint64 fraction = other.t2 - t2;
return (secs * Q_INT64_C(1000000000) + fraction) / Q_INT64_C(1000000);
}
-qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
{
return other.t1 - t1;
}
-bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept
{
return v1.t1 < v2.t1 || (v1.t1 == v2.t1 && v1.t2 < v2.t2);
}
-QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW
+QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
{
Q_STATIC_ASSERT(QDeadlineTimerNanosecondsInT2);
QDeadlineTimer result;
diff --git a/src/corelib/kernel/qelapsedtimer_win.cpp b/src/corelib/kernel/qelapsedtimer_win.cpp
index 3beb158b8a..8becb17461 100644
--- a/src/corelib/kernel/qelapsedtimer_win.cpp
+++ b/src/corelib/kernel/qelapsedtimer_win.cpp
@@ -101,25 +101,25 @@ quint64 qt_msectime()
return ticksToNanoseconds(getTickCount()) / 1000000;
}
-QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
+QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
{
resolveCounterFrequency();
return counterFrequency > 0 ? PerformanceCounter : TickCounter;
}
-bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW
+bool QElapsedTimer::isMonotonic() noexcept
{
return true;
}
-void QElapsedTimer::start() Q_DECL_NOTHROW
+void QElapsedTimer::start() noexcept
{
t1 = getTickCount();
t2 = 0;
}
-qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
+qint64 QElapsedTimer::restart() noexcept
{
qint64 oldt1 = t1;
t1 = getTickCount();
@@ -127,40 +127,40 @@ qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
return ticksToNanoseconds(t1 - oldt1) / 1000000;
}
-qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::nsecsElapsed() const noexcept
{
qint64 elapsed = getTickCount() - t1;
return ticksToNanoseconds(elapsed);
}
-qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::elapsed() const noexcept
{
qint64 elapsed = getTickCount() - t1;
return ticksToNanoseconds(elapsed) / 1000000;
}
-qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW
+qint64 QElapsedTimer::msecsSinceReference() const noexcept
{
return ticksToNanoseconds(t1) / 1000000;
}
-qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
{
qint64 difference = other.t1 - t1;
return ticksToNanoseconds(difference) / 1000000;
}
-qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
{
return msecsTo(other) / 1000;
}
-bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept
{
return (v1.t1 - v2.t1) < 0;
}
-QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW
+QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
{
Q_STATIC_ASSERT(!QDeadlineTimerNanosecondsInT2);
QDeadlineTimer result;
diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm
index b7b379e2c1..33c231987f 100644
--- a/src/corelib/kernel/qeventdispatcher_cf.mm
+++ b/src/corelib/kernel/qeventdispatcher_cf.mm
@@ -190,7 +190,7 @@ Q_ENUM_PRINTER(Result);
QDebug operator<<(QDebug s, timespec tv)
{
- s << tv.tv_sec << "." << qSetFieldWidth(9) << qSetPadChar(QChar(48)) << tv.tv_nsec << reset;
+ s << tv.tv_sec << "." << qSetFieldWidth(9) << qSetPadChar(QChar(48)) << tv.tv_nsec << Qt::reset;
return s;
}
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
index 45c6e29e4b..d9746ef6e2 100644
--- a/src/corelib/kernel/qeventdispatcher_glib.cpp
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -86,9 +86,10 @@ static gboolean socketNotifierSourceCheck(GSource *source)
p->pollfd.fd, t[int(p->socketNotifier->type())]);
// ### note, modifies src->pollfds!
p->socketNotifier->setEnabled(false);
+ i--;
+ } else {
+ pending = pending || ((p->pollfd.revents & p->pollfd.events) != 0);
}
-
- pending = ((p->pollfd.revents & p->pollfd.events) != 0);
}
return pending;
@@ -260,7 +261,7 @@ static gboolean postEventSourcePrepare(GSource *s, gint *timeout)
*timeout = canWait ? -1 : 0;
GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
- source->d->wakeUpCalled = source->serialNumber.load() != source->lastSerialNumber;
+ source->d->wakeUpCalled = source->serialNumber.loadRelaxed() != source->lastSerialNumber;
return !canWait || source->d->wakeUpCalled;
}
@@ -272,7 +273,7 @@ static gboolean postEventSourceCheck(GSource *source)
static gboolean postEventSourceDispatch(GSource *s, GSourceFunc, gpointer)
{
GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
- source->lastSerialNumber = source->serialNumber.load();
+ source->lastSerialNumber = source->serialNumber.loadRelaxed();
QCoreApplication::sendPostedEvents();
source->d->runTimersOnceWithNormalPriority();
return true; // i dunno, george...
@@ -319,7 +320,7 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
// setup post event source
postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs,
sizeof(GPostEventSource)));
- postEventSource->serialNumber.store(1);
+ postEventSource->serialNumber.storeRelaxed(1);
postEventSource->d = this;
g_source_set_can_recurse(&postEventSource->source, true);
g_source_attach(&postEventSource->source, mainContext);
diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h
index 88ff316ee5..313825d0a7 100644
--- a/src/corelib/kernel/qeventdispatcher_glib_p.h
+++ b/src/corelib/kernel/qeventdispatcher_glib_p.h
@@ -66,8 +66,8 @@ class Q_CORE_EXPORT QEventDispatcherGlib : public QAbstractEventDispatcher
Q_DECLARE_PRIVATE(QEventDispatcherGlib)
public:
- explicit QEventDispatcherGlib(QObject *parent = 0);
- explicit QEventDispatcherGlib(GMainContext *context, QObject *parent = 0);
+ explicit QEventDispatcherGlib(QObject *parent = nullptr);
+ explicit QEventDispatcherGlib(GMainContext *context, QObject *parent = nullptr);
~QEventDispatcherGlib();
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
@@ -102,7 +102,7 @@ class Q_CORE_EXPORT QEventDispatcherGlibPrivate : public QAbstractEventDispatche
{
public:
- QEventDispatcherGlibPrivate(GMainContext *context = 0);
+ QEventDispatcherGlibPrivate(GMainContext *context = nullptr);
GMainContext *mainContext;
GPostEventSource *postEventSource;
GSocketNotifierSource *socketNotifierSource;
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index 535f86fefe..5bc65b7110 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -225,7 +225,7 @@ int QThreadPipe::check(const pollfd &pfd)
QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate()
{
if (Q_UNLIKELY(threadPipe.init() == false))
- qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe");
+ qFatal("QEventDispatcherUNIXPrivate(): Cannot continue without a thread pipe");
}
QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
@@ -459,7 +459,7 @@ void QEventDispatcherUNIX::unregisterSocketNotifier(QSocketNotifier *notifier)
bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherUNIX);
- d->interrupt.store(0);
+ d->interrupt.storeRelaxed(0);
// we are awake, broadcast it
emit awake();
@@ -470,13 +470,13 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
const bool wait_for_events = flags & QEventLoop::WaitForMoreEvents;
const bool canWait = (d->threadData->canWaitLocked()
- && !d->interrupt.load()
+ && !d->interrupt.loadRelaxed()
&& wait_for_events);
if (canWait)
emit aboutToBlock();
- if (d->interrupt.load())
+ if (d->interrupt.loadRelaxed())
return false;
timespec *tm = nullptr;
@@ -545,7 +545,7 @@ void QEventDispatcherUNIX::wakeUp()
void QEventDispatcherUNIX::interrupt()
{
Q_D(QEventDispatcherUNIX);
- d->interrupt.store(1);
+ d->interrupt.storeRelaxed(1);
wakeUp();
}
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index 0fd068b074..f37edfc967 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -64,10 +64,10 @@ class QEventDispatcherUNIXPrivate;
struct Q_CORE_EXPORT QSocketNotifierSetUNIX final
{
- inline QSocketNotifierSetUNIX() Q_DECL_NOTHROW;
+ inline QSocketNotifierSetUNIX() noexcept;
- inline bool isEmpty() const Q_DECL_NOTHROW;
- inline short events() const Q_DECL_NOTHROW;
+ inline bool isEmpty() const noexcept;
+ inline short events() const noexcept;
QSocketNotifier *notifiers[3];
};
@@ -102,7 +102,7 @@ class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher
Q_DECLARE_PRIVATE(QEventDispatcherUNIX)
public:
- explicit QEventDispatcherUNIX(QObject *parent = 0);
+ explicit QEventDispatcherUNIX(QObject *parent = nullptr);
~QEventDispatcherUNIX();
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
@@ -123,7 +123,7 @@ public:
void flush() override;
protected:
- QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = 0);
+ QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = nullptr);
};
class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate
@@ -150,19 +150,19 @@ public:
QAtomicInt interrupt; // bool
};
-inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() Q_DECL_NOTHROW
+inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() noexcept
{
- notifiers[0] = 0;
- notifiers[1] = 0;
- notifiers[2] = 0;
+ notifiers[0] = nullptr;
+ notifiers[1] = nullptr;
+ notifiers[2] = nullptr;
}
-inline bool QSocketNotifierSetUNIX::isEmpty() const Q_DECL_NOTHROW
+inline bool QSocketNotifierSetUNIX::isEmpty() const noexcept
{
return !notifiers[0] && !notifiers[1] && !notifiers[2];
}
-inline short QSocketNotifierSetUNIX::events() const Q_DECL_NOTHROW
+inline short QSocketNotifierSetUNIX::events() const noexcept
{
short result = 0;
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index b3b6b1be20..c2e57a7924 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -82,8 +82,13 @@ extern uint qGlobalPostedEventsCount();
enum {
WM_QT_SOCKETNOTIFIER = WM_USER,
WM_QT_SENDPOSTEDEVENTS = WM_USER + 1,
- WM_QT_ACTIVATENOTIFIERS = WM_USER + 2,
- SendPostedEventsWindowsTimerId = ~1u
+ WM_QT_ACTIVATENOTIFIERS = WM_USER + 2
+};
+
+// WM_QT_SENDPOSTEDEVENTS message parameter
+enum {
+ WMWP_QT_TOFOREIGNLOOP = 0,
+ WMWP_QT_FROMWAKEUP
};
class QEventDispatcherWin32Private;
@@ -96,8 +101,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
: threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0),
- getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0),
- wakeUps(0), activateNotifiersPosted(false), winEventNotifierActivatedEvent(NULL)
+ getMessageHook(0), wakeUps(0), activateNotifiersPosted(false),
+ winEventNotifierActivatedEvent(NULL)
{
}
@@ -136,7 +141,11 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
msg.wParam = wp;
msg.lParam = lp;
QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr result;
+#else
long result;
+#endif
if (!dispatcher) {
if (message == WM_TIMER)
KillTimer(hwnd, wp);
@@ -230,22 +239,20 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
return 0;
}
case WM_TIMER:
- if (d->sendPostedEventsWindowsTimerId == 0
- || wp != uint(d->sendPostedEventsWindowsTimerId)) {
- Q_ASSERT(d != 0);
- d->sendTimerEvent(wp);
- return 0;
- }
- // we also use a Windows timer to send posted events when the message queue is full
- Q_FALLTHROUGH();
- case WM_QT_SENDPOSTEDEVENTS: {
- const int localSerialNumber = d->serialNumber.load();
- if (localSerialNumber != d->lastSerialNumber) {
- d->lastSerialNumber = localSerialNumber;
- q->sendPostedEvents();
- }
+ Q_ASSERT(d != 0);
+
+ d->sendTimerEvent(wp);
+ return 0;
+ case WM_QT_SENDPOSTEDEVENTS:
+ Q_ASSERT(d != 0);
+
+ // Allow posting WM_QT_SENDPOSTEDEVENTS message.
+ d->wakeUps.storeRelaxed(0);
+
+ // We send posted events manually, if the window procedure was invoked
+ // by the foreign event loop (e.g. from the native modal dialog).
+ q->sendPostedEvents();
return 0;
- }
} // switch (message)
return DefWindowProc(hwnd, message, wp, lp);
@@ -268,39 +275,6 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
Q_ASSERT(q != 0);
- if (wp == PM_REMOVE) {
- if (q) {
- MSG *msg = (MSG *) lp;
- QEventDispatcherWin32Private *d = q->d_func();
- const int localSerialNumber = d->serialNumber.load();
- static const UINT mask = inputTimerMask();
- if (HIWORD(GetQueueStatus(mask)) == 0) {
- // no more input or timer events in the message queue, we can allow posted events to be sent normally now
- if (d->sendPostedEventsWindowsTimerId != 0) {
- // stop the timer to send posted events, since we now allow the WM_QT_SENDPOSTEDEVENTS message
- KillTimer(d->internalHwnd, d->sendPostedEventsWindowsTimerId);
- d->sendPostedEventsWindowsTimerId = 0;
- }
- (void) d->wakeUps.fetchAndStoreRelease(0);
- if (localSerialNumber != d->lastSerialNumber
- // if this message IS the one that triggers sendPostedEvents(), no need to post it again
- && (msg->hwnd != d->internalHwnd
- || msg->message != WM_QT_SENDPOSTEDEVENTS)) {
- PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
- }
- } else if (d->sendPostedEventsWindowsTimerId == 0
- && localSerialNumber != d->lastSerialNumber) {
- // start a special timer to continue delivering posted events while
- // there are still input and timer messages in the message queue
- d->sendPostedEventsWindowsTimerId = SetTimer(d->internalHwnd,
- SendPostedEventsWindowsTimerId,
- 0, // we specify zero, but Windows uses USER_TIMER_MINIMUM
- NULL);
- // we don't check the return value of SetTimer()... if creating the timer failed, there's little
- // we can do. we just have to accept that posted events will be starved
- }
- }
- }
return q->d_func()->getMessageHook ? CallNextHookEx(0, code, wp, lp) : 0;
}
@@ -338,7 +312,7 @@ QWindowsMessageWindowClassContext::QWindowsMessageWindowClassContext()
wc.lpszClassName = className;
atom = RegisterClass(&wc);
if (!atom) {
- qErrnoWarning("%s RegisterClass() failed", qPrintable(qClassName));
+ qErrnoWarning("%ls RegisterClass() failed", qUtf16Printable(qClassName));
delete [] className;
className = 0;
}
@@ -500,8 +474,8 @@ void QEventDispatcherWin32::installMessageHook()
d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
if (Q_UNLIKELY(!d->getMessageHook)) {
int errorCode = GetLastError();
- qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %s",
- errorCode, qPrintable(qt_error_string(errorCode)));
+ qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %ls",
+ errorCode, qUtf16Printable(qt_error_string(errorCode)));
}
}
@@ -552,12 +526,15 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
wakeUp(); // trigger a call to sendPostedEvents()
}
- d->interrupt.store(false);
+ d->interrupt.storeRelaxed(false);
emit awake();
+ // To prevent livelocks, send posted events once per iteration.
+ // QCoreApplication::sendPostedEvents() takes care about recursions.
+ sendPostedEvents();
+
bool canWait;
bool retVal = false;
- bool seenWM_QT_SENDPOSTEDEVENTS = false;
bool needWM_QT_SENDPOSTEDEVENTS = false;
do {
DWORD waitRet = 0;
@@ -568,7 +545,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
pHandles = &d->winEventNotifierActivatedEvent;
}
QVarLengthArray<MSG> processedTimers;
- while (!d->interrupt.load()) {
+ while (!d->interrupt.loadRelaxed()) {
MSG msg;
bool haveMessage;
@@ -606,19 +583,20 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
}
}
if (haveMessage) {
- // WinCE doesn't support hooks at all, so we have to call this by hand :(
+ // The Direct2d integration unsets getMessageHook. See QTBUG-42428
if (!d->getMessageHook)
(void) qt_GetMessageHook(0, PM_REMOVE, reinterpret_cast<LPARAM>(&msg));
if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
- if (seenWM_QT_SENDPOSTEDEVENTS) {
- // when calling processEvents() "manually", we only want to send posted
- // events once
- needWM_QT_SENDPOSTEDEVENTS = true;
- continue;
+ // Set result to 'true', if the message was sent by wakeUp().
+ if (msg.wParam == WMWP_QT_FROMWAKEUP) {
+ d->wakeUps.storeRelaxed(0);
+ retVal = true;
}
- seenWM_QT_SENDPOSTEDEVENTS = true;
- } else if (msg.message == WM_TIMER) {
+ needWM_QT_SENDPOSTEDEVENTS = true;
+ continue;
+ }
+ if (msg.message == WM_TIMER) {
// avoid live-lock by keeping track of the timers we've already sent
bool found = false;
for (int i = 0; !found && i < processedTimers.count(); ++i) {
@@ -635,10 +613,22 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
}
if (!filterNativeEvent(QByteArrayLiteral("windows_generic_MSG"), &msg, 0)) {
+ // Post WM_QT_SENDPOSTEDEVENTS before calling external code,
+ // as it can start a foreign event loop.
+ if (needWM_QT_SENDPOSTEDEVENTS) {
+ needWM_QT_SENDPOSTEDEVENTS = false;
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
+ WMWP_QT_TOFOREIGNLOOP, 0);
+ }
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} else if (waitRet - WAIT_OBJECT_0 < nCount) {
+ if (needWM_QT_SENDPOSTEDEVENTS) {
+ needWM_QT_SENDPOSTEDEVENTS = false;
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
+ WMWP_QT_TOFOREIGNLOOP, 0);
+ }
activateEventNotifiers();
} else {
// nothing todo so break
@@ -649,26 +639,27 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
// still nothing - wait for message or signalled objects
canWait = (!retVal
- && !d->interrupt.load()
+ && !d->interrupt.loadRelaxed()
&& (flags & QEventLoop::WaitForMoreEvents));
if (canWait) {
emit aboutToBlock();
waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
emit awake();
if (waitRet - WAIT_OBJECT_0 < nCount) {
+ if (needWM_QT_SENDPOSTEDEVENTS) {
+ needWM_QT_SENDPOSTEDEVENTS = false;
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
+ WMWP_QT_TOFOREIGNLOOP, 0);
+ }
activateEventNotifiers();
retVal = true;
}
}
} while (canWait);
- if (!seenWM_QT_SENDPOSTEDEVENTS && (flags & QEventLoop::EventLoopExec) == 0) {
- // when called "manually", always send posted events
- sendPostedEvents();
- }
-
if (needWM_QT_SENDPOSTEDEVENTS)
- PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
+ WMWP_QT_TOFOREIGNLOOP, 0);
return retVal;
}
@@ -958,7 +949,7 @@ void QEventDispatcherWin32::activateEventNotifiers()
for (int i = 0; i < d->winEventNotifierList.count(); ++i) {
QWinEventNotifier *notifier = d->winEventNotifierList.at(i);
QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
- if (nd->signaledCount.load() != 0) {
+ if (nd->signaledCount.loadRelaxed() != 0) {
--nd->signaledCount;
nd->unregisterWaitObject();
d->activateEventNotifier(notifier);
@@ -992,8 +983,14 @@ int QEventDispatcherWin32::remainingTime(int timerId)
quint64 currentTime = qt_msectime();
for (const WinTimerInfo *t : qAsConst(d->timerVec)) {
- if (t && t->timerId == timerId) // timer found, return time to wait
- return t->timeout > currentTime ? t->timeout - currentTime : 0;
+ if (t && t->timerId == timerId) {
+ // timer found, return time to wait
+
+ if (d->internalHwnd)
+ return t->timeout > currentTime ? t->timeout - currentTime : 0;
+ else
+ return t->interval;
+ }
}
#ifndef QT_NO_DEBUG
@@ -1006,17 +1003,18 @@ int QEventDispatcherWin32::remainingTime(int timerId)
void QEventDispatcherWin32::wakeUp()
{
Q_D(QEventDispatcherWin32);
- d->serialNumber.ref();
if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) {
// post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
- PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
+ if (!PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
+ WMWP_QT_FROMWAKEUP, 0))
+ qErrnoWarning("QEventDispatcherWin32::wakeUp: Failed to post a message");
}
}
void QEventDispatcherWin32::interrupt()
{
Q_D(QEventDispatcherWin32);
- d->interrupt.store(true);
+ d->interrupt.storeRelaxed(true);
wakeUp();
}
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
index 3bb618153b..f672530ff8 100644
--- a/src/corelib/kernel/qeventdispatcher_win_p.h
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -80,31 +80,31 @@ public:
explicit QEventDispatcherWin32(QObject *parent = 0);
~QEventDispatcherWin32();
- bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags);
- bool hasPendingEvents();
+ bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags) override;
+ bool hasPendingEvents() override;
- void registerSocketNotifier(QSocketNotifier *notifier);
- void unregisterSocketNotifier(QSocketNotifier *notifier);
+ void registerSocketNotifier(QSocketNotifier *notifier) override;
+ void unregisterSocketNotifier(QSocketNotifier *notifier) override;
- void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object);
- bool unregisterTimer(int timerId);
- bool unregisterTimers(QObject *object);
- QList<TimerInfo> registeredTimers(QObject *object) const;
+ void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) override;
+ bool unregisterTimer(int timerId) override;
+ bool unregisterTimers(QObject *object) override;
+ QList<TimerInfo> registeredTimers(QObject *object) const override;
- bool registerEventNotifier(QWinEventNotifier *notifier);
- void unregisterEventNotifier(QWinEventNotifier *notifier);
+ bool registerEventNotifier(QWinEventNotifier *notifier) override;
+ void unregisterEventNotifier(QWinEventNotifier *notifier) override;
void activateEventNotifiers();
- int remainingTime(int timerId);
+ int remainingTime(int timerId) override;
- void wakeUp();
- void interrupt();
- void flush();
+ void wakeUp() override;
+ void interrupt() override;
+ void flush() override;
- void startingUp();
- void closingDown();
+ void startingUp() override;
+ void closingDown() override;
- bool event(QEvent *e);
+ bool event(QEvent *e) override;
HWND internalHwnd();
@@ -172,8 +172,6 @@ public:
HHOOK getMessageHook;
// for controlling when to send posted events
- QAtomicInt serialNumber;
- int lastSerialNumber, sendPostedEventsWindowsTimerId;
QAtomicInt wakeUps;
// timers
diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp
index a6cc51621a..2104b22095 100644
--- a/src/corelib/kernel/qeventloop.cpp
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -135,7 +135,7 @@ bool QEventLoop::processEvents(ProcessEventsFlags flags)
Q_D(QEventLoop);
if (!d->threadData->hasEventDispatcher())
return false;
- return d->threadData->eventDispatcher.load()->processEvents(flags);
+ return d->threadData->eventDispatcher.loadRelaxed()->processEvents(flags);
}
/*!
@@ -225,7 +225,7 @@ int QEventLoop::exec(ProcessEventsFlags flags)
processEvents(flags | WaitForMoreEvents | EventLoopExec);
ref.exceptionCaught = false;
- return d->returnCode.load();
+ return d->returnCode.loadRelaxed();
}
/*!
@@ -279,9 +279,9 @@ void QEventLoop::exit(int returnCode)
if (!d->threadData->hasEventDispatcher())
return;
- d->returnCode.store(returnCode);
+ d->returnCode.storeRelaxed(returnCode);
d->exit.storeRelease(true);
- d->threadData->eventDispatcher.load()->interrupt();
+ d->threadData->eventDispatcher.loadRelaxed()->interrupt();
#ifdef Q_OS_WASM
// QEventLoop::exec() never returns in emscripten. We implement approximate behavior here.
@@ -318,7 +318,7 @@ void QEventLoop::wakeUp()
Q_D(QEventLoop);
if (!d->threadData->hasEventDispatcher())
return;
- d->threadData->eventDispatcher.load()->wakeUp();
+ d->threadData->eventDispatcher.loadRelaxed()->wakeUp();
}
diff --git a/src/corelib/kernel/qeventloop_p.h b/src/corelib/kernel/qeventloop_p.h
index dcbb5c63c6..4ad6d92007 100644
--- a/src/corelib/kernel/qeventloop_p.h
+++ b/src/corelib/kernel/qeventloop_p.h
@@ -63,8 +63,8 @@ public:
inline QEventLoopPrivate()
: inExec(false)
{
- returnCode.store(-1);
- exit.store(true);
+ returnCode.storeRelaxed(-1);
+ exit.storeRelaxed(true);
}
QAtomicInt quitLockRef;
diff --git a/src/corelib/kernel/qfunctions_fake_env_p.h b/src/corelib/kernel/qfunctions_fake_env_p.h
index 7010d2cf5d..68d17ed4a1 100644
--- a/src/corelib/kernel/qfunctions_fake_env_p.h
+++ b/src/corelib/kernel/qfunctions_fake_env_p.h
@@ -72,8 +72,8 @@ Q_DECLARE_TYPEINFO(Variable, Q_MOVABLE_TYPE);
struct NameEquals {
typedef bool result_type;
const char *name;
- explicit NameEquals(const char *name) Q_DECL_NOTHROW : name(name) {}
- result_type operator()(const Variable &other) const Q_DECL_NOTHROW
+ explicit NameEquals(const char *name) noexcept : name(name) {}
+ result_type operator()(const Variable &other) const noexcept
{ return qstrcmp(other.name, name) == 0; }
};
diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp
index 75a2436d9d..5f652d70e3 100644
--- a/src/corelib/kernel/qjni.cpp
+++ b/src/corelib/kernel/qjni.cpp
@@ -47,9 +47,9 @@
QT_BEGIN_NAMESPACE
-static inline QString keyBase()
+static inline QLatin1String keyBase()
{
- return QStringLiteral("%1%2:%3");
+ return QLatin1String("%1%2:%3");
}
static QString qt_convertJString(jstring string)
@@ -154,7 +154,7 @@ static jmethodID getCachedMethodID(JNIEnv *env,
if (className.isEmpty())
return getMethodID(env, clazz, name, sig, isStatic);
- const QString key = keyBase().arg(QLatin1String(className)).arg(QLatin1String(name)).arg(QLatin1String(sig));
+ const QString key = keyBase().arg(QLatin1String(className), QLatin1String(name), QLatin1String(sig));
QHash<QString, jmethodID>::const_iterator it;
{
@@ -206,7 +206,7 @@ static jfieldID getCachedFieldID(JNIEnv *env,
if (className.isNull())
return getFieldID(env, clazz, name, sig, isStatic);
- const QString key = keyBase().arg(QLatin1String(className)).arg(QLatin1String(name)).arg(QLatin1String(sig));
+ const QString key = keyBase().arg(QLatin1String(className), QLatin1String(name), QLatin1String(sig));
QHash<QString, jfieldID>::const_iterator it;
{
diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h
index 52abd51dc1..ec8525e6e1 100644
--- a/src/corelib/kernel/qjni_p.h
+++ b/src/corelib/kernel/qjni_p.h
@@ -76,7 +76,7 @@ public:
private:
friend class QAndroidJniEnvironment;
- Q_DISABLE_COPY(QJNIEnvironmentPrivate)
+ Q_DISABLE_COPY_MOVE(QJNIEnvironmentPrivate)
JNIEnv *jniEnv;
};
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 666bb6eace..56217262f2 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -216,8 +216,8 @@ private:
Constructs a new instance of this class. You can pass up to ten arguments
(\a val0, \a val1, \a val2, \a val3, \a val4, \a val5, \a val6, \a val7,
- \a val8, and \a val9) to the constructor. Returns the new object, or 0 if
- no suitable constructor is available.
+ \a val8, and \a val9) to the constructor. Returns the new object, or
+ \nullptr if no suitable constructor is available.
Note that only constructors that are declared with the Q_INVOKABLE
modifier are made available through the meta-object system.
@@ -327,8 +327,8 @@ const char *QMetaObject::className() const
/*!
\fn QMetaObject *QMetaObject::superClass() const
- Returns the meta-object of the superclass, or 0 if there is no
- such object.
+ Returns the meta-object of the superclass, or \nullptr if there is
+ no such object.
\sa className()
*/
@@ -341,7 +341,7 @@ const char *QMetaObject::className() const
\since 5.7
*/
-bool QMetaObject::inherits(const QMetaObject *metaObject) const Q_DECL_NOEXCEPT
+bool QMetaObject::inherits(const QMetaObject *metaObject) const noexcept
{
const QMetaObject *m = this;
do {
@@ -2263,9 +2263,9 @@ bool QMetaMethod::invoke(QObject *object,
return false;
// check connection type
- QThread *currentThread = QThread::currentThread();
- QThread *objectThread = object->thread();
if (connectionType == Qt::AutoConnection) {
+ QThread *currentThread = QThread::currentThread();
+ QThread *objectThread = object->thread();
connectionType = currentThread == objectThread
? Qt::DirectConnection
: Qt::QueuedConnection;
@@ -2348,6 +2348,8 @@ bool QMetaMethod::invoke(QObject *object,
0, -1, nargs, types, args));
} else { // blocking queued connection
#if QT_CONFIG(thread)
+ QThread *currentThread = QThread::currentThread();
+ QThread *objectThread = object->thread();
if (currentThread == objectThread) {
qWarning("QMetaMethod::invoke: Dead lock detected in "
"BlockingQueuedConnection: Receiver is %s(%p)",
@@ -2619,7 +2621,7 @@ int QMetaEnum::keyCount() const
}
/*!
- Returns the key with the given \a index, or 0 if no such key exists.
+ Returns the key with the given \a index, or \nullptr if no such key exists.
\sa keyCount(), value(), valueToKey()
*/
@@ -2741,7 +2743,7 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
/*!
Returns the string that is used as the name of the given
- enumeration \a value, or 0 if \a value is not defined.
+ enumeration \a value, or \nullptr if \a value is not defined.
For flag types, use valueToKeys().
@@ -3021,6 +3023,18 @@ int QMetaProperty::propertyIndex() const
}
/*!
+ \since 5.14
+
+ Returns this property's index relative within the enclosing meta object.
+*/
+int QMetaProperty::relativePropertyIndex() const
+{
+ if (!mobj)
+ return -1;
+ return idx;
+}
+
+/*!
Returns \c true if the property's type is an enumeration value that
is used as a flag; otherwise returns \c false.
@@ -3526,7 +3540,7 @@ bool QMetaProperty::isStored(const QObject *object) const
false. e.g., the \c text property is the \c USER editable property
of a QLineEdit.
- If \a object is null, the function returns \c false if the \c
+ If \a object is \nullptr, the function returns \c false if the \c
{Q_PROPERTY()}'s \c USER attribute is false. Otherwise it returns
true.
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
index 1efb49017f..fcd92afd89 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -183,7 +183,7 @@ private:
// signature() has been renamed to methodSignature() in Qt 5.
// Warning, that function returns a QByteArray; check the life time if
// you convert to char*.
- char *signature(struct renamedInQt5_warning_checkTheLifeTime * = nullptr) Q_DECL_EQ_DELETE;
+ char *signature(struct renamedInQt5_warning_checkTheLifeTime * = nullptr) = delete;
#endif
static QMetaMethod fromSignalImpl(const QMetaObject *, void **);
@@ -254,6 +254,7 @@ public:
QVariant::Type type() const;
int userType() const;
int propertyIndex() const;
+ int relativePropertyIndex() const;
bool isReadable() const;
bool isWritable() const;
diff --git a/src/corelib/kernel/qmetaobject_moc_p.h b/src/corelib/kernel/qmetaobject_moc_p.h
index ad258acfcd..8c7900767b 100644
--- a/src/corelib/kernel/qmetaobject_moc_p.h
+++ b/src/corelib/kernel/qmetaobject_moc_p.h
@@ -138,7 +138,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc
{ "struct ", 7 },
{ "class ", 6 },
{ "enum ", 5 },
- { 0, 0 }
+ { nullptr, 0 }
};
int i = 0;
do {
@@ -146,7 +146,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc
t += optional[i].len;
break;
}
- } while (optional[++i].keyword != 0);
+ } while (optional[++i].keyword != nullptr);
}
bool star = false;
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index 522bd78e42..0cd9da2eac 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -54,6 +54,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qobjectdefs.h>
+#include <QtCore/qmutex.h>
#ifndef QT_NO_QOBJECT
#include <private/qobject_p.h> // For QObjectPrivate::Connection
#endif
@@ -168,7 +169,6 @@ Q_DECLARE_TYPEINFO(QArgumentType, Q_MOVABLE_TYPE);
typedef QVarLengthArray<QArgumentType, 10> QArgumentTypeArray;
class QMetaMethodPrivate;
-class QMutex;
struct QMetaObjectPrivate
{
@@ -226,15 +226,15 @@ struct QMetaObjectPrivate
static QObjectPrivate::Connection *connect(const QObject *sender, int signal_index,
const QMetaObject *smeta,
const QObject *receiver, int method_index_relative,
- const QMetaObject *rmeta = 0,
- int type = 0, int *types = 0);
+ const QMetaObject *rmeta = nullptr,
+ int type = 0, int *types = nullptr);
static bool disconnect(const QObject *sender, int signal_index,
const QMetaObject *smeta,
const QObject *receiver, int method_index, void **slot,
DisconnectType = DisconnectAll);
- static inline bool disconnectHelper(QObjectPrivate::Connection *c,
+ static inline bool disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex,
const QObject *receiver, int method_index, void **slot,
- QMutex *senderMutex, DisconnectType = DisconnectAll);
+ QBasicMutex *senderMutex, DisconnectType = DisconnectAll);
#endif
};
diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h
index 115ec835aa..6d43be7811 100644
--- a/src/corelib/kernel/qmetaobjectbuilder_p.h
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -173,7 +173,7 @@ public:
void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value);
QMetaObject *toMetaObject() const;
- QByteArray toRelocatableData(bool * = 0) const;
+ QByteArray toRelocatableData(bool * = nullptr) const;
static void fromRelocatableData(QMetaObject *, const QMetaObject *, const QByteArray &);
#ifndef QT_NO_DATASTREAM
@@ -184,7 +184,7 @@ public:
#endif
private:
- Q_DISABLE_COPY(QMetaObjectBuilder)
+ Q_DISABLE_COPY_MOVE(QMetaObjectBuilder)
QMetaObjectBuilderPrivate *d;
@@ -196,7 +196,7 @@ private:
class Q_CORE_EXPORT QMetaMethodBuilder
{
public:
- QMetaMethodBuilder() : _mobj(0), _index(0) {}
+ QMetaMethodBuilder() : _mobj(nullptr), _index(0) {}
int index() const;
@@ -238,7 +238,7 @@ private:
class Q_CORE_EXPORT QMetaPropertyBuilder
{
public:
- QMetaPropertyBuilder() : _mobj(0), _index(0) {}
+ QMetaPropertyBuilder() : _mobj(nullptr), _index(0) {}
int index() const { return _index; }
@@ -294,7 +294,7 @@ private:
class Q_CORE_EXPORT QMetaEnumBuilder
{
public:
- QMetaEnumBuilder() : _mobj(0), _index(0) {}
+ QMetaEnumBuilder() : _mobj(nullptr), _index(0) {}
int index() const { return _index; }
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 632b86959d..754f5a13e4 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -51,6 +51,7 @@
#include "quuid.h"
#include "qvariant.h"
#include "qdatastream.h"
+#include "qregexp.h"
#include "qmetatypeswitcher_p.h"
#if QT_CONFIG(regularexpression)
@@ -290,6 +291,10 @@ struct DefinedTypesFilter {
\value QJsonObject QJsonObject
\value QJsonArray QJsonArray
\value QJsonDocument QJsonDocument
+ \value QCborValue QCborValue
+ \value QCborArray QCborArray
+ \value QCborMap QCborMap
+ \value QCborSimpleType QCborSimpleType
\value QModelIndex QModelIndex
\value QPersistentModelIndex QPersistentModelIndex (since 5.5)
\value QUuid QUuid
@@ -373,6 +378,13 @@ struct DefinedTypesFilter {
*/
/*!
+ \fn int QMetaType::id() const
+ \since 5.13
+
+ Returns id type hold by this QMetatype instance.
+*/
+
+/*!
\fn bool QMetaType::sizeOf() const
\since 5.0
@@ -410,8 +422,8 @@ struct DefinedTypesFilter {
pointer of this type. (given by QVariant::data for example)
If the type is an enumeration, flags() contains QMetaType::IsEnumeration, and this function
- returns the QMetaObject of the enclosing object if the enum was registered as a Q_ENUM or 0
- otherwise
+ returns the QMetaObject of the enclosing object if the enum was registered as a Q_ENUM or
+ \nullptr otherwise
\sa QMetaType::metaObjectForType(), QMetaType::flags()
*/
@@ -421,7 +433,7 @@ struct DefinedTypesFilter {
\since 5.0
Returns a copy of \a copy, assuming it is of the type that this
- QMetaType instance was created for. If \a copy is null, creates
+ QMetaType instance was created for. If \a copy is \nullptr, creates
a default constructed instance.
\sa QMetaType::destroy()
@@ -505,12 +517,12 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ
QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
QT_FOR_EACH_STATIC_HACKS_TYPE(QT_ADD_STATIC_METATYPE_HACKS_ITER)
- {0, 0, QMetaType::UnknownType}
+ {nullptr, 0, QMetaType::UnknownType}
};
-Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = 0;
-Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeWidgetsHelper = 0;
-Q_CORE_EXPORT const QMetaObject *qMetaObjectWidgetsHelper = 0;
+Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = nullptr;
+Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeWidgetsHelper = nullptr;
+Q_CORE_EXPORT const QMetaObject *qMetaObjectWidgetsHelper = nullptr;
class QCustomTypeInfo : public QMetaTypeInterface
{
@@ -545,7 +557,7 @@ public:
{
const QWriteLocker locker(&lock);
const T* &fun = map[k];
- if (fun != 0)
+ if (fun)
return false;
fun = f;
return true;
@@ -554,7 +566,7 @@ public:
const T *function(Key k) const
{
const QReadLocker locker(&lock);
- return map.value(k, 0);
+ return map.value(k, nullptr);
}
void remove(int from, int to)
@@ -575,13 +587,7 @@ QMetaTypeComparatorRegistry;
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
QMetaTypeDebugStreamRegistry;
-namespace
-{
-union CheckThatItIsPod
-{ // This should break if QMetaTypeInterface is not a POD type
- QMetaTypeInterface iface;
-};
-}
+Q_STATIC_ASSERT(std::is_pod<QMetaTypeInterface>::value);
Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
@@ -904,7 +910,7 @@ template <int... TypeIds> struct MetaTypeOffsets<QtPrivate::IndexesList<TypeIds.
short offsets[sizeof...(TypeIds)];
constexpr MetaTypeOffsets() : offsets{calculateOffsetForTypeId(TypeIds)...} {}
- const char *operator[](int typeId) const Q_DECL_NOTHROW
+ const char *operator[](int typeId) const noexcept
{
short o = offsets[typeId];
return o < 0 ? nullptr : metaTypeStrings + o;
@@ -961,7 +967,7 @@ static inline int qMetaTypeStaticType(const char *typeName, int length)
The extra \a firstInvalidIndex parameter is an easy way to avoid
iterating over customTypes() a second time in registerNormalizedType().
*/
-static int qMetaTypeCustomType_unlocked(const char *typeName, int length, int *firstInvalidIndex = 0)
+static int qMetaTypeCustomType_unlocked(const char *typeName, int length, int *firstInvalidIndex = nullptr)
{
const QVector<QCustomTypeInfo> * const ct = customTypes();
if (!ct)
@@ -994,7 +1000,7 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
{
return registerType(typeName, deleter, creator,
QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Destruct,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Construct, 0, TypeFlags(), 0);
+ QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Construct, 0, TypeFlags(), nullptr);
}
/*!
@@ -1374,236 +1380,197 @@ int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
}
#ifndef QT_NO_DATASTREAM
-/*!
- Writes the object pointed to by \a data with the ID \a type to
- the given \a stream. Returns \c true if the object is saved
- successfully; otherwise returns \c false.
- The type must have been registered with qRegisterMetaType() and
- qRegisterMetaTypeStreamOperators() beforehand.
+namespace
+{
- Normally, you should not need to call this function directly.
- Instead, use QVariant's \c operator<<(), which relies on save()
- to stream custom types.
+template<typename T>
+class HasStreamOperator
+{
+ struct Yes { char unused[1]; };
+ struct No { char unused[2]; };
+ Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No));
+
+ template<class C> static decltype(std::declval<QDataStream&>().operator>>(std::declval<C&>()), Yes()) load(int);
+ template<class C> static decltype(operator>>(std::declval<QDataStream&>(), std::declval<C&>()), Yes()) load(int);
+ template<class C> static No load(...);
+ template<class C> static decltype(operator<<(std::declval<QDataStream&>(), std::declval<const C&>()), Yes()) saveFunction(int);
+ template<class C> static decltype(std::declval<QDataStream&>().operator<<(std::declval<const C&>()), Yes()) saveMethod(int);
+ template<class C> static No saveMethod(...);
+ template<class C> static No saveFunction(...);
+ static constexpr bool LoadValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && (sizeof(load<T>(0)) == sizeof(Yes));
+ static constexpr bool SaveValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable &&
+ ((sizeof(saveMethod<T>(0)) == sizeof(Yes)) || (sizeof(saveFunction<T>(0)) == sizeof(Yes)));
+public:
+ static constexpr bool Value = LoadValue && SaveValue;
+};
- \sa load(), qRegisterMetaTypeStreamOperators()
-*/
-bool QMetaType::save(QDataStream &stream, int type, const void *data)
+// Quick sanity checks
+Q_STATIC_ASSERT(HasStreamOperator<NS(QJsonDocument)>::Value);
+Q_STATIC_ASSERT(!HasStreamOperator<void*>::Value);
+Q_STATIC_ASSERT(HasStreamOperator<qint8>::Value);
+
+template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted && HasStreamOperator<T>::Value>
+struct FilteredOperatorSwitch
+{
+ static bool load(QDataStream &stream, T *data, int)
+ {
+ stream >> *data;
+ return true;
+ }
+ static bool save(QDataStream &stream, const T *data, int)
+ {
+ stream << *data;
+ return true;
+ }
+};
+template<typename T>
+struct FilteredOperatorSwitch<T, /* IsAcceptedType = */ false>
{
- if (!data || !isRegistered(type))
+ static const QMetaTypeInterface* getMetaTypeInterface(int type)
+ {
+ if (QModulesPrivate::QTypeModuleInfo<T>::IsGui && qMetaTypeGuiHelper)
+ return &qMetaTypeGuiHelper[type - QMetaType::FirstGuiType];
+ else if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget && qMetaTypeWidgetsHelper)
+ return &qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType];
+ return nullptr;
+ }
+ static bool save(QDataStream &stream, const T *data, int type)
+ {
+ if (auto interface = getMetaTypeInterface(type)) {
+ interface->saveOp(stream, data);
+ return true;
+ }
return false;
-
- switch(type) {
- case QMetaType::UnknownType:
- case QMetaType::Void:
- case QMetaType::VoidStar:
- case QMetaType::QObjectStar:
-#if QT_CONFIG(itemmodel)
- case QMetaType::QModelIndex:
- case QMetaType::QPersistentModelIndex:
-#endif
- case QMetaType::QJsonValue:
- case QMetaType::QJsonObject:
- case QMetaType::QJsonArray:
- case QMetaType::QJsonDocument:
- case QMetaType::QCborValue:
- case QMetaType::QCborArray:
- case QMetaType::QCborMap:
+ }
+ static bool load(QDataStream &stream, T *data, int type)
+ {
+ if (auto interface = getMetaTypeInterface(type)) {
+ interface->loadOp(stream, data);
+ return true;
+ }
return false;
- case QMetaType::Nullptr:
- stream << *static_cast<const std::nullptr_t *>(data);
- return true;
- case QMetaType::Long:
- stream << qlonglong(*static_cast<const long *>(data));
- break;
- case QMetaType::Int:
- stream << *static_cast<const int *>(data);
- break;
- case QMetaType::Short:
- stream << *static_cast<const short *>(data);
- break;
- case QMetaType::Char:
+ }
+};
+
+class SaveOperatorSwitch
+{
+public:
+ QDataStream &stream;
+ int m_type;
+
+ template<typename T>
+ bool delegate(const T *data)
+ {
+ return FilteredOperatorSwitch<T>::save(stream, data, m_type);
+ }
+ bool delegate(const char *data)
+ {
// force a char to be signed
- stream << *static_cast<const signed char *>(data);
- break;
- case QMetaType::ULong:
- stream << qulonglong(*static_cast<const ulong *>(data));
- break;
- case QMetaType::UInt:
- stream << *static_cast<const uint *>(data);
- break;
- case QMetaType::LongLong:
- stream << *static_cast<const qlonglong *>(data);
- break;
- case QMetaType::ULongLong:
- stream << *static_cast<const qulonglong *>(data);
- break;
- case QMetaType::UShort:
- stream << *static_cast<const ushort *>(data);
- break;
- case QMetaType::SChar:
- stream << *static_cast<const signed char *>(data);
- break;
- case QMetaType::UChar:
- stream << *static_cast<const uchar *>(data);
- break;
- case QMetaType::Bool:
- stream << qint8(*static_cast<const bool *>(data));
- break;
- case QMetaType::Float:
- stream << *static_cast<const float *>(data);
- break;
- case QMetaType::Double:
- stream << *static_cast<const double *>(data);
- break;
- case QMetaType::QChar:
- stream << *static_cast<const NS(QChar) *>(data);
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QVariantMap:
- stream << *static_cast<const NS(QVariantMap)*>(data);
- break;
- case QMetaType::QVariantHash:
- stream << *static_cast<const NS(QVariantHash)*>(data);
- break;
- case QMetaType::QVariantList:
- stream << *static_cast<const NS(QVariantList)*>(data);
- break;
- case QMetaType::QVariant:
- stream << *static_cast<const NS(QVariant)*>(data);
- break;
- case QMetaType::QByteArrayList:
- stream << *static_cast<const NS(QByteArrayList)*>(data);
- break;
-#endif
- case QMetaType::QByteArray:
- stream << *static_cast<const NS(QByteArray)*>(data);
- break;
- case QMetaType::QString:
- stream << *static_cast<const NS(QString)*>(data);
- break;
- case QMetaType::QStringList:
- stream << *static_cast<const NS(QStringList)*>(data);
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QBitArray:
- stream << *static_cast<const NS(QBitArray)*>(data);
- break;
-#endif
- case QMetaType::QDate:
- stream << *static_cast<const NS(QDate)*>(data);
- break;
- case QMetaType::QTime:
- stream << *static_cast<const NS(QTime)*>(data);
- break;
- case QMetaType::QDateTime:
- stream << *static_cast<const NS(QDateTime)*>(data);
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QUrl:
- stream << *static_cast<const NS(QUrl)*>(data);
- break;
-#endif
- case QMetaType::QLocale:
- stream << *static_cast<const NS(QLocale)*>(data);
- break;
-#ifndef QT_NO_GEOM_VARIANT
- case QMetaType::QRect:
- stream << *static_cast<const NS(QRect)*>(data);
- break;
- case QMetaType::QRectF:
- stream << *static_cast<const NS(QRectF)*>(data);
- break;
- case QMetaType::QSize:
- stream << *static_cast<const NS(QSize)*>(data);
- break;
- case QMetaType::QSizeF:
- stream << *static_cast<const NS(QSizeF)*>(data);
- break;
- case QMetaType::QLine:
- stream << *static_cast<const NS(QLine)*>(data);
- break;
- case QMetaType::QLineF:
- stream << *static_cast<const NS(QLineF)*>(data);
- break;
- case QMetaType::QPoint:
- stream << *static_cast<const NS(QPoint)*>(data);
- break;
- case QMetaType::QPointF:
- stream << *static_cast<const NS(QPointF)*>(data);
- break;
-#endif
-#ifndef QT_NO_REGEXP
- case QMetaType::QRegExp:
- stream << *static_cast<const NS(QRegExp)*>(data);
- break;
-#endif
-#if QT_CONFIG(regularexpression)
- case QMetaType::QRegularExpression:
- stream << *static_cast<const NS(QRegularExpression)*>(data);
- break;
-#endif // QT_CONFIG(regularexpression)
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QEasingCurve:
- stream << *static_cast<const NS(QEasingCurve)*>(data);
- break;
- case QMetaType::QCborSimpleType:
- stream << *static_cast<const quint8 *>(data);
- break;
-#endif // QT_BOOTSTRAPPED
- case QMetaType::QFont:
- case QMetaType::QPixmap:
- case QMetaType::QBrush:
- case QMetaType::QColor:
- case QMetaType::QPalette:
- case QMetaType::QImage:
- case QMetaType::QPolygon:
- case QMetaType::QPolygonF:
- case QMetaType::QRegion:
- case QMetaType::QBitmap:
- case QMetaType::QCursor:
- case QMetaType::QKeySequence:
- case QMetaType::QPen:
- case QMetaType::QTextLength:
- case QMetaType::QTextFormat:
- case QMetaType::QMatrix:
- case QMetaType::QTransform:
- case QMetaType::QMatrix4x4:
- case QMetaType::QVector2D:
- case QMetaType::QVector3D:
- case QMetaType::QVector4D:
- case QMetaType::QQuaternion:
- case QMetaType::QIcon:
- if (!qMetaTypeGuiHelper)
- return false;
- qMetaTypeGuiHelper[type - FirstGuiType].saveOp(stream, data);
- break;
- case QMetaType::QSizePolicy:
- if (!qMetaTypeWidgetsHelper)
- return false;
- qMetaTypeWidgetsHelper[type - FirstWidgetsType].saveOp(stream, data);
- break;
- case QMetaType::QUuid:
- stream << *static_cast<const NS(QUuid)*>(data);
- break;
- default: {
+ stream << qint8(*data);
+ return true;
+ }
+ bool delegate(const long *data)
+ {
+ stream << qlonglong(*data);
+ return true;
+ }
+ bool delegate(const unsigned long *data)
+ {
+ stream << qulonglong(*data);
+ return true;
+ }
+ bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data)
+ {
const QVector<QCustomTypeInfo> * const ct = customTypes();
if (!ct)
return false;
-
- SaveOperator saveOp = 0;
+ QMetaType::SaveOperator saveOp = nullptr;
{
QReadLocker locker(customTypesLock());
- saveOp = ct->at(type - User).saveOp;
+ saveOp = ct->at(m_type - QMetaType::User).saveOp;
}
-
if (!saveOp)
return false;
saveOp(stream, data);
- break; }
+ return true;
}
+ bool delegate(const void*) { return false; }
+ bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; }
+};
+class LoadOperatorSwitch
+{
+public:
+ QDataStream &stream;
+ int m_type;
- return true;
+ template<typename T>
+ bool delegate(const T *data)
+ {
+ return FilteredOperatorSwitch<T>::load(stream, const_cast<T*>(data), m_type);
+ }
+ bool delegate(const char *data)
+ {
+ // force a char to be signed
+ qint8 c;
+ stream >> c;
+ *const_cast<char*>(data) = c;
+ return true;
+ }
+ bool delegate(const long *data)
+ {
+ qlonglong l;
+ stream >> l;
+ *const_cast<long*>(data) = l;
+ return true;
+ }
+ bool delegate(const unsigned long *data)
+ {
+ qlonglong l;
+ stream >> l;
+ *const_cast<unsigned long*>(data) = l;
+ return true;
+ }
+ bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data)
+ {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ if (!ct)
+ return false;
+ QMetaType::LoadOperator loadOp = nullptr;
+ {
+ QReadLocker locker(customTypesLock());
+ loadOp = ct->at(m_type - QMetaType::User).loadOp;
+ }
+ if (!loadOp)
+ return false;
+ loadOp(stream, const_cast<QMetaTypeSwitcher::NotBuiltinType*>(data));
+ return true;
+ }
+ bool delegate(const void*) { return false; }
+ bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; }
+};
+} // namespace
+
+/*!
+ Writes the object pointed to by \a data with the ID \a type to
+ the given \a stream. Returns \c true if the object is saved
+ successfully; otherwise returns \c false.
+
+ The type must have been registered with qRegisterMetaType() and
+ qRegisterMetaTypeStreamOperators() beforehand.
+
+ Normally, you should not need to call this function directly.
+ Instead, use QVariant's \c operator<<(), which relies on save()
+ to stream custom types.
+
+ \sa load(), qRegisterMetaTypeStreamOperators()
+*/
+bool QMetaType::save(QDataStream &stream, int type, const void *data)
+{
+ if (!data)
+ return false;
+ SaveOperatorSwitch saveOp{stream, type};
+ return QMetaTypeSwitcher::switcher<bool>(saveOp, type, data);
}
/*!
@@ -1622,225 +1589,10 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
*/
bool QMetaType::load(QDataStream &stream, int type, void *data)
{
- if (!data || !isRegistered(type))
+ if (!data)
return false;
-
- switch(type) {
- case QMetaType::UnknownType:
- case QMetaType::Void:
- case QMetaType::VoidStar:
- case QMetaType::QObjectStar:
-#if QT_CONFIG(itemmodel)
- case QMetaType::QModelIndex:
- case QMetaType::QPersistentModelIndex:
-#endif
- case QMetaType::QJsonValue:
- case QMetaType::QJsonObject:
- case QMetaType::QJsonArray:
- case QMetaType::QJsonDocument:
- case QMetaType::QCborValue:
- case QMetaType::QCborArray:
- case QMetaType::QCborMap:
- return false;
- case QMetaType::Nullptr:
- stream >> *static_cast<std::nullptr_t *>(data);
- return true;
- case QMetaType::Long: {
- qlonglong l;
- stream >> l;
- *static_cast<long *>(data) = long(l);
- break; }
- case QMetaType::Int:
- stream >> *static_cast<int *>(data);
- break;
- case QMetaType::Short:
- stream >> *static_cast<short *>(data);
- break;
- case QMetaType::Char:
- // force a char to be signed
- stream >> *static_cast<signed char *>(data);
- break;
- case QMetaType::ULong: {
- qulonglong ul;
- stream >> ul;
- *static_cast<ulong *>(data) = ulong(ul);
- break; }
- case QMetaType::UInt:
- stream >> *static_cast<uint *>(data);
- break;
- case QMetaType::LongLong:
- stream >> *static_cast<qlonglong *>(data);
- break;
- case QMetaType::ULongLong:
- stream >> *static_cast<qulonglong *>(data);
- break;
- case QMetaType::UShort:
- stream >> *static_cast<ushort *>(data);
- break;
- case QMetaType::SChar:
- stream >> *static_cast<signed char *>(data);
- break;
- case QMetaType::UChar:
- stream >> *static_cast<uchar *>(data);
- break;
- case QMetaType::Bool: {
- qint8 b;
- stream >> b;
- *static_cast<bool *>(data) = b;
- break; }
- case QMetaType::Float:
- stream >> *static_cast<float *>(data);
- break;
- case QMetaType::Double:
- stream >> *static_cast<double *>(data);
- break;
- case QMetaType::QChar:
- stream >> *static_cast< NS(QChar)*>(data);
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QVariantMap:
- stream >> *static_cast< NS(QVariantMap)*>(data);
- break;
- case QMetaType::QVariantHash:
- stream >> *static_cast< NS(QVariantHash)*>(data);
- break;
- case QMetaType::QVariantList:
- stream >> *static_cast< NS(QVariantList)*>(data);
- break;
- case QMetaType::QVariant:
- stream >> *static_cast< NS(QVariant)*>(data);
- break;
- case QMetaType::QByteArrayList:
- stream >> *static_cast< NS(QByteArrayList)*>(data);
- break;
-#endif
- case QMetaType::QByteArray:
- stream >> *static_cast< NS(QByteArray)*>(data);
- break;
- case QMetaType::QString:
- stream >> *static_cast< NS(QString)*>(data);
- break;
- case QMetaType::QStringList:
- stream >> *static_cast< NS(QStringList)*>(data);
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QBitArray:
- stream >> *static_cast< NS(QBitArray)*>(data);
- break;
-#endif
- case QMetaType::QDate:
- stream >> *static_cast< NS(QDate)*>(data);
- break;
- case QMetaType::QTime:
- stream >> *static_cast< NS(QTime)*>(data);
- break;
- case QMetaType::QDateTime:
- stream >> *static_cast< NS(QDateTime)*>(data);
- break;
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QUrl:
- stream >> *static_cast< NS(QUrl)*>(data);
- break;
-#endif
- case QMetaType::QLocale:
- stream >> *static_cast< NS(QLocale)*>(data);
- break;
-#ifndef QT_NO_GEOM_VARIANT
- case QMetaType::QRect:
- stream >> *static_cast< NS(QRect)*>(data);
- break;
- case QMetaType::QRectF:
- stream >> *static_cast< NS(QRectF)*>(data);
- break;
- case QMetaType::QSize:
- stream >> *static_cast< NS(QSize)*>(data);
- break;
- case QMetaType::QSizeF:
- stream >> *static_cast< NS(QSizeF)*>(data);
- break;
- case QMetaType::QLine:
- stream >> *static_cast< NS(QLine)*>(data);
- break;
- case QMetaType::QLineF:
- stream >> *static_cast< NS(QLineF)*>(data);
- break;
- case QMetaType::QPoint:
- stream >> *static_cast< NS(QPoint)*>(data);
- break;
- case QMetaType::QPointF:
- stream >> *static_cast< NS(QPointF)*>(data);
- break;
-#endif
-#ifndef QT_NO_REGEXP
- case QMetaType::QRegExp:
- stream >> *static_cast< NS(QRegExp)*>(data);
- break;
-#endif
-#if QT_CONFIG(regularexpression)
- case QMetaType::QRegularExpression:
- stream >> *static_cast< NS(QRegularExpression)*>(data);
- break;
-#endif // QT_CONFIG(regularexpression)
-#ifndef QT_BOOTSTRAPPED
- case QMetaType::QEasingCurve:
- stream >> *static_cast< NS(QEasingCurve)*>(data);
- break;
- case QMetaType::QCborSimpleType:
- stream >> *static_cast<quint8 *>(data);
- break;
-#endif // QT_BOOTSTRAPPED
- case QMetaType::QFont:
- case QMetaType::QPixmap:
- case QMetaType::QBrush:
- case QMetaType::QColor:
- case QMetaType::QPalette:
- case QMetaType::QImage:
- case QMetaType::QPolygon:
- case QMetaType::QPolygonF:
- case QMetaType::QRegion:
- case QMetaType::QBitmap:
- case QMetaType::QCursor:
- case QMetaType::QKeySequence:
- case QMetaType::QPen:
- case QMetaType::QTextLength:
- case QMetaType::QTextFormat:
- case QMetaType::QMatrix:
- case QMetaType::QTransform:
- case QMetaType::QMatrix4x4:
- case QMetaType::QVector2D:
- case QMetaType::QVector3D:
- case QMetaType::QVector4D:
- case QMetaType::QQuaternion:
- case QMetaType::QIcon:
- if (!qMetaTypeGuiHelper)
- return false;
- qMetaTypeGuiHelper[type - FirstGuiType].loadOp(stream, data);
- break;
- case QMetaType::QSizePolicy:
- if (!qMetaTypeWidgetsHelper)
- return false;
- qMetaTypeWidgetsHelper[type - FirstWidgetsType].loadOp(stream, data);
- break;
- case QMetaType::QUuid:
- stream >> *static_cast< NS(QUuid)*>(data);
- break;
- default: {
- const QVector<QCustomTypeInfo> * const ct = customTypes();
- if (!ct)
- return false;
-
- LoadOperator loadOp = 0;
- {
- QReadLocker locker(customTypesLock());
- loadOp = ct->at(type - User).loadOp;
- }
-
- if (!loadOp)
- return false;
- loadOp(stream, data);
- break; }
- }
- return true;
+ LoadOperatorSwitch loadOp{stream, type};
+ return QMetaTypeSwitcher::switcher<bool>(loadOp, type, data);
}
#endif // QT_NO_DATASTREAM
@@ -1855,7 +1607,7 @@ void *QMetaType::create(int type, const void *copy)
QMetaType info(type);
if (int size = info.sizeOf())
return info.construct(operator new(size), copy);
- return 0;
+ return nullptr;
}
/*!
@@ -1881,14 +1633,18 @@ class TypeConstructor {
static void *Construct(const int type, void *where, const void *copy)
{
if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
- return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].constructor(where, copy) : 0;
+ return Q_LIKELY(qMetaTypeGuiHelper)
+ ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].constructor(where, copy)
+ : nullptr;
if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
- return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].constructor(where, copy) : 0;
+ return Q_LIKELY(qMetaTypeWidgetsHelper)
+ ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].constructor(where, copy)
+ : nullptr;
// This point can be reached only for known types that definition is not available, for example
// in bootstrap mode. We have no other choice then ignore it.
- return 0;
+ return nullptr;
}
};
public:
@@ -1912,7 +1668,7 @@ private:
{
QReadLocker locker(customTypesLock());
if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
- return 0;
+ return nullptr;
const auto &typeInfo = ct->at(type - QMetaType::User);
ctor = typeInfo.constructor;
tctor = typeInfo.typedConstructor;
@@ -1957,7 +1713,7 @@ private:
void *QMetaType::construct(int type, void *where, const void *copy)
{
if (!where)
- return 0;
+ return nullptr;
TypeConstructor constructor(type, where);
return QMetaTypeSwitcher::switcher<void*>(constructor, type, copy);
}
@@ -2103,7 +1859,7 @@ private:
int QMetaType::sizeOf(int type)
{
SizeOf sizeOf(type);
- return QMetaTypeSwitcher::switcher<int>(sizeOf, type, 0);
+ return QMetaTypeSwitcher::switcher<int>(sizeOf, type);
}
namespace {
@@ -2167,7 +1923,7 @@ private:
QMetaType::TypeFlags QMetaType::typeFlags(int type)
{
Flags flags(type);
- return static_cast<QMetaType::TypeFlags>(QMetaTypeSwitcher::switcher<quint32>(flags, type, 0));
+ return static_cast<QMetaType::TypeFlags>(QMetaTypeSwitcher::switcher<quint32>(flags, type));
}
#ifndef QT_BOOTSTRAPPED
@@ -2190,17 +1946,21 @@ public:
{
static const QMetaObject *MetaObject(int type) {
if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
- return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].metaObject : 0;
+ return Q_LIKELY(qMetaTypeGuiHelper)
+ ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].metaObject
+ : nullptr;
if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
- return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].metaObject : 0;
+ return Q_LIKELY(qMetaTypeWidgetsHelper)
+ ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].metaObject
+ : nullptr;
return 0;
}
};
template <typename T>
const QMetaObject *delegate(const T *) { return MetaObjectImpl<T>::MetaObject(m_type); }
- const QMetaObject *delegate(const void*) { return 0; }
- const QMetaObject *delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
+ const QMetaObject *delegate(const void*) { return nullptr; }
+ const QMetaObject *delegate(const QMetaTypeSwitcher::UnknownType*) { return nullptr; }
const QMetaObject *delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customMetaObject(m_type); }
private:
const int m_type;
@@ -2208,10 +1968,10 @@ private:
{
const QVector<QCustomTypeInfo> * const ct = customTypes();
if (Q_UNLIKELY(!ct || type < QMetaType::User))
- return 0;
+ return nullptr;
QReadLocker locker(customTypesLock());
if (Q_UNLIKELY(ct->count() <= type - QMetaType::User))
- return 0;
+ return nullptr;
return ct->at(type - QMetaType::User).metaObject;
}
};
@@ -2229,10 +1989,10 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
{
#ifndef QT_BOOTSTRAPPED
MetaObject mo(type);
- return QMetaTypeSwitcher::switcher<const QMetaObject*>(mo, type, 0);
+ return QMetaTypeSwitcher::switcher<const QMetaObject*>(mo, type);
#else
Q_UNUSED(type);
- return 0;
+ return nullptr;
#endif
}
@@ -2429,7 +2189,7 @@ private:
QMetaType QMetaType::typeInfo(const int type)
{
TypeInfo typeInfo(type);
- QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
+ QMetaTypeSwitcher::switcher<void>(typeInfo, type);
return (typeInfo.info.constructor || typeInfo.info.typedConstructor)
? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx |
(typeInfo.info.typedConstructor ? QMetaType::ConstructEx | QMetaType::DestructEx : 0))
@@ -2549,7 +2309,7 @@ void QMetaType::dtor()
void *QMetaType::createExtended(const void *copy) const
{
if (m_typeId == QMetaType::UnknownType)
- return 0;
+ return nullptr;
if (Q_UNLIKELY(m_typedConstructor && !m_constructor))
return m_typedConstructor(m_typeId, operator new(m_size), copy);
return m_constructor(operator new(m_size), copy);
@@ -2629,7 +2389,7 @@ uint QMetaType::sizeExtended() const
*/
QMetaType::TypeFlags QMetaType::flagsExtended() const
{
- return 0;
+ return { };
}
/*!
@@ -2642,7 +2402,7 @@ QMetaType::TypeFlags QMetaType::flagsExtended() const
*/
const QMetaObject *QMetaType::metaObjectExtended() const
{
- return 0;
+ return nullptr;
}
@@ -2651,7 +2411,7 @@ namespace QtPrivate
const QMetaObject *metaObjectForQWidget()
{
if (!qMetaTypeWidgetsHelper)
- return 0;
+ return nullptr;
return qMetaObjectWidgetsHelper;
}
}
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index ed7feee775..9fe2b9733b 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -570,6 +570,7 @@ public:
inline bool isValid() const;
inline bool isRegistered() const;
+ inline int id() const;
inline int sizeOf() const;
inline TypeFlags flags() const;
inline const QMetaObject *metaObject() const;
@@ -848,7 +849,7 @@ struct VariantData
const uint flags;
private:
// copy constructor allowed to be implicit to silence level 4 warning from MSVC
- VariantData &operator=(const VariantData &) Q_DECL_EQ_DELETE;
+ VariantData &operator=(const VariantData &) = delete;
};
template<typename const_iterator>
@@ -1714,12 +1715,17 @@ namespace QtPrivate {
}
};
+ // hack to delay name lookup to instantiation time by making
+ // EnableInternalData a dependent name:
+ template <typename T>
+ struct EnableInternalDataWrap;
+
template<typename T>
struct QSmartPointerConvertFunctor<QWeakPointer<T> >
{
QObject* operator()(const QWeakPointer<T> &p) const
{
- return p.data();
+ return QtPrivate::EnableInternalDataWrap<T>::internalData(p);
}
};
}
@@ -1976,7 +1982,9 @@ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
typedef QList<QVariant> QVariantList;
typedef QMap<QString, QVariant> QVariantMap;
typedef QHash<QString, QVariant> QVariantHash;
-#ifndef Q_CLANG_QDOC
+#ifdef Q_CLANG_QDOC
+class QByteArrayList;
+#else
typedef QList<QByteArray> QByteArrayList;
#endif
@@ -1991,7 +1999,7 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
static int qt_metatype_id() \
{ \
static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
- if (const int id = metatype_id.load()) \
+ if (const int id = metatype_id.loadRelaxed()) \
return id; \
const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \
Q_ASSERT(tName); \
@@ -2221,6 +2229,11 @@ inline bool QMetaType::isRegistered() const
return isValid();
}
+inline int QMetaType::id() const
+{
+ return m_typeId;
+}
+
inline void *QMetaType::create(const void *copy) const
{
// ### TODO Qt6 remove the extension
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index 94e9228778..97d6001937 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -87,7 +87,7 @@ template<> \
class QTypeModuleInfo<TYPE > \
{ \
public: \
- enum Module { \
+ enum Module : bool { \
IsCore = (((MODULE) == (QModulesPrivate::Core))), \
IsWidget = (((MODULE) == (QModulesPrivate::Widgets))), \
IsGui = (((MODULE) == (QModulesPrivate::Gui))), \
@@ -140,12 +140,12 @@ public:
/*saveOp*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Save), \
/*loadOp*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Load),
# define QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type) \
- /*saveOp*/ 0, \
- /*loadOp*/ 0,
+ /*saveOp*/ nullptr, \
+ /*loadOp*/ nullptr,
#else
# define QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type) \
- /*saveOp*/ 0, \
- /*loadOp*/ 0,
+ /*saveOp*/ nullptr, \
+ /*loadOp*/ nullptr,
# define QT_METATYPE_INTERFACE_INIT_DATASTREAM_IMPL(Type) \
QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(Type)
#endif
@@ -153,7 +153,7 @@ public:
#ifndef QT_BOOTSTRAPPED
#define METAOBJECT_DELEGATE(Type) (QtPrivate::MetaObjectForType<Type>::value())
#else
-#define METAOBJECT_DELEGATE(Type) 0
+#define METAOBJECT_DELEGATE(Type) nullptr
#endif
#define QT_METATYPE_INTERFACE_INIT_IMPL(Type, DATASTREAM_DELEGATE) \
@@ -184,11 +184,11 @@ public:
#define QT_METATYPE_INTERFACE_INIT_EMPTY() \
{ \
QT_METATYPE_INTERFACE_INIT_EMPTY_DATASTREAM_IMPL(void) \
- /*constructor*/ 0, \
- /*destructor*/ 0, \
+ /*constructor*/ nullptr, \
+ /*destructor*/ nullptr, \
/*size*/ 0, \
/*flags*/ 0, \
- /*metaObject*/ 0 , \
+ /*metaObject*/ nullptr , \
/*typedConstructor*/ nullptr, \
/*typedDestructor*/ nullptr \
}
diff --git a/src/corelib/kernel/qmetatypeswitcher_p.h b/src/corelib/kernel/qmetatypeswitcher_p.h
index 154fb8ab7f..dabc70f4b0 100644
--- a/src/corelib/kernel/qmetatypeswitcher_p.h
+++ b/src/corelib/kernel/qmetatypeswitcher_p.h
@@ -60,7 +60,7 @@ public:
class NotBuiltinType; // type is not a built-in type, but it may be a custom type or an unknown type
class UnknownType; // type not known to QMetaType system
template<class ReturnType, class DelegateObject>
- static ReturnType switcher(DelegateObject &logic, int type, const void *data);
+ static ReturnType switcher(DelegateObject &logic, int type, const void *data = nullptr);
};
diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp
index c8ad1bc43f..9a98db21d3 100644
--- a/src/corelib/kernel/qmimedata.cpp
+++ b/src/corelib/kernel/qmimedata.cpp
@@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE
static inline QString textUriListLiteral() { return QStringLiteral("text/uri-list"); }
static inline QString textHtmlLiteral() { return QStringLiteral("text/html"); }
static inline QString textPlainLiteral() { return QStringLiteral("text/plain"); }
+static inline QString textPlainUtf8Literal() { return QStringLiteral("text/plain;charset=utf-8"); }
static inline QString applicationXColorLiteral() { return QStringLiteral("application/x-color"); }
static inline QString applicationXQtImageLiteral() { return QStringLiteral("application/x-qt-image"); }
@@ -399,6 +400,10 @@ bool QMimeData::hasUrls() const
QString QMimeData::text() const
{
Q_D(const QMimeData);
+ QVariant utf8Text = d->retrieveTypedData(textPlainUtf8Literal(), QVariant::String);
+ if (!utf8Text.isNull())
+ return utf8Text.toString();
+
QVariant data = d->retrieveTypedData(textPlainLiteral(), QVariant::String);
return data.toString();
}
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 68c5460b6a..8f80be30bd 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
@@ -58,6 +58,7 @@
#include <qdebug.h>
#include <qpair.h>
#include <qvarlengtharray.h>
+#include <qscopeguard.h>
#include <qset.h>
#if QT_CONFIG(thread)
#include <qsemaphore.h>
@@ -77,6 +78,12 @@ QT_BEGIN_NAMESPACE
static int DIRECT_CONNECTION_ONLY = 0;
+Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
+
+void qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set)
+{
+ qt_signal_spy_callback_set.storeRelease(callback_set);
+}
QDynamicMetaObjectData::~QDynamicMetaObjectData()
{
@@ -146,10 +153,9 @@ static QBasicMutex _q_ObjectMutexPool[131];
* \internal
* mutex to be locked when accessing the connectionlists or the senders list
*/
-static inline QMutex *signalSlotLock(const QObject *o)
+static inline QBasicMutex *signalSlotLock(const QObject *o)
{
- return static_cast<QMutex *>(&_q_ObjectMutexPool[
- uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]);
+ return &_q_ObjectMutexPool[uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)];
}
#if QT_VERSION < 0x60000
@@ -160,39 +166,6 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
{}
#endif
-struct QConnectionSenderSwitcher {
- QObject *receiver;
- QObjectPrivate::Sender *previousSender;
- QObjectPrivate::Sender currentSender;
- bool switched;
-
- inline QConnectionSenderSwitcher() : switched(false) {}
-
- inline QConnectionSenderSwitcher(QObject *receiver, QObject *sender, int signal_absolute_id)
- {
- switchSender(receiver, sender, signal_absolute_id);
- }
-
- inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id)
- {
- this->receiver = receiver;
- currentSender.sender = sender;
- currentSender.signal = signal_absolute_id;
- currentSender.ref = 1;
- previousSender = QObjectPrivate::setCurrentSender(receiver, &currentSender);
- switched = true;
- }
-
- inline ~QConnectionSenderSwitcher()
- {
- if (switched)
- QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
- }
-private:
- Q_DISABLE_COPY(QConnectionSenderSwitcher)
-};
-
-
void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0;
void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0;
void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0;
@@ -201,6 +174,12 @@ int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QO
bool (*QAbstractDeclarativeData::isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int) = 0;
void (*QAbstractDeclarativeData::setWidgetParent)(QObject *, QObject *) = 0;
+/*!
+ \fn QObjectData::QObjectData()
+ \internal
+ */
+
+
QObjectData::~QObjectData() {}
QMetaObject *QObjectData::dynamicMetaObject() const
@@ -209,7 +188,7 @@ QMetaObject *QObjectData::dynamicMetaObject() const
}
QObjectPrivate::QObjectPrivate(int version)
- : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0)
+ : threadData(0), currentChildBeingDeleted(0)
{
#ifdef QT_BUILD_INTERNAL
// Don't check the version parameter in internal builds.
@@ -232,7 +211,6 @@ QObjectPrivate::QObjectPrivate(int version)
receiveChildEvents = true;
postedEvents = 0;
extraData = 0;
- connectedSignals[0] = connectedSignals[1] = 0;
metaObject = 0;
isWindow = false;
deleteLaterCalled = false;
@@ -244,7 +222,7 @@ QObjectPrivate::~QObjectPrivate()
if (Q_LIKELY(threadData->thread == QThread::currentThread())) {
// unregister pending timers
if (threadData->hasEventDispatcher())
- threadData->eventDispatcher.load()->unregisterTimers(q_ptr);
+ threadData->eventDispatcher.loadRelaxed()->unregisterTimers(q_ptr);
// release the timer ids back to the pool
for (int i = 0; i < extraData->runningTimers.size(); ++i)
@@ -285,59 +263,22 @@ static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int
}
}
-/*
- This vector contains the all connections from an object.
-
- Each object may have one vector containing the lists of
- connections for a given signal. The index in the vector correspond
- to the signal index. The signal index is the one returned by
- QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal).
- Negative index means connections to all signals.
-
- This vector is protected by the object mutex (signalSlotMutexes())
-
- Each Connection is also part of a 'senders' linked list. The mutex
- of the receiver must be locked when touching the pointers of this
- linked list.
-*/
-class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList>
-{
-public:
- bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse
- bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet
- int inUse; //number of functions that are currently accessing this object or its connections
- QObjectPrivate::ConnectionList allsignals;
-
- QObjectConnectionListVector()
- : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0)
- { }
-
- QObjectPrivate::ConnectionList &operator[](int at)
- {
- if (at < 0)
- return allsignals;
- return QVector<QObjectPrivate::ConnectionList>::operator[](at);
- }
-};
-
// Used by QAccessibleWidget
bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
{
Q_Q(const QObject);
int signal_index = signalIndex(signal);
- if (signal_index < 0)
+ ConnectionData *cd = connections.loadRelaxed();
+ if (signal_index < 0 || !cd)
return false;
- QMutexLocker locker(signalSlotLock(q));
- if (connectionLists) {
- if (signal_index < connectionLists->count()) {
- const QObjectPrivate::Connection *c =
- connectionLists->at(signal_index).first;
-
- while (c) {
- if (c->receiver == receiver)
- return true;
- c = c->nextConnectionList;
- }
+ QBasicMutexLocker locker(signalSlotLock(q));
+ if (signal_index < cd->signalVectorCount()) {
+ const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
+
+ while (c) {
+ if (c->receiver.loadRelaxed() == receiver)
+ return true;
+ c = c->nextConnectionList.loadRelaxed();
}
}
return false;
@@ -346,21 +287,19 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
// Used by QAccessibleWidget
QObjectList QObjectPrivate::receiverList(const char *signal) const
{
- Q_Q(const QObject);
QObjectList returnValue;
int signal_index = signalIndex(signal);
- if (signal_index < 0)
+ ConnectionData *cd = connections.loadRelaxed();
+ if (signal_index < 0 || !cd)
return returnValue;
- QMutexLocker locker(signalSlotLock(q));
- if (connectionLists) {
- if (signal_index < connectionLists->count()) {
- const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first;
-
- while (c) {
- if (c->receiver)
- returnValue << c->receiver;
- c = c->nextConnectionList;
- }
+ if (signal_index < cd->signalVectorCount()) {
+ const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
+
+ while (c) {
+ QObject *r = c->receiver.loadRelaxed();
+ if (r)
+ returnValue << r;
+ c = c->nextConnectionList.loadRelaxed();
}
}
return returnValue;
@@ -370,9 +309,12 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const
QObjectList QObjectPrivate::senderList() const
{
QObjectList returnValue;
- QMutexLocker locker(signalSlotLock(q_func()));
- for (Connection *c = senders; c; c = c->next)
- returnValue << c->sender;
+ ConnectionData *cd = connections.loadRelaxed();
+ if (cd) {
+ QBasicMutexLocker locker(signalSlotLock(q_func()));
+ for (Connection *c = cd->senders; c; c = c->next)
+ returnValue << c->sender;
+ }
return returnValue;
}
@@ -389,89 +331,197 @@ QObjectList QObjectPrivate::senderList() const
void QObjectPrivate::addConnection(int signal, Connection *c)
{
Q_ASSERT(c->sender == q_ptr);
- if (!connectionLists)
- connectionLists = new QObjectConnectionListVector();
- if (signal >= connectionLists->count())
- connectionLists->resize(signal + 1);
-
- ConnectionList &connectionList = (*connectionLists)[signal];
- if (connectionList.last) {
- connectionList.last->nextConnectionList = c;
+ ensureConnectionData();
+ ConnectionData *cd = connections.loadRelaxed();
+ cd->resizeSignalVector(signal + 1);
+
+ ConnectionList &connectionList = cd->connectionsForSignal(signal);
+ if (connectionList.last.loadRelaxed()) {
+ Q_ASSERT(connectionList.last.loadRelaxed()->receiver.loadRelaxed());
+ connectionList.last.loadRelaxed()->nextConnectionList.storeRelaxed(c);
} else {
- connectionList.first = c;
+ connectionList.first.storeRelaxed(c);
}
- connectionList.last = c;
+ c->id = ++cd->currentConnectionId;
+ c->prevConnectionList = connectionList.last.loadRelaxed();
+ connectionList.last.storeRelaxed(c);
- cleanConnectionLists();
+ QObjectPrivate *rd = QObjectPrivate::get(c->receiver.loadRelaxed());
+ rd->ensureConnectionData();
- c->prev = &(QObjectPrivate::get(c->receiver)->senders);
+ c->prev = &(rd->connections.loadRelaxed()->senders);
c->next = *c->prev;
*c->prev = c;
if (c->next)
c->next->prev = &c->next;
+}
+
+void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection *c)
+{
+ Q_ASSERT(c->receiver.loadRelaxed());
+ ConnectionList &connections = signalVector.loadRelaxed()->at(c->signal_index);
+ c->receiver.storeRelaxed(nullptr);
+ QThreadData *td = c->receiverThreadData.loadRelaxed();
+ if (td)
+ td->deref();
+ c->receiverThreadData.storeRelaxed(nullptr);
- if (signal < 0) {
- connectedSignals[0] = connectedSignals[1] = ~0;
- } else if (signal < (int)sizeof(connectedSignals) * 8) {
- connectedSignals[signal >> 5] |= (1 << (signal & 0x1f));
+#ifndef QT_NO_DEBUG
+ bool found = false;
+ for (Connection *cc = connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
+ if (cc == c) {
+ found = true;
+ break;
+ }
}
+ Q_ASSERT(found);
+#endif
+
+ // remove from the senders linked list
+ *c->prev = c->next;
+ if (c->next)
+ c->next->prev = c->prev;
+ c->prev = nullptr;
+
+ if (connections.first.loadRelaxed() == c)
+ connections.first.storeRelaxed(c->nextConnectionList.loadRelaxed());
+ if (connections.last.loadRelaxed() == c)
+ connections.last.storeRelaxed(c->prevConnectionList);
+ Q_ASSERT(signalVector.loadRelaxed()->at(c->signal_index).first.loadRelaxed() != c);
+ Q_ASSERT(signalVector.loadRelaxed()->at(c->signal_index).last.loadRelaxed() != c);
+
+ // keep c->nextConnectionList intact, as it might still get accessed by activate
+ Connection *n = c->nextConnectionList.loadRelaxed();
+ if (n)
+ n->prevConnectionList = c->prevConnectionList;
+ if (c->prevConnectionList)
+ c->prevConnectionList->nextConnectionList.storeRelaxed(n);
+ c->prevConnectionList = nullptr;
+
+ Q_ASSERT(c != orphaned.loadRelaxed());
+ // add c to orphanedConnections
+ c->nextInOrphanList = orphaned.loadRelaxed();
+ orphaned.storeRelaxed(c);
+
+#ifndef QT_NO_DEBUG
+ found = false;
+ for (Connection *cc = connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
+ if (cc == c) {
+ found = true;
+ break;
+ }
+ }
+ Q_ASSERT(!found);
+#endif
+
}
-void QObjectPrivate::cleanConnectionLists()
+void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender)
{
- if (connectionLists->dirty && !connectionLists->inUse) {
- // remove broken connections
- bool allConnected = false;
- for (int signal = -1; signal < connectionLists->count(); ++signal) {
- QObjectPrivate::ConnectionList &connectionList =
- (*connectionLists)[signal];
-
- // Set to the last entry in the connection list that was *not*
- // deleted. This is needed to update the list's last pointer
- // at the end of the cleanup.
- QObjectPrivate::Connection *last = 0;
-
- QObjectPrivate::Connection **prev = &connectionList.first;
- QObjectPrivate::Connection *c = *prev;
- bool connected = false; // whether the signal is still connected somewhere
- while (c) {
- if (c->receiver) {
- last = c;
- prev = &c->nextConnectionList;
- c = *prev;
- connected = true;
- } else {
- QObjectPrivate::Connection *next = c->nextConnectionList;
- *prev = next;
- c->deref();
- c = next;
- }
- }
+ ConnectionOrSignalVector *c = nullptr;
+ {
+ QBasicMutexLocker l(signalSlotLock(sender));
+ if (ref > 1)
+ return;
- // Correct the connection list's last pointer.
- // As conectionList.last could equal last, this could be a noop
- connectionList.last = last;
+ // Since ref == 1, no activate() is in process since we locked the mutex. That implies,
+ // that nothing can reference the orphaned connection objects anymore and they can
+ // be safely deleted
+ c = orphaned.loadRelaxed();
+ orphaned.storeRelaxed(nullptr);
+ }
+ deleteOrphaned(c);
+}
- if (!allConnected && !connected && signal >= 0
- && size_t(signal) < sizeof(connectedSignals) * 8) {
- // This signal is no longer connected
- connectedSignals[signal >> 5] &= ~(1 << (signal & 0x1f));
- } else if (signal == -1) {
- allConnected = connected;
- }
+void QObjectPrivate::ConnectionData::deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector *o)
+{
+ while (o) {
+ QObjectPrivate::ConnectionOrSignalVector *next = nullptr;
+ if (SignalVector *v = ConnectionOrSignalVector::asSignalVector(o)) {
+ next = v->nextInOrphanList;
+ free(v);
+ } else {
+ QObjectPrivate::Connection *c = static_cast<Connection *>(o);
+ next = c->nextInOrphanList;
+ Q_ASSERT(!c->receiver.loadRelaxed());
+ Q_ASSERT(!c->prev);
+ c->freeSlotObject();
+ c->deref();
}
- connectionLists->dirty = false;
+ o = next;
}
}
+/*! \internal
+
+ Returns \c true if the signal with index \a signal_index from object \a sender is connected.
+
+ \a signal_index must be the index returned by QObjectPrivate::signalIndex;
+*/
+bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) const
+{
+ if (checkDeclarative && isDeclarativeSignalConnected(signalIndex))
+ return true;
+
+ ConnectionData *cd = connections.loadRelaxed();
+ if (!cd)
+ return false;
+ SignalVector *signalVector = cd->signalVector.loadRelaxed();
+ if (!signalVector)
+ return false;
+
+ if (signalVector->at(-1).first.loadRelaxed())
+ return true;
+
+ if (signalIndex < uint(cd->signalVectorCount())) {
+ const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.loadRelaxed();
+ while (c) {
+ if (c->receiver.loadRelaxed())
+ return true;
+ c = c->nextConnectionList.loadRelaxed();
+ }
+ }
+ return false;
+}
+
+bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const
+{
+ ConnectionData *cd = connections.loadRelaxed();
+ if (!cd)
+ return false;
+ SignalVector *signalVector = cd->signalVector.loadRelaxed();
+ if (!signalVector)
+ return false;
+
+ if (signalVector->at(-1).first)
+ return true;
+
+ if (signalIndex < uint(cd->signalVectorCount())) {
+ const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first;
+ return c != nullptr;
+ }
+ return false;
+}
+
+/*!
+ \internal
+ */
+QAbstractMetaCallEvent::~QAbstractMetaCallEvent()
+{
+#if QT_CONFIG(thread)
+ if (semaphore_)
+ semaphore_->release();
+#endif
+}
+
/*!
\internal
*/
QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction,
const QObject *sender, int signalId,
int nargs, int *types, void **args, QSemaphore *semaphore)
- : QEvent(MetaCall), slotObj_(0), sender_(sender), signalId_(signalId),
- nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
+ : QAbstractMetaCallEvent(sender, signalId, semaphore),
+ slotObj_(nullptr), nargs_(nargs), types_(types), args_(args),
callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative)
{ }
@@ -480,9 +530,9 @@ QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QOb
*/
QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO, const QObject *sender, int signalId,
int nargs, int *types, void **args, QSemaphore *semaphore)
- : QEvent(MetaCall), slotObj_(slotO), sender_(sender), signalId_(signalId),
- nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
- callFunction_(0), method_offset_(0), method_relative_(ushort(-1))
+ : QAbstractMetaCallEvent(sender, signalId, semaphore),
+ slotObj_(slotO), nargs_(nargs), types_(types), args_(args),
+ callFunction_(nullptr), method_offset_(0), method_relative_(ushort(-1))
{
if (slotObj_)
slotObj_->ref();
@@ -501,10 +551,6 @@ QMetaCallEvent::~QMetaCallEvent()
free(types_);
free(args_);
}
-#if QT_CONFIG(thread)
- if (semaphore_)
- semaphore_->release();
-#endif
if (slotObj_)
slotObj_->destroyIfLastRef();
}
@@ -797,7 +843,7 @@ static bool check_parent_thread(QObject *parent,
The destructor of a parent object destroys all child objects.
- Setting \a parent to 0 constructs an object with no parent. If the
+ Setting \a parent to \nullptr constructs an object with no parent. If the
object is a widget, it will become a top-level window.
\sa parent(), findChild(), findChildren()
@@ -806,6 +852,8 @@ static bool check_parent_thread(QObject *parent,
QObject::QObject(QObject *parent)
: d_ptr(new QObjectPrivate)
{
+ Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QObject to itself");
+
Q_D(QObject);
d_ptr->q_ptr = this;
d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
@@ -834,6 +882,8 @@ QObject::QObject(QObject *parent)
QObject::QObject(QObjectPrivate &dd, QObject *parent)
: d_ptr(&dd)
{
+ Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QObject to itself");
+
Q_D(QObject);
d_ptr->q_ptr = this;
d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
@@ -894,15 +944,15 @@ QObject::~QObject()
d->wasDeleted = true;
d->blockSig = 0; // unblock signals so we always emit destroyed()
- QtSharedPointer::ExternalRefCountData *sharedRefcount = d->sharedRefcount.load();
+ QtSharedPointer::ExternalRefCountData *sharedRefcount = d->sharedRefcount.loadRelaxed();
if (sharedRefcount) {
- if (sharedRefcount->strongref.load() > 0) {
+ if (sharedRefcount->strongref.loadRelaxed() > 0) {
qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
// but continue deleting, it's too late to stop anyway
}
// indicate to all QWeakPointers that this QObject has now been deleted
- sharedRefcount->strongref.store(0);
+ sharedRefcount->strongref.storeRelaxed(0);
if (!sharedRefcount->weakref.deref())
delete sharedRefcount;
}
@@ -921,92 +971,56 @@ QObject::~QObject()
}
}
- // set ref to zero to indicate that this object has been deleted
- if (d->currentSender != 0)
- d->currentSender->ref = 0;
- d->currentSender = 0;
+ QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
+ if (cd) {
+ if (cd->currentSender) {
+ cd->currentSender->receiverDeleted();
+ cd->currentSender = nullptr;
+ }
- if (d->connectionLists || d->senders) {
- QMutex *signalSlotMutex = signalSlotLock(this);
- QMutexLocker locker(signalSlotMutex);
+ QBasicMutex *signalSlotMutex = signalSlotLock(this);
+ QBasicMutexLocker locker(signalSlotMutex);
// disconnect all receivers
- if (d->connectionLists) {
- ++d->connectionLists->inUse;
- int connectionListsCount = d->connectionLists->count();
- for (int signal = -1; signal < connectionListsCount; ++signal) {
- QObjectPrivate::ConnectionList &connectionList =
- (*d->connectionLists)[signal];
-
- while (QObjectPrivate::Connection *c = connectionList.first) {
- if (!c->receiver) {
- connectionList.first = c->nextConnectionList;
- c->deref();
- continue;
- }
+ int receiverCount = cd->signalVectorCount();
+ for (int signal = -1; signal < receiverCount; ++signal) {
+ QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal);
- QMutex *m = signalSlotLock(c->receiver);
- bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
+ while (QObjectPrivate::Connection *c = connectionList.first.loadRelaxed()) {
+ Q_ASSERT(c->receiver);
- if (c->receiver) {
- *c->prev = c->next;
- if (c->next) c->next->prev = c->prev;
- }
- c->receiver = 0;
- if (needToUnlock)
- m->unlock();
-
- connectionList.first = c->nextConnectionList;
-
- // The destroy operation must happen outside the lock
- if (c->isSlotObject) {
- c->isSlotObject = false;
- locker.unlock();
- c->slotObj->destroyIfLastRef();
- locker.relock();
- }
- c->deref();
+ QBasicMutex *m = signalSlotLock(c->receiver.loadRelaxed());
+ bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
+ if (c->receiver) {
+ cd->removeConnection(c);
+ Q_ASSERT(connectionList.first.loadRelaxed() != c);
}
+ if (needToUnlock)
+ m->unlock();
}
-
- if (!--d->connectionLists->inUse) {
- delete d->connectionLists;
- } else {
- d->connectionLists->orphaned = true;
- }
- d->connectionLists = 0;
}
/* Disconnect all senders:
- * This loop basically just does
- * for (node = d->senders; node; node = node->next) { ... }
- *
- * We need to temporarily unlock the receiver mutex to destroy the functors or to lock the
- * sender's mutex. And when the mutex is released, node->next might be destroyed by another
- * thread. That's why we set node->prev to &node, that way, if node is destroyed, node will
- * be updated.
*/
- QObjectPrivate::Connection *node = d->senders;
- while (node) {
+ while (QObjectPrivate::Connection *node = cd->senders) {
+ Q_ASSERT(node->receiver);
QObject *sender = node->sender;
// Send disconnectNotify before removing the connection from sender's connection list.
// This ensures any eventual destructor of sender will block on getting receiver's lock
// and not finish until we release it.
sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index));
- QMutex *m = signalSlotLock(sender);
- node->prev = &node;
+ QBasicMutex *m = signalSlotLock(sender);
bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
//the node has maybe been removed while the mutex was unlocked in relock?
- if (!node || node->sender != sender) {
+ if (node != cd->senders) {
// We hold the wrong mutex
Q_ASSERT(needToUnlock);
m->unlock();
continue;
}
- node->receiver = 0;
- QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists;
- if (senderLists)
- senderLists->dirty = true;
+
+ QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections.loadRelaxed();
+ Q_ASSERT(senderData);
QtPrivate::QSlotObjectBase *slotObj = nullptr;
if (node->isSlotObject) {
@@ -1014,19 +1028,24 @@ QObject::~QObject()
node->isSlotObject = false;
}
- node = node->next;
+ senderData->removeConnection(node);
if (needToUnlock)
m->unlock();
if (slotObj) {
- if (node)
- node->prev = &node;
locker.unlock();
slotObj->destroyIfLastRef();
locker.relock();
}
}
+
+ // invalidate all connections on the object and make sure
+ // activate() will skip them
+ cd->currentConnectionId.storeRelaxed(0);
}
+ if (cd && !cd->ref.deref())
+ delete cd;
+ d->connections.storeRelaxed(nullptr);
if (!d->children.isEmpty())
d->deleteChildren();
@@ -1046,7 +1065,7 @@ QObject::~QObject()
QObjectPrivate::Connection::~Connection()
{
if (ownArgumentTypes) {
- const int *v = argumentTypes.load();
+ const int *v = argumentTypes.loadRelaxed();
if (v != &DIRECT_CONNECTION_ONLY)
delete [] v;
}
@@ -1253,9 +1272,13 @@ bool QObject::event(QEvent *e)
case QEvent::MetaCall:
{
- QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e);
+ QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e);
- QConnectionSenderSwitcher sw(this, const_cast<QObject*>(mce->sender()), mce->signalId());
+ if (!d_func()->connections.loadRelaxed()) {
+ QBasicMutexLocker locker(signalSlotLock(this));
+ d_func()->ensureConnectionData();
+ }
+ QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId());
mce->placeMetaCall(this);
break;
@@ -1264,7 +1287,7 @@ bool QObject::event(QEvent *e)
case QEvent::ThreadChange: {
Q_D(QObject);
QThreadData *threadData = d->threadData;
- QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed();
if (eventDispatcher) {
QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this);
if (!timers.isEmpty()) {
@@ -1415,7 +1438,7 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
\sa signalsBlocked(), QSignalBlocker
*/
-bool QObject::blockSignals(bool block) Q_DECL_NOTHROW
+bool QObject::blockSignals(bool block) noexcept
{
Q_D(QObject);
bool previous = d->blockSig;
@@ -1499,7 +1522,7 @@ void QObject::moveToThread(QThread *targetThread)
} else if (d->threadData != currentData) {
qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
"Cannot move to target thread (%p)\n",
- currentData->thread.load(), d->threadData->thread.load(), targetData ? targetData->thread.load() : nullptr);
+ currentData->thread.loadRelaxed(), d->threadData->thread.loadRelaxed(), targetData ? targetData->thread.loadRelaxed() : nullptr);
#ifdef Q_OS_MAC
qWarning("You might be loading two sets of Qt binaries into the same process. "
@@ -1516,6 +1539,9 @@ void QObject::moveToThread(QThread *targetThread)
if (!targetData)
targetData = new QThreadData(0);
+ // make sure nobody adds/removes connections to this object while we're moving it
+ QMutexLocker l(signalSlotLock(this));
+
QOrderedMutexLocker locker(&currentData->postEventList.mutex,
&targetData->postEventList.mutex);
@@ -1561,13 +1587,35 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData
}
if (eventsMoved > 0 && targetData->hasEventDispatcher()) {
targetData->canWait = false;
- targetData->eventDispatcher.load()->wakeUp();
+ targetData->eventDispatcher.loadRelaxed()->wakeUp();
}
// the current emitting thread shouldn't restore currentSender after calling moveToThread()
- if (currentSender)
- currentSender->ref = 0;
- currentSender = 0;
+ ConnectionData *cd = connections.loadRelaxed();
+ if (cd) {
+ if (cd->currentSender) {
+ cd->currentSender->receiverDeleted();
+ cd->currentSender = nullptr;
+ }
+
+ // adjust the receiverThreadId values in the Connections
+ if (cd) {
+ auto *c = cd->senders;
+ while (c) {
+ QObject *r = c->receiver.loadRelaxed();
+ if (r) {
+ Q_ASSERT(r == q);
+ targetData->ref();
+ QThreadData *old = c->receiverThreadData.loadRelaxed();
+ if (old)
+ old->deref();
+ c->receiverThreadData.storeRelaxed(targetData);
+ }
+ c = c->next;
+ }
+ }
+
+ }
// set new thread data
targetData->ref();
@@ -1584,7 +1632,7 @@ void QObjectPrivate::_q_reregisterTimers(void *pointer)
{
Q_Q(QObject);
QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer);
- QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed();
for (int i = 0; i < timerList->size(); ++i) {
const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i);
eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, q);
@@ -1650,7 +1698,7 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
qWarning("QObject::startTimer: Timers cannot be started from another thread");
return 0;
}
- int timerId = d->threadData->eventDispatcher.load()->registerTimer(interval, timerType, this);
+ int timerId = d->threadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, this);
if (!d->extraData)
d->extraData = new QObjectPrivate::ExtraData;
d->extraData->runningTimers.append(timerId);
@@ -1716,16 +1764,16 @@ void QObject::killTimer(int id)
int at = d->extraData ? d->extraData->runningTimers.indexOf(id) : -1;
if (at == -1) {
// timer isn't owned by this object
- qWarning("QObject::killTimer(): Error: timer id %d is not valid for object %p (%s, %s), timer has not been killed",
+ qWarning("QObject::killTimer(): Error: timer id %d is not valid for object %p (%s, %ls), timer has not been killed",
id,
this,
metaObject()->className(),
- qPrintable(objectName()));
+ qUtf16Printable(objectName()));
return;
}
if (d->threadData->hasEventDispatcher())
- d->threadData->eventDispatcher.load()->unregisterTimer(id);
+ d->threadData->eventDispatcher.loadRelaxed()->unregisterTimer(id);
d->extraData->runningTimers.remove(at);
QAbstractEventDispatcherPrivate::releaseTimerId(id);
@@ -1769,7 +1817,7 @@ void QObject::killTimer(int id)
\fn template<typename T> T *QObject::findChild(const QString &name, Qt::FindChildOptions options) const
Returns the child of this object that can be cast into type T and
- that is called \a name, or 0 if there is no such object.
+ that is called \a name, or \nullptr if there is no such object.
Omitting the \a name argument causes all object names to be matched.
The search is performed recursively, unless \a options specifies the
option FindDirectChildrenOnly.
@@ -1830,12 +1878,15 @@ void QObject::killTimer(int id)
/*!
\fn template<typename T> QList<T> QObject::findChildren(const QRegExp &regExp, Qt::FindChildOptions options) const
\overload findChildren()
+ \obsolete
Returns the children of this object that can be cast to type T
and that have names matching the regular expression \a regExp,
or an empty list if there are no such objects.
The search is performed recursively, unless \a options specifies the
option FindDirectChildrenOnly.
+
+ Use the findChildren overload taking a QRegularExpression instead.
*/
/*!
@@ -2023,8 +2074,25 @@ void QObjectPrivate::deleteChildren()
void QObjectPrivate::setParent_helper(QObject *o)
{
Q_Q(QObject);
+ Q_ASSERT_X(q != o, Q_FUNC_INFO, "Cannot parent a QObject to itself");
+#ifdef QT_DEBUG
+ const auto checkForParentChildLoops = qScopeGuard([&](){
+ int depth = 0;
+ auto p = parent;
+ while (p) {
+ if (++depth == CheckForParentChildLoopsWarnDepth) {
+ qWarning("QObject %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
+ "this is undefined behavior",
+ q, q->metaObject()->className(), qPrintable(q->objectName()));
+ }
+ p = p->parent();
+ }
+ });
+#endif
+
if (o == parent)
return;
+
if (parent) {
QObjectPrivate *parentD = parent->d_func();
if (parentD->isDeletingChildren && wasDeleted
@@ -2154,7 +2222,8 @@ void QObject::removeEventFilter(QObject *obj)
\fn void QObject::destroyed(QObject *obj)
This signal is emitted immediately before the object \a obj is
- destroyed, and can not be blocked.
+ destroyed, after any instances of QPointer have been notified,
+ and cannot be blocked.
All the objects's children are destroyed immediately after this
signal is emitted.
@@ -2372,13 +2441,14 @@ QObject *QObject::sender() const
{
Q_D(const QObject);
- QMutexLocker locker(signalSlotLock(this));
- if (!d->currentSender)
- return 0;
+ QBasicMutexLocker locker(signalSlotLock(this));
+ QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
+ if (!cd || !cd->currentSender)
+ return nullptr;
- for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
- if (c->sender == d->currentSender->sender)
- return d->currentSender->sender;
+ for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) {
+ if (c->sender == cd->currentSender->sender)
+ return cd->currentSender->sender;
}
return 0;
@@ -2413,14 +2483,15 @@ int QObject::senderSignalIndex() const
{
Q_D(const QObject);
- QMutexLocker locker(signalSlotLock(this));
- if (!d->currentSender)
+ QBasicMutexLocker locker(signalSlotLock(this));
+ QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
+ if (!cd || !cd->currentSender)
return -1;
- for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
- if (c->sender == d->currentSender->sender) {
+ for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) {
+ if (c->sender == cd->currentSender->sender) {
// Convert from signal range to method range
- return QMetaObjectPrivate::signal(c->sender->metaObject(), d->currentSender->signal).methodIndex();
+ return QMetaObjectPrivate::signal(c->sender->metaObject(), cd->currentSender->signal).methodIndex();
}
}
@@ -2476,15 +2547,13 @@ int QObject::receivers(const char *signal) const
signal_index);
}
- QMutexLocker locker(signalSlotLock(this));
- if (d->connectionLists) {
- if (signal_index < d->connectionLists->count()) {
- const QObjectPrivate::Connection *c =
- d->connectionLists->at(signal_index).first;
- while (c) {
- receivers += c->receiver ? 1 : 0;
- c = c->nextConnectionList;
- }
+ QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
+ QBasicMutexLocker locker(signalSlotLock(this));
+ if (cd && signal_index < cd->signalVectorCount()) {
+ const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
+ while (c) {
+ receivers += c->receiver.loadRelaxed() ? 1 : 0;
+ c = c->nextConnectionList.loadRelaxed();
}
}
}
@@ -2524,22 +2593,8 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const
signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj);
- QMutexLocker locker(signalSlotLock(this));
- if (d->connectionLists) {
- if (signalIndex < sizeof(d->connectedSignals) * 8 && !d->connectionLists->dirty)
- return d->isSignalConnected(signalIndex);
-
- if (signalIndex < uint(d->connectionLists->count())) {
- const QObjectPrivate::Connection *c =
- d->connectionLists->at(signalIndex).first;
- while (c) {
- if (c->receiver)
- return true;
- c = c->nextConnectionList;
- }
- }
- }
- return d->isDeclarativeSignalConnected(signalIndex);
+ QBasicMutexLocker locker(signalSlotLock(this));
+ return d->isSignalConnected(signalIndex, true);
}
/*!
@@ -2936,8 +2991,8 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
0 may be used as a wildcard, meaning "any signal", "any receiving
object", or "any slot in the receiving object", respectively.
- The \a sender may never be 0. (You cannot disconnect signals from
- more than one object in a single call.)
+ The \a sender may never be \nullptr. (You cannot disconnect signals
+ from more than one object in a single call.)
If \a signal is 0, it disconnects \a receiver and \a method from
any signal. If not, only the specified signal is disconnected.
@@ -2948,8 +3003,8 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
If \a method is 0, it disconnects anything that is connected to \a
receiver. If not, only slots named \a method will be disconnected,
- and all other slots are left alone. The \a method must be 0 if \a
- receiver is left out, so you cannot disconnect a
+ and all other slots are left alone. The \a method must be \nullptr
+ if \a receiver is left out, so you cannot disconnect a
specifically-named slot on all objects.
\sa connect()
@@ -3288,7 +3343,7 @@ QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_i
\internal
Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
- method_index is relative to the rmeta metaobject, if rmeta is null, then it is absolute index
+ method_index is relative to the rmeta metaobject, if rmeta is \nullptr, then it is absolute index
the QObjectPrivate::Connection* has a refcount of 2, so it must be passed to a QMetaObject::Connection
*/
@@ -3302,24 +3357,22 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
int method_offset = rmeta ? rmeta->methodOffset() : 0;
Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6);
- QObjectPrivate::StaticMetaCallFunction callFunction =
- rmeta ? rmeta->d.static_metacall : 0;
+ QObjectPrivate::StaticMetaCallFunction callFunction = rmeta ? rmeta->d.static_metacall : nullptr;
QOrderedMutexLocker locker(signalSlotLock(sender),
signalSlotLock(receiver));
- if (type & Qt::UniqueConnection) {
- QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
- if (connectionLists && connectionLists->count() > signal_index) {
- const QObjectPrivate::Connection *c2 =
- (*connectionLists)[signal_index].first;
+ QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.loadRelaxed();
+ if (type & Qt::UniqueConnection && scd) {
+ if (scd->signalVectorCount() > signal_index) {
+ const QObjectPrivate::Connection *c2 = scd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
int method_index_absolute = method_index + method_offset;
while (c2) {
- if (!c2->isSlotObject && c2->receiver == receiver && c2->method() == method_index_absolute)
- return 0;
- c2 = c2->nextConnectionList;
+ if (!c2->isSlotObject && c2->receiver.loadRelaxed() == receiver && c2->method() == method_index_absolute)
+ return nullptr;
+ c2 = c2->nextConnectionList.loadRelaxed();
}
}
type &= Qt::UniqueConnection - 1;
@@ -3328,13 +3381,15 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
c->sender = s;
c->signal_index = signal_index;
- c->receiver = r;
+ c->receiver.storeRelaxed(r);
+ QThreadData *td = r->d_func()->threadData;
+ td->ref();
+ c->receiverThreadData.storeRelaxed(td);
c->method_relative = method_index;
c->method_offset = method_offset;
c->connectionType = type;
c->isSlotObject = false;
- c->argumentTypes.store(types);
- c->nextConnectionList = 0;
+ c->argumentTypes.storeRelaxed(types);
c->callFunction = callFunction;
QObjectPrivate::get(s)->addConnection(signal_index, c.data());
@@ -3378,49 +3433,40 @@ bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
/*!
\internal
- Helper function to remove the connection from the senders list and setting the receivers to 0
+ Helper function to remove the connection from the senders list and set the receivers to \nullptr
*/
-bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c,
+bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex,
const QObject *receiver, int method_index, void **slot,
- QMutex *senderMutex, DisconnectType disconnectType)
+ QBasicMutex *senderMutex, DisconnectType disconnectType)
{
bool success = false;
+
+ auto &connectionList = connections->connectionsForSignal(signalIndex);
+ auto *c = connectionList.first.loadRelaxed();
while (c) {
- if (c->receiver
- && (receiver == 0 || (c->receiver == receiver
+ QObject *r = c->receiver.loadRelaxed();
+ if (r && (receiver == nullptr || (r == receiver
&& (method_index < 0 || (!c->isSlotObject && c->method() == method_index))
- && (slot == 0 || (c->isSlotObject && c->slotObj->compare(slot)))))) {
+ && (slot == nullptr || (c->isSlotObject && c->slotObj->compare(slot)))))) {
bool needToUnlock = false;
- QMutex *receiverMutex = 0;
- if (c->receiver) {
- receiverMutex = signalSlotLock(c->receiver);
+ QBasicMutex *receiverMutex = nullptr;
+ if (r) {
+ receiverMutex = signalSlotLock(r);
// need to relock this receiver and sender in the correct order
needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex);
}
- if (c->receiver) {
- *c->prev = c->next;
- if (c->next)
- c->next->prev = c->prev;
- }
+ if (c->receiver.loadRelaxed())
+ connections->removeConnection(c);
if (needToUnlock)
receiverMutex->unlock();
- c->receiver = 0;
-
- if (c->isSlotObject) {
- c->isSlotObject = false;
- senderMutex->unlock();
- c->slotObj->destroyIfLastRef();
- senderMutex->lock();
- }
-
success = true;
if (disconnectType == DisconnectOne)
return success;
}
- c = c->nextConnectionList;
+ c = c->nextConnectionList.loadRelaxed();
}
return success;
}
@@ -3439,43 +3485,34 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender,
QObject *s = const_cast<QObject *>(sender);
- QMutex *senderMutex = signalSlotLock(sender);
- QMutexLocker locker(senderMutex);
+ QBasicMutex *senderMutex = signalSlotLock(sender);
+ QBasicMutexLocker locker(senderMutex);
- QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
- if (!connectionLists)
+ QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.loadRelaxed();
+ if (!scd)
return false;
- // prevent incoming connections changing the connectionLists while unlocked
- ++connectionLists->inUse;
-
bool success = false;
- if (signal_index < 0) {
- // remove from all connection lists
- for (int sig_index = -1; sig_index < connectionLists->count(); ++sig_index) {
- QObjectPrivate::Connection *c =
- (*connectionLists)[sig_index].first;
- if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) {
- success = true;
- connectionLists->dirty = true;
+ {
+ // prevent incoming connections changing the connections->receivers while unlocked
+ QObjectPrivate::ConnectionDataPointer connections(scd);
+
+ if (signal_index < 0) {
+ // remove from all connection lists
+ for (int sig_index = -1; sig_index < scd->signalVectorCount(); ++sig_index) {
+ if (disconnectHelper(connections.data(), sig_index, receiver, method_index, slot, senderMutex, disconnectType))
+ success = true;
}
- }
- } else if (signal_index < connectionLists->count()) {
- QObjectPrivate::Connection *c =
- (*connectionLists)[signal_index].first;
- if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) {
- success = true;
- connectionLists->dirty = true;
+ } else if (signal_index < scd->signalVectorCount()) {
+ if (disconnectHelper(connections.data(), signal_index, receiver, method_index, slot, senderMutex, disconnectType))
+ success = true;
}
}
- --connectionLists->inUse;
- Q_ASSERT(connectionLists->inUse >= 0);
- if (connectionLists->orphaned && !connectionLists->inUse)
- delete connectionLists;
-
locker.unlock();
if (success) {
+ scd->cleanOrphanedConnections(s);
+
QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
if (smethod.isValid())
s->disconnectNotify(smethod);
@@ -3591,10 +3628,9 @@ void QMetaObject::connectSlotsByName(QObject *o)
\a signal must be in the signal index range (see QObjectPrivate::signalIndex()).
*/
-static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv,
- QMutexLocker &locker)
+static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
{
- const int *argumentTypes = c->argumentTypes.load();
+ const int *argumentTypes = c->argumentTypes.loadRelaxed();
if (!argumentTypes) {
QMetaMethod m = QMetaObjectPrivate::signal(sender->metaObject(), signal);
argumentTypes = queuedConnectionTypes(m.parameterTypes());
@@ -3603,7 +3639,7 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
if (!c->argumentTypes.testAndSetOrdered(0, argumentTypes)) {
if (argumentTypes != &DIRECT_CONNECTION_ONLY)
delete [] argumentTypes;
- argumentTypes = c->argumentTypes.load();
+ argumentTypes = c->argumentTypes.loadRelaxed();
}
}
if (argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
@@ -3622,129 +3658,109 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
for (int n = 1; n < nargs; ++n)
types[n] = argumentTypes[n-1];
- locker.unlock();
for (int n = 1; n < nargs; ++n)
args[n] = QMetaType::create(types[n], argv[n]);
- locker.relock();
-
- if (!c->receiver) {
- locker.unlock();
- // we have been disconnected while the mutex was unlocked
- for (int n = 1; n < nargs; ++n)
- QMetaType::destroy(types[n], args[n]);
- free(types);
- free(args);
- locker.relock();
- return;
- }
+ }
+
+ QBasicMutexLocker locker(signalSlotLock(c->receiver.loadRelaxed()));
+ if (!c->receiver.loadRelaxed()) {
+ // the connection has been disconnected before we got the lock
+ locker.unlock();
+ for (int n = 1; n < nargs; ++n)
+ QMetaType::destroy(types[n], args[n]);
+ free(types);
+ free(args);
+ return;
}
QMetaCallEvent *ev = c->isSlotObject ?
new QMetaCallEvent(c->slotObj, sender, signal, nargs, types, args) :
new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs, types, args);
- QCoreApplication::postEvent(c->receiver, ev);
+ QCoreApplication::postEvent(c->receiver.loadRelaxed(), ev);
}
-/*!
- \internal
- */
-void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
- void **argv)
+template <bool callbacks_enabled>
+void doActivate(QObject *sender, int signal_index, void **argv)
{
- activate(sender, QMetaObjectPrivate::signalOffset(m), local_signal_index, argv);
-}
+ QObjectPrivate *sp = QObjectPrivate::get(sender);
-/*!
- \internal
- */
-void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
-{
- int signal_index = signalOffset + local_signal_index;
-
- if (sender->d_func()->blockSig)
+ if (sp->blockSig)
return;
Q_TRACE_SCOPE(QMetaObject_activate, sender, signal_index);
- if (sender->d_func()->isDeclarativeSignalConnected(signal_index)
+ if (sp->isDeclarativeSignalConnected(signal_index)
&& QAbstractDeclarativeData::signalEmitted) {
Q_TRACE_SCOPE(QMetaObject_activate_declarative_signal, sender, signal_index);
- QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender,
+ QAbstractDeclarativeData::signalEmitted(sp->declarativeData, sender,
signal_index, argv);
}
- if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false)
- && !qt_signal_spy_callback_set.signal_begin_callback
- && !qt_signal_spy_callback_set.signal_end_callback) {
- // The possible declarative connection is done, and nothing else is connected, so:
+ const QSignalSpyCallbackSet *signal_spy_set = callbacks_enabled ? qt_signal_spy_callback_set.loadAcquire() : nullptr;
+
+ void *empty_argv[] = { nullptr };
+ if (!argv)
+ argv = empty_argv;
+
+ if (!sp->maybeSignalConnected(signal_index)) {
+ // The possible declarative connection is done, and nothing else is connected
+ if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)
+ signal_spy_set->signal_begin_callback(sender, signal_index, argv);
+ if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
+ signal_spy_set->signal_end_callback(sender, signal_index);
return;
}
- void *empty_argv[] = { 0 };
- if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
- qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index,
- argv ? argv : empty_argv);
- }
+ if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)
+ signal_spy_set->signal_begin_callback(sender, signal_index, argv);
+ bool senderDeleted = false;
{
- QMutexLocker locker(signalSlotLock(sender));
- struct ConnectionListsRef {
- QObjectConnectionListVector *connectionLists;
- ConnectionListsRef(QObjectConnectionListVector *connectionLists) : connectionLists(connectionLists)
- {
- if (connectionLists)
- ++connectionLists->inUse;
- }
- ~ConnectionListsRef()
- {
- if (!connectionLists)
- return;
-
- --connectionLists->inUse;
- Q_ASSERT(connectionLists->inUse >= 0);
- if (connectionLists->orphaned) {
- if (!connectionLists->inUse)
- delete connectionLists;
- }
- }
-
- QObjectConnectionListVector *operator->() const { return connectionLists; }
- };
- ConnectionListsRef connectionLists = sender->d_func()->connectionLists;
- if (!connectionLists.connectionLists) {
- locker.unlock();
- if (qt_signal_spy_callback_set.signal_end_callback != 0)
- qt_signal_spy_callback_set.signal_end_callback(sender, signal_index);
- return;
- }
+ Q_ASSERT(sp->connections);
+ QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed());
+ QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed();
const QObjectPrivate::ConnectionList *list;
- if (signal_index < connectionLists->count())
- list = &connectionLists->at(signal_index);
+ if (signal_index < signalVector->count())
+ list = &signalVector->at(signal_index);
else
- list = &connectionLists->allsignals;
+ list = &signalVector->at(-1);
Qt::HANDLE currentThreadId = QThread::currentThreadId();
+ bool inSenderThread = currentThreadId == QObjectPrivate::get(sender)->threadData->threadId.loadRelaxed();
+ // We need to check against the highest connection id to ensure that signals added
+ // during the signal emission are not emitted in this emission.
+ uint highestConnectionId = connections->currentConnectionId.loadRelaxed();
do {
- QObjectPrivate::Connection *c = list->first;
- if (!c) continue;
- // We need to check against last here to ensure that signals added
- // during the signal emission are not emitted in this emission.
- QObjectPrivate::Connection *last = list->last;
+ QObjectPrivate::Connection *c = list->first.loadRelaxed();
+ if (!c)
+ continue;
do {
- if (!c->receiver)
+ QObject * const receiver = c->receiver.loadRelaxed();
+ if (!receiver)
+ continue;
+
+ QThreadData *td = c->receiverThreadData.loadRelaxed();
+ if (!td)
continue;
- QObject * const receiver = c->receiver;
- const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId.load();
+ bool receiverInSameThread;
+ if (inSenderThread) {
+ receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();
+ } else {
+ // need to lock before reading the threadId, because moveToThread() could interfere
+ QMutexLocker lock(signalSlotLock(receiver));
+ receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();
+ }
+
// determine if this connection should be sent immediately or
// put into the event queue
if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
|| (c->connectionType == Qt::QueuedConnection)) {
- queued_activate(sender, signal_index, c, argv ? argv : empty_argv, locker);
+ queued_activate(sender, signal_index, c, argv);
continue;
#if QT_CONFIG(thread)
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
@@ -3755,94 +3771,105 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
receiver->metaObject()->className(), receiver);
}
QSemaphore semaphore;
- QMetaCallEvent *ev = c->isSlotObject ?
- new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv ? argv : empty_argv, &semaphore) :
- new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_index, 0, 0, argv ? argv : empty_argv, &semaphore);
- QCoreApplication::postEvent(receiver, ev);
- locker.unlock();
+ {
+ QBasicMutexLocker locker(signalSlotLock(sender));
+ if (!c->receiver)
+ continue;
+ QMetaCallEvent *ev = c->isSlotObject ?
+ new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv, &semaphore) :
+ new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_index, 0, 0, argv, &semaphore);
+ QCoreApplication::postEvent(receiver, ev);
+ }
semaphore.acquire();
- locker.relock();
continue;
#endif
}
- QConnectionSenderSwitcher sw;
+ QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index);
- if (receiverInSameThread) {
- sw.switchSender(receiver, sender, signal_index);
- }
if (c->isSlotObject) {
c->slotObj->ref();
QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj);
- locker.unlock();
{
Q_TRACE_SCOPE(QMetaObject_activate_slot_functor, obj.data());
- obj->call(receiver, argv ? argv : empty_argv);
+ obj->call(receiver, argv);
}
-
- // Make sure the slot object gets destroyed before the mutex is locked again, as the
- // destructor of the slot object might also lock a mutex from the signalSlotLock() mutex pool,
- // and that would deadlock if the pool happens to return the same mutex.
- obj.reset();
-
- locker.relock();
} else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
//we compare the vtable to make sure we are not in the destructor of the object.
- const int methodIndex = c->method();
const int method_relative = c->method_relative;
const auto callFunction = c->callFunction;
- locker.unlock();
- if (qt_signal_spy_callback_set.slot_begin_callback != 0)
- qt_signal_spy_callback_set.slot_begin_callback(receiver, methodIndex, argv ? argv : empty_argv);
+ const int methodIndex = (Q_HAS_TRACEPOINTS || callbacks_enabled) ? c->method() : 0;
+ if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr)
+ signal_spy_set->slot_begin_callback(receiver, methodIndex, argv);
{
Q_TRACE_SCOPE(QMetaObject_activate_slot, receiver, methodIndex);
- callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv);
+ callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv);
}
- if (qt_signal_spy_callback_set.slot_end_callback != 0)
- qt_signal_spy_callback_set.slot_end_callback(receiver, methodIndex);
- locker.relock();
+ if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr)
+ signal_spy_set->slot_end_callback(receiver, methodIndex);
} else {
const int method = c->method_relative + c->method_offset;
- locker.unlock();
- if (qt_signal_spy_callback_set.slot_begin_callback != 0) {
- qt_signal_spy_callback_set.slot_begin_callback(receiver,
- method,
- argv ? argv : empty_argv);
+ if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) {
+ signal_spy_set->slot_begin_callback(receiver, method, argv);
}
{
Q_TRACE_SCOPE(QMetaObject_activate_slot, receiver, method);
- metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ QMetaObject::metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv);
}
- if (qt_signal_spy_callback_set.slot_end_callback != 0)
- qt_signal_spy_callback_set.slot_end_callback(receiver, method);
-
- locker.relock();
+ if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr)
+ signal_spy_set->slot_end_callback(receiver, method);
}
+ } while ((c = c->nextConnectionList.loadRelaxed()) != nullptr && c->id <= highestConnectionId);
- if (connectionLists->orphaned)
- break;
- } while (c != last && (c = c->nextConnectionList) != 0);
-
- if (connectionLists->orphaned)
- break;
- } while (list != &connectionLists->allsignals &&
+ } while (list != &signalVector->at(-1) &&
//start over for all signals;
- ((list = &connectionLists->allsignals), true));
+ ((list = &signalVector->at(-1)), true));
+ if (connections->currentConnectionId.loadRelaxed() == 0)
+ senderDeleted = true;
}
+ if (!senderDeleted)
+ sp->connections.loadRelaxed()->cleanOrphanedConnections(sender);
+
+ if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
+ signal_spy_set->signal_end_callback(sender, signal_index);
+}
+
+/*!
+ \internal
+ */
+void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
+ void **argv)
+{
+ int signal_index = local_signal_index + QMetaObjectPrivate::signalOffset(m);
- if (qt_signal_spy_callback_set.signal_end_callback != 0)
- qt_signal_spy_callback_set.signal_end_callback(sender, signal_index);
+ if (Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()))
+ doActivate<true>(sender, signal_index, argv);
+ else
+ doActivate<false>(sender, signal_index, argv);
}
/*!
\internal
+ */
+void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
+{
+ int signal_index = signalOffset + local_signal_index;
+
+ if (Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()))
+ doActivate<true>(sender, signal_index, argv);
+ else
+ doActivate<false>(sender, signal_index, argv);
+ }
+
+/*!
+ \internal
signal_index comes from indexOfMethod()
*/
void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
@@ -3855,12 +3882,12 @@ void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
/*!
\internal
- Returns the signal index used in the internal connectionLists vector.
+ Returns the signal index used in the internal connections->receivers vector.
It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod
while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots.
- If \a meta is not 0, it is set to the meta-object where the signal was found.
+ If \a meta is not \nullptr, it is set to the meta-object where the signal was found.
*/
int QObjectPrivate::signalIndex(const char *signalName,
const QMetaObject **meta) const
@@ -4038,6 +4065,7 @@ static void dumpRecursive(int level, const QObject *object)
}
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
/*!
\overload
\obsolete
@@ -4051,6 +4079,7 @@ void QObject::dumpObjectTree()
{
const_cast<const QObject *>(this)->dumpObjectTree();
}
+#endif
/*!
Dumps a tree of children to the debug output.
@@ -4065,6 +4094,7 @@ void QObject::dumpObjectTree() const
dumpRecursive(0, this);
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
/*!
\overload
\obsolete
@@ -4079,6 +4109,7 @@ void QObject::dumpObjectInfo()
{
const_cast<const QObject *>(this)->dumpObjectInfo();
}
+#endif
/*!
Dumps information about signal connections, etc. for this object
@@ -4095,37 +4126,40 @@ void QObject::dumpObjectInfo() const
objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
Q_D(const QObject);
- QMutexLocker locker(signalSlotLock(this));
+ QBasicMutexLocker locker(signalSlotLock(this));
// first, look for connections where this object is the sender
qDebug(" SIGNALS OUT");
- if (d->connectionLists) {
- for (int signal_index = 0; signal_index < d->connectionLists->count(); ++signal_index) {
+ QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
+ if (cd && cd->signalVectorCount()) {
+ QObjectPrivate::SignalVector *signalVector = cd->signalVector.loadRelaxed();
+ for (int signal_index = 0; signal_index < signalVector->count(); ++signal_index) {
+ const QObjectPrivate::Connection *c = signalVector->at(signal_index).first.loadRelaxed();
+ if (!c)
+ continue;
const QMetaMethod signal = QMetaObjectPrivate::signal(metaObject(), signal_index);
qDebug(" signal: %s", signal.methodSignature().constData());
// receivers
- const QObjectPrivate::Connection *c =
- d->connectionLists->at(signal_index).first;
while (c) {
- if (!c->receiver) {
+ if (!c->receiver.loadRelaxed()) {
qDebug(" <Disconnected receiver>");
- c = c->nextConnectionList;
+ c = c->nextConnectionList.loadRelaxed();
continue;
}
if (c->isSlotObject) {
qDebug(" <functor or function pointer>");
- c = c->nextConnectionList;
+ c = c->nextConnectionList.loadRelaxed();
continue;
}
- const QMetaObject *receiverMetaObject = c->receiver->metaObject();
+ const QMetaObject *receiverMetaObject = c->receiver.loadRelaxed()->metaObject();
const QMetaMethod method = receiverMetaObject->method(c->method());
qDebug(" --> %s::%s %s",
receiverMetaObject->className(),
- c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
+ c->receiver.loadRelaxed()->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver.loadRelaxed()->objectName()),
method.methodSignature().constData());
- c = c->nextConnectionList;
+ c = c->nextConnectionList.loadRelaxed();
}
}
} else {
@@ -4135,8 +4169,8 @@ void QObject::dumpObjectInfo() const
// now look for connections where this object is the receiver
qDebug(" SIGNALS IN");
- if (d->senders) {
- for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) {
+ if (cd && cd->senders) {
+ for (QObjectPrivate::Connection *s = cd->senders; s; s = s->next) {
QByteArray slotName = QByteArrayLiteral("<unknown>");
if (!s->isSlotObject) {
const QMetaMethod slot = metaObject()->method(s->method());
@@ -4163,6 +4197,11 @@ uint QObject::registerUserData()
}
/*!
+ \fn QObjectUserData::QObjectUserData()
+ \internal
+ */
+
+/*!
\internal
*/
QObjectUserData::~QObjectUserData()
@@ -4871,18 +4910,17 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
QOrderedMutexLocker locker(signalSlotLock(sender),
signalSlotLock(receiver));
- if (type & Qt::UniqueConnection && slot) {
- QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
- if (connectionLists && connectionLists->count() > signal_index) {
- const QObjectPrivate::Connection *c2 =
- (*connectionLists)[signal_index].first;
+ if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.loadRelaxed()) {
+ QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.loadRelaxed();
+ if (connections->signalVectorCount() > signal_index) {
+ const QObjectPrivate::Connection *c2 = connections->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
while (c2) {
- if (c2->receiver == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) {
+ if (c2->receiver.loadRelaxed() == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) {
slotObj->destroyIfLastRef();
return QMetaObject::Connection();
}
- c2 = c2->nextConnectionList;
+ c2 = c2->nextConnectionList.loadRelaxed();
}
}
type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection);
@@ -4891,12 +4929,15 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
c->sender = s;
c->signal_index = signal_index;
- c->receiver = r;
+ QThreadData *td = r->d_func()->threadData;
+ td->ref();
+ c->receiverThreadData.storeRelaxed(td);
+ c->receiver.storeRelaxed(r);
c->slotObj = slotObj;
c->connectionType = type;
c->isSlotObject = true;
if (types) {
- c->argumentTypes.store(types);
+ c->argumentTypes.storeRelaxed(types);
c->ownArgumentTypes = false;
}
@@ -4923,35 +4964,35 @@ bool QObject::disconnect(const QMetaObject::Connection &connection)
{
QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(connection.d_ptr);
- if (!c || !c->receiver)
+ if (!c)
+ return false;
+ QObject *receiver = c->receiver.loadRelaxed();
+ if (!receiver)
return false;
- QMutex *senderMutex = signalSlotLock(c->sender);
- QMutex *receiverMutex = signalSlotLock(c->receiver);
+ QBasicMutex *senderMutex = signalSlotLock(c->sender);
+ QBasicMutex *receiverMutex = signalSlotLock(receiver);
+ QObjectPrivate::ConnectionData *connections;
{
QOrderedMutexLocker locker(senderMutex, receiverMutex);
- QObjectConnectionListVector *connectionLists = QObjectPrivate::get(c->sender)->connectionLists;
- Q_ASSERT(connectionLists);
- connectionLists->dirty = true;
+ // load receiver once again and recheck to ensure nobody else has removed the connection in the meantime
+ receiver = c->receiver.loadRelaxed();
+ if (!receiver)
+ return false;
- *c->prev = c->next;
- if (c->next)
- c->next->prev = c->prev;
- c->receiver = 0;
+ connections = QObjectPrivate::get(c->sender)->connections.loadRelaxed();
+ Q_ASSERT(connections);
+ connections->removeConnection(c);
}
- // destroy the QSlotObject, if possible
- if (c->isSlotObject) {
- c->slotObj->destroyIfLastRef();
- c->isSlotObject = false;
- }
+ connections->cleanOrphanedConnections(c->sender);
c->sender->disconnectNotify(QMetaObjectPrivate::signal(c->sender->metaObject(),
c->signal_index));
- const_cast<QMetaObject::Connection &>(connection).d_ptr = 0;
+ const_cast<QMetaObject::Connection &>(connection).d_ptr = nullptr;
c->deref(); // has been removed from the QMetaObject::Connection object
return true;
@@ -4993,8 +5034,8 @@ bool QObject::disconnect(const QMetaObject::Connection &connection)
0 may be used as a wildcard, meaning "any signal", "any receiving
object", or "any slot in the receiving object", respectively.
- The \a sender may never be 0. (You cannot disconnect signals from
- more than one object in a single call.)
+ The \a sender may never be \nullptr. (You cannot disconnect signals
+ from more than one object in a single call.)
If \a signal is 0, it disconnects \a receiver and \a method from
any signal. If not, only the specified signal is disconnected.
@@ -5005,8 +5046,8 @@ bool QObject::disconnect(const QMetaObject::Connection &connection)
If \a method is 0, it disconnects anything that is connected to \a
receiver. If not, only slots named \a method will be disconnected,
- and all other slots are left alone. The \a method must be 0 if \a
- receiver is left out, so you cannot disconnect a
+ and all other slots are left alone. The \a method must be \nullptr
+ if \a receiver is left out, so you cannot disconnect a
specifically-named slot on all objects.
\note It is not possible to use this overload to diconnect signals
@@ -5133,7 +5174,7 @@ bool QMetaObject::Connection::isConnected_helper() const
Q_ASSERT(d_ptr); // we're only called from operator RestrictedBool() const
QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(d_ptr);
- return c->receiver;
+ return c->receiver.loadRelaxed();
}
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index aac9bcdee9..7f72b69c1a 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -93,7 +93,9 @@ Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QRegular
Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options);
class Q_CORE_EXPORT QObjectData {
+ Q_DISABLE_COPY(QObjectData)
public:
+ QObjectData() = default;
virtual ~QObjectData() = 0;
QObject *q_ptr;
QObject *parent;
@@ -111,12 +113,17 @@ public:
int postedEvents;
QDynamicMetaObjectData *metaObject;
QMetaObject *dynamicMetaObject() const;
+
+#ifdef QT_DEBUG
+ enum { CheckForParentChildLoopsWarnDepth = 4096 };
+#endif
};
class Q_CORE_EXPORT QObject
{
Q_OBJECT
+
Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)
Q_DECLARE_PRIVATE(QObject)
@@ -127,7 +134,7 @@ public:
virtual bool event(QEvent *event);
virtual bool eventFilter(QObject *watched, QEvent *event);
-#if defined(QT_NO_TRANSLATION)
+#if defined(QT_NO_TRANSLATION) || defined(Q_CLANG_QDOC)
static QString tr(const char *sourceText, const char * = nullptr, int = -1)
{ return QString::fromUtf8(sourceText); }
#if QT_DEPRECATED_SINCE(5, 0)
@@ -142,8 +149,8 @@ public:
inline bool isWidgetType() const { return d_ptr->isWidget; }
inline bool isWindowType() const { return d_ptr->isWindow; }
- inline bool signalsBlocked() const Q_DECL_NOTHROW { return d_ptr->blockSig; }
- bool blockSignals(bool b) Q_DECL_NOTHROW;
+ inline bool signalsBlocked() const noexcept { return d_ptr->blockSig; }
+ bool blockSignals(bool b) noexcept;
QThread *thread() const;
void moveToThread(QThread *thread);
@@ -176,7 +183,9 @@ public:
}
#ifndef QT_NO_REGEXP
+#if QT_DEPRECATED_SINCE(5, 13)
template<typename T>
+ QT_DEPRECATED_X("Use findChildren(const QRegularExpression &, ...) instead.")
inline QList<T> findChildren(const QRegExp &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{
typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
@@ -186,6 +195,7 @@ public:
return list;
}
#endif
+#endif
#if QT_CONFIG(regularexpression)
template<typename T>
@@ -433,7 +443,7 @@ protected:
QScopedPointer<QObjectData> d_ptr;
static const QMetaObject staticQtMetaObject;
- friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT;
+ friend inline const QMetaObject *qt_getQtMetaObject() noexcept;
friend struct QMetaObject;
friend struct QMetaObjectPrivate;
@@ -464,12 +474,14 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch
const char *amember, Qt::ConnectionType atype) const
{ return connect(asender, asignal, this, amember, atype); }
-inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT
+inline const QMetaObject *qt_getQtMetaObject() noexcept
{ return &QObject::staticQtMetaObject; }
#ifndef QT_NO_USERDATA
class Q_CORE_EXPORT QObjectUserData {
+ Q_DISABLE_COPY(QObjectUserData)
public:
+ QObjectUserData() = default;
virtual ~QObjectUserData();
};
#endif
@@ -517,7 +529,10 @@ inline T qobject_cast(const QObject *object)
template <class T> inline const char * qobject_interface_iid()
{ return nullptr; }
-#if !defined(Q_MOC_RUN) && !defined(Q_CLANG_QDOC)
+
+#if defined(Q_CLANG_QDOC)
+# define Q_DECLARE_INTERFACE(IFace, IId)
+#elif !defined(Q_MOC_RUN)
# define Q_DECLARE_INTERFACE(IFace, IId) \
template <> inline const char *qobject_interface_iid<IFace *>() \
{ return IId; } \
@@ -534,17 +549,15 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
class QSignalBlocker
{
public:
- inline explicit QSignalBlocker(QObject *o) Q_DECL_NOTHROW;
- inline explicit QSignalBlocker(QObject &o) Q_DECL_NOTHROW;
+ inline explicit QSignalBlocker(QObject *o) noexcept;
+ inline explicit QSignalBlocker(QObject &o) noexcept;
inline ~QSignalBlocker();
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW;
- inline QSignalBlocker &operator=(QSignalBlocker &&other) Q_DECL_NOTHROW;
-#endif
+ inline QSignalBlocker(QSignalBlocker &&other) noexcept;
+ inline QSignalBlocker &operator=(QSignalBlocker &&other) noexcept;
- inline void reblock() Q_DECL_NOTHROW;
- inline void unblock() Q_DECL_NOTHROW;
+ inline void reblock() noexcept;
+ inline void unblock() noexcept;
private:
Q_DISABLE_COPY(QSignalBlocker)
QObject * m_o;
@@ -552,20 +565,19 @@ private:
bool m_inhibited;
};
-QSignalBlocker::QSignalBlocker(QObject *o) Q_DECL_NOTHROW
+QSignalBlocker::QSignalBlocker(QObject *o) noexcept
: m_o(o),
m_blocked(o && o->blockSignals(true)),
m_inhibited(false)
{}
-QSignalBlocker::QSignalBlocker(QObject &o) Q_DECL_NOTHROW
+QSignalBlocker::QSignalBlocker(QObject &o) noexcept
: m_o(&o),
m_blocked(o.blockSignals(true)),
m_inhibited(false)
{}
-#ifdef Q_COMPILER_RVALUE_REFS
-QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW
+QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) noexcept
: m_o(other.m_o),
m_blocked(other.m_blocked),
m_inhibited(other.m_inhibited)
@@ -573,7 +585,7 @@ QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW
other.m_o = nullptr;
}
-QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) Q_DECL_NOTHROW
+QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) noexcept
{
if (this != &other) {
// if both *this and other block the same object's signals:
@@ -588,7 +600,6 @@ QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) Q_DECL_NOTHROW
}
return *this;
}
-#endif
QSignalBlocker::~QSignalBlocker()
{
@@ -596,13 +607,13 @@ QSignalBlocker::~QSignalBlocker()
m_o->blockSignals(m_blocked);
}
-void QSignalBlocker::reblock() Q_DECL_NOTHROW
+void QSignalBlocker::reblock() noexcept
{
if (m_o) m_o->blockSignals(true);
m_inhibited = false;
}
-void QSignalBlocker::unblock() Q_DECL_NOTHROW
+void QSignalBlocker::unblock() noexcept
{
if (m_o) m_o->blockSignals(m_blocked);
m_inhibited = true;
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 5dfef786ec..1953aea21e 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
**
@@ -79,9 +79,9 @@ struct QSignalSpyCallbackSet
EndCallback signal_end_callback,
slot_end_callback;
};
-void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set);
+void Q_CORE_EXPORT qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set);
-extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set;
+extern Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set;
enum { QObjectPrivateVersion = QT_VERSION };
@@ -124,54 +124,199 @@ public:
};
typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
- struct Connection
+ struct Connection;
+ struct SignalVector;
+
+ struct ConnectionOrSignalVector {
+ union {
+ // linked list of orphaned connections that need cleaning up
+ ConnectionOrSignalVector *nextInOrphanList;
+ // linked list of connections connected to slots in this object
+ Connection *next;
+ };
+
+ static SignalVector *asSignalVector(ConnectionOrSignalVector *c) {
+ if (reinterpret_cast<quintptr>(c) & 1)
+ return reinterpret_cast<SignalVector *>(reinterpret_cast<quintptr>(c) & ~quintptr(1u));
+ return nullptr;
+ }
+ static Connection *fromSignalVector(SignalVector *v) {
+ return reinterpret_cast<Connection *>(reinterpret_cast<quintptr>(v) | quintptr(1u));
+ }
+ };
+
+ struct Connection : public ConnectionOrSignalVector
{
+ // linked list of connections connected to slots in this object, next is in base class
+ Connection **prev;
+ // linked list of connections connected to signals in this object
+ QAtomicPointer<Connection> nextConnectionList;
+ Connection *prevConnectionList;
+
QObject *sender;
- QObject *receiver;
+ QAtomicPointer<QObject> receiver;
+ QAtomicPointer<QThreadData> receiverThreadData;
union {
StaticMetaCallFunction callFunction;
QtPrivate::QSlotObjectBase *slotObj;
};
- // The next pointer for the singly-linked ConnectionList
- Connection *nextConnectionList;
- //senders linked list
- Connection *next;
- Connection **prev;
QAtomicPointer<const int> argumentTypes;
QAtomicInt ref_;
+ uint id = 0;
ushort method_offset;
ushort method_relative;
- uint signal_index : 27; // In signal range (see QObjectPrivate::signalIndex())
+ int signal_index : 27; // In signal range (see QObjectPrivate::signalIndex())
ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
ushort isSlotObject : 1;
ushort ownArgumentTypes : 1;
- Connection() : nextConnectionList(nullptr), ref_(2), ownArgumentTypes(true) {
+ Connection() : ref_(2), ownArgumentTypes(true) {
//ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection
}
~Connection();
int method() const { Q_ASSERT(!isSlotObject); return method_offset + method_relative; }
void ref() { ref_.ref(); }
+ void freeSlotObject()
+ {
+ if (isSlotObject) {
+ slotObj->destroyIfLastRef();
+ isSlotObject = false;
+ }
+ }
void deref() {
if (!ref_.deref()) {
- Q_ASSERT(!receiver);
+ Q_ASSERT(!receiver.loadRelaxed());
+ Q_ASSERT(!isSlotObject);
delete this;
}
}
};
// ConnectionList is a singly-linked list
struct ConnectionList {
- ConnectionList() : first(nullptr), last(nullptr) {}
- Connection *first;
- Connection *last;
+ QAtomicPointer<Connection> first;
+ QAtomicPointer<Connection> last;
};
struct Sender
{
+ Sender(QObject *receiver, QObject *sender, int signal)
+ : receiver(receiver), sender(sender), signal(signal)
+ {
+ if (receiver) {
+ ConnectionData *cd = receiver->d_func()->connections.loadRelaxed();
+ previous = cd->currentSender;
+ cd->currentSender = this;
+ }
+ }
+ ~Sender()
+ {
+ if (receiver)
+ receiver->d_func()->connections.loadRelaxed()->currentSender = previous;
+ }
+ void receiverDeleted()
+ {
+ Sender *s = this;
+ while (s) {
+ s->receiver = nullptr;
+ s = s->previous;
+ }
+ }
+ Sender *previous;
+ QObject *receiver;
QObject *sender;
int signal;
- int ref;
};
+ struct SignalVector : public ConnectionOrSignalVector {
+ quintptr allocated;
+ // ConnectionList signals[]
+ ConnectionList &at(int i)
+ {
+ return reinterpret_cast<ConnectionList *>(this + 1)[i + 1];
+ }
+ const ConnectionList &at(int i) const
+ {
+ return reinterpret_cast<const ConnectionList *>(this + 1)[i + 1];
+ }
+ int count() const { return static_cast<int>(allocated); }
+ };
+
+
+
+ /*
+ This contains the all connections from and to an object.
+
+ The signalVector contains the lists of connections for a given signal. The index in the vector correspond
+ to the signal index. The signal index is the one returned by QObjectPrivate::signalIndex (not
+ QMetaObject::indexOfSignal). allsignals contains a list of special connections that will get invoked on
+ any signal emission. This is done by connecting to signal index -1.
+
+ This vector is protected by the object mutex (signalSlotLock())
+
+ Each Connection is also part of a 'senders' linked list. This one contains all connections connected
+ to a slot in this object. The mutex of the receiver must be locked when touching the pointers of this
+ linked list.
+ */
+ struct ConnectionData {
+ // the id below is used to avoid activating new connections. When the object gets
+ // deleted it's set to 0, so that signal emission stops
+ QAtomicInteger<uint> currentConnectionId;
+ QAtomicInt ref;
+ QAtomicPointer<SignalVector> signalVector;
+ Connection *senders = nullptr;
+ Sender *currentSender = nullptr; // object currently activating the object
+ QAtomicPointer<Connection> orphaned;
+
+ ~ConnectionData()
+ {
+ deleteOrphaned(orphaned.loadRelaxed());
+ SignalVector *v = signalVector.loadRelaxed();
+ if (v)
+ free(v);
+ }
+
+ // must be called on the senders connection data
+ // assumes the senders and receivers lock are held
+ void removeConnection(Connection *c);
+ void cleanOrphanedConnections(QObject *sender)
+ {
+ if (orphaned.loadRelaxed() && ref == 1)
+ cleanOrphanedConnectionsImpl(sender);
+ }
+ void cleanOrphanedConnectionsImpl(QObject *sender);
+
+ ConnectionList &connectionsForSignal(int signal)
+ {
+ return signalVector.loadRelaxed()->at(signal);
+ }
+
+ void resizeSignalVector(uint size) {
+ SignalVector *vector = this->signalVector.loadRelaxed();
+ if (vector && vector->allocated > size)
+ return;
+ size = (size + 7) & ~7;
+ SignalVector *newVector = reinterpret_cast<SignalVector *>(malloc(sizeof(SignalVector) + (size + 1) * sizeof(ConnectionList)));
+ int start = -1;
+ if (vector) {
+ memcpy(newVector, vector, sizeof(SignalVector) + (vector->allocated + 1) * sizeof(ConnectionList));
+ start = vector->count();
+ }
+ for (int i = start; i < int(size); ++i)
+ newVector->at(i) = ConnectionList();
+ newVector->next = nullptr;
+ newVector->allocated = size;
+
+ signalVector.storeRelaxed(newVector);
+ if (vector) {
+ vector->nextInOrphanList = orphaned.loadRelaxed();
+ orphaned.storeRelaxed(ConnectionOrSignalVector::fromSignalVector(vector));
+ }
+ }
+ int signalVectorCount() const {
+ return signalVector ? signalVector.loadRelaxed()->count() : -1;
+ }
+
+ static void deleteOrphaned(ConnectionOrSignalVector *c);
+ };
QObjectPrivate(int version = QObjectPrivateVersion);
virtual ~QObjectPrivate();
@@ -187,13 +332,6 @@ public:
QObjectList senderList() const;
void addConnection(int signal, Connection *c);
- void cleanConnectionLists();
-
- static inline Sender *setCurrentSender(QObject *receiver,
- Sender *sender);
- static inline void resetCurrentSender(QObject *receiver,
- Sender *currentSender,
- Sender *previousSender);
static QObjectPrivate *get(QObject *o) {
return o->d_func();
@@ -201,7 +339,8 @@ public:
static const QObjectPrivate *get(const QObject *o) { return o->d_func(); }
int signalIndex(const char *signalName, const QMetaObject **meta = nullptr) const;
- inline bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const;
+ bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const;
+ bool maybeSignalConnected(uint signalIndex) const;
inline bool isDeclarativeSignalConnected(uint signalIdx) const;
// To allow abitrary objects to call connectNotify()/disconnectNotify() without making
@@ -224,15 +363,21 @@ public:
const int *types, const QMetaObject *senderMetaObject);
static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type);
static bool disconnect(const QObject *sender, int signal_index, void **slot);
+
+ void ensureConnectionData()
+ {
+ if (connections.loadRelaxed())
+ return;
+ ConnectionData *cd = new ConnectionData;
+ cd->ref.ref();
+ connections.storeRelaxed(cd);
+ }
public:
ExtraData *extraData; // extra data set by the user
QThreadData *threadData; // id of the thread that owns the object
- QObjectConnectionListVector *connectionLists;
-
- Connection *senders; // linked list of connections connected to this object
- Sender *currentSender; // object currently activating the object
- mutable quint32 connectedSignals[2];
+ using ConnectionDataPointer = QExplicitlySharedDataPointer<ConnectionData>;
+ QAtomicPointer<ConnectionData> connections;
union {
QObject *currentChildBeingDeleted; // should only be used when QObjectData::isDeletingChildren is set
@@ -246,47 +391,12 @@ public:
Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_MOVABLE_TYPE);
-/*! \internal
-
- Returns \c true if the signal with index \a signal_index from object \a sender is connected.
- Signals with indices above a certain range are always considered connected (see connectedSignals
- in QObjectPrivate).
-
- \a signal_index must be the index returned by QObjectPrivate::signalIndex;
-*/
-inline bool QObjectPrivate::isSignalConnected(uint signal_index, bool checkDeclarative) const
-{
- return signal_index >= sizeof(connectedSignals) * 8
- || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f))
- || (checkDeclarative && isDeclarativeSignalConnected(signal_index)));
-}
-
inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const
{
return declarativeData && QAbstractDeclarativeData::isSignalConnected
&& QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index);
}
-inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
- Sender *sender)
-{
- Sender *previousSender = receiver->d_func()->currentSender;
- receiver->d_func()->currentSender = sender;
- return previousSender;
-}
-
-inline void QObjectPrivate::resetCurrentSender(QObject *receiver,
- Sender *currentSender,
- Sender *previousSender)
-{
- // ref is set to zero when this object is deleted during the metacall
- if (currentSender->ref == 1)
- receiver->d_func()->currentSender = previousSender;
- // if we've recursed, we need to tell the caller about the objects deletion
- if (previousSender)
- previousSender->ref = currentSender->ref;
-}
-
inline void QObjectPrivate::connectNotify(const QMetaMethod &signal)
{
q_ptr->connectNotify(signal);
@@ -372,7 +482,26 @@ Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE);
class QSemaphore;
-class Q_CORE_EXPORT QMetaCallEvent : public QEvent
+class Q_CORE_EXPORT QAbstractMetaCallEvent : public QEvent
+{
+public:
+ QAbstractMetaCallEvent(const QObject *sender, int signalId, QSemaphore *semaphore = nullptr)
+ : QEvent(MetaCall), signalId_(signalId), sender_(sender), semaphore_(semaphore)
+ {}
+ ~QAbstractMetaCallEvent();
+
+ virtual void placeMetaCall(QObject *object) = 0;
+
+ inline const QObject *sender() const { return sender_; }
+ inline int signalId() const { return signalId_; }
+
+private:
+ int signalId_;
+ const QObject *sender_;
+ QSemaphore *semaphore_;
+};
+
+class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent
{
public:
QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId,
@@ -383,23 +512,18 @@ public:
QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signalId,
int nargs = 0, int *types = nullptr, void **args = nullptr, QSemaphore *semaphore = nullptr);
- ~QMetaCallEvent();
+ ~QMetaCallEvent() override;
inline int id() const { return method_offset_ + method_relative_; }
- inline const QObject *sender() const { return sender_; }
- inline int signalId() const { return signalId_; }
inline void **args() const { return args_; }
- virtual void placeMetaCall(QObject *object);
+ virtual void placeMetaCall(QObject *object) override;
private:
QtPrivate::QSlotObjectBase *slotObj_;
- const QObject *sender_;
- int signalId_;
int nargs_;
int *types_;
void **args_;
- QSemaphore *semaphore_;
QObjectPrivate::StaticMetaCallFunction callFunction_;
ushort method_offset_;
ushort method_relative_;
@@ -407,7 +531,7 @@ private:
class QBoolBlocker
{
- Q_DISABLE_COPY(QBoolBlocker)
+ Q_DISABLE_COPY_MOVE(QBoolBlocker)
public:
explicit inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;}
inline ~QBoolBlocker(){block = reset; }
@@ -432,9 +556,9 @@ struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QDynamicMetaObjectData,
{
~QAbstractDynamicMetaObject();
- virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) override { return this; }
+ QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) override { return this; }
virtual int createProperty(const char *, const char *) { return -1; }
- virtual int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) override
+ int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) override
{ return metaCall(c, _id, a); }
virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } // Compat overload
};
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 059bb44e10..4d5ac4dcb2 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -64,11 +64,7 @@ class QString;
// The following macros can be defined by tools that understand Qt
// to have the information from the macro.
#ifndef QT_ANNOTATE_CLASS
-# ifndef Q_COMPILER_VARIADIC_MACROS
-# define QT_ANNOTATE_CLASS(type, x)
-# else
-# define QT_ANNOTATE_CLASS(type, ...)
-# endif
+# define QT_ANNOTATE_CLASS(type, ...)
#endif
#ifndef QT_ANNOTATE_CLASS2
# define QT_ANNOTATE_CLASS2(type, a1, a2)
@@ -105,11 +101,7 @@ class QString;
#endif
#define Q_PLUGIN_METADATA(x) QT_ANNOTATE_CLASS(qt_plugin_metadata, x)
#define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x)
-#ifdef Q_COMPILER_VARIADIC_MACROS
-# define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__)
-#else
-# define Q_PROPERTY(text) QT_ANNOTATE_CLASS(qt_property, text)
-#endif
+#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__)
#define Q_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_private_property, d, text)
#ifndef Q_REVISION
# define Q_REVISION(v)
@@ -119,13 +111,13 @@ class QString;
#define Q_ENUMS(x) QT_ANNOTATE_CLASS(qt_enums, x)
#define Q_FLAGS(x) QT_ANNOTATE_CLASS(qt_enums, x)
#define Q_ENUM_IMPL(ENUM) \
- friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) Q_DECL_NOEXCEPT { return &staticMetaObject; } \
- friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) Q_DECL_NOEXCEPT { return #ENUM; }
+ friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
+ friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
#define Q_ENUM(x) Q_ENUMS(x) Q_ENUM_IMPL(x)
#define Q_FLAG(x) Q_FLAGS(x) Q_ENUM_IMPL(x)
#define Q_ENUM_NS_IMPL(ENUM) \
- inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) Q_DECL_NOEXCEPT { return &staticMetaObject; } \
- inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) Q_DECL_NOEXCEPT { return #ENUM; }
+ inline Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &staticMetaObject; } \
+ inline Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
#define Q_ENUM_NS(x) Q_ENUMS(x) Q_ENUM_NS_IMPL(x)
#define Q_FLAG_NS(x) Q_FLAGS(x) Q_ENUM_NS_IMPL(x)
#define Q_SCRIPTABLE QT_ANNOTATE_FUNCTION(qt_scriptable)
@@ -146,6 +138,10 @@ class QString;
# define QT_TR_FUNCTIONS
#endif
+#ifdef Q_CLANG_QDOC
+#define QT_TR_FUNCTIONS
+#endif
+
// ### Qt6: remove
#define Q_OBJECT_CHECK /* empty, unused since Qt 5.2 */
@@ -340,7 +336,7 @@ struct Q_CORE_EXPORT QMetaObject
const char *className() const;
const QMetaObject *superClass() const;
- bool inherits(const QMetaObject *metaObject) const Q_DECL_NOEXCEPT;
+ bool inherits(const QMetaObject *metaObject) const noexcept;
QObject *cast(QObject *obj) const;
const QObject *cast(const QObject *obj) const;
@@ -584,6 +580,7 @@ struct Q_CORE_EXPORT QMetaObject
private:
static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret);
+ friend class QTimer;
};
class Q_CORE_EXPORT QMetaObject::Connection {
@@ -605,8 +602,8 @@ public:
operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; }
#endif
- Connection(Connection &&o) Q_DECL_NOTHROW : d_ptr(o.d_ptr) { o.d_ptr = nullptr; }
- Connection &operator=(Connection &&other) Q_DECL_NOTHROW
+ Connection(Connection &&o) noexcept : d_ptr(o.d_ptr) { o.d_ptr = nullptr; }
+ Connection &operator=(Connection &&other) noexcept
{ qSwap(d_ptr, other.d_ptr); return *this; }
};
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index 8afff1fb98..31ecc8b20d 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -386,8 +386,8 @@ namespace QtPrivate {
public:
explicit QSlotObjectBase(ImplFn fn) : m_ref(1), m_impl(fn) {}
- inline int ref() Q_DECL_NOTHROW { return m_ref.ref(); }
- inline void destroyIfLastRef() Q_DECL_NOTHROW
+ inline int ref() noexcept { return m_ref.ref(); }
+ inline void destroyIfLastRef() noexcept
{ if (!m_ref.deref()) m_impl(Destroy, this, nullptr, nullptr, nullptr); }
inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, nullptr, a, &ret); return ret; }
@@ -395,7 +395,7 @@ namespace QtPrivate {
protected:
~QSlotObjectBase() {}
private:
- Q_DISABLE_COPY(QSlotObjectBase)
+ Q_DISABLE_COPY_MOVE(QSlotObjectBase)
};
// implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject
diff --git a/src/corelib/kernel/qpointer.cpp b/src/corelib/kernel/qpointer.cpp
index c3dee7989e..068314633b 100644
--- a/src/corelib/kernel/qpointer.cpp
+++ b/src/corelib/kernel/qpointer.cpp
@@ -45,7 +45,7 @@
\ingroup objectmodel
A guarded pointer, QPointer<T>, behaves like a normal C++
- pointer \c{T *}, except that it is automatically set to 0 when the
+ pointer \c{T *}, except that it is automatically cleared when the
referenced object is destroyed (unlike normal C++ pointers, which
become "dangling pointers" in such cases). \c T must be a
subclass of QObject.
@@ -79,7 +79,7 @@
\snippet pointer/pointer.cpp 2
If the QLabel is deleted in the meantime, the \c label variable
- will hold 0 instead of an invalid address, and the last line will
+ will hold \nullptr instead of an invalid address, and the last line will
never be executed.
The functions and operators available with a QPointer are the
@@ -93,7 +93,7 @@
For creating guarded pointers, you can construct or assign to them
from a T* or from another guarded pointer of the same type. You
can compare them with each other using operator==() and
- operator!=(), or test for 0 with isNull(). You can dereference
+ operator!=(), or test for \nullptr with isNull(). You can dereference
them using either the \c *x or the \c x->member notation.
A guarded pointer will automatically cast to a \c T *, so you can
@@ -113,7 +113,7 @@
/*!
\fn template <class T> QPointer<T>::QPointer()
- Constructs a 0 guarded pointer.
+ Constructs a guarded pointer with value \nullptr.
\sa isNull()
*/
diff --git a/src/corelib/kernel/qpointer.h b/src/corelib/kernel/qpointer.h
index b2b3cda4ab..7052bcf0d4 100644
--- a/src/corelib/kernel/qpointer.h
+++ b/src/corelib/kernel/qpointer.h
@@ -77,13 +77,13 @@ public:
~QPointer();
#endif
- inline void swap(QPointer &other) { wp.swap(other.wp); }
+ inline void swap(QPointer &other) noexcept { wp.swap(other.wp); }
inline QPointer<T> &operator=(T* p)
{ wp.assign(static_cast<QObjectType*>(p)); return *this; }
inline T* data() const
- { return static_cast<T*>( wp.data()); }
+ { return static_cast<T*>(wp.internalData()); }
inline T* operator->() const
{ return data(); }
inline T& operator*() const
@@ -143,9 +143,14 @@ template<typename T>
QPointer<T>
qPointerFromVariant(const QVariant &variant)
{
- return QPointer<T>(qobject_cast<T*>(QtSharedPointer::weakPointerFromVariant_internal(variant).data()));
+ const auto wp = QtSharedPointer::weakPointerFromVariant_internal(variant);
+ return QPointer<T>{qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(wp))};
}
+template <class T>
+inline void swap(QPointer<T> &p1, QPointer<T> &p2) noexcept
+{ p1.swap(p2); }
+
QT_END_NAMESPACE
#endif // QT_NO_QOBJECT
diff --git a/src/corelib/kernel/qpoll.cpp b/src/corelib/kernel/qpoll.cpp
index 8e93c4d363..8b87bfe79d 100644
--- a/src/corelib/kernel/qpoll.cpp
+++ b/src/corelib/kernel/qpoll.cpp
@@ -39,6 +39,10 @@
#include "qcore_unix_p.h"
+#ifdef Q_OS_RTEMS
+#include <rtems/rtems_bsdnet_internal.h>
+#endif
+
QT_BEGIN_NAMESPACE
#define QT_POLL_READ_MASK (POLLIN | POLLRDNORM)
@@ -135,6 +139,11 @@ static inline int qt_poll_sweep(struct pollfd *fds, nfds_t nfds,
static inline bool qt_poll_is_bad_fd(int fd)
{
+#ifdef Q_OS_RTEMS
+ if (!rtems_bsdnet_fdToSocket(fd))
+ return true;
+#endif
+
int ret;
EINTR_LOOP(ret, fcntl(fd, F_GETFD));
return (ret == -1 && errno == EBADF);
diff --git a/src/corelib/kernel/qppsattribute.cpp b/src/corelib/kernel/qppsattribute.cpp
index 6be462edb5..166d590872 100644
--- a/src/corelib/kernel/qppsattribute.cpp
+++ b/src/corelib/kernel/qppsattribute.cpp
@@ -145,7 +145,6 @@ QPpsAttribute &QPpsAttribute::operator=(const QPpsAttribute &other)
return *this;
}
-#ifdef Q_COMPILER_RVALUE_REFS
QPpsAttribute::QPpsAttribute(QPpsAttribute &&other) : d(other.d)
{
other.d->type = QPpsAttribute::None;
@@ -156,7 +155,6 @@ QPpsAttribute &QPpsAttribute::operator=(QPpsAttribute &&other)
qSwap(d, other.d);
return *this;
}
-#endif
bool QPpsAttribute::operator==(const QPpsAttribute &other) const
{
diff --git a/src/corelib/kernel/qppsattribute_p.h b/src/corelib/kernel/qppsattribute_p.h
index b59dcd5851..d6611cb675 100644
--- a/src/corelib/kernel/qppsattribute_p.h
+++ b/src/corelib/kernel/qppsattribute_p.h
@@ -96,10 +96,8 @@ public:
bool operator==(const QPpsAttribute &other) const;
bool operator!=(const QPpsAttribute &other) const;
-#ifdef Q_COMPILER_RVALUE_REFS
QPpsAttribute(QPpsAttribute &&other);
QPpsAttribute &operator=(QPpsAttribute &&other);
-#endif
bool isValid() const;
Type type() const;
diff --git a/src/corelib/kernel/qppsobject_p.h b/src/corelib/kernel/qppsobject_p.h
index abcf00fa05..a3bf3a5bc1 100644
--- a/src/corelib/kernel/qppsobject_p.h
+++ b/src/corelib/kernel/qppsobject_p.h
@@ -119,7 +119,7 @@ Q_SIGNALS:
private:
Q_DECLARE_PRIVATE(QPpsObject)
- Q_DISABLE_COPY(QPpsObject)
+ Q_DISABLE_COPY_MOVE(QPpsObject)
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
index c952655cb8..39f3002394 100644
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -150,11 +150,18 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
\sa setKey()
*/
+
+#ifndef QT_NO_QOBJECT
QSharedMemory::QSharedMemory(QObject *parent)
: QObject(*new QSharedMemoryPrivate, parent)
{
}
-
+#else
+QSharedMemory::QSharedMemory()
+ : d_ptr(new QSharedMemoryPrivate)
+{
+}
+#endif
/*!
Constructs a shared memory object with the given \a parent and with
its key set to \a key. Because its key is set, its create() and
@@ -162,11 +169,19 @@ QSharedMemory::QSharedMemory(QObject *parent)
\sa setKey(), create(), attach()
*/
+#ifndef QT_NO_QOBJECT
QSharedMemory::QSharedMemory(const QString &key, QObject *parent)
: QObject(*new QSharedMemoryPrivate, parent)
{
setKey(key);
}
+#else
+QSharedMemory::QSharedMemory(const QString &key)
+ : d_ptr(new QSharedMemoryPrivate)
+{
+ setKey(key);
+}
+#endif
/*!
The destructor clears the key, which forces the shared memory object
@@ -604,4 +619,6 @@ QString QSharedMemory::errorString() const
QT_END_NAMESPACE
+#ifndef QT_NO_QOBJECT
#include "moc_qsharedmemory.cpp"
+#endif
diff --git a/src/corelib/kernel/qsharedmemory.h b/src/corelib/kernel/qsharedmemory.h
index 67cf52ac17..6236c6aa4c 100644
--- a/src/corelib/kernel/qsharedmemory.h
+++ b/src/corelib/kernel/qsharedmemory.h
@@ -40,8 +40,14 @@
#ifndef QSHAREDMEMORY_H
#define QSHAREDMEMORY_H
-#include <QtCore/qobject.h>
-
+#include <QtCore/qglobal.h>
+#ifndef QT_NO_QOBJECT
+# include <QtCore/qobject.h>
+#else
+# include <QtCore/qobjectdefs.h>
+# include <QtCore/qscopedpointer.h>
+# include <QtCore/qstring.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -49,9 +55,14 @@ QT_BEGIN_NAMESPACE
class QSharedMemoryPrivate;
-class Q_CORE_EXPORT QSharedMemory : public QObject
+class Q_CORE_EXPORT QSharedMemory
+#ifndef QT_NO_QOBJECT
+ : public QObject
+#endif
{
+#ifndef QT_NO_QOBJECT
Q_OBJECT
+#endif
Q_DECLARE_PRIVATE(QSharedMemory)
public:
@@ -74,8 +85,17 @@ public:
UnknownError
};
+#ifndef QT_NO_QOBJECT
QSharedMemory(QObject *parent = nullptr);
QSharedMemory(const QString &key, QObject *parent = nullptr);
+#else
+ QSharedMemory();
+ QSharedMemory(const QString &key);
+ static QString tr(const char * str)
+ {
+ return QString::fromLatin1(str);
+ }
+#endif
~QSharedMemory();
void setKey(const QString &key);
@@ -104,6 +124,9 @@ public:
private:
Q_DISABLE_COPY(QSharedMemory)
+#ifdef QT_NO_QOBJECT
+ QScopedPointer<QSharedMemoryPrivate> d_ptr;
+#endif
};
#endif // QT_NO_SHAREDMEMORY
diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h
index 95fe0d1083..e6e989abda 100644
--- a/src/corelib/kernel/qsharedmemory_p.h
+++ b/src/corelib/kernel/qsharedmemory_p.h
@@ -67,9 +67,12 @@ namespace QSharedMemoryPrivate
#else
#include "qsystemsemaphore.h"
-#include "private/qobject_p.h"
-#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY)
+#ifndef QT_NO_QOBJECT
+# include "private/qobject_p.h"
+#endif
+
+#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_RTEMS)
# include <sys/sem.h>
#endif
@@ -98,7 +101,7 @@ public:
{
if (q_sm && q_sm->lock())
return true;
- q_sm = 0;
+ q_sm = nullptr;
return false;
}
@@ -107,9 +110,14 @@ private:
};
#endif // QT_NO_SYSTEMSEMAPHORE
-class Q_AUTOTEST_EXPORT QSharedMemoryPrivate : public QObjectPrivate
+class Q_AUTOTEST_EXPORT QSharedMemoryPrivate
+#ifndef QT_NO_QOBJECT
+ : public QObjectPrivate
+#endif
{
+#ifndef QT_NO_QOBJECT
Q_DECLARE_PUBLIC(QSharedMemory)
+#endif
public:
QSharedMemoryPrivate();
diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp
index d1d44747e0..f6d7e78441 100644
--- a/src/corelib/kernel/qsharedmemory_unix.cpp
+++ b/src/corelib/kernel/qsharedmemory_unix.cpp
@@ -64,8 +64,11 @@
#ifndef QT_NO_SHAREDMEMORY
QT_BEGIN_NAMESPACE
-QSharedMemoryPrivate::QSharedMemoryPrivate()
- : QObjectPrivate(), memory(0), size(0), error(QSharedMemory::NoError),
+QSharedMemoryPrivate::QSharedMemoryPrivate() :
+#ifndef QT_NO_QOBJECT
+ QObjectPrivate(),
+#endif
+ memory(0), size(0), error(QSharedMemory::NoError),
#ifndef QT_NO_SYSTEMSEMAPHORE
systemSemaphore(QString()), lockedByMe(false),
#endif
diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
index c1dba30e2b..02de2339a5 100644
--- a/src/corelib/kernel/qsharedmemory_win.cpp
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -47,7 +47,10 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_SHAREDMEMORY
-QSharedMemoryPrivate::QSharedMemoryPrivate() : QObjectPrivate(),
+QSharedMemoryPrivate::QSharedMemoryPrivate() :
+#ifndef QT_NO_QOBJECT
+ QObjectPrivate(),
+#endif
memory(0), size(0), error(QSharedMemory::NoError),
systemSemaphore(QString()), lockedByMe(false), hand(0)
{
diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp
index 02a1281f92..34fea861cd 100644
--- a/src/corelib/kernel/qsignalmapper.cpp
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -37,6 +37,9 @@
**
****************************************************************************/
+#include "qglobal.h"
+#if QT_DEPRECATED_SINCE(5, 10)
+
#include "qsignalmapper.h"
#include "qhash.h"
#include "qobject_p.h"
@@ -312,3 +315,4 @@ QT_END_NAMESPACE
#include "moc_qsignalmapper.cpp"
+#endif
diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp
index 6ff8268978..2a246b1204 100644
--- a/src/corelib/kernel/qsocketnotifier.cpp
+++ b/src/corelib/kernel/qsocketnotifier.cpp
@@ -152,7 +152,7 @@ QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent)
else if (!d->threadData->hasEventDispatcher())
qWarning("QSocketNotifier: Can only be used with threads started with QThread");
else
- d->threadData->eventDispatcher.load()->registerSocketNotifier(this);
+ d->threadData->eventDispatcher.loadRelaxed()->registerSocketNotifier(this);
}
/*!
@@ -241,9 +241,9 @@ void QSocketNotifier::setEnabled(bool enable)
return;
}
if (d->snenabled)
- d->threadData->eventDispatcher.load()->registerSocketNotifier(this);
+ d->threadData->eventDispatcher.loadRelaxed()->registerSocketNotifier(this);
else
- d->threadData->eventDispatcher.load()->unregisterSocketNotifier(this);
+ d->threadData->eventDispatcher.loadRelaxed()->unregisterSocketNotifier(this);
}
diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp
index 53c3136857..a735e12925 100644
--- a/src/corelib/kernel/qsystemerror.cpp
+++ b/src/corelib/kernel/qsystemerror.cpp
@@ -112,7 +112,7 @@ static QString windowsErrorString(int errorCode)
static QString standardLibraryErrorString(int errorCode)
{
- const char *s = 0;
+ const char *s = nullptr;
QString ret;
switch (errorCode) {
case 0:
@@ -152,10 +152,7 @@ QString QSystemError::string(ErrorScope errorScope, int errorCode)
case NativeError:
#if defined (Q_OS_WIN)
return windowsErrorString(errorCode);
-#else
- //unix: fall through as native and standard library are the same
- Q_FALLTHROUGH();
-#endif
+#endif // else unix: native and standard library are the same
case StandardLibraryError:
return standardLibraryErrorString(errorCode);
default:
diff --git a/src/corelib/kernel/qsystemsemaphore_systemv.cpp b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
index 9e438ae2a6..2c38d74d2d 100644
--- a/src/corelib/kernel/qsystemsemaphore_systemv.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
@@ -76,7 +76,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
#if QT_CONFIG(translation)
QCoreApplication::tr("%1: key is empty", "QSystemSemaphore")
#else
- QString::fromLatin1("%1: key is empty")
+ QLatin1String("%1: key is empty")
#endif
.arg(QLatin1String("QSystemSemaphore::handle:"));
error = QSystemSemaphore::KeyError;
@@ -94,7 +94,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
#if QT_CONFIG(translation)
QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore")
#else
- QString::fromLatin1("%1: unable to make key")
+ QLatin1String("%1: unable to make key")
#endif
.arg(QLatin1String("QSystemSemaphore::handle:"));
error = QSystemSemaphore::KeyError;
@@ -111,7 +111,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
#if QT_CONFIG(translation)
QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore")
#else
- QString::fromLatin1("%1: ftok failed")
+ QLatin1String("%1: ftok failed")
#endif
.arg(QLatin1String("QSystemSemaphore::handle:"));
error = QSystemSemaphore::KeyError;
diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp
deleted file mode 100644
index 5437210699..0000000000
--- a/src/corelib/kernel/qtcore_eval.cpp
+++ /dev/null
@@ -1,560 +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:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qcoreevent.h>
-#include <qdatetime.h>
-#include <qlibraryinfo.h>
-#include <qobject.h>
-#include <qcoreapplication.h>
-#include <private/qcoreapplication_p.h>
-
-#include "stdio.h"
-#include "stdlib.h"
-
-QT_BEGIN_NAMESPACE
-
-#include "qconfig_eval.cpp"
-
-static const char boilerplate_supported_but_time_limited[] =
- "\nQt %1 Evaluation License\n"
- "Copyright (C) 2016 The Qt Company Ltd.\n"
- "This trial version may only be used for evaluation purposes\n"
- "and will shut down after 120 minutes.\n"
- "Registered to:\n"
- " Licensee: %2\n\n"
- "The evaluation expires in %4 days\n\n"
- "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n";
-
-static const char boilerplate_supported[] =
- "\nQt %1 Evaluation License\n"
- "Copyright (C) 2016 The Qt Company Ltd.\n"
- "This trial version may only be used for evaluation purposes\n"
- "Registered to:\n"
- " Licensee: %2\n\n"
- "The evaluation expires in %4 days\n\n"
- "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n";
-
-static const char boilerplate_expired[] =
- "This software is using the trial version of the Qt GUI toolkit.\n"
- "The trial period has expired. If you need more time to\n"
- "evaluate Qt, or if you have any questions about Qt, contact us\n"
- "at: http://www.qt.io/contact-us.\n\n";
-
-static const char will_shutdown_1min[] =
- "\nThe evaluation of Qt will SHUT DOWN in 1 minute.\n"
- "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n";
-
-static const char will_shutdown_now[] =
- "\nThe evaluation of Qt has now reached its automatic\n"
- "timeout and will shut down.\n"
- "Contact http://www.qt.io/contact-us for pricing and purchasing information.\n";
-
-enum EvaluationStatus {
- EvaluationNotSupported = 0,
- EvaluationSupportedButTimeLimited,
- EvaluationSupported
-};
-
-static EvaluationStatus qt_eval_is_supported()
-{
- const volatile char *const license_key = qt_eval_key_data + 12;
-
- // fast fail
- if (!qt_eval_key_data[0] || !*license_key)
- return EvaluationNotSupported;
-
- // is this an unsupported evaluation?
- const volatile char *typecode = license_key;
- int field = 2;
- for ( ; field && *typecode; ++typecode)
- if (*typecode == '-')
- --field;
-
- if (!field && typecode[1] == '4' && typecode[2] == 'M') {
- if (typecode[0] == 'Q')
- return EvaluationSupportedButTimeLimited;
- else if (typecode[0] == 'R' || typecode[0] == 'Z')
- return EvaluationSupported;
- }
- return EvaluationNotSupported;
-}
-
-static int qt_eval_days_left()
-{
- const volatile char *const expiry_date = qt_eval_expiry_date + 12;
-
- QDate today = QDate::currentDate();
- QDate lastday = QDate::fromString(
- QString::fromLatin1(const_cast<const char*>(expiry_date)), Qt::ISODate);
- return today.daysTo(lastday);
-}
-
-static bool qt_eval_is_expired()
-{
- return qt_eval_days_left() < 0;
-}
-
-static QString qt_eval_string()
-{
- const char *msg;
- switch (qt_eval_is_supported()) {
- case EvaluationSupportedButTimeLimited:
- msg = boilerplate_supported_but_time_limited;
- break;
- case EvaluationSupported:
- msg = boilerplate_supported;
- break;
- default:
- return QString();
- }
-
- return QString::fromLatin1(msg)
- .arg(QLatin1String(QT_VERSION_STR))
- .arg(QLibraryInfo::licensee())
- .arg(qt_eval_days_left());
-}
-
-#define WARN_TIMEOUT 60 * 1000 * 119
-#define KILL_DELAY 60 * 1000 * 1
-
-class QCoreFuriCuri : public QObject
-{
-public:
-
- int warn;
- int kill;
-
- QCoreFuriCuri() : QObject(), warn(-1), kill(-1)
- {
- if (qt_eval_is_supported() == EvaluationSupportedButTimeLimited) {
- warn = startTimer(WARN_TIMEOUT);
- kill = 0;
- }
- }
-
- void timerEvent(QTimerEvent *e) override {
- if (e->timerId() == warn) {
- killTimer(warn);
- fprintf(stderr, "%s\n", will_shutdown_1min);
- kill = startTimer(KILL_DELAY);
- } else if (e->timerId() == kill) {
- fprintf(stderr, "%s\n", will_shutdown_now);
- QCoreApplication::instance()->quit();
- }
- }
-};
-
-#if defined(QT_BUILD_CORE_LIB) || defined (QT_BOOTSTRAPPED)
-
-void qt_core_eval_init(QCoreApplicationPrivate::Type type)
-{
- if (type != QCoreApplicationPrivate::Tty)
- return;
-
- if (!qt_eval_is_supported())
- return;
-
- if (qt_eval_is_expired()) {
- fprintf(stderr, "%s\n", boilerplate_expired);
- exit(0);
- } else {
- fprintf(stderr, "%s\n", qPrintable(qt_eval_string()));
- Q_UNUSED(new QCoreFuriCuri());
- }
-}
-#endif
-
-#ifdef QT_BUILD_WIDGETS_LIB
-
-QT_BEGIN_INCLUDE_NAMESPACE
-#include <qdialog.h>
-#include <qlabel.h>
-#include <qlayout.h>
-#include <qmessagebox.h>
-#if QT_CONFIG(pushbutton)
-#include <qpushbutton.h>
-#endif
-#include <qtimer.h>
-#include <qapplication.h>
-QT_END_INCLUDE_NAMESPACE
-
-
-static const char * const qtlogo_eval_xpm[] = {
-/* columns rows colors chars-per-pixel */
-"46 55 174 2",
-" c #002E02",
-". c #00370D",
-"X c #003A0E",
-"o c #003710",
-"O c #013C13",
-"+ c #043E1A",
-"@ c #084F0A",
-"# c #0B520C",
-"$ c #054413",
-"% c #0C4C17",
-"& c #07421D",
-"* c #09451D",
-"= c #0D491E",
-"- c #125515",
-"; c #13541A",
-": c #17591B",
-"> c #1B5C1D",
-", c #1F611F",
-"< c #20621E",
-"1 c #337B1E",
-"2 c #0B4521",
-"3 c #0F4923",
-"4 c #114B24",
-"5 c #154D2A",
-"6 c #175323",
-"7 c #1C5924",
-"8 c #1C532F",
-"9 c #1E5432",
-"0 c #245936",
-"q c #265938",
-"w c #295C3B",
-"e c #246324",
-"r c #266823",
-"t c #2A6C24",
-"y c #276628",
-"u c #2D7026",
-"i c #327427",
-"p c #367927",
-"a c #37782A",
-"s c #397C2A",
-"d c #2E613E",
-"f c #336C37",
-"g c #2F6040",
-"h c #356545",
-"j c #3C6B4E",
-"k c #3F6C51",
-"l c #406E4F",
-"z c #406D52",
-"x c #477457",
-"c c #497557",
-"v c #4B7857",
-"b c #517B5E",
-"n c #3C8423",
-"m c #3E812C",
-"M c #53A61D",
-"N c #41862C",
-"B c #458A2D",
-"V c #498F2D",
-"C c #479324",
-"Z c #489226",
-"A c #4D952C",
-"S c #478B30",
-"D c #488C30",
-"F c #4D9232",
-"G c #509632",
-"H c #549A33",
-"J c #589F35",
-"K c #56A526",
-"L c #57A821",
-"P c #5BAA27",
-"I c #57A32A",
-"U c #5CA72E",
-"Y c #5DAB2A",
-"T c #5CA336",
-"R c #60AD2E",
-"E c #63B12D",
-"W c #65AF35",
-"Q c #62A53F",
-"! c #65AE39",
-"~ c #66B036",
-"^ c #6AB437",
-"/ c #67B138",
-"( c #6AB339",
-") c #6DB838",
-"_ c #70BA3C",
-"` c #4D8545",
-"' c #4E8942",
-"] c #548851",
-"[ c #6FAF4A",
-"{ c #6DB243",
-"} c #71B546",
-"| c #70B840",
-" . c #73B648",
-".. c #79BA4E",
-"X. c #7CBB53",
-"o. c #598266",
-"O. c #62886D",
-"+. c #6A8F75",
-"@. c #6B9173",
-"#. c #70937A",
-"$. c #799F79",
-"%. c #7BAF66",
-"&. c #81BD5B",
-"*. c #85BF60",
-"=. c #85AC7F",
-"-. c #8DBA7B",
-";. c #87C061",
-":. c #8AC364",
-">. c #8DC46A",
-",. c #90C56E",
-"<. c #93C771",
-"1. c #96CA73",
-"2. c #9ACB7C",
-"3. c #9FD07D",
-"4. c #779981",
-"5. c #7F9F89",
-"6. c #809F88",
-"7. c #82A18B",
-"8. c #86A192",
-"9. c #8DA994",
-"0. c #8FA998",
-"q. c #94AF9B",
-"w. c #97B991",
-"e. c #97B19E",
-"r. c #9DB6A3",
-"t. c #A3BCA7",
-"y. c #A6BCAB",
-"u. c #A9BEB1",
-"i. c #9ECD81",
-"p. c #A2CF85",
-"a. c #A5D284",
-"s. c #A6D189",
-"d. c #A9D28E",
-"f. c #ABD491",
-"g. c #B1D797",
-"h. c #B1D699",
-"j. c #B5D89E",
-"k. c #ADC5AC",
-"l. c #B1CAAE",
-"z. c #B9DAA3",
-"x. c #BDDDA8",
-"c. c #ADC1B4",
-"v. c #B2C6B6",
-"b. c #B5C6BC",
-"n. c #B6C9BA",
-"m. c #BCD1BA",
-"M. c #C6E1B4",
-"N. c #CDE5BD",
-"B. c #C2D2C6",
-"V. c #CADEC2",
-"C. c #C6D3CC",
-"Z. c #C8D7CB",
-"A. c #CEDAD2",
-"S. c #D2DDD4",
-"D. c #D3E9C6",
-"F. c #D7EBC9",
-"G. c #D9EBCD",
-"H. c #DEEED4",
-"J. c #D6E0D9",
-"K. c #DAE4DC",
-"L. c #E0EFD7",
-"P. c #E5F2DD",
-"I. c #DFE8E0",
-"U. c #E4EBE5",
-"Y. c #E9EFEA",
-"T. c #EDF4EB",
-"R. c #F0FAE6",
-"E. c #F1F8EC",
-"W. c #EDF0F0",
-"Q. c #F4F7F3",
-"!. c #F6F9F4",
-"~. c #F8FAF7",
-"^. c #FEFEFE",
-"/. c None",
-/* pixels */
-"/././././.c h ' Q / W _ &.p././././././././././././././././././././././././././././././././.",
-"/././.4 O % Z ~ ~ W ~ W R U R R ( X.>.p././././././././././././././././././././././././././.",
-"/./.. * = J _ ~ ~ ~ ~ ~ / / / / W W U P P U W .;.2././././././././././././././././././././.",
-"/.= = & a ) W ~ ~ ~ ~ ~ / W / ~ ~ ~ ^ ( ( ^ ~ R R U P Y ~ .;.2././././././././././././././.",
-"O.O = = T ^ W ~ ~ ~ ~ ~ ~ W W / W ~ ~ ~ ~ ~ ~ ~ ( ( ( ( ~ W Y Y Y Y W { &.1././././././././.",
-"0 = * 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ / / W ~ ~ ~ ~ ~ ~ ~ ~ W W W ~ ~ ~ ~ ( ( ( W W R U P U W { X.1.f./.",
-"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ / / ~ ~ ~ ~ ~ ~ ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ^ ( ( / ~ W R U U Y ",
-"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W ~ ~ ~ ^ ^ ( ",
-"= = * e ^ W ~ ~ ~ ~ ~ ~ / W / W ! ( / ~ W ^ ( ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ~ W W ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ ! ~ ~ ~ ~ ~ ~ W W ^ _ ~ K Y W W R P Y W ( ~ ~ ~ ~ ~ ~ ~ W / ~ ~ ~ ^ W ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ W ~ ~ ~ ~ ~ ~ W ) W 1 ` w.V.L.H.D.z.,.~ Y ^ ~ ~ ~ ~ ~ W ~ ~ ~ ( ~ W W ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ W ~ ~ ~ ~ ~ W ) V = 8.~.^.^.^.^.^.^.^.U.<.Y ~ ~ ~ ~ ~ W W ! ~ Y W ^ W ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ W ~ ~ ~ ~ W ^ B O u.^.~.^.^.^.^.~.~.^.^.^.h.Y ^ ~ ~ ^ F $ k.R.G.1.Y / ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ ~ ~ ~ / W ( J X 7.^.~.^.^.^.^.^.^.^.^.^.^.^.s.Y / W ) a 2 U.^.^.d.U ( ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ W / ~ ~ ~ ^ > w ~.^.^.^.^.^.F.%.v c.^.^.^.^.~.X.W ~ ^ > h ^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ W ~ ~ W ^ H o e.^.^.^.^.^.G.Y E n . y.^.^.^.^.M.Y ( ! $ @.^.~.^.f.U ( / ~ ~ W ~ ~ ",
-"= = & e ^ W ~ W ! ) t 4 U.^.^.^.^.^.>.U ( _ , 9 ~.^.^.^.~...^ A y.^.~.^.s.M W Y ~ ~ ~ ~ ~ ",
-"= 3 & e ^ W ~ ( ^ ( $ c ^.^.^.^.^.E.) ~ ~ ^ S o n.^.^.^.^.=.- l.v.Y.^.^.^.M.:.:.X.~ ~ ~ ~ ~ ",
-"= = & e ^ ! W W ( J X 7.^.^.^.^.^.F.Y ( W ^ T X 6.^.^.~.^.c.. J.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ",
-"= = & r ^ W / W ) B o v.^.~.^.^.^.M.U / ~ ~ ! $ o.^.^.^.^.K.* S.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ",
-"= = & e ^ ! ~ W ) a + S.^.^.^.^.^.z.P ( W ~ ( % z ^.^.^.^.~.f t.U.^.^.^.^.~.^.^.P.~ ~ ~ ~ ~ ",
-"* = & e ^ W ~ W ) t 3 Y.^.^.^.^.^.f.P ( ~ ~ ^ ; h ^.^.^.^.^.:.@ j ^.^.^.^.h.{ X.&.~ ~ ~ ~ ~ ",
-"3 = & e ^ W ~ ~ ^ e 8 Q.^.^.^.^.^.s.P ~ ~ W ^ > 0 ~.^.^.^.^.1.# z ^.^.^.^.d.L W R ~ ~ ~ ~ ~ ",
-"= = & e ^ W ~ ~ ^ > q ~.^.^.^.^.^.p.U ^ ~ W ) e 9 ~.^.^.^.^.3.# k ^.^.^.^.f.Y ( / ~ ~ ~ ~ ~ ",
-"= = & e ^ W / W ^ > w ~.^.^.^.^.^.i.Y / ~ W ^ e 8 Q.^.^.^.^.a.# z ^.^.^.^.f.Y / ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ W / W ^ > w ^.^.^.^.^.^.2.Y / ~ ~ ) e 8 Q.^.^.^.^.s.# z ^.^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ W W W ^ > q ^.^.^.^.^.^.p.Y / ~ ~ ^ e 9 Q.^.^.^.^.a.@ z ^.^.^.^.f.U / ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ W / W ) 7 9 Q.^.^.^.^.^.a.P / ~ W ) , 9 Q.^.^.^.^.3.# z ^.^.~.^.f.P ^ ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ W / W ) r 5 T.^.^.^.^.^.d.Y / ~ W ) > q ~.^.^.^.^.1.# k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ / / W ) i 2 I.^.^.^.^.^.h.P ( ~ W ( > g ^.^.^.^.^.:.# z ^.^.^.^.f.P / ~ ~ ~ ~ ~ ~ ",
-"= = & e ( W / W ) m O Z.^.^.^.^.^.x.P / ~ ~ ( ; j ^.^.^.^.~.&.- k ^.^.~.^.f.P / ~ ~ ~ ~ ~ ~ ",
-"= = & e ( W / W ) F o y.^.~.^.^.^.N.U ( ~ ~ W $ b ^.^.^.^.R._ - k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ W ~ ~ ^ J X 4.^.^.^.^.^.L.~ ~ W ^ T X #.^.^.^.^.F.~ ; j ^.^.^.^.f.U ( ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ ~ ~ ~ / ^ % l ^.^.^.^.^.!. .R ^ ^ G . r.^.~.^.^.j.E : j ^.^.^.^.f.P ) ( ~ ~ ~ ~ ~ ",
-"= = & e ^ W ~ ~ W ) u = U.^.^.^.^.^.1.Y ! ) a & K.^.^.^.^.;.~ : j ^.^.~.^.z.M I I / ~ ~ W ~ ",
-"= = & e ( W ~ ~ W ( G . q.^.^.^.^.^.D.U ^ ! X o.^.^.^.^.P.~ ^ > g ^.^.^.^.E.-.$.m.X.W ~ ~ ~ ",
-"= = & e ^ / ~ ~ ^ ! ( > w ~.^.^.^.^.^.h.T > j T.^.^.~.^.a.Y _ i 3 U.^.^.^.^.^.^.^.X.R ~ ~ ~ ",
-"= = & e ^ / ~ ~ W W ^ H . 9.^.~.^.^.^.^.K.C.~.^.^.^.^.H.W W ^ T . q.^.~.^.^.^.^.^.X.R ~ ~ ~ ",
-"= = + e ^ W / ~ W W W ) m + B.^.~.^.^.^.^.^.^.^.^.^.E.X.Y ( W ^ B 6 y.^.^.^.E.D.2.( ~ ~ ~ ~ ",
-"= = * e ^ ! / ! W ^ W W ) a 4 b.^.^.^.^.^.^.^.^.^.P...Y ( ! W ! ^ W Z [ *.X.{ Y U ~ ~ ~ ~ ~ ",
-"= = & e ( W ~ ~ W / W / W ) A < +.A.~.^.^.^.^.!.p.W R ~ ~ ~ ~ ~ W / ) E U W W / ^ ~ ~ ~ ~ ~ ",
-"= = & e ^ W ~ ~ / W / / / W ( _ Z X 6.^.^.^.^.E.W ~ ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ / ~ ~ ~ ~ ~ ~ ~ ~ ",
-"= = & e ^ ~ ~ ~ W W / W ~ ~ ~ ~ ) ; h ^.^.^.^.^.d.M U ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ",
-"= = & e ^ W ~ ~ ^ W W / ~ ~ ~ W ) p + S.^.^.^.^.~.M.f. .W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ .",
-"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( T O +.^.~.^.^.^.^.^.&.Y ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( Y 2.",
-"= = & e ( W ~ ~ ~ ~ ~ ~ ~ ~ ~ / W ) N + b.^.^.^.^.^.^.&.R ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W /.",
-"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ^ N 7 r.W.^.^.^.!.X.W ~ ~ W ~ W ~ ~ ~ ~ ~ ~ / ( ( K p./.",
-"= = & e ( W ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W C Q &.:.X.| ~ ~ ~ ~ W ~ / ~ ( / ( ~ W E U P 1././.",
-"= = + e ^ / / / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W / ) ^ R Y W W ~ ~ ( / ( / W R Y Y U R ( X.,././././.",
-"= = * e ( / ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W ! ( ( ( W W E U P Y W ( X.,.d./././././././././.",
-"= = * e ( W ~ ~ ~ ~ W ! ~ W ~ W ~ ( ( / ^ W W U Y P W ( X.,.d./././././././././././././././.",
-"8 $ * e ( W ~ ~ ~ ! ( ( ( / ( W R Y Y Y R ( X.>.d./././././././././././././././././././././.",
-"/.d . y ^ / / / ( W Y Y P P W ( X.>.d./././././././././././././././././././././././././././.",
-"/./.h : ^ R R R W ( X.<.f./././././././././././././././././././././././././././././././././.",
-"/././.] _ *.3./././././././././././././././././././././././././././././././././././././././."
-};
-
-class EvalMessageBox : public QDialog
-{
-public:
- EvalMessageBox(bool expired)
- {
- setWindowTitle(QLatin1String(" "));
-
- QString str = expired ? QLatin1String(boilerplate_expired) : qt_eval_string();
- str = str.trimmed();
-
- QFrame *border = new QFrame(this);
-
- QLabel *pixmap_label = new QLabel(border);
- pixmap_label->setPixmap(QPixmap(qtlogo_eval_xpm));
- pixmap_label->setAlignment(Qt::AlignTop);
-
- QLabel *text_label = new QLabel(str, border);
-
- QHBoxLayout *pm_and_text_layout = new QHBoxLayout();
- pm_and_text_layout->addWidget(pixmap_label);
- pm_and_text_layout->addWidget(text_label);
-
- QVBoxLayout *master_layout = new QVBoxLayout(border);
- master_layout->addLayout(pm_and_text_layout);
-
- QVBoxLayout *border_layout = new QVBoxLayout(this);
- border_layout->setMargin(0);
- border_layout->addWidget(border);
-
- if (expired) {
- QPushButton *cmd = new QPushButton(QLatin1String("OK"), border);
- cmd->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- cmd->setDefault(true);
-
- QHBoxLayout *button_layout = new QHBoxLayout();
- master_layout->addLayout(button_layout);
- button_layout->addWidget(cmd);
-
- connect(cmd, SIGNAL(clicked()), this, SLOT(close()));
- } else {
- border->setFrameShape(QFrame::WinPanel);
- border->setFrameShadow(QFrame::Raised);
- setParent(parentWidget(), Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
- QTimer::singleShot(7000, this, SLOT(close()));
- setAttribute(Qt::WA_DeleteOnClose);
- setAttribute(Qt::WA_QuitOnClose, false);
- }
-
- setFixedSize(sizeHint());
- }
-};
-
-class QGuiFuriCuri : public QCoreFuriCuri
-{
-public:
- void timerEvent(QTimerEvent *e) {
- if (e->timerId() == warn) {
- killTimer(warn);
- QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_1min));
- kill = startTimer(KILL_DELAY);
- } else if (e->timerId() == kill) {
- killTimer(kill);
- QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_now));
- qApp->quit();
- }
- }
-};
-
-
-void qt_gui_eval_init(QCoreApplicationPrivate::Type type)
-{
- Q_UNUSED(type);
-
- if (!qt_eval_is_supported())
- return;
-
- if (qt_eval_is_expired()) {
- EvalMessageBox box(true);
- box.exec();
- ::exit(0);
- } else {
- Q_UNUSED(new QGuiFuriCuri());
- }
-}
-
-static QString qt_eval_title_prefix()
-{
- return QLatin1String("[Qt Evaluation] ");
-}
-
-QString qt_eval_adapt_window_title(const QString &title)
-{
- if (!qt_eval_is_supported())
- return title;
- return qt_eval_title_prefix() + title;
-}
-
-void qt_eval_init_widget(QWidget *w)
-{
- if (!qt_eval_is_supported())
- return;
- if (w->isTopLevel() && w->windowTitle().isEmpty() && w->windowType() != Qt::Desktop ) {
- w->setWindowTitle(QLatin1String(" "));
- }
-}
-#endif
-
-QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtestsupport_core.cpp b/src/corelib/kernel/qtestsupport_core.cpp
index c54b933f94..7bd81ed498 100644
--- a/src/corelib/kernel/qtestsupport_core.cpp
+++ b/src/corelib/kernel/qtestsupport_core.cpp
@@ -102,7 +102,7 @@ Q_CORE_EXPORT void QTest::qWait(int ms)
int remaining = ms;
do {
QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
- QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
remaining = timer.remainingTime();
if (remaining <= 0)
break;
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index 13f027074a..178227e914 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -42,6 +42,8 @@
#include "qabstracteventdispatcher.h"
#include "qcoreapplication.h"
#include "qobject_p.h"
+#include "qthread.h"
+#include "qcoreapplication_p.h"
QT_BEGIN_NAMESPACE
@@ -343,6 +345,33 @@ void QTimer::singleShotImpl(int msec, Qt::TimerType timerType,
const QObject *receiver,
QtPrivate::QSlotObjectBase *slotObj)
{
+ if (msec == 0) {
+ bool deleteReceiver = false;
+ // Optimize: set a receiver context when none is given, such that we can use
+ // QMetaObject::invokeMethod which is more efficient than going through a timer.
+ // We need a QObject living in the current thread. But the QThread itself lives
+ // in a different thread - with the exception of the main QThread which lives in
+ // itself. And QThread::currentThread() is among the few QObjects we know that will
+ // most certainly be there. Note that one can actually call singleShot before the
+ // QApplication is created!
+ if (!receiver && QThread::currentThread() == QCoreApplicationPrivate::mainThread()) {
+ // reuse main thread as context object
+ receiver = QThread::currentThread();
+ } else if (!receiver) {
+ // Create a receiver context object on-demand. According to the benchmarks,
+ // this is still more efficient than going through a timer.
+ receiver = new QObject;
+ deleteReceiver = true;
+ }
+
+ QMetaObject::invokeMethodImpl(const_cast<QObject *>(receiver), slotObj,
+ Qt::QueuedConnection, nullptr);
+
+ if (deleteReceiver)
+ const_cast<QObject *>(receiver)->deleteLater();
+ return;
+ }
+
new QSingleShotTimer(msec, timerType, receiver, slotObj);
}
@@ -599,7 +628,7 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
*/
/*!
- \fn template <typename PointerToMemberFunction> QMetaObject::Connection QTimer::callOnTimeout(const QObject *receiver, PointerToMemberFunction slot, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \fn template <typename MemberFunction> QMetaObject::Connection QTimer::callOnTimeout(const QObject *receiver, MemberFunction *slot, Qt::ConnectionType connectionType = Qt::AutoConnection)
\since 5.12
\overload callOnTimeout()
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index 66f317c567..eb7185c12d 100644
--- a/src/corelib/kernel/qtimer.h
+++ b/src/corelib/kernel/qtimer.h
@@ -100,8 +100,8 @@ public:
QMetaObject::Connection callOnTimeout(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
template <typename Functor>
QMetaObject::Connection callOnTimeout(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
- template <typename PointerToMemberFunction>
- QMetaObject::Connection callOnTimeout(const QObject *receiver, PointerToMemberFunction slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
+ template <typename MemberFunction>
+ QMetaObject::Connection callOnTimeout(const QObject *receiver, MemberFunction *slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
#else
// singleShot to a QObject slot
template <typename Duration, typename Func1>
@@ -218,7 +218,7 @@ private:
inline int startTimer(int){ return -1;}
inline void killTimer(int){}
- static Q_DECL_CONSTEXPR Qt::TimerType defaultTypeFor(int msecs) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR Qt::TimerType defaultTypeFor(int msecs) noexcept
{ return msecs >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer; }
static void singleShotImpl(int msec, Qt::TimerType timerType,
const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
diff --git a/src/corelib/kernel/qtimerinfo_unix.cpp b/src/corelib/kernel/qtimerinfo_unix.cpp
index c3b8c86063..39010c19cb 100644
--- a/src/corelib/kernel/qtimerinfo_unix.cpp
+++ b/src/corelib/kernel/qtimerinfo_unix.cpp
@@ -215,7 +215,7 @@ static timespec roundToMillisecond(timespec val)
QDebug operator<<(QDebug s, timeval tv)
{
QDebugStateSaver saver(s);
- s.nospace() << tv.tv_sec << "." << qSetFieldWidth(6) << qSetPadChar(QChar(48)) << tv.tv_usec << reset;
+ s.nospace() << tv.tv_sec << "." << qSetFieldWidth(6) << qSetPadChar(QChar(48)) << tv.tv_usec << Qt::reset;
return s;
}
QDebug operator<<(QDebug s, Qt::TimerType t)
@@ -373,7 +373,7 @@ static void calculateNextTimeout(QTimerInfo *t, timespec currentTime)
#ifdef QTIMERINFO_DEBUG
if (t->timerType != Qt::PreciseTimer)
- qDebug() << "timer" << t->timerType << hex << t->id << dec << "interval" << t->interval
+ qDebug() << "timer" << t->timerType << Qt::hex << t->id << Qt::dec << "interval" << t->interval
<< "originally expected at" << t->expected << "will fire at" << t->timeout
<< "or" << (t->timeout - t->expected) << "s late";
#endif
@@ -500,7 +500,7 @@ void QTimerInfoList::registerTimer(int timerId, int interval, Qt::TimerType time
t->cumulativeError = 0;
t->count = 0;
if (t->timerType != Qt::PreciseTimer)
- qDebug() << "timer" << t->timerType << hex <<t->id << dec << "interval" << t->interval << "expected at"
+ qDebug() << "timer" << t->timerType << Qt::hex <<t->id << Qt::dec << "interval" << t->interval << "expected at"
<< t->expected << "will fire first at" << t->timeout;
#endif
}
@@ -620,7 +620,7 @@ int QTimerInfoList::activateTimers()
currentTimerInfo->cumulativeError += diff;
++currentTimerInfo->count;
if (currentTimerInfo->timerType != Qt::PreciseTimer)
- qDebug() << "timer" << currentTimerInfo->timerType << hex << currentTimerInfo->id << dec << "interval"
+ qDebug() << "timer" << currentTimerInfo->timerType << Qt::hex << currentTimerInfo->id << Qt::dec << "interval"
<< currentTimerInfo->interval << "firing at" << currentTime
<< "(orig" << currentTimerInfo->expected << "scheduled at" << currentTimerInfo->timeout
<< ") off by" << diff << "activation" << currentTimerInfo->count
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index 63aeed07c3..dc0ab9f08a 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -61,14 +61,8 @@
#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
#define QT_USE_MMAP
#include "private/qcore_unix_p.h"
-#endif
-
-// most of the headers below are already included in qplatformdefs.h
-// also this lacks Large File support but that's probably irrelevant
-#if defined(QT_USE_MMAP)
// for mmap
#include <sys/mman.h>
-#include <errno.h>
#endif
#include <stdlib.h>
@@ -303,7 +297,7 @@ public:
bool used_mmap : 1;
#endif
char *unmapPointer; // used memory (mmap, new or resource file)
- quint32 unmapLength;
+ qsizetype unmapLength;
// The resource object in case we loaded the translations from a resource
QResource *resource;
@@ -323,7 +317,7 @@ public:
uint numerusRulesLength;
bool do_load(const QString &filename, const QString &directory);
- bool do_load(const uchar *data, int len, const QString &directory);
+ bool do_load(const uchar *data, qsizetype len, const QString &directory);
QString do_translate(const char *context, const char *sourceText, const char *comment,
int n) const;
void clear();
@@ -554,7 +548,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
return false;
qint64 fileSize = file.size();
- if (fileSize < MagicLength || quint32(-1) <= fileSize)
+ if (fileSize < MagicLength || fileSize > std::numeric_limits<qsizetype>::max())
return false;
{
@@ -564,7 +558,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
return false;
}
- d->unmapLength = quint32(fileSize);
+ d->unmapLength = qsizetype(fileSize);
#ifdef QT_USE_MMAP
@@ -572,21 +566,20 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
#define MAP_FILE 0
#endif
#ifndef MAP_FAILED
-#define MAP_FAILED -1
+#define MAP_FAILED reinterpret_cast<void *>(-1)
#endif
int fd = file.handle();
if (fd >= 0) {
- char *ptr;
- ptr = reinterpret_cast<char *>(
- mmap(0, d->unmapLength, // any address, whole file
- PROT_READ, // read-only memory
- MAP_FILE | MAP_PRIVATE, // swap-backed map from file
- fd, 0)); // from offset 0 of fd
- if (ptr && ptr != reinterpret_cast<char *>(MAP_FAILED)) {
+ int protection = PROT_READ; // read-only memory
+ int flags = MAP_FILE | MAP_PRIVATE; // swap-backed map from file
+ void *ptr = QT_MMAP(nullptr, d->unmapLength,// any address, whole file
+ protection, flags,
+ fd, 0); // from offset 0 of fd
+ if (ptr != MAP_FAILED) {
file.close();
d->used_mmap = true;
- d->unmapPointer = ptr;
+ d->unmapPointer = static_cast<char *>(ptr);
ok = true;
}
}
@@ -816,7 +809,7 @@ static quint32 read32(const uchar *data)
return qFromBigEndian<quint32>(data);
}
-bool QTranslatorPrivate::do_load(const uchar *data, int len, const QString &directory)
+bool QTranslatorPrivate::do_load(const uchar *data, qsizetype len, const QString &directory)
{
bool ok = true;
const uchar *end = data + len;
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 090436a3c7..511dc3c81c 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2018 Intel Corporation.
** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
@@ -55,6 +55,7 @@
#include "qstringlist.h"
#include "qurl.h"
#include "qlocale.h"
+#include "qregexp.h"
#include "quuid.h"
#if QT_CONFIG(itemmodel)
#include "qabstractitemmodel.h"
@@ -118,19 +119,19 @@ namespace { // annonymous used to hide QVariant handlers
static void construct(QVariant::Private *x, const void *copy)
{
QVariantConstructor<CoreTypesFilter> constructor(x, copy);
- QMetaTypeSwitcher::switcher<void>(constructor, x->type, 0);
+ QMetaTypeSwitcher::switcher<void>(constructor, x->type);
}
static void clear(QVariant::Private *d)
{
QVariantDestructor<CoreTypesFilter> cleaner(d);
- QMetaTypeSwitcher::switcher<void>(cleaner, d->type, 0);
+ QMetaTypeSwitcher::switcher<void>(cleaner, d->type);
}
static bool isNull(const QVariant::Private *d)
{
QVariantIsNull<CoreTypesFilter> isNull(d);
- return QMetaTypeSwitcher::switcher<bool>(isNull, d->type, 0);
+ return QMetaTypeSwitcher::switcher<bool>(isNull, d->type);
}
/*!
@@ -142,7 +143,7 @@ static bool isNull(const QVariant::Private *d)
static bool compare(const QVariant::Private *a, const QVariant::Private *b)
{
QVariantComparator<CoreTypesFilter> comparator(a, b);
- return QMetaTypeSwitcher::switcher<bool>(comparator, a->type, 0);
+ return QMetaTypeSwitcher::switcher<bool>(comparator, a->type);
}
/*!
@@ -1400,7 +1401,7 @@ static void streamDebug(QDebug dbg, const QVariant &v)
{
QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
QVariantDebugStream<CoreTypesFilter> stream(dbg, d);
- QMetaTypeSwitcher::switcher<void>(stream, d->type, 0);
+ QMetaTypeSwitcher::switcher<void>(stream, d->type);
}
#endif
@@ -1409,16 +1410,16 @@ const QVariant::Handler qt_kernel_variant_handler = {
clear,
isNull,
#ifndef QT_NO_DATASTREAM
- 0,
- 0,
+ nullptr,
+ nullptr,
#endif
compare,
convert,
- 0,
+ nullptr,
#if !defined(QT_NO_DEBUG_STREAM)
streamDebug
#else
- 0
+ nullptr
#endif
};
@@ -1435,16 +1436,16 @@ const QVariant::Handler qt_dummy_variant_handler = {
dummyClear,
dummyIsNull,
#ifndef QT_NO_DATASTREAM
- 0,
- 0,
+ nullptr,
+ nullptr,
#endif
dummyCompare,
dummyConvert,
- 0,
+ nullptr,
#if !defined(QT_NO_DEBUG_STREAM)
dummyStreamDebug
#else
- 0
+ nullptr
#endif
};
@@ -1462,6 +1463,7 @@ static void customConstruct(QVariant::Private *d, const void *copy)
if (size <= sizeof(QVariant::Private::Data)
&& (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) {
type.construct(&d->data.ptr, copy);
+ d->is_null = d->data.ptr == nullptr;
d->is_shared = false;
} else {
// Private::Data contains long long, and long double is the biggest standard type.
@@ -1472,6 +1474,7 @@ static void customConstruct(QVariant::Private *d, const void *copy)
void *data = operator new(offset + size);
void *ptr = static_cast<char *>(data) + offset;
type.construct(ptr, copy);
+ d->is_null = ptr == nullptr;
d->is_shared = true;
d->data.shared = new (data) QVariant::PrivateShared(ptr);
}
@@ -1552,16 +1555,16 @@ const QVariant::Handler qt_custom_variant_handler = {
customClear,
customIsNull,
#ifndef QT_NO_DATASTREAM
- 0,
- 0,
+ nullptr,
+ nullptr,
#endif
customCompare,
customConvert,
- 0,
+ nullptr,
#if !defined(QT_NO_DEBUG_STREAM)
customStreamDebug
#else
- 0
+ nullptr
#endif
};
@@ -1768,7 +1771,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
\fn QVariant::QVariant(int typeId, const void *copy)
Constructs variant of type \a typeId, and initializes with
- \a copy if \a copy is not 0.
+ \a copy if \a copy is not \nullptr.
Note that you have to pass the address of the variable you want stored.
@@ -1797,7 +1800,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
\internal
Constructs a variant private of type \a type, and initializes with \a copy if
- \a copy is not 0.
+ \a copy is not \nullptr.
*/
void QVariant::create(int type, const void *copy)
@@ -2122,7 +2125,7 @@ QVariant::QVariant(const char *val)
*/
QVariant::QVariant(Type type)
-{ create(type, 0); }
+{ create(type, nullptr); }
QVariant::QVariant(int typeId, const void *copy)
{ create(typeId, copy); d.is_null = false; }
@@ -2363,7 +2366,7 @@ QVariant& QVariant::operator=(const QVariant &variant)
void QVariant::detach()
{
- if (!d.is_shared || d.data.shared->ref.load() == 1)
+ if (!d.is_shared || d.data.shared->ref.loadRelaxed() == 1)
return;
Private dd;
@@ -2408,7 +2411,7 @@ void QVariant::clear()
Converts the int representation of the storage type, \a typeId, to
its string representation.
- Returns a null pointer if the type is QMetaType::UnknownType or doesn't exist.
+ Returns \nullptr if the type is QMetaType::UnknownType or doesn't exist.
*/
const char *QVariant::typeToName(int typeId)
{
@@ -2664,7 +2667,7 @@ inline T qVariantToHelper(const QVariant::Private &d, const HandlersManager &han
return ret;
}
- handlerManager[d.type]->convert(&d, targetType, &ret, 0);
+ handlerManager[d.type]->convert(&d, targetType, &ret, nullptr);
return ret;
}
@@ -3214,7 +3217,7 @@ bool QVariant::toBool() const
return d.data.b;
bool res = false;
- handlerManager[d.type]->convert(&d, Bool, &res, 0);
+ handlerManager[d.type]->convert(&d, Bool, &res, nullptr);
return res;
}
@@ -3732,7 +3735,7 @@ bool QVariant::convert(int targetTypeId)
if (!oldValue.canConvert(targetTypeId))
return false;
- create(targetTypeId, 0);
+ create(targetTypeId, nullptr);
// Fail if the value is not initialized or was forced null by a previous failed convert.
if (oldValue.d.is_null && oldValue.d.type != QMetaType::Nullptr)
return false;
@@ -3757,7 +3760,7 @@ bool QVariant::convert(int targetTypeId)
*/
bool QVariant::convert(const int type, void *ptr) const
{
- return handlerManager[type]->convert(&d, type, ptr, 0);
+ return handlerManager[type]->convert(&d, type, ptr, nullptr);
}
@@ -4002,8 +4005,8 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private *
return 0;
// only do fuzzy comparisons for finite, non-zero numbers
- int c1 = std::fpclassify(r1);
- int c2 = std::fpclassify(r2);
+ int c1 = qFpClassify(r1);
+ int c2 = qFpClassify(r2);
if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) {
if (qFuzzyCompare(r1, r2))
return 0;
@@ -4144,7 +4147,7 @@ void* QVariant::data()
/*!
Returns \c true if this is a null variant, false otherwise. A variant is
considered null if it contains no initialized value, or the contained value
- is a null pointer or is an instance of a built-in type that has an isNull
+ is \nullptr or is an instance of a built-in type that has an isNull
method, in which case the result would be the same as calling isNull on the
wrapped object.
@@ -4224,7 +4227,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
If the QVariant contains a pointer to a type derived from QObject then
\c{T} may be any QObject type. If the pointer stored in the QVariant can be
- qobject_cast to T, then that result is returned. Otherwise a null pointer is
+ qobject_cast to T, then that result is returned. Otherwise \nullptr is
returned. Note that this only works for QObject subclasses which use the
Q_OBJECT macro.
@@ -4280,6 +4283,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa fromValue()
*/
+#if QT_DEPRECATED_SINCE(5, 14)
/*!
\fn template<typename T> QVariant qVariantFromValue(const T &value)
\relates QVariant
@@ -4317,6 +4321,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa QVariant::setValue()
*/
+#endif
/*!
\fn template<typename T> T qvariant_cast(const QVariant &value)
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index ff73c27b6e..c8cb551863 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -55,6 +55,8 @@
#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
#include <variant>
+#elif defined(Q_CLANG_QDOC)
+namespace std { template<typename...> struct variant; }
#endif
QT_BEGIN_NAMESPACE
@@ -90,9 +92,6 @@ class QUrl;
class QVariant;
class QVariantComparisonHelper;
-template <typename T>
-inline QVariant qVariantFromValue(const T &);
-
template<typename T>
inline T qvariant_cast(const QVariant &);
@@ -202,7 +201,7 @@ class Q_CORE_EXPORT QVariant
LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
};
- QVariant() Q_DECL_NOTHROW : d() {}
+ QVariant() noexcept : d() {}
~QVariant();
QVariant(Type type);
QVariant(int typeId, const void *copy);
@@ -268,14 +267,12 @@ class Q_CORE_EXPORT QVariant
#endif
QVariant& operator=(const QVariant &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QVariant(QVariant &&other) Q_DECL_NOTHROW : d(other.d)
+ inline QVariant(QVariant &&other) noexcept : d(other.d)
{ other.d = Private(); }
- inline QVariant &operator=(QVariant &&other) Q_DECL_NOTHROW
+ inline QVariant &operator=(QVariant &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- inline void swap(QVariant &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ inline void swap(QVariant &other) noexcept { qSwap(d, other.d); }
Type type() const;
int userType() const;
@@ -363,9 +360,9 @@ class Q_CORE_EXPORT QVariant
template<typename T>
static inline QVariant fromValue(const T &value)
- { return qVariantFromValue(value); }
+ { return QVariant(qMetaTypeId<T>(), &value, QTypeInfo<T>::isPointer); }
-#if defined(Q_CLANG_QDOC) || (QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L)
+#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
template<typename... Types>
static inline QVariant fromStdVariant(const std::variant<Types...> &value)
{
@@ -388,18 +385,21 @@ class Q_CORE_EXPORT QVariant
};
struct Private
{
- inline Private() Q_DECL_NOTHROW : type(Invalid), is_shared(false), is_null(true)
+ inline Private() noexcept : type(Invalid), is_shared(false), is_null(true)
{ data.ptr = nullptr; }
// Internal constructor for initialized variants.
- explicit inline Private(uint variantType) Q_DECL_NOTHROW
+ explicit inline Private(uint variantType) noexcept
: type(variantType), is_shared(false), is_null(false)
{}
- inline Private(const Private &other) Q_DECL_NOTHROW
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ Private(const Private &other) noexcept
: data(other.data), type(other.type),
is_shared(other.is_shared), is_null(other.is_null)
{}
+ Private &operator=(const Private &other) noexcept = default;
+#endif
union Data
{
char c;
@@ -486,27 +486,27 @@ public:
private:
// force compile error, prevent QVariant(bool) to be called
- inline QVariant(void *) Q_DECL_EQ_DELETE;
+ inline QVariant(void *) = delete;
// QVariant::Type is marked as \obsolete, but we don't want to
// provide a constructor from its intended replacement,
// QMetaType::Type, instead, because the idea behind these
// constructors is flawed in the first place. But we also don't
// want QVariant(QMetaType::String) to compile and falsely be an
// int variant, so delete this constructor:
- QVariant(QMetaType::Type) Q_DECL_EQ_DELETE;
+ QVariant(QMetaType::Type) = delete;
// These constructors don't create QVariants of the type associcated
// with the enum, as expected, but they would create a QVariant of
// type int with the value of the enum value.
// Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
// example.
- QVariant(Qt::GlobalColor) Q_DECL_EQ_DELETE;
- QVariant(Qt::BrushStyle) Q_DECL_EQ_DELETE;
- QVariant(Qt::PenStyle) Q_DECL_EQ_DELETE;
- QVariant(Qt::CursorShape) Q_DECL_EQ_DELETE;
+ QVariant(Qt::GlobalColor) = delete;
+ QVariant(Qt::BrushStyle) = delete;
+ QVariant(Qt::PenStyle) = delete;
+ QVariant(Qt::CursorShape) = delete;
#ifdef QT_NO_CAST_FROM_ASCII
// force compile error when implicit conversion is not wanted
- inline QVariant(const char *) Q_DECL_EQ_DELETE;
+ inline QVariant(const char *) = delete;
#endif
public:
typedef Private DataPtr;
@@ -514,50 +514,61 @@ public:
inline const DataPtr &data_ptr() const { return d; }
};
+#if QT_DEPRECATED_SINCE(5, 14)
template <typename T>
+QT_DEPRECATED_X("Use QVariant::fromValue() instead.")
inline QVariant qVariantFromValue(const T &t)
{
- return QVariant(qMetaTypeId<T>(), &t, QTypeInfo<T>::isPointer);
+ return QVariant::fromValue(t);
+}
+
+template <typename T>
+QT_DEPRECATED_X("Use QVariant::setValue() instead.")
+inline void qVariantSetValue(QVariant &v, const T &t)
+{
+ v.setValue(t);
}
+#endif
-template <>
-inline QVariant qVariantFromValue(const QVariant &t) { return t; }
+template<>
+inline QVariant QVariant::fromValue(const QVariant &value)
+{
+ return value;
+}
#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
-template <>
-inline QVariant qVariantFromValue(const std::monostate &) { return QVariant(); }
+template<>
+inline QVariant QVariant::fromValue(const std::monostate &)
+{
+ return QVariant();
+}
#endif
-template <typename T>
-inline void qVariantSetValue(QVariant &v, const T &t)
+inline bool QVariant::isValid() const { return d.type != Invalid; }
+
+template<typename T>
+inline void QVariant::setValue(const T &avalue)
{
- //if possible we reuse the current QVariant private
+ // If possible we reuse the current QVariant private.
const uint type = qMetaTypeId<T>();
- QVariant::Private &d = v.data_ptr();
- if (v.isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) {
+ if (isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) {
d.type = type;
d.is_null = false;
T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
if (QTypeInfo<T>::isComplex)
old->~T();
- new (old) T(t); //call the copy constructor
+ new (old) T(avalue); // call the copy constructor
} else {
- v = QVariant(type, &t, QTypeInfo<T>::isPointer);
+ *this = QVariant(type, &avalue, QTypeInfo<T>::isPointer);
}
}
-template <>
-inline void qVariantSetValue<QVariant>(QVariant &v, const QVariant &t)
+template<>
+inline void QVariant::setValue(const QVariant &avalue)
{
- v = t;
+ *this = avalue;
}
-inline bool QVariant::isValid() const { return d.type != Invalid; }
-
-template<typename T>
-inline void QVariant::setValue(const T &avalue)
-{ qVariantSetValue(*this, avalue); }
-
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p);
Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p);
@@ -566,7 +577,7 @@ Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p);
#endif
inline bool QVariant::isDetached() const
-{ return !d.is_shared || d.data.shared->ref.load() == 1; }
+{ return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; }
#ifdef Q_QDOC
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index b22b7c231e..3d87beac83 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -88,7 +88,7 @@ inline T *v_cast(const QVariant::Private *nd, T * = 0)
#else // every other compiler in this world
template <typename T>
-inline const T *v_cast(const QVariant::Private *d, T * = 0)
+inline const T *v_cast(const QVariant::Private *d, T * = nullptr)
{
return !QVariantIntegrator<T>::CanUseInternalSpace
? static_cast<const T *>(d->data.shared->ptr)
@@ -96,7 +96,7 @@ inline const T *v_cast(const QVariant::Private *d, T * = 0)
}
template <typename T>
-inline T *v_cast(QVariant::Private *d, T * = 0)
+inline T *v_cast(QVariant::Private *d, T * = nullptr)
{
return !QVariantIntegrator<T>::CanUseInternalSpace
? static_cast<T *>(d->data.shared->ptr)
@@ -154,7 +154,7 @@ inline void v_construct(QVariant::Private *x, const T &t)
// constructs a new variant if copy is 0, otherwise copy-constructs
template <class T>
-inline void v_construct(QVariant::Private *x, const void *copy, T * = 0)
+inline void v_construct(QVariant::Private *x, const void *copy, T * = nullptr)
{
if (copy)
v_construct<T>(x, *static_cast<const T *>(copy));
@@ -164,7 +164,7 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0)
// deletes the internal structures
template <class T>
-inline void v_clear(QVariant::Private *d, T* = 0)
+inline void v_clear(QVariant::Private *d, T* = nullptr)
{
if (!QVariantIntegrator<T>::CanUseInternalSpace) {
@@ -264,7 +264,7 @@ class QVariantIsNull
struct No { char unused[2]; };
Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No));
- template<class C> static decltype(static_cast<const C*>(0)->isNull(), Yes()) test(int);
+ template<class C> static decltype(static_cast<const C*>(nullptr)->isNull(), Yes()) test(int);
template<class C> static No test(...);
public:
static const bool Value = (sizeof(test<T>(0)) == sizeof(Yes));
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index 3c73c0b851..d2ae9668fe 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -124,7 +124,7 @@ QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
: QObject(*new QWinEventNotifierPrivate(hEvent, false), parent)
{
Q_D(QWinEventNotifier);
- QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.loadRelaxed();
if (Q_UNLIKELY(!eventDispatcher)) {
qWarning("QWinEventNotifier: Can only be used with threads started with QThread");
return;
@@ -197,7 +197,7 @@ void QWinEventNotifier::setEnabled(bool enable)
return;
d->enabled = enable;
- QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.loadRelaxed();
if (!eventDispatcher) { // perhaps application is shutting down
if (!enable && d->waitHandle != nullptr)
d->unregisterWaitObject();
@@ -256,7 +256,7 @@ void QWinEventNotifierPrivate::unregisterWaitObject()
static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/)
{
QWinEventNotifierPrivate *nd = reinterpret_cast<QWinEventNotifierPrivate *>(context);
- QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.loadRelaxed();
// Happens when Q(Core)Application is destroyed before QWinEventNotifier.
// https://bugreports.qt.io/browse/QTBUG-70214
diff --git a/src/corelib/mimetypes/mime/packages/freedesktop.org.xml b/src/corelib/mimetypes/mime/packages/freedesktop.org.xml
index b749fe41ac..d384ffb2d5 100644
--- a/src/corelib/mimetypes/mime/packages/freedesktop.org.xml
+++ b/src/corelib/mimetypes/mime/packages/freedesktop.org.xml
@@ -64,20 +64,32 @@
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-atari-2600-rom">
<comment>Atari 2600</comment>
+ <comment xml:lang="ast">Atari 2600</comment>
<comment xml:lang="ca">Atari 2600</comment>
+ <comment xml:lang="cs">Atari 2600</comment>
<comment xml:lang="da">Atari 2600</comment>
<comment xml:lang="de">Atari 2600</comment>
+ <comment xml:lang="en_GB">Atari 2600</comment>
<comment xml:lang="es">Atari 2600</comment>
+ <comment xml:lang="eu">Atari 2600</comment>
<comment xml:lang="fi">Atari 2600</comment>
<comment xml:lang="fr">Atari 2600</comment>
+ <comment xml:lang="ga">Atari 2600</comment>
<comment xml:lang="he">×ט×רי 2600</comment>
+ <comment xml:lang="hr">Atari 2600</comment>
<comment xml:lang="hu">Atari 2600</comment>
+ <comment xml:lang="id">Atari 2600</comment>
+ <comment xml:lang="it">Atari 2600</comment>
<comment xml:lang="kk">Atari 2600</comment>
<comment xml:lang="ko">Atari 2600</comment>
+ <comment xml:lang="oc">Atari 2600</comment>
<comment xml:lang="pl">Atari 2600</comment>
<comment xml:lang="pt_BR">Atari 2600</comment>
<comment xml:lang="ru">Atari 2600</comment>
<comment xml:lang="sk">Atari 2600</comment>
+ <comment xml:lang="sr">Ðтари 2600</comment>
+ <comment xml:lang="sv">Atari 2600</comment>
+ <comment xml:lang="tr">Atari 2600</comment>
<comment xml:lang="uk">Atari 2600</comment>
<comment xml:lang="zh_CN">雅达利 2600</comment>
<comment xml:lang="zh_TW">Atari 2600</comment>
@@ -86,20 +98,32 @@
</mime-type>
<mime-type type="application/x-atari-7800-rom">
<comment>Atari 7800</comment>
+ <comment xml:lang="ast">Atari 7800</comment>
<comment xml:lang="ca">Atari 7800</comment>
+ <comment xml:lang="cs">Atari 7800</comment>
<comment xml:lang="da">Atari 7800</comment>
<comment xml:lang="de">Atari 7800</comment>
+ <comment xml:lang="en_GB">Atari 7800</comment>
<comment xml:lang="es">Atari 7800</comment>
+ <comment xml:lang="eu">Atari 7800</comment>
<comment xml:lang="fi">Atari 7800</comment>
<comment xml:lang="fr">Atari 7800</comment>
+ <comment xml:lang="ga">Atari 7800</comment>
<comment xml:lang="he">×ט×רי 7800</comment>
+ <comment xml:lang="hr">Atari 7800</comment>
<comment xml:lang="hu">Atari 7800</comment>
+ <comment xml:lang="id">Atari 7800</comment>
+ <comment xml:lang="it">Atari 7800</comment>
<comment xml:lang="kk">Atari 7800</comment>
<comment xml:lang="ko">Atari 7800</comment>
+ <comment xml:lang="oc">Atari 7800</comment>
<comment xml:lang="pl">Atari 7800</comment>
<comment xml:lang="pt_BR">Atari 7800</comment>
<comment xml:lang="ru">Atari 7800</comment>
<comment xml:lang="sk">Atari 7800</comment>
+ <comment xml:lang="sr">Ðтари 7800</comment>
+ <comment xml:lang="sv">Atari 7800</comment>
+ <comment xml:lang="tr">Atari 7800</comment>
<comment xml:lang="uk">Atari 7800</comment>
<comment xml:lang="zh_CN">雅达利 7800</comment>
<comment xml:lang="zh_TW">Atari 7800</comment>
@@ -109,6 +133,35 @@
<match value="ATARI7800" type="string" offset="1"/>
</magic>
</mime-type>
+ <mime-type type="application/x-atari-lynx-rom">
+ <comment>Atari Lynx</comment>
+ <comment xml:lang="ast">Atari Lynx</comment>
+ <comment xml:lang="ca">Atari Lynx</comment>
+ <comment xml:lang="cs">Atari Lynx</comment>
+ <comment xml:lang="de">Atari Lynx</comment>
+ <comment xml:lang="en_GB">Atari Lynx</comment>
+ <comment xml:lang="es">Atari Lynx</comment>
+ <comment xml:lang="fi">Atari Lynx</comment>
+ <comment xml:lang="hr">Atari Lynx</comment>
+ <comment xml:lang="hu">Atari Lynx</comment>
+ <comment xml:lang="id">Atari Lynx</comment>
+ <comment xml:lang="it">Atari Lynx</comment>
+ <comment xml:lang="kk">Atari Lynx</comment>
+ <comment xml:lang="ko">Atari Lynx</comment>
+ <comment xml:lang="pl">Atari Lynx</comment>
+ <comment xml:lang="pt_BR">Atari Lynx</comment>
+ <comment xml:lang="ru">Atari Lynx</comment>
+ <comment xml:lang="sk">Atari Lynx</comment>
+ <comment xml:lang="sv">Atari Lynx</comment>
+ <comment xml:lang="uk">Atari Lynx</comment>
+ <comment xml:lang="zh_CN">雅达利 Lynx</comment>
+ <comment xml:lang="zh_TW">Atari Lynx</comment>
+ <generic-icon name="application-x-executable"/>
+ <glob pattern="*.lnx"/>
+ <magic>
+ <match value="LYNX" type="string" offset="0"/>
+ </magic>
+ </mime-type>
<mime-type type="application/andrew-inset">
<comment>ATK inset</comment>
<comment xml:lang="ar">شكل ATK</comment>
@@ -146,7 +199,7 @@
<comment xml:lang="pt">Suplemento ATK</comment>
<comment xml:lang="pt_BR">Conjunto de entrada do ATK</comment>
<comment xml:lang="ro">Inset ATK</comment>
- <comment xml:lang="ru">вкладка ATK</comment>
+ <comment xml:lang="ru">Вкладка ATK</comment>
<comment xml:lang="sk">Vložka ATK</comment>
<comment xml:lang="sl">Vložka ATK</comment>
<comment xml:lang="sq">Inset ATK</comment>
@@ -165,6 +218,7 @@
<mime-type type="application/epub+zip">
<comment>electronic book document</comment>
<comment xml:lang="ar">مستند كتاب إلكتروني</comment>
+ <comment xml:lang="ast">documentu de llibru electrónicu</comment>
<comment xml:lang="be@latin">elektronnaja kniha</comment>
<comment xml:lang="bg">Документ — електронна книга</comment>
<comment xml:lang="ca">document de llibre electrònic</comment>
@@ -181,7 +235,7 @@
<comment xml:lang="ga">leabhar leictreonach</comment>
<comment xml:lang="gl">documento de libro electrónico</comment>
<comment xml:lang="he">מסמך מסוג ספר ×לקטרוני</comment>
- <comment xml:lang="hr">dokument elektroniÄke knjige</comment>
+ <comment xml:lang="hr">Dokument elektroniÄke knjige</comment>
<comment xml:lang="hu">elektronikus könyvdokumentum</comment>
<comment xml:lang="ia">Documento de libro electronic</comment>
<comment xml:lang="id">dokumen buku elektronik</comment>
@@ -198,7 +252,7 @@
<comment xml:lang="pt">documento de livro eletrónico</comment>
<comment xml:lang="pt_BR">Documento de livro eletrônico</comment>
<comment xml:lang="ro">document carte electronică</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ ÐºÐ½Ð¸Ð³Ð°</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ ÐºÐ½Ð¸Ð³Ð°</comment>
<comment xml:lang="sk">Dokument elektronickej knihy</comment>
<comment xml:lang="sl">dokument elektronske knjige</comment>
<comment xml:lang="sq">Dokument libri elektronik</comment>
@@ -224,6 +278,7 @@
<mime-type type="application/illustrator">
<comment>Adobe Illustrator document</comment>
<comment xml:lang="ar">مستند أدوبي المصور</comment>
+ <comment xml:lang="ast">Documentu d'Adobe Illustrator</comment>
<comment xml:lang="be@latin">Dakument Adobe Illustrator</comment>
<comment xml:lang="bg">Документ — Adobe Illustrator</comment>
<comment xml:lang="ca">document d'Adobe Illustrator</comment>
@@ -244,7 +299,7 @@
<comment xml:lang="hr">Adobe Illustrator dokument</comment>
<comment xml:lang="hu">Adobe Illustrator-dokumentum</comment>
<comment xml:lang="ia">Documento Adobe Illustrator</comment>
- <comment xml:lang="id">Dokumen Adobe Illustrator</comment>
+ <comment xml:lang="id">dokumen Adobe Illustrator</comment>
<comment xml:lang="it">Documento Adobe Illustrator</comment>
<comment xml:lang="ja">Adobe Illustrator ドキュメント</comment>
<comment xml:lang="ka">Adobe Illustrator-ის დáƒáƒ™áƒ£áƒ›áƒ”ნტი</comment>
@@ -261,11 +316,11 @@
<comment xml:lang="pt">documento Adobe Illustrator</comment>
<comment xml:lang="pt_BR">Documento do Adobe Illustrator</comment>
<comment xml:lang="ro">Document Adobe Illustrator</comment>
- <comment xml:lang="ru">документ Adobe Illustrator</comment>
+ <comment xml:lang="ru">Документ Adobe Illustrator</comment>
<comment xml:lang="sk">Dokument Adobe Illustrator</comment>
<comment xml:lang="sl">Dokument Adobe Illustrator</comment>
<comment xml:lang="sq">Dokument Adobe Illustrator</comment>
- <comment xml:lang="sr">документ Ðдобе ИлуÑтратора</comment>
+ <comment xml:lang="sr">документ Ðдобе илуÑтратора</comment>
<comment xml:lang="sv">Adobe Illustrator-dokument</comment>
<comment xml:lang="tr">Adobe Illustrator belgesi</comment>
<comment xml:lang="uk">документ Adobe Illustrator</comment>
@@ -274,10 +329,12 @@
<comment xml:lang="zh_TW">Adobe Illustrator 文件</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.ai"/>
+ <alias type="application/vnd.adobe.illustrator"/>
</mime-type>
<mime-type type="application/mac-binhex40">
<comment>Macintosh BinHex-encoded file</comment>
<comment xml:lang="ar">مل٠Macintosh BinHex مشÙر</comment>
+ <comment xml:lang="ast">Ficheru codificáu en BinHex de Machintosh</comment>
<comment xml:lang="az">Macintosh BinHex-kodlanmış fayl</comment>
<comment xml:lang="be@latin">Fajł Macintosh, BinHex-zakadavany</comment>
<comment xml:lang="bg">Файл — кодиран във формат BinHex за Macintosh</comment>
@@ -297,10 +354,10 @@
<comment xml:lang="ga">comhad ionchódaithe le Macintosh BinHex</comment>
<comment xml:lang="gl">ficheiro de Macintosh codificado con BinHex</comment>
<comment xml:lang="he">קובץ בקידוד Macintosh BinHex</comment>
- <comment xml:lang="hr">Macintosh BinHex-kodirana datoteka</comment>
+ <comment xml:lang="hr">Macintosh BinHex-kôdirana datoteka</comment>
<comment xml:lang="hu">Macintosh BinHex kódolású fájl</comment>
<comment xml:lang="ia">File codificate in BinHex de Macintosh</comment>
- <comment xml:lang="id">Berkas tersandi Macintosh BinHex</comment>
+ <comment xml:lang="id">berkas tersandi Macintosh BinHex</comment>
<comment xml:lang="it">File Macintosh codificato BinHex</comment>
<comment xml:lang="ja">Macintosh BinHex エンコードファイル</comment>
<comment xml:lang="kk">Macintosh BinHex кодталған файлы</comment>
@@ -316,7 +373,7 @@
<comment xml:lang="pt">ficheiro codificado em BinHex de Macintosh</comment>
<comment xml:lang="pt_BR">Arquivo do Macintosh codificado com BinHex</comment>
<comment xml:lang="ro">Fișier codat Macintosh BinHex</comment>
- <comment xml:lang="ru">файл (закодированный Macintosh BinHex)</comment>
+ <comment xml:lang="ru">Файл (закодированный Macintosh BinHex)</comment>
<comment xml:lang="sk">Súbor kódovaný pomocou Macintosh BinHex</comment>
<comment xml:lang="sl">Kodirana datoteka Macintosh (BinHex)</comment>
<comment xml:lang="sq">File Macintosh i kodifikuar BinHex</comment>
@@ -393,6 +450,7 @@
<mime-type type="application/mathml+xml">
<comment>MathML document</comment>
<comment xml:lang="ar">مستند MathML</comment>
+ <comment xml:lang="ast">Documentu MathML</comment>
<comment xml:lang="az">MathML sənədi</comment>
<comment xml:lang="be@latin">Dakument MathML</comment>
<comment xml:lang="bg">Документ — MathML</comment>
@@ -415,7 +473,7 @@
<comment xml:lang="hr">MathML dokument</comment>
<comment xml:lang="hu">MathML-dokumentum</comment>
<comment xml:lang="ia">Documento MathML</comment>
- <comment xml:lang="id">Dokumen MathML</comment>
+ <comment xml:lang="id">dokumen MathML</comment>
<comment xml:lang="it">Documento MathML</comment>
<comment xml:lang="ja">MathML ドキュメント</comment>
<comment xml:lang="ka">MathML-ის დáƒáƒ™áƒ£áƒ›áƒ”ნტი</comment>
@@ -432,7 +490,7 @@
<comment xml:lang="pt">documento MathML</comment>
<comment xml:lang="pt_BR">Documento do MathML</comment>
<comment xml:lang="ro">Document MathML</comment>
- <comment xml:lang="ru">документ MathML</comment>
+ <comment xml:lang="ru">Документ MathML</comment>
<comment xml:lang="sk">Dokument MathML</comment>
<comment xml:lang="sl">Dokument MathML</comment>
<comment xml:lang="sq">Dokument MathML</comment>
@@ -469,7 +527,7 @@
<comment xml:lang="ga">comhad bhosca poist</comment>
<comment xml:lang="gl">ficheiro de caixa de correo</comment>
<comment xml:lang="he">קובץ תיבת-דו×ר</comment>
- <comment xml:lang="hr">datoteka poÅ¡tanskog sanduÄića</comment>
+ <comment xml:lang="hr">Datoteka poÅ¡tanskog sanduÄića</comment>
<comment xml:lang="hu">mailbox fájl</comment>
<comment xml:lang="ia">File de cassa postal</comment>
<comment xml:lang="id">berkas kotak surat</comment>
@@ -487,7 +545,7 @@
<comment xml:lang="pt">ficheiro de caixa de correio</comment>
<comment xml:lang="pt_BR">Arquivo de caixa de correio</comment>
<comment xml:lang="ro">fișier căsuță poștală</comment>
- <comment xml:lang="ru">файл почтового Ñщика</comment>
+ <comment xml:lang="ru">Файл почтового Ñщика</comment>
<comment xml:lang="sk">Súbor mailbox</comment>
<comment xml:lang="sl">datoteka poštnega predala</comment>
<comment xml:lang="sq">File mailbox</comment>
@@ -496,7 +554,7 @@
<comment xml:lang="tr">posta kutusu dosyası</comment>
<comment xml:lang="uk">файл поштової Ñкриньки</comment>
<comment xml:lang="vi">tập tin hộp thư</comment>
- <comment xml:lang="zh_CN">mailbox 文件</comment>
+ <comment xml:lang="zh_CN">邮箱文件</comment>
<comment xml:lang="zh_TW">郵箱檔</comment>
<generic-icon name="text-x-generic"/>
<sub-class-of type="text/plain"/>
@@ -508,6 +566,7 @@
<mime-type type="application/metalink+xml">
<comment>Metalink file</comment>
<comment xml:lang="ar">مل٠ميتالنك</comment>
+ <comment xml:lang="ast">Ficheru d'enllaz meta</comment>
<comment xml:lang="bg">ИзтеглÑне — Metalink</comment>
<comment xml:lang="ca">fitxer Metalink</comment>
<comment xml:lang="cs">soubor metalink</comment>
@@ -527,7 +586,7 @@
<comment xml:lang="hr">Datoteka meta poveznice</comment>
<comment xml:lang="hu">Metalink fájl</comment>
<comment xml:lang="ia">File Metalink</comment>
- <comment xml:lang="id">Berkas Metalink</comment>
+ <comment xml:lang="id">berkas Metalink</comment>
<comment xml:lang="it">File Metalink</comment>
<comment xml:lang="ja">Metalink ファイル</comment>
<comment xml:lang="kk">Metalink файлы</comment>
@@ -540,14 +599,14 @@
<comment xml:lang="pt">ficheiro Metalink</comment>
<comment xml:lang="pt_BR">Arquivo Metalink</comment>
<comment xml:lang="ro">Fișier Metalink</comment>
- <comment xml:lang="ru">файл Metalink</comment>
+ <comment xml:lang="ru">Файл Metalink</comment>
<comment xml:lang="sk">Súbor Metalink</comment>
<comment xml:lang="sl">Datoteka povezave Metalink</comment>
<comment xml:lang="sr">датотека метавезе</comment>
<comment xml:lang="sv">Metalink-fil</comment>
<comment xml:lang="tr">Metalink dosyası</comment>
<comment xml:lang="uk">файл метапоÑиланнÑ</comment>
- <comment xml:lang="zh_CN">元链接文件</comment>
+ <comment xml:lang="zh_CN">Metalink 文件</comment>
<comment xml:lang="zh_TW">Metalink 檔案</comment>
<sub-class-of type="application/xml"/>
<magic priority="50">
@@ -559,6 +618,7 @@
<mime-type type="application/metalink4+xml">
<comment>Metalink file</comment>
<comment xml:lang="ar">مل٠ميتالنك</comment>
+ <comment xml:lang="ast">Ficheru d'enllaz meta</comment>
<comment xml:lang="bg">ИзтеглÑне — Metalink</comment>
<comment xml:lang="ca">fitxer Metalink</comment>
<comment xml:lang="cs">soubor metalink</comment>
@@ -578,7 +638,7 @@
<comment xml:lang="hr">Datoteka meta poveznice</comment>
<comment xml:lang="hu">Metalink fájl</comment>
<comment xml:lang="ia">File Metalink</comment>
- <comment xml:lang="id">Berkas Metalink</comment>
+ <comment xml:lang="id">berkas Metalink</comment>
<comment xml:lang="it">File Metalink</comment>
<comment xml:lang="ja">Metalink ファイル</comment>
<comment xml:lang="kk">Metalink файлы</comment>
@@ -591,14 +651,14 @@
<comment xml:lang="pt">ficheiro Metalink</comment>
<comment xml:lang="pt_BR">Arquivo Metalink</comment>
<comment xml:lang="ro">Fișier Metalink</comment>
- <comment xml:lang="ru">файл Metalink</comment>
+ <comment xml:lang="ru">Файл Metalink</comment>
<comment xml:lang="sk">Súbor Metalink</comment>
<comment xml:lang="sl">Datoteka povezave Metalink</comment>
<comment xml:lang="sr">датотека метавезе</comment>
<comment xml:lang="sv">Metalink-fil</comment>
<comment xml:lang="tr">Metalink dosyası</comment>
<comment xml:lang="uk">файл метапоÑиланнÑ</comment>
- <comment xml:lang="zh_CN">元链接文件</comment>
+ <comment xml:lang="zh_CN">Metalink 文件</comment>
<comment xml:lang="zh_TW">Metalink 檔案</comment>
<sub-class-of type="application/xml"/>
<magic priority="50">
@@ -610,12 +670,13 @@
<mime-type type="application/octet-stream">
<comment>unknown</comment>
<comment xml:lang="ar">مجهول</comment>
+ <comment xml:lang="ast">desconozse</comment>
<comment xml:lang="be@latin">nieviadomy</comment>
<comment xml:lang="bg">ÐеизвеÑтен тип</comment>
<comment xml:lang="ca">desconegut</comment>
<comment xml:lang="cs">neznámý</comment>
<comment xml:lang="da">ukendt</comment>
- <comment xml:lang="de">Unbekannt</comment>
+ <comment xml:lang="de">unbekannt</comment>
<comment xml:lang="el">Άγνωστο</comment>
<comment xml:lang="en_GB">unknown</comment>
<comment xml:lang="eo">nekonate</comment>
@@ -627,7 +688,7 @@
<comment xml:lang="ga">anaithnid</comment>
<comment xml:lang="gl">descoñecido</comment>
<comment xml:lang="he">×œ× ×™×“×•×¢</comment>
- <comment xml:lang="hr">nepoznato</comment>
+ <comment xml:lang="hr">Nepoznato</comment>
<comment xml:lang="hu">ismeretlen</comment>
<comment xml:lang="ia">incognite</comment>
<comment xml:lang="id">tak diketahui</comment>
@@ -647,7 +708,7 @@
<comment xml:lang="pt">desconhecido</comment>
<comment xml:lang="pt_BR">Desconhecido</comment>
<comment xml:lang="ro">necunoscut</comment>
- <comment xml:lang="ru">неизвеÑтно</comment>
+ <comment xml:lang="ru">ÐеизвеÑтно</comment>
<comment xml:lang="sk">Neznámy</comment>
<comment xml:lang="sl">neznano</comment>
<comment xml:lang="sq">Nuk njihet</comment>
@@ -658,10 +719,10 @@
<comment xml:lang="vi">không rõ</comment>
<comment xml:lang="zh_CN">未知</comment>
<comment xml:lang="zh_TW">ä¸æ˜Ž</comment>
- <glob pattern="*.bin"/>
</mime-type>
<mime-type type="application/x-partial-download">
<comment>Partially downloaded file</comment>
+ <comment xml:lang="ast">Ficheru baxáu parcialmente</comment>
<comment xml:lang="ca">fitxer baixat parcialment</comment>
<comment xml:lang="cs">ÄásteÄnÄ› stažený soubor</comment>
<comment xml:lang="da">Delvist hentet fil</comment>
@@ -672,6 +733,7 @@
<comment xml:lang="eu">Partzialki deskargatutako fitxategia</comment>
<comment xml:lang="fi">Osittain ladattu tiedosto</comment>
<comment xml:lang="fr">fichier partiellement téléchargé</comment>
+ <comment xml:lang="ga">Comhad leath-íoslódáilte</comment>
<comment xml:lang="gl">Ficheiro descargado parcialmente</comment>
<comment xml:lang="he">קובץ שהתקבל חלקית</comment>
<comment xml:lang="hr">DjelomiÄno preuzeta datoteka</comment>
@@ -692,7 +754,7 @@
<comment xml:lang="sv">Delvis hämtad fil</comment>
<comment xml:lang="tr">Kısmen indirilmiş dosya</comment>
<comment xml:lang="uk">чаÑтково отриманий файл</comment>
- <comment xml:lang="zh_CN">下载的部分文件</comment>
+ <comment xml:lang="zh_CN">部分下载的文件</comment>
<comment xml:lang="zh_TW">已部份下載的檔案</comment>
<generic-icon name="package-x-generic"/>
<glob pattern="*.wkdownload"/>
@@ -702,6 +764,7 @@
<mime-type type="application/oda">
<comment>ODA document</comment>
<comment xml:lang="ar">مستند ODA</comment>
+ <comment xml:lang="ast">Documentu ODA</comment>
<comment xml:lang="az">ODA sənədi</comment>
<comment xml:lang="be@latin">Dakument ODA</comment>
<comment xml:lang="bg">Документ — ODA</comment>
@@ -741,7 +804,7 @@
<comment xml:lang="pt">documento ODA</comment>
<comment xml:lang="pt_BR">Documento ODA</comment>
<comment xml:lang="ro">Document ODA</comment>
- <comment xml:lang="ru">документ ODA</comment>
+ <comment xml:lang="ru">Документ ODA</comment>
<comment xml:lang="sk">Dokument ODA</comment>
<comment xml:lang="sl">Dokument ODA</comment>
<comment xml:lang="sq">Dokument ODA</comment>
@@ -759,6 +822,7 @@
</mime-type>
<mime-type type="application/x-wwf">
<comment>WWF document</comment>
+ <comment xml:lang="ast">Documentu WWF</comment>
<comment xml:lang="bg">Документ — WWF</comment>
<comment xml:lang="ca">document WWF</comment>
<comment xml:lang="cs">dokument WWF</comment>
@@ -771,6 +835,7 @@
<comment xml:lang="eu">WWF dokumentua</comment>
<comment xml:lang="fi">WWF-asiakirja</comment>
<comment xml:lang="fr">document WWF</comment>
+ <comment xml:lang="ga">cáipéis WWF</comment>
<comment xml:lang="gl">documento de WWF</comment>
<comment xml:lang="he">מסמך WWF</comment>
<comment xml:lang="hr">WWF dokument</comment>
@@ -788,7 +853,7 @@
<comment xml:lang="pl">Dokument WWF</comment>
<comment xml:lang="pt">documento WWF</comment>
<comment xml:lang="pt_BR">Documento WWF</comment>
- <comment xml:lang="ru">документ WWF</comment>
+ <comment xml:lang="ru">Документ WWF</comment>
<comment xml:lang="sk">Dokument WWF</comment>
<comment xml:lang="sl">Dokument WWF</comment>
<comment xml:lang="sr">ВВФ документ</comment>
@@ -805,6 +870,7 @@
<mime-type type="application/pdf">
<comment>PDF document</comment>
<comment xml:lang="ar">مستند PDF</comment>
+ <comment xml:lang="ast">Documentu PDF</comment>
<comment xml:lang="be@latin">Dakument PDF</comment>
<comment xml:lang="bg">Документ — PDF</comment>
<comment xml:lang="ca">document PDF</comment>
@@ -842,7 +908,7 @@
<comment xml:lang="pt">documento PDF</comment>
<comment xml:lang="pt_BR">Documento PDF</comment>
<comment xml:lang="ro">Document PDF</comment>
- <comment xml:lang="ru">документ PDF</comment>
+ <comment xml:lang="ru">Документ PDF</comment>
<comment xml:lang="sk">Dokument PDF</comment>
<comment xml:lang="sl">Dokument PDF</comment>
<comment xml:lang="sq">Dokument PDF</comment>
@@ -868,6 +934,7 @@
<mime-type type="application/xspf+xml">
<comment>XSPF playlist</comment>
<comment xml:lang="ar">قائمة تشغيل XSPF</comment>
+ <comment xml:lang="ast">Llista de reproducción XSPF</comment>
<comment xml:lang="be@latin">Śpis piesień XSPF</comment>
<comment xml:lang="bg">СпиÑък за изпълнение — XSPF</comment>
<comment xml:lang="ca">llista de reproducció XSPF</comment>
@@ -885,7 +952,7 @@
<comment xml:lang="ga">seinmliosta XSPF</comment>
<comment xml:lang="gl">lista de reprodución XSPF</comment>
<comment xml:lang="he">רשימת נגינה XSPF</comment>
- <comment xml:lang="hr">XSPF popis za reprodukciju</comment>
+ <comment xml:lang="hr">XSPF popis izvođenja</comment>
<comment xml:lang="hu">XSPF-lejátszólista</comment>
<comment xml:lang="ia">Lista de selection XSPF</comment>
<comment xml:lang="id">Senarai pular XSPF</comment>
@@ -903,7 +970,7 @@
<comment xml:lang="pt">lista de reprodução XSPF</comment>
<comment xml:lang="pt_BR">Lista de reprodução XSPF</comment>
<comment xml:lang="ro">Listă XSPF</comment>
- <comment xml:lang="ru">ÑпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ XSPF</comment>
+ <comment xml:lang="ru">СпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ XSPF</comment>
<comment xml:lang="sk">Zoznam skladieb XSPF</comment>
<comment xml:lang="sl">Seznam predvajanja XSPF</comment>
<comment xml:lang="sq">Listë titujsh XSPF</comment>
@@ -929,11 +996,12 @@
<mime-type type="application/x-windows-themepack">
<comment>Microsoft Windows theme pack</comment>
<comment xml:lang="ar">حزمة سمات Microsoft Works</comment>
+ <comment xml:lang="ast">Paquete de temes de Microsoft Windows</comment>
<comment xml:lang="bg">Пакет Ñ Ñ‚ÐµÐ¼Ð° — Microsoft Windows</comment>
<comment xml:lang="ca">paquet de temes de Microsoft Windows</comment>
<comment xml:lang="cs">balík motivů Microsoft Windows</comment>
<comment xml:lang="da">Microsoft Windows-temapakke</comment>
- <comment xml:lang="de">Themenpaket für Microsoft Windows</comment>
+ <comment xml:lang="de">Microsoft-Windows-Themenpaket</comment>
<comment xml:lang="el">Πακέτο θέματος Microsoft Windows</comment>
<comment xml:lang="en_GB">Microsoft Windows theme pack</comment>
<comment xml:lang="es">paquete de tema para Microsoft Windows</comment>
@@ -961,7 +1029,7 @@
<comment xml:lang="pt">pacote de tema Microsoft Windows</comment>
<comment xml:lang="pt_BR">Pacote de temas do Microsoft Windows</comment>
<comment xml:lang="ro">Pachet de teme Microsoft Windows</comment>
- <comment xml:lang="ru">пакет темы Microsoft Windows</comment>
+ <comment xml:lang="ru">Пакет темы Microsoft Windows</comment>
<comment xml:lang="sk">Balík tém Microsoft Windows</comment>
<comment xml:lang="sl">Datoteka teme Microsoft Windows</comment>
<comment xml:lang="sr">пакет теме МајкроÑофт Виндоуза</comment>
@@ -976,6 +1044,7 @@
</mime-type>
<mime-type type="audio/x-amzxml">
<comment>AmazonMP3 download file</comment>
+ <comment xml:lang="ast">Ficheru de descarga AmazonMP3</comment>
<comment xml:lang="ca">fitxer baixat d'AmazonMP3</comment>
<comment xml:lang="cs">soubor stahování AmazonMP3</comment>
<comment xml:lang="da">AmazonMP3-downloadfil</comment>
@@ -985,6 +1054,7 @@
<comment xml:lang="es">archivo de descarga de AmazonMP3</comment>
<comment xml:lang="eu">AmazonMP3 deskarga fitxategia</comment>
<comment xml:lang="fr">fichier téléchargé AmazonMP3</comment>
+ <comment xml:lang="ga">comhad íoslódáilte AmazonMP3</comment>
<comment xml:lang="gl">Ficheiro de descarga de AmazonMP3</comment>
<comment xml:lang="he">קובץ הורדת AmazonMP3</comment>
<comment xml:lang="hr">AmazonMP3 preuzeta datoteka</comment>
@@ -1000,7 +1070,7 @@
<comment xml:lang="pl">Pobrany plik AmazonMP3</comment>
<comment xml:lang="pt">ficheiro transferido AmazonMP3</comment>
<comment xml:lang="pt_BR">Arquivo de download AmazonMP3</comment>
- <comment xml:lang="ru">файл загрузки AmazonMP3</comment>
+ <comment xml:lang="ru">Файл загрузки AmazonMP3</comment>
<comment xml:lang="sk">Stiahnutý súbor AmazonMP3 </comment>
<comment xml:lang="sl">Datoteka prenosa AmazonMP3</comment>
<comment xml:lang="sr">датотека преузимања ÐмазонаМП3</comment>
@@ -1014,6 +1084,7 @@
<mime-type type="audio/x-gsm">
<comment>GSM 06.10 audio</comment>
<comment xml:lang="ar">GSM 06.10 سمعي</comment>
+ <comment xml:lang="ast">Audiu GSM 6.10</comment>
<comment xml:lang="bg">Ðудио — GSM 06.10</comment>
<comment xml:lang="ca">àudio de GSM 06.10</comment>
<comment xml:lang="cs">zvuk GSM 06.10</comment>
@@ -1029,7 +1100,7 @@
<comment xml:lang="ga">fuaim GSM 06.10</comment>
<comment xml:lang="gl">son de GSM 06.10</comment>
<comment xml:lang="he">שמע GSM 06.10</comment>
- <comment xml:lang="hr">GSM 06.10 audio</comment>
+ <comment xml:lang="hr">GSM 06.10 zvuÄni zapis</comment>
<comment xml:lang="hu">GSM 06.10 hang</comment>
<comment xml:lang="ia">Audio GSM 06.10</comment>
<comment xml:lang="id">Audio GSM 06.10</comment>
@@ -1046,7 +1117,7 @@
<comment xml:lang="pt">áudio GSM 06.10</comment>
<comment xml:lang="pt_BR">Ãudio GSM 06.10</comment>
<comment xml:lang="ro">GSM 06.10 audio</comment>
- <comment xml:lang="ru">аудио GSM 06.10</comment>
+ <comment xml:lang="ru">Ðудио GSM 06.10</comment>
<comment xml:lang="sk">Zvuk GSM 06.10</comment>
<comment xml:lang="sl">ZvoÄna datoteka GSM 06.10</comment>
<comment xml:lang="sr">ГСМ 06.10 звук</comment>
@@ -1063,6 +1134,7 @@
<mime-type type="audio/x-iriver-pla">
<comment>iRiver Playlist</comment>
<comment xml:lang="ar">قائمة تشغيل iRiver</comment>
+ <comment xml:lang="ast">Llista de reproducción iRiver</comment>
<comment xml:lang="be@latin">Śpis piesień iRiver</comment>
<comment xml:lang="bg">СпиÑък за изпълнение — iRiver</comment>
<comment xml:lang="ca">llista de reproducció iRiver</comment>
@@ -1080,7 +1152,7 @@
<comment xml:lang="ga">seinmliosta iRiver</comment>
<comment xml:lang="gl">lista de reprodución de iRiver</comment>
<comment xml:lang="he">רשימת נגינה של iRiver</comment>
- <comment xml:lang="hr">iRiver popis za reprodukciju</comment>
+ <comment xml:lang="hr">iRiver popis izvođenja</comment>
<comment xml:lang="hu">iRiver lejátszólista</comment>
<comment xml:lang="ia">Lista de selection iRiver</comment>
<comment xml:lang="id">iRiver Playlist</comment>
@@ -1098,7 +1170,7 @@
<comment xml:lang="pt">lista de reprodução iRiver</comment>
<comment xml:lang="pt_BR">Lista de reprodução do iRiver</comment>
<comment xml:lang="ro">Listă iRiver</comment>
- <comment xml:lang="ru">ÑпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ iRiver</comment>
+ <comment xml:lang="ru">СпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ iRiver</comment>
<comment xml:lang="sk">Zoznam skladieb iRiver</comment>
<comment xml:lang="sl">Seznam predvajanja iRiver</comment>
<comment xml:lang="sq">Listë titujsh iRiver</comment>
@@ -1117,6 +1189,7 @@
<mime-type type="application/pgp-encrypted">
<comment>PGP/MIME-encrypted message header</comment>
<comment xml:lang="ar">ترويسة رسالة PGP/MIME-مشÙرة</comment>
+ <comment xml:lang="ast">Testera de mensaxe cifrada en PGP/MIME</comment>
<comment xml:lang="be@latin">Zahałovak paviedamleńnia, zašyfravany ŭ PGP/MIME</comment>
<comment xml:lang="bg">Заглавна чаÑÑ‚ на шифрирано Ñъобщение — PGP/MIME</comment>
<comment xml:lang="ca">capçalera de missatge amb xifrat PGP/MIME</comment>
@@ -1153,7 +1226,7 @@
<comment xml:lang="pt">cabeçalho de mensagem encriptada com PGP/MIME</comment>
<comment xml:lang="pt_BR">Cabeçalho de mensagem criptografada PGP/MIME</comment>
<comment xml:lang="ro">Antet de mesaj encriptat PGP/MIME</comment>
- <comment xml:lang="ru">заголовок ÑообщениÑ, зашифрованный PGP/MIME</comment>
+ <comment xml:lang="ru">Заголовок ÑообщениÑ, зашифрованный PGP/MIME</comment>
<comment xml:lang="sk">HlaviÄke správy zaÅ¡ifrovaná pomocou PGP/MIME</comment>
<comment xml:lang="sl">Datoteka glave Å¡ifriranega sporoÄila PGP/MIME</comment>
<comment xml:lang="sq">Header mesazhi të kriptuar PGP/MIME</comment>
@@ -1177,6 +1250,7 @@
<mime-type type="application/pgp-keys">
<comment>PGP keys</comment>
<comment xml:lang="ar">Ù…Ùاتيح PGP</comment>
+ <comment xml:lang="ast">Claves PGP</comment>
<comment xml:lang="az">PGP açarları</comment>
<comment xml:lang="be@latin">KluÄy PGP</comment>
<comment xml:lang="bg">Ключове — PGP</comment>
@@ -1215,7 +1289,7 @@
<comment xml:lang="pt">chaves PGP</comment>
<comment xml:lang="pt_BR">Chaves PGP</comment>
<comment xml:lang="ro">Chei PGP</comment>
- <comment xml:lang="ru">ключи PGP</comment>
+ <comment xml:lang="ru">Ключи PGP</comment>
<comment xml:lang="sk">KľúÄe PGP</comment>
<comment xml:lang="sl">Datoteka kljuÄa PGP</comment>
<comment xml:lang="sq">Kyçe PGP</comment>
@@ -1252,7 +1326,7 @@
<comment xml:lang="ca">signatura OpenPGP abstreta</comment>
<comment xml:lang="cs">oddělený podpis OpenPGP</comment>
<comment xml:lang="da">frigjort OpenPGP-signatur</comment>
- <comment xml:lang="de">Isolierte OpenPGP-Signatur</comment>
+ <comment xml:lang="de">isolierte OpenPGP-Signatur</comment>
<comment xml:lang="el">Αποκομμένη υπογÏαφή OpenPGP</comment>
<comment xml:lang="en_GB">detached OpenPGP signature</comment>
<comment xml:lang="eo">dekroĉa OpenPGP-subskribo</comment>
@@ -1264,7 +1338,7 @@
<comment xml:lang="ga">síniú OpenPGP scartha</comment>
<comment xml:lang="gl">sinatura de OpenPGP independente</comment>
<comment xml:lang="he">חתימת OpenPGP מנותקת</comment>
- <comment xml:lang="hr">odvojen OpenPGP potpis</comment>
+ <comment xml:lang="hr">Odvojen OpenPGP potpis</comment>
<comment xml:lang="hu">leválasztott OpenPGP-aláírás</comment>
<comment xml:lang="ia">Signatura OpenPGP distachate</comment>
<comment xml:lang="id">tanda tangan OpenPGP yang terlepas</comment>
@@ -1283,7 +1357,7 @@
<comment xml:lang="pt">assinatura OpenPGP solta</comment>
<comment xml:lang="pt_BR">Assinatura OpenPGP destacada</comment>
<comment xml:lang="ro">semnătură OpenPGP detașată</comment>
- <comment xml:lang="ru">отÑÐ¾ÐµÐ´Ð¸Ð½Ñ‘Ð½Ð½Ð°Ñ Ð¿Ð¾Ð´Ð¿Ð¸ÑÑŒ OpenPGP</comment>
+ <comment xml:lang="ru">ОтÑÐ¾ÐµÐ´Ð¸Ð½Ñ‘Ð½Ð½Ð°Ñ Ð¿Ð¾Ð´Ð¿Ð¸ÑÑŒ OpenPGP</comment>
<comment xml:lang="sk">Oddelený podpis OpenPGP</comment>
<comment xml:lang="sl">odpet podpis OpenPGP</comment>
<comment xml:lang="sq">Firmë e shkëputur OpenPGP</comment>
@@ -1307,6 +1381,7 @@
<mime-type type="application/pkcs7-mime">
<comment>PKCS#7 Message or Certificate</comment>
+ <comment xml:lang="ast">Mensaxe o certificáu PKCS#7</comment>
<comment xml:lang="ca">missatge o certificat PKCS#7</comment>
<comment xml:lang="cs">zpráva nebo certifikát PKCS#7</comment>
<comment xml:lang="da">PKCS#7-besked eller certifikat</comment>
@@ -1317,6 +1392,7 @@
<comment xml:lang="eu">PKCS#7 mezu edo zertifikazioa</comment>
<comment xml:lang="fi">PKCS#7-viesti tai -varmenne</comment>
<comment xml:lang="fr">Message ou certificat PKCS#7</comment>
+ <comment xml:lang="ga">Teachtaireacht nó Teastas PKCS#7</comment>
<comment xml:lang="gl">Mensaxe ou certificado PKCS#7</comment>
<comment xml:lang="he">הודעה ×ו ×ישור מסוג PKCS#7</comment>
<comment xml:lang="hr">PKCS#7 poruka ili vjerodajnica</comment>
@@ -1332,7 +1408,7 @@
<comment xml:lang="pl">Wiadomość lub certyfikat PKCS#7</comment>
<comment xml:lang="pt">Mensagem ou certificado PKCS#7</comment>
<comment xml:lang="pt_BR">Certificado ou Mensagem PKCS#7</comment>
- <comment xml:lang="ru">Ñообщение или Ñертификат PKCS#7</comment>
+ <comment xml:lang="ru">Сообщение или Ñертификат PKCS#7</comment>
<comment xml:lang="sk">Správa alebo certifikát PKCS#7</comment>
<comment xml:lang="sl">SporoÄilo ali dovoljenje PKCS#7</comment>
<comment xml:lang="sr">ПКЦС#7 порука или уверење</comment>
@@ -1355,7 +1431,7 @@
<comment xml:lang="ca">signatura S/MIME abstreta</comment>
<comment xml:lang="cs">oddělený podpis S/MIME</comment>
<comment xml:lang="da">frigjort S/MIME-signatur</comment>
- <comment xml:lang="de">Isolierte S/MIME-Signatur</comment>
+ <comment xml:lang="de">isolierte S/MIME-Signatur</comment>
<comment xml:lang="el">Αποκομμένη υπογÏαφή S/MIME</comment>
<comment xml:lang="en_GB">detached S/MIME signature</comment>
<comment xml:lang="eo">dekroĉa S/MIME-subskribo</comment>
@@ -1367,7 +1443,7 @@
<comment xml:lang="ga">síniú S/MIME scartha</comment>
<comment xml:lang="gl">sinatura S/MIME independente</comment>
<comment xml:lang="he">חתימת S/MIME מנותקת</comment>
- <comment xml:lang="hr">odvojen S/MIME potpis</comment>
+ <comment xml:lang="hr">Odvojen S/MIME potpis</comment>
<comment xml:lang="hu">leválasztott S/MIME-aláírás</comment>
<comment xml:lang="ia">Signatura S/MIME distachate</comment>
<comment xml:lang="id">tanda tangan S/MIME yang terlepas</comment>
@@ -1386,7 +1462,7 @@
<comment xml:lang="pt">assinatura S/MIME solta</comment>
<comment xml:lang="pt_BR">Assinatura S/MIME destacada</comment>
<comment xml:lang="ro">semnătură S/MIME detașată</comment>
- <comment xml:lang="ru">отÑÐ¾ÐµÐ´Ð¸Ð½Ñ‘Ð½Ð½Ð°Ñ Ð¿Ð¾Ð´Ð¿Ð¸ÑÑŒ S/MIME</comment>
+ <comment xml:lang="ru">ОтÑÐ¾ÐµÐ´Ð¸Ð½Ñ‘Ð½Ð½Ð°Ñ Ð¿Ð¾Ð´Ð¿Ð¸ÑÑŒ S/MIME</comment>
<comment xml:lang="sk">Oddelený podpis S/MIME</comment>
<comment xml:lang="sl">odpet podpis S/MIME</comment>
<comment xml:lang="sq">Firmë e shkëputur S/MIME</comment>
@@ -1437,7 +1513,7 @@
<comment xml:lang="pt">chave privada PKCS#8</comment>
<comment xml:lang="pt_BR">Chave privada PKCS#8</comment>
<comment xml:lang="ro">Cheie privată PKCS#8</comment>
- <comment xml:lang="ru">личный ключ PKCS#8</comment>
+ <comment xml:lang="ru">Личный ключ PKCS#8</comment>
<comment xml:lang="sk">Súkromný kÄ¾ÃºÄ PKCS#8</comment>
<comment xml:lang="sl">Datoteka osebnega kljuÄa PKCS#8</comment>
<comment xml:lang="sr">ПКЦС#8 лични кључ</comment>
@@ -1450,6 +1526,12 @@
<expanded-acronym>Public-Key Cryptography Standards</expanded-acronym>
<glob pattern="*.p8"/>
</mime-type>
+ <mime-type type="application/pkcs8-encrypted">
+ <comment>PKCS#8 private key (encrypted)</comment>
+ <acronym>PKCS</acronym>
+ <expanded-acronym>Public-Key Cryptography Standards</expanded-acronym>
+ <glob pattern="*.p8e"/>
+ </mime-type>
<mime-type type="application/pkcs10">
<comment>PKCS#10 certification request</comment>
<comment xml:lang="ar">طلب شهادة PKCS#10</comment>
@@ -1487,7 +1569,7 @@
<comment xml:lang="pt">pedido de certificação PKCS#10</comment>
<comment xml:lang="pt_BR">Pedido de certificação PKCS#12</comment>
<comment xml:lang="ro">Cerere de certificat PKCS#10</comment>
- <comment xml:lang="ru">Ð·Ð°Ð¿Ñ€Ð¾Ñ Ñертификации PKCS#10</comment>
+ <comment xml:lang="ru">Ð—Ð°Ð¿Ñ€Ð¾Ñ Ñертификации PKCS#10</comment>
<comment xml:lang="sk">Požiadavka na certifikát PKCS#10</comment>
<comment xml:lang="sl">Datoteka potrdila PKCS#10</comment>
<comment xml:lang="sq">Kërkesë çertifikimi PKCS#10</comment>
@@ -1506,6 +1588,7 @@
<mime-type type="application/pkix-cert">
<comment>X.509 certificate</comment>
<comment xml:lang="ar">شهادة X.509</comment>
+ <comment xml:lang="ast">Certificáu X.509</comment>
<comment xml:lang="bg">Сертификат — X.509</comment>
<comment xml:lang="ca">certificat X.509</comment>
<comment xml:lang="cs">certifikát X.509</comment>
@@ -1521,7 +1604,7 @@
<comment xml:lang="ga">teastas X.509</comment>
<comment xml:lang="gl">Certificado X.509</comment>
<comment xml:lang="he">×ישור X.509</comment>
- <comment xml:lang="hr">X.509 certifikat</comment>
+ <comment xml:lang="hr">X.509 vjerodajnica</comment>
<comment xml:lang="hu">X.509 tanúsítvány</comment>
<comment xml:lang="ia">Certificato X.509</comment>
<comment xml:lang="id">Sertifikat X.509</comment>
@@ -1537,7 +1620,7 @@
<comment xml:lang="pt">certificado X.509</comment>
<comment xml:lang="pt_BR">Certificado X.509</comment>
<comment xml:lang="ro">Certificat X.509</comment>
- <comment xml:lang="ru">Ñертификат X.509</comment>
+ <comment xml:lang="ru">Сертификат X.509</comment>
<comment xml:lang="sk">Certifikát X.509</comment>
<comment xml:lang="sl">Datoteka potrdila X.509</comment>
<comment xml:lang="sr">ИкÑ.509 уверење</comment>
@@ -1551,6 +1634,7 @@
<mime-type type="application/pkix-crl">
<comment>Certificate revocation list</comment>
<comment xml:lang="ar">قائمة إبطال الشهادات</comment>
+ <comment xml:lang="ast">Llistáu de revocación de certificaos</comment>
<comment xml:lang="bg">СпиÑък Ñ Ð¾Ñ‚Ñ…Ð²ÑŠÑ€Ð»ÐµÐ½Ð¸ Ñертификати</comment>
<comment xml:lang="ca">llista de revocació de certificats</comment>
<comment xml:lang="cs">seznam odvolaných certifikátů</comment>
@@ -1563,10 +1647,10 @@
<comment xml:lang="fi">Varmenteiden sulkulista</comment>
<comment xml:lang="fo">Prógv afturtøkulisti</comment>
<comment xml:lang="fr">liste de révocation de certificat</comment>
- <comment xml:lang="ga">liosta teastas cúlghairmthe</comment>
+ <comment xml:lang="ga">Liosta teastas cúlghairmthe</comment>
<comment xml:lang="gl">lista de certificados de revogación</comment>
<comment xml:lang="he">רשימת ××™×©×•×¨×™× ×ž×‘×•×˜×œ×™×</comment>
- <comment xml:lang="hr">popis povuÄenih certifikata</comment>
+ <comment xml:lang="hr">Popis opozvanih vjerodajnica</comment>
<comment xml:lang="hu">Tanúsítvány-visszavonási lista</comment>
<comment xml:lang="ia">Lista de revocation de certificatos</comment>
<comment xml:lang="id">Daftar pencabutan sertificat (CRL)</comment>
@@ -1596,6 +1680,7 @@
<mime-type type="application/pkix-pkipath">
<comment>PkiPath certification path</comment>
<comment xml:lang="ar">مسار شهادة PkiPath</comment>
+ <comment xml:lang="ast">Camín de certificación PkiPath</comment>
<comment xml:lang="bg">Сертификационна верига — PkiPath</comment>
<comment xml:lang="ca">camí cap a la certificació PkiPath</comment>
<comment xml:lang="cs">cesta k certifikátu PkiPath</comment>
@@ -1627,7 +1712,7 @@
<comment xml:lang="pt">caminho de certificação PkiPath</comment>
<comment xml:lang="pt_BR">Pedido de certificação PkiPath</comment>
<comment xml:lang="ro">Cale certificare PkiPath</comment>
- <comment xml:lang="ru">путь Ñертификации PkiPath</comment>
+ <comment xml:lang="ru">Путь Ñертификации PkiPath</comment>
<comment xml:lang="sk">Cesta k certifikátu PkiPath</comment>
<comment xml:lang="sl">Datoteka poti potrdila PkiPath</comment>
<comment xml:lang="sr">путања уверења ПкиПат-а</comment>
@@ -1642,6 +1727,7 @@
<mime-type type="application/postscript">
<comment>PS document</comment>
<comment xml:lang="ar">مستند PS</comment>
+ <comment xml:lang="ast">Documentu PS</comment>
<comment xml:lang="be@latin">Dakument PS</comment>
<comment xml:lang="bg">Документ — PS</comment>
<comment xml:lang="ca">document PS</comment>
@@ -1677,7 +1763,7 @@
<comment xml:lang="pt">documento PS</comment>
<comment xml:lang="pt_BR">Documento PS</comment>
<comment xml:lang="ro">Document PS</comment>
- <comment xml:lang="ru">документ PS</comment>
+ <comment xml:lang="ru">Документ PS</comment>
<comment xml:lang="sk">Dokument PS</comment>
<comment xml:lang="sl">Dokument PS</comment>
<comment xml:lang="sq">Dokument PS</comment>
@@ -1701,6 +1787,7 @@
<mime-type type="application/prs.plucker">
<comment>Plucker document</comment>
<comment xml:lang="ar">مستند Plucker</comment>
+ <comment xml:lang="ast">Documentu Plucker</comment>
<comment xml:lang="be@latin">Dakument Plucker</comment>
<comment xml:lang="bg">Документ — Plucker</comment>
<comment xml:lang="ca">document Plucker</comment>
@@ -1736,7 +1823,7 @@
<comment xml:lang="pt">documento Plucker</comment>
<comment xml:lang="pt_BR">Documento do Plucker</comment>
<comment xml:lang="ro">Document Plucker</comment>
- <comment xml:lang="ru">документ Plucker</comment>
+ <comment xml:lang="ru">Документ Plucker</comment>
<comment xml:lang="sk">Dokument Plucker</comment>
<comment xml:lang="sl">Dokument Plucker</comment>
<comment xml:lang="sq">Dokument Plucker</comment>
@@ -1754,20 +1841,32 @@
</mime-type>
<mime-type type="application/raml+yaml">
<comment>RAML document</comment>
+ <comment xml:lang="ast">Documentu RAML</comment>
<comment xml:lang="ca">document RAML</comment>
+ <comment xml:lang="cs">dokument RAML</comment>
<comment xml:lang="da">RAML-dokument</comment>
<comment xml:lang="de">RAML-Dokument</comment>
+ <comment xml:lang="en_GB">RAML document</comment>
<comment xml:lang="es">documento RAML</comment>
+ <comment xml:lang="eu">RAML dokumentua</comment>
<comment xml:lang="fi">RAML-asiakirja</comment>
<comment xml:lang="fr">document RAML</comment>
+ <comment xml:lang="ga">cáipéis RAML</comment>
<comment xml:lang="he">מסמך RAML</comment>
+ <comment xml:lang="hr">RAML dokument</comment>
<comment xml:lang="hu">RAML dokumentum</comment>
+ <comment xml:lang="id">dokumen RAML</comment>
+ <comment xml:lang="it">Documento RAML</comment>
<comment xml:lang="kk">RAML құжаты</comment>
<comment xml:lang="ko">RAML 문서</comment>
+ <comment xml:lang="oc">Document RAML</comment>
<comment xml:lang="pl">Dokument RAML</comment>
<comment xml:lang="pt_BR">Documento RAML</comment>
- <comment xml:lang="ru">документ RAML</comment>
+ <comment xml:lang="ru">Документ RAML</comment>
<comment xml:lang="sk">Dokument RAML</comment>
+ <comment xml:lang="sr">РÐМЛ документ</comment>
+ <comment xml:lang="sv">RAML-dokument</comment>
+ <comment xml:lang="tr">RAML belgesi</comment>
<comment xml:lang="uk">документ RAML</comment>
<comment xml:lang="zh_CN">RAML 文档</comment>
<comment xml:lang="zh_TW">RAML 文件</comment>
@@ -1831,6 +1930,7 @@
<mime-type type="application/rtf">
<comment>RTF document</comment>
<comment xml:lang="ar">مستند RTF</comment>
+ <comment xml:lang="ast">Documentu RTF</comment>
<comment xml:lang="be@latin">Dakument RTF</comment>
<comment xml:lang="bg">Документ — RTF</comment>
<comment xml:lang="ca">document RTF</comment>
@@ -1866,7 +1966,7 @@
<comment xml:lang="pt">documento RTF</comment>
<comment xml:lang="pt_BR">Documento RTF</comment>
<comment xml:lang="ro">Document RTF</comment>
- <comment xml:lang="ru">документ RTF</comment>
+ <comment xml:lang="ru">Документ RTF</comment>
<comment xml:lang="sk">Dokument RTF</comment>
<comment xml:lang="sl">Dokument RTF</comment>
<comment xml:lang="sq">Dokument RTF</comment>
@@ -1902,7 +2002,7 @@
<comment xml:lang="eu">Sieve posta-iragazki script-a</comment>
<comment xml:lang="fi">Sieve-postinsuodatuskomentotiedosto</comment>
<comment xml:lang="fr">script de filtrage de courriel Sieve</comment>
- <comment xml:lang="ga">script scagaire phost Sieve</comment>
+ <comment xml:lang="ga">script scagaire r-phost Sieve</comment>
<comment xml:lang="gl">Script de filtro de correo Sieve</comment>
<comment xml:lang="he">תסריט סינון דו×ר של Sieve</comment>
<comment xml:lang="hr">Sieve skripta filtriranja pošte</comment>
@@ -1923,7 +2023,7 @@
<comment xml:lang="pt">Script de filtragem de correio Sieve</comment>
<comment xml:lang="pt_BR">Script de filtro de mensagens do Sieve</comment>
<comment xml:lang="ro">Script filtrare email Sieve</comment>
- <comment xml:lang="ru">Ñценарий почтового фильтра Sieve</comment>
+ <comment xml:lang="ru">Сценарий почтового фильтра Sieve</comment>
<comment xml:lang="sk">Skript poštového filtra Sieve</comment>
<comment xml:lang="sl">Skriptna datoteka Sieve poštnega filtra</comment>
<comment xml:lang="sq">Script filtrim poste Sieve</comment>
@@ -1941,6 +2041,7 @@
<mime-type type="application/smil+xml">
<comment>SMIL document</comment>
<comment xml:lang="ar">مستند SMIL</comment>
+ <comment xml:lang="ast">Documentu SMIL</comment>
<comment xml:lang="be@latin">Dakument SMIL</comment>
<comment xml:lang="bg">Документ — SMIL</comment>
<comment xml:lang="ca">document SMIL</comment>
@@ -1976,7 +2077,7 @@
<comment xml:lang="pt">documento SMIL</comment>
<comment xml:lang="pt_BR">Documento SMIL</comment>
<comment xml:lang="ro">Document SMIL</comment>
- <comment xml:lang="ru">документ SMIL</comment>
+ <comment xml:lang="ru">Документ SMIL</comment>
<comment xml:lang="sk">Dokument SMIL</comment>
<comment xml:lang="sl">Dokument SMIL</comment>
<comment xml:lang="sq">Dokument SMIL</comment>
@@ -2022,7 +2123,7 @@
<comment xml:lang="ga">seinmliosta WPL</comment>
<comment xml:lang="gl">lista de reprodución WPL</comment>
<comment xml:lang="he">רשימת נגינה WPL</comment>
- <comment xml:lang="hr">WPL popis za reprodukciju</comment>
+ <comment xml:lang="hr">WPL popis izvođenja</comment>
<comment xml:lang="hu">WPL-lejátszólista</comment>
<comment xml:lang="ia">Lista de selection WPL</comment>
<comment xml:lang="id">Senarai putar WPL</comment>
@@ -2038,7 +2139,7 @@
<comment xml:lang="pt">lista de reprodução WPL</comment>
<comment xml:lang="pt_BR">Lista de reprodução do WPL</comment>
<comment xml:lang="ro">Listă redare WPL</comment>
- <comment xml:lang="ru">ÑпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ WPL</comment>
+ <comment xml:lang="ru">СпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ WPL</comment>
<comment xml:lang="sk">Zoznam skladieb WPL</comment>
<comment xml:lang="sl">Seznam predvajanja WPL</comment>
<comment xml:lang="sr">ВПЛ ÑпиÑак нумера</comment>
@@ -2094,7 +2195,7 @@
<comment xml:lang="pt">base de dados SQLite2</comment>
<comment xml:lang="pt_BR">Banco de dados SQLite2</comment>
<comment xml:lang="ro">Bază de date SQLite2</comment>
- <comment xml:lang="ru">база данных SQLite2</comment>
+ <comment xml:lang="ru">База данных SQLite2</comment>
<comment xml:lang="sk">Databáza SQLite2</comment>
<comment xml:lang="sl">Podatkovna zbirka SQLite2</comment>
<comment xml:lang="sq">Bazë me të dhëna SQLite2</comment>
@@ -2105,11 +2206,12 @@
<comment xml:lang="vi">Cơ sở dữ liệu SQLite2</comment>
<comment xml:lang="zh_CN">SQLite2 æ•°æ®åº“</comment>
<comment xml:lang="zh_TW">SQLite2 資料庫</comment>
+ <glob pattern="*.sqlite2"/>
<magic>
<match value="** This file contains an SQLite" type="string" offset="0"/>
</magic>
</mime-type>
- <mime-type type="application/x-sqlite3">
+ <mime-type type="application/vnd.sqlite3">
<comment>SQLite3 database</comment>
<comment xml:lang="ar">قاعدة بيانات SQLite3</comment>
<comment xml:lang="be@latin">Baza źviestak SQLite3</comment>
@@ -2147,7 +2249,7 @@
<comment xml:lang="pt">base de dados SQLite3</comment>
<comment xml:lang="pt_BR">Banco de dados SQLite3</comment>
<comment xml:lang="ro">Bază de date SQLite3</comment>
- <comment xml:lang="ru">база данных SQLite3</comment>
+ <comment xml:lang="ru">База данных SQLite3</comment>
<comment xml:lang="sk">Databáza SQLite3</comment>
<comment xml:lang="sl">Podatkovna zbirka SQLite3</comment>
<comment xml:lang="sq">Bazë me të dhëna SQLite3</comment>
@@ -2158,9 +2260,11 @@
<comment xml:lang="vi">Cơ sở dữ liệu SQLite3</comment>
<comment xml:lang="zh_CN">SQLite3 æ•°æ®åº“</comment>
<comment xml:lang="zh_TW">SQLite3 資料庫</comment>
+ <glob pattern="*.sqlite3"/>
<magic>
<match value="SQLite format 3" type="string" offset="0"/>
</magic>
+ <alias type="application/x-sqlite3"/>
</mime-type>
<mime-type type="application/x-gedcom">
<comment>GEDCOM family history</comment>
@@ -2189,7 +2293,7 @@
<comment xml:lang="ja">GEDCOM 家系図データ</comment>
<comment xml:lang="ka">GEDCOM áƒáƒ¯áƒáƒ®áƒ˜áƒ¡ ისტáƒáƒ áƒ˜áƒ</comment>
<comment xml:lang="kk">GEDCOM отбаÑÑ‹ тарихы</comment>
- <comment xml:lang="ko">GEDCOM 가족 내력</comment>
+ <comment xml:lang="ko">GEDCOM 패밀리 기ë¡</comment>
<comment xml:lang="lt">GEDCOM Å¡eimos istorija</comment>
<comment xml:lang="lv">GEDCOM ģimenes vēsture</comment>
<comment xml:lang="nb">GEDCOM-familiehistorikk</comment>
@@ -2200,7 +2304,7 @@
<comment xml:lang="pt">história familiar GEDCOM</comment>
<comment xml:lang="pt_BR">Histórico familiar do GEDCOM</comment>
<comment xml:lang="ro">Tablou genealogic GEDCOM</comment>
- <comment xml:lang="ru">иÑÑ‚Ð¾Ñ€Ð¸Ñ Ñемьи GEDCOM</comment>
+ <comment xml:lang="ru">ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ñемьи GEDCOM</comment>
<comment xml:lang="sk">Rodokmeň GEDCOM</comment>
<comment xml:lang="sl">Datoteka družinske zgodovine GEDCOM</comment>
<comment xml:lang="sq">Kronollogji familje GEDCOM</comment>
@@ -2224,6 +2328,7 @@
<mime-type type="video/x-flv">
<comment>Flash video</comment>
<comment xml:lang="ar">Flash مرئي</comment>
+ <comment xml:lang="ast">Videu en Flash</comment>
<comment xml:lang="be@latin">Videa Flash</comment>
<comment xml:lang="bg">Видео — Flash</comment>
<comment xml:lang="ca">vídeo de Flash</comment>
@@ -2241,7 +2346,7 @@
<comment xml:lang="ga">físeán Flash</comment>
<comment xml:lang="gl">vídeo Flash</comment>
<comment xml:lang="he">ויד×ו של פל×ש</comment>
- <comment xml:lang="hr">Flash video</comment>
+ <comment xml:lang="hr">Flash video snimka</comment>
<comment xml:lang="hu">Flash videó</comment>
<comment xml:lang="ia">Video Flash</comment>
<comment xml:lang="id">Video Flash</comment>
@@ -2260,7 +2365,7 @@
<comment xml:lang="pt">vídeo Flash</comment>
<comment xml:lang="pt_BR">Vídeo Flash</comment>
<comment xml:lang="ro">Video Flash</comment>
- <comment xml:lang="ru">видео Flash</comment>
+ <comment xml:lang="ru">Видео Flash</comment>
<comment xml:lang="sk">Video Flash</comment>
<comment xml:lang="sl">Video datoteka Flash</comment>
<comment xml:lang="sq">Video Flash</comment>
@@ -2269,7 +2374,7 @@
<comment xml:lang="tr">Flash video</comment>
<comment xml:lang="uk">відеокліп Flash</comment>
<comment xml:lang="vi">Ảnh động Flash</comment>
- <comment xml:lang="zh_CN">Flash 影片</comment>
+ <comment xml:lang="zh_CN">Flash 视频</comment>
<comment xml:lang="zh_TW">Flash 視訊</comment>
<generic-icon name="video-x-generic"/>
<magic priority="50">
@@ -2282,6 +2387,7 @@
</mime-type>
<mime-type type="video/x-javafx">
<comment>JavaFX video</comment>
+ <comment xml:lang="ast">Videu en JavaFX</comment>
<comment xml:lang="bg">Видео — JavaFX</comment>
<comment xml:lang="ca">vídeo de JavaFX</comment>
<comment xml:lang="cs">video JavaFX</comment>
@@ -2298,7 +2404,7 @@
<comment xml:lang="ga">físeán JavaFX</comment>
<comment xml:lang="gl">vídeo JavaFX</comment>
<comment xml:lang="he">ויד×ו JavaFX</comment>
- <comment xml:lang="hr">JavaFX video</comment>
+ <comment xml:lang="hr">JavaFX video snimka</comment>
<comment xml:lang="hu">JavaFX videó</comment>
<comment xml:lang="ia">Video JavaFX</comment>
<comment xml:lang="id">Video JavaFX</comment>
@@ -2313,7 +2419,7 @@
<comment xml:lang="pt">vídeo JavaFX</comment>
<comment xml:lang="pt_BR">Vídeo JavaFX</comment>
<comment xml:lang="ro">Video JavaFX</comment>
- <comment xml:lang="ru">видео JavaFX</comment>
+ <comment xml:lang="ru">Видео JavaFX</comment>
<comment xml:lang="sk">Video JavaFX</comment>
<comment xml:lang="sl">Video JavaFX</comment>
<comment xml:lang="sr">ÐˆÐ°Ð²Ð°Ð¤Ð˜ÐºÑ Ð²Ð¸Ð´ÐµÐ¾</comment>
@@ -2367,7 +2473,7 @@
<comment xml:lang="pt">gravação SGF</comment>
<comment xml:lang="pt_BR">Gravação SGF</comment>
<comment xml:lang="ro">ÃŽnregistrare SGF</comment>
- <comment xml:lang="ru">запиÑÑŒ SGF</comment>
+ <comment xml:lang="ru">ЗапиÑÑŒ SGF</comment>
<comment xml:lang="sk">Záznam SGF</comment>
<comment xml:lang="sl">Datoteka shranjene igre SGF</comment>
<comment xml:lang="sq">Regjistrim SGF</comment>
@@ -2388,9 +2494,10 @@
<match value="(;FF[4]" type="string" offset="0"/>
</magic>
</mime-type>
- <mime-type type="application/x-xliff">
+ <mime-type type="application/xliff+xml">
<comment>XLIFF translation file</comment>
<comment xml:lang="ar">مل٠ترجمة XLIFF</comment>
+ <comment xml:lang="ast">Ficheru de traducciones XLIFF</comment>
<comment xml:lang="be@latin">Fajł pierakładu XLIFF</comment>
<comment xml:lang="bg">Превод — XLIFF</comment>
<comment xml:lang="ca">fitxer de traducció XLIFF</comment>
@@ -2404,7 +2511,7 @@
<comment xml:lang="fi">XLIFF-käännöstiedosto</comment>
<comment xml:lang="fo">XLIFF týðingarfíla</comment>
<comment xml:lang="fr">fichier de traduction XLIFF</comment>
- <comment xml:lang="ga">comhad aistrithe XLIFF</comment>
+ <comment xml:lang="ga">comhad aistriúcháin XLIFF</comment>
<comment xml:lang="gl">ficheiro de tradución XLIFF</comment>
<comment xml:lang="he">קובץ ×ª×¨×’×•× CLIFF</comment>
<comment xml:lang="hr">XLIFF datoteka prijevoda</comment>
@@ -2425,7 +2532,7 @@
<comment xml:lang="pt">ficheiro de tradução XLIFF</comment>
<comment xml:lang="pt_BR">Arquivo de tradução XLIFF</comment>
<comment xml:lang="ro">Fișier de traducere XLIFF</comment>
- <comment xml:lang="ru">файл перевода XLIFF</comment>
+ <comment xml:lang="ru">Файл перевода XLIFF</comment>
<comment xml:lang="sk">Súbor prekladu XLIFF</comment>
<comment xml:lang="sl">Datoteka prevoda XLIFF</comment>
<comment xml:lang="sq">File përkthimesh XLIFF</comment>
@@ -2434,7 +2541,7 @@
<comment xml:lang="tr">XLIFF çeviri dosyası</comment>
<comment xml:lang="uk">файл перекладу XLIFF</comment>
<comment xml:lang="vi">Tập tin dịch XLIFF</comment>
- <comment xml:lang="zh_CN">XLIFF 消æ¯ç¿»è¯‘文件</comment>
+ <comment xml:lang="zh_CN">XLIFF 翻译文件</comment>
<comment xml:lang="zh_TW">XLIFF 翻譯檔</comment>
<acronym>XLIFF</acronym>
<expanded-acronym>XML Localization Interchange File Format</expanded-acronym>
@@ -2446,10 +2553,12 @@
<match value="&lt;xliff" type="string" offset="0:256"/>
</magic>
<root-XML namespaceURI='urn:oasis:names:tc:xliff:document:1.1' localName='xliff'/>
+ <alias type="application/x-xliff"/>
</mime-type>
<mime-type type="application/x-yaml">
<comment>YAML document</comment>
<comment xml:lang="ar">مستند YAML</comment>
+ <comment xml:lang="ast">Documentu YAML</comment>
<comment xml:lang="bg">Документ — YAML</comment>
<comment xml:lang="ca">document YAML</comment>
<comment xml:lang="cs">dokument YAML</comment>
@@ -2482,7 +2591,7 @@
<comment xml:lang="pt">documento YAML</comment>
<comment xml:lang="pt_BR">Documento YAML</comment>
<comment xml:lang="ro">Document YAML</comment>
- <comment xml:lang="ru">документ YAML</comment>
+ <comment xml:lang="ru">Документ YAML</comment>
<comment xml:lang="sk">Dokument YAML</comment>
<comment xml:lang="sl">Dokument YAML</comment>
<comment xml:lang="sr">ЈÐМЛ документ</comment>
@@ -2506,6 +2615,7 @@
<mime-type type="application/vnd.corel-draw">
<comment>Corel Draw drawing</comment>
<comment xml:lang="ar">تصميم Corel Draw</comment>
+ <comment xml:lang="ast">Dibuxu de Corel Draw</comment>
<comment xml:lang="az">Corel Draw çəkimi</comment>
<comment xml:lang="be@latin">Rysunak Corel Draw</comment>
<comment xml:lang="bg">Чертеж — Corel Draw</comment>
@@ -2533,7 +2643,7 @@
<comment xml:lang="ja">Corel Draw ドロー</comment>
<comment xml:lang="ka">Corel Draw-ის ნáƒáƒ®áƒáƒ–ი</comment>
<comment xml:lang="kk">Corel Draw Ñуреті</comment>
- <comment xml:lang="ko">Corel Draw 드로잉</comment>
+ <comment xml:lang="ko">ì½”ë  ë“œë¡œìš° 드로잉</comment>
<comment xml:lang="lt">Corel Draw piešinys</comment>
<comment xml:lang="lv">Corel Draw zīmējums</comment>
<comment xml:lang="ms">Lukisan Corel Draw</comment>
@@ -2545,16 +2655,16 @@
<comment xml:lang="pt">desenho Corel Drawdesenho Corel Draw</comment>
<comment xml:lang="pt_BR">Desenho do Corel Draw</comment>
<comment xml:lang="ro">Desen Corel Draw</comment>
- <comment xml:lang="ru">изображение Corel Draw</comment>
+ <comment xml:lang="ru">РиÑунок Corel Draw</comment>
<comment xml:lang="sk">Kresba Corel Draw</comment>
<comment xml:lang="sl">Datoteka risbe Corel Draw</comment>
<comment xml:lang="sq">Vizatim Corel Draw</comment>
- <comment xml:lang="sr">Корел Дров цртеж</comment>
+ <comment xml:lang="sr">Корелов цртеж</comment>
<comment xml:lang="sv">Corel Draw-teckning</comment>
<comment xml:lang="tr">Corel Draw çizimi</comment>
<comment xml:lang="uk">малюнок Corel Draw</comment>
<comment xml:lang="vi">Bản vẽ Corel Draw</comment>
- <comment xml:lang="zh_CN">Corel Draw 图形</comment>
+ <comment xml:lang="zh_CN">Corel Draw 绘图</comment>
<comment xml:lang="zh_TW">Corel Draw 繪圖</comment>
<generic-icon name="image-x-generic"/>
<magic priority="80">
@@ -2572,6 +2682,7 @@
<mime-type type="application/vnd.hp-hpgl">
<comment>HPGL file</comment>
<comment xml:lang="ar">مل٠HPGL</comment>
+ <comment xml:lang="ast">Ficheru HPGL</comment>
<comment xml:lang="be@latin">Fajł HPGL</comment>
<comment xml:lang="bg">Файл — HPGL</comment>
<comment xml:lang="ca">fitxer HPGL</comment>
@@ -2607,7 +2718,7 @@
<comment xml:lang="pt">ficheiro HPGL</comment>
<comment xml:lang="pt_BR">Arquivo HPGL</comment>
<comment xml:lang="ro">Fișier HPGL</comment>
- <comment xml:lang="ru">файл HPGL</comment>
+ <comment xml:lang="ru">Файл HPGL</comment>
<comment xml:lang="sk">Súbor HPGL</comment>
<comment xml:lang="sl">Datoteka HPGL</comment>
<comment xml:lang="sq">File HPGL</comment>
@@ -2626,6 +2737,7 @@
<mime-type type="application/vnd.hp-pcl">
<comment>PCL file</comment>
<comment xml:lang="ar">مل٠PCL</comment>
+ <comment xml:lang="ast">FIcheru PCL</comment>
<comment xml:lang="be@latin">Fajł PCL</comment>
<comment xml:lang="bg">Файл — PCL</comment>
<comment xml:lang="ca">fitxer PCL</comment>
@@ -2661,7 +2773,7 @@
<comment xml:lang="pt">ficheiro PCL</comment>
<comment xml:lang="pt_BR">Arquivo PCL</comment>
<comment xml:lang="ro">Fișier PCL</comment>
- <comment xml:lang="ru">файл PCL</comment>
+ <comment xml:lang="ru">Файл PCL</comment>
<comment xml:lang="sk">Súbor PCL</comment>
<comment xml:lang="sl">Datoteka PCL</comment>
<comment xml:lang="sq">File PCL</comment>
@@ -2680,6 +2792,7 @@
<mime-type type="application/vnd.lotus-1-2-3">
<comment>Lotus 1-2-3 spreadsheet</comment>
<comment xml:lang="ar">جدول Lotus 1-2-3</comment>
+ <comment xml:lang="ast">Fueya de cálculu de Lotus 1-2-3</comment>
<comment xml:lang="az">Lotus 1-2-3 hesab cədvəli</comment>
<comment xml:lang="be@latin">Raźlikovy arkuš Lotus 1-2-3</comment>
<comment xml:lang="bg">Таблица — Lotus 1-2-3</comment>
@@ -2718,7 +2831,7 @@
<comment xml:lang="pt">folha de cálculo Lotus 1-2-3</comment>
<comment xml:lang="pt_BR">Planilha do Lotus 1-2-3</comment>
<comment xml:lang="ro">Foaie de calcul Lotus 1-2-3</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Lotus 1-2-3</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Lotus 1-2-3</comment>
<comment xml:lang="sk">Zošit Lotus 1-2-3</comment>
<comment xml:lang="sl">Preglednica Lotus 1-2-3</comment>
<comment xml:lang="sq">Fletë llogaritjesh Lotus 1-2-3</comment>
@@ -2727,7 +2840,7 @@
<comment xml:lang="tr">Lotus 1-2-3 hesap tablosu</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Lotus 1-2-3</comment>
<comment xml:lang="vi">Bảng tính Lotus 1-2-3</comment>
- <comment xml:lang="zh_CN">Lotus 1-2-3 工作簿</comment>
+ <comment xml:lang="zh_CN">Lotus 1-2-3 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">Lotus 1-2-3 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="50">
@@ -2746,6 +2859,7 @@
</mime-type>
<mime-type type="application/vnd.lotus-wordpro">
<comment>Lotus Word Pro</comment>
+ <comment xml:lang="ast">Lotus Word Pro</comment>
<comment xml:lang="ca">Lotus Word Pro</comment>
<comment xml:lang="cs">Lotus Word Pro</comment>
<comment xml:lang="da">Lotus Word Pro</comment>
@@ -2756,6 +2870,7 @@
<comment xml:lang="eu">Lotus Word Pro</comment>
<comment xml:lang="fi">Lotus Word Pro</comment>
<comment xml:lang="fr">Lotus Word Pro</comment>
+ <comment xml:lang="ga">Lotus Word Pro</comment>
<comment xml:lang="gl">Lotus Word Pro</comment>
<comment xml:lang="he">Lotus Word Pro</comment>
<comment xml:lang="hr">Lotus Word Pro</comment>
@@ -2789,6 +2904,7 @@
<mime-type type="application/vnd.ms-access">
<comment>JET database</comment>
<comment xml:lang="ar">قاعدة بيانات JET</comment>
+ <comment xml:lang="ast">Base de datos JETº</comment>
<comment xml:lang="be@latin">Baza źviestak JET</comment>
<comment xml:lang="bg">База от данни — JET</comment>
<comment xml:lang="ca">base de dades JET</comment>
@@ -2824,7 +2940,7 @@
<comment xml:lang="pt">base de dados JET</comment>
<comment xml:lang="pt_BR">Banco de dados JET</comment>
<comment xml:lang="ro">Bază de date JET</comment>
- <comment xml:lang="ru">база данных JET</comment>
+ <comment xml:lang="ru">База данных JET</comment>
<comment xml:lang="sk">Databáza JET</comment>
<comment xml:lang="sl">Podatkovna zbirka JET</comment>
<comment xml:lang="sq">Bazë me të dhëna JET</comment>
@@ -2885,7 +3001,7 @@
<comment xml:lang="pt">arquivo Microsoft Cabinet</comment>
<comment xml:lang="pt_BR">Pacote Cabinet da Microsoft</comment>
<comment xml:lang="ro">Arhivă Microsoft Cabinet</comment>
- <comment xml:lang="ru">архив Microsoft Cabinet</comment>
+ <comment xml:lang="ru">Ðрхив Microsoft Cabinet</comment>
<comment xml:lang="sk">Archív Microsoft Cabinet</comment>
<comment xml:lang="sl">Datoteka arhiva Microsoft Cabinet</comment>
<comment xml:lang="sr">МајкроÑофтова кабинет архива</comment>
@@ -2893,7 +3009,7 @@
<comment xml:lang="tr">Microsoft Cabinet arÅŸivi</comment>
<comment xml:lang="uk">архів Cabinet Microsoft</comment>
<comment xml:lang="vi">Kho lÆ°u Cabinet Microsoft</comment>
- <comment xml:lang="zh_CN">Microsoft CAB 归档文件</comment>
+ <comment xml:lang="zh_CN">Microsoft Cabinet 归档文件</comment>
<comment xml:lang="zh_TW">微軟 Cabinet å°å­˜æª”</comment>
<generic-icon name="package-x-generic"/>
<magic priority="60">
@@ -2941,7 +3057,7 @@
<comment xml:lang="pt">folha de cálculo Excel</comment>
<comment xml:lang="pt_BR">Planilha do Excel</comment>
<comment xml:lang="ro">Foaie de calcul Excel</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Excel</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Excel</comment>
<comment xml:lang="sk">Zošit Excel</comment>
<comment xml:lang="sl">Razpredelnica Microsoft Excel</comment>
<comment xml:lang="sq">Fletë llogaritje Excel</comment>
@@ -2950,7 +3066,7 @@
<comment xml:lang="tr">Excel çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Excel</comment>
<comment xml:lang="vi">Bảng tính Excel</comment>
- <comment xml:lang="zh_CN">Microsoft Excel 工作簿</comment>
+ <comment xml:lang="zh_CN">Excel 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">Excel 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="50">
@@ -2981,9 +3097,10 @@
<comment xml:lang="eu">Excel gehigarria</comment>
<comment xml:lang="fi">Excel-lisäosa</comment>
<comment xml:lang="fr">complément Excel</comment>
+ <comment xml:lang="ga">breiseán Excel</comment>
<comment xml:lang="gl">complemento de Excel</comment>
<comment xml:lang="he">תוסף של Excel</comment>
- <comment xml:lang="hr">Excel prikljuÄak</comment>
+ <comment xml:lang="hr">Excel dodatak</comment>
<comment xml:lang="hu">Excel bővítmény</comment>
<comment xml:lang="ia">Add-in Excel</comment>
<comment xml:lang="id">Add-in Excel</comment>
@@ -2998,14 +3115,14 @@
<comment xml:lang="pl">Dodatek Excel</comment>
<comment xml:lang="pt">Extensão Excel</comment>
<comment xml:lang="pt_BR">Suplemento do Excel</comment>
- <comment xml:lang="ru">дополнение Excel</comment>
+ <comment xml:lang="ru">Дополнение Excel</comment>
<comment xml:lang="sk">Doplnok aplikácie Excel</comment>
<comment xml:lang="sl">Vstavek Excel</comment>
<comment xml:lang="sr">ЕкÑелов додатак</comment>
<comment xml:lang="sv">Excel-tillägg</comment>
<comment xml:lang="tr">Excel eklentisi</comment>
<comment xml:lang="uk">додаток Excel</comment>
- <comment xml:lang="zh_CN">Excel 附加组件</comment>
+ <comment xml:lang="zh_CN">Excel 外接程åº</comment>
<comment xml:lang="zh_TW">Excel 增益集</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.xlam"/>
@@ -3024,6 +3141,7 @@
<comment xml:lang="eu">Excel 2007 kalkulu-orri binarioa</comment>
<comment xml:lang="fi">Excel 2007:n binaarinen taulukko</comment>
<comment xml:lang="fr">feuille de calcul binaire Excel 2007</comment>
+ <comment xml:lang="ga">scarbhileog dhénártha Excel 2007</comment>
<comment xml:lang="gl">ficheiro binario de folla de cálculo Excel 2007</comment>
<comment xml:lang="he">גיליון × ×ª×•× ×™× ×‘×™× ×¨×™ של Excel 2007</comment>
<comment xml:lang="hr">Excel 2007 binarna proraÄunska tablica</comment>
@@ -3041,14 +3159,14 @@
<comment xml:lang="pl">Binarny arkusz Excel 2007</comment>
<comment xml:lang="pt">folha de cálculo binária Excel 2007</comment>
<comment xml:lang="pt_BR">Planilha binária do Excel 2007</comment>
- <comment xml:lang="ru">Ð´Ð²Ð¾Ð¸Ñ‡Ð½Ð°Ñ ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Excel 2007</comment>
+ <comment xml:lang="ru">Ð”Ð²Ð¾Ð¸Ñ‡Ð½Ð°Ñ ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Excel 2007</comment>
<comment xml:lang="sk">Binárny zošit Excel 2007</comment>
<comment xml:lang="sl">Binarna preglednica Excel 2007</comment>
<comment xml:lang="sr">ЕкÑел 2007 бинарна табела</comment>
<comment xml:lang="sv">Binärt Excel 2007-kalkylblad</comment>
<comment xml:lang="tr">Excel 2007 ikilik çalışma sayfası</comment>
<comment xml:lang="uk">бінарна електронна Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Excel 2007</comment>
- <comment xml:lang="zh_CN">Excel 2007 二进制工作表</comment>
+ <comment xml:lang="zh_CN">Excel 2007 二进制电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">Excel 2007 二進ä½è©¦ç®—表</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.xlsb"/>
@@ -3093,7 +3211,7 @@
<comment xml:lang="pt">folha de cálculo Excel</comment>
<comment xml:lang="pt_BR">Planilha do Excel</comment>
<comment xml:lang="ro">Foaie de calcul Excel</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Excel</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Excel</comment>
<comment xml:lang="sk">Zošit Excel</comment>
<comment xml:lang="sl">Razpredelnica Microsoft Excel</comment>
<comment xml:lang="sq">Fletë llogaritje Excel</comment>
@@ -3102,7 +3220,7 @@
<comment xml:lang="tr">Excel çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Excel</comment>
<comment xml:lang="vi">Bảng tính Excel</comment>
- <comment xml:lang="zh_CN">Microsoft Excel 工作簿</comment>
+ <comment xml:lang="zh_CN">Excel 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">Excel 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.xlsm"/>
@@ -3120,6 +3238,7 @@
<comment xml:lang="eu">Excel kalkulu-orri txantiloia</comment>
<comment xml:lang="fi">Excel-taulukkomalli</comment>
<comment xml:lang="fr">modèle de feuille de calcul Excel</comment>
+ <comment xml:lang="ga">teimpléad scarbhileoige Excel</comment>
<comment xml:lang="he">תבנית גיליון × ×ª×•× ×™× ×©×œ Excel</comment>
<comment xml:lang="hr">Predložak Excel proraÄunske tablice</comment>
<comment xml:lang="hu">Excel munkafüzetsablon</comment>
@@ -3127,18 +3246,18 @@
<comment xml:lang="id">Templat lembar kerja Excel</comment>
<comment xml:lang="it">Modello foglio di calcolo Excel</comment>
<comment xml:lang="kk">Excel кеÑтеÑінің үлгіÑÑ–</comment>
- <comment xml:lang="ko">ì•¡ì…€ 스프레드시트 ì–‘ì‹</comment>
+ <comment xml:lang="ko">Excel 스프레드시트 ì„œì‹</comment>
<comment xml:lang="oc">Modèl de fuèlh de calcul Excel</comment>
<comment xml:lang="pl">Szablon arkusza Excel</comment>
<comment xml:lang="pt">modelo de folha de cálculo Excel</comment>
<comment xml:lang="pt_BR">Modelo de planilha do Excel</comment>
- <comment xml:lang="ru">шаблон таблицы Excel</comment>
+ <comment xml:lang="ru">Шаблон таблицы Excel</comment>
<comment xml:lang="sk">Šablóna tabuľky aplikácie Excel</comment>
- <comment xml:lang="sr">Шаблон табеле ЕкÑела</comment>
+ <comment xml:lang="sr">ЕкÑелов шаблон табеле</comment>
<comment xml:lang="sv">Excel-kalkylarksmall</comment>
<comment xml:lang="tr">Excel hesap tablosu ÅŸablonu</comment>
<comment xml:lang="uk">шаблон електронної таблиці Excel</comment>
- <comment xml:lang="zh_CN">Microsoft Excel 工作簿模æ¿</comment>
+ <comment xml:lang="zh_CN">Excel 电å­è¡¨æ ¼æ¨¡æ¿</comment>
<comment xml:lang="zh_TW">Excel 試算表範本</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.xltm"/>
@@ -3182,16 +3301,16 @@
<comment xml:lang="pt">apresentação PowerPoint</comment>
<comment xml:lang="pt_BR">Apresentação do PowerPoint</comment>
<comment xml:lang="ro">Prezentare PowerPoint</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ PowerPoint</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ PowerPoint</comment>
<comment xml:lang="sk">Prezentácia PowerPoint</comment>
<comment xml:lang="sl">Predstavitev Microsoft PowerPoint</comment>
<comment xml:lang="sq">Prezantim PowerPoint</comment>
- <comment xml:lang="sr">Пауер Поинт презентација</comment>
+ <comment xml:lang="sr">Пауер поинт презентација</comment>
<comment xml:lang="sv">PowerPoint-presentation</comment>
<comment xml:lang="tr">PowerPoint sunumu</comment>
<comment xml:lang="uk">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ PowerPoint</comment>
<comment xml:lang="vi">Trình diễn PowerPoint</comment>
- <comment xml:lang="zh_CN">Microsoft PowerPoint 演示文稿</comment>
+ <comment xml:lang="zh_CN">PowerPoint 演示文稿</comment>
<comment xml:lang="zh_TW">PowerPoint ç°¡å ±</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.ppz"/>
@@ -3215,9 +3334,10 @@
<comment xml:lang="eu">PowerPoint gehigarria</comment>
<comment xml:lang="fi">PowerPoint-lisäosa</comment>
<comment xml:lang="fr">complément PowerPoint</comment>
+ <comment xml:lang="ga">breiseán PowerPoint</comment>
<comment xml:lang="gl">complemento de PowerPoint</comment>
<comment xml:lang="he">תוסף של PowerPoint</comment>
- <comment xml:lang="hr">PowerPoint prikljuÄak</comment>
+ <comment xml:lang="hr">PowerPoint dodatak</comment>
<comment xml:lang="hu">PowerPoint bővítmény</comment>
<comment xml:lang="ia">Add-in PowerPoint</comment>
<comment xml:lang="id">Add-in PowerPoint</comment>
@@ -3232,14 +3352,14 @@
<comment xml:lang="pl">Dodatek PowerPoint</comment>
<comment xml:lang="pt">extensão PowerPoint</comment>
<comment xml:lang="pt_BR">Suplemento do PowerPoint</comment>
- <comment xml:lang="ru">дополнение PowerPoint</comment>
+ <comment xml:lang="ru">Дополнение PowerPoint</comment>
<comment xml:lang="sk">Doplnok aplikácie PowerPoint </comment>
<comment xml:lang="sl">Vstavek PowerPoint</comment>
- <comment xml:lang="sr">Пауер Поинт додатак</comment>
+ <comment xml:lang="sr">Пауер поинт додатак</comment>
<comment xml:lang="sv">PowerPoint-tillägg</comment>
<comment xml:lang="tr">PowerPoint eklentisi</comment>
<comment xml:lang="uk">додаток PowerPoint</comment>
- <comment xml:lang="zh_CN">PowerPoint 附加组件</comment>
+ <comment xml:lang="zh_CN">PowerPoint 外接程åº</comment>
<comment xml:lang="zh_TW">PowerPoint 增益集</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.ppam"/>
@@ -3282,16 +3402,16 @@
<comment xml:lang="pt">apresentação PowerPoint</comment>
<comment xml:lang="pt_BR">Apresentação do PowerPoint</comment>
<comment xml:lang="ro">Prezentare PowerPoint</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ PowerPoint</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ PowerPoint</comment>
<comment xml:lang="sk">Prezentácia PowerPoint</comment>
<comment xml:lang="sl">Predstavitev Microsoft PowerPoint</comment>
<comment xml:lang="sq">Prezantim PowerPoint</comment>
- <comment xml:lang="sr">Пауер Поинт презентација</comment>
+ <comment xml:lang="sr">Пауер поинт презентација</comment>
<comment xml:lang="sv">PowerPoint-presentation</comment>
<comment xml:lang="tr">PowerPoint sunumu</comment>
<comment xml:lang="uk">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ PowerPoint</comment>
<comment xml:lang="vi">Trình diễn PowerPoint</comment>
- <comment xml:lang="zh_CN">Microsoft PowerPoint 演示文稿</comment>
+ <comment xml:lang="zh_CN">PowerPoint 演示文稿</comment>
<comment xml:lang="zh_TW">PowerPoint ç°¡å ±</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.pptm"/>
@@ -3299,6 +3419,7 @@
</mime-type>
<mime-type type="application/vnd.ms-powerpoint.slide.macroEnabled.12">
<comment>PowerPoint slide</comment>
+ <comment xml:lang="ast">Diapositiva de PowerPoint</comment>
<comment xml:lang="ca">dispositiva de PowerPoint</comment>
<comment xml:lang="cs">promítání PowerPoint</comment>
<comment xml:lang="da">PowerPoint-dias</comment>
@@ -3309,6 +3430,7 @@
<comment xml:lang="eu">PowerPoint diapositiba</comment>
<comment xml:lang="fi">PowerPoint-dia</comment>
<comment xml:lang="fr">diapositive PowerPoint</comment>
+ <comment xml:lang="ga">sleamhnán PowerPoint</comment>
<comment xml:lang="he">שקופית של PowerPoint</comment>
<comment xml:lang="hr">PowerPoint prezentacija</comment>
<comment xml:lang="hu">PowerPoint dia</comment>
@@ -3321,13 +3443,13 @@
<comment xml:lang="pl">Slajd PowerPoint</comment>
<comment xml:lang="pt">diapositivo PowerPoint</comment>
<comment xml:lang="pt_BR">Slide do PowerPoint</comment>
- <comment xml:lang="ru">Ñлайд PowerPoint</comment>
+ <comment xml:lang="ru">Слайд PowerPoint</comment>
<comment xml:lang="sk">Snímka aplikácie PowerPoint</comment>
- <comment xml:lang="sr">Слајд Пауер Поинта</comment>
+ <comment xml:lang="sr">Пауер поинт Ñлајд</comment>
<comment xml:lang="sv">PowerPoint-bildspel</comment>
<comment xml:lang="tr">PowerPoint sunusu</comment>
<comment xml:lang="uk">Ñлайд PowerPoint</comment>
- <comment xml:lang="zh_CN">PowerPoint 文稿</comment>
+ <comment xml:lang="zh_CN">PowerPoint å¹»ç¯ç‰‡</comment>
<comment xml:lang="zh_TW">PowerPoint 投影片</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.sldm"/>
@@ -3371,16 +3493,16 @@
<comment xml:lang="pt">apresentação PowerPoint</comment>
<comment xml:lang="pt_BR">Apresentação do PowerPoint</comment>
<comment xml:lang="ro">Prezentare PowerPoint</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ PowerPoint</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ PowerPoint</comment>
<comment xml:lang="sk">Prezentácia PowerPoint</comment>
<comment xml:lang="sl">Predstavitev Microsoft PowerPoint</comment>
<comment xml:lang="sq">Prezantim PowerPoint</comment>
- <comment xml:lang="sr">Пауер Поинт презентација</comment>
+ <comment xml:lang="sr">Пауер поинт презентација</comment>
<comment xml:lang="sv">PowerPoint-presentation</comment>
<comment xml:lang="tr">PowerPoint sunumu</comment>
<comment xml:lang="uk">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ PowerPoint</comment>
<comment xml:lang="vi">Trình diễn PowerPoint</comment>
- <comment xml:lang="zh_CN">Microsoft PowerPoint 演示文稿</comment>
+ <comment xml:lang="zh_CN">PowerPoint 演示文稿</comment>
<comment xml:lang="zh_TW">PowerPoint ç°¡å ±</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.ppsm"/>
@@ -3388,6 +3510,7 @@
</mime-type>
<mime-type type="application/vnd.ms-powerpoint.template.macroEnabled.12">
<comment>PowerPoint presentation template</comment>
+ <comment xml:lang="ast">Plantía de presentaciones de PowerPoint</comment>
<comment xml:lang="ca">plantilla de presentació de PowerPoint</comment>
<comment xml:lang="cs">Å¡ablona prezentace PowerPoint</comment>
<comment xml:lang="da">PowerPoint-præsentationsskabelon</comment>
@@ -3398,6 +3521,7 @@
<comment xml:lang="eu">PowerPoint aurkezpen txantiloia</comment>
<comment xml:lang="fi">PowerPoint-esitysmalli</comment>
<comment xml:lang="fr">modèle de présentation PowerPoint</comment>
+ <comment xml:lang="ga">teimpléad láithreoireachta PowerPoint</comment>
<comment xml:lang="he">תבנית מצגת PowerPoint</comment>
<comment xml:lang="hr">Predložak PowerPoint prezentacije</comment>
<comment xml:lang="hu">PowerPoint bemutatósablon</comment>
@@ -3405,18 +3529,18 @@
<comment xml:lang="id">Templat presentasi PowerPoint</comment>
<comment xml:lang="it">Modello presentazione PowerPoint</comment>
<comment xml:lang="kk">PowerPoint Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ò¯Ð»Ð³Ñ–ÑÑ–</comment>
- <comment xml:lang="ko">파워í¬ì¸ë“œ 프리젠테ì´ì…˜ ì–‘ì‹</comment>
+ <comment xml:lang="ko">PowerPoint 프리젠테ì´ì…˜ ì„œì‹</comment>
<comment xml:lang="oc">Modèl de presentacion PowerPoint</comment>
<comment xml:lang="pl">Szablon prezentacji PowerPoint</comment>
<comment xml:lang="pt">modelo de apresentação PowerPoint</comment>
<comment xml:lang="pt_BR">Modelo de apresentação do PowerPoint</comment>
- <comment xml:lang="ru">шаблон презентации PowerPoint</comment>
+ <comment xml:lang="ru">Шаблон презентации PowerPoint</comment>
<comment xml:lang="sk">Šablóna prezentácie aplikácie PowerPoint</comment>
- <comment xml:lang="sr">Шаблон презентације Пауер Поинта</comment>
+ <comment xml:lang="sr">Шаблон презентације Пауер поинта</comment>
<comment xml:lang="sv">PowerPoint-presentationsmall</comment>
<comment xml:lang="tr">PowerPoint sunum ÅŸablonu</comment>
<comment xml:lang="uk">шаблон презентації PowerPoint</comment>
- <comment xml:lang="zh_CN">Microsoft PowerPoint 演示文稿模æ¿</comment>
+ <comment xml:lang="zh_CN">PowerPoint 演示文稿模æ¿</comment>
<comment xml:lang="zh_TW">PowerPoint 簡報範本</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.potm"/>
@@ -3434,6 +3558,7 @@
<comment xml:lang="eu">Office Open XML Visio marrazkia</comment>
<comment xml:lang="fi">Office Open XML Visio -piirros</comment>
<comment xml:lang="fr">dessin Visio Office Open XML</comment>
+ <comment xml:lang="ga">Líníocht Office Open XML Visio</comment>
<comment xml:lang="he">ציור Visio ב־Open XML מבית Office</comment>
<comment xml:lang="hr">Office Open XML Visio crtež</comment>
<comment xml:lang="hu">Office Open XML Visio rajz</comment>
@@ -3445,13 +3570,13 @@
<comment xml:lang="pl">Rysunek Office Open XML Visio</comment>
<comment xml:lang="pt">desenho Office Open XML Visio</comment>
<comment xml:lang="pt_BR">Desenho do Visio em Office Open XML</comment>
- <comment xml:lang="ru">Ñхема Visio формата Office Open XML</comment>
+ <comment xml:lang="ru">РиÑунок Visio формата Office Open XML</comment>
<comment xml:lang="sk">Kresba aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">ÐžÑ„Ð¸Ñ Ð¾Ð¿ÐµÐ½ ИкÑМЛ Визио цртање</comment>
+ <comment xml:lang="sr">ОфиÑов отворени ИкÑМЛ Визио цртеж</comment>
<comment xml:lang="sv">Office Open XML Visio-teckning</comment>
<comment xml:lang="tr">Office Open XML Visio Çizimi</comment>
<comment xml:lang="uk">Ñхема VIisio у форматі Office Open XML</comment>
- <comment xml:lang="zh_CN">OOXML Visio 绘图</comment>
+ <comment xml:lang="zh_CN">Office Open XML Visio 绘图</comment>
<comment xml:lang="zh_TW">Office Open XML Visio 繪圖</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vsdx"/>
@@ -3469,6 +3594,7 @@
<comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
<comment xml:lang="fi">Office Open XML Visio -malli</comment>
<comment xml:lang="fr">modèle Visio Office Open XML</comment>
+ <comment xml:lang="ga">Teimpléad Office Open XML Visio</comment>
<comment xml:lang="he">תבנית Visio ב־Open XML מבית Office</comment>
<comment xml:lang="hr">Predložak Office Open XML Visio</comment>
<comment xml:lang="hu">Office Open XML Visio sablon</comment>
@@ -3476,17 +3602,17 @@
<comment xml:lang="id">Templat Visio Office Open XML</comment>
<comment xml:lang="it">Modello Visio Office Open XML</comment>
<comment xml:lang="kk">Office Open XML Visio үлгіÑÑ–</comment>
- <comment xml:lang="ko">오피스 오픈 XML 비지오 ì–‘ì‹</comment>
+ <comment xml:lang="ko">오피스 오픈 XML 비지오 ì„œì‹</comment>
<comment xml:lang="pl">Szablon Office Open XML Visio</comment>
<comment xml:lang="pt">modelo Office Open XML Visio</comment>
<comment xml:lang="pt_BR">Modelo do Visio em Office Open XML</comment>
- <comment xml:lang="ru">шаблон Visio формата Office Open XML</comment>
+ <comment xml:lang="ru">Шаблон Visio формата Office Open XML</comment>
<comment xml:lang="sk">Šablóna aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">ÐžÑ„Ð¸Ñ Ð¾Ð¿ÐµÐ½ ИкÑМЛ Визио шаблон</comment>
+ <comment xml:lang="sr">ОфиÑов отворени ИкÑМЛ Визио шаблон</comment>
<comment xml:lang="sv">Office Open XML Visio-mall</comment>
<comment xml:lang="tr">Office Open XML Visio Åžablonu</comment>
<comment xml:lang="uk">шаблон Visio у форматі Office Open XML</comment>
- <comment xml:lang="zh_CN">OOXML Visio 模æ¿</comment>
+ <comment xml:lang="zh_CN">Office Open XML Visio 模æ¿</comment>
<comment xml:lang="zh_TW">Office Open XML Visio 範本</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vstx"/>
@@ -3500,8 +3626,10 @@
<comment xml:lang="de">Office-Open-XML-Visio-Schablone</comment>
<comment xml:lang="en_GB">Office Open XML Visio Stencil</comment>
<comment xml:lang="es">esténcil en OOXML de Visio</comment>
+ <comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
<comment xml:lang="fi">Office Open XML Visio -kaavio</comment>
<comment xml:lang="fr">stencil Visio Office Open XML</comment>
+ <comment xml:lang="ga">Stionsal Office Open XML Visio</comment>
<comment xml:lang="he">×“×’× ×œÖ¾Visio ב־Open XML מבית Office</comment>
<comment xml:lang="hr">Office Open XML Visio Å¡ablona</comment>
<comment xml:lang="hu">Office Open XML Visio stencil</comment>
@@ -3513,13 +3641,13 @@
<comment xml:lang="pl">Wzór Office Open XML Visio</comment>
<comment xml:lang="pt">Stencil Office Open XML Visio</comment>
<comment xml:lang="pt_BR">Estêncil do Visio em Office Open XML</comment>
- <comment xml:lang="ru">трафарет Visio формата Office Open XML</comment>
+ <comment xml:lang="ru">Трафарет Visio формата Office Open XML</comment>
<comment xml:lang="sk">Objekt aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">ÐžÑ„Ð¸Ñ Ð¾Ð¿ÐµÐ½ ИкÑМЛ Визио шаблон</comment>
+ <comment xml:lang="sr">ОфиÑов отворени ИкÑМЛ Визио шаблон</comment>
<comment xml:lang="sv">Office Open XML Visio-stencil</comment>
<comment xml:lang="tr">Office Open XML Visio Kalıbı</comment>
<comment xml:lang="uk">трафарет Visio у форматі Office Open XML</comment>
- <comment xml:lang="zh_CN">OOXML Visio 模具</comment>
+ <comment xml:lang="zh_CN">Office Open XML Visio 模具</comment>
<comment xml:lang="zh_TW">Office Open XML Visio 圖形樣本</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vssx"/>
@@ -3537,6 +3665,7 @@
<comment xml:lang="eu">Office Open XML Visio marrazkia</comment>
<comment xml:lang="fi">Office Open XML Visio -piirros</comment>
<comment xml:lang="fr">dessin Visio Office Open XML</comment>
+ <comment xml:lang="ga">Líníocht Office Open XML Visio</comment>
<comment xml:lang="he">ציור Visio ב־Open XML מבית Office</comment>
<comment xml:lang="hr">Office Open XML Visio crtež</comment>
<comment xml:lang="hu">Office Open XML Visio rajz</comment>
@@ -3548,13 +3677,13 @@
<comment xml:lang="pl">Rysunek Office Open XML Visio</comment>
<comment xml:lang="pt">desenho Office Open XML Visio</comment>
<comment xml:lang="pt_BR">Desenho do Visio em Office Open XML</comment>
- <comment xml:lang="ru">Ñхема Visio формата Office Open XML</comment>
+ <comment xml:lang="ru">РиÑунок Visio формата Office Open XML</comment>
<comment xml:lang="sk">Kresba aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">ÐžÑ„Ð¸Ñ Ð¾Ð¿ÐµÐ½ ИкÑМЛ Визио цртање</comment>
+ <comment xml:lang="sr">ОфиÑов отворени ИкÑМЛ Визио цртеж</comment>
<comment xml:lang="sv">Office Open XML Visio-teckning</comment>
<comment xml:lang="tr">Office Open XML Visio Çizimi</comment>
<comment xml:lang="uk">Ñхема VIisio у форматі Office Open XML</comment>
- <comment xml:lang="zh_CN">OOXML Visio 绘图</comment>
+ <comment xml:lang="zh_CN">Office Open XML Visio 绘图</comment>
<comment xml:lang="zh_TW">Office Open XML Visio 繪圖</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vsdm"/>
@@ -3572,6 +3701,7 @@
<comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
<comment xml:lang="fi">Office Open XML Visio -malli</comment>
<comment xml:lang="fr">modèle Visio Office Open XML</comment>
+ <comment xml:lang="ga">Teimpléad Office Open XML Visio</comment>
<comment xml:lang="he">תבנית Visio ב־Open XML מבית Office</comment>
<comment xml:lang="hr">Predložak Office Open XML Visio</comment>
<comment xml:lang="hu">Office Open XML Visio sablon</comment>
@@ -3579,17 +3709,17 @@
<comment xml:lang="id">Templat Visio Office Open XML</comment>
<comment xml:lang="it">Modello Visio Office Open XML</comment>
<comment xml:lang="kk">Office Open XML Visio үлгіÑÑ–</comment>
- <comment xml:lang="ko">오피스 오픈 XML 비지오 ì–‘ì‹</comment>
+ <comment xml:lang="ko">오피스 오픈 XML 비지오 ì„œì‹</comment>
<comment xml:lang="pl">Szablon Office Open XML Visio</comment>
<comment xml:lang="pt">modelo Office Open XML Visio</comment>
<comment xml:lang="pt_BR">Modelo do Visio em Office Open XML</comment>
- <comment xml:lang="ru">шаблон Visio формата Office Open XML</comment>
+ <comment xml:lang="ru">Шаблон Visio формата Office Open XML</comment>
<comment xml:lang="sk">Šablóna aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">ÐžÑ„Ð¸Ñ Ð¾Ð¿ÐµÐ½ ИкÑМЛ Визио шаблон</comment>
+ <comment xml:lang="sr">ОфиÑов отворени ИкÑМЛ Визио шаблон</comment>
<comment xml:lang="sv">Office Open XML Visio-mall</comment>
<comment xml:lang="tr">Office Open XML Visio Åžablonu</comment>
<comment xml:lang="uk">шаблон Visio у форматі Office Open XML</comment>
- <comment xml:lang="zh_CN">OOXML Visio 模æ¿</comment>
+ <comment xml:lang="zh_CN">Office Open XML Visio 模æ¿</comment>
<comment xml:lang="zh_TW">Office Open XML Visio 範本</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vstm"/>
@@ -3603,8 +3733,10 @@
<comment xml:lang="de">Office-Open-XML-Visio-Schablone</comment>
<comment xml:lang="en_GB">Office Open XML Visio Stencil</comment>
<comment xml:lang="es">esténcil en OOXML de Visio</comment>
+ <comment xml:lang="eu">Office Open XML Visio txantiloia</comment>
<comment xml:lang="fi">Office Open XML Visio -kaavio</comment>
<comment xml:lang="fr">stencil Visio Office Open XML</comment>
+ <comment xml:lang="ga">Stionsal Office Open XML Visio</comment>
<comment xml:lang="he">×“×’× ×œÖ¾Visio ב־Open XML מבית Office</comment>
<comment xml:lang="hr">Office Open XML Visio Å¡ablona</comment>
<comment xml:lang="hu">Office Open XML Visio stencil</comment>
@@ -3616,13 +3748,13 @@
<comment xml:lang="pl">Wzór Office Open XML Visio</comment>
<comment xml:lang="pt">Stencil Office Open XML Visio</comment>
<comment xml:lang="pt_BR">Estêncil do Visio em Office Open XML</comment>
- <comment xml:lang="ru">трафарет Visio формата Office Open XML</comment>
+ <comment xml:lang="ru">Трафарет Visio формата Office Open XML</comment>
<comment xml:lang="sk">Objekt aplikácie Visio Office Open XML</comment>
- <comment xml:lang="sr">ÐžÑ„Ð¸Ñ Ð¾Ð¿ÐµÐ½ ИкÑМЛ Визио шаблон</comment>
+ <comment xml:lang="sr">ОфиÑов отворени ИкÑМЛ Визио шаблон</comment>
<comment xml:lang="sv">Office Open XML Visio-stencil</comment>
<comment xml:lang="tr">Office Open XML Visio Kalıbı</comment>
<comment xml:lang="uk">трафарет Visio у форматі Office Open XML</comment>
- <comment xml:lang="zh_CN">OOXML Visio 模具</comment>
+ <comment xml:lang="zh_CN">Office Open XML Visio 模具</comment>
<comment xml:lang="zh_TW">Office Open XML Visio 圖形樣本</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.vssm"/>
@@ -3631,6 +3763,7 @@
<mime-type type="application/vnd.ms-word.document.macroEnabled.12">
<comment>Word document</comment>
<comment xml:lang="ar">مستند Word</comment>
+ <comment xml:lang="ast">Documentu de Word</comment>
<comment xml:lang="be@latin">Dakument Word</comment>
<comment xml:lang="bg">Документ — Word</comment>
<comment xml:lang="ca">document Word</comment>
@@ -3666,16 +3799,16 @@
<comment xml:lang="pt">documento Word</comment>
<comment xml:lang="pt_BR">Documento do Word</comment>
<comment xml:lang="ro">Document Word</comment>
- <comment xml:lang="ru">документ Word</comment>
+ <comment xml:lang="ru">Документ Word</comment>
<comment xml:lang="sk">Dokument Word</comment>
<comment xml:lang="sl">Dokument Word</comment>
<comment xml:lang="sq">Dokument Word</comment>
- <comment xml:lang="sr">Вордов документ</comment>
+ <comment xml:lang="sr">Ворд документ</comment>
<comment xml:lang="sv">Word-dokument</comment>
<comment xml:lang="tr">Word belgesi</comment>
<comment xml:lang="uk">документ Word</comment>
<comment xml:lang="vi">Tài liệu Word</comment>
- <comment xml:lang="zh_CN">Microsoft Word 文档</comment>
+ <comment xml:lang="zh_CN">Word 文档</comment>
<comment xml:lang="zh_TW">Word 文件</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.docm"/>
@@ -3683,6 +3816,7 @@
</mime-type>
<mime-type type="application/vnd.ms-word.template.macroEnabled.12">
<comment>Word document template</comment>
+ <comment xml:lang="ast">Plantía de documentu de Word</comment>
<comment xml:lang="ca">plantilla de document Word</comment>
<comment xml:lang="cs">Å¡ablona dokumentu Word</comment>
<comment xml:lang="da">Word-dokumentskabelon</comment>
@@ -3693,6 +3827,7 @@
<comment xml:lang="eu">Word dokumentuaren txantiloia</comment>
<comment xml:lang="fi">Word-asiakirjamalli</comment>
<comment xml:lang="fr">modèle de document Word</comment>
+ <comment xml:lang="ga">teimpléad Word</comment>
<comment xml:lang="he">תבנית מסמך Word</comment>
<comment xml:lang="hr">Predložak Word dokumenta</comment>
<comment xml:lang="hu">Word dokumentumsablon</comment>
@@ -3700,18 +3835,18 @@
<comment xml:lang="id">Templat dokumen Word</comment>
<comment xml:lang="it">Modello documento Word</comment>
<comment xml:lang="kk">Word құжатының үлгіÑÑ–</comment>
- <comment xml:lang="ko">워드 문서 ì–‘ì‹</comment>
+ <comment xml:lang="ko">Word 문서 ì„œì‹</comment>
<comment xml:lang="oc">modèl de document Word</comment>
<comment xml:lang="pl">Szablon dokumentu Word</comment>
<comment xml:lang="pt">modelo de documento Word</comment>
<comment xml:lang="pt_BR">Modelo de documento do Word</comment>
- <comment xml:lang="ru">шаблон документа Word</comment>
+ <comment xml:lang="ru">Шаблон документа Word</comment>
<comment xml:lang="sk">Šablóna dokumentu aplikácie Word</comment>
- <comment xml:lang="sr">Шаблон документа Ворда</comment>
+ <comment xml:lang="sr">Шаблон Ворд документа</comment>
<comment xml:lang="sv">Word-dokumentmall</comment>
<comment xml:lang="tr">Word belgesi ÅŸablonu</comment>
<comment xml:lang="uk">шаблон документа Word</comment>
- <comment xml:lang="zh_CN">Microsoft Word 文档模æ¿</comment>
+ <comment xml:lang="zh_CN">Word 文档模æ¿</comment>
<comment xml:lang="zh_TW">Word 文件範本</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.dotm"/>
@@ -3720,6 +3855,7 @@
<mime-type type="application/oxps">
<comment>XPS document</comment>
<comment xml:lang="ar">مستند XPS</comment>
+ <comment xml:lang="ast">Documentu XPS</comment>
<comment xml:lang="be@latin">Dakument XPS</comment>
<comment xml:lang="bg">Документ — XPS</comment>
<comment xml:lang="ca">document XPS</comment>
@@ -3755,7 +3891,7 @@
<comment xml:lang="pt">documento XPS</comment>
<comment xml:lang="pt_BR">Documento XPS</comment>
<comment xml:lang="ro">Document XPS</comment>
- <comment xml:lang="ru">документ XPS</comment>
+ <comment xml:lang="ru">Документ XPS</comment>
<comment xml:lang="sk">Dokument XPS</comment>
<comment xml:lang="sl">Dokument XPS</comment>
<comment xml:lang="sq">Dokument XPS</comment>
@@ -3773,10 +3909,12 @@
<glob pattern="*.oxps"/>
<glob pattern="*.xps"/>
<alias type="application/vnd.ms-xpsdocument"/>
+ <alias type="application/xps"/>
</mime-type>
<mime-type type="application/vnd.ms-works">
<comment>Microsoft Works document</comment>
<comment xml:lang="ar">مستند Microsoft Works</comment>
+ <comment xml:lang="ast">Documentu de Microsoft Works</comment>
<comment xml:lang="be@latin">Dakument Microsoft Works</comment>
<comment xml:lang="bg">Документ — Microsoft Works</comment>
<comment xml:lang="ca">document de Microsoft Works</comment>
@@ -3812,11 +3950,11 @@
<comment xml:lang="pt">documento Microsoft Works</comment>
<comment xml:lang="pt_BR">Documento do Microsoft Works</comment>
<comment xml:lang="ro">Document Microsoft Works</comment>
- <comment xml:lang="ru">документ Microsoft Works</comment>
+ <comment xml:lang="ru">Документ Microsoft Works</comment>
<comment xml:lang="sk">Dokument Microsoft Works</comment>
<comment xml:lang="sl">Dokument Microsoft Works</comment>
<comment xml:lang="sq">Dokument Microsoft Works</comment>
- <comment xml:lang="sr">МикроÑофтов Ð’Ð¾Ñ€ÐºÑ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚</comment>
+ <comment xml:lang="sr">документ МајкроÑофт ВоркÑа</comment>
<comment xml:lang="sv">Microsoft Works-dokument</comment>
<comment xml:lang="tr">Microsoft Works belgesi</comment>
<comment xml:lang="uk">документ Microsoft Works</comment>
@@ -3833,6 +3971,7 @@
</mime-type>
<mime-type type="application/vnd.visio">
<comment>Microsoft Visio document</comment>
+ <comment xml:lang="ast">Documentu de Microsoft Visio</comment>
<comment xml:lang="bg">Документ — Microsoft Visio</comment>
<comment xml:lang="ca">document de Microsoft Visio</comment>
<comment xml:lang="cs">dokument Microsoft Visio</comment>
@@ -3844,6 +3983,7 @@
<comment xml:lang="eu">Microsoft Visio dokumentua</comment>
<comment xml:lang="fi">Microsoft Visio -asiakirja</comment>
<comment xml:lang="fr">document Microsoft Visio</comment>
+ <comment xml:lang="ga">cáipéis Microsoft Visio</comment>
<comment xml:lang="gl">Documento de Microsoft Visio</comment>
<comment xml:lang="he">מסמך </comment>
<comment xml:lang="hr">Microsoft Visio dokument</comment>
@@ -3861,10 +4001,10 @@
<comment xml:lang="pl">Dokument Microsoft Visio</comment>
<comment xml:lang="pt">documento Microsoft Visio</comment>
<comment xml:lang="pt_BR">Documento do Microsoft Visio</comment>
- <comment xml:lang="ru">документ Microsoft Visio</comment>
+ <comment xml:lang="ru">Документ Microsoft Visio</comment>
<comment xml:lang="sk">Dokument Microsoft Visio</comment>
<comment xml:lang="sl">Dokument Microsoft Visio</comment>
- <comment xml:lang="sr">МикроÑофтов Визио документ</comment>
+ <comment xml:lang="sr">документ МајкроÑофт Визиа</comment>
<comment xml:lang="sv">Microsoft Visio-dokument</comment>
<comment xml:lang="tr">Microsoft Visio belgesi</comment>
<comment xml:lang="uk">документ Microsoft Visio</comment>
@@ -3880,6 +4020,7 @@
<mime-type type="application/msword">
<comment>Word document</comment>
<comment xml:lang="ar">مستند Word</comment>
+ <comment xml:lang="ast">Documentu de Word</comment>
<comment xml:lang="be@latin">Dakument Word</comment>
<comment xml:lang="bg">Документ — Word</comment>
<comment xml:lang="ca">document Word</comment>
@@ -3915,16 +4056,16 @@
<comment xml:lang="pt">documento Word</comment>
<comment xml:lang="pt_BR">Documento do Word</comment>
<comment xml:lang="ro">Document Word</comment>
- <comment xml:lang="ru">документ Word</comment>
+ <comment xml:lang="ru">Документ Word</comment>
<comment xml:lang="sk">Dokument Word</comment>
<comment xml:lang="sl">Dokument Word</comment>
<comment xml:lang="sq">Dokument Word</comment>
- <comment xml:lang="sr">Вордов документ</comment>
+ <comment xml:lang="sr">Ворд документ</comment>
<comment xml:lang="sv">Word-dokument</comment>
<comment xml:lang="tr">Word belgesi</comment>
<comment xml:lang="uk">документ Word</comment>
<comment xml:lang="vi">Tài liệu Word</comment>
- <comment xml:lang="zh_CN">Microsoft Word 文档</comment>
+ <comment xml:lang="zh_CN">Word 文档</comment>
<comment xml:lang="zh_TW">Word 文件</comment>
<sub-class-of type="application/x-ole-storage"/>
<generic-icon name="x-office-document"/>
@@ -3947,6 +4088,7 @@
<mime-type type="application/msword-template">
<comment>Word template</comment>
<comment xml:lang="ar">قالب Word</comment>
+ <comment xml:lang="ast">Plantía de Word</comment>
<comment xml:lang="be@latin">Å ablon Word</comment>
<comment xml:lang="bg">Шаблон за документи — Word</comment>
<comment xml:lang="ca">plantilla de Word</comment>
@@ -3982,11 +4124,11 @@
<comment xml:lang="pt">modelo Word</comment>
<comment xml:lang="pt_BR">Modelo do Word</comment>
<comment xml:lang="ro">Șablon Word</comment>
- <comment xml:lang="ru">шаблон Word</comment>
+ <comment xml:lang="ru">Шаблон Word</comment>
<comment xml:lang="sk">Šablóna Word</comment>
<comment xml:lang="sl">Predloga dokumenta Microsoft Word</comment>
<comment xml:lang="sq">Model Word</comment>
- <comment xml:lang="sr">Вордов шаблон</comment>
+ <comment xml:lang="sr">Ворд шаблон</comment>
<comment xml:lang="sv">Word-mall</comment>
<comment xml:lang="tr">Word ÅŸablonu</comment>
<comment xml:lang="uk">шаблон Word</comment>
@@ -3999,6 +4141,7 @@
</mime-type>
<mime-type type="application/gml+xml">
<comment>GML document</comment>
+ <comment xml:lang="ast">Documentu GML</comment>
<comment xml:lang="ca">document GML</comment>
<comment xml:lang="cs">dokument GML</comment>
<comment xml:lang="da">GML-dokument</comment>
@@ -4009,6 +4152,7 @@
<comment xml:lang="eu">GML dokumentua</comment>
<comment xml:lang="fi">GML-asiakirja</comment>
<comment xml:lang="fr">document GML</comment>
+ <comment xml:lang="ga">cáipéis GML</comment>
<comment xml:lang="gl">Documento GML</comment>
<comment xml:lang="he">מסמך GML</comment>
<comment xml:lang="hr">GML dokument</comment>
@@ -4024,7 +4168,7 @@
<comment xml:lang="pl">Dokument GML</comment>
<comment xml:lang="pt">documento GML</comment>
<comment xml:lang="pt_BR">Documento GML</comment>
- <comment xml:lang="ru">документ GML</comment>
+ <comment xml:lang="ru">Документ GML</comment>
<comment xml:lang="sk">Dokument GML</comment>
<comment xml:lang="sl">Dokument GML</comment>
<comment xml:lang="sr">ГМЛ документ</comment>
@@ -4077,7 +4221,7 @@
<comment xml:lang="pt">ficheiro de procura GNUnet</comment>
<comment xml:lang="pt_BR">Arquivo de pesquisa do GNUnet</comment>
<comment xml:lang="ro">Fișier căutare GNUnet</comment>
- <comment xml:lang="ru">файл поиÑка GNUnet</comment>
+ <comment xml:lang="ru">Файл поиÑка GNUnet</comment>
<comment xml:lang="sk">Vyhľadávací súbor GNUnet</comment>
<comment xml:lang="sl">Iskalna datoteka GNUnet</comment>
<comment xml:lang="sq">File kërkimi GNUnet</comment>
@@ -4096,6 +4240,7 @@
<mime-type type="application/vnd.ms-tnef">
<comment>TNEF message</comment>
<comment xml:lang="ar">رسالة TNEF</comment>
+ <comment xml:lang="ast">Mensaxe TNEF</comment>
<comment xml:lang="be@latin">List TNEF</comment>
<comment xml:lang="bg">Съобщение — TNEF</comment>
<comment xml:lang="ca">missatge TNEF</comment>
@@ -4130,7 +4275,7 @@
<comment xml:lang="pt">mensagem TNEF</comment>
<comment xml:lang="pt_BR">Mensagem TNEF</comment>
<comment xml:lang="ro">Mesaj TNEF</comment>
- <comment xml:lang="ru">Ñообщение TNEF</comment>
+ <comment xml:lang="ru">Сообщение TNEF</comment>
<comment xml:lang="sk">Správa TNEF</comment>
<comment xml:lang="sl">Datoteka sporoÄila TNEF</comment>
<comment xml:lang="sq">Mesazh TNEF</comment>
@@ -4192,16 +4337,16 @@
<comment xml:lang="pt">folha de cálculo do StarCalc</comment>
<comment xml:lang="pt_BR">Planilha do StarCalc</comment>
<comment xml:lang="ro">Foaie de calcul StarCalc</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° StarCalc</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° StarCalc</comment>
<comment xml:lang="sk">Zošit StarCalc</comment>
<comment xml:lang="sl">Preglednica StarCalc</comment>
<comment xml:lang="sq">Fletë llogaritjesh StarCalc</comment>
- <comment xml:lang="sr">Табела Стар Рачуна</comment>
+ <comment xml:lang="sr">Стар калк табела</comment>
<comment xml:lang="sv">StarCalc-kalkylblad</comment>
<comment xml:lang="tr">StarCalc çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ StarCalc</comment>
<comment xml:lang="vi">Bảng tính StarCalc</comment>
- <comment xml:lang="zh_CN">STarCalc 工作簿</comment>
+ <comment xml:lang="zh_CN">StarCalc 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">StarCalc 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.sdc"/>
@@ -4247,7 +4392,7 @@
<comment xml:lang="pt">gráfico do StarChart</comment>
<comment xml:lang="pt_BR">Gráfico do StarChart</comment>
<comment xml:lang="ro">Diagramă StarChart</comment>
- <comment xml:lang="ru">диаграмма StarChart</comment>
+ <comment xml:lang="ru">Диаграмма StarChart</comment>
<comment xml:lang="sk">Graf StarChart</comment>
<comment xml:lang="sl">Datoteka grafikona StarChart</comment>
<comment xml:lang="sq">Grafik StarChart</comment>
@@ -4256,7 +4401,7 @@
<comment xml:lang="tr">StarChart çizgelgesi</comment>
<comment xml:lang="uk">діаграма StarChart</comment>
<comment xml:lang="vi">Äồ thị StarChart</comment>
- <comment xml:lang="zh_CN">STarChart 图表</comment>
+ <comment xml:lang="zh_CN">StarCalc 图表</comment>
<comment xml:lang="zh_TW">StarChart 圖表</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.sds"/>
@@ -4302,7 +4447,7 @@
<comment xml:lang="pt">desenho do StarDraw</comment>
<comment xml:lang="pt_BR">Desenho do StarDraw</comment>
<comment xml:lang="ro">Desen StarDraw</comment>
- <comment xml:lang="ru">изображение StarDraw</comment>
+ <comment xml:lang="ru">РиÑунок StarDraw</comment>
<comment xml:lang="sk">Kresba StarDraw</comment>
<comment xml:lang="sl">Datoteka risbe StarDraw</comment>
<comment xml:lang="sq">Vizatim StarDraw</comment>
@@ -4311,7 +4456,7 @@
<comment xml:lang="tr">StarDraw çizimi</comment>
<comment xml:lang="uk">малюнок StarDraw</comment>
<comment xml:lang="vi">Bản vẽ StarDraw</comment>
- <comment xml:lang="zh_CN">STarDraw 绘图</comment>
+ <comment xml:lang="zh_CN">StarDraw 绘图</comment>
<comment xml:lang="zh_TW">StarDraw 繪圖</comment>
<generic-icon name="image-x-generic"/>
<glob pattern="*.sda"/>
@@ -4357,7 +4502,7 @@
<comment xml:lang="pt">apresentação do StarImpress</comment>
<comment xml:lang="pt_BR">Apresentação do StarImpress</comment>
<comment xml:lang="ro">Prezentare StarImpress</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ StarImpress</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ StarImpress</comment>
<comment xml:lang="sk">Prezentácia StarImpress</comment>
<comment xml:lang="sl">Predstavitev StarImpress</comment>
<comment xml:lang="sq">Prezantim StarImpress</comment>
@@ -4366,7 +4511,7 @@
<comment xml:lang="tr">StarImpress sunumu</comment>
<comment xml:lang="uk">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ StarImpress</comment>
<comment xml:lang="vi">Trình diễn StarImpress</comment>
- <comment xml:lang="zh_CN">STarImpress 演示文稿</comment>
+ <comment xml:lang="zh_CN">StarImpress 演示文稿</comment>
<comment xml:lang="zh_TW">StarImpress 簡報檔</comment>
<generic-icon name="x-office-presentation"/>
<glob pattern="*.sdd"/>
@@ -4411,7 +4556,7 @@
<comment xml:lang="pt">email do StarMail</comment>
<comment xml:lang="pt_BR">E-mail do StarMail</comment>
<comment xml:lang="ro">Email StarEmail</comment>
- <comment xml:lang="ru">Ñлектронное пиÑьмо StarMail</comment>
+ <comment xml:lang="ru">Электронное пиÑьмо StarMail</comment>
<comment xml:lang="sk">E-mail StarMail</comment>
<comment xml:lang="sl">Datoteka pošte StarMail</comment>
<comment xml:lang="sq">Mesazh StarMail</comment>
@@ -4420,7 +4565,7 @@
<comment xml:lang="tr">StarMail epostası</comment>
<comment xml:lang="uk">поштове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ StarMail</comment>
<comment xml:lang="vi">Thư điện tử StarMail</comment>
- <comment xml:lang="zh_CN">STarMail 电å­é‚®ä»¶</comment>
+ <comment xml:lang="zh_CN">StarMail 电å­é‚®ä»¶</comment>
<comment xml:lang="zh_TW">StarMail 郵件</comment>
<glob pattern="*.smd"/>
</mime-type>
@@ -4463,7 +4608,7 @@
<comment xml:lang="pt">fórmula do StarMath</comment>
<comment xml:lang="pt_BR">Fórmula do StarMath</comment>
<comment xml:lang="ro">Formulă StarMath</comment>
- <comment xml:lang="ru">формула StarMath</comment>
+ <comment xml:lang="ru">Формула StarMath</comment>
<comment xml:lang="sk">Vzorec StarMath</comment>
<comment xml:lang="sl">Datoteka formule StarMath</comment>
<comment xml:lang="sq">Formulë StarMath</comment>
@@ -4472,7 +4617,7 @@
<comment xml:lang="tr">StarMath formülü</comment>
<comment xml:lang="uk">формула StarMath</comment>
<comment xml:lang="vi">Công thức StarMath</comment>
- <comment xml:lang="zh_CN">STarMath å…¬å¼</comment>
+ <comment xml:lang="zh_CN">StarMath å…¬å¼</comment>
<comment xml:lang="zh_TW">StarMath å…¬å¼</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.smf"/>
@@ -4480,6 +4625,7 @@
<mime-type type="application/vnd.stardivision.writer">
<comment>StarWriter document</comment>
<comment xml:lang="ar">مستند StarWriter</comment>
+ <comment xml:lang="ast">Documentu de StarWriter</comment>
<comment xml:lang="az">StarWriter sənədi</comment>
<comment xml:lang="be@latin">Dakument StarWriter</comment>
<comment xml:lang="bg">Документ — StarWriter</comment>
@@ -4518,7 +4664,7 @@
<comment xml:lang="pt">documento do StarWriter</comment>
<comment xml:lang="pt_BR">Documento do StarWriter</comment>
<comment xml:lang="ro">Document StarWriter</comment>
- <comment xml:lang="ru">документ StarWriter</comment>
+ <comment xml:lang="ru">Документ StarWriter</comment>
<comment xml:lang="sk">Dokument StarWriter</comment>
<comment xml:lang="sl">Dokument StarWriter</comment>
<comment xml:lang="sq">Dokument StarWriter</comment>
@@ -4527,7 +4673,7 @@
<comment xml:lang="tr">StarWriter belgesi</comment>
<comment xml:lang="uk">документ StarWriter</comment>
<comment xml:lang="vi">Tài liệu StarWriter</comment>
- <comment xml:lang="zh_CN">STarWriter 文档</comment>
+ <comment xml:lang="zh_CN">StarWriter 文档</comment>
<comment xml:lang="zh_TW">StarWriter 文件</comment>
<generic-icon name="x-office-document"/>
<glob pattern="*.sdw"/>
@@ -4576,7 +4722,7 @@
<comment xml:lang="pt">folha de cálculo OpenOffice Calc</comment>
<comment xml:lang="pt_BR">Planilha do OpenOffice Calc</comment>
<comment xml:lang="ro">Foaie de calcul OpenOffice Calc</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° OpenOffice Calc</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° OpenOffice Calc</comment>
<comment xml:lang="sk">Zošit OpenOffice Calc</comment>
<comment xml:lang="sl">Razpredelnica OpenOffice.org Calc</comment>
<comment xml:lang="sq">Fletë llogaritjesh OpenOffice Calc</comment>
@@ -4585,7 +4731,7 @@
<comment xml:lang="tr">OpenOffice Calc çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ OpenOffice Calc</comment>
<comment xml:lang="vi">Bảng tính Calc của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org Calc 工作簿</comment>
+ <comment xml:lang="zh_CN">OpenOffice Calc 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">OpenOffice Calc 試算表</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-spreadsheet"/>
@@ -4636,7 +4782,7 @@
<comment xml:lang="pt">modelo OpenOffice Calc</comment>
<comment xml:lang="pt_BR">Modelo do OpenOffice Calc</comment>
<comment xml:lang="ro">Șablon OpenOffice Calc</comment>
- <comment xml:lang="ru">шаблон OpenOffice Calc</comment>
+ <comment xml:lang="ru">Шаблон OpenOffice Calc</comment>
<comment xml:lang="sk">Šablóna OpenOffice Calc</comment>
<comment xml:lang="sl">Predloga OpenOffice.org Calc</comment>
<comment xml:lang="sq">Model OpenOffice Calc</comment>
@@ -4645,7 +4791,7 @@
<comment xml:lang="tr">OpenOffice Calc ÅŸablonu</comment>
<comment xml:lang="uk">шаблон ел.таблиці OpenOffice Calc</comment>
<comment xml:lang="vi">Mẫu bảng tính Calc của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org Calc 工作簿模æ¿</comment>
+ <comment xml:lang="zh_CN">OpenOffice Calc 模æ¿</comment>
<comment xml:lang="zh_TW">OpenOffice Calc 範本</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-spreadsheet"/>
@@ -4696,7 +4842,7 @@
<comment xml:lang="pt">desenho OpenOffice Draw</comment>
<comment xml:lang="pt_BR">Desenho do OpenOffice Draw</comment>
<comment xml:lang="ro">Desen OpenOffice Draw</comment>
- <comment xml:lang="ru">изображение OpenOffice Draw</comment>
+ <comment xml:lang="ru">РиÑунок OpenOffice Draw</comment>
<comment xml:lang="sk">Kresba OpenOffice Draw</comment>
<comment xml:lang="sl">Datoteka risbe OpenOffice.org Draw</comment>
<comment xml:lang="sq">Vizatim OpenOffice Draw</comment>
@@ -4705,7 +4851,7 @@
<comment xml:lang="tr">OpenOffice Draw çizimi</comment>
<comment xml:lang="uk">малюнок OpenOffice Draw</comment>
<comment xml:lang="vi">Bản vẽ Draw của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org Draw 绘图</comment>
+ <comment xml:lang="zh_CN">OpenOffice Draw 绘图</comment>
<comment xml:lang="zh_TW">OpenOffice Draw 繪圖</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="image-x-generic"/>
@@ -4756,7 +4902,7 @@
<comment xml:lang="pt">modelo OpenOffice Draw</comment>
<comment xml:lang="pt_BR">Modelo do OpenOffice Draw</comment>
<comment xml:lang="ro">Șablon OpenOffice Draw</comment>
- <comment xml:lang="ru">шаблон OpenOffice Draw</comment>
+ <comment xml:lang="ru">Шаблон OpenOffice Draw</comment>
<comment xml:lang="sk">Šablóna OpenOffice Draw</comment>
<comment xml:lang="sl">Predloga OpenOffice.org Draw</comment>
<comment xml:lang="sq">Model OpenOffice Draw</comment>
@@ -4765,7 +4911,7 @@
<comment xml:lang="tr">OpenOffice Draw ÅŸablonu</comment>
<comment xml:lang="uk">шаблон малюнку OpenOffice Draw</comment>
<comment xml:lang="vi">Mẫu bản vẽ Draw của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org Draw 绘图模æ¿</comment>
+ <comment xml:lang="zh_CN">OpenOffice Draw 模æ¿</comment>
<comment xml:lang="zh_TW">OpenOffice Draw 範本</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="image-x-generic"/>
@@ -4818,7 +4964,7 @@
<comment xml:lang="pt">apresentação OpenOffice Impress</comment>
<comment xml:lang="pt_BR">Apresentação do OpenOffice Impress</comment>
<comment xml:lang="ro">Prezentare OpenOffice Impress</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ OpenOffice Impress</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ OpenOffice Impress</comment>
<comment xml:lang="sk">Prezentácia OpenOffice Impress</comment>
<comment xml:lang="sl">Predstavitev OpenOffice.org Impress</comment>
<comment xml:lang="sq">Prezantim OpenOffice Impress</comment>
@@ -4827,7 +4973,7 @@
<comment xml:lang="tr">OpenOffice Impress sunumu</comment>
<comment xml:lang="uk">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ OpenOffice Impress</comment>
<comment xml:lang="vi">Trình diễn Impress của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org Impress 演示文稿</comment>
+ <comment xml:lang="zh_CN">OpenOffice Impress 演示文稿</comment>
<comment xml:lang="zh_TW">OpenOffice Impress ç°¡å ±</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
@@ -4878,7 +5024,7 @@
<comment xml:lang="pt">modelo OpenOffice Impress</comment>
<comment xml:lang="pt_BR">Modelo do OpenOffice Impress</comment>
<comment xml:lang="ro">Șablon OpenOffice Impress</comment>
- <comment xml:lang="ru">шаблон OpenOffice Impress</comment>
+ <comment xml:lang="ru">Шаблон OpenOffice Impress</comment>
<comment xml:lang="sk">Šablóna OpenOffice Impress</comment>
<comment xml:lang="sl">Predloga OpenOffice.org Impress</comment>
<comment xml:lang="sq">Model OpenOffice Impress</comment>
@@ -4887,7 +5033,7 @@
<comment xml:lang="tr">OpenOffice Impress ÅŸablonu</comment>
<comment xml:lang="uk">шаблон презентації OpenOffice Impress</comment>
<comment xml:lang="vi">Mẫu trình diễn Impress của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org Impress 演示文稿模æ¿</comment>
+ <comment xml:lang="zh_CN">OpenOffice Impress 模æ¿</comment>
<comment xml:lang="zh_TW">OpenOffice Impress 範本</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-presentation"/>
@@ -4938,7 +5084,7 @@
<comment xml:lang="pt">fórmula OpenOffice Math</comment>
<comment xml:lang="pt_BR">Fórmula do OpenOffice Math</comment>
<comment xml:lang="ro">Formulă OpenOffice Math</comment>
- <comment xml:lang="ru">формула OpenOffice Math</comment>
+ <comment xml:lang="ru">Формула OpenOffice Math</comment>
<comment xml:lang="sk">Vzorec OpenOffice Math</comment>
<comment xml:lang="sl">Dokument formule OpenOffice.org Math</comment>
<comment xml:lang="sq">Formulë OpenOffice Math</comment>
@@ -4947,7 +5093,7 @@
<comment xml:lang="tr">OpenOffice Math formülü</comment>
<comment xml:lang="uk">формула OpenOffice Math</comment>
<comment xml:lang="vi">Công thức Math của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org Math å…¬å¼</comment>
+ <comment xml:lang="zh_CN">OpenOffice Math å…¬å¼</comment>
<comment xml:lang="zh_TW">OpenOffice Math å…¬å¼</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
@@ -4963,6 +5109,7 @@
<mime-type type="application/vnd.sun.xml.writer">
<comment>OpenOffice Writer document</comment>
<comment xml:lang="ar">مستند Writer المكتب المÙتوح</comment>
+ <comment xml:lang="ast">Documentu d'OpenOffice Writer</comment>
<comment xml:lang="az">OpenOffice Writer sənədi</comment>
<comment xml:lang="be@latin">Dakument OpenOffice Writer</comment>
<comment xml:lang="bg">Документ — OpenOffice Writer</comment>
@@ -5000,7 +5147,7 @@
<comment xml:lang="pt">documento OpenOffice Writer</comment>
<comment xml:lang="pt_BR">Documento do OpenOffice Writer</comment>
<comment xml:lang="ro">Document OpenOffice Writer</comment>
- <comment xml:lang="ru">документ OpenOffice Writer</comment>
+ <comment xml:lang="ru">Документ OpenOffice Writer</comment>
<comment xml:lang="sk">Dokument OpenOffice Writer</comment>
<comment xml:lang="sl">Dokument OpenOffice.org Writer</comment>
<comment xml:lang="sq">Dokument OpenOffice Writer</comment>
@@ -5009,7 +5156,7 @@
<comment xml:lang="tr">OpenOffice Writer belgesi</comment>
<comment xml:lang="uk">документ OpenOffice Writer</comment>
<comment xml:lang="vi">Tài liệu Writer của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org Writer 文档</comment>
+ <comment xml:lang="zh_CN">OpenOffice Writer 文档</comment>
<comment xml:lang="zh_TW">OpenOffice Writer 文件</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
@@ -5025,6 +5172,7 @@
<mime-type type="application/vnd.sun.xml.writer.global">
<comment>OpenOffice Writer global document</comment>
<comment xml:lang="ar">مستند المكتب المÙتوح Writer العالمي</comment>
+ <comment xml:lang="ast">Documentu global d'OpenOffice Writer</comment>
<comment xml:lang="az">OpenOffice Writer qlobal sənədi</comment>
<comment xml:lang="be@latin">Hlabalny dakument OpenOffice Writer</comment>
<comment xml:lang="bg">Документ - глобален — OpenOffice Writer</comment>
@@ -5062,7 +5210,7 @@
<comment xml:lang="pt">documento global OpenOffice Writer</comment>
<comment xml:lang="pt_BR">Documento global do OpenOffice Writer</comment>
<comment xml:lang="ro">Document global OpenOffice Writer</comment>
- <comment xml:lang="ru">оÑновной документ OpenOffice Writer</comment>
+ <comment xml:lang="ru">ОÑновной документ OpenOffice Writer</comment>
<comment xml:lang="sk">Globálny dokument OpenOffice Writer</comment>
<comment xml:lang="sl">Splošni dokument OpenOffice.org Writer</comment>
<comment xml:lang="sq">Dokument i përgjithshëm OpenOffice Writer</comment>
@@ -5071,7 +5219,7 @@
<comment xml:lang="tr">OpenOffice Writer global belgesi</comment>
<comment xml:lang="uk">загальний документ OpenOffice Writer</comment>
<comment xml:lang="vi">Tài liệu toàn cục Writer của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org Writer 全局文档</comment>
+ <comment xml:lang="zh_CN">OpenOffice Writer 全局文档</comment>
<comment xml:lang="zh_TW">OpenOffice Writer 主控文件</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
@@ -5125,7 +5273,7 @@
<comment xml:lang="pt">modelo OpenOffice Writer</comment>
<comment xml:lang="pt_BR">Modelo do OpenOffice Writer</comment>
<comment xml:lang="ro">Șablon OpenOffice Writer</comment>
- <comment xml:lang="ru">шаблон OpenOffice Writer</comment>
+ <comment xml:lang="ru">Шаблон OpenOffice Writer</comment>
<comment xml:lang="sk">Šablóna OpenOffice Writer</comment>
<comment xml:lang="sl">Predloga OpenOffice.org Writer</comment>
<comment xml:lang="sq">Model OpenOffice Writer</comment>
@@ -5134,7 +5282,7 @@
<comment xml:lang="tr">OpenOffice Writer ÅŸablonu</comment>
<comment xml:lang="uk">шаблон документа OpenOffice Writer</comment>
<comment xml:lang="vi">Mẫu tài liệu Writer của OpenOffice.org</comment>
- <comment xml:lang="zh_CN">OpenOffice.org Writer 文档模æ¿</comment>
+ <comment xml:lang="zh_CN">OpenOffice Writer 模æ¿</comment>
<comment xml:lang="zh_TW">OpenOffice Writer 範本</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
@@ -5150,6 +5298,7 @@
<mime-type type="application/vnd.oasis.opendocument.text">
<comment>ODT document</comment>
<comment xml:lang="ar">مستند ODT</comment>
+ <comment xml:lang="ast">Documentu ODT</comment>
<comment xml:lang="be@latin">Dakument ODT</comment>
<comment xml:lang="bg">Документ — ODT</comment>
<comment xml:lang="ca">document ODT</comment>
@@ -5186,7 +5335,7 @@
<comment xml:lang="pt">documento ODT</comment>
<comment xml:lang="pt_BR">Documento ODT</comment>
<comment xml:lang="ro">Document ODT</comment>
- <comment xml:lang="ru">документ ODT</comment>
+ <comment xml:lang="ru">Документ ODT</comment>
<comment xml:lang="sk">Dokument ODT</comment>
<comment xml:lang="sl">Dokument ODT</comment>
<comment xml:lang="sq">Dokument ODT</comment>
@@ -5213,6 +5362,7 @@
<mime-type type="application/vnd.oasis.opendocument.text-flat-xml">
<comment>ODT document (Flat XML)</comment>
<comment xml:lang="ar">مستند ODT (Flat XML)</comment>
+ <comment xml:lang="ast">Documentu ODT (XML planu)</comment>
<comment xml:lang="bg">Документ — ODT (Ñамо XML)</comment>
<comment xml:lang="ca">document ODT (XML pla)</comment>
<comment xml:lang="cs">dokument ODT (Flat XML)</comment>
@@ -5245,14 +5395,14 @@
<comment xml:lang="pt">documento ODT (XML plano)</comment>
<comment xml:lang="pt_BR">Documento ODT (Flat XML)</comment>
<comment xml:lang="ro">Document ODT (XML simplu)</comment>
- <comment xml:lang="ru">документ ODT (проÑтой XML)</comment>
+ <comment xml:lang="ru">Документ ODT (проÑтой XML)</comment>
<comment xml:lang="sk">Dokument ODT (Äisté XML)</comment>
<comment xml:lang="sl">Datoteka dokumenta ODT (nepovezan XML)</comment>
<comment xml:lang="sr">ОДТ документ (Обични ИкÑМЛ)</comment>
<comment xml:lang="sv">ODT-dokument (platt XML)</comment>
<comment xml:lang="tr">ODT belgesi (Düz XML)</comment>
<comment xml:lang="uk">документ ODT (Flat XML)</comment>
- <comment xml:lang="zh_CN">ODT 文档(Flat XML)</comment>
+ <comment xml:lang="zh_CN">ODT 文档(Flat XML)</comment>
<comment xml:lang="zh_TW">ODT 文件 (Flat XML)</comment>
<acronym>FODT</acronym>
<expanded-acronym>OpenDocument Text (Flat XML)</expanded-acronym>
@@ -5299,7 +5449,7 @@
<comment xml:lang="pt">modelo ODT</comment>
<comment xml:lang="pt_BR">Modelo ODT</comment>
<comment xml:lang="ro">Șablon ODT</comment>
- <comment xml:lang="ru">шаблон ODT</comment>
+ <comment xml:lang="ru">Шаблон ODT</comment>
<comment xml:lang="sk">Šablóna ODT</comment>
<comment xml:lang="sl">Predloga dokumenta ODT</comment>
<comment xml:lang="sq">Model ODT</comment>
@@ -5362,7 +5512,7 @@
<comment xml:lang="pt">modelo OTH</comment>
<comment xml:lang="pt_BR">Modelo OTH</comment>
<comment xml:lang="ro">Șablon OTH</comment>
- <comment xml:lang="ru">шаблон OTH</comment>
+ <comment xml:lang="ru">Шаблон OTH</comment>
<comment xml:lang="sk">Šablóna OTH</comment>
<comment xml:lang="sl">Predloga OTH</comment>
<comment xml:lang="sq">Model OTH</comment>
@@ -5389,6 +5539,7 @@
<mime-type type="application/vnd.oasis.opendocument.text-master">
<comment>ODM document</comment>
<comment xml:lang="ar">مستند ODM</comment>
+ <comment xml:lang="ast">Documentu ODM</comment>
<comment xml:lang="be@latin">Dakument ODM</comment>
<comment xml:lang="bg">Документ — ODM</comment>
<comment xml:lang="ca">document ODM</comment>
@@ -5425,7 +5576,7 @@
<comment xml:lang="pt">documento ODM</comment>
<comment xml:lang="pt_BR">Documento ODM</comment>
<comment xml:lang="ro">Document ODM</comment>
- <comment xml:lang="ru">документ ODM</comment>
+ <comment xml:lang="ru">Документ ODM</comment>
<comment xml:lang="sk">Dokument ODM</comment>
<comment xml:lang="sl">Dokument ODM</comment>
<comment xml:lang="sq">Dokument ODM</comment>
@@ -5488,7 +5639,7 @@
<comment xml:lang="pt">desenho ODG</comment>
<comment xml:lang="pt_BR">Desenho ODG</comment>
<comment xml:lang="ro">Desen ODG</comment>
- <comment xml:lang="ru">изображение ODG</comment>
+ <comment xml:lang="ru">РиÑунок ODG</comment>
<comment xml:lang="sk">Kresba ODG</comment>
<comment xml:lang="sl">Datoteka risbe ODG</comment>
<comment xml:lang="sq">Vizatim ODG</comment>
@@ -5547,14 +5698,14 @@
<comment xml:lang="pt">desenho ODG (XML plano)</comment>
<comment xml:lang="pt_BR">Desenho ODG (Flat XML)</comment>
<comment xml:lang="ro">Desen ODG (XML simplu)</comment>
- <comment xml:lang="ru">изображение ODG (проÑтой XML)</comment>
+ <comment xml:lang="ru">РиÑунок ODG (проÑтой XML)</comment>
<comment xml:lang="sk">Kresba ODG (Äisté XML)</comment>
<comment xml:lang="sl">Datoteka risbe ODG (nepovezan XML)</comment>
<comment xml:lang="sr">ОДГ цртеж (Обичан ИкÑМЛ)</comment>
<comment xml:lang="sv">ODG-teckning (platt XML)</comment>
<comment xml:lang="tr">ODG çizimi (Düz XML)</comment>
<comment xml:lang="uk">малюнок ODG (Flat XML)</comment>
- <comment xml:lang="zh_CN">ODG 绘图(Flat XML)</comment>
+ <comment xml:lang="zh_CN">ODG 绘图(Flat XML)</comment>
<comment xml:lang="zh_TW">ODG 繪圖 (Flat XML)</comment>
<acronym>FODG</acronym>
<expanded-acronym>OpenDocument Drawing (Flat XML)</expanded-acronym>
@@ -5601,7 +5752,7 @@
<comment xml:lang="pt">modelo ODG</comment>
<comment xml:lang="pt_BR">Modelo ODG</comment>
<comment xml:lang="ro">Șablon ODG</comment>
- <comment xml:lang="ru">шаблон ODG</comment>
+ <comment xml:lang="ru">Шаблон ODG</comment>
<comment xml:lang="sk">Šablóna ODG</comment>
<comment xml:lang="sl">Predloga dokumenta ODG</comment>
<comment xml:lang="sq">Model ODG</comment>
@@ -5664,7 +5815,7 @@
<comment xml:lang="pt">apresentação ODP</comment>
<comment xml:lang="pt_BR">Apresentação ODP</comment>
<comment xml:lang="ro">Prezentare ODP</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ ODP</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ ODP</comment>
<comment xml:lang="sk">Prezentácia ODP</comment>
<comment xml:lang="sl">Predstavitev ODP</comment>
<comment xml:lang="sq">Prezantim ODP</comment>
@@ -5723,14 +5874,14 @@
<comment xml:lang="pt">apresentação ODP (XML plano)</comment>
<comment xml:lang="pt_BR">Apresentação ODP (Flat XML)</comment>
<comment xml:lang="ro">Prezentare ODP (XML simplu)</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ ODP (проÑтой XML)</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ ODP (проÑтой XML)</comment>
<comment xml:lang="sk">Prezentácia ODP (Äisté XML)</comment>
<comment xml:lang="sl">Predstavitev ODP (nepovezan XML)</comment>
<comment xml:lang="sr">ОДП презентација (Обични ИкÑМЛ)</comment>
<comment xml:lang="sv">ODP-presentation (platt XML)</comment>
<comment xml:lang="tr">ODP sunumu (Düz XML)</comment>
<comment xml:lang="uk">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ ODP (Flat XML)</comment>
- <comment xml:lang="zh_CN">ODP 演示文稿(Flat XML)</comment>
+ <comment xml:lang="zh_CN">ODP 演示文稿(Flat XML)</comment>
<comment xml:lang="zh_TW">ODP 範本 (Flat XML)</comment>
<acronym>FODP</acronym>
<expanded-acronym>OpenDocument Presentation (Flat XML)</expanded-acronym>
@@ -5777,7 +5928,7 @@
<comment xml:lang="pt">modelo ODP</comment>
<comment xml:lang="pt_BR">Modelo ODP</comment>
<comment xml:lang="ro">Șablon ODP</comment>
- <comment xml:lang="ru">шаблон ODP</comment>
+ <comment xml:lang="ru">Шаблон ODP</comment>
<comment xml:lang="sk">Šablóna ODP</comment>
<comment xml:lang="sl">Predloga dokumenta ODP</comment>
<comment xml:lang="sq">Model ODP</comment>
@@ -5840,16 +5991,16 @@
<comment xml:lang="pt">folha de cálculo ODS</comment>
<comment xml:lang="pt_BR">Planilha ODS</comment>
<comment xml:lang="ro">Foaie de calcul ODS</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° ODS</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° ODS</comment>
<comment xml:lang="sk">Zošit ODS</comment>
<comment xml:lang="sl">Preglednica ODS</comment>
<comment xml:lang="sq">Fletë llogaritjesh ODS</comment>
- <comment xml:lang="sr">ОДС spreadsheet</comment>
+ <comment xml:lang="sr">ОДС табела</comment>
<comment xml:lang="sv">ODS-kalkylblad</comment>
<comment xml:lang="tr">ODS çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ ODS</comment>
<comment xml:lang="vi">Bảng tính ODS</comment>
- <comment xml:lang="zh_CN">ODS 工作簿</comment>
+ <comment xml:lang="zh_CN">ODS 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">ODS 試算表</comment>
<acronym>ODS</acronym>
<expanded-acronym>OpenDocument Spreadsheet</expanded-acronym>
@@ -5899,14 +6050,14 @@
<comment xml:lang="pt">folha de cálculo ODS (XML plano)</comment>
<comment xml:lang="pt_BR">Planilha ODS (Flat XML)</comment>
<comment xml:lang="ro">Foaie de calcul ODS (XML simplu)</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° ODS (проÑтой XML)</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° ODS (проÑтой XML)</comment>
<comment xml:lang="sk">ZoÅ¡it ODS (Äisté XML)</comment>
<comment xml:lang="sl">Preglednica ODS (nepovezan XML)</comment>
- <comment xml:lang="sr">ОДС spreadsheet (Обични ИкÑМЛ)</comment>
+ <comment xml:lang="sr">ОДС табела (обични ИкÑМЛ)</comment>
<comment xml:lang="sv">ODS-kalkylblad (platt XML)</comment>
<comment xml:lang="tr">ODS sunumu (Düz XML)</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ ODS (Flat XML)</comment>
- <comment xml:lang="zh_CN">ODS 工作簿(Flat XML)</comment>
+ <comment xml:lang="zh_CN">ODS 电å­è¡¨æ ¼ (Flat XML)</comment>
<comment xml:lang="zh_TW">ODS 試算表 (Flat XML)</comment>
<acronym>FODS</acronym>
<expanded-acronym>OpenDocument Spreadsheet (Flat XML)</expanded-acronym>
@@ -5953,7 +6104,7 @@
<comment xml:lang="pt">modelo ODS</comment>
<comment xml:lang="pt_BR">Modelo ODS</comment>
<comment xml:lang="ro">Șablon ODS</comment>
- <comment xml:lang="ru">шаблон ODS</comment>
+ <comment xml:lang="ru">Шаблон ODS</comment>
<comment xml:lang="sk">Šablóna ODS</comment>
<comment xml:lang="sl">Predloga dokumenta ODS</comment>
<comment xml:lang="sq">Model ODS</comment>
@@ -6015,11 +6166,11 @@
<comment xml:lang="pt">gráfico ODC</comment>
<comment xml:lang="pt_BR">Gráfico ODC</comment>
<comment xml:lang="ro">Diagramă ODC</comment>
- <comment xml:lang="ru">диаграмма ODC</comment>
+ <comment xml:lang="ru">Диаграмма ODC</comment>
<comment xml:lang="sk">Graf ODC</comment>
<comment xml:lang="sl">Datoteka grafikona ODC</comment>
<comment xml:lang="sq">Grafik ODC</comment>
- <comment xml:lang="sr">ОДЦ chart</comment>
+ <comment xml:lang="sr">ОДЦ график</comment>
<comment xml:lang="sv">ODC-diagram</comment>
<comment xml:lang="tr">ODC çizelgesi</comment>
<comment xml:lang="uk">діаграма ODC</comment>
@@ -6075,7 +6226,7 @@
<comment xml:lang="pt">modelo ODC</comment>
<comment xml:lang="pt_BR">Modelo ODC</comment>
<comment xml:lang="ro">Șablon ODC</comment>
- <comment xml:lang="ru">шаблон ODC</comment>
+ <comment xml:lang="ru">Шаблон ODC</comment>
<comment xml:lang="sk">Šablóna ODC</comment>
<comment xml:lang="sl">Predloga ODC</comment>
<comment xml:lang="sr">ОДЦ шаблон</comment>
@@ -6137,11 +6288,11 @@
<comment xml:lang="pt">fórmula ODF</comment>
<comment xml:lang="pt_BR">Fórmula ODF</comment>
<comment xml:lang="ro">Formulă ODF</comment>
- <comment xml:lang="ru">формула ODF</comment>
+ <comment xml:lang="ru">Формула ODF</comment>
<comment xml:lang="sk">Vzorec ODF</comment>
<comment xml:lang="sl">Dokument formule ODF</comment>
<comment xml:lang="sq">Formulë ODF</comment>
- <comment xml:lang="sr">ОДФ formula</comment>
+ <comment xml:lang="sr">ОДФ формула</comment>
<comment xml:lang="sv">ODF-formel</comment>
<comment xml:lang="tr">ODF formülü</comment>
<comment xml:lang="uk">формула ODF</comment>
@@ -6197,7 +6348,7 @@
<comment xml:lang="pt">modelo ODF</comment>
<comment xml:lang="pt_BR">Modelo ODF</comment>
<comment xml:lang="ro">Șablon ODF</comment>
- <comment xml:lang="ru">шаблон ODF</comment>
+ <comment xml:lang="ru">Шаблон ODF</comment>
<comment xml:lang="sk">Šablóna ODF</comment>
<comment xml:lang="sl">Predloga dokumenta ODF</comment>
<comment xml:lang="sr">ОДФ шаблон</comment>
@@ -6259,7 +6410,7 @@
<comment xml:lang="pt">base de dados ODB</comment>
<comment xml:lang="pt_BR">Banco de dados ODB</comment>
<comment xml:lang="ro">Bază de date ODB</comment>
- <comment xml:lang="ru">база данных ODB</comment>
+ <comment xml:lang="ru">База данных ODB</comment>
<comment xml:lang="sk">Databáza ODB</comment>
<comment xml:lang="sl">Podatkovna zbirka ODB</comment>
<comment xml:lang="sq">Bazë me të dhëna ODB</comment>
@@ -6287,6 +6438,7 @@
<mime-type type="application/vnd.oasis.opendocument.image">
<comment>ODI image</comment>
<comment xml:lang="ar">صورة ODI</comment>
+ <comment xml:lang="ast">Imaxe ODI</comment>
<comment xml:lang="be@latin">Vyjava ODI</comment>
<comment xml:lang="bg">Изображение — ODI</comment>
<comment xml:lang="ca">imatge ODI</comment>
@@ -6323,7 +6475,7 @@
<comment xml:lang="pt">imagem ODI</comment>
<comment xml:lang="pt_BR">Imagem ODI</comment>
<comment xml:lang="ro">Imagine ODI</comment>
- <comment xml:lang="ru">изображение ODI</comment>
+ <comment xml:lang="ru">Изображение ODI</comment>
<comment xml:lang="sk">Obrázok ODI</comment>
<comment xml:lang="sl">Slikovna datoteka ODI</comment>
<comment xml:lang="sq">Figurë ODI</comment>
@@ -6350,6 +6502,7 @@
<mime-type type="application/vnd.openofficeorg.extension">
<comment>OpenOffice.org extension</comment>
<comment xml:lang="ar">امتداد OpenOffice.org</comment>
+ <comment xml:lang="ast">Estensión d'OpenOffice.org</comment>
<comment xml:lang="be@latin">Pašyreńnie OpenOffice.org</comment>
<comment xml:lang="bg">Разширение — OpenOffice</comment>
<comment xml:lang="ca">extensió d'OpenOffice.org</comment>
@@ -6384,7 +6537,7 @@
<comment xml:lang="pt">extensão OpenOffice.org</comment>
<comment xml:lang="pt_BR">Extensão do OpenOffice</comment>
<comment xml:lang="ro">Extensie OpenOffice.org</comment>
- <comment xml:lang="ru">раÑширение OpenOffice.org</comment>
+ <comment xml:lang="ru">РаÑширение OpenOffice.org</comment>
<comment xml:lang="sk">Rozšírenie OpenOffice.org</comment>
<comment xml:lang="sl">Razširitev OpenOffice.org</comment>
<comment xml:lang="sq">Shtojcë për OpenOffice.org</comment>
@@ -6401,6 +6554,7 @@
</mime-type>
<mime-type type="application/vnd.android.package-archive">
<comment>Android package</comment>
+ <comment xml:lang="ast">Paquete d'Android</comment>
<comment xml:lang="bg">Пакет — Android</comment>
<comment xml:lang="ca">paquet d'Android</comment>
<comment xml:lang="cs">balíÄky systému Android</comment>
@@ -6413,6 +6567,7 @@
<comment xml:lang="eu">Android paketea</comment>
<comment xml:lang="fi">Android-paketti</comment>
<comment xml:lang="fr">paquet Android</comment>
+ <comment xml:lang="ga">pacáiste Android</comment>
<comment xml:lang="gl">paquete de Android</comment>
<comment xml:lang="he">חבילת ×נדרויד</comment>
<comment xml:lang="hr">Android paket</comment>
@@ -6430,14 +6585,14 @@
<comment xml:lang="pl">Pakiet Androida</comment>
<comment xml:lang="pt">pacote Android</comment>
<comment xml:lang="pt_BR">Pacote do Android</comment>
- <comment xml:lang="ru">пакет Android</comment>
+ <comment xml:lang="ru">Пакет Android</comment>
<comment xml:lang="sk">Balík Android</comment>
<comment xml:lang="sl">Paket Android</comment>
<comment xml:lang="sr">Ðндроидов пакет</comment>
<comment xml:lang="sv">Android-paket</comment>
<comment xml:lang="tr">Android paketi</comment>
<comment xml:lang="uk">пакунок Android</comment>
- <comment xml:lang="zh_CN">Android</comment>
+ <comment xml:lang="zh_CN">Android 应用包</comment>
<comment xml:lang="zh_TW">Android 軟體包</comment>
<sub-class-of type="application/x-java-archive"/>
<glob pattern="*.apk"/>
@@ -6445,6 +6600,7 @@
<mime-type type="application/vnd.symbian.install">
<comment>SIS package</comment>
<comment xml:lang="ar">حزمة SIS</comment>
+ <comment xml:lang="ast">Paquete SIS</comment>
<comment xml:lang="be@latin">Pakunak SIS</comment>
<comment xml:lang="bg">Пакет — SIS</comment>
<comment xml:lang="ca">paquet SIS</comment>
@@ -6480,7 +6636,7 @@
<comment xml:lang="pt">pacote SIS</comment>
<comment xml:lang="pt_BR">Pacote SIS</comment>
<comment xml:lang="ro">Pachet SIS</comment>
- <comment xml:lang="ru">пакет SIS</comment>
+ <comment xml:lang="ru">Пакет SIS</comment>
<comment xml:lang="sk">BalíÄek SIS</comment>
<comment xml:lang="sl">Datoteka paketa SIS</comment>
<comment xml:lang="sq">Paketë SIS</comment>
@@ -6502,6 +6658,7 @@
<mime-type type="x-epoc/x-sisx-app">
<comment>SISX package</comment>
<comment xml:lang="ar">حزمة SISX</comment>
+ <comment xml:lang="ast">Paquete SISX</comment>
<comment xml:lang="be@latin">Pakunak SISX</comment>
<comment xml:lang="bg">Пакет — SISX</comment>
<comment xml:lang="ca">paquet SISX</comment>
@@ -6537,7 +6694,7 @@
<comment xml:lang="pt">pacote SISX</comment>
<comment xml:lang="pt_BR">Pacote SISX</comment>
<comment xml:lang="ro">Pachet SISX</comment>
- <comment xml:lang="ru">пакет SISX</comment>
+ <comment xml:lang="ru">Пакет SISX</comment>
<comment xml:lang="sk">BalíÄek SISX</comment>
<comment xml:lang="sl">Datoteka paketa SISX</comment>
<comment xml:lang="sq">Paketë SISX</comment>
@@ -6569,6 +6726,7 @@
<comment xml:lang="eu">Sareko pakete kaptura</comment>
<comment xml:lang="fi">Verkkopakettien kaappaus</comment>
<comment xml:lang="fr">capture de paquet réseau</comment>
+ <comment xml:lang="ga">Gabháltas Paicéid Líonra</comment>
<comment xml:lang="gl">Captura de Network Packet</comment>
<comment xml:lang="he">לכידה של מנות × ×ª×•× ×™× ×‘×¨×©×ª</comment>
<comment xml:lang="hr">Mrežno hvatanje paketa</comment>
@@ -6586,7 +6744,7 @@
<comment xml:lang="pl">Przechwycenie pakietu sieciowego</comment>
<comment xml:lang="pt">captura Network Packet</comment>
<comment xml:lang="pt_BR">Pacote de captura de rede</comment>
- <comment xml:lang="ru">захваченные Ñетевые пакеты</comment>
+ <comment xml:lang="ru">Захваченные Ñетевые пакеты</comment>
<comment xml:lang="sk">Zachytené sieťové pakety</comment>
<comment xml:lang="sl">Zajem omrežnih paketov</comment>
<comment xml:lang="sr">Снимање мрежног пакета</comment>
@@ -6608,6 +6766,7 @@
<mime-type type="application/vnd.wordperfect">
<comment>WordPerfect document</comment>
<comment xml:lang="ar">مستند WordPerfect</comment>
+ <comment xml:lang="ast">Documentu de WordPerfect</comment>
<comment xml:lang="az">WordPerfect sənədi</comment>
<comment xml:lang="be@latin">Dakument WordPerfect</comment>
<comment xml:lang="bg">Документ — WordPerfect</comment>
@@ -6646,11 +6805,11 @@
<comment xml:lang="pt">documento WordPerfect</comment>
<comment xml:lang="pt_BR">Documento do WordPerfect</comment>
<comment xml:lang="ro">Document WordPerfect</comment>
- <comment xml:lang="ru">документ WordPerfect</comment>
+ <comment xml:lang="ru">Документ WordPerfect</comment>
<comment xml:lang="sk">Dokument WordPerfect</comment>
<comment xml:lang="sl">Dokument WordPerfect</comment>
<comment xml:lang="sq">Dokument WordPerfect</comment>
- <comment xml:lang="sr">документ Ворд Перфекта</comment>
+ <comment xml:lang="sr">документ Ворд перфекта</comment>
<comment xml:lang="sv">WordPerfect-dokument</comment>
<comment xml:lang="tr">WordPerfect belgesi</comment>
<comment xml:lang="uk">документ WordPerfect</comment>
@@ -6671,6 +6830,12 @@
<glob pattern="*.wpd"/>
<glob pattern="*.wpp"/>
</mime-type>
+ <mime-type type="application/vnd.youtube.yt">
+ <comment>YouTube Media Archive</comment>
+ <generic-icon name="video-x-generic"/>
+ <glob pattern="*.yt"/>
+ <sub-class-of type="application/zip"/>
+ </mime-type>
<mime-type type="application/x-spss-por">
<comment>SPSS Portable Data File</comment>
<comment xml:lang="ar">مل٠بيانات SPSS متنقلة</comment>
@@ -6704,7 +6869,7 @@
<comment xml:lang="pt">ficheiro de dados portátil SPSS</comment>
<comment xml:lang="pt_BR">Arquivo de Dados Portáteis SPSS</comment>
<comment xml:lang="ro">Fișier portabil de date SPSS</comment>
- <comment xml:lang="ru">файл переноÑимых данных SPSS</comment>
+ <comment xml:lang="ru">Файл переноÑимых данных SPSS</comment>
<comment xml:lang="sk">Súbor prenosných dát SPSS</comment>
<comment xml:lang="sl">Prenosna podatkovna datoteka SPSS</comment>
<comment xml:lang="sr">СПСС датотека преноÑних података</comment>
@@ -6730,6 +6895,7 @@
<comment xml:lang="en_GB">SPSS Data File</comment>
<comment xml:lang="es">archivo de datos SPSS</comment>
<comment xml:lang="eu">SPSS datuen fitxategia</comment>
+ <comment xml:lang="fi">SPSS-datatiedosto</comment>
<comment xml:lang="fo">SPSS dátufíla</comment>
<comment xml:lang="fr">fichier de données SPSS</comment>
<comment xml:lang="ga">comhad sonraí SPSS</comment>
@@ -6751,7 +6917,7 @@
<comment xml:lang="pt">ficheiro de dados SPSS</comment>
<comment xml:lang="pt_BR">Arquivo de dados SPSS</comment>
<comment xml:lang="ro">Fișier date SPSS</comment>
- <comment xml:lang="ru">файл данных SPSS</comment>
+ <comment xml:lang="ru">Файл данных SPSS</comment>
<comment xml:lang="sk">Dátový súbor SPSS</comment>
<comment xml:lang="sl">Podatkovna datoteka SPSS</comment>
<comment xml:lang="sr">СПСС датотека података</comment>
@@ -6788,7 +6954,7 @@
<comment xml:lang="ga">leabharmharcanna XBEL</comment>
<comment xml:lang="gl">Marcadores XBEL</comment>
<comment xml:lang="he">סימניית XBEL</comment>
- <comment xml:lang="hr">XBEL knjižne oznake</comment>
+ <comment xml:lang="hr">XBEL zabilješka</comment>
<comment xml:lang="hu">XBEL-könyvjelzők</comment>
<comment xml:lang="ia">Marcapaginas XBEL</comment>
<comment xml:lang="id">Bookmark XBEL</comment>
@@ -6807,7 +6973,7 @@
<comment xml:lang="pt">marcadores XBEL</comment>
<comment xml:lang="pt_BR">Marcadores do XBEL</comment>
<comment xml:lang="ro">Semne de carte XBEL</comment>
- <comment xml:lang="ru">закладки XBEL</comment>
+ <comment xml:lang="ru">Закладки XBEL</comment>
<comment xml:lang="sk">Záložky XBEL</comment>
<comment xml:lang="sl">Datoteka zaznamkov XBEL</comment>
<comment xml:lang="sq">Libërshënues XBEL</comment>
@@ -6830,6 +6996,7 @@
<mime-type type="application/x-7z-compressed">
<comment>7-zip archive</comment>
<comment xml:lang="ar">أرشي٠7-zip</comment>
+ <comment xml:lang="ast">Archivu 7-zip</comment>
<comment xml:lang="be@latin">ArchiÅ­ 7-zip</comment>
<comment xml:lang="bg">Ðрхив — 7-zip</comment>
<comment xml:lang="ca">arxiu 7-zip</comment>
@@ -6866,7 +7033,7 @@
<comment xml:lang="pt">arquivo 7-zip</comment>
<comment xml:lang="pt_BR">Pacote 7-Zip</comment>
<comment xml:lang="ro">Arhivă 7-zip</comment>
- <comment xml:lang="ru">архив 7-zip</comment>
+ <comment xml:lang="ru">Ðрхив 7-zip</comment>
<comment xml:lang="sk">Archív 7-zip</comment>
<comment xml:lang="sl">Datoteka arhiva 7-zip</comment>
<comment xml:lang="sq">Arkiv 7-zip</comment>
@@ -6886,6 +7053,7 @@
<mime-type type="application/x-abiword">
<comment>AbiWord document</comment>
<comment xml:lang="ar">مستند آبي وورد</comment>
+ <comment xml:lang="ast">Documentu d'AbiWord</comment>
<comment xml:lang="be@latin">Dakument AbiWord</comment>
<comment xml:lang="bg">Документ — AbiWord</comment>
<comment xml:lang="ca">document AbiWord</comment>
@@ -6923,7 +7091,7 @@
<comment xml:lang="pt">documento AbiWord</comment>
<comment xml:lang="pt_BR">Documento do AbiWord</comment>
<comment xml:lang="ro">Document AbiWord</comment>
- <comment xml:lang="ru">документ AbiWord</comment>
+ <comment xml:lang="ru">Документ AbiWord</comment>
<comment xml:lang="sk">Dokument AbiWord</comment>
<comment xml:lang="sl">Dokument AbiWord</comment>
<comment xml:lang="sq">Dokument AbiWord</comment>
@@ -6961,7 +7129,7 @@
<comment xml:lang="eu">CD irudiaren CUE orria</comment>
<comment xml:lang="fi">CD-vedos cuesheet</comment>
<comment xml:lang="fr">index de pistes de CD</comment>
- <comment xml:lang="ga">bileog chiúáil íomhá CD</comment>
+ <comment xml:lang="ga">bileog chiúála íomhá CD</comment>
<comment xml:lang="gl">cue sheet dunha imaxe de CD</comment>
<comment xml:lang="he">גליון × ×ª×•× ×™× ×œ×ª×ž×•× ×ª דיסק</comment>
<comment xml:lang="hr">CD slika s meta podacima</comment>
@@ -6982,11 +7150,11 @@
<comment xml:lang="pt">índice de CD de imagem</comment>
<comment xml:lang="pt_BR">Ãndice de Imagem de CD</comment>
<comment xml:lang="ro">Imagine CD cuesheet</comment>
- <comment xml:lang="ru">таблица ÑÐ¾Ð´ÐµÑ€Ð¶Ð°Ð½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·Ð° CD</comment>
+ <comment xml:lang="ru">Таблица ÑÐ¾Ð´ÐµÑ€Ð¶Ð°Ð½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·Ð° CD</comment>
<comment xml:lang="sk">Rozvrhnutie stôp obrazu CD</comment>
<comment xml:lang="sl">Datoteka razpredelnice odtisa CD cue</comment>
<comment xml:lang="sq">Cuesheet imazhi CD</comment>
- <comment xml:lang="sr">редоÑлед Ñлика ЦД-а</comment>
+ <comment xml:lang="sr">Кју лиÑÑ‚ ЦД одраза</comment>
<comment xml:lang="sv">Indexblad för cd-avbild</comment>
<comment xml:lang="tr">CD görüntüsü belgesi</comment>
<comment xml:lang="uk">Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ CUE образу CD</comment>
@@ -7000,6 +7168,7 @@
<mime-type type="application/x-amipro">
<comment>Lotus AmiPro document</comment>
<comment xml:lang="ar">مستند Lotus AmiPro</comment>
+ <comment xml:lang="ast">Documentu de Lotus AmiPro</comment>
<comment xml:lang="az">Lotus AmiPro sənədi</comment>
<comment xml:lang="be@latin">Dakument Lotus AmiPro</comment>
<comment xml:lang="bg">Документ — Lotus AmiPro</comment>
@@ -7038,7 +7207,7 @@
<comment xml:lang="pt">documento Lotus AmiPro</comment>
<comment xml:lang="pt_BR">Documento do Lotus AmiPro</comment>
<comment xml:lang="ro">Document Lotus AmiPro</comment>
- <comment xml:lang="ru">документ Lotus AmiPro</comment>
+ <comment xml:lang="ru">Документ Lotus AmiPro</comment>
<comment xml:lang="sk">Dokument Lotus AmiPro</comment>
<comment xml:lang="sl">Dokument Lotus AmiPro</comment>
<comment xml:lang="sq">Dokument Lotus AmiPro</comment>
@@ -7055,6 +7224,7 @@
<mime-type type="application/x-aportisdoc">
<comment>AportisDoc document</comment>
<comment xml:lang="ar">مستند AportisDoc</comment>
+ <comment xml:lang="ast">Documentu d'AportisDoc</comment>
<comment xml:lang="bg">Документ — AportisDoc</comment>
<comment xml:lang="ca">document AportisDoc</comment>
<comment xml:lang="cs">dokument AportisDoc</comment>
@@ -7088,7 +7258,7 @@
<comment xml:lang="pt">documento AportisDoc</comment>
<comment xml:lang="pt_BR">Documento do AportisDoc</comment>
<comment xml:lang="ro">Document AportisDoc</comment>
- <comment xml:lang="ru">документ AportisDoc</comment>
+ <comment xml:lang="ru">Документ AportisDoc</comment>
<comment xml:lang="sk">Dokument AportisDoc</comment>
<comment xml:lang="sl">Dokument AportisDoc</comment>
<comment xml:lang="sr">ÐÐ¿Ð¾Ñ€Ñ‚Ð¸Ñ Ð”Ð¾Ðº документ</comment>
@@ -7147,7 +7317,7 @@
<comment xml:lang="pt">folha de cálculo Applix Spreadsheets</comment>
<comment xml:lang="pt_BR">Planilha do Applix Spreadsheets</comment>
<comment xml:lang="ro">Foaie de calcul Applix</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Applix Spreadsheets</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Applix Spreadsheets</comment>
<comment xml:lang="sk">Zošit Applix Spreadsheets</comment>
<comment xml:lang="sl">Razpredelnica Applix Spreadsheets</comment>
<comment xml:lang="sq">Fletë llogaritjesh Applix Spreadsheets</comment>
@@ -7156,7 +7326,7 @@
<comment xml:lang="tr">Applix Spreadsheets çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Applix Spreadsheets</comment>
<comment xml:lang="vi">Bảng tính Applix Spreadsheets</comment>
- <comment xml:lang="zh_CN">Applix Spreadsheets 工作簿</comment>
+ <comment xml:lang="zh_CN">Applix Spreadsheets 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">Applix Spreadsheets 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="50">
@@ -7170,6 +7340,7 @@
<mime-type type="application/x-applix-word">
<comment>Applix Words document</comment>
<comment xml:lang="ar">مستند كلمات Applix</comment>
+ <comment xml:lang="ast">Documentu d'Applix Words</comment>
<comment xml:lang="az">Applix Words sənədi</comment>
<comment xml:lang="be@latin">Dakument Applix Words</comment>
<comment xml:lang="bg">Документ — Applix Words</comment>
@@ -7209,7 +7380,7 @@
<comment xml:lang="pt">documento Applix Words</comment>
<comment xml:lang="pt_BR">Documento do Applix Words</comment>
<comment xml:lang="ro">Document Applix Words</comment>
- <comment xml:lang="ru">документ Applix Words</comment>
+ <comment xml:lang="ru">Документ Applix Words</comment>
<comment xml:lang="sk">Dokument Applix Words</comment>
<comment xml:lang="sl">Dokument Applix Words</comment>
<comment xml:lang="sq">Dokument Applix Words</comment>
@@ -7267,7 +7438,7 @@
<comment xml:lang="pt">arquivo ARC</comment>
<comment xml:lang="pt_BR">Pacote ARC</comment>
<comment xml:lang="ro">Arhivă ARC</comment>
- <comment xml:lang="ru">архив ARC</comment>
+ <comment xml:lang="ru">Ðрхив ARC</comment>
<comment xml:lang="sk">Archív ARC</comment>
<comment xml:lang="sl">Datoteka arhiva ARC</comment>
<comment xml:lang="sq">Arkiv ARC</comment>
@@ -7328,7 +7499,7 @@
<comment xml:lang="pt">arquivo AR</comment>
<comment xml:lang="pt_BR">Pacote AR</comment>
<comment xml:lang="ro">Arhivă AR</comment>
- <comment xml:lang="ru">архив AR</comment>
+ <comment xml:lang="ru">Ðрхив AR</comment>
<comment xml:lang="sk">Archív AR</comment>
<comment xml:lang="sl">Datoteka arhiva AR</comment>
<comment xml:lang="sq">Arkiv AR</comment>
@@ -7389,7 +7560,7 @@
<comment xml:lang="pt">arquivo ARJ</comment>
<comment xml:lang="pt_BR">Pacote ARJ</comment>
<comment xml:lang="ro">Arhivă ARJ</comment>
- <comment xml:lang="ru">архив ARJ</comment>
+ <comment xml:lang="ru">Ðрхив ARJ</comment>
<comment xml:lang="sk">Archív ARJ</comment>
<comment xml:lang="sl">Datoteka arhiva ARJ</comment>
<comment xml:lang="sq">Arkiv ARJ</comment>
@@ -7411,6 +7582,7 @@
<mime-type type="application/x-asp">
<comment>ASP page</comment>
<comment xml:lang="ar">صÙحة ASP</comment>
+ <comment xml:lang="ast">Páxina ASP</comment>
<comment xml:lang="be@latin">Staronka ASP</comment>
<comment xml:lang="bg">Страница — ASP</comment>
<comment xml:lang="ca">pàgina ASP</comment>
@@ -7447,7 +7619,7 @@
<comment xml:lang="pt">página ASP</comment>
<comment xml:lang="pt_BR">Página ASP</comment>
<comment xml:lang="ro">Pagină ASP</comment>
- <comment xml:lang="ru">Ñтраница ASP</comment>
+ <comment xml:lang="ru">Страница ASP</comment>
<comment xml:lang="sk">Stránka ASP</comment>
<comment xml:lang="sl">Datoteka spletne strani ASP</comment>
<comment xml:lang="sq">Faqe ASP</comment>
@@ -7467,6 +7639,7 @@
<mime-type type="application/x-awk">
<comment>AWK script</comment>
<comment xml:lang="ar">سكربت AWK</comment>
+ <comment xml:lang="ast">Script AWK</comment>
<comment xml:lang="az">AWK skripti</comment>
<comment xml:lang="be@latin">Skrypt AWK</comment>
<comment xml:lang="bg">Скрипт — AWK</comment>
@@ -7506,7 +7679,7 @@
<comment xml:lang="pt">script AWK</comment>
<comment xml:lang="pt_BR">Script AWK</comment>
<comment xml:lang="ro">Script AWK</comment>
- <comment xml:lang="ru">Ñценарий AWK</comment>
+ <comment xml:lang="ru">Сценарий AWK</comment>
<comment xml:lang="sk">Skript AWK</comment>
<comment xml:lang="sl">Skriptna datoteka AWK</comment>
<comment xml:lang="sq">Script AWK</comment>
@@ -7537,6 +7710,7 @@
<mime-type type="application/x-bcpio">
<comment>BCPIO document</comment>
<comment xml:lang="ar">مستند BCPIO</comment>
+ <comment xml:lang="ast">Documentu BCPIO</comment>
<comment xml:lang="az">BCPIO sənədi</comment>
<comment xml:lang="be@latin">Dakument BCPIO</comment>
<comment xml:lang="bg">Документ — BCPIO</comment>
@@ -7576,7 +7750,7 @@
<comment xml:lang="pt">documento BCPIO</comment>
<comment xml:lang="pt_BR">Documento BCPIO</comment>
<comment xml:lang="ro">Document BCPIO</comment>
- <comment xml:lang="ru">документ BCPIO</comment>
+ <comment xml:lang="ru">Документ BCPIO</comment>
<comment xml:lang="sk">Dokument BCPIO</comment>
<comment xml:lang="sl">Dokument BCPIO</comment>
<comment xml:lang="sq">Dokument BCPIO</comment>
@@ -7633,7 +7807,7 @@
<comment xml:lang="pt">ficheiro de semente BitTorrent</comment>
<comment xml:lang="pt_BR">Arquivo semente BitTorrent</comment>
<comment xml:lang="ro">Fișier sursă-completă BitTorrent</comment>
- <comment xml:lang="ru">файл иÑточника BitTorrent</comment>
+ <comment xml:lang="ru">Файл иÑточника BitTorrent</comment>
<comment xml:lang="sk">Súbor BitTorrent</comment>
<comment xml:lang="sl">Datoteka sejanja BitTorrent</comment>
<comment xml:lang="sq">File bazë BitTorrent</comment>
@@ -7652,6 +7826,7 @@
<mime-type type="application/x-blender">
<comment>Blender scene</comment>
<comment xml:lang="ar">مشهد بلندر</comment>
+ <comment xml:lang="ast">Escena de Blender</comment>
<comment xml:lang="be@latin">Scena Blender</comment>
<comment xml:lang="bg">Сцена — Blender</comment>
<comment xml:lang="ca">escena de Blender</comment>
@@ -7689,7 +7864,7 @@
<comment xml:lang="pt">cenário Blender</comment>
<comment xml:lang="pt_BR">Cena do Blender</comment>
<comment xml:lang="ro">Scenă Blender</comment>
- <comment xml:lang="ru">Ñцена Blender</comment>
+ <comment xml:lang="ru">Сцена Blender</comment>
<comment xml:lang="sk">Scéna Blender</comment>
<comment xml:lang="sl">Datoteka scene Blender</comment>
<comment xml:lang="sq">Skenë Blender</comment>
@@ -7711,6 +7886,7 @@
<mime-type type="application/x-bzdvi">
<comment>TeX DVI document (bzip-compressed)</comment>
<comment xml:lang="ar">مستند TeX DVI (مضغوط-bzip)</comment>
+ <comment xml:lang="ast">Documentu Tex DVI (comprimíu en bzip)</comment>
<comment xml:lang="be@latin">Dakument TeX DVI (bzip-skampresavany)</comment>
<comment xml:lang="bg">Документ — TeX DVI, компреÑиран Ñ bzip</comment>
<comment xml:lang="ca">document de TeX DVI (amb compressió bzip)</comment>
@@ -7727,7 +7903,7 @@
<comment xml:lang="ga">cáipéis DVI TeX (comhbhrúite le bzip)</comment>
<comment xml:lang="gl">documento DVI de TeX (comprimido con bzip)</comment>
<comment xml:lang="he">מסמך מסוג TeX DVI (מכווץ ע״י bzip)</comment>
- <comment xml:lang="hr">TeX DVI dokument (komprimiran bzip-om)</comment>
+ <comment xml:lang="hr">TeX DVI dokument (bzip sažeto)</comment>
<comment xml:lang="hu">TeX DVI dokumentum (bzip-pel tömörítve)</comment>
<comment xml:lang="ia">Documento TeX DVI (comprimite con bzip)</comment>
<comment xml:lang="id">Dokumen TeX DVI (terkompresi bzip)</comment>
@@ -7745,7 +7921,7 @@
<comment xml:lang="pt">documento TeX DVI (compressão bzip)</comment>
<comment xml:lang="pt_BR">Documento DVI TeX (compactado com bzip)</comment>
<comment xml:lang="ro">Document TeX DVI (comprimat bzip)</comment>
- <comment xml:lang="ru">документ TeX DVI (Ñжатый bzip)</comment>
+ <comment xml:lang="ru">Документ TeX DVI (Ñжатый bzip)</comment>
<comment xml:lang="sk">Dokument TeX DVI (komprimovaný pomocou bzip)</comment>
<comment xml:lang="sl">Dokument TeX DVI (stisnjen z bzip)</comment>
<comment xml:lang="sq">Dokument Tex DVI (i kompresuar me bzip)</comment>
@@ -7754,7 +7930,7 @@
<comment xml:lang="tr">TeX DVI belgesi (bzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">документ TeX DVI (ÑтиÑнений bzip)</comment>
<comment xml:lang="vi">Tài liệu DVI TeX (đã nén bzip)</comment>
- <comment xml:lang="zh_CN">TeX DVI 文档(gzip 压缩)</comment>
+ <comment xml:lang="zh_CN">TeX DVI 文档(gzip 压缩)</comment>
<comment xml:lang="zh_TW">TeX DVI 文件 (bzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/x-bzip"/>
<generic-icon name="x-office-document"/>
@@ -7763,6 +7939,7 @@
<mime-type type="application/x-bzip">
<comment>Bzip archive</comment>
<comment xml:lang="ar">أرشي٠Bzip</comment>
+ <comment xml:lang="ast">Archivu Bzip</comment>
<comment xml:lang="be@latin">ArchiÅ­ bzip</comment>
<comment xml:lang="bg">Ðрхив — bzip</comment>
<comment xml:lang="ca">arxiu bzip</comment>
@@ -7799,7 +7976,7 @@
<comment xml:lang="pt">arquivo Bzip</comment>
<comment xml:lang="pt_BR">Pacote Bzip</comment>
<comment xml:lang="ro">Arhivă Bzip</comment>
- <comment xml:lang="ru">архив BZIP</comment>
+ <comment xml:lang="ru">Ðрхив BZIP</comment>
<comment xml:lang="sk">Archív bzip</comment>
<comment xml:lang="sl">Datoteka arhiva Bzip</comment>
<comment xml:lang="sq">Arkiv bzip</comment>
@@ -7808,7 +7985,7 @@
<comment xml:lang="tr">Bzip arÅŸivi</comment>
<comment xml:lang="uk">архів bzip</comment>
<comment xml:lang="vi">Kho nén bzip</comment>
- <comment xml:lang="zh_CN">bzip 归档文件</comment>
+ <comment xml:lang="zh_CN">Bzip 归档文件</comment>
<comment xml:lang="zh_TW">Bzip å°å­˜æª”</comment>
<generic-icon name="package-x-generic"/>
<magic priority="50">
@@ -7821,6 +7998,7 @@
<mime-type type="application/x-bzip-compressed-tar">
<comment>Tar archive (bzip-compressed)</comment>
<comment xml:lang="ar">أرشي٠Tar (مضغوط-bzip)</comment>
+ <comment xml:lang="ast">Archivu Tar (comprimíu en bzip)</comment>
<comment xml:lang="be@latin">ArchiÅ­ tar (bzip-skampresavany)</comment>
<comment xml:lang="bg">Ðрхив — tar, компреÑиран Ñ bzip</comment>
<comment xml:lang="ca">arxiu tar (amb compressió bzip)</comment>
@@ -7837,7 +8015,7 @@
<comment xml:lang="ga">cartlann Tar (comhbhrúite le bzip)</comment>
<comment xml:lang="gl">arquivo Tar (comprimido con bzip)</comment>
<comment xml:lang="he">×רכיון Tar (מכווץ ×¢×´×™ bzip)</comment>
- <comment xml:lang="hr">Tar arhiva (komprimirana bzip-om)</comment>
+ <comment xml:lang="hr">Tar arhiva (bzip sažeto)</comment>
<comment xml:lang="hu">Tar archívum (bzip-pel tömörítve)</comment>
<comment xml:lang="ia">Archivo Tar (comprimite con bzip)</comment>
<comment xml:lang="id">Arsip Tar (terkompresi bzip)</comment>
@@ -7855,7 +8033,7 @@
<comment xml:lang="pt">arquivo Tar (compressão bzip)</comment>
<comment xml:lang="pt_BR">Pacote Tar (compactado com bzip)</comment>
<comment xml:lang="ro">Arhivă Tar (comprimată bzip)</comment>
- <comment xml:lang="ru">архив TAR (Ñжатый BZIP)</comment>
+ <comment xml:lang="ru">Ðрхив TAR (Ñжатый bzip)</comment>
<comment xml:lang="sk">Archív tar (komprimovaný pomocou bzip)</comment>
<comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z bzip)</comment>
<comment xml:lang="sq">Arkiv tar (i kompresuar me bzip)</comment>
@@ -7864,7 +8042,7 @@
<comment xml:lang="tr">Tar arşivi (bzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">архів tar (ÑтиÑнений bzip)</comment>
<comment xml:lang="vi">Kho nén tar (đã nén bzip)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件(bzip 压缩)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(bzip 压缩)</comment>
<comment xml:lang="zh_TW">Tar å°å­˜æª” (bzip æ ¼å¼å£“縮)</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="application/x-bzip"/>
@@ -7877,6 +8055,7 @@
<mime-type type="application/x-bzpdf">
<comment>PDF document (bzip-compressed)</comment>
<comment xml:lang="ar">مستند PDF (مضغوط-bzip)</comment>
+ <comment xml:lang="ast">Documentu PDF (comprimíu en bzip)</comment>
<comment xml:lang="be@latin">Dakument PDF (bzip-skampresavany)</comment>
<comment xml:lang="bg">Документ — PDF, компреÑиран Ñ bzip</comment>
<comment xml:lang="ca">document PDF (amb compressió bzip)</comment>
@@ -7911,7 +8090,7 @@
<comment xml:lang="pt">documento PDF (compressão bzip)</comment>
<comment xml:lang="pt_BR">Documento PDF (compactado com bzip)</comment>
<comment xml:lang="ro">Document PDF (comprimat bzip)</comment>
- <comment xml:lang="ru">документ PDF (Ñжатый bzip)</comment>
+ <comment xml:lang="ru">Документ PDF (Ñжатый bzip)</comment>
<comment xml:lang="sk">Dokument PDF (komprimovaný pomocou bzip)</comment>
<comment xml:lang="sl">Dokument PDF (stisnjen z bzip)</comment>
<comment xml:lang="sq">Dokument PDF (i kompresuar me bzip)</comment>
@@ -7920,7 +8099,7 @@
<comment xml:lang="tr">PDF belgesi (bzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">документ PDF (ÑтиÑнений bzip)</comment>
<comment xml:lang="vi">Tài liệu PDF (đã nén bzip)</comment>
- <comment xml:lang="zh_CN">PDF 文档(bzip 压缩)</comment>
+ <comment xml:lang="zh_CN">PDF 文档(bzip 压缩)</comment>
<comment xml:lang="zh_TW">PDF 文件 (bzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/x-bzip"/>
<generic-icon name="x-office-document"/>
@@ -7929,6 +8108,7 @@
<mime-type type="application/x-bzpostscript">
<comment>PostScript document (bzip-compressed)</comment>
<comment xml:lang="ar">مستند PostScript (مضغوط-bzip)</comment>
+ <comment xml:lang="ast">Documentu PostScript (comprimíu en bzip)</comment>
<comment xml:lang="be@latin">Dakument PostScript (bzip-skampresavany)</comment>
<comment xml:lang="bg">Документ — PostScript, компреÑиран Ñ bzip</comment>
<comment xml:lang="ca">document PostScript (amb compressió bzip)</comment>
@@ -7963,7 +8143,7 @@
<comment xml:lang="pt">documento PostScript (compressão bzip)</comment>
<comment xml:lang="pt_BR">Documento PostScript (compactado com bzip)</comment>
<comment xml:lang="ro">Document PostScript (comprimat bzip)</comment>
- <comment xml:lang="ru">документ PostScript (Ñжатый bzip)</comment>
+ <comment xml:lang="ru">Документ PostScript (Ñжатый bzip)</comment>
<comment xml:lang="sk">Dokument PostScript (komprimovaný pomocou bzip)</comment>
<comment xml:lang="sl">Dokument PostScript (stisnjen z bzip)</comment>
<comment xml:lang="sq">Dokument PostScript (i kompresuar me bzip)</comment>
@@ -7972,13 +8152,13 @@
<comment xml:lang="tr">PostScript belgesi (bzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">документ PostScript (ÑтиÑнене bzip)</comment>
<comment xml:lang="vi">Tài liệu PostScript (đã nén bzip)</comment>
- <comment xml:lang="zh_CN">PostScript 文档(bzip 压缩)</comment>
+ <comment xml:lang="zh_CN">PostScript 文档(bzip 压缩)</comment>
<comment xml:lang="zh_TW">PostScript 文件 (bzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/x-bzip"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.ps.bz2"/>
</mime-type>
- <mime-type type="application/x-cbr">
+ <mime-type type="application/vnd.comicbook-rar">
<comment>comic book archive</comment>
<comment xml:lang="ar">أرشي٠comic book</comment>
<comment xml:lang="be@latin">archiÅ­ komiksaÅ­</comment>
@@ -8015,7 +8195,7 @@
<comment xml:lang="pt">arquivo de banda desenhada</comment>
<comment xml:lang="pt_BR">Pacote de histórias em quadrinhos</comment>
<comment xml:lang="ro">arhivă benzi desenate</comment>
- <comment xml:lang="ru">архив комикÑов</comment>
+ <comment xml:lang="ru">Ðрхив комикÑов</comment>
<comment xml:lang="sk">Archív knihy komiksov</comment>
<comment xml:lang="sl">Datoteka arhiva stripov</comment>
<comment xml:lang="sq">Arkiv comic book</comment>
@@ -8024,11 +8204,12 @@
<comment xml:lang="tr">çizgi roman arşivi</comment>
<comment xml:lang="uk">архів комікÑів</comment>
<comment xml:lang="vi">Kho nén sách tranh chuyện vui</comment>
- <comment xml:lang="zh_CN">Comic Book 归档文件</comment>
+ <comment xml:lang="zh_CN">漫画书归档文件</comment>
<comment xml:lang="zh_TW">漫畫書å°å­˜æª”</comment>
<sub-class-of type="application/vnd.rar"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.cbr"/>
+ <alias type="application/x-cbr"/>
</mime-type>
<mime-type type="application/x-cb7">
<comment>comic book archive</comment>
@@ -8067,7 +8248,7 @@
<comment xml:lang="pt">arquivo de banda desenhada</comment>
<comment xml:lang="pt_BR">Pacote de histórias em quadrinhos</comment>
<comment xml:lang="ro">arhivă benzi desenate</comment>
- <comment xml:lang="ru">архив комикÑов</comment>
+ <comment xml:lang="ru">Ðрхив комикÑов</comment>
<comment xml:lang="sk">Archív knihy komiksov</comment>
<comment xml:lang="sl">Datoteka arhiva stripov</comment>
<comment xml:lang="sq">Arkiv comic book</comment>
@@ -8076,7 +8257,7 @@
<comment xml:lang="tr">çizgi roman arşivi</comment>
<comment xml:lang="uk">архів комікÑів</comment>
<comment xml:lang="vi">Kho nén sách tranh chuyện vui</comment>
- <comment xml:lang="zh_CN">Comic Book 归档文件</comment>
+ <comment xml:lang="zh_CN">漫画书归档文件</comment>
<comment xml:lang="zh_TW">漫畫書å°å­˜æª”</comment>
<sub-class-of type="application/x-7z-compressed"/>
<generic-icon name="x-office-document"/>
@@ -8119,7 +8300,7 @@
<comment xml:lang="pt">arquivo de banda desenhada</comment>
<comment xml:lang="pt_BR">Pacote de histórias em quadrinhos</comment>
<comment xml:lang="ro">arhivă benzi desenate</comment>
- <comment xml:lang="ru">архив комикÑов</comment>
+ <comment xml:lang="ru">Ðрхив комикÑов</comment>
<comment xml:lang="sk">Archív knihy komiksov</comment>
<comment xml:lang="sl">Datoteka arhiva stripov</comment>
<comment xml:lang="sq">Arkiv comic book</comment>
@@ -8128,7 +8309,7 @@
<comment xml:lang="tr">çizgi roman arşivi</comment>
<comment xml:lang="uk">архів комікÑів</comment>
<comment xml:lang="vi">Kho nén sách tranh chuyện vui</comment>
- <comment xml:lang="zh_CN">Comic Book 归档文件</comment>
+ <comment xml:lang="zh_CN">漫画书归档文件</comment>
<comment xml:lang="zh_TW">漫畫書å°å­˜æª”</comment>
<sub-class-of type="application/x-tar"/>
<generic-icon name="x-office-document"/>
@@ -8171,7 +8352,7 @@
<comment xml:lang="pt">arquivo de banda desenhada</comment>
<comment xml:lang="pt_BR">Pacote de histórias em quadrinhos</comment>
<comment xml:lang="ro">arhivă benzi desenate</comment>
- <comment xml:lang="ru">архив комикÑов</comment>
+ <comment xml:lang="ru">Ðрхив комикÑов</comment>
<comment xml:lang="sk">Archív knihy komiksov</comment>
<comment xml:lang="sl">Datoteka arhiva stripov</comment>
<comment xml:lang="sq">Arkiv comic book</comment>
@@ -8180,7 +8361,7 @@
<comment xml:lang="tr">çizgi roman arşivi</comment>
<comment xml:lang="uk">архів комікÑів</comment>
<comment xml:lang="vi">Kho nén sách tranh chuyện vui</comment>
- <comment xml:lang="zh_CN">Comic Book 归档文件</comment>
+ <comment xml:lang="zh_CN">漫画书归档文件</comment>
<comment xml:lang="zh_TW">漫畫書å°å­˜æª”</comment>
<sub-class-of type="application/zip"/>
<generic-icon name="x-office-document"/>
@@ -8222,7 +8403,7 @@
<comment xml:lang="pt">arquivo Lrzip</comment>
<comment xml:lang="pt_BR">Pacote Lrzip</comment>
<comment xml:lang="ro">Arhivă Lrzip</comment>
- <comment xml:lang="ru">архив LRZIP</comment>
+ <comment xml:lang="ru">Ðрхив LRZIP</comment>
<comment xml:lang="sk">Archív Lrzip</comment>
<comment xml:lang="sl">Datoteka arhiva Lrzip</comment>
<comment xml:lang="sr">Лрзип архива</comment>
@@ -8255,7 +8436,7 @@
<comment xml:lang="ga">cartlann Tar (comhbhrúite le lrzip)</comment>
<comment xml:lang="gl">arquivo Tar (comprimido con lrzip)</comment>
<comment xml:lang="he">×רכיון Tar (מכווץ ×¢×´×™ lrzip)</comment>
- <comment xml:lang="hr">Tar arhiva (komprimirana lrzip-om)</comment>
+ <comment xml:lang="hr">Tar arhiva (lrzip sažeta)</comment>
<comment xml:lang="hu">Tar archívum (lrzip-pel tömörítve)</comment>
<comment xml:lang="ia">Archivo Tar (comprimite con lrzip)</comment>
<comment xml:lang="id">Arsip Tar (terkompresi lrzip)</comment>
@@ -8271,14 +8452,14 @@
<comment xml:lang="pt">arquivo Tar (compressão Lrzip)</comment>
<comment xml:lang="pt_BR">Pacote Tar (compactado com lrzip)</comment>
<comment xml:lang="ro">Arhivă Tar (comprimată lrzip)</comment>
- <comment xml:lang="ru">архив TAR (Ñжатый LRZIP)</comment>
+ <comment xml:lang="ru">Ðрхив TAR (Ñжатый lrzip)</comment>
<comment xml:lang="sk">Archív tar (komprimovaný pomocou lrzip)</comment>
<comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z lrzip)</comment>
<comment xml:lang="sr">Тар архива (запакована лрзипом)</comment>
<comment xml:lang="sv">Tar-arkiv (lrzip-komprimerat)</comment>
<comment xml:lang="tr">Tar arşivi (lrzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">архів tar (ÑтиÑнений lrzip)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件 (lrzip 压缩)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(lrzip 压缩)</comment>
<comment xml:lang="zh_TW">Tar å°å­˜æª” (lrzip æ ¼å¼å£“縮)</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="application/x-lrzip"/>
@@ -8287,6 +8468,7 @@
</mime-type>
<mime-type type="application/x-apple-diskimage">
<comment>Apple disk image</comment>
+ <comment xml:lang="ast">Imaxe de discu d'Apple</comment>
<comment xml:lang="bg">ДиÑк — Apple</comment>
<comment xml:lang="ca">imatge de disc d'Apple</comment>
<comment xml:lang="cs">obraz disku Apple</comment>
@@ -8298,9 +8480,10 @@
<comment xml:lang="eu">Apple disko irudia</comment>
<comment xml:lang="fi">Apple-levytiedosto</comment>
<comment xml:lang="fr">image disque Apple</comment>
+ <comment xml:lang="ga">íomhá diosca Apple</comment>
<comment xml:lang="gl">imaxe de disco de Appl</comment>
<comment xml:lang="he">תמונת כונן Apple</comment>
- <comment xml:lang="hr">Apple snimka diska</comment>
+ <comment xml:lang="hr">Apple slika diska</comment>
<comment xml:lang="hu">Apple lemezkép</comment>
<comment xml:lang="ia">Imagine de disco Apple</comment>
<comment xml:lang="id">Image disk Apple</comment>
@@ -8315,95 +8498,107 @@
<comment xml:lang="pl">Obraz dysku Apple</comment>
<comment xml:lang="pt">imagem de disco Apple</comment>
<comment xml:lang="pt_BR">Imagem de disco Apple</comment>
- <comment xml:lang="ru">образ диÑка Apple Mac OS X</comment>
+ <comment xml:lang="ru">Образ диÑка Apple Mac OS X</comment>
<comment xml:lang="sk">Obraz disku Apple</comment>
<comment xml:lang="sl">Odtis diska Apple</comment>
- <comment xml:lang="sr">Еплова Ñлика диÑка</comment>
+ <comment xml:lang="sr">Еплов одраз диÑка</comment>
<comment xml:lang="sv">Apple-diskavbild</comment>
<comment xml:lang="tr">Apple disk görüntüsü</comment>
<comment xml:lang="uk">образ диÑка Apple</comment>
- <comment xml:lang="zh_CN">Apple ç£ç›˜é•œåƒ</comment>
- <comment xml:lang="zh_TW">Apple ç£ç¢Ÿæ˜ åƒ</comment>
+ <comment xml:lang="zh_CN">Apple ç£ç›˜æ˜ åƒ</comment>
+ <comment xml:lang="zh_TW">Apple ç£ç¢Ÿæ˜ åƒæª”</comment>
<glob pattern="*.dmg"/>
</mime-type>
<mime-type type="application/x-raw-disk-image">
- <comment>Raw disk image</comment>
- <comment xml:lang="ca">imatge de disc RAW</comment>
- <comment xml:lang="cs">surový obraz disku</comment>
- <comment xml:lang="da">RÃ¥ diskaftryk</comment>
- <comment xml:lang="de">Rohes Datenträgerabbild</comment>
- <comment xml:lang="el">ΑνεπεξέÏγαστη εικόνα δίσκου</comment>
- <comment xml:lang="en_GB">Raw disk image</comment>
- <comment xml:lang="es">imagen de disco en bruto</comment>
- <comment xml:lang="eu">Disko gordinaren irudia</comment>
- <comment xml:lang="fi">Raaka levytiedosto</comment>
- <comment xml:lang="fr">image disque Raw</comment>
- <comment xml:lang="gl">Imaxe de disco en bruto</comment>
- <comment xml:lang="he">דמות גולמית של כונן</comment>
- <comment xml:lang="hr">Osnovna slika diska</comment>
- <comment xml:lang="hu">Nyers lemezkép</comment>
- <comment xml:lang="ia">Imagine de disco crude</comment>
- <comment xml:lang="id">Image disk mentah</comment>
- <comment xml:lang="it">Immagine disco raw</comment>
- <comment xml:lang="kk">Шикі диÑк бейнеÑÑ–</comment>
- <comment xml:lang="ko">RAW ë””ìŠ¤í¬ ì´ë¯¸ì§€</comment>
- <comment xml:lang="oc">imatge disc Raw</comment>
- <comment xml:lang="pl">Surowy obraz dysku</comment>
- <comment xml:lang="pt">imagem de disco Raw</comment>
- <comment xml:lang="pt_BR">Imagem bruta de disco</comment>
- <comment xml:lang="ru">необработанный образ диÑка</comment>
- <comment xml:lang="sk">Obraz disku</comment>
- <comment xml:lang="sl">Surovi odtis diska</comment>
- <comment xml:lang="sr">Ñирова Ñлика диÑка</comment>
- <comment xml:lang="sv">RÃ¥ diskavbild</comment>
- <comment xml:lang="tr">İşlem görmemiş disk imajı</comment>
- <comment xml:lang="uk">проÑтий образ диÑка</comment>
- <comment xml:lang="zh_CN">原始ç£ç›˜é•œåƒ</comment>
- <comment xml:lang="zh_TW">原生ç£ç¢Ÿæ˜ åƒ</comment>
- <glob pattern="*.raw-disk-image"/>
- <glob pattern="*.img"/>
- </mime-type>
- <mime-type type="application/x-raw-disk-image-xz-compressed">
- <comment>Raw disk image (XZ-compressed)</comment>
- <comment xml:lang="ca">imatge de disc RAW (amb compressió XZ)</comment>
- <comment xml:lang="cs">surový obraz disku (komprimovaný pomocí XZ)</comment>
- <comment xml:lang="da">RÃ¥ diskaftryk (XZ-komprimeret)</comment>
- <comment xml:lang="de">Rohes Datenträgerabbild (XZ-komprimiert)</comment>
- <comment xml:lang="el">ΑνεπεξέÏγαστη εικόνα δίσκου (συμπιεσμένη XZ)</comment>
- <comment xml:lang="en_GB">Raw disk image (XZ-compressed)</comment>
- <comment xml:lang="es">imagen de disco en bruto (comprimida con XZ)</comment>
- <comment xml:lang="eu">Disko gordinaren irudia (XZ-rekin konprimitua)</comment>
- <comment xml:lang="fi">Raaka levytiedosto (XZ-pakattu)</comment>
- <comment xml:lang="fr">image disque Raw (compression XZ)</comment>
- <comment xml:lang="gl">Imaxe de disco en bruto (comprimida en XZ)</comment>
- <comment xml:lang="he">דמות גולמית של כונן (בדחיסת XZ)</comment>
- <comment xml:lang="hr">Osnovna slika diska (XZ sažeta)</comment>
- <comment xml:lang="hu">Nyers lemezkép (XZ-vel tömörítve)</comment>
- <comment xml:lang="ia">Imagine de disco crude (comprimite con XZ)</comment>
- <comment xml:lang="id">Image disk mentah (terkompresi XZ)</comment>
- <comment xml:lang="it">Immagine disco raw (compressa XZ)</comment>
- <comment xml:lang="kk">Шикі диÑк бейнеÑÑ– (XZ-мен Ñығылған)</comment>
- <comment xml:lang="ko">RAW ë””ìŠ¤í¬ ì´ë¯¸ì§€(XZ 압축)</comment>
- <comment xml:lang="oc">imatge disc Raw (compression XZ)</comment>
- <comment xml:lang="pl">Surowy obraz dysku (kompresja XZ)</comment>
- <comment xml:lang="pt">imagem de disco Raw (compressão XZ)</comment>
- <comment xml:lang="pt_BR">Imagem bruta de disco (compactada com XZ)</comment>
- <comment xml:lang="ru">необработанный образ диÑка (XZ-Ñжатый)</comment>
- <comment xml:lang="sk">Obraz disku (komprimovaný pomocou XZ)</comment>
- <comment xml:lang="sl">Surovi odtis diska (stisnjeno z XZ)</comment>
- <comment xml:lang="sr">Ñирова Ñлика диÑка (запакована ИкÑЗ-ом)</comment>
- <comment xml:lang="sv">RÃ¥ diskavbild (XZ-komprimerad)</comment>
- <comment xml:lang="tr">İşlem görmemiş disk imajı (XZ ile sıkıştırılmış)</comment>
- <comment xml:lang="uk">проÑтий образ диÑка (ÑтиÑнений XZ)</comment>
- <comment xml:lang="zh_CN">原始ç£ç›˜é•œåƒ(XZ 压缩)</comment>
- <comment xml:lang="zh_TW">原生ç£ç¢Ÿæ˜ åƒ (XZ æ ¼å¼å£“縮)</comment>
- <sub-class-of type="application/x-xz"/>
- <glob pattern="*.raw-disk-image.xz"/>
- <glob pattern="*.img.xz"/>
- </mime-type>
+ <comment>Raw disk image</comment>
+ <comment xml:lang="ast">Imaxe de discu en bruto</comment>
+ <comment xml:lang="ca">imatge de disc RAW</comment>
+ <comment xml:lang="cs">surový obraz disku</comment>
+ <comment xml:lang="da">RÃ¥ diskaftryk</comment>
+ <comment xml:lang="de">Rohes Datenträgerabbild</comment>
+ <comment xml:lang="el">ΑνεπεξέÏγαστη εικόνα δίσκου</comment>
+ <comment xml:lang="en_GB">Raw disk image</comment>
+ <comment xml:lang="es">imagen de disco en bruto</comment>
+ <comment xml:lang="eu">Disko gordinaren irudia</comment>
+ <comment xml:lang="fi">Raaka levytiedosto</comment>
+ <comment xml:lang="fr">image disque Raw</comment>
+ <comment xml:lang="ga">Amhíomha diosca</comment>
+ <comment xml:lang="gl">Imaxe de disco en bruto</comment>
+ <comment xml:lang="he">דמות גולמית של כונן</comment>
+ <comment xml:lang="hr">Osnovna slika diska</comment>
+ <comment xml:lang="hu">Nyers lemezkép</comment>
+ <comment xml:lang="ia">Imagine de disco crude</comment>
+ <comment xml:lang="id">Image disk mentah</comment>
+ <comment xml:lang="it">Immagine disco raw</comment>
+ <comment xml:lang="kk">Шикі диÑк бейнеÑÑ–</comment>
+ <comment xml:lang="ko">RAW ë””ìŠ¤í¬ ì´ë¯¸ì§€</comment>
+ <comment xml:lang="oc">imatge disc Raw</comment>
+ <comment xml:lang="pl">Surowy obraz dysku</comment>
+ <comment xml:lang="pt">imagem de disco Raw</comment>
+ <comment xml:lang="pt_BR">Imagem bruta de disco</comment>
+ <comment xml:lang="ru">Ðеобработанный образ диÑка</comment>
+ <comment xml:lang="sk">Obraz disku</comment>
+ <comment xml:lang="sl">Surovi odtis diska</comment>
+ <comment xml:lang="sr">Ñиров одраз диÑка</comment>
+ <comment xml:lang="sv">RÃ¥ diskavbild</comment>
+ <comment xml:lang="tr">İşlem görmemiş disk imajı</comment>
+ <comment xml:lang="uk">проÑтий образ диÑка</comment>
+ <comment xml:lang="zh_CN">原始ç£ç›˜æ˜ åƒ</comment>
+ <comment xml:lang="zh_TW">原生ç£ç¢Ÿæ˜ åƒæª”</comment>
+ <glob pattern="*.raw-disk-image"/>
+ <glob pattern="*.img"/>
+ </mime-type>
+ <mime-type type="application/x-raw-floppy-disk-image">
+ <comment>Floppy disk image</comment>
+ <sub-class-of type="application/x-raw-disk-image"/>
+ <alias type="application/x-fd-file"/>
+ <glob pattern="*.fd"/>
+ <glob pattern="*.qd"/>
+ </mime-type>
+ <mime-type type="application/x-raw-disk-image-xz-compressed">
+ <comment>Raw disk image (XZ-compressed)</comment>
+ <comment xml:lang="ast">Imaxe de discu en bruto (comprimida en XZ)</comment>
+ <comment xml:lang="ca">imatge de disc RAW (amb compressió XZ)</comment>
+ <comment xml:lang="cs">surový obraz disku (komprimovaný pomocí XZ)</comment>
+ <comment xml:lang="da">RÃ¥ diskaftryk (XZ-komprimeret)</comment>
+ <comment xml:lang="de">Rohes Datenträgerabbild (XZ-komprimiert)</comment>
+ <comment xml:lang="el">ΑνεπεξέÏγαστη εικόνα δίσκου (συμπιεσμένη XZ)</comment>
+ <comment xml:lang="en_GB">Raw disk image (XZ-compressed)</comment>
+ <comment xml:lang="es">imagen de disco en bruto (comprimida con XZ)</comment>
+ <comment xml:lang="eu">Disko gordinaren irudia (XZ-rekin konprimitua)</comment>
+ <comment xml:lang="fi">Raaka levytiedosto (XZ-pakattu)</comment>
+ <comment xml:lang="fr">image disque Raw (compression XZ)</comment>
+ <comment xml:lang="ga">Amhíomhá (comhbhrúite le XZ)</comment>
+ <comment xml:lang="gl">Imaxe de disco en bruto (comprimida en XZ)</comment>
+ <comment xml:lang="he">דמות גולמית של כונן (בדחיסת XZ)</comment>
+ <comment xml:lang="hr">Osnovna slika diska (XZ sažeta)</comment>
+ <comment xml:lang="hu">Nyers lemezkép (XZ-vel tömörítve)</comment>
+ <comment xml:lang="ia">Imagine de disco crude (comprimite con XZ)</comment>
+ <comment xml:lang="id">Image disk mentah (terkompresi XZ)</comment>
+ <comment xml:lang="it">Immagine disco raw (compressa XZ)</comment>
+ <comment xml:lang="kk">Шикі диÑк бейнеÑÑ– (XZ-мен Ñығылған)</comment>
+ <comment xml:lang="ko">RAW ë””ìŠ¤í¬ ì´ë¯¸ì§€(XZ 압축)</comment>
+ <comment xml:lang="oc">imatge disc Raw (compression XZ)</comment>
+ <comment xml:lang="pl">Surowy obraz dysku (kompresja XZ)</comment>
+ <comment xml:lang="pt">imagem de disco Raw (compressão XZ)</comment>
+ <comment xml:lang="pt_BR">Imagem bruta de disco (compactada com XZ)</comment>
+ <comment xml:lang="ru">Ðеобработанный образ диÑка (Ñжатый xz)</comment>
+ <comment xml:lang="sk">Obraz disku (komprimovaný pomocou XZ)</comment>
+ <comment xml:lang="sl">Surovi odtis diska (stisnjeno z XZ)</comment>
+ <comment xml:lang="sr">Ñиров одраз диÑка (запакована ИкÑЗ-ом)</comment>
+ <comment xml:lang="sv">RÃ¥ diskavbild (XZ-komprimerad)</comment>
+ <comment xml:lang="tr">İşlem görmemiş disk imajı (XZ ile sıkıştırılmış)</comment>
+ <comment xml:lang="uk">проÑтий образ диÑка (ÑтиÑнений XZ)</comment>
+ <comment xml:lang="zh_CN">原始ç£ç›˜æ˜ åƒï¼ˆXZ 压缩)</comment>
+ <comment xml:lang="zh_TW">原生ç£ç¢Ÿæ˜ åƒ (XZ æ ¼å¼å£“縮)</comment>
+ <sub-class-of type="application/x-xz"/>
+ <glob pattern="*.raw-disk-image.xz"/>
+ <glob pattern="*.img.xz"/>
+ </mime-type>
<mime-type type="application/x-cd-image">
<comment>raw CD image</comment>
<comment xml:lang="ar">صورة CD خامة</comment>
+ <comment xml:lang="ast">imaxe de CD en bruto</comment>
<comment xml:lang="be@latin">suvoraja vyjava CD</comment>
<comment xml:lang="bg">Изображение — raw CD</comment>
<comment xml:lang="ca">imatge de CD en cru</comment>
@@ -8440,17 +8635,17 @@
<comment xml:lang="pt">imagem em bruto de CD</comment>
<comment xml:lang="pt_BR">Imagem bruta de CD</comment>
<comment xml:lang="ro">imagine de CD brută</comment>
- <comment xml:lang="ru">необработанный образ компакт-диÑка</comment>
+ <comment xml:lang="ru">Ðеобработанный образ компакт-диÑка</comment>
<comment xml:lang="sk">Surový obraz CD</comment>
<comment xml:lang="sl">surovi CD odtis</comment>
<comment xml:lang="sq">Imazh raw CD</comment>
- <comment xml:lang="sr">Ñирова Ñлика ЦД-а</comment>
+ <comment xml:lang="sr">Ñиров одраз ЦД-а</comment>
<comment xml:lang="sv">rå cd-avbild</comment>
<comment xml:lang="tr">Ham CD görüntüsü</comment>
<comment xml:lang="uk">образ raw CD</comment>
<comment xml:lang="vi">ảnh đĩa CD thô</comment>
<comment xml:lang="zh_CN">原始 CD 映åƒ</comment>
- <comment xml:lang="zh_TW">原生 CD 映åƒ</comment>
+ <comment xml:lang="zh_TW">原生 CD 映åƒæª”</comment>
<sub-class-of type="application/x-raw-disk-image"/>
<alias type="application/x-iso9660-image"/>
@@ -8460,20 +8655,31 @@
<mime-type type="application/x-iso9660-appimage">
<comment>AppImage application bundle</comment>
<comment xml:lang="ca">paquet d'aplicació AppImage</comment>
+ <comment xml:lang="cs">balíÄek AppImage s aplikací</comment>
<comment xml:lang="da">Applmage-programsamling</comment>
<comment xml:lang="de">AppImage-Anwendungspaket</comment>
+ <comment xml:lang="en_GB">AppImage application bundle</comment>
<comment xml:lang="es">paquete de aplicación AppImage</comment>
+ <comment xml:lang="eu">AppImage aplikazio bilduma</comment>
+ <comment xml:lang="fi">AppImage-sovelluspaketti</comment>
<comment xml:lang="fr">lot applicatif AppImage</comment>
+ <comment xml:lang="ga">burla feidhmchláir AppImage</comment>
<comment xml:lang="he">חבילת יישומי AppImage</comment>
+ <comment xml:lang="hr">AppImage paket aplikacije</comment>
<comment xml:lang="hu">AppImage alkalmazáscsomag</comment>
+ <comment xml:lang="id">bundel aplikasi AppImage</comment>
+ <comment xml:lang="it">Bundle applicazione AppImage</comment>
<comment xml:lang="kk">AppImage қолданбалар деÑтеÑÑ–</comment>
<comment xml:lang="ko">AppImage 프로그램 번들</comment>
<comment xml:lang="pl">Pakiet programu AppImage</comment>
<comment xml:lang="pt_BR">Pacote de aplicativo AppImage</comment>
- <comment xml:lang="ru">пакет приложений AppImage</comment>
+ <comment xml:lang="ru">Пакет Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ AppImage</comment>
<comment xml:lang="sk">Balík aplikácií AppImage</comment>
+ <comment xml:lang="sr">Ñкуп програма Ðп-Ñлике</comment>
+ <comment xml:lang="sv">AppImage-programbunt</comment>
+ <comment xml:lang="tr">AppImage uygulama paketi</comment>
<comment xml:lang="uk">пакунок із програмами AppImage</comment>
- <comment xml:lang="zh_CN">AppImage 应用包</comment>
+ <comment xml:lang="zh_CN">AppImage 应用组åˆåŒ…</comment>
<comment xml:lang="zh_TW">AppImage 應用程å¼å¥—組</comment>
<sub-class-of type="application/x-executable"/>
<sub-class-of type="application/x-iso9660-image"/>
@@ -8488,7 +8694,6 @@
</match>
</magic>
<glob pattern="*.appimage"/>
- <glob pattern="*.AppImage"/>
</mime-type>
<mime-type type="application/x-cdrdao-toc">
<comment>CD Table Of Contents</comment>
@@ -8527,7 +8732,7 @@
<comment xml:lang="pt">Tabela de conteúdos de CD</comment>
<comment xml:lang="pt_BR">Sumário de CD</comment>
<comment xml:lang="ro">Tabel conținut CD</comment>
- <comment xml:lang="ru">таблица ÑÐ¾Ð´ÐµÑ€Ð¶Ð°Ð½Ð¸Ñ CD</comment>
+ <comment xml:lang="ru">Таблица ÑÐ¾Ð´ÐµÑ€Ð¶Ð°Ð½Ð¸Ñ CD</comment>
<comment xml:lang="sk">Obsah CD</comment>
<comment xml:lang="sl">Kazalo vsebine CD nosilca</comment>
<comment xml:lang="sq">Tregues CD</comment>
@@ -8588,7 +8793,7 @@
<comment xml:lang="pt">notação de jogo de xadrez PGN</comment>
<comment xml:lang="pt_BR">Notação de jogo de xadrez PGN</comment>
<comment xml:lang="ro">Notație joc șah PGN</comment>
- <comment xml:lang="ru">ÑˆÐ°Ñ…Ð¼Ð°Ñ‚Ð½Ð°Ñ Ð¿Ð°Ñ€Ñ‚Ð¸Ñ PGN</comment>
+ <comment xml:lang="ru">Ð¨Ð°Ñ…Ð¼Ð°Ñ‚Ð½Ð°Ñ Ð¿Ð°Ñ€Ñ‚Ð¸Ñ PGN</comment>
<comment xml:lang="sk">Šachová notácia PGN</comment>
<comment xml:lang="sl">Datoteka opomb Å¡ahovske igre PGN</comment>
<comment xml:lang="sq">Njoftim loje shahu PGN</comment>
@@ -8612,6 +8817,7 @@
<mime-type type="application/vnd.ms-htmlhelp">
<comment>CHM document</comment>
<comment xml:lang="ar">مستند CHM</comment>
+ <comment xml:lang="ast">Documentu CHM</comment>
<comment xml:lang="be@latin">Dakument CHM</comment>
<comment xml:lang="bg">Документ — CHM</comment>
<comment xml:lang="ca">document CHM</comment>
@@ -8648,7 +8854,7 @@
<comment xml:lang="pt">documento CHM</comment>
<comment xml:lang="pt_BR">Documento CHM</comment>
<comment xml:lang="ro">Document CHM</comment>
- <comment xml:lang="ru">документ CHM</comment>
+ <comment xml:lang="ru">Документ CHM</comment>
<comment xml:lang="sk">Dokument CHM</comment>
<comment xml:lang="sl">Dokument CHM</comment>
<comment xml:lang="sq">Dokument CHM</comment>
@@ -8706,7 +8912,7 @@
<comment xml:lang="pt">byte-code Java</comment>
<comment xml:lang="pt_BR">Código compilado Java</comment>
<comment xml:lang="ro">Bytecode Java</comment>
- <comment xml:lang="ru">байт-код Java</comment>
+ <comment xml:lang="ru">Байт-код Java</comment>
<comment xml:lang="sk">Bajtový kód Java</comment>
<comment xml:lang="sl">Datoteka bitne kode Java</comment>
<comment xml:lang="sq">Byte code Java</comment>
@@ -8738,7 +8944,7 @@
<comment xml:lang="ga">comhad UNIX-comhbhrúite</comment>
<comment xml:lang="gl">ficheiro comprimido de UNIX</comment>
<comment xml:lang="he">קובץ בכיווץ UNIX</comment>
- <comment xml:lang="hr">UNIX-komprimirana datoteka</comment>
+ <comment xml:lang="hr">UNIX sažeta datoteka</comment>
<comment xml:lang="hu">Tömörített UNIX-fájl</comment>
<comment xml:lang="ia">File comprimite de UNIX</comment>
<comment xml:lang="id">Berkas terkompresi UNIX</comment>
@@ -8757,7 +8963,7 @@
<comment xml:lang="pt">ficheiro comprimido UNIX</comment>
<comment xml:lang="pt_BR">Arquivo compactado do UNIX</comment>
<comment xml:lang="ro">Fișier comprimat UNIX</comment>
- <comment xml:lang="ru">файл (UNIX-Ñжатый)</comment>
+ <comment xml:lang="ru">Файл (UNIX-Ñжатый)</comment>
<comment xml:lang="sk">Súbor komprimovaný v Unixe</comment>
<comment xml:lang="sl">SkrÄena Unix datoteka</comment>
<comment xml:lang="sq">File i kompresuar UNIX</comment>
@@ -8793,7 +8999,7 @@
<comment xml:lang="ga">cartlann Tar (comhbhrúite le gzip)</comment>
<comment xml:lang="gl">arquivo Tar (comprimido con gzip)</comment>
<comment xml:lang="he">×רכיון Tar (מכווץ ×¢×´×™ gzip)</comment>
- <comment xml:lang="hr">Tar arhiva (komprimirana gzip-om)</comment>
+ <comment xml:lang="hr">Tar arhiva (gzip sažeta)</comment>
<comment xml:lang="hu">Tar archívum (gzip-pel tömörítve)</comment>
<comment xml:lang="ia">Archivo Tar (comprimite con gzip)</comment>
<comment xml:lang="id">Arsip Tar (terkompresi gzip)</comment>
@@ -8811,7 +9017,7 @@
<comment xml:lang="pt">arquivo Tar (compressão gzip)</comment>
<comment xml:lang="pt_BR">Pacote Tar (compactado com gzip)</comment>
<comment xml:lang="ro">Arhivă Tar (comprimată gzip)</comment>
- <comment xml:lang="ru">архив TAR (Ñжатый GZIP)</comment>
+ <comment xml:lang="ru">Ðрхив TAR (Ñжатый gzip)</comment>
<comment xml:lang="sk">Archív tar (komprimovaný pomocou gzip)</comment>
<comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z gzip)</comment>
<comment xml:lang="sq">Arkiv tar (i kompresuar me gzip)</comment>
@@ -8820,7 +9026,7 @@
<comment xml:lang="tr">Tar arşivi (gzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">архів tar (ÑтиÑнений gzip)</comment>
<comment xml:lang="vi">Kho nén tar (đã nén gzip)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件(gzip 压缩)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(gzip 压缩)</comment>
<comment xml:lang="zh_TW">Tar å°å­˜æª” (gzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="package-x-generic"/>
@@ -8844,7 +9050,7 @@
<comment xml:lang="fi">ohjelman kaatumistiedot</comment>
<comment xml:lang="fo">forrits sordáta</comment>
<comment xml:lang="fr">données de plantage de programme</comment>
- <comment xml:lang="ga">sonraí thuairt ríomhchláir</comment>
+ <comment xml:lang="ga">sonraí tuairte ríomhchláir</comment>
<comment xml:lang="gl">datos de colgue do programa</comment>
<comment xml:lang="he">מידע מקריסת תכנית</comment>
<comment xml:lang="hr">podaci o rušenju programa</comment>
@@ -8866,7 +9072,7 @@
<comment xml:lang="pt">dados de rebentamento de aplicação</comment>
<comment xml:lang="pt_BR">Dados de travamento de programa</comment>
<comment xml:lang="ro">date eroare program</comment>
- <comment xml:lang="ru">данные аварийного завершениÑ</comment>
+ <comment xml:lang="ru">Данные аварийного Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹</comment>
<comment xml:lang="sk">Údaje o páde programu</comment>
<comment xml:lang="sl">podatki sesutja programa</comment>
<comment xml:lang="sq">Të dhëna nga programi i bllokuar</comment>
@@ -8897,6 +9103,7 @@
<mime-type type="application/x-cpio">
<comment>CPIO archive</comment>
<comment xml:lang="ar">أرشي٠CPIO</comment>
+ <comment xml:lang="ast">Archivu CPIO</comment>
<comment xml:lang="az">CPIO arxivi</comment>
<comment xml:lang="be@latin">ArchiÅ­ CPIO</comment>
<comment xml:lang="bg">Ðрхив — CPIO</comment>
@@ -8936,7 +9143,7 @@
<comment xml:lang="pt">arquivo CPIO</comment>
<comment xml:lang="pt_BR">Pacote CPIO</comment>
<comment xml:lang="ro">Arhivă CPIO</comment>
- <comment xml:lang="ru">архив CPIO</comment>
+ <comment xml:lang="ru">Ðрхив CPIO</comment>
<comment xml:lang="sk">Archív CPIO</comment>
<comment xml:lang="sl">Datoteka arhiva CPIO</comment>
<comment xml:lang="sq">Arkiv CPIO</comment>
@@ -8978,7 +9185,7 @@
<comment xml:lang="ga">cartlann CPIO (comhbhrúite le gzip)</comment>
<comment xml:lang="gl">arquivo CPIO (comprimido con gzip)</comment>
<comment xml:lang="he">×רכיון CPIO (מכווץ ×¢×´×™ gzip)</comment>
- <comment xml:lang="hr">CPIO arhiva (komprimirana gzip-om)</comment>
+ <comment xml:lang="hr">CPIO arhiva (gzip sažeta)</comment>
<comment xml:lang="hu">CPIO-archívum (gzip-pel tömörítve)</comment>
<comment xml:lang="ia">Archivo CPIO (comprimite con gzip)</comment>
<comment xml:lang="id">Arsip CPIO (terkompresi gzip)</comment>
@@ -8998,7 +9205,7 @@
<comment xml:lang="pt">arquivo CPIO (compressão gzip)</comment>
<comment xml:lang="pt_BR">Pacote CPIO (compactado com gzip)</comment>
<comment xml:lang="ro">Arhivă CPIO (compresie gzip)</comment>
- <comment xml:lang="ru">архив CPIO (Ñжатый GZIP)</comment>
+ <comment xml:lang="ru">Ðрхив CPIO (Ñжатый gzip)</comment>
<comment xml:lang="sk">Archív CPIO (komprimovaný pomocou gzip)</comment>
<comment xml:lang="sl">Datoteka arhiva CPIO (skrÄena z gzip)</comment>
<comment xml:lang="sq">Arkiv CPIO (kompresuar me gzip)</comment>
@@ -9007,7 +9214,7 @@
<comment xml:lang="tr">CPIO arşivi (gzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">архів CPIO (ÑтиÑнений gzip)</comment>
<comment xml:lang="vi">Kho nén CPIO (đã nén gzip)</comment>
- <comment xml:lang="zh_CN">CPIO 归档文件(gzip 压缩)</comment>
+ <comment xml:lang="zh_CN">CPIO 归档文件(gzip 压缩)</comment>
<comment xml:lang="zh_TW">CPIO å°å­˜æª” (gzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="package-x-generic"/>
@@ -9019,7 +9226,7 @@
<comment xml:lang="az">C qabıq skripti</comment>
<comment xml:lang="be@latin">Skrypt abałonki C</comment>
<comment xml:lang="bg">Скрипт — обвивка C</comment>
- <comment xml:lang="ca">script de C shell</comment>
+ <comment xml:lang="ca">script C shell</comment>
<comment xml:lang="cs">skript shellu C</comment>
<comment xml:lang="cy">Sgript plisgyn C</comment>
<comment xml:lang="da">C-skalprogram</comment>
@@ -9032,10 +9239,10 @@
<comment xml:lang="fi">Csh-komentotiedosto</comment>
<comment xml:lang="fo">C skel boðrøð</comment>
<comment xml:lang="fr">script C shell</comment>
- <comment xml:lang="ga">script bhlaosc C</comment>
+ <comment xml:lang="ga">script bhlaoisce C</comment>
<comment xml:lang="gl">script de C shell</comment>
<comment xml:lang="he">תסריט מעטפת C</comment>
- <comment xml:lang="hr">C skripta</comment>
+ <comment xml:lang="hr">C skripta ljuske</comment>
<comment xml:lang="hu">C héj-parancsfájl</comment>
<comment xml:lang="ia">Script C-shell</comment>
<comment xml:lang="id">Skrip shell C</comment>
@@ -9054,11 +9261,11 @@
<comment xml:lang="pt">script de terminal C</comment>
<comment xml:lang="pt_BR">Script de shell C</comment>
<comment xml:lang="ro">Script C shell</comment>
- <comment xml:lang="ru">Ñценарий C shell</comment>
+ <comment xml:lang="ru">Сценарий C shell</comment>
<comment xml:lang="sk">Skript shellu C</comment>
<comment xml:lang="sl">Skriptna datoteka lupine C</comment>
<comment xml:lang="sq">Script shell C</comment>
- <comment xml:lang="sr">Ñкрипта Ц љуÑке</comment>
+ <comment xml:lang="sr">Ñкрипта Ц шкољке</comment>
<comment xml:lang="sv">Skalskript (csh)</comment>
<comment xml:lang="tr">C kabuk betiÄŸi</comment>
<comment xml:lang="uk">Ñкрипт оболонки C</comment>
@@ -9079,6 +9286,7 @@
<mime-type type="application/x-dbf">
<comment>Xbase document</comment>
<comment xml:lang="ar">مستند Xbase</comment>
+ <comment xml:lang="ast">Documentu Xbase</comment>
<comment xml:lang="be@latin">Dakument Xbase</comment>
<comment xml:lang="bg">Документ — Xbase</comment>
<comment xml:lang="ca">document Xbase</comment>
@@ -9114,7 +9322,7 @@
<comment xml:lang="pt">documento Xbase</comment>
<comment xml:lang="pt_BR">Documento do Xbase</comment>
<comment xml:lang="ro">Document Xbase</comment>
- <comment xml:lang="ru">документ Xbase</comment>
+ <comment xml:lang="ru">Документ Xbase</comment>
<comment xml:lang="sk">Dokument Xbase</comment>
<comment xml:lang="sl">Dokument Xbase</comment>
<comment xml:lang="sq">Dokument Xbase</comment>
@@ -9169,7 +9377,7 @@
<comment xml:lang="pt">programa ECMAScript</comment>
<comment xml:lang="pt_BR">Programa ECMAScript</comment>
<comment xml:lang="ro">Program ECMAScript</comment>
- <comment xml:lang="ru">программа ECMAScript</comment>
+ <comment xml:lang="ru">Программа ECMAScript</comment>
<comment xml:lang="sk">Program ECMAScript</comment>
<comment xml:lang="sl">Programska datoteka ECMAScript</comment>
<comment xml:lang="sq">Program ECMAScript</comment>
@@ -9181,6 +9389,7 @@
<comment xml:lang="zh_CN">ECMAScript 程åº</comment>
<comment xml:lang="zh_TW">ECMAScript 程å¼</comment>
<alias type="text/ecmascript"/>
+ <sub-class-of type='application/x-executable'/>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
<glob pattern="*.es"/>
@@ -9188,22 +9397,33 @@
<mime-type type="application/x-sega-cd-rom">
<comment>Sega CD disc image</comment>
+ <comment xml:lang="ast">Imaxe de discu de Sega CD</comment>
<comment xml:lang="ca">imatge de disc de Sega CD</comment>
+ <comment xml:lang="cs">obraz disku CD pro Sega</comment>
<comment xml:lang="da">Sega CD-diskaftryk</comment>
<comment xml:lang="de">Sega-CD-Datenträgerabbild</comment>
+ <comment xml:lang="en_GB">Sega CD disc image</comment>
<comment xml:lang="es">imagen de disco CD de Sega</comment>
+ <comment xml:lang="eu">Sega CD disko irudia</comment>
<comment xml:lang="fi">Sega CD -levykuva</comment>
<comment xml:lang="fr">image disque Sega CD</comment>
+ <comment xml:lang="ga">íomhá dlúthdhiosca Sega</comment>
<comment xml:lang="he">דמות כונן Sega CD</comment>
+ <comment xml:lang="hr">Sega CD slika diska</comment>
<comment xml:lang="hu">Sega CD-lemezkép</comment>
+ <comment xml:lang="id">image cakram CD Sega</comment>
+ <comment xml:lang="it">Immagine disco Sega Mega CD</comment>
<comment xml:lang="kk">Sega CD диÑк бейнеÑÑ–</comment>
<comment xml:lang="ko">세가 CD ë””ìŠ¤í¬ ì´ë¯¸ì§€</comment>
<comment xml:lang="pl">Obraz płyty konsoli Mega-CD</comment>
<comment xml:lang="pt_BR">Imagem de disco Sega CD</comment>
- <comment xml:lang="ru">образ диÑка CD Sega</comment>
+ <comment xml:lang="ru">Образ диÑка CD Sega</comment>
<comment xml:lang="sk">Obraz disku CD Sega</comment>
+ <comment xml:lang="sr">одраз диÑка Сега ЦД-а</comment>
+ <comment xml:lang="sv">Mega-CD-skivavbild</comment>
+ <comment xml:lang="tr">Sega CD disk kalıbı</comment>
<comment xml:lang="uk">образ диÑка Sega CD</comment>
- <comment xml:lang="zh_CN">Sega CD 光盘镜åƒ</comment>
+ <comment xml:lang="zh_CN">Sega CD 光盘映åƒ</comment>
<comment xml:lang="zh_TW">Sega CD 光碟映åƒæª”</comment>
<generic-icon name="application-x-executable"/>
@@ -9221,6 +9441,32 @@
<mime-type type="application/x-sega-pico-rom">
<comment>Sega Pico ROM</comment>
+ <comment xml:lang="ast">ROM de Sega Pico</comment>
+ <comment xml:lang="ca">ROM de Sega Pico</comment>
+ <comment xml:lang="cs">ROM pro Sega Pico</comment>
+ <comment xml:lang="de">Sega Pico ROM</comment>
+ <comment xml:lang="en_GB">Sega Pico ROM</comment>
+ <comment xml:lang="es">ROM de Sega Pico</comment>
+ <comment xml:lang="eu">Sega Pico ROM</comment>
+ <comment xml:lang="fi">Sega Pico ROM</comment>
+ <comment xml:lang="fr">ROM Sega Pico</comment>
+ <comment xml:lang="ga">ROM Sega Pico</comment>
+ <comment xml:lang="hr">Sega Pico ROM</comment>
+ <comment xml:lang="hu">Sega Pico ROM</comment>
+ <comment xml:lang="id">ROM Sega Pico</comment>
+ <comment xml:lang="it">ROM Sega Pico</comment>
+ <comment xml:lang="kk">Sega Pico ROM</comment>
+ <comment xml:lang="ko">세카 피코 롬</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Sega Pico</comment>
+ <comment xml:lang="pt_BR">ROM de Sega Pico</comment>
+ <comment xml:lang="ru">Sega Pico ROM</comment>
+ <comment xml:lang="sk">ROM pre Sega Pico</comment>
+ <comment xml:lang="sr">Сега Пико РОМ</comment>
+ <comment xml:lang="sv">Sega Pico-rom</comment>
+ <comment xml:lang="tr">Sega Pico ROM</comment>
+ <comment xml:lang="uk">ППП Sega Pico</comment>
+ <comment xml:lang="zh_CN">Sega Pico ROM</comment>
+ <comment xml:lang="zh_TW">Sega Pico ROM</comment>
<generic-icon name="application-x-executable"/>
<magic priority="50">
<match value="SEGA PICO" type="string" offset="256"/>
@@ -9228,6 +9474,7 @@
</mime-type>
<mime-type type="application/x-saturn-rom">
<comment>Sega Saturn disc image</comment>
+ <comment xml:lang="ast">Imaxe de discu de Sega Saturn</comment>
<comment xml:lang="ca">imatge de disc de Sega Saturn</comment>
<comment xml:lang="cs">obraz disku pro Sega Saturn</comment>
<comment xml:lang="da">Sega Saturn-diskaftryk</comment>
@@ -9238,6 +9485,7 @@
<comment xml:lang="eu">Sega Saturn disko irudia</comment>
<comment xml:lang="fi">Sega Saturn -levykuva</comment>
<comment xml:lang="fr">image disque Sega Saturn</comment>
+ <comment xml:lang="ga">íomhá diosca Sega Saturn</comment>
<comment xml:lang="he">דמות כונן Sega Saturn</comment>
<comment xml:lang="hr">Sega Saturn slika diska</comment>
<comment xml:lang="hu">Sega Saturn lemezkép</comment>
@@ -9250,13 +9498,13 @@
<comment xml:lang="pl">Obraz płyty konsoli Sega Saturn</comment>
<comment xml:lang="pt">imagem de disco Sega Saturn</comment>
<comment xml:lang="pt_BR">Imagem de disco do Sega Saturn</comment>
- <comment xml:lang="ru">образ диÑка Sega Saturn</comment>
+ <comment xml:lang="ru">Образ диÑка Sega Saturn</comment>
<comment xml:lang="sk">Obraz disku Sega Saturn</comment>
- <comment xml:lang="sr">Ñлика диÑка Сега Сатурна</comment>
+ <comment xml:lang="sr">одраз диÑка Сега Сатурна</comment>
<comment xml:lang="sv">Sega Saturn-skivavbild</comment>
<comment xml:lang="tr">Sega Saturn disk kalıbı</comment>
<comment xml:lang="uk">образ диÑка Sega Saturn</comment>
- <comment xml:lang="zh_CN">Sega Saturn 光盘镜åƒ</comment>
+ <comment xml:lang="zh_CN">Sega Saturn 光盘映åƒ</comment>
<comment xml:lang="zh_TW">Sega Saturn 光碟映åƒæª”</comment>
<generic-icon name="application-x-executable"/>
<magic priority="50">
@@ -9268,6 +9516,7 @@
</mime-type>
<mime-type type="application/x-dc-rom">
<comment>Dreamcast GD-ROM</comment>
+ <comment xml:lang="ast">GD-ROM de Dreamcast</comment>
<comment xml:lang="ca">GD-ROM de Dreamcast</comment>
<comment xml:lang="cs">GD-ROM pro Dreamcast</comment>
<comment xml:lang="da">Dreamcast GD-ROM</comment>
@@ -9277,6 +9526,7 @@
<comment xml:lang="es">GD-ROM de Dreamcast</comment>
<comment xml:lang="eu">Dreamcast GD-ROM</comment>
<comment xml:lang="fr">GD-ROM Dreamcast</comment>
+ <comment xml:lang="ga">GD-ROM Dreamcast</comment>
<comment xml:lang="he">Dreamcast GD-ROM</comment>
<comment xml:lang="hr">Dreamcast GD-ROM</comment>
<comment xml:lang="hu">Dreamcast GD-ROM</comment>
@@ -9288,8 +9538,8 @@
<comment xml:lang="oc">GD-ROM Dreamcast</comment>
<comment xml:lang="pl">Plik GD-ROM konsoli Dreamcast</comment>
<comment xml:lang="pt">GD-ROM Dreamcast</comment>
- <comment xml:lang="pt_BR">GD-ROM do Dreamcast</comment>
- <comment xml:lang="ru">GD-ROM Dreamcast</comment>
+ <comment xml:lang="pt_BR">GD-ROM de Dreamcast</comment>
+ <comment xml:lang="ru">Dreamcast GD-ROM</comment>
<comment xml:lang="sk">Dreamcast GD-ROM</comment>
<comment xml:lang="sr">ДримкаÑÑ‚ ГД-РОМ</comment>
<comment xml:lang="sv">Dreamcast-gd-rom</comment>
@@ -9303,6 +9553,7 @@
<mime-type type="application/x-nintendo-ds-rom">
<comment>Nintendo DS ROM</comment>
<comment xml:lang="ar">Nintendo DS ROM</comment>
+ <comment xml:lang="ast">ROM de Nintendo DS</comment>
<comment xml:lang="be@latin">Nintendo DS ROM</comment>
<comment xml:lang="bg">ROM — Nintendo DS</comment>
<comment xml:lang="ca">ROM de Nintendo DS</comment>
@@ -9335,7 +9586,7 @@
<comment xml:lang="oc">ROM Nintendo DS</comment>
<comment xml:lang="pl">Plik ROM konsoli Nintendo DS</comment>
<comment xml:lang="pt">ROM Nintendo DS</comment>
- <comment xml:lang="pt_BR">ROM do Nintendo DS</comment>
+ <comment xml:lang="pt_BR">ROM de Nintendo DS</comment>
<comment xml:lang="ro">ROM Nintendo DS</comment>
<comment xml:lang="ru">Nintendo DS ROM</comment>
<comment xml:lang="sk">ROM pre Nintendo DS</comment>
@@ -9346,13 +9597,14 @@
<comment xml:lang="tr">Nintendo DS ROM</comment>
<comment xml:lang="uk">ППП Nintendo</comment>
<comment xml:lang="vi">ROM DS Nintendo</comment>
- <comment xml:lang="zh_CN">Nintendo DS ROM</comment>
+ <comment xml:lang="zh_CN">任天堂 DS ROM</comment>
<comment xml:lang="zh_TW">任天堂 DS ROM</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.nds"/>
</mime-type>
<mime-type type="application/x-pc-engine-rom">
<comment>PC Engine ROM</comment>
+ <comment xml:lang="ast">ROM de PC Engine</comment>
<comment xml:lang="ca">ROM de PC Engine</comment>
<comment xml:lang="cs">ROM pro PC Engine</comment>
<comment xml:lang="da">PC Engine ROM</comment>
@@ -9363,6 +9615,7 @@
<comment xml:lang="eu">PC Engine ROM</comment>
<comment xml:lang="fi">PC Engine ROM</comment>
<comment xml:lang="fr">ROM PC Engine</comment>
+ <comment xml:lang="ga">ROM PC Engine</comment>
<comment xml:lang="gl">ROM de máquina de PC</comment>
<comment xml:lang="he">ROM של PC Engine</comment>
<comment xml:lang="hr">PC Engine ROM</comment>
@@ -9390,6 +9643,7 @@
</mime-type>
<mime-type type="application/x-wii-rom">
<comment>Wii disc image</comment>
+ <comment xml:lang="ast">Imaxe de discu de Wii</comment>
<comment xml:lang="ca">imatge de disc de Wii</comment>
<comment xml:lang="cs">obraz disku pro Wii</comment>
<comment xml:lang="da">Wii-diskaftryk</comment>
@@ -9400,6 +9654,7 @@
<comment xml:lang="eu">Wii disko irudia</comment>
<comment xml:lang="fi">Wii-levykuva</comment>
<comment xml:lang="fr">image disque Wii</comment>
+ <comment xml:lang="ga">íomhá diosca Wii</comment>
<comment xml:lang="gl">Imaxe de disco de Wii</comment>
<comment xml:lang="he">דמות כונן Wii</comment>
<comment xml:lang="hr">Wii slika diska</comment>
@@ -9413,14 +9668,14 @@
<comment xml:lang="pl">Obraz płyty konsoli Wii</comment>
<comment xml:lang="pt">imagem de disco Wii</comment>
<comment xml:lang="pt_BR">Imagem de disco Wii</comment>
- <comment xml:lang="ru">образ диÑка Wii</comment>
+ <comment xml:lang="ru">Образ диÑка Wii</comment>
<comment xml:lang="sk">Obraz disku Wii</comment>
<comment xml:lang="sl">Odtis diska Wii</comment>
- <comment xml:lang="sr">Ñлика диÑка Вии-ја</comment>
+ <comment xml:lang="sr">одраз диÑка Вии-ја</comment>
<comment xml:lang="sv">Wii-skivavbild</comment>
<comment xml:lang="tr">Wii disk görüntüsü</comment>
<comment xml:lang="uk">образ диÑка Wii</comment>
- <comment xml:lang="zh_CN">Wii光盘镜åƒ</comment>
+ <comment xml:lang="zh_CN">Wii 光盘映åƒ</comment>
<comment xml:lang="zh_TW">Wii 光碟映åƒæª”</comment>
<alias type="application/x-wii-iso-image"/>
<alias type="application/x-wbfs"/>
@@ -9441,7 +9696,9 @@
<comment xml:lang="de">WiiWare-Paket</comment>
<comment xml:lang="en_GB">WiiWare bundle</comment>
<comment xml:lang="es">conjunto de WiiWare</comment>
+ <comment xml:lang="eu">WiiWare bilduma</comment>
<comment xml:lang="fr">lot WiiWare</comment>
+ <comment xml:lang="ga">burla WiiWare</comment>
<comment xml:lang="he">מ×גד WiiWare</comment>
<comment xml:lang="hr">WiiWare paket</comment>
<comment xml:lang="hu">WiiWare csomag</comment>
@@ -9454,13 +9711,13 @@
<comment xml:lang="pl">Pakiet WiiWare</comment>
<comment xml:lang="pt">pacote WiiWare</comment>
<comment xml:lang="pt_BR">Pacote WiiWare</comment>
- <comment xml:lang="ru">пакет WiiWare</comment>
+ <comment xml:lang="ru">Пакет WiiWare</comment>
<comment xml:lang="sk">Balík WiiWare</comment>
<comment xml:lang="sr">ВииВер комплет</comment>
<comment xml:lang="sv">WiiWare-paket</comment>
<comment xml:lang="tr">WiiWare paketi</comment>
<comment xml:lang="uk">пакет WiiWare</comment>
- <comment xml:lang="zh_CN">WiiWare bundle</comment>
+ <comment xml:lang="zh_CN">WiiWare æ†ç»‘包</comment>
<comment xml:lang="zh_TW">WiiWare ç¶åŒ…</comment>
<generic-icon name="application-x-executable"/>
<magic priority="50">
@@ -9482,6 +9739,7 @@
<comment xml:lang="eu">GameCube disko irudia</comment>
<comment xml:lang="fi">GameCube-levykuva</comment>
<comment xml:lang="fr">image disque GameCube</comment>
+ <comment xml:lang="ga">íomhá diosca GameCube</comment>
<comment xml:lang="gl">Imae de disco de GameCube</comment>
<comment xml:lang="he">דמות כונן GameCube</comment>
<comment xml:lang="hr">GameCube slika diska</comment>
@@ -9495,14 +9753,14 @@
<comment xml:lang="pl">Obraz płyty konsoli GameCube</comment>
<comment xml:lang="pt">imagem de disco GameCube</comment>
<comment xml:lang="pt_BR">Imagem de disco GameCube</comment>
- <comment xml:lang="ru">образ диÑка GameCube</comment>
+ <comment xml:lang="ru">Образ диÑка GameCube</comment>
<comment xml:lang="sk">Obraz disku GameCube</comment>
<comment xml:lang="sl">Odtis diska GameCube</comment>
- <comment xml:lang="sr">Ñлика диÑка Гејм Коцке</comment>
+ <comment xml:lang="sr">одраз диÑка Гејм Коцке</comment>
<comment xml:lang="sv">GameCube-skivavbild</comment>
<comment xml:lang="tr">GameCube disk görüntüsü</comment>
<comment xml:lang="uk">образ диÑка GameCube</comment>
- <comment xml:lang="zh_CN">GameCube光盘镜åƒ</comment>
+ <comment xml:lang="zh_CN">GameCube 光盘映åƒ</comment>
<comment xml:lang="zh_TW">GameCube 光碟映åƒæª”</comment>
<generic-icon name="application-x-executable"/>
<alias type="application/x-gamecube-iso-image"/>
@@ -9513,16 +9771,85 @@
</mime-type>
<mime-type type="application/x-thomson-cartridge-memo7">
<comment>Thomson Mémo7 cartridge</comment>
+ <comment xml:lang="ca">cartutx Thomson Mémo7</comment>
+ <comment xml:lang="cs">Kazeta Thomson Mémo7</comment>
+ <comment xml:lang="de">Thomson-Mémo7-Steckmodul</comment>
+ <comment xml:lang="en_GB">Thomson Mémo7 cartridge</comment>
+ <comment xml:lang="es">cartucho Mémo7 de Thomson</comment>
+ <comment xml:lang="fr">cartouche Thomson Mémo7</comment>
+ <comment xml:lang="ga">cartús Thomson Mémo7</comment>
+ <comment xml:lang="hr">Thomson Mémo7 uložak</comment>
+ <comment xml:lang="hu">Thomson Mémo7 kazetta</comment>
+ <comment xml:lang="id">cartridge Thomson Mémo7</comment>
+ <comment xml:lang="it">Cartuccia Thomson Mémo7</comment>
+ <comment xml:lang="kk">Thomson Mémo7 картриджі</comment>
+ <comment xml:lang="ko">톰슨 메모7 카트릿지</comment>
+ <comment xml:lang="pl">Kartridż Thomson Mémo7</comment>
+ <comment xml:lang="pt_BR">Cartucho Thomson Mémo7</comment>
+ <comment xml:lang="ru">Картридж Thomson Mémo7</comment>
+ <comment xml:lang="sk">Kazeta Thomson Mémo7</comment>
+ <comment xml:lang="sr">ТомÑон Мемо7 кертриџ</comment>
+ <comment xml:lang="sv">Thomson Mémo7-spelkassett</comment>
+ <comment xml:lang="tr">Thomson Mémo7 kartuşu</comment>
+ <comment xml:lang="uk">картридж Thomson Mémo7</comment>
+ <comment xml:lang="zh_CN">Thomson Mémo7 å¡å¸¦</comment>
+ <comment xml:lang="zh_TW">Thomson Mémo7 å¡åŒ£</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.m7"/>
</mime-type>
<mime-type type="application/x-thomson-cassette">
<comment>Thomson cassette</comment>
+ <comment xml:lang="ca">cinta de casset Thomson</comment>
+ <comment xml:lang="cs">Kazeta Thomson</comment>
+ <comment xml:lang="de">Thomson-Kassette</comment>
+ <comment xml:lang="en_GB">Thomson cassette</comment>
+ <comment xml:lang="es">casete de Thomson</comment>
+ <comment xml:lang="fr">cassette Thomson</comment>
+ <comment xml:lang="ga">caiséad Thomson</comment>
+ <comment xml:lang="hr">Thomson kaseta</comment>
+ <comment xml:lang="hu">Thomson kazetta</comment>
+ <comment xml:lang="id">kaset Thomson</comment>
+ <comment xml:lang="it">Cassetta Thomson</comment>
+ <comment xml:lang="kk">Thomson каÑÑетаÑÑ‹</comment>
+ <comment xml:lang="ko">톰슨 카셋트</comment>
+ <comment xml:lang="pl">Kaseta Thomson</comment>
+ <comment xml:lang="pt_BR">Cassete Thomson</comment>
+ <comment xml:lang="ru">КаÑÑета Thomson</comment>
+ <comment xml:lang="sk">Kazeta Thomson</comment>
+ <comment xml:lang="sr">ТомÑон каÑете</comment>
+ <comment xml:lang="sv">Thomson-kassett</comment>
+ <comment xml:lang="tr">Thomson kaset</comment>
+ <comment xml:lang="uk">каÑета Thomson</comment>
+ <comment xml:lang="zh_CN">Thomson ç£å¸¦</comment>
+ <comment xml:lang="zh_TW">Thomson å¡åŒ£</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.k7"/>
</mime-type>
<mime-type type="application/x-hfe-floppy-image">
<comment>HFE floppy disk image</comment>
+ <comment xml:lang="ca">imatge de disquet HFE</comment>
+ <comment xml:lang="cs">Obraz diskety HFE</comment>
+ <comment xml:lang="de">HFE-Diskettenabbild</comment>
+ <comment xml:lang="en_GB">HFE floppy disk image</comment>
+ <comment xml:lang="es">imagen de disquete HFE</comment>
+ <comment xml:lang="fr">image disquette HFE</comment>
+ <comment xml:lang="ga">íomhá diosca fhlapaigh HFE</comment>
+ <comment xml:lang="hr">HFE slika diskete</comment>
+ <comment xml:lang="hu">HFE flopi lemezkép</comment>
+ <comment xml:lang="id">image disk floppy HFE</comment>
+ <comment xml:lang="it">Immagine disco floppy HFE</comment>
+ <comment xml:lang="kk">HFE иілгіш диÑк бейнеÑÑ–</comment>
+ <comment xml:lang="ko">HFE 플로피 ë””ìŠ¤í¬ ì´ë¯¸ì§€</comment>
+ <comment xml:lang="pl">Obraz dyskietki HFE</comment>
+ <comment xml:lang="pt_BR">Imagem de disco flexível HFE</comment>
+ <comment xml:lang="ru">Образ гибкого диÑка HFE</comment>
+ <comment xml:lang="sk">Obraz pružného disku HFE</comment>
+ <comment xml:lang="sr">ХФЕ Ñлика флопи диÑка</comment>
+ <comment xml:lang="sv">HFE-diskavbild</comment>
+ <comment xml:lang="tr">HFE disket kalıbı</comment>
+ <comment xml:lang="uk">образ диÑкети HFE</comment>
+ <comment xml:lang="zh_CN">HFE 软盘映åƒ</comment>
+ <comment xml:lang="zh_TW">HFE 軟碟映åƒæª”</comment>
<acronym>HFE</acronym>
<expanded-acronym>HxC Floppy Emulator</expanded-acronym>
<generic-icon name="application-x-executable"/>
@@ -9530,9 +9857,33 @@
<magic>
<match value="HXCPICFE" type="string" offset="0"/>
</magic>
+ <alias type="application/x-hfe-file"/>
</mime-type>
<mime-type type="application/x-thomson-sap-image">
<comment>SAP Thomson floppy disk image</comment>
+ <comment xml:lang="ca">imatge de disquet SAP Thomson</comment>
+ <comment xml:lang="cs">Obraz diskety SAP Thomson</comment>
+ <comment xml:lang="de">SAP-Thomson-Diskettenabbild</comment>
+ <comment xml:lang="en_GB">SAP Thomson floppy disk image</comment>
+ <comment xml:lang="es">imagen de disquete SAP de Thomson</comment>
+ <comment xml:lang="fr">image disquette SAP Thomson</comment>
+ <comment xml:lang="ga">íomhá diosca fhlapaigh SAP Thomson</comment>
+ <comment xml:lang="hr">SAP Thomson slika diskete</comment>
+ <comment xml:lang="hu">SAP Thomson flopi lemezkép</comment>
+ <comment xml:lang="id">image disk floppy SAP Thomson</comment>
+ <comment xml:lang="it">Immagine disco floppy Thomson SAP</comment>
+ <comment xml:lang="kk">SAP Thomson иілгіш диÑк бейнеÑÑ–</comment>
+ <comment xml:lang="ko">SAP 톰슨 플로피 ë””ìŠ¤í¬ ì´ë¯¸ì§€</comment>
+ <comment xml:lang="pl">Obraz dyskietki SAP Thomson</comment>
+ <comment xml:lang="pt_BR">Imagem de disco flexível SAP Thomson</comment>
+ <comment xml:lang="ru">Образ гибкого диÑка SAP Thomson</comment>
+ <comment xml:lang="sk">Obraz pružného disku SAP Thomson</comment>
+ <comment xml:lang="sr">СÐП ТомÑон Ñлика флопи диÑка</comment>
+ <comment xml:lang="sv">SAP Thomson-diskavbild</comment>
+ <comment xml:lang="tr">SAP Thomson disket kalıbı</comment>
+ <comment xml:lang="uk">образ диÑкети Thomson SAP</comment>
+ <comment xml:lang="zh_CN">SAP Thomson 软盘映åƒ</comment>
+ <comment xml:lang="zh_TW">SAP Thomson 軟碟映åƒæª”</comment>
<acronym>SAP</acronym>
<expanded-acronym>Système d'Archivage Pukall</expanded-acronym>
<generic-icon name="application-x-executable"/>
@@ -9540,6 +9891,7 @@
<magic>
<match value="SYSTEME D'ARCHIVAGE PUKALL S.A.P. (c) Alexandre PUKALL Avril 1998" type="string" offset="1"/>
</magic>
+ <alias type="application/x-sap-file"/>
</mime-type>
<mime-type type="application/vnd.debian.binary-package">
<comment>Debian package</comment>
@@ -9583,7 +9935,7 @@
<comment xml:lang="pt">pacote Debian</comment>
<comment xml:lang="pt_BR">Pacote Debian</comment>
<comment xml:lang="ro">Pachet Debian</comment>
- <comment xml:lang="ru">пакет Debian</comment>
+ <comment xml:lang="ru">Пакет Debian</comment>
<comment xml:lang="sk">BalíÄek Debianu</comment>
<comment xml:lang="sl">Datoteka paketa Debian</comment>
<comment xml:lang="sq">Paketë Debian</comment>
@@ -9644,11 +9996,11 @@
<comment xml:lang="pt">ficheiro do Qt Designer</comment>
<comment xml:lang="pt_BR">Arquivo do Qt Designer</comment>
<comment xml:lang="ro">Fișier Qt Designer</comment>
- <comment xml:lang="ru">файл Qt Designer</comment>
+ <comment xml:lang="ru">Файл Qt Designer</comment>
<comment xml:lang="sk">Súbor Qt Designer</comment>
<comment xml:lang="sl">Datoteka Qt Designer</comment>
<comment xml:lang="sq">File Qt Designer</comment>
- <comment xml:lang="sr">датотека Кут Дизајнера</comment>
+ <comment xml:lang="sr">датотека Кут дизајнера</comment>
<comment xml:lang="sv">Qt Designer-fil</comment>
<comment xml:lang="tr">Qt Tasarımcı dosyası</comment>
<comment xml:lang="uk">файл програми Qt-дизайнер</comment>
@@ -9676,6 +10028,7 @@
<comment xml:lang="eu">Qt Markup lengoai fitxategia</comment>
<comment xml:lang="fi">QML-tiedosto</comment>
<comment xml:lang="fr">fichier Qt Markup Language</comment>
+ <comment xml:lang="ga">comhad teanga mharcála Qt</comment>
<comment xml:lang="gl">ficheiro de linguaxe de marcado Qt</comment>
<comment xml:lang="he">קובץ שפת סימון של Qt</comment>
<comment xml:lang="hr">Qt Markup Language datoteka</comment>
@@ -9692,17 +10045,23 @@
<comment xml:lang="pl">Plik języka znaczników Qt</comment>
<comment xml:lang="pt">ficheiro de linguagem Qt Markup</comment>
<comment xml:lang="pt_BR">Arquivo de Qt Markup Language</comment>
- <comment xml:lang="ru">файл Qt Markup Language</comment>
+ <comment xml:lang="ru">Файл Qt Markup Language</comment>
<comment xml:lang="sk">Súbor znaÄkovacieho jazyka Qt</comment>
<comment xml:lang="sl">Datoteka oznaÄevalnega jezika Qt</comment>
- <comment xml:lang="sr">датотека Кутовог језика означавања</comment>
+ <comment xml:lang="sr">датотека КуТ-овог језика означавања</comment>
<comment xml:lang="sv">Qt-märkspråksfil</comment>
<comment xml:lang="tr">Qt İşaretleme Dili dosyası</comment>
<comment xml:lang="uk">файл мови розмітки Qt</comment>
- <comment xml:lang="zh_CN">Qt </comment>
+ <comment xml:lang="zh_CN">Qt Markup Language 文件</comment>
<comment xml:lang="zh_TW">Qt 標記語言檔</comment>
<magic priority="80">
- <match value="import Qt " type="string" offset="0:256"/>
+ <match value="/bin/env qml" type="string" offset="2:16"/>
+ <match value="import Qt" type="string" offset="0:3000">
+ <match value="{" type="string" offset="9:3009"/>
+ </match>
+ <match value="import Qml" type="string" offset="0:3000">
+ <match value="{" type="string" offset="9:3009"/>
+ </match>
</magic>
<glob pattern="*.qml"/>
<glob pattern="*.qmltypes"/>
@@ -9725,10 +10084,10 @@
<comment xml:lang="fi">työpöydän asetustiedosto</comment>
<comment xml:lang="fo">skriviborðssamansetingarfíla</comment>
<comment xml:lang="fr">fichier de configuration desktop</comment>
- <comment xml:lang="ga">comhad chumraíocht deisce</comment>
+ <comment xml:lang="ga">comhad cumraíochta deisce</comment>
<comment xml:lang="gl">ficheiro de configuración de escritorio</comment>
<comment xml:lang="he">קובץ הגדרות שולחן עבודה</comment>
- <comment xml:lang="hr">datoteka postavki radne površine</comment>
+ <comment xml:lang="hr">Datoteka preÄaca radne povrÅ¡ine</comment>
<comment xml:lang="hu">asztalbeállító fájl</comment>
<comment xml:lang="ia">File de configuration de scriptorio</comment>
<comment xml:lang="id">berkas konfigurasi destop</comment>
@@ -9747,7 +10106,7 @@
<comment xml:lang="pt">ficheiro de configuração de área de trabalho</comment>
<comment xml:lang="pt_BR">Arquivo de configuração desktop</comment>
<comment xml:lang="ro">fișier de configurare al desktopului</comment>
- <comment xml:lang="ru">файл наÑтроек рабочего Ñтола</comment>
+ <comment xml:lang="ru">Файл наÑтроек рабочего Ñтола</comment>
<comment xml:lang="sk">Súbor nastavení pracovnej plochy</comment>
<comment xml:lang="sl">nastavitvena datoteka namizja</comment>
<comment xml:lang="sq">File konfigurimi desktop</comment>
@@ -9774,6 +10133,7 @@
<mime-type type="application/x-fictionbook+xml">
<comment>FictionBook document</comment>
<comment xml:lang="ar">مستند FictionBook</comment>
+ <comment xml:lang="ast">Documentu de FictionBook</comment>
<comment xml:lang="bg">Документ — FictionBook</comment>
<comment xml:lang="ca">document FictionBook</comment>
<comment xml:lang="cs">dokument FictionBook</comment>
@@ -9807,7 +10167,7 @@
<comment xml:lang="pt">documento FictionBook</comment>
<comment xml:lang="pt_BR">Documento FictionBook</comment>
<comment xml:lang="ro">Document FictionBook</comment>
- <comment xml:lang="ru">документ FictionBook</comment>
+ <comment xml:lang="ru">Документ FictionBook</comment>
<comment xml:lang="sk">Dokument FictionBook</comment>
<comment xml:lang="sl">Dokument FictionBook</comment>
<comment xml:lang="sr">документ Фикшон Књиге</comment>
@@ -9827,6 +10187,7 @@
</mime-type>
<mime-type type="application/x-zip-compressed-fb2">
<comment>Compressed FictionBook document</comment>
+ <comment xml:lang="ast">Documentu comprimíu de FictionBook</comment>
<comment xml:lang="ca">document FictionBook amb compressió</comment>
<comment xml:lang="cs">komprimovaný dokument FictionBook</comment>
<comment xml:lang="da">Komprimeret FictionBook-dokument</comment>
@@ -9837,6 +10198,7 @@
<comment xml:lang="eu">Konprimitutako FictionBook dokumentua</comment>
<comment xml:lang="fi">Pakattu FictionBook-asiakirja</comment>
<comment xml:lang="fr">document FictionBook compressé</comment>
+ <comment xml:lang="ga">cáipéis chomhbhrúite FictionBook</comment>
<comment xml:lang="gl">Documento de FictionBook comprimida</comment>
<comment xml:lang="he">מסמך FictionBook מכווץ</comment>
<comment xml:lang="hr">Sažet FictionBook dokument</comment>
@@ -9858,7 +10220,7 @@
<comment xml:lang="tr">Sıkıştırılmış KurguKitap belgesi</comment>
<comment xml:lang="uk">ÑтиÑнений документ FictionBook</comment>
<comment xml:lang="zh_CN">压缩的 FictionBook 文档</comment>
- <comment xml:lang="zh_TW">壓縮的 FictionBook 文件</comment>
+ <comment xml:lang="zh_TW">壓縮版 FictionBook 文件</comment>
<sub-class-of type="application/zip"/>
<glob pattern="*.fb2.zip"/>
<magic priority="70">
@@ -9910,7 +10272,7 @@
<comment xml:lang="pt">diagrama Dia</comment>
<comment xml:lang="pt_BR">Diagrama do Dia</comment>
<comment xml:lang="ro">Diagramă Dia</comment>
- <comment xml:lang="ru">диаграмма Dia</comment>
+ <comment xml:lang="ru">Диаграмма Dia</comment>
<comment xml:lang="sk">Diagram Dia</comment>
<comment xml:lang="sl">Datoteka diagrama Dia</comment>
<comment xml:lang="sq">Diagramë Dia</comment>
@@ -9963,7 +10325,7 @@
<comment xml:lang="pt">forma Dia</comment>
<comment xml:lang="pt_BR">Formato Dia</comment>
<comment xml:lang="ro">Figură Dia</comment>
- <comment xml:lang="ru">фигура Dia</comment>
+ <comment xml:lang="ru">Фигура Dia</comment>
<comment xml:lang="sk">Tvar Dia</comment>
<comment xml:lang="sl">Datoteka oblik Dia</comment>
<comment xml:lang="sr">облик Дие</comment>
@@ -9983,6 +10345,7 @@
<mime-type type="application/x-dvi">
<comment>TeX DVI document</comment>
<comment xml:lang="ar">مستند TeX DVI</comment>
+ <comment xml:lang="ast">Documentu Tex DVI</comment>
<comment xml:lang="be@latin">Dakument TeX DVI</comment>
<comment xml:lang="bg">Документ — TeX DVI</comment>
<comment xml:lang="ca">document DVI de TeX</comment>
@@ -10019,7 +10382,7 @@
<comment xml:lang="pt">documento TeX DVI</comment>
<comment xml:lang="pt_BR">Documento DVI TeX</comment>
<comment xml:lang="ro">Document Tex DVI</comment>
- <comment xml:lang="ru">документ TeX DVI</comment>
+ <comment xml:lang="ru">Документ TeX DVI</comment>
<comment xml:lang="sk">Dokument TeX DVI</comment>
<comment xml:lang="sl">Dokument TeX DVI</comment>
<comment xml:lang="sq">Dokument TeX DVI</comment>
@@ -10080,11 +10443,11 @@
<comment xml:lang="pt">tema Enlightenment</comment>
<comment xml:lang="pt_BR">Tema do Enlightenment</comment>
<comment xml:lang="ro">Temă Enlightenment</comment>
- <comment xml:lang="ru">тема Enlightenment</comment>
+ <comment xml:lang="ru">Тема Enlightenment</comment>
<comment xml:lang="sk">Motív Enlightenment</comment>
<comment xml:lang="sl">Datoteka teme Enlightenment</comment>
<comment xml:lang="sq">Tema Enlightenment</comment>
- <comment xml:lang="sr">тема ПроÑвећеноÑти</comment>
+ <comment xml:lang="sr">тема за Енлајтмент</comment>
<comment xml:lang="sv">Enlightenment-tema</comment>
<comment xml:lang="tr">Enlightenment teması</comment>
<comment xml:lang="uk">тема Enlightenment</comment>
@@ -10133,7 +10496,7 @@
<comment xml:lang="pt">animação Egon Animator</comment>
<comment xml:lang="pt_BR">Animação do Egon Animator</comment>
<comment xml:lang="ro">Animație Egon Animator</comment>
- <comment xml:lang="ru">Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ñ Egon Animator</comment>
+ <comment xml:lang="ru">ÐÐ½Ð¸Ð¼Ð°Ñ†Ð¸Ñ Egon Animator</comment>
<comment xml:lang="sk">Animácia Egon Animator</comment>
<comment xml:lang="sl">Datoteka animacije Egon Animator</comment>
<comment xml:lang="sq">Animim Egon Animator</comment>
@@ -10167,7 +10530,7 @@
<comment xml:lang="ga">comhad inrite</comment>
<comment xml:lang="gl">executábel</comment>
<comment xml:lang="he">קובץ הרצה</comment>
- <comment xml:lang="hr">izvršna datoteka</comment>
+ <comment xml:lang="hr">Izvršna datoteka</comment>
<comment xml:lang="hu">futtatható</comment>
<comment xml:lang="ia">Executabile</comment>
<comment xml:lang="id">dapat dieksekusi</comment>
@@ -10186,7 +10549,7 @@
<comment xml:lang="pt">executável</comment>
<comment xml:lang="pt_BR">Executável</comment>
<comment xml:lang="ro">executabil</comment>
- <comment xml:lang="ru">иÑполнÑемый</comment>
+ <comment xml:lang="ru">ИÑполнÑемый</comment>
<comment xml:lang="sk">Spustiteľný súbor</comment>
<comment xml:lang="sl">izvedljiva datoteka</comment>
<comment xml:lang="sq">I ekzekutueshëm</comment>
@@ -10254,7 +10617,7 @@
<comment xml:lang="pt">ficheiro FLTK Fluid</comment>
<comment xml:lang="pt_BR">Arquivo Fluid do FLTK</comment>
<comment xml:lang="ro">Fișier FLTK Fluid</comment>
- <comment xml:lang="ru">файл FLTK Fluid</comment>
+ <comment xml:lang="ru">Файл FLTK Fluid</comment>
<comment xml:lang="sk">Súbor FLTK Fluid</comment>
<comment xml:lang="sl">Datoteka FLTK Fluid</comment>
<comment xml:lang="sq">File FLTK Fluid</comment>
@@ -10274,10 +10637,11 @@
</magic>
<glob pattern="*.fl"/>
</mime-type>
- <mime-type type="application/font-woff">
+ <mime-type type="font/woff">
<comment>WOFF font</comment>
- <comment xml:lang="ca">tipus de lletra WOFF</comment>
- <comment xml:lang="cs">písmo WOFF</comment>
+ <comment xml:lang="ast">Fonte WOFF</comment>
+ <comment xml:lang="ca">lletra WOFF</comment>
+ <comment xml:lang="cs">font WOFF</comment>
<comment xml:lang="da">WOFF-skrifttype</comment>
<comment xml:lang="de">WOFF-Schrift</comment>
<comment xml:lang="el">ΓÏαμματοσειÏά WOFF</comment>
@@ -10286,13 +10650,14 @@
<comment xml:lang="eu">WOFF letra-tipoa</comment>
<comment xml:lang="fi">WOFF-fontti</comment>
<comment xml:lang="fr">police WOFF</comment>
+ <comment xml:lang="ga">cló WOFF</comment>
<comment xml:lang="gl">Tipo de letra WOFF</comment>
<comment xml:lang="he">גופן WOFF</comment>
<comment xml:lang="hr">WOFF slovo</comment>
<comment xml:lang="hu">WOFF-betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras WOFF</comment>
<comment xml:lang="id">Fonta WOFF</comment>
- <comment xml:lang="it">Font WOFF</comment>
+ <comment xml:lang="it">Carattere WOFF</comment>
<comment xml:lang="ja">WOFF フォント</comment>
<comment xml:lang="kk">WOFF қарібі</comment>
<comment xml:lang="ko">WOFF 글꼴</comment>
@@ -10301,7 +10666,7 @@
<comment xml:lang="pl">Czcionka WOFF</comment>
<comment xml:lang="pt">letra WOFF</comment>
<comment xml:lang="pt_BR">Fonte WOFF</comment>
- <comment xml:lang="ru">шрифт WOFF</comment>
+ <comment xml:lang="ru">Шрифт WOFF</comment>
<comment xml:lang="sk">Písmo WOFF</comment>
<comment xml:lang="sl">Pisava WOFF</comment>
<comment xml:lang="sr">ВОФФ Ñлова</comment>
@@ -10317,55 +10682,65 @@
<match value="0x774f4646" type="big32" offset="0"/>
</magic>
<glob pattern="*.woff"/>
+ <alias type="application/font-woff"/>
+ </mime-type>
+ <mime-type type="font/woff">
+ <comment>WOFF2 font</comment>
+ <comment xml:lang="ast">Fonte WOFF2</comment>
+ <comment xml:lang="ca">lletra WOFF2</comment>
+ <comment xml:lang="cs">font WOFF2</comment>
+ <comment xml:lang="de">WOFF2-Schrift</comment>
+ <comment xml:lang="en_GB">WOFF2 font</comment>
+ <comment xml:lang="es">tipo de letra WOFF2</comment>
+ <comment xml:lang="fi">WOFF2-fontti</comment>
+ <comment xml:lang="hr">WOFF2 slovo</comment>
+ <comment xml:lang="hu">WOFF2 betűkészlet</comment>
+ <comment xml:lang="id">Fonta WOFF2</comment>
+ <comment xml:lang="it">Carattere WOFF2</comment>
+ <comment xml:lang="kk">WOFF2 қарібі</comment>
+ <comment xml:lang="ko">WOFF2 글꼴</comment>
+ <comment xml:lang="pl">Czcionka WOFF2</comment>
+ <comment xml:lang="pt_BR">Fonte WOFF2</comment>
+ <comment xml:lang="ru">Шрифт WOFF2</comment>
+ <comment xml:lang="sk">Písmo WOFF2</comment>
+ <comment xml:lang="sv">WOFF2-typsnitt</comment>
+ <comment xml:lang="uk">шрифт WOFF2</comment>
+ <comment xml:lang="zh_CN">WOFF2 字体</comment>
+ <comment xml:lang="zh_TW">WOFF2 å­—åž‹</comment>
+ <acronym>WOFF2</acronym>
+ <expanded-acronym>Web Open Font Format 2.0</expanded-acronym>
+ <generic-icon name="font-x-generic"/>
+ <magic priority="50">
+ <match value="0x774f4632" type="big32" offset="0"/>
+ </magic>
+ <glob pattern="*.woff2"/>
</mime-type>
<mime-type type="application/x-font-type1">
- <comment>Postscript type-1 font</comment>
- <comment xml:lang="ar">خط Postscript type-1</comment>
- <comment xml:lang="be@latin">Å ryft Postscript type-1</comment>
- <comment xml:lang="bg">Шрифт — Postscript Type 1</comment>
- <comment xml:lang="ca">tipus de lletra Postscript type-1</comment>
- <comment xml:lang="cs">písmo Postscript type-1</comment>
- <comment xml:lang="da">PostScript type-1-skrifttype</comment>
- <comment xml:lang="de">Postscript-Typ-1-Schrift</comment>
- <comment xml:lang="el">ΓÏαμματοσειÏά Postscript type-1</comment>
- <comment xml:lang="en_GB">Postscript type-1 font</comment>
+ <comment>PostScript type-1 font</comment>
+ <comment xml:lang="ca">lletra type-1 de PostScript</comment>
+ <comment xml:lang="cs">font PostScript type-1</comment>
+ <comment xml:lang="de">PostScript-Typ-1-Schrift</comment>
+ <comment xml:lang="en_GB">PostScript type-1 font</comment>
<comment xml:lang="es">tipo de letra PostScript Type-1</comment>
<comment xml:lang="eu">PostScript type-1 letra-tipoa</comment>
- <comment xml:lang="fi">PostScript tyyppi-1 -fontti</comment>
- <comment xml:lang="fo">Postscript type-1 stavasnið</comment>
- <comment xml:lang="fr">police Postscript Type 1</comment>
- <comment xml:lang="ga">cló Postscript type-1</comment>
- <comment xml:lang="gl">tipo de letra PostScript tipo-1</comment>
- <comment xml:lang="he">גופן של Postscript type-1</comment>
- <comment xml:lang="hr">Postscript crsta-1 slovo</comment>
- <comment xml:lang="hu">Postscript type-1 betűkészlet</comment>
- <comment xml:lang="ia">Typo de litteras PostScript typo 1</comment>
- <comment xml:lang="id">Fonta tipe-1 Postscript</comment>
- <comment xml:lang="it">Carattere Postscript type-1</comment>
- <comment xml:lang="ja">PostScript type-1 フォント</comment>
- <comment xml:lang="kk">Postscript type-1 қарібі</comment>
+ <comment xml:lang="fr">police PostScript Type 1</comment>
+ <comment xml:lang="ga">cló PostScript type-1</comment>
+ <comment xml:lang="hr">PostScript type-1 slovo</comment>
+ <comment xml:lang="hu">PostScript type-1 betűkészlet</comment>
+ <comment xml:lang="id">fonta PostScript type-1</comment>
+ <comment xml:lang="it">Carattere PostScript type-1</comment>
+ <comment xml:lang="kk">PostScript type-1 қарібі</comment>
<comment xml:lang="ko">PostScript Type-1 글꼴</comment>
- <comment xml:lang="lt">Postscript type-1 Å¡riftas</comment>
- <comment xml:lang="lv">Postscript 1-tipa fonts</comment>
- <comment xml:lang="nb">Postscript type-1 skrift</comment>
- <comment xml:lang="nl">PostScript type-1-lettertype</comment>
- <comment xml:lang="nn">PostScript type 1-skrifttype</comment>
- <comment xml:lang="oc">poliça Postescript Type 1</comment>
<comment xml:lang="pl">Czcionka PostScript Type-1</comment>
- <comment xml:lang="pt">letra PostScript tipo 1</comment>
<comment xml:lang="pt_BR">Fonte PostScript tipo-1</comment>
- <comment xml:lang="ro">Font Postscript type-1</comment>
- <comment xml:lang="ru">шрифт PostScript Type-1</comment>
- <comment xml:lang="sk">Písmo Postscript type-1</comment>
- <comment xml:lang="sl">Datoteka pisave Postscript vrste-1</comment>
- <comment xml:lang="sq">Lloj gërmash Postscript type-1</comment>
+ <comment xml:lang="ru">Шрифт PostScript Type-1</comment>
+ <comment xml:lang="sk">Písmo PostScript typu 1</comment>
<comment xml:lang="sr">Ñлова ПоÑÑ‚Ñкрипта врÑте-1</comment>
- <comment xml:lang="sv">Postscript type-1-typsnitt</comment>
- <comment xml:lang="tr">Postscript type-1 yazı tipi</comment>
- <comment xml:lang="uk">шрифт Postscript type-1</comment>
- <comment xml:lang="vi">Phông kiểu 1 PostScript</comment>
- <comment xml:lang="zh_CN">Postscript type-1 字体</comment>
- <comment xml:lang="zh_TW">Postscript type-1 å­—åž‹</comment>
+ <comment xml:lang="sv">PostScript type-1-typsnitt</comment>
+ <comment xml:lang="tr">PostScript tip-1 yazı tipi</comment>
+ <comment xml:lang="uk">шрифт type-1 PostScript</comment>
+ <comment xml:lang="zh_CN">PostScript type-1 字体</comment>
+ <comment xml:lang="zh_TW">PostScript type-1 å­—åž‹</comment>
<sub-class-of type="application/postscript"/>
<generic-icon name="font-x-generic"/>
<magic priority="60">
@@ -10386,8 +10761,8 @@
<comment xml:lang="az">Adobe yazı növü metrikləri</comment>
<comment xml:lang="be@latin">Metryka Å¡ryftu Adobe</comment>
<comment xml:lang="bg">Шрифтова метрика — Adobe</comment>
- <comment xml:lang="ca">mètrica de tipus de lletra Adobe</comment>
- <comment xml:lang="cs">metrika písma Adobe</comment>
+ <comment xml:lang="ca">mètrica de lletra d'Adobe</comment>
+ <comment xml:lang="cs">metrika fontu Adobe</comment>
<comment xml:lang="cy">Metrigau Ffont Adobe</comment>
<comment xml:lang="da">Adobe skrifttypefil</comment>
<comment xml:lang="de">Adobe-Schriftmetriken</comment>
@@ -10401,7 +10776,7 @@
<comment xml:lang="ga">meadarachtaí cló Adobe</comment>
<comment xml:lang="gl">métricas de fonte de Adobe</comment>
<comment xml:lang="he">מדדי גופן של Adobe</comment>
- <comment xml:lang="hr">Adobe mjere fonta</comment>
+ <comment xml:lang="hr">Adobe mjere slova</comment>
<comment xml:lang="hu">Adobe-betűmetrika</comment>
<comment xml:lang="ia">Metricas de typo de litteras Adobe</comment>
<comment xml:lang="id">Metrik fonta Adobe</comment>
@@ -10420,7 +10795,7 @@
<comment xml:lang="pt">métrica de letras Adobe</comment>
<comment xml:lang="pt_BR">Métricas de fonte Adobe</comment>
<comment xml:lang="ro">Dimensiuni font Adobe</comment>
- <comment xml:lang="ru">метрика шрифта Adobe</comment>
+ <comment xml:lang="ru">Метрика шрифта Adobe</comment>
<comment xml:lang="sk">Metrika písma Adobe</comment>
<comment xml:lang="sl">Matrika pisave Adobe</comment>
<comment xml:lang="sq">Metrik lloj gërmash Adobe</comment>
@@ -10429,7 +10804,7 @@
<comment xml:lang="tr">Adobe yazıtipi ölçüleri</comment>
<comment xml:lang="uk">метрики шрифту Adobe</comment>
<comment xml:lang="vi">Cách đo phông chữ Adobe</comment>
- <comment xml:lang="zh_CN">Adobe 字体å‚æ•°</comment>
+ <comment xml:lang="zh_CN">Adobe 字体规格</comment>
<comment xml:lang="zh_TW">Adobe å­—åž‹æ述檔</comment>
<generic-icon name="font-x-generic"/>
<glob pattern="*.afm"/>
@@ -10440,8 +10815,8 @@
<comment xml:lang="az">BDF yazı növü</comment>
<comment xml:lang="be@latin">Å ryft BDF</comment>
<comment xml:lang="bg">Шрифт — BDF</comment>
- <comment xml:lang="ca">tipus de lletra BDF</comment>
- <comment xml:lang="cs">písmo BDF</comment>
+ <comment xml:lang="ca">lletra BDF</comment>
+ <comment xml:lang="cs">font BDF</comment>
<comment xml:lang="cy">Ffont BDF</comment>
<comment xml:lang="da">BDF-skrifttype</comment>
<comment xml:lang="de">BDF-Schrift</comment>
@@ -10456,7 +10831,7 @@
<comment xml:lang="ga">cló BDF</comment>
<comment xml:lang="gl">tipo de fonte BDF</comment>
<comment xml:lang="he">גופן BDF</comment>
- <comment xml:lang="hr">BDF font</comment>
+ <comment xml:lang="hr">BDF slovo</comment>
<comment xml:lang="hu">BDF-betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras BDF</comment>
<comment xml:lang="id">Fonta BDF</comment>
@@ -10475,7 +10850,7 @@
<comment xml:lang="pt">letra BDF</comment>
<comment xml:lang="pt_BR">Fonte BDF</comment>
<comment xml:lang="ro">Font BDF</comment>
- <comment xml:lang="ru">шрифт BDF</comment>
+ <comment xml:lang="ru">Шрифт BDF</comment>
<comment xml:lang="sk">Písmo BDF</comment>
<comment xml:lang="sl">Datoteka pisave BDF</comment>
<comment xml:lang="sq">Lloj gërme BDF</comment>
@@ -10498,8 +10873,8 @@
<comment xml:lang="az">DOS yazı növü</comment>
<comment xml:lang="be@latin">Å ryft DOS</comment>
<comment xml:lang="bg">Шрифт — DOS</comment>
- <comment xml:lang="ca">tipus de lletra DOS</comment>
- <comment xml:lang="cs">písmo pro DOS</comment>
+ <comment xml:lang="ca">lletra DOS</comment>
+ <comment xml:lang="cs">font pro DOS</comment>
<comment xml:lang="cy">Ffont DOS</comment>
<comment xml:lang="da">DOS-skrifttype</comment>
<comment xml:lang="de">DOS-Schrift</comment>
@@ -10514,7 +10889,7 @@
<comment xml:lang="ga">cló DOS</comment>
<comment xml:lang="gl">tipo de fonte de DOS</comment>
<comment xml:lang="he">גופן DOS</comment>
- <comment xml:lang="hr">DOS font</comment>
+ <comment xml:lang="hr">DOS slovo</comment>
<comment xml:lang="hu">DOS-betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras DOS</comment>
<comment xml:lang="id">Fonta DOS</comment>
@@ -10533,7 +10908,7 @@
<comment xml:lang="pt">letra DOS</comment>
<comment xml:lang="pt_BR">Fonte do DOS</comment>
<comment xml:lang="ro">Font DOS</comment>
- <comment xml:lang="ru">шрифт DOS</comment>
+ <comment xml:lang="ru">Шрифт DOS</comment>
<comment xml:lang="sk">Písmo pre DOS</comment>
<comment xml:lang="sl">Datoteka pisave DOS</comment>
<comment xml:lang="sq">Gërmë DOS</comment>
@@ -10557,8 +10932,8 @@
<comment xml:lang="az">Adobe FrameMaker yazı növü</comment>
<comment xml:lang="be@latin">Å ryft Adobe FrameMaker</comment>
<comment xml:lang="bg">Шрифт — Adobe FrameMaker</comment>
- <comment xml:lang="ca">tipus de lletra d'Adobe FrameMaker</comment>
- <comment xml:lang="cs">písmo Adobe FrameMaker</comment>
+ <comment xml:lang="ca">lletra d'Adobe FrameMaker</comment>
+ <comment xml:lang="cs">font Adobe FrameMaker</comment>
<comment xml:lang="cy">Ffont Adobe FrameMaker</comment>
<comment xml:lang="da">Adobe FrameMaker-skrifttype</comment>
<comment xml:lang="de">Adobe-FrameMaker-Schrift</comment>
@@ -10573,7 +10948,7 @@
<comment xml:lang="ga">cló Adobe FrameMaker</comment>
<comment xml:lang="gl">tipo de fonte de Adobe FrameMaker</comment>
<comment xml:lang="he">גופן של Adobe FrameMaker</comment>
- <comment xml:lang="hr">Adobe FrameMaker font</comment>
+ <comment xml:lang="hr">Adobe FrameMaker slovo</comment>
<comment xml:lang="hu">Adobe FrameMaker-betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras pro Adobe FrameMaker</comment>
<comment xml:lang="id">Fonta Adobe FrameMaker</comment>
@@ -10592,7 +10967,7 @@
<comment xml:lang="pt">letra Adobe FrameMaker</comment>
<comment xml:lang="pt_BR">Fonte do Adobe FrameMaker</comment>
<comment xml:lang="ro">Font Adobe FrameMaker</comment>
- <comment xml:lang="ru">шрифт Adobe FrameMaker</comment>
+ <comment xml:lang="ru">Шрифт Adobe FrameMaker</comment>
<comment xml:lang="sk">Písmo Adobe FrameMaker</comment>
<comment xml:lang="sl">Datoteka pisave Adobe FrameMaker</comment>
<comment xml:lang="sq">Gërma Adobe FrameMaker</comment>
@@ -10614,8 +10989,8 @@
<comment xml:lang="az">LIBGRX yazı növü</comment>
<comment xml:lang="be@latin">Å ryft LIBGRX</comment>
<comment xml:lang="bg">Шрифт — LIBGRX</comment>
- <comment xml:lang="ca">tipus de lletra LIBGRX</comment>
- <comment xml:lang="cs">písmo LIBGRX</comment>
+ <comment xml:lang="ca">lletra LIBGRX</comment>
+ <comment xml:lang="cs">font LIBGRX</comment>
<comment xml:lang="cy">Ffont LIBGRX</comment>
<comment xml:lang="da">LIBGRX-skrifttype</comment>
<comment xml:lang="de">LIBGRX-Schrift</comment>
@@ -10630,7 +11005,7 @@
<comment xml:lang="ga">cló LIBGRX</comment>
<comment xml:lang="gl">tipo de fonte en LIBGRX</comment>
<comment xml:lang="he">גופן LIBGRX</comment>
- <comment xml:lang="hr">LIBGRX font</comment>
+ <comment xml:lang="hr">LIBGRX slovo</comment>
<comment xml:lang="hu">LIBGRX-betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras LIBGRX</comment>
<comment xml:lang="id">Fonta LIBGRX</comment>
@@ -10649,7 +11024,7 @@
<comment xml:lang="pt">letra LIBGRX</comment>
<comment xml:lang="pt_BR">Fonte LIBGRX</comment>
<comment xml:lang="ro">Font LIBGRX</comment>
- <comment xml:lang="ru">шрифт LIBGRX</comment>
+ <comment xml:lang="ru">Шрифт LIBGRX</comment>
<comment xml:lang="sk">Písmo LIBGRX</comment>
<comment xml:lang="sl">Datoteka pisave LIBGRX</comment>
<comment xml:lang="sq">Lloj gërme LIBGRX</comment>
@@ -10671,8 +11046,8 @@
<comment xml:lang="az">Linux PSF konsol yazı növü</comment>
<comment xml:lang="be@latin">Kansolny Å¡ryft PSF dla Linuksa</comment>
<comment xml:lang="bg">Шрифт — PSF, за конзолата на ЛинукÑ</comment>
- <comment xml:lang="ca">tipus de lletra de consola Linux PSF</comment>
- <comment xml:lang="cs">písmo PSF pro konzolu Linuxu</comment>
+ <comment xml:lang="ca">lletra de consola PSF de Linux</comment>
+ <comment xml:lang="cs">font PSF pro konzolu Linuxu</comment>
<comment xml:lang="cy">Ffont Linux PSF</comment>
<comment xml:lang="da">Linux PSF-konsolskrifttype</comment>
<comment xml:lang="de">Linux-PSF-Konsolenschrift</comment>
@@ -10684,10 +11059,10 @@
<comment xml:lang="fi">Linux PSF -konsolifontti</comment>
<comment xml:lang="fo">Linux PSF stýristøðs stavasnið</comment>
<comment xml:lang="fr">police console Linux PSF</comment>
- <comment xml:lang="ga">cló chonsól Linux PSF</comment>
+ <comment xml:lang="ga">cló consóil Linux PSF</comment>
<comment xml:lang="gl">tipo de fonte de consola Linux PSF</comment>
<comment xml:lang="he">גופן לקונסול מסוג Linux PSF</comment>
- <comment xml:lang="hr">Linux PSF konzolni font</comment>
+ <comment xml:lang="hr">Linux PSF konzolno slovo</comment>
<comment xml:lang="hu">Linux PSF konzolos betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras console Linux PSF</comment>
<comment xml:lang="id">Fonta konsol Linux PSF</comment>
@@ -10706,7 +11081,7 @@
<comment xml:lang="pt">letra de consola Linux PSF</comment>
<comment xml:lang="pt_BR">Fonte de console Linux PSF</comment>
<comment xml:lang="ro">Font consolă Linux PSF</comment>
- <comment xml:lang="ru">конÑольный шрифт Linux PSF</comment>
+ <comment xml:lang="ru">КонÑольный шрифт Linux PSF</comment>
<comment xml:lang="sk">Písmo PSF pre konzolu Linuxu</comment>
<comment xml:lang="sl">Datoteka pisave konzole Linux PSF</comment>
<comment xml:lang="sq">Lloj gërme për konsolë Linux PSF</comment>
@@ -10728,8 +11103,8 @@
<comment xml:lang="ar">خط كونسول PSF لينكس (مضغوط-gzip)</comment>
<comment xml:lang="be@latin">Kansolny Å¡ryft PSF dla Linuksa (gzip-skampresavany)</comment>
<comment xml:lang="bg">Шрифт — Linux PSF, компреÑиран Ñ gzip</comment>
- <comment xml:lang="ca">tipus de lletra de consola Linux PSF (amb compressió gzip)</comment>
- <comment xml:lang="cs">písmo PSF pro konzolu Linuxu (komprimované pomocí gzip)</comment>
+ <comment xml:lang="ca">lletra de consola PSF de Linux (amb compressió gzip)</comment>
+ <comment xml:lang="cs">font PSF pro konzolu Linuxu (komprimace gzip)</comment>
<comment xml:lang="da">Linux PSF-konsolskrifttype (gzip-komprimeret)</comment>
<comment xml:lang="de">Linux-PSF-Konsolenschrift (gzip-komprimiert)</comment>
<comment xml:lang="el">ΓÏαμματοσειÏά κονσόλας PSF Linux (συμπιεσμένη με gzip)</comment>
@@ -10739,10 +11114,10 @@
<comment xml:lang="fi">Linux PSF -konsolifontti (gzip-pakattu)</comment>
<comment xml:lang="fo">Linux PSF stýristøðs stavasnið (gzip-stappað)</comment>
<comment xml:lang="fr">police console Linux PSF (compressée gzip)</comment>
- <comment xml:lang="ga">cló chonsól Linux PSF (comhbhrúite le gzip)</comment>
+ <comment xml:lang="ga">cló consóil Linux PSF (comhbhrúite le gzip)</comment>
<comment xml:lang="gl">tipo de fonte de consola Linux PSF (comprimida con gzip)</comment>
<comment xml:lang="he">גופן למסוף מסוג Linux PSF (מכווץ ע״י gzip)</comment>
- <comment xml:lang="hr">Linux PSF konzolni font (komprimiran gzip-om)</comment>
+ <comment xml:lang="hr">Linux PSF konzolno slovo (gzip sažeto)</comment>
<comment xml:lang="hu">Linux PSF konzolos betűkészlet (gzip-tömörítésű)</comment>
<comment xml:lang="ia">Typo de litteras console Linux PSF (comprimite con gzip)</comment>
<comment xml:lang="id">Fonta konsol Linux PSF (terkompresi gzip)</comment>
@@ -10760,7 +11135,7 @@
<comment xml:lang="pt">letra de consola Linux PSF (compressão gzip)</comment>
<comment xml:lang="pt_BR">Fonte de console Linux PSF (compactada com gzip)</comment>
<comment xml:lang="ro">Font consolă Linux PSF (compresie gzip)</comment>
- <comment xml:lang="ru">конÑольный шрифт Linux PSF (Ñжатый gzip)</comment>
+ <comment xml:lang="ru">КонÑольный шрифт Linux PSF (Ñжатый gzip)</comment>
<comment xml:lang="sk">Písmo PSF pre konzolu Linuxu (komprimované pomocou gzip)</comment>
<comment xml:lang="sl">Datoteka pisave konzole Linux PSF (skrÄena z gzip)</comment>
<comment xml:lang="sq">Lloj gërme për konsolë Linux PSF (komresuar me gzip)</comment>
@@ -10769,7 +11144,7 @@
<comment xml:lang="tr">Linux PSF konsol fontu (gzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">конÑольний шрифт Linux PSF (ÑтиÑнений gzip)</comment>
<comment xml:lang="vi">Phông chữ bàn giao tiếp PSF Linux (đã nén gzip)</comment>
- <comment xml:lang="zh_CN">Linux PSF 控制å°å­—体(gzip 压缩)</comment>
+ <comment xml:lang="zh_CN">Linux PSF 控制å°å­—体(gzip 压缩)</comment>
<comment xml:lang="zh_TW">Linux PSF console å­—åž‹ (gzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="font-x-generic"/>
@@ -10781,8 +11156,8 @@
<comment xml:lang="az">PCF yazı növü</comment>
<comment xml:lang="be@latin">Å ryft PCF</comment>
<comment xml:lang="bg">Шрифт — PCF</comment>
- <comment xml:lang="ca">tipus de lletra PCF</comment>
- <comment xml:lang="cs">písmo PCF</comment>
+ <comment xml:lang="ca">lletra PCF</comment>
+ <comment xml:lang="cs">font PCF</comment>
<comment xml:lang="cy">Ffont PCF</comment>
<comment xml:lang="da">PCF-skrifttype</comment>
<comment xml:lang="de">PCF-Schrift</comment>
@@ -10816,7 +11191,7 @@
<comment xml:lang="pt">letra PCF</comment>
<comment xml:lang="pt_BR">Fonte PCF</comment>
<comment xml:lang="ro">Font PCF</comment>
- <comment xml:lang="ru">шрифт PCF</comment>
+ <comment xml:lang="ru">Шрифт PCF</comment>
<comment xml:lang="sk">Písmo PCF</comment>
<comment xml:lang="sl">Datoteka pisave PCF</comment>
<comment xml:lang="sq">Gërma PCF</comment>
@@ -10835,14 +11210,14 @@
<glob pattern="*.pcf.Z"/>
<glob pattern="*.pcf.gz"/>
</mime-type>
- <mime-type type="application/x-font-otf">
+ <mime-type type="font/otf">
<comment>OpenType font</comment>
<comment xml:lang="ar">خط OpenType</comment>
<comment xml:lang="az">OpenType yazı növü</comment>
<comment xml:lang="be@latin">Å ryft OpenType</comment>
<comment xml:lang="bg">Шрифт — OpenType</comment>
- <comment xml:lang="ca">tipus de lletra OpenType</comment>
- <comment xml:lang="cs">písmo OpenType</comment>
+ <comment xml:lang="ca">lletra OpenType</comment>
+ <comment xml:lang="cs">font OpenType</comment>
<comment xml:lang="cy">Ffont OpenType</comment>
<comment xml:lang="da">OpenType-skrifttype</comment>
<comment xml:lang="de">OpenType-Schrift</comment>
@@ -10876,7 +11251,7 @@
<comment xml:lang="pt">letra OpenType</comment>
<comment xml:lang="pt_BR">Fonte OpenType</comment>
<comment xml:lang="ro">Font OpenType</comment>
- <comment xml:lang="ru">шрифт OpenType</comment>
+ <comment xml:lang="ru">Шрифт OpenType</comment>
<comment xml:lang="sk">Písmo OpenType</comment>
<comment xml:lang="sl">Datoteka pisave OpenType</comment>
<comment xml:lang="sq">Gërma OpenType</comment>
@@ -10887,12 +11262,13 @@
<comment xml:lang="vi">Phông chữ OpenType</comment>
<comment xml:lang="zh_CN">OpenType 字体</comment>
<comment xml:lang="zh_TW">OpenType å­—åž‹</comment>
- <sub-class-of type="application/x-font-ttf"/>
+ <sub-class-of type="font/ttf"/>
<generic-icon name="font-x-generic"/>
<magic priority="50">
<match value="OTTO" type="string" offset="0"/>
</magic>
<glob pattern="*.otf"/>
+ <alias type="application/x-font-otf"/>
</mime-type>
<mime-type type="application/x-font-speedo">
<comment>Speedo font</comment>
@@ -10900,8 +11276,8 @@
<comment xml:lang="az">Speedo yazı növü</comment>
<comment xml:lang="be@latin">Å ryft Speedo</comment>
<comment xml:lang="bg">Шрифт — Speedo</comment>
- <comment xml:lang="ca">tipus de lletra Speedo</comment>
- <comment xml:lang="cs">písmo Speedo</comment>
+ <comment xml:lang="ca">lletra Speedo</comment>
+ <comment xml:lang="cs">font Speedo</comment>
<comment xml:lang="cy">Ffont Speedo</comment>
<comment xml:lang="da">Speedoskrifttype</comment>
<comment xml:lang="de">Speedo-Schrift</comment>
@@ -10916,7 +11292,7 @@
<comment xml:lang="ga">cló Speedo</comment>
<comment xml:lang="gl">tipo de letra Speedo</comment>
<comment xml:lang="he">גופן של Speedo</comment>
- <comment xml:lang="hr">Speedo font</comment>
+ <comment xml:lang="hr">Speedo slovo</comment>
<comment xml:lang="hu">Speedo-betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras Speedo</comment>
<comment xml:lang="id">Fonta Speedo</comment>
@@ -10935,7 +11311,7 @@
<comment xml:lang="pt">letra Speedo</comment>
<comment xml:lang="pt_BR">Fonte Speedo</comment>
<comment xml:lang="ro">Font Speedo</comment>
- <comment xml:lang="ru">шрифт Speedo</comment>
+ <comment xml:lang="ru">Шрифт Speedo</comment>
<comment xml:lang="sk">Písmo Speedo</comment>
<comment xml:lang="sl">Datoteka pisave Speedo</comment>
<comment xml:lang="sq">Gërma Speedo</comment>
@@ -10958,8 +11334,8 @@
<comment xml:lang="az">SunOS News yazı növü</comment>
<comment xml:lang="be@latin">Å ryft SunOS News</comment>
<comment xml:lang="bg">Шрифт — SunOS News</comment>
- <comment xml:lang="ca">tipus de lletra SunOS News</comment>
- <comment xml:lang="cs">písmo SunOS News</comment>
+ <comment xml:lang="ca">lletra News de SunOS</comment>
+ <comment xml:lang="cs">font SunOS News</comment>
<comment xml:lang="cy">Ffont SunOS News</comment>
<comment xml:lang="da">SunOS News-skrifttype</comment>
<comment xml:lang="de">SunOS-News-Schrift</comment>
@@ -10974,7 +11350,7 @@
<comment xml:lang="ga">cló SunOS News</comment>
<comment xml:lang="gl">tipo de letra SunOS News</comment>
<comment xml:lang="he">גופן של SunOS News</comment>
- <comment xml:lang="hr">SunOS News font</comment>
+ <comment xml:lang="hr">SunOS News slovo</comment>
<comment xml:lang="hu">SunOS News-betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras SunOS News</comment>
<comment xml:lang="id">Fonta SunOS News</comment>
@@ -10993,7 +11369,7 @@
<comment xml:lang="pt">letra SunOS News</comment>
<comment xml:lang="pt_BR">Fonte SunOS News</comment>
<comment xml:lang="ro">Font SunOS News</comment>
- <comment xml:lang="ru">шрифт SunOS News</comment>
+ <comment xml:lang="ru">Шрифт SunOS News</comment>
<comment xml:lang="sk">Písmo SunOS News</comment>
<comment xml:lang="sl">Datoteka pisave SunOS News</comment>
<comment xml:lang="sq">Gërma SunOS News</comment>
@@ -11017,8 +11393,8 @@
<comment xml:lang="az">TeX yazı növü</comment>
<comment xml:lang="be@latin">Å ryft TeX</comment>
<comment xml:lang="bg">Шрифт — TeX</comment>
- <comment xml:lang="ca">tipus de lletra TeX</comment>
- <comment xml:lang="cs">písmo TeX</comment>
+ <comment xml:lang="ca">lletra TeX</comment>
+ <comment xml:lang="cs">font TeX</comment>
<comment xml:lang="cy">Ffont TeX</comment>
<comment xml:lang="da">TeX-skrifttype</comment>
<comment xml:lang="de">TeX-Schrift</comment>
@@ -11033,7 +11409,7 @@
<comment xml:lang="ga">cló TeX</comment>
<comment xml:lang="gl">tipo de letra de TeX</comment>
<comment xml:lang="he">גופן TeX</comment>
- <comment xml:lang="hr">TeX font</comment>
+ <comment xml:lang="hr">TeX slovo</comment>
<comment xml:lang="hu">TeX-betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras TeX</comment>
<comment xml:lang="id">Fonta TeX</comment>
@@ -11052,7 +11428,7 @@
<comment xml:lang="pt">letra TeX</comment>
<comment xml:lang="pt_BR">Fonte TeX</comment>
<comment xml:lang="ro">Font TeX</comment>
- <comment xml:lang="ru">шрифт TeX</comment>
+ <comment xml:lang="ru">Шрифт TeX</comment>
<comment xml:lang="sk">Písmo TeX</comment>
<comment xml:lang="sl">Datoteka pisave TeX</comment>
<comment xml:lang="sq">Gërma TeX</comment>
@@ -11076,8 +11452,8 @@
<comment xml:lang="az">TeX yazı növü metrikləri</comment>
<comment xml:lang="be@latin">Metryka Å¡ryftu TeX</comment>
<comment xml:lang="bg">Шрифтова метрика — TeX</comment>
- <comment xml:lang="ca">mètrica de tipus de lletra TeX</comment>
- <comment xml:lang="cs">metrika písma TeX</comment>
+ <comment xml:lang="ca">mètrica de lletra de TeX</comment>
+ <comment xml:lang="cs">metrika fontu TeX</comment>
<comment xml:lang="cy">Metrigau Ffont TeX</comment>
<comment xml:lang="da">TeX-skrifttypeinformation</comment>
<comment xml:lang="de">TeX-Schriftmetriken</comment>
@@ -11091,7 +11467,7 @@
<comment xml:lang="ga">meadarachtaí cló TeX</comment>
<comment xml:lang="gl">Métricas de tipo de letra de TeX</comment>
<comment xml:lang="he">ממדי גופן של TeX</comment>
- <comment xml:lang="hr">TeX mjere fonta</comment>
+ <comment xml:lang="hr">TeX mjere slova</comment>
<comment xml:lang="hu">TeX-betűmetrika</comment>
<comment xml:lang="ia">Metricas de typo de litteras TeX</comment>
<comment xml:lang="id">Fonta metrik TeX</comment>
@@ -11110,7 +11486,7 @@
<comment xml:lang="pt">métricas de letra TeX</comment>
<comment xml:lang="pt_BR">Métrica de fonte TeX</comment>
<comment xml:lang="ro">Dimensiuni font TeX</comment>
- <comment xml:lang="ru">метрика шрифта TeX</comment>
+ <comment xml:lang="ru">Метрика шрифта TeX</comment>
<comment xml:lang="sk">Metrika písma TeX</comment>
<comment xml:lang="sl">Matrika pisave Tex</comment>
<comment xml:lang="sq">Gërma TeX metrics</comment>
@@ -11119,7 +11495,7 @@
<comment xml:lang="tr">TeX yazı tipi ölçüleri</comment>
<comment xml:lang="uk">метрики шрифту TeX</comment>
<comment xml:lang="vi">Cách đo phông chữ TeX</comment>
- <comment xml:lang="zh_CN">TeX 字体å‚æ•°</comment>
+ <comment xml:lang="zh_CN">TeX 字体规格</comment>
<comment xml:lang="zh_TW">TeX å­—åž‹æ述檔</comment>
<generic-icon name="font-x-generic"/>
<magic priority="50">
@@ -11127,13 +11503,13 @@
<match value="\000\022" type="string" offset="2"/>
</magic>
</mime-type>
- <mime-type type="application/x-font-ttf">
+ <mime-type type="font/ttf">
<comment>TrueType font</comment>
<comment xml:lang="ar">خط TrueType</comment>
<comment xml:lang="be@latin">Å ryft TrueType</comment>
<comment xml:lang="bg">Шрифт — TrueType</comment>
- <comment xml:lang="ca">tipus de lletra TrueType</comment>
- <comment xml:lang="cs">písmo TrueType</comment>
+ <comment xml:lang="ca">lletra TrueType</comment>
+ <comment xml:lang="cs">font TrueType</comment>
<comment xml:lang="da">TrueType-skrifttype</comment>
<comment xml:lang="de">TrueType-Schrift</comment>
<comment xml:lang="el">ΓÏαμματοσειÏά TrueType</comment>
@@ -11147,7 +11523,7 @@
<comment xml:lang="ga">cló TrueType</comment>
<comment xml:lang="gl">tipo de letra TrueType</comment>
<comment xml:lang="he">גופן מסוג TrueType</comment>
- <comment xml:lang="hr">TrueType font</comment>
+ <comment xml:lang="hr">TrueType slovo</comment>
<comment xml:lang="hu">TrueType-betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras TrueType</comment>
<comment xml:lang="id">Fonta TrueType</comment>
@@ -11166,7 +11542,7 @@
<comment xml:lang="pt">letra TrueType</comment>
<comment xml:lang="pt_BR">Fonte TrueType</comment>
<comment xml:lang="ro">Font TrueType</comment>
- <comment xml:lang="ru">шрифт TrueType</comment>
+ <comment xml:lang="ru">Шрифт TrueType</comment>
<comment xml:lang="sk">Písmo TrueType</comment>
<comment xml:lang="sl">Datoteka pisave TrueType</comment>
<comment xml:lang="sq">Lloj gërme TrueType</comment>
@@ -11184,6 +11560,31 @@
<match value="\000\001\000\000\000" type="string" offset="0"/>
</magic>
<glob pattern="*.ttf"/>
+ <alias type="application/x-font-ttf"/>
+ </mime-type>
+ <mime-type type="font/collection">
+ <comment>Font collection</comment>
+ <comment xml:lang="ca">ccol·lecció de lletres</comment>
+ <comment xml:lang="cs">kolekce fontů</comment>
+ <comment xml:lang="de">Schriftsammlung</comment>
+ <comment xml:lang="en_GB">Font collection</comment>
+ <comment xml:lang="es">colección tipográfica</comment>
+ <comment xml:lang="fi">Fonttikokoelma</comment>
+ <comment xml:lang="hr">Kolekcija slova</comment>
+ <comment xml:lang="hu">Betűkészlet-gyűjtemény</comment>
+ <comment xml:lang="id">Koleksi fonta</comment>
+ <comment xml:lang="it">Raccolta di caratteri</comment>
+ <comment xml:lang="kk">Қаріптер жинағы</comment>
+ <comment xml:lang="ko">글꼴 모ìŒ</comment>
+ <comment xml:lang="pl">Kolekcja czcionek</comment>
+ <comment xml:lang="pt_BR">coleção de fontes</comment>
+ <comment xml:lang="ru">ÐšÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ ÑˆÑ€Ð¸Ñ„Ñ‚Ð¾Ð²</comment>
+ <comment xml:lang="sk">Zbierka písiem</comment>
+ <comment xml:lang="sv">Typsnittssamling</comment>
+ <comment xml:lang="uk">збірка шрифтів</comment>
+ <comment xml:lang="zh_CN">字体集</comment>
+ <comment xml:lang="zh_TW">字型集</comment>
+ <generic-icon name="font-x-generic"/>
<glob pattern="*.ttc"/>
</mime-type>
<mime-type type="application/x-font-ttx">
@@ -11191,8 +11592,8 @@
<comment xml:lang="ar">خط TrueType XML</comment>
<comment xml:lang="be@latin">Å ryft TrueType XML</comment>
<comment xml:lang="bg">Шрифт — TrueType XML</comment>
- <comment xml:lang="ca">tipus de lletra TrueType XML</comment>
- <comment xml:lang="cs">písmo TrueType XML</comment>
+ <comment xml:lang="ca">lletra XML de TrueType</comment>
+ <comment xml:lang="cs">font TrueType XML</comment>
<comment xml:lang="da">TrueType XML-skrifttype</comment>
<comment xml:lang="de">TrueType-XML-Schrift</comment>
<comment xml:lang="el">ΓÏαμματοσειÏά XML TrueType</comment>
@@ -11205,7 +11606,7 @@
<comment xml:lang="ga">cló XML TrueType</comment>
<comment xml:lang="gl">tipo de letra TrueType XML</comment>
<comment xml:lang="he">גופן XML מסוג TrueType</comment>
- <comment xml:lang="hr">TrueType XML font</comment>
+ <comment xml:lang="hr">TrueType XML slovo</comment>
<comment xml:lang="hu">TrueType XML betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras TrueType XML</comment>
<comment xml:lang="id">Fonta TrueType XML</comment>
@@ -11223,7 +11624,7 @@
<comment xml:lang="pt">letra TrueType XML</comment>
<comment xml:lang="pt_BR">Fonte TrueType XML</comment>
<comment xml:lang="ro">Font XML TrueType</comment>
- <comment xml:lang="ru">шрифт TrueType XML</comment>
+ <comment xml:lang="ru">Шрифт TrueType XML</comment>
<comment xml:lang="sk">Písmo TrueType XML</comment>
<comment xml:lang="sl">Datoteka pisave TrueType XML</comment>
<comment xml:lang="sq">Lloj gërme TrueType XML</comment>
@@ -11247,8 +11648,8 @@
<comment xml:lang="az">V yazı növü</comment>
<comment xml:lang="be@latin">Å ryft V</comment>
<comment xml:lang="bg">Шрифт — V</comment>
- <comment xml:lang="ca">tipus de lletra V</comment>
- <comment xml:lang="cs">písmo V</comment>
+ <comment xml:lang="ca">lletra V</comment>
+ <comment xml:lang="cs">font V</comment>
<comment xml:lang="cy">Ffont V</comment>
<comment xml:lang="da">V-skrifttype</comment>
<comment xml:lang="de">V-Schrift</comment>
@@ -11263,7 +11664,7 @@
<comment xml:lang="ga">cló V</comment>
<comment xml:lang="gl">tipo de letra V</comment>
<comment xml:lang="he">גופן של V</comment>
- <comment xml:lang="hr">V font</comment>
+ <comment xml:lang="hr">V slovo</comment>
<comment xml:lang="hu">V-betűkészlet</comment>
<comment xml:lang="ia">Typo de litteras V</comment>
<comment xml:lang="id">Fonta V</comment>
@@ -11282,7 +11683,7 @@
<comment xml:lang="pt">letra V</comment>
<comment xml:lang="pt_BR">Fonte V</comment>
<comment xml:lang="ro">Font V</comment>
- <comment xml:lang="ru">шрифт V font</comment>
+ <comment xml:lang="ru">Шрифт V font</comment>
<comment xml:lang="sk">Písmo V</comment>
<comment xml:lang="sl">Datoteka pisave V</comment>
<comment xml:lang="sq">Gërmë V</comment>
@@ -11301,6 +11702,7 @@
<mime-type type="application/vnd.framemaker">
<comment>Adobe FrameMaker document</comment>
<comment xml:lang="ar">مستند أدوبي الصانع للإطارات</comment>
+ <comment xml:lang="ast">Documentu d'Adobe FrameMaker</comment>
<comment xml:lang="be@latin">Dakument Adobe FrameMaker</comment>
<comment xml:lang="bg">Документ — Adobe FrameMaker</comment>
<comment xml:lang="ca">document d'Adobe FrameMaker</comment>
@@ -11337,7 +11739,7 @@
<comment xml:lang="pt">documento Adobe FrameMaker</comment>
<comment xml:lang="pt_BR">Documento do Adobe FrameMaker</comment>
<comment xml:lang="ro">Document Adobe FrameMaker</comment>
- <comment xml:lang="ru">документ Adobe FrameMaker</comment>
+ <comment xml:lang="ru">Документ Adobe FrameMaker</comment>
<comment xml:lang="sk">Dokument Adobe FrameMaker</comment>
<comment xml:lang="sl">Dokument Adobe FrameMaker</comment>
<comment xml:lang="sq">Dokument Adobe FrameMaker</comment>
@@ -11399,7 +11801,7 @@
<comment xml:lang="oc">ROM Game Boy</comment>
<comment xml:lang="pl">Plik ROM konsoli Game Boy</comment>
<comment xml:lang="pt">ROM Game Boy</comment>
- <comment xml:lang="pt_BR">ROM do Game Boy</comment>
+ <comment xml:lang="pt_BR">ROM de Game Boy</comment>
<comment xml:lang="ro">ROM Game Boy</comment>
<comment xml:lang="ru">Game Boy ROM</comment>
<comment xml:lang="sk">ROM pre Game Boy</comment>
@@ -11424,18 +11826,29 @@
<mime-type type="application/x-gameboy-color-rom">
<comment>Game Boy Color ROM</comment>
<comment xml:lang="ca">ROM de Game Boy Color</comment>
+ <comment xml:lang="cs">ROM pro Game Boy Color</comment>
<comment xml:lang="da">Game Boy Color ROM</comment>
<comment xml:lang="de">Game Boy Color ROM</comment>
+ <comment xml:lang="en_GB">Game Boy Colour ROM</comment>
<comment xml:lang="es">ROM de Game Boy Color</comment>
+ <comment xml:lang="eu">Game Boy Color ROM</comment>
<comment xml:lang="fi">Game Boy Color -ROM</comment>
<comment xml:lang="fr">ROM Game Boy Color</comment>
+ <comment xml:lang="ga">ROM Game Boy Color</comment>
+ <comment xml:lang="he">ROM של Game Boy Color</comment>
+ <comment xml:lang="hr">Game Boy Color ROM</comment>
<comment xml:lang="hu">Game Boy Color ROM</comment>
+ <comment xml:lang="id">ROM Game Boy Color</comment>
+ <comment xml:lang="it">ROM Game Boy Color</comment>
<comment xml:lang="kk">Game Boy Color ROM</comment>
<comment xml:lang="ko">ê²Œìž„ë³´ì´ ì»¬ëŸ¬ 롬</comment>
<comment xml:lang="pl">Plik ROM konsoli Game Boy Color</comment>
<comment xml:lang="pt_BR">ROM de Game Boy Color</comment>
<comment xml:lang="ru">Game Boy Color ROM</comment>
<comment xml:lang="sk">ROM pre Game Boy Color</comment>
+ <comment xml:lang="sr">Гејм Бој РОМ боје</comment>
+ <comment xml:lang="sv">Game Boy Color-rom</comment>
+ <comment xml:lang="tr">Game Boy Color ROM</comment>
<comment xml:lang="uk">ППП Game Boy Color</comment>
<comment xml:lang="zh_CN">Game Boy Color ROM</comment>
<comment xml:lang="zh_TW">Game Boy Color ROM</comment>
@@ -11484,7 +11897,7 @@
<comment xml:lang="oc">ROM Game Boy Advance</comment>
<comment xml:lang="pl">Plik ROM konsoli Game Boy Advance</comment>
<comment xml:lang="pt">ROM Game Boy Advance</comment>
- <comment xml:lang="pt_BR">ROM do Game Boy Advance</comment>
+ <comment xml:lang="pt_BR">ROM de Game Boy Advance</comment>
<comment xml:lang="ro">ROM Game Boy Advance</comment>
<comment xml:lang="ru">Game Boy Advance ROM</comment>
<comment xml:lang="sk">ROM pre Game Boy Advance</comment>
@@ -11501,6 +11914,30 @@
<glob pattern="*.gba"/>
<glob pattern="*.agb"/>
</mime-type>
+ <mime-type type="application/x-virtual-boy-rom">
+ <comment>Virtual Boy ROM</comment>
+ <comment xml:lang="ca">ROM de Virtual Boy</comment>
+ <comment xml:lang="cs">ROM pro Virtual Boy</comment>
+ <comment xml:lang="de">Virtual Boy ROM</comment>
+ <comment xml:lang="en_GB">Virtual Boy ROM</comment>
+ <comment xml:lang="es">ROM de Virtual Boy</comment>
+ <comment xml:lang="hr">Virtual Boy ROM</comment>
+ <comment xml:lang="hu">Virtual Boy ROM</comment>
+ <comment xml:lang="id">ROM Virtual Boy</comment>
+ <comment xml:lang="it">ROM Virtual Boy</comment>
+ <comment xml:lang="kk">Virtual Boy ROM</comment>
+ <comment xml:lang="ko">ë²„ì¶”ì–¼ë³´ì´ ë¡¬</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Virtual Boy</comment>
+ <comment xml:lang="pt_BR">ROM de Virtual Boy</comment>
+ <comment xml:lang="ru">Virtual Boy ROM</comment>
+ <comment xml:lang="sk">ROM pre Virtual Boy</comment>
+ <comment xml:lang="sv">Virtual Boy-rom</comment>
+ <comment xml:lang="uk">ROM Virtual Boy</comment>
+ <comment xml:lang="zh_CN">Virtual Boy ROM</comment>
+ <comment xml:lang="zh_TW">Virtual Boy ROM</comment>
+ <generic-icon name="application-x-executable"/>
+ <glob pattern="*.vb"/>
+ </mime-type>
<mime-type type="application/x-gdbm">
<comment>GDBM database</comment>
<comment xml:lang="ar">قاعدة بيانات GDBM</comment>
@@ -11540,7 +11977,7 @@
<comment xml:lang="pt">base de dados GDMB</comment>
<comment xml:lang="pt_BR">Banco de dados GDBM</comment>
<comment xml:lang="ro">Bază de date GDBM</comment>
- <comment xml:lang="ru">база данных GDBM</comment>
+ <comment xml:lang="ru">База данных GDBM</comment>
<comment xml:lang="sk">Databáza GDBM</comment>
<comment xml:lang="sl">Podatkovna zbirka GDBM</comment>
<comment xml:lang="sq">Bazë me të dhëna GDBM</comment>
@@ -11597,7 +12034,7 @@
<comment xml:lang="oc">ROM Mega Drive/Genesis</comment>
<comment xml:lang="pl">Plik ROM konsoli Mega Drive</comment>
<comment xml:lang="pt">ROM Mega Drive</comment>
- <comment xml:lang="pt_BR">ROM do Gênesis (Mega Drive)</comment>
+ <comment xml:lang="pt_BR">ROM de Genesis (Mega Drive)</comment>
<comment xml:lang="ro">ROM Genesis</comment>
<comment xml:lang="ru">Genesis ROM</comment>
<comment xml:lang="sk">ROM pre Megadrive</comment>
@@ -11624,19 +12061,29 @@
<comment>Genesis 32X ROM</comment>
<comment xml:lang="ca">ROM de Genesis 32X</comment>
+ <comment xml:lang="cs">ROM pro Genesis 32X</comment>
<comment xml:lang="da">Genesis 32X ROM</comment>
<comment xml:lang="de">Genesis 32X ROM</comment>
+ <comment xml:lang="en_GB">Genesis 32X ROM</comment>
<comment xml:lang="es">ROM de Genesis 32X</comment>
+ <comment xml:lang="eu">Genesis 32X ROM</comment>
<comment xml:lang="fi">Genesis 32X -ROM</comment>
<comment xml:lang="fr">ROM Genesis 32X</comment>
+ <comment xml:lang="ga">ROM Genesis 32X</comment>
<comment xml:lang="he">ROM מסוג Genesis 32X</comment>
+ <comment xml:lang="hr">Genesis 32X ROM</comment>
<comment xml:lang="hu">Genesis 32X ROM</comment>
+ <comment xml:lang="id">ROM Genesis 32X</comment>
+ <comment xml:lang="it">ROM Sega Mega Drive 32X</comment>
<comment xml:lang="kk">Genesis 32X ROM</comment>
<comment xml:lang="ko">제네시스 32X 롬</comment>
<comment xml:lang="pl">Plik ROM konsoli Mega Drive 32X</comment>
<comment xml:lang="pt_BR">ROM de Genesis 32X</comment>
<comment xml:lang="ru">Genesis 32X ROM</comment>
<comment xml:lang="sk">ROM pre Genesis 32X</comment>
+ <comment xml:lang="sr">ÐÐµÐ½ÐµÐ·Ð¸Ñ 32X РОМ</comment>
+ <comment xml:lang="sv">Mega Drive 32X-rom</comment>
+ <comment xml:lang="tr">Genesis 32X ROM</comment>
<comment xml:lang="uk">ППП Genesis 32X</comment>
<comment xml:lang="zh_CN">Genesis 32X ROM</comment>
<comment xml:lang="zh_TW">Genesis 32X ROM</comment>
@@ -11667,7 +12114,7 @@
<comment xml:lang="ga">teachtaireachtaí aistrithe (inléite ag meaisín)</comment>
<comment xml:lang="gl">mensaxes traducidos (lexíbeis por máquinas)</comment>
<comment xml:lang="he">הודעות מתורגמות (מובן ע״י מכונה)</comment>
- <comment xml:lang="hr">prevedene poruke (strojno Äitljive)</comment>
+ <comment xml:lang="hr">Prevedene poruke (strojno Äitljive)</comment>
<comment xml:lang="hu">lefordított üzenetek (gépi kód)</comment>
<comment xml:lang="ia">messages traducite (legibile pro machinas)</comment>
<comment xml:lang="id">pesan diterjemahkan (dapat dibaca mesin)</comment>
@@ -11687,7 +12134,7 @@
<comment xml:lang="pt">mensagens traduzidas (leitura pelo computador)</comment>
<comment xml:lang="pt_BR">Mensagens traduzidas (legível pelo computador)</comment>
<comment xml:lang="ro">mesaje traduse (citite de calculator)</comment>
- <comment xml:lang="ru">переводы Ñообщений (откомпилированые)</comment>
+ <comment xml:lang="ru">Переводы Ñообщений (откомпилированые)</comment>
<comment xml:lang="sk">Preložené správy (strojovo Äitateľné)</comment>
<comment xml:lang="sl">prevedena sporoÄila (strojni zapis)</comment>
<comment xml:lang="sq">Mesazhe të përkthyer (të lexueshëm nga makina)</comment>
@@ -11696,7 +12143,7 @@
<comment xml:lang="tr">çevrilmiş iletiler (makine tarafından okunabilir)</comment>
<comment xml:lang="uk">перекладені Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ (у машинній формі)</comment>
<comment xml:lang="vi">thông Ä‘iệp đã dịch (máy Ä‘á»c được)</comment>
- <comment xml:lang="zh_CN">消æ¯ç¿»è¯‘(机读)</comment>
+ <comment xml:lang="zh_CN">已翻译消æ¯ï¼ˆæœºè¯»ï¼‰</comment>
<comment xml:lang="zh_TW">ç¿»è­¯è¨Šæ¯ (程å¼è®€å–æ ¼å¼)</comment>
<magic priority="50">
<match value="\336\22\4\225" type="string" offset="0"/>
@@ -11717,6 +12164,7 @@
<comment xml:lang="eu">GTK+ Builder</comment>
<comment xml:lang="fi">GTK+ Builder</comment>
<comment xml:lang="fr">GTK+ Builder</comment>
+ <comment xml:lang="ga">Tógálaí GTK+</comment>
<comment xml:lang="gl">Construtor de GTK+</comment>
<comment xml:lang="he">בנייה של GTK+‎</comment>
<comment xml:lang="hr">GTK+ Builder</comment>
@@ -11739,7 +12187,7 @@
<comment xml:lang="sv">GTK+ Builder</comment>
<comment xml:lang="tr">GTK+ Ä°nÅŸa Edici</comment>
<comment xml:lang="uk">GTK+ Builder</comment>
- <comment xml:lang="zh_CN">GTK+ 构建程åº</comment>
+ <comment xml:lang="zh_CN">GTK+ Builder</comment>
<comment xml:lang="zh_TW">GTK+ Builder</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="x-office-document"/>
@@ -11789,7 +12237,7 @@
<comment xml:lang="pt">projecto Glade</comment>
<comment xml:lang="pt_BR">Projeto do Glade</comment>
<comment xml:lang="ro">Proiect Glade</comment>
- <comment xml:lang="ru">проект Glade</comment>
+ <comment xml:lang="ru">Проект Glade</comment>
<comment xml:lang="sk">Projekt Glade</comment>
<comment xml:lang="sl">Datoteka projekta Glade</comment>
<comment xml:lang="sq">Projekt Glade</comment>
@@ -11841,7 +12289,7 @@
<comment xml:lang="pt">dados financeiros GnuCash</comment>
<comment xml:lang="pt_BR">Dados financeiros do GnuCash</comment>
<comment xml:lang="ro">Date financiare GnuCash</comment>
- <comment xml:lang="ru">финанÑовые данные GnuCash</comment>
+ <comment xml:lang="ru">ФинанÑовые данные GnuCash</comment>
<comment xml:lang="sk">FinanÄné údaje GnuCash</comment>
<comment xml:lang="sl">Datoteka finanÄnih podatkov GnuCash</comment>
<comment xml:lang="sr">финанÑијÑки подаци Гнуовог новца</comment>
@@ -11895,7 +12343,7 @@
<comment xml:lang="pt">folha de cálculo Gnumeric</comment>
<comment xml:lang="pt_BR">Planilha do Gnumeric</comment>
<comment xml:lang="ro">Foaie de calcul Gnumeric</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Gnumeric</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Gnumeric</comment>
<comment xml:lang="sk">Zošit Gnumeric</comment>
<comment xml:lang="sl">Razpredelnica Gnumeric</comment>
<comment xml:lang="sq">Fletë llogaritjesh Gnumeric</comment>
@@ -11904,7 +12352,7 @@
<comment xml:lang="tr">Gnumeric çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Gnumeric</comment>
<comment xml:lang="vi">Bảng tính Gnumeric.</comment>
- <comment xml:lang="zh_CN">Gnumeric 工作簿</comment>
+ <comment xml:lang="zh_CN">Gnumeric 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">Gnumeric 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="50">
@@ -11916,6 +12364,7 @@
<mime-type type="application/x-gnuplot">
<comment>Gnuplot document</comment>
<comment xml:lang="ar">مستند Gnuplot</comment>
+ <comment xml:lang="ast">Documentu de Gnuplot</comment>
<comment xml:lang="be@latin">Dakument Gnuplot</comment>
<comment xml:lang="bg">Документ — Gnuplot</comment>
<comment xml:lang="ca">document gnuplot</comment>
@@ -11951,7 +12400,7 @@
<comment xml:lang="pt">documento Gnuplot</comment>
<comment xml:lang="pt_BR">Documento do Gnuplot</comment>
<comment xml:lang="ro">Document Gnuplot</comment>
- <comment xml:lang="ru">документ Gnuplot</comment>
+ <comment xml:lang="ru">Документ Gnuplot</comment>
<comment xml:lang="sk">Dokument Gnuplot</comment>
<comment xml:lang="sl">Dokument Gnuplot</comment>
<comment xml:lang="sq">Dokument Gnuplot</comment>
@@ -11985,7 +12434,7 @@
<comment xml:lang="fi">Graphite- tieteellinen graafi</comment>
<comment xml:lang="fo">Grapite vísindarlig ritmynd</comment>
<comment xml:lang="fr">graphe Graphite scientific</comment>
- <comment xml:lang="ga">graf eolaíoch Graphite</comment>
+ <comment xml:lang="ga">graf eolaíochta Graphite</comment>
<comment xml:lang="gl">gráfica científica de Graphite</comment>
<comment xml:lang="he">×ª×¨×©×™× ×ž×“×¢×™ של Graphite</comment>
<comment xml:lang="hr">Graphite znanstveni grafikon</comment>
@@ -12007,7 +12456,7 @@
<comment xml:lang="pt">gráfico científico Graphite</comment>
<comment xml:lang="pt_BR">Gráfico científico do Graphite</comment>
<comment xml:lang="ro">Grafic științific Graphite</comment>
- <comment xml:lang="ru">Ð½Ð°ÑƒÑ‡Ð½Ð°Ñ Ð´Ð¸Ð°Ð³Ñ€Ð°Ð¼Ð¼Ð° Graphite</comment>
+ <comment xml:lang="ru">ÐÐ°ÑƒÑ‡Ð½Ð°Ñ Ð´Ð¸Ð°Ð³Ñ€Ð°Ð¼Ð¼Ð° Graphite</comment>
<comment xml:lang="sk">Vedecký graf Graphite</comment>
<comment xml:lang="sl">Datoteka znanstvenega grafa Graphite</comment>
<comment xml:lang="sq">Grafik shkencor Graphite </comment>
@@ -12061,7 +12510,7 @@
<comment xml:lang="pt">catálogo GTKtalog</comment>
<comment xml:lang="pt_BR">Catálogo GTKtalog</comment>
<comment xml:lang="ro">Catalog GTKalog</comment>
- <comment xml:lang="ru">каталог GTKtalog</comment>
+ <comment xml:lang="ru">Каталог GTKtalog</comment>
<comment xml:lang="sk">Katalóg GTKtalog</comment>
<comment xml:lang="sl">Datoteka kataloga GTKtalog</comment>
<comment xml:lang="sq">Katallog GTKtalog</comment>
@@ -12080,6 +12529,7 @@
<mime-type type="application/x-gzdvi">
<comment>TeX DVI document (gzip-compressed)</comment>
<comment xml:lang="ar">مستند TeX DVI (مضغوط-gzip)</comment>
+ <comment xml:lang="ast">Documentu Tex DVI (comprimíu en gzip)</comment>
<comment xml:lang="be@latin">Dakument TeX DVI (gzip-skampresavany)</comment>
<comment xml:lang="bg">Документ — TeX DVI, компреÑиран Ñ gzip</comment>
<comment xml:lang="ca">document DVI de TeX (amb compressió gzip)</comment>
@@ -12096,7 +12546,7 @@
<comment xml:lang="ga">cáipéis DVI TeX (comhbhrúite le gzip)</comment>
<comment xml:lang="gl">documento DVI de TeX (comprimido con gzip)</comment>
<comment xml:lang="he">מסמך מסוג TeX DVI (מכווץ ע״י gzip)</comment>
- <comment xml:lang="hr">TeX DVI dokument (komprimiran gzip-om)</comment>
+ <comment xml:lang="hr">TeX DVI dokument (gzip sažet)</comment>
<comment xml:lang="hu">TeX DVI dokumentum (gzip-pel tömörítve)</comment>
<comment xml:lang="ia">Documento TeX DVI (comprimite con gzip)</comment>
<comment xml:lang="id">Dokumen TeX DVI (terkompresi gzip)</comment>
@@ -12114,7 +12564,7 @@
<comment xml:lang="pt">documento TeX DVI (compressão gzip)</comment>
<comment xml:lang="pt_BR">Documento DVI TeX (compactado com gzip)</comment>
<comment xml:lang="ro">Document TeX DVI (comprimat gzip)</comment>
- <comment xml:lang="ru">документ TeX DVI (Ñжатый gzip)</comment>
+ <comment xml:lang="ru">Документ TeX DVI (Ñжатый gzip)</comment>
<comment xml:lang="sk">Dokument TeX DVI (komprimovaný pomocou gzip)</comment>
<comment xml:lang="sl">Dokument TeX DVI (stisnjen z gzip)</comment>
<comment xml:lang="sq">Dokument TeX DVI (i kompresuar me gzip)</comment>
@@ -12123,7 +12573,7 @@
<comment xml:lang="tr">TeX DVI belgesi (gzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">документ TeX DVI (ÑтиÑнений gzip)</comment>
<comment xml:lang="vi">Tài liệu DVI TeX (đã nén gzip)</comment>
- <comment xml:lang="zh_CN">TeX DVI 文档(gzip 压缩)</comment>
+ <comment xml:lang="zh_CN">TeX DVI 文档(gzip 压缩)</comment>
<comment xml:lang="zh_TW">TeX DVI 文件 (gzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="x-office-document"/>
@@ -12167,7 +12617,7 @@
<comment xml:lang="pt">arquivo Gzip</comment>
<comment xml:lang="pt_BR">Pacote Gzip</comment>
<comment xml:lang="ro">Arhivă Gzip</comment>
- <comment xml:lang="ru">архив GZIP</comment>
+ <comment xml:lang="ru">Ðрхив GZIP</comment>
<comment xml:lang="sk">Archív gzip</comment>
<comment xml:lang="sl">Datoteka arhiva Gzip</comment>
<comment xml:lang="sq">Arkiv gzip</comment>
@@ -12188,6 +12638,7 @@
<mime-type type="application/x-gzpdf">
<comment>PDF document (gzip-compressed)</comment>
<comment xml:lang="ar">مستند PDF (مضغوط-gzip)</comment>
+ <comment xml:lang="ast">Documentu PDF (comprimíu en gzip)</comment>
<comment xml:lang="be@latin">Dakument PDF (gzip-skampresavany)</comment>
<comment xml:lang="bg">Документ — PDF, компреÑиран Ñ gzip</comment>
<comment xml:lang="ca">document PDF (amb compressió gzip)</comment>
@@ -12222,7 +12673,7 @@
<comment xml:lang="pt">documento PDF (compressão gzip)</comment>
<comment xml:lang="pt_BR">Documento PDF (compactado com gzip)</comment>
<comment xml:lang="ro">Document PDF (comprimat gzip)</comment>
- <comment xml:lang="ru">документ PDF (Ñжатый gzip)</comment>
+ <comment xml:lang="ru">Документ PDF (Ñжатый gzip)</comment>
<comment xml:lang="sk">Dokument PDF (komprimovaný pomocou gzip)</comment>
<comment xml:lang="sl">Dokument PDF (stisnjen z gzip)</comment>
<comment xml:lang="sq">Dokument PDF (i kompresuar me gzip)</comment>
@@ -12231,7 +12682,7 @@
<comment xml:lang="tr">PDF belgesi (gzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">документ PDF (ÑтиÑнений gzip)</comment>
<comment xml:lang="vi">Tài liệu PDF (đã nén gzip)</comment>
- <comment xml:lang="zh_CN">PDF 文档(gzip 压缩)</comment>
+ <comment xml:lang="zh_CN">PDF 文档(gzip 压缩)</comment>
<comment xml:lang="zh_TW">PDF 文件 (gzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="x-office-document"/>
@@ -12240,6 +12691,7 @@
<mime-type type="application/x-gzpostscript">
<comment>PostScript document (gzip-compressed)</comment>
<comment xml:lang="ar">مستند PostScript (مضغوط-gzip)</comment>
+ <comment xml:lang="ast">Documentu PostScript (comprimíu en gzip)</comment>
<comment xml:lang="be@latin">Dakument PostScript (gzip-skampresavany)</comment>
<comment xml:lang="bg">Документ — PostScript, компреÑиран Ñ gzip</comment>
<comment xml:lang="ca">document PostScript (amb compressió gzip)</comment>
@@ -12276,7 +12728,7 @@
<comment xml:lang="pt">documento PostScript (compressão gzip)</comment>
<comment xml:lang="pt_BR">Documento PostScript (compactado com gzip)</comment>
<comment xml:lang="ro">Document PostScript (comprimat gzip)</comment>
- <comment xml:lang="ru">документ PostScript (Ñжатый gzip)</comment>
+ <comment xml:lang="ru">Документ PostScript (Ñжатый gzip)</comment>
<comment xml:lang="sk">Dokument PostScript (komprimovaný pomocou gzip)</comment>
<comment xml:lang="sl">Dokument PostScript (stisnjen z gzip)</comment>
<comment xml:lang="sq">Dokument PostScript (i kompresuar me gzip)</comment>
@@ -12285,7 +12737,7 @@
<comment xml:lang="tr">PostScript belgesi (gzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">документ PostScript (ÑтиÑнене gzip)</comment>
<comment xml:lang="vi">Tài liệu PostScript (đã nén gzip)</comment>
- <comment xml:lang="zh_CN">PostScript 文档(gzip 压缩)</comment>
+ <comment xml:lang="zh_CN">PostScript 文档(gzip 压缩)</comment>
<comment xml:lang="zh_TW">PostScript 文件 (gzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/gzip"/>
<generic-icon name="x-office-document"/>
@@ -12294,6 +12746,7 @@
<mime-type type="application/x-hdf">
<comment>HDF document</comment>
<comment xml:lang="ar">مستند HDF</comment>
+ <comment xml:lang="ast">Documentu HDF</comment>
<comment xml:lang="az">HDF sənədi</comment>
<comment xml:lang="be@latin">Dakument HDF</comment>
<comment xml:lang="bg">Документ — HDF</comment>
@@ -12332,7 +12785,7 @@
<comment xml:lang="pt">documento HDF</comment>
<comment xml:lang="pt_BR">Documento HDF</comment>
<comment xml:lang="ro">Document HDF</comment>
- <comment xml:lang="ru">документ HDF</comment>
+ <comment xml:lang="ru">Документ HDF</comment>
<comment xml:lang="sk">Dokument HDF</comment>
<comment xml:lang="sl">Dokument HDF</comment>
<comment xml:lang="sq">Dokument HDF</comment>
@@ -12368,6 +12821,7 @@
<comment xml:lang="eu">IFF fitxtegia</comment>
<comment xml:lang="fi">IFF-tiedosto</comment>
<comment xml:lang="fr">fichier IFF</comment>
+ <comment xml:lang="ga">comhad IFF</comment>
<comment xml:lang="gl">Ficheiro IFF</comment>
<comment xml:lang="he">קובץ IFF</comment>
<comment xml:lang="hr">IFF datoteka</comment>
@@ -12383,7 +12837,7 @@
<comment xml:lang="pl">Plik IFF</comment>
<comment xml:lang="pt">ficheiro IFF</comment>
<comment xml:lang="pt_BR">Arquivo IFF</comment>
- <comment xml:lang="ru">файл IFF</comment>
+ <comment xml:lang="ru">Файл IFF</comment>
<comment xml:lang="sk">Súbor IFF</comment>
<comment xml:lang="sl">Datoteka IFF</comment>
<comment xml:lang="sr">ИФФ датотека</comment>
@@ -12437,7 +12891,7 @@
<comment xml:lang="pt">firmware iPod</comment>
<comment xml:lang="pt_BR">Firmware do iPod</comment>
<comment xml:lang="ro">Firmware iPod</comment>
- <comment xml:lang="ru">микропрограмма iPod</comment>
+ <comment xml:lang="ru">Микропрограмма iPod</comment>
<comment xml:lang="sk">Firmware iPod</comment>
<comment xml:lang="sl">Programska strojna oprema iPod</comment>
<comment xml:lang="sq">Firmware iPod</comment>
@@ -12491,7 +12945,7 @@
<comment xml:lang="pt">arquivo Java</comment>
<comment xml:lang="pt_BR">Pacote Java</comment>
<comment xml:lang="ro">Arhivă Java</comment>
- <comment xml:lang="ru">архив Java</comment>
+ <comment xml:lang="ru">Ðрхив Java</comment>
<comment xml:lang="sk">Archív Java</comment>
<comment xml:lang="sl">Datoteka arhiva Java</comment>
<comment xml:lang="sq">Arkiv Java</comment>
@@ -12547,7 +13001,7 @@
<comment xml:lang="pt">classe Java</comment>
<comment xml:lang="pt_BR">Classe Java</comment>
<comment xml:lang="ro">Clasă Java</comment>
- <comment xml:lang="ru">клаÑÑ Java</comment>
+ <comment xml:lang="ru">КлаÑÑ Java</comment>
<comment xml:lang="sk">Trieda Java</comment>
<comment xml:lang="sl">Datoteka razreda Java</comment>
<comment xml:lang="sq">Klasë Java</comment>
@@ -12606,7 +13060,7 @@
<comment xml:lang="pt">ficheiro JNLP</comment>
<comment xml:lang="pt_BR">Arquivo JNLP</comment>
<comment xml:lang="ro">Fișier JNLP</comment>
- <comment xml:lang="ru">файл JNLP</comment>
+ <comment xml:lang="ru">Файл JNLP</comment>
<comment xml:lang="sk">Súbor JNLP</comment>
<comment xml:lang="sl">Datoteka JNLP</comment>
<comment xml:lang="sq">File JNLP</comment>
@@ -12660,7 +13114,7 @@
<comment xml:lang="pt">armazém de chaves Java</comment>
<comment xml:lang="pt_BR">Keystore de Java</comment>
<comment xml:lang="ro">Stocare chei Java</comment>
- <comment xml:lang="ru">хранилище ключей Java</comment>
+ <comment xml:lang="ru">Хранилище ключей Java</comment>
<comment xml:lang="sk">Úložisko kľúÄov Java</comment>
<comment xml:lang="sl">Datoteka tipkovne razporeditve Java</comment>
<comment xml:lang="sr">Ñмештај кључа Јаве</comment>
@@ -12710,7 +13164,7 @@
<comment xml:lang="pt">armazém de chaves JavaJCE</comment>
<comment xml:lang="pt_BR">Keystore JCE do Java</comment>
<comment xml:lang="ro">Stocare chei Java JCE</comment>
- <comment xml:lang="ru">хранилище ключей Java JCE</comment>
+ <comment xml:lang="ru">Хранилище ключей Java JCE</comment>
<comment xml:lang="sk">Úložisko kľúÄov Java JCE</comment>
<comment xml:lang="sl">Datoteka tipkovne razporeditve Java JCE</comment>
<comment xml:lang="sr">Ñмештај ЈЦЕ кључа Јаве</comment>
@@ -12763,7 +13217,7 @@
<comment xml:lang="pt">arquivo Java Pack200</comment>
<comment xml:lang="pt_BR">Pacote Java Pack200</comment>
<comment xml:lang="ro">Arhivă Java Pack2000</comment>
- <comment xml:lang="ru">архив Java Pack200</comment>
+ <comment xml:lang="ru">Ðрхив Java Pack200</comment>
<comment xml:lang="sk">Archív Java Pack200</comment>
<comment xml:lang="sl">Datoteka arhiva Pack200 Java</comment>
<comment xml:lang="sq">Arkiv Java Pack200</comment>
@@ -12819,7 +13273,7 @@
<comment xml:lang="pt">programa JavaScript</comment>
<comment xml:lang="pt_BR">Programa JavaScript</comment>
<comment xml:lang="ro">Program JavaScript</comment>
- <comment xml:lang="ru">Ñценарий JavaScript</comment>
+ <comment xml:lang="ru">Программа JavaScript</comment>
<comment xml:lang="sk">Program jazyka JavaScript</comment>
<comment xml:lang="sl">Programska datoteka JavaScript</comment>
<comment xml:lang="sq">Program JavaScript</comment>
@@ -12828,17 +13282,31 @@
<comment xml:lang="tr">JavaScript programı</comment>
<comment xml:lang="uk">програма мовою JavaScript</comment>
<comment xml:lang="vi">Chương trình JavaScript</comment>
- <comment xml:lang="zh_CN">Javascript 程åº</comment>
+ <comment xml:lang="zh_CN">JavaScript 程åº</comment>
<comment xml:lang="zh_TW">JavaScript 程å¼</comment>
<alias type="application/x-javascript"/>
<alias type="text/javascript"/>
<sub-class-of type="application/ecmascript"/>
<generic-icon name="text-x-script"/>
+ <magic priority="50">
+ <match value="#!/bin/gjs" type="string" offset="0"/>
+ <match value="#! /bin/gjs" type="string" offset="0"/>
+ <match value='eval \"exec /bin/gjs' type="string" offset="0"/>
+ <match value="#!/usr/bin/gjs" type="string" offset="0"/>
+ <match value="#! /usr/bin/gjs" type="string" offset="0"/>
+ <match value='eval \"exec /usr/bin/gjs' type="string" offset="0"/>
+ <match value="#!/usr/local/bin/gjs" type="string" offset="0"/>
+ <match value="#! /usr/local/bin/gjs" type="string" offset="0"/>
+ <match value='eval \"exec /usr/local/bin/gjs' type="string" offset="0"/>
+ <match value='/bin/env gjs' type="string" offset="2:16"/>
+ </magic>
<glob pattern="*.js"/>
<glob pattern="*.jsm"/>
+ <glob pattern="*.mjs"/>
</mime-type>
<mime-type type="application/json">
<comment>JSON document</comment>
+ <comment xml:lang="ast">Documentu JSON</comment>
<comment xml:lang="ca">document JSON</comment>
<comment xml:lang="cs">dokument JSON</comment>
<comment xml:lang="da">JSON-dokument</comment>
@@ -12849,6 +13317,7 @@
<comment xml:lang="eu">JSON dokumentua</comment>
<comment xml:lang="fi">JSON-asiakirja</comment>
<comment xml:lang="fr">document JSON</comment>
+ <comment xml:lang="ga">cáipéis JSON</comment>
<comment xml:lang="gl">Documento JSON</comment>
<comment xml:lang="he">מסמך JSON</comment>
<comment xml:lang="hr">JSON dokument</comment>
@@ -12879,6 +13348,7 @@
</mime-type>
<mime-type type="application/jrd+json">
<comment>JRD document</comment>
+ <comment xml:lang="ast">Documentu JRD</comment>
<comment xml:lang="ca">document JRD</comment>
<comment xml:lang="cs">dokument JRD</comment>
<comment xml:lang="da">JRD-dokument</comment>
@@ -12889,6 +13359,7 @@
<comment xml:lang="eu">JRD dokumentua</comment>
<comment xml:lang="fi">JRD-asiakirja</comment>
<comment xml:lang="fr">document JRD</comment>
+ <comment xml:lang="ga">cáipéis JRD</comment>
<comment xml:lang="he">מסמך JRD</comment>
<comment xml:lang="hr">JRD dokument</comment>
<comment xml:lang="hu">JRD dokumentum</comment>
@@ -12901,7 +13372,7 @@
<comment xml:lang="pl">Dokument JRD</comment>
<comment xml:lang="pt">doxumento JRD</comment>
<comment xml:lang="pt_BR">Documento JRD</comment>
- <comment xml:lang="ru">документ JRD</comment>
+ <comment xml:lang="ru">Документ JRD</comment>
<comment xml:lang="sk">Dokument JRD</comment>
<comment xml:lang="sr">ЈРД документ</comment>
<comment xml:lang="sv">JRD-dokument</comment>
@@ -12923,7 +13394,9 @@
<comment xml:lang="de">JSON-Patch</comment>
<comment xml:lang="en_GB">JSON patch</comment>
<comment xml:lang="es">parche en JSON</comment>
+ <comment xml:lang="eu">JSON adabakia</comment>
<comment xml:lang="fr">correctif JSON</comment>
+ <comment xml:lang="ga">paiste JSON</comment>
<comment xml:lang="he">טל××™ JSON</comment>
<comment xml:lang="hr">JSON zakrpa</comment>
<comment xml:lang="hu">JSON javítócsomag</comment>
@@ -12936,13 +13409,13 @@
<comment xml:lang="pl">Åata JSON</comment>
<comment xml:lang="pt">patch JSON</comment>
<comment xml:lang="pt_BR">Patch JSON</comment>
- <comment xml:lang="ru">изменение JSON</comment>
+ <comment xml:lang="ru">Патч JSON</comment>
<comment xml:lang="sk">Záplata JSON</comment>
<comment xml:lang="sr">ЈСОРзакрпа</comment>
<comment xml:lang="sv">JSON patch</comment>
<comment xml:lang="tr">JSON yaması</comment>
<comment xml:lang="uk">латка JSON</comment>
- <comment xml:lang="zh_CN">JSON è¡¥ä¸æ–‡ä»¶</comment>
+ <comment xml:lang="zh_CN">JSON è¡¥ä¸</comment>
<comment xml:lang="zh_TW">JSON 修補檔</comment>
<acronym>JSON</acronym>
<expanded-acronym>JavaScript Object Notation</expanded-acronym>
@@ -12952,6 +13425,7 @@
</mime-type>
<mime-type type="application/ld+json">
<comment>JSON-LD document</comment>
+ <comment xml:lang="ast">Documentu JSON-LD</comment>
<comment xml:lang="ca">document JSON-LD</comment>
<comment xml:lang="cs">dokument JSON-LD</comment>
<comment xml:lang="da">JSON-LD-dokument</comment>
@@ -12962,6 +13436,7 @@
<comment xml:lang="eu">JSON-LD dokumentua</comment>
<comment xml:lang="fi">JSON-LD-asiakirja</comment>
<comment xml:lang="fr">document JSON-LD</comment>
+ <comment xml:lang="ga">cáipéis JSON-LD</comment>
<comment xml:lang="he">מסמך JSON-LD</comment>
<comment xml:lang="hr">JSON-LD dokument</comment>
<comment xml:lang="hu">JSON-LD dokumentum</comment>
@@ -12974,7 +13449,7 @@
<comment xml:lang="pl">Dokument JSON-LD</comment>
<comment xml:lang="pt">documento JSON-LD</comment>
<comment xml:lang="pt_BR">Documento JSON-LD</comment>
- <comment xml:lang="ru">документ JSON-LD</comment>
+ <comment xml:lang="ru">Документ JSON-LD</comment>
<comment xml:lang="sk">Dokument JSON-LD</comment>
<comment xml:lang="sr">ЈСОÐ-ЛД документ</comment>
<comment xml:lang="sv">JSON-LD-dokument</comment>
@@ -12991,18 +13466,28 @@
<mime-type type="application/x-ipynb+json">
<comment>Jupyter Notebook</comment>
<comment xml:lang="ca">llibreta de notes de Jupyter</comment>
+ <comment xml:lang="cs">sešit Jupyter</comment>
<comment xml:lang="da">Jupyter Notebook</comment>
<comment xml:lang="de">Jupyter-Dokument</comment>
+ <comment xml:lang="en_GB">Jupyter Notebook</comment>
<comment xml:lang="es">libreta de Jupyter</comment>
+ <comment xml:lang="eu">Jupyter Notebook</comment>
<comment xml:lang="fr">carnet de notes Jupyter</comment>
+ <comment xml:lang="ga">Leabhar nótaí Jupyter</comment>
<comment xml:lang="he">מחברת Jupyter</comment>
+ <comment xml:lang="hr">Jupyter bilježnica</comment>
<comment xml:lang="hu">Jupyter notesz</comment>
+ <comment xml:lang="id">Notebook Jupyter</comment>
+ <comment xml:lang="it">Notebook Jupyter</comment>
<comment xml:lang="kk">Jupyter Notebook</comment>
<comment xml:lang="ko">Jupyter 노트ë¶</comment>
<comment xml:lang="pl">Notatnik Jupyter</comment>
<comment xml:lang="pt_BR">Bloco de Notas Jupyter</comment>
<comment xml:lang="ru">Jupyter Notebook</comment>
<comment xml:lang="sk">Zošit programu Jupyter</comment>
+ <comment xml:lang="sr">Ðупитер бележница</comment>
+ <comment xml:lang="sv">Jupyter Notebook-dokument</comment>
+ <comment xml:lang="tr">Jupyter Notebook</comment>
<comment xml:lang="uk">запиÑник Jupyter</comment>
<comment xml:lang="zh_CN">Jupyter 笔记本</comment>
<comment xml:lang="zh_TW">Jupyter 記事本</comment>
@@ -13017,6 +13502,7 @@
</mime-type>
<mime-type type="application/vnd.coffeescript">
<comment>CoffeeScript document</comment>
+ <comment xml:lang="ast">Documentu de CoffeScript</comment>
<comment xml:lang="ca">document CoffeeScript</comment>
<comment xml:lang="cs">dokument CoffeeScript</comment>
<comment xml:lang="da">CoffeeScript-dokument</comment>
@@ -13027,6 +13513,7 @@
<comment xml:lang="eu">CoffeeScript dokumentua</comment>
<comment xml:lang="fi">CoffeeScript-asiakirja</comment>
<comment xml:lang="fr">document CoffeeScript</comment>
+ <comment xml:lang="ga">cáipéis CoffeeScript</comment>
<comment xml:lang="he">מסמך CoffeeScript</comment>
<comment xml:lang="hr">CoffeeScript dokument</comment>
<comment xml:lang="hu">CoffeeScript dokumentum</comment>
@@ -13039,7 +13526,7 @@
<comment xml:lang="pl">Dokument CoffeeScript</comment>
<comment xml:lang="pt">documento CoffeeScript</comment>
<comment xml:lang="pt_BR">Documento CoffeeScript</comment>
- <comment xml:lang="ru">документ CoffeeScript</comment>
+ <comment xml:lang="ru">Документ CoffeeScript</comment>
<comment xml:lang="sk">Dokument CoffeeScript</comment>
<comment xml:lang="sr">Кофи Ñкрипт документ</comment>
<comment xml:lang="sv">CoffeeScript-dokument</comment>
@@ -13090,7 +13577,7 @@
<comment xml:lang="pt">projecto JBuilder</comment>
<comment xml:lang="pt_BR">Projeto do JBuilder</comment>
<comment xml:lang="ro">Proiect JBuilder</comment>
- <comment xml:lang="ru">проект JBuilder</comment>
+ <comment xml:lang="ru">Проект JBuilder</comment>
<comment xml:lang="sk">Projekt JBuilder</comment>
<comment xml:lang="sl">Datoteka projekta JBuilder</comment>
<comment xml:lang="sq">Projekt JBuilder</comment>
@@ -13144,7 +13631,7 @@
<comment xml:lang="pt">desenho Karbon14</comment>
<comment xml:lang="pt_BR">Desenho do Karbon14</comment>
<comment xml:lang="ro">Desen Karbon14</comment>
- <comment xml:lang="ru">изображение Karbon14</comment>
+ <comment xml:lang="ru">РиÑунок Karbon14</comment>
<comment xml:lang="sk">Kresba Karbon14</comment>
<comment xml:lang="sl">Datoteka risbe Karbon14</comment>
<comment xml:lang="sq">Vizatim Karbon14</comment>
@@ -13209,7 +13696,7 @@
<comment xml:lang="pt">gráfico KChart</comment>
<comment xml:lang="pt_BR">Gráfico do KChart</comment>
<comment xml:lang="ro">Diagramă KChart</comment>
- <comment xml:lang="ru">диаграмма KChart</comment>
+ <comment xml:lang="ru">Диаграмма KChart</comment>
<comment xml:lang="sk">Graf KChart</comment>
<comment xml:lang="sl">Datoteka grafikona KChart</comment>
<comment xml:lang="sq">Grafik KChart</comment>
@@ -13269,7 +13756,7 @@
<comment xml:lang="pt">definições Kexi para ligação de servidor de base de dados</comment>
<comment xml:lang="pt_BR">Configurações do Kexi para conexão a servidor de banco de dados</comment>
<comment xml:lang="ro">Configurări Kexi pentru conexiunea la serverul de baze de date</comment>
- <comment xml:lang="ru">параметры Kexi Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Ñерверу БД</comment>
+ <comment xml:lang="ru">Параметры Kexi Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Ñерверу БД</comment>
<comment xml:lang="sk">Nastavenia Kexi pre pripojenie k databázovému serveru</comment>
<comment xml:lang="sl">Strežniška povezava do nastavitvene datoteke Kexi.</comment>
<comment xml:lang="sr">подешавања КекÑија за везу Ñа Ñервером базе података</comment>
@@ -13298,7 +13785,7 @@
<comment xml:lang="ga">aicearra go tionscadal Kexi ar fhreastalaí bunachair sonraí</comment>
<comment xml:lang="gl">acceso directo a proxecto Kexi no servidor de bases de datos</comment>
<comment xml:lang="he">קיצור דרך לפרוירט Kexi בשרת נתוני×</comment>
- <comment xml:lang="hr">preÄac za Kexi projekt na poslužitelju baze podataka</comment>
+ <comment xml:lang="hr">PreÄac do Kexi projekta na poslužitelju baze podataka</comment>
<comment xml:lang="hu">indítóikon adatbázis-kiszolgálón lévő Kexi projektre</comment>
<comment xml:lang="ia">Ligamine a projecto Kexi in servitor de base de datos</comment>
<comment xml:lang="id">pintasan ke projek Kexi pada server basis data</comment>
@@ -13314,7 +13801,7 @@
<comment xml:lang="pt">atalho para projeto Kexi em servidor de base de dados</comment>
<comment xml:lang="pt_BR">Atalho para projeto Kexi no servidor de banco de dados</comment>
<comment xml:lang="ro">scurtătură către un proiect Kexi pe un server de baze de date</comment>
- <comment xml:lang="ru">ÑÑылка на проект Kexi на Ñервере БД</comment>
+ <comment xml:lang="ru">СÑылка на проект Kexi на Ñервере БД</comment>
<comment xml:lang="sk">Zástupca projektu Kexi na databázovom serveri</comment>
<comment xml:lang="sl">bližnjica do Kexi projekta na podatkovnem strežniku</comment>
<comment xml:lang="sr">пречица до пројекта КекÑија на Ñерверу базе података</comment>
@@ -13355,11 +13842,11 @@
<comment xml:lang="lv">Kexi datubÄzes datnes balstÄ«ts projekts</comment>
<comment xml:lang="nl">Kexi database bestandgebaseerd project</comment>
<comment xml:lang="oc">projècte de banca de donadas Kexi en mòde fichièr</comment>
- <comment xml:lang="pl">Projekt bazy danych Kexi oparty na pliku</comment>
+ <comment xml:lang="pl">Projekt bazy danych Kexi na podstawie plików</comment>
<comment xml:lang="pt">projeto Kexi em base de dados baseada em ficheiros</comment>
<comment xml:lang="pt_BR">Projeto de banco de dados baseado em arquivo do Kexi</comment>
<comment xml:lang="ro">Proiect bazat pe fișiere al bazei de date Kexi</comment>
- <comment xml:lang="ru">файловый проект базы данных Kexi</comment>
+ <comment xml:lang="ru">Файловый проект базы данных Kexi</comment>
<comment xml:lang="sk">Projekt databázy Kexi s úložiskom typu súbor</comment>
<comment xml:lang="sl">Datoteka projekta podatkovne zbirke Kexi</comment>
<comment xml:lang="sr">пројекат КекÑијеве базе података на оÑнову датотеке</comment>
@@ -13401,11 +13888,11 @@
<comment xml:lang="lv">Kexi datubÄzes datnes balstÄ«ts projekts</comment>
<comment xml:lang="nl">Kexi database bestandgebaseerd project</comment>
<comment xml:lang="oc">projècte de banca de donadas Kexi en mòde fichièr</comment>
- <comment xml:lang="pl">Projekt bazy danych Kexi oparty na pliku</comment>
+ <comment xml:lang="pl">Projekt bazy danych Kexi na podstawie plików</comment>
<comment xml:lang="pt">projeto Kexi em base de dados baseada em ficheiros</comment>
<comment xml:lang="pt_BR">Projeto de banco de dados baseado em arquivo do Kexi</comment>
<comment xml:lang="ro">Proiect bazat pe fișiere al bazei de date Kexi</comment>
- <comment xml:lang="ru">файловый проект базы данных Kexi</comment>
+ <comment xml:lang="ru">Файловый проект базы данных Kexi</comment>
<comment xml:lang="sk">Projekt databázy Kexi s úložiskom typu súbor</comment>
<comment xml:lang="sl">Datoteka projekta podatkovne zbirke Kexi</comment>
<comment xml:lang="sr">пројекат КекÑијеве базе података на оÑнову датотеке</comment>
@@ -13458,7 +13945,7 @@
<comment xml:lang="pt">fórmula KFormula</comment>
<comment xml:lang="pt_BR">Fórmula do KFormula</comment>
<comment xml:lang="ro">Formulă KFormula</comment>
- <comment xml:lang="ru">формула KFormula</comment>
+ <comment xml:lang="ru">Формула KFormula</comment>
<comment xml:lang="sk">Vzorec KFormula</comment>
<comment xml:lang="sl">Datoteka formule KFormula</comment>
<comment xml:lang="sq">Formulë KFormula</comment>
@@ -13523,7 +14010,7 @@
<comment xml:lang="pt">desenho KIllustrator</comment>
<comment xml:lang="pt_BR">Desenho do KIllustrator</comment>
<comment xml:lang="ro">Desen KIllustrator</comment>
- <comment xml:lang="ru">изображение KIllustrator</comment>
+ <comment xml:lang="ru">РиÑунок KIllustrator</comment>
<comment xml:lang="sk">Kresba KIllustrator</comment>
<comment xml:lang="sl">Datoteka risbe KIllustrator</comment>
<comment xml:lang="sq">Vizatim KIllustrator</comment>
@@ -13583,11 +14070,11 @@
<comment xml:lang="pt">gráfico de fluxo Kivio</comment>
<comment xml:lang="pt_BR">Fluxograma do Kivio</comment>
<comment xml:lang="ro">Diagramă Kivio</comment>
- <comment xml:lang="ru">диаграмма Kivio</comment>
+ <comment xml:lang="ru">Диаграмма Kivio</comment>
<comment xml:lang="sk">Vývojový diagram Kivio</comment>
<comment xml:lang="sl">Datoteka grafikona Kivio</comment>
<comment xml:lang="sq">Diagramë fluksi Kivio</comment>
- <comment xml:lang="sr">Кливиов дијаграм протока</comment>
+ <comment xml:lang="sr">Кивиов дијаграм тока</comment>
<comment xml:lang="sv">Kivio-flödesschema</comment>
<comment xml:lang="tr">Kivio akış şeması</comment>
<comment xml:lang="uk">блок-Ñхема Kivio</comment>
@@ -13648,7 +14135,7 @@
<comment xml:lang="pt">desenho Kontour</comment>
<comment xml:lang="pt_BR">Desenho do Kontour</comment>
<comment xml:lang="ro">Desen Kontour</comment>
- <comment xml:lang="ru">изображение Kontour</comment>
+ <comment xml:lang="ru">РиÑунок Kontour</comment>
<comment xml:lang="sk">Kresba Kontour</comment>
<comment xml:lang="sl">Datoteka risbe Kontour</comment>
<comment xml:lang="sq">Vizatim Kontour</comment>
@@ -13713,7 +14200,7 @@
<comment xml:lang="pt">cenário KPovModeler</comment>
<comment xml:lang="pt_BR">Cena do KPovModeler</comment>
<comment xml:lang="ro">Scenă KPovModeler</comment>
- <comment xml:lang="ru">Ñцена KPovModeler</comment>
+ <comment xml:lang="ru">Сцена KPovModeler</comment>
<comment xml:lang="sk">Scéna KPovModeler</comment>
<comment xml:lang="sl">Datoteka scene KPovModeler</comment>
<comment xml:lang="sq">Skenë KPovModeler</comment>
@@ -13766,7 +14253,7 @@
<comment xml:lang="pt">apresentação KPresenter</comment>
<comment xml:lang="pt_BR">Apresentação do KPresenter</comment>
<comment xml:lang="ro">Prezentare KPresenter</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ KPresenter</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ KPresenter</comment>
<comment xml:lang="sk">Prezentácia KPresenter</comment>
<comment xml:lang="sl">Predstavitev KPresenter</comment>
<comment xml:lang="sq">Prezantim i KPresenter</comment>
@@ -13796,6 +14283,7 @@
<mime-type type="application/x-krita">
<comment>Krita document</comment>
<comment xml:lang="ar">مستند Krita</comment>
+ <comment xml:lang="ast">Documentu de Krita</comment>
<comment xml:lang="be@latin">Dakument Krita</comment>
<comment xml:lang="bg">Документ — Krita</comment>
<comment xml:lang="ca">document Krita</comment>
@@ -13832,7 +14320,7 @@
<comment xml:lang="pt">documento Krita</comment>
<comment xml:lang="pt_BR">Documento do Krita</comment>
<comment xml:lang="ro">Document Krita</comment>
- <comment xml:lang="ru">документ Krita</comment>
+ <comment xml:lang="ru">Документ Krita</comment>
<comment xml:lang="sk">Dokument Krita</comment>
<comment xml:lang="sl">Dokument Krita</comment>
<comment xml:lang="sq">Dokument Krita</comment>
@@ -13897,7 +14385,7 @@
<comment xml:lang="pt">folha de cálculo KSpread</comment>
<comment xml:lang="pt_BR">Planilha do KSpread</comment>
<comment xml:lang="ro">Foaie de calcul KSpread</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° KSpread</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° KSpread</comment>
<comment xml:lang="sk">Zošit KSpread</comment>
<comment xml:lang="sl">Preglednica KSpread</comment>
<comment xml:lang="sq">Fletë llogaritjesh KSpread</comment>
@@ -13906,7 +14394,7 @@
<comment xml:lang="tr">KSpread çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ KSpread</comment>
<comment xml:lang="vi">Bảng tính KSpread</comment>
- <comment xml:lang="zh_CN">KSpread 工作簿</comment>
+ <comment xml:lang="zh_CN">KSpread 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">KSpread 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="60">
@@ -13962,7 +14450,7 @@
<comment xml:lang="pt">folha de cálculo KSpread (encriptada)</comment>
<comment xml:lang="pt_BR">Planilha do KSpread (criptografada)</comment>
<comment xml:lang="ro">Foaie de calcul KSpread (criptat)</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° KSpread (зашифрованнаÑ)</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° KSpread (зашифрованнаÑ)</comment>
<comment xml:lang="sk">Zošit KSpread (šifrovaný)</comment>
<comment xml:lang="sl">Preglednica KSpread (Å¡ifrirana)</comment>
<comment xml:lang="sq">Fletë llogaritjesh KSpread (e kriptuar)</comment>
@@ -13971,7 +14459,7 @@
<comment xml:lang="tr">KSpread çalışma sayfası (şifreli)</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ KSpread (зашифрована)</comment>
<comment xml:lang="vi">Bảng tính KSpread (đã mật mã)</comment>
- <comment xml:lang="zh_CN">KSpread 加密工作簿</comment>
+ <comment xml:lang="zh_CN">KSpread 电å­è¡¨æ ¼ï¼ˆåŠ å¯†ï¼‰</comment>
<comment xml:lang="zh_TW">KSpread 試算表 (已加密)</comment>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="50">
@@ -13994,7 +14482,7 @@
<comment xml:lang="fi">KSysV init -paketti</comment>
<comment xml:lang="fo">KSysV init pakki</comment>
<comment xml:lang="fr">paquet d'initialisation KSysV</comment>
- <comment xml:lang="ga">pacáiste thosú KSysV</comment>
+ <comment xml:lang="ga">pacáiste túsaithe KSysV</comment>
<comment xml:lang="gl">paquete de KsysV init</comment>
<comment xml:lang="he">חבילת KSysV init</comment>
<comment xml:lang="hr">KSysV init paket</comment>
@@ -14015,7 +14503,7 @@
<comment xml:lang="pt">pacote inicial KSysV</comment>
<comment xml:lang="pt_BR">Pacote init do KSysV</comment>
<comment xml:lang="ro">Pachet KSysV init</comment>
- <comment xml:lang="ru">пакет инициализации KSysV</comment>
+ <comment xml:lang="ru">Пакет инициализации KSysV</comment>
<comment xml:lang="sk">BalíÄek KSysV init</comment>
<comment xml:lang="sl">Datoteka paketa KSysV init</comment>
<comment xml:lang="sq">Paketë init KSysV</comment>
@@ -14036,6 +14524,7 @@
<mime-type type="application/x-kugar">
<comment>Kugar document</comment>
<comment xml:lang="ar">مستند Kugar</comment>
+ <comment xml:lang="ast">Documentu de Kugar</comment>
<comment xml:lang="be@latin">Dakument Kugar</comment>
<comment xml:lang="bg">Документ — Kugar</comment>
<comment xml:lang="ca">document Kugar</comment>
@@ -14072,7 +14561,7 @@
<comment xml:lang="pt">documento Kugar</comment>
<comment xml:lang="pt_BR">Documento do Kugar</comment>
<comment xml:lang="ro">Document Kugar</comment>
- <comment xml:lang="ru">документ Kugar</comment>
+ <comment xml:lang="ru">Документ Kugar</comment>
<comment xml:lang="sk">Dokument Kugar</comment>
<comment xml:lang="sl">Dokument Kugar</comment>
<comment xml:lang="sq">Dokument Kugar</comment>
@@ -14089,6 +14578,7 @@
<mime-type type="application/x-kword">
<comment>KWord document</comment>
<comment xml:lang="ar">مستند KWord</comment>
+ <comment xml:lang="ast">Documentu de Kword</comment>
<comment xml:lang="be@latin">Dakument KWord</comment>
<comment xml:lang="bg">Документ — KWord</comment>
<comment xml:lang="ca">document KWord</comment>
@@ -14126,7 +14616,7 @@
<comment xml:lang="pt">documento KWord</comment>
<comment xml:lang="pt_BR">Documento do KWord</comment>
<comment xml:lang="ro">Document KWord</comment>
- <comment xml:lang="ru">документ KWord</comment>
+ <comment xml:lang="ru">Документ KWord</comment>
<comment xml:lang="sk">Dokument KWord</comment>
<comment xml:lang="sl">Dokument KWord</comment>
<comment xml:lang="sq">Dokument KWord</comment>
@@ -14156,6 +14646,7 @@
<mime-type type="application/x-kword-crypt">
<comment>KWord document (encrypted)</comment>
<comment xml:lang="ar">مستند KWord (مشÙر)</comment>
+ <comment xml:lang="ast">Documentu de Kword (cifráu)</comment>
<comment xml:lang="be@latin">Dakument KWord (zašyfravany)</comment>
<comment xml:lang="bg">Документ — KWord, шифриран</comment>
<comment xml:lang="ca">document KWord (xifrat)</comment>
@@ -14192,7 +14683,7 @@
<comment xml:lang="pt">documento KWord (encriptado)</comment>
<comment xml:lang="pt_BR">Documento do KWord (criptografado)</comment>
<comment xml:lang="ro">Document KWord (criptat)</comment>
- <comment xml:lang="ru">документ KWord (зашифрованный)</comment>
+ <comment xml:lang="ru">Документ KWord (зашифрованный)</comment>
<comment xml:lang="sk">Dokument KWord (šifrovaný)</comment>
<comment xml:lang="sl">Dokument KWord (Å¡ifriran)</comment>
<comment xml:lang="sq">Dokument KWord (i kriptuar)</comment>
@@ -14201,7 +14692,7 @@
<comment xml:lang="tr">KWord belgesi (ÅŸifreli)</comment>
<comment xml:lang="uk">документ KWord (зашифрований)</comment>
<comment xml:lang="vi">Tài liệu KWord (đã mật mã)</comment>
- <comment xml:lang="zh_CN">KWord 加密文档</comment>
+ <comment xml:lang="zh_CN">KWord 文档(加密)</comment>
<comment xml:lang="zh_TW">KWord 文件 (已加密)</comment>
<generic-icon name="x-office-document"/>
<magic priority="50">
@@ -14249,7 +14740,7 @@
<comment xml:lang="pt">arquivo LHA</comment>
<comment xml:lang="pt_BR">Pacote LHA</comment>
<comment xml:lang="ro">Arhivă LHA</comment>
- <comment xml:lang="ru">архив LHA</comment>
+ <comment xml:lang="ru">Ðрхив LHA</comment>
<comment xml:lang="sk">Archív LHA</comment>
<comment xml:lang="sl">Datoteka arhiva LHA</comment>
<comment xml:lang="sq">Arkiv LHA</comment>
@@ -14318,7 +14809,7 @@
<comment xml:lang="pt">arquivo LHZ</comment>
<comment xml:lang="pt_BR">Pacote LHZ</comment>
<comment xml:lang="ro">Arhivă LHZ</comment>
- <comment xml:lang="ru">архив LHZ</comment>
+ <comment xml:lang="ru">Ðрхив LHZ</comment>
<comment xml:lang="sk">Archív LHZ</comment>
<comment xml:lang="sl">Datoteka arhiva LHZ</comment>
<comment xml:lang="sq">Arkiv LHZ</comment>
@@ -14332,7 +14823,7 @@
<generic-icon name="package-x-generic"/>
<glob pattern="*.lhz"/>
</mime-type>
- <mime-type type="text/vnd.trolltech.linguist">
+ <mime-type type="text/vnd.qt.linguist">
<comment>message catalog</comment>
<comment xml:lang="ar">كتالوج الرسالة</comment>
<comment xml:lang="be@latin">kataloh paviedamleńniaŭ</comment>
@@ -14352,7 +14843,7 @@
<comment xml:lang="ga">catalóg theachtaireachtaí</comment>
<comment xml:lang="gl">catálogo de mensaxes</comment>
<comment xml:lang="he">קטלוג הודעות</comment>
- <comment xml:lang="hr">katalog poruka</comment>
+ <comment xml:lang="hr">Katalog poruka</comment>
<comment xml:lang="hu">üzenetkatalógus</comment>
<comment xml:lang="ia">Catalogo de messages</comment>
<comment xml:lang="id">katalog pesan</comment>
@@ -14371,7 +14862,7 @@
<comment xml:lang="pt">catálogo de mensagens</comment>
<comment xml:lang="pt_BR">Catálogo de mensagens</comment>
<comment xml:lang="ro">catalog de mesaje</comment>
- <comment xml:lang="ru">каталог Ñообщений</comment>
+ <comment xml:lang="ru">Каталог Ñообщений</comment>
<comment xml:lang="sk">Katalóg správ</comment>
<comment xml:lang="sl">katalogov sporoÄil</comment>
<comment xml:lang="sq">Katallog mesazhesh</comment>
@@ -14388,10 +14879,12 @@
</magic>
<glob pattern="*.ts"/>
<alias type="application/x-linguist"/>
+ <alias type="text/vnd.trolltech.linguist"/>
</mime-type>
<mime-type type="application/x-lyx">
<comment>LyX document</comment>
<comment xml:lang="ar">مستند LyX</comment>
+ <comment xml:lang="ast">Documentu de Lyx</comment>
<comment xml:lang="be@latin">Dakument LyX</comment>
<comment xml:lang="bg">Документ — LyX</comment>
<comment xml:lang="ca">document LyX</comment>
@@ -14428,7 +14921,7 @@
<comment xml:lang="pt">documento LyX</comment>
<comment xml:lang="pt_BR">Documento LyX</comment>
<comment xml:lang="ro">Document LyX</comment>
- <comment xml:lang="ru">документ LyX</comment>
+ <comment xml:lang="ru">Документ LyX</comment>
<comment xml:lang="sk">Dokument LyX</comment>
<comment xml:lang="sl">Dokument LyX</comment>
<comment xml:lang="sq">Dokument LyX</comment>
@@ -14459,6 +14952,7 @@
<comment xml:lang="eu">LZ4 artxiboa</comment>
<comment xml:lang="fi">LZ4-arkisto</comment>
<comment xml:lang="fr">archive LZ4</comment>
+ <comment xml:lang="ga">Cartlann LZ4</comment>
<comment xml:lang="gl">Arquivo LZ4</comment>
<comment xml:lang="he">×רכיון LZ4</comment>
<comment xml:lang="hr">LZ4 arhiva</comment>
@@ -14472,7 +14966,7 @@
<comment xml:lang="pl">Archiwum LZ4</comment>
<comment xml:lang="pt">arquivo LZ4</comment>
<comment xml:lang="pt_BR">Pacote LZ4</comment>
- <comment xml:lang="ru">архив LZ4</comment>
+ <comment xml:lang="ru">Ðрхив LZ4</comment>
<comment xml:lang="sk">Archív LZ4</comment>
<comment xml:lang="sl">Datoteka arhiva LZ4</comment>
<comment xml:lang="sr">ЛЗ4 архива</comment>
@@ -14491,21 +14985,31 @@
<mime-type type="application/x-lz4-compressed-tar">
<comment>Tar archive (LZ4-compressed)</comment>
<comment xml:lang="ca">arxiu tar (amb compressió LZ4)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimace LZ4)</comment>
<comment xml:lang="da">Tar-arkiv (LZ4-komprimeret)</comment>
<comment xml:lang="de">Tar-Archiv (LZ4-komprimiert)</comment>
+ <comment xml:lang="en_GB">Tar archive (LZ4-compressed)</comment>
<comment xml:lang="es">archivador Tar (comprimido con LZ4)</comment>
+ <comment xml:lang="eu">Tar artxiboa (LZ4-rekin konprimatua)</comment>
<comment xml:lang="fi">Tar-arkisto (LZ4-pakattu)</comment>
<comment xml:lang="fr">archive tar (compression LZ4)</comment>
+ <comment xml:lang="ga">cartlann Tar (comhbhrúite le LZ4)</comment>
<comment xml:lang="he">×רכיון Tar (מכווץ ×¢×´×™ LZ4)</comment>
+ <comment xml:lang="hr">Tar arhiva (LZ4 sažeto)</comment>
<comment xml:lang="hu">Tar archívum (LZ4-el tömörítve)</comment>
+ <comment xml:lang="id">arsip tar (terkompresi LZ4)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con LZ4)</comment>
<comment xml:lang="kk">Tar архиві (LZ4-пен Ñығылған)</comment>
<comment xml:lang="ko">Tar ë¬¶ìŒ íŒŒì¼(LZ4 압축)</comment>
<comment xml:lang="pl">Archiwum tar (kompresja LZ4)</comment>
<comment xml:lang="pt_BR">Arquvio Tar (compactado com LZ4)</comment>
- <comment xml:lang="ru">архив TAR (Ñжатый LZ4)</comment>
+ <comment xml:lang="ru">Ðрхив TAR (Ñжатый lz4)</comment>
<comment xml:lang="sk">Archív tar (komprimovaný pomocou LZ4)</comment>
+ <comment xml:lang="sr">Тар архива (запакована ЛЗ4-ом)</comment>
+ <comment xml:lang="sv">Tar-arkiv (LZ4-komprimerat)</comment>
+ <comment xml:lang="tr">Tar arşivi (LZ4 ile sıkıştırılmış)</comment>
<comment xml:lang="uk">архів tar (ÑтиÑнений LZ4)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件 (LZ4 压缩)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(LZ4 压缩)</comment>
<comment xml:lang="zh_TW">Tar å°å­˜æª” (LZ4 æ ¼å¼å£“縮)</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="application/x-lz4"/>
@@ -14546,7 +15050,7 @@
<comment xml:lang="pt">arquivo LZip</comment>
<comment xml:lang="pt_BR">Pacote Lzip</comment>
<comment xml:lang="ro">Arhivă Lzip</comment>
- <comment xml:lang="ru">архив LZIP</comment>
+ <comment xml:lang="ru">Ðрхив LZIP</comment>
<comment xml:lang="sk">Archív Lzip</comment>
<comment xml:lang="sl">Datoteka arhiva Lzip</comment>
<comment xml:lang="sr">Лзип архива</comment>
@@ -14564,21 +15068,31 @@
<mime-type type="application/x-lzip-compressed-tar">
<comment>Tar archive (lzip-compressed)</comment>
<comment xml:lang="ca">arxiu tar (amb compressió lzip)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimace lzip)</comment>
<comment xml:lang="da">Tar-arkiv (lzip-komprimeret)</comment>
<comment xml:lang="de">Tar-Archiv (lzip-komprimiert)</comment>
+ <comment xml:lang="en_GB">Tar archive (lzip-compressed)</comment>
<comment xml:lang="es">archivador Tar (comprimido con lzip)</comment>
+ <comment xml:lang="eu">Tar artxiboa (lzip-rekin konprimatua)</comment>
<comment xml:lang="fi">Tar-arkisto (lzip-pakattu)</comment>
<comment xml:lang="fr">archive tar (compressée lzip)</comment>
+ <comment xml:lang="ga">cartlann Tar (comhbhrúite le lzip)</comment>
<comment xml:lang="he">×רכיון Tar (מכווץ ×¢×´×™ lzip)</comment>
+ <comment xml:lang="hr">Tar arhiva (lzip sažeto)</comment>
<comment xml:lang="hu">Tar archívum (lzippel tömörítve)</comment>
+ <comment xml:lang="id">arsip tar (terkompresi lzip)</comment>
+ <comment xml:lang="it">Archivio tar (compresso con lzip)</comment>
<comment xml:lang="kk">Tar архиві (lzip-пен Ñығылған)</comment>
<comment xml:lang="ko">TAR ë¬¶ìŒ íŒŒì¼(LZIP 압축)</comment>
<comment xml:lang="pl">Archiwum tar (kompresja lzip)</comment>
<comment xml:lang="pt_BR">Arquivo Tar (compactado com lzip)</comment>
- <comment xml:lang="ru">архив TAR (Ñжатый lzip)</comment>
+ <comment xml:lang="ru">Ðрхив TAR (Ñжатый lzip)</comment>
<comment xml:lang="sk">Archív tar (komprimovaný pomocou lzip)</comment>
+ <comment xml:lang="sr">Тар архива (запакована лзипом)</comment>
+ <comment xml:lang="sv">Tar-arkiv (lzip-komprimerat)</comment>
+ <comment xml:lang="tr">Tar arşivi (lzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">архів tar (ÑтиÑнений lzip)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件 (lzip 压缩)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(lzip 压缩)</comment>
<comment xml:lang="zh_TW">Tar å°å­˜æª” (lzip æ ¼å¼å£“縮)</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="application/x-lzip"/>
@@ -14586,6 +15100,32 @@
</mime-type>
<mime-type type="application/x-lzpdf">
<comment>PDF document (lzip-compressed)</comment>
+ <comment xml:lang="ast">Documentu PDF (comprimíu en lzip)</comment>
+ <comment xml:lang="ca">document PDF (amb compressió lzip)</comment>
+ <comment xml:lang="cs">dokument PDF (komprimace lzip)</comment>
+ <comment xml:lang="de">PDF-Dokument (lzip-komprimiert)</comment>
+ <comment xml:lang="en_GB">PDF document (lzip-compressed)</comment>
+ <comment xml:lang="es">documento PDF (comprimido con lzip)</comment>
+ <comment xml:lang="eu">PDF dokumentua (lzip-rekin konprimitua)</comment>
+ <comment xml:lang="fi">PDF-asiakirja (lzip-pakattu)</comment>
+ <comment xml:lang="fr">document PDF (compressé lzip)</comment>
+ <comment xml:lang="ga">cáipéis PDF (comhbhrúite le lzip)</comment>
+ <comment xml:lang="hr">PDF dokument (lzip sažeto)</comment>
+ <comment xml:lang="hu">PDF dokumentum (lzip-tömörítésű)</comment>
+ <comment xml:lang="id">dokumen PDF (termkompresi lzip)</comment>
+ <comment xml:lang="it">Documento PDF (compresso con lzip)</comment>
+ <comment xml:lang="kk">PDF құжаты (lzip-пен Ñығылған)</comment>
+ <comment xml:lang="ko">PDF 문서(LZIP 압축)</comment>
+ <comment xml:lang="pl">Dokument PDF (kompresja lzip)</comment>
+ <comment xml:lang="pt_BR">Documento PDF (compactado com lzip)</comment>
+ <comment xml:lang="ru">Документ PDF (Ñжатый lzip)</comment>
+ <comment xml:lang="sk">Dokument PDF (komprimovaný pomocou lzip)</comment>
+ <comment xml:lang="sr">ПДФ документ (запакован лзип-ом)</comment>
+ <comment xml:lang="sv">PDF-dokument (lzip-komprimerat)</comment>
+ <comment xml:lang="tr">PDF belgesi (lzip ile sıkıştırılmış)</comment>
+ <comment xml:lang="uk">документ PDF (ÑтиÑнений lzip)</comment>
+ <comment xml:lang="zh_CN">PDF 文档(lzip 压缩)</comment>
+ <comment xml:lang="zh_TW">PDF 文件 (lzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/x-lzip"/>
<generic-icon name="x-office-document"/>
<glob pattern="*.pdf.lz"/>
@@ -14628,7 +15168,7 @@
<comment xml:lang="pt">arquivo LZMA</comment>
<comment xml:lang="pt_BR">Pacote LZMA</comment>
<comment xml:lang="ro">Arhivă LZMA</comment>
- <comment xml:lang="ru">архив LZMA</comment>
+ <comment xml:lang="ru">Ðрхив LZMA</comment>
<comment xml:lang="sk">Archív LZMA</comment>
<comment xml:lang="sl">Datoteka arhiva LZMA</comment>
<comment xml:lang="sq">Arkiv LZMA</comment>
@@ -14650,7 +15190,7 @@
<comment xml:lang="be@latin">ArchiÅ­ tar (LZMA-skampresavany)</comment>
<comment xml:lang="bg">Ðрхив — tar, компреÑиран Ñ LZMA</comment>
<comment xml:lang="ca">arxiu tar (amb compressió LZMA)</comment>
- <comment xml:lang="cs">archiv tar (komprimovaný pomocí LZMA)</comment>
+ <comment xml:lang="cs">archiv Tar (komprimace LZMA)</comment>
<comment xml:lang="da">Tar-arkiv (LZMA-komprimeret)</comment>
<comment xml:lang="de">Tar-Archiv (LZMA-komprimiert)</comment>
<comment xml:lang="el">ΑÏχείο Tar (συμπιεσμένο με LZMA)</comment>
@@ -14663,7 +15203,7 @@
<comment xml:lang="ga">cartlann Tar (comhbhrúite le LZMA)</comment>
<comment xml:lang="gl">arquivo Tar (comprimido con LZMA)</comment>
<comment xml:lang="he">×רכיון Tar (מכווץ ×¢×´×™ LZMA)</comment>
- <comment xml:lang="hr">Tar arhiva (komprimirana LZMA-om)</comment>
+ <comment xml:lang="hr">Tar arhiva (LZMA sažeta)</comment>
<comment xml:lang="hu">Tar archívum (LZMA-val tömörítve)</comment>
<comment xml:lang="ia">Archivo Tar (comprimite con LZMA)</comment>
<comment xml:lang="id">Arsip Tar (terkompresi LZMA)</comment>
@@ -14681,7 +15221,7 @@
<comment xml:lang="pt">arquivo Tar (compressão LZMA)</comment>
<comment xml:lang="pt_BR">Pacote Tar (compactado com LZMA)</comment>
<comment xml:lang="ro">Arhivă Tar (comprimată LZMA)</comment>
- <comment xml:lang="ru">архив TAR (Ñжатый LZMA)</comment>
+ <comment xml:lang="ru">Ðрхив TAR (Ñжатый lzma)</comment>
<comment xml:lang="sk">Archív tar (komprimovaný pomocou LZMA)</comment>
<comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z LZMA)</comment>
<comment xml:lang="sq">Arkiv tar (i kompresuar me LZMA)</comment>
@@ -14690,7 +15230,7 @@
<comment xml:lang="tr">Tar arşivi (LZMA ile sıkıştırılmış)</comment>
<comment xml:lang="uk">архів tar (ÑтиÑнений LZMA)</comment>
<comment xml:lang="vi">Kho nén tar (đã nén LZMA)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件 (LZMA 压缩)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(LZMA 压缩)</comment>
<comment xml:lang="zh_TW">Tar å°å­˜æª” (LZMA æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/x-lzma"/>
<generic-icon name="package-x-generic"/>
@@ -14736,7 +15276,7 @@
<comment xml:lang="pt">arquivo LZO</comment>
<comment xml:lang="pt_BR">Pacote LZO</comment>
<comment xml:lang="ro">Arhivă LZO</comment>
- <comment xml:lang="ru">архив LZO</comment>
+ <comment xml:lang="ru">Ðрхив LZO</comment>
<comment xml:lang="sk">Archív LZO</comment>
<comment xml:lang="sl">Datoteka arhiva LZO</comment>
<comment xml:lang="sq">Arkiv LZO</comment>
@@ -14764,9 +15304,9 @@
<comment xml:lang="el">Συμπιεσμένο αÏχείο Qpress</comment>
<comment xml:lang="en_GB">Qpress archive</comment>
<comment xml:lang="es">archivador de Qpress</comment>
- <comment xml:lang="eu">Qpress artxiboa</comment>
<comment xml:lang="fi">Qpress-arkisto</comment>
<comment xml:lang="fr">Archive Qpress</comment>
+ <comment xml:lang="ga">cartlann Qpress</comment>
<comment xml:lang="gl">Arquivo Qpress</comment>
<comment xml:lang="he">×רכיון Qpress</comment>
<comment xml:lang="hr">Qpress arhiva</comment>
@@ -14780,7 +15320,7 @@
<comment xml:lang="pl">Archiwum Qpress</comment>
<comment xml:lang="pt">arquivo Qpress</comment>
<comment xml:lang="pt_BR">Pacote Qpress</comment>
- <comment xml:lang="ru">архив Qpress</comment>
+ <comment xml:lang="ru">Ðрхив Qpress</comment>
<comment xml:lang="sk">Archív Qpress</comment>
<comment xml:lang="sl">Datoteka arhiva Qpress</comment>
<comment xml:lang="sr">ÐšÑƒÐ¿Ñ€ÐµÑ Ð°Ñ€Ñ…Ð¸Ð²Ð°</comment>
@@ -14806,6 +15346,7 @@
<comment xml:lang="eu">XAR artxiboa</comment>
<comment xml:lang="fi">XAR-arkisto</comment>
<comment xml:lang="fr">archive XAR</comment>
+ <comment xml:lang="ga">cartlann XAR</comment>
<comment xml:lang="he">×רכיון XAR</comment>
<comment xml:lang="hr">XAR arhiva</comment>
<comment xml:lang="hu">XAR archívum</comment>
@@ -14816,7 +15357,7 @@
<comment xml:lang="oc">Archiu XAR</comment>
<comment xml:lang="pl">Archiwum XAR</comment>
<comment xml:lang="pt_BR">Arquivo XAR</comment>
- <comment xml:lang="ru">архив XAR</comment>
+ <comment xml:lang="ru">Ðрхив XAR</comment>
<comment xml:lang="sk">Archív XAR</comment>
<comment xml:lang="sr">ИкÑÐР архива</comment>
<comment xml:lang="sv">XAR-arkiv</comment>
@@ -14843,9 +15384,9 @@
<comment xml:lang="el">Συμπιεσμένο αÏχείο Zlib</comment>
<comment xml:lang="en_GB">Zlib archive</comment>
<comment xml:lang="es">archivador Zlib</comment>
- <comment xml:lang="eu">Zlib artxiboa</comment>
<comment xml:lang="fi">Zlib-arkisto</comment>
<comment xml:lang="fr">Archive Zlib</comment>
+ <comment xml:lang="ga">cartlann Zlib</comment>
<comment xml:lang="gl">Arquivo Zlib</comment>
<comment xml:lang="he">×רכיון Zlib</comment>
<comment xml:lang="hr">Zlib arhiva</comment>
@@ -14859,7 +15400,7 @@
<comment xml:lang="pl">Archiwum Zlib</comment>
<comment xml:lang="pt">arquivo Zlib</comment>
<comment xml:lang="pt_BR">Pacote Zlib</comment>
- <comment xml:lang="ru">архив Zlib</comment>
+ <comment xml:lang="ru">Ðрхив Zlib</comment>
<comment xml:lang="sk">Archív Zlib</comment>
<comment xml:lang="sl">Datoteka arhiva Zlib</comment>
<comment xml:lang="sr">Злиб архива</comment>
@@ -14912,7 +15453,7 @@
<comment xml:lang="pt">apresentação MagicPoint</comment>
<comment xml:lang="pt_BR">Apresentação do MagicPoint</comment>
<comment xml:lang="ro">Prezentare MagicPoint</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ MagicPoint</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ MagicPoint</comment>
<comment xml:lang="sk">Prezentácia MagicPoint</comment>
<comment xml:lang="sl">Predstavitev MagicPoint</comment>
<comment xml:lang="sq">Prezantim MagicPoint</comment>
@@ -14966,7 +15507,7 @@
<comment xml:lang="pt">ficheiro MacBinary de Macintosh</comment>
<comment xml:lang="pt_BR">Arquivo do Macintosh MacBinary</comment>
<comment xml:lang="ro">Fișier Macintosh MacBinary</comment>
- <comment xml:lang="ru">файл Macintosh MacBinary</comment>
+ <comment xml:lang="ru">Файл Macintosh MacBinary</comment>
<comment xml:lang="sk">Súbor pre Macintosh MacBinary</comment>
<comment xml:lang="sl">Izvedljiva dvojiška datoteka Macintosh MacBinary</comment>
<comment xml:lang="sq">File MacBinary Macintosh</comment>
@@ -15019,7 +15560,7 @@
<comment xml:lang="pt">fluxo Matroska</comment>
<comment xml:lang="pt_BR">Transmissão do Matroska</comment>
<comment xml:lang="ro">Flux Matroska</comment>
- <comment xml:lang="ru">поток Matroska</comment>
+ <comment xml:lang="ru">Поток Matroska</comment>
<comment xml:lang="sk">Stream Matroska</comment>
<comment xml:lang="sl">PretoÄni vir Matroska</comment>
<comment xml:lang="sq">Stream Matroska</comment>
@@ -15045,6 +15586,7 @@
<mime-type type="video/x-matroska">
<comment>Matroska video</comment>
<comment xml:lang="ar">Matroska مرئي</comment>
+ <comment xml:lang="ast">Videu en Matroska</comment>
<comment xml:lang="be@latin">Videa Matroska</comment>
<comment xml:lang="bg">Видео — Matroska</comment>
<comment xml:lang="ca">vídeo Matroska</comment>
@@ -15062,7 +15604,7 @@
<comment xml:lang="ga">físeán Matroska</comment>
<comment xml:lang="gl">vídeo de Matroska</comment>
<comment xml:lang="he">ויד×ו Matroska</comment>
- <comment xml:lang="hr">Matroska video</comment>
+ <comment xml:lang="hr">Matroška video snimka</comment>
<comment xml:lang="hu">Matroska-videó</comment>
<comment xml:lang="ia">Video Matroska</comment>
<comment xml:lang="id">Video Matroska</comment>
@@ -15082,7 +15624,7 @@
<comment xml:lang="pt">vídeo Matroska</comment>
<comment xml:lang="pt_BR">Vídeo Matroska</comment>
<comment xml:lang="ro">Video Matroska</comment>
- <comment xml:lang="ru">видео Matroska</comment>
+ <comment xml:lang="ru">Видео Matroska</comment>
<comment xml:lang="sk">Video Matroska</comment>
<comment xml:lang="sl">Video datoteka Matroska</comment>
<comment xml:lang="sq">Video Matroska</comment>
@@ -15098,6 +15640,7 @@
</mime-type>
<mime-type type="video/x-matroska-3d">
<comment>Matroska 3D video</comment>
+ <comment xml:lang="ast">Videu en Matroska 3D</comment>
<comment xml:lang="ca">vídeo Matroska 3D</comment>
<comment xml:lang="cs">3D video Matroska</comment>
<comment xml:lang="da">Matroska 3D-video</comment>
@@ -15108,6 +15651,7 @@
<comment xml:lang="eu">Matroska 3D bideoa</comment>
<comment xml:lang="fi">Matroska 3D-video</comment>
<comment xml:lang="fr">vidéo Matroska 3D</comment>
+ <comment xml:lang="ga">físeán Matroska 3D</comment>
<comment xml:lang="gl">Video Matroska 3D</comment>
<comment xml:lang="he">סרטון תלת ממדי מסוג Matroska</comment>
<comment xml:lang="hr">Matroška 3D video snimka</comment>
@@ -15153,7 +15697,7 @@
<comment xml:lang="ga">fuaim Matroska</comment>
<comment xml:lang="gl">son de Matroska</comment>
<comment xml:lang="he">שמע Matroska</comment>
- <comment xml:lang="hr">Matroska audio</comment>
+ <comment xml:lang="hr">MatroÅ¡ka zvuÄni zapis</comment>
<comment xml:lang="hu">Matroska hang</comment>
<comment xml:lang="ia">Audio Matroska</comment>
<comment xml:lang="id">Audio Matroska</comment>
@@ -15172,7 +15716,7 @@
<comment xml:lang="pt">áudio Matroska</comment>
<comment xml:lang="pt_BR">Ãudio Matroska</comment>
<comment xml:lang="ro">Audio Matroska</comment>
- <comment xml:lang="ru">аудио Matroska</comment>
+ <comment xml:lang="ru">Ðудио Matroska</comment>
<comment xml:lang="sk">Zvuk Matroska</comment>
<comment xml:lang="sl">ZvoÄna datoteka Matroska</comment>
<comment xml:lang="sq">Audio Matroska</comment>
@@ -15189,6 +15733,7 @@
<mime-type type="video/webm">
<comment>WebM video</comment>
<comment xml:lang="ar">WebM مرئي</comment>
+ <comment xml:lang="ast">Videu en WebM</comment>
<comment xml:lang="bg">Видео — WebM</comment>
<comment xml:lang="ca">vídeo WebM</comment>
<comment xml:lang="cs">video WebM</comment>
@@ -15205,7 +15750,7 @@
<comment xml:lang="ga">físeán WebM</comment>
<comment xml:lang="gl">vídeo WebM</comment>
<comment xml:lang="he">ויד×ו WebM</comment>
- <comment xml:lang="hr">WebM video</comment>
+ <comment xml:lang="hr">WebM video snimka</comment>
<comment xml:lang="hu">WebM videó</comment>
<comment xml:lang="ia">Video WebM</comment>
<comment xml:lang="id">Video WebM</comment>
@@ -15221,7 +15766,7 @@
<comment xml:lang="pt">vídeo WebM</comment>
<comment xml:lang="pt_BR">Vídeo WebM</comment>
<comment xml:lang="ro">Video WebM</comment>
- <comment xml:lang="ru">видео WebM</comment>
+ <comment xml:lang="ru">Видео WebM</comment>
<comment xml:lang="sk">Video WebM</comment>
<comment xml:lang="sl">Video datoteka WebM</comment>
<comment xml:lang="sr">ВебМ видео</comment>
@@ -15261,7 +15806,7 @@
<comment xml:lang="ga">fuaim WebM</comment>
<comment xml:lang="gl">son WebM</comment>
<comment xml:lang="he">שמע WebM</comment>
- <comment xml:lang="hr">WebM audio</comment>
+ <comment xml:lang="hr">WebM zvuÄni zapis</comment>
<comment xml:lang="hu">WebM hang</comment>
<comment xml:lang="ia">Audio WebM</comment>
<comment xml:lang="id">Audio WebM</comment>
@@ -15277,7 +15822,7 @@
<comment xml:lang="pt">áudio WebM</comment>
<comment xml:lang="pt_BR">Ãudio WebM</comment>
<comment xml:lang="ro">Audio WebM</comment>
- <comment xml:lang="ru">аудио WebM</comment>
+ <comment xml:lang="ru">Ðудио WebM</comment>
<comment xml:lang="sk">Zvuk WebM</comment>
<comment xml:lang="sl">ZvoÄna datoteka WebM</comment>
<comment xml:lang="sr">ВебМ звук</comment>
@@ -15300,6 +15845,7 @@
<comment xml:lang="eu">MHTML web artxiboa</comment>
<comment xml:lang="fi">MHTML-kooste</comment>
<comment xml:lang="fr">archive web MHTML</comment>
+ <comment xml:lang="ga">cartlann ghréasáin MHTML</comment>
<comment xml:lang="gl">Arquivo web MHTML</comment>
<comment xml:lang="he">×רכיון רשת MHTML</comment>
<comment xml:lang="hr">MHTML web arhiva</comment>
@@ -15315,7 +15861,7 @@
<comment xml:lang="pl">Archiwum witryny MHTML</comment>
<comment xml:lang="pt">arquivo web MHTML</comment>
<comment xml:lang="pt_BR">Pacote web MHTML</comment>
- <comment xml:lang="ru">веб-архив MHTML</comment>
+ <comment xml:lang="ru">Веб-архив MHTML</comment>
<comment xml:lang="sk">Webový archív MHTML</comment>
<comment xml:lang="sl">Spletni arhiv MHTML</comment>
<comment xml:lang="sr">МХТМЛ веб архива</comment>
@@ -15333,6 +15879,7 @@
<mime-type type="application/mxf">
<comment>MXF video</comment>
<comment xml:lang="ar">MXF مرئي</comment>
+ <comment xml:lang="ast">Videu en MXF</comment>
<comment xml:lang="bg">Видео — MXF</comment>
<comment xml:lang="ca">vídeo MXF</comment>
<comment xml:lang="cs">video MXF</comment>
@@ -15349,7 +15896,7 @@
<comment xml:lang="ga">físeán MXF</comment>
<comment xml:lang="gl">vídeo MXF</comment>
<comment xml:lang="he">ויד×ו MXF</comment>
- <comment xml:lang="hr">MXF video</comment>
+ <comment xml:lang="hr">MXF video snimka</comment>
<comment xml:lang="hu">MXF videó</comment>
<comment xml:lang="ia">Video MXF</comment>
<comment xml:lang="id">Video MXF</comment>
@@ -15366,7 +15913,7 @@
<comment xml:lang="pt">vídeo MXF</comment>
<comment xml:lang="pt_BR">Vídeo MXF</comment>
<comment xml:lang="ro">Video MXF</comment>
- <comment xml:lang="ru">видео MXF</comment>
+ <comment xml:lang="ru">Видео MXF</comment>
<comment xml:lang="sk">Video MXF</comment>
<comment xml:lang="sl">Video datoteka MXF</comment>
<comment xml:lang="sr">МИкÑФ видео</comment>
@@ -15421,7 +15968,7 @@
<comment xml:lang="pt">ficheiro OCL</comment>
<comment xml:lang="pt_BR">Arquivo OCL</comment>
<comment xml:lang="ro">Fișier OCL</comment>
- <comment xml:lang="ru">файл OCL</comment>
+ <comment xml:lang="ru">Файл OCL</comment>
<comment xml:lang="sk">Súbor OCL</comment>
<comment xml:lang="sl">Datoteka OCL</comment>
<comment xml:lang="sq">File OCL</comment>
@@ -15451,6 +15998,7 @@
<comment xml:lang="eu">COBOL iturburu-kodea</comment>
<comment xml:lang="fi">COBOL-lähdekoodi</comment>
<comment xml:lang="fr">fichier source COBOL</comment>
+ <comment xml:lang="ga">cód foinseach COBOL</comment>
<comment xml:lang="gl">ficheiro fonte de COBOL</comment>
<comment xml:lang="he">קובץ מקור של COBOL</comment>
<comment xml:lang="hr">COBOL izvorna datoteka</comment>
@@ -15468,14 +16016,14 @@
<comment xml:lang="pl">Plik źródłowy COBOL</comment>
<comment xml:lang="pt">ficheiro origem COBOL</comment>
<comment xml:lang="pt_BR">Arquivo de código-fonte em COBOL</comment>
- <comment xml:lang="ru">файл иÑходного кода на COBOL</comment>
+ <comment xml:lang="ru">Файл иÑходного кода на COBOL</comment>
<comment xml:lang="sk">Zdrojový súbor COBOLu</comment>
<comment xml:lang="sl">Izvorna koda COBOL</comment>
<comment xml:lang="sr">изворна датотека КОБОЛ-а</comment>
<comment xml:lang="sv">COBOL-källkodsfil</comment>
<comment xml:lang="tr">COBOL kaynak dosyası</comment>
<comment xml:lang="uk">вихідний код мовою COBOL</comment>
- <comment xml:lang="zh_CN">COBOL æº</comment>
+ <comment xml:lang="zh_CN">COBOL æºæ–‡ä»¶</comment>
<comment xml:lang="zh_TW">COBOL æºæª”</comment>
<acronym>COBOL</acronym>
<expanded-acronym>COmmon Business Oriented Language</expanded-acronym>
@@ -15496,6 +16044,7 @@
<comment xml:lang="eu">Mobipocket liburua</comment>
<comment xml:lang="fi">Mobipocket e-kirja</comment>
<comment xml:lang="fr">livre numérique Mobipocket</comment>
+ <comment xml:lang="ga">r-leabhar Mobipocket</comment>
<comment xml:lang="gl">E-book Mobipocket</comment>
<comment xml:lang="he">ספר ×לקטרוני של Mobipocket</comment>
<comment xml:lang="hr">Mobipocket e-knjiga</comment>
@@ -15513,7 +16062,7 @@
<comment xml:lang="pl">E-book Mobipocket</comment>
<comment xml:lang="pt">ebook Mobipocket</comment>
<comment xml:lang="pt_BR">E-book Mobipocket</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ ÐºÐ½Ð¸Ð³Ð° Mobipocket</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ ÐºÐ½Ð¸Ð³Ð° Mobipocket</comment>
<comment xml:lang="sk">E-kniha Mobipocket</comment>
<comment xml:lang="sl">e-knjiga Mobipocket</comment>
<comment xml:lang="sr">Мобипокет ел. књига</comment>
@@ -15537,6 +16086,7 @@
<mime-type type="application/x-mif">
<comment>Adobe FrameMaker MIF document</comment>
<comment xml:lang="ar">مستند أدوبي الصانع للإطارات MIF</comment>
+ <comment xml:lang="ast">Documentu MIF d'Adobe FrameMaker</comment>
<comment xml:lang="be@latin">Dakument Adobe FrameMaker MIF</comment>
<comment xml:lang="bg">Документ — Adobe FrameMaker MIF</comment>
<comment xml:lang="ca">document MIF d'Adobe FrameMaker</comment>
@@ -15573,7 +16123,7 @@
<comment xml:lang="pt">documento Adobe FrameMaker MIF</comment>
<comment xml:lang="pt_BR">Documento MIF do Adobe FrameMaker</comment>
<comment xml:lang="ro">Document Adobe FrameMaker MIF</comment>
- <comment xml:lang="ru">документ Adobe FrameMaker MIF</comment>
+ <comment xml:lang="ru">Документ Adobe FrameMaker MIF</comment>
<comment xml:lang="sk">Dokument Adobe FrameMaker MIF</comment>
<comment xml:lang="sl">Dokument Adobe FrameMaker MIF</comment>
<comment xml:lang="sq">Dokument MIF Adobe FrameMaker</comment>
@@ -15606,7 +16156,7 @@
<comment xml:lang="ga">leabharmharcanna Mozilla</comment>
<comment xml:lang="gl">Marcadores de Mozilla</comment>
<comment xml:lang="he">סימניה של Mozilla</comment>
- <comment xml:lang="hr">Mozilla knjižne oznake</comment>
+ <comment xml:lang="hr">Mozilla zabilješke</comment>
<comment xml:lang="hu">Mozilla-könyvjelzők</comment>
<comment xml:lang="ia">Marcapaginas Mozilla</comment>
<comment xml:lang="id">Bookmark Mozilla</comment>
@@ -15625,7 +16175,7 @@
<comment xml:lang="pt">marcadores do Mozilla</comment>
<comment xml:lang="pt_BR">Favoritos do Mozilla</comment>
<comment xml:lang="ro">Semne de carte Mozilla</comment>
- <comment xml:lang="ru">закладки Mozilla</comment>
+ <comment xml:lang="ru">Закладки Mozilla</comment>
<comment xml:lang="sk">Záložky Mozilla</comment>
<comment xml:lang="sl">Datoteka zaznamkov Mozilla</comment>
<comment xml:lang="sq">Libërshënues Mozilla</comment>
@@ -15683,7 +16233,7 @@
<comment xml:lang="pt">executável DOS/Windows</comment>
<comment xml:lang="pt_BR">Executável do DOS/Windows</comment>
<comment xml:lang="ro">Executabil DOS/Windows</comment>
- <comment xml:lang="ru">иÑполнÑемый файл DOS/Windows</comment>
+ <comment xml:lang="ru">ИÑполнÑемый файл DOS/Windows</comment>
<comment xml:lang="sk">Spustiteľný súbor pre DOS/Windows</comment>
<comment xml:lang="sl">Izvedljiva datoteka DOS/Windows</comment>
<comment xml:lang="sq">I ekzekutueshëm DOS/Windows</comment>
@@ -15741,7 +16291,7 @@
<comment xml:lang="sk">Internetový odkaz</comment>
<comment xml:lang="sl">Internetna bližnjica</comment>
<comment xml:lang="sq">Shkurtim internet</comment>
- <comment xml:lang="sr">Интернет пречица</comment>
+ <comment xml:lang="sr">интернет пречица</comment>
<comment xml:lang="sv">Internetgenväg</comment>
<comment xml:lang="tr">İnternet kısayolu</comment>
<comment xml:lang="uk">інтернет-поÑиланнÑ</comment>
@@ -15759,6 +16309,7 @@
<mime-type type="application/x-mswrite">
<comment>WRI document</comment>
<comment xml:lang="ar">مستند WRI</comment>
+ <comment xml:lang="ast">Documentu WRI</comment>
<comment xml:lang="be@latin">Dakument WRI</comment>
<comment xml:lang="bg">Документ — WRI</comment>
<comment xml:lang="ca">document WRI</comment>
@@ -15794,7 +16345,7 @@
<comment xml:lang="pt">documento WRI</comment>
<comment xml:lang="pt_BR">Documento WRI</comment>
<comment xml:lang="ro">Document WRI</comment>
- <comment xml:lang="ru">документ WRI</comment>
+ <comment xml:lang="ru">Документ WRI</comment>
<comment xml:lang="sk">Dokument WRI</comment>
<comment xml:lang="sl">Dokument WRI</comment>
<comment xml:lang="sq">Dokument WRI</comment>
@@ -15847,7 +16398,7 @@
<comment xml:lang="oc">ROM MSX</comment>
<comment xml:lang="pl">Plik ROM konsoli MSX</comment>
<comment xml:lang="pt">ROM MSX</comment>
- <comment xml:lang="pt_BR">ROM do MSX</comment>
+ <comment xml:lang="pt_BR">ROM de MSX</comment>
<comment xml:lang="ro">ROM MSX</comment>
<comment xml:lang="ru">MSX ROM</comment>
<comment xml:lang="sk">ROM pre MSX</comment>
@@ -15900,7 +16451,7 @@
<comment xml:lang="pt">macro M4</comment>
<comment xml:lang="pt_BR">Macro M4</comment>
<comment xml:lang="ro">Macro M4</comment>
- <comment xml:lang="ru">Ð¼Ð°ÐºÑ€Ð¾Ñ M4</comment>
+ <comment xml:lang="ru">ÐœÐ°ÐºÑ€Ð¾Ñ M4</comment>
<comment xml:lang="sk">Makro M4</comment>
<comment xml:lang="sl">Makro datoteka M4</comment>
<comment xml:lang="sq">Macro M4</comment>
@@ -15952,7 +16503,7 @@
<comment xml:lang="oc">ROM Nintendo64</comment>
<comment xml:lang="pl">Plik ROM konsoli Nintendo64</comment>
<comment xml:lang="pt">ROM Nintendo64</comment>
- <comment xml:lang="pt_BR">ROM do Nintendo64</comment>
+ <comment xml:lang="pt_BR">ROM de Nintendo64</comment>
<comment xml:lang="ro">ROM Nintendo64</comment>
<comment xml:lang="ru">Nintendo64 ROM</comment>
<comment xml:lang="sk">ROM pre Nintendo64</comment>
@@ -15963,7 +16514,7 @@
<comment xml:lang="tr">Nintendo64 ROM</comment>
<comment xml:lang="uk">ППП Nintendo64</comment>
<comment xml:lang="vi">ROM Nintendo64</comment>
- <comment xml:lang="zh_CN">Nintendo64 ROM</comment>
+ <comment xml:lang="zh_CN">任天堂 64 ROM</comment>
<comment xml:lang="zh_TW">Nintendo64 ROM</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.n64"/>
@@ -16000,7 +16551,7 @@
<comment xml:lang="ga">nasc Nautilus</comment>
<comment xml:lang="gl">ligazón de nautilus</comment>
<comment xml:lang="he">קישור של Nautilus</comment>
- <comment xml:lang="hr">Nautilus veza</comment>
+ <comment xml:lang="hr">Nautilusova poveznica</comment>
<comment xml:lang="hu">Nautilus-link</comment>
<comment xml:lang="ia">Ligamine Nautilus</comment>
<comment xml:lang="id">Taut Nautilus</comment>
@@ -16019,7 +16570,7 @@
<comment xml:lang="pt">atalho Nautilus</comment>
<comment xml:lang="pt_BR">Link do Nautilus</comment>
<comment xml:lang="ro">Legătură Nautilus</comment>
- <comment xml:lang="ru">ÑÑылка Nautilus</comment>
+ <comment xml:lang="ru">СÑылка Nautilus</comment>
<comment xml:lang="sk">Odkaz Nautilus</comment>
<comment xml:lang="sl">Datoteka povezave Nautilus</comment>
<comment xml:lang="sq">Lidhje Nautilus</comment>
@@ -16039,25 +16590,49 @@
<mime-type type="application/x-neo-geo-pocket-rom">
<comment>Neo-Geo Pocket ROM</comment>
<comment xml:lang="ca">ROM de Neo-Geo Pocket</comment>
+ <comment xml:lang="cs">ROM pro Neo-Geo Pocket</comment>
<comment xml:lang="da">Neo-Geo Pocket ROM</comment>
<comment xml:lang="de">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="en_GB">Neo-Geo Pocket ROM</comment>
<comment xml:lang="es">ROM de Neo-Geo Pocket</comment>
+ <comment xml:lang="eu">Neo-Geo Pocket ROM</comment>
<comment xml:lang="fi">Neo-Geo Pocket -ROM</comment>
<comment xml:lang="fr">ROM Neo-Geo Pocket</comment>
+ <comment xml:lang="ga">ROM Neo-Geo Pocket</comment>
+ <comment xml:lang="hr">Neo-Geo Pocket ROM</comment>
<comment xml:lang="hu">Neo-Geo Pocket ROM</comment>
+ <comment xml:lang="id">ROM Neo-Geo Pocket</comment>
+ <comment xml:lang="it">ROM Neo-Geo Pocket</comment>
<comment xml:lang="kk">Neo-Geo Pocket ROM</comment>
<comment xml:lang="ko">네오지오 í¬ì¼“ 롬</comment>
<comment xml:lang="pl">Plik ROM konsoli Neo-Geo Pocket</comment>
<comment xml:lang="pt_BR">ROM de Neo-Geo Pocket</comment>
<comment xml:lang="ru">Neo-Geo Pocket ROM</comment>
<comment xml:lang="sk">ROM pre Neo-Geo Pocket</comment>
+ <comment xml:lang="sr">Ðео-Гео Покет РОМ</comment>
+ <comment xml:lang="sv">Neo-Geo Pocket-rom</comment>
+ <comment xml:lang="tr">Neo-Geo Pocket ROM</comment>
<comment xml:lang="uk">ППП Neo-Geo Pocket</comment>
<comment xml:lang="zh_CN">Neo-Geo Pocket ROM</comment>
<comment xml:lang="zh_TW">Neo-Geo Pocket ROM</comment>
<generic-icon name="application-x-executable"/>
<glob pattern="*.ngp"/>
<magic>
- <match value="COPYRIGHT BY SNK CORPORATION" type="string" offset="0"/>
+ <match value="0x0" type="byte" offset="35">
+ <match value="COPYRIGHT BY SNK CORPORATION" type="string" offset="0"/>
+ <match value=" LICENSED BY SNK CORPORATION" type="string" offset="0"/>
+ </match>
+ </magic>
+ </mime-type>
+ <mime-type type="application/x-neo-geo-pocket-color-rom">
+ <comment>Neo-Geo Pocket Color ROM</comment>
+ <generic-icon name="application-x-executable"/>
+ <glob pattern="*.ngc"/>
+ <magic>
+ <match value="0x10" type="byte" offset="35">
+ <match value="COPYRIGHT BY SNK CORPORATION" type="string" offset="0"/>
+ <match value=" LICENSED BY SNK CORPORATION" type="string" offset="0"/>
+ </match>
</magic>
</mime-type>
<mime-type type="application/x-nes-rom">
@@ -16099,7 +16674,7 @@
<comment xml:lang="oc">ROM NES</comment>
<comment xml:lang="pl">Plik ROM konsoli NES</comment>
<comment xml:lang="pt">ROM NES</comment>
- <comment xml:lang="pt_BR">ROM do NES</comment>
+ <comment xml:lang="pt_BR">ROM de NES</comment>
<comment xml:lang="ro">ROM NES</comment>
<comment xml:lang="ru">NES ROM</comment>
<comment xml:lang="sk">ROM pre NES</comment>
@@ -16121,6 +16696,7 @@
<mime-type type="application/x-netcdf">
<comment>Unidata NetCDF document</comment>
<comment xml:lang="ar">مستند Unidata NetCDF</comment>
+ <comment xml:lang="ast">Documentu NetCDF d'Unidata</comment>
<comment xml:lang="be@latin">Dakument Unidata NetCDF</comment>
<comment xml:lang="bg">Документ — Unidata NetCDF</comment>
<comment xml:lang="ca">document d'Unidata NetCDF</comment>
@@ -16157,7 +16733,7 @@
<comment xml:lang="pt">documento Unidata NetCDF</comment>
<comment xml:lang="pt_BR">Documento do Unidata NetCDF</comment>
<comment xml:lang="ro">Document Unidata NetCDF</comment>
- <comment xml:lang="ru">документ Unidata NetCDF</comment>
+ <comment xml:lang="ru">Документ Unidata NetCDF</comment>
<comment xml:lang="sk">Dokument Unidata NetCDF</comment>
<comment xml:lang="sl">Dokument Unidata NetCDF</comment>
<comment xml:lang="sq">Dokument Unidata NetCDF</comment>
@@ -16186,6 +16762,7 @@
<comment xml:lang="es">índice NewzBin de usenet</comment>
<comment xml:lang="eu">NewzBin usenet indizea</comment>
<comment xml:lang="fr">index usenet </comment>
+ <comment xml:lang="ga">innéacs usenet NewzBin</comment>
<comment xml:lang="gl">Ãndice de usenet NEwzBin</comment>
<comment xml:lang="he">×ינדקס שרתי חדשות NewzBin</comment>
<comment xml:lang="hr">NewzBin usenet indeks</comment>
@@ -16202,14 +16779,14 @@
<comment xml:lang="pl">Indeks grup dyskusyjnych NewzBin</comment>
<comment xml:lang="pt">índice usenet NewzBin</comment>
<comment xml:lang="pt_BR">Ãndice de usenet NewzBin</comment>
- <comment xml:lang="ru">Ð¸Ð½Ð´ÐµÐºÑ usenet NewzBin</comment>
+ <comment xml:lang="ru">Ð˜Ð½Ð´ÐµÐºÑ usenet NewzBin</comment>
<comment xml:lang="sk">Index Usenetu NewzBin</comment>
<comment xml:lang="sl">Kazalo usenet NewzBin</comment>
<comment xml:lang="sr">Њузбин Ð¿Ð¾Ð¿Ð¸Ñ Ñ˜ÑƒÐ·Ð½ÐµÑ‚Ð°</comment>
<comment xml:lang="sv">NewzBin-usenetindex</comment>
<comment xml:lang="tr">NewzBin usenet dizini</comment>
<comment xml:lang="uk">покажчик usenet NewzBin</comment>
- <comment xml:lang="zh_CN">NewzBin usenet 索引</comment>
+ <comment xml:lang="zh_CN">NewzBin Usenet 索引</comment>
<comment xml:lang="zh_TW">NewzBin usenet 索引</comment>
<sub-class-of type="application/xml"/>
<magic priority="80">
@@ -16236,10 +16813,10 @@
<comment xml:lang="ga">cód réada</comment>
<comment xml:lang="gl">código obxecto</comment>
<comment xml:lang="he">קוד ×ובייקט</comment>
- <comment xml:lang="hr">kod objekta</comment>
+ <comment xml:lang="hr">Object kôd</comment>
<comment xml:lang="hu">tárgykód</comment>
<comment xml:lang="ia">Codice objecto</comment>
- <comment xml:lang="id">kode object</comment>
+ <comment xml:lang="id">kode objek</comment>
<comment xml:lang="it">Codice oggetto</comment>
<comment xml:lang="ja">オブジェクトコード</comment>
<comment xml:lang="kk">объектті коды</comment>
@@ -16255,7 +16832,7 @@
<comment xml:lang="pt">código de objeto</comment>
<comment xml:lang="pt_BR">Código-objeto</comment>
<comment xml:lang="ro">cod sursă obiect</comment>
- <comment xml:lang="ru">объектный код</comment>
+ <comment xml:lang="ru">Объектный код</comment>
<comment xml:lang="sk">Objektový kód</comment>
<comment xml:lang="sl">predmetna koda</comment>
<comment xml:lang="sq">Kod objekti</comment>
@@ -16299,7 +16876,7 @@
<comment xml:lang="ga">formáid mhalairte Annodex</comment>
<comment xml:lang="gl">formato intercambiábel de Annodex</comment>
<comment xml:lang="he">תבנית החלפת Annodex</comment>
- <comment xml:lang="hr">Annodex oblik za razmjenu</comment>
+ <comment xml:lang="hr">Annodex format razmjene</comment>
<comment xml:lang="hu">Annodex csereformátum</comment>
<comment xml:lang="ia">Formato de excambio Annodex</comment>
<comment xml:lang="id">Format pertukaran Annodex</comment>
@@ -16316,7 +16893,7 @@
<comment xml:lang="pt">formato de troca Annodex</comment>
<comment xml:lang="pt_BR">Formato de troca Annodex</comment>
<comment xml:lang="ro">Format schimb Annodex</comment>
- <comment xml:lang="ru">формат обмена Annodex</comment>
+ <comment xml:lang="ru">Формат обмена Annodex</comment>
<comment xml:lang="sk">Formát pre výmenu Annodex</comment>
<comment xml:lang="sl">Izmenjalna datoteka Annodex</comment>
<comment xml:lang="sr">ÐнодекÑов Ð·Ð°Ð¿Ð¸Ñ Ñ€Ð°Ð·Ð¼ÐµÐ½Ðµ</comment>
@@ -16340,6 +16917,7 @@
<mime-type type="video/annodex">
<comment>Annodex Video</comment>
<comment xml:lang="ar">Annodex مرئي</comment>
+ <comment xml:lang="ast">Videu n'Annodex</comment>
<comment xml:lang="bg">Видео — Annodex</comment>
<comment xml:lang="ca">Annodex Video</comment>
<comment xml:lang="cs">video Annodex</comment>
@@ -16353,10 +16931,10 @@
<comment xml:lang="fi">Annodex-video</comment>
<comment xml:lang="fo">Annodex video</comment>
<comment xml:lang="fr">vidéo Annodex</comment>
- <comment xml:lang="ga">físeán Annodex</comment>
+ <comment xml:lang="ga">Físeán Annodex</comment>
<comment xml:lang="gl">vídeo de Annodex</comment>
<comment xml:lang="he">ויד×ו Annodex</comment>
- <comment xml:lang="hr">Annodex Video</comment>
+ <comment xml:lang="hr">Annodex video snimka</comment>
<comment xml:lang="hu">Annodex videó</comment>
<comment xml:lang="ia">Video Annodex</comment>
<comment xml:lang="id">Video Annodex</comment>
@@ -16373,7 +16951,7 @@
<comment xml:lang="pt">vídeo Annodex</comment>
<comment xml:lang="pt_BR">Vídeo Annodex</comment>
<comment xml:lang="ro">Video Annodex</comment>
- <comment xml:lang="ru">видео Annodex</comment>
+ <comment xml:lang="ru">Видео Annodex</comment>
<comment xml:lang="sk">Video Annodex</comment>
<comment xml:lang="sl">Video datoteka Annodex</comment>
<comment xml:lang="sr">ÐÐ½Ð¾Ð´ÐµÐºÑ Ð²Ð¸Ð´ÐµÐ¾</comment>
@@ -16410,10 +16988,10 @@
<comment xml:lang="fi">Annodex-ääni</comment>
<comment xml:lang="fo">Annodex ljóður</comment>
<comment xml:lang="fr">audio Annodex</comment>
- <comment xml:lang="ga">fuaim Annodex</comment>
+ <comment xml:lang="ga">Fuaim Annodex</comment>
<comment xml:lang="gl">son de Annodex</comment>
<comment xml:lang="he">שמע Annodex</comment>
- <comment xml:lang="hr">Annodex Audio</comment>
+ <comment xml:lang="hr">Annodex zvuÄni zapis</comment>
<comment xml:lang="hu">Annodex hang</comment>
<comment xml:lang="ia">Audio Annodex</comment>
<comment xml:lang="id">Audio Annodex</comment>
@@ -16430,7 +17008,7 @@
<comment xml:lang="pt">áudio Annodex</comment>
<comment xml:lang="pt_BR">Ãudio Annodex</comment>
<comment xml:lang="ro">Audio Annodex</comment>
- <comment xml:lang="ru">аудио Annodex</comment>
+ <comment xml:lang="ru">Ðудио Annodex</comment>
<comment xml:lang="sk">Zvuk Annodex</comment>
<comment xml:lang="sl">ZvoÄna datoteka Annodex</comment>
<comment xml:lang="sr">ÐÐ½Ð¾Ð´ÐµÐºÑ Ð°ÑƒÐ´Ð¸Ð¾</comment>
@@ -16489,7 +17067,7 @@
<comment xml:lang="pt">ficheiro multimédia Ogg</comment>
<comment xml:lang="pt_BR">Arquivo multimídia Ogg</comment>
<comment xml:lang="ro">Fișier multimedia Ogg</comment>
- <comment xml:lang="ru">мультимедийный файл Ogg</comment>
+ <comment xml:lang="ru">Мультимедийный файл Ogg</comment>
<comment xml:lang="sk">Súbor multimédií Ogg</comment>
<comment xml:lang="sl">VeÄpredstavnostna datoteka Ogg</comment>
<comment xml:lang="sq">File multimedial Ogg</comment>
@@ -16523,7 +17101,7 @@
<comment xml:lang="fi">Ogg-ääni</comment>
<comment xml:lang="fo">Ogg ljóður</comment>
<comment xml:lang="fr">audio Ogg</comment>
- <comment xml:lang="ga">fuaim Ogg</comment>
+ <comment xml:lang="ga">Fuaim Ogg</comment>
<comment xml:lang="gl">son Ogg</comment>
<comment xml:lang="he">שמע Ogg</comment>
<comment xml:lang="hr">Ogg zvuÄni zapis</comment>
@@ -16545,7 +17123,7 @@
<comment xml:lang="pt">áudio Ogg</comment>
<comment xml:lang="pt_BR">Ãudio Ogg</comment>
<comment xml:lang="ro">Audio Ogg</comment>
- <comment xml:lang="ru">аудио Ogg</comment>
+ <comment xml:lang="ru">Ðудио Ogg</comment>
<comment xml:lang="sk">Zvuk Ogg</comment>
<comment xml:lang="sl">ZvoÄna datoteka Ogg</comment>
<comment xml:lang="sq">Audio Ogg</comment>
@@ -16568,6 +17146,7 @@
<mime-type type="video/ogg">
<comment>Ogg Video</comment>
<comment xml:lang="ar">Ogg مرئي</comment>
+ <comment xml:lang="ast">Videu n'Ogg</comment>
<comment xml:lang="be@latin">Videa Ogg</comment>
<comment xml:lang="bg">Видео — Ogg</comment>
<comment xml:lang="ca">vídeo Ogg</comment>
@@ -16581,7 +17160,7 @@
<comment xml:lang="fi">Ogg-video</comment>
<comment xml:lang="fo">Ogg Video</comment>
<comment xml:lang="fr">vidéo Ogg</comment>
- <comment xml:lang="ga">físeán Ogg</comment>
+ <comment xml:lang="ga">Físeán Ogg</comment>
<comment xml:lang="gl">vídeo Ogg</comment>
<comment xml:lang="he">ויד×ו Ogg</comment>
<comment xml:lang="hr">Ogg video snimka</comment>
@@ -16603,7 +17182,7 @@
<comment xml:lang="pt">vídeo Ogg</comment>
<comment xml:lang="pt_BR">Vídeo Ogg</comment>
<comment xml:lang="ro">Video Ogg</comment>
- <comment xml:lang="ru">видео Ogg</comment>
+ <comment xml:lang="ru">Видео Ogg</comment>
<comment xml:lang="sk">Video Ogg</comment>
<comment xml:lang="sl">Video datoteka Ogg</comment>
<comment xml:lang="sq">Video Ogg</comment>
@@ -16664,7 +17243,7 @@
<comment xml:lang="pt">áudio Ogg Vorbis</comment>
<comment xml:lang="pt_BR">Ãudio Ogg Vorbis</comment>
<comment xml:lang="ro">Audio Ogg Vorbis</comment>
- <comment xml:lang="ru">аудио Ogg Vorbis</comment>
+ <comment xml:lang="ru">Ðудио Ogg Vorbis</comment>
<comment xml:lang="sk">Zvuk Ogg Vorbis</comment>
<comment xml:lang="sl">ZvoÄna datoteka Ogg Vorbis</comment>
<comment xml:lang="sq">Audio Ogg Vorbis</comment>
@@ -16724,7 +17303,7 @@
<comment xml:lang="pt">áudio Ogg FLAC</comment>
<comment xml:lang="pt_BR">Ãudio Ogg FLAC</comment>
<comment xml:lang="ro">Audio Ogg FLAC</comment>
- <comment xml:lang="ru">аудио Ogg FLAC</comment>
+ <comment xml:lang="ru">Ðудио Ogg FLAC</comment>
<comment xml:lang="sk">Zvuk Ogg FLAC</comment>
<comment xml:lang="sl">ZvoÄna datoteka Ogg FLAC</comment>
<comment xml:lang="sq">Audio Ogg FLAC</comment>
@@ -16760,6 +17339,7 @@
<comment xml:lang="eu">Opus audioa</comment>
<comment xml:lang="fi">Opus-ääni</comment>
<comment xml:lang="fr">audio Opus</comment>
+ <comment xml:lang="ga">fuaim Opus</comment>
<comment xml:lang="gl">Son Opus</comment>
<comment xml:lang="he">שמע Opus</comment>
<comment xml:lang="hr">Opus zvuÄni zapis</comment>
@@ -16828,7 +17408,7 @@
<comment xml:lang="pt">áudio Ogg Speex</comment>
<comment xml:lang="pt_BR">Ãudio Ogg Speex</comment>
<comment xml:lang="ro">Audio Ogg Speex</comment>
- <comment xml:lang="ru">аудио Ogg Speex</comment>
+ <comment xml:lang="ru">Ðудио Ogg Speex</comment>
<comment xml:lang="sk">Zvuk Ogg Speex</comment>
<comment xml:lang="sl">ZvoÄna datoteka Ogg Speex</comment>
<comment xml:lang="sq">Audio Ogg Speex</comment>
@@ -16867,7 +17447,7 @@
<comment xml:lang="ga">fuaim Speex</comment>
<comment xml:lang="gl">son Speex</comment>
<comment xml:lang="he">שמע של Speex</comment>
- <comment xml:lang="hr">Speex audio</comment>
+ <comment xml:lang="hr">Speex zvuÄni zapis</comment>
<comment xml:lang="hu">Speex hang</comment>
<comment xml:lang="ia">Audio Speex</comment>
<comment xml:lang="id">Audio Speex</comment>
@@ -16885,7 +17465,7 @@
<comment xml:lang="pt">áudio Speex</comment>
<comment xml:lang="pt_BR">Ãudio Speex</comment>
<comment xml:lang="ro">Audio Speex</comment>
- <comment xml:lang="ru">аудио Speex</comment>
+ <comment xml:lang="ru">Ðудио Speex</comment>
<comment xml:lang="sk">Zvuk Speex</comment>
<comment xml:lang="sl">ZvoÄna datoteka Speex</comment>
<comment xml:lang="sq">Audio Speex</comment>
@@ -16904,6 +17484,7 @@
<mime-type type="video/x-theora+ogg">
<comment>Ogg Theora video</comment>
<comment xml:lang="ar">Ogg Theora مرئي</comment>
+ <comment xml:lang="ast">Videu n'Ogg Theora</comment>
<comment xml:lang="be@latin">Videa Ogg Theora</comment>
<comment xml:lang="bg">Видео — Ogg Theora</comment>
<comment xml:lang="ca">vídeo Ogg Theora</comment>
@@ -16939,7 +17520,7 @@
<comment xml:lang="pt">vídeo Ogg Theora</comment>
<comment xml:lang="pt_BR">Vídeo Ogg Theora</comment>
<comment xml:lang="ro">Video Ogg Theora</comment>
- <comment xml:lang="ru">видео Ogg Theora</comment>
+ <comment xml:lang="ru">Видео Ogg Theora</comment>
<comment xml:lang="sk">Video Ogg Theora</comment>
<comment xml:lang="sl">Video datoteka Ogg Theora</comment>
<comment xml:lang="sq">Video Ogg Theora</comment>
@@ -16962,6 +17543,7 @@
<mime-type type="video/x-ogm+ogg">
<comment>OGM video</comment>
<comment xml:lang="ar">OGM مرئي</comment>
+ <comment xml:lang="ast">Videu n'OGM</comment>
<comment xml:lang="be@latin">Videa OGM</comment>
<comment xml:lang="bg">Видео — OGM</comment>
<comment xml:lang="ca">vídeo OGM</comment>
@@ -16979,7 +17561,7 @@
<comment xml:lang="ga">físeán OGM</comment>
<comment xml:lang="gl">vídeo OGM</comment>
<comment xml:lang="he">ויד×ו OGM</comment>
- <comment xml:lang="hr">OGM video</comment>
+ <comment xml:lang="hr">OGM video snimka</comment>
<comment xml:lang="hu">OGM-videó</comment>
<comment xml:lang="ia">Video OGM</comment>
<comment xml:lang="id">Video OGM</comment>
@@ -16998,7 +17580,7 @@
<comment xml:lang="pt">vídeo OGM</comment>
<comment xml:lang="pt_BR">Vídeo OGM</comment>
<comment xml:lang="ro">Video OGM</comment>
- <comment xml:lang="ru">видео OGM</comment>
+ <comment xml:lang="ru">Видео OGM</comment>
<comment xml:lang="sk">Video OGM</comment>
<comment xml:lang="sl">Video datoteka OGM</comment>
<comment xml:lang="sq">Video OGM</comment>
@@ -17022,6 +17604,7 @@
<mime-type type="application/x-ole-storage">
<comment>OLE2 compound document storage</comment>
<comment xml:lang="ar">تخزين مجمع مستند OLE2</comment>
+ <comment xml:lang="ast">Almacenamientu de documentos compuestu por OLE2</comment>
<comment xml:lang="be@latin">SchoviÅ¡Äa dla kampanentaÅ­ dakumentu OLE2</comment>
<comment xml:lang="bg">СъÑтавен документ-хранилище — OLE2</comment>
<comment xml:lang="ca">emmagatzematge de documents compostos OLE2</comment>
@@ -17036,7 +17619,7 @@
<comment xml:lang="fi">OLE2-yhdisteasiakirjatallenne</comment>
<comment xml:lang="fo">OLE2 samansett skjalagoymsla</comment>
<comment xml:lang="fr">document de stockage composé OLE2</comment>
- <comment xml:lang="ga">stóras cháipéisí comhshuite OLE2</comment>
+ <comment xml:lang="ga">stóras cáipéisí comhshuite OLE2</comment>
<comment xml:lang="gl">almacenamento de documento composto OLE2</comment>
<comment xml:lang="he">×חסון מסמך משותף OLE2</comment>
<comment xml:lang="hr">OLE2 pohrana složenog dokumenta</comment>
@@ -17058,7 +17641,7 @@
<comment xml:lang="pt">armazenamento de documento composto OLE2</comment>
<comment xml:lang="pt_BR">Armazenamento de documento composto OLE2</comment>
<comment xml:lang="ro">Document de stocare compus OLE2</comment>
- <comment xml:lang="ru">хранилище ÑоÑтавных документов OLE2</comment>
+ <comment xml:lang="ru">Хранилище ÑоÑтавных документов OLE2</comment>
<comment xml:lang="sk">Úložisko zloženého dokumentu OLE2</comment>
<comment xml:lang="sl">Združeni dokument OLE2</comment>
<comment xml:lang="sq">Arkiv dokumenti i përbërë OLE2</comment>
@@ -17077,6 +17660,7 @@
</mime-type>
<mime-type type="application/vnd.ms-publisher">
<comment>Microsoft Publisher document</comment>
+ <comment xml:lang="ast">Documentu de Microsoft Publisher</comment>
<comment xml:lang="ca">document de Microsoft Publisher</comment>
<comment xml:lang="cs">dokument Microsoft Publisher</comment>
<comment xml:lang="da">Microsoft Publisher-dokument</comment>
@@ -17087,6 +17671,7 @@
<comment xml:lang="eu">Microsoft Publisher dokumentua</comment>
<comment xml:lang="fi">Microsoft Publisher -asiakirja</comment>
<comment xml:lang="fr">document Microsoft Publisher</comment>
+ <comment xml:lang="ga">cáipéis Microsoft Publisher</comment>
<comment xml:lang="gl">Documento de Microsoft Publisher</comment>
<comment xml:lang="he">מסמך Microsoft Publisher</comment>
<comment xml:lang="hr">Microsoft Publisher dokument</comment>
@@ -17131,7 +17716,7 @@
<comment xml:lang="ga">pacáiste Windows Installer</comment>
<comment xml:lang="gl">paquete de instalación de Windows</comment>
<comment xml:lang="he">חבילה של Windows Installer</comment>
- <comment xml:lang="hr">Windows Installer paket</comment>
+ <comment xml:lang="hr">Windows Instalacijski paket</comment>
<comment xml:lang="hu">Windows Installer csomag</comment>
<comment xml:lang="ia">Pacchetto Windows Installer</comment>
<comment xml:lang="id">Paket Windows Installer</comment>
@@ -17148,7 +17733,7 @@
<comment xml:lang="pt">pacote de instalação Windows</comment>
<comment xml:lang="pt_BR">Pacote do Windows Installer</comment>
<comment xml:lang="ro">Pachet instalator Windows</comment>
- <comment xml:lang="ru">пакет Windows Installer</comment>
+ <comment xml:lang="ru">Пакет Windows Installer</comment>
<comment xml:lang="sk">Balík Windows Installer</comment>
<comment xml:lang="sl">Datoteka paketa Windows namestilnika</comment>
<comment xml:lang="sq">Paketë Windows Installer</comment>
@@ -17202,7 +17787,7 @@
<comment xml:lang="pt">folha de cálculo GNU Oleo</comment>
<comment xml:lang="pt_BR">Planilha do GNU Oleo</comment>
<comment xml:lang="ro">Foaie de calcul GNU Oleo</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° GNU Oleo</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° GNU Oleo</comment>
<comment xml:lang="sk">Zošit GNU Oleo</comment>
<comment xml:lang="sl">Preglednica GNU Oleo</comment>
<comment xml:lang="sq">Fletë llogaritje GNU Oleo</comment>
@@ -17211,7 +17796,7 @@
<comment xml:lang="tr">GNU Oleo çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ GNU Oleo</comment>
<comment xml:lang="vi">Bảng tính Oleo của GNU</comment>
- <comment xml:lang="zh_CN">GNU Oleo 工作簿</comment>
+ <comment xml:lang="zh_CN">GNU Oleo 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">GNU Oleo 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="50">
@@ -17258,7 +17843,7 @@
<comment xml:lang="pt">arquivo PAK</comment>
<comment xml:lang="pt_BR">Pacote PAK</comment>
<comment xml:lang="ro">Arhivă PAK</comment>
- <comment xml:lang="ru">архив PAK</comment>
+ <comment xml:lang="ru">Ðрхив PAK</comment>
<comment xml:lang="sk">Archív PAK</comment>
<comment xml:lang="sl">Datoteka arhiva PAK</comment>
<comment xml:lang="sq">Arkiv PAK</comment>
@@ -17267,7 +17852,7 @@
<comment xml:lang="tr">PAK arÅŸivi</comment>
<comment xml:lang="uk">архів PAK</comment>
<comment xml:lang="vi">Kho nén PAK</comment>
- <comment xml:lang="zh_CN">AR 归档文件</comment>
+ <comment xml:lang="zh_CN">PAK 归档文件</comment>
<comment xml:lang="zh_TW">PAK å°å­˜æª”</comment>
<generic-icon name="package-x-generic"/>
<magic priority="80">
@@ -17316,7 +17901,7 @@
<comment xml:lang="pt">base de dados Palm OS</comment>
<comment xml:lang="pt_BR">Banco de dados do Palm OS</comment>
<comment xml:lang="ro">Bază de date Palm OS</comment>
- <comment xml:lang="ru">база данных Palm OS</comment>
+ <comment xml:lang="ru">База данных Palm OS</comment>
<comment xml:lang="sk">Databáza Palm OS</comment>
<comment xml:lang="sl">Podatkovna zbirka Palm OS</comment>
<comment xml:lang="sq">Bankë me të dhëna Palm OS</comment>
@@ -17370,7 +17955,7 @@
<comment xml:lang="pt">arquivo Parchive</comment>
<comment xml:lang="pt_BR">Pacote Parchive</comment>
<comment xml:lang="ro">Arhivă Parchive</comment>
- <comment xml:lang="ru">архив Parchive</comment>
+ <comment xml:lang="ru">Ðрхив Parchive</comment>
<comment xml:lang="sk">Archív Parchive</comment>
<comment xml:lang="sl">Datoteka arhiva Parchive</comment>
<comment xml:lang="sq">Arkiv Parchive</comment>
@@ -17429,7 +18014,7 @@
<comment xml:lang="pt">executável PEF</comment>
<comment xml:lang="pt_BR">Executável PEF</comment>
<comment xml:lang="ro">Executabil PEF</comment>
- <comment xml:lang="ru">иÑполнÑемый файл PEF</comment>
+ <comment xml:lang="ru">ИÑполнÑемый файл PEF</comment>
<comment xml:lang="sk">Spustiteľný súbor PEF</comment>
<comment xml:lang="sl">Izvedljiva datoteka PEF</comment>
<comment xml:lang="sq">E ekzekutueshme PEF</comment>
@@ -17485,7 +18070,7 @@
<comment xml:lang="pt">script Perl</comment>
<comment xml:lang="pt_BR">Script Perl</comment>
<comment xml:lang="ro">Script Perl</comment>
- <comment xml:lang="ru">Ñценарий Perl</comment>
+ <comment xml:lang="ru">Сценарий Perl</comment>
<comment xml:lang="sk">Skript jazyka Perl</comment>
<comment xml:lang="sl">Skriptna datoteka Perl</comment>
<comment xml:lang="sq">Script Perl</comment>
@@ -17499,6 +18084,7 @@
<sub-class-of type="application/x-executable"/>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-script"/>
+ <alias type="text/x-perl"/>
<magic priority="50">
<match value='eval \"exec /usr/local/bin/perl' type="string" offset="0"/>
<match value="/bin/perl" type="string" offset="2:16"/>
@@ -17563,7 +18149,7 @@
<comment xml:lang="pt">script PHP</comment>
<comment xml:lang="pt_BR">Script PHP</comment>
<comment xml:lang="ro">Script PHP</comment>
- <comment xml:lang="ru">Ñценарий PHP</comment>
+ <comment xml:lang="ru">Сценарий PHP</comment>
<comment xml:lang="sk">Skript PHP</comment>
<comment xml:lang="sl">Skriptna datoteka PHP</comment>
<comment xml:lang="sq">Script PHP</comment>
@@ -17600,7 +18186,7 @@
<comment xml:lang="fi">PKCS#7-varmennenippu</comment>
<comment xml:lang="fo">PKCS#7 váttanar bundi</comment>
<comment xml:lang="fr">lot de certificats PKCS#7</comment>
- <comment xml:lang="ga">cuach theastas PKCS#7</comment>
+ <comment xml:lang="ga">burla teastas PKCS#7</comment>
<comment xml:lang="gl">paquete de certificado PKCS#7</comment>
<comment xml:lang="he">בקשה מוסמכת PKCS#7</comment>
<comment xml:lang="hr">PKCS#7 paket vjerodajnica</comment>
@@ -17619,7 +18205,7 @@
<comment xml:lang="pt">pacote de certificação PKCS#7</comment>
<comment xml:lang="pt_BR">Pacote de certificados PKCS#7</comment>
<comment xml:lang="ro">Pachet certificat PKCS#7</comment>
- <comment xml:lang="ru">пакет Ñертификатов PKCS#7</comment>
+ <comment xml:lang="ru">Пакет Ñертификата PKCS#7</comment>
<comment xml:lang="sk">Zväzok certifikátov PKCS#7</comment>
<comment xml:lang="sl">Datoteka potrdila PKCS#7</comment>
<comment xml:lang="sr">ПКЦС#7 пакет уверења</comment>
@@ -17651,7 +18237,7 @@
<comment xml:lang="fi">PKCS#12-varmennenippu</comment>
<comment xml:lang="fo">PKCS#12 váttanar bundi</comment>
<comment xml:lang="fr">lot de certificats PKCS#12</comment>
- <comment xml:lang="ga">cuach theastas PKCS#12</comment>
+ <comment xml:lang="ga">burla teastas PKCS#12</comment>
<comment xml:lang="gl">paquete de certificado PKCS#12</comment>
<comment xml:lang="he">בקשה מוסמכת PKCS#12</comment>
<comment xml:lang="hr">PKCS#12 paket vjerodajnica</comment>
@@ -17673,7 +18259,7 @@
<comment xml:lang="pt">pacote de certificação PKCS#12</comment>
<comment xml:lang="pt_BR">Pacote de certificados PKCS#12</comment>
<comment xml:lang="ro">Certificat împachetat PKCS#12</comment>
- <comment xml:lang="ru">пакет Ñертификатов PKCS#12</comment>
+ <comment xml:lang="ru">Пакет Ñертификата PKCS#12</comment>
<comment xml:lang="sk">Zväzok certifikátov PKCS#12</comment>
<comment xml:lang="sl">Datoteka potrdila PKCS#12</comment>
<comment xml:lang="sq">Bundle çertifikate PKCS#12</comment>
@@ -17727,7 +18313,7 @@
<comment xml:lang="pt">folha de cálculo PlanPerfect</comment>
<comment xml:lang="pt_BR">Planilha do PlanPerfect</comment>
<comment xml:lang="ro">Foaie de calcul PlanPerfect</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° PlanPerfect</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° PlanPerfect</comment>
<comment xml:lang="sk">Zošit PlanPerfect</comment>
<comment xml:lang="sl">Preglednica PlanPerfect</comment>
<comment xml:lang="sq">Fletë llogaritjesh PlanPerfect</comment>
@@ -17736,7 +18322,7 @@
<comment xml:lang="tr">PlanPerfect çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ PlanPerfect</comment>
<comment xml:lang="vi">Bảng tính PlanPerfect</comment>
- <comment xml:lang="zh_CN">PlanPerfect 工作簿</comment>
+ <comment xml:lang="zh_CN">PlanPerfect 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">PlanPerfect 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.pln"/>
@@ -17744,6 +18330,7 @@
<mime-type type="application/x-pocket-word">
<comment>Pocket Word document</comment>
<comment xml:lang="ar">مستند Pocket Word</comment>
+ <comment xml:lang="ast">Documentu de PocketWord</comment>
<comment xml:lang="bg">Документ — Pocket Word</comment>
<comment xml:lang="ca">document de Pocket Word</comment>
<comment xml:lang="cs">dokument Pocket Word</comment>
@@ -17775,7 +18362,7 @@
<comment xml:lang="pt">documento Pocket Word</comment>
<comment xml:lang="pt_BR">Documento do Pocket Word</comment>
<comment xml:lang="ro">Document Pocket Word</comment>
- <comment xml:lang="ru">документ Pocket Word</comment>
+ <comment xml:lang="ru">Документ Pocket Word</comment>
<comment xml:lang="sk">Dokument Pocket Word</comment>
<comment xml:lang="sl">Dokument Pocket Word</comment>
<comment xml:lang="sr">документ Покет Ворда</comment>
@@ -17831,7 +18418,7 @@
<comment xml:lang="pt">resultados de análise de perfil</comment>
<comment xml:lang="pt_BR">Resultados do profiler</comment>
<comment xml:lang="ro">rezultate profiler</comment>
- <comment xml:lang="ru">результаты профилированиÑ</comment>
+ <comment xml:lang="ru">Результаты профилированиÑ</comment>
<comment xml:lang="sk">Výsledky profilera</comment>
<comment xml:lang="sl">rezultati profilirnika</comment>
<comment xml:lang="sq">Rezultate të profiluesit</comment>
@@ -17840,7 +18427,7 @@
<comment xml:lang="tr">profil sonuçları</comment>
<comment xml:lang="uk">результати профілюваннÑ</comment>
<comment xml:lang="vi">kết quả nét hiện trạng</comment>
- <comment xml:lang="zh_CN">profiler 结果</comment>
+ <comment xml:lang="zh_CN">探查器结果</comment>
<comment xml:lang="zh_TW">硬體資訊產生器æˆæžœ</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-x-generic"/>
@@ -17849,6 +18436,7 @@
<mime-type type="application/x-pw">
<comment>Pathetic Writer document</comment>
<comment xml:lang="ar">مستند Pathetic Writer</comment>
+ <comment xml:lang="ast">Documentu de Pathetic Writer</comment>
<comment xml:lang="be@latin">Dakument Pathetic Writer</comment>
<comment xml:lang="bg">Документ — Pathetic Writer</comment>
<comment xml:lang="ca">document de Pathetic Writer</comment>
@@ -17885,7 +18473,7 @@
<comment xml:lang="pt">documento do Pathetic Writer</comment>
<comment xml:lang="pt_BR">Documento do Pathetic Writer</comment>
<comment xml:lang="ro">Document Pathetic Writer</comment>
- <comment xml:lang="ru">документ Pathetic Writer</comment>
+ <comment xml:lang="ru">Документ Pathetic Writer</comment>
<comment xml:lang="sk">Dokument Pathetic Writer</comment>
<comment xml:lang="sl">Dokument Pathetic Writer</comment>
<comment xml:lang="sq">Dokument Pathetic Writer</comment>
@@ -17940,7 +18528,7 @@
<comment xml:lang="pt">código binário Python</comment>
<comment xml:lang="pt_BR">Código compilado Python</comment>
<comment xml:lang="ro">Bytecode Python</comment>
- <comment xml:lang="ru">байт-код Python</comment>
+ <comment xml:lang="ru">Байт-код Python</comment>
<comment xml:lang="sk">Bajtový kód Python</comment>
<comment xml:lang="sl">Datoteka bitne kode Python</comment>
<comment xml:lang="sq">Bytecode Python</comment>
@@ -17959,6 +18547,7 @@
</mime-type>
<mime-type type="application/x-qtiplot">
<comment>QtiPlot document</comment>
+ <comment xml:lang="ast">Documentu de QtiPlot</comment>
<comment xml:lang="ca">document QtiPlot</comment>
<comment xml:lang="cs">dokument GtiPlot</comment>
<comment xml:lang="da">QtiPlot-dokument</comment>
@@ -17969,6 +18558,7 @@
<comment xml:lang="eu">QtiPlot dokumentua</comment>
<comment xml:lang="fi">QtiPlot-asiakirja</comment>
<comment xml:lang="fr">document QtiPlot</comment>
+ <comment xml:lang="ga">cáipéis QtiPlot</comment>
<comment xml:lang="gl">Documento de QtiPilot</comment>
<comment xml:lang="he">מסמך QtiPlot</comment>
<comment xml:lang="hr">QtiPlot dokument</comment>
@@ -17984,7 +18574,7 @@
<comment xml:lang="pl">Dokument QtiPlot</comment>
<comment xml:lang="pt">documento QtiPlot</comment>
<comment xml:lang="pt_BR">Documento do QtiPlot</comment>
- <comment xml:lang="ru">документ QtiPlot</comment>
+ <comment xml:lang="ru">Документ QtiPlot</comment>
<comment xml:lang="sk">Dokument QtiPlot</comment>
<comment xml:lang="sl">Dokument QtiPlot</comment>
<comment xml:lang="sr">КутиПлот документ</comment>
@@ -18040,7 +18630,7 @@
<comment xml:lang="pt">folha de cálculo Quattro Pro</comment>
<comment xml:lang="pt_BR">Planilha do Quattro Pro</comment>
<comment xml:lang="ro">Foaie de calcul Quattro Pro</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Quattro Pro</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Quattro Pro</comment>
<comment xml:lang="sk">Zošit Quattro Pro</comment>
<comment xml:lang="sl">Preglednica Quattro Pro</comment>
<comment xml:lang="sq">Fletë llogaritjesh Quattro Pro</comment>
@@ -18049,7 +18639,7 @@
<comment xml:lang="tr">Quattro Pro çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Quattro Pro</comment>
<comment xml:lang="vi">Bảng tính Quattro Pro</comment>
- <comment xml:lang="zh_CN">Quattro Pro 工作簿</comment>
+ <comment xml:lang="zh_CN">Quattro Pro 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">Quattro Pro 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.wb1"/>
@@ -18093,7 +18683,7 @@
<comment xml:lang="pt">lista de reprodução QuickTime metalink</comment>
<comment xml:lang="pt_BR">Lista de reprodução metalink do QuickTime</comment>
<comment xml:lang="ro">Listă cu metalegături QuickTime</comment>
- <comment xml:lang="ru">ÑпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¼ÐµÑ‚Ð°-ÑÑылок QuickTime</comment>
+ <comment xml:lang="ru">СпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¼ÐµÑ‚Ð°-ÑÑылок QuickTime</comment>
<comment xml:lang="sk">Zoznam skladieb metalink QuickTime</comment>
<comment xml:lang="sl">Seznam predvajanja QuickTime</comment>
<comment xml:lang="sq">Listë titujsh metalink QuickTime</comment>
@@ -18102,7 +18692,7 @@
<comment xml:lang="tr">QuickTime metalink çalma listesi</comment>
<comment xml:lang="uk">ÑпиÑок Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ QuickTime metalink</comment>
<comment xml:lang="vi">Danh mục nhạc siêu liên kết Quicktime</comment>
- <comment xml:lang="zh_CN">QuickTime 元链接播放列表</comment>
+ <comment xml:lang="zh_CN">QuickTime Metalink 播放列表</comment>
<comment xml:lang="zh_TW">QuickTime metalink 播放清單</comment>
<generic-icon name="video-x-generic"/>
<sub-class-of type="video/quicktime"/>
@@ -18120,6 +18710,7 @@
<mime-type type="application/x-qw">
<comment>Quicken document</comment>
<comment xml:lang="ar">مستند Quicken</comment>
+ <comment xml:lang="ast">Documentu de Quicken</comment>
<comment xml:lang="az">Quicken sənədi</comment>
<comment xml:lang="be@latin">Dakument Quicken</comment>
<comment xml:lang="bg">Документ — Quicken</comment>
@@ -18158,7 +18749,7 @@
<comment xml:lang="pt">documento Quicken</comment>
<comment xml:lang="pt_BR">Documento do Quicken</comment>
<comment xml:lang="ro">Document Quicken</comment>
- <comment xml:lang="ru">документ Quicken</comment>
+ <comment xml:lang="ru">Документ Quicken</comment>
<comment xml:lang="sk">Dokument Quicken</comment>
<comment xml:lang="sl">Dokument Quicken</comment>
<comment xml:lang="sq">Dokument Quicken</comment>
@@ -18212,7 +18803,7 @@
<comment xml:lang="pt">arquivo RAR</comment>
<comment xml:lang="pt_BR">Pacote RAR</comment>
<comment xml:lang="ro">Arhivă RAR</comment>
- <comment xml:lang="ru">архив RAR</comment>
+ <comment xml:lang="ru">Ðрхив RAR</comment>
<comment xml:lang="sk">Archív RAR</comment>
<comment xml:lang="sl">Datoteka arhiva RAR</comment>
<comment xml:lang="sq">Arkiv RAR</comment>
@@ -18272,7 +18863,7 @@
<comment xml:lang="pt">arquivo DAR</comment>
<comment xml:lang="pt_BR">Pacote DAR</comment>
<comment xml:lang="ro">Arhivă DAR</comment>
- <comment xml:lang="ru">архив DAR</comment>
+ <comment xml:lang="ru">Ðрхив DAR</comment>
<comment xml:lang="sk">Archív DAR</comment>
<comment xml:lang="sl">Datoteka arhiva DAR</comment>
<comment xml:lang="sq">Arkiv DAR</comment>
@@ -18328,7 +18919,7 @@
<comment xml:lang="pt">arquivo Alzip</comment>
<comment xml:lang="pt_BR">Pacote Alzip</comment>
<comment xml:lang="ro">Arhivă Alzip</comment>
- <comment xml:lang="ru">архив ALZIP</comment>
+ <comment xml:lang="ru">Ðрхив ALZIP</comment>
<comment xml:lang="sk">Archív Alzip</comment>
<comment xml:lang="sl">Datoteka arhiva Alzip</comment>
<comment xml:lang="sq">Arkiv Alzip</comment>
@@ -18358,14 +18949,14 @@
<comment xml:lang="en_GB">rejected patch</comment>
<comment xml:lang="eo">reĵeta flikaĵo</comment>
<comment xml:lang="es">parche rechazado</comment>
- <comment xml:lang="eu">baztertutako bide-izena</comment>
+ <comment xml:lang="eu">baztertutako adabakia</comment>
<comment xml:lang="fi">hylättyjen muutosten tiedosto</comment>
<comment xml:lang="fo">vrakað rætting</comment>
<comment xml:lang="fr">correctif rejeté</comment>
<comment xml:lang="ga">paiste diúltaithe</comment>
<comment xml:lang="gl">parche rexeitado</comment>
<comment xml:lang="he">טל××™ שנדחה</comment>
- <comment xml:lang="hr">odbijena zakrpa</comment>
+ <comment xml:lang="hr">Odbijena zakrpa</comment>
<comment xml:lang="hu">visszautasított folt</comment>
<comment xml:lang="ia">Patch rejectate</comment>
<comment xml:lang="id">patch ditolak</comment>
@@ -18384,7 +18975,7 @@
<comment xml:lang="pt">patch rejeitado</comment>
<comment xml:lang="pt_BR">Arquivo de patch rejeitado</comment>
<comment xml:lang="ro">petec respsins</comment>
- <comment xml:lang="ru">отвергнутый патч</comment>
+ <comment xml:lang="ru">Отклонённый патч</comment>
<comment xml:lang="sk">Odmietnutá záplata</comment>
<comment xml:lang="sl">zavrnjen popravek</comment>
<comment xml:lang="sq">Patch i kthyer mbrapsht</comment>
@@ -18439,7 +19030,7 @@
<comment xml:lang="pt">pacote RPM</comment>
<comment xml:lang="pt_BR">Pacote RPM</comment>
<comment xml:lang="ro">Pachet RPM</comment>
- <comment xml:lang="ru">пакет RPM</comment>
+ <comment xml:lang="ru">Пакет RPM</comment>
<comment xml:lang="sk">Balík RPM</comment>
<comment xml:lang="sl">Datoteka paketa RPM</comment>
<comment xml:lang="sq">Paketë RPM</comment>
@@ -18469,6 +19060,7 @@
<comment xml:lang="eu">Iturburu RPM paketea</comment>
<comment xml:lang="fi">RPM-lähdepaketti</comment>
<comment xml:lang="fr">paquet source RPM</comment>
+ <comment xml:lang="ga">pacáiste foinse RPM</comment>
<comment xml:lang="gl">Paquete RPM de fontes</comment>
<comment xml:lang="he">חבילת מקור RPM</comment>
<comment xml:lang="hr">RPM paket izvora</comment>
@@ -18484,7 +19076,7 @@
<comment xml:lang="pl">Źródłowy pakiet RPM</comment>
<comment xml:lang="pt">pacote origem RPM</comment>
<comment xml:lang="pt_BR">Pacote fonte RPM</comment>
- <comment xml:lang="ru">пакет RPM Ñ Ð¸Ñходным кодом</comment>
+ <comment xml:lang="ru">Пакет RPM Ñ Ð¸Ñходным кодом</comment>
<comment xml:lang="sk">Zdrojový balík RPM</comment>
<comment xml:lang="sl">Paket izvorne kode RPM</comment>
<comment xml:lang="sr">изворни РПМ пакет</comment>
@@ -18537,7 +19129,7 @@
<comment xml:lang="pt">script Ruby</comment>
<comment xml:lang="pt_BR">Script Ruby</comment>
<comment xml:lang="ro">Script Ruby</comment>
- <comment xml:lang="ru">Ñценарий Ruby</comment>
+ <comment xml:lang="ru">Сценарий Ruby</comment>
<comment xml:lang="sk">Skript Ruby</comment>
<comment xml:lang="sl">Skriptna datoteka Ruby</comment>
<comment xml:lang="sq">Script Ruby</comment>
@@ -18596,7 +19188,7 @@
<comment xml:lang="pt">script Markaby</comment>
<comment xml:lang="pt_BR">Script Markaby</comment>
<comment xml:lang="ro">Script Markaby</comment>
- <comment xml:lang="ru">Ñценарий Markaby</comment>
+ <comment xml:lang="ru">Сценарий Markaby</comment>
<comment xml:lang="sk">Skript Markaby</comment>
<comment xml:lang="sl">Skriptna datoteka Markaby</comment>
<comment xml:lang="sq">Script Markaby</comment>
@@ -18623,6 +19215,7 @@
<comment xml:lang="eu">Rust iturburu-kodea</comment>
<comment xml:lang="fi">Rust-lähdekoodi</comment>
<comment xml:lang="fr">code source Rust</comment>
+ <comment xml:lang="ga">cód foinseach Rust</comment>
<comment xml:lang="he">קוד מקור של Rust</comment>
<comment xml:lang="hr">Rust izvorni kôd</comment>
<comment xml:lang="hu">Rust forrásfájl</comment>
@@ -18635,7 +19228,7 @@
<comment xml:lang="pl">Kod źródłowy Rust</comment>
<comment xml:lang="pt">código origem Rust</comment>
<comment xml:lang="pt_BR">Código-fonte Rust</comment>
- <comment xml:lang="ru">иÑходный код Rust</comment>
+ <comment xml:lang="ru">ИÑходный код Rust</comment>
<comment xml:lang="sk">Zdrojový kód Rust</comment>
<comment xml:lang="sr">РаÑÑ‚ изворни ко̂д</comment>
<comment xml:lang="sv">Rust-källkod</comment>
@@ -18684,7 +19277,7 @@
<comment xml:lang="pt">folha de cálculo SC/Xspread</comment>
<comment xml:lang="pt_BR">Planilha do SC/Xspread</comment>
<comment xml:lang="ro">Foaie de calcul SC/Xspread</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° SC/Xspread</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° SC/Xspread</comment>
<comment xml:lang="sk">Zošit SC/Xspread</comment>
<comment xml:lang="sl">Preglednica SC/Xspread</comment>
<comment xml:lang="sq">Fletë llogaritjesh SC/Xspread</comment>
@@ -18693,7 +19286,7 @@
<comment xml:lang="tr">SC/Xspread çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ SC/Xspread</comment>
<comment xml:lang="vi">Bảng tính SC/Xspread</comment>
- <comment xml:lang="zh_CN">SC/Xspread 工作簿</comment>
+ <comment xml:lang="zh_CN">SC/Xspread 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">SC/Xspread 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<magic priority="50">
@@ -18722,7 +19315,7 @@
<comment xml:lang="ga">cartlann bhlaoisce</comment>
<comment xml:lang="gl">ficheiro shell</comment>
<comment xml:lang="he">×רכיון מעטפת</comment>
- <comment xml:lang="hr">arhiva ljuske</comment>
+ <comment xml:lang="hr">Arhiva ljuske</comment>
<comment xml:lang="hu">héjarchívum</comment>
<comment xml:lang="ia">Archivo de shell</comment>
<comment xml:lang="id">arsip shell</comment>
@@ -18741,7 +19334,7 @@
<comment xml:lang="pt">arquivo de terminal</comment>
<comment xml:lang="pt_BR">Pacote shell</comment>
<comment xml:lang="ro">arhivă shell</comment>
- <comment xml:lang="ru">архив оболочки UNIX</comment>
+ <comment xml:lang="ru">Ðрхив shell</comment>
<comment xml:lang="sk">Archív shellu</comment>
<comment xml:lang="sl">lupinski arhiv</comment>
<comment xml:lang="sq">Arkiv shell</comment>
@@ -18792,7 +19385,7 @@
<comment xml:lang="pt">biblioteca partilhada libtool</comment>
<comment xml:lang="pt_BR">Biblioteca compartilhada libtool</comment>
<comment xml:lang="ro">bibliotecă partajată libtool</comment>
- <comment xml:lang="ru">разделÑÐµÐ¼Ð°Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° libtool</comment>
+ <comment xml:lang="ru">РазделÑÐµÐ¼Ð°Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° libtool</comment>
<comment xml:lang="sk">Zdieľaná knižnica libtool</comment>
<comment xml:lang="sl">Souporabna knjižnica libtool</comment>
<comment xml:lang="sq">Librari e përbashkët libtool</comment>
@@ -18848,7 +19441,7 @@
<comment xml:lang="pt">biblioteca partilhada</comment>
<comment xml:lang="pt_BR">Biblioteca compartilhada</comment>
<comment xml:lang="ro">bibliotecă partajată</comment>
- <comment xml:lang="ru">разделÑÐµÐ¼Ð°Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ°</comment>
+ <comment xml:lang="ru">РазделÑÐµÐ¼Ð°Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ°</comment>
<comment xml:lang="sk">Zdieľaná knižnica</comment>
<comment xml:lang="sl">souporabljena knjižnica</comment>
<comment xml:lang="sq">Librari e përbashkët</comment>
@@ -18883,7 +19476,7 @@
<comment xml:lang="az">qabıq skripti</comment>
<comment xml:lang="be@latin">skrypt abałonki</comment>
<comment xml:lang="bg">Скрипт на обвивката</comment>
- <comment xml:lang="ca">script de shell</comment>
+ <comment xml:lang="ca">script shell</comment>
<comment xml:lang="cs">skript shellu</comment>
<comment xml:lang="cy">sgript plisgyn</comment>
<comment xml:lang="da">skalprogram</comment>
@@ -18899,7 +19492,7 @@
<comment xml:lang="ga">script bhlaoisce</comment>
<comment xml:lang="gl">script de shell</comment>
<comment xml:lang="he">תסריט מעטפת</comment>
- <comment xml:lang="hr">skripta ljuske</comment>
+ <comment xml:lang="hr">Skripta ljuske</comment>
<comment xml:lang="hu">héj-parancsfájl</comment>
<comment xml:lang="ia">Script de shell</comment>
<comment xml:lang="id">skrip shell</comment>
@@ -18918,7 +19511,7 @@
<comment xml:lang="pt">script de terminal</comment>
<comment xml:lang="pt_BR">Script shell</comment>
<comment xml:lang="ro">script shell</comment>
- <comment xml:lang="ru">Ñценарий оболочки UNIX</comment>
+ <comment xml:lang="ru">Сценарий shell</comment>
<comment xml:lang="sk">Skript shellu</comment>
<comment xml:lang="sl">lupinski skript</comment>
<comment xml:lang="sq">Script shell</comment>
@@ -18987,7 +19580,7 @@
<comment xml:lang="pt">ficheiro Shockwave Flash</comment>
<comment xml:lang="pt_BR">Arquivo Shockwave Flash</comment>
<comment xml:lang="ro">Fișier Shockwave Flash</comment>
- <comment xml:lang="ru">файл Shockwave Flash</comment>
+ <comment xml:lang="ru">Файл Shockwave Flash</comment>
<comment xml:lang="sk">Súbor Shockwave Flash</comment>
<comment xml:lang="sl">Datoteka Shockwave Flash</comment>
<comment xml:lang="sq">File Flash Shockwave</comment>
@@ -19029,7 +19622,7 @@
<comment xml:lang="ga">fuaim Shorten</comment>
<comment xml:lang="gl">son Shorten</comment>
<comment xml:lang="he">שמע של Shorten</comment>
- <comment xml:lang="hr">Shorten audio</comment>
+ <comment xml:lang="hr">Shorten zvuÄni zapis</comment>
<comment xml:lang="hu">Shorten hang</comment>
<comment xml:lang="ia">Audio Shorten</comment>
<comment xml:lang="id">Audio Shorten</comment>
@@ -19047,7 +19640,7 @@
<comment xml:lang="pt">áudio Shorten</comment>
<comment xml:lang="pt_BR">Ãudio Shorten</comment>
<comment xml:lang="ro">Audio Shorten</comment>
- <comment xml:lang="ru">аудио Shorten</comment>
+ <comment xml:lang="ru">Ðудио Shorten</comment>
<comment xml:lang="sk">Zvuk Shorten</comment>
<comment xml:lang="sl">ZvoÄna datoteka Shorten</comment>
<comment xml:lang="sq">Audio Shorten</comment>
@@ -19104,7 +19697,7 @@
<comment xml:lang="pt">folha de cálculo Siag</comment>
<comment xml:lang="pt_BR">Planilha do Siag</comment>
<comment xml:lang="ro">Foaie de calcul Siag</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Siag</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Siag</comment>
<comment xml:lang="sk">Zošit Siag</comment>
<comment xml:lang="sl">Preglednica Siag</comment>
<comment xml:lang="sq">Fletë llogaritjesh Siag</comment>
@@ -19113,7 +19706,7 @@
<comment xml:lang="tr">Siag çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Siag</comment>
<comment xml:lang="vi">Bảng tính Slag</comment>
- <comment xml:lang="zh_CN">Siag 工作簿</comment>
+ <comment xml:lang="zh_CN">Siag 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">Siag 試算表</comment>
<generic-icon name="x-office-spreadsheet"/>
<glob pattern="*.siag"/>
@@ -19121,6 +19714,7 @@
<mime-type type="image/x-skencil">
<comment>Skencil document</comment>
<comment xml:lang="ar">مستند Skencil</comment>
+ <comment xml:lang="ast">Documentu de Skencil</comment>
<comment xml:lang="be@latin">Dakument Skencil</comment>
<comment xml:lang="bg">Документ — Skencil</comment>
<comment xml:lang="ca">document Skencil</comment>
@@ -19155,7 +19749,7 @@
<comment xml:lang="pt">documento Skencil</comment>
<comment xml:lang="pt_BR">Documento do Skencil</comment>
<comment xml:lang="ro">Document Skencil</comment>
- <comment xml:lang="ru">документ Skencil</comment>
+ <comment xml:lang="ru">Документ Skencil</comment>
<comment xml:lang="sk">Dokument Skencil</comment>
<comment xml:lang="sl">Dokument Skencil</comment>
<comment xml:lang="sq">Dokument Skencil</comment>
@@ -19213,7 +19807,7 @@
<comment xml:lang="pt">pacote Stampede</comment>
<comment xml:lang="pt_BR">Pacote Stampede</comment>
<comment xml:lang="ro">Pachet Stampede</comment>
- <comment xml:lang="ru">пакет Stampede</comment>
+ <comment xml:lang="ru">Пакет Stampede</comment>
<comment xml:lang="sk">BalíÄek Stampede</comment>
<comment xml:lang="sl">Datoteka paketa Stampede</comment>
<comment xml:lang="sq">Paketë Stampede</comment>
@@ -19229,18 +19823,28 @@
<mime-type type="application/x-sg1000-rom">
<comment>SG-1000 ROM</comment>
<comment xml:lang="ca">ROM de SG-1000</comment>
+ <comment xml:lang="cs">ROM pro SG-1000</comment>
<comment xml:lang="da">SG-1000 ROM</comment>
<comment xml:lang="de">SG-1000 ROM</comment>
+ <comment xml:lang="en_GB">SG-1000 ROM</comment>
<comment xml:lang="es">ROM de SG-1000</comment>
+ <comment xml:lang="eu">SG-1000 ROM</comment>
<comment xml:lang="fi">SG-1000 -ROM</comment>
<comment xml:lang="fr">ROM SG-1000</comment>
+ <comment xml:lang="ga">ROM SG-1000</comment>
+ <comment xml:lang="hr">SG-1000 ROM</comment>
<comment xml:lang="hu">SG-1000 ROM</comment>
+ <comment xml:lang="id">ROM SG-1000</comment>
+ <comment xml:lang="it">ROM SG-1000</comment>
<comment xml:lang="kk">SG-1000 ROM</comment>
<comment xml:lang="ko">SG-1000 롬</comment>
<comment xml:lang="pl">Plik ROM konsoli SG-1000</comment>
<comment xml:lang="pt_BR">ROM de SG-1000</comment>
<comment xml:lang="ru">SG-1000 ROM</comment>
<comment xml:lang="sk">ROM pre SG-1000</comment>
+ <comment xml:lang="sr">СГ-1000 РОМ</comment>
+ <comment xml:lang="sv">SG-1000-rom</comment>
+ <comment xml:lang="tr">SG-1000 ROM</comment>
<comment xml:lang="uk">ППП SG-1000</comment>
<comment xml:lang="zh_CN">SG-1000 ROM</comment>
<comment xml:lang="zh_TW">SG-1000 ROM</comment>
@@ -19251,18 +19855,28 @@
<comment>Master System ROM</comment>
<comment xml:lang="ca">ROM de Master System</comment>
+ <comment xml:lang="cs">ROM pro Master System</comment>
<comment xml:lang="da">Master System ROM</comment>
<comment xml:lang="de">Master System ROM</comment>
+ <comment xml:lang="en_GB">Master System ROM</comment>
<comment xml:lang="es">ROM de Master System</comment>
+ <comment xml:lang="eu">Master System ROM</comment>
<comment xml:lang="fi">Master System -ROM</comment>
<comment xml:lang="fr">ROM Master System</comment>
+ <comment xml:lang="ga">ROM Master System</comment>
+ <comment xml:lang="hr">Master System ROM</comment>
<comment xml:lang="hu">Master System ROM</comment>
+ <comment xml:lang="id">ROM Master System</comment>
+ <comment xml:lang="it">ROM Master System</comment>
<comment xml:lang="kk">Master System ROM</comment>
<comment xml:lang="ko">마스터 시스템 롬</comment>
<comment xml:lang="pl">Plik ROM konsoli SMS</comment>
<comment xml:lang="pt_BR">ROM de Master System</comment>
<comment xml:lang="ru">Master System ROM</comment>
<comment xml:lang="sk">ROM pre Master System</comment>
+ <comment xml:lang="sr">МаÑтер СиÑтем РОМ</comment>
+ <comment xml:lang="sv">Master System-rom</comment>
+ <comment xml:lang="tr">Master System ROM</comment>
<comment xml:lang="uk">ППП Master System</comment>
<comment xml:lang="zh_CN">Master System ROM</comment>
<comment xml:lang="zh_TW">Master System ROM</comment>
@@ -19273,18 +19887,28 @@
<mime-type type="application/x-gamegear-rom">
<comment>Game Gear ROM</comment>
<comment xml:lang="ca">ROM de Game Gear</comment>
+ <comment xml:lang="cs">ROM pro Game Gear</comment>
<comment xml:lang="da">Game Gear ROM</comment>
<comment xml:lang="de">Game Gear ROM</comment>
+ <comment xml:lang="en_GB">Game Gear ROM</comment>
<comment xml:lang="es">ROM de Game Gear</comment>
+ <comment xml:lang="eu">Game Gear ROM</comment>
<comment xml:lang="fi">Game Gear -ROM</comment>
<comment xml:lang="fr">ROM Game Gear</comment>
+ <comment xml:lang="ga">ROM Game Gear</comment>
+ <comment xml:lang="hr">Game Gear ROM</comment>
<comment xml:lang="hu">Game Gear ROM</comment>
+ <comment xml:lang="id">ROM Game Gear</comment>
+ <comment xml:lang="it">ROM Game Gear</comment>
<comment xml:lang="kk">Game Gear ROM</comment>
<comment xml:lang="ko">게임 기어 롬</comment>
<comment xml:lang="pl">Plik ROM konsoli Game Gear</comment>
<comment xml:lang="pt_BR">ROM de Game Gear</comment>
<comment xml:lang="ru">Game Gear ROM</comment>
<comment xml:lang="sk">ROM pre Game Gear</comment>
+ <comment xml:lang="sr">Гејм Гир РОМ</comment>
+ <comment xml:lang="sv">Game Gear-rom</comment>
+ <comment xml:lang="tr">Game Gear ROM</comment>
<comment xml:lang="uk">ППП Game Gear</comment>
<comment xml:lang="zh_CN">Game Gear ROM</comment>
<comment xml:lang="zh_TW">Game Gear ROM</comment>
@@ -19328,7 +19952,7 @@
<comment xml:lang="oc">ROM Super Nintendo</comment>
<comment xml:lang="pl">Plik ROM konsoli SNES</comment>
<comment xml:lang="pt">ROM Super Nintendo</comment>
- <comment xml:lang="pt_BR">ROM do Super Nintendo</comment>
+ <comment xml:lang="pt_BR">ROM de Super Nintendo</comment>
<comment xml:lang="ro">ROM Super Nintendo</comment>
<comment xml:lang="ru">Super NES ROM</comment>
<comment xml:lang="sk">ROM pre Super Nintendo</comment>
@@ -19384,7 +20008,7 @@
<comment xml:lang="pt">arquivo StuffIt</comment>
<comment xml:lang="pt_BR">Pacote StuffIt</comment>
<comment xml:lang="ro">Arhivă StuffIt</comment>
- <comment xml:lang="ru">архив StuffIt</comment>
+ <comment xml:lang="ru">Ðрхив StuffIt</comment>
<comment xml:lang="sk">Archív StuffIt</comment>
<comment xml:lang="sl">Datoteka arhiva StuffIt</comment>
<comment xml:lang="sq">Arkiv StuffIt</comment>
@@ -19424,7 +20048,7 @@
<comment xml:lang="ga">fotheidil SubRip</comment>
<comment xml:lang="gl">subtítulos SubRip</comment>
<comment xml:lang="he">כתוביות של SubRip</comment>
- <comment xml:lang="hr">SubRip titlovi</comment>
+ <comment xml:lang="hr">SubRip podnaslovi</comment>
<comment xml:lang="hu">SubRip feliratok</comment>
<comment xml:lang="ia">Subtitulos SubRip</comment>
<comment xml:lang="id">Subjudul SubRip</comment>
@@ -19442,7 +20066,7 @@
<comment xml:lang="pt">legendas SubRip</comment>
<comment xml:lang="pt_BR">Legendas SubRip</comment>
<comment xml:lang="ro">Subtitrare SubRip</comment>
- <comment xml:lang="ru">Ñубтитры SubRip</comment>
+ <comment xml:lang="ru">Субтитры SubRip</comment>
<comment xml:lang="sk">Titulky SubRip</comment>
<comment xml:lang="sl">Datoteka podnapisov SubRip</comment>
<comment xml:lang="sq">Nëntituj SubRip</comment>
@@ -19476,12 +20100,13 @@
<comment xml:lang="eu">WebVTT azpitituluak</comment>
<comment xml:lang="fi">WebVTT-tekstitykset</comment>
<comment xml:lang="fr">sous-titres WebVTT</comment>
+ <comment xml:lang="ga">fotheidil WebVTT</comment>
<comment xml:lang="gl">subtítulos WebVTT</comment>
<comment xml:lang="he">כתוביות WebVTT</comment>
- <comment xml:lang="hr">WebVTT titlovi</comment>
+ <comment xml:lang="hr">WebVTT podnaslovi</comment>
<comment xml:lang="hu">WebVTT feliratok</comment>
<comment xml:lang="ia">Subtitulos WebVTT</comment>
- <comment xml:lang="id">Subtitel WebVTT</comment>
+ <comment xml:lang="id">Subjudul WebVTT</comment>
<comment xml:lang="it">Sottotitoli WebVTT</comment>
<comment xml:lang="ja">WebVTT サブタイトル</comment>
<comment xml:lang="ka">WebVTT ქვეტიტრები</comment>
@@ -19493,7 +20118,7 @@
<comment xml:lang="pl">Napisy WebVTT</comment>
<comment xml:lang="pt">legendas WebVTT</comment>
<comment xml:lang="pt_BR">Legendas WebVTT</comment>
- <comment xml:lang="ru">Ñубтитры WebVTT</comment>
+ <comment xml:lang="ru">Субтитры WebVTT</comment>
<comment xml:lang="sk">Titulky WebVTT</comment>
<comment xml:lang="sl">Podnapisi WebVTT</comment>
<comment xml:lang="sr">Веб ВТТ преводи</comment>
@@ -19531,7 +20156,7 @@
<comment xml:lang="ga">fotheidil SAMI</comment>
<comment xml:lang="gl">subtítulos SAMI</comment>
<comment xml:lang="he">כתוביות SAMI</comment>
- <comment xml:lang="hr">SAMI titlovi</comment>
+ <comment xml:lang="hr">SAMI podnaslovi</comment>
<comment xml:lang="hu">SAMI feliratok</comment>
<comment xml:lang="ia">Subtitulos SAMI</comment>
<comment xml:lang="id">Subjudul SAMI</comment>
@@ -19549,7 +20174,7 @@
<comment xml:lang="pt">legendas SAMI</comment>
<comment xml:lang="pt_BR">Legendas SAMI</comment>
<comment xml:lang="ro">Subtitrări SAMI</comment>
- <comment xml:lang="ru">Ñубтитры SAMI</comment>
+ <comment xml:lang="ru">Субтитры SAMI</comment>
<comment xml:lang="sk">Titulky SAMI</comment>
<comment xml:lang="sl">Datoteka podnapisov SAMI</comment>
<comment xml:lang="sq">Nëntituj SAMI</comment>
@@ -19590,7 +20215,7 @@
<comment xml:lang="ga">fotheidil MicroDVD</comment>
<comment xml:lang="gl">subtítulos de MicroDVD</comment>
<comment xml:lang="he">כתוביות של MicroDVD</comment>
- <comment xml:lang="hr">MicroDVD titlovi</comment>
+ <comment xml:lang="hr">MicroDVD podnaslovi</comment>
<comment xml:lang="hu">MicroDVD feliratok</comment>
<comment xml:lang="ia">Subtitulos MicroDVD</comment>
<comment xml:lang="id">Subjudul MicroDVD</comment>
@@ -19609,7 +20234,7 @@
<comment xml:lang="pt">legendas MicroDVD</comment>
<comment xml:lang="pt_BR">Legendas MicroDVD</comment>
<comment xml:lang="ro">Subtitrări MicroDVD</comment>
- <comment xml:lang="ru">Ñубтитры MicroDVD</comment>
+ <comment xml:lang="ru">Субтитры MicroDVD</comment>
<comment xml:lang="sk">Titulky MicroDVD</comment>
<comment xml:lang="sl">Datoteka podnapisov MicroDVD</comment>
<comment xml:lang="sq">Nëntituj MicroDVD</comment>
@@ -19648,7 +20273,7 @@
<comment xml:lang="ga">fotheidil MPSub</comment>
<comment xml:lang="gl">subtítulos MPSub</comment>
<comment xml:lang="he">כתוביות MPSub</comment>
- <comment xml:lang="hr">MPSub titlovi</comment>
+ <comment xml:lang="hr">MPSub podnaslovi</comment>
<comment xml:lang="hu">MPSub feliratok</comment>
<comment xml:lang="ia">Subtitulos MPSub</comment>
<comment xml:lang="id">Subjudul MPSub</comment>
@@ -19667,7 +20292,7 @@
<comment xml:lang="pt">legendas MPSub</comment>
<comment xml:lang="pt_BR">Legendas MPSub</comment>
<comment xml:lang="ro">Subtitrări MPSub</comment>
- <comment xml:lang="ru">Ñубтитры MPSub</comment>
+ <comment xml:lang="ru">Субтитры MPSub</comment>
<comment xml:lang="sk">Titulky MPSub</comment>
<comment xml:lang="sl">Datoteka podnapisov MPSub</comment>
<comment xml:lang="sq">Nëntituj MPSub</comment>
@@ -19706,7 +20331,7 @@
<comment xml:lang="ga">fotheidil SSA</comment>
<comment xml:lang="gl">Subtitulos SSA</comment>
<comment xml:lang="he">כתובית SSA</comment>
- <comment xml:lang="hr">SSA titlovi</comment>
+ <comment xml:lang="hr">SSA podnaslovi</comment>
<comment xml:lang="hu">SSA feliratok</comment>
<comment xml:lang="ia">Subtitulos SSA</comment>
<comment xml:lang="id">Subjudul SSA</comment>
@@ -19724,7 +20349,7 @@
<comment xml:lang="pt">legendas SSA</comment>
<comment xml:lang="pt_BR">Legendas SSA</comment>
<comment xml:lang="ro">Subtitrări SSA</comment>
- <comment xml:lang="ru">Ñубтитры SSA</comment>
+ <comment xml:lang="ru">Субтитры SSA</comment>
<comment xml:lang="sk">Titulky SSA</comment>
<comment xml:lang="sl">Datoteka podnapisov SSA</comment>
<comment xml:lang="sq">Nëntituj SSA</comment>
@@ -19765,7 +20390,7 @@
<comment xml:lang="ga">fotheidil SubViewer</comment>
<comment xml:lang="gl">subtítulos SubViewer</comment>
<comment xml:lang="he">כתוביות של SubViewer</comment>
- <comment xml:lang="hr">SubViewer titlovi</comment>
+ <comment xml:lang="hr">SubViewer podnaslovi</comment>
<comment xml:lang="hu">SubViewer feliratok</comment>
<comment xml:lang="ia">Subtitulos SubViewer</comment>
<comment xml:lang="id">Subjudul SubViewer</comment>
@@ -19783,7 +20408,7 @@
<comment xml:lang="pt">legendas SubViewer</comment>
<comment xml:lang="pt_BR">Legendas SubViewer</comment>
<comment xml:lang="ro">Subtitrare SubViewer</comment>
- <comment xml:lang="ru">Ñубтитры SubViewer</comment>
+ <comment xml:lang="ru">Субтитры SubViewer</comment>
<comment xml:lang="sk">Titulky SubViewer</comment>
<comment xml:lang="sl">Datoteka podnapisov SubViewer</comment>
<comment xml:lang="sq">Nëntituj SubViewer</comment>
@@ -19819,7 +20444,7 @@
<comment xml:lang="ga">ton buailte iMelody</comment>
<comment xml:lang="gl">Melodía de iMelody</comment>
<comment xml:lang="he">צלצול של iMelody</comment>
- <comment xml:lang="hr">iMelody ton zvonjenja</comment>
+ <comment xml:lang="hr">iMelody melodija zvona</comment>
<comment xml:lang="hu">iMelody csengőhang</comment>
<comment xml:lang="ia">Tono de appello iMelody</comment>
<comment xml:lang="id">nada dering iMelody</comment>
@@ -19837,7 +20462,7 @@
<comment xml:lang="pt">toque iMelody</comment>
<comment xml:lang="pt_BR">Toque de celular do iMelody</comment>
<comment xml:lang="ro">Sonerie iMelody</comment>
- <comment xml:lang="ru">Ð¼ÐµÐ»Ð¾Ð´Ð¸Ñ iMelody</comment>
+ <comment xml:lang="ru">ÐœÐµÐ»Ð¾Ð´Ð¸Ñ iMelody</comment>
<comment xml:lang="sk">Vyzváňacie melódie iMelody</comment>
<comment xml:lang="sl">Zvonjenje iMelody</comment>
<comment xml:lang="sq">Zile iMelody</comment>
@@ -19876,7 +20501,7 @@
<comment xml:lang="ga">fuaim SMAF</comment>
<comment xml:lang="gl">son SMAF</comment>
<comment xml:lang="he">שמע SMAF</comment>
- <comment xml:lang="hr">SMAF audio</comment>
+ <comment xml:lang="hr">SMAF zvuÄni zapis</comment>
<comment xml:lang="hu">SMAF hang</comment>
<comment xml:lang="ia">Audio SMAF</comment>
<comment xml:lang="id">Audio SMAF</comment>
@@ -19894,7 +20519,7 @@
<comment xml:lang="pt">áudio SMAF</comment>
<comment xml:lang="pt_BR">Ãudio SMAF</comment>
<comment xml:lang="ro">Audio SMAF</comment>
- <comment xml:lang="ru">аудио SMAF</comment>
+ <comment xml:lang="ru">Ðудио SMAF</comment>
<comment xml:lang="sk">Zvuk SMAF</comment>
<comment xml:lang="sl">ZvoÄna datoteka SMAF</comment>
<comment xml:lang="sq">Audio SMAF</comment>
@@ -19935,7 +20560,7 @@
<comment xml:lang="ga">seinmliosta MRML</comment>
<comment xml:lang="gl">lista de reprodución MRML</comment>
<comment xml:lang="he">רשימת השמעה MRML</comment>
- <comment xml:lang="hr">MRML popis za reprodukciju</comment>
+ <comment xml:lang="hr">MRML popis izvođenja</comment>
<comment xml:lang="hu">MRML-lejátszólista</comment>
<comment xml:lang="ia">Lista de selection MRML</comment>
<comment xml:lang="id">Senarai putar MRML</comment>
@@ -19954,7 +20579,7 @@
<comment xml:lang="pt">lista de reprodução MRML</comment>
<comment xml:lang="pt_BR">Lista de reprodução do MRML</comment>
<comment xml:lang="ro">Listă redare MRML</comment>
- <comment xml:lang="ru">ÑпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ MRML</comment>
+ <comment xml:lang="ru">СпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ MRML</comment>
<comment xml:lang="sk">Zoznam skladieb MRML</comment>
<comment xml:lang="sl">Seznam predvajanja MRML</comment>
<comment xml:lang="sq">Listë titujsh MRML</comment>
@@ -19993,7 +20618,7 @@
<comment xml:lang="ga">fuaim XMF</comment>
<comment xml:lang="gl">son XMF</comment>
<comment xml:lang="he">שמע XMF</comment>
- <comment xml:lang="hr">XMF audio</comment>
+ <comment xml:lang="hr">XMF zvuÄni zapis</comment>
<comment xml:lang="hu">XMF hang</comment>
<comment xml:lang="ia">Audio XMF</comment>
<comment xml:lang="id">Audio XMF</comment>
@@ -20011,7 +20636,7 @@
<comment xml:lang="pt">aúdio XMF</comment>
<comment xml:lang="pt_BR">Ãudio XMF</comment>
<comment xml:lang="ro">Audio XMF</comment>
- <comment xml:lang="ru">аудио XMF</comment>
+ <comment xml:lang="ru">Ðудио XMF</comment>
<comment xml:lang="sk">Zvuk XMF</comment>
<comment xml:lang="sl">ZvoÄna datoteka XMF</comment>
<comment xml:lang="sq">Audio XMF</comment>
@@ -20073,7 +20698,7 @@
<comment xml:lang="pt">arquivo SV4 CPIO</comment>
<comment xml:lang="pt_BR">Pacote SV4 CPIO</comment>
<comment xml:lang="ro">Arhivă SV4 CPIO</comment>
- <comment xml:lang="ru">архив SV4 CPIO</comment>
+ <comment xml:lang="ru">Ðрхив SV4 CPIO</comment>
<comment xml:lang="sk">Archív SV4 CPIO</comment>
<comment xml:lang="sl">Datoteka arhiva SV4 CPIO</comment>
<comment xml:lang="sq">Arkiv SV4 CPIO</comment>
@@ -20126,7 +20751,7 @@
<comment xml:lang="pt">arquivo SV4 CPIO (com CRC)</comment>
<comment xml:lang="pt_BR">Pacote SV4 CPIO (com CRC)</comment>
<comment xml:lang="ro">Arhivă SV4 CPIO (cu CRC)</comment>
- <comment xml:lang="ru">архив SV4 CPIP (Ñ CRC)</comment>
+ <comment xml:lang="ru">Ðрхив SV4 CPIO (Ñ CRC)</comment>
<comment xml:lang="sk">Archív SV4 CPIO (s CRC)</comment>
<comment xml:lang="sl">Datoteka arhiva SV4 CPIO (z razpršilom CRC)</comment>
<comment xml:lang="sq">Arkiv SV4 CPIO (me CRC)</comment>
@@ -20135,7 +20760,7 @@
<comment xml:lang="tr">SV4 CPIO arÅŸivi (CRC ile)</comment>
<comment xml:lang="uk">архів SV4 CPIO (з CRC)</comment>
<comment xml:lang="vi">Kho nén CPIO SV4 (với CRC)</comment>
- <comment xml:lang="zh_CN">SV4 CPIP 归档文件(带有 CRC)</comment>
+ <comment xml:lang="zh_CN">SV4 CPIP 归档文件(带 CRC)</comment>
<comment xml:lang="zh_TW">SV4 CPIO å°å­˜æª” (具有 CRC)</comment>
<generic-icon name="package-x-generic"/>
<glob pattern="*.sv4crc"/>
@@ -20180,7 +20805,7 @@
<comment xml:lang="pt">arquivo Tar</comment>
<comment xml:lang="pt_BR">Pacote Tar</comment>
<comment xml:lang="ro">Arhivă Tar</comment>
- <comment xml:lang="ru">архив TAR</comment>
+ <comment xml:lang="ru">Ðрхив TAR</comment>
<comment xml:lang="sk">Archív tar</comment>
<comment xml:lang="sl">Datoteka arhiva Tar</comment>
<comment xml:lang="sq">Arkiv tar</comment>
@@ -20220,7 +20845,7 @@
<comment xml:lang="ga">cartlann Tar (comhbhrúite)</comment>
<comment xml:lang="gl">arquivo Tar (comprimido)</comment>
<comment xml:lang="he">×רכיון Tar (מכווץ)</comment>
- <comment xml:lang="hr">Tar arhiva (komprimirana)</comment>
+ <comment xml:lang="hr">Tar arhiva (sažeta)</comment>
<comment xml:lang="hu">Tar archívum (tömörített)</comment>
<comment xml:lang="ia">Archivo Tar (comprimite)</comment>
<comment xml:lang="id">Arsip Tar (terkompresi)</comment>
@@ -20238,7 +20863,7 @@
<comment xml:lang="pt">arquivo Tar (comprimido)</comment>
<comment xml:lang="pt_BR">Pacote Tar (compactado)</comment>
<comment xml:lang="ro">Arhivă Tar (comprimată)</comment>
- <comment xml:lang="ru">архив TAR (Ñжатый)</comment>
+ <comment xml:lang="ru">Ðрхив TAR (Ñжатый)</comment>
<comment xml:lang="sk">Archív tar (komprimovaný)</comment>
<comment xml:lang="sl">Datoteka arhiva Tar (stisnjen)</comment>
<comment xml:lang="sq">Arkiv tar (i kompresuar)</comment>
@@ -20247,7 +20872,7 @@
<comment xml:lang="tr">Tar arşivi (sıkıştırılmış)</comment>
<comment xml:lang="uk">архів tar (ÑтиÑнений)</comment>
<comment xml:lang="vi">Kho nén tar (đã nén)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件(压缩)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(压缩)</comment>
<comment xml:lang="zh_TW">Tar å°å­˜æª” (UNIX æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/x-compress"/>
<generic-icon name="package-x-generic"/>
@@ -20259,8 +20884,8 @@
<comment xml:lang="ar">مل٠الخط العام</comment>
<comment xml:lang="be@latin">zvyÄajny fajÅ‚ Å¡ryftu</comment>
<comment xml:lang="bg">Шрифт</comment>
- <comment xml:lang="ca">fitxer genèric de tipus de lletra</comment>
- <comment xml:lang="cs">obecný soubor písma</comment>
+ <comment xml:lang="ca">fitxer de lletra genèrica</comment>
+ <comment xml:lang="cs">obecný soubor s fontem</comment>
<comment xml:lang="da">general skrifttypefil</comment>
<comment xml:lang="de">Allgemeine Schriftdatei</comment>
<comment xml:lang="el">Γενικό αÏχείο γÏαμματοσειÏάς</comment>
@@ -20274,7 +20899,7 @@
<comment xml:lang="ga">comhad cló ginearálta</comment>
<comment xml:lang="gl">ficheiro de tipo de fonte xenérica</comment>
<comment xml:lang="he">קובץ גופן גנרי</comment>
- <comment xml:lang="hr">općenita datoteka fonta</comment>
+ <comment xml:lang="hr">Izvorna datoteka slova</comment>
<comment xml:lang="hu">általános betűkészletfájl</comment>
<comment xml:lang="ia">File de typo de litteras generic</comment>
<comment xml:lang="id">berkas fonta generik</comment>
@@ -20293,7 +20918,7 @@
<comment xml:lang="pt">ficheiro genérico de letra</comment>
<comment xml:lang="pt_BR">Arquivo de fonte genérico</comment>
<comment xml:lang="ro">fișier de font generic</comment>
- <comment xml:lang="ru">обычный файл шрифта</comment>
+ <comment xml:lang="ru">Обычный файл шрифта</comment>
<comment xml:lang="sk">ObyÄajný súbor písma</comment>
<comment xml:lang="sl">izvorna datoteka pisave</comment>
<comment xml:lang="sq">File lloj gërme i përgjithshëm</comment>
@@ -20312,8 +20937,8 @@
<comment xml:lang="ar">مل٠الخط المرزم</comment>
<comment xml:lang="be@latin">zapakavany fajł šryftu</comment>
<comment xml:lang="bg">Шрифт — компреÑиран</comment>
- <comment xml:lang="ca">fitxer empaquetat de tipus de lletra</comment>
- <comment xml:lang="cs">komprimovaný soubor písma</comment>
+ <comment xml:lang="ca">fitxer de lletra empaquetada</comment>
+ <comment xml:lang="cs">komprimovaný soubor s fontem</comment>
<comment xml:lang="da">pakket skrifttypefil</comment>
<comment xml:lang="de">Gepackte Schriftdatei</comment>
<comment xml:lang="el">ΑÏχείο συμπιεσμένης γÏαμματοσειÏάς</comment>
@@ -20327,7 +20952,7 @@
<comment xml:lang="ga">comhad cló pacáilte</comment>
<comment xml:lang="gl">ficheiro de fonte empaquetada</comment>
<comment xml:lang="he">קובץ גופן ×רוז</comment>
- <comment xml:lang="hr">pakirana datoteka fonta</comment>
+ <comment xml:lang="hr">Zapakirana datoteka slova</comment>
<comment xml:lang="hu">packed font-fájl</comment>
<comment xml:lang="ia">File de typos de litteras impacchettate</comment>
<comment xml:lang="id">berkas fonta terkemas</comment>
@@ -20346,7 +20971,7 @@
<comment xml:lang="pt">ficheiro de letras empacotadas</comment>
<comment xml:lang="pt_BR">Arquivo de fonte empacotado</comment>
<comment xml:lang="ro">fișier font împachetat</comment>
- <comment xml:lang="ru">Ñжатый файл шрифта</comment>
+ <comment xml:lang="ru">Сжатый файл шрифта</comment>
<comment xml:lang="sk">Komprimovaný súbor písma</comment>
<comment xml:lang="sl">pakirana datoteka pisave</comment>
<comment xml:lang="sq">File lloj gërmash i kondensuar</comment>
@@ -20363,6 +20988,7 @@
<mime-type type="application/x-tgif">
<comment>TGIF document</comment>
<comment xml:lang="ar">مستند TGIF</comment>
+ <comment xml:lang="ast">Documentu de TGIF</comment>
<comment xml:lang="be@latin">Dakument TGIF</comment>
<comment xml:lang="bg">Документ — TGIF</comment>
<comment xml:lang="ca">document TGIF</comment>
@@ -20399,7 +21025,7 @@
<comment xml:lang="pt">documento TGIF</comment>
<comment xml:lang="pt_BR">Documento TGIF</comment>
<comment xml:lang="ro">Document TGIF</comment>
- <comment xml:lang="ru">документ TGIF</comment>
+ <comment xml:lang="ru">Документ TGIF</comment>
<comment xml:lang="sk">Dokument TGIF</comment>
<comment xml:lang="sl">Dokument TGIF</comment>
<comment xml:lang="sq">Dokument TGIF</comment>
@@ -20438,7 +21064,7 @@
<comment xml:lang="ga">téama</comment>
<comment xml:lang="gl">tema</comment>
<comment xml:lang="he">ערכת נוש×</comment>
- <comment xml:lang="hr">tema</comment>
+ <comment xml:lang="hr">Tema</comment>
<comment xml:lang="hu">téma</comment>
<comment xml:lang="ia">Thema</comment>
<comment xml:lang="id">tema</comment>
@@ -20458,7 +21084,7 @@
<comment xml:lang="pt">tema</comment>
<comment xml:lang="pt_BR">Tema</comment>
<comment xml:lang="ro">temă</comment>
- <comment xml:lang="ru">тема</comment>
+ <comment xml:lang="ru">Тема</comment>
<comment xml:lang="sk">Motív</comment>
<comment xml:lang="sl">tema</comment>
<comment xml:lang="sq">Temë</comment>
@@ -20476,6 +21102,7 @@
<mime-type type="application/x-toutdoux">
<comment>ToutDoux document</comment>
<comment xml:lang="ar">مستند ToutDoux</comment>
+ <comment xml:lang="ast">Documentu de ToutDoux</comment>
<comment xml:lang="az">ToutDoux sənədi</comment>
<comment xml:lang="be@latin">Dakument ToutDoux</comment>
<comment xml:lang="bg">Документ — ToutDoux</comment>
@@ -20514,7 +21141,7 @@
<comment xml:lang="pt">documento ToutDoux</comment>
<comment xml:lang="pt_BR">Documento do ToutDoux</comment>
<comment xml:lang="ro">Document ToutDoux</comment>
- <comment xml:lang="ru">документ ToutDoux</comment>
+ <comment xml:lang="ru">Документ ToutDoux</comment>
<comment xml:lang="sk">Dokument ToutDoux</comment>
<comment xml:lang="sl">Dokument ToutDoux</comment>
<comment xml:lang="sq">Dokument ToutDoux</comment>
@@ -20566,7 +21193,7 @@
<comment xml:lang="pt">cópia de segurança</comment>
<comment xml:lang="pt_BR">Arquivo de backup</comment>
<comment xml:lang="ro">fișier de backup</comment>
- <comment xml:lang="ru">Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ</comment>
+ <comment xml:lang="ru">Ð ÐµÐ·ÐµÑ€Ð²Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ</comment>
<comment xml:lang="sk">Záložný súbor</comment>
<comment xml:lang="sl">varnostna kopija datoteke</comment>
<comment xml:lang="sq">File backup</comment>
@@ -20586,6 +21213,7 @@
<mime-type type="text/troff">
<comment>Troff document</comment>
<comment xml:lang="ar">مستند Troff</comment>
+ <comment xml:lang="ast">Documentu de Troff</comment>
<comment xml:lang="az">Troff sənədi</comment>
<comment xml:lang="be@latin">Dakument Troff</comment>
<comment xml:lang="bg">Документ — Troff</comment>
@@ -20624,7 +21252,7 @@
<comment xml:lang="pt">documento Troff</comment>
<comment xml:lang="pt_BR">Documento Troff</comment>
<comment xml:lang="ro">Document Troff</comment>
- <comment xml:lang="ru">документ Troff</comment>
+ <comment xml:lang="ru">Документ Troff</comment>
<comment xml:lang="sk">Dokument troff</comment>
<comment xml:lang="sl">Dokument Troff</comment>
<comment xml:lang="sq">Dokument Troff</comment>
@@ -20657,7 +21285,9 @@
<comment xml:lang="el">ΈγγÏαφο βοήθειας manpage</comment>
<comment xml:lang="en_GB">Manpage manual document</comment>
<comment xml:lang="es">documento de manual de Manpage</comment>
+ <comment xml:lang="eu">Manpage eskuliburu dokumentua</comment>
<comment xml:lang="fr">document manuel Manpage</comment>
+ <comment xml:lang="ga">cáipéis lámhleabhair Man</comment>
<comment xml:lang="he">מסמך תיעוד man</comment>
<comment xml:lang="hr">Manpage dokument priruÄnika</comment>
<comment xml:lang="hu">Manpage kézikönyv-dokumentum</comment>
@@ -20670,7 +21300,7 @@
<comment xml:lang="pl">Dokument podręcznika stron pomocy</comment>
<comment xml:lang="pt">documento de ajuda Manpage</comment>
<comment xml:lang="pt_BR">Documento Manpage</comment>
- <comment xml:lang="ru">документ Ñправочной ÑиÑтемы Manpage</comment>
+ <comment xml:lang="ru">Документ Ñправочной ÑиÑтемы Manpage</comment>
<comment xml:lang="sk">Dokument manuálu Manpage</comment>
<comment xml:lang="sr">документ упутÑтва Ñтранице упутÑтва</comment>
<comment xml:lang="sv">Manpage-manualdokument</comment>
@@ -20704,7 +21334,7 @@
<comment xml:lang="ga">leathanach lámhleabhair (comhbhrúite)</comment>
<comment xml:lang="gl">páxina de manual (comprimida)</comment>
<comment xml:lang="he">דף עזר (מכווץ)</comment>
- <comment xml:lang="hr">stranica priruÄnika (komprimirana)</comment>
+ <comment xml:lang="hr">Stranica priruÄnika (sažeta)</comment>
<comment xml:lang="hu">kézikönyvoldal (tömörített)</comment>
<comment xml:lang="ia">Pagina de manual (comprimite)</comment>
<comment xml:lang="id">halaman manual (terkompresi)</comment>
@@ -20723,7 +21353,7 @@
<comment xml:lang="pt">página de manual (comprimida)</comment>
<comment xml:lang="pt_BR">Página de manual (compactada)</comment>
<comment xml:lang="ro">pagină de manual (comprimată)</comment>
- <comment xml:lang="ru">Ñтраница руководÑтва (ÑжатаÑ)</comment>
+ <comment xml:lang="ru">Страница руководÑтва (ÑжатаÑ)</comment>
<comment xml:lang="sk">Manuálová stránka (komprimovaná)</comment>
<comment xml:lang="sl">stran priroÄnika (stisnjena)</comment>
<comment xml:lang="sq">Faqe manuali (e kompresuar)</comment>
@@ -20732,7 +21362,7 @@
<comment xml:lang="tr">kılavuz dosyası (sıkıştırılmış)</comment>
<comment xml:lang="uk">Ñторінка поÑібника (ÑтиÑнена)</comment>
<comment xml:lang="vi">trang hướng dẫn (đã nén)</comment>
- <comment xml:lang="zh_CN">手册页 (压缩)</comment>
+ <comment xml:lang="zh_CN">手册页(压缩)</comment>
<comment xml:lang="zh_TW">手冊é é¢ (壓縮版)</comment>
<generic-icon name="text-x-generic"/>
</mime-type>
@@ -20755,7 +21385,7 @@
<comment xml:lang="ga">cartlann Tar (comhbhrúite le LZO)</comment>
<comment xml:lang="gl">arquivo Tar (comprimido con LZO)</comment>
<comment xml:lang="he">×רכיון Tar (מכווץ ×¢×´×™ LZO)</comment>
- <comment xml:lang="hr">Tar arhiva (komprimirana LZO-om)</comment>
+ <comment xml:lang="hr">Tar arhiva (LZO sažeta)</comment>
<comment xml:lang="hu">Tar archívum (LZO-val tömörítve)</comment>
<comment xml:lang="ia">Archivo Tar (comprimite con LZO)</comment>
<comment xml:lang="id">Arsip Tar (terkompresi LZO)</comment>
@@ -20773,7 +21403,7 @@
<comment xml:lang="pt">arquivo Tar (compressão LZO)</comment>
<comment xml:lang="pt_BR">Pacote Tar (compactado com LZO)</comment>
<comment xml:lang="ro">Arhivă Tar (comprimată LZO)</comment>
- <comment xml:lang="ru">архив TAR (Ñжатый LZO)</comment>
+ <comment xml:lang="ru">Ðрхив TAR (Ñжатый lzo)</comment>
<comment xml:lang="sk">Archív tar (komprimovaný pomocou LZO)</comment>
<comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z LZO)</comment>
<comment xml:lang="sq">Arkiv tar (i kompresuar me LZO)</comment>
@@ -20782,7 +21412,7 @@
<comment xml:lang="tr">Tar arşivi (LZO ile sıkıştırılmış)</comment>
<comment xml:lang="uk">архів tar (ÑтиÑнений LZO)</comment>
<comment xml:lang="vi">Kho nén tar (đã nén LZO)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件(LZO 压缩)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(LZO 压缩)</comment>
<comment xml:lang="zh_TW">Tar å°å­˜æª” (LZO æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/x-lzop"/>
<generic-icon name="package-x-generic"/>
@@ -20824,7 +21454,7 @@
<comment xml:lang="pt">arquivo XZ</comment>
<comment xml:lang="pt_BR">Pacote XZ</comment>
<comment xml:lang="ro">Arhivă XZ</comment>
- <comment xml:lang="ru">архив XZ</comment>
+ <comment xml:lang="ru">Ðрхив XZ</comment>
<comment xml:lang="sk">Archív XZ</comment>
<comment xml:lang="sl">Datoteka arhiva XZ</comment>
<comment xml:lang="sr">ИкÑЗ архива</comment>
@@ -20857,7 +21487,7 @@
<comment xml:lang="ga">cartlann Tar (comhbhrúite le XZ)</comment>
<comment xml:lang="gl">arquivo Tar (comprimido con XZ)</comment>
<comment xml:lang="he">×רכיון Tar (מכווץ ×¢×´×™ XZ)</comment>
- <comment xml:lang="hr">Tar arhiva (komprimirana XZ-om)</comment>
+ <comment xml:lang="hr">Tar arhiva ( XZ sažeta)</comment>
<comment xml:lang="hu">Tar archívum (XZ-vel tömörítve)</comment>
<comment xml:lang="ia">Archivo Tar (comprimite con XZ)</comment>
<comment xml:lang="id">Arsip Tar (terkompresi XZ)</comment>
@@ -20873,14 +21503,14 @@
<comment xml:lang="pt">arquivo Tar (compressão XZ)</comment>
<comment xml:lang="pt_BR">Pacote Tar (compactado com XZ)</comment>
<comment xml:lang="ro">Arhivă Tar (comprimată XZ)</comment>
- <comment xml:lang="ru">архив TAR (Ñжатый XZ)</comment>
+ <comment xml:lang="ru">Ðрхив TAR (Ñжатый xz)</comment>
<comment xml:lang="sk">Archív tar (komprimovaný pomocou XZ)</comment>
<comment xml:lang="sl">Datoteka arhiva Tar (stisnjen z XZ)</comment>
<comment xml:lang="sr">Тар архива (запакована ИкÑЗ-ом)</comment>
<comment xml:lang="sv">Tar-arkiv (XZ-komprimerat)</comment>
<comment xml:lang="tr">Tar arşivi (XZ ile sıkıştırılmış)</comment>
<comment xml:lang="uk">архів tar (ÑтиÑнений XZ)</comment>
- <comment xml:lang="zh_CN">Tar 归档文件(XZ 压缩)</comment>
+ <comment xml:lang="zh_CN">Tar 归档文件(XZ 压缩)</comment>
<comment xml:lang="zh_TW">Tar å°å­˜æª” (XZ æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/x-xz"/>
<generic-icon name="package-x-generic"/>
@@ -20889,6 +21519,7 @@
</mime-type>
<mime-type type="application/x-xzpdf">
<comment>PDF document (XZ-compressed)</comment>
+ <comment xml:lang="ast">Documentu PDF (comprimíu en XZ)</comment>
<comment xml:lang="bg">Документ — PDF, компреÑиран Ñ XZ</comment>
<comment xml:lang="ca">document PDF (amb compressió XZ)</comment>
<comment xml:lang="cs">dokument PDF (komprimovaný pomocí XZ)</comment>
@@ -20900,9 +21531,10 @@
<comment xml:lang="eu">PDF dokumentua (XZ-rekin konprimitua)</comment>
<comment xml:lang="fi">PDF-asiakirja (XZ-pakattu)</comment>
<comment xml:lang="fr">document PDF (compressé XZ)</comment>
+ <comment xml:lang="ga">cáipéis PDF (comhbhrúite le XZ)</comment>
<comment xml:lang="gl">documento PDF (comprimido en XZ)</comment>
<comment xml:lang="he">מסמך PDF (מכווץ ע״י XZ)</comment>
- <comment xml:lang="hr">PDF dokument (komprimiran XZ-om)</comment>
+ <comment xml:lang="hr">PDF dokument ( XZ sažet)</comment>
<comment xml:lang="hu">PDF dokumentum (XZ-vel tömörített)</comment>
<comment xml:lang="ia">Documento PDF (comprimite con XZ)</comment>
<comment xml:lang="id">Dokumen PDF (terkompresi XZ)</comment>
@@ -20917,14 +21549,14 @@
<comment xml:lang="pl">Dokument PDF (kompresja XZ)</comment>
<comment xml:lang="pt">documento PDF (compressão XZ)</comment>
<comment xml:lang="pt_BR">Documento PDF (compactado com XZ)</comment>
- <comment xml:lang="ru">документ PDF (Ñжатый XZ)</comment>
+ <comment xml:lang="ru">Документ PDF (Ñжатый xz)</comment>
<comment xml:lang="sk">Dokument PDF (komprimovaný pomocou XZ)</comment>
<comment xml:lang="sl">Dokument PDF (XZ-stisnjen)</comment>
<comment xml:lang="sr">ПДФ документ (запакован ИкÑЗ-ом)</comment>
<comment xml:lang="sv">PDF-dokument (XZ-komprimerat)</comment>
<comment xml:lang="tr">PDF belgesi (XZ ile sıkıştırılmış)</comment>
<comment xml:lang="uk">документ PDF (ÑтиÑнений xz)</comment>
- <comment xml:lang="zh_CN">PDF 文档(XZ)</comment>
+ <comment xml:lang="zh_CN">PDF 文档(XZ)</comment>
<comment xml:lang="zh_TW">PDF 文件 (XZ æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/x-xz"/>
<generic-icon name="x-office-document"/>
@@ -20968,7 +21600,7 @@
<comment xml:lang="pt">arquivo Ustar</comment>
<comment xml:lang="pt_BR">Pacote Ustar</comment>
<comment xml:lang="ro">Arhivă Ustar</comment>
- <comment xml:lang="ru">архив Ustar</comment>
+ <comment xml:lang="ru">Ðрхив Ustar</comment>
<comment xml:lang="sk">Archív ustar</comment>
<comment xml:lang="sl">Datoteka arhiva Ustar</comment>
<comment xml:lang="sq">Arkiv Ustar</comment>
@@ -21004,7 +21636,7 @@
<comment xml:lang="ga">cód foinseach WAIS</comment>
<comment xml:lang="gl">código fonte WAIS</comment>
<comment xml:lang="he">קוד מקור של WAIS</comment>
- <comment xml:lang="hr">WAIS izvorni kod</comment>
+ <comment xml:lang="hr">WAIS izvorni kôd</comment>
<comment xml:lang="hu">WAIS-forráskód</comment>
<comment xml:lang="ia">Codice-fonte WAIS</comment>
<comment xml:lang="id">Kode program WAIS</comment>
@@ -21023,7 +21655,7 @@
<comment xml:lang="pt">código origem WAIS</comment>
<comment xml:lang="pt_BR">Código-fonte WAIS</comment>
<comment xml:lang="ro">Cod sursă WAIS</comment>
- <comment xml:lang="ru">иÑходный код WAIS</comment>
+ <comment xml:lang="ru">ИÑходный код WAIS</comment>
<comment xml:lang="sk">Zdrojový kód WAIS</comment>
<comment xml:lang="sl">Datoteka izvorne kode WAIS</comment>
<comment xml:lang="sq">Kod burues WAIS</comment>
@@ -21077,7 +21709,7 @@
<comment xml:lang="pt">imagem do WordPerfect/Drawperfect</comment>
<comment xml:lang="pt_BR">Imagem do WordPerfect/Drawperfect</comment>
<comment xml:lang="ro">Imagine WordPerfect/Drawperfect</comment>
- <comment xml:lang="ru">изображение WordPerfect/Drawperfect</comment>
+ <comment xml:lang="ru">Изображение WordPerfect/Drawperfect</comment>
<comment xml:lang="sk">Obrázok WordPerfect/Drawperfect</comment>
<comment xml:lang="sl">Slikovna datoteka Drawperfect</comment>
<comment xml:lang="sq">Figurë WordPerfect/Drawperfect</comment>
@@ -21091,6 +21723,54 @@
<generic-icon name="image-x-generic"/>
<glob pattern="*.wpg"/>
</mime-type>
+ <mime-type type="application/x-wonderswan-rom">
+ <comment>Bandai WonderSwan ROM</comment>
+ <comment xml:lang="ca">ROM de Bandai WonderSwan</comment>
+ <comment xml:lang="cs">ROM pro Bandai WonderSwan</comment>
+ <comment xml:lang="de">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="en_GB">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="es">ROM de Bandai WonderSwan</comment>
+ <comment xml:lang="hr">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="hu">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="id">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="it">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="kk">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="ko">ë°˜ë‹¤ì´ ì›ë”스완 롬</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Bandai WonderSwan</comment>
+ <comment xml:lang="pt_BR">ROM de WonderSwan da Bandai</comment>
+ <comment xml:lang="ru">Bandai WonderSwan ROM</comment>
+ <comment xml:lang="sk">ROM pre Bandai WonderSwan</comment>
+ <comment xml:lang="sv">Bandai WonderSwan-rom</comment>
+ <comment xml:lang="uk">ROM Bandai WonderSwan</comment>
+ <comment xml:lang="zh_CN">万代 WonderSwan ROM</comment>
+ <comment xml:lang="zh_TW">Bandai WonderSwan ROM</comment>
+ <generic-icon name="application-x-executable"/>
+ <glob pattern="*.ws"/>
+ </mime-type>
+ <mime-type type="application/x-wonderswan-color-rom">
+ <comment>Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="ca">ROM de Bandai WonderSwan Color</comment>
+ <comment xml:lang="cs">ROM pro Bandai WonderSwan Color</comment>
+ <comment xml:lang="de">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="en_GB">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="es">ROM de Bandai WonderSwan Color</comment>
+ <comment xml:lang="hr">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="hu">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="id">ROM Bandai WonderSwan Color</comment>
+ <comment xml:lang="it">ROM Bandai WonderSwan Color</comment>
+ <comment xml:lang="kk">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="ko">ë°˜ë‹¤ì´ ì›ë”스완 컬러 롬</comment>
+ <comment xml:lang="pl">Plik ROM konsoli Bandai WonderSwan Color</comment>
+ <comment xml:lang="pt_BR">ROM de WonderSwan Color da Bandai</comment>
+ <comment xml:lang="ru">Bandai WonderSwan Color ROM</comment>
+ <comment xml:lang="sk">ROM pre Bandai WonderSwan Color</comment>
+ <comment xml:lang="sv">Bandai WonderSwan Color-rom</comment>
+ <comment xml:lang="uk">ROM Bandai WonderSwan Color</comment>
+ <comment xml:lang="zh_CN">万代 WonderSwan Color ROM</comment>
+ <comment xml:lang="zh_TW">Bandai WonderSwan Color ROM</comment>
+ <generic-icon name="application-x-executable"/>
+ <glob pattern="*.wsc"/>
+ </mime-type>
<mime-type type="application/x-x509-ca-cert">
<comment>DER/PEM/Netscape-encoded X.509 certificate</comment>
<comment xml:lang="ar">شهادة DER/PEM/Netscape-encoded X.509</comment>
@@ -21111,7 +21791,7 @@
<comment xml:lang="ga">teastas X.509 ionchódaithe le DER/PEM/Netscape</comment>
<comment xml:lang="gl">certificado X.509 codificado con DER/PEM/Netscape</comment>
<comment xml:lang="he">×ישור מסוג X.509 של DER/PEM/Netscape-encoded</comment>
- <comment xml:lang="hr">DER/PEM/Netscape-kodiran X.509 certifikat</comment>
+ <comment xml:lang="hr">DER/PEM/Netscape-kodiran X.509 vjerodajnica</comment>
<comment xml:lang="hu">DER/PEM/Netscape formátumú X.509-tanúsítvány</comment>
<comment xml:lang="ia">Certificato X.509 codificate in DER/PEM/Netscape</comment>
<comment xml:lang="id">Sertifikat DER/PEM/Netscape-tersandi X.509</comment>
@@ -21131,7 +21811,7 @@
<comment xml:lang="pt">certificado X.509 codificado com DER/PEM/Netscape</comment>
<comment xml:lang="pt_BR">Certificado X.509 codificado com DER/PEM/Netscape</comment>
<comment xml:lang="ro">Certificat DER/PEM/Netscape-codat X.509</comment>
- <comment xml:lang="ru">Ñертификат X.509 (DER/PEM/Netscape-закодированный)</comment>
+ <comment xml:lang="ru">Сертификат X.509 (DER/PEM/Netscape-закодированный)</comment>
<comment xml:lang="sk">Certifikát X.509 kódovaný ako DER/PEM/Netscape</comment>
<comment xml:lang="sl">Datoteka potrdila DER/PEM/Netscape X.509</comment>
<comment xml:lang="sq">Çertifikatë DER/PEM/Netscape-encoded X.509</comment>
@@ -21151,6 +21831,7 @@
<mime-type type="application/x-zerosize">
<comment>empty document</comment>
<comment xml:lang="ar">مستند Ùارغ</comment>
+ <comment xml:lang="ast">documentu baleru</comment>
<comment xml:lang="be@latin">pusty dakument</comment>
<comment xml:lang="bg">Празен документ</comment>
<comment xml:lang="ca">document buit</comment>
@@ -21168,7 +21849,7 @@
<comment xml:lang="ga">cáipéis fholamh</comment>
<comment xml:lang="gl">documeto baleiro</comment>
<comment xml:lang="he">מסמך ריק</comment>
- <comment xml:lang="hr">prazan dokument</comment>
+ <comment xml:lang="hr">Prazan dokument</comment>
<comment xml:lang="hu">üres dokumentum</comment>
<comment xml:lang="ia">Documento vacue</comment>
<comment xml:lang="id">dokumen kosong</comment>
@@ -21187,7 +21868,7 @@
<comment xml:lang="pt">documento vazio</comment>
<comment xml:lang="pt_BR">Documento vazio</comment>
<comment xml:lang="ro">document gol</comment>
- <comment xml:lang="ru">пуÑтой документ</comment>
+ <comment xml:lang="ru">ПуÑтой документ</comment>
<comment xml:lang="sk">Prázdny dokument</comment>
<comment xml:lang="sl">prazen dokument</comment>
<comment xml:lang="sq">Dokument bosh</comment>
@@ -21239,7 +21920,7 @@
<comment xml:lang="pt">arquivo Zoo</comment>
<comment xml:lang="pt_BR">Pacote Zoo</comment>
<comment xml:lang="ro">Arhivă Zoo</comment>
- <comment xml:lang="ru">архив ZOO</comment>
+ <comment xml:lang="ru">Ðрхив ZOO</comment>
<comment xml:lang="sk">Archív zoo</comment>
<comment xml:lang="sl">Datoteka arhiva ZOO</comment>
<comment xml:lang="sq">Arkiv zoo</comment>
@@ -21295,7 +21976,7 @@
<comment xml:lang="pt">página XHTML</comment>
<comment xml:lang="pt_BR">Página XHTML</comment>
<comment xml:lang="ro">Pagină XHTML</comment>
- <comment xml:lang="ru">Ñтраница XHTML</comment>
+ <comment xml:lang="ru">Страница XHTML</comment>
<comment xml:lang="sk">Stránka XHTML</comment>
<comment xml:lang="sl">Datoteka spletne strani XHTML</comment>
<comment xml:lang="sq">Faqe XHTML</comment>
@@ -21360,7 +22041,7 @@
<comment xml:lang="pt">arquivo Zip</comment>
<comment xml:lang="pt_BR">Pacote Zip</comment>
<comment xml:lang="ro">Arhivă zip</comment>
- <comment xml:lang="ru">архив ZIP</comment>
+ <comment xml:lang="ru">Ðрхив ZIP</comment>
<comment xml:lang="sk">Archív ZIP</comment>
<comment xml:lang="sl">Datoteka arhiva ZIP</comment>
<comment xml:lang="sq">Arkiv zip</comment>
@@ -21391,6 +22072,7 @@
<comment xml:lang="eu">WIM disko irudia</comment>
<comment xml:lang="fi">WIM-levytiedosto</comment>
<comment xml:lang="fr">image disque WIM</comment>
+ <comment xml:lang="ga">íomhá diosca WIM</comment>
<comment xml:lang="he">דמות דיסק WIM</comment>
<comment xml:lang="hr">WIM slika diska</comment>
<comment xml:lang="hu">WIM lemezkép</comment>
@@ -21403,13 +22085,13 @@
<comment xml:lang="pl">Obraz dysku WIM</comment>
<comment xml:lang="pt">imagem de disco WIM</comment>
<comment xml:lang="pt_BR">Imagem de disco WIM</comment>
- <comment xml:lang="ru">образ диÑка WIM</comment>
+ <comment xml:lang="ru">Образ диÑка WIM</comment>
<comment xml:lang="sk">Obraz disku WIM</comment>
<comment xml:lang="sr">Ñлика диÑка ВИМ-а</comment>
<comment xml:lang="sv">WIM-diskavbild</comment>
<comment xml:lang="tr">WIM disk kalıbı</comment>
<comment xml:lang="uk">образ диÑка WIM</comment>
- <comment xml:lang="zh_CN">WIM ç£ç›˜é•œåƒ</comment>
+ <comment xml:lang="zh_CN">WIM ç£ç›˜æ˜ åƒ</comment>
<comment xml:lang="zh_TW">WIM ç£ç¢Ÿæ˜ åƒæª”</comment>
<acronym>WIM</acronym>
<expanded-acronym>Windows Imaging Format</expanded-acronym>
@@ -21441,7 +22123,7 @@
<comment xml:lang="ga">fuaim Dolby Digital</comment>
<comment xml:lang="gl">son Dolby Digital</comment>
<comment xml:lang="he">שמע Dolby Digital</comment>
- <comment xml:lang="hr">Dolby Digital audio</comment>
+ <comment xml:lang="hr">Dolby Digital zvuÄni zapis</comment>
<comment xml:lang="hu">Dolby Digital hang</comment>
<comment xml:lang="ia">Audio Dolby Digital</comment>
<comment xml:lang="id">Audio Dolby Digital</comment>
@@ -21461,7 +22143,7 @@
<comment xml:lang="pt">áudio Dolby Digital</comment>
<comment xml:lang="pt_BR">Ãudio Dolby Digital</comment>
<comment xml:lang="ro">Audio Dolby Digital</comment>
- <comment xml:lang="ru">аудио Dolby Digital</comment>
+ <comment xml:lang="ru">Ðудио Dolby Digital</comment>
<comment xml:lang="sk">Zvuk Dolby Digital</comment>
<comment xml:lang="sl">ZvoÄna datoteka Dolby Digital</comment>
<comment xml:lang="sq">Audio Dolby Digital</comment>
@@ -21489,6 +22171,7 @@
<comment xml:lang="eu">DTS audioa</comment>
<comment xml:lang="fi">DTS-ääni</comment>
<comment xml:lang="fr">audio DTS</comment>
+ <comment xml:lang="ga">fuaim DTS</comment>
<comment xml:lang="gl">Son DTS</comment>
<comment xml:lang="he">שמע DTS</comment>
<comment xml:lang="hr">DTS zvuÄni zapis</comment>
@@ -21501,10 +22184,10 @@
<comment xml:lang="ko">DTS 오디오</comment>
<comment xml:lang="lv">DTS audio</comment>
<comment xml:lang="oc">àudio DTS</comment>
- <comment xml:lang="pl">Dźwięk DTS</comment>
+ <comment xml:lang="pl">Plik dźwiękowy DTS</comment>
<comment xml:lang="pt">aúdio DTS</comment>
<comment xml:lang="pt_BR">Ãudio DTS</comment>
- <comment xml:lang="ru">аудио DTS</comment>
+ <comment xml:lang="ru">Ðудио DTS</comment>
<comment xml:lang="sk">Zvuk DTS</comment>
<comment xml:lang="sl">Zvok DTS</comment>
<comment xml:lang="sr">ДТС звук</comment>
@@ -21534,6 +22217,7 @@
<comment xml:lang="eu">DTSHD audioa</comment>
<comment xml:lang="fi">DTS-HD-ääni</comment>
<comment xml:lang="fr">audio DTSHD</comment>
+ <comment xml:lang="ga">fuaim DTSHD</comment>
<comment xml:lang="gl">Son DTSHD</comment>
<comment xml:lang="he">שמע DTSHD</comment>
<comment xml:lang="hr">DTSHD zvuÄni zapis</comment>
@@ -21546,10 +22230,10 @@
<comment xml:lang="ko">DTSHD 오디오</comment>
<comment xml:lang="lv">DTSHD audio</comment>
<comment xml:lang="oc">àudio DTSHD</comment>
- <comment xml:lang="pl">Dźwięk DTSHD</comment>
+ <comment xml:lang="pl">Plik dźwiękowy DTSHD</comment>
<comment xml:lang="pt">áudio DTSHD</comment>
<comment xml:lang="pt_BR">Ãudio DTSHD</comment>
- <comment xml:lang="ru">аудио DTSHD</comment>
+ <comment xml:lang="ru">Ðудио DTSHD</comment>
<comment xml:lang="sk">Zvuk DTSHD</comment>
<comment xml:lang="sl">Zvok DTSHD</comment>
<comment xml:lang="sr">ДТСХД звук</comment>
@@ -21585,7 +22269,7 @@
<comment xml:lang="ga">fuaim AMR</comment>
<comment xml:lang="gl">son AMR</comment>
<comment xml:lang="he">שמע AMR</comment>
- <comment xml:lang="hr">AMR audio</comment>
+ <comment xml:lang="hr">AMR zvuÄni zapis</comment>
<comment xml:lang="hu">AMR hang</comment>
<comment xml:lang="ia">Audio AMR</comment>
<comment xml:lang="id">Audio AMR</comment>
@@ -21604,7 +22288,7 @@
<comment xml:lang="pt">áudio AMR</comment>
<comment xml:lang="pt_BR">Ãudio AMR</comment>
<comment xml:lang="ro">Audio AMR</comment>
- <comment xml:lang="ru">аудио AMR</comment>
+ <comment xml:lang="ru">Ðудио AMR</comment>
<comment xml:lang="sk">Zvuk AMR</comment>
<comment xml:lang="sl">ZvoÄna datoteka AMR</comment>
<comment xml:lang="sq">Audio AMR</comment>
@@ -21644,7 +22328,7 @@
<comment xml:lang="ga">fuaim AMR-WB</comment>
<comment xml:lang="gl">son AMR-WB</comment>
<comment xml:lang="he">שמע AMR-WN</comment>
- <comment xml:lang="hr">AMR-WB audio</comment>
+ <comment xml:lang="hr">AMR-WB zvuÄni zapis</comment>
<comment xml:lang="hu">AMR-WB hang</comment>
<comment xml:lang="ia">Audio AMR-WB</comment>
<comment xml:lang="id">Audio AMR-WB</comment>
@@ -21663,7 +22347,7 @@
<comment xml:lang="pt">áudio AMR-WB</comment>
<comment xml:lang="pt_BR">Ãudio AMR-WB</comment>
<comment xml:lang="ro">Audio AMR-WB</comment>
- <comment xml:lang="ru">аудио AMR-WB</comment>
+ <comment xml:lang="ru">Ðудио AMR-WB</comment>
<comment xml:lang="sk">Zvuk AMR-WB</comment>
<comment xml:lang="sl">ZvoÄna datoteka AMR-WB</comment>
<comment xml:lang="sq">Audio AMR-WB</comment>
@@ -21724,7 +22408,7 @@
<comment xml:lang="pt">áudio ULAW (Sun)</comment>
<comment xml:lang="pt_BR">Ãudio ULAW (Sun)</comment>
<comment xml:lang="ro">Fișier audio ULAW (Sun)</comment>
- <comment xml:lang="ru">аудио ULAW (Sun)</comment>
+ <comment xml:lang="ru">Ðудио ULAW (Sun)</comment>
<comment xml:lang="sk">Zvuk ULAW (Sun)</comment>
<comment xml:lang="sl">ZvoÄna datoteka ULAW (Sun)</comment>
<comment xml:lang="sq">Audio ULAW (Sun)</comment>
@@ -21761,7 +22445,7 @@
<comment xml:lang="ga">fuaim Commodore 64</comment>
<comment xml:lang="gl">son de Commodore 64</comment>
<comment xml:lang="he">שמע של Commodore 64</comment>
- <comment xml:lang="hr">Commodore 64 audio</comment>
+ <comment xml:lang="hr">Commodore 64 zvuÄni zapis</comment>
<comment xml:lang="hu">Commodore 64 hang</comment>
<comment xml:lang="ia">Audio Commodore 64</comment>
<comment xml:lang="id">Audio Commodore 64</comment>
@@ -21781,7 +22465,7 @@
<comment xml:lang="pt">áudio Commodore 64</comment>
<comment xml:lang="pt_BR">Ãudio Commodore 64</comment>
<comment xml:lang="ro">Audio Commodore 64</comment>
- <comment xml:lang="ru">аудио Commodore 64</comment>
+ <comment xml:lang="ru">Ðудио Commodore 64</comment>
<comment xml:lang="sk">Zvuk Commodore 64</comment>
<comment xml:lang="sl">ZvoÄna datoteka Commodore 64</comment>
<comment xml:lang="sq">Audio Commodore 64</comment>
@@ -21839,7 +22523,7 @@
<comment xml:lang="pt">áudio PCM</comment>
<comment xml:lang="pt_BR">Ãudio PCM</comment>
<comment xml:lang="ro">Audio PCM</comment>
- <comment xml:lang="ru">аудио PCM</comment>
+ <comment xml:lang="ru">Ðудио PCM</comment>
<comment xml:lang="sk">Zvuk PCM</comment>
<comment xml:lang="sl">ZvoÄna datoteka PCM</comment>
<comment xml:lang="sq">Audio PCM</comment>
@@ -21888,7 +22572,7 @@
<comment xml:lang="ga">fuaim AIFC</comment>
<comment xml:lang="gl">son AIFC</comment>
<comment xml:lang="he">שמע AIFC</comment>
- <comment xml:lang="hr">AIFC audio</comment>
+ <comment xml:lang="hr">AIFC zvuÄni zapis</comment>
<comment xml:lang="hu">AIFC hang</comment>
<comment xml:lang="ia">Audio AIFC</comment>
<comment xml:lang="id">Audio AIFC</comment>
@@ -21908,7 +22592,7 @@
<comment xml:lang="pt">áudio AIFC</comment>
<comment xml:lang="pt_BR">Ãudio AIFC</comment>
<comment xml:lang="ro">Fișier audio AIFC</comment>
- <comment xml:lang="ru">аудио AIFC</comment>
+ <comment xml:lang="ru">Ðудио AIFC</comment>
<comment xml:lang="sk">Zvuk AIFC</comment>
<comment xml:lang="sl">ZvoÄna datoteka AIFC</comment>
<comment xml:lang="sq">Audio AIFC</comment>
@@ -21951,7 +22635,7 @@
<comment xml:lang="ga">fuaim AIFF/Amiga/Mac</comment>
<comment xml:lang="gl">son AIFF/Amiga/Mac</comment>
<comment xml:lang="he">שמע AIFF/Amiga/Mac</comment>
- <comment xml:lang="hr">AIFF/Amiga/Mac audio</comment>
+ <comment xml:lang="hr">AIFF/Amiga/Mac zvuÄni zapis</comment>
<comment xml:lang="hu">AIFF/Amiga/Mac hang</comment>
<comment xml:lang="ia">Audio AIFF/Amiga/Mac</comment>
<comment xml:lang="id">Audio AIFF/Amiga/Mac</comment>
@@ -21971,7 +22655,7 @@
<comment xml:lang="pt">áudio AIFF/Amiga/Mac</comment>
<comment xml:lang="pt_BR">Ãudio AIFF/Amiga/Mac</comment>
<comment xml:lang="ro">Audio AIFF/Amiga/Mac</comment>
- <comment xml:lang="ru">аудио AIFF/Amiga/Mac</comment>
+ <comment xml:lang="ru">Ðудио AIFF/Amiga/Mac</comment>
<comment xml:lang="sk">Zvuk AIFF/Amiga/Mac</comment>
<comment xml:lang="sl">ZvoÄna datoteka AIFF/Amiga/Mac</comment>
<comment xml:lang="sq">Audio AIFF/Amiga/Mac</comment>
@@ -22029,7 +22713,7 @@
<comment xml:lang="pt">áudio Monkey</comment>
<comment xml:lang="pt_BR">Ãudio Monkey's</comment>
<comment xml:lang="ro">Audio Monkey's</comment>
- <comment xml:lang="ru">аудио Monkey's</comment>
+ <comment xml:lang="ru">Ðудио Monkey's</comment>
<comment xml:lang="sk">Zvuk Monkey's</comment>
<comment xml:lang="sl">ZvoÄna datoteka Monkey</comment>
<comment xml:lang="sq">Audio Monkey's</comment>
@@ -22038,13 +22722,44 @@
<comment xml:lang="tr">Monkey's sesi</comment>
<comment xml:lang="uk">звук Monkey's</comment>
<comment xml:lang="vi">Âm thanh cua Monkey</comment>
- <comment xml:lang="zh_CN">Monkey's audio 音频</comment>
+ <comment xml:lang="zh_CN">Monkey's Audio 音频</comment>
<comment xml:lang="zh_TW">Monkey's 音訊</comment>
<magic priority="50">
<match value="MAC " type="string" offset="0"/>
</magic>
<glob pattern="*.ape"/>
</mime-type>
+ <mime-type type="audio/x-pn-audibleaudio">
+ <comment>Audible.Com audio</comment>
+ <comment xml:lang="ca">àudio Audible.Com</comment>
+ <comment xml:lang="cs">zvuk Audible.Com</comment>
+ <comment xml:lang="de">Audible.Com-Audio</comment>
+ <comment xml:lang="en_GB">Audible.Com audio</comment>
+ <comment xml:lang="es">sonido de Audible.com</comment>
+ <comment xml:lang="hr">Audible.Com zvuÄni zapis</comment>
+ <comment xml:lang="hu">Audible.Com hang</comment>
+ <comment xml:lang="id">Audio Audible.Com</comment>
+ <comment xml:lang="it">Audio Audible.Com</comment>
+ <comment xml:lang="kk">Audible.Com аудиоÑÑ‹</comment>
+ <comment xml:lang="ko">Audible.Com 오디오</comment>
+ <comment xml:lang="pl">Plik dźwiękowy Audible.com</comment>
+ <comment xml:lang="pt_BR">Ãudio de audible.com</comment>
+ <comment xml:lang="ru">Ðудио Audible.Com</comment>
+ <comment xml:lang="sk">Audio Audible.Com</comment>
+ <comment xml:lang="sv">Audible.Com-ljud</comment>
+ <comment xml:lang="uk">звук Audible.Com</comment>
+ <comment xml:lang="zh_CN">Audible.Com 音频</comment>
+ <comment xml:lang="zh_TW">Audible.Com 音訊</comment>
+ <magic priority="50">
+
+ <match value="1469084982" type="big32" offset="4"/>
+ <match value="aax " type="string" offset="8"/>
+ </magic>
+ <glob pattern="*.aa"/>
+ <glob pattern="*.aax"/>
+ <alias type="audio/vnd.audible"/>
+ <alias type="audio/vnd.audible.aax"/>
+ </mime-type>
<mime-type type="audio/x-it">
<comment>Impulse Tracker audio</comment>
<comment xml:lang="ar">Impulse Tracker سمعي</comment>
@@ -22067,7 +22782,7 @@
<comment xml:lang="ga">fuaim Impulse Tracker</comment>
<comment xml:lang="gl">son de Impulse Tracker</comment>
<comment xml:lang="he">שמע של Impulse Tracker</comment>
- <comment xml:lang="hr">Impulse Tracker audio</comment>
+ <comment xml:lang="hr">Impulse Tracker zvuÄni zapis</comment>
<comment xml:lang="hu">Impulse Tracker hang</comment>
<comment xml:lang="ia">Audio Impulse Tracker</comment>
<comment xml:lang="id">Audio Impulse Tracker</comment>
@@ -22086,7 +22801,7 @@
<comment xml:lang="pt">áudio Impulse Tracker</comment>
<comment xml:lang="pt_BR">Ãudio Impulse Tracker</comment>
<comment xml:lang="ro">Audio Impulse Tracker</comment>
- <comment xml:lang="ru">аудио Impulse Tracker</comment>
+ <comment xml:lang="ru">Ðудио Impulse Tracker</comment>
<comment xml:lang="sk">Zvuk Impulse Tracker</comment>
<comment xml:lang="sl">ZvoÄna datoteka Impulse Tracker</comment>
<comment xml:lang="sq">Audio Impulse Tracker</comment>
@@ -22122,7 +22837,7 @@
<comment xml:lang="ga">fuaim FLAC</comment>
<comment xml:lang="gl">son FLAC</comment>
<comment xml:lang="he">קובץ שמע מסוג FLAC</comment>
- <comment xml:lang="hr">FLAC audio</comment>
+ <comment xml:lang="hr">FLAC zvuÄni zapis</comment>
<comment xml:lang="hu">FLAC hang</comment>
<comment xml:lang="ia">Audio FLAC</comment>
<comment xml:lang="id">Audio FLAC</comment>
@@ -22142,7 +22857,7 @@
<comment xml:lang="pt">áudio FLAC</comment>
<comment xml:lang="pt_BR">Ãudio FLAC</comment>
<comment xml:lang="ro">Audio FLAC</comment>
- <comment xml:lang="ru">аудио FLAC</comment>
+ <comment xml:lang="ru">Ðудио FLAC</comment>
<comment xml:lang="sk">Zvuk FLAC</comment>
<comment xml:lang="sl">ZvoÄna datoteka Flac</comment>
<comment xml:lang="sq">Audio FLAC</comment>
@@ -22179,7 +22894,7 @@
<comment xml:lang="ga">fuaim WavPack</comment>
<comment xml:lang="gl">son WavPack</comment>
<comment xml:lang="he">שמע WavPack</comment>
- <comment xml:lang="hr">WavPack audio</comment>
+ <comment xml:lang="hr">WavPack zvuÄni zapis</comment>
<comment xml:lang="hu">WavPack hang</comment>
<comment xml:lang="ia">Audio WavPack</comment>
<comment xml:lang="id">Audio WavPack</comment>
@@ -22197,7 +22912,7 @@
<comment xml:lang="pt">áudio WavPack</comment>
<comment xml:lang="pt_BR">Ãudio WavPack</comment>
<comment xml:lang="ro">Audio WavPack</comment>
- <comment xml:lang="ru">аудио WavPack</comment>
+ <comment xml:lang="ru">Ðудио WavPack</comment>
<comment xml:lang="sk">Zvuk WavPack</comment>
<comment xml:lang="sl">ZvoÄna datoteka WavPack</comment>
<comment xml:lang="sq">Audio WavPack</comment>
@@ -22230,7 +22945,7 @@
<comment xml:lang="fi">WavPack-äänikorjaustiedosto</comment>
<comment xml:lang="fo">WavPack ljóðrættingarfíla</comment>
<comment xml:lang="fr">fichier de correction audio WavPack</comment>
- <comment xml:lang="ga">comhad cheartú fhuaim WavPack</comment>
+ <comment xml:lang="ga">comhad ceartúchán fuaime WavPack</comment>
<comment xml:lang="gl">ficheiro de corrección de son WavPack</comment>
<comment xml:lang="he">קובץ תיקון שמע של WavPack</comment>
<comment xml:lang="hr">WavPack datoteka ispravke zvuka</comment>
@@ -22251,7 +22966,7 @@
<comment xml:lang="pt">ficheiro de correção áudio WavPack</comment>
<comment xml:lang="pt_BR">Arquivo de correção de áudio WavPack</comment>
<comment xml:lang="ro">Fișier audio de corecție WavPack</comment>
- <comment xml:lang="ru">файл коррекции аудио WavPack</comment>
+ <comment xml:lang="ru">Файл коррекции аудио WavPack</comment>
<comment xml:lang="sk">Opravný zvukový súbor WavPack</comment>
<comment xml:lang="sl">popravljalna zvoÄna datoteka WavPack</comment>
<comment xml:lang="sq">File korrigjgimi audio WavPack</comment>
@@ -22260,7 +22975,7 @@
<comment xml:lang="tr">WavPack ses düzeltme dosyası</comment>
<comment xml:lang="uk">файл корекції звуку WavPack</comment>
<comment xml:lang="vi">Tập tin sửa chữa âm thanh WavPack</comment>
- <comment xml:lang="zh_CN">WavPack 音频校正文档</comment>
+ <comment xml:lang="zh_CN">WavPack 音频校正文件</comment>
<comment xml:lang="zh_TW">WavPack 音訊校正檔</comment>
<magic priority="50">
<match value="wvpk" type="string" offset="0"/>
@@ -22289,7 +23004,7 @@
<comment xml:lang="ga">fuaim MIDI</comment>
<comment xml:lang="gl">son MIDI</comment>
<comment xml:lang="he">שמע MIDI</comment>
- <comment xml:lang="hr">MIDI audio</comment>
+ <comment xml:lang="hr">MIDI zvuÄni zapis</comment>
<comment xml:lang="hu">MIDI hang</comment>
<comment xml:lang="ia">Audio MIDI</comment>
<comment xml:lang="id">Audio MIDI</comment>
@@ -22308,7 +23023,7 @@
<comment xml:lang="pt">áudio MIDI</comment>
<comment xml:lang="pt_BR">Ãudio MIDI</comment>
<comment xml:lang="ro">Audio MIDI</comment>
- <comment xml:lang="ru">аудио MIDI</comment>
+ <comment xml:lang="ru">Ðудио MIDI</comment>
<comment xml:lang="sk">Zvuk MIDI</comment>
<comment xml:lang="sl">ZvoÄna datoteka MIDI</comment>
<comment xml:lang="sq">Audio MIDI</comment>
@@ -22346,7 +23061,7 @@
<comment xml:lang="ga">fuaim chomhbhrúite Tracker</comment>
<comment xml:lang="gl">son comprimido de Tracker</comment>
<comment xml:lang="he">שמע גשש מכווץ</comment>
- <comment xml:lang="hr">komprimirani Tracker audio</comment>
+ <comment xml:lang="hr">Sažeti Tracker zvuÄni zapis</comment>
<comment xml:lang="hu">tömörített Tracker hang</comment>
<comment xml:lang="ia">Audio Tracker comprimite</comment>
<comment xml:lang="id">audio Tracker terkompresi</comment>
@@ -22363,7 +23078,7 @@
<comment xml:lang="pt">áudio comprimido Tracker</comment>
<comment xml:lang="pt_BR">Ãudio Tracker compactado</comment>
<comment xml:lang="ro">Tracker audio comprimat</comment>
- <comment xml:lang="ru">аудио Tracker (Ñжатое)</comment>
+ <comment xml:lang="ru">Сжатое аудио Tracker</comment>
<comment xml:lang="sk">Komprimovaný zvuk Tracker</comment>
<comment xml:lang="sl">SkrÄena zvoÄna datoteka Tracker</comment>
<comment xml:lang="sq">Audio Tracker e kompresuar</comment>
@@ -22391,6 +23106,7 @@
<comment xml:lang="eu">AAC audioa</comment>
<comment xml:lang="fi">AAC-ääni</comment>
<comment xml:lang="fr">audio AAC</comment>
+ <comment xml:lang="ga">fuaim AAC</comment>
<comment xml:lang="gl">Son AAC</comment>
<comment xml:lang="he">שמע AAC</comment>
<comment xml:lang="hr">AAC zvuÄni zapis</comment>
@@ -22403,10 +23119,10 @@
<comment xml:lang="ko">AAC 오디오</comment>
<comment xml:lang="lv">AAC audio</comment>
<comment xml:lang="oc">àudio AAC</comment>
- <comment xml:lang="pl">Dźwięk AAC</comment>
+ <comment xml:lang="pl">Plik dźwiękowy AAC</comment>
<comment xml:lang="pt">áudio AAC</comment>
<comment xml:lang="pt_BR">Ãudio AAC</comment>
- <comment xml:lang="ru">аудио AAC</comment>
+ <comment xml:lang="ru">Ðудио AAC</comment>
<comment xml:lang="sk">Zvuk AAC</comment>
<comment xml:lang="sl">Zvok AAC</comment>
<comment xml:lang="sr">ÐÐЦ звук</comment>
@@ -22422,8 +23138,17 @@
<match value="0xFFF0" type="big16" offset="0" mask="0xFFF6"/>
</magic>
<glob pattern="*.aac"/>
+ <glob pattern="*.adts"/>
+ <glob weight="10" pattern="*.ass"/>
<alias type="audio/x-aac"/>
</mime-type>
+ <mime-type type="audio/usac">
+ <comment>USAC audio</comment>
+ <acronym>USAC</acronym>
+ <expanded-acronym>Unified Speech and Audio Coding</expanded-acronym>
+ <glob pattern="*.loas"/>
+ <glob pattern="*.xhe"/>
+ </mime-type>
<mime-type type="audio/mp4">
<comment>MPEG-4 audio</comment>
<comment xml:lang="ar">MPEG-4 سمعي</comment>
@@ -22444,7 +23169,7 @@
<comment xml:lang="ga">fuaim MPEG-4</comment>
<comment xml:lang="gl">son MPEG-4</comment>
<comment xml:lang="he">שמע MPEG-4</comment>
- <comment xml:lang="hr">MPEG-4 audio</comment>
+ <comment xml:lang="hr">MPEG-4 zvuÄni zapis</comment>
<comment xml:lang="hu">MPEG-4 hang</comment>
<comment xml:lang="ia">Audio MPEG-4</comment>
<comment xml:lang="id">Audio MPEG-4</comment>
@@ -22463,7 +23188,7 @@
<comment xml:lang="pt">áudio MPEG-4</comment>
<comment xml:lang="pt_BR">Ãudio MPEG-4</comment>
<comment xml:lang="ro">Audio MPEG-4</comment>
- <comment xml:lang="ru">аудио MPEG-4</comment>
+ <comment xml:lang="ru">Ðудио MPEG-4</comment>
<comment xml:lang="sk">Zvuk MPEG-4</comment>
<comment xml:lang="sl">ZvoÄna datoteka MPEG-4</comment>
<comment xml:lang="sq">Audio MPEG-4</comment>
@@ -22482,9 +23207,15 @@
<glob pattern="*.m4a"/>
<glob pattern="*.f4a"/>
</mime-type>
+ <mime-type type="audio/x-m4r">
+ <comment>MPEG-4 Ringtone</comment>
+ <glob pattern="*.m4r"/>
+ <sub-class-of type="video/mp4"/>
+ </mime-type>
<mime-type type="video/mp4">
<comment>MPEG-4 video</comment>
<comment xml:lang="ar">MPEG-4 مرئي</comment>
+ <comment xml:lang="ast">Videu en MPEG-4</comment>
<comment xml:lang="be@latin">Videa MPEG-4</comment>
<comment xml:lang="bg">Видео — MPEG-4</comment>
<comment xml:lang="ca">vídeo MPEG-4</comment>
@@ -22502,7 +23233,7 @@
<comment xml:lang="ga">físeán MPEG-4</comment>
<comment xml:lang="gl">vídeo MPEG-4</comment>
<comment xml:lang="he">ויד×ו MPEG-4</comment>
- <comment xml:lang="hr">MPEG-4 video</comment>
+ <comment xml:lang="hr">MPEG-4 video snimka</comment>
<comment xml:lang="hu">MPEG-4 videó</comment>
<comment xml:lang="ia">Video MPEG-4</comment>
<comment xml:lang="id">Video MPEG-4</comment>
@@ -22521,7 +23252,7 @@
<comment xml:lang="pt">vídeo MPEG-4</comment>
<comment xml:lang="pt_BR">Vídeo MPEG-4</comment>
<comment xml:lang="ro">Video MPEG-4</comment>
- <comment xml:lang="ru">видео MPEG-4</comment>
+ <comment xml:lang="ru">Видео MPEG-4</comment>
<comment xml:lang="sk">Video MPEG-4</comment>
<comment xml:lang="sl">Video datoteka MPEG-4</comment>
<comment xml:lang="sq">Video MPEG-4</comment>
@@ -22563,10 +23294,10 @@
<comment xml:lang="fi">MPEG-4-äänikirja</comment>
<comment xml:lang="fo">MPEG-4 ljóðbók</comment>
<comment xml:lang="fr">livre audio MPEG-4</comment>
- <comment xml:lang="ga">leabhar fhuaim MPEG-4</comment>
+ <comment xml:lang="ga">closleabhar MPEG-4</comment>
<comment xml:lang="gl">sonlibro de MPEG-4</comment>
<comment xml:lang="he">ספר דיגיטלי MPEG-4</comment>
- <comment xml:lang="hr">MPEG-4 audio knjiga</comment>
+ <comment xml:lang="hr">MPEG-4 zvuÄna knjiga</comment>
<comment xml:lang="hu">MPEG-4 hangoskönyv</comment>
<comment xml:lang="ia">Libro audio MPEG-4</comment>
<comment xml:lang="id">Buku audio MPEG-4</comment>
@@ -22585,7 +23316,7 @@
<comment xml:lang="pt">livro áudio MPEG-4</comment>
<comment xml:lang="pt_BR">Ãudio livro MPEG-4</comment>
<comment xml:lang="ro">Carte audio MPEG-4</comment>
- <comment xml:lang="ru">аудиокнига MPEG-4</comment>
+ <comment xml:lang="ru">Ðудиокнига MPEG-4</comment>
<comment xml:lang="sk">Zvuková kniha MPEG-4</comment>
<comment xml:lang="sl">ZvoÄna knjiga MPEG-4</comment>
<comment xml:lang="sq">Audiolibër MPEG-4</comment>
@@ -22641,7 +23372,7 @@
<comment xml:lang="pt">ficheiro multimédia 3GPP</comment>
<comment xml:lang="pt_BR">Arquivo multimídia 3GPP</comment>
<comment xml:lang="ro">Fișier multimedia 3GPP</comment>
- <comment xml:lang="ru">мультимедийный файл 3GPP</comment>
+ <comment xml:lang="ru">Мультимедийный файл 3GPP</comment>
<comment xml:lang="sk">Súbor multimédií 3GPP</comment>
<comment xml:lang="sl">VeÄpredstavnostna datoteka 3GPP</comment>
<comment xml:lang="sq">File multimedial 3GPP</comment>
@@ -22707,7 +23438,7 @@
<comment xml:lang="pt">ficheiro multimédia 3GPP2</comment>
<comment xml:lang="pt_BR">Arquivo multimídia 3GPP2</comment>
<comment xml:lang="ro">Fișier multimedia 3GPP2</comment>
- <comment xml:lang="ru">мультимедийный файл 3GPP2</comment>
+ <comment xml:lang="ru">Мультимедийный файл 3GPP2</comment>
<comment xml:lang="sk">Súbor multimédií 3GPP2</comment>
<comment xml:lang="sl">VeÄpredstavnostna datoteka 3GPP2</comment>
<comment xml:lang="sr">3ГПП2 мултимедијална датотека</comment>
@@ -22747,7 +23478,7 @@
<comment xml:lang="ga">fuaim Amiga SoundTracker</comment>
<comment xml:lang="gl">son de Amiga SoundTracker</comment>
<comment xml:lang="he">קובץ שמע של Amiga SoundTracker</comment>
- <comment xml:lang="hr">Amiga SoundTracker audio</comment>
+ <comment xml:lang="hr">Amiga SoundTracker zvuÄni zapis</comment>
<comment xml:lang="hu">Amiga SoundTracker hang</comment>
<comment xml:lang="ia">Audio Amiga SoundTracker</comment>
<comment xml:lang="id">Audio Amida SoundTracker</comment>
@@ -22767,7 +23498,7 @@
<comment xml:lang="pt">áudio SoundTracker do Amiga</comment>
<comment xml:lang="pt_BR">Ãudio Amiga SoundTracker</comment>
<comment xml:lang="ro">Audio Amiga SoundTracker</comment>
- <comment xml:lang="ru">аудио Amiga SoundTracker</comment>
+ <comment xml:lang="ru">Ðудио Amiga SoundTracker</comment>
<comment xml:lang="sk">Zvuk Amiga SoundTracker</comment>
<comment xml:lang="sl">ZvoÄna datoteka Amiga SoundTracker</comment>
<comment xml:lang="sq">Audio Amiga SoundTracker</comment>
@@ -22840,7 +23571,7 @@
<comment xml:lang="ga">fuaim MP2</comment>
<comment xml:lang="gl">son MP2</comment>
<comment xml:lang="he">שמע MP2</comment>
- <comment xml:lang="hr">MP2 audio</comment>
+ <comment xml:lang="hr">MP2 zvuÄni zapis</comment>
<comment xml:lang="hu">MP2 hang</comment>
<comment xml:lang="ia">Audio MP2</comment>
<comment xml:lang="id">Audio MP2</comment>
@@ -22858,7 +23589,7 @@
<comment xml:lang="pt">áudio MP2</comment>
<comment xml:lang="pt_BR">Ãudio MP2</comment>
<comment xml:lang="ro">Audio MP2</comment>
- <comment xml:lang="ru">аудио MP2</comment>
+ <comment xml:lang="ru">Ðудио MP2</comment>
<comment xml:lang="sk">Zvuk MP2</comment>
<comment xml:lang="sl">ZvoÄna datoteka MP2</comment>
<comment xml:lang="sq">Audio MP2</comment>
@@ -22894,7 +23625,7 @@
<comment xml:lang="ga">fuaim MP3</comment>
<comment xml:lang="gl">son MP3</comment>
<comment xml:lang="he">שמע MP3</comment>
- <comment xml:lang="hr">MP3 audio</comment>
+ <comment xml:lang="hr">MP3 zvuÄni zapis</comment>
<comment xml:lang="hu">MP3 hang</comment>
<comment xml:lang="ia">Audio MP3</comment>
<comment xml:lang="id">Audio MP3</comment>
@@ -22914,7 +23645,7 @@
<comment xml:lang="pt">áudio MP3</comment>
<comment xml:lang="pt_BR">Ãudio MP3</comment>
<comment xml:lang="ro">Audio MP3</comment>
- <comment xml:lang="ru">аудио MP3</comment>
+ <comment xml:lang="ru">Ðудио MP3</comment>
<comment xml:lang="sk">Zvuk MP3</comment>
<comment xml:lang="sl">ZvoÄna datoteka MP3</comment>
<comment xml:lang="sq">Audio MP3</comment>
@@ -22972,11 +23703,11 @@
<comment xml:lang="nl">MP3-audio (gestreamd)</comment>
<comment xml:lang="nn">Strauma MP3-lyd</comment>
<comment xml:lang="oc">àudio MP3 (flux)</comment>
- <comment xml:lang="pl">Dźwięk MP3 (strumień)</comment>
+ <comment xml:lang="pl">Plik dźwiękowy MP3 (strumień)</comment>
<comment xml:lang="pt">áudio MP3 (em fluxo)</comment>
<comment xml:lang="pt_BR">Ãudio MP3 (em fluxo)</comment>
<comment xml:lang="ro">Audio MP3 (flux)</comment>
- <comment xml:lang="ru">аудио MP3 (потоковое)</comment>
+ <comment xml:lang="ru">Ðудио MP3 (потоковое)</comment>
<comment xml:lang="sk">Zvuk MP3 (streamovaný)</comment>
<comment xml:lang="sl">ZvoÄna datoteka MP3 (pretoÄna)</comment>
<comment xml:lang="sq">Audio MP3 (streamed)</comment>
@@ -22985,7 +23716,7 @@
<comment xml:lang="tr">MP3 sesi (akış)</comment>
<comment xml:lang="uk">звук MP3 (потоковий)</comment>
<comment xml:lang="vi">Âm thanh MP3 (chạy luồng)</comment>
- <comment xml:lang="zh_CN">MP3 æµéŸ³é¢‘</comment>
+ <comment xml:lang="zh_CN">MP3 音频æµåª’体</comment>
<comment xml:lang="zh_TW">MP3 音訊 (串æµ)</comment>
<sub-class-of type="text/plain"/>
<alias type="audio/mpegurl"/>
@@ -23033,14 +23764,14 @@
<comment xml:lang="pt">lista de reprodução HTTP Live Streaming</comment>
<comment xml:lang="pt_BR">Lista de Reprodução Streaming ao Vivo de HTTP</comment>
<comment xml:lang="ro">Listă de redare difuzată ca flux HTTP</comment>
- <comment xml:lang="ru">ÑпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ HTTP-потока</comment>
+ <comment xml:lang="ru">СпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ HTTP-потока</comment>
<comment xml:lang="sk">Zoznam stôp HTTP Live Streaming</comment>
<comment xml:lang="sl">Seznam predvajanja živega pretoka HTTP</comment>
<comment xml:lang="sr">ХТТП ÑпиÑак нумера Живог Протока</comment>
<comment xml:lang="sv">HTTP Live Streaming-spellista</comment>
<comment xml:lang="tr">HTTP Canlı Akış çalma listesi</comment>
<comment xml:lang="uk">ÑпиÑок Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ HTTP Live Streaming</comment>
- <comment xml:lang="zh_CN">HTTP ç›´æ’­æµæ’­æ”¾åˆ—表</comment>
+ <comment xml:lang="zh_CN">HTTP 实时æµæ’­æ”¾åˆ—表</comment>
<comment xml:lang="zh_TW">HTTP å³æ™‚串æµæ’­æ”¾æ¸…å–®</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.m3u"/>
@@ -23071,7 +23802,7 @@
<comment xml:lang="ga">seinmliosta Microsoft ASX</comment>
<comment xml:lang="gl">lista de reprodución Microsoft ASX</comment>
<comment xml:lang="he">רשימת השמעה ASX (מיקרוסופט)</comment>
- <comment xml:lang="hr">Microsoft ASX popis za reprodukciju</comment>
+ <comment xml:lang="hr">Microsoft ASX popis izvođenja</comment>
<comment xml:lang="hu">Microsoft ASX lejátszólista</comment>
<comment xml:lang="ia">Lista de selection Microsoft ASX</comment>
<comment xml:lang="id">Senarai putar Microsoft ASX</comment>
@@ -23090,7 +23821,7 @@
<comment xml:lang="pt">lista de reprodução Microsoft ASX</comment>
<comment xml:lang="pt_BR">Lista de reprodução do Microsoft ASX</comment>
<comment xml:lang="ro">Listă redare Microsoft ASX</comment>
- <comment xml:lang="ru">ÑпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Microsoft ASX</comment>
+ <comment xml:lang="ru">СпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Microsoft ASX</comment>
<comment xml:lang="sk">Zoznam skladieb Microsoft ASX</comment>
<comment xml:lang="sl">Seznam predvajanja Microsoft ASX</comment>
<comment xml:lang="sq">Listë titujsh Microsoft ASF</comment>
@@ -23154,7 +23885,7 @@
<comment xml:lang="pt">áudio PSF</comment>
<comment xml:lang="pt_BR">Ãudio PSF</comment>
<comment xml:lang="ro">Audio PSF</comment>
- <comment xml:lang="ru">аудио PSF</comment>
+ <comment xml:lang="ru">Ðудио PSF</comment>
<comment xml:lang="sk">Zvuk PSF</comment>
<comment xml:lang="sl">ZvoÄna datoteka PSF</comment>
<comment xml:lang="sq">Audio PSF</comment>
@@ -23192,7 +23923,7 @@
<comment xml:lang="ga">fuaim MiniPSF</comment>
<comment xml:lang="gl">son MiniPSF</comment>
<comment xml:lang="he">שמע של MiniPSP</comment>
- <comment xml:lang="hr">MiniPSF audio</comment>
+ <comment xml:lang="hr">MiniPSF zvuÄni zapis</comment>
<comment xml:lang="hu">MiniPSF hang</comment>
<comment xml:lang="ia">Audio MiniPSF</comment>
<comment xml:lang="id">Audio MiniPSF</comment>
@@ -23211,7 +23942,7 @@
<comment xml:lang="pt">áudio MiniPSF</comment>
<comment xml:lang="pt_BR">Ãudio MiniPSF</comment>
<comment xml:lang="ro">Audio MiniPSF</comment>
- <comment xml:lang="ru">аудио MiniPSF</comment>
+ <comment xml:lang="ru">Ðудио MiniPSF</comment>
<comment xml:lang="sk">Zvuk MiniPSF</comment>
<comment xml:lang="sl">ZvoÄna datoteka MiniPSF</comment>
<comment xml:lang="sq">Audio MiniPSF</comment>
@@ -23243,7 +23974,7 @@
<comment xml:lang="fi">PSFlib-äänikirjasto</comment>
<comment xml:lang="fo">PSFlib ljóðsavn</comment>
<comment xml:lang="fr">bibliothèque audio PSFlib</comment>
- <comment xml:lang="ga">leabharlann fhuaim PSFlib</comment>
+ <comment xml:lang="ga">leabharlann fhuaime PSFlib</comment>
<comment xml:lang="gl">Biblioteca de son PSFlib</comment>
<comment xml:lang="he">ספריית שמע PSFlib</comment>
<comment xml:lang="hr">PSFlib zvuÄna biblioteka</comment>
@@ -23264,7 +23995,7 @@
<comment xml:lang="pt">biblioteca áudio PSFlib</comment>
<comment xml:lang="pt_BR">Biblioteca de áudio PSFlib</comment>
<comment xml:lang="ro">Bibliotecă audio PSFlib</comment>
- <comment xml:lang="ru">фонотека PSFlib</comment>
+ <comment xml:lang="ru">Фонотека PSFlib</comment>
<comment xml:lang="sk">Zvuková knižnica PSFlib</comment>
<comment xml:lang="sl">ZvoÄna knjižnica PSFlib</comment>
<comment xml:lang="sq">Librari audio PSFlib</comment>
@@ -23273,7 +24004,7 @@
<comment xml:lang="tr">PSFlib ses kitaplığı</comment>
<comment xml:lang="uk">аудіобібліотека PSFlib</comment>
<comment xml:lang="vi">Thư viện âm thanh PSFlib</comment>
- <comment xml:lang="zh_CN">PSFlib 音频库文件</comment>
+ <comment xml:lang="zh_CN">PSFlib 音频库</comment>
<comment xml:lang="zh_TW">PSFlib 音訊庫</comment>
<acronym>PSFlib</acronym>
<expanded-acronym>Portable Sound Format Library</expanded-acronym>
@@ -23299,7 +24030,7 @@
<comment xml:lang="ga">fuaim Windows Media</comment>
<comment xml:lang="gl">son de Windows Media</comment>
<comment xml:lang="he">שמע של Windows Media</comment>
- <comment xml:lang="hr">Windows Media audio</comment>
+ <comment xml:lang="hr">Windows Media zvuÄni zapis</comment>
<comment xml:lang="hu">Windows Media hang</comment>
<comment xml:lang="ia">Audio Windows Media</comment>
<comment xml:lang="id">Audio Windows Media</comment>
@@ -23317,7 +24048,7 @@
<comment xml:lang="pt">áudio Windows Media</comment>
<comment xml:lang="pt_BR">Ãudio do Windows Media</comment>
<comment xml:lang="ro">Audio Windows Media</comment>
- <comment xml:lang="ru">аудио Windows Media</comment>
+ <comment xml:lang="ru">Ðудио Windows Media</comment>
<comment xml:lang="sk">Zvuk Windows Media</comment>
<comment xml:lang="sl">ZvoÄna datoteka Windows Media</comment>
<comment xml:lang="sq">Audio Windows Media</comment>
@@ -23351,7 +24082,7 @@
<comment xml:lang="ga">fuaim Musepack</comment>
<comment xml:lang="gl">son de Musepack</comment>
<comment xml:lang="he">שמע של Musepack</comment>
- <comment xml:lang="hr">Musepack audio</comment>
+ <comment xml:lang="hr">Musepack zvuÄni zapis</comment>
<comment xml:lang="hu">Musepack hang</comment>
<comment xml:lang="ia">Audio Musepack</comment>
<comment xml:lang="id">Audio Musepack</comment>
@@ -23369,7 +24100,7 @@
<comment xml:lang="pt">áudio Musepack</comment>
<comment xml:lang="pt_BR">Ãudio Musepack</comment>
<comment xml:lang="ro">Audio Musepack</comment>
- <comment xml:lang="ru">аудио Musepack</comment>
+ <comment xml:lang="ru">Ðудио Musepack</comment>
<comment xml:lang="sk">Zvuk Musepack</comment>
<comment xml:lang="sl">ZvoÄna datoteka Musepack</comment>
<comment xml:lang="sq">Audio Musepack</comment>
@@ -23390,6 +24121,7 @@
<mime-type type="audio/vnd.rn-realaudio">
<comment>RealAudio document</comment>
<comment xml:lang="ar">مستند RealAudio</comment>
+ <comment xml:lang="ast">Documentu RealAudio</comment>
<comment xml:lang="be@latin">Dakument RealAudio</comment>
<comment xml:lang="bg">Документ — RealAudio</comment>
<comment xml:lang="ca">document RealAudio</comment>
@@ -23425,7 +24157,7 @@
<comment xml:lang="pt">documento RealAudio</comment>
<comment xml:lang="pt_BR">Documento RealAudio</comment>
<comment xml:lang="ro">Document RealAudio</comment>
- <comment xml:lang="ru">документ RealAudio</comment>
+ <comment xml:lang="ru">Документ RealAudio</comment>
<comment xml:lang="sk">Dokument RealAudio</comment>
<comment xml:lang="sl">Dokument RealAudio</comment>
<comment xml:lang="sq">Dokument RealAudio</comment>
@@ -23457,7 +24189,7 @@
<comment xml:lang="fi">RealMedia-metatiedosto</comment>
<comment xml:lang="fo">RealMedia metafíla</comment>
<comment xml:lang="fr">métafichier RealMedia</comment>
- <comment xml:lang="ga">meiteachomhad RealMedia</comment>
+ <comment xml:lang="ga">Meiteachomhad RealMedia</comment>
<comment xml:lang="gl">Metaficheiro RealMedia</comment>
<comment xml:lang="he">קובץ ×ž×˜× ×©×œ RealMedia</comment>
<comment xml:lang="hr">RealMedia meta datoteka</comment>
@@ -23478,7 +24210,7 @@
<comment xml:lang="pt">metaficheiro RealMedia</comment>
<comment xml:lang="pt_BR">Meta arquivo do RealMedia</comment>
<comment xml:lang="ro">Metafișier RealMedia</comment>
- <comment xml:lang="ru">мета-файл RealMedia</comment>
+ <comment xml:lang="ru">Мета-файл RealMedia</comment>
<comment xml:lang="sk">RealMedia Metafile</comment>
<comment xml:lang="sl">Metadatoteka RealMedia</comment>
<comment xml:lang="sq">Metafile RealMedia</comment>
@@ -23494,6 +24226,7 @@
<mime-type type="video/vnd.rn-realvideo">
<comment>RealVideo document</comment>
<comment xml:lang="ar">مستند RealVideo</comment>
+ <comment xml:lang="ast">Documentu RealVideo</comment>
<comment xml:lang="be@latin">Dakument RealVideo</comment>
<comment xml:lang="bg">Документ — RealVideo</comment>
<comment xml:lang="ca">document RealVideo</comment>
@@ -23529,7 +24262,7 @@
<comment xml:lang="pt">documento RealVideo</comment>
<comment xml:lang="pt_BR">Documento RealVideo</comment>
<comment xml:lang="ro">Document RealVideo</comment>
- <comment xml:lang="ru">документ RealVideo</comment>
+ <comment xml:lang="ru">Документ RealVideo</comment>
<comment xml:lang="sk">Dokument RealVideo</comment>
<comment xml:lang="sl">Video datoteka RealVideo</comment>
<comment xml:lang="sq">Dokument RealVideo</comment>
@@ -23547,6 +24280,7 @@
<mime-type type="application/vnd.rn-realmedia">
<comment>RealMedia document</comment>
<comment xml:lang="ar">مستند RealMedia</comment>
+ <comment xml:lang="ast">Documentu RealMedia</comment>
<comment xml:lang="be@latin">Dakument RealMedia</comment>
<comment xml:lang="bg">Документ — RealMedia</comment>
<comment xml:lang="ca">document RealMedia</comment>
@@ -23582,7 +24316,7 @@
<comment xml:lang="pt">documento RealMedia</comment>
<comment xml:lang="pt_BR">Documento RealMedia</comment>
<comment xml:lang="ro">Document RealMedia</comment>
- <comment xml:lang="ru">документ RealMedia</comment>
+ <comment xml:lang="ru">Документ RealMedia</comment>
<comment xml:lang="sk">Dokument RealMedia</comment>
<comment xml:lang="sl">Dokument RealMedia</comment>
<comment xml:lang="sq">Dokument RealMedia</comment>
@@ -23608,6 +24342,7 @@
<mime-type type="image/vnd.rn-realpix">
<comment>RealPix document</comment>
<comment xml:lang="ar">مستند RealPix</comment>
+ <comment xml:lang="ast">Documentu RealPix</comment>
<comment xml:lang="be@latin">Dakument RealPix</comment>
<comment xml:lang="bg">Документ — RealPix</comment>
<comment xml:lang="ca">document RealPix</comment>
@@ -23643,7 +24378,7 @@
<comment xml:lang="pt">documento RealPix</comment>
<comment xml:lang="pt_BR">Documento RealPix</comment>
<comment xml:lang="ro">Document RealPix</comment>
- <comment xml:lang="ru">документ RealPix</comment>
+ <comment xml:lang="ru">Документ RealPix</comment>
<comment xml:lang="sk">Dokument RealPix</comment>
<comment xml:lang="sl">Dokument RealPix</comment>
<comment xml:lang="sq">Dokument RealPix</comment>
@@ -23659,6 +24394,7 @@
<mime-type type="text/vnd.rn-realtext">
<comment>RealText document</comment>
<comment xml:lang="ar">مستند RealText</comment>
+ <comment xml:lang="ast">Documentu RealText</comment>
<comment xml:lang="be@latin">Dakument RealText</comment>
<comment xml:lang="bg">Документ — RealText</comment>
<comment xml:lang="ca">document RealText</comment>
@@ -23694,7 +24430,7 @@
<comment xml:lang="pt">documento RealText</comment>
<comment xml:lang="pt_BR">Documento RealText</comment>
<comment xml:lang="ro">Document RealText</comment>
- <comment xml:lang="ru">документ RealText</comment>
+ <comment xml:lang="ru">Документ RealText</comment>
<comment xml:lang="sk">Dokument RealText</comment>
<comment xml:lang="sl">Dokument RealText</comment>
<comment xml:lang="sq">Dokument RealText</comment>
@@ -23729,7 +24465,7 @@
<comment xml:lang="ga">fuaim RIFF</comment>
<comment xml:lang="gl">son RIFF</comment>
<comment xml:lang="he">שמע RIFF</comment>
- <comment xml:lang="hr">RIFF audio</comment>
+ <comment xml:lang="hr">RIFF zvuÄni zapis</comment>
<comment xml:lang="hu">RIFF-kép</comment>
<comment xml:lang="ia">Audio RIFF</comment>
<comment xml:lang="id">Audio RIFF</comment>
@@ -23748,7 +24484,7 @@
<comment xml:lang="pt">áudio RIFF</comment>
<comment xml:lang="pt_BR">Ãudio RIFF</comment>
<comment xml:lang="ro">Audio RIFF</comment>
- <comment xml:lang="ru">аудио RIFF</comment>
+ <comment xml:lang="ru">Ðудио RIFF</comment>
<comment xml:lang="sk">Zvuk RIFF</comment>
<comment xml:lang="sl">ZvoÄna datoteka RIFF</comment>
<comment xml:lang="sq">Audio RIFF</comment>
@@ -23771,6 +24507,7 @@
<comment xml:lang="es">contenedor RIFF</comment>
<comment xml:lang="eu">RIFF edukitzailea</comment>
<comment xml:lang="fr">conteneur RIFF</comment>
+ <comment xml:lang="ga">coimeádán RIFF</comment>
<comment xml:lang="gl">Contenedor RIFF</comment>
<comment xml:lang="he">מכולת RIFF</comment>
<comment xml:lang="hr">RIFF spremnik</comment>
@@ -23820,7 +24557,7 @@
<comment xml:lang="ga">fuaim Scream Tracker 3</comment>
<comment xml:lang="gl">son Scream Tracker 3</comment>
<comment xml:lang="he">שמע של Scream Tracker 3</comment>
- <comment xml:lang="hr">Scream Tracker 3 audio</comment>
+ <comment xml:lang="hr">Scream Tracker 3 zvuÄni zapis</comment>
<comment xml:lang="hu">Scream Tracker 3 hang</comment>
<comment xml:lang="ia">Audio Scream Tracker 3</comment>
<comment xml:lang="id">Audio Scream Tracker 3</comment>
@@ -23839,7 +24576,7 @@
<comment xml:lang="pt">áudio Scream Tracker 3</comment>
<comment xml:lang="pt_BR">Ãudio Scream Tracker 3</comment>
<comment xml:lang="ro">Audio Scream Tracker 3</comment>
- <comment xml:lang="ru">аудио Scream Tracker 3</comment>
+ <comment xml:lang="ru">Ðудио Scream Tracker 3</comment>
<comment xml:lang="sk">Skladba Scream Tracker 3</comment>
<comment xml:lang="sl">ZvoÄna datoteka Scream Tracker 3</comment>
<comment xml:lang="sq">Audio Scream Tracker 3</comment>
@@ -23875,7 +24612,7 @@
<comment xml:lang="ga">seinmliosta MP3 ShoutCast</comment>
<comment xml:lang="gl">lista de reprodución MP3 de ShoutCast</comment>
<comment xml:lang="he">רשימת השמעה MP3 של ShoutCast</comment>
- <comment xml:lang="hr">MP3 ShoutCast popis za reprodukciju</comment>
+ <comment xml:lang="hr">MP3 ShoutCast popis izvođenja</comment>
<comment xml:lang="hu">MP3 ShoutCast-lejátszólista</comment>
<comment xml:lang="ia">Lista de selection MP3 ShoutCast</comment>
<comment xml:lang="id">Senarai putar MP3 ShoutCast</comment>
@@ -23894,7 +24631,7 @@
<comment xml:lang="pt">lista de reprodução MP3 ShoutCast</comment>
<comment xml:lang="pt_BR">Lista de reprodução MP3 ShoutCast</comment>
<comment xml:lang="ro">Listă MP3 ShoutCast</comment>
- <comment xml:lang="ru">ÑпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ MP3 ShoutCast</comment>
+ <comment xml:lang="ru">СпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ MP3 ShoutCast</comment>
<comment xml:lang="sk">Zoznam skladieb MP3 ShoutCast</comment>
<comment xml:lang="sl">Seznam predvajanja MP3 ShoutCast</comment>
<comment xml:lang="sq">Listë titujsh MP3 ShoutCast</comment>
@@ -23936,7 +24673,7 @@
<comment xml:lang="ga">fuaim Scream Tracker</comment>
<comment xml:lang="gl">son Scream Tracker</comment>
<comment xml:lang="he">שמע של Scream Tracker</comment>
- <comment xml:lang="hr">Scream Tracker audio</comment>
+ <comment xml:lang="hr">Scream Tracker zvuÄni zapis</comment>
<comment xml:lang="hu">Scream Tracker hang</comment>
<comment xml:lang="ia">Audio Scream Tracker</comment>
<comment xml:lang="id">Audio Scream Tracker</comment>
@@ -23955,7 +24692,7 @@
<comment xml:lang="pt">áudio Scream Tracker</comment>
<comment xml:lang="pt_BR">Ãudio Scream Tracker</comment>
<comment xml:lang="ro">Audio Scream Tracker</comment>
- <comment xml:lang="ru">аудио Scream Tracker</comment>
+ <comment xml:lang="ru">Ðудио Scream Tracker</comment>
<comment xml:lang="sk">Skladba Scream Tracker</comment>
<comment xml:lang="sl">ZvoÄna datoteka Scream Tracker</comment>
<comment xml:lang="sq">Audio Scream Tracker</comment>
@@ -23995,7 +24732,7 @@
<comment xml:lang="ga">fuaim VOC</comment>
<comment xml:lang="gl">son VOC</comment>
<comment xml:lang="he">שמע VOC</comment>
- <comment xml:lang="hr">VOC audio</comment>
+ <comment xml:lang="hr">VOC zvuÄni zapis</comment>
<comment xml:lang="hu">VOC hang</comment>
<comment xml:lang="ia">Audio VOC</comment>
<comment xml:lang="id">Audio VOC</comment>
@@ -24014,7 +24751,7 @@
<comment xml:lang="pt">áudio VOC</comment>
<comment xml:lang="pt_BR">Ãudio VOC</comment>
<comment xml:lang="ro">Audio VOC</comment>
- <comment xml:lang="ru">аудио VOC</comment>
+ <comment xml:lang="ru">Ðудио VOC</comment>
<comment xml:lang="sk">Zvuk VOC</comment>
<comment xml:lang="sl">ZvoÄna datoteka VOC</comment>
<comment xml:lang="sq">Audio VOC</comment>
@@ -24049,7 +24786,7 @@
<comment xml:lang="ga">fuaim WAV</comment>
<comment xml:lang="gl">son WAV</comment>
<comment xml:lang="he">שמע WAV</comment>
- <comment xml:lang="hr">WAV audio</comment>
+ <comment xml:lang="hr">WAV zvuÄni zapis</comment>
<comment xml:lang="hu">WAV hang</comment>
<comment xml:lang="ia">Audio WAV</comment>
<comment xml:lang="id">Audio WAV</comment>
@@ -24068,7 +24805,7 @@
<comment xml:lang="pt">áudio WAV</comment>
<comment xml:lang="pt_BR">Ãudio WAV</comment>
<comment xml:lang="ro">Audio WAV</comment>
- <comment xml:lang="ru">аудио WAV</comment>
+ <comment xml:lang="ru">Ðудио WAV</comment>
<comment xml:lang="sk">Zvuk WAV</comment>
<comment xml:lang="sl">ZvoÄna datoteka WAV</comment>
<comment xml:lang="sq">Audio WAV</comment>
@@ -24128,7 +24865,7 @@
<comment xml:lang="pt">instrumento Scream Tracker</comment>
<comment xml:lang="pt_BR">Instrumento Scream Tracker</comment>
<comment xml:lang="ro">Instrument Scream Tracker</comment>
- <comment xml:lang="ru">инÑтрумент Scream Tracker</comment>
+ <comment xml:lang="ru">ИнÑтрумент Scream Tracker</comment>
<comment xml:lang="sk">Nástroj pre Scream Tracker</comment>
<comment xml:lang="sl">Datoteka zvoka glasbila Scream Tracker</comment>
<comment xml:lang="sq">Instrument Scream Tracker</comment>
@@ -24166,7 +24903,7 @@
<comment xml:lang="ga">fuaim FastTracker II</comment>
<comment xml:lang="gl">son de FastTracker II</comment>
<comment xml:lang="he">שמע FastTracker II</comment>
- <comment xml:lang="hr">FastTracker II audio</comment>
+ <comment xml:lang="hr">FastTracker II zvuÄni zapis</comment>
<comment xml:lang="hu">FastTracker II hang</comment>
<comment xml:lang="ia">Audio FastTracker II</comment>
<comment xml:lang="id">Audio FastTracker II</comment>
@@ -24186,7 +24923,7 @@
<comment xml:lang="pt">áudio FastTracker II</comment>
<comment xml:lang="pt_BR">Ãudio FastTracker II</comment>
<comment xml:lang="ro">Audio FastTracker II</comment>
- <comment xml:lang="ru">аудио FastTracker II</comment>
+ <comment xml:lang="ru">Ðудио FastTracker II</comment>
<comment xml:lang="sk">Zvuk FastTracker II</comment>
<comment xml:lang="sl">ZvoÄna datoteka FastTracker II</comment>
<comment xml:lang="sq">Audio FastTracker II</comment>
@@ -24222,7 +24959,7 @@
<comment xml:lang="ga">fuaim TrueAudio</comment>
<comment xml:lang="gl">son Trueson</comment>
<comment xml:lang="he">שמע TrueAudio</comment>
- <comment xml:lang="hr">TrueAudio audio</comment>
+ <comment xml:lang="hr">TrueAudio zvuÄni zapis</comment>
<comment xml:lang="hu">TrueAudio hang</comment>
<comment xml:lang="ia">Audio TrueAudio</comment>
<comment xml:lang="id">Audio TrueAudio</comment>
@@ -24240,7 +24977,7 @@
<comment xml:lang="pt">áudio TrueAudio</comment>
<comment xml:lang="pt_BR">Ãudio TrueAudio</comment>
<comment xml:lang="ro">Audio TrueAudio</comment>
- <comment xml:lang="ru">аудио TrueAudio</comment>
+ <comment xml:lang="ru">Ðудио TrueAudio</comment>
<comment xml:lang="sk">Zvuk TrueAudio</comment>
<comment xml:lang="sl">ZvoÄna datoteka TrueAudio</comment>
<comment xml:lang="sq">Audio TrueAudio</comment>
@@ -24298,7 +25035,7 @@
<comment xml:lang="pt">imagem BMP Windows</comment>
<comment xml:lang="pt_BR">Imagem BMP do Windows</comment>
<comment xml:lang="ro">Imagine Windows BMP</comment>
- <comment xml:lang="ru">изображение Windows BMP</comment>
+ <comment xml:lang="ru">Изображение Windows BMP</comment>
<comment xml:lang="sk">Obrázok Windows BMP</comment>
<comment xml:lang="sl">Slikovna datoteka Windows BMP</comment>
<comment xml:lang="sq">Figurë Windows BMP</comment>
@@ -24360,7 +25097,7 @@
<comment xml:lang="pt">imagem WBMP</comment>
<comment xml:lang="pt_BR">Imagem WBMP</comment>
<comment xml:lang="ro">Imagine WBMP</comment>
- <comment xml:lang="ru">изображение WBMP</comment>
+ <comment xml:lang="ru">Изображение WBMP</comment>
<comment xml:lang="sk">Obrázok WBMP</comment>
<comment xml:lang="sl">Slikovna datoteka WBMP</comment>
<comment xml:lang="sq">Figurë WBMP</comment>
@@ -24393,7 +25130,7 @@
<comment xml:lang="fi">Computer Graphics -metatiedosto</comment>
<comment xml:lang="fo">Teldugrafikk metafíla</comment>
<comment xml:lang="fr">métafichier Computer Graphics</comment>
- <comment xml:lang="ga">meiteachomhad Grafaicí Ríomhaire</comment>
+ <comment xml:lang="ga">Meiteachomhad Grafaicí Ríomhaire</comment>
<comment xml:lang="gl">metaficheiro de Computer Graphics</comment>
<comment xml:lang="he">קובץ-מטה מסוג Computer Graphics</comment>
<comment xml:lang="hr">Computer Graphics meta datoteka</comment>
@@ -24415,7 +25152,7 @@
<comment xml:lang="pt">metaficheiro Computer Graphics</comment>
<comment xml:lang="pt_BR">Meta-arquivo do Computer Graphics</comment>
<comment xml:lang="ro">Metafișier Computer Graphics</comment>
- <comment xml:lang="ru">метафайл компьютерной графики</comment>
+ <comment xml:lang="ru">Метафайл компьютерной графики</comment>
<comment xml:lang="sk">Computer Graphics Metafile</comment>
<comment xml:lang="sl">Metadatoteka raÄunalniÅ¡ke grafike (CGM)</comment>
<comment xml:lang="sq">Metafile Computer Graphics</comment>
@@ -24424,7 +25161,7 @@
<comment xml:lang="tr">Computer Graphics Meta dosyası</comment>
<comment xml:lang="uk">метафайл комп'ютерної графіки</comment>
<comment xml:lang="vi">Siêu tập tin đồ há»a máy tính (CMF)</comment>
- <comment xml:lang="zh_CN">CGM 计算机图åƒå…ƒæ–‡ä»¶</comment>
+ <comment xml:lang="zh_CN">计算机图形图元文件 (CGM)</comment>
<comment xml:lang="zh_TW">CGM å½±åƒ</comment>
<glob pattern="*.cgm"/>
</mime-type>
@@ -24468,7 +25205,7 @@
<comment xml:lang="pt">fax CCITT G3</comment>
<comment xml:lang="pt_BR">Fax do CCITT G3</comment>
<comment xml:lang="ro">Fax CCITT G3</comment>
- <comment xml:lang="ru">Ñ„Ð°ÐºÑ CCITT G3</comment>
+ <comment xml:lang="ru">Ð¤Ð°ÐºÑ CCITT G3</comment>
<comment xml:lang="sk">Fax CCITT G3</comment>
<comment xml:lang="sl">Datoteka faksimila CCITT G3</comment>
<comment xml:lang="sq">Fax CCITT G3</comment>
@@ -24523,7 +25260,7 @@
<comment xml:lang="pt">imagem de fax G3</comment>
<comment xml:lang="pt_BR">Imagem de fax G3</comment>
<comment xml:lang="ro">Imagine fax G3</comment>
- <comment xml:lang="ru">факÑовое изображение G3</comment>
+ <comment xml:lang="ru">ФакÑовое изображение G3</comment>
<comment xml:lang="sk">Obrázok fax G3</comment>
<comment xml:lang="sl">Slikovna datoteka G3 fax</comment>
<comment xml:lang="sq">Figurë Fax G3</comment>
@@ -24532,7 +25269,7 @@
<comment xml:lang="tr">G3 fax görüntüsü</comment>
<comment xml:lang="uk">Ñ„Ð°ÐºÑ G3</comment>
<comment xml:lang="vi">Ảnh điện thư G3</comment>
- <comment xml:lang="zh_CN">G3 传真文档</comment>
+ <comment xml:lang="zh_CN">G3 传真图åƒ</comment>
<comment xml:lang="zh_TW">G3 傳真圖</comment>
</mime-type>
<mime-type type="image/gif">
@@ -24577,7 +25314,7 @@
<comment xml:lang="pt">imagem GIF</comment>
<comment xml:lang="pt_BR">Imagem GIF</comment>
<comment xml:lang="ro">Imagine GIF</comment>
- <comment xml:lang="ru">изображение GIF</comment>
+ <comment xml:lang="ru">Изображение GIF</comment>
<comment xml:lang="sk">Obrázok GIF</comment>
<comment xml:lang="sl">Slikovna datoteka GIF</comment>
<comment xml:lang="sq">Figurë GIF</comment>
@@ -24593,6 +25330,16 @@
</magic>
<glob pattern="*.gif"/>
</mime-type>
+ <mime-type type="image/heif">
+ <comment>HEIF image</comment>
+ <acronym>HEIF</acronym>
+ <expanded-acronym>High Efficiency Image File</expanded-acronym>
+ <glob pattern="*.heic"/>
+ <glob pattern="*.heif"/>
+ <alias type="image/heic"/>
+ <alias type="image/heic-sequence"/>
+ <alias type="image/heif-sequence"/>
+ </mime-type>
<mime-type type="image/ief">
<comment>IEF image</comment>
<comment xml:lang="ar">صورة IEF</comment>
@@ -24634,7 +25381,7 @@
<comment xml:lang="pt">imagem IEF</comment>
<comment xml:lang="pt_BR">Imagem IEF</comment>
<comment xml:lang="ro">Imagine IEF</comment>
- <comment xml:lang="ru">изображение IEF</comment>
+ <comment xml:lang="ru">Изображение IEF</comment>
<comment xml:lang="sk">Obrázok IEF</comment>
<comment xml:lang="sl">Slikovna datoteka IEF</comment>
<comment xml:lang="sq">Figurë IEF</comment>
@@ -24688,7 +25435,7 @@
<comment xml:lang="pt">imagem JPEG</comment>
<comment xml:lang="pt_BR">Imagem JPEG</comment>
<comment xml:lang="ro">Imagine JPEG</comment>
- <comment xml:lang="ru">изображение JPEG</comment>
+ <comment xml:lang="ru">Изображение JPEG</comment>
<comment xml:lang="sk">Obrázok JPEG</comment>
<comment xml:lang="sl">Slikovna datoteka JPEG</comment>
<comment xml:lang="sq">Figurë JPEG</comment>
@@ -24708,69 +25455,164 @@
<glob pattern="*.jpe"/>
<alias type="image/pjpeg"/>
</mime-type>
- <mime-type type="image/jp2">
- <comment>JPEG-2000 image</comment>
- <comment xml:lang="ar">صورة JPEG-2000</comment>
- <comment xml:lang="be@latin">Vyjava JPEG-2000</comment>
- <comment xml:lang="bg">Изображение — JPEG-2000</comment>
- <comment xml:lang="ca">imatge JPEG-2000</comment>
- <comment xml:lang="cs">obrázek JPEG-2000</comment>
- <comment xml:lang="da">JPEG2000-billede</comment>
- <comment xml:lang="de">JPEG-2000-Bild</comment>
- <comment xml:lang="el">Εικόνα JPEG-2000</comment>
- <comment xml:lang="en_GB">JPEG-2000 image</comment>
- <comment xml:lang="eo">JPEG-2000-bildo</comment>
- <comment xml:lang="es">imagen JPEG-2000</comment>
- <comment xml:lang="eu">JPEG-2000 irudia</comment>
- <comment xml:lang="fi">JPEG-2000-kuva</comment>
- <comment xml:lang="fo">JPEG-2000 mynd</comment>
- <comment xml:lang="fr">image JPEG-2000</comment>
- <comment xml:lang="ga">íomhá JPEG-2000</comment>
- <comment xml:lang="gl">imaxe JPEG-2000</comment>
- <comment xml:lang="he">תמונת JPEG-2000</comment>
- <comment xml:lang="hr">JPEG-2000 slika</comment>
- <comment xml:lang="hu">JPEG-2000 kép</comment>
- <comment xml:lang="ia">Imagine JPEG-2000</comment>
- <comment xml:lang="id">Citra JPEG-2000</comment>
- <comment xml:lang="it">Immagine JPEG-2000</comment>
- <comment xml:lang="ja">JPEG-2000 ç”»åƒ</comment>
- <comment xml:lang="kk">JPEG-2000 Ñуреті</comment>
- <comment xml:lang="ko">JPEG-2000 그림</comment>
- <comment xml:lang="lt">JPEG-2000 paveikslÄ—lis</comment>
- <comment xml:lang="lv">JPEG-2000 attēls</comment>
- <comment xml:lang="ms">Imej JPEG-2000</comment>
- <comment xml:lang="nb">JPEG-2000-bilde</comment>
- <comment xml:lang="nl">JPEG-2000-afbeelding</comment>
- <comment xml:lang="nn">JPEG-2000-bilete</comment>
- <comment xml:lang="oc">imatge JPEG-2000</comment>
- <comment xml:lang="pl">Obraz JPEG-2000</comment>
- <comment xml:lang="pt">imagem JPEG-2000</comment>
+ <mime-type type="video/x-mjpeg">
+ <comment>MJPEG video stream</comment>
+ <acronym>MJPEG</acronym>
+ <expanded-acronym>Motion JPEG</expanded-acronym>
+ <sub-class-of type="image/jpeg"/>
+ <glob pattern="*.mjpeg"/>
+ <glob pattern="*.mjpg"/>
+ </mime-type>
+ <mime-type type="image/x-jp2-codestream">
+ <comment>JPEG-2000 codestream</comment>
+ <comment xml:lang="ca">flux de codis JPEG-2000</comment>
+ <comment xml:lang="cs">datový tok JPEG-2000</comment>
+ <comment xml:lang="de">JPEG-2000 Codestream</comment>
+ <comment xml:lang="en_GB">JPEG-2000 codestream</comment>
+ <comment xml:lang="es">secuencia de código JPEG-2000</comment>
+ <comment xml:lang="hr">JPEG-2000 kôd strujanja</comment>
+ <comment xml:lang="hu">JPEG-2000 kódfolyam</comment>
+ <comment xml:lang="id">codestream JPEG-2000</comment>
+ <comment xml:lang="it">Codestream JPEG-2000</comment>
+ <comment xml:lang="kk">JPEG-2000 код ағыны</comment>
+ <comment xml:lang="ko">JPEG-2000 코드스트림</comment>
+ <comment xml:lang="pl">Strumień kodu JPEG-2000</comment>
<comment xml:lang="pt_BR">Imagem JPEG-2000</comment>
- <comment xml:lang="ro">Imagine JPEG-2000</comment>
- <comment xml:lang="ru">изображение JPEG-2000</comment>
- <comment xml:lang="sk">Obrázok JPEG-2000</comment>
- <comment xml:lang="sl">Slikovna datoteka JPEG-2000</comment>
- <comment xml:lang="sq">Figurë JPEG-2000</comment>
- <comment xml:lang="sr">ЈПЕГ-2000 Ñлика</comment>
- <comment xml:lang="sv">JPEG-2000-bild</comment>
- <comment xml:lang="tr">JPEG-2000 görüntüsü</comment>
- <comment xml:lang="uk">Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ JPEG-2000</comment>
- <comment xml:lang="vi">Ảnh JPEG-2000</comment>
- <comment xml:lang="zh_CN">JPEG-2000 图åƒ</comment>
- <comment xml:lang="zh_TW">JPEG-2000 å½±åƒ</comment>
+ <comment xml:lang="ru">Кодовый поток JPEG-2000</comment>
+ <comment xml:lang="sk">JPEG-2000 codestream</comment>
+ <comment xml:lang="sv">JPEG-2000-kodström</comment>
+ <comment xml:lang="uk">потік коду JPEG-2000</comment>
+ <comment xml:lang="zh_CN">JPEG-2000 ç æµ</comment>
+ <comment xml:lang="zh_TW">JPEG-2000 代碼串æµ</comment>
+ <magic priority="50">
+ <match value="0xff4fff51" type="big32" offset="0"/>
+ </magic>
+ <glob pattern="*.j2c"/>
+ <glob pattern="*.j2k"/>
+ <glob pattern="*.jpc"/>
+ </mime-type>
+ <mime-type type="image/jp2">
+ <comment>JPEG-2000 JP2 image</comment>
+ <comment xml:lang="ca">imatge JPEG-2000 JP2</comment>
+ <comment xml:lang="cs">obrázek JPEG-2000 JP2</comment>
+ <comment xml:lang="de">JPEG-2000 JP2-Bild</comment>
+ <comment xml:lang="en_GB">JPEG-2000 JP2 image</comment>
+ <comment xml:lang="es">imagen JPEG-2000 JP2</comment>
+ <comment xml:lang="fi">JPEG-2000 JP2 -kuva</comment>
+ <comment xml:lang="hr">JPEG-2000 JP2 slika</comment>
+ <comment xml:lang="hu">JPEG-2000 JP2 kép</comment>
+ <comment xml:lang="id">Citra JPEG-2000 JP2</comment>
+ <comment xml:lang="it">Immagine JPEG-2000 JP2</comment>
+ <comment xml:lang="kk">JPEG-2000 JP2 Ñуреті</comment>
+ <comment xml:lang="ko">JPEG-2000 JP2 그림</comment>
+ <comment xml:lang="pl">Obraz JP2 JPEG-2000</comment>
+ <comment xml:lang="pt_BR">Imagem JP2 de JPEG-2000</comment>
+ <comment xml:lang="ru">Изоражение JPEG-2000 JP2</comment>
+ <comment xml:lang="sk">Obrázok JPEG-2000 JP2</comment>
+ <comment xml:lang="sv">JPEG-2000 JP2-bild</comment>
+ <comment xml:lang="uk">Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ JP2 JPEG-2000</comment>
+ <comment xml:lang="zh_CN">JPEG-2000 JP2 图åƒ</comment>
+ <comment xml:lang="zh_TW">JPEG-2000 JP2 å½±åƒ</comment>
+ <acronym>JP2</acronym>
+ <expanded-acronym>JPEG-2000</expanded-acronym>
<alias type="image/jpeg2000"/>
- <alias type="image/jpx"/>
<alias type="image/jpeg2000-image"/>
<alias type="image/x-jpeg2000-image"/>
<magic priority="50">
- <match value="\xFF\x4F\xFF\x51\x00" type="string" offset="0"/>
- <match value="0x0c6a5020" type="big32" offset="3"/>
- <match value="jp2" type="string" offset="20"/>
+ <match value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a jp2\x20" type="string" offset="0" mask="0xffffffffffffffffffffffff0000000000000000ffffffff"/>
</magic>
<glob pattern="*.jp2"/>
- <glob pattern="*.jpx"/>
+ <glob pattern="*.jpg2"/>
+ </mime-type>
+ <mime-type type="image/jpx">
+ <comment>JPEG-2000 JPX image</comment>
+ <comment xml:lang="ca">imatge JPEG-2000 JPX</comment>
+ <comment xml:lang="cs">obrázek JPEG-2000 JPX</comment>
+ <comment xml:lang="de">JPEG-2000 JPX-Bild</comment>
+ <comment xml:lang="en_GB">JPEG-2000 JPX image</comment>
+ <comment xml:lang="es">imagen JPEG-2000 JPX</comment>
+ <comment xml:lang="fi">JPEG-2000 JPX -kuva</comment>
+ <comment xml:lang="hr">JPEG-2000 JPX slika</comment>
+ <comment xml:lang="hu">JPEG-2000 JPX kép</comment>
+ <comment xml:lang="id">Citra JPEG-2000 JPX</comment>
+ <comment xml:lang="it">Immagine JPEG-2000 JPX</comment>
+ <comment xml:lang="kk">JPEG-2000 JPX Ñуреті</comment>
+ <comment xml:lang="ko">JPEG-2000 JPX 그림</comment>
+ <comment xml:lang="pl">Obraz JPX JPEG-2000</comment>
+ <comment xml:lang="pt_BR">Imagem JPX de JPEG-2000</comment>
+ <comment xml:lang="ru">Изображение JPEG-2000 JPX</comment>
+ <comment xml:lang="sk">Obrázok JPEG-2000 JPX</comment>
+ <comment xml:lang="sv">JPEG-2000 JPX-bild</comment>
+ <comment xml:lang="uk">Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ JPX JPEG-2000</comment>
+ <comment xml:lang="zh_CN">JPEG-2000 JPX 图åƒ</comment>
+ <comment xml:lang="zh_TW">JPEG-2000 JPX å½±åƒ</comment>
+ <acronym>JPX</acronym>
+ <expanded-acronym>JPEG-2000 eXtended</expanded-acronym>
+ <magic priority="50">
+ <match value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a jpx\x20" type="string" offset="0" mask="0xffffffffffffffffffffffff0000000000000000ffffffff"/>
+ </magic>
<glob pattern="*.jpf"/>
-
+ <glob pattern="*.jpx"/>
+ </mime-type>
+ <mime-type type="image/jpm">
+ <comment>JPEG-2000 JPM image</comment>
+ <comment xml:lang="ca">imatge JPEG-2000 JPM</comment>
+ <comment xml:lang="cs">obrázek JPEG-2000 JPM</comment>
+ <comment xml:lang="de">JPEG-2000 JPM-Bild</comment>
+ <comment xml:lang="en_GB">JPEG-2000 JPM image</comment>
+ <comment xml:lang="es">imagen JPEG-2000 JPM</comment>
+ <comment xml:lang="fi">JPEG-2000 JPM -kuva</comment>
+ <comment xml:lang="hr">JPEG-2000 JPM slika</comment>
+ <comment xml:lang="hu">JPEG-2000 JPM kép</comment>
+ <comment xml:lang="id">Citra JPEG-2000 JPM</comment>
+ <comment xml:lang="it">Immagine JPEG-2000 JPM</comment>
+ <comment xml:lang="kk">JPEG-2000 JPM Ñуреті</comment>
+ <comment xml:lang="ko">JPEG-2000 JPM 그림</comment>
+ <comment xml:lang="pl">Obraz JPM JPEG-2000</comment>
+ <comment xml:lang="pt_BR">Imagem JPM de JPEG-2000</comment>
+ <comment xml:lang="ru">Изображение JPEG-2000 JPM</comment>
+ <comment xml:lang="sk">Obrázok JPEG-2000 JPM</comment>
+ <comment xml:lang="sv">JPEG-2000 JPM-bild</comment>
+ <comment xml:lang="uk">Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ JPM JPEG-2000</comment>
+ <comment xml:lang="zh_CN">JPEG-2000 JPM 图åƒ</comment>
+ <comment xml:lang="zh_TW">JPEG-2000 JPM å½±åƒ</comment>
+ <acronym>JPM</acronym>
+ <expanded-acronym>JPEG-2000 Mixed</expanded-acronym>
+ <magic priority="50">
+ <match value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a jpm\x20" type="string" offset="0" mask="0xffffffffffffffffffffffff0000000000000000ffffffff"/>
+ </magic>
+ <glob pattern="*.jpm"/>
+ <glob pattern="*.jpgm"/>
+ </mime-type>
+ <mime-type type="video/mj2">
+ <comment>JPEG-2000 MJ2 video</comment>
+ <comment xml:lang="ca">vídeo JPEG-2000 MJ2</comment>
+ <comment xml:lang="cs">video JPEG-2000 MJ2</comment>
+ <comment xml:lang="de">JPEG-2000 MJ2-Video</comment>
+ <comment xml:lang="en_GB">JPEG-2000 MJ2 video</comment>
+ <comment xml:lang="es">vídeo JPEG-2000 MJ2</comment>
+ <comment xml:lang="fi">JPEG-2000 MJ2 -video</comment>
+ <comment xml:lang="hr">JPEG-2000 MJ2 video snimka</comment>
+ <comment xml:lang="hu">JPEG-2000 MJ2 videó</comment>
+ <comment xml:lang="id">Video JPEG-2000 MJ2</comment>
+ <comment xml:lang="it">Video JPEG-2000 MJ2</comment>
+ <comment xml:lang="kk">JPEG-2000 MJ2 видеоÑÑ‹</comment>
+ <comment xml:lang="ko">JPEG-2000 MJ2 ë™ì˜ìƒ</comment>
+ <comment xml:lang="pl">Plik wideo MJ2 JPEG-2000</comment>
+ <comment xml:lang="pt_BR">Imagem MJ2 de JPEG-2000</comment>
+ <comment xml:lang="ru">Видео JPEG-2000 MJ2</comment>
+ <comment xml:lang="sk">Video JPEG-2000 MJ2</comment>
+ <comment xml:lang="sv">JPEG-2000 MJ2-bild</comment>
+ <comment xml:lang="uk">Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ MJ2 JPEG-2000</comment>
+ <comment xml:lang="zh_CN">JPEG-2000 MJ2 视频</comment>
+ <comment xml:lang="zh_TW">JPEG-2000 MJ2 視訊</comment>
+ <acronym>MJ2</acronym>
+ <expanded-acronym>Motion JPEG-2000</expanded-acronym>
+ <magic priority="50">
+ <match value="\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a mjp2" type="string" offset="0" mask="0xffffffffffffffffffffffff0000000000000000ffffffff"/>
+ </magic>
+ <glob pattern="*.mj2"/>
+ <glob pattern="*.mjp2"/>
</mime-type>
<mime-type type="image/openraster">
<comment>OpenRaster archiving image</comment>
@@ -24807,14 +25649,14 @@
<comment xml:lang="pt">imagem arquivo OpenRaster</comment>
<comment xml:lang="pt_BR">Imagem de arquivamento OpenRaster</comment>
<comment xml:lang="ro">Arhivă imagine OpenRaster</comment>
- <comment xml:lang="ru">архивное изображение OpenRaster</comment>
+ <comment xml:lang="ru">Ðрхивное изображение OpenRaster</comment>
<comment xml:lang="sk">ArchivaÄný obrázok OpenRaster</comment>
<comment xml:lang="sl">Odtis arhiva OpenRaster</comment>
<comment xml:lang="sr">Ñлика Опен РаÑтер архивирања</comment>
<comment xml:lang="sv">OpenRaster-arkivbild</comment>
<comment xml:lang="tr">OpenRaster arşivleme görüntüsü</comment>
<comment xml:lang="uk">архівоване Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ OpenRaster</comment>
- <comment xml:lang="zh_CN">OpenRaster 归档映åƒ</comment>
+ <comment xml:lang="zh_CN">OpenRaster 归档图åƒ</comment>
<comment xml:lang="zh_TW">OpenRaster å°å­˜å½±åƒ</comment>
<sub-class-of type="application/zip"/>
<magic priority="70">
@@ -24864,7 +25706,7 @@
<comment xml:lang="pt">superfície DirectDraw</comment>
<comment xml:lang="pt_BR">Superfície do DirectDraw</comment>
<comment xml:lang="ro">Suprafață DirectDraw</comment>
- <comment xml:lang="ru">плоÑкоÑÑ‚ÑŒ DirectDraw</comment>
+ <comment xml:lang="ru">ПлоÑкоÑÑ‚ÑŒ DirectDraw</comment>
<comment xml:lang="sk">Plocha DirectDraw</comment>
<comment xml:lang="sl">Datoteka predmeta DirectDraw</comment>
<comment xml:lang="sq">Superfaqe DirectDraw</comment>
@@ -24899,7 +25741,7 @@
<comment xml:lang="ga">cúrsóir X11</comment>
<comment xml:lang="gl">Cursor X11</comment>
<comment xml:lang="he">סמן של X11</comment>
- <comment xml:lang="hr">X11 kursor</comment>
+ <comment xml:lang="hr">X11 pokazivaÄ</comment>
<comment xml:lang="hu">X11 kurzor</comment>
<comment xml:lang="ia">Cursor X11</comment>
<comment xml:lang="id">Kursor X11</comment>
@@ -24917,7 +25759,7 @@
<comment xml:lang="pt">cursor X11</comment>
<comment xml:lang="pt_BR">Cursor do X11</comment>
<comment xml:lang="ro">Cursor X11</comment>
- <comment xml:lang="ru">курÑор X11</comment>
+ <comment xml:lang="ru">КурÑор X11</comment>
<comment xml:lang="sk">Kurzor X11</comment>
<comment xml:lang="sl">Datoteka kazalke X11</comment>
<comment xml:lang="sq">Kursor X11</comment>
@@ -24971,7 +25813,7 @@
<comment xml:lang="pt">imagem EXR</comment>
<comment xml:lang="pt_BR">Imagem EXR</comment>
<comment xml:lang="ro">Imagine EXR</comment>
- <comment xml:lang="ru">изображение EXR</comment>
+ <comment xml:lang="ru">Изображение EXR</comment>
<comment xml:lang="sk">Obrázok EXR</comment>
<comment xml:lang="sl">Slikovna datoteka EXR</comment>
<comment xml:lang="sq">Figurë EXR</comment>
@@ -25026,7 +25868,7 @@
<comment xml:lang="pt">desenho Quickdraw/PICT de Macintosh</comment>
<comment xml:lang="pt_BR">Desenho do Macintosh Quickdraw/PICT</comment>
<comment xml:lang="ro">Desen Macintosh Quickdraw/PICT</comment>
- <comment xml:lang="ru">риÑунок Macintosh Quickdraw/PICT</comment>
+ <comment xml:lang="ru">РиÑунок Macintosh Quickdraw/PICT</comment>
<comment xml:lang="sk">Kresba Macintosh QuickDraw/PICT</comment>
<comment xml:lang="sl">Datoteka risbe Macintosh Quickdraw/PICT</comment>
<comment xml:lang="sq">Vizatim Macintosh Quickdraw/PICT</comment>
@@ -25097,7 +25939,7 @@
<comment xml:lang="pt">imagem UFRaw ID</comment>
<comment xml:lang="pt_BR">Imagem ID do UFRaw</comment>
<comment xml:lang="ro">ID imagine UFRaw</comment>
- <comment xml:lang="ru">изображение UFRaw ID</comment>
+ <comment xml:lang="ru">Изображение UFRaw ID</comment>
<comment xml:lang="sk">Obrázok ID UFRaw</comment>
<comment xml:lang="sl">Slikovna datoteka UFRaw ID</comment>
<comment xml:lang="sq">Figurë UFRaw ID</comment>
@@ -25130,7 +25972,7 @@
<comment xml:lang="fi">digitaalinen raakakuva</comment>
<comment xml:lang="fo">talgild rámynd</comment>
<comment xml:lang="fr">image brute numérique</comment>
- <comment xml:lang="ga">amhíomhá digiteach</comment>
+ <comment xml:lang="ga">amhíomhá dhigiteach</comment>
<comment xml:lang="gl">imaxe en bruto dixital</comment>
<comment xml:lang="he">תמונה דיגטלית גולמית</comment>
<comment xml:lang="hr">Digitalna osnovna slika</comment>
@@ -25151,7 +25993,7 @@
<comment xml:lang="pt">imagem digital em bruto</comment>
<comment xml:lang="pt_BR">Imagem digital bruta</comment>
<comment xml:lang="ro">imagine digitală brută</comment>
- <comment xml:lang="ru">необработанные цифровые изображениÑ</comment>
+ <comment xml:lang="ru">Ðеобработанное цифровое изображение</comment>
<comment xml:lang="sk">Digitálny surový obrázok</comment>
<comment xml:lang="sl">surova digitalna slika</comment>
<comment xml:lang="sq">Figurë raw dixhitale</comment>
@@ -25201,7 +26043,7 @@
<comment xml:lang="pt">negativo Adobe DNG</comment>
<comment xml:lang="pt_BR">Negativo DNG da Adobe</comment>
<comment xml:lang="ro">Negativ Adobe DNG</comment>
- <comment xml:lang="ru">негатив Adobe DNG</comment>
+ <comment xml:lang="ru">Ðегатив Adobe DNG</comment>
<comment xml:lang="sk">Adobe Digital Negative (DNG)</comment>
<comment xml:lang="sl">Datoteka negativa Adobe DNG</comment>
<comment xml:lang="sq">Negativ Adobe DNG</comment>
@@ -25258,7 +26100,7 @@
<comment xml:lang="pt">imagem em bruto Canon CRW</comment>
<comment xml:lang="pt_BR">Imagem bruta CRW da Canon</comment>
<comment xml:lang="ro">Imagine brută Canon CRW</comment>
- <comment xml:lang="ru">необработанное изображение Canon CRW</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Canon CRW</comment>
<comment xml:lang="sk">Surový obrázok Canon CRW</comment>
<comment xml:lang="sl">Surova slikovna datoteka Canon CRW</comment>
<comment xml:lang="sq">Figurë raw Canon CRW</comment>
@@ -25267,7 +26109,7 @@
<comment xml:lang="tr">Canon CRW ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив CRW Canon</comment>
<comment xml:lang="vi">Ảnh thô Canon CRW</comment>
- <comment xml:lang="zh_CN">Canon CRW 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">佳能 CRW 原始图åƒ</comment>
<comment xml:lang="zh_TW">Canon CRW 原生影åƒ</comment>
<acronym>CRW</acronym>
<expanded-acronym>Canon RaW</expanded-acronym>
@@ -25316,7 +26158,7 @@
<comment xml:lang="pt">imagem em bruto Canon CR2</comment>
<comment xml:lang="pt_BR">Imagem bruta CR2 da Canon</comment>
<comment xml:lang="ro">Imagine brută Canon CR2</comment>
- <comment xml:lang="ru">необработанное изображение Canon CR2</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Canon CR2</comment>
<comment xml:lang="sk">Surový obrázok Canon CR2</comment>
<comment xml:lang="sl">Surova slikovna datoteka Canon CR2</comment>
<comment xml:lang="sq">Figurë raw Canon CR2</comment>
@@ -25325,7 +26167,7 @@
<comment xml:lang="tr">Canon CR2 ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив CR2 Canon</comment>
<comment xml:lang="vi">Ảnh thô Canon CR2</comment>
- <comment xml:lang="zh_CN">Canon CR2 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">佳能 CR2 原始图åƒ</comment>
<comment xml:lang="zh_TW">Canon CR2 原生影åƒ</comment>
<acronym>CR2</acronym>
<expanded-acronym>Canon Raw 2</expanded-acronym>
@@ -25371,7 +26213,7 @@
<comment xml:lang="pt">imagem em bruto Fuji RAF</comment>
<comment xml:lang="pt_BR">Imagem bruta RAF da Fuji</comment>
<comment xml:lang="ro">Imagine brută Fuji RAF</comment>
- <comment xml:lang="ru">необработанное изображение Fuji RAF</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Fuji RAF</comment>
<comment xml:lang="sk">Surový obrázok Fuji RAF</comment>
<comment xml:lang="sl">Surova slikovna datoteka Fuji RAF</comment>
<comment xml:lang="sq">Figurë raw Fuji RAF</comment>
@@ -25380,7 +26222,7 @@
<comment xml:lang="tr">Fuji RAF ham görüntüsü</comment>
<comment xml:lang="uk">Цифровий негатив RAF Fuji</comment>
<comment xml:lang="vi">Ảnh thô Fuji RAF</comment>
- <comment xml:lang="zh_CN">富士RAF 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">富士 RAF 原始图åƒ</comment>
<comment xml:lang="zh_TW">Fuji RAF 原生影åƒ</comment>
<acronym>RAF</acronym>
<expanded-acronym>RAw Format</expanded-acronym>
@@ -25427,7 +26269,7 @@
<comment xml:lang="pt">imagem em bruto Kodak DCR</comment>
<comment xml:lang="pt_BR">Imagem bruta DCR da Kodak</comment>
<comment xml:lang="ro">Imagine brută Kodak DCR</comment>
- <comment xml:lang="ru">необработанное изображение Kodak DCR</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Kodak DCR</comment>
<comment xml:lang="sk">Surový obrázok Kodak DCR</comment>
<comment xml:lang="sl">Surova slikovna datoteka Kodak DCR</comment>
<comment xml:lang="sq">Figurë raw Kodak DCR</comment>
@@ -25436,7 +26278,7 @@
<comment xml:lang="tr">Kodak DCR ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив DCR Kodak</comment>
<comment xml:lang="vi">Ảnh thô Kodak DCR</comment>
- <comment xml:lang="zh_CN">Kodak DCR 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">柯达 DCR 原始图åƒ</comment>
<comment xml:lang="zh_TW">Kodak DCR 原生影åƒ</comment>
<acronym>DCR</acronym>
<expanded-acronym>Digital Camera Raw</expanded-acronym>
@@ -25481,7 +26323,7 @@
<comment xml:lang="pt">imagem em bruto Kodak K25</comment>
<comment xml:lang="pt_BR">Imagem bruta K25 da Kodak</comment>
<comment xml:lang="ro">Imagine brută Kodak K25</comment>
- <comment xml:lang="ru">необработанное изображение Kodak K25</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Kodak K25</comment>
<comment xml:lang="sk">Surový obrázok Kodak K25</comment>
<comment xml:lang="sl">Surova slikovna datoteka Kodak K25</comment>
<comment xml:lang="sq">Figurë raw Kodak K25</comment>
@@ -25490,7 +26332,7 @@
<comment xml:lang="tr">Kodak K25 ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив K25 Kodak</comment>
<comment xml:lang="vi">Ảnh thô Kodak K25</comment>
- <comment xml:lang="zh_CN">Kodak K25 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">柯达 K25 原始图åƒ</comment>
<comment xml:lang="zh_TW">Kodak K25 原生影åƒ</comment>
<acronym>K25</acronym>
<expanded-acronym>Kodak DC25</expanded-acronym>
@@ -25535,7 +26377,7 @@
<comment xml:lang="pt">imagem em bruto Kodak KDC</comment>
<comment xml:lang="pt_BR">Imagem bruta KDC da Kodak</comment>
<comment xml:lang="ro">Imagine brută Kodak KDC</comment>
- <comment xml:lang="ru">необработанное изображение Kodak KDC</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Kodak KDC</comment>
<comment xml:lang="sk">Surový obrázok Kodak KDC</comment>
<comment xml:lang="sl">Surova slikovna datoteka Kodak KDC</comment>
<comment xml:lang="sq">Figurë raw Kodak KDC</comment>
@@ -25544,7 +26386,7 @@
<comment xml:lang="tr">Kodak KDC ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив KDC Kodak</comment>
<comment xml:lang="vi">Ảnh thô Kodak KDC</comment>
- <comment xml:lang="zh_CN">Kodak KDC 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">柯达 KDC 原始图åƒ</comment>
<comment xml:lang="zh_TW">Kodak KDC 原生影åƒ</comment>
<acronym>KDC</acronym>
<expanded-acronym>Kodak Digital Camera</expanded-acronym>
@@ -25592,7 +26434,7 @@
<comment xml:lang="pt">imagem em bruto Minolta MRW</comment>
<comment xml:lang="pt_BR">Imagem bruta MRW do Minolta</comment>
<comment xml:lang="ro">Imagine brută Minolta MRW</comment>
- <comment xml:lang="ru">необработанное изображение Minolta MRW</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Minolta MRW</comment>
<comment xml:lang="sk">Surový obrázok Minolta MRW</comment>
<comment xml:lang="sl">Surova slikovna datoteka Minolta MRW</comment>
<comment xml:lang="sq">Figurë raw Minolta MRW</comment>
@@ -25601,7 +26443,7 @@
<comment xml:lang="tr">Minolta MRW ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив MRW Minolta</comment>
<comment xml:lang="vi">Ảnh thô Minolta MRW</comment>
- <comment xml:lang="zh_CN">Minolta MRW 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">美能达 MRW 原始图åƒ</comment>
<comment xml:lang="zh_TW">Minolta MRW 原生影åƒ</comment>
<acronym>MRW</acronym>
<expanded-acronym>Minolta RaW</expanded-acronym>
@@ -25648,7 +26490,7 @@
<comment xml:lang="pt">imagem em bruto Nikon NEF</comment>
<comment xml:lang="pt_BR">Imagem bruta NEF da Nikon</comment>
<comment xml:lang="ro">Imagine brută Nikon NEF</comment>
- <comment xml:lang="ru">необработанное изображение Nikon NEF</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Nikon NEF</comment>
<comment xml:lang="sk">Surový obrázok Nikon NEF</comment>
<comment xml:lang="sl">Surova slikovna datoteka Nikon NEF</comment>
<comment xml:lang="sq">Figurë raw Nikon NEF</comment>
@@ -25657,7 +26499,7 @@
<comment xml:lang="tr">Nikon NEF ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив NEF Nikon</comment>
<comment xml:lang="vi">Ảnh thô Nikon NEF</comment>
- <comment xml:lang="zh_CN">Nikon NEF 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">尼康 NEF 原始图åƒ</comment>
<comment xml:lang="zh_TW">Nikon NEF 原生影åƒ</comment>
<acronym>NEF</acronym>
<expanded-acronym>Nikon Electronic Format</expanded-acronym>
@@ -25703,7 +26545,7 @@
<comment xml:lang="pt">imagem em bruto Olympus ORF</comment>
<comment xml:lang="pt_BR">Imagem bruta ORF da Olympus</comment>
<comment xml:lang="ro">Imagine brută Olympus ORF</comment>
- <comment xml:lang="ru">необработанное изображение Olympus ORF</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Olympus ORF</comment>
<comment xml:lang="sk">Surový obrázok Olympus ORF</comment>
<comment xml:lang="sl">Surova slikovna datoteka Olympus ORF</comment>
<comment xml:lang="sq">Figurë raw Olympus ORF</comment>
@@ -25712,7 +26554,7 @@
<comment xml:lang="tr">Olympus ORF ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив ORF Olympus</comment>
<comment xml:lang="vi">Ảnh thô Olympus ORF</comment>
- <comment xml:lang="zh_CN">Olympus ORF 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">奥林巴斯 ORF 原始图åƒ</comment>
<comment xml:lang="zh_TW">Olympus ORF 原生影åƒ</comment>
<acronym>ORF</acronym>
<expanded-acronym>Olympus Raw Format</expanded-acronym>
@@ -25727,7 +26569,7 @@
</magic>
<glob pattern="*.orf"/>
</mime-type>
- <mime-type type="image/x-panasonic-raw">
+ <mime-type type="image/x-panasonic-rw">
<comment>Panasonic raw image</comment>
<comment xml:lang="ar">صورة Panasonic خامة</comment>
<comment xml:lang="be@latin">Suvoraja vyjava Panasonic</comment>
@@ -25764,7 +26606,7 @@
<comment xml:lang="pt">imagem em bruto Panasonic</comment>
<comment xml:lang="pt_BR">Imagem bruta da Panasonic</comment>
<comment xml:lang="ro">Imagine brută Panasonic</comment>
- <comment xml:lang="ru">необработанное изображение Panasonic</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Panasonic</comment>
<comment xml:lang="sk">Surový obrázok Panasonic</comment>
<comment xml:lang="sl">Surova slikovna datoteka Panasonic</comment>
<comment xml:lang="sq">Figurë raw Panasonic</comment>
@@ -25773,7 +26615,7 @@
<comment xml:lang="tr">Panasonic ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив Panasonic</comment>
<comment xml:lang="vi">Ảnh thô Panasonic</comment>
- <comment xml:lang="zh_CN">Panasonic 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">æ¾ä¸‹åŽŸå§‹å›¾åƒ</comment>
<comment xml:lang="zh_TW">Panasonic 原生影åƒ</comment>
<sub-class-of type="image/x-dcraw"/>
<magic priority="50">
@@ -25781,8 +26623,9 @@
<match value="IIU\x00\x08\x00\x00\x00" type="string" offset="0"/>
</magic>
<glob pattern="*.raw"/>
+ <alias type="image/x-panasonic-raw"/>
</mime-type>
- <mime-type type="image/x-panasonic-raw2">
+ <mime-type type="image/x-panasonic-rw2">
<comment>Panasonic raw2 image</comment>
<comment xml:lang="bg">Изображение — Panasonic raw2</comment>
<comment xml:lang="ca">imatge «RAW2» de Panasonic</comment>
@@ -25795,6 +26638,7 @@
<comment xml:lang="eu">Panasonic raw2 irudia</comment>
<comment xml:lang="fi">Panasonic raw2 -kuva</comment>
<comment xml:lang="fr">image raw2 Panasonic</comment>
+ <comment xml:lang="ga">íomhá raw2 Panasonic</comment>
<comment xml:lang="gl">imaxe en bruto raw2 de Panasonic</comment>
<comment xml:lang="he">תמונת raw2 של Panasonic</comment>
<comment xml:lang="hr">Panasonic raw2 image</comment>
@@ -25811,14 +26655,14 @@
<comment xml:lang="pl">Obraz raw2 Panasonic</comment>
<comment xml:lang="pt">imagem em bruto Panasonic</comment>
<comment xml:lang="pt_BR">Imagem raw2 da Panasonic</comment>
- <comment xml:lang="ru">необработанное изображение Panasonic RAW 2</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Panasonic raw2</comment>
<comment xml:lang="sk">Surový obrázok Panasonic raw2</comment>
<comment xml:lang="sl">Slikovna datoteka Panasonic raw2</comment>
<comment xml:lang="sr">ПанаÑоник Ñирова2 Ñлика</comment>
<comment xml:lang="sv">Panasonic raw2-bild</comment>
<comment xml:lang="tr">Panasonic raw2 görüntüsü</comment>
<comment xml:lang="uk">Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ñƒ raw2 Panasonic</comment>
- <comment xml:lang="zh_CN">Panasonic raw2 图åƒ</comment>
+ <comment xml:lang="zh_CN">æ¾ä¸‹ raw2 图åƒ</comment>
<comment xml:lang="zh_TW">Panasonic raw2 å½±åƒ</comment>
<sub-class-of type="image/x-dcraw"/>
<magic priority="50">
@@ -25826,6 +26670,7 @@
<match value="IIU\x00\x18\x00\x00\x00" type="string" offset="0"/>
</magic>
<glob pattern="*.rw2"/>
+ <alias type="image/x-panasonic-raw2"/>
</mime-type>
<mime-type type="image/x-pentax-pef">
<comment>Pentax PEF raw image</comment>
@@ -25864,7 +26709,7 @@
<comment xml:lang="pt">imagem em bruto Pentax PEF</comment>
<comment xml:lang="pt_BR">Imagem bruta PEF da Pentax</comment>
<comment xml:lang="ro">Imagine brută Pentax PEF</comment>
- <comment xml:lang="ru">необработанное изображение Pentax PEF</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Pentax PEF</comment>
<comment xml:lang="sk">Surový obrázok Pentax PEF</comment>
<comment xml:lang="sl">Surova slikovna datoteka Pentax PEF</comment>
<comment xml:lang="sq">Figurë raw Pentax PEF</comment>
@@ -25873,7 +26718,7 @@
<comment xml:lang="tr">Pentax PEF ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив PEF Pentax</comment>
<comment xml:lang="vi">Ảnh thô Pentax PEF</comment>
- <comment xml:lang="zh_CN">Pentax PEF 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">宾得 PEF 原始图åƒ</comment>
<comment xml:lang="zh_TW">Pentax PEF 原生影åƒ</comment>
<acronym>PEF</acronym>
<expanded-acronym>Pentax Electronic Format</expanded-acronym>
@@ -25918,7 +26763,7 @@
<comment xml:lang="pt">imagem em bruto Sigma X3F</comment>
<comment xml:lang="pt_BR">Imagem bruta X3F da Sigma</comment>
<comment xml:lang="ro">Imagine brută Sigma X3F</comment>
- <comment xml:lang="ru">необработанное изображение Sigma X3F</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Sigma X3F</comment>
<comment xml:lang="sk">Surový obrázok Sigma X3F</comment>
<comment xml:lang="sl">Surova slikovna datoteka Sigma X3F</comment>
<comment xml:lang="sq">Fifurë raw Sigma X3F</comment>
@@ -25927,7 +26772,7 @@
<comment xml:lang="tr">Sigma X3F ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив X3F Sigma</comment>
<comment xml:lang="vi">Ảnh thô Sigma X3F</comment>
- <comment xml:lang="zh_CN">Sigma X3F 原始图åƒ</comment>
+ <comment xml:lang="zh_CN">适马 X3F 原始图åƒ</comment>
<comment xml:lang="zh_TW">Sigma X3F 原生影åƒ</comment>
<acronym>X3F</acronym>
<expanded-acronym>X3 Foveon</expanded-acronym>
@@ -25978,7 +26823,7 @@
<comment xml:lang="pt">imagem em bruto Sony SRF</comment>
<comment xml:lang="pt_BR">Imagem bruta SRF da Sony</comment>
<comment xml:lang="ro">Imagine brută Sony SRF</comment>
- <comment xml:lang="ru">необработанное изображение Sony SRF</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Sony SRF</comment>
<comment xml:lang="sk">Surový obrázok Sony SRF</comment>
<comment xml:lang="sl">Surova slikovna datoteka Sony SRF</comment>
<comment xml:lang="sq">Figurë raw Sony SRF</comment>
@@ -25987,7 +26832,7 @@
<comment xml:lang="tr">Sony SRF ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив SRF Sony</comment>
<comment xml:lang="vi">Ảnh thô Sony SRF</comment>
- <comment xml:lang="zh_CN">Sony SRF 原始映åƒ</comment>
+ <comment xml:lang="zh_CN">索尼 SRF 原始映åƒ</comment>
<comment xml:lang="zh_TW">Sony SRF 原生影åƒ</comment>
<acronym>SRF</acronym>
<expanded-acronym>Sony Raw Format</expanded-acronym>
@@ -26032,7 +26877,7 @@
<comment xml:lang="pt">imagem em bruto Sony SR2</comment>
<comment xml:lang="pt_BR">Imagem bruta SR2 da Sony</comment>
<comment xml:lang="ro">Imagine brută Sony SR2</comment>
- <comment xml:lang="ru">необработанное изображение Sony SR2</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Sony SR2</comment>
<comment xml:lang="sk">Surový obrázok Sony SR2</comment>
<comment xml:lang="sl">Surova slikovna datoteka Sony SR2</comment>
<comment xml:lang="sq">Figurë raw Sony SR2</comment>
@@ -26041,7 +26886,7 @@
<comment xml:lang="tr">Sony SR2 ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив SR2 Sony</comment>
<comment xml:lang="vi">Ảnh thô Sony SR2</comment>
- <comment xml:lang="zh_CN">Sony SR2 原始映åƒ</comment>
+ <comment xml:lang="zh_CN">索尼 SR2 原始映åƒ</comment>
<comment xml:lang="zh_TW">Sony SR2 原生影åƒ</comment>
<acronym>SR2</acronym>
<expanded-acronym>Sony Raw format 2</expanded-acronym>
@@ -26086,7 +26931,7 @@
<comment xml:lang="pt">imagem em bruto Sony ARW</comment>
<comment xml:lang="pt_BR">Imagem bruta ARW da Sony</comment>
<comment xml:lang="ro">Imagine brută Sony ARW</comment>
- <comment xml:lang="ru">необработанное изображение Sony ARW</comment>
+ <comment xml:lang="ru">Ðеобработанное изображение Sony ARW</comment>
<comment xml:lang="sk">Surový obrázok Sony ARW</comment>
<comment xml:lang="sl">Surova slikovna datoteka Sony ARW</comment>
<comment xml:lang="sq">Figurë raw Sony ARW</comment>
@@ -26095,7 +26940,7 @@
<comment xml:lang="tr">Sony ARW ham görüntüsü</comment>
<comment xml:lang="uk">цифровий негатив ARW Sony</comment>
<comment xml:lang="vi">Ảnh thô Sony ARW</comment>
- <comment xml:lang="zh_CN">Sony ARW 原始映åƒ</comment>
+ <comment xml:lang="zh_CN">索尼 ARW 原始映åƒ</comment>
<comment xml:lang="zh_TW">Sony ARW 原生影åƒ</comment>
<acronym>ARW</acronym>
<expanded-acronym>Alpha Raw format</expanded-acronym>
@@ -26144,7 +26989,7 @@
<comment xml:lang="pt">imagem PNG</comment>
<comment xml:lang="pt_BR">Imagem PNG</comment>
<comment xml:lang="ro">Imagine PNG</comment>
- <comment xml:lang="ru">изображение PNG</comment>
+ <comment xml:lang="ru">Изображение PNG</comment>
<comment xml:lang="sk">Obrázok PNG</comment>
<comment xml:lang="sl">Slikovna datoteka PNG</comment>
<comment xml:lang="sq">Figurë PNG</comment>
@@ -26175,7 +27020,7 @@
<comment xml:lang="eu">'Run Lenght Encoded' bitmap irudia</comment>
<comment xml:lang="fi">RLE-koodattu bittikartta</comment>
<comment xml:lang="fr">image matricielle Run Length Encoded</comment>
- <comment xml:lang="ga">íomhá mhapa giotáin Run Length Encoded</comment>
+ <comment xml:lang="ga">íomhá ghiotánmhapach ionchódaithe fad reatha</comment>
<comment xml:lang="gl">mapa de bits con codificación do tamaño durante a execución</comment>
<comment xml:lang="he">מקודד מפת סיביות של Run Length</comment>
<comment xml:lang="hr">Run Length Encoded bitmap slika</comment>
@@ -26196,7 +27041,7 @@
<comment xml:lang="pt">mapa de bitas Run Length Encoded</comment>
<comment xml:lang="pt_BR">Classe de comprimento imagem bitmap codificada</comment>
<comment xml:lang="ro">Imagine bitmap codată RLE</comment>
- <comment xml:lang="ru">раÑтровое изображение (Ñжатое RLE)</comment>
+ <comment xml:lang="ru">РаÑтровое изображение, Ñжатое RLE</comment>
<comment xml:lang="sk">Bitmapový obrázok Run Length Encoded</comment>
<comment xml:lang="sl">Zaporedno kodirana bitna slika (RLE)</comment>
<comment xml:lang="sq">Figurë bitmap RLE (Run Length Encoded)</comment>
@@ -26247,7 +27092,7 @@
<comment xml:lang="pt">imagem SVG</comment>
<comment xml:lang="pt_BR">Imagem SVG</comment>
<comment xml:lang="ro">Imagine SVG</comment>
- <comment xml:lang="ru">изображение SVG</comment>
+ <comment xml:lang="ru">Изображение SVG</comment>
<comment xml:lang="sk">Obrázok SVG</comment>
<comment xml:lang="sl">Slikovna vektorska datoteka SVG</comment>
<comment xml:lang="sq">Figurë SVG</comment>
@@ -26287,7 +27132,7 @@
<comment xml:lang="ga">íomhá SVG comhbhrúite</comment>
<comment xml:lang="gl">imaxe SVG comprimida</comment>
<comment xml:lang="he">תמונת SVG מכווצת</comment>
- <comment xml:lang="hr">komprimirana SVG slika</comment>
+ <comment xml:lang="hr">Sažeta SVG slika</comment>
<comment xml:lang="hu">tömörített SVG kép</comment>
<comment xml:lang="ia">Imagine SVG comprimite</comment>
<comment xml:lang="id">Citra SVG terkompresi</comment>
@@ -26305,7 +27150,7 @@
<comment xml:lang="pt">imagem SVG comprimida</comment>
<comment xml:lang="pt_BR">Imagem SVG compactada</comment>
<comment xml:lang="ro">imagine comprimată SVG</comment>
- <comment xml:lang="ru">Ñжатое изображение SVG</comment>
+ <comment xml:lang="ru">Сжатое изображение SVG</comment>
<comment xml:lang="sk">Komprimovaný obrázok SVG</comment>
<comment xml:lang="sl">Slikovna datoteka SVG (stisnjena)</comment>
<comment xml:lang="sq">Figurë SVG e kompresuar</comment>
@@ -26360,7 +27205,7 @@
<comment xml:lang="pt">imagem TIFF</comment>
<comment xml:lang="pt_BR">Imagem TIFF</comment>
<comment xml:lang="ro">Imagine TIFF</comment>
- <comment xml:lang="ru">изображение TIFF</comment>
+ <comment xml:lang="ru">Изображение TIFF</comment>
<comment xml:lang="sk">Obrázok TIFF</comment>
<comment xml:lang="sl">Slikovna datoteka TIFF</comment>
<comment xml:lang="sq">Figurë TIFF</comment>
@@ -26389,9 +27234,9 @@
<comment xml:lang="el">Πολυσέλιδη εικόνα TIFF</comment>
<comment xml:lang="en_GB">Multi-page TIFF image</comment>
<comment xml:lang="es">imagen TIFF de varias páginas</comment>
- <comment xml:lang="eu">Orri anitzeko TIFF irudia</comment>
<comment xml:lang="fi">Monisivuinen TIFF-kuva</comment>
<comment xml:lang="fr">Image TIFF multi-page</comment>
+ <comment xml:lang="ga">íomhá il-leathanach TIFF</comment>
<comment xml:lang="gl">Imaxe TIFF multipáxina</comment>
<comment xml:lang="he">תמונת TIFF ×¢× ×¨×™×‘×•×™ עמודי×</comment>
<comment xml:lang="hr">Višestrana TIFF slika</comment>
@@ -26425,7 +27270,7 @@
<comment xml:lang="be@latin">Vyjava AutoCAD</comment>
<comment xml:lang="bg">Изображение — AutoCAD</comment>
<comment xml:lang="ca">imatge d'AutoCAD</comment>
- <comment xml:lang="cs">obrázek AutoCAD</comment>
+ <comment xml:lang="cs">výkres AutoCAD</comment>
<comment xml:lang="cy">Delwedd AutoCAD</comment>
<comment xml:lang="da">AutoCAD-billede</comment>
<comment xml:lang="de">AutoCAD-Bild</comment>
@@ -26460,7 +27305,7 @@
<comment xml:lang="pt">imagem AutoCAD</comment>
<comment xml:lang="pt_BR">Imagem do AutoCAD</comment>
<comment xml:lang="ro">Imagine AutoCAD</comment>
- <comment xml:lang="ru">изображение AutoCAD</comment>
+ <comment xml:lang="ru">Изображение AutoCAD</comment>
<comment xml:lang="sk">Obrázok AutoCAD</comment>
<comment xml:lang="sl">Slikovna datoteka AutoCAD</comment>
<comment xml:lang="sq">Figurë AutoCAD</comment>
@@ -26490,7 +27335,7 @@
<comment xml:lang="fi">DXF-vektorikuva</comment>
<comment xml:lang="fo">DXF vektormynd</comment>
<comment xml:lang="fr">image vectorielle DXF</comment>
- <comment xml:lang="ga">íomhá veicteoir DXF</comment>
+ <comment xml:lang="ga">íomhá veicteoireach DXF</comment>
<comment xml:lang="gl">imaxe de vector DXF</comment>
<comment xml:lang="he">תמונת DXF וקטורית</comment>
<comment xml:lang="hr">DXF vektorska slika</comment>
@@ -26513,7 +27358,7 @@
<comment xml:lang="pt">imagem de vectores DXF</comment>
<comment xml:lang="pt_BR">Imagem vetorial DXF</comment>
<comment xml:lang="ro">Imagine vectorială DXF</comment>
- <comment xml:lang="ru">векторное изображение DXF</comment>
+ <comment xml:lang="ru">Векторное изображение DXF</comment>
<comment xml:lang="sk">Vektorový obrázok DXF</comment>
<comment xml:lang="sl">Slikovna vektorska datoteka DXF</comment>
<comment xml:lang="sq">Figurë vektoriale DFX</comment>
@@ -26533,6 +27378,7 @@
<mime-type type="image/vnd.ms-modi">
<comment>Microsoft Document Imaging format</comment>
<comment xml:lang="ar">صيغة مستند تصوير مايكروسوÙت</comment>
+ <comment xml:lang="ast">Formatu d'imáxenes de Microsoft Document</comment>
<comment xml:lang="bg">Изображение — Microsoft Document Imaging</comment>
<comment xml:lang="ca">format Microsoft Document Imaging</comment>
<comment xml:lang="cs">formát Microsoft Document Imaging</comment>
@@ -26564,7 +27410,7 @@
<comment xml:lang="pt">formato Microsoft Document Imaging</comment>
<comment xml:lang="pt_BR">Formato do Microsoft Document Imaging</comment>
<comment xml:lang="ro">Format Microsoft Document Imaging</comment>
- <comment xml:lang="ru">формат Microsoft Document Imaging</comment>
+ <comment xml:lang="ru">Формат Microsoft Document Imaging</comment>
<comment xml:lang="sk">Formát Microsoft Document Imaging</comment>
<comment xml:lang="sl">Zapis Microsoft Document Imaging</comment>
<comment xml:lang="sr">Ð·Ð°Ð¿Ð¸Ñ Ñлика МајкроÑофтовог документа</comment>
@@ -26572,7 +27418,7 @@
<comment xml:lang="tr">Microsoft Belge Görüntüleme biçimi</comment>
<comment xml:lang="uk">формат Microsoft Document Imaging</comment>
<comment xml:lang="vi">Äịnh dạng tạo ảnh tài liệu Microsoft</comment>
- <comment xml:lang="zh_CN">Microsoft Document Imaging 扫æ图åƒ</comment>
+ <comment xml:lang="zh_CN">Microsoft Document Imaging æ ¼å¼</comment>
<comment xml:lang="zh_TW">微軟文件影åƒæ ¼å¼</comment>
<acronym>MDI</acronym>
<expanded-acronym>Microsoft Document Imaging</expanded-acronym>
@@ -26593,6 +27439,7 @@
<comment xml:lang="eu">WebP irudia</comment>
<comment xml:lang="fi">WebP-kuva</comment>
<comment xml:lang="fr">image WebP</comment>
+ <comment xml:lang="ga">íomhá WebP</comment>
<comment xml:lang="gl">Imaxe WebP</comment>
<comment xml:lang="he">תמונת WebP</comment>
<comment xml:lang="hr">WebP slika</comment>
@@ -26664,7 +27511,7 @@
<comment xml:lang="pt">imagem 3D Studio</comment>
<comment xml:lang="pt_BR">Imagem do 3D Studio</comment>
<comment xml:lang="ro">Imagine 3D Studio</comment>
- <comment xml:lang="ru">Ñцена 3D Studio</comment>
+ <comment xml:lang="ru">Сцена 3D Studio</comment>
<comment xml:lang="sk">Obrázok 3D Studio</comment>
<comment xml:lang="sl">Slikovna datoteka 3D Studio</comment>
<comment xml:lang="sq">Figurë 3D Studio</comment>
@@ -26717,7 +27564,7 @@
<comment xml:lang="pt">imagem Applix Graphics</comment>
<comment xml:lang="pt_BR">Imagem do Applix Graphics</comment>
<comment xml:lang="ro">Imagine Applix Graphics</comment>
- <comment xml:lang="ru">изображение Applix Graphics</comment>
+ <comment xml:lang="ru">Изображение Applix Graphics</comment>
<comment xml:lang="sk">Obrázok Applix Graphics</comment>
<comment xml:lang="sl">Slikovna datoteka Applix Graphics</comment>
<comment xml:lang="sq">Figurë Applix Graphics</comment>
@@ -26754,7 +27601,7 @@
<comment xml:lang="ga">íomhá EPS (comhbhrúite le bzip)</comment>
<comment xml:lang="gl">imaxe EPS (comprimida con bzip)</comment>
<comment xml:lang="he">תמונת EPS (מכווץ בbzip)</comment>
- <comment xml:lang="hr">EPS slika (komprimirana bzip-om)</comment>
+ <comment xml:lang="hr">EPS slika (bzip sažeta)</comment>
<comment xml:lang="hu">EPS kép (bzip-tömörítésű)</comment>
<comment xml:lang="ia">Imagine EPS (comprimite con bzip)</comment>
<comment xml:lang="id">Citra EPS (terkompresi bzip)</comment>
@@ -26773,7 +27620,7 @@
<comment xml:lang="pt">imagem EPS (compressão bzip)</comment>
<comment xml:lang="pt_BR">Imagem EPS (compactada com bzip)</comment>
<comment xml:lang="ro">Imagine EPS (compresie bzip)</comment>
- <comment xml:lang="ru">изображение EPS (Ñжатое bzip)</comment>
+ <comment xml:lang="ru">Изображение EPS (Ñжатое bzip)</comment>
<comment xml:lang="sk">Obrázok EPS (komprimovaný pomocou bzip)</comment>
<comment xml:lang="sl">Slikovna datoteka EPS (stisnjena z bzip)</comment>
<comment xml:lang="sq">Figurë EPS (e kompresuar me bzip)</comment>
@@ -26782,7 +27629,7 @@
<comment xml:lang="tr">EPS görüntüsü (bzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ EPS (ÑтиÑнене bzip)</comment>
<comment xml:lang="vi">Ảnh EPS (đã nén bzip)</comment>
- <comment xml:lang="zh_CN">EPS 图åƒ(bzip 压缩)</comment>
+ <comment xml:lang="zh_CN">EPS 图åƒï¼ˆbzip 压缩)</comment>
<comment xml:lang="zh_TW">EPS å½±åƒ (bzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/x-bzip"/>
<glob pattern="*.eps.bz2"/>
@@ -26831,7 +27678,7 @@
<comment xml:lang="pt">imagem raster CMU</comment>
<comment xml:lang="pt_BR">Imagem raster CMU</comment>
<comment xml:lang="ro">Imagine raster CMU</comment>
- <comment xml:lang="ru">раÑтровое изображение CMU</comment>
+ <comment xml:lang="ru">РаÑтровое изображение CMU</comment>
<comment xml:lang="sk">Rastrový obrázok CMU</comment>
<comment xml:lang="sl">Slikovna rastrska datoteka CMU</comment>
<comment xml:lang="sq">Figurë raster CMU</comment>
@@ -26840,7 +27687,7 @@
<comment xml:lang="tr">CMU tarama görüntüsü</comment>
<comment xml:lang="uk">раÑтрове Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ CMU</comment>
<comment xml:lang="vi">Ảnh mành CMU</comment>
- <comment xml:lang="zh_CN">CMU 矢é‡å›¾åƒ</comment>
+ <comment xml:lang="zh_CN">CMU 光栅图åƒ</comment>
<comment xml:lang="zh_TW">CMU raster å½±åƒ</comment>
<glob pattern="*.ras"/>
</mime-type>
@@ -26881,7 +27728,7 @@
<comment xml:lang="pt">imagem GIMP comprimida</comment>
<comment xml:lang="pt_BR">Imagem do GIMP compactada</comment>
<comment xml:lang="ro">imagine comprimată GIMP</comment>
- <comment xml:lang="ru">Ñжатое изображение GIMP</comment>
+ <comment xml:lang="ru">Сжатое изображение GIMP</comment>
<comment xml:lang="sk">Komprimovaný obrázok GIMP</comment>
<comment xml:lang="sl">Slikovna datoteka GIMP (stisnjena)</comment>
<comment xml:lang="sq">Figurë GIMP e kompresuar</comment>
@@ -26934,7 +27781,7 @@
<comment xml:lang="pt">imagem DICOM</comment>
<comment xml:lang="pt_BR">Imagem DICOM</comment>
<comment xml:lang="ro">Imagine DICOM</comment>
- <comment xml:lang="ru">изображение DICOM</comment>
+ <comment xml:lang="ru">Изображение DICOM</comment>
<comment xml:lang="sk">Obrázok DICOM</comment>
<comment xml:lang="sl">Slikovna datoteka DICOM</comment>
<comment xml:lang="sq">Figurë DICOM</comment>
@@ -26957,6 +27804,7 @@
<mime-type type="application/x-docbook+xml">
<comment>DocBook document</comment>
<comment xml:lang="ar">مستند DocBook</comment>
+ <comment xml:lang="ast">Documentu DocBook</comment>
<comment xml:lang="be@latin">Dakument DocBook</comment>
<comment xml:lang="bg">Документ — DocBook</comment>
<comment xml:lang="ca">document DocBook</comment>
@@ -26993,7 +27841,7 @@
<comment xml:lang="pt">documento DocBook</comment>
<comment xml:lang="pt_BR">Documento DocBook</comment>
<comment xml:lang="ro">Document DocBook</comment>
- <comment xml:lang="ru">документ DocBook</comment>
+ <comment xml:lang="ru">Документ DocBook</comment>
<comment xml:lang="sk">Dokument DocBook</comment>
<comment xml:lang="sl">Dokument DocBook</comment>
<comment xml:lang="sq">Dokument DocBook</comment>
@@ -27056,7 +27904,7 @@
<comment xml:lang="pt">imagem DIB</comment>
<comment xml:lang="pt_BR">Imagem DIB</comment>
<comment xml:lang="ro">Imagine DIB</comment>
- <comment xml:lang="ru">изображение DIB</comment>
+ <comment xml:lang="ru">Изображение DIB</comment>
<comment xml:lang="sk">Obrázok DIB</comment>
<comment xml:lang="sl">Slikovna datoteka DIB</comment>
<comment xml:lang="sq">Figurë DIB</comment>
@@ -27113,7 +27961,7 @@
<comment xml:lang="pt">imagem DjVu</comment>
<comment xml:lang="pt_BR">Imagem DjVu</comment>
<comment xml:lang="ro">Imagine DjVu</comment>
- <comment xml:lang="ru">изображение DjVu</comment>
+ <comment xml:lang="ru">Изображение DjVu</comment>
<comment xml:lang="sk">Obrázok DjVu</comment>
<comment xml:lang="sl">Slikovna datoteka DjVu</comment>
<comment xml:lang="sq">Figurë DjVu</comment>
@@ -27126,7 +27974,7 @@
<comment xml:lang="zh_TW">DjVu å½±åƒ</comment>
<alias type="image/x-djvu"/>
<alias type="image/x.djvu"/>
- <magic priority="50">
+ <magic priority="80">
<match value="AT&amp;TFORM" type="string" offset="0">
<match value="DJVU" type="string" offset="12"/>
</match>
@@ -27139,6 +27987,7 @@
</mime-type>
<mime-type type="image/vnd.djvu+multipage">
<comment>DjVu document</comment>
+ <comment xml:lang="ast">Documentu DjVu</comment>
<comment xml:lang="ca">document DjVu</comment>
<comment xml:lang="cs">dokument DjVu</comment>
<comment xml:lang="da">DjVu-dokument</comment>
@@ -27149,6 +27998,7 @@
<comment xml:lang="eu">DjVu dokumentua</comment>
<comment xml:lang="fi">DjVu-asiakirja</comment>
<comment xml:lang="fr">document DjVu</comment>
+ <comment xml:lang="ga">cáipéis DjVu</comment>
<comment xml:lang="he">מסמך DjVu</comment>
<comment xml:lang="hr">DjVu dokument</comment>
<comment xml:lang="hu">DjVu dokumentum</comment>
@@ -27161,7 +28011,7 @@
<comment xml:lang="pl">Dokument DjVu</comment>
<comment xml:lang="pt">documento DjVu</comment>
<comment xml:lang="pt_BR">Documento DjVu</comment>
- <comment xml:lang="ru">документ DjVu</comment>
+ <comment xml:lang="ru">Документ DjVu</comment>
<comment xml:lang="sk">Dokument DjVu</comment>
<comment xml:lang="sr">ДјВу документ</comment>
<comment xml:lang="sv">DjVu-dokument</comment>
@@ -27170,7 +28020,7 @@
<comment xml:lang="zh_CN">DjVu 文档</comment>
<comment xml:lang="zh_TW">DjVu 文件</comment>
<generic-icon name="x-office-document"/>
- <magic priority="50">
+ <magic priority="80">
<match value="AT&amp;TFORM" type="string" offset="0">
<match value="DJVM" type="string" offset="12"/>
</match>
@@ -27221,7 +28071,7 @@
<comment xml:lang="pt">imagem DPX</comment>
<comment xml:lang="pt_BR">Imagem DPX</comment>
<comment xml:lang="ro">Imagine DPX</comment>
- <comment xml:lang="ru">изображение DPX</comment>
+ <comment xml:lang="ru">Изображение DPX</comment>
<comment xml:lang="sk">Obrázok DPX</comment>
<comment xml:lang="sl">Slikovna datoteka DPX</comment>
<comment xml:lang="sq">Figurë DPX</comment>
@@ -27277,7 +28127,7 @@
<comment xml:lang="pt">imagem EPS</comment>
<comment xml:lang="pt_BR">Imagem EPS</comment>
<comment xml:lang="ro">Imagine EPS</comment>
- <comment xml:lang="ru">изображение EPS</comment>
+ <comment xml:lang="ru">Изображение EPS</comment>
<comment xml:lang="sk">Obrázok EPS</comment>
<comment xml:lang="sl">Slikovna datoteka EPS</comment>
<comment xml:lang="sq">Figurë EPS</comment>
@@ -27307,6 +28157,7 @@
<mime-type type="image/fits">
<comment>FITS document</comment>
<comment xml:lang="ar">مستند FITS</comment>
+ <comment xml:lang="ast">Documentu FITS</comment>
<comment xml:lang="be@latin">Dakument FITS</comment>
<comment xml:lang="bg">Документ — FITS</comment>
<comment xml:lang="ca">document FITS</comment>
@@ -27343,7 +28194,7 @@
<comment xml:lang="pt">documento FITS</comment>
<comment xml:lang="pt_BR">Documento FITS</comment>
<comment xml:lang="ro">Document FITS</comment>
- <comment xml:lang="ru">документ FITS</comment>
+ <comment xml:lang="ru">Документ FITS</comment>
<comment xml:lang="sk">Dokument FITS</comment>
<comment xml:lang="sl">Dokument FITS</comment>
<comment xml:lang="sq">Dokument FITS</comment>
@@ -27401,7 +28252,7 @@
<comment xml:lang="pt">imagem FPX</comment>
<comment xml:lang="pt_BR">Imagem FPX</comment>
<comment xml:lang="ro">Imagine FPX</comment>
- <comment xml:lang="ru">изображение FPX</comment>
+ <comment xml:lang="ru">Изображение FPX</comment>
<comment xml:lang="sk">Obrázok FPX</comment>
<comment xml:lang="sl">Slikovna datoteka FPX</comment>
<comment xml:lang="sq">Figurë FPX</comment>
@@ -27437,7 +28288,7 @@
<comment xml:lang="ga">íomhá EPS (comhbhrúite le gzip)</comment>
<comment xml:lang="gl">imaxe EPS (comprimida con gzip)</comment>
<comment xml:lang="he">תמונת EPS (מכווץ ע״י gzip)</comment>
- <comment xml:lang="hr">EPS slika (komprimirana gzip-om)</comment>
+ <comment xml:lang="hr">EPS slika (gzip sažeta)</comment>
<comment xml:lang="hu">EPS kép (gzip-tömörítésű)</comment>
<comment xml:lang="ia">Imagine EPS (comprimite con gzip)</comment>
<comment xml:lang="id">Citra EPS (terkompresi gzip)</comment>
@@ -27456,7 +28307,7 @@
<comment xml:lang="pt">imagem EPS (compressão gzip)</comment>
<comment xml:lang="pt_BR">Imagem EPS (compactada com gzip)</comment>
<comment xml:lang="ro">Imagine EPS (compresie gzip)</comment>
- <comment xml:lang="ru">изображение EPS (Ñжатое gzip)</comment>
+ <comment xml:lang="ru">Изображение EPS (Ñжатое gzip)</comment>
<comment xml:lang="sk">Obrázok EPS (komprimovaný pomocou gzip)</comment>
<comment xml:lang="sl">Slikovna datoteka EPS (stisnjena z gzip)</comment>
<comment xml:lang="sq">Figurë EPS (e kompresuar me gzip)</comment>
@@ -27465,7 +28316,7 @@
<comment xml:lang="tr">EPS görüntüsü (gzip ile sıkıştırılmış)</comment>
<comment xml:lang="uk">Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ EPS (ÑтиÑнене gzip)</comment>
<comment xml:lang="vi">Ảnh EPS (đã nén gzip)</comment>
- <comment xml:lang="zh_CN">EPS 图åƒ(gzip 压缩)</comment>
+ <comment xml:lang="zh_CN">EPS 图åƒï¼ˆgzip 压缩)</comment>
<comment xml:lang="zh_TW">EPS å½±åƒ (gzip æ ¼å¼å£“縮)</comment>
<sub-class-of type="application/gzip"/>
<glob pattern="*.eps.gz"/>
@@ -27484,6 +28335,7 @@
<comment xml:lang="eu">Windows ikonoa</comment>
<comment xml:lang="fi">Windows-kuvake</comment>
<comment xml:lang="fr">icône Windows</comment>
+ <comment xml:lang="ga">deilbhín Windows</comment>
<comment xml:lang="he">סמל של Windows</comment>
<comment xml:lang="hr">Windows ikona</comment>
<comment xml:lang="hu">Windows ikon</comment>
@@ -27496,7 +28348,7 @@
<comment xml:lang="pl">Ikona Windows</comment>
<comment xml:lang="pt">ícone Windows</comment>
<comment xml:lang="pt_BR">Ãcone do Windows</comment>
- <comment xml:lang="ru">значок Windows</comment>
+ <comment xml:lang="ru">Значок Windows</comment>
<comment xml:lang="sk">Ikona Windows</comment>
<comment xml:lang="sl">Ikona Windows</comment>
<comment xml:lang="sr">Иконица Виндоуза</comment>
@@ -27557,7 +28409,7 @@
<comment xml:lang="pt">ćone MacOS X</comment>
<comment xml:lang="pt_BR">Ãcone do MacOS X</comment>
<comment xml:lang="ro">Iconiță MacOS X</comment>
- <comment xml:lang="ru">значок MacOS X</comment>
+ <comment xml:lang="ru">Значок MacOS X</comment>
<comment xml:lang="sk">Ikona MacOS X</comment>
<comment xml:lang="sl">Datoteka ikone MacOS X</comment>
<comment xml:lang="sq">Ikonë MacOS X</comment>
@@ -27614,7 +28466,7 @@
<comment xml:lang="pt">imagem ILBM</comment>
<comment xml:lang="pt_BR">Imagem ILBM</comment>
<comment xml:lang="ro">Imagine ILBM</comment>
- <comment xml:lang="ru">изображение ILBM</comment>
+ <comment xml:lang="ru">Изображение ILBM</comment>
<comment xml:lang="sk">Obrázok ILMB</comment>
<comment xml:lang="sl">Slikovna datoteka ILBM</comment>
<comment xml:lang="sq">Figurë ILBM</comment>
@@ -27678,7 +28530,7 @@
<comment xml:lang="pt">imagem JNG</comment>
<comment xml:lang="pt_BR">Imagem JNG</comment>
<comment xml:lang="ro">Imagine JNG</comment>
- <comment xml:lang="ru">изображение JNG</comment>
+ <comment xml:lang="ru">Изображение JNG</comment>
<comment xml:lang="sk">Obrázok JNG</comment>
<comment xml:lang="sl">Slikovna datoteka JNG</comment>
<comment xml:lang="sq">Figurë JNG</comment>
@@ -27734,7 +28586,7 @@
<comment xml:lang="pt">Objecto LightWave</comment>
<comment xml:lang="pt_BR">Objeto LightWave</comment>
<comment xml:lang="ro">Obiect LightWave</comment>
- <comment xml:lang="ru">объект LightWave</comment>
+ <comment xml:lang="ru">Объект LightWave</comment>
<comment xml:lang="sk">Objekt LightWave</comment>
<comment xml:lang="sl">Datoteka predmeta LightWave</comment>
<comment xml:lang="sq">Objekt LightWave</comment>
@@ -27789,7 +28641,7 @@
<comment xml:lang="pt">cenário LightWave</comment>
<comment xml:lang="pt_BR">Cena LightWave</comment>
<comment xml:lang="ro">Scenă LightWave</comment>
- <comment xml:lang="ru">Ñцена LightWave</comment>
+ <comment xml:lang="ru">Сцена LightWave</comment>
<comment xml:lang="sk">Scéna LightWave</comment>
<comment xml:lang="sl">Datoteka scene LightWave</comment>
<comment xml:lang="sq">Skenë LightWave</comment>
@@ -27818,7 +28670,7 @@
<comment xml:lang="fi">MacPaint-bittikartta</comment>
<comment xml:lang="fo">MacPaint Bitmap mynd</comment>
<comment xml:lang="fr">image matricielle MacPaint</comment>
- <comment xml:lang="ga">íomhá MacPaint Bitmap</comment>
+ <comment xml:lang="ga">íomhá ghiotánmhapach MacPaint</comment>
<comment xml:lang="gl">imaxe de mapa de bits MacPaint</comment>
<comment xml:lang="he">תמונת מפת-סיביות של MacPaint</comment>
<comment xml:lang="hr">MacPaint Bitmap slika</comment>
@@ -27839,7 +28691,7 @@
<comment xml:lang="pt">imagem MacPaint Bitmap</comment>
<comment xml:lang="pt_BR">Imagem de bitmap do MacPaint</comment>
<comment xml:lang="ro">Imagine MacPaint Bitmap</comment>
- <comment xml:lang="ru">раÑтровое изображение MacPaint</comment>
+ <comment xml:lang="ru">РаÑтровое изображение MacPaint</comment>
<comment xml:lang="sk">Obrázok MacPaint Bitmap</comment>
<comment xml:lang="sl">Slikovna bitna datoteka MacPaint</comment>
<comment xml:lang="sq">Figurë BitMap MacPaint</comment>
@@ -27889,7 +28741,7 @@
<comment xml:lang="pt">desenho Office</comment>
<comment xml:lang="pt_BR">Desenho do Office</comment>
<comment xml:lang="ro">Desen Office</comment>
- <comment xml:lang="ru">изображение Office</comment>
+ <comment xml:lang="ru">РиÑунок Office</comment>
<comment xml:lang="sk">Kresba Office</comment>
<comment xml:lang="sl">Datoteka risbe Office</comment>
<comment xml:lang="sq">Vizatim Office</comment>
@@ -27898,7 +28750,7 @@
<comment xml:lang="tr">Ofis çizimi</comment>
<comment xml:lang="uk">малюнок Office</comment>
<comment xml:lang="vi">Bản vẽ Office</comment>
- <comment xml:lang="zh_CN">Microsoft Office 绘图</comment>
+ <comment xml:lang="zh_CN">Office 绘图</comment>
<comment xml:lang="zh_TW">Office 繪圖</comment>
<glob pattern="*.msod"/>
</mime-type>
@@ -27940,7 +28792,7 @@
<comment xml:lang="pt">imagem NIFF</comment>
<comment xml:lang="pt_BR">Imagem NIFF</comment>
<comment xml:lang="ro">Imagine NIF</comment>
- <comment xml:lang="ru">изображение NIFF</comment>
+ <comment xml:lang="ru">Изображение NIFF</comment>
<comment xml:lang="sk">Obrázok NIFF</comment>
<comment xml:lang="sl">Slikovna datoteka NIFF</comment>
<comment xml:lang="sq">Figurë NIFF</comment>
@@ -27993,7 +28845,7 @@
<comment xml:lang="pt">imagem PCX</comment>
<comment xml:lang="pt_BR">Imagem PCX</comment>
<comment xml:lang="ro">Imagine PCX</comment>
- <comment xml:lang="ru">изображение PCX</comment>
+ <comment xml:lang="ru">Изображение PCX</comment>
<comment xml:lang="sk">Obrázok PCX</comment>
<comment xml:lang="sl">Slikovna datoteka PCX</comment>
<comment xml:lang="sq">Figurë PCX</comment>
@@ -28056,7 +28908,7 @@
<comment xml:lang="pt">imagem PCD</comment>
<comment xml:lang="pt_BR">Imagem PCD</comment>
<comment xml:lang="ro">Imagine PCD</comment>
- <comment xml:lang="ru">изображение PCD</comment>
+ <comment xml:lang="ru">Изображение PCD</comment>
<comment xml:lang="sk">Obrázok PCD</comment>
<comment xml:lang="sl">Slikovna datoteka PCD</comment>
<comment xml:lang="sq">Figurë PCD</comment>
@@ -28112,7 +28964,7 @@
<comment xml:lang="pt">imagem PNM</comment>
<comment xml:lang="pt_BR">Imagem PNM</comment>
<comment xml:lang="ro">Imagine PNM</comment>
- <comment xml:lang="ru">изображение PNM</comment>
+ <comment xml:lang="ru">Изображение PNM</comment>
<comment xml:lang="sk">Obrázok PNM</comment>
<comment xml:lang="sl">Slikovna datoteka PNM</comment>
<comment xml:lang="sq">Figurë PNM</comment>
@@ -28165,7 +29017,7 @@
<comment xml:lang="pt">imagem PBM</comment>
<comment xml:lang="pt_BR">Imagem PBM</comment>
<comment xml:lang="ro">Imagine PBM</comment>
- <comment xml:lang="ru">изображение PBM</comment>
+ <comment xml:lang="ru">Изображение PBM</comment>
<comment xml:lang="sk">Obrázok PBM</comment>
<comment xml:lang="sl">Slikovna datoteka PBM</comment>
<comment xml:lang="sq">Figurë PBM</comment>
@@ -28234,7 +29086,7 @@
<comment xml:lang="pt">imagem PGM</comment>
<comment xml:lang="pt_BR">Imagem PGM</comment>
<comment xml:lang="ro">Imagine PGM</comment>
- <comment xml:lang="ru">изображение PGM</comment>
+ <comment xml:lang="ru">Изображение PGM</comment>
<comment xml:lang="sk">Obrázok PGM</comment>
<comment xml:lang="sl">Slikovna datoteka PGM</comment>
<comment xml:lang="sq">Figurë PGM</comment>
@@ -28303,7 +29155,7 @@
<comment xml:lang="pt">imagem PPM</comment>
<comment xml:lang="pt_BR">Imagem PPM</comment>
<comment xml:lang="ro">Imagine PPM</comment>
- <comment xml:lang="ru">изображение PPM</comment>
+ <comment xml:lang="ru">Изображение PPM</comment>
<comment xml:lang="sk">Obrázok PPM</comment>
<comment xml:lang="sl">Slikovna datoteka PPM</comment>
<comment xml:lang="sq">Figurë PPM</comment>
@@ -28369,7 +29221,7 @@
<comment xml:lang="pt">imagem Photoshop</comment>
<comment xml:lang="pt_BR">Imagem do Photoshop</comment>
<comment xml:lang="ro">Imagine Photoshop</comment>
- <comment xml:lang="ru">изображение Photoshop</comment>
+ <comment xml:lang="ru">Изображение Photoshop</comment>
<comment xml:lang="sk">Obrázok Photoshop</comment>
<comment xml:lang="sl">Slikovna datoteka Photoshop</comment>
<comment xml:lang="sr">Фотошоп Ñлика</comment>
@@ -28431,7 +29283,7 @@
<comment xml:lang="pt">imagem RGB</comment>
<comment xml:lang="pt_BR">Imagem RGB</comment>
<comment xml:lang="ro">Imagine RGB</comment>
- <comment xml:lang="ru">изображение RGB</comment>
+ <comment xml:lang="ru">Изображение RGB</comment>
<comment xml:lang="sk">Obrázok RGB</comment>
<comment xml:lang="sl">Slikovna datoteka RGB</comment>
<comment xml:lang="sq">Figurë RGB</comment>
@@ -28482,7 +29334,7 @@
<comment xml:lang="pt">imagem SGI</comment>
<comment xml:lang="pt_BR">Imagem SGI</comment>
<comment xml:lang="ro">Imagine SGI</comment>
- <comment xml:lang="ru">изображение SGI</comment>
+ <comment xml:lang="ru">Изображение SGI</comment>
<comment xml:lang="sk">Obrázok SGI</comment>
<comment xml:lang="sl">Slikovna datoteka SGI</comment>
<comment xml:lang="sq">Figurë SGI</comment>
@@ -28532,7 +29384,7 @@
<comment xml:lang="pt">imagem raster Sun</comment>
<comment xml:lang="pt_BR">Imagem raster da Sun</comment>
<comment xml:lang="ro">Imagine rasterizată Sun</comment>
- <comment xml:lang="ru">раÑтровое изображение Sun</comment>
+ <comment xml:lang="ru">РаÑтровое изображение Sun</comment>
<comment xml:lang="sk">Rastrový obrázok Sun</comment>
<comment xml:lang="sl">Slikovna rastrska datoteka Sun</comment>
<comment xml:lang="sq">Figurë raster Sun</comment>
@@ -28586,7 +29438,7 @@
<comment xml:lang="pt">imagem TGA</comment>
<comment xml:lang="pt_BR">Imagem TGA</comment>
<comment xml:lang="ro">Imagine TGA</comment>
- <comment xml:lang="ru">изображение TGA</comment>
+ <comment xml:lang="ru">Изображение TGA</comment>
<comment xml:lang="sk">Obrázok TGA</comment>
<comment xml:lang="sl">Slikovna datoteka TGA</comment>
<comment xml:lang="sq">Figurë TGA</comment>
@@ -28614,8 +29466,8 @@
<match value="0x20" type="byte" offset="16"/>
</match>
</magic>
- <glob pattern="*.icb"/>
<glob pattern="*.tga"/>
+ <glob pattern="*.icb"/>
<glob pattern="*.tpic"/>
<glob pattern="*.vda"/>
<glob pattern="*.vst"/>
@@ -28641,7 +29493,7 @@
<comment xml:lang="ga">cúrsóir Windows</comment>
<comment xml:lang="gl">Cursor de Windows</comment>
<comment xml:lang="he">סמן של Windows</comment>
- <comment xml:lang="hr">Windows kursor</comment>
+ <comment xml:lang="hr">Windows pokazivaÄ</comment>
<comment xml:lang="hu">Windows-kurzor</comment>
<comment xml:lang="ia">Cursor pro Windows</comment>
<comment xml:lang="id">Kursor Windows</comment>
@@ -28660,7 +29512,7 @@
<comment xml:lang="pt">cursor Windows</comment>
<comment xml:lang="pt_BR">Cursor do Windows</comment>
<comment xml:lang="ro">Cursor Windows</comment>
- <comment xml:lang="ru">курÑор Windows</comment>
+ <comment xml:lang="ru">КурÑор Windows</comment>
<comment xml:lang="sk">Kurzor Windows</comment>
<comment xml:lang="sl">Datoteka kazalke Windows</comment>
<comment xml:lang="sq">Kursor Windows</comment>
@@ -28694,10 +29546,10 @@
<comment xml:lang="fi">animoitu Windows-osoitin</comment>
<comment xml:lang="fo">Windows livindaigjørdur vísi</comment>
<comment xml:lang="fr">curseur animé Windows</comment>
- <comment xml:lang="ga">cúrsóir beo Windows</comment>
+ <comment xml:lang="ga">cúrsóir beoite Windows</comment>
<comment xml:lang="gl">Cursor animado de Windows</comment>
<comment xml:lang="he">סמן מונפש של Windows</comment>
- <comment xml:lang="hr">Windows animirani kursor</comment>
+ <comment xml:lang="hr">Windows animirani pokazivaÄ</comment>
<comment xml:lang="hu">Windows animált kurzor</comment>
<comment xml:lang="ia">Cursor animate pro Windows</comment>
<comment xml:lang="id">Kursor animasi Windows</comment>
@@ -28714,7 +29566,7 @@
<comment xml:lang="pt">cursor animado Windows</comment>
<comment xml:lang="pt_BR">Cursor animado do Windows</comment>
<comment xml:lang="ro">Cursor animat Windows</comment>
- <comment xml:lang="ru">анимированный курÑор Windows</comment>
+ <comment xml:lang="ru">Ðнимированный курÑор Windows</comment>
<comment xml:lang="sk">Animovaný kurzor Windows</comment>
<comment xml:lang="sl">Datoteka animirane kazalke Windows</comment>
<comment xml:lang="sq">Kursor i animuar Windows</comment>
@@ -28723,7 +29575,7 @@
<comment xml:lang="tr">Windows canlandırmalı imleci</comment>
<comment xml:lang="uk">анімований курÑор Windows</comment>
<comment xml:lang="vi">Con chạy hoạt há»a Windows</comment>
- <comment xml:lang="zh_CN">Windows 动画光标</comment>
+ <comment xml:lang="zh_CN">Windows 动æ€å…‰æ ‡</comment>
<comment xml:lang="zh_TW">Windows 滑鼠動畫游標</comment>
<magic priority="50">
<match value="RIFF" type="string" offset="0">
@@ -28771,7 +29623,7 @@
<comment xml:lang="pt">imagem EMF</comment>
<comment xml:lang="pt_BR">Imagem EMF</comment>
<comment xml:lang="ro">Imagine EMF</comment>
- <comment xml:lang="ru">изображение EMF</comment>
+ <comment xml:lang="ru">Изображение EMF</comment>
<comment xml:lang="sk">Obrázok EMF</comment>
<comment xml:lang="sl">Slikovna datoteka EMF</comment>
<comment xml:lang="sq">Figurë EMF</comment>
@@ -28836,7 +29688,7 @@
<comment xml:lang="pt">imagem WMF</comment>
<comment xml:lang="pt_BR">Imagem WMF</comment>
<comment xml:lang="ro">Imagine WMF</comment>
- <comment xml:lang="ru">изображение WMF</comment>
+ <comment xml:lang="ru">Изображение WMF</comment>
<comment xml:lang="sk">Obrázok WMF</comment>
<comment xml:lang="sl">Slikovna datoteka WMF</comment>
<comment xml:lang="sq">Figurë WMF</comment>
@@ -28907,7 +29759,7 @@
<comment xml:lang="pt">imagem XBM</comment>
<comment xml:lang="pt_BR">Imagem XBM</comment>
<comment xml:lang="ro">Imagine XBM</comment>
- <comment xml:lang="ru">изображение XBM</comment>
+ <comment xml:lang="ru">Изображение XBM</comment>
<comment xml:lang="sk">Obrázok XBM</comment>
<comment xml:lang="sl">Slikovna datoteka XBM</comment>
<comment xml:lang="sq">Figurë XBM</comment>
@@ -28962,7 +29814,7 @@
<comment xml:lang="pt">imagem GIMP</comment>
<comment xml:lang="pt_BR">Imagem do GIMP</comment>
<comment xml:lang="ro">Imagine GIMP</comment>
- <comment xml:lang="ru">изображение GIMP</comment>
+ <comment xml:lang="ru">Изображение GIMP</comment>
<comment xml:lang="sk">Obrázok GIMP</comment>
<comment xml:lang="sl">Slikovna datoteka GIMP</comment>
<comment xml:lang="sq">Figurë GIMP</comment>
@@ -28979,6 +29831,80 @@
<match value="gimp xcf v" type="string" offset="0"/>
</magic>
</mime-type>
+ <mime-type type="image/x-gimp-gbr">
+ <comment>GIMP brush</comment>
+ <comment xml:lang="ca">pinzell de GIMP</comment>
+ <comment xml:lang="cs">štětec GIMP</comment>
+ <comment xml:lang="de">GIMP-Pinsel</comment>
+ <comment xml:lang="en_GB">GIMP brush</comment>
+ <comment xml:lang="es">pincel del GIMP</comment>
+ <comment xml:lang="hr">GIMP kist</comment>
+ <comment xml:lang="hu">GIMP ecset</comment>
+ <comment xml:lang="id">Kuas GIMP</comment>
+ <comment xml:lang="it">Pennello GIMP</comment>
+ <comment xml:lang="kk">GIMP боÑу жаққышы</comment>
+ <comment xml:lang="ko">GIMP 붓</comment>
+ <comment xml:lang="pl">Pędzel programu GIMP</comment>
+ <comment xml:lang="pt_BR">Pincel do GIMP</comment>
+ <comment xml:lang="ru">КиÑÑ‚ÑŒ GIMP</comment>
+ <comment xml:lang="sk">Štetec aplikácie GIMP</comment>
+ <comment xml:lang="sv">GIMP-pensel</comment>
+ <comment xml:lang="uk">пензель GIMP</comment>
+ <comment xml:lang="zh_CN">GIMP 笔刷</comment>
+ <comment xml:lang="zh_TW">GIMP 筆刷</comment>
+ <glob pattern="*.gbr"/>
+ <magic priority="50">
+ <match value="GIMP" type="string" offset="20"/>
+ </magic>
+ </mime-type>
+ <mime-type type="image/x-gimp-gih">
+ <comment>GIMP brush pipe</comment>
+ <comment xml:lang="ca">conducte del pinzell de GIMP</comment>
+ <comment xml:lang="cs">zřetězení štětců GIMP</comment>
+ <comment xml:lang="de">GIMP-Pinselanimation</comment>
+ <comment xml:lang="en_GB">GIMP brush pipe</comment>
+ <comment xml:lang="es">pincel animado del GIMP</comment>
+ <comment xml:lang="hr">GIMP valjkasti kist</comment>
+ <comment xml:lang="hu">GIMP ecsetcsatorna</comment>
+ <comment xml:lang="id">Pipa kuas GIMP</comment>
+ <comment xml:lang="it">Pipe pennello GIMP</comment>
+ <comment xml:lang="kk">GIMP боÑу жаққыш түтігі</comment>
+ <comment xml:lang="ko">GIMP 붓 파ì´í”„</comment>
+ <comment xml:lang="pl">Potok pędzla programu GIMP</comment>
+ <comment xml:lang="pt_BR">Tubo de pincel do GIMP</comment>
+ <comment xml:lang="ru">ÐÐ½Ð¸Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ ÐºÐ¸ÑÑ‚ÑŒ GIMP</comment>
+ <comment xml:lang="sv">GIMP-penselrör</comment>
+ <comment xml:lang="uk">канал пензлів GIMP</comment>
+ <comment xml:lang="zh_CN">GIMP 管刷</comment>
+ <comment xml:lang="zh_TW">GIMP 筆刷導管</comment>
+ <glob pattern="*.gih"/>
+ </mime-type>
+ <mime-type type="image/x-gimp-pat">
+ <comment>GIMP pattern</comment>
+ <comment xml:lang="ca">patró de GIMP</comment>
+ <comment xml:lang="cs">vzorek GIMP</comment>
+ <comment xml:lang="de">GIMP-Muster</comment>
+ <comment xml:lang="en_GB">GIMP pattern</comment>
+ <comment xml:lang="es">patrón del GIMP</comment>
+ <comment xml:lang="hr">GIMP uzorak</comment>
+ <comment xml:lang="hu">GIMP minta</comment>
+ <comment xml:lang="id">Pola GIMP</comment>
+ <comment xml:lang="it">Motivo GIMP</comment>
+ <comment xml:lang="kk">GIMP оюы</comment>
+ <comment xml:lang="ko">GIMP 패턴</comment>
+ <comment xml:lang="pl">Deseń programu GIMP</comment>
+ <comment xml:lang="pt_BR">Textura do GIMP</comment>
+ <comment xml:lang="ru">Шаблон GIMP</comment>
+ <comment xml:lang="sk">Vzor aplikácie GIMP</comment>
+ <comment xml:lang="sv">GIMP-mönster</comment>
+ <comment xml:lang="uk">візерунок GIMP</comment>
+ <comment xml:lang="zh_CN">GIMP 图案</comment>
+ <comment xml:lang="zh_TW">GIMP 樣å¼</comment>
+ <glob pattern="*.pat"/>
+ <magic priority="50">
+ <match value="GPAT" type="string" offset="20"/>
+ </magic>
+ </mime-type>
<mime-type type="image/x-xfig">
<comment>XFig image</comment>
<comment xml:lang="ar">صورة XFig</comment>
@@ -29018,7 +29944,7 @@
<comment xml:lang="pt">imagem XFig</comment>
<comment xml:lang="pt_BR">Imagem do XFig</comment>
<comment xml:lang="ro">Imagine XFig</comment>
- <comment xml:lang="ru">изображение XFig</comment>
+ <comment xml:lang="ru">Изображение XFig</comment>
<comment xml:lang="sk">Obrázok XFig</comment>
<comment xml:lang="sl">Slikovna datoteka XFig</comment>
<comment xml:lang="sq">Figurë XFig</comment>
@@ -29073,7 +29999,7 @@
<comment xml:lang="pt">imagem XPM</comment>
<comment xml:lang="pt_BR">Imagem XPM</comment>
<comment xml:lang="ro">Imagine XPM</comment>
- <comment xml:lang="ru">изображение XPM</comment>
+ <comment xml:lang="ru">Изображение XPM</comment>
<comment xml:lang="sk">Obrázok XPM</comment>
<comment xml:lang="sl">Slikovna datoteka XPM</comment>
<comment xml:lang="sq">Figurë XPM</comment>
@@ -29111,7 +30037,7 @@
<comment xml:lang="fi">X-ikkunakuva</comment>
<comment xml:lang="fo">X vindeyga mynd</comment>
<comment xml:lang="fr">image X window</comment>
- <comment xml:lang="ga">íomhá fhuinneog X</comment>
+ <comment xml:lang="ga">íomhá X-windows</comment>
<comment xml:lang="gl">imaxe de X Window</comment>
<comment xml:lang="he">תמונת חלון של X</comment>
<comment xml:lang="hr">X window slika</comment>
@@ -29133,7 +30059,7 @@
<comment xml:lang="pt">imagem de janela X</comment>
<comment xml:lang="pt_BR">Imagem de janela do X</comment>
<comment xml:lang="ro">Imagine X window</comment>
- <comment xml:lang="ru">изображение X window</comment>
+ <comment xml:lang="ru">Изображение X window</comment>
<comment xml:lang="sk">Obrázok X window</comment>
<comment xml:lang="sl">slika X oken</comment>
<comment xml:lang="sq">Figurë X window</comment>
@@ -29142,13 +30068,14 @@
<comment xml:lang="tr">X pencere görüntüsü</comment>
<comment xml:lang="uk">Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ X window</comment>
<comment xml:lang="vi">Ảnh cửa sổ X</comment>
- <comment xml:lang="zh_CN">X window 图åƒ</comment>
+ <comment xml:lang="zh_CN">X Window 图åƒ</comment>
<comment xml:lang="zh_TW">X window å½±åƒ</comment>
<glob pattern="*.xwd"/>
</mime-type>
<mime-type type="inode/blockdevice">
<comment>block device</comment>
<comment xml:lang="ar">جهاز كتلي</comment>
+ <comment xml:lang="ast">preséu de bloques</comment>
<comment xml:lang="be@latin">blokavaja pryłada</comment>
<comment xml:lang="bg">Блоково уÑтройÑтво</comment>
<comment xml:lang="ca">dispositiu de blocs</comment>
@@ -29169,7 +30096,7 @@
<comment xml:lang="hr">Blokovski uređaj</comment>
<comment xml:lang="hu">blokkos eszköz</comment>
<comment xml:lang="ia">Dispositivo de blocos</comment>
- <comment xml:lang="id">blok divais</comment>
+ <comment xml:lang="id">peranti blok</comment>
<comment xml:lang="it">Device a blocchi</comment>
<comment xml:lang="ja">ブロックデãƒã‚¤ã‚¹</comment>
<comment xml:lang="kk">блоктық құрылғыÑÑ‹</comment>
@@ -29185,7 +30112,7 @@
<comment xml:lang="pt">dispositivo de bloco</comment>
<comment xml:lang="pt_BR">Dispositivo de bloco</comment>
<comment xml:lang="ro">dispozitiv bloc</comment>
- <comment xml:lang="ru">блочное уÑтройÑтво</comment>
+ <comment xml:lang="ru">Блочное уÑтройÑтво</comment>
<comment xml:lang="sk">Blokové zariadenie</comment>
<comment xml:lang="sl">bloÄna naprava</comment>
<comment xml:lang="sq">device me blloqe</comment>
@@ -29200,6 +30127,7 @@
<mime-type type="inode/chardevice">
<comment>character device</comment>
<comment xml:lang="ar">جهاز حرÙÙŠ</comment>
+ <comment xml:lang="ast">preséu de caráuteres</comment>
<comment xml:lang="be@latin">znakavaja pryłada</comment>
<comment xml:lang="bg">Символно уÑтройÑтво</comment>
<comment xml:lang="ca">dispositiu de caràcters</comment>
@@ -29220,7 +30148,7 @@
<comment xml:lang="hr">Znakovni uređaj</comment>
<comment xml:lang="hu">karakteres eszköz</comment>
<comment xml:lang="ia">Dispositivo de characteres</comment>
- <comment xml:lang="id">karakter divais</comment>
+ <comment xml:lang="id">peranti karakter</comment>
<comment xml:lang="it">Device a caratteri</comment>
<comment xml:lang="ja">キャラクタデãƒã‚¤ã‚¹</comment>
<comment xml:lang="kk">Ñимволдық құрылғыÑÑ‹</comment>
@@ -29236,7 +30164,7 @@
<comment xml:lang="pt">dispositivo de caracteres</comment>
<comment xml:lang="pt_BR">Dispositivo de caractere</comment>
<comment xml:lang="ro">dispozitiv caracter</comment>
- <comment xml:lang="ru">Ñимвольное уÑтройÑтво</comment>
+ <comment xml:lang="ru">Символьное уÑтройÑтво</comment>
<comment xml:lang="sk">Znakové zariadenie</comment>
<comment xml:lang="sl">znakovna naprava</comment>
<comment xml:lang="sq">device me karaktere</comment>
@@ -29251,6 +30179,7 @@
<mime-type type="inode/directory">
<comment>folder</comment>
<comment xml:lang="ar">مجلّد</comment>
+ <comment xml:lang="ast">carpeta</comment>
<comment xml:lang="be@latin">kataloh</comment>
<comment xml:lang="bg">Папка</comment>
<comment xml:lang="ca">carpeta</comment>
@@ -29268,7 +30197,7 @@
<comment xml:lang="ga">fillteán</comment>
<comment xml:lang="gl">cartafol</comment>
<comment xml:lang="he">תיקייה</comment>
- <comment xml:lang="hr">direktorij</comment>
+ <comment xml:lang="hr">Mapa</comment>
<comment xml:lang="hu">mappa</comment>
<comment xml:lang="ia">Dossier</comment>
<comment xml:lang="id">folder</comment>
@@ -29287,7 +30216,7 @@
<comment xml:lang="pt">pasta</comment>
<comment xml:lang="pt_BR">Pasta</comment>
<comment xml:lang="ro">dosar</comment>
- <comment xml:lang="ru">папка</comment>
+ <comment xml:lang="ru">Папка</comment>
<comment xml:lang="sk">PrieÄinok</comment>
<comment xml:lang="sl">mapa</comment>
<comment xml:lang="sq">Kartelë</comment>
@@ -29340,7 +30269,7 @@
<comment xml:lang="pt">canal</comment>
<comment xml:lang="pt_BR">Pipe</comment>
<comment xml:lang="ro">canal pipe</comment>
- <comment xml:lang="ru">канал</comment>
+ <comment xml:lang="ru">Канал</comment>
<comment xml:lang="sk">Rúra</comment>
<comment xml:lang="sl">cev</comment>
<comment xml:lang="sq">Pipe</comment>
@@ -29355,6 +30284,7 @@
<mime-type type="inode/mount-point">
<comment>mount point</comment>
<comment xml:lang="ar">نقطة الوصْل</comment>
+ <comment xml:lang="ast">puntu de montaxe</comment>
<comment xml:lang="be@latin">punkt mantavańnia</comment>
<comment xml:lang="bg">Точка на монтиране</comment>
<comment xml:lang="ca">punt de muntatge</comment>
@@ -29372,7 +30302,7 @@
<comment xml:lang="ga">pointe feistithe</comment>
<comment xml:lang="gl">punto de montaxe</comment>
<comment xml:lang="he">נקודת עיגון</comment>
- <comment xml:lang="hr">toÄka montiranja</comment>
+ <comment xml:lang="hr">ToÄka montiranja</comment>
<comment xml:lang="hu">csatolási pont</comment>
<comment xml:lang="ia">Puncto de montage</comment>
<comment xml:lang="id">titik mount</comment>
@@ -29391,7 +30321,7 @@
<comment xml:lang="pt">ponto de montagem</comment>
<comment xml:lang="pt_BR">Ponto de montagem</comment>
<comment xml:lang="ro">loc montare</comment>
- <comment xml:lang="ru">точка монтированиÑ</comment>
+ <comment xml:lang="ru">Точка монтированиÑ</comment>
<comment xml:lang="sk">Miesto pripojenia</comment>
<comment xml:lang="sl">priklopna toÄka</comment>
<comment xml:lang="sq">Pikë montimi</comment>
@@ -29424,7 +30354,7 @@
<comment xml:lang="ga">soicéad</comment>
<comment xml:lang="gl">socket</comment>
<comment xml:lang="he">נקודת חיבור</comment>
- <comment xml:lang="hr">utiÄnica</comment>
+ <comment xml:lang="hr">PrikljuÄnica</comment>
<comment xml:lang="hu">illesztőpont</comment>
<comment xml:lang="ia">Socket</comment>
<comment xml:lang="id">soket</comment>
@@ -29443,7 +30373,7 @@
<comment xml:lang="pt">tomada</comment>
<comment xml:lang="pt_BR">Socket</comment>
<comment xml:lang="ro">socket</comment>
- <comment xml:lang="ru">Ñокет</comment>
+ <comment xml:lang="ru">Сокет</comment>
<comment xml:lang="sk">Soket</comment>
<comment xml:lang="sl">vtiÄ</comment>
<comment xml:lang="sq">Socket</comment>
@@ -29458,6 +30388,7 @@
<mime-type type="inode/symlink">
<comment>symbolic link</comment>
<comment xml:lang="ar">وصلة رمزية</comment>
+ <comment xml:lang="ast">enllaz simbólicu</comment>
<comment xml:lang="az">simvolik körpü</comment>
<comment xml:lang="be@latin">symbalnaja spasyłka</comment>
<comment xml:lang="bg">Символна връзка</comment>
@@ -29477,7 +30408,7 @@
<comment xml:lang="ga">nasc siombalach</comment>
<comment xml:lang="gl">ligazón simbólica</comment>
<comment xml:lang="he">קישור סימבולי</comment>
- <comment xml:lang="hr">simboliÄka veza</comment>
+ <comment xml:lang="hr">SimboliÄka poveznica</comment>
<comment xml:lang="hu">szimbolikus link</comment>
<comment xml:lang="ia">Ligamine symbolic</comment>
<comment xml:lang="id">taut simbolik</comment>
@@ -29497,7 +30428,7 @@
<comment xml:lang="pt">ligação simbólica</comment>
<comment xml:lang="pt_BR">Ligação simbólica</comment>
<comment xml:lang="ro">legătură simbolică</comment>
- <comment xml:lang="ru">ÑÐ¸Ð¼Ð²Ð¾Ð»ÑŒÐ½Ð°Ñ ÑÑылка</comment>
+ <comment xml:lang="ru">Ð¡Ð¸Ð¼Ð²Ð¾Ð»ÑŒÐ½Ð°Ñ ÑÑылка</comment>
<comment xml:lang="sk">Symbolický odkaz</comment>
<comment xml:lang="sl">simbolna povezava</comment>
<comment xml:lang="sq">Lidhje simbolike</comment>
@@ -29528,10 +30459,10 @@
<comment xml:lang="fi">viestin jakeluilmoitus</comment>
<comment xml:lang="fo">post útberingarfrásøgn</comment>
<comment xml:lang="fr">rapport de livraison de courriels</comment>
- <comment xml:lang="ga">tuairisc sheachadadh poist</comment>
+ <comment xml:lang="ga">tuairisc sheachadta r-phoist</comment>
<comment xml:lang="gl">informe de entrega de correo</comment>
<comment xml:lang="he">דוח העברת דו×ר</comment>
- <comment xml:lang="hr">izvještaj dostave pošte</comment>
+ <comment xml:lang="hr">Izvještaj dostave pošte</comment>
<comment xml:lang="hu">jelentés levélkézbesítésről</comment>
<comment xml:lang="ia">Reporto de livration de e-mail</comment>
<comment xml:lang="id">laporan pengantaran surat</comment>
@@ -29550,7 +30481,7 @@
<comment xml:lang="pt">relatório de entrega de email</comment>
<comment xml:lang="pt_BR">Relatório de entrega de correspondência</comment>
<comment xml:lang="ro">raport de trimitere email</comment>
- <comment xml:lang="ru">отчёт о доÑтавке ÑообщениÑ</comment>
+ <comment xml:lang="ru">Отчёт о доÑтавке ÑообщениÑ</comment>
<comment xml:lang="sk">Správa o doruÄení poÅ¡ty</comment>
<comment xml:lang="sl">poroÄilo dostave poÅ¡te</comment>
<comment xml:lang="sq">Raport mbi dorëzimin e mesazhit</comment>
@@ -29583,7 +30514,7 @@
<comment xml:lang="fi">viestin kuittausilmoitus</comment>
<comment xml:lang="fo">post avhendingarfrásøgn</comment>
<comment xml:lang="fr">rapport de disposition de courriels</comment>
- <comment xml:lang="ga">tuairisc chóiriú poist</comment>
+ <comment xml:lang="ga">tuairisc chóirithe r-phoist</comment>
<comment xml:lang="gl">informe de disposición de correo</comment>
<comment xml:lang="he">דוח ×ספקת דו×ר</comment>
<comment xml:lang="hr">Izvještaj smještaja e-pošte</comment>
@@ -29605,7 +30536,7 @@
<comment xml:lang="pt">relatório de disposição de email</comment>
<comment xml:lang="pt_BR">Relatório de disposição de correspondência</comment>
<comment xml:lang="ro">confirmare primire email</comment>
- <comment xml:lang="ru">отчёт о перемещении почты</comment>
+ <comment xml:lang="ru">Отчёт о перемещении почты</comment>
<comment xml:lang="sk">Správa o odovzdaní pošty</comment>
<comment xml:lang="sl">poroÄilo razporeditve poÅ¡te</comment>
<comment xml:lang="sq">Raport mbi njoftimin e mesazhit</comment>
@@ -29641,7 +30572,7 @@
<comment xml:lang="ga">tagairt do chomhad cianda</comment>
<comment xml:lang="gl">referencia a un ficheiro remoto</comment>
<comment xml:lang="he">התיחסות לקובץ מרוחק</comment>
- <comment xml:lang="hr">referenca na udaljenu datoteku</comment>
+ <comment xml:lang="hr">Preporuka na udaljenu datoteku</comment>
<comment xml:lang="hu">hivatkozás távoli fájlra</comment>
<comment xml:lang="ia">Referentia a un file remote</comment>
<comment xml:lang="id">referensi ke berkas jarak jauh</comment>
@@ -29660,7 +30591,7 @@
<comment xml:lang="pt">referência a um ficheiro remoto</comment>
<comment xml:lang="pt_BR">Referência para arquivo remoto</comment>
<comment xml:lang="ro">referință fișier la distanță</comment>
- <comment xml:lang="ru">ÑÑылка на удалённый файл</comment>
+ <comment xml:lang="ru">СÑылка на удалённый файл</comment>
<comment xml:lang="sk">Odkaz na vzdialený súbor</comment>
<comment xml:lang="sl">sklic do oddaljene datoteke</comment>
<comment xml:lang="sq">Referim për tek file në distancë</comment>
@@ -29692,7 +30623,7 @@
<comment xml:lang="fi">nyyssiviesti</comment>
<comment xml:lang="fo">Usenet news boð</comment>
<comment xml:lang="fr">message de groupe d'échange Usenet</comment>
- <comment xml:lang="ga">teachtaireacht nuacht Usenet</comment>
+ <comment xml:lang="ga">teachtaireacht nuachta Usenet</comment>
<comment xml:lang="gl">mensaxes de noticias de Usenet</comment>
<comment xml:lang="he">הודעת חדשות של Usenet</comment>
<comment xml:lang="hr">Usenet poruka novosti</comment>
@@ -29714,7 +30645,7 @@
<comment xml:lang="pt">mensagem de notícias Usenet</comment>
<comment xml:lang="pt_BR">Mensagem de notícias da Usenet</comment>
<comment xml:lang="ro">Mesaj Usenet de știri </comment>
- <comment xml:lang="ru">новоÑтное Ñообщение Usenet</comment>
+ <comment xml:lang="ru">ÐовоÑтное Ñообщение Usenet</comment>
<comment xml:lang="sk">Príspevok do diskusných skupín Usenet</comment>
<comment xml:lang="sl">noviÄarsko sporoÄilo Usenet</comment>
<comment xml:lang="sq">Mesazh lajmesh Usenet</comment>
@@ -29754,14 +30685,14 @@
<comment xml:lang="ga">teachtaireacht ríomhphoist neamhiomlán</comment>
<comment xml:lang="gl">mensaxe de correo electrónico parcial</comment>
<comment xml:lang="he">מסר דו×״ל חלקי</comment>
- <comment xml:lang="hr">djelomiÄna poruka e-poÅ¡te</comment>
+ <comment xml:lang="hr">Nepotpuna poruka e-pošte</comment>
<comment xml:lang="hu">részleges elektronikus levél</comment>
<comment xml:lang="ia">Message de e-mail partial</comment>
<comment xml:lang="id">pesan email sebagian</comment>
<comment xml:lang="it">Messaggio email parziale</comment>
<comment xml:lang="ja">部分メールメッセージ</comment>
<comment xml:lang="kk">Ñлектронды поштаның үзінді мәлімдемеÑÑ–</comment>
- <comment xml:lang="ko">ë¶€ë¶„ì  ì „ìž ìš°íŽ¸ 메시지</comment>
+ <comment xml:lang="ko">ì „ìž ìš°íŽ¸ 메시지 ì¼ë¶€</comment>
<comment xml:lang="lt">nepilnas el. laiškas</comment>
<comment xml:lang="lv">daļēja e-pasta vēstule</comment>
<comment xml:lang="ms">Bahagian mesej emel</comment>
@@ -29773,7 +30704,7 @@
<comment xml:lang="pt">mensagem parcial de email</comment>
<comment xml:lang="pt_BR">Mensagem de e-mail parcial</comment>
<comment xml:lang="ro">mesaj de email parțial</comment>
- <comment xml:lang="ru">фрагмент ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñлектронной почты</comment>
+ <comment xml:lang="ru">Фрагмент ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñлектронной почты</comment>
<comment xml:lang="sk">ÄŒiastoÄná e-mailová správa</comment>
<comment xml:lang="sl">delno elektronsko sporoÄilo</comment>
<comment xml:lang="sq">Mesazh poste i pjesëshëm</comment>
@@ -29807,7 +30738,7 @@
<comment xml:lang="ga">teachtaireacht ríomhphoist</comment>
<comment xml:lang="gl">mensaxe de correo electrónico</comment>
<comment xml:lang="he">הודעת דו×ר ×לקטרוני</comment>
- <comment xml:lang="hr">poruka e-pošte</comment>
+ <comment xml:lang="hr">Poruka e-pošte</comment>
<comment xml:lang="hu">elektronikus levél</comment>
<comment xml:lang="ia">Message de e-mail</comment>
<comment xml:lang="id">pesan email</comment>
@@ -29826,7 +30757,7 @@
<comment xml:lang="pt">mensagem de email</comment>
<comment xml:lang="pt_BR">Mensagem de e-mail</comment>
<comment xml:lang="ro">mesaj email</comment>
- <comment xml:lang="ru">почтовое Ñообщение</comment>
+ <comment xml:lang="ru">Почтовое Ñообщение</comment>
<comment xml:lang="sk">E-mailová správa</comment>
<comment xml:lang="sl">sporoÄilo elektronske poÅ¡te</comment>
<comment xml:lang="sq">Mesazh poste</comment>
@@ -29872,7 +30803,7 @@
<comment xml:lang="fi">GNU-postiviesti</comment>
<comment xml:lang="fo">GNU mail boð</comment>
<comment xml:lang="fr">message de courriel GNU</comment>
- <comment xml:lang="ga">teachtaireacht phost GNU</comment>
+ <comment xml:lang="ga">teachtaireacht r-phoist GNU</comment>
<comment xml:lang="gl">mensaxe de correo electrónico de GNU</comment>
<comment xml:lang="he">הודעת דו×ר של GNU</comment>
<comment xml:lang="hr">GNU poruka pošte</comment>
@@ -29895,7 +30826,7 @@
<comment xml:lang="pt">mensagem de email GNU</comment>
<comment xml:lang="pt_BR">Mensagem de e-mail GNU</comment>
<comment xml:lang="ro">Mesaj GNU mail</comment>
- <comment xml:lang="ru">почтовое Ñообщение GNU</comment>
+ <comment xml:lang="ru">Почтовое Ñообщение GNU</comment>
<comment xml:lang="sk">Správa GNU mail</comment>
<comment xml:lang="sl">SporoÄilo poÅ¡te GNU</comment>
<comment xml:lang="sq">Mesazh GNU mail</comment>
@@ -29911,20 +30842,31 @@
</mime-type>
<mime-type type="model/iges">
<comment>IGES document</comment>
+ <comment xml:lang="ast">Documentu IGES</comment>
<comment xml:lang="ca">document IGES</comment>
+ <comment xml:lang="cs">dokument IGES</comment>
<comment xml:lang="da">IGES-dokument</comment>
<comment xml:lang="de">IGES-Dokument</comment>
+ <comment xml:lang="en_GB">IGES document</comment>
<comment xml:lang="es">documento IGES</comment>
+ <comment xml:lang="eu">IGES dokumentua</comment>
<comment xml:lang="fi">IGES-asiakirja</comment>
<comment xml:lang="fr">document IGES</comment>
+ <comment xml:lang="ga">cáipéis IGES</comment>
<comment xml:lang="he">מסמך IGES</comment>
+ <comment xml:lang="hr">IGES dokument</comment>
<comment xml:lang="hu">IGES dokumentum</comment>
+ <comment xml:lang="id">dokumen IGES</comment>
+ <comment xml:lang="it">Documento IGES</comment>
<comment xml:lang="kk">IGES құжаты</comment>
<comment xml:lang="ko">IGES 문서</comment>
<comment xml:lang="pl">Dokument IGES</comment>
<comment xml:lang="pt_BR">Documento IGES</comment>
- <comment xml:lang="ru">документ IGES</comment>
+ <comment xml:lang="ru">Документ IGES</comment>
<comment xml:lang="sk">Dokument IGES</comment>
+ <comment xml:lang="sr">ИГЕС документ</comment>
+ <comment xml:lang="sv">IGES-dokument</comment>
+ <comment xml:lang="tr">IGES belgesi</comment>
<comment xml:lang="uk">документ IGES</comment>
<comment xml:lang="zh_CN">IGES 文档</comment>
<comment xml:lang="zh_TW">IGES 文件</comment>
@@ -29942,6 +30884,7 @@
<mime-type type="model/vrml">
<comment>VRML document</comment>
<comment xml:lang="ar">مستند VRML</comment>
+ <comment xml:lang="ast">Documentu VRML</comment>
<comment xml:lang="az">VRML sənədi</comment>
<comment xml:lang="be@latin">Dakument VRML</comment>
<comment xml:lang="bg">Документ — VRML</comment>
@@ -29980,7 +30923,7 @@
<comment xml:lang="pt">documento VRML</comment>
<comment xml:lang="pt_BR">Documento VRML</comment>
<comment xml:lang="ro">Document VRML</comment>
- <comment xml:lang="ru">документ VRML</comment>
+ <comment xml:lang="ru">Документ VRML</comment>
<comment xml:lang="sk">Dokument VRML</comment>
<comment xml:lang="sl">Dokument VRML</comment>
<comment xml:lang="sq">Dokument VRML</comment>
@@ -30021,10 +30964,10 @@
<comment xml:lang="fi">viesti useissa muodoissa</comment>
<comment xml:lang="fo">boð í fleiri sniðum</comment>
<comment xml:lang="fr">message en formats divers</comment>
- <comment xml:lang="ga">teachtaireacht i roinnt fhormáidí</comment>
+ <comment xml:lang="ga">teachtaireacht i bhformáidí éagsúla</comment>
<comment xml:lang="gl">mensaxe en varios formatos</comment>
<comment xml:lang="he">הודעה במספר תבניות</comment>
- <comment xml:lang="hr">poruka u nekoliko oblika</comment>
+ <comment xml:lang="hr">Poruka u nekoliko oblika</comment>
<comment xml:lang="hu">többféle formátumú üzenet</comment>
<comment xml:lang="ia">Message in plure formatos</comment>
<comment xml:lang="id">pesan dalam beberapa format</comment>
@@ -30043,7 +30986,7 @@
<comment xml:lang="pt">mensagem em vários formatos</comment>
<comment xml:lang="pt_BR">Mensagem em vários formatos</comment>
<comment xml:lang="ro">mesaj în diferite formate</comment>
- <comment xml:lang="ru">Ñообщение в неÑкольких форматах</comment>
+ <comment xml:lang="ru">Сообщение в неÑкольких форматах</comment>
<comment xml:lang="sk">Správa v niekoľkých formátoch</comment>
<comment xml:lang="sl">sporoÄilo v veÄ zapisih</comment>
<comment xml:lang="sq">Mesazh në formate të ndryshëm</comment>
@@ -30052,7 +30995,7 @@
<comment xml:lang="tr">farklı biçimlerde ileti</comment>
<comment xml:lang="uk">Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñƒ кількох форматах</comment>
<comment xml:lang="vi">thông điệp có vài định dạng</comment>
- <comment xml:lang="zh_CN">å„ç§æ ¼å¼çš„消æ¯</comment>
+ <comment xml:lang="zh_CN">å„ç§æ ¼å¼çš„信件</comment>
<comment xml:lang="zh_TW">多種格å¼çš„訊æ¯</comment>
</mime-type>
<mime-type type="multipart/appledouble">
@@ -30096,7 +31039,7 @@
<comment xml:lang="pt">ficheiro codificado em AppleDouble de Macintosh</comment>
<comment xml:lang="pt_BR">Arquivo do Macintosh codificado com AppleDouble</comment>
<comment xml:lang="ro">Fișier codat Macintosh AppleDouble</comment>
- <comment xml:lang="ru">файл (закодированный Macintosh AppleDouble)</comment>
+ <comment xml:lang="ru">Файл, закодированный Macintosh AppleDouble</comment>
<comment xml:lang="sk">Súbor kódovaný pomocou Macintosh AppleDouble</comment>
<comment xml:lang="sl">Kodirana datoteka Macintosh (AppleDouble)</comment>
<comment xml:lang="sq">File Macintosh i kodifikuar AppleDouble</comment>
@@ -30133,7 +31076,7 @@
<comment xml:lang="hr">Poruka kratkg sadržaja</comment>
<comment xml:lang="hu">ömlesztett üzenet</comment>
<comment xml:lang="ia">Digesto de messages</comment>
- <comment xml:lang="id">pesan digest</comment>
+ <comment xml:lang="id">digest pesan</comment>
<comment xml:lang="it">Digest di messaggi</comment>
<comment xml:lang="ja">メッセージダイジェスト</comment>
<comment xml:lang="kk">мәлімдеме профилі</comment>
@@ -30149,7 +31092,7 @@
<comment xml:lang="pt">grupo de mensagens</comment>
<comment xml:lang="pt_BR">Resumo de mensagem</comment>
<comment xml:lang="ro">colecție mesaje email</comment>
- <comment xml:lang="ru">профиль ÑообщениÑ</comment>
+ <comment xml:lang="ru">ДайджеÑÑ‚ ÑообщениÑ</comment>
<comment xml:lang="sk">Prehľad správ</comment>
<comment xml:lang="sl">povzetek sporoÄila</comment>
<comment xml:lang="sq">Shpërndarje mesazhesh</comment>
@@ -30158,7 +31101,7 @@
<comment xml:lang="tr">mesaj özeti</comment>
<comment xml:lang="uk">збірка повідомлень</comment>
<comment xml:lang="vi">bản tóm tắt thông điệp</comment>
- <comment xml:lang="zh_CN">消æ¯æ‘˜è¦</comment>
+ <comment xml:lang="zh_CN">信件摘è¦</comment>
<comment xml:lang="zh_TW">訊æ¯æ‘˜è¦</comment>
</mime-type>
<mime-type type="multipart/encrypted">
@@ -30183,7 +31126,7 @@
<comment xml:lang="ga">teachtaireacht chriptithe</comment>
<comment xml:lang="gl">mensaxe cifrado</comment>
<comment xml:lang="he">הודעה מוצפנת</comment>
- <comment xml:lang="hr">Å¡ifrirana poruka</comment>
+ <comment xml:lang="hr">Å ifrirana poruka</comment>
<comment xml:lang="hu">titkosított üzenet</comment>
<comment xml:lang="ia">Message cryptate</comment>
<comment xml:lang="id">pesan terenkripsi</comment>
@@ -30202,7 +31145,7 @@
<comment xml:lang="pt">mensagem encriptada</comment>
<comment xml:lang="pt_BR">Mensagem criptografada</comment>
<comment xml:lang="ro">mesaj criptat</comment>
- <comment xml:lang="ru">зашифрованное Ñообщение</comment>
+ <comment xml:lang="ru">Зашифрованное Ñообщение</comment>
<comment xml:lang="sk">Zašifrovaná správa</comment>
<comment xml:lang="sl">Å¡ifrirano sporoÄilo</comment>
<comment xml:lang="sq">Mesazh i kriptuar</comment>
@@ -30217,6 +31160,7 @@
<mime-type type="multipart/mixed">
<comment>compound documents</comment>
<comment xml:lang="ar">مستندات مركبة</comment>
+ <comment xml:lang="ast">documentos compuestos</comment>
<comment xml:lang="be@latin">składanyja dakumenty</comment>
<comment xml:lang="bg">СъÑтавни документи</comment>
<comment xml:lang="ca">documents compostos</comment>
@@ -30253,7 +31197,7 @@
<comment xml:lang="pt">documentos compostos</comment>
<comment xml:lang="pt_BR">Documentos compostos</comment>
<comment xml:lang="ro">documente compuse</comment>
- <comment xml:lang="ru">ÑоÑтавные документы</comment>
+ <comment xml:lang="ru">СоÑтавные документы</comment>
<comment xml:lang="sk">Zložené dokumenty</comment>
<comment xml:lang="sl">združeni dokumenti</comment>
<comment xml:lang="sq">dokumente të përbërë</comment>
@@ -30268,6 +31212,7 @@
<mime-type type="multipart/related">
<comment>compound document</comment>
<comment xml:lang="ar">مستند مركب</comment>
+ <comment xml:lang="ast">documentu compuestu</comment>
<comment xml:lang="az">birləşik sənəd</comment>
<comment xml:lang="be@latin">składany dakument</comment>
<comment xml:lang="bg">СъÑтавен документ</comment>
@@ -30306,7 +31251,7 @@
<comment xml:lang="pt">documento composto</comment>
<comment xml:lang="pt_BR">Documento composto</comment>
<comment xml:lang="ro">document compus</comment>
- <comment xml:lang="ru">ÑоÑтавной документ</comment>
+ <comment xml:lang="ru">СоÑтавной документ</comment>
<comment xml:lang="sk">Zložený dokument</comment>
<comment xml:lang="sl">združeni dokument</comment>
<comment xml:lang="sq">dokumet i përbërë</comment>
@@ -30337,7 +31282,7 @@
<comment xml:lang="fi">viestijärjestelmän ilmoitus</comment>
<comment xml:lang="fo">postkervisfrásøgn</comment>
<comment xml:lang="fr">rapport système de courriels</comment>
- <comment xml:lang="ga">tuairisc chóras poist</comment>
+ <comment xml:lang="ga">tuairisc chórais r-phoist</comment>
<comment xml:lang="gl">informe do sistema de correo</comment>
<comment xml:lang="he">דו״ח של מערכת הדו×ר</comment>
<comment xml:lang="hr">Izvještaj sustava pošte</comment>
@@ -30359,7 +31304,7 @@
<comment xml:lang="pt">relatório de sistema de email</comment>
<comment xml:lang="pt_BR">Relatório do sistema de correspondência</comment>
<comment xml:lang="ro">raport sistem email</comment>
- <comment xml:lang="ru">отчёт почтовой ÑиÑтемы</comment>
+ <comment xml:lang="ru">Отчёт почтовой ÑиÑтемы</comment>
<comment xml:lang="sk">Správa poštového systému</comment>
<comment xml:lang="sl">poroÄilo poÅ¡tnega sistema</comment>
<comment xml:lang="sq">Raport i sistemit të postës</comment>
@@ -30393,7 +31338,7 @@
<comment xml:lang="ga">teachtaireacht sínithe</comment>
<comment xml:lang="gl">mensaxe firmado</comment>
<comment xml:lang="he">הודעה חתומה</comment>
- <comment xml:lang="hr">potpisana poruka</comment>
+ <comment xml:lang="hr">Potpisana poruka</comment>
<comment xml:lang="hu">aláírt üzenet</comment>
<comment xml:lang="ia">Message signate</comment>
<comment xml:lang="id">pesan ditandatangani</comment>
@@ -30412,7 +31357,7 @@
<comment xml:lang="pt">mensagem assinada</comment>
<comment xml:lang="pt_BR">Mensagem assinada</comment>
<comment xml:lang="ro">mesaj semnat</comment>
- <comment xml:lang="ru">подпиÑанное Ñообщение</comment>
+ <comment xml:lang="ru">ПодпиÑанное Ñообщение</comment>
<comment xml:lang="sk">Podpísaná správa</comment>
<comment xml:lang="sl">podpisano sporoÄilo</comment>
<comment xml:lang="sq">Mesazh i firmosur</comment>
@@ -30444,7 +31389,7 @@
<comment xml:lang="ga">sruth sonraí (brú freastalaí)</comment>
<comment xml:lang="gl">fluxo de datos (por iniciativa do servidor)</comment>
<comment xml:lang="he">מידע בזרימה (דחיפה ע״י השרת)</comment>
- <comment xml:lang="hr">Tok podataka (poslužiteljem pogurano)</comment>
+ <comment xml:lang="hr">Strujanje podataka (poslužiteljem pogurano)</comment>
<comment xml:lang="hu">sugárzott adatfolyam (kiszolgálóról)</comment>
<comment xml:lang="ia">Fluxo de datos (pulsate per servitor)</comment>
<comment xml:lang="id">arus data (dorongan server)</comment>
@@ -30463,7 +31408,7 @@
<comment xml:lang="pt">fluxo de dados (empurrados pelo servidor)</comment>
<comment xml:lang="pt_BR">Fluxo de dados (por iniciativa do servidor)</comment>
<comment xml:lang="ro">flux de date (de la server)</comment>
- <comment xml:lang="ru">поток данных (server push)</comment>
+ <comment xml:lang="ru">Поток данных (server push)</comment>
<comment xml:lang="sk">Prúd dát (posielaný serverom)</comment>
<comment xml:lang="sl">pretok podatkov (strežniški)</comment>
<comment xml:lang="sq">Fluks me të dhëna (server push)</comment>
@@ -30472,7 +31417,7 @@
<comment xml:lang="tr">veri akışı (sunucudan gönderilen)</comment>
<comment xml:lang="uk">потік даних (від Ñервера)</comment>
<comment xml:lang="vi">luồng dữ liệu (trình phục vụ đẩy)</comment>
- <comment xml:lang="zh_CN">æ•°æ®æµ(æœåŠ¡å™¨æŽ¨é€)</comment>
+ <comment xml:lang="zh_CN">æ•°æ®æµï¼ˆæœåŠ¡å™¨æŽ¨é€ï¼‰</comment>
<comment xml:lang="zh_TW">è³‡æ–™ä¸²æµ (server push)</comment>
</mime-type>
<mime-type type="text/calendar">
@@ -30513,7 +31458,7 @@
<comment xml:lang="pt">calendário VCS/ICS</comment>
<comment xml:lang="pt_BR">Calendário VCS/ICS</comment>
<comment xml:lang="ro">Calendar VCS/ICS</comment>
- <comment xml:lang="ru">календарь VCS/ICS</comment>
+ <comment xml:lang="ru">Календарь VCS/ICS</comment>
<comment xml:lang="sk">Kalendár VCS/ICS</comment>
<comment xml:lang="sl">Datoteka koledarja VCS/ICS</comment>
<comment xml:lang="sq">Kalendar VCS/ICS</comment>
@@ -30575,7 +31520,7 @@
<comment xml:lang="pt">folha de estilos CSS</comment>
<comment xml:lang="pt_BR">Folha de estilo CSS</comment>
<comment xml:lang="ro">Pagină de stil CSS</comment>
- <comment xml:lang="ru">таблица Ñтилей CSS</comment>
+ <comment xml:lang="ru">Таблица Ñтилей CSS</comment>
<comment xml:lang="sk">Štýly CSS</comment>
<comment xml:lang="sl">Slogovna predloga CSS</comment>
<comment xml:lang="sq">Fletë stili CSS</comment>
@@ -30611,7 +31556,7 @@
<comment xml:lang="ga">cárta gnó leictreonach</comment>
<comment xml:lang="gl">tarxeta de negocio electrónica</comment>
<comment xml:lang="he">כרטיס ביקור ×לקטרוני</comment>
- <comment xml:lang="hr">elektroniÄka posjetnica</comment>
+ <comment xml:lang="hr">ElektroniÄka posjetnica</comment>
<comment xml:lang="hu">elektronikus névjegykártya</comment>
<comment xml:lang="ia">Carta de visita electronic</comment>
<comment xml:lang="id">kartu bisnis elektronik</comment>
@@ -30628,7 +31573,7 @@
<comment xml:lang="pt">cartão de visita eletrónico</comment>
<comment xml:lang="pt_BR">Cartão de visitas eletrônico</comment>
<comment xml:lang="ro">carte de vizită electronică</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð²Ð¸Ð·Ð¸Ñ‚Ð½Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð¾Ñ‡ÐºÐ°</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð²Ð¸Ð·Ð¸Ñ‚Ð½Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð¾Ñ‡ÐºÐ°</comment>
<comment xml:lang="sk">Elektronická vizitka</comment>
<comment xml:lang="sl">elektronska poslovna vizitka</comment>
<comment xml:lang="sq">Skedë elektronike biznesi</comment>
@@ -30653,6 +31598,7 @@
</mime-type>
<mime-type type="text/turtle">
<comment>Turtle document</comment>
+ <comment xml:lang="ast">Documentu Turtle</comment>
<comment xml:lang="ca">document Turtle</comment>
<comment xml:lang="cs">dokument Turtle</comment>
<comment xml:lang="da">Turtle-dokument</comment>
@@ -30663,6 +31609,7 @@
<comment xml:lang="eu">Turtle dokumentua</comment>
<comment xml:lang="fi">Turtle-asiakirja</comment>
<comment xml:lang="fr">document Turtle</comment>
+ <comment xml:lang="ga">cáipéis Turtle</comment>
<comment xml:lang="he">מסמך Turtle</comment>
<comment xml:lang="hr">Turtle dokument</comment>
<comment xml:lang="hu">Turtle dokumentum</comment>
@@ -30675,7 +31622,7 @@
<comment xml:lang="pl">Dokument Turtle</comment>
<comment xml:lang="pt">documento Turtle</comment>
<comment xml:lang="pt_BR">Documento Turtle</comment>
- <comment xml:lang="ru">документ Turtle</comment>
+ <comment xml:lang="ru">Документ Turtle</comment>
<comment xml:lang="sk">Dokument Turtle</comment>
<comment xml:lang="sr">Тартл документ</comment>
<comment xml:lang="sv">Turtle-dokument</comment>
@@ -30689,6 +31636,7 @@
<mime-type type="text/x-txt2tags">
<comment>txt2tags document</comment>
<comment xml:lang="ar">مستند txt2tags</comment>
+ <comment xml:lang="ast">Documentu txt2tags</comment>
<comment xml:lang="be@latin">dakument txt2tags</comment>
<comment xml:lang="bg">Документ — txt2tags</comment>
<comment xml:lang="ca">document txt2tags</comment>
@@ -30709,7 +31657,7 @@
<comment xml:lang="hr">txt2tags dokument</comment>
<comment xml:lang="hu">txt2tags dokumentum</comment>
<comment xml:lang="ia">Documento txt2tags</comment>
- <comment xml:lang="id">dokumen txt2tags</comment>
+ <comment xml:lang="id">Dokumen txt2tags</comment>
<comment xml:lang="it">Documento txt2tags</comment>
<comment xml:lang="ja">txt2tags ドキュメント</comment>
<comment xml:lang="ka">txt2tags დáƒáƒ™áƒ£áƒ›áƒ”ნტი</comment>
@@ -30725,7 +31673,7 @@
<comment xml:lang="pt">documento txt2tags</comment>
<comment xml:lang="pt_BR">Documento do txt2tags</comment>
<comment xml:lang="ro">document txt2tags</comment>
- <comment xml:lang="ru">документ txt2tags</comment>
+ <comment xml:lang="ru">Документ txt2tags</comment>
<comment xml:lang="sk">Dokument txt2tags</comment>
<comment xml:lang="sl">Dokument txt2tags</comment>
<comment xml:lang="sq">Dokument txt2tags</comment>
@@ -30747,7 +31695,7 @@
<comment>Verilog source code</comment>
<comment xml:lang="bg">Изходен код — Verilog</comment>
<comment xml:lang="ca">codi font en Verilog</comment>
- <comment xml:lang="cs">zdrojový kód Verilog</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Verilog</comment>
<comment xml:lang="da">Verilog-kildekode</comment>
<comment xml:lang="de">Verilog-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας Verilog</comment>
@@ -30757,9 +31705,10 @@
<comment xml:lang="eu">Verilog iturburu-kodea</comment>
<comment xml:lang="fi">Verilog-lähdekoodi</comment>
<comment xml:lang="fr">code source Verilog</comment>
+ <comment xml:lang="ga">cód foinseach Verilog</comment>
<comment xml:lang="gl">código fonte en Verilog</comment>
<comment xml:lang="he">קוד מקור של </comment>
- <comment xml:lang="hr">Verilog izvorni kod</comment>
+ <comment xml:lang="hr">Verilog izvorni kôd</comment>
<comment xml:lang="hu">Verilog-forráskód</comment>
<comment xml:lang="ia">Codice-fonte Verilog</comment>
<comment xml:lang="id">Kode sumber Verilog</comment>
@@ -30773,7 +31722,7 @@
<comment xml:lang="pl">Kod źródłowy Verilog</comment>
<comment xml:lang="pt">código origem Verilog</comment>
<comment xml:lang="pt_BR">Código-fonte Verilog</comment>
- <comment xml:lang="ru">иÑходный код Verilog</comment>
+ <comment xml:lang="ru">ИÑходный код Verilog</comment>
<comment xml:lang="sk">Zdrojový kód Verilog</comment>
<comment xml:lang="sl">Datoteka izvorne kode Verilog</comment>
<comment xml:lang="sr">изворни код Верилога</comment>
@@ -30798,6 +31747,7 @@
<comment xml:lang="eu">SystemVerilog goiburua</comment>
<comment xml:lang="fi">SystemVerilog-otsake</comment>
<comment xml:lang="fr">en-tête </comment>
+ <comment xml:lang="ga">ceanntásc SystemVerilog</comment>
<comment xml:lang="gl">Cabeceiras de SystemVerilog</comment>
<comment xml:lang="he">כותרת SystemVerilog</comment>
<comment xml:lang="hr">SystemVerilog zaglavlje</comment>
@@ -30814,14 +31764,14 @@
<comment xml:lang="pl">Nagłówek SystemVerilog</comment>
<comment xml:lang="pt">cabeçalho SystemVerilog</comment>
<comment xml:lang="pt_BR">Cabeçalho de SystemVerilog</comment>
- <comment xml:lang="ru">заголовочный файл SystemVerilog</comment>
+ <comment xml:lang="ru">Заголовочный файл SystemVerilog</comment>
<comment xml:lang="sk">HlaviÄky SystemVerilog</comment>
<comment xml:lang="sl">Datoteka glave SystemVerilog</comment>
<comment xml:lang="sr">заглавље СиÑтема Верилога</comment>
<comment xml:lang="sv">SystemVerilog-headerfil</comment>
<comment xml:lang="tr">SystemVerilog başlığı</comment>
<comment xml:lang="uk">заголовки SystemVerilog</comment>
- <comment xml:lang="zh_CN">SystemVerilog 头</comment>
+ <comment xml:lang="zh_CN">SystemVerilog 头文件</comment>
<comment xml:lang="zh_TW">SystemVerilog 標頭</comment>
<sub-class-of type="text/x-verilog"/>
<glob pattern="*.svh"/>
@@ -30839,9 +31789,10 @@
<comment xml:lang="eu">SystemVerilog iturburu-kodea</comment>
<comment xml:lang="fi">SystemVerilog-lähdekoodi</comment>
<comment xml:lang="fr">code source </comment>
+ <comment xml:lang="ga">cód foinseach SystemVerilog</comment>
<comment xml:lang="gl">código fonte en SystemVerilog</comment>
<comment xml:lang="he">קוד מקור של SystemVerilog</comment>
- <comment xml:lang="hr">SystemVerilog izvorni kod</comment>
+ <comment xml:lang="hr">SystemVerilog izvorni kôd</comment>
<comment xml:lang="hu">SystemVerilog-forráskód</comment>
<comment xml:lang="ia">Codice-fonte SystemVerilog</comment>
<comment xml:lang="id">Kode sumber SystemVerilog</comment>
@@ -30855,7 +31806,7 @@
<comment xml:lang="pl">Kod źródłowy SystemVerilog</comment>
<comment xml:lang="pt">código origem SystemVerilog</comment>
<comment xml:lang="pt_BR">Código-fonte de SystemVerilog</comment>
- <comment xml:lang="ru">иÑходный код SystemVerilog</comment>
+ <comment xml:lang="ru">ИÑходный код SystemVerilog</comment>
<comment xml:lang="sk">Zdrojový kód SystemVerilog</comment>
<comment xml:lang="sl">Datoteka izvorne kode SystemVerilog</comment>
<comment xml:lang="sr">изворни код СиÑтема Верилога</comment>
@@ -30871,7 +31822,7 @@
<comment>VHDL source code</comment>
<comment xml:lang="bg">Изходен код — VHDL</comment>
<comment xml:lang="ca">codi font en VHDL</comment>
- <comment xml:lang="cs">zdrojový kód VHDL</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce VHDL</comment>
<comment xml:lang="da">VHDL-kildekode</comment>
<comment xml:lang="de">VHDL-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας VHDL</comment>
@@ -30881,9 +31832,10 @@
<comment xml:lang="eu">VHDL iturburu-kodea</comment>
<comment xml:lang="fi">VHDL-lähdekoodi</comment>
<comment xml:lang="fr">code source VHDL</comment>
+ <comment xml:lang="ga">cód foinseach VHDL</comment>
<comment xml:lang="gl">código fonte en VHDL</comment>
<comment xml:lang="he">קוד מקור של VHDL</comment>
- <comment xml:lang="hr">VHDL izvorni kod</comment>
+ <comment xml:lang="hr">VHDL izvorni kôd</comment>
<comment xml:lang="hu">VHDL-forráskód</comment>
<comment xml:lang="ia">Codice-fonte VHDL</comment>
<comment xml:lang="id">Kode sumber VHDL</comment>
@@ -30897,7 +31849,7 @@
<comment xml:lang="pl">Kod źródłowy VHDL</comment>
<comment xml:lang="pt">código origem VHDL</comment>
<comment xml:lang="pt_BR">Código-fonte VHDL</comment>
- <comment xml:lang="ru">иÑходный код VHDL</comment>
+ <comment xml:lang="ru">ИÑходный код VHDL</comment>
<comment xml:lang="sk">Zdrojový kód VHDL</comment>
<comment xml:lang="sl">Datoteka izvorne kode VHDL</comment>
<comment xml:lang="sr">ВХДЛ изворни код</comment>
@@ -30915,6 +31867,7 @@
<mime-type type="text/enriched">
<comment>enriched text document</comment>
<comment xml:lang="ar">مستند نصي مغنى</comment>
+ <comment xml:lang="ast">documentu de testu arriquecíu</comment>
<comment xml:lang="az">zəngin mətn sənədi</comment>
<comment xml:lang="be@latin">azdobleny tekstavy dakument</comment>
<comment xml:lang="bg">Документ Ñ Ð¾Ð±Ð¾Ð³Ð°Ñ‚ÐµÐ½ текÑÑ‚</comment>
@@ -30934,7 +31887,7 @@
<comment xml:lang="ga">cáipéis téacs saibhrithe</comment>
<comment xml:lang="gl">documento de texto enriquecido</comment>
<comment xml:lang="he">מסמך טקסט מועשר</comment>
- <comment xml:lang="hr">obogaćeni tekstualni dokument</comment>
+ <comment xml:lang="hr">Obogaćeni tekstovni dokument</comment>
<comment xml:lang="hu">enriched text dokumentum</comment>
<comment xml:lang="ia">Documento de texto inricchite</comment>
<comment xml:lang="id">dokumen teks diperkaya</comment>
@@ -30953,7 +31906,7 @@
<comment xml:lang="pt">documento de texto rico</comment>
<comment xml:lang="pt_BR">Documento de texto enriquecido</comment>
<comment xml:lang="ro">document text îmbogățit</comment>
- <comment xml:lang="ru">форматированный текÑтовый документ</comment>
+ <comment xml:lang="ru">Форматированный текÑтовый документ</comment>
<comment xml:lang="sk">Rozšírený textový dokument</comment>
<comment xml:lang="sl">dokument z obogatenim besedilom</comment>
<comment xml:lang="sq">Dokument teksti i pasuruar</comment>
@@ -30962,7 +31915,7 @@
<comment xml:lang="tr">zenginleÅŸtirilmiÅŸ metin belgesi</comment>
<comment xml:lang="uk">форматований текÑтовий документ</comment>
<comment xml:lang="vi">tài liệu văn bản có kiểu dáng</comment>
- <comment xml:lang="zh_CN">富文本文档</comment>
+ <comment xml:lang="zh_CN">浓缩文本文档 (ETF)</comment>
<comment xml:lang="zh_TW">è±å¯ŒåŒ–文字文件</comment>
<sub-class-of type="text/plain"/>
</mime-type>
@@ -30988,7 +31941,7 @@
<comment xml:lang="ga">leathanach cabhrach</comment>
<comment xml:lang="gl">páxina de axuda</comment>
<comment xml:lang="he">דף עזרה</comment>
- <comment xml:lang="hr">stranica pomoći</comment>
+ <comment xml:lang="hr">Stranica pomoći</comment>
<comment xml:lang="hu">súgóoldal</comment>
<comment xml:lang="ia">Pagina de adjuta</comment>
<comment xml:lang="id">halaman bantuan</comment>
@@ -31007,7 +31960,7 @@
<comment xml:lang="pt">página de ajuda</comment>
<comment xml:lang="pt_BR">Página de ajuda</comment>
<comment xml:lang="ro">pagină de ajutor</comment>
- <comment xml:lang="ru">Ñтраница Ñправки</comment>
+ <comment xml:lang="ru">Страница Ñправки</comment>
<comment xml:lang="sk">Stránka Pomocníka</comment>
<comment xml:lang="sl">stran pomoÄi</comment>
<comment xml:lang="sq">Faqe ndihme</comment>
@@ -31023,6 +31976,7 @@
<mime-type type="text/plain">
<comment>plain text document</comment>
<comment xml:lang="ar">مستند نصي مجرد</comment>
+ <comment xml:lang="ast">documentu de testu planu</comment>
<comment xml:lang="be@latin">prosty tekstavy dakument</comment>
<comment xml:lang="bg">Документ Ñ Ð½ÐµÑ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¸Ñ€Ð°Ð½ текÑÑ‚</comment>
<comment xml:lang="ca">document de text pla</comment>
@@ -31039,10 +31993,10 @@
<comment xml:lang="ga">cáipéis ghnáth-théacs</comment>
<comment xml:lang="gl">documento de texto sinxelo</comment>
<comment xml:lang="he">מסמך טקסט פשוט</comment>
- <comment xml:lang="hr">obiÄan tekstualni dokument</comment>
+ <comment xml:lang="hr">ObiÄan tekstovni dokument</comment>
<comment xml:lang="hu">egyszerű szöveg</comment>
<comment xml:lang="ia">Documento de texto simple</comment>
- <comment xml:lang="id">dokumen teks biasa</comment>
+ <comment xml:lang="id">dokumen teks polos</comment>
<comment xml:lang="it">Documento in testo semplice</comment>
<comment xml:lang="ja">平文テキストドキュメント</comment>
<comment xml:lang="kk">мәтіндік құжаты</comment>
@@ -31058,7 +32012,7 @@
<comment xml:lang="pt">documento em texto simples</comment>
<comment xml:lang="pt_BR">Documento de Texto</comment>
<comment xml:lang="ro">document text simplu</comment>
- <comment xml:lang="ru">текÑтовый документ</comment>
+ <comment xml:lang="ru">ТекÑтовый документ</comment>
<comment xml:lang="sk">ObyÄajný textový dokument</comment>
<comment xml:lang="sl">obiÄajna besedilna datoteka</comment>
<comment xml:lang="sq">Dokument në tekst të thjeshtë</comment>
@@ -31115,7 +32069,7 @@
<comment xml:lang="pt">ficheiro RDF</comment>
<comment xml:lang="pt_BR">Arquivo RDF</comment>
<comment xml:lang="ro">Fișier RDF</comment>
- <comment xml:lang="ru">файл RDF</comment>
+ <comment xml:lang="ru">Файл RDF</comment>
<comment xml:lang="sk">Súbor RDF</comment>
<comment xml:lang="sl">Datoteka RDF</comment>
<comment xml:lang="sq">File RDF</comment>
@@ -31146,6 +32100,7 @@
<comment xml:lang="es">archivo en XML OWL</comment>
<comment xml:lang="eu">OWL XML fitxategia</comment>
<comment xml:lang="fr">fichier XML OWL</comment>
+ <comment xml:lang="ga">comhad XML OWL</comment>
<comment xml:lang="hr">OWL XML datoteka</comment>
<comment xml:lang="hu">OWL XML-fájl</comment>
<comment xml:lang="ia">File XML OWL</comment>
@@ -31157,7 +32112,7 @@
<comment xml:lang="pl">Plik XML OWL</comment>
<comment xml:lang="pt">ficheiro OWL XML</comment>
<comment xml:lang="pt_BR">Arquivo OWL XML</comment>
- <comment xml:lang="ru">файл XML OWL</comment>
+ <comment xml:lang="ru">Файл XML OWL</comment>
<comment xml:lang="sk">Súbor XML OWL</comment>
<comment xml:lang="sr">ОВЛ ИкÑМЛ датотека</comment>
<comment xml:lang="sv">OWL XML-fil</comment>
@@ -31196,14 +32151,14 @@
<comment xml:lang="ga">ceanntásca ríomhphoist</comment>
<comment xml:lang="gl">cabeceiras de correo electrónico</comment>
<comment xml:lang="he">כותרת דו×״ל</comment>
- <comment xml:lang="hr">zaglavlja e-pošte</comment>
+ <comment xml:lang="hr">Zaglavlja e-pošte</comment>
<comment xml:lang="hu">levélfejléc</comment>
<comment xml:lang="ia">Capites de e-mail</comment>
- <comment xml:lang="id">tajuk email</comment>
+ <comment xml:lang="id">header email</comment>
<comment xml:lang="it">Intestazioni email</comment>
<comment xml:lang="ja">メールヘッダー</comment>
<comment xml:lang="kk">пошталық тақырыптамалары</comment>
- <comment xml:lang="ko">ì „ìž ìš°íŽ¸ í—¤ë”</comment>
+ <comment xml:lang="ko">ì „ìžë©”ì¼ í—¤ë”</comment>
<comment xml:lang="lt">el. laiško antraštės</comment>
<comment xml:lang="lv">e-pasta galvene</comment>
<comment xml:lang="ms">Pengepala emel</comment>
@@ -31215,7 +32170,7 @@
<comment xml:lang="pt">cabeçalhos de email</comment>
<comment xml:lang="pt_BR">Cabeçalhos de e-mail</comment>
<comment xml:lang="ro">antete email</comment>
- <comment xml:lang="ru">почтовые заголовки</comment>
+ <comment xml:lang="ru">Почтовые заголовки</comment>
<comment xml:lang="sk">HlaviÄky e-mailu</comment>
<comment xml:lang="sl">glava elektronske pošte</comment>
<comment xml:lang="sq">Header email</comment>
@@ -31231,6 +32186,7 @@
<mime-type type="text/richtext">
<comment>rich text document</comment>
<comment xml:lang="ar">مستند نصي غني</comment>
+ <comment xml:lang="ast">documentu de testu ricu</comment>
<comment xml:lang="az">zəngin mətn sənədi</comment>
<comment xml:lang="be@latin">azdobleny tekstavy dakument</comment>
<comment xml:lang="bg">Документ — rich text</comment>
@@ -31249,7 +32205,7 @@
<comment xml:lang="ga">cáipéis mhéith-théacs</comment>
<comment xml:lang="gl">documento do texto enriquecido</comment>
<comment xml:lang="he">מסמך טקסט עשיר</comment>
- <comment xml:lang="hr">obogaćeni tekstualni dokument</comment>
+ <comment xml:lang="hr">Obogaćeni tekstovni dokument</comment>
<comment xml:lang="hu">rich text-dokumentum</comment>
<comment xml:lang="ia">Documento de texto inricchite</comment>
<comment xml:lang="id">dokumen teks kaya</comment>
@@ -31268,7 +32224,7 @@
<comment xml:lang="pt">documento em texto rico</comment>
<comment xml:lang="pt_BR">Documento rich text</comment>
<comment xml:lang="ro">document text îmbogățit</comment>
- <comment xml:lang="ru">документ Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ñ‹Ð¼ текÑтом</comment>
+ <comment xml:lang="ru">Документ Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ñ‹Ð¼ текÑтом</comment>
<comment xml:lang="sk">Textový dokument RTF</comment>
<comment xml:lang="sl">dokument z oblikovanim besedilom</comment>
<comment xml:lang="sq">Dokument rich text</comment>
@@ -31277,7 +32233,7 @@
<comment xml:lang="tr">zengin metin belgesi</comment>
<comment xml:lang="uk">форматований текÑтовий документ</comment>
<comment xml:lang="vi">tài liệu văn bản có kiểu dáng (RTF)</comment>
- <comment xml:lang="zh_CN">RTF 丰富文本文档</comment>
+ <comment xml:lang="zh_CN">富文本文档 (RTF)</comment>
<comment xml:lang="zh_TW">è±å¯Œæ–‡å­—文件</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.rtx"/>
@@ -31319,7 +32275,7 @@
<comment xml:lang="pt">resumo RSS</comment>
<comment xml:lang="pt_BR">Resumo RSS</comment>
<comment xml:lang="ro">Rezumat RSS</comment>
- <comment xml:lang="ru">Ñводка RSS</comment>
+ <comment xml:lang="ru">Сводка RSS</comment>
<comment xml:lang="sk">Súhrn RSS</comment>
<comment xml:lang="sl">Datoteka povzetek RSS</comment>
<comment xml:lang="sq">Përmbledhje RSS</comment>
@@ -31366,7 +32322,7 @@
<comment xml:lang="it">Feed di distribuzione Atom</comment>
<comment xml:lang="ja">Atom é…信フィード</comment>
<comment xml:lang="kk">Atom жаңалықтар таÑпаÑÑ‹</comment>
- <comment xml:lang="ko">Atom ë™ê¸°í™” 피드</comment>
+ <comment xml:lang="ko">Atom ë¬¶ìŒ í”¼ë“œ</comment>
<comment xml:lang="lt">Atom sindikacijos kanalas</comment>
<comment xml:lang="lv">Atom sindikÄta barotne</comment>
<comment xml:lang="nb">Atom syndikeringsstrøm</comment>
@@ -31377,7 +32333,7 @@
<comment xml:lang="pt">feed Atom</comment>
<comment xml:lang="pt_BR">Fonte de notícias Atom</comment>
<comment xml:lang="ro">Flux agregare Atom</comment>
- <comment xml:lang="ru">лента новоÑтей Atom</comment>
+ <comment xml:lang="ru">Лента новоÑтей Atom</comment>
<comment xml:lang="sk">Kanál Atom</comment>
<comment xml:lang="sl">Sindikalni vir Atom</comment>
<comment xml:lang="sq">Feed për përhapje Atom</comment>
@@ -31386,7 +32342,7 @@
<comment xml:lang="tr">Atom besleme kaynağı</comment>
<comment xml:lang="uk">транÑлÑÑ†Ñ–Ñ Ð¿Ð¾Ð´Ð°Ñ‡ Atom</comment>
<comment xml:lang="vi">Nguồn tin tức Atom</comment>
- <comment xml:lang="zh_CN">Atom æ›´æ–°ç§å­</comment>
+ <comment xml:lang="zh_CN">Atom èšåˆç§å­</comment>
<comment xml:lang="zh_TW">Atom è¯åˆä¾›ç¨¿é¥‹æµ</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="text-html"/>
@@ -31432,7 +32388,7 @@
<comment xml:lang="pt">feed OPML</comment>
<comment xml:lang="pt_BR">Fonte de notícias OPML</comment>
<comment xml:lang="ro">Flux OPML syndication</comment>
- <comment xml:lang="ru">лента новоÑтей OPML</comment>
+ <comment xml:lang="ru">Лента новоÑтей OPML</comment>
<comment xml:lang="sk">Kanál OPML</comment>
<comment xml:lang="sl">Sindikalni vir OPML</comment>
<comment xml:lang="sq">Feed për përhapje OPML</comment>
@@ -31454,6 +32410,7 @@
<mime-type type="text/sgml">
<comment>SGML document</comment>
<comment xml:lang="ar">مستند SGML</comment>
+ <comment xml:lang="ast">Documentu SGML</comment>
<comment xml:lang="be@latin">Dakument SGML</comment>
<comment xml:lang="bg">Документ — SGML</comment>
<comment xml:lang="ca">document SGML</comment>
@@ -31491,7 +32448,7 @@
<comment xml:lang="pt">documento SGML</comment>
<comment xml:lang="pt_BR">Documento SGML</comment>
<comment xml:lang="ro">Document SGML</comment>
- <comment xml:lang="ru">документ SGML</comment>
+ <comment xml:lang="ru">Документ SGML</comment>
<comment xml:lang="sk">Dokument SGML</comment>
<comment xml:lang="sl">Dokument SGML</comment>
<comment xml:lang="sq">Dokument SGML</comment>
@@ -31511,6 +32468,7 @@
<mime-type type="text/spreadsheet">
<comment>spreadsheet interchange document</comment>
<comment xml:lang="ar">مستند تبادل الجدول</comment>
+ <comment xml:lang="ast">documentu d'intercambéu de fueyes de cálculu</comment>
<comment xml:lang="be@latin">dakument dla abmienu raźlikovymi arkušami</comment>
<comment xml:lang="bg">Документ за обмÑна между програми за електронни таблици</comment>
<comment xml:lang="ca">document d'intercanvi de full de càlcul</comment>
@@ -31545,7 +32503,7 @@
<comment xml:lang="pt">documento de troca interna de folhas de cálculo</comment>
<comment xml:lang="pt_BR">Documento de intercâmbio de planilhas</comment>
<comment xml:lang="ro">document schimb filă de calcul</comment>
- <comment xml:lang="ru">документ Spreadsheet Interchange</comment>
+ <comment xml:lang="ru">Документ Spreadsheet Interchange</comment>
<comment xml:lang="sk">Zošitový prenosový dokument</comment>
<comment xml:lang="sl">dokument izmenjeve preglednic</comment>
<comment xml:lang="sq">Dokument shkëmbimi për fletë llogaritje</comment>
@@ -31566,6 +32524,7 @@
<mime-type type="text/tab-separated-values">
<comment>TSV document</comment>
<comment xml:lang="ar">مستند TSV</comment>
+ <comment xml:lang="ast">Documentu TSV</comment>
<comment xml:lang="be@latin">Dakument TSV</comment>
<comment xml:lang="bg">Документ — TSV</comment>
<comment xml:lang="ca">document TSV</comment>
@@ -31600,7 +32559,7 @@
<comment xml:lang="pt">documento TSV</comment>
<comment xml:lang="pt_BR">Documento TSV</comment>
<comment xml:lang="ro">Document TSV</comment>
- <comment xml:lang="ru">документ TSV</comment>
+ <comment xml:lang="ru">Документ TSV</comment>
<comment xml:lang="sk">Dokument TSV</comment>
<comment xml:lang="sl">Dokument TSV</comment>
<comment xml:lang="sq">Dokument TSV</comment>
@@ -31658,7 +32617,7 @@
<comment xml:lang="tr">Graphviz DOT grafiÄŸi</comment>
<comment xml:lang="uk">граф DOT Graphviz</comment>
<comment xml:lang="vi">Biểu đồ DOT Graphviz</comment>
- <comment xml:lang="zh_CN">Graphviz DOT 科学图形</comment>
+ <comment xml:lang="zh_CN">Graphviz DOT 图形</comment>
<comment xml:lang="zh_TW">Graphviz DOT 圖</comment>
<generic-icon name="x-office-document"/>
<magic priority="50">
@@ -31673,6 +32632,7 @@
<mime-type type="text/vnd.sun.j2me.app-descriptor">
<comment>JAD document</comment>
<comment xml:lang="ar">مستند JAD</comment>
+ <comment xml:lang="ast">Documentu JAD</comment>
<comment xml:lang="be@latin">Dakument JAD</comment>
<comment xml:lang="bg">Документ — JAD</comment>
<comment xml:lang="ca">document JAD</comment>
@@ -31708,7 +32668,7 @@
<comment xml:lang="pt">documento JAD</comment>
<comment xml:lang="pt_BR">Documento JAD</comment>
<comment xml:lang="ro">Document JAD</comment>
- <comment xml:lang="ru">документ JAD</comment>
+ <comment xml:lang="ru">Документ JAD</comment>
<comment xml:lang="sk">Dokument JAD</comment>
<comment xml:lang="sl">Dokument JAD</comment>
<comment xml:lang="sq">Dokument JAD</comment>
@@ -31729,6 +32689,7 @@
<mime-type type="text/vnd.wap.wml">
<comment>WML document</comment>
<comment xml:lang="ar">مستند WML</comment>
+ <comment xml:lang="ast">Documentu WML</comment>
<comment xml:lang="az">WML sənədi</comment>
<comment xml:lang="be@latin">Dakument WML</comment>
<comment xml:lang="bg">Документ — WML</comment>
@@ -31767,7 +32728,7 @@
<comment xml:lang="pt">documento WML</comment>
<comment xml:lang="pt_BR">Documento WML</comment>
<comment xml:lang="ro">Document WML</comment>
- <comment xml:lang="ru">документ WML</comment>
+ <comment xml:lang="ru">Документ WML</comment>
<comment xml:lang="sk">Dokument WML</comment>
<comment xml:lang="sl">Dokument WML</comment>
<comment xml:lang="sq">Dokument WML</comment>
@@ -31820,7 +32781,7 @@
<comment xml:lang="pt">programa WMLScript</comment>
<comment xml:lang="pt_BR">Programa WMLScript</comment>
<comment xml:lang="ro">Program WMLScript</comment>
- <comment xml:lang="ru">Ñценарий WMLScript</comment>
+ <comment xml:lang="ru">Программа WMLScript</comment>
<comment xml:lang="sk">Program WMLScript</comment>
<comment xml:lang="sl">Programska datoteka WMLScript</comment>
<comment xml:lang="sq">Program WMLScript</comment>
@@ -31872,7 +32833,7 @@
<comment xml:lang="pt">arquivo ACE</comment>
<comment xml:lang="pt_BR">Pacote ACE</comment>
<comment xml:lang="ro">Arhivă ACE</comment>
- <comment xml:lang="ru">архив ACE</comment>
+ <comment xml:lang="ru">Ðрхив ACE</comment>
<comment xml:lang="sk">Archív ACE</comment>
<comment xml:lang="sl">Datoteka arhiva ACE</comment>
<comment xml:lang="sq">Arkiv ACE</comment>
@@ -31909,10 +32870,10 @@
<comment xml:lang="ga">cód foinseach Ada</comment>
<comment xml:lang="gl">código fonte en Ada</comment>
<comment xml:lang="he">קוד מקור Ada</comment>
- <comment xml:lang="hr">Ada izvorni kod</comment>
+ <comment xml:lang="hr">Ada izvorni kôd</comment>
<comment xml:lang="hu">Ada-forráskód</comment>
<comment xml:lang="ia">Codice-fonte Ada</comment>
- <comment xml:lang="id">Kode program Ada</comment>
+ <comment xml:lang="id">Kode sumber Ada</comment>
<comment xml:lang="it">Codice sorgente Ada</comment>
<comment xml:lang="ja">Ada ソースコード</comment>
<comment xml:lang="ka">Ada-ის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ კáƒáƒ“ი</comment>
@@ -31929,7 +32890,7 @@
<comment xml:lang="pt">código origem Ada</comment>
<comment xml:lang="pt_BR">Código-fonte Ada</comment>
<comment xml:lang="ro">Cod sursă Ada</comment>
- <comment xml:lang="ru">иÑходный код Ada</comment>
+ <comment xml:lang="ru">ИÑходный код Ada</comment>
<comment xml:lang="sk">Zdrojový kód jazyka Ada</comment>
<comment xml:lang="sl">Datoteka izvorne kode Ada</comment>
<comment xml:lang="sq">Kod burues Ada</comment>
@@ -31983,7 +32944,7 @@
<comment xml:lang="pt">lista de autores</comment>
<comment xml:lang="pt_BR">Lista de autores</comment>
<comment xml:lang="ro">listă autori</comment>
- <comment xml:lang="ru">ÑпиÑок авторов</comment>
+ <comment xml:lang="ru">СпиÑок авторов</comment>
<comment xml:lang="sk">Zoznam autorov</comment>
<comment xml:lang="sl">seznam avtorjev</comment>
<comment xml:lang="sq">Lista e autorëve</comment>
@@ -32000,6 +32961,7 @@
<mime-type type="text/x-bibtex">
<comment>BibTeX document</comment>
<comment xml:lang="ar">مستند BibTeX</comment>
+ <comment xml:lang="ast">Documentu de BibTeX</comment>
<comment xml:lang="be@latin">Dakument BibTeX</comment>
<comment xml:lang="bg">Документ — BibTeX</comment>
<comment xml:lang="ca">document BibTeX</comment>
@@ -32036,7 +32998,7 @@
<comment xml:lang="pt">documento BibTeX</comment>
<comment xml:lang="pt_BR">Documento BibTeX</comment>
<comment xml:lang="ro">Document BibTeX</comment>
- <comment xml:lang="ru">документ BibTeX</comment>
+ <comment xml:lang="ru">Документ BibTeX</comment>
<comment xml:lang="sk">Dokument BibTeX</comment>
<comment xml:lang="sl">Dokument BibTeX</comment>
<comment xml:lang="sq">Dokument BibTeX</comment>
@@ -32075,7 +33037,7 @@
<comment xml:lang="hr">C++ zaglavlje</comment>
<comment xml:lang="hu">C++ fejléc</comment>
<comment xml:lang="ia">Capite C++</comment>
- <comment xml:lang="id">Tajuk C++</comment>
+ <comment xml:lang="id">Header C++</comment>
<comment xml:lang="it">Header C++</comment>
<comment xml:lang="ja">C++ ヘッダー</comment>
<comment xml:lang="ka">C++-ის თáƒáƒ•áƒ¡áƒáƒ áƒ—ი</comment>
@@ -32091,7 +33053,7 @@
<comment xml:lang="pt">cabeçalho C++</comment>
<comment xml:lang="pt_BR">Cabeçalho C++</comment>
<comment xml:lang="ro">Antet C++</comment>
- <comment xml:lang="ru">заголовочный файл C++</comment>
+ <comment xml:lang="ru">Заголовочный файл C++</comment>
<comment xml:lang="sk">HlaviÄky jazyka C++</comment>
<comment xml:lang="sl">Datoteka glave C++</comment>
<comment xml:lang="sq">Header C++</comment>
@@ -32100,7 +33062,7 @@
<comment xml:lang="tr">C++ başlığı</comment>
<comment xml:lang="uk">файл заголовків мовою C++</comment>
<comment xml:lang="vi">Phần đầu mã nguồn C++</comment>
- <comment xml:lang="zh_CN">C++ æºä»£ç å¤´æ–‡ä»¶</comment>
+ <comment xml:lang="zh_CN">C++ 头文件</comment>
<comment xml:lang="zh_TW">C++ 標頭檔</comment>
<sub-class-of type="text/x-chdr"/>
<glob pattern="*.hh"/>
@@ -32115,7 +33077,7 @@
<comment xml:lang="be@latin">KryniÄny kod C++</comment>
<comment xml:lang="bg">Изходен код — C++</comment>
<comment xml:lang="ca">codi font en C++</comment>
- <comment xml:lang="cs">zdrojový kód C++</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce C++</comment>
<comment xml:lang="da">C++-kildekode</comment>
<comment xml:lang="de">C++-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας C++</comment>
@@ -32129,10 +33091,10 @@
<comment xml:lang="ga">cód foinseach C++</comment>
<comment xml:lang="gl">código fonte de C++</comment>
<comment xml:lang="he">קוד מקור של C++‎</comment>
- <comment xml:lang="hr">C++ izvorni kod</comment>
+ <comment xml:lang="hr">C++ izvorni kôd</comment>
<comment xml:lang="hu">C++-forráskód</comment>
<comment xml:lang="ia">Codice-fonte C++</comment>
- <comment xml:lang="id">Kode program C++</comment>
+ <comment xml:lang="id">Kode sumber C++</comment>
<comment xml:lang="it">Codice sorgente C++</comment>
<comment xml:lang="ja">C++ ソースコード</comment>
<comment xml:lang="ka">C++-ის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ კáƒáƒ“ი</comment>
@@ -32149,7 +33111,7 @@
<comment xml:lang="pt">código origem C++</comment>
<comment xml:lang="pt_BR">Código-fonte C++</comment>
<comment xml:lang="ro">Cod sursă C++</comment>
- <comment xml:lang="ru">иÑходный код C++</comment>
+ <comment xml:lang="ru">ИÑходный код C++</comment>
<comment xml:lang="sk">Zdrojový kód jazyka C++</comment>
<comment xml:lang="sl">Datoteka izvorne kode C++</comment>
<comment xml:lang="sq">Kod burues C++</comment>
@@ -32170,6 +33132,7 @@
<mime-type type="text/x-changelog">
<comment>ChangeLog document</comment>
<comment xml:lang="ar">مستند ChangeLog</comment>
+ <comment xml:lang="ast">Documentu de rexistru de cambeos</comment>
<comment xml:lang="be@latin">Dakument zafiksavanych źmienaŭ ChangeLog</comment>
<comment xml:lang="bg">Дневник за промени — ChangeLog</comment>
<comment xml:lang="ca">document de registre de canvis</comment>
@@ -32186,7 +33149,7 @@
<comment xml:lang="ga">cáipéis ChangeLog</comment>
<comment xml:lang="gl">documento Changelog</comment>
<comment xml:lang="he">מסמך של ChangeLog</comment>
- <comment xml:lang="hr">Dokument zaspisa promjena</comment>
+ <comment xml:lang="hr">Dokument zapisa promjena</comment>
<comment xml:lang="hu">ChangeLog dokumentum</comment>
<comment xml:lang="ia">Lista de cambiamentos</comment>
<comment xml:lang="id">Dokumen ChangeLog</comment>
@@ -32205,11 +33168,11 @@
<comment xml:lang="pt">documento ChangeLog</comment>
<comment xml:lang="pt_BR">Documento ChangeLog</comment>
<comment xml:lang="ro">Document ChangeLog</comment>
- <comment xml:lang="ru">протокол изменений</comment>
+ <comment xml:lang="ru">Протокол изменений</comment>
<comment xml:lang="sk">Dokument ChangeLog</comment>
<comment xml:lang="sl">Dokument ChangeLog</comment>
<comment xml:lang="sq">Dokument ChangeLog</comment>
- <comment xml:lang="sr">Ченџ Лог документ</comment>
+ <comment xml:lang="sr">документ дневника измена</comment>
<comment xml:lang="sv">Ändringsloggsdokument</comment>
<comment xml:lang="tr">Değişim Günlüğü belgesi</comment>
<comment xml:lang="uk">документ ChangeLog</comment>
@@ -32241,7 +33204,7 @@
<comment xml:lang="hr">C zaglavlje</comment>
<comment xml:lang="hu">C fejléc</comment>
<comment xml:lang="ia">Capite C</comment>
- <comment xml:lang="id">Tajuk C</comment>
+ <comment xml:lang="id">Header C</comment>
<comment xml:lang="it">Header C</comment>
<comment xml:lang="ja">C ヘッダー</comment>
<comment xml:lang="ka">C-ის თáƒáƒ•áƒ¡áƒáƒ áƒ—ი</comment>
@@ -32257,7 +33220,7 @@
<comment xml:lang="pt">cabeçalho C</comment>
<comment xml:lang="pt_BR">Cabeçalho C</comment>
<comment xml:lang="ro">Antet C</comment>
- <comment xml:lang="ru">заголовочный файл C</comment>
+ <comment xml:lang="ru">Заголовочный файл C</comment>
<comment xml:lang="sk">HlaviÄky jazyka C</comment>
<comment xml:lang="sl">Datoteka glave C</comment>
<comment xml:lang="sq">Header C</comment>
@@ -32291,10 +33254,10 @@
<comment xml:lang="ga">cód foinseach CMake</comment>
<comment xml:lang="gl">código fonte de CMake</comment>
<comment xml:lang="he">קוד מקור של CMake</comment>
- <comment xml:lang="hr">CMake izvorni kod</comment>
+ <comment xml:lang="hr">CMake izvorni kôd</comment>
<comment xml:lang="hu">CMake-forráskód</comment>
<comment xml:lang="ia">Codice-fonte CMake</comment>
- <comment xml:lang="id">Kode program CMake</comment>
+ <comment xml:lang="id">Kode sumber CMake</comment>
<comment xml:lang="it">Codice sorgente CMake</comment>
<comment xml:lang="ja">CMake ソースコード</comment>
<comment xml:lang="ka">CMake-ის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ კáƒáƒ“ი</comment>
@@ -32310,7 +33273,7 @@
<comment xml:lang="pt">código origem CMake</comment>
<comment xml:lang="pt_BR">Código-fonte CMake</comment>
<comment xml:lang="ro">Cod sursă CMake</comment>
- <comment xml:lang="ru">иÑходный код CMake</comment>
+ <comment xml:lang="ru">ИÑходный код CMake</comment>
<comment xml:lang="sk">Zdrojový kód CMake</comment>
<comment xml:lang="sl">Datoteka izvorne kode CMake</comment>
<comment xml:lang="sq">Kod burues CMake</comment>
@@ -32328,6 +33291,7 @@
<mime-type type="text/csv">
<comment>CSV document</comment>
<comment xml:lang="ar">مستند CSV</comment>
+ <comment xml:lang="ast">Documentu CVS</comment>
<comment xml:lang="be@latin">Dakument CSV</comment>
<comment xml:lang="bg">Документ — CSV</comment>
<comment xml:lang="ca">document CSV</comment>
@@ -32364,7 +33328,7 @@
<comment xml:lang="pt">documento CSV</comment>
<comment xml:lang="pt_BR">Documento CSV</comment>
<comment xml:lang="ro">Document CSV</comment>
- <comment xml:lang="ru">документ CSV</comment>
+ <comment xml:lang="ru">Документ CSV</comment>
<comment xml:lang="sk">Dokument CSV</comment>
<comment xml:lang="sl">Dokument CSV</comment>
<comment xml:lang="sq">Dokument CSV</comment>
@@ -32384,6 +33348,7 @@
</mime-type>
<mime-type type="text/csv-schema">
<comment>CSV Schema document</comment>
+ <comment xml:lang="ast">Documentu d'esquema CSV</comment>
<comment xml:lang="ca">document Schema de CSV</comment>
<comment xml:lang="cs">dokument schématu CSV</comment>
<comment xml:lang="da">CSV Schema-dokument</comment>
@@ -32392,6 +33357,8 @@
<comment xml:lang="es">documento esquemático CSV</comment>
<comment xml:lang="eu">CSV Schema dokumentua</comment>
<comment xml:lang="fr">document schéma CSV</comment>
+ <comment xml:lang="ga">cáipéis scéimre CSV</comment>
+ <comment xml:lang="he">מסמך פריסת CSV</comment>
<comment xml:lang="hr">CSV Shema dokument</comment>
<comment xml:lang="hu">CSV sémadokumentum</comment>
<comment xml:lang="ia">Documento CSV Schema</comment>
@@ -32402,7 +33369,7 @@
<comment xml:lang="pl">Dokument schematu CSV</comment>
<comment xml:lang="pt">documento CSV Schema</comment>
<comment xml:lang="pt_BR">Documento CSV Schema</comment>
- <comment xml:lang="ru">документ CSV Schema</comment>
+ <comment xml:lang="ru">Документ CSV Schema</comment>
<comment xml:lang="sk">Dokument schémy CSV</comment>
<comment xml:lang="sr">документ ЦСВ шеме</comment>
<comment xml:lang="sv">CSV Schema-dokument</comment>
@@ -32418,6 +33385,7 @@
<mime-type type="text/x-copying">
<comment>license terms</comment>
<comment xml:lang="ar">شروط الترخيص</comment>
+ <comment xml:lang="ast">términos de llicencia</comment>
<comment xml:lang="be@latin">licenzijnyja Å­movy</comment>
<comment xml:lang="bg">Лицензни уÑловиÑ</comment>
<comment xml:lang="ca">condicions de llicència</comment>
@@ -32434,7 +33402,7 @@
<comment xml:lang="ga">téarmaí ceadúnais</comment>
<comment xml:lang="gl">termos de licenza</comment>
<comment xml:lang="he">תנ××™ רישיון</comment>
- <comment xml:lang="hr">uvjeti licence</comment>
+ <comment xml:lang="hr">Uvjeti licence</comment>
<comment xml:lang="hu">licencfeltételek</comment>
<comment xml:lang="ia">Conditiones de licentia</comment>
<comment xml:lang="id">persyaratan lisensi</comment>
@@ -32452,7 +33420,7 @@
<comment xml:lang="pt">termos de licença</comment>
<comment xml:lang="pt_BR">Termos de licença</comment>
<comment xml:lang="ro">termeni de licență</comment>
- <comment xml:lang="ru">лицензионное Ñоглашение</comment>
+ <comment xml:lang="ru">Лицензионное Ñоглашение</comment>
<comment xml:lang="sk">LicenÄné podmienky</comment>
<comment xml:lang="sl">pogoji in dovoljenja uporabe</comment>
<comment xml:lang="sq">Kushte liçence</comment>
@@ -32469,6 +33437,7 @@
<mime-type type="text/x-credits">
<comment>author credits</comment>
<comment xml:lang="ar">شكر وتقدير المؤلÙ</comment>
+ <comment xml:lang="ast">creitos del autor</comment>
<comment xml:lang="be@latin">zasłuhi aŭtara</comment>
<comment xml:lang="bg">БлагодарноÑти към авторите</comment>
<comment xml:lang="ca">atribucions d'autor</comment>
@@ -32502,7 +33471,7 @@
<comment xml:lang="pt">créditos de autor</comment>
<comment xml:lang="pt_BR">Créditos do autor</comment>
<comment xml:lang="ro">mulțumiri autori</comment>
- <comment xml:lang="ru">авторы программы</comment>
+ <comment xml:lang="ru">Ðвторы программы</comment>
<comment xml:lang="sk">Autorské zásluhy</comment>
<comment xml:lang="sl">avtorske zasluge</comment>
<comment xml:lang="sq">Kreditë e autorëve</comment>
@@ -32522,7 +33491,7 @@
<comment xml:lang="be@latin">KryniÄny kod C</comment>
<comment xml:lang="bg">Изходен код — C</comment>
<comment xml:lang="ca">codi font en C</comment>
- <comment xml:lang="cs">zdrojový kód C</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce C</comment>
<comment xml:lang="da">C-kildekode</comment>
<comment xml:lang="de">C-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας C</comment>
@@ -32536,10 +33505,10 @@
<comment xml:lang="ga">cód foinseach C</comment>
<comment xml:lang="gl">código fonte en C</comment>
<comment xml:lang="he">קוד מקור של C</comment>
- <comment xml:lang="hr">C izvorni kod</comment>
+ <comment xml:lang="hr">C izvorni kôd</comment>
<comment xml:lang="hu">C-forráskód</comment>
<comment xml:lang="ia">Codice-fonte C</comment>
- <comment xml:lang="id">Kode program C</comment>
+ <comment xml:lang="id">Kode sumber C</comment>
<comment xml:lang="it">Codice sorgente C</comment>
<comment xml:lang="ja">C ソースコード</comment>
<comment xml:lang="ka">C-ის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ კáƒáƒ“ი</comment>
@@ -32556,7 +33525,7 @@
<comment xml:lang="pt">código origem C</comment>
<comment xml:lang="pt_BR">Código-fonte C</comment>
<comment xml:lang="ro">Cod sursă C</comment>
- <comment xml:lang="ru">иÑходный код C</comment>
+ <comment xml:lang="ru">ИÑходный код C</comment>
<comment xml:lang="sk">Zdrojový kód jazyka C</comment>
<comment xml:lang="sl">Datoteka izvorne kode C</comment>
<comment xml:lang="sq">Kod burues C</comment>
@@ -32582,7 +33551,7 @@
<comment xml:lang="be@latin">KryniÄny kod C#</comment>
<comment xml:lang="bg">Изходен код — C#</comment>
<comment xml:lang="ca">codi font en C#</comment>
- <comment xml:lang="cs">zdrojový kód C#</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce C#</comment>
<comment xml:lang="da">C#-kildekode</comment>
<comment xml:lang="de">C#-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας C#</comment>
@@ -32596,10 +33565,10 @@
<comment xml:lang="ga">cód foinseach C#</comment>
<comment xml:lang="gl">código fonte en C#</comment>
<comment xml:lang="he">קוד מקור של C#‎</comment>
- <comment xml:lang="hr">C# izvorni kod</comment>
+ <comment xml:lang="hr">C# izvorni kôd</comment>
<comment xml:lang="hu">C#-forráskód</comment>
<comment xml:lang="ia">Codice-fonte C#</comment>
- <comment xml:lang="id">Kode program C#</comment>
+ <comment xml:lang="id">Kode sumber C#</comment>
<comment xml:lang="it">Codice sorgente C#</comment>
<comment xml:lang="ja">C# ソースコード</comment>
<comment xml:lang="ka">C#-ის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ კáƒáƒ“ი</comment>
@@ -32616,7 +33585,7 @@
<comment xml:lang="pt">código origem C#</comment>
<comment xml:lang="pt_BR">Código-fonte C#</comment>
<comment xml:lang="ro">Cod sursă C#</comment>
- <comment xml:lang="ru">иÑходный код C#</comment>
+ <comment xml:lang="ru">ИÑходный код C#</comment>
<comment xml:lang="sk">Zdrojový kód jazyka C#</comment>
<comment xml:lang="sl">Datoteka izvorne kode C#</comment>
<comment xml:lang="sq">Kod burues C#</comment>
@@ -32636,7 +33605,7 @@
<comment xml:lang="be@latin">KryniÄny kod Vala</comment>
<comment xml:lang="bg">Изходен код — Vala</comment>
<comment xml:lang="ca">codi font en Vala</comment>
- <comment xml:lang="cs">zdrojový kód Vala</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Vala</comment>
<comment xml:lang="da">Valakildekode</comment>
<comment xml:lang="de">Vala-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας Vala</comment>
@@ -32650,10 +33619,10 @@
<comment xml:lang="ga">cód foinseach Vala</comment>
<comment xml:lang="gl">código fonte en Vala</comment>
<comment xml:lang="he">קוד מקור של Vala</comment>
- <comment xml:lang="hr">Vala izvorni kod</comment>
+ <comment xml:lang="hr">Vala izvorni kôd</comment>
<comment xml:lang="hu">Vala forráskód</comment>
<comment xml:lang="ia">Codice-fonte Vala</comment>
- <comment xml:lang="id">Kode program Vala</comment>
+ <comment xml:lang="id">Kode sumber Vala</comment>
<comment xml:lang="it">Codice sorgente Vala</comment>
<comment xml:lang="ja">Vala ソースコード</comment>
<comment xml:lang="kk">Vala баÑтапқы коды</comment>
@@ -32668,7 +33637,7 @@
<comment xml:lang="pt">código origem Vala</comment>
<comment xml:lang="pt_BR">Código-fonte Vala</comment>
<comment xml:lang="ro">Cod sursă Vala</comment>
- <comment xml:lang="ru">иÑходный код Vala</comment>
+ <comment xml:lang="ru">ИÑходный код Vala</comment>
<comment xml:lang="sk">Zdrojový kód Vala</comment>
<comment xml:lang="sl">Datoteka izvorne kode Vala</comment>
<comment xml:lang="sq">Kod burues Vala</comment>
@@ -32697,9 +33666,10 @@
<comment xml:lang="eu">OOC iturburu-kodea</comment>
<comment xml:lang="fi">OOC-lähdekoodi</comment>
<comment xml:lang="fr">source code OOC</comment>
+ <comment xml:lang="ga">cód foinseach OOC</comment>
<comment xml:lang="gl">código fonte de OOC</comment>
<comment xml:lang="he">קוד מקור של OOC</comment>
- <comment xml:lang="hr">OOC izvorni kod</comment>
+ <comment xml:lang="hr">OOC izvorni kôd</comment>
<comment xml:lang="hu">OOC forráskód</comment>
<comment xml:lang="ia">Codice-fonte OCC</comment>
<comment xml:lang="id">Kode sumber OOC</comment>
@@ -32714,14 +33684,14 @@
<comment xml:lang="pl">Kod źródłowy OOC</comment>
<comment xml:lang="pt">código origem OOC</comment>
<comment xml:lang="pt_BR">Código-fonte OOC</comment>
- <comment xml:lang="ru">иÑходный код OOC</comment>
+ <comment xml:lang="ru">ИÑходный код OOC</comment>
<comment xml:lang="sk">Zdrojový kód OOC</comment>
<comment xml:lang="sl">Izvorna koda OOC</comment>
<comment xml:lang="sr">ООЦ изворни ко̂д</comment>
<comment xml:lang="sv">OOC-källkod</comment>
<comment xml:lang="tr">OOC kaynak kodu</comment>
<comment xml:lang="uk">вихідний код мовою OOC</comment>
- <comment xml:lang="zh_CN">OOC</comment>
+ <comment xml:lang="zh_CN">OOC æºä»£ç </comment>
<comment xml:lang="zh_TW">OOC æºç¢¼</comment>
<acronym>OOC</acronym>
<expanded-acronym>Out Of Class</expanded-acronym>
@@ -32770,7 +33740,7 @@
<comment xml:lang="pt">script DCL</comment>
<comment xml:lang="pt_BR">Script DCL</comment>
<comment xml:lang="ro">Script DCL</comment>
- <comment xml:lang="ru">Ñценарий DCL</comment>
+ <comment xml:lang="ru">Сценарий DCL</comment>
<comment xml:lang="sk">Skript DCL</comment>
<comment xml:lang="sl">Skriptna datoteka DCL</comment>
<comment xml:lang="sq">Script DCL</comment>
@@ -32789,6 +33759,7 @@
<mime-type type="text/x-dsl">
<comment>DSSSL document</comment>
<comment xml:lang="ar">مستند DSSSL</comment>
+ <comment xml:lang="ast">Documentu DSSSL</comment>
<comment xml:lang="az">DSSSL sənədi</comment>
<comment xml:lang="be@latin">Dakument DSSSL</comment>
<comment xml:lang="bg">Документ — DSSSL</comment>
@@ -32828,7 +33799,7 @@
<comment xml:lang="pt">documento DSSSL</comment>
<comment xml:lang="pt_BR">Documento DSSSL</comment>
<comment xml:lang="ro">Document DSSSL</comment>
- <comment xml:lang="ru">документ DSSSL</comment>
+ <comment xml:lang="ru">Документ DSSSL</comment>
<comment xml:lang="sk">Dokument DSSSL</comment>
<comment xml:lang="sl">Dokument DSSSL</comment>
<comment xml:lang="sq">Dokument DSSSL</comment>
@@ -32850,7 +33821,7 @@
<comment xml:lang="be@latin">KryniÄny kod D</comment>
<comment xml:lang="bg">Изходен код — D</comment>
<comment xml:lang="ca">codi font en D</comment>
- <comment xml:lang="cs">zdrojový kód D</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce D</comment>
<comment xml:lang="da">D-kildekode</comment>
<comment xml:lang="de">D-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας D</comment>
@@ -32864,10 +33835,10 @@
<comment xml:lang="ga">cód foinseach D</comment>
<comment xml:lang="gl">código fonte de D</comment>
<comment xml:lang="he">קוד מקור לשפת D</comment>
- <comment xml:lang="hr">D izvorni kod</comment>
+ <comment xml:lang="hr">D izvorni kôd</comment>
<comment xml:lang="hu">D-forráskód</comment>
<comment xml:lang="ia">Codice-fonte D</comment>
- <comment xml:lang="id">Kode program D</comment>
+ <comment xml:lang="id">Kode sumber D</comment>
<comment xml:lang="it">Codice sorgente D</comment>
<comment xml:lang="ja">D ソースコード</comment>
<comment xml:lang="ka">D-ის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ კáƒáƒ“ი</comment>
@@ -32883,7 +33854,7 @@
<comment xml:lang="pt">código origem D</comment>
<comment xml:lang="pt_BR">Código-fonte D</comment>
<comment xml:lang="ro">Cod sursă D</comment>
- <comment xml:lang="ru">иÑходный код D</comment>
+ <comment xml:lang="ru">ИÑходный код D</comment>
<comment xml:lang="sk">Zdrojový kód jazyka D</comment>
<comment xml:lang="sl">Datoteka izvorne kode D</comment>
<comment xml:lang="sq">Kod burues D</comment>
@@ -32937,7 +33908,7 @@
<comment xml:lang="pt">ficheiro DTD</comment>
<comment xml:lang="pt_BR">Arquivo DTD</comment>
<comment xml:lang="ro">Fișier DTD</comment>
- <comment xml:lang="ru">файл DTD</comment>
+ <comment xml:lang="ru">Файл DTD</comment>
<comment xml:lang="sk">Súbor DTD</comment>
<comment xml:lang="sl">Datoteka DTD</comment>
<comment xml:lang="sq">File DTD</comment>
@@ -32961,7 +33932,7 @@
<comment xml:lang="be@latin">KryniÄny kod Eiffel</comment>
<comment xml:lang="bg">Изходен код — Eiffel</comment>
<comment xml:lang="ca">codi font en Eiffel</comment>
- <comment xml:lang="cs">zdrojový kód Eiffel</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Eiffel</comment>
<comment xml:lang="da">Eiffelkildekode</comment>
<comment xml:lang="de">Eiffel-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας Eiffel</comment>
@@ -32975,10 +33946,10 @@
<comment xml:lang="ga">cód foinseach Eiffel</comment>
<comment xml:lang="gl">código fone de Eiffel</comment>
<comment xml:lang="he">קוד מקור של Eiffel</comment>
- <comment xml:lang="hr">Eiffel izvorni kod</comment>
+ <comment xml:lang="hr">Eiffel izvorni kôd</comment>
<comment xml:lang="hu">Eiffel forráskód</comment>
<comment xml:lang="ia">Codice-fonte Eiffel</comment>
- <comment xml:lang="id">Kode program Eiffel</comment>
+ <comment xml:lang="id">Kode sumber Eiffel</comment>
<comment xml:lang="it">Codice sorgente Eiffel</comment>
<comment xml:lang="ja">Eiffel ソースコード</comment>
<comment xml:lang="ka">Eiffel-ის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ კáƒáƒ“ი</comment>
@@ -32994,7 +33965,7 @@
<comment xml:lang="pt">código origem Eiffel</comment>
<comment xml:lang="pt_BR">Código-fonte Eiffel</comment>
<comment xml:lang="ro">Cod sursă Eiffel</comment>
- <comment xml:lang="ru">иÑходный код Eiffel</comment>
+ <comment xml:lang="ru">ИÑходный код Eiffel</comment>
<comment xml:lang="sk">Zdrojový kód Eiffel</comment>
<comment xml:lang="sl">Datoteka izvorne kode Eiffel</comment>
<comment xml:lang="sq">Kod burues Eiffel</comment>
@@ -33031,7 +34002,7 @@
<comment xml:lang="ga">cód foinseach Emacs Lisp</comment>
<comment xml:lang="gl">código fonte de Emacs Lisp</comment>
<comment xml:lang="he">קוד מקור של Emcas Lisp</comment>
- <comment xml:lang="hr">Emacs Lisp izvorni kod</comment>
+ <comment xml:lang="hr">Emacs Lisp izvorni kôd</comment>
<comment xml:lang="hu">Emacs Lisp-forráskód</comment>
<comment xml:lang="ia">Codice-fonte Lisp de Emacs</comment>
<comment xml:lang="id">Kode sumber Emacs Lisp</comment>
@@ -33051,7 +34022,7 @@
<comment xml:lang="pt">código origem Emacs Lisp</comment>
<comment xml:lang="pt_BR">Código-fonte Lisp do Emacs</comment>
<comment xml:lang="ro">Cod sursă Emacs Lisp</comment>
- <comment xml:lang="ru">иÑходный код Emacs Lisp</comment>
+ <comment xml:lang="ru">ИÑходный код Emacs Lisp</comment>
<comment xml:lang="sk">Zdrojový kód Emacs Lisp</comment>
<comment xml:lang="sl">Datoteka izvorne kode Emacs Lisp</comment>
<comment xml:lang="sq">Kod burues Emacs Lisp</comment>
@@ -33075,7 +34046,7 @@
<comment xml:lang="be@latin">KryniÄny kod Erlang</comment>
<comment xml:lang="bg">Изходен код — Erlang</comment>
<comment xml:lang="ca">codi font en Erlang</comment>
- <comment xml:lang="cs">zdrojový kód Erlang</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Erlang</comment>
<comment xml:lang="da">Erlangkildekode</comment>
<comment xml:lang="de">Erlang-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας Erlang</comment>
@@ -33089,10 +34060,10 @@
<comment xml:lang="ga">cód foinseach Erlang</comment>
<comment xml:lang="gl">código fonte de Erlang</comment>
<comment xml:lang="he">קוד מקור של Erlang</comment>
- <comment xml:lang="hr">Erlang izvorni kod</comment>
+ <comment xml:lang="hr">Erlang izvorni kôd</comment>
<comment xml:lang="hu">Erlang forráskód</comment>
<comment xml:lang="ia">Codice-fonte Erlang</comment>
- <comment xml:lang="id">Kode program Erlang</comment>
+ <comment xml:lang="id">Kode sumber Erlang</comment>
<comment xml:lang="it">Codice sorgente Erlang</comment>
<comment xml:lang="ja">Erlang ソースコード</comment>
<comment xml:lang="ka">Erlang-ის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ კáƒáƒ“ი</comment>
@@ -33108,7 +34079,7 @@
<comment xml:lang="pt">código origem Erlang</comment>
<comment xml:lang="pt_BR">Código-fonte Erlang</comment>
<comment xml:lang="ro">Cod sursă Erlang</comment>
- <comment xml:lang="ru">иÑходный код Erlang</comment>
+ <comment xml:lang="ru">ИÑходный код Erlang</comment>
<comment xml:lang="sk">Zdrojový kód Erlang</comment>
<comment xml:lang="sl">Datoteka izvorne kode Erlang</comment>
<comment xml:lang="sq">Kod burues Erlang</comment>
@@ -33129,7 +34100,7 @@
<comment xml:lang="be@latin">KryniÄny kod Fortran</comment>
<comment xml:lang="bg">Изходен код — Fortran</comment>
<comment xml:lang="ca">codi font en Fortran</comment>
- <comment xml:lang="cs">zdrojový kód Fortran</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Fortran</comment>
<comment xml:lang="cy">Ffynhonnell rhaglen FORTRAN</comment>
<comment xml:lang="da">Fortrankildekode</comment>
<comment xml:lang="de">Fortran-Quelltext</comment>
@@ -33144,10 +34115,10 @@
<comment xml:lang="ga">cód foinseach Fortran</comment>
<comment xml:lang="gl">código fonte de Fortran</comment>
<comment xml:lang="he">קוד מקור של Fortran</comment>
- <comment xml:lang="hr">Fortran izvorni kod</comment>
+ <comment xml:lang="hr">Fortran izvorni kôd</comment>
<comment xml:lang="hu">Fortran-forráskód</comment>
<comment xml:lang="ia">Codice-fonte Fortran</comment>
- <comment xml:lang="id">Kode program Fortran</comment>
+ <comment xml:lang="id">Kode sumber Fortran</comment>
<comment xml:lang="it">Codice sorgente Fortran</comment>
<comment xml:lang="ja">Fortran ソースコード</comment>
<comment xml:lang="ka">Fortran-ის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ კáƒáƒ“ი</comment>
@@ -33164,7 +34135,7 @@
<comment xml:lang="pt">código origem Fortran</comment>
<comment xml:lang="pt_BR">Código-fonte Fortran</comment>
<comment xml:lang="ro">Cod sursă Fortran</comment>
- <comment xml:lang="ru">иÑходный код Fortran</comment>
+ <comment xml:lang="ru">ИÑходный код Fortran</comment>
<comment xml:lang="sk">Zdrojový kód Fortran</comment>
<comment xml:lang="sl">Datoteka izvorne kode Fortran</comment>
<comment xml:lang="sq">Kod burues Fortran</comment>
@@ -33193,10 +34164,12 @@
<comment xml:lang="eu">Genie iturburu-kodea</comment>
<comment xml:lang="fi">Genie-lähdekoodi</comment>
<comment xml:lang="fr">code source Genie</comment>
+ <comment xml:lang="ga">cód foinseach Genie</comment>
+ <comment xml:lang="he">קוד מקור של Genie</comment>
<comment xml:lang="hr">Genie izvorni kôd</comment>
<comment xml:lang="hu">Genie forráskód</comment>
<comment xml:lang="ia">Codice-fonte Genie</comment>
- <comment xml:lang="id">Kode program Genie</comment>
+ <comment xml:lang="id">Kode sumber Genie</comment>
<comment xml:lang="it">Codice sorgente Genie</comment>
<comment xml:lang="kk">Genie баÑтапқы коды</comment>
<comment xml:lang="ko">Genie 소스 코드</comment>
@@ -33204,7 +34177,7 @@
<comment xml:lang="pl">Kod źródłowy Genie</comment>
<comment xml:lang="pt">código origem Genie</comment>
<comment xml:lang="pt_BR">Código-fonte Genie</comment>
- <comment xml:lang="ru">иÑходный код Genie</comment>
+ <comment xml:lang="ru">ИÑходный код Genie</comment>
<comment xml:lang="sk">Zdrojový kód Genie</comment>
<comment xml:lang="sl">Izvorna koda Genie</comment>
<comment xml:lang="sr">Гение изворни ко̂д</comment>
@@ -33220,6 +34193,7 @@
<mime-type type="text/x-gettext-translation">
<comment>translation file</comment>
<comment xml:lang="ar">مل٠الترجمة</comment>
+ <comment xml:lang="ast">ficheru de traducción</comment>
<comment xml:lang="be@latin">fajł pierakładu</comment>
<comment xml:lang="bg">Превод</comment>
<comment xml:lang="ca">fitxer de traducció</comment>
@@ -33234,10 +34208,10 @@
<comment xml:lang="fi">käännöstiedosto</comment>
<comment xml:lang="fo">týðingarfíla</comment>
<comment xml:lang="fr">fichier de traduction</comment>
- <comment xml:lang="ga">comhad aistrithe</comment>
+ <comment xml:lang="ga">comhad aistriúcháin</comment>
<comment xml:lang="gl">ficheiro de tradución</comment>
<comment xml:lang="he">קובץ תרגו×</comment>
- <comment xml:lang="hr">datoteka prijevoda</comment>
+ <comment xml:lang="hr">Datoteka prijevoda</comment>
<comment xml:lang="hu">fordítási fájl</comment>
<comment xml:lang="ia">File de traduction</comment>
<comment xml:lang="id">berkas terjemahan</comment>
@@ -33256,7 +34230,7 @@
<comment xml:lang="pt">ficheiro de tradução</comment>
<comment xml:lang="pt_BR">Arquivo de tradução</comment>
<comment xml:lang="ro">fișier traducere</comment>
- <comment xml:lang="ru">файл переводов</comment>
+ <comment xml:lang="ru">Файл переводов</comment>
<comment xml:lang="sk">Súbor prekladu</comment>
<comment xml:lang="sl">datoteka prevoda programa</comment>
<comment xml:lang="sq">File përkthimesh</comment>
@@ -33265,7 +34239,7 @@
<comment xml:lang="tr">çeviri dosyası</comment>
<comment xml:lang="uk">файл перекладу</comment>
<comment xml:lang="vi">tập tin dịch</comment>
- <comment xml:lang="zh_CN">消æ¯ç¿»è¯‘文件</comment>
+ <comment xml:lang="zh_CN">翻译文件</comment>
<comment xml:lang="zh_TW">翻譯檔</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.po"/>
@@ -33275,6 +34249,7 @@
<mime-type type="text/x-gettext-translation-template">
<comment>translation template</comment>
<comment xml:lang="ar">قالب الترجمة</comment>
+ <comment xml:lang="ast">plantía de traducción</comment>
<comment xml:lang="be@latin">šablon dla pierakładu</comment>
<comment xml:lang="bg">Шаблон за преводи</comment>
<comment xml:lang="ca">plantilla de traducció</comment>
@@ -33289,10 +34264,10 @@
<comment xml:lang="fi">käännösmalli</comment>
<comment xml:lang="fo">týðingarformur</comment>
<comment xml:lang="fr">modèle de traduction</comment>
- <comment xml:lang="ga">teimpléad aistrithe</comment>
+ <comment xml:lang="ga">teimpléad aistriúcháin</comment>
<comment xml:lang="gl">plantilla de tradución</comment>
<comment xml:lang="he">תבנית תרגו×</comment>
- <comment xml:lang="hr">predložak prijevoda</comment>
+ <comment xml:lang="hr">Predložak prijevoda</comment>
<comment xml:lang="hu">fordítási sablon</comment>
<comment xml:lang="ia">Patrono de traduction</comment>
<comment xml:lang="id">templat terjemahan</comment>
@@ -33311,7 +34286,7 @@
<comment xml:lang="pt">modelo de tradução</comment>
<comment xml:lang="pt_BR">Modelo de tradução</comment>
<comment xml:lang="ro">șablon de traducere</comment>
- <comment xml:lang="ru">шаблон переводов</comment>
+ <comment xml:lang="ru">Шаблон переводов</comment>
<comment xml:lang="sk">Šablóna prekladu</comment>
<comment xml:lang="sl">predloga datoteke prevoda programa</comment>
<comment xml:lang="sq">Model përkthimesh</comment>
@@ -33320,7 +34295,7 @@
<comment xml:lang="tr">çeviri şablonu</comment>
<comment xml:lang="uk">шаблон перекладу</comment>
<comment xml:lang="vi">mẫu dịch</comment>
- <comment xml:lang="zh_CN">消æ¯ç¿»è¯‘模æ¿</comment>
+ <comment xml:lang="zh_CN">翻译模æ¿</comment>
<comment xml:lang="zh_TW">翻譯模版</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.pot"/>
@@ -33332,18 +34307,27 @@
<mime-type type="text/x-gherkin">
<comment>feature specification in Gherkin format</comment>
<comment xml:lang="ca">especificació de funcionalitat en format Gherkin</comment>
+ <comment xml:lang="cs">specifikace vlastností ve formátu Gherkin</comment>
<comment xml:lang="da">funktionspecifikation i Gherkin-format</comment>
<comment xml:lang="de">Funktionsspezifikation im Gherkin-Format</comment>
+ <comment xml:lang="en_GB">feature specification in Gherkin format</comment>
<comment xml:lang="es">especificación de funcionalidad en formato Gherkin</comment>
<comment xml:lang="fr">spécification fonctionnelle au format Gherkin</comment>
+ <comment xml:lang="ga">sonraíocht gnéithe i bhformáid Gherkin</comment>
<comment xml:lang="he">פירוט תכונות בתבנית Gherkin</comment>
+ <comment xml:lang="hr">opis znaÄajke u Gherkin formatu</comment>
<comment xml:lang="hu">funkcióleírás Gherkin formátumban</comment>
+ <comment xml:lang="id">spesifikasi fitur dalam format Gherkin</comment>
+ <comment xml:lang="it">Specifica di funzionalità in formato Gherkin</comment>
<comment xml:lang="kk">Gherkin пішіміндегі функционалды анықтамалар</comment>
<comment xml:lang="ko">Gherkin 형ì‹ì˜ 기능 명세</comment>
<comment xml:lang="pl">Specyfikacja funkcji w formacie Gherkin</comment>
<comment xml:lang="pt_BR">Especificação de recurso no formato Gherkin</comment>
- <comment xml:lang="ru">функциональные Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð² формате Gherkin</comment>
+ <comment xml:lang="ru">Функциональные Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð² формате Gherkin</comment>
<comment xml:lang="sk">Špecifikácia funkcie vo formáte Gherkin</comment>
+ <comment xml:lang="sr">одредба функције у запиÑу Геркина</comment>
+ <comment xml:lang="sv">egenskapsspecifikation i Gherkin-format</comment>
+ <comment xml:lang="tr">Gherkin biçiminde özellik belirtimi</comment>
<comment xml:lang="uk">ÑÐ¿ÐµÑ†Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾ÑÑ‚Ñ– у форматі Gherkin</comment>
<comment xml:lang="zh_CN">Gherkin æ ¼å¼ä¸­çš„功能规范</comment>
<comment xml:lang="zh_TW">Gherkin æ ¼å¼çš„特徵è¦æ ¼</comment>
@@ -33353,6 +34337,7 @@
<mime-type type="text/html">
<comment>HTML document</comment>
<comment xml:lang="ar">مستند HTML</comment>
+ <comment xml:lang="ast">Documentu HTML</comment>
<comment xml:lang="be@latin">Dakument HTML</comment>
<comment xml:lang="bg">Документ — HTML</comment>
<comment xml:lang="ca">document HTML</comment>
@@ -33388,7 +34373,7 @@
<comment xml:lang="pt">documento HTML</comment>
<comment xml:lang="pt_BR">Documento HTML</comment>
<comment xml:lang="ro">Document HTML</comment>
- <comment xml:lang="ru">документ HTML</comment>
+ <comment xml:lang="ru">Документ HTML</comment>
<comment xml:lang="sk">Dokument HTML</comment>
<comment xml:lang="sl">Dokument HTML</comment>
<comment xml:lang="sq">Dokument HTML</comment>
@@ -33434,7 +34419,7 @@
<comment xml:lang="de">Webanwendungscache-Manifest</comment>
<comment xml:lang="el">Δηλωτικό λανθάνουσας μνήμης εφαÏμογής ΙστοÏ</comment>
<comment xml:lang="en_GB">Web application cache manifest</comment>
- <comment xml:lang="es">manifiesto de caché de aplicación web</comment>
+ <comment xml:lang="es">manifiesto de antememoria de aplicación web</comment>
<comment xml:lang="eu">Web aplikazioaren cache-aren agiria</comment>
<comment xml:lang="fo">Net nýtsluskipanarkova manifest</comment>
<comment xml:lang="fr">manifeste de cache d'application Web</comment>
@@ -33457,7 +34442,7 @@
<comment xml:lang="pt">manifesto de cache de aplicação web</comment>
<comment xml:lang="pt_BR">Manifest de cache de aplicação web</comment>
<comment xml:lang="ro">Manifest de cache pentru aplicații web</comment>
- <comment xml:lang="ru">манифеÑÑ‚ кÑша веб-приложениÑ</comment>
+ <comment xml:lang="ru">МанифеÑÑ‚ кÑша веб-приложениÑ</comment>
<comment xml:lang="sk">Manifest vyrovnávacej pamäte webovej aplikácie</comment>
<comment xml:lang="sl">Predpomnilnik spletnega programa</comment>
<comment xml:lang="sr">Ð¿Ñ€Ð¾Ð³Ð»Ð°Ñ Ð¾Ñтаве Веб програма</comment>
@@ -33480,6 +34465,7 @@
<mime-type type="text/x-google-video-pointer">
<comment>Google Video Pointer</comment>
<comment xml:lang="ar">مؤشر Ùيديو جوجل</comment>
+ <comment xml:lang="ast">Google Video Pointer</comment>
<comment xml:lang="be@latin">Pakazalnik Google Video</comment>
<comment xml:lang="bg">Документ-указател към видео на Google</comment>
<comment xml:lang="ca">apuntador a vídeo de Google</comment>
@@ -33539,7 +34525,7 @@
<comment xml:lang="be@latin">KryniÄny kod Haskell</comment>
<comment xml:lang="bg">Изходен код на Haskell</comment>
<comment xml:lang="ca">codi font en Haskell</comment>
- <comment xml:lang="cs">zdrojový kód Haskell</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Haskell</comment>
<comment xml:lang="cy">Ffynhonnell rhaglen Haskell</comment>
<comment xml:lang="da">Haskellkildekode</comment>
<comment xml:lang="de">Haskell-Quelltext</comment>
@@ -33554,10 +34540,10 @@
<comment xml:lang="ga">cód foinseach Haskell</comment>
<comment xml:lang="gl">código fonte de Haskell</comment>
<comment xml:lang="he">קוד מקור של Haskell</comment>
- <comment xml:lang="hr">Haskell izvorni kod</comment>
+ <comment xml:lang="hr">Haskell izvorni kôd</comment>
<comment xml:lang="hu">Haskell-forráskód</comment>
<comment xml:lang="ia">Codice-fonte Haskell</comment>
- <comment xml:lang="id">Kode program Haskell</comment>
+ <comment xml:lang="id">Kode sumber Haskell</comment>
<comment xml:lang="it">Codice sorgente Haskell</comment>
<comment xml:lang="ja">Haskell ソースコード</comment>
<comment xml:lang="kk">Haskell баÑтапқы коды</comment>
@@ -33573,7 +34559,7 @@
<comment xml:lang="pt">código origem Haskell</comment>
<comment xml:lang="pt_BR">Código-fonte Haskell</comment>
<comment xml:lang="ro">Cod sursă Haskell</comment>
- <comment xml:lang="ru">иÑходный код Haskell</comment>
+ <comment xml:lang="ru">ИÑходный код Haskell</comment>
<comment xml:lang="sk">Zdrojový kód Haskell</comment>
<comment xml:lang="sl">Datoteka izvorne kode Haskell</comment>
<comment xml:lang="sq">Kod burues Haskell</comment>
@@ -33590,6 +34576,7 @@
<mime-type type="text/x-idl">
<comment>IDL document</comment>
<comment xml:lang="ar">مستند IDL</comment>
+ <comment xml:lang="ast">Documentu IDL</comment>
<comment xml:lang="az">IDL sənədi</comment>
<comment xml:lang="be@latin">Dakument IDL</comment>
<comment xml:lang="bg">Документ — IDL</comment>
@@ -33628,7 +34615,7 @@
<comment xml:lang="pt">documento IDL</comment>
<comment xml:lang="pt_BR">Documento IDL</comment>
<comment xml:lang="ro">Document IDL</comment>
- <comment xml:lang="ru">документ IDL</comment>
+ <comment xml:lang="ru">Документ IDL</comment>
<comment xml:lang="sk">Dokument IDL</comment>
<comment xml:lang="sl">Dokument IDL</comment>
<comment xml:lang="sq">Dokument IDL</comment>
@@ -33647,6 +34634,7 @@
<mime-type type="text/x-install">
<comment>installation instructions</comment>
<comment xml:lang="ar">تعليمات التثبيت</comment>
+ <comment xml:lang="ast">instrucciones d'instalación</comment>
<comment xml:lang="be@latin">instrukcyja dla instalavańnia</comment>
<comment xml:lang="bg">ИнÑтрукции за инÑталациÑ</comment>
<comment xml:lang="ca">instruccions d'instal·lació</comment>
@@ -33663,7 +34651,7 @@
<comment xml:lang="ga">treoracha suiteála</comment>
<comment xml:lang="gl">instrucións de instalación</comment>
<comment xml:lang="he">הור×ות התקנה</comment>
- <comment xml:lang="hr">upute za instalaciju</comment>
+ <comment xml:lang="hr">Upute za instalaciju</comment>
<comment xml:lang="hu">telepítési utasítások</comment>
<comment xml:lang="ia">Instructiones de installation</comment>
<comment xml:lang="id">instruksi instalasi</comment>
@@ -33681,7 +34669,7 @@
<comment xml:lang="pt">instruções de instalação</comment>
<comment xml:lang="pt_BR">Instruções de instalação</comment>
<comment xml:lang="ro">instrucțiuni de instalare</comment>
- <comment xml:lang="ru">инÑтрукции по уÑтановке программы</comment>
+ <comment xml:lang="ru">ИнÑтрукции по уÑтановке</comment>
<comment xml:lang="sk">Návod na inštaláciu</comment>
<comment xml:lang="sl">navodila namestitve</comment>
<comment xml:lang="sq">Udhëzime instalimi</comment>
@@ -33701,7 +34689,7 @@
<comment xml:lang="be@latin">KryniÄny kod Java</comment>
<comment xml:lang="bg">Изходен код на Java</comment>
<comment xml:lang="ca">codi font en Java</comment>
- <comment xml:lang="cs">zdrojový kód Java</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Java</comment>
<comment xml:lang="da">Javakildekode</comment>
<comment xml:lang="de">Java-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας Java</comment>
@@ -33715,10 +34703,10 @@
<comment xml:lang="ga">cód foinseach Java</comment>
<comment xml:lang="gl">código fonte de Java</comment>
<comment xml:lang="he">קוד מקור ב־Java</comment>
- <comment xml:lang="hr">Java izvorni kod</comment>
+ <comment xml:lang="hr">Java izvorni kôd</comment>
<comment xml:lang="hu">Java-forráskód</comment>
<comment xml:lang="ia">Codice-fonte Java</comment>
- <comment xml:lang="id">Kode program Java</comment>
+ <comment xml:lang="id">Kode sumber Java</comment>
<comment xml:lang="it">Codice sorgente Java</comment>
<comment xml:lang="ja">Java ソースコード</comment>
<comment xml:lang="kk">Java баÑтапқы коды</comment>
@@ -33734,7 +34722,7 @@
<comment xml:lang="pt">código origem Java</comment>
<comment xml:lang="pt_BR">Código-fonte Java</comment>
<comment xml:lang="ro">Cod sursă Java</comment>
- <comment xml:lang="ru">иÑходный код Java</comment>
+ <comment xml:lang="ru">ИÑходный код Java</comment>
<comment xml:lang="sk">Zdrojový kód Java</comment>
<comment xml:lang="sl">Datoteka izvorne kode Java</comment>
<comment xml:lang="sq">Kod burues Java</comment>
@@ -33765,7 +34753,7 @@
<comment xml:lang="fi">LDIF-osoitekirja</comment>
<comment xml:lang="fo">LDIF adressubók</comment>
<comment xml:lang="fr">carnet d'adresses LDIF</comment>
- <comment xml:lang="ga">leabhar sheoltaí LDIF</comment>
+ <comment xml:lang="ga">leabhar seoltaí LDIF</comment>
<comment xml:lang="gl">lista de enderezos LDIF</comment>
<comment xml:lang="he">ספר כתובות של LDIF</comment>
<comment xml:lang="hr">LDIF adresar</comment>
@@ -33786,7 +34774,7 @@
<comment xml:lang="pt">livro de endereços LDIF</comment>
<comment xml:lang="pt_BR">Livro de endereços LDIF</comment>
<comment xml:lang="ro">Agendă LDIF</comment>
- <comment xml:lang="ru">адреÑÐ½Ð°Ñ ÐºÐ½Ð¸Ð³Ð° LDIF</comment>
+ <comment xml:lang="ru">ÐдреÑÐ½Ð°Ñ ÐºÐ½Ð¸Ð³Ð° LDIF</comment>
<comment xml:lang="sk">Adresár LDIF</comment>
<comment xml:lang="sl">Datoteka imenika naslovov LDIF</comment>
<comment xml:lang="sq">Rubrikë LDIF</comment>
@@ -33842,7 +34830,7 @@
<comment xml:lang="pt">folha de música Lilypond</comment>
<comment xml:lang="pt_BR">Partitura do Lilypond</comment>
<comment xml:lang="ro">Fișă muzică Lilypond</comment>
- <comment xml:lang="ru">ÑпиÑок музыки Lilypond</comment>
+ <comment xml:lang="ru">СпиÑок музыки Lilypond</comment>
<comment xml:lang="sk">Notový papier Lilypond</comment>
<comment xml:lang="sl">Glasbena predloga Lilypond</comment>
<comment xml:lang="sq">Partiturë Lilypond</comment>
@@ -33876,10 +34864,10 @@
<comment xml:lang="ga">cód foinseach LHS</comment>
<comment xml:lang="gl">código fonte en LHS</comment>
<comment xml:lang="he">קוד מקור של LHS</comment>
- <comment xml:lang="hr">LHS izvorni kod</comment>
+ <comment xml:lang="hr">LHS izvorni kôd</comment>
<comment xml:lang="hu">LHS forráskód</comment>
<comment xml:lang="ia">Codice-fonte LHS</comment>
- <comment xml:lang="id">Kode program LHS</comment>
+ <comment xml:lang="id">Kode sumber LHS</comment>
<comment xml:lang="it">Codice sorgente LHS</comment>
<comment xml:lang="ja">LHS ソースコード</comment>
<comment xml:lang="kk">LHS баÑтапқы коды</comment>
@@ -33894,7 +34882,7 @@
<comment xml:lang="pt">código origem LHS</comment>
<comment xml:lang="pt_BR">Código-fonte LHS</comment>
<comment xml:lang="ro">Cod sursă LHS</comment>
- <comment xml:lang="ru">иÑходный код LHS</comment>
+ <comment xml:lang="ru">ИÑходный код LHS</comment>
<comment xml:lang="sk">Zdrojový kód LHS</comment>
<comment xml:lang="sl">Datoteka izvorne kode LHS</comment>
<comment xml:lang="sq">Kod burues LHS</comment>
@@ -33913,6 +34901,7 @@
<mime-type type="text/x-log">
<comment>application log</comment>
<comment xml:lang="ar">سجل التطبيق</comment>
+ <comment xml:lang="ast">rexistru d'aplicación</comment>
<comment xml:lang="be@latin">Äasopis aplikacyi</comment>
<comment xml:lang="bg">Файл-дневник на приложение</comment>
<comment xml:lang="ca">registre d'aplicació</comment>
@@ -33949,7 +34938,7 @@
<comment xml:lang="pt">diário de aplicação</comment>
<comment xml:lang="pt_BR">Registro de aplicativo</comment>
<comment xml:lang="ro">înregistrare aplicație</comment>
- <comment xml:lang="ru">журнал Ñообщений</comment>
+ <comment xml:lang="ru">Журнал Ñообщений</comment>
<comment xml:lang="sk">Záznam aplikácie</comment>
<comment xml:lang="sl">dnevnik programa</comment>
<comment xml:lang="sq">log i mesazheve të programit</comment>
@@ -34005,7 +34994,7 @@
<comment xml:lang="pt">Makefile</comment>
<comment xml:lang="pt_BR">Makefile (arquivo do make)</comment>
<comment xml:lang="ro">Makefile</comment>
- <comment xml:lang="ru">Makefile (файл Ñборки)</comment>
+ <comment xml:lang="ru">Файл Makefile</comment>
<comment xml:lang="sk">Makefile</comment>
<comment xml:lang="sl">Datoteka Makefile</comment>
<comment xml:lang="sq">Makefile</comment>
@@ -34029,6 +35018,7 @@
</mime-type>
<mime-type type="text/markdown">
<comment>Markdown document</comment>
+ <comment xml:lang="ast">Documentu Markdown</comment>
<comment xml:lang="bg">Документ — Markdown</comment>
<comment xml:lang="ca">document Markdown</comment>
<comment xml:lang="cs">dokument Markdown</comment>
@@ -34040,6 +35030,7 @@
<comment xml:lang="eu">Markdown dokumentua</comment>
<comment xml:lang="fi">Markdown-asiakirja</comment>
<comment xml:lang="fr">document Markdown</comment>
+ <comment xml:lang="ga">cáipéis Markdown</comment>
<comment xml:lang="gl">documento de Markdown</comment>
<comment xml:lang="he">מסמך Markdown</comment>
<comment xml:lang="hr">Markdown dokument</comment>
@@ -34056,7 +35047,7 @@
<comment xml:lang="pl">Dokument Markdown</comment>
<comment xml:lang="pt">documento Markdown</comment>
<comment xml:lang="pt_BR">Documento Markdown</comment>
- <comment xml:lang="ru">документ Markdown</comment>
+ <comment xml:lang="ru">Документ Markdown</comment>
<comment xml:lang="sk">Dokument Markdown</comment>
<comment xml:lang="sl">Dokument Markdown</comment>
<comment xml:lang="sr">Маркдаун документ</comment>
@@ -34108,7 +35099,7 @@
<comment xml:lang="pt">ficheiro Qt MOC</comment>
<comment xml:lang="pt_BR">Arquivo Qt MOC</comment>
<comment xml:lang="ro">Fișier Qt MOC</comment>
- <comment xml:lang="ru">файл Qt MOC</comment>
+ <comment xml:lang="ru">Файл Qt MOC</comment>
<comment xml:lang="sk">Súbor Qt MOC</comment>
<comment xml:lang="sl">Datoteka Qt MOC</comment>
<comment xml:lang="sq">File Qt MOC</comment>
@@ -34117,7 +35108,7 @@
<comment xml:lang="tr">Qt MOC dosyası</comment>
<comment xml:lang="uk">файл-метаоб'єкт Qt</comment>
<comment xml:lang="vi">Tập tin MOC của Qt</comment>
- <comment xml:lang="zh_CN">Qt 元对象编译文件</comment>
+ <comment xml:lang="zh_CN">Qt 元对象编译器文件</comment>
<comment xml:lang="zh_TW">Qt MOC 檔</comment>
<acronym>Qt MOC</acronym>
<expanded-acronym>Qt Meta Object Compiler</expanded-acronym>
@@ -34161,7 +35152,7 @@
<comment xml:lang="pt">extrato do registo do Windows</comment>
<comment xml:lang="pt_BR">Extrator de registro do Windows</comment>
<comment xml:lang="ro">Extras al registrului Windows</comment>
- <comment xml:lang="ru">фрагмент Windows Registry</comment>
+ <comment xml:lang="ru">Фрагмент Windows Registry</comment>
<comment xml:lang="sk">Časť registrov Windows</comment>
<comment xml:lang="sl">izvleÄek vpisnika Windows</comment>
<comment xml:lang="sq">Pjesë Windows Registry</comment>
@@ -34170,7 +35161,7 @@
<comment xml:lang="tr">Windows Kayıt Defteri özü</comment>
<comment xml:lang="uk">чаÑтина реєÑтру Windows</comment>
<comment xml:lang="vi">Bản trích Registry Windows</comment>
- <comment xml:lang="zh_CN">Windows 注册表文件</comment>
+ <comment xml:lang="zh_CN">Windows 注册表æå–</comment>
<comment xml:lang="zh_TW">Windows Registry 抽出</comment>
<sub-class-of type="text/plain"/>
<magic priority="50">
@@ -34216,7 +35207,7 @@
<comment xml:lang="pt">formato Managed Object</comment>
<comment xml:lang="pt_BR">Formato de objeto gerenciado</comment>
<comment xml:lang="ro">Managed Object Format</comment>
- <comment xml:lang="ru">формат управлÑемого объекта</comment>
+ <comment xml:lang="ru">Формат управлÑемого объекта</comment>
<comment xml:lang="sk">Formát Managed Object</comment>
<comment xml:lang="sl">Datoteka Managed Object</comment>
<comment xml:lang="sq">Managed Object Format</comment>
@@ -34267,7 +35258,7 @@
<comment xml:lang="pt">publicação Mup</comment>
<comment xml:lang="pt_BR">Publicação do Mup</comment>
<comment xml:lang="ro">Publicație Mup</comment>
- <comment xml:lang="ru">Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ñ Mup</comment>
+ <comment xml:lang="ru">ÐŸÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ñ Mup</comment>
<comment xml:lang="sk">Publikácie Mup</comment>
<comment xml:lang="sl">Datoteka objave Mup</comment>
<comment xml:lang="sq">Publikim Mup</comment>
@@ -34291,7 +35282,7 @@
<comment xml:lang="be@latin">KryniÄny kod Objective-C</comment>
<comment xml:lang="bg">Изходен код — Objective C</comment>
<comment xml:lang="ca">codi font en Objective-C</comment>
- <comment xml:lang="cs">zdrojový kód Objective-C</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Objective-C</comment>
<comment xml:lang="da">Objektiv C-kildekode</comment>
<comment xml:lang="de">Objective-C-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας Objective-C</comment>
@@ -34308,7 +35299,7 @@
<comment xml:lang="hr">Objective-C izvorni kôd</comment>
<comment xml:lang="hu">Objective-C forráskód</comment>
<comment xml:lang="ia">Codice-fonte Objective-C</comment>
- <comment xml:lang="id">Kode program Objective-C</comment>
+ <comment xml:lang="id">Kode sumber Objective-C</comment>
<comment xml:lang="it">Codice sorgente Objective-C</comment>
<comment xml:lang="ja">Objective-C ソースコード</comment>
<comment xml:lang="ka">Objective-C-ის სáƒáƒ¬áƒ§áƒ˜áƒ¡áƒ˜ კáƒáƒ“ი</comment>
@@ -34325,7 +35316,7 @@
<comment xml:lang="pt">código origem Objective-C</comment>
<comment xml:lang="pt_BR">Código-fonte Objective-C</comment>
<comment xml:lang="ro">Cod sursă Objective-C</comment>
- <comment xml:lang="ru">иÑходный код Objective-C</comment>
+ <comment xml:lang="ru">ИÑходный код Objective-C</comment>
<comment xml:lang="sk">Zdrojový kód Objective-C</comment>
<comment xml:lang="sl">Datoteka izvorne kode Objective-C</comment>
<comment xml:lang="sq">Kod burues C objekt</comment>
@@ -34348,7 +35339,7 @@
<comment xml:lang="be@latin">KryniÄny kod OCaml</comment>
<comment xml:lang="bg">Изходен код — OCaml</comment>
<comment xml:lang="ca">codi font en OCaml</comment>
- <comment xml:lang="cs">zdrojový kód OCaml</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce OCaml</comment>
<comment xml:lang="da">OCaml-kildekode</comment>
<comment xml:lang="de">OCaml-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας OCaml</comment>
@@ -34362,10 +35353,10 @@
<comment xml:lang="ga">cód foinseach OCaml</comment>
<comment xml:lang="gl">código fonte de OCaml</comment>
<comment xml:lang="he">קוד מקור של OCaml</comment>
- <comment xml:lang="hr">OCaml izvorni kod</comment>
+ <comment xml:lang="hr">OCaml izvorni kôd</comment>
<comment xml:lang="hu">OCaml forráskód</comment>
<comment xml:lang="ia">Codice-fonte OCaml</comment>
- <comment xml:lang="id">Kode program OCaml</comment>
+ <comment xml:lang="id">Kode sumber OCaml</comment>
<comment xml:lang="it">Codice sorgente OCaml</comment>
<comment xml:lang="ja">OCaml ソースコード</comment>
<comment xml:lang="kk">OCaml баÑтапқы коды</comment>
@@ -34380,7 +35371,7 @@
<comment xml:lang="pt">código origem OCaml</comment>
<comment xml:lang="pt_BR">Código-fonte OCaml</comment>
<comment xml:lang="ro">Cod sursă OCaml</comment>
- <comment xml:lang="ru">иÑходный код OCaml</comment>
+ <comment xml:lang="ru">ИÑходный код OCaml</comment>
<comment xml:lang="sk">Zdrojový kód OCaml</comment>
<comment xml:lang="sl">Datoteka izvorne kode OCaml</comment>
<comment xml:lang="sq">Kod burues OCaml</comment>
@@ -34394,6 +35385,33 @@
<glob pattern="*.ml"/>
<glob pattern="*.mli"/>
</mime-type>
+ <mime-type type="text/x-opencl-src">
+ <comment>OpenCL source code</comment>
+ <comment xml:lang="ca">codi font en OpenCL</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce OpenCL</comment>
+ <comment xml:lang="de">OpenCL-Quelltext</comment>
+ <comment xml:lang="en_GB">OpenCL source code</comment>
+ <comment xml:lang="es">código fuente en OpenCL</comment>
+ <comment xml:lang="fi">OpenCL-lähdekoodi</comment>
+ <comment xml:lang="hr">OpenCL izvorni kôd</comment>
+ <comment xml:lang="hu">OpenCL forráskód</comment>
+ <comment xml:lang="id">Kode sumber OpenCL</comment>
+ <comment xml:lang="it">Codice sorgente OpenCL</comment>
+ <comment xml:lang="kk">OpenCL баÑтапқы коды</comment>
+ <comment xml:lang="ko">OpenCL 소스 코드</comment>
+ <comment xml:lang="pl">Kod źródłowy OpenCL</comment>
+ <comment xml:lang="pt_BR">Código-fonte do OpenCL</comment>
+ <comment xml:lang="ru">ИÑходный код OpenGL</comment>
+ <comment xml:lang="sk">Zdrojový kód OpenCL</comment>
+ <comment xml:lang="sv">OpenCL-källkod</comment>
+ <comment xml:lang="uk">вихідний код мовою OpenCL</comment>
+ <comment xml:lang="zh_CN">OpenCL æºä»£ç </comment>
+ <comment xml:lang="zh_TW">OpenCL æºç¢¼</comment>
+ <acronym>OpenCL</acronym>
+ <expanded-acronym>Open Computing Language</expanded-acronym>
+ <sub-class-of type="text/x-csrc"/>
+ <glob pattern="*.cl"/>
+ </mime-type>
<mime-type type="text/x-matlab">
<comment>MATLAB script/function</comment>
<comment xml:lang="ar">سكربت/وظيÙØ© MATLAB</comment>
@@ -34431,7 +35449,7 @@
<comment xml:lang="pt">script/função MATLAB</comment>
<comment xml:lang="pt_BR">Script/função do MATLAB</comment>
<comment xml:lang="ro">Funcție/script MATLAB</comment>
- <comment xml:lang="ru">Ñценарий/Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ MATLAB</comment>
+ <comment xml:lang="ru">Сценарий/Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ MATLAB</comment>
<comment xml:lang="sk">Skript/funkcia MATLAB</comment>
<comment xml:lang="sl">Skriptna datoteka MATLAB</comment>
<comment xml:lang="sq">Script/Funksion MATLAB</comment>
@@ -34467,11 +35485,12 @@
<comment xml:lang="eu">Meson iturburu-kodea</comment>
<comment xml:lang="fi">Meson-lähdekoodi</comment>
<comment xml:lang="fr">code source Meson</comment>
+ <comment xml:lang="ga">cód foinseach Meson</comment>
<comment xml:lang="he">קוד מקור Meson</comment>
<comment xml:lang="hr">Meson izvorni kôd</comment>
<comment xml:lang="hu">Meson forráskód</comment>
<comment xml:lang="ia">Codice-fonte Meson</comment>
- <comment xml:lang="id">Kode program Meson</comment>
+ <comment xml:lang="id">Kode sumber Meson</comment>
<comment xml:lang="it">Codice sorgente Meson</comment>
<comment xml:lang="kk">Meson баÑтапқы коды</comment>
<comment xml:lang="ko">Meson 소스 코드</comment>
@@ -34479,7 +35498,7 @@
<comment xml:lang="pl">Kod źródłowy Meson</comment>
<comment xml:lang="pt">código origem Meson</comment>
<comment xml:lang="pt_BR">Código-fonte Meson</comment>
- <comment xml:lang="ru">иÑходный код Meson</comment>
+ <comment xml:lang="ru">ИÑходный код Meson</comment>
<comment xml:lang="sk">Zdrojový kód Meson</comment>
<comment xml:lang="sr">МеÑон изворни ко̂д</comment>
<comment xml:lang="sv">Meson-källkod</comment>
@@ -34503,6 +35522,7 @@
<comment xml:lang="eu">Modelica modeloa</comment>
<comment xml:lang="fi">Modelica-malli</comment>
<comment xml:lang="fr">modèle Modelica</comment>
+ <comment xml:lang="ga">samhail Modelica</comment>
<comment xml:lang="gl">Modelo de Modelica</comment>
<comment xml:lang="he">×“×’× ×©×œ Modelica</comment>
<comment xml:lang="hr">Modelica model</comment>
@@ -34518,7 +35538,7 @@
<comment xml:lang="pl">Model Modelica</comment>
<comment xml:lang="pt">modelo Modelica</comment>
<comment xml:lang="pt_BR">Modelo da Modelica</comment>
- <comment xml:lang="ru">модель Modelica</comment>
+ <comment xml:lang="ru">Модель Modelica</comment>
<comment xml:lang="sk">Model Modelica</comment>
<comment xml:lang="sl">Model Modelica</comment>
<comment xml:lang="sr">модел Моделике</comment>
@@ -34551,7 +35571,7 @@
<comment xml:lang="be@latin">KryniÄny kod Pascal</comment>
<comment xml:lang="bg">Изходен код — Pascal</comment>
<comment xml:lang="ca">codi font en Pascal</comment>
- <comment xml:lang="cs">zdrojový kód Pascal</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Pascal</comment>
<comment xml:lang="da">Pascalkildekode</comment>
<comment xml:lang="de">Pascal-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας Pascal</comment>
@@ -34568,7 +35588,7 @@
<comment xml:lang="hr">Pascal izvorni kôd</comment>
<comment xml:lang="hu">Pascal-forráskód</comment>
<comment xml:lang="ia">Codice-fonte Pascal</comment>
- <comment xml:lang="id">Kode program Pascal</comment>
+ <comment xml:lang="id">Kode sumber Pascal</comment>
<comment xml:lang="it">Codice sorgente Pascal</comment>
<comment xml:lang="ja">Pascal ソースコード</comment>
<comment xml:lang="kk">Pascal баÑтапқы коды</comment>
@@ -34584,7 +35604,7 @@
<comment xml:lang="pt">código origem Pascal</comment>
<comment xml:lang="pt_BR">Código-fonte Pascal</comment>
<comment xml:lang="ro">Cod sursă Pascal</comment>
- <comment xml:lang="ru">иÑходный код Pascal</comment>
+ <comment xml:lang="ru">ИÑходный код Pascal</comment>
<comment xml:lang="sk">Zdrojový kód Pascal</comment>
<comment xml:lang="sl">Datoteka izvorne kode Pascal</comment>
<comment xml:lang="sq">Kod burues Pascal</comment>
@@ -34619,7 +35639,7 @@
<comment xml:lang="ga">difríochtaí idir chomhaid</comment>
<comment xml:lang="gl">diferenzas entre ficheiros</comment>
<comment xml:lang="he">הבדל בין קבצי×</comment>
- <comment xml:lang="hr">razlike između datoteka</comment>
+ <comment xml:lang="hr">Razlike između datoteka</comment>
<comment xml:lang="hu">diff-különbségfájl</comment>
<comment xml:lang="ia">Differentias inter files</comment>
<comment xml:lang="id">perbedaan diantara berkas</comment>
@@ -34638,7 +35658,7 @@
<comment xml:lang="pt">diferenças entre ficheiros</comment>
<comment xml:lang="pt_BR">Diferenças entre arquivos</comment>
<comment xml:lang="ro">diferențe între fișiere</comment>
- <comment xml:lang="ru">Ñ€Ð°Ð·Ð»Ð¸Ñ‡Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ файлами</comment>
+ <comment xml:lang="ru">Ð Ð°Ð·Ð»Ð¸Ñ‡Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ файлами</comment>
<comment xml:lang="sk">Rozdiely medzi súbormi</comment>
<comment xml:lang="sl">razlike med datotekami</comment>
<comment xml:lang="sq">Diferencë midis file</comment>
@@ -34670,7 +35690,7 @@
<comment>Go source code</comment>
<comment xml:lang="bg">Изходен код — Go</comment>
<comment xml:lang="ca">codi font en Go</comment>
- <comment xml:lang="cs">zdrojový kód Go</comment>
+ <comment xml:lang="cs">zdrojový kód v jazyce Go</comment>
<comment xml:lang="da">Go-kildekode</comment>
<comment xml:lang="de">Go-Quelltext</comment>
<comment xml:lang="el">Πηγαίος κώδικας Go</comment>
@@ -34680,9 +35700,10 @@
<comment xml:lang="eu">Go iturburu-kodea</comment>
<comment xml:lang="fi">Go-lähdekoodi</comment>
<comment xml:lang="fr">code source Go</comment>
+ <comment xml:lang="ga">cód foinseach Go</comment>
<comment xml:lang="gl">código fonte de Go</comment>
<comment xml:lang="he">קוד מקור של Go</comment>
- <comment xml:lang="hr">Go izvorni kod</comment>
+ <comment xml:lang="hr">Go izvorni kôd</comment>
<comment xml:lang="hu">Go forráskód</comment>
<comment xml:lang="ia">Codice-fonte Go</comment>
<comment xml:lang="id">Kode sumber Go</comment>
@@ -34697,14 +35718,14 @@
<comment xml:lang="pl">Kod źródłowy Go</comment>
<comment xml:lang="pt">cigo origem Go</comment>
<comment xml:lang="pt_BR">Código-fonte Go</comment>
- <comment xml:lang="ru">иÑходный код Go</comment>
+ <comment xml:lang="ru">ИÑходный код Go</comment>
<comment xml:lang="sk">Zdrojový kód Go</comment>
<comment xml:lang="sl">Izvorna koda Go</comment>
<comment xml:lang="sr">Гоу изворни ко̂д</comment>
<comment xml:lang="sv">Go-källkod</comment>
<comment xml:lang="tr">Go kaynak kodu</comment>
<comment xml:lang="uk">вихідний код мовою Go</comment>
- <comment xml:lang="zh_CN">Go </comment>
+ <comment xml:lang="zh_CN">Go æºä»£ç </comment>
<comment xml:lang="zh_TW">Go æºç¢¼</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.go"/>
@@ -34721,6 +35742,7 @@
<comment xml:lang="eu">SCons konfigurazio-fitxategia</comment>
<comment xml:lang="fi">SCons-asetustiedosto</comment>
<comment xml:lang="fr">fichier de configuration SCons</comment>
+ <comment xml:lang="ga">comhad cumraíochta SCons</comment>
<comment xml:lang="he">קובץ תצורה של SCons</comment>
<comment xml:lang="hr">SCons datoteka podešavanja</comment>
<comment xml:lang="hu">SCons beállítófájl</comment>
@@ -34733,7 +35755,7 @@
<comment xml:lang="pl">Plik konfiguracji SCons</comment>
<comment xml:lang="pt">ficheiro de configuração SCons</comment>
<comment xml:lang="pt_BR">Arquivo de configuração do SCons</comment>
- <comment xml:lang="ru">файл наÑтроек SCons</comment>
+ <comment xml:lang="ru">Файл наÑтроек SCons</comment>
<comment xml:lang="sk">KonfiguraÄný súbor SCons</comment>
<comment xml:lang="sl">Prilagoditvena datoteka SCons</comment>
<comment xml:lang="sr">Ð¡ÐšÐ¾Ð½Ñ Ð´Ð°Ñ‚Ð¾Ñ‚ÐµÐºÐ° подешавања</comment>
@@ -34747,13 +35769,52 @@
<glob pattern="SConscript"/>
<glob pattern="SConscript.*"/>
</mime-type>
+ <mime-type type="text/x-python3">
+ <comment>Python 3 script</comment>
+ <comment xml:lang="ca">script Python 3</comment>
+ <comment xml:lang="cs">skript v jazyce Python 3</comment>
+ <comment xml:lang="de">Python-3-Skript</comment>
+ <comment xml:lang="en_GB">Python 3 script</comment>
+ <comment xml:lang="es">secuencia de órdenes en Python 3</comment>
+ <comment xml:lang="fi">Python 3 -skripti</comment>
+ <comment xml:lang="hr">Python3 skripta</comment>
+ <comment xml:lang="hu">Python 3 parancsfájl</comment>
+ <comment xml:lang="id">Skrip Python 3</comment>
+ <comment xml:lang="it">Script Python 3</comment>
+ <comment xml:lang="kk">Python 3 Ñкрипті</comment>
+ <comment xml:lang="ko">파ì´ì¬ 3 스í¬ë¦½íŠ¸</comment>
+ <comment xml:lang="pl">Skrypt Python 3</comment>
+ <comment xml:lang="pt_BR">Script Python 3</comment>
+ <comment xml:lang="ru">Сценарий Python 3</comment>
+ <comment xml:lang="sk">Skript Python 3</comment>
+ <comment xml:lang="sv">Python 3-skript</comment>
+ <comment xml:lang="uk">Ñкрипт мовою Python 3</comment>
+ <comment xml:lang="zh_CN">Python 3 脚本</comment>
+ <comment xml:lang="zh_TW">Python 3 指令稿</comment>
+ <sub-class-of type='text/x-python'/>
+ <magic priority="60">
+ <match value="#!/bin/python3" type="string" offset="0"/>
+ <match value="#! /bin/python3" type="string" offset="0"/>
+ <match value='eval \"exec /bin/python3' type="string" offset="0"/>
+ <match value="#!/usr/bin/python3" type="string" offset="0"/>
+ <match value="#! /usr/bin/python3" type="string" offset="0"/>
+ <match value='eval \"exec /usr/bin/python3' type="string" offset="0"/>
+ <match value="#!/usr/local/bin/python3" type="string" offset="0"/>
+ <match value="#! /usr/local/bin/python3" type="string" offset="0"/>
+ <match value='eval \"exec /usr/local/bin/python3' type="string" offset="0"/>
+ <match value='/bin/env python3' type="string" offset="2:16"/>
+ </magic>
+ <glob weight="50" pattern="*.py"/>
+ <glob weight="60" pattern="*.py3"/>
+ <glob weight="60" pattern="*.py3x"/>
+ </mime-type>
<mime-type type="text/x-python">
<comment>Python script</comment>
<comment xml:lang="ar">سكربت بايثون</comment>
<comment xml:lang="be@latin">Skrypt Python</comment>
<comment xml:lang="bg">Скрипт — Python</comment>
<comment xml:lang="ca">script Python</comment>
- <comment xml:lang="cs">skript Python</comment>
+ <comment xml:lang="cs">skript v jazyce Python</comment>
<comment xml:lang="da">Pythonprogram</comment>
<comment xml:lang="de">Python-Skript</comment>
<comment xml:lang="el">Δέσμη ενεÏγειών Python</comment>
@@ -34786,7 +35847,7 @@
<comment xml:lang="pt">script Python</comment>
<comment xml:lang="pt_BR">Script Python</comment>
<comment xml:lang="ro">Script Python</comment>
- <comment xml:lang="ru">Ñценарий Python</comment>
+ <comment xml:lang="ru">Сценарий Python</comment>
<comment xml:lang="sk">Skript Python</comment>
<comment xml:lang="sl">Skriptna datoteka Python</comment>
<comment xml:lang="sq">Script Python</comment>
@@ -34811,9 +35872,9 @@
<match value='eval \"exec /usr/local/bin/python' type="string" offset="0"/>
<match value='/bin/env python' type="string" offset="2:16"/>
</magic>
- <glob pattern="*.py"/>
- <glob pattern="*.pyx"/>
- <glob pattern="*.wsgi"/>
+ <glob weight="60" pattern="*.py"/>
+ <glob weight="60" pattern="*.pyx"/>
+ <glob weight="60" pattern="*.wsgi"/>
</mime-type>
<mime-type type="text/x-lua">
<comment>Lua script</comment>
@@ -34821,7 +35882,7 @@
<comment xml:lang="be@latin">Skrypt Lua</comment>
<comment xml:lang="bg">Скрипт на Lua</comment>
<comment xml:lang="ca">script Lua</comment>
- <comment xml:lang="cs">skript Lua</comment>
+ <comment xml:lang="cs">skript v jazyce Lua</comment>
<comment xml:lang="da">Luaprogram</comment>
<comment xml:lang="de">Lua-Skript</comment>
<comment xml:lang="el">Δέσμη ενεÏγειών Lua</comment>
@@ -34853,7 +35914,7 @@
<comment xml:lang="pt">script Lua</comment>
<comment xml:lang="pt_BR">Script Lua</comment>
<comment xml:lang="ro">Script Lua</comment>
- <comment xml:lang="ru">Ñценарий Lua</comment>
+ <comment xml:lang="ru">Сценарий Lua</comment>
<comment xml:lang="sk">Skript Lua</comment>
<comment xml:lang="sl">Skriptna datoteka Lua</comment>
<comment xml:lang="sq">Script Lua</comment>
@@ -34877,6 +35938,7 @@
<mime-type type="text/x-readme">
<comment>README document</comment>
<comment xml:lang="ar">مستند README</comment>
+ <comment xml:lang="ast">Documentu LLEIME</comment>
<comment xml:lang="az">README sənədi</comment>
<comment xml:lang="be@latin">Dakument README</comment>
<comment xml:lang="bg">Документ — „Да Ñе прочете“</comment>
@@ -34915,7 +35977,7 @@
<comment xml:lang="pt">documento LEIA-ME</comment>
<comment xml:lang="pt_BR">Documento README</comment>
<comment xml:lang="ro">Document README</comment>
- <comment xml:lang="ru">документ README</comment>
+ <comment xml:lang="ru">Документ README</comment>
<comment xml:lang="sk">Dokument README</comment>
<comment xml:lang="sl">Dokument README</comment>
<comment xml:lang="sq">Dokument README</comment>
@@ -34932,6 +35994,7 @@
<mime-type type="text/x-nfo">
<comment>NFO document</comment>
<comment xml:lang="ar">مستند NFO</comment>
+ <comment xml:lang="ast">Documentu NFO</comment>
<comment xml:lang="be@latin">Dakument NFO</comment>
<comment xml:lang="bg">Документ — NFO</comment>
<comment xml:lang="ca">document NFO</comment>
@@ -34967,7 +36030,7 @@
<comment xml:lang="pt">documento NFO</comment>
<comment xml:lang="pt_BR">Documento NFO</comment>
<comment xml:lang="ro">Document NFO</comment>
- <comment xml:lang="ru">документ NFO</comment>
+ <comment xml:lang="ru">Документ NFO</comment>
<comment xml:lang="sk">Dokument NFO</comment>
<comment xml:lang="sl">Dokument NFO</comment>
<comment xml:lang="sq">Dokument NFO</comment>
@@ -35018,7 +36081,7 @@
<comment xml:lang="pt">ficheiro de especificações RPM</comment>
<comment xml:lang="pt_BR">Arquivo de especificação RPM</comment>
<comment xml:lang="ro">Fișier RPM spec</comment>
- <comment xml:lang="ru">файл опиÑÐ°Ð½Ð¸Ñ RPM</comment>
+ <comment xml:lang="ru">Файл опиÑÐ°Ð½Ð¸Ñ RPM</comment>
<comment xml:lang="sk">Súbor RPM spec</comment>
<comment xml:lang="sl">DoloÄilna datoteka RPM</comment>
<comment xml:lang="sq">File specifikimi RPM</comment>
@@ -35041,18 +36104,27 @@
<mime-type type="text/x-sass">
<comment>Sass CSS pre-processor file</comment>
<comment xml:lang="ca">fitxer preprocessador CSS Sass</comment>
+ <comment xml:lang="cs">soubor preprocesoru Sass CSS</comment>
<comment xml:lang="da">Sass CSS-forbrænderfil</comment>
<comment xml:lang="de">Sass-CSS-Präprozessordatei</comment>
+ <comment xml:lang="en_GB">Sass CSS pre-processor file</comment>
<comment xml:lang="es">archivo de preprocesador de CSS Sass</comment>
<comment xml:lang="fr">fichier de prétraitement CSS Sass</comment>
+ <comment xml:lang="ga">comhad réamhphróiseálaí CSS Sass</comment>
<comment xml:lang="he">קובץ ×§×“× ×¢×™×‘×•×“ Sass CSS</comment>
+ <comment xml:lang="hr">Sass CSS datoteka predobrade</comment>
<comment xml:lang="hu">Sass CSS előfeldolgozó fájl</comment>
+ <comment xml:lang="id">berkas pre-processor Sass CSS</comment>
+ <comment xml:lang="it">File CSS Sass</comment>
<comment xml:lang="kk">Sass CSS препроцеÑÑор файлы</comment>
<comment xml:lang="ko">Sass CSS 전처리기 파ì¼</comment>
<comment xml:lang="pl">Plik preprocesora CSS Sass</comment>
<comment xml:lang="pt_BR">Arquivo de pré-processamento Sass CSS</comment>
- <comment xml:lang="ru">файл препроцеÑÑора Sass CSS</comment>
+ <comment xml:lang="ru">Файл препроцеÑÑора Sass CSS</comment>
<comment xml:lang="sk">Súbor Sass CSS pre-procesora</comment>
+ <comment xml:lang="sr">датотека Ð¡Ð°Ñ Ð¦Ð¡Ð¡ пре-процеÑора</comment>
+ <comment xml:lang="sv">Sass CSS-preprocessorfil</comment>
+ <comment xml:lang="tr">Sass CSS önişlemci dosyası</comment>
<comment xml:lang="uk">файл препроцеÑора CSS Sass</comment>
<comment xml:lang="zh_CN">Sass CSS 预处ç†å™¨æ–‡ä»¶</comment>
<comment xml:lang="zh_TW">Sass CSS 處ç†å™¨å‰æª”案</comment>
@@ -35073,9 +36145,10 @@
<comment xml:lang="eu">Scala iturburu-kodea</comment>
<comment xml:lang="fi">Scala-lähdekoodi</comment>
<comment xml:lang="fr">code source Scala</comment>
+ <comment xml:lang="ga">cód foinseach Scala</comment>
<comment xml:lang="gl">código fnote en Scala</comment>
<comment xml:lang="he">קוד מקור של Scala</comment>
- <comment xml:lang="hr">Scala izvorni kod</comment>
+ <comment xml:lang="hr">Scala izvorni kôd</comment>
<comment xml:lang="hu">Scala forráskód</comment>
<comment xml:lang="ia">Codice-fonte Scala</comment>
<comment xml:lang="id">Kode sumber Scala</comment>
@@ -35090,7 +36163,7 @@
<comment xml:lang="pl">Kod źródłowy Scala</comment>
<comment xml:lang="pt">código origem Scala</comment>
<comment xml:lang="pt_BR">Código-fonte Scala</comment>
- <comment xml:lang="ru">иÑходный код Scala</comment>
+ <comment xml:lang="ru">ИÑходный код Scala</comment>
<comment xml:lang="sk">Zdrojový kód Scala</comment>
<comment xml:lang="sl">Izvorna koda Scala</comment>
<comment xml:lang="sr">Скала изворни ко̂д</comment>
@@ -35124,7 +36197,7 @@
<comment xml:lang="ga">cód foinseach Scheme</comment>
<comment xml:lang="gl">código fonte en Scheme</comment>
<comment xml:lang="he">קוד מקור של Scheme</comment>
- <comment xml:lang="hr">Scheme izvorni kod</comment>
+ <comment xml:lang="hr">Scheme izvorni kôd</comment>
<comment xml:lang="hu">Scheme-forráskód</comment>
<comment xml:lang="ia">Codice-fonte Scheme</comment>
<comment xml:lang="id">Kode program Scheme</comment>
@@ -35143,7 +36216,7 @@
<comment xml:lang="pt">código origem Scheme</comment>
<comment xml:lang="pt_BR">Código-fonte Scheme</comment>
<comment xml:lang="ro">Cod sursă Scheme</comment>
- <comment xml:lang="ru">иÑходный код Scheme</comment>
+ <comment xml:lang="ru">ИÑходный код Scheme</comment>
<comment xml:lang="sk">Zdrojový kód Scheme</comment>
<comment xml:lang="sl">Datoteka izvorne kode Scheme</comment>
<comment xml:lang="sq">Kod burues Scheme</comment>
@@ -35161,18 +36234,27 @@
<mime-type type="text/x-scss">
<comment>Sass CSS pre-processor file</comment>
<comment xml:lang="ca">fitxer preprocessador CSS Sass</comment>
+ <comment xml:lang="cs">soubor preprocesoru Sass CSS</comment>
<comment xml:lang="da">Sass CSS-forbrænderfil</comment>
<comment xml:lang="de">Sass-CSS-Präprozessordatei</comment>
+ <comment xml:lang="en_GB">Sass CSS pre-processor file</comment>
<comment xml:lang="es">archivo de preprocesador de CSS Sass</comment>
<comment xml:lang="fr">fichier de prétraitement CSS Sass</comment>
+ <comment xml:lang="ga">comhad réamhphróiseálaí CSS Sass</comment>
<comment xml:lang="he">קובץ ×§×“× ×¢×™×‘×•×“ Sass CSS</comment>
+ <comment xml:lang="hr">Sass CSS datoteka predobrade</comment>
<comment xml:lang="hu">Sass CSS előfeldolgozó fájl</comment>
+ <comment xml:lang="id">berkas pre-processor Sass CSS</comment>
+ <comment xml:lang="it">File CSS Sass</comment>
<comment xml:lang="kk">Sass CSS препроцеÑÑор файлы</comment>
<comment xml:lang="ko">Sass CSS 전처리기 파ì¼</comment>
<comment xml:lang="pl">Plik preprocesora CSS Sass</comment>
<comment xml:lang="pt_BR">Arquivo de pré-processamento Sass CSS</comment>
- <comment xml:lang="ru">файл препроцеÑÑора Sass CSS</comment>
+ <comment xml:lang="ru">Файл препроцеÑÑора Sass CSS</comment>
<comment xml:lang="sk">Súbor Sass CSS pre-procesora</comment>
+ <comment xml:lang="sr">датотека Ð¡Ð°Ñ Ð¦Ð¡Ð¡ пре-процеÑора</comment>
+ <comment xml:lang="sv">Sass CSS-preprocessorfil</comment>
+ <comment xml:lang="tr">Sass CSS önişlemci dosyası</comment>
<comment xml:lang="uk">файл препроцеÑора CSS Sass</comment>
<comment xml:lang="zh_CN">Sass CSS 预处ç†å™¨æ–‡ä»¶</comment>
<comment xml:lang="zh_TW">Sass CSS 處ç†å™¨å‰æª”案</comment>
@@ -35183,6 +36265,7 @@
<mime-type type="text/x-setext">
<comment>Setext document</comment>
<comment xml:lang="ar">مستند Setext</comment>
+ <comment xml:lang="ast">Documentu Setext</comment>
<comment xml:lang="az">Setext sənədi</comment>
<comment xml:lang="be@latin">Dakument Setext</comment>
<comment xml:lang="bg">Документ — Setext</comment>
@@ -35221,7 +36304,7 @@
<comment xml:lang="pt">documento Setext</comment>
<comment xml:lang="pt_BR">Documento Setext</comment>
<comment xml:lang="ro">Document Setext</comment>
- <comment xml:lang="ru">документ Setext</comment>
+ <comment xml:lang="ru">Документ Setext</comment>
<comment xml:lang="sk">Dokument Setext</comment>
<comment xml:lang="sl">Dokument Setext</comment>
<comment xml:lang="sq">Dokument Setext</comment>
@@ -35257,7 +36340,7 @@
<comment xml:lang="ga">cód SQL</comment>
<comment xml:lang="gl">código SQL</comment>
<comment xml:lang="he">קוד SQL</comment>
- <comment xml:lang="hr">SQL kod</comment>
+ <comment xml:lang="hr">SQL kôd</comment>
<comment xml:lang="hu">SQL-kód</comment>
<comment xml:lang="ia">Codice SQL</comment>
<comment xml:lang="id">Kode SQL</comment>
@@ -35276,7 +36359,7 @@
<comment xml:lang="pt">código SQL</comment>
<comment xml:lang="pt_BR">Código SQL</comment>
<comment xml:lang="ro">Cod SQL</comment>
- <comment xml:lang="ru">код SQL</comment>
+ <comment xml:lang="ru">Код SQL</comment>
<comment xml:lang="sk">Kód SQL</comment>
<comment xml:lang="sl">Datoteka kode SQL</comment>
<comment xml:lang="sq">Kod SQL</comment>
@@ -35330,7 +36413,7 @@
<comment xml:lang="pt">script Tcl</comment>
<comment xml:lang="pt_BR">Script Tcl</comment>
<comment xml:lang="ro">Script Tcl</comment>
- <comment xml:lang="ru">Ñценарий Tcl</comment>
+ <comment xml:lang="ru">Сценарий Tcl</comment>
<comment xml:lang="sk">Skript Tcl</comment>
<comment xml:lang="sl">Skriptna datoteka Tcl</comment>
<comment xml:lang="sq">Script Tcl</comment>
@@ -35348,6 +36431,7 @@
<mime-type type="text/x-tex">
<comment>TeX document</comment>
<comment xml:lang="ar">مستند TeX</comment>
+ <comment xml:lang="ast">Documentu TeX</comment>
<comment xml:lang="be@latin">Dakument TeX</comment>
<comment xml:lang="bg">Документ — TeX</comment>
<comment xml:lang="ca">document TeX</comment>
@@ -35385,7 +36469,7 @@
<comment xml:lang="pt">documento TeX</comment>
<comment xml:lang="pt_BR">Documento TeX</comment>
<comment xml:lang="ro">Document TeX</comment>
- <comment xml:lang="ru">документ TeX</comment>
+ <comment xml:lang="ru">Документ TeX</comment>
<comment xml:lang="sk">Dokument TeX</comment>
<comment xml:lang="sl">Dokument TeX</comment>
<comment xml:lang="sq">Dokument TeX</comment>
@@ -35415,6 +36499,7 @@
<mime-type type="text/x-texinfo">
<comment>TeXInfo document</comment>
<comment xml:lang="ar">مستند TeXInfo</comment>
+ <comment xml:lang="ast">Documentu TeXInfo</comment>
<comment xml:lang="az">TeXInfo sənədi</comment>
<comment xml:lang="be@latin">Dakument TeXInfo</comment>
<comment xml:lang="bg">Документ — TeXInfo</comment>
@@ -35453,7 +36538,7 @@
<comment xml:lang="pt">documento TeXInfo</comment>
<comment xml:lang="pt_BR">Documento TeXInfo</comment>
<comment xml:lang="ro">Document TexInfo</comment>
- <comment xml:lang="ru">документ TeXInfo</comment>
+ <comment xml:lang="ru">Документ TeXInfo</comment>
<comment xml:lang="sk">Dokument TeXInfo</comment>
<comment xml:lang="sl">Dokument TeXInfo</comment>
<comment xml:lang="sq">Dokument TeXInfo</comment>
@@ -35471,6 +36556,7 @@
<mime-type type="text/x-troff-me">
<comment>Troff ME input document</comment>
<comment xml:lang="ar">مستند Troff ME input</comment>
+ <comment xml:lang="ast">Documentu d'entrada de Troff ME</comment>
<comment xml:lang="be@latin">Uvodny dakument Troff ME</comment>
<comment xml:lang="bg">Изходен документ — Troff ME</comment>
<comment xml:lang="ca">document d'entrada Troff ME</comment>
@@ -35485,7 +36571,7 @@
<comment xml:lang="fi">Troff ME -syöteasiakirja</comment>
<comment xml:lang="fo">Troff ME inntaksskjal</comment>
<comment xml:lang="fr">document d'entrée Troff ME</comment>
- <comment xml:lang="ga">cáipéis ionchur Troff ME</comment>
+ <comment xml:lang="ga">cáipéis ionchurtha Troff ME</comment>
<comment xml:lang="gl">documento de entrada Troff ME</comment>
<comment xml:lang="he">מסמך קלט של Troff ME</comment>
<comment xml:lang="hr">Troff ME ulazni dokument</comment>
@@ -35507,7 +36593,7 @@
<comment xml:lang="pt">documento origem Troff ME</comment>
<comment xml:lang="pt_BR">Documento de entrada Troff ME</comment>
<comment xml:lang="ro">Document intrare Troff ME</comment>
- <comment xml:lang="ru">входной документ Troff ME</comment>
+ <comment xml:lang="ru">Входной документ Troff ME</comment>
<comment xml:lang="sk">Vstupný dokument Troff ME</comment>
<comment xml:lang="sl">Vnosni dokument Troff ME</comment>
<comment xml:lang="sq">Dokument i input Troff ME</comment>
@@ -35524,6 +36610,7 @@
<mime-type type="text/x-troff-mm">
<comment>Troff MM input document</comment>
<comment xml:lang="ar">مستند Troff MM input</comment>
+ <comment xml:lang="ast">Documentu d'entrada de Troff MM</comment>
<comment xml:lang="be@latin">Uvodny dakument Troff MM</comment>
<comment xml:lang="bg">Изходен документ — Troff MM</comment>
<comment xml:lang="ca">document d'entrada Troff MM</comment>
@@ -35538,7 +36625,7 @@
<comment xml:lang="fi">Troff MM -syöteasiakirja</comment>
<comment xml:lang="fo">Troff MM inntaksskjal</comment>
<comment xml:lang="fr">document d'entrée Troff MM</comment>
- <comment xml:lang="ga">cáipéis ionchur Troff MM</comment>
+ <comment xml:lang="ga">cáipéis ionchurtha Troff MM</comment>
<comment xml:lang="gl">documento de entrada Troff MM</comment>
<comment xml:lang="he">מסמך קלט של Troff MM</comment>
<comment xml:lang="hr">Troff MM ulazni dokument</comment>
@@ -35560,7 +36647,7 @@
<comment xml:lang="pt">documento origem Troff MM</comment>
<comment xml:lang="pt_BR">Documento de entrada Troff MM</comment>
<comment xml:lang="ro">Document intrare Troff MM</comment>
- <comment xml:lang="ru">входной документ Troff MM</comment>
+ <comment xml:lang="ru">Входной документ Troff MM</comment>
<comment xml:lang="sk">Vstupný dokument Troff MM</comment>
<comment xml:lang="sl">Vnosni dokument Troff MM</comment>
<comment xml:lang="sq">Dokument i input Troff MM</comment>
@@ -35577,6 +36664,7 @@
<mime-type type="text/x-troff-ms">
<comment>Troff MS input document</comment>
<comment xml:lang="ar">مستند Troff MS input</comment>
+ <comment xml:lang="ast">Documentu d'entrada de Troff MS</comment>
<comment xml:lang="be@latin">Uvodny dakument Troff MS</comment>
<comment xml:lang="bg">Изходен документ — Troff MS</comment>
<comment xml:lang="ca">document d'entrada Troff MS</comment>
@@ -35591,7 +36679,7 @@
<comment xml:lang="fi">Troff MS -syöteasiakirja</comment>
<comment xml:lang="fo">Troff MS inntaksskjal</comment>
<comment xml:lang="fr">document d'entrée Troff MS</comment>
- <comment xml:lang="ga">cáipéis ionchur Troff MS</comment>
+ <comment xml:lang="ga">cáipéis ionchurtha Troff MS</comment>
<comment xml:lang="gl">documento de entrada Troff MS</comment>
<comment xml:lang="he">מסמך קלט של Troff MS</comment>
<comment xml:lang="hr">Troff MS ulazni dokument</comment>
@@ -35613,7 +36701,7 @@
<comment xml:lang="pt">documento origem Troff MS</comment>
<comment xml:lang="pt_BR">Documento de entrada Troff MS</comment>
<comment xml:lang="ro">Document intrare Troff MS</comment>
- <comment xml:lang="ru">входной документ Troff MS</comment>
+ <comment xml:lang="ru">Входной документ Troff MS</comment>
<comment xml:lang="sk">Vstupný dokument Troff MS</comment>
<comment xml:lang="sl">Vnosni dokument Troff MS</comment>
<comment xml:lang="sq">Dokument i input Troff MS</comment>
@@ -35630,18 +36718,28 @@
<mime-type type="text/x-twig">
<comment>Twig template</comment>
<comment xml:lang="ca">plantilla Twig</comment>
+ <comment xml:lang="cs">Å¡ablona Twig</comment>
<comment xml:lang="da">Twig-skabelon</comment>
<comment xml:lang="de">Twig-Vorlage</comment>
+ <comment xml:lang="en_GB">Twig template</comment>
<comment xml:lang="es">plantilla de Twig</comment>
+ <comment xml:lang="eu">Twig txantiloia</comment>
<comment xml:lang="fr">modèle Twig</comment>
+ <comment xml:lang="ga">teimpléad Twig</comment>
<comment xml:lang="he">תבנית Twig</comment>
+ <comment xml:lang="hr">Twig predložak</comment>
<comment xml:lang="hu">Twig-sablon</comment>
+ <comment xml:lang="id">templat Twig</comment>
+ <comment xml:lang="it">Modello twig</comment>
<comment xml:lang="kk">Twig үлгіÑÑ–</comment>
<comment xml:lang="ko">Twig 문서 ì„œì‹</comment>
<comment xml:lang="pl">Szablon Twig</comment>
<comment xml:lang="pt_BR">Modelo Twig</comment>
- <comment xml:lang="ru">шаблон Twig</comment>
+ <comment xml:lang="ru">Шаблон Twig</comment>
<comment xml:lang="sk">Šablóna Twig</comment>
+ <comment xml:lang="sr">Твиг шаблон</comment>
+ <comment xml:lang="sv">Twig-mall</comment>
+ <comment xml:lang="tr">Twig ÅŸablonu</comment>
<comment xml:lang="uk">шаблон twig</comment>
<comment xml:lang="zh_CN">Twig 模æ¿</comment>
<comment xml:lang="zh_TW">Twig 範本</comment>
@@ -35687,7 +36785,7 @@
<comment xml:lang="pt">tabela UIL do X-Motif</comment>
<comment xml:lang="pt_BR">Tabela UIL do X-Motif</comment>
<comment xml:lang="ro">Tabel X-Motif UIL</comment>
- <comment xml:lang="ru">таблица UIL X-Motif</comment>
+ <comment xml:lang="ru">Таблица UIL X-Motif</comment>
<comment xml:lang="sk">Tabuľka X-Motif UIL</comment>
<comment xml:lang="sl">Preglednica X-Motif UIL</comment>
<comment xml:lang="sq">Tabelë X-Motif UIL</comment>
@@ -35721,7 +36819,7 @@
<comment xml:lang="ga">suíomh acmhainne</comment>
<comment xml:lang="gl">localización do recurso</comment>
<comment xml:lang="he">×ž×™×§×•× ×©×œ מש×ב</comment>
- <comment xml:lang="hr">položaj resursa</comment>
+ <comment xml:lang="hr">Lokacija resursa</comment>
<comment xml:lang="hu">erőforrás-hely</comment>
<comment xml:lang="ia">Loco de ressources</comment>
<comment xml:lang="id">lokasi sumber daya</comment>
@@ -35740,7 +36838,7 @@
<comment xml:lang="pt">localização de recurso</comment>
<comment xml:lang="pt_BR">Localização de recurso</comment>
<comment xml:lang="ro">locație de resursă</comment>
- <comment xml:lang="ru">раÑположение реÑурÑа</comment>
+ <comment xml:lang="ru">РаÑположение реÑурÑа</comment>
<comment xml:lang="sk">Umiestnenie zdroja</comment>
<comment xml:lang="sl">mesto vira</comment>
<comment xml:lang="sq">Pozicion rezerve</comment>
@@ -35765,6 +36863,7 @@
<comment xml:lang="es">archivo codificado con uuencode</comment>
<comment xml:lang="eu">uuencode-aturiko fitxategia</comment>
<comment xml:lang="fr">fichier uuencodé</comment>
+ <comment xml:lang="ga">comhad uuencoded</comment>
<comment xml:lang="gl">Ficheiro uuencoded</comment>
<comment xml:lang="he">קובץ בקידוד uu</comment>
<comment xml:lang="hr">uuencoded datoteka</comment>
@@ -35780,14 +36879,14 @@
<comment xml:lang="pl">Plik zakodowany za pomocÄ… uuencode</comment>
<comment xml:lang="pt">ficheiro uuencoded</comment>
<comment xml:lang="pt_BR">Arquivo codificado UUE</comment>
- <comment xml:lang="ru">файл в кодировке uuencode</comment>
+ <comment xml:lang="ru">Файл, кодированный uuencode</comment>
<comment xml:lang="sk">Súbor v kódovaní uuencode</comment>
<comment xml:lang="sl">Datoteka uuencode</comment>
<comment xml:lang="sr">уукодирана датотека</comment>
<comment xml:lang="sv">uuencode-fil</comment>
<comment xml:lang="tr">uuencoded dosyası</comment>
<comment xml:lang="uk">файл даних у форматі UUE</comment>
- <comment xml:lang="zh_CN">未编ç çš„文件</comment>
+ <comment xml:lang="zh_CN">Uuencode 文件</comment>
<comment xml:lang="zh_TW">uuencoded 檔</comment>
<sub-class-of type="text/plain"/>
<glob pattern="*.uue"/>
@@ -35834,7 +36933,7 @@
<comment xml:lang="pt">ficheiro XMI</comment>
<comment xml:lang="pt_BR">Arquivo XMI</comment>
<comment xml:lang="ro">Fișier XMI</comment>
- <comment xml:lang="ru">файл XMI</comment>
+ <comment xml:lang="ru">Файл XMI</comment>
<comment xml:lang="sk">Súbor XMI</comment>
<comment xml:lang="sl">Datoteka XMI</comment>
<comment xml:lang="sq">File XMI</comment>
@@ -35890,7 +36989,7 @@
<comment xml:lang="pt">ficheiro XSL FO</comment>
<comment xml:lang="pt_BR">Arquivo XSL FO</comment>
<comment xml:lang="ro">Fișier XSL FO</comment>
- <comment xml:lang="ru">файл XSL FO</comment>
+ <comment xml:lang="ru">Файл XSL FO</comment>
<comment xml:lang="sk">Súbor XSL FO</comment>
<comment xml:lang="sl">Datoteka XSL FO</comment>
<comment xml:lang="sq">File XSL FO</comment>
@@ -35911,6 +37010,7 @@
<mime-type type="text/x-iptables">
<comment>iptables configuration file</comment>
<comment xml:lang="ar">مل٠تضبيط iptables</comment>
+ <comment xml:lang="ast">ficheru de configuración d'iptables</comment>
<comment xml:lang="be@latin">kanfihuracyjny fajł iptables</comment>
<comment xml:lang="bg">ÐаÑтройки за iptables</comment>
<comment xml:lang="ca">fitxer de configuració d'iptables</comment>
@@ -35927,7 +37027,7 @@
<comment xml:lang="ga">comhad cumraíochta iptables</comment>
<comment xml:lang="gl">ficheiro de configuración de iptables</comment>
<comment xml:lang="he">קובץ הגדרה של iptables</comment>
- <comment xml:lang="hr">iptables datoteka s postavkama</comment>
+ <comment xml:lang="hr">iptables datoteka podešavanja</comment>
<comment xml:lang="hu">iptables beállítófájl</comment>
<comment xml:lang="ia">File de configuration IPTables</comment>
<comment xml:lang="id">berkas konfigurasi iptables</comment>
@@ -35945,7 +37045,7 @@
<comment xml:lang="pt">ficheiro de configuração iptables</comment>
<comment xml:lang="pt_BR">Arquivo de configuração do iptables</comment>
<comment xml:lang="ro">fișier configurare iptables</comment>
- <comment xml:lang="ru">файл наÑтроек iptables</comment>
+ <comment xml:lang="ru">Файл наÑтроек iptables</comment>
<comment xml:lang="sk">Súbor nastavení iptables</comment>
<comment xml:lang="sl">nastavitvena datoteka iptables</comment>
<comment xml:lang="sq">File konfigurimi iptables</comment>
@@ -35979,6 +37079,110 @@
</magic>
<glob pattern="*.iptables"/>
</mime-type>
+ <mime-type type="text/x-dbus-service">
+ <comment>D-Bus service file</comment>
+ <comment xml:lang="ca">fitxer de servei de D-Bus</comment>
+ <comment xml:lang="cs">soubor služby D-Bus</comment>
+ <comment xml:lang="de">D-Bus-Dienstdatei</comment>
+ <comment xml:lang="en_GB">D-Bus service file</comment>
+ <comment xml:lang="es">archivo de servicio de D-Bus</comment>
+ <comment xml:lang="eu">D-Bus zerbitzu fitxategia</comment>
+ <comment xml:lang="fi">D-Bus-palvelutiedosto</comment>
+ <comment xml:lang="fr">fichier de service D-Bus</comment>
+ <comment xml:lang="ga">comhad seirbhíse D-Bus</comment>
+ <comment xml:lang="hr">Datoteka D-Bus usluge</comment>
+ <comment xml:lang="hu">D-Bus szolgáltatás fájl</comment>
+ <comment xml:lang="id">berkas layanan D-Bus</comment>
+ <comment xml:lang="it">File servizio D-Bus</comment>
+ <comment xml:lang="kk">D-Bus қызметтік файлы</comment>
+ <comment xml:lang="ko">D-Bus 서비스 파ì¼</comment>
+ <comment xml:lang="pl">Plik usługi D-Bus</comment>
+ <comment xml:lang="pt_BR">Arquivo de serviço do D-Bus</comment>
+ <comment xml:lang="ru">Файл Ñлужбы D-Bus</comment>
+ <comment xml:lang="sk">Súbor služby D-Bus</comment>
+ <comment xml:lang="sr">датотека уÑлуге Д-Ñабирнице</comment>
+ <comment xml:lang="sv">D-BUS-tjänstfil</comment>
+ <comment xml:lang="tr">D-Bus hizmeti dosyası</comment>
+ <comment xml:lang="uk">файл Ñлужби D-Bus</comment>
+ <comment xml:lang="zh_CN">D-Bus æœåŠ¡æ–‡ä»¶</comment>
+ <comment xml:lang="zh_TW">D-Bus æœå‹™æª”</comment>
+ <sub-class-of type="text/plain"/>
+ <magic priority="50">
+ <match value="\n[D-BUS Service]\n" type="string" offset="0:256"/>
+ <match value="[D-BUS Service]\n" type="string" offset="0"/>
+ </magic>
+ <glob pattern="*.service"/>
+ </mime-type>
+ <mime-type type="text/x-systemd-unit">
+ <comment>systemd unit file</comment>
+ <comment xml:lang="ast">ficheru d'unidaes de systemd</comment>
+ <comment xml:lang="ca">fitxer d'unitat de systemd</comment>
+ <comment xml:lang="cs">jednotkový soubor systemd</comment>
+ <comment xml:lang="de">systemd-Einheitsdatei</comment>
+ <comment xml:lang="en_GB">systemd unit file</comment>
+ <comment xml:lang="es">archivo de unidad de systemd</comment>
+ <comment xml:lang="eu">systemd unitate fitxategia</comment>
+ <comment xml:lang="fi">systemd-yksikkötiedosto</comment>
+ <comment xml:lang="fr">fichier d'unité systemd</comment>
+ <comment xml:lang="ga">comhad aonaid systemd</comment>
+ <comment xml:lang="hr">Datoteka systemd jedinice</comment>
+ <comment xml:lang="hu">systemd egység fájl</comment>
+ <comment xml:lang="id">berkas unit systemd</comment>
+ <comment xml:lang="it">File unità systemd</comment>
+ <comment xml:lang="kk">systemd юнит файлы</comment>
+ <comment xml:lang="ko">systemd 유닛 파ì¼</comment>
+ <comment xml:lang="pl">Plik jednostki systemd</comment>
+ <comment xml:lang="pt_BR">Arquivo de unit do systemd</comment>
+ <comment xml:lang="ru">Модульный файл Systemd</comment>
+ <comment xml:lang="sk">Súbor jednotky systemd</comment>
+ <comment xml:lang="sr">датотека јединице ÑиÑтемд-а</comment>
+ <comment xml:lang="sv">systemd-enhetsfil</comment>
+ <comment xml:lang="tr">systemd birim dosyası</comment>
+ <comment xml:lang="uk">файл Ð¼Ð¾Ð´ÑƒÐ»Ñ systemd</comment>
+ <comment xml:lang="zh_CN">systemd å•å…ƒæ–‡ä»¶</comment>
+ <comment xml:lang="zh_TW">systemd å–®ä½æª”</comment>
+ <sub-class-of type="text/plain"/>
+ <magic priority="50">
+
+ <match value="\n[Unit]\n" type="string" offset="0:256"/>
+ <match value="\n[Install]\n" type="string" offset="0:256"/>
+ <match value="\n[Automount]\n" type="string" offset="0:256"/>
+
+ <match value="\n[Mount]\n" type="string" offset="0:256"/>
+ <match value="\n[Path]\n" type="string" offset="0:256"/>
+ <match value="\n[Scope]\n" type="string" offset="0:256"/>
+ <match value="\n[Service]\n" type="string" offset="0:256"/>
+ <match value="\n[Slice]\n" type="string" offset="0:256"/>
+ <match value="\n[Socket]\n" type="string" offset="0:256"/>
+ <match value="\n[Swap]\n" type="string" offset="0:256"/>
+
+ <match value="\n[Timer]\n" type="string" offset="0:256"/>
+
+
+ <match value="[Unit]\n" type="string" offset="0"/>
+ <match value="[Install]\n" type="string" offset="0"/>
+ <match value="[Automount]\n" type="string" offset="0"/>
+ <match value="[Mount]\n" type="string" offset="0"/>
+ <match value="[Path]\n" type="string" offset="0"/>
+ <match value="[Scope]\n" type="string" offset="0"/>
+ <match value="[Service]\n" type="string" offset="0"/>
+ <match value="[Slice]\n" type="string" offset="0"/>
+ <match value="[Socket]\n" type="string" offset="0"/>
+ <match value="[Swap]\n" type="string" offset="0"/>
+ <match value="[Timer]\n" type="string" offset="0"/>
+ </magic>
+ <glob pattern="*.automount"/>
+ <glob pattern="*.device"/>
+ <glob pattern="*.mount"/>
+ <glob pattern="*.path"/>
+ <glob pattern="*.scope"/>
+ <glob pattern="*.service"/>
+ <glob pattern="*.slice"/>
+ <glob pattern="*.socket"/>
+ <glob pattern="*.swap"/>
+ <glob pattern="*.target"/>
+ <glob pattern="*.timer"/>
+ </mime-type>
<mime-type type="application/xslt+xml">
<comment>XSLT stylesheet</comment>
<comment xml:lang="ar">نمط XSLT</comment>
@@ -36018,7 +37222,7 @@
<comment xml:lang="pt">folha de estilos XSLT</comment>
<comment xml:lang="pt_BR">Folha de estilo XSLT</comment>
<comment xml:lang="ro">Fișă de stil XSLT</comment>
- <comment xml:lang="ru">таблица Ñтилей XSLT</comment>
+ <comment xml:lang="ru">Таблица Ñтилей XSLT</comment>
<comment xml:lang="sk">Štýl XSLT</comment>
<comment xml:lang="sl">Slogovna predloga XSLT</comment>
<comment xml:lang="sq">Fletë stili XSLT</comment>
@@ -36077,7 +37281,7 @@
<comment xml:lang="pt">base de dados XMCD CD</comment>
<comment xml:lang="pt_BR">Banco de dados de CD XMCD</comment>
<comment xml:lang="ro">Bază de date XMCD CD</comment>
- <comment xml:lang="ru">база данных компакт-диÑков XMCD</comment>
+ <comment xml:lang="ru">База данных компакт-диÑков XMCD</comment>
<comment xml:lang="sk">Databáza XMCD CD</comment>
<comment xml:lang="sl">Podatkovna zbirka XMCD CD</comment>
<comment xml:lang="sq">Bazë me të dhëna XMCD CD</comment>
@@ -36096,6 +37300,7 @@
<mime-type type="application/xml">
<comment>XML document</comment>
<comment xml:lang="ar">مستند XML</comment>
+ <comment xml:lang="ast">Documentu XML</comment>
<comment xml:lang="be@latin">Dakument XML</comment>
<comment xml:lang="bg">Документ — XML</comment>
<comment xml:lang="ca">document XML</comment>
@@ -36131,7 +37336,7 @@
<comment xml:lang="pt">documento XML</comment>
<comment xml:lang="pt_BR">Documento XML</comment>
<comment xml:lang="ro">Document XML</comment>
- <comment xml:lang="ru">документ XML</comment>
+ <comment xml:lang="ru">Документ XML</comment>
<comment xml:lang="sk">Dokument XML</comment>
<comment xml:lang="sl">Dokument XML</comment>
<comment xml:lang="sq">Dokument XML</comment>
@@ -36159,6 +37364,7 @@
<mime-type type="application/xml-external-parsed-entity">
<comment>XML entities document</comment>
<comment xml:lang="ar">مستند كيانات XML</comment>
+ <comment xml:lang="ast">Documentu d'entidaes XML</comment>
<comment xml:lang="be@latin">Dakument elementaÅ­ XML</comment>
<comment xml:lang="bg">Документ — замеÑтващи поÑледователноÑти в XML</comment>
<comment xml:lang="ca">document d'entitats XML</comment>
@@ -36193,7 +37399,7 @@
<comment xml:lang="pt">documento de entidades XML</comment>
<comment xml:lang="pt_BR">Documento de entidades XML</comment>
<comment xml:lang="ro">Document entități XML</comment>
- <comment xml:lang="ru">файл ÑущноÑтей XML</comment>
+ <comment xml:lang="ru">Файл ÑущноÑтей XML</comment>
<comment xml:lang="sk">Dokument entít XML</comment>
<comment xml:lang="sl">Dokument XML doloÄil</comment>
<comment xml:lang="sq">Dokument njësish XML</comment>
@@ -36214,6 +37420,7 @@
<mime-type type="video/dv">
<comment>DV video</comment>
<comment xml:lang="ar">DV مرئي</comment>
+ <comment xml:lang="ast">Videu en DV</comment>
<comment xml:lang="be@latin">Videa DV</comment>
<comment xml:lang="bg">Видео — DV</comment>
<comment xml:lang="ca">vídeo DV</comment>
@@ -36231,7 +37438,7 @@
<comment xml:lang="ga">físeán DV</comment>
<comment xml:lang="gl">vídeo DV</comment>
<comment xml:lang="he">ויד×ו DV</comment>
- <comment xml:lang="hr">DV video</comment>
+ <comment xml:lang="hr">DV video snimka</comment>
<comment xml:lang="hu">DV videó</comment>
<comment xml:lang="ia">Video DV</comment>
<comment xml:lang="id">Video DV</comment>
@@ -36250,7 +37457,7 @@
<comment xml:lang="pt">vídeo DV</comment>
<comment xml:lang="pt_BR">Vídeo DV</comment>
<comment xml:lang="ro">Video DV</comment>
- <comment xml:lang="ru">видео DV</comment>
+ <comment xml:lang="ru">Видео DV</comment>
<comment xml:lang="sk">Video DV</comment>
<comment xml:lang="sl">Video datoteka DV</comment>
<comment xml:lang="sq">Video DV</comment>
@@ -36271,6 +37478,7 @@
<mime-type type="video/isivideo">
<comment>ISI video</comment>
<comment xml:lang="ar">مرئي ISI</comment>
+ <comment xml:lang="ast">Videu n'ISI</comment>
<comment xml:lang="az">ISI video faylı</comment>
<comment xml:lang="be@latin">Videa ISI</comment>
<comment xml:lang="bg">Видео — ISI</comment>
@@ -36290,7 +37498,7 @@
<comment xml:lang="ga">físeán ISI</comment>
<comment xml:lang="gl">vídeo ISI</comment>
<comment xml:lang="he">ויד×ו ISI</comment>
- <comment xml:lang="hr">ISI video</comment>
+ <comment xml:lang="hr">ISI video snimka</comment>
<comment xml:lang="hu">ISI-videó</comment>
<comment xml:lang="ia">Video ISI</comment>
<comment xml:lang="id">Video ISI</comment>
@@ -36309,7 +37517,7 @@
<comment xml:lang="pt">vídeo ISI</comment>
<comment xml:lang="pt_BR">Vídeo ISI</comment>
<comment xml:lang="ro">Video ISI</comment>
- <comment xml:lang="ru">видео ISI</comment>
+ <comment xml:lang="ru">Видео ISI</comment>
<comment xml:lang="sk">Video ISI</comment>
<comment xml:lang="sl">Video datoteka ISI</comment>
<comment xml:lang="sq">Video ISI</comment>
@@ -36336,10 +37544,10 @@
<comment xml:lang="fi">MPEG-2 -siirtobittivirta</comment>
<comment xml:lang="fo">MPEG-2 flutningsstreymur</comment>
<comment xml:lang="fr">flux de transport MPEG-2</comment>
- <comment xml:lang="ga">Sruth aistrithe MPEG-2</comment>
+ <comment xml:lang="ga">sruth aistrithe MPEG-2</comment>
<comment xml:lang="gl">fluxo de transporte MPEG-2</comment>
<comment xml:lang="he">העברת זרימה של MPEG-2</comment>
- <comment xml:lang="hr">MPEG-2 transportni tok</comment>
+ <comment xml:lang="hr">MPEG-2 transportno strujanje</comment>
<comment xml:lang="hu">MPEG-2 átviteli adatfolyam</comment>
<comment xml:lang="ia">Fluxo de transporto MPEG-2</comment>
<comment xml:lang="id">Stream transport MPEG-2</comment>
@@ -36356,7 +37564,7 @@
<comment xml:lang="pt">fluxo de transporte MPEG-2</comment>
<comment xml:lang="pt_BR">Fluxo de transporte de MPEG-2</comment>
<comment xml:lang="ro">Flux transport MPEG-2</comment>
- <comment xml:lang="ru">транÑпортный поток MPEG-2</comment>
+ <comment xml:lang="ru">ТранÑпортный поток MPEG-2</comment>
<comment xml:lang="sk">MPEG-2 Transport Stream</comment>
<comment xml:lang="sl">PretoÄni vir prenosega MPEG</comment>
<comment xml:lang="sr">МПЕГ-2 ток преноÑа</comment>
@@ -36401,6 +37609,7 @@
<mime-type type="video/mpeg">
<comment>MPEG video</comment>
<comment xml:lang="ar">MPEG مرئي</comment>
+ <comment xml:lang="ast">Videu en MPEG</comment>
<comment xml:lang="be@latin">Videa MPEG</comment>
<comment xml:lang="bg">Видео — MPEG</comment>
<comment xml:lang="ca">vídeo MPEG</comment>
@@ -36418,7 +37627,7 @@
<comment xml:lang="ga">físeán MPEG</comment>
<comment xml:lang="gl">vídeo MPEG</comment>
<comment xml:lang="he">ויד×ו MPEG</comment>
- <comment xml:lang="hr">MPEG video</comment>
+ <comment xml:lang="hr">MPEG video snimka</comment>
<comment xml:lang="hu">MPEG-videó</comment>
<comment xml:lang="ia">Video MPEG</comment>
<comment xml:lang="id">Video MPEG</comment>
@@ -36438,7 +37647,7 @@
<comment xml:lang="pt">vídeo MPEG</comment>
<comment xml:lang="pt_BR">Vídeo MPEG</comment>
<comment xml:lang="ro">Video MPEG</comment>
- <comment xml:lang="ru">видео MPEG</comment>
+ <comment xml:lang="ru">Видео MPEG</comment>
<comment xml:lang="sk">Video MPEG</comment>
<comment xml:lang="sl">Video datoteka MPEG</comment>
<comment xml:lang="sq">Video MPEG</comment>
@@ -36469,6 +37678,7 @@
</mime-type>
<mime-type type="video/vnd.mpegurl">
<comment>MPEG video (streamed)</comment>
+ <comment xml:lang="ast">Videu en MPEG (tresmitíu)</comment>
<comment xml:lang="bg">Видео — MPEG, поточно</comment>
<comment xml:lang="ca">vídeo MPEG (flux)</comment>
<comment xml:lang="cs">video MPEG (proud)</comment>
@@ -36480,6 +37690,7 @@
<comment xml:lang="eu">MPEG bideoa (korronte bidez)</comment>
<comment xml:lang="fi">MPEG-video (virtaus)</comment>
<comment xml:lang="fr">vidéo MPEG (flux)</comment>
+ <comment xml:lang="ga">físeán MPEG (sruthaithe)</comment>
<comment xml:lang="gl">vídeo MPEG (en stream)</comment>
<comment xml:lang="he">קובץ MPEG (בהזרמה)</comment>
<comment xml:lang="hr">MPEG video snimka (strujanje)</comment>
@@ -36497,7 +37708,7 @@
<comment xml:lang="pl">Plik wideo MPEG (strumień)</comment>
<comment xml:lang="pt">vídeo MPEG (em fluxo)</comment>
<comment xml:lang="pt_BR">Vídeo MPEG (fluxo)</comment>
- <comment xml:lang="ru">видео MPEG (потоковое)</comment>
+ <comment xml:lang="ru">Видео MPEG (потоковое)</comment>
<comment xml:lang="sk">MPEG video (streamované)</comment>
<comment xml:lang="sl">MPEG-video (pretoÄni)</comment>
<comment xml:lang="sr">МПЕГ видео (проточни)</comment>
@@ -36518,6 +37729,7 @@
<mime-type type="video/quicktime">
<comment>QuickTime video</comment>
<comment xml:lang="ar">QuickTime مرئي</comment>
+ <comment xml:lang="ast">Videu en QuickTime</comment>
<comment xml:lang="be@latin">Videa QuickTime</comment>
<comment xml:lang="bg">Видео — QuickTime</comment>
<comment xml:lang="ca">vídeo QuickTime</comment>
@@ -36535,7 +37747,7 @@
<comment xml:lang="ga">físeán QuickTime</comment>
<comment xml:lang="gl">vídeo QuickTime</comment>
<comment xml:lang="he">ויד×ו של QuickTime</comment>
- <comment xml:lang="hr">QuickTime video</comment>
+ <comment xml:lang="hr">QuickTime video snimka</comment>
<comment xml:lang="hu">QuickTime videó</comment>
<comment xml:lang="ia">Video QuickTime</comment>
<comment xml:lang="id">Video QuickTime</comment>
@@ -36554,7 +37766,7 @@
<comment xml:lang="pt">vídeo QuickTime</comment>
<comment xml:lang="pt_BR">Vídeo do QuickTime</comment>
<comment xml:lang="ro">Video QuickTime</comment>
- <comment xml:lang="ru">видео QuickTime</comment>
+ <comment xml:lang="ru">Видео QuickTime</comment>
<comment xml:lang="sk">Video QuickTime</comment>
<comment xml:lang="sl">Video datoteka QuickTime</comment>
<comment xml:lang="sq">Video QuickTime</comment>
@@ -36614,7 +37826,7 @@
<comment xml:lang="pt">imagem QuickTime</comment>
<comment xml:lang="pt_BR">Imagem do QuickTime</comment>
<comment xml:lang="ro">Imagine QuickTime</comment>
- <comment xml:lang="ru">изображение QuickTime</comment>
+ <comment xml:lang="ru">Изображение QuickTime</comment>
<comment xml:lang="sk">Obrázok QuickTime</comment>
<comment xml:lang="sl">Slikovna datoteka QuickTime</comment>
<comment xml:lang="sq">Figurë QuickTime</comment>
@@ -36631,9 +37843,44 @@
<glob pattern="*.qtif"/>
<glob pattern="*.qif"/>
</mime-type>
+ <mime-type type="image/ktx">
+ <comment>Khronos texture image</comment>
+ <comment xml:lang="ca">imatge de textura de Khronos</comment>
+ <comment xml:lang="cs">obrázek s texturou Khronos</comment>
+ <comment xml:lang="de">Khronos-Texturbild</comment>
+ <comment xml:lang="en_GB">Khronos texture image</comment>
+ <comment xml:lang="es">imagen de textura de Khronos</comment>
+ <comment xml:lang="fr">image de texture Khronos</comment>
+ <comment xml:lang="ga">íomhá uigeachta Khronos</comment>
+ <comment xml:lang="hr">Khronos tekstura slika</comment>
+ <comment xml:lang="hu">Khronos textúra kép</comment>
+ <comment xml:lang="id">citra tekstur Khronos</comment>
+ <comment xml:lang="it">Immagine texture Khronos</comment>
+ <comment xml:lang="kk">Khronos текÑтура Ñуреті</comment>
+ <comment xml:lang="ko">í¬ë¡œë…¸ìŠ¤ í…스처 파ì¼</comment>
+ <comment xml:lang="pl">Obraz tekstury Khronos</comment>
+ <comment xml:lang="pt_BR">Imagem de textura do Khronos</comment>
+ <comment xml:lang="ru">Изображение текÑтуры Khronos</comment>
+ <comment xml:lang="sk">Obrázok textúry Khronos</comment>
+ <comment xml:lang="sr">Ñлика ÐšÑ€Ð¾Ð½Ð¾Ñ Ñ‚ÐµÐºÑтуре</comment>
+ <comment xml:lang="sv">Khronos-texturbild</comment>
+ <comment xml:lang="tr">Khronos kaplama görüntüsü</comment>
+ <comment xml:lang="uk">Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‚ÐµÐºÑтури Khronos</comment>
+ <comment xml:lang="zh_CN">Khronos 纹ç†å›¾åƒ</comment>
+ <comment xml:lang="zh_TW">Khronos ç´‹ç†å½±åƒ</comment>
+ <magic priority="80">
+ <match value="0xAB4B5458" type="big32" offset="0">
+ <match value="0x203131BB" type="big32" offset="4">
+ <match value="0x0D0A1A0A" type="big32" offset="8"/>
+ </match>
+ </match>
+ </magic>
+ <glob pattern="*.ktx"/>
+ </mime-type>
<mime-type type="video/vnd.vivo">
<comment>Vivo video</comment>
<comment xml:lang="ar">Vivo مرئي</comment>
+ <comment xml:lang="ast">Videu en Vivo</comment>
<comment xml:lang="az">Vivo video faylı</comment>
<comment xml:lang="be@latin">Videa Vivo</comment>
<comment xml:lang="bg">Видео — Vivo</comment>
@@ -36653,7 +37900,7 @@
<comment xml:lang="ga">físeán Vivo</comment>
<comment xml:lang="gl">vídeo Vivo</comment>
<comment xml:lang="he">ויד×ו של Vivo</comment>
- <comment xml:lang="hr">Vivo video</comment>
+ <comment xml:lang="hr">Vivo video snimka</comment>
<comment xml:lang="hu">Vivo-videó</comment>
<comment xml:lang="ia">Video Vivo</comment>
<comment xml:lang="id">Video Vivo</comment>
@@ -36672,7 +37919,7 @@
<comment xml:lang="pt">vídeo Vivo</comment>
<comment xml:lang="pt_BR">Vídeo Vivo</comment>
<comment xml:lang="ro">Video Vivo</comment>
- <comment xml:lang="ru">видео Vivo</comment>
+ <comment xml:lang="ru">Видео Vivo</comment>
<comment xml:lang="sk">Video Vivo</comment>
<comment xml:lang="sl">Video datoteka Vivo</comment>
<comment xml:lang="sq">Video Vivo</comment>
@@ -36690,6 +37937,7 @@
<mime-type type="video/wavelet">
<comment>Wavelet video</comment>
<comment xml:lang="ar">Wavelet مرئي</comment>
+ <comment xml:lang="ast">Videu en Wavelet</comment>
<comment xml:lang="az">Wavelet video faylı</comment>
<comment xml:lang="be@latin">Videa Wavelet</comment>
<comment xml:lang="bg">Видео — Wavelet</comment>
@@ -36709,7 +37957,7 @@
<comment xml:lang="ga">físeán Wavelet</comment>
<comment xml:lang="gl">vídeo Wavelet</comment>
<comment xml:lang="he">ויד×ו של Wavelet</comment>
- <comment xml:lang="hr">Wavelet video</comment>
+ <comment xml:lang="hr">Wavelet video snimka</comment>
<comment xml:lang="hu">Wavelet-videó</comment>
<comment xml:lang="ia">Video Wavelet</comment>
<comment xml:lang="id">Video Wavelet</comment>
@@ -36728,7 +37976,7 @@
<comment xml:lang="pt">vídeo Wavelet</comment>
<comment xml:lang="pt_BR">Vídeo Wavelet</comment>
<comment xml:lang="ro">Video Wavelet</comment>
- <comment xml:lang="ru">видео Wavelet</comment>
+ <comment xml:lang="ru">Видео Wavelet</comment>
<comment xml:lang="sk">Video Wavelet</comment>
<comment xml:lang="sl">Video datoteka Wavelet</comment>
<comment xml:lang="sq">Video Wavelet</comment>
@@ -36782,7 +38030,7 @@
<comment xml:lang="pt">animação ANIM</comment>
<comment xml:lang="pt_BR">Animação ANIM</comment>
<comment xml:lang="ro">Animație ANIM</comment>
- <comment xml:lang="ru">Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ñ ANIM</comment>
+ <comment xml:lang="ru">ÐÐ½Ð¸Ð¼Ð°Ñ†Ð¸Ñ ANIM</comment>
<comment xml:lang="sk">Animácia ANIM</comment>
<comment xml:lang="sl">Datoteka animacije ANIM</comment>
<comment xml:lang="sq">Animim ANIM</comment>
@@ -36833,7 +38081,7 @@
<comment xml:lang="pt">animação FLIC</comment>
<comment xml:lang="pt_BR">Animação FLIC</comment>
<comment xml:lang="ro">Animație FLIC</comment>
- <comment xml:lang="ru">Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ñ FLIC</comment>
+ <comment xml:lang="ru">ÐÐ½Ð¸Ð¼Ð°Ñ†Ð¸Ñ FLIC</comment>
<comment xml:lang="sk">Animácia FLIC</comment>
<comment xml:lang="sl">Datoteka animacije FLIC</comment>
<comment xml:lang="sq">Animim FLIC</comment>
@@ -36856,6 +38104,7 @@
<mime-type type="application/x-hwp">
<comment>Haansoft Hangul document</comment>
<comment xml:lang="ar">مستند Haansoft Hangul</comment>
+ <comment xml:lang="ast">Documentu de Haansoft Hangul</comment>
<comment xml:lang="be@latin">Dakument Haansoft Hangul</comment>
<comment xml:lang="bg">Документ — Haansoft Hangul</comment>
<comment xml:lang="ca">document d'Haansoft Hangul</comment>
@@ -36890,7 +38139,7 @@
<comment xml:lang="pt">documento Haansoft Hangul</comment>
<comment xml:lang="pt_BR">Documento do Haansoft Hangul</comment>
<comment xml:lang="ro">Document Haansoft Hangul</comment>
- <comment xml:lang="ru">документ Haansoft Hangul</comment>
+ <comment xml:lang="ru">Документ Haansoft Hangul</comment>
<comment xml:lang="sk">Dokument Haansoft Hangul</comment>
<comment xml:lang="sl">Dokument Haansoft Hangul</comment>
<comment xml:lang="sq">Dokument Haansoft Hangul</comment>
@@ -36911,6 +38160,7 @@
<mime-type type="application/x-hwt">
<comment>Haansoft Hangul document template</comment>
<comment xml:lang="ar">قالب مستند Haansoft Hangul</comment>
+ <comment xml:lang="ast">Plantía de documentu de Haansoft Hangul</comment>
<comment xml:lang="be@latin">Å ablon dakumentu Haansoft Hangul</comment>
<comment xml:lang="bg">Шаблон за документи — Haansoft Hangul</comment>
<comment xml:lang="ca">plantilla de document d'Haansoft Hangul</comment>
@@ -36945,7 +38195,7 @@
<comment xml:lang="pt">modelo de documento Haansoft Hangul</comment>
<comment xml:lang="pt_BR">Modelo de documento do Haansoft Hangul</comment>
<comment xml:lang="ro">Document șablon Haansoft Hangul</comment>
- <comment xml:lang="ru">шаблон документа Haansoft Hangul</comment>
+ <comment xml:lang="ru">Шаблон документа Haansoft Hangul</comment>
<comment xml:lang="sk">Šablóna dokumentu Haansoft Hangul</comment>
<comment xml:lang="sl">Predloga dokumenta Haansoft Hangul</comment>
<comment xml:lang="sq">Model dokumenti Haansoft Hangul</comment>
@@ -36999,7 +38249,7 @@
<comment xml:lang="pt">animação MNG</comment>
<comment xml:lang="pt_BR">Animação MNG</comment>
<comment xml:lang="ro">Animație MNG</comment>
- <comment xml:lang="ru">Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ñ MNG</comment>
+ <comment xml:lang="ru">ÐÐ½Ð¸Ð¼Ð°Ñ†Ð¸Ñ MNG</comment>
<comment xml:lang="sk">Animácia MNG</comment>
<comment xml:lang="sl">Datoteka animacije MNG</comment>
<comment xml:lang="sq">Animim MNG</comment>
@@ -37020,6 +38270,7 @@
<mime-type type="application/vnd.ms-asf">
<comment>ASF video</comment>
<comment xml:lang="ar">ASF مرئي</comment>
+ <comment xml:lang="ast">Videu n'ASF</comment>
<comment xml:lang="be@latin">Videa ASF</comment>
<comment xml:lang="bg">Видео — ASF</comment>
<comment xml:lang="ca">vídeo ASF</comment>
@@ -37037,7 +38288,7 @@
<comment xml:lang="ga">físeán ASF</comment>
<comment xml:lang="gl">vídeo ASF</comment>
<comment xml:lang="he">ויד×ו ASF</comment>
- <comment xml:lang="hr">ASF video</comment>
+ <comment xml:lang="hr">ASF video snimka</comment>
<comment xml:lang="hu">ASF videó</comment>
<comment xml:lang="ia">Video ASF</comment>
<comment xml:lang="id">Video ASF</comment>
@@ -37056,7 +38307,7 @@
<comment xml:lang="pt">vídeo ASF</comment>
<comment xml:lang="pt_BR">Vídeo ASF</comment>
<comment xml:lang="ro">Video ASF</comment>
- <comment xml:lang="ru">видео ASF</comment>
+ <comment xml:lang="ru">Видео ASF</comment>
<comment xml:lang="sk">Video ASF</comment>
<comment xml:lang="sl">Video datoteka ASF</comment>
<comment xml:lang="sq">Video ASF</comment>
@@ -37115,7 +38366,7 @@
<comment xml:lang="pt">ficheiro Windows Media Station</comment>
<comment xml:lang="pt_BR">Arquivo de estação do Windows Media</comment>
<comment xml:lang="ro">Fișier Windows Media Station</comment>
- <comment xml:lang="ru">файл Windows Media Station</comment>
+ <comment xml:lang="ru">Файл Windows Media Station</comment>
<comment xml:lang="sk">Súbor Windows Media Station</comment>
<comment xml:lang="sl">Datoteka Windows Media Station</comment>
<comment xml:lang="sq">File Windows Media Station</comment>
@@ -37136,6 +38387,7 @@
<mime-type type="video/x-ms-wmv">
<comment>Windows Media video</comment>
<comment xml:lang="ar">Windows Media مرئي</comment>
+ <comment xml:lang="ast">Videu de Windows Media</comment>
<comment xml:lang="be@latin">Videa Windows Media</comment>
<comment xml:lang="bg">Видео — Windows Media</comment>
<comment xml:lang="ca">vídeo de Windows Media</comment>
@@ -37152,7 +38404,7 @@
<comment xml:lang="ga">físeán Windows Media</comment>
<comment xml:lang="gl">vídeo de Windows Media</comment>
<comment xml:lang="he">ויד×ו של Windows Media</comment>
- <comment xml:lang="hr">Windows Media video</comment>
+ <comment xml:lang="hr">Windows Media video snimka</comment>
<comment xml:lang="hu">Windows Media videó</comment>
<comment xml:lang="ia">Video Windows Media</comment>
<comment xml:lang="id">Video Windows Media</comment>
@@ -37170,7 +38422,7 @@
<comment xml:lang="pt">vídeo Windows Media</comment>
<comment xml:lang="pt_BR">Vídeo do Windows Media</comment>
<comment xml:lang="ro">Video Windows Media</comment>
- <comment xml:lang="ru">видео Windows Media</comment>
+ <comment xml:lang="ru">Видео Windows Media</comment>
<comment xml:lang="sk">Video Windows Media</comment>
<comment xml:lang="sl">Video datoteka Windows Media</comment>
<comment xml:lang="sq">Video Windows Media</comment>
@@ -37187,6 +38439,7 @@
<mime-type type="video/x-msvideo">
<comment>AVI video</comment>
<comment xml:lang="ar">AVI مرئي</comment>
+ <comment xml:lang="ast">Videu n'AVI</comment>
<comment xml:lang="az">AVI video faylı</comment>
<comment xml:lang="be@latin">Videa AVI</comment>
<comment xml:lang="bg">Видео — AVI</comment>
@@ -37206,7 +38459,7 @@
<comment xml:lang="ga">físeán AVI</comment>
<comment xml:lang="gl">vídeo AVI</comment>
<comment xml:lang="he">ויד×ו AVI</comment>
- <comment xml:lang="hr">AVI video</comment>
+ <comment xml:lang="hr">AVI video snimka</comment>
<comment xml:lang="hu">AVI-videó</comment>
<comment xml:lang="ia">Video AVI</comment>
<comment xml:lang="id">Video AVI</comment>
@@ -37226,7 +38479,7 @@
<comment xml:lang="pt">vídeo AVI</comment>
<comment xml:lang="pt_BR">Vídeo AVI</comment>
<comment xml:lang="ro">Video AVI</comment>
- <comment xml:lang="ru">видео AVI</comment>
+ <comment xml:lang="ru">Видео AVI</comment>
<comment xml:lang="sk">Video AVI</comment>
<comment xml:lang="sl">Video datoteka AVI</comment>
<comment xml:lang="sq">Video AVI</comment>
@@ -37259,6 +38512,7 @@
<mime-type type="video/x-nsv">
<comment>NullSoft video</comment>
<comment xml:lang="ar">NullSoft مرئي</comment>
+ <comment xml:lang="ast">Videu de NullSoft</comment>
<comment xml:lang="be@latin">Videa NullSoft</comment>
<comment xml:lang="bg">Видео — NullSoft</comment>
<comment xml:lang="ca">vídeo NullSoft</comment>
@@ -37276,7 +38530,7 @@
<comment xml:lang="ga">físeán NullSoft</comment>
<comment xml:lang="gl">vídeo de NullSoft</comment>
<comment xml:lang="he">ויד×ו של NullSot</comment>
- <comment xml:lang="hr">NullSoft video</comment>
+ <comment xml:lang="hr">NullSoft video snimka</comment>
<comment xml:lang="hu">NullSoft videó</comment>
<comment xml:lang="ia">Video NullSoft</comment>
<comment xml:lang="id">Video NullSoft</comment>
@@ -37294,7 +38548,7 @@
<comment xml:lang="pt">vídeo NullSoft</comment>
<comment xml:lang="pt_BR">Vídeo do NullSoft</comment>
<comment xml:lang="ro">Video NullSoft</comment>
- <comment xml:lang="ru">видео Nullsoft</comment>
+ <comment xml:lang="ru">Видео Nullsoft</comment>
<comment xml:lang="sk">Video NullSoft</comment>
<comment xml:lang="sl">Video datoteka NullSoft</comment>
<comment xml:lang="sq">Video NullSoft</comment>
@@ -37303,7 +38557,7 @@
<comment xml:lang="tr">Nullsoft videosu</comment>
<comment xml:lang="uk">відеокліп NullSoft</comment>
<comment xml:lang="vi">Ảnh động NullSoft</comment>
- <comment xml:lang="zh_CN">Nullsoft 视频</comment>
+ <comment xml:lang="zh_CN">NullSoft 视频</comment>
<comment xml:lang="zh_TW">NullSoft 視訊</comment>
<magic priority="50">
<match value="NSVf" type="string" offset="0"/>
@@ -37347,7 +38601,7 @@
<comment xml:lang="pt">ficheiro de fluxo SDP multicast</comment>
<comment xml:lang="pt_BR">Arquivo de canal multicast SDP</comment>
<comment xml:lang="ro">Fișier flux multicast SDP</comment>
- <comment xml:lang="ru">файл мультикаÑÑ‚-потока SDP</comment>
+ <comment xml:lang="ru">Файл мультикаÑÑ‚-потока SDP</comment>
<comment xml:lang="sk">Súbor viacsmerového vysielania prúdu SDP</comment>
<comment xml:lang="sl">PretoÄni vir veÄsmernega oddajanja</comment>
<comment xml:lang="sq">File stream multicast SDP</comment>
@@ -37374,6 +38628,7 @@
<mime-type type="video/x-sgi-movie">
<comment>SGI video</comment>
<comment xml:lang="ar">SGI مرئي</comment>
+ <comment xml:lang="ast">Videu en SGI</comment>
<comment xml:lang="az">SGI video faylı</comment>
<comment xml:lang="be@latin">Videa SGI</comment>
<comment xml:lang="bg">Видео — SGI</comment>
@@ -37393,7 +38648,7 @@
<comment xml:lang="ga">físeán SGI</comment>
<comment xml:lang="gl">vídeo SGI</comment>
<comment xml:lang="he">ויד×ו SGI</comment>
- <comment xml:lang="hr">SGI video</comment>
+ <comment xml:lang="hr">SGI video snimka</comment>
<comment xml:lang="hu">SGI-videó</comment>
<comment xml:lang="ia">Video SGI</comment>
<comment xml:lang="id">Video SGI</comment>
@@ -37412,7 +38667,7 @@
<comment xml:lang="pt">vídeo SGI</comment>
<comment xml:lang="pt_BR">Vídeo SGI</comment>
<comment xml:lang="ro">Video SGI</comment>
- <comment xml:lang="ru">видео SGI</comment>
+ <comment xml:lang="ru">Видео SGI</comment>
<comment xml:lang="sk">Video SGI</comment>
<comment xml:lang="sl">Video datoteka SGI</comment>
<comment xml:lang="sq">Video SGI</comment>
@@ -37465,7 +38720,7 @@
<comment xml:lang="pt">pacote transferido eMusic</comment>
<comment xml:lang="pt_BR">Pacote de download do eMusic</comment>
<comment xml:lang="ro">pachet descărcare eMusic</comment>
- <comment xml:lang="ru">пакет загрузок eMusic</comment>
+ <comment xml:lang="ru">Пакет загрузок eMusic</comment>
<comment xml:lang="sk">BalíÄek sÅ¥ahovania eMusic</comment>
<comment xml:lang="sl">Datoteka paketa eMusic</comment>
<comment xml:lang="sq">Paketë shkarkimi eMusic</comment>
@@ -37516,7 +38771,7 @@
<comment xml:lang="pt">dados geográficos KML</comment>
<comment xml:lang="pt_BR">Dados geográficos KML</comment>
<comment xml:lang="ro">Date geografice KML</comment>
- <comment xml:lang="ru">географичеÑкие данные KML</comment>
+ <comment xml:lang="ru">ГеографичеÑкие данные KML</comment>
<comment xml:lang="sk">Zemepisné údaje KML</comment>
<comment xml:lang="sl">Datoteka geografskih podatkov KML</comment>
<comment xml:lang="sr">КМЛ географÑки подаци</comment>
@@ -37549,7 +38804,7 @@
<comment xml:lang="ga">sonraí comhbhrúite geografacha KML</comment>
<comment xml:lang="gl">datos xeográficos KML comprimidos </comment>
<comment xml:lang="he">מידע ×’×וגרפי דחוס KML</comment>
- <comment xml:lang="hr">KML geografski komprimirani podaci</comment>
+ <comment xml:lang="hr">KML sažeti geografski podaci</comment>
<comment xml:lang="hu">KML tömörített földrajzi adatok</comment>
<comment xml:lang="ia">Datos geographic KML comprimite</comment>
<comment xml:lang="id">Data geografis KML terkompresi</comment>
@@ -37565,14 +38820,14 @@
<comment xml:lang="pt">dados geográficos comprimidos KML</comment>
<comment xml:lang="pt_BR">Dados geográficos KML compactados</comment>
<comment xml:lang="ro">Date geografice comprimate KML</comment>
- <comment xml:lang="ru">Ñжатые географичеÑкие данные KML</comment>
+ <comment xml:lang="ru">Сжатые географичеÑкие данные KML</comment>
<comment xml:lang="sk">Komprimované zemepisné údaje KML</comment>
<comment xml:lang="sl">SkrÄeni geografski podatki KML</comment>
<comment xml:lang="sr">КМЛ географÑки запаковани подаци</comment>
<comment xml:lang="sv">KML geografiskt komprimerat data</comment>
<comment xml:lang="tr">KML sıkıştırılmış coğrafi verisi</comment>
<comment xml:lang="uk">ÑтиÑнуті географічні дані KML</comment>
- <comment xml:lang="zh_CN">KML 压缩地ç†æ•°æ®</comment>
+ <comment xml:lang="zh_CN">KML 地ç†åŽ‹ç¼©æ•°æ®</comment>
<comment xml:lang="zh_TW">KML 地ç†å£“縮資料</comment>
<acronym>KML</acronym>
<expanded-acronym>Keyhole Markup Language</expanded-acronym>
@@ -37588,6 +38843,7 @@
<comment xml:lang="en_GB">GeoJSON geospatial data</comment>
<comment xml:lang="es">datos geoespaciales en GeoJSON</comment>
<comment xml:lang="fr">données géospatiales GeoJSON</comment>
+ <comment xml:lang="ga">sonraí geospásúla GeoJSON</comment>
<comment xml:lang="hr">GeoJSON geoprostorni podaci</comment>
<comment xml:lang="hu">GeoJSON téradatok</comment>
<comment xml:lang="id">Data geospasial GeoJSON</comment>
@@ -37596,10 +38852,10 @@
<comment xml:lang="ko">GeoJSON 지리 ì •ë³´ ë°ì´í„°</comment>
<comment xml:lang="pl">Dane geoprzestrzenne GeoJSON</comment>
<comment xml:lang="pt_BR">Dados geoespaciais GeoJSON</comment>
- <comment xml:lang="ru">геопроÑтранÑтвенные данные GeoJSON</comment>
+ <comment xml:lang="ru">ГеопроÑтранÑтвенные данные GeoJSON</comment>
<comment xml:lang="sk">Geopriestorové údaje GeoJSON</comment>
<comment xml:lang="sr">ГеоЈСОРгеопроÑторни подаци</comment>
- <comment xml:lang="sv">GeoJSON geospatial data</comment>
+ <comment xml:lang="sv">Geospatialt GeoJSON-data</comment>
<comment xml:lang="tr">GeoJSON coÄŸrafi veriler</comment>
<comment xml:lang="uk">геопроÑторові дані GeoJSON</comment>
<comment xml:lang="zh_CN">GeoJSON 地ç†ç©ºé—´æ•°æ®</comment>
@@ -37620,6 +38876,7 @@
<comment xml:lang="eu">GPX datu geografikoak</comment>
<comment xml:lang="fi">GPX-paikkatieto</comment>
<comment xml:lang="fr">données géographiques GPX</comment>
+ <comment xml:lang="ga">sonraí geografacha GPX</comment>
<comment xml:lang="he">× ×ª×•× ×™× ×’××•×’×¨×¤×™×™× GPX</comment>
<comment xml:lang="hr">GPX geografski podaci</comment>
<comment xml:lang="hu">GPX földrajzi adatok</comment>
@@ -37630,13 +38887,13 @@
<comment xml:lang="oc">Donadas geograficas GPX</comment>
<comment xml:lang="pl">Dane geograficzne GPX</comment>
<comment xml:lang="pt_BR">Dados geográficos GPX</comment>
- <comment xml:lang="ru">географичеÑкие данные GPX</comment>
+ <comment xml:lang="ru">ГеографичеÑкие данные GPX</comment>
<comment xml:lang="sk">Zemepisné údaje GPX</comment>
<comment xml:lang="sr">Ð“ÐŸÐ˜ÐºÑ Ð³ÐµÐ¾Ð³Ñ€Ð°Ñ„Ñки подаци</comment>
<comment xml:lang="sv">GPX geografisk data</comment>
<comment xml:lang="tr">GPX coÄŸrafi verileri</comment>
<comment xml:lang="uk">географічні дані GPX</comment>
- <comment xml:lang="zh_CN">GPX 地ç†ç©ºé—´æ•°æ®</comment>
+ <comment xml:lang="zh_CN">GPX 地ç†æ•°æ®</comment>
<comment xml:lang="zh_TW">GPX 地ç†è³‡æ–™</comment>
<acronym>GPX</acronym>
<expanded-acronym>GPS Exchange Format</expanded-acronym>
@@ -37686,7 +38943,7 @@
<comment xml:lang="pt">ficheiro de definições Citrix ICA</comment>
<comment xml:lang="pt_BR">Arquivo de configuração do Citrix ICA</comment>
<comment xml:lang="ro">Fișier de configurări Citrix ICA</comment>
- <comment xml:lang="ru">файл наÑтроек Citrix ICA</comment>
+ <comment xml:lang="ru">Файл наÑтроек Citrix ICA</comment>
<comment xml:lang="sk">Súbor nastavení Citrix ICA</comment>
<comment xml:lang="sl">Nastavitvena datoteka Citrix ICA</comment>
<comment xml:lang="sq">File rregullimesh Citrix ICA</comment>
@@ -37706,6 +38963,7 @@
<mime-type type="application/vnd.mozilla.xul+xml">
<comment>XUL interface document</comment>
<comment xml:lang="ar">مستند واجهة XUL</comment>
+ <comment xml:lang="ast">Documentu d'interfaz XUL</comment>
<comment xml:lang="be@latin">Interfejsny dakument XUL</comment>
<comment xml:lang="bg">Документ — Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð·Ð° XUL</comment>
<comment xml:lang="ca">document d'interfície XUL</comment>
@@ -37740,7 +38998,7 @@
<comment xml:lang="pt">documento de ambiente XUL</comment>
<comment xml:lang="pt_BR">Documento de interface XUL</comment>
<comment xml:lang="ro">Document interfață XUL</comment>
- <comment xml:lang="ru">документ интерфейÑа XUL</comment>
+ <comment xml:lang="ru">Документ интерфейÑа XUL</comment>
<comment xml:lang="sk">Dokument rozhrania XUL</comment>
<comment xml:lang="sl">Dokument vmesnika XUL</comment>
<comment xml:lang="sq">Dokument interfaqe XUL</comment>
@@ -37792,7 +39050,7 @@
<comment xml:lang="pt">módulo de instalador XPInstall</comment>
<comment xml:lang="pt_BR">Módulo de instalador XPInstall</comment>
<comment xml:lang="ro">Modul de instalare XPInstall</comment>
- <comment xml:lang="ru">модуль уÑтановщика XPInstall</comment>
+ <comment xml:lang="ru">Модуль уÑтановщика XPInstall</comment>
<comment xml:lang="sk">Modul inštalátora XPInstall</comment>
<comment xml:lang="sl">modul namestilnika XPInstall</comment>
<comment xml:lang="sr">модул инÑталатера ИнÑталирања ИкÑПе-а</comment>
@@ -37807,6 +39065,7 @@
<mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.document">
<comment>Word 2007 document</comment>
<comment xml:lang="ar">مستند Word 2007</comment>
+ <comment xml:lang="ast">Documentu de Word 2007</comment>
<comment xml:lang="bg">Документ — Word 2007</comment>
<comment xml:lang="ca">document de Word 2007</comment>
<comment xml:lang="cs">dokument Word 2007</comment>
@@ -37838,7 +39097,7 @@
<comment xml:lang="pt">documento Word 2007</comment>
<comment xml:lang="pt_BR">Documento do Word 2007</comment>
<comment xml:lang="ro">Document Word 2007</comment>
- <comment xml:lang="ru">документ Word 2007</comment>
+ <comment xml:lang="ru">Документ Word 2007</comment>
<comment xml:lang="sk">Dokument Word 2007</comment>
<comment xml:lang="sl">Dokument Word 2007</comment>
<comment xml:lang="sr">документ Ворда 2007</comment>
@@ -37846,7 +39105,7 @@
<comment xml:lang="tr">Word 2007 belgesi</comment>
<comment xml:lang="uk">документ Word 2007</comment>
<comment xml:lang="vi">Tài liệu Word 2007</comment>
- <comment xml:lang="zh_CN">Microsoft Word 2007 文档</comment>
+ <comment xml:lang="zh_CN">Word 2007 文档</comment>
<comment xml:lang="zh_TW">Word 2007 文件</comment>
<glob pattern="*.docx"/>
<sub-class-of type="application/zip"/>
@@ -37854,6 +39113,7 @@
</mime-type>
<mime-type type="application/vnd.openxmlformats-officedocument.wordprocessingml.template">
<comment>Word 2007 document template</comment>
+ <comment xml:lang="ast">Plantía de documentu de Word 2007</comment>
<comment xml:lang="bg">Шаблон за документи — Word 2007</comment>
<comment xml:lang="ca">plantilla de document de Word 2007</comment>
<comment xml:lang="cs">Å¡ablona dokumentu Word 2007</comment>
@@ -37865,6 +39125,7 @@
<comment xml:lang="eu">Word 2007 dokumentuaren txantiloia</comment>
<comment xml:lang="fi">Word 2007 -asiakirjamalli</comment>
<comment xml:lang="fr">modèle de document Word 2007</comment>
+ <comment xml:lang="ga">teimpléad cháipéis Word 2007</comment>
<comment xml:lang="gl">Plantilla de documento de Word 2007</comment>
<comment xml:lang="he">תבנית מסמך של Word 2007</comment>
<comment xml:lang="hr">Word 2007 predložak dokumenta</comment>
@@ -37882,7 +39143,7 @@
<comment xml:lang="pl">Szablon dokumentu Word 2007</comment>
<comment xml:lang="pt">modelo de documento Word 2007</comment>
<comment xml:lang="pt_BR">Modelo de documento do Word 2007</comment>
- <comment xml:lang="ru">шаблон документа Word 2007</comment>
+ <comment xml:lang="ru">Шаблон документа Word 2007</comment>
<comment xml:lang="sk">Šablóna dokumentu Word 2007</comment>
<comment xml:lang="sl">Predloga dokumenta Word 2007</comment>
<comment xml:lang="sr">шаблон документа Ворда 2007</comment>
@@ -37929,7 +39190,7 @@
<comment xml:lang="pt">apresentação PowerPoint 2007</comment>
<comment xml:lang="pt_BR">Apresentação do PowerPoint 2007</comment>
<comment xml:lang="ro">Prezentare PowerPoint 2007</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ PowerPoint 2007</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ PowerPoint 2007</comment>
<comment xml:lang="sk">Prezentácia PowerPoint 2007</comment>
<comment xml:lang="sl">Predstavitev Microsoft PowerPoint 2007</comment>
<comment xml:lang="sr">презентација Пауер Поинта 2007</comment>
@@ -37937,7 +39198,7 @@
<comment xml:lang="tr">PowerPoint 2007 sunumu</comment>
<comment xml:lang="uk">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ PowerPoint 2007</comment>
<comment xml:lang="vi">Trình diễn PowerPoint 2007</comment>
- <comment xml:lang="zh_CN">Microsoft PowerPoint 2007 演示文稿</comment>
+ <comment xml:lang="zh_CN">PowerPoint 2007 演示文稿</comment>
<comment xml:lang="zh_TW">PowerPoint 2007 ç°¡å ±</comment>
<glob pattern="*.pptx"/>
<sub-class-of type="application/zip"/>
@@ -37956,9 +39217,10 @@
<comment xml:lang="eu">PowerPoint 2007 diapositiba</comment>
<comment xml:lang="fi">PowerPoint 2007 -dia</comment>
<comment xml:lang="fr">diapositive PowerPoint 2007</comment>
+ <comment xml:lang="ga">sleamhnán PowerPoint 2007</comment>
<comment xml:lang="gl">Diaporama de PowerPoint 2007</comment>
<comment xml:lang="he">שקופית של PowerPoint 2007</comment>
- <comment xml:lang="hr">PowerPoint 2007 slajd</comment>
+ <comment xml:lang="hr">PowerPoint 2007 slikovna prezentacija</comment>
<comment xml:lang="hu">PowerPoint 2007 dia</comment>
<comment xml:lang="ia">Diapositiva PowerPoint 2007</comment>
<comment xml:lang="id">Slide PowerPoint 2007</comment>
@@ -37973,14 +39235,14 @@
<comment xml:lang="pl">Slajd PowerPoint 2007</comment>
<comment xml:lang="pt">diapositivo PowerPoint 2007</comment>
<comment xml:lang="pt_BR">Slide do PowerPoint 2007</comment>
- <comment xml:lang="ru">Ñлайд PowerPoint 2007</comment>
+ <comment xml:lang="ru">Слайд PowerPoint 2007</comment>
<comment xml:lang="sk">Snímka PowerPoint 2007</comment>
<comment xml:lang="sl">Prosojnica PowerPoint 2007</comment>
<comment xml:lang="sr">Ñлајд Пауер Поинта 2007</comment>
<comment xml:lang="sv">PowerPoint 2007-bildspel</comment>
<comment xml:lang="tr">PowerPoint 2007 slaytı</comment>
<comment xml:lang="uk">Ñлайд PowerPoint 2007</comment>
- <comment xml:lang="zh_CN">PowerPoint 2007 文稿</comment>
+ <comment xml:lang="zh_CN">PowerPoint 2007 å¹»ç¯ç‰‡</comment>
<comment xml:lang="zh_TW">PowerPoint 2007 投影片</comment>
<glob pattern="*.sldx"/>
<sub-class-of type="application/zip"/>
@@ -38020,14 +39282,14 @@
<comment xml:lang="pt">espetáculo PowerPoint 2007</comment>
<comment xml:lang="pt_BR">Apresentação do PowerPoint 2007</comment>
<comment xml:lang="ro">Prezentare PowerPoint 2007</comment>
- <comment xml:lang="ru">Ð¿Ñ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ PowerPoint 2007</comment>
+ <comment xml:lang="ru">ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ PowerPoint 2007</comment>
<comment xml:lang="sk">Ukážka PowerPoint 2007</comment>
<comment xml:lang="sl">Zagonska predstavitev PowerPoint 2007</comment>
<comment xml:lang="sr">приказ Пауер Поинта 2007</comment>
<comment xml:lang="sv">PowerPoint 2007-visning</comment>
<comment xml:lang="tr">PowerPoint 2007 gösterisi</comment>
<comment xml:lang="uk">показ Ñлайдів PowerPoint 2007</comment>
- <comment xml:lang="zh_CN">Microsoft PowerPoint 2007 演示文稿</comment>
+ <comment xml:lang="zh_CN">PowerPoint 2007 放映</comment>
<comment xml:lang="zh_TW">PowerPoint 2007 展示</comment>
<glob pattern="*.ppsx"/>
<sub-class-of type="application/zip"/>
@@ -38046,6 +39308,7 @@
<comment xml:lang="eu">PowerPoint 2007 aurkezpen txantiloia</comment>
<comment xml:lang="fi">PowerPoint 2007 -esitysmalli</comment>
<comment xml:lang="fr">modèle de présentation PowerPoint 2007</comment>
+ <comment xml:lang="ga">teimpléad láithreoireachta PowerPoint 2007</comment>
<comment xml:lang="gl">modelo de presentación de PowerPoint 2007</comment>
<comment xml:lang="he">תבנית למצגת של PowerPoint 2007</comment>
<comment xml:lang="hr">PowerPoint 2007 predložak prezentacije</comment>
@@ -38063,7 +39326,7 @@
<comment xml:lang="pl">Szablon prezentacji PowerPoint 2007</comment>
<comment xml:lang="pt">modelo de apresentação PowerPoint 2007</comment>
<comment xml:lang="pt_BR">Modelo de apresentação do PowerPoint 2007</comment>
- <comment xml:lang="ru">шаблон презентации PowerPoint 2007</comment>
+ <comment xml:lang="ru">Шаблон презентации PowerPoint 2007</comment>
<comment xml:lang="sk">Šablóna prezentácie PowerPoint 2007</comment>
<comment xml:lang="sl">Predloga predstavitve PowerPoint 2007</comment>
<comment xml:lang="sr">шаблон презентације Пауер Поинта 2007</comment>
@@ -38111,7 +39374,7 @@
<comment xml:lang="pt">folha de cálculo Excel 2007</comment>
<comment xml:lang="pt_BR">Planilha do Excel 2007</comment>
<comment xml:lang="ro">Foaie de calcul Excel 2007</comment>
- <comment xml:lang="ru">ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Excel 2007</comment>
+ <comment xml:lang="ru">Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° Excel 2007</comment>
<comment xml:lang="sk">Zošit Excel 2007</comment>
<comment xml:lang="sl">Razpredelnica Microsoft Excel 2007</comment>
<comment xml:lang="sr">табела ЕкÑела 2007</comment>
@@ -38119,7 +39382,7 @@
<comment xml:lang="tr">Excel 2007 çalışma sayfası</comment>
<comment xml:lang="uk">ел. Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Excel 2007</comment>
<comment xml:lang="vi">Bảng tính Excel 2007</comment>
- <comment xml:lang="zh_CN">Microsoft Excel 2007 工作簿</comment>
+ <comment xml:lang="zh_CN">Excel 2007 电å­è¡¨æ ¼</comment>
<comment xml:lang="zh_TW">Excel 2007 試算表</comment>
<glob pattern="*.xlsx"/>
<sub-class-of type="application/zip"/>
@@ -38138,6 +39401,7 @@
<comment xml:lang="eu">Excel 2007 kalkulu-orri txantiloia</comment>
<comment xml:lang="fi">Excel 2007 -taulukkomalli</comment>
<comment xml:lang="fr">modèle de feuille de calcul Excel 2007</comment>
+ <comment xml:lang="ga">teimpléad scarbhileoige Excel 2007</comment>
<comment xml:lang="gl">modelo de folla de cálculo Excel 2007</comment>
<comment xml:lang="he">תבנית של גיליון × ×ª×•× ×™× ×©×œ Excel 2007</comment>
<comment xml:lang="hr">Excel 2007 predložak proraÄunske tablice</comment>
@@ -38155,14 +39419,14 @@
<comment xml:lang="pl">Szablon arkusza Excel 2007</comment>
<comment xml:lang="pt">modelo de folha de cálculo Excel 2007</comment>
<comment xml:lang="pt_BR">Modelo de planilha do Excel 2007</comment>
- <comment xml:lang="ru">шаблон Ñлектронной таблицы Excel 2007</comment>
+ <comment xml:lang="ru">Шаблон Ñлектронной таблицы Excel 2007</comment>
<comment xml:lang="sk">Šablóna zošitu Excel 2007</comment>
<comment xml:lang="sl">Predloga razpredelnice Excel 2007</comment>
<comment xml:lang="sr">шаблон табеле ЕкÑела 2007</comment>
<comment xml:lang="sv">Excel 2007-kalkylarksmall</comment>
<comment xml:lang="tr">Excel 2007 çalışma sayfası şablonu</comment>
<comment xml:lang="uk">шаблон електронної таблиці Excel 2007</comment>
- <comment xml:lang="zh_CN">Excel 2007 工作表模æ¿</comment>
+ <comment xml:lang="zh_CN">Excel 2007 电å­è¡¨æ ¼æ¨¡æ¿</comment>
<comment xml:lang="zh_TW">Excel 2007 試算表範本</comment>
<glob pattern="*.xltx"/>
<sub-class-of type="application/zip"/>
@@ -38171,6 +39435,7 @@
<mime-type type="application/x-t602">
<comment>T602 document</comment>
<comment xml:lang="ar">مستند T602</comment>
+ <comment xml:lang="ast">Documentu T602</comment>
<comment xml:lang="be@latin">Dakument T602</comment>
<comment xml:lang="bg">Документ — T602</comment>
<comment xml:lang="ca">document T602</comment>
@@ -38206,7 +39471,7 @@
<comment xml:lang="pt">documento T602</comment>
<comment xml:lang="pt_BR">Documento T602</comment>
<comment xml:lang="ro">Document T602</comment>
- <comment xml:lang="ru">документ T602</comment>
+ <comment xml:lang="ru">Документ T602</comment>
<comment xml:lang="sk">Dokument T602</comment>
<comment xml:lang="sl">Dokument T602</comment>
<comment xml:lang="sq">Dokument T602</comment>
@@ -38263,7 +39528,7 @@
<comment xml:lang="pt">definições de Cisco VPN</comment>
<comment xml:lang="pt_BR">Configurações de VPN da Cisco</comment>
<comment xml:lang="ro">Configurări VPN Cisco</comment>
- <comment xml:lang="ru">файл наÑтроек Cisco VPN</comment>
+ <comment xml:lang="ru">Файл наÑтроек Cisco VPN</comment>
<comment xml:lang="sk">Nastavenia Cisco VPN</comment>
<comment xml:lang="sl">Datoteka nastavitev Cisco VPN</comment>
<comment xml:lang="sq">Rregullime VPN Cisco</comment>
@@ -38285,6 +39550,7 @@
<mime-type type="application/vnd.iccprofile">
<comment>ICC profile</comment>
<comment xml:lang="ar">تشكيلة OCL</comment>
+ <comment xml:lang="ast">Perfil ICC</comment>
<comment xml:lang="bg">Цветови профил — OCL</comment>
<comment xml:lang="ca">perfil ICC</comment>
<comment xml:lang="cs">profil ICC</comment>
@@ -38317,14 +39583,14 @@
<comment xml:lang="pt">perfil ICC</comment>
<comment xml:lang="pt_BR">Perfil ICC</comment>
<comment xml:lang="ro">Profil ICC</comment>
- <comment xml:lang="ru">профиль ICC</comment>
+ <comment xml:lang="ru">Профиль ICC</comment>
<comment xml:lang="sk">Profil farieb ICC</comment>
<comment xml:lang="sl">Datoteka profila ICC</comment>
<comment xml:lang="sr">ИЦЦ профил</comment>
<comment xml:lang="sv">ICC-profil</comment>
<comment xml:lang="tr">ICC profili</comment>
<comment xml:lang="uk">профіль ICC</comment>
- <comment xml:lang="zh_CN">ICC 文件</comment>
+ <comment xml:lang="zh_CN">ICC é…置文件</comment>
<comment xml:lang="zh_TW">ICC 設定檔</comment>
<magic priority="50">
<match value="acsp" type="string" offset="36"/>
@@ -38366,7 +39632,7 @@
<comment xml:lang="pt">ficheiro de calibração de cor IT 8.7</comment>
<comment xml:lang="pt_BR">Arquivo de calibração de cor IT 8.7</comment>
<comment xml:lang="ro">Fișier de calibrare a culorii IT 8.7</comment>
- <comment xml:lang="ru">файл калибровки цвета IT 8.7</comment>
+ <comment xml:lang="ru">Файл калибровки цвета IT 8.7</comment>
<comment xml:lang="sk">Súbor kalibrácie farieb IT 8.7</comment>
<comment xml:lang="sl">Umeritvena datoteka barve IT 8.7</comment>
<comment xml:lang="sr">ИТ 8.7 датотека калибрације боје</comment>
@@ -38394,6 +39660,7 @@
<comment xml:lang="eu">CCMX kolore-kalibrazioaren fitxategia</comment>
<comment xml:lang="fi">CCMX-värikorjaustiedosto</comment>
<comment xml:lang="fr">fichier de correction colorimétrique CCMX</comment>
+ <comment xml:lang="ga">comhad ceartúchán dathanna CCMX</comment>
<comment xml:lang="gl">Ficheiro de corrección de cor CCMX</comment>
<comment xml:lang="he">קובץ תיקון צבע מסוג CCMX</comment>
<comment xml:lang="hr">CCMX datotkea ispravka boja</comment>
@@ -38409,7 +39676,7 @@
<comment xml:lang="pl">Plik korekcji kolorów CCMX</comment>
<comment xml:lang="pt">ficheiro de correção de cor CCMX</comment>
<comment xml:lang="pt_BR">Arquivo de correção de cor CCMX</comment>
- <comment xml:lang="ru">файл цветовой коррекции CCMX</comment>
+ <comment xml:lang="ru">Файл цветовой коррекции CCMX</comment>
<comment xml:lang="sk">Súbor korekcie farieb CCMX</comment>
<comment xml:lang="sl">Datoteka barvne poprave CCMX</comment>
<comment xml:lang="sr">Ð¦Ð¦ÐœÐ˜ÐºÑ Ð´Ð°Ñ‚Ð¾Ñ‚ÐµÐºÐ° поправке боје</comment>
@@ -38437,6 +39704,7 @@
<comment xml:lang="eu">WinHelp laguntza fitxategia</comment>
<comment xml:lang="fi">WinHelp-ohjetiedosto</comment>
<comment xml:lang="fr">fichier d'aide WinHelp</comment>
+ <comment xml:lang="ga">comhad cabhrach WinHelp</comment>
<comment xml:lang="gl">Ficheiro de axuda WinHelp</comment>
<comment xml:lang="he">קובץ עזרה מסוג WinHelp</comment>
<comment xml:lang="hr">WinHelp datoteka pomoći</comment>
@@ -38452,7 +39720,7 @@
<comment xml:lang="pl">Plik pomocy WinHelp</comment>
<comment xml:lang="pt">ficheiro de ajuda WinHelp</comment>
<comment xml:lang="pt_BR">Arquivo de ajuda WinHelp</comment>
- <comment xml:lang="ru">файл Ñправки WinHelp</comment>
+ <comment xml:lang="ru">Файл Ñправки WinHelp</comment>
<comment xml:lang="sk">Súbor Pomocníka WinHelp</comment>
<comment xml:lang="sl">Datoteka pomoÄi WinHelp</comment>
<comment xml:lang="sr">датотека помоћи Вин хелпа</comment>
@@ -38470,18 +39738,28 @@
<mime-type type="application/x-bsdiff">
<comment>binary differences between files</comment>
<comment xml:lang="ca">diferencies binàries entre fitxers</comment>
+ <comment xml:lang="cs">binární rozdíl mezi soubory</comment>
<comment xml:lang="da">binære forskelle mellem filer</comment>
<comment xml:lang="de">binäre Unterschiede zwischen Dateien</comment>
+ <comment xml:lang="en_GB">binary differences between files</comment>
<comment xml:lang="es">diferencias entre archivos binarios</comment>
+ <comment xml:lang="eu">fitxategi binarioen arteko ezberdinstasunak</comment>
<comment xml:lang="fr">différences binaires entre fichiers</comment>
+ <comment xml:lang="ga">difríochtaí dénártha idir comhaid</comment>
<comment xml:lang="he">×”×‘×“×œ×™× ×‘×™× ×¨×™×™× ×‘×™×Ÿ קבצי×</comment>
+ <comment xml:lang="hr">Binarne razlike između datoteka</comment>
<comment xml:lang="hu">bináris különbségfájl</comment>
+ <comment xml:lang="id">perbedaan biner antar berkas</comment>
+ <comment xml:lang="it">Differenze binarie tra file</comment>
<comment xml:lang="kk">файлдар араÑындағы бинарлық айырмашылықтар</comment>
<comment xml:lang="ko">ë°”ì´ë„ˆë¦¬ ì°¨ì´ ë¹„êµ íŒŒì¼</comment>
<comment xml:lang="pl">Binarna różnica pomiędzy plikami</comment>
<comment xml:lang="pt_BR">Diferenças binárias entre arquivos</comment>
- <comment xml:lang="ru">двоичные Ñ€Ð°Ð·Ð»Ð¸Ñ‡Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ файлами</comment>
+ <comment xml:lang="ru">Двоичные Ñ€Ð°Ð·Ð»Ð¸Ñ‡Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ файлами</comment>
<comment xml:lang="sk">Binárne rozdiely medzi súbormi</comment>
+ <comment xml:lang="sr">бинарне разлике датотека</comment>
+ <comment xml:lang="sv">binära skillnader mellan filer</comment>
+ <comment xml:lang="tr">dosyalar arasındaki ikilik farklar</comment>
<comment xml:lang="uk">двійкова Ñ€Ñ–Ð·Ð½Ð¸Ñ†Ñ Ð¼Ñ–Ð¶ файлами</comment>
<comment xml:lang="zh_CN">文件的二进制区别</comment>
<comment xml:lang="zh_TW">檔案間的二進ä½å·®ç•°</comment>
@@ -38513,7 +39791,7 @@
<comment xml:lang="ga">grianghraif dhigiteacha</comment>
<comment xml:lang="gl">fotos dixitais</comment>
<comment xml:lang="he">תמונות דיגיטליות</comment>
- <comment xml:lang="hr">digitalne fotografije</comment>
+ <comment xml:lang="hr">Digitalne fotografije</comment>
<comment xml:lang="hu">digitális fényképek</comment>
<comment xml:lang="ia">Photos digital</comment>
<comment xml:lang="id">foto digital</comment>
@@ -38530,7 +39808,7 @@
<comment xml:lang="pt">fotografias digitais</comment>
<comment xml:lang="pt_BR">Fotos digitais</comment>
<comment xml:lang="ro">fotografii digitale</comment>
- <comment xml:lang="ru">цифровые фотографии</comment>
+ <comment xml:lang="ru">Цифровые фотографии</comment>
<comment xml:lang="sk">Digitálne fotografie</comment>
<comment xml:lang="sl">digitalne fotografije</comment>
<comment xml:lang="sq">Fotografi dixhitale</comment>
@@ -38550,6 +39828,7 @@
<comment>Video CD</comment>
<comment xml:lang="ar">Video CD</comment>
+ <comment xml:lang="ast">CD de videu</comment>
<comment xml:lang="be@latin">Videa CD</comment>
<comment xml:lang="bg">CD — видео</comment>
<comment xml:lang="ca">Video CD</comment>
@@ -38564,7 +39843,7 @@
<comment xml:lang="fi">Video CD</comment>
<comment xml:lang="fo">Video CD</comment>
<comment xml:lang="fr">CD vidéo</comment>
- <comment xml:lang="ga">Video CD</comment>
+ <comment xml:lang="ga">dlúthdhiosca físe</comment>
<comment xml:lang="gl">Video CD</comment>
<comment xml:lang="he">תקליטור ויד×ו</comment>
<comment xml:lang="hr">Video CD</comment>
@@ -38584,7 +39863,7 @@
<comment xml:lang="pt">Video CD</comment>
<comment xml:lang="pt_BR">CD de vídeo</comment>
<comment xml:lang="ro">CD video</comment>
- <comment xml:lang="ru">видеодиÑк VCD</comment>
+ <comment xml:lang="ru">Видео CD</comment>
<comment xml:lang="sk">Video CD</comment>
<comment xml:lang="sl">Video CD</comment>
<comment xml:lang="sq">CD Video</comment>
@@ -38604,6 +39883,7 @@
<comment>Super Video CD</comment>
<comment xml:lang="ar">Super Video CD</comment>
+ <comment xml:lang="ast">CD de Super Video</comment>
<comment xml:lang="be@latin">Super Video CD</comment>
<comment xml:lang="bg">CD — Ñупер видео</comment>
<comment xml:lang="ca">Super Video CD</comment>
@@ -38618,7 +39898,7 @@
<comment xml:lang="fi">Super Video CD</comment>
<comment xml:lang="fo">Super Video CD</comment>
<comment xml:lang="fr">Super VCD</comment>
- <comment xml:lang="ga">Super Video CD</comment>
+ <comment xml:lang="ga">dlúthdhiosca Super Video</comment>
<comment xml:lang="gl">Super vídeo CD</comment>
<comment xml:lang="he">Super Video CD</comment>
<comment xml:lang="hr">Super Video CD</comment>
@@ -38638,7 +39918,7 @@
<comment xml:lang="pt">Super Video CD</comment>
<comment xml:lang="pt_BR">CD de Super Vídeo (SVCD)</comment>
<comment xml:lang="ro">Super Video CD</comment>
- <comment xml:lang="ru">компакт-диÑк Super Video</comment>
+ <comment xml:lang="ru">Super Video CD</comment>
<comment xml:lang="sk">Super Video CD</comment>
<comment xml:lang="sl">Super Video CD</comment>
<comment xml:lang="sq">CD Super Video</comment>
@@ -38658,6 +39938,7 @@
<comment>video DVD</comment>
<comment xml:lang="ar">DVD مرئي</comment>
+ <comment xml:lang="ast">DVD de videu</comment>
<comment xml:lang="be@latin">videa DVD</comment>
<comment xml:lang="bg">DVD — видео</comment>
<comment xml:lang="ca">DVD-Video</comment>
@@ -38675,7 +39956,7 @@
<comment xml:lang="ga">DVD físe</comment>
<comment xml:lang="gl">DVD de vídeo</comment>
<comment xml:lang="he">DVD ויד×ו</comment>
- <comment xml:lang="hr">video DVD</comment>
+ <comment xml:lang="hr">Video DVD</comment>
<comment xml:lang="hu">video DVD</comment>
<comment xml:lang="ia">DVD video</comment>
<comment xml:lang="id">DVD video</comment>
@@ -38693,7 +39974,7 @@
<comment xml:lang="pt">DVD vídeo</comment>
<comment xml:lang="pt_BR">DVD de vídeo</comment>
<comment xml:lang="ro">DVD video</comment>
- <comment xml:lang="ru">видео-DVD</comment>
+ <comment xml:lang="ru">Видео DVD</comment>
<comment xml:lang="sk">DVD-Video</comment>
<comment xml:lang="sl">video DVD</comment>
<comment xml:lang="sq">DVD video</comment>
@@ -38750,7 +40031,7 @@
<comment xml:lang="pt">CD áudio</comment>
<comment xml:lang="pt_BR">CD de áudio</comment>
<comment xml:lang="ro">CD audio</comment>
- <comment xml:lang="ru">звуковой CD</comment>
+ <comment xml:lang="ru">Ðудио CD</comment>
<comment xml:lang="sk">Zvukové CD</comment>
<comment xml:lang="sl">zvoÄni CD</comment>
<comment xml:lang="sq">CD audio</comment>
@@ -38800,7 +40081,7 @@
<comment xml:lang="pt">CD vazio</comment>
<comment xml:lang="pt_BR">Disco CD vazio</comment>
<comment xml:lang="ro">disc gol CD</comment>
- <comment xml:lang="ru">чиÑтый компакт-диÑк</comment>
+ <comment xml:lang="ru">ЧиÑтый диÑк CD</comment>
<comment xml:lang="sk">Prázdny disk CD</comment>
<comment xml:lang="sl">prazen CD disk</comment>
<comment xml:lang="sq">Disk bosh CD</comment>
@@ -38850,7 +40131,7 @@
<comment xml:lang="pt">DVD vazio</comment>
<comment xml:lang="pt_BR">Disco DVD vazio</comment>
<comment xml:lang="ro">disc gol DVD</comment>
- <comment xml:lang="ru">чиÑтый диÑк DVD</comment>
+ <comment xml:lang="ru">ЧиÑтый диÑк DVD</comment>
<comment xml:lang="sk">Prázdny disk DVD</comment>
<comment xml:lang="sl">prazen DVD disk</comment>
<comment xml:lang="sq">Disk bosh DVD</comment>
@@ -38900,7 +40181,7 @@
<comment xml:lang="pt">Blu-Ray vazio</comment>
<comment xml:lang="pt_BR">Disco Blu-ray vazio</comment>
<comment xml:lang="ro">disc gol Blu-ray</comment>
- <comment xml:lang="ru">чиÑтый диÑк Blu-ray</comment>
+ <comment xml:lang="ru">ЧиÑтый диÑк Blu-ray</comment>
<comment xml:lang="sk">Prázdny disk Blu-ray</comment>
<comment xml:lang="sl">prazen Blu-Ray disk</comment>
<comment xml:lang="sq">Disk bosh Blu-ray</comment>
@@ -38950,7 +40231,7 @@
<comment xml:lang="pt">HD DVD vazio</comment>
<comment xml:lang="pt_BR">Disco HD DVD vazio</comment>
<comment xml:lang="ro">disc gol HD DVD</comment>
- <comment xml:lang="ru">чиÑтый диÑк HD DVD</comment>
+ <comment xml:lang="ru">ЧиÑтый диÑк HD DVD</comment>
<comment xml:lang="sk">Prázdny disk HD DVD</comment>
<comment xml:lang="sl">prazen HD DVD disk</comment>
<comment xml:lang="sq">Disk bosh DVD HD</comment>
@@ -39001,7 +40282,7 @@
<comment xml:lang="pt">DVD áudio</comment>
<comment xml:lang="pt_BR">DVD de áudio</comment>
<comment xml:lang="ro">DVD audio</comment>
- <comment xml:lang="ru">звуковой DVD</comment>
+ <comment xml:lang="ru">Ðудио DVD</comment>
<comment xml:lang="sk">Zvukové DVD</comment>
<comment xml:lang="sl">zvoÄni DVD</comment>
<comment xml:lang="sq">DVD audio</comment>
@@ -39022,6 +40303,7 @@
<comment>Blu-ray video disc</comment>
<comment xml:lang="ar">قرص بلو-راي مرئي</comment>
+ <comment xml:lang="ast">Discu Blu-ray de videu</comment>
<comment xml:lang="be@latin">Videadysk Blu-ray</comment>
<comment xml:lang="bg">Blu-ray — видео</comment>
<comment xml:lang="ca">disc de vídeo Blu-Ray</comment>
@@ -39056,7 +40338,7 @@
<comment xml:lang="pt">Blu-ray de vídeo</comment>
<comment xml:lang="pt_BR">Disco de vídeo Blu-ray</comment>
<comment xml:lang="ro">Disc video Blu-ray</comment>
- <comment xml:lang="ru">видеодиÑк Blu-ray</comment>
+ <comment xml:lang="ru">ВидеодиÑк Blu-ray</comment>
<comment xml:lang="sk">Videodisk Blu-ray</comment>
<comment xml:lang="sl">Blu-ray video disk</comment>
<comment xml:lang="sq">Disk video Blu-ray</comment>
@@ -39077,6 +40359,7 @@
<comment>HD DVD video disc</comment>
<comment xml:lang="ar">قرص HD DVD مرئي</comment>
+ <comment xml:lang="ast">Discu HD DVD de videu</comment>
<comment xml:lang="be@latin">Videadysk HD DVD</comment>
<comment xml:lang="bg">HD DVD — видео</comment>
<comment xml:lang="ca">disc de vídeo HD-DVD</comment>
@@ -39110,7 +40393,7 @@
<comment xml:lang="pt">HD DVD de vídeo</comment>
<comment xml:lang="pt_BR">Disco de vídeo HD DVD</comment>
<comment xml:lang="ro">Disc video HD DVD</comment>
- <comment xml:lang="ru">видеодиÑк HD DVD</comment>
+ <comment xml:lang="ru">ВидеодиÑк HD DVD</comment>
<comment xml:lang="sk">Videodisk HD DVD</comment>
<comment xml:lang="sl">HD DVD video disk</comment>
<comment xml:lang="sq">Disk video DVD HD</comment>
@@ -39142,9 +40425,10 @@
<comment xml:lang="eu">e-book irakurlea</comment>
<comment xml:lang="fi">e-kirjan lukulaite</comment>
<comment xml:lang="fr">lecteur de livre numérique</comment>
+ <comment xml:lang="ga">léitheoir r-leabhair</comment>
<comment xml:lang="gl">lector de libros electrónicos</comment>
<comment xml:lang="he">×§×•×¨× ×¡×¤×¨×™× ×לקטרוניי×</comment>
- <comment xml:lang="hr">ÄitaÄ e-knjiga</comment>
+ <comment xml:lang="hr">ÄŒitaÄ e-knjiga</comment>
<comment xml:lang="hu">e-könyvolvasó</comment>
<comment xml:lang="ia">Lector de libro electronic</comment>
<comment xml:lang="id">Pembaca e-book</comment>
@@ -39158,7 +40442,7 @@
<comment xml:lang="pl">Czytnik e-booków</comment>
<comment xml:lang="pt">leitor de ebooks</comment>
<comment xml:lang="pt_BR">Leitor de e-book</comment>
- <comment xml:lang="ru">уÑтройÑтво Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ñлектронных книг</comment>
+ <comment xml:lang="ru">УÑтройÑтво Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ñлектронных книг</comment>
<comment xml:lang="sk">ČítaÄka e-kníh</comment>
<comment xml:lang="sl">Bralnik elektronskih knjig</comment>
<comment xml:lang="sr">читач ел. књига</comment>
@@ -39190,7 +40474,7 @@
<comment xml:lang="fi">Picture CD</comment>
<comment xml:lang="fo">Picture CD</comment>
<comment xml:lang="fr">CD Picture</comment>
- <comment xml:lang="ga">Picture CD</comment>
+ <comment xml:lang="ga">dlúthdhiosca grianghraf</comment>
<comment xml:lang="gl">Picture CD</comment>
<comment xml:lang="he">תקליטור תמונות</comment>
<comment xml:lang="hr">Slikovni CD</comment>
@@ -39246,7 +40530,7 @@
<comment xml:lang="ga">seinnteoir iniompartha fuaime</comment>
<comment xml:lang="gl">dispositivo de son portábel</comment>
<comment xml:lang="he">נגן מוזיקה נייד</comment>
- <comment xml:lang="hr">prenosivi audio sviraÄ</comment>
+ <comment xml:lang="hr">Prenosivi glazbeni sviraÄ</comment>
<comment xml:lang="hu">hordozható zenelejátszó</comment>
<comment xml:lang="ia">Lector audio portabile</comment>
<comment xml:lang="id">pemutar audio portable</comment>
@@ -39263,7 +40547,7 @@
<comment xml:lang="pt">reprodutor áudio portátil</comment>
<comment xml:lang="pt_BR">Reprodutor de áudio portátil</comment>
<comment xml:lang="ro">player audio portabil</comment>
- <comment xml:lang="ru">портативный аудиопроигрыватель</comment>
+ <comment xml:lang="ru">Портативный аудиопроигрыватель</comment>
<comment xml:lang="sk">Prenosný hudobný prehrávaÄ</comment>
<comment xml:lang="sl">prenosni predvajalnik zvoka</comment>
<comment xml:lang="sq">Lexues audio portativ</comment>
@@ -39296,7 +40580,7 @@
<comment xml:lang="ga">bogearraí</comment>
<comment xml:lang="gl">software</comment>
<comment xml:lang="he">תכנה</comment>
- <comment xml:lang="hr">softver</comment>
+ <comment xml:lang="hr">Softver</comment>
<comment xml:lang="hu">szoftver</comment>
<comment xml:lang="ia">Software</comment>
<comment xml:lang="id">peranti lunak</comment>
@@ -39314,7 +40598,7 @@
<comment xml:lang="pt">programa</comment>
<comment xml:lang="pt_BR">Aplicativo</comment>
<comment xml:lang="ro">software</comment>
- <comment xml:lang="ru">программное обеÑпечение</comment>
+ <comment xml:lang="ru">Программное обеÑпечение</comment>
<comment xml:lang="sk">Softvér</comment>
<comment xml:lang="sl">programska oprema</comment>
<comment xml:lang="sq">Software</comment>
@@ -39362,7 +40646,7 @@
<comment xml:lang="pt">programa UNIX</comment>
<comment xml:lang="pt_BR">Aplicativo UNIX</comment>
<comment xml:lang="ro">Software UNIX</comment>
- <comment xml:lang="ru">программа UNIX</comment>
+ <comment xml:lang="ru">Программа UNIX</comment>
<comment xml:lang="sk">Softvér UNIX</comment>
<comment xml:lang="sl">Programska datoteka UNIX</comment>
<comment xml:lang="sr">ЈУÐИКС-ов Ñофтвер</comment>
@@ -39414,7 +40698,7 @@
<comment xml:lang="pt">programa Windows</comment>
<comment xml:lang="pt_BR">Programa do Windows</comment>
<comment xml:lang="ro">Software Windows</comment>
- <comment xml:lang="ru">программа Windows</comment>
+ <comment xml:lang="ru">Программа Windows</comment>
<comment xml:lang="sk">Softvér Windows</comment>
<comment xml:lang="sl">Programska oprema za okolje Windows</comment>
<comment xml:lang="sr">Виндоузов Ñофтвер</comment>
@@ -39430,9 +40714,9 @@
</treemagic>
</mime-type>
- <mime-type type="application/x-trig">
-
+ <mime-type type="application/trig">
<comment>TriG RDF document</comment>
+ <comment xml:lang="ast">Documentu RDF TriG</comment>
<comment xml:lang="ca">document TriG RDF</comment>
<comment xml:lang="cs">dokument Trig RDF</comment>
<comment xml:lang="da">TriG RDF-dokument</comment>
@@ -39443,6 +40727,7 @@
<comment xml:lang="eu">TriG RDF dokumentua</comment>
<comment xml:lang="fi">TriG RDF -asiakirja</comment>
<comment xml:lang="fr">document RDF TriG</comment>
+ <comment xml:lang="ga">cáipéis RDF TriG</comment>
<comment xml:lang="gl">Documento RDF TriG</comment>
<comment xml:lang="he">מסמך RDF של TriG</comment>
<comment xml:lang="hr">TriG RDF dokument</comment>
@@ -39469,6 +40754,7 @@
<expanded-acronym>TriG RDF Graph Triple Language</expanded-acronym>
<sub-class-of type="text/plain"/>
<glob pattern="*.trig"/>
+ <alias type="application/x-trig"/>
</mime-type>
<mime-type type="application/x-iwork-keynote-sffkey">
@@ -39483,6 +40769,7 @@
<comment xml:lang="eu">Apple Keynote 5 aurkezpena</comment>
<comment xml:lang="fi">Apple Keynote 5 -esitys</comment>
<comment xml:lang="fr">présentation Apple Keynote 5</comment>
+ <comment xml:lang="ga">láithreoireacht Apple Keynote 5</comment>
<comment xml:lang="gl">Presentación de Apple Keynote 5</comment>
<comment xml:lang="he">מצגת Apple Keynote 5</comment>
<comment xml:lang="hr">Apple Keynote 5 prezentacija</comment>
@@ -39528,6 +40815,7 @@
<comment xml:lang="eu">Adobe PageMaker</comment>
<comment xml:lang="fi">Adobe PageMaker</comment>
<comment xml:lang="fr">Adobe PageMaker</comment>
+ <comment xml:lang="ga">Adobe PageMaker</comment>
<comment xml:lang="gl">Adobe PageMaker</comment>
<comment xml:lang="he">Adobe PageMaker</comment>
<comment xml:lang="hr">Adobe PageMaker</comment>
@@ -39568,6 +40856,7 @@
<comment xml:lang="es">WAD de Doom</comment>
<comment xml:lang="eu">Doom WAD</comment>
<comment xml:lang="fr">WAD Doom</comment>
+ <comment xml:lang="ga">WAD Doom</comment>
<comment xml:lang="hr">Doom WAD</comment>
<comment xml:lang="hu">Doom WAD</comment>
<comment xml:lang="ia">WAD pro Doom</comment>
@@ -39608,6 +40897,7 @@
<comment xml:lang="eu">Amiga disko irudia</comment>
<comment xml:lang="fi">Amiga-levytiedosto</comment>
<comment xml:lang="fr">image disque Amiga</comment>
+ <comment xml:lang="ga">íomhá diosca Amiga</comment>
<comment xml:lang="he">דמות כונן Amiga</comment>
<comment xml:lang="hr">Amiga slika diska</comment>
<comment xml:lang="hu">Amiga lemezkép</comment>
@@ -39615,18 +40905,18 @@
<comment xml:lang="id">Image disk Amiga</comment>
<comment xml:lang="it">Disco immagine Amiga</comment>
<comment xml:lang="kk">Amiga диÑк бейнеÑÑ–</comment>
- <comment xml:lang="ko">아미가 ë””ìŠ¤í¬ ì´ë¯¸ì§€</comment>
+ <comment xml:lang="ko">Amiga ë””ìŠ¤í¬ ì´ë¯¸ì§€</comment>
<comment xml:lang="oc">imatge disc Amiga</comment>
<comment xml:lang="pl">Obraz dysku Amiga</comment>
<comment xml:lang="pt">imagem de disco Amiga</comment>
<comment xml:lang="pt_BR">Imagem de disco Amiga</comment>
- <comment xml:lang="ru">образ диÑка Amiga</comment>
+ <comment xml:lang="ru">Образ диÑка Amiga</comment>
<comment xml:lang="sk">Obraz disku Amiga</comment>
<comment xml:lang="sr">Ñлика диÑка Ðмиге</comment>
<comment xml:lang="sv">Amiga-diskavbild</comment>
<comment xml:lang="tr">Amiga disk kalıbı</comment>
<comment xml:lang="uk">образ диÑка Amiga</comment>
- <comment xml:lang="zh_CN">Amiga ç£ç›˜é•œåƒ</comment>
+ <comment xml:lang="zh_CN">Amiga ç£ç›˜æ˜ åƒ</comment>
<comment xml:lang="zh_TW">Amiga ç£ç¢Ÿæ˜ åƒæª”</comment>
<magic priority="50">
<match value="DOS\x00" type="string" offset="0"/>
@@ -39637,19 +40927,31 @@
<mime-type type="application/vnd.flatpak">
<comment>Flatpak application bundle</comment>
<comment xml:lang="ca">paquet d'aplicació Flatpak</comment>
+ <comment xml:lang="cs">balíÄek Flatpak s aplikací</comment>
<comment xml:lang="da">Flatpak-programsamling</comment>
<comment xml:lang="de">Flatpak-Anwendungspaket</comment>
+ <comment xml:lang="en_GB">Flatpak application bundle</comment>
<comment xml:lang="es">paquete de aplicación Flatpak</comment>
+ <comment xml:lang="eu">Flatpak aplikazio bilduma</comment>
+ <comment xml:lang="fi">Flatpak-sovelluspaketti</comment>
<comment xml:lang="fr">lot applicatif Flatpak</comment>
+ <comment xml:lang="ga">burla feidhmchláir Flatpak</comment>
+ <comment xml:lang="he">חבילת יישומי Flatpak</comment>
+ <comment xml:lang="hr">Flatpak paket aplikacije</comment>
<comment xml:lang="hu">Flatpak alkalmazáscsomag</comment>
+ <comment xml:lang="id">bundel aplikasi Flatpak</comment>
+ <comment xml:lang="it">Bundle applicazione Flatpak</comment>
<comment xml:lang="kk">Flatpak қолданбалар деÑтеÑÑ–</comment>
<comment xml:lang="ko">Flatpak 프로그램 번들</comment>
<comment xml:lang="pl">Pakiet programu Flatpak</comment>
<comment xml:lang="pt_BR">Pacote de aplicativo Flatpak</comment>
- <comment xml:lang="ru">пакет приложений Flatpak</comment>
+ <comment xml:lang="ru">Пакет Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Flatpak</comment>
<comment xml:lang="sk">Balík aplikácií Flatpak</comment>
+ <comment xml:lang="sr">Ñкуп програма Флатпака</comment>
+ <comment xml:lang="sv">Flatpak-programbunt</comment>
+ <comment xml:lang="tr">Flatpak uygulama paketi</comment>
<comment xml:lang="uk">пакунок із програмами Flatpak</comment>
- <comment xml:lang="zh_CN">Flatpak 应用包</comment>
+ <comment xml:lang="zh_CN">Flatpak 应用组åˆåŒ…</comment>
<comment xml:lang="zh_TW">Flatpak 應用程å¼å¥—組</comment>
<generic-icon name="package-x-generic"/>
<magic priority="50">
@@ -39664,17 +40966,29 @@
<mime-type type="application/vnd.flatpak.repo">
<comment>Flatpak repository description</comment>
<comment xml:lang="ca">descripció de dipòsit de Flatpak</comment>
+ <comment xml:lang="cs">popis repozitáře Flatpak</comment>
<comment xml:lang="da">Flatpak-arkivbeskrivelse</comment>
<comment xml:lang="de">Flatpak-Repositoriumsbeschreibung</comment>
+ <comment xml:lang="en_GB">Flatpak repository description</comment>
<comment xml:lang="es">descripción de repositorio de Flatpak</comment>
+ <comment xml:lang="eu">Flatpak biltegi deskribapena</comment>
+ <comment xml:lang="fi">Flatpak-ohjelmistolähdekuvaus</comment>
<comment xml:lang="fr">description de dépôt Flatpak</comment>
+ <comment xml:lang="ga">cur síos ar stórlann Flatpak</comment>
+ <comment xml:lang="he">תי×ור מ×גר Flatpak</comment>
+ <comment xml:lang="hr">Flatpak opis repozitorija</comment>
<comment xml:lang="hu">Flatpak tárolóleírás</comment>
+ <comment xml:lang="id">deskripsi repositori Flatpak</comment>
+ <comment xml:lang="it">Descrizione repository Flatpack</comment>
<comment xml:lang="kk">Flatpak репозиторийі ÑипаттамаÑÑ‹</comment>
<comment xml:lang="ko">Flatpak 저장소 디스í¬ë¦½ì…˜</comment>
<comment xml:lang="pl">Opis repozytorium Flatpak</comment>
<comment xml:lang="pt_BR">Descrição de repositório Flatpak</comment>
- <comment xml:lang="ru">опиÑание Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Flatpak</comment>
+ <comment xml:lang="ru">ОпиÑание Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Flatpak</comment>
<comment xml:lang="sk">Popis repozitára Flatpak</comment>
+ <comment xml:lang="sr">Ð¾Ð¿Ð¸Ñ Ñ€Ð¸Ð·Ð½Ð¸Ñ†Ðµ Флатпака</comment>
+ <comment xml:lang="sv">Flatpak-förrådsbeskrivning</comment>
+ <comment xml:lang="tr">Flatpak depo açıklaması</comment>
<comment xml:lang="uk">Ð¾Ð¿Ð¸Ñ Ñховища Flatpak</comment>
<comment xml:lang="zh_CN">Flatpak 软件库æè¿°</comment>
<comment xml:lang="zh_TW">Flatpak 軟體庫æè¿°</comment>
@@ -39688,6 +41002,31 @@
<mime-type type="application/vnd.flatpak.ref">
<comment>Flatpak repository reference</comment>
+ <comment xml:lang="ca">referència de dipòsit Flatpak</comment>
+ <comment xml:lang="cs">odkaz na repozitář Flatpak</comment>
+ <comment xml:lang="de">Flatpak-Repositoriumsreferenz</comment>
+ <comment xml:lang="en_GB">Flatpak repository reference</comment>
+ <comment xml:lang="es">referencia a repositorio de Flatpak</comment>
+ <comment xml:lang="eu">Flatpak biltegi erreferentzia</comment>
+ <comment xml:lang="fi">Flatpak-ohjelmistolähdeviite</comment>
+ <comment xml:lang="fr">référence de dépôt Flatpak</comment>
+ <comment xml:lang="ga">tagairt do stórlann Flatpak</comment>
+ <comment xml:lang="hr">Flatpak preporuÄeni repozitorij</comment>
+ <comment xml:lang="hu">Flatpak tárolóhivatkozás</comment>
+ <comment xml:lang="id">acuan repositori Flatpak</comment>
+ <comment xml:lang="it">Riferimento repository Flatpack</comment>
+ <comment xml:lang="kk">Flatpak репозиторийіне Ñілтеме</comment>
+ <comment xml:lang="ko">Flatpak 저장소 참조</comment>
+ <comment xml:lang="pl">Odwołanie do repozytorium Flatpak</comment>
+ <comment xml:lang="pt_BR">Referência de repositório Flatpak</comment>
+ <comment xml:lang="ru">СÑылка на репозиторий Flatpak</comment>
+ <comment xml:lang="sk">Referencia repozitára Flatpak</comment>
+ <comment xml:lang="sr">упута ризнице Флатпака</comment>
+ <comment xml:lang="sv">Flatpak-förrådsreferens</comment>
+ <comment xml:lang="tr">Flatpak depo baÅŸvurusu</comment>
+ <comment xml:lang="uk">поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° Ñховище Flatpak</comment>
+ <comment xml:lang="zh_CN">Flatpak 软件库引用</comment>
+ <comment xml:lang="zh_TW">Flatpak 軟體庫åƒç…§</comment>
<generic-icon name="package-x-generic"/>
<sub-class-of type="text/plain"/>
<magic priority="50">
@@ -39699,18 +41038,29 @@
<mime-type type="application/vnd.squashfs">
<comment>Squashfs filesystem</comment>
<comment xml:lang="ca">Sistema de fitxers Squashfs</comment>
+ <comment xml:lang="cs">souborový systém Squashfs</comment>
<comment xml:lang="da">Squashfs-filsystem</comment>
<comment xml:lang="de">Squashfs-Dateisystem</comment>
+ <comment xml:lang="en_GB">Squashfs filesystem</comment>
<comment xml:lang="es">sistema de archivos Squashfs</comment>
+ <comment xml:lang="eu">Squashfs fitxategi sistema</comment>
+ <comment xml:lang="fi">Squashfs-tiedostojärjestelmä</comment>
<comment xml:lang="fr">système de fichiers Squashfs</comment>
+ <comment xml:lang="ga">córas comhad Squashfs</comment>
<comment xml:lang="he">מערכת ×§×‘×¦×™× Squashfs</comment>
+ <comment xml:lang="hr">Squashfs datoteÄni sustav</comment>
<comment xml:lang="hu">Squashfs fájlrendszer</comment>
+ <comment xml:lang="id">sistem berkas Squashfs</comment>
+ <comment xml:lang="it">File system squashfs</comment>
<comment xml:lang="kk">Squashfs файлдық жүйеÑÑ–</comment>
<comment xml:lang="ko">Squashfs íŒŒì¼ ì‹œìŠ¤í…œ</comment>
<comment xml:lang="pl">System plików SquashFS</comment>
<comment xml:lang="pt_BR">Sistema de arquivos Squashfs</comment>
- <comment xml:lang="ru">Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема Squashfs</comment>
+ <comment xml:lang="ru">Ð¤Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема Squashfs</comment>
<comment xml:lang="sk">Systém súborov Squashfs</comment>
+ <comment xml:lang="sr">ÑиÑтем датотека СквошфÑ</comment>
+ <comment xml:lang="sv">Squashfs-filsystem</comment>
+ <comment xml:lang="tr">Squashfs dosya sistemi</comment>
<comment xml:lang="uk">файлова ÑиÑтема squashfs</comment>
<comment xml:lang="zh_CN">Squashfs 文件系统</comment>
<comment xml:lang="zh_TW">Squashfs 檔案系統</comment>
@@ -39721,21 +41071,77 @@
<glob pattern="*.sqsh"/>
</mime-type>
+
+ <mime-type type="application/vnd.appimage">
+ <comment>AppImage application bundle</comment>
+ <comment xml:lang="ca">paquet d'aplicació AppImage</comment>
+ <comment xml:lang="cs">balíÄek AppImage s aplikací</comment>
+ <comment xml:lang="da">Applmage-programsamling</comment>
+ <comment xml:lang="de">AppImage-Anwendungspaket</comment>
+ <comment xml:lang="en_GB">AppImage application bundle</comment>
+ <comment xml:lang="es">paquete de aplicación AppImage</comment>
+ <comment xml:lang="eu">AppImage aplikazio bilduma</comment>
+ <comment xml:lang="fi">AppImage-sovelluspaketti</comment>
+ <comment xml:lang="fr">lot applicatif AppImage</comment>
+ <comment xml:lang="ga">burla feidhmchláir AppImage</comment>
+ <comment xml:lang="he">חבילת יישומי AppImage</comment>
+ <comment xml:lang="hr">AppImage paket aplikacije</comment>
+ <comment xml:lang="hu">AppImage alkalmazáscsomag</comment>
+ <comment xml:lang="id">bundel aplikasi AppImage</comment>
+ <comment xml:lang="it">Bundle applicazione AppImage</comment>
+ <comment xml:lang="kk">AppImage қолданбалар деÑтеÑÑ–</comment>
+ <comment xml:lang="ko">AppImage 프로그램 번들</comment>
+ <comment xml:lang="pl">Pakiet programu AppImage</comment>
+ <comment xml:lang="pt_BR">Pacote de aplicativo AppImage</comment>
+ <comment xml:lang="ru">Пакет Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ AppImage</comment>
+ <comment xml:lang="sk">Balík aplikácií AppImage</comment>
+ <comment xml:lang="sr">Ñкуп програма Ðп-Ñлике</comment>
+ <comment xml:lang="sv">AppImage-programbunt</comment>
+ <comment xml:lang="tr">AppImage uygulama paketi</comment>
+ <comment xml:lang="uk">пакунок із програмами AppImage</comment>
+ <comment xml:lang="zh_CN">AppImage 应用组åˆåŒ…</comment>
+ <comment xml:lang="zh_TW">AppImage 應用程å¼å¥—組</comment>
+ <sub-class-of type="application/x-executable"/>
+ <sub-class-of type="application/vnd.squashfs"/>
+ <generic-icon name="application-x-executable"/>
+ <magic priority="50">
+ <match value="ELF" type="string" offset="1">
+ <match value="0x41" type="byte" offset="8">
+ <match value="0x49" type="byte" offset="9">
+ <match value="0x02" type="byte" offset="10"/>
+ </match>
+ </match>
+ </match>
+ </magic>
+ <glob weight="60" pattern="*.appimage"/>
+ </mime-type>
+
<mime-type type="application/vnd.snap">
<comment>Snap package</comment>
<comment xml:lang="ca">Paquet Snap</comment>
+ <comment xml:lang="cs">balíÄek Snap</comment>
<comment xml:lang="da">Snap-pakke</comment>
<comment xml:lang="de">Snap-Paket</comment>
+ <comment xml:lang="en_GB">Snap package</comment>
<comment xml:lang="es">paquete Snap</comment>
+ <comment xml:lang="eu">Snap paketea</comment>
+ <comment xml:lang="fi">Snap-paketti</comment>
<comment xml:lang="fr">paquet Snap</comment>
+ <comment xml:lang="ga">pacáiste Snap</comment>
<comment xml:lang="he">חבילת Snap</comment>
+ <comment xml:lang="hr">Snap paket</comment>
<comment xml:lang="hu">Snap-csomag</comment>
+ <comment xml:lang="id">paket Snap</comment>
+ <comment xml:lang="it">Pacchetto snap</comment>
<comment xml:lang="kk">Snap деÑтеÑÑ–</comment>
<comment xml:lang="ko">Snap 패키지</comment>
<comment xml:lang="pl">Pakiet Snap</comment>
<comment xml:lang="pt_BR">Pacote Snap</comment>
- <comment xml:lang="ru">пакет Snap</comment>
+ <comment xml:lang="ru">Пакет Snap</comment>
<comment xml:lang="sk">Balík Snap</comment>
+ <comment xml:lang="sr">Снап пакет</comment>
+ <comment xml:lang="sv">Snap-paket</comment>
+ <comment xml:lang="tr">Snap paketi</comment>
<comment xml:lang="uk">пакунок snap</comment>
<comment xml:lang="zh_CN">Snap 软件包</comment>
<comment xml:lang="zh_TW">Snap 軟體包</comment>
@@ -39743,4 +41149,85 @@
<sub-class-of type="application/vnd.squashfs"/>
</mime-type>
+
+ <mime-type type="model/stl">
+ <comment>STL 3D model</comment>
+ <acronym>STL</acronym>
+ <expanded-acronym>StereoLithography</expanded-acronym>
+ <magic priority="50">
+ <match value="solid" type="string" offset="0"/>
+ <match value="SOLID" type="string" offset="0"/>
+ </magic>
+ <glob pattern="*.stl"/>
+ <alias type="model/x.stl-ascii"/>
+ <alias type="model/x.stl-binary"/>
+ </mime-type>
+
+ <mime-type type="text/x.gcode">
+ <comment>G-code file</comment>
+ <comment xml:lang="ca">fitxer G-code</comment>
+ <comment xml:lang="cs">soubor G-code</comment>
+ <comment xml:lang="de">G-Code-Datei</comment>
+ <comment xml:lang="en_GB">G-code file</comment>
+ <comment xml:lang="es">archivo G-code</comment>
+ <comment xml:lang="eu">G-code fitxategia</comment>
+ <comment xml:lang="fi">G-code-tiedosto</comment>
+ <comment xml:lang="fr">fichier G-code</comment>
+ <comment xml:lang="ga">comhad G-code</comment>
+ <comment xml:lang="hr">G-kôd datoteka</comment>
+ <comment xml:lang="hu">G-code fájl</comment>
+ <comment xml:lang="id">berkas G-code</comment>
+ <comment xml:lang="it">File G-code</comment>
+ <comment xml:lang="kk">G-code файлы</comment>
+ <comment xml:lang="ko">지-코드 파ì¼</comment>
+ <comment xml:lang="pl">Plik G-code</comment>
+ <comment xml:lang="pt_BR">Arquivo G-code</comment>
+ <comment xml:lang="ru">Файл G-code</comment>
+ <comment xml:lang="sk">Súbor G-code</comment>
+ <comment xml:lang="sr">датотека Г-ко̂да</comment>
+ <comment xml:lang="sv">G-code-fil</comment>
+ <comment xml:lang="tr">G-code dosyası</comment>
+ <comment xml:lang="uk">файл G-code</comment>
+ <comment xml:lang="zh_CN">G-code 文件</comment>
+ <comment xml:lang="zh_TW">G-code 檔案</comment>
+ <sub-class-of type="text/plain"/>
+ <generic-icon name="text-x-generic"/>
+ <glob pattern="*.gcode"/>
+ </mime-type>
+
+ <mime-type type="application/x-fds-disk">
+ <comment>Nintendo FDS disk image</comment>
+ <comment xml:lang="ca">Imatge de disc Nintendo FDS</comment>
+ <comment xml:lang="cs">obraz disku pro Nintendo FDS</comment>
+ <comment xml:lang="de">Nintendo-FDS-Datenträgerabbild</comment>
+ <comment xml:lang="en_GB">Nintendo FDS disk image</comment>
+ <comment xml:lang="es">imagen de disco FDS de Nintendo</comment>
+ <comment xml:lang="eu">Nintendo FDS disko irudia</comment>
+ <comment xml:lang="fi">Nintendo FDS -levykuva</comment>
+ <comment xml:lang="fr">image disque Nintendo FDS</comment>
+ <comment xml:lang="ga">íomhá diosca Nintendo FDS</comment>
+ <comment xml:lang="hr">Nintendo FDS slika diska</comment>
+ <comment xml:lang="hu">Nintendo FDS lemezkép</comment>
+ <comment xml:lang="id">image disk Nintendo FDS</comment>
+ <comment xml:lang="it">Immagine disco Nintendo FDS</comment>
+ <comment xml:lang="kk">Nintendo FDS диÑк бейнеÑÑ–</comment>
+ <comment xml:lang="ko">ë‹Œí…ë„ FDS ë””ìŠ¤í¬ ì´ë¯¸ì§€</comment>
+ <comment xml:lang="pl">Obraz dysku Nintendo FDS</comment>
+ <comment xml:lang="pt_BR">Imagem de disco Nintendo FDS</comment>
+ <comment xml:lang="ru">Образ диÑка Nintendo FDS</comment>
+ <comment xml:lang="sk">Obraz disku Nintendo FDS</comment>
+ <comment xml:lang="sr">Ðинтендо ФДС Ñлика диÑка</comment>
+ <comment xml:lang="sv">Nintendo FDS-diskavbild</comment>
+ <comment xml:lang="tr">Nintendo FDS disk kalıbı</comment>
+ <comment xml:lang="uk">образ диÑка FDS Nintendo</comment>
+ <comment xml:lang="zh_CN">任天堂 FDS ç£ç›˜æ˜ åƒ</comment>
+ <comment xml:lang="zh_TW">Nintendo FDS ç£ç¢Ÿæ˜ åƒæª”</comment>
+ <acronym>FDS</acronym>
+ <expanded-acronym>Famicom Disk System</expanded-acronym>
+ <glob pattern="*.fds"/>
+ <magic>
+ <match value="*NINTENDO-HVC*" type="string" offset="1"/>
+ </magic>
+ </mime-type>
+
</mime-info>
diff --git a/src/corelib/mimetypes/mimetypes.pri b/src/corelib/mimetypes/mimetypes.pri
index 870b6c65a5..62bbe348e4 100644
--- a/src/corelib/mimetypes/mimetypes.pri
+++ b/src/corelib/mimetypes/mimetypes.pri
@@ -21,5 +21,5 @@ qtConfig(mimetype) {
mimetypes/qmimeglobpattern.cpp \
mimetypes/qmimeprovider.cpp
- RESOURCES += mimetypes/mimetypes.qrc
+ qtConfig(mimetype-database): RESOURCES += mimetypes/mimetypes.qrc
}
diff --git a/src/corelib/mimetypes/mimetypes.qrc b/src/corelib/mimetypes/mimetypes.qrc
index 19bc1d3e2a..4720bd302a 100644
--- a/src/corelib/mimetypes/mimetypes.qrc
+++ b/src/corelib/mimetypes/mimetypes.qrc
@@ -1,5 +1,5 @@
<RCC>
<qresource prefix="/qt-project.org/qmime/packages">
- <file alias="freedesktop.org.xml">mime/packages/freedesktop.org.xml</file>
+ <file alias="freedesktop.org.xml" compression-algorithm="best">mime/packages/freedesktop.org.xml</file>
</qresource>
</RCC>
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index bfe9be559a..24a7a35ea5 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -74,7 +74,6 @@ QMimeDatabasePrivate::QMimeDatabasePrivate()
QMimeDatabasePrivate::~QMimeDatabasePrivate()
{
- qDeleteAll(m_providers);
}
#ifdef QT_BUILD_INTERNAL
@@ -107,52 +106,52 @@ void QMimeDatabasePrivate::loadProviders()
mimeDirs.prepend(QLatin1String(":/qt-project.org/qmime"));
//qDebug() << "mime dirs:" << mimeDirs;
- QVector<QMimeProviderBase *> currentProviders = m_providers;
- m_providers.clear();
+ Providers currentProviders;
+ std::swap(m_providers, currentProviders);
m_providers.reserve(mimeDirs.size());
for (const QString &mimeDir : qAsConst(mimeDirs)) {
const QString cacheFile = mimeDir + QStringLiteral("/mime.cache");
QFileInfo fileInfo(cacheFile);
// Check if we already have a provider for this dir
- const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), [mimeDir](QMimeProviderBase *prov) { return prov->directory() == mimeDir; });
+ const auto predicate = [mimeDir](const std::unique_ptr<QMimeProviderBase> &prov)
+ {
+ return prov && prov->directory() == mimeDir;
+ };
+ const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), predicate);
if (it == currentProviders.end()) {
- QMimeProviderBase *provider = nullptr;
+ std::unique_ptr<QMimeProviderBase> provider;
#if defined(QT_USE_MMAP)
if (qEnvironmentVariableIsEmpty("QT_NO_MIME_CACHE") && fileInfo.exists()) {
- provider = new QMimeBinaryProvider(this, mimeDir);
+ provider.reset(new QMimeBinaryProvider(this, mimeDir));
//qDebug() << "Created binary provider for" << mimeDir;
if (!provider->isValid()) {
- delete provider;
- provider = nullptr;
+ provider.reset();
}
}
#endif
if (!provider) {
- provider = new QMimeXMLProvider(this, mimeDir);
+ provider.reset(new QMimeXMLProvider(this, mimeDir));
//qDebug() << "Created XML provider for" << mimeDir;
}
- m_providers.append(provider);
+ m_providers.push_back(std::move(provider));
} else {
- QMimeProviderBase *provider = *it;
- currentProviders.erase(it);
+ auto provider = std::move(*it); // take provider out of the vector
provider->ensureLoaded();
if (!provider->isValid()) {
- delete provider;
- provider = new QMimeXMLProvider(this, mimeDir);
+ provider.reset(new QMimeXMLProvider(this, mimeDir));
//qDebug() << "Created XML provider to replace binary provider for" << mimeDir;
}
- m_providers.append(provider);
+ m_providers.push_back(std::move(provider));
}
}
- qDeleteAll(currentProviders);
}
-QVector<QMimeProviderBase *> QMimeDatabasePrivate::providers()
+const QMimeDatabasePrivate::Providers &QMimeDatabasePrivate::providers()
{
#ifndef Q_OS_WASM // stub implementation always returns true
Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex
#endif
- if (m_providers.isEmpty()) {
+ if (m_providers.empty()) {
loadProviders();
m_lastCheck.start();
} else {
@@ -164,8 +163,7 @@ QVector<QMimeProviderBase *> QMimeDatabasePrivate::providers()
QString QMimeDatabasePrivate::resolveAlias(const QString &nameOrAlias)
{
- const auto allProviders = providers();
- for (QMimeProviderBase *provider : allProviders) {
+ for (const auto &provider : providers()) {
const QString ret = provider->resolveAlias(nameOrAlias);
if (!ret.isEmpty())
return ret;
@@ -179,9 +177,8 @@ QString QMimeDatabasePrivate::resolveAlias(const QString &nameOrAlias)
*/
QMimeType QMimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias)
{
- const auto allProviders = providers();
const QString mimeName = resolveAlias(nameOrAlias);
- for (QMimeProviderBase *provider : allProviders) {
+ for (const auto &provider : providers()) {
const QMimeType mime = provider->mimeTypeForName(mimeName);
if (mime.isValid())
return mime;
@@ -205,8 +202,7 @@ QMimeGlobMatchResult QMimeDatabasePrivate::findByFileName(const QString &fileNam
{
QMimeGlobMatchResult result;
// TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly.
- const auto allProviders = providers();
- for (QMimeProviderBase *provider : allProviders)
+ for (const auto &provider : providers())
provider->addFileNameMatches(fileName, result);
return result;
}
@@ -227,8 +223,7 @@ void QMimeDatabasePrivate::loadGenericIcon(QMimeTypePrivate &mimePrivate)
QMutexLocker locker(&mutex);
if (mimePrivate.fromCache) {
mimePrivate.genericIconName.clear();
- const auto allProviders = providers();
- for (QMimeProviderBase *provider : allProviders) {
+ for (const auto &provider : providers()) {
provider->loadGenericIcon(mimePrivate);
if (!mimePrivate.genericIconName.isEmpty())
break;
@@ -241,8 +236,7 @@ void QMimeDatabasePrivate::loadIcon(QMimeTypePrivate &mimePrivate)
QMutexLocker locker(&mutex);
if (mimePrivate.fromCache) {
mimePrivate.iconName.clear();
- const auto allProviders = providers();
- for (QMimeProviderBase *provider : allProviders) {
+ for (const auto &provider : providers()) {
provider->loadIcon(mimePrivate);
if (!mimePrivate.iconName.isEmpty())
break;
@@ -276,8 +270,7 @@ QStringList QMimeDatabasePrivate::parents(const QString &mimeName)
{
Q_ASSERT(!mutex.tryLock());
QStringList result;
- const auto allProviders = providers();
- for (QMimeProviderBase *provider : allProviders)
+ for (const auto &provider : providers())
provider->addParents(mimeName, result);
if (result.isEmpty()) {
const QString parent = fallbackParent(mimeName);
@@ -291,8 +284,7 @@ QStringList QMimeDatabasePrivate::listAliases(const QString &mimeName)
{
QMutexLocker locker(&mutex);
QStringList result;
- const auto allProviders = providers();
- for (QMimeProviderBase *provider : allProviders)
+ for (const auto &provider : providers())
provider->addAliases(mimeName, result);
return result;
}
@@ -331,8 +323,7 @@ QMimeType QMimeDatabasePrivate::findByData(const QByteArray &data, int *accuracy
*accuracyPtr = 0;
QMimeType candidate;
- const auto allProviders = providers();
- for (QMimeProviderBase *provider : allProviders)
+ for (const auto &provider : providers())
provider->findByMagic(data, accuracyPtr, candidate);
if (candidate.isValid())
@@ -414,8 +405,7 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
QList<QMimeType> QMimeDatabasePrivate::allMimeTypes()
{
QList<QMimeType> result;
- const auto allProviders = providers();
- for (QMimeProviderBase *provider : allProviders)
+ for (const auto &provider : providers())
provider->addAllMimeTypes(result);
return result;
}
@@ -432,7 +422,7 @@ bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
toCheck.pop();
const auto parentList = parents(mimeName);
for (const QString &par : parentList)
- toCheck.push(par);
+ toCheck.push(resolveAlias(par));
}
return false;
}
diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h
index 1e605d9a24..d9cf446d44 100644
--- a/src/corelib/mimetypes/qmimedatabase_p.h
+++ b/src/corelib/mimetypes/qmimedatabase_p.h
@@ -63,6 +63,8 @@ QT_REQUIRE_CONFIG(mimetype);
#include <QtCore/qmutex.h>
#include <QtCore/qvector.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QIODevice;
@@ -72,7 +74,7 @@ class QMimeProviderBase;
class QMimeDatabasePrivate
{
public:
- Q_DISABLE_COPY(QMimeDatabasePrivate)
+ Q_DISABLE_COPY_MOVE(QMimeDatabasePrivate)
QMimeDatabasePrivate();
~QMimeDatabasePrivate();
@@ -102,11 +104,12 @@ public:
bool mimeInherits(const QString &mime, const QString &parent);
private:
- QVector<QMimeProviderBase *> providers();
+ using Providers = std::vector<std::unique_ptr<QMimeProviderBase>>;
+ const Providers &providers();
bool shouldCheck();
void loadProviders();
- mutable QVector<QMimeProviderBase *> m_providers;
+ mutable Providers m_providers;
QElapsedTimer m_lastCheck;
public:
diff --git a/src/corelib/mimetypes/qmimeglobpattern.cpp b/src/corelib/mimetypes/qmimeglobpattern.cpp
index cd42b4da83..ad78cd9ffa 100644
--- a/src/corelib/mimetypes/qmimeglobpattern.cpp
+++ b/src/corelib/mimetypes/qmimeglobpattern.cpp
@@ -39,7 +39,9 @@
#include "qmimeglobpattern_p.h"
-#include <QRegExp>
+#if QT_CONFIG(regularexpression)
+#include <QRegularExpression>
+#endif
#include <QStringList>
#include <QDebug>
@@ -142,8 +144,12 @@ bool QMimeGlobPattern::matchFileName(const QString &inputFilename) const
return (m_pattern == filename);
// Other (quite rare) patterns, like "*.anim[1-9j]": use slow but correct method
- QRegExp rx(m_pattern, Qt::CaseSensitive, QRegExp::WildcardUnix);
- return rx.exactMatch(filename);
+#if QT_CONFIG(regularexpression)
+ QRegularExpression rx(QRegularExpression::wildcardToRegularExpression(m_pattern));
+ return rx.match(filename).hasMatch();
+#else
+ return false;
+#endif
}
static bool isFastPattern(const QString &pattern)
diff --git a/src/corelib/mimetypes/qmimeglobpattern_p.h b/src/corelib/mimetypes/qmimeglobpattern_p.h
index bb6f64320b..cf27d6ab30 100644
--- a/src/corelib/mimetypes/qmimeglobpattern_p.h
+++ b/src/corelib/mimetypes/qmimeglobpattern_p.h
@@ -88,7 +88,7 @@ public:
{
}
- void swap(QMimeGlobPattern &other) Q_DECL_NOTHROW
+ void swap(QMimeGlobPattern &other) noexcept
{
qSwap(m_pattern, other.m_pattern);
qSwap(m_mimeType, other.m_mimeType);
diff --git a/src/corelib/mimetypes/qmimemagicrule_p.h b/src/corelib/mimetypes/qmimemagicrule_p.h
index 6962a6ca59..5091d483b6 100644
--- a/src/corelib/mimetypes/qmimemagicrule_p.h
+++ b/src/corelib/mimetypes/qmimemagicrule_p.h
@@ -69,7 +69,7 @@ public:
QMimeMagicRule(const QString &typeStr, const QByteArray &value, const QString &offsets,
const QByteArray &mask, QString *errorString);
- void swap(QMimeMagicRule &other) Q_DECL_NOTHROW
+ void swap(QMimeMagicRule &other) noexcept
{
qSwap(m_type, other.m_type);
qSwap(m_value, other.m_value);
diff --git a/src/corelib/mimetypes/qmimemagicrulematcher_p.h b/src/corelib/mimetypes/qmimemagicrulematcher_p.h
index 5e74e2e3fc..fe714987e6 100644
--- a/src/corelib/mimetypes/qmimemagicrulematcher_p.h
+++ b/src/corelib/mimetypes/qmimemagicrulematcher_p.h
@@ -66,7 +66,7 @@ class QMimeMagicRuleMatcher
public:
explicit QMimeMagicRuleMatcher(const QString &mime, unsigned priority = 65535);
- void swap(QMimeMagicRuleMatcher &other) Q_DECL_NOTHROW
+ void swap(QMimeMagicRuleMatcher &other) noexcept
{
qSwap(m_list, other.m_list);
qSwap(m_priority, other.m_priority);
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index aac51184a4..a3a6b9615c 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -54,7 +54,9 @@
static void initResources()
{
+#if QT_CONFIG(mimetype_database)
Q_INIT_RESOURCE(mimetypes);
+#endif
}
QT_BEGIN_NAMESPACE
@@ -445,10 +447,10 @@ void QMimeBinaryProvider::addAllMimeTypes(QList<QMimeType> &result)
loadMimeTypeList();
if (result.isEmpty()) {
result.reserve(m_mimetypeNames.count());
- for (const QString &name : m_mimetypeNames)
+ for (const QString &name : qAsConst(m_mimetypeNames))
result.append(mimeTypeForNameUnchecked(name));
} else {
- for (const QString &name : m_mimetypeNames)
+ for (const QString &name : qAsConst(m_mimetypeNames))
if (std::find_if(result.constBegin(), result.constEnd(), [name](const QMimeType &mime) -> bool { return mime.name() == name; })
== result.constEnd())
result.append(mimeTypeForNameUnchecked(name));
@@ -458,6 +460,7 @@ void QMimeBinaryProvider::addAllMimeTypes(QList<QMimeType> &result)
void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
{
#ifdef QT_NO_XMLSTREAMREADER
+ Q_UNUSED(data);
qWarning("Cannot load mime type since QXmlStreamReader is not available.");
return;
#else
@@ -670,7 +673,7 @@ void QMimeXMLProvider::load(const QString &fileName)
{
QString errorMessage;
if (!load(fileName, &errorMessage))
- qWarning("QMimeDatabase: Error loading %s\n%s", qPrintable(fileName), qPrintable(errorMessage));
+ qWarning("QMimeDatabase: Error loading %ls\n%ls", qUtf16Printable(fileName), qUtf16Printable(errorMessage));
}
bool QMimeXMLProvider::load(const QString &fileName, QString *errorMessage)
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index 875ff9e0eb..b6268210c0 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -97,17 +97,17 @@ public:
QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory);
virtual ~QMimeBinaryProvider();
- virtual bool isValid() override;
- virtual QMimeType mimeTypeForName(const QString &name) override;
+ bool isValid() override;
+ QMimeType mimeTypeForName(const QString &name) override;
void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override;
void addParents(const QString &mime, QStringList &result) override;
- virtual QString resolveAlias(const QString &name) override;
+ QString resolveAlias(const QString &name) override;
void addAliases(const QString &name, QStringList &result) override;
void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override;
void addAllMimeTypes(QList<QMimeType> &result) override;
static void loadMimeTypePrivate(QMimeTypePrivate &);
- virtual void loadIcon(QMimeTypePrivate &) override;
- virtual void loadGenericIcon(QMimeTypePrivate &) override;
+ void loadIcon(QMimeTypePrivate &) override;
+ void loadGenericIcon(QMimeTypePrivate &) override;
void ensureLoaded() override;
private:
@@ -135,11 +135,11 @@ public:
QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory);
~QMimeXMLProvider();
- virtual bool isValid() override;
- virtual QMimeType mimeTypeForName(const QString &name) override;
+ bool isValid() override;
+ QMimeType mimeTypeForName(const QString &name) override;
void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override;
void addParents(const QString &mime, QStringList &result) override;
- virtual QString resolveAlias(const QString &name) override;
+ QString resolveAlias(const QString &name) override;
void addAliases(const QString &name, QStringList &result) override;
void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override;
void addAllMimeTypes(QList<QMimeType> &result) override;
diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp
index 55c7de0c87..de450c68f4 100644
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -192,7 +192,7 @@ bool QMimeType::operator==(const QMimeType &other) const
Returns the hash value for \a key, using
\a seed to seed the calculation.
*/
-uint qHash(const QMimeType &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QMimeType &key, uint seed) noexcept
{
return qHash(key.d->name, seed);
}
@@ -253,7 +253,7 @@ QString QMimeType::name() const
*/
QString QMimeType::comment() const
{
- QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d);
+ QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
QStringList languageList;
languageList << QLocale().name();
@@ -294,7 +294,7 @@ QString QMimeType::comment() const
*/
QString QMimeType::genericIconName() const
{
- QMimeDatabasePrivate::instance()->loadGenericIcon(*d);
+ QMimeDatabasePrivate::instance()->loadGenericIcon(const_cast<QMimeTypePrivate&>(*d));
if (d->genericIconName.isEmpty()) {
// From the spec:
// If the generic icon name is empty (not specified by the mimetype definition)
@@ -311,6 +311,14 @@ QString QMimeType::genericIconName() const
return d->genericIconName;
}
+static QString make_default_icon_name_from_mimetype_name(QString iconName)
+{
+ const int slashindex = iconName.indexOf(QLatin1Char('/'));
+ if (slashindex != -1)
+ iconName[slashindex] = QLatin1Char('-');
+ return iconName;
+}
+
/*!
\property QMimeType::iconName
\brief the file name of an icon image that represents the MIME type
@@ -322,13 +330,9 @@ QString QMimeType::genericIconName() const
*/
QString QMimeType::iconName() const
{
- QMimeDatabasePrivate::instance()->loadIcon(*d);
+ QMimeDatabasePrivate::instance()->loadIcon(const_cast<QMimeTypePrivate&>(*d));
if (d->iconName.isEmpty()) {
- // Make default icon name from the mimetype name
- d->iconName = name();
- const int slashindex = d->iconName.indexOf(QLatin1Char('/'));
- if (slashindex != -1)
- d->iconName[slashindex] = QLatin1Char('-');
+ return make_default_icon_name_from_mimetype_name(name());
}
return d->iconName;
}
@@ -342,7 +346,7 @@ QString QMimeType::iconName() const
*/
QStringList QMimeType::globPatterns() const
{
- QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d);
+ QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
return d->globPatterns;
}
@@ -437,7 +441,7 @@ QStringList QMimeType::aliases() const
*/
QStringList QMimeType::suffixes() const
{
- QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d);
+ QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
QStringList result;
for (const QString &pattern : qAsConst(d->globPatterns)) {
@@ -480,7 +484,7 @@ QString QMimeType::preferredSuffix() const
*/
QString QMimeType::filterString() const
{
- QMimeDatabasePrivate::instance()->loadMimeTypePrivate(*d);
+ QMimeDatabasePrivate::instance()->loadMimeTypePrivate(const_cast<QMimeTypePrivate&>(*d));
QString filter;
if (!d->globPatterns.empty()) {
diff --git a/src/corelib/mimetypes/qmimetype.h b/src/corelib/mimetypes/qmimetype.h
index 8287f1434b..df1b60f2ce 100644
--- a/src/corelib/mimetypes/qmimetype.h
+++ b/src/corelib/mimetypes/qmimetype.h
@@ -48,14 +48,14 @@ QT_REQUIRE_CONFIG(mimetype);
#include <QtCore/qobjectdefs.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
class QMimeTypePrivate;
-class QStringList;
class QMimeType;
-Q_CORE_EXPORT uint qHash(const QMimeType &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT uint qHash(const QMimeType &key, uint seed = 0) noexcept;
class Q_CORE_EXPORT QMimeType
{
@@ -78,10 +78,8 @@ public:
QMimeType();
QMimeType(const QMimeType &other);
QMimeType &operator=(const QMimeType &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QMimeType &operator=(QMimeType &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
- void swap(QMimeType &other) Q_DECL_NOTHROW
+ QMimeType &operator=(QMimeType &&other) noexcept { swap(other); return *this; }
+ void swap(QMimeType &other) noexcept
{
qSwap(d, other.d);
}
@@ -121,7 +119,7 @@ protected:
friend class QMimeXMLProvider;
friend class QMimeBinaryProvider;
friend class QMimeTypePrivate;
- friend Q_CORE_EXPORT uint qHash(const QMimeType &key, uint seed) Q_DECL_NOTHROW;
+ friend Q_CORE_EXPORT uint qHash(const QMimeType &key, uint seed) noexcept;
QExplicitlySharedDataPointer<QMimeTypePrivate> d;
};
diff --git a/src/corelib/mimetypes/qmimetype_p.h b/src/corelib/mimetypes/qmimetype_p.h
index 5a36e6613c..0d6b4b4b12 100644
--- a/src/corelib/mimetypes/qmimetype_p.h
+++ b/src/corelib/mimetypes/qmimetype_p.h
@@ -84,26 +84,6 @@ public:
QT_END_NAMESPACE
-#define QMIMETYPE_BUILDER \
- QT_BEGIN_NAMESPACE \
- static QMimeType buildQMimeType ( \
- const QString &name, \
- const QString &genericIconName, \
- const QString &iconName, \
- const QStringList &globPatterns \
- ) \
- { \
- QMimeTypePrivate qMimeTypeData; \
- qMimeTypeData.name = name; \
- qMimeTypeData.loaded = true; \
- qMimeTypeData.genericIconName = genericIconName; \
- qMimeTypeData.iconName = iconName; \
- qMimeTypeData.globPatterns = globPatterns; \
- return QMimeType(qMimeTypeData); \
- } \
- QT_END_NAMESPACE
-
-#ifdef Q_COMPILER_RVALUE_REFS
#define QMIMETYPE_BUILDER_FROM_RVALUE_REFS \
QT_BEGIN_NAMESPACE \
static QMimeType buildQMimeType ( \
@@ -122,6 +102,5 @@ QT_END_NAMESPACE
return QMimeType(qMimeTypeData); \
} \
QT_END_NAMESPACE
-#endif
#endif // QMIMETYPE_P_H
diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp
index d10575cfe9..815e0aa03b 100644
--- a/src/corelib/mimetypes/qmimetypeparser.cpp
+++ b/src/corelib/mimetypes/qmimetypeparser.cpp
@@ -194,8 +194,9 @@ static CreateMagicMatchRuleResult createMagicMatchRule(const QXmlStreamAttribute
bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString *errorMessage)
{
#ifdef QT_NO_XMLSTREAMREADER
+ Q_UNUSED(dev);
if (errorMessage)
- *errorMessage = QString::fromLatin1("QXmlStreamReader is not available, cannot parse.");
+ *errorMessage = QString::fromLatin1("QXmlStreamReader is not available, cannot parse '%1'.").arg(fileName);
return false;
#else
QMimeTypePrivate data;
diff --git a/src/corelib/mimetypes/qmimetypeparser_p.h b/src/corelib/mimetypes/qmimetypeparser_p.h
index 6e3f5fd556..d6a1444592 100644
--- a/src/corelib/mimetypes/qmimetypeparser_p.h
+++ b/src/corelib/mimetypes/qmimetypeparser_p.h
@@ -64,7 +64,7 @@ class QIODevice;
class QMimeTypeParserBase
{
- Q_DISABLE_COPY(QMimeTypeParserBase)
+ Q_DISABLE_COPY_MOVE(QMimeTypeParserBase)
public:
QMimeTypeParserBase() {}
diff --git a/src/corelib/platform/platform.pri b/src/corelib/platform/platform.pri
new file mode 100644
index 0000000000..1fe2db81b0
--- /dev/null
+++ b/src/corelib/platform/platform.pri
@@ -0,0 +1 @@
+wasm:include(wasm/wasm.pri)
diff --git a/src/corelib/platform/wasm/qstdweb.cpp b/src/corelib/platform/wasm/qstdweb.cpp
new file mode 100644
index 0000000000..198ce897ca
--- /dev/null
+++ b/src/corelib/platform/wasm/qstdweb.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstdweb_p.h"
+
+#include <emscripten/bind.h>
+#include <cstdint>
+#include <iostream>
+
+QT_BEGIN_NAMESPACE
+
+namespace qstdweb {
+
+typedef double uint53_t; // see Number.MAX_SAFE_INTEGER
+
+ArrayBuffer::ArrayBuffer(const emscripten::val &arrayBuffer)
+ :m_arrayBuffer(arrayBuffer)
+{
+
+}
+
+uint32_t ArrayBuffer::byteLength() const
+{
+ if (m_arrayBuffer.isUndefined() || m_arrayBuffer.isNull())
+ return 0;
+
+ return m_arrayBuffer["byteLength"].as<uint32_t>();
+}
+
+Blob::Blob(const emscripten::val &blob)
+ :m_blob(blob)
+{
+
+}
+
+uint32_t Blob::size() const
+{
+ return m_blob["size"].as<uint32_t>();
+}
+
+File::File(const emscripten::val &file)
+:m_file(file)
+{
+
+}
+
+Blob File::slice(uint64_t begin, uint64_t end) const
+{
+ return Blob(m_file.call<emscripten::val>("slice", uint53_t(begin), uint53_t(end)));
+}
+
+std::string File::name() const
+{
+ return m_file["name"].as<std::string>();
+}
+
+uint64_t File::size() const
+{
+ return uint64_t(m_file["size"].as<uint53_t>());
+}
+
+FileList::FileList(const emscripten::val &fileList)
+ :m_fileList(fileList)
+{
+
+}
+
+int FileList::length() const
+{
+ return m_fileList["length"].as<int>();
+}
+
+File FileList::item(int index) const
+{
+ return File(m_fileList[index]);
+}
+
+File FileList::operator[](int index) const
+{
+ return item(index);
+}
+
+ArrayBuffer FileReader::result() const
+{
+ return ArrayBuffer(m_fileReader["result"]);
+}
+
+void FileReader::readAsArrayBuffer(const Blob &blob) const
+{
+ m_fileReader.call<void>("readAsArrayBuffer", blob.m_blob);
+}
+
+void FileReader::onLoad(const std::function<void ()> &onLoad)
+{
+ m_onLoad.reset(new EventCallback(m_fileReader, "load", onLoad));
+}
+
+void FileReader::onError(const std::function<void ()> &onError)
+{
+ m_onError.reset(new EventCallback(m_fileReader, "error", onError));
+}
+
+void FileReader::onAbort(const std::function<void ()> &onAbort)
+{
+ m_onAbort.reset(new EventCallback(m_fileReader, "abort", onAbort));
+}
+
+Uint8Array Uint8Array::heap()
+{
+ return Uint8Array(heap_());
+}
+
+Uint8Array::Uint8Array(const emscripten::val &uint8Array)
+: m_uint8Array(uint8Array)
+{
+
+}
+
+Uint8Array::Uint8Array(const ArrayBuffer &buffer)
+: m_uint8Array(Uint8Array::constructor_().new_(buffer.m_arrayBuffer))
+{
+
+}
+
+Uint8Array::Uint8Array(const ArrayBuffer &buffer, uint32_t offset, uint32_t length)
+: m_uint8Array(Uint8Array::constructor_().new_(buffer.m_arrayBuffer, offset, length))
+{
+
+}
+
+Uint8Array::Uint8Array(char *buffer, uint32_t size)
+:m_uint8Array(Uint8Array::constructor_().new_(Uint8Array::heap().buffer().m_arrayBuffer, uint32_t(buffer), size))
+{
+
+}
+
+ArrayBuffer Uint8Array::buffer() const
+{
+ return ArrayBuffer(m_uint8Array["buffer"]);
+}
+
+uint32_t Uint8Array::length() const
+{
+ return m_uint8Array["length"].as<uint32_t>();
+}
+
+void Uint8Array::set(const Uint8Array &source)
+{
+ m_uint8Array.call<void>("set", source.m_uint8Array); // copies source content
+}
+
+void Uint8Array::copyTo(char *destination) const
+{
+ Uint8Array(destination, length()).set(*this);
+}
+
+void Uint8Array::copy(char *destination, const Uint8Array &source)
+{
+ Uint8Array(destination, source.length()).set(source);
+}
+
+emscripten::val Uint8Array::heap_()
+{
+ return emscripten::val::module_property("HEAPU8");
+}
+
+emscripten::val Uint8Array::constructor_()
+{
+ return emscripten::val::global("Uint8Array");
+}
+
+// Registers a callback function for a named event on the given element. The event
+// name must be the name as returned by the Event.type property: e.g. "load", "error".
+EventCallback::EventCallback(emscripten::val element, const std::string &name, const std::function<void ()> &fn)
+:m_fn(fn)
+{
+ element.set(contextPropertyName(name).c_str(), emscripten::val(intptr_t(this)));
+ element.set((std::string("on") + name).c_str(), emscripten::val::module_property("qtStdWebEventCallbackActivate"));
+}
+
+void EventCallback::activate(emscripten::val event)
+{
+ emscripten::val target = event["target"];
+ std::string eventName = event["type"].as<std::string>();
+ EventCallback *that = reinterpret_cast<EventCallback *>(target[contextPropertyName(eventName).c_str()].as<intptr_t>());
+ that->m_fn();
+}
+
+std::string EventCallback::contextPropertyName(const std::string &eventName)
+{
+ return std::string("data-qtEventCallbackContext") + eventName;
+}
+
+EMSCRIPTEN_BINDINGS(qtStdwebCalback) {
+ emscripten::function("qtStdWebEventCallbackActivate", &EventCallback::activate);
+}
+
+} // namespace qstdweb
+
+QT_END_NAMESPACE
diff --git a/src/corelib/platform/wasm/qstdweb_p.h b/src/corelib/platform/wasm/qstdweb_p.h
new file mode 100644
index 0000000000..75c2ec34b1
--- /dev/null
+++ b/src/corelib/platform/wasm/qstdweb_p.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTDWEB_P_H
+#define QSTDWEB_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qglobal.h>
+#include <emscripten/val.h>
+#include <cstdint>
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+namespace qstdweb {
+
+ // DOM API in C++, implemented using emscripten val.h and bind.h.
+ // This is private API and can be extened and changed as needed.
+
+ class ArrayBuffer;
+ class Blob;
+ class File;
+ class FileList;
+ class FileReader;
+ class Uint8Array;
+ class EventCallback;
+
+ class ArrayBuffer {
+ public:
+ explicit ArrayBuffer(const emscripten::val &arrayBuffer);
+ uint32_t byteLength() const;
+
+ private:
+ friend class Uint8Array;
+ emscripten::val m_arrayBuffer = emscripten::val::undefined();
+ };
+
+ class Blob {
+ public:
+ explicit Blob(const emscripten::val &blob);
+ uint32_t size() const;
+
+ private:
+ friend class FileReader;
+ emscripten::val m_blob = emscripten::val::undefined();
+ };
+
+ class File {
+ public:
+ File() = default;
+ explicit File(const emscripten::val &file);
+
+ Blob slice(uint64_t begin, uint64_t end) const;
+ std::string name() const;
+ uint64_t size() const;
+
+ private:
+ emscripten::val m_file = emscripten::val::undefined();
+ };
+
+ class FileList {
+ public:
+ FileList() = default;
+ explicit FileList(const emscripten::val &fileList);
+
+ int length() const;
+ File item(int index) const;
+ File operator[](int index) const;
+
+ private:
+ emscripten::val m_fileList = emscripten::val::undefined();
+ };
+
+ class FileReader {
+ public:
+ ArrayBuffer result() const;
+ void readAsArrayBuffer(const Blob &blob) const;
+
+ void onLoad(const std::function<void ()> &onLoad);
+ void onError(const std::function<void ()> &onError);
+ void onAbort(const std::function<void ()> &onAbort);
+
+ private:
+ emscripten::val m_fileReader = emscripten::val::global("FileReader").new_();
+ std::unique_ptr<EventCallback> m_onLoad;
+ std::unique_ptr<EventCallback> m_onError;
+ std::unique_ptr<EventCallback> m_onAbort;
+ };
+
+ class Uint8Array {
+ public:
+ static Uint8Array heap();
+ explicit Uint8Array(const emscripten::val &uint8Array);
+ explicit Uint8Array(const ArrayBuffer &buffer);
+ Uint8Array(const ArrayBuffer &buffer, uint32_t offset, uint32_t length);
+ Uint8Array(char *buffer, uint32_t size);
+
+ ArrayBuffer buffer() const;
+ uint32_t length() const;
+ void set(const Uint8Array &source);
+
+ void copyTo(char *destination) const;
+ static void copy(char *destination, const Uint8Array &source);
+ private:
+ static emscripten::val heap_();
+ static emscripten::val constructor_();
+ emscripten::val m_uint8Array = emscripten::val::undefined();
+ };
+
+ class EventCallback
+ {
+ public:
+ EventCallback(emscripten::val element, const std::string &name, const std::function<void ()> &fn);
+ static void activate(emscripten::val event);
+ private:
+ static std::string contextPropertyName(const std::string &eventName);
+ std::function<void ()> m_fn;
+ };
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/platform/wasm/wasm.pri b/src/corelib/platform/wasm/wasm.pri
new file mode 100644
index 0000000000..73447030fb
--- /dev/null
+++ b/src/corelib/platform/wasm/wasm.pri
@@ -0,0 +1,3 @@
+INCLUDEDIR += $$PWD
+HEADERS += $$PWD/qstdweb_p.h
+SOURCES += $$PWD/qstdweb.cpp
diff --git a/src/corelib/plugin/qfactoryinterface.h b/src/corelib/plugin/qfactoryinterface.h
index f306460690..3aec4ddd55 100644
--- a/src/corelib/plugin/qfactoryinterface.h
+++ b/src/corelib/plugin/qfactoryinterface.h
@@ -52,8 +52,9 @@ struct Q_CORE_EXPORT QFactoryInterface
virtual QStringList keys() const = 0;
};
-
+#ifndef Q_CLANG_QDOC
Q_DECLARE_INTERFACE(QFactoryInterface, "org.qt-project.Qt.QFactoryInterface")
+#endif
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 35c64180d4..8e349f23ce 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -239,7 +239,7 @@ void QFactoryLoader::update()
library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
if (!library->isPlugin()) {
if (qt_debug_component()) {
- qDebug() << library->errorString << endl
+ qDebug() << library->errorString << Qt::endl
<< " not a plugin";
}
library->release();
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 29ef697fe8..1ace28c93f 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE
# define QLIBRARY_AS_DEBUG true
#endif
-#if defined(Q_OS_UNIX)
+#if defined(Q_OS_UNIX) || defined(Q_CC_MINGW)
// We don't use separate debug and release libs on UNIX, so we want
// to allow loading plugins, regardless of how they were built.
# define QT_NO_DEBUG_PLUGIN_CHECK
@@ -133,8 +133,8 @@ QT_BEGIN_NAMESPACE
The following code snippet loads a library, resolves the symbol
"mysymbol", and calls the function if everything succeeded. If
something goes wrong, e.g. the library file does not exist or the
- symbol is not defined, the function pointer will be 0 and won't be
- called.
+ symbol is not defined, the function pointer will be \nullptr and
+ won't be called.
\snippet code/src_corelib_plugin_qlibrary.cpp 0
@@ -241,8 +241,8 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
if (lib)
lib->errorString = file.errorString();
if (qt_debug_component()) {
- qWarning("%s: %s", QFile::encodeName(library).constData(),
- qPrintable(QSystemError::stdString()));
+ qWarning("%s: %ls", QFile::encodeName(library).constData(),
+ qUtf16Printable(QSystemError::stdString()));
}
return false;
}
@@ -275,7 +275,7 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen);
if (r == QElfParser::Corrupt || r == QElfParser::NotElf) {
if (lib && qt_debug_component()) {
- qWarning("QElfParser: %s",qPrintable(lib->errorString));
+ qWarning("QElfParser: %ls", qUtf16Printable(lib->errorString));
}
return false;
} else if (r == QElfParser::QtMetaDataSection) {
@@ -292,7 +292,7 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
int r = QMachOParser::parse(filedata, fdlen, library, &errorString, &pos, &fdlen);
if (r == QMachOParser::NotSuitable) {
if (qt_debug_component())
- qWarning("QMachOParser: %s", qPrintable(errorString));
+ qWarning("QMachOParser: %ls", qUtf16Printable(errorString));
if (lib)
lib->errorString = errorString;
return false;
@@ -319,8 +319,8 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
QString errMsg;
QJsonDocument doc = qJsonFromRawLibraryMetaData(data, fdlen, &errMsg);
if (doc.isNull()) {
- qWarning("Found invalid metadata in lib %s: %s",
- qPrintable(library), qPrintable(errMsg));
+ qWarning("Found invalid metadata in lib %ls: %ls",
+ qUtf16Printable(library), qUtf16Printable(errMsg));
} else {
lib->metaData = doc.object();
if (qt_debug_component())
@@ -356,11 +356,11 @@ static void installCoverageTool(QLibraryPrivate *libPrivate)
if (qt_debug_component()) {
if (ret >= 0) {
- qDebug("coverage data for %s registered",
- qPrintable(libPrivate->fileName));
+ qDebug("coverage data for %ls registered",
+ qUtf16Printable(libPrivate->fileName));
} else {
- qWarning("could not register %s: error %d; coverage data may be incomplete",
- qPrintable(libPrivate->fileName),
+ qWarning("could not register %ls: error %d; coverage data may be incomplete",
+ qUtf16Printable(libPrivate->fileName),
ret);
}
}
@@ -405,10 +405,10 @@ inline void QLibraryStore::cleanup()
LibraryMap::Iterator it = data->libraryMap.begin();
for (; it != data->libraryMap.end(); ++it) {
QLibraryPrivate *lib = it.value();
- if (lib->libraryRefCount.load() == 1) {
- if (lib->libraryUnloadCount.load() > 0) {
+ if (lib->libraryRefCount.loadRelaxed() == 1) {
+ if (lib->libraryUnloadCount.loadRelaxed() > 0) {
Q_ASSERT(lib->pHnd);
- lib->libraryUnloadCount.store(1);
+ lib->libraryUnloadCount.storeRelaxed(1);
#ifdef __GLIBC__
// glibc has a bug in unloading from global destructors
// see https://bugzilla.novell.com/show_bug.cgi?id=622977
@@ -428,7 +428,7 @@ inline void QLibraryStore::cleanup()
for (QLibraryPrivate *lib : qAsConst(data->libraryMap)) {
if (lib)
qDebug() << "On QtCore unload," << lib->fileName << "was leaked, with"
- << lib->libraryRefCount.load() << "users";
+ << lib->libraryRefCount.loadRelaxed() << "users";
}
}
@@ -487,7 +487,7 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
}
// no one else is using
- Q_ASSERT(lib->libraryUnloadCount.load() == 0);
+ Q_ASSERT(lib->libraryUnloadCount.loadRelaxed() == 0);
if (Q_LIKELY(data) && !lib->fileName.isEmpty()) {
QLibraryPrivate *that = data->libraryMap.take(lib->fileName);
@@ -501,7 +501,7 @@ QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString
: pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0),
libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
{
- loadHintsInt.store(loadHints);
+ loadHintsInt.storeRelaxed(loadHints);
if (canonicalFileName.isEmpty())
errorString = QLibrary::tr("The shared library was not found.");
}
@@ -522,7 +522,7 @@ void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
if (pHnd)
return;
- loadHintsInt.store(lh);
+ loadHintsInt.storeRelaxed(lh);
}
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
@@ -575,7 +575,7 @@ bool QLibraryPrivate::unload(UnloadFlag flag)
{
if (!pHnd)
return false;
- if (libraryUnloadCount.load() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
+ if (libraryUnloadCount.loadRelaxed() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
delete inst.data();
if (flag == NoUnloadSys || unload_sys()) {
if (qt_debug_component())
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
index 3f650501c8..db5afac98e 100644
--- a/src/corelib/plugin/qlibrary_p.h
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -92,11 +92,11 @@ public:
QFunctionPointer resolve(const char *);
QLibrary::LoadHints loadHints() const
- { return QLibrary::LoadHints(loadHintsInt.load()); }
+ { return QLibrary::LoadHints(loadHintsInt.loadRelaxed()); }
void setLoadHints(QLibrary::LoadHints lh);
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(),
- QLibrary::LoadHints loadHints = 0);
+ QLibrary::LoadHints loadHints = nullptr);
static QStringList suffixes_sys(const QString &fullVersion);
static QStringList prefixes_sys();
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index e03814984c..84fcc53d52 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -77,14 +77,14 @@ QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion)
// .so is preferred.
# if defined(__ia64)
if (!fullVersion.isEmpty()) {
- suffixes << QString::fromLatin1(".so.%1").arg(fullVersion);
+ suffixes << QLatin1String(".so.%1").arg(fullVersion);
} else {
suffixes << QLatin1String(".so");
}
# endif
if (!fullVersion.isEmpty()) {
- suffixes << QString::fromLatin1(".sl.%1").arg(fullVersion);
- suffixes << QString::fromLatin1(".%1").arg(fullVersion);
+ suffixes << QLatin1String(".sl.%1").arg(fullVersion);
+ suffixes << QLatin1String(".%1").arg(fullVersion);
} else {
suffixes << QLatin1String(".sl");
}
@@ -93,15 +93,15 @@ QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion)
#else
if (!fullVersion.isEmpty()) {
- suffixes << QString::fromLatin1(".so.%1").arg(fullVersion);
+ suffixes << QLatin1String(".so.%1").arg(fullVersion);
} else {
suffixes << QLatin1String(".so");
}
#endif
# ifdef Q_OS_MAC
if (!fullVersion.isEmpty()) {
- suffixes << QString::fromLatin1(".%1.bundle").arg(fullVersion);
- suffixes << QString::fromLatin1(".%1.dylib").arg(fullVersion);
+ suffixes << QLatin1String(".%1.bundle").arg(fullVersion);
+ suffixes << QLatin1String(".%1.dylib").arg(fullVersion);
} else {
suffixes << QLatin1String(".bundle") << QLatin1String(".dylib");
}
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h
index 5aca22497a..c176155c28 100644
--- a/src/corelib/plugin/qplugin.h
+++ b/src/corelib/plugin/qplugin.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -71,13 +72,34 @@ inline constexpr unsigned char qPluginArchRequirements()
}
typedef QObject *(*QtPluginInstanceFunction)();
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
typedef const char *(*QtPluginMetaDataFunction)();
+#else
+struct QPluginMetaData
+{
+ const uchar *data;
+ size_t size;
+};
+typedef QPluginMetaData (*QtPluginMetaDataFunction)();
+#endif
+
struct Q_CORE_EXPORT QStaticPlugin
{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+public:
+ constexpr QStaticPlugin(QtPluginInstanceFunction i, QtPluginMetaDataFunction m)
+ : instance(i), rawMetaData(m().data), rawMetaDataSize(m().size)
+ {}
+ QtPluginInstanceFunction instance;
+private:
+ // ### Qt 6: revise, as this is not standard-layout
+ const void *rawMetaData;
+ qsizetype rawMetaDataSize;
+public:
+#elif !defined(Q_QDOC)
// Note: This struct is initialized using an initializer list.
// As such, it cannot have any new constructors or variables.
-#ifndef Q_QDOC
QtPluginInstanceFunction instance;
QtPluginMetaDataFunction rawMetaData;
#else
@@ -139,6 +161,16 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin);
#if defined(QT_STATICPLUGIN)
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
+ static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \
+ Q_PLUGIN_INSTANCE(PLUGINCLASS) \
+ static QPluginMetaData qt_plugin_query_metadata_##PLUGINCLASSNAME() \
+ { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \
+ const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASSNAME() { \
+ return { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \
+ }
+#else
# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \
Q_PLUGIN_INSTANCE(PLUGINCLASS) \
@@ -147,6 +179,17 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin);
QT_PREPEND_NAMESPACE(QStaticPlugin) plugin = { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \
return plugin; \
}
+#endif
+
+#else
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+
+# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
+ Q_EXTERN_C Q_DECL_EXPORT \
+ QPluginMetaData qt_plugin_query_metadata() \
+ { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \
+ Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \
+ Q_PLUGIN_INSTANCE(PLUGINCLASS)
#else
@@ -159,6 +202,7 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin);
#endif
+#endif
#define Q_EXPORT_PLUGIN(PLUGIN) \
Q_EXPORT_PLUGIN2(PLUGIN, PLUGIN)
diff --git a/src/corelib/plugin/qplugin_p.h b/src/corelib/plugin/qplugin_p.h
index 717129268b..ce45ebf700 100644
--- a/src/corelib/plugin/qplugin_p.h
+++ b/src/corelib/plugin/qplugin_p.h
@@ -60,7 +60,8 @@ enum class QtPluginMetaDataKeys {
Requirements,
IID,
ClassName,
- MetaData
+ MetaData,
+ URI
};
// F(IntKey, StringKey, Description)
@@ -68,7 +69,8 @@ enum class QtPluginMetaDataKeys {
#define QT_PLUGIN_FOREACH_METADATA(F) \
F(QtPluginMetaDataKeys::IID, "IID", "Plugin's Interface ID") \
F(QtPluginMetaDataKeys::ClassName, "className", "Plugin class name") \
- F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data")
+ F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data") \
+ F(QtPluginMetaDataKeys::URI, "URI", "Plugin URI")
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
index b113ca13ce..83873edf6f 100644
--- a/src/corelib/plugin/quuid.cpp
+++ b/src/corelib/plugin/quuid.cpp
@@ -112,7 +112,7 @@ static char *_q_uuidToHex(const QUuid &uuid, char *dst, QUuid::StringFormat mode
Parses the string representation of a UUID (with optional surrounding "{}")
by reading at most MaxStringUuidLength (38) characters from \a src, which
- may be \c nullptr. Stops at the first invalid character (which includes a
+ may be \nullptr. Stops at the first invalid character (which includes a
premature NUL).
Returns the successfully parsed QUuid, or a null QUuid in case of failure.
@@ -397,7 +397,7 @@ QUuid::QUuid(const QString &text)
\sa toString(), QUuid()
*/
-QUuid QUuid::fromString(QStringView text) Q_DECL_NOTHROW
+QUuid QUuid::fromString(QStringView text) noexcept
{
if (text.size() > MaxStringUuidLength)
text = text.left(MaxStringUuidLength); // text.truncate(MaxStringUuidLength);
@@ -427,7 +427,7 @@ QUuid QUuid::fromString(QStringView text) Q_DECL_NOTHROW
\sa toString(), QUuid()
*/
-QUuid QUuid::fromString(QLatin1String text) Q_DECL_NOTHROW
+QUuid QUuid::fromString(QLatin1String text) noexcept
{
if (Q_UNLIKELY(text.size() < MaxStringUuidLength - 2
|| (text.front() == QLatin1Char('{') && text.size() < MaxStringUuidLength - 1))) {
@@ -864,7 +864,7 @@ QDataStream &operator>>(QDataStream &s, QUuid &id)
Returns \c true if this is the null UUID
{00000000-0000-0000-0000-000000000000}; otherwise returns \c false.
*/
-bool QUuid::isNull() const Q_DECL_NOTHROW
+bool QUuid::isNull() const noexcept
{
return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 &&
data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 &&
@@ -913,7 +913,7 @@ bool QUuid::isNull() const Q_DECL_NOTHROW
\sa version()
*/
-QUuid::Variant QUuid::variant() const Q_DECL_NOTHROW
+QUuid::Variant QUuid::variant() const noexcept
{
if (isNull())
return VarUnknown;
@@ -934,7 +934,7 @@ QUuid::Variant QUuid::variant() const Q_DECL_NOTHROW
\sa variant()
*/
-QUuid::Version QUuid::version() const Q_DECL_NOTHROW
+QUuid::Version QUuid::version() const noexcept
{
// Check the 4 MSB of data3
Version ver = (Version)(data3>>12);
@@ -957,7 +957,7 @@ QUuid::Version QUuid::version() const Q_DECL_NOTHROW
\sa variant()
*/
-bool QUuid::operator<(const QUuid &other) const Q_DECL_NOTHROW
+bool QUuid::operator<(const QUuid &other) const noexcept
{
if (variant() != other.variant())
return variant() < other.variant();
@@ -984,7 +984,7 @@ bool QUuid::operator<(const QUuid &other) const Q_DECL_NOTHROW
\sa variant()
*/
-bool QUuid::operator>(const QUuid &other) const Q_DECL_NOTHROW
+bool QUuid::operator>(const QUuid &other) const noexcept
{
return other < *this;
}
@@ -1089,7 +1089,7 @@ QDebug operator<<(QDebug dbg, const QUuid &id)
\relates QUuid
Returns a hash of the UUID \a uuid, using \a seed to seed the calculation.
*/
-uint qHash(const QUuid &uuid, uint seed) Q_DECL_NOTHROW
+uint qHash(const QUuid &uuid, uint seed) noexcept
{
return uuid.data1 ^ uuid.data2 ^ (uuid.data3 << 16)
^ ((uuid.data4[0] << 24) | (uuid.data4[1] << 16) | (uuid.data4[2] << 8) | uuid.data4[3])
diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h
index 08a1843640..713ca070c8 100644
--- a/src/corelib/plugin/quuid.h
+++ b/src/corelib/plugin/quuid.h
@@ -93,13 +93,13 @@ public:
#if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_CLANG_QDOC)
- Q_DECL_CONSTEXPR QUuid() Q_DECL_NOTHROW : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {}
+ Q_DECL_CONSTEXPR QUuid() noexcept : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {}
Q_DECL_CONSTEXPR QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3,
- uchar b4, uchar b5, uchar b6, uchar b7, uchar b8) Q_DECL_NOTHROW
+ uchar b4, uchar b5, uchar b6, uchar b7, uchar b8) noexcept
: data1(l), data2(w1), data3(w2), data4{b1, b2, b3, b4, b5, b6, b7, b8} {}
#else
- QUuid() Q_DECL_NOTHROW
+ QUuid() noexcept
{
data1 = 0;
data2 = 0;
@@ -107,7 +107,7 @@ public:
for(int i = 0; i < 8; i++)
data4[i] = 0;
}
- QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8) Q_DECL_NOTHROW
+ QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8) noexcept
{
data1 = l;
data2 = w1;
@@ -124,8 +124,8 @@ public:
#endif
QUuid(const QString &);
- static QUuid fromString(QStringView string) Q_DECL_NOTHROW;
- static QUuid fromString(QLatin1String string) Q_DECL_NOTHROW;
+ static QUuid fromString(QStringView string) noexcept;
+ static QUuid fromString(QLatin1String string) noexcept;
QUuid(const char *);
QString toString() const;
QString toString(StringFormat mode) const; // ### Qt6: merge with previous
@@ -134,9 +134,9 @@ public:
QByteArray toByteArray(StringFormat mode) const; // ### Qt6: merge with previous
QByteArray toRfc4122() const;
static QUuid fromRfc4122(const QByteArray &);
- bool isNull() const Q_DECL_NOTHROW;
+ bool isNull() const noexcept;
- Q_DECL_RELAXED_CONSTEXPR bool operator==(const QUuid &orig) const Q_DECL_NOTHROW
+ Q_DECL_RELAXED_CONSTEXPR bool operator==(const QUuid &orig) const noexcept
{
if (data1 != orig.data1 || data2 != orig.data2 ||
data3 != orig.data3)
@@ -149,24 +149,24 @@ public:
return true;
}
- Q_DECL_RELAXED_CONSTEXPR bool operator!=(const QUuid &orig) const Q_DECL_NOTHROW
+ Q_DECL_RELAXED_CONSTEXPR bool operator!=(const QUuid &orig) const noexcept
{
return !(*this == orig);
}
- bool operator<(const QUuid &other) const Q_DECL_NOTHROW;
- bool operator>(const QUuid &other) const Q_DECL_NOTHROW;
+ bool operator<(const QUuid &other) const noexcept;
+ bool operator>(const QUuid &other) const noexcept;
#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
// On Windows we have a type GUID that is used by the platform API, so we
// provide convenience operators to cast from and to this type.
#if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_CLANG_QDOC)
- Q_DECL_CONSTEXPR QUuid(const GUID &guid) Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR QUuid(const GUID &guid) noexcept
: data1(guid.Data1), data2(guid.Data2), data3(guid.Data3),
data4{guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]} {}
#else
- QUuid(const GUID &guid) Q_DECL_NOTHROW
+ QUuid(const GUID &guid) noexcept
{
data1 = guid.Data1;
data2 = guid.Data2;
@@ -176,24 +176,24 @@ public:
}
#endif
- Q_DECL_RELAXED_CONSTEXPR QUuid &operator=(const GUID &guid) Q_DECL_NOTHROW
+ Q_DECL_RELAXED_CONSTEXPR QUuid &operator=(const GUID &guid) noexcept
{
*this = QUuid(guid);
return *this;
}
- Q_DECL_RELAXED_CONSTEXPR operator GUID() const Q_DECL_NOTHROW
+ Q_DECL_RELAXED_CONSTEXPR operator GUID() const noexcept
{
GUID guid = { data1, data2, data3, { data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7] } };
return guid;
}
- Q_DECL_RELAXED_CONSTEXPR bool operator==(const GUID &guid) const Q_DECL_NOTHROW
+ Q_DECL_RELAXED_CONSTEXPR bool operator==(const GUID &guid) const noexcept
{
return *this == QUuid(guid);
}
- Q_DECL_RELAXED_CONSTEXPR bool operator!=(const GUID &guid) const Q_DECL_NOTHROW
+ Q_DECL_RELAXED_CONSTEXPR bool operator!=(const GUID &guid) const noexcept
{
return !(*this == guid);
}
@@ -216,8 +216,8 @@ public:
}
- QUuid::Variant variant() const Q_DECL_NOTHROW;
- QUuid::Version version() const Q_DECL_NOTHROW;
+ QUuid::Variant variant() const noexcept;
+ QUuid::Version version() const noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_CLANG_QDOC)
static QUuid fromCFUUID(CFUUIDRef uuid);
@@ -243,11 +243,11 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QUuid &);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QUuid &);
#endif
-Q_CORE_EXPORT uint qHash(const QUuid &uuid, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT uint qHash(const QUuid &uuid, uint seed = 0) noexcept;
-inline bool operator<=(const QUuid &lhs, const QUuid &rhs) Q_DECL_NOTHROW
+inline bool operator<=(const QUuid &lhs, const QUuid &rhs) noexcept
{ return !(rhs < lhs); }
-inline bool operator>=(const QUuid &lhs, const QUuid &rhs) Q_DECL_NOTHROW
+inline bool operator>=(const QUuid &lhs, const QUuid &rhs) noexcept
{ return !(lhs < rhs); }
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp
index c56536cdb1..28ae40f3df 100644
--- a/src/corelib/serialization/qcborarray.cpp
+++ b/src/corelib/serialization/qcborarray.cpp
@@ -39,6 +39,7 @@
#include "qcborarray.h"
#include "qcborvalue_p.h"
+#include "qdatastream.h"
QT_BEGIN_NAMESPACE
@@ -1218,4 +1219,23 @@ QDebug operator<<(QDebug dbg, const QCborArray &a)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QCborArray &value)
+{
+ stream << value.toCborValue().toCbor();
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QCborArray &value)
+{
+ QByteArray buffer;
+ stream >> buffer;
+ QCborParserError parseError{};
+ value = QCborValue::fromCbor(buffer, &parseError).toArray();
+ if (parseError.error)
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h
index ed0f4912ba..e06544f245 100644
--- a/src/corelib/serialization/qcborarray.h
+++ b/src/corelib/serialization/qcborarray.h
@@ -47,6 +47,7 @@
QT_BEGIN_NAMESPACE
class QJsonArray;
+class QDataStream;
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborArray
@@ -271,6 +272,7 @@ private:
void detach(qsizetype reserve = 0);
friend QCborValue;
+ friend QCborValueRef;
explicit QCborArray(QCborContainerPrivate &dd) noexcept;
QExplicitlySharedDataPointer<QCborContainerPrivate> d;
};
@@ -298,6 +300,11 @@ Q_CORE_EXPORT uint qHash(const QCborArray &array, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborArray &a);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QCborArray &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QCborArray &);
+#endif
+
QT_END_NAMESPACE
#endif // QCBORARRAY_H
diff --git a/src/corelib/serialization/qcborcommon.h b/src/corelib/serialization/qcborcommon.h
index f8278f1649..3dfe50cd09 100644
--- a/src/corelib/serialization/qcborcommon.h
+++ b/src/corelib/serialization/qcborcommon.h
@@ -133,6 +133,11 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, QCborKnownTags tg);
Q_CORE_EXPORT QDebug operator<<(QDebug, QCborTag tg);
#endif
+#if !defined(QT_NO_DEBUG_STREAM)
+QDataStream &operator<<(QDataStream &ds, QCborSimpleType st);
+QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st);
+#endif
+
inline uint qHash(QCborSimpleType tag, uint seed = 0)
{
return qHash(quint8(tag), seed);
diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp
index 33f9249993..4b28ca4a2e 100644
--- a/src/corelib/serialization/qcbormap.cpp
+++ b/src/corelib/serialization/qcbormap.cpp
@@ -1763,4 +1763,23 @@ QDebug operator<<(QDebug dbg, const QCborMap &m)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QCborMap &value)
+{
+ stream << value.toCborValue().toCbor();
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QCborMap &value)
+{
+ QByteArray buffer;
+ stream >> buffer;
+ QCborParserError parseError{};
+ value = QCborValue::fromCbor(buffer, &parseError).toMap();
+ if (parseError.error)
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h
index 3eb2107691..4aea901eef 100644
--- a/src/corelib/serialization/qcbormap.h
+++ b/src/corelib/serialization/qcbormap.h
@@ -52,6 +52,7 @@ typedef QMap<QString, QVariant> QVariantMap;
template <class Key, class T> class QHash;
typedef QHash<QString, QVariant> QVariantHash;
class QJsonObject;
+class QDataStream;
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborMap
@@ -117,6 +118,8 @@ public:
QCborValueRef item; // points to the value
friend class Iterator;
friend class QCborMap;
+ friend class QCborValue;
+ friend class QCborValueRef;
ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
public:
typedef std::random_access_iterator_tag iterator_category;
@@ -170,7 +173,7 @@ public:
: QCborMap()
{
detach(args.size());
- for (auto pair : args)
+ for (const auto &pair : args)
insert(pair.first, pair.second);
}
~QCborMap();
@@ -322,9 +325,10 @@ public:
QJsonObject toJsonObject() const;
private:
+ friend class QCborValue;
+ friend class QCborValueRef;
void detach(qsizetype reserve = 0);
- friend QCborValue;
explicit QCborMap(QCborContainerPrivate &dd) noexcept;
QExplicitlySharedDataPointer<QCborContainerPrivate> d;
};
@@ -352,6 +356,12 @@ Q_CORE_EXPORT uint qHash(const QCborMap &map, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborMap &m);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QCborMap &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QCborMap &);
+#endif
+
+
QT_END_NAMESPACE
#endif // QCBORMAP_H
diff --git a/src/corelib/serialization/qcborstream.cpp b/src/corelib/serialization/qcborstream.cpp
index 87ae316041..078c14a32d 100644
--- a/src/corelib/serialization/qcborstream.cpp
+++ b/src/corelib/serialization/qcborstream.cpp
@@ -44,6 +44,7 @@
#include <qbuffer.h>
#include <qdebug.h>
#include <qstack.h>
+#include <qdatastream.h>
QT_BEGIN_NAMESPACE
@@ -180,6 +181,21 @@ Q_CORE_EXPORT const char *qt_cbor_simpletype_id(QCborSimpleType st)
return nullptr;
}
+#if !defined(QT_NO_DATASTREAM)
+QDataStream &operator<<(QDataStream &ds, QCborSimpleType st)
+{
+ return ds << quint8(st);
+}
+
+QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
+{
+ quint8 v;
+ ds >> v;
+ st = QCborSimpleType(v);
+ return ds;
+}
+#endif
+
#if !defined(QT_NO_DEBUG_STREAM)
QDebug operator<<(QDebug dbg, QCborSimpleType st)
{
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index 80ef515fd2..ba616c0a7d 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -39,7 +39,7 @@
#include "qcborvalue.h"
#include "qcborvalue_p.h"
-
+#include "qdatastream.h"
#include "qcborarray.h"
#include "qcbormap.h"
#include "qcborstream.h"
@@ -108,7 +108,7 @@ QT_BEGIN_NAMESPACE
QCborValue can contain a value of "null", which is not of any specific type.
It resembles the C++ \c {std::nullptr_t} type, whose only possible value is
- \c nullptr. QCborValue has a constructor taking such a type and creates a
+ \nullptr. QCborValue has a constructor taking such a type and creates a
null QCborValue.
Null values are used to indicate that an optional value is not present. In
@@ -128,10 +128,11 @@ QT_BEGIN_NAMESPACE
Such values are completely valid and may appear in CBOR streams, unlike
JSON content and QJsonValue's undefined bit. But like QJsonValue's
- Undefined, it is returned by QCborArray::value() when out of range or
- QCborMap::operator[] when the key is not found in the container. It is not
- possible to tell such a case apart from the value of Undefined, so if that
- is required, check the QCborArray size and use the QCborMap iterator API.
+ Undefined, it is returned by a CBOR container's value() or read-only
+ operator[] for invalid look-ups (index out of range for QCborArray, or key
+ not found for QCborMap). It is not possible to tell such a case apart from
+ the value of Undefined, so if that is required, check the QCborArray size
+ and use the QCborMap iterator API.
\section1 Simple types
@@ -416,7 +417,7 @@ QT_BEGIN_NAMESPACE
using toSimpleType() as well as isSimpleType(st).
CBOR simple types are types that do not have any associated value, like
- C++'s \c{std::nullptr_t} type, whose only possible value is \c nullptr.
+ C++'s \c{std::nullptr_t} type, whose only possible value is \nullptr.
If \a st is \c{QCborSimpleType::Null}, the resulting QCborValue will be of
the \l{Type}{Null} type and similarly for \c{QCborSimpleType::Undefined}.
@@ -457,7 +458,7 @@ QT_BEGIN_NAMESPACE
\fn QCborValue::QCborValue(QCborValue &&other)
\overload
- Moves the contents of the \a other CBorValue object into this one and frees
+ Moves the contents of the \a other QCborValue object into this one and frees
the resources of this one.
*/
@@ -465,7 +466,7 @@ QT_BEGIN_NAMESPACE
\fn QCborValue &&QCborValue::operator=(QCborValue &&other)
\overload
- Moves the contents of the \a other CBorValue object into this one and frees
+ Moves the contents of the \a other QCborValue object into this one and frees
the resources of this one. Returns a reference to this object.
*/
@@ -765,8 +766,8 @@ static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::E
if (qt_is_nan(d)) {
if (opt & QCborValue::UseFloat16) {
if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16)
- return writer.append(qfloat16(qt_qnan()));
- return writer.append(float(qt_qnan()));
+ return writer.append(std::numeric_limits<qfloat16>::quiet_NaN());
+ return writer.append(std::numeric_limits<float>::quiet_NaN());
}
return writer.append(qt_qnan());
}
@@ -848,7 +849,7 @@ QCborContainerPrivate *QCborContainerPrivate::clone(QCborContainerPrivate *d, qs
QCborContainerPrivate *QCborContainerPrivate::detach(QCborContainerPrivate *d, qsizetype reserved)
{
- if (!d || d->ref.load() != 1)
+ if (!d || d->ref.loadRelaxed() != 1)
return clone(d, reserved);
return d;
}
@@ -883,12 +884,12 @@ void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &valu
// detect self-assignment
if (Q_UNLIKELY(this == value.container)) {
- Q_ASSERT(ref.load() >= 2);
+ Q_ASSERT(ref.loadRelaxed() >= 2);
if (disp == MoveContainer)
ref.deref(); // not deref() because it can't drop to 0
QCborContainerPrivate *d = QCborContainerPrivate::clone(this);
d->elements.detach();
- d->ref.store(1);
+ d->ref.storeRelaxed(1);
e.container = d;
} else {
e.container = value.container;
@@ -1367,7 +1368,7 @@ static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader)
{
auto d = new QCborContainerPrivate;
- d->ref.store(1);
+ d->ref.storeRelaxed(1);
d->decodeFromCbor(reader);
return d;
}
@@ -1642,7 +1643,7 @@ QCborValue::QCborValue(const QByteArray &ba)
: n(0), container(new QCborContainerPrivate), t(ByteArray)
{
container->appendByteData(ba.constData(), ba.size(), t);
- container->ref.store(1);
+ container->ref.storeRelaxed(1);
}
/*!
@@ -1655,7 +1656,7 @@ QCborValue::QCborValue(const QString &s)
: n(0), container(new QCborContainerPrivate), t(String)
{
container->append(s);
- container->ref.store(1);
+ container->ref.storeRelaxed(1);
}
/*!
@@ -1670,7 +1671,7 @@ QCborValue::QCborValue(QLatin1String s)
: n(0), container(new QCborContainerPrivate), t(String)
{
container->append(s);
- container->ref.store(1);
+ container->ref.storeRelaxed(1);
}
/*!
@@ -1718,7 +1719,7 @@ QCborValue::QCborValue(const QCborMap &m)
QCborValue::QCborValue(QCborTag t, const QCborValue &tv)
: n(-1), container(new QCborContainerPrivate), t(Tag)
{
- container->ref.store(1);
+ container->ref.storeRelaxed(1);
container->append(t);
container->append(tv);
}
@@ -1986,12 +1987,24 @@ QUuid QCborValue::toUuid(const QUuid &defaultValue) const
return QUuid::fromRfc4122(byteData->asByteArrayView());
}
-QCborArray QCborValue::toArray() const
-{
- return toArray(QCborArray());
-}
+/*!
+ \fn QCborArray QCborValue::toArray() const
+ \fn QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
+
+ Returns the array value stored in this QCborValue, if it is of the array
+ type. Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to
+ QCborArray.
+
+ \sa isArray(), isByteArray(), isMap(), isContainer(), toMap()
+ */
/*!
+ \fn QCborArray QCborValueRef::toArray() const
+ \fn QCborArray QCborValueRef::toArray(const QCborArray &defaultValue) const
+ \internal
+
Returns the array value stored in this QCborValue, if it is of the array
type. Otherwise, it returns \a defaultValue.
@@ -2000,6 +2013,11 @@ QCborArray QCborValue::toArray() const
\sa isArray(), isByteArray(), isMap(), isContainer(), toMap()
*/
+QCborArray QCborValue::toArray() const
+{
+ return toArray(QCborArray());
+}
+
QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
{
if (!isArray())
@@ -2011,12 +2029,24 @@ QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
return dd ? QCborArray(*dd) : defaultValue;
}
-QCborMap QCborValue::toMap() const
-{
- return toMap(QCborMap());
-}
+/*!
+ \fn QCborMap QCborValue::toMap() const
+ \fn QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
+
+ Returns the map value stored in this QCborValue, if it is of the map type.
+ Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to
+ QCborMap.
+
+ \sa isMap(), isArray(), isContainer(), toArray()
+ */
/*!
+ \fn QCborMap QCborValueRef::toMap() const
+ \fn QCborMap QCborValueRef::toMap(const QCborMap &defaultValue) const
+ \internal
+
Returns the map value stored in this QCborValue, if it is of the map type.
Otherwise, it returns \a defaultValue.
@@ -2025,6 +2055,11 @@ QCborMap QCborValue::toMap() const
\sa isMap(), isArray(), isContainer(), toArray()
*/
+QCborMap QCborValue::toMap() const
+{
+ return toMap(QCborMap());
+}
+
QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
{
if (!isMap())
@@ -2077,15 +2112,16 @@ const QCborValue QCborValue::operator[](QLatin1String key) const
}
/*!
+ \overload
+
If this QCborValue is a QCborMap, searches elements for the value whose key
- matches \a key. If this is an array, returns the element whose index is \a
- key. If there's no matching value in the array or map, or if this
+ matches \a key. If this is a QCborArray, returns the element whose index is
+ \a key. If there's no matching value in the array or map, or if this
QCborValue object is not an array or map, returns the undefined value.
\sa operator[], QCborMap::operator[], QCborMap::value(),
QCborMap::find(), QCborArray::operator[], QCborArray::at()
*/
-
const QCborValue QCborValue::operator[](qint64 key) const
{
if (isMap())
@@ -2096,6 +2132,191 @@ const QCborValue QCborValue::operator[](qint64 key) const
}
/*!
+ \internal
+ */
+static Q_DECL_COLD_FUNCTION QCborMap arrayAsMap(const QCborArray &array)
+{
+ if (array.size())
+ qWarning("Using CBOR array as map forced conversion");
+ QCborMap map;
+ for (qsizetype i = array.size(); i-- > 0; ) {
+ QCborValue entry = array.at(i);
+ // Ignore padding entries that may have been added to grow the array
+ // when inserting past its end:
+ if (!entry.isInvalid())
+ map[i] = entry;
+ }
+ return map;
+}
+
+/*!
+ \internal
+ */
+static QCborContainerPrivate *maybeDetach(QCborContainerPrivate *container, qsizetype size)
+{
+ auto replace = QCborContainerPrivate::detach(container, size);
+ Q_ASSERT(replace);
+ if (replace != container) {
+ if (container)
+ container->deref();
+ replace->ref.ref();
+ }
+ return replace;
+}
+
+/*!
+ \internal
+ */
+static QCborContainerPrivate *maybeGrow(QCborContainerPrivate *container, qsizetype index)
+{
+ auto replace = QCborContainerPrivate::grow(container, index);
+ Q_ASSERT(replace);
+ if (replace != container) {
+ if (container)
+ container->deref();
+ replace->ref.ref();
+ }
+ if (replace->elements.size() == index)
+ replace->append(Undefined());
+ else
+ Q_ASSERT(replace->elements.size() > index);
+ return replace;
+}
+
+/*!
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map, with the given \a key. When this QCborValue is a QCborMap,
+ this function is equivalent to the matching operator[] on that map.
+
+ Before returning the reference: if this QCborValue was an array, it is first
+ converted to a map (so that \c{map[i]} is \c{array[i]} for each index, \c i,
+ with valid \c{array[i]}); otherwise, if it was not a map it will be
+ over-written with an empty map.
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+QCborValueRef QCborValue::operator[](const QString &key)
+{
+ if (!isMap())
+ *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
+
+ const qsizetype size = container ? container->elements.size() : 0;
+ qsizetype index = size + 1;
+ bool found = false;
+ if (container) {
+ QCborMap proxy(*container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ container = maybeDetach(container, size + (found ? 0 : 2));
+ Q_ASSERT(container);
+ if (!found) {
+ container->append(key);
+ container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(container->elements.size() & 1));
+ Q_ASSERT(index < container->elements.size());
+ return { container, index };
+}
+
+/*!
+ \overload
+
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map, with the given \a key. When this QCborValue is a QCborMap,
+ this function is equivalent to the matching operator[] on that map.
+
+ Before returning the reference: if this QCborValue was an array, it is first
+ converted to a map (so that \c{map[i]} is \c{array[i]} for each index, \c i,
+ with valid \c{array[i]}); otherwise, if it was not a map it will be
+ over-written with an empty map.
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+QCborValueRef QCborValue::operator[](QLatin1String key)
+{
+ if (!isMap())
+ *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
+
+ const qsizetype size = container ? container->elements.size() : 0;
+ qsizetype index = size + 1;
+ bool found = false;
+ if (container) {
+ QCborMap proxy(*container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ container = maybeDetach(container, size + (found ? 0 : 2));
+ Q_ASSERT(container);
+ if (!found) {
+ container->append(key);
+ container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(container->elements.size() & 1));
+ Q_ASSERT(index < container->elements.size());
+ return { container, index };
+}
+
+/*!
+ \overload
+
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map or array, with the given \a key. When this QCborValue is a
+ QCborMap or, for 0 <= key < 0x10000, a QCborArray, this function is
+ equivalent to the matching operator[] on that map or array.
+
+ Before returning the reference: if this QCborValue was an array but the key
+ is out of range, the array is first converted to a map (so that \c{map[i]}
+ is \c{array[i]} for each index, \c i, with valid \c{array[i]}); otherwise,
+ if it was not a map it will be over-written with an empty map.
+
+ \sa operator[], QCborMap::operator[], QCborMap::value(),
+ QCborMap::find(), QCborArray::operator[], QCborArray::at()
+ */
+QCborValueRef QCborValue::operator[](qint64 key)
+{
+ if (isArray() && key >= 0 && key < 0x10000) {
+ container = maybeGrow(container, key);
+ return { container, qsizetype(key) };
+ }
+ if (!isMap())
+ *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
+
+ const qsizetype size = container ? container->elements.size() : 0;
+ Q_ASSERT(!(size & 1));
+ qsizetype index = size + 1;
+ bool found = false;
+ if (container) {
+ QCborMap proxy(*container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ container = maybeDetach(container, size + (found ? 0 : 2));
+ Q_ASSERT(container);
+ if (!found) {
+ container->append(key);
+ container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(container->elements.size() & 1));
+ Q_ASSERT(index < container->elements.size());
+ return { container, index };
+}
+
+/*!
Decodes one item from the CBOR stream found in \a reader and returns the
equivalent representation. This function is recursive: if the item is a map
or array, it will decode all items found in that map or array, until the
@@ -2359,6 +2580,255 @@ QCborValue::Type QCborValueRef::concreteType(QCborValueRef self) noexcept
return self.d->elements.at(self.i).type;
}
+/*!
+ If this QCborValueRef refers to a QCborMap, searches elements for the value
+ whose key matches \a key. If there's no key matching \a key in the map or if
+ this QCborValueRef object is not a map, returns the undefined value.
+
+ This function is equivalent to:
+
+ \code
+ value.toMap().value(key);
+ \endcode
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+const QCborValue QCborValueRef::operator[](const QString &key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+/*!
+ \overload
+
+ If this QCborValueRef refers to a QCborMap, searches elements for the value
+ whose key matches \a key. If there's no key matching \a key in the map or if
+ this QCborValueRef object is not a map, returns the undefined value.
+
+ This function is equivalent to:
+
+ \code
+ value.toMap().value(key);
+ \endcode
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+const QCborValue QCborValueRef::operator[](QLatin1String key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+/*!
+ \overload
+
+ If this QCborValueRef refers to a QCborMap, searches elements for the value
+ whose key matches \a key. If this is a QCborArray, returns the element whose
+ index is \a key. If there's no matching value in the array or map, or if
+ this QCborValueRef object is not an array or map, returns the undefined
+ value.
+
+ \sa operator[], QCborMap::operator[], QCborMap::value(),
+ QCborMap::find(), QCborArray::operator[], QCborArray::at()
+ */
+const QCborValue QCborValueRef::operator[](qint64 key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+/*!
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map, with the given \a key. When this QCborValueRef refers to a
+ QCborMap, this function is equivalent to the matching operator[] on that
+ map.
+
+ Before returning the reference: if the QCborValue referenced was an array,
+ it is first converted to a map (so that \c{map[i]} is \c{array[i]} for each
+ index, \c i, with valid \c{array[i]}); otherwise, if it was not a map it
+ will be over-written with an empty map.
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+QCborValueRef QCborValueRef::operator[](const QString &key)
+{
+ auto &e = d->elements[i];
+ qsizetype size = 0;
+ if (e.flags & QtCbor::Element::IsContainer) {
+ if (e.container) {
+ if (e.type == QCborValue::Array) {
+ QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
+ qSwap(e.container, repack.container);
+ } else if (e.type != QCborValue::Map) {
+ e.container->deref();
+ e.container = nullptr;
+ }
+ }
+ e.type = QCborValue::Map;
+ if (e.container)
+ size = e.container->elements.size();
+ } else {
+ // Stomp any prior e.value, replace with a map (that we'll grow)
+ e.container = nullptr;
+ e.type = QCborValue::Map;
+ e.flags = QtCbor::Element::IsContainer;
+ }
+
+ qsizetype index = size + 1;
+ bool found = false;
+ if (e.container) {
+ QCborMap proxy(*e.container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ e.container = maybeDetach(e.container, size + (found ? 0 : 2));
+ Q_ASSERT(e.container);
+ if (!found) {
+ e.container->append(key);
+ e.container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
+ Q_ASSERT(index < e.container->elements.size());
+ return { e.container, index };
+}
+
+/*!
+ \overload
+
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map, with the given \a key. When this QCborValue is a QCborMap,
+ this function is equivalent to the matching operator[] on that map.
+
+ Before returning the reference: if the QCborValue referenced was an array,
+ it is first converted to a map (so that \c{map[i]} is \c{array[i]} for each
+ index, \c i, with valid \c{array[i]}); otherwise, if it was not a map it
+ will be over-written with an empty map.
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+QCborValueRef QCborValueRef::operator[](QLatin1String key)
+{
+ auto &e = d->elements[i];
+ qsizetype size = 0;
+ if (e.flags & QtCbor::Element::IsContainer) {
+ if (e.container) {
+ if (e.type == QCborValue::Array) {
+ QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
+ qSwap(e.container, repack.container);
+ } else if (e.type != QCborValue::Map) {
+ e.container->deref();
+ e.container = nullptr;
+ }
+ }
+ e.type = QCborValue::Map;
+ if (e.container)
+ size = e.container->elements.size();
+ } else {
+ // Stomp any prior e.value, replace with a map (that we'll grow)
+ e.container = nullptr;
+ e.type = QCborValue::Map;
+ e.flags = QtCbor::Element::IsContainer;
+ }
+
+ qsizetype index = size + 1;
+ bool found = false;
+ if (e.container) {
+ QCborMap proxy(*e.container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ e.container = maybeDetach(e.container, size + (found ? 0 : 2));
+ Q_ASSERT(e.container);
+ if (!found) {
+ e.container->append(key);
+ e.container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
+ Q_ASSERT(index < e.container->elements.size());
+ return { e.container, index };
+}
+
+/*!
+ \overload
+
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map or array, with the given \a key. When this QCborValue is a
+ QCborMap or, for 0 <= key < 0x10000, a QCborArray, this function is
+ equivalent to the matching operator[] on that map or array.
+
+ Before returning the reference: if the QCborValue referenced was an array
+ but the key is out of range, the array is first converted to a map (so that
+ \c{map[i]} is \c{array[i]} for each index, \c i, with valid \c{array[i]});
+ otherwise, if it was not a map it will be over-written with an empty map.
+
+ \sa operator[], QCborMap::operator[], QCborMap::value(),
+ QCborMap::find(), QCborArray::operator[], QCborArray::at()
+ */
+QCborValueRef QCborValueRef::operator[](qint64 key)
+{
+ auto &e = d->elements[i];
+ if (e.type == QCborValue::Array && key >= 0 && key < 0x10000) {
+ e.container = maybeGrow(e.container, key);
+ return { e.container, qsizetype(key) };
+ }
+ qsizetype size = 0;
+ if (e.flags & QtCbor::Element::IsContainer) {
+ if (e.container) {
+ if (e.type == QCborValue::Array) {
+ QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
+ qSwap(e.container, repack.container);
+ } else if (e.type != QCborValue::Map) {
+ e.container->deref();
+ e.container = nullptr;
+ }
+ }
+ e.type = QCborValue::Map;
+ if (e.container)
+ size = e.container->elements.size();
+ } else {
+ // Stomp any prior e.value, replace with a map (that we'll grow)
+ e.container = nullptr;
+ e.type = QCborValue::Map;
+ e.flags = QtCbor::Element::IsContainer;
+ }
+ Q_ASSERT(!(size & 1));
+
+ qsizetype index = size + 1;
+ bool found = false;
+ if (e.container) {
+ QCborMap proxy(*e.container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ e.container = maybeDetach(e.container, size + (found ? 0 : 2));
+ Q_ASSERT(e.container);
+ if (!found) {
+ e.container->append(key);
+ e.container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
+ Q_ASSERT(index < e.container->elements.size());
+ return { e.container, index };
+}
+
+
inline QCborArray::QCborArray(QCborContainerPrivate &dd) noexcept
: d(&dd)
{
@@ -2471,7 +2941,7 @@ static QDebug debugContents(QDebug &dbg, const QCborValue &v)
}
if (v.isSimpleType())
return dbg << v.toSimpleType();
- return dbg << "<unknown type " << hex << int(v.type()) << dec << '>';
+ return dbg << "<unknown type " << Qt::hex << int(v.type()) << Qt::dec << '>';
}
QDebug operator<<(QDebug dbg, const QCborValue &v)
{
@@ -2481,6 +2951,26 @@ QDebug operator<<(QDebug dbg, const QCborValue &v)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QCborValue &value)
+{
+ stream << QCborValue(value).toCbor();
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QCborValue &value)
+{
+ QByteArray buffer;
+ stream >> buffer;
+ QCborParserError parseError{};
+ value = QCborValue::fromCbor(buffer, &parseError);
+ if (parseError.error)
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return stream;
+}
+#endif
+
+
QT_END_NAMESPACE
#include "qcborarray.cpp"
diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h
index d6ba4e88d8..f542e44c47 100644
--- a/src/corelib/serialization/qcborvalue.h
+++ b/src/corelib/serialization/qcborvalue.h
@@ -69,6 +69,7 @@ class QCborArray;
class QCborMap;
class QCborStreamReader;
class QCborStreamWriter;
+class QDataStream;
struct QCborParserError
{
@@ -78,6 +79,7 @@ struct QCborParserError
QString errorString() const { return error.toString(); }
};
+class QCborValueRef;
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborValue
{
@@ -242,20 +244,18 @@ public:
#endif
QUuid toUuid(const QUuid &defaultValue = {}) const;
-#ifdef Q_QDOC
- QCborArray toArray(const QCborArray &a = {}) const;
- QCborMap toMap(const QCborMap &m = {}) const;
-#else
// only forward-declared, need split functions
QCborArray toArray() const;
QCborArray toArray(const QCborArray &defaultValue) const;
QCborMap toMap() const;
QCborMap toMap(const QCborMap &defaultValue) const;
-#endif
const QCborValue operator[](const QString &key) const;
const QCborValue operator[](QLatin1String key) const;
const QCborValue operator[](qint64 key) const;
+ QCborValueRef operator[](qint64 key);
+ QCborValueRef operator[](QLatin1String key);
+ QCborValueRef operator[](const QString & key);
int compare(const QCborValue &other) const;
#if 0 && QT_HAS_INCLUDE(<compare>)
@@ -393,16 +393,18 @@ public:
QUuid toUuid(const QUuid &defaultValue = {}) const
{ return concrete().toUuid(defaultValue); }
-#ifdef Q_QDOC
- QCborArray toArray(const QCborArray &a = {}) const;
- QCborMap toMap(const QCborMap &m = {}) const;
-#else
// only forward-declared, need split functions. Implemented in qcbor{array,map}.h
QCborArray toArray() const;
QCborArray toArray(const QCborArray &a) const;
QCborMap toMap() const;
QCborMap toMap(const QCborMap &m) const;
-#endif
+
+ const QCborValue operator[](const QString &key) const;
+ const QCborValue operator[](QLatin1String key) const;
+ const QCborValue operator[](qint64 key) const;
+ QCborValueRef operator[](qint64 key);
+ QCborValueRef operator[](QLatin1String key);
+ QCborValueRef operator[](const QString & key);
int compare(const QCborValue &other) const
{ return concrete().compare(other); }
@@ -434,6 +436,7 @@ public:
{ return concrete().toDiagnosticNotation(opt); }
private:
+ friend class QCborValue;
friend class QCborArray;
friend class QCborMap;
friend class QCborContainerPrivate;
@@ -465,6 +468,11 @@ Q_CORE_EXPORT uint qHash(const QCborValue &value, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborValue &v);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QCborValue &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QCborValue &);
+#endif
+
QT_END_NAMESPACE
#if defined(QT_X11_DEFINES_FOUND)
diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp
index 951f6c9736..b3330d6cea 100644
--- a/src/corelib/serialization/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
@@ -98,6 +98,10 @@ QT_BEGIN_NAMESPACE
ensures that you get integers of the size you want and insulates
you from compiler and platform differences.
+ Enumerations can be serialized through QDataStream without the
+ need of manually defining streaming operators. Enum classes are
+ serialized using the declared size.
+
To take one example, a \c{char *} string is written as a 32-bit
integer equal to the length of the string including the '\\0' byte,
followed by all the characters of the string including the
@@ -273,7 +277,7 @@ QT_BEGIN_NAMESPACE
QDataStream::QDataStream()
{
- dev = 0;
+ dev = nullptr;
owndev = false;
byteorder = BigEndian;
ver = Qt_DefaultCompiledVersion;
@@ -368,7 +372,7 @@ QDataStream::~QDataStream()
/*!
\fn QIODevice *QDataStream::device() const
- Returns the I/O device currently set, or 0 if no
+ Returns the I/O device currently set, or \nullptr if no
device is currently set.
\sa setDevice()
@@ -377,7 +381,7 @@ QDataStream::~QDataStream()
/*!
void QDataStream::setDevice(QIODevice *d)
- Sets the I/O device to \a d, which can be 0
+ Sets the I/O device to \a d, which can be \nullptr
to unset to current I/O device.
\sa device()
@@ -392,17 +396,18 @@ void QDataStream::setDevice(QIODevice *d)
dev = d;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
Unsets the I/O device.
- Use setDevice(0) instead.
+ Use setDevice(nullptr) instead.
*/
void QDataStream::unsetDevice()
{
- setDevice(0);
+ setDevice(nullptr);
}
-
+#endif
/*!
\fn bool QDataStream::atEnd() const
@@ -428,7 +433,7 @@ bool QDataStream::atEnd() const
*/
QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
{
- return d == 0 ? QDataStream::DoublePrecision : d->floatingPointPrecision;
+ return d ? d->floatingPointPrecision : QDataStream::DoublePrecision;
}
/*!
@@ -453,7 +458,7 @@ QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
*/
void QDataStream::setFloatingPointPrecision(QDataStream::FloatingPointPrecision precision)
{
- if (d == 0)
+ if (!d)
d.reset(new QDataStreamPrivate());
d->floatingPointPrecision = precision;
}
@@ -559,6 +564,8 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_10 Same as Qt_5_6
\value Qt_5_11 Same as Qt_5_6
\value Qt_5_12 Version 18 (Qt 5.12)
+ \value Qt_5_13 Version 19 (Qt 5.13)
+ \value Qt_5_14 Same as Qt_5_13
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
@@ -632,7 +639,7 @@ void QDataStream::startTransaction()
{
CHECK_STREAM_PRECOND(Q_VOID)
- if (d == 0)
+ if (!d)
d.reset(new QDataStreamPrivate());
if (++d->transactionDepth == 1) {
@@ -1026,8 +1033,7 @@ QDataStream &QDataStream::operator>>(char *&s)
\c{delete []} operator.
The \a l parameter is set to the length of the buffer. If the
- string read is empty, \a l is set to 0 and \a s is set to
- a null pointer.
+ string read is empty, \a l is set to 0 and \a s is set to \nullptr.
The serialization format is a quint32 length specifier first,
then \a l bytes of data.
@@ -1037,7 +1043,7 @@ QDataStream &QDataStream::operator>>(char *&s)
QDataStream &QDataStream::readBytes(char *&s, uint &l)
{
- s = 0;
+ s = nullptr;
l = 0;
CHECK_STREAM_PRECOND(*this)
@@ -1048,8 +1054,8 @@ QDataStream &QDataStream::readBytes(char *&s, uint &l)
const quint32 Step = 1024 * 1024;
quint32 allocated = 0;
- char *prevBuf = 0;
- char *curBuf = 0;
+ char *prevBuf = nullptr;
+ char *curBuf = nullptr;
do {
int blockSize = qMin(Step, len - allocated);
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index eae0146553..cfcd89333b 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -55,7 +55,6 @@ class QByteArray;
class QIODevice;
template <typename T> class QList;
-template <typename T> class QLinkedList;
template <typename T> class QVector;
template <typename T> class QSet;
template <class Key, class T> class QHash;
@@ -99,10 +98,20 @@ public:
Qt_5_10 = Qt_5_9,
Qt_5_11 = Qt_5_10,
Qt_5_12 = 18,
-#if QT_VERSION >= 0x050d00
+ Qt_5_13 = 19,
+ Qt_5_14 = Qt_5_13,
+#if QT_VERSION >= 0x050f00
+ Qt_5_15 = Qt_5_14,
+ Qt_DefaultCompiledVersion = Qt_5_15
+#elif QT_VERSION >= 0x060000
+ Qt_6_0 = Qt_5_15,
+ Qt_DefaultCompiledVersion = Qt_6_0
+#else
+ Qt_DefaultCompiledVersion = Qt_5_14
+#endif
+#if QT_VERSION >= 0x060100
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
- Qt_DefaultCompiledVersion = Qt_5_12
};
enum ByteOrder {
@@ -130,7 +139,10 @@ public:
QIODevice *device() const;
void setDevice(QIODevice *);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QDataStream::setDevice(nullptr) instead")
void unsetDevice();
+#endif
bool atEnd() const;
@@ -373,25 +385,23 @@ inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e)
{ return s >> e.i; }
template <typename T>
-inline QDataStream &operator>>(QDataStream &s, QList<T> &l)
-{
- return QtPrivate::readArrayBasedContainer(s, l);
-}
+typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
+operator<<(QDataStream &s, const T &t)
+{ return s << static_cast<typename std::underlying_type<T>::type>(t); }
template <typename T>
-inline QDataStream &operator<<(QDataStream &s, const QList<T> &l)
-{
- return QtPrivate::writeSequentialContainer(s, l);
-}
+typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
+operator>>(QDataStream &s, T &t)
+{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
template <typename T>
-inline QDataStream &operator>>(QDataStream &s, QLinkedList<T> &l)
+inline QDataStream &operator>>(QDataStream &s, QList<T> &l)
{
- return QtPrivate::readListBasedContainer(s, l);
+ return QtPrivate::readArrayBasedContainer(s, l);
}
template <typename T>
-inline QDataStream &operator<<(QDataStream &s, const QLinkedList<T> &l)
+inline QDataStream &operator<<(QDataStream &s, const QList<T> &l)
{
return QtPrivate::writeSequentialContainer(s, l);
}
diff --git a/src/corelib/serialization/qjson_p.h b/src/corelib/serialization/qjson_p.h
index feba1faac6..9de53d5b74 100644
--- a/src/corelib/serialization/qjson_p.h
+++ b/src/corelib/serialization/qjson_p.h
@@ -304,7 +304,7 @@ public:
return *this;
}
- QLatin1String toQLatin1String() const Q_DECL_NOTHROW {
+ QLatin1String toQLatin1String() const noexcept {
return QLatin1String(d->latin1, d->length);
}
@@ -339,23 +339,23 @@ public:
};
#define DEF_OP(op) \
- inline bool operator op(Latin1String lhs, Latin1String rhs) Q_DECL_NOTHROW \
+ inline bool operator op(Latin1String lhs, Latin1String rhs) noexcept \
{ \
return lhs.toQLatin1String() op rhs.toQLatin1String(); \
} \
- inline bool operator op(QLatin1String lhs, Latin1String rhs) Q_DECL_NOTHROW \
+ inline bool operator op(QLatin1String lhs, Latin1String rhs) noexcept \
{ \
return lhs op rhs.toQLatin1String(); \
} \
- inline bool operator op(Latin1String lhs, QLatin1String rhs) Q_DECL_NOTHROW \
+ inline bool operator op(Latin1String lhs, QLatin1String rhs) noexcept \
{ \
return lhs.toQLatin1String() op rhs; \
} \
- inline bool operator op(const QString &lhs, Latin1String rhs) Q_DECL_NOTHROW \
+ inline bool operator op(const QString &lhs, Latin1String rhs) noexcept \
{ \
return lhs op rhs.toQLatin1String(); \
} \
- inline bool operator op(Latin1String lhs, const QString &rhs) Q_DECL_NOTHROW \
+ inline bool operator op(Latin1String lhs, const QString &rhs) noexcept \
{ \
return lhs.toQLatin1String() op rhs; \
} \
@@ -686,7 +686,7 @@ public:
{
}
inline Data(int reserved, QJsonValue::Type valueType)
- : rawData(0), compactionCounter(0), ownsData(true)
+ : rawData(nullptr), compactionCounter(0), ownsData(true)
{
Q_ASSERT(valueType == QJsonValue::Array || valueType == QJsonValue::Object);
@@ -719,7 +719,7 @@ public:
Data *clone(Base *b, int reserve = 0)
{
int size = sizeof(Header) + b->size;
- if (b == header->root() && ref.load() == 1 && alloc >= size + reserve)
+ if (b == header->root() && ref.loadRelaxed() == 1 && alloc >= size + reserve)
return this;
if (reserve) {
@@ -728,7 +728,7 @@ public:
size = qMax(size + reserve, qMin(size *2, (int)Value::MaxSize));
if (size > Value::MaxSize) {
qWarning("QJson: Document too large to store in data structure");
- return 0;
+ return nullptr;
}
}
char *raw = (char *)malloc(size);
@@ -746,7 +746,7 @@ public:
bool valid() const;
private:
- Q_DISABLE_COPY(Data)
+ Q_DISABLE_COPY_MOVE(Data)
};
}
diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp
index 1187bb03a3..6b327619ad 100644
--- a/src/corelib/serialization/qjsonarray.cpp
+++ b/src/corelib/serialization/qjsonarray.cpp
@@ -132,7 +132,7 @@ QT_BEGIN_NAMESPACE
Creates an empty array.
*/
QJsonArray::QJsonArray()
- : d(0), a(0)
+ : d(nullptr), a(nullptr)
{
}
@@ -168,8 +168,8 @@ QJsonArray::QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array)
*/
void QJsonArray::initialize()
{
- d = 0;
- a = 0;
+ d = nullptr;
+ a = nullptr;
}
/*!
@@ -675,6 +675,14 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa begin(), constEnd()
*/
+/*! \fn QJsonArray::const_iterator QJsonArray::cbegin() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
+ in the array.
+
+ \sa begin(), cend()
+*/
+
/*! \fn QJsonArray::iterator QJsonArray::end()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
@@ -696,6 +704,14 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa constBegin(), end()
*/
+/*! \fn QJsonArray::const_iterator QJsonArray::cend() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ item after the last item in the array.
+
+ \sa cbegin(), end()
+*/
+
/*! \fn void QJsonArray::push_back(const QJsonValue &value)
This function is provided for STL compatibility. It is equivalent
@@ -1210,7 +1226,7 @@ bool QJsonArray::detach2(uint reserve)
d->ref.ref();
return true;
}
- if (reserve == 0 && d->ref.load() == 1)
+ if (reserve == 0 && d->ref.loadRelaxed() == 1)
return true;
QJsonPrivate::Data *x = d->clone(a, reserve);
@@ -1259,5 +1275,22 @@ QDebug operator<<(QDebug dbg, const QJsonArray &a)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QJsonArray &array)
+{
+ QJsonDocument doc{array};
+ stream << doc.toJson(QJsonDocument::Compact);
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QJsonArray &array)
+{
+ QJsonDocument doc;
+ stream >> doc;
+ array = doc.array();
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h
index 5dff4a0aa9..983a6753b5 100644
--- a/src/corelib/serialization/qjsonarray.h
+++ b/src/corelib/serialization/qjsonarray.h
@@ -42,9 +42,7 @@
#include <QtCore/qjsonvalue.h>
#include <QtCore/qiterator.h>
-#if defined(Q_COMPILER_INITIALIZER_LISTS)
#include <initializer_list>
-#endif
QT_BEGIN_NAMESPACE
@@ -58,21 +56,19 @@ class Q_CORE_EXPORT QJsonArray
public:
QJsonArray();
-#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC)
QJsonArray(std::initializer_list<QJsonValue> args)
{
initialize();
for (std::initializer_list<QJsonValue>::const_iterator i = args.begin(); i != args.end(); ++i)
append(*i);
}
-#endif
~QJsonArray();
QJsonArray(const QJsonArray &other);
QJsonArray &operator =(const QJsonArray &other);
- QJsonArray(QJsonArray &&other) Q_DECL_NOTHROW
+ QJsonArray(QJsonArray &&other) noexcept
: d(other.d),
a(other.a)
{
@@ -80,7 +76,7 @@ public:
other.a = nullptr;
}
- QJsonArray &operator =(QJsonArray &&other) Q_DECL_NOTHROW
+ QJsonArray &operator =(QJsonArray &&other) noexcept
{
swap(other);
return *this;
@@ -115,7 +111,7 @@ public:
bool operator==(const QJsonArray &other) const;
bool operator!=(const QJsonArray &other) const;
- void swap(QJsonArray &other) Q_DECL_NOTHROW
+ void swap(QJsonArray &other) noexcept
{
qSwap(d, other.d);
qSwap(a, other.a);
@@ -214,9 +210,11 @@ public:
inline iterator begin() { detach2(); return iterator(this, 0); }
inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator constBegin() const { return const_iterator(this, 0); }
+ inline const_iterator cbegin() const { return const_iterator(this, 0); }
inline iterator end() { detach2(); return iterator(this, size()); }
inline const_iterator end() const { return const_iterator(this, size()); }
inline const_iterator constEnd() const { return const_iterator(this, size()); }
+ inline const_iterator cend() const { return const_iterator(this, size()); }
iterator insert(iterator before, const QJsonValue &value) { insert(before.i, value); return before; }
iterator erase(iterator it) { removeAt(it.i); return it; }
@@ -271,6 +269,11 @@ Q_CORE_EXPORT uint qHash(const QJsonArray &array, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonArray &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonArray &);
+#endif
+
QT_END_NAMESPACE
#endif // QJSONARRAY_H
diff --git a/src/corelib/serialization/qjsoncbor.cpp b/src/corelib/serialization/qjsoncbor.cpp
index 4603750d11..e0c390f610 100644
--- a/src/corelib/serialization/qjsoncbor.cpp
+++ b/src/corelib/serialization/qjsoncbor.cpp
@@ -826,7 +826,7 @@ QCborArray QCborArray::fromJsonArray(const QJsonArray &array)
{
QCborArray a;
a.detach(array.size());
- for (const QJsonValue v : array) {
+ for (const QJsonValue &v : array) {
if (v.isString())
a.d->append(v.toString());
else
diff --git a/src/corelib/serialization/qjsondocument.cpp b/src/corelib/serialization/qjsondocument.cpp
index 0cd86d3ded..f8027efb58 100644
--- a/src/corelib/serialization/qjsondocument.cpp
+++ b/src/corelib/serialization/qjsondocument.cpp
@@ -47,6 +47,7 @@
#include "qjsonwriter_p.h"
#include "qjsonparser_p.h"
#include "qjson_p.h"
+#include "qdatastream.h"
QT_BEGIN_NAMESPACE
@@ -83,7 +84,7 @@ QT_BEGIN_NAMESPACE
* Constructs an empty and invalid document.
*/
QJsonDocument::QJsonDocument()
- : d(0)
+ : d(nullptr)
{
}
@@ -91,7 +92,7 @@ QJsonDocument::QJsonDocument()
* Creates a QJsonDocument from \a object.
*/
QJsonDocument::QJsonDocument(const QJsonObject &object)
- : d(0)
+ : d(nullptr)
{
setObject(object);
}
@@ -100,7 +101,7 @@ QJsonDocument::QJsonDocument(const QJsonObject &object)
* Constructs a QJsonDocument from \a array.
*/
QJsonDocument::QJsonDocument(const QJsonArray &array)
- : d(0)
+ : d(nullptr)
{
setArray(array);
}
@@ -235,7 +236,7 @@ const char *QJsonDocument::rawData(int *size) const
{
if (!d) {
*size = 0;
- return 0;
+ return nullptr;
}
*size = d->alloc;
return d->rawData;
@@ -634,7 +635,7 @@ bool QJsonDocument::operator==(const QJsonDocument &other) const
*/
bool QJsonDocument::isNull() const
{
- return (d == 0);
+ return (d == nullptr);
}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
@@ -657,4 +658,23 @@ QDebug operator<<(QDebug dbg, const QJsonDocument &o)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QJsonDocument &doc)
+{
+ stream << doc.toJson(QJsonDocument::Compact);
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QJsonDocument &doc)
+{
+ QByteArray buffer;
+ stream >> buffer;
+ QJsonParseError parseError{};
+ doc = QJsonDocument::fromJson(buffer, &parseError);
+ if (parseError.error && !buffer.isEmpty())
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsondocument.h b/src/corelib/serialization/qjsondocument.h
index b784890c54..a8006a6cc5 100644
--- a/src/corelib/serialization/qjsondocument.h
+++ b/src/corelib/serialization/qjsondocument.h
@@ -93,19 +93,19 @@ public:
QJsonDocument(const QJsonDocument &other);
QJsonDocument &operator =(const QJsonDocument &other);
- QJsonDocument(QJsonDocument &&other) Q_DECL_NOTHROW
+ QJsonDocument(QJsonDocument &&other) noexcept
: d(other.d)
{
other.d = nullptr;
}
- QJsonDocument &operator =(QJsonDocument &&other) Q_DECL_NOTHROW
+ QJsonDocument &operator =(QJsonDocument &&other) noexcept
{
swap(other);
return *this;
}
- void swap(QJsonDocument &other) Q_DECL_NOTHROW
+ void swap(QJsonDocument &other) noexcept
{
qSwap(d, other.d);
}
@@ -172,6 +172,11 @@ Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonDocument)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonDocument &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonDocument &);
+#endif
+
QT_END_NAMESPACE
#endif // QJSONDOCUMENT_H
diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp
index 950bec535b..c1a6328b2f 100644
--- a/src/corelib/serialization/qjsonobject.cpp
+++ b/src/corelib/serialization/qjsonobject.cpp
@@ -110,7 +110,7 @@ QT_BEGIN_NAMESPACE
\sa isEmpty()
*/
QJsonObject::QJsonObject()
- : d(0), o(0)
+ : d(nullptr), o(nullptr)
{
}
@@ -149,8 +149,8 @@ QJsonObject::QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object)
void QJsonObject::initialize()
{
- d = 0;
- o = 0;
+ d = nullptr;
+ o = nullptr;
}
/*!
@@ -646,7 +646,7 @@ bool QJsonObject::operator!=(const QJsonObject &other) const
*/
QJsonObject::iterator QJsonObject::erase(QJsonObject::iterator it)
{
- Q_ASSERT(d && d->ref.load() == 1);
+ Q_ASSERT(d && d->ref.loadRelaxed() == 1);
if (it.o != this || it.i < 0 || it.i >= (int)o->length)
return iterator(this, o->length);
@@ -1231,7 +1231,7 @@ bool QJsonObject::detach2(uint reserve)
d->ref.ref();
return true;
}
- if (reserve == 0 && d->ref.load() == 1)
+ if (reserve == 0 && d->ref.loadRelaxed() == 1)
return true;
QJsonPrivate::Data *x = d->clone(o, reserve);
@@ -1320,4 +1320,21 @@ QDebug operator<<(QDebug dbg, const QJsonObject &o)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QJsonObject &object)
+{
+ QJsonDocument doc{object};
+ stream << doc.toJson(QJsonDocument::Compact);
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QJsonObject &object)
+{
+ QJsonDocument doc;
+ stream >> doc;
+ object = doc.object();
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h
index be42d3747a..d8e2ab9ca7 100644
--- a/src/corelib/serialization/qjsonobject.h
+++ b/src/corelib/serialization/qjsonobject.h
@@ -42,10 +42,8 @@
#include <QtCore/qjsonvalue.h>
#include <QtCore/qiterator.h>
-#ifdef Q_COMPILER_INITIALIZER_LISTS
#include <QtCore/qpair.h>
#include <initializer_list>
-#endif
QT_BEGIN_NAMESPACE
@@ -60,34 +58,32 @@ class Q_CORE_EXPORT QJsonObject
public:
QJsonObject();
-#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC)
QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
{
initialize();
for (std::initializer_list<QPair<QString, QJsonValue> >::const_iterator i = args.begin(); i != args.end(); ++i)
insert(i->first, i->second);
}
-#endif
~QJsonObject();
QJsonObject(const QJsonObject &other);
QJsonObject &operator =(const QJsonObject &other);
- QJsonObject(QJsonObject &&other) Q_DECL_NOTHROW
+ QJsonObject(QJsonObject &&other) noexcept
: d(other.d), o(other.o)
{
other.d = nullptr;
other.o = nullptr;
}
- QJsonObject &operator =(QJsonObject &&other) Q_DECL_NOTHROW
+ QJsonObject &operator =(QJsonObject &&other) noexcept
{
swap(other);
return *this;
}
- void swap(QJsonObject &other) Q_DECL_NOTHROW
+ void swap(QJsonObject &other) noexcept
{
qSwap(d, other.d);
qSwap(o, other.o);
@@ -268,6 +264,11 @@ Q_CORE_EXPORT uint qHash(const QJsonObject &object, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonObject &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonObject &);
+#endif
+
QT_END_NAMESPACE
#endif // QJSONOBJECT_H
diff --git a/src/corelib/serialization/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp
index bfba95520e..cd36bd5a5b 100644
--- a/src/corelib/serialization/qjsonparser.cpp
+++ b/src/corelib/serialization/qjsonparser.cpp
@@ -198,7 +198,9 @@ QString QJsonParseError::errorString() const
using namespace QJsonPrivate;
Parser::Parser(const char *json, int length)
- : head(json), json(json), data(0), dataLength(0), current(0), nestingLevel(0), lastError(QJsonParseError::NoError)
+ : head(json), json(json), data(nullptr)
+ , dataLength(0), current(0), nestingLevel(0)
+ , lastError(QJsonParseError::NoError)
{
end = json + length;
}
@@ -316,7 +318,7 @@ QJsonDocument Parser::parse(QJsonParseError *error)
eatBOM();
char token = nextToken();
- DEBUG << hex << (uint)token;
+ DEBUG << Qt::hex << (uint)token;
if (token == BeginArray) {
if (!parseArray())
goto error;
diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp
index 2c04da4885..0bd28581f3 100644
--- a/src/corelib/serialization/qjsonvalue.cpp
+++ b/src/corelib/serialization/qjsonvalue.cpp
@@ -45,6 +45,7 @@
#include <qvariant.h>
#include <qstringlist.h>
#include <qdebug.h>
+#include "qdatastream.h"
#ifndef QT_BOOTSTRAPPED
# include <qcborarray.h>
@@ -111,7 +112,7 @@ QT_BEGIN_NAMESPACE
The default is to create a Null value.
*/
QJsonValue::QJsonValue(Type type)
- : ui(0), d(0), t(type)
+ : ui(0), d(nullptr), t(type)
{
}
@@ -119,7 +120,7 @@ QJsonValue::QJsonValue(Type type)
\internal
*/
QJsonValue::QJsonValue(QJsonPrivate::Data *data, QJsonPrivate::Base *base, const QJsonPrivate::Value &v)
- : d(0)
+ : d(nullptr)
{
t = (Type)(uint)v.type;
switch (t) {
@@ -153,7 +154,7 @@ QJsonValue::QJsonValue(QJsonPrivate::Data *data, QJsonPrivate::Base *base, const
Creates a value of type Bool, with value \a b.
*/
QJsonValue::QJsonValue(bool b)
- : d(0), t(Bool)
+ : d(nullptr), t(Bool)
{
this->b = b;
}
@@ -162,7 +163,7 @@ QJsonValue::QJsonValue(bool b)
Creates a value of type Double, with value \a n.
*/
QJsonValue::QJsonValue(double n)
- : d(0), t(Double)
+ : d(nullptr), t(Double)
{
this->dbl = n;
}
@@ -172,7 +173,7 @@ QJsonValue::QJsonValue(double n)
Creates a value of type Double, with value \a n.
*/
QJsonValue::QJsonValue(int n)
- : d(0), t(Double)
+ : d(nullptr), t(Double)
{
this->dbl = n;
}
@@ -184,7 +185,7 @@ QJsonValue::QJsonValue(int n)
If you pass in values outside this range expect a loss of precision to occur.
*/
QJsonValue::QJsonValue(qint64 n)
- : d(0), t(Double)
+ : d(nullptr), t(Double)
{
this->dbl = double(n);
}
@@ -193,7 +194,7 @@ QJsonValue::QJsonValue(qint64 n)
Creates a value of type String, with value \a s.
*/
QJsonValue::QJsonValue(const QString &s)
- : d(0), t(String)
+ : d(nullptr), t(String)
{
stringDataFromQStringHelper(s);
}
@@ -220,7 +221,7 @@ void QJsonValue::stringDataFromQStringHelper(const QString &string)
Creates a value of type String, with value \a s.
*/
QJsonValue::QJsonValue(QLatin1String s)
- : d(0), t(String)
+ : d(nullptr), t(String)
{
// ### FIXME: Avoid creating the temp QString below
QString str(s);
@@ -933,4 +934,78 @@ QDebug operator<<(QDebug dbg, const QJsonValue &o)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QJsonValue &v)
+{
+ quint8 type = v.t;
+ stream << type;
+ switch (type) {
+ case QJsonValue::Undefined:
+ case QJsonValue::Null:
+ break;
+ case QJsonValue::Bool:
+ stream << v.toBool();
+ break;
+ case QJsonValue::Double:
+ stream << v.toDouble();
+ break;
+ case QJsonValue::String:
+ stream << v.toString();
+ break;
+ case QJsonValue::Array:
+ stream << v.toArray();
+ break;
+ case QJsonValue::Object:
+ stream << v.toObject();
+ break;
+ }
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QJsonValue &v)
+{
+ quint8 type;
+ stream >> type;
+ switch (type) {
+ case QJsonValue::Undefined:
+ case QJsonValue::Null:
+ v = QJsonValue{QJsonValue::Type(type)};
+ break;
+ case QJsonValue::Bool: {
+ bool b;
+ stream >> b;
+ v = QJsonValue(b);
+ break;
+ } case QJsonValue::Double: {
+ double d;
+ stream >> d;
+ v = QJsonValue{d};
+ break;
+ } case QJsonValue::String: {
+ QString s;
+ stream >> s;
+ v = QJsonValue{s};
+ break;
+ }
+ case QJsonValue::Array: {
+ QJsonArray a;
+ stream >> a;
+ v = QJsonValue{a};
+ break;
+ }
+ case QJsonValue::Object: {
+ QJsonObject o;
+ stream >> o;
+ v = QJsonValue{o};
+ break;
+ }
+ default: {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ v = QJsonValue{QJsonValue::Undefined};
+ }
+ }
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h
index d8e121524d..37d84f9e60 100644
--- a/src/corelib/serialization/qjsonvalue.h
+++ b/src/corelib/serialization/qjsonvalue.h
@@ -92,7 +92,7 @@ public:
QJsonValue(const QJsonValue &other);
QJsonValue &operator =(const QJsonValue &other);
- QJsonValue(QJsonValue &&other) Q_DECL_NOTHROW
+ QJsonValue(QJsonValue &&other) noexcept
: ui(other.ui),
d(other.d),
t(other.t)
@@ -102,13 +102,13 @@ public:
other.t = Null;
}
- QJsonValue &operator =(QJsonValue &&other) Q_DECL_NOTHROW
+ QJsonValue &operator =(QJsonValue &&other) noexcept
{
swap(other);
return *this;
}
- void swap(QJsonValue &other) Q_DECL_NOTHROW
+ void swap(QJsonValue &other) noexcept
{
qSwap(ui, other.ui);
qSwap(d, other.d);
@@ -152,6 +152,7 @@ private:
friend class QJsonObject;
friend class QCborValue;
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonValue &);
QJsonValue(QJsonPrivate::Data *d, QJsonPrivate::Base *b, const QJsonPrivate::Value& v);
void stringDataFromQStringHelper(const QString &string);
@@ -218,7 +219,6 @@ private:
uint index : 31;
};
-#ifndef Q_QDOC
// ### Qt 6: Get rid of these fake pointer classes
class QJsonValuePtr
{
@@ -243,7 +243,6 @@ public:
QJsonValueRef& operator*() { return valueRef; }
QJsonValueRef* operator->() { return &valueRef; }
};
-#endif
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonValue)
@@ -253,6 +252,11 @@ Q_CORE_EXPORT uint qHash(const QJsonValue &value, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonValue &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonValue &);
+#endif
+
QT_END_NAMESPACE
#endif // QJSONVALUE_H
diff --git a/src/corelib/serialization/qjsonwriter.cpp b/src/corelib/serialization/qjsonwriter.cpp
index 12ce20ef09..5b246837d2 100644
--- a/src/corelib/serialization/qjsonwriter.cpp
+++ b/src/corelib/serialization/qjsonwriter.cpp
@@ -58,7 +58,6 @@ static inline uchar hexdig(uint u)
static QByteArray escapedString(const QString &s)
{
- const uchar replacement = '?';
QByteArray ba(s.length(), Qt::Uninitialized);
uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(ba.constData()));
@@ -111,9 +110,14 @@ static QByteArray escapedString(const QString &s)
} else {
*cursor++ = (uchar)u;
}
- } else {
- if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, cursor, src, end) < 0)
- *cursor++ = replacement;
+ } else if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, cursor, src, end) < 0) {
+ // failed to get valid utf8 use JSON escape sequence
+ *cursor++ = '\\';
+ *cursor++ = 'u';
+ *cursor++ = hexdig(u>>12 & 0x0f);
+ *cursor++ = hexdig(u>>8 & 0x0f);
+ *cursor++ = hexdig(u>>4 & 0x0f);
+ *cursor++ = hexdig(u & 0x0f);
}
}
diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp
index fb7b677b2d..9d4bc223ab 100644
--- a/src/corelib/serialization/qtextstream.cpp
+++ b/src/corelib/serialization/qtextstream.cpp
@@ -135,30 +135,30 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
\table
\header \li Manipulator \li Description
- \row \li \c bin \li Same as setIntegerBase(2).
- \row \li \c oct \li Same as setIntegerBase(8).
- \row \li \c dec \li Same as setIntegerBase(10).
- \row \li \c hex \li Same as setIntegerBase(16).
- \row \li \c showbase \li Same as setNumberFlags(numberFlags() | ShowBase).
- \row \li \c forcesign \li Same as setNumberFlags(numberFlags() | ForceSign).
- \row \li \c forcepoint \li Same as setNumberFlags(numberFlags() | ForcePoint).
- \row \li \c noshowbase \li Same as setNumberFlags(numberFlags() & ~ShowBase).
- \row \li \c noforcesign \li Same as setNumberFlags(numberFlags() & ~ForceSign).
- \row \li \c noforcepoint \li Same as setNumberFlags(numberFlags() & ~ForcePoint).
- \row \li \c uppercasebase \li Same as setNumberFlags(numberFlags() | UppercaseBase).
- \row \li \c uppercasedigits \li Same as setNumberFlags(numberFlags() | UppercaseDigits).
- \row \li \c lowercasebase \li Same as setNumberFlags(numberFlags() & ~UppercaseBase).
- \row \li \c lowercasedigits \li Same as setNumberFlags(numberFlags() & ~UppercaseDigits).
- \row \li \c fixed \li Same as setRealNumberNotation(FixedNotation).
- \row \li \c scientific \li Same as setRealNumberNotation(ScientificNotation).
- \row \li \c left \li Same as setFieldAlignment(AlignLeft).
- \row \li \c right \li Same as setFieldAlignment(AlignRight).
- \row \li \c center \li Same as setFieldAlignment(AlignCenter).
- \row \li \c endl \li Same as operator<<('\\n') and flush().
- \row \li \c flush \li Same as flush().
- \row \li \c reset \li Same as reset().
- \row \li \c ws \li Same as skipWhiteSpace().
- \row \li \c bom \li Same as setGenerateByteOrderMark(true).
+ \row \li \c Qt::bin \li Same as setIntegerBase(2).
+ \row \li \c Qt::oct \li Same as setIntegerBase(8).
+ \row \li \c Qt::dec \li Same as setIntegerBase(10).
+ \row \li \c Qt::hex \li Same as setIntegerBase(16).
+ \row \li \c Qt::showbase \li Same as setNumberFlags(numberFlags() | ShowBase).
+ \row \li \c Qt::forcesign \li Same as setNumberFlags(numberFlags() | ForceSign).
+ \row \li \c Qt::forcepoint \li Same as setNumberFlags(numberFlags() | ForcePoint).
+ \row \li \c Qt::noshowbase \li Same as setNumberFlags(numberFlags() & ~ShowBase).
+ \row \li \c Qt::noforcesign \li Same as setNumberFlags(numberFlags() & ~ForceSign).
+ \row \li \c Qt::noforcepoint \li Same as setNumberFlags(numberFlags() & ~ForcePoint).
+ \row \li \c Qt::uppercasebase \li Same as setNumberFlags(numberFlags() | UppercaseBase).
+ \row \li \c Qt::uppercasedigits \li Same as setNumberFlags(numberFlags() | UppercaseDigits).
+ \row \li \c Qt::lowercasebase \li Same as setNumberFlags(numberFlags() & ~UppercaseBase).
+ \row \li \c Qt::lowercasedigits \li Same as setNumberFlags(numberFlags() & ~UppercaseDigits).
+ \row \li \c Qt::fixed \li Same as setRealNumberNotation(FixedNotation).
+ \row \li \c Qt::scientific \li Same as setRealNumberNotation(ScientificNotation).
+ \row \li \c Qt::left \li Same as setFieldAlignment(AlignLeft).
+ \row \li \c Qt::right \li Same as setFieldAlignment(AlignRight).
+ \row \li \c Qt::center \li Same as setFieldAlignment(AlignCenter).
+ \row \li \c Qt::endl \li Same as operator<<('\\n') and flush().
+ \row \li \c Qt::flush \li Same as flush().
+ \row \li \c Qt::reset \li Same as reset().
+ \row \li \c Qt::ws \li Same as skipWhiteSpace().
+ \row \li \c Qt::bom \li Same as setGenerateByteOrderMark(true).
\endtable
In addition, Qt provides three global manipulators that take a
@@ -327,7 +327,7 @@ QT_BEGIN_NAMESPACE
QTextStreamPrivate::QTextStreamPrivate(QTextStream *q_ptr)
:
#if QT_CONFIG(textcodec)
- readConverterSavedState(0),
+ readConverterSavedState(nullptr),
#endif
readConverterSavedStateOffset(0),
locale(QLocale::c())
@@ -381,7 +381,7 @@ void QTextStreamPrivate::Params::reset()
padChar = QLatin1Char(' ');
fieldAlignment = QTextStream::AlignRight;
realNumberNotation = QTextStream::SmartNotation;
- numberFlags = 0;
+ numberFlags = { };
}
/*!
@@ -391,9 +391,9 @@ void QTextStreamPrivate::reset()
{
params.reset();
- device = 0;
+ device = nullptr;
deleteDevice = false;
- string = 0;
+ string = nullptr;
stringOffset = 0;
stringOpenMode = QIODevice::NotOpen;
@@ -406,7 +406,7 @@ void QTextStreamPrivate::reset()
resetCodecConverterStateHelper(&readConverterState);
resetCodecConverterStateHelper(&writeConverterState);
delete readConverterSavedState;
- readConverterSavedState = 0;
+ readConverterSavedState = nullptr;
writeConverterState.flags |= QTextCodec::IgnoreHeader;
autoDetectUnicode = true;
#endif
@@ -1207,7 +1207,7 @@ bool QTextStream::seek(qint64 pos)
resetCodecConverterStateHelper(&d->readConverterState);
resetCodecConverterStateHelper(&d->writeConverterState);
delete d->readConverterSavedState;
- d->readConverterSavedState = 0;
+ d->readConverterSavedState = nullptr;
d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
#endif
return true;
@@ -1295,7 +1295,7 @@ void QTextStream::skipWhiteSpace()
{
Q_D(QTextStream);
CHECK_VALID_STREAM(Q_VOID);
- d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->scan(nullptr, nullptr, 0, QTextStreamPrivate::NotSpace);
d->consumeLastToken();
}
@@ -1332,7 +1332,7 @@ void QTextStream::setDevice(QIODevice *device)
/*!
Returns the current device associated with the QTextStream,
- or 0 if no device has been assigned.
+ or \nullptr if no device has been assigned.
\sa setDevice(), string()
*/
@@ -1369,8 +1369,8 @@ void QTextStream::setString(QString *string, QIODevice::OpenMode openMode)
}
/*!
- Returns the current string assigned to the QTextStream, or 0 if no
- string has been assigned.
+ Returns the current string assigned to the QTextStream, or
+ \nullptr if no string has been assigned.
\sa setString(), device()
*/
@@ -1751,7 +1751,7 @@ QString QTextStream::read(qint64 maxlen)
*/
QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong *ret)
{
- scan(0, 0, 0, NotSpace);
+ scan(nullptr, nullptr, 0, NotSpace);
consumeLastToken();
// detect int encoding
@@ -1980,7 +1980,7 @@ bool QTextStreamPrivate::getReal(double *f)
ParserState state = Init;
InputToken input = None;
- scan(0, 0, 0, NotSpace);
+ scan(nullptr, nullptr, 0, NotSpace);
consumeLastToken();
const int BufferSize = 128;
@@ -2084,7 +2084,7 @@ QTextStream &QTextStream::operator>>(QChar &c)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
- d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->scan(nullptr, nullptr, 0, QTextStreamPrivate::NotSpace);
if (!d->getChar(&c))
setStatus(ReadPastEnd);
return *this;
@@ -2245,7 +2245,7 @@ QTextStream &QTextStream::operator>>(QString &str)
CHECK_VALID_STREAM(*this);
str.clear();
- d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->scan(nullptr, nullptr, 0, QTextStreamPrivate::NotSpace);
d->consumeLastToken();
const QChar *ptr;
@@ -2273,7 +2273,7 @@ QTextStream &QTextStream::operator>>(QByteArray &array)
CHECK_VALID_STREAM(*this);
array.clear();
- d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->scan(nullptr, nullptr, 0, QTextStreamPrivate::NotSpace);
d->consumeLastToken();
const QChar *ptr;
@@ -2308,7 +2308,7 @@ QTextStream &QTextStream::operator>>(char *c)
Q_D(QTextStream);
*c = 0;
CHECK_VALID_STREAM(*this);
- d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->scan(nullptr, nullptr, 0, QTextStreamPrivate::NotSpace);
d->consumeLastToken();
const QChar *ptr;
@@ -2356,7 +2356,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
} else if (negative) {
// Workaround for backward compatibility for writing negative
// numbers in octal and hex:
- // QTextStream(result) << showbase << hex << -1 << oct << -1
+ // QTextStream(result) << Qt::showbase << Qt::hex << -1 << oct << -1
// should output: -0x1 -0b1
result = dd->unsLongLongToString(number, -1, base, -1, flags);
result.prepend(locale.negativeSign());
@@ -2689,6 +2689,11 @@ QTextStream &QTextStream::operator<<(const void *ptr)
d->params.numberFlags = oldFlags;
return *this;
}
+#if defined(Q_QDOC) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+namespace Qt {
+#else
+namespace QTextStreamFunctions {
+#endif
/*!
\relates QTextStream
@@ -2973,7 +2978,7 @@ QTextStream &center(QTextStream &stream)
*/
QTextStream &endl(QTextStream &stream)
{
- return stream << QLatin1Char('\n') << flush;
+ return stream << QLatin1Char('\n') << Qt::flush;
}
/*!
@@ -3015,6 +3020,8 @@ QTextStream &ws(QTextStream &stream)
return stream;
}
+} // namespace QTextStreamFunctions
+
/*!
\fn QTextStreamManipulator qSetFieldWidth(int width)
\relates QTextStream
@@ -3037,6 +3044,12 @@ QTextStream &ws(QTextStream &stream)
*/
#if QT_CONFIG(textcodec)
+
+#if defined(Q_QDOC) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+namespace Qt {
+#else
+namespace QTextStreamFunctions {
+#endif
/*!
\relates QTextStream
@@ -3051,6 +3064,8 @@ QTextStream &bom(QTextStream &stream)
return stream;
}
+} // namespace QTextStreamFunctions
+
/*!
Sets the codec for this stream to \a codec. The codec is used for
decoding any data that is read from the assigned device, and for
@@ -3200,6 +3215,43 @@ QLocale QTextStream::locale() const
return d->locale;
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC)
+// Binary compatible definitions for Qt<5.14
+Q_CORE_EXPORT QTextStream &bin(QTextStream &s) { return Qt::bin(s); }
+Q_CORE_EXPORT QTextStream &oct(QTextStream &s) { return Qt::oct(s); }
+Q_CORE_EXPORT QTextStream &dec(QTextStream &s) { return Qt::dec(s); }
+Q_CORE_EXPORT QTextStream &hex(QTextStream &s) { return Qt::hex(s); }
+
+Q_CORE_EXPORT QTextStream &showbase(QTextStream &s) { return Qt::showbase(s); }
+Q_CORE_EXPORT QTextStream &forcesign(QTextStream &s) { return Qt::forcesign(s); }
+Q_CORE_EXPORT QTextStream &forcepoint(QTextStream &s) { return Qt::forcepoint(s); }
+Q_CORE_EXPORT QTextStream &noshowbase(QTextStream &s) { return Qt::noshowbase(s); }
+Q_CORE_EXPORT QTextStream &noforcesign(QTextStream &s) { return Qt::noforcesign(s); }
+Q_CORE_EXPORT QTextStream &noforcepoint(QTextStream &s) { return Qt::noforcepoint(s); }
+
+Q_CORE_EXPORT QTextStream &uppercasebase(QTextStream &s) { return Qt::uppercasebase(s); }
+Q_CORE_EXPORT QTextStream &uppercasedigits(QTextStream &s) { return Qt::uppercasedigits(s); }
+Q_CORE_EXPORT QTextStream &lowercasebase(QTextStream &s) { return Qt::lowercasebase(s); }
+Q_CORE_EXPORT QTextStream &lowercasedigits(QTextStream &s) { return Qt::lowercasedigits(s); }
+
+Q_CORE_EXPORT QTextStream &fixed(QTextStream &s) { return Qt::fixed(s); }
+Q_CORE_EXPORT QTextStream &scientific(QTextStream &s) { return Qt::scientific(s); }
+
+Q_CORE_EXPORT QTextStream &left(QTextStream &s) { return Qt::left(s); }
+Q_CORE_EXPORT QTextStream &right(QTextStream &s) { return Qt::right(s); }
+Q_CORE_EXPORT QTextStream &center(QTextStream &s) { return Qt::center(s); }
+
+Q_CORE_EXPORT QTextStream &endl(QTextStream &s) { return Qt::endl(s); }
+Q_CORE_EXPORT QTextStream &flush(QTextStream &s) { return Qt::flush(s); }
+Q_CORE_EXPORT QTextStream &reset(QTextStream &s) { return Qt::reset(s); }
+
+Q_CORE_EXPORT QTextStream &ws(QTextStream &s) { return Qt::ws(s); }
+
+#if QT_CONFIG(textcodec)
+Q_CORE_EXPORT QTextStream &bom(QTextStream &s) { return Qt::bom(s); }
+#endif
+#endif
+
QT_END_NAMESPACE
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/serialization/qtextstream.h b/src/corelib/serialization/qtextstream.h
index 1d86a18b9c..4efa84f1f1 100644
--- a/src/corelib/serialization/qtextstream.h
+++ b/src/corelib/serialization/qtextstream.h
@@ -213,8 +213,8 @@ typedef void (QTextStream::*QTSMFC)(QChar); // manipulator w/QChar argument
class Q_CORE_EXPORT QTextStreamManipulator
{
public:
- Q_DECL_CONSTEXPR QTextStreamManipulator(QTSMFI m, int a) Q_DECL_NOTHROW : mf(m), mc(nullptr), arg(a), ch() {}
- Q_DECL_CONSTEXPR QTextStreamManipulator(QTSMFC m, QChar c) Q_DECL_NOTHROW : mf(nullptr), mc(m), arg(-1), ch(c) {}
+ Q_DECL_CONSTEXPR QTextStreamManipulator(QTSMFI m, int a) noexcept : mf(m), mc(nullptr), arg(a), ch() {}
+ Q_DECL_CONSTEXPR QTextStreamManipulator(QTSMFC m, QChar c) noexcept : mf(nullptr), mc(m), arg(-1), ch(c) {}
void exec(QTextStream &s) { if (mf) { (s.*mf)(arg); } else { (s.*mc)(ch); } }
private:
@@ -233,6 +233,13 @@ inline QTextStream &operator<<(QTextStream &s, QTextStreamFunction f)
inline QTextStream &operator<<(QTextStream &s, QTextStreamManipulator m)
{ m.exec(s); return s; }
+#if defined(Q_QDOC) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+namespace Qt {
+#else
+// This namespace only exists for 'using namespace' declarations.
+namespace QTextStreamFunctions {
+#endif
+
Q_CORE_EXPORT QTextStream &bin(QTextStream &s);
Q_CORE_EXPORT QTextStream &oct(QTextStream &s);
Q_CORE_EXPORT QTextStream &dec(QTextStream &s);
@@ -265,6 +272,18 @@ Q_CORE_EXPORT QTextStream &bom(QTextStream &s);
Q_CORE_EXPORT QTextStream &ws(QTextStream &s);
+} // namespace QTextStreamFunctions
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC)
+namespace Qt {
+using namespace QTextStreamFunctions;
+}
+
+// We use 'using namespace' as that doesn't cause
+// conflicting definitions compiler errors.
+using namespace QTextStreamFunctions;
+#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC)
+
inline QTextStreamManipulator qSetFieldWidth(int width)
{
QTSMFI func = &QTextStream::setFieldWidth;
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index 827996ee2d..be3a476cb2 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -58,9 +58,9 @@
// case for most bootstrapped applications.
#define Q_DECLARE_TR_FUNCTIONS(context) \
public: \
- static inline QString tr(const char *sourceText, const char *comment = 0) \
+ static inline QString tr(const char *sourceText, const char *comment = nullptr) \
{ Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
- static inline QString trUtf8(const char *sourceText, const char *comment = 0) \
+ static inline QString trUtf8(const char *sourceText, const char *comment = nullptr) \
{ Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
static inline QString tr(const char *sourceText, const char*, int) \
{ return QString::fromLatin1(sourceText); } \
@@ -223,7 +223,7 @@ QString QXmlStreamReaderPrivate::resolveUndeclaredEntity(const QString &name)
The stream reader does \e not take ownership of the resolver. It's
the callers responsibility to ensure that the resolver is valid
during the entire life-time of the stream reader object, or until
- another resolver or 0 is set.
+ another resolver or \nullptr is set.
\sa entityResolver()
*/
@@ -236,7 +236,7 @@ void QXmlStreamReader::setEntityResolver(QXmlStreamEntityResolver *resolver)
/*!
\since 4.4
- Returns the entity resolver, or 0 if there is no entity resolver.
+ Returns the entity resolver, or \nullptr if there is no entity resolver.
\sa setEntityResolver()
*/
@@ -480,7 +480,7 @@ void QXmlStreamReader::setDevice(QIODevice *device)
/*!
Returns the current device associated with the QXmlStreamReader,
- or 0 if no device has been assigned.
+ or \nullptr if no device has been assigned.
\sa setDevice()
*/
@@ -548,7 +548,7 @@ void QXmlStreamReader::clear()
if (d->device) {
if (d->deleteDevice)
delete d->device;
- d->device = 0;
+ d->device = nullptr;
}
}
@@ -792,16 +792,16 @@ QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
:q_ptr(q)
{
- device = 0;
+ device = nullptr;
deleteDevice = false;
#if QT_CONFIG(textcodec)
- decoder = 0;
+ decoder = nullptr;
#endif
stack_size = 64;
- sym_stack = 0;
- state_stack = 0;
+ sym_stack = nullptr;
+ state_stack = nullptr;
reallocateStack();
- entityResolver = 0;
+ entityResolver = nullptr;
init();
#define ADD_PREDEFINED(n, v) \
do { \
@@ -843,11 +843,11 @@ void QXmlStreamReaderPrivate::init()
#if QT_CONFIG(textcodec)
codec = QTextCodec::codecForMib(106); // utf8
delete decoder;
- decoder = 0;
+ decoder = nullptr;
#endif
attributeStack.clear();
attributeStack.reserve(16);
- entityParser = 0;
+ entityParser = nullptr;
hasCheckedStartDocument = false;
normalizeLiterals = false;
hasSeenTag = false;
@@ -2285,12 +2285,14 @@ QXmlStreamAttribute::QXmlStreamAttribute()
m_isDefault = false;
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
/*!
Destructs an attribute.
*/
QXmlStreamAttribute::~QXmlStreamAttribute()
{
}
+#endif
/*! Constructs an attribute in the namespace described with \a
namespaceUri with \a name and value \a value.
@@ -2366,6 +2368,7 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QSt
*/
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
/*!
Creates a copy of \a other.
*/
@@ -2386,7 +2389,7 @@ QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &o
m_isDefault = other.m_isDefault;
return *this;
}
-
+#endif
/*!
\class QXmlStreamAttributes
@@ -2442,6 +2445,8 @@ QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &o
QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration()
{
}
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
/*!
Creates a copy of \a other.
*/
@@ -2467,6 +2472,7 @@ Destructs this notation declaration.
QXmlStreamNotationDeclaration::~QXmlStreamNotationDeclaration()
{
}
+#endif
/*! \fn QStringRef QXmlStreamNotationDeclaration::name() const
@@ -2539,6 +2545,7 @@ QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QString &pr
m_namespaceUri = namespaceUri;
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
/*!
Creates a copy of \a other.
*/
@@ -2562,6 +2569,7 @@ Destructs this namespace declaration.
QXmlStreamNamespaceDeclaration::~QXmlStreamNamespaceDeclaration()
{
}
+#endif
/*! \fn QStringRef QXmlStreamNamespaceDeclaration::prefix() const
@@ -2609,6 +2617,7 @@ QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration()
{
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
/*!
Creates a copy of \a other.
*/
@@ -2636,6 +2645,7 @@ QXmlStreamEntityDeclaration& QXmlStreamEntityDeclaration::operator=(const QXmlSt
QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration()
{
}
+#endif
/*! \fn QXmlStreamStringRef::swap(QXmlStreamStringRef &other)
\since 5.6
@@ -3014,8 +3024,8 @@ QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
:autoFormattingIndent(4, ' ')
{
q_ptr = q;
- device = 0;
- stringDevice = 0;
+ device = nullptr;
+ stringDevice = nullptr;
deleteDevice = false;
#if QT_CONFIG(textcodec)
codec = QTextCodec::codecForMib(106); // utf8
@@ -3305,7 +3315,7 @@ void QXmlStreamWriter::setDevice(QIODevice *device)
Q_D(QXmlStreamWriter);
if (device == d->device)
return;
- d->stringDevice = 0;
+ d->stringDevice = nullptr;
if (d->deleteDevice) {
delete d->device;
d->deleteDevice = false;
@@ -3315,7 +3325,7 @@ void QXmlStreamWriter::setDevice(QIODevice *device)
/*!
Returns the current device associated with the QXmlStreamWriter,
- or 0 if no device has been assigned.
+ or \nullptr if no device has been assigned.
\sa setDevice()
*/
diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
index 10bfcd491c..12ecc9bdb2 100644
--- a/src/corelib/serialization/qxmlstream.g
+++ b/src/corelib/serialization/qxmlstream.g
@@ -41,6 +41,8 @@
%merged_output qxmlstream_p.h
+%expect 4
+
%token NOTOKEN
%token SPACE " "
%token LANGLE "<"
@@ -144,7 +146,12 @@
%start document
+
+
/.
+
+#include <QtCore/private/qglobal_p.h>
+
template <typename T> class QXmlStreamSimpleStack {
T *data;
int tos, cap;
@@ -155,7 +162,8 @@ public:
inline void reserve(int extraCapacity) {
if (tos + extraCapacity + 1 > cap) {
cap = qMax(tos + extraCapacity + 1, cap << 1 );
- data = reinterpret_cast<T *>(realloc(data, cap * sizeof(T)));
+ void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
+ data = reinterpret_cast<T *>(ptr);
Q_CHECK_PTR(data);
}
}
@@ -498,7 +506,7 @@ public:
int fastScanLiteralContent();
int fastScanSpace();
int fastScanContentCharList();
- int fastScanName(int *prefix = 0);
+ int fastScanName(int *prefix = nullptr);
inline int fastScanNMTOKEN();
@@ -753,7 +761,7 @@ bool QXmlStreamReaderPrivate::parse()
state_stack[tos] = 0;
return true;
} else if (act > 0) {
- if (++tos == stack_size-1)
+ if (++tos >= stack_size-1)
reallocateStack();
Value &val = sym_stack[tos];
@@ -890,7 +898,7 @@ doctype_decl ::= langle_bang DOCTYPE qname markup space_opt RANGLE;
/.
case $rule_number:
dtdName = symString(3);
- // fall through
+ Q_FALLTHROUGH();
./
doctype_decl ::= doctype_decl_start external_id space_opt markup space_opt RANGLE;
/.
diff --git a/src/corelib/serialization/qxmlstream.h b/src/corelib/serialization/qxmlstream.h
index d30c6bc01f..7d0aa64570 100644
--- a/src/corelib/serialization/qxmlstream.h
+++ b/src/corelib/serialization/qxmlstream.h
@@ -59,19 +59,15 @@ public:
inline QXmlStreamStringRef(const QStringRef &aString)
:m_string(aString.string()?*aString.string():QString()), m_position(aString.position()), m_size(aString.size()){}
QXmlStreamStringRef(const QString &aString) : m_string(aString), m_position(0), m_size(m_string.size()) {}
-#ifdef Q_COMPILER_RVALUE_REFS
- QXmlStreamStringRef(QString &&aString) Q_DECL_NOTHROW : m_string(std::move(aString)), m_position(0), m_size(m_string.size()) {}
-#endif
+ QXmlStreamStringRef(QString &&aString) noexcept : m_string(std::move(aString)), m_position(0), m_size(m_string.size()) {}
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QXmlStreamStringRef(const QXmlStreamStringRef &other) // = default
: m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {}
-#ifdef Q_COMPILER_RVALUE_REFS
- QXmlStreamStringRef(QXmlStreamStringRef &&other) Q_DECL_NOTHROW // = default
+ QXmlStreamStringRef(QXmlStreamStringRef &&other) noexcept // = default
: m_string(std::move(other.m_string)), m_position(other.m_position), m_size(other.m_size) {}
- QXmlStreamStringRef &operator=(QXmlStreamStringRef &&other) Q_DECL_NOTHROW // = default
+ QXmlStreamStringRef &operator=(QXmlStreamStringRef &&other) noexcept // = default
{ swap(other); return *this; }
-#endif
QXmlStreamStringRef &operator=(const QXmlStreamStringRef &other) // = default
{ m_string = other.m_string; m_position = other.m_position; m_size = other.m_size; return *this; }
inline ~QXmlStreamStringRef() {} // ### this prevents (or deprecates) all the move/copy special member functions,
@@ -79,7 +75,7 @@ public:
// ### Qt 5, since that would change the way its passed to functions. In Qt 6, remove all.
#endif // Qt < 6.0
- void swap(QXmlStreamStringRef &other) Q_DECL_NOTHROW
+ void swap(QXmlStreamStringRef &other) noexcept
{
qSwap(m_string, other.m_string);
qSwap(m_position, other.m_position);
@@ -108,11 +104,10 @@ class Q_CORE_EXPORT QXmlStreamAttribute {
public:
QXmlStreamAttribute();
QXmlStreamAttribute(const QString &qualifiedName, const QString &value);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QXmlStreamAttribute(const QXmlStreamAttribute &);
-#ifdef Q_COMPILER_RVALUE_REFS
- QXmlStreamAttribute(QXmlStreamAttribute &&other) Q_DECL_NOTHROW // = default;
+ QXmlStreamAttribute(QXmlStreamAttribute &&other) noexcept // = default;
: m_name(std::move(other.m_name)),
m_namespaceUri(std::move(other.m_namespaceUri)),
m_qualifiedName(std::move(other.m_qualifiedName)),
@@ -122,7 +117,7 @@ public:
{
other.reserved = nullptr;
}
- QXmlStreamAttribute &operator=(QXmlStreamAttribute &&other) Q_DECL_NOTHROW // = default;
+ QXmlStreamAttribute &operator=(QXmlStreamAttribute &&other) noexcept // = default;
{
m_name = std::move(other.m_name);
m_namespaceUri = std::move(other.m_namespaceUri);
@@ -132,7 +127,6 @@ public:
m_isDefault = other.m_isDefault;
return *this;
}
-#endif
QXmlStreamAttribute& operator=(const QXmlStreamAttribute &);
~QXmlStreamAttribute();
#endif // < Qt 6
@@ -197,23 +191,23 @@ class Q_CORE_EXPORT QXmlStreamNamespaceDeclaration {
friend class QXmlStreamReaderPrivate;
public:
QXmlStreamNamespaceDeclaration();
+ QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &);
- QXmlStreamNamespaceDeclaration(QXmlStreamNamespaceDeclaration &&other) Q_DECL_NOTHROW // = default
+ QXmlStreamNamespaceDeclaration(QXmlStreamNamespaceDeclaration &&other) noexcept // = default
: m_prefix(std::move(other.m_prefix)),
m_namespaceUri(std::move(other.m_namespaceUri)),
reserved(other.reserved)
{
other.reserved = nullptr;
}
- QXmlStreamNamespaceDeclaration &operator=(QXmlStreamNamespaceDeclaration &&other) Q_DECL_NOTHROW // = default
+ QXmlStreamNamespaceDeclaration &operator=(QXmlStreamNamespaceDeclaration &&other) noexcept // = default
{
m_prefix = std::move(other.m_prefix);
m_namespaceUri = std::move(other.m_namespaceUri);
qSwap(reserved, other.reserved);
return *this;
}
- QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri);
~QXmlStreamNamespaceDeclaration();
QXmlStreamNamespaceDeclaration& operator=(const QXmlStreamNamespaceDeclaration &);
#endif // < Qt 6
@@ -242,7 +236,7 @@ public:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
~QXmlStreamNotationDeclaration();
QXmlStreamNotationDeclaration(const QXmlStreamNotationDeclaration &);
- QXmlStreamNotationDeclaration(QXmlStreamNotationDeclaration &&other) Q_DECL_NOTHROW // = default
+ QXmlStreamNotationDeclaration(QXmlStreamNotationDeclaration &&other) noexcept // = default
: m_name(std::move(other.m_name)),
m_systemId(std::move(other.m_systemId)),
m_publicId(std::move(other.m_publicId)),
@@ -251,7 +245,7 @@ public:
other.reserved = nullptr;
}
QXmlStreamNotationDeclaration& operator=(const QXmlStreamNotationDeclaration &);
- QXmlStreamNotationDeclaration &operator=(QXmlStreamNotationDeclaration &&other) Q_DECL_NOTHROW // = default
+ QXmlStreamNotationDeclaration &operator=(QXmlStreamNotationDeclaration &&other) noexcept // = default
{
m_name = std::move(other.m_name);
m_systemId = std::move(other.m_systemId);
@@ -287,7 +281,7 @@ public:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
~QXmlStreamEntityDeclaration();
QXmlStreamEntityDeclaration(const QXmlStreamEntityDeclaration &);
- QXmlStreamEntityDeclaration(QXmlStreamEntityDeclaration &&other) Q_DECL_NOTHROW // = default
+ QXmlStreamEntityDeclaration(QXmlStreamEntityDeclaration &&other) noexcept // = default
: m_name(std::move(other.m_name)),
m_notationName(std::move(other.m_notationName)),
m_systemId(std::move(other.m_systemId)),
@@ -298,7 +292,7 @@ public:
other.reserved = nullptr;
}
QXmlStreamEntityDeclaration& operator=(const QXmlStreamEntityDeclaration &);
- QXmlStreamEntityDeclaration &operator=(QXmlStreamEntityDeclaration &&other) Q_DECL_NOTHROW // = default
+ QXmlStreamEntityDeclaration &operator=(QXmlStreamEntityDeclaration &&other) noexcept // = default
{
m_name = std::move(other.m_name);
m_notationName = std::move(other.m_notationName);
diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
index 61f501f81b..cde66a48a3 100644
--- a/src/corelib/serialization/qxmlstream_p.h
+++ b/src/corelib/serialization/qxmlstream_p.h
@@ -162,12 +162,12 @@ public:
const char *const QXmlStreamReader_Table::spell [] = {
- "end of file", 0, " ", "<", ">", "&", "#", "\'", "\"", "[",
+ "end of file", nullptr, " ", "<", ">", "&", "#", "\'", "\"", "[",
"]", "(", ")", "|", "=", "%", "/", ":", ";", ",",
"-", "+", "*", ".", "?", "!", "[a-zA-Z]", "[0-9]", "[CDATA[", "DOCTYPE",
"ELEMENT", "ATTLIST", "ENTITY", "NOTATION", "SYSTEM", "PUBLIC", "NDATA", "REQUIRED", "IMPLIED", "FIXED",
- "EMPTY", "ANY", "PCDATA", 0, 0, 0, 0, "CDATA", "ID", "IDREF",
- "IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", "<?xml", "version", 0};
+ "EMPTY", "ANY", "PCDATA", nullptr, nullptr, nullptr, nullptr, "CDATA", "ID", "IDREF",
+ "IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", "<?xml", "version", nullptr};
const short QXmlStreamReader_Table::lhs [] = {
57, 57, 59, 59, 59, 59, 59, 59, 59, 59,
@@ -645,7 +645,7 @@ template <typename T> class QXmlStreamSimpleStack {
T *data;
int tos, cap;
public:
- inline QXmlStreamSimpleStack():data(0), tos(-1), cap(0){}
+ inline QXmlStreamSimpleStack():data(nullptr), tos(-1), cap(0){}
inline ~QXmlStreamSimpleStack(){ if (data) free(data); }
inline void reserve(int extraCapacity) {
@@ -995,7 +995,7 @@ public:
int fastScanLiteralContent();
int fastScanSpace();
int fastScanContentCharList();
- int fastScanName(int *prefix = 0);
+ int fastScanName(int *prefix = nullptr);
inline int fastScanNMTOKEN();
diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp
index 1a9ad4601d..0db44bc427 100644
--- a/src/corelib/statemachine/qabstractstate.cpp
+++ b/src/corelib/statemachine/qabstractstate.cpp
@@ -155,7 +155,8 @@ QAbstractState::~QAbstractState()
}
/*!
- Returns this state's parent state, or 0 if the state has no parent state.
+ Returns this state's parent state, or \nullptr if the state has no
+ parent state.
*/
QState *QAbstractState::parentState() const
{
@@ -166,8 +167,8 @@ QState *QAbstractState::parentState() const
}
/*!
- Returns the state machine that this state is part of, or 0 if the state is
- not part of a state machine.
+ Returns the state machine that this state is part of, or \nullptr if
+ the state is not part of a state machine.
*/
QStateMachine *QAbstractState::machine() const
{
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
index ebf33e120a..d841fd3c8b 100644
--- a/src/corelib/statemachine/qabstracttransition.cpp
+++ b/src/corelib/statemachine/qabstracttransition.cpp
@@ -195,8 +195,8 @@ QAbstractTransition::~QAbstractTransition()
}
/*!
- Returns the source state of this transition, or 0 if this transition has no
- source state.
+ Returns the source state of this transition, or \nullptr if this
+ transition has no source state.
*/
QState *QAbstractTransition::sourceState() const
{
@@ -205,14 +205,14 @@ QState *QAbstractTransition::sourceState() const
}
/*!
- Returns the target state of this transition, or 0 if the transition has no
- target.
+ Returns the target state of this transition, or \nullptr if the
+ transition has no target.
*/
QAbstractState *QAbstractTransition::targetState() const
{
Q_D(const QAbstractTransition);
if (d->targetStates.isEmpty())
- return 0;
+ return nullptr;
return d->targetStates.first().data();
}
@@ -325,8 +325,8 @@ void QAbstractTransition::setTransitionType(TransitionType type)
}
/*!
- Returns the state machine that this transition is part of, or 0 if the
- transition is not part of a state machine.
+ Returns the state machine that this transition is part of, or
+ \nullptr if the transition is not part of a state machine.
*/
QStateMachine *QAbstractTransition::machine() const
{
diff --git a/src/corelib/statemachine/qsignaleventgenerator_p.h b/src/corelib/statemachine/qsignaleventgenerator_p.h
index 271f6317bd..72592b8731 100644
--- a/src/corelib/statemachine/qsignaleventgenerator_p.h
+++ b/src/corelib/statemachine/qsignaleventgenerator_p.h
@@ -71,7 +71,7 @@ private:
void execute(void **_a);
private:
- Q_DISABLE_COPY(QSignalEventGenerator)
+ Q_DISABLE_COPY_MOVE(QSignalEventGenerator)
};
QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qsignaltransition_p.h b/src/corelib/statemachine/qsignaltransition_p.h
index 0666e600a4..b3de334677 100644
--- a/src/corelib/statemachine/qsignaltransition_p.h
+++ b/src/corelib/statemachine/qsignaltransition_p.h
@@ -70,7 +70,7 @@ public:
void unregister();
void maybeRegister();
- virtual void callOnTransition(QEvent *e) override;
+ void callOnTransition(QEvent *e) override;
const QObject *sender;
QByteArray signal;
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
index 2531874a87..62dd4f0284 100644
--- a/src/corelib/statemachine/qstate.cpp
+++ b/src/corelib/statemachine/qstate.cpp
@@ -285,7 +285,7 @@ QAbstractState *QState::errorState() const
/*!
Sets this state's error state to be the given \a state. If the error state
- is not set, or if it is set to 0, the state will inherit its parent's error
+ is not set, or if it is set to \nullptr, the state will inherit its parent's error
state recursively. If no error state is set for the state itself or any of
its ancestors, an error will cause the machine to stop executing and an error
will be printed to the console.
@@ -473,7 +473,8 @@ void QState::onExit(QEvent *event)
}
/*!
- Returns this state's initial state, or 0 if the state has no initial state.
+ Returns this state's initial state, or \nullptr if the state has no
+ initial state.
*/
QAbstractState *QState::initialState() const
{
diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h
index 7fb40392e7..ec746caae1 100644
--- a/src/corelib/statemachine/qstate_p.h
+++ b/src/corelib/statemachine/qstate_p.h
@@ -68,14 +68,14 @@ QT_BEGIN_NAMESPACE
struct QPropertyAssignment
{
QPropertyAssignment()
- : object(0), explicitlySet(true) {}
+ : object(nullptr), explicitlySet(true) {}
QPropertyAssignment(QObject *o, const QByteArray &n,
const QVariant &v, bool es = true)
: object(o), propertyName(n), value(v), explicitlySet(es)
{}
bool objectDeleted() const { return !object; }
- void write() const { Q_ASSERT(object != 0); object->setProperty(propertyName, value); }
+ void write() const { Q_ASSERT(object != nullptr); object->setProperty(propertyName, value); }
bool hasTarget(QObject *o, const QByteArray &pn) const
{ return object == o && propertyName == pn; }
@@ -99,8 +99,8 @@ public:
QStatePrivate();
~QStatePrivate();
- static QStatePrivate *get(QState *q) { return q ? q->d_func() : 0; }
- static const QStatePrivate *get(const QState *q) { return q? q->d_func() : 0; }
+ static QStatePrivate *get(QState *q) { return q ? q->d_func() : nullptr; }
+ static const QStatePrivate *get(const QState *q) { return q? q->d_func() : nullptr; }
QList<QAbstractState*> childStates() const;
QList<QHistoryState*> historyStates() const;
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 7388d496d9..3a86d971e2 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -140,6 +140,10 @@ QT_BEGIN_NAMESPACE
no error state applies to the erroneous state, the machine will stop
executing and an error message will be printed to the console.
+ \note Important: setting the \l{ChildMode} of a state machine to parallel (\l{ParallelStates})
+ results in an invalid state machine. It can only be set to (or kept as)
+ \l{ExclusiveStates}.
+
\sa QAbstractState, QAbstractTransition, QState, {The State Machine Framework}
*/
@@ -370,10 +374,11 @@ static QList<QAbstractState *> getEffectiveTargetStates(QAbstractTransition *tra
QList<QAbstractState*> historyConfiguration = QHistoryStatePrivate::get(historyState)->configuration;
if (!historyConfiguration.isEmpty()) {
// There is a saved history, so apply that.
- targets.unite(historyConfiguration.toSet());
+ targets.unite(QSet<QAbstractState *>(historyConfiguration.constBegin(), historyConfiguration.constEnd()));
} else if (QAbstractTransition *defaultTransition = historyState->defaultTransition()) {
// No saved history, take all default transition targets.
- targets.unite(defaultTransition->targetStates().toSet());
+ const auto &targetStates = defaultTransition->targetStates();
+ targets.unite(QSet<QAbstractState *>(targetStates.constBegin(), targetStates.constEnd()));
} else {
// Woops, we found a history state without a default state. That's not valid!
QStateMachinePrivate *m = QStateMachinePrivate::get(historyState->machine());
@@ -384,7 +389,7 @@ static QList<QAbstractState *> getEffectiveTargetStates(QAbstractTransition *tra
}
}
- targetsList = targets.toList();
+ targetsList = targets.values();
cache->insert(transition, targetsList);
return targetsList;
}
@@ -518,7 +523,7 @@ bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState
}
}
-QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states, bool onlyCompound) const
+QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states, bool onlyCompound)
{
if (states.isEmpty())
return 0;
@@ -537,10 +542,16 @@ QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states, bool
if (ok)
return anc;
}
- return 0;
+
+ // Oops, this should never happen! The state machine itself is a common ancestor of all states,
+ // no matter what. But, for the onlyCompound case: we probably have a state machine whose
+ // childMode is set to parallel, which is illegal. However, we're stuck with it (and with
+ // exposing this invalid/dangerous API to users), so recover in the least horrible way.
+ setError(QStateMachine::StateMachineChildModeSetToParallelError, q_func());
+ return q_func(); // make the statemachine the LCA/LCCA (which it should have been anyway)
}
-QState *QStateMachinePrivate::findLCCA(const QList<QAbstractState*> &states) const
+QState *QStateMachinePrivate::findLCCA(const QList<QAbstractState*> &states)
{
return findLCA(states, true);
}
@@ -740,7 +751,7 @@ QList<QAbstractState*> QStateMachinePrivate::computeExitSet(const QList<QAbstrac
{
Q_ASSERT(cache);
- QList<QAbstractState*> statesToExit_sorted = computeExitSet_Unordered(enabledTransitions, cache).toList();
+ QList<QAbstractState*> statesToExit_sorted = computeExitSet_Unordered(enabledTransitions, cache).values();
std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
return statesToExit_sorted;
}
@@ -777,7 +788,7 @@ QSet<QAbstractState*> QStateMachinePrivate::computeExitSet_Unordered(QAbstractTr
// makes the state machine invalid.
if (error == QStateMachine::NoError)
setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState());
- QList<QAbstractState *> lst = pendingErrorStates.toList();
+ QList<QAbstractState *> lst = pendingErrorStates.values();
lst.prepend(t->sourceState());
domain = findLCCA(lst);
@@ -879,7 +890,7 @@ QList<QAbstractState*> QStateMachinePrivate::computeEntrySet(const QList<QAbstra
pendingErrorStatesForDefaultEntry.clear();
}
- QList<QAbstractState*> statesToEnter_sorted = statesToEnter.toList();
+ QList<QAbstractState*> statesToEnter_sorted = statesToEnter.values();
std::sort(statesToEnter_sorted.begin(), statesToEnter_sorted.end(), stateEntryLessThan);
return statesToEnter_sorted;
}
@@ -902,7 +913,7 @@ function getTransitionDomain(t)
*/
QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t,
const QList<QAbstractState *> &effectiveTargetStates,
- CalculationCache *cache) const
+ CalculationCache *cache)
{
Q_ASSERT(cache);
@@ -1483,6 +1494,14 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta
errorString = QStateMachine::tr("No common ancestor for targets and source of transition from state '%1'")
.arg(currentContext->objectName());
break;
+
+ case QStateMachine::StateMachineChildModeSetToParallelError:
+ Q_ASSERT(currentContext != nullptr);
+
+ errorString = QStateMachine::tr("Child mode of state machine '%1' is not 'ExclusiveStates'!")
+ .arg(currentContext->objectName());
+ break;
+
default:
errorString = QStateMachine::tr("Unknown error");
};
@@ -1507,8 +1526,8 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta
addAncestorStatesToEnter(currentErrorState, rootState(), pendingErrorStates, pendingErrorStatesForDefaultEntry);
pendingErrorStates -= configuration;
} else {
- qWarning("Unrecoverable error detected in running state machine: %s",
- qPrintable(errorString));
+ qWarning("Unrecoverable error detected in running state machine: %ls",
+ qUtf16Printable(errorString));
q->stop();
}
}
@@ -1721,8 +1740,8 @@ QAbstractTransition *QStateMachinePrivate::createInitialTransition() const
: QAbstractTransition()
{ setTargetStates(targets); }
protected:
- virtual bool eventTest(QEvent *) override { return true; }
- virtual void onTransition(QEvent *) override {}
+ bool eventTest(QEvent *) override { return true; }
+ void onTransition(QEvent *) override {}
};
QState *root = rootState();
@@ -2444,9 +2463,13 @@ QStateMachine::QStateMachine(QObject *parent)
/*!
\since 5.0
+ \deprecated
Constructs a new state machine with the given \a childMode
and \a parent.
+
+ \warning Do not set the \a childMode to anything else than \l{ExclusiveStates}, otherwise the
+ state machine is invalid, and might work incorrectly!
*/
QStateMachine::QStateMachine(QState::ChildMode childMode, QObject *parent)
: QState(*new QStateMachinePrivate, /*parentState=*/0)
@@ -2454,6 +2477,18 @@ QStateMachine::QStateMachine(QState::ChildMode childMode, QObject *parent)
Q_D(QStateMachine);
d->childMode = childMode;
setParent(parent); // See comment in constructor above
+
+ if (childMode != ExclusiveStates) {
+ //### FIXME for Qt6: remove this constructor completely, and hide the childMode property.
+ // Yes, the StateMachine itself is conceptually a state, but it should only expose a limited
+ // number of properties. The execution algorithm (in the URL below) treats a state machine
+ // as a state, but from an API point of view, it's questionable if the QStateMachine should
+ // inherit from QState.
+ //
+ // See function findLCCA in https://www.w3.org/TR/2014/WD-scxml-20140529/#AlgorithmforSCXMLInterpretation
+ // to see where setting childMode to parallel will break down.
+ qWarning() << "Invalid childMode for QStateMachine" << this;
+ }
}
/*!
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
index e520285437..07781d09a4 100644
--- a/src/corelib/statemachine/qstatemachine.h
+++ b/src/corelib/statemachine/qstatemachine.h
@@ -106,7 +106,8 @@ public:
NoError,
NoInitialStateError,
NoDefaultStateInHistoryStateError,
- NoCommonAncestorForTransitionError
+ NoCommonAncestorForTransitionError,
+ StateMachineChildModeSetToParallelError
};
explicit QStateMachine(QObject *parent = nullptr);
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
index f3366ca5f7..f140023e31 100644
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -108,10 +108,10 @@ public:
~QStateMachinePrivate();
static QStateMachinePrivate *get(QStateMachine *q)
- { return q ? q->d_func() : 0; }
+ { return q ? q->d_func() : nullptr; }
- QState *findLCA(const QList<QAbstractState*> &states, bool onlyCompound = false) const;
- QState *findLCCA(const QList<QAbstractState*> &states) const;
+ QState *findLCA(const QList<QAbstractState*> &states, bool onlyCompound = false);
+ QState *findLCCA(const QList<QAbstractState*> &states);
static bool transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2);
static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2);
@@ -160,7 +160,7 @@ public:
QSet<QAbstractState*> &statesForDefaultEntry, CalculationCache *cache);
QAbstractState *getTransitionDomain(QAbstractTransition *t,
const QList<QAbstractState *> &effectiveTargetStates,
- CalculationCache *cache) const;
+ CalculationCache *cache);
void addDescendantStatesToEnter(QAbstractState *state,
QSet<QAbstractState*> &statesToEnter,
QSet<QAbstractState*> &statesForDefaultEntry);
@@ -218,18 +218,18 @@ public:
QByteArray prop;
// two overloads because friends can't have default arguments
friend uint qHash(const RestorableId &key, uint seed)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(std::declval<QByteArray>())))
+ noexcept(noexcept(qHash(std::declval<QByteArray>())))
{ return qHash(qMakePair(key.obj, key.prop), seed); }
- friend uint qHash(const RestorableId &key) Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(key, 0U)))
+ friend uint qHash(const RestorableId &key) noexcept(noexcept(qHash(key, 0U)))
{ return qHash(key, 0U); }
- friend bool operator==(const RestorableId &lhs, const RestorableId &rhs) Q_DECL_NOTHROW
+ friend bool operator==(const RestorableId &lhs, const RestorableId &rhs) noexcept
{ return lhs.obj == rhs.obj && lhs.prop == rhs.prop; }
- friend bool operator!=(const RestorableId &lhs, const RestorableId &rhs) Q_DECL_NOTHROW
+ friend bool operator!=(const RestorableId &lhs, const RestorableId &rhs) noexcept
{ return !operator==(lhs, rhs); }
public:
- explicit RestorableId(QObject *o, QByteArray p) Q_DECL_NOTHROW : guard(o), obj(o), prop(qMove(p)) {}
- QObject *object() const Q_DECL_NOTHROW { return guard; }
- QByteArray propertyName() const Q_DECL_NOTHROW { return prop; }
+ explicit RestorableId(QObject *o, QByteArray p) noexcept : guard(o), obj(o), prop(std::move(p)) {}
+ QObject *object() const noexcept { return guard; }
+ QByteArray propertyName() const noexcept { return prop; }
};
QHash<QAbstractState*, QHash<RestorableId, QVariant> > registeredRestorablesForState;
bool hasRestorable(QAbstractState *state, QObject *object, const QByteArray &propertyName) const;
@@ -271,7 +271,7 @@ public:
QList<QAbstractAnimation*> handledAnimations;
QList<QAbstractAnimation*> localResetEndValues;
- void swap(InitializeAnimationResult &other) Q_DECL_NOTHROW
+ void swap(InitializeAnimationResult &other) noexcept
{
qSwap(handledAnimations, other.handledAnimations);
qSwap(localResetEndValues, other.localResetEndValues);
@@ -313,7 +313,7 @@ public:
DelayedEvent(QEvent *e, int tid)
: event(e), timerId(tid) {}
DelayedEvent()
- : event(0), timerId(0) {}
+ : event(nullptr), timerId(0) {}
};
QHash<int, DelayedEvent> delayedEvents;
QHash<int, int> timerIdToDelayedEventId;
diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp
index c161bec537..b1a7edad91 100644
--- a/src/corelib/thread/qatomic.cpp
+++ b/src/corelib/thread/qatomic.cpp
@@ -258,12 +258,26 @@
/*!
\fn template <typename T> T QAtomicInteger<T>::load() const
+ \obsolete
+
+ Use loadRelaxed() instead.
Atomically loads the value of this QAtomicInteger using relaxed memory
ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so.
- \sa store(), loadAcquire()
+ \sa storeRelaxed(), loadAcquire()
+*/
+
+/*!
+ \fn template <typename T> T QAtomicInteger<T>::loadRelaxed() const
+ \since 5.14
+
+ Atomically loads the value of this QAtomicInteger using relaxed memory
+ ordering. The value is not modified in any way, but note that there's no
+ guarantee that it remains so.
+
+ \sa storeRelaxed(), loadAcquire()
*/
/*!
@@ -273,16 +287,29 @@
ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so.
- \sa store(), load()
+ \sa storeRelaxed(), loadRelaxed()
*/
/*!
\fn template <typename T> void QAtomicInteger<T>::store(T newValue)
+ \obsolete
+
+ Use storeRelaxed() instead.
Atomically stores the \a newValue value into this atomic type, using
relaxed memory ordering.
- \sa storeRelease(), load()
+ \sa storeRelease(), loadRelaxed()
+*/
+
+/*!
+ \fn template <typename T> void QAtomicInteger<T>::storeRelaxed(T newValue)
+ \since 5.14
+
+ Atomically stores the \a newValue value into this atomic type, using
+ relaxed memory ordering.
+
+ \sa storeRelease(), loadRelaxed()
*/
/*!
@@ -291,7 +318,7 @@
Atomically stores the \a newValue value into this atomic type, using
the "Release" memory ordering.
- \sa store(), load()
+ \sa store(), loadAcquire()
*/
/*!
@@ -303,7 +330,7 @@
value is not modified in any way, but note that there's no guarantee that
it remains so.
- \sa load(), loadAcquire()
+ \sa loadRelaxed(), loadAcquire()
*/
/*!
@@ -314,7 +341,7 @@
sequentially consistent memory ordering if possible; or "Release" ordering
if not. This function returns a reference to this object.
- \sa store(), storeRelease()
+ \sa storeRelaxed(), storeRelease()
*/
/*! \fn template <typename T> bool QAtomicInteger<T>::isReferenceCountingNative()
@@ -1278,31 +1305,59 @@
/*!
\fn template <typename T> T *QAtomicPointer<T>::load() const
+ \obsolete
+
+ Use loadRelaxed() instead.
Atomically loads the value of this QAtomicPointer using relaxed memory
ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so.
- \sa store(), loadAcquire()
+ \sa storeRelaxed(), loadAcquire()
*/
/*!
+ \fn template <typename T> T *QAtomicPointer<T>::loadRelaxed() const
+ \since 5.14
+
+ Atomically loads the value of this QAtomicPointer using relaxed memory
+ ordering. The value is not modified in any way, but note that there's no
+ guarantee that it remains so.
+
+ \sa storeRelaxed(), loadAcquire()
+*/
+
+
+/*!
\fn template <typename T> T *QAtomicPointer<T>::loadAcquire() const
Atomically loads the value of this QAtomicPointer using the "Acquire" memory
ordering. The value is not modified in any way, but note that there's no
guarantee that it remains so.
- \sa store(), load()
+ \sa storeRelease(), loadRelaxed()
*/
/*!
\fn template <typename T> void QAtomicPointer<T>::store(T *newValue)
+ \obsolete
+
+ Use storeRelaxed() instead.
+
+ Atomically stores the \a newValue value into this atomic type, using
+ relaxed memory ordering.
+
+ \sa storeRelease(), loadRelaxed()
+*/
+
+/*!
+ \fn template <typename T> void QAtomicPointer<T>::storeRelaxed(T *newValue)
+ \since 5.14
Atomically stores the \a newValue value into this atomic type, using
relaxed memory ordering.
- \sa storeRelease(), load()
+ \sa storeRelease(), loadRelaxed()
*/
/*!
@@ -1311,7 +1366,7 @@
Atomically stores the \a newValue value into this atomic type, using
the "Release" memory ordering.
- \sa store(), load()
+ \sa storeRelaxed(), loadRelaxed()
*/
/*! \fn template <typename T> bool QAtomicPointer<T>::isTestAndSetNative()
diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h
index f842534c38..a3b9be0729 100644
--- a/src/corelib/thread/qatomic.h
+++ b/src/corelib/thread/qatomic.h
@@ -57,15 +57,15 @@ class QAtomicInteger : public QBasicAtomicInteger<T>
public:
// Non-atomic API
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
- constexpr QAtomicInteger(T value = 0) Q_DECL_NOTHROW : QBasicAtomicInteger<T>(value) {}
+ constexpr QAtomicInteger(T value = 0) noexcept : QBasicAtomicInteger<T>(value) {}
#else
- inline QAtomicInteger(T value = 0) Q_DECL_NOTHROW
+ inline QAtomicInteger(T value = 0) noexcept
{
this->_q_value = value;
}
#endif
- inline QAtomicInteger(const QAtomicInteger &other) Q_DECL_NOTHROW
+ inline QAtomicInteger(const QAtomicInteger &other) noexcept
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
: QBasicAtomicInteger<T>()
#endif
@@ -73,7 +73,7 @@ public:
this->storeRelease(other.loadAcquire());
}
- inline QAtomicInteger &operator=(const QAtomicInteger &other) Q_DECL_NOTHROW
+ inline QAtomicInteger &operator=(const QAtomicInteger &other) noexcept
{
this->storeRelease(other.loadAcquire());
return *this;
@@ -81,8 +81,10 @@ public:
#ifdef Q_CLANG_QDOC
T load() const;
+ T loadRelaxed() const;
T loadAcquire() const;
void store(T newValue);
+ void storeRelaxed(T newValue);
void storeRelease(T newValue);
operator T() const;
@@ -159,7 +161,7 @@ public:
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
constexpr
#endif
- QAtomicInt(int value = 0) Q_DECL_NOTHROW : QAtomicInteger<int>(value) {}
+ QAtomicInt(int value = 0) noexcept : QAtomicInteger<int>(value) {}
};
// High-level atomic pointer operations
@@ -168,14 +170,14 @@ class QAtomicPointer : public QBasicAtomicPointer<T>
{
public:
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
- constexpr QAtomicPointer(T *value = nullptr) Q_DECL_NOTHROW : QBasicAtomicPointer<T>(value) {}
+ constexpr QAtomicPointer(T *value = nullptr) noexcept : QBasicAtomicPointer<T>(value) {}
#else
- inline QAtomicPointer(T *value = nullptr) Q_DECL_NOTHROW
+ inline QAtomicPointer(T *value = nullptr) noexcept
{
- this->store(value);
+ this->storeRelaxed(value);
}
#endif
- inline QAtomicPointer(const QAtomicPointer<T> &other) Q_DECL_NOTHROW
+ inline QAtomicPointer(const QAtomicPointer<T> &other) noexcept
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
: QBasicAtomicPointer<T>()
#endif
@@ -183,7 +185,7 @@ public:
this->storeRelease(other.loadAcquire());
}
- inline QAtomicPointer<T> &operator=(const QAtomicPointer<T> &other) Q_DECL_NOTHROW
+ inline QAtomicPointer<T> &operator=(const QAtomicPointer<T> &other) noexcept
{
this->storeRelease(other.loadAcquire());
return *this;
@@ -255,7 +257,7 @@ inline void qAtomicAssign(T *&d, T *x)
template <typename T>
inline void qAtomicDetach(T *&d)
{
- if (d->ref.load() == 1)
+ if (d->ref.loadRelaxed() == 1)
return;
T *x = d;
d = new T(*d);
diff --git a/src/corelib/thread/qatomic_bootstrap.h b/src/corelib/thread/qatomic_bootstrap.h
index b463f817bd..c4279ee7b1 100644
--- a/src/corelib/thread/qatomic_bootstrap.h
+++ b/src/corelib/thread/qatomic_bootstrap.h
@@ -56,16 +56,16 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
{
typedef T Type;
- static bool ref(T &_q_value) Q_DECL_NOTHROW
+ static bool ref(T &_q_value) noexcept
{
return ++_q_value != 0;
}
- static bool deref(T &_q_value) Q_DECL_NOTHROW
+ static bool deref(T &_q_value) noexcept
{
return --_q_value != 0;
}
- static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW
+ static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
{
if (currentValue)
*currentValue = _q_value;
@@ -76,7 +76,7 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
return false;
}
- static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+ static T fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
{
T tmp = _q_value;
_q_value = newValue;
@@ -84,7 +84,7 @@ template <typename T> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<T> >
}
template <typename AdditiveType> static
- T fetchAndAddRelaxed(T &_q_value, AdditiveType valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelaxed(T &_q_value, AdditiveType valueToAdd) noexcept
{
T returnValue = _q_value;
_q_value += valueToAdd;
diff --git a/src/corelib/thread/qatomic_cxx11.h b/src/corelib/thread/qatomic_cxx11.h
index 2fc0bf5419..7386aee126 100644
--- a/src/corelib/thread/qatomic_cxx11.h
+++ b/src/corelib/thread/qatomic_cxx11.h
@@ -222,43 +222,61 @@ template <typename X> struct QAtomicOps
typedef std::atomic<X> Type;
template <typename T> static inline
- T load(const std::atomic<T> &_q_value) Q_DECL_NOTHROW
+ T load(const std::atomic<T> &_q_value) noexcept
{
return _q_value.load(std::memory_order_relaxed);
}
template <typename T> static inline
- T load(const volatile std::atomic<T> &_q_value) Q_DECL_NOTHROW
+ T load(const volatile std::atomic<T> &_q_value) noexcept
{
return _q_value.load(std::memory_order_relaxed);
}
template <typename T> static inline
- T loadAcquire(const std::atomic<T> &_q_value) Q_DECL_NOTHROW
+ T loadRelaxed(const std::atomic<T> &_q_value) noexcept
+ {
+ return _q_value.load(std::memory_order_relaxed);
+ }
+
+ template <typename T> static inline
+ T loadRelaxed(const volatile std::atomic<T> &_q_value) noexcept
+ {
+ return _q_value.load(std::memory_order_relaxed);
+ }
+
+ template <typename T> static inline
+ T loadAcquire(const std::atomic<T> &_q_value) noexcept
{
return _q_value.load(std::memory_order_acquire);
}
template <typename T> static inline
- T loadAcquire(const volatile std::atomic<T> &_q_value) Q_DECL_NOTHROW
+ T loadAcquire(const volatile std::atomic<T> &_q_value) noexcept
{
return _q_value.load(std::memory_order_acquire);
}
template <typename T> static inline
- void store(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ void store(std::atomic<T> &_q_value, T newValue) noexcept
+ {
+ _q_value.store(newValue, std::memory_order_relaxed);
+ }
+
+ template <typename T> static inline
+ void storeRelaxed(std::atomic<T> &_q_value, T newValue) noexcept
{
_q_value.store(newValue, std::memory_order_relaxed);
}
template <typename T> static inline
- void storeRelease(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ void storeRelease(std::atomic<T> &_q_value, T newValue) noexcept
{
_q_value.store(newValue, std::memory_order_release);
}
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept { return isTestAndSetNative(); }
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept { return false; }
template <typename T>
static inline bool ref(std::atomic<T> &_q_value)
{
@@ -266,17 +284,17 @@ template <typename X> struct QAtomicOps
}
template <typename T>
- static inline bool deref(std::atomic<T> &_q_value) Q_DECL_NOTHROW
+ static inline bool deref(std::atomic<T> &_q_value) noexcept
{
return --_q_value != 0;
}
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept
{ return QAtomicTraits<sizeof(X)>::isLockFree(); }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return false; }
template <typename T>
- static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
+ static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
if (currentValue)
@@ -285,7 +303,7 @@ template <typename X> struct QAtomicOps
}
template <typename T>
- static bool testAndSetAcquire(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
+ static bool testAndSetAcquire(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire, std::memory_order_acquire);
if (currentValue)
@@ -294,7 +312,7 @@ template <typename X> struct QAtomicOps
}
template <typename T>
- static bool testAndSetRelease(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
+ static bool testAndSetRelease(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release, std::memory_order_relaxed);
if (currentValue)
@@ -303,7 +321,7 @@ template <typename X> struct QAtomicOps
}
template <typename T>
- static bool testAndSetOrdered(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW
+ static bool testAndSetOrdered(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel, std::memory_order_acquire);
if (currentValue)
@@ -311,158 +329,158 @@ template <typename X> struct QAtomicOps
return tmp;
}
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return isTestAndSetNative(); }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return false; }
template <typename T>
- static T fetchAndStoreRelaxed(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ static T fetchAndStoreRelaxed(std::atomic<T> &_q_value, T newValue) noexcept
{
return _q_value.exchange(newValue, std::memory_order_relaxed);
}
template <typename T>
- static T fetchAndStoreAcquire(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ static T fetchAndStoreAcquire(std::atomic<T> &_q_value, T newValue) noexcept
{
return _q_value.exchange(newValue, std::memory_order_acquire);
}
template <typename T>
- static T fetchAndStoreRelease(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ static T fetchAndStoreRelease(std::atomic<T> &_q_value, T newValue) noexcept
{
return _q_value.exchange(newValue, std::memory_order_release);
}
template <typename T>
- static T fetchAndStoreOrdered(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
+ static T fetchAndStoreOrdered(std::atomic<T> &_q_value, T newValue) noexcept
{
return _q_value.exchange(newValue, std::memory_order_acq_rel);
}
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return isTestAndSetNative(); }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return false; }
template <typename T> static inline
- T fetchAndAddRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_add(valueToAdd, std::memory_order_relaxed);
}
template <typename T> static inline
- T fetchAndAddAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_add(valueToAdd, std::memory_order_acquire);
}
template <typename T> static inline
- T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_add(valueToAdd, std::memory_order_release);
}
template <typename T> static inline
- T fetchAndAddOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_add(valueToAdd, std::memory_order_acq_rel);
}
template <typename T> static inline
- T fetchAndSubRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_sub(valueToAdd, std::memory_order_relaxed);
}
template <typename T> static inline
- T fetchAndSubAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_sub(valueToAdd, std::memory_order_acquire);
}
template <typename T> static inline
- T fetchAndSubRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_sub(valueToAdd, std::memory_order_release);
}
template <typename T> static inline
- T fetchAndSubOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_sub(valueToAdd, std::memory_order_acq_rel);
}
template <typename T> static inline
- T fetchAndAndRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_and(valueToAdd, std::memory_order_relaxed);
}
template <typename T> static inline
- T fetchAndAndAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_and(valueToAdd, std::memory_order_acquire);
}
template <typename T> static inline
- T fetchAndAndRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_and(valueToAdd, std::memory_order_release);
}
template <typename T> static inline
- T fetchAndAndOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_and(valueToAdd, std::memory_order_acq_rel);
}
template <typename T> static inline
- T fetchAndOrRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_or(valueToAdd, std::memory_order_relaxed);
}
template <typename T> static inline
- T fetchAndOrAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_or(valueToAdd, std::memory_order_acquire);
}
template <typename T> static inline
- T fetchAndOrRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_or(valueToAdd, std::memory_order_release);
}
template <typename T> static inline
- T fetchAndOrOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_or(valueToAdd, std::memory_order_acq_rel);
}
template <typename T> static inline
- T fetchAndXorRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_xor(valueToAdd, std::memory_order_relaxed);
}
template <typename T> static inline
- T fetchAndXorAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_xor(valueToAdd, std::memory_order_acquire);
}
template <typename T> static inline
- T fetchAndXorRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_xor(valueToAdd, std::memory_order_release);
}
template <typename T> static inline
- T fetchAndXorOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return _q_value.fetch_xor(valueToAdd, std::memory_order_acq_rel);
}
};
-#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
+#if defined(Q_COMPILER_CONSTEXPR)
# define Q_BASIC_ATOMIC_INITIALIZER(a) { a }
#else
# define Q_BASIC_ATOMIC_INITIALIZER(a) { ATOMIC_VAR_INIT(a) }
diff --git a/src/corelib/thread/qatomic_msvc.h b/src/corelib/thread/qatomic_msvc.h
index 5eae2bdc48..67b5224cd7 100644
--- a/src/corelib/thread/qatomic_msvc.h
+++ b/src/corelib/thread/qatomic_msvc.h
@@ -269,24 +269,24 @@ template <> struct QAtomicWindowsType<4> { typedef long Type; };
template <int N> struct QAtomicOpsBySize : QGenericAtomicOps<QAtomicOpsBySize<N> >
{
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static bool ref(T &_q_value) Q_DECL_NOTHROW;
- template <typename T> static bool deref(T &_q_value) Q_DECL_NOTHROW;
-
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept { return true; }
+ template <typename T> static bool ref(T &_q_value) noexcept;
+ template <typename T> static bool deref(T &_q_value) noexcept;
+
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return true; }
+ template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept;
template <typename T>
- static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW;
+ static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept;
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return true; }
+ template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept;
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return true; }
- template <typename T> static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return true; }
+ template <typename T> static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept;
private:
typedef typename QAtomicWindowsType<N>::Type Type;
@@ -303,76 +303,76 @@ struct QAtomicOps : QAtomicOpsBySize<sizeof(T)>
};
template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::ref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<4>::ref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Increment)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::deref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<4>::deref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Decrement)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(CompareExchange)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
}
template<> template <typename T>
-inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept
{
*currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange)(atomic(&_q_value), newValue, expectedValue));
return *currentValue == expectedValue;
}
template<> template<typename T>
-inline T QAtomicOpsBySize<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(Exchange)(atomic(&_q_value), value(newValue));
}
template<> template<typename T>
-inline T QAtomicOpsBySize<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return QT_INTERLOCKED_FUNCTION(ExchangeAdd)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
}
#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::ref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<2>::ref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Increment16)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::deref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<2>::deref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Decrement16)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(CompareExchange16)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
}
template<> template <typename T>
-inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept
{
*currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange16)(atomic(&_q_value), newValue, expectedValue));
return *currentValue == expectedValue;
}
template<> template<typename T>
-inline T QAtomicOpsBySize<2>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<2>::fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(Exchange16)(atomic(&_q_value), value(newValue));
}
template<> template<typename T>
-inline T QAtomicOpsBySize<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return QT_INTERLOCKED_FUNCTION(ExchangeAdd16)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
}
@@ -380,38 +380,38 @@ inline T QAtomicOpsBySize<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAd
#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::ref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<8>::ref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Increment64)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::deref(T &_q_value) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<8>::deref(T &_q_value) noexcept
{
return QT_INTERLOCKED_FUNCTION(Decrement64)(atomic(&_q_value)) != 0;
}
template<> template<typename T>
-inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(CompareExchange64)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
}
template<> template <typename T>
-inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
+inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) noexcept
{
*currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange64)(atomic(&_q_value), newValue, expectedValue));
return *currentValue == expectedValue;
}
template<> template<typename T>
-inline T QAtomicOpsBySize<8>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<8>::fetchAndStoreRelaxed(T &_q_value, T newValue) noexcept
{
return QT_INTERLOCKED_FUNCTION(Exchange64)(atomic(&_q_value), value(newValue));
}
template<> template<typename T>
-inline T QAtomicOpsBySize<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+inline T QAtomicOpsBySize<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
return QT_INTERLOCKED_FUNCTION(ExchangeAdd64)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
}
@@ -423,41 +423,41 @@ struct QAtomicOps<T *> : QGenericAtomicOps<QAtomicOps<T *> >
{
typedef T *Type;
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; }
- static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) Q_DECL_NOTHROW;
- static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return true; }
+ static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) noexcept;
+ static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) noexcept;
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; }
- static T *fetchAndStoreRelaxed(T *&_q_value, T *newValue) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return true; }
+ static T *fetchAndStoreRelaxed(T *&_q_value, T *newValue) noexcept;
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return true; }
- static T *fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return true; }
+ static T *fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) noexcept;
};
template <typename T>
-inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) Q_DECL_NOTHROW
+inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) noexcept
{
return QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue) == expectedValue;
}
template <typename T>
-inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) Q_DECL_NOTHROW
+inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) noexcept
{
*currentValue = reinterpret_cast<T *>(QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue));
return *currentValue == expectedValue;
}
template <typename T>
-inline T *QAtomicOps<T *>::fetchAndStoreRelaxed(T *&_q_value, T *newValue) Q_DECL_NOTHROW
+inline T *QAtomicOps<T *>::fetchAndStoreRelaxed(T *&_q_value, T *newValue) noexcept
{
return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, newValue));
}
template <typename T>
-inline T *QAtomicOps<T *>::fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) Q_DECL_NOTHROW
+inline T *QAtomicOps<T *>::fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) noexcept
{
return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_ADD_POINTER(&_q_value, valueToAdd * sizeof(T)));
}
diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h
index 6b6ac10713..9804e60119 100644
--- a/src/corelib/thread/qbasicatomic.h
+++ b/src/corelib/thread/qbasicatomic.h
@@ -75,7 +75,7 @@ QT_END_NAMESPACE
// New atomics
-#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
+#if defined(Q_COMPILER_CONSTEXPR)
# if defined(Q_CC_CLANG) && Q_CC_CLANG < 303
/*
Do not define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS for Clang before version 3.3.
@@ -99,126 +99,130 @@ public:
typename Ops::Type _q_value;
// Everything below is either implemented in ../arch/qatomic_XXX.h or (as fallback) in qgenericatomic.h
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_VERSION_X_5_14("Use loadRelaxed") T load() const noexcept { return loadRelaxed(); }
+ QT_DEPRECATED_VERSION_X_5_14("Use storeRelaxed") void store(T newValue) noexcept { storeRelaxed(newValue); }
+#endif
- T load() const Q_DECL_NOTHROW { return Ops::load(_q_value); }
- void store(T newValue) Q_DECL_NOTHROW { Ops::store(_q_value, newValue); }
+ T loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); }
+ void storeRelaxed(T newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); }
- T loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); }
- void storeRelease(T newValue) Q_DECL_NOTHROW { Ops::storeRelease(_q_value, newValue); }
- operator T() const Q_DECL_NOTHROW { return loadAcquire(); }
- T operator=(T newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; }
+ T loadAcquire() const noexcept { return Ops::loadAcquire(_q_value); }
+ void storeRelease(T newValue) noexcept { Ops::storeRelease(_q_value, newValue); }
+ operator T() const noexcept { return loadAcquire(); }
+ T operator=(T newValue) noexcept { storeRelease(newValue); return newValue; }
- static Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return Ops::isReferenceCountingNative(); }
- static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return Ops::isReferenceCountingWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept { return Ops::isReferenceCountingNative(); }
+ static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept { return Ops::isReferenceCountingWaitFree(); }
- bool ref() Q_DECL_NOTHROW { return Ops::ref(_q_value); }
- bool deref() Q_DECL_NOTHROW { return Ops::deref(_q_value); }
+ bool ref() noexcept { return Ops::ref(_q_value); }
+ bool deref() noexcept { return Ops::deref(_q_value); }
- static Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return Ops::isTestAndSetNative(); }
- static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return Ops::isTestAndSetWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); }
+ static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); }
- bool testAndSetRelaxed(T expectedValue, T newValue) Q_DECL_NOTHROW
+ bool testAndSetRelaxed(T expectedValue, T newValue) noexcept
{ return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); }
- bool testAndSetAcquire(T expectedValue, T newValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(T expectedValue, T newValue) noexcept
{ return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); }
- bool testAndSetRelease(T expectedValue, T newValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(T expectedValue, T newValue) noexcept
{ return Ops::testAndSetRelease(_q_value, expectedValue, newValue); }
- bool testAndSetOrdered(T expectedValue, T newValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(T expectedValue, T newValue) noexcept
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); }
- bool testAndSetRelaxed(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ bool testAndSetRelaxed(T expectedValue, T newValue, T &currentValue) noexcept
{ return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetAcquire(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(T expectedValue, T newValue, T &currentValue) noexcept
{ return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetRelease(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(T expectedValue, T newValue, T &currentValue) noexcept
{ return Ops::testAndSetRelease(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetOrdered(T expectedValue, T newValue, T &currentValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(T expectedValue, T newValue, T &currentValue) noexcept
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return Ops::isFetchAndStoreNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndStoreWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); }
- T fetchAndStoreRelaxed(T newValue) Q_DECL_NOTHROW
+ T fetchAndStoreRelaxed(T newValue) noexcept
{ return Ops::fetchAndStoreRelaxed(_q_value, newValue); }
- T fetchAndStoreAcquire(T newValue) Q_DECL_NOTHROW
+ T fetchAndStoreAcquire(T newValue) noexcept
{ return Ops::fetchAndStoreAcquire(_q_value, newValue); }
- T fetchAndStoreRelease(T newValue) Q_DECL_NOTHROW
+ T fetchAndStoreRelease(T newValue) noexcept
{ return Ops::fetchAndStoreRelease(_q_value, newValue); }
- T fetchAndStoreOrdered(T newValue) Q_DECL_NOTHROW
+ T fetchAndStoreOrdered(T newValue) noexcept
{ return Ops::fetchAndStoreOrdered(_q_value, newValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return Ops::isFetchAndAddNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndAddWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); }
- T fetchAndAddRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); }
- T fetchAndAddAcquire(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddAcquire(T valueToAdd) noexcept
{ return Ops::fetchAndAddAcquire(_q_value, valueToAdd); }
- T fetchAndAddRelease(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelease(T valueToAdd) noexcept
{ return Ops::fetchAndAddRelease(_q_value, valueToAdd); }
- T fetchAndAddOrdered(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddOrdered(T valueToAdd) noexcept
{ return Ops::fetchAndAddOrdered(_q_value, valueToAdd); }
- T fetchAndSubRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); }
- T fetchAndSubAcquire(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubAcquire(T valueToAdd) noexcept
{ return Ops::fetchAndSubAcquire(_q_value, valueToAdd); }
- T fetchAndSubRelease(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubRelease(T valueToAdd) noexcept
{ return Ops::fetchAndSubRelease(_q_value, valueToAdd); }
- T fetchAndSubOrdered(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndSubOrdered(T valueToAdd) noexcept
{ return Ops::fetchAndSubOrdered(_q_value, valueToAdd); }
- T fetchAndAndRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndAndRelaxed(_q_value, valueToAdd); }
- T fetchAndAndAcquire(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndAcquire(T valueToAdd) noexcept
{ return Ops::fetchAndAndAcquire(_q_value, valueToAdd); }
- T fetchAndAndRelease(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndRelease(T valueToAdd) noexcept
{ return Ops::fetchAndAndRelease(_q_value, valueToAdd); }
- T fetchAndAndOrdered(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAndOrdered(T valueToAdd) noexcept
{ return Ops::fetchAndAndOrdered(_q_value, valueToAdd); }
- T fetchAndOrRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndOrRelaxed(_q_value, valueToAdd); }
- T fetchAndOrAcquire(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrAcquire(T valueToAdd) noexcept
{ return Ops::fetchAndOrAcquire(_q_value, valueToAdd); }
- T fetchAndOrRelease(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrRelease(T valueToAdd) noexcept
{ return Ops::fetchAndOrRelease(_q_value, valueToAdd); }
- T fetchAndOrOrdered(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndOrOrdered(T valueToAdd) noexcept
{ return Ops::fetchAndOrOrdered(_q_value, valueToAdd); }
- T fetchAndXorRelaxed(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorRelaxed(T valueToAdd) noexcept
{ return Ops::fetchAndXorRelaxed(_q_value, valueToAdd); }
- T fetchAndXorAcquire(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorAcquire(T valueToAdd) noexcept
{ return Ops::fetchAndXorAcquire(_q_value, valueToAdd); }
- T fetchAndXorRelease(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorRelease(T valueToAdd) noexcept
{ return Ops::fetchAndXorRelease(_q_value, valueToAdd); }
- T fetchAndXorOrdered(T valueToAdd) Q_DECL_NOTHROW
+ T fetchAndXorOrdered(T valueToAdd) noexcept
{ return Ops::fetchAndXorOrdered(_q_value, valueToAdd); }
- T operator++() Q_DECL_NOTHROW
+ T operator++() noexcept
{ return fetchAndAddOrdered(1) + 1; }
- T operator++(int) Q_DECL_NOTHROW
+ T operator++(int) noexcept
{ return fetchAndAddOrdered(1); }
- T operator--() Q_DECL_NOTHROW
+ T operator--() noexcept
{ return fetchAndSubOrdered(1) - 1; }
- T operator--(int) Q_DECL_NOTHROW
+ T operator--(int) noexcept
{ return fetchAndSubOrdered(1); }
- T operator+=(T v) Q_DECL_NOTHROW
+ T operator+=(T v) noexcept
{ return fetchAndAddOrdered(v) + v; }
- T operator-=(T v) Q_DECL_NOTHROW
+ T operator-=(T v) noexcept
{ return fetchAndSubOrdered(v) - v; }
- T operator&=(T v) Q_DECL_NOTHROW
+ T operator&=(T v) noexcept
{ return fetchAndAndOrdered(v) & v; }
- T operator|=(T v) Q_DECL_NOTHROW
+ T operator|=(T v) noexcept
{ return fetchAndOrOrdered(v) | v; }
- T operator^=(T v) Q_DECL_NOTHROW
+ T operator^=(T v) noexcept
{ return fetchAndXorOrdered(v) ^ v; }
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
QBasicAtomicInteger() = default;
- constexpr QBasicAtomicInteger(T value) Q_DECL_NOTHROW : _q_value(value) {}
+ constexpr QBasicAtomicInteger(T value) noexcept : _q_value(value) {}
QBasicAtomicInteger(const QBasicAtomicInteger &) = delete;
QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) = delete;
QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) volatile = delete;
@@ -236,85 +240,91 @@ public:
AtomicType _q_value;
- Type load() const Q_DECL_NOTHROW { return Ops::load(_q_value); }
- void store(Type newValue) Q_DECL_NOTHROW { Ops::store(_q_value, newValue); }
- operator Type() const Q_DECL_NOTHROW { return loadAcquire(); }
- Type operator=(Type newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; }
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_VERSION_X_5_14("Use loadRelaxed") Type load() const noexcept { return loadRelaxed(); }
+ QT_DEPRECATED_VERSION_X_5_14("Use storeRelaxed") void store(Type newValue) noexcept { storeRelaxed(newValue); }
+#endif
+
+ Type loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); }
+ void storeRelaxed(Type newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); }
+
+ operator Type() const noexcept { return loadAcquire(); }
+ Type operator=(Type newValue) noexcept { storeRelease(newValue); return newValue; }
// Atomic API, implemented in qatomic_XXX.h
- Type loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); }
- void storeRelease(Type newValue) Q_DECL_NOTHROW { Ops::storeRelease(_q_value, newValue); }
+ Type loadAcquire() const noexcept { return Ops::loadAcquire(_q_value); }
+ void storeRelease(Type newValue) noexcept { Ops::storeRelease(_q_value, newValue); }
- static Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return Ops::isTestAndSetNative(); }
- static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return Ops::isTestAndSetWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); }
+ static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); }
- bool testAndSetRelaxed(Type expectedValue, Type newValue) Q_DECL_NOTHROW
+ bool testAndSetRelaxed(Type expectedValue, Type newValue) noexcept
{ return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); }
- bool testAndSetAcquire(Type expectedValue, Type newValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(Type expectedValue, Type newValue) noexcept
{ return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); }
- bool testAndSetRelease(Type expectedValue, Type newValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(Type expectedValue, Type newValue) noexcept
{ return Ops::testAndSetRelease(_q_value, expectedValue, newValue); }
- bool testAndSetOrdered(Type expectedValue, Type newValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(Type expectedValue, Type newValue) noexcept
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); }
- bool testAndSetRelaxed(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ bool testAndSetRelaxed(Type expectedValue, Type newValue, Type &currentValue) noexcept
{ return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetAcquire(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(Type expectedValue, Type newValue, Type &currentValue) noexcept
{ return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetRelease(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(Type expectedValue, Type newValue, Type &currentValue) noexcept
{ return Ops::testAndSetRelease(_q_value, expectedValue, newValue, &currentValue); }
- bool testAndSetOrdered(Type expectedValue, Type newValue, Type &currentValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(Type expectedValue, Type newValue, Type &currentValue) noexcept
{ return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return Ops::isFetchAndStoreNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndStoreWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); }
- Type fetchAndStoreRelaxed(Type newValue) Q_DECL_NOTHROW
+ Type fetchAndStoreRelaxed(Type newValue) noexcept
{ return Ops::fetchAndStoreRelaxed(_q_value, newValue); }
- Type fetchAndStoreAcquire(Type newValue) Q_DECL_NOTHROW
+ Type fetchAndStoreAcquire(Type newValue) noexcept
{ return Ops::fetchAndStoreAcquire(_q_value, newValue); }
- Type fetchAndStoreRelease(Type newValue) Q_DECL_NOTHROW
+ Type fetchAndStoreRelease(Type newValue) noexcept
{ return Ops::fetchAndStoreRelease(_q_value, newValue); }
- Type fetchAndStoreOrdered(Type newValue) Q_DECL_NOTHROW
+ Type fetchAndStoreOrdered(Type newValue) noexcept
{ return Ops::fetchAndStoreOrdered(_q_value, newValue); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return Ops::isFetchAndAddNative(); }
- static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndAddWaitFree(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); }
+ static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); }
- Type fetchAndAddRelaxed(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndAddRelaxed(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); }
- Type fetchAndAddAcquire(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndAddAcquire(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndAddAcquire(_q_value, valueToAdd); }
- Type fetchAndAddRelease(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndAddRelease(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndAddRelease(_q_value, valueToAdd); }
- Type fetchAndAddOrdered(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndAddOrdered(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndAddOrdered(_q_value, valueToAdd); }
- Type fetchAndSubRelaxed(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndSubRelaxed(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); }
- Type fetchAndSubAcquire(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndSubAcquire(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndSubAcquire(_q_value, valueToAdd); }
- Type fetchAndSubRelease(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndSubRelease(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndSubRelease(_q_value, valueToAdd); }
- Type fetchAndSubOrdered(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type fetchAndSubOrdered(qptrdiff valueToAdd) noexcept
{ return Ops::fetchAndSubOrdered(_q_value, valueToAdd); }
- Type operator++() Q_DECL_NOTHROW
+ Type operator++() noexcept
{ return fetchAndAddOrdered(1) + 1; }
- Type operator++(int) Q_DECL_NOTHROW
+ Type operator++(int) noexcept
{ return fetchAndAddOrdered(1); }
- Type operator--() Q_DECL_NOTHROW
+ Type operator--() noexcept
{ return fetchAndSubOrdered(1) - 1; }
- Type operator--(int) Q_DECL_NOTHROW
+ Type operator--(int) noexcept
{ return fetchAndSubOrdered(1); }
- Type operator+=(qptrdiff valueToAdd) Q_DECL_NOTHROW
+ Type operator+=(qptrdiff valueToAdd) noexcept
{ return fetchAndAddOrdered(valueToAdd) + valueToAdd; }
- Type operator-=(qptrdiff valueToSub) Q_DECL_NOTHROW
+ Type operator-=(qptrdiff valueToSub) noexcept
{ return fetchAndSubOrdered(valueToSub) - valueToSub; }
#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
QBasicAtomicPointer() = default;
- constexpr QBasicAtomicPointer(Type value) Q_DECL_NOTHROW : _q_value(value) {}
+ constexpr QBasicAtomicPointer(Type value) noexcept : _q_value(value) {}
QBasicAtomicPointer(const QBasicAtomicPointer &) = delete;
QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) = delete;
QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) volatile = delete;
diff --git a/src/corelib/thread/qfutex_p.h b/src/corelib/thread/qfutex_p.h
index 483664c783..7bec4554b7 100644
--- a/src/corelib/thread/qfutex_p.h
+++ b/src/corelib/thread/qfutex_p.h
@@ -81,15 +81,43 @@ QT_END_NAMESPACE
// if not defined in linux/futex.h
# define FUTEX_PRIVATE_FLAG 128 // added in v2.6.22
+# if QT_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+# include <sanitizer/tsan_interface.h>
+inline void _q_tsan_acquire(void *addr, void *addr2)
+{
+ __tsan_acquire(addr);
+ if (addr2)
+ __tsan_acquire(addr2);
+}
+inline void _q_tsan_release(void *addr, void *addr2)
+{
+ if (addr2)
+ __tsan_release(addr2);
+ __tsan_release(addr);
+}
+# else
+inline void _q_tsan_acquire(void *, void *) {}
+inline void _q_tsan_release(void *, void *) {}
+# endif // QT_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+
QT_BEGIN_NAMESPACE
namespace QtLinuxFutex {
constexpr inline bool futexAvailable() { return true; }
inline int _q_futex(int *addr, int op, int val, quintptr val2 = 0,
- int *addr2 = nullptr, int val3 = 0) Q_DECL_NOTHROW
+ int *addr2 = nullptr, int val3 = 0) noexcept
{
+ // A futex call ensures total ordering on the futex words
+ // (in either success or failure of the call). Instruct TSAN accordingly,
+ // as TSAN does not understand the futex(2) syscall.
+ _q_tsan_release(addr, addr2);
+
// we use __NR_futex because some libcs (like Android's bionic) don't
// provide SYS_futex etc.
- return syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
+ int result = syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
+
+ _q_tsan_acquire(addr, addr2);
+
+ return result;
}
template <typename T> int *addr(T *ptr)
{
diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h
index a456dd9139..d3135510b3 100644
--- a/src/corelib/thread/qfuture.h
+++ b/src/corelib/thread/qfuture.h
@@ -111,33 +111,79 @@ public:
typedef const T &reference;
inline const_iterator() {}
- inline const_iterator(QFuture const * const _future, int _index) : future(_future), index(_index) {}
+ inline const_iterator(QFuture const * const _future, int _index)
+ : future(_future), index(advanceIndex(_index, 0)) { }
inline const_iterator(const const_iterator &o) : future(o.future), index(o.index) {}
inline const_iterator &operator=(const const_iterator &o)
{ future = o.future; index = o.index; return *this; }
inline const T &operator*() const { return future->d.resultReference(index); }
inline const T *operator->() const { return future->d.resultPointer(index); }
-
- inline bool operator!=(const const_iterator &other) const
+ inline bool operator!=(const const_iterator &other) const { return index != other.index; }
+ inline bool operator==(const const_iterator &o) const { return !operator!=(o); }
+ inline const_iterator &operator++()
+ { index = advanceIndex(index, 1); return *this; }
+ inline const_iterator &operator--()
+ { index = advanceIndex(index, -1); return *this; }
+ inline const_iterator operator++(int)
+ {
+ const_iterator r = *this;
+ index = advanceIndex(index, 1);
+ return r;
+ }
+ inline const_iterator operator--(int)
{
- if (index == -1 && other.index == -1) // comparing end != end?
- return false;
- if (other.index == -1)
- return (future->isRunning() || (index < future->resultCount()));
- return (index != other.index);
+ const_iterator r = *this;
+ index = advanceIndex(index, -1);
+ return r;
}
+ inline const_iterator operator+(int j) const
+ { return const_iterator(future, advanceIndex(index, j)); }
+ inline const_iterator operator-(int j) const
+ { return const_iterator(future, advanceIndex(index, -j)); }
+ inline const_iterator &operator+=(int j)
+ { index = advanceIndex(index, j); return *this; }
+ inline const_iterator &operator-=(int j)
+ { index = advanceIndex(index, -j); return *this; }
+ friend inline const_iterator operator+(int j, const_iterator k)
+ { return const_iterator(k.future, k.advanceIndex(k.index, j)); }
- inline bool operator==(const const_iterator &o) const { return !operator!=(o); }
- inline const_iterator &operator++() { ++index; return *this; }
- inline const_iterator operator++(int) { const_iterator r = *this; ++index; return r; }
- inline const_iterator &operator--() { --index; return *this; }
- inline const_iterator operator--(int) { const_iterator r = *this; --index; return r; }
- inline const_iterator operator+(int j) const { return const_iterator(future, index + j); }
- inline const_iterator operator-(int j) const { return const_iterator(future, index - j); }
- inline const_iterator &operator+=(int j) { index += j; return *this; }
- inline const_iterator &operator-=(int j) { index -= j; return *this; }
- friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
private:
+ /*! \internal
+
+ Advances the iterator index \a idx \a n steps, waits for the
+ result at the target index, and returns the target index.
+
+ The index may be -1, indicating the end iterator, either
+ as the argument or as the return value. The end iterator
+ may be decremented.
+
+ The caller is responsible for not advancing the iterator
+ before begin() or past end(), with the exception that
+ attempting to advance a non-end iterator past end() for
+ a running future is allowed and will return the end iterator.
+
+ Note that n == 0 is valid and will wait for the result
+ at the given index.
+ */
+ int advanceIndex(int idx, int n) const
+ {
+ // The end iterator can be decremented, leave as-is for other cases
+ if (idx == -1 && n >= 0)
+ return idx;
+
+ // Special case for decrementing the end iterator: wait for
+ // finished to get the total result count.
+ if (idx == -1 && future->isRunning())
+ future->d.waitForFinished();
+
+ // Wait for result at target index
+ const int targetIndex = (idx == -1) ? future->resultCount() + n : idx + n;
+ future->d.waitForResult(targetIndex);
+
+ // After waiting there is either a result or the end was reached
+ return (targetIndex < future->resultCount()) ? targetIndex : -1;
+ }
+
QFuture const * future;
int index;
};
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp
index dfbed5fb0f..8f4cae8816 100644
--- a/src/corelib/thread/qfutureinterface.cpp
+++ b/src/corelib/thread/qfutureinterface.cpp
@@ -97,7 +97,7 @@ static inline int switch_off(QAtomicInt &a, int which)
static inline int switch_from_to(QAtomicInt &a, int from, int to)
{
int newValue;
- int expected = a.load();
+ int expected = a.loadRelaxed();
do {
newValue = (expected & ~from) | to;
} while (!a.testAndSetRelaxed(expected, newValue, expected));
@@ -107,7 +107,7 @@ static inline int switch_from_to(QAtomicInt &a, int from, int to)
void QFutureInterfaceBase::cancel()
{
QMutexLocker locker(&d->m_mutex);
- if (d->state.load() & Canceled)
+ if (d->state.loadRelaxed() & Canceled)
return;
switch_from_to(d->state, Paused, Canceled);
@@ -132,7 +132,7 @@ void QFutureInterfaceBase::setPaused(bool paused)
void QFutureInterfaceBase::togglePaused()
{
QMutexLocker locker(&d->m_mutex);
- if (d->state.load() & Paused) {
+ if (d->state.loadRelaxed() & Paused) {
switch_off(d->state, Paused);
d->pausedWaitCondition.wakeAll();
d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Resumed));
@@ -149,7 +149,7 @@ void QFutureInterfaceBase::setThrottled(bool enable)
switch_on(d->state, Throttled);
} else {
switch_off(d->state, Throttled);
- if (!(d->state.load() & Paused))
+ if (!(d->state.loadRelaxed() & Paused))
d->pausedWaitCondition.wakeAll();
}
}
@@ -201,13 +201,13 @@ void QFutureInterfaceBase::waitForResume()
{
// return early if possible to avoid taking the mutex lock.
{
- const int state = d->state.load();
+ const int state = d->state.loadRelaxed();
if (!(state & Paused) || (state & Canceled))
return;
}
QMutexLocker lock(&d->m_mutex);
- const int state = d->state.load();
+ const int state = d->state.loadRelaxed();
if (!(state & Paused) || (state & Canceled))
return;
@@ -256,7 +256,7 @@ bool QFutureInterfaceBase::isProgressUpdateNeeded() const
void QFutureInterfaceBase::reportStarted()
{
QMutexLocker locker(&d->m_mutex);
- if (d->state.load() & (Started|Canceled|Finished))
+ if (d->state.loadRelaxed() & (Started|Canceled|Finished))
return;
d->setState(State(Started | Running));
@@ -272,7 +272,7 @@ void QFutureInterfaceBase::reportCanceled()
void QFutureInterfaceBase::reportException(const QException &exception)
{
QMutexLocker locker(&d->m_mutex);
- if (d->state.load() & (Canceled|Finished))
+ if (d->state.loadRelaxed() & (Canceled|Finished))
return;
d->m_exceptionStore.setException(exception);
@@ -307,7 +307,7 @@ int QFutureInterfaceBase::expectedResultCount()
bool QFutureInterfaceBase::queryState(State state) const
{
- return d->state.load() & state;
+ return d->state.loadRelaxed() & state;
}
void QFutureInterfaceBase::waitForResult(int resultIndex)
@@ -352,7 +352,7 @@ void QFutureInterfaceBase::waitForFinished()
void QFutureInterfaceBase::reportResultsReady(int beginIndex, int endIndex)
{
- if (beginIndex == endIndex || (d->state.load() & (Canceled|Finished)))
+ if (beginIndex == endIndex || (d->state.loadRelaxed() & (Canceled|Finished)))
return;
d->waitCondition.wakeAll();
@@ -414,7 +414,7 @@ void QFutureInterfaceBase::setProgressValueAndText(int progressValue,
if (d->m_progressValue >= progressValue)
return;
- if (d->state.load() & (Canceled|Finished))
+ if (d->state.loadRelaxed() & (Canceled|Finished))
return;
if (d->internal_updateProgress(progressValue, progressText)) {
@@ -486,10 +486,10 @@ bool QFutureInterfaceBasePrivate::internal_waitForNextResult()
if (m_results.hasNextResult())
return true;
- while ((state.load() & QFutureInterfaceBase::Running) && m_results.hasNextResult() == false)
+ while ((state.loadRelaxed() & QFutureInterfaceBase::Running) && m_results.hasNextResult() == false)
waitCondition.wait(&m_mutex);
- return !(state.load() & QFutureInterfaceBase::Canceled) && m_results.hasNextResult();
+ return !(state.loadRelaxed() & QFutureInterfaceBase::Canceled) && m_results.hasNextResult();
}
bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress,
@@ -512,8 +512,8 @@ bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress,
void QFutureInterfaceBasePrivate::internal_setThrottled(bool enable)
{
// bail out if we are not changing the state
- if ((enable && (state.load() & QFutureInterfaceBase::Throttled))
- || (!enable && !(state.load() & QFutureInterfaceBase::Throttled)))
+ if ((enable && (state.loadRelaxed() & QFutureInterfaceBase::Throttled))
+ || (!enable && !(state.loadRelaxed() & QFutureInterfaceBase::Throttled)))
return;
// change the state
@@ -521,7 +521,7 @@ void QFutureInterfaceBasePrivate::internal_setThrottled(bool enable)
switch_on(state, QFutureInterfaceBase::Throttled);
} else {
switch_off(state, QFutureInterfaceBase::Throttled);
- if (!(state.load() & QFutureInterfaceBase::Paused))
+ if (!(state.loadRelaxed() & QFutureInterfaceBase::Paused))
pausedWaitCondition.wakeAll();
}
}
@@ -556,7 +556,7 @@ void QFutureInterfaceBasePrivate::connectOutputInterface(QFutureCallOutInterface
{
QMutexLocker locker(&m_mutex);
- if (state.load() & QFutureInterfaceBase::Started) {
+ if (state.loadRelaxed() & QFutureInterfaceBase::Started) {
interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Started));
interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::ProgressRange,
m_progressMinimum,
@@ -576,13 +576,13 @@ void QFutureInterfaceBasePrivate::connectOutputInterface(QFutureCallOutInterface
it.batchedAdvance();
}
- if (state.load() & QFutureInterfaceBase::Paused)
+ if (state.loadRelaxed() & QFutureInterfaceBase::Paused)
interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Paused));
- if (state.load() & QFutureInterfaceBase::Canceled)
+ if (state.loadRelaxed() & QFutureInterfaceBase::Canceled)
interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
- if (state.load() & QFutureInterfaceBase::Finished)
+ if (state.loadRelaxed() & QFutureInterfaceBase::Finished)
interface->postCallOutEvent(QFutureCallOutEvent(QFutureCallOutEvent::Finished));
outputConnections.append(interface);
@@ -601,7 +601,7 @@ void QFutureInterfaceBasePrivate::disconnectOutputInterface(QFutureCallOutInterf
void QFutureInterfaceBasePrivate::setState(QFutureInterfaceBase::State newState)
{
- state.store(newState);
+ state.storeRelaxed(newState);
}
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qfutureinterface_p.h b/src/corelib/thread/qfutureinterface_p.h
index 63e534464f..b297dff633 100644
--- a/src/corelib/thread/qfutureinterface_p.h
+++ b/src/corelib/thread/qfutureinterface_p.h
@@ -144,11 +144,11 @@ public:
// Default ref counter for QFIBP
inline bool ref() { return m_refCount.ref(); }
inline bool deref() { return m_refCount.deref(); }
- inline int load() const { return m_refCount.load(); }
+ inline int load() const { return m_refCount.loadRelaxed(); }
// Ref counter for type T
inline bool refT() { return m_refCountT.ref(); }
inline bool derefT() { return m_refCountT.deref(); }
- inline int loadT() const { return m_refCountT.load(); }
+ inline int loadT() const { return m_refCountT.loadRelaxed(); }
private:
QAtomicInt m_refCount;
diff --git a/src/corelib/thread/qfuturewatcher.cpp b/src/corelib/thread/qfuturewatcher.cpp
index 8e90d043ef..06bc4740f9 100644
--- a/src/corelib/thread/qfuturewatcher.cpp
+++ b/src/corelib/thread/qfuturewatcher.cpp
@@ -402,7 +402,7 @@ void QFutureWatcherBase::disconnectOutputInterface(bool pendingAssignment)
{
if (pendingAssignment) {
Q_D(QFutureWatcherBase);
- d->pendingResultsReady.store(0);
+ d->pendingResultsReady.storeRelaxed(0);
qDeleteAll(d->pendingCallOutEvents);
d->pendingCallOutEvents.clear();
d->finished = false; /* May soon be amended, during connectOutputInterface() */
@@ -441,7 +441,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
emit q->finished();
break;
case QFutureCallOutEvent::Canceled:
- pendingResultsReady.store(0);
+ pendingResultsReady.storeRelaxed(0);
emit q->canceled();
break;
case QFutureCallOutEvent::Paused:
@@ -466,7 +466,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
emit q->resultsReadyAt(beginIndex, endIndex);
- if (resultAtConnected.load() <= 0)
+ if (resultAtConnected.loadRelaxed() <= 0)
break;
for (int i = beginIndex; i < endIndex; ++i)
@@ -479,7 +479,7 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event)
emit q->progressValueChanged(event->index1);
if (!event->text.isNull()) // ###
- q->progressTextChanged(event->text);
+ emit q->progressTextChanged(event->text);
break;
case QFutureCallOutEvent::ProgressRange:
emit q->progressRangeChanged(event->index1, event->index2);
diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h
index 89c4fe9a11..e9e5f3c74b 100644
--- a/src/corelib/thread/qgenericatomic.h
+++ b/src/corelib/thread/qgenericatomic.h
@@ -72,32 +72,44 @@ template <typename BaseClass> struct QGenericAtomicOps
{
template <typename T> struct AtomicType { typedef T Type; typedef T *PointerType; };
- template <typename T> static void acquireMemoryFence(const T &_q_value) Q_DECL_NOTHROW
+ template <typename T> static void acquireMemoryFence(const T &_q_value) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
}
- template <typename T> static void releaseMemoryFence(const T &_q_value) Q_DECL_NOTHROW
+ template <typename T> static void releaseMemoryFence(const T &_q_value) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
}
- template <typename T> static void orderedMemoryFence(const T &) Q_DECL_NOTHROW
+ template <typename T> static void orderedMemoryFence(const T &) noexcept
{
}
template <typename T> static Q_ALWAYS_INLINE
- T load(const T &_q_value) Q_DECL_NOTHROW
+ T load(const T &_q_value) noexcept
{
return _q_value;
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- void store(T &_q_value, X newValue) Q_DECL_NOTHROW
+ void store(T &_q_value, X newValue) noexcept
{
_q_value = newValue;
}
template <typename T> static Q_ALWAYS_INLINE
- T loadAcquire(const T &_q_value) Q_DECL_NOTHROW
+ T loadRelaxed(const T &_q_value) noexcept
+ {
+ return _q_value;
+ }
+
+ template <typename T, typename X> static Q_ALWAYS_INLINE
+ void storeRelaxed(T &_q_value, X newValue) noexcept
+ {
+ _q_value = newValue;
+ }
+
+ template <typename T> static Q_ALWAYS_INLINE
+ T loadAcquire(const T &_q_value) noexcept
{
T tmp = *static_cast<const volatile T *>(&_q_value);
BaseClass::acquireMemoryFence(_q_value);
@@ -105,24 +117,24 @@ template <typename BaseClass> struct QGenericAtomicOps
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- void storeRelease(T &_q_value, X newValue) Q_DECL_NOTHROW
+ void storeRelease(T &_q_value, X newValue) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
*static_cast<volatile T *>(&_q_value) = newValue;
}
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() noexcept
{ return BaseClass::isFetchAndAddNative(); }
- static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() noexcept
{ return BaseClass::isFetchAndAddWaitFree(); }
template <typename T> static Q_ALWAYS_INLINE
- bool ref(T &_q_value) Q_DECL_NOTHROW
+ bool ref(T &_q_value) noexcept
{
return BaseClass::fetchAndAddRelaxed(_q_value, 1) != T(-1);
}
template <typename T> static Q_ALWAYS_INLINE
- bool deref(T &_q_value) Q_DECL_NOTHROW
+ bool deref(T &_q_value) noexcept
{
return BaseClass::fetchAndAddRelaxed(_q_value, -1) != 1;
}
@@ -130,16 +142,16 @@ template <typename BaseClass> struct QGenericAtomicOps
#if 0
// These functions have no default implementation
// Archictectures must implement them
- static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW;
- static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW;
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() noexcept;
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() noexcept;
template <typename T, typename X> static inline
- bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW;
+ bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue) noexcept;
template <typename T, typename X> static inline
- bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW;
+ bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept;
#endif
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue) noexcept
{
bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
BaseClass::acquireMemoryFence(_q_value);
@@ -147,21 +159,21 @@ template <typename BaseClass> struct QGenericAtomicOps
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetRelease(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(T &_q_value, X expectedValue, X newValue) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue);
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept
{
bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
BaseClass::acquireMemoryFence(_q_value);
@@ -169,35 +181,35 @@ template <typename BaseClass> struct QGenericAtomicOps
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetRelease(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ bool testAndSetRelease(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue, X *currentValue) Q_DECL_NOTHROW
+ bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue, X *currentValue) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue, currentValue);
}
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return false; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() noexcept { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() noexcept { return false; }
template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreRelaxed(T &_q_value, X newValue) Q_DECL_NOTHROW
+ T fetchAndStoreRelaxed(T &_q_value, X newValue) noexcept
{
// implement fetchAndStore on top of testAndSet
Q_FOREVER {
- T tmp = load(_q_value);
+ T tmp = loadRelaxed(_q_value);
if (BaseClass::testAndSetRelaxed(_q_value, tmp, newValue))
return tmp;
}
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreAcquire(T &_q_value, X newValue) Q_DECL_NOTHROW
+ T fetchAndStoreAcquire(T &_q_value, X newValue) noexcept
{
T tmp = BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
BaseClass::acquireMemoryFence(_q_value);
@@ -205,34 +217,34 @@ template <typename BaseClass> struct QGenericAtomicOps
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreRelease(T &_q_value, X newValue) Q_DECL_NOTHROW
+ T fetchAndStoreRelease(T &_q_value, X newValue) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
}
template <typename T, typename X> static Q_ALWAYS_INLINE
- T fetchAndStoreOrdered(T &_q_value, X newValue) Q_DECL_NOTHROW
+ T fetchAndStoreOrdered(T &_q_value, X newValue) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndStoreRelaxed(_q_value, newValue);
}
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return false; }
- static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() noexcept { return false; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() noexcept { return false; }
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
// implement fetchAndAdd on top of testAndSet
Q_FOREVER {
- T tmp = BaseClass::load(_q_value);
+ T tmp = BaseClass::loadRelaxed(_q_value);
if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp + valueToAdd)))
return tmp;
}
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
T tmp = BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
BaseClass::acquireMemoryFence(_q_value);
@@ -240,14 +252,14 @@ template <typename BaseClass> struct QGenericAtomicOps
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAddOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+ T fetchAndAddOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd);
@@ -256,7 +268,7 @@ template <typename BaseClass> struct QGenericAtomicOps
QT_WARNING_PUSH
QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type, result still unsigned
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
{
// implement fetchAndSub on top of fetchAndAdd
return fetchAndAddRelaxed(_q_value, -operand);
@@ -264,7 +276,7 @@ QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type
QT_WARNING_POP
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
{
T tmp = BaseClass::fetchAndSubRelaxed(_q_value, operand);
BaseClass::acquireMemoryFence(_q_value);
@@ -272,24 +284,24 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ T fetchAndSubRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndSubRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndSubOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) Q_DECL_NOTHROW
+ T fetchAndSubOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT operand) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndSubRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndAndRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
// implement fetchAndAnd on top of testAndSet
- T tmp = BaseClass::load(_q_value);
+ T tmp = BaseClass::loadRelaxed(_q_value);
Q_FOREVER {
if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp & operand), &tmp))
return tmp;
@@ -297,7 +309,7 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndAndAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
T tmp = BaseClass::fetchAndAndRelaxed(_q_value, operand);
BaseClass::acquireMemoryFence(_q_value);
@@ -305,24 +317,24 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndAndRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndAndRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndAndOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndAndOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndAndRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndOrRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
// implement fetchAndOr on top of testAndSet
- T tmp = BaseClass::load(_q_value);
+ T tmp = BaseClass::loadRelaxed(_q_value);
Q_FOREVER {
if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp | operand), &tmp))
return tmp;
@@ -330,7 +342,7 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndOrAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
T tmp = BaseClass::fetchAndOrRelaxed(_q_value, operand);
BaseClass::acquireMemoryFence(_q_value);
@@ -338,24 +350,24 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndOrRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndOrRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndOrOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndOrOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndOrRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndXorRelaxed(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
// implement fetchAndXor on top of testAndSet
- T tmp = BaseClass::load(_q_value);
+ T tmp = BaseClass::loadRelaxed(_q_value);
Q_FOREVER {
if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp ^ operand), &tmp))
return tmp;
@@ -363,7 +375,7 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndXorAcquire(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
T tmp = BaseClass::fetchAndXorRelaxed(_q_value, operand);
BaseClass::acquireMemoryFence(_q_value);
@@ -371,14 +383,14 @@ QT_WARNING_POP
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndXorRelease(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::releaseMemoryFence(_q_value);
return BaseClass::fetchAndXorRelaxed(_q_value, operand);
}
template <typename T> static Q_ALWAYS_INLINE
- T fetchAndXorOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) Q_DECL_NOTHROW
+ T fetchAndXorOrdered(T &_q_value, typename std::enable_if<QTypeInfo<T>::isIntegral, T>::type operand) noexcept
{
BaseClass::orderedMemoryFence(_q_value);
return BaseClass::fetchAndXorRelaxed(_q_value, operand);
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 3881ac017e..bd3a0fa7ba 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -82,7 +82,7 @@ public:
QMutex mutex;
bool lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT;
- void unlock() Q_DECL_NOTHROW;
+ void unlock() noexcept;
};
/*
@@ -179,7 +179,7 @@ public:
*/
QMutex::QMutex(RecursionMode mode)
{
- d_ptr.store(mode == Recursive ? new QRecursiveMutexPrivate : 0);
+ d_ptr.storeRelaxed(mode == Recursive ? new QRecursiveMutexPrivate : 0);
}
/*!
@@ -189,12 +189,12 @@ QMutex::QMutex(RecursionMode mode)
*/
QMutex::~QMutex()
{
- QMutexData *d = d_ptr.load();
+ QMutexData *d = d_ptr.loadRelaxed();
if (isRecursive()) {
delete static_cast<QRecursiveMutexPrivate *>(d);
} else if (d) {
#ifndef QT_LINUX_FUTEX
- if (d != dummyLocked() && static_cast<QMutexPrivate *>(d)->possiblyUnlocked.load()
+ if (d != dummyLocked() && static_cast<QMutexPrivate *>(d)->possiblyUnlocked.loadRelaxed()
&& tryLock()) {
unlock();
return;
@@ -329,7 +329,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
\sa lock()
*/
-void QMutex::unlock() Q_DECL_NOTHROW
+void QMutex::unlock() noexcept
{
QMutexData *current;
if (fastTryUnlock(current))
@@ -348,7 +348,7 @@ void QMutex::unlock() Q_DECL_NOTHROW
Returns \c true if the mutex is recursive.
*/
-bool QBasicMutex::isRecursive() Q_DECL_NOTHROW
+bool QBasicMutex::isRecursive() noexcept
{
return QT_PREPEND_NAMESPACE(isRecursive)(d_ptr.loadAcquire());
}
@@ -358,7 +358,7 @@ bool QBasicMutex::isRecursive() Q_DECL_NOTHROW
Returns \c true if the mutex is recursive.
*/
-bool QBasicMutex::isRecursive() const Q_DECL_NOTHROW
+bool QBasicMutex::isRecursive() const noexcept
{
return QT_PREPEND_NAMESPACE(isRecursive)(d_ptr.loadAcquire());
}
@@ -517,7 +517,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
}
QMutexPrivate *d = static_cast<QMutexPrivate *>(copy);
- if (timeout == 0 && !d->possiblyUnlocked.load())
+ if (timeout == 0 && !d->possiblyUnlocked.loadRelaxed())
return false;
// At this point we have a pointer to a QMutexPrivate. But the other thread
@@ -541,7 +541,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
// is set to the BigNumber magic value set in unlockInternal()
int old_waiters;
do {
- old_waiters = d->waiters.load();
+ old_waiters = d->waiters.loadRelaxed();
if (old_waiters == -QMutexPrivate::BigNumber) {
// we are unlocking, and the thread that unlocks is about to change d to 0
// we try to acquire the mutex by changing to dummyLocked()
@@ -550,7 +550,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
d->deref();
return true;
} else {
- Q_ASSERT(d != d_ptr.load()); //else testAndSetAcquire should have succeeded
+ Q_ASSERT(d != d_ptr.loadRelaxed()); //else testAndSetAcquire should have succeeded
// Mutex is likely to bo 0, we should continue the outer-loop,
// set old_waiters to the magic value of BigNumber
old_waiters = QMutexPrivate::BigNumber;
@@ -563,7 +563,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
// The mutex was unlocked before we incremented waiters.
if (old_waiters != QMutexPrivate::BigNumber) {
//we did not break the previous loop
- Q_ASSERT(d->waiters.load() >= 1);
+ Q_ASSERT(d->waiters.loadRelaxed() >= 1);
d->waiters.deref();
}
d->deref();
@@ -572,11 +572,11 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
if (d->wait(timeout)) {
// reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
- if (d->possiblyUnlocked.load() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
+ if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
d->deref();
d->derefWaiters(1);
//we got the lock. (do not deref)
- Q_ASSERT(d == d_ptr.load());
+ Q_ASSERT(d == d_ptr.loadRelaxed());
return true;
} else {
Q_ASSERT(timeout >= 0);
@@ -593,14 +593,14 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
return false;
}
}
- Q_ASSERT(d_ptr.load() != 0);
+ Q_ASSERT(d_ptr.loadRelaxed() != 0);
return true;
}
/*!
\internal
*/
-void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
+void QBasicMutex::unlockInternal() noexcept
{
QMutexData *copy = d_ptr.loadAcquire();
Q_ASSERT(copy); //we must be locked
@@ -618,7 +618,7 @@ void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
//there is no one waiting on this mutex anymore, set the mutex as unlocked (d = 0)
if (d_ptr.testAndSetRelease(d, 0)) {
// reset the possiblyUnlocked flag if needed (and deref its corresponding reference)
- if (d->possiblyUnlocked.load() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
+ if (d->possiblyUnlocked.loadRelaxed() && d->possiblyUnlocked.testAndSetRelaxed(true, false))
d->deref();
}
d->derefWaiters(0);
@@ -657,30 +657,30 @@ QMutexPrivate *QMutexPrivate::allocate()
int i = freelist()->next();
QMutexPrivate *d = &(*freelist())[i];
d->id = i;
- Q_ASSERT(d->refCount.load() == 0);
+ Q_ASSERT(d->refCount.loadRelaxed() == 0);
Q_ASSERT(!d->recursive);
- Q_ASSERT(!d->possiblyUnlocked.load());
- Q_ASSERT(d->waiters.load() == 0);
- d->refCount.store(1);
+ Q_ASSERT(!d->possiblyUnlocked.loadRelaxed());
+ Q_ASSERT(d->waiters.loadRelaxed() == 0);
+ d->refCount.storeRelaxed(1);
return d;
}
void QMutexPrivate::release()
{
Q_ASSERT(!recursive);
- Q_ASSERT(refCount.load() == 0);
- Q_ASSERT(!possiblyUnlocked.load());
- Q_ASSERT(waiters.load() == 0);
+ Q_ASSERT(refCount.loadRelaxed() == 0);
+ Q_ASSERT(!possiblyUnlocked.loadRelaxed());
+ Q_ASSERT(waiters.loadRelaxed() == 0);
freelist()->release(id);
}
// atomically subtract "value" to the waiters, and remove the QMutexPrivate::BigNumber flag
-void QMutexPrivate::derefWaiters(int value) Q_DECL_NOTHROW
+void QMutexPrivate::derefWaiters(int value) noexcept
{
int old_waiters;
int new_waiters;
do {
- old_waiters = waiters.load();
+ old_waiters = waiters.loadRelaxed();
new_waiters = old_waiters;
if (new_waiters < 0) {
new_waiters += QMutexPrivate::BigNumber;
@@ -696,7 +696,7 @@ void QMutexPrivate::derefWaiters(int value) Q_DECL_NOTHROW
inline bool QRecursiveMutexPrivate::lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
{
Qt::HANDLE self = QThread::currentThreadId();
- if (owner.load() == self) {
+ if (owner.loadRelaxed() == self) {
++count;
Q_ASSERT_X(count != 0, "QMutex::lock", "Overflow in recursion counter");
return true;
@@ -709,19 +709,19 @@ inline bool QRecursiveMutexPrivate::lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
}
if (success)
- owner.store(self);
+ owner.storeRelaxed(self);
return success;
}
/*!
\internal
*/
-inline void QRecursiveMutexPrivate::unlock() Q_DECL_NOTHROW
+inline void QRecursiveMutexPrivate::unlock() noexcept
{
if (count > 0) {
count--;
} else {
- owner.store(0);
+ owner.storeRelaxed(0);
mutex.QBasicMutex::unlock();
}
}
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index 837355a602..0de0869cb2 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
#if QT_CONFIG(thread) || defined(Q_CLANG_QDOC)
#ifdef Q_OS_LINUX
-# define QT_MUTEX_LOCK_NOEXCEPT Q_DECL_NOTHROW
+# define QT_MUTEX_LOCK_NOEXCEPT noexcept
#else
# define QT_MUTEX_LOCK_NOEXCEPT
#endif
@@ -80,39 +80,39 @@ public:
}
// BasicLockable concept
- inline void unlock() Q_DECL_NOTHROW {
- Q_ASSERT(d_ptr.load()); //mutex must be locked
+ inline void unlock() noexcept {
+ Q_ASSERT(d_ptr.loadRelaxed()); //mutex must be locked
if (!fastTryUnlock())
unlockInternal();
}
- bool tryLock() Q_DECL_NOTHROW {
+ bool tryLock() noexcept {
return fastTryLock();
}
// Lockable concept
- bool try_lock() Q_DECL_NOTHROW { return tryLock(); }
+ bool try_lock() noexcept { return tryLock(); }
- bool isRecursive() Q_DECL_NOTHROW; //### Qt6: remove me
- bool isRecursive() const Q_DECL_NOTHROW;
+ bool isRecursive() noexcept; //### Qt6: remove me
+ bool isRecursive() const noexcept;
private:
- inline bool fastTryLock() Q_DECL_NOTHROW {
+ inline bool fastTryLock() noexcept {
return d_ptr.testAndSetAcquire(nullptr, dummyLocked());
}
- inline bool fastTryUnlock() Q_DECL_NOTHROW {
+ inline bool fastTryUnlock() noexcept {
return d_ptr.testAndSetRelease(dummyLocked(), nullptr);
}
- inline bool fastTryLock(QMutexData *&current) Q_DECL_NOTHROW {
+ inline bool fastTryLock(QMutexData *&current) noexcept {
return d_ptr.testAndSetAcquire(nullptr, dummyLocked(), current);
}
- inline bool fastTryUnlock(QMutexData *&current) Q_DECL_NOTHROW {
+ inline bool fastTryUnlock(QMutexData *&current) noexcept {
return d_ptr.testAndSetRelease(dummyLocked(), nullptr, current);
}
void lockInternal() QT_MUTEX_LOCK_NOEXCEPT;
bool lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT;
- void unlockInternal() Q_DECL_NOTHROW;
+ void unlockInternal() noexcept;
QBasicAtomicPointer<QMutexData> d_ptr;
static inline QMutexData *dummyLocked() {
@@ -134,7 +134,7 @@ public:
void lock() QT_MUTEX_LOCK_NOEXCEPT;
bool tryLock(int timeout = 0) QT_MUTEX_LOCK_NOEXCEPT;
// BasicLockable concept
- void unlock() Q_DECL_NOTHROW;
+ void unlock() noexcept;
// Lockable concept
bool try_lock() QT_MUTEX_LOCK_NOEXCEPT { return tryLock(); }
@@ -158,7 +158,7 @@ public:
}
#endif
- bool isRecursive() const Q_DECL_NOTHROW
+ bool isRecursive() const noexcept
{ return QBasicMutex::isRecursive(); }
private:
@@ -212,7 +212,7 @@ public:
#endif
inline ~QMutexLocker() { unlock(); }
- inline void unlock() Q_DECL_NOTHROW
+ inline void unlock() noexcept
{
if ((val & quintptr(1u)) == quintptr(1u)) {
val &= ~quintptr(1u);
@@ -257,24 +257,24 @@ class Q_CORE_EXPORT QMutex
public:
enum RecursionMode { NonRecursive, Recursive };
- inline Q_DECL_CONSTEXPR explicit QMutex(RecursionMode = NonRecursive) Q_DECL_NOTHROW { }
+ inline Q_DECL_CONSTEXPR explicit QMutex(RecursionMode = NonRecursive) noexcept { }
- inline void lock() Q_DECL_NOTHROW {}
- inline bool tryLock(int timeout = 0) Q_DECL_NOTHROW { Q_UNUSED(timeout); return true; }
- inline bool try_lock() Q_DECL_NOTHROW { return true; }
- inline void unlock() Q_DECL_NOTHROW {}
- inline bool isRecursive() const Q_DECL_NOTHROW { return true; }
+ inline void lock() noexcept {}
+ inline bool tryLock(int timeout = 0) noexcept { Q_UNUSED(timeout); return true; }
+ inline bool try_lock() noexcept { return true; }
+ inline void unlock() noexcept {}
+ inline bool isRecursive() const noexcept { return true; }
#if QT_HAS_INCLUDE(<chrono>)
template <class Rep, class Period>
- inline bool try_lock_for(std::chrono::duration<Rep, Period> duration) Q_DECL_NOTHROW
+ inline bool try_lock_for(std::chrono::duration<Rep, Period> duration) noexcept
{
Q_UNUSED(duration);
return true;
}
template<class Clock, class Duration>
- inline bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint) Q_DECL_NOTHROW
+ inline bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint) noexcept
{
Q_UNUSED(timePoint);
return true;
@@ -288,12 +288,12 @@ private:
class Q_CORE_EXPORT QMutexLocker
{
public:
- inline explicit QMutexLocker(QMutex *) Q_DECL_NOTHROW {}
- inline ~QMutexLocker() Q_DECL_NOTHROW {}
+ inline explicit QMutexLocker(QMutex *) noexcept {}
+ inline ~QMutexLocker() noexcept {}
- inline void unlock() Q_DECL_NOTHROW {}
- void relock() Q_DECL_NOTHROW {}
- inline QMutex *mutex() const Q_DECL_NOTHROW { return nullptr; }
+ inline void unlock() noexcept {}
+ void relock() noexcept {}
+ inline QMutex *mutex() const noexcept { return nullptr; }
private:
Q_DISABLE_COPY(QMutexLocker)
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp
index 507e72cb76..3270875471 100644
--- a/src/corelib/thread/qmutex_linux.cpp
+++ b/src/corelib/thread/qmutex_linux.cpp
@@ -106,7 +106,7 @@ static inline QMutexData *dummyFutexValue()
}
template <bool IsTimed> static inline
-bool lockInternal_helper(QBasicAtomicPointer<QMutexData> &d_ptr, int timeout = -1, QElapsedTimer *elapsedTimer = 0) Q_DECL_NOTHROW
+bool lockInternal_helper(QBasicAtomicPointer<QMutexData> &d_ptr, int timeout = -1, QElapsedTimer *elapsedTimer = 0) noexcept
{
if (!IsTimed)
timeout = -1;
@@ -149,17 +149,17 @@ bool lockInternal_helper(QBasicAtomicPointer<QMutexData> &d_ptr, int timeout = -
}
}
- Q_ASSERT(d_ptr.load());
+ Q_ASSERT(d_ptr.loadRelaxed());
return true;
}
-void QBasicMutex::lockInternal() Q_DECL_NOTHROW
+void QBasicMutex::lockInternal() noexcept
{
Q_ASSERT(!isRecursive());
lockInternal_helper<false>(d_ptr);
}
-bool QBasicMutex::lockInternal(int timeout) Q_DECL_NOTHROW
+bool QBasicMutex::lockInternal(int timeout) noexcept
{
Q_ASSERT(!isRecursive());
QElapsedTimer elapsedTimer;
@@ -167,9 +167,9 @@ bool QBasicMutex::lockInternal(int timeout) Q_DECL_NOTHROW
return lockInternal_helper<true>(d_ptr, timeout, &elapsedTimer);
}
-void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
+void QBasicMutex::unlockInternal() noexcept
{
- QMutexData *d = d_ptr.load();
+ QMutexData *d = d_ptr.loadRelaxed();
Q_ASSERT(d); //we must be locked
Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
Q_UNUSED(d);
diff --git a/src/corelib/thread/qmutex_mac.cpp b/src/corelib/thread/qmutex_mac.cpp
index 9a8d9bc750..923f89f697 100644
--- a/src/corelib/thread/qmutex_mac.cpp
+++ b/src/corelib/thread/qmutex_mac.cpp
@@ -79,7 +79,7 @@ bool QMutexPrivate::wait(int timeout)
return (r == KERN_SUCCESS);
}
-void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
+void QMutexPrivate::wakeUp() noexcept
{
semaphore_signal(mach_semaphore);
}
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
index ec9bfc1152..048d8707c4 100644
--- a/src/corelib/thread/qmutex_p.h
+++ b/src/corelib/thread/qmutex_p.h
@@ -92,28 +92,28 @@ public:
QMutexPrivate();
bool wait(int timeout = -1);
- void wakeUp() Q_DECL_NOTHROW;
+ void wakeUp() noexcept;
// Control the lifetime of the privates
QAtomicInt refCount;
int id;
bool ref() {
- Q_ASSERT(refCount.load() >= 0);
+ Q_ASSERT(refCount.loadRelaxed() >= 0);
int c;
do {
- c = refCount.load();
+ c = refCount.loadRelaxed();
if (c == 0)
return false;
} while (!refCount.testAndSetRelaxed(c, c + 1));
- Q_ASSERT(refCount.load() >= 0);
+ Q_ASSERT(refCount.loadRelaxed() >= 0);
return true;
}
void deref() {
- Q_ASSERT(refCount.load() >= 0);
+ Q_ASSERT(refCount.loadRelaxed() >= 0);
if (!refCount.deref())
release();
- Q_ASSERT(refCount.load() >= 0);
+ Q_ASSERT(refCount.loadRelaxed() >= 0);
}
void release();
static QMutexPrivate *allocate();
@@ -125,7 +125,7 @@ public:
when the mutex is unlocked.
*/
enum { BigNumber = 0x100000 }; //Must be bigger than the possible number of waiters (number of threads)
- void derefWaiters(int value) Q_DECL_NOTHROW;
+ void derefWaiters(int value) noexcept;
//platform specific stuff
#if defined(Q_OS_MAC)
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index 3ee24a292c..df2f606a23 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
static void report_error(int code, const char *where, const char *what)
{
if (code != 0)
- qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
+ qErrnoWarning(code, "%s: %s failure", where, what);
}
#ifdef QT_UNIX_SEMAPHORE
@@ -99,7 +99,7 @@ bool QMutexPrivate::wait(int timeout)
return true;
}
-void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
+void QMutexPrivate::wakeUp() noexcept
{
report_error(sem_post(&semaphore), "QMutex::unlock", "sem_post");
}
@@ -146,7 +146,7 @@ bool QMutexPrivate::wait(int timeout)
return ret;
}
-void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
+void QMutexPrivate::wakeUp() noexcept
{
report_error(pthread_mutex_lock(&mutex), "QMutex::unlock", "mutex lock");
wakeup = true;
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
index 3c314a4c0c..e221bc89cb 100644
--- a/src/corelib/thread/qmutex_win.cpp
+++ b/src/corelib/thread/qmutex_win.cpp
@@ -64,7 +64,7 @@ bool QMutexPrivate::wait(int timeout)
return (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0);
}
-void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
+void QMutexPrivate::wakeUp() noexcept
{ SetEvent(event); }
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp
index 3f9e8da942..2a02197859 100644
--- a/src/corelib/thread/qmutexpool.cpp
+++ b/src/corelib/thread/qmutexpool.cpp
@@ -93,7 +93,7 @@ QMutexPool::QMutexPool(QMutex::RecursionMode recursionMode, int size)
: mutexes(size), recursionMode(recursionMode)
{
for (int index = 0; index < mutexes.count(); ++index) {
- mutexes[index].store(0);
+ mutexes[index].storeRelaxed(0);
}
}
@@ -104,7 +104,7 @@ QMutexPool::QMutexPool(QMutex::RecursionMode recursionMode, int size)
QMutexPool::~QMutexPool()
{
for (int index = 0; index < mutexes.count(); ++index)
- delete mutexes[index].load();
+ delete mutexes[index].loadRelaxed();
}
/*!
@@ -131,7 +131,7 @@ QMutex *QMutexPool::createMutex(int index)
QMutex *newMutex = new QMutex(recursionMode);
if (!mutexes[index].testAndSetRelease(0, newMutex))
delete newMutex;
- return mutexes[index].load();
+ return mutexes[index].loadRelaxed();
}
/*!
diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h
index 89d006ac29..1a47231abc 100644
--- a/src/corelib/thread/qmutexpool_p.h
+++ b/src/corelib/thread/qmutexpool_p.h
@@ -68,7 +68,7 @@ public:
inline QMutex *get(const void *address) {
int index = uint(quintptr(address)) % mutexes.count();
- QMutex *m = mutexes[index].load();
+ QMutex *m = mutexes[index].loadRelaxed();
if (m)
return m;
else
diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h
index ded102d32d..e0a67388d4 100644
--- a/src/corelib/thread/qorderedmutexlocker_p.h
+++ b/src/corelib/thread/qorderedmutexlocker_p.h
@@ -58,6 +58,8 @@
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(thread)
+
/*
Locks 2 mutexes in a defined order, avoiding a recursive lock if
we're trying to lock the same mutex twice.
@@ -65,9 +67,9 @@ QT_BEGIN_NAMESPACE
class QOrderedMutexLocker
{
public:
- QOrderedMutexLocker(QMutex *m1, QMutex *m2)
- : mtx1((m1 == m2) ? m1 : (std::less<QMutex *>()(m1, m2) ? m1 : m2)),
- mtx2((m1 == m2) ? 0 : (std::less<QMutex *>()(m1, m2) ? m2 : m1)),
+ QOrderedMutexLocker(QBasicMutex *m1, QBasicMutex *m2)
+ : mtx1((m1 == m2) ? m1 : (std::less<QBasicMutex *>()(m1, m2) ? m1 : m2)),
+ mtx2((m1 == m2) ? 0 : (std::less<QBasicMutex *>()(m1, m2) ? m2 : m1)),
locked(false)
{
relock();
@@ -95,12 +97,12 @@ public:
}
}
- static bool relock(QMutex *mtx1, QMutex *mtx2)
+ static bool relock(QBasicMutex *mtx1, QBasicMutex *mtx2)
{
// mtx1 is already locked, mtx2 not... do we need to unlock and relock?
if (mtx1 == mtx2)
return false;
- if (std::less<QMutex *>()(mtx1, mtx2)) {
+ if (std::less<QBasicMutex *>()(mtx1, mtx2)) {
mtx2->lock();
return true;
}
@@ -113,10 +115,58 @@ public:
}
private:
- QMutex *mtx1, *mtx2;
+ QBasicMutex *mtx1, *mtx2;
bool locked;
};
+class QBasicMutexLocker
+{
+public:
+ inline explicit QBasicMutexLocker(QBasicMutex *m) QT_MUTEX_LOCK_NOEXCEPT
+ : m(m), isLocked(true)
+ {
+ m->lock();
+ }
+ inline ~QBasicMutexLocker() { if (isLocked) unlock(); }
+
+ inline void unlock() noexcept
+ {
+ isLocked = false;
+ m->unlock();
+ }
+
+ inline void relock() QT_MUTEX_LOCK_NOEXCEPT
+ {
+ isLocked = true;
+ m->lock();
+ }
+
+private:
+ Q_DISABLE_COPY(QBasicMutexLocker)
+
+ QBasicMutex *m;
+ bool isLocked;
+};
+
+#else
+
+class QOrderedMutexLocker
+{
+public:
+ QOrderedMutexLocker(QBasicMutex *, QBasicMutex *) {}
+ ~QOrderedMutexLocker() {}
+
+ void relock() {}
+ void unlock() {}
+
+ static bool relock(QBasicMutex *, QBasicMutex *) {}
+};
+
+using QBasicMutexLocker = QMutexLocker;
+
+#endif
+
+
QT_END_NAMESPACE
#endif
diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp
index d7cf7a7284..30e9b95a52 100644
--- a/src/corelib/thread/qreadwritelock.cpp
+++ b/src/corelib/thread/qreadwritelock.cpp
@@ -143,7 +143,7 @@ inline bool isUncontendedLocked(const QReadWriteLockPrivate *d)
QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
: d_ptr(recursionMode == Recursive ? new QReadWriteLockPrivate(true) : nullptr)
{
- Q_ASSERT_X(!(quintptr(d_ptr.load()) & StateMask), "QReadWriteLock::QReadWriteLock", "bad d_ptr alignment");
+ Q_ASSERT_X(!(quintptr(d_ptr.loadRelaxed()) & StateMask), "QReadWriteLock::QReadWriteLock", "bad d_ptr alignment");
}
/*!
@@ -154,7 +154,7 @@ QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
*/
QReadWriteLock::~QReadWriteLock()
{
- auto d = d_ptr.load();
+ auto d = d_ptr.loadRelaxed();
if (isUncontendedLocked(d)) {
qWarning("QReadWriteLock: destroying locked QReadWriteLock");
return;
@@ -263,7 +263,7 @@ bool QReadWriteLock::tryLockForRead(int timeout)
return d->recursiveLockForRead(timeout);
QMutexLocker lock(&d->mutex);
- if (d != d_ptr.load()) {
+ if (d != d_ptr.loadRelaxed()) {
// d_ptr has changed: this QReadWriteLock was unlocked before we had
// time to lock d->mutex.
// We are holding a lock to a mutex within a QReadWriteLockPrivate
@@ -370,7 +370,7 @@ bool QReadWriteLock::tryLockForWrite(int timeout)
return d->recursiveLockForWrite(timeout);
QMutexLocker lock(&d->mutex);
- if (d != d_ptr.load()) {
+ if (d != d_ptr.loadRelaxed()) {
// The mutex was unlocked before we had time to lock the mutex.
// We are holding to a mutex within a QReadWriteLockPrivate that is already released
// (or even is already re-used) but that's ok because the QFreeList never frees them.
@@ -433,7 +433,7 @@ void QReadWriteLock::unlock()
if (d->waitingReaders || d->waitingWriters) {
d->unlock();
} else {
- Q_ASSERT(d_ptr.load() == d); // should not change when we still hold the mutex
+ Q_ASSERT(d_ptr.loadRelaxed() == d); // should not change when we still hold the mutex
d_ptr.storeRelease(nullptr);
d->release();
}
@@ -444,7 +444,7 @@ void QReadWriteLock::unlock()
/*! \internal Helper for QWaitCondition::wait */
QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() const
{
- QReadWriteLockPrivate *d = d_ptr.load();
+ QReadWriteLockPrivate *d = d_ptr.loadRelaxed();
switch (quintptr(d) & StateMask) {
case StateLockedForRead: return LockedForRead;
case StateLockedForWrite: return LockedForWrite;
diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h
index 65fa76fd6d..139fde9214 100644
--- a/src/corelib/thread/qreadwritelock.h
+++ b/src/corelib/thread/qreadwritelock.h
@@ -180,18 +180,18 @@ class Q_CORE_EXPORT QReadWriteLock
{
public:
enum RecursionMode { NonRecursive, Recursive };
- inline explicit QReadWriteLock(RecursionMode = NonRecursive) Q_DECL_NOTHROW { }
+ inline explicit QReadWriteLock(RecursionMode = NonRecursive) noexcept { }
inline ~QReadWriteLock() { }
- static inline void lockForRead() Q_DECL_NOTHROW { }
- static inline bool tryLockForRead() Q_DECL_NOTHROW { return true; }
- static inline bool tryLockForRead(int timeout) Q_DECL_NOTHROW { Q_UNUSED(timeout); return true; }
+ static inline void lockForRead() noexcept { }
+ static inline bool tryLockForRead() noexcept { return true; }
+ static inline bool tryLockForRead(int timeout) noexcept { Q_UNUSED(timeout); return true; }
- static inline void lockForWrite() Q_DECL_NOTHROW { }
- static inline bool tryLockForWrite() Q_DECL_NOTHROW { return true; }
- static inline bool tryLockForWrite(int timeout) Q_DECL_NOTHROW { Q_UNUSED(timeout); return true; }
+ static inline void lockForWrite() noexcept { }
+ static inline bool tryLockForWrite() noexcept { return true; }
+ static inline bool tryLockForWrite(int timeout) noexcept { Q_UNUSED(timeout); return true; }
- static inline void unlock() Q_DECL_NOTHROW { }
+ static inline void unlock() noexcept { }
private:
Q_DISABLE_COPY(QReadWriteLock)
@@ -200,12 +200,12 @@ private:
class Q_CORE_EXPORT QReadLocker
{
public:
- inline QReadLocker(QReadWriteLock *) Q_DECL_NOTHROW { }
- inline ~QReadLocker() Q_DECL_NOTHROW { }
+ inline QReadLocker(QReadWriteLock *) noexcept { }
+ inline ~QReadLocker() noexcept { }
- static inline void unlock() Q_DECL_NOTHROW { }
- static inline void relock() Q_DECL_NOTHROW { }
- static inline QReadWriteLock *readWriteLock() Q_DECL_NOTHROW { return nullptr; }
+ static inline void unlock() noexcept { }
+ static inline void relock() noexcept { }
+ static inline QReadWriteLock *readWriteLock() noexcept { return nullptr; }
private:
Q_DISABLE_COPY(QReadLocker)
@@ -214,12 +214,12 @@ private:
class Q_CORE_EXPORT QWriteLocker
{
public:
- inline explicit QWriteLocker(QReadWriteLock *) Q_DECL_NOTHROW { }
- inline ~QWriteLocker() Q_DECL_NOTHROW { }
+ inline explicit QWriteLocker(QReadWriteLock *) noexcept { }
+ inline ~QWriteLocker() noexcept { }
- static inline void unlock() Q_DECL_NOTHROW { }
- static inline void relock() Q_DECL_NOTHROW { }
- static inline QReadWriteLock *readWriteLock() Q_DECL_NOTHROW { return nullptr; }
+ static inline void unlock() noexcept { }
+ static inline void relock() noexcept { }
+ static inline QReadWriteLock *readWriteLock() noexcept { return nullptr; }
private:
Q_DISABLE_COPY(QWriteLocker)
diff --git a/src/corelib/thread/qresultstore.cpp b/src/corelib/thread/qresultstore.cpp
index e0ce1b4b78..1b3bc20eca 100644
--- a/src/corelib/thread/qresultstore.cpp
+++ b/src/corelib/thread/qresultstore.cpp
@@ -43,6 +43,21 @@ QT_BEGIN_NAMESPACE
namespace QtPrivate {
+/*!
+ \class QtPrivate::ResultItem
+ \internal
+ */
+
+/*!
+ \class QtPrivate::ResultIteratorBase
+ \internal
+ */
+
+/*!
+ \class QtPrivate::ResultStoreBase
+ \internal
+ */
+
ResultIteratorBase::ResultIteratorBase()
: mapIterator(QMap<int, ResultItem>::const_iterator()), m_vectorIndex(0) { }
ResultIteratorBase::ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex)
diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h
index 39f0a6d1bb..7a65089396 100644
--- a/src/corelib/thread/qresultstore.h
+++ b/src/corelib/thread/qresultstore.h
@@ -56,7 +56,6 @@ QT_BEGIN_NAMESPACE
either individually or in batches.
*/
-#ifndef Q_QDOC
namespace QtPrivate {
@@ -143,7 +142,7 @@ public:
template <typename T>
int addResult(int index, const T *result)
{
- if (result == 0)
+ if (result == nullptr)
return addResult(index, static_cast<void *>(nullptr));
else
return addResult(index, static_cast<void *>(new T(*result)));
@@ -159,7 +158,7 @@ public:
int addResults(int index, const QVector<T> *results, int totalCount)
{
if (m_filterMode == true && results->count() != totalCount && 0 == results->count())
- return addResults(index, 0, 0, totalCount);
+ return addResults(index, nullptr, 0, totalCount);
else
return addResults(index, new QVector<T>(*results), results->count(), totalCount);
}
@@ -196,7 +195,6 @@ public:
Q_DECLARE_TYPEINFO(QtPrivate::ResultItem, Q_PRIMITIVE_TYPE);
-#endif //Q_QDOC
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
index aa04fb10ff..d4fb756b94 100644
--- a/src/corelib/thread/qsemaphore.cpp
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -264,7 +264,7 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp
if (futexHasWaiterCount) {
// decrement the number of threads waiting
- Q_ASSERT(futexHigh32(&u)->load() & 0x7fffffffU);
+ Q_ASSERT(futexHigh32(&u)->loadRelaxed() & 0x7fffffffU);
u.fetchAndSubRelaxed(oneWaiter);
}
return false;
@@ -293,7 +293,7 @@ QSemaphore::QSemaphore(int n)
quintptr nn = unsigned(n);
if (futexHasWaiterCount)
nn |= quint64(nn) << 32; // token count replicated in high word
- u.store(nn);
+ u.storeRelaxed(nn);
} else {
d = new QSemaphorePrivate(n);
}
@@ -425,7 +425,7 @@ void QSemaphore::release(int n)
int QSemaphore::available() const
{
if (futexAvailable())
- return futexAvailCounter(u.load());
+ return futexAvailCounter(u.loadRelaxed());
QMutexLocker locker(&d->mutex);
return d->avail;
@@ -606,7 +606,7 @@ bool QSemaphore::tryAcquire(int n, int timeout)
\fn QSemaphoreReleaser::semaphore() const
Returns a pointer to the QSemaphore object provided to the constructor,
- or by the last move assignment, if any. Otherwise, returns \c nullptr.
+ or by the last move assignment, if any. Otherwise, returns \nullptr.
*/
/*!
@@ -614,7 +614,7 @@ bool QSemaphore::tryAcquire(int n, int timeout)
Cancels this QSemaphoreReleaser such that the destructor will no longer
call \c{semaphore()->release()}. Returns the value of semaphore()
- before this call. After this call, semaphore() will return \c nullptr.
+ before this call. After this call, semaphore() will return \nullptr.
To enable again, assign a new QSemaphoreReleaser:
diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h
index b830ff1bfd..58c12997ad 100644
--- a/src/corelib/thread/qsemaphore.h
+++ b/src/corelib/thread/qsemaphore.h
@@ -75,14 +75,14 @@ class QSemaphoreReleaser
{
public:
QSemaphoreReleaser() = default;
- explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) Q_DECL_NOTHROW
+ explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) noexcept
: m_sem(&sem), m_n(n) {}
- explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) Q_DECL_NOTHROW
+ explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) noexcept
: m_sem(sem), m_n(n) {}
- QSemaphoreReleaser(QSemaphoreReleaser &&other) Q_DECL_NOTHROW
+ QSemaphoreReleaser(QSemaphoreReleaser &&other) noexcept
: m_sem(other.m_sem), m_n(other.m_n)
{ other.m_sem = nullptr; }
- QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) Q_DECL_NOTHROW
+ QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) noexcept
{ QSemaphoreReleaser moved(std::move(other)); swap(moved); return *this; }
~QSemaphoreReleaser()
@@ -91,16 +91,16 @@ public:
m_sem->release(m_n);
}
- void swap(QSemaphoreReleaser &other) Q_DECL_NOTHROW
+ void swap(QSemaphoreReleaser &other) noexcept
{
qSwap(m_sem, other.m_sem);
qSwap(m_n, other.m_n);
}
- QSemaphore *semaphore() const Q_DECL_NOTHROW
+ QSemaphore *semaphore() const noexcept
{ return m_sem; }
- QSemaphore *cancel() Q_DECL_NOTHROW
+ QSemaphore *cancel() noexcept
{
QSemaphore *old = m_sem;
m_sem = nullptr;
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 9f60de1f87..1eac7db11d 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -65,7 +65,7 @@ QThreadData::QThreadData(int initialRefCount)
QThreadData::~QThreadData()
{
- Q_ASSERT(_ref.load() == 0);
+ Q_ASSERT(_ref.loadRelaxed() == 0);
// In the odd case that Qt is running on a secondary thread, the main
// thread instance will have been dereffed asunder because of the deref in
@@ -105,7 +105,7 @@ void QThreadData::ref()
{
#if QT_CONFIG(thread)
(void) _ref.ref();
- Q_ASSERT(_ref.load() != 0);
+ Q_ASSERT(_ref.loadRelaxed() != 0);
#endif
}
@@ -839,7 +839,7 @@ bool QThread::event(QEvent* event)
return QObject::event(event);
}
-Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
+Qt::HANDLE QThread::currentThreadId() noexcept
{
return Qt::HANDLE(currentThread());
}
@@ -849,7 +849,7 @@ QThread *QThread::currentThread()
return QThreadData::current()->thread;
}
-int QThread::idealThreadCount() Q_DECL_NOTHROW
+int QThread::idealThreadCount() noexcept
{
return 1;
}
@@ -878,11 +878,11 @@ QThreadData *QThreadData::current(bool createIfNecessary)
if (!data && createIfNecessary) {
data = new QThreadData;
data->thread = new QAdoptedThread(data);
- data->threadId.store(Qt::HANDLE(data->thread));
+ data->threadId.storeRelaxed(Qt::HANDLE(data->thread));
data->deref();
data->isAdopted = true;
if (!QCoreApplicationPrivate::theMainThread)
- QCoreApplicationPrivate::theMainThread = data->thread.load();
+ QCoreApplicationPrivate::theMainThread = data->thread.loadRelaxed();
}
return data;
}
@@ -925,7 +925,7 @@ QThreadPrivate::~QThreadPrivate()
QAbstractEventDispatcher *QThread::eventDispatcher() const
{
Q_D(const QThread);
- return d->data->eventDispatcher.load();
+ return d->data->eventDispatcher.loadRelaxed();
}
/*!
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index b6c5bf47d0..c7a6dc8f1a 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -70,9 +70,9 @@ class Q_CORE_EXPORT QThread : public QObject
{
Q_OBJECT
public:
- static Qt::HANDLE currentThreadId() Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION;
+ static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION;
static QThread *currentThread();
- static int idealThreadCount() Q_DECL_NOTHROW;
+ static int idealThreadCount() noexcept;
static void yieldCurrentThread();
explicit QThread(QObject *parent = nullptr);
@@ -209,7 +209,6 @@ struct Callable
{
}
-#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
// Apply the same semantics of a lambda closure type w.r.t. the special
// member functions, if possible: delete the copy assignment operator,
// bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
@@ -218,7 +217,6 @@ struct Callable
Callable(Callable &&) = default;
Callable &operator=(const Callable &) = delete;
Callable &operator=(Callable &&) = default;
-#endif
void operator()()
{
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index 7d9442ab79..b2d1628e6e 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -89,7 +89,7 @@ public:
QEvent *event;
int priority;
inline QPostEvent()
- : receiver(0), event(0), priority(0)
+ : receiver(nullptr), event(nullptr), priority(0)
{ }
inline QPostEvent(QObject *r, QEvent *e, int p)
: receiver(r), event(e), priority(p)
@@ -148,7 +148,7 @@ private:
class Q_CORE_EXPORT QDaemonThread : public QThread
{
public:
- QDaemonThread(QObject *parent = 0);
+ QDaemonThread(QObject *parent = nullptr);
~QDaemonThread();
};
@@ -157,7 +157,7 @@ class QThreadPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QThread)
public:
- QThreadPrivate(QThreadData *d = 0);
+ QThreadPrivate(QThreadData *d = nullptr);
~QThreadPrivate();
void setPriority(QThread::Priority prio);
@@ -187,14 +187,17 @@ public:
#endif // Q_OS_UNIX
#ifdef Q_OS_WIN
- static unsigned int __stdcall start(void *) Q_DECL_NOEXCEPT;
- static void finish(void *, bool lockAnyway=true) Q_DECL_NOEXCEPT;
+ static unsigned int __stdcall start(void *) noexcept;
+ static void finish(void *, bool lockAnyway=true) noexcept;
Qt::HANDLE handle;
unsigned int id;
int waiters;
bool terminationEnabled, terminatePending;
#endif // Q_OS_WIN
+#ifdef Q_OS_WASM
+ static int idealThreadCount;
+#endif
QThreadData *data;
static QAbstractEventDispatcher *createEventDispatcher(QThreadData *data);
@@ -248,17 +251,17 @@ public:
#endif
static void clearCurrentThreadData();
static QThreadData *get2(QThread *thread)
- { Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; }
+ { Q_ASSERT_X(thread != nullptr, "QThread", "internal error"); return thread->d_func()->data; }
void ref();
void deref();
inline bool hasEventDispatcher() const
- { return eventDispatcher.load() != nullptr; }
+ { return eventDispatcher.loadRelaxed() != nullptr; }
QAbstractEventDispatcher *createEventDispatcher();
QAbstractEventDispatcher *ensureEventDispatcher()
{
- QAbstractEventDispatcher *ed = eventDispatcher.load();
+ QAbstractEventDispatcher *ed = eventDispatcher.loadRelaxed();
if (Q_LIKELY(ed))
return ed;
return createEventDispatcher();
@@ -281,7 +284,7 @@ public:
public:
FlaggedDebugSignatures() : idx(0)
- { std::fill_n(locations, Count, static_cast<char*>(0)); }
+ { std::fill_n(locations, Count, static_cast<char*>(nullptr)); }
void store(const char* method)
{ locations[idx++ % Count] = method; }
@@ -328,7 +331,7 @@ class QAdoptedThread : public QThread
Q_DECLARE_PRIVATE(QThread)
public:
- QAdoptedThread(QThreadData *data = 0);
+ QAdoptedThread(QThreadData *data = nullptr);
~QAdoptedThread();
void init();
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 695d45d8e7..89efbff6aa 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -100,7 +100,6 @@
#include <sys/neutrino.h>
#endif
-
QT_BEGIN_NAMESPACE
#if QT_CONFIG(thread)
@@ -116,6 +115,9 @@ enum { ThreadPriorityResetFlag = 0x80000000 };
#if defined(Q_CC_XLC) || defined (Q_CC_SUN)
#define HAVE_TLS
#endif
+#if defined(Q_OS_RTEMS)
+#define HAVE_TLS
+#endif
#ifdef HAVE_TLS
static __thread QThreadData *currentThreadData = 0;
@@ -250,9 +252,9 @@ QThreadData *QThreadData::current(bool createIfNecessary)
}
data->deref();
data->isAdopted = true;
- data->threadId.store(to_HANDLE(pthread_self()));
+ data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
if (!QCoreApplicationPrivate::theMainThread)
- QCoreApplicationPrivate::theMainThread = data->thread.load();
+ QCoreApplicationPrivate::theMainThread = data->thread.loadRelaxed();
}
return data;
}
@@ -332,7 +334,7 @@ void *QThreadPrivate::start(void *arg)
thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
}
- data->threadId.store(to_HANDLE(pthread_self()));
+ data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
set_thread_data(data);
data->ref();
@@ -402,7 +404,7 @@ void QThreadPrivate::finish(void *arg)
QThreadStorageData::finish((void **)data);
locker.relock();
- QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.loadRelaxed();
if (eventDispatcher) {
d->data->eventDispatcher = 0;
locker.unlock();
@@ -440,7 +442,7 @@ void QThreadPrivate::finish(void *arg)
** QThread
*************************************************************************/
-Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
+Qt::HANDLE QThread::currentThreadId() noexcept
{
// requires a C cast here otherwise we run into trouble on AIX
return to_HANDLE(pthread_self());
@@ -451,7 +453,11 @@ Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
# define _SC_NPROCESSORS_ONLN 84
#endif
-int QThread::idealThreadCount() Q_DECL_NOTHROW
+#ifdef Q_OS_WASM
+int QThreadPrivate::idealThreadCount = 1;
+#endif
+
+int QThread::idealThreadCount() noexcept
{
int cores = 1;
@@ -499,6 +505,8 @@ int QThread::idealThreadCount() Q_DECL_NOTHROW
// as of aug 2008 VxWorks < 6.6 only supports one single core CPU
cores = 1;
# endif
+#elif defined(Q_OS_WASM)
+ cores = QThreadPrivate::idealThreadCount;
#else
// the rest: Linux, Solaris, AIX, Tru64
cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
@@ -709,8 +717,7 @@ void QThread::start(Priority priority)
#endif // _POSIX_THREAD_ATTR_STACKSIZE
if (code) {
- qWarning("QThread::start: Thread stack size error: %s",
- qPrintable(qt_error_string(code)));
+ qErrnoWarning(code, "QThread::start: Thread stack size error");
// we failed to set the stacksize, and as the documentation states,
// the thread will fail to run...
@@ -736,16 +743,16 @@ void QThread::start(Priority priority)
#endif
code = pthread_create(&threadId, &attr, QThreadPrivate::start, this);
}
- d->data->threadId.store(to_HANDLE(threadId));
+ d->data->threadId.storeRelaxed(to_HANDLE(threadId));
pthread_attr_destroy(&attr);
if (code) {
- qWarning("QThread::start: Thread creation error: %s", qPrintable(qt_error_string(code)));
+ qErrnoWarning(code, "QThread::start: Thread creation error");
d->running = false;
d->finished = false;
- d->data->threadId.store(nullptr);
+ d->data->threadId.storeRelaxed(nullptr);
}
}
@@ -755,13 +762,12 @@ void QThread::terminate()
Q_D(QThread);
QMutexLocker locker(&d->mutex);
- if (!d->data->threadId.load())
+ if (!d->data->threadId.loadRelaxed())
return;
- int code = pthread_cancel(from_HANDLE<pthread_t>(d->data->threadId.load()));
+ int code = pthread_cancel(from_HANDLE<pthread_t>(d->data->threadId.loadRelaxed()));
if (code) {
- qWarning("QThread::start: Thread termination error: %s",
- qPrintable(qt_error_string((code))));
+ qErrnoWarning(code, "QThread::start: Thread termination error");
}
#endif
}
@@ -771,7 +777,7 @@ bool QThread::wait(unsigned long time)
Q_D(QThread);
QMutexLocker locker(&d->mutex);
- if (from_HANDLE<pthread_t>(d->data->threadId.load()) == pthread_self()) {
+ if (from_HANDLE<pthread_t>(d->data->threadId.loadRelaxed()) == pthread_self()) {
qWarning("QThread::wait: Thread tried to wait on itself");
return false;
}
@@ -813,7 +819,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
int sched_policy;
sched_param param;
- if (pthread_getschedparam(from_HANDLE<pthread_t>(data->threadId.load()), &sched_policy, &param) != 0) {
+ if (pthread_getschedparam(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), &sched_policy, &param) != 0) {
// failed to get the scheduling policy, don't bother setting
// the priority
qWarning("QThread::setPriority: Cannot get scheduler parameters");
@@ -829,15 +835,15 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
}
param.sched_priority = prio;
- int status = pthread_setschedparam(from_HANDLE<pthread_t>(data->threadId.load()), sched_policy, &param);
+ int status = pthread_setschedparam(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), sched_policy, &param);
# ifdef SCHED_IDLE
// were we trying to set to idle priority and failed?
if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) {
// reset to lowest priority possible
- pthread_getschedparam(from_HANDLE<pthread_t>(data->threadId.load()), &sched_policy, &param);
+ pthread_getschedparam(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), &sched_policy, &param);
param.sched_priority = sched_get_priority_min(sched_policy);
- pthread_setschedparam(from_HANDLE<pthread_t>(data->threadId.load()), sched_policy, &param);
+ pthread_setschedparam(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), sched_policy, &param);
}
# else
Q_UNUSED(status);
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index e56fe2c6ae..f8a0b0abaa 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -138,11 +138,11 @@ QThreadData *QThreadData::current(bool createIfNecessary)
}
threadData->deref();
threadData->isAdopted = true;
- threadData->threadId.store(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
+ threadData->threadId.storeRelaxed(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
#ifndef Q_OS_WINRT
if (!QCoreApplicationPrivate::theMainThread) {
- QCoreApplicationPrivate::theMainThread = threadData->thread.load();
+ QCoreApplicationPrivate::theMainThread = threadData->thread.loadRelaxed();
} else {
#else
// for winrt the main thread is set explicitly in QCoreApplication's constructor as the
@@ -184,9 +184,9 @@ void QThreadData::setMainThread()
}
threadData->deref();
threadData->isAdopted = true;
- threadData->threadId.store(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
+ threadData->threadId.storeRelaxed(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
}
- QCoreApplicationPrivate::theMainThread = threadData->thread.load();
+ QCoreApplicationPrivate::theMainThread = threadData->thread.loadRelaxed();
}
#endif
@@ -372,14 +372,14 @@ QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *dat
#if QT_CONFIG(thread)
-unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg) Q_DECL_NOEXCEPT
+unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg) noexcept
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadData *data = QThreadData::get2(thr);
qt_create_tls();
TlsSetValue(qt_current_thread_data_tls_index, data);
- data->threadId.store(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
+ data->threadId.storeRelaxed(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
QThread::setTerminationEnabled(false);
@@ -406,7 +406,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
return 0;
}
-void QThreadPrivate::finish(void *arg, bool lockAnyway) Q_DECL_NOEXCEPT
+void QThreadPrivate::finish(void *arg, bool lockAnyway) noexcept
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadPrivate *d = thr->d_func();
@@ -421,7 +421,7 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) Q_DECL_NOEXCEPT
QThreadStorageData::finish(tls_data);
locker.relock();
- QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load();
+ QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.loadRelaxed();
if (eventDispatcher) {
d->data->eventDispatcher = 0;
locker.unlock();
@@ -447,12 +447,12 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) Q_DECL_NOEXCEPT
** QThread
*************************************************************************/
-Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
+Qt::HANDLE QThread::currentThreadId() noexcept
{
return reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId()));
}
-int QThread::idealThreadCount() Q_DECL_NOTHROW
+int QThread::idealThreadCount() noexcept
{
SYSTEM_INFO sysinfo;
#ifndef Q_OS_WINRT
diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h
index 952e02ef20..01852d8366 100644
--- a/src/corelib/thread/qthreadpool_p.h
+++ b/src/corelib/thread/qthreadpool_p.h
@@ -162,7 +162,7 @@ public:
void tryToStartMoreThreads();
bool tooManyThreadsActive() const;
- void startThread(QRunnable *runnable = 0);
+ void startThread(QRunnable *runnable = nullptr);
void reset();
bool waitForDone(int msecs);
bool waitForDone(const QDeadlineTimer &timer);
diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp
index 8b82118a5c..fdc484d2d2 100644
--- a/src/corelib/thread/qthreadstorage.cpp
+++ b/src/corelib/thread/qthreadstorage.cpp
@@ -126,7 +126,7 @@ void **QThreadStorageData::get() const
DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p",
id,
*v,
- data->thread.load());
+ data->thread.loadRelaxed());
return *v ? v : 0;
}
@@ -148,7 +148,7 @@ void **QThreadStorageData::set(void *p)
DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p",
id,
value,
- data->thread.load());
+ data->thread.loadRelaxed());
QMutexLocker locker(&destructorsMutex);
DestructorMap *destr = destructors();
@@ -164,7 +164,7 @@ void **QThreadStorageData::set(void *p)
// store new data
value = p;
- DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread.load(), p);
+ DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread.loadRelaxed(), p);
return &value;
}
diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h
index 55fc482da3..9eb8672e92 100644
--- a/src/corelib/thread/qthreadstorage.h
+++ b/src/corelib/thread/qthreadstorage.h
@@ -69,7 +69,7 @@ inline
T *&qThreadStorage_localData(QThreadStorageData &d, T **)
{
void **v = d.get();
- if (!v) v = d.set(0);
+ if (!v) v = d.set(nullptr);
return *(reinterpret_cast<T**>(v));
}
@@ -139,7 +139,7 @@ public:
inline ~QThreadStorage() { }
inline bool hasLocalData() const
- { return d.get() != 0; }
+ { return d.get() != nullptr; }
inline T& localData()
{ return qThreadStorage_localData(d, reinterpret_cast<T*>(0)); }
diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp
index 0ba90763cf..dd7475cec5 100644
--- a/src/corelib/thread/qwaitcondition_unix.cpp
+++ b/src/corelib/thread/qwaitcondition_unix.cpp
@@ -72,7 +72,7 @@ __attribute__((weakref("__pthread_cond_timedwait_relative")));
static void report_error(int code, const char *where, const char *what)
{
if (code != 0)
- qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
+ qErrnoWarning(code, "%s: %s failure", where, what);
}
void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where)
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index 9b0ed18742..e34ce71212 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -58,6 +58,9 @@
#endif
#include <cmath>
+#ifdef Q_CC_MINGW
+# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
+#endif
#include <time.h>
#ifdef Q_OS_WIN
# include <qt_windows.h>
@@ -169,12 +172,11 @@ static ParsedDate getDateFromJulianDay(qint64 julianDay)
Date/Time formatting helper functions
*****************************************************************************/
-static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
#if QT_CONFIG(textdate)
static const char qt_shortMonthNames[][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
static int qt_monthNumberFromShortName(QStringRef shortName)
{
@@ -256,7 +258,7 @@ static QString toOffsetString(Qt::DateFormat format, int offset)
#if QT_CONFIG(datestring)
// Parse offset in [+-]HH[[:]mm] format
-static int fromOffsetString(const QStringRef &offsetString, bool *valid) Q_DECL_NOTHROW
+static int fromOffsetString(const QStringRef &offsetString, bool *valid) noexcept
{
*valid = false;
@@ -301,6 +303,12 @@ static int fromOffsetString(const QStringRef &offsetString, bool *valid) Q_DECL_
}
#endif // datestring
+static constexpr int daysInUsualMonth(int month) // (February isn't usual.)
+{
+ // Long if odd up to July = 7, or if even from 8 = August onwards:
+ return Q_ASSERT(month != 2 && month > 0 && month <= 12), 30 | ((month & 1) ^ (month >> 3));
+}
+
/*****************************************************************************
QDate member functions
*****************************************************************************/
@@ -417,7 +425,6 @@ QDate::QDate(int y, int m, int d)
\sa isValid()
*/
-
/*!
\fn bool QDate::isValid() const
@@ -426,7 +433,6 @@ QDate::QDate(int y, int m, int d)
\sa isNull()
*/
-
/*!
Returns the year of this date. Negative numbers indicate years
before 1 CE, such that year -44 is 44 BCE.
@@ -542,10 +548,10 @@ int QDate::daysInMonth() const
return 0;
const ParsedDate pd = getDateFromJulianDay(jd);
- if (pd.month == 2 && isLeapYear(pd.year))
- return 29;
- else
- return monthDays[pd.month];
+ if (pd.month == 2)
+ return isLeapYear(pd.year) ? 29 : 28;
+
+ return daysInUsualMonth(pd.month);
}
/*!
@@ -607,12 +613,275 @@ int QDate::weekNumber(int *yearNumber) const
Q_ASSERT(week == 53 || week == 1);
}
- if (yearNumber != 0)
+ if (yearNumber)
*yearNumber = year;
return week;
}
+static bool inDateTimeRange(qint64 jd, bool start)
+{
+ using Bounds = std::numeric_limits<qint64>;
+ if (jd < Bounds::min() + JULIAN_DAY_FOR_EPOCH)
+ return false;
+ jd -= JULIAN_DAY_FOR_EPOCH;
+ const qint64 maxDay = Bounds::max() / MSECS_PER_DAY;
+ const qint64 minDay = Bounds::min() / MSECS_PER_DAY - 1;
+ // (Divisions rounded towards zero, as MSECS_PER_DAY has factors other than two.)
+ // Range includes start of last day and end of first:
+ if (start)
+ return jd > minDay && jd <= maxDay;
+ return jd >= minDay && jd < maxDay;
+}
+
+static QDateTime toEarliest(const QDate &day, const QDateTime &form)
+{
+ const Qt::TimeSpec spec = form.timeSpec();
+ const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
+#if QT_CONFIG(timezone)
+ QTimeZone zone;
+ if (spec == Qt::TimeZone)
+ zone = form.timeZone();
+#endif
+ auto moment = [=](QTime time) {
+ switch (spec) {
+ case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
+#if QT_CONFIG(timezone)
+ case Qt::TimeZone: return QDateTime(day, time, zone);
+#endif
+ default: return QDateTime(day, time, spec);
+ }
+ };
+ // Longest routine time-zone transition is 2 hours:
+ QDateTime when = moment(QTime(2, 0));
+ if (!when.isValid()) {
+ // Noon should be safe ...
+ when = moment(QTime(12, 0));
+ if (!when.isValid()) {
+ // ... unless it's a 24-hour jump (moving the date-line)
+ when = moment(QTime(23, 59, 59, 999));
+ if (!when.isValid())
+ return QDateTime();
+ }
+ }
+ int high = when.time().msecsSinceStartOfDay() / 60000;
+ int low = 0;
+ // Binary chop to the right minute
+ while (high > low + 1) {
+ int mid = (high + low) / 2;
+ QDateTime probe = moment(QTime(mid / 60, mid % 60));
+ if (probe.isValid() && probe.date() == day) {
+ high = mid;
+ when = probe;
+ } else {
+ low = mid;
+ }
+ }
+ return when;
+}
+
+/*!
+ \since 5.14
+ \fn QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
+ \fn QDateTime QDate::startOfDay(const QTimeZone &zone) const
+
+ Returns the start-moment of the day. Usually, this shall be midnight at the
+ start of the day: however, if a time-zone transition causes the given date
+ to skip over that midnight (e.g. a DST spring-forward skipping from the end
+ of the previous day to 01:00 of the new day), the actual earliest time in
+ the day is returned. This can only arise when the start-moment is specified
+ in terms of a time-zone (by passing its QTimeZone as \a zone) or in terms of
+ local time (by passing Qt::LocalTime as \a spec; this is its default).
+
+ The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
+ gives the implied zone's offset from UTC. As UTC and such zones have no
+ transitions, the start of the day is QTime(0, 0) in these cases.
+
+ In the rare case of a date that was entirely skipped (this happens when a
+ zone east of the international date-line switches to being west of it), the
+ return shall be invalid. Passing Qt::TimeZone as \a spec (instead of
+ passing a QTimeZone) or passing an invalid time-zone as \a zone will also
+ produce an invalid result, as shall dates that start outside the range
+ representable by QDateTime.
+
+ \sa endOfDay()
+*/
+QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const
+{
+ if (!inDateTimeRange(jd, true))
+ return QDateTime();
+
+ switch (spec) {
+ case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
+ qWarning() << "Called QDate::startOfDay(Qt::TimeZone) on" << *this;
+ return QDateTime();
+ case Qt::OffsetFromUTC:
+ case Qt::UTC:
+ return QDateTime(*this, QTime(0, 0), spec, offsetSeconds);
+
+ case Qt::LocalTime:
+ if (offsetSeconds)
+ qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
+ break;
+ }
+ QDateTime when(*this, QTime(0, 0), spec);
+ if (!when.isValid())
+ when = toEarliest(*this, when);
+
+ return when.isValid() ? when : QDateTime();
+}
+
+#if QT_CONFIG(timezone)
+/*!
+ \overload
+ \since 5.14
+*/
+QDateTime QDate::startOfDay(const QTimeZone &zone) const
+{
+ if (!inDateTimeRange(jd, true) || !zone.isValid())
+ return QDateTime();
+
+ QDateTime when(*this, QTime(0, 0), zone);
+ if (when.isValid())
+ return when;
+
+ // The start of the day must have fallen in a spring-forward's gap; find the spring-forward:
+ if (zone.hasTransitions()) {
+ QTimeZone::OffsetData tran = zone.previousTransition(QDateTime(*this, QTime(23, 59, 59, 999), zone));
+ const QDateTime &at = tran.atUtc.toTimeZone(zone);
+ if (at.isValid() && at.date() == *this)
+ return at;
+ }
+
+ when = toEarliest(*this, when);
+ return when.isValid() ? when : QDateTime();
+}
+#endif // timezone
+
+static QDateTime toLatest(const QDate &day, const QDateTime &form)
+{
+ const Qt::TimeSpec spec = form.timeSpec();
+ const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
+#if QT_CONFIG(timezone)
+ QTimeZone zone;
+ if (spec == Qt::TimeZone)
+ zone = form.timeZone();
+#endif
+ auto moment = [=](QTime time) {
+ switch (spec) {
+ case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset);
+#if QT_CONFIG(timezone)
+ case Qt::TimeZone: return QDateTime(day, time, zone);
+#endif
+ default: return QDateTime(day, time, spec);
+ }
+ };
+ // Longest routine time-zone transition is 2 hours:
+ QDateTime when = moment(QTime(21, 59, 59, 999));
+ if (!when.isValid()) {
+ // Noon should be safe ...
+ when = moment(QTime(12, 0));
+ if (!when.isValid()) {
+ // ... unless it's a 24-hour jump (moving the date-line)
+ when = moment(QTime(0, 0));
+ if (!when.isValid())
+ return QDateTime();
+ }
+ }
+ int high = 24 * 60;
+ int low = when.time().msecsSinceStartOfDay() / 60000;
+ // Binary chop to the right minute
+ while (high > low + 1) {
+ int mid = (high + low) / 2;
+ QDateTime probe = moment(QTime(mid / 60, mid % 60, 59, 999));
+ if (probe.isValid() && probe.date() == day) {
+ low = mid;
+ when = probe;
+ } else {
+ high = mid;
+ }
+ }
+ return when;
+}
+
+/*!
+ \since 5.14
+ \fn QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
+ \fn QDateTime QDate::endOfDay(const QTimeZone &zone) const
+
+ Returns the end-moment of the day. Usually, this is one millisecond before
+ the midnight at the end of the day: however, if a time-zone transition
+ causes the given date to skip over that midnight (e.g. a DST spring-forward
+ skipping from just before 23:00 to the start of the next day), the actual
+ latest time in the day is returned. This can only arise when the
+ start-moment is specified in terms of a time-zone (by passing its QTimeZone
+ as \a zone) or in terms of local time (by passing Qt::LocalTime as \a spec;
+ this is its default).
+
+ The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it
+ gives the implied zone's offset from UTC. As UTC and such zones have no
+ transitions, the end of the day is QTime(23, 59, 59, 999) in these cases.
+
+ In the rare case of a date that was entirely skipped (this happens when a
+ zone east of the international date-line switches to being west of it), the
+ return shall be invalid. Passing Qt::TimeZone as \a spec (instead of
+ passing a QTimeZone) will also produce an invalid result, as shall dates
+ that end outside the range representable by QDateTime.
+
+ \sa startOfDay()
+*/
+QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const
+{
+ if (!inDateTimeRange(jd, false))
+ return QDateTime();
+
+ switch (spec) {
+ case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone
+ qWarning() << "Called QDate::endOfDay(Qt::TimeZone) on" << *this;
+ return QDateTime();
+ case Qt::UTC:
+ case Qt::OffsetFromUTC:
+ return QDateTime(*this, QTime(23, 59, 59, 999), spec, offsetSeconds);
+
+ case Qt::LocalTime:
+ if (offsetSeconds)
+ qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds);
+ break;
+ }
+ QDateTime when(*this, QTime(23, 59, 59, 999), spec);
+ if (!when.isValid())
+ when = toLatest(*this, when);
+ return when.isValid() ? when : QDateTime();
+}
+
+#if QT_CONFIG(timezone)
+/*!
+ \overload
+ \since 5.14
+*/
+QDateTime QDate::endOfDay(const QTimeZone &zone) const
+{
+ if (!inDateTimeRange(jd, false) || !zone.isValid())
+ return QDateTime();
+
+ QDateTime when(*this, QTime(23, 59, 59, 999), zone);
+ if (when.isValid())
+ return when;
+
+ // The end of the day must have fallen in a spring-forward's gap; find the spring-forward:
+ if (zone.hasTransitions()) {
+ QTimeZone::OffsetData tran = zone.nextTransition(QDateTime(*this, QTime(0, 0), zone));
+ const QDateTime &at = tran.atUtc.toTimeZone(zone);
+ if (at.isValid() && at.date() == *this)
+ return at;
+ }
+
+ when = toLatest(*this, when);
+ return when.isValid() ? when : QDateTime();
+}
+#endif // timezone
+
#if QT_DEPRECATED_SINCE(5, 11) && QT_CONFIG(textdate)
+
/*!
\since 4.5
\deprecated
@@ -1208,8 +1477,6 @@ qint64 QDate::daysTo(const QDate &d) const
#if QT_CONFIG(datestring)
/*!
- \fn QDate QDate::fromString(const QString &string, Qt::DateFormat format)
-
Returns the QDate represented by the \a string, using the
\a format given, or an invalid date if the string cannot be
parsed.
@@ -1220,7 +1487,8 @@ qint64 QDate::daysTo(const QDate &d) const
\sa toString(), QLocale::toDate()
*/
-QDate QDate::fromString(const QString& string, Qt::DateFormat format)
+
+QDate QDate::fromString(const QString &string, Qt::DateFormat format)
{
if (string.isEmpty())
return QDate();
@@ -1246,19 +1514,17 @@ QDate QDate::fromString(const QString& string, Qt::DateFormat format)
if (parts.count() != 4)
return QDate();
- QStringRef monthName = parts.at(1);
- const int month = fromShortMonthName(monthName);
- if (month == -1) {
- // Month name matches neither English nor other localised name.
- return QDate();
- }
-
bool ok = false;
int year = parts.at(3).toInt(&ok);
- if (!ok)
+ int day = ok ? parts.at(2).toInt(&ok) : 0;
+ if (!ok || !day)
return QDate();
- return QDate(year, month, parts.at(2).toInt());
+ const int month = fromShortMonthName(parts.at(1));
+ if (month == -1) // Month name matches no English or localised name.
+ return QDate();
+
+ return QDate(year, month, day);
}
#endif // textdate
case Qt::ISODate: {
@@ -1277,8 +1543,6 @@ QDate QDate::fromString(const QString& string, Qt::DateFormat format)
}
/*!
- \fn QDate QDate::fromString(const QString &string, const QString &format)
-
Returns the QDate represented by the \a string, using the \a
format given, or an invalid date if the string cannot be parsed.
@@ -1371,12 +1635,9 @@ QDate QDate::fromString(const QString &string, const QString &format)
bool QDate::isValid(int year, int month, int day)
{
- // there is no year 0 in the Gregorian calendar
- if (year == 0)
- return false;
-
- return (day > 0 && month > 0 && month <= 12) &&
- (day <= monthDays[month] || (day == 29 && month == 2 && isLeapYear(year)));
+ // There is no year 0 in the Gregorian calendar.
+ return year && day > 0 && month > 0 && month <= 12 &&
+ day <= (month == 2 ? isLeapYear(year) ? 29 : 28 : daysInUsualMonth(month));
}
/*!
@@ -1421,12 +1682,10 @@ bool QDate::isLeapYear(int y)
\brief The QTime class provides clock time functions.
- A QTime object contains a clock time, which it can express as the
- numbers of hours, minutes, seconds, and milliseconds since
- midnight. It can read the current time from the system clock and
- measure a span of elapsed time. It provides functions for
- comparing times and for manipulating a time by adding a number of
- milliseconds.
+ A QTime object contains a clock time, which it can express as the numbers of
+ hours, minutes, seconds, and milliseconds since midnight. It provides
+ functions for comparing times and for manipulating a time by adding a number
+ of milliseconds.
QTime uses the 24-hour clock format; it has no concept of AM/PM.
Unlike QDateTime, QTime knows nothing about time zones or
@@ -1451,18 +1710,15 @@ bool QDate::isLeapYear(int y)
objects; an earlier time is considered smaller than a later one;
if A.msecsTo(B) is positive, then A < B.
- QTime can be used to measure a span of elapsed time using the
- start(), restart(), and elapsed() functions.
-
\sa QDate, QDateTime
*/
/*!
\fn QTime::QTime()
- Constructs a null time object. A null time can be a QTime(0, 0, 0, 0)
- (i.e., midnight) object, except that isNull() returns \c true and isValid()
- returns \c false.
+ Constructs a null time object. For a null time, isNull() returns \c true and
+ isValid() returns \c false. If you need a zero time, use QTime(0, 0). For
+ the start of a day, see QDate::startOfDay().
\sa isNull(), isValid()
*/
@@ -1976,8 +2232,6 @@ static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format,
}
/*!
- \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
-
Returns the time represented in the \a string as a QTime using the
\a format given, or an invalid time if this is not possible.
@@ -1989,7 +2243,7 @@ static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format,
\sa toString(), QLocale::toTime()
*/
-QTime QTime::fromString(const QString& string, Qt::DateFormat format)
+QTime QTime::fromString(const QString &string, Qt::DateFormat format)
{
if (string.isEmpty())
return QTime();
@@ -2011,13 +2265,11 @@ QTime QTime::fromString(const QString& string, Qt::DateFormat format)
case Qt::ISODateWithMs:
case Qt::TextDate:
default:
- return fromIsoTimeString(QStringRef(&string), format, 0);
+ return fromIsoTimeString(QStringRef(&string), format, nullptr);
}
}
/*!
- \fn QTime QTime::fromString(const QString &string, const QString &format)
-
Returns the QTime represented by the \a string, using the \a
format given, or an invalid time if the string cannot be parsed.
@@ -2107,7 +2359,7 @@ bool QTime::isValid(int h, int m, int s, int ms)
return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
}
-
+#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove
/*!
Sets this time to the current time. This is practical for timing:
@@ -2176,6 +2428,7 @@ int QTime::elapsed() const
n += 86400 * 1000;
return n;
}
+#endif // Use QElapsedTimer instead !
/*****************************************************************************
QDateTime static helper functions
@@ -2185,16 +2438,6 @@ int QTime::elapsed() const
typedef QDateTimePrivate::QDateTimeShortData ShortData;
typedef QDateTimePrivate::QDateTimeData QDateTimeData;
-// Calls the platform variant of tzset
-static void qt_tzset()
-{
-#if defined(Q_OS_WIN)
- _tzset();
-#else
- tzset();
-#endif // Q_OS_WIN
-}
-
// Returns the platform variant of timezone, i.e. the standard time offset
// The timezone external variable is documented as always holding the
// Standard Time offset as seconds west of Greenwich, i.e. UTC+01:00 is -3600
@@ -2269,7 +2512,7 @@ int QDateTimeParser::startsWithLocalTimeZone(const QStringRef name)
// then null date/time will be returned, you should adjust the date first if
// you need a guaranteed result.
static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStatus *daylightStatus,
- QString *abbreviation, bool *ok = 0)
+ QString *abbreviation, bool *ok = nullptr)
{
const qint64 msec = time->msec();
int yy, mm, dd;
@@ -2292,7 +2535,7 @@ static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStat
#if defined(Q_OS_WIN)
int hh = local.tm_hour;
#endif // Q_OS_WIN
- time_t secsSinceEpoch = mktime(&local);
+ time_t secsSinceEpoch = qMkTime(&local);
if (secsSinceEpoch != time_t(-1)) {
*date = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
*time = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec);
@@ -2351,14 +2594,14 @@ static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localT
tm local;
bool valid = false;
- // localtime() is required to work as if tzset() was called before it.
- // localtime_r() does not have this requirement, so make an explicit call.
+ // localtime() is specified to work as if it called tzset().
+ // localtime_r() does not have this constraint, so make an explicit call.
// The explicit call should also request the timezone info be re-parsed.
- qt_tzset();
+ qTzSet();
#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
// Use the reentrant version of localtime() where available
// as is thread-safe and doesn't use a shared static data area
- tm *res = 0;
+ tm *res = nullptr;
res = localtime_r(&secsSinceEpoch, &local);
if (res)
valid = true;
@@ -2368,7 +2611,7 @@ static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localT
#else
// Returns shared static data which may be overwritten at any time
// So copy the result asap
- tm *res = 0;
+ tm *res = nullptr;
res = localtime(&secsSinceEpoch);
if (res) {
local = *res;
@@ -2402,8 +2645,8 @@ static void msecsToTime(qint64 msecs, QDate *date, QTime *time)
qint64 jd = JULIAN_DAY_FOR_EPOCH;
qint64 ds = 0;
- if (qAbs(msecs) >= MSECS_PER_DAY) {
- jd += (msecs / MSECS_PER_DAY);
+ if (msecs >= MSECS_PER_DAY || msecs <= -MSECS_PER_DAY) {
+ jd += msecs / MSECS_PER_DAY;
msecs %= MSECS_PER_DAY;
}
@@ -2431,12 +2674,12 @@ static qint64 timeToMSecs(const QDate &date, const QTime &time)
// Convert an MSecs Since Epoch into Local Time
static bool epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTime *localTime,
- QDateTimePrivate::DaylightStatus *daylightStatus = 0)
+ QDateTimePrivate::DaylightStatus *daylightStatus = nullptr)
{
if (msecs < 0) {
// Docs state any LocalTime before 1970-01-01 will *not* have any Daylight Time applied
// Instead just use the standard offset from UTC to convert to UTC time
- qt_tzset();
+ qTzSet();
msecsToTime(msecs - qt_timezone() * 1000, localDate, localTime);
if (daylightStatus)
*daylightStatus = QDateTimePrivate::StandardTime;
@@ -2471,8 +2714,8 @@ static bool epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTime *localTi
// values from mktime for the adjusted local date and time.
static qint64 localMSecsToEpochMSecs(qint64 localMsecs,
QDateTimePrivate::DaylightStatus *daylightStatus,
- QDate *localDate = 0, QTime *localTime = 0,
- QString *abbreviation = 0)
+ QDate *localDate = nullptr, QTime *localTime = nullptr,
+ QString *abbreviation = nullptr)
{
QDate dt;
QTime tm;
@@ -2499,7 +2742,7 @@ static qint64 localMSecsToEpochMSecs(qint64 localMsecs,
}
} else {
// If we don't call mktime then need to call tzset to get offset
- qt_tzset();
+ qTzSet();
}
// Time is clearly before 1970-01-01 so just use standard offset to convert
qint64 utcMsecs = localMsecs + qt_timezone() * 1000;
@@ -2775,7 +3018,7 @@ static void setDateTime(QDateTimeData &d, const QDate &date, const QTime &time)
if (!useTime.isValid() && date.isValid())
useTime = QTime::fromMSecsSinceStartOfDay(0);
- QDateTimePrivate::StatusFlags newStatus = 0;
+ QDateTimePrivate::StatusFlags newStatus = { };
// Set date value and status
qint64 days = 0;
@@ -2853,7 +3096,7 @@ inline QDateTime::Data::Data(Qt::TimeSpec spec)
// the structure is too small, we need to detach
d = new QDateTimePrivate;
d->ref.ref();
- d->m_status = mergeSpec(0, spec);
+ d->m_status = mergeSpec(nullptr, spec);
}
}
@@ -2938,13 +3181,13 @@ inline void QDateTime::Data::detach()
x->m_status = QDateTimePrivate::StatusFlag(data.status & ~QDateTimePrivate::ShortData);
x->m_msecs = data.msecs;
} else {
- if (d->ref.load() == 1)
+ if (d->ref.loadRelaxed() == 1)
return;
x = new QDateTimePrivate(*d);
}
- x->ref.store(1);
+ x->ref.storeRelaxed(1);
if (!wasShort && !d->ref.deref())
delete d;
d = x;
@@ -2960,7 +3203,7 @@ inline QDateTimePrivate *QDateTime::Data::operator->()
{
// should we attempt to detach here?
Q_ASSERT(!isShort());
- Q_ASSERT(d->ref.load() == 1);
+ Q_ASSERT(d->ref.loadRelaxed() == 1);
return d;
}
@@ -3149,7 +3392,7 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
\sa isValid()
*/
-QDateTime::QDateTime() Q_DECL_NOEXCEPT_EXPR(Data::CanBeSmall)
+QDateTime::QDateTime() noexcept(Data::CanBeSmall)
{
}
@@ -3160,7 +3403,7 @@ QDateTime::QDateTime() Q_DECL_NOEXCEPT_EXPR(Data::CanBeSmall)
*/
QDateTime::QDateTime(const QDate &date)
- : d(QDateTimePrivate::create(date, QTime(0, 0, 0), Qt::LocalTime, 0))
+ : d(QDateTimePrivate::create(date, QTime(0, 0), Qt::LocalTime, 0))
{
}
@@ -3228,7 +3471,7 @@ QDateTime::QDateTime(const QDate &date, const QTime &time, const QTimeZone &time
/*!
Constructs a copy of the \a other datetime.
*/
-QDateTime::QDateTime(const QDateTime &other) Q_DECL_NOTHROW
+QDateTime::QDateTime(const QDateTime &other) noexcept
: d(other.d)
{
}
@@ -3238,7 +3481,7 @@ QDateTime::QDateTime(const QDateTime &other) Q_DECL_NOTHROW
Moves the content of the temporary \a other datetime to this object and
leaves \a other in an unspecified (but proper) state.
*/
-QDateTime::QDateTime(QDateTime &&other) Q_DECL_NOTHROW
+QDateTime::QDateTime(QDateTime &&other) noexcept
: d(std::move(other.d))
{
}
@@ -3255,7 +3498,7 @@ QDateTime::~QDateTime()
copy.
*/
-QDateTime &QDateTime::operator=(const QDateTime &other) Q_DECL_NOTHROW
+QDateTime &QDateTime::operator=(const QDateTime &other) noexcept
{
d = other.d;
return *this;
@@ -3312,7 +3555,7 @@ QDate QDateTime::date() const
if (!status.testFlag(QDateTimePrivate::ValidDate))
return QDate();
QDate dt;
- msecsToTime(getMSecs(d), &dt, 0);
+ msecsToTime(getMSecs(d), &dt, nullptr);
return dt;
}
@@ -3328,7 +3571,7 @@ QTime QDateTime::time() const
if (!status.testFlag(QDateTimePrivate::ValidTime))
return QTime();
QTime tm;
- msecsToTime(getMSecs(d), 0, &tm);
+ msecsToTime(getMSecs(d), nullptr, &tm);
return tm;
}
@@ -3446,7 +3689,7 @@ QString QDateTime::timeZoneAbbreviation() const
case Qt::LocalTime: {
QString abbrev;
auto status = extractDaylightStatus(getStatus(d));
- localMSecsToEpochMSecs(getMSecs(d), &status, 0, 0, &abbrev);
+ localMSecsToEpochMSecs(getMSecs(d), &status, nullptr, nullptr, &abbrev);
return abbrev;
}
}
@@ -4483,7 +4726,7 @@ QDateTime QDateTime::currentDateTimeUtc()
return QDateTime(d, t, Qt::UTC);
}
-qint64 QDateTime::currentMSecsSinceEpoch() Q_DECL_NOTHROW
+qint64 QDateTime::currentMSecsSinceEpoch() noexcept
{
SYSTEMTIME st;
memset(&st, 0, sizeof(SYSTEMTIME));
@@ -4494,7 +4737,7 @@ qint64 QDateTime::currentMSecsSinceEpoch() Q_DECL_NOTHROW
- julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400000);
}
-qint64 QDateTime::currentSecsSinceEpoch() Q_DECL_NOTHROW
+qint64 QDateTime::currentSecsSinceEpoch() noexcept
{
SYSTEMTIME st;
memset(&st, 0, sizeof(SYSTEMTIME));
@@ -4526,19 +4769,19 @@ QDateTime QDateTime::currentDateTimeUtc()
return fromMSecsSinceEpoch(currentMSecsSinceEpoch(), Qt::UTC);
}
-qint64 QDateTime::currentMSecsSinceEpoch() Q_DECL_NOTHROW
+qint64 QDateTime::currentMSecsSinceEpoch() noexcept
{
// posix compliant system
// we have milliseconds
struct timeval tv;
- gettimeofday(&tv, 0);
+ gettimeofday(&tv, nullptr);
return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000;
}
-qint64 QDateTime::currentSecsSinceEpoch() Q_DECL_NOTHROW
+qint64 QDateTime::currentSecsSinceEpoch() noexcept
{
struct timeval tv;
- gettimeofday(&tv, 0);
+ gettimeofday(&tv, nullptr);
return qint64(tv.tv_sec);
}
#else
@@ -4752,8 +4995,6 @@ int QDateTime::utcOffset() const
#if QT_CONFIG(datestring)
/*!
- \fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
-
Returns the QDateTime represented by the \a string, using the
\a format given, or an invalid datetime if this is not possible.
@@ -4763,7 +5004,7 @@ int QDateTime::utcOffset() const
\sa toString(), QLocale::toDateTime()
*/
-QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
+QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
{
if (string.isEmpty())
return QDateTime();
@@ -4862,48 +5103,45 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
return QDateTime();
// Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974"
+
+ // Year and time can be in either order.
+ // Guess which by looking for ':' in the time
+ int yearPart = 3;
+ int timePart = 3;
+ if (parts.at(3).contains(QLatin1Char(':')))
+ yearPart = 4;
+ else if (parts.at(4).contains(QLatin1Char(':')))
+ timePart = 4;
+ else
+ return QDateTime();
+
int month = 0;
int day = 0;
bool ok = false;
- // First try month then day
+ int year = parts.at(yearPart).toInt(&ok);
+ if (!ok || year == 0)
+ return QDateTime();
+
+ // Next try month then day
month = fromShortMonthName(parts.at(1));
if (month)
- day = parts.at(2).toInt();
+ day = parts.at(2).toInt(&ok);
- // If failed try day then month
- if (!month || !day) {
+ // If failed, try day then month
+ if (!ok || !month || !day) {
month = fromShortMonthName(parts.at(2));
if (month) {
QStringRef dayStr = parts.at(1);
if (dayStr.endsWith(QLatin1Char('.'))) {
dayStr = dayStr.left(dayStr.size() - 1);
- day = dayStr.toInt();
+ day = dayStr.toInt(&ok);
}
}
}
// If both failed, give up
- if (!month || !day)
- return QDateTime();
-
- // Year can be before or after time, "Sun Dec 1 1974 13:02:00" or "Sun Dec 1 13:02:00 1974"
- // Guess which by looking for ':' in the time
- int year = 0;
- int yearPart = 0;
- int timePart = 0;
- if (parts.at(3).contains(QLatin1Char(':'))) {
- yearPart = 4;
- timePart = 3;
- } else if (parts.at(4).contains(QLatin1Char(':'))) {
- yearPart = 3;
- timePart = 4;
- } else {
- return QDateTime();
- }
-
- year = parts.at(yearPart).toInt(&ok);
- if (!ok)
+ if (!ok || !month || !day)
return QDateTime();
QDate date(year, month, day);
@@ -4970,8 +5208,6 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
}
/*!
- \fn QDateTime QDateTime::fromString(const QString &string, const QString &format)
-
Returns the QDateTime represented by the \a string, using the \a
format given, or an invalid datetime if the string cannot be parsed.
@@ -5432,7 +5668,7 @@ uint qHash(const QDateTime &key, uint seed)
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-uint qHash(const QDate &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QDate &key, uint seed) noexcept
{
return qHash(key.toJulianDay(), seed);
}
@@ -5443,7 +5679,7 @@ uint qHash(const QDate &key, uint seed) Q_DECL_NOTHROW
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-uint qHash(const QTime &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QTime &key, uint seed) noexcept
{
return qHash(key.msecsSinceStartOfDay(), seed);
}
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/time/qdatetime.h
index 43271b34ed..3e3b953b52 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/time/qdatetime.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -55,6 +55,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSDate);
QT_BEGIN_NAMESPACE
class QTimeZone;
+class QDateTime;
class Q_CORE_EXPORT QDate
{
@@ -81,6 +82,13 @@ public:
int daysInYear() const;
int weekNumber(int *yearNum = nullptr) const;
+ QDateTime startOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const;
+ QDateTime endOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const;
+#if QT_CONFIG(timezone)
+ QDateTime startOfDay(const QTimeZone &zone) const;
+ QDateTime endOfDay(const QTimeZone &zone) const;
+#endif
+
#if QT_DEPRECATED_SINCE(5, 10) && QT_CONFIG(textdate)
QT_DEPRECATED_X("Use QLocale::monthName or QLocale::standaloneMonthName")
static QString shortMonthName(int month, MonthNameType type = DateFormat);
@@ -99,8 +107,8 @@ public:
QString toString(QStringView format) const;
#endif
#if QT_DEPRECATED_SINCE(5,0)
-QT_DEPRECATED inline bool setYMD(int y, int m, int d)
-{ if (uint(y) <= 99) y += 1900; return setDate(y, m, d); }
+ QT_DEPRECATED_X("Use setDate() instead") inline bool setYMD(int y, int m, int d)
+ { if (uint(y) <= 99) y += 1900; return setDate(y, m, d); }
#endif
bool setDate(int year, int month, int day);
@@ -198,9 +206,11 @@ public:
#endif
static bool isValid(int h, int m, int s, int ms = 0);
- void start();
- int restart();
- int elapsed() const;
+#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove
+ QT_DEPRECATED_X("Use QElapsedTimer instead") void start();
+ QT_DEPRECATED_X("Use QElapsedTimer instead") int restart();
+ QT_DEPRECATED_X("Use QElapsedTimer instead") int elapsed() const;
+#endif
private:
enum TimeFlag { NullTime = -1 };
Q_DECL_CONSTEXPR inline int ds() const { return mds == -1 ? 0 : mds; }
@@ -258,7 +268,7 @@ class Q_CORE_EXPORT QDateTime
};
public:
- QDateTime() Q_DECL_NOEXCEPT_EXPR(Data::CanBeSmall);
+ QDateTime() noexcept(Data::CanBeSmall);
explicit QDateTime(const QDate &);
QDateTime(const QDate &, const QTime &, Qt::TimeSpec spec = Qt::LocalTime);
// ### Qt 6: Merge with above with default offsetSeconds = 0
@@ -266,16 +276,14 @@ public:
#if QT_CONFIG(timezone)
QDateTime(const QDate &date, const QTime &time, const QTimeZone &timeZone);
#endif // timezone
- QDateTime(const QDateTime &other) Q_DECL_NOTHROW;
- QDateTime(QDateTime &&other) Q_DECL_NOTHROW;
+ QDateTime(const QDateTime &other) noexcept;
+ QDateTime(QDateTime &&other) noexcept;
~QDateTime();
-#ifdef Q_COMPILER_RVALUE_REFS
- QDateTime &operator=(QDateTime &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
- QDateTime &operator=(const QDateTime &other) Q_DECL_NOTHROW;
+ QDateTime &operator=(QDateTime &&other) noexcept { swap(other); return *this; }
+ QDateTime &operator=(const QDateTime &other) noexcept;
- void swap(QDateTime &other) Q_DECL_NOTHROW { qSwap(d.d, other.d.d); }
+ void swap(QDateTime &other) noexcept { qSwap(d.d, other.d.d); }
bool isNull() const;
bool isValid() const;
@@ -335,9 +343,9 @@ public:
inline bool operator>(const QDateTime &other) const { return other < *this; }
inline bool operator>=(const QDateTime &other) const { return !(*this < other); }
-#if QT_DEPRECATED_SINCE(5, 2)
- QT_DEPRECATED void setUtcOffset(int seconds);
- QT_DEPRECATED int utcOffset() const;
+#if QT_DEPRECATED_SINCE(5, 2) // ### Qt 6: remove
+ QT_DEPRECATED_X("Use setOffsetFromUtc() instead") void setUtcOffset(int seconds);
+ QT_DEPRECATED_X("Use offsetFromUtc() instead") int utcOffset() const;
#endif // QT_DEPRECATED_SINCE
static QDateTime currentDateTime();
@@ -366,8 +374,8 @@ public:
static QDateTime fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone);
#endif
- static qint64 currentMSecsSinceEpoch() Q_DECL_NOTHROW;
- static qint64 currentSecsSinceEpoch() Q_DECL_NOTHROW;
+ static qint64 currentMSecsSinceEpoch() noexcept;
+ static qint64 currentSecsSinceEpoch() noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
static QDateTime fromCFDate(CFDateRef date);
@@ -410,8 +418,8 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QDateTime &);
// QDateTime is not noexcept for now -- to be revised once
// timezone and calendaring support is added
Q_CORE_EXPORT uint qHash(const QDateTime &key, uint seed = 0);
-Q_CORE_EXPORT uint qHash(const QDate &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT uint qHash(const QTime &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT uint qHash(const QDate &key, uint seed = 0) noexcept;
+Q_CORE_EXPORT uint qHash(const QTime &key, uint seed = 0) noexcept;
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/time/qdatetime_p.h
index b3d00745d0..6018f8f7b0 100644
--- a/src/corelib/tools/qdatetime_p.h
+++ b/src/corelib/time/qdatetime_p.h
@@ -135,7 +135,7 @@ public:
#if QT_CONFIG(timezone)
static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone,
DaylightStatus hint = UnknownDaylightTime,
- QDate *localDate = 0, QTime *localTime = 0);
+ QDate *localDate = nullptr, QTime *localTime = nullptr);
// Inlined for its one caller in qdatetime.cpp
inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch);
diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
index e8470f6cde..728b066db1 100644
--- a/src/corelib/tools/qdatetimeparser.cpp
+++ b/src/corelib/time/qdatetimeparser.cpp
@@ -47,7 +47,6 @@
#if QT_CONFIG(timezone)
#include "qtimezone.h"
#endif
-#include "qregexp.h"
#include "qdebug.h"
//#define QDATETIMEPARSER_DEBUG
@@ -78,8 +77,8 @@ int QDateTimeParser::getDigit(const QDateTime &t, int index) const
{
if (index < 0 || index >= sectionNodes.size()) {
#if QT_CONFIG(datestring)
- qWarning("QDateTimeParser::getDigit() Internal error (%s %d)",
- qPrintable(t.toString()), index);
+ qWarning("QDateTimeParser::getDigit() Internal error (%ls %d)",
+ qUtf16Printable(t.toString()), index);
#else
qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
#endif
@@ -104,8 +103,8 @@ int QDateTimeParser::getDigit(const QDateTime &t, int index) const
}
#if QT_CONFIG(datestring)
- qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)",
- qPrintable(t.toString()), index);
+ qWarning("QDateTimeParser::getDigit() Internal error 2 (%ls %d)",
+ qUtf16Printable(t.toString()), index);
#else
qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index);
#endif
@@ -128,8 +127,8 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
{
if (index < 0 || index >= sectionNodes.size()) {
#if QT_CONFIG(datestring)
- qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)",
- qPrintable(v.toString()), index, newVal);
+ qWarning("QDateTimeParser::setDigit() Internal error (%ls %d %d)",
+ qUtf16Printable(v.toString()), index, newVal);
#else
qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
#endif
@@ -177,8 +176,8 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
break;
case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
default:
- qWarning("QDateTimeParser::setDigit() Internal error (%s)",
- qPrintable(node.name()));
+ qWarning("QDateTimeParser::setDigit() Internal error (%ls)",
+ qUtf16Printable(node.name()));
break;
}
@@ -239,8 +238,8 @@ int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
case AmPmSection: return 1;
default: break;
}
- qWarning("QDateTimeParser::absoluteMax() Internal error (%s)",
- qPrintable(sn.name()));
+ qWarning("QDateTimeParser::absoluteMax() Internal error (%ls)",
+ qUtf16Printable(sn.name()));
return -1;
}
@@ -271,8 +270,8 @@ int QDateTimeParser::absoluteMin(int s) const
case AmPmSection: return 0;
default: break;
}
- qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)",
- qPrintable(sn.name()), sn.type);
+ qWarning("QDateTimeParser::absoluteMin() Internal error (%ls, %0x)",
+ qUtf16Printable(sn.name()), sn.type);
return -1;
}
@@ -327,7 +326,7 @@ int QDateTimeParser::sectionPos(const SectionNode &sn) const
default: break;
}
if (sn.pos == -1) {
- qWarning("QDateTimeParser::sectionPos Internal error (%s)", qPrintable(sn.name()));
+ qWarning("QDateTimeParser::sectionPos Internal error (%ls)", qUtf16Printable(sn.name()));
return -1;
}
return sn.pos;
@@ -734,8 +733,8 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
ParsedSection result; // initially Invalid
const SectionNode &sn = sectionNode(sectionIndex);
if (sn.type & Internal) {
- qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
- qPrintable(sn.name()), sectionIndex);
+ qWarning("QDateTimeParser::parseSection Internal error (%ls %d)",
+ qUtf16Printable(sn.name()), sectionIndex);
return result;
}
@@ -885,8 +884,8 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
}
break; }
default:
- qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
- qPrintable(sn.name()), sectionIndex);
+ qWarning("QDateTimeParser::parseSection Internal error (%ls %d)",
+ qUtf16Printable(sn.name()), sectionIndex);
return result;
}
Q_ASSERT(result.state != Invalid || result.value == -1);
@@ -1200,8 +1199,8 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
case DaySection: current = &day; sect.value = qMax<int>(1, sect.value); break;
case AmPmSection: current = &ampm; break;
default:
- qWarning("QDateTimeParser::parse Internal error (%s)",
- qPrintable(sn.name()));
+ qWarning("QDateTimeParser::parse Internal error (%ls)",
+ qUtf16Printable(sn.name()));
break;
}
@@ -1391,8 +1390,8 @@ QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValu
if (context != FromString && scan.value < minimum) {
const QLatin1Char space(' ');
if (scan.value >= minimum)
- qWarning("QDateTimeParser::parse Internal error 3 (%s %s)",
- qPrintable(scan.value.toString()), qPrintable(minimum.toString()));
+ qWarning("QDateTimeParser::parse Internal error 3 (%ls %ls)",
+ qUtf16Printable(scan.value.toString()), qUtf16Printable(minimum.toString()));
bool done = false;
scan.state = Invalid;
@@ -1474,8 +1473,8 @@ QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValu
const int min = getDigit(minimum, i);
if (min == -1) {
- qWarning("QDateTimeParser::parse Internal error 4 (%s)",
- qPrintable(sn.name()));
+ qWarning("QDateTimeParser::parse Internal error 4 (%ls)",
+ qUtf16Printable(sn.name()));
scan.state = Invalid;
done = true;
break;
@@ -1773,8 +1772,8 @@ int QDateTimeParser::SectionNode::maxChange() const
case YearSection: return 9999 * 365;
case YearSection2Digits: return 100 * 365;
default:
- qWarning("QDateTimeParser::maxChange() Internal error (%s)",
- qPrintable(name()));
+ qWarning("QDateTimeParser::maxChange() Internal error (%ls)",
+ qUtf16Printable(name()));
}
return -1;
@@ -1822,8 +1821,8 @@ QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
case TimeZoneSection:
break;
default:
- qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)",
- index, qPrintable(sn.name()), sn.count);
+ qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %ls %d)",
+ index, qUtf16Printable(sn.name()), sn.count);
break;
}
return ret;
@@ -1846,8 +1845,8 @@ QString QDateTimeParser::SectionNode::format() const
case YearSection2Digits:
case YearSection: fillChar = QLatin1Char('y'); break;
default:
- qWarning("QDateTimeParser::sectionFormat Internal error (%s)",
- qPrintable(name(type)));
+ qWarning("QDateTimeParser::sectionFormat Internal error (%ls)",
+ qUtf16Printable(name(type)));
return QString();
}
if (fillChar.isNull()) {
@@ -1983,7 +1982,7 @@ QString QDateTimeParser::stateName(State s) const
#if QT_CONFIG(datestring)
bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
{
- QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN);
+ QDateTime val(QDate(1900, 1, 1).startOfDay());
const StateNode tmp = parse(t, -1, val, false);
if (tmp.state != Acceptable || tmp.conflicts) {
return false;
@@ -2011,20 +2010,20 @@ QDateTime QDateTimeParser::getMinimum() const
{
// Cache the most common case
if (spec == Qt::LocalTime) {
- static const QDateTime localTimeMin(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, Qt::LocalTime);
+ static const QDateTime localTimeMin(QDATETIMEEDIT_DATE_MIN.startOfDay(Qt::LocalTime));
return localTimeMin;
}
- return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec);
+ return QDateTime(QDATETIMEEDIT_DATE_MIN.startOfDay(spec));
}
QDateTime QDateTimeParser::getMaximum() const
{
// Cache the most common case
if (spec == Qt::LocalTime) {
- static const QDateTime localTimeMax(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, Qt::LocalTime);
+ static const QDateTime localTimeMax(QDATETIMEEDIT_DATE_MAX.endOfDay(Qt::LocalTime));
return localTimeMax;
}
- return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec);
+ return QDateTime(QDATETIMEEDIT_DATE_MAX.endOfDay(spec));
}
QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/time/qdatetimeparser_p.h
index f7e6e351fe..d9e39f0795 100644
--- a/src/corelib/tools/qdatetimeparser_p.h
+++ b/src/corelib/time/qdatetimeparser_p.h
@@ -65,14 +65,11 @@
QT_REQUIRE_CONFIG(datetimeparser);
-#define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0)
-#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999)
+#define QDATETIMEEDIT_TIME_MIN QTime(0, 0) // Prefer QDate::startOfDay()
+#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999) // Prefer QDate::endOfDay()
#define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1)
#define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14)
#define QDATETIMEEDIT_DATE_MAX QDate(9999, 12, 31)
-#define QDATETIMEEDIT_DATETIME_MIN QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
-#define QDATETIMEEDIT_COMPAT_DATETIME_MIN QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
-#define QDATETIMEEDIT_DATETIME_MAX QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX)
#define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1)
QT_BEGIN_NAMESPACE
@@ -86,7 +83,7 @@ public:
DateTimeEdit
};
QDateTimeParser(QVariant::Type t, Context ctx)
- : currentSectionIndex(-1), display(0), cachedDay(-1), parserType(t),
+ : currentSectionIndex(-1), display(nullptr), cachedDay(-1), parserType(t),
fixday(false), spec(Qt::LocalTime), context(ctx)
{
defaultLocale = QLocale::system();
@@ -218,9 +215,9 @@ private:
ParsedSection parseSection(const QDateTime &currentValue, int sectionIndex,
int offset, QString *text) const;
int findMonth(const QString &str1, int monthstart, int sectionIndex,
- QString *monthName = 0, int *used = 0) const;
+ QString *monthName = nullptr, int *used = nullptr) const;
int findDay(const QString &str1, int intDaystart, int sectionIndex,
- QString *dayName = 0, int *used = 0) const;
+ QString *dayName = nullptr, int *used = nullptr) const;
ParsedSection findTimeZone(QStringRef str, const QDateTime &when,
int maxVal, int minVal) const;
#if QT_CONFIG(timezone)
@@ -236,7 +233,7 @@ private:
PossiblePM = 3,
PossibleBoth = 4
};
- AmPmFinder findAmPm(QString &str, int index, int *used = 0) const;
+ AmPmFinder findAmPm(QString &str, int index, int *used = nullptr) const;
#endif // datestring
bool potentialValue(const QStringRef &str, int min, int max, int index,
diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/time/qtimezone.cpp
index cbc6b50c98..ef323de14a 100644
--- a/src/corelib/tools/qtimezone.cpp
+++ b/src/corelib/time/qtimezone.cpp
@@ -317,7 +317,7 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
Create a null/invalid time zone instance.
*/
-QTimeZone::QTimeZone() Q_DECL_NOTHROW
+QTimeZone::QTimeZone() noexcept
: d(0)
{
}
diff --git a/src/corelib/tools/qtimezone.h b/src/corelib/time/qtimezone.h
index 29d8a4dbe5..62ecee49bb 100644
--- a/src/corelib/tools/qtimezone.h
+++ b/src/corelib/time/qtimezone.h
@@ -89,7 +89,7 @@ public:
};
typedef QVector<OffsetData> OffsetDataList;
- QTimeZone() Q_DECL_NOTHROW;
+ QTimeZone() noexcept;
explicit QTimeZone(const QByteArray &ianaId);
explicit QTimeZone(int offsetSeconds);
/*implicit*/ QTimeZone(const QByteArray &zoneId, int offsetSeconds, const QString &name,
@@ -99,11 +99,9 @@ public:
~QTimeZone();
QTimeZone &operator=(const QTimeZone &other);
- #ifdef Q_COMPILER_RVALUE_REFS
- QTimeZone &operator=(QTimeZone &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QTimeZone &operator=(QTimeZone &&other) noexcept { swap(other); return *this; }
- void swap(QTimeZone &other) Q_DECL_NOTHROW
+ void swap(QTimeZone &other) noexcept
{ d.swap(other.d); }
bool operator==(const QTimeZone &other) const;
diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
index 569b343187..569b343187 100644
--- a/src/corelib/tools/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
diff --git a/src/corelib/tools/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp
index be4f374fdd..be4f374fdd 100644
--- a/src/corelib/tools/qtimezoneprivate_android.cpp
+++ b/src/corelib/time/qtimezoneprivate_android.cpp
diff --git a/src/corelib/time/qtimezoneprivate_data_p.h b/src/corelib/time/qtimezoneprivate_data_p.h
new file mode 100644
index 0000000000..40d6c972c2
--- /dev/null
+++ b/src/corelib/time/qtimezoneprivate_data_p.h
@@ -0,0 +1,1257 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 John Layt <jlayt@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QTIMEZONEPRIVATE_DATA_P_H
+#define QTIMEZONEPRIVATE_DATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of internal files. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Windows Zone ID support, included in default base class build so can be used on all platforms,
+ e.g. an app running on Linux may need to communicate with a Windows Outlook server. These
+ tables can also be used to look-up Region Codes and UTC Offsets on platforms that don't directly
+ support them., e.g. Mac does not support availableTimeZones() filtering by region or offset.
+
+ Another data table is provided for generic UTC+00:00 format time zones to be used as a
+ fall-back if no system time zones are available (QT_NO_SYSTEMLOCALE is set) or for QDateTimes
+ with a QT:Spec of OffsetFromUTC
+
+ These tables are automatically adapted from the CLDR supplemental/windowsZones.xml data file
+ using a script in qtbase/util/locale_database. Please do not edit this data directly. In the
+ future if ICU is made a hard dependency then the ICU resource can be used directly and this
+ table removed
+*/
+
+struct QZoneData {
+ quint16 windowsIdKey; // Windows ID Key
+ quint16 country; // Country of IANA ID's, AnyCountry means No Country
+ quint16 ianaIdIndex; // All IANA ID's for the Windows ID and Country, space separated
+};
+
+struct QWindowsData {
+ quint16 windowsIdKey; // Windows ID Key
+ quint16 windowsIdIndex; // Windows ID Literal
+ quint16 ianaIdIndex; // Default IANA ID for the Windows ID
+ qint32 offsetFromUtc; // Standard Time Offset from UTC, used for quick look-ups
+};
+
+struct QUtcData {
+ quint16 ianaIdIndex; // IANA ID's
+ qint32 offsetFromUtc; // Offset form UTC is seconds
+};
+
+/*
+ COPYRIGHT AND PERMISSION NOTICE
+
+ Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under
+ the Terms of Use in http://www.unicode.org/copyright.html.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of the Unicode data files and any associated documentation (the "Data
+ Files") or Unicode software and any associated documentation (the "Software")
+ to deal in the Data Files or Software without restriction, including without
+ limitation the rights to use, copy, modify, merge, publish, distribute, and/or
+ sell copies of the Data Files or Software, and to permit persons to whom the
+ Data Files or Software are furnished to do so, provided that (a) the above
+ copyright notice(s) and this permission notice appear with all copies of the
+ Data Files or Software, (b) both the above copyright notice(s) and this
+ permission notice appear in associated documentation, and (c) there is clear
+ notice in each modified Data File or in the Software as well as in the
+ documentation associated with the Data File(s) or Software that the data or
+ software has been modified.
+*/
+
+// GENERATED PART STARTS HERE
+
+/*
+ This part of the file was generated on 2019-05-28 from the
+ Common Locale Data Repository v35.1 supplemental/windowsZones.xml file $Revision: 14742 $
+
+ http://www.unicode.org/cldr/
+
+ Do not edit this code: run cldr2qtimezone.py on updated (or
+ edited) CLDR data; see qtbase/util/locale_database/.
+*/
+
+// Windows ID Key, Country Enum, IANA ID Index
+static const QZoneData zoneDataTable[] = {
+ { 131, 143, 0 }, // W. Mongolia Standard Time / Mongolia
+ { 124, 112, 10 }, // UTC+12 / Kiribati
+ { 52, 94, 25 }, // Haiti Standard Time / Haiti
+ { 32, 44, 48 }, // China Standard Time / China
+ { 95, 244, 62 }, // SA Western Standard Time / Saint Barthelemy
+ { 25, 116, 84 }, // Central Asia Standard Time / Kyrgyzstan
+ { 36, 8, 97 }, // E. Africa Standard Time / Antarctica
+ { 33, 154, 114 }, // Chatham Islands Standard Time / New Zealand
+ { 95, 144, 130 }, // SA Western Standard Time / Montserrat
+ { 37, 13, 149 }, // E. Australia Standard Time / Australia
+ { 61, 0, 187 }, // Line Islands Standard Time / AnyCountry
+ { 132, 218, 198 }, // West Asia Standard Time / Turkmenistan
+ { 122, 30, 212 }, // UTC-02 / Brazil
+ { 24, 52, 228 }, // Central America Standard Time / Costa Rica
+ { 36, 67, 247 }, // E. Africa Standard Time / Eritrea
+ { 128, 8, 261 }, // W. Australia Standard Time / Antarctica
+ { 101, 101, 278 }, // SE Asia Standard Time / Indonesia
+ { 93, 8, 306 }, // SA Eastern Standard Time / Antarctica
+ { 4, 178, 325 }, // Altai Standard Time / Russia
+ { 95, 256, 338 }, // SA Western Standard Time / Sint Maarten
+ { 95, 60, 360 }, // SA Western Standard Time / Dominica
+ { 134, 167, 377 }, // West Pacific Standard Time / Papua New Guinea
+ { 13, 13, 398 }, // AUS Eastern Standard Time / Australia
+ { 69, 236, 435 }, // Morocco Standard Time / Western Sahara
+ { 39, 30, 451 }, // E. South America Standard Time / Brazil
+ { 124, 134, 469 }, // UTC+12 / Marshall Islands
+ { 125, 112, 502 }, // UTC+13 / Kiribati
+ { 103, 146, 520 }, // South Africa Standard Time / Mozambique
+ { 94, 30, 534 }, // SA Pacific Standard Time / Brazil
+ { 88, 74, 570 }, // Romance Standard Time / France
+ { 71, 38, 583 }, // Mountain Standard Time / Canada
+ { 72, 147, 657 }, // Myanmar Standard Time / Myanmar
+ { 26, 30, 670 }, // Central Brazilian Standard Time / Brazil
+ { 130, 123, 706 }, // W. Europe Standard Time / Liechtenstein
+ { 46, 73, 719 }, // FLE Standard Time / Finland
+ { 93, 70, 735 }, // SA Eastern Standard Time / Falkland Islands
+ { 78, 159, 752 }, // Norfolk Standard Time / Norfolk Island
+ { 53, 0, 768 }, // Hawaiian Standard Time / AnyCountry
+ { 28, 54, 779 }, // Central European Standard Time / Croatia
+ { 75, 150, 793 }, // Nepal Standard Time / Nepal
+ { 46, 33, 807 }, // FLE Standard Time / Bulgaria
+ { 6, 162, 820 }, // Arabian Standard Time / Oman
+ { 132, 131, 832 }, // West Asia Standard Time / Maldives
+ { 88, 197, 848 }, // Romance Standard Time / Spain
+ { 50, 91, 875 }, // Greenwich Standard Time / Guinea
+ { 5, 237, 890 }, // Arab Standard Time / Yemen
+ { 92, 222, 900 }, // Russian Standard Time / Ukraine
+ { 103, 204, 918 }, // South Africa Standard Time / Swaziland
+ { 130, 203, 933 }, // W. Europe Standard Time / Svalbard And Jan Mayen Islands
+ { 7, 103, 953 }, // Arabic Standard Time / Iraq
+ { 119, 226, 966 }, // UTC-11 / United States Minor Outlying Islands
+ { 5, 115, 981 }, // Arab Standard Time / Kuwait
+ { 50, 189, 993 }, // Greenwich Standard Time / Sierra Leone
+ { 31, 0, 1009 }, // Central Standard Time / AnyCountry
+ { 53, 51, 1017 }, // Hawaiian Standard Time / Cook Islands
+ { 129, 50, 1035 }, // W. Central Africa Standard Time / Congo Brazzaville
+ { 64, 43, 1054 }, // Magallanes Standard Time / Chile
+ { 119, 0, 1075 }, // UTC-11 / AnyCountry
+ { 84, 38, 1086 }, // Pacific Standard Time / Canada
+ { 22, 11, 1138 }, // Caucasus Standard Time / Armenia
+ { 130, 142, 1151 }, // W. Europe Standard Time / Monaco
+ { 103, 239, 1165 }, // South Africa Standard Time / Zambia
+ { 46, 222, 1179 }, // FLE Standard Time / Ukraine
+ { 87, 168, 1225 }, // Paraguay Standard Time / Paraguay
+ { 57, 109, 1242 }, // Jordan Standard Time / Jordan
+ { 109, 30, 1253 }, // Tocantins Standard Time / Brazil
+ { 55, 102, 1271 }, // Iran Standard Time / Iran
+ { 101, 8, 1283 }, // SE Asia Standard Time / Antarctica
+ { 27, 57, 1300 }, // Central Europe Standard Time / Czech Republic
+ { 95, 215, 1314 }, // SA Western Standard Time / Trinidad And Tobago
+ { 103, 28, 1336 }, // South Africa Standard Time / Botswana
+ { 132, 0, 1352 }, // West Asia Standard Time / AnyCountry
+ { 94, 63, 1362 }, // SA Pacific Standard Time / Ecuador
+ { 51, 85, 1380 }, // GTB Standard Time / Greece
+ { 36, 128, 1394 }, // E. Africa Standard Time / Madagascar
+ { 53, 226, 1414 }, // Hawaiian Standard Time / United States Minor Outlying Islands
+ { 94, 107, 1431 }, // SA Pacific Standard Time / Jamaica
+ { 104, 198, 1447 }, // Sri Lanka Standard Time / Sri Lanka
+ { 27, 243, 1460 }, // Central Europe Standard Time / Serbia
+ { 25, 110, 1476 }, // Central Asia Standard Time / Kazakhstan
+ { 125, 0, 1502 }, // UTC+13 / AnyCountry
+ { 94, 38, 1513 }, // SA Pacific Standard Time / Canada
+ { 25, 31, 1535 }, // Central Asia Standard Time / British Indian Ocean Territory
+ { 108, 13, 1549 }, // Tasmania Standard Time / Australia
+ { 95, 174, 1583 }, // SA Western Standard Time / Puerto Rico
+ { 95, 180, 1603 }, // SA Western Standard Time / Saint Kitts And Nevis
+ { 130, 206, 1620 }, // W. Europe Standard Time / Switzerland
+ { 117, 225, 1634 }, // US Eastern Standard Time / United States
+ { 29, 140, 1701 }, // Central Pacific Standard Time / Micronesia
+ { 120, 77, 1731 }, // UTC-09 / French Polynesia
+ { 129, 156, 1747 }, // W. Central Africa Standard Time / Niger
+ { 118, 139, 1761 }, // US Mountain Standard Time / Mexico
+ { 36, 194, 1780 }, // E. Africa Standard Time / Somalia
+ { 118, 0, 1797 }, // US Mountain Standard Time / AnyCountry
+ { 10, 24, 1807 }, // Atlantic Standard Time / Bermuda
+ { 103, 240, 1824 }, // South Africa Standard Time / Zimbabwe
+ { 32, 126, 1838 }, // China Standard Time / Macau
+ { 129, 66, 1849 }, // W. Central Africa Standard Time / Equatorial Guinea
+ { 66, 137, 1863 }, // Mauritius Standard Time / Mauritius
+ { 46, 68, 1880 }, // FLE Standard Time / Estonia
+ { 50, 187, 1895 }, // Greenwich Standard Time / Senegal
+ { 132, 110, 1908 }, // West Asia Standard Time / Kazakhstan
+ { 25, 44, 1968 }, // Central Asia Standard Time / China
+ { 130, 106, 1980 }, // W. Europe Standard Time / Italy
+ { 48, 251, 1992 }, // GMT Standard Time / Isle Of Man
+ { 36, 210, 2011 }, // E. Africa Standard Time / Tanzania
+ { 10, 86, 2032 }, // Atlantic Standard Time / Greenland
+ { 123, 86, 2046 }, // UTC / Greenland
+ { 20, 38, 2067 }, // Canada Central Standard Time / Canada
+ { 15, 86, 2104 }, // Azores Standard Time / Greenland
+ { 69, 145, 2125 }, // Morocco Standard Time / Morocco
+ { 115, 219, 2143 }, // Turks And Caicos Standard Time / Turks And Caicos Islands
+ { 50, 80, 2162 }, // Greenwich Standard Time / Gambia
+ { 129, 42, 2176 }, // W. Central Africa Standard Time / Chad
+ { 56, 105, 2192 }, // Israel Standard Time / Israel
+ { 64, 8, 2207 }, // Magallanes Standard Time / Antarctica
+ { 12, 13, 2225 }, // Aus Central W. Standard Time / Australia
+ { 24, 155, 2241 }, // Central America Standard Time / Nicaragua
+ { 102, 170, 2257 }, // Singapore Standard Time / Philippines
+ { 134, 160, 2269 }, // West Pacific Standard Time / Northern Mariana Islands
+ { 43, 64, 2284 }, // Egypt Standard Time / Egypt
+ { 88, 21, 2297 }, // Romance Standard Time / Belgium
+ { 76, 8, 2313 }, // New Zealand Standard Time / Antarctica
+ { 51, 177, 2332 }, // GTB Standard Time / Romania
+ { 103, 0, 2349 }, // South Africa Standard Time / AnyCountry
+ { 41, 225, 2359 }, // Eastern Standard Time / United States
+ { 129, 23, 2516 }, // W. Central Africa Standard Time / Benin
+ { 79, 178, 2534 }, // North Asia East Standard Time / Russia
+ { 116, 143, 2547 }, // Ulaanbaatar Standard Time / Mongolia
+ { 130, 14, 2580 }, // W. Europe Standard Time / Austria
+ { 41, 38, 2594 }, // Eastern Standard Time / Canada
+ { 95, 255, 2699 }, // SA Western Standard Time / Bonaire
+ { 124, 149, 2718 }, // UTC+12 / Nauru
+ { 134, 8, 2732 }, // West Pacific Standard Time / Antarctica
+ { 63, 178, 2758 }, // Magadan Standard Time / Russia
+ { 130, 161, 2771 }, // W. Europe Standard Time / Norway
+ { 110, 0, 2783 }, // Tokyo Standard Time / AnyCountry
+ { 24, 63, 2793 }, // Central America Standard Time / Ecuador
+ { 103, 35, 2811 }, // South Africa Standard Time / Burundi
+ { 10, 38, 2828 }, // Atlantic Standard Time / Canada
+ { 29, 0, 2896 }, // Central Pacific Standard Time / AnyCountry
+ { 95, 87, 2907 }, // SA Western Standard Time / Grenada
+ { 29, 153, 2923 }, // Central Pacific Standard Time / New Caledonia
+ { 42, 139, 2938 }, // Eastern Standard Time (Mexico) / Mexico
+ { 2, 225, 2953 }, // Alaskan Standard Time / United States
+ { 49, 86, 3029 }, // Greenland Standard Time / Greenland
+ { 50, 92, 3045 }, // Greenwich Standard Time / Guinea Bissau
+ { 130, 184, 3059 }, // W. Europe Standard Time / San Marino
+ { 27, 98, 3077 }, // Central Europe Standard Time / Hungary
+ { 24, 96, 3093 }, // Central America Standard Time / Honduras
+ { 62, 13, 3113 }, // Lord Howe Standard Time / Australia
+ { 36, 0, 3133 }, // E. Africa Standard Time / AnyCountry
+ { 129, 79, 3143 }, // W. Central Africa Standard Time / Gabon
+ { 95, 182, 3161 }, // SA Western Standard Time / Saint Vincent And The Grenadines
+ { 48, 224, 3180 }, // GMT Standard Time / United Kingdom
+ { 68, 227, 3194 }, // Montevideo Standard Time / Uruguay
+ { 124, 0, 3213 }, // UTC+12 / AnyCountry
+ { 130, 230, 3224 }, // W. Europe Standard Time / Vatican City State
+ { 50, 99, 3239 }, // Greenwich Standard Time / Iceland
+ { 34, 55, 3258 }, // Cuba Standard Time / Cuba
+ { 41, 16, 3273 }, // Eastern Standard Time / Bahamas
+ { 122, 196, 3288 }, // UTC-02 / South Georgia And The South Sandwich Islands
+ { 24, 65, 3311 }, // Central America Standard Time / El Salvador
+ { 31, 225, 3331 }, // Central Standard Time / United States
+ { 95, 0, 3499 }, // SA Western Standard Time / AnyCountry
+ { 94, 166, 3509 }, // SA Pacific Standard Time / Panama
+ { 94, 47, 3524 }, // SA Pacific Standard Time / Colombia
+ { 70, 139, 3539 }, // Mountain Standard Time (Mexico) / Mexico
+ { 124, 220, 3574 }, // UTC+12 / Tuvalu
+ { 130, 84, 3591 }, // W. Europe Standard Time / Gibraltar
+ { 82, 178, 3608 }, // Omsk Standard Time / Russia
+ { 60, 122, 3618 }, // Libya Standard Time / Libya
+ { 25, 8, 3633 }, // Central Asia Standard Time / Antarctica
+ { 95, 12, 3651 }, // SA Western Standard Time / Aruba
+ { 67, 119, 3665 }, // Middle East Standard Time / Lebanon
+ { 102, 0, 3677 }, // Singapore Standard Time / AnyCountry
+ { 74, 148, 3687 }, // Namibia Standard Time / Namibia
+ { 126, 231, 3703 }, // Venezuela Standard Time / Venezuela
+ { 95, 234, 3719 }, // SA Western Standard Time / United States Virgin Islands
+ { 21, 0, 3737 }, // Cape Verde Standard Time / AnyCountry
+ { 95, 9, 3747 }, // SA Western Standard Time / Antigua And Barbuda
+ { 94, 169, 3763 }, // SA Pacific Standard Time / Peru
+ { 46, 248, 3776 }, // FLE Standard Time / Aland Islands
+ { 50, 199, 3793 }, // Greenwich Standard Time / Saint Helena
+ { 134, 140, 3812 }, // West Pacific Standard Time / Micronesia
+ { 102, 190, 3825 }, // Singapore Standard Time / Singapore
+ { 95, 61, 3840 }, // SA Western Standard Time / Dominican Republic
+ { 103, 129, 3862 }, // South Africa Standard Time / Malawi
+ { 30, 139, 3878 }, // Central Standard Time (Mexico) / Mexico
+ { 102, 130, 3954 }, // Singapore Standard Time / Malaysia
+ { 45, 72, 3985 }, // Fiji Standard Time / Fiji
+ { 118, 225, 3998 }, // US Mountain Standard Time / United States
+ { 17, 25, 4014 }, // Bangladesh Standard Time / Bhutan
+ { 130, 133, 4027 }, // W. Europe Standard Time / Malta
+ { 92, 178, 4040 }, // Russian Standard Time / Russia
+ { 95, 135, 4084 }, // SA Western Standard Time / Martinique
+ { 35, 0, 4103 }, // Dateline Standard Time / AnyCountry
+ { 135, 178, 4114 }, // Yakutsk Standard Time / Russia
+ { 1, 1, 4141 }, // Afghanistan Standard Time / Afghanistan
+ { 123, 0, 4152 }, // UTC / AnyCountry
+ { 31, 139, 4168 }, // Central Standard Time / Mexico
+ { 6, 0, 4186 }, // Arabian Standard Time / AnyCountry
+ { 101, 45, 4196 }, // SE Asia Standard Time / Christmas Island
+ { 15, 173, 4213 }, // Azores Standard Time / Portugal
+ { 129, 0, 4229 }, // W. Central Africa Standard Time / AnyCountry
+ { 17, 18, 4239 }, // Bangladesh Standard Time / Bangladesh
+ { 31, 38, 4250 }, // Central Standard Time / Canada
+ { 94, 0, 4325 }, // SA Pacific Standard Time / AnyCountry
+ { 125, 213, 4335 }, // UTC+13 / Tokelau
+ { 73, 178, 4351 }, // N. Central Asia Standard Time / Russia
+ { 133, 165, 4368 }, // West Bank Standard Time / Palestinian Territories
+ { 114, 217, 4390 }, // Turkey Standard Time / Turkey
+ { 3, 225, 4406 }, // Aleutian Standard Time / United States
+ { 101, 0, 4419 }, // SE Asia Standard Time / AnyCountry
+ { 71, 225, 4429 }, // Mountain Standard Time / United States
+ { 36, 69, 4458 }, // E. Africa Standard Time / Ethiopia
+ { 130, 151, 4477 }, // W. Europe Standard Time / Netherlands
+ { 95, 245, 4494 }, // SA Western Standard Time / Saint Martin
+ { 48, 173, 4510 }, // GMT Standard Time / Portugal
+ { 46, 124, 4541 }, // FLE Standard Time / Lithuania
+ { 130, 82, 4556 }, // W. Europe Standard Time / Germany
+ { 65, 77, 4586 }, // Marquesas Standard Time / French Polynesia
+ { 80, 178, 4604 }, // North Asia Standard Time / Russia
+ { 61, 112, 4639 }, // Line Islands Standard Time / Kiribati
+ { 96, 200, 4658 }, // Saint Pierre Standard Time / Saint Pierre And Miquelon
+ { 48, 104, 4675 }, // GMT Standard Time / Ireland
+ { 5, 186, 4689 }, // Arab Standard Time / Saudi Arabia
+ { 83, 43, 4701 }, // Pacific SA Standard Time / Chile
+ { 91, 178, 4718 }, // Russia Time Zone 11 / Russia
+ { 36, 48, 4745 }, // E. Africa Standard Time / Comoros
+ { 95, 152, 4759 }, // SA Western Standard Time / Cura Sao
+ { 38, 141, 4775 }, // E. Europe Standard Time / Moldova
+ { 24, 22, 4791 }, // Central America Standard Time / Belize
+ { 103, 195, 4806 }, // South Africa Standard Time / South Africa
+ { 127, 178, 4826 }, // Vladivostok Standard Time / Russia
+ { 122, 0, 4857 }, // UTC-02 / AnyCountry
+ { 106, 207, 4867 }, // Syria Standard Time / Syria
+ { 93, 76, 4881 }, // SA Eastern Standard Time / French Guiana
+ { 50, 136, 4897 }, // Greenwich Standard Time / Mauritania
+ { 41, 0, 4915 }, // Eastern Standard Time / AnyCountry
+ { 16, 30, 4923 }, // Bahia Standard Time / Brazil
+ { 40, 43, 4937 }, // Easter Island Standard Time / Chile
+ { 93, 0, 4952 }, // SA Eastern Standard Time / AnyCountry
+ { 9, 178, 4962 }, // Astrakhan Standard Time / Russia
+ { 95, 30, 4996 }, // SA Western Standard Time / Brazil
+ { 18, 20, 5049 }, // Belarus Standard Time / Belarus
+ { 95, 181, 5062 }, // SA Western Standard Time / Saint Lucia
+ { 129, 6, 5079 }, // W. Central Africa Standard Time / Angola
+ { 129, 157, 5093 }, // W. Central Africa Standard Time / Nigeria
+ { 130, 5, 5106 }, // W. Europe Standard Time / Andorra
+ { 58, 178, 5121 }, // Kaliningrad Standard Time / Russia
+ { 71, 0, 5140 }, // Mountain Standard Time / AnyCountry
+ { 95, 7, 5148 }, // SA Western Standard Time / Anguilla
+ { 124, 235, 5165 }, // UTC+12 / Wallis And Futuna Islands
+ { 6, 223, 5180 }, // Arabian Standard Time / United Arab Emirates
+ { 94, 40, 5191 }, // SA Pacific Standard Time / Cayman Islands
+ { 101, 211, 5206 }, // SE Asia Standard Time / Thailand
+ { 29, 193, 5219 }, // Central Pacific Standard Time / Solomon Islands
+ { 47, 81, 5239 }, // Georgian Standard Time / Georgia
+ { 101, 36, 5252 }, // SE Asia Standard Time / Cambodia
+ { 132, 228, 5268 }, // West Asia Standard Time / Uzbekistan
+ { 51, 56, 5297 }, // GTB Standard Time / Cyprus
+ { 95, 88, 5325 }, // SA Western Standard Time / Guadeloupe
+ { 101, 232, 5344 }, // SE Asia Standard Time / Vietnam
+ { 113, 178, 5356 }, // Transbaikal Standard Time / Russia
+ { 50, 121, 5367 }, // Greenwich Standard Time / Liberia
+ { 95, 233, 5383 }, // SA Western Standard Time / British Virgin Islands
+ { 129, 49, 5399 }, // W. Central Africa Standard Time / Congo Kinshasa
+ { 97, 178, 5415 }, // Sakhalin Standard Time / Russia
+ { 124, 226, 5429 }, // UTC+12 / United States Minor Outlying Islands
+ { 50, 83, 5442 }, // Greenwich Standard Time / Ghana
+ { 76, 154, 5455 }, // New Zealand Standard Time / New Zealand
+ { 23, 13, 5472 }, // Cen. Australia Standard Time / Australia
+ { 53, 77, 5513 }, // Hawaiian Standard Time / French Polynesia
+ { 50, 34, 5528 }, // Greenwich Standard Time / Burkina Faso
+ { 132, 78, 5547 }, // West Asia Standard Time / French Southern Territories
+ { 121, 0, 5564 }, // UTC-08 / AnyCountry
+ { 27, 2, 5574 }, // Central Europe Standard Time / Albania
+ { 107, 208, 5588 }, // Taipei Standard Time / Taiwan
+ { 88, 58, 5600 }, // Romance Standard Time / Denmark
+ { 36, 221, 5618 }, // E. Africa Standard Time / Uganda
+ { 95, 19, 5633 }, // SA Western Standard Time / Barbados
+ { 14, 15, 5650 }, // Azerbaijan Standard Time / Azerbaijan
+ { 32, 97, 5660 }, // China Standard Time / Hong Kong
+ { 110, 101, 5675 }, // Tokyo Standard Time / Indonesia
+ { 53, 225, 5689 }, // Hawaiian Standard Time / United States
+ { 36, 111, 5706 }, // E. Africa Standard Time / Kenya
+ { 134, 89, 5721 }, // West Pacific Standard Time / Guam
+ { 36, 254, 5734 }, // E. Africa Standard Time / South Sudan
+ { 48, 71, 5746 }, // GMT Standard Time / Faroe Islands
+ { 90, 178, 5762 }, // Russia Time Zone 10 / Russia
+ { 119, 158, 5781 }, // UTC-11 / Niue
+ { 129, 3, 5794 }, // W. Central Africa Standard Time / Algeria
+ { 110, 62, 5809 }, // Tokyo Standard Time / East Timor
+ { 93, 30, 5819 }, // SA Eastern Standard Time / Brazil
+ { 27, 242, 5898 }, // Central Europe Standard Time / Montenegro
+ { 129, 37, 5915 }, // W. Central Africa Standard Time / Cameroon
+ { 101, 117, 5929 }, // SE Asia Standard Time / Laos
+ { 85, 139, 5944 }, // Pacific Standard Time (Mexico) / Mexico
+ { 50, 212, 5981 }, // Greenwich Standard Time / Togo
+ { 46, 118, 5993 }, // FLE Standard Time / Latvia
+ { 95, 38, 6005 }, // SA Western Standard Time / Canada
+ { 132, 209, 6026 }, // West Asia Standard Time / Tajikistan
+ { 77, 38, 6040 }, // Newfoundland Standard Time / Canada
+ { 110, 108, 6057 }, // Tokyo Standard Time / Japan
+ { 25, 0, 6068 }, // Central Asia Standard Time / AnyCountry
+ { 28, 27, 6078 }, // Central European Standard Time / Bosnia And Herzegowina
+ { 27, 191, 6094 }, // Central Europe Standard Time / Slovakia
+ { 95, 93, 6112 }, // SA Western Standard Time / Guyana
+ { 48, 197, 6127 }, // GMT Standard Time / Spain
+ { 19, 167, 6143 }, // Bougainville Standard Time / Papua New Guinea
+ { 5, 17, 6164 }, // Arab Standard Time / Bahrain
+ { 24, 90, 6177 }, // Central America Standard Time / Guatemala
+ { 95, 26, 6195 }, // SA Western Standard Time / Bolivia
+ { 81, 113, 6210 }, // North Korea Standard Time / North Korea
+ { 119, 4, 6225 }, // UTC-11 / American Samoa
+ { 66, 176, 6243 }, // Mauritius Standard Time / Reunion
+ { 103, 120, 6258 }, // South Africa Standard Time / Lesotho
+ { 84, 0, 6272 }, // Pacific Standard Time / AnyCountry
+ { 120, 0, 6280 }, // UTC-09 / AnyCountry
+ { 129, 216, 6290 }, // W. Central Africa Standard Time / Tunisia
+ { 99, 185, 6303 }, // Sao Tome Standard Time / Sao Tome And Principe
+ { 100, 178, 6319 }, // Saratov Standard Time / Russia
+ { 105, 201, 6334 }, // Sudan Standard Time / Sudan
+ { 48, 252, 6350 }, // GMT Standard Time / Jersey
+ { 29, 13, 6364 }, // Central Pacific Standard Time / Australia
+ { 71, 139, 6385 }, // Mountain Standard Time / Mexico
+ { 21, 39, 6401 }, // Cape Verde Standard Time / Cape Verde
+ { 102, 101, 6421 }, // Singapore Standard Time / Indonesia
+ { 27, 192, 6435 }, // Central Europe Standard Time / Slovenia
+ { 48, 75, 6452 }, // GMT Standard Time / Guernsey
+ { 132, 8, 6468 }, // West Asia Standard Time / Antarctica
+ { 8, 10, 6486 }, // Argentina Standard Time / Argentina
+ { 98, 183, 6759 }, // Samoa Standard Time / Samoa
+ { 129, 41, 6772 }, // W. Central Africa Standard Time / Central African Republic
+ { 111, 178, 6786 }, // Tomsk Standard Time / Russia
+ { 110, 164, 6797 }, // Tokyo Standard Time / Palau
+ { 11, 13, 6811 }, // AUS Central Standard Time / Australia
+ { 121, 171, 6828 }, // UTC-08 / Pitcairn
+ { 102, 32, 6845 }, // Singapore Standard Time / Brunei
+ { 112, 214, 6857 }, // Tonga Standard Time / Tonga
+ { 89, 178, 6875 }, // Russia Time Zone 3 / Russia
+ { 128, 13, 6889 }, // W. Australia Standard Time / Australia
+ { 28, 172, 6905 }, // Central European Standard Time / Poland
+ { 72, 46, 6919 }, // Myanmar Standard Time / Cocos Islands
+ { 66, 188, 6932 }, // Mauritius Standard Time / Seychelles
+ { 84, 225, 6944 }, // Pacific Standard Time / United States
+ { 54, 100, 6983 }, // India Standard Time / India
+ { 50, 53, 6997 }, // Greenwich Standard Time / Ivory Coast
+ { 24, 0, 7012 }, // Central America Standard Time / AnyCountry
+ { 29, 229, 7022 }, // Central Pacific Standard Time / Vanuatu
+ { 130, 125, 7036 }, // W. Europe Standard Time / Luxembourg
+ { 50, 132, 7054 }, // Greenwich Standard Time / Mali
+ { 103, 179, 7068 }, // South Africa Standard Time / Rwanda
+ { 5, 175, 7082 }, // Arab Standard Time / Qatar
+ { 86, 163, 7093 }, // Pakistan Standard Time / Pakistan
+ { 134, 0, 7106 }, // West Pacific Standard Time / AnyCountry
+ { 36, 59, 7117 }, // E. Africa Standard Time / Djibouti
+ { 44, 178, 7133 }, // Ekaterinburg Standard Time / Russia
+ { 118, 38, 7152 }, // US Mountain Standard Time / Canada
+ { 36, 138, 7209 }, // E. Africa Standard Time / Mayotte
+ { 28, 127, 7224 }, // Central European Standard Time / Macedonia
+ { 59, 114, 7238 }, // Korea Standard Time / South Korea
+ { 93, 202, 7249 }, // SA Eastern Standard Time / Suriname
+ { 130, 205, 7268 }, // W. Europe Standard Time / Sweden
+ { 103, 49, 7285 }, // South Africa Standard Time / Congo Kinshasa
+ { 0, 0, 0 } // Trailing zeroes
+};
+
+// Windows ID Key, Windows ID Index, IANA ID Index, UTC Offset
+static const QWindowsData windowsDataTable[] = {
+ { 1, 0, 4141, 16200 }, // Afghanistan Standard Time
+ { 2, 26, 7303,-32400 }, // Alaskan Standard Time
+ { 3, 48, 4406,-36000 }, // Aleutian Standard Time
+ { 4, 71, 325, 25200 }, // Altai Standard Time
+ { 5, 91, 4689, 10800 }, // Arab Standard Time
+ { 6, 110, 5180, 14400 }, // Arabian Standard Time
+ { 7, 132, 953, 10800 }, // Arabic Standard Time
+ { 8, 153, 7321,-10800 }, // Argentina Standard Time
+ { 9, 177, 7342, 14400 }, // Astrakhan Standard Time
+ { 10, 201, 7359,-14400 }, // Atlantic Standard Time
+ { 11, 224, 6811, 34200 }, // AUS Central Standard Time
+ { 12, 250, 2225, 31500 }, // Aus Central W. Standard Time
+ { 13, 279, 7375, 36000 }, // AUS Eastern Standard Time
+ { 14, 305, 5650, 14400 }, // Azerbaijan Standard Time
+ { 15, 330, 4213, -3600 }, // Azores Standard Time
+ { 16, 351, 4923,-10800 }, // Bahia Standard Time
+ { 17, 371, 4239, 21600 }, // Bangladesh Standard Time
+ { 18, 396, 5049, 10800 }, // Belarus Standard Time
+ { 19, 418, 6143, 39600 }, // Bougainville Standard Time
+ { 20, 445, 7392,-21600 }, // Canada Central Standard Time
+ { 21, 474, 6401, -3600 }, // Cape Verde Standard Time
+ { 22, 499, 1138, 14400 }, // Caucasus Standard Time
+ { 23, 522, 7407, 34200 }, // Cen. Australia Standard Time
+ { 24, 551, 6177,-21600 }, // Central America Standard Time
+ { 25, 581, 7426, 21600 }, // Central Asia Standard Time
+ { 26, 608, 7438,-14400 }, // Central Brazilian Standard Time
+ { 27, 640, 3077, 3600 }, // Central Europe Standard Time
+ { 28, 669, 6905, 3600 }, // Central European Standard Time
+ { 29, 700, 5219, 39600 }, // Central Pacific Standard Time
+ { 30, 730, 7453,-21600 }, // Central Standard Time (Mexico)
+ { 31, 761, 7473,-21600 }, // Central Standard Time
+ { 32, 783, 48, 28800 }, // China Standard Time
+ { 33, 803, 114, 45900 }, // Chatham Islands Standard Time
+ { 34, 833, 3258,-18000 }, // Cuba Standard Time
+ { 35, 852, 4103,-43200 }, // Dateline Standard Time
+ { 36, 875, 5706, 10800 }, // E. Africa Standard Time
+ { 37, 899, 7489, 36000 }, // E. Australia Standard Time
+ { 38, 926, 4775, 7200 }, // E. Europe Standard Time
+ { 39, 950, 451,-10800 }, // E. South America Standard Time
+ { 40, 981, 4937,-21600 }, // Easter Island Standard Time
+ { 41, 1009, 7508,-18000 }, // Eastern Standard Time
+ { 42, 1031, 2938,-18000 }, // Eastern Standard Time (Mexico)
+ { 43, 1062, 2284, 7200 }, // Egypt Standard Time
+ { 44, 1082, 7133, 18000 }, // Ekaterinburg Standard Time
+ { 45, 1109, 3985, 43200 }, // Fiji Standard Time
+ { 46, 1128, 7525, 7200 }, // FLE Standard Time
+ { 47, 1146, 5239, 14400 }, // Georgian Standard Time
+ { 48, 1169, 3180, 0 }, // GMT Standard Time
+ { 49, 1187, 3029,-10800 }, // Greenland Standard Time
+ { 50, 1211, 3239, 0 }, // Greenwich Standard Time
+ { 51, 1235, 2332, 7200 }, // GTB Standard Time
+ { 52, 1253, 25,-18000 }, // Haiti Standard Time
+ { 53, 1273, 5689,-36000 }, // Hawaiian Standard Time
+ { 54, 1296, 6983, 19800 }, // India Standard Time
+ { 55, 1316, 1271, 12600 }, // Iran Standard Time
+ { 56, 1335, 2192, 7200 }, // Israel Standard Time
+ { 57, 1356, 1242, 7200 }, // Jordan Standard Time
+ { 58, 1377, 5121, 7200 }, // Kaliningrad Standard Time
+ { 59, 1403, 7238, 32400 }, // Korea Standard Time
+ { 60, 1423, 3618, 7200 }, // Libya Standard Time
+ { 61, 1443, 4639, 50400 }, // Line Islands Standard Time
+ { 62, 1470, 3113, 37800 }, // Lord Howe Standard Time
+ { 63, 1494, 2758, 36000 }, // Magadan Standard Time
+ { 64, 1516, 1054,-10800 }, // Magallanes Standard Time
+ { 65, 1541, 4586,-34200 }, // Marquesas Standard Time
+ { 66, 1565, 1863, 14400 }, // Mauritius Standard Time
+ { 67, 1589, 3665, 7200 }, // Middle East Standard Time
+ { 68, 1615, 3194,-10800 }, // Montevideo Standard Time
+ { 69, 1640, 2125, 0 }, // Morocco Standard Time
+ { 70, 1662, 7537,-25200 }, // Mountain Standard Time (Mexico)
+ { 71, 1694, 7555,-25200 }, // Mountain Standard Time
+ { 72, 1717, 657, 23400 }, // Myanmar Standard Time
+ { 73, 1739, 4351, 21600 }, // N. Central Asia Standard Time
+ { 74, 1769, 3687, 3600 }, // Namibia Standard Time
+ { 75, 1791, 793, 20700 }, // Nepal Standard Time
+ { 76, 1811, 5455, 43200 }, // New Zealand Standard Time
+ { 77, 1837, 6040,-12600 }, // Newfoundland Standard Time
+ { 78, 1864, 752, 39600 }, // Norfolk Standard Time
+ { 79, 1886, 2534, 28800 }, // North Asia East Standard Time
+ { 80, 1916, 7570, 25200 }, // North Asia Standard Time
+ { 81, 1941, 6210, 30600 }, // North Korea Standard Time
+ { 82, 1967, 3608, 21600 }, // Omsk Standard Time
+ { 83, 1986, 4701,-10800 }, // Pacific SA Standard Time
+ { 84, 2011, 7587,-28800 }, // Pacific Standard Time
+ { 85, 2033, 7607,-28800 }, // Pacific Standard Time (Mexico)
+ { 86, 2064, 7093, 18000 }, // Pakistan Standard Time
+ { 87, 2087, 1225,-14400 }, // Paraguay Standard Time
+ { 88, 2110, 570, 3600 }, // Romance Standard Time
+ { 89, 2132, 6875, 14400 }, // Russia Time Zone 3
+ { 90, 2151, 5762, 39600 }, // Russia Time Zone 10
+ { 91, 2171, 7623, 43200 }, // Russia Time Zone 11
+ { 92, 2191, 7638, 10800 }, // Russian Standard Time
+ { 93, 2213, 4881,-10800 }, // SA Eastern Standard Time
+ { 94, 2238, 3524,-18000 }, // SA Pacific Standard Time
+ { 95, 2263, 6195,-14400 }, // SA Western Standard Time
+ { 96, 2288, 4658,-10800 }, // Saint Pierre Standard Time
+ { 97, 2315, 5415, 39600 }, // Sakhalin Standard Time
+ { 98, 2338, 6759, 46800 }, // Samoa Standard Time
+ { 99, 2358, 6303, 0 }, // Sao Tome Standard Time
+ { 100, 2381, 6319, 14400 }, // Saratov Standard Time
+ { 101, 2403, 5206, 25200 }, // SE Asia Standard Time
+ { 102, 2425, 3825, 28800 }, // Singapore Standard Time
+ { 103, 2449, 4806, 7200 }, // South Africa Standard Time
+ { 104, 2476, 1447, 19800 }, // Sri Lanka Standard Time
+ { 105, 2500, 6334, 7200 }, // Sudan Standard Time
+ { 106, 2520, 4867, 7200 }, // Syria Standard Time
+ { 107, 2540, 5588, 28800 }, // Taipei Standard Time
+ { 108, 2561, 7652, 36000 }, // Tasmania Standard Time
+ { 109, 2584, 1253,-10800 }, // Tocantins Standard Time
+ { 110, 2608, 6057, 32400 }, // Tokyo Standard Time
+ { 111, 2628, 6786, 25200 }, // Tomsk Standard Time
+ { 112, 2648, 6857, 46800 }, // Tonga Standard Time
+ { 113, 2668, 5356, 32400 }, // Transbaikal Standard Time
+ { 114, 2694, 4390, 7200 }, // Turkey Standard Time
+ { 115, 2715, 2143,-14400 }, // Turks And Caicos Standard Time
+ { 116, 2746, 7669, 28800 }, // Ulaanbaatar Standard Time
+ { 117, 2772, 7686,-18000 }, // US Eastern Standard Time
+ { 118, 2797, 3998,-25200 }, // US Mountain Standard Time
+ { 119, 2823, 1075,-39600 }, // UTC-11
+ { 120, 2830, 6280,-32400 }, // UTC-09
+ { 121, 2837, 5564,-28800 }, // UTC-08
+ { 122, 2844, 4857, -7200 }, // UTC-02
+ { 123, 2851, 7707, 0 }, // UTC
+ { 124, 2855, 3213, 43200 }, // UTC+12
+ { 125, 2862, 1502, 46800 }, // UTC+13
+ { 126, 2869, 3703,-16200 }, // Venezuela Standard Time
+ { 127, 2893, 7715, 36000 }, // Vladivostok Standard Time
+ { 128, 2919, 6889, 28800 }, // W. Australia Standard Time
+ { 129, 2946, 5093, 3600 }, // W. Central Africa Standard Time
+ { 130, 2978, 7732, 3600 }, // W. Europe Standard Time
+ { 131, 3002, 0, 25200 }, // W. Mongolia Standard Time
+ { 132, 3028, 7746, 18000 }, // West Asia Standard Time
+ { 133, 3052, 7760, 7200 }, // West Bank Standard Time
+ { 134, 3076, 377, 36000 }, // West Pacific Standard Time
+ { 135, 3103, 7772, 32400 }, // Yakutsk Standard Time
+ { 0, 0, 0, 0 } // Trailing zeroes
+};
+
+// IANA ID Index, UTC Offset
+static const QUtcData utcDataTable[] = {
+ { 7785, 0 }, // UTC
+ { 7789,-50400 }, // UTC-14:00
+ { 7799,-46800 }, // UTC-13:00
+ { 7809,-43200 }, // UTC-12:00
+ { 7819,-39600 }, // UTC-11:00
+ { 7829,-36000 }, // UTC-10:00
+ { 7839,-32400 }, // UTC-09:00
+ { 7849,-28800 }, // UTC-08:00
+ { 7859,-25200 }, // UTC-07:00
+ { 7869,-21600 }, // UTC-06:00
+ { 7879,-18000 }, // UTC-05:00
+ { 7889,-16200 }, // UTC-04:30
+ { 7899,-14400 }, // UTC-04:00
+ { 7909,-12600 }, // UTC-03:30
+ { 7919,-10800 }, // UTC-03:00
+ { 7929, -7200 }, // UTC-02:00
+ { 7939, -3600 }, // UTC-01:00
+ { 7949, 0 }, // UTC-00:00
+ { 7959, 0 }, // UTC+00:00
+ { 7969, 3600 }, // UTC+01:00
+ { 7979, 7200 }, // UTC+02:00
+ { 7989, 10800 }, // UTC+03:00
+ { 7999, 12600 }, // UTC+03:30
+ { 8009, 14400 }, // UTC+04:00
+ { 8019, 16200 }, // UTC+04:30
+ { 8029, 18000 }, // UTC+05:00
+ { 8039, 19800 }, // UTC+05:30
+ { 8049, 20700 }, // UTC+05:45
+ { 8059, 21600 }, // UTC+06:00
+ { 8069, 23400 }, // UTC+06:30
+ { 8079, 25200 }, // UTC+07:00
+ { 8089, 28800 }, // UTC+08:00
+ { 8099, 30600 }, // UTC+08:30
+ { 8109, 32400 }, // UTC+09:00
+ { 8119, 34200 }, // UTC+09:30
+ { 8129, 36000 }, // UTC+10:00
+ { 8139, 39600 }, // UTC+11:00
+ { 8149, 43200 }, // UTC+12:00
+ { 8159, 46800 }, // UTC+13:00
+ { 8169, 50400 }, // UTC+14:00
+ { 0, 0 } // Trailing zeroes
+};
+
+static const char windowsIdData[] = {
+0x41, 0x66, 0x67, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x63, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
+0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x73, 0x74,
+0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
+0x69, 0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x75, 0x73, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61,
+0x6c, 0x20, 0x57, 0x2e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41,
+0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x65, 0x72, 0x62, 0x61, 0x69, 0x6a, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x68, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x6e, 0x67, 0x6c, 0x61, 0x64, 0x65, 0x73,
+0x68, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x65, 0x6c, 0x61,
+0x72, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x6f,
+0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x70, 0x65, 0x20, 0x56,
+0x65, 0x72, 0x64, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43,
+0x61, 0x75, 0x63, 0x61, 0x73, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
+0x65, 0x0, 0x43, 0x65, 0x6e, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x42, 0x72, 0x61, 0x7a,
+0x69, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29,
+0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x75, 0x62, 0x61, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x44, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6e, 0x65,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45,
+0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f,
+0x29, 0x0, 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
+0x65, 0x0, 0x45, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x69, 0x6a, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x4c, 0x45, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x4d, 0x54, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x54, 0x42, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x69, 0x74, 0x69, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x61,
+0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69,
+0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x72, 0x61, 0x6e,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65,
+0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4a, 0x6f, 0x72, 0x64,
+0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, 0x61, 0x6c,
+0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x4c, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c, 0x6f, 0x72, 0x64, 0x20, 0x48, 0x6f, 0x77, 0x65, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61,
+0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61,
+0x6c, 0x6c, 0x61, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x20, 0x45, 0x61, 0x73, 0x74,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x6e, 0x74, 0x65,
+0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x4d, 0x6f, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
+0x65, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61,
+0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x79, 0x61,
+0x6e, 0x6d, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e,
+0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x70, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61,
+0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77,
+0x66, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
+0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x45, 0x61, 0x73,
+0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74,
+0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x41, 0x20, 0x53, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69,
+0x63, 0x6f, 0x29, 0x0, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e,
+0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x6f, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54,
+0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x33, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x30, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x31, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x45, 0x61, 0x73, 0x74,
+0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41,
+0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x57, 0x65, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x20, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x6b, 0x68, 0x61,
+0x6c, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61,
+0x6d, 0x6f, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61,
+0x6f, 0x20, 0x54, 0x6f, 0x6d, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x53, 0x45, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63,
+0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x72, 0x69, 0x20,
+0x4c, 0x61, 0x6e, 0x6b, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x53, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x53, 0x79, 0x72, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
+0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
+0x0, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
+0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x63, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x62, 0x61, 0x69, 0x6b, 0x61, 0x6c, 0x20,
+0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79,
+0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x73,
+0x20, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65,
+0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20,
+0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x39, 0x0, 0x55, 0x54, 0x43,
+0x2d, 0x30, 0x38, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31,
+0x32, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x0, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x20, 0x53,
+0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f,
+0x73, 0x74, 0x6f, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57,
+0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
+0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e,
+0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
+0x65, 0x0, 0x57, 0x2e, 0x20, 0x4d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
+0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74,
+0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x42, 0x61, 0x6e,
+0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74,
+0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
+0x6d, 0x65, 0x0, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+0x54, 0x69, 0x6d, 0x65, 0x0
+};
+
+static const char ianaIdData[] = {
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61,
+0x72, 0x61, 0x77, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75,
+0x2d, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61,
+0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65, 0x6c,
+0x65, 0x6d, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, 0x6b, 0x0, 0x41, 0x6e, 0x74,
+0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79, 0x6f, 0x77, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
+0x63, 0x2f, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f,
+0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42,
+0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x69,
+0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x73, 0x74,
+0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61,
+0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74,
+0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74,
+0x68, 0x65, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0, 0x50, 0x61, 0x63,
+0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0, 0x41, 0x75,
+0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72,
+0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53,
+0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a,
+0x75, 0x72, 0x6f, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69,
+0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72,
+0x69, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x20,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61,
+0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x75, 0x76, 0x69, 0x6b, 0x20, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75,
+0x69, 0x61, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f, 0x47,
+0x72, 0x61, 0x6e, 0x64, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0, 0x45,
+0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
+0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
+0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x45,
+0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61,
+0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6f, 0x66, 0x69, 0x61, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75, 0x73, 0x63, 0x61, 0x74, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d,
+0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69,
+0x64, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d, 0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63, 0x2f,
+0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61,
+0x67, 0x68, 0x64, 0x61, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x77, 0x61, 0x69, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0, 0x50, 0x61, 0x63,
+0x69, 0x66, 0x69, 0x63, 0x2f, 0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
+0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61, 0x6e, 0x63, 0x6f, 0x75,
+0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f,
+0x6e, 0x61, 0x63, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61, 0x0, 0x45,
+0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x7a,
+0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x70, 0x6f, 0x72, 0x6f,
+0x7a, 0x68, 0x79, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63, 0x69, 0x6f,
+0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72,
+0x61, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f, 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d,
+0x35, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
+0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
+0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
+0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61,
+0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x6f, 0x73, 0x74, 0x61, 0x6e, 0x61,
+0x79, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61,
+0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48,
+0x6f, 0x62, 0x61, 0x72, 0x74, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72,
+0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69,
+0x63, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67, 0x6f, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79,
+0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65, 0x20, 0x50, 0x61, 0x63, 0x69,
+0x66, 0x69, 0x63, 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47,
+0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0, 0x45, 0x74, 0x63,
+0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d,
+0x75, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61,
+0x62, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65,
+0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79, 0x72, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x79,
+0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49,
+0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61,
+0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x54, 0x68, 0x75, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72,
+0x6b, 0x73, 0x68, 0x61, 0x76, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e,
+0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x43, 0x75, 0x72, 0x72,
+0x65, 0x6e, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79,
+0x73, 0x75, 0x6e, 0x64, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e,
+0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72,
+0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x6a, 0x75, 0x6c, 0x0, 0x41, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72,
+0x75, 0x73, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61,
+0x6c, 0x6d, 0x65, 0x72, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45, 0x75, 0x63, 0x6c, 0x61,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69,
+0x70, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
+0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75, 0x72, 0x64, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42,
+0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65,
+0x6e, 0x6e, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
+0x2f, 0x57, 0x69, 0x6e, 0x61, 0x6d, 0x61, 0x63, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e,
+0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49,
+0x72, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61,
+0x74, 0x61, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71,
+0x61, 0x6c, 0x75, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65,
+0x61, 0x6c, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69, 0x67, 0x6f, 0x6e, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61, 0x79, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0, 0x50, 0x61,
+0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
+0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73,
+0x6c, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x39, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
+0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75,
+0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69,
+0x66, 0x61, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x42, 0x61,
+0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63, 0x74, 0x6f, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f,
+0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61,
+0x64, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
+0x75, 0x6e, 0x65, 0x61, 0x75, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d, 0x65, 0x20, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x64,
+0x74, 0x68, 0x61, 0x62, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x0, 0x45,
+0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c,
+0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
+0x2d, 0x33, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c, 0x6c, 0x65,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
+0x2d, 0x31, 0x32, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0, 0x41,
+0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75,
+0x74, 0x68, 0x5f, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45,
+0x6c, 0x5f, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
+0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61,
+0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69,
+0x61, 0x6e, 0x61, 0x2f, 0x54, 0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x20,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61,
+0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74,
+0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x45,
+0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
+0x61, 0x6d, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x67, 0x6f, 0x74, 0x61, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x20, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
+0x63, 0x2f, 0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x69,
+0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
+0x69, 0x63, 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
+0x72, 0x75, 0x62, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, 0x72, 0x75, 0x74, 0x0, 0x45, 0x74, 0x63,
+0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f,
+0x65, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x45, 0x74, 0x63,
+0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67,
+0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f,
+0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
+0x63, 0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
+0x54, 0x72, 0x75, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67,
+0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74, 0x79, 0x72, 0x65, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73,
+0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
+0x75, 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x63,
+0x68, 0x69, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x69, 0x6a, 0x69, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54,
+0x68, 0x69, 0x6d, 0x70, 0x68, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
+0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x6f, 0x6c, 0x67, 0x6f, 0x67,
+0x72, 0x61, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71,
+0x75, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x32, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59,
+0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x20,
+0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61,
+0x6d, 0x6f, 0x72, 0x6f, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0, 0x49, 0x6e, 0x64, 0x69,
+0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
+0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x0, 0x41,
+0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69,
+0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79,
+0x5f, 0x52, 0x69, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x6b, 0x69,
+0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f,
+0x6c, 0x75, 0x74, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
+0x69, 0x63, 0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f,
+0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x20,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74,
+0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0, 0x45,
+0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e,
+0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x69, 0x73, 0x65, 0x0, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0, 0x45, 0x75, 0x72,
+0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73,
+0x62, 0x6f, 0x6e, 0x20, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64, 0x65, 0x69, 0x72, 0x61,
+0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f,
+0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73,
+0x69, 0x6e, 0x67, 0x65, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65,
+0x73, 0x61, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b,
+0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0, 0x50,
+0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72, 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
+0x65, 0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x69, 0x79, 0x61, 0x64, 0x68,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e,
+0x61, 0x64, 0x79, 0x72, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
+0x65, 0x2f, 0x43, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
+0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65,
+0x73, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74,
+0x6f, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0, 0x45, 0x74, 0x63,
+0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68, 0x6f, 0x74, 0x74, 0x0, 0x45, 0x53, 0x54, 0x35, 0x45,
+0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63,
+0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
+0x33, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x45,
+0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
+0x6f, 0x61, 0x5f, 0x56, 0x69, 0x73, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72,
+0x74, 0x6f, 0x5f, 0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73,
+0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0, 0x41,
+0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61,
+0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x0,
+0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75,
+0x69, 0x6c, 0x6c, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
+0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0, 0x50,
+0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61, 0x6c, 0x0, 0x41,
+0x73, 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e,
+0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e,
+0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61, 0x67, 0x75, 0x73, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63,
+0x6f, 0x73, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f,
+0x75, 0x70, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61,
+0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76,
+0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x74, 0x6f, 0x6c, 0x61, 0x0, 0x41,
+0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b,
+0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x63, 0x63, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
+0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
+0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
+0x2f, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
+0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, 0x61,
+0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65,
+0x6c, 0x65, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
+0x2f, 0x54, 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0,
+0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70, 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e,
+0x6f, 0x6c, 0x75, 0x6c, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69,
+0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x4a, 0x75, 0x62, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x65, 0x72, 0x6f,
+0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b,
+0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x20, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d,
+0x61, 0x63, 0x65, 0x69, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65,
+0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x6d, 0x0, 0x45, 0x75,
+0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69,
+0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x20,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c,
+0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
+0x52, 0x69, 0x67, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53,
+0x61, 0x62, 0x6c, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x65, 0x0,
+0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x41, 0x73, 0x69,
+0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x36, 0x0, 0x45, 0x75,
+0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x6a, 0x65, 0x76, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
+0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61,
+0x72, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69,
+0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67,
+0x79, 0x61, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61,
+0x67, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x0,
+0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e,
+0x69, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0, 0x45,
+0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75, 0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72,
+0x73, 0x65, 0x79, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75,
+0x61, 0x72, 0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, 0x61, 0x67, 0x61,
+0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56, 0x65, 0x72, 0x64, 0x65,
+0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
+0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47,
+0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d,
+0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73,
+0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e,
+0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f, 0x6a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c,
+0x65, 0x67, 0x6f, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
+0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
+0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75,
+0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
+0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
+0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68, 0x75, 0x61, 0x69, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a,
+0x75, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x50,
+0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
+0x61, 0x6e, 0x67, 0x75, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0, 0x50, 0x61, 0x63,
+0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
+0x2f, 0x44, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63,
+0x61, 0x69, 0x72, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0, 0x50, 0x61, 0x63,
+0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
+0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50,
+0x65, 0x72, 0x74, 0x68, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0, 0x49,
+0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d,
+0x61, 0x68, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65,
+0x6c, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74,
+0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x41, 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
+0x36, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x66, 0x61, 0x74, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f,
+0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x42, 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c,
+0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61,
+0x72, 0x61, 0x63, 0x68, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65,
+0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72,
+0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f,
+0x74, 0x74, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0, 0x41, 0x73,
+0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x72,
+0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x63, 0x6b,
+0x68, 0x6f, 0x6c, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73,
+0x68, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65,
+0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65,
+0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72,
+0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
+0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65,
+0x6c, 0x61, 0x69, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
+0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42,
+0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f,
+0x59, 0x6f, 0x72, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x41, 0x6d, 0x65,
+0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e,
+0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41,
+0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61,
+0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0, 0x45, 0x75,
+0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
+0x61, 0x2f, 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62,
+0x61, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
+0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
+0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42,
+0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0,
+0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b,
+0x75, 0x74, 0x73, 0x6b, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2d, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2d, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2d, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2d, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2d, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2d, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x34, 0x35, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x33, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55,
+0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0
+};
+// GENERATED PART ENDS HERE
+
+QT_END_NAMESPACE
+
+#endif // QTIMEZONEPRIVATE_DATA_P_H
diff --git a/src/corelib/tools/qtimezoneprivate_icu.cpp b/src/corelib/time/qtimezoneprivate_icu.cpp
index 5570ce7571..5570ce7571 100644
--- a/src/corelib/tools/qtimezoneprivate_icu.cpp
+++ b/src/corelib/time/qtimezoneprivate_icu.cpp
diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/time/qtimezoneprivate_mac.mm
index d3c4fbe5da..d3c4fbe5da 100644
--- a/src/corelib/tools/qtimezoneprivate_mac.mm
+++ b/src/corelib/time/qtimezoneprivate_mac.mm
diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index 24a9a00f11..5f6491ef81 100644
--- a/src/corelib/tools/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -53,7 +53,7 @@
//
#include "qtimezone.h"
-#include "qlocale_p.h"
+#include "private/qlocale_p.h"
#include "qvector.h"
#if QT_CONFIG(icu)
@@ -282,9 +282,9 @@ struct QTzTransitionRule
quint8 abbreviationIndex;
};
Q_DECLARE_TYPEINFO(QTzTransitionRule, Q_PRIMITIVE_TYPE);
-Q_DECL_CONSTEXPR inline bool operator==(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator==(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
{ return lhs.stdOffset == rhs.stdOffset && lhs.dstOffset == rhs.dstOffset && lhs.abbreviationIndex == rhs.abbreviationIndex; }
-Q_DECL_CONSTEXPR inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
{ return !operator==(lhs, rhs); }
class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate
diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp
index 57bc000af5..f62d7998c8 100644
--- a/src/corelib/tools/qtimezoneprivate_tz.cpp
+++ b/src/corelib/time/qtimezoneprivate_tz.cpp
@@ -40,6 +40,7 @@
#include "qtimezone.h"
#include "qtimezoneprivate_p.h"
#include "qdatetime_p.h" // ### Qt 5.14: remove once YearRange is on QDateTime
+#include "private/qlocale_tools_p.h"
#include <QtCore/QFile>
#include <QtCore/QHash>
@@ -48,8 +49,6 @@
#include <qdebug.h>
-#include "qlocale_tools_p.h"
-
#include <algorithm>
#include <errno.h>
#include <limits.h>
@@ -474,7 +473,7 @@ struct PosixZone
static PosixZone invalid() { return {QString(), InvalidOffset}; }
static PosixZone parse(const char *&pos, const char *end);
- bool hasValidOffset() const Q_DECL_NOTHROW { return offset != InvalidOffset; }
+ bool hasValidOffset() const noexcept { return offset != InvalidOffset; }
};
} // unnamed namespace
@@ -522,6 +521,10 @@ PosixZone PosixZone::parse(const char *&pos, const char *end)
QString name = QString::fromUtf8(nameBegin, nameEnd - nameBegin);
const int offset = zoneEnd > zoneBegin ? parsePosixOffset(zoneBegin, zoneEnd) : InvalidOffset;
pos = zoneEnd;
+ // UTC+hh:mm:ss or GMT+hh:mm:ss should be read as offsets from UTC, not as a
+ // POSIX rule naming a zone as UTC or GMT and specifying a non-zero offset.
+ if (offset != 0 && (name == QLatin1String("UTC") || name == QLatin1String("GMT")))
+ return invalid();
return {std::move(name), offset};
}
@@ -660,8 +663,17 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId)
tzif.setFileName(QLatin1String("/usr/share/zoneinfo/") + QString::fromLocal8Bit(ianaId));
if (!tzif.open(QIODevice::ReadOnly)) {
tzif.setFileName(QLatin1String("/usr/lib/zoneinfo/") + QString::fromLocal8Bit(ianaId));
- if (!tzif.open(QIODevice::ReadOnly))
+ if (!tzif.open(QIODevice::ReadOnly)) {
+ // ianaId may be a POSIX rule, taken from $TZ or /etc/TZ
+ const QByteArray zoneInfo = ianaId.split(',').at(0);
+ const char *begin = zoneInfo.constBegin();
+ if (PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset()
+ && (begin == zoneInfo.constEnd()
+ || PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset())) {
+ m_id = m_posixRule = ianaId;
+ }
return;
+ }
}
}
@@ -1100,7 +1112,7 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
path = QFile::symLinkTarget(path);
if (index >= 0) {
// /etc/localtime is a symlink to the current TZ file, so extract from path
- ianaId = path.mid(index + zoneinfo.size()).toUtf8();
+ ianaId = path.midRef(index + zoneinfo.size()).toUtf8();
}
}
@@ -1126,14 +1138,21 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
while (ianaId.isEmpty() && !ts.atEnd() && ts.status() == QTextStream::Ok) {
line = ts.readLine();
if (line.startsWith(QLatin1String("ZONE="))) {
- ianaId = line.mid(6, line.size() - 7).toUtf8();
+ ianaId = line.midRef(6, line.size() - 7).toUtf8();
} else if (line.startsWith(QLatin1String("TIMEZONE="))) {
- ianaId = line.mid(10, line.size() - 11).toUtf8();
+ ianaId = line.midRef(10, line.size() - 11).toUtf8();
}
}
}
}
+ // Some systems (e.g. uClibc) have a default value for $TZ in /etc/TZ:
+ if (ianaId.isEmpty()) {
+ QFile zone(QStringLiteral("/etc/TZ"));
+ if (zone.open(QIODevice::ReadOnly))
+ ianaId = zone.readAll().trimmed();
+ }
+
// Give up for now and return UTC
if (ianaId.isEmpty())
ianaId = utcQByteArray();
diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp
index 1bf2366748..1bf2366748 100644
--- a/src/corelib/tools/qtimezoneprivate_win.cpp
+++ b/src/corelib/time/qtimezoneprivate_win.cpp
diff --git a/src/corelib/time/time.pri b/src/corelib/time/time.pri
new file mode 100644
index 0000000000..bacb7e875d
--- /dev/null
+++ b/src/corelib/time/time.pri
@@ -0,0 +1,34 @@
+# Qt time / date / zone / calendar module
+
+HEADERS += \
+ time/qdatetime.h \
+ time/qdatetime_p.h
+
+SOURCES += time/qdatetime.cpp
+
+qtConfig(timezone) {
+ HEADERS += \
+ time/qtimezone.h \
+ time/qtimezoneprivate_p.h \
+ time/qtimezoneprivate_data_p.h
+ SOURCES += \
+ time/qtimezone.cpp \
+ time/qtimezoneprivate.cpp
+ !nacl:darwin: {
+ SOURCES += time/qtimezoneprivate_mac.mm
+ } else: android:!android-embedded: {
+ SOURCES += time/qtimezoneprivate_android.cpp
+ } else: unix: {
+ SOURCES += time/qtimezoneprivate_tz.cpp
+ qtConfig(icu): SOURCES += time/qtimezoneprivate_icu.cpp
+ } else: qtConfig(icu): {
+ SOURCES += time/qtimezoneprivate_icu.cpp
+ } else: win32: {
+ SOURCES += time/qtimezoneprivate_win.cpp
+ }
+}
+
+qtConfig(datetimeparser) {
+ HEADERS += time/qdatetimeparser_p.h
+ SOURCES += time/qdatetimeparser.cpp
+}
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h
index 0146e22fa3..b01ce0db58 100644
--- a/src/corelib/tools/qalgorithms.h
+++ b/src/corelib/tools/qalgorithms.h
@@ -524,7 +524,7 @@ QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessItera
# if (defined __apple_build_version__ && __clang_major__ >= 7) || (Q_CC_CLANG >= 307)
# define QT_HAS_CONSTEXPR_BUILTINS
# endif
-#elif defined(Q_CC_MSVC) && !defined(Q_CC_INTEL) && !defined(Q_OS_WINCE) && !defined(Q_PROCESSOR_ARM)
+#elif defined(Q_CC_MSVC) && !defined(Q_CC_INTEL) && !defined(Q_PROCESSOR_ARM)
# define QT_HAS_CONSTEXPR_BUILTINS
#elif defined(Q_CC_GNU)
# define QT_HAS_CONSTEXPR_BUILTINS
@@ -533,7 +533,7 @@ QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessItera
#if defined QT_HAS_CONSTEXPR_BUILTINS
#if defined(Q_CC_GNU) || defined(Q_CC_CLANG)
# define QT_HAS_BUILTIN_CTZS
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
{
# if QT_HAS_BUILTIN(__builtin_ctzs)
return __builtin_ctzs(v);
@@ -542,7 +542,7 @@ Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) Q_DECL_NOTHROW
# endif
}
#define QT_HAS_BUILTIN_CLZS
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) noexcept
{
# if QT_HAS_BUILTIN(__builtin_clzs)
return __builtin_clzs(v);
@@ -551,44 +551,44 @@ Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) Q_DECL_NOTHROW
# endif
}
#define QT_HAS_BUILTIN_CTZ
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctz(quint32 v) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctz(quint32 v) noexcept
{
return __builtin_ctz(v);
}
#define QT_HAS_BUILTIN_CLZ
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clz(quint32 v) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clz(quint32 v) noexcept
{
return __builtin_clz(v);
}
#define QT_HAS_BUILTIN_CTZLL
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzll(quint64 v) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzll(quint64 v) noexcept
{
return __builtin_ctzll(v);
}
#define QT_HAS_BUILTIN_CLZLL
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzll(quint64 v) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzll(quint64 v) noexcept
{
return __builtin_clzll(v);
}
#define QALGORITHMS_USE_BUILTIN_POPCOUNT
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcount(quint32 v) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcount(quint32 v) noexcept
{
return __builtin_popcount(v);
}
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcount(quint8 v) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcount(quint8 v) noexcept
{
return __builtin_popcount(v);
}
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcount(quint16 v) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcount(quint16 v) noexcept
{
return __builtin_popcount(v);
}
#define QALGORITHMS_USE_BUILTIN_POPCOUNTLL
-Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) noexcept
{
return __builtin_popcountll(v);
}
-#elif defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) && !defined(Q_PROCESSOR_ARM)
+#elif defined(Q_CC_MSVC) && !defined(Q_PROCESSOR_ARM)
#define QT_POPCOUNT_CONSTEXPR
#define QT_POPCOUNT_RELAXED_CONSTEXPR
#define QT_HAS_BUILTIN_CTZ
@@ -630,12 +630,12 @@ Q_ALWAYS_INLINE unsigned long qt_builtin_clzll(quint64 val)
}
#endif // MSVC 64bit
# define QT_HAS_BUILTIN_CTZS
-Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) Q_DECL_NOTHROW
+Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
{
return qt_builtin_ctz(v);
}
#define QT_HAS_BUILTIN_CLZS
-Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) Q_DECL_NOTHROW
+Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) noexcept
{
return qt_builtin_clz(v) - 16U;
}
@@ -652,19 +652,19 @@ Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) Q_DECL_NOTHROW
#if defined(__AVX__) || defined(__SSE4_2__) || defined(__POPCNT__)
#define QALGORITHMS_USE_BUILTIN_POPCOUNT
#define QALGORITHMS_USE_BUILTIN_POPCOUNTLL
-Q_ALWAYS_INLINE uint qt_builtin_popcount(quint32 v) Q_DECL_NOTHROW
+Q_ALWAYS_INLINE uint qt_builtin_popcount(quint32 v) noexcept
{
return __popcnt(v);
}
-Q_ALWAYS_INLINE uint qt_builtin_popcount(quint8 v) Q_DECL_NOTHROW
+Q_ALWAYS_INLINE uint qt_builtin_popcount(quint8 v) noexcept
{
return __popcnt16(v);
}
-Q_ALWAYS_INLINE uint qt_builtin_popcount(quint16 v) Q_DECL_NOTHROW
+Q_ALWAYS_INLINE uint qt_builtin_popcount(quint16 v) noexcept
{
return __popcnt16(v);
}
-Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) Q_DECL_NOTHROW
+Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) noexcept
{
#if Q_PROCESSOR_WORDSIZE == 8
return __popcnt64(v);
@@ -685,7 +685,7 @@ Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) Q_DECL_NOTHROW
} //namespace QAlgorithmsPrivate
-Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint32 v) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint32 v) noexcept
{
#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
return QAlgorithmsPrivate::qt_builtin_popcount(v);
@@ -698,7 +698,7 @@ Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint32
#endif
}
-Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint8 v) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint8 v) noexcept
{
#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
return QAlgorithmsPrivate::qt_builtin_popcount(v);
@@ -708,7 +708,7 @@ Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint8
#endif
}
-Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint16 v) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint16 v) noexcept
{
#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNT
return QAlgorithmsPrivate::qt_builtin_popcount(v);
@@ -719,7 +719,7 @@ Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint16
#endif
}
-Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint64 v) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint64 v) noexcept
{
#ifdef QALGORITHMS_USE_BUILTIN_POPCOUNTLL
return QAlgorithmsPrivate::qt_builtin_popcountll(v);
@@ -734,7 +734,7 @@ Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(quint64
#endif
}
-Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(long unsigned int v) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(long unsigned int v) noexcept
{
return qPopulationCount(static_cast<quint64>(v));
}
@@ -744,7 +744,7 @@ Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(long un
#endif
#undef QT_POPCOUNT_CONSTEXPR
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint32 v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint32 v) noexcept
{
#if defined(QT_HAS_BUILTIN_CTZ)
return v ? QAlgorithmsPrivate::qt_builtin_ctz(v) : 32U;
@@ -762,7 +762,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint32 v) Q_DECL_NO
#endif
}
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint8 v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint8 v) noexcept
{
#if defined(QT_HAS_BUILTIN_CTZ)
return v ? QAlgorithmsPrivate::qt_builtin_ctz(v) : 8U;
@@ -777,7 +777,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint8 v) Q_DECL_NOT
#endif
}
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint16 v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint16 v) noexcept
{
#if defined(QT_HAS_BUILTIN_CTZS)
return v ? QAlgorithmsPrivate::qt_builtin_ctzs(v) : 16U;
@@ -793,7 +793,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint16 v) Q_DECL_NO
#endif
}
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint64 v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint64 v) noexcept
{
#if defined(QT_HAS_BUILTIN_CTZLL)
return v ? QAlgorithmsPrivate::qt_builtin_ctzll(v) : 64;
@@ -804,12 +804,12 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint64 v) Q_DECL_NO
#endif
}
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(unsigned long v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(unsigned long v) noexcept
{
return qCountTrailingZeroBits(QIntegerForSizeof<long>::Unsigned(v));
}
-Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) noexcept
{
#if defined(QT_HAS_BUILTIN_CLZ)
return v ? QAlgorithmsPrivate::qt_builtin_clz(v) : 32U;
@@ -824,7 +824,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOT
#endif
}
-QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW
+QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) noexcept
{
#if defined(QT_HAS_BUILTIN_CLZ)
return v ? QAlgorithmsPrivate::qt_builtin_clz(v)-24U : 8U;
@@ -836,7 +836,7 @@ QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL
#endif
}
-QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW
+QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) noexcept
{
#if defined(QT_HAS_BUILTIN_CLZS)
return v ? QAlgorithmsPrivate::qt_builtin_clzs(v) : 16U;
@@ -849,7 +849,7 @@ QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DEC
#endif
}
-QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW
+QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) noexcept
{
#if defined(QT_HAS_BUILTIN_CLZLL)
return v ? QAlgorithmsPrivate::qt_builtin_clzll(v) : 64U;
@@ -864,7 +864,7 @@ QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DEC
#endif
}
-QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW
+QT_POPCOUNT_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) noexcept
{
return qCountLeadingZeroBits(QIntegerForSizeof<long>::Unsigned(v));
}
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index a04536b18b..234a44f6b6 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -41,11 +41,114 @@
#include <QtCore/qarraydata.h>
#include <QtCore/private/qnumeric_p.h>
#include <QtCore/private/qtools_p.h>
+#include <QtCore/qmath.h>
#include <stdlib.h>
QT_BEGIN_NAMESPACE
+/*
+ * This pair of functions is declared in qtools_p.h and is used by the Qt
+ * containers to allocate memory and grow the memory block during append
+ * operations.
+ *
+ * They take size_t parameters and return size_t so they will change sizes
+ * according to the pointer width. However, knowing Qt containers store the
+ * container size and element indexes in ints, these functions never return a
+ * size larger than INT_MAX. This is done by casting the element count and
+ * memory block size to int in several comparisons: the check for negative is
+ * very fast on most platforms as the code only needs to check the sign bit.
+ *
+ * These functions return SIZE_MAX on overflow, which can be passed to malloc()
+ * and will surely cause a NULL return (there's no way you can allocate a
+ * memory block the size of your entire VM space).
+ */
+
+/*!
+ \internal
+ \since 5.7
+
+ Returns the memory block size for a container containing \a elementCount
+ elements, each of \a elementSize bytes, plus a header of \a headerSize
+ bytes. That is, this function returns \c
+ {elementCount * elementSize + headerSize}
+
+ but unlike the simple calculation, it checks for overflows during the
+ multiplication and the addition.
+
+ Both \a elementCount and \a headerSize can be zero, but \a elementSize
+ cannot.
+
+ This function returns SIZE_MAX (~0) on overflow or if the memory block size
+ would not fit an int.
+*/
+size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept
+{
+ unsigned count = unsigned(elementCount);
+ unsigned size = unsigned(elementSize);
+ unsigned header = unsigned(headerSize);
+ Q_ASSERT(elementSize);
+ Q_ASSERT(size == elementSize);
+ Q_ASSERT(header == headerSize);
+
+ if (Q_UNLIKELY(count != elementCount))
+ return std::numeric_limits<size_t>::max();
+
+ unsigned bytes;
+ if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) ||
+ Q_UNLIKELY(add_overflow(bytes, header, &bytes)))
+ return std::numeric_limits<size_t>::max();
+ if (Q_UNLIKELY(int(bytes) < 0)) // catches bytes >= 2GB
+ return std::numeric_limits<size_t>::max();
+
+ return bytes;
+}
+
+/*!
+ \internal
+ \since 5.7
+
+ Returns the memory block size and the number of elements that will fit in
+ that block for a container containing \a elementCount elements, each of \a
+ elementSize bytes, plus a header of \a headerSize bytes. This function
+ assumes the container will grow and pre-allocates a growth factor.
+
+ Both \a elementCount and \a headerSize can be zero, but \a elementSize
+ cannot.
+
+ This function returns SIZE_MAX (~0) on overflow or if the memory block size
+ would not fit an int.
+
+ \note The memory block may contain up to \a elementSize - 1 bytes more than
+ needed.
+*/
+CalculateGrowingBlockSizeResult
+qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept
+{
+ CalculateGrowingBlockSizeResult result = {
+ std::numeric_limits<size_t>::max(),std::numeric_limits<size_t>::max()
+ };
+
+ unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize));
+ if (int(bytes) < 0) // catches std::numeric_limits<size_t>::max()
+ return result;
+
+ unsigned morebytes = qNextPowerOfTwo(bytes);
+ if (Q_UNLIKELY(int(morebytes) < 0)) {
+ // catches morebytes == 2GB
+ // grow by half the difference between bytes and morebytes
+ bytes += (morebytes - bytes) / 2;
+ } else {
+ bytes = morebytes;
+ }
+
+ result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize);
+ result.size = bytes;
+ return result;
+}
+
+// End of qtools_p.h implementation
+
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers")
@@ -87,7 +190,7 @@ static QArrayData *reallocateData(QArrayData *header, size_t allocSize, uint opt
}
QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
- size_t capacity, AllocationOptions options) Q_DECL_NOTHROW
+ size_t capacity, AllocationOptions options) noexcept
{
// Alignment is a power of two
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
@@ -112,7 +215,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
headerSize += (alignment - Q_ALIGNOF(QArrayData));
if (headerSize > size_t(MaxAllocSize))
- return 0;
+ return nullptr;
size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));
@@ -121,9 +224,9 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
& ~(alignment - 1);
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- header->ref.atomic.store(bool(!(options & Unsharable)));
+ header->ref.atomic.storeRelaxed(bool(!(options & Unsharable)));
#else
- header->ref.atomic.store(1);
+ header->ref.atomic.storeRelaxed(1);
#endif
header->size = 0;
header->alloc = capacity;
@@ -135,7 +238,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
}
QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize, size_t capacity,
- AllocationOptions options) Q_DECL_NOTHROW
+ AllocationOptions options) noexcept
{
Q_ASSERT(data);
Q_ASSERT(data->isMutable());
@@ -150,7 +253,7 @@ QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize,
}
void QArrayData::deallocate(QArrayData *data, size_t objectSize,
- size_t alignment) Q_DECL_NOTHROW
+ size_t alignment) noexcept
{
// Alignment is a power of two
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
@@ -163,7 +266,7 @@ void QArrayData::deallocate(QArrayData *data, size_t objectSize,
#endif
Q_ASSERT_X(data == 0 || !data->ref.isStatic(), "QArrayData::deallocate",
- "Static data can not be deleted");
+ "Static data cannot be deleted");
::free(data);
}
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index a642fb9b39..074072b987 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -113,14 +113,14 @@ struct Q_CORE_EXPORT QArrayData
}
Q_REQUIRED_RESULT static QArrayData *allocate(size_t objectSize, size_t alignment,
- size_t capacity, AllocationOptions options = Default) Q_DECL_NOTHROW;
+ size_t capacity, AllocationOptions options = Default) noexcept;
Q_REQUIRED_RESULT static QArrayData *reallocateUnaligned(QArrayData *data, size_t objectSize,
- size_t newCapacity, AllocationOptions newOptions = Default) Q_DECL_NOTHROW;
+ size_t newCapacity, AllocationOptions newOptions = Default) noexcept;
static void deallocate(QArrayData *data, size_t objectSize,
- size_t alignment) Q_DECL_NOTHROW;
+ size_t alignment) noexcept;
static const QArrayData shared_null[2];
- static QArrayData *sharedNull() Q_DECL_NOTHROW { return const_cast<QArrayData*>(shared_null); }
+ static QArrayData *sharedNull() noexcept { return const_cast<QArrayData*>(shared_null); }
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::AllocationOptions)
@@ -254,7 +254,7 @@ struct QTypedArrayData
return result;
}
- static QTypedArrayData *sharedNull() Q_DECL_NOTHROW
+ static QTypedArrayData *sharedNull() noexcept
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
return static_cast<QTypedArrayData *>(QArrayData::sharedNull());
@@ -306,8 +306,6 @@ struct QArrayDataPointerRef
// accomplished by hiding a static const instance of QStaticArrayData, which is
// POD.
-#if defined(Q_COMPILER_VARIADIC_MACROS)
-#if defined(Q_COMPILER_LAMBDA)
// Hide array inside a lambda
#define Q_ARRAY_LITERAL(Type, ...) \
([]() -> QArrayDataPointerRef<Type> { \
@@ -324,15 +322,12 @@ struct QArrayDataPointerRef
return StaticWrapper::get(); \
}()) \
/**/
-#endif
-#endif // defined(Q_COMPILER_VARIADIC_MACROS)
-#if defined(Q_ARRAY_LITERAL)
#define Q_ARRAY_LITERAL_IMPL(Type, ...) \
- union { Type type_must_be_POD; } dummy; Q_UNUSED(dummy) \
+ Q_STATIC_ASSERT(std::is_literal_type<Type>::value); \
\
/* Portable compile-time array size computation */ \
- Type data[] = { __VA_ARGS__ }; Q_UNUSED(data) \
+ Q_CONSTEXPR Type data[] = { __VA_ARGS__ }; Q_UNUSED(data); \
enum { Size = sizeof(data) / sizeof(data[0]) }; \
\
static const QStaticArrayData<Type, Size> literal = { \
@@ -342,31 +337,6 @@ struct QArrayDataPointerRef
{ static_cast<QTypedArrayData<Type> *>( \
const_cast<QArrayData *>(&literal.header)) }; \
/**/
-#else
-// As a fallback, memory is allocated and data copied to the heap.
-
-// The fallback macro does NOT use variadic macros and does NOT support
-// variable number of arguments. It is suitable for char arrays.
-
-namespace QtPrivate {
- template <class T, size_t N>
- inline QArrayDataPointerRef<T> qMakeArrayLiteral(const T (&array)[N])
- {
- union { T type_must_be_POD; } dummy; Q_UNUSED(dummy)
-
- QArrayDataPointerRef<T> result = { QTypedArrayData<T>::allocate(N) };
- Q_CHECK_PTR(result.ptr);
-
- ::memcpy(result.ptr->data(), array, N * sizeof(T));
- result.ptr->size = N;
-
- return result;
- }
-}
-
-#define Q_ARRAY_LITERAL(Type, Array) \
- QT_PREPEND_NAMESPACE(QtPrivate::qMakeArrayLiteral)<Type>( Array )
-#endif // !defined(Q_ARRAY_LITERAL)
namespace QtPrivate {
struct Q_CORE_EXPORT QContainerImplHelper
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index 7e1b43f9b1..8e19525f07 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -106,7 +106,7 @@ struct QPodArrayOps
void destroyAll() // Call from destructors, ONLY!
{
Q_ASSERT(this->isMutable());
- Q_ASSERT(this->ref.atomic.load() == 0);
+ Q_ASSERT(this->ref.atomic.loadRelaxed() == 0);
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
@@ -204,7 +204,7 @@ struct QGenericArrayOps
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
- Q_ASSERT(this->ref.atomic.load() == 0);
+ Q_ASSERT(this->ref.atomic.loadRelaxed() == 0);
const T *const b = this->begin();
const T *i = this->end();
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
index 51cfa6e849..0322615f91 100644
--- a/src/corelib/tools/qarraydatapointer.h
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -52,7 +52,7 @@ private:
typedef QArrayDataOps<T> DataOps;
public:
- QArrayDataPointer() Q_DECL_NOTHROW
+ QArrayDataPointer() noexcept
: d(Data::sharedNull())
{
}
@@ -82,20 +82,18 @@ public:
return *this;
}
-#ifdef Q_COMPILER_RVALUE_REFS
- QArrayDataPointer(QArrayDataPointer &&other) Q_DECL_NOTHROW
+ QArrayDataPointer(QArrayDataPointer &&other) noexcept
: d(other.d)
{
other.d = Data::sharedNull();
}
- QArrayDataPointer &operator=(QArrayDataPointer &&other) Q_DECL_NOTHROW
+ QArrayDataPointer &operator=(QArrayDataPointer &&other) noexcept
{
QArrayDataPointer moved(std::move(other));
this->swap(moved);
return *this;
}
-#endif
DataOps &operator*() const
{
@@ -150,7 +148,7 @@ public:
bool isSharable() const { return d->isSharable(); }
#endif
- void swap(QArrayDataPointer &other) Q_DECL_NOTHROW
+ void swap(QArrayDataPointer &other) noexcept
{
qSwap(d, other.d);
}
diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h
index ff40bf5654..9b0e931aca 100644
--- a/src/corelib/tools/qbitarray.h
+++ b/src/corelib/tools/qbitarray.h
@@ -50,21 +50,19 @@ class Q_CORE_EXPORT QBitArray
{
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
- friend Q_CORE_EXPORT uint qHash(const QBitArray &key, uint seed) Q_DECL_NOTHROW;
+ friend Q_CORE_EXPORT uint qHash(const QBitArray &key, uint seed) noexcept;
QByteArray d;
public:
- inline QBitArray() Q_DECL_NOTHROW {}
+ inline QBitArray() noexcept {}
explicit QBitArray(int size, bool val = false);
QBitArray(const QBitArray &other) : d(other.d) {}
inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; }
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QBitArray(QBitArray &&other) Q_DECL_NOTHROW : d(std::move(other.d)) {}
- inline QBitArray &operator=(QBitArray &&other) Q_DECL_NOTHROW
+ inline QBitArray(QBitArray &&other) noexcept : d(std::move(other.d)) {}
+ inline QBitArray &operator=(QBitArray &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- inline void swap(QBitArray &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ inline void swap(QBitArray &other) noexcept { qSwap(d, other.d); }
inline int size() const { return (d.size() << 3) - *d.constData(); }
inline int count() const { return (d.size() << 3) - *d.constData(); }
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index c8bb384532..c25d39461f 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -130,106 +130,6 @@ int qFindByteArray(
const char *haystack0, int haystackLen, int from,
const char *needle0, int needleLen);
-/*
- * This pair of functions is declared in qtools_p.h and is used by the Qt
- * containers to allocate memory and grow the memory block during append
- * operations.
- *
- * They take size_t parameters and return size_t so they will change sizes
- * according to the pointer width. However, knowing Qt containers store the
- * container size and element indexes in ints, these functions never return a
- * size larger than INT_MAX. This is done by casting the element count and
- * memory block size to int in several comparisons: the check for negative is
- * very fast on most platforms as the code only needs to check the sign bit.
- *
- * These functions return SIZE_MAX on overflow, which can be passed to malloc()
- * and will surely cause a NULL return (there's no way you can allocate a
- * memory block the size of your entire VM space).
- */
-
-/*!
- \internal
- \since 5.7
-
- Returns the memory block size for a container containing \a elementCount
- elements, each of \a elementSize bytes, plus a header of \a headerSize
- bytes. That is, this function returns \c
- {elementCount * elementSize + headerSize}
-
- but unlike the simple calculation, it checks for overflows during the
- multiplication and the addition.
-
- Both \a elementCount and \a headerSize can be zero, but \a elementSize
- cannot.
-
- This function returns SIZE_MAX (~0) on overflow or if the memory block size
- would not fit an int.
-*/
-size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) Q_DECL_NOTHROW
-{
- unsigned count = unsigned(elementCount);
- unsigned size = unsigned(elementSize);
- unsigned header = unsigned(headerSize);
- Q_ASSERT(elementSize);
- Q_ASSERT(size == elementSize);
- Q_ASSERT(header == headerSize);
-
- if (Q_UNLIKELY(count != elementCount))
- return std::numeric_limits<size_t>::max();
-
- unsigned bytes;
- if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) ||
- Q_UNLIKELY(add_overflow(bytes, header, &bytes)))
- return std::numeric_limits<size_t>::max();
- if (Q_UNLIKELY(int(bytes) < 0)) // catches bytes >= 2GB
- return std::numeric_limits<size_t>::max();
-
- return bytes;
-}
-
-/*!
- \internal
- \since 5.7
-
- Returns the memory block size and the number of elements that will fit in
- that block for a container containing \a elementCount elements, each of \a
- elementSize bytes, plus a header of \a headerSize bytes. This function
- assumes the container will grow and pre-allocates a growth factor.
-
- Both \a elementCount and \a headerSize can be zero, but \a elementSize
- cannot.
-
- This function returns SIZE_MAX (~0) on overflow or if the memory block size
- would not fit an int.
-
- \note The memory block may contain up to \a elementSize - 1 bytes more than
- needed.
-*/
-CalculateGrowingBlockSizeResult
-qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) Q_DECL_NOTHROW
-{
- CalculateGrowingBlockSizeResult result = {
- std::numeric_limits<size_t>::max(),std::numeric_limits<size_t>::max()
- };
-
- unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize));
- if (int(bytes) < 0) // catches std::numeric_limits<size_t>::max()
- return result;
-
- unsigned morebytes = qNextPowerOfTwo(bytes);
- if (Q_UNLIKELY(int(morebytes) < 0)) {
- // catches morebytes == 2GB
- // grow by half the difference between bytes and morebytes
- bytes += (morebytes - bytes) / 2;
- } else {
- bytes = morebytes;
- }
-
- result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize);
- result.size = bytes;
- return result;
-}
-
/*****************************************************************************
Safe and portable C string functions; extensions to standard string.h
*****************************************************************************/
@@ -239,8 +139,8 @@ qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t heade
Returns a duplicate string.
Allocates space for a copy of \a src, copies it, and returns a
- pointer to the copy. If \a src is nullptr, it immediately returns
- nullptr.
+ pointer to the copy. If \a src is \nullptr, it immediately returns
+ \nullptr.
Ownership is passed to the caller, so the returned string must be
deleted using \c delete[].
@@ -258,7 +158,7 @@ char *qstrdup(const char *src)
Copies all the characters up to and including the '\\0' from \a
src into \a dst and returns a pointer to \a dst. If \a src is
- nullptr, it immediately returns nullptr.
+ \nullptr, it immediately returns \nullptr.
This function assumes that \a dst is large enough to hold the
contents of \a src.
@@ -291,7 +191,7 @@ char *qstrcpy(char *dst, const char *src)
Copies at most \a len bytes from \a src (stopping at \a len or the
terminating '\\0' whichever comes first) into \a dst and returns a
pointer to \a dst. Guarantees that \a dst is '\\0'-terminated. If
- \a src or \a dst is nullptr, returns nullptr immediately.
+ \a src or \a dst is \nullptr, returns \nullptr immediately.
This function assumes that \a dst is at least \a len characters
long.
@@ -326,7 +226,7 @@ char *qstrncpy(char *dst, const char *src, uint len)
A safe \c strlen() function.
Returns the number of characters that precede the terminating '\\0',
- or 0 if \a str is nullptr.
+ or 0 if \a str is \nullptr.
\sa qstrnlen()
*/
@@ -338,7 +238,7 @@ char *qstrncpy(char *dst, const char *src, uint len)
A safe \c strnlen() function.
Returns the number of characters that precede the terminating '\\0', but
- at most \a maxlen. If \a str is nullptr, returns 0.
+ at most \a maxlen. If \a str is \nullptr, returns 0.
\sa qstrlen()
*/
@@ -352,10 +252,10 @@ char *qstrncpy(char *dst, const char *src, uint len)
is less than \a str2, 0 if \a str1 is equal to \a str2 or a
positive value if \a str1 is greater than \a str2.
- Special case 1: Returns 0 if \a str1 and \a str2 are both nullptr.
+ Special case 1: Returns 0 if \a str1 and \a str2 are both \nullptr.
Special case 2: Returns an arbitrary non-zero value if \a str1 is
- nullptr or \a str2 is nullptr (but not both).
+ \nullptr or \a str2 is \nullptr (but not both).
\sa qstrncmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons},
QByteArray::compare()
@@ -378,10 +278,10 @@ int qstrcmp(const char *str1, const char *str2)
str1 is equal to \a str2 or a positive value if \a str1 is greater
than \a str2.
- Special case 1: Returns 0 if \a str1 and \a str2 are both nullptr.
+ Special case 1: Returns 0 if \a str1 and \a str2 are both \nullptr.
- Special case 2: Returns a random non-zero value if \a str1 is nullptr
- or \a str2 is nullptr (but not both).
+ Special case 2: Returns a random non-zero value if \a str1 is \nullptr
+ or \a str2 is \nullptr (but not both).
\sa qstrcmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons},
QByteArray::compare()
@@ -398,10 +298,10 @@ int qstrcmp(const char *str1, const char *str2)
str1 is equal to \a str2 or a positive value if \a str1 is greater
than \a str2.
- Special case 1: Returns 0 if \a str1 and \a str2 are both nullptr.
+ Special case 1: Returns 0 if \a str1 and \a str2 are both \nullptr.
- Special case 2: Returns a random non-zero value if \a str1 is nullptr
- or \a str2 is nullptr (but not both).
+ Special case 2: Returns a random non-zero value if \a str1 is \nullptr
+ or \a str2 is \nullptr (but not both).
\sa qstrcmp(), qstrncmp(), qstrnicmp(), {8-bit Character Comparisons},
QByteArray::compare()
@@ -491,10 +391,10 @@ int qstricmp(const char *str1, const char *str2)
is equal to \a str2 or a positive value if \a str1 is greater than \a
str2.
- Special case 1: Returns 0 if \a str1 and \a str2 are both nullptr.
+ Special case 1: Returns 0 if \a str1 and \a str2 are both \nullptr.
- Special case 2: Returns a random non-zero value if \a str1 is nullptr
- or \a str2 is nullptr (but not both).
+ Special case 2: Returns a random non-zero value if \a str1 is \nullptr
+ or \a str2 is \nullptr (but not both).
\sa qstrcmp(), qstrncmp(), qstricmp(), {8-bit Character Comparisons},
QByteArray::compare()
@@ -523,7 +423,7 @@ int qstrnicmp(const char *str1, const char *str2, uint len)
A helper for QByteArray::compare. Compares \a len1 bytes from \a str1 to \a
len2 bytes from \a str2. If \a len2 is -1, then \a str2 is expected to be
- null-terminated.
+ '\\0'-terminated.
*/
int qstrnicmp(const char *str1, qsizetype len1, const char *str2, qsizetype len2)
{
@@ -1038,8 +938,8 @@ QByteArray qUncompress(const uchar* data, int nbytes)
\snippet code/src_corelib_tools_qbytearray.cpp 5
All functions except isNull() treat null byte arrays the same as
- empty byte arrays. For example, data() returns a pointer to a
- '\\0' character for a null byte array (\e not a null pointer),
+ empty byte arrays. For example, data() returns a valid pointer
+ (\e not nullptr) to a '\\0' character for a byte array
and QByteArray() compares equal to QByteArray(""). We recommend
that you always use isEmpty() and avoid isNull().
@@ -1281,7 +1181,7 @@ QByteArray qUncompress(const uchar* data, int nbytes)
Assigns \a other to this byte array and returns a reference to
this byte array.
*/
-QByteArray &QByteArray::operator=(const QByteArray & other) Q_DECL_NOTHROW
+QByteArray &QByteArray::operator=(const QByteArray & other) noexcept
{
other.d->ref.ref();
if (!d->ref.deref())
@@ -1537,6 +1437,15 @@ QByteArray &QByteArray::operator=(const char *str)
will apply to the character in the QByteArray from which you got
the reference.
+ \note Before Qt 5.14 it was possible to use this operator to access
+ a character at an out-of-bounds position in the byte array, and
+ then assign to such a position, causing the byte array to be
+ automatically resized. Furthermore, assigning a value to the
+ returned QByteRef would cause a detach of the byte array, even if the
+ byte array has been copied in the meanwhile (and the QByteRef kept
+ alive while the copy was taken). These behaviors are deprecated,
+ and will be changed in a future version of Qt.
+
\sa at()
*/
@@ -1765,9 +1674,10 @@ void QByteArray::chop(int n)
If \a data is 0, a null byte array is constructed.
- If \a size is negative, \a data is assumed to point to a nul-terminated
- string and its length is determined dynamically. The terminating
- nul-character is not considered part of the byte array.
+ If \a size is negative, \a data is assumed to point to a
+ '\\0'-terminated string and its length is determined dynamically.
+ The terminating \\0 character is not considered part of the
+ byte array.
QByteArray makes a deep copy of the string data.
@@ -1924,7 +1834,7 @@ void QByteArray::expand(int i)
/*!
\internal
- Return a QByteArray that is sure to be NUL-terminated.
+ Return a QByteArray that is sure to be '\\0'-terminated.
By default, all QByteArray have an extra NUL at the end,
guaranteeing that assumption. However, if QByteArray::fromRawData
@@ -2162,7 +2072,7 @@ static inline QByteArray &qbytearray_insert(QByteArray *ba,
{
Q_ASSERT(pos >= 0);
- if (pos < 0 || len <= 0 || arr == 0)
+ if (pos < 0 || len <= 0 || arr == nullptr)
return *ba;
int oldsize = ba->size();
@@ -2336,8 +2246,8 @@ QByteArray &QByteArray::replace(int pos, int len, const QByteArray &after)
\overload
- Replaces \a len bytes from index position \a pos with the zero terminated
- string \a after.
+ Replaces \a len bytes from index position \a pos with the
+ '\\0'-terminated string \a after.
Notice: this can change the length of the byte array.
*/
@@ -2415,7 +2325,7 @@ QByteArray &QByteArray::replace(const char *c, const QByteArray &after)
Replaces every occurrence of the string \a before with the string \a after.
Since the sizes of the strings are given by \a bsize and \a asize, they
- may contain zero characters and do not need to be zero-terminated.
+ may contain zero characters and do not need to be '\\0'-terminated.
*/
QByteArray &QByteArray::replace(const char *before, int bsize, const char *after, int asize)
@@ -3281,10 +3191,10 @@ static QByteArray toCase_template(T &input, const uchar * table)
}
if (firstBad == e)
- return qMove(input);
+ return std::move(input);
// transform the rest
- QByteArray s = qMove(input); // will copy if T is const QByteArray
+ QByteArray s = std::move(input); // will copy if T is const QByteArray
char *b = s.begin(); // will detach if necessary
char *p = b + (firstBad - orig_begin);
e = b + s.size();
@@ -3882,9 +3792,7 @@ static qulonglong toIntegral_helper(const char *data, bool *ok, int base, qulong
template <typename T> static inline
T toIntegral_helper(const char *data, bool *ok, int base)
{
- // ### Qt6: use std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type
- const bool isUnsigned = T(0) < T(-1);
- typedef typename QtPrivate::QConditional<isUnsigned, qulonglong, qlonglong>::Type Int64;
+ using Int64 = typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type;
#if defined(QT_CHECK_RANGE)
if (base != 0 && (base < 2 || base > 36)) {
@@ -3914,7 +3822,7 @@ T toIntegral_helper(const char *data, bool *ok, int base)
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\note The conversion of the number is performed in the default C locale,
@@ -3940,7 +3848,7 @@ qlonglong QByteArray::toLongLong(bool *ok, int base) const
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\note The conversion of the number is performed in the default C locale,
@@ -3965,7 +3873,7 @@ qulonglong QByteArray::toULongLong(bool *ok, int base) const
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\snippet code/src_corelib_tools_qbytearray.cpp 36
@@ -3992,7 +3900,7 @@ int QByteArray::toInt(bool *ok, int base) const
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\note The conversion of the number is performed in the default C locale,
@@ -4019,7 +3927,7 @@ uint QByteArray::toUInt(bool *ok, int base) const
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\snippet code/src_corelib_tools_qbytearray.cpp 37
@@ -4047,7 +3955,7 @@ long QByteArray::toLong(bool *ok, int base) const
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\note The conversion of the number is performed in the default C locale,
@@ -4071,7 +3979,7 @@ ulong QByteArray::toULong(bool *ok, int base) const
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\note The conversion of the number is performed in the default C locale,
@@ -4096,7 +4004,7 @@ short QByteArray::toShort(bool *ok, int base) const
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\note The conversion of the number is performed in the default C locale,
@@ -4117,7 +4025,7 @@ ushort QByteArray::toUShort(bool *ok, int base) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for other reasons (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\snippet code/src_corelib_tools_qbytearray.cpp 38
@@ -4137,10 +4045,9 @@ ushort QByteArray::toUShort(bool *ok, int base) const
double QByteArray::toDouble(bool *ok) const
{
- QByteArray nulled = nulTerminated();
bool nonNullOk = false;
int processed = 0;
- double d = qt_asciiToDouble(nulled.constData(), nulled.length(),
+ double d = qt_asciiToDouble(constData(), size(),
nonNullOk, processed, WhitespacesAllowed);
if (ok)
*ok = nonNullOk;
@@ -4153,7 +4060,7 @@ double QByteArray::toDouble(bool *ok) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for other reasons (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\snippet code/src_corelib_tools_qbytearray.cpp 38float
@@ -4543,7 +4450,7 @@ QByteArray QByteArray::number(double n, char f, int prec)
\snippet code/src_corelib_tools_qbytearray.cpp 43
\warning A byte array created with fromRawData() is \e not
- null-terminated, unless the raw data contains a 0 character at
+ '\\0'-terminated, unless the raw data contains a 0 character at
position \a size. While that does not matter for QDataStream or
functions like indexOf(), passing the byte array to a function
accepting a \c{const char *} expected to be '\\0'-terminated will
@@ -4868,7 +4775,7 @@ static void q_toPercentEncoding(QByteArray *ba, const char *dontEncode, const ch
QByteArray input = *ba;
int len = input.count();
const char *inputData = input.constData();
- char *output = 0;
+ char *output = nullptr;
int length = 0;
for (int i = 0; i < len; ++i) {
@@ -4908,7 +4815,7 @@ void q_toPercentEncoding(QByteArray *ba, const char *exclude, const char *includ
void q_normalizePercentEncoding(QByteArray *ba, const char *exclude)
{
q_fromPercentEncoding(ba, '%');
- q_toPercentEncoding(ba, exclude, 0, '%');
+ q_toPercentEncoding(ba, exclude, nullptr, '%');
}
/*!
@@ -5056,4 +4963,41 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA
\sa QStringLiteral
*/
+namespace QtPrivate {
+namespace DeprecatedRefClassBehavior {
+void warn(WarningType w, EmittingClass c)
+{
+ static const char deprecatedBehaviorString[] =
+ "The corresponding behavior is deprecated, and will be changed"
+ " in a future version of Qt.";
+
+ const char *emittingClassName = nullptr;
+ const char *containerClassName = nullptr;
+
+ switch (c) {
+ case EmittingClass::QByteRef:
+ emittingClassName = "QByteRef";
+ containerClassName = "QByteArray";
+ break;
+ case EmittingClass::QCharRef:
+ emittingClassName = "QCharRef";
+ containerClassName = "QString";
+ break;
+ }
+
+ switch (w) {
+ case WarningType::OutOfRange:
+ qWarning("Using %s with an index pointing outside the valid range of a %s. %s",
+ emittingClassName, containerClassName, deprecatedBehaviorString);
+ break;
+ case WarningType::DelayedDetach:
+ qWarning("Using %s with on a %s that is not already detached. %s",
+ emittingClassName, containerClassName, deprecatedBehaviorString);
+ break;
+ }
+}
+} // namespace DeprecatedRefClassBehavior
+} // namespace QtPrivate
+
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 8ee3a29ecc..a81051d309 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -168,22 +168,20 @@ public:
};
Q_DECLARE_FLAGS(Base64Options, Base64Option)
- inline QByteArray() Q_DECL_NOTHROW;
+ inline QByteArray() noexcept;
QByteArray(const char *, int size = -1);
QByteArray(int size, char c);
QByteArray(int size, Qt::Initialization);
- inline QByteArray(const QByteArray &) Q_DECL_NOTHROW;
+ inline QByteArray(const QByteArray &) noexcept;
inline ~QByteArray();
- QByteArray &operator=(const QByteArray &) Q_DECL_NOTHROW;
+ QByteArray &operator=(const QByteArray &) noexcept;
QByteArray &operator=(const char *str);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QByteArray(QByteArray && other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }
- inline QByteArray &operator=(QByteArray &&other) Q_DECL_NOTHROW
+ inline QByteArray(QByteArray && other) noexcept : d(other.d) { other.d = Data::sharedNull(); }
+ inline QByteArray &operator=(QByteArray &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- inline void swap(QByteArray &other) Q_DECL_NOTHROW
+ inline void swap(QByteArray &other) noexcept
{ qSwap(d, other.d); }
inline int size() const;
@@ -211,8 +209,8 @@ public:
inline char at(int i) const;
inline char operator[](int i) const;
inline char operator[](uint i) const;
- inline QByteRef operator[](int i);
- inline QByteRef operator[](uint i);
+ Q_REQUIRED_RESULT inline QByteRef operator[](int i);
+ Q_REQUIRED_RESULT inline QByteRef operator[](uint i);
Q_REQUIRED_RESULT char front() const { return at(0); }
Q_REQUIRED_RESULT inline QByteRef front();
Q_REQUIRED_RESULT char back() const { return at(size() - 1); }
@@ -472,7 +470,7 @@ public:
Q_DECLARE_OPERATORS_FOR_FLAGS(QByteArray::Base64Options)
-inline QByteArray::QByteArray() Q_DECL_NOTHROW : d(Data::sharedNull()) { }
+inline QByteArray::QByteArray() noexcept : d(Data::sharedNull()) { }
inline QByteArray::~QByteArray() { if (!d->ref.deref()) Data::deallocate(d); }
inline int QByteArray::size() const
{ return d->size; }
@@ -502,7 +500,7 @@ inline void QByteArray::detach()
{ if (d->ref.isShared() || (d->offset != sizeof(QByteArrayData))) reallocData(uint(d->size) + 1u, d->detachFlags()); }
inline bool QByteArray::isDetached() const
{ return !d->ref.isShared(); }
-inline QByteArray::QByteArray(const QByteArray &a) Q_DECL_NOTHROW : d(a.d)
+inline QByteArray::QByteArray(const QByteArray &a) noexcept : d(a.d)
{ d->ref.ref(); }
inline int QByteArray::capacity() const
@@ -530,7 +528,27 @@ inline void QByteArray::squeeze()
}
}
-class Q_CORE_EXPORT QByteRef {
+namespace QtPrivate {
+namespace DeprecatedRefClassBehavior {
+ enum class EmittingClass {
+ QByteRef,
+ QCharRef,
+ };
+
+ enum class WarningType {
+ OutOfRange,
+ DelayedDetach,
+ };
+
+ Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void warn(WarningType w, EmittingClass c);
+} // namespace DeprecatedAssignmentOperatorBehavior
+} // namespace QtPrivate
+
+class
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+Q_CORE_EXPORT
+#endif
+QByteRef {
QByteArray &a;
int i;
inline QByteRef(QByteArray &array, int idx)
@@ -538,13 +556,37 @@ class Q_CORE_EXPORT QByteRef {
friend class QByteArray;
public:
inline operator char() const
- { return i < a.d->size ? a.d->data()[i] : char(0); }
+ {
+ using namespace QtPrivate::DeprecatedRefClassBehavior;
+ if (Q_LIKELY(i < a.d->size))
+ return a.d->data()[i];
+#ifdef QT_DEBUG
+ warn(WarningType::OutOfRange, EmittingClass::QByteRef);
+#endif
+ return char(0);
+ }
inline QByteRef &operator=(char c)
- { if (i >= a.d->size) a.expand(i); else a.detach();
- a.d->data()[i] = c; return *this; }
+ {
+ using namespace QtPrivate::DeprecatedRefClassBehavior;
+ if (Q_UNLIKELY(i >= a.d->size)) {
+#ifdef QT_DEBUG
+ warn(WarningType::OutOfRange, EmittingClass::QByteRef);
+#endif
+ a.expand(i);
+ } else {
+#ifdef QT_DEBUG
+ if (Q_UNLIKELY(!a.isDetached()))
+ warn(WarningType::DelayedDetach, EmittingClass::QByteRef);
+#endif
+ a.detach();
+ }
+ a.d->data()[i] = c;
+ return *this;
+ }
inline QByteRef &operator=(const QByteRef &c)
- { if (i >= a.d->size) a.expand(i); else a.detach();
- a.d->data()[i] = c.a.d->data()[c.i]; return *this; }
+ {
+ return operator=(char(c));
+ }
inline bool operator==(char c) const
{ return a.d->data()[i] == c; }
inline bool operator!=(char c) const
@@ -560,9 +602,9 @@ public:
};
inline QByteRef QByteArray::operator[](int i)
-{ Q_ASSERT(i >= 0); return QByteRef(*this, i); }
+{ Q_ASSERT(i >= 0); detach(); return QByteRef(*this, i); }
inline QByteRef QByteArray::operator[](uint i)
-{ return QByteRef(*this, i); }
+{ detach(); return QByteRef(*this, i); }
inline QByteRef QByteArray::front() { return operator[](0); }
inline QByteRef QByteArray::back() { return operator[](size() - 1); }
inline QByteArray::iterator QByteArray::begin()
@@ -617,41 +659,41 @@ inline int QByteArray::compare(const QByteArray &a, Qt::CaseSensitivity cs) cons
return cs == Qt::CaseSensitive ? qstrcmp(*this, a) :
qstrnicmp(data(), size(), a.data(), a.size());
}
-inline bool operator==(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator==(const QByteArray &a1, const QByteArray &a2) noexcept
{ return (a1.size() == a2.size()) && (memcmp(a1.constData(), a2.constData(), a1.size())==0); }
-inline bool operator==(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW
+inline bool operator==(const QByteArray &a1, const char *a2) noexcept
{ return a2 ? qstrcmp(a1,a2) == 0 : a1.isEmpty(); }
-inline bool operator==(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator==(const char *a1, const QByteArray &a2) noexcept
{ return a1 ? qstrcmp(a1,a2) == 0 : a2.isEmpty(); }
-inline bool operator!=(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator!=(const QByteArray &a1, const QByteArray &a2) noexcept
{ return !(a1==a2); }
-inline bool operator!=(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW
+inline bool operator!=(const QByteArray &a1, const char *a2) noexcept
{ return a2 ? qstrcmp(a1,a2) != 0 : !a1.isEmpty(); }
-inline bool operator!=(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator!=(const char *a1, const QByteArray &a2) noexcept
{ return a1 ? qstrcmp(a1,a2) != 0 : !a2.isEmpty(); }
-inline bool operator<(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator<(const QByteArray &a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) < 0; }
- inline bool operator<(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW
+ inline bool operator<(const QByteArray &a1, const char *a2) noexcept
{ return qstrcmp(a1, a2) < 0; }
-inline bool operator<(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator<(const char *a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) < 0; }
-inline bool operator<=(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator<=(const QByteArray &a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) <= 0; }
-inline bool operator<=(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW
+inline bool operator<=(const QByteArray &a1, const char *a2) noexcept
{ return qstrcmp(a1, a2) <= 0; }
-inline bool operator<=(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator<=(const char *a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) <= 0; }
-inline bool operator>(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator>(const QByteArray &a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) > 0; }
-inline bool operator>(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW
+inline bool operator>(const QByteArray &a1, const char *a2) noexcept
{ return qstrcmp(a1, a2) > 0; }
-inline bool operator>(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator>(const char *a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) > 0; }
-inline bool operator>=(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator>=(const QByteArray &a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) >= 0; }
-inline bool operator>=(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW
+inline bool operator>=(const QByteArray &a1, const char *a2) noexcept
{ return qstrcmp(a1, a2) >= 0; }
-inline bool operator>=(const char *a1, const QByteArray &a2) Q_DECL_NOTHROW
+inline bool operator>=(const char *a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) >= 0; }
#if !defined(QT_USE_QSTRINGBUILDER)
inline const QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
diff --git a/src/corelib/tools/qbytearraylist.cpp b/src/corelib/tools/qbytearraylist.cpp
index c815e766ab..d04555ed4d 100644
--- a/src/corelib/tools/qbytearraylist.cpp
+++ b/src/corelib/tools/qbytearraylist.cpp
@@ -150,4 +150,26 @@ QByteArray QtPrivate::QByteArrayList_join(const QByteArrayList *that, const char
return res;
}
+/*!
+ \fn int QByteArrayList::indexOf(const char *needle, int from) const
+
+ Returns the index position of the first occurrence of \a needle in
+ the list, searching forward from index position \a from. Returns
+ -1 if no item matched.
+
+ \a needle must be NUL-terminated.
+
+ This overload doesn't require creating a QByteArray, thus saving a
+ memory allocation and some CPU time.
+
+ \since 5.13
+ \overload
+*/
+
+int QtPrivate::QByteArrayList_indexOf(const QByteArrayList *that, const char *needle, int from)
+{
+ const auto it = std::find_if(that->begin() + from, that->end(), [needle](const QByteArray &item) { return item == needle; });
+ return it == that->end() ? -1 : int(std::distance(that->begin(), it));
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbytearraylist.h b/src/corelib/tools/qbytearraylist.h
index ed014dd157..1261e1757c 100644
--- a/src/corelib/tools/qbytearraylist.h
+++ b/src/corelib/tools/qbytearraylist.h
@@ -50,23 +50,24 @@ QT_BEGIN_NAMESPACE
typedef QListIterator<QByteArray> QByteArrayListIterator;
typedef QMutableListIterator<QByteArray> QMutableByteArrayListIterator;
-#ifndef Q_QDOC
+#ifndef Q_CLANG_QDOC
typedef QList<QByteArray> QByteArrayList;
namespace QtPrivate {
QByteArray Q_CORE_EXPORT QByteArrayList_join(const QByteArrayList *that, const char *separator, int separatorLength);
+ int Q_CORE_EXPORT QByteArrayList_indexOf(const QByteArrayList *that, const char *needle, int from);
}
#endif
-#ifdef Q_QDOC
+#ifdef Q_CLANG_QDOC
class QByteArrayList : public QList<QByteArray>
#else
template <> struct QListSpecialMethods<QByteArray>
#endif
{
-#ifndef Q_QDOC
+#ifndef Q_CLANG_QDOC
protected:
- ~QListSpecialMethods() {}
+ ~QListSpecialMethods() = default;
#endif
public:
inline QByteArray join() const
@@ -76,6 +77,9 @@ public:
inline QByteArray join(char sep) const
{ return QtPrivate::QByteArrayList_join(self(), &sep, 1); }
+ inline int indexOf(const char *needle, int from = 0) const
+ { return QtPrivate::QByteArrayList_indexOf(self(), needle, from); }
+
private:
typedef QList<QByteArray> Self;
Self *self() { return static_cast<Self *>(this); }
diff --git a/src/corelib/tools/qbytearraymatcher.cpp b/src/corelib/tools/qbytearraymatcher.cpp
index 72f0e0519d..72e09226af 100644
--- a/src/corelib/tools/qbytearraymatcher.cpp
+++ b/src/corelib/tools/qbytearraymatcher.cpp
@@ -116,9 +116,9 @@ static inline int bm_find(const uchar *cc, int l, int index, const uchar *puc, u
Call setPattern() to give it a pattern to match.
*/
QByteArrayMatcher::QByteArrayMatcher()
- : d(0)
+ : d(nullptr)
{
- p.p = 0;
+ p.p = nullptr;
p.l = 0;
memset(p.q_skiptable, 0, sizeof(p.q_skiptable));
}
@@ -129,7 +129,7 @@ QByteArrayMatcher::QByteArrayMatcher()
the destructor does not delete \a pattern.
*/
QByteArrayMatcher::QByteArrayMatcher(const char *pattern, int length)
- : d(0)
+ : d(nullptr)
{
p.p = reinterpret_cast<const uchar *>(pattern);
p.l = length;
@@ -141,7 +141,7 @@ QByteArrayMatcher::QByteArrayMatcher(const char *pattern, int length)
Call indexIn() to perform a search.
*/
QByteArrayMatcher::QByteArrayMatcher(const QByteArray &pattern)
- : d(0), q_pattern(pattern)
+ : d(nullptr), q_pattern(pattern)
{
p.p = reinterpret_cast<const uchar *>(pattern.constData());
p.l = pattern.size();
@@ -152,7 +152,7 @@ QByteArrayMatcher::QByteArrayMatcher(const QByteArray &pattern)
Copies the \a other byte array matcher to this byte array matcher.
*/
QByteArrayMatcher::QByteArrayMatcher(const QByteArrayMatcher &other)
- : d(0)
+ : d(nullptr)
{
operator=(other);
}
@@ -404,7 +404,7 @@ int qFindByteArray(
/*!
\internal
*/
-int QStaticByteArrayMatcherBase::indexOfIn(const char *needle, uint nlen, const char *haystack, int hlen, int from) const Q_DECL_NOTHROW
+int QStaticByteArrayMatcherBase::indexOfIn(const char *needle, uint nlen, const char *haystack, int hlen, int from) const noexcept
{
if (from < 0)
from = 0;
diff --git a/src/corelib/tools/qbytearraymatcher.h b/src/corelib/tools/qbytearraymatcher.h
index dafaea9c12..0eedfc1d20 100644
--- a/src/corelib/tools/qbytearraymatcher.h
+++ b/src/corelib/tools/qbytearraymatcher.h
@@ -90,15 +90,15 @@ class QStaticByteArrayMatcherBase
uchar data[256];
} m_skiptable;
protected:
- explicit Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcherBase(const char *pattern, uint n) Q_DECL_NOTHROW
+ explicit Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcherBase(const char *pattern, uint n) noexcept
: m_skiptable(generate(pattern, n)) {}
// compiler-generated copy/more ctors/assignment operators are ok!
// compiler-generated dtor is ok!
- Q_CORE_EXPORT int indexOfIn(const char *needle, uint nlen, const char *haystack, int hlen, int from) const Q_DECL_NOTHROW;
+ Q_CORE_EXPORT int indexOfIn(const char *needle, uint nlen, const char *haystack, int hlen, int from) const noexcept;
private:
- static Q_DECL_RELAXED_CONSTEXPR Skiptable generate(const char *pattern, uint n) Q_DECL_NOTHROW
+ static Q_DECL_RELAXED_CONSTEXPR Skiptable generate(const char *pattern, uint n) noexcept
{
const auto uchar_max = (std::numeric_limits<uchar>::max)();
uchar max = n > uchar_max ? uchar_max : n;
@@ -140,23 +140,23 @@ class QStaticByteArrayMatcher : QStaticByteArrayMatcherBase
char m_pattern[N];
Q_STATIC_ASSERT_X(N > 2, "QStaticByteArrayMatcher makes no sense for finding a single-char pattern");
public:
- explicit Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcher(const char (&patternToMatch)[N]) Q_DECL_NOTHROW
+ explicit Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcher(const char (&patternToMatch)[N]) noexcept
: QStaticByteArrayMatcherBase(patternToMatch, N - 1), m_pattern()
{
for (uint i = 0; i < N; ++i)
m_pattern[i] = patternToMatch[i];
}
- int indexIn(const QByteArray &haystack, int from = 0) const Q_DECL_NOTHROW
+ int indexIn(const QByteArray &haystack, int from = 0) const noexcept
{ return this->indexOfIn(m_pattern, N - 1, haystack.data(), haystack.size(), from); }
- int indexIn(const char *haystack, int hlen, int from = 0) const Q_DECL_NOTHROW
+ int indexIn(const char *haystack, int hlen, int from = 0) const noexcept
{ return this->indexOfIn(m_pattern, N - 1, haystack, hlen, from); }
QByteArray pattern() const { return QByteArray(m_pattern, int(N - 1)); }
};
template <uint N>
-Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcher<N> qMakeStaticByteArrayMatcher(const char (&pattern)[N]) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcher<N> qMakeStaticByteArrayMatcher(const char (&pattern)[N]) noexcept
{ return QStaticByteArrayMatcher<N>(pattern); }
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbytedata_p.h b/src/corelib/tools/qbytedata_p.h
index 8331be112d..b319d75811 100644
--- a/src/corelib/tools/qbytedata_p.h
+++ b/src/corelib/tools/qbytedata_p.h
@@ -199,7 +199,7 @@ public:
}
// the number of QByteArrays
- inline qint64 bufferCount() const
+ inline int bufferCount() const
{
return buffers.length();
}
diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h
index 8c0e7860f7..4fcde46fbc 100644
--- a/src/corelib/tools/qcache.h
+++ b/src/corelib/tools/qcache.h
@@ -51,7 +51,7 @@ class QCache
struct Node {
inline Node() : keyPtr(0) {}
inline Node(T *data, int cost)
- : keyPtr(0), t(data), c(cost), p(0), n(0) {}
+ : keyPtr(nullptr), t(data), c(cost), p(nullptr), n(nullptr) {}
const Key *keyPtr; T *t; int c; Node *p,*n;
};
Node *f, *l;
@@ -71,14 +71,14 @@ class QCache
inline T *relink(const Key &key) {
typename QHash<Key, Node>::iterator i = hash.find(key);
if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd())
- return 0;
+ return nullptr;
Node &n = *i;
if (f != &n) {
if (n.p) n.p->n = n.n;
if (n.n) n.n->p = n.p;
if (l == &n) l = n.p;
- n.p = 0;
+ n.p = nullptr;
n.n = f;
f->p = &n;
f = &n;
@@ -89,7 +89,7 @@ class QCache
Q_DISABLE_COPY(QCache)
public:
- inline explicit QCache(int maxCost = 100) Q_DECL_NOTHROW;
+ inline explicit QCache(int maxCost = 100) noexcept;
inline ~QCache() { clear(); }
inline int maxCost() const { return mx; }
@@ -116,13 +116,13 @@ private:
};
template <class Key, class T>
-inline QCache<Key, T>::QCache(int amaxCost) Q_DECL_NOTHROW
- : f(0), l(0), mx(amaxCost), total(0) {}
+inline QCache<Key, T>::QCache(int amaxCost) noexcept
+ : f(nullptr), l(nullptr), mx(amaxCost), total(0) {}
template <class Key, class T>
inline void QCache<Key,T>::clear()
{ while (f) { delete f->t; f = f->n; }
- hash.clear(); l = 0; total = 0; }
+ hash.clear(); l = nullptr; total = 0; }
template <class Key, class T>
inline void QCache<Key,T>::setMaxCost(int m)
@@ -153,11 +153,11 @@ inline T *QCache<Key,T>::take(const Key &key)
{
typename QHash<Key, Node>::iterator i = hash.find(key);
if (i == hash.end())
- return 0;
+ return nullptr;
Node &n = *i;
T *t = n.t;
- n.t = 0;
+ n.t = nullptr;
unlink(n);
return t;
}
diff --git a/src/corelib/tools/qcache.qdoc b/src/corelib/tools/qcache.qdoc
index 31dfcb42cf..ffc21318f4 100644
--- a/src/corelib/tools/qcache.qdoc
+++ b/src/corelib/tools/qcache.qdoc
@@ -70,7 +70,7 @@
To look up objects in the cache, use object() or
operator[](). This function looks up an object by its key, and
returns either a pointer to the cached object (which is owned by
- the cache) or 0.
+ the cache) or \nullptr.
If you want to remove an object from the cache for a particular key,
call remove(). This will also delete the object. If you want to
@@ -171,7 +171,7 @@
/*! \fn template <class Key, class T> T *QCache<Key, T>::object(const Key &key) const
- Returns the object associated with key \a key, or 0 if the key does
+ Returns the object associated with key \a key, or \nullptr if the key does
not exist in the cache.
\warning The returned object is owned by QCache and may be
@@ -190,7 +190,7 @@
/*! \fn template <class Key, class T> T *QCache<Key, T>::operator[](const Key &key) const
- Returns the object associated with key \a key, or 0 if the key does
+ Returns the object associated with key \a key, or \nullptr if the key does
not exist in the cache.
This is the same as object().
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index 47c853084b..e097e4a5fe 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -733,7 +733,7 @@ QT_BEGIN_NAMESPACE
Note that this gives no indication of whether the character is
available in a particular font.
*/
-bool QChar::isPrint(uint ucs4) Q_DECL_NOTHROW
+bool QChar::isPrint(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return false;
@@ -766,7 +766,7 @@ bool QChar::isPrint(uint ucs4) Q_DECL_NOTHROW
/*!
\internal
*/
-bool QT_FASTCALL QChar::isSpace_helper(uint ucs4) Q_DECL_NOTHROW
+bool QT_FASTCALL QChar::isSpace_helper(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return false;
@@ -792,7 +792,7 @@ bool QT_FASTCALL QChar::isSpace_helper(uint ucs4) Q_DECL_NOTHROW
Returns \c true if the UCS-4-encoded character specified by \a ucs4 is
a mark (Mark_* categories); otherwise returns \c false.
*/
-bool QChar::isMark(uint ucs4) Q_DECL_NOTHROW
+bool QChar::isMark(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return false;
@@ -816,7 +816,7 @@ bool QChar::isMark(uint ucs4) Q_DECL_NOTHROW
Returns \c true if the UCS-4-encoded character specified by \a ucs4 is
a punctuation mark (Punctuation_* categories); otherwise returns \c false.
*/
-bool QChar::isPunct(uint ucs4) Q_DECL_NOTHROW
+bool QChar::isPunct(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return false;
@@ -844,7 +844,7 @@ bool QChar::isPunct(uint ucs4) Q_DECL_NOTHROW
Returns \c true if the UCS-4-encoded character specified by \a ucs4 is
a symbol (Symbol_* categories); otherwise returns \c false.
*/
-bool QChar::isSymbol(uint ucs4) Q_DECL_NOTHROW
+bool QChar::isSymbol(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return false;
@@ -874,7 +874,7 @@ bool QChar::isSymbol(uint ucs4) Q_DECL_NOTHROW
/*!
\internal
*/
-bool QT_FASTCALL QChar::isLetter_helper(uint ucs4) Q_DECL_NOTHROW
+bool QT_FASTCALL QChar::isLetter_helper(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return false;
@@ -909,7 +909,7 @@ bool QT_FASTCALL QChar::isLetter_helper(uint ucs4) Q_DECL_NOTHROW
/*!
\internal
*/
-bool QT_FASTCALL QChar::isNumber_helper(uint ucs4) Q_DECL_NOTHROW
+bool QT_FASTCALL QChar::isNumber_helper(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return false;
@@ -938,7 +938,7 @@ bool QT_FASTCALL QChar::isNumber_helper(uint ucs4) Q_DECL_NOTHROW
/*!
\internal
*/
-bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) Q_DECL_NOTHROW
+bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return false;
@@ -1101,7 +1101,7 @@ bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) Q_DECL_NOTHROW
Returns the numeric value of the digit specified by the UCS-4-encoded
character, \a ucs4, or -1 if the character is not a digit.
*/
-int QChar::digitValue(uint ucs4) Q_DECL_NOTHROW
+int QChar::digitValue(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return -1;
@@ -1118,7 +1118,7 @@ int QChar::digitValue(uint ucs4) Q_DECL_NOTHROW
\overload
Returns the category of the UCS-4-encoded character specified by \a ucs4.
*/
-QChar::Category QChar::category(uint ucs4) Q_DECL_NOTHROW
+QChar::Category QChar::category(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return QChar::Other_NotAssigned;
@@ -1135,7 +1135,7 @@ QChar::Category QChar::category(uint ucs4) Q_DECL_NOTHROW
\overload
Returns the direction of the UCS-4-encoded character specified by \a ucs4.
*/
-QChar::Direction QChar::direction(uint ucs4) Q_DECL_NOTHROW
+QChar::Direction QChar::direction(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return QChar::DirL;
@@ -1158,7 +1158,7 @@ QChar::Direction QChar::direction(uint ucs4) Q_DECL_NOTHROW
character specified by \a ucs4
(needed for certain languages such as Arabic or Syriac).
*/
-QChar::JoiningType QChar::joiningType(uint ucs4) Q_DECL_NOTHROW
+QChar::JoiningType QChar::joiningType(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return QChar::Joining_None;
@@ -1181,7 +1181,7 @@ QChar::JoiningType QChar::joiningType(uint ucs4) Q_DECL_NOTHROW
Returns information about the joining properties of the UCS-4-encoded
character specified by \a ucs4 (needed for certain languages such as Arabic).
*/
-QChar::Joining QChar::joining(uint ucs4) Q_DECL_NOTHROW
+QChar::Joining QChar::joining(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return QChar::OtherJoining;
@@ -1217,7 +1217,7 @@ QChar::Joining QChar::joining(uint ucs4) Q_DECL_NOTHROW
\sa mirroredChar()
*/
-bool QChar::hasMirrored(uint ucs4) Q_DECL_NOTHROW
+bool QChar::hasMirrored(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return false;
@@ -1299,7 +1299,7 @@ bool QChar::hasMirrored(uint ucs4) Q_DECL_NOTHROW
\sa hasMirrored()
*/
-uint QChar::mirroredChar(uint ucs4) Q_DECL_NOTHROW
+uint QChar::mirroredChar(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return ucs4;
@@ -1339,7 +1339,7 @@ static const unsigned short * QT_FASTCALL decompositionHelper
if (index == 0xffff) {
*length = 0;
*tag = QChar::NoDecomposition;
- return 0;
+ return nullptr;
}
const unsigned short *decomposition = uc_decomposition_map+index;
@@ -1383,7 +1383,7 @@ QString QChar::decomposition(uint ucs4)
Returns the tag defining the composition of the UCS-4-encoded character
specified by \a ucs4. Returns QChar::NoDecomposition if no decomposition exists.
*/
-QChar::Decomposition QChar::decompositionTag(uint ucs4) Q_DECL_NOTHROW
+QChar::Decomposition QChar::decompositionTag(uint ucs4) noexcept
{
if (ucs4 >= Hangul_SBase && ucs4 < Hangul_SBase + Hangul_SCount)
return QChar::Canonical;
@@ -1409,7 +1409,7 @@ QChar::Decomposition QChar::decompositionTag(uint ucs4) Q_DECL_NOTHROW
Returns the combining class for the UCS-4-encoded character specified by
\a ucs4, as defined in the Unicode standard.
*/
-unsigned char QChar::combiningClass(uint ucs4) Q_DECL_NOTHROW
+unsigned char QChar::combiningClass(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return 0;
@@ -1430,7 +1430,7 @@ unsigned char QChar::combiningClass(uint ucs4) Q_DECL_NOTHROW
Returns the Unicode script property value for the character specified in
its UCS-4-encoded form as \a ucs4.
*/
-QChar::Script QChar::script(uint ucs4) Q_DECL_NOTHROW
+QChar::Script QChar::script(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return QChar::Script_Unknown;
@@ -1448,7 +1448,7 @@ QChar::Script QChar::script(uint ucs4) Q_DECL_NOTHROW
Returns the Unicode version that introduced the character specified in
its UCS-4-encoded form as \a ucs4.
*/
-QChar::UnicodeVersion QChar::unicodeVersion(uint ucs4) Q_DECL_NOTHROW
+QChar::UnicodeVersion QChar::unicodeVersion(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return QChar::Unicode_Unassigned;
@@ -1458,14 +1458,14 @@ QChar::UnicodeVersion QChar::unicodeVersion(uint ucs4) Q_DECL_NOTHROW
/*!
Returns the most recent supported Unicode version.
*/
-QChar::UnicodeVersion QChar::currentUnicodeVersion() Q_DECL_NOTHROW
+QChar::UnicodeVersion QChar::currentUnicodeVersion() noexcept
{
return UNICODE_DATA_VERSION;
}
template <typename Traits, typename T>
-Q_DECL_CONST_FUNCTION static inline T convertCase_helper(T uc) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION static inline T convertCase_helper(T uc) noexcept
{
const QUnicodeTables::Properties *prop = qGetProp(uc);
@@ -1491,7 +1491,7 @@ Q_DECL_CONST_FUNCTION static inline T convertCase_helper(T uc) Q_DECL_NOTHROW
by \a ucs4 if the character is uppercase or titlecase; otherwise returns
the character itself.
*/
-uint QChar::toLower(uint ucs4) Q_DECL_NOTHROW
+uint QChar::toLower(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return ucs4;
@@ -1511,7 +1511,7 @@ uint QChar::toLower(uint ucs4) Q_DECL_NOTHROW
by \a ucs4 if the character is lowercase or titlecase; otherwise returns
the character itself.
*/
-uint QChar::toUpper(uint ucs4) Q_DECL_NOTHROW
+uint QChar::toUpper(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return ucs4;
@@ -1531,7 +1531,7 @@ uint QChar::toUpper(uint ucs4) Q_DECL_NOTHROW
by \a ucs4 if the character is lowercase or uppercase; otherwise returns
the character itself.
*/
-uint QChar::toTitleCase(uint ucs4) Q_DECL_NOTHROW
+uint QChar::toTitleCase(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return ucs4;
@@ -1546,7 +1546,7 @@ static inline uint foldCase(const ushort *ch, const ushort *start)
return convertCase_helper<QUnicodeTables::CasefoldTraits>(ucs4);
}
-static inline uint foldCase(uint ch, uint &last) Q_DECL_NOTHROW
+static inline uint foldCase(uint ch, uint &last) noexcept
{
uint ucs4 = ch;
if (QChar::isLowSurrogate(ucs4) && QChar::isHighSurrogate(last))
@@ -1555,12 +1555,12 @@ static inline uint foldCase(uint ch, uint &last) Q_DECL_NOTHROW
return convertCase_helper<QUnicodeTables::CasefoldTraits>(ucs4);
}
-static inline ushort foldCase(ushort ch) Q_DECL_NOTHROW
+static inline ushort foldCase(ushort ch) noexcept
{
return convertCase_helper<QUnicodeTables::CasefoldTraits>(ch);
}
-static inline QChar foldCase(QChar ch) Q_DECL_NOTHROW
+static inline QChar foldCase(QChar ch) noexcept
{
return QChar(foldCase(ch.unicode()));
}
@@ -1577,7 +1577,7 @@ static inline QChar foldCase(QChar ch) Q_DECL_NOTHROW
Returns the case folded equivalent of the UCS-4-encoded character specified
by \a ucs4. For most Unicode characters this is the same as toLower().
*/
-uint QChar::toCaseFolded(uint ucs4) Q_DECL_NOTHROW
+uint QChar::toCaseFolded(uint ucs4) noexcept
{
if (ucs4 > LastValidCodePoint)
return ucs4;
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
index 8590b91ba3..73344ecf52 100644
--- a/src/corelib/tools/qchar.h
+++ b/src/corelib/tools/qchar.h
@@ -50,14 +50,27 @@ class QString;
struct QLatin1Char
{
public:
- Q_DECL_CONSTEXPR inline explicit QLatin1Char(char c) Q_DECL_NOTHROW : ch(c) {}
- Q_DECL_CONSTEXPR inline char toLatin1() const Q_DECL_NOTHROW { return ch; }
- Q_DECL_CONSTEXPR inline ushort unicode() const Q_DECL_NOTHROW { return ushort(uchar(ch)); }
+ Q_DECL_CONSTEXPR inline explicit QLatin1Char(char c) noexcept : ch(c) {}
+ Q_DECL_CONSTEXPR inline char toLatin1() const noexcept { return ch; }
+ Q_DECL_CONSTEXPR inline ushort unicode() const noexcept { return ushort(uchar(ch)); }
private:
char ch;
};
+Q_DECL_CONSTEXPR inline bool operator==(char lhs, QLatin1Char rhs) noexcept { return lhs == rhs.toLatin1(); }
+Q_DECL_CONSTEXPR inline bool operator!=(char lhs, QLatin1Char rhs) noexcept { return lhs != rhs.toLatin1(); }
+Q_DECL_CONSTEXPR inline bool operator<=(char lhs, QLatin1Char rhs) noexcept { return lhs <= rhs.toLatin1(); }
+Q_DECL_CONSTEXPR inline bool operator>=(char lhs, QLatin1Char rhs) noexcept { return lhs >= rhs.toLatin1(); }
+Q_DECL_CONSTEXPR inline bool operator< (char lhs, QLatin1Char rhs) noexcept { return lhs < rhs.toLatin1(); }
+Q_DECL_CONSTEXPR inline bool operator> (char lhs, QLatin1Char rhs) noexcept { return lhs > rhs.toLatin1(); }
+
+Q_DECL_CONSTEXPR inline bool operator==(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() == rhs; }
+Q_DECL_CONSTEXPR inline bool operator!=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() != rhs; }
+Q_DECL_CONSTEXPR inline bool operator<=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() <= rhs; }
+Q_DECL_CONSTEXPR inline bool operator>=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() >= rhs; }
+Q_DECL_CONSTEXPR inline bool operator< (QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() < rhs; }
+Q_DECL_CONSTEXPR inline bool operator> (QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() > rhs; }
class Q_CORE_EXPORT QChar {
public:
@@ -78,30 +91,30 @@ public:
LastValidCodePoint = 0x10ffff
};
- Q_DECL_CONSTEXPR QChar() Q_DECL_NOTHROW : ucs(0) {}
- Q_DECL_CONSTEXPR QChar(ushort rc) Q_DECL_NOTHROW : ucs(rc) {} // implicit
- Q_DECL_CONSTEXPR QChar(uchar c, uchar r) Q_DECL_NOTHROW : ucs(ushort((r << 8) | c)) {}
- Q_DECL_CONSTEXPR QChar(short rc) Q_DECL_NOTHROW : ucs(ushort(rc)) {} // implicit
- Q_DECL_CONSTEXPR QChar(uint rc) Q_DECL_NOTHROW : ucs(ushort(rc & 0xffff)) {}
- Q_DECL_CONSTEXPR QChar(int rc) Q_DECL_NOTHROW : ucs(ushort(rc & 0xffff)) {}
- Q_DECL_CONSTEXPR QChar(SpecialCharacter s) Q_DECL_NOTHROW : ucs(ushort(s)) {} // implicit
- Q_DECL_CONSTEXPR QChar(QLatin1Char ch) Q_DECL_NOTHROW : ucs(ch.unicode()) {} // implicit
+ Q_DECL_CONSTEXPR QChar() noexcept : ucs(0) {}
+ Q_DECL_CONSTEXPR QChar(ushort rc) noexcept : ucs(rc) {} // implicit
+ Q_DECL_CONSTEXPR QChar(uchar c, uchar r) noexcept : ucs(ushort((r << 8) | c)) {}
+ Q_DECL_CONSTEXPR QChar(short rc) noexcept : ucs(ushort(rc)) {} // implicit
+ Q_DECL_CONSTEXPR QChar(uint rc) noexcept : ucs(ushort(rc & 0xffff)) {}
+ Q_DECL_CONSTEXPR QChar(int rc) noexcept : ucs(ushort(rc & 0xffff)) {}
+ Q_DECL_CONSTEXPR QChar(SpecialCharacter s) noexcept : ucs(ushort(s)) {} // implicit
+ Q_DECL_CONSTEXPR QChar(QLatin1Char ch) noexcept : ucs(ch.unicode()) {} // implicit
#if defined(Q_COMPILER_UNICODE_STRINGS)
- Q_DECL_CONSTEXPR QChar(char16_t ch) Q_DECL_NOTHROW : ucs(ushort(ch)) {} // implicit
+ Q_DECL_CONSTEXPR QChar(char16_t ch) noexcept : ucs(ushort(ch)) {} // implicit
#endif
#if defined(Q_OS_WIN)
Q_STATIC_ASSERT(sizeof(wchar_t) == sizeof(ushort));
#endif
#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
# if !defined(_WCHAR_T_DEFINED) || defined(_NATIVE_WCHAR_T_DEFINED)
- Q_DECL_CONSTEXPR QChar(wchar_t ch) Q_DECL_NOTHROW : ucs(ushort(ch)) {} // implicit
+ Q_DECL_CONSTEXPR QChar(wchar_t ch) noexcept : ucs(ushort(ch)) {} // implicit
# endif
#endif
#ifndef QT_NO_CAST_FROM_ASCII
- QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(char c) Q_DECL_NOTHROW : ucs(uchar(c)) { }
+ QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(char c) noexcept : ucs(uchar(c)) { }
#ifndef QT_RESTRICTED_CAST_FROM_ASCII
- QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(uchar c) Q_DECL_NOTHROW : ucs(c) { }
+ QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(uchar c) noexcept : ucs(c) { }
#endif
#endif
// Unicode information
@@ -411,11 +424,11 @@ public:
};
// ****** WHEN ADDING FUNCTIONS, CONSIDER ADDING TO QCharRef TOO
- inline Category category() const Q_DECL_NOTHROW { return QChar::category(ucs); }
- inline Direction direction() const Q_DECL_NOTHROW { return QChar::direction(ucs); }
- inline JoiningType joiningType() const Q_DECL_NOTHROW { return QChar::joiningType(ucs); }
+ inline Category category() const noexcept { return QChar::category(ucs); }
+ inline Direction direction() const noexcept { return QChar::direction(ucs); }
+ inline JoiningType joiningType() const noexcept { return QChar::joiningType(ucs); }
#if QT_DEPRECATED_SINCE(5, 3)
- QT_DEPRECATED inline Joining joining() const Q_DECL_NOTHROW
+ QT_DEPRECATED inline Joining joining() const noexcept
{
switch (QChar::joiningType(ucs)) {
case QChar::Joining_Causing: return QChar::Center;
@@ -428,198 +441,198 @@ public:
}
}
#endif
- inline unsigned char combiningClass() const Q_DECL_NOTHROW { return QChar::combiningClass(ucs); }
+ inline unsigned char combiningClass() const noexcept { return QChar::combiningClass(ucs); }
- inline QChar mirroredChar() const Q_DECL_NOTHROW { return QChar::mirroredChar(ucs); }
- inline bool hasMirrored() const Q_DECL_NOTHROW { return QChar::hasMirrored(ucs); }
+ inline QChar mirroredChar() const noexcept { return QChar::mirroredChar(ucs); }
+ inline bool hasMirrored() const noexcept { return QChar::hasMirrored(ucs); }
QString decomposition() const;
- inline Decomposition decompositionTag() const Q_DECL_NOTHROW { return QChar::decompositionTag(ucs); }
+ inline Decomposition decompositionTag() const noexcept { return QChar::decompositionTag(ucs); }
- inline int digitValue() const Q_DECL_NOTHROW { return QChar::digitValue(ucs); }
- inline QChar toLower() const Q_DECL_NOTHROW { return QChar::toLower(ucs); }
- inline QChar toUpper() const Q_DECL_NOTHROW { return QChar::toUpper(ucs); }
- inline QChar toTitleCase() const Q_DECL_NOTHROW { return QChar::toTitleCase(ucs); }
- inline QChar toCaseFolded() const Q_DECL_NOTHROW { return QChar::toCaseFolded(ucs); }
+ inline int digitValue() const noexcept { return QChar::digitValue(ucs); }
+ inline QChar toLower() const noexcept { return QChar::toLower(ucs); }
+ inline QChar toUpper() const noexcept { return QChar::toUpper(ucs); }
+ inline QChar toTitleCase() const noexcept { return QChar::toTitleCase(ucs); }
+ inline QChar toCaseFolded() const noexcept { return QChar::toCaseFolded(ucs); }
- inline Script script() const Q_DECL_NOTHROW { return QChar::script(ucs); }
+ inline Script script() const noexcept { return QChar::script(ucs); }
- inline UnicodeVersion unicodeVersion() const Q_DECL_NOTHROW { return QChar::unicodeVersion(ucs); }
+ inline UnicodeVersion unicodeVersion() const noexcept { return QChar::unicodeVersion(ucs); }
#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED Q_DECL_CONSTEXPR inline char toAscii() const Q_DECL_NOTHROW { return toLatin1(); }
+ QT_DEPRECATED Q_DECL_CONSTEXPR inline char toAscii() const noexcept { return toLatin1(); }
#endif
- Q_DECL_CONSTEXPR inline char toLatin1() const Q_DECL_NOTHROW { return ucs > 0xff ? '\0' : char(ucs); }
- Q_DECL_CONSTEXPR inline ushort unicode() const Q_DECL_NOTHROW { return ucs; }
- Q_DECL_RELAXED_CONSTEXPR inline ushort &unicode() Q_DECL_NOTHROW { return ucs; }
+ Q_DECL_CONSTEXPR inline char toLatin1() const noexcept { return ucs > 0xff ? '\0' : char(ucs); }
+ Q_DECL_CONSTEXPR inline ushort unicode() const noexcept { return ucs; }
+ Q_DECL_RELAXED_CONSTEXPR inline ushort &unicode() noexcept { return ucs; }
#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED static Q_DECL_CONSTEXPR inline QChar fromAscii(char c) Q_DECL_NOTHROW
+ QT_DEPRECATED static Q_DECL_CONSTEXPR inline QChar fromAscii(char c) noexcept
{ return fromLatin1(c); }
#endif
- static Q_DECL_CONSTEXPR inline QChar fromLatin1(char c) Q_DECL_NOTHROW { return QChar(ushort(uchar(c))); }
-
- Q_DECL_CONSTEXPR inline bool isNull() const Q_DECL_NOTHROW { return ucs == 0; }
-
- inline bool isPrint() const Q_DECL_NOTHROW { return QChar::isPrint(ucs); }
- Q_DECL_CONSTEXPR inline bool isSpace() const Q_DECL_NOTHROW { return QChar::isSpace(ucs); }
- inline bool isMark() const Q_DECL_NOTHROW { return QChar::isMark(ucs); }
- inline bool isPunct() const Q_DECL_NOTHROW { return QChar::isPunct(ucs); }
- inline bool isSymbol() const Q_DECL_NOTHROW { return QChar::isSymbol(ucs); }
- Q_DECL_CONSTEXPR inline bool isLetter() const Q_DECL_NOTHROW { return QChar::isLetter(ucs); }
- Q_DECL_CONSTEXPR inline bool isNumber() const Q_DECL_NOTHROW { return QChar::isNumber(ucs); }
- Q_DECL_CONSTEXPR inline bool isLetterOrNumber() const Q_DECL_NOTHROW { return QChar::isLetterOrNumber(ucs); }
- Q_DECL_CONSTEXPR inline bool isDigit() const Q_DECL_NOTHROW { return QChar::isDigit(ucs); }
- Q_DECL_CONSTEXPR inline bool isLower() const Q_DECL_NOTHROW { return QChar::isLower(ucs); }
- Q_DECL_CONSTEXPR inline bool isUpper() const Q_DECL_NOTHROW { return QChar::isUpper(ucs); }
- Q_DECL_CONSTEXPR inline bool isTitleCase() const Q_DECL_NOTHROW { return QChar::isTitleCase(ucs); }
-
- Q_DECL_CONSTEXPR inline bool isNonCharacter() const Q_DECL_NOTHROW { return QChar::isNonCharacter(ucs); }
- Q_DECL_CONSTEXPR inline bool isHighSurrogate() const Q_DECL_NOTHROW { return QChar::isHighSurrogate(ucs); }
- Q_DECL_CONSTEXPR inline bool isLowSurrogate() const Q_DECL_NOTHROW { return QChar::isLowSurrogate(ucs); }
- Q_DECL_CONSTEXPR inline bool isSurrogate() const Q_DECL_NOTHROW { return QChar::isSurrogate(ucs); }
-
- Q_DECL_CONSTEXPR inline uchar cell() const Q_DECL_NOTHROW { return uchar(ucs & 0xff); }
- Q_DECL_CONSTEXPR inline uchar row() const Q_DECL_NOTHROW { return uchar((ucs>>8)&0xff); }
- Q_DECL_RELAXED_CONSTEXPR inline void setCell(uchar acell) Q_DECL_NOTHROW { ucs = ushort((ucs & 0xff00) + acell); }
- Q_DECL_RELAXED_CONSTEXPR inline void setRow(uchar arow) Q_DECL_NOTHROW { ucs = ushort((ushort(arow)<<8) + (ucs&0xff)); }
-
- static Q_DECL_CONSTEXPR inline bool isNonCharacter(uint ucs4) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR inline QChar fromLatin1(char c) noexcept { return QChar(ushort(uchar(c))); }
+
+ Q_DECL_CONSTEXPR inline bool isNull() const noexcept { return ucs == 0; }
+
+ inline bool isPrint() const noexcept { return QChar::isPrint(ucs); }
+ Q_DECL_CONSTEXPR inline bool isSpace() const noexcept { return QChar::isSpace(ucs); }
+ inline bool isMark() const noexcept { return QChar::isMark(ucs); }
+ inline bool isPunct() const noexcept { return QChar::isPunct(ucs); }
+ inline bool isSymbol() const noexcept { return QChar::isSymbol(ucs); }
+ Q_DECL_CONSTEXPR inline bool isLetter() const noexcept { return QChar::isLetter(ucs); }
+ Q_DECL_CONSTEXPR inline bool isNumber() const noexcept { return QChar::isNumber(ucs); }
+ Q_DECL_CONSTEXPR inline bool isLetterOrNumber() const noexcept { return QChar::isLetterOrNumber(ucs); }
+ Q_DECL_CONSTEXPR inline bool isDigit() const noexcept { return QChar::isDigit(ucs); }
+ Q_DECL_CONSTEXPR inline bool isLower() const noexcept { return QChar::isLower(ucs); }
+ Q_DECL_CONSTEXPR inline bool isUpper() const noexcept { return QChar::isUpper(ucs); }
+ Q_DECL_CONSTEXPR inline bool isTitleCase() const noexcept { return QChar::isTitleCase(ucs); }
+
+ Q_DECL_CONSTEXPR inline bool isNonCharacter() const noexcept { return QChar::isNonCharacter(ucs); }
+ Q_DECL_CONSTEXPR inline bool isHighSurrogate() const noexcept { return QChar::isHighSurrogate(ucs); }
+ Q_DECL_CONSTEXPR inline bool isLowSurrogate() const noexcept { return QChar::isLowSurrogate(ucs); }
+ Q_DECL_CONSTEXPR inline bool isSurrogate() const noexcept { return QChar::isSurrogate(ucs); }
+
+ Q_DECL_CONSTEXPR inline uchar cell() const noexcept { return uchar(ucs & 0xff); }
+ Q_DECL_CONSTEXPR inline uchar row() const noexcept { return uchar((ucs>>8)&0xff); }
+ Q_DECL_RELAXED_CONSTEXPR inline void setCell(uchar acell) noexcept { ucs = ushort((ucs & 0xff00) + acell); }
+ Q_DECL_RELAXED_CONSTEXPR inline void setRow(uchar arow) noexcept { ucs = ushort((ushort(arow)<<8) + (ucs&0xff)); }
+
+ static Q_DECL_CONSTEXPR inline bool isNonCharacter(uint ucs4) noexcept
{
return ucs4 >= 0xfdd0 && (ucs4 <= 0xfdef || (ucs4 & 0xfffe) == 0xfffe);
}
- static Q_DECL_CONSTEXPR inline bool isHighSurrogate(uint ucs4) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR inline bool isHighSurrogate(uint ucs4) noexcept
{
return ((ucs4 & 0xfffffc00) == 0xd800);
}
- static Q_DECL_CONSTEXPR inline bool isLowSurrogate(uint ucs4) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR inline bool isLowSurrogate(uint ucs4) noexcept
{
return ((ucs4 & 0xfffffc00) == 0xdc00);
}
- static Q_DECL_CONSTEXPR inline bool isSurrogate(uint ucs4) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR inline bool isSurrogate(uint ucs4) noexcept
{
return (ucs4 - 0xd800u < 2048u);
}
- static Q_DECL_CONSTEXPR inline bool requiresSurrogates(uint ucs4) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR inline bool requiresSurrogates(uint ucs4) noexcept
{
return (ucs4 >= 0x10000);
}
- static Q_DECL_CONSTEXPR inline uint surrogateToUcs4(ushort high, ushort low) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR inline uint surrogateToUcs4(ushort high, ushort low) noexcept
{
return (uint(high)<<10) + low - 0x35fdc00;
}
- static Q_DECL_CONSTEXPR inline uint surrogateToUcs4(QChar high, QChar low) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR inline uint surrogateToUcs4(QChar high, QChar low) noexcept
{
return surrogateToUcs4(high.ucs, low.ucs);
}
- static Q_DECL_CONSTEXPR inline ushort highSurrogate(uint ucs4) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR inline ushort highSurrogate(uint ucs4) noexcept
{
return ushort((ucs4>>10) + 0xd7c0);
}
- static Q_DECL_CONSTEXPR inline ushort lowSurrogate(uint ucs4) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR inline ushort lowSurrogate(uint ucs4) noexcept
{
return ushort(ucs4%0x400 + 0xdc00);
}
- static Category QT_FASTCALL category(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static Direction QT_FASTCALL direction(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static JoiningType QT_FASTCALL joiningType(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ static Category QT_FASTCALL category(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static Direction QT_FASTCALL direction(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static JoiningType QT_FASTCALL joiningType(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
#if QT_DEPRECATED_SINCE(5, 3)
- QT_DEPRECATED static Joining QT_FASTCALL joining(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ QT_DEPRECATED static Joining QT_FASTCALL joining(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
#endif
- static unsigned char QT_FASTCALL combiningClass(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ static unsigned char QT_FASTCALL combiningClass(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static uint QT_FASTCALL mirroredChar(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL hasMirrored(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL mirroredChar(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL hasMirrored(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
static QString QT_FASTCALL decomposition(uint ucs4);
- static Decomposition QT_FASTCALL decompositionTag(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ static Decomposition QT_FASTCALL decompositionTag(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static int QT_FASTCALL digitValue(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static uint QT_FASTCALL toLower(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static uint QT_FASTCALL toUpper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static uint QT_FASTCALL toTitleCase(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static uint QT_FASTCALL toCaseFolded(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ static int QT_FASTCALL digitValue(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toLower(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toUpper(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toTitleCase(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static uint QT_FASTCALL toCaseFolded(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static Script QT_FASTCALL script(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ static Script QT_FASTCALL script(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
- static UnicodeVersion QT_FASTCALL currentUnicodeVersion() Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ static UnicodeVersion QT_FASTCALL currentUnicodeVersion() noexcept Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isPrint(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static Q_DECL_CONSTEXPR inline bool isSpace(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION
+ static bool QT_FASTCALL isPrint(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static Q_DECL_CONSTEXPR inline bool isSpace(uint ucs4) noexcept Q_DECL_CONST_FUNCTION
{
// note that [0x09..0x0d] + 0x85 are exceptional Cc-s and must be handled explicitly
return ucs4 == 0x20 || (ucs4 <= 0x0d && ucs4 >= 0x09)
|| (ucs4 > 127 && (ucs4 == 0x85 || ucs4 == 0xa0 || QChar::isSpace_helper(ucs4)));
}
- static bool QT_FASTCALL isMark(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isPunct(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isSymbol(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static Q_DECL_CONSTEXPR inline bool isLetter(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION
+ static bool QT_FASTCALL isMark(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isPunct(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isSymbol(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static Q_DECL_CONSTEXPR inline bool isLetter(uint ucs4) noexcept Q_DECL_CONST_FUNCTION
{
return (ucs4 >= 'A' && ucs4 <= 'z' && (ucs4 >= 'a' || ucs4 <= 'Z'))
|| (ucs4 > 127 && QChar::isLetter_helper(ucs4));
}
- static Q_DECL_CONSTEXPR inline bool isNumber(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION
+ static Q_DECL_CONSTEXPR inline bool isNumber(uint ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return (ucs4 <= '9' && ucs4 >= '0') || (ucs4 > 127 && QChar::isNumber_helper(ucs4)); }
- static Q_DECL_CONSTEXPR inline bool isLetterOrNumber(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION
+ static Q_DECL_CONSTEXPR inline bool isLetterOrNumber(uint ucs4) noexcept Q_DECL_CONST_FUNCTION
{
return (ucs4 >= 'A' && ucs4 <= 'z' && (ucs4 >= 'a' || ucs4 <= 'Z'))
|| (ucs4 >= '0' && ucs4 <= '9')
|| (ucs4 > 127 && QChar::isLetterOrNumber_helper(ucs4));
}
- static Q_DECL_CONSTEXPR inline bool isDigit(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION
+ static Q_DECL_CONSTEXPR inline bool isDigit(uint ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return (ucs4 <= '9' && ucs4 >= '0') || (ucs4 > 127 && QChar::category(ucs4) == Number_DecimalDigit); }
- static Q_DECL_CONSTEXPR inline bool isLower(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION
+ static Q_DECL_CONSTEXPR inline bool isLower(uint ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return (ucs4 <= 'z' && ucs4 >= 'a') || (ucs4 > 127 && QChar::category(ucs4) == Letter_Lowercase); }
- static Q_DECL_CONSTEXPR inline bool isUpper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION
+ static Q_DECL_CONSTEXPR inline bool isUpper(uint ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return (ucs4 <= 'Z' && ucs4 >= 'A') || (ucs4 > 127 && QChar::category(ucs4) == Letter_Uppercase); }
- static Q_DECL_CONSTEXPR inline bool isTitleCase(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION
+ static Q_DECL_CONSTEXPR inline bool isTitleCase(uint ucs4) noexcept Q_DECL_CONST_FUNCTION
{ return ucs4 > 127 && QChar::category(ucs4) == Letter_Titlecase; }
private:
- static bool QT_FASTCALL isSpace_helper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isLetter_helper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isNumber_helper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
- static bool QT_FASTCALL isLetterOrNumber_helper(uint ucs4) Q_DECL_NOTHROW Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isSpace_helper(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isLetter_helper(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isNumber_helper(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
+ static bool QT_FASTCALL isLetterOrNumber_helper(uint ucs4) noexcept Q_DECL_CONST_FUNCTION;
#ifdef QT_NO_CAST_FROM_ASCII
- QChar(char c) Q_DECL_NOTHROW;
- QChar(uchar c) Q_DECL_NOTHROW;
+ QChar(char c) noexcept;
+ QChar(uchar c) noexcept;
#endif
- friend Q_DECL_CONSTEXPR bool operator==(QChar, QChar) Q_DECL_NOTHROW;
- friend Q_DECL_CONSTEXPR bool operator< (QChar, QChar) Q_DECL_NOTHROW;
+ friend Q_DECL_CONSTEXPR bool operator==(QChar, QChar) noexcept;
+ friend Q_DECL_CONSTEXPR bool operator< (QChar, QChar) noexcept;
ushort ucs;
};
Q_DECLARE_TYPEINFO(QChar, Q_MOVABLE_TYPE);
-Q_DECL_CONSTEXPR inline bool operator==(QChar c1, QChar c2) Q_DECL_NOTHROW { return c1.ucs == c2.ucs; }
-Q_DECL_CONSTEXPR inline bool operator< (QChar c1, QChar c2) Q_DECL_NOTHROW { return c1.ucs < c2.ucs; }
+Q_DECL_CONSTEXPR inline bool operator==(QChar c1, QChar c2) noexcept { return c1.ucs == c2.ucs; }
+Q_DECL_CONSTEXPR inline bool operator< (QChar c1, QChar c2) noexcept { return c1.ucs < c2.ucs; }
-Q_DECL_CONSTEXPR inline bool operator!=(QChar c1, QChar c2) Q_DECL_NOTHROW { return !operator==(c1, c2); }
-Q_DECL_CONSTEXPR inline bool operator>=(QChar c1, QChar c2) Q_DECL_NOTHROW { return !operator< (c1, c2); }
-Q_DECL_CONSTEXPR inline bool operator> (QChar c1, QChar c2) Q_DECL_NOTHROW { return operator< (c2, c1); }
-Q_DECL_CONSTEXPR inline bool operator<=(QChar c1, QChar c2) Q_DECL_NOTHROW { return !operator< (c2, c1); }
+Q_DECL_CONSTEXPR inline bool operator!=(QChar c1, QChar c2) noexcept { return !operator==(c1, c2); }
+Q_DECL_CONSTEXPR inline bool operator>=(QChar c1, QChar c2) noexcept { return !operator< (c1, c2); }
+Q_DECL_CONSTEXPR inline bool operator> (QChar c1, QChar c2) noexcept { return operator< (c2, c1); }
+Q_DECL_CONSTEXPR inline bool operator<=(QChar c1, QChar c2) noexcept { return !operator< (c2, c1); }
-Q_DECL_CONSTEXPR inline bool operator==(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return lhs.isNull(); }
-Q_DECL_CONSTEXPR inline bool operator< (QChar, std::nullptr_t) Q_DECL_NOTHROW { return false; }
-Q_DECL_CONSTEXPR inline bool operator==(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return rhs.isNull(); }
-Q_DECL_CONSTEXPR inline bool operator< (std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !rhs.isNull(); }
+Q_DECL_CONSTEXPR inline bool operator==(QChar lhs, std::nullptr_t) noexcept { return lhs.isNull(); }
+Q_DECL_CONSTEXPR inline bool operator< (QChar, std::nullptr_t) noexcept { return false; }
+Q_DECL_CONSTEXPR inline bool operator==(std::nullptr_t, QChar rhs) noexcept { return rhs.isNull(); }
+Q_DECL_CONSTEXPR inline bool operator< (std::nullptr_t, QChar rhs) noexcept { return !rhs.isNull(); }
-Q_DECL_CONSTEXPR inline bool operator!=(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return !operator==(lhs, nullptr); }
-Q_DECL_CONSTEXPR inline bool operator>=(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return !operator< (lhs, nullptr); }
-Q_DECL_CONSTEXPR inline bool operator> (QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return operator< (nullptr, lhs); }
-Q_DECL_CONSTEXPR inline bool operator<=(QChar lhs, std::nullptr_t) Q_DECL_NOTHROW { return !operator< (nullptr, lhs); }
+Q_DECL_CONSTEXPR inline bool operator!=(QChar lhs, std::nullptr_t) noexcept { return !operator==(lhs, nullptr); }
+Q_DECL_CONSTEXPR inline bool operator>=(QChar lhs, std::nullptr_t) noexcept { return !operator< (lhs, nullptr); }
+Q_DECL_CONSTEXPR inline bool operator> (QChar lhs, std::nullptr_t) noexcept { return operator< (nullptr, lhs); }
+Q_DECL_CONSTEXPR inline bool operator<=(QChar lhs, std::nullptr_t) noexcept { return !operator< (nullptr, lhs); }
-Q_DECL_CONSTEXPR inline bool operator!=(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !operator==(nullptr, rhs); }
-Q_DECL_CONSTEXPR inline bool operator>=(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !operator< (nullptr, rhs); }
-Q_DECL_CONSTEXPR inline bool operator> (std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return operator< (rhs, nullptr); }
-Q_DECL_CONSTEXPR inline bool operator<=(std::nullptr_t, QChar rhs) Q_DECL_NOTHROW { return !operator< (rhs, nullptr); }
+Q_DECL_CONSTEXPR inline bool operator!=(std::nullptr_t, QChar rhs) noexcept { return !operator==(nullptr, rhs); }
+Q_DECL_CONSTEXPR inline bool operator>=(std::nullptr_t, QChar rhs) noexcept { return !operator< (nullptr, rhs); }
+Q_DECL_CONSTEXPR inline bool operator> (std::nullptr_t, QChar rhs) noexcept { return operator< (rhs, nullptr); }
+Q_DECL_CONSTEXPR inline bool operator<=(std::nullptr_t, QChar rhs) noexcept { return !operator< (rhs, nullptr); }
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QChar);
diff --git a/src/corelib/tools/qcollator.cpp b/src/corelib/tools/qcollator.cpp
index 76dcf35833..958216bde8 100644
--- a/src/corelib/tools/qcollator.cpp
+++ b/src/corelib/tools/qcollator.cpp
@@ -46,7 +46,6 @@
QT_BEGIN_NAMESPACE
-
/*!
\class QCollator
\inmodule QtCore
@@ -59,20 +58,32 @@ QT_BEGIN_NAMESPACE
\ingroup string-processing
\ingroup shared
- QCollator is initialized with a QLocale and an optional collation strategy. It tries to
- initialize the collator with the specified values. The collator can then be used to compare
- and sort strings in a locale dependent fashion.
+ QCollator is initialized with a QLocale and an optional collation strategy.
+ It tries to initialize the collator with the specified values. The collator
+ can then be used to compare and sort strings in a locale dependent fashion.
- A QCollator object can be used together with template based sorting algorithms such as std::sort
- to sort a list of QStrings.
+ A QCollator object can be used together with template based sorting
+ algorithms such as std::sort to sort a list of QStrings.
- In addition to the locale and collation strategy, several optional flags can be set that influence
- the result of the collation.
+ In addition to the locale and collation strategy, several optional flags can
+ be set that influence the result of the collation.
*/
/*!
- Constructs a QCollator from \a locale. If \a locale is not specified
- the system's default locale is used.
+ \since 5.13
+
+ Constructs a QCollator using the system's default collation locale.
+
+ \sa setLocale(), QLocale::collation()
+*/
+QCollator::QCollator()
+ : d(new QCollatorPrivate(QLocale::system().collation()))
+{
+ d->init();
+}
+
+/*!
+ Constructs a QCollator from \a locale.
\sa setLocale()
*/
@@ -128,9 +139,9 @@ QCollator &QCollator::operator=(const QCollator &other)
Move constructor. Moves from \a other into this collator.
- Note that a moved-from QCollator can only be destroyed or assigned
- to. The effect of calling other functions than the destructor or
- one of the assignment operators is undefined.
+ Note that a moved-from QCollator can only be destroyed or assigned to.
+ The effect of calling other functions than the destructor or one of the
+ assignment operators is undefined.
*/
/*!
@@ -138,9 +149,9 @@ QCollator &QCollator::operator=(const QCollator &other)
Move-assigns from \a other to this collator.
- Note that a moved-from QCollator can only be destroyed or assigned
- to. The effect of calling other functions than the destructor or
- one of the assignment operators is undefined.
+ Note that a moved-from QCollator can only be destroyed or assigned to.
+ The effect of calling other functions than the destructor or one of the
+ assignment operators is undefined.
*/
/*!
@@ -155,7 +166,7 @@ QCollator &QCollator::operator=(const QCollator &other)
*/
void QCollator::detach()
{
- if (d->ref.load() != 1) {
+ if (d->ref.loadRelaxed() != 1) {
QCollatorPrivate *x = new QCollatorPrivate(d->locale);
if (!d->ref.deref())
delete d;
@@ -218,7 +229,8 @@ Qt::CaseSensitivity QCollator::caseSensitivity() const
Enables numeric sorting mode when \a on is set to true.
- This will enable proper sorting of numeric digits, so that e.g. 100 sorts after 99.
+ This will enable proper sorting of numeric digits, so that e.g. 100 sorts
+ after 99.
By default this mode is off.
@@ -248,11 +260,13 @@ bool QCollator::numericMode() const
/*!
\fn void QCollator::setIgnorePunctuation(bool on)
- If \a on is set to true, punctuation characters and symbols are ignored when determining sort order.
+ If \a on is set to true, punctuation characters and symbols are ignored when
+ determining sort order.
The default is locale dependent.
- \note This method is not currently supported if Qt is configured to not use ICU on Linux.
+ \note This method is not currently supported if Qt is configured to not use
+ ICU on Linux.
\sa ignorePunctuation()
*/
@@ -268,7 +282,8 @@ void QCollator::setIgnorePunctuation(bool on)
/*!
\fn bool QCollator::ignorePunctuation() const
- Returns \c true if punctuation characters and symbols are ignored when determining sort order.
+ Returns \c true if punctuation characters and symbols are ignored when
+ determining sort order.
\sa setIgnorePunctuation()
*/
@@ -278,35 +293,66 @@ bool QCollator::ignorePunctuation() const
}
/*!
- \fn int QCollator::compare(const QString &s1, const QString &s2) const
+ \since 5.13
+ \fn bool QCollator::operator()(QStringView s1, QStringView s2) const
+ \internal
+*/
- Compares \a s1 with \a s2. Returns an integer less than, equal to, or greater than zero
- depending on whether \a s1 is smaller, equal or larger than \a s2.
- */
+/*!
+ \since 5.13
+ \fn int QCollator::compare(QStringView s1, QStringView s2) const
+
+ Compares \a s1 with \a s2.
+ Returns an integer less than, equal to, or greater than zero depending on
+ whether \a s1 sorts before, with or after \a s2.
+*/
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn bool QCollator::operator()(const QString &s1, const QString &s2) const
\internal
*/
/*!
- \fn int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const
\overload
- Compares \a s1 with \a s2. Returns an integer less than, equal to, or greater than zero
- depending on whether \a s1 is smaller, equal or larger than \a s2.
+ Compares \a s1 with \a s2.
+
+ Returns an integer less than, equal to, or greater than zero depending on
+ whether \a s1 sorts before, with or after \a s2.
+*/
+int QCollator::compare(const QString &s1, const QString &s2) const
+{
+ return compare(QStringView(s1), QStringView(s2));
+}
+
+/*!
+ \overload
+
+ Compares \a s1 with \a s2.
+
+ Returns an integer less than, equal to, or greater than zero depending on
+ whether \a s1 sorts before, with or after \a s2.
*/
+int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const
+{
+ return compare(QStringView(s1), QStringView(s2));
+}
/*!
- \fn int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
\overload
- Compares \a s1 with \a s2. \a len1 and \a len2 specify the length of the
- QChar arrays pointer to by \a s1 and \a s2.
+ Compares \a s1 with \a s2. \a len1 and \a len2 specify the lengths of the
+ QChar arrays pointed to by \a s1 and \a s2.
- Returns an integer less than, equal to, or greater than zero
- depending on whether \a s1 is smaller, equal or larger than \a s2.
+ Returns an integer less than, equal to, or greater than zero depending on
+ whether \a s1 sorts before, with or after \a s2.
*/
+int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
+{
+ return compare(QStringView(s1, len1), QStringView(s2, len2));
+}
+#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\fn QCollatorSortKey QCollator::sortKey(const QString &string) const
@@ -314,9 +360,9 @@ bool QCollator::ignorePunctuation() const
Returns a sortKey for \a string.
Creating the sort key is usually somewhat slower, than using the compare()
- methods directly. But if the string is compared repeatedly (e.g. when sorting
- a whole list of strings), it's usually faster to create the sort keys for each
- string and then sort using the keys.
+ methods directly. But if the string is compared repeatedly (e.g. when
+ sorting a whole list of strings), it's usually faster to create the sort
+ keys for each string and then sort using the keys.
\note Not supported with the C (a.k.a. POSIX) locale on Darwin.
*/
@@ -328,8 +374,8 @@ bool QCollator::ignorePunctuation() const
\since 5.2
- The QCollatorSortKey class is always created by QCollator::sortKey()
- and is used for fast strings collation, for example when collating many strings.
+ The QCollatorSortKey class is always created by QCollator::sortKey() and is
+ used for fast strings collation, for example when collating many strings.
\reentrant
\ingroup i18n
@@ -398,9 +444,11 @@ QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other)
/*!
\fn int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const
- Compares the key to \a otherKey. Returns a negative value if the key
- is less than \a otherKey, 0 if the key is equal to \a otherKey or a
- positive value if the key is greater than \a otherKey.
+ Compares this key to \a otherKey.
+
+ Returns a negative value if the key is less than \a otherKey, 0 if the key
+ is equal to \a otherKey or a positive value if the key is greater than \a
+ otherKey.
\sa operator<()
*/
diff --git a/src/corelib/tools/qcollator.h b/src/corelib/tools/qcollator.h
index 6fa199cb0f..6bb5038371 100644
--- a/src/corelib/tools/qcollator.h
+++ b/src/corelib/tools/qcollator.h
@@ -57,11 +57,9 @@ public:
QCollatorSortKey(const QCollatorSortKey &other);
~QCollatorSortKey();
QCollatorSortKey &operator=(const QCollatorSortKey &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QCollatorSortKey &operator=(QCollatorSortKey &&other) Q_DECL_NOTHROW
+ inline QCollatorSortKey &operator=(QCollatorSortKey &&other) noexcept
{ swap(other); return *this; }
-#endif
- void swap(QCollatorSortKey &other) Q_DECL_NOTHROW
+ void swap(QCollatorSortKey &other) noexcept
{ d.swap(other.d); }
int compare(const QCollatorSortKey &key) const;
@@ -83,18 +81,17 @@ inline bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
class Q_CORE_EXPORT QCollator
{
public:
- explicit QCollator(const QLocale &locale = QLocale());
+ QCollator();
+ explicit QCollator(const QLocale &locale);
QCollator(const QCollator &);
~QCollator();
QCollator &operator=(const QCollator &);
-#ifdef Q_COMPILER_RVALUE_REFS
- QCollator(QCollator &&other) Q_DECL_NOTHROW
+ QCollator(QCollator &&other) noexcept
: d(other.d) { other.d = nullptr; }
- QCollator &operator=(QCollator &&other) Q_DECL_NOTHROW
+ QCollator &operator=(QCollator &&other) noexcept
{ swap(other); return *this; }
-#endif
- void swap(QCollator &other) Q_DECL_NOTHROW
+ void swap(QCollator &other) noexcept
{ qSwap(d, other.d); }
void setLocale(const QLocale &locale);
@@ -109,12 +106,18 @@ public:
void setIgnorePunctuation(bool on);
bool ignorePunctuation() const;
+#if QT_STRINGVIEW_LEVEL < 2
int compare(const QString &s1, const QString &s2) const;
int compare(const QStringRef &s1, const QStringRef &s2) const;
int compare(const QChar *s1, int len1, const QChar *s2, int len2) const;
bool operator()(const QString &s1, const QString &s2) const
{ return compare(s1, s2) < 0; }
+#endif
+ int compare(QStringView s1, QStringView s2) const;
+
+ bool operator()(QStringView s1, QStringView s2) const
+ { return compare(s1, s2) < 0; }
QCollatorSortKey sortKey(const QString &string) const;
diff --git a/src/corelib/tools/qcollator_icu.cpp b/src/corelib/tools/qcollator_icu.cpp
index ab45b9a1a1..8acda45070 100644
--- a/src/corelib/tools/qcollator_icu.cpp
+++ b/src/corelib/tools/qcollator_icu.cpp
@@ -78,7 +78,8 @@ void QCollatorPrivate::init()
// and does case sensitive comparison.
// UCOL_QUATERNARY is used as default in a few languages such as Japanese to take care of some
// additional differences in those languages.
- UColAttributeValue val = (caseSensitivity == Qt::CaseSensitive) ? UCOL_DEFAULT_STRENGTH : UCOL_SECONDARY;
+ UColAttributeValue val = (caseSensitivity == Qt::CaseSensitive)
+ ? UCOL_DEFAULT_STRENGTH : UCOL_SECONDARY;
status = U_ZERO_ERROR;
ucol_setAttribute(collator, UCOL_STRENGTH, val, &status);
@@ -91,7 +92,8 @@ void QCollatorPrivate::init()
qWarning("ucol_setAttribute: numeric collation failed: %d", status);
status = U_ZERO_ERROR;
- ucol_setAttribute(collator, UCOL_ALTERNATE_HANDLING, ignorePunctuation ? UCOL_SHIFTED : UCOL_NON_IGNORABLE, &status);
+ ucol_setAttribute(collator, UCOL_ALTERNATE_HANDLING,
+ ignorePunctuation ? UCOL_SHIFTED : UCOL_NON_IGNORABLE, &status);
if (U_FAILURE(status))
qWarning("ucol_setAttribute: Alternate handling failed: %d", status);
@@ -105,37 +107,20 @@ void QCollatorPrivate::cleanup()
collator = nullptr;
}
-int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
+int QCollator::compare(QStringView s1, QStringView s2) const
{
if (d->dirty)
d->init();
- if (d->collator)
- return ucol_strcoll(d->collator, (const UChar *)s1, len1, (const UChar *)s2, len2);
-
- return QString::compare_helper(s1, len1, s2, len2, d->caseSensitivity);
-}
-
-int QCollator::compare(const QString &s1, const QString &s2) const
-{
- if (d->dirty)
- d->init();
-
- if (d->collator)
- return compare(s1.constData(), s1.size(), s2.constData(), s2.size());
-
- return QString::compare(s1, s2, d->caseSensitivity);
-}
-
-int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const
-{
- if (d->dirty)
- d->init();
-
- if (d->collator)
- return compare(s1.constData(), s1.size(), s2.constData(), s2.size());
+ if (d->collator) {
+ return ucol_strcoll(d->collator,
+ reinterpret_cast<const UChar *>(s1.data()), s1.size(),
+ reinterpret_cast<const UChar *>(s2.data()), s2.size());
+ }
- return QStringRef::compare(s1, s2, d->caseSensitivity);
+ return QString::compare_helper(s1.data(), s1.size(),
+ s2.data(), s2.size(),
+ d->caseSensitivity);
}
QCollatorSortKey QCollator::sortKey(const QString &string) const
diff --git a/src/corelib/tools/qcollator_macx.cpp b/src/corelib/tools/qcollator_macx.cpp
index 42e67e0c12..071d7c048f 100644
--- a/src/corelib/tools/qcollator_macx.cpp
+++ b/src/corelib/tools/qcollator_macx.cpp
@@ -65,12 +65,12 @@ void QCollatorPrivate::init()
return;
LocaleRef localeRef;
- int rc = LocaleRefFromLocaleString(QLocalePrivate::get(locale)->bcp47Name().constData(), &localeRef);
- if (rc != 0)
- qWarning("couldn't initialize the locale");
+ OSStatus status =
+ LocaleRefFromLocaleString(QLocalePrivate::get(locale)->bcp47Name().constData(), &localeRef);
+ if (status != 0)
+ qWarning("Couldn't initialize the locale (%d)", int(status));
UInt32 options = 0;
-
if (caseSensitivity == Qt::CaseInsensitive)
options |= kUCCollateCaseInsensitiveMask;
if (numericMode)
@@ -78,14 +78,9 @@ void QCollatorPrivate::init()
if (!ignorePunctuation)
options |= kUCCollatePunctuationSignificantMask;
- OSStatus status = UCCreateCollator(
- localeRef,
- 0,
- options,
- &collator
- );
+ status = UCCreateCollator(localeRef, 0, options, &collator);
if (status != 0)
- qWarning("Couldn't initialize the collator");
+ qWarning("Couldn't initialize the collator (%d)", int(status));
dirty = false;
}
@@ -97,18 +92,18 @@ void QCollatorPrivate::cleanup()
collator = 0;
}
-int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
+int QCollator::compare(QStringView s1, QStringView s2) const
{
if (d->dirty)
d->init();
if (!d->collator)
- return QStringView(s1, len1).compare(QStringView(s2, len2), caseSensitivity());
+ return s1.compare(s2, caseSensitivity());
SInt32 result;
Boolean equivalent;
UCCompareText(d->collator,
- reinterpret_cast<const UniChar *>(s1), len1,
- reinterpret_cast<const UniChar *>(s2), len2,
+ reinterpret_cast<const UniChar *>(s1.data()), s1.size(),
+ reinterpret_cast<const UniChar *>(s2.data()), s2.size(),
&equivalent,
&result);
if (equivalent)
@@ -116,16 +111,6 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con
return result < 0 ? -1 : 1;
}
-int QCollator::compare(const QString &str1, const QString &str2) const
-{
- return compare(str1.constData(), str1.size(), str2.constData(), str2.size());
-}
-
-int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const
-{
- return compare(s1.constData(), s1.size(), s2.constData(), s2.size());
-}
-
QCollatorSortKey QCollator::sortKey(const QString &string) const
{
if (d->dirty)
@@ -139,13 +124,14 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const
//Documentation recommends having it 5 times as big as the input
QVector<UCCollationValue> ret(string.size() * 5);
ItemCount actualSize;
- int status = UCGetCollationKey(d->collator, reinterpret_cast<const UniChar *>(string.constData()), string.count(),
- ret.size(), &actualSize, ret.data());
+ int status = UCGetCollationKey(d->collator,
+ reinterpret_cast<const UniChar *>(string.constData()),
+ string.count(), ret.size(), &actualSize, ret.data());
- ret.resize(actualSize+1);
+ ret.resize(actualSize + 1);
if (status == kUCOutputBufferTooSmall) {
- UCGetCollationKey(d->collator, reinterpret_cast<const UniChar *>(string.constData()), string.count(),
- ret.size(), &actualSize, ret.data());
+ UCGetCollationKey(d->collator, reinterpret_cast<const UniChar *>(string.constData()),
+ string.count(), ret.size(), &actualSize, ret.data());
}
ret[actualSize] = 0;
return QCollatorSortKey(new QCollatorSortKeyPrivate(std::move(ret)));
diff --git a/src/corelib/tools/qcollator_p.h b/src/corelib/tools/qcollator_p.h
index 361c3fb987..fc2d434a8d 100644
--- a/src/corelib/tools/qcollator_p.h
+++ b/src/corelib/tools/qcollator_p.h
@@ -122,7 +122,7 @@ public:
void cleanup();
private:
- Q_DISABLE_COPY(QCollatorPrivate)
+ Q_DISABLE_COPY_MOVE(QCollatorPrivate)
};
class QCollatorSortKeyPrivate : public QSharedData
@@ -139,7 +139,7 @@ public:
CollatorKeyType m_key;
private:
- Q_DISABLE_COPY(QCollatorSortKeyPrivate)
+ Q_DISABLE_COPY_MOVE(QCollatorSortKeyPrivate)
};
diff --git a/src/corelib/tools/qcollator_posix.cpp b/src/corelib/tools/qcollator_posix.cpp
index 81f97a02e1..9cbc539ebe 100644
--- a/src/corelib/tools/qcollator_posix.cpp
+++ b/src/corelib/tools/qcollator_posix.cpp
@@ -65,7 +65,7 @@ void QCollatorPrivate::cleanup()
{
}
-static void stringToWCharArray(QVarLengthArray<wchar_t> &ret, const QString &string)
+static void stringToWCharArray(QVarLengthArray<wchar_t> &ret, QStringView string)
{
ret.resize(string.length());
int len = string.toWCharArray(ret.data());
@@ -73,12 +73,7 @@ static void stringToWCharArray(QVarLengthArray<wchar_t> &ret, const QString &str
ret[len] = 0;
}
-int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
-{
- return compare(QString::fromRawData(s1, len1), QString::fromRawData(s2, len2));
-}
-
-int QCollator::compare(const QString &s1, const QString &s2) const
+int QCollator::compare(QStringView s1, QStringView s2) const
{
if (d->isC())
return s1.compare(s2, caseSensitivity());
@@ -91,11 +86,6 @@ int QCollator::compare(const QString &s1, const QString &s2) const
return std::wcscoll(array1.constData(), array2.constData());
}
-int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const
-{
- return compare(s1.toString(), s2.toString());
-}
-
QCollatorSortKey QCollator::sortKey(const QString &string) const
{
if (d->dirty)
diff --git a/src/corelib/tools/qcollator_win.cpp b/src/corelib/tools/qcollator_win.cpp
index 10cfdaa264..9d81de882f 100644
--- a/src/corelib/tools/qcollator_win.cpp
+++ b/src/corelib/tools/qcollator_win.cpp
@@ -87,30 +87,30 @@ void QCollatorPrivate::cleanup()
{
}
-
-int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
+int QCollator::compare(QStringView s1, QStringView s2) const
{
if (d->isC())
- return QString::compare_helper(s1, len1, s2, len2, d->caseSensitivity);
+ return s1.compare(s2, d->caseSensitivity);
if (d->dirty)
d->init();
//* from Windows documentation *
- // Returns one of the following values if successful. To maintain the C runtime convention of
- // comparing strings, the value 2 can be subtracted from a nonzero return value. Then, the
- // meaning of <0, ==0, and >0 is consistent with the C runtime.
+ // Returns one of the following values if successful. To maintain the C
+ // runtime convention of comparing strings, the value 2 can be subtracted
+ // from a nonzero return value. Then, the meaning of <0, ==0, and >0 is
+ // consistent with the C runtime.
// [...] The function returns 0 if it does not succeed.
// https://docs.microsoft.com/en-us/windows/desktop/api/stringapiset/nf-stringapiset-comparestringex#return-value
#ifndef USE_COMPARESTRINGEX
const int ret = CompareString(d->localeID, d->collator,
- reinterpret_cast<const wchar_t*>(s1), len1,
- reinterpret_cast<const wchar_t*>(s2), len2);
+ reinterpret_cast<const wchar_t *>(s1.data()), s1.size(),
+ reinterpret_cast<const wchar_t *>(s2.data()), s2.size());
#else
const int ret = CompareStringEx(LPCWSTR(d->localeName.utf16()), d->collator,
- reinterpret_cast<LPCWSTR>(s1), len1,
- reinterpret_cast<LPCWSTR>(s2), len2,
+ reinterpret_cast<LPCWSTR>(s1.data()), s1.size(),
+ reinterpret_cast<LPCWSTR>(s2.data()), s2.size(),
nullptr, nullptr, 0);
#endif
if (Q_LIKELY(ret))
@@ -132,16 +132,6 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con
return 0;
}
-int QCollator::compare(const QString &str1, const QString &str2) const
-{
- return compare(str1.constData(), str1.size(), str2.constData(), str2.size());
-}
-
-int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const
-{
- return compare(s1.constData(), s1.size(), s2.constData(), s2.size());
-}
-
QCollatorSortKey QCollator::sortKey(const QString &string) const
{
if (d->dirty)
@@ -170,7 +160,9 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const
NULL, NULL, 0);
#endif
if (finalSize == 0) {
- qWarning() << "there were problems when generating the ::sortKey by LCMapStringW with error:" << GetLastError();
+ qWarning()
+ << "there were problems when generating the ::sortKey by LCMapStringW with error:"
+ << GetLastError();
}
return QCollatorSortKey(new QCollatorSortKeyPrivate(std::move(ret)));
}
diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp
index c2b86014ba..aff684fad2 100644
--- a/src/corelib/tools/qcommandlineoption.cpp
+++ b/src/corelib/tools/qcommandlineoption.cpp
@@ -254,7 +254,7 @@ namespace {
typedef QString argument_type;
Q_NEVER_INLINE
- result_type operator()(const QString &name) const Q_DECL_NOEXCEPT
+ result_type operator()(const QString &name) const noexcept
{
if (Q_UNLIKELY(name.isEmpty()))
return warn("be empty");
@@ -271,7 +271,7 @@ namespace {
}
Q_NEVER_INLINE
- static bool warn(const char *what) Q_DECL_NOEXCEPT
+ static bool warn(const char *what) noexcept
{
qWarning("QCommandLineOption: Option names cannot %s", what);
return true;
diff --git a/src/corelib/tools/qcommandlineoption.h b/src/corelib/tools/qcommandlineoption.h
index 276be042de..e2ca64acef 100644
--- a/src/corelib/tools/qcommandlineoption.h
+++ b/src/corelib/tools/qcommandlineoption.h
@@ -71,11 +71,9 @@ public:
~QCommandLineOption();
QCommandLineOption &operator=(const QCommandLineOption &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QCommandLineOption &operator=(QCommandLineOption &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QCommandLineOption &operator=(QCommandLineOption &&other) noexcept { swap(other); return *this; }
- void swap(QCommandLineOption &other) Q_DECL_NOTHROW
+ void swap(QCommandLineOption &other) noexcept
{ qSwap(d, other.d); }
QStringList names() const;
diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp
index 279d6565da..48501f5271 100644
--- a/src/corelib/tools/qcommandlineparser.cpp
+++ b/src/corelib/tools/qcommandlineparser.cpp
@@ -41,6 +41,7 @@
#include "qcommandlineparser.h"
#include <qcoreapplication.h>
+#include <private/qcoreapplication_p.h>
#include <qhash.h>
#include <qvector.h>
#include <qdebug.h>
@@ -70,11 +71,12 @@ public:
bool parse(const QStringList &args);
void checkParsed(const char *method);
QStringList aliases(const QString &name) const;
- QString helpText() const;
+ QString helpText(bool includeQtOptions) const;
bool registerFoundOption(const QString &optionName);
bool parseOptionValue(const QString &optionName, const QString &argument,
QStringList::const_iterator *argumentIterator,
QStringList::const_iterator argsEnd);
+ Q_NORETURN void showHelp(int exitCode, bool includeQtOptions);
//! Error text set when parse() returns false
QString errorText;
@@ -130,7 +132,7 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
{
const NameHash_t::const_iterator it = nameHash.constFind(optionName);
if (it == nameHash.cend()) {
- qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName));
+ qWarning("QCommandLineParser: option not defined: \"%ls\"", qUtf16Printable(optionName));
return QStringList();
}
return commandLineOptionList.at(*it).names();
@@ -362,8 +364,10 @@ bool QCommandLineParser::addOption(const QCommandLineOption &option)
if (!optionNames.isEmpty()) {
for (const QString &name : optionNames) {
- if (d->nameHash.contains(name))
+ if (d->nameHash.contains(name)) {
+ qWarning() << "QCommandLineParser: already having an option named" << name;
return false;
+ }
}
d->commandLineOptionList.append(option);
@@ -417,7 +421,9 @@ QCommandLineOption QCommandLineParser::addVersionOption()
/*!
Adds the help option (\c{-h}, \c{--help} and \c{-?} on Windows)
- This option is handled automatically by QCommandLineParser.
+ as well as an option \c{--help-all} to include Qt-specific options in the output.
+
+ These options are handled automatically by QCommandLineParser.
Remember to use setApplicationDescription to set the application description,
which will be displayed when this option is used.
@@ -434,8 +440,10 @@ QCommandLineOption QCommandLineParser::addHelpOption()
<< QStringLiteral("?")
#endif
<< QStringLiteral("h")
- << QStringLiteral("help"), tr("Displays this help."));
+ << QStringLiteral("help"), tr("Displays help on commandline options."));
addOption(opt);
+ QCommandLineOption optHelpAll(QStringLiteral("help-all"), tr("Displays help including Qt specific options."));
+ addOption(optHelpAll);
d->builtinHelpOption = true;
return opt;
}
@@ -552,9 +560,9 @@ static void showParserMessage(const QString &message, MessageType type)
{
#if defined(Q_OS_WINRT)
if (type == UsageMessage)
- qInfo(qPrintable(message));
+ qInfo("%ls", qUtf16Printable(message));
else
- qCritical(qPrintable(message));
+ qCritical("%ls", qUtf16Printable(message));
return;
#elif defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED)
if (displayMessageBox()) {
@@ -579,7 +587,8 @@ static void showParserMessage(const QString &message, MessageType type)
In addition to parsing the options (like parse()), this function also handles the builtin
options and handles errors.
- The builtin options are \c{--version} if addVersionOption was called and \c{--help} if addHelpOption was called.
+ The builtin options are \c{--version} if addVersionOption was called and
+ \c{--help} / \c{--help-all} if addHelpOption was called.
When invoking one of these options, or when an error happens (for instance an unknown option was
passed), the current process will then stop, using the exit() function.
@@ -589,7 +598,7 @@ static void showParserMessage(const QString &message, MessageType type)
void QCommandLineParser::process(const QStringList &arguments)
{
if (!d->parse(arguments)) {
- showParserMessage(errorText() + QLatin1Char('\n'), ErrorMessage);
+ showParserMessage(QCoreApplication::applicationName() + QLatin1String(": ") + errorText() + QLatin1Char('\n'), ErrorMessage);
qt_call_post_routines();
::exit(EXIT_FAILURE);
}
@@ -598,7 +607,10 @@ void QCommandLineParser::process(const QStringList &arguments)
showVersion();
if (d->builtinHelpOption && isSet(QStringLiteral("help")))
- showHelp(EXIT_SUCCESS);
+ d->showHelp(EXIT_SUCCESS, false);
+
+ if (d->builtinHelpOption && isSet(QStringLiteral("help-all")))
+ d->showHelp(EXIT_SUCCESS, true);
}
/*!
@@ -886,7 +898,7 @@ QStringList QCommandLineParser::values(const QString &optionName) const
return values;
}
- qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName));
+ qWarning("QCommandLineParser: option not defined: \"%ls\"", qUtf16Printable(optionName));
return QStringList();
}
@@ -1031,7 +1043,12 @@ Q_NORETURN void QCommandLineParser::showVersion()
*/
Q_NORETURN void QCommandLineParser::showHelp(int exitCode)
{
- showParserMessage(d->helpText(), UsageMessage);
+ d->showHelp(exitCode, false);
+}
+
+Q_NORETURN void QCommandLineParserPrivate::showHelp(int exitCode, bool includeQtOptions)
+{
+ showParserMessage(helpText(includeQtOptions), UsageMessage);
qt_call_post_routines();
::exit(exitCode);
}
@@ -1043,7 +1060,7 @@ Q_NORETURN void QCommandLineParser::showHelp(int exitCode)
*/
QString QCommandLineParser::helpText() const
{
- return d->helpText();
+ return d->helpText(false);
}
static QString wrapText(const QString &names, int longestOptionNameString, const QString &description)
@@ -1101,13 +1118,16 @@ static QString wrapText(const QString &names, int longestOptionNameString, const
return text;
}
-QString QCommandLineParserPrivate::helpText() const
+QString QCommandLineParserPrivate::helpText(bool includeQtOptions) const
{
const QLatin1Char nl('\n');
QString text;
QString usage;
usage += QCoreApplication::instance()->arguments().constFirst(); // executable name
- if (!commandLineOptionList.isEmpty())
+ QList<QCommandLineOption> options = commandLineOptionList;
+ if (includeQtOptions)
+ QCoreApplication::instance()->d_func()->addQtOptions(&options);
+ if (!options.isEmpty())
usage += QLatin1Char(' ') + QCommandLineParser::tr("[options]");
for (const PositionalArgumentDefinition &arg : positionalArgumentDefinitions)
usage += QLatin1Char(' ') + arg.syntax;
@@ -1115,12 +1135,12 @@ QString QCommandLineParserPrivate::helpText() const
if (!description.isEmpty())
text += description + nl;
text += nl;
- if (!commandLineOptionList.isEmpty())
+ if (!options.isEmpty())
text += QCommandLineParser::tr("Options:") + nl;
QStringList optionNameList;
- optionNameList.reserve(commandLineOptionList.size());
+ optionNameList.reserve(options.size());
int longestOptionNameString = 0;
- for (const QCommandLineOption &option : commandLineOptionList) {
+ for (const QCommandLineOption &option : qAsConst(options)) {
if (option.flags() & QCommandLineOption::HiddenFromHelp)
continue;
const QStringList optionNames = option.names();
@@ -1139,14 +1159,14 @@ QString QCommandLineParserPrivate::helpText() const
}
++longestOptionNameString;
auto optionNameIterator = optionNameList.cbegin();
- for (const QCommandLineOption &option : commandLineOptionList) {
+ for (const QCommandLineOption &option : qAsConst(options)) {
if (option.flags() & QCommandLineOption::HiddenFromHelp)
continue;
text += wrapText(*optionNameIterator, longestOptionNameString, option.description());
++optionNameIterator;
}
if (!positionalArgumentDefinitions.isEmpty()) {
- if (!commandLineOptionList.isEmpty())
+ if (!options.isEmpty())
text += nl;
text += QCommandLineParser::tr("Arguments:") + nl;
for (const PositionalArgumentDefinition &arg : positionalArgumentDefinitions)
diff --git a/src/corelib/tools/qcontainertools_impl.h b/src/corelib/tools/qcontainertools_impl.h
new file mode 100644
index 0000000000..86a16eb32b
--- /dev/null
+++ b/src/corelib/tools/qcontainertools_impl.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if 0
+#pragma qt_sync_skip_header_check
+#pragma qt_sync_stop_processing
+#endif
+
+#ifndef QCONTAINERTOOLS_IMPL_H
+#define QCONTAINERTOOLS_IMPL_H
+
+#include <QtCore/qglobal.h>
+#include <iterator>
+
+#ifndef Q_QDOC
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate
+{
+template <typename Iterator>
+using IfIsInputIterator = typename std::enable_if<
+ std::is_convertible<typename std::iterator_traits<Iterator>::iterator_category, std::input_iterator_tag>::value,
+ bool>::type;
+
+template <typename Iterator>
+using IfIsForwardIterator = typename std::enable_if<
+ std::is_convertible<typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>::value,
+ bool>::type;
+
+template <typename Iterator>
+using IfIsNotForwardIterator = typename std::enable_if<
+ !std::is_convertible<typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>::value,
+ bool>::type;
+
+template <typename Container,
+ typename InputIterator,
+ IfIsNotForwardIterator<InputIterator> = true>
+void reserveIfForwardIterator(Container *, InputIterator, InputIterator)
+{
+}
+
+template <typename Container,
+ typename ForwardIterator,
+ IfIsForwardIterator<ForwardIterator> = true>
+void reserveIfForwardIterator(Container *c, ForwardIterator f, ForwardIterator l)
+{
+ c->reserve(static_cast<typename Container::size_type>(std::distance(f, l)));
+}
+
+// for detecting expression validity
+template <typename ... T>
+using void_t = void;
+
+template <typename Iterator, typename = void_t<>>
+struct AssociativeIteratorHasKeyAndValue : std::false_type
+{
+};
+
+template <typename Iterator>
+struct AssociativeIteratorHasKeyAndValue<
+ Iterator,
+ void_t<decltype(std::declval<Iterator &>().key()),
+ decltype(std::declval<Iterator &>().value())>
+ >
+ : std::true_type
+{
+};
+
+template <typename Iterator, typename = void_t<>, typename = void_t<>>
+struct AssociativeIteratorHasFirstAndSecond : std::false_type
+{
+};
+
+template <typename Iterator>
+struct AssociativeIteratorHasFirstAndSecond<
+ Iterator,
+ void_t<decltype(std::declval<Iterator &>()->first),
+ decltype(std::declval<Iterator &>()->second)>
+ >
+ : std::true_type
+{
+};
+
+template <typename Iterator>
+using IfAssociativeIteratorHasKeyAndValue =
+ typename std::enable_if<AssociativeIteratorHasKeyAndValue<Iterator>::value, bool>::type;
+
+template <typename Iterator>
+using IfAssociativeIteratorHasFirstAndSecond =
+ typename std::enable_if<AssociativeIteratorHasFirstAndSecond<Iterator>::value, bool>::type;
+
+} // namespace QtPrivate
+
+QT_END_NAMESPACE
+
+#endif // Q_QDOC
+
+#endif // QCONTAINERTOOLS_IMPL_H
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
index fdb9c6d19a..7b74b4f526 100644
--- a/src/corelib/tools/qcontiguouscache.h
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -100,18 +100,16 @@ public:
inline ~QContiguousCache() { if (!d) return; if (!d->ref.deref()) freeData(p); }
- inline void detach() { if (d->ref.load() != 1) detach_helper(); }
- inline bool isDetached() const { return d->ref.load() == 1; }
+ inline void detach() { if (d->ref.loadRelaxed() != 1) detach_helper(); }
+ inline bool isDetached() const { return d->ref.loadRelaxed() == 1; }
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
#endif
QContiguousCache<T> &operator=(const QContiguousCache<T> &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other)
+ inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- inline void swap(QContiguousCache<T> &other) { qSwap(d, other.d); }
+ inline void swap(QContiguousCache<T> &other) noexcept { qSwap(d, other.d); }
bool operator==(const QContiguousCache<T> &other) const;
inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); }
@@ -178,7 +176,7 @@ void QContiguousCache<T>::detach_helper()
union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
x.d = allocateData(d->alloc);
- x.d->ref.store(1);
+ x.d->ref.storeRelaxed(1);
x.d->count = d->count;
x.d->start = d->start;
x.d->offset = d->offset;
@@ -217,7 +215,7 @@ void QContiguousCache<T>::setCapacity(int asize)
detach();
union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
x.d = allocateData(asize);
- x.d->ref.store(1);
+ x.d->ref.storeRelaxed(1);
x.d->alloc = asize;
x.d->count = qMin(d->count, asize);
x.d->offset = d->offset + d->count - x.d->count;
@@ -253,7 +251,7 @@ void QContiguousCache<T>::setCapacity(int asize)
template <typename T>
void QContiguousCache<T>::clear()
{
- if (d->ref.load() == 1) {
+ if (d->ref.loadRelaxed() == 1) {
if (QTypeInfo<T>::isComplex) {
int oldcount = d->count;
T * i = p->array + d->start;
@@ -269,7 +267,7 @@ void QContiguousCache<T>::clear()
} else {
union { QContiguousCacheData *d; QContiguousCacheTypedData<T> *p; } x;
x.d = allocateData(d->alloc);
- x.d->ref.store(1);
+ x.d->ref.storeRelaxed(1);
x.d->alloc = d->alloc;
x.d->count = x.d->start = x.d->offset = 0;
x.d->sharable = true;
@@ -289,7 +287,7 @@ QContiguousCache<T>::QContiguousCache(int cap)
{
Q_ASSERT(cap >= 0);
d = allocateData(cap);
- d->ref.store(1);
+ d->ref.storeRelaxed(1);
d->alloc = cap;
d->count = d->start = d->offset = 0;
d->sharable = true;
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index 3c79bb797d..ee7657789c 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -58,6 +58,10 @@ typedef unsigned char BitSequence;
typedef unsigned long long DataLength;
typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn;
+#ifdef Q_OS_RTEMS
+# undef ALIGN
+#endif
+
#include "../../3rdparty/sha3/KeccakSponge.c"
typedef spongeState hashState;
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
index f82048db0f..9169b5c7f1 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -339,6 +339,23 @@ struct TCBPoint {
};
Q_DECLARE_TYPEINFO(TCBPoint, Q_PRIMITIVE_TYPE);
+QDataStream &operator<<(QDataStream &stream, const TCBPoint &point)
+{
+ stream << point._point
+ << point._t
+ << point._c
+ << point._b;
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, TCBPoint &point)
+{
+ stream >> point._point
+ >> point._t
+ >> point._c
+ >> point._b;
+ return stream;
+}
typedef QVector<TCBPoint> TCBPoints;
@@ -363,6 +380,34 @@ public:
};
+QDataStream &operator<<(QDataStream &stream, QEasingCurveFunction *func)
+{
+ if (func) {
+ stream << func->_p;
+ stream << func->_a;
+ stream << func->_o;
+ if (stream.version() > QDataStream::Qt_5_12) {
+ stream << func->_bezierCurves;
+ stream << func->_tcbPoints;
+ }
+ }
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QEasingCurveFunction *func)
+{
+ if (func) {
+ stream >> func->_p;
+ stream >> func->_a;
+ stream >> func->_o;
+ if (stream.version() > QDataStream::Qt_5_12) {
+ stream >> func->_bezierCurves;
+ stream >> func->_tcbPoints;
+ }
+ }
+ return stream;
+}
+
static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve);
qreal QEasingCurveFunction::value(qreal t)
@@ -1480,9 +1525,7 @@ QDataStream &operator<<(QDataStream &stream, const QEasingCurve &easing)
bool hasConfig = easing.d_ptr->config;
stream << hasConfig;
if (hasConfig) {
- stream << easing.d_ptr->config->_p;
- stream << easing.d_ptr->config->_a;
- stream << easing.d_ptr->config->_o;
+ stream << easing.d_ptr->config;
}
return stream;
}
@@ -1515,9 +1558,7 @@ QDataStream &operator>>(QDataStream &stream, QEasingCurve &easing)
easing.d_ptr->config = nullptr;
if (hasConfig) {
QEasingCurveFunction *config = curveToFunctionObject(type);
- stream >> config->_p;
- stream >> config->_a;
- stream >> config->_o;
+ stream >> config;
easing.d_ptr->config = config;
}
return stream;
diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h
index 74bde5825a..725ddd5dcc 100644
--- a/src/corelib/tools/qeasingcurve.h
+++ b/src/corelib/tools/qeasingcurve.h
@@ -80,13 +80,11 @@ public:
QEasingCurve &operator=(const QEasingCurve &other)
{ if ( this != &other ) { QEasingCurve copy(other); swap(copy); } return *this; }
-#ifdef Q_COMPILER_RVALUE_REFS
- QEasingCurve(QEasingCurve &&other) Q_DECL_NOTHROW : d_ptr(other.d_ptr) { other.d_ptr = nullptr; }
- QEasingCurve &operator=(QEasingCurve &&other) Q_DECL_NOTHROW
+ QEasingCurve(QEasingCurve &&other) noexcept : d_ptr(other.d_ptr) { other.d_ptr = nullptr; }
+ QEasingCurve &operator=(QEasingCurve &&other) noexcept
{ qSwap(d_ptr, other.d_ptr); return *this; }
-#endif
- void swap(QEasingCurve &other) Q_DECL_NOTHROW { qSwap(d_ptr, other.d_ptr); }
+ void swap(QEasingCurve &other) noexcept { qSwap(d_ptr, other.d_ptr); }
bool operator==(const QEasingCurve &other) const;
inline bool operator!=(const QEasingCurve &other) const
diff --git a/src/corelib/tools/qfreelist_p.h b/src/corelib/tools/qfreelist_p.h
index 2f98cf5cc1..dcaf5688dc 100644
--- a/src/corelib/tools/qfreelist_p.h
+++ b/src/corelib/tools/qfreelist_p.h
@@ -171,7 +171,7 @@ class QFreeList
// qDebug("QFreeList: allocating %d elements (%ld bytes) with offset %d", size, size * sizeof(ElementType), offset);
ElementType *v = new ElementType[size];
for (int i = 0; i < size; ++i)
- v[i].next.store(offset + i + 1);
+ v[i].next.storeRelaxed(offset + i + 1);
return v;
}
@@ -187,7 +187,7 @@ class QFreeList
QAtomicInt _next;
// QFreeList is not copyable
- Q_DISABLE_COPY(QFreeList)
+ Q_DISABLE_COPY_MOVE(QFreeList)
public:
Q_DECL_CONSTEXPR inline QFreeList();
@@ -218,21 +218,21 @@ template <typename T, typename ConstantsType>
inline QFreeList<T, ConstantsType>::~QFreeList()
{
for (int i = 0; i < ConstantsType::BlockCount; ++i)
- delete [] _v[i].load();
+ delete [] _v[i].loadRelaxed();
}
template <typename T, typename ConstantsType>
inline typename QFreeList<T, ConstantsType>::ConstReferenceType QFreeList<T, ConstantsType>::at(int x) const
{
const int block = blockfor(x);
- return (_v[block].load())[x].t();
+ return (_v[block].loadRelaxed())[x].t();
}
template <typename T, typename ConstantsType>
inline typename QFreeList<T, ConstantsType>::ReferenceType QFreeList<T, ConstantsType>::operator[](int x)
{
const int block = blockfor(x);
- return (_v[block].load())[x].t();
+ return (_v[block].loadRelaxed())[x].t();
}
template <typename T, typename ConstantsType>
@@ -249,15 +249,15 @@ inline int QFreeList<T, ConstantsType>::next()
if (!v) {
v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
- if (!_v[block].testAndSetRelease(0, v)) {
+ if (!_v[block].testAndSetRelease(nullptr, v)) {
// race with another thread lost
delete [] v;
v = _v[block].loadAcquire();
- Q_ASSERT(v != 0);
+ Q_ASSERT(v != nullptr);
}
}
- newid = v[at].next.load() | (id & ~ConstantsType::IndexMask);
+ newid = v[at].next.loadRelaxed() | (id & ~ConstantsType::IndexMask);
} while (!_next.testAndSetRelease(id, newid));
// qDebug("QFreeList::next(): returning %d (_next now %d, serial %d)",
// id & ConstantsType::IndexMask,
@@ -271,12 +271,12 @@ inline void QFreeList<T, ConstantsType>::release(int id)
{
int at = id & ConstantsType::IndexMask;
const int block = blockfor(at);
- ElementType *v = _v[block].load();
+ ElementType *v = _v[block].loadRelaxed();
int x, newid;
do {
x = _next.loadAcquire();
- v[at].next.store(x & ConstantsType::IndexMask);
+ v[at].next.storeRelaxed(x & ConstantsType::IndexMask);
newid = incrementserial(x, id);
} while (!_next.testAndSetRelease(x, newid));
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 32e9a4269c..a53d6db997 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -197,7 +197,7 @@ static uint crc32(...)
}
#endif
-static inline uint hash(const uchar *p, size_t len, uint seed) Q_DECL_NOTHROW
+static inline uint hash(const uchar *p, size_t len, uint seed) noexcept
{
uint h = seed;
@@ -210,12 +210,12 @@ static inline uint hash(const uchar *p, size_t len, uint seed) Q_DECL_NOTHROW
return h;
}
-uint qHashBits(const void *p, size_t len, uint seed) Q_DECL_NOTHROW
+uint qHashBits(const void *p, size_t len, uint seed) noexcept
{
return hash(static_cast<const uchar*>(p), int(len), seed);
}
-static inline uint hash(const QChar *p, size_t len, uint seed) Q_DECL_NOTHROW
+static inline uint hash(const QChar *p, size_t len, uint seed) noexcept
{
uint h = seed;
@@ -228,29 +228,29 @@ static inline uint hash(const QChar *p, size_t len, uint seed) Q_DECL_NOTHROW
return h;
}
-uint qHash(const QByteArray &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QByteArray &key, uint seed) noexcept
{
return hash(reinterpret_cast<const uchar *>(key.constData()), size_t(key.size()), seed);
}
#if QT_STRINGVIEW_LEVEL < 2
-uint qHash(const QString &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QString &key, uint seed) noexcept
{
return hash(key.unicode(), size_t(key.size()), seed);
}
-uint qHash(const QStringRef &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QStringRef &key, uint seed) noexcept
{
return hash(key.unicode(), size_t(key.size()), seed);
}
#endif
-uint qHash(QStringView key, uint seed) Q_DECL_NOTHROW
+uint qHash(QStringView key, uint seed) noexcept
{
return hash(key.data(), key.size(), seed);
}
-uint qHash(const QBitArray &bitArray, uint seed) Q_DECL_NOTHROW
+uint qHash(const QBitArray &bitArray, uint seed) noexcept
{
int m = bitArray.d.size() - 1;
uint result = hash(reinterpret_cast<const uchar *>(bitArray.d.constData()),
@@ -264,7 +264,7 @@ uint qHash(const QBitArray &bitArray, uint seed) Q_DECL_NOTHROW
return result;
}
-uint qHash(QLatin1String key, uint seed) Q_DECL_NOTHROW
+uint qHash(QLatin1String key, uint seed) noexcept
{
return hash(reinterpret_cast<const uchar *>(key.data()), size_t(key.size()), seed);
}
@@ -321,7 +321,7 @@ static QBasicAtomicInt qt_qhash_seed = Q_BASIC_ATOMIC_INITIALIZER(-1);
*/
static void qt_initialize_qhash_seed()
{
- if (qt_qhash_seed.load() == -1) {
+ if (qt_qhash_seed.loadRelaxed() == -1) {
int x(qt_create_qhash_seed() & INT_MAX);
qt_qhash_seed.testAndSetRelaxed(-1, x);
}
@@ -340,7 +340,7 @@ static void qt_initialize_qhash_seed()
int qGlobalQHashSeed()
{
qt_initialize_qhash_seed();
- return qt_qhash_seed.load();
+ return qt_qhash_seed.loadRelaxed();
}
/*! \relates QHash
@@ -372,14 +372,14 @@ void qSetGlobalQHashSeed(int newSeed)
return;
if (newSeed == -1) {
int x(qt_create_qhash_seed() & INT_MAX);
- qt_qhash_seed.store(x);
+ qt_qhash_seed.storeRelaxed(x);
} else {
if (newSeed) {
// can't use qWarning here (reentrancy)
fprintf(stderr, "qSetGlobalQHashSeed: forced seed value is not 0, cannot guarantee that the "
"hashing functions will produce a stable value.");
}
- qt_qhash_seed.store(newSeed & INT_MAX);
+ qt_qhash_seed.storeRelaxed(newSeed & INT_MAX);
}
}
@@ -398,7 +398,7 @@ void qSetGlobalQHashSeed(int newSeed)
This function can hash discontiguous memory by invoking it on each chunk,
passing the previous's result in the next call's \a chained argument.
*/
-uint qt_hash(QStringView key, uint chained) Q_DECL_NOTHROW
+uint qt_hash(QStringView key, uint chained) noexcept
{
auto n = key.size();
auto p = key.utf16();
@@ -471,7 +471,7 @@ static int countBits(int hint)
const int MinNumBits = 4;
const QHashData QHashData::shared_null = {
- 0, 0, Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, MinNumBits, 0, 0, 0, true, false, 0
+ nullptr, nullptr, Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, MinNumBits, 0, 0, 0, true, false, 0
};
void *QHashData::allocateNode(int nodeAlign)
@@ -501,15 +501,15 @@ QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *),
if (this == &shared_null)
qt_initialize_qhash_seed(); // may throw
d = new QHashData;
- d->fakeNext = 0;
- d->buckets = 0;
+ d->fakeNext = nullptr;
+ d->buckets = nullptr;
d->ref.initializeOwned();
d->size = size;
d->nodeSize = nodeSize;
d->userNumBits = userNumBits;
d->numBits = numBits;
d->numBuckets = numBuckets;
- d->seed = (this == &shared_null) ? uint(qt_qhash_seed.load()) : seed;
+ d->seed = (this == &shared_null) ? uint(qt_qhash_seed.loadRelaxed()) : seed;
d->sharable = true;
d->strictAlignment = nodeAlign > 8;
d->reserved = 0;
@@ -709,7 +709,7 @@ void QHashData::dump()
}
n = n->next;
}
- qDebug("%s", qPrintable(line));
+ qDebug("%ls", qUtf16Printable(line));
}
}
}
@@ -938,7 +938,7 @@ void QHashData::checkSanity()
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-uint qHash(float key, uint seed) Q_DECL_NOTHROW
+uint qHash(float key, uint seed) noexcept
{
return key != 0.0f ? hash(reinterpret_cast<const uchar *>(&key), sizeof(key), seed) : seed ;
}
@@ -948,7 +948,7 @@ uint qHash(float key, uint seed) Q_DECL_NOTHROW
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-uint qHash(double key, uint seed) Q_DECL_NOTHROW
+uint qHash(double key, uint seed) noexcept
{
return key != 0.0 ? hash(reinterpret_cast<const uchar *>(&key), sizeof(key), seed) : seed ;
}
@@ -959,7 +959,7 @@ uint qHash(double key, uint seed) Q_DECL_NOTHROW
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
-uint qHash(long double key, uint seed) Q_DECL_NOTHROW
+uint qHash(long double key, uint seed) noexcept
{
return key != 0.0L ? hash(reinterpret_cast<const uchar *>(&key), sizeof(key), seed) : seed ;
}
@@ -1251,6 +1251,17 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
compiled in C++11 mode.
*/
+/*! \fn template <class Key, class T> template <class InputIterator> QHash<Key, T>::QHash(InputIterator begin, InputIterator end)
+ \since 5.14
+
+ Constructs a hash with a copy of each of the elements in the iterator range
+ [\a begin, \a end). Either the elements iterated by the range must be
+ objects with \c{first} and \c{second} data members (like \c{QPair},
+ \c{std::pair}, etc.) convertible to \c Key and to \c T respectively; or the
+ iterators must have \c{key()} and \c{value()} member functions, returning a
+ key convertible to \c Key and a value convertible to \c T respectively.
+*/
+
/*! \fn template <class Key, class T> QHash<Key, T>::QHash(const QHash &other)
Constructs a copy of \a other.
@@ -2586,6 +2597,17 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
\sa operator=()
*/
+/*! \fn template <class Key, class T> template <class InputIterator> QMultiHash::QMultiHash(InputIterator begin, InputIterator end)
+ \since 5.14
+
+ Constructs a multi-hash with a copy of each of the elements in the iterator range
+ [\a begin, \a end). Either the elements iterated by the range must be
+ objects with \c{first} and \c{second} data members (like \c{QPair},
+ \c{std::pair}, etc.) convertible to \c Key and to \c T respectively; or the
+ iterators must have \c{key()} and \c{value()} member functions, returning a
+ key convertible to \c Key and a value convertible to \c T respectively.
+*/
+
/*! \fn template <class Key, class T> QMultiHash<Key, T>::iterator QMultiHash<Key, T>::replace(const Key &key, const T &value)
Inserts a new item with the \a key and a value of \a value.
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index a586ca5671..4b4cb2d5f0 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -46,12 +46,10 @@
#include <QtCore/qlist.h>
#include <QtCore/qrefcount.h>
#include <QtCore/qhashfunctions.h>
-
-#ifdef Q_COMPILER_INITIALIZER_LISTS
-#include <initializer_list>
-#endif
+#include <QtCore/qcontainertools_impl.h>
#include <algorithm>
+#include <initializer_list>
#if defined(Q_CC_MSVC)
#pragma warning( push )
@@ -240,8 +238,7 @@ class QHash
static inline int alignOfNode() { return qMax<int>(sizeof(void*), Q_ALIGNOF(Node)); }
public:
- inline QHash() Q_DECL_NOTHROW : d(const_cast<QHashData *>(&QHashData::shared_null)) { }
-#ifdef Q_COMPILER_INITIALIZER_LISTS
+ inline QHash() noexcept : d(const_cast<QHashData *>(&QHashData::shared_null)) { }
inline QHash(std::initializer_list<std::pair<Key,T> > list)
: d(const_cast<QHashData *>(&QHashData::shared_null))
{
@@ -249,17 +246,36 @@ public:
for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
insert(it->first, it->second);
}
-#endif
QHash(const QHash &other) : d(other.d) { d->ref.ref(); if (!d->sharable) detach(); }
~QHash() { if (!d->ref.deref()) freeData(d); }
QHash &operator=(const QHash &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QHash(QHash &&other) Q_DECL_NOTHROW : d(other.d) { other.d = const_cast<QHashData *>(&QHashData::shared_null); }
- QHash &operator=(QHash &&other) Q_DECL_NOTHROW
+ QHash(QHash &&other) noexcept : d(other.d) { other.d = const_cast<QHashData *>(&QHashData::shared_null); }
+ QHash &operator=(QHash &&other) noexcept
{ QHash moved(std::move(other)); swap(moved); return *this; }
+#ifdef Q_QDOC
+ template <typename InputIterator>
+ QHash(InputIterator f, InputIterator l);
+#else
+ template <typename InputIterator, QtPrivate::IfAssociativeIteratorHasKeyAndValue<InputIterator> = true>
+ QHash(InputIterator f, InputIterator l)
+ : QHash()
+ {
+ QtPrivate::reserveIfForwardIterator(this, f, l);
+ for (; f != l; ++f)
+ insert(f.key(), f.value());
+ }
+
+ template <typename InputIterator, QtPrivate::IfAssociativeIteratorHasFirstAndSecond<InputIterator> = true>
+ QHash(InputIterator f, InputIterator l)
+ : QHash()
+ {
+ QtPrivate::reserveIfForwardIterator(this, f, l);
+ for (; f != l; ++f)
+ insert(f->first, f->second);
+ }
#endif
- void swap(QHash &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QHash &other) noexcept { qSwap(d, other.d); }
bool operator==(const QHash &other) const;
bool operator!=(const QHash &other) const { return !(*this == other); }
@@ -473,7 +489,7 @@ public:
inline const_key_value_iterator constKeyValueEnd() const { return const_key_value_iterator(end()); }
QPair<iterator, iterator> equal_range(const Key &key);
- QPair<const_iterator, const_iterator> equal_range(const Key &key) const Q_DECL_NOTHROW;
+ QPair<const_iterator, const_iterator> equal_range(const Key &key) const noexcept;
iterator erase(iterator it) { return erase(const_iterator(it.i)); }
iterator erase(const_iterator it);
@@ -512,11 +528,11 @@ private:
static void duplicateNode(QHashData::Node *originalNode, void *newNode);
- bool isValidIterator(const iterator &it) const Q_DECL_NOTHROW
+ bool isValidIterator(const iterator &it) const noexcept
{ return isValidNode(it.i); }
- bool isValidIterator(const const_iterator &it) const Q_DECL_NOTHROW
+ bool isValidIterator(const const_iterator &it) const noexcept
{ return isValidNode(it.i); }
- bool isValidNode(QHashData::Node *node) const Q_DECL_NOTHROW
+ bool isValidNode(QHashData::Node *node) const noexcept
{
#if defined(QT_DEBUG) && !defined(Q_HASH_NO_ITERATOR_DEBUG)
while (node->next)
@@ -993,7 +1009,7 @@ QPair<typename QHash<Key, T>::iterator, typename QHash<Key, T>::iterator> QHash<
}
template <class Key, class T>
-QPair<typename QHash<Key, T>::const_iterator, typename QHash<Key, T>::const_iterator> QHash<Key, T>::equal_range(const Key &akey) const Q_DECL_NOTHROW
+QPair<typename QHash<Key, T>::const_iterator, typename QHash<Key, T>::const_iterator> QHash<Key, T>::equal_range(const Key &akey) const noexcept
{
Node *node = *findNode(akey);
const_iterator firstIt = const_iterator(node);
@@ -1020,23 +1036,39 @@ template <class Key, class T>
class QMultiHash : public QHash<Key, T>
{
public:
- QMultiHash() Q_DECL_NOTHROW {}
-#ifdef Q_COMPILER_INITIALIZER_LISTS
+ QMultiHash() noexcept {}
inline QMultiHash(std::initializer_list<std::pair<Key,T> > list)
{
this->reserve(int(list.size()));
for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
insert(it->first, it->second);
}
+#ifdef Q_QDOC
+ template <typename InputIterator>
+ QMultiHash(InputIterator f, InputIterator l);
+#else
+ template <typename InputIterator, QtPrivate::IfAssociativeIteratorHasKeyAndValue<InputIterator> = true>
+ QMultiHash(InputIterator f, InputIterator l)
+ {
+ QtPrivate::reserveIfForwardIterator(this, f, l);
+ for (; f != l; ++f)
+ insert(f.key(), f.value());
+ }
+
+ template <typename InputIterator, QtPrivate::IfAssociativeIteratorHasFirstAndSecond<InputIterator> = true>
+ QMultiHash(InputIterator f, InputIterator l)
+ {
+ QtPrivate::reserveIfForwardIterator(this, f, l);
+ for (; f != l; ++f)
+ insert(f->first, f->second);
+ }
#endif
// compiler-generated copy/move ctors/assignment operators are fine!
// compiler-generated destructor is fine!
QMultiHash(const QHash<Key, T> &other) : QHash<Key, T>(other) {}
-#ifdef Q_COMPILER_RVALUE_REFS
- QMultiHash(QHash<Key, T> &&other) Q_DECL_NOTHROW : QHash<Key, T>(std::move(other)) {}
-#endif
- void swap(QMultiHash &other) Q_DECL_NOTHROW { QHash<Key, T>::swap(other); } // prevent QMultiHash<->QHash swaps
+ QMultiHash(QHash<Key, T> &&other) noexcept : QHash<Key, T>(std::move(other)) {}
+ void swap(QMultiHash &other) noexcept { QHash<Key, T>::swap(other); } // prevent QMultiHash<->QHash swaps
inline typename QHash<Key, T>::iterator replace(const Key &key, const T &value)
{ return QHash<Key, T>::insert(key, value); }
@@ -1130,7 +1162,7 @@ Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Hash)
template <class Key, class T>
uint qHash(const QHash<Key, T> &key, uint seed = 0)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>())))
+ noexcept(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>())))
{
QtPrivate::QHashCombineCommutative hash;
for (auto it = key.begin(), end = key.end(); it != end; ++it) {
@@ -1143,7 +1175,7 @@ uint qHash(const QHash<Key, T> &key, uint seed = 0)
template <class Key, class T>
inline uint qHash(const QMultiHash<Key, T> &key, uint seed = 0)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>())))
+ noexcept(noexcept(qHash(std::declval<Key&>())) && noexcept(qHash(std::declval<T&>())))
{
const QHash<Key, T> &key2 = key;
return qHash(key2, seed);
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index d013c26d66..2ff3464912 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -45,6 +45,7 @@
#include <QtCore/qpair.h>
#include <numeric> // for std::accumulate
+#include <functional> // for std::hash
#if 0
#pragma qt_class(QHashFunctions)
@@ -67,54 +68,54 @@ class QLatin1String;
Q_CORE_EXPORT int qGlobalQHashSeed();
Q_CORE_EXPORT void qSetGlobalQHashSeed(int newSeed);
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHashBits(const void *p, size_t size, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHashBits(const void *p, size_t size, uint seed = 0) noexcept;
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(char key, uint seed = 0) noexcept { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uchar key, uint seed = 0) noexcept { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(signed char key, uint seed = 0) noexcept { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ushort key, uint seed = 0) noexcept { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(short key, uint seed = 0) noexcept { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uint key, uint seed = 0) noexcept { return key ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(int key, uint seed = 0) noexcept { return uint(key) ^ seed; }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ulong key, uint seed = 0) noexcept
{
return (sizeof(ulong) > sizeof(uint))
? (uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed)
: (uint(key & (~0U)) ^ seed);
}
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); }
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(long key, uint seed = 0) noexcept { return qHash(ulong(key), seed); }
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(quint64 key, uint seed = 0) noexcept
{
return uint(((key >> (8 * sizeof(uint) - 1)) ^ key) & (~0U)) ^ seed;
}
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); }
-Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW;
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(qint64 key, uint seed = 0) noexcept { return qHash(quint64(key), seed); }
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(float key, uint seed = 0) noexcept;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(double key, uint seed = 0) noexcept;
#if !defined(Q_OS_DARWIN) || defined(Q_CLANG_QDOC)
-Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(long double key, uint seed = 0) noexcept;
#endif
-Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(const QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); }
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(const QChar key, uint seed = 0) noexcept { return qHash(key.unicode(), seed); }
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QByteArray &key, uint seed = 0) noexcept;
#if QT_STRINGVIEW_LEVEL < 2
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QString &key, uint seed = 0) noexcept;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QStringRef &key, uint seed = 0) noexcept;
#endif
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QStringView key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(QStringView key, uint chained = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QStringView key, uint seed = 0) noexcept;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = 0) noexcept;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) noexcept;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(QStringView key, uint chained = 0) noexcept;
-Q_DECL_CONST_FUNCTION inline uint qHash(std::nullptr_t, uint seed = 0) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION inline uint qHash(std::nullptr_t, uint seed = 0) noexcept
{
return qHash(reinterpret_cast<quintptr>(nullptr), seed);
}
-template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW
+template <class T> inline uint qHash(const T *key, uint seed = 0) noexcept
{
return qHash(reinterpret_cast<quintptr>(key), seed);
}
template<typename T> inline uint qHash(const T &t, uint seed)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t)))
+ noexcept(noexcept(qHash(t)))
{ return qHash(t) ^ seed; }
namespace QtPrivate {
@@ -122,7 +123,7 @@ namespace QtPrivate {
struct QHashCombine {
typedef uint result_type;
template <typename T>
- Q_DECL_CONSTEXPR result_type operator()(uint seed, const T &t) const Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t)))
+ Q_DECL_CONSTEXPR result_type operator()(uint seed, const T &t) const noexcept(noexcept(qHash(t)))
// combiner taken from N3876 / boost::hash_combine
{ return seed ^ (qHash(t) + 0x9e3779b9 + (seed << 6) + (seed >> 2)) ; }
};
@@ -135,7 +136,7 @@ struct QHashCombineCommutative {
// QHash). Therefore, provide a commutative combiner, too.
typedef uint result_type;
template <typename T>
- Q_DECL_CONSTEXPR result_type operator()(uint seed, const T &t) const Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t)))
+ Q_DECL_CONSTEXPR result_type operator()(uint seed, const T &t) const noexcept(noexcept(qHash(t)))
{ return seed + qHash(t); } // don't use xor!
};
@@ -143,20 +144,20 @@ struct QHashCombineCommutative {
template <typename InputIterator>
inline uint qHashRange(InputIterator first, InputIterator last, uint seed = 0)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(*first))) // assume iterator operations don't throw
+ noexcept(noexcept(qHash(*first))) // assume iterator operations don't throw
{
return std::accumulate(first, last, seed, QtPrivate::QHashCombine());
}
template <typename InputIterator>
inline uint qHashRangeCommutative(InputIterator first, InputIterator last, uint seed = 0)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(*first))) // assume iterator operations don't throw
+ noexcept(noexcept(qHash(*first))) // assume iterator operations don't throw
{
return std::accumulate(first, last, seed, QtPrivate::QHashCombineCommutative());
}
template <typename T1, typename T2> inline uint qHash(const QPair<T1, T2> &key, uint seed = 0)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed)))
+ noexcept(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed)))
{
uint h1 = qHash(key.first, seed);
uint h2 = qHash(key.second, seed);
@@ -164,7 +165,7 @@ template <typename T1, typename T2> inline uint qHash(const QPair<T1, T2> &key,
}
template <typename T1, typename T2> inline uint qHash(const std::pair<T1, T2> &key, uint seed = 0)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed)))
+ noexcept(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed)))
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.first);
@@ -172,6 +173,41 @@ template <typename T1, typename T2> inline uint qHash(const std::pair<T1, T2> &k
return seed;
}
+#define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, Arguments) \
+ QT_BEGIN_INCLUDE_NAMESPACE \
+ namespace std { \
+ template <> \
+ struct hash< QT_PREPEND_NAMESPACE(Class) > { \
+ using argument_type = QT_PREPEND_NAMESPACE(Class); \
+ using result_type = size_t; \
+ size_t operator()(Arguments s) const \
+ noexcept(noexcept(QT_PREPEND_NAMESPACE(qHash)(s))) \
+ { \
+ /* this seeds qHash with the result of */ \
+ /* std::hash applied to an int, to reap */ \
+ /* any protection against predictable hash */ \
+ /* values the std implementation may provide */ \
+ return QT_PREPEND_NAMESPACE(qHash)(s, \
+ QT_PREPEND_NAMESPACE(qHash)( \
+ std::hash<int>{}(0))); \
+ } \
+ }; \
+ } \
+ QT_END_INCLUDE_NAMESPACE \
+ /*end*/
+
+#define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(Class) \
+ QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, const argument_type &)
+#define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(Class) \
+ QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH(Class, argument_type)
+
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QString)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QStringRef)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QStringView)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_VALUE(QLatin1String)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QByteArray)
+QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(QBitArray)
+
QT_END_NAMESPACE
#if defined(Q_CC_MSVC)
diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h
index 586d26cbad..82212c3eb5 100644
--- a/src/corelib/tools/qiterator.h
+++ b/src/corelib/tools/qiterator.h
@@ -190,15 +190,15 @@ public:
typedef const value_type &reference;
QKeyValueIterator() = default;
- Q_DECL_CONSTEXPR explicit QKeyValueIterator(Iterator o) Q_DECL_NOEXCEPT_EXPR(std::is_nothrow_move_constructible<Iterator>::value)
+ Q_DECL_CONSTEXPR explicit QKeyValueIterator(Iterator o) noexcept(std::is_nothrow_move_constructible<Iterator>::value)
: i(std::move(o)) {}
std::pair<Key, T> operator*() const {
return std::pair<Key, T>(i.key(), i.value());
}
- friend bool operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) Q_DECL_NOEXCEPT { return lhs.i == rhs.i; }
- friend bool operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) Q_DECL_NOEXCEPT { return lhs.i != rhs.i; }
+ friend bool operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i == rhs.i; }
+ friend bool operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i != rhs.i; }
inline QKeyValueIterator &operator++() { ++i; return *this; }
inline QKeyValueIterator operator++(int) { return QKeyValueIterator(i++);}
diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp
index 949f63ea15..3afd23d76b 100644
--- a/src/corelib/tools/qline.cpp
+++ b/src/corelib/tools/qline.cpp
@@ -347,7 +347,7 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
function to determine whether the QLineF represents a valid line
or a null line.
- The intersect() function determines the IntersectType for this
+ The intersects() function determines the IntersectionType for this
line and a given line, while the angleTo() function returns the
angle between the lines. In addition, the unitVector() function
returns a line that has the same starting point as this line, but
@@ -370,6 +370,11 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
/*!
\enum QLineF::IntersectType
+ \obsolete Use QLineF::IntersectionType instead
+*/
+
+/*!
+ \enum QLineF::IntersectionType
Describes the intersection between two lines.
@@ -657,8 +662,10 @@ QLineF QLineF::unitVector() const
return f;
}
+#if QT_DEPRECATED_SINCE(5, 14)
/*!
\fn QLineF::IntersectType QLineF::intersect(const QLineF &line, QPointF *intersectionPoint) const
+ \obsolete Use intersects() instead
Returns a value indicating whether or not \e this line intersects
with the given \a line.
@@ -670,6 +677,23 @@ QLineF QLineF::unitVector() const
QLineF::IntersectType QLineF::intersect(const QLineF &l, QPointF *intersectionPoint) const
{
+ return intersects(l, intersectionPoint);
+}
+#endif
+
+/*!
+ \fn QLineF::IntersectionType QLineF::intersects(const QLineF &line, QPointF *intersectionPoint) const
+ \since 5.14
+
+ Returns a value indicating whether or not \e this line intersects
+ with the given \a line.
+
+ The actual intersection point is extracted to \a intersectionPoint
+ (if the pointer is valid). If the lines are parallel, the
+ intersection point is undefined.
+*/
+QLineF::IntersectionType QLineF::intersects(const QLineF &l, QPointF *intersectionPoint) const
+{
// ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection"
const QPointF a = pt2 - pt1;
const QPointF b = l.pt1 - l.pt2;
@@ -805,6 +829,7 @@ qreal QLineF::angleTo(const QLineF &l) const
return delta_normalized;
}
+#if QT_DEPRECATED_SINCE(5, 14)
/*!
\fn qreal QLineF::angle(const QLineF &line) const
@@ -837,6 +862,7 @@ qreal QLineF::angle(const QLineF &l) const
if (cos_line >= -1.0 && cos_line <= 1.0) rad = qAcos( cos_line );
return rad * 360 / M_2PI;
}
+#endif
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/corelib/tools/qline.h b/src/corelib/tools/qline.h
index 6361c1af9f..c96d624afd 100644
--- a/src/corelib/tools/qline.h
+++ b/src/corelib/tools/qline.h
@@ -215,6 +215,7 @@ class Q_CORE_EXPORT QLineF {
public:
enum IntersectType { NoIntersection, BoundedIntersection, UnboundedIntersection };
+ using IntersectionType = IntersectType;
Q_DECL_CONSTEXPR inline QLineF();
Q_DECL_CONSTEXPR inline QLineF(const QPointF &pt1, const QPointF &pt2);
@@ -248,10 +249,14 @@ public:
Q_REQUIRED_RESULT QLineF unitVector() const;
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QLineF normalVector() const;
- // ### Qt 6: rename intersects() or intersection() and rename IntersectType IntersectionType
- IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const;
+ IntersectionType intersects(const QLineF &l, QPointF *intersectionPoint) const;
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_VERSION_X(5, 14, "Use intersects() instead")
+ IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const;
+ QT_DEPRECATED_X("Use angleTo() instead, take care that the return value is between 0 and 360 degree.")
qreal angle(const QLineF &l) const;
+#endif
Q_DECL_CONSTEXPR inline QPointF pointAt(qreal t) const;
inline void translate(const QPointF &p);
diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp
index d9d93862e5..c0450f5cd8 100644
--- a/src/corelib/tools/qlinkedlist.cpp
+++ b/src/corelib/tools/qlinkedlist.cpp
@@ -153,6 +153,14 @@ const QLinkedListData QLinkedListData::shared_null = {
initializer lists.
*/
+/*! \fn template <class T> template<typename InputIterator> QLinkedList<T>::QLinkedList(InputIterator first, InputIterator last)
+ \since 5.14
+
+ Constructs a list with the contents in the iterator range [\a first, \a last).
+
+ The value type of \c InputIterator must be convertible to \c T.
+*/
+
/*! \fn template <class T> QLinkedList<T>::~QLinkedList()
Destroys the list. References to the values in the list, and all
diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h
index 1e6d4df474..d4e5bca0ed 100644
--- a/src/corelib/tools/qlinkedlist.h
+++ b/src/corelib/tools/qlinkedlist.h
@@ -42,16 +42,15 @@
#include <QtCore/qiterator.h>
#include <QtCore/qrefcount.h>
+#include <QtCore/qcontainertools_impl.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qtypeinfo.h>
+#include <algorithm>
+#include <initializer_list>
#include <iterator>
#include <list>
-#include <algorithm>
-
-#if defined(Q_COMPILER_INITIALIZER_LISTS)
-# include <initializer_list>
-#endif
-
QT_BEGIN_NAMESPACE
@@ -80,24 +79,23 @@ class QLinkedList
union { QLinkedListData *d; QLinkedListNode<T> *e; };
public:
- inline QLinkedList() Q_DECL_NOTHROW : d(const_cast<QLinkedListData *>(&QLinkedListData::shared_null)) { }
+ inline QLinkedList() noexcept : d(const_cast<QLinkedListData *>(&QLinkedListData::shared_null)) { }
inline QLinkedList(const QLinkedList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); }
-#if defined(Q_COMPILER_INITIALIZER_LISTS)
inline QLinkedList(std::initializer_list<T> list)
- : d(const_cast<QLinkedListData *>(&QLinkedListData::shared_null))
+ : QLinkedList(list.begin(), list.end()) {}
+ template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
+ inline QLinkedList(InputIterator first, InputIterator last)
+ : QLinkedList()
{
- std::copy(list.begin(), list.end(), std::back_inserter(*this));
+ std::copy(first, last, std::back_inserter(*this));
}
-#endif
~QLinkedList();
QLinkedList<T> &operator=(const QLinkedList<T> &);
-#ifdef Q_COMPILER_RVALUE_REFS
- QLinkedList(QLinkedList<T> &&other) Q_DECL_NOTHROW
+ QLinkedList(QLinkedList<T> &&other) noexcept
: d(other.d) { other.d = const_cast<QLinkedListData *>(&QLinkedListData::shared_null); }
- QLinkedList<T> &operator=(QLinkedList<T> &&other) Q_DECL_NOTHROW
+ QLinkedList<T> &operator=(QLinkedList<T> &&other) noexcept
{ QLinkedList moved(std::move(other)); swap(moved); return *this; }
-#endif
- inline void swap(QLinkedList<T> &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ inline void swap(QLinkedList<T> &other) noexcept { qSwap(d, other.d); }
bool operator==(const QLinkedList<T> &l) const;
inline bool operator!=(const QLinkedList<T> &l) const { return !(*this == l); }
@@ -137,10 +135,10 @@ public:
inline iterator() : i(nullptr) {}
inline iterator(Node *n) : i(n) {}
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- iterator(const iterator &other) Q_DECL_NOTHROW : i(other.i) {}
- iterator &operator=(const iterator &other) Q_DECL_NOTHROW { i = other.i; return *this; }
- iterator(iterator &&other) Q_DECL_NOTHROW : i(other.i) {}
- iterator &operator=(iterator &&other) Q_DECL_NOTHROW { return *this = other; }
+ iterator(const iterator &other) noexcept : i(other.i) {}
+ iterator &operator=(const iterator &other) noexcept { i = other.i; return *this; }
+ iterator(iterator &&other) noexcept : i(other.i) {}
+ iterator &operator=(iterator &&other) noexcept { return *this = other; }
#endif
inline T &operator*() const { return i->t; }
inline T *operator->() const { return &i->t; }
@@ -176,10 +174,10 @@ public:
inline const_iterator(Node *n) : i(n) {}
inline const_iterator(iterator ci) : i(ci.i){}
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- const_iterator(const const_iterator &other) Q_DECL_NOTHROW : i(other.i) {}
- const_iterator &operator=(const const_iterator &other) Q_DECL_NOTHROW { i = other.i; return *this; }
- const_iterator(const_iterator &&other) Q_DECL_NOTHROW : i(other.i) {}
- const_iterator &operator=(const_iterator &&other) Q_DECL_NOTHROW { return *this = other; }
+ const_iterator(const const_iterator &other) noexcept : i(other.i) {}
+ const_iterator &operator=(const const_iterator &other) noexcept { i = other.i; return *this; }
+ const_iterator(const_iterator &&other) noexcept : i(other.i) {}
+ const_iterator &operator=(const_iterator &&other) noexcept { return *this = other; }
#endif
inline const T &operator*() const { return i->t; }
inline const T *operator->() const { return &i->t; }
@@ -203,20 +201,20 @@ public:
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
inline iterator begin() { detach(); return e->n; }
- inline const_iterator begin() const Q_DECL_NOTHROW { return e->n; }
- inline const_iterator cbegin() const Q_DECL_NOTHROW { return e->n; }
- inline const_iterator constBegin() const Q_DECL_NOTHROW { return e->n; }
+ inline const_iterator begin() const noexcept { return e->n; }
+ inline const_iterator cbegin() const noexcept { return e->n; }
+ inline const_iterator constBegin() const noexcept { return e->n; }
inline iterator end() { detach(); return e; }
- inline const_iterator end() const Q_DECL_NOTHROW { return e; }
- inline const_iterator cend() const Q_DECL_NOTHROW { return e; }
- inline const_iterator constEnd() const Q_DECL_NOTHROW { return e; }
+ inline const_iterator end() const noexcept { return e; }
+ inline const_iterator cend() const noexcept { return e; }
+ inline const_iterator constEnd() const noexcept { return e; }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
- const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
iterator insert(iterator before, const T &t);
iterator erase(iterator pos);
@@ -270,6 +268,8 @@ private:
iterator detach_helper2(iterator);
void freeData(QLinkedListData*);
};
+template <typename T>
+Q_DECLARE_TYPEINFO_BODY(QLinkedList<T>, Q_MOVABLE_TYPE|Q_RELOCATABLE_TYPE);
template <typename T>
inline QLinkedList<T>::~QLinkedList()
@@ -340,7 +340,7 @@ void QLinkedList<T>::freeData(QLinkedListData *x)
{
Node *y = reinterpret_cast<Node*>(x);
Node *i = y->n;
- Q_ASSERT(x->ref.atomic.load() == 0);
+ Q_ASSERT(x->ref.atomic.loadRelaxed() == 0);
while (i != y) {
Node *n = i;
i = i->n;
@@ -565,6 +565,20 @@ QLinkedList<T> QLinkedList<T>::operator+(const QLinkedList<T> &l) const
Q_DECLARE_SEQUENTIAL_ITERATOR(LinkedList)
Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(LinkedList)
+#ifndef QT_NO_DATASTREAM
+template <typename T>
+inline QDataStream &operator>>(QDataStream &s, QLinkedList<T> &l)
+{
+ return QtPrivate::readListBasedContainer(s, l);
+}
+
+template <typename T>
+inline QDataStream &operator<<(QDataStream &s, const QLinkedList<T> &l)
+{
+ return QtPrivate::writeSequentialContainer(s, l);
+}
+#endif
+
QT_END_NAMESPACE
#endif // QLINKEDLIST_H
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp
index 17aba8035b..dfebd57e34 100644
--- a/src/corelib/tools/qlist.cpp
+++ b/src/corelib/tools/qlist.cpp
@@ -48,6 +48,23 @@
QT_BEGIN_NAMESPACE
/*
+ ### Qt 5:
+ ### This needs to be removed for next releases of Qt. It is a workaround for vc++ because
+ ### Qt exports QPolygon and QPolygonF that inherit QVector<QPoint> and
+ ### QVector<QPointF> respectively.
+*/
+
+#if defined(Q_CC_MSVC) && defined(QT_BUILD_CORE_LIB)
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <QtCore/qpoint.h>
+QT_END_INCLUDE_NAMESPACE
+
+template class Q_CORE_EXPORT QVector<QPointF>;
+template class Q_CORE_EXPORT QVector<QPoint>;
+#endif
+
+
+/*
QList as an array-list combines the easy-of-use of a random
access interface with fast list operations and the low memory
management overhead of an array. Accessing elements by index,
@@ -58,7 +75,7 @@ QT_BEGIN_NAMESPACE
the number of elements in the list.
*/
-const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, { 0 } };
+const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, { nullptr } };
/*!
* Detaches the QListData by allocating new memory for a list which will be bigger
@@ -528,6 +545,14 @@ void **QListData::erase(void **xi)
\since 5.2
*/
+/*! \fn template <class T> template<typename InputIterator> QList<T>::QList(InputIterator first, InputIterator last)
+ \since 5.14
+
+ Constructs a QList with the contents in the iterator range [\a first, \a last).
+
+ The value type of \c InputIterator must be convertible to \c T.
+*/
+
/*!
\fn template <class T> QList<T> QList<T>::mid(int pos, int length) const
@@ -948,6 +973,14 @@ void **QListData::erase(void **xi)
/*! \fn template <class T> void QList<T>::swap(int i, int j)
+ \obsolete Use swapItemsAt()
+
+ \sa move(), swapItemsAt()
+*/
+
+/*! \fn template <class T> void QList<T>::swapItemsAt(int i, int j)
+ \since 5.13
+
Exchange the item at index position \a i with the item at index
position \a j. This function assumes that both \a i and \a j are
at least 0 but less than size(). To avoid failure, test that both
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 49ccbc9c9f..70bbc11ad2 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -45,12 +45,14 @@
#include <QtCore/qrefcount.h>
#include <QtCore/qarraydata.h>
#include <QtCore/qhashfunctions.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qcontainertools_impl.h>
-#include <iterator>
-#include <list>
#include <algorithm>
-#ifdef Q_COMPILER_INITIALIZER_LISTS
#include <initializer_list>
+#include <iterator>
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+#include <list>
#endif
#include <stdlib.h>
@@ -72,7 +74,7 @@ template <typename T> class QSet;
template <typename T> struct QListSpecialMethods
{
protected:
- ~QListSpecialMethods() {}
+ ~QListSpecialMethods() = default;
};
template <> struct QListSpecialMethods<QByteArray>;
template <> struct QListSpecialMethods<QString>;
@@ -110,13 +112,18 @@ struct Q_CORE_EXPORT QListData {
void remove(int i);
void remove(int i, int n);
void move(int from, int to);
- inline int size() const Q_DECL_NOTHROW { return d->end - d->begin; }
- inline bool isEmpty() const Q_DECL_NOTHROW { return d->end == d->begin; }
- inline void **at(int i) const Q_DECL_NOTHROW { return d->array + d->begin + i; }
- inline void **begin() const Q_DECL_NOTHROW { return d->array + d->begin; }
- inline void **end() const Q_DECL_NOTHROW { return d->array + d->end; }
+ inline int size() const noexcept { return d->end - d->begin; }
+ inline bool isEmpty() const noexcept { return d->end == d->begin; }
+ inline void **at(int i) const noexcept { return d->array + d->begin + i; }
+ inline void **begin() const noexcept { return d->array + d->begin; }
+ inline void **end() const noexcept { return d->array + d->end; }
};
+namespace QtPrivate {
+ template <typename V, typename U> int indexOf(const QList<V> &list, const U &u, int from);
+ template <typename V, typename U> int lastIndexOf(const QList<V> &list, const U &u, int from);
+}
+
template <typename T>
class QList
#ifndef Q_QDOC
@@ -135,6 +142,8 @@ public:
QListData::InlineWithPaddingLayout
>::type>::type {};
private:
+ template <typename V, typename U> friend int QtPrivate::indexOf(const QList<V> &list, const U &u, int from);
+ template <typename V, typename U> friend int QtPrivate::lastIndexOf(const QList<V> &list, const U &u, int from);
struct Node { void *v;
#if defined(Q_CC_BOR)
Q_INLINE_TEMPLATE T &t();
@@ -148,26 +157,23 @@ private:
union { QListData p; QListData::Data *d; };
public:
- inline QList() Q_DECL_NOTHROW : d(const_cast<QListData::Data *>(&QListData::shared_null)) { }
+ inline QList() noexcept : d(const_cast<QListData::Data *>(&QListData::shared_null)) { }
QList(const QList<T> &l);
~QList();
QList<T> &operator=(const QList<T> &l);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QList(QList<T> &&other) Q_DECL_NOTHROW
+ inline QList(QList<T> &&other) noexcept
: d(other.d) { other.d = const_cast<QListData::Data *>(&QListData::shared_null); }
- inline QList &operator=(QList<T> &&other) Q_DECL_NOTHROW
+ inline QList &operator=(QList<T> &&other) noexcept
{ QList moved(std::move(other)); swap(moved); return *this; }
-#endif
- inline void swap(QList<T> &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
-#ifdef Q_COMPILER_INITIALIZER_LISTS
+ inline void swap(QList<T> &other) noexcept { qSwap(d, other.d); }
inline QList(std::initializer_list<T> args)
- : d(const_cast<QListData::Data *>(&QListData::shared_null))
- { reserve(int(args.size())); std::copy(args.begin(), args.end(), std::back_inserter(*this)); }
-#endif
+ : QList(args.begin(), args.end()) {}
+ template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
+ QList(InputIterator first, InputIterator last);
bool operator==(const QList<T> &l) const;
inline bool operator!=(const QList<T> &l) const { return !(*this == l); }
- inline int size() const Q_DECL_NOTHROW { return p.size(); }
+ inline int size() const noexcept { return p.size(); }
inline void detach() { if (d->ref.isShared()) detach_helper(); }
@@ -190,9 +196,9 @@ public:
d->ref.setSharable(sharable);
}
#endif
- inline bool isSharedWith(const QList<T> &other) const Q_DECL_NOTHROW { return d == other.d; }
+ inline bool isSharedWith(const QList<T> &other) const noexcept { return d == other.d; }
- inline bool isEmpty() const Q_DECL_NOTHROW { return p.isEmpty(); }
+ inline bool isEmpty() const noexcept { return p.isEmpty(); }
void clear();
@@ -213,7 +219,11 @@ public:
T takeFirst();
T takeLast();
void move(int from, int to);
- void swap(int i, int j);
+ void swapItemsAt(int i, int j);
+#if QT_DEPRECATED_SINCE(5, 13) && QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ QT_DEPRECATED_X("Use QList<T>::swapItemsAt()")
+ void swap(int i, int j) { swapItemsAt(i, j); }
+#endif
int indexOf(const T &t, int from = 0) const;
int lastIndexOf(const T &t, int from = -1) const;
bool contains(const T &t) const;
@@ -231,34 +241,36 @@ public:
typedef T *pointer;
typedef T &reference;
- inline iterator() Q_DECL_NOTHROW : i(nullptr) {}
- inline iterator(Node *n) Q_DECL_NOTHROW : i(n) {}
+ inline iterator() noexcept : i(nullptr) {}
+ inline iterator(Node *n) noexcept : i(n) {}
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
// can't remove it in Qt 5, since doing so would make the type trivial,
// which changes the way it's passed to functions by value.
- inline iterator(const iterator &o) Q_DECL_NOTHROW : i(o.i){}
+ inline iterator(const iterator &o) noexcept : i(o.i){}
+ inline iterator &operator=(const iterator &o) noexcept
+ { i = o.i; return *this; }
#endif
inline T &operator*() const { return i->t(); }
inline T *operator->() const { return &i->t(); }
inline T &operator[](difference_type j) const { return i[j].t(); }
- inline bool operator==(const iterator &o) const Q_DECL_NOTHROW { return i == o.i; }
- inline bool operator!=(const iterator &o) const Q_DECL_NOTHROW { return i != o.i; }
- inline bool operator<(const iterator& other) const Q_DECL_NOTHROW { return i < other.i; }
- inline bool operator<=(const iterator& other) const Q_DECL_NOTHROW { return i <= other.i; }
- inline bool operator>(const iterator& other) const Q_DECL_NOTHROW { return i > other.i; }
- inline bool operator>=(const iterator& other) const Q_DECL_NOTHROW { return i >= other.i; }
+ inline bool operator==(const iterator &o) const noexcept { return i == o.i; }
+ inline bool operator!=(const iterator &o) const noexcept { return i != o.i; }
+ inline bool operator<(const iterator& other) const noexcept { return i < other.i; }
+ inline bool operator<=(const iterator& other) const noexcept { return i <= other.i; }
+ inline bool operator>(const iterator& other) const noexcept { return i > other.i; }
+ inline bool operator>=(const iterator& other) const noexcept { return i >= other.i; }
#ifndef QT_STRICT_ITERATORS
- inline bool operator==(const const_iterator &o) const Q_DECL_NOTHROW
+ inline bool operator==(const const_iterator &o) const noexcept
{ return i == o.i; }
- inline bool operator!=(const const_iterator &o) const Q_DECL_NOTHROW
+ inline bool operator!=(const const_iterator &o) const noexcept
{ return i != o.i; }
- inline bool operator<(const const_iterator& other) const Q_DECL_NOTHROW
+ inline bool operator<(const const_iterator& other) const noexcept
{ return i < other.i; }
- inline bool operator<=(const const_iterator& other) const Q_DECL_NOTHROW
+ inline bool operator<=(const const_iterator& other) const noexcept
{ return i <= other.i; }
- inline bool operator>(const const_iterator& other) const Q_DECL_NOTHROW
+ inline bool operator>(const const_iterator& other) const noexcept
{ return i > other.i; }
- inline bool operator>=(const const_iterator& other) const Q_DECL_NOTHROW
+ inline bool operator>=(const const_iterator& other) const noexcept
{ return i >= other.i; }
#endif
inline iterator &operator++() { ++i; return *this; }
@@ -284,27 +296,29 @@ public:
typedef const T *pointer;
typedef const T &reference;
- inline const_iterator() Q_DECL_NOTHROW : i(nullptr) {}
- inline const_iterator(Node *n) Q_DECL_NOTHROW : i(n) {}
+ inline const_iterator() noexcept : i(nullptr) {}
+ inline const_iterator(Node *n) noexcept : i(n) {}
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
// can't remove it in Qt 5, since doing so would make the type trivial,
// which changes the way it's passed to functions by value.
- inline const_iterator(const const_iterator &o) Q_DECL_NOTHROW : i(o.i) {}
+ inline const_iterator(const const_iterator &o) noexcept : i(o.i) {}
+ inline const_iterator &operator=(const const_iterator &o) noexcept
+ { i = o.i; return *this; }
#endif
#ifdef QT_STRICT_ITERATORS
- inline explicit const_iterator(const iterator &o) Q_DECL_NOTHROW : i(o.i) {}
+ inline explicit const_iterator(const iterator &o) noexcept : i(o.i) {}
#else
- inline const_iterator(const iterator &o) Q_DECL_NOTHROW : i(o.i) {}
+ inline const_iterator(const iterator &o) noexcept : i(o.i) {}
#endif
inline const T &operator*() const { return i->t(); }
inline const T *operator->() const { return &i->t(); }
inline const T &operator[](difference_type j) const { return i[j].t(); }
- inline bool operator==(const const_iterator &o) const Q_DECL_NOTHROW { return i == o.i; }
- inline bool operator!=(const const_iterator &o) const Q_DECL_NOTHROW { return i != o.i; }
- inline bool operator<(const const_iterator& other) const Q_DECL_NOTHROW { return i < other.i; }
- inline bool operator<=(const const_iterator& other) const Q_DECL_NOTHROW { return i <= other.i; }
- inline bool operator>(const const_iterator& other) const Q_DECL_NOTHROW { return i > other.i; }
- inline bool operator>=(const const_iterator& other) const Q_DECL_NOTHROW { return i >= other.i; }
+ inline bool operator==(const const_iterator &o) const noexcept { return i == o.i; }
+ inline bool operator!=(const const_iterator &o) const noexcept { return i != o.i; }
+ inline bool operator<(const const_iterator& other) const noexcept { return i < other.i; }
+ inline bool operator<=(const const_iterator& other) const noexcept { return i <= other.i; }
+ inline bool operator>(const const_iterator& other) const noexcept { return i > other.i; }
+ inline bool operator>=(const const_iterator& other) const noexcept { return i >= other.i; }
inline const_iterator &operator++() { ++i; return *this; }
inline const_iterator operator++(int) { Node *n = i; ++i; return n; }
inline const_iterator &operator--() { i--; return *this; }
@@ -322,19 +336,19 @@ public:
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
inline iterator begin() { detach(); return reinterpret_cast<Node *>(p.begin()); }
- inline const_iterator begin() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.begin()); }
- inline const_iterator cbegin() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.begin()); }
- inline const_iterator constBegin() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.begin()); }
+ inline const_iterator begin() const noexcept { return reinterpret_cast<Node *>(p.begin()); }
+ inline const_iterator cbegin() const noexcept { return reinterpret_cast<Node *>(p.begin()); }
+ inline const_iterator constBegin() const noexcept { return reinterpret_cast<Node *>(p.begin()); }
inline iterator end() { detach(); return reinterpret_cast<Node *>(p.end()); }
- inline const_iterator end() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.end()); }
- inline const_iterator cend() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.end()); }
- inline const_iterator constEnd() const Q_DECL_NOTHROW { return reinterpret_cast<Node *>(p.end()); }
+ inline const_iterator end() const noexcept { return reinterpret_cast<Node *>(p.end()); }
+ inline const_iterator cend() const noexcept { return reinterpret_cast<Node *>(p.end()); }
+ inline const_iterator constEnd() const noexcept { return reinterpret_cast<Node *>(p.end()); }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
- const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
iterator insert(iterator before, const T &t);
iterator erase(iterator pos);
iterator erase(iterator first, iterator last);
@@ -389,16 +403,22 @@ public:
inline QList<T> &operator<<(const QList<T> &l)
{ *this += l; return *this; }
+ static QList<T> fromVector(const QVector<T> &vector);
QVector<T> toVector() const;
- QSet<T> toSet() const;
- static QList<T> fromVector(const QVector<T> &vector);
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ Q_DECL_DEPRECATED_X("Use QList<T>(set.begin(), set.end()) instead.")
static QList<T> fromSet(const QSet<T> &set);
+ Q_DECL_DEPRECATED_X("Use QSet<T>(list.begin(), list.end()) instead.")
+ QSet<T> toSet() const;
+ Q_DECL_DEPRECATED_X("Use QList<T>(list.begin(), list.end()) instead.")
static inline QList<T> fromStdList(const std::list<T> &list)
- { QList<T> tmp; std::copy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; }
+ { return QList<T>(list.begin(), list.end()); }
+ Q_DECL_DEPRECATED_X("Use std::list<T>(list.begin(), list.end()) instead.")
inline std::list<T> toStdList() const
- { std::list<T> tmp; std::copy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
+ { return std::list<T>(begin(), end()); }
+#endif
private:
Node *detach_helper_grow(int i, int n);
@@ -411,7 +431,7 @@ private:
void node_copy(Node *from, Node *to, Node *src);
void node_destruct(Node *from, Node *to);
- bool isValidIterator(const iterator &i) const Q_DECL_NOTHROW
+ bool isValidIterator(const iterator &i) const noexcept
{
const std::less<const Node *> less = {};
return !less(i.i, cbegin().i) && !less(cend().i, i.i);
@@ -514,7 +534,7 @@ inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t)
Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid");
int iBefore = int(before.i - reinterpret_cast<Node *>(p.begin()));
- Node *n = 0;
+ Node *n = nullptr;
if (d->ref.isShared())
n = detach_helper_grow(iBefore, 1);
else
@@ -689,12 +709,12 @@ inline void QList<T>::replace(int i, const T &t)
}
template <typename T>
-inline void QList<T>::swap(int i, int j)
+inline void QList<T>::swapItemsAt(int i, int j)
{
Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(),
"QList<T>::swap", "index out of range");
detach();
- std::swap(d->array[d->begin + i], d->array[d->begin + j]);
+ qSwap(d->array[d->begin + i], d->array[d->begin + j]);
}
template <typename T>
@@ -831,6 +851,15 @@ Q_OUTOFLINE_TEMPLATE QList<T>::~QList()
}
template <typename T>
+template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator>>
+QList<T>::QList(InputIterator first, InputIterator last)
+ : QList()
+{
+ QtPrivate::reserveIfForwardIterator(this, first, last);
+ std::copy(first, last, std::back_inserter(*this));
+}
+
+template <typename T>
Q_OUTOFLINE_TEMPLATE bool QList<T>::operator==(const QList<T> &l) const
{
if (d == l.d)
@@ -970,35 +999,57 @@ inline void QList<T>::append(const QList<T> &t)
template <typename T>
Q_OUTOFLINE_TEMPLATE int QList<T>::indexOf(const T &t, int from) const
{
+ return QtPrivate::indexOf<T, T>(*this, t, from);
+}
+
+namespace QtPrivate
+{
+template <typename T, typename U>
+int indexOf(const QList<T> &list, const U &u, int from)
+{
+ typedef typename QList<T>::Node Node;
+
if (from < 0)
- from = qMax(from + p.size(), 0);
- if (from < p.size()) {
- Node *n = reinterpret_cast<Node *>(p.at(from -1));
- Node *e = reinterpret_cast<Node *>(p.end());
+ from = qMax(from + list.p.size(), 0);
+ if (from < list.p.size()) {
+ Node *n = reinterpret_cast<Node *>(list.p.at(from -1));
+ Node *e = reinterpret_cast<Node *>(list.p.end());
while (++n != e)
- if (n->t() == t)
- return int(n - reinterpret_cast<Node *>(p.begin()));
+ if (n->t() == u)
+ return int(n - reinterpret_cast<Node *>(list.p.begin()));
}
return -1;
}
+}
template <typename T>
Q_OUTOFLINE_TEMPLATE int QList<T>::lastIndexOf(const T &t, int from) const
{
+ return QtPrivate::lastIndexOf<T, T>(*this, t, from);
+}
+
+namespace QtPrivate
+{
+template <typename T, typename U>
+int lastIndexOf(const QList<T> &list, const U &u, int from)
+{
+ typedef typename QList<T>::Node Node;
+
if (from < 0)
- from += p.size();
- else if (from >= p.size())
- from = p.size()-1;
+ from += list.p.size();
+ else if (from >= list.p.size())
+ from = list.p.size()-1;
if (from >= 0) {
- Node *b = reinterpret_cast<Node *>(p.begin());
- Node *n = reinterpret_cast<Node *>(p.at(from + 1));
+ Node *b = reinterpret_cast<Node *>(list.p.begin());
+ Node *n = reinterpret_cast<Node *>(list.p.at(from + 1));
while (n-- != b) {
- if (n->t() == t)
+ if (n->t() == u)
return n - b;
}
}
return -1;
}
+}
template <typename T>
Q_OUTOFLINE_TEMPLATE bool QList<T>::contains(const T &t) const
@@ -1051,19 +1102,43 @@ inline int QList<T>::count_impl(const T &t, QListData::ArrayCompatibleLayout) co
t));
}
+template <typename T>
+Q_OUTOFLINE_TEMPLATE QVector<T> QList<T>::toVector() const
+{
+ return QVector<T>(begin(), end());
+}
+
+template <typename T>
+QList<T> QList<T>::fromVector(const QVector<T> &vector)
+{
+ return vector.toList();
+}
+
+template <typename T>
+Q_OUTOFLINE_TEMPLATE QList<T> QVector<T>::toList() const
+{
+ return QList<T>(begin(), end());
+}
+
+template <typename T>
+QVector<T> QVector<T>::fromList(const QList<T> &list)
+{
+ return list.toVector();
+}
+
Q_DECLARE_SEQUENTIAL_ITERATOR(List)
Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List)
template <typename T>
uint qHash(const QList<T> &key, uint seed = 0)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHashRange(key.cbegin(), key.cend(), seed)))
+ noexcept(noexcept(qHashRange(key.cbegin(), key.cend(), seed)))
{
return qHashRange(key.cbegin(), key.cend(), seed);
}
template <typename T>
bool operator<(const QList<T> &lhs, const QList<T> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
+ noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end())))
{
return std::lexicographical_compare(lhs.begin(), lhs.end(),
@@ -1072,21 +1147,21 @@ bool operator<(const QList<T> &lhs, const QList<T> &rhs)
template <typename T>
inline bool operator>(const QList<T> &lhs, const QList<T> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
+ noexcept(noexcept(lhs < rhs))
{
return rhs < lhs;
}
template <typename T>
inline bool operator<=(const QList<T> &lhs, const QList<T> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
+ noexcept(noexcept(lhs < rhs))
{
return !(lhs > rhs);
}
template <typename T>
inline bool operator>=(const QList<T> &lhs, const QList<T> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
+ noexcept(noexcept(lhs < rhs))
{
return !(lhs < rhs);
}
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 506b32a257..939f8eb34d 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -55,7 +55,7 @@
#include "qlocale_p.h"
#include "qlocale_tools_p.h"
#if QT_CONFIG(datetimeparser)
-#include "qdatetimeparser_p.h"
+#include "private/qdatetimeparser_p.h"
#endif
#include "qnamespace.h"
#include "qdatetime.h"
@@ -94,7 +94,7 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qlocale_data_p.h"
QT_END_INCLUDE_NAMESPACE
-QLocale::Language QLocalePrivate::codeToLanguage(QStringView code) Q_DECL_NOTHROW
+QLocale::Language QLocalePrivate::codeToLanguage(QStringView code) noexcept
{
const auto len = code.size();
if (len != 2 && len != 3)
@@ -138,7 +138,7 @@ QLocale::Language QLocalePrivate::codeToLanguage(QStringView code) Q_DECL_NOTHRO
return QLocale::C;
}
-QLocale::Script QLocalePrivate::codeToScript(QStringView code) Q_DECL_NOTHROW
+QLocale::Script QLocalePrivate::codeToScript(QStringView code) noexcept
{
const auto len = code.size();
if (len != 4)
@@ -158,7 +158,7 @@ QLocale::Script QLocalePrivate::codeToScript(QStringView code) Q_DECL_NOTHROW
return QLocale::AnyScript;
}
-QLocale::Country QLocalePrivate::codeToCountry(QStringView code) Q_DECL_NOTHROW
+QLocale::Country QLocalePrivate::codeToCountry(QStringView code) noexcept
{
const auto len = code.size();
if (len != 2 && len != 3)
@@ -301,9 +301,9 @@ QByteArray QLocaleId::name(char separator) const
const unsigned char *lang = language_code_list + 3 * language_id;
const unsigned char *script =
- (script_id != QLocale::AnyScript ? script_code_list + 4 * script_id : 0);
+ (script_id != QLocale::AnyScript ? script_code_list + 4 * script_id : nullptr);
const unsigned char *country =
- (country_id != QLocale::AnyCountry ? country_code_list + 3 * country_id : 0);
+ (country_id != QLocale::AnyCountry ? country_code_list + 3 * country_id : nullptr);
char len = (lang[2] != 0 ? 3 : 2) + (script ? 4+1 : 0) + (country ? (country[2] != 0 ? 3 : 2)+1 : 0);
QByteArray name(len, Qt::Uninitialized);
char *uc = name.data();
@@ -373,7 +373,7 @@ static const QLocaleData *findLocaleDataById(const QLocaleId &localeId)
} while (data->m_language_id && data->m_language_id == localeId.language_id);
}
- return 0;
+ return nullptr;
}
const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLocale::Script script, QLocale::Country country)
@@ -604,7 +604,7 @@ int qt_repeatCount(QStringView s)
return int(j);
}
-static const QLocaleData *default_data = 0;
+static const QLocaleData *default_data = nullptr;
static QLocale::NumberOptions default_number_options = QLocale::DefaultNumberOptions;
static const QLocaleData *const c_data = locale_data;
@@ -620,13 +620,18 @@ static QLocalePrivate *c_private()
*/
/*!
- Constructs a QSystemLocale object. The constructor will automatically
- install this object as the system locale and remove any earlier installed
- system locales.
+ Constructs a QSystemLocale object.
+
+ The constructor will automatically install this object as the system locale,
+ if there's not one active. It also resets the flag that'll prompt
+ QLocale::system() to re-initialize its data, so that instantiating a
+ QSystemLocale transiently (doesn't install the transient as system locale if
+ there was one already and) triggers an update to the system locale's data.
*/
QSystemLocale::QSystemLocale()
{
- _systemLocale = this;
+ if (!_systemLocale)
+ _systemLocale = this;
globalLocaleData.m_language_id = 0;
}
@@ -656,15 +661,17 @@ static const QSystemLocale *systemLocale()
return QSystemLocale_globalSystemLocale();
}
-void QLocalePrivate::updateSystemPrivate()
+static void updateSystemPrivate()
{
- // this function is NOT thread-safe!
+ // This function is NOT thread-safe!
+ // It *should not* be called by anything but systemData()
const QSystemLocale *sys_locale = systemLocale();
// tell the object that the system locale has changed.
sys_locale->query(QSystemLocale::LocaleChanged, QVariant());
- globalLocaleData = *sys_locale->fallbackUiLocale().d->m_data;
+ // Populate global with fallback as basis:
+ globalLocaleData = *sys_locale->fallbackUiLocaleData();
QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant());
if (!res.isNull()) {
@@ -715,7 +722,7 @@ static const QLocaleData *systemData()
static QBasicMutex systemDataMutex;
systemDataMutex.lock();
if (globalLocaleData.m_language_id == 0)
- QLocalePrivate::updateSystemPrivate();
+ updateSystemPrivate();
systemDataMutex.unlock();
}
@@ -975,7 +982,7 @@ bool QLocale::operator!=(const QLocale &other) const
Returns the hash value for \a key, using
\a seed to seed the calculation.
*/
-uint qHash(const QLocale &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QLocale &key, uint seed) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.d->m_data);
@@ -1180,9 +1187,7 @@ static qulonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool
template <typename T> static inline
T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok)
{
- // ### Qt6: use std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type
- const bool isUnsigned = T(0) < T(-1);
- typedef typename QtPrivate::QConditional<isUnsigned, qulonglong, qlonglong>::Type Int64;
+ using Int64 = typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type;
// we select the right overload by the last, unused parameter
Int64 val = toIntegral_helper(d->m_data, str, ok, d->m_numberOptions, Int64());
@@ -1260,7 +1265,7 @@ QString QLocale::scriptToString(QLocale::Script script)
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1278,7 +1283,7 @@ short QLocale::toShort(const QString &s, bool *ok) const
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1296,7 +1301,7 @@ ushort QLocale::toUShort(const QString &s, bool *ok) const
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1314,7 +1319,7 @@ int QLocale::toInt(const QString &s, bool *ok) const
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1328,11 +1333,53 @@ uint QLocale::toUInt(const QString &s, bool *ok) const
}
/*!
+ Returns the long int represented by the localized string \a s.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toInt(), toULong(), toDouble(), toString()
+
+ \since 5.13
+ */
+
+
+long QLocale::toLong(const QString &s, bool *ok) const
+{
+ return toIntegral_helper<long>(d, s, ok);
+}
+
+/*!
+ Returns the unsigned long int represented by the localized
+ string \a s.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toLong(), toInt(), toDouble(), toString()
+
+ \since 5.13
+*/
+
+ulong QLocale::toULong(const QString &s, bool *ok) const
+{
+ return toIntegral_helper<ulong>(d, s, ok);
+}
+
+/*!
Returns the long long int represented by the localized string \a s.
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1352,7 +1399,7 @@ qlonglong QLocale::toLongLong(const QString &s, bool *ok) const
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1371,7 +1418,7 @@ qulonglong QLocale::toULongLong(const QString &s, bool *ok) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for any other reason (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function does not fall back to the 'C' locale if the string
@@ -1393,7 +1440,7 @@ float QLocale::toFloat(const QString &s, bool *ok) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for any other reason (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function does not fall back to the 'C' locale if the string
@@ -1419,7 +1466,7 @@ double QLocale::toDouble(const QString &s, bool *ok) const
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1439,7 +1486,7 @@ short QLocale::toShort(const QStringRef &s, bool *ok) const
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1459,7 +1506,7 @@ ushort QLocale::toUShort(const QStringRef &s, bool *ok) const
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1479,7 +1526,7 @@ int QLocale::toInt(const QStringRef &s, bool *ok) const
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1495,11 +1542,53 @@ uint QLocale::toUInt(const QStringRef &s, bool *ok) const
}
/*!
+ Returns the long int represented by the localized string \a s.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toInt(), toULong(), toDouble(), toString()
+
+ \since 5.13
+ */
+
+
+long QLocale::toLong(const QStringRef &s, bool *ok) const
+{
+ return toIntegral_helper<long>(d, s, ok);
+}
+
+/*!
+ Returns the unsigned long int represented by the localized
+ string \a s.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toLong(), toInt(), toDouble(), toString()
+
+ \since 5.13
+ */
+
+ulong QLocale::toULong(const QStringRef &s, bool *ok) const
+{
+ return toIntegral_helper<ulong>(d, s, ok);
+}
+
+/*!
Returns the long long int represented by the localized string \a s.
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1521,7 +1610,7 @@ qlonglong QLocale::toLongLong(const QStringRef &s, bool *ok) const
If the conversion fails the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1542,7 +1631,7 @@ qulonglong QLocale::toULongLong(const QStringRef &s, bool *ok) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for any other reason (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function does not fall back to the 'C' locale if the string
@@ -1566,7 +1655,7 @@ float QLocale::toFloat(const QStringRef &s, bool *ok) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for any other reason (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function does not fall back to the 'C' locale if the string
@@ -1595,7 +1684,7 @@ double QLocale::toDouble(const QStringRef &s, bool *ok) const
If the conversion fails, the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1615,7 +1704,7 @@ short QLocale::toShort(QStringView s, bool *ok) const
If the conversion fails, the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1635,7 +1724,7 @@ ushort QLocale::toUShort(QStringView s, bool *ok) const
If the conversion fails, the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1655,7 +1744,7 @@ int QLocale::toInt(QStringView s, bool *ok) const
If the conversion fails, the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1671,11 +1760,53 @@ uint QLocale::toUInt(QStringView s, bool *ok) const
}
/*!
+ Returns the long int represented by the localized string \a s.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toInt(), toULong(), toDouble(), toString()
+
+ \since 5.13
+ */
+
+
+long QLocale::toLong(QStringView s, bool *ok) const
+{
+ return toIntegral_helper<long>(d, s, ok);
+}
+
+/*!
+ Returns the unsigned long int represented by the localized
+ string \a s.
+
+ If the conversion fails the function returns 0.
+
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
+ to \c false, and success by setting *\a{ok} to \c true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toLong(), toInt(), toDouble(), toString()
+
+ \since 5.13
+ */
+
+ulong QLocale::toULong(QStringView s, bool *ok) const
+{
+ return toIntegral_helper<ulong>(d, s, ok);
+}
+
+/*!
Returns the long long int represented by the localized string \a s.
If the conversion fails, the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1697,7 +1828,7 @@ qlonglong QLocale::toLongLong(QStringView s, bool *ok) const
If the conversion fails, the function returns 0.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1718,7 +1849,7 @@ qulonglong QLocale::toULongLong(QStringView s, bool *ok) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for any other reason (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
This function ignores leading and trailing whitespace.
@@ -1739,7 +1870,7 @@ float QLocale::toFloat(QStringView s, bool *ok) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for any other reason (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
Unlike QString::toDouble(), this function does not fall back to
@@ -2376,7 +2507,6 @@ QString QLocale::toString(double i, char f, int prec) const
QLocale QLocale::system()
{
- // this function is NOT thread-safe!
QT_PREPEND_NAMESPACE(systemData)(); // trigger updating of the system data if necessary
if (systemLocalePrivate.isDestroyed())
return QLocale(QLocale::C);
@@ -3902,6 +4032,19 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci
\sa formattedDataSize()
*/
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \obsolete
+
+ Use the const version instead.
+*/
+QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format)
+{
+ const auto *that = this;
+ return that->formattedDataSize(bytes, precision, format);
+}
+#endif
+
/*!
\since 5.10
@@ -3918,7 +4061,7 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci
whereas \c DataSizeSIFormat uses the older SI quantifiers k, M, etc., and
\c DataSizeTraditionalFormat abuses them.
*/
-QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format)
+QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) const
{
int power, base = 1000;
if (!bytes) {
@@ -4000,6 +4143,29 @@ QStringList QLocale::uiLanguages() const
}
/*!
+ \since 5.13
+
+ Returns the locale to use for collation.
+
+ The result is usually this locale; however, the system locale (which is
+ commonly the default locale) will return the system collation locale.
+ The result is suitable for passing to QCollator's constructor.
+
+ \sa QCollator
+*/
+QLocale QLocale::collation() const
+{
+#ifndef QT_NO_SYSTEMLOCALE
+ if (d->m_data == systemData()) {
+ QString res = systemLocale()->query(QSystemLocale::Collation, QVariant()).toString();
+ if (!res.isEmpty())
+ return QLocale(res);
+ }
+#endif
+ return *this;
+}
+
+/*!
\since 4.8
Returns a native name of the language for the locale. For example
diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h
index f3afb8c406..09de830ca3 100644
--- a/src/corelib/tools/qlocale.h
+++ b/src/corelib/tools/qlocale.h
@@ -59,7 +59,7 @@ class QTextStreamPrivate;
class QLocalePrivate;
-Q_CORE_EXPORT uint qHash(const QLocale &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT uint qHash(const QLocale &key, uint seed = 0) noexcept;
class Q_CORE_EXPORT QLocale
{
@@ -436,6 +436,13 @@ public:
Cantonese = 357,
Osage = 358,
Tangut = 359,
+ Ido = 360,
+ Lojban = 361,
+ Sicilian = 362,
+ SouthernKurdish = 363,
+ WesternBalochi = 364,
+ Cebuano = 365,
+ Erzya = 366,
Afan = Oromo,
Bhutani = Dzongkha,
@@ -452,7 +459,7 @@ public:
Twi = Akan,
Uigur = Uighur,
- LastLanguage = Tangut
+ LastLanguage = Erzya
};
enum Script {
@@ -934,13 +941,11 @@ public:
QLocale(Language language, Country country = AnyCountry);
QLocale(Language language, Script script, Country country);
QLocale(const QLocale &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QLocale &operator=(QLocale &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QLocale &operator=(QLocale &&other) noexcept { swap(other); return *this; }
QLocale &operator=(const QLocale &other);
~QLocale();
- void swap(QLocale &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QLocale &other) noexcept { qSwap(d, other.d); }
Language language() const;
Script script() const;
@@ -956,6 +961,8 @@ public:
ushort toUShort(const QString &s, bool *ok = nullptr) const;
int toInt(const QString &s, bool *ok = nullptr) const;
uint toUInt(const QString &s, bool *ok = nullptr) const;
+ long toLong(const QString &s, bool *ok = nullptr) const;
+ ulong toULong(const QString &s, bool *ok = nullptr) const;
qlonglong toLongLong(const QString &s, bool *ok = nullptr) const;
qulonglong toULongLong(const QString &s, bool *ok = nullptr) const;
float toFloat(const QString &s, bool *ok = nullptr) const;
@@ -965,6 +972,8 @@ public:
ushort toUShort(const QStringRef &s, bool *ok = nullptr) const;
int toInt(const QStringRef &s, bool *ok = nullptr) const;
uint toUInt(const QStringRef &s, bool *ok = nullptr) const;
+ long toLong(const QStringRef &s, bool *ok = nullptr) const;
+ ulong toULong(const QStringRef &s, bool *ok = nullptr) const;
qlonglong toLongLong(const QStringRef &s, bool *ok = nullptr) const;
qulonglong toULongLong(const QStringRef &s, bool *ok = nullptr) const;
float toFloat(const QStringRef &s, bool *ok = nullptr) const;
@@ -975,6 +984,8 @@ public:
ushort toUShort(QStringView s, bool *ok = nullptr) const;
int toInt(QStringView s, bool *ok = nullptr) const;
uint toUInt(QStringView s, bool *ok = nullptr) const;
+ long toLong(QStringView s, bool *ok = nullptr) const;
+ ulong toULong(QStringView s, bool *ok = nullptr) const;
qlonglong toLongLong(QStringView s, bool *ok = nullptr) const;
qulonglong toULongLong(QStringView s, bool *ok = nullptr) const;
float toFloat(QStringView s, bool *ok = nullptr) const;
@@ -982,6 +993,8 @@ public:
QString toString(qlonglong i) const;
QString toString(qulonglong i) const;
+ inline QString toString(long i) const;
+ inline QString toString(ulong i) const;
inline QString toString(short i) const;
inline QString toString(ushort i) const;
inline QString toString(int i) const;
@@ -1035,7 +1048,7 @@ public:
QString pmText() const;
MeasurementSystem measurementSystem() const;
-
+ QLocale collation() const;
Qt::LayoutDirection textDirection() const;
QString toUpper(const QString &str) const;
@@ -1061,7 +1074,10 @@ public:
{ return toCurrencyString(double(i), symbol, precision); }
#endif
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QString formattedDataSize(qint64 bytes, int precision = 2, DataSizeFormats format = DataSizeIecFormat);
+#endif
+ QString formattedDataSize(qint64 bytes, int precision = 2, DataSizeFormats format = DataSizeIecFormat) const;
QStringList uiLanguages() const;
@@ -1091,13 +1107,18 @@ public:
private:
QLocale(QLocalePrivate &dd);
friend class QLocalePrivate;
- friend Q_CORE_EXPORT uint qHash(const QLocale &key, uint seed) Q_DECL_NOTHROW;
+ friend class QSystemLocale;
+ friend Q_CORE_EXPORT uint qHash(const QLocale &key, uint seed) noexcept;
QSharedDataPointer<QLocalePrivate> d;
};
Q_DECLARE_SHARED(QLocale)
Q_DECLARE_OPERATORS_FOR_FLAGS(QLocale::NumberOptions)
+inline QString QLocale::toString(long i) const
+ { return toString(qlonglong(i)); }
+inline QString QLocale::toString(ulong i) const
+ { return toString(qulonglong(i)); }
inline QString QLocale::toString(short i) const
{ return toString(qlonglong(i)); }
inline QString QLocale::toString(ushort i) const
diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc
index afc9bb6e21..426cb9dbeb 100644
--- a/src/corelib/tools/qlocale.qdoc
+++ b/src/corelib/tools/qlocale.qdoc
@@ -105,42 +105,81 @@
\value AnyLanguage
\value C A simplified English locale; see QLocale::c()
+
\value Abkhazian
- \value Oromo
\value Afan Obsolete, please use Oromo
\value Afar
\value Afrikaans
+ \value Aghem
+ \value Ahom Since Qt 5.7
+ \value Akan
+ \value Akkadian Since Qt 5.1
\value Akoose Since Qt 5.3
\value Albanian
+ \value AmericanSignLanguage Since Qt 5.7
\value Amharic
+ \value AncientEgyptian Since Qt 5.1
+ \value AncientGreek Since Qt 5.1
+ \value AncientNorthArabian Since Qt 5.5
\value Arabic
+ \value Aragonese Since Qt 5.1
+ \value Aramaic Since Qt 5.1
+ \value ArdhamagadhiPrakrit Since Qt 5.7
\value Armenian
\value Assamese
+ \value Asturian
+ \value Asu
+ \value Atsam
\value Avaric
+ \value Avestan
\value Aymara
\value Azerbaijani
+ \value Bafia
+ \value Balinese Since Qt 5.1
+ \value Bambara
+ \value Bamun Since Qt 5.1
+ \value Basaa
\value Bashkir
\value Basque
+ \value Bassa Since Qt 5.5
+ \value BatakToba Since Qt 5.1
+ \value Belarusian
+ \value Bemba
+ \value Bena
\value Bengali
- \value Dzongkha
+ \value Bhojpuri Since Qt 5.7
\value Bhutani Obsolete, please use Dzongkha
\value Bihari
\value Bislama
- \value Bosnian
+ \value Blin
\value Bodo
+ \value Bosnian
\value Breton
+ \value Buginese Since Qt 5.1
+ \value Buhid Since Qt 5.1
\value Bulgarian
\value Burmese
- \value Belarusian
\value Byelorussian Obsolete, please use Belarusian
- \value Khmer
\value Cambodian Obsolete, please use Khmer
+ \value Cantonese Since Qt 5.7
+ \value Carian Since Qt 5.1
\value Catalan
+ \value Cebuano Since Qt 5.14
+ \value CentralKurdish Since Qt 5.5
+ \value CentralMoroccoTamazight
+ \value Chakma Since Qt 5.1
\value Chamorro
\value Chechen
+ \value Cherokee
+ \value Chewa Obsolete, please use Nyanja
+ \value Chiga
\value Chinese
\value Church
\value Chuvash
+ \value ClassicalMandaic Since Qt 5.1
+ \value Colognian
+ \value CongoSwahili
+ \value Coptic Since Qt 5.1
\value Cornish
\value Corsican
\value Cree
@@ -148,33 +187,59 @@
\value Czech
\value Danish
\value Divehi
+ \value Dogri Since Qt 5.1
+ \value Duala
\value Dutch
+ \value Dzongkha
+ \value EasternCham Since Qt 5.1
+ \value EasternKayah Since Qt 5.1
+ \value Embu
\value English
+ \value Erzya Since Qt 5.14
\value Esperanto
\value Estonian
+ \value Etruscan Since Qt 5.1
+ \value Ewe
+ \value Ewondo
\value Faroese
\value Fijian
+ \value Filipino
\value Finnish
\value French
- \value WesternFrisian same as Frisian
\value Frisian same as WesternFrisian
+ \value Friulian
+ \value Fulah
+ \value Ga
\value Gaelic
\value Galician
+ \value Ganda
+ \value Geez
\value Georgian
\value German
+ \value Gothic Since Qt 5.1
\value Greek
\value Greenlandic
\value Guarani
\value Gujarati
+ \value Gusii
\value Haitian
+ \value Hanunoo Since Qt 5.1
\value Hausa
+ \value Hawaiian
\value Hebrew
\value Herero
+ \value HieroglyphicLuwian Since Qt 5.7
\value Hindi
\value HiriMotu
+ \value HmongNjua Since Qt 5.5
+ \value Ho Since Qt 5.5
\value Hungarian
\value Icelandic
+ \value Ido Since Qt 5.12
+ \value Igbo
+ \value InariSami Since Qt 5.5
\value Indonesian
+ \value Ingush Since Qt 5.1
\value Interlingua
\value Interlingue
\value Inuktitut
@@ -183,306 +248,244 @@
\value Italian
\value Japanese
\value Javanese
+ \value Jju
+ \value JolaFonyi
+ \value Kabuverdianu
+ \value Kabyle
+ \value Kako
+ \value Kalenjin
+ \value Kamba
\value Kannada
\value Kanuri
\value Kashmiri
\value Kazakh
+ \value Kenyang Since Qt 5.5
+ \value Khmer
+ \value Kiche Since Qt 5.5
+ \value Kikuyu
\value Kinyarwanda
\value Kirghiz
\value Komi
\value Kongo
+ \value Konkani
\value Korean
+ \value Koro
+ \value KoyraboroSenni
+ \value KoyraChiini
+ \value Kpelle
\value Kurdish
- \value Rundi
\value Kurundi Obsolete, please use Rundi
\value Kwanyama
+ \value Kwasio
\value Lakota Since Qt 5.3
+ \value Langi
\value Lao
+ \value LargeFloweryMiao Since Qt 5.1
\value Latin
\value Latvian
+ \value Lepcha Since Qt 5.1
+ \value Lezghian Since Qt 5.5
\value Limburgish
+ \value Limbu Since Qt 5.1
+ \value LinearA Since Qt 5.5
\value Lingala
+ \value Lisu Since Qt 5.1
+ \value LiteraryChinese Since Qt 5.7
\value Lithuanian
+ \value Lojban Since Qt 5.12
+ \value LowerSorbian Since Qt 5.5
+ \value LowGerman
\value LubaKatanga
+ \value LuleSami Since Qt 5.5
+ \value Luo
+ \value Lu Since Qt 5.1
\value Luxembourgish
- \value Marshallese
+ \value Luyia
+ \value Lycian Since Qt 5.1
+ \value Lydian Since Qt 5.1
\value Macedonian
+ \value Machame
+ \value Maithili Since Qt 5.5
+ \value MakhuwaMeetto
+ \value Makonde
\value Malagasy
\value Malay
\value Malayalam
\value Maltese
+ \value Mandingo Since Qt 5.1
+ \value ManichaeanMiddlePersian Since Qt 5.5
+ \value Manipuri Since Qt 5.1
\value Manx
\value Maori
+ \value Mapuche Since Qt 5.5
\value Marathi
+ \value Marshallese
+ \value Masai
+ \value Mazanderani Since Qt 5.7
+ \value Mende Since Qt 5.5
+ \value Meroitic Since Qt 5.1
+ \value Meru
+ \value Meta
+ \value Mohawk Since Qt 5.5
\value Moldavian Obsolete, please use Romanian
\value Mongolian
+ \value Mono Since Qt 5.5
+ \value Morisyen
+ \value Mru Since Qt 5.7
+ \value Mundang
+ \value Nama
\value NauruLanguage
\value Navaho
\value Ndonga
\value Nepali
- \value Norwegian same as NorwegianBokmal
+ \value Newari Since Qt 5.7
+ \value Ngiemboon
+ \value Ngomba
+ \value Nko Since Qt 5.5
+ \value NorthernLuri Since Qt 5.7
+ \value NorthernSami
+ \value NorthernSotho
+ \value NorthernThai Since Qt 5.1
+ \value NorthNdebele
\value NorwegianBokmal same as Norwegian
\value NorwegianNynorsk
+ \value Norwegian same as NorwegianBokmal
+ \value Nuer
+ \value Nyanja
+ \value Nyankole
\value Occitan
\value Ojibwa
+ \value OldIrish Since Qt 5.1
+ \value OldNorse Since Qt 5.1
+ \value OldPersian Since Qt 5.1
+ \value OldTurkish Since Qt 5.1
\value Oriya
+ \value Oromo
+ \value Osage Since Qt 5.7
\value Ossetic
+ \value Pahlavi Since Qt 5.1
+ \value Palauan Since Qt 5.7
\value Pali
+ \value Papiamento Since Qt 5.7
+ \value Parthian Since Qt 5.1
\value Pashto
\value Persian
+ \value Phoenician Since Qt 5.1
\value Polish
\value Portuguese
+ \value PrakritLanguage Since Qt 5.1
+ \value Prussian Since Qt 5.5
\value Punjabi
\value Quechua
- \value Romansh
+ \value Rejang Since Qt 5.1
\value RhaetoRomance Obsolete, please use Romansh
\value Romanian
+ \value Romansh
+ \value Rombo
+ \value Rundi
\value Russian
+ \value Rwa
+ \value Sabaean Since Qt 5.1
+ \value Saho
+ \value Sakha
+ \value Samaritan Since Qt 5.1
+ \value Samburu
\value Samoan
\value Sango
+ \value Sangu
\value Sanskrit
+ \value Santali Since Qt 5.1
+ \value Saraiki Since Qt 5.7
\value Sardinian
+ \value Saurashtra Since Qt 5.1
+ \value Sena
\value Serbian
\value SerboCroatian Obsolete, please use Serbian
- \value SouthernSotho
- \value Tswana
+ \value Shambala
\value Shona
+ \value SichuanYi
+ \value Sicilian Since Qt 5.12
+ \value Sidamo
\value Sindhi
\value Sinhala
- \value Swati
+ \value SkoltSami Since Qt 5.5
\value Slovak
\value Slovenian
+ \value Soga
\value Somali
+ \value Sora Since Qt 5.1
+ \value SouthernKurdish Since Qt 5.12
+ \value SouthernSami Since Qt 5.5
+ \value SouthernSotho
+ \value SouthNdebele
\value Spanish
\value StandardMoroccanTamazight Since Qt 5.3
\value Sundanese
\value Swahili
+ \value Swati
\value Swedish
+ \value SwissGerman
+ \value Sylheti Since Qt 5.1
+ \value Syriac
+ \value Tachelhit
\value Tagalog Obsolete, please use Filipino
+ \value Tagbanwa Since Qt 5.1
\value Tahitian
+ \value TaiDam Since Qt 5.1
+ \value TaiNua Since Qt 5.1
+ \value Taita
\value Tajik
\value Tamil
+ \value Tangut Since Qt 5.7
+ \value Taroko
+ \value Tasawaq
\value Tatar
+ \value TedimChin Since Qt 5.5
\value Telugu
+ \value Teso
\value Thai
\value Tibetan
+ \value Tigre
\value Tigrinya
+ \value TokelauLanguage Since Qt 5.7
+ \value TokPisin Since Qt 5.7
\value Tongan
\value Tsonga
+ \value Tswana
\value Turkish
\value Turkmen
+ \value TuvaluLanguage Since Qt 5.7
\value Twi Obsolete, please use Akan
+ \value Tyap
+ \value Ugaritic Since Qt 5.1
\value Uighur
\value Uigur Obsolete, please use Uighur
\value Ukrainian
+ \value UncodedLanguages Since Qt 5.7
+ \value UpperSorbian Since Qt 5.5
\value Urdu
\value Uzbek
+ \value Vai
+ \value Venda
\value Vietnamese
\value Volapuk
+ \value Vunjo
+ \value Walamo
\value Walloon
+ \value Walser
+ \value Warlpiri Since Qt 5.5
\value Welsh
+ \value WesternBalochi Since Qt 5.12
+ \value WesternFrisian same as Frisian
\value Wolof
\value Xhosa
+ \value Yangben
\value Yiddish
\value Yoruba
+ \value Zarma
\value Zhuang
\value Zulu
- \value Bosnian
- \value Divehi
- \value Manx
- \value Cornish
- \value Akan
- \value Konkani
- \value Ga
- \value Igbo
- \value Kamba
- \value Syriac
- \value Blin
- \value Geez
- \value Koro
- \value Sidamo
- \value Atsam
- \value Tigre
- \value Jju
- \value Friulian
- \value Venda
- \value Ewe
- \value Walamo
- \value Hawaiian
- \value Tyap
- \value Nyanja
- \value Chewa Obsolete, please use Nyanja
- \value Filipino
- \value SwissGerman
- \value SichuanYi
- \value Kpelle
- \value LowGerman
- \value SouthNdebele
- \value NorthernSotho
- \value NorthernSami
- \value Taroko
- \value Gusii
- \value Taita
- \value Fulah
- \value Kikuyu
- \value Samburu
- \value Sena
- \value NorthNdebele
- \value Rombo
- \value Tachelhit
- \value Kabyle
- \value Nyankole
- \value Bena
- \value Vunjo
- \value Bambara
- \value Embu
- \value Cherokee
- \value Morisyen
- \value Makonde
- \value Langi
- \value Ganda
- \value Bemba
- \value Kabuverdianu
- \value Meru
- \value Kalenjin
- \value Nama
- \value Machame
- \value Colognian
- \value Masai
- \value Soga
- \value Luyia
- \value Asu
- \value Teso
- \value Saho
- \value KoyraChiini
- \value Rwa
- \value Luo
- \value Chiga
- \value CentralMoroccoTamazight
- \value KoyraboroSenni
- \value Shambala
- \value Aghem
- \value Basaa
- \value Zarma
- \value Duala
- \value JolaFonyi
- \value Ewondo
- \value Bafia
- \value MakhuwaMeetto
- \value Mundang
- \value Kwasio
- \value Nuer
- \value Sakha
- \value Sangu
- \value CongoSwahili
- \value Tasawaq
- \value Vai
- \value Walser
- \value Yangben
- \value Avestan
- \value Asturian
- \value Ngomba
- \value Kako
- \value Meta
- \value Ngiemboon
- \value Aragonese
- \value Akkadian
- \value AncientEgyptian
- \value AncientGreek
- \value Aramaic
- \value Balinese
- \value Bamun
- \value BatakToba
- \value Buginese
- \value Buhid
- \value Carian
- \value Chakma
- \value ClassicalMandaic
- \value Coptic
- \value Dogri
- \value EasternCham
- \value EasternKayah
- \value Etruscan
- \value Gothic
- \value Hanunoo
- \value Ingush
- \value LargeFloweryMiao
- \value Lepcha
- \value Limbu
- \value Lisu
- \value Lu
- \value Lycian
- \value Lydian
- \value Mandingo
- \value Manipuri
- \value Meroitic
- \value NorthernThai
- \value OldIrish
- \value OldNorse
- \value OldPersian
- \value OldTurkish
- \value Pahlavi
- \value Parthian
- \value Phoenician
- \value PrakritLanguage
- \value Rejang
- \value Sabaean
- \value Samaritan
- \value Santali
- \value Saurashtra
- \value Sora
- \value Sylheti
- \value Tagbanwa
- \value TaiDam
- \value TaiNua
- \value Ugaritic
- \value Mapuche Since Qt 5.5
- \value CentralKurdish Since Qt 5.5
- \value LowerSorbian Since Qt 5.5
- \value UpperSorbian Since Qt 5.5
- \value Kenyang Since Qt 5.5
- \value Mohawk Since Qt 5.5
- \value Nko Since Qt 5.5
- \value Prussian Since Qt 5.5
- \value Kiche Since Qt 5.5
- \value SouthernSami Since Qt 5.5
- \value LuleSami Since Qt 5.5
- \value InariSami Since Qt 5.5
- \value SkoltSami Since Qt 5.5
- \value Warlpiri Since Qt 5.5
- \value ManichaeanMiddlePersian Since Qt 5.5
- \value Mende Since Qt 5.5
- \value AncientNorthArabian Since Qt 5.5
- \value LinearA Since Qt 5.5
- \value HmongNjua Since Qt 5.5
- \value Ho Since Qt 5.5
- \value Lezghian Since Qt 5.5
- \value Bassa Since Qt 5.5
- \value Mono Since Qt 5.5
- \value TedimChin Since Qt 5.5
- \value Maithili Since Qt 5.5
- \value LowerSorbian Since Qt 5.5
- \value UpperSorbian Since Qt 5.5
- \value Ahom Since Qt 5.7
- \value AmericanSignLanguage Since Qt 5.7
- \value ArdhamagadhiPrakrit Since Qt 5.7
- \value Bhojpuri Since Qt 5.7
- \value Cantonese Since Qt 5.7
- \value HieroglyphicLuwian Since Qt 5.7
- \value LiteraryChinese Since Qt 5.7
- \value Mazanderani Since Qt 5.7
- \value Mru Since Qt 5.7
- \value Newari Since Qt 5.7
- \value NorthernLuri Since Qt 5.7
- \value Osage Since Qt 5.7
- \value Palauan Since Qt 5.7
- \value Papiamento Since Qt 5.7
- \value Saraiki Since Qt 5.7
- \value Tangut Since Qt 5.7
- \value TokelauLanguage Since Qt 5.7
- \value TokPisin Since Qt 5.7
- \value TuvaluLanguage Since Qt 5.7
- \value UncodedLanguages Since Qt 5.7
+
\omitvalue LastLanguage
\sa language(), languageToString()
@@ -494,7 +497,9 @@
This enumerated type is used to specify a country.
\value AnyCountry
+
\value Afghanistan
+ \value AlandIslands
\value Albania
\value Algeria
\value AmericanSamoa
@@ -506,6 +511,7 @@
\value Argentina
\value Armenia
\value Aruba
+ \value AscensionIsland
\value Australia
\value Austria
\value Azerbaijan
@@ -520,11 +526,13 @@
\value Bermuda
\value Bhutan
\value Bolivia
+ \value Bonaire
\value BosniaAndHerzegowina
\value Botswana
\value BouvetIsland
\value Brazil
\value BritishIndianOceanTerritory
+ \value BritishVirginIslands
\value Brunei
\value Bulgaria
\value BurkinaFaso
@@ -536,6 +544,7 @@
\value CapeVerde
\value CaymanIslands
\value CentralAfricanRepublic
+ \value CeutaAndMelilla
\value Chad
\value Chile
\value China
@@ -544,18 +553,19 @@
\value CocosIslands
\value Colombia
\value Comoros
- \value CongoKinshasa
\value CongoBrazzaville
- \value DemocraticRepublicOfCongo Obsolete, please use CongoKinshasa
- \value PeoplesRepublicOfCongo Obsolete, please use CongoBrazzaville
+ \value CongoKinshasa
\value CookIslands
\value CostaRica
- \value IvoryCoast
\value Croatia
\value Cuba
+ \value CuraSao
\value Cyprus
\value CzechRepublic
+ \value DemocraticRepublicOfCongo Obsolete, please use CongoKinshasa
+ \value DemocraticRepublicOfKorea Obsolete, please use NorthKorea
\value Denmark
+ \value DiegoGarcia
\value Djibouti
\value Dominica
\value DominicanRepublic
@@ -604,19 +614,18 @@
\value Iran
\value Iraq
\value Ireland
+ \value IsleOfMan
\value Israel
\value Italy
+ \value IvoryCoast
\value Jamaica
\value Japan
+ \value Jersey
\value Jordan
\value Kazakhstan
\value Kenya
\value Kiribati
- \value NorthKorea
- \value SouthKorea
- \value DemocraticRepublicOfKorea Obsolete, please use NorthKorea
- \value RepublicOfKorea Obsolete, please use SouthKorea
- \value Kosovo
+ \value Kosovo Since Qt 5.2
\value Kuwait
\value Kyrgyzstan
\value Laos
@@ -648,6 +657,7 @@
\value Moldova
\value Monaco
\value Mongolia
+ \value Montenegro
\value Montserrat
\value Morocco
\value Mozambique
@@ -664,6 +674,7 @@
\value Niue
\value NorfolkIsland
\value NorthernMarianaIslands
+ \value NorthKorea
\value Norway
\value Oman
\value OutlyingOceania Since Qt 5.7
@@ -673,6 +684,7 @@
\value Panama
\value PapuaNewGuinea
\value Paraguay
+ \value PeoplesRepublicOfCongo Obsolete, please use CongoBrazzaville
\value Peru
\value Philippines
\value Pitcairn
@@ -680,32 +692,39 @@
\value Portugal
\value PuertoRico
\value Qatar
+ \value RepublicOfKorea Obsolete, please use SouthKorea
\value Reunion
\value Romania
- \value Russia same as RussianFederation
\value RussianFederation same as Russia
+ \value Russia same as RussianFederation
\value Rwanda
+ \value SaintBarthelemy
+ \value SaintHelena
\value SaintKittsAndNevis
\value SaintLucia
+ \value SaintMartin
+ \value SaintPierreAndMiquelon
\value SaintVincentAndTheGrenadines
\value Samoa
\value SanMarino
\value SaoTomeAndPrincipe
\value SaudiArabia
\value Senegal
+ \value Serbia
\value Seychelles
\value SierraLeone
\value Singapore
+ \value SintMaarten
\value Slovakia
\value Slovenia
\value SolomonIslands
\value Somalia
\value SouthAfrica
\value SouthGeorgiaAndTheSouthSandwichIslands
+ \value SouthKorea
+ \value SouthSudan
\value Spain
\value SriLanka
- \value SaintHelena
- \value SaintPierreAndMiquelon
\value Sudan
\value Suriname
\value SvalbardAndJanMayenIslands
@@ -723,6 +742,7 @@
\value Tokelau Obsolete, please use TokelauCountry
\value Tonga
\value TrinidadAndTobago
+ \value TristanDaCunha
\value Tunisia
\value Turkey
\value Turkmenistan
@@ -735,35 +755,20 @@
\value UnitedKingdom
\value UnitedStates
\value UnitedStatesMinorOutlyingIslands
+ \value UnitedStatesVirginIslands
\value Uruguay
\value Uzbekistan
\value Vanuatu
\value VaticanCityState
\value Venezuela
\value Vietnam
- \value BritishVirginIslands
- \value UnitedStatesVirginIslands
\value WallisAndFutunaIslands
\value WesternSahara
\value World Since Qt 5.12
\value Yemen
\value Zambia
\value Zimbabwe
- \value Montenegro
- \value Serbia
- \value SaintBarthelemy
- \value SaintMartin
- \value AscensionIsland
- \value AlandIslands
- \value DiegoGarcia
- \value CeutaAndMelilla
- \value IsleOfMan
- \value Jersey
- \value TristanDaCunha
- \value SouthSudan
- \value CuraSao
- \value Bonaire
- \value SintMaarten
+
\omitvalue LastCountry
\sa country(), countryToString()
@@ -775,135 +780,136 @@
This enumerated type is used to specify a script.
\value AnyScript
+
\value AdlamScript Since Qt 5.7
\value AhomScript Since Qt 5.7
\value AnatolianHieroglyphsScript Since Qt 5.7
\value ArabicScript
\value ArmenianScript
- \value AvestanScript
- \value BalineseScript
- \value BamumScript
+ \value AvestanScript Since Qt 5.1
+ \value BalineseScript Since Qt 5.1
+ \value BamumScript Since Qt 5.1
\value BassaVahScript Since Qt 5.5
- \value BatakScript
+ \value BatakScript Since Qt 5.1
\value BengaliScript
\value BhaiksukiScript Since Qt 5.7
- \value BopomofoScript
- \value BrahmiScript
- \value BrailleScript
- \value BugineseScript
- \value BuhidScript
- \value CanadianAboriginalScript
- \value CarianScript
+ \value BopomofoScript Since Qt 5.1
+ \value BrahmiScript Since Qt 5.1
+ \value BrailleScript Since Qt 5.1
+ \value BugineseScript Since Qt 5.1
+ \value BuhidScript Since Qt 5.1
+ \value CanadianAboriginalScript Since Qt 5.1
+ \value CarianScript Since Qt 5.1
\value CaucasianAlbanianScript Since Qt 5.5
- \value ChakmaScript
- \value ChamScript
+ \value ChakmaScript Since Qt 5.1
+ \value ChamScript Since Qt 5.1
\value CherokeeScript
- \value CopticScript
- \value CypriotScript
+ \value CopticScript Since Qt 5.1
+ \value CuneiformScript Since Qt 5.1
+ \value CypriotScript Since Qt 5.1
\value CyrillicScript
- \value DeseretScript
+ \value DeseretScript Since Qt 5.1
\value DevanagariScript
\value DuployanScript Since Qt 5.5
- \value EgyptianHieroglyphsScript
+ \value EgyptianHieroglyphsScript Since Qt 5.1
\value ElbasanScript Since Qt 5.5
\value EthiopicScript
- \value FraserScript
+ \value FraserScript Since Qt 5.1
\value GeorgianScript
- \value GlagoliticScript
- \value GothicScript
+ \value GlagoliticScript Since Qt 5.1
+ \value GothicScript Since Qt 5.1
\value GranthaScript Since Qt 5.5
\value GreekScript
\value GujaratiScript
\value GurmukhiScript
- \value HanScript
- \value HangulScript
- \value HanunooScript
+ \value HangulScript Since Qt 5.1
+ \value HanScript Since Qt 5.1
+ \value HanunooScript Since Qt 5.1
\value HanWithBopomofoScript Since Qt 5.7
\value HatranScript Since Qt 5.7
\value HebrewScript
- \value HiraganaScript
- \value ImperialAramaicScript
- \value InscriptionalPahlaviScript
- \value InscriptionalParthianScript
+ \value HiraganaScript Since Qt 5.1
+ \value ImperialAramaicScript Since Qt 5.1
+ \value InscriptionalPahlaviScript Since Qt 5.1
+ \value InscriptionalParthianScript Since Qt 5.1
\value JamoScript Since Qt 5.7
\value JapaneseScript
- \value JavaneseScript
- \value KaithiScript
+ \value JavaneseScript Since Qt 5.1
+ \value KaithiScript Since Qt 5.1
\value KannadaScript
- \value KatakanaScript
- \value KayahLiScript
- \value KharoshthiScript
- \value KhmerScript
+ \value KatakanaScript Since Qt 5.1
+ \value KayahLiScript Since Qt 5.1
+ \value KharoshthiScript Since Qt 5.1
+ \value KhmerScript Since Qt 5.1
\value KhojkiScript Since Qt 5.5
\value KhudawadiScript Since Qt 5.5
\value KoreanScript
- \value LannaScript
+ \value LannaScript Since Qt 5.1
\value LaoScript
\value LatinScript
- \value LepchaScript
- \value LimbuScript
+ \value LepchaScript Since Qt 5.1
+ \value LimbuScript Since Qt 5.1
\value LinearAScript Since Qt 5.5
- \value LinearBScript
- \value LycianScript
- \value LydianScript
+ \value LinearBScript Since Qt 5.1
+ \value LycianScript Since Qt 5.1
+ \value LydianScript Since Qt 5.1
\value MahajaniScript Since Qt 5.5
\value MalayalamScript
- \value MandaeanScript
+ \value MandaeanScript Since Qt 5.1
\value ManichaeanScript Since Qt 5.5
\value MarchenScript Since Qt 5.7
- \value MeiteiMayekScript
+ \value MeiteiMayekScript Since Qt 5.1
\value MendeKikakuiScript Since Qt 5.5
- \value MeroiticScript
- \value MeroiticCursiveScript
+ \value MeroiticCursiveScript Since Qt 5.1
+ \value MeroiticScript Since Qt 5.1
\value ModiScript Since Qt 5.5
\value MongolianScript
\value MroScript Since Qt 5.5
\value MultaniScript Since Qt 5.7
\value MyanmarScript
\value NabataeanScript Since Qt 5.5
- \value NkoScript
\value NewaScript Since Qt 5.7
- \value NewTaiLueScript
- \value OghamScript
- \value OlChikiScript
- \value OldItalicScript
+ \value NewTaiLueScript Since Qt 5.1
+ \value NkoScript Since Qt 5.1
+ \value OghamScript Since Qt 5.1
+ \value OlChikiScript Since Qt 5.1
\value OldHungarianScript Since Qt 5.7
+ \value OldItalicScript Since Qt 5.1
\value OldNorthArabianScript Since Qt 5.5
\value OldPermicScript Since Qt 5.5
- \value OldPersianScript
- \value OldSouthArabianScript
+ \value OldPersianScript Since Qt 5.1
+ \value OldSouthArabianScript Since Qt 5.1
\value OriyaScript
- \value OrkhonScript
+ \value OrkhonScript Since Qt 5.1
\value OsageScript Since Qt 5.7
- \value OsmanyaScript
+ \value OsmanyaScript Since Qt 5.1
\value PahawhHmongScript Since Qt 5.5
\value PalmyreneScript Since Qt 5.5
\value PauCinHauScript Since Qt 5.5
- \value PhagsPaScript
- \value PhoenicianScript
- \value PollardPhoneticScript
+ \value PhagsPaScript Since Qt 5.1
+ \value PhoenicianScript Since Qt 5.1
+ \value PollardPhoneticScript Since Qt 5.1
\value PsalterPahlaviScript Since Qt 5.5
- \value RejangScript
- \value RunicScript
- \value SamaritanScript
- \value SaurashtraScript
- \value SharadaScript
- \value ShavianScript
+ \value RejangScript Since Qt 5.1
+ \value RunicScript Since Qt 5.1
+ \value SamaritanScript Since Qt 5.1
+ \value SaurashtraScript Since Qt 5.1
+ \value SharadaScript Since Qt 5.1
+ \value ShavianScript Since Qt 5.1
\value SiddhamScript Since Qt 5.5
\value SignWritingScript Since Qt 5.7
- \value SimplifiedHanScript same as SimplifiedChineseScript
\value SimplifiedChineseScript same as SimplifiedHanScript
+ \value SimplifiedHanScript same as SimplifiedChineseScript
\value SinhalaScript
- \value SoraSompengScript
- \value CuneiformScript
- \value SundaneseScript
- \value SylotiNagriScript
+ \value SoraSompengScript Since Qt 5.1
+ \value SundaneseScript Since Qt 5.1
+ \value SylotiNagriScript Since Qt 5.1
\value SyriacScript
- \value TagalogScript
- \value TagbanwaScript
- \value TaiLeScript
- \value TaiVietScript
- \value TakriScript
+ \value TagalogScript Since Qt 5.1
+ \value TagbanwaScript Since Qt 5.1
+ \value TaiLeScript Since Qt 5.1
+ \value TaiVietScript Since Qt 5.1
+ \value TakriScript Since Qt 5.1
\value TamilScript
\value TangutScript Since Qt 5.7
\value TeluguScript
@@ -912,12 +918,13 @@
\value TibetanScript
\value TifinaghScript
\value TirhutaScript Since Qt 5.5
- \value TraditionalHanScript same as TraditionalChineseScript
\value TraditionalChineseScript same as TraditionalHanScript
- \value UgariticScript
+ \value TraditionalHanScript same as TraditionalChineseScript
+ \value UgariticScript Since Qt 5.1
\value VaiScript
\value VarangKshitiScript Since Qt 5.5
\value YiScript
+
\omitvalue LastScript
\sa script(), scriptToString(), languageToString()
@@ -1158,6 +1165,30 @@
currency string.
*/
+/*!
+\fn QString QLocale::toString(long i) const
+
+\overload
+
+\sa toLong()
+*/
+
+/*!
+\fn QString QLocale::toString(ulong i) const
+
+\overload
+
+\sa toULong()
+*/
+
+/*!
+\fn QString QLocale::toString(ushort i) const
+
+\overload
+
+\sa toUShort()
+*/
+
/*!
\fn QString QLocale::toString(short i) const
diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/tools/qlocale_data_p.h
index 09e4e70d6b..2c351a3fb1 100644
--- a/src/corelib/tools/qlocale_data_p.h
+++ b/src/corelib/tools/qlocale_data_p.h
@@ -77,14 +77,14 @@ static const int ImperialMeasurementSystemsCount =
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2019-05-02 from the
+ This part of the file was generated on 2019-05-09 from the
Common Locale Data Repository v35.1
http://www.unicode.org/cldr/
Do not edit this section: instead regenerate it using
cldr2qlocalexml.py and qlocalexml2cpp.py on updated (or
- edited) CLDR data; see qtbase/util/local_database/.
+ edited) CLDR data; see qtbase/util/locale_database/.
*/
static const QLocaleId likely_subtags[] = {
@@ -122,6 +122,7 @@ static const QLocaleId likely_subtags[] = {
{ 195, 0, 0 }, { 195, 7, 239 }, // bem -> bem_Latn_ZM
{ 186, 0, 0 }, { 186, 7, 210 }, // bez -> bez_Latn_TZ
{ 20, 0, 0 }, { 20, 2, 33 }, // bg -> bg_Cyrl_BG
+ { 364, 0, 0 }, { 364, 1, 163 }, // bgn -> bgn_Arab_PK
{ 343, 0, 0 }, { 343, 13, 100 }, // bho -> bho_Deva_IN
{ 18, 0, 0 }, { 18, 7, 229 }, // bi -> bi_Latn_VU
{ 270, 0, 0 }, { 270, 7, 170 }, // bku -> bku_Latn_PH
@@ -140,6 +141,7 @@ static const QLocaleId likely_subtags[] = {
{ 156, 0, 0 }, { 156, 7, 157 }, // cch -> cch_Latn_NG
{ 272, 0, 0 }, { 272, 46, 18 }, // ccp -> ccp_Cakm_BD
{ 218, 0, 0 }, { 218, 2, 178 }, // ce -> ce_Cyrl_RU
+ { 365, 0, 0 }, { 365, 7, 170 }, // ceb -> ceb_Latn_PH
{ 211, 0, 0 }, { 211, 7, 221 }, // cgg -> cgg_Latn_UG
{ 217, 0, 0 }, { 217, 7, 89 }, // ch -> ch_Latn_GU
{ 190, 0, 0 }, { 190, 12, 225 }, // chr -> chr_Cher_US
@@ -224,10 +226,12 @@ static const QLocaleId likely_subtags[] = {
{ 168, 0, 0 }, { 168, 34, 44 }, // ii -> ii_Yiii_CN
{ 56, 0, 0 }, { 56, 7, 225 }, // ik -> ik_Latn_US
{ 281, 0, 0 }, { 281, 2, 178 }, // inh -> inh_Cyrl_RU
+ { 360, 0, 0 }, { 360, 7, 260 }, // io -> io_Latn_001
{ 51, 0, 0 }, { 51, 7, 99 }, // is -> is_Latn_IS
{ 58, 0, 0 }, { 58, 7, 106 }, // it -> it_Latn_IT
{ 55, 0, 0 }, { 55, 44, 38 }, // iu -> iu_Cans_CA
{ 59, 0, 0 }, { 59, 19, 108 }, // ja -> ja_Jpan_JP
+ { 361, 0, 0 }, { 361, 7, 260 }, // jbo -> jbo_Latn_001
{ 257, 0, 0 }, { 257, 7, 37 }, // jgo -> jgo_Latn_CM
{ 200, 0, 0 }, { 200, 7, 210 }, // jmc -> jmc_Latn_TZ
{ 60, 0, 0 }, { 60, 7, 101 }, // jv -> jv_Latn_ID
@@ -324,6 +328,7 @@ static const QLocaleId likely_subtags[] = {
{ 78, 0, 0 }, { 78, 7, 133 }, // mt -> mt_Latn_MT
{ 245, 0, 0 }, { 245, 7, 37 }, // mua -> mua_Latn_CM
{ 21, 0, 0 }, { 21, 25, 147 }, // my -> my_Mymr_MM
+ { 366, 0, 0 }, { 366, 2, 178 }, // myv -> myv_Cyrl_RU
{ 273, 0, 0 }, { 273, 71, 102 }, // myz -> myz_Mand_IR
{ 346, 0, 0 }, { 346, 1, 102 }, // mzn -> mzn_Arab_IR
{ 83, 0, 0 }, { 83, 7, 149 }, // na -> na_Latn_NR
@@ -385,10 +390,12 @@ static const QLocaleId likely_subtags[] = {
{ 305, 0, 0 }, { 305, 90, 100 }, // saz -> saz_Saur_IN
{ 249, 0, 0 }, { 249, 7, 210 }, // sbp -> sbp_Latn_TZ
{ 115, 0, 0 }, { 115, 7, 106 }, // sc -> sc_Latn_IT
+ { 362, 0, 0 }, { 362, 7, 106 }, // scn -> scn_Latn_IT
{ 105, 0, 0 }, { 105, 1, 163 }, // sd -> sd_Arab_PK
{ 105, 13, 0 }, { 105, 13, 100 }, // sd_Deva -> sd_Deva_IN
{ 105, 111, 0 }, { 105, 111, 100 }, // sd_Khoj -> sd_Khoj_IN
{ 105, 125, 0 }, { 105, 125, 100 }, // sd_Sind -> sd_Sind_IN
+ { 363, 0, 0 }, { 363, 1, 102 }, // sdh -> sdh_Arab_IR
{ 173, 0, 0 }, { 173, 7, 161 }, // se -> se_Latn_NO
{ 180, 0, 0 }, { 180, 7, 146 }, // seh -> seh_Latn_MZ
{ 213, 0, 0 }, { 213, 7, 132 }, // ses -> ses_Latn_ML
@@ -1252,6 +1259,13 @@ static const quint16 locale_index[] = {
576, // Cantonese
0, // Osage
0, // Tangut
+ 578, // Ido
+ 579, // Lojban
+ 580, // Sicilian
+ 581, // Southern Kurdish
+ 582, // Western Balochi
+ 583, // Cebuano
+ 584, // Erzya
0 // trailing 0
};
@@ -1835,6 +1849,13 @@ static const QLocaleData locale_data[] = {
{ 349, 1, 103, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 39288,77 , 39288,77 , 158,27 , 39288,77 , 39288,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,81,68}, 44,5 , 0,7 , 8,5 , 4,0 , 5913,11 , 0,0 , 0, 0, 6, 5, 6 }, // Northern Luri/Arabic/Iraq
{ 357, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 1027,5 , 1027,5 , 394,8 , 423,14 , 198,6 , 215,13 , 4423,39 , 4423,39 , 158,27 , 4423,39 , 4423,39 , 158,27 , 1953,28 , 1953,28 , 1981,14 , 1953,28 , 1953,28 , 1981,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {72,75,68}, 166,3 , 17468,11 , 4,4 , 4,0 , 5924,2 , 5926,14 , 2, 1, 7, 6, 7 }, // Cantonese/Traditional Han/Hong Kong
{ 357, 5, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 1027,5 , 1027,5 , 394,8 , 402,13 , 198,6 , 204,11 , 4423,39 , 4462,38 , 158,27 , 4423,39 , 4462,38 , 158,27 , 1932,21 , 1953,28 , 1981,14 , 1932,21 , 1953,28 , 1981,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 133,1 , 3122,13 , 4,4 , 4,0 , 5940,2 , 5942,7 , 2, 1, 7, 6, 7 }, // Cantonese/Simplified Han/China
+ { 360, 7, 260, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Ido/Latin/World
+ { 361, 7, 260, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Lojban/Latin/World
+ { 362, 7, 106, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Sicilian/Latin/Italy
+ { 363, 1, 102, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 6, 5, 5 }, // Southern Kurdish/Arabic/Iran
+ { 364, 1, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,75,82}, 175,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Western Balochi/Arabic/Pakistan
+ { 365, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 897,9 , 906,8 , 547,6 , 35,18 , 18,7 , 25,12 , 39365,46 , 39411,88 , 39499,24 , 39365,46 , 39411,88 , 39499,24 , 21469,25 , 21494,56 , 21550,14 , 21469,25 , 21494,56 , 21550,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,72,80}, 178,1 , 0,7 , 4,4 , 4,0 , 5949,7 , 4701,9 , 2, 1, 7, 6, 7 }, // Cebuano/Latin/Philippines
+ { 366, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 123,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Erzya/Cyrillic/Russia
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, {0,0,0}, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0, 0, 0, 0, 0 } // trailing 0s
};
@@ -3991,7 +4012,15 @@ static const ushort months_data[] = {
0x6d5, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x6a4, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x659,
0x623, 0x646, 0x3b, 0x62c, 0x648, 0x659, 0x644, 0x627, 0x3b, 0x622, 0x6af, 0x648, 0x633, 0x62a, 0x3b, 0x633, 0x626, 0x67e, 0x62a, 0x627,
0x645, 0x631, 0x3b, 0x626, 0x648, 0x6a9, 0x62a, 0x648, 0x6a4, 0x631, 0x3b, 0x646, 0x648, 0x6a4, 0x627, 0x645, 0x631, 0x3b, 0x62f, 0x626,
-0x633, 0x627, 0x645, 0x631, 0x3b
+0x633, 0x627, 0x645, 0x631, 0x3b, 0x45, 0x6e, 0x3b, 0x50, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b,
+0x4d, 0x61, 0x79, 0x3b, 0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f,
+0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x50, 0x65, 0x62,
+0x72, 0x65, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79,
+0x6f, 0x3b, 0x48, 0x75, 0x6e, 0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6c, 0x79, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f,
+0x3b, 0x53, 0x65, 0x74, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x6b, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e,
+0x6f, 0x62, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x73, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x45,
+0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e,
+0x3b, 0x44, 0x3b
};
static const ushort days_data[] = {
@@ -5068,7 +5097,12 @@ static const ushort days_data[] = {
0x72, 0x67, 0xe2, 0x3b, 0x6d, 0x61, 0x6a, 0x65, 0x62, 0x61, 0x61, 0x72, 0x67, 0xe2, 0x3b, 0x6b, 0x6f, 0x73, 0x6b, 0x6f,
0x68, 0x6f, 0x3b, 0x74, 0x75, 0x6f, 0x72, 0xe2, 0x73, 0x74, 0x75, 0x76, 0x3b, 0x76, 0xe1, 0x73, 0x74, 0x75, 0x70, 0x70,
0x65, 0x65, 0x69, 0x76, 0x69, 0x3b, 0x6c, 0xe1, 0x76, 0x75, 0x72, 0x64, 0x75, 0x76, 0x3b, 0x70, 0x3b, 0x56, 0x3b, 0x4d,
-0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x56, 0x3b, 0x4c, 0x3b
+0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x56, 0x3b, 0x4c, 0x3b, 0x44, 0x6f, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72,
+0x3b, 0x4d, 0x6b, 0x73, 0x3b, 0x48, 0x75, 0x3b, 0x42, 0x69, 0x3b, 0x53, 0x61, 0x3b, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67,
+0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0x79, 0x65, 0x72,
+0x6b, 0x75, 0x6c, 0x65, 0x73, 0x3b, 0x48, 0x75, 0x77, 0x65, 0x62, 0x65, 0x73, 0x3b, 0x42, 0x69, 0x79, 0x65, 0x72, 0x6e,
+0x65, 0x73, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x48, 0x3b,
+0x42, 0x3b, 0x53, 0x3b
};
static const ushort byte_unit_data[] = {
@@ -6431,7 +6465,7 @@ static const ushort endonyms_data[] = {
0x73, 0x6b, 0x61, 0x6e, 0x73, 0x77, 0x12b, 0x74, 0x61, 0x69, 0x61, 0x6e, 0x61, 0x72, 0xe2, 0x161, 0x6b, 0x69, 0x65, 0x6c,
0xe2, 0x53, 0x75, 0x6f, 0x6d, 0xe2, 0x645, 0x627, 0x632, 0x631, 0x648, 0x646, 0x6cc, 0x644, 0x6ca, 0x631, 0x6cc, 0x20, 0x634, 0x648,
0x645, 0x627, 0x644, 0x6cc, 0x7cb5, 0x8a9e, 0x4e2d, 0x83ef, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x570b, 0x9999, 0x6e2f, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340,
-0x7ca4, 0x8bed, 0x4e2d, 0x534e, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x56fd
+0x7ca4, 0x8bed, 0x4e2d, 0x534e, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x56fd, 0x43, 0x65, 0x62, 0x75, 0x61, 0x6e, 0x6f
};
static const char language_name_list[] =
@@ -6795,6 +6829,13 @@ static const char language_name_list[] =
"Cantonese\0"
"Osage\0"
"Tangut\0"
+"Ido\0"
+"Lojban\0"
+"Sicilian\0"
+"Southern Kurdish\0"
+"Western Balochi\0"
+"Cebuano\0"
+"Erzya\0"
;
static const quint16 language_name_index[] = {
@@ -7158,6 +7199,13 @@ static const quint16 language_name_index[] = {
3050, // Cantonese
3060, // Osage
3066, // Tangut
+ 3073, // Ido
+ 3077, // Lojban
+ 3084, // Sicilian
+ 3093, // Southern Kurdish
+ 3110, // Western Balochi
+ 3126, // Cebuano
+ 3134, // Erzya
};
static const char script_name_list[] =
@@ -8341,6 +8389,13 @@ static const unsigned char language_code_list[] =
"yue" // Cantonese
"osa" // Osage
"txg" // Tangut
+"io\0" // Ido
+"jbo" // Lojban
+"scn" // Sicilian
+"sdh" // Southern Kurdish
+"bgn" // Western Balochi
+"ceb" // Cebuano
+"myv" // Erzya
;
static const unsigned char script_code_list[] =
diff --git a/src/corelib/tools/qlocale_mac.mm b/src/corelib/tools/qlocale_mac.mm
index 574cb0714c..9719278426 100644
--- a/src/corelib/tools/qlocale_mac.mm
+++ b/src/corelib/tools/qlocale_mac.mm
@@ -44,10 +44,8 @@
#include "qdatetime.h"
#ifdef Q_OS_DARWIN
-#include "qtimezone.h"
#include "private/qcore_mac_p.h"
#include <CoreFoundation/CoreFoundation.h>
-QT_REQUIRE_CONFIG(timezone);
#endif
QT_BEGIN_NAMESPACE
@@ -147,7 +145,7 @@ static QString macTimeToString(const QTime &time, bool short_format)
// Mac uses the Unicode CLDR format codes
// http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
-// See also qtbase/util/local_database/dateconverter.py
+// See also qtbase/util/locale_database/dateconverter.py
// Makes the assumption that input formats are always well formed and consecutive letters
// never exceed the maximum for the format code.
static QString macToQtFormat(QStringView sys_fmt)
@@ -491,8 +489,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
} else if (typeId == CFStringGetTypeID()) {
result = QStringList(QString::fromCFString(languages.as<CFStringRef>()));
} else {
- qWarning("QLocale::uiLanguages(): CFPreferencesCopyValue returned unhandled type \"%s\"; please report to http://bugreports.qt.io",
- qPrintable(QString::fromCFString(CFCopyTypeIDDescription(typeId))));
+ qWarning("QLocale::uiLanguages(): CFPreferencesCopyValue returned unhandled type \"%ls\"; please report to http://bugreports.qt.io",
+ qUtf16Printable(QString::fromCFString(CFCopyTypeIDDescription(typeId))));
}
return QVariant(result);
}
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index 7487c9128c..1e3da35a02 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -66,6 +66,7 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_SYSTEMLOCALE
+struct QLocaleData;
class Q_CORE_EXPORT QSystemLocale
{
public:
@@ -112,6 +113,7 @@ public:
Weekdays, // QList<Qt::DayOfWeek>
CurrencySymbol, // QString in: CurrencyToStringArgument
CurrencyToString, // QString in: qlonglong, qulonglong or double
+ Collation, // QString
UILanguages, // QStringList
StringToStandardQuotation, // QString in: QStringRef to quote
StringToAlternateQuotation, // QString in: QStringRef to quote
@@ -126,6 +128,7 @@ public:
virtual QVariant query(QueryType type, QVariant in) const;
virtual QLocale fallbackUiLocale() const;
+ inline const QLocaleData *fallbackUiLocaleData() const;
private:
QSystemLocale(bool);
friend class QSystemLocaleSingleton;
@@ -247,14 +250,14 @@ public:
if (qIsInf(d))
return float(d);
if (std::fabs(d) > std::numeric_limits<float>::max()) {
- if (ok != 0)
+ if (ok)
*ok = false;
const float huge = std::numeric_limits<float>::infinity();
return d < 0 ? -huge : huge;
}
if (d != 0 && float(d) == 0) {
// Values that underflow double already failed. Match them:
- if (ok != 0)
+ if (ok)
*ok = false;
return 0;
}
@@ -334,7 +337,7 @@ public:
{
QLocalePrivate *retval = new QLocalePrivate;
retval->m_data = data;
- retval->ref.store(0);
+ retval->ref.storeRelaxed(0);
retval->m_numberOptions = numberOptions;
return retval;
}
@@ -356,23 +359,21 @@ public:
QByteArray bcp47Name(char separator = '-') const;
- inline QLatin1String languageCode() const { return QLocalePrivate::languageToCode(QLocale::Language(m_data->m_language_id)); }
- inline QLatin1String scriptCode() const { return QLocalePrivate::scriptToCode(QLocale::Script(m_data->m_script_id)); }
- inline QLatin1String countryCode() const { return QLocalePrivate::countryToCode(QLocale::Country(m_data->m_country_id)); }
+ inline QLatin1String languageCode() const { return languageToCode(QLocale::Language(m_data->m_language_id)); }
+ inline QLatin1String scriptCode() const { return scriptToCode(QLocale::Script(m_data->m_script_id)); }
+ inline QLatin1String countryCode() const { return countryToCode(QLocale::Country(m_data->m_country_id)); }
static QLatin1String languageToCode(QLocale::Language language);
static QLatin1String scriptToCode(QLocale::Script script);
static QLatin1String countryToCode(QLocale::Country country);
- static QLocale::Language codeToLanguage(QStringView code) Q_DECL_NOTHROW;
- static QLocale::Script codeToScript(QStringView code) Q_DECL_NOTHROW;
- static QLocale::Country codeToCountry(QStringView code) Q_DECL_NOTHROW;
+ static QLocale::Language codeToLanguage(QStringView code) noexcept;
+ static QLocale::Script codeToScript(QStringView code) noexcept;
+ static QLocale::Country codeToCountry(QStringView code) noexcept;
static void getLangAndCountry(const QString &name, QLocale::Language &lang,
QLocale::Script &script, QLocale::Country &cntry);
QLocale::MeasurementSystem measurementSystem() const;
- static void updateSystemPrivate();
-
QString dateTimeToString(QStringView format, const QDateTime &datetime,
const QDate &dateOnly, const QTime &timeOnly,
const QLocale *q) const;
@@ -382,6 +383,10 @@ public:
QLocale::NumberOptions m_numberOptions;
};
+#ifndef QT_NO_SYSTEMLOCALE
+const QLocaleData *QSystemLocale::fallbackUiLocaleData() const { return fallbackUiLocale().d->m_data; }
+#endif
+
template <>
inline QLocalePrivate *QSharedDataPointer<QLocalePrivate>::clone()
{
diff --git a/src/corelib/tools/qlocale_tools.cpp b/src/corelib/tools/qlocale_tools.cpp
index 53258bec3e..db8c8cd12f 100644
--- a/src/corelib/tools/qlocale_tools.cpp
+++ b/src/corelib/tools/qlocale_tools.cpp
@@ -398,7 +398,7 @@ qstrtoull(const char * nptr, const char **endptr, int base, bool *ok)
*ok = true;
errno = 0;
- char *endptr2 = 0;
+ char *endptr2 = nullptr;
unsigned long long result = qt_strtoull(nptr, &endptr2, base);
if (endptr)
*endptr = endptr2;
@@ -415,7 +415,7 @@ qstrtoll(const char * nptr, const char **endptr, int base, bool *ok)
{
*ok = true;
errno = 0;
- char *endptr2 = 0;
+ char *endptr2 = nullptr;
long long result = qt_strtoll(nptr, &endptr2, base);
if (endptr)
*endptr = endptr2;
diff --git a/src/corelib/tools/qlocale_unix.cpp b/src/corelib/tools/qlocale_unix.cpp
index f202082213..ff4274d932 100644
--- a/src/corelib/tools/qlocale_unix.cpp
+++ b/src/corelib/tools/qlocale_unix.cpp
@@ -69,6 +69,7 @@ struct QSystemLocaleData
QLocale lc_messages;
QByteArray lc_messages_var;
QByteArray lc_measurement_var;
+ QByteArray lc_collate_var;
QStringList uiLanguages;
};
@@ -82,6 +83,7 @@ void QSystemLocaleData::readEnvironment()
QByteArray monetary = all.isEmpty() ? qgetenv("LC_MONETARY") : all;
lc_messages_var = all.isEmpty() ? qgetenv("LC_MESSAGES") : all;
lc_measurement_var = all.isEmpty() ? qgetenv("LC_MEASUREMENT") : all;
+ lc_collate_var = all.isEmpty() ? qgetenv("LC_COLLATE") : all;
QByteArray lang = qgetenv("LANG");
if (lang.isEmpty())
lang = QByteArray("C");
@@ -95,6 +97,8 @@ void QSystemLocaleData::readEnvironment()
lc_messages_var = lang;
if (lc_measurement_var.isEmpty())
lc_measurement_var = lang;
+ if (lc_collate_var.isEmpty())
+ lc_collate_var = lang;
lc_numeric = QLocale(QString::fromLatin1(numeric));
lc_time = QLocale(QString::fromLatin1(time));
lc_monetary = QLocale(QString::fromLatin1(monetary));
@@ -247,13 +251,15 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
return QString();
}
case MeasurementSystem: {
- const QString meas_locale = QString::fromLatin1(d->lc_measurement_var.constData(), d->lc_measurement_var.size());
+ const QString meas_locale = QString::fromLatin1(d->lc_measurement_var);
if (meas_locale.compare(QLatin1String("Metric"), Qt::CaseInsensitive) == 0)
return QLocale::MetricSystem;
if (meas_locale.compare(QLatin1String("Other"), Qt::CaseInsensitive) == 0)
return QLocale::MetricSystem;
return QVariant((int)QLocale(meas_locale).measurementSystem());
}
+ case Collation:
+ return QString::fromLatin1(d->lc_collate_var);
case UILanguages: {
if (!d->uiLanguages.isEmpty())
return d->uiLanguages;
diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp
index ebc4430046..dc904ad02d 100644
--- a/src/corelib/tools/qlocale_win.cpp
+++ b/src/corelib/tools/qlocale_win.cpp
@@ -120,6 +120,7 @@ struct QSystemLocalePrivate
QVariant toString(const QTime &, QLocale::FormatType);
QVariant toString(const QDateTime &, QLocale::FormatType);
QVariant measurementSystem();
+ QVariant collation();
QVariant amText();
QVariant pmText();
QVariant firstDayOfWeek();
@@ -455,6 +456,11 @@ QVariant QSystemLocalePrivate::measurementSystem()
return QLocale::MetricSystem;
}
+QVariant QSystemLocalePrivate::collation()
+{
+ return getLocaleInfo(LOCALE_SSORTLOCALE);
+}
+
QVariant QSystemLocalePrivate::amText()
{
wchar_t output[15]; // maximum length including terminating zero character for Win2003+
@@ -808,6 +814,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
return QVariant(QLocale::AnyScript);
case MeasurementSystem:
return d->measurementSystem();
+ case Collation:
+ return d->collation();
case AMText:
return d->amText();
case PMText:
diff --git a/src/corelib/tools/qmakearray_p.h b/src/corelib/tools/qmakearray_p.h
index ae4d7f07c6..71441c2c27 100644
--- a/src/corelib/tools/qmakearray_p.h
+++ b/src/corelib/tools/qmakearray_p.h
@@ -111,10 +111,10 @@ struct QuickSortFilter<Predicate, QuickSortData<Head, Tail...>>
using TailFilteredData = typename QuickSortFilter<
Predicate, QuickSortData<Tail...>>::Type;
- using Type = typename QConditional<
+ using Type = typename std::conditional<
Predicate<Head>::value,
decltype(quickSortConcat(QuickSortData<Head> {}, TailFilteredData{})),
- TailFilteredData>::Type;
+ TailFilteredData>::type;
};
template <template <typename> class Predicate>
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
index 5f7275c5f8..a0ec372f9a 100644
--- a/src/corelib/tools/qmap.cpp
+++ b/src/corelib/tools/qmap.cpp
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
-const QMapDataBase QMapDataBase::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, { 0, 0, 0 }, 0 };
+const QMapDataBase QMapDataBase::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, { 0, nullptr, nullptr }, nullptr };
const QMapNodeBase *QMapNodeBase::nextNode() const
{
@@ -92,7 +92,7 @@ void QMapDataBase::rotateLeft(QMapNodeBase *x)
QMapNodeBase *&root = header.left;
QMapNodeBase *y = x->right;
x->right = y->left;
- if (y->left != 0)
+ if (y->left != nullptr)
y->left->setParent(x);
y->setParent(x->parent());
if (x == root)
@@ -111,7 +111,7 @@ void QMapDataBase::rotateRight(QMapNodeBase *x)
QMapNodeBase *&root = header.left;
QMapNodeBase *y = x->left;
x->left = y->right;
- if (y->right != 0)
+ if (y->right != nullptr)
y->right->setParent(x);
y->setParent(x->parent());
if (x == root)
@@ -173,7 +173,7 @@ void QMapDataBase::freeNodeAndRebalance(QMapNodeBase *z)
QMapNodeBase *y = z;
QMapNodeBase *x;
QMapNodeBase *x_parent;
- if (y->left == 0) {
+ if (y->left == nullptr) {
x = y->right;
if (y == mostLeftNode) {
if (x)
@@ -182,11 +182,11 @@ void QMapDataBase::freeNodeAndRebalance(QMapNodeBase *z)
mostLeftNode = y->parent();
}
} else {
- if (y->right == 0) {
+ if (y->right == nullptr) {
x = y->left;
} else {
y = y->right;
- while (y->left != 0)
+ while (y->left != nullptr)
y = y->left;
x = y->right;
}
@@ -228,7 +228,7 @@ void QMapDataBase::freeNodeAndRebalance(QMapNodeBase *z)
z->parent()->right = x;
}
if (y->color() != QMapNodeBase::Red) {
- while (x != root && (x == 0 || x->color() == QMapNodeBase::Black)) {
+ while (x != root && (x == nullptr || x->color() == QMapNodeBase::Black)) {
if (x == x_parent->left) {
QMapNodeBase *w = x_parent->right;
if (w->color() == QMapNodeBase::Red) {
@@ -237,13 +237,13 @@ void QMapDataBase::freeNodeAndRebalance(QMapNodeBase *z)
rotateLeft(x_parent);
w = x_parent->right;
}
- if ((w->left == 0 || w->left->color() == QMapNodeBase::Black) &&
- (w->right == 0 || w->right->color() == QMapNodeBase::Black)) {
+ if ((w->left == nullptr || w->left->color() == QMapNodeBase::Black) &&
+ (w->right == nullptr || w->right->color() == QMapNodeBase::Black)) {
w->setColor(QMapNodeBase::Red);
x = x_parent;
x_parent = x_parent->parent();
} else {
- if (w->right == 0 || w->right->color() == QMapNodeBase::Black) {
+ if (w->right == nullptr || w->right->color() == QMapNodeBase::Black) {
if (w->left)
w->left->setColor(QMapNodeBase::Black);
w->setColor(QMapNodeBase::Red);
@@ -265,13 +265,13 @@ void QMapDataBase::freeNodeAndRebalance(QMapNodeBase *z)
rotateRight(x_parent);
w = x_parent->left;
}
- if ((w->right == 0 || w->right->color() == QMapNodeBase::Black) &&
- (w->left == 0 || w->left->color() == QMapNodeBase::Black)) {
+ if ((w->right == nullptr || w->right->color() == QMapNodeBase::Black) &&
+ (w->left == nullptr|| w->left->color() == QMapNodeBase::Black)) {
w->setColor(QMapNodeBase::Red);
x = x_parent;
x_parent = x_parent->parent();
} else {
- if (w->left == 0 || w->left->color() == QMapNodeBase::Black) {
+ if (w->left == nullptr || w->left->color() == QMapNodeBase::Black) {
if (w->right)
w->right->setColor(QMapNodeBase::Black);
w->setColor(QMapNodeBase::Red);
@@ -363,8 +363,8 @@ QMapDataBase *QMapDataBase::createData()
d->size = 0;
d->header.p = 0;
- d->header.left = 0;
- d->header.right = 0;
+ d->header.left = nullptr;
+ d->header.right = nullptr;
d->mostLeftNode = &(d->header);
return d;
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 1cf9299e26..18c681581f 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -49,13 +49,10 @@
#include <QtCore/qdebug.h>
#endif
-#include <map>
-#include <new>
#include <functional>
-
-#ifdef Q_COMPILER_INITIALIZER_LISTS
#include <initializer_list>
-#endif
+#include <map>
+#include <new>
QT_BEGIN_NAMESPACE
@@ -100,10 +97,10 @@ struct Q_CORE_EXPORT QMapNodeBase
template <typename T>
static typename std::enable_if<QTypeInfo<T>::isComplex>::type
- callDestructorIfNecessary(T &t) Q_DECL_NOTHROW { Q_UNUSED(t); t.~T(); } // Q_UNUSED: silence MSVC unused 't' warning
+ callDestructorIfNecessary(T &t) noexcept { Q_UNUSED(t); t.~T(); } // Q_UNUSED: silence MSVC unused 't' warning
template <typename T>
static typename std::enable_if<!QTypeInfo<T>::isComplex>::type
- callDestructorIfNecessary(T &) Q_DECL_NOTHROW {}
+ callDestructorIfNecessary(T &) noexcept {}
};
template <class Key, class T>
@@ -142,7 +139,7 @@ private:
rightNode()->destroySubTree();
}
- QMapNode() Q_DECL_EQ_DELETE;
+ QMapNode() = delete;
Q_DISABLE_COPY(QMapNode)
};
@@ -325,32 +322,28 @@ class QMap
QMapData<Key, T> *d;
public:
- inline QMap() Q_DECL_NOTHROW : d(static_cast<QMapData<Key, T> *>(const_cast<QMapDataBase *>(&QMapDataBase::shared_null))) { }
-#ifdef Q_COMPILER_INITIALIZER_LISTS
+ inline QMap() noexcept : d(static_cast<QMapData<Key, T> *>(const_cast<QMapDataBase *>(&QMapDataBase::shared_null))) { }
inline QMap(std::initializer_list<std::pair<Key,T> > list)
: d(static_cast<QMapData<Key, T> *>(const_cast<QMapDataBase *>(&QMapDataBase::shared_null)))
{
for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
insert(it->first, it->second);
}
-#endif
QMap(const QMap<Key, T> &other);
inline ~QMap() { if (!d->ref.deref()) d->destroy(); }
QMap<Key, T> &operator=(const QMap<Key, T> &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QMap(QMap<Key, T> &&other) Q_DECL_NOTHROW
+ inline QMap(QMap<Key, T> &&other) noexcept
: d(other.d)
{
other.d = static_cast<QMapData<Key, T> *>(
const_cast<QMapDataBase *>(&QMapDataBase::shared_null));
}
- inline QMap<Key, T> &operator=(QMap<Key, T> &&other) Q_DECL_NOTHROW
+ inline QMap<Key, T> &operator=(QMap<Key, T> &&other) noexcept
{ QMap moved(std::move(other)); swap(moved); return *this; }
-#endif
- inline void swap(QMap<Key, T> &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ inline void swap(QMap<Key, T> &other) noexcept { qSwap(d, other.d); }
explicit QMap(const typename std::map<Key, T> &other);
std::map<Key, T> toStdMap() const;
@@ -1187,19 +1180,15 @@ template <class Key, class T>
class QMultiMap : public QMap<Key, T>
{
public:
- QMultiMap() Q_DECL_NOTHROW {}
-#ifdef Q_COMPILER_INITIALIZER_LISTS
+ QMultiMap() noexcept {}
inline QMultiMap(std::initializer_list<std::pair<Key,T> > list)
{
for (typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
insert(it->first, it->second);
}
-#endif
QMultiMap(const QMap<Key, T> &other) : QMap<Key, T>(other) {}
-#ifdef Q_COMPILER_RVALUE_REFS
- QMultiMap(QMap<Key, T> &&other) Q_DECL_NOTHROW : QMap<Key, T>(std::move(other)) {}
-#endif
- void swap(QMultiMap<Key, T> &other) Q_DECL_NOTHROW { QMap<Key, T>::swap(other); }
+ QMultiMap(QMap<Key, T> &&other) noexcept : QMap<Key, T>(std::move(other)) {}
+ void swap(QMultiMap<Key, T> &other) noexcept { QMap<Key, T>::swap(other); }
inline typename QMap<Key, T>::iterator replace(const Key &key, const T &value)
{ return QMap<Key, T>::insert(key, value); }
diff --git a/src/corelib/tools/qmargins.h b/src/corelib/tools/qmargins.h
index 0c73235d26..447037daaa 100644
--- a/src/corelib/tools/qmargins.h
+++ b/src/corelib/tools/qmargins.h
@@ -51,28 +51,28 @@ QT_BEGIN_NAMESPACE
class QMargins
{
public:
- Q_DECL_CONSTEXPR QMargins() Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QMargins(int left, int top, int right, int bottom) Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR bool isNull() const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR int left() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR int top() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR int right() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR int bottom() const Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR void setLeft(int left) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR void setTop(int top) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR void setRight(int right) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR void setBottom(int bottom) Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator+=(const QMargins &margins) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator-=(const QMargins &margins) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator+=(int) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator-=(int) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator*=(int) Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR QMargins() noexcept;
+ Q_DECL_CONSTEXPR QMargins(int left, int top, int right, int bottom) noexcept;
+
+ Q_DECL_CONSTEXPR bool isNull() const noexcept;
+
+ Q_DECL_CONSTEXPR int left() const noexcept;
+ Q_DECL_CONSTEXPR int top() const noexcept;
+ Q_DECL_CONSTEXPR int right() const noexcept;
+ Q_DECL_CONSTEXPR int bottom() const noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR void setLeft(int left) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR void setTop(int top) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR void setRight(int right) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR void setBottom(int bottom) noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR QMargins &operator+=(const QMargins &margins) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR QMargins &operator-=(const QMargins &margins) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR QMargins &operator+=(int) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR QMargins &operator-=(int) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR QMargins &operator*=(int) noexcept;
Q_DECL_RELAXED_CONSTEXPR QMargins &operator/=(int);
- Q_DECL_RELAXED_CONSTEXPR QMargins &operator*=(qreal) Q_DECL_NOTHROW;
+ Q_DECL_RELAXED_CONSTEXPR QMargins &operator*=(qreal) noexcept;
Q_DECL_RELAXED_CONSTEXPR QMargins &operator/=(qreal);
private:
@@ -81,8 +81,8 @@ private:
int m_right;
int m_bottom;
- friend Q_DECL_CONSTEXPR inline bool operator==(const QMargins &, const QMargins &) Q_DECL_NOTHROW;
- friend Q_DECL_CONSTEXPR inline bool operator!=(const QMargins &, const QMargins &) Q_DECL_NOTHROW;
+ friend Q_DECL_CONSTEXPR inline bool operator==(const QMargins &, const QMargins &) noexcept;
+ friend Q_DECL_CONSTEXPR inline bool operator!=(const QMargins &, const QMargins &) noexcept;
};
Q_DECLARE_TYPEINFO(QMargins, Q_MOVABLE_TYPE);
@@ -99,40 +99,40 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QMargins &);
QMargins inline functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QMargins::QMargins() Q_DECL_NOTHROW : m_left(0), m_top(0), m_right(0), m_bottom(0) {}
+Q_DECL_CONSTEXPR inline QMargins::QMargins() noexcept : m_left(0), m_top(0), m_right(0), m_bottom(0) {}
-Q_DECL_CONSTEXPR inline QMargins::QMargins(int aleft, int atop, int aright, int abottom) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins::QMargins(int aleft, int atop, int aright, int abottom) noexcept
: m_left(aleft), m_top(atop), m_right(aright), m_bottom(abottom) {}
-Q_DECL_CONSTEXPR inline bool QMargins::isNull() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QMargins::isNull() const noexcept
{ return m_left==0 && m_top==0 && m_right==0 && m_bottom==0; }
-Q_DECL_CONSTEXPR inline int QMargins::left() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QMargins::left() const noexcept
{ return m_left; }
-Q_DECL_CONSTEXPR inline int QMargins::top() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QMargins::top() const noexcept
{ return m_top; }
-Q_DECL_CONSTEXPR inline int QMargins::right() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QMargins::right() const noexcept
{ return m_right; }
-Q_DECL_CONSTEXPR inline int QMargins::bottom() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QMargins::bottom() const noexcept
{ return m_bottom; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setLeft(int aleft) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setLeft(int aleft) noexcept
{ m_left = aleft; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setTop(int atop) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setTop(int atop) noexcept
{ m_top = atop; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setRight(int aright) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setRight(int aright) noexcept
{ m_right = aright; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setBottom(int abottom) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QMargins::setBottom(int abottom) noexcept
{ m_bottom = abottom; }
-Q_DECL_CONSTEXPR inline bool operator==(const QMargins &m1, const QMargins &m2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator==(const QMargins &m1, const QMargins &m2) noexcept
{
return
m1.m_left == m2.m_left &&
@@ -141,7 +141,7 @@ Q_DECL_CONSTEXPR inline bool operator==(const QMargins &m1, const QMargins &m2)
m1.m_bottom == m2.m_bottom;
}
-Q_DECL_CONSTEXPR inline bool operator!=(const QMargins &m1, const QMargins &m2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator!=(const QMargins &m1, const QMargins &m2) noexcept
{
return
m1.m_left != m2.m_left ||
@@ -150,55 +150,55 @@ Q_DECL_CONSTEXPR inline bool operator!=(const QMargins &m1, const QMargins &m2)
m1.m_bottom != m2.m_bottom;
}
-Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &m1, const QMargins &m2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &m1, const QMargins &m2) noexcept
{
return QMargins(m1.left() + m2.left(), m1.top() + m2.top(),
m1.right() + m2.right(), m1.bottom() + m2.bottom());
}
-Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &m1, const QMargins &m2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &m1, const QMargins &m2) noexcept
{
return QMargins(m1.left() - m2.left(), m1.top() - m2.top(),
m1.right() - m2.right(), m1.bottom() - m2.bottom());
}
-Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &lhs, int rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &lhs, int rhs) noexcept
{
return QMargins(lhs.left() + rhs, lhs.top() + rhs,
lhs.right() + rhs, lhs.bottom() + rhs);
}
-Q_DECL_CONSTEXPR inline QMargins operator+(int lhs, const QMargins &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator+(int lhs, const QMargins &rhs) noexcept
{
return QMargins(rhs.left() + lhs, rhs.top() + lhs,
rhs.right() + lhs, rhs.bottom() + lhs);
}
-Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &lhs, int rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &lhs, int rhs) noexcept
{
return QMargins(lhs.left() - rhs, lhs.top() - rhs,
lhs.right() - rhs, lhs.bottom() - rhs);
}
-Q_DECL_CONSTEXPR inline QMargins operator*(const QMargins &margins, int factor) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator*(const QMargins &margins, int factor) noexcept
{
return QMargins(margins.left() * factor, margins.top() * factor,
margins.right() * factor, margins.bottom() * factor);
}
-Q_DECL_CONSTEXPR inline QMargins operator*(int factor, const QMargins &margins) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator*(int factor, const QMargins &margins) noexcept
{
return QMargins(margins.left() * factor, margins.top() * factor,
margins.right() * factor, margins.bottom() * factor);
}
-Q_DECL_CONSTEXPR inline QMargins operator*(const QMargins &margins, qreal factor) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator*(const QMargins &margins, qreal factor) noexcept
{
return QMargins(qRound(margins.left() * factor), qRound(margins.top() * factor),
qRound(margins.right() * factor), qRound(margins.bottom() * factor));
}
-Q_DECL_CONSTEXPR inline QMargins operator*(qreal factor, const QMargins &margins) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator*(qreal factor, const QMargins &margins) noexcept
{
return QMargins(qRound(margins.left() * factor), qRound(margins.top() * factor),
qRound(margins.right() * factor), qRound(margins.bottom() * factor));
@@ -216,17 +216,17 @@ Q_DECL_CONSTEXPR inline QMargins operator/(const QMargins &margins, qreal diviso
qRound(margins.right() / divisor), qRound(margins.bottom() / divisor));
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator+=(const QMargins &margins) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator+=(const QMargins &margins) noexcept
{
return *this = *this + margins;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator-=(const QMargins &margins) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator-=(const QMargins &margins) noexcept
{
return *this = *this - margins;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator+=(int margin) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator+=(int margin) noexcept
{
m_left += margin;
m_top += margin;
@@ -235,7 +235,7 @@ Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator+=(int margin) Q_DEC
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator-=(int margin) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator-=(int margin) noexcept
{
m_left -= margin;
m_top -= margin;
@@ -244,7 +244,7 @@ Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator-=(int margin) Q_DEC
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator*=(int factor) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator*=(int factor) noexcept
{
return *this = *this * factor;
}
@@ -254,7 +254,7 @@ Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator/=(int divisor)
return *this = *this / divisor;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator*=(qreal factor) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator*=(qreal factor) noexcept
{
return *this = *this * factor;
}
@@ -264,12 +264,12 @@ Q_DECL_RELAXED_CONSTEXPR inline QMargins &QMargins::operator/=(qreal divisor)
return *this = *this / divisor;
}
-Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &margins) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &margins) noexcept
{
return margins;
}
-Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &margins) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &margins) noexcept
{
return QMargins(-margins.left(), -margins.top(), -margins.right(), -margins.bottom());
}
@@ -285,30 +285,30 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QMargins &);
class QMarginsF
{
public:
- Q_DECL_CONSTEXPR QMarginsF() Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QMarginsF(qreal left, qreal top, qreal right, qreal bottom) Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QMarginsF(const QMargins &margins) Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR bool isNull() const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR qreal left() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR qreal top() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR qreal right() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR qreal bottom() const Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR void setLeft(qreal left) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR void setTop(qreal top) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR void setRight(qreal right) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR void setBottom(qreal bottom) Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator+=(const QMarginsF &margins) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator-=(const QMarginsF &margins) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator+=(qreal addend) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator-=(qreal subtrahend) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator*=(qreal factor) Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR QMarginsF() noexcept;
+ Q_DECL_CONSTEXPR QMarginsF(qreal left, qreal top, qreal right, qreal bottom) noexcept;
+ Q_DECL_CONSTEXPR QMarginsF(const QMargins &margins) noexcept;
+
+ Q_DECL_CONSTEXPR bool isNull() const noexcept;
+
+ Q_DECL_CONSTEXPR qreal left() const noexcept;
+ Q_DECL_CONSTEXPR qreal top() const noexcept;
+ Q_DECL_CONSTEXPR qreal right() const noexcept;
+ Q_DECL_CONSTEXPR qreal bottom() const noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR void setLeft(qreal left) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR void setTop(qreal top) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR void setRight(qreal right) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR void setBottom(qreal bottom) noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator+=(const QMarginsF &margins) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator-=(const QMarginsF &margins) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator+=(qreal addend) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator-=(qreal subtrahend) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator*=(qreal factor) noexcept;
Q_DECL_RELAXED_CONSTEXPR QMarginsF &operator/=(qreal divisor);
- Q_DECL_CONSTEXPR inline QMargins toMargins() const Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR inline QMargins toMargins() const noexcept;
private:
qreal m_left;
@@ -332,44 +332,44 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QMarginsF &);
QMarginsF inline functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF() Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF() noexcept
: m_left(0), m_top(0), m_right(0), m_bottom(0) {}
-Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF(qreal aleft, qreal atop, qreal aright, qreal abottom) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF(qreal aleft, qreal atop, qreal aright, qreal abottom) noexcept
: m_left(aleft), m_top(atop), m_right(aright), m_bottom(abottom) {}
-Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF(const QMargins &margins) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF(const QMargins &margins) noexcept
: m_left(margins.left()), m_top(margins.top()), m_right(margins.right()), m_bottom(margins.bottom()) {}
-Q_DECL_CONSTEXPR inline bool QMarginsF::isNull() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QMarginsF::isNull() const noexcept
{ return qFuzzyIsNull(m_left) && qFuzzyIsNull(m_top) && qFuzzyIsNull(m_right) && qFuzzyIsNull(m_bottom); }
-Q_DECL_CONSTEXPR inline qreal QMarginsF::left() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline qreal QMarginsF::left() const noexcept
{ return m_left; }
-Q_DECL_CONSTEXPR inline qreal QMarginsF::top() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline qreal QMarginsF::top() const noexcept
{ return m_top; }
-Q_DECL_CONSTEXPR inline qreal QMarginsF::right() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline qreal QMarginsF::right() const noexcept
{ return m_right; }
-Q_DECL_CONSTEXPR inline qreal QMarginsF::bottom() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline qreal QMarginsF::bottom() const noexcept
{ return m_bottom; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setLeft(qreal aleft) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setLeft(qreal aleft) noexcept
{ m_left = aleft; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setTop(qreal atop) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setTop(qreal atop) noexcept
{ m_top = atop; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setRight(qreal aright) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setRight(qreal aright) noexcept
{ m_right = aright; }
-Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setBottom(qreal abottom) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QMarginsF::setBottom(qreal abottom) noexcept
{ m_bottom = abottom; }
-Q_DECL_CONSTEXPR inline bool operator==(const QMarginsF &lhs, const QMarginsF &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator==(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
{
return qFuzzyCompare(lhs.left(), rhs.left())
&& qFuzzyCompare(lhs.top(), rhs.top())
@@ -377,48 +377,48 @@ Q_DECL_CONSTEXPR inline bool operator==(const QMarginsF &lhs, const QMarginsF &r
&& qFuzzyCompare(lhs.bottom(), rhs.bottom());
}
-Q_DECL_CONSTEXPR inline bool operator!=(const QMarginsF &lhs, const QMarginsF &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator!=(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
{
return !operator==(lhs, rhs);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &lhs, const QMarginsF &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
{
return QMarginsF(lhs.left() + rhs.left(), lhs.top() + rhs.top(),
lhs.right() + rhs.right(), lhs.bottom() + rhs.bottom());
}
-Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &lhs, const QMarginsF &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
{
return QMarginsF(lhs.left() - rhs.left(), lhs.top() - rhs.top(),
lhs.right() - rhs.right(), lhs.bottom() - rhs.bottom());
}
-Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &lhs, qreal rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &lhs, qreal rhs) noexcept
{
return QMarginsF(lhs.left() + rhs, lhs.top() + rhs,
lhs.right() + rhs, lhs.bottom() + rhs);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator+(qreal lhs, const QMarginsF &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF operator+(qreal lhs, const QMarginsF &rhs) noexcept
{
return QMarginsF(rhs.left() + lhs, rhs.top() + lhs,
rhs.right() + lhs, rhs.bottom() + lhs);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &lhs, qreal rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &lhs, qreal rhs) noexcept
{
return QMarginsF(lhs.left() - rhs, lhs.top() - rhs,
lhs.right() - rhs, lhs.bottom() - rhs);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator*(const QMarginsF &lhs, qreal rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF operator*(const QMarginsF &lhs, qreal rhs) noexcept
{
return QMarginsF(lhs.left() * rhs, lhs.top() * rhs,
lhs.right() * rhs, lhs.bottom() * rhs);
}
-Q_DECL_CONSTEXPR inline QMarginsF operator*(qreal lhs, const QMarginsF &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF operator*(qreal lhs, const QMarginsF &rhs) noexcept
{
return QMarginsF(rhs.left() * lhs, rhs.top() * lhs,
rhs.right() * lhs, rhs.bottom() * lhs);
@@ -430,17 +430,17 @@ Q_DECL_CONSTEXPR inline QMarginsF operator/(const QMarginsF &lhs, qreal divisor)
lhs.right() / divisor, lhs.bottom() / divisor);
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator+=(const QMarginsF &margins) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator+=(const QMarginsF &margins) noexcept
{
return *this = *this + margins;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator-=(const QMarginsF &margins) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator-=(const QMarginsF &margins) noexcept
{
return *this = *this - margins;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator+=(qreal addend) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator+=(qreal addend) noexcept
{
m_left += addend;
m_top += addend;
@@ -449,7 +449,7 @@ Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator+=(qreal addend) Q
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator-=(qreal subtrahend) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator-=(qreal subtrahend) noexcept
{
m_left -= subtrahend;
m_top -= subtrahend;
@@ -458,7 +458,7 @@ Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator-=(qreal subtrahen
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator*=(qreal factor) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator*=(qreal factor) noexcept
{
return *this = *this * factor;
}
@@ -468,17 +468,17 @@ Q_DECL_RELAXED_CONSTEXPR inline QMarginsF &QMarginsF::operator/=(qreal divisor)
return *this = *this / divisor;
}
-Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &margins) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &margins) noexcept
{
return margins;
}
-Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &margins) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &margins) noexcept
{
return QMarginsF(-margins.left(), -margins.top(), -margins.right(), -margins.bottom());
}
-Q_DECL_CONSTEXPR inline QMargins QMarginsF::toMargins() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QMargins QMarginsF::toMargins() const noexcept
{
return QMargins(qRound(m_left), qRound(m_top), qRound(m_right), qRound(m_bottom));
}
diff --git a/src/corelib/tools/qoffsetstringarray_p.h b/src/corelib/tools/qoffsetstringarray_p.h
new file mode 100644
index 0000000000..4dd9e9603b
--- /dev/null
+++ b/src/corelib/tools/qoffsetstringarray_p.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOFFSETSTRINGARRAY_P_H
+#define QOFFSETSTRINGARRAY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qglobal_p.h"
+
+#include <tuple>
+#include <array>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+template<int N, int O, int I, int ... Idx>
+struct OffsetSequenceHelper : OffsetSequenceHelper<N - 1, O + I, Idx..., O> { };
+
+template<int Last, int I, int S, int ... Idx>
+struct OffsetSequenceHelper<1, Last, I, S, Idx...> : IndexesList<Last + I, Idx..., Last>
+{
+ static const constexpr auto Length = Last + I;
+ using Type = typename std::conditional<
+ Last <= std::numeric_limits<quint8>::max(),
+ quint8,
+ typename std::conditional<
+ Last <= std::numeric_limits<quint16>::max(),
+ quint16,
+ int>::type
+ >::type;
+};
+
+template<int ... Idx>
+struct OffsetSequence : OffsetSequenceHelper<sizeof ... (Idx), 0, Idx..., 0> { };
+
+template<int N>
+struct StaticString
+{
+ const char data[N];
+};
+
+
+template<>
+struct StaticString<0>
+{
+ static constexpr int size() noexcept
+ {
+ return 0;
+ }
+};
+
+template<typename, typename>
+struct StaticStringBuilder;
+
+template<int ... I1, int ... I2>
+struct StaticStringBuilder<IndexesList<I1...>, IndexesList<I2...>>
+{
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_MSVC(4100) // The formal parameter is not referenced in the body of the function.
+ // The unreferenced parameter is ignored.
+ // It happens when 'rs' is StaticString<0>
+ template<int N1, int N2>
+ static constexpr StaticString<N1 + N2> concatenate(
+ const char (&ls)[N1], const StaticString<N2> &rs) noexcept
+ {
+ return StaticString<N1 + N2>{{ls[I1]..., rs.data[I2]...}};
+ }
+QT_WARNING_POP
+};
+
+template<int Sum>
+constexpr StaticString<0> staticString() noexcept
+{
+ return StaticString<0>{};
+}
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_MSVC(4503)
+template<int Sum, int I, int ... Ix>
+constexpr StaticString<Sum> staticString(const char (&s)[I], const char (&...sx)[Ix]) noexcept
+{
+ return StaticStringBuilder<
+ makeIndexSequence<I>,
+ makeIndexSequence<Sum - I>>::concatenate(s, staticString<Sum - I>(sx...));
+}
+QT_WARNING_POP
+} // namespace QtPrivate
+
+template<typename T, int SizeString, int SizeOffsets>
+class QOffsetStringArray
+{
+public:
+ using Type = T;
+
+ template<int ... Ox>
+ constexpr QOffsetStringArray(const QtPrivate::StaticString<SizeString> &str,
+ QtPrivate::IndexesList<SizeString, Ox...>) noexcept
+ : m_string(str),
+ m_offsets{Ox...}
+ { }
+
+ constexpr inline const char *operator[](const int index) const noexcept
+ {
+ return m_string.data + m_offsets[qBound(int(0), index, SizeOffsets - 1)];
+ }
+
+ constexpr inline const char *at(const int index) const noexcept
+ {
+ return m_string.data + m_offsets[index];
+ }
+
+ constexpr inline const char *str() const { return m_string.data; }
+ constexpr inline const T *offsets() const { return m_offsets; }
+ constexpr inline int count() const { return SizeOffsets; };
+
+ static constexpr const auto sizeString = SizeString;
+ static constexpr const auto sizeOffsets = SizeOffsets;
+
+private:
+ QtPrivate::StaticString<SizeString> m_string;
+ const T m_offsets[SizeOffsets];
+};
+
+template<typename T, int N, int ... Ox>
+constexpr QOffsetStringArray<T, N, sizeof ... (Ox)> qOffsetStringArray(
+ const QtPrivate::StaticString<N> &string,
+ QtPrivate::IndexesList<N, Ox...> offsets) noexcept
+{
+ return QOffsetStringArray<T, N, sizeof ... (Ox)>(
+ string,
+ offsets);
+}
+
+template<int ... Nx>
+struct QOffsetStringArrayRet
+{
+ using Offsets = QtPrivate::OffsetSequence<Nx...>;
+ using Type = QOffsetStringArray<typename Offsets::Type, Offsets::Length, sizeof ... (Nx)>;
+};
+
+template<int ... Nx>
+constexpr auto qOffsetStringArray(const char (&...strings)[Nx]) noexcept -> typename QOffsetStringArrayRet<Nx...>::Type
+{
+ using Offsets = QtPrivate::OffsetSequence<Nx...>;
+ return qOffsetStringArray<typename Offsets::Type>(
+ QtPrivate::staticString<Offsets::Length>(strings...), Offsets{});
+}
+
+QT_END_NAMESPACE
+
+#endif // QOFFSETSTRINGARRAY_P_H
diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h
index 94977fc826..9ebf88bc8f 100644
--- a/src/corelib/tools/qpair.h
+++ b/src/corelib/tools/qpair.h
@@ -52,41 +52,39 @@ struct QPair
typedef T2 second_type;
Q_DECL_CONSTEXPR QPair()
- Q_DECL_NOEXCEPT_EXPR((std::is_nothrow_default_constructible<T1>::value &&
+ noexcept((std::is_nothrow_default_constructible<T1>::value &&
std::is_nothrow_default_constructible<T2>::value))
: first(), second() {}
Q_DECL_CONSTEXPR QPair(const T1 &t1, const T2 &t2)
- Q_DECL_NOEXCEPT_EXPR((std::is_nothrow_copy_constructible<T1>::value &&
+ noexcept((std::is_nothrow_copy_constructible<T1>::value &&
std::is_nothrow_copy_constructible<T2>::value))
: first(t1), second(t2) {}
// compiler-generated copy/move ctor/assignment operators are fine!
template <typename TT1, typename TT2>
Q_DECL_CONSTEXPR QPair(const QPair<TT1, TT2> &p)
- Q_DECL_NOEXCEPT_EXPR((std::is_nothrow_constructible<T1, TT1&>::value &&
+ noexcept((std::is_nothrow_constructible<T1, TT1&>::value &&
std::is_nothrow_constructible<T2, TT2&>::value))
: first(p.first), second(p.second) {}
template <typename TT1, typename TT2>
Q_DECL_RELAXED_CONSTEXPR QPair &operator=(const QPair<TT1, TT2> &p)
- Q_DECL_NOEXCEPT_EXPR((std::is_nothrow_assignable<T1, TT1&>::value &&
+ noexcept((std::is_nothrow_assignable<T1, TT1&>::value &&
std::is_nothrow_assignable<T2, TT2&>::value))
{ first = p.first; second = p.second; return *this; }
-#ifdef Q_COMPILER_RVALUE_REFS
template <typename TT1, typename TT2>
Q_DECL_CONSTEXPR QPair(QPair<TT1, TT2> &&p)
- Q_DECL_NOEXCEPT_EXPR((std::is_nothrow_constructible<T1, TT1>::value &&
+ noexcept((std::is_nothrow_constructible<T1, TT1>::value &&
std::is_nothrow_constructible<T2, TT2>::value))
// can't use std::move here as it's not constexpr in C++11:
: first(static_cast<TT1 &&>(p.first)), second(static_cast<TT2 &&>(p.second)) {}
template <typename TT1, typename TT2>
Q_DECL_RELAXED_CONSTEXPR QPair &operator=(QPair<TT1, TT2> &&p)
- Q_DECL_NOEXCEPT_EXPR((std::is_nothrow_assignable<T1, TT1>::value &&
+ noexcept((std::is_nothrow_assignable<T1, TT1>::value &&
std::is_nothrow_assignable<T2, TT2>::value))
{ first = std::move(p.first); second = std::move(p.second); return *this; }
-#endif
Q_DECL_RELAXED_CONSTEXPR void swap(QPair &other)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qSwap(other.first, other.first)) && noexcept(qSwap(other.second, other.second)))
+ noexcept(noexcept(qSwap(other.first, other.first)) && noexcept(qSwap(other.second, other.second)))
{
// use qSwap() to pick up ADL swaps automatically:
qSwap(first, other.first);
@@ -97,8 +95,13 @@ struct QPair
T2 second;
};
+#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
+template<class T1, class T2>
+QPair(T1, T2) -> QPair<T1, T2>;
+#endif
+
template <typename T1, typename T2>
-void swap(QPair<T1, T2> &lhs, QPair<T1, T2> &rhs) Q_DECL_NOEXCEPT_EXPR(noexcept(lhs.swap(rhs)))
+void swap(QPair<T1, T2> &lhs, QPair<T1, T2> &rhs) noexcept(noexcept(lhs.swap(rhs)))
{ lhs.swap(rhs); }
// mark QPair<T1,T2> as complex/movable/primitive depending on the
@@ -108,45 +111,45 @@ class QTypeInfo<QPair<T1, T2> > : public QTypeInfoMerger<QPair<T1, T2>, T1, T2>
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator==(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
- Q_DECL_NOEXCEPT_EXPR(noexcept(p1.first == p2.first && p1.second == p2.second))
+ noexcept(noexcept(p1.first == p2.first && p1.second == p2.second))
{ return p1.first == p2.first && p1.second == p2.second; }
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator!=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
- Q_DECL_NOEXCEPT_EXPR(noexcept(!(p1 == p2)))
+ noexcept(noexcept(!(p1 == p2)))
{ return !(p1 == p2); }
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator<(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
- Q_DECL_NOEXCEPT_EXPR(noexcept(p1.first < p2.first || (!(p2.first < p1.first) && p1.second < p2.second)))
+ noexcept(noexcept(p1.first < p2.first || (!(p2.first < p1.first) && p1.second < p2.second)))
{
return p1.first < p2.first || (!(p2.first < p1.first) && p1.second < p2.second);
}
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator>(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
- Q_DECL_NOEXCEPT_EXPR(noexcept(p2 < p1))
+ noexcept(noexcept(p2 < p1))
{
return p2 < p1;
}
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator<=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
- Q_DECL_NOEXCEPT_EXPR(noexcept(!(p2 < p1)))
+ noexcept(noexcept(!(p2 < p1)))
{
return !(p2 < p1);
}
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator>=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
- Q_DECL_NOEXCEPT_EXPR(noexcept(!(p1 < p2)))
+ noexcept(noexcept(!(p1 < p2)))
{
return !(p1 < p2);
}
template <class T1, class T2>
Q_DECL_CONSTEXPR Q_OUTOFLINE_TEMPLATE QPair<T1, T2> qMakePair(const T1 &x, const T2 &y)
- Q_DECL_NOEXCEPT_EXPR(noexcept(QPair<T1, T2>(x, y)))
+ noexcept(noexcept(QPair<T1, T2>(x, y)))
{
return QPair<T1, T2>(x, y);
}
diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h
index d7323f7707..34df673b93 100644
--- a/src/corelib/tools/qpoint.h
+++ b/src/corelib/tools/qpoint.h
@@ -94,7 +94,7 @@ public:
friend Q_DECL_CONSTEXPR inline const QPoint operator/(const QPoint &, qreal);
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT CGPoint toCGPoint() const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT CGPoint toCGPoint() const noexcept;
#endif
private:
@@ -256,8 +256,8 @@ public:
Q_DECL_CONSTEXPR QPoint toPoint() const;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT static QPointF fromCGPoint(CGPoint point) Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT CGPoint toCGPoint() const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT static QPointF fromCGPoint(CGPoint point) noexcept;
+ Q_REQUIRED_RESULT CGPoint toCGPoint() const noexcept;
#endif
private:
diff --git a/src/corelib/tools/qqueue.h b/src/corelib/tools/qqueue.h
index b55f210577..d5a60ada56 100644
--- a/src/corelib/tools/qqueue.h
+++ b/src/corelib/tools/qqueue.h
@@ -50,11 +50,11 @@ class QQueue : public QList<T>
{
public:
// compiler-generated special member functions are fine!
- inline void swap(QQueue<T> &other) Q_DECL_NOTHROW { QList<T>::swap(other); } // prevent QList<->QQueue swaps
+ inline void swap(QQueue<T> &other) noexcept { QList<T>::swap(other); } // prevent QList<->QQueue swaps
#ifndef Q_QDOC
// bring in QList::swap(int, int). We cannot say using QList<T>::swap,
// because we don't want to make swap(QList&) available.
- inline void swap(int i, int j) { QList<T>::swap(i, j); }
+ Q_DECL_DEPRECATED inline void swap(int i, int j) { QList<T>::swapItemsAt(i, j); }
#endif
inline void enqueue(const T &t) { QList<T>::append(t); }
inline T dequeue() { return QList<T>::takeFirst(); }
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index 6e51deebea..d622f92530 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -300,7 +300,7 @@ QT_BEGIN_NAMESPACE
\sa isValid(), isEmpty()
*/
-QRect QRect::normalized() const Q_DECL_NOTHROW
+QRect QRect::normalized() const noexcept
{
QRect r;
if (x2 < x1 - 1) { // swap bad x values
@@ -820,7 +820,7 @@ QRect QRect::normalized() const Q_DECL_NOTHROW
\sa intersects()
*/
-bool QRect::contains(const QPoint &p, bool proper) const Q_DECL_NOTHROW
+bool QRect::contains(const QPoint &p, bool proper) const noexcept
{
int l, r;
if (x2 < x1 - 1) {
@@ -884,7 +884,7 @@ bool QRect::contains(const QPoint &p, bool proper) const Q_DECL_NOTHROW
rectangle (not on the edge).
*/
-bool QRect::contains(const QRect &r, bool proper) const Q_DECL_NOTHROW
+bool QRect::contains(const QRect &r, bool proper) const noexcept
{
if (isNull() || r.isNull())
return false;
@@ -962,7 +962,7 @@ bool QRect::contains(const QRect &r, bool proper) const Q_DECL_NOTHROW
\sa operator|=(), united()
*/
-QRect QRect::operator|(const QRect &r) const Q_DECL_NOTHROW
+QRect QRect::operator|(const QRect &r) const noexcept
{
if (isNull())
return r;
@@ -1033,7 +1033,7 @@ QRect QRect::operator|(const QRect &r) const Q_DECL_NOTHROW
\sa operator&=(), intersected()
*/
-QRect QRect::operator&(const QRect &r) const Q_DECL_NOTHROW
+QRect QRect::operator&(const QRect &r) const noexcept
{
if (isNull() || r.isNull())
return QRect();
@@ -1112,7 +1112,7 @@ QRect QRect::operator&(const QRect &r) const Q_DECL_NOTHROW
\sa contains()
*/
-bool QRect::intersects(const QRect &r) const Q_DECL_NOTHROW
+bool QRect::intersects(const QRect &r) const noexcept
{
if (isNull() || r.isNull())
return false;
@@ -1540,7 +1540,7 @@ QDebug operator<<(QDebug dbg, const QRect &r)
\sa isValid(), isEmpty()
*/
-QRectF QRectF::normalized() const Q_DECL_NOTHROW
+QRectF QRectF::normalized() const noexcept
{
QRectF r = *this;
if (r.w < 0) {
@@ -1964,7 +1964,7 @@ QRectF QRectF::normalized() const Q_DECL_NOTHROW
\sa intersects()
*/
-bool QRectF::contains(const QPointF &p) const Q_DECL_NOTHROW
+bool QRectF::contains(const QPointF &p) const noexcept
{
qreal l = xp;
qreal r = xp;
@@ -2010,7 +2010,7 @@ bool QRectF::contains(const QPointF &p) const Q_DECL_NOTHROW
otherwise returns \c false.
*/
-bool QRectF::contains(const QRectF &r) const Q_DECL_NOTHROW
+bool QRectF::contains(const QRectF &r) const noexcept
{
qreal l1 = xp;
qreal r1 = xp;
@@ -2148,7 +2148,7 @@ bool QRectF::contains(const QRectF &r) const Q_DECL_NOTHROW
\sa united(), operator|=()
*/
-QRectF QRectF::operator|(const QRectF &r) const Q_DECL_NOTHROW
+QRectF QRectF::operator|(const QRectF &r) const noexcept
{
if (isNull())
return r;
@@ -2217,7 +2217,7 @@ QRectF QRectF::operator|(const QRectF &r) const Q_DECL_NOTHROW
\sa operator&=(), intersected()
*/
-QRectF QRectF::operator&(const QRectF &r) const Q_DECL_NOTHROW
+QRectF QRectF::operator&(const QRectF &r) const noexcept
{
qreal l1 = xp;
qreal r1 = xp;
@@ -2302,7 +2302,7 @@ QRectF QRectF::operator&(const QRectF &r) const Q_DECL_NOTHROW
\sa contains()
*/
-bool QRectF::intersects(const QRectF &r) const Q_DECL_NOTHROW
+bool QRectF::intersects(const QRectF &r) const noexcept
{
qreal l1 = xp;
qreal r1 = xp;
@@ -2369,7 +2369,7 @@ bool QRectF::intersects(const QRectF &r) const Q_DECL_NOTHROW
\sa toRect()
*/
-QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW
+QRect QRectF::toAlignedRect() const noexcept
{
int xmin = int(qFloor(xp));
int xmax = int(qCeil(xp + w));
diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h
index 3b40055b5a..7aa2312f38 100644
--- a/src/corelib/tools/qrect.h
+++ b/src/corelib/tools/qrect.h
@@ -57,104 +57,104 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QRect
{
public:
- Q_DECL_CONSTEXPR QRect() Q_DECL_NOTHROW : x1(0), y1(0), x2(-1), y2(-1) {}
- Q_DECL_CONSTEXPR QRect(const QPoint &topleft, const QPoint &bottomright) Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QRect(const QPoint &topleft, const QSize &size) Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QRect(int left, int top, int width, int height) Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline bool isNull() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline bool isEmpty() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline bool isValid() const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline int left() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline int top() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline int right() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline int bottom() const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT QRect normalized() const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline int x() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline int y() const Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setLeft(int pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setTop(int pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setRight(int pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottom(int pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setX(int x) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setY(int y) Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline void setTopLeft(const QPoint &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottomRight(const QPoint &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setTopRight(const QPoint &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottomLeft(const QPoint &p) Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline QPoint topLeft() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline QPoint bottomRight() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline QPoint topRight() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline QPoint bottomLeft() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline QPoint center() const Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline void moveLeft(int pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTop(int pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveRight(int pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottom(int pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTopLeft(const QPoint &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottomRight(const QPoint &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTopRight(const QPoint &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottomLeft(const QPoint &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveCenter(const QPoint &p) Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline void translate(int dx, int dy) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void translate(const QPoint &p) Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect translated(int dx, int dy) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect translated(const QPoint &p) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect transposed() const Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline void moveTo(int x, int t) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTo(const QPoint &p) Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline void setRect(int x, int y, int w, int h) Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR QRect() noexcept : x1(0), y1(0), x2(-1), y2(-1) {}
+ Q_DECL_CONSTEXPR QRect(const QPoint &topleft, const QPoint &bottomright) noexcept;
+ Q_DECL_CONSTEXPR QRect(const QPoint &topleft, const QSize &size) noexcept;
+ Q_DECL_CONSTEXPR QRect(int left, int top, int width, int height) noexcept;
+
+ Q_DECL_CONSTEXPR inline bool isNull() const noexcept;
+ Q_DECL_CONSTEXPR inline bool isEmpty() const noexcept;
+ Q_DECL_CONSTEXPR inline bool isValid() const noexcept;
+
+ Q_DECL_CONSTEXPR inline int left() const noexcept;
+ Q_DECL_CONSTEXPR inline int top() const noexcept;
+ Q_DECL_CONSTEXPR inline int right() const noexcept;
+ Q_DECL_CONSTEXPR inline int bottom() const noexcept;
+ Q_REQUIRED_RESULT QRect normalized() const noexcept;
+
+ Q_DECL_CONSTEXPR inline int x() const noexcept;
+ Q_DECL_CONSTEXPR inline int y() const noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setLeft(int pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setTop(int pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setRight(int pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setBottom(int pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setX(int x) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setY(int y) noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline void setTopLeft(const QPoint &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setBottomRight(const QPoint &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setTopRight(const QPoint &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setBottomLeft(const QPoint &p) noexcept;
+
+ Q_DECL_CONSTEXPR inline QPoint topLeft() const noexcept;
+ Q_DECL_CONSTEXPR inline QPoint bottomRight() const noexcept;
+ Q_DECL_CONSTEXPR inline QPoint topRight() const noexcept;
+ Q_DECL_CONSTEXPR inline QPoint bottomLeft() const noexcept;
+ Q_DECL_CONSTEXPR inline QPoint center() const noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline void moveLeft(int pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveTop(int pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveRight(int pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveBottom(int pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveTopLeft(const QPoint &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveBottomRight(const QPoint &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveTopRight(const QPoint &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveBottomLeft(const QPoint &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveCenter(const QPoint &p) noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline void translate(int dx, int dy) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void translate(const QPoint &p) noexcept;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect translated(int dx, int dy) const noexcept;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect translated(const QPoint &p) const noexcept;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect transposed() const noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline void moveTo(int x, int t) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveTo(const QPoint &p) noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline void setRect(int x, int y, int w, int h) noexcept;
Q_DECL_RELAXED_CONSTEXPR inline void getRect(int *x, int *y, int *w, int *h) const;
- Q_DECL_RELAXED_CONSTEXPR inline void setCoords(int x1, int y1, int x2, int y2) Q_DECL_NOTHROW;
+ Q_DECL_RELAXED_CONSTEXPR inline void setCoords(int x1, int y1, int x2, int y2) noexcept;
Q_DECL_RELAXED_CONSTEXPR inline void getCoords(int *x1, int *y1, int *x2, int *y2) const;
- Q_DECL_RELAXED_CONSTEXPR inline void adjust(int x1, int y1, int x2, int y2) Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect adjusted(int x1, int y1, int x2, int y2) const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline QSize size() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline int width() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline int height() const Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setWidth(int w) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setHeight(int h) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setSize(const QSize &s) Q_DECL_NOTHROW;
-
- QRect operator|(const QRect &r) const Q_DECL_NOTHROW;
- QRect operator&(const QRect &r) const Q_DECL_NOTHROW;
- inline QRect& operator|=(const QRect &r) Q_DECL_NOTHROW;
- inline QRect& operator&=(const QRect &r) Q_DECL_NOTHROW;
-
- bool contains(const QRect &r, bool proper = false) const Q_DECL_NOTHROW;
- bool contains(const QPoint &p, bool proper=false) const Q_DECL_NOTHROW;
- inline bool contains(int x, int y) const Q_DECL_NOTHROW;
- inline bool contains(int x, int y, bool proper) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT inline QRect united(const QRect &other) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT inline QRect intersected(const QRect &other) const Q_DECL_NOTHROW;
- bool intersects(const QRect &r) const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline QRect marginsAdded(const QMargins &margins) const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline QRect marginsRemoved(const QMargins &margins) const Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline QRect &operator+=(const QMargins &margins) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline QRect &operator-=(const QMargins &margins) Q_DECL_NOTHROW;
+ Q_DECL_RELAXED_CONSTEXPR inline void adjust(int x1, int y1, int x2, int y2) noexcept;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect adjusted(int x1, int y1, int x2, int y2) const noexcept;
+
+ Q_DECL_CONSTEXPR inline QSize size() const noexcept;
+ Q_DECL_CONSTEXPR inline int width() const noexcept;
+ Q_DECL_CONSTEXPR inline int height() const noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setWidth(int w) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setHeight(int h) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setSize(const QSize &s) noexcept;
+
+ QRect operator|(const QRect &r) const noexcept;
+ QRect operator&(const QRect &r) const noexcept;
+ inline QRect& operator|=(const QRect &r) noexcept;
+ inline QRect& operator&=(const QRect &r) noexcept;
+
+ bool contains(const QRect &r, bool proper = false) const noexcept;
+ bool contains(const QPoint &p, bool proper=false) const noexcept;
+ inline bool contains(int x, int y) const noexcept;
+ inline bool contains(int x, int y, bool proper) const noexcept;
+ Q_REQUIRED_RESULT inline QRect united(const QRect &other) const noexcept;
+ Q_REQUIRED_RESULT inline QRect intersected(const QRect &other) const noexcept;
+ bool intersects(const QRect &r) const noexcept;
+
+ Q_DECL_CONSTEXPR inline QRect marginsAdded(const QMargins &margins) const noexcept;
+ Q_DECL_CONSTEXPR inline QRect marginsRemoved(const QMargins &margins) const noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline QRect &operator+=(const QMargins &margins) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline QRect &operator-=(const QMargins &margins) noexcept;
#if QT_DEPRECATED_SINCE(5, 0)
- Q_REQUIRED_RESULT QT_DEPRECATED QRect unite(const QRect &r) const Q_DECL_NOTHROW { return united(r); }
- Q_REQUIRED_RESULT QT_DEPRECATED QRect intersect(const QRect &r) const Q_DECL_NOTHROW { return intersected(r); }
+ Q_REQUIRED_RESULT QT_DEPRECATED QRect unite(const QRect &r) const noexcept { return united(r); }
+ Q_REQUIRED_RESULT QT_DEPRECATED QRect intersect(const QRect &r) const noexcept { return intersected(r); }
#endif
- friend Q_DECL_CONSTEXPR inline bool operator==(const QRect &, const QRect &) Q_DECL_NOTHROW;
- friend Q_DECL_CONSTEXPR inline bool operator!=(const QRect &, const QRect &) Q_DECL_NOTHROW;
+ friend Q_DECL_CONSTEXPR inline bool operator==(const QRect &, const QRect &) noexcept;
+ friend Q_DECL_CONSTEXPR inline bool operator!=(const QRect &, const QRect &) noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT CGRect toCGRect() const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT CGRect toCGRect() const noexcept;
#endif
private:
@@ -165,8 +165,8 @@ private:
};
Q_DECLARE_TYPEINFO(QRect, Q_MOVABLE_TYPE);
-Q_DECL_CONSTEXPR inline bool operator==(const QRect &, const QRect &) Q_DECL_NOTHROW;
-Q_DECL_CONSTEXPR inline bool operator!=(const QRect &, const QRect &) Q_DECL_NOTHROW;
+Q_DECL_CONSTEXPR inline bool operator==(const QRect &, const QRect &) noexcept;
+Q_DECL_CONSTEXPR inline bool operator!=(const QRect &, const QRect &) noexcept;
/*****************************************************************************
@@ -181,97 +181,97 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QRect &);
QRect inline member functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QRect::QRect(int aleft, int atop, int awidth, int aheight) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect::QRect(int aleft, int atop, int awidth, int aheight) noexcept
: x1(aleft), y1(atop), x2(aleft + awidth - 1), y2(atop + aheight - 1) {}
-Q_DECL_CONSTEXPR inline QRect::QRect(const QPoint &atopLeft, const QPoint &abottomRight) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect::QRect(const QPoint &atopLeft, const QPoint &abottomRight) noexcept
: x1(atopLeft.x()), y1(atopLeft.y()), x2(abottomRight.x()), y2(abottomRight.y()) {}
-Q_DECL_CONSTEXPR inline QRect::QRect(const QPoint &atopLeft, const QSize &asize) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect::QRect(const QPoint &atopLeft, const QSize &asize) noexcept
: x1(atopLeft.x()), y1(atopLeft.y()), x2(atopLeft.x()+asize.width() - 1), y2(atopLeft.y()+asize.height() - 1) {}
-Q_DECL_CONSTEXPR inline bool QRect::isNull() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QRect::isNull() const noexcept
{ return x2 == x1 - 1 && y2 == y1 - 1; }
-Q_DECL_CONSTEXPR inline bool QRect::isEmpty() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QRect::isEmpty() const noexcept
{ return x1 > x2 || y1 > y2; }
-Q_DECL_CONSTEXPR inline bool QRect::isValid() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QRect::isValid() const noexcept
{ return x1 <= x2 && y1 <= y2; }
-Q_DECL_CONSTEXPR inline int QRect::left() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QRect::left() const noexcept
{ return x1; }
-Q_DECL_CONSTEXPR inline int QRect::top() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QRect::top() const noexcept
{ return y1; }
-Q_DECL_CONSTEXPR inline int QRect::right() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QRect::right() const noexcept
{ return x2; }
-Q_DECL_CONSTEXPR inline int QRect::bottom() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QRect::bottom() const noexcept
{ return y2; }
-Q_DECL_CONSTEXPR inline int QRect::x() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QRect::x() const noexcept
{ return x1; }
-Q_DECL_CONSTEXPR inline int QRect::y() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QRect::y() const noexcept
{ return y1; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setLeft(int pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setLeft(int pos) noexcept
{ x1 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTop(int pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTop(int pos) noexcept
{ y1 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setRight(int pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setRight(int pos) noexcept
{ x2 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottom(int pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottom(int pos) noexcept
{ y2 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTopLeft(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTopLeft(const QPoint &p) noexcept
{ x1 = p.x(); y1 = p.y(); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottomRight(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottomRight(const QPoint &p) noexcept
{ x2 = p.x(); y2 = p.y(); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTopRight(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setTopRight(const QPoint &p) noexcept
{ x2 = p.x(); y1 = p.y(); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottomLeft(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setBottomLeft(const QPoint &p) noexcept
{ x1 = p.x(); y2 = p.y(); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setX(int ax) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setX(int ax) noexcept
{ x1 = ax; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setY(int ay) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setY(int ay) noexcept
{ y1 = ay; }
-Q_DECL_CONSTEXPR inline QPoint QRect::topLeft() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QPoint QRect::topLeft() const noexcept
{ return QPoint(x1, y1); }
-Q_DECL_CONSTEXPR inline QPoint QRect::bottomRight() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QPoint QRect::bottomRight() const noexcept
{ return QPoint(x2, y2); }
-Q_DECL_CONSTEXPR inline QPoint QRect::topRight() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QPoint QRect::topRight() const noexcept
{ return QPoint(x2, y1); }
-Q_DECL_CONSTEXPR inline QPoint QRect::bottomLeft() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QPoint QRect::bottomLeft() const noexcept
{ return QPoint(x1, y2); }
-Q_DECL_CONSTEXPR inline QPoint QRect::center() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QPoint QRect::center() const noexcept
{ return QPoint(int((qint64(x1)+x2)/2), int((qint64(y1)+y2)/2)); } // cast avoids overflow on addition
-Q_DECL_CONSTEXPR inline int QRect::width() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QRect::width() const noexcept
{ return x2 - x1 + 1; }
-Q_DECL_CONSTEXPR inline int QRect::height() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QRect::height() const noexcept
{ return y2 - y1 + 1; }
-Q_DECL_CONSTEXPR inline QSize QRect::size() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QSize QRect::size() const noexcept
{ return QSize(width(), height()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(int dx, int dy) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(int dx, int dy) noexcept
{
x1 += dx;
y1 += dy;
@@ -279,7 +279,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(int dx, int dy) Q_DECL_NOT
y2 += dy;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(const QPoint &p) noexcept
{
x1 += p.x();
y1 += p.y();
@@ -287,16 +287,16 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::translate(const QPoint &p) Q_DECL_NO
y2 += p.y();
}
-Q_DECL_CONSTEXPR inline QRect QRect::translated(int dx, int dy) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect QRect::translated(int dx, int dy) const noexcept
{ return QRect(QPoint(x1 + dx, y1 + dy), QPoint(x2 + dx, y2 + dy)); }
-Q_DECL_CONSTEXPR inline QRect QRect::translated(const QPoint &p) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect QRect::translated(const QPoint &p) const noexcept
{ return QRect(QPoint(x1 + p.x(), y1 + p.y()), QPoint(x2 + p.x(), y2 + p.y())); }
-Q_DECL_CONSTEXPR inline QRect QRect::transposed() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect QRect::transposed() const noexcept
{ return QRect(topLeft(), size().transposed()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(int ax, int ay) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(int ax, int ay) noexcept
{
x2 += ax - x1;
y2 += ay - y1;
@@ -304,7 +304,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(int ax, int ay) Q_DECL_NOTHRO
y1 = ay;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(const QPoint &p) noexcept
{
x2 += p.x() - x1;
y2 += p.y() - y1;
@@ -312,49 +312,49 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTo(const QPoint &p) Q_DECL_NOTHR
y1 = p.y();
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveLeft(int pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveLeft(int pos) noexcept
{ x2 += (pos - x1); x1 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTop(int pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTop(int pos) noexcept
{ y2 += (pos - y1); y1 = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveRight(int pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveRight(int pos) noexcept
{
x1 += (pos - x2);
x2 = pos;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottom(int pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottom(int pos) noexcept
{
y1 += (pos - y2);
y2 = pos;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTopLeft(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTopLeft(const QPoint &p) noexcept
{
moveLeft(p.x());
moveTop(p.y());
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottomRight(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottomRight(const QPoint &p) noexcept
{
moveRight(p.x());
moveBottom(p.y());
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTopRight(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveTopRight(const QPoint &p) noexcept
{
moveRight(p.x());
moveTop(p.y());
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottomLeft(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveBottomLeft(const QPoint &p) noexcept
{
moveLeft(p.x());
moveBottom(p.y());
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveCenter(const QPoint &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::moveCenter(const QPoint &p) noexcept
{
int w = x2 - x1;
int h = y2 - y1;
@@ -372,7 +372,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::getRect(int *ax, int *ay, int *aw, i
*ah = y2 - y1 + 1;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setRect(int ax, int ay, int aw, int ah) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setRect(int ax, int ay, int aw, int ah) noexcept
{
x1 = ax;
y1 = ay;
@@ -388,7 +388,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::getCoords(int *xp1, int *yp1, int *x
*yp2 = y2;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setCoords(int xp1, int yp1, int xp2, int yp2) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setCoords(int xp1, int yp1, int xp2, int yp2) noexcept
{
x1 = xp1;
y1 = yp1;
@@ -396,10 +396,10 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::setCoords(int xp1, int yp1, int xp2,
y2 = yp2;
}
-Q_DECL_CONSTEXPR inline QRect QRect::adjusted(int xp1, int yp1, int xp2, int yp2) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect QRect::adjusted(int xp1, int yp1, int xp2, int yp2) const noexcept
{ return QRect(QPoint(x1 + xp1, y1 + yp1), QPoint(x2 + xp2, y2 + yp2)); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::adjust(int dx1, int dy1, int dx2, int dy2) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::adjust(int dx1, int dy1, int dx2, int dy2) noexcept
{
x1 += dx1;
y1 += dy1;
@@ -407,97 +407,97 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRect::adjust(int dx1, int dy1, int dx2, in
y2 += dy2;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setWidth(int w) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setWidth(int w) noexcept
{ x2 = (x1 + w - 1); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setHeight(int h) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setHeight(int h) noexcept
{ y2 = (y1 + h - 1); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRect::setSize(const QSize &s) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRect::setSize(const QSize &s) noexcept
{
x2 = (s.width() + x1 - 1);
y2 = (s.height() + y1 - 1);
}
-inline bool QRect::contains(int ax, int ay, bool aproper) const Q_DECL_NOTHROW
+inline bool QRect::contains(int ax, int ay, bool aproper) const noexcept
{
return contains(QPoint(ax, ay), aproper);
}
-inline bool QRect::contains(int ax, int ay) const Q_DECL_NOTHROW
+inline bool QRect::contains(int ax, int ay) const noexcept
{
return contains(QPoint(ax, ay), false);
}
-inline QRect& QRect::operator|=(const QRect &r) Q_DECL_NOTHROW
+inline QRect& QRect::operator|=(const QRect &r) noexcept
{
*this = *this | r;
return *this;
}
-inline QRect& QRect::operator&=(const QRect &r) Q_DECL_NOTHROW
+inline QRect& QRect::operator&=(const QRect &r) noexcept
{
*this = *this & r;
return *this;
}
-inline QRect QRect::intersected(const QRect &other) const Q_DECL_NOTHROW
+inline QRect QRect::intersected(const QRect &other) const noexcept
{
return *this & other;
}
-inline QRect QRect::united(const QRect &r) const Q_DECL_NOTHROW
+inline QRect QRect::united(const QRect &r) const noexcept
{
return *this | r;
}
-Q_DECL_CONSTEXPR inline bool operator==(const QRect &r1, const QRect &r2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator==(const QRect &r1, const QRect &r2) noexcept
{
return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2;
}
-Q_DECL_CONSTEXPR inline bool operator!=(const QRect &r1, const QRect &r2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator!=(const QRect &r1, const QRect &r2) noexcept
{
return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2;
}
-Q_DECL_CONSTEXPR inline QRect operator+(const QRect &rectangle, const QMargins &margins) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect operator+(const QRect &rectangle, const QMargins &margins) noexcept
{
return QRect(QPoint(rectangle.left() - margins.left(), rectangle.top() - margins.top()),
QPoint(rectangle.right() + margins.right(), rectangle.bottom() + margins.bottom()));
}
-Q_DECL_CONSTEXPR inline QRect operator+(const QMargins &margins, const QRect &rectangle) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect operator+(const QMargins &margins, const QRect &rectangle) noexcept
{
return QRect(QPoint(rectangle.left() - margins.left(), rectangle.top() - margins.top()),
QPoint(rectangle.right() + margins.right(), rectangle.bottom() + margins.bottom()));
}
-Q_DECL_CONSTEXPR inline QRect operator-(const QRect &lhs, const QMargins &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect operator-(const QRect &lhs, const QMargins &rhs) noexcept
{
return QRect(QPoint(lhs.left() + rhs.left(), lhs.top() + rhs.top()),
QPoint(lhs.right() - rhs.right(), lhs.bottom() - rhs.bottom()));
}
-Q_DECL_CONSTEXPR inline QRect QRect::marginsAdded(const QMargins &margins) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect QRect::marginsAdded(const QMargins &margins) const noexcept
{
return QRect(QPoint(x1 - margins.left(), y1 - margins.top()),
QPoint(x2 + margins.right(), y2 + margins.bottom()));
}
-Q_DECL_CONSTEXPR inline QRect QRect::marginsRemoved(const QMargins &margins) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect QRect::marginsRemoved(const QMargins &margins) const noexcept
{
return QRect(QPoint(x1 + margins.left(), y1 + margins.top()),
QPoint(x2 - margins.right(), y2 - margins.bottom()));
}
-Q_DECL_RELAXED_CONSTEXPR inline QRect &QRect::operator+=(const QMargins &margins) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QRect &QRect::operator+=(const QMargins &margins) noexcept
{
*this = marginsAdded(margins);
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QRect &QRect::operator-=(const QMargins &margins) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QRect &QRect::operator-=(const QMargins &margins) noexcept
{
*this = marginsRemoved(margins);
return *this;
@@ -511,110 +511,110 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QRect &);
class Q_CORE_EXPORT QRectF
{
public:
- Q_DECL_CONSTEXPR QRectF() Q_DECL_NOTHROW : xp(0.), yp(0.), w(0.), h(0.) {}
- Q_DECL_CONSTEXPR QRectF(const QPointF &topleft, const QSizeF &size) Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QRectF(const QPointF &topleft, const QPointF &bottomRight) Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QRectF(qreal left, qreal top, qreal width, qreal height) Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QRectF(const QRect &rect) Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline bool isNull() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline bool isEmpty() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline bool isValid() const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT QRectF normalized() const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline qreal left() const Q_DECL_NOTHROW { return xp; }
- Q_DECL_CONSTEXPR inline qreal top() const Q_DECL_NOTHROW { return yp; }
- Q_DECL_CONSTEXPR inline qreal right() const Q_DECL_NOTHROW { return xp + w; }
- Q_DECL_CONSTEXPR inline qreal bottom() const Q_DECL_NOTHROW { return yp + h; }
-
- Q_DECL_CONSTEXPR inline qreal x() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline qreal y() const Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setLeft(qreal pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setTop(qreal pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setRight(qreal pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottom(qreal pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setX(qreal pos) Q_DECL_NOTHROW { setLeft(pos); }
- Q_DECL_RELAXED_CONSTEXPR inline void setY(qreal pos) Q_DECL_NOTHROW { setTop(pos); }
-
- Q_DECL_CONSTEXPR inline QPointF topLeft() const Q_DECL_NOTHROW { return QPointF(xp, yp); }
- Q_DECL_CONSTEXPR inline QPointF bottomRight() const Q_DECL_NOTHROW { return QPointF(xp+w, yp+h); }
- Q_DECL_CONSTEXPR inline QPointF topRight() const Q_DECL_NOTHROW { return QPointF(xp+w, yp); }
- Q_DECL_CONSTEXPR inline QPointF bottomLeft() const Q_DECL_NOTHROW { return QPointF(xp, yp+h); }
- Q_DECL_CONSTEXPR inline QPointF center() const Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline void setTopLeft(const QPointF &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottomRight(const QPointF &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setTopRight(const QPointF &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setBottomLeft(const QPointF &p) Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline void moveLeft(qreal pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTop(qreal pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveRight(qreal pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottom(qreal pos) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTopLeft(const QPointF &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottomRight(const QPointF &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTopRight(const QPointF &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveBottomLeft(const QPointF &p) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveCenter(const QPointF &p) Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline void translate(qreal dx, qreal dy) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void translate(const QPointF &p) Q_DECL_NOTHROW;
-
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF translated(qreal dx, qreal dy) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF translated(const QPointF &p) const Q_DECL_NOTHROW;
-
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF transposed() const Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline void moveTo(qreal x, qreal y) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void moveTo(const QPointF &p) Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline void setRect(qreal x, qreal y, qreal w, qreal h) Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR QRectF() noexcept : xp(0.), yp(0.), w(0.), h(0.) {}
+ Q_DECL_CONSTEXPR QRectF(const QPointF &topleft, const QSizeF &size) noexcept;
+ Q_DECL_CONSTEXPR QRectF(const QPointF &topleft, const QPointF &bottomRight) noexcept;
+ Q_DECL_CONSTEXPR QRectF(qreal left, qreal top, qreal width, qreal height) noexcept;
+ Q_DECL_CONSTEXPR QRectF(const QRect &rect) noexcept;
+
+ Q_DECL_CONSTEXPR inline bool isNull() const noexcept;
+ Q_DECL_CONSTEXPR inline bool isEmpty() const noexcept;
+ Q_DECL_CONSTEXPR inline bool isValid() const noexcept;
+ Q_REQUIRED_RESULT QRectF normalized() const noexcept;
+
+ Q_DECL_CONSTEXPR inline qreal left() const noexcept { return xp; }
+ Q_DECL_CONSTEXPR inline qreal top() const noexcept { return yp; }
+ Q_DECL_CONSTEXPR inline qreal right() const noexcept { return xp + w; }
+ Q_DECL_CONSTEXPR inline qreal bottom() const noexcept { return yp + h; }
+
+ Q_DECL_CONSTEXPR inline qreal x() const noexcept;
+ Q_DECL_CONSTEXPR inline qreal y() const noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setLeft(qreal pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setTop(qreal pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setRight(qreal pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setBottom(qreal pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setX(qreal pos) noexcept { setLeft(pos); }
+ Q_DECL_RELAXED_CONSTEXPR inline void setY(qreal pos) noexcept { setTop(pos); }
+
+ Q_DECL_CONSTEXPR inline QPointF topLeft() const noexcept { return QPointF(xp, yp); }
+ Q_DECL_CONSTEXPR inline QPointF bottomRight() const noexcept { return QPointF(xp+w, yp+h); }
+ Q_DECL_CONSTEXPR inline QPointF topRight() const noexcept { return QPointF(xp+w, yp); }
+ Q_DECL_CONSTEXPR inline QPointF bottomLeft() const noexcept { return QPointF(xp, yp+h); }
+ Q_DECL_CONSTEXPR inline QPointF center() const noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline void setTopLeft(const QPointF &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setBottomRight(const QPointF &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setTopRight(const QPointF &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setBottomLeft(const QPointF &p) noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline void moveLeft(qreal pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveTop(qreal pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveRight(qreal pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveBottom(qreal pos) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveTopLeft(const QPointF &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveBottomRight(const QPointF &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveTopRight(const QPointF &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveBottomLeft(const QPointF &p) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveCenter(const QPointF &p) noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline void translate(qreal dx, qreal dy) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void translate(const QPointF &p) noexcept;
+
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF translated(qreal dx, qreal dy) const noexcept;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF translated(const QPointF &p) const noexcept;
+
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF transposed() const noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline void moveTo(qreal x, qreal y) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void moveTo(const QPointF &p) noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline void setRect(qreal x, qreal y, qreal w, qreal h) noexcept;
Q_DECL_RELAXED_CONSTEXPR inline void getRect(qreal *x, qreal *y, qreal *w, qreal *h) const;
- Q_DECL_RELAXED_CONSTEXPR inline void setCoords(qreal x1, qreal y1, qreal x2, qreal y2) Q_DECL_NOTHROW;
+ Q_DECL_RELAXED_CONSTEXPR inline void setCoords(qreal x1, qreal y1, qreal x2, qreal y2) noexcept;
Q_DECL_RELAXED_CONSTEXPR inline void getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const;
- Q_DECL_RELAXED_CONSTEXPR inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2) Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline QSizeF size() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline qreal width() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline qreal height() const Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setWidth(qreal w) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setHeight(qreal h) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setSize(const QSizeF &s) Q_DECL_NOTHROW;
-
- QRectF operator|(const QRectF &r) const Q_DECL_NOTHROW;
- QRectF operator&(const QRectF &r) const Q_DECL_NOTHROW;
- inline QRectF& operator|=(const QRectF &r) Q_DECL_NOTHROW;
- inline QRectF& operator&=(const QRectF &r) Q_DECL_NOTHROW;
-
- bool contains(const QRectF &r) const Q_DECL_NOTHROW;
- bool contains(const QPointF &p) const Q_DECL_NOTHROW;
- inline bool contains(qreal x, qreal y) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT inline QRectF united(const QRectF &other) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT inline QRectF intersected(const QRectF &other) const Q_DECL_NOTHROW;
- bool intersects(const QRectF &r) const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline QRectF marginsAdded(const QMarginsF &margins) const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline QRectF marginsRemoved(const QMarginsF &margins) const Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline QRectF &operator+=(const QMarginsF &margins) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline QRectF &operator-=(const QMarginsF &margins) Q_DECL_NOTHROW;
+ Q_DECL_RELAXED_CONSTEXPR inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2) noexcept;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept;
+
+ Q_DECL_CONSTEXPR inline QSizeF size() const noexcept;
+ Q_DECL_CONSTEXPR inline qreal width() const noexcept;
+ Q_DECL_CONSTEXPR inline qreal height() const noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setWidth(qreal w) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setHeight(qreal h) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setSize(const QSizeF &s) noexcept;
+
+ QRectF operator|(const QRectF &r) const noexcept;
+ QRectF operator&(const QRectF &r) const noexcept;
+ inline QRectF& operator|=(const QRectF &r) noexcept;
+ inline QRectF& operator&=(const QRectF &r) noexcept;
+
+ bool contains(const QRectF &r) const noexcept;
+ bool contains(const QPointF &p) const noexcept;
+ inline bool contains(qreal x, qreal y) const noexcept;
+ Q_REQUIRED_RESULT inline QRectF united(const QRectF &other) const noexcept;
+ Q_REQUIRED_RESULT inline QRectF intersected(const QRectF &other) const noexcept;
+ bool intersects(const QRectF &r) const noexcept;
+
+ Q_DECL_CONSTEXPR inline QRectF marginsAdded(const QMarginsF &margins) const noexcept;
+ Q_DECL_CONSTEXPR inline QRectF marginsRemoved(const QMarginsF &margins) const noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline QRectF &operator+=(const QMarginsF &margins) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline QRectF &operator-=(const QMarginsF &margins) noexcept;
#if QT_DEPRECATED_SINCE(5, 0)
- Q_REQUIRED_RESULT QT_DEPRECATED QRectF unite(const QRectF &r) const Q_DECL_NOTHROW { return united(r); }
- Q_REQUIRED_RESULT QT_DEPRECATED QRectF intersect(const QRectF &r) const Q_DECL_NOTHROW { return intersected(r); }
+ Q_REQUIRED_RESULT QT_DEPRECATED QRectF unite(const QRectF &r) const noexcept { return united(r); }
+ Q_REQUIRED_RESULT QT_DEPRECATED QRectF intersect(const QRectF &r) const noexcept { return intersected(r); }
#endif
- friend Q_DECL_CONSTEXPR inline bool operator==(const QRectF &, const QRectF &) Q_DECL_NOTHROW;
- friend Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &, const QRectF &) Q_DECL_NOTHROW;
+ friend Q_DECL_CONSTEXPR inline bool operator==(const QRectF &, const QRectF &) noexcept;
+ friend Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &, const QRectF &) noexcept;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect toRect() const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT QRect toAlignedRect() const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QRect toRect() const noexcept;
+ Q_REQUIRED_RESULT QRect toAlignedRect() const noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT static QRectF fromCGRect(CGRect rect) Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT CGRect toCGRect() const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT static QRectF fromCGRect(CGRect rect) noexcept;
+ Q_REQUIRED_RESULT CGRect toCGRect() const noexcept;
#endif
private:
@@ -625,8 +625,8 @@ private:
};
Q_DECLARE_TYPEINFO(QRectF, Q_MOVABLE_TYPE);
-Q_DECL_CONSTEXPR inline bool operator==(const QRectF &, const QRectF &) Q_DECL_NOTHROW;
-Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &, const QRectF &) Q_DECL_NOTHROW;
+Q_DECL_CONSTEXPR inline bool operator==(const QRectF &, const QRectF &) noexcept;
+Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &, const QRectF &) noexcept;
/*****************************************************************************
@@ -641,23 +641,23 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QRectF &);
QRectF inline member functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QRectF::QRectF(qreal aleft, qreal atop, qreal awidth, qreal aheight) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF::QRectF(qreal aleft, qreal atop, qreal awidth, qreal aheight) noexcept
: xp(aleft), yp(atop), w(awidth), h(aheight)
{
}
-Q_DECL_CONSTEXPR inline QRectF::QRectF(const QPointF &atopLeft, const QSizeF &asize) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF::QRectF(const QPointF &atopLeft, const QSizeF &asize) noexcept
: xp(atopLeft.x()), yp(atopLeft.y()), w(asize.width()), h(asize.height())
{
}
-Q_DECL_CONSTEXPR inline QRectF::QRectF(const QPointF &atopLeft, const QPointF &abottomRight) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF::QRectF(const QPointF &atopLeft, const QPointF &abottomRight) noexcept
: xp(atopLeft.x()), yp(atopLeft.y()), w(abottomRight.x() - atopLeft.x()), h(abottomRight.y() - atopLeft.y())
{
}
-Q_DECL_CONSTEXPR inline QRectF::QRectF(const QRect &r) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF::QRectF(const QRect &r) noexcept
: xp(r.x()), yp(r.y()), w(r.width()), h(r.height())
{
}
@@ -666,117 +666,117 @@ QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal")
-Q_DECL_CONSTEXPR inline bool QRectF::isNull() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QRectF::isNull() const noexcept
{ return w == 0. && h == 0.; }
-Q_DECL_CONSTEXPR inline bool QRectF::isEmpty() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QRectF::isEmpty() const noexcept
{ return w <= 0. || h <= 0.; }
QT_WARNING_POP
-Q_DECL_CONSTEXPR inline bool QRectF::isValid() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QRectF::isValid() const noexcept
{ return w > 0. && h > 0.; }
-Q_DECL_CONSTEXPR inline qreal QRectF::x() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline qreal QRectF::x() const noexcept
{ return xp; }
-Q_DECL_CONSTEXPR inline qreal QRectF::y() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline qreal QRectF::y() const noexcept
{ return yp; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setLeft(qreal pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setLeft(qreal pos) noexcept
{ qreal diff = pos - xp; xp += diff; w -= diff; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setRight(qreal pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setRight(qreal pos) noexcept
{ w = pos - xp; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTop(qreal pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTop(qreal pos) noexcept
{ qreal diff = pos - yp; yp += diff; h -= diff; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottom(qreal pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottom(qreal pos) noexcept
{ h = pos - yp; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTopLeft(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTopLeft(const QPointF &p) noexcept
{ setLeft(p.x()); setTop(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTopRight(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setTopRight(const QPointF &p) noexcept
{ setRight(p.x()); setTop(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottomLeft(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottomLeft(const QPointF &p) noexcept
{ setLeft(p.x()); setBottom(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottomRight(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setBottomRight(const QPointF &p) noexcept
{ setRight(p.x()); setBottom(p.y()); }
-Q_DECL_CONSTEXPR inline QPointF QRectF::center() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QPointF QRectF::center() const noexcept
{ return QPointF(xp + w/2, yp + h/2); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveLeft(qreal pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveLeft(qreal pos) noexcept
{ xp = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTop(qreal pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTop(qreal pos) noexcept
{ yp = pos; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveRight(qreal pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveRight(qreal pos) noexcept
{ xp = pos - w; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottom(qreal pos) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottom(qreal pos) noexcept
{ yp = pos - h; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTopLeft(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTopLeft(const QPointF &p) noexcept
{ moveLeft(p.x()); moveTop(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTopRight(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTopRight(const QPointF &p) noexcept
{ moveRight(p.x()); moveTop(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottomLeft(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottomLeft(const QPointF &p) noexcept
{ moveLeft(p.x()); moveBottom(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottomRight(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveBottomRight(const QPointF &p) noexcept
{ moveRight(p.x()); moveBottom(p.y()); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveCenter(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveCenter(const QPointF &p) noexcept
{ xp = p.x() - w/2; yp = p.y() - h/2; }
-Q_DECL_CONSTEXPR inline qreal QRectF::width() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline qreal QRectF::width() const noexcept
{ return w; }
-Q_DECL_CONSTEXPR inline qreal QRectF::height() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline qreal QRectF::height() const noexcept
{ return h; }
-Q_DECL_CONSTEXPR inline QSizeF QRectF::size() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QSizeF QRectF::size() const noexcept
{ return QSizeF(w, h); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::translate(qreal dx, qreal dy) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::translate(qreal dx, qreal dy) noexcept
{
xp += dx;
yp += dy;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::translate(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::translate(const QPointF &p) noexcept
{
xp += p.x();
yp += p.y();
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTo(qreal ax, qreal ay) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTo(qreal ax, qreal ay) noexcept
{
xp = ax;
yp = ay;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTo(const QPointF &p) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::moveTo(const QPointF &p) noexcept
{
xp = p.x();
yp = p.y();
}
-Q_DECL_CONSTEXPR inline QRectF QRectF::translated(qreal dx, qreal dy) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF QRectF::translated(qreal dx, qreal dy) const noexcept
{ return QRectF(xp + dx, yp + dy, w, h); }
-Q_DECL_CONSTEXPR inline QRectF QRectF::translated(const QPointF &p) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF QRectF::translated(const QPointF &p) const noexcept
{ return QRectF(xp + p.x(), yp + p.y(), w, h); }
-Q_DECL_CONSTEXPR inline QRectF QRectF::transposed() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF QRectF::transposed() const noexcept
{ return QRectF(topLeft(), size().transposed()); }
Q_DECL_RELAXED_CONSTEXPR inline void QRectF::getRect(qreal *ax, qreal *ay, qreal *aaw, qreal *aah) const
@@ -787,7 +787,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRectF::getRect(qreal *ax, qreal *ay, qreal
*aah = this->h;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setRect(qreal ax, qreal ay, qreal aaw, qreal aah) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setRect(qreal ax, qreal ay, qreal aaw, qreal aah) noexcept
{
this->xp = ax;
this->yp = ay;
@@ -803,7 +803,7 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRectF::getCoords(qreal *xp1, qreal *yp1, q
*yp2 = yp + h;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setCoords(qreal xp1, qreal yp1, qreal xp2, qreal yp2) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setCoords(qreal xp1, qreal yp1, qreal xp2, qreal yp2) noexcept
{
xp = xp1;
yp = yp1;
@@ -811,105 +811,105 @@ Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setCoords(qreal xp1, qreal yp1, qre
h = yp2 - yp1;
}
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::adjust(qreal xp1, qreal yp1, qreal xp2, qreal yp2) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::adjust(qreal xp1, qreal yp1, qreal xp2, qreal yp2) noexcept
{ xp += xp1; yp += yp1; w += xp2 - xp1; h += yp2 - yp1; }
-Q_DECL_CONSTEXPR inline QRectF QRectF::adjusted(qreal xp1, qreal yp1, qreal xp2, qreal yp2) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF QRectF::adjusted(qreal xp1, qreal yp1, qreal xp2, qreal yp2) const noexcept
{ return QRectF(xp + xp1, yp + yp1, w + xp2 - xp1, h + yp2 - yp1); }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setWidth(qreal aw) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setWidth(qreal aw) noexcept
{ this->w = aw; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setHeight(qreal ah) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setHeight(qreal ah) noexcept
{ this->h = ah; }
-Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setSize(const QSizeF &s) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QRectF::setSize(const QSizeF &s) noexcept
{
w = s.width();
h = s.height();
}
-inline bool QRectF::contains(qreal ax, qreal ay) const Q_DECL_NOTHROW
+inline bool QRectF::contains(qreal ax, qreal ay) const noexcept
{
return contains(QPointF(ax, ay));
}
-inline QRectF& QRectF::operator|=(const QRectF &r) Q_DECL_NOTHROW
+inline QRectF& QRectF::operator|=(const QRectF &r) noexcept
{
*this = *this | r;
return *this;
}
-inline QRectF& QRectF::operator&=(const QRectF &r) Q_DECL_NOTHROW
+inline QRectF& QRectF::operator&=(const QRectF &r) noexcept
{
*this = *this & r;
return *this;
}
-inline QRectF QRectF::intersected(const QRectF &r) const Q_DECL_NOTHROW
+inline QRectF QRectF::intersected(const QRectF &r) const noexcept
{
return *this & r;
}
-inline QRectF QRectF::united(const QRectF &r) const Q_DECL_NOTHROW
+inline QRectF QRectF::united(const QRectF &r) const noexcept
{
return *this | r;
}
-Q_DECL_CONSTEXPR inline bool operator==(const QRectF &r1, const QRectF &r2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator==(const QRectF &r1, const QRectF &r2) noexcept
{
return qFuzzyCompare(r1.xp, r2.xp) && qFuzzyCompare(r1.yp, r2.yp)
&& qFuzzyCompare(r1.w, r2.w) && qFuzzyCompare(r1.h, r2.h);
}
-Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &r1, const QRectF &r2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &r1, const QRectF &r2) noexcept
{
return !qFuzzyCompare(r1.xp, r2.xp) || !qFuzzyCompare(r1.yp, r2.yp)
|| !qFuzzyCompare(r1.w, r2.w) || !qFuzzyCompare(r1.h, r2.h);
}
-Q_DECL_CONSTEXPR inline QRect QRectF::toRect() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRect QRectF::toRect() const noexcept
{
return QRect(QPoint(qRound(xp), qRound(yp)), QPoint(qRound(xp + w) - 1, qRound(yp + h) - 1));
}
-Q_DECL_CONSTEXPR inline QRectF operator+(const QRectF &lhs, const QMarginsF &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF operator+(const QRectF &lhs, const QMarginsF &rhs) noexcept
{
return QRectF(QPointF(lhs.left() - rhs.left(), lhs.top() - rhs.top()),
QSizeF(lhs.width() + rhs.left() + rhs.right(), lhs.height() + rhs.top() + rhs.bottom()));
}
-Q_DECL_CONSTEXPR inline QRectF operator+(const QMarginsF &lhs, const QRectF &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF operator+(const QMarginsF &lhs, const QRectF &rhs) noexcept
{
return QRectF(QPointF(rhs.left() - lhs.left(), rhs.top() - lhs.top()),
QSizeF(rhs.width() + lhs.left() + lhs.right(), rhs.height() + lhs.top() + lhs.bottom()));
}
-Q_DECL_CONSTEXPR inline QRectF operator-(const QRectF &lhs, const QMarginsF &rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF operator-(const QRectF &lhs, const QMarginsF &rhs) noexcept
{
return QRectF(QPointF(lhs.left() + rhs.left(), lhs.top() + rhs.top()),
QSizeF(lhs.width() - rhs.left() - rhs.right(), lhs.height() - rhs.top() - rhs.bottom()));
}
-Q_DECL_CONSTEXPR inline QRectF QRectF::marginsAdded(const QMarginsF &margins) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF QRectF::marginsAdded(const QMarginsF &margins) const noexcept
{
return QRectF(QPointF(xp - margins.left(), yp - margins.top()),
QSizeF(w + margins.left() + margins.right(), h + margins.top() + margins.bottom()));
}
-Q_DECL_CONSTEXPR inline QRectF QRectF::marginsRemoved(const QMarginsF &margins) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QRectF QRectF::marginsRemoved(const QMarginsF &margins) const noexcept
{
return QRectF(QPointF(xp + margins.left(), yp + margins.top()),
QSizeF(w - margins.left() - margins.right(), h - margins.top() - margins.bottom()));
}
-Q_DECL_RELAXED_CONSTEXPR inline QRectF &QRectF::operator+=(const QMarginsF &margins) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QRectF &QRectF::operator+=(const QMarginsF &margins) noexcept
{
*this = marginsAdded(margins);
return *this;
}
-Q_DECL_RELAXED_CONSTEXPR inline QRectF &QRectF::operator-=(const QMarginsF &margins) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QRectF &QRectF::operator-=(const QMarginsF &margins) noexcept
{
*this = marginsRemoved(margins);
return *this;
diff --git a/src/corelib/tools/qrefcount.h b/src/corelib/tools/qrefcount.h
index 9586c3a79a..2e5388ad9a 100644
--- a/src/corelib/tools/qrefcount.h
+++ b/src/corelib/tools/qrefcount.h
@@ -51,8 +51,8 @@ namespace QtPrivate
class RefCount
{
public:
- inline bool ref() Q_DECL_NOTHROW {
- int count = atomic.load();
+ inline bool ref() noexcept {
+ int count = atomic.loadRelaxed();
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
if (count == 0) // !isSharable
return false;
@@ -62,8 +62,8 @@ public:
return true;
}
- inline bool deref() Q_DECL_NOTHROW {
- int count = atomic.load();
+ inline bool deref() noexcept {
+ int count = atomic.loadRelaxed();
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
if (count == 0) // !isSharable
return false;
@@ -74,7 +74,7 @@ public:
}
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
- bool setSharable(bool sharable) Q_DECL_NOTHROW
+ bool setSharable(bool sharable) noexcept
{
Q_ASSERT(!isShared());
if (sharable)
@@ -83,27 +83,27 @@ public:
return atomic.testAndSetRelaxed(1, 0);
}
- bool isSharable() const Q_DECL_NOTHROW
+ bool isSharable() const noexcept
{
// Sharable === Shared ownership.
- return atomic.load() != 0;
+ return atomic.loadRelaxed() != 0;
}
#endif
- bool isStatic() const Q_DECL_NOTHROW
+ bool isStatic() const noexcept
{
// Persistent object, never deleted
- return atomic.load() == -1;
+ return atomic.loadRelaxed() == -1;
}
- bool isShared() const Q_DECL_NOTHROW
+ bool isShared() const noexcept
{
- int count = atomic.load();
+ int count = atomic.loadRelaxed();
return (count != 1) && (count != 0);
}
- void initializeOwned() Q_DECL_NOTHROW { atomic.store(1); }
- void initializeUnsharable() Q_DECL_NOTHROW { atomic.store(0); }
+ void initializeOwned() noexcept { atomic.storeRelaxed(1); }
+ void initializeUnsharable() noexcept { atomic.storeRelaxed(0); }
QBasicAtomicInt atomic;
};
diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp
index ef24c952eb..128df84053 100644
--- a/src/corelib/tools/qregexp.cpp
+++ b/src/corelib/tools/qregexp.cpp
@@ -58,9 +58,6 @@
QT_BEGIN_NAMESPACE
-int qFindString(const QChar *haystack, int haystackLen, int from,
- const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
-
// error strings for the regexp parser
#define RXERR_OK QT_TRANSLATE_NOOP("QRegExp", "no error occurred")
#define RXERR_DISABLED QT_TRANSLATE_NOOP("QRegExp", "disabled feature used")
@@ -893,7 +890,7 @@ static bool operator==(const QRegExpEngineKey &key1, const QRegExpEngineKey &key
&& key1.cs == key2.cs;
}
-static uint qHash(const QRegExpEngineKey &key, uint seed = 0) Q_DECL_NOTHROW
+static uint qHash(const QRegExpEngineKey &key, uint seed = 0) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.pattern);
@@ -940,10 +937,10 @@ struct QRegExpMatchState
const QRegExpEngine *eng;
- inline QRegExpMatchState() : bigArray(0), captured(0) {}
+ inline QRegExpMatchState() : bigArray(nullptr), captured(nullptr) {}
inline ~QRegExpMatchState() { free(bigArray); }
- void drain() { free(bigArray); bigArray = 0; captured = 0; } // to save memory
+ void drain() { free(bigArray); bigArray = nullptr; captured = nullptr; } // to save memory
void prepareForMatch(QRegExpEngine *eng);
void match(const QChar *str, int len, int pos, bool minimal,
bool oneTest, int caretIndex);
@@ -1423,14 +1420,15 @@ void QRegExpMatchState::match(const QChar *str0, int len0, int pos0,
#ifndef QT_NO_REGEXP_OPTIM
if (eng->trivial && !oneTest) {
- pos = qFindString(str0, len0, pos0, eng->goodStr.unicode(), eng->goodStr.length(), eng->cs);
+ // ### Qt6: qsize
+ pos = int(QtPrivate::findString(QStringView(str0, len0), pos0, QStringView(eng->goodStr.unicode(), eng->goodStr.length()), eng->cs));
matchLen = eng->goodStr.length();
matched = (pos != -1);
} else
#endif
{
in = str0;
- if (in == 0)
+ if (in == nullptr)
in = &char_null;
pos = pos0;
caretPos = caretIndex;
@@ -1709,7 +1707,7 @@ void QRegExpEngine::dump() const
void QRegExpEngine::setup()
{
- ref.store(1);
+ ref.storeRelaxed(1);
#ifndef QT_NO_REGEXP_CAPTURE
f.resize(32);
nf = 0;
@@ -2912,7 +2910,7 @@ int QRegExpEngine::getEscape()
#ifndef QT_NO_REGEXP_ESCAPE
if ((prevCh & ~0xff) == 0) {
const char *p = strchr(tab, prevCh);
- if (p != 0)
+ if (p != nullptr)
return Tok_Char | backTab[p - tab];
}
#endif
@@ -3532,7 +3530,7 @@ int QRegExpEngine::parse(const QChar *pattern, int len)
#endif
box.cat(middleBox);
box.cat(rightBox);
- yyCharClass.reset(0);
+ yyCharClass.reset();
#ifndef QT_NO_REGEXP_CAPTURE
for (int i = 0; i < nf; ++i) {
@@ -3610,7 +3608,7 @@ int QRegExpEngine::parse(const QChar *pattern, int len)
void QRegExpEngine::parseAtom(Box *box)
{
#ifndef QT_NO_REGEXP_LOOKAHEAD
- QRegExpEngine *eng = 0;
+ QRegExpEngine *eng = nullptr;
bool neg;
int len;
#endif
@@ -3807,9 +3805,9 @@ struct QRegExpPrivate
QRegExpMatchState matchState;
inline QRegExpPrivate()
- : eng(0), engineKey(QString(), QRegExp::RegExp, Qt::CaseSensitive), minimal(false) { }
+ : eng(nullptr), engineKey(QString(), QRegExp::RegExp, Qt::CaseSensitive), minimal(false) { }
inline QRegExpPrivate(const QRegExpEngineKey &key)
- : eng(0), engineKey(key), minimal(false) {}
+ : eng(nullptr), engineKey(key), minimal(false) {}
};
#if !defined(QT_NO_REGEXP_OPTIM)
@@ -3888,9 +3886,9 @@ static void prepareEngineForMatch(QRegExpPrivate *priv, const QString &str)
static void invalidateEngine(QRegExpPrivate *priv)
{
- if (priv->eng != 0) {
+ if (priv->eng) {
derefEngine(priv->eng, priv->engineKey);
- priv->eng = 0;
+ priv->eng = nullptr;
priv->matchState.drain();
}
}
@@ -4048,7 +4046,7 @@ bool QRegExp::operator==(const QRegExp &rx) const
Returns the hash value for \a key, using
\a seed to seed the calculation.
*/
-uint qHash(const QRegExp &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QRegExp &key, uint seed) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.priv->engineKey);
diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h
index b3fa242168..8f6de24c74 100644
--- a/src/corelib/tools/qregexp.h
+++ b/src/corelib/tools/qregexp.h
@@ -53,7 +53,7 @@ struct QRegExpPrivate;
class QStringList;
class QRegExp;
-Q_CORE_EXPORT uint qHash(const QRegExp &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT uint qHash(const QRegExp &key, uint seed = 0) noexcept;
class Q_CORE_EXPORT QRegExp
{
@@ -73,10 +73,8 @@ public:
QRegExp(const QRegExp &rx);
~QRegExp();
QRegExp &operator=(const QRegExp &rx);
-#ifdef Q_COMPILER_RVALUE_REFS
- QRegExp &operator=(QRegExp &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
- void swap(QRegExp &other) Q_DECL_NOTHROW { qSwap(priv, other.priv); }
+ QRegExp &operator=(QRegExp &&other) noexcept { swap(other); return *this; }
+ void swap(QRegExp &other) noexcept { qSwap(priv, other.priv); }
bool operator==(const QRegExp &rx) const;
inline bool operator!=(const QRegExp &rx) const { return !operator==(rx); }
@@ -112,7 +110,7 @@ public:
static QString escape(const QString &str);
- friend Q_CORE_EXPORT uint qHash(const QRegExp &key, uint seed) Q_DECL_NOTHROW;
+ friend Q_CORE_EXPORT uint qHash(const QRegExp &key, uint seed) noexcept;
private:
QRegExpPrivate *priv;
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
index bdaa2d3243..17acd476b2 100644
--- a/src/corelib/tools/qregularexpression.cpp
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -460,34 +460,13 @@ QT_BEGIN_NAMESPACE
\row \li \c{"[a-z]+\\d+"} \li \b true \li \b true
\endtable
- Exact matching is not reflected in QRegularExpression. If you want to be
- sure that the subject string matches the regular expression exactly, you can wrap the
- pattern between a couple of anchoring expressions. Simply
- putting the pattern between the \c{^} and the \c{$} anchors is enough
- in most cases:
+ Exact matching is not reflected in QRegularExpression. If you want
+ to be sure that the subject string matches the regular expression
+ exactly, you can wrap the pattern using the anchoredPattern()
+ function:
\snippet code/src_corelib_tools_qregularexpression.cpp 24
- However, remember that the \c{$} anchor not only matches at the end of the
- string, but also at a newline character right before the end of the string;
- that is, the previous pattern matches against the string "this pattern must
- match exactly\\n". Also, the behaviour of both the \c{^} and the \c{$}
- anchors changes if the MultiLineOption is set either explicitly (as a
- pattern option) or implicitly (as a directive inside the pattern string).
-
- Therefore, in the most general case, you should wrap the pattern between
- the \c{\A} and the \c{\z} anchors:
-
- \snippet code/src_corelib_tools_qregularexpression.cpp 25
-
- Note the usage of the non-capturing group in order to preserve the meaning
- of the branch operator inside the pattern.
-
- The QRegularExpression::anchoredPattern() helper method does exactly that for
- you.
-
- \sa anchoredPattern
-
\section3 Porting from QRegExp's Partial Matching
When using QRegExp::exactMatch(), if an exact match was not found, one
@@ -1048,8 +1027,8 @@ void QRegularExpressionPrivate::getPatternInfo()
unsigned int hasJOptionChanged;
pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_JCHANGED, &hasJOptionChanged);
if (Q_UNLIKELY(hasJOptionChanged)) {
- qWarning("QRegularExpressionPrivate::getPatternInfo(): the pattern '%s'\n is using the (?J) option; duplicate capturing group names are not supported by Qt",
- qPrintable(pattern));
+ qWarning("QRegularExpressionPrivate::getPatternInfo(): the pattern '%ls'\n is using the (?J) option; duplicate capturing group names are not supported by Qt",
+ qUtf16Printable(pattern));
}
}
@@ -1810,7 +1789,7 @@ bool QRegularExpression::operator==(const QRegularExpression &re) const
Returns the hash value for \a key, using
\a seed to seed the calculation.
*/
-uint qHash(const QRegularExpression &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QRegularExpression &key, uint seed) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.d->pattern);
diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h
index f9e7029550..f799a38ae4 100644
--- a/src/corelib/tools/qregularexpression.h
+++ b/src/corelib/tools/qregularexpression.h
@@ -59,7 +59,7 @@ class QRegularExpressionMatchIterator;
struct QRegularExpressionPrivate;
class QRegularExpression;
-Q_CORE_EXPORT uint qHash(const QRegularExpression &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_CORE_EXPORT uint qHash(const QRegularExpression &key, uint seed = 0) noexcept;
class Q_CORE_EXPORT QRegularExpression
{
@@ -86,13 +86,10 @@ public:
QRegularExpression(const QRegularExpression &re);
~QRegularExpression();
QRegularExpression &operator=(const QRegularExpression &re);
-
-#ifdef Q_COMPILER_RVALUE_REFS
- QRegularExpression &operator=(QRegularExpression &&re) Q_DECL_NOTHROW
+ QRegularExpression &operator=(QRegularExpression &&re) noexcept
{ d.swap(re.d); return *this; }
-#endif
- void swap(QRegularExpression &other) Q_DECL_NOTHROW { d.swap(other.d); }
+ void swap(QRegularExpression &other) noexcept { d.swap(other.d); }
QString pattern() const;
void setPattern(const QString &pattern);
@@ -157,7 +154,7 @@ private:
friend class QRegularExpressionMatch;
friend struct QRegularExpressionMatchPrivate;
friend class QRegularExpressionMatchIterator;
- friend Q_CORE_EXPORT uint qHash(const QRegularExpression &key, uint seed) Q_DECL_NOTHROW;
+ friend Q_CORE_EXPORT uint qHash(const QRegularExpression &key, uint seed) noexcept;
QRegularExpression(QRegularExpressionPrivate &dd);
QExplicitlySharedDataPointer<QRegularExpressionPrivate> d;
@@ -186,12 +183,9 @@ public:
~QRegularExpressionMatch();
QRegularExpressionMatch(const QRegularExpressionMatch &match);
QRegularExpressionMatch &operator=(const QRegularExpressionMatch &match);
-
-#ifdef Q_COMPILER_RVALUE_REFS
- QRegularExpressionMatch &operator=(QRegularExpressionMatch &&match) Q_DECL_NOTHROW
+ QRegularExpressionMatch &operator=(QRegularExpressionMatch &&match) noexcept
{ d.swap(match.d); return *this; }
-#endif
- void swap(QRegularExpressionMatch &other) Q_DECL_NOTHROW { d.swap(other.d); }
+ void swap(QRegularExpressionMatch &other) noexcept { d.swap(other.d); }
QRegularExpression regularExpression() const;
QRegularExpression::MatchType matchType() const;
@@ -257,11 +251,9 @@ public:
~QRegularExpressionMatchIterator();
QRegularExpressionMatchIterator(const QRegularExpressionMatchIterator &iterator);
QRegularExpressionMatchIterator &operator=(const QRegularExpressionMatchIterator &iterator);
-#ifdef Q_COMPILER_RVALUE_REFS
- QRegularExpressionMatchIterator &operator=(QRegularExpressionMatchIterator &&iterator) Q_DECL_NOTHROW
+ QRegularExpressionMatchIterator &operator=(QRegularExpressionMatchIterator &&iterator) noexcept
{ d.swap(iterator.d); return *this; }
-#endif
- void swap(QRegularExpressionMatchIterator &other) Q_DECL_NOTHROW { d.swap(other.d); }
+ void swap(QRegularExpressionMatchIterator &other) noexcept { d.swap(other.d); }
bool isValid() const;
diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp
index 59650ed2f7..311058a776 100644
--- a/src/corelib/tools/qringbuffer.cpp
+++ b/src/corelib/tools/qringbuffer.cpp
@@ -59,7 +59,7 @@ void QRingChunk::detach()
const int chunkSize = size();
QByteArray x(chunkSize, Qt::Uninitialized);
::memcpy(x.data(), chunk.constData() + headOffset, chunkSize);
- chunk = qMove(x);
+ chunk = std::move(x);
headOffset = 0;
tailOffset = chunkSize;
}
@@ -105,7 +105,7 @@ const char *QRingBuffer::readPointerAtPosition(qint64 pos, qint64 &length) const
}
length = 0;
- return 0;
+ return nullptr;
}
void QRingBuffer::free(qint64 bytes)
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 76ab4a5b62..838cb31697 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -65,11 +65,11 @@ class QRingChunk
{
public:
// initialization and cleanup
- inline QRingChunk() Q_DECL_NOTHROW :
+ inline QRingChunk() noexcept :
headOffset(0), tailOffset(0)
{
}
- inline QRingChunk(const QRingChunk &other) Q_DECL_NOTHROW :
+ inline QRingChunk(const QRingChunk &other) noexcept :
chunk(other.chunk), headOffset(other.headOffset), tailOffset(other.tailOffset)
{
}
@@ -77,30 +77,30 @@ public:
chunk(alloc, Qt::Uninitialized), headOffset(0), tailOffset(0)
{
}
- explicit inline QRingChunk(const QByteArray &qba) Q_DECL_NOTHROW :
+ explicit inline QRingChunk(const QByteArray &qba) noexcept :
chunk(qba), headOffset(0), tailOffset(qba.size())
{
}
- inline QRingChunk &operator=(const QRingChunk &other) Q_DECL_NOTHROW
+ inline QRingChunk &operator=(const QRingChunk &other) noexcept
{
chunk = other.chunk;
headOffset = other.headOffset;
tailOffset = other.tailOffset;
return *this;
}
- inline QRingChunk(QRingChunk &&other) Q_DECL_NOTHROW :
+ inline QRingChunk(QRingChunk &&other) noexcept :
chunk(other.chunk), headOffset(other.headOffset), tailOffset(other.tailOffset)
{
other.headOffset = other.tailOffset = 0;
}
- inline QRingChunk &operator=(QRingChunk &&other) Q_DECL_NOTHROW
+ inline QRingChunk &operator=(QRingChunk &&other) noexcept
{
swap(other);
return *this;
}
- inline void swap(QRingChunk &other) Q_DECL_NOTHROW
+ inline void swap(QRingChunk &other) noexcept
{
chunk.swap(other.chunk);
qSwap(headOffset, other.headOffset);
diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp
index 769a18f9e0..eb08bdba62 100644
--- a/src/corelib/tools/qscopedpointer.cpp
+++ b/src/corelib/tools/qscopedpointer.cpp
@@ -157,7 +157,7 @@ QT_BEGIN_NAMESPACE
Provides access to the scoped pointer's object.
- If the contained pointer is \c null, behavior is undefined.
+ If the contained pointer is \nullptr, behavior is undefined.
\sa isNull()
*/
@@ -166,7 +166,7 @@ QT_BEGIN_NAMESPACE
Provides access to the scoped pointer's object.
- If the contained pointer is \c null, behavior is undefined.
+ If the contained pointer is \nullptr, behavior is undefined.
\sa isNull()
*/
@@ -174,8 +174,8 @@ QT_BEGIN_NAMESPACE
/*!
\fn template <typename T, typename Cleanup> QScopedPointer<T, Cleanup>::operator bool() const
- Returns \c true if this object is not \c null. This function is suitable
- for use in \tt if-constructs, like:
+ Returns \c true if the contained pointer is not \nullptr.
+ This function is suitable for use in \tt if-constructs, like:
\snippet code/src_corelib_tools_qscopedpointer.cpp 3
@@ -185,18 +185,14 @@ QT_BEGIN_NAMESPACE
/*!
\fn template <typename T, typename Cleanup> bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
- Equality operator. Returns \c true if the scoped pointers
- \a lhs and \a rhs are pointing to the same object.
- Otherwise returns \c false.
+ Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
*/
/*!
\fn template <typename T, typename Cleanup> bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
- Inequality operator. Returns \c true if the scoped pointers
- \a lhs and \a rhs are \e not pointing to the same object.
- Otherwise returns \c false.
+ Returns \c true if \a lhs and \a rhs refer to distinct pointers.
*/
/*!
@@ -204,7 +200,7 @@ QT_BEGIN_NAMESPACE
\relates QScopedPointer
\since 5.8
- Returns \c true if the scoped pointer \a lhs is a null pointer.
+ Returns \c true if \a lhs refers to \nullptr.
\sa QScopedPointer::isNull()
*/
@@ -214,7 +210,7 @@ QT_BEGIN_NAMESPACE
\relates QScopedPointer
\since 5.8
- Returns \c true if the scoped pointer \a rhs is a null pointer.
+ Returns \c true if \a rhs refers to \nullptr.
\sa QScopedPointer::isNull()
*/
@@ -224,8 +220,7 @@ QT_BEGIN_NAMESPACE
\relates QScopedPointer
\since 5.8
- Returns \c true if the scoped pointer \a lhs is a valid (i.e. a non-null)
- pointer.
+ Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer.
\sa QScopedPointer::isNull()
*/
@@ -235,8 +230,7 @@ QT_BEGIN_NAMESPACE
\relates QScopedPointer
\since 5.8
- Returns \c true if the scoped pointer \a rhs is a valid (i.e. a non-null)
- pointer.
+ Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer.
\sa QScopedPointer::isNull()
*/
@@ -244,7 +238,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::isNull() const
- Returns \c true if this object is holding a pointer that is \c null.
+ Returns \c true if this object refers to \nullptr.
*/
/*!
@@ -262,15 +256,14 @@ QT_BEGIN_NAMESPACE
\fn template <typename T, typename Cleanup> T *QScopedPointer<T, Cleanup>::take()
Returns the value of the pointer referenced by this object. The pointer of this
- QScopedPointer object will be reset to \c null.
+ QScopedPointer object will be reset to \nullptr.
Callers of this function take ownership of the pointer.
*/
/*! \fn template <typename T, typename Cleanup> bool QScopedPointer<T, Cleanup>::operator!() const
- Returns \c true if the pointer referenced by this object is \c null, otherwise
- returns \c false.
+ Returns \c true if this object refers to \nullptr.
\sa isNull()
*/
@@ -325,7 +318,7 @@ QT_BEGIN_NAMESPACE
Provides access to entry \a i of the scoped pointer's array of
objects.
- If the contained pointer is \c null, behavior is undefined.
+ If the contained pointer is \nullptr, behavior is undefined.
\sa isNull()
*/
@@ -336,7 +329,7 @@ QT_BEGIN_NAMESPACE
Provides access to entry \a i of the scoped pointer's array of
objects.
- If the contained pointer is \c null, behavior is undefined.
+ If the contained pointer is \nullptr behavior is undefined.
\sa isNull()
*/
diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h
index 2a4083466b..af0c0ed336 100644
--- a/src/corelib/tools/qscopedpointer.h
+++ b/src/corelib/tools/qscopedpointer.h
@@ -97,7 +97,7 @@ class QScopedPointer
{
typedef T *QScopedPointer:: *RestrictedBool;
public:
- explicit QScopedPointer(T *p = nullptr) Q_DECL_NOTHROW : d(p)
+ explicit QScopedPointer(T *p = nullptr) noexcept : d(p)
{
}
@@ -113,12 +113,12 @@ public:
return *d;
}
- T *operator->() const Q_DECL_NOTHROW
+ T *operator->() const noexcept
{
return d;
}
- bool operator!() const Q_DECL_NOTHROW
+ bool operator!() const noexcept
{
return !d;
}
@@ -129,28 +129,28 @@ public:
return isNull() ? nullptr : &QScopedPointer::d;
}
#else
- operator RestrictedBool() const Q_DECL_NOTHROW
+ operator RestrictedBool() const noexcept
{
return isNull() ? nullptr : &QScopedPointer::d;
}
#endif
- T *data() const Q_DECL_NOTHROW
+ T *data() const noexcept
{
return d;
}
- T *get() const Q_DECL_NOTHROW
+ T *get() const noexcept
{
return d;
}
- bool isNull() const Q_DECL_NOTHROW
+ bool isNull() const noexcept
{
return !d;
}
- void reset(T *other = nullptr) Q_DECL_NOEXCEPT_EXPR(noexcept(Cleanup::cleanup(std::declval<T *>())))
+ void reset(T *other = nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval<T *>())))
{
if (d == other)
return;
@@ -159,14 +159,14 @@ public:
Cleanup::cleanup(oldD);
}
- T *take() Q_DECL_NOTHROW
+ T *take() noexcept
{
T *oldD = d;
d = nullptr;
return oldD;
}
- void swap(QScopedPointer<T, Cleanup> &other) Q_DECL_NOTHROW
+ void swap(QScopedPointer<T, Cleanup> &other) noexcept
{
qSwap(d, other.d);
}
@@ -181,43 +181,43 @@ private:
};
template <class T, class Cleanup>
-inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) Q_DECL_NOTHROW
+inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
{
return lhs.data() == rhs.data();
}
template <class T, class Cleanup>
-inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) Q_DECL_NOTHROW
+inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
{
return lhs.data() != rhs.data();
}
template <class T, class Cleanup>
-inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) Q_DECL_NOTHROW
+inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
{
return lhs.isNull();
}
template <class T, class Cleanup>
-inline bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) Q_DECL_NOTHROW
+inline bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
{
return rhs.isNull();
}
template <class T, class Cleanup>
-inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) Q_DECL_NOTHROW
+inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
{
return !lhs.isNull();
}
template <class T, class Cleanup>
-inline bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) Q_DECL_NOTHROW
+inline bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
{
return !rhs.isNull();
}
template <class T, class Cleanup>
-inline void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) Q_DECL_NOTHROW
+inline void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept
{ p1.swap(p2); }
template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> >
@@ -244,7 +244,7 @@ public:
return this->d[i];
}
- void swap(QScopedArrayPointer &other) Q_DECL_NOTHROW // prevent QScopedPointer <->QScopedArrayPointer swaps
+ void swap(QScopedArrayPointer &other) noexcept // prevent QScopedPointer <->QScopedArrayPointer swaps
{ QScopedPointer<T, Cleanup>::swap(other); }
private:
@@ -263,7 +263,7 @@ private:
};
template <typename T, typename Cleanup>
-inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) Q_DECL_NOTHROW
+inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) noexcept
{ lhs.swap(rhs); }
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h
index 5f76269388..f904b8dfcb 100644
--- a/src/corelib/tools/qscopedvaluerollback.h
+++ b/src/corelib/tools/qscopedvaluerollback.h
@@ -48,20 +48,20 @@ template <typename T>
class QScopedValueRollback
{
public:
- explicit QScopedValueRollback(T &var) :
- varRef(var), oldValue(var)
+ explicit QScopedValueRollback(T &var)
+ : varRef(var), oldValue(var)
{
}
- explicit QScopedValueRollback(T &var, T value) :
- varRef(var), oldValue(var)
+ explicit QScopedValueRollback(T &var, T value)
+ : varRef(var), oldValue(std::move(var))
{
- varRef = qMove(value);
+ varRef = std::move(value);
}
~QScopedValueRollback()
{
- varRef = qMove(oldValue);
+ varRef = std::move(oldValue);
}
void commit()
@@ -70,7 +70,7 @@ public:
}
private:
- T& varRef;
+ T &varRef;
T oldValue;
Q_DISABLE_COPY(QScopedValueRollback)
diff --git a/src/corelib/tools/qscopeguard.h b/src/corelib/tools/qscopeguard.h
index 31100fcabb..45c3f93da4 100644
--- a/src/corelib/tools/qscopeguard.h
+++ b/src/corelib/tools/qscopeguard.h
@@ -50,14 +50,19 @@ template <typename F> class QScopeGuard;
template <typename F> QScopeGuard<F> qScopeGuard(F f);
template <typename F>
-class QScopeGuard
+class
+#if QT_HAS_CPP_ATTRIBUTE(nodiscard)
+// Q_REQUIRED_RESULT can be defined as __warn_unused_result__ or as [[nodiscard]]
+// but the 1st one has some limitations for example can be placed only on functions.
+Q_REQUIRED_RESULT
+#endif
+QScopeGuard
{
public:
- QScopeGuard(QScopeGuard &&other) Q_DECL_NOEXCEPT
+ QScopeGuard(QScopeGuard &&other) noexcept
: m_func(std::move(other.m_func))
- , m_invoke(other.m_invoke)
+ , m_invoke(qExchange(other.m_invoke, false))
{
- other.dismiss();
}
~QScopeGuard()
@@ -66,13 +71,13 @@ public:
m_func();
}
- void dismiss() Q_DECL_NOEXCEPT
+ void dismiss() noexcept
{
m_invoke = false;
}
private:
- explicit QScopeGuard(F f) Q_DECL_NOEXCEPT
+ explicit QScopeGuard(F &&f) noexcept
: m_func(std::move(f))
{
}
@@ -86,6 +91,9 @@ private:
template <typename F>
+#if QT_HAS_CPP_ATTRIBUTE(nodiscard)
+Q_REQUIRED_RESULT
+#endif
QScopeGuard<F> qScopeGuard(F f)
{
return QScopeGuard<F>(std::move(f));
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index 6640c8486d..83e574bf1c 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -41,10 +41,9 @@
#define QSET_H
#include <QtCore/qhash.h>
-#ifdef Q_COMPILER_INITIALIZER_LISTS
-#include <initializer_list>
-#endif
+#include <QtCore/qcontainertools_impl.h>
+#include <initializer_list>
#include <iterator>
QT_BEGIN_NAMESPACE
@@ -56,19 +55,21 @@ class QSet
typedef QHash<T, QHashDummyValue> Hash;
public:
- inline QSet() Q_DECL_NOTHROW {}
-#ifdef Q_COMPILER_INITIALIZER_LISTS
+ inline QSet() noexcept {}
inline QSet(std::initializer_list<T> list)
+ : QSet(list.begin(), list.end()) {}
+ template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
+ inline QSet(InputIterator first, InputIterator last)
{
- reserve(int(list.size()));
- for (typename std::initializer_list<T>::const_iterator it = list.begin(); it != list.end(); ++it)
- insert(*it);
+ QtPrivate::reserveIfForwardIterator(this, first, last);
+ for (; first != last; ++first)
+ insert(*first);
}
-#endif
+
// compiler-generated copy/move ctor/assignment operators are fine!
// compiler-generated destructor is fine!
- inline void swap(QSet<T> &other) Q_DECL_NOTHROW { q_hash.swap(other.q_hash); }
+ inline void swap(QSet<T> &other) noexcept { q_hash.swap(other.q_hash); }
inline bool operator==(const QSet<T> &other) const
{ return q_hash == other.q_hash; }
@@ -176,20 +177,20 @@ public:
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
inline iterator begin() { return q_hash.begin(); }
- inline const_iterator begin() const Q_DECL_NOTHROW { return q_hash.begin(); }
- inline const_iterator cbegin() const Q_DECL_NOTHROW { return q_hash.begin(); }
- inline const_iterator constBegin() const Q_DECL_NOTHROW { return q_hash.constBegin(); }
+ inline const_iterator begin() const noexcept { return q_hash.begin(); }
+ inline const_iterator cbegin() const noexcept { return q_hash.begin(); }
+ inline const_iterator constBegin() const noexcept { return q_hash.constBegin(); }
inline iterator end() { return q_hash.end(); }
- inline const_iterator end() const Q_DECL_NOTHROW { return q_hash.end(); }
- inline const_iterator cend() const Q_DECL_NOTHROW { return q_hash.end(); }
- inline const_iterator constEnd() const Q_DECL_NOTHROW { return q_hash.constEnd(); }
+ inline const_iterator end() const noexcept { return q_hash.end(); }
+ inline const_iterator cend() const noexcept { return q_hash.end(); }
+ inline const_iterator constEnd() const noexcept { return q_hash.constEnd(); }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
- const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
iterator erase(iterator i)
{ return erase(m2c(i)); }
@@ -244,22 +245,25 @@ public:
inline QSet<T> operator-(const QSet<T> &other) const
{ QSet<T> result = *this; result -= other; return result; }
- QList<T> toList() const;
- inline QList<T> values() const { return toList(); }
-
+ QList<T> values() const;
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ Q_DECL_DEPRECATED_X("Use values() instead.")
+ QList<T> toList() const { return values(); }
+ Q_DECL_DEPRECATED_X("Use QSet<T>(list.begin(), list.end()) instead.")
static QSet<T> fromList(const QList<T> &list);
+#endif
private:
Hash q_hash;
- static const_iterator m2c(iterator it) Q_DECL_NOTHROW
+ static const_iterator m2c(iterator it) noexcept
{ return const_iterator(typename Hash::const_iterator(it.i.i)); }
bool isValidIterator(const iterator &i) const
{
return q_hash.isValidIterator(reinterpret_cast<const typename Hash::iterator&>(i));
}
- bool isValidIterator(const const_iterator &i) const Q_DECL_NOTHROW
+ bool isValidIterator(const const_iterator &i) const noexcept
{
return q_hash.isValidIterator(reinterpret_cast<const typename Hash::const_iterator&>(i));
}
@@ -267,7 +271,7 @@ private:
template <typename T>
uint qHash(const QSet<T> &key, uint seed = 0)
-Q_DECL_NOEXCEPT_EXPR(noexcept(qHashRangeCommutative(key.begin(), key.end(), seed)))
+noexcept(noexcept(qHashRangeCommutative(key.begin(), key.end(), seed)))
{
return qHashRangeCommutative(key.begin(), key.end(), seed);
}
@@ -367,7 +371,7 @@ Q_INLINE_TEMPLATE bool QSet<T>::contains(const QSet<T> &other) const
}
template <typename T>
-Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::toList() const
+Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::values() const
{
QList<T> result;
result.reserve(size());
@@ -379,6 +383,7 @@ Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::toList() const
return result;
}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
template <typename T>
Q_OUTOFLINE_TEMPLATE QSet<T> QList<T>::toSet() const
{
@@ -400,6 +405,7 @@ QList<T> QList<T>::fromSet(const QSet<T> &set)
{
return set.toList();
}
+#endif
Q_DECLARE_SEQUENTIAL_ITERATOR(Set)
diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc
index 48863f2399..2e7a5a29ce 100644
--- a/src/corelib/tools/qset.qdoc
+++ b/src/corelib/tools/qset.qdoc
@@ -113,6 +113,17 @@
compiled in C++11 mode.
*/
+/*! \fn template <class T> template<typename InputIterator> QSet<T>::QSet(InputIterator first, InputIterator last)
+ \since 5.14
+
+ Constructs a set with the contents in the iterator range [\a first, \a last).
+
+ The value type of \c InputIterator must be convertible to \c T.
+
+ \note If the range [\a first, \a last) contains duplicate elements,
+ the first one is retained.
+*/
+
/*!
\fn template <class T> void QSet<T>::swap(QSet<T> &other)
diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp
index c334f71fa0..2748f9d95f 100644
--- a/src/corelib/tools/qshareddata.cpp
+++ b/src/corelib/tools/qshareddata.cpp
@@ -321,7 +321,7 @@ QT_BEGIN_NAMESPACE
*/
/*! \fn template <class T> QSharedDataPointer<T>::QSharedDataPointer()
- Constructs a QSharedDataPointer initialized with a null \e{d pointer}.
+ Constructs a QSharedDataPointer initialized with \nullptr as \e{d pointer}.
*/
/*!
@@ -368,7 +368,7 @@ QT_BEGIN_NAMESPACE
*/
/*! \fn template <class T> bool QSharedDataPointer<T>::operator!() const
- Returns \c true if the \e{d pointer} of \e this is null.
+ Returns \c true if the \e{d pointer} of \e this is \nullptr.
*/
/*! \fn template <class T> void QSharedDataPointer<T>::detach()
@@ -494,8 +494,8 @@ QT_BEGIN_NAMESPACE
*/
/*! \fn template <class T> QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer()
- Constructs a QExplicitlySharedDataPointer initialized with a null
- \e{d pointer}.
+ Constructs a QExplicitlySharedDataPointer initialized with \nullptr
+ as \e{d pointer}.
*/
/*! \fn template <class T> QExplicitlySharedDataPointer<T>::~QExplicitlySharedDataPointer()
@@ -573,8 +573,8 @@ QT_BEGIN_NAMESPACE
*/
/*! \fn template <class T> void QExplicitlySharedDataPointer<T>::reset()
- Resets \e this to be null. i.e., this function sets the
- \e{d pointer} of \e this to 0, but first it decrements
+ Resets \e this to be null - i.e., this function sets the
+ \e{d pointer} of \e this to \nullptr, but first it decrements
the reference count of the shared data object and deletes
the shared data object if the reference count became 0.
*/
@@ -582,8 +582,8 @@ QT_BEGIN_NAMESPACE
/*! \fn template <class T> T *QExplicitlySharedDataPointer<T>::take()
\since 5.12
- Returns a pointer to the shared object, and resets \e this to be null.
- That is, this function sets the \e{d pointer} of \e this to \c nullptr.
+ Returns a pointer to the shared object, and resets \e this to be \nullptr.
+ That is, this function sets the \e{d pointer} of \e this to \nullptr.
*/
/*! \fn template <class T> QExplicitlySharedDataPointer<T>::operator bool () const
@@ -591,7 +591,7 @@ QT_BEGIN_NAMESPACE
*/
/*! \fn template <class T> bool QExplicitlySharedDataPointer<T>::operator!() const
- Returns \c true if the \e{d pointer} of \e this is null.
+ Returns \c true if the \e{d pointer} of \e this is \nullptr.
*/
/*! \fn template <class T> void QExplicitlySharedDataPointer<T>::detach()
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index 6930cb96a5..ab54c76720 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -52,17 +52,21 @@ QT_BEGIN_NAMESPACE
template <class T> class QSharedDataPointer;
-class Q_CORE_EXPORT QSharedData
+class
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+Q_CORE_EXPORT
+#endif
+QSharedData
{
public:
mutable QAtomicInt ref;
- inline QSharedData() : ref(0) { }
- inline QSharedData(const QSharedData &) : ref(0) { }
+ inline QSharedData() noexcept : ref(0) { }
+ inline QSharedData(const QSharedData &) noexcept : ref(0) { }
-private:
// using the assignment operator would lead to corruption in the ref-counting
- QSharedData &operator=(const QSharedData &);
+ QSharedData &operator=(const QSharedData &) = delete;
+ ~QSharedData() = default;
};
template <class T> class QSharedDataPointer
@@ -71,7 +75,7 @@ public:
typedef T Type;
typedef T *pointer;
- inline void detach() { if (d && d->ref.load() != 1) detach_helper(); }
+ inline void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
inline T &operator*() { detach(); return *d; }
inline const T &operator*() const { return *d; }
inline T *operator->() { detach(); return d; }
@@ -88,7 +92,7 @@ public:
inline QSharedDataPointer() { d = nullptr; }
inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
- explicit QSharedDataPointer(T *data) Q_DECL_NOTHROW;
+ explicit QSharedDataPointer(T *data) noexcept;
inline QSharedDataPointer(const QSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
inline QSharedDataPointer<T> & operator=(const QSharedDataPointer<T> &o) {
if (o.d != d) {
@@ -112,19 +116,17 @@ public:
}
return *this;
}
-#ifdef Q_COMPILER_RVALUE_REFS
- QSharedDataPointer(QSharedDataPointer &&o) Q_DECL_NOTHROW : d(o.d) { o.d = nullptr; }
- inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) Q_DECL_NOTHROW
+ QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; }
+ inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) noexcept
{
QSharedDataPointer moved(std::move(other));
swap(moved);
return *this;
}
-#endif
inline bool operator!() const { return !d; }
- inline void swap(QSharedDataPointer &other) Q_DECL_NOTHROW
+ inline void swap(QSharedDataPointer &other) noexcept
{ qSwap(d, other.d); }
protected:
@@ -161,7 +163,7 @@ public:
inline const T *constData() const { return d; }
inline T *take() { T *x = d; d = nullptr; return x; }
- inline void detach() { if (d && d->ref.load() != 1) detach_helper(); }
+ inline void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
inline void reset()
{
@@ -181,7 +183,7 @@ public:
inline QExplicitlySharedDataPointer() { d = nullptr; }
inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; }
- explicit QExplicitlySharedDataPointer(T *data) Q_DECL_NOTHROW;
+ explicit QExplicitlySharedDataPointer(T *data) noexcept;
inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
template<class X>
@@ -218,19 +220,17 @@ public:
}
return *this;
}
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) Q_DECL_NOTHROW : d(o.d) { o.d = nullptr; }
- inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) Q_DECL_NOTHROW
+ inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; }
+ inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) noexcept
{
QExplicitlySharedDataPointer moved(std::move(other));
swap(moved);
return *this;
}
-#endif
inline bool operator!() const { return !d; }
- inline void swap(QExplicitlySharedDataPointer &other) Q_DECL_NOTHROW
+ inline void swap(QExplicitlySharedDataPointer &other) noexcept
{ qSwap(d, other.d); }
protected:
@@ -243,7 +243,7 @@ private:
};
template <class T>
-Q_INLINE_TEMPLATE QSharedDataPointer<T>::QSharedDataPointer(T *adata) Q_DECL_NOTHROW
+Q_INLINE_TEMPLATE QSharedDataPointer<T>::QSharedDataPointer(T *adata) noexcept
: d(adata)
{ if (d) d->ref.ref(); }
@@ -280,7 +280,7 @@ Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper()
}
template <class T>
-Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) Q_DECL_NOTHROW
+Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) noexcept
: d(adata)
{ if (d) d->ref.ref(); }
@@ -317,12 +317,12 @@ namespace std {
QT_BEGIN_NAMESPACE
template <class T>
-Q_INLINE_TEMPLATE uint qHash(const QSharedDataPointer<T> &ptr, uint seed = 0) Q_DECL_NOTHROW
+Q_INLINE_TEMPLATE uint qHash(const QSharedDataPointer<T> &ptr, uint seed = 0) noexcept
{
return qHash(ptr.data(), seed);
}
template <class T>
-Q_INLINE_TEMPLATE uint qHash(const QExplicitlySharedDataPointer<T> &ptr, uint seed = 0) Q_DECL_NOTHROW
+Q_INLINE_TEMPLATE uint qHash(const QExplicitlySharedDataPointer<T> &ptr, uint seed = 0) noexcept
{
return qHash(ptr.data(), seed);
}
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index b755941b73..f185d2f23f 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -343,12 +343,6 @@
if you obtain a non-null object, you may use the pointer. See
QWeakPointer::toStrongRef() for an example.
- QWeakPointer also provides the QWeakPointer::data() method that returns
- the tracked pointer without ensuring that it remains valid. This function
- is provided if you can guarantee by external means that the object will
- not get deleted (or if you only need the pointer value) and the cost of
- creating a QSharedPointer using toStrongRef() is too high.
-
\omit
\section1 QWeakPointer internals
@@ -384,7 +378,7 @@
You can inherit this class when you need to create a QSharedPointer
from any instance of a class; for instance, from within the
object itself. The key point is that the technique of
- just returning QSharedPointer<T>(this) can not be used, because
+ just returning QSharedPointer<T>(this) cannot be used, because
this winds up creating multiple distinct QSharedPointer objects
with separate reference counts. For this reason you must never
create more than one QSharedPointer from the same raw pointer.
@@ -406,7 +400,8 @@
/*!
\fn template <class T> QSharedPointer<T>::QSharedPointer()
- Creates a QSharedPointer that points to null (0).
+ Creates a QSharedPointer that is null (the object is holding
+ a reference to \nullptr).
*/
/*!
@@ -552,6 +547,7 @@
Provides access to the shared pointer's members.
+ If the contained pointer is \nullptr, behavior is undefined.
\sa isNull()
*/
@@ -560,21 +556,21 @@
Provides access to the shared pointer's members.
+ If the contained pointer is \nullptr, behavior is undefined.
\sa isNull()
*/
/*!
\fn template <class T> bool QSharedPointer<T>::isNull() const
- Returns \c true if this object is holding a reference to a null
- pointer.
+ Returns \c true if this object refers to \nullptr.
*/
/*!
\fn template <class T> QSharedPointer<T>::operator bool() const
- Returns \c true if this object is not null. This function is suitable
- for use in \tt if-constructs, like:
+ Returns \c true if the contained pointer is not \nullptr.
+ This function is suitable for use in \tt if-constructs, like:
\snippet code/src_corelib_tools_qsharedpointer.cpp 4
@@ -584,8 +580,8 @@
/*!
\fn template <class T> bool QSharedPointer<T>::operator !() const
- Returns \c true if this object is null. This function is suitable
- for use in \tt if-constructs, like:
+ Returns \c true if this object refers to \nullptr.
+ This function is suitable for use in \tt if-constructs, like:
\snippet code/src_corelib_tools_qsharedpointer.cpp 5
@@ -808,11 +804,10 @@
/*!
\fn template <class T> bool QWeakPointer<T>::isNull() const
- Returns \c true if this object is holding a reference to a null
- pointer.
+ Returns \c true if this object refers to \nullptr.
Note that, due to the nature of weak references, the pointer that
- QWeakPointer references can become null at any moment, so
+ QWeakPointer references can become \nullptr at any moment, so
the value returned from this function can change from false to
true from one call to the next.
*/
@@ -820,13 +815,13 @@
/*!
\fn template <class T> QWeakPointer<T>::operator bool() const
- Returns \c true if this object is not null. This function is suitable
- for use in \tt if-constructs, like:
+ Returns \c true if the contained pointer is not \nullptr.
+ This function is suitable for use in \tt if-constructs, like:
\snippet code/src_corelib_tools_qsharedpointer.cpp 8
Note that, due to the nature of weak references, the pointer that
- QWeakPointer references can become null at any moment, so
+ QWeakPointer references can become \nullptr at any moment, so
the value returned from this function can change from true to
false from one call to the next.
@@ -836,13 +831,13 @@
/*!
\fn template <class T> bool QWeakPointer<T>::operator !() const
- Returns \c true if this object is null. This function is suitable
- for use in \tt if-constructs, like:
+ Returns \c true if this object refers to \nullptr.
+ This function is suitable for use in \tt if-constructs, like:
\snippet code/src_corelib_tools_qsharedpointer.cpp 9
Note that, due to the nature of weak references, the pointer that
- QWeakPointer references can become null at any moment, so
+ QWeakPointer references can become \nullptr at any moment, so
the value returned from this function can change from false to
true from one call to the next.
@@ -852,6 +847,7 @@
/*!
\fn template <class T> T *QWeakPointer<T>::data() const
\since 4.6
+ \obsolete Use toStrongRef() instead, and data() on the returned QSharedPointer.
Returns the value of the pointer being tracked by this QWeakPointer,
\b without ensuring that it cannot get deleted. To have that guarantee,
@@ -923,7 +919,7 @@
If \c this (that is, the subclass instance invoking this method) is being
managed by a QSharedPointer, returns a shared pointer instance pointing to
- \c this; otherwise returns a QSharedPointer holding a null pointer.
+ \c this; otherwise returns a null QSharedPointer.
*/
/*!
@@ -938,8 +934,7 @@
\fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QSharedPointer
- Returns \c true if the pointer referenced by \a ptr1 is the
- same pointer as that referenced by \a ptr2.
+ Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
If \a ptr2's template parameter is different from \a ptr1's,
QSharedPointer will attempt to perform an automatic \tt static_cast
@@ -952,8 +947,7 @@
\fn template <class T> template <class X> bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QSharedPointer
- Returns \c true if the pointer referenced by \a ptr1 is not the
- same pointer as that referenced by \a ptr2.
+ Returns \c true if \a ptr1 and \a ptr2 refer to distinct pointers.
If \a ptr2's template parameter is different from \a ptr1's,
QSharedPointer will attempt to perform an automatic \tt static_cast
@@ -966,8 +960,7 @@
\fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
\relates QSharedPointer
- Returns \c true if the pointer referenced by \a ptr1 is the
- same pointer as \a ptr2.
+ Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
If \a ptr2's type is different from \a ptr1's,
QSharedPointer will attempt to perform an automatic \tt static_cast
@@ -980,8 +973,7 @@
\fn template <class T> template <class X> bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
\relates QSharedPointer
- Returns \c true if the pointer referenced by \a ptr1 is not the
- same pointer as \a ptr2.
+ Returns \c true if \a ptr1 and \a ptr2 refer to distinct pointers.
If \a ptr2's type is different from \a ptr1's,
QSharedPointer will attempt to perform an automatic \tt static_cast
@@ -1022,8 +1014,7 @@
\fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
\relates QWeakPointer
- Returns \c true if the pointer referenced by \a ptr1 is the
- same pointer as that referenced by \a ptr2.
+ Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
If \a ptr2's template parameter is different from \a ptr1's,
QSharedPointer will attempt to perform an automatic \tt static_cast
@@ -1036,8 +1027,7 @@
\fn template <class T> template <class X> bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
\relates QWeakPointer
- Returns \c true if the pointer referenced by \a ptr1 is not the
- same pointer as that referenced by \a ptr2.
+ Returns \c true if \a ptr1 and \a ptr2 refer to distinct pointers.
If \a ptr2's template parameter is different from \a ptr1's,
QSharedPointer will attempt to perform an automatic \tt static_cast
@@ -1050,8 +1040,7 @@
\fn template <class T> template <class X> bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QWeakPointer
- Returns \c true if the pointer referenced by \a ptr1 is the
- same pointer as that referenced by \a ptr2.
+ Returns \c true if \a ptr1 and \a ptr2 refer to the same pointer.
If \a ptr2's template parameter is different from \a ptr1's,
QSharedPointer will attempt to perform an automatic \tt static_cast
@@ -1065,7 +1054,7 @@
\relates QSharedPointer
\since 5.8
- Returns \c true if the pointer referenced by \a lhs is a null pointer.
+ Returns \c true if \a lhs refers to \nullptr.
\sa QSharedPointer::isNull()
*/
@@ -1075,7 +1064,7 @@
\relates QSharedPointer
\since 5.8
- Returns \c true if the pointer referenced by \a rhs is a null pointer.
+ Returns \c true if \a rhs refers to \nullptr.
\sa QSharedPointer::isNull()
*/
@@ -1085,8 +1074,7 @@
\relates QSharedPointer
\since 5.8
- Returns \c true if the pointer referenced by \a lhs is a valid (i.e.
- non-null) pointer.
+ Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer.
\sa QSharedPointer::isNull()
*/
@@ -1096,8 +1084,7 @@
\relates QSharedPointer
\since 5.8
- Returns \c true if the pointer referenced by \a rhs is a valid (i.e.
- non-null) pointer.
+ Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer.
\sa QSharedPointer::isNull()
*/
@@ -1107,7 +1094,7 @@
\relates QWeakPointer
\since 5.8
- Returns \c true if the pointer referenced by \a lhs is a null pointer.
+ Returns \c true if \a lhs refers to \nullptr.
\sa QWeakPointer::isNull()
*/
@@ -1117,7 +1104,7 @@
\relates QWeakPointer
\since 5.8
- Returns \c true if the pointer referenced by \a rhs is a null pointer.
+ Returns \c true if \a rhs refers to \nullptr.
\sa QWeakPointer::isNull()
*/
@@ -1127,8 +1114,7 @@
\relates QWeakPointer
\since 5.8
- Returns \c true if the pointer referenced by \a lhs is a valid (i.e.
- non-null) pointer.
+ Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer.
\sa QWeakPointer::isNull()
*/
@@ -1138,8 +1124,7 @@
\relates QWeakPointer
\since 5.8
- Returns \c true if the pointer referenced by \a rhs is a valid (i.e.
- non-null) pointer.
+ Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer.
\sa QWeakPointer::isNull()
*/
@@ -1148,8 +1133,7 @@
\fn template <class T> template <class X> bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
\relates QWeakPointer
- Returns \c true if the pointer referenced by \a ptr1 is not the
- same pointer as that referenced by \a ptr2.
+ Returns \c true if \a ptr1 and \a ptr2 refer to distinct pointers.
If \a ptr2's template parameter is different from \a ptr1's,
QSharedPointer will attempt to perform an automatic \tt static_cast
@@ -1282,6 +1266,57 @@
*/
/*!
+ \fn template <class X, class T> std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
+ \relates QSharedPointer
+ \since 5.14
+
+ Returns a shared pointer to the pointer held by \a src, using a
+ \l qobject_cast() to type \tt X to obtain an internal pointer of the
+ appropriate type. If the \tt qobject_cast fails, the object
+ returned will be null.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use const_pointer_cast to cast away the constness.
+*/
+
+/*!
+ \fn template <class X, class T> std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
+ \relates QSharedPointer
+ \since 5.14
+
+ Same as qSharedPointerObjectCast(). This function is provided for STL
+ compatibility.
+*/
+
+/*!
+ \fn template <class X, class T> std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
+ \relates QSharedPointer
+ \since 5.14
+
+ Returns a shared pointer to the pointer held by \a src, using a
+ \l qobject_cast() to type \tt X to obtain an internal pointer of the
+ appropriate type.
+
+ If the \tt qobject_cast succeeds, the function will return a valid shared
+ pointer, and \a src is reset to null. If the \tt qobject_cast fails, the
+ object returned will be null, and \a src will not be modified.
+
+ Note that \tt X must have the same cv-qualifiers (\tt const and
+ \tt volatile) that \tt T has, or the code will fail to
+ compile. Use const_pointer_cast to cast away the constness.
+*/
+
+/*!
+ \fn template <class X, class T> std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
+ \relates QSharedPointer
+ \since 5.14
+
+ Same as qSharedPointerObjectCast(). This function is provided for STL
+ compatibility.
+*/
+
+/*!
\fn template <class X> template <class T> QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src)
\relates QSharedPointer
\relates QWeakPointer
@@ -1345,7 +1380,7 @@ void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *, bo
*/
void QtSharedPointer::ExternalRefCountData::checkQObjectShared(const QObject *)
{
- if (strongref.load() < 0)
+ if (strongref.loadRelaxed() < 0)
qWarning("QSharedPointer: cannot create a QSharedPointer from a QObject-tracking QWeakPointer");
}
@@ -1355,7 +1390,7 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj));
Q_ASSERT_X(!d->wasDeleted, "QWeakPointer", "Detected QWeakPointer creation in a QObject being deleted");
- ExternalRefCountData *that = d->sharedRefcount.load();
+ ExternalRefCountData *that = d->sharedRefcount.loadRelaxed();
if (that) {
that->weakref.ref();
return that;
@@ -1363,8 +1398,8 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
// we can create the refcount data because it doesn't exist
ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized);
- x->strongref.store(-1);
- x->weakref.store(2); // the QWeakPointer that called us plus the QObject itself
+ x->strongref.storeRelaxed(-1);
+ x->weakref.storeRelaxed(2); // the QWeakPointer that called us plus the QObject itself
ExternalRefCountData *ret;
if (d->sharedRefcount.testAndSetOrdered(nullptr, x, ret)) { // ought to be release+acquire; this is acq_rel+acquire
@@ -1372,7 +1407,7 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
} else {
// ~ExternalRefCountData has a Q_ASSERT, so we use this trick to
// only execute this if Q_ASSERTs are enabled
- Q_ASSERT((x->weakref.store(0), true));
+ Q_ASSERT((x->weakref.storeRelaxed(0), true));
delete x;
ret->weakref.ref();
}
diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h
index a2c5f990fc..5d47369687 100644
--- a/src/corelib/tools/qsharedpointer.h
+++ b/src/corelib/tools/qsharedpointer.h
@@ -48,6 +48,8 @@
# include <QtCore/qsharedpointer_impl.h>
#else
+#include <memory> // for std::shared_ptr
+
QT_BEGIN_NAMESPACE
@@ -167,6 +169,10 @@ template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QSha
template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src);
template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &src);
template <class X, class T> QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &src);
+template <typename X, class T> std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src);
+template <typename X, class T> std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src);
+template <typename X, class T> std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src);
+template <typename X, class T> std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src);
template <class X, class T> QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &src);
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index bccf8c5740..198cc58c38 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -67,6 +67,8 @@ QT_END_NAMESPACE
#endif
#include <QtCore/qhashfunctions.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
@@ -105,6 +107,10 @@ template <class X, class T>
QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &ptr);
#endif
+namespace QtPrivate {
+struct EnableInternalData;
+}
+
namespace QtSharedPointer {
template <class T> class ExternalRefCount;
@@ -148,11 +154,11 @@ namespace QtSharedPointer {
inline ExternalRefCountData(DestroyerFn d)
: destroyer(d)
{
- strongref.store(1);
- weakref.store(1);
+ strongref.storeRelaxed(1);
+ weakref.storeRelaxed(1);
}
inline ExternalRefCountData(Qt::Initialization) { }
- ~ExternalRefCountData() { Q_ASSERT(!weakref.load()); Q_ASSERT(strongref.load() <= 0); }
+ ~ExternalRefCountData() { Q_ASSERT(!weakref.loadRelaxed()); Q_ASSERT(strongref.loadRelaxed() <= 0); }
void destroy() { destroyer(this); }
@@ -233,8 +239,8 @@ namespace QtSharedPointer {
}
private:
// prevent construction
- ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE;
- ~ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE;
+ ExternalRefCountWithCustomDeleter() = delete;
+ ~ExternalRefCountWithCustomDeleter() = delete;
Q_DISABLE_COPY(ExternalRefCountWithCustomDeleter)
};
@@ -278,8 +284,8 @@ namespace QtSharedPointer {
private:
// prevent construction
- ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
- ~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE;
+ ExternalRefCountWithContiguousData() = delete;
+ ~ExternalRefCountWithContiguousData() = delete;
Q_DISABLE_COPY(ExternalRefCountWithContiguousData)
};
@@ -303,18 +309,18 @@ public:
typedef const value_type &const_reference;
typedef qptrdiff difference_type;
- T *data() const Q_DECL_NOTHROW { return value; }
- T *get() const Q_DECL_NOTHROW { return value; }
- bool isNull() const Q_DECL_NOTHROW { return !data(); }
- operator RestrictedBool() const Q_DECL_NOTHROW { return isNull() ? nullptr : &QSharedPointer::value; }
- bool operator !() const Q_DECL_NOTHROW { return isNull(); }
+ T *data() const noexcept { return value; }
+ T *get() const noexcept { return value; }
+ bool isNull() const noexcept { return !data(); }
+ operator RestrictedBool() const noexcept { return isNull() ? nullptr : &QSharedPointer::value; }
+ bool operator !() const noexcept { return isNull(); }
T &operator*() const { return *data(); }
- T *operator->() const Q_DECL_NOTHROW { return data(); }
+ T *operator->() const noexcept { return data(); }
- Q_DECL_CONSTEXPR QSharedPointer() Q_DECL_NOTHROW : value(nullptr), d(nullptr) { }
+ Q_DECL_CONSTEXPR QSharedPointer() noexcept : value(nullptr), d(nullptr) { }
~QSharedPointer() { deref(); }
- Q_DECL_CONSTEXPR QSharedPointer(std::nullptr_t) Q_DECL_NOTHROW : value(nullptr), d(nullptr) { }
+ Q_DECL_CONSTEXPR QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
template <class X>
inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
@@ -327,22 +333,21 @@ public:
template <typename Deleter>
QSharedPointer(std::nullptr_t, Deleter) : value(nullptr), d(nullptr) { }
- QSharedPointer(const QSharedPointer &other) Q_DECL_NOTHROW : value(other.value), d(other.d)
+ QSharedPointer(const QSharedPointer &other) noexcept : value(other.value), d(other.d)
{ if (d) ref(); }
- QSharedPointer &operator=(const QSharedPointer &other) Q_DECL_NOTHROW
+ QSharedPointer &operator=(const QSharedPointer &other) noexcept
{
QSharedPointer copy(other);
swap(copy);
return *this;
}
-#ifdef Q_COMPILER_RVALUE_REFS
- QSharedPointer(QSharedPointer &&other) Q_DECL_NOTHROW
+ QSharedPointer(QSharedPointer &&other) noexcept
: value(other.value), d(other.d)
{
other.d = nullptr;
other.value = nullptr;
}
- QSharedPointer &operator=(QSharedPointer &&other) Q_DECL_NOTHROW
+ QSharedPointer &operator=(QSharedPointer &&other) noexcept
{
QSharedPointer moved(std::move(other));
swap(moved);
@@ -350,7 +355,7 @@ public:
}
template <class X>
- QSharedPointer(QSharedPointer<X> &&other) Q_DECL_NOTHROW
+ QSharedPointer(QSharedPointer<X> &&other) noexcept
: value(other.value), d(other.d)
{
other.d = nullptr;
@@ -358,17 +363,15 @@ public:
}
template <class X>
- QSharedPointer &operator=(QSharedPointer<X> &&other) Q_DECL_NOTHROW
+ QSharedPointer &operator=(QSharedPointer<X> &&other) noexcept
{
QSharedPointer moved(std::move(other));
swap(moved);
return *this;
}
-#endif
-
template <class X>
- QSharedPointer(const QSharedPointer<X> &other) Q_DECL_NOTHROW : value(other.value), d(other.d)
+ QSharedPointer(const QSharedPointer<X> &other) noexcept : value(other.value), d(other.d)
{ if (d) ref(); }
template <class X>
@@ -387,7 +390,7 @@ public:
inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
{ internalSet(other.d, other.value); return *this; }
- inline void swap(QSharedPointer &other)
+ inline void swap(QSharedPointer &other) noexcept
{ this->internalSwap(other); }
inline void reset() { clear(); }
@@ -456,9 +459,9 @@ public:
private:
explicit QSharedPointer(Qt::Initialization) {}
- void deref() Q_DECL_NOTHROW
+ void deref() noexcept
{ deref(d); }
- static void deref(Data *dd) Q_DECL_NOTHROW
+ static void deref(Data *dd) noexcept
{
if (!dd) return;
if (!dd->strongref.deref()) {
@@ -499,7 +502,7 @@ private:
enableSharedFromThis(ptr);
}
- void internalSwap(QSharedPointer &other) Q_DECL_NOTHROW
+ void internalSwap(QSharedPointer &other) noexcept
{
qSwap(d, other.d);
qSwap(this->value, other.value);
@@ -512,19 +515,19 @@ public:
template <class X> friend class QWeakPointer;
template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src);
#endif
- void ref() const Q_DECL_NOTHROW { d->weakref.ref(); d->strongref.ref(); }
+ void ref() const noexcept { d->weakref.ref(); d->strongref.ref(); }
inline void internalSet(Data *o, T *actual)
{
if (o) {
// increase the strongref, but never up from zero
// or less (-1 is used by QWeakPointer on untracked QObject)
- int tmp = o->strongref.load();
+ int tmp = o->strongref.loadRelaxed();
while (tmp > 0) {
// try to increment from "tmp" to "tmp + 1"
if (o->strongref.testAndSetRelaxed(tmp, tmp + 1))
break; // succeeded
- tmp = o->strongref.load(); // failed, try again
+ tmp = o->strongref.loadRelaxed(); // failed, try again
}
if (tmp > 0) {
@@ -537,7 +540,7 @@ public:
qSwap(d, o);
qSwap(this->value, actual);
- if (!d || d->strongref.load() == 0)
+ if (!d || d->strongref.loadRelaxed() == 0)
this->value = nullptr;
// dereference saved data
@@ -563,12 +566,16 @@ public:
typedef const value_type &const_reference;
typedef qptrdiff difference_type;
- bool isNull() const Q_DECL_NOTHROW { return d == nullptr || d->strongref.load() == 0 || value == nullptr; }
- operator RestrictedBool() const Q_DECL_NOTHROW { return isNull() ? nullptr : &QWeakPointer::value; }
- bool operator !() const Q_DECL_NOTHROW { return isNull(); }
- T *data() const Q_DECL_NOTHROW { return d == nullptr || d->strongref.load() == 0 ? nullptr : value; }
+ bool isNull() const noexcept { return d == nullptr || d->strongref.loadRelaxed() == 0 || value == nullptr; }
+ operator RestrictedBool() const noexcept { return isNull() ? nullptr : &QWeakPointer::value; }
+ bool operator !() const noexcept { return isNull(); }
- inline QWeakPointer() Q_DECL_NOTHROW : d(nullptr), value(nullptr) { }
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_X("Use toStrongRef() instead, and data() on the returned QSharedPointer")
+ T *data() const noexcept { return internalData(); }
+#endif
+
+ inline QWeakPointer() noexcept : d(nullptr), value(nullptr) { }
inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
#ifndef QT_NO_QOBJECT
@@ -586,26 +593,24 @@ public:
{ return *this = QWeakPointer(ptr); }
#endif
- QWeakPointer(const QWeakPointer &other) Q_DECL_NOTHROW : d(other.d), value(other.value)
+ QWeakPointer(const QWeakPointer &other) noexcept : d(other.d), value(other.value)
{ if (d) d->weakref.ref(); }
-#ifdef Q_COMPILER_RVALUE_REFS
- QWeakPointer(QWeakPointer &&other) Q_DECL_NOTHROW
+ QWeakPointer(QWeakPointer &&other) noexcept
: d(other.d), value(other.value)
{
other.d = nullptr;
other.value = nullptr;
}
- QWeakPointer &operator=(QWeakPointer &&other) Q_DECL_NOTHROW
+ QWeakPointer &operator=(QWeakPointer &&other) noexcept
{ QWeakPointer moved(std::move(other)); swap(moved); return *this; }
-#endif
- QWeakPointer &operator=(const QWeakPointer &other) Q_DECL_NOTHROW
+ QWeakPointer &operator=(const QWeakPointer &other) noexcept
{
QWeakPointer copy(other);
swap(copy);
return *this;
}
- void swap(QWeakPointer &other) Q_DECL_NOTHROW
+ void swap(QWeakPointer &other) noexcept
{
qSwap(this->d, other.d);
qSwap(this->value, other.value);
@@ -633,11 +638,11 @@ public:
}
template <class X>
- bool operator==(const QWeakPointer<X> &o) const Q_DECL_NOTHROW
+ bool operator==(const QWeakPointer<X> &o) const noexcept
{ return d == o.d && value == static_cast<const T *>(o.value); }
template <class X>
- bool operator!=(const QWeakPointer<X> &o) const Q_DECL_NOTHROW
+ bool operator!=(const QWeakPointer<X> &o) const noexcept
{ return !(*this == o); }
template <class X>
@@ -653,11 +658,11 @@ public:
}
template <class X>
- bool operator==(const QSharedPointer<X> &o) const Q_DECL_NOTHROW
+ bool operator==(const QSharedPointer<X> &o) const noexcept
{ return d == o.d; }
template <class X>
- bool operator!=(const QSharedPointer<X> &o) const Q_DECL_NOTHROW
+ bool operator!=(const QSharedPointer<X> &o) const noexcept
{ return !(*this == o); }
inline void clear() { *this = QWeakPointer(); }
@@ -671,7 +676,7 @@ public:
#endif
private:
-
+ friend struct QtPrivate::EnableInternalData;
#if defined(Q_NO_TEMPLATE_FRIENDS)
public:
#else
@@ -700,19 +705,33 @@ public:
value = actual;
}
+ // ### Qt 6: remove users of this API; no one should ever access
+ // a weak pointer's data but the weak pointer itself
+ inline T *internalData() const noexcept
+ {
+ return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : value;
+ }
+
Data *d;
T *value;
};
+namespace QtPrivate {
+struct EnableInternalData {
+ template <typename T>
+ static T *internalData(const QWeakPointer<T> &p) noexcept { return p.internalData(); }
+};
+// hack to delay name lookup to instantiation time by making
+// EnableInternalData a dependent name:
+template <typename T>
+struct EnableInternalDataWrap : EnableInternalData {};
+}
+
template <class T>
class QEnableSharedFromThis
{
protected:
-#ifdef Q_COMPILER_DEFAULT_MEMBERS
QEnableSharedFromThis() = default;
-#else
- Q_DECL_CONSTEXPR QEnableSharedFromThis() {}
-#endif
QEnableSharedFromThis(const QEnableSharedFromThis &) {}
QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; }
@@ -739,92 +758,92 @@ public:
// operator== and operator!=
//
template <class T, class X>
-bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
+bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) noexcept
{
return ptr1.data() == ptr2.data();
}
template <class T, class X>
-bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
+bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) noexcept
{
return ptr1.data() != ptr2.data();
}
template <class T, class X>
-bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) Q_DECL_NOTHROW
+bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) noexcept
{
return ptr1.data() == ptr2;
}
template <class T, class X>
-bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
+bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) noexcept
{
return ptr1 == ptr2.data();
}
template <class T, class X>
-bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) Q_DECL_NOTHROW
+bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) noexcept
{
return !(ptr1 == ptr2);
}
template <class T, class X>
-bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) Q_DECL_NOTHROW
+bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) noexcept
{
return !(ptr2 == ptr1);
}
template <class T, class X>
-bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) Q_DECL_NOTHROW
+bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) noexcept
{
return ptr2 == ptr1;
}
template <class T, class X>
-bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) Q_DECL_NOTHROW
+bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) noexcept
{
return ptr2 != ptr1;
}
template<class T>
-inline bool operator==(const QSharedPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
+inline bool operator==(const QSharedPointer<T> &lhs, std::nullptr_t) noexcept
{
return lhs.isNull();
}
template<class T>
-inline bool operator!=(const QSharedPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
+inline bool operator!=(const QSharedPointer<T> &lhs, std::nullptr_t) noexcept
{
return !lhs.isNull();
}
template<class T>
-inline bool operator==(std::nullptr_t, const QSharedPointer<T> &rhs) Q_DECL_NOTHROW
+inline bool operator==(std::nullptr_t, const QSharedPointer<T> &rhs) noexcept
{
return rhs.isNull();
}
template<class T>
-inline bool operator!=(std::nullptr_t, const QSharedPointer<T> &rhs) Q_DECL_NOTHROW
+inline bool operator!=(std::nullptr_t, const QSharedPointer<T> &rhs) noexcept
{
return !rhs.isNull();
}
template<class T>
-inline bool operator==(const QWeakPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
+inline bool operator==(const QWeakPointer<T> &lhs, std::nullptr_t) noexcept
{
return lhs.isNull();
}
template<class T>
-inline bool operator!=(const QWeakPointer<T> &lhs, std::nullptr_t) Q_DECL_NOTHROW
+inline bool operator!=(const QWeakPointer<T> &lhs, std::nullptr_t) noexcept
{
return !lhs.isNull();
}
template<class T>
-inline bool operator==(std::nullptr_t, const QWeakPointer<T> &rhs) Q_DECL_NOTHROW
+inline bool operator==(std::nullptr_t, const QWeakPointer<T> &rhs) noexcept
{
return rhs.isNull();
}
template<class T>
-inline bool operator!=(std::nullptr_t, const QWeakPointer<T> &rhs) Q_DECL_NOTHROW
+inline bool operator!=(std::nullptr_t, const QWeakPointer<T> &rhs) noexcept
{
return !rhs.isNull();
}
@@ -887,18 +906,12 @@ Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const
}
template <class T>
-inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2)
-{
- p1.swap(p2);
-}
+inline void swap(QSharedPointer<T> &p1, QSharedPointer<T> &p2) noexcept
+{ p1.swap(p2); }
-QT_END_NAMESPACE
-namespace std {
- template <class T>
- inline void swap(QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p2)
- { p1.swap(p2); }
-}
-QT_BEGIN_NAMESPACE
+template <class T>
+inline void swap(QWeakPointer<T> &p1, QWeakPointer<T> &p2) noexcept
+{ p1.swap(p2); }
namespace QtSharedPointer {
// helper functions:
@@ -983,11 +996,13 @@ qobject_cast(const QWeakPointer<T> &src)
return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src);
}
+/// ### Qt 6: make this use toStrongRef() (once support for storing
+/// non-managed QObjects in QWeakPointer is removed)
template<typename T>
QWeakPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
qWeakPointerFromVariant(const QVariant &variant)
{
- return QWeakPointer<T>(qobject_cast<T*>(QtSharedPointer::weakPointerFromVariant_internal(variant).data()));
+ return QWeakPointer<T>(qobject_cast<T*>(QtPrivate::EnableInternalData::internalData(QtSharedPointer::weakPointerFromVariant_internal(variant))));
}
template<typename T>
QSharedPointer<typename std::enable_if<QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value, T>::type>
@@ -996,6 +1011,46 @@ qSharedPointerFromVariant(const QVariant &variant)
return qSharedPointerObjectCast<T>(QtSharedPointer::sharedPointerFromVariant_internal(variant));
}
+// std::shared_ptr helpers
+
+template <typename X, class T>
+std::shared_ptr<X> qobject_pointer_cast(const std::shared_ptr<T> &src)
+{
+ using element_type = typename std::shared_ptr<X>::element_type;
+ return std::shared_ptr<X>(src, qobject_cast<element_type *>(src.get()));
+}
+
+template <typename X, class T>
+std::shared_ptr<X> qobject_pointer_cast(std::shared_ptr<T> &&src)
+{
+ using element_type = typename std::shared_ptr<X>::element_type;
+ auto castResult = qobject_cast<element_type *>(src.get());
+ if (castResult) {
+ auto result = std::shared_ptr<X>(std::move(src), castResult);
+#if __cplusplus <= 201703L
+ // C++2a's move aliasing constructor will leave src empty.
+ // Before C++2a we don't really know if the compiler has support for it.
+ // The move aliasing constructor is the resolution for LWG2996,
+ // which does not impose a feature-testing macro. So: clear src.
+ src.reset();
+#endif
+ return result;
+ }
+ return std::shared_ptr<X>();
+}
+
+template <typename X, class T>
+std::shared_ptr<X> qSharedPointerObjectCast(const std::shared_ptr<T> &src)
+{
+ return qobject_pointer_cast<X>(src);
+}
+
+template <typename X, class T>
+std::shared_ptr<X> qSharedPointerObjectCast(std::shared_ptr<T> &&src)
+{
+ return qobject_pointer_cast<X>(std::move(src));
+}
+
#endif
template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE);
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index e44307f28d..ecf1822e42 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -533,7 +533,7 @@ Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC
Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) };
#endif
-void qDetectCpuFeatures()
+quint64 qDetectCpuFeatures()
{
quint64 f = detectProcessorFeatures();
QByteArray disable = qgetenv("QT_NO_CPU_FEATURE");
@@ -563,10 +563,11 @@ void qDetectCpuFeatures()
features_string + features_indices[qCountTrailingZeroBits(missing)]);
}
- qt_cpu_features[0].store(f | quint32(QSimdInitialized));
+ qt_cpu_features[0].storeRelaxed(f | quint32(QSimdInitialized));
#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
- qt_cpu_features[1].store(f >> 32);
+ qt_cpu_features[1].storeRelaxed(f >> 32);
#endif
+ return f;
}
void qDumpCPUFeatures()
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index 9f1321df94..db2f546651 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -344,20 +344,16 @@ extern Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1];
#else
extern Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2];
#endif
-Q_CORE_EXPORT void qDetectCpuFeatures();
+Q_CORE_EXPORT quint64 qDetectCpuFeatures();
static inline quint64 qCpuFeatures()
{
- quint64 features = qt_cpu_features[0].load();
+ quint64 features = qt_cpu_features[0].loadRelaxed();
#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
- features |= quint64(qt_cpu_features[1].load()) << 32;
+ features |= quint64(qt_cpu_features[1].loadRelaxed()) << 32;
#endif
if (Q_UNLIKELY(features == 0)) {
- qDetectCpuFeatures();
- features = qt_cpu_features[0].load();
-#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
- features |= quint64(qt_cpu_features[1].load()) << 32;
-#endif
+ features = qDetectCpuFeatures();
Q_ASSUME(features != 0);
}
return features;
diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp
index 3e97947ad2..fe508ad459 100644
--- a/src/corelib/tools/qsize.cpp
+++ b/src/corelib/tools/qsize.cpp
@@ -163,7 +163,7 @@ QT_BEGIN_NAMESPACE
\sa setWidth(), setHeight(), transposed()
*/
-void QSize::transpose() Q_DECL_NOTHROW
+void QSize::transpose() noexcept
{
qSwap(wd, ht);
}
@@ -222,7 +222,7 @@ void QSize::transpose() Q_DECL_NOTHROW
Return a size scaled to a rectangle with the given size \a s,
according to the specified \a mode.
*/
-QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW
+QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
{
if (mode == Qt::IgnoreAspectRatio || wd == 0 || ht == 0) {
return s;
@@ -594,7 +594,7 @@ QDebug operator<<(QDebug dbg, const QSize &s)
\sa setWidth(), setHeight(), transposed()
*/
-void QSizeF::transpose() Q_DECL_NOTHROW
+void QSizeF::transpose() noexcept
{
qSwap(wd, ht);
}
@@ -653,7 +653,7 @@ void QSizeF::transpose() Q_DECL_NOTHROW
Returns a size scaled to a rectangle with the given size \a s,
according to the specified \a mode.
*/
-QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW
+QSizeF QSizeF::scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept
{
if (mode == Qt::IgnoreAspectRatio || qIsNull(wd) || qIsNull(ht)) {
return s;
diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h
index bb29dca7c4..4114609856 100644
--- a/src/corelib/tools/qsize.h
+++ b/src/corelib/tools/qsize.h
@@ -52,46 +52,46 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QSize
{
public:
- Q_DECL_CONSTEXPR QSize() Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QSize(int w, int h) Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline bool isNull() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline bool isEmpty() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline bool isValid() const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline int width() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline int height() const Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setWidth(int w) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setHeight(int h) Q_DECL_NOTHROW;
- void transpose() Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize transposed() const Q_DECL_NOTHROW;
-
- inline void scale(int w, int h, Qt::AspectRatioMode mode) Q_DECL_NOTHROW;
- inline void scale(const QSize &s, Qt::AspectRatioMode mode) Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT QSize scaled(int w, int h, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW;
-
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize expandedTo(const QSize &) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize boundedTo(const QSize &) const Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline int &rwidth() Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline int &rheight() Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline QSize &operator+=(const QSize &) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline QSize &operator-=(const QSize &) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline QSize &operator*=(qreal c) Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR QSize() noexcept;
+ Q_DECL_CONSTEXPR QSize(int w, int h) noexcept;
+
+ Q_DECL_CONSTEXPR inline bool isNull() const noexcept;
+ Q_DECL_CONSTEXPR inline bool isEmpty() const noexcept;
+ Q_DECL_CONSTEXPR inline bool isValid() const noexcept;
+
+ Q_DECL_CONSTEXPR inline int width() const noexcept;
+ Q_DECL_CONSTEXPR inline int height() const noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setWidth(int w) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setHeight(int h) noexcept;
+ void transpose() noexcept;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize transposed() const noexcept;
+
+ inline void scale(int w, int h, Qt::AspectRatioMode mode) noexcept;
+ inline void scale(const QSize &s, Qt::AspectRatioMode mode) noexcept;
+ Q_REQUIRED_RESULT QSize scaled(int w, int h, Qt::AspectRatioMode mode) const noexcept;
+ Q_REQUIRED_RESULT QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept;
+
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize expandedTo(const QSize &) const noexcept;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize boundedTo(const QSize &) const noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline int &rwidth() noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline int &rheight() noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline QSize &operator+=(const QSize &) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline QSize &operator-=(const QSize &) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline QSize &operator*=(qreal c) noexcept;
inline QSize &operator/=(qreal c);
- friend inline Q_DECL_CONSTEXPR bool operator==(const QSize &, const QSize &) Q_DECL_NOTHROW;
- friend inline Q_DECL_CONSTEXPR bool operator!=(const QSize &, const QSize &) Q_DECL_NOTHROW;
- friend inline Q_DECL_CONSTEXPR const QSize operator+(const QSize &, const QSize &) Q_DECL_NOTHROW;
- friend inline Q_DECL_CONSTEXPR const QSize operator-(const QSize &, const QSize &) Q_DECL_NOTHROW;
- friend inline Q_DECL_CONSTEXPR const QSize operator*(const QSize &, qreal) Q_DECL_NOTHROW;
- friend inline Q_DECL_CONSTEXPR const QSize operator*(qreal, const QSize &) Q_DECL_NOTHROW;
+ friend inline Q_DECL_CONSTEXPR bool operator==(const QSize &, const QSize &) noexcept;
+ friend inline Q_DECL_CONSTEXPR bool operator!=(const QSize &, const QSize &) noexcept;
+ friend inline Q_DECL_CONSTEXPR const QSize operator+(const QSize &, const QSize &) noexcept;
+ friend inline Q_DECL_CONSTEXPR const QSize operator-(const QSize &, const QSize &) noexcept;
+ friend inline Q_DECL_CONSTEXPR const QSize operator*(const QSize &, qreal) noexcept;
+ friend inline Q_DECL_CONSTEXPR const QSize operator*(qreal, const QSize &) noexcept;
friend inline const QSize operator/(const QSize &, qreal);
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT CGSize toCGSize() const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT CGSize toCGSize() const noexcept;
#endif
private:
@@ -114,74 +114,74 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSize &);
QSize inline functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QSize::QSize() Q_DECL_NOTHROW : wd(-1), ht(-1) {}
+Q_DECL_CONSTEXPR inline QSize::QSize() noexcept : wd(-1), ht(-1) {}
-Q_DECL_CONSTEXPR inline QSize::QSize(int w, int h) Q_DECL_NOTHROW : wd(w), ht(h) {}
+Q_DECL_CONSTEXPR inline QSize::QSize(int w, int h) noexcept : wd(w), ht(h) {}
-Q_DECL_CONSTEXPR inline bool QSize::isNull() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QSize::isNull() const noexcept
{ return wd==0 && ht==0; }
-Q_DECL_CONSTEXPR inline bool QSize::isEmpty() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QSize::isEmpty() const noexcept
{ return wd<1 || ht<1; }
-Q_DECL_CONSTEXPR inline bool QSize::isValid() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QSize::isValid() const noexcept
{ return wd>=0 && ht>=0; }
-Q_DECL_CONSTEXPR inline int QSize::width() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QSize::width() const noexcept
{ return wd; }
-Q_DECL_CONSTEXPR inline int QSize::height() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int QSize::height() const noexcept
{ return ht; }
-Q_DECL_RELAXED_CONSTEXPR inline void QSize::setWidth(int w) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QSize::setWidth(int w) noexcept
{ wd = w; }
-Q_DECL_RELAXED_CONSTEXPR inline void QSize::setHeight(int h) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QSize::setHeight(int h) noexcept
{ ht = h; }
-Q_DECL_CONSTEXPR inline QSize QSize::transposed() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QSize QSize::transposed() const noexcept
{ return QSize(ht, wd); }
-inline void QSize::scale(int w, int h, Qt::AspectRatioMode mode) Q_DECL_NOTHROW
+inline void QSize::scale(int w, int h, Qt::AspectRatioMode mode) noexcept
{ scale(QSize(w, h), mode); }
-inline void QSize::scale(const QSize &s, Qt::AspectRatioMode mode) Q_DECL_NOTHROW
+inline void QSize::scale(const QSize &s, Qt::AspectRatioMode mode) noexcept
{ *this = scaled(s, mode); }
-inline QSize QSize::scaled(int w, int h, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW
+inline QSize QSize::scaled(int w, int h, Qt::AspectRatioMode mode) const noexcept
{ return scaled(QSize(w, h), mode); }
-Q_DECL_RELAXED_CONSTEXPR inline int &QSize::rwidth() Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline int &QSize::rwidth() noexcept
{ return wd; }
-Q_DECL_RELAXED_CONSTEXPR inline int &QSize::rheight() Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline int &QSize::rheight() noexcept
{ return ht; }
-Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator+=(const QSize &s) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator+=(const QSize &s) noexcept
{ wd+=s.wd; ht+=s.ht; return *this; }
-Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator-=(const QSize &s) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator-=(const QSize &s) noexcept
{ wd-=s.wd; ht-=s.ht; return *this; }
-Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator*=(qreal c) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QSize &QSize::operator*=(qreal c) noexcept
{ wd = qRound(wd*c); ht = qRound(ht*c); return *this; }
-Q_DECL_CONSTEXPR inline bool operator==(const QSize &s1, const QSize &s2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator==(const QSize &s1, const QSize &s2) noexcept
{ return s1.wd == s2.wd && s1.ht == s2.ht; }
-Q_DECL_CONSTEXPR inline bool operator!=(const QSize &s1, const QSize &s2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator!=(const QSize &s1, const QSize &s2) noexcept
{ return s1.wd != s2.wd || s1.ht != s2.ht; }
-Q_DECL_CONSTEXPR inline const QSize operator+(const QSize & s1, const QSize & s2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline const QSize operator+(const QSize & s1, const QSize & s2) noexcept
{ return QSize(s1.wd+s2.wd, s1.ht+s2.ht); }
-Q_DECL_CONSTEXPR inline const QSize operator-(const QSize &s1, const QSize &s2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline const QSize operator-(const QSize &s1, const QSize &s2) noexcept
{ return QSize(s1.wd-s2.wd, s1.ht-s2.ht); }
-Q_DECL_CONSTEXPR inline const QSize operator*(const QSize &s, qreal c) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline const QSize operator*(const QSize &s, qreal c) noexcept
{ return QSize(qRound(s.wd*c), qRound(s.ht*c)); }
-Q_DECL_CONSTEXPR inline const QSize operator*(qreal c, const QSize &s) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline const QSize operator*(qreal c, const QSize &s) noexcept
{ return QSize(qRound(s.wd*c), qRound(s.ht*c)); }
inline QSize &QSize::operator/=(qreal c)
@@ -197,12 +197,12 @@ inline const QSize operator/(const QSize &s, qreal c)
return QSize(qRound(s.wd/c), qRound(s.ht/c));
}
-Q_DECL_CONSTEXPR inline QSize QSize::expandedTo(const QSize & otherSize) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QSize QSize::expandedTo(const QSize & otherSize) const noexcept
{
return QSize(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht));
}
-Q_DECL_CONSTEXPR inline QSize QSize::boundedTo(const QSize & otherSize) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QSize QSize::boundedTo(const QSize & otherSize) const noexcept
{
return QSize(qMin(wd,otherSize.wd), qMin(ht,otherSize.ht));
}
@@ -215,50 +215,50 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QSize &);
class Q_CORE_EXPORT QSizeF
{
public:
- Q_DECL_CONSTEXPR QSizeF() Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QSizeF(const QSize &sz) Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR QSizeF(qreal w, qreal h) Q_DECL_NOTHROW;
-
- inline bool isNull() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline bool isEmpty() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline bool isValid() const Q_DECL_NOTHROW;
-
- Q_DECL_CONSTEXPR inline qreal width() const Q_DECL_NOTHROW;
- Q_DECL_CONSTEXPR inline qreal height() const Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setWidth(qreal w) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline void setHeight(qreal h) Q_DECL_NOTHROW;
- void transpose() Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF transposed() const Q_DECL_NOTHROW;
-
- inline void scale(qreal w, qreal h, Qt::AspectRatioMode mode) Q_DECL_NOTHROW;
- inline void scale(const QSizeF &s, Qt::AspectRatioMode mode) Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT QSizeF scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT QSizeF scaled(const QSizeF &s, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW;
-
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF expandedTo(const QSizeF &) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF boundedTo(const QSizeF &) const Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline qreal &rwidth() Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline qreal &rheight() Q_DECL_NOTHROW;
-
- Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator+=(const QSizeF &) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator-=(const QSizeF &) Q_DECL_NOTHROW;
- Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator*=(qreal c) Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR QSizeF() noexcept;
+ Q_DECL_CONSTEXPR QSizeF(const QSize &sz) noexcept;
+ Q_DECL_CONSTEXPR QSizeF(qreal w, qreal h) noexcept;
+
+ inline bool isNull() const noexcept;
+ Q_DECL_CONSTEXPR inline bool isEmpty() const noexcept;
+ Q_DECL_CONSTEXPR inline bool isValid() const noexcept;
+
+ Q_DECL_CONSTEXPR inline qreal width() const noexcept;
+ Q_DECL_CONSTEXPR inline qreal height() const noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setWidth(qreal w) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline void setHeight(qreal h) noexcept;
+ void transpose() noexcept;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF transposed() const noexcept;
+
+ inline void scale(qreal w, qreal h, Qt::AspectRatioMode mode) noexcept;
+ inline void scale(const QSizeF &s, Qt::AspectRatioMode mode) noexcept;
+ Q_REQUIRED_RESULT QSizeF scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const noexcept;
+ Q_REQUIRED_RESULT QSizeF scaled(const QSizeF &s, Qt::AspectRatioMode mode) const noexcept;
+
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF expandedTo(const QSizeF &) const noexcept;
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF boundedTo(const QSizeF &) const noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline qreal &rwidth() noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline qreal &rheight() noexcept;
+
+ Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator+=(const QSizeF &) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator-=(const QSizeF &) noexcept;
+ Q_DECL_RELAXED_CONSTEXPR inline QSizeF &operator*=(qreal c) noexcept;
inline QSizeF &operator/=(qreal c);
- friend Q_DECL_CONSTEXPR inline bool operator==(const QSizeF &, const QSizeF &) Q_DECL_NOTHROW;
- friend Q_DECL_CONSTEXPR inline bool operator!=(const QSizeF &, const QSizeF &) Q_DECL_NOTHROW;
- friend Q_DECL_CONSTEXPR inline const QSizeF operator+(const QSizeF &, const QSizeF &) Q_DECL_NOTHROW;
- friend Q_DECL_CONSTEXPR inline const QSizeF operator-(const QSizeF &, const QSizeF &) Q_DECL_NOTHROW;
- friend Q_DECL_CONSTEXPR inline const QSizeF operator*(const QSizeF &, qreal) Q_DECL_NOTHROW;
- friend Q_DECL_CONSTEXPR inline const QSizeF operator*(qreal, const QSizeF &) Q_DECL_NOTHROW;
+ friend Q_DECL_CONSTEXPR inline bool operator==(const QSizeF &, const QSizeF &) noexcept;
+ friend Q_DECL_CONSTEXPR inline bool operator!=(const QSizeF &, const QSizeF &) noexcept;
+ friend Q_DECL_CONSTEXPR inline const QSizeF operator+(const QSizeF &, const QSizeF &) noexcept;
+ friend Q_DECL_CONSTEXPR inline const QSizeF operator-(const QSizeF &, const QSizeF &) noexcept;
+ friend Q_DECL_CONSTEXPR inline const QSizeF operator*(const QSizeF &, qreal) noexcept;
+ friend Q_DECL_CONSTEXPR inline const QSizeF operator*(qreal, const QSizeF &) noexcept;
friend inline const QSizeF operator/(const QSizeF &, qreal);
- Q_DECL_CONSTEXPR inline QSize toSize() const Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR inline QSize toSize() const noexcept;
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
- Q_REQUIRED_RESULT static QSizeF fromCGSize(CGSize size) Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT CGSize toCGSize() const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT static QSizeF fromCGSize(CGSize size) noexcept;
+ Q_REQUIRED_RESULT CGSize toCGSize() const noexcept;
#endif
private:
@@ -282,76 +282,76 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSizeF &);
QSizeF inline functions
*****************************************************************************/
-Q_DECL_CONSTEXPR inline QSizeF::QSizeF() Q_DECL_NOTHROW : wd(-1.), ht(-1.) {}
+Q_DECL_CONSTEXPR inline QSizeF::QSizeF() noexcept : wd(-1.), ht(-1.) {}
-Q_DECL_CONSTEXPR inline QSizeF::QSizeF(const QSize &sz) Q_DECL_NOTHROW : wd(sz.width()), ht(sz.height()) {}
+Q_DECL_CONSTEXPR inline QSizeF::QSizeF(const QSize &sz) noexcept : wd(sz.width()), ht(sz.height()) {}
-Q_DECL_CONSTEXPR inline QSizeF::QSizeF(qreal w, qreal h) Q_DECL_NOTHROW : wd(w), ht(h) {}
+Q_DECL_CONSTEXPR inline QSizeF::QSizeF(qreal w, qreal h) noexcept : wd(w), ht(h) {}
-inline bool QSizeF::isNull() const Q_DECL_NOTHROW
+inline bool QSizeF::isNull() const noexcept
{ return qIsNull(wd) && qIsNull(ht); }
-Q_DECL_CONSTEXPR inline bool QSizeF::isEmpty() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QSizeF::isEmpty() const noexcept
{ return wd <= 0. || ht <= 0.; }
-Q_DECL_CONSTEXPR inline bool QSizeF::isValid() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool QSizeF::isValid() const noexcept
{ return wd >= 0. && ht >= 0.; }
-Q_DECL_CONSTEXPR inline qreal QSizeF::width() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline qreal QSizeF::width() const noexcept
{ return wd; }
-Q_DECL_CONSTEXPR inline qreal QSizeF::height() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline qreal QSizeF::height() const noexcept
{ return ht; }
-Q_DECL_RELAXED_CONSTEXPR inline void QSizeF::setWidth(qreal w) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QSizeF::setWidth(qreal w) noexcept
{ wd = w; }
-Q_DECL_RELAXED_CONSTEXPR inline void QSizeF::setHeight(qreal h) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline void QSizeF::setHeight(qreal h) noexcept
{ ht = h; }
-Q_DECL_CONSTEXPR inline QSizeF QSizeF::transposed() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QSizeF QSizeF::transposed() const noexcept
{ return QSizeF(ht, wd); }
-inline void QSizeF::scale(qreal w, qreal h, Qt::AspectRatioMode mode) Q_DECL_NOTHROW
+inline void QSizeF::scale(qreal w, qreal h, Qt::AspectRatioMode mode) noexcept
{ scale(QSizeF(w, h), mode); }
-inline void QSizeF::scale(const QSizeF &s, Qt::AspectRatioMode mode) Q_DECL_NOTHROW
+inline void QSizeF::scale(const QSizeF &s, Qt::AspectRatioMode mode) noexcept
{ *this = scaled(s, mode); }
-inline QSizeF QSizeF::scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const Q_DECL_NOTHROW
+inline QSizeF QSizeF::scaled(qreal w, qreal h, Qt::AspectRatioMode mode) const noexcept
{ return scaled(QSizeF(w, h), mode); }
-Q_DECL_RELAXED_CONSTEXPR inline qreal &QSizeF::rwidth() Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline qreal &QSizeF::rwidth() noexcept
{ return wd; }
-Q_DECL_RELAXED_CONSTEXPR inline qreal &QSizeF::rheight() Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline qreal &QSizeF::rheight() noexcept
{ return ht; }
-Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator+=(const QSizeF &s) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator+=(const QSizeF &s) noexcept
{ wd += s.wd; ht += s.ht; return *this; }
-Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator-=(const QSizeF &s) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator-=(const QSizeF &s) noexcept
{ wd -= s.wd; ht -= s.ht; return *this; }
-Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator*=(qreal c) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline QSizeF &QSizeF::operator*=(qreal c) noexcept
{ wd *= c; ht *= c; return *this; }
-Q_DECL_CONSTEXPR inline bool operator==(const QSizeF &s1, const QSizeF &s2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator==(const QSizeF &s1, const QSizeF &s2) noexcept
{ return qFuzzyCompare(s1.wd, s2.wd) && qFuzzyCompare(s1.ht, s2.ht); }
-Q_DECL_CONSTEXPR inline bool operator!=(const QSizeF &s1, const QSizeF &s2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator!=(const QSizeF &s1, const QSizeF &s2) noexcept
{ return !qFuzzyCompare(s1.wd, s2.wd) || !qFuzzyCompare(s1.ht, s2.ht); }
-Q_DECL_CONSTEXPR inline const QSizeF operator+(const QSizeF & s1, const QSizeF & s2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline const QSizeF operator+(const QSizeF & s1, const QSizeF & s2) noexcept
{ return QSizeF(s1.wd+s2.wd, s1.ht+s2.ht); }
-Q_DECL_CONSTEXPR inline const QSizeF operator-(const QSizeF &s1, const QSizeF &s2) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline const QSizeF operator-(const QSizeF &s1, const QSizeF &s2) noexcept
{ return QSizeF(s1.wd-s2.wd, s1.ht-s2.ht); }
-Q_DECL_CONSTEXPR inline const QSizeF operator*(const QSizeF &s, qreal c) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline const QSizeF operator*(const QSizeF &s, qreal c) noexcept
{ return QSizeF(s.wd*c, s.ht*c); }
-Q_DECL_CONSTEXPR inline const QSizeF operator*(qreal c, const QSizeF &s) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline const QSizeF operator*(qreal c, const QSizeF &s) noexcept
{ return QSizeF(s.wd*c, s.ht*c); }
inline QSizeF &QSizeF::operator/=(qreal c)
@@ -367,17 +367,17 @@ inline const QSizeF operator/(const QSizeF &s, qreal c)
return QSizeF(s.wd/c, s.ht/c);
}
-Q_DECL_CONSTEXPR inline QSizeF QSizeF::expandedTo(const QSizeF & otherSize) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QSizeF QSizeF::expandedTo(const QSizeF & otherSize) const noexcept
{
return QSizeF(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht));
}
-Q_DECL_CONSTEXPR inline QSizeF QSizeF::boundedTo(const QSizeF & otherSize) const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QSizeF QSizeF::boundedTo(const QSizeF & otherSize) const noexcept
{
return QSizeF(qMin(wd,otherSize.wd), qMin(ht,otherSize.ht));
}
-Q_DECL_CONSTEXPR inline QSize QSizeF::toSize() const Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline QSize QSizeF::toSize() const noexcept
{
return QSize(qRound(wd), qRound(ht));
}
diff --git a/src/corelib/tools/qstack.h b/src/corelib/tools/qstack.h
index bf04935b50..e59212aa2a 100644
--- a/src/corelib/tools/qstack.h
+++ b/src/corelib/tools/qstack.h
@@ -50,7 +50,7 @@ class QStack : public QVector<T>
{
public:
// compiler-generated special member functions are fine!
- inline void swap(QStack<T> &other) Q_DECL_NOTHROW { QVector<T>::swap(other); } // prevent QVector<->QStack swaps
+ inline void swap(QStack<T> &other) noexcept { QVector<T>::swap(other); } // prevent QVector<->QStack swaps
inline void push(const T &t) { QVector<T>::append(t); }
T pop();
T &top();
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 4852d20082..f9a9fcfe91 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -2,6 +2,7 @@
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2018 Intel Corporation.
+** Copyright (C) 2019 Mail.ru Group.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -120,7 +121,7 @@ QT_BEGIN_NAMESPACE
* Whenever multiple alternatives are equivalent or near so, we prefer the one
* using instructions from SSE2, since SSE2 is guaranteed to be enabled for all
* 64-bit builds and we enable it for 32-bit builds by default. Use of higher
- * SSE versions should be done when there's a clear performance benefit and
+ * SSE versions should be done when there is a clear performance benefit and
* requires fallback code to SSE2, if it exists.
*
* Performance measurement in the past shows that most strings are short in
@@ -142,19 +143,13 @@ extern "C" void qt_toLatin1_mips_dsp_asm(uchar *dst, const ushort *src, int leng
#endif
// internal
-int qFindString(const QChar *haystack, int haystackLen, int from,
- const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
-int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from,
- const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
-static inline int qt_last_index_of(const QChar *haystack, int haystackLen, QChar needle,
- int from, Qt::CaseSensitivity cs);
-static inline int qt_string_count(const QChar *haystack, int haystackLen,
- const QChar *needle, int needleLen,
- Qt::CaseSensitivity cs);
-static inline int qt_string_count(const QChar *haystack, int haystackLen,
- QChar needle, Qt::CaseSensitivity cs);
-static inline int qt_find_latin1_string(const QChar *hay, int size, QLatin1String needle,
- int from, Qt::CaseSensitivity cs);
+qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs);
+static inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept;
+template <typename Haystack>
+static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs) noexcept;
+static inline qsizetype qt_string_count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs);
+static inline qsizetype qt_string_count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
+
static inline bool qt_starts_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs);
static inline bool qt_starts_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
@@ -162,7 +157,7 @@ static inline bool qt_ends_with(QStringView haystack, QStringView needle, Qt::Ca
static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
-qsizetype QtPrivate::qustrlen(const ushort *str) Q_DECL_NOTHROW
+qsizetype QtPrivate::qustrlen(const ushort *str) noexcept
{
qsizetype result = 0;
@@ -208,7 +203,7 @@ qsizetype QtPrivate::qustrlen(const ushort *str) Q_DECL_NOTHROW
return result;
}
-#if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
+#if !defined(__OPTIMIZE_SIZE__)
namespace {
template <uint MaxCount> struct UnrollTailLoop
{
@@ -460,7 +455,7 @@ static Q_ALWAYS_INLINE __m128i mm_load8_zero_extend(const void *ptr)
// Note: ptr on output may be off by one and point to a preceding US-ASCII
// character. Usually harmless.
-bool qt_is_ascii(const char *&ptr, const char *end) Q_DECL_NOTHROW
+bool qt_is_ascii(const char *&ptr, const char *end) noexcept
{
#if defined(__SSE2__)
// Testing for the high bit can be done efficiently with just PMOVMSKB
@@ -520,7 +515,7 @@ bool qt_is_ascii(const char *&ptr, const char *end) Q_DECL_NOTHROW
return true;
}
-bool QtPrivate::isAscii(QLatin1String s) Q_DECL_NOTHROW
+bool QtPrivate::isAscii(QLatin1String s) noexcept
{
const char *ptr = s.begin();
const char *end = s.end();
@@ -547,7 +542,7 @@ static bool isAscii(const QChar *&ptr, const QChar *end)
return true;
}
-bool QtPrivate::isAscii(QStringView s) Q_DECL_NOTHROW
+bool QtPrivate::isAscii(QStringView s) noexcept
{
const QChar *ptr = s.begin();
const QChar *end = s.end();
@@ -555,7 +550,7 @@ bool QtPrivate::isAscii(QStringView s) Q_DECL_NOTHROW
return isAscii(ptr, end);
}
-bool QtPrivate::isLatin1(QStringView s) Q_DECL_NOTHROW
+bool QtPrivate::isLatin1(QStringView s) noexcept
{
const QChar *ptr = s.begin();
const QChar *end = s.end();
@@ -595,7 +590,7 @@ bool QtPrivate::isLatin1(QStringView s) Q_DECL_NOTHROW
}
// conversion between Latin 1 and UTF-16
-void qt_from_latin1(ushort *dst, const char *str, size_t size) Q_DECL_NOTHROW
+void qt_from_latin1(ushort *dst, const char *str, size_t size) noexcept
{
/* SIMD:
* Unpacking with SSE has been shown to improve performance on recent CPUs
@@ -638,7 +633,7 @@ void qt_from_latin1(ushort *dst, const char *str, size_t size) Q_DECL_NOTHROW
size = size % 8;
dst += offset;
str += offset;
-# if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
+# if !defined(__OPTIMIZE_SIZE__)
return UnrollTailLoop<7>::exec(int(size), [=](int i) { dst[i] = (uchar)str[i]; });
# endif
#endif
@@ -833,9 +828,9 @@ static int ucstricmp(const QChar *a, const QChar *ae, const QChar *b, const QCha
uint alast = 0;
uint blast = 0;
while (a < e) {
-// qDebug() << hex << alast << blast;
-// qDebug() << hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast);
-// qDebug() << hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast);
+// qDebug() << Qt::hex << alast << blast;
+// qDebug() << Qt::hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast);
+// qDebug() << Qt::hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast);
int diff = foldCase(a->unicode(), alast) - foldCase(b->unicode(), blast);
if ((diff))
return diff;
@@ -1152,7 +1147,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, size_t l)
}
template <typename Number>
-Q_DECL_CONSTEXPR int lencmp(Number lhs, Number rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR int lencmp(Number lhs, Number rhs) noexcept
{
return lhs == rhs ? 0 :
lhs > rhs ? 1 :
@@ -1176,7 +1171,7 @@ static int ucstrcmp(const QChar *a, size_t alen, const char *b, size_t blen)
return cmp ? cmp : lencmp(alen, blen);
}
-static int qt_compare_strings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+static int qt_compare_strings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) noexcept
{
if (cs == Qt::CaseSensitive)
return ucstrcmp(lhs.begin(), lhs.size(), rhs.begin(), rhs.size());
@@ -1184,7 +1179,7 @@ static int qt_compare_strings(QStringView lhs, QStringView rhs, Qt::CaseSensitiv
return ucstricmp(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
-static int qt_compare_strings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+static int qt_compare_strings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs) noexcept
{
if (cs == Qt::CaseSensitive)
return ucstrcmp(lhs.begin(), lhs.size(), rhs.begin(), rhs.size());
@@ -1192,12 +1187,12 @@ static int qt_compare_strings(QStringView lhs, QLatin1String rhs, Qt::CaseSensit
return ucstricmp(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
-static int qt_compare_strings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+static int qt_compare_strings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs) noexcept
{
return -qt_compare_strings(rhs, lhs, cs);
}
-static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) noexcept
{
if (cs == Qt::CaseInsensitive)
return qstrnicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size());
@@ -1222,7 +1217,7 @@ static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSens
of the characters and is very fast, but is not what a human would expect.
Consider sorting user-visible strings with QString::localeAwareCompare().
*/
-int QtPrivate::compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+int QtPrivate::compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) noexcept
{
return qt_compare_strings(lhs, rhs, cs);
}
@@ -1242,7 +1237,7 @@ int QtPrivate::compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitiv
of the characters and is very fast, but is not what a human would expect.
Consider sorting user-visible strings with QString::localeAwareCompare().
*/
-int QtPrivate::compareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+int QtPrivate::compareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs) noexcept
{
return qt_compare_strings(lhs, rhs, cs);
}
@@ -1262,7 +1257,7 @@ int QtPrivate::compareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensit
of the characters and is very fast, but is not what a human would expect.
Consider sorting user-visible strings with QString::localeAwareCompare().
*/
-int QtPrivate::compareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+int QtPrivate::compareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs) noexcept
{
return qt_compare_strings(lhs, rhs, cs);
}
@@ -1282,47 +1277,14 @@ int QtPrivate::compareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensit
of the characters and is very fast, but is not what a human would expect.
Consider sorting user-visible strings with QString::localeAwareCompare().
*/
-int QtPrivate::compareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+int QtPrivate::compareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) noexcept
{
return qt_compare_strings(lhs, rhs, cs);
}
-/*!
- \internal
-
- Returns the index position of the first occurrence of the
- character \a ch in the string given by \a str and \a len,
- searching forward from index
- position \a from. Returns -1 if \a ch could not be found.
-*/
-static int findChar(const QChar *str, int len, QChar ch, int from,
- Qt::CaseSensitivity cs)
-{
- const ushort *s = (const ushort *)str;
- ushort c = ch.unicode();
- if (from < 0)
- from = qMax(from + len, 0);
- if (from < len) {
- const ushort *n = s + from;
- const ushort *e = s + len;
- if (cs == Qt::CaseSensitive) {
- n = QtPrivate::qustrchr(QStringView(n, e), c);
- if (n != e)
- return n - s;
- } else {
- c = foldCase(c);
- --n;
- while (++n != e)
- if (foldCase(*n) == c)
- return n - s;
- }
- }
- return -1;
-}
-
#define REHASH(a) \
- if (sl_minus_1 < sizeof(uint) * CHAR_BIT) \
- hashHaystack -= uint(a) << sl_minus_1; \
+ if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
+ hashHaystack -= std::size_t(a) << sl_minus_1; \
hashHaystack <<= 1
inline bool qIsUpper(char ch)
@@ -1472,7 +1434,7 @@ const QString::Null QString::null = { };
In all of the QString functions that take \c{const char *}
parameters, the \c{const char *} is interpreted as a classic
C-style '\\0'-terminated string encoded in UTF-8. It is legal for
- the \c{const char *} parameter to be 0.
+ the \c{const char *} parameter to be \nullptr.
You can also provide string data as an array of \l{QChar}s:
@@ -1556,7 +1518,7 @@ const QString::Null QString::null = { };
functions. The former searches forward starting from a given index
position, the latter searches backward. Both return the index
position of the character or substring if they find it; otherwise,
- they return -1. For example, here's a typical loop that finds all
+ they return -1. For example, here is a typical loop that finds all
occurrences of a particular substring:
\snippet qstring/main.cpp 6
@@ -1685,10 +1647,9 @@ const QString::Null QString::null = { };
\snippet qstring/main.cpp 8
All functions except isNull() treat null strings the same as empty
- strings. For example, toUtf8().constData() returns a pointer to a
- '\\0' character for a null string (\e not a null pointer), and
- QString() compares equal to QString(""). We recommend that you
- always use the isEmpty() function and avoid isNull().
+ strings. For example, toUtf8().constData() returns a valid pointer
+ (\e not nullptr) to a '\\0' character for a null string. We
+ recommend that you always use the isEmpty() function and avoid isNull().
\section1 Argument Formats
@@ -2045,7 +2006,7 @@ const QString::Null QString::null = { };
the size of wchar. If wchar is 4 bytes, the \a string is interpreted as UCS-4,
if wchar is 2 bytes it is interpreted as UTF-16.
- If \a size is -1 (default), the \a string has to be 0 terminated.
+ If \a size is -1 (default), the \a string has to be \\0'-terminated.
\sa fromUtf16(), fromLatin1(), fromLocal8Bit(), fromUtf8(), fromUcs4(), fromStdWString()
*/
@@ -2090,7 +2051,7 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
\note This function does not append a null character to the array.
- \sa utf16(), toUcs4(), toLatin1(), toUtf8(), toLocal8Bit(), toStdWString()
+ \sa utf16(), toUcs4(), toLatin1(), toUtf8(), toLocal8Bit(), toStdWString(), QStringView::toWCharArray()
*/
/*! \fn QString::QString(const QString &other)
@@ -2111,7 +2072,7 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
If \a unicode is 0, a null string is constructed.
- If \a size is negative, \a unicode is assumed to point to a nul-terminated
+ If \a size is negative, \a unicode is assumed to point to a \\0'-terminated
array and its length is determined dynamically. The terminating
nul-character is not considered part of the string.
@@ -2411,7 +2372,7 @@ void QString::expand(int i)
string.
*/
-QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
+QString &QString::operator=(const QString &other) noexcept
{
other.d->ref.ref();
if (!d->ref.deref())
@@ -3084,7 +3045,7 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar
{
// Copy after if it lies inside our own d->data() area (which we could
// possibly invalidate via a realloc or modify by replacement).
- QChar *afterBuffer = 0;
+ QChar *afterBuffer = nullptr;
if (pointsIntoRange(after, d->data(), d->size)) // Use copy in place of vulnerable original:
after = afterBuffer = textCopy(after, alen);
@@ -3169,7 +3130,7 @@ QString &QString::replace(const QChar *before, int blen,
return *this;
QStringMatcher matcher(before, blen, cs);
- QChar *beforeBuffer = 0, *afterBuffer = 0;
+ QChar *beforeBuffer = nullptr, *afterBuffer = nullptr;
int index = 0;
while (1) {
@@ -3397,7 +3358,7 @@ QString &QString::replace(QChar c, QLatin1String after, Qt::CaseSensitivity cs)
expect. Consider sorting user-interface strings with
localeAwareCompare().
*/
-bool operator==(const QString &s1, const QString &s2) Q_DECL_NOTHROW
+bool operator==(const QString &s1, const QString &s2) noexcept
{
if (s1.d->size != s2.d->size)
return false;
@@ -3410,7 +3371,7 @@ bool operator==(const QString &s1, const QString &s2) Q_DECL_NOTHROW
Returns \c true if this string is equal to \a other; otherwise
returns \c false.
*/
-bool QString::operator==(QLatin1String other) const Q_DECL_NOTHROW
+bool QString::operator==(QLatin1String other) const noexcept
{
if (d->size != other.size())
return false;
@@ -3462,7 +3423,7 @@ bool QString::operator==(QLatin1String other) const Q_DECL_NOTHROW
expect. Consider sorting user-interface strings using the
QString::localeAwareCompare() function.
*/
-bool operator<(const QString &s1, const QString &s2) Q_DECL_NOTHROW
+bool operator<(const QString &s1, const QString &s2) noexcept
{
return qt_compare_strings(s1, s2, Qt::CaseSensitive) < 0;
}
@@ -3473,7 +3434,7 @@ bool operator<(const QString &s1, const QString &s2) Q_DECL_NOTHROW
Returns \c true if this string is lexically less than the parameter
string called \a other; otherwise returns \c false.
*/
-bool QString::operator<(QLatin1String other) const Q_DECL_NOTHROW
+bool QString::operator<(QLatin1String other) const noexcept
{
return qt_compare_strings(*this, other, Qt::CaseSensitive) < 0;
}
@@ -3582,7 +3543,7 @@ bool QString::operator<(QLatin1String other) const Q_DECL_NOTHROW
Returns \c true if this string is lexically greater than the parameter
string \a other; otherwise returns \c false.
*/
-bool QString::operator>(QLatin1String other) const Q_DECL_NOTHROW
+bool QString::operator>(QLatin1String other) const noexcept
{
return qt_compare_strings(*this, other, Qt::CaseSensitive) > 0;
}
@@ -3720,6 +3681,7 @@ bool QString::operator>(QLatin1String other) const Q_DECL_NOTHROW
\sa QT_NO_CAST_FROM_ASCII
*/
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns the index position of the first occurrence of the string \a
str in this string, searching forward from index position \a
@@ -3739,8 +3701,28 @@ bool QString::operator>(QLatin1String other) const Q_DECL_NOTHROW
*/
int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
{
- return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs));
}
+#endif // QT_STRINGVIEW_LEVEL < 2
+
+/*!
+ \fn int QString::indexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
+ \since 5.14
+ \overload indexOf()
+
+ Returns the index position of the first occurrence of the string view \a str
+ in this string, searching forward from index position \a from.
+ Returns -1 if \a str is not found.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ If \a from is -1, the search starts at the last character; if it is
+ -2, at the next to last character and so on.
+
+ \sa QStringView::indexOf(), lastIndexOf(), contains(), count()
+*/
/*!
\since 4.5
@@ -3763,85 +3745,8 @@ int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
int QString::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
{
- return qt_find_latin1_string(unicode(), size(), str, from, cs);
-}
-
-int qFindString(
- const QChar *haystack0, int haystackLen, int from,
- const QChar *needle0, int needleLen, Qt::CaseSensitivity cs)
-{
- const int l = haystackLen;
- const int sl = needleLen;
- if (from < 0)
- from += l;
- if (uint(sl + from) > (uint)l)
- return -1;
- if (!sl)
- return from;
- if (!l)
- return -1;
-
- if (sl == 1)
- return findChar(haystack0, haystackLen, needle0[0], from, cs);
-
- /*
- We use the Boyer-Moore algorithm in cases where the overhead
- for the skip table should pay off, otherwise we use a simple
- hash function.
- */
- if (l > 500 && sl > 5)
- return qFindStringBoyerMoore(haystack0, haystackLen, from,
- needle0, needleLen, cs);
-
- auto sv = [sl](const ushort *v) { return QStringView(v, sl); };
- /*
- We use some hashing for efficiency's sake. Instead of
- comparing strings, we compare the hash value of str with that
- of a part of this QString. Only if that matches, we call
- qt_string_compare().
- */
- const ushort *needle = (const ushort *)needle0;
- const ushort *haystack = (const ushort *)haystack0 + from;
- const ushort *end = (const ushort *)haystack0 + (l-sl);
- const uint sl_minus_1 = sl - 1;
- uint hashNeedle = 0, hashHaystack = 0;
- int idx;
-
- if (cs == Qt::CaseSensitive) {
- for (idx = 0; idx < sl; ++idx) {
- hashNeedle = ((hashNeedle<<1) + needle[idx]);
- hashHaystack = ((hashHaystack<<1) + haystack[idx]);
- }
- hashHaystack -= haystack[sl_minus_1];
-
- while (haystack <= end) {
- hashHaystack += haystack[sl_minus_1];
- if (hashHaystack == hashNeedle
- && qt_compare_strings(sv(needle), sv(haystack), Qt::CaseSensitive) == 0)
- return haystack - (const ushort *)haystack0;
-
- REHASH(*haystack);
- ++haystack;
- }
- } else {
- const ushort *haystack_start = (const ushort *)haystack0;
- for (idx = 0; idx < sl; ++idx) {
- hashNeedle = (hashNeedle<<1) + foldCase(needle + idx, needle);
- hashHaystack = (hashHaystack<<1) + foldCase(haystack + idx, haystack_start);
- }
- hashHaystack -= foldCase(haystack + sl_minus_1, haystack_start);
-
- while (haystack <= end) {
- hashHaystack += foldCase(haystack + sl_minus_1, haystack_start);
- if (hashHaystack == hashNeedle
- && qt_compare_strings(sv(needle), sv(haystack), Qt::CaseInsensitive) == 0)
- return haystack - (const ushort *)haystack0;
-
- REHASH(foldCase(haystack, haystack_start));
- ++haystack;
- }
- }
- return -1;
+ // ### Qt6: qsize
+ return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs));
}
/*!
@@ -3853,9 +3758,11 @@ int qFindString(
*/
int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
{
- return findChar(unicode(), length(), ch, from, cs);
+ // ### Qt6: qsize
+ return int(qFindChar(QStringView(unicode(), length()), ch, from, cs));
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\since 4.8
@@ -3870,74 +3777,8 @@ int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
*/
int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
{
- return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs);
-}
-
-static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *needle, int sl, Qt::CaseSensitivity cs)
-{
- /*
- See indexOf() for explanations.
- */
-
- auto sv = [sl](const ushort *v) { return QStringView(v, sl); };
-
- const ushort *end = haystack;
- haystack += from;
- const uint sl_minus_1 = sl - 1;
- const ushort *n = needle+sl_minus_1;
- const ushort *h = haystack+sl_minus_1;
- uint hashNeedle = 0, hashHaystack = 0;
- int idx;
-
- if (cs == Qt::CaseSensitive) {
- for (idx = 0; idx < sl; ++idx) {
- hashNeedle = ((hashNeedle<<1) + *(n-idx));
- hashHaystack = ((hashHaystack<<1) + *(h-idx));
- }
- hashHaystack -= *haystack;
-
- while (haystack >= end) {
- hashHaystack += *haystack;
- if (hashHaystack == hashNeedle
- && qt_compare_strings(sv(needle), sv(haystack), Qt::CaseSensitive) == 0)
- return haystack - end;
- --haystack;
- REHASH(haystack[sl]);
- }
- } else {
- for (idx = 0; idx < sl; ++idx) {
- hashNeedle = ((hashNeedle<<1) + foldCase(n-idx, needle));
- hashHaystack = ((hashHaystack<<1) + foldCase(h-idx, end));
- }
- hashHaystack -= foldCase(haystack, end);
-
- while (haystack >= end) {
- hashHaystack += foldCase(haystack, end);
- if (hashHaystack == hashNeedle
- && qt_compare_strings(sv(haystack), sv(needle), Qt::CaseInsensitive) == 0)
- return haystack - end;
- --haystack;
- REHASH(foldCase(haystack + sl, end));
- }
- }
- return -1;
-}
-
-static inline int lastIndexOfHelper(
- const QStringRef &haystack, int from, const QStringRef &needle, Qt::CaseSensitivity cs)
-{
- return lastIndexOfHelper(reinterpret_cast<const ushort*>(haystack.unicode()), from,
- reinterpret_cast<const ushort*>(needle.unicode()), needle.size(), cs);
-}
-
-static inline int lastIndexOfHelper(
- const QStringRef &haystack, int from, QLatin1String needle, Qt::CaseSensitivity cs)
-{
- const int size = needle.size();
- QVarLengthArray<ushort> s(size);
- qt_from_latin1(s.data(), needle.latin1(), size);
- return lastIndexOfHelper(reinterpret_cast<const ushort*>(haystack.unicode()), from,
- s.data(), size, cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs));
}
/*!
@@ -3958,9 +3799,12 @@ static inline int lastIndexOfHelper(
*/
int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
{
- return QStringRef(this).lastIndexOf(QStringRef(&str), from, cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::lastIndexOf(*this, from, str, cs));
}
+#endif // QT_STRINGVIEW_LEVEL < 2
+
/*!
\since 4.5
\overload lastIndexOf()
@@ -3982,7 +3826,8 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c
*/
int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
{
- return QStringRef(this).lastIndexOf(str, from, cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::lastIndexOf(*this, from, str, cs));
}
/*!
@@ -3993,9 +3838,11 @@ int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) co
*/
int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
{
- return qt_last_index_of(unicode(), size(), ch, from, cs);
+ // ### Qt6: qsize
+ return int(qLastIndexOf(*this, ch, from, cs));
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\since 4.8
\overload lastIndexOf()
@@ -4013,8 +3860,27 @@ int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
*/
int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
{
- return QStringRef(this).lastIndexOf(str, from, cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::lastIndexOf(*this, from, str, cs));
}
+#endif // QT_STRINGVIEW_LEVEL < 2
+
+/*!
+ \fn int QString::lastIndexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
+ \since 5.14
+ \overload lastIndexOf()
+
+ Returns the index position of the last occurrence of the string view \a
+ str in this string, searching backward from index position \a
+ from. If \a from is -1 (default), the search starts at the last
+ character; if \a from is -2, at the next to last character and so
+ on. Returns -1 if \a str is not found.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \sa indexOf(), contains(), count()
+*/
#if !(defined(QT_NO_REGEXP) && !QT_CONFIG(regularexpression))
@@ -4326,7 +4192,8 @@ QString &QString::replace(const QRegularExpression &re, const QString &after)
int QString::count(const QString &str, Qt::CaseSensitivity cs) const
{
- return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
+ // ### Qt6: qsize
+ return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
}
/*!
@@ -4342,8 +4209,9 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const
int QString::count(QChar ch, Qt::CaseSensitivity cs) const
{
- return qt_string_count(unicode(), size(), ch, cs);
- }
+ // ### Qt6: qsize
+ return int(qt_string_count(QStringView(unicode(), size()), ch, cs));
+}
/*!
\since 4.8
@@ -4358,10 +4226,11 @@ int QString::count(QChar ch, Qt::CaseSensitivity cs) const
*/
int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const
{
- return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
+ // ### Qt6: qsize
+ return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
}
-
+#if QT_STRINGVIEW_LEVEL < 2
/*! \fn bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
Returns \c true if this string contains an occurrence of the string
@@ -4375,6 +4244,7 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const
\sa indexOf(), count()
*/
+#endif // QT_STRINGVIEW_LEVEL < 2
/*! \fn bool QString::contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\since 5.3
@@ -4393,6 +4263,7 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const
character \a ch; otherwise returns \c false.
*/
+#if QT_STRINGVIEW_LEVEL < 2
/*! \fn bool QString::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\since 4.8
@@ -4404,6 +4275,20 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const
\sa indexOf(), count()
*/
+#endif // QT_STRINGVIEW_LEVEL < 2
+
+/*! \fn bool QString::contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 5.14
+ \overload contains()
+
+ Returns \c true if this string contains an occurrence of the string view
+ \a str; otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
+
+ \sa indexOf(), count()
+*/
/*! \fn bool QString::contains(const QRegExp &rx) const
@@ -4553,7 +4438,7 @@ int QString::indexOf(const QRegularExpression& re, int from) const
expression \a re in the string, searching forward from index
position \a from. Returns -1 if \a re didn't match anywhere.
- If the match is successful and \a rmatch is not a null pointer, it also
+ If the match is successful and \a rmatch is not \nullptr, it also
writes the results of the match into the QRegularExpressionMatch object
pointed to by \a rmatch.
@@ -4572,7 +4457,7 @@ int QString::indexOf(const QRegularExpression &re, int from, QRegularExpressionM
if (match.hasMatch()) {
const int ret = match.capturedStart();
if (rmatch)
- *rmatch = qMove(match);
+ *rmatch = std::move(match);
return ret;
}
@@ -4604,7 +4489,7 @@ int QString::lastIndexOf(const QRegularExpression &re, int from) const
expression \a re in the string, which starts before the index
position \a from. Returns -1 if \a re didn't match anywhere.
- If the match is successful and \a rmatch is not a null pointer, it also
+ If the match is successful and \a rmatch is not \nullptr, it also
writes the results of the match into the QRegularExpressionMatch object
pointed to by \a rmatch.
@@ -4628,7 +4513,7 @@ int QString::lastIndexOf(const QRegularExpression &re, int from, QRegularExpress
if (start < endpos) {
lastIndex = start;
if (rmatch)
- *rmatch = qMove(match);
+ *rmatch = std::move(match);
} else {
break;
}
@@ -4655,14 +4540,14 @@ bool QString::contains(const QRegularExpression &re) const
Returns \c true if the regular expression \a re matches somewhere in this
string; otherwise returns \c false.
- If the match is successful and \a match is not a null pointer, it also
+ If the match is successful and \a rmatch is not \nullptr, it also
writes the results of the match into the QRegularExpressionMatch object
- pointed to by \a match.
+ pointed to by \a rmatch.
\sa QRegularExpression::match()
*/
-bool QString::contains(const QRegularExpression &re, QRegularExpressionMatch *match) const
+bool QString::contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch) const
{
if (!re.isValid()) {
qWarning("QString::contains: invalid QRegularExpression object");
@@ -4670,8 +4555,8 @@ bool QString::contains(const QRegularExpression &re, QRegularExpressionMatch *ma
}
QRegularExpressionMatch m = re.match(*this);
bool hasMatch = m.hasMatch();
- if (hasMatch && match)
- *match = qMove(m);
+ if (hasMatch && rmatch)
+ *rmatch = std::move(m);
return hasMatch;
}
@@ -4831,7 +4716,7 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
class qt_section_chunk {
public:
qt_section_chunk() {}
- qt_section_chunk(int l, QStringRef s) : length(l), string(qMove(s)) {}
+ qt_section_chunk(int l, QStringRef s) : length(l), string(std::move(s)) {}
int length;
QStringRef string;
};
@@ -5452,7 +5337,7 @@ static QVector<uint> qt_convert_to_ucs4(QStringView string);
this string is replaced by the Unicode's replacement character
(QChar::ReplacementCharacter, which corresponds to \c{U+FFFD}).
- The returned vector is not NUL terminated.
+ The returned vector is not \\0'-terminated.
\sa fromUtf8(), toUtf8(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray()
*/
@@ -5484,7 +5369,7 @@ static QVector<uint> qt_convert_to_ucs4(QStringView string)
this string is replaced by the Unicode's replacement character
(QChar::ReplacementCharacter, which corresponds to \c{U+FFFD}).
- The returned vector is not NUL terminated.
+ The returned vector is not \\0'-terminated.
\sa QString::toUcs4(), QStringView::toUcs4(), QtPrivate::convertToLatin1(),
QtPrivate::convertToLocal8Bit(), QtPrivate::convertToUtf8()
@@ -5642,8 +5527,7 @@ QString QString::fromUtf8_helper(const char *str, int size)
Returns a QString initialized with the first \a size characters
of the Unicode string \a unicode (ISO-10646-UTF-16 encoded).
- If \a size is -1 (default), \a unicode must be terminated
- with a 0.
+ If \a size is -1 (default), \a unicode must be \\0'-terminated.
This function checks for a Byte Order Mark (BOM). If it is missing,
host byte order is assumed.
@@ -5664,7 +5548,7 @@ QString QString::fromUtf16(const ushort *unicode, int size)
while (unicode[size] != 0)
++size;
}
- return QUtf16::convertToUnicode((const char *)unicode, size*2, 0);
+ return QUtf16::convertToUnicode((const char *)unicode, size*2, nullptr);
}
/*!
@@ -5674,8 +5558,7 @@ QString QString::fromUtf16(const ushort *unicode, int size)
Returns a QString initialized with the first \a size characters
of the Unicode string \a str (ISO-10646-UTF-16 encoded).
- If \a size is -1 (default), \a str must be terminated
- with a 0.
+ If \a size is -1 (default), \a str must be \\0'-terminated.
This function checks for a Byte Order Mark (BOM). If it is missing,
host byte order is assumed.
@@ -5695,8 +5578,7 @@ QString QString::fromUtf16(const ushort *unicode, int size)
Returns a QString initialized with the first \a size characters
of the Unicode string \a str (ISO-10646-UCS-4 encoded).
- If \a size is -1 (default), \a str must be terminated
- with a 0.
+ If \a size is -1 (default), \a str must be \\0'-terminated.
\sa toUcs4(), fromUtf16(), utf16(), setUtf16(), fromWCharArray(), fromStdU32String()
*/
@@ -5707,8 +5589,7 @@ QString QString::fromUtf16(const ushort *unicode, int size)
Returns a QString initialized with the first \a size characters
of the Unicode string \a unicode (ISO-10646-UCS-4 encoded).
- If \a size is -1 (default), \a unicode must be terminated
- with a 0.
+ If \a size is -1 (default), \a unicode must be \\0'-terminated.
\sa toUcs4(), fromUtf16(), utf16(), setUtf16(), fromWCharArray(), fromStdU32String()
*/
@@ -5721,7 +5602,7 @@ QString QString::fromUcs4(const uint *unicode, int size)
while (unicode[size] != 0)
++size;
}
- return QUtf32::convertToUnicode((const char *)unicode, size*4, 0);
+ return QUtf32::convertToUnicode((const char *)unicode, size*4, nullptr);
}
@@ -5786,7 +5667,7 @@ QString QString::simplified_helper(QString &str)
namespace {
template <typename StringView>
- StringView qt_trimmed(StringView s) Q_DECL_NOTHROW
+ StringView qt_trimmed(StringView s) noexcept
{
auto begin = s.begin();
auto end = s.end();
@@ -5810,12 +5691,12 @@ namespace {
\sa QString::trimmed(), QStringView::trimmed(), QLatin1String::trimmed()
*/
-QStringView QtPrivate::trimmed(QStringView s) Q_DECL_NOTHROW
+QStringView QtPrivate::trimmed(QStringView s) noexcept
{
return qt_trimmed(s);
}
-QLatin1String QtPrivate::trimmed(QLatin1String s) Q_DECL_NOTHROW
+QLatin1String QtPrivate::trimmed(QLatin1String s) noexcept
{
return qt_trimmed(s);
}
@@ -5874,6 +5755,15 @@ QString QString::trimmed_helper(QString &str)
were a QChar &. If you assign to it, the assignment will apply to
the character in the QString from which you got the reference.
+ \note Before Qt 5.14 it was possible to use this operator to access
+ a character at an out-of-bounds position in the string, and
+ then assign to such a position, causing the string to be
+ automatically resized. Furthermore, assigning a value to the
+ returned QCharRef would cause a detach of the string, even if the
+ string has been copied in the meanwhile (and the QCharRef kept
+ alive while the copy was taken). These behaviors are deprecated,
+ and will be changed in a future version of Qt.
+
\sa at()
*/
@@ -6353,7 +6243,7 @@ QString& QString::fill(QChar ch, int size)
Same as compare(*this, \a other, \a cs).
*/
-int QString::compare(const QString &other, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+int QString::compare(const QString &other, Qt::CaseSensitivity cs) const noexcept
{
return qt_compare_strings(*this, other, cs);
}
@@ -6364,7 +6254,7 @@ int QString::compare(const QString &other, Qt::CaseSensitivity cs) const Q_DECL_
\since 4.5
*/
int QString::compare_helper(const QChar *data1, int length1, const QChar *data2, int length2,
- Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+ Qt::CaseSensitivity cs) noexcept
{
Q_ASSERT(length1 >= 0);
Q_ASSERT(length2 >= 0);
@@ -6379,7 +6269,7 @@ int QString::compare_helper(const QChar *data1, int length1, const QChar *data2,
Same as compare(*this, \a other, \a cs).
*/
-int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const noexcept
{
return qt_compare_strings(*this, other, cs);
}
@@ -6425,7 +6315,7 @@ int QString::compare_helper(const QChar *data1, int length1, const char *data2,
\since 4.5
*/
int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2,
- Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+ Qt::CaseSensitivity cs) noexcept
{
Q_ASSERT(length1 >= 0);
Q_ASSERT(data1 || length1 == 0);
@@ -6718,7 +6608,7 @@ namespace QUnicodeTables {
this function requires to be a valid, empty string) and \c{s} contains the
only copy of the string, without reallocation (thus, \a it is still valid).
- There's one pathological case left: when the in-place conversion needs to
+ There is one pathological case left: when the in-place conversion needs to
reallocate memory to grow the buffer. In that case, we need to adjust the \a
it pointer.
*/
@@ -6727,7 +6617,7 @@ Q_NEVER_INLINE
static QString detachAndConvertCase(T &str, QStringIterator it)
{
Q_ASSERT(!str.isEmpty());
- QString s = qMove(str); // will copy if T is const QString
+ QString s = std::move(str); // will copy if T is const QString
QChar *pp = s.begin() + it.index(); // will detach if necessary
do {
@@ -6785,7 +6675,7 @@ static QString convertCase(T &str)
return detachAndConvertCase<Traits>(str, it);
}
}
- return qMove(str);
+ return std::move(str);
}
} // namespace QUnicodeTables
@@ -6839,6 +6729,7 @@ QString QString::toUpper_helper(QString &str)
return QUnicodeTables::convertCase<QUnicodeTables::UppercaseTraits>(str);
}
+#if QT_DEPRECATED_SINCE(5, 14)
/*!
\obsolete
@@ -6852,6 +6743,7 @@ QString &QString::sprintf(const char *cformat, ...)
va_end(ap);
return *this;
}
+#endif
// ### Qt 6: Consider whether this function shouldn't be removed See task 202871.
/*!
@@ -6876,7 +6768,7 @@ QString &QString::sprintf(const char *cformat, ...)
\warning We do not recommend using QString::asprintf() in new Qt
code. Instead, consider using QTextStream or arg(), both of
which support Unicode strings seamlessly and are type-safe.
- Here's an example that uses QTextStream:
+ Here is an example that uses QTextStream:
\snippet qstring/main.cpp 64
@@ -6897,6 +6789,7 @@ QString QString::asprintf(const char *cformat, ...)
return s;
}
+#if QT_DEPRECATED_SINCE(5, 14)
/*!
\obsolete
@@ -6906,6 +6799,7 @@ QString &QString::vsprintf(const char *cformat, va_list ap)
{
return *this = vasprintf(cformat, ap);
}
+#endif
static void append_utf8(QString &qs, const char *cs, int len)
{
@@ -6915,7 +6809,7 @@ static void append_utf8(QString &qs, const char *cs, int len)
qs.resize(newEnd - qs.constData());
}
-static uint parse_flag_characters(const char * &c) Q_DECL_NOTHROW
+static uint parse_flag_characters(const char * &c) noexcept
{
uint flags = QLocaleData::ZeroPadExponent;
while (true) {
@@ -6952,7 +6846,7 @@ static int parse_field_width(const char * &c)
enum LengthMod { lm_none, lm_hh, lm_h, lm_l, lm_ll, lm_L, lm_j, lm_z, lm_t };
-static inline bool can_consume(const char * &c, char ch) Q_DECL_NOTHROW
+static inline bool can_consume(const char * &c, char ch) noexcept
{
if (*c == ch) {
++c;
@@ -6961,7 +6855,7 @@ static inline bool can_consume(const char * &c, char ch) Q_DECL_NOTHROW
return false;
}
-static LengthMod parse_length_modifier(const char * &c) Q_DECL_NOTHROW
+static LengthMod parse_length_modifier(const char * &c) noexcept
{
switch (*c++) {
case 'h': return can_consume(c, 'h') ? lm_hh : lm_h;
@@ -7237,7 +7131,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -7279,7 +7173,7 @@ qlonglong QString::toIntegral_helper(const QChar *data, int len, bool *ok, int b
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -7323,7 +7217,7 @@ qulonglong QString::toIntegral_helper(const QChar *data, uint len, bool *ok, int
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -7354,7 +7248,7 @@ long QString::toLong(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -7384,7 +7278,7 @@ ulong QString::toULong(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -7413,7 +7307,7 @@ int QString::toInt(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -7442,7 +7336,7 @@ uint QString::toUInt(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -7471,7 +7365,7 @@ short QString::toShort(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -7502,7 +7396,7 @@ ushort QString::toUShort(bool *ok, int base) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for other reasons (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\snippet qstring/main.cpp 66
@@ -7541,7 +7435,7 @@ double QString::toDouble(bool *ok) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for other reasons (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
\warning The QString content may only contain valid numerical characters
@@ -7786,10 +7680,10 @@ static ResultList splitString(const StringSource &source, const QChar *sep,
QString::SplitBehavior behavior, Qt::CaseSensitivity cs, const int separatorSize)
{
ResultList list;
- int start = 0;
- int end;
- int extra = 0;
- while ((end = qFindString(source.constData(), source.size(), start + extra, sep, separatorSize, cs)) != -1) {
+ typename StringSource::size_type start = 0;
+ typename StringSource::size_type end;
+ typename StringSource::size_type extra = 0;
+ while ((end = QtPrivate::findString(QStringView(source.constData(), source.size()), start + extra, QStringView(sep, separatorSize), cs)) != -1) {
if (start != end || behavior == QString::KeepEmptyParts)
list.append(source.mid(start, end - start));
start = end + separatorSize;
@@ -7843,7 +7737,7 @@ QStringList QString::split(const QString &sep, SplitBehavior behavior, Qt::CaseS
the result.
\note All references are valid as long this string is alive. Destroying this
- string will cause all references be dangling pointers.
+ string will cause all references to be dangling pointers.
\since 5.4
\sa QStringRef split()
@@ -7877,7 +7771,7 @@ QVector<QStringRef> QString::splitRef(QChar sep, SplitBehavior behavior, Qt::Cas
the result.
\note All references are valid as long this string is alive. Destroying this
- string will cause all references be dangling pointers.
+ string will cause all references to be dangling pointers.
\since 5.4
*/
@@ -7926,17 +7820,17 @@ static ResultList splitString(const QString &source, MidMethod mid, const QRegEx
does not match anywhere in the string, split() returns a
single-element list containing this string.
- Here's an example where we extract the words in a sentence
+ Here is an example where we extract the words in a sentence
using one or more whitespace characters as the separator:
\snippet qstring/main.cpp 59
- Here's a similar example, but this time we use any sequence of
+ Here is a similar example, but this time we use any sequence of
non-word characters as the separator:
\snippet qstring/main.cpp 60
- Here's a third example where we use a zero-length assertion,
+ Here is a third example where we use a zero-length assertion,
\b{\\b} (word boundary), to split the string into an
alternating sequence of non-word and word tokens:
@@ -7959,7 +7853,7 @@ QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
single-element vector containing this string reference.
\note All references are valid as long this string is alive. Destroying this
- string will cause all references be dangling pointers.
+ string will cause all references to be dangling pointers.
\sa QStringRef split()
*/
@@ -8008,17 +7902,17 @@ static ResultList splitString(const QString &source, MidMethod mid, const QRegul
does not match anywhere in the string, split() returns a
single-element list containing this string.
- Here's an example where we extract the words in a sentence
+ Here is an example where we extract the words in a sentence
using one or more whitespace characters as the separator:
\snippet qstring/main.cpp 90
- Here's a similar example, but this time we use any sequence of
+ Here is a similar example, but this time we use any sequence of
non-word characters as the separator:
\snippet qstring/main.cpp 91
- Here's a third example where we use a zero-length assertion,
+ Here is a third example where we use a zero-length assertion,
\b{\\b} (word boundary), to split the string into an
alternating sequence of non-word and word tokens:
@@ -8041,7 +7935,7 @@ QStringList QString::split(const QRegularExpression &re, SplitBehavior behavior)
single-element vector containing this string reference.
\note All references are valid as long this string is alive. Destroying this
- string will cause all references be dangling pointers.
+ string will cause all references to be dangling pointers.
\sa split() QStringRef
*/
@@ -8123,7 +8017,7 @@ void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::
version = QChar::currentUnicodeVersion();
} else if (int(version) <= NormalizationCorrectionsVersionMax) {
const QString &s = *data;
- QChar *d = 0;
+ QChar *d = nullptr;
for (int i = 0; i < NumNormalizationCorrections; ++i) {
const NormalizationCorrection &n = uc_normalization_corrections[i];
if (n.version > version) {
@@ -8860,19 +8754,23 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha
return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar);
}
-static int getEscape(const QChar *uc, int *pos, int len, int maxNumber = 999)
+static inline ushort to_unicode(const QChar c) { return c.unicode(); }
+static inline ushort to_unicode(const char c) { return QLatin1Char{c}.unicode(); }
+
+template <typename Char>
+static int getEscape(const Char *uc, qsizetype *pos, qsizetype len, int maxNumber = 999)
{
int i = *pos;
++i;
if (i < len && uc[i] == QLatin1Char('L'))
++i;
if (i < len) {
- int escape = uc[i].unicode() - '0';
+ int escape = to_unicode(uc[i]) - '0';
if (uint(escape) >= 10U)
return -1;
++i;
while (i < len) {
- int digit = uc[i].unicode() - '0';
+ int digit = to_unicode(uc[i]) - '0';
if (uint(digit) >= 10U)
break;
escape = (escape * 10) + digit;
@@ -8923,18 +8821,23 @@ static int getEscape(const QChar *uc, int *pos, int len, int maxNumber = 999)
namespace {
struct Part
{
- Part() : stringRef(), number(0) {}
- Part(const QString &s, int pos, int len, int num = -1) Q_DECL_NOTHROW
- : stringRef(&s, pos, len), number(num) {}
+ Part() = default; // for QVarLengthArray; do not use
+ Q_DECL_CONSTEXPR Part(QStringView s, int num = -1)
+ : tag{QtPrivate::ArgBase::U16}, number{num}, data{s.utf16()}, size{s.size()} {}
+ Q_DECL_CONSTEXPR Part(QLatin1String s, int num = -1)
+ : tag{QtPrivate::ArgBase::L1}, number{num}, data{s.data()}, size{s.size()} {}
+
+ void reset(QStringView s) noexcept { *this = {s, number}; }
+ void reset(QLatin1String s) noexcept { *this = {s, number}; }
- QStringRef stringRef;
+ QtPrivate::ArgBase::Tag tag;
int number;
+ const void *data;
+ qsizetype size;
};
} // unnamed namespace
-template <>
-class QTypeInfo<Part> : public QTypeInfoMerger<Part, QStringRef, int> {}; // Q_DECLARE_METATYPE
-
+Q_DECLARE_TYPEINFO(Part, Q_PRIMITIVE_TYPE);
namespace {
@@ -8943,24 +8846,25 @@ enum { ExpectedParts = 32 };
typedef QVarLengthArray<Part, ExpectedParts> ParseResult;
typedef QVarLengthArray<int, ExpectedParts/2> ArgIndexToPlaceholderMap;
-static ParseResult parseMultiArgFormatString(const QString &s)
+template <typename StringView>
+static ParseResult parseMultiArgFormatString(StringView s)
{
ParseResult result;
- const QChar *uc = s.constData();
- const int len = s.size();
- const int end = len - 1;
- int i = 0;
- int last = 0;
+ const auto uc = s.data();
+ const auto len = s.size();
+ const auto end = len - 1;
+ qsizetype i = 0;
+ qsizetype last = 0;
while (i < end) {
if (uc[i] == QLatin1Char('%')) {
- int percent = i;
+ qsizetype percent = i;
int number = getEscape(uc, &i, len);
if (number != -1) {
if (last != percent)
- result.push_back(Part(s, last, percent - last)); // literal text (incl. failed placeholders)
- result.push_back(Part(s, percent, i - percent, number)); // parsed placeholder
+ result.push_back(Part{s.mid(last, percent - last)}); // literal text (incl. failed placeholders)
+ result.push_back(Part{s.mid(percent, i - percent), number}); // parsed placeholder
last = i;
continue;
}
@@ -8969,7 +8873,7 @@ static ParseResult parseMultiArgFormatString(const QString &s)
}
if (last < len)
- result.push_back(Part(s, last, len - last)); // trailing literal text
+ result.push_back(Part{s.mid(last, len - last)}); // trailing literal text
return result;
}
@@ -8978,9 +8882,9 @@ static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(const ParseResult &
{
ArgIndexToPlaceholderMap result;
- for (ParseResult::const_iterator it = parts.begin(), end = parts.end(); it != end; ++it) {
- if (it->number >= 0)
- result.push_back(it->number);
+ for (Part part : parts) {
+ if (part.number >= 0)
+ result.push_back(part.number);
}
std::sort(result.begin(), result.end());
@@ -8990,54 +8894,107 @@ static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(const ParseResult &
return result;
}
-static int resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap, const QString *args[])
+static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts, const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap, const QtPrivate::ArgBase *args[])
{
- int totalSize = 0;
- for (ParseResult::iterator pit = parts.begin(), end = parts.end(); pit != end; ++pit) {
- if (pit->number != -1) {
- const ArgIndexToPlaceholderMap::const_iterator ait
- = std::find(argIndexToPlaceholderMap.begin(), argIndexToPlaceholderMap.end(), pit->number);
- if (ait != argIndexToPlaceholderMap.end())
- pit->stringRef = QStringRef(args[ait - argIndexToPlaceholderMap.begin()]);
+ using namespace QtPrivate;
+ qsizetype totalSize = 0;
+ for (Part &part : parts) {
+ if (part.number != -1) {
+ const auto it = std::find(argIndexToPlaceholderMap.begin(), argIndexToPlaceholderMap.end(), part.number);
+ if (it != argIndexToPlaceholderMap.end()) {
+ const auto &arg = *args[it - argIndexToPlaceholderMap.begin()];
+ switch (arg.tag) {
+ case ArgBase::L1:
+ part.reset(static_cast<const QLatin1StringArg&>(arg).string);
+ break;
+ case ArgBase::U8:
+ Q_UNREACHABLE(); // waiting for QUtf8String...
+ break;
+ case ArgBase::U16:
+ part.reset(static_cast<const QStringViewArg&>(arg).string);
+ break;
+ }
+ }
}
- totalSize += pit->stringRef.size();
+ totalSize += part.size;
}
return totalSize;
}
} // unnamed namespace
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QString QString::multiArg(int numArgs, const QString **args) const
{
+ QVarLengthArray<QtPrivate::QStringViewArg, 9> sva;
+ sva.reserve(numArgs);
+ QVarLengthArray<const QtPrivate::ArgBase *, 9> pointers;
+ pointers.reserve(numArgs);
+ for (int i = 0; i < numArgs; ++i) {
+ sva.push_back(QtPrivate::qStringLikeToArg(*args[i]));
+ pointers.push_back(&sva.back());
+ }
+ return QtPrivate::argToQString(qToStringViewIgnoringNull(*this), static_cast<size_t>(numArgs), pointers.data());
+}
+#endif
+
+Q_ALWAYS_INLINE QString to_string(QLatin1String s) noexcept { return s; }
+Q_ALWAYS_INLINE QString to_string(QStringView s) noexcept { return s.toString(); }
+
+template <typename StringView>
+static QString argToQStringImpl(StringView pattern, size_t numArgs, const QtPrivate::ArgBase **args)
+{
// Step 1-2 above
- ParseResult parts = parseMultiArgFormatString(*this);
+ ParseResult parts = parseMultiArgFormatString(pattern);
// 3-4
ArgIndexToPlaceholderMap argIndexToPlaceholderMap = makeArgIndexToPlaceholderMap(parts);
- if (argIndexToPlaceholderMap.size() > numArgs) // 3a
- argIndexToPlaceholderMap.resize(numArgs);
- else if (argIndexToPlaceholderMap.size() < numArgs) // 3b
- qWarning("QString::arg: %d argument(s) missing in %s",
- numArgs - argIndexToPlaceholderMap.size(), toLocal8Bit().data());
+ if (static_cast<size_t>(argIndexToPlaceholderMap.size()) > numArgs) // 3a
+ argIndexToPlaceholderMap.resize(int(numArgs));
+ else if (Q_UNLIKELY(static_cast<size_t>(argIndexToPlaceholderMap.size()) < numArgs)) // 3b
+ qWarning("QString::arg: %d argument(s) missing in %ls",
+ int(numArgs - argIndexToPlaceholderMap.size()), qUtf16Printable(to_string(pattern)));
// 5
- const int totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap, args);
+ const qsizetype totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap, args);
// 6:
QString result(totalSize, Qt::Uninitialized);
- QChar *out = result.data();
-
- for (ParseResult::const_iterator it = parts.begin(), end = parts.end(); it != end; ++it) {
- if (const int sz = it->stringRef.size()) {
- memcpy(out, it->stringRef.constData(), sz * sizeof(QChar));
- out += sz;
+ auto out = const_cast<QChar*>(result.constData());
+
+ for (Part part : parts) {
+ switch (part.tag) {
+ case QtPrivate::ArgBase::L1:
+ if (part.size) {
+ qt_from_latin1(reinterpret_cast<ushort*>(out),
+ reinterpret_cast<const char*>(part.data), part.size);
+ }
+ break;
+ case QtPrivate::ArgBase::U8:
+ Q_UNREACHABLE(); // waiting for QUtf8String
+ break;
+ case QtPrivate::ArgBase::U16:
+ if (part.size)
+ memcpy(out, part.data, part.size * sizeof(QChar));
+ break;
}
+ out += part.size;
}
return result;
}
+QString QtPrivate::argToQString(QStringView pattern, size_t n, const ArgBase **args)
+{
+ return argToQStringImpl(pattern, n, args);
+}
+
+QString QtPrivate::argToQString(QLatin1String pattern, size_t n, const ArgBase **args)
+{
+ return argToQStringImpl(pattern, n, args);
+}
+
/*! \fn bool QString::isSimpleText() const
\internal
@@ -9178,7 +9135,7 @@ bool QString::isRightToLeft() const
to create a deep copy of the data, ensuring that the raw data
isn't modified.
- Here's an example of how we can use a QRegularExpression on raw data in
+ Here is an example of how we can use a QRegularExpression on raw data in
memory without requiring to copy the data into a QString:
\snippet qstring/main.cpp 22
@@ -9446,11 +9403,11 @@ QString &QString::setRawData(const QChar *unicode, int size)
The range \c{[first,last)} must remain valid for the lifetime of
this Latin-1 string object.
- Passing \c nullptr as \a first is safe if \a last is \c nullptr,
+ Passing \nullptr as \a first is safe if \a last is \nullptr,
too, and results in a null Latin-1 string.
The behavior is undefined if \a last precedes \a first, \a first
- is \c nullptr and \a last is not, or if \c{last - first >
+ is \nullptr and \a last is not, or if \c{last - first >
INT_MAX}.
*/
@@ -9591,6 +9548,58 @@ QString &QString::setRawData(const QChar *unicode, int size)
*/
/*!
+ \fn int QLatin1String::indexOf(QStringView str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \fn int QLatin1String::indexOf(QLatin1String l1, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \fn int QLatin1String::indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 5.14
+
+ Returns the index position of the first occurrence of the string-view \a str,
+ Latin-1 string \a l1, or character \a ch, respectively, in this Latin-1 string,
+ searching forward from index position \a from. Returns -1 if \a str is not found.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ If \a from is -1, the search starts at the last character; if it is
+ -2, at the next to last character and so on.
+
+ \sa QString::indexOf()
+*/
+
+/*!
+ \fn bool QLatin1String::contains(QStringView str, Qt::CaseSensitivity cs) const
+ \fn bool QLatin1String::contains(QLatin1String l1, Qt::CaseSensitivity cs) const
+ \fn bool QLatin1String::contains(QChar c, Qt::CaseSensitivity cs) const
+ \since 5.14
+
+ Returns \c true if this Latin-1 string contains an occurrence of the string-view
+ \a str, Latin-1 string \a l1, or character \a ch; otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (the default), the search is
+ case-sensitive; otherwise the search is case-insensitive.
+
+ \sa indexOf(), QStringView::contains(), QStringView::indexOf(), QString::indexOf()
+*/
+
+/*!
+ \fn int QLatin1String::lastIndexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
+ \fn int QLatin1String::lastIndexOf(QLatin1String l1, int from, Qt::CaseSensitivity cs) const
+ \fn int QLatin1String::lastIndexOf(QChar c, int from, Qt::CaseSensitivity cs) const
+ \since 5.14
+
+ Returns the index position of the last occurrence of the string-view \a str,
+ Latin-1 string \a l1, or character \a ch, respectively, in this Latin-1 string,
+ searching backward from index position \a from. If \a from is -1 (default),
+ the search starts at the last character; if \a from is -2, at the next to last
+ character and so on. Returns -1 if \a str is not found.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \sa indexOf(), QStringView::lastIndexOf(), QStringView::indexOf(), QString::indexOf()
+*/
+
+/*!
\fn QLatin1String::const_iterator QLatin1String::begin() const
\since 5.10
@@ -10337,8 +10346,8 @@ ownership of it, no memory is freed when instances are destroyed.
/*!
\fn bool QStringRef::isNull() const
- Returns \c true if string() returns a null pointer or a pointer to a
- null string; otherwise returns \c true.
+ Returns \c true if this string reference does not reference a string or if
+ the string it references is null (i.e. QString::isNull() is true).
\sa size()
*/
@@ -10358,7 +10367,7 @@ ownership of it, no memory is freed when instances are destroyed.
Returns a Unicode representation of the string reference. Since
the data stems directly from the referenced string, it is not
- null-terminated unless the string reference includes the string's
+ \\0'-terminated unless the string reference includes the string's
null terminator.
\sa string()
@@ -10493,7 +10502,7 @@ QString QStringRef::toString() const {
Returns \c true if string reference \a s1 is lexically equal to string reference \a s2; otherwise
returns \c false.
*/
-bool operator==(const QStringRef &s1,const QStringRef &s2) Q_DECL_NOTHROW
+bool operator==(const QStringRef &s1,const QStringRef &s2) noexcept
{
return s1.size() == s2.size() && qt_compare_strings(s1, s2, Qt::CaseSensitive) == 0;
}
@@ -10503,7 +10512,7 @@ bool operator==(const QStringRef &s1,const QStringRef &s2) Q_DECL_NOTHROW
Returns \c true if string \a s1 is lexically equal to string reference \a s2; otherwise
returns \c false.
*/
-bool operator==(const QString &s1,const QStringRef &s2) Q_DECL_NOTHROW
+bool operator==(const QString &s1,const QStringRef &s2) noexcept
{
return s1.size() == s2.size() && qt_compare_strings(s1, s2, Qt::CaseSensitive) == 0;
}
@@ -10513,7 +10522,7 @@ bool operator==(const QString &s1,const QStringRef &s2) Q_DECL_NOTHROW
Returns \c true if string \a s1 is lexically equal to string reference \a s2; otherwise
returns \c false.
*/
-bool operator==(QLatin1String s1, const QStringRef &s2) Q_DECL_NOTHROW
+bool operator==(QLatin1String s1, const QStringRef &s2) noexcept
{
if (s1.size() != s2.size())
return false;
@@ -10532,7 +10541,7 @@ bool operator==(QLatin1String s1, const QStringRef &s2) Q_DECL_NOTHROW
expect. Consider sorting user-interface strings using the
QString::localeAwareCompare() function.
*/
-bool operator<(const QStringRef &s1,const QStringRef &s2) Q_DECL_NOTHROW
+bool operator<(const QStringRef &s1,const QStringRef &s2) noexcept
{
return qt_compare_strings(s1, s2, Qt::CaseSensitive) < 0;
}
@@ -11145,6 +11154,7 @@ QStringRef QString::midRef(int position, int n) const
\sa QString::chop(), truncate()
*/
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\since 4.8
@@ -11162,8 +11172,28 @@ QStringRef QString::midRef(int position, int n) const
*/
int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
{
- return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::findString(QStringView(unicode(), length()), from, QStringView(str.unicode(), str.length()), cs));
}
+#endif // QT_STRINGVIEW_LEVEL < 2
+
+/*!
+ \fn int QStringRef::indexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
+ \since 5.14
+ \overload indexOf()
+
+ Returns the index position of the first occurrence of the string view \a str
+ in this string reference, searching forward from index position \a from.
+ Returns -1 if \a str is not found.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ If \a from is -1, the search starts at the last character; if it is
+ -2, at the next to last character and so on.
+
+ \sa QString::indexOf(), QStringView::indexOf(), lastIndexOf(), contains(), count()
+*/
/*!
\since 4.8
@@ -11177,7 +11207,8 @@ int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) co
*/
int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
{
- return findChar(unicode(), length(), ch, from, cs);
+ // ### Qt6: qsize
+ return int(qFindChar(QStringView(unicode(), length()), ch, from, cs));
}
/*!
@@ -11197,9 +11228,11 @@ int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
*/
int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
{
- return qt_find_latin1_string(unicode(), size(), str, from, cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::findString(QStringView(unicode(), size()), from, str, cs));
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\since 4.8
@@ -11216,8 +11249,10 @@ int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) con
*/
int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
{
- return qFindString(unicode(), size(), from, str.unicode(), str.size(), cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::findString(QStringView(unicode(), size()), from, QStringView(str.unicode(), str.size()), cs));
}
+#endif // QT_STRINGVIEW_LEVEL < 2
/*!
\since 4.8
@@ -11235,7 +11270,8 @@ int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs)
*/
int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
{
- return lastIndexOf(QStringRef(&str), from, cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::lastIndexOf(*this, from, str, cs));
}
/*!
@@ -11249,28 +11285,8 @@ int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs
*/
int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
{
- return qt_last_index_of(unicode(), size(), ch, from, cs);
-}
-
-template<typename T>
-static int last_index_of_impl(const QStringRef &haystack, int from, const T &needle, Qt::CaseSensitivity cs)
-{
- const int sl = needle.size();
- if (sl == 1)
- return haystack.lastIndexOf(needle.at(0), from, cs);
-
- const int l = haystack.size();
- if (from < 0)
- from += l;
- int delta = l - sl;
- if (from == l && sl == 0)
- return from;
- if (uint(from) >= uint(l) || delta < 0)
- return -1;
- if (from > delta)
- from = delta;
-
- return lastIndexOfHelper(haystack, from, needle, cs);
+ // ### Qt6: qsize
+ return int(qLastIndexOf(*this, ch, from, cs));
}
/*!
@@ -11290,7 +11306,8 @@ static int last_index_of_impl(const QStringRef &haystack, int from, const T &nee
*/
int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const
{
- return last_index_of_impl(*this, from, str, cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::lastIndexOf(*this, from, str, cs));
}
/*!
@@ -11310,10 +11327,28 @@ int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs)
*/
int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const
{
- return last_index_of_impl(*this, from, str, cs);
+ // ### Qt6: qsize
+ return int(QtPrivate::lastIndexOf(*this, from, str, cs));
}
/*!
+ \fn int QStringRef::lastIndexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
+ \since 5.14
+ \overload lastIndexOf()
+
+ Returns the index position of the last occurrence of the string view \a
+ str in this string, searching backward from index position \a
+ from. If \a from is -1 (default), the search starts at the last
+ character; if \a from is -2, at the next to last character and so
+ on. Returns -1 if \a str is not found.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \sa indexOf(), contains(), count()
+*/
+
+/*!
\since 4.8
Returns the number of (potentially overlapping) occurrences of
the string \a str in this string reference.
@@ -11325,7 +11360,8 @@ int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity
*/
int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const
{
- return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
+ // ### Qt6: qsize
+ return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
}
/*!
@@ -11342,7 +11378,8 @@ int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const
*/
int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const
{
- return qt_string_count(unicode(), size(), ch, cs);
+ // ### Qt6: qsize
+ return int(qt_string_count(QStringView(unicode(), size()), ch, cs));
}
/*!
@@ -11359,7 +11396,8 @@ int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const
*/
int QStringRef::count(const QStringRef &str, Qt::CaseSensitivity cs) const
{
- return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs);
+ // ### Qt6: qsize
+ return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs));
}
/*!
@@ -11544,7 +11582,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
return qt_ends_with(*this, str, cs);
}
-
+#if QT_STRINGVIEW_LEVEL < 2
/*! \fn bool QStringRef::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\since 4.8
@@ -11556,6 +11594,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
\sa indexOf(), count()
*/
+#endif // QT_STRINGVIEW_LEVEL < 2
/*! \fn bool QStringRef::contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
@@ -11570,6 +11609,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
*/
+#if QT_STRINGVIEW_LEVEL < 2
/*! \fn bool QStringRef::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\overload contains()
\since 4.8
@@ -11582,6 +11622,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
\sa indexOf(), count()
*/
+#endif // QT_STRINGVIEW_LEVEL < 2
/*! \fn bool QStringRef::contains(QLatin1String str, Qt::CaseSensitivity cs) const
\since 4.8
@@ -11596,57 +11637,41 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
\sa indexOf(), count()
*/
-static inline int qt_last_index_of(const QChar *haystack, int haystackLen, QChar needle,
- int from, Qt::CaseSensitivity cs)
-{
- ushort c = needle.unicode();
- if (from < 0)
- from += haystackLen;
- if (uint(from) >= uint(haystackLen))
- return -1;
- if (from >= 0) {
- const ushort *b = reinterpret_cast<const ushort*>(haystack);
- const ushort *n = b + from;
- if (cs == Qt::CaseSensitive) {
- for (; n >= b; --n)
- if (*n == c)
- return n - b;
- } else {
- c = foldCase(c);
- for (; n >= b; --n)
- if (foldCase(*n) == c)
- return n - b;
- }
- }
- return -1;
+/*! \fn bool QStringRef::contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 5.14
+ \overload contains()
+ Returns \c true if this string reference contains an occurrence of
+ the string view \a str; otherwise returns \c false.
-}
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
-static inline int qt_string_count(const QChar *haystack, int haystackLen,
- const QChar *needle, int needleLen,
- Qt::CaseSensitivity cs)
+ \sa indexOf(), count()
+*/
+
+static inline qsizetype qt_string_count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
{
- int num = 0;
- int i = -1;
- if (haystackLen > 500 && needleLen > 5) {
- QStringMatcher matcher(needle, needleLen, cs);
- while ((i = matcher.indexIn(haystack, haystackLen, i + 1)) != -1)
+ qsizetype num = 0;
+ qsizetype i = -1;
+ if (haystack.size() > 500 && needle.size() > 5) {
+ QStringMatcher matcher(needle, cs);
+ while ((i = matcher.indexIn(haystack, i + 1)) != -1)
++num;
} else {
- while ((i = qFindString(haystack, haystackLen, i + 1, needle, needleLen, cs)) != -1)
+ while ((i = QtPrivate::findString(haystack, i + 1, needle, cs)) != -1)
++num;
}
return num;
}
-static inline int qt_string_count(const QChar *unicode, int size, QChar ch,
+static inline qsizetype qt_string_count(QStringView haystack, QChar ch,
Qt::CaseSensitivity cs)
{
ushort c = ch.unicode();
- int num = 0;
- const ushort *b = reinterpret_cast<const ushort*>(unicode);
- const ushort *i = b + size;
+ qsizetype num = 0;
+ const ushort *b = reinterpret_cast<const ushort*>(haystack.data());
+ const ushort *i = b + haystack.size();
if (cs == Qt::CaseSensitive) {
while (i != b)
if (*--i == c)
@@ -11660,24 +11685,8 @@ static inline int qt_string_count(const QChar *unicode, int size, QChar ch,
return num;
}
-static inline int qt_find_latin1_string(const QChar *haystack, int size,
- QLatin1String needle,
- int from, Qt::CaseSensitivity cs)
-{
- if (size < needle.size())
- return -1;
-
- const char *latin1 = needle.latin1();
- int len = needle.size();
- QVarLengthArray<ushort> s(len);
- qt_from_latin1(s.data(), latin1, len);
-
- return qFindString(haystack, size, from,
- reinterpret_cast<const QChar*>(s.constData()), len, cs);
-}
-
template <typename Haystack, typename Needle>
-bool qt_starts_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+bool qt_starts_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) noexcept
{
if (haystack.isNull())
return needle.isNull(); // historical behavior, consider changing in ### Qt 6.
@@ -11729,28 +11738,28 @@ static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSe
\sa QtPrivate::endsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1String::endsWith()
*/
-bool QtPrivate::startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+bool QtPrivate::startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
{
return qt_starts_with_impl(haystack, needle, cs);
}
-bool QtPrivate::startsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+bool QtPrivate::startsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
{
return qt_starts_with_impl(haystack, needle, cs);
}
-bool QtPrivate::startsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+bool QtPrivate::startsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
{
return qt_starts_with_impl(haystack, needle, cs);
}
-bool QtPrivate::startsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+bool QtPrivate::startsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
{
return qt_starts_with_impl(haystack, needle, cs);
}
template <typename Haystack, typename Needle>
-bool qt_ends_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+bool qt_ends_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) noexcept
{
if (haystack.isNull())
return needle.isNull(); // historical behavior, consider changing in ### Qt 6.
@@ -11802,26 +11811,310 @@ static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSens
\sa QtPrivate::startsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1String::endsWith()
*/
-bool QtPrivate::endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+bool QtPrivate::endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
{
return qt_ends_with_impl(haystack, needle, cs);
}
-bool QtPrivate::endsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+bool QtPrivate::endsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
{
return qt_ends_with_impl(haystack, needle, cs);
}
-bool QtPrivate::endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+bool QtPrivate::endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) noexcept
{
return qt_ends_with_impl(haystack, needle, cs);
}
-bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+bool QtPrivate::endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
{
return qt_ends_with_impl(haystack, needle, cs);
}
+namespace {
+template <typename Pointer>
+uint foldCaseHelper(Pointer ch, Pointer start) = delete;
+
+template <>
+uint foldCaseHelper<const QChar*>(const QChar* ch, const QChar* start)
+{
+ return foldCase(reinterpret_cast<const ushort*>(ch), reinterpret_cast<const ushort*>(start));
+}
+
+template <>
+uint foldCaseHelper<const char*>(const char* ch, const char*)
+{
+ return foldCase(ushort(uchar(*ch)));
+}
+
+template <typename T>
+ushort valueTypeToUtf16(T t) = delete;
+
+template <>
+ushort valueTypeToUtf16<QChar>(QChar t)
+{
+ return t.unicode();
+}
+
+template <>
+ushort valueTypeToUtf16<char>(char t)
+{
+ return ushort(uchar(t));
+}
+}
+
+/*!
+ \internal
+
+ Returns the index position of the first occurrence of the
+ character \a ch in the string given by \a str and \a len,
+ searching forward from index
+ position \a from. Returns -1 if \a ch could not be found.
+*/
+
+static inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept
+{
+ if (from < 0)
+ from = qMax(from + str.size(), qsizetype(0));
+ if (from < str.size()) {
+ const ushort *s = (const ushort *)str.data();
+ ushort c = ch.unicode();
+ const ushort *n = s + from;
+ const ushort *e = s + str.size();
+ if (cs == Qt::CaseSensitive) {
+ n = QtPrivate::qustrchr(QStringView(n, e), c);
+ if (n != e)
+ return n - s;
+ } else {
+ c = foldCase(c);
+ --n;
+ while (++n != e)
+ if (foldCase(*n) == c)
+ return n - s;
+ }
+ }
+ return -1;
+}
+
+qsizetype QtPrivate::findString(QStringView haystack0, qsizetype from, QStringView needle0, Qt::CaseSensitivity cs) noexcept
+{
+ const qsizetype l = haystack0.size();
+ const qsizetype sl = needle0.size();
+ if (from < 0)
+ from += l;
+ if (std::size_t(sl + from) > std::size_t(l))
+ return -1;
+ if (!sl)
+ return from;
+ if (!l)
+ return -1;
+
+ if (sl == 1)
+ return qFindChar(haystack0, needle0[0], from, cs);
+
+ /*
+ We use the Boyer-Moore algorithm in cases where the overhead
+ for the skip table should pay off, otherwise we use a simple
+ hash function.
+ */
+ if (l > 500 && sl > 5)
+ return qFindStringBoyerMoore(haystack0, from, needle0, cs);
+
+ auto sv = [sl](const ushort *v) { return QStringView(v, sl); };
+ /*
+ We use some hashing for efficiency's sake. Instead of
+ comparing strings, we compare the hash value of str with that
+ of a part of this QString. Only if that matches, we call
+ qt_string_compare().
+ */
+ const ushort *needle = (const ushort *)needle0.data();
+ const ushort *haystack = (const ushort *)(haystack0.data()) + from;
+ const ushort *end = (const ushort *)(haystack0.data()) + (l - sl);
+ const std::size_t sl_minus_1 = sl - 1;
+ std::size_t hashNeedle = 0, hashHaystack = 0;
+ qsizetype idx;
+
+ if (cs == Qt::CaseSensitive) {
+ for (idx = 0; idx < sl; ++idx) {
+ hashNeedle = ((hashNeedle<<1) + needle[idx]);
+ hashHaystack = ((hashHaystack<<1) + haystack[idx]);
+ }
+ hashHaystack -= haystack[sl_minus_1];
+
+ while (haystack <= end) {
+ hashHaystack += haystack[sl_minus_1];
+ if (hashHaystack == hashNeedle
+ && qt_compare_strings(needle0, sv(haystack), Qt::CaseSensitive) == 0)
+ return haystack - (const ushort *)haystack0.data();
+
+ REHASH(*haystack);
+ ++haystack;
+ }
+ } else {
+ const ushort *haystack_start = (const ushort *)haystack0.data();
+ for (idx = 0; idx < sl; ++idx) {
+ hashNeedle = (hashNeedle<<1) + foldCase(needle + idx, needle);
+ hashHaystack = (hashHaystack<<1) + foldCase(haystack + idx, haystack_start);
+ }
+ hashHaystack -= foldCase(haystack + sl_minus_1, haystack_start);
+
+ while (haystack <= end) {
+ hashHaystack += foldCase(haystack + sl_minus_1, haystack_start);
+ if (hashHaystack == hashNeedle
+ && qt_compare_strings(needle0, sv(haystack), Qt::CaseInsensitive) == 0)
+ return haystack - (const ushort *)haystack0.data();
+
+ REHASH(foldCase(haystack, haystack_start));
+ ++haystack;
+ }
+ }
+ return -1;
+}
+
+template <typename Haystack>
+static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle,
+ qsizetype from, Qt::CaseSensitivity cs) noexcept
+{
+ if (from < 0)
+ from += haystack.size();
+ if (std::size_t(from) >= std::size_t(haystack.size()))
+ return -1;
+ if (from >= 0) {
+ ushort c = needle.unicode();
+ const auto b = haystack.data();
+ auto n = b + from;
+ if (cs == Qt::CaseSensitive) {
+ for (; n >= b; --n)
+ if (valueTypeToUtf16(*n) == c)
+ return n - b;
+ } else {
+ c = foldCase(c);
+ for (; n >= b; --n)
+ if (foldCase(valueTypeToUtf16(*n)) == c)
+ return n - b;
+ }
+ }
+ return -1;
+}
+
+template<typename Haystack, typename Needle>
+static qsizetype qLastIndexOf(Haystack haystack0, qsizetype from,
+ Needle needle0, Qt::CaseSensitivity cs) noexcept
+{
+ const qsizetype sl = needle0.size();
+ if (sl == 1)
+ return qLastIndexOf(haystack0, needle0.front(), from, cs);
+
+ const qsizetype l = haystack0.size();
+ if (from < 0)
+ from += l;
+ if (from == l && sl == 0)
+ return from;
+ const qsizetype delta = l - sl;
+ if (std::size_t(from) >= std::size_t(l) || delta < 0)
+ return -1;
+ if (from > delta)
+ from = delta;
+
+ auto sv = [sl](const typename Haystack::value_type *v) { return Haystack(v, sl); };
+
+ auto haystack = haystack0.data();
+ const auto needle = needle0.data();
+ const auto *end = haystack;
+ haystack += from;
+ const std::size_t sl_minus_1 = sl - 1;
+ const auto *n = needle + sl_minus_1;
+ const auto *h = haystack + sl_minus_1;
+ std::size_t hashNeedle = 0, hashHaystack = 0;
+ qsizetype idx;
+
+ if (cs == Qt::CaseSensitive) {
+ for (idx = 0; idx < sl; ++idx) {
+ hashNeedle = (hashNeedle << 1) + valueTypeToUtf16(*(n - idx));
+ hashHaystack = (hashHaystack << 1) + valueTypeToUtf16(*(h - idx));
+ }
+ hashHaystack -= valueTypeToUtf16(*haystack);
+
+ while (haystack >= end) {
+ hashHaystack += valueTypeToUtf16(*haystack);
+ if (hashHaystack == hashNeedle
+ && qt_compare_strings(needle0, sv(haystack), Qt::CaseSensitive) == 0)
+ return haystack - end;
+ --haystack;
+ REHASH(valueTypeToUtf16(haystack[sl]));
+ }
+ } else {
+ for (idx = 0; idx < sl; ++idx) {
+ hashNeedle = (hashNeedle << 1) + foldCaseHelper(n - idx, needle);
+ hashHaystack = (hashHaystack << 1) + foldCaseHelper(h - idx, end);
+ }
+ hashHaystack -= foldCaseHelper(haystack, end);
+
+ while (haystack >= end) {
+ hashHaystack += foldCaseHelper(haystack, end);
+ if (hashHaystack == hashNeedle
+ && qt_compare_strings(sv(haystack), needle0, Qt::CaseInsensitive) == 0)
+ return haystack - end;
+ --haystack;
+ REHASH(foldCaseHelper(haystack + sl, end));
+ }
+ }
+ return -1;
+}
+
+qsizetype QtPrivate::findString(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+{
+ if (haystack.size() < needle.size())
+ return -1;
+
+ QVarLengthArray<ushort> s(needle.size());
+ qt_from_latin1(s.data(), needle.latin1(), needle.size());
+ return QtPrivate::findString(haystack, from, QStringView(reinterpret_cast<const QChar*>(s.constData()), s.size()), cs);
+}
+
+qsizetype QtPrivate::findString(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
+{
+ if (haystack.size() < needle.size())
+ return -1;
+
+ QVarLengthArray<ushort> s(haystack.size());
+ qt_from_latin1(s.data(), haystack.latin1(), haystack.size());
+ return QtPrivate::findString(QStringView(reinterpret_cast<const QChar*>(s.constData()), s.size()), from, needle, cs);
+}
+
+qsizetype QtPrivate::findString(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+{
+ if (haystack.size() < needle.size())
+ return -1;
+
+ QVarLengthArray<ushort> h(haystack.size());
+ qt_from_latin1(h.data(), haystack.latin1(), haystack.size());
+ QVarLengthArray<ushort> n(needle.size());
+ qt_from_latin1(n.data(), needle.latin1(), needle.size());
+ return QtPrivate::findString(QStringView(reinterpret_cast<const QChar*>(h.constData()), h.size()), from,
+ QStringView(reinterpret_cast<const QChar*>(n.constData()), n.size()), cs);
+}
+
+qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
+{
+ return qLastIndexOf(haystack, from, needle, cs);
+}
+
+qsizetype QtPrivate::lastIndexOf(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+{
+ return qLastIndexOf(haystack, from, needle, cs);
+}
+
+qsizetype QtPrivate::lastIndexOf(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs) noexcept
+{
+ return qLastIndexOf(haystack, from, needle, cs);
+}
+
+qsizetype QtPrivate::lastIndexOf(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs) noexcept
+{
+ return qLastIndexOf(haystack, from, needle, cs);
+}
+
/*!
\since 4.8
@@ -11900,7 +12193,7 @@ QByteArray QStringRef::toUtf8() const
this string is replaced by the Unicode's replacement character
(QChar::ReplacementCharacter, which corresponds to \c{U+FFFD}).
- The returned vector is not NUL terminated.
+ The returned vector is not \\0'-terminated.
\sa toUtf8(), toLatin1(), toLocal8Bit(), QTextCodec
*/
@@ -11939,7 +12232,7 @@ QStringRef QStringRef::trimmed() const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -11964,7 +12257,7 @@ qint64 QStringRef::toLongLong(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -11991,7 +12284,7 @@ quint64 QStringRef::toULongLong(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -12018,7 +12311,7 @@ long QStringRef::toLong(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -12044,7 +12337,7 @@ ulong QStringRef::toULong(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -12069,7 +12362,7 @@ int QStringRef::toInt(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -12094,7 +12387,7 @@ uint QStringRef::toUInt(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -12119,7 +12412,7 @@ short QStringRef::toShort(bool *ok, int base) const
base, which is 10 by default and must be between 2 and 36, or 0.
Returns 0 if the conversion fails.
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
If \a base is 0, the C language convention is used: If the string
@@ -12146,7 +12439,7 @@ ushort QStringRef::toUShort(bool *ok, int base) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for other reasons (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
The string conversion will always happen in the 'C' locale. For locale
@@ -12172,7 +12465,7 @@ double QStringRef::toDouble(bool *ok) const
Returns an infinity if the conversion overflows or 0.0 if the
conversion fails for other reasons (e.g. underflow).
- If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
+ If \a ok is not \nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
The string conversion will always happen in the 'C' locale. For locale
@@ -12274,7 +12567,7 @@ QString QString::toHtmlEscaped() const
/*!
\internal
*/
-void QAbstractConcatenable::appendLatin1To(const char *a, int len, QChar *out) Q_DECL_NOTHROW
+void QAbstractConcatenable::appendLatin1To(const char *a, int len, QChar *out) noexcept
{
qt_from_latin1(reinterpret_cast<ushort *>(out), a, uint(len));
}
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 6be3dcdbe1..b56b37edf3 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -2,6 +2,7 @@
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2019 Mail.ru Group.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -91,19 +92,22 @@ template <typename T> class QVector;
class QLatin1String
{
public:
- Q_DECL_CONSTEXPR inline QLatin1String() Q_DECL_NOTHROW : m_size(0), m_data(nullptr) {}
- Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) Q_DECL_NOTHROW : m_size(s ? int(strlen(s)) : 0), m_data(s) {}
+ Q_DECL_CONSTEXPR inline QLatin1String() noexcept : m_size(0), m_data(nullptr) {}
+ Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) noexcept : m_size(s ? int(strlen(s)) : 0), m_data(s) {}
Q_DECL_CONSTEXPR explicit QLatin1String(const char *f, const char *l)
: QLatin1String(f, int(l - f)) {}
- Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) Q_DECL_NOTHROW : m_size(sz), m_data(s) {}
- inline explicit QLatin1String(const QByteArray &s) Q_DECL_NOTHROW : m_size(int(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {}
+ Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) noexcept : m_size(sz), m_data(s) {}
+ inline explicit QLatin1String(const QByteArray &s) noexcept : m_size(int(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {}
- Q_DECL_CONSTEXPR const char *latin1() const Q_DECL_NOTHROW { return m_data; }
- Q_DECL_CONSTEXPR int size() const Q_DECL_NOTHROW { return m_size; }
- Q_DECL_CONSTEXPR const char *data() const Q_DECL_NOTHROW { return m_data; }
+ Q_DECL_CONSTEXPR const char *latin1() const noexcept { return m_data; }
+ Q_DECL_CONSTEXPR int size() const noexcept { return m_size; }
+ Q_DECL_CONSTEXPR const char *data() const noexcept { return m_data; }
- Q_DECL_CONSTEXPR bool isNull() const Q_DECL_NOTHROW { return !data(); }
- Q_DECL_CONSTEXPR bool isEmpty() const Q_DECL_NOTHROW { return !size(); }
+ Q_DECL_CONSTEXPR bool isNull() const noexcept { return !data(); }
+ Q_DECL_CONSTEXPR bool isEmpty() const noexcept { return !size(); }
+
+ template <typename...Args>
+ Q_REQUIRED_RESULT inline QString arg(Args &&...args) const;
Q_DECL_CONSTEXPR QLatin1Char at(int i) const
{ return Q_ASSERT(i >= 0), Q_ASSERT(i < size()), QLatin1Char(m_data[i]); }
@@ -112,24 +116,45 @@ public:
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char front() const { return at(0); }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char back() const { return at(size() - 1); }
- Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); }
- Q_REQUIRED_RESULT bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool startsWith(QChar c) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool startsWith(QChar c) const noexcept
{ return !isEmpty() && front() == c; }
- Q_REQUIRED_RESULT inline bool startsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::startsWith(*this, QStringView(&c, 1), cs); }
- Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::endsWith(*this, s, cs); }
- Q_REQUIRED_RESULT bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::endsWith(*this, s, cs); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool endsWith(QChar c) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool endsWith(QChar c) const noexcept
{ return !isEmpty() && back() == c; }
- Q_REQUIRED_RESULT inline bool endsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
+ Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsize
+ Q_REQUIRED_RESULT int indexOf(QLatin1String s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsize
+ Q_REQUIRED_RESULT inline int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return int(QtPrivate::findString(*this, from, QStringView(&c, 1), cs)); } // ### Qt6: qsize
+
+ Q_REQUIRED_RESULT bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return indexOf(s, 0, cs) != -1; }
+ Q_REQUIRED_RESULT bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return indexOf(s, 0, cs) != -1; }
+ Q_REQUIRED_RESULT inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return indexOf(QStringView(&c, 1), 0, cs) != -1; }
+
+ Q_REQUIRED_RESULT int lastIndexOf(QStringView s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsize
+ Q_REQUIRED_RESULT int lastIndexOf(QLatin1String s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsize
+ Q_REQUIRED_RESULT inline int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return int(QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs)); } // ### Qt6: qsize
+
using value_type = const char;
using reference = value_type&;
using const_reference = reference;
@@ -138,18 +163,18 @@ public:
using difference_type = int; // violates Container concept requirements
using size_type = int; // violates Container concept requirements
- Q_DECL_CONSTEXPR const_iterator begin() const Q_DECL_NOTHROW { return data(); }
- Q_DECL_CONSTEXPR const_iterator cbegin() const Q_DECL_NOTHROW { return data(); }
- Q_DECL_CONSTEXPR const_iterator end() const Q_DECL_NOTHROW { return data() + size(); }
- Q_DECL_CONSTEXPR const_iterator cend() const Q_DECL_NOTHROW { return data() + size(); }
+ Q_DECL_CONSTEXPR const_iterator begin() const noexcept { return data(); }
+ Q_DECL_CONSTEXPR const_iterator cbegin() const noexcept { return data(); }
+ Q_DECL_CONSTEXPR const_iterator end() const noexcept { return data() + size(); }
+ Q_DECL_CONSTEXPR const_iterator cend() const noexcept { return data() + size(); }
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = reverse_iterator;
- const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
- const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
Q_DECL_CONSTEXPR QLatin1String mid(int pos) const
{ return Q_ASSERT(pos >= 0), Q_ASSERT(pos <= size()), QLatin1String(m_data + pos, m_size - pos); }
@@ -167,14 +192,14 @@ public:
Q_DECL_RELAXED_CONSTEXPR void truncate(int n)
{ Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size = n; }
- Q_REQUIRED_RESULT QLatin1String trimmed() const Q_DECL_NOTHROW { return QtPrivate::trimmed(*this); }
+ Q_REQUIRED_RESULT QLatin1String trimmed() const noexcept { return QtPrivate::trimmed(*this); }
- inline bool operator==(const QString &s) const Q_DECL_NOTHROW;
- inline bool operator!=(const QString &s) const Q_DECL_NOTHROW;
- inline bool operator>(const QString &s) const Q_DECL_NOTHROW;
- inline bool operator<(const QString &s) const Q_DECL_NOTHROW;
- inline bool operator>=(const QString &s) const Q_DECL_NOTHROW;
- inline bool operator<=(const QString &s) const Q_DECL_NOTHROW;
+ inline bool operator==(const QString &s) const noexcept;
+ inline bool operator!=(const QString &s) const noexcept;
+ inline bool operator>(const QString &s) const noexcept;
+ inline bool operator<(const QString &s) const noexcept;
+ inline bool operator>=(const QString &s) const noexcept;
+ inline bool operator<=(const QString &s) const noexcept;
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
inline QT_ASCII_CAST_WARN bool operator==(const char *s) const;
@@ -199,43 +224,49 @@ private:
Q_DECLARE_TYPEINFO(QLatin1String, Q_MOVABLE_TYPE);
// Qt 4.x compatibility
-typedef QLatin1String QLatin1Literal;
+#if QT_DEPRECATED_SINCE(5, 14)
+QT_DEPRECATED_X("Use QLatin1String") typedef QLatin1String QLatin1Literal;
+#endif
//
// QLatin1String inline implementations
//
-inline bool QtPrivate::isLatin1(QLatin1String) Q_DECL_NOTHROW
+inline bool QtPrivate::isLatin1(QLatin1String) noexcept
{ return true; }
//
// QStringView members that require QLatin1String:
//
-bool QStringView::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+bool QStringView::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); }
-bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::endsWith(*this, s, cs); }
+qsizetype QStringView::indexOf(QLatin1String s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
+{ return QtPrivate::findString(*this, from, s, cs); }
+bool QStringView::contains(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
+{ return indexOf(s, 0, cs) != qsizetype(-1); }
+qsizetype QStringView::lastIndexOf(QLatin1String s, qsizetype from, Qt::CaseSensitivity cs) const noexcept
+{ return QtPrivate::lastIndexOf(*this, from, s, cs); }
class Q_CORE_EXPORT QString
{
public:
typedef QStringData Data;
- inline QString() Q_DECL_NOTHROW;
+ inline QString() noexcept;
explicit QString(const QChar *unicode, int size = -1);
QString(QChar c);
QString(int size, QChar c);
inline QString(QLatin1String latin1);
- inline QString(const QString &) Q_DECL_NOTHROW;
+ inline QString(const QString &) noexcept;
inline ~QString();
QString &operator=(QChar c);
- QString &operator=(const QString &) Q_DECL_NOTHROW;
+ QString &operator=(const QString &) noexcept;
QString &operator=(QLatin1String latin1);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QString(QString && other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }
- inline QString &operator=(QString &&other) Q_DECL_NOTHROW
+ inline QString(QString && other) noexcept : d(other.d) { other.d = Data::sharedNull(); }
+ inline QString &operator=(QString &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- inline void swap(QString &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ inline void swap(QString &other) noexcept { qSwap(d, other.d); }
inline int size() const { return d->size; }
inline int count() const { return d->size; }
inline int length() const;
@@ -263,9 +294,9 @@ public:
inline const QChar at(int i) const;
const QChar operator[](int i) const;
- QCharRef operator[](int i);
+ Q_REQUIRED_RESULT QCharRef operator[](int i);
const QChar operator[](uint i) const;
- QCharRef operator[](uint i);
+ Q_REQUIRED_RESULT QCharRef operator[](uint i);
Q_REQUIRED_RESULT inline QChar front() const { return at(0); }
Q_REQUIRED_RESULT inline QCharRef front();
@@ -320,24 +351,40 @@ public:
const QString &a4, const QString &a5, const QString &a6,
const QString &a7, const QString &a8, const QString &a9) const;
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_X("Use vasprintf(), arg() or QTextStream instead")
QString &vsprintf(const char *format, va_list ap) Q_ATTRIBUTE_FORMAT_PRINTF(2, 0);
+ QT_DEPRECATED_X("Use asprintf(), arg() or QTextStream instead")
QString &sprintf(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);
+#endif
static QString vasprintf(const char *format, va_list ap) Q_ATTRIBUTE_FORMAT_PRINTF(1, 0);
static QString asprintf(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2);
int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int indexOf(QLatin1String s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#if QT_STRINGVIEW_LEVEL < 2
+ int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int indexOf(const QStringRef &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
+ Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsize
int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int lastIndexOf(QLatin1String s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#if QT_STRINGVIEW_LEVEL < 2
+ int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int lastIndexOf(const QStringRef &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
+
+ Q_REQUIRED_RESULT int lastIndexOf(QStringView s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsize
inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#if QT_STRINGVIEW_LEVEL < 2
inline bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
inline bool contains(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
+ inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -359,7 +406,7 @@ public:
int lastIndexOf(const QRegularExpression &re, int from = -1) const;
int lastIndexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads
bool contains(const QRegularExpression &re) const;
- bool contains(const QRegularExpression &re, QRegularExpressionMatch *match) const; // ### Qt 6: merge overloads
+ bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads
int count(const QRegularExpression &re) const;
#endif
@@ -395,7 +442,7 @@ public:
bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
#endif
- Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); }
bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -404,7 +451,7 @@ public:
bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
#endif
- Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::endsWith(*this, s, cs); }
bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -529,6 +576,30 @@ public:
Q_REQUIRED_RESULT QStringList split(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const;
Q_REQUIRED_RESULT QVector<QStringRef> splitRef(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const;
#endif
+
+private:
+ static Q_DECL_CONSTEXPR SplitBehavior _sb(Qt::SplitBehavior sb) Q_DECL_NOTHROW
+ { return sb & Qt::SkipEmptyParts ? SkipEmptyParts : KeepEmptyParts; }
+public:
+
+ Q_REQUIRED_RESULT inline QStringList split(const QString &sep, Qt::SplitBehavior behavior,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ Q_REQUIRED_RESULT inline QVector<QStringRef> splitRef(const QString &sep, Qt::SplitBehavior behavior,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ Q_REQUIRED_RESULT inline QStringList split(QChar sep, Qt::SplitBehavior behavior,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ Q_REQUIRED_RESULT inline QVector<QStringRef> splitRef(QChar sep, Qt::SplitBehavior behavior,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#ifndef QT_NO_REGEXP
+ Q_REQUIRED_RESULT inline QStringList split(const QRegExp &sep, Qt::SplitBehavior behavior) const;
+ Q_REQUIRED_RESULT inline QVector<QStringRef> splitRef(const QRegExp &sep, Qt::SplitBehavior behavior) const;
+#endif
+#ifndef QT_NO_REGULAREXPRESSION
+ Q_REQUIRED_RESULT inline QStringList split(const QRegularExpression &sep, Qt::SplitBehavior behavior) const;
+ Q_REQUIRED_RESULT inline QVector<QStringRef> splitRef(const QRegularExpression &sep, Qt::SplitBehavior behavior) const;
+#endif
+
+
enum NormalizationForm {
NormalizationForm_D,
NormalizationForm_C,
@@ -609,25 +680,25 @@ public:
inline QString &setUtf16(const ushort *utf16, int size);
#if QT_STRINGVIEW_LEVEL < 2
- int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
- inline int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
+ int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ inline int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
#endif
- int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
- inline int compare(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
+ int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ inline int compare(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
static inline int compare(const QString &s1, const QString &s2,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
{ return s1.compare(s2, cs); }
static inline int compare(const QString &s1, QLatin1String s2,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
{ return s1.compare(s2, cs); }
static inline int compare(QLatin1String s1, const QString &s2,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
{ return -s2.compare(s1, cs); }
static int compare(const QString &s1, const QStringRef &s2,
- Qt::CaseSensitivity = Qt::CaseSensitive) Q_DECL_NOTHROW;
+ Qt::CaseSensitivity = Qt::CaseSensitive) noexcept;
int localeAwareCompare(const QString& s) const;
static int localeAwareCompare(const QString& s1, const QString& s2)
@@ -667,19 +738,19 @@ public:
static QString number(qulonglong, int base=10);
static QString number(double, char f='g', int prec=6);
- friend Q_CORE_EXPORT bool operator==(const QString &s1, const QString &s2) Q_DECL_NOTHROW;
- friend Q_CORE_EXPORT bool operator<(const QString &s1, const QString &s2) Q_DECL_NOTHROW;
- friend inline bool operator>(const QString &s1, const QString &s2) Q_DECL_NOTHROW { return s2 < s1; }
- friend inline bool operator!=(const QString &s1, const QString &s2) Q_DECL_NOTHROW { return !(s1 == s2); }
- friend inline bool operator<=(const QString &s1, const QString &s2) Q_DECL_NOTHROW { return !(s1 > s2); }
- friend inline bool operator>=(const QString &s1, const QString &s2) Q_DECL_NOTHROW { return !(s1 < s2); }
+ friend Q_CORE_EXPORT bool operator==(const QString &s1, const QString &s2) noexcept;
+ friend Q_CORE_EXPORT bool operator<(const QString &s1, const QString &s2) noexcept;
+ friend inline bool operator>(const QString &s1, const QString &s2) noexcept { return s2 < s1; }
+ friend inline bool operator!=(const QString &s1, const QString &s2) noexcept { return !(s1 == s2); }
+ friend inline bool operator<=(const QString &s1, const QString &s2) noexcept { return !(s1 > s2); }
+ friend inline bool operator>=(const QString &s1, const QString &s2) noexcept { return !(s1 < s2); }
- bool operator==(QLatin1String s) const Q_DECL_NOTHROW;
- bool operator<(QLatin1String s) const Q_DECL_NOTHROW;
- bool operator>(QLatin1String s) const Q_DECL_NOTHROW;
- inline bool operator!=(QLatin1String s) const Q_DECL_NOTHROW { return !operator==(s); }
- inline bool operator<=(QLatin1String s) const Q_DECL_NOTHROW { return !operator>(s); }
- inline bool operator>=(QLatin1String s) const Q_DECL_NOTHROW { return !operator<(s); }
+ bool operator==(QLatin1String s) const noexcept;
+ bool operator<(QLatin1String s) const noexcept;
+ bool operator>(QLatin1String s) const noexcept;
+ inline bool operator!=(QLatin1String s) const noexcept { return !operator==(s); }
+ inline bool operator<=(QLatin1String s) const noexcept { return !operator>(s); }
+ inline bool operator>=(QLatin1String s) const noexcept { return !operator<(s); }
// ASCII compatibility
#if defined(QT_RESTRICTED_CAST_FROM_ASCII)
@@ -840,30 +911,30 @@ private:
Data *d;
- friend inline bool operator==(QChar, const QString &) Q_DECL_NOTHROW;
- friend inline bool operator< (QChar, const QString &) Q_DECL_NOTHROW;
- friend inline bool operator> (QChar, const QString &) Q_DECL_NOTHROW;
- friend inline bool operator==(QChar, const QStringRef &) Q_DECL_NOTHROW;
- friend inline bool operator< (QChar, const QStringRef &) Q_DECL_NOTHROW;
- friend inline bool operator> (QChar, const QStringRef &) Q_DECL_NOTHROW;
- friend inline bool operator==(QChar, QLatin1String) Q_DECL_NOTHROW;
- friend inline bool operator< (QChar, QLatin1String) Q_DECL_NOTHROW;
- friend inline bool operator> (QChar, QLatin1String) Q_DECL_NOTHROW;
+ friend inline bool operator==(QChar, const QString &) noexcept;
+ friend inline bool operator< (QChar, const QString &) noexcept;
+ friend inline bool operator> (QChar, const QString &) noexcept;
+ friend inline bool operator==(QChar, const QStringRef &) noexcept;
+ friend inline bool operator< (QChar, const QStringRef &) noexcept;
+ friend inline bool operator> (QChar, const QStringRef &) noexcept;
+ friend inline bool operator==(QChar, QLatin1String) noexcept;
+ friend inline bool operator< (QChar, QLatin1String) noexcept;
+ friend inline bool operator> (QChar, QLatin1String) noexcept;
void reallocData(uint alloc, bool grow = false);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void expand(int i);
-#endif
QString multiArg(int numArgs, const QString **args) const;
+#endif
static int compare_helper(const QChar *data1, int length1,
const QChar *data2, int length2,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
static int compare_helper(const QChar *data1, int length1,
const char *data2, int length2,
Qt::CaseSensitivity cs = Qt::CaseSensitive);
static int compare_helper(const QChar *data1, int length1,
QLatin1String s2,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
static int localeAwareCompare_helper(const QChar *data1, int length1,
const QChar *data2, int length2);
static QString toLower_helper(const QString &str);
@@ -899,10 +970,8 @@ private:
template <typename T> static
T toIntegral_helper(const QChar *data, int len, bool *ok, int base)
{
- // ### Qt6: use std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type
- const bool isUnsigned = T(0) < T(-1);
- typedef typename QtPrivate::QConditional<isUnsigned, qulonglong, qlonglong>::Type Int64;
- typedef typename QtPrivate::QConditional<isUnsigned, uint, int>::Type Int32;
+ using Int64 = typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type;
+ using Int32 = typename std::conditional<std::is_unsigned<T>::value, uint, int>::type;
// we select the right overload by casting size() to int or uint
Int64 val = toIntegral_helper(data, Int32(len), ok, base);
@@ -954,7 +1023,7 @@ inline bool QString::isDetached() const
{ return !d->ref.isShared(); }
inline void QString::clear()
{ if (!isNull()) *this = QString(); }
-inline QString::QString(const QString &other) Q_DECL_NOTHROW : d(other.d)
+inline QString::QString(const QString &other) noexcept : d(other.d)
{ Q_ASSERT(&other != this); d->ref.ref(); }
inline int QString::capacity() const
{ return d->alloc ? d->alloc - 1 : 0; }
@@ -985,30 +1054,30 @@ inline QString QString::arg(short a, int fieldWidth, int base, QChar fillChar) c
inline QString QString::arg(ushort a, int fieldWidth, int base, QChar fillChar) const
{ return arg(qulonglong(a), fieldWidth, base, fillChar); }
inline QString QString::arg(const QString &a1, const QString &a2) const
-{ const QString *args[2] = { &a1, &a2 }; return multiArg(2, args); }
+{ return qToStringViewIgnoringNull(*this).arg(a1, a2); }
inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3) const
-{ const QString *args[3] = { &a1, &a2, &a3 }; return multiArg(3, args); }
+{ return qToStringViewIgnoringNull(*this).arg(a1, a2, a3); }
inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3,
const QString &a4) const
-{ const QString *args[4] = { &a1, &a2, &a3, &a4 }; return multiArg(4, args); }
+{ return qToStringViewIgnoringNull(*this).arg(a1, a2, a3, a4); }
inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3,
const QString &a4, const QString &a5) const
-{ const QString *args[5] = { &a1, &a2, &a3, &a4, &a5 }; return multiArg(5, args); }
+{ return qToStringViewIgnoringNull(*this).arg(a1, a2, a3, a4, a5); }
inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3,
const QString &a4, const QString &a5, const QString &a6) const
-{ const QString *args[6] = { &a1, &a2, &a3, &a4, &a5, &a6 }; return multiArg(6, args); }
+{ return qToStringViewIgnoringNull(*this).arg(a1, a2, a3, a4, a5, a6); }
inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3,
const QString &a4, const QString &a5, const QString &a6,
const QString &a7) const
-{ const QString *args[7] = { &a1, &a2, &a3, &a4, &a5, &a6, &a7 }; return multiArg(7, args); }
+{ return qToStringViewIgnoringNull(*this).arg(a1, a2, a3, a4, a5, a6, a7); }
inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3,
const QString &a4, const QString &a5, const QString &a6,
const QString &a7, const QString &a8) const
-{ const QString *args[8] = { &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8 }; return multiArg(8, args); }
+{ return qToStringViewIgnoringNull(*this).arg(a1, a2, a3, a4, a5, a6, a7, a8); }
inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3,
const QString &a4, const QString &a5, const QString &a6,
const QString &a7, const QString &a8, const QString &a9) const
-{ const QString *args[9] = { &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9 }; return multiArg(9, args); }
+{ return qToStringViewIgnoringNull(*this).arg(a1, a2, a3, a4, a5, a6, a7, a8, a9); }
inline QString QString::section(QChar asep, int astart, int aend, SectionFlags aflags) const
{ return section(QString(asep), astart, aend, aflags); }
@@ -1019,12 +1088,7 @@ QT_WARNING_DISABLE_INTEL(111) // "statement is unreachable"
inline int QString::toWCharArray(wchar_t *array) const
{
- if (sizeof(wchar_t) == sizeof(QChar)) {
- memcpy(array, d->data(), sizeof(QChar) * size());
- return size();
- } else {
- return toUcs4_helper(d->data(), size(), reinterpret_cast<uint *>(array));
- }
+ return QStringView(*this).toWCharArray(array);
}
QT_WARNING_POP
@@ -1035,8 +1099,11 @@ inline QString QString::fromWCharArray(const wchar_t *string, int size)
: fromUcs4(reinterpret_cast<const uint *>(string), size);
}
-
-class Q_CORE_EXPORT QCharRef {
+class
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+Q_CORE_EXPORT
+#endif
+QCharRef {
QString &s;
int i;
inline QCharRef(QString &str, int idx)
@@ -1048,10 +1115,33 @@ public:
// all this is not documented: We just say "like QChar" and let it be.
inline operator QChar() const
- { return i < s.d->size ? s.d->data()[i] : 0; }
+ {
+ using namespace QtPrivate::DeprecatedRefClassBehavior;
+ if (Q_LIKELY(i < s.d->size))
+ return s.d->data()[i];
+#ifdef QT_DEBUG
+ warn(WarningType::OutOfRange, EmittingClass::QCharRef);
+#endif
+ return 0;
+ }
inline QCharRef &operator=(QChar c)
- { if (i >= s.d->size) s.resize(i + 1, QLatin1Char(' ')); else s.detach();
- s.d->data()[i] = c.unicode(); return *this; }
+ {
+ using namespace QtPrivate::DeprecatedRefClassBehavior;
+ if (Q_UNLIKELY(i >= s.d->size)) {
+#ifdef QT_DEBUG
+ warn(WarningType::OutOfRange, EmittingClass::QCharRef);
+#endif
+ s.resize(i + 1, QLatin1Char(' '));
+ } else {
+#ifdef QT_DEBUG
+ if (Q_UNLIKELY(!s.isDetached()))
+ warn(WarningType::DelayedDetach, EmittingClass::QCharRef);
+#endif
+ s.detach();
+ }
+ s.d->data()[i] = c.unicode();
+ return *this;
+ }
// An operator= for each QChar cast constructors
#ifndef QT_NO_CAST_FROM_ASCII
@@ -1131,7 +1221,7 @@ inline void QCharRef::setRow(uchar arow) { QChar(*this).setRow(arow); }
inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); }
-inline QString::QString() Q_DECL_NOTHROW : d(Data::sharedNull()) {}
+inline QString::QString() noexcept : d(Data::sharedNull()) {}
inline QString::~QString() { if (!d->ref.deref()) Data::deallocate(d); }
inline void QString::reserve(int asize)
@@ -1160,9 +1250,9 @@ inline void QString::squeeze()
inline QString &QString::setUtf16(const ushort *autf16, int asize)
{ return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); }
inline QCharRef QString::operator[](int i)
-{ Q_ASSERT(i >= 0); return QCharRef(*this, i); }
+{ Q_ASSERT(i >= 0); detach(); return QCharRef(*this, i); }
inline QCharRef QString::operator[](uint i)
-{ return QCharRef(*this, i); }
+{ detach(); return QCharRef(*this, i); }
inline QCharRef QString::front() { return operator[](0); }
inline QCharRef QString::back() { return operator[](size() - 1); }
inline QString::iterator QString::begin()
@@ -1181,14 +1271,18 @@ inline QString::const_iterator QString::cend() const
{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
inline QString::const_iterator QString::constEnd() const
{ return reinterpret_cast<const QChar*>(d->data() + d->size); }
+#if QT_STRINGVIEW_LEVEL < 2
inline bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const
{ return indexOf(s, 0, cs) != -1; }
inline bool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
{ return indexOf(s, 0, cs) != -1; }
+#endif
inline bool QString::contains(QLatin1String s, Qt::CaseSensitivity cs) const
{ return indexOf(s, 0, cs) != -1; }
inline bool QString::contains(QChar c, Qt::CaseSensitivity cs) const
{ return indexOf(c, 0, cs) != -1; }
+inline bool QString::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept
+{ return indexOf(s, 0, cs) != -1; }
#if QT_DEPRECATED_SINCE(5, 9)
inline bool operator==(QString::Null, QString::Null) { return true; }
@@ -1203,34 +1297,34 @@ QT_DEPRECATED_X("use !QString::isNull()")
inline bool operator!=(const QString &s, QString::Null) { return !s.isNull(); }
#endif
-inline bool operator==(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
+inline bool operator==(QLatin1String s1, QLatin1String s2) noexcept
{ return s1.size() == s2.size() && (!s1.size() || !memcmp(s1.latin1(), s2.latin1(), s1.size())); }
-inline bool operator!=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
+inline bool operator!=(QLatin1String s1, QLatin1String s2) noexcept
{ return !operator==(s1, s2); }
-inline bool operator<(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
+inline bool operator<(QLatin1String s1, QLatin1String s2) noexcept
{
const int len = qMin(s1.size(), s2.size());
const int r = len ? memcmp(s1.latin1(), s2.latin1(), len) : 0;
return r < 0 || (r == 0 && s1.size() < s2.size());
}
-inline bool operator>(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
+inline bool operator>(QLatin1String s1, QLatin1String s2) noexcept
{ return operator<(s2, s1); }
-inline bool operator<=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
+inline bool operator<=(QLatin1String s1, QLatin1String s2) noexcept
{ return !operator>(s1, s2); }
-inline bool operator>=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW
+inline bool operator>=(QLatin1String s1, QLatin1String s2) noexcept
{ return !operator<(s1, s2); }
-inline bool QLatin1String::operator==(const QString &s) const Q_DECL_NOTHROW
+inline bool QLatin1String::operator==(const QString &s) const noexcept
{ return s == *this; }
-inline bool QLatin1String::operator!=(const QString &s) const Q_DECL_NOTHROW
+inline bool QLatin1String::operator!=(const QString &s) const noexcept
{ return s != *this; }
-inline bool QLatin1String::operator>(const QString &s) const Q_DECL_NOTHROW
+inline bool QLatin1String::operator>(const QString &s) const noexcept
{ return s < *this; }
-inline bool QLatin1String::operator<(const QString &s) const Q_DECL_NOTHROW
+inline bool QLatin1String::operator<(const QString &s) const noexcept
{ return s > *this; }
-inline bool QLatin1String::operator>=(const QString &s) const Q_DECL_NOTHROW
+inline bool QLatin1String::operator>=(const QString &s) const noexcept
{ return s <= *this; }
-inline bool QLatin1String::operator<=(const QString &s) const Q_DECL_NOTHROW
+inline bool QLatin1String::operator<=(const QString &s) const noexcept
{ return s >= *this; }
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
@@ -1378,14 +1472,12 @@ inline std::wstring QString::toStdWString() const
{
std::wstring str;
str.resize(length());
-
-#ifdef Q_CC_MSVC
- // VS2005 crashes if the string is empty
- if (!length())
- return str;
+#if __cplusplus >= 201703L
+ str.resize(toWCharArray(str.data()));
+#else
+ if (length())
+ str.resize(toWCharArray(&str.front()));
#endif
-
- str.resize(toWCharArray(&(*str.begin())));
return str;
}
@@ -1439,14 +1531,12 @@ public:
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
// ### Qt 6: remove all of these, the implicit ones are fine
- QStringRef(const QStringRef &other) Q_DECL_NOTHROW
+ QStringRef(const QStringRef &other) noexcept
:m_string(other.m_string), m_position(other.m_position), m_size(other.m_size)
{}
-#ifdef Q_COMPILER_RVALUE_REFS
- QStringRef(QStringRef &&other) Q_DECL_NOTHROW : m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {}
- QStringRef &operator=(QStringRef &&other) Q_DECL_NOTHROW { return *this = other; }
-#endif
- QStringRef &operator=(const QStringRef &other) Q_DECL_NOTHROW
+ QStringRef(QStringRef &&other) noexcept : m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {}
+ QStringRef &operator=(QStringRef &&other) noexcept { return *this = other; }
+ QStringRef &operator=(const QStringRef &other) noexcept
{
m_string = other.m_string; m_position = other.m_position;
m_size = other.m_size; return *this;
@@ -1460,19 +1550,30 @@ public:
inline int count() const { return m_size; }
inline int length() const { return m_size; }
+#if QT_STRINGVIEW_LEVEL < 2
int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ int indexOf(const QStringRef &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
+ Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsize
int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int indexOf(QLatin1String str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int indexOf(const QStringRef &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#if QT_STRINGVIEW_LEVEL < 2
+ int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int lastIndexOf(const QString &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
int lastIndexOf(QChar ch, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int lastIndexOf(QLatin1String str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ Q_REQUIRED_RESULT int lastIndexOf(QStringView s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsize
+#if QT_STRINGVIEW_LEVEL < 2
inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline bool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
inline bool contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
inline bool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
- inline bool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline bool contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -1483,14 +1584,19 @@ public:
Q_REQUIRED_RESULT QVector<QStringRef> split(QChar sep, QString::SplitBehavior behavior = QString::KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ Q_REQUIRED_RESULT inline QVector<QStringRef> split(const QString &sep, Qt::SplitBehavior behavior,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ Q_REQUIRED_RESULT inline QVector<QStringRef> split(QChar sep, Qt::SplitBehavior behavior,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
Q_REQUIRED_RESULT QStringRef left(int n) const;
Q_REQUIRED_RESULT QStringRef right(int n) const;
Q_REQUIRED_RESULT QStringRef mid(int pos, int n = -1) const;
Q_REQUIRED_RESULT QStringRef chopped(int n) const
{ Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return left(size() - n); }
- void truncate(int pos) Q_DECL_NOTHROW { m_size = qBound(0, pos, m_size); }
- void chop(int n) Q_DECL_NOTHROW
+ void truncate(int pos) noexcept { m_size = qBound(0, pos, m_size); }
+ void chop(int n) noexcept
{
if (n >= m_size)
m_size = 0;
@@ -1500,7 +1606,7 @@ public:
bool isRightToLeft() const;
- Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); }
bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -1509,7 +1615,7 @@ public:
bool startsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
#endif
- Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::endsWith(*this, s, cs); }
bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -1572,19 +1678,19 @@ public:
inline QT_ASCII_CAST_WARN bool operator>=(const char *s) const;
#endif
- int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
- int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
- int compare(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
+ int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ int compare(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
int compare(const QByteArray &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
{ return QString::compare_helper(unicode(), size(), s.data(), qstrnlen(s.data(), s.size()), cs); }
#endif
static int compare(const QStringRef &s1, const QString &s2,
- Qt::CaseSensitivity = Qt::CaseSensitive) Q_DECL_NOTHROW;
+ Qt::CaseSensitivity = Qt::CaseSensitive) noexcept;
static int compare(const QStringRef &s1, const QStringRef &s2,
- Qt::CaseSensitivity = Qt::CaseSensitive) Q_DECL_NOTHROW;
+ Qt::CaseSensitivity = Qt::CaseSensitive) noexcept;
static int compare(const QStringRef &s1, QLatin1String s2,
- Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+ Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
int localeAwareCompare(const QString &s) const;
int localeAwareCompare(const QStringRef &s) const;
@@ -1615,162 +1721,162 @@ inline QStringRef::QStringRef(const QString *aString)
:m_string(aString), m_position(0), m_size(aString?aString->size() : 0){}
// QStringRef <> QStringRef
-Q_CORE_EXPORT bool operator==(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW;
-inline bool operator!=(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW
+Q_CORE_EXPORT bool operator==(const QStringRef &s1, const QStringRef &s2) noexcept;
+inline bool operator!=(const QStringRef &s1, const QStringRef &s2) noexcept
{ return !(s1 == s2); }
-Q_CORE_EXPORT bool operator<(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW;
-inline bool operator>(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW
+Q_CORE_EXPORT bool operator<(const QStringRef &s1, const QStringRef &s2) noexcept;
+inline bool operator>(const QStringRef &s1, const QStringRef &s2) noexcept
{ return s2 < s1; }
-inline bool operator<=(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW
+inline bool operator<=(const QStringRef &s1, const QStringRef &s2) noexcept
{ return !(s1 > s2); }
-inline bool operator>=(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW
+inline bool operator>=(const QStringRef &s1, const QStringRef &s2) noexcept
{ return !(s1 < s2); }
// QString <> QStringRef
-Q_CORE_EXPORT bool operator==(const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW;
-inline bool operator!=(const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return lhs.compare(rhs) != 0; }
-inline bool operator< (const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return lhs.compare(rhs) < 0; }
-inline bool operator> (const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return lhs.compare(rhs) > 0; }
-inline bool operator<=(const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return lhs.compare(rhs) <= 0; }
-inline bool operator>=(const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return lhs.compare(rhs) >= 0; }
-
-inline bool operator==(const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs == lhs; }
-inline bool operator!=(const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs != lhs; }
-inline bool operator< (const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs > lhs; }
-inline bool operator> (const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs < lhs; }
-inline bool operator<=(const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs >= lhs; }
-inline bool operator>=(const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs <= lhs; }
+Q_CORE_EXPORT bool operator==(const QString &lhs, const QStringRef &rhs) noexcept;
+inline bool operator!=(const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) != 0; }
+inline bool operator< (const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) < 0; }
+inline bool operator> (const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) > 0; }
+inline bool operator<=(const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) <= 0; }
+inline bool operator>=(const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) >= 0; }
+
+inline bool operator==(const QStringRef &lhs, const QString &rhs) noexcept { return rhs == lhs; }
+inline bool operator!=(const QStringRef &lhs, const QString &rhs) noexcept { return rhs != lhs; }
+inline bool operator< (const QStringRef &lhs, const QString &rhs) noexcept { return rhs > lhs; }
+inline bool operator> (const QStringRef &lhs, const QString &rhs) noexcept { return rhs < lhs; }
+inline bool operator<=(const QStringRef &lhs, const QString &rhs) noexcept { return rhs >= lhs; }
+inline bool operator>=(const QStringRef &lhs, const QString &rhs) noexcept { return rhs <= lhs; }
#if QT_STRINGVIEW_LEVEL < 2
-inline int QString::compare(const QStringRef &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+inline int QString::compare(const QStringRef &s, Qt::CaseSensitivity cs) const noexcept
{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); }
#endif
-inline int QString::compare(QStringView s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+inline int QString::compare(QStringView s, Qt::CaseSensitivity cs) const noexcept
{ return -s.compare(*this, cs); }
-inline int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+inline int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs) noexcept
{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); }
-inline int QStringRef::compare(const QString &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+inline int QStringRef::compare(const QString &s, Qt::CaseSensitivity cs) const noexcept
{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); }
-inline int QStringRef::compare(const QStringRef &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+inline int QStringRef::compare(const QStringRef &s, Qt::CaseSensitivity cs) const noexcept
{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); }
-inline int QStringRef::compare(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+inline int QStringRef::compare(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
{ return QString::compare_helper(constData(), length(), s, cs); }
-inline int QStringRef::compare(const QStringRef &s1, const QString &s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+inline int QStringRef::compare(const QStringRef &s1, const QString &s2, Qt::CaseSensitivity cs) noexcept
{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); }
-inline int QStringRef::compare(const QStringRef &s1, const QStringRef &s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+inline int QStringRef::compare(const QStringRef &s1, const QStringRef &s2, Qt::CaseSensitivity cs) noexcept
{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); }
-inline int QStringRef::compare(const QStringRef &s1, QLatin1String s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+inline int QStringRef::compare(const QStringRef &s1, QLatin1String s2, Qt::CaseSensitivity cs) noexcept
{ return QString::compare_helper(s1.constData(), s1.length(), s2, cs); }
// QLatin1String <> QStringRef
-Q_CORE_EXPORT bool operator==(QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW;
-inline bool operator!=(QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return rhs.compare(lhs) != 0; }
-inline bool operator< (QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return rhs.compare(lhs) > 0; }
-inline bool operator> (QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return rhs.compare(lhs) < 0; }
-inline bool operator<=(QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return rhs.compare(lhs) >= 0; }
-inline bool operator>=(QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return rhs.compare(lhs) <= 0; }
-
-inline bool operator==(const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs == lhs; }
-inline bool operator!=(const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs != lhs; }
-inline bool operator< (const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs > lhs; }
-inline bool operator> (const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs < lhs; }
-inline bool operator<=(const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs >= lhs; }
-inline bool operator>=(const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs <= lhs; }
+Q_CORE_EXPORT bool operator==(QLatin1String lhs, const QStringRef &rhs) noexcept;
+inline bool operator!=(QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) != 0; }
+inline bool operator< (QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) > 0; }
+inline bool operator> (QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) < 0; }
+inline bool operator<=(QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) >= 0; }
+inline bool operator>=(QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) <= 0; }
+
+inline bool operator==(const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs == lhs; }
+inline bool operator!=(const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs != lhs; }
+inline bool operator< (const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs > lhs; }
+inline bool operator> (const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs < lhs; }
+inline bool operator<=(const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs >= lhs; }
+inline bool operator>=(const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs <= lhs; }
// QChar <> QString
-inline bool operator==(QChar lhs, const QString &rhs) Q_DECL_NOTHROW
+inline bool operator==(QChar lhs, const QString &rhs) noexcept
{ return rhs.size() == 1 && lhs == rhs.front(); }
-inline bool operator< (QChar lhs, const QString &rhs) Q_DECL_NOTHROW
+inline bool operator< (QChar lhs, const QString &rhs) noexcept
{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) < 0; }
-inline bool operator> (QChar lhs, const QString &rhs) Q_DECL_NOTHROW
+inline bool operator> (QChar lhs, const QString &rhs) noexcept
{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) > 0; }
-inline bool operator!=(QChar lhs, const QString &rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
-inline bool operator<=(QChar lhs, const QString &rhs) Q_DECL_NOTHROW { return !(lhs > rhs); }
-inline bool operator>=(QChar lhs, const QString &rhs) Q_DECL_NOTHROW { return !(lhs < rhs); }
+inline bool operator!=(QChar lhs, const QString &rhs) noexcept { return !(lhs == rhs); }
+inline bool operator<=(QChar lhs, const QString &rhs) noexcept { return !(lhs > rhs); }
+inline bool operator>=(QChar lhs, const QString &rhs) noexcept { return !(lhs < rhs); }
-inline bool operator==(const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return rhs == lhs; }
-inline bool operator!=(const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs == lhs); }
-inline bool operator< (const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return rhs > lhs; }
-inline bool operator> (const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return rhs < lhs; }
-inline bool operator<=(const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs < lhs); }
-inline bool operator>=(const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs > lhs); }
+inline bool operator==(const QString &lhs, QChar rhs) noexcept { return rhs == lhs; }
+inline bool operator!=(const QString &lhs, QChar rhs) noexcept { return !(rhs == lhs); }
+inline bool operator< (const QString &lhs, QChar rhs) noexcept { return rhs > lhs; }
+inline bool operator> (const QString &lhs, QChar rhs) noexcept { return rhs < lhs; }
+inline bool operator<=(const QString &lhs, QChar rhs) noexcept { return !(rhs < lhs); }
+inline bool operator>=(const QString &lhs, QChar rhs) noexcept { return !(rhs > lhs); }
// QChar <> QStringRef
-inline bool operator==(QChar lhs, const QStringRef &rhs) Q_DECL_NOTHROW
+inline bool operator==(QChar lhs, const QStringRef &rhs) noexcept
{ return rhs.size() == 1 && lhs == rhs.front(); }
-inline bool operator< (QChar lhs, const QStringRef &rhs) Q_DECL_NOTHROW
+inline bool operator< (QChar lhs, const QStringRef &rhs) noexcept
{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) < 0; }
-inline bool operator> (QChar lhs, const QStringRef &rhs) Q_DECL_NOTHROW
+inline bool operator> (QChar lhs, const QStringRef &rhs) noexcept
{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) > 0; }
-inline bool operator!=(QChar lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
-inline bool operator<=(QChar lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return !(lhs > rhs); }
-inline bool operator>=(QChar lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return !(lhs < rhs); }
+inline bool operator!=(QChar lhs, const QStringRef &rhs) noexcept { return !(lhs == rhs); }
+inline bool operator<=(QChar lhs, const QStringRef &rhs) noexcept { return !(lhs > rhs); }
+inline bool operator>=(QChar lhs, const QStringRef &rhs) noexcept { return !(lhs < rhs); }
-inline bool operator==(const QStringRef &lhs, QChar rhs) Q_DECL_NOTHROW { return rhs == lhs; }
-inline bool operator!=(const QStringRef &lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs == lhs); }
-inline bool operator< (const QStringRef &lhs, QChar rhs) Q_DECL_NOTHROW { return rhs > lhs; }
-inline bool operator> (const QStringRef &lhs, QChar rhs) Q_DECL_NOTHROW { return rhs < lhs; }
-inline bool operator<=(const QStringRef &lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs < lhs); }
-inline bool operator>=(const QStringRef &lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs > lhs); }
+inline bool operator==(const QStringRef &lhs, QChar rhs) noexcept { return rhs == lhs; }
+inline bool operator!=(const QStringRef &lhs, QChar rhs) noexcept { return !(rhs == lhs); }
+inline bool operator< (const QStringRef &lhs, QChar rhs) noexcept { return rhs > lhs; }
+inline bool operator> (const QStringRef &lhs, QChar rhs) noexcept { return rhs < lhs; }
+inline bool operator<=(const QStringRef &lhs, QChar rhs) noexcept { return !(rhs < lhs); }
+inline bool operator>=(const QStringRef &lhs, QChar rhs) noexcept { return !(rhs > lhs); }
// QChar <> QLatin1String
-inline bool operator==(QChar lhs, QLatin1String rhs) Q_DECL_NOTHROW
+inline bool operator==(QChar lhs, QLatin1String rhs) noexcept
{ return rhs.size() == 1 && lhs == rhs.front(); }
-inline bool operator< (QChar lhs, QLatin1String rhs) Q_DECL_NOTHROW
+inline bool operator< (QChar lhs, QLatin1String rhs) noexcept
{ return QString::compare_helper(&lhs, 1, rhs) < 0; }
-inline bool operator> (QChar lhs, QLatin1String rhs) Q_DECL_NOTHROW
+inline bool operator> (QChar lhs, QLatin1String rhs) noexcept
{ return QString::compare_helper(&lhs, 1, rhs) > 0; }
-inline bool operator!=(QChar lhs, QLatin1String rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
-inline bool operator<=(QChar lhs, QLatin1String rhs) Q_DECL_NOTHROW { return !(lhs > rhs); }
-inline bool operator>=(QChar lhs, QLatin1String rhs) Q_DECL_NOTHROW { return !(lhs < rhs); }
+inline bool operator!=(QChar lhs, QLatin1String rhs) noexcept { return !(lhs == rhs); }
+inline bool operator<=(QChar lhs, QLatin1String rhs) noexcept { return !(lhs > rhs); }
+inline bool operator>=(QChar lhs, QLatin1String rhs) noexcept { return !(lhs < rhs); }
-inline bool operator==(QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return rhs == lhs; }
-inline bool operator!=(QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs == lhs); }
-inline bool operator< (QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return rhs > lhs; }
-inline bool operator> (QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return rhs < lhs; }
-inline bool operator<=(QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs < lhs); }
-inline bool operator>=(QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs > lhs); }
+inline bool operator==(QLatin1String lhs, QChar rhs) noexcept { return rhs == lhs; }
+inline bool operator!=(QLatin1String lhs, QChar rhs) noexcept { return !(rhs == lhs); }
+inline bool operator< (QLatin1String lhs, QChar rhs) noexcept { return rhs > lhs; }
+inline bool operator> (QLatin1String lhs, QChar rhs) noexcept { return rhs < lhs; }
+inline bool operator<=(QLatin1String lhs, QChar rhs) noexcept { return !(rhs < lhs); }
+inline bool operator>=(QLatin1String lhs, QChar rhs) noexcept { return !(rhs > lhs); }
// QStringView <> QStringView
-inline bool operator==(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
-inline bool operator!=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
-inline bool operator< (QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) < 0; }
-inline bool operator<=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
-inline bool operator> (QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) > 0; }
-inline bool operator>=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
+inline bool operator==(QStringView lhs, QStringView rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
+inline bool operator!=(QStringView lhs, QStringView rhs) noexcept { return !(lhs == rhs); }
+inline bool operator< (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) < 0; }
+inline bool operator<=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
+inline bool operator> (QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) > 0; }
+inline bool operator>=(QStringView lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
// QStringView <> QChar
-inline bool operator==(QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs == QStringView(&rhs, 1); }
-inline bool operator!=(QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs != QStringView(&rhs, 1); }
-inline bool operator< (QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs < QStringView(&rhs, 1); }
-inline bool operator<=(QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs <= QStringView(&rhs, 1); }
-inline bool operator> (QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs > QStringView(&rhs, 1); }
-inline bool operator>=(QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs >= QStringView(&rhs, 1); }
-
-inline bool operator==(QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) == rhs; }
-inline bool operator!=(QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) != rhs; }
-inline bool operator< (QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) < rhs; }
-inline bool operator<=(QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) <= rhs; }
-inline bool operator> (QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) > rhs; }
-inline bool operator>=(QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) >= rhs; }
+inline bool operator==(QStringView lhs, QChar rhs) noexcept { return lhs == QStringView(&rhs, 1); }
+inline bool operator!=(QStringView lhs, QChar rhs) noexcept { return lhs != QStringView(&rhs, 1); }
+inline bool operator< (QStringView lhs, QChar rhs) noexcept { return lhs < QStringView(&rhs, 1); }
+inline bool operator<=(QStringView lhs, QChar rhs) noexcept { return lhs <= QStringView(&rhs, 1); }
+inline bool operator> (QStringView lhs, QChar rhs) noexcept { return lhs > QStringView(&rhs, 1); }
+inline bool operator>=(QStringView lhs, QChar rhs) noexcept { return lhs >= QStringView(&rhs, 1); }
+
+inline bool operator==(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) == rhs; }
+inline bool operator!=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) != rhs; }
+inline bool operator< (QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) < rhs; }
+inline bool operator<=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) <= rhs; }
+inline bool operator> (QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) > rhs; }
+inline bool operator>=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) >= rhs; }
// QStringView <> QLatin1String
-inline bool operator==(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
-inline bool operator!=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
-inline bool operator< (QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) < 0; }
-inline bool operator<=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
-inline bool operator> (QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) > 0; }
-inline bool operator>=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
-
-inline bool operator==(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
-inline bool operator!=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
-inline bool operator< (QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) < 0; }
-inline bool operator<=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
-inline bool operator> (QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) > 0; }
-inline bool operator>=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
+inline bool operator==(QStringView lhs, QLatin1String rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
+inline bool operator!=(QStringView lhs, QLatin1String rhs) noexcept { return !(lhs == rhs); }
+inline bool operator< (QStringView lhs, QLatin1String rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) < 0; }
+inline bool operator<=(QStringView lhs, QLatin1String rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
+inline bool operator> (QStringView lhs, QLatin1String rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) > 0; }
+inline bool operator>=(QStringView lhs, QLatin1String rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
+
+inline bool operator==(QLatin1String lhs, QStringView rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::compareStrings(lhs, rhs) == 0; }
+inline bool operator!=(QLatin1String lhs, QStringView rhs) noexcept { return !(lhs == rhs); }
+inline bool operator< (QLatin1String lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) < 0; }
+inline bool operator<=(QLatin1String lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) <= 0; }
+inline bool operator> (QLatin1String lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) > 0; }
+inline bool operator>=(QLatin1String lhs, QStringView rhs) noexcept { return QtPrivate::compareStrings(lhs, rhs) >= 0; }
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
// QStringRef <> QByteArray
@@ -1829,13 +1935,17 @@ inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QString &s
inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef &s2)
{ return QString::localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); }
+#if QT_STRINGVIEW_LEVEL < 2
inline bool QStringRef::contains(const QString &s, Qt::CaseSensitivity cs) const
{ return indexOf(s, 0, cs) != -1; }
+inline bool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
+{ return indexOf(s, 0, cs) != -1; }
+#endif
inline bool QStringRef::contains(QLatin1String s, Qt::CaseSensitivity cs) const
{ return indexOf(s, 0, cs) != -1; }
inline bool QStringRef::contains(QChar c, Qt::CaseSensitivity cs) const
{ return indexOf(c, 0, cs) != -1; }
-inline bool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const
+inline bool QStringRef::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept
{ return indexOf(s, 0, cs) != -1; }
inline QString &QString::insert(int i, const QStringRef &s)
@@ -1872,6 +1982,58 @@ inline const QString &asString(const QString &s) { return s; }
inline QString &&asString(QString &&s) { return std::move(s); }
}
+//
+// QStringView::arg() implementation
+//
+
+namespace QtPrivate {
+
+struct ArgBase {
+ enum Tag : uchar { L1, U8, U16 } tag;
+};
+
+struct QStringViewArg : ArgBase {
+ QStringView string;
+ QStringViewArg() = default;
+ Q_DECL_CONSTEXPR explicit QStringViewArg(QStringView v) noexcept : ArgBase{U16}, string{v} {}
+};
+
+struct QLatin1StringArg : ArgBase {
+ QLatin1String string;
+ QLatin1StringArg() = default;
+ Q_DECL_CONSTEXPR explicit QLatin1StringArg(QLatin1String v) noexcept : ArgBase{L1}, string{v} {}
+};
+
+Q_REQUIRED_RESULT Q_CORE_EXPORT QString argToQString(QStringView pattern, size_t n, const ArgBase **args);
+Q_REQUIRED_RESULT Q_CORE_EXPORT QString argToQString(QLatin1String pattern, size_t n, const ArgBase **args);
+
+template <typename StringView, typename...Args>
+Q_REQUIRED_RESULT Q_ALWAYS_INLINE QString argToQStringDispatch(StringView pattern, const Args &...args)
+{
+ const ArgBase *argBases[] = {&args..., /* avoid zero-sized array */ nullptr};
+ return QtPrivate::argToQString(pattern, sizeof...(Args), argBases);
+}
+
+Q_DECL_CONSTEXPR inline QStringViewArg qStringLikeToArg(QStringView s) noexcept { return QStringViewArg{s}; }
+ inline QStringViewArg qStringLikeToArg(const QChar &c) noexcept { return QStringViewArg{QStringView{&c, 1}}; }
+Q_DECL_CONSTEXPR inline QLatin1StringArg qStringLikeToArg(QLatin1String s) noexcept { return QLatin1StringArg{s}; }
+
+} // namespace QtPrivate
+
+template <typename...Args>
+Q_ALWAYS_INLINE
+QString QStringView::arg(Args &&...args) const
+{
+ return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
+}
+
+template <typename...Args>
+Q_ALWAYS_INLINE
+QString QLatin1String::arg(Args &&...args) const
+{
+ return QtPrivate::argToQStringDispatch(*this, QtPrivate::qStringLikeToArg(args)...);
+}
+
QT_END_NAMESPACE
#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
diff --git a/src/corelib/tools/qstringalgorithms.h b/src/corelib/tools/qstringalgorithms.h
index cc0eda71f3..2b480b1e4c 100644
--- a/src/corelib/tools/qstringalgorithms.h
+++ b/src/corelib/tools/qstringalgorithms.h
@@ -51,31 +51,42 @@ QT_BEGIN_NAMESPACE
class QByteArray;
class QLatin1String;
class QStringView;
+class QChar;
template <typename T> class QVector;
namespace QtPrivate {
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype qustrlen(const ushort *str) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype qustrlen(const ushort *str) noexcept;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION const ushort *qustrchr(QStringView str, ushort ch) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView trimmed(QStringView s) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1String trimmed(QLatin1String s) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype findString(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QStringView haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QLatin1String haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QLatin1String haystack, qsizetype from, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
+
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView trimmed(QStringView s) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1String trimmed(QLatin1String s) noexcept;
Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLatin1(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToUtf8(QStringView str);
@@ -83,10 +94,10 @@ Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLocal8Bit(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT QVector<uint> convertToUcs4(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT bool isRightToLeft(QStringView string);
-Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QLatin1String s) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QStringView s) Q_DECL_NOTHROW;
-Q_REQUIRED_RESULT bool isLatin1(QLatin1String s) Q_DECL_NOTHROW; // in qstring.h
-Q_REQUIRED_RESULT Q_CORE_EXPORT bool isLatin1(QStringView s) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QLatin1String s) noexcept;
+Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QStringView s) noexcept;
+Q_REQUIRED_RESULT bool isLatin1(QLatin1String s) noexcept; // in qstring.h
+Q_REQUIRED_RESULT Q_CORE_EXPORT bool isLatin1(QStringView s) noexcept;
} // namespace QtPRivate
diff --git a/src/corelib/tools/qstringalgorithms_p.h b/src/corelib/tools/qstringalgorithms_p.h
index 4bcf697f78..64d9f2e676 100644
--- a/src/corelib/tools/qstringalgorithms_p.h
+++ b/src/corelib/tools/qstringalgorithms_p.h
@@ -77,7 +77,7 @@ template <typename StringType> struct QStringAlgorithms
if (begin != data)
memmove(data, begin, (end - begin) * sizeof(Char));
str.resize(end - begin);
- return qMove(str);
+ return std::move(str);
}
static inline StringType trimmed_helper_inplace(const NakedStringType &, const Char *, const Char *)
@@ -118,7 +118,7 @@ template <typename StringType> struct QStringAlgorithms
const Char *end = str.cend();
NakedStringType result = isConst || !str.isDetached() ?
StringType(str.size(), Qt::Uninitialized) :
- qMove(str);
+ std::move(str);
Char *dst = const_cast<Char *>(result.cbegin());
Char *ptr = dst;
diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp
index 8afc83819b..cf443ec369 100644
--- a/src/corelib/tools/qstringbuilder.cpp
+++ b/src/corelib/tools/qstringbuilder.cpp
@@ -124,7 +124,7 @@ QT_BEGIN_NAMESPACE
/*!
\internal
*/
-void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out) Q_DECL_NOTHROW
+void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out) noexcept
{
if (Q_UNLIKELY(len == -1)) {
if (!a)
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index 1d96d70637..b3cf2f695e 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -58,12 +58,12 @@ QT_BEGIN_NAMESPACE
struct Q_CORE_EXPORT QAbstractConcatenable
{
protected:
- static void convertFromAscii(const char *a, int len, QChar *&out) Q_DECL_NOTHROW;
- static inline void convertFromAscii(char a, QChar *&out) Q_DECL_NOTHROW
+ static void convertFromAscii(const char *a, int len, QChar *&out) noexcept;
+ static inline void convertFromAscii(char a, QChar *&out) noexcept
{
*out++ = QLatin1Char(a);
}
- static void appendLatin1To(const char *a, int len, QChar *out) Q_DECL_NOTHROW;
+ static void appendLatin1To(const char *a, int len, QChar *out) noexcept;
};
template <typename T> struct QConcatenable {};
@@ -150,7 +150,7 @@ class QStringBuilder <QString, QString> : public QStringBuilderBase<QStringBuild
const QString &b;
private:
- QStringBuilder &operator=(const QStringBuilder &) Q_DECL_EQ_DELETE;
+ QStringBuilder &operator=(const QStringBuilder &) = delete;
};
template <>
@@ -167,7 +167,7 @@ class QStringBuilder <QByteArray, QByteArray> : public QStringBuilderBase<QStrin
const QByteArray &b;
private:
- QStringBuilder &operator=(const QStringBuilder &) Q_DECL_EQ_DELETE;
+ QStringBuilder &operator=(const QStringBuilder &) = delete;
};
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index cf150c2a1b..f6da7b1428 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include <qstringlist.h>
+#include <qregexp.h>
#include <qset.h>
#if QT_CONFIG(regularexpression)
# include <qregularexpression.h>
@@ -376,6 +377,56 @@ bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1String str,
return stringList_contains(*that, str, cs);
}
+/*!
+ \fn bool QStringList::indexOf(QStringView str, int from) const
+ \overload
+ \since 5.13
+
+ Returns the index position of the first occurrence of \a str in
+ the list, searching forward from index position \a from. Returns
+ -1 if no item matched.
+
+ \sa lastIndexOf(), contains()
+ */
+
+/*!
+ \fn bool QStringList::indexOf(QLatin1String str, int from) const
+ \overload
+ \since 5.13
+
+ Returns the index position of the first occurrence of \a str in
+ the list, searching forward from index position \a from. Returns
+ -1 if no item matched.
+
+ \sa lastIndexOf(), contains()
+ */
+
+/*!
+ \fn bool QStringList::lastIndexOf(QStringView str, int from) const
+ \overload
+ \since 5.13
+
+ Returns the index position of the last occurrence of \a str in
+ the list, searching backward from index position \a from. If \a
+ from is -1 (the default), the search starts at the last item.
+ Returns -1 if no item matched.
+
+ \sa indexOf(), contains()
+ */
+
+/*!
+ \fn bool QStringList::lastIndexOf(QLatin1String str, int from) const
+ \overload
+ \since 5.13
+
+ Returns the index position of the last occurrence of \a str in
+ the list, searching backward from index position \a from. If \a
+ from is -1 (the default), the search starts at the last item.
+ Returns -1 if no item matched.
+
+ \sa indexOf(), contains()
+ */
+
#ifndef QT_NO_REGEXP
/*!
\fn QStringList QStringList::filter(const QRegExp &rx) const
@@ -780,7 +831,7 @@ int QtPrivate::QStringList_removeDuplicates(QStringList *that)
continue;
++setSize;
if (j != i)
- that->swap(i, j);
+ that->swapItemsAt(i, j);
++j;
}
if (n != j)
@@ -797,5 +848,12 @@ int QtPrivate::QStringList_removeDuplicates(QStringList *that)
lists.
*/
+ /*! \fn template<typename InputIterator> QStringList::QStringList(InputIterator first, InputIterator last)
+ \since 5.14
+
+ Constructs a QStringList with the contents in the iterator range [\a first, \a last).
+
+ The value type of \c InputIterator must be convertible to \c QString.
+ */
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index 10cbad04d6..3bb657069b 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -44,6 +44,7 @@
#define QSTRINGLIST_H
#include <QtCore/qalgorithms.h>
+#include <QtCore/qcontainertools_impl.h>
#include <QtCore/qregexp.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringmatcher.h>
@@ -66,7 +67,7 @@ template <> struct QListSpecialMethods<QString>
{
#ifndef Q_QDOC
protected:
- ~QListSpecialMethods() {}
+ ~QListSpecialMethods() = default;
#endif
public:
inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive);
@@ -100,22 +101,19 @@ class QStringList : public QList<QString>
{
#endif
public:
- inline QStringList() Q_DECL_NOTHROW { }
+ inline QStringList() noexcept { }
inline explicit QStringList(const QString &i) { append(i); }
inline QStringList(const QList<QString> &l) : QList<QString>(l) { }
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QStringList(QList<QString> &&l) Q_DECL_NOTHROW : QList<QString>(std::move(l)) { }
-#endif
-#ifdef Q_COMPILER_INITIALIZER_LISTS
+ inline QStringList(QList<QString> &&l) noexcept : QList<QString>(std::move(l)) { }
inline QStringList(std::initializer_list<QString> args) : QList<QString>(args) { }
-#endif
+ template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
+ inline QStringList(InputIterator first, InputIterator last)
+ : QList<QString>(first, last) { }
QStringList &operator=(const QList<QString> &other)
{ QList<QString>::operator=(other); return *this; }
-#ifdef Q_COMPILER_RVALUE_REFS
- QStringList &operator=(QList<QString> &&other) Q_DECL_NOTHROW
+ QStringList &operator=(QList<QString> &&other) noexcept
{ QList<QString>::operator=(std::move(other)); return *this; }
-#endif
#if QT_STRINGVIEW_LEVEL < 2
inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -132,6 +130,12 @@ public:
inline QStringList &operator<<(const QList<QString> &l)
{ *this += l; return *this; }
+ inline int indexOf(QStringView str, int from = 0) const;
+ inline int indexOf(QLatin1String str, int from = 0) const;
+
+ inline int lastIndexOf(QStringView str, int from = -1) const;
+ inline int lastIndexOf(QLatin1String str, int from = -1) const;
+
#ifndef QT_NO_REGEXP
inline int indexOf(const QRegExp &rx, int from = 0) const;
inline int lastIndexOf(const QRegExp &rx, int from = -1) const;
@@ -249,6 +253,26 @@ inline QStringList operator+(const QList<QString> &one, const QStringList &other
return n;
}
+inline int QStringList::indexOf(QStringView string, int from) const
+{
+ return QtPrivate::indexOf<QString, QStringView>(*this, string, from);
+}
+
+inline int QStringList::indexOf(QLatin1String string, int from) const
+{
+ return QtPrivate::indexOf<QString, QLatin1String>(*this, string, from);
+}
+
+inline int QStringList::lastIndexOf(QStringView string, int from) const
+{
+ return QtPrivate::lastIndexOf<QString, QStringView>(*this, string, from);
+}
+
+inline int QStringList::lastIndexOf(QLatin1String string, int from) const
+{
+ return QtPrivate::lastIndexOf<QString, QLatin1String>(*this, string, from);
+}
+
#ifndef QT_NO_REGEXP
inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QRegExp &rx, const QString &after)
{
@@ -306,6 +330,23 @@ inline int QStringList::lastIndexOf(const QRegularExpression &rx, int from) cons
#endif // QT_CONFIG(regularexpression)
#endif // Q_QDOC
+//
+// QString inline functions:
+//
+
+QStringList QString::split(const QString &sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
+{ return split(sep, _sb(behavior), cs); }
+QStringList QString::split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
+{ return split(sep, _sb(behavior), cs); }
+#ifndef QT_NO_REGEXP
+QStringList QString::split(const QRegExp &sep, Qt::SplitBehavior behavior) const
+{ return split(sep, _sb(behavior)); }
+#endif
+#if QT_CONFIG(regularexpression)
+QStringList QString::split(const QRegularExpression &sep, Qt::SplitBehavior behavior) const
+{ return split(sep, _sb(behavior)); }
+#endif
+
QT_END_NAMESPACE
#endif // QSTRINGLIST_H
diff --git a/src/corelib/tools/qstringliteral.h b/src/corelib/tools/qstringliteral.h
index 64296b89fc..603f19c0b4 100644
--- a/src/corelib/tools/qstringliteral.h
+++ b/src/corelib/tools/qstringliteral.h
@@ -63,7 +63,7 @@ Q_STATIC_ASSERT_X(sizeof(qunicodechar) == 2,
#define QT_UNICODE_LITERAL(str) u"" str
#define QStringLiteral(str) \
- ([]() Q_DECL_NOEXCEPT -> QString { \
+ ([]() noexcept -> QString { \
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
static const QStaticStringData<Size> qstring_literal = { \
Q_STATIC_STRING_DATA_HEADER_INITIALIZER(Size), \
diff --git a/src/corelib/tools/qstringmatcher.cpp b/src/corelib/tools/qstringmatcher.cpp
index 67d3f0ebc8..167a467480 100644
--- a/src/corelib/tools/qstringmatcher.cpp
+++ b/src/corelib/tools/qstringmatcher.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Mail.ru Group.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -41,43 +42,43 @@
QT_BEGIN_NAMESPACE
-static void bm_init_skiptable(const ushort *uc, int len, uchar *skiptable, Qt::CaseSensitivity cs)
+static void bm_init_skiptable(const ushort *uc, qsizetype len, uchar *skiptable, Qt::CaseSensitivity cs)
{
- int l = qMin(len, 255);
- memset(skiptable, l, 256*sizeof(uchar));
+ int l = int(qMin(len, qsizetype(255)));
+ memset(skiptable, l, 256 * sizeof(uchar));
uc += len - l;
if (cs == Qt::CaseSensitive) {
while (l--) {
skiptable[*uc & 0xff] = l;
- uc++;
+ ++uc;
}
} else {
const ushort *start = uc;
while (l--) {
skiptable[foldCase(uc, start) & 0xff] = l;
- uc++;
+ ++uc;
}
}
}
-static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc, uint pl,
+static inline qsizetype bm_find(const ushort *uc, qsizetype l, qsizetype index, const ushort *puc, qsizetype pl,
const uchar *skiptable, Qt::CaseSensitivity cs)
{
if (pl == 0)
- return index > (int)l ? -1 : index;
- const uint pl_minus_one = pl - 1;
+ return index > l ? -1 : index;
+ const qsizetype pl_minus_one = pl - 1;
const ushort *current = uc + index + pl_minus_one;
const ushort *end = uc + l;
if (cs == Qt::CaseSensitive) {
while (current < end) {
- uint skip = skiptable[*current & 0xff];
+ qsizetype skip = skiptable[*current & 0xff];
if (!skip) {
// possible match
while (skip < pl) {
if (*(current - skip) != puc[pl_minus_one-skip])
break;
- skip++;
+ ++skip;
}
if (skip > pl_minus_one) // we have a match
return (current - uc) - pl_minus_one;
@@ -95,13 +96,13 @@ static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc
}
} else {
while (current < end) {
- uint skip = skiptable[foldCase(current, uc) & 0xff];
+ qsizetype skip = skiptable[foldCase(current, uc) & 0xff];
if (!skip) {
// possible match
while (skip < pl) {
if (foldCase(current - skip, uc) != foldCase(puc + pl_minus_one - skip, puc))
break;
- skip++;
+ ++skip;
}
if (skip > pl_minus_one) // we have a match
return (current - uc) - pl_minus_one;
@@ -148,7 +149,7 @@ static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc
Call setPattern() to give it a pattern to match.
*/
QStringMatcher::QStringMatcher()
- : d_ptr(0), q_cs(Qt::CaseSensitive)
+ : d_ptr(nullptr), q_cs(Qt::CaseSensitive)
{
memset(q_data, 0, sizeof(q_data));
}
@@ -160,7 +161,7 @@ QStringMatcher::QStringMatcher()
Call indexIn() to perform a search.
*/
QStringMatcher::QStringMatcher(const QString &pattern, Qt::CaseSensitivity cs)
- : d_ptr(0), q_pattern(pattern), q_cs(cs)
+ : d_ptr(nullptr), q_pattern(pattern), q_cs(cs)
{
p.uc = pattern.unicode();
p.len = pattern.size();
@@ -175,18 +176,31 @@ QStringMatcher::QStringMatcher(const QString &pattern, Qt::CaseSensitivity cs)
by \a uc with the given \a length and case sensitivity specified by \a cs.
*/
QStringMatcher::QStringMatcher(const QChar *uc, int len, Qt::CaseSensitivity cs)
- : d_ptr(0), q_cs(cs)
+ : QStringMatcher(QStringView(uc, len), cs)
{
- p.uc = uc;
- p.len = len;
- bm_init_skiptable((const ushort *)p.uc, len, p.q_skiptable, cs);
}
/*!
+ \fn QStringMatcher::QStringMatcher(QStringView pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive)
+ \since 5.14
+
+ Constructs a string matcher that will search for \a pattern, with
+ case sensitivity \a cs.
+
+ Call indexIn() to perform a search.
+*/
+QStringMatcher::QStringMatcher(QStringView str, Qt::CaseSensitivity cs)
+ : d_ptr(nullptr), q_cs(cs)
+{
+ p.uc = str.data();
+ p.len = int(str.size());
+ bm_init_skiptable((const ushort *)p.uc, p.len, p.q_skiptable, cs);
+}
+/*!
Copies the \a other string matcher to this string matcher.
*/
QStringMatcher::QStringMatcher(const QStringMatcher &other)
- : d_ptr(0)
+ : d_ptr(nullptr)
{
operator=(other);
}
@@ -267,11 +281,7 @@ void QStringMatcher::setCaseSensitivity(Qt::CaseSensitivity cs)
*/
int QStringMatcher::indexIn(const QString &str, int from) const
{
- if (from < 0)
- from = 0;
- return bm_find((const ushort *)str.unicode(), str.size(), from,
- (const ushort *)p.uc, p.len,
- p.q_skiptable, q_cs);
+ return int(indexIn(QStringView(str), from));
}
/*!
@@ -288,9 +298,25 @@ int QStringMatcher::indexIn(const QString &str, int from) const
*/
int QStringMatcher::indexIn(const QChar *str, int length, int from) const
{
+ return int(indexIn(QStringView(str, length), from));
+}
+
+/*!
+ \since 5.14
+
+ Searches the string \a str from character position \a from
+ (default 0, i.e. from the first character), for the string
+ pattern() that was set in the constructor or in the most recent
+ call to setPattern(). Returns the position where the pattern()
+ matched in \a str, or -1 if no match was found.
+
+ \sa setPattern(), setCaseSensitivity()
+*/
+qsizetype QStringMatcher::indexIn(QStringView str, qsizetype from) const
+{
if (from < 0)
from = 0;
- return bm_find((const ushort *)str, length, from,
+ return bm_find((const ushort *)str.data(), str.size(), from,
(const ushort *)p.uc, p.len,
p.q_skiptable, q_cs);
}
@@ -307,16 +333,16 @@ int QStringMatcher::indexIn(const QChar *str, int length, int from) const
\internal
*/
-int qFindStringBoyerMoore(
- const QChar *haystack, int haystackLen, int haystackOffset,
- const QChar *needle, int needleLen, Qt::CaseSensitivity cs)
+qsizetype qFindStringBoyerMoore(
+ QStringView haystack, qsizetype haystackOffset,
+ QStringView needle, Qt::CaseSensitivity cs)
{
uchar skiptable[256];
- bm_init_skiptable((const ushort *)needle, needleLen, skiptable, cs);
+ bm_init_skiptable((const ushort *)needle.data(), needle.size(), skiptable, cs);
if (haystackOffset < 0)
haystackOffset = 0;
- return bm_find((const ushort *)haystack, haystackLen, haystackOffset,
- (const ushort *)needle, needleLen, skiptable, cs);
+ return bm_find((const ushort *)haystack.data(), haystack.size(), haystackOffset,
+ (const ushort *)needle.data(), needle.size(), skiptable, cs);
}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringmatcher.h b/src/corelib/tools/qstringmatcher.h
index 549bff9f29..6de4353930 100644
--- a/src/corelib/tools/qstringmatcher.h
+++ b/src/corelib/tools/qstringmatcher.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 Mail.ru Group.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -41,6 +42,7 @@
#define QSTRINGMATCHER_H
#include <QtCore/qstring.h>
+#include <QtCore/qstringview.h>
QT_BEGIN_NAMESPACE
@@ -55,6 +57,8 @@ public:
Qt::CaseSensitivity cs = Qt::CaseSensitive);
QStringMatcher(const QChar *uc, int len,
Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QStringMatcher(QStringView pattern,
+ Qt::CaseSensitivity cs = Qt::CaseSensitive);
QStringMatcher(const QStringMatcher &other);
~QStringMatcher();
@@ -65,6 +69,7 @@ public:
int indexIn(const QString &str, int from = 0) const;
int indexIn(const QChar *str, int length, int from = 0) const;
+ qsizetype indexIn(QStringView str, qsizetype from = 0) const;
QString pattern() const;
inline Qt::CaseSensitivity caseSensitivity() const { return q_cs; }
diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/tools/qstringview.cpp
index a7d9426fa6..cc852dd042 100644
--- a/src/corelib/tools/qstringview.cpp
+++ b/src/corelib/tools/qstringview.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qstringview.h"
+#include "qstring.h"
QT_BEGIN_NAMESPACE
@@ -232,9 +233,9 @@ QT_BEGIN_NAMESPACE
The range \c{[str,len)} must remain valid for the lifetime of this string view object.
- Passing \c nullptr as \a str is safe if \a len is 0, too, and results in a null string view.
+ Passing \nullptr as \a str is safe if \a len is 0, too, and results in a null string view.
- The behavior is undefined if \a len is negative or, when positive, if \a str is \c nullptr.
+ The behavior is undefined if \a len is negative or, when positive, if \a str is \nullptr.
This constructor only participates in overload resolution if \c Char is a compatible
character type. The compatible character types are: \c QChar, \c ushort, \c char16_t and
@@ -249,11 +250,11 @@ QT_BEGIN_NAMESPACE
The range \c{[first,last)} must remain valid for the lifetime of
this string view object.
- Passing \c nullptr as \a first is safe if \a last is nullptr, too,
+ Passing \c \nullptr as \a first is safe if \a last is \nullptr, too,
and results in a null string view.
The behavior is undefined if \a last precedes \a first, or \a first
- is \c nullptr and \a last is not.
+ is \nullptr and \a last is not.
This constructor only participates in overload resolution if \c Char
is a compatible character type. The compatible character types
@@ -269,7 +270,7 @@ QT_BEGIN_NAMESPACE
\a str must remain valid for the lifetime of this string view object.
- Passing \c nullptr as \a str is safe and results in a null string view.
+ Passing \nullptr as \a str is safe and results in a null string view.
This constructor only participates in overload resolution if \a
str is not an array and if \c Char is a compatible character
@@ -332,7 +333,7 @@ QT_BEGIN_NAMESPACE
The string view will be empty if and only if \c{str.empty()}. It is unspecified
whether this constructor can result in a null string view (\c{str.data()} would
- have to return \c nullptr for this).
+ have to return \nullptr for this).
\sa isNull(), isEmpty()
*/
@@ -529,6 +530,24 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QString QStringView::arg(Args &&...args) const
+ \fn QString QLatin1String::arg(Args &&...args) const
+ \since 5.14
+
+ Replaces occurrences of \c{%N} in this string with the corresponding
+ argument from \a args. The arguments are not positional: the first of
+ the \a args replaces the \c{%N} with the lowest \c{N} (all of them), the
+ second of the \a args the \c{%N} with the next-lowest \c{N} etc.
+
+ \c Args can consist of anything that implicitly converts to QStringView
+ or QLatin1String.
+
+ In addition, the following types are also supported: QChar, QLatin1Char.
+
+ \sa QString::arg()
+*/
+
+/*!
\fn QChar QStringView::front() const
Returns the first character in the string. Same as first().
@@ -720,6 +739,58 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn qsizetype QStringView::indexOf(QStringView str, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \fn qsizetype QStringView::indexOf(QLatin1String l1, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \fn qsizetype QStringView::indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 5.14
+
+ Returns the index position of the first occurrence of the string-view \a str,
+ Latin-1 string \a l1, or character \a ch, respectively, in this string-view,
+ searching forward from index position \a from. Returns -1 if \a str is not found.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ If \a from is -1, the search starts at the last character; if it is
+ -2, at the next to last character and so on.
+
+ \sa QString::indexOf()
+*/
+
+/*!
+ \fn bool QStringView::contains(QStringView str, Qt::CaseSensitivity cs) const
+ \fn bool QStringView::contains(QLatin1String l1, Qt::CaseSensitivity cs) const
+ \fn bool QStringView::contains(QChar c, Qt::CaseSensitivity cs) const
+ \since 5.14
+
+ Returns \c true if this string-view contains an occurrence of the string-view
+ \a str, Latin-1 string \a l1, or character \a ch; otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (the default), the search is
+ case-sensitive; otherwise the search is case-insensitive.
+
+ \sa indexOf()
+*/
+
+/*!
+ \fn qsizetype QStringView::lastIndexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QStringView::lastIndexOf(QLatin1String l1, qsizetype from, Qt::CaseSensitivity cs) const
+ \fn qsizetype QStringView::lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs) const
+ \since 5.14
+
+ Returns the index position of the last occurrence of the string-view \a str,
+ Latin-1 string \a l1, or character \a ch, respectively, in this string-view,
+ searching backward from index position \a from. If \a from is -1 (default),
+ the search starts at the last character; if \a from is -2, at the next to last
+ character and so on. Returns -1 if \a str is not found.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \sa QString::lastIndexOf()
+*/
+
+/*!
\fn QByteArray QStringView::toLatin1() const
Returns a Latin-1 representation of the string as a QByteArray.
@@ -794,4 +865,34 @@ QT_BEGIN_NAMESPACE
\sa QString::isRightToLeft()
*/
+/*!
+ \since 5.14
+
+ Transcribes this string into the given \a array.
+
+ Caller is responsible for ensuring \a array is large enough to hold the
+ \c wchar_t encoding of this string (allocating the array with the same length
+ as the string is always sufficient). The array is encoded in UTF-16 on
+ platforms where \c wchar_t is 2 bytes wide (e.g. Windows); otherwise (Unix
+ systems), \c wchar_t is assumed to be 4 bytes wide and the data is written
+ in UCS-4.
+
+ \note This function writes no null terminator to the end of \a array.
+
+ Returns the number of \c wchar_t entries written to \a array.
+
+ \sa QString::toWCharArray()
+*/
+
+int QStringView::toWCharArray(wchar_t *array) const
+{
+ if (sizeof(wchar_t) == sizeof(QChar)) {
+ memcpy(array, data(), sizeof(QChar) * size());
+ return size();
+ } else {
+ return QString::toUcs4_helper(reinterpret_cast<const ushort *>(data()), int(size()),
+ reinterpret_cast<uint *>(array));
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h
index 2e95c2b218..b84b2995b9 100644
--- a/src/corelib/tools/qstringview.h
+++ b/src/corelib/tools/qstringview.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Copyright (C) 2019 Mail.ru Group.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -139,13 +140,13 @@ private:
using if_compatible_qstring_like = typename std::enable_if<std::is_same<T, QString>::value || std::is_same<T, QStringRef>::value, bool>::type;
template <typename Char, size_t N>
- static Q_DECL_CONSTEXPR qsizetype lengthHelperArray(const Char (&)[N]) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR qsizetype lengthHelperArray(const Char (&)[N]) noexcept
{
return qsizetype(N - 1);
}
template <typename Char>
- static qsizetype lengthHelperPointer(const Char *str) Q_DECL_NOTHROW
+ static qsizetype lengthHelperPointer(const Char *str) noexcept
{
#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
if (__builtin_constant_p(*str)) {
@@ -157,21 +158,21 @@ private:
#endif
return QtPrivate::qustrlen(reinterpret_cast<const ushort *>(str));
}
- static qsizetype lengthHelperPointer(const QChar *str) Q_DECL_NOTHROW
+ static qsizetype lengthHelperPointer(const QChar *str) noexcept
{
return QtPrivate::qustrlen(reinterpret_cast<const ushort *>(str));
}
template <typename Char>
- static const storage_type *castHelper(const Char *str) Q_DECL_NOTHROW
+ static const storage_type *castHelper(const Char *str) noexcept
{ return reinterpret_cast<const storage_type*>(str); }
- static Q_DECL_CONSTEXPR const storage_type *castHelper(const storage_type *str) Q_DECL_NOTHROW
+ static Q_DECL_CONSTEXPR const storage_type *castHelper(const storage_type *str) noexcept
{ return str; }
public:
- Q_DECL_CONSTEXPR QStringView() Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR QStringView() noexcept
: m_size(0), m_data(nullptr) {}
- Q_DECL_CONSTEXPR QStringView(std::nullptr_t) Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR QStringView(std::nullptr_t) noexcept
: QStringView() {}
template <typename Char, if_compatible_char<Char> = true>
@@ -185,38 +186,38 @@ public:
#ifdef Q_CLANG_QDOC
template <typename Char, size_t N>
- Q_DECL_CONSTEXPR QStringView(const Char (&array)[N]) Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR QStringView(const Char (&array)[N]) noexcept;
template <typename Char>
- Q_DECL_CONSTEXPR QStringView(const Char *str) Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR QStringView(const Char *str) noexcept;
#else
template <typename Array, if_compatible_array<Array> = true>
- Q_DECL_CONSTEXPR QStringView(const Array &str) Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR QStringView(const Array &str) noexcept
: QStringView(str, lengthHelperArray(str)) {}
template <typename Pointer, if_compatible_pointer<Pointer> = true>
- Q_DECL_CONSTEXPR QStringView(const Pointer &str) Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR QStringView(const Pointer &str) noexcept
: QStringView(str, str ? lengthHelperPointer(str) : 0) {}
#endif
#ifdef Q_CLANG_QDOC
- QStringView(const QString &str) Q_DECL_NOTHROW;
- QStringView(const QStringRef &str) Q_DECL_NOTHROW;
+ QStringView(const QString &str) noexcept;
+ QStringView(const QStringRef &str) noexcept;
#else
template <typename String, if_compatible_qstring_like<String> = true>
- QStringView(const String &str) Q_DECL_NOTHROW
+ QStringView(const String &str) noexcept
: QStringView(str.isNull() ? nullptr : str.data(), qsizetype(str.size())) {}
#endif
template <typename StdBasicString, if_compatible_string<StdBasicString> = true>
- QStringView(const StdBasicString &str) Q_DECL_NOTHROW
+ QStringView(const StdBasicString &str) noexcept
: QStringView(str.data(), qsizetype(str.size())) {}
Q_REQUIRED_RESULT inline QString toString() const; // defined in qstring.h
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR qsizetype size() const Q_DECL_NOTHROW { return m_size; }
- Q_REQUIRED_RESULT const_pointer data() const Q_DECL_NOTHROW { return reinterpret_cast<const_pointer>(m_data); }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR const storage_type *utf16() const Q_DECL_NOTHROW { return m_data; }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR qsizetype size() const noexcept { return m_size; }
+ Q_REQUIRED_RESULT const_pointer data() const noexcept { return reinterpret_cast<const_pointer>(m_data); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR const storage_type *utf16() const noexcept { return m_data; }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar operator[](qsizetype n) const
{ return Q_ASSERT(n >= 0), Q_ASSERT(n < size()), QChar(m_data[n]); }
@@ -225,6 +226,9 @@ public:
// QString API
//
+ template <typename...Args>
+ Q_REQUIRED_RESULT inline QString arg(Args &&...args) const; // defined in qstring.h
+
Q_REQUIRED_RESULT QByteArray toLatin1() const { return QtPrivate::convertToLatin1(*this); }
Q_REQUIRED_RESULT QByteArray toUtf8() const { return QtPrivate::convertToUtf8(*this); }
Q_REQUIRED_RESULT QByteArray toLocal8Bit() const { return QtPrivate::convertToLocal8Bit(*this); }
@@ -248,51 +252,71 @@ public:
Q_DECL_RELAXED_CONSTEXPR void chop(qsizetype n)
{ Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size -= n; }
- Q_REQUIRED_RESULT QStringView trimmed() const Q_DECL_NOTHROW { return QtPrivate::trimmed(*this); }
+ Q_REQUIRED_RESULT QStringView trimmed() const noexcept { return QtPrivate::trimmed(*this); }
- Q_REQUIRED_RESULT int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::compareStrings(*this, other, cs); }
- Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); }
- Q_REQUIRED_RESULT inline bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT bool startsWith(QChar c) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ Q_REQUIRED_RESULT bool startsWith(QChar c) const noexcept
{ return !empty() && front() == c; }
- Q_REQUIRED_RESULT bool startsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::startsWith(*this, QStringView(&c, 1), cs); }
- Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::endsWith(*this, s, cs); }
- Q_REQUIRED_RESULT inline bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT bool endsWith(QChar c) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ Q_REQUIRED_RESULT bool endsWith(QChar c) const noexcept
{ return !empty() && back() == c; }
- Q_REQUIRED_RESULT bool endsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
- Q_REQUIRED_RESULT bool isRightToLeft() const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::findString(*this, from, QStringView(&c, 1), cs); }
+ Q_REQUIRED_RESULT qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::findString(*this, from, s, cs); }
+ Q_REQUIRED_RESULT inline qsizetype indexOf(QLatin1String s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+
+ Q_REQUIRED_RESULT bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return indexOf(QStringView(&c, 1), 0, cs) != qsizetype(-1); }
+ Q_REQUIRED_RESULT bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return indexOf(s, 0, cs) != qsizetype(-1); }
+ Q_REQUIRED_RESULT inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+
+ Q_REQUIRED_RESULT qsizetype lastIndexOf(QChar c, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs); }
+ Q_REQUIRED_RESULT qsizetype lastIndexOf(QStringView s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, s, cs); }
+ Q_REQUIRED_RESULT inline qsizetype lastIndexOf(QLatin1String s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+
+ Q_REQUIRED_RESULT bool isRightToLeft() const noexcept
{ return QtPrivate::isRightToLeft(*this); }
+ Q_REQUIRED_RESULT Q_CORE_EXPORT int toWCharArray(wchar_t *array) const;
+
//
// STL compatibility API:
//
- Q_REQUIRED_RESULT const_iterator begin() const Q_DECL_NOTHROW { return data(); }
- Q_REQUIRED_RESULT const_iterator end() const Q_DECL_NOTHROW { return data() + size(); }
- Q_REQUIRED_RESULT const_iterator cbegin() const Q_DECL_NOTHROW { return begin(); }
- Q_REQUIRED_RESULT const_iterator cend() const Q_DECL_NOTHROW { return end(); }
- Q_REQUIRED_RESULT const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- Q_REQUIRED_RESULT const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
- Q_REQUIRED_RESULT const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return rbegin(); }
- Q_REQUIRED_RESULT const_reverse_iterator crend() const Q_DECL_NOTHROW { return rend(); }
-
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool empty() const Q_DECL_NOTHROW { return size() == 0; }
+ Q_REQUIRED_RESULT const_iterator begin() const noexcept { return data(); }
+ Q_REQUIRED_RESULT const_iterator end() const noexcept { return data() + size(); }
+ Q_REQUIRED_RESULT const_iterator cbegin() const noexcept { return begin(); }
+ Q_REQUIRED_RESULT const_iterator cend() const noexcept { return end(); }
+ Q_REQUIRED_RESULT const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ Q_REQUIRED_RESULT const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ Q_REQUIRED_RESULT const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ Q_REQUIRED_RESULT const_reverse_iterator crend() const noexcept { return rend(); }
+
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool empty() const noexcept { return size() == 0; }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar front() const { return Q_ASSERT(!empty()), QChar(m_data[0]); }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar back() const { return Q_ASSERT(!empty()), QChar(m_data[m_size - 1]); }
//
// Qt compatibility API:
//
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool isNull() const Q_DECL_NOTHROW { return !m_data; }
- Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool isEmpty() const Q_DECL_NOTHROW { return empty(); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool isNull() const noexcept { return !m_data; }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool isEmpty() const noexcept { return empty(); }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR int length() const /* not nothrow! */
{ return Q_ASSERT(int(size()) == size()), int(size()); }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar first() const { return front(); }
@@ -306,7 +330,7 @@ Q_DECLARE_TYPEINFO(QStringView, Q_PRIMITIVE_TYPE);
template <typename QStringLike, typename std::enable_if<
std::is_same<QStringLike, QString>::value || std::is_same<QStringLike, QStringRef>::value,
bool>::type = true>
-inline QStringView qToStringViewIgnoringNull(const QStringLike &s) Q_DECL_NOTHROW
+inline QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
{ return QStringView(s.data(), s.size()); }
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qt_attribution.json b/src/corelib/tools/qt_attribution.json
index 912da3f22c..f91742d421 100644
--- a/src/corelib/tools/qt_attribution.json
+++ b/src/corelib/tools/qt_attribution.json
@@ -22,7 +22,7 @@
"Name": "Unicode Common Locale Data Repository (CLDR)",
"QDocModule": "qtcore",
"QtUsage": "Used in Qt Core (QTimeZone, QLocale).",
- "Files": "For update, see qtbase/util/local_database/cldr2qlocalexml.py",
+ "Files": "For update, see qtbase/util/locale_database/cldr2qlocalexml.py",
"Files": "qlocale_data_p.h qtimezoneprivate_data_p.h",
"Description": "The Unicode CLDR provides key building blocks for software to support the
diff --git a/src/corelib/tools/qtimezoneprivate_data_p.h b/src/corelib/tools/qtimezoneprivate_data_p.h
deleted file mode 100644
index 69b9417f19..0000000000
--- a/src/corelib/tools/qtimezoneprivate_data_p.h
+++ /dev/null
@@ -1,1154 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef QTIMEZONEPRIVATE_DATA_P_H
-#define QTIMEZONEPRIVATE_DATA_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of internal files. This header file may change from version to version
-// without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/private/qglobal_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*
- Windows Zone ID support, included in default base class build so can be used on all platforms,
- e.g. an app running on Linux may need to communicate with a Windows Outlook server. These
- tables can also be used to look-up Region Codes and UTC Offsets on platforms that don't directly
- support them., e.g. Mac does not support availableTimeZones() filtering by region or offset.
-
- Another data table is provided for generic UTC+00:00 format time zones to be used as a
- fall-back if no system time zones are available (QT_NO_SYSTEMLOCALE is set) or for QDateTimes
- with a QT:Spec of OffsetFromUTC
-
- These tables are automatically adapted from the CLDR supplemental/windowsZones.xml data file
- using a script in qtbase/util/local_database. Please do not edit this data directly. In the
- future if ICU is made a hard dependency then the ICU resource can be used directly and this
- table removed
-*/
-
-struct QZoneData {
- quint16 windowsIdKey; // Windows ID Key
- quint16 country; // Country of IANA ID's, AnyCountry means No Country
- quint16 ianaIdIndex; // All IANA ID's for the Windows ID and Country, space separated
-};
-
-struct QWindowsData {
- quint16 windowsIdKey; // Windows ID Key
- quint16 windowsIdIndex; // Windows ID Literal
- quint16 ianaIdIndex; // Default IANA ID for the Windows ID
- qint32 offsetFromUtc; // Standard Time Offset from UTC, used for quick look-ups
-};
-
-struct QUtcData {
- quint16 ianaIdIndex; // IANA ID's
- qint32 offsetFromUtc; // Offset form UTC is seconds
-};
-
-/*
- COPYRIGHT AND PERMISSION NOTICE
-
- Copyright © 1991-2012 Unicode, Inc. All rights reserved. Distributed under
- the Terms of Use in http://www.unicode.org/copyright.html.
-
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of the Unicode data files and any associated documentation (the "Data
- Files") or Unicode software and any associated documentation (the "Software")
- to deal in the Data Files or Software without restriction, including without
- limitation the rights to use, copy, modify, merge, publish, distribute, and/or
- sell copies of the Data Files or Software, and to permit persons to whom the
- Data Files or Software are furnished to do so, provided that (a) the above
- copyright notice(s) and this permission notice appear with all copies of the
- Data Files or Software, (b) both the above copyright notice(s) and this
- permission notice appear in associated documentation, and (c) there is clear
- notice in each modified Data File or in the Software as well as in the
- documentation associated with the Data File(s) or Software that the data or
- software has been modified.
-*/
-
-// GENERATED PART STARTS HERE
-
-/*
- This part of the file was generated on 2017-05-23 from the
- Common Locale Data Repository v29 supplemental/windowsZones.xml file $Revision: 12348 $
-
- http://www.unicode.org/cldr/
-
- Do not edit this code: run cldr2qtimezone.py on updated (or
- edited) CLDR data; see qtbase/util/local_database/.
-*/
-
-// Windows ID Key, Country Enum, IANA ID Index
-static const QZoneData zoneDataTable[] = {
- { 22, 57, 0 }, // Central Europe Standard Time / CzechRepublic
- { 69, 139, 14 }, // Pacific Standard Time / Mexico
- { 53, 188, 51 }, // Mauritius Standard Time / Seychelles
- { 50, 122, 63 }, // Libya Standard Time / Libya
- { 79, 38, 78 }, // SA Western Standard Time / Canada
- { 83, 35, 99 }, // South Africa Standard Time / Burundi
- { 102, 205, 116 }, // W. Europe Standard Time / Sweden
- { 89, 213, 133 }, // Tonga Standard Time / Tokelau
- { 77, 76, 149 }, // SA Eastern Standard Time / FrenchGuiana
- { 79, 215, 165 }, // SA Western Standard Time / TrinidadAndTobago
- { 69, 38, 187 }, // Pacific Standard Time / Canada
- { 97, 0, 239 }, // UTC+12 / AnyCountry
- { 19, 65, 250 }, // Central America Standard Time / ElSalvador
- { 82, 101, 270 }, // Singapore Standard Time / Indonesia
- { 37, 248, 284 }, // FLE Standard Time / AlandIslands
- { 16, 0, 301 }, // Cape Verde Standard Time / AnyCountry
- { 97, 220, 311 }, // UTC+12 / Tuvalu
- { 79, 182, 328 }, // SA Western Standard Time / SaintVincentAndTheGrenadines
- { 83, 179, 347 }, // South Africa Standard Time / Rwanda
- { 102, 125, 361 }, // W. Europe Standard Time / Luxembourg
- { 41, 34, 379 }, // Greenwich Standard Time / BurkinaFaso
- { 20, 116, 398 }, // Central Asia Standard Time / Kyrgyzstan
- { 101, 216, 411 }, // W. Central Africa Standard Time / Tunisia
- { 101, 79, 424 }, // W. Central Africa Standard Time / Gabon
- { 19, 96, 442 }, // Central America Standard Time / Honduras
- { 81, 36, 462 }, // SE Asia Standard Time / Cambodia
- { 82, 170, 478 }, // Singapore Standard Time / Philippines
- { 101, 41, 490 }, // W. Central Africa Standard Time / CentralAfricanRepublic
- { 5, 103, 504 }, // Arabic Standard Time / Iraq
- { 72, 21, 517 }, // Romance Standard Time / Belgium
- { 74, 178, 533 }, // Russia Time Zone 10 / Russia
- { 20, 44, 552 }, // Central Asia Standard Time / China
- { 3, 17, 564 }, // Arab Standard Time / Bahrain
- { 88, 62, 577 }, // Tokyo Standard Time / EastTimor
- { 37, 68, 587 }, // FLE Standard Time / Estonia
- { 41, 136, 602 }, // Greenwich Standard Time / Mauritania
- { 83, 49, 620 }, // South Africa Standard Time / CongoKinshasa
- { 72, 74, 638 }, // Romance Standard Time / France
- { 35, 178, 651 }, // Ekaterinburg Standard Time / Russia
- { 32, 16, 670 }, // Eastern Standard Time / Bahamas
- { 94, 30, 685 }, // UTC-02 / Brazil
- { 12, 30, 701 }, // Bahia Standard Time / Brazil
- { 82, 0, 715 }, // Singapore Standard Time / AnyCountry
- { 29, 201, 725 }, // E. Africa Standard Time / Sudan
- { 24, 229, 741 }, // Central Pacific Standard Time / Vanuatu
- { 55, 227, 755 }, // Montevideo Standard Time / Uruguay
- { 79, 233, 774 }, // SA Western Standard Time / BritishVirginIslands
- { 29, 221, 790 }, // E. Africa Standard Time / Uganda
- { 101, 6, 805 }, // W. Central Africa Standard Time / Angola
- { 68, 141, 819 }, // E. Europe Standard Time / Moldova
- { 51, 112, 835 }, // Line Islands Standard Time / Kiribati
- { 89, 0, 854 }, // Tonga Standard Time / AnyCountry
- { 79, 61, 865 }, // SA Western Standard Time / DominicanRepublic
- { 39, 75, 887 }, // GMT Standard Time / Guernsey
- { 37, 222, 903 }, // FLE Standard Time / Ukraine
- { 83, 28, 949 }, // South Africa Standard Time / Botswana
- { 82, 130, 965 }, // Singapore Standard Time / Malaysia
- { 95, 4, 996 }, // UTC-11 / AmericanSamoa
- { 41, 189, 1014 }, // Greenwich Standard Time / SierraLeone
- { 29, 194, 1030 }, // E. Africa Standard Time / Somalia
- { 94, 196, 1047 }, // UTC-02 / SouthGeorgiaAndTheSouthSandwichIslands
- { 96, 0, 1070 }, // UTC / AnyCountry
- { 101, 37, 1078 }, // W. Central Africa Standard Time / Cameroon
- { 13, 25, 1092 }, // Bangladesh Standard Time / Bhutan
- { 102, 151, 1105 }, // W. Europe Standard Time / Netherlands
- { 37, 118, 1122 }, // FLE Standard Time / Latvia
- { 29, 48, 1134 }, // E. Africa Standard Time / Comoros
- { 60, 178, 1148 }, // N. Central Asia Standard Time / Russia
- { 81, 117, 1175 }, // SE Asia Standard Time / Laos
- { 22, 242, 1190 }, // Central Europe Standard Time / Montenegro
- { 37, 33, 1207 }, // FLE Standard Time / Bulgaria
- { 11, 173, 1220 }, // Azores Standard Time / Portugal
- { 97, 149, 1236 }, // UTC+12 / Nauru
- { 83, 146, 1250 }, // South Africa Standard Time / Mozambique
- { 102, 82, 1264 }, // W. Europe Standard Time / Germany
- { 79, 255, 1294 }, // SA Western Standard Time / Bonaire
- { 24, 153, 1313 }, // Central Pacific Standard Time / NewCaledonia
- { 45, 102, 1328 }, // Iran Standard Time / Iran
- { 13, 18, 1340 }, // Bangladesh Standard Time / Bangladesh
- { 69, 225, 1351 }, // Pacific Standard Time / UnitedStates
- { 102, 142, 1371 }, // W. Europe Standard Time / Monaco
- { 29, 128, 1385 }, // E. Africa Standard Time / Madagascar
- { 65, 178, 1405 }, // North Asia East Standard Time / Russia
- { 20, 8, 1418 }, // Central Asia Standard Time / Antarctica
- { 22, 2, 1436 }, // Central Europe Standard Time / Albania
- { 79, 87, 1450 }, // SA Western Standard Time / Grenada
- { 81, 0, 1466 }, // SE Asia Standard Time / AnyCountry
- { 39, 173, 1476 }, // GMT Standard Time / Portugal
- { 103, 228, 1507 }, // West Asia Standard Time / Uzbekistan
- { 58, 139, 1536 }, // Mountain Standard Time / Mexico
- { 83, 129, 1552 }, // South Africa Standard Time / Malawi
- { 78, 107, 1568 }, // SA Pacific Standard Time / Jamaica
- { 41, 91, 1584 }, // Greenwich Standard Time / Guinea
- { 101, 49, 1599 }, // W. Central Africa Standard Time / CongoKinshasa
- { 43, 226, 1615 }, // Hawaiian Standard Time / UnitedStatesMinorOutlyingIslands
- { 77, 8, 1632 }, // SA Eastern Standard Time / Antarctica
- { 97, 235, 1651 }, // UTC+12 / WallisAndFutunaIslands
- { 81, 232, 1666 }, // SE Asia Standard Time / Vietnam
- { 34, 64, 1678 }, // Egypt Standard Time / Egypt
- { 102, 106, 1691 }, // W. Europe Standard Time / Italy
- { 79, 256, 1703 }, // SA Western Standard Time / SintMaarten
- { 59, 147, 1725 }, // Myanmar Standard Time / Myanmar
- { 78, 166, 1738 }, // SA Pacific Standard Time / Panama
- { 56, 236, 1753 }, // Morocco Standard Time / WesternSahara
- { 24, 193, 1769 }, // Central Pacific Standard Time / SolomonIslands
- { 48, 178, 1789 }, // Kaliningrad Standard Time / Russia
- { 47, 109, 1808 }, // Jordan Standard Time / Jordan
- { 42, 177, 1819 }, // GTB Standard Time / Romania
- { 41, 92, 1836 }, // Greenwich Standard Time / GuineaBissau
- { 102, 184, 1850 }, // W. Europe Standard Time / SanMarino
- { 103, 209, 1868 }, // West Asia Standard Time / Tajikistan
- { 75, 178, 1882 }, // Russia Time Zone 11 / Russia
- { 101, 157, 1909 }, // W. Central Africa Standard Time / Nigeria
- { 79, 152, 1922 }, // SA Western Standard Time / CuraSao
- { 57, 139, 1938 }, // Mountain Standard Time (Mexico) / Mexico
- { 4, 162, 1973 }, // Arabian Standard Time / Oman
- { 78, 169, 1985 }, // SA Pacific Standard Time / Peru
- { 102, 206, 1998 }, // W. Europe Standard Time / Switzerland
- { 41, 99, 2012 }, // Greenwich Standard Time / Iceland
- { 33, 139, 2031 }, // Eastern Standard Time (Mexico) / Mexico
- { 58, 225, 2046 }, // Mountain Standard Time / UnitedStates
- { 100, 8, 2075 }, // W. Australia Standard Time / Antarctica
- { 79, 30, 2092 }, // SA Western Standard Time / Brazil
- { 101, 23, 2145 }, // W. Central Africa Standard Time / Benin
- { 78, 43, 2163 }, // SA Pacific Standard Time / Chile
- { 104, 0, 2178 }, // West Pacific Standard Time / AnyCountry
- { 79, 181, 2189 }, // SA Western Standard Time / SaintLucia
- { 27, 126, 2206 }, // China Standard Time / Macau
- { 101, 66, 2217 }, // W. Central Africa Standard Time / EquatorialGuinea
- { 43, 51, 2231 }, // Hawaiian Standard Time / CookIslands
- { 41, 80, 2249 }, // Greenwich Standard Time / Gambia
- { 51, 0, 2263 }, // Line Islands Standard Time / AnyCountry
- { 52, 178, 2274 }, // Magadan Standard Time / Russia
- { 22, 191, 2287 }, // Central Europe Standard Time / Slovakia
- { 102, 5, 2305 }, // W. Europe Standard Time / Andorra
- { 81, 211, 2320 }, // SE Asia Standard Time / Thailand
- { 103, 0, 2333 }, // West Asia Standard Time / AnyCountry
- { 24, 167, 2343 }, // Central Pacific Standard Time / PapuaNewGuinea
- { 102, 230, 2364 }, // W. Europe Standard Time / VaticanCityState
- { 58, 38, 2379 }, // Mountain Standard Time / Canada
- { 77, 202, 2453 }, // SA Eastern Standard Time / Suriname
- { 9, 13, 2472 }, // AUS Eastern Standard Time / Australia
- { 29, 210, 2509 }, // E. Africa Standard Time / Tanzania
- { 58, 0, 2530 }, // Mountain Standard Time / AnyCountry
- { 83, 120, 2538 }, // South Africa Standard Time / Lesotho
- { 97, 134, 2552 }, // UTC+12 / MarshallIslands
- { 29, 111, 2585 }, // E. Africa Standard Time / Kenya
- { 103, 218, 2600 }, // West Asia Standard Time / Turkmenistan
- { 27, 97, 2614 }, // China Standard Time / HongKong
- { 29, 0, 2629 }, // E. Africa Standard Time / AnyCountry
- { 19, 22, 2639 }, // Central America Standard Time / Belize
- { 31, 30, 2654 }, // E. South America Standard Time / Brazil
- { 72, 197, 2672 }, // Romance Standard Time / Spain
- { 81, 101, 2699 }, // SE Asia Standard Time / Indonesia
- { 88, 0, 2727 }, // Tokyo Standard Time / AnyCountry
- { 2, 225, 2737 }, // Alaskan Standard Time / UnitedStates
- { 72, 58, 2832 }, // Romance Standard Time / Denmark
- { 63, 8, 2850 }, // New Zealand Standard Time / Antarctica
- { 3, 175, 2869 }, // Arab Standard Time / Qatar
- { 79, 245, 2880 }, // SA Western Standard Time / Saint Martin
- { 79, 19, 2896 }, // SA Western Standard Time / Barbados
- { 97, 226, 2913 }, // UTC+12 / UnitedStatesMinorOutlyingIslands
- { 37, 73, 2926 }, // FLE Standard Time / Finland
- { 29, 138, 2942 }, // E. Africa Standard Time / Mayotte
- { 39, 71, 2957 }, // GMT Standard Time / FaroeIslands
- { 78, 38, 2973 }, // SA Pacific Standard Time / Canada
- { 43, 0, 2995 }, // Hawaiian Standard Time / AnyCountry
- { 23, 27, 3006 }, // Central European Standard Time / BosniaAndHerzegowina
- { 38, 81, 3022 }, // Georgian Standard Time / Georgia
- { 95, 0, 3035 }, // UTC-11 / AnyCountry
- { 24, 13, 3046 }, // Central Pacific Standard Time / Australia
- { 104, 167, 3067 }, // West Pacific Standard Time / PapuaNewGuinea
- { 71, 168, 3088 }, // Paraguay Standard Time / Paraguay
- { 43, 77, 3105 }, // Hawaiian Standard Time / FrenchPolynesia
- { 41, 212, 3120 }, // Greenwich Standard Time / Togo
- { 39, 197, 3132 }, // GMT Standard Time / Spain
- { 83, 195, 3148 }, // South Africa Standard Time / SouthAfrica
- { 18, 13, 3168 }, // Cen. Australia Standard Time / Australia
- { 104, 160, 3209 }, // West Pacific Standard Time / NorthernMarianaIslands
- { 77, 70, 3224 }, // SA Eastern Standard Time / FalklandIslands
- { 42, 56, 3241 }, // GTB Standard Time / Cyprus
- { 4, 223, 3254 }, // Arabian Standard Time / UnitedArabEmirates
- { 103, 78, 3265 }, // West Asia Standard Time / FrenchSouthernTerritories
- { 101, 42, 3282 }, // W. Central Africa Standard Time / Chad
- { 23, 127, 3298 }, // Central European Standard Time / Macedonia
- { 3, 237, 3312 }, // Arab Standard Time / Yemen
- { 80, 183, 3322 }, // Samoa Standard Time / Samoa
- { 43, 225, 3335 }, // Hawaiian Standard Time / UnitedStates
- { 28, 0, 3352 }, // Dateline Standard Time / AnyCountry
- { 93, 139, 3363 }, // US Mountain Standard Time / Mexico
- { 64, 38, 3382 }, // Newfoundland Standard Time / Canada
- { 63, 154, 3399 }, // New Zealand Standard Time / NewZealand
- { 76, 178, 3416 }, // Russian Standard Time / Russia
- { 82, 190, 3465 }, // Singapore Standard Time / Singapore
- { 1, 1, 3480 }, // Afghanistan Standard Time / Afghanistan
- { 102, 133, 3491 }, // W. Europe Standard Time / Malta
- { 79, 12, 3504 }, // SA Western Standard Time / Aruba
- { 25, 139, 3518 }, // Central Standard Time (Mexico) / Mexico
- { 39, 251, 3594 }, // GMT Standard Time / IsleOfMan
- { 102, 123, 3613 }, // W. Europe Standard Time / Liechtenstein
- { 77, 30, 3626 }, // SA Eastern Standard Time / Brazil
- { 49, 114, 3723 }, // Korea Standard Time / SouthKorea
- { 79, 88, 3734 }, // SA Western Standard Time / Guadeloupe
- { 94, 0, 3753 }, // UTC-02 / AnyCountry
- { 59, 46, 3763 }, // Myanmar Standard Time / CocosIslands
- { 102, 203, 3776 }, // W. Europe Standard Time / SvalbardAndJanMayenIslands
- { 29, 69, 3796 }, // E. Africa Standard Time / Ethiopia
- { 73, 178, 3815 }, // Russia Time Zone 3 / Russia
- { 83, 240, 3829 }, // South Africa Standard Time / Zimbabwe
- { 100, 13, 3843 }, // W. Australia Standard Time / Australia
- { 101, 0, 3859 }, // W. Central Africa Standard Time / AnyCountry
- { 32, 55, 3869 }, // Eastern Standard Time / Cuba
- { 56, 145, 3884 }, // Morocco Standard Time / Morocco
- { 17, 11, 3902 }, // Caucasus Standard Time / Armenia
- { 7, 24, 3915 }, // Atlantic Standard Time / Bermuda
- { 86, 208, 3932 }, // Taipei Standard Time / Taiwan
- { 20, 0, 3944 }, // Central Asia Standard Time / AnyCountry
- { 40, 86, 3954 }, // Greenland Standard Time / Greenland
- { 23, 172, 3970 }, // Central European Standard Time / Poland
- { 89, 214, 3984 }, // Tonga Standard Time / Tonga
- { 20, 110, 4002 }, // Central Asia Standard Time / Kazakhstan
- { 81, 8, 4029 }, // SE Asia Standard Time / Antarctica
- { 54, 119, 4046 }, // Middle East Standard Time / Lebanon
- { 19, 90, 4058 }, // Central America Standard Time / Guatemala
- { 70, 163, 4076 }, // Pakistan Standard Time / Pakistan
- { 41, 83, 4089 }, // Greenwich Standard Time / Ghana
- { 79, 174, 4102 }, // SA Western Standard Time / PuertoRico
- { 79, 26, 4122 }, // SA Western Standard Time / Bolivia
- { 32, 225, 4137 }, // Eastern Standard Time / UnitedStates
- { 85, 207, 4294 }, // Syria Standard Time / Syria
- { 97, 112, 4308 }, // UTC+12 / Kiribati
- { 79, 0, 4323 }, // SA Western Standard Time / AnyCountry
- { 78, 47, 4333 }, // SA Pacific Standard Time / Colombia
- { 16, 39, 4348 }, // Cape Verde Standard Time / CapeVerde
- { 8, 13, 4368 }, // AUS Central Standard Time / Australia
- { 106, 113, 4385 }, // North Korea Standard Time / NorthKorea
- { 10, 15, 4400 }, // Azerbaijan Standard Time / Azerbaijan
- { 102, 84, 4410 }, // W. Europe Standard Time / Gibraltar
- { 46, 105, 4427 }, // Israel Standard Time / Israel
- { 22, 192, 4442 }, // Central Europe Standard Time / Slovenia
- { 24, 159, 4459 }, // Central Pacific Standard Time / NorfolkIsland
- { 82, 32, 4475 }, // Singapore Standard Time / Brunei
- { 101, 50, 4487 }, // W. Central Africa Standard Time / CongoBrazzaville
- { 62, 150, 4506 }, // Nepal Standard Time / Nepal
- { 44, 100, 4520 }, // India Standard Time / India
- { 79, 9, 4534 }, // SA Western Standard Time / AntiguaAndBarbuda
- { 39, 252, 4550 }, // GMT Standard Time / Jersey
- { 79, 144, 4564 }, // SA Western Standard Time / Montserrat
- { 93, 0, 4583 }, // US Mountain Standard Time / AnyCountry
- { 79, 93, 4593 }, // SA Western Standard Time / Guyana
- { 41, 187, 4608 }, // Greenwich Standard Time / Senegal
- { 102, 161, 4621 }, // W. Europe Standard Time / Norway
- { 42, 85, 4633 }, // GTB Standard Time / Greece
- { 3, 115, 4647 }, // Arab Standard Time / Kuwait
- { 24, 140, 4659 }, // Central Pacific Standard Time / Micronesia
- { 19, 52, 4689 }, // Central America Standard Time / CostaRica
- { 79, 60, 4708 }, // SA Western Standard Time / Dominica
- { 83, 204, 4725 }, // South Africa Standard Time / Swaziland
- { 79, 135, 4740 }, // SA Western Standard Time / Martinique
- { 53, 176, 4759 }, // Mauritius Standard Time / Reunion
- { 19, 0, 4774 }, // Central America Standard Time / AnyCountry
- { 90, 217, 4784 }, // Turkey Standard Time / Turkey
- { 66, 178, 4800 }, // North Asia Standard Time / Russia
- { 41, 53, 4835 }, // Greenwich Standard Time / IvoryCoast
- { 78, 30, 4850 }, // SA Pacific Standard Time / Brazil
- { 26, 0, 4886 }, // Central Standard Time / AnyCountry
- { 93, 225, 4894 }, // US Mountain Standard Time / UnitedStates
- { 15, 38, 4910 }, // Canada Central Standard Time / Canada
- { 78, 0, 4947 }, // SA Pacific Standard Time / AnyCountry
- { 103, 8, 4957 }, // West Asia Standard Time / Antarctica
- { 103, 131, 4975 }, // West Asia Standard Time / Maldives
- { 22, 243, 4991 }, // Central Europe Standard Time / Serbia
- { 29, 67, 5007 }, // E. Africa Standard Time / Eritrea
- { 93, 38, 5021 }, // US Mountain Standard Time / Canada
- { 22, 98, 5078 }, // Central Europe Standard Time / Hungary
- { 61, 148, 5094 }, // Namibia Standard Time / Namibia
- { 88, 101, 5110 }, // Tokyo Standard Time / Indonesia
- { 30, 13, 5124 }, // E. Australia Standard Time / Australia
- { 4, 0, 5162 }, // Arabian Standard Time / AnyCountry
- { 98, 231, 5172 }, // Venezuela Standard Time / Venezuela
- { 29, 8, 5188 }, // E. Africa Standard Time / Antarctica
- { 23, 54, 5205 }, // Central European Standard Time / Croatia
- { 6, 10, 5219 }, // Argentina Standard Time / Argentina
- { 67, 8, 5492 }, // Pacific SA Standard Time / Antarctica
- { 32, 38, 5510 }, // Eastern Standard Time / Canada
- { 41, 132, 5615 }, // Greenwich Standard Time / Mali
- { 3, 186, 5629 }, // Arab Standard Time / SaudiArabia
- { 104, 140, 5641 }, // West Pacific Standard Time / Micronesia
- { 88, 108, 5654 }, // Tokyo Standard Time / Japan
- { 89, 112, 5665 }, // Tonga Standard Time / Kiribati
- { 39, 224, 5683 }, // GMT Standard Time / UnitedKingdom
- { 92, 225, 5697 }, // US Eastern Standard Time / UnitedStates
- { 84, 198, 5764 }, // Sri Lanka Standard Time / SriLanka
- { 26, 38, 5777 }, // Central Standard Time / Canada
- { 29, 59, 5852 }, // E. Africa Standard Time / Djibouti
- { 7, 38, 5868 }, // Atlantic Standard Time / Canada
- { 41, 185, 5936 }, // Greenwich Standard Time / SaoTomeAndPrincipe
- { 79, 234, 5952 }, // SA Western Standard Time / UnitedStatesVirginIslands
- { 83, 239, 5970 }, // South Africa Standard Time / Zambia
- { 32, 94, 5984 }, // Eastern Standard Time / Haiti
- { 101, 156, 6007 }, // W. Central Africa Standard Time / Niger
- { 77, 0, 6021 }, // SA Eastern Standard Time / AnyCountry
- { 101, 3, 6031 }, // W. Central Africa Standard Time / Algeria
- { 78, 63, 6046 }, // SA Pacific Standard Time / Ecuador
- { 20, 31, 6064 }, // Central Asia Standard Time / BritishIndianOceanTerritory
- { 27, 44, 6078 }, // China Standard Time / China
- { 21, 30, 6092 }, // Central Brazilian Standard Time / Brazil
- { 95, 226, 6128 }, // UTC-11 / UnitedStatesMinorOutlyingIslands
- { 32, 0, 6143 }, // Eastern Standard Time / AnyCountry
- { 81, 45, 6151 }, // SE Asia Standard Time / ChristmasIsland
- { 19, 63, 6168 }, // Central America Standard Time / Ecuador
- { 79, 7, 6186 }, // SA Western Standard Time / Anguilla
- { 78, 40, 6203 }, // SA Pacific Standard Time / CaymanIslands
- { 79, 180, 6218 }, // SA Western Standard Time / SaintKittsAndNevis
- { 67, 43, 6235 }, // Pacific SA Standard Time / Chile
- { 88, 164, 6252 }, // Tokyo Standard Time / Palau
- { 105, 178, 6266 }, // Yakutsk Standard Time / Russia
- { 37, 124, 6304 }, // FLE Standard Time / Lithuania
- { 41, 121, 6319 }, // Greenwich Standard Time / Liberia
- { 104, 89, 6335 }, // West Pacific Standard Time / Guam
- { 96, 86, 6348 }, // UTC / Greenland
- { 36, 72, 6369 }, // Fiji Standard Time / Fiji
- { 19, 155, 6382 }, // Central America Standard Time / Nicaragua
- { 11, 86, 6398 }, // Azores Standard Time / Greenland
- { 79, 244, 6419 }, // SA Western Standard Time / Saint Barthelemy
- { 69, 0, 6441 }, // Pacific Standard Time / AnyCountry
- { 79, 219, 6449 }, // SA Western Standard Time / TurksAndCaicosIslands
- { 103, 110, 6468 }, // West Asia Standard Time / Kazakhstan
- { 26, 225, 6501 }, // Central Standard Time / UnitedStates
- { 26, 139, 6669 }, // Central Standard Time / Mexico
- { 7, 86, 6687 }, // Atlantic Standard Time / Greenland
- { 24, 0, 6701 }, // Central Pacific Standard Time / AnyCountry
- { 41, 199, 6712 }, // Greenwich Standard Time / SaintHelena
- { 95, 158, 6731 }, // UTC-11 / Niue
- { 53, 137, 6744 }, // Mauritius Standard Time / Mauritius
- { 91, 143, 6761 }, // Ulaanbaatar Standard Time / Mongolia
- { 83, 0, 6794 }, // South Africa Standard Time / AnyCountry
- { 14, 20, 6804 }, // Belarus Standard Time / Belarus
- { 29, 254, 6817 }, // E. Africa Standard Time / SouthSudan
- { 87, 13, 6829 }, // Tasmania Standard Time / Australia
- { 99, 178, 6863 }, // Vladivostok Standard Time / Russia
- { 104, 8, 6908 }, // West Pacific Standard Time / Antarctica
- { 39, 104, 6934 }, // GMT Standard Time / Ireland
- { 102, 14, 6948 }, // W. Europe Standard Time / Austria
- { 0, 0, 0 } // Trailing zeroes
-};
-
-// Windows ID Key, Windows ID Index, IANA ID Index, UTC Offset
-static const QWindowsData windowsDataTable[] = {
- { 1, 0, 3480, 16200 }, // Afghanistan Standard Time
- { 2, 26, 6962,-32400 }, // Alaskan Standard Time
- { 3, 48, 5629, 10800 }, // Arab Standard Time
- { 4, 67, 3254, 14400 }, // Arabian Standard Time
- { 5, 89, 504, 10800 }, // Arabic Standard Time
- { 6, 110, 6980,-10800 }, // Argentina Standard Time
- { 7, 134, 7001,-14400 }, // Atlantic Standard Time
- { 8, 157, 4368, 34200 }, // AUS Central Standard Time
- { 9, 183, 7017, 36000 }, // AUS Eastern Standard Time
- { 10, 209, 4400, 14400 }, // Azerbaijan Standard Time
- { 11, 234, 1220, -3600 }, // Azores Standard Time
- { 12, 255, 701,-10800 }, // Bahia Standard Time
- { 13, 275, 1340, 21600 }, // Bangladesh Standard Time
- { 14, 300, 6804, 10800 }, // Belarus Standard Time
- { 15, 322, 7034,-21600 }, // Canada Central Standard Time
- { 16, 351, 4348, -3600 }, // Cape Verde Standard Time
- { 17, 376, 3902, 14400 }, // Caucasus Standard Time
- { 18, 399, 7049, 34200 }, // Cen. Australia Standard Time
- { 19, 428, 4058,-21600 }, // Central America Standard Time
- { 20, 458, 7068, 21600 }, // Central Asia Standard Time
- { 21, 485, 7080,-14400 }, // Central Brazilian Standard Time
- { 22, 517, 5078, 3600 }, // Central Europe Standard Time
- { 23, 546, 3970, 3600 }, // Central European Standard Time
- { 24, 577, 1769, 39600 }, // Central Pacific Standard Time
- { 25, 607, 7095,-21600 }, // Central Standard Time (Mexico)
- { 26, 638, 7115,-21600 }, // Central Standard Time
- { 27, 660, 6078, 28800 }, // China Standard Time
- { 28, 680, 3352,-43200 }, // Dateline Standard Time
- { 29, 703, 2585, 10800 }, // E. Africa Standard Time
- { 30, 727, 7131, 36000 }, // E. Australia Standard Time
- { 31, 754, 2654,-10800 }, // E. South America Standard Time
- { 32, 785, 7150,-18000 }, // Eastern Standard Time
- { 33, 807, 2031,-18000 }, // Eastern Standard Time (Mexico)
- { 34, 838, 1678, 7200 }, // Egypt Standard Time
- { 35, 858, 651, 18000 }, // Ekaterinburg Standard Time
- { 36, 885, 6369, 43200 }, // Fiji Standard Time
- { 37, 904, 7167, 7200 }, // FLE Standard Time
- { 38, 922, 3022, 14400 }, // Georgian Standard Time
- { 39, 945, 5683, 0 }, // GMT Standard Time
- { 40, 963, 3954,-10800 }, // Greenland Standard Time
- { 41, 987, 2012, 0 }, // Greenwich Standard Time
- { 42, 1011, 1819, 7200 }, // GTB Standard Time
- { 43, 1029, 3335,-36000 }, // Hawaiian Standard Time
- { 44, 1052, 4520, 19800 }, // India Standard Time
- { 45, 1072, 1328, 12600 }, // Iran Standard Time
- { 46, 1091, 4427, 7200 }, // Israel Standard Time
- { 47, 1112, 1808, 7200 }, // Jordan Standard Time
- { 48, 1133, 1789, 7200 }, // Kaliningrad Standard Time
- { 49, 1159, 3723, 32400 }, // Korea Standard Time
- { 50, 1179, 63, 7200 }, // Libya Standard Time
- { 51, 1199, 835, 50400 }, // Line Islands Standard Time
- { 52, 1226, 2274, 36000 }, // Magadan Standard Time
- { 53, 1248, 6744, 14400 }, // Mauritius Standard Time
- { 54, 1272, 4046, 7200 }, // Middle East Standard Time
- { 55, 1298, 755,-10800 }, // Montevideo Standard Time
- { 56, 1323, 3884, 0 }, // Morocco Standard Time
- { 57, 1345, 7179,-25200 }, // Mountain Standard Time (Mexico)
- { 58, 1377, 7197,-25200 }, // Mountain Standard Time
- { 59, 1400, 1725, 23400 }, // Myanmar Standard Time
- { 60, 1422, 7212, 21600 }, // N. Central Asia Standard Time
- { 61, 1452, 5094, 3600 }, // Namibia Standard Time
- { 62, 1474, 4506, 20700 }, // Nepal Standard Time
- { 63, 1494, 3399, 43200 }, // New Zealand Standard Time
- { 64, 1520, 3382,-12600 }, // Newfoundland Standard Time
- { 65, 1547, 1405, 28800 }, // North Asia East Standard Time
- { 66, 1577, 7229, 25200 }, // North Asia Standard Time
- { 67, 1602, 6235,-10800 }, // Pacific SA Standard Time
- { 68, 1627, 819, 7200 }, // E. Europe Standard Time
- { 69, 1651, 1351,-28800 }, // Pacific Standard Time
- { 70, 1673, 4076, 18000 }, // Pakistan Standard Time
- { 71, 1696, 3088,-14400 }, // Paraguay Standard Time
- { 72, 1719, 638, 3600 }, // Romance Standard Time
- { 73, 1741, 3815, 14400 }, // Russia Time Zone 3
- { 74, 1760, 533, 39600 }, // Russia Time Zone 10
- { 75, 1780, 7246, 43200 }, // Russia Time Zone 11
- { 76, 1800, 7261, 10800 }, // Russian Standard Time
- { 77, 1822, 149,-10800 }, // SA Eastern Standard Time
- { 78, 1847, 4333,-18000 }, // SA Pacific Standard Time
- { 79, 1872, 4122,-14400 }, // SA Western Standard Time
- { 80, 1897, 3322, 46800 }, // Samoa Standard Time
- { 81, 1917, 2320, 25200 }, // SE Asia Standard Time
- { 82, 1939, 3465, 28800 }, // Singapore Standard Time
- { 83, 1963, 3148, 7200 }, // South Africa Standard Time
- { 84, 1990, 5764, 19800 }, // Sri Lanka Standard Time
- { 85, 2014, 4294, 7200 }, // Syria Standard Time
- { 86, 2034, 3932, 28800 }, // Taipei Standard Time
- { 87, 2055, 7275, 36000 }, // Tasmania Standard Time
- { 88, 2078, 5654, 32400 }, // Tokyo Standard Time
- { 89, 2098, 3984, 46800 }, // Tonga Standard Time
- { 90, 2118, 4784, 7200 }, // Turkey Standard Time
- { 91, 2139, 7292, 28800 }, // Ulaanbaatar Standard Time
- { 92, 2165, 7309,-18000 }, // US Eastern Standard Time
- { 93, 2190, 4894,-25200 }, // US Mountain Standard Time
- { 94, 2216, 3753, -7200 }, // UTC-02
- { 95, 2223, 3035,-39600 }, // UTC-11
- { 96, 2230, 1070, 0 }, // UTC
- { 97, 2234, 239, 43200 }, // UTC+12
- { 98, 2241, 5172,-16200 }, // Venezuela Standard Time
- { 99, 2265, 7330, 36000 }, // Vladivostok Standard Time
- { 100, 2291, 3843, 28800 }, // W. Australia Standard Time
- { 101, 2318, 1909, 3600 }, // W. Central Africa Standard Time
- { 102, 2350, 7347, 3600 }, // W. Europe Standard Time
- { 103, 2374, 7361, 18000 }, // West Asia Standard Time
- { 104, 2398, 3067, 36000 }, // West Pacific Standard Time
- { 105, 2425, 7375, 32400 }, // Yakutsk Standard Time
- { 106, 2447, 4385, 30600 }, // North Korea Standard Time
- { 0, 0, 0, 0 } // Trailing zeroes
-};
-
-// IANA ID Index, UTC Offset
-static const QUtcData utcDataTable[] = {
- { 7388, 0 }, // UTC
- { 7392,-50400 }, // UTC-14:00
- { 7402,-46800 }, // UTC-13:00
- { 7412,-43200 }, // UTC-12:00
- { 7422,-39600 }, // UTC-11:00
- { 7432,-36000 }, // UTC-10:00
- { 7442,-32400 }, // UTC-09:00
- { 7452,-28800 }, // UTC-08:00
- { 7462,-25200 }, // UTC-07:00
- { 7472,-21600 }, // UTC-06:00
- { 7482,-18000 }, // UTC-05:00
- { 7492,-16200 }, // UTC-04:30
- { 7502,-14400 }, // UTC-04:00
- { 7512,-12600 }, // UTC-03:30
- { 7522,-10800 }, // UTC-03:00
- { 7532, -7200 }, // UTC-02:00
- { 7542, -3600 }, // UTC-01:00
- { 7552, 0 }, // UTC-00:00
- { 7562, 0 }, // UTC+00:00
- { 7572, 3600 }, // UTC+01:00
- { 7582, 7200 }, // UTC+02:00
- { 7592, 10800 }, // UTC+03:00
- { 7602, 12600 }, // UTC+03:30
- { 7612, 14400 }, // UTC+04:00
- { 7622, 16200 }, // UTC+04:30
- { 7632, 18000 }, // UTC+05:00
- { 7642, 19800 }, // UTC+05:30
- { 7652, 20700 }, // UTC+05:45
- { 7662, 21600 }, // UTC+06:00
- { 7672, 23400 }, // UTC+06:30
- { 7682, 25200 }, // UTC+07:00
- { 7692, 28800 }, // UTC+08:00
- { 7702, 32400 }, // UTC+09:00
- { 7712, 34200 }, // UTC+09:30
- { 7722, 36000 }, // UTC+10:00
- { 7732, 39600 }, // UTC+11:00
- { 7742, 43200 }, // UTC+12:00
- { 7752, 46800 }, // UTC+13:00
- { 7762, 50400 }, // UTC+14:00
- { 7772, 30600 }, // UTC+08:30
- { 0, 0 } // Trailing zeroes
-};
-
-static const char windowsIdData[] = {
-0x41, 0x66, 0x67, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
-0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
-0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74,
-0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x55, 0x53,
-0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x65, 0x72, 0x62, 0x61, 0x69, 0x6a, 0x61, 0x6e, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73,
-0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x68, 0x69, 0x61,
-0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x6e, 0x67, 0x6c,
-0x61, 0x64, 0x65, 0x73, 0x68, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
-0x42, 0x65, 0x6c, 0x61, 0x72, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x70, 0x65, 0x20, 0x56, 0x65, 0x72, 0x64,
-0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x75, 0x63,
-0x61, 0x73, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43,
-0x65, 0x6e, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
-0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65,
-0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x69,
-0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e,
-0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
-0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
-0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e,
-0x74, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x43, 0x65,
-0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
-0x43, 0x68, 0x69, 0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
-0x44, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x53, 0x6f, 0x75,
-0x74, 0x68, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x45, 0x67,
-0x79, 0x70, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x6b,
-0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x69, 0x6a, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54,
-0x69, 0x6d, 0x65, 0x0, 0x46, 0x4c, 0x45, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x4d, 0x54, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x54, 0x42, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64,
-0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x72, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4a, 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e,
-0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b,
-0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c,
-0x69, 0x62, 0x79, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c,
-0x69, 0x6e, 0x65, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64,
-0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
-0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x20, 0x45,
-0x61, 0x73, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f,
-0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61,
-0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x4d, 0x6f, 0x75,
-0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
-0x4d, 0x79, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x4e, 0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x70, 0x61, 0x6c, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65,
-0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0,
-0x4e, 0x65, 0x77, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x45, 0x61,
-0x73, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72,
-0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x41, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61,
-0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x72, 0x61,
-0x67, 0x75, 0x61, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52,
-0x6f, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65,
-0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x33, 0x0,
-0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x30, 0x0,
-0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x31, 0x0,
-0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d,
-0x65, 0x0, 0x53, 0x41, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74,
-0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x57, 0x65, 0x73, 0x74, 0x65,
-0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x6d,
-0x6f, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x45, 0x20,
-0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53,
-0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69,
-0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x72, 0x69, 0x20, 0x4c, 0x61, 0x6e, 0x6b, 0x61, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x79, 0x72, 0x69, 0x61, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69,
-0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x61, 0x73, 0x6d, 0x61,
-0x6e, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f,
-0x6b, 0x79, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f,
-0x6e, 0x67, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75,
-0x72, 0x6b, 0x65, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55,
-0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69,
-0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x54, 0x43, 0x2d,
-0x30, 0x32, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32,
-0x0, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x20, 0x53, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61,
-0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e,
-0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e,
-0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20,
-0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x41,
-0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65,
-0x73, 0x74, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
-0x54, 0x69, 0x6d, 0x65, 0x0, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
-0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53,
-0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0
-};
-
-static const char ianaIdData[] = {
-0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61,
-0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61,
-0x68, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53, 0x61, 0x62, 0x6c, 0x6f, 0x6e, 0x0, 0x41,
-0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f,
-0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
-0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79,
-0x65, 0x6e, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66,
-0x5f, 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61, 0x6e, 0x63, 0x6f,
-0x75, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x20,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x45,
-0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x32, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c,
-0x5f, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73,
-0x73, 0x61, 0x72, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e,
-0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46,
-0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56,
-0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, 0x69,
-0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x0, 0x41,
-0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, 0x61, 0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0, 0x41, 0x73,
-0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, 0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75,
-0x6e, 0x69, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c, 0x6c,
-0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70,
-0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, 0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0, 0x41, 0x73,
-0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e,
-0x67, 0x75, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x67, 0x68, 0x64, 0x61, 0x64, 0x0, 0x45, 0x75, 0x72,
-0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x72,
-0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75,
-0x6d, 0x71, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69,
-0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x61, 0x6c, 0x6c, 0x69, 0x6e,
-0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68, 0x6f, 0x74, 0x74, 0x0,
-0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, 0x68, 0x69, 0x0, 0x45, 0x75,
-0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x6b, 0x61,
-0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61,
-0x73, 0x73, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
-0x4d, 0x54, 0x2d, 0x38, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75, 0x6d,
-0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x66, 0x61, 0x74, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x54, 0x6f, 0x72, 0x74, 0x6f, 0x6c, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d,
-0x70, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0, 0x45,
-0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x61, 0x75, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
-0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72, 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
-0x54, 0x2d, 0x31, 0x33, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44,
-0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73,
-0x65, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70,
-0x65, 0x2f, 0x55, 0x7a, 0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61,
-0x70, 0x6f, 0x72, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f,
-0x72, 0x6f, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70,
-0x75, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69,
-0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67,
-0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75, 0x74,
-0x68, 0x5f, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x41, 0x66,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69,
-0x6d, 0x70, 0x68, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61,
-0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x69, 0x67, 0x61, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
-0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x73, 0x69, 0x62,
-0x69, 0x72, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
-0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x6f, 0x64,
-0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6f, 0x66, 0x69, 0x61, 0x0,
-0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69,
-0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70,
-0x75, 0x74, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x20, 0x45, 0x75,
-0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
-0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72, 0x61, 0x6e, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c,
-0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f,
-0x6e, 0x61, 0x63, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61,
-0x72, 0x69, 0x76, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x72, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x6e,
-0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f,
-0x70, 0x65, 0x2f, 0x54, 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72,
-0x65, 0x6e, 0x61, 0x64, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0, 0x45, 0x75, 0x72, 0x6f,
-0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x20, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x4d,
-0x61, 0x64, 0x65, 0x69, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74,
-0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, 0x61, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
-0x6c, 0x61, 0x6e, 0x74, 0x79, 0x72, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x61, 0x6d, 0x61,
-0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0, 0x41,
-0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
-0x69, 0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
-0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57,
-0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0, 0x41, 0x66,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f,
-0x6d, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x50, 0x72, 0x69,
-0x6e, 0x63, 0x65, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61,
-0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61, 0x6c, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69,
-0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61, 0x6e, 0x0, 0x45,
-0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e,
-0x5f, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62,
-0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x73, 0x69,
-0x61, 0x2f, 0x41, 0x6e, 0x61, 0x64, 0x79, 0x72, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x67, 0x6f,
-0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75,
-0x73, 0x63, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0, 0x45, 0x75,
-0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63,
-0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43,
-0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72,
-0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x69, 0x73, 0x65, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72,
-0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x61, 0x5f, 0x56,
-0x69, 0x73, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x56,
-0x65, 0x6c, 0x68, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f,
-0x76, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0, 0x45, 0x74,
-0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f,
-0x4c, 0x75, 0x63, 0x69, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x66, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61, 0x62, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x52,
-0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x6a,
-0x75, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d,
-0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73,
-0x6c, 0x61, 0x76, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
-0x2d, 0x35, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69,
-0x6c, 0x6c, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x75, 0x76, 0x69, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
-0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d,
-0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x72, 0x5f,
-0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0, 0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0, 0x41, 0x66,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
-0x4d, 0x61, 0x6a, 0x75, 0x72, 0x6f, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61,
-0x6c, 0x65, 0x69, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48,
-0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x33, 0x0, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d,
-0x61, 0x64, 0x72, 0x69, 0x64, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0, 0x41,
-0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e,
-0x74, 0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x39, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6e, 0x65, 0x61, 0x75, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65,
-0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74, 0x6c, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d,
-0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43,
-0x6f, 0x70, 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61,
-0x2f, 0x4d, 0x63, 0x4d, 0x75, 0x72, 0x64, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
-0x2f, 0x57, 0x61, 0x6b, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b,
-0x69, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74, 0x65, 0x0, 0x41, 0x74, 0x6c,
-0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x65, 0x72, 0x6f, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
-0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x6a, 0x65, 0x76,
-0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47,
-0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63,
-0x71, 0x75, 0x61, 0x72, 0x69, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f,
-0x4d, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e,
-0x63, 0x69, 0x6f, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0,
-0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63,
-0x2f, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x79, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e,
-0x6e, 0x65, 0x73, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64,
-0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x6f,
-0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69,
-0x70, 0x61, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79,
-0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44,
-0x75, 0x62, 0x61, 0x69, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, 0x6c, 0x65,
-0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x0, 0x45, 0x75,
-0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65,
-0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
-0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, 0x6f, 0x6c, 0x75, 0x6c, 0x75, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
-0x31, 0x32, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c,
-0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x50,
-0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x45, 0x75, 0x72, 0x6f,
-0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d,
-0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x6f, 0x6c, 0x67, 0x6f,
-0x67, 0x72, 0x61, 0x64, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61,
-0x6c, 0x74, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x75, 0x62, 0x61, 0x0, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73,
-0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
-0x2f, 0x49, 0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
-0x56, 0x61, 0x64, 0x75, 0x7a, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c,
-0x65, 0x7a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69, 0x6e,
-0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x65, 0x69, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52,
-0x65, 0x63, 0x69, 0x66, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x72,
-0x65, 0x6d, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f, 0x75, 0x70, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
-0x2b, 0x32, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0, 0x41, 0x72, 0x63, 0x74,
-0x69, 0x63, 0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70,
-0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61,
-0x72, 0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50, 0x65, 0x72, 0x74, 0x68, 0x0, 0x45,
-0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76,
-0x61, 0x6e, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e, 0x63,
-0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e,
-0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69,
-0x70, 0x65, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x36, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x47, 0x6f, 0x64, 0x74, 0x68, 0x61, 0x62, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x57, 0x61, 0x72,
-0x73, 0x61, 0x77, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70,
-0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51,
-0x79, 0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f,
-0x44, 0x61, 0x76, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, 0x72, 0x75, 0x74, 0x0, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61,
-0x2f, 0x4b, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x63, 0x63, 0x72,
-0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, 0x63,
-0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
-0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x20, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x6e,
-0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x57,
-0x69, 0x6e, 0x61, 0x6d, 0x61, 0x63, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75,
-0x63, 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44,
-0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61, 0x72, 0x61,
-0x77, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x42, 0x6f, 0x67, 0x6f, 0x74, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70,
-0x65, 0x5f, 0x56, 0x65, 0x72, 0x64, 0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61,
-0x72, 0x77, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67, 0x79, 0x61, 0x6e, 0x67, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x69, 0x62,
-0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c, 0x65,
-0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0, 0x50,
-0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
-0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61,
-0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72,
-0x73, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72,
-0x61, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72,
-0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73, 0x6c, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
-0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x77, 0x61, 0x69, 0x74, 0x0, 0x50,
-0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
-0x63, 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x73,
-0x74, 0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69,
-0x6e, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0, 0x49,
-0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
-0x54, 0x2b, 0x36, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69,
-0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x41, 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69,
-0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x69, 0x72,
-0x75, 0x6e, 0x65, 0x70, 0x65, 0x0, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65,
-0x67, 0x69, 0x6e, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x43,
-0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0, 0x41, 0x6e, 0x74,
-0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61,
-0x6e, 0x2f, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65,
-0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65,
-0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0, 0x45, 0x75,
-0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
-0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f, 0x65, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x79, 0x61, 0x70,
-0x75, 0x72, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x69, 0x73, 0x62, 0x61,
-0x6e, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x69, 0x6e, 0x64, 0x65, 0x6d, 0x61,
-0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53,
-0x79, 0x6f, 0x77, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x20,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61,
-0x5f, 0x52, 0x69, 0x6f, 0x6a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e,
-0x74, 0x69, 0x6e, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, 0x65, 0x67, 0x6f, 0x73, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6c, 0x74,
-0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f,
-0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
-0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61,
-0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f,
-0x55, 0x73, 0x68, 0x75, 0x61, 0x69, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61,
-0x6d, 0x61, 0x72, 0x63, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62,
-0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
-0x63, 0x61, 0x2f, 0x50, 0x61, 0x6c, 0x6d, 0x65, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f,
-0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71, 0x61, 0x6c, 0x75, 0x69,
-0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69, 0x67, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61, 0x79, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x42, 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x69, 0x79, 0x61, 0x64, 0x68,
-0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54,
-0x6f, 0x6b, 0x79, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x75,
-0x72, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67,
-0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65,
-0x76, 0x61, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, 0x5f, 0x52, 0x69, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x52, 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
-0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69,
-0x66, 0x61, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x42, 0x61,
-0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73,
-0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, 0x2d,
-0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79,
-0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6c,
-0x67, 0x69, 0x65, 0x72, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x79, 0x61, 0x71,
-0x75, 0x69, 0x6c, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x73,
-0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
-0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f,
-0x5f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77,
-0x61, 0x79, 0x0, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, 0x54, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68,
-0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6c, 0x61,
-0x70, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c,
-0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
-0x50, 0x61, 0x6c, 0x61, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x41,
-0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x6e, 0x64,
-0x79, 0x67, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0, 0x41,
-0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66,
-0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d,
-0x61, 0x72, 0x6b, 0x73, 0x68, 0x61, 0x76, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x69, 0x6a,
-0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x73, 0x75, 0x6e, 0x64, 0x0, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65, 0x6c, 0x65, 0x6d, 0x79,
-0x0, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61,
-0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73,
-0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x54, 0x65, 0x6c, 0x6c, 0x5f, 0x43,
-0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65,
-0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f,
-0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f,
-0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e,
-0x65, 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74,
-0x61, 0x6d, 0x6f, 0x72, 0x6f, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6c, 0x65,
-0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63,
-0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e,
-0x69, 0x75, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73,
-0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x41, 0x73,
-0x69, 0x61, 0x2f, 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
-0x54, 0x2d, 0x32, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, 0x6b, 0x0, 0x41, 0x66, 0x72,
-0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x62, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48,
-0x6f, 0x62, 0x61, 0x72, 0x74, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72,
-0x69, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x20,
-0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55,
-0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44,
-0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
-0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x6e,
-0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73,
-0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x41, 0x75, 0x73,
-0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41,
-0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0,
-0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
-0x2f, 0x42, 0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65,
-0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76,
-0x6f, 0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f,
-0x79, 0x61, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61,
-0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72,
-0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61,
-0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64,
-0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69,
-0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e,
-0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f,
-0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x34, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x32, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x30, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x36, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x33,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x33,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x30, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x31, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x34,
-0x35, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x33,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x33,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x31, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30,
-0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x33,
-0x30, 0x0
-};
-// GENERATED PART ENDS HERE
-
-QT_END_NAMESPACE
-
-#endif // QTIMEZONEPRIVATE_DATA_P_H
diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h
index 17d2ab852a..d48318b474 100644
--- a/src/corelib/tools/qtools_p.h
+++ b/src/corelib/tools/qtools_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -57,17 +57,17 @@
QT_BEGIN_NAMESPACE
namespace QtMiscUtils {
-Q_DECL_CONSTEXPR inline char toHexUpper(uint value) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline char toHexUpper(uint value) noexcept
{
return "0123456789ABCDEF"[value & 0xF];
}
-Q_DECL_CONSTEXPR inline char toHexLower(uint value) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline char toHexLower(uint value) noexcept
{
return "0123456789abcdef"[value & 0xF];
}
-Q_DECL_CONSTEXPR inline int fromHex(uint c) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int fromHex(uint c) noexcept
{
return ((c >= '0') && (c <= '9')) ? int(c - '0') :
((c >= 'A') && (c <= 'F')) ? int(c - 'A' + 10) :
@@ -75,12 +75,12 @@ Q_DECL_CONSTEXPR inline int fromHex(uint c) Q_DECL_NOTHROW
/* otherwise */ -1;
}
-Q_DECL_CONSTEXPR inline char toOct(uint value) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline char toOct(uint value) noexcept
{
return '0' + char(value & 0x7);
}
-Q_DECL_CONSTEXPR inline int fromOct(uint c) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline int fromOct(uint c) noexcept
{
return ((c >= '0') && (c <= '7')) ? int(c - '0') : -1;
}
@@ -96,11 +96,11 @@ struct CalculateGrowingBlockSizeResult {
size_t elementCount;
};
-// implemented in qbytearray.cpp
+// Implemented in qarraydata.cpp:
size_t Q_CORE_EXPORT Q_DECL_CONST_FUNCTION
-qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) Q_DECL_NOTHROW;
+qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) noexcept;
CalculateGrowingBlockSizeResult Q_CORE_EXPORT Q_DECL_CONST_FUNCTION
-qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) Q_DECL_NOTHROW ;
+qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) noexcept ;
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qunicodetables.cpp b/src/corelib/tools/qunicodetables.cpp
index 4c4821802d..d57b39ff1f 100644
--- a/src/corelib/tools/qunicodetables.cpp
+++ b/src/corelib/tools/qunicodetables.cpp
@@ -8803,42 +8803,42 @@ static const Properties uc_properties[] = {
{ 12, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 12, 0 }
};
-Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(uint ucs4) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(uint ucs4) noexcept
{
return uc_properties + GET_PROP_INDEX(ucs4);
}
-Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(ushort ucs2) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(ushort ucs2) noexcept
{
return uc_properties + GET_PROP_INDEX_UCS2(ucs2);
}
-Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4) noexcept
{
return qGetProp(ucs4);
}
-Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2) Q_DECL_NOTHROW
+Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2) noexcept
{
return qGetProp(ucs2);
}
-Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(uint ucs4) Q_DECL_NOTHROW
+Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(uint ucs4) noexcept
{
return static_cast<GraphemeBreakClass>(qGetProp(ucs4)->graphemeBreakClass);
}
-Q_CORE_EXPORT WordBreakClass QT_FASTCALL wordBreakClass(uint ucs4) Q_DECL_NOTHROW
+Q_CORE_EXPORT WordBreakClass QT_FASTCALL wordBreakClass(uint ucs4) noexcept
{
return static_cast<WordBreakClass>(qGetProp(ucs4)->wordBreakClass);
}
-Q_CORE_EXPORT SentenceBreakClass QT_FASTCALL sentenceBreakClass(uint ucs4) Q_DECL_NOTHROW
+Q_CORE_EXPORT SentenceBreakClass QT_FASTCALL sentenceBreakClass(uint ucs4) noexcept
{
return static_cast<SentenceBreakClass>(qGetProp(ucs4)->sentenceBreakClass);
}
-Q_CORE_EXPORT LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4) Q_DECL_NOTHROW
+Q_CORE_EXPORT LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4) noexcept
{
return static_cast<LineBreakClass>(qGetProp(ucs4)->lineBreakClass);
}
diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h
index 3f2e91a9b2..cb7a211cb6 100644
--- a/src/corelib/tools/qunicodetables_p.h
+++ b/src/corelib/tools/qunicodetables_p.h
@@ -93,8 +93,8 @@ struct Properties {
ushort script : 8;
};
-Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4) Q_DECL_NOTHROW;
-Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2) Q_DECL_NOTHROW;
+Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4) noexcept;
+Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2) noexcept;
struct LowercaseTraits
{
@@ -209,20 +209,20 @@ enum LineBreakClass {
NumLineBreakClasses
};
-Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(uint ucs4) Q_DECL_NOTHROW;
-inline GraphemeBreakClass graphemeBreakClass(QChar ch) Q_DECL_NOTHROW
+Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(uint ucs4) noexcept;
+inline GraphemeBreakClass graphemeBreakClass(QChar ch) noexcept
{ return graphemeBreakClass(ch.unicode()); }
-Q_CORE_EXPORT WordBreakClass QT_FASTCALL wordBreakClass(uint ucs4) Q_DECL_NOTHROW;
-inline WordBreakClass wordBreakClass(QChar ch) Q_DECL_NOTHROW
+Q_CORE_EXPORT WordBreakClass QT_FASTCALL wordBreakClass(uint ucs4) noexcept;
+inline WordBreakClass wordBreakClass(QChar ch) noexcept
{ return wordBreakClass(ch.unicode()); }
-Q_CORE_EXPORT SentenceBreakClass QT_FASTCALL sentenceBreakClass(uint ucs4) Q_DECL_NOTHROW;
-inline SentenceBreakClass sentenceBreakClass(QChar ch) Q_DECL_NOTHROW
+Q_CORE_EXPORT SentenceBreakClass QT_FASTCALL sentenceBreakClass(uint ucs4) noexcept;
+inline SentenceBreakClass sentenceBreakClass(QChar ch) noexcept
{ return sentenceBreakClass(ch.unicode()); }
-Q_CORE_EXPORT LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4) Q_DECL_NOTHROW;
-inline LineBreakClass lineBreakClass(QChar ch) Q_DECL_NOTHROW
+Q_CORE_EXPORT LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4) noexcept;
+inline LineBreakClass lineBreakClass(QChar ch) noexcept
{ return lineBreakClass(ch.unicode()); }
} // namespace QUnicodeTables
diff --git a/src/corelib/tools/qunicodetools.cpp b/src/corelib/tools/qunicodetools.cpp
index c9d0868fef..d14118abf7 100644
--- a/src/corelib/tools/qunicodetools.cpp
+++ b/src/corelib/tools/qunicodetools.cpp
@@ -542,7 +542,7 @@ static const uchar breakTable[QUnicodeTables::LineBreak_SA][QUnicodeTables::Line
} // namespace LB
-static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *attributes)
+static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *attributes, QUnicodeTools::CharAttributeOptions options)
{
quint32 nestart = 0;
LB::NS::Class nelast = LB::NS::XX;
@@ -564,6 +564,31 @@ static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *at
QUnicodeTables::LineBreakClass ncls = (QUnicodeTables::LineBreakClass) prop->lineBreakClass;
QUnicodeTables::LineBreakClass tcls;
+ if (options & QUnicodeTools::HangulLineBreakTailoring) {
+ if (Q_UNLIKELY((ncls >= QUnicodeTables::LineBreak_H2
+ && ncls <= QUnicodeTables::LineBreak_JT)
+ || (ucs4 >= 0x3130 && ucs4 <= 0x318F && ncls == QUnicodeTables::LineBreak_ID))
+ ) {
+ // LB27: use SPACE for line breaking
+ // "When Korean uses SPACE for line breaking, the classes in rule LB26,
+ // as well as characters of class ID, are often tailored to AL; see Section 8, Customization."
+ // In case of Korean syllables: "3130..318F HANGUL COMPATIBILITY JAMO"
+ ncls = QUnicodeTables::LineBreak_AL;
+ } else {
+ if (Q_UNLIKELY(ncls == QUnicodeTables::LineBreak_SA)) {
+ // LB1: resolve SA to AL, except of those that have Category Mn or Mc be resolved to CM
+ static const int test = FLAG(QChar::Mark_NonSpacing) | FLAG(QChar::Mark_SpacingCombining);
+ if (FLAG(prop->category) & test)
+ ncls = QUnicodeTables::LineBreak_CM;
+ }
+ if (Q_UNLIKELY(ncls == QUnicodeTables::LineBreak_CM)) {
+ // LB10: treat CM that follows SP, BK, CR, LF, NL, or ZW as AL
+ if (lcls == QUnicodeTables::LineBreak_ZW || lcls >= QUnicodeTables::LineBreak_SP)
+ ncls = QUnicodeTables::LineBreak_AL;
+ }
+ }
+ }
+
if (Q_UNLIKELY(ncls == QUnicodeTables::LineBreak_SA)) {
// LB1: resolve SA to AL, except of those that have Category Mn or Mc be resolved to CM
static const int test = FLAG(QChar::Mark_NonSpacing) | FLAG(QChar::Mark_SpacingCombining);
@@ -716,7 +741,7 @@ Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length,
if (options & SentenceBreaks)
getSentenceBreaks(string, length, attributes);
if (options & LineBreaks)
- getLineBreaks(string, length, attributes);
+ getLineBreaks(string, length, attributes, options);
if (options & WhiteSpaces)
getWhiteSpaces(string, length, attributes);
diff --git a/src/corelib/tools/qunicodetools_p.h b/src/corelib/tools/qunicodetools_p.h
index 5e2d56a226..ed6fcb5d65 100644
--- a/src/corelib/tools/qunicodetools_p.h
+++ b/src/corelib/tools/qunicodetools_p.h
@@ -88,6 +88,7 @@ enum CharAttributeOption {
SentenceBreaks = 0x04,
LineBreaks = 0x08,
WhiteSpaces = 0x10,
+ HangulLineBreakTailoring = 0x20,
DefaultOptionsCompat = GraphemeBreaks | LineBreaks | WhiteSpaces, // ### remove
DontClearAttributes = 0x1000
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index 597e7464cb..a49e0af687 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -43,15 +43,15 @@
#include <QtCore/qcontainerfwd.h>
#include <QtCore/qglobal.h>
#include <QtCore/qalgorithms.h>
+#include <QtCore/qcontainertools_impl.h>
+#include <QtCore/qhashfunctions.h>
-#include <new>
-#include <string.h>
-#include <stdlib.h>
#include <algorithm>
-#ifdef Q_COMPILER_INITIALIZER_LISTS
#include <initializer_list>
-#endif
#include <iterator>
+#include <new>
+#include <string.h>
+#include <stdlib.h>
QT_BEGIN_NAMESPACE
@@ -69,14 +69,18 @@ public:
append(other.constData(), other.size());
}
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QVarLengthArray(std::initializer_list<T> args)
- : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array))
+ : QVarLengthArray(args.begin(), args.end())
{
- if (args.size())
- append(args.begin(), int(args.size()));
}
-#endif
+
+ template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
+ inline QVarLengthArray(InputIterator first, InputIterator last)
+ : QVarLengthArray()
+ {
+ QtPrivate::reserveIfForwardIterator(this, first, last);
+ std::copy(first, last, std::back_inserter(*this));
+ }
inline ~QVarLengthArray() {
if (QTypeInfo<T>::isComplex) {
@@ -96,7 +100,6 @@ public:
return *this;
}
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QVarLengthArray<T, Prealloc> &operator=(std::initializer_list<T> list)
{
resize(list.size());
@@ -104,7 +107,6 @@ public:
QT_MAKE_CHECKED_ARRAY_ITERATOR(this->begin(), this->size()));
return *this;
}
-#endif
inline void removeLast() {
Q_ASSERT(s > 0);
@@ -570,7 +572,7 @@ bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T,
template <typename T, int Prealloc1, int Prealloc2>
bool operator<(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
+ noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end())))
{
return std::lexicographical_compare(lhs.begin(), lhs.end(),
@@ -579,25 +581,32 @@ bool operator<(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T
template <typename T, int Prealloc1, int Prealloc2>
inline bool operator>(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
+ noexcept(noexcept(lhs < rhs))
{
return rhs < lhs;
}
template <typename T, int Prealloc1, int Prealloc2>
inline bool operator<=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
+ noexcept(noexcept(lhs < rhs))
{
return !(lhs > rhs);
}
template <typename T, int Prealloc1, int Prealloc2>
inline bool operator>=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
+ noexcept(noexcept(lhs < rhs))
{
return !(lhs < rhs);
}
+template <typename T, int Prealloc>
+uint qHash(const QVarLengthArray<T, Prealloc> &key, uint seed = 0)
+ noexcept(noexcept(qHashRange(key.cbegin(), key.cend(), seed)))
+{
+ return qHashRange(key.cbegin(), key.cend(), seed);
+}
+
QT_END_NAMESPACE
#endif // QVARLENGTHARRAY_H
diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc
index bc8df82517..e5ba47b8ef 100644
--- a/src/corelib/tools/qvarlengtharray.qdoc
+++ b/src/corelib/tools/qvarlengtharray.qdoc
@@ -110,6 +110,14 @@
lists.
*/
+/*! \fn template<class T, int Prealloc> template<typename InputIterator> QVarLengthArray<T, Prealloc>::QVarLengthArray(InputIterator first, InputIterator last)
+ \since 5.14
+
+ Constructs an array with the contents in the iterator range [\a first, \a last).
+
+ The value type of \c InputIterator must be convertible to \c T.
+*/
+
/*! \fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc>::~QVarLengthArray()
@@ -895,3 +903,11 @@
\sa indexOf(), lastIndexOf()
*/
+/*!
+ template <typename T, int Prealloc> uint qHash(const QVarLengthArray<T, Prealloc> &key, uint seed = 0)
+ \relates QVarLengthArray
+ \since 5.14
+
+ Returns the hash value for \a key, using \a seed to seed the
+ calculation.
+*/
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 30fd7b2865..65a5174abf 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -42,18 +42,18 @@
#include <QtCore/qalgorithms.h>
#include <QtCore/qiterator.h>
-#include <QtCore/qlist.h>
#include <QtCore/qrefcount.h>
#include <QtCore/qarraydata.h>
#include <QtCore/qhashfunctions.h>
+#include <QtCore/qcontainertools_impl.h>
#include <iterator>
+#include <initializer_list>
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
#include <vector>
+#endif
#include <stdlib.h>
#include <string.h>
-#ifdef Q_COMPILER_INITIALIZER_LISTS
-#include <initializer_list>
-#endif
#include <algorithm>
@@ -66,21 +66,22 @@ class QVector
Data *d;
public:
- inline QVector() Q_DECL_NOTHROW : d(Data::sharedNull()) { }
+ inline QVector() noexcept : d(Data::sharedNull()) { }
explicit QVector(int size);
QVector(int size, const T &t);
inline QVector(const QVector<T> &v);
inline ~QVector() { if (!d->ref.deref()) freeData(d); }
QVector<T> &operator=(const QVector<T> &v);
-#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC)
- QVector(QVector<T> &&other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }
- QVector<T> &operator=(QVector<T> &&other) Q_DECL_NOTHROW
+ QVector(QVector<T> &&other) noexcept : d(other.d) { other.d = Data::sharedNull(); }
+ QVector<T> &operator=(QVector<T> &&other) noexcept
{ QVector moved(std::move(other)); swap(moved); return *this; }
-#endif
- void swap(QVector<T> &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
-#ifdef Q_COMPILER_INITIALIZER_LISTS
+ void swap(QVector<T> &other) noexcept { qSwap(d, other.d); }
inline QVector(std::initializer_list<T> args);
-#endif
+ QVector<T> &operator=(std::initializer_list<T> args);
+ template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
+ inline QVector(InputIterator first, InputIterator last);
+ explicit QVector(QArrayDataPointerRef<T> ref) noexcept : d(ref.ptr) {}
+
bool operator==(const QVector<T> &v) const;
inline bool operator!=(const QVector<T> &v) const { return !(*this == v); }
@@ -94,7 +95,13 @@ public:
void reserve(int size);
inline void squeeze()
{
- reallocData(d->size, d->size);
+ if (d->size < int(d->alloc)) {
+ if (!d->size) {
+ *this = QVector<T>();
+ return;
+ }
+ realloc(d->size);
+ }
if (d->capacityReserved) {
// capacity reserved in a read only memory would be useless
// this checks avoid writing to such memory.
@@ -133,9 +140,7 @@ public:
T &operator[](int i);
const T &operator[](int i) const;
void append(const T &t);
-#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC)
void append(T &&t);
-#endif
inline void append(const QVector<T> &l) { *this += l; }
void prepend(T &&t);
void prepend(const T &t);
@@ -203,29 +208,29 @@ public:
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
#if !defined(QT_STRICT_ITERATORS) || defined(Q_CLANG_QDOC)
inline iterator begin() { detach(); return d->begin(); }
- inline const_iterator begin() const Q_DECL_NOTHROW { return d->constBegin(); }
- inline const_iterator cbegin() const Q_DECL_NOTHROW { return d->constBegin(); }
- inline const_iterator constBegin() const Q_DECL_NOTHROW { return d->constBegin(); }
+ inline const_iterator begin() const noexcept { return d->constBegin(); }
+ inline const_iterator cbegin() const noexcept { return d->constBegin(); }
+ inline const_iterator constBegin() const noexcept { return d->constBegin(); }
inline iterator end() { detach(); return d->end(); }
- inline const_iterator end() const Q_DECL_NOTHROW { return d->constEnd(); }
- inline const_iterator cend() const Q_DECL_NOTHROW { return d->constEnd(); }
- inline const_iterator constEnd() const Q_DECL_NOTHROW { return d->constEnd(); }
+ inline const_iterator end() const noexcept { return d->constEnd(); }
+ inline const_iterator cend() const noexcept { return d->constEnd(); }
+ inline const_iterator constEnd() const noexcept { return d->constEnd(); }
#else
inline iterator begin(iterator = iterator()) { detach(); return d->begin(); }
- inline const_iterator begin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); }
- inline const_iterator cbegin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); }
- inline const_iterator constBegin(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constBegin(); }
+ inline const_iterator begin(const_iterator = const_iterator()) const noexcept { return d->constBegin(); }
+ inline const_iterator cbegin(const_iterator = const_iterator()) const noexcept { return d->constBegin(); }
+ inline const_iterator constBegin(const_iterator = const_iterator()) const noexcept { return d->constBegin(); }
inline iterator end(iterator = iterator()) { detach(); return d->end(); }
- inline const_iterator end(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constEnd(); }
- inline const_iterator cend(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constEnd(); }
- inline const_iterator constEnd(const_iterator = const_iterator()) const Q_DECL_NOTHROW { return d->constEnd(); }
+ inline const_iterator end(const_iterator = const_iterator()) const noexcept { return d->constEnd(); }
+ inline const_iterator cend(const_iterator = const_iterator()) const noexcept { return d->constEnd(); }
+ inline const_iterator constEnd(const_iterator = const_iterator()) const noexcept { return d->constEnd(); }
#endif
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
- const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
iterator insert(iterator before, int n, const T &x);
inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
inline iterator insert(iterator before, T &&x);
@@ -247,6 +252,13 @@ public:
T value(int i) const;
T value(int i, const T &defaultValue) const;
+ void swapItemsAt(int i, int j) {
+ Q_ASSERT_X(i >= 0 && i < size() && j >= 0 && j < size(),
+ "QVector<T>::swap", "index out of range");
+ detach();
+ qSwap(d->begin()[i], d->begin()[j]);
+ }
+
// STL compatibility
typedef T value_type;
typedef value_type* pointer;
@@ -258,10 +270,8 @@ public:
typedef const_iterator ConstIterator;
typedef int size_type;
inline void push_back(const T &t) { append(t); }
-#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC)
void push_back(T &&t) { append(std::move(t)); }
void push_front(T &&t) { prepend(std::move(t)); }
-#endif
inline void push_front(const T &t) { prepend(t); }
void pop_back() { removeLast(); }
void pop_front() { removeFirst(); }
@@ -288,18 +298,22 @@ public:
inline QVector<T> &operator<<(T &&t)
{ append(std::move(t)); return *this; }
- QList<T> toList() const;
-
static QVector<T> fromList(const QList<T> &list);
+ QList<T> toList() const;
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ Q_DECL_DEPRECATED_X("Use QVector<T>(vector.begin(), vector.end()) instead.")
static inline QVector<T> fromStdVector(const std::vector<T> &vector)
- { QVector<T> tmp; tmp.reserve(int(vector.size())); std::copy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
+ { return QVector<T>(vector.begin(), vector.end()); }
+ Q_DECL_DEPRECATED_X("Use std::vector<T>(vector.begin(), vector.end()) instead.")
inline std::vector<T> toStdVector() const
{ return std::vector<T>(d->begin(), d->end()); }
+#endif
private:
- // ### Qt6: remove const from int parameters
+ // ### Qt6: remove methods, they are unused
void reallocData(const int size, const int alloc, QArrayData::AllocationOptions options = QArrayData::Default);
void reallocData(const int sz) { reallocData(sz, d->alloc); }
+ void realloc(int alloc, QArrayData::AllocationOptions options = QArrayData::Default);
void freeData(Data *d);
void defaultConstruct(T *from, T *to);
void copyConstruct(const T *srcFrom, const T *srcTo, T *dstFrom);
@@ -387,7 +401,7 @@ void QVector<T>::detach()
d = Data::unsharableEmpty();
else
#endif
- reallocData(d->size, int(d->alloc));
+ realloc(int(d->alloc));
}
Q_ASSERT(isDetached());
}
@@ -396,7 +410,7 @@ template <typename T>
void QVector<T>::reserve(int asize)
{
if (asize > int(d->alloc))
- reallocData(d->size, asize);
+ realloc(asize);
if (isDetached()
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
&& d != Data::unsharableEmpty()
@@ -409,21 +423,26 @@ void QVector<T>::reserve(int asize)
template <typename T>
void QVector<T>::resize(int asize)
{
- int newAlloc;
- const int oldAlloc = int(d->alloc);
- QArrayData::AllocationOptions opt;
-
- if (asize > oldAlloc) { // there is not enough space
- newAlloc = asize;
- opt = QArrayData::Grow;
- } else {
- newAlloc = oldAlloc;
+ if (asize == d->size)
+ return;
+ if (asize > int(d->alloc) || !isDetached()) { // there is not enough space
+ QArrayData::AllocationOptions opt = asize > int(d->alloc) ? QArrayData::Grow : QArrayData::Default;
+ realloc(qMax(int(d->alloc), asize), opt);
}
- reallocData(asize, newAlloc, opt);
+ if (asize < d->size)
+ destruct(begin() + asize, end());
+ else
+ defaultConstruct(end(), begin() + asize);
+ d->size = asize;
}
template <typename T>
inline void QVector<T>::clear()
-{ resize(0); }
+{
+ if (!d->size)
+ return;
+ destruct(begin(), end());
+ d->size = 0;
+}
template <typename T>
inline const T &QVector<T>::at(int i) const
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
@@ -511,11 +530,10 @@ QVector<T>::QVector(int asize, const T &t)
}
}
-#ifdef Q_COMPILER_INITIALIZER_LISTS
-# if defined(Q_CC_MSVC)
+#if defined(Q_CC_MSVC)
QT_WARNING_PUSH
QT_WARNING_DISABLE_MSVC(4127) // conditional expression is constant
-# endif // Q_CC_MSVC
+#endif // Q_CC_MSVC
template <typename T>
QVector<T>::QVector(std::initializer_list<T> args)
@@ -531,10 +549,27 @@ QVector<T>::QVector(std::initializer_list<T> args)
d = Data::sharedNull();
}
}
-# if defined(Q_CC_MSVC)
+
+template <typename T>
+QVector<T> &QVector<T>::operator=(std::initializer_list<T> args)
+{
+ QVector<T> tmp(args);
+ tmp.swap(*this);
+ return *this;
+}
+
+#if defined(Q_CC_MSVC)
QT_WARNING_POP
-# endif // Q_CC_MSVC
-#endif // Q_COMPILER_INITALIZER_LISTS
+#endif // Q_CC_MSVC
+
+template <typename T>
+template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator>>
+QVector<T>::QVector(InputIterator first, InputIterator last)
+ : QVector()
+{
+ QtPrivate::reserveIfForwardIterator(this, first, last);
+ std::copy(first, last, std::back_inserter(*this));
+}
template <typename T>
void QVector<T>::freeData(Data *x)
@@ -654,6 +689,76 @@ void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::Allo
Q_ASSERT(d->size == asize);
}
+template<typename T>
+void QVector<T>::realloc(int aalloc, QArrayData::AllocationOptions options)
+{
+ Q_ASSERT(aalloc >= d->size);
+ Data *x = d;
+
+ const bool isShared = d->ref.isShared();
+
+ QT_TRY {
+ // allocate memory
+ x = Data::allocate(aalloc, options);
+ Q_CHECK_PTR(x);
+ // aalloc is bigger then 0 so it is not [un]sharedEmpty
+#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
+ Q_ASSERT(x->ref.isSharable() || options.testFlag(QArrayData::Unsharable));
+#endif
+ Q_ASSERT(!x->ref.isStatic());
+ x->size = d->size;
+
+ T *srcBegin = d->begin();
+ T *srcEnd = d->end();
+ T *dst = x->begin();
+
+ if (!QTypeInfoQuery<T>::isRelocatable || (isShared && QTypeInfo<T>::isComplex)) {
+ QT_TRY {
+ if (isShared || !std::is_nothrow_move_constructible<T>::value) {
+ // we can not move the data, we need to copy construct it
+ while (srcBegin != srcEnd)
+ new (dst++) T(*srcBegin++);
+ } else {
+ while (srcBegin != srcEnd)
+ new (dst++) T(std::move(*srcBegin++));
+ }
+ } QT_CATCH (...) {
+ // destruct already copied objects
+ destruct(x->begin(), dst);
+ QT_RETHROW;
+ }
+ } else {
+ ::memcpy(static_cast<void *>(dst), static_cast<void *>(srcBegin), (srcEnd - srcBegin) * sizeof(T));
+ dst += srcEnd - srcBegin;
+ }
+
+ } QT_CATCH (...) {
+ Data::deallocate(x);
+ QT_RETHROW;
+ }
+ x->capacityReserved = d->capacityReserved;
+
+ Q_ASSERT(d != x);
+ if (!d->ref.deref()) {
+ if (!QTypeInfoQuery<T>::isRelocatable || !aalloc || (isShared && QTypeInfo<T>::isComplex)) {
+ // data was copy constructed, we need to call destructors
+ // or if !alloc we did nothing to the old 'd'.
+ freeData(d);
+ } else {
+ Data::deallocate(d);
+ }
+ }
+ d = x;
+
+ Q_ASSERT(d->data());
+ Q_ASSERT(uint(d->size) <= d->alloc);
+#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
+ Q_ASSERT(d != Data::unsharableEmpty());
+#endif
+ Q_ASSERT(d != Data::sharedNull());
+ Q_ASSERT(d->alloc >= uint(aalloc));
+}
+
#if defined(Q_CC_MSVC)
QT_WARNING_POP
#endif
@@ -679,12 +784,12 @@ void QVector<T>::append(const T &t)
if (!isDetached() || isTooSmall) {
T copy(t);
QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
- reallocData(d->size, isTooSmall ? d->size + 1 : d->alloc, opt);
+ realloc(isTooSmall ? d->size + 1 : d->alloc, opt);
if (QTypeInfo<T>::isComplex)
- new (d->end()) T(qMove(copy));
+ new (d->end()) T(std::move(copy));
else
- *d->end() = qMove(copy);
+ *d->end() = std::move(copy);
} else {
if (QTypeInfo<T>::isComplex)
@@ -695,21 +800,19 @@ void QVector<T>::append(const T &t)
++d->size;
}
-#ifdef Q_COMPILER_RVALUE_REFS
template <typename T>
void QVector<T>::append(T &&t)
{
const bool isTooSmall = uint(d->size + 1) > d->alloc;
if (!isDetached() || isTooSmall) {
QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
- reallocData(d->size, isTooSmall ? d->size + 1 : d->alloc, opt);
+ realloc(isTooSmall ? d->size + 1 : d->alloc, opt);
}
new (d->end()) T(std::move(t));
++d->size;
}
-#endif
template <typename T>
void QVector<T>::removeLast()
@@ -717,13 +820,11 @@ void QVector<T>::removeLast()
Q_ASSERT(!isEmpty());
Q_ASSERT(d->alloc);
- if (!d->ref.isShared()) {
- --d->size;
- if (QTypeInfo<T>::isComplex)
- (d->data() + d->size)->~T();
- } else {
- reallocData(d->size - 1);
- }
+ if (d->ref.isShared())
+ detach();
+ --d->size;
+ if (QTypeInfo<T>::isComplex)
+ (d->data() + d->size)->~T();
}
template <typename T>
@@ -735,7 +836,7 @@ typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, c
if (n != 0) {
const T copy(t);
if (!isDetached() || d->size + n > int(d->alloc))
- reallocData(d->size, d->size + n, QArrayData::Grow);
+ realloc(d->size + n, QArrayData::Grow);
if (!QTypeInfoQuery<T>::isRelocatable) {
T *b = d->end();
T *i = d->end() + n;
@@ -768,7 +869,7 @@ typename QVector<T>::iterator QVector<T>::insert(iterator before, T &&t)
const auto offset = std::distance(d->begin(), before);
if (!isDetached() || d->size + 1 > int(d->alloc))
- reallocData(d->size, d->size + 1, QArrayData::Grow);
+ realloc(d->size + 1, QArrayData::Grow);
if (!QTypeInfoQuery<T>::isRelocatable) {
T *i = d->end();
T *j = i + 1;
@@ -870,14 +971,14 @@ QVector<T> &QVector<T>::fill(const T &from, int asize)
template <typename T>
QVector<T> &QVector<T>::operator+=(const QVector &l)
{
- if (d == Data::sharedNull()) {
+ if (d->size == 0) {
*this = l;
} else {
uint newSize = d->size + l.d->size;
const bool isTooSmall = newSize > d->alloc;
if (!isDetached() || isTooSmall) {
QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
- reallocData(d->size, isTooSmall ? newSize : d->alloc, opt);
+ realloc(isTooSmall ? newSize : d->alloc, opt);
}
if (d->alloc) {
@@ -960,7 +1061,7 @@ Q_OUTOFLINE_TEMPLATE QVector<T> QVector<T>::mid(int pos, int len) const
}
QVector<T> midResult;
- midResult.reallocData(0, len);
+ midResult.realloc(len);
T *srcFrom = d->begin() + pos;
T *srcTo = d->begin() + pos + len;
midResult.copyConstruct(srcFrom, srcTo, midResult.data());
@@ -968,50 +1069,19 @@ Q_OUTOFLINE_TEMPLATE QVector<T> QVector<T>::mid(int pos, int len) const
return midResult;
}
-template <typename T>
-Q_OUTOFLINE_TEMPLATE QList<T> QVector<T>::toList() const
-{
- QList<T> result;
- result.reserve(size());
- for (int i = 0; i < size(); ++i)
- result.append(at(i));
- return result;
-}
-
-template <typename T>
-Q_OUTOFLINE_TEMPLATE QVector<T> QList<T>::toVector() const
-{
- QVector<T> result(size());
- for (int i = 0; i < size(); ++i)
- result[i] = at(i);
- return result;
-}
-
-template <typename T>
-QVector<T> QVector<T>::fromList(const QList<T> &list)
-{
- return list.toVector();
-}
-
-template <typename T>
-QList<T> QList<T>::fromVector(const QVector<T> &vector)
-{
- return vector.toList();
-}
-
Q_DECLARE_SEQUENTIAL_ITERATOR(Vector)
Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(Vector)
template <typename T>
uint qHash(const QVector<T> &key, uint seed = 0)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHashRange(key.cbegin(), key.cend(), seed)))
+ noexcept(noexcept(qHashRange(key.cbegin(), key.cend(), seed)))
{
return qHashRange(key.cbegin(), key.cend(), seed);
}
template <typename T>
bool operator<(const QVector<T> &lhs, const QVector<T> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
+ noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end())))
{
return std::lexicographical_compare(lhs.begin(), lhs.end(),
@@ -1020,21 +1090,21 @@ bool operator<(const QVector<T> &lhs, const QVector<T> &rhs)
template <typename T>
inline bool operator>(const QVector<T> &lhs, const QVector<T> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
+ noexcept(noexcept(lhs < rhs))
{
return rhs < lhs;
}
template <typename T>
inline bool operator<=(const QVector<T> &lhs, const QVector<T> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
+ noexcept(noexcept(lhs < rhs))
{
return !(lhs > rhs);
}
template <typename T>
inline bool operator>=(const QVector<T> &lhs, const QVector<T> &rhs)
- Q_DECL_NOEXCEPT_EXPR(noexcept(lhs < rhs))
+ noexcept(noexcept(lhs < rhs))
{
return !(lhs < rhs);
}
@@ -1046,23 +1116,33 @@ inline bool operator>=(const QVector<T> &lhs, const QVector<T> &rhs)
### QVector<QPointF> respectively.
*/
-#ifdef Q_CC_MSVC
+#if defined(Q_CC_MSVC) && !defined(QT_BUILD_CORE_LIB)
QT_BEGIN_INCLUDE_NAMESPACE
#include <QtCore/qpoint.h>
QT_END_INCLUDE_NAMESPACE
-
-#ifndef Q_TEMPLATE_EXTERN
-#if defined(QT_BUILD_CORE_LIB)
-#define Q_TEMPLATE_EXTERN
-#else
-#define Q_TEMPLATE_EXTERN extern
+extern template class Q_CORE_EXPORT QVector<QPointF>;
+extern template class Q_CORE_EXPORT QVector<QPoint>;
#endif
+
+QVector<uint> QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); }
+
+QVector<QStringRef> QString::splitRef(const QString &sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
+{ return splitRef(sep, _sb(behavior), cs); }
+QVector<QStringRef> QString::splitRef(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
+{ return splitRef(sep, _sb(behavior), cs); }
+#ifndef QT_NO_REGEXP
+QVector<QStringRef> QString::splitRef(const QRegExp &sep, Qt::SplitBehavior behavior) const
+{ return splitRef(sep, _sb(behavior)); }
#endif
-Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>;
-Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>;
+#if QT_CONFIG(regularexpression)
+QVector<QStringRef> QString::splitRef(const QRegularExpression &sep, Qt::SplitBehavior behavior) const
+{ return splitRef(sep, _sb(behavior)); }
#endif
+QVector<QStringRef> QStringRef::split(const QString &sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
+{ return split(sep, QString::_sb(behavior), cs); }
+QVector<QStringRef> QStringRef::split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const
+{ return split(sep, QString::_sb(behavior), cs); }
-QVector<uint> QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); }
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qvector.qdoc b/src/corelib/tools/qvector.qdoc
index 75b17a4207..4c442511ea 100644
--- a/src/corelib/tools/qvector.qdoc
+++ b/src/corelib/tools/qvector.qdoc
@@ -243,6 +243,18 @@
lists.
*/
+/*! \fn template <typename T> template<typename InputIterator> QVector<T>::QVector(InputIterator first, InputIterator last)
+ \since 5.14
+
+ Constructs a vector with the contents in the iterator range [\a first, \a last).
+
+ The value type of \c InputIterator must be convertible to \c T.
+*/
+
+/*!
+ \fn template <typename T> QVector<T>::QVector(QArrayDataPointerRef<T> ref)
+ \internal
+*/
/*! \fn template <typename T> QVector<T>::~QVector()
@@ -263,6 +275,17 @@
\since 5.2
*/
+/*!
+ \fn template <typename T> QVector<T> &QVector<T>::operator=(std::initializer_list<T> args)
+
+ Assigns the collection of values in \a args to this QVector instance.
+
+ This operator is only enabled if the compiler supports C++11 initializer
+ lists.
+
+ \since 5.14
+*/
+
/*! \fn template <typename T> void QVector<T>::swap(QVector<T> &other)
\since 4.8
@@ -270,6 +293,16 @@
never fails.
*/
+/*! \fn template <typename T> void QVector<T>::swapItemsAt(int i, int j)
+ \since 5.14
+
+ Exchange the item at index position \a i with the item at index
+ position \a j. This function assumes that both \a i and \a j are
+ at least 0 but less than size(). To avoid failure, test that both
+ \a i and \a j are at least 0 and less than size().
+*/
+
+
/*! \fn template <typename T> bool QVector<T>::operator==(const QVector<T> &other) const
Returns \c true if \a other is equal to this vector; otherwise
diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp
index b96e48252e..58e3c15560 100644
--- a/src/corelib/tools/qversionnumber.cpp
+++ b/src/corelib/tools/qversionnumber.cpp
@@ -235,7 +235,7 @@ QVersionNumber QVersionNumber::normalized() const
\sa commonPrefix()
*/
-bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHROW
+bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const noexcept
{
if (segmentCount() > other.segmentCount())
return false;
@@ -259,7 +259,7 @@ bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHRO
\snippet qversionnumber/main.cpp 1
*/
-int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2) Q_DECL_NOTHROW
+int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept
{
int commonlen;
@@ -482,7 +482,7 @@ QVersionNumber QVersionNumber::fromString(QLatin1String string, int *suffixIndex
if (suffixIndex)
*suffixIndex = int(lastGoodEnd - string.begin());
- return QVersionNumber(qMove(seg));
+ return QVersionNumber(std::move(seg));
}
void QVersionNumber::SegmentStorage::setVector(int len, int maj, int min, int mic)
diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h
index 1bfb4aab39..d43b86ba51 100644
--- a/src/corelib/tools/qversionnumber.h
+++ b/src/corelib/tools/qversionnumber.h
@@ -87,7 +87,7 @@ class QVersionNumber
};
// set the InlineSegmentMarker and set length to zero
- SegmentStorage() Q_DECL_NOTHROW : dummy(1) {}
+ SegmentStorage() noexcept : dummy(1) {}
SegmentStorage(const QVector<int> &seg)
{
@@ -119,14 +119,13 @@ class QVersionNumber
return *this;
}
-#ifdef Q_COMPILER_RVALUE_REFS
- SegmentStorage(SegmentStorage &&other) Q_DECL_NOTHROW
+ SegmentStorage(SegmentStorage &&other) noexcept
: dummy(other.dummy)
{
other.dummy = 1;
}
- SegmentStorage &operator=(SegmentStorage &&other) Q_DECL_NOTHROW
+ SegmentStorage &operator=(SegmentStorage &&other) noexcept
{
qSwap(dummy, other.dummy);
return *this;
@@ -139,8 +138,6 @@ class QVersionNumber
else
pointer_segments = new QVector<int>(std::move(seg));
}
-#endif
-#ifdef Q_COMPILER_INITIALIZER_LISTS
SegmentStorage(std::initializer_list<int> args)
{
if (dataFitsInline(args.begin(), int(args.size()))) {
@@ -149,14 +146,13 @@ class QVersionNumber
pointer_segments = new QVector<int>(args);
}
}
-#endif
~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; }
- bool isUsingPointer() const Q_DECL_NOTHROW
+ bool isUsingPointer() const noexcept
{ return (inline_segments[InlineSegmentMarker] & 1) == 0; }
- int size() const Q_DECL_NOTHROW
+ int size() const noexcept
{ return isUsingPointer() ? pointer_segments->size() : (inline_segments[InlineSegmentMarker] >> 1); }
void setInlineSize(int len)
@@ -218,7 +214,7 @@ class QVersionNumber
} m_segments;
public:
- inline QVersionNumber() Q_DECL_NOTHROW
+ inline QVersionNumber() noexcept
: m_segments()
{}
inline explicit QVersionNumber(const QVector<int> &seg)
@@ -227,17 +223,13 @@ public:
// compiler-generated copy/move ctor/assignment operators and the destructor are ok
-#ifdef Q_COMPILER_RVALUE_REFS
explicit QVersionNumber(QVector<int> &&seg)
: m_segments(std::move(seg))
{}
-#endif
-#ifdef Q_COMPILER_INITIALIZER_LISTS
inline QVersionNumber(std::initializer_list<int> args)
: m_segments(args)
{}
-#endif
inline explicit QVersionNumber(int maj)
{ m_segments.setSegments(1, maj); }
@@ -248,34 +240,34 @@ public:
inline explicit QVersionNumber(int maj, int min, int mic)
{ m_segments.setSegments(3, maj, min, mic); }
- Q_REQUIRED_RESULT inline bool isNull() const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline bool isNull() const noexcept
{ return segmentCount() == 0; }
- Q_REQUIRED_RESULT inline bool isNormalized() const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline bool isNormalized() const noexcept
{ return isNull() || segmentAt(segmentCount() - 1) != 0; }
- Q_REQUIRED_RESULT inline int majorVersion() const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline int majorVersion() const noexcept
{ return segmentAt(0); }
- Q_REQUIRED_RESULT inline int minorVersion() const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline int minorVersion() const noexcept
{ return segmentAt(1); }
- Q_REQUIRED_RESULT inline int microVersion() const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline int microVersion() const noexcept
{ return segmentAt(2); }
Q_REQUIRED_RESULT Q_CORE_EXPORT QVersionNumber normalized() const;
Q_REQUIRED_RESULT Q_CORE_EXPORT QVector<int> segments() const;
- Q_REQUIRED_RESULT inline int segmentAt(int index) const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline int segmentAt(int index) const noexcept
{ return (m_segments.size() > index) ? m_segments.at(index) : 0; }
- Q_REQUIRED_RESULT inline int segmentCount() const Q_DECL_NOTHROW
+ Q_REQUIRED_RESULT inline int segmentCount() const noexcept
{ return m_segments.size(); }
- Q_REQUIRED_RESULT Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept;
- Q_REQUIRED_RESULT Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept;
Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2);
@@ -299,22 +291,22 @@ Q_DECLARE_TYPEINFO(QVersionNumber, Q_MOVABLE_TYPE);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version);
#endif
-Q_REQUIRED_RESULT inline bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
{ return QVersionNumber::compare(lhs, rhs) > 0; }
-Q_REQUIRED_RESULT inline bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
{ return QVersionNumber::compare(lhs, rhs) >= 0; }
-Q_REQUIRED_RESULT inline bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
{ return QVersionNumber::compare(lhs, rhs) < 0; }
-Q_REQUIRED_RESULT inline bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
{ return QVersionNumber::compare(lhs, rhs) <= 0; }
-Q_REQUIRED_RESULT inline bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
{ return QVersionNumber::compare(lhs, rhs) == 0; }
-Q_REQUIRED_RESULT inline bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW
+Q_REQUIRED_RESULT inline bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
{ return QVersionNumber::compare(lhs, rhs) != 0; }
QT_END_NAMESPACE
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index dc28e0e0a2..52eddd5d6b 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -18,9 +18,8 @@ HEADERS += \
tools/qcollator.h \
tools/qcollator_p.h \
tools/qcontainerfwd.h \
+ tools/qcontainertools_impl.h \
tools/qcryptographichash.h \
- tools/qdatetime.h \
- tools/qdatetime_p.h \
tools/qdoublescanprint_p.h \
tools/qeasingcurve.h \
tools/qfreelist_p.h \
@@ -39,6 +38,7 @@ HEADERS += \
tools/qmargins.h \
tools/qmessageauthenticationcode.h \
tools/qcontiguouscache.h \
+ tools/qoffsetstringarray_p.h \
tools/qpair.h \
tools/qpoint.h \
tools/qqueue.h \
@@ -84,7 +84,6 @@ SOURCES += \
tools/qbytearraymatcher.cpp \
tools/qcollator.cpp \
tools/qcryptographichash.cpp \
- tools/qdatetime.cpp \
tools/qeasingcurve.cpp \
tools/qfreelist.cpp \
tools/qhash.cpp \
@@ -152,33 +151,6 @@ qtConfig(icu) {
SOURCES += tools/qcollator_posix.cpp
}
-qtConfig(timezone) {
- HEADERS += \
- tools/qtimezone.h \
- tools/qtimezoneprivate_p.h \
- tools/qtimezoneprivate_data_p.h
- SOURCES += \
- tools/qtimezone.cpp \
- tools/qtimezoneprivate.cpp
- !nacl:darwin: {
- SOURCES += tools/qtimezoneprivate_mac.mm
- } else: android:!android-embedded: {
- SOURCES += tools/qtimezoneprivate_android.cpp
- } else: unix: {
- SOURCES += tools/qtimezoneprivate_tz.cpp
- qtConfig(icu): SOURCES += tools/qtimezoneprivate_icu.cpp
- } else: qtConfig(icu): {
- SOURCES += tools/qtimezoneprivate_icu.cpp
- } else: win32: {
- SOURCES += tools/qtimezoneprivate_win.cpp
- }
-}
-
-qtConfig(datetimeparser) {
- HEADERS += tools/qdatetimeparser_p.h
- SOURCES += tools/qdatetimeparser.cpp
-}
-
qtConfig(regularexpression) {
QMAKE_USE_PRIVATE += pcre2
diff --git a/src/dbus/dbus.pro b/src/dbus/dbus.pro
index ce799e0951..2cfd7e086c 100644
--- a/src/dbus/dbus.pro
+++ b/src/dbus/dbus.pro
@@ -9,18 +9,18 @@ qtConfig(dbus-linked) {
}
win32 {
- LIBS_PRIVATE += \
- -lws2_32 \
- -ladvapi32 \
- -lnetapi32 \
- -luser32
+ QMAKE_USE_PRIVATE += \
+ advapi32 \
+ netapi32 \
+ user32 \
+ ws2_32
}
DEFINES += QT_NO_FOREACH
QMAKE_DOCS = $$PWD/doc/qtdbus.qdocconf
-PUB_HEADERS = qtdbusglobal.h \
+HEADERS += qtdbusglobal.h \
qdbusargument.h \
qdbusconnectioninterface.h \
qdbuserror.h \
@@ -38,8 +38,7 @@ PUB_HEADERS = qtdbusglobal.h \
qdbuscontext.h \
qdbusvirtualobject.h \
qdbusservicewatcher.h \
- qdbusunixfiledescriptor.h
-HEADERS += $$PUB_HEADERS \
+ qdbusunixfiledescriptor.h \
qtdbusglobal_p.h \
qdbusconnection_p.h \
qdbusconnectionmanager_p.h \
diff --git a/src/dbus/dbus_minimal_p.h b/src/dbus/dbus_minimal_p.h
index 869c02b59d..243c8ceaba 100644
--- a/src/dbus/dbus_minimal_p.h
+++ b/src/dbus/dbus_minimal_p.h
@@ -53,7 +53,7 @@
extern "C" {
-// Equivalent to dbus-arch-deps.h
+// Equivalent to dbus-arch-deps.h (generated from dbus-arch-deps.h.in)
typedef qint64 dbus_int64_t;
typedef quint64 dbus_uint64_t;
typedef qint32 dbus_int32_t;
@@ -78,7 +78,7 @@ struct DBusWatch;
// which carry the following copyright:
/*
* Copyright (C) 2002, 2003 CodeFactory AB
- * Copyright (C) 2004, 2005 Red Hat, Inc.
+ * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
*
* Licensed under the Academic Free License version 2.1
*
@@ -103,6 +103,20 @@ typedef dbus_uint32_t dbus_unichar_t;
typedef dbus_uint32_t dbus_bool_t;
/* dbus-shared.h */
+typedef enum
+{
+ DBUS_BUS_SESSION, /**< The login session bus */
+ DBUS_BUS_SYSTEM, /**< The systemwide bus */
+ DBUS_BUS_STARTER /**< The bus that started us, if any */
+} DBusBusType;
+
+typedef enum
+{
+ DBUS_HANDLER_RESULT_HANDLED, /**< Message has had its effect - no need to run more handlers. */
+ DBUS_HANDLER_RESULT_NOT_YET_HANDLED, /**< Message has not had any effect - see if other handlers want it. */
+ DBUS_HANDLER_RESULT_NEED_MEMORY /**< Need more memory in order to return #DBUS_HANDLER_RESULT_HANDLED or #DBUS_HANDLER_RESULT_NOT_YET_HANDLED. Please try again later with more memory. */
+} DBusHandlerResult;
+
#define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
#define DBUS_PATH_DBUS "/org/freedesktop/DBus"
#define DBUS_PATH_LOCAL "/org/freedesktop/DBus/Local"
@@ -124,20 +138,6 @@ typedef dbus_uint32_t dbus_bool_t;
#define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT 2 /**< The given name does not exist on the bus */
#define DBUS_RELEASE_NAME_REPLY_NOT_OWNER 3 /**< Service is not an owner of the given name */
-typedef enum
-{
- DBUS_BUS_SESSION, /**< The login session bus */
- DBUS_BUS_SYSTEM, /**< The systemwide bus */
- DBUS_BUS_STARTER /**< The bus that started us, if any */
-} DBusBusType;
-
-typedef enum
-{
- DBUS_HANDLER_RESULT_HANDLED, /**< Message has had its effect - no need to run more handlers. */
- DBUS_HANDLER_RESULT_NOT_YET_HANDLED, /**< Message has not had any effect - see if other handlers want it. */
- DBUS_HANDLER_RESULT_NEED_MEMORY /**< Need more memory in order to return #DBUS_HANDLER_RESULT_HANDLED or #DBUS_HANDLER_RESULT_NOT_YET_HANDLED. Please try again later with more memory. */
-} DBusHandlerResult;
-
/* dbus-memory.h */
typedef void (* DBusFreeFunction) (void *memory);
diff --git a/src/dbus/doc/qtdbus.qdocconf b/src/dbus/doc/qtdbus.qdocconf
index 69eaa0eec3..4ff7242b25 100644
--- a/src/dbus/doc/qtdbus.qdocconf
+++ b/src/dbus/doc/qtdbus.qdocconf
@@ -21,6 +21,8 @@ excludedirs += ../../../examples/widgets/doc
examplesinstallpath = dbus
+tagfile = qtdbus.tags
+
depends += qtdoc qtcore
# The following parameters are for creating a qhp file, the qhelpgenerator
diff --git a/src/dbus/doc/src/dontdocument.qdoc b/src/dbus/doc/src/dontdocument.qdoc
new file mode 100644
index 0000000000..bbb8acb53c
--- /dev/null
+++ b/src/dbus/doc/src/dontdocument.qdoc
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+/*!
+ \dontdocument (QTypeInfo QMetaTypeId QDBusAbstractInterfaceBase QDBusPendingReplyData QMetaTypeId2)
+*/
diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp
index 148bd54147..87de784fc0 100644
--- a/src/dbus/qdbusabstractinterface.cpp
+++ b/src/dbus/qdbusabstractinterface.cpp
@@ -66,11 +66,11 @@ namespace {
// of to QDBusAbstractInterface::customEvent.
// See solution in Patch Set 1 of this change in the Qt Gerrit servers.
// (https://codereview.qt-project.org/#/c/126384/1)
-class DisconnectRelayEvent : public QMetaCallEvent
+class DisconnectRelayEvent : public QAbstractMetaCallEvent
{
public:
DisconnectRelayEvent(QObject *sender, const QMetaMethod &m)
- : QMetaCallEvent(0, 0, nullptr, sender, m.methodIndex())
+ : QAbstractMetaCallEvent(sender, m.methodIndex())
{}
void placeMetaCall(QObject *object) override
@@ -164,7 +164,7 @@ bool QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp, void *retu
"used to read property %s.%s",
mp.typeName(), qPrintable(interface), mp.name());
lastError = QDBusError(QDBusError::Failed,
- QString::fromLatin1("Unregistered type %1 cannot be handled")
+ QLatin1String("Unregistered type %1 cannot be handled")
.arg(QLatin1String(mp.typeName())));
return false;
}
@@ -185,7 +185,7 @@ bool QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp, void *retu
if (reply.signature() != QLatin1String("v")) {
QString errmsg = QLatin1String("Invalid signature `%1' in return from call to "
DBUS_INTERFACE_PROPERTIES);
- lastError = QDBusError(QDBusError::InvalidSignature, qMove(errmsg).arg(reply.signature()));
+ lastError = QDBusError(QDBusError::InvalidSignature, std::move(errmsg).arg(reply.signature()));
return false;
}
@@ -220,15 +220,15 @@ bool QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp, void *retu
}
// there was an error...
- QString errmsg = QLatin1String("Unexpected `%1' (%2) when retrieving property `%3.%4' "
- "(expected type `%5' (%6))");
+ const auto errmsg = QLatin1String("Unexpected `%1' (%2) when retrieving property `%3.%4' "
+ "(expected type `%5' (%6))");
lastError = QDBusError(QDBusError::InvalidSignature,
- errmsg.arg(QString::fromLatin1(foundType),
- QString::fromLatin1(foundSignature),
+ errmsg.arg(QLatin1String(foundType),
+ QLatin1String(foundSignature),
interface,
- QString::fromUtf8(mp.name()),
- QString::fromLatin1(mp.typeName()),
- QString::fromLatin1(expectedSignature)));
+ QLatin1String(mp.name()),
+ QLatin1String(mp.typeName()),
+ QLatin1String(expectedSignature)));
return false;
}
@@ -691,18 +691,20 @@ void QDBusAbstractInterface::internalPropSet(const char *propname, const QVarian
}
/*!
- Calls the method \a method on this interface and passes the parameters to this function to the
- method.
+ \fn QDBusAbstractInterface::call(const QString &message)
+ \internal
+*/
+
+/*!
+ \fn QDBusAbstractInterface::call(const QString &message, Args&&...args)
+
+ Calls the method \a method on this interface and passes \a args to the method.
+ All \a args must be convertible to QVariant.
The parameters to \c call are passed on to the remote function via D-Bus as input
arguments. Output arguments are returned in the QDBusMessage reply. If the reply is an error
reply, lastError() will also be set to the contents of the error message.
- This function can be used with up to 8 parameters, passed in arguments \a arg1, \a arg2,
- \a arg3, \a arg4, \a arg5, \a arg6, \a arg7 and \a arg8. If you need more than 8
- parameters or if you have a variable number of parameters to be passed, use
- callWithArgumentList().
-
It can be used the following way:
\snippet code/src_qdbus_qdbusabstractinterface.cpp 0
@@ -710,6 +712,19 @@ void QDBusAbstractInterface::internalPropSet(const char *propname, const QVarian
This example illustrates function calling with 0, 1 and 2 parameters and illustrates different
parameter types passed in each (the first call to \c "ProcessWorkUnicode" will contain one
Unicode string, the second call to \c "ProcessWork" will contain one string and one byte array).
+
+ \note Before Qt 5.14, this function accepted a maximum of just eight (8) arguments.
+
+ \sa callWithArgumentList()
+*/
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \internal
+
+ This function exists for binary compatibility with Qt versions < 5.14.
+ Programs recompiled against Qt 5.14 will use the variadic template function
+ instead.
*/
QDBusMessage QDBusAbstractInterface::call(const QString &method, const QVariant &arg1,
const QVariant &arg2,
@@ -722,27 +737,44 @@ QDBusMessage QDBusAbstractInterface::call(const QString &method, const QVariant
{
return call(QDBus::AutoDetect, method, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
+#endif
+
+/*!
+ \fn QDBusAbstractInterface::call(QDBus::CallMode mode, const QString &message)
+ \internal
+*/
/*!
+ \fn QDBusAbstractInterface::call(QDBus::CallMode mode, const QString &message, Args&&...args)
+
\overload
- Calls the method \a method on this interface and passes the
- parameters to this function to the method. If \a mode is \c
- NoWaitForReply, then this function will return immediately after
+ Calls the method \a method on this interface and passes \a args to the method.
+ All \a args must be convertible to QVariant.
+
+ If \a mode is \c NoWaitForReply, then this function will return immediately after
placing the call, without waiting for a reply from the remote
method. Otherwise, \a mode indicates whether this function should
activate the Qt Event Loop while waiting for the reply to arrive.
- This function can be used with up to 8 parameters, passed in arguments \a arg1, \a arg2,
- \a arg3, \a arg4, \a arg5, \a arg6, \a arg7 and \a arg8. If you need more than 8
- parameters or if you have a variable number of parameters to be passed, use
- callWithArgumentList().
-
If this function reenters the Qt event loop in order to wait for the
reply, it will exclude user input. During the wait, it may deliver
signals and other method calls to your application. Therefore, it
must be prepared to handle a reentrancy whenever a call is placed
with call().
+
+ \note Before Qt 5.14, this function accepted a maximum of just eight (8) arguments.
+
+ \sa callWithArgumentList()
+*/
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \internal
+
+ This function exists for binary compatibility with Qt versions < 5.14.
+ Programs recompiled against Qt 5.14 will use the variadic template function
+ instead.
*/
QDBusMessage QDBusAbstractInterface::call(QDBus::CallMode mode, const QString &method,
const QVariant &arg1,
@@ -787,22 +819,23 @@ QDBusMessage QDBusAbstractInterface::call(QDBus::CallMode mode, const QString &m
return callWithArgumentList(mode, method, argList);
}
+#endif // Qt 5
+/*!
+ \fn QDBusAbstractInterface::asyncCall(const QString &message)
+ \internal
+*/
/*!
- \since 4.5
- Calls the method \a method on this interface and passes the parameters to this function to the
- method.
+ \fn QDBusAbstractInterface::asyncCall(const QString &message, Args&&...args)
+
+ Calls the method \a method on this interface and passes \a args to the method.
+ All \a args must be convertible to QVariant.
The parameters to \c call are passed on to the remote function via D-Bus as input
arguments. The returned QDBusPendingCall object can be used to find out information about
the reply.
- This function can be used with up to 8 parameters, passed in arguments \a arg1, \a arg2,
- \a arg3, \a arg4, \a arg5, \a arg6, \a arg7 and \a arg8. If you need more than 8
- parameters or if you have a variable number of parameters to be passed, use
- asyncCallWithArgumentList().
-
It can be used the following way:
\snippet code/src_qdbus_qdbusabstractinterface.cpp 1
@@ -810,6 +843,19 @@ QDBusMessage QDBusAbstractInterface::call(QDBus::CallMode mode, const QString &m
This example illustrates function calling with 0, 1 and 2 parameters and illustrates different
parameter types passed in each (the first call to \c "ProcessWorkUnicode" will contain one
Unicode string, the second call to \c "ProcessWork" will contain one string and one byte array).
+
+ \note Before Qt 5.14, this function accepted a maximum of just eight (8) arguments.
+
+ \sa asyncCallWithArgumentList()
+*/
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \internal
+
+ This function exists for binary compatibility with Qt versions < 5.14.
+ Programs recompiled against Qt 5.14 will use the variadic template function
+ instead.
*/
QDBusPendingCall QDBusAbstractInterface::asyncCall(const QString &method, const QVariant &arg1,
const QVariant &arg2,
@@ -853,6 +899,7 @@ QDBusPendingCall QDBusAbstractInterface::asyncCall(const QString &method, const
return asyncCallWithArgumentList(method, argList);
}
+#endif // Qt 5
/*!
\internal
@@ -865,6 +912,24 @@ QDBusMessage QDBusAbstractInterface::internalConstCall(QDBus::CallMode mode,
return const_cast<QDBusAbstractInterface*>(this)->callWithArgumentList(mode, method, args);
}
+QDBusMessage QDBusAbstractInterface::doCall(QDBus::CallMode mode, const QString &method, const QVariant *args, size_t numArgs)
+{
+ QList<QVariant> list;
+ list.reserve(int(numArgs));
+ for (size_t i = 0; i < numArgs; ++i)
+ list.append(args[i]);
+ return callWithArgumentList(mode, method, list);
+}
+
+QDBusPendingCall QDBusAbstractInterface::doAsyncCall(const QString &method, const QVariant *args, size_t numArgs)
+{
+ QList<QVariant> list;
+ list.reserve(int(numArgs));
+ for (size_t i = 0; i < numArgs; ++i)
+ list.append(args[i]);
+ return asyncCallWithArgumentList(method, list);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DBUS
diff --git a/src/dbus/qdbusabstractinterface.h b/src/dbus/qdbusabstractinterface.h
index d6b0870787..4f4c7430a5 100644
--- a/src/dbus/qdbusabstractinterface.h
+++ b/src/dbus/qdbusabstractinterface.h
@@ -49,6 +49,7 @@
#include <QtDBus/qdbusmessage.h>
#include <QtDBus/qdbusextratypes.h>
#include <QtDBus/qdbusconnection.h>
+#include <QtDBus/qdbuspendingcall.h>
#ifdef interface
#undef interface
@@ -98,26 +99,52 @@ public:
void setTimeout(int timeout);
int timeout() const;
+ QDBusMessage call(const QString &method)
+ {
+ return doCall(QDBus::AutoDetect, method, nullptr, 0);
+ }
+
+ template <typename...Args>
+ QDBusMessage call(const QString &method, Args &&...args)
+ {
+ const QVariant variants[] = { QVariant(std::forward<Args>(args))... };
+ return doCall(QDBus::AutoDetect, method, variants, sizeof...(args));
+ }
+
+ QDBusMessage call(QDBus::CallMode mode, const QString &method)
+ {
+ return doCall(mode, method, nullptr, 0);
+ }
+
+ template <typename...Args>
+ QDBusMessage call(QDBus::CallMode mode, const QString &method, Args &&...args)
+ {
+ const QVariant variants[] = { QVariant(std::forward<Args>(args))... };
+ return doCall(mode, method, variants, sizeof...(args));
+ }
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QDBusMessage call(const QString &method,
- const QVariant &arg1 = QVariant(),
- const QVariant &arg2 = QVariant(),
- const QVariant &arg3 = QVariant(),
- const QVariant &arg4 = QVariant(),
- const QVariant &arg5 = QVariant(),
- const QVariant &arg6 = QVariant(),
- const QVariant &arg7 = QVariant(),
- const QVariant &arg8 = QVariant());
+ const QVariant &arg1,
+ const QVariant &arg2,
+ const QVariant &arg3,
+ const QVariant &arg4,
+ const QVariant &arg5,
+ const QVariant &arg6,
+ const QVariant &arg7,
+ const QVariant &arg8);
QDBusMessage call(QDBus::CallMode mode,
const QString &method,
- const QVariant &arg1 = QVariant(),
- const QVariant &arg2 = QVariant(),
- const QVariant &arg3 = QVariant(),
- const QVariant &arg4 = QVariant(),
- const QVariant &arg5 = QVariant(),
- const QVariant &arg6 = QVariant(),
- const QVariant &arg7 = QVariant(),
- const QVariant &arg8 = QVariant());
+ const QVariant &arg1,
+ const QVariant &arg2,
+ const QVariant &arg3,
+ const QVariant &arg4,
+ const QVariant &arg5,
+ const QVariant &arg6,
+ const QVariant &arg7,
+ const QVariant &arg8);
+#endif // Qt 5
QDBusMessage callWithArgumentList(QDBus::CallMode mode,
const QString &method,
@@ -130,15 +157,30 @@ public:
const QList<QVariant> &args,
QObject *receiver, const char *member);
+ QDBusPendingCall asyncCall(const QString &method)
+ {
+ return doAsyncCall(method, nullptr, 0);
+ }
+
+ template <typename...Args>
+ QDBusPendingCall asyncCall(const QString &method, Args&&...args)
+ {
+ const QVariant variants[] = { QVariant(std::forward<Args>(args))... };
+ return doAsyncCall(method, variants, sizeof...(args));
+ }
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QDBusPendingCall asyncCall(const QString &method,
- const QVariant &arg1 = QVariant(),
- const QVariant &arg2 = QVariant(),
- const QVariant &arg3 = QVariant(),
- const QVariant &arg4 = QVariant(),
- const QVariant &arg5 = QVariant(),
- const QVariant &arg6 = QVariant(),
- const QVariant &arg7 = QVariant(),
- const QVariant &arg8 = QVariant());
+ const QVariant &arg1,
+ const QVariant &arg2,
+ const QVariant &arg3,
+ const QVariant &arg4,
+ const QVariant &arg5,
+ const QVariant &arg6,
+ const QVariant &arg7,
+ const QVariant &arg8);
+#endif // Qt 5
+
QDBusPendingCall asyncCallWithArgumentList(const QString &method,
const QList<QVariant> &args);
@@ -156,6 +198,10 @@ protected:
const QList<QVariant> &args = QList<QVariant>()) const;
private:
+ QDBusMessage doCall(QDBus::CallMode mode, const QString &method, const QVariant *args, size_t numArgs);
+ QDBusPendingCall doAsyncCall(const QString &method, const QVariant *args, size_t numArgs);
+
+private:
Q_DECLARE_PRIVATE(QDBusAbstractInterface)
Q_PRIVATE_SLOT(d_func(), void _q_serviceOwnerChanged(QString,QString,QString))
};
diff --git a/src/dbus/qdbusargument.cpp b/src/dbus/qdbusargument.cpp
index a33c4f8363..764bc24165 100644
--- a/src/dbus/qdbusargument.cpp
+++ b/src/dbus/qdbusargument.cpp
@@ -111,7 +111,7 @@ bool QDBusArgumentPrivate::checkWrite(QDBusArgumentPrivate *&d)
if (!d->marshaller()->ok)
return false;
- if (d->message && d->ref.load() != 1) {
+ if (d->message && d->ref.loadRelaxed() != 1) {
QDBusMarshaller *dd = new QDBusMarshaller(d->capabilities);
dd->message = q_dbus_message_copy(d->message);
q_dbus_message_iter_init_append(dd->message, &dd->iterator);
@@ -152,7 +152,7 @@ bool QDBusArgumentPrivate::checkReadAndDetach(QDBusArgumentPrivate *&d)
if (!checkRead(d))
return false; // don't bother
- if (d->ref.load() == 1)
+ if (d->ref.loadRelaxed() == 1)
return true; // no need to detach
QDBusDemarshaller *dd = new QDBusDemarshaller(d->capabilities);
@@ -267,7 +267,7 @@ bool QDBusArgumentPrivate::checkReadAndDetach(QDBusArgumentPrivate *&d)
*/
/*!
- \fn qdbus_cast(const QDBusArgument &arg)
+ \fn template<typename T> T qdbus_cast(const QDBusArgument &arg, T*)
\relates QDBusArgument
\since 4.2
diff --git a/src/dbus/qdbusargument.h b/src/dbus/qdbusargument.h
index a6d4e9cd25..b7cd4c8989 100644
--- a/src/dbus/qdbusargument.h
+++ b/src/dbus/qdbusargument.h
@@ -76,14 +76,12 @@ public:
QDBusArgument();
QDBusArgument(const QDBusArgument &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QDBusArgument(QDBusArgument &&other) Q_DECL_NOTHROW : d(other.d) { other.d = nullptr; }
- QDBusArgument &operator=(QDBusArgument &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDBusArgument(QDBusArgument &&other) noexcept : d(other.d) { other.d = nullptr; }
+ QDBusArgument &operator=(QDBusArgument &&other) noexcept { swap(other); return *this; }
QDBusArgument &operator=(const QDBusArgument &other);
~QDBusArgument();
- void swap(QDBusArgument &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QDBusArgument &other) noexcept { qSwap(d, other.d); }
// used for marshalling (Qt -> D-BUS)
QDBusArgument &operator<<(uchar arg);
@@ -158,22 +156,15 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(QDBusArgument)
QT_BEGIN_NAMESPACE
-template<typename T> inline T qdbus_cast(const QDBusArgument &arg
-#ifndef Q_QDOC
-, T * = nullptr
-#endif
- )
+// ### Qt6: remove the defaulted T * = nullptr from these two (MSVC6 work-around):
+template<typename T> inline T qdbus_cast(const QDBusArgument &arg, T * = nullptr)
{
T item;
arg >> item;
return item;
}
-template<typename T> inline T qdbus_cast(const QVariant &v
-#ifndef Q_QDOC
-, T * = nullptr
-#endif
- )
+template<typename T> inline T qdbus_cast(const QVariant &v, T * = nullptr)
{
int id = v.userType();
if (id == qMetaTypeId<QDBusArgument>())
diff --git a/src/dbus/qdbusargument_p.h b/src/dbus/qdbusargument_p.h
index 559f8b1186..3553d3d151 100644
--- a/src/dbus/qdbusargument_p.h
+++ b/src/dbus/qdbusargument_p.h
@@ -71,7 +71,7 @@ class QDBusArgumentPrivate
{
public:
inline QDBusArgumentPrivate(int flags = 0)
- : message(0), ref(1), capabilities(flags)
+ : message(nullptr), ref(1), capabilities(flags)
{ }
virtual ~QDBusArgumentPrivate();
@@ -104,7 +104,7 @@ public:
class QDBusMarshaller: public QDBusArgumentPrivate
{
public:
- QDBusMarshaller(int flags) : QDBusArgumentPrivate(flags), parent(0), ba(0), closeCode(0), ok(true), skipSignature(false)
+ QDBusMarshaller(int flags) : QDBusArgumentPrivate(flags), parent(nullptr), ba(nullptr), closeCode(0), ok(true), skipSignature(false)
{ direction = Marshalling; }
~QDBusMarshaller();
@@ -155,13 +155,13 @@ public:
bool skipSignature;
private:
- Q_DISABLE_COPY(QDBusMarshaller)
+ Q_DISABLE_COPY_MOVE(QDBusMarshaller)
};
class QDBusDemarshaller: public QDBusArgumentPrivate
{
public:
- inline QDBusDemarshaller(int flags) : QDBusArgumentPrivate(flags), parent(0)
+ inline QDBusDemarshaller(int flags) : QDBusArgumentPrivate(flags), parent(nullptr)
{ direction = Demarshalling; }
~QDBusDemarshaller();
@@ -208,7 +208,7 @@ public:
QDBusDemarshaller *parent;
private:
- Q_DISABLE_COPY(QDBusDemarshaller)
+ Q_DISABLE_COPY_MOVE(QDBusDemarshaller)
QString toStringUnchecked();
QDBusObjectPath toObjectPathUnchecked();
QDBusSignature toSignatureUnchecked();
diff --git a/src/dbus/qdbusconnection.h b/src/dbus/qdbusconnection.h
index ca7adfaaeb..368f811602 100644
--- a/src/dbus/qdbusconnection.h
+++ b/src/dbus/qdbusconnection.h
@@ -122,9 +122,7 @@ public:
SubPath = 0x1
// Reserved = 0xff000000
};
-#ifndef Q_QDOC
Q_DECLARE_FLAGS(VirtualObjectRegisterOptions, VirtualObjectRegisterOption)
-#endif
enum ConnectionCapability {
UnixFileDescriptorPassing = 0x0001
@@ -133,14 +131,12 @@ public:
explicit QDBusConnection(const QString &name);
QDBusConnection(const QDBusConnection &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QDBusConnection(QDBusConnection &&other) Q_DECL_NOTHROW : d(other.d) { other.d = nullptr; }
- QDBusConnection &operator=(QDBusConnection &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDBusConnection(QDBusConnection &&other) noexcept : d(other.d) { other.d = nullptr; }
+ QDBusConnection &operator=(QDBusConnection &&other) noexcept { swap(other); return *this; }
QDBusConnection &operator=(const QDBusConnection &other);
~QDBusConnection();
- void swap(QDBusConnection &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QDBusConnection &other) noexcept { qSwap(d, other.d); }
bool isConnected() const;
QString baseService() const;
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index 444d4727fd..da67a6c5d4 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -94,7 +94,7 @@ class QDBusServer;
class QDBusErrorInternal
{
mutable DBusError error;
- Q_DISABLE_COPY(QDBusErrorInternal)
+ Q_DISABLE_COPY_MOVE(QDBusErrorInternal)
public:
inline QDBusErrorInternal() { q_dbus_error_init(&error); }
inline ~QDBusErrorInternal() { q_dbus_error_free(&error); }
@@ -115,20 +115,29 @@ public:
struct Watcher
{
- Watcher(): watch(0), read(0), write(0) {}
+ Watcher(): watch(nullptr), read(nullptr), write(nullptr) {}
DBusWatch *watch;
QSocketNotifier *read;
QSocketNotifier *write;
};
+ struct ArgMatchRules {
+ QStringList args;
+ QString arg0namespace;
+ bool operator==(const ArgMatchRules &other) const {
+ return args == other.args &&
+ arg0namespace == other.arg0namespace;
+ }
+ };
+
struct SignalHook
{
- inline SignalHook() : obj(0), midx(-1) { }
+ inline SignalHook() : obj(nullptr), midx(-1) { }
QString service, path, signature;
QObject* obj;
int midx;
QVector<int> params;
- QStringList argumentMatch;
+ ArgMatchRules argumentMatch;
QByteArray matchRule;
};
@@ -141,9 +150,9 @@ public:
{
typedef QVector<ObjectTreeNode> DataList;
- inline ObjectTreeNode() : obj(0), flags(0) { }
+ inline ObjectTreeNode() : obj(nullptr), flags(0) { }
inline ObjectTreeNode(const QString &n) // intentionally implicit
- : name(n), obj(0), flags(0) { }
+ : name(n), obj(nullptr), flags(0) { }
inline bool operator<(const QString &other) const
{ return name < other; }
inline bool operator<(const QStringRef &other) const
@@ -185,7 +194,7 @@ public:
public:
// public methods are entry points from other objects
- explicit QDBusConnectionPrivate(QObject *parent = 0);
+ explicit QDBusConnectionPrivate(QObject *parent = nullptr);
~QDBusConnectionPrivate();
void createBusService();
@@ -207,12 +216,19 @@ public:
QDBusMessage sendWithReplyLocal(const QDBusMessage &message);
QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
const char *returnMethod, const char *errorMethod,int timeout = -1);
+
bool connectSignal(const QString &service, const QString &path, const QString& interface,
const QString &name, const QStringList &argumentMatch, const QString &signature,
QObject *receiver, const char *slot);
bool disconnectSignal(const QString &service, const QString &path, const QString& interface,
const QString &name, const QStringList &argumentMatch, const QString &signature,
QObject *receiver, const char *slot);
+ bool connectSignal(const QString &service, const QString &path, const QString& interface,
+ const QString &name, const ArgMatchRules &argumentMatch, const QString &signature,
+ QObject *receiver, const char *slot);
+ bool disconnectSignal(const QString &service, const QString &path, const QString& interface,
+ const QString &name, const ArgMatchRules &argumentMatch, const QString &signature,
+ QObject *receiver, const char *slot);
void registerObject(const ObjectTreeNode *node);
void unregisterObject(const QString &path, QDBusConnection::UnregisterMode mode);
void connectRelay(const QString &service,
@@ -332,7 +348,7 @@ public:
static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
const QString &service,
const QString &path, const QString &interface, const QString &name,
- const QStringList &argMatch,
+ const ArgMatchRules &argMatch,
QObject *receiver, const char *signal, int minMIdx,
bool buildSignature);
static DBusHandlerResult messageFilter(DBusConnection *, DBusMessage *, void *);
diff --git a/src/dbus/qdbuserror.cpp b/src/dbus/qdbuserror.cpp
index e966f9dcde..decd345ece 100644
--- a/src/dbus/qdbuserror.cpp
+++ b/src/dbus/qdbuserror.cpp
@@ -41,6 +41,7 @@
#include <qdebug.h>
#include <qvarlengtharray.h>
+#include <private/qoffsetstringarray_p.h>
#ifndef QT_BOOTSTRAPPED
#include "qdbus_symbols_p.h"
@@ -52,110 +53,46 @@
QT_BEGIN_NAMESPACE
-/*
- * Use the following Perl script to generate the error string index list:
-===== PERL SCRIPT ====
-print "static const char errorMessages_string[] =\n";
-$counter = 0;
-$i = 0;
-while (<STDIN>) {
- chomp;
- print " \"$_\\0\"\n";
- $sizes[$i++] = $counter;
- $counter += 1 + length $_;
-}
-print " \"\\0\";\n\nstatic const int errorMessages_indices[] = {\n ";
-for ($j = 0; $j < $i; ++$j) {
- printf "$sizes[$j], ";
-}
-print "0\n};\n";
-===== PERL SCRIPT ====
-
- * The input data is as follows:
-other
-org.freedesktop.DBus.Error.Failed
-org.freedesktop.DBus.Error.NoMemory
-org.freedesktop.DBus.Error.ServiceUnknown
-org.freedesktop.DBus.Error.NoReply
-org.freedesktop.DBus.Error.BadAddress
-org.freedesktop.DBus.Error.NotSupported
-org.freedesktop.DBus.Error.LimitsExceeded
-org.freedesktop.DBus.Error.AccessDenied
-org.freedesktop.DBus.Error.NoServer
-org.freedesktop.DBus.Error.Timeout
-org.freedesktop.DBus.Error.NoNetwork
-org.freedesktop.DBus.Error.AddressInUse
-org.freedesktop.DBus.Error.Disconnected
-org.freedesktop.DBus.Error.InvalidArgs
-org.freedesktop.DBus.Error.UnknownMethod
-org.freedesktop.DBus.Error.TimedOut
-org.freedesktop.DBus.Error.InvalidSignature
-org.freedesktop.DBus.Error.UnknownInterface
-org.freedesktop.DBus.Error.UnknownObject
-org.freedesktop.DBus.Error.UnknownProperty
-org.freedesktop.DBus.Error.PropertyReadOnly
-org.qtproject.QtDBus.Error.InternalError
-org.qtproject.QtDBus.Error.InvalidService
-org.qtproject.QtDBus.Error.InvalidObjectPath
-org.qtproject.QtDBus.Error.InvalidInterface
-org.qtproject.QtDBus.Error.InvalidMember
-*/
-
-// in the same order as KnownErrors!
-static const char errorMessages_string[] =
- "other\0"
- "org.freedesktop.DBus.Error.Failed\0"
- "org.freedesktop.DBus.Error.NoMemory\0"
- "org.freedesktop.DBus.Error.ServiceUnknown\0"
- "org.freedesktop.DBus.Error.NoReply\0"
- "org.freedesktop.DBus.Error.BadAddress\0"
- "org.freedesktop.DBus.Error.NotSupported\0"
- "org.freedesktop.DBus.Error.LimitsExceeded\0"
- "org.freedesktop.DBus.Error.AccessDenied\0"
- "org.freedesktop.DBus.Error.NoServer\0"
- "org.freedesktop.DBus.Error.Timeout\0"
- "org.freedesktop.DBus.Error.NoNetwork\0"
- "org.freedesktop.DBus.Error.AddressInUse\0"
- "org.freedesktop.DBus.Error.Disconnected\0"
- "org.freedesktop.DBus.Error.InvalidArgs\0"
- "org.freedesktop.DBus.Error.UnknownMethod\0"
- "org.freedesktop.DBus.Error.TimedOut\0"
- "org.freedesktop.DBus.Error.InvalidSignature\0"
- "org.freedesktop.DBus.Error.UnknownInterface\0"
- "org.freedesktop.DBus.Error.UnknownObject\0"
- "org.freedesktop.DBus.Error.UnknownProperty\0"
- "org.freedesktop.DBus.Error.PropertyReadOnly\0"
- "org.qtproject.QtDBus.Error.InternalError\0"
- "org.qtproject.QtDBus.Error.InvalidService\0"
- "org.qtproject.QtDBus.Error.InvalidObjectPath\0"
- "org.qtproject.QtDBus.Error.InvalidInterface\0"
- "org.qtproject.QtDBus.Error.InvalidMember\0"
- "\0";
-
-static const int errorMessages_indices[] = {
- 0, 6, 40, 76, 118, 153, 191, 231,
- 273, 313, 349, 384, 421, 461, 501, 540,
- 581, 617, 661, 705, 746, 789, 833, 874,
- 916, 961, 1005
-};
-
-static const int errorMessages_count = sizeof errorMessages_indices /
- sizeof errorMessages_indices[0];
-
-static inline const char *get(QDBusError::ErrorType code)
-{
- int intcode = qBound(0, int(code) - int(QDBusError::Other), errorMessages_count);
- return errorMessages_string + errorMessages_indices[intcode];
-}
+static constexpr const auto errorMessages = qOffsetStringArray(
+ "NoError",
+ "other",
+ "org.freedesktop.DBus.Error.Failed",
+ "org.freedesktop.DBus.Error.NoMemory",
+ "org.freedesktop.DBus.Error.ServiceUnknown",
+ "org.freedesktop.DBus.Error.NoReply",
+ "org.freedesktop.DBus.Error.BadAddress",
+ "org.freedesktop.DBus.Error.NotSupported",
+ "org.freedesktop.DBus.Error.LimitsExceeded",
+ "org.freedesktop.DBus.Error.AccessDenied",
+ "org.freedesktop.DBus.Error.NoServer",
+ "org.freedesktop.DBus.Error.Timeout",
+ "org.freedesktop.DBus.Error.NoNetwork",
+ "org.freedesktop.DBus.Error.AddressInUse",
+ "org.freedesktop.DBus.Error.Disconnected",
+ "org.freedesktop.DBus.Error.InvalidArgs",
+ "org.freedesktop.DBus.Error.UnknownMethod",
+ "org.freedesktop.DBus.Error.TimedOut",
+ "org.freedesktop.DBus.Error.InvalidSignature",
+ "org.freedesktop.DBus.Error.UnknownInterface",
+ "org.freedesktop.DBus.Error.UnknownObject",
+ "org.freedesktop.DBus.Error.UnknownProperty",
+ "org.freedesktop.DBus.Error.PropertyReadOnly",
+ "org.qtproject.QtDBus.Error.InternalError",
+ "org.qtproject.QtDBus.Error.InvalidService",
+ "org.qtproject.QtDBus.Error.InvalidObjectPath",
+ "org.qtproject.QtDBus.Error.InvalidInterface",
+ "org.qtproject.QtDBus.Error.InvalidMember",
+ ""
+);
#ifndef QT_BOOTSTRAPPED
static inline QDBusError::ErrorType get(const char *name)
{
if (!name || !*name)
return QDBusError::NoError;
- for (int i = 0; i < errorMessages_count; ++i)
- if (strcmp(name, errorMessages_string + errorMessages_indices[i]) == 0)
- return QDBusError::ErrorType(i + int(QDBusError::Other));
+ for (int i = 0; i < errorMessages.count(); ++i)
+ if (strcmp(name, errorMessages.at(i)) == 0)
+ return QDBusError::ErrorType(i);
return QDBusError::Other;
}
#endif
@@ -301,7 +238,7 @@ QDBusError::QDBusError(const QDBusMessage &qdmsg)
QDBusError::QDBusError(ErrorType error, const QString &mess)
: code(error)
{
- nm = QLatin1String(::get(error));
+ nm = QLatin1String(errorMessages[error]);
msg = mess;
}
@@ -397,7 +334,7 @@ bool QDBusError::isValid() const
*/
QString QDBusError::errorString(ErrorType error)
{
- return QLatin1String(::get(error));
+ return QLatin1String(errorMessages[error]);
}
#ifndef QT_NO_DEBUG_STREAM
@@ -418,3 +355,11 @@ QDebug operator<<(QDebug dbg, const QDBusError &msg)
QT_END_NAMESPACE
#endif // QT_NO_DBUS
+
+/*
+MSVC2015 has the warning C4503 at the end of the file:
+QtPrivate::StaticStringBuilder<QtPrivate::IndexesList<...> - decorated name length exceeded, name was truncated
+It is used by qOffsetStringArray in a constexpr evaulation and this code does not exist in the object file,
+but we still have the warning or even error with -WX flag
+*/
+QT_WARNING_DISABLE_MSVC(4503)
diff --git a/src/dbus/qdbuserror.h b/src/dbus/qdbuserror.h
index c264f62b7d..bcf68dbcdc 100644
--- a/src/dbus/qdbuserror.h
+++ b/src/dbus/qdbuserror.h
@@ -98,18 +98,16 @@ public:
#endif
QDBusError(ErrorType error, const QString &message);
QDBusError(const QDBusError &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QDBusError(QDBusError &&other) Q_DECL_NOTHROW
+ QDBusError(QDBusError &&other) noexcept
: code(other.code), msg(std::move(other.msg)), nm(std::move(other.nm))
{}
- QDBusError &operator=(QDBusError &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDBusError &operator=(QDBusError &&other) noexcept { swap(other); return *this; }
QDBusError &operator=(const QDBusError &other);
#ifndef QT_BOOTSTRAPPED
QDBusError &operator=(const QDBusMessage &msg);
#endif
- void swap(QDBusError &other) Q_DECL_NOTHROW
+ void swap(QDBusError &other) noexcept
{
qSwap(code, other.code);
qSwap(msg, other.msg);
diff --git a/src/dbus/qdbusextratypes.h b/src/dbus/qdbusextratypes.h
index 12961e2702..fdac917947 100644
--- a/src/dbus/qdbusextratypes.h
+++ b/src/dbus/qdbusextratypes.h
@@ -59,18 +59,16 @@ class Q_DBUS_EXPORT QDBusObjectPath
{
QString m_path;
public:
- QDBusObjectPath() Q_DECL_NOTHROW : m_path() {}
+ QDBusObjectPath() noexcept : m_path() {}
// compiler-generated copy/move constructor/assignment operators are ok!
// compiler-generated destructor is ok!
inline explicit QDBusObjectPath(const char *path);
inline explicit QDBusObjectPath(QLatin1String path);
inline explicit QDBusObjectPath(const QString &path);
-#ifdef Q_COMPILER_RVALUE_REFS
explicit QDBusObjectPath(QString &&p) : m_path(std::move(p)) { doCheck(); }
-#endif
- void swap(QDBusObjectPath &other) Q_DECL_NOTHROW { qSwap(m_path, other.m_path); }
+ void swap(QDBusObjectPath &other) noexcept { qSwap(m_path, other.m_path); }
inline void setPath(const QString &path);
@@ -114,18 +112,16 @@ class Q_DBUS_EXPORT QDBusSignature
{
QString m_signature;
public:
- QDBusSignature() Q_DECL_NOTHROW : m_signature() {}
+ QDBusSignature() noexcept : m_signature() {}
// compiler-generated copy/move constructor/assignment operators are ok!
// compiler-generated destructor is ok!
inline explicit QDBusSignature(const char *signature);
inline explicit QDBusSignature(QLatin1String signature);
inline explicit QDBusSignature(const QString &signature);
-#ifdef Q_COMPILER_RVALUE_REFS
explicit QDBusSignature(QString &&sig) : m_signature(std::move(sig)) { doCheck(); }
-#endif
- void swap(QDBusSignature &other) Q_DECL_NOTHROW { qSwap(m_signature, other.m_signature); }
+ void swap(QDBusSignature &other) noexcept { qSwap(m_signature, other.m_signature); }
inline void setSignature(const QString &signature);
@@ -168,16 +164,14 @@ class QDBusVariant
{
QVariant m_variant;
public:
- QDBusVariant() Q_DECL_NOTHROW : m_variant() {}
+ QDBusVariant() noexcept : m_variant() {}
// compiler-generated copy/move constructor/assignment operators are ok!
// compiler-generated destructor is ok!
inline explicit QDBusVariant(const QVariant &variant);
-#ifdef Q_COMPILER_RVALUE_REFS
- explicit QDBusVariant(QVariant &&v) Q_DECL_NOTHROW : m_variant(std::move(v)) {}
-#endif
+ explicit QDBusVariant(QVariant &&v) noexcept : m_variant(std::move(v)) {}
- void swap(QDBusVariant &other) Q_DECL_NOTHROW { qSwap(m_variant, other.m_variant); }
+ void swap(QDBusVariant &other) noexcept { qSwap(m_variant, other.m_variant); }
inline void setVariant(const QVariant &variant);
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index dfef25e3a8..9306498f89 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -338,10 +338,11 @@ void QDBusConnectionPrivate::_q_newConnection(QDBusConnectionPrivate *newConnect
static QByteArray buildMatchRule(const QString &service,
const QString &objectPath, const QString &interface,
- const QString &member, const QStringList &argMatch, const QString & /*signature*/)
+ const QString &member, const QDBusConnectionPrivate::ArgMatchRules &argMatch, const QString & /*signature*/)
{
- QString result = QLatin1String("type='signal',");
- QString keyValue = QLatin1String("%1='%2',");
+ QString result;
+ result += QLatin1String("type='signal',");
+ const auto keyValue = QLatin1String("%1='%2',");
if (!service.isEmpty())
result += keyValue.arg(QLatin1String("sender"), service);
@@ -353,11 +354,14 @@ static QByteArray buildMatchRule(const QString &service,
result += keyValue.arg(QLatin1String("member"), member);
// add the argument string-matching now
- if (!argMatch.isEmpty()) {
- keyValue = QLatin1String("arg%1='%2',");
- for (int i = 0; i < argMatch.count(); ++i)
- if (!argMatch.at(i).isNull())
- result += keyValue.arg(i).arg(argMatch.at(i));
+ if (!argMatch.args.isEmpty()) {
+ const QString keyValue = QLatin1String("arg%1='%2',");
+ for (int i = 0; i < argMatch.args.count(); ++i)
+ if (!argMatch.args.at(i).isNull())
+ result += keyValue.arg(i).arg(argMatch.args.at(i));
+ }
+ if (!argMatch.arg0namespace.isEmpty()) {
+ result += QLatin1String("arg0namespace='%1',").arg(argMatch.arg0namespace);
}
result.chop(1); // remove ending comma
@@ -456,21 +460,26 @@ static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *ro
return 0;
}
-static QStringList matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode)
+static QDBusConnectionPrivate::ArgMatchRules matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode)
{
- QStringList matchArgs;
- matchArgs << service;
+ QDBusConnectionPrivate::ArgMatchRules matchArgs;
+ if (service.endsWith(QLatin1Char('*'))) {
+ matchArgs.arg0namespace = service.chopped(1);
+ matchArgs.args << QString();
+ }
+ else
+ matchArgs.args << service;
switch (mode) {
case QDBusServiceWatcher::WatchForOwnerChange:
break;
case QDBusServiceWatcher::WatchForRegistration:
- matchArgs << QString::fromLatin1("", 0);
+ matchArgs.args << QString::fromLatin1("", 0);
break;
case QDBusServiceWatcher::WatchForUnregistration:
- matchArgs << QString() << QString::fromLatin1("", 0);
+ matchArgs.args << QString() << QString::fromLatin1("", 0);
break;
}
return matchArgs;
@@ -526,7 +535,7 @@ qDBusSignalFilter(DBusConnection *connection, DBusMessage *message, void *data)
bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg)
{
- if (!ref.load())
+ if (!ref.loadRelaxed())
return false;
// local message are always delivered, regardless of filtering
@@ -1069,7 +1078,7 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate()
if (lastMode == ClientMode || lastMode == PeerMode) {
// the bus service object holds a reference back to us;
// we need to destroy it before we finish destroying ourselves
- Q_ASSERT(ref.load() == 0);
+ Q_ASSERT(ref.loadRelaxed() == 0);
QObject *obj = (QObject *)busService;
if (obj) {
disconnect(obj, nullptr, this, nullptr);
@@ -1188,7 +1197,7 @@ void QDBusConnectionPrivate::doDispatch()
PendingMessageList::Iterator end = pendingMessages.end();
for ( ; it != end; ++it) {
qDBusDebug() << this << "dequeueing message" << *it;
- handleMessage(qMove(*it));
+ handleMessage(std::move(*it));
}
pendingMessages.clear();
}
@@ -1311,7 +1320,7 @@ int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedN
bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
const QString &service,
const QString &path, const QString &interface, const QString &name,
- const QStringList &argMatch,
+ const ArgMatchRules &argMatch,
QObject *receiver, const char *signal, int minMIdx,
bool buildSignature)
{
@@ -1322,8 +1331,6 @@ bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hoo
hook.midx = findSlot(receiver, normalizedName, hook.params);
}
if (hook.midx < minMIdx) {
- if (hook.midx == -1)
- {}
return false;
}
@@ -1363,19 +1370,19 @@ void QDBusConnectionPrivate::sendError(const QDBusMessage &msg, QDBusError::Erro
if (msg.interface().isEmpty())
interfaceMsg = QLatin1String("any interface");
else
- interfaceMsg = QString::fromLatin1("interface '%1'").arg(msg.interface());
+ interfaceMsg = QLatin1String("interface '%1'").arg(msg.interface());
send(msg.createErrorReply(code,
- QString::fromLatin1("No such method '%1' in %2 at object path '%3' "
- "(signature '%4')")
+ QLatin1String("No such method '%1' in %2 at object path '%3' "
+ "(signature '%4')")
.arg(msg.member(), interfaceMsg, msg.path(), msg.signature())));
} else if (code == QDBusError::UnknownInterface) {
send(msg.createErrorReply(QDBusError::UnknownInterface,
- QString::fromLatin1("No such interface '%1' at object path '%2'")
+ QLatin1String("No such interface '%1' at object path '%2'")
.arg(msg.interface(), msg.path())));
} else if (code == QDBusError::UnknownObject) {
send(msg.createErrorReply(QDBusError::UnknownObject,
- QString::fromLatin1("No such object path '%1'").arg(msg.path())));
+ QLatin1String("No such object path '%1'").arg(msg.path())));
}
}
@@ -1545,8 +1552,8 @@ void QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
objThread = result.obj->thread();
if (!objThread) {
send(msg.createErrorReply(QDBusError::InternalError,
- QString::fromLatin1("Object '%1' (at path '%2')"
- " has no thread. Cannot deliver message.")
+ QLatin1String("Object '%1' (at path '%2')"
+ " has no thread. Cannot deliver message.")
.arg(result.obj->objectName(), msg.path())));
return;
}
@@ -1621,14 +1628,14 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage
continue;
if (hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty())
continue;
- if (!hook.argumentMatch.isEmpty()) {
+ if (!hook.argumentMatch.args.isEmpty()) {
const QVariantList arguments = msg.arguments();
- if (hook.argumentMatch.size() > arguments.size())
+ if (hook.argumentMatch.args.size() > arguments.size())
continue;
bool matched = true;
- for (int i = 0; i < hook.argumentMatch.size(); ++i) {
- const QString &param = hook.argumentMatch.at(i);
+ for (int i = 0; i < hook.argumentMatch.args.size(); ++i) {
+ const QString &param = hook.argumentMatch.args.at(i);
if (param.isNull())
continue; // don't try to match against this
if (param == arguments.at(i).toString())
@@ -1639,7 +1646,15 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage
if (!matched)
continue;
}
-
+ if (!hook.argumentMatch.arg0namespace.isEmpty()) {
+ const QVariantList arguments = msg.arguments();
+ if (arguments.size() < 1)
+ continue;
+ const QString param = arguments.at(0).toString();
+ if (param != hook.argumentMatch.arg0namespace
+ && !param.startsWith(hook.argumentMatch.arg0namespace + QLatin1Char('.')))
+ continue;
+ }
activateSignal(hook, msg);
}
}
@@ -2068,7 +2083,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &mess
if (interface.isEmpty())
interface = QLatin1String("<no-interface>");
return QDBusMessage::createError(QDBusError::InternalError,
- QString::fromLatin1("Internal error trying to call %1.%2 at %3 (signature '%4'")
+ QLatin1String("Internal error trying to call %1.%2 at %3 (signature '%4'")
.arg(interface, message.member(),
message.path(), message.signature()));
}
@@ -2112,11 +2127,11 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM
if ((receiver && returnMethod) || errorMethod) {
// no one waiting, will delete pcall in processFinishedCall()
- pcall->ref.store(1);
+ pcall->ref.storeRelaxed(1);
} else {
// set double ref to prevent race between processFinishedCall() and ref counting
// by QDBusPendingCall::QExplicitlySharedDataPointer<QDBusPendingCallPrivate>
- pcall->ref.store(2);
+ pcall->ref.storeRelaxed(2);
}
if (isLoopback) {
@@ -2181,11 +2196,22 @@ void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall, void *
}
}
+
bool QDBusConnectionPrivate::connectSignal(const QString &service,
const QString &path, const QString &interface, const QString &name,
const QStringList &argumentMatch, const QString &signature,
QObject *receiver, const char *slot)
{
+ ArgMatchRules rules;
+ rules.args = argumentMatch;
+ return connectSignal(service, path, interface, name, rules, signature, receiver, slot);
+}
+
+bool QDBusConnectionPrivate::connectSignal(const QString &service,
+ const QString &path, const QString &interface, const QString &name,
+ const ArgMatchRules &argumentMatch, const QString &signature,
+ QObject *receiver, const char *slot)
+{
// check the slot
QDBusConnectionPrivate::SignalHook hook;
QString key;
@@ -2242,9 +2268,11 @@ bool QDBusConnectionPrivate::addSignalHook(const QString &key, const SignalHook
WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
if (++data.refcount == 1) {
// we need to watch for this service changing
+ ArgMatchRules rules;
+ rules.args << hook.service;
q_dbus_bus_add_match(connection,
buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
- QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()),
+ QDBusUtil::nameOwnerChanged(), rules, QString()),
NULL);
data.owner = getNameOwnerNoCache(hook.service);
qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
@@ -2257,8 +2285,18 @@ bool QDBusConnectionPrivate::addSignalHook(const QString &key, const SignalHook
}
bool QDBusConnectionPrivate::disconnectSignal(const QString &service,
+ const QString &path, const QString &interface, const QString &name,
+ const QStringList &argumentMatch, const QString &signature,
+ QObject *receiver, const char *slot)
+{
+ ArgMatchRules rules;
+ rules.args = argumentMatch;
+ return disconnectSignal(service, path, interface, name, rules, signature, receiver, slot);
+}
+
+bool QDBusConnectionPrivate::disconnectSignal(const QString &service,
const QString &path, const QString &interface, const QString &name,
- const QStringList &argumentMatch, const QString &signature,
+ const ArgMatchRules &argumentMatch, const QString &signature,
QObject *receiver, const char *slot)
{
// check the slot
@@ -2289,7 +2327,7 @@ bool QDBusConnectionPrivate::removeSignalHook(const QString &key, const SignalHo
entry.signature == hook.signature &&
entry.obj == hook.obj &&
entry.midx == hook.midx &&
- entry.argumentMatch == hook.argumentMatch) {
+ entry.argumentMatch.args == hook.argumentMatch.args) {
// no need to compare the parameters if it's the same slot
removeSignalHookNoLock(it);
return true; // it was there
@@ -2331,9 +2369,11 @@ QDBusConnectionPrivate::removeSignalHookNoLock(SignalHookHash::Iterator it)
if (sit != watchedServices.end()) {
if (--sit.value().refcount == 0) {
watchedServices.erase(sit);
+ ArgMatchRules rules;
+ rules.args << hook.service;
q_dbus_bus_remove_match(connection,
buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
- QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()),
+ QDBusUtil::nameOwnerChanged(), rules, QString()),
NULL);
}
}
@@ -2394,7 +2434,7 @@ void QDBusConnectionPrivate::connectRelay(const QString &service,
QByteArray sig;
sig.append(QSIGNAL_CODE + '0');
sig.append(signal.methodSignature());
- if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, sig,
+ if (!prepareHook(hook, key, service, path, interface, QString(), ArgMatchRules(), receiver, sig,
QDBusAbstractInterface::staticMetaObject.methodCount(), true))
return; // don't connect
@@ -2415,7 +2455,7 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service,
QByteArray sig;
sig.append(QSIGNAL_CODE + '0');
sig.append(signal.methodSignature());
- if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, sig,
+ if (!prepareHook(hook, key, service, path, interface, QString(), ArgMatchRules(), receiver, sig,
QDBusAbstractInterface::staticMetaObject.methodCount(), true))
return; // don't disconnect
@@ -2448,7 +2488,7 @@ bool QDBusConnectionPrivate::shouldWatchService(const QString &service)
*/
void QDBusConnectionPrivate::watchService(const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj, const char *member)
{
- QStringList matchArgs = matchArgsForService(service, mode);
+ ArgMatchRules matchArgs = matchArgsForService(service, mode);
connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
matchArgs, QString(), obj, member);
}
@@ -2463,7 +2503,7 @@ void QDBusConnectionPrivate::watchService(const QString &service, QDBusServiceWa
*/
void QDBusConnectionPrivate::unwatchService(const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj, const char *member)
{
- QStringList matchArgs = matchArgsForService(service, mode);
+ ArgMatchRules matchArgs = matchArgsForService(service, mode);
disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
matchArgs, QString(), obj, member);
}
diff --git a/src/dbus/qdbusintegrator_p.h b/src/dbus/qdbusintegrator_p.h
index 3cd029a933..87db910d25 100644
--- a/src/dbus/qdbusintegrator_p.h
+++ b/src/dbus/qdbusintegrator_p.h
@@ -86,7 +86,7 @@ struct QDBusSlotCache
int slotIdx;
QVector<int> metaTypes;
- void swap(Data &other) Q_DECL_NOTHROW
+ void swap(Data &other) noexcept
{
qSwap(flags, other.flags);
qSwap(slotIdx, other.slotIdx);
@@ -96,41 +96,42 @@ struct QDBusSlotCache
typedef QMultiHash<QString, Data> Hash;
Hash hash;
- void swap(QDBusSlotCache &other) Q_DECL_NOTHROW { qSwap(hash, other.hash); }
+ void swap(QDBusSlotCache &other) noexcept { qSwap(hash, other.hash); }
};
Q_DECLARE_SHARED(QDBusSlotCache::Data)
Q_DECLARE_SHARED(QDBusSlotCache)
-class QDBusCallDeliveryEvent: public QMetaCallEvent
+class QDBusCallDeliveryEvent: public QAbstractMetaCallEvent
{
public:
QDBusCallDeliveryEvent(const QDBusConnection &c, int id, QObject *sender,
const QDBusMessage &msg, const QVector<int> &types, int f = 0)
- : QMetaCallEvent(0, id, 0, sender, -1), connection(c), message(msg), metaTypes(types), flags(f)
+ : QAbstractMetaCallEvent(sender, -1), connection(c), message(msg), metaTypes(types), id(id), flags(f)
{ }
void placeMetaCall(QObject *object) override
{
- QDBusConnectionPrivate::d(connection)->deliverCall(object, flags, message, metaTypes, id());
+ QDBusConnectionPrivate::d(connection)->deliverCall(object, flags, message, metaTypes, id);
}
private:
QDBusConnection connection; // just for refcounting
QDBusMessage message;
QVector<int> metaTypes;
+ int id;
int flags;
};
-class QDBusActivateObjectEvent: public QMetaCallEvent
+class QDBusActivateObjectEvent: public QAbstractMetaCallEvent
{
public:
QDBusActivateObjectEvent(const QDBusConnection &c, QObject *sender,
const QDBusConnectionPrivate::ObjectTreeNode &n,
- int p, const QDBusMessage &m, QSemaphore *s = 0)
- : QMetaCallEvent(0, ushort(-1), 0, sender, -1, 0, 0, 0, s), connection(c), node(n),
+ int p, const QDBusMessage &m, QSemaphore *s = nullptr)
+ : QAbstractMetaCallEvent(sender, -1, s), connection(c), node(n),
pathStartPos(p), message(m), handled(false)
{ }
- ~QDBusActivateObjectEvent();
+ ~QDBusActivateObjectEvent() override;
void placeMetaCall(QObject *) override;
@@ -142,15 +143,15 @@ private:
bool handled;
};
-class QDBusSpyCallEvent : public QMetaCallEvent
+class QDBusSpyCallEvent : public QAbstractMetaCallEvent
{
public:
typedef void (*Hook)(const QDBusMessage&);
QDBusSpyCallEvent(QDBusConnectionPrivate *cp, const QDBusConnection &c, const QDBusMessage &msg,
const Hook *hooks, int count)
- : QMetaCallEvent(0, 0, nullptr, cp, 0), conn(c), msg(msg), hooks(hooks), hookCount(count)
+ : QAbstractMetaCallEvent(cp, 0), conn(c), msg(msg), hooks(hooks), hookCount(count)
{}
- ~QDBusSpyCallEvent();
+ ~QDBusSpyCallEvent() override;
void placeMetaCall(QObject *) override;
static inline void invokeSpyHooks(const QDBusMessage &msg, const Hook *hooks, int hookCount);
diff --git a/src/dbus/qdbusinternalfilters.cpp b/src/dbus/qdbusinternalfilters.cpp
index 0ef5061b5f..edee4fc1e5 100644
--- a/src/dbus/qdbusinternalfilters.cpp
+++ b/src/dbus/qdbusinternalfilters.cpp
@@ -203,7 +203,7 @@ QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node
static inline QDBusMessage interfaceNotFoundError(const QDBusMessage &msg, const QString &interface_name)
{
return msg.createErrorReply(QDBusError::UnknownInterface,
- QString::fromLatin1("Interface %1 was not found in object %2")
+ QLatin1String("Interface %1 was not found in object %2")
.arg(interface_name, msg.path()));
}
@@ -211,10 +211,10 @@ static inline QDBusMessage
propertyNotFoundError(const QDBusMessage &msg, const QString &interface_name, const QByteArray &property_name)
{
return msg.createErrorReply(QDBusError::UnknownProperty,
- QString::fromLatin1("Property %1%2%3 was not found in object %4")
+ QLatin1String("Property %1%2%3 was not found in object %4")
.arg(interface_name,
- QString::fromLatin1(interface_name.isEmpty() ? "" : "."),
- QString::fromLatin1(property_name),
+ QLatin1String(interface_name.isEmpty() ? "" : "."),
+ QLatin1String(property_name),
msg.path()));
}
@@ -302,16 +302,16 @@ static QDBusMessage propertyWriteReply(const QDBusMessage &msg, const QString &i
return propertyNotFoundError(msg, interface_name, property_name);
case PropertyTypeMismatch:
return msg.createErrorReply(QDBusError::InvalidArgs,
- QString::fromLatin1("Invalid arguments for writing to property %1%2%3")
+ QLatin1String("Invalid arguments for writing to property %1%2%3")
.arg(interface_name,
- QString::fromLatin1(interface_name.isEmpty() ? "" : "."),
- QString::fromLatin1(property_name)));
+ QLatin1String(interface_name.isEmpty() ? "" : "."),
+ QLatin1String(property_name)));
case PropertyReadOnly:
return msg.createErrorReply(QDBusError::PropertyReadOnly,
- QString::fromLatin1("Property %1%2%3 is read-only")
+ QLatin1String("Property %1%2%3 is read-only")
.arg(interface_name,
- QString::fromLatin1(interface_name.isEmpty() ? "" : "."),
- QString::fromLatin1(property_name)));
+ QLatin1String(interface_name.isEmpty() ? "" : "."),
+ QLatin1String(property_name)));
case PropertyWriteFailed:
return msg.createErrorReply(QDBusError::InternalError,
QString::fromLatin1("Internal error"));
diff --git a/src/dbus/qdbusmarshaller.cpp b/src/dbus/qdbusmarshaller.cpp
index 4ea6cefff6..8e0b3e4598 100644
--- a/src/dbus/qdbusmarshaller.cpp
+++ b/src/dbus/qdbusmarshaller.cpp
@@ -211,7 +211,7 @@ inline bool QDBusMarshaller::append(const QDBusVariant &arg)
qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. "
"Use qDBusRegisterMetaType to register it",
QMetaType::typeName(id), id);
- error(QString::fromLatin1("Unregistered type %1 passed in arguments")
+ error(QLatin1String("Unregistered type %1 passed in arguments")
.arg(QLatin1String(QMetaType::typeName(id))));
return false;
}
@@ -253,7 +253,7 @@ inline QDBusMarshaller *QDBusMarshaller::beginArray(int id)
qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. "
"Use qDBusRegisterMetaType to register it",
QMetaType::typeName(id), id);
- error(QString::fromLatin1("Unregistered type %1 passed in arguments")
+ error(QLatin1String("Unregistered type %1 passed in arguments")
.arg(QLatin1String(QMetaType::typeName(id))));
return this;
}
@@ -268,14 +268,14 @@ inline QDBusMarshaller *QDBusMarshaller::beginMap(int kid, int vid)
qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. "
"Use qDBusRegisterMetaType to register it",
QMetaType::typeName(kid), kid);
- error(QString::fromLatin1("Unregistered type %1 passed in arguments")
+ error(QLatin1String("Unregistered type %1 passed in arguments")
.arg(QLatin1String(QMetaType::typeName(kid))));
return this;
}
if (ksignature[1] != 0 || !QDBusUtil::isValidBasicType(*ksignature)) {
qWarning("QDBusMarshaller: type '%s' (%d) cannot be used as the key type in a D-BUS map.",
QMetaType::typeName(kid), kid);
- error(QString::fromLatin1("Type %1 passed in arguments cannot be used as a key in a map")
+ error(QLatin1String("Type %1 passed in arguments cannot be used as a key in a map")
.arg(QLatin1String(QMetaType::typeName(kid))));
return this;
}
@@ -286,7 +286,7 @@ inline QDBusMarshaller *QDBusMarshaller::beginMap(int kid, int vid)
qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. "
"Use qDBusRegisterMetaType to register it",
typeName, vid);
- error(QString::fromLatin1("Unregistered type %1 passed in arguments")
+ error(QLatin1String("Unregistered type %1 passed in arguments")
.arg(QLatin1String(typeName)));
return this;
}
@@ -417,7 +417,7 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg)
qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. "
"Use qDBusRegisterMetaType to register it",
QMetaType::typeName(id), id);
- error(QString::fromLatin1("Unregistered type %1 passed in arguments")
+ error(QLatin1String("Unregistered type %1 passed in arguments")
.arg(QLatin1String(QMetaType::typeName(id))));
return false;
}
diff --git a/src/dbus/qdbusmessage.h b/src/dbus/qdbusmessage.h
index 23e04045d8..41845317c4 100644
--- a/src/dbus/qdbusmessage.h
+++ b/src/dbus/qdbusmessage.h
@@ -68,13 +68,11 @@ public:
QDBusMessage();
QDBusMessage(const QDBusMessage &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QDBusMessage &operator=(QDBusMessage &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDBusMessage &operator=(QDBusMessage &&other) noexcept { swap(other); return *this; }
QDBusMessage &operator=(const QDBusMessage &other);
~QDBusMessage();
- void swap(QDBusMessage &other) Q_DECL_NOTHROW { qSwap(d_ptr, other.d_ptr); }
+ void swap(QDBusMessage &other) noexcept { qSwap(d_ptr, other.d_ptr); }
static QDBusMessage createSignal(const QString &path, const QString &interface,
const QString &name);
diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp
index c4296f5c55..806cf7b415 100644
--- a/src/dbus/qdbusmetaobject.cpp
+++ b/src/dbus/qdbusmetaobject.cpp
@@ -649,7 +649,7 @@ QDBusMetaObject *QDBusMetaObject::createMetaObject(const QString &interface, con
// mark as an error
error = QDBusError(QDBusError::UnknownInterface,
- QString::fromLatin1("Interface '%1' was not found")
+ QLatin1String("Interface '%1' was not found")
.arg(interface));
return 0;
}
diff --git a/src/dbus/qdbusmetatype.cpp b/src/dbus/qdbusmetatype.cpp
index 0729a3cbbb..58ce4f8930 100644
--- a/src/dbus/qdbusmetatype.cpp
+++ b/src/dbus/qdbusmetatype.cpp
@@ -93,7 +93,7 @@ void QDBusMetaTypeId::init()
// reentrancy is not a problem since everything else is locked on their own
// set the guard variable at the end
- if (!initialized.load()) {
+ if (!initialized.loadRelaxed()) {
// register our types with Qt Core (calling qMetaTypeId<T>() does this implicitly)
(void)message();
(void)argument();
@@ -145,7 +145,7 @@ void QDBusMetaTypeId::init()
qDBusRegisterMetaType<QVector<QDBusUnixFileDescriptor> >();
#endif
- initialized.store(true);
+ initialized.storeRelaxed(true);
}
}
diff --git a/src/dbus/qdbuspendingcall.cpp b/src/dbus/qdbuspendingcall.cpp
index 2a31dd950a..7c2238900c 100644
--- a/src/dbus/qdbuspendingcall.cpp
+++ b/src/dbus/qdbuspendingcall.cpp
@@ -221,8 +221,8 @@ void QDBusPendingCallPrivate::checkReceivedSignature()
// can't use startsWith here because a null string doesn't start or end with an empty string
if (replyMessage.signature().indexOf(expectedReplySignature) != 0) {
- QString errorMsg = QLatin1String("Unexpected reply signature: got \"%1\", "
- "expected \"%2\"");
+ const auto errorMsg = QLatin1String("Unexpected reply signature: got \"%1\", "
+ "expected \"%2\"");
replyMessage = QDBusMessage::createError(
QDBusError::InvalidSignature,
errorMsg.arg(replyMessage.signature(), expectedReplySignature));
@@ -311,7 +311,7 @@ QDBusPendingCall &QDBusPendingCall::operator=(const QDBusPendingCall &other)
\sa QDBusPendingReply::isFinished()
*/
/*!
- \fn bool QDBusPendingReply::isFinished() const
+ \fn template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> bool QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::isFinished() const
Returns \c true if the pending call has finished processing and the
reply has been received. If this function returns \c true, the
@@ -340,7 +340,7 @@ void QDBusPendingCall::waitForFinished()
}
/*!
- \fn bool QDBusPendingReply::isValid() const
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> bool QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::isValid() const
Returns \c true if the reply contains a normal reply message, false
if it contains anything else.
@@ -357,7 +357,7 @@ bool QDBusPendingCall::isValid() const
}
/*!
- \fn bool QDBusPendingReply::isError() const
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> bool QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::isError() const
Returns \c true if the reply contains an error message, false if it
contains a normal method reply.
@@ -374,7 +374,7 @@ bool QDBusPendingCall::isError() const
}
/*!
- \fn QDBusError QDBusPendingReply::error() const
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusError QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::error() const
Retrieves the error content of the reply message, if it has
finished processing. If the reply message has not finished
@@ -395,7 +395,7 @@ QDBusError QDBusPendingCall::error() const
}
/*!
- \fn QDBusMessage QDBusPendingReply::reply() const
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusMessage QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::reply() const
Retrieves the reply message received for the asynchronous call
that was sent, if it has finished processing. If the pending call
@@ -445,7 +445,7 @@ bool QDBusPendingCall::setReplyCallback(QObject *target, const char *member)
\since 4.6
Creates a QDBusPendingCall object based on the error condition
\a error. The resulting pending call object will be in the
- "finished" state and QDBusPendingReply::isError() will return true.
+ "finished" state and QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::isError() will return true.
\sa fromCompletedCall()
*/
@@ -473,7 +473,7 @@ QDBusPendingCall QDBusPendingCall::fromCompletedCall(const QDBusMessage &msg)
msg.type() == QDBusMessage::ReplyMessage) {
d = new QDBusPendingCallPrivate(QDBusMessage(), 0);
d->replyMessage = msg;
- d->ref.store(1);
+ d->ref.storeRelaxed(1);
}
return QDBusPendingCall(d);
diff --git a/src/dbus/qdbuspendingcall.h b/src/dbus/qdbuspendingcall.h
index ec8ba6c541..dd99346301 100644
--- a/src/dbus/qdbuspendingcall.h
+++ b/src/dbus/qdbuspendingcall.h
@@ -60,14 +60,12 @@ class Q_DBUS_EXPORT QDBusPendingCall
public:
QDBusPendingCall(const QDBusPendingCall &other);
~QDBusPendingCall();
-#ifdef Q_COMPILER_RVALUE_REFS
- QDBusPendingCall &operator=(QDBusPendingCall &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDBusPendingCall &operator=(QDBusPendingCall &&other) noexcept { swap(other); return *this; }
QDBusPendingCall &operator=(const QDBusPendingCall &other);
- void swap(QDBusPendingCall &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QDBusPendingCall &other) noexcept { qSwap(d, other.d); }
-#ifndef Q_QDOC
+#ifndef Q_CLANG_QDOC
// pretend that they aren't here
bool isFinished() const;
void waitForFinished();
diff --git a/src/dbus/qdbuspendingcall_p.h b/src/dbus/qdbuspendingcall_p.h
index 10f189ae43..e1f6240f3e 100644
--- a/src/dbus/qdbuspendingcall_p.h
+++ b/src/dbus/qdbuspendingcall_p.h
@@ -99,7 +99,7 @@ public:
// }
QDBusPendingCallPrivate(const QDBusMessage &sent, QDBusConnectionPrivate *connection)
- : sentMessage(sent), connection(connection), watcherHelper(0), pending(0)
+ : sentMessage(sent), connection(connection), watcherHelper(nullptr), pending(nullptr)
{ }
~QDBusPendingCallPrivate();
bool setReplyCallback(QObject *target, const char *member);
diff --git a/src/dbus/qdbuspendingreply.cpp b/src/dbus/qdbuspendingreply.cpp
index fef6f36432..6aec571563 100644
--- a/src/dbus/qdbuspendingreply.cpp
+++ b/src/dbus/qdbuspendingreply.cpp
@@ -94,7 +94,7 @@
*/
/*!
- \fn QDBusPendingReply::QDBusPendingReply()
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::QDBusPendingReply()
Creates an empty QDBusPendingReply object. Without assigning a
QDBusPendingCall object to this reply, QDBusPendingReply cannot do
@@ -102,7 +102,7 @@
*/
/*!
- \fn QDBusPendingReply::QDBusPendingReply(const QDBusPendingReply &other)
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::QDBusPendingReply(const QDBusPendingReply &other)
Creates a copy of the \a other QDBusPendingReply object. Just like
QDBusPendingCall and QDBusPendingCallWatcher, this QDBusPendingReply
@@ -111,7 +111,7 @@
*/
/*!
- \fn QDBusPendingReply::QDBusPendingReply(const QDBusPendingCall &call)
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::QDBusPendingReply(const QDBusPendingCall &call)
Creates a QDBusPendingReply object that will take its contents from
the \a call pending asynchronous call. This QDBusPendingReply object
@@ -119,7 +119,7 @@
*/
/*!
- \fn QDBusPendingReply::QDBusPendingReply(const QDBusMessage &message)
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::QDBusPendingReply(const QDBusMessage &message)
Creates a QDBusPendingReply object that will take its contents from
the message \a message. In this case, this object will be already
@@ -129,7 +129,7 @@
*/
/*!
- \fn QDBusPendingReply &QDBusPendingReply::operator=(const QDBusPendingReply &other)
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply &QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::operator=(const QDBusPendingReply &other)
Makes a copy of \a other and drops the reference to the current
pending call. If the current reference is to an unfinished pending
@@ -139,7 +139,7 @@
*/
/*!
- \fn QDBusPendingReply &QDBusPendingReply::operator=(const QDBusPendingCall &call)
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply &QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::operator=(const QDBusPendingCall &call)
Makes this object take its contents from the \a call pending call
and drops the reference to the current pending call. If the
@@ -149,7 +149,7 @@
*/
/*!
- \fn QDBusPendingReply &QDBusPendingReply::operator=(const QDBusMessage &message)
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply &QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::operator=(const QDBusMessage &message)
Makes this object take its contents from the \a message message
and drops the reference to the current pending call. If the
@@ -171,7 +171,7 @@
*/
/*!
- \fn int QDBusPendingReply::count() const
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> int QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::count() const
Return the number of arguments the reply is supposed to have. This
number matches the number of non-void template parameters in this
@@ -183,7 +183,7 @@
*/
/*!
- \fn QVariant QDBusPendingReply::argumentAt(int index) const
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QVariant QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::argumentAt(int index) const
Returns the argument at position \a index in the reply's
contents. If the reply doesn't have that many elements, this
@@ -198,12 +198,7 @@
*/
/*!
- \typedef QDBusPendingReply::T1
- \internal
- */
-
-/*!
- \fn T1 QDBusPendingReply::value() const
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> T1 QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::value() const
Returns the first argument in this reply, cast to type \c T1 (the
first template parameter of this class). This is equivalent to
@@ -221,7 +216,7 @@
*/
/*!
- \fn QDBusPendingReply::operator T1() const
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::operator T1() const
Returns the first argument in this reply, cast to type \c T1 (the
first template parameter of this class). This is equivalent to
@@ -239,7 +234,7 @@
*/
/*!
- \fn void QDBusPendingReply::waitForFinished()
+ \fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> void QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::waitForFinished()
Suspends the execution of the calling thread until the reply is
received and processed. After this function returns, isFinished()
diff --git a/src/dbus/qdbuspendingreply.h b/src/dbus/qdbuspendingreply.h
index 4d2c3a7c5a..1d7e60ad7f 100644
--- a/src/dbus/qdbuspendingreply.h
+++ b/src/dbus/qdbuspendingreply.h
@@ -108,10 +108,8 @@ namespace QDBusPendingReplyTypes {
template <> struct NotVoid<void> { typedef TypeIsVoid Type; };
} // namespace QDBusPendingReplyTypes
-#ifndef Q_CLANG_QDOC
template<typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
-#endif
class QDBusPendingReply:
#ifdef Q_CLANG_QDOC
public QDBusPendingCall
@@ -158,7 +156,7 @@ public:
{
Q_STATIC_ASSERT_X(Index >= 0 && Index < Count, "Index out of bounds");
typedef typename Select<Index>::Type ResultType;
- return qdbus_cast<ResultType>(argumentAt(Index), 0);
+ return qdbus_cast<ResultType>(argumentAt(Index), nullptr);
}
#endif
@@ -171,7 +169,6 @@ public:
QDBusError error() const;
QDBusMessage reply() const;
- typedef QVariant T1;
inline T1 value() const;
inline operator T1() const;
#else
diff --git a/src/dbus/qdbusreply.cpp b/src/dbus/qdbusreply.cpp
index ab361f1674..cf1a70508c 100644
--- a/src/dbus/qdbusreply.cpp
+++ b/src/dbus/qdbusreply.cpp
@@ -81,7 +81,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn template<typename T> QDBusReply<T>::QDBusReply(const QDBusPendingReply &reply)
+ \fn template<typename T> QDBusReply<T>::QDBusReply(const QDBusPendingReply<T> &reply)
Constructs a QDBusReply object from the pending reply message, \a reply.
*/
@@ -228,14 +228,14 @@ void qDBusReplyFill(const QDBusMessage &reply, QDBusError &error, QVariant &data
receivedSignature = "<empty signature>";
QString errorMsg;
if (receivedType) {
- errorMsg = QString::fromLatin1("Unexpected reply signature: got \"%1\" (%4), "
+ errorMsg = QLatin1String("Unexpected reply signature: got \"%1\" (%4), "
"expected \"%2\" (%3)")
.arg(QLatin1String(receivedSignature),
QLatin1String(expectedSignature),
QLatin1String(data.typeName()),
QLatin1String(receivedType));
} else {
- errorMsg = QString::fromLatin1("Unexpected reply signature: got \"%1\", "
+ errorMsg = QLatin1String("Unexpected reply signature: got \"%1\", "
"expected \"%2\" (%3)")
.arg(QLatin1String(receivedSignature),
QLatin1String(expectedSignature),
diff --git a/src/dbus/qdbusreply.h b/src/dbus/qdbusreply.h
index 177b6c6e89..869687ac85 100644
--- a/src/dbus/qdbusreply.h
+++ b/src/dbus/qdbusreply.h
@@ -82,14 +82,10 @@ public:
other.waitForFinished();
return *this = other.reply();
}
-#if defined(Q_CLANG_QDOC)
- inline QDBusReply(const QDBusPendingReply &reply) { }
-#else
inline QDBusReply(const QDBusPendingReply<T> &reply)
{
*this = static_cast<QDBusPendingCall>(reply);
}
-#endif
inline QDBusReply(const QDBusError &dbusError = QDBusError())
: m_error(dbusError), m_data(Type())
diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp
index a2dfb86164..2899fb7bea 100644
--- a/src/dbus/qdbusserver.cpp
+++ b/src/dbus/qdbusserver.cpp
@@ -117,7 +117,7 @@ QDBusServer::~QDBusServer()
d->serverConnectionNames.clear();
}
d->serverObject = nullptr;
- d->ref.store(0);
+ d->ref.storeRelaxed(0);
d->deleteLater();
}
diff --git a/src/dbus/qdbusservicewatcher.cpp b/src/dbus/qdbusservicewatcher.cpp
index 0c2fb9118f..b0bfe7254d 100644
--- a/src/dbus/qdbusservicewatcher.cpp
+++ b/src/dbus/qdbusservicewatcher.cpp
@@ -139,6 +139,17 @@ void QDBusServiceWatcherPrivate::removeService(const QString &service)
QDBusConnectionInterface::serviceOwnerChanged() signal because it allows
one to receive only the signals for which the class is interested in.
+ Ending a service name with the character '*' will match all service names
+ within the specified namespace.
+
+ For example "com.example.backend1*" will match
+ \list
+ \li com.example.backend1
+ \li com.example.backend1.foo
+ \li com.example.backend1.foo.bar
+ \endlist
+ Substrings in the same domain will not be matched, i.e "com.example.backend12".
+
\sa QDBusConnection
*/
diff --git a/src/dbus/qdbusunixfiledescriptor.cpp b/src/dbus/qdbusunixfiledescriptor.cpp
index 459cfc6c66..73d1db2680 100644
--- a/src/dbus/qdbusunixfiledescriptor.cpp
+++ b/src/dbus/qdbusunixfiledescriptor.cpp
@@ -208,7 +208,7 @@ QDBusUnixFileDescriptor::~QDBusUnixFileDescriptor()
*/
bool QDBusUnixFileDescriptor::isValid() const
{
- return d ? d->fd.load() != -1 : false;
+ return d ? d->fd.loadRelaxed() != -1 : false;
}
/*!
@@ -226,7 +226,7 @@ bool QDBusUnixFileDescriptor::isValid() const
*/
int QDBusUnixFileDescriptor::fileDescriptor() const
{
- return d ? d->fd.load() : -1;
+ return d ? d->fd.loadRelaxed() : -1;
}
// actual implementation
@@ -283,12 +283,12 @@ void QDBusUnixFileDescriptor::giveFileDescriptor(int fileDescriptor)
else
d = new QDBusUnixFileDescriptorPrivate;
- const int fdl = d->fd.load();
+ const int fdl = d->fd.loadRelaxed();
if (fdl != -1)
qt_safe_close(fdl);
if (fileDescriptor != -1)
- d->fd.store(fileDescriptor);
+ d->fd.storeRelaxed(fileDescriptor);
}
/*!
@@ -309,7 +309,7 @@ int QDBusUnixFileDescriptor::takeFileDescriptor()
QDBusUnixFileDescriptorPrivate::~QDBusUnixFileDescriptorPrivate()
{
- const int fdl = fd.load();
+ const int fdl = fd.loadRelaxed();
if (fdl != -1)
qt_safe_close(fdl);
}
diff --git a/src/dbus/qdbusunixfiledescriptor.h b/src/dbus/qdbusunixfiledescriptor.h
index ed3209ceda..fcd73b2ec5 100644
--- a/src/dbus/qdbusunixfiledescriptor.h
+++ b/src/dbus/qdbusunixfiledescriptor.h
@@ -46,9 +46,7 @@
#ifndef QT_NO_DBUS
-#ifdef Q_COMPILER_RVALUE_REFS
-# include <utility>
-#endif
+#include <utility>
QT_BEGIN_NAMESPACE
@@ -61,13 +59,11 @@ public:
QDBusUnixFileDescriptor();
explicit QDBusUnixFileDescriptor(int fileDescriptor);
QDBusUnixFileDescriptor(const QDBusUnixFileDescriptor &other);
-#if defined(Q_COMPILER_RVALUE_REFS)
- QDBusUnixFileDescriptor &operator=(QDBusUnixFileDescriptor &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDBusUnixFileDescriptor &operator=(QDBusUnixFileDescriptor &&other) noexcept { swap(other); return *this; }
QDBusUnixFileDescriptor &operator=(const QDBusUnixFileDescriptor &other);
~QDBusUnixFileDescriptor();
- void swap(QDBusUnixFileDescriptor &other) Q_DECL_NOTHROW
+ void swap(QDBusUnixFileDescriptor &other) noexcept
{ qSwap(d, other.d); }
bool isValid() const;
diff --git a/src/dbus/qdbusutil.cpp b/src/dbus/qdbusutil.cpp
index 28341a71a8..dc94897ac4 100644
--- a/src/dbus/qdbusutil.cpp
+++ b/src/dbus/qdbusutil.cpp
@@ -331,8 +331,8 @@ namespace QDBusUtil
/*!
\internal
- \fn bool QDBusUtil::isValidPartOfObjectPath(const QStringRef &part)
- See QDBusUtil::isValidObjectPath
+ \fn bool isValidPartOfObjectPath(const QStringRef &part)
+ See isValidObjectPath
*/
bool isValidPartOfObjectPath(const QStringRef &part)
{
@@ -349,13 +349,13 @@ namespace QDBusUtil
/*!
\internal
- \fn bool QDBusUtil::isValidPartOfObjectPath(const QString &part)
+ \fn bool isValidPartOfObjectPath(const QString &part)
\overload
*/
/*!
- \fn bool QDBusUtil::isValidInterfaceName(const QString &ifaceName)
+ \fn bool isValidInterfaceName(const QString &ifaceName)
Returns \c true if this is \a ifaceName is a valid interface name.
Valid interface names must:
@@ -384,7 +384,7 @@ namespace QDBusUtil
}
/*!
- \fn bool QDBusUtil::isValidUniqueConnectionName(const QStringRef &connName)
+ \fn bool isValidUniqueConnectionName(const QStringRef &connName)
Returns \c true if \a connName is a valid unique connection name.
Unique connection names start with a colon (":") and are followed by a list of dot-separated
@@ -414,13 +414,13 @@ namespace QDBusUtil
}
/*!
- \fn bool QDBusUtil::isValidUniqueConnectionName(const QString &connName)
+ \fn bool isValidUniqueConnectionName(const QString &connName)
\overload
*/
/*!
- \fn bool QDBusUtil::isValidBusName(const QString &busName)
+ \fn bool isValidBusName(const QString &busName)
Returns \c true if \a busName is a valid bus name.
A valid bus name is either a valid unique connection name or follows the rules:
@@ -462,7 +462,7 @@ namespace QDBusUtil
}
/*!
- \fn bool QDBusUtil::isValidMemberName(const QStringRef &memberName)
+ \fn bool isValidMemberName(const QStringRef &memberName)
Returns \c true if \a memberName is a valid member name. A valid member name does not exceed
255 characters in length, is not empty, is composed only of ASCII letters, digits and
underscores, but does not start with a digit.
@@ -482,13 +482,13 @@ namespace QDBusUtil
}
/*!
- \fn bool QDBusUtil::isValidMemberName(const QString &memberName)
+ \fn bool isValidMemberName(const QString &memberName)
\overload
*/
/*!
- \fn bool QDBusUtil::isValidErrorName(const QString &errorName)
+ \fn bool isValidErrorName(const QString &errorName)
Returns \c true if \a errorName is a valid error name. Valid error names are valid interface
names and vice-versa, so this function is actually an alias for isValidInterfaceName.
*/
@@ -498,7 +498,7 @@ namespace QDBusUtil
}
/*!
- \fn bool QDBusUtil::isValidObjectPath(const QString &path)
+ \fn bool isValidObjectPath(const QString &path)
Returns \c true if \a path is valid object path.
Valid object paths follow the rules:
@@ -529,7 +529,7 @@ namespace QDBusUtil
}
/*!
- \fn bool QDBusUtil::isValidBasicType(int type)
+ \fn bool isValidBasicType(int type)
Returns \c true if \a c is a valid, basic D-Bus type.
*/
bool isValidBasicType(int c)
@@ -538,7 +538,7 @@ namespace QDBusUtil
}
/*!
- \fn bool QDBusUtil::isValidFixedType(int type)
+ \fn bool isValidFixedType(int type)
Returns \c true if \a c is a valid, fixed D-Bus type.
*/
bool isValidFixedType(int c)
@@ -548,7 +548,7 @@ namespace QDBusUtil
/*!
- \fn bool QDBusUtil::isValidSignature(const QString &signature)
+ \fn bool isValidSignature(const QString &signature)
Returns \c true if \a signature is a valid D-Bus type signature for one or more types.
This function returns \c true if it can all of \a signature into valid, individual types and no
characters remain in \a signature.
@@ -569,7 +569,7 @@ namespace QDBusUtil
}
/*!
- \fn bool QDBusUtil::isValidSingleSignature(const QString &signature)
+ \fn bool isValidSingleSignature(const QString &signature)
Returns \c true if \a signature is a valid D-Bus type signature for exactly one full type. This
function tries to convert the type signature into a D-Bus type and, if it succeeds and no
characters remain in the signature, it returns \c true.
diff --git a/src/dbus/qdbusutil_p.h b/src/dbus/qdbusutil_p.h
index 2f187687b8..0814cc8050 100644
--- a/src/dbus/qdbusutil_p.h
+++ b/src/dbus/qdbusutil_p.h
@@ -106,7 +106,7 @@ namespace Q_DBUS_NO_EXPORT QDBusUtil
return false;
}
if (isValidInterfaceName(name)) return true;
- *error = QDBusError(QDBusError::InvalidInterface, QString::fromLatin1("Invalid interface class: %1").arg(name));
+ *error = QDBusError(QDBusError::InvalidInterface, QLatin1String("Invalid interface class: %1").arg(name));
return false;
}
@@ -118,7 +118,7 @@ namespace Q_DBUS_NO_EXPORT QDBusUtil
return false;
}
if (isValidBusName(name)) return true;
- *error = QDBusError(QDBusError::InvalidService, QString::fromLatin1("Invalid service name: %1").arg(name));
+ *error = QDBusError(QDBusError::InvalidService, QLatin1String("Invalid service name: %1").arg(name));
return false;
}
@@ -130,11 +130,11 @@ namespace Q_DBUS_NO_EXPORT QDBusUtil
return false;
}
if (isValidObjectPath(path)) return true;
- *error = QDBusError(QDBusError::InvalidObjectPath, QString::fromLatin1("Invalid object path: %1").arg(path));
+ *error = QDBusError(QDBusError::InvalidObjectPath, QLatin1String("Invalid object path: %1").arg(path));
return false;
}
- inline bool checkMemberName(const QString &name, AllowEmptyFlag empty, QDBusError *error, const char *nameType = 0)
+ inline bool checkMemberName(const QString &name, AllowEmptyFlag empty, QDBusError *error, const char *nameType = nullptr)
{
if (!nameType) nameType = "member";
if (name.isEmpty()) {
@@ -143,8 +143,8 @@ namespace Q_DBUS_NO_EXPORT QDBusUtil
return false;
}
if (isValidMemberName(name)) return true;
- *error = QDBusError(QDBusError::InvalidMember, QString::fromLatin1("Invalid %1 name: %2")
- .arg(QString::fromLatin1(nameType), name));
+ *error = QDBusError(QDBusError::InvalidMember, QLatin1String("Invalid %1 name: %2")
+ .arg(QLatin1String(nameType), name));
return false;
}
@@ -156,7 +156,7 @@ namespace Q_DBUS_NO_EXPORT QDBusUtil
return false;
}
if (isValidErrorName(name)) return true;
- *error = QDBusError(QDBusError::InvalidInterface, QString::fromLatin1("Invalid error name: %1").arg(name));
+ *error = QDBusError(QDBusError::InvalidInterface, QLatin1String("Invalid error name: %1").arg(name));
return false;
}
diff --git a/src/dbus/qdbusxmlgenerator.cpp b/src/dbus/qdbusxmlgenerator.cpp
index e3c503aa0f..c6b3b90508 100644
--- a/src/dbus/qdbusxmlgenerator.cpp
+++ b/src/dbus/qdbusxmlgenerator.cpp
@@ -108,14 +108,14 @@ static QString generateInterfaceXml(const QMetaObject *mo, int flags, int method
if (!signature)
continue;
- retval += QString::fromLatin1(" <property name=\"%1\" type=\"%2\" access=\"%3\"")
+ retval += QLatin1String(" <property name=\"%1\" type=\"%2\" access=\"%3\"")
.arg(QLatin1String(mp.name()),
QLatin1String(signature),
accessAsString(mp.isReadable(), mp.isWritable()));
if (QDBusMetaType::signatureToType(signature) == QVariant::Invalid) {
const char *typeName = QMetaType::typeName(typeId);
- retval += QString::fromLatin1(">\n <annotation name=\"org.qtproject.QtDBus.QtTypeName\" value=\"%3\"/>\n </property>\n")
+ retval += QLatin1String(">\n <annotation name=\"org.qtproject.QtDBus.QtTypeName\" value=\"%3\"/>\n </property>\n")
.arg(typeNameToXml(typeName));
} else {
retval += QLatin1String("/>\n");
@@ -157,12 +157,12 @@ static QString generateInterfaceXml(const QMetaObject *mo, int flags, int method
if (typeId != QMetaType::UnknownType && typeId != QMetaType::Void) {
const char *typeName = QDBusMetaType::typeToSignature(typeId);
if (typeName) {
- xml += QString::fromLatin1(" <arg type=\"%1\" direction=\"out\"/>\n")
+ xml += QLatin1String(" <arg type=\"%1\" direction=\"out\"/>\n")
.arg(typeNameToXml(typeName));
// do we need to describe this argument?
if (QDBusMetaType::signatureToType(typeName) == QVariant::Invalid)
- xml += QString::fromLatin1(" <annotation name=\"org.qtproject.QtDBus.QtTypeName.Out0\" value=\"%1\"/>\n")
+ xml += QLatin1String(" <annotation name=\"org.qtproject.QtDBus.QtTypeName.Out0\" value=\"%1\"/>\n")
.arg(typeNameToXml(QMetaType::typeName(typeId)));
} else {
qWarning() << "Unsupported return type" << typeId << QMetaType::typeName(typeId) << "in method" << mm.name();
@@ -199,7 +199,7 @@ static QString generateInterfaceXml(const QMetaObject *mo, int flags, int method
QString name;
if (!names.at(j - 1).isEmpty())
- name = QString::fromLatin1("name=\"%1\" ").arg(QLatin1String(names.at(j - 1)));
+ name = QLatin1String("name=\"%1\" ").arg(QLatin1String(names.at(j - 1)));
bool isOutput = isSignal || j > inputCount;
@@ -233,7 +233,7 @@ static QString generateInterfaceXml(const QMetaObject *mo, int flags, int method
" value=\"true\"/>\n");
retval += xml;
- retval += QString::fromLatin1(" </%1>\n")
+ retval += QLatin1String(" </%1>\n")
.arg(isSignal ? QLatin1String("signal") : QLatin1String("method"));
}
@@ -256,7 +256,7 @@ QString qDBusGenerateMetaObjectXml(QString interface, const QMetaObject *mo,
if (xml.isEmpty())
return QString(); // don't add an empty interface
- return QString::fromLatin1(" <interface name=\"%1\">\n%2 </interface>\n")
+ return QLatin1String(" <interface name=\"%1\">\n%2 </interface>\n")
.arg(interface, xml);
}
#if 0
diff --git a/src/dbus/qt_attribution.json b/src/dbus/qt_attribution.json
index 69d946ba5c..33eaee1ed1 100644
--- a/src/dbus/qt_attribution.json
+++ b/src/dbus/qt_attribution.json
@@ -7,7 +7,7 @@
"Description": "D-Bus is a message bus system, a simple way for applications to talk to one another.",
"Homepage": "https://www.freedesktop.org/wiki/Software/dbus/",
"Version": "Minimal supported is 1.2, compatible up to ...",
- "Version": "1.12",
+ "Version": "dbus-1.12.12",
"LicenseId": "AFL-2.1 OR GPL-2.0-or-later",
"License": "Academic Free License v2.1, or GNU General Public License v2.0 or later",
"LicenseFile": "LIBDBUS-1-LICENSE.txt",
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index baee4fc252..db47a3abc1 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -527,7 +527,7 @@ static void qAccessibleCleanup()
to it.
If the key and the QObject does not have a corresponding
- QAccessibleInterface, a null-pointer will be returned.
+ QAccessibleInterface, \nullptr will be returned.
Installed factories are called by queryAccessibilityInterface() until
one provides an interface.
@@ -1859,7 +1859,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface)
return d;
}
d.nospace();
- d << "QAccessibleInterface(" << hex << (const void *) iface << dec;
+ d << "QAccessibleInterface(" << Qt::hex << (const void *) iface << Qt::dec;
if (iface->isValid()) {
d << " name=" << iface->text(QAccessible::Name) << ' ';
d << "role=" << qAccessibleRoleString(iface->role()) << ' ';
@@ -1898,7 +1898,7 @@ QDebug operator<<(QDebug d, const QAccessibleEvent &ev)
QDebugStateSaver saver(d);
d.nospace() << "QAccessibleEvent(";
if (ev.object()) {
- d.nospace() << "object=" << hex << ev.object() << dec;
+ d.nospace() << "object=" << Qt::hex << ev.object() << Qt::dec;
d.nospace() << "child=" << ev.child();
} else {
d.nospace() << "no object, uniqueId=" << ev.uniqueId();
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index 857b9c5ef5..2220efd5cb 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -967,8 +967,10 @@ protected:
int m_lastColumn;
};
+#ifndef Q_CLANG_QDOC
#define QAccessibleInterface_iid "org.qt-project.Qt.QAccessibleInterface"
Q_DECLARE_INTERFACE(QAccessibleInterface, QAccessibleInterface_iid)
+#endif
Q_GUI_EXPORT const char *qAccessibleRoleString(QAccessible::Role role);
Q_GUI_EXPORT const char *qAccessibleEventString(QAccessible::Event event);
diff --git a/src/gui/accessible/qaccessiblecache_p.h b/src/gui/accessible/qaccessiblecache_p.h
index a976277c1d..cf1ed04f35 100644
--- a/src/gui/accessible/qaccessiblecache_p.h
+++ b/src/gui/accessible/qaccessiblecache_p.h
@@ -73,7 +73,7 @@ public:
QAccessibleInterface *interfaceForId(QAccessible::Id id) const;
QAccessible::Id idForInterface(QAccessibleInterface *iface) const;
QAccessible::Id insert(QObject *object, QAccessibleInterface *iface) const;
- void deleteInterface(QAccessible::Id id, QObject *obj = 0);
+ void deleteInterface(QAccessible::Id id, QObject *obj = nullptr);
#ifdef Q_OS_MAC
QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *elementForId(QAccessible::Id axid) const;
diff --git a/src/gui/accessible/qaccessibleobject.h b/src/gui/accessible/qaccessibleobject.h
index 81479c32ab..fd07d33a18 100644
--- a/src/gui/accessible/qaccessibleobject.h
+++ b/src/gui/accessible/qaccessibleobject.h
@@ -65,7 +65,7 @@ public:
QAccessibleInterface *childAt(int x, int y) const override;
protected:
- virtual ~QAccessibleObject();
+ ~QAccessibleObject();
private:
QAccessibleObjectPrivate *d;
diff --git a/src/gui/configure.json b/src/gui/configure.json
index c51e3ceee3..c7bafb8925 100644
--- a/src/gui/configure.json
+++ b/src/gui/configure.json
@@ -28,9 +28,9 @@
"lgmon": "boolean",
"libinput": "boolean",
"libjpeg": { "type": "enum", "values": [ "no", "qt", "system" ] },
+ "libmd4c": { "type": "enum", "values": [ "no", "qt", "system" ] },
"libpng": { "type": "enum", "values": [ "no", "qt", "system" ] },
"linuxfb": "boolean",
- "mirclient": "boolean",
"mtdev": "boolean",
"opengl": { "type": "optionalString", "values": [ "no", "yes", "desktop", "es2", "dynamic" ] },
"opengl-es-2": { "type": "void", "name": "opengl", "value": "es2" },
@@ -377,6 +377,17 @@
"-ljpeg"
]
},
+ "libmd4c": {
+ "label": "libmd4c",
+ "test": {
+ "main": "md_parse(\"hello\", 5, nullptr, nullptr);"
+ },
+ "headers": "md4c.h",
+ "sources": [
+ { "type": "pkgConfig", "args": "md4c" },
+ { "libs": "-lmd4c" }
+ ]
+ },
"libpng": {
"label": "libpng",
"test": {
@@ -395,20 +406,6 @@
{ "lib": "zlib", "condition": "features.system-zlib" }
]
},
- "mirclient": {
- "label": "Mir client libraries",
- "test": {
- "tail": "static void surfaceCreateCallback(MirSurface*, void*) {}",
- "main": [
- "u_application_lifecycle_delegate_new();",
- "mir_surface_create(0, surfaceCreateCallback, 0);"
- ]
- },
- "headers": [ "mir_toolkit/mir_client_library.h", "ubuntu/application/lifecycle_delegate.h", "EGL/egl.h" ],
- "sources": [
- { "type": "pkgConfig", "args": "egl mirclient ubuntu-platform-api libcontent-hub >= 0.2.0" }
- ]
- },
"mtdev": {
"label": "mtdev",
"test": {
@@ -491,7 +488,7 @@
"tslib": {
"label": "tslib",
"test": {
- "main": "ts_open(\"foo\", 0);"
+ "main": "ts_setup(nullptr, 0);"
},
"headers": "tslib.h",
"sources": [
@@ -1108,7 +1105,7 @@
"angle": {
"label": "ANGLE",
"autoDetect": "features.opengles2 || features.opengl-dynamic",
- "condition": "features.dxguid && tests.fxc && (features.direct3d9 || (config.winrt && features.direct3d11 && libs.d3dcompiler))",
+ "condition": "!features.opengl-desktop && features.dxguid && tests.fxc && (features.direct3d9 || (config.winrt && features.direct3d11 && libs.d3dcompiler))",
"output": [
"publicFeature",
{ "type": "define", "name": "QT_OPENGL_ES_2_ANGLE" },
@@ -1297,13 +1294,6 @@
],
"output": [ "privateFeature" ]
},
- "mirclient": {
- "label": "Mir client",
- "section": "Platform plugins",
- "autoDetect": false,
- "condition": "libs.mirclient && features.xkbcommon",
- "output": [ "privateFeature" ]
- },
"mtdev": {
"label": "mtdev",
"condition": "libs.mtdev",
@@ -1311,9 +1301,9 @@
},
"opengles2": {
"label": "OpenGL ES 2.0",
- "enable": "input.opengl == 'es2'",
+ "enable": "input.opengl == 'es2' || input.angle == 'yes'",
"disable": "input.opengl == 'desktop' || input.opengl == 'dynamic' || input.opengl == 'no'",
- "condition": "config.win32 || (!config.watchos && !features.opengl-desktop && libs.opengl_es2)",
+ "condition": "(config.win32 && !features.opengl-dynamic) || (!config.watchos && !features.opengl-desktop && libs.opengl_es2)",
"output": [
"publicFeature",
"publicQtConfig",
@@ -1347,6 +1337,7 @@
},
"opengl-desktop": {
"label": "Desktop OpenGL",
+ "autoDetect": "!config.win32",
"enable": "input.opengl == 'desktop'",
"disable": "input.opengl == 'es2' || input.opengl == 'dynamic' || input.opengl == 'no'",
"condition": "(config.win32 && !config.winrt && !features.opengles2 && (config.msvc || libs.opengl))
@@ -1354,8 +1345,7 @@
},
"opengl-dynamic": {
"label": "Dynamic OpenGL",
- "enable": "input.opengl == 'dynamic'",
- "autoDetect": false,
+ "disable": "input.angle == 'yes' || input.opengl == 'no' || input.opengl == 'desktop'",
"condition": "config.win32 && !config.winrt",
"output": [
{ "type": "publicFeature", "name": "dynamicgl" },
@@ -1390,7 +1380,7 @@
"eglfs": {
"label": "EGLFS",
"section": "Platform plugins",
- "condition": "!config.android && !config.darwin && !config.win32 && features.egl",
+ "condition": "!config.android && !config.darwin && !config.win32 && !config.wasm && features.egl",
"output": [ "privateFeature" ]
},
"eglfs_brcm": {
@@ -1605,6 +1595,28 @@
"section": "Kernel",
"output": [ "publicFeature", "feature" ]
},
+ "textmarkdownreader": {
+ "label": "MarkdownReader",
+ "disable": "input.libmd4c == 'no'",
+ "enable": "input.libmd4c == 'system' || input.libmd4c == 'qt' || input.libmd4c == 'yes'",
+ "purpose": "Provides a Markdown (CommonMark and GitHub) reader",
+ "section": "Kernel",
+ "output": [ "publicFeature" ]
+ },
+ "system-textmarkdownreader": {
+ "label": " Using system libmd4c",
+ "disable": "input.libmd4c == 'qt'",
+ "enable": "input.libmd4c == 'system'",
+ "section": "Kernel",
+ "condition": "libs.libmd4c",
+ "output": [ "publicFeature" ]
+ },
+ "textmarkdownwriter": {
+ "label": "MarkdownWriter",
+ "purpose": "Provides a Markdown (CommonMark) writer",
+ "section": "Kernel",
+ "output": [ "publicFeature" ]
+ },
"textodfwriter": {
"label": "OdfWriter",
"purpose": "Provides an ODF writer.",
@@ -1647,7 +1659,7 @@
"label": "QClipboard",
"purpose": "Provides cut and paste operations.",
"section": "Kernel",
- "condition": "!config.integrity && !config.qnx",
+ "condition": "!config.integrity && !config.qnx && !config.rtems",
"output": [ "publicFeature", "feature" ]
},
"wheelevent": {
@@ -1791,7 +1803,7 @@
"label": "Multi process",
"purpose": "Provides support for detecting the desktop environment, launching external processes and opening URLs.",
"section": "Utilities",
- "condition": "!config.integrity",
+ "condition": "!config.integrity && !config.rtems",
"output": [ "privateFeature" ]
},
"whatsthis": {
@@ -1799,6 +1811,12 @@
"purpose": "Supports displaying \"What's this\" help.",
"section": "Widget Support",
"output": [ "publicFeature", "feature" ]
+ },
+ "raster-64bit": {
+ "label": "QPainter - 64 bit raster",
+ "purpose": "Internal painting support for 64 bit (16 bpc) rasterization.",
+ "section": "Painting",
+ "output": [ "privateFeature" ]
}
},
@@ -1830,7 +1848,7 @@ or may depend on your system and XQuartz setup."
},
{
"type": "warning",
- "condition": "features.gui && config.linux && !config.android && !features.xcb && !features.eglfs && !features.directfb && !features.linuxfb && !features.mirclient",
+ "condition": "features.gui && config.linux && !config.android && !features.xcb && !features.eglfs && !features.directfb && !features.linuxfb",
"message": "No QPA platform plugin enabled! This will
produce a Qt that cannot run GUI applications.
See \"Platform backends\" in the output of --help."
@@ -1877,6 +1895,12 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
"gif", "ico", "jpeg", "system-jpeg", "png", "system-png"
]
},
+ {
+ "section": "Text formats",
+ "entries": [
+ "texthtmlparser", "cssparser", "textodfwriter", "textmarkdownreader", "system-textmarkdownreader", "textmarkdownwriter"
+ ]
+ },
"egl",
"openvg",
{
@@ -1938,7 +1962,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
"eglfs_openwfd", "eglfs_viv", "eglfs_viv_wl", "eglfs_rcar", "eglfs_egldevice", "eglfs_gbm", "eglfs_vsp2", "eglfs_mali", "eglfs_brcm", "eglfs_x11"
]
},
- "linuxfb", "vnc", "mirclient",
+ "linuxfb", "vnc",
{
"type": "feature",
"condition": "config.integrity",
diff --git a/src/gui/doc/snippets/clipboard/clipwindow.cpp b/src/gui/doc/snippets/clipboard/clipwindow.cpp
index bf1b2d904b..d1b39070fa 100644
--- a/src/gui/doc/snippets/clipboard/clipwindow.cpp
+++ b/src/gui/doc/snippets/clipboard/clipwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "clipwindow.h"
@@ -67,10 +67,11 @@ ClipWindow::ClipWindow(QWidget *parent)
previousItems = new QListWidget(centralWidget);
//! [0]
- connect(clipboard, SIGNAL(dataChanged()), this, SLOT(updateClipboard()));
+ connect(clipboard, &QClipboard::dataChanged,
+ this, &ClipWindow::updateClipboard);
//! [0]
- connect(mimeTypeCombo, SIGNAL(activated(QString)),
- this, SLOT(updateData(QString)));
+ connect(mimeTypeCombo, QOverload<QString>::of(&QComboBox::activated),
+ this, &ClipWindow::updateData);
QVBoxLayout *currentLayout = new QVBoxLayout(currentItem);
currentLayout->addWidget(mimeTypeLabel);
diff --git a/src/gui/doc/snippets/code/doc_src_coordsys.cpp b/src/gui/doc/snippets/code/doc_src_coordsys.cpp
index 7c53d9e731..147c146b44 100644
--- a/src/gui/doc/snippets/code/doc_src_coordsys.cpp
+++ b/src/gui/doc/snippets/code/doc_src_coordsys.cpp
@@ -52,6 +52,7 @@
QPainter painter(this);
painter.setPen(Qt::darkGreen);
+// Using the (x y w h) overload
painter.drawRect(1, 2, 6, 4);
//! [0]
@@ -69,6 +70,7 @@ QPainter painter(this);
painter.setRenderHint(
QPainter::Antialiasing);
painter.setPen(Qt::darkGreen);
+// Using the (x y w h) overload
painter.drawRect(1, 2, 6, 4);
//! [2]
diff --git a/src/gui/doc/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp b/src/gui/doc/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp
index 40893fae87..a7e22e549d 100644
--- a/src/gui/doc/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp
+++ b/src/gui/doc/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp
@@ -50,8 +50,8 @@
//! [0]
QStandardItemModel model(4, 4);
-for (int row = 0; row < 4; ++row) {
- for (int column = 0; column < 4; ++column) {
+for (int row = 0; row < model.rowCount(); ++row) {
+ for (int column = 0; column < model.columnCount(); ++column) {
QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
model.setItem(row, column, item);
}
@@ -73,8 +73,8 @@ for (int i = 0; i < 4; ++i) {
//! [2]
QTreeView *treeView = new QTreeView(this);
treeView->setModel(myStandardItemModel);
-connect(treeView, SIGNAL(clicked(QModelIndex)),
- this, SLOT(clicked(QModelIndex)));
+connect(treeView, &QTreeView::clicked,
+ this, &MyWidget::clicked);
//! [2]
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp
index 7c5c387a5a..a399d444e1 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp
@@ -64,7 +64,8 @@ MyMainWidget::MyMainWidget(QWidget *parent)
:QWidget(parent)
{
QGuiApplication::setFallbackSessionManagementEnabled(false);
- connect(qApp, SIGNAL(commitDataRequest(QSessionManager)), SLOT(commitData(QSessionManager)));
+ connect(qApp, &QGuiApplication::commitDataRequest,
+ this, &MyMainWidget::commitData);
}
void MyMainWidget::commitData(QSessionManager& manager)
@@ -102,12 +103,14 @@ appname -session id
//! [3]
-foreach (const QString &command, mySession.restartCommand())
+const QStringList commands = mySession.restartCommand();
+for (const QString &command : commands)
do_something(command);
//! [3]
//! [4]
-foreach (const QString &command, mySession.discardCommand())
+const QStringList commands = mySession.discardCommand();
+for (const QString &command : mySession.discardCommand())
do_something(command);
//! [4]
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication_x11.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication_x11.cpp
index e91aa3d548..961ecd6cde 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication_x11.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication_x11.cpp
@@ -49,7 +49,7 @@
****************************************************************************/
//! [0]
-QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
calculateHugeMandelbrot(); // lunch time...
-QApplication::restoreOverrideCursor();
+QGuiApplication::restoreOverrideCursor();
//! [0]
diff --git a/src/gui/doc/snippets/draganddrop/mainwindow.cpp b/src/gui/doc/snippets/draganddrop/mainwindow.cpp
index 551114856e..11311a0b57 100644
--- a/src/gui/doc/snippets/draganddrop/mainwindow.cpp
+++ b/src/gui/doc/snippets/draganddrop/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "dragwidget.h"
#include "mainwindow.h"
@@ -64,10 +64,10 @@ MainWindow::MainWindow(QWidget *parent)
QLabel *dataLabel = new QLabel(tr("Amount of data (bytes):"), centralWidget);
dragWidget = new DragWidget(centralWidget);
- connect(dragWidget, SIGNAL(mimeTypes(QStringList)),
- this, SLOT(setMimeTypes(QStringList)));
- connect(dragWidget, SIGNAL(dragResult(QString)),
- this, SLOT(setDragResult(QString)));
+ connect(dragWidget, &DragWidget::mimeTypes,
+ this, &MainWindow::setMimeTypes);
+ connect(dragWidget, &DragWidget:dragResult,
+ this, &MainWindow::setDragResult);
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
mainLayout->addWidget(mimeTypeLabel);
diff --git a/src/gui/doc/snippets/picture/picture.cpp b/src/gui/doc/snippets/picture/picture.cpp
index 3a7676f60a..863476fdbf 100644
--- a/src/gui/doc/snippets/picture/picture.cpp
+++ b/src/gui/doc/snippets/picture/picture.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
void myProcessing(const QString &)
{
@@ -85,8 +85,8 @@ int main()
{
// FORMATS
//! [2]
- QStringList list = QPicture::inputFormatList();
- foreach (const QString &string, list)
+ const QStringList list = QPicture::inputFormatList();
+ for (const QString &string : list)
myProcessing(string);
//! [2]
}
@@ -94,8 +94,8 @@ int main()
{
// OUTPUT
//! [3]
- QStringList list = QPicture::outputFormatList();
- foreach (const QString &string, list)
+ const QStringList list = QPicture::outputFormatList();
+ for (const QString &string : list)
myProcessing(string);
//! [3]
}
diff --git a/src/gui/doc/snippets/qfontdatabase/main.cpp b/src/gui/doc/snippets/qfontdatabase/main.cpp
index ae078f374d..5a5aa7b485 100644
--- a/src/gui/doc/snippets/qfontdatabase/main.cpp
+++ b/src/gui/doc/snippets/qfontdatabase/main.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
int main(int argc, char **argv)
{
@@ -60,16 +60,19 @@ int main(int argc, char **argv)
fontTree.setColumnCount(2);
fontTree.setHeaderLabels(QStringList() << "Font" << "Smooth Sizes");
- foreach (const QString &family, database.families()) {
+ const QStringList fontFamilies = database.families();
+ for (const QString &family : fontFamilies) {
QTreeWidgetItem *familyItem = new QTreeWidgetItem(&fontTree);
familyItem->setText(0, family);
- foreach (const QString &style, database.styles(family)) {
+ const QStringList fontStyles = database.styles(family);
+ for (const QString &style : fontStyles) {
QTreeWidgetItem *styleItem = new QTreeWidgetItem(familyItem);
styleItem->setText(0, style);
QString sizes;
- foreach (int points, database.smoothSizes(family, style))
+ const QList<int> smoothSizes = database.smoothSizes(family, style)
+ for (int points : smoothSizes)
sizes += QString::number(points) + ' ';
styleItem->setText(1, sizes.trimmed());
diff --git a/src/gui/doc/snippets/separations/screenwidget.cpp b/src/gui/doc/snippets/separations/screenwidget.cpp
index 6f8be49bfa..d562991d26 100644
--- a/src/gui/doc/snippets/separations/screenwidget.cpp
+++ b/src/gui/doc/snippets/separations/screenwidget.cpp
@@ -105,8 +105,8 @@ ScreenWidget::ScreenWidget(QWidget *parent, QColor initialColor,
//invertButton->setOn(inverted);
invertButton->setEnabled(false);
- connect(colorButton, SIGNAL(clicked()), this, SLOT(setColor()));
- connect(invertButton, SIGNAL(clicked()), this, SLOT(invertImage()));
+ connect(colorButton, &QPushButton::clicked, this, &ScreenWidget::setColor);
+ connect(invertButton, &QPushButton::clicked, this, &ScreenWidget::invertImage);
QGridLayout *gridLayout = new QGridLayout;
gridLayout->addWidget(imageLabel, 0, 0, 1, 2);
diff --git a/src/gui/doc/snippets/separations/viewer.cpp b/src/gui/doc/snippets/separations/viewer.cpp
index 641294ea35..018b397f1a 100644
--- a/src/gui/doc/snippets/separations/viewer.cpp
+++ b/src/gui/doc/snippets/separations/viewer.cpp
@@ -58,7 +58,7 @@ A main menu provides entries for selecting files, and adjusting the
brightness of the separations.
*/
-#include <QtGui>
+#include <QtWidgets>
#include "finalwidget.h"
#include "screenwidget.h"
@@ -126,11 +126,11 @@ void Viewer::createMenus()
menuBar()->addMenu(fileMenu);
menuBar()->addMenu(brightnessMenu);
- connect(openAction, SIGNAL(triggered()), this, SLOT(chooseFile()));
- connect(saveAction, SIGNAL(triggered()), this, SLOT(saveImage()));
- connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
- connect(brightnessMenu, SIGNAL(triggered(QAction*)), this,
- SLOT(setBrightness(QAction*)));
+ connect(openAction, &QAction::triggered, this, &Viewer::chooseFile);
+ connect(saveAction, &QAction::triggered, this, &Viewer::saveImage);
+ connect(quitAction, &QAction::triggered, qApp, QApplication::quit);
+ connect(brightnessMenu, &QMenu::triggered,
+ this, &Viewer::setBrightness);
}
/*
@@ -160,9 +160,9 @@ QFrame* Viewer::createCentralWidget()
yellowWidget = new ScreenWidget(frame, Qt::yellow, tr("Yellow"),
ScreenWidget::Yellow, labelSize);
- connect(cyanWidget, SIGNAL(imageChanged()), this, SLOT(createImage()));
- connect(magentaWidget, SIGNAL(imageChanged()), this, SLOT(createImage()));
- connect(yellowWidget, SIGNAL(imageChanged()), this, SLOT(createImage()));
+ connect(cyanWidget, &ScreenWidget::imageChanged, this, &Viewer::createImage);
+ connect(magentaWidget, &ScreenWidget::imageChanged, this, &Viewer::createImage);
+ connect(yellowWidget, &ScreenWidget::imageChanged, this, &Viewer::createImage);
grid->addWidget(finalWidget, 0, 0, Qt::AlignTop | Qt::AlignHCenter);
grid->addWidget(cyanWidget, 0, 1, Qt::AlignTop | Qt::AlignHCenter);
diff --git a/src/gui/doc/snippets/textblock-fragments/mainwindow.cpp b/src/gui/doc/snippets/textblock-fragments/mainwindow.cpp
index bcc5c7dc30..bf864ce48d 100644
--- a/src/gui/doc/snippets/textblock-fragments/mainwindow.cpp
+++ b/src/gui/doc/snippets/textblock-fragments/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
#include "xmlwriter.h"
@@ -73,9 +73,9 @@ MainWindow::MainWindow()
editor = new QTextEdit(this);
- connect(saveAction, SIGNAL(triggered()), this, SLOT(saveFile()));
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
- connect(calendarAction, SIGNAL(triggered()), this, SLOT(insertCalendar()));
+ connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
+ connect(quitAction, &QAction::triggered, this, &MainWindow::close);
+ connect(calendarAction, &QAction::triggered, this, &MainWindow::insertCalendar);
setCentralWidget(editor);
setWindowTitle(tr("Text Document Writer"));
diff --git a/src/gui/doc/snippets/textdocument-blocks/mainwindow.cpp b/src/gui/doc/snippets/textdocument-blocks/mainwindow.cpp
index f512cf0dc6..a5801da67e 100644
--- a/src/gui/doc/snippets/textdocument-blocks/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-blocks/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
#include "xmlwriter.h"
@@ -75,9 +75,9 @@ MainWindow::MainWindow()
editor = new QTextEdit(this);
//! [0]
- connect(saveAction, SIGNAL(triggered()), this, SLOT(saveFile()));
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
- connect(calendarAction, SIGNAL(triggered()), this, SLOT(insertCalendar()));
+ connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
+ connect(quitAction, &QAction::triggered, this, &MainWindow::close);
+ connect(calendarAction, &QAction::triggered, this, &MainWindow::insertCalendar);
setCentralWidget(editor);
setWindowTitle(tr("Text Document Writer"));
diff --git a/src/gui/doc/snippets/textdocument-frames/mainwindow.cpp b/src/gui/doc/snippets/textdocument-frames/mainwindow.cpp
index f15ad45f2e..edfadb4c77 100644
--- a/src/gui/doc/snippets/textdocument-frames/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-frames/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
#include "xmlwriter.h"
@@ -64,7 +64,7 @@ MainWindow::MainWindow()
quitAction->setShortcut(tr("Ctrl+Q"));
menuBar()->addMenu(fileMenu);
- editor = new QTextEdit();
+ editor = new QTextEdit;
QTextCursor cursor(editor->textCursor());
cursor.movePosition(QTextCursor::Start);
@@ -130,8 +130,8 @@ MainWindow::MainWindow()
plainCharFormat);
- connect(saveAction, SIGNAL(triggered()), this, SLOT(saveFile()));
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
+ connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
+ connect(quitAction, &QAction::triggered, this, &MainWindow::close);
setCentralWidget(editor);
setWindowTitle(tr("Text Document Frames"));
diff --git a/src/gui/doc/snippets/textdocument-lists/mainwindow.cpp b/src/gui/doc/snippets/textdocument-lists/mainwindow.cpp
index 15a2752c8b..785f7ebcc9 100644
--- a/src/gui/doc/snippets/textdocument-lists/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-lists/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
@@ -88,7 +88,8 @@ MainWindow::MainWindow()
document = new QTextDocument(this);
editor->setDocument(document);
- connect(editor, SIGNAL(selectionChanged()), this, SLOT(updateMenus()));
+ connect(editor, &QTextEdit::selectionChanged,
+ this, &MainWindow::updateMenus);
updateMenus();
diff --git a/src/gui/doc/snippets/textdocument-printing/mainwindow.cpp b/src/gui/doc/snippets/textdocument-printing/mainwindow.cpp
index 40459b49da..a7bd90a9f1 100644
--- a/src/gui/doc/snippets/textdocument-printing/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-printing/mainwindow.cpp
@@ -74,7 +74,7 @@ MainWindow::MainWindow()
document = new QTextDocument(this);
editor->setDocument(document);
- connect(editor, SIGNAL(selectionChanged()), this, SLOT(updateMenus()));
+ connect(editor, &QTextEdit::selectionChanged, this, &MainWindow::updateMenus);
setCentralWidget(editor);
setWindowTitle(tr("Text Document Writer"));
diff --git a/src/gui/doc/snippets/textdocument-selections/mainwindow.cpp b/src/gui/doc/snippets/textdocument-selections/mainwindow.cpp
index 8ac3913f3c..9253e87670 100644
--- a/src/gui/doc/snippets/textdocument-selections/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-selections/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
@@ -90,7 +90,8 @@ MainWindow::MainWindow()
document = new QTextDocument(this);
editor->setDocument(document);
- connect(editor, SIGNAL(selectionChanged()), this, SLOT(updateMenus()));
+ connect(editor, &QTextEdit::selectionChanged,
+ this, &MainWindow::updateMenus);
setCentralWidget(editor);
setWindowTitle(tr("Text Document Writer"));
diff --git a/src/gui/doc/snippets/textdocument-tables/mainwindow.cpp b/src/gui/doc/snippets/textdocument-tables/mainwindow.cpp
index 061c191f1c..bd976a8ce4 100644
--- a/src/gui/doc/snippets/textdocument-tables/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-tables/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
#include "xmlwriter.h"
@@ -132,9 +132,9 @@ MainWindow::MainWindow()
}
//! [8]
- connect(saveAction, SIGNAL(triggered()), this, SLOT(saveFile()));
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
- connect(showTableAction, SIGNAL(triggered()), this, SLOT(showTable()));
+ connect(saveAction, &QAction:triggered, this, &MainWindow::saveFile);
+ connect(quitAction, &QAction:triggered, this, &MainWindow::close);
+ connect(showTableAction, &QAction:triggered, this, &MainWindow::showTable);
setCentralWidget(editor);
setWindowTitle(tr("Text Document Tables"));
diff --git a/src/gui/doc/snippets/textdocumentendsnippet.cpp b/src/gui/doc/snippets/textdocumentendsnippet.cpp
index c8de501838..cb7abd5ca7 100644
--- a/src/gui/doc/snippets/textdocumentendsnippet.cpp
+++ b/src/gui/doc/snippets/textdocumentendsnippet.cpp
@@ -59,7 +59,7 @@ int main(int argv, char **args)
//! [0]
for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next())
- cout << it.text().toStdString() << endl;
+ cout << it.text().toStdString() << Qt::endl;
//! [0]
return 0;
diff --git a/src/gui/doc/src/coordsys.qdoc b/src/gui/doc/src/coordsys.qdoc
index 1856428361..1018b2122b 100644
--- a/src/gui/doc/src/coordsys.qdoc
+++ b/src/gui/doc/src/coordsys.qdoc
@@ -70,8 +70,15 @@
\li \inlineimage coordinatesystem-rect.png
\li \inlineimage coordinatesystem-line.png
\row
- \li QRect(1, 2, 6, 4)
+ \li QRect(QPoint(1, 2), QPoint(7, 6))
+ \li QLine(QPoint(2, 7), QPoint(6, 1))
+ \row
+ \li
\li QLine(2, 7, 6, 1)
+ \row
+ \li QRect(QPoint(1, 2), QSize(6, 4))
+ \row
+ \li QRect(1, 2, 6, 4)
\endtable
\section2 Aliased Painting
diff --git a/src/gui/doc/src/dontdocument.qdoc b/src/gui/doc/src/dontdocument.qdoc
new file mode 100644
index 0000000000..b360acefc1
--- /dev/null
+++ b/src/gui/doc/src/dontdocument.qdoc
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+/*!
+ \dontdocument (QTypeInfo QScreenOrientationChangeEvent QApplicationStateChangeEvent
+ QImageTextKeyLang QMetaTypeId QAbstractUndoItem
+ QOpenGLVersionStatus
+ QOpenGLVersionFunctionsBackend
+ QOpenGLVersionFunctionsStorage
+ QOpenGLFunctions_1_0_CoreBackend
+ QOpenGLFunctions_1_1_CoreBackend
+ QOpenGLFunctions_1_2_CoreBackend
+ QOpenGLFunctions_1_3_CoreBackend
+ QOpenGLFunctions_1_4_CoreBackend
+ QOpenGLFunctions_1_5_CoreBackend
+ QOpenGLFunctions_2_0_CoreBackend
+ QOpenGLFunctions_2_1_CoreBackend
+ QOpenGLFunctions_3_0_CoreBackend
+ QOpenGLFunctions_3_1_CoreBackend
+ QOpenGLFunctions_3_2_CoreBackend
+ QOpenGLFunctions_3_3_CoreBackend
+ QOpenGLFunctions_4_0_CoreBackend
+ QOpenGLFunctions_4_1_CoreBackend
+ QOpenGLFunctions_4_2_CoreBackend
+ QOpenGLFunctions_4_3_CoreBackend
+ QOpenGLFunctions_4_4_CoreBackend
+ QOpenGLFunctions_4_5_CoreBackend
+ QOpenGLFunctions_1_0_DeprecatedBackend
+ QOpenGLFunctions_1_1_DeprecatedBackend
+ QOpenGLFunctions_1_2_DeprecatedBackend
+ QOpenGLFunctions_1_3_DeprecatedBackend
+ QOpenGLFunctions_1_4_DeprecatedBackend
+ QOpenGLFunctions_2_0_DeprecatedBackend
+ QOpenGLFunctions_3_0_DeprecatedBackend
+ QOpenGLFunctions_3_3_DeprecatedBackend
+ QOpenGLFunctions_4_5_DeprecatedBackend
+ QTextFrameLayoutData QPlatformDropQtResponse QPlatformDragQtResponse
+ QPlatformOffscreenSurface QColorDialogOptions QFontDialogOptions
+ QFileDialogOptions QMessageDialogOptions QMessageDialogOptions::CustomButton
+ QPlatformSessionManager QPlatformIntegrationPlugin QPlatformMenuItem
+ QPlatformMenu QPlatformMenuBar QPlatformTextureList)
+*/
diff --git a/src/gui/doc/src/richtext.qdoc b/src/gui/doc/src/richtext.qdoc
index a0f739d418..a8ba076e3d 100644
--- a/src/gui/doc/src/richtext.qdoc
+++ b/src/gui/doc/src/richtext.qdoc
@@ -1197,6 +1197,9 @@
\row \li \c text-transform
\li [ uppercase | lowercase ]
\li Select the transformation that will be performed on the text prior to displaying it.
+ \row \li \c font-kerning
+ \li [ normal | none ]
+ \li Enables or disables kerning between text characters.
\row \li \c font-variant
\li small-caps
\li Perform the smallcaps transformation on the text prior to displaying it.
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 06c9cd3939..45c8c05162 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -48,6 +48,8 @@ include(opengl/opengl.pri)
qtConfig(animation): include(animation/animation.pri)
include(itemmodels/itemmodels.pri)
include(vulkan/vulkan.pri)
+include(platform/platform.pri)
+include(rhi/rhi.pri)
QMAKE_LIBS += $$QMAKE_LIBS_GUI
diff --git a/src/gui/image/qbitmap.cpp b/src/gui/image/qbitmap.cpp
index 2453242fa8..455045eb57 100644
--- a/src/gui/image/qbitmap.cpp
+++ b/src/gui/image/qbitmap.cpp
@@ -310,6 +310,7 @@ QBitmap QBitmap::transformed(const QTransform &matrix) const
return bm;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\overload
\obsolete
@@ -321,5 +322,6 @@ QBitmap QBitmap::transformed(const QMatrix &matrix) const
{
return transformed(QTransform(matrix));
}
+#endif
QT_END_NAMESPACE
diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h
index 188064fccf..3cc360f670 100644
--- a/src/gui/image/qbitmap.h
+++ b/src/gui/image/qbitmap.h
@@ -61,7 +61,7 @@ public:
QBitmap(const QBitmap &other) : QPixmap(other) {}
// QBitmap(QBitmap &&other) : QPixmap(std::move(other)) {} // QPixmap doesn't, yet, have a move ctor
QBitmap &operator=(const QBitmap &other) { QPixmap::operator=(other); return *this; }
- QBitmap &operator=(QBitmap &&other) Q_DECL_NOTHROW { QPixmap::operator=(std::move(other)); return *this; }
+ QBitmap &operator=(QBitmap &&other) noexcept { QPixmap::operator=(std::move(other)); return *this; }
~QBitmap();
#endif
@@ -76,7 +76,10 @@ public:
static QBitmap fromData(const QSize &size, const uchar *bits,
QImage::Format monoFormat = QImage::Format_MonoLSB);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QBitmap::transformed(QTransform) instead")
QBitmap transformed(const QMatrix &) const;
+#endif
QBitmap transformed(const QTransform &matrix) const;
typedef QExplicitlySharedDataPointer<QPlatformPixmap> DataPtr;
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index 7257853c3e..7f8e072322 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -866,10 +866,12 @@ void QBmpHandler::setOption(ImageOption option, const QVariant &value)
Q_UNUSED(value);
}
+#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QBmpHandler::name() const
{
return formatName();
}
+#endif
QT_END_NAMESPACE
diff --git a/src/gui/image/qbmphandler_p.h b/src/gui/image/qbmphandler_p.h
index 56b39dd0f0..33b5b9c501 100644
--- a/src/gui/image/qbmphandler_p.h
+++ b/src/gui/image/qbmphandler_p.h
@@ -113,8 +113,9 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
+#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
-
+#endif
static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override;
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index c362d0dc3f..df8220a0c6 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -315,9 +315,9 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
% HexString<uint>(actualSize.height());
if (mode == QIcon::Active) {
- if (QPixmapCache::find(key % HexString<uint>(mode), pm))
+ if (QPixmapCache::find(key % HexString<uint>(mode), &pm))
return pm; // horray
- if (QPixmapCache::find(key % HexString<uint>(QIcon::Normal), pm)) {
+ if (QPixmapCache::find(key % HexString<uint>(QIcon::Normal), &pm)) {
QPixmap active = pm;
if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp))
active = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(QIcon::Active, pm);
@@ -326,7 +326,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
}
}
- if (!QPixmapCache::find(key % HexString<uint>(mode), pm)) {
+ if (!QPixmapCache::find(key % HexString<uint>(mode), &pm)) {
if (pm.size() != actualSize)
pm = pm.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
if (pe->mode != mode && mode != QIcon::Normal) {
@@ -663,7 +663,7 @@ QFactoryLoader *qt_iconEngineFactoryLoader()
/*!
Constructs a null icon.
*/
-QIcon::QIcon() Q_DECL_NOEXCEPT
+QIcon::QIcon() noexcept
: d(0)
{
}
@@ -987,7 +987,7 @@ bool QIcon::isNull() const
*/
bool QIcon::isDetached() const
{
- return !d || d->ref.load() == 1;
+ return !d || d->ref.loadRelaxed() == 1;
}
/*! \internal
@@ -1000,7 +1000,7 @@ void QIcon::detach()
delete d;
d = 0;
return;
- } else if (d->ref.load() != 1) {
+ } else if (d->ref.loadRelaxed() != 1) {
QIconPrivate *x = new QIconPrivate(d->engine->clone());
if (!d->ref.deref())
delete d;
@@ -1080,11 +1080,12 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State
if (!d) {
QFileInfo info(fileName);
- QIconEngine *engine = iconEngineFromSuffix(fileName, info.suffix());
+ QString suffix = info.suffix();
#if QT_CONFIG(mimetype)
- if (!engine)
- engine = iconEngineFromSuffix(fileName, QMimeDatabase().mimeTypeForFile(info).preferredSuffix());
+ if (suffix.isEmpty())
+ suffix = QMimeDatabase().mimeTypeForFile(info).preferredSuffix(); // determination from contents
#endif // mimetype
+ QIconEngine *engine = iconEngineFromSuffix(fileName, suffix);
d = new QIconPrivate(engine ? engine : new QPixmapIconEngine);
}
@@ -1495,7 +1496,7 @@ QDebug operator<<(QDebug dbg, const QIcon &i)
if (!i.name().isEmpty())
dbg << i.name() << ',';
dbg << "availableSizes[normal,Off]=" << i.availableSizes()
- << ",cacheKey=" << showbase << hex << i.cacheKey() << dec << noshowbase;
+ << ",cacheKey=" << Qt::showbase << Qt::hex << i.cacheKey() << Qt::dec << Qt::noshowbase;
}
dbg << ')';
return dbg;
@@ -1522,7 +1523,7 @@ QDebug operator<<(QDebug dbg, const QIcon &i)
foo@3x.png, then foo@2x, then fall back to foo.png if not found.
\a sourceDevicePixelRatio will be set to the value of N if the argument is
- a non-null pointer
+ not \nullptr
*/
QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio,
qreal *sourceDevicePixelRatio)
diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h
index 6a4fc8927a..735a3e134d 100644
--- a/src/gui/image/qicon.h
+++ b/src/gui/image/qicon.h
@@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE
class QIconPrivate;
class QIconEngine;
+class QPainter;
class Q_GUI_EXPORT QIcon
{
@@ -57,23 +58,19 @@ public:
enum Mode { Normal, Disabled, Active, Selected };
enum State { On, Off };
- QIcon() Q_DECL_NOEXCEPT;
+ QIcon() noexcept;
QIcon(const QPixmap &pixmap);
QIcon(const QIcon &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QIcon(QIcon &&other) Q_DECL_NOEXCEPT
+ QIcon(QIcon &&other) noexcept
: d(other.d)
{ other.d = nullptr; }
-#endif
explicit QIcon(const QString &fileName); // file or resource name
explicit QIcon(QIconEngine *engine);
~QIcon();
QIcon &operator=(const QIcon &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QIcon &operator=(QIcon &&other) Q_DECL_NOEXCEPT
+ inline QIcon &operator=(QIcon &&other) noexcept
{ swap(other); return *this; }
-#endif
- inline void swap(QIcon &other) Q_DECL_NOEXCEPT
+ inline void swap(QIcon &other) noexcept
{ qSwap(d, other.d); }
operator QVariant() const;
diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h
index 0c5b51dc71..89fed5ccda 100644
--- a/src/gui/image/qiconengine.h
+++ b/src/gui/image/qiconengine.h
@@ -94,7 +94,7 @@ public:
virtual void virtual_hook(int id, void *data);
private:
- QIconEngine &operator=(const QIconEngine &other) Q_DECL_EQ_DELETE;
+ QIconEngine &operator=(const QIconEngine &other) = delete;
};
#if QT_DEPRECATED_SINCE(5, 0)
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index ef0481bdb2..61d32b0dec 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -38,8 +38,10 @@
****************************************************************************/
#include "qimage.h"
-#include "qdatastream.h"
+
#include "qbuffer.h"
+#include "qdatastream.h"
+#include "qcolortransform.h"
#include "qmap.h"
#include "qmatrix.h"
#include "qtransform.h"
@@ -54,6 +56,7 @@
#include <stdlib.h>
#include <limits.h>
#include <qpa/qplatformpixmap.h>
+#include <private/qcolortransform_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qmemrotate_p.h>
#include <private/qimagescale_p.h>
@@ -117,7 +120,7 @@ QImageData::QImageData()
*/
QImageData * QImageData::create(const QSize &size, QImage::Format format)
{
- if (!size.isValid() || format == QImage::Format_Invalid)
+ if (size.isEmpty() || format == QImage::Format_Invalid)
return nullptr; // invalid parameter(s)
int width = size.width();
@@ -288,6 +291,7 @@ bool QImageData::checkForAlphaPixels() const
case QImage::Format_BGR30:
case QImage::Format_RGB30:
case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
case QImage::Format_RGBX64:
break;
case QImage::Format_Invalid:
@@ -710,6 +714,7 @@ bool QImageData::checkForAlphaPixels() const
\value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10). (added in Qt 5.4)
\value Format_Alpha8 The image is stored using an 8-bit alpha only format. (added in Qt 5.5)
\value Format_Grayscale8 The image is stored using an 8-bit grayscale format. (added in Qt 5.5)
+ \value Format_Grayscale16 The image is stored using an 16-bit grayscale format. (added in Qt 5.13)
\value Format_RGBX64 The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16).
This is the same as the Format_RGBX64 except alpha must always be 65535. (added in Qt 5.12)
\value Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16). (added in Qt 5.12)
@@ -736,7 +741,7 @@ bool QImageData::checkForAlphaPixels() const
\sa isNull()
*/
-QImage::QImage() Q_DECL_NOEXCEPT
+QImage::QImage() noexcept
: QPaintDevice()
{
d = 0;
@@ -1077,10 +1082,10 @@ QImage::operator QVariant() const
void QImage::detach()
{
if (d) {
- if (d->is_cached && d->ref.load() == 1)
+ if (d->is_cached && d->ref.loadRelaxed() == 1)
QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
- if (d->ref.load() != 1 || d->ro_data)
+ if (d->ref.loadRelaxed() != 1 || d->ro_data)
*this = copy();
if (d)
@@ -1101,6 +1106,7 @@ static void copyMetadata(QImageData *dst, const QImageData *src)
// Doesn't copy colortable and alpha_clut, or offset.
copyPhysicalMetadata(dst, src);
dst->text = src->text;
+ dst->colorSpace = src->colorSpace;
}
static void copyMetadata(QImage *dst, const QImage &src)
@@ -1390,7 +1396,7 @@ void QImage::setColorTable(const QVector<QRgb> colors)
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
d->colortable = colors;
#else
- d->colortable = qMove(const_cast<QVector<QRgb>&>(colors));
+ d->colortable = std::move(const_cast<QVector<QRgb>&>(colors));
#endif
d->has_alpha_clut = false;
for (int i = 0; i < d->colortable.size(); ++i) {
@@ -1464,6 +1470,7 @@ void QImage::setDevicePixelRatio(qreal scaleFactor)
d->devicePixelRatio = scaleFactor;
}
+#if QT_DEPRECATED_SINCE(5, 10)
/*!
\since 4.6
\obsolete
@@ -1480,6 +1487,7 @@ int QImage::byteCount() const
Q_ASSERT(!d || d->nbytes < std::numeric_limits<int>::max());
return d ? int(d->nbytes) : 0;
}
+#endif
/*!
\since 5.10
@@ -2063,6 +2071,7 @@ static bool highColorPrecision(QImage::Format format)
case QImage::Format_RGBX64:
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_Grayscale16:
return true;
default:
break;
@@ -2084,13 +2093,7 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
Image_Converter converter = qimage_converter_map[d->format][format];
if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
if (highColorPrecision(format) && highColorPrecision(d->format)) {
- // Convert over RGBA64_Premultiplied
- if (format == QImage::Format_RGBA64_Premultiplied)
- converter = convert_generic_to_rgb64;
- else {
- Q_ASSERT(d->format != QImage::Format_RGBA64_Premultiplied);
- return convertToFormat(Format_RGBA64_Premultiplied, flags).convertToFormat(format, flags);
- }
+ converter = convert_generic_to_rgb64;
} else
converter = convert_generic;
}
@@ -2271,6 +2274,29 @@ bool QImage::reinterpretAsFormat(Format format)
}
/*!
+ \since 5.13
+
+ Detach and convert the image to the given \a format in place.
+
+ The specified image conversion \a flags control how the image data
+ is handled during the conversion process.
+
+ \sa convertToFormat()
+*/
+
+void QImage::convertTo(Format format, Qt::ImageConversionFlags flags)
+{
+ if (!d || format == QImage::Format_Invalid)
+ return;
+
+ detach();
+ if (convertToFormat_inplace(format, flags))
+ return;
+
+ *this = convertToFormat_helper(format, flags);
+}
+
+/*!
\fn bool QImage::valid(const QPoint &pos) const
Returns \c true if \a pos is a valid coordinate pair within the
@@ -2556,6 +2582,10 @@ QColor QImage::pixelColor(int x, int y) const
case Format_RGBA64_Premultiplied:
c = reinterpret_cast<const QRgba64 *>(s)[x];
break;
+ case Format_Grayscale16: {
+ quint16 v = reinterpret_cast<const quint16 *>(s)[x];
+ return QColor(qRgba64(v, v, v, 0xffff));
+ }
default:
c = QRgba64::fromArgb32(pixel(x, y));
break;
@@ -2666,6 +2696,7 @@ bool QImage::allGray() const
case Format_Alpha8:
return false;
case Format_Grayscale8:
+ case Format_Grayscale16:
return true;
case Format_RGB32:
case Format_ARGB32:
@@ -2732,7 +2763,7 @@ bool QImage::isGrayscale() const
if (d->format == QImage::Format_Alpha8)
return false;
- if (d->format == QImage::Format_Grayscale8)
+ if (d->format == QImage::Format_Grayscale8 || d->format == QImage::Format_Grayscale16)
return true;
switch (depth()) {
@@ -3371,6 +3402,7 @@ QImage QImage::rgbSwapped_helper() const
break;
case Format_Alpha8:
case Format_Grayscale8:
+ case Format_Grayscale16:
return *this;
case Format_Mono:
case Format_MonoLSB:
@@ -3482,6 +3514,7 @@ void QImage::rgbSwapped_inplace()
break;
case Format_Alpha8:
case Format_Grayscale8:
+ case Format_Grayscale16:
return;
case Format_Mono:
case Format_MonoLSB:
@@ -4389,7 +4422,7 @@ qint64 QImage::cacheKey() const
bool QImage::isDetached() const
{
- return d && d->ref.load() == 1;
+ return d && d->ref.loadRelaxed() == 1;
}
@@ -4657,12 +4690,14 @@ QImage QImage::smoothScaled(int w, int h) const {
case QImage::Format_RGBX8888:
#endif
case QImage::Format_RGBA8888_Premultiplied:
+#if QT_CONFIG(raster_64bit)
case QImage::Format_RGBX64:
case QImage::Format_RGBA64_Premultiplied:
break;
case QImage::Format_RGBA64:
src = src.convertToFormat(QImage::Format_RGBA64_Premultiplied);
break;
+#endif
default:
if (src.hasAlphaChannel())
src = src.convertToFormat(QImage::Format_ARGB32_Premultiplied);
@@ -4920,13 +4955,139 @@ QTransform QImage::trueMatrix(const QTransform &matrix, int w, int h)
return matrix * QTransform().translate(-delta.x(), -delta.y());
}
+/*!
+ \since 5.14
+
+ Sets the image color space to \a colorSpace without performing any conversions on image data.
+
+ \sa colorSpace()
+*/
+void QImage::setColorSpace(const QColorSpace &colorSpace)
+{
+ if (!d)
+ return;
+ if (d->colorSpace == colorSpace)
+ return;
+ if (!isDetached()) // Detach only if shared, not for read-only data.
+ detach();
+ d->colorSpace = colorSpace;
+}
+
+/*!
+ \since 5.14
+
+ Converts the image to \a colorSpace.
+
+ If the image has no valid color space, the method does nothing.
+
+ \sa convertedToColorSpace(), setColorSpace()
+*/
+void QImage::convertToColorSpace(const QColorSpace &colorSpace)
+{
+ if (!d)
+ return;
+ if (!d->colorSpace.isValid())
+ return;
+ if (!colorSpace.isValid()) {
+ qWarning() << "QImage::convertToColorSpace: Output colorspace is not valid";
+ return;
+ }
+ detach();
+ applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace));
+ d->colorSpace = colorSpace;
+}
+
+/*!
+ \since 5.14
+
+ Returns the image converted to \a colorSpace.
+
+ If the image has no valid color space, a null QImage is returned.
+
+ \sa convertToColorSpace()
+*/
+QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace) const
+{
+ if (!d || !d->colorSpace.isValid() || !colorSpace.isValid())
+ return QImage();
+ QImage image = copy();
+ image.convertToColorSpace(colorSpace);
+ return image;
+}
+
+/*!
+ \since 5.14
+
+ Returns the color space of the image if a color space is defined.
+*/
+QColorSpace QImage::colorSpace() const
+{
+ if (!d)
+ return QColorSpace::Undefined;
+ return d->colorSpace;
+}
+
+/*!
+ \since 5.14
+
+ Applies the color transformation \a transform to all pixels in the image.
+*/
+void QImage::applyColorTransform(const QColorTransform &transform)
+{
+ QImage::Format oldFormat = format();
+ if (depth() > 32) {
+ if (format() != QImage::Format_RGBX64 && format() != QImage::Format_RGBA64
+ && format() != QImage::Format_RGBA64_Premultiplied)
+ *this = std::move(*this).convertToFormat(QImage::Format_RGBA64);
+ } else if (format() != QImage::Format_ARGB32 && format() != QImage::Format_RGB32
+ && format() != QImage::Format_ARGB32_Premultiplied) {
+ if (hasAlphaChannel())
+ *this = std::move(*this).convertToFormat(QImage::Format_ARGB32);
+ else
+ *this = std::move(*this).convertToFormat(QImage::Format_RGB32);
+ }
+
+ QColorTransformPrivate::TransformFlags flags = QColorTransformPrivate::Unpremultiplied;
+ switch (format()) {
+ case Format_ARGB32_Premultiplied:
+ case Format_RGBA64_Premultiplied:
+ flags = QColorTransformPrivate::Premultiplied;
+ break;
+ case Format_RGB32:
+ case Format_RGBX64:
+ flags = QColorTransformPrivate::InputOpaque;
+ break;
+ case Format_ARGB32:
+ case Format_RGBA64:
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+
+ if (depth() > 32) {
+ for (int i = 0; i < height(); ++i) {
+ QRgba64 *scanline = reinterpret_cast<QRgba64 *>(scanLine(i));
+ transform.d_func()->apply(scanline, scanline, width(), flags);
+ }
+ } else {
+ for (int i = 0; i < height(); ++i) {
+ QRgb *scanline = reinterpret_cast<QRgb *>(scanLine(i));
+ transform.d_func()->apply(scanline, scanline, width(), flags);
+ }
+ }
+
+ if (oldFormat != format())
+ *this = std::move(*this).convertToFormat(oldFormat);
+}
+
+
bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags)
{
if (format == newFormat)
return true;
// No in-place conversion if we have to detach
- if (ref.load() > 1 || !own_data)
+ if (ref.loadRelaxed() > 1 || !own_data)
return false;
InPlace_Image_Converter converter = qimage_inplace_converter_map[format][newFormat];
@@ -5376,13 +5537,26 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = {
/*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
/*INTERPRETATION*/ QPixelFormat::UnsignedShort,
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_Grayscale16:
+ QPixelFormat(QPixelFormat::Grayscale,
+ /*GRAY*/ 16,
+ /*SECOND*/ 0,
+ /*THIRD*/ 0,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
};
Q_STATIC_ASSERT(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
/*!
Returns the QImage::Format as a QPixelFormat
*/
-QPixelFormat QImage::pixelFormat() const Q_DECL_NOTHROW
+QPixelFormat QImage::pixelFormat() const noexcept
{
return toPixelFormat(format());
}
@@ -5390,7 +5564,7 @@ QPixelFormat QImage::pixelFormat() const Q_DECL_NOTHROW
/*!
Converts \a format into a QPixelFormat
*/
-QPixelFormat QImage::toPixelFormat(QImage::Format format) Q_DECL_NOTHROW
+QPixelFormat QImage::toPixelFormat(QImage::Format format) noexcept
{
Q_ASSERT(static_cast<int>(format) < NImageFormats);
return pixelformats[format];
@@ -5399,7 +5573,7 @@ QPixelFormat QImage::toPixelFormat(QImage::Format format) Q_DECL_NOTHROW
/*!
Converts \a format into a QImage::Format
*/
-QImage::Format QImage::toImageFormat(QPixelFormat format) Q_DECL_NOTHROW
+QImage::Format QImage::toImageFormat(QPixelFormat format) noexcept
{
for (int i = 0; i < NImageFormats; i++) {
if (format == pixelformats[i])
@@ -5415,7 +5589,7 @@ Q_GUI_EXPORT void qt_imageTransform(QImage &src, QImageIOHandler::Transformation
if (orient == QImageIOHandler::TransformationRotate270) {
src = rotated270(src);
} else {
- src = qMove(src).mirrored(orient & QImageIOHandler::TransformationMirror,
+ src = std::move(src).mirrored(orient & QImageIOHandler::TransformationMirror,
orient & QImageIOHandler::TransformationFlip);
if (orient & QImageIOHandler::TransformationRotate90)
src = rotated90(src);
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 6505fd5845..7c68168be8 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -61,9 +61,11 @@ Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(CGImage);
QT_BEGIN_NAMESPACE
+class QColorSpace;
+class QColorTransform;
class QIODevice;
-class QStringList;
class QMatrix;
+class QStringList;
class QTransform;
class QVariant;
template <class T> class QList;
@@ -128,17 +130,14 @@ public:
Format_RGBX64,
Format_RGBA64,
Format_RGBA64_Premultiplied,
-#if 0
- // reserved for future use
Format_Grayscale16,
-#endif
#ifndef Q_QDOC
NImageFormats
#endif
};
Q_ENUM(Format)
- QImage() Q_DECL_NOEXCEPT;
+ QImage() noexcept;
QImage(const QSize &size, Format format);
QImage(int width, int height, Format format);
QImage(uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr);
@@ -152,19 +151,15 @@ public:
explicit QImage(const QString &fileName, const char *format = nullptr);
QImage(const QImage &);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QImage(QImage &&other) Q_DECL_NOEXCEPT
+ inline QImage(QImage &&other) noexcept
: QPaintDevice(), d(nullptr)
{ qSwap(d, other.d); }
-#endif
~QImage();
QImage &operator=(const QImage &);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QImage &operator=(QImage &&other) Q_DECL_NOEXCEPT
+ inline QImage &operator=(QImage &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- inline void swap(QImage &other) Q_DECL_NOEXCEPT
+ inline void swap(QImage &other) noexcept
{ qSwap(d, other.d); }
bool isNull() const;
@@ -199,6 +194,8 @@ public:
Q_REQUIRED_RESULT QImage convertToFormat(Format f, const QVector<QRgb> &colorTable, Qt::ImageConversionFlags flags = Qt::AutoColor) const;
bool reinterpretAsFormat(Format f);
+ void convertTo(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor);
+
int width() const;
int height() const;
QSize size() const;
@@ -290,17 +287,23 @@ public:
QImage mirrored(bool horizontally = false, bool vertically = true) const &
{ return mirrored_helper(horizontally, vertically); }
QImage &&mirrored(bool horizontally = false, bool vertically = true) &&
- { mirrored_inplace(horizontally, vertically); return qMove(*this); }
+ { mirrored_inplace(horizontally, vertically); return std::move(*this); }
QImage rgbSwapped() const &
{ return rgbSwapped_helper(); }
QImage &&rgbSwapped() &&
- { rgbSwapped_inplace(); return qMove(*this); }
+ { rgbSwapped_inplace(); return std::move(*this); }
#else
QImage mirrored(bool horizontally = false, bool vertically = true) const;
QImage rgbSwapped() const;
#endif
void invertPixels(InvertMode = InvertRgb);
+ QColorSpace colorSpace() const;
+ QImage convertedToColorSpace(const QColorSpace &) const;
+ void convertToColorSpace(const QColorSpace &);
+ void setColorSpace(const QColorSpace &);
+
+ void applyColorTransform(const QColorTransform &transform);
bool load(QIODevice *device, const char* format);
bool load(const QString &fileName, const char *format = nullptr);
@@ -334,9 +337,9 @@ public:
QString text(const QString &key = QString()) const;
void setText(const QString &key, const QString &value);
- QPixelFormat pixelFormat() const Q_DECL_NOTHROW;
- static QPixelFormat toPixelFormat(QImage::Format format) Q_DECL_NOTHROW;
- static QImage::Format toImageFormat(QPixelFormat format) Q_DECL_NOTHROW;
+ QPixelFormat pixelFormat() const noexcept;
+ static QPixelFormat toPixelFormat(QImage::Format format) noexcept;
+ static QImage::Format toImageFormat(QPixelFormat format) noexcept;
// Platform specific conversion functions
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 215dd33499..837ac88470 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -39,7 +39,7 @@
#include <private/qdrawhelper_p.h>
#include <private/qguiapplication_p.h>
-#include <private/qcolorprofile_p.h>
+#include <private/qcolortrclut_p.h>
#include <private/qendian_p.h>
#include <private/qsimd_p.h>
#include <private/qimage_p.h>
@@ -100,7 +100,7 @@ const uchar *qt_get_bitflip_array()
void qGamma_correct_back_to_linear_cs(QImage *image)
{
- const QColorProfile *cp = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
+ const QColorTrcLut *cp = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
if (!cp)
return;
// gamma correct the pixels back to linear color space...
@@ -223,18 +223,29 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
- Q_ASSERT(dest->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(dest->format > QImage::Format_Indexed8);
Q_ASSERT(src->format > QImage::Format_Indexed8);
+ QRgba64 buf[BufferSize];
+ QRgba64 *buffer = buf;
const QPixelLayout *srcLayout = &qPixelLayouts[src->format];
+ const QPixelLayout *destLayout = &qPixelLayouts[dest->format];
const uchar *srcData = src->data;
uchar *destData = dest->data;
const FetchAndConvertPixelsFunc64 fetch = srcLayout->fetchToRGBA64PM;
+ const ConvertAndStorePixelsFunc64 store = qStoreFromRGBA64PM[dest->format];
for (int y = 0; y < src->height; ++y) {
- const QRgba64 *ptr = fetch((QRgba64*)destData, srcData, 0, src->width, nullptr, nullptr);
- if (ptr != (const QRgba64*)destData) {
- memcpy(destData, ptr, dest->bytes_per_line);
+ int x = 0;
+ while (x < src->width) {
+ int l = src->width - x;
+ if (destLayout->bpp == QPixelLayout::BPP64)
+ buffer = reinterpret_cast<QRgba64 *>(destData) + x;
+ else
+ l = qMin(l, BufferSize);
+ const QRgba64 *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr);
+ store(destData, ptr, x, l, nullptr, nullptr);
+ x += l;
}
srcData += src->bytes_per_line;
destData += dest->bytes_per_line;
@@ -1205,33 +1216,6 @@ static void convert_RGBA64_to_ARGB32(QImageData *dest, const QImageData *src, Qt
}
template<bool RGBA>
-static void convert_RGBA64PM_to_ARGB32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
- Q_ASSERT(RGBA || dest->format == QImage::Format_ARGB32);
- Q_ASSERT(!RGBA || dest->format == QImage::Format_RGBA8888);
- Q_ASSERT(src->width == dest->width);
- Q_ASSERT(src->height == dest->height);
-
- const int src_pad = (src->bytes_per_line >> 3) - src->width;
- const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
- const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
- uint *dest_data = reinterpret_cast<uint *>(dest->data);
-
- for (int i = 0; i < src->height; ++i) {
- const QRgba64 *end = src_data + src->width;
- while (src_data < end) {
- QRgba64 s = src_data->unpremultiplied();
- *dest_data = RGBA ? ARGB2RGBA(s.toArgb32()) : s.toArgb32();
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
-template<bool RGBA>
static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(RGBA || src->format == QImage::Format_ARGB32);
@@ -1240,74 +1224,14 @@ static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);
- const int src_pad = (src->bytes_per_line >> 2) - src->width;
- const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
- const uint *src_data = reinterpret_cast<const uint *>(src->data);
- QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
-
- for (int i = 0; i < src->height; ++i) {
- const uint *end = src_data + src->width;
- while (src_data < end) {
- if (RGBA)
- *dest_data = QRgba64::fromArgb32(RGBA2ARGB(*src_data));
- else
- *dest_data = QRgba64::fromArgb32(*src_data);
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
-template<QtPixelOrder PixelOrder>
-static void convert_RGBA64PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
- Q_ASSERT(dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_BGR30);
- Q_ASSERT(src->width == dest->width);
- Q_ASSERT(src->height == dest->height);
-
- const int src_pad = (src->bytes_per_line >> 3) - src->width;
- const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
- const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
- uint *dest_data = reinterpret_cast<uint *>(dest->data);
-
- for (int i = 0; i < src->height; ++i) {
- const QRgba64 *end = src_data + src->width;
- while (src_data < end) {
- *dest_data = 0xc0000000 | qConvertRgb64ToRgb30<PixelOrder>(src_data->unpremultiplied());
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
-template<QtPixelOrder PixelOrder>
-static void convert_RGBA64PM_to_A2RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
- Q_ASSERT(dest->format == QImage::Format_A2RGB30_Premultiplied
- || dest->format == QImage::Format_A2BGR30_Premultiplied);
- Q_ASSERT(src->width == dest->width);
- Q_ASSERT(src->height == dest->height);
-
- const int src_pad = (src->bytes_per_line >> 3) - src->width;
- const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
- const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
- uint *dest_data = reinterpret_cast<uint *>(dest->data);
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+ const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[src->format + 1].fetchToRGBA64PM;
for (int i = 0; i < src->height; ++i) {
- const QRgba64 *end = src_data + src->width;
- while (src_data < end) {
- *dest_data = qConvertRgb64ToRgb30<PixelOrder>(*src_data);
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
+ fetch(reinterpret_cast<QRgba64 *>(dest_data), src_data, 0, src->width, nullptr, nullptr);
+ src_data += src->bytes_per_line;;
+ dest_data += dest->bytes_per_line;
}
}
@@ -1447,6 +1371,56 @@ static bool convert_RGBA64PM_to_RGBA64_inplace(QImageData *data, Qt::ImageConver
return true;
}
+static void convert_gray16_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_Grayscale16);
+ Q_ASSERT(dest->format == QImage::Format_RGBA64 || dest->format == QImage::Format_RGBX64 ||
+ dest->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const qsizetype sbpl = src->bytes_per_line;
+ const qsizetype dbpl = dest->bytes_per_line;
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const quint16 *src_line = reinterpret_cast<const quint16 *>(src_data);
+ QRgba64 *dest_line = reinterpret_cast<QRgba64 *>(dest_data);
+ for (int j = 0; j < src->width; ++j) {
+ quint16 s = src_line[j];
+ dest_line[j] = qRgba64(s, s, s, 0xFFFF);
+ }
+ src_data += sbpl;
+ dest_data += dbpl;
+ }
+}
+
+static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(dest->format == QImage::Format_Grayscale16);
+ Q_ASSERT(src->format == QImage::Format_RGBX64 ||
+ src->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const qsizetype sbpl = src->bytes_per_line;
+ const qsizetype dbpl = dest->bytes_per_line;
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ const QRgba64 *src_line = reinterpret_cast<const QRgba64 *>(src_data);
+ quint16 *dest_line = reinterpret_cast<quint16 *>(dest_data);
+ for (int j = 0; j < src->width; ++j) {
+ QRgba64 s = src_line[j].unpremultiplied();
+ dest_line[j] = qGray(s.red(), s.green(), s.blue());
+ }
+ src_data += sbpl;
+ dest_data += dbpl;
+ }
+}
+
static QVector<QRgb> fix_color_table(const QVector<QRgb> &ctbl, QImage::Format format)
{
QVector<QRgb> colorTable = ctbl;
@@ -2291,7 +2265,7 @@ static bool convert_Grayscale8_to_Indexed8_inplace(QImageData *data, Qt::ImageCo
Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
{
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{
0,
@@ -2312,7 +2286,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Mono
{
@@ -2334,7 +2308,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_MonoLSB
{
@@ -2359,7 +2333,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0, 0, 0, 0, 0,
convert_Indexed8_to_Alpha8,
convert_Indexed8_to_Grayscale8,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_Indexed8
{
@@ -2387,7 +2361,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_RGB_to_RGB30<PixelOrderRGB, false>,
0,
0, 0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_RGB32
{
@@ -2417,7 +2391,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0, 0,
0,
convert_ARGB32_to_RGBA64<false>,
- 0
+ 0, 0
}, // Format_ARGB32
{
@@ -2442,7 +2416,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_ARGB_to_RGBA,
0, 0, 0, 0,
0, 0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_ARGB32_Premultiplied
{
@@ -2464,7 +2438,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB16
{
@@ -2486,7 +2460,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8565_Premultiplied
{
@@ -2508,7 +2482,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB666
{
@@ -2530,7 +2504,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB6666_Premultiplied
{
@@ -2552,7 +2526,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB555
{
@@ -2574,7 +2548,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8555_Premultiplied
{
@@ -2597,7 +2571,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_RGB888_to_RGB<true>,
convert_RGB888_to_RGB<true>,
convert_RGB888_to_RGB<true>,
- 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB888
{
@@ -2619,7 +2593,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB444
{
@@ -2640,7 +2614,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB4444_Premultiplied
{
0,
@@ -2667,7 +2641,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_RGB_to_RGB30<PixelOrderRGB, true>,
0,
0, 0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_RGBX8888
{
0,
@@ -2696,7 +2670,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0, 0,
0,
convert_ARGB32_to_RGBA64<true>,
- 0
+ 0, 0
}, // Format_RGBA8888
{
@@ -2718,7 +2692,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGBA8888_Premultiplied
{
@@ -2746,7 +2720,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_BGR30_to_RGB30,
convert_BGR30_to_RGB30,
0, 0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_BGR30
{
0,
@@ -2773,8 +2747,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_A2RGB30_PM_to_RGB30<true>,
convert_BGR30_to_RGB30,
0, 0,
- 0, 0, 0
- }, // Format_BGR30A2_Premultiplied
+ 0, 0, 0, 0
+ }, // Format_A2BGR30_Premultiplied
{
0,
0,
@@ -2799,7 +2773,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_BGR30_to_RGB30,
0,
convert_passthrough,
- 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0
}, // Format_RGB30
{
0,
@@ -2826,8 +2800,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_A2RGB30_PM_to_RGB30<false>,
0,
0, 0,
- 0, 0, 0
- }, // Format_RGB30A2_Premultiplied
+ 0, 0, 0, 0
+ }, // Format_A2RGB30_Premultiplied
{
0,
0,
@@ -2846,7 +2820,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Alpha8
{
0,
@@ -2872,7 +2846,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // self
convert_passthrough,
- convert_passthrough
+ convert_passthrough,
+ convert_RGBA64_to_gray16
}, // Format_RGBX64
{
0,
@@ -2898,7 +2873,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0, 0,
convert_RGBA64_to_RGBx64,
0, // self
- convert_RGBA64_to_RGBA64PM
+ convert_RGBA64_to_RGBA64PM,
+ 0
}, // Format_RGBA64
{
0,
@@ -2906,7 +2882,6 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_RGBA64PM_to_ARGB32<false>,
0,
0,
0,
@@ -2918,29 +2893,58 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_RGBA64PM_to_ARGB32<true>,
0,
- convert_RGBA64PM_to_RGB30<PixelOrderBGR>,
- convert_RGBA64PM_to_A2RGB30<PixelOrderBGR>,
- convert_RGBA64PM_to_RGB30<PixelOrderRGB>,
- convert_RGBA64PM_to_A2RGB30<PixelOrderRGB>,
+ 0,
+ 0,
+ 0, 0, 0, 0,
0, 0,
convert_RGBA64PM_to_RGBA64<true>,
convert_RGBA64PM_to_RGBA64<false>,
- 0 // self
- } // Format_RGBA64_Premultiplied
+ 0, // self
+ convert_RGBA64_to_gray16
+ }, // Format_RGBA64_Premultiplied
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, 0,
+ convert_gray16_to_RGBA64,
+ convert_gray16_to_RGBA64,
+ convert_gray16_to_RGBA64,
+ 0 // self
+ }, // Format_Grayscale16
};
InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
{
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Mono
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_MonoLSB
{
0,
@@ -2964,7 +2968,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0, 0, 0, 0, 0,
convert_Indexed8_to_Alpha8_inplace,
convert_Indexed8_to_Grayscale8_inplace,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_Indexed8
{
0,
@@ -2991,7 +2995,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_RGB_to_RGB30_inplace<PixelOrderRGB, false>,
0,
0, 0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_RGB32
{
0,
@@ -3018,7 +3022,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_RGB_to_RGB30_inplace<PixelOrderRGB, false>,
0,
0, 0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_ARGB32
{
0,
@@ -3042,34 +3046,34 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_ARGB_to_RGBA_inplace<QImage::Format_RGBA8888_Premultiplied>,
0, 0, 0, 0,
0, 0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_ARGB32_Premultiplied
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB16
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8565_Premultiplied
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB666
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB6666_Premultiplied
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB555
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8555_Premultiplied
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB888
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB444
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB4444_Premultiplied
{
0,
@@ -3096,7 +3100,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_RGB_to_RGB30_inplace<PixelOrderRGB, true>,
0,
0, 0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_RGBX8888
{
0,
@@ -3123,7 +3127,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_RGB_to_RGB30_inplace<PixelOrderRGB, true>,
0,
0, 0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_RGBA8888
{
0,
@@ -3145,7 +3149,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGBA8888_Premultiplied
{
0,
@@ -3172,7 +3176,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_BGR30_to_RGB30_inplace,
convert_BGR30_to_A2RGB30_inplace,
0, 0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_BGR30
{
0,
@@ -3198,8 +3202,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0, // self
convert_A2RGB30_PM_to_RGB30_inplace<true>,
convert_BGR30_to_RGB30_inplace,
- 0, 0, 0, 0, 0
- }, // Format_BGR30A2_Premultiplied
+ 0, 0, 0, 0, 0, 0
+ }, // Format_A2BGR30_Premultiplied
{
0,
0,
@@ -3224,7 +3228,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_BGR30_to_A2RGB30_inplace,
0, // self
convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>,
- 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0
}, // Format_RGB30
{
0,
@@ -3251,8 +3255,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_A2RGB30_PM_to_RGB30_inplace<false>,
0, // self
0, 0,
- 0, 0, 0
- }, // Format_RGB30A2_Premultiplied
+ 0, 0, 0, 0
+ }, // Format_A2RGB30_Premultiplied
{
0,
0,
@@ -3276,7 +3280,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0, 0, 0, 0,
0, // self
0,
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_Alpha8
{
0,
@@ -3301,26 +3305,32 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0, 0, 0, 0,
0,
0, // self
- 0, 0, 0
+ 0, 0, 0, 0
}, // Format_Grayscale8
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // self
convert_passthrough_inplace<QImage::Format_RGBA64>,
convert_passthrough_inplace<QImage::Format_RGBA64_Premultiplied>,
+ 0
}, // Format_RGBX64
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
convert_RGBA64_to_RGBx64_inplace,
0, // self
- convert_RGBA64_to_RGBA64PM_inplace
+ convert_RGBA64_to_RGBA64PM_inplace,
+ 0
}, // Format_RGBA64
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
convert_RGBA64PM_to_RGBA64_inplace<true>,
convert_RGBA64PM_to_RGBA64_inplace<false>,
- 0 // self
- } // Format_RGBA64_Premultiplied
+ 0, // self
+ 0
+ }, // Format_RGBA64_Premultiplied
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ }, // Format_Grayscale16
};
static void qInitImageConversions()
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index a0a3b5406e..9da6acd0a7 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -51,7 +51,9 @@
// We mean it.
//
+#include <QtGui/qcolorspace.h>
#include <QtGui/private/qtguiglobal_p.h>
+#include <QtGui/qimage.h>
#include <QtCore/private/qnumeric_p.h>
#include <QMap>
@@ -65,7 +67,7 @@ struct Q_GUI_EXPORT QImageData { // internal image data
QImageData();
~QImageData();
static QImageData *create(const QSize &size, QImage::Format format);
- static QImageData *create(uchar *data, int w, int h, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0);
+ static QImageData *create(uchar *data, int w, int h, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr);
QAtomicInt ref;
@@ -106,6 +108,8 @@ struct Q_GUI_EXPORT QImageData { // internal image data
QPaintEngine *paintEngine;
+ QColorSpace colorSpace;
+
struct ImageSizeParameters {
qsizetype bytesPerLine;
qsizetype totalSize;
@@ -195,6 +199,7 @@ inline int qt_depthForFormat(QImage::Format format)
case QImage::Format_RGB16:
case QImage::Format_RGB444:
case QImage::Format_ARGB4444_Premultiplied:
+ case QImage::Format_Grayscale16:
depth = 16;
break;
case QImage::Format_RGB666:
diff --git a/src/gui/image/qimageiohandler.cpp b/src/gui/image/qimageiohandler.cpp
index 5d1f8fa91f..0e7b541cf2 100644
--- a/src/gui/image/qimageiohandler.cpp
+++ b/src/gui/image/qimageiohandler.cpp
@@ -340,7 +340,7 @@ void QImageIOHandler::setDevice(QIODevice *device)
/*!
Returns the device currently assigned to the QImageIOHandler. If
- not device has been assigned, 0 is returned.
+ not device has been assigned, \nullptr is returned.
*/
QIODevice *QImageIOHandler::device() const
{
@@ -416,6 +416,7 @@ QByteArray QImageIOHandler::format() const
\sa read(), QIODevice::peek()
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -426,6 +427,7 @@ QByteArray QImageIOHandler::name() const
{
return format();
}
+#endif
/*!
Writes the image \a image to the assigned device. Returns \c true on
diff --git a/src/gui/image/qimageiohandler.h b/src/gui/image/qimageiohandler.h
index 35984dd6a5..c20b84afbb 100644
--- a/src/gui/image/qimageiohandler.h
+++ b/src/gui/image/qimageiohandler.h
@@ -69,7 +69,10 @@ public:
void setFormat(const QByteArray &format) const;
QByteArray format() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QImageIOHandler::format() instead")
virtual QByteArray name() const;
+#endif
virtual bool canRead() const = 0;
virtual bool read(QImage *image) = 0;
@@ -141,7 +144,7 @@ class Q_GUI_EXPORT QImageIOPlugin : public QObject
Q_OBJECT
public:
explicit QImageIOPlugin(QObject *parent = nullptr);
- virtual ~QImageIOPlugin();
+ ~QImageIOPlugin();
enum Capability {
CanRead = 0x1,
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 0c75196612..2762b702b2 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -526,7 +526,7 @@ bool QImageReaderPrivate::initHandler()
// Try the most probable extension first
int currentFormatIndex = extensions.indexOf(format.toLower());
if (currentFormatIndex > 0)
- extensions.swap(0, currentFormatIndex);
+ extensions.swapItemsAt(0, currentFormatIndex);
}
int currentExtension = 0;
@@ -756,13 +756,13 @@ void QImageReader::setDevice(QIODevice *device)
d->device = device;
d->deleteDevice = false;
delete d->handler;
- d->handler = 0;
+ d->handler = nullptr;
d->text.clear();
}
/*!
- Returns the device currently assigned to QImageReader, or 0 if no
- device has been assigned.
+ Returns the device currently assigned to QImageReader, or \nullptr
+ if no device has been assigned.
*/
QIODevice *QImageReader::device() const
{
@@ -1115,8 +1115,10 @@ bool QImageReader::autoTransform() const
case QImageReaderPrivate::DoNotApplyTransform:
return false;
case QImageReaderPrivate::UsePluginDefault:
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (d->initHandler())
return d->handler->supportsOption(QImageIOHandler::TransformedByDefault);
+#endif
Q_FALLTHROUGH();
default:
break;
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index d3f9a9b881..ec66588ddf 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -407,8 +407,8 @@ void QImageWriter::setDevice(QIODevice *device)
}
/*!
- Returns the device currently assigned to QImageWriter, or 0 if no
- device has been assigned.
+ Returns the device currently assigned to QImageWriter, or \nullptr
+ if no device has been assigned.
*/
QIODevice *QImageWriter::device() const
{
@@ -648,6 +648,7 @@ QImageIOHandler::Transformations QImageWriter::transformation() const
return d->transformation;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -679,6 +680,7 @@ QString QImageWriter::description() const
{
return d->description;
}
+#endif
/*!
\since 4.1
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index 29c06ccdd2..ef84a59b7c 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -100,9 +100,12 @@ public:
QImageIOHandler::Transformations transformation() const;
void setTransformation(QImageIOHandler::Transformations orientation);
- // Obsolete as of 4.1
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QImageWriter::setText() instead")
void setDescription(const QString &description);
+ QT_DEPRECATED_X("Use QImageReader::text() instead")
QString description() const;
+#endif
void setText(const QString &key, const QString &text);
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index 7d17b7d5ef..4b588527ae 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -175,11 +175,12 @@
#include "qmovie.h"
#include "qglobal.h"
+#include "qelapsedtimer.h"
#include "qimage.h"
#include "qimagereader.h"
#include "qpixmap.h"
#include "qrect.h"
-#include "qdatetime.h"
+#include "qelapsedtimer.h"
#include "qtimer.h"
#include "qpair.h"
#include "qmap.h"
@@ -437,7 +438,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
*/
bool QMoviePrivate::next()
{
- QTime time;
+ QElapsedTimer time;
time.start();
QFrameInfo info = infoForFrame(nextFrameNumber);
if (!info.isValid())
@@ -659,7 +660,7 @@ void QMovie::setDevice(QIODevice *device)
/*!
Returns the device QMovie reads image data from. If no device has
- currently been assigned, 0 is returned.
+ currently been assigned, \nullptr is returned.
\sa setDevice(), fileName()
*/
diff --git a/src/gui/image/qpaintengine_pic_p.h b/src/gui/image/qpaintengine_pic_p.h
index c3044796ad..c9e4b43197 100644
--- a/src/gui/image/qpaintengine_pic_p.h
+++ b/src/gui/image/qpaintengine_pic_p.h
@@ -103,7 +103,7 @@ protected:
QPicturePaintEngine(QPaintEnginePrivate &dptr);
private:
- Q_DISABLE_COPY(QPicturePaintEngine)
+ Q_DISABLE_COPY_MOVE(QPicturePaintEngine)
void writeCmdLength(int pos, const QRectF &r, bool corr);
};
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index 2f2f85f68d..8548f1857e 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -54,6 +54,7 @@
#include "qpainter.h"
#include "qpainterpath.h"
#include "qpixmap.h"
+#include "qregexp.h"
#include "qregion.h"
#include "qdebug.h"
@@ -234,7 +235,7 @@ void QPicture::detach()
bool QPicture::isDetached() const
{
- return d_func()->ref.load() == 1;
+ return d_func()->ref.loadRelaxed() == 1;
}
/*!
@@ -858,7 +859,7 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
break;
case QPicturePrivate::PdcSetWXform:
s >> i_8;
- painter->setMatrixEnabled(i_8);
+ painter->setWorldMatrixEnabled(i_8);
break;
case QPicturePrivate::PdcSetWMatrix:
if (d->formatMajor >= 8) {
@@ -1200,8 +1201,8 @@ QT_END_INCLUDE_NAMESPACE
\obsolete
Returns a string that specifies the picture format of the file \a
- fileName, or 0 if the file cannot be read or if the format is not
- recognized.
+ fileName, or \nullptr if the file cannot be read or if the format
+ is not recognized.
\sa load(), save()
*/
@@ -1485,8 +1486,8 @@ static QPictureHandler *get_picture_handler(const char *format)
\a format is used to select a handler to write a QPicture; \a header
is used to select a handler to read an picture file.
- If \a readPicture is a null pointer, the QPictureIO will not be able
- to read pictures in \a format. If \a writePicture is a null pointer,
+ If \a readPicture is \nullptr, the QPictureIO will not be able
+ to read pictures in \a format. If \a writePicture is \nullptr,
the QPictureIO will not be able to write pictures in \a format. If
both are null, the QPictureIO object is valid but useless.
@@ -1543,7 +1544,7 @@ const QPicture &QPictureIO::picture() const { return d->pi; }
int QPictureIO::status() const { return d->iostat; }
/*!
- Returns the picture format string or 0 if no format has been
+ Returns the picture format string or \nullptr if no format has been
explicitly set.
*/
const char *QPictureIO::format() const { return d->frmt; }
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index ec7b4bd7e3..189e57b9a3 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -78,11 +78,9 @@ public:
void setBoundingRect(const QRect &r);
QPicture& operator=(const QPicture &p);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QPicture &operator=(QPicture &&other) Q_DECL_NOEXCEPT
+ inline QPicture &operator=(QPicture &&other) noexcept
{ qSwap(d_ptr, other.d_ptr); return *this; }
-#endif
- inline void swap(QPicture &other) Q_DECL_NOEXCEPT
+ inline void swap(QPicture &other) noexcept
{ d_ptr.swap(other.d_ptr); }
void detach();
bool isDetached() const;
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 7e862e9826..b6e41f16a5 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -262,7 +262,7 @@ QPixmap::QPixmap(const char * const xpm[])
QPixmap::~QPixmap()
{
- Q_ASSERT(!data || data->ref.load() >= 1); // Catch if ref-counting changes again
+ Q_ASSERT(!data || data->ref.loadRelaxed() >= 1); // Catch if ref-counting changes again
}
/*!
@@ -858,6 +858,7 @@ bool QPixmap::doImageIO(QImageWriter *writer, int quality) const
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -878,6 +879,14 @@ void QPixmap::fill(const QPaintDevice *device, const QPoint &p)
Use QPainter or the fill(QColor) overload instead.
*/
+void QPixmap::fill(const QPaintDevice *device, int xofs, int yofs)
+{
+ Q_UNUSED(device)
+ Q_UNUSED(xofs)
+ Q_UNUSED(yofs)
+ qWarning("this function is deprecated, ignored");
+}
+#endif
/*!
@@ -901,7 +910,7 @@ void QPixmap::fill(const QColor &color)
return;
}
- if (data->ref.load() == 1) {
+ if (data->ref.loadRelaxed() == 1) {
// detach() will also remove this pixmap from caches, so
// it has to be called even when ref == 1.
detach();
@@ -961,6 +970,7 @@ static void sendResizeEvents(QWidget *target)
}
#endif
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -984,6 +994,14 @@ QPixmap QPixmap::grabWidget(QObject *widget, const QRect &rectangle)
Use QWidget::grab() instead.
*/
+QPixmap QPixmap::grabWidget(QObject *widget, int x, int y, int w, int h)
+{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+ return grabWidget(widget, QRect(x, y, w, h));
+QT_WARNING_POP
+}
+#endif
/*****************************************************************************
QPixmap stream functions
@@ -1035,7 +1053,7 @@ QDataStream &operator>>(QDataStream &stream, QPixmap &pixmap)
bool QPixmap::isDetached() const
{
- return data && data->ref.load() == 1;
+ return data && data->ref.loadRelaxed() == 1;
}
/*!
@@ -1358,12 +1376,6 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
The cacheKey() function returns a number that uniquely
identifies the contents of the QPixmap object.
- The x11Info() function returns information about the configuration
- of the X display used by the screen to which the pixmap currently
- belongs. The x11PictureHandle() function returns the X11 Picture
- handle of the pixmap for XRender support. Note that the two latter
- functions are only available on x11.
-
\endtable
\section1 Pixmap Conversion
@@ -1394,9 +1406,6 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
function returns the actual matrix used for transforming the
pixmap.
- \note When using the native X11 graphics system, the pixmap
- becomes invalid when the QApplication instance is destroyed.
-
\sa QBitmap, QImage, QImageReader, QImageWriter
*/
@@ -1514,10 +1523,10 @@ void QPixmap::detach()
rasterData->image.detach();
}
- if (data->is_cached && data->ref.load() == 1)
+ if (data->is_cached && data->ref.loadRelaxed() == 1)
QImagePixmapCleanupHooks::executePlatformPixmapModificationHooks(data.data());
- if (data->ref.load() != 1) {
+ if (data->ref.loadRelaxed() != 1) {
*this = copy();
}
++data->detach_no;
@@ -1604,6 +1613,7 @@ QPixmap QPixmap::fromImageReader(QImageReader *imageReader, Qt::ImageConversionF
return QPixmap(data.take());
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\fn QPixmap QPixmap::grabWindow(WId window, int x, int y, int
width, int height)
@@ -1657,6 +1667,7 @@ QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
" Defaulting to primary screen.");
return QGuiApplication::primaryScreen()->grabWindow(window, x, y, w, h);
}
+#endif
/*!
\internal
@@ -1678,7 +1689,7 @@ QDebug operator<<(QDebug dbg, const QPixmap &r)
} else {
dbg << r.size() << ",depth=" << r.depth()
<< ",devicePixelRatio=" << r.devicePixelRatio()
- << ",cacheKey=" << showbase << hex << r.cacheKey() << dec << noshowbase;
+ << ",cacheKey=" << Qt::showbase << Qt::hex << r.cacheKey() << Qt::dec << Qt::noshowbase;
}
dbg << ')';
return dbg;
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 55cca7a766..8c1395857e 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -73,11 +73,9 @@ public:
~QPixmap();
QPixmap &operator=(const QPixmap &);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QPixmap &operator=(QPixmap &&other) Q_DECL_NOEXCEPT
+ inline QPixmap &operator=(QPixmap &&other) noexcept
{ qSwap(data, other.data); return *this; }
-#endif
- inline void swap(QPixmap &other) Q_DECL_NOEXCEPT
+ inline void swap(QPixmap &other) noexcept
{ qSwap(data, other.data); }
operator QVariant() const;
@@ -94,8 +92,12 @@ public:
static int defaultDepth();
void fill(const QColor &fillColor = Qt::white);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QPainter or fill(QColor)")
void fill(const QPaintDevice *device, const QPoint &ofs);
- inline void fill(const QPaintDevice *device, int xofs, int yofs) { fill(device, QPoint(xofs, yofs)); }
+ QT_DEPRECATED_X("Use QPainter or fill(QColor)")
+ void fill(const QPaintDevice *device, int xofs, int yofs);
+#endif
QBitmap mask() const;
void setMask(const QBitmap &);
@@ -111,10 +113,14 @@ public:
#endif
QBitmap createMaskFromColor(const QColor &maskColor, Qt::MaskMode mode = Qt::MaskInColor) const;
- static QPixmap grabWindow(WId, int x=0, int y=0, int w=-1, int h=-1);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QScreen::grabWindow() instead")
+ static QPixmap grabWindow(WId, int x = 0, int y = 0, int w = -1, int h = -1);
+ QT_DEPRECATED_X("Use QWidget::grab() instead")
static QPixmap grabWidget(QObject *widget, const QRect &rect);
- static inline QPixmap grabWidget(QObject *widget, int x=0, int y=0, int w=-1, int h=-1)
- { return grabWidget(widget, QRect(x, y, w, h)); }
+ QT_DEPRECATED_X("Use QWidget::grab() instead")
+ static QPixmap grabWidget(QObject *widget, int x = 0, int y = 0, int w = -1, int h = -1);
+#endif
inline QPixmap scaled(int w, int h, Qt::AspectRatioMode aspectMode = Qt::IgnoreAspectRatio,
Qt::TransformationMode mode = Qt::FastTransformation) const
@@ -131,12 +137,10 @@ public:
QImage toImage() const;
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);
static QPixmap fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags = Qt::AutoColor);
-#ifdef Q_COMPILER_RVALUE_REFS
static QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags = Qt::AutoColor)
{
return fromImageInPlace(image, flags);
}
-#endif
bool load(const QString& fileName, const char *format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor);
bool loadFromData(const uchar *buf, uint len, const char* format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor);
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 13c1c29d5b..2732bbd197 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -203,6 +203,9 @@ void QRasterPlatformPixmap::fill(const QColor &color)
pixel = qAlpha(color.rgba());
} else if (image.format() == QImage::Format_Grayscale8) {
pixel = qGray(color.rgba());
+ } else if (image.format() == QImage::Format_Grayscale16) {
+ QRgba64 c = color.rgba64();
+ pixel = qGray(c.red(), c.green(), c.blue());
} else
{
pixel = 0;
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index b5f8d43041..3a2db74098 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -210,7 +210,7 @@ static QImage copyImageData(const BITMAPINFOHEADER &header, const RGBQUAD *color
class DisplayHdc
{
- Q_DISABLE_COPY(DisplayHdc)
+ Q_DISABLE_COPY_MOVE(DisplayHdc)
public:
DisplayHdc() : m_displayDc(GetDC(nullptr)) {}
~DisplayHdc() { ReleaseDC(nullptr, m_displayDc); }
diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index 3d1652f68b..a41ec8f35c 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -176,7 +176,7 @@ bool QPixmapCache::Key::operator ==(const Key &key) const
Otherwise, if pixmap was flushed, the key is no longer valid.
\since 5.7
*/
-bool QPixmapCache::Key::isValid() const Q_DECL_NOTHROW
+bool QPixmapCache::Key::isValid() const noexcept
{
return d && d->isValid;
}
@@ -469,10 +469,13 @@ QPixmapCacheEntry::~QPixmapCacheEntry()
pm_cache()->releaseKey(key);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
\overload
+ Use bool find(const QString &, QPixmap *) instead.
+
Returns the pixmap associated with the \a key in the cache, or
null if there is no such pixmap.
@@ -494,13 +497,14 @@ QPixmap *QPixmapCache::find(const QString &key)
/*!
\obsolete
- Use bool find(const QString&, QPixmap*) instead.
+ Use bool find(const QString &, QPixmap *) instead.
*/
-bool QPixmapCache::find(const QString &key, QPixmap& pixmap)
+bool QPixmapCache::find(const QString &key, QPixmap &pixmap)
{
return find(key, &pixmap);
}
+#endif
/*!
Looks for a cached pixmap associated with the given \a key in the cache.
@@ -513,7 +517,7 @@ bool QPixmapCache::find(const QString &key, QPixmap& pixmap)
\snippet code/src_gui_image_qpixmapcache.cpp 1
*/
-bool QPixmapCache::find(const QString &key, QPixmap* pixmap)
+bool QPixmapCache::find(const QString &key, QPixmap *pixmap)
{
QPixmap *ptr = pm_cache()->object(key);
if (ptr && pixmap)
@@ -530,7 +534,7 @@ bool QPixmapCache::find(const QString &key, QPixmap* pixmap)
\since 4.6
*/
-bool QPixmapCache::find(const Key &key, QPixmap* pixmap)
+bool QPixmapCache::find(const Key &key, QPixmap *pixmap)
{
//The key is not valid anymore, a flush happened before probably
if (!key.d || !key.d->isValid)
diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h
index ea10ab1b76..55af35a5d9 100644
--- a/src/gui/image/qpixmapcache.h
+++ b/src/gui/image/qpixmapcache.h
@@ -55,18 +55,16 @@ public:
public:
Key();
Key(const Key &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- Key(Key &&other) Q_DECL_NOTHROW : d(other.d) { other.d = nullptr; }
- Key &operator =(Key &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ Key(Key &&other) noexcept : d(other.d) { other.d = nullptr; }
+ Key &operator =(Key &&other) noexcept { swap(other); return *this; }
~Key();
bool operator ==(const Key &key) const;
inline bool operator !=(const Key &key) const
{ return !operator==(key); }
Key &operator =(const Key &other);
- void swap(Key &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
- bool isValid() const Q_DECL_NOTHROW;
+ void swap(Key &other) noexcept { qSwap(d, other.d); }
+ bool isValid() const noexcept;
private:
KeyData *d;
@@ -76,8 +74,12 @@ public:
static int cacheLimit();
static void setCacheLimit(int);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use bool find(const QString &, QPixmap *) instead")
static QPixmap *find(const QString &key);
+ QT_DEPRECATED_X("Use bool find(const QString &, QPixmap *) instead")
static bool find(const QString &key, QPixmap &pixmap);
+#endif
static bool find(const QString &key, QPixmap *pixmap);
static bool find(const Key &key, QPixmap *pixmap);
static bool insert(const QString &key, const QPixmap &pixmap);
diff --git a/src/gui/image/qpixmapcache_p.h b/src/gui/image/qpixmapcache_p.h
index 3c57367514..ab8e2b7558 100644
--- a/src/gui/image/qpixmapcache_p.h
+++ b/src/gui/image/qpixmapcache_p.h
@@ -87,7 +87,7 @@ public:
&& !d->image.d->paintEngine->isActive())
{
delete d->image.d->paintEngine;
- d->image.d->paintEngine = 0;
+ d->image.d->paintEngine = nullptr;
}
}
}
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 801b30881d..39d0807606 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -42,6 +42,7 @@
#ifndef QT_NO_IMAGEFORMAT_PNG
#include <qcoreapplication.h>
+#include <qdebug.h>
#include <qiodevice.h>
#include <qimage.h>
#include <qlist.h>
@@ -50,6 +51,10 @@
#include <private/qimage_p.h> // for qt_getImageText
+#include <qcolorspace.h>
+#include <private/qcolorspace_p.h>
+#include <private/qicc_p.h>
+
#include <png.h>
#include <pngconf.h>
@@ -96,9 +101,16 @@ public:
ReadingEnd,
Error
};
+ // Defines the order of how the various ways of setting colorspace overrides eachother:
+ enum ColorSpaceState {
+ Undefined = 0,
+ GammaChrm = 1, // gAMA+cHRM chunks
+ Srgb = 2, // sRGB chunk
+ Icc = 3 // iCCP chunk
+ };
QPngHandlerPrivate(QPngHandler *qq)
- : gamma(0.0), fileGamma(0.0), quality(50), compression(50), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq)
+ : gamma(0.0), fileGamma(0.0), quality(50), compression(50), colorSpaceState(Undefined), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq)
{ }
float gamma;
@@ -108,6 +120,8 @@ public:
QString description;
QSize scaledSize;
QStringList readTexts;
+ QColorSpace colorSpace;
+ ColorSpaceState colorSpaceState;
png_struct *png_ptr;
png_info *info_ptr;
@@ -226,11 +240,8 @@ void qpiw_flush_fn(png_structp /* png_ptr */)
}
static
-void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead, float screen_gamma=0.0, float file_gamma=0.0)
+void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead)
{
- if (screen_gamma != 0.0 && file_gamma != 0.0)
- png_set_gamma(png_ptr, 1.0f / screen_gamma, file_gamma);
-
png_uint_32 width = 0;
png_uint_32 height = 0;
int bit_depth = 0;
@@ -266,6 +277,18 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
else if (g == 1)
image.setColor(0, qRgba(255, 255, 255, 0));
}
+ } else if (bit_depth == 16
+ && png_get_channels(png_ptr, info_ptr) == 1
+ && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ if (image.size() != QSize(width, height) || image.format() != QImage::Format_Grayscale16) {
+ image = QImage(width, height, QImage::Format_Grayscale16);
+ if (image.isNull())
+ return;
+ }
+
+ png_read_update_info(png_ptr, info_ptr);
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
+ png_set_swap(png_ptr);
} else if (bit_depth == 16) {
bool hasMask = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
if (!hasMask)
@@ -573,10 +596,45 @@ bool QPngHandlerPrivate::readPngHeader()
readPngTexts(info_ptr);
+#ifdef PNG_iCCP_SUPPORTED
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) {
+ png_charp name = nullptr;
+ int compressionType = 0;
+#if (PNG_LIBPNG_VER < 10500)
+ png_charp profileData = nullptr;
+#else
+ png_bytep profileData = nullptr;
+#endif
+ png_uint_32 profLen;
+ png_get_iCCP(png_ptr, info_ptr, &name, &compressionType, &profileData, &profLen);
+ if (!QIcc::fromIccProfile(QByteArray::fromRawData((const char *)profileData, profLen), &colorSpace)) {
+ qWarning() << "QPngHandler: Failed to parse ICC profile";
+ } else {
+ colorSpaceState = Icc;
+ }
+ }
+#endif
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) {
+ int rendering_intent = -1;
+ png_get_sRGB(png_ptr, info_ptr, &rendering_intent);
+ // We don't actually care about the rendering_intent, just that it is valid
+ if (rendering_intent >= 0 && rendering_intent <= 3 && colorSpaceState <= Srgb) {
+ colorSpace = QColorSpace::SRgb;
+ colorSpaceState = Srgb;
+ }
+ }
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) {
double file_gamma = 0.0;
png_get_gAMA(png_ptr, info_ptr, &file_gamma);
fileGamma = file_gamma;
+ if (fileGamma > 0.0f && colorSpaceState <= GammaChrm) {
+ QColorSpacePrivate *csPrivate = colorSpace.d_func();
+ csPrivate->gamut = QColorSpace::Gamut::SRgb;
+ csPrivate->transferFunction = QColorSpace::TransferFunction::Gamma;
+ csPrivate->gamma = fileGamma;
+ csPrivate->initialize();
+ colorSpaceState = GammaChrm;
+ }
}
state = ReadHeader;
@@ -601,8 +659,19 @@ bool QPngHandlerPrivate::readPngImage(QImage *outImage)
return false;
}
+ if (gamma != 0.0 && fileGamma != 0.0) {
+ // This configuration forces gamma correction and
+ // thus changes the output colorspace
+ png_set_gamma(png_ptr, 1.0f / gamma, fileGamma);
+ QColorSpacePrivate *csPrivate = colorSpace.d_func();
+ csPrivate->transferFunction = QColorSpace::TransferFunction::Gamma;
+ csPrivate->gamma = gamma;
+ csPrivate->initialize();
+ colorSpaceState = GammaChrm;
+ }
+
bool doScaledRead = false;
- setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma, fileGamma);
+ setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead);
if (outImage->isNull()) {
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
@@ -671,6 +740,9 @@ bool QPngHandlerPrivate::readPngImage(QImage *outImage)
if (scaledSize.isValid() && outImage->size() != scaledSize)
*outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ if (colorSpaceState > Undefined && colorSpace.isValid())
+ outImage->setColorSpace(colorSpace);
+
return true;
}
@@ -687,7 +759,7 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
format = QImage::Format_Mono;
} else if (bit_depth == 16) {
- format = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? QImage::Format_RGBA64 : QImage::Format_RGBX64;
+ format = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? QImage::Format_RGBA64 : QImage::Format_Grayscale16;
} else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
format = QImage::Format_Grayscale8;
} else {
@@ -861,7 +933,8 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i
else
color_type = PNG_COLOR_TYPE_PALETTE;
}
- else if (image.format() == QImage::Format_Grayscale8)
+ else if (image.format() == QImage::Format_Grayscale8
+ || image.format() == QImage::Format_Grayscale16)
color_type = PNG_COLOR_TYPE_GRAY;
else if (image.hasAlphaChannel())
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
@@ -877,6 +950,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i
case QImage::Format_RGBX64:
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_Grayscale16:
bpc = 16;
break;
default:
@@ -988,6 +1062,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i
case QImage::Format_RGBX64:
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_Grayscale16:
png_set_swap(png_ptr);
break;
default:
@@ -1018,6 +1093,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i
case QImage::Format_MonoLSB:
case QImage::Format_Indexed8:
case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
case QImage::Format_RGB32:
case QImage::Format_ARGB32:
case QImage::Format_RGB888:
@@ -1181,10 +1257,12 @@ void QPngHandler::setOption(ImageOption option, const QVariant &value)
d->scaledSize = value.toSize();
}
+#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QPngHandler::name() const
{
return "png";
}
+#endif
QT_END_NAMESPACE
diff --git a/src/gui/image/qpnghandler_p.h b/src/gui/image/qpnghandler_p.h
index 4ca716e7c2..5d4da97395 100644
--- a/src/gui/image/qpnghandler_p.h
+++ b/src/gui/image/qpnghandler_p.h
@@ -69,7 +69,9 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
+#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
+#endif
QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override;
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index 53e3fa293d..13ee2eadd2 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -68,13 +68,19 @@ static int read_pbm_int(QIODevice *d)
char c;
int val = -1;
bool digit;
+ bool hasOverflow = false;
for (;;) {
if (!d->getChar(&c)) // end of file
break;
digit = isdigit((uchar) c);
if (val != -1) {
if (digit) {
- val = 10*val + c - '0';
+ const int cValue = c - '0';
+ if (val <= (INT_MAX - cValue) / 10) {
+ val = 10*val + cValue;
+ } else {
+ hasOverflow = true;
+ }
continue;
} else {
if (c == '#') // comment
@@ -91,7 +97,7 @@ static int read_pbm_int(QIODevice *d)
else
break;
}
- return val;
+ return hasOverflow ? -1 : val;
}
static bool read_pbm_header(QIODevice *device, char& type, int& w, int& h, int& mcc)
@@ -123,7 +129,7 @@ static bool read_pbm_header(QIODevice *device, char& type, int& w, int& h, int&
static inline QRgb scale_pbm_color(quint16 mx, quint16 rv, quint16 gv, quint16 bv)
{
- return QRgba64::fromRgba64((rv * 0xffff) / mx, (gv * 0xffff) / mx, (bv * 0xffff) / mx, 0xffff).toArgb32();
+ return QRgba64::fromRgba64((rv * 0xffffu) / mx, (gv * 0xffffu) / mx, (bv * 0xffffu) / mx, 0xffff).toArgb32();
}
static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, QImage *outImage)
@@ -252,7 +258,7 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
}
} else {
while (n--) {
- *p++ = read_pbm_int(device) * 255 / mcc;
+ *p++ = (read_pbm_int(device) & 0xffff) * 255 / mcc;
}
}
} else { // 32 bits
@@ -570,10 +576,12 @@ void QPpmHandler::setOption(ImageOption option, const QVariant &value)
subType = value.toByteArray().toLower();
}
+#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QPpmHandler::name() const
{
return subType.isEmpty() ? QByteArray("ppm") : subType;
}
+#endif
QT_END_NAMESPACE
diff --git a/src/gui/image/qppmhandler_p.h b/src/gui/image/qppmhandler_p.h
index 1c6fbd6869..2f3811b759 100644
--- a/src/gui/image/qppmhandler_p.h
+++ b/src/gui/image/qppmhandler_p.h
@@ -67,9 +67,11 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
+#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
+#endif
- static bool canRead(QIODevice *device, QByteArray *subType = 0);
+ static bool canRead(QIODevice *device, QByteArray *subType = nullptr);
QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override;
diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp
index 7ba44049b4..3cd15b3e4d 100644
--- a/src/gui/image/qxbmhandler.cpp
+++ b/src/gui/image/qxbmhandler.cpp
@@ -44,6 +44,7 @@
#include <qimage.h>
#include <qiodevice.h>
+#include <qregexp.h>
#include <qvariant.h>
#include <stdio.h>
@@ -356,10 +357,12 @@ void QXbmHandler::setOption(ImageOption option, const QVariant &value)
fileName = value.toString();
}
+#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QXbmHandler::name() const
{
return "xbm";
}
+#endif
QT_END_NAMESPACE
diff --git a/src/gui/image/qxbmhandler_p.h b/src/gui/image/qxbmhandler_p.h
index 26439af527..ae590a1944 100644
--- a/src/gui/image/qxbmhandler_p.h
+++ b/src/gui/image/qxbmhandler_p.h
@@ -66,7 +66,9 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
+#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
+#endif
static bool canRead(QIODevice *device);
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index 17272ffe69..deff56aa58 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -45,6 +45,7 @@
#include <qbytearraymatcher.h>
#include <qimage.h>
#include <qmap.h>
+#include <qregexp.h>
#include <qtextstream.h>
#include <qvariant.h>
@@ -1128,8 +1129,8 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
// write header
QTextStream s(device);
- s << "/* XPM */" << endl
- << "static char *" << fbname(fileName) << "[]={" << endl
+ s << "/* XPM */" << Qt::endl
+ << "static char *" << fbname(fileName) << "[]={" << Qt::endl
<< '\"' << w << ' ' << h << ' ' << ncolors << ' ' << cpp << '\"';
// write palette
@@ -1146,7 +1147,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
qGreen(color),
qBlue(color));
++c;
- s << ',' << endl << line;
+ s << ',' << Qt::endl << line;
}
// write pixels, limit to 4 characters per pixel
@@ -1168,9 +1169,9 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
}
}
}
- s << ',' << endl << '\"' << line << '\"';
+ s << ',' << Qt::endl << '\"' << line << '\"';
}
- s << "};" << endl;
+ s << "};" << Qt::endl;
return (s.status() == QTextStream::Ok);
}
@@ -1287,10 +1288,12 @@ void QXpmHandler::setOption(ImageOption option, const QVariant &value)
fileName = value.toString();
}
+#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QXpmHandler::name() const
{
return "xpm";
}
+#endif
QT_END_NAMESPACE
diff --git a/src/gui/image/qxpmhandler_p.h b/src/gui/image/qxpmhandler_p.h
index f118bf2309..a4dd88cd17 100644
--- a/src/gui/image/qxpmhandler_p.h
+++ b/src/gui/image/qxpmhandler_p.h
@@ -68,7 +68,9 @@ public:
static bool canRead(QIODevice *device);
+#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
+#endif
QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override;
diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp
index 7afad95bd9..2390c62b9f 100644
--- a/src/gui/itemmodels/qstandarditemmodel.cpp
+++ b/src/gui/itemmodels/qstandarditemmodel.cpp
@@ -1846,7 +1846,7 @@ bool QStandardItem::hasChildren() const
item) takes ownership of \a item. If necessary, the row count and column
count are increased to fit the item.
- \note Passing a null pointer as \a item removes the item.
+ \note Passing \nullptr as \a item removes the item.
\sa child()
*/
@@ -1905,7 +1905,7 @@ QStandardItem *QStandardItem::takeChild(int row, int column)
/*!
Removes \a row without deleting the row items, and returns a list of
pointers to the removed items. For items in the row that have not been
- set, the corresponding pointers in the list will be 0.
+ set, the corresponding pointers in the list will be \nullptr.
\sa removeRow(), insertRow(), takeColumn()
*/
@@ -1939,7 +1939,7 @@ QList<QStandardItem*> QStandardItem::takeRow(int row)
/*!
Removes \a column without deleting the column items, and returns a list of
pointers to the removed items. For items in the column that have not been
- set, the corresponding pointers in the list will be 0.
+ set, the corresponding pointers in the list will be \nullptr.
\sa removeColumn(), insertColumn(), takeRow()
*/
@@ -2718,7 +2718,7 @@ QStandardItem *QStandardItemModel::takeItem(int row, int column)
Removes the given \a row without deleting the row items, and returns a
list of pointers to the removed items. The model releases ownership of the
items. For items in the row that have not been set, the corresponding
- pointers in the list will be 0.
+ pointers in the list will be \nullptr.
\sa takeColumn()
*/
@@ -2734,7 +2734,7 @@ QList<QStandardItem*> QStandardItemModel::takeRow(int row)
Removes the given \a column without deleting the column items, and returns
a list of pointers to the removed items. The model releases ownership of
the items. For items in the column that have not been set, the
- corresponding pointers in the list will be 0.
+ corresponding pointers in the list will be \nullptr.
\sa takeRow()
*/
@@ -3010,6 +3010,11 @@ bool QStandardItemModel::setData(const QModelIndex &index, const QVariant &value
return true;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \reimp
+ */
+#else
/*!
\since 5.12
Removes the data stored in all the roles for the given \a index.
@@ -3018,6 +3023,7 @@ bool QStandardItemModel::setData(const QModelIndex &index, const QVariant &value
\sa setData(), data()
*/
+#endif
bool QStandardItemModel::clearItemData(const QModelIndex &index)
{
if (!checkIndex(index, CheckIndexOption::IndexIsValid))
diff --git a/src/gui/itemmodels/qstandarditemmodel_p.h b/src/gui/itemmodels/qstandarditemmodel_p.h
index 00e83f7b08..97c2e6f01b 100644
--- a/src/gui/itemmodels/qstandarditemmodel_p.h
+++ b/src/gui/itemmodels/qstandarditemmodel_p.h
@@ -109,11 +109,11 @@ class QStandardItemPrivate
Q_DECLARE_PUBLIC(QStandardItem)
public:
inline QStandardItemPrivate()
- : model(0),
- parent(0),
+ : model(nullptr),
+ parent(nullptr),
rows(0),
columns(0),
- q_ptr(0),
+ q_ptr(nullptr),
lastKnownIndex(-1)
{ }
@@ -207,7 +207,7 @@ class QStandardItemModelPrivate : public QAbstractItemModelPrivate
public:
QStandardItemModelPrivate();
- virtual ~QStandardItemModelPrivate();
+ ~QStandardItemModelPrivate();
void init();
@@ -220,10 +220,10 @@ public:
if (!index.isValid())
return root.data();
if (index.model() != q)
- return 0;
+ return nullptr;
QStandardItem *parent = static_cast<QStandardItem*>(index.internalPointer());
- if (parent == 0)
- return 0;
+ if (parent == nullptr)
+ return nullptr;
return parent->child(index.row(), index.column());
}
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 1f137fc46f..9c80f1e2cc 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -21,7 +21,7 @@ HEADERS += \
kernel/qplatforminputcontextplugin_p.h \
kernel/qplatformintegrationfactory_p.h \
kernel/qplatformintegrationplugin.h \
- kernel/qplatformtheme.h\
+ kernel/qplatformtheme.h \
kernel/qplatformtheme_p.h \
kernel/qplatformthemefactory_p.h \
kernel/qplatformthemeplugin.h \
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index a76150d91d..267c079ad9 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -439,7 +439,7 @@ void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode)
\fn QMimeData *QClipboard::mimeData(Mode mode) const
Returns a pointer to a QMimeData representation of the current
- clipboard data (can be NULL if the given \a mode is not
+ clipboard data (can be \nullptr if the given \a mode is not
supported by the platform).
The \a mode argument is used to control which part of the system
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index bb81ca109a..1ba8760a9d 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -494,7 +494,7 @@ QCursor::QCursor(Qt::CursorShape shape)
\sa operator!=(const QCursor &lhs, const QCursor &rhs)
*/
-bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW
+bool operator==(const QCursor &lhs, const QCursor &rhs) noexcept
{
if (lhs.d == rhs.d)
return true; // Copy or same shape
@@ -564,8 +564,8 @@ void QCursor::setShape(Qt::CursorShape shape)
}
/*!
- Returns the cursor bitmap, or 0 if it is one of the standard
- cursors.
+ Returns the cursor bitmap, or \nullptr if it is one of the
+ standard cursors.
*/
const QBitmap *QCursor::bitmap() const
{
@@ -575,8 +575,8 @@ const QBitmap *QCursor::bitmap() const
}
/*!
- Returns the cursor bitmap mask, or 0 if it is one of the standard
- cursors.
+ Returns the cursor bitmap mask, or \nullptr if it is one of the
+ standard cursors.
*/
const QBitmap *QCursor::mask() const
diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h
index d62ee7a053..7966e35840 100644
--- a/src/gui/kernel/qcursor.h
+++ b/src/gui/kernel/qcursor.h
@@ -86,13 +86,11 @@ public:
QCursor(const QCursor &cursor);
~QCursor();
QCursor &operator=(const QCursor &cursor);
-#ifdef Q_COMPILER_RVALUE_REFS
- QCursor(QCursor &&other) Q_DECL_NOTHROW : d(other.d) { other.d = nullptr; }
- inline QCursor &operator=(QCursor &&other) Q_DECL_NOTHROW
+ QCursor(QCursor &&other) noexcept : d(other.d) { other.d = nullptr; }
+ inline QCursor &operator=(QCursor &&other) noexcept
{ swap(other); return *this; }
-#endif
- void swap(QCursor &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QCursor &other) noexcept { qSwap(d, other.d); }
operator QVariant() const;
@@ -112,13 +110,13 @@ public:
inline static void setPos(QScreen *screen, const QPoint &p) { setPos(screen, p.x(), p.y()); }
private:
- friend Q_GUI_EXPORT bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW;
+ friend Q_GUI_EXPORT bool operator==(const QCursor &lhs, const QCursor &rhs) noexcept;
QCursorData *d;
};
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QCursor)
-Q_GUI_EXPORT bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW;
-inline bool operator!=(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
+Q_GUI_EXPORT bool operator==(const QCursor &lhs, const QCursor &rhs) noexcept;
+inline bool operator!=(const QCursor &lhs, const QCursor &rhs) noexcept { return !(lhs == rhs); }
/*****************************************************************************
QCursor stream functions
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index 5f6db07987..b1219c8658 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -73,9 +73,9 @@ class QDragPrivate : public QObjectPrivate
{
public:
QDragPrivate()
- : source(0)
- , target(0)
- , data(0)
+ : source(nullptr)
+ , target(nullptr)
+ , data(nullptr)
{ }
QObject *source;
QObject *target;
@@ -110,7 +110,7 @@ private:
QDrag *m_object;
static QDragManager *m_instance;
- Q_DISABLE_COPY(QDragManager)
+ Q_DISABLE_COPY_MOVE(QDragManager)
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdrag.cpp b/src/gui/kernel/qdrag.cpp
index bb0e490aa0..dcd0d13d5c 100644
--- a/src/gui/kernel/qdrag.cpp
+++ b/src/gui/kernel/qdrag.cpp
@@ -284,6 +284,7 @@ Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defa
return d->executed_action;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -311,6 +312,7 @@ Qt::DropAction QDrag::start(Qt::DropActions request)
d->executed_action = QDragManager::self()->drag(this);
return d->executed_action;
}
+#endif
/*!
Sets the drag \a cursor for the \a action. This allows you
diff --git a/src/gui/kernel/qdrag.h b/src/gui/kernel/qdrag.h
index 27b9c2c88f..7acd5088bd 100644
--- a/src/gui/kernel/qdrag.h
+++ b/src/gui/kernel/qdrag.h
@@ -74,7 +74,10 @@ public:
QObject *source() const;
QObject *target() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QDrag::exec() instead")
Qt::DropAction start(Qt::DropActions supportedActions = Qt::CopyAction);
+#endif
Qt::DropAction exec(Qt::DropActions supportedActions = Qt::MoveAction);
Qt::DropAction exec(Qt::DropActions supportedActions, Qt::DropAction defaultAction);
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index e7a320f3a4..e1d685b1b0 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3764,13 +3764,13 @@ static inline void formatTouchEvent(QDebug d, const QTouchEvent &t)
static void formatUnicodeString(QDebug d, const QString &s)
{
- d << '"' << hex;
+ d << '"' << Qt::hex;
for (int i = 0; i < s.size(); ++i) {
if (i)
d << ',';
d << "U+" << s.at(i).unicode();
}
- d << dec << '"';
+ d << Qt::dec << '"';
}
static inline void formatInputMethodEvent(QDebug d, const QInputMethodEvent *e)
@@ -3807,8 +3807,8 @@ static inline void formatInputMethodQueryEvent(QDebug d, const QInputMethodQuery
QDebugStateSaver saver(d);
d.noquote();
const Qt::InputMethodQueries queries = e->queries();
- d << "QInputMethodQueryEvent(queries=" << showbase << hex << int(queries)
- << noshowbase << dec << ", {";
+ d << "QInputMethodQueryEvent(queries=" << Qt::showbase << Qt::hex << int(queries)
+ << Qt::noshowbase << Qt::dec << ", {";
for (unsigned mask = 1; mask <= Qt::ImInputItemClipRectangle; mask<<=1) {
if (queries & mask) {
const Qt::InputMethodQuery query = static_cast<Qt::InputMethodQuery>(mask);
@@ -4001,7 +4001,7 @@ QDebug operator<<(QDebug dbg, const QTouchEvent::TouchPoint &tp)
{
QDebugStateSaver saver(dbg);
dbg.nospace();
- dbg << "TouchPoint(" << hex << tp.id() << dec << " (";
+ dbg << "TouchPoint(" << Qt::hex << tp.id() << Qt::dec << " (";
QtDebugUtils::formatQPoint(dbg, tp.pos());
dbg << ") ";
QtDebugUtils::formatQEnum(dbg, tp.state());
@@ -4921,7 +4921,7 @@ QVector<QPointF> QTouchEvent::TouchPoint::rawScreenPositions() const
/*! \internal */
void QTouchEvent::TouchPoint::setId(int id)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->id = id;
}
@@ -4929,7 +4929,7 @@ void QTouchEvent::TouchPoint::setId(int id)
/*! \internal */
void QTouchEvent::TouchPoint::setUniqueId(qint64 uid)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->uniqueId = QPointingDeviceUniqueId::fromNumericId(uid);
}
@@ -4937,7 +4937,7 @@ void QTouchEvent::TouchPoint::setUniqueId(qint64 uid)
/*! \internal */
void QTouchEvent::TouchPoint::setState(Qt::TouchPointStates state)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->state = state;
}
@@ -4945,7 +4945,7 @@ void QTouchEvent::TouchPoint::setState(Qt::TouchPointStates state)
/*! \internal */
void QTouchEvent::TouchPoint::setPos(const QPointF &pos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->pos = pos;
}
@@ -4953,7 +4953,7 @@ void QTouchEvent::TouchPoint::setPos(const QPointF &pos)
/*! \internal */
void QTouchEvent::TouchPoint::setScenePos(const QPointF &scenePos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->scenePos = scenePos;
}
@@ -4961,7 +4961,7 @@ void QTouchEvent::TouchPoint::setScenePos(const QPointF &scenePos)
/*! \internal */
void QTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->screenPos = screenPos;
}
@@ -4969,7 +4969,7 @@ void QTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos)
/*! \internal */
void QTouchEvent::TouchPoint::setNormalizedPos(const QPointF &normalizedPos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->normalizedPos = normalizedPos;
}
@@ -4977,7 +4977,7 @@ void QTouchEvent::TouchPoint::setNormalizedPos(const QPointF &normalizedPos)
/*! \internal */
void QTouchEvent::TouchPoint::setStartPos(const QPointF &startPos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->startPos = startPos;
}
@@ -4985,7 +4985,7 @@ void QTouchEvent::TouchPoint::setStartPos(const QPointF &startPos)
/*! \internal */
void QTouchEvent::TouchPoint::setStartScenePos(const QPointF &startScenePos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->startScenePos = startScenePos;
}
@@ -4993,7 +4993,7 @@ void QTouchEvent::TouchPoint::setStartScenePos(const QPointF &startScenePos)
/*! \internal */
void QTouchEvent::TouchPoint::setStartScreenPos(const QPointF &startScreenPos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->startScreenPos = startScreenPos;
}
@@ -5001,7 +5001,7 @@ void QTouchEvent::TouchPoint::setStartScreenPos(const QPointF &startScreenPos)
/*! \internal */
void QTouchEvent::TouchPoint::setStartNormalizedPos(const QPointF &startNormalizedPos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->startNormalizedPos = startNormalizedPos;
}
@@ -5009,7 +5009,7 @@ void QTouchEvent::TouchPoint::setStartNormalizedPos(const QPointF &startNormaliz
/*! \internal */
void QTouchEvent::TouchPoint::setLastPos(const QPointF &lastPos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->lastPos = lastPos;
}
@@ -5017,7 +5017,7 @@ void QTouchEvent::TouchPoint::setLastPos(const QPointF &lastPos)
/*! \internal */
void QTouchEvent::TouchPoint::setLastScenePos(const QPointF &lastScenePos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->lastScenePos = lastScenePos;
}
@@ -5025,7 +5025,7 @@ void QTouchEvent::TouchPoint::setLastScenePos(const QPointF &lastScenePos)
/*! \internal */
void QTouchEvent::TouchPoint::setLastScreenPos(const QPointF &lastScreenPos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->lastScreenPos = lastScreenPos;
}
@@ -5033,7 +5033,7 @@ void QTouchEvent::TouchPoint::setLastScreenPos(const QPointF &lastScreenPos)
/*! \internal */
void QTouchEvent::TouchPoint::setLastNormalizedPos(const QPointF &lastNormalizedPos)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->lastNormalizedPos = lastNormalizedPos;
}
@@ -5044,7 +5044,7 @@ void QTouchEvent::TouchPoint::setLastNormalizedPos(const QPointF &lastNormalized
*/
void QTouchEvent::TouchPoint::setRect(const QRectF &rect)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->pos = rect.center();
d->ellipseDiameters = rect.size();
@@ -5055,7 +5055,7 @@ void QTouchEvent::TouchPoint::setRect(const QRectF &rect)
*/
void QTouchEvent::TouchPoint::setSceneRect(const QRectF &sceneRect)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->scenePos = sceneRect.center();
d->ellipseDiameters = sceneRect.size();
@@ -5066,7 +5066,7 @@ void QTouchEvent::TouchPoint::setSceneRect(const QRectF &sceneRect)
*/
void QTouchEvent::TouchPoint::setScreenRect(const QRectF &screenRect)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->screenPos = screenRect.center();
d->ellipseDiameters = screenRect.size();
@@ -5075,7 +5075,7 @@ void QTouchEvent::TouchPoint::setScreenRect(const QRectF &screenRect)
/*! \internal */
void QTouchEvent::TouchPoint::setPressure(qreal pressure)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->pressure = pressure;
}
@@ -5083,7 +5083,7 @@ void QTouchEvent::TouchPoint::setPressure(qreal pressure)
/*! \internal */
void QTouchEvent::TouchPoint::setRotation(qreal angle)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->rotation = angle;
}
@@ -5091,7 +5091,7 @@ void QTouchEvent::TouchPoint::setRotation(qreal angle)
/*! \internal */
void QTouchEvent::TouchPoint::setEllipseDiameters(const QSizeF &dia)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->ellipseDiameters = dia;
}
@@ -5099,7 +5099,7 @@ void QTouchEvent::TouchPoint::setEllipseDiameters(const QSizeF &dia)
/*! \internal */
void QTouchEvent::TouchPoint::setVelocity(const QVector2D &v)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->velocity = v;
}
@@ -5107,7 +5107,7 @@ void QTouchEvent::TouchPoint::setVelocity(const QVector2D &v)
/*! \internal */
void QTouchEvent::TouchPoint::setRawScreenPositions(const QVector<QPointF> &positions)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->rawScreenPositions = positions;
}
@@ -5117,7 +5117,7 @@ void QTouchEvent::TouchPoint::setRawScreenPositions(const QVector<QPointF> &posi
*/
void QTouchEvent::TouchPoint::setFlags(InfoFlags flags)
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d = d->detach();
d->flags = flags;
}
@@ -5320,7 +5320,7 @@ QScrollEvent::ScrollState QScrollEvent::scrollState() const
/*!
Creates a new QScreenOrientationChangeEvent
- \a orientation is the new orientation of the screen.
+ \a screenOrientation is the new orientation of the \a screen.
*/
QScreenOrientationChangeEvent::QScreenOrientationChangeEvent(QScreen *screen, Qt::ScreenOrientation screenOrientation)
: QEvent(QEvent::OrientationChange), m_screen(screen), m_orientation(screenOrientation)
@@ -5426,7 +5426,7 @@ QPointingDeviceUniqueId QPointingDeviceUniqueId::fromNumericId(qint64 id)
\sa isValid()
*/
-qint64 QPointingDeviceUniqueId::numericId() const Q_DECL_NOTHROW
+qint64 QPointingDeviceUniqueId::numericId() const noexcept
{
return m_numericId;
}
@@ -5438,7 +5438,7 @@ qint64 QPointingDeviceUniqueId::numericId() const Q_DECL_NOTHROW
Returns whether the two unique pointer IDs \a lhs and \a rhs identify the same pointer
(\c true) or not (\c false).
*/
-bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) Q_DECL_NOTHROW
+bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) noexcept
{
return lhs.numericId() == rhs.numericId();
}
@@ -5458,7 +5458,7 @@ bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) Q_DECL
Returns the hash value for \a key, using \a seed to seed the calculation.
*/
-uint qHash(QPointingDeviceUniqueId key, uint seed) Q_DECL_NOTHROW
+uint qHash(QPointingDeviceUniqueId key, uint seed) noexcept
{
return qHash(key.numericId(), seed);
}
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 2b1c6a6e31..eb0a6208a9 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -549,7 +549,7 @@ public:
};
class Attribute {
public:
- Attribute(AttributeType typ, int s, int l, QVariant val) : type(typ), start(s), length(l), value(qMove(val)) {}
+ Attribute(AttributeType typ, int s, int l, QVariant val) : type(typ), start(s), length(l), value(std::move(val)) {}
Attribute(AttributeType typ, int s, int l) : type(typ), start(s), length(l), value() {}
AttributeType type;
@@ -811,14 +811,14 @@ class Q_GUI_EXPORT QPointingDeviceUniqueId
Q_PROPERTY(qint64 numericId READ numericId CONSTANT)
public:
Q_ALWAYS_INLINE
- Q_DECL_CONSTEXPR QPointingDeviceUniqueId() Q_DECL_NOTHROW : m_numericId(-1) {}
+ Q_DECL_CONSTEXPR QPointingDeviceUniqueId() noexcept : m_numericId(-1) {}
// compiler-generated copy/move ctor/assignment operators are ok!
// compiler-generated dtor is ok!
static QPointingDeviceUniqueId fromNumericId(qint64 id);
- Q_ALWAYS_INLINE Q_DECL_CONSTEXPR bool isValid() const Q_DECL_NOTHROW { return m_numericId != -1; }
- qint64 numericId() const Q_DECL_NOTHROW;
+ Q_ALWAYS_INLINE Q_DECL_CONSTEXPR bool isValid() const noexcept { return m_numericId != -1; }
+ qint64 numericId() const noexcept;
private:
// TODO: for TUIO 2, or any other type of complex token ID, an internal
@@ -829,10 +829,10 @@ private:
Q_DECLARE_TYPEINFO(QPointingDeviceUniqueId, Q_MOVABLE_TYPE);
template <> class QList<QPointingDeviceUniqueId> {}; // to prevent instantiation: use QVector instead
-Q_GUI_EXPORT bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) Q_DECL_NOTHROW;
-inline bool operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) Q_DECL_NOTHROW
+Q_GUI_EXPORT bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) noexcept;
+inline bool operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) noexcept
{ return !operator==(lhs, rhs); }
-Q_GUI_EXPORT uint qHash(QPointingDeviceUniqueId key, uint seed = 0) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(QPointingDeviceUniqueId key, uint seed = 0) noexcept;
@@ -855,19 +855,17 @@ public:
explicit TouchPoint(int id = -1);
TouchPoint(const TouchPoint &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- TouchPoint(TouchPoint &&other) Q_DECL_NOEXCEPT
+ TouchPoint(TouchPoint &&other) noexcept
: d(nullptr)
{ qSwap(d, other.d); }
- TouchPoint &operator=(TouchPoint &&other) Q_DECL_NOEXCEPT
+ TouchPoint &operator=(TouchPoint &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
~TouchPoint();
TouchPoint &operator=(const TouchPoint &other)
{ if ( d != other.d ) { TouchPoint copy(other); swap(copy); } return *this; }
- void swap(TouchPoint &other) Q_DECL_NOEXCEPT
+ void swap(TouchPoint &other) noexcept
{ qSwap(d, other.d); }
int id() const;
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 7df4a1e25b..c2d8bd72b9 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -73,7 +73,7 @@ public:
inline QTouchEventTouchPointPrivate *detach()
{
QTouchEventTouchPointPrivate *d = new QTouchEventTouchPointPrivate(*this);
- d->ref.store(1);
+ d->ref.storeRelaxed(1);
if (!this->ref.deref())
delete this;
return d;
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index a67214bd9a..7799be77d2 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -68,7 +68,7 @@
#include <qpalette.h>
#include <qscreen.h>
#include "qsessionmanager.h"
-#include <private/qcolorprofile_p.h>
+#include <private/qcolortrclut_p.h>
#include <private/qscreen_p.h>
#include <QtGui/qgenericpluginfactory.h>
@@ -210,6 +210,8 @@ bool QGuiApplicationPrivate::obey_desktop_settings = true;
QInputDeviceManager *QGuiApplicationPrivate::m_inputDeviceManager = 0;
+qreal QGuiApplicationPrivate::m_maxDevicePixelRatio = 0.0;
+
static qreal fontSmoothingGamma = 1.7;
extern void qRegisterGuiVariant();
@@ -1029,7 +1031,7 @@ QList<QScreen *> QGuiApplication::screens()
}
/*!
- Returns the screen at \a point, or \c nullptr if outside of any screen.
+ Returns the screen at \a point, or \nullptr if outside of any screen.
The \a point is in relation to the virtualGeometry() of each set of virtual
siblings. If the point maps to more than one set of virtual siblings the first
@@ -1101,17 +1103,19 @@ QScreen *QGuiApplication::screenAt(const QPoint &point)
*/
qreal QGuiApplication::devicePixelRatio() const
{
- // Cache topDevicePixelRatio, iterate through the screen list once only.
- static qreal topDevicePixelRatio = 0.0;
- if (!qFuzzyIsNull(topDevicePixelRatio)) {
- return topDevicePixelRatio;
- }
+ if (!qFuzzyIsNull(QGuiApplicationPrivate::m_maxDevicePixelRatio))
+ return QGuiApplicationPrivate::m_maxDevicePixelRatio;
- topDevicePixelRatio = 1.0; // make sure we never return 0.
+ QGuiApplicationPrivate::m_maxDevicePixelRatio = 1.0; // make sure we never return 0.
for (QScreen *screen : qAsConst(QGuiApplicationPrivate::screen_list))
- topDevicePixelRatio = qMax(topDevicePixelRatio, screen->devicePixelRatio());
+ QGuiApplicationPrivate::m_maxDevicePixelRatio = qMax(QGuiApplicationPrivate::m_maxDevicePixelRatio, screen->devicePixelRatio());
+
+ return QGuiApplicationPrivate::m_maxDevicePixelRatio;
+}
- return topDevicePixelRatio;
+void QGuiApplicationPrivate::resetCachedDevicePixelRatio()
+{
+ m_maxDevicePixelRatio = 0.0;
}
/*!
@@ -1176,7 +1180,7 @@ static void init_platform(const QString &pluginNamesWithArguments, const QString
QStringList plugins = pluginNamesWithArguments.split(QLatin1Char(';'));
QStringList platformArguments;
QStringList availablePlugins = QPlatformIntegrationFactory::keys(platformPluginPath);
- for (auto pluginArgument : plugins) {
+ for (const auto &pluginArgument : plugins) {
// Split into platform name and arguments
QStringList arguments = pluginArgument.split(QLatin1Char(':'));
const QString name = arguments.takeFirst().toLower();
@@ -1302,6 +1306,58 @@ static void init_plugins(const QList<QByteArray> &pluginList)
}
}
+void QGuiApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
+{
+ QCoreApplicationPrivate::addQtOptions(options);
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
+ const QByteArray sessionType = qgetenv("XDG_SESSION_TYPE");
+ const bool x11 = sessionType == "x11";
+ // Technically the x11 aliases are only available if platformName is "xcb", but we can't know that here.
+#else
+ const bool x11 = false;
+#endif
+
+ options->append(QCommandLineOption(QStringLiteral("platform"),
+ QGuiApplication::tr("QPA plugin. See QGuiApplication documentation for available options for each plugin."), QStringLiteral("platformName[:options]")));
+ options->append(QCommandLineOption(QStringLiteral("platformpluginpath"),
+ QGuiApplication::tr("Path to the platform plugins."), QStringLiteral("path")));
+ options->append(QCommandLineOption(QStringLiteral("platformtheme"),
+ QGuiApplication::tr("Platform theme."), QStringLiteral("theme")));
+ options->append(QCommandLineOption(QStringLiteral("plugin"),
+ QGuiApplication::tr("Additional plugins to load, can be specified multiple times."), QStringLiteral("plugin")));
+ options->append(QCommandLineOption(QStringLiteral("qwindowgeometry"),
+ QGuiApplication::tr("Window geometry for the main window, using the X11-syntax, like 100x100+50+50."), QStringLiteral("geometry")));
+ options->append(QCommandLineOption(QStringLiteral("qwindowicon"),
+ QGuiApplication::tr("Default window icon."), QStringLiteral("icon")));
+ options->append(QCommandLineOption(QStringLiteral("qwindowtitle"),
+ QGuiApplication::tr("Title of the first window."), QStringLiteral("title")));
+ options->append(QCommandLineOption(QStringLiteral("reverse"),
+ QGuiApplication::tr("Sets the application's layout direction to Qt::RightToLeft (debugging helper).")));
+ options->append(QCommandLineOption(QStringLiteral("session"),
+ QGuiApplication::tr("Restores the application from an earlier session."), QStringLiteral("session")));
+
+ if (x11) {
+ options->append(QCommandLineOption(QStringLiteral("display"),
+ QGuiApplication::tr("Display name, overrides $DISPLAY."), QStringLiteral("display")));
+ options->append(QCommandLineOption(QStringLiteral("name"),
+ QGuiApplication::tr("Instance name according to ICCCM 4.1.2.5."), QStringLiteral("name")));
+ options->append(QCommandLineOption(QStringLiteral("nograb"),
+ QGuiApplication::tr("Disable mouse grabbing (useful in debuggers).")));
+ options->append(QCommandLineOption(QStringLiteral("dograb"),
+ QGuiApplication::tr("Force mouse grabbing (even when running in a debugger).")));
+ options->append(QCommandLineOption(QStringLiteral("visual"),
+ QGuiApplication::tr("ID of the X11 Visual to use."), QStringLiteral("id")));
+ // Not using the "QStringList names" solution for those aliases, because it makes the first column too wide
+ options->append(QCommandLineOption(QStringLiteral("geometry"),
+ QGuiApplication::tr("Alias for --windowgeometry."), QStringLiteral("geometry")));
+ options->append(QCommandLineOption(QStringLiteral("icon"),
+ QGuiApplication::tr("Alias for --windowicon."), QStringLiteral("icon")));
+ options->append(QCommandLineOption(QStringLiteral("title"),
+ QGuiApplication::tr("Alias for --windowtitle."), QStringLiteral("title")));
+ }
+}
+
void QGuiApplicationPrivate::createPlatformIntegration()
{
QHighDpiScaling::initHighDpiScaling();
@@ -1644,8 +1700,6 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
platform_theme = 0;
delete platform_integration;
platform_integration = 0;
- delete m_a8ColorProfile.load();
- delete m_a32ColorProfile.load();
window_list.clear();
screen_list.clear();
@@ -1828,7 +1882,11 @@ bool QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(QWindow *window,
return platformWindow->windowEvent(event);
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, qintptr *result)
+#else
bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result)
+#endif
{
return window->nativeEvent(eventType, message, result);
}
@@ -2188,8 +2246,6 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh
#endif // QT_CONFIG(wheelevent)
}
-// Remember, Qt convention is: keyboard state is state *before*
-
void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e)
{
QWindow *window = e->window.data();
@@ -2428,9 +2484,9 @@ void QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePr
window->d_func()->resizeEventPending = false;
if (actualGeometry.width() != lastReportedGeometry.width())
- window->widthChanged(actualGeometry.width());
+ emit window->widthChanged(actualGeometry.width());
if (actualGeometry.height() != lastReportedGeometry.height())
- window->heightChanged(actualGeometry.height());
+ emit window->heightChanged(actualGeometry.height());
}
if (isMove) {
@@ -2439,9 +2495,9 @@ void QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePr
QGuiApplication::sendSpontaneousEvent(window, &e);
if (actualGeometry.x() != lastReportedGeometry.x())
- window->xChanged(actualGeometry.x());
+ emit window->xChanged(actualGeometry.x());
if (actualGeometry.y() != lastReportedGeometry.y())
- window->yChanged(actualGeometry.y());
+ emit window->yChanged(actualGeometry.y());
}
}
@@ -3005,6 +3061,8 @@ void QGuiApplicationPrivate::processScreenGeometryChange(QWindowSystemInterfaceP
for (QScreen* sibling : siblings)
emit sibling->virtualGeometryChanged(sibling->virtualGeometry());
}
+
+ resetCachedDevicePixelRatio();
}
void QGuiApplicationPrivate::processScreenLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e)
@@ -3020,6 +3078,8 @@ void QGuiApplicationPrivate::processScreenLogicalDotsPerInchChange(QWindowSystem
s->d_func()->logicalDpi = QDpi(e->dpiX, e->dpiY);
emit s->logicalDotsPerInchChanged(s->logicalDotsPerInch());
+
+ resetCachedDevicePixelRatio();
}
void QGuiApplicationPrivate::processScreenRefreshRateChange(QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *e)
@@ -3075,41 +3135,8 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E
/*! \internal
- This function updates an internal state to keep the source compatibility. Documentation of
- QGuiApplication::mouseButtons() states - "The current state is updated synchronously as
- the event queue is emptied of events that will spontaneously change the mouse state
- (QEvent::MouseButtonPress and QEvent::MouseButtonRelease events)". But internally we have
- been updating these state variables from various places to keep buttons returned by
- mouseButtons() in sync with the systems state. This is not the documented behavior.
-
- ### Qt6 - Remove QGuiApplication::mouseButtons()/keyboardModifiers() API? And here
- are the reasons:
-
- - It is an easy to misuse API by:
-
- a) Application developers: The only place where the values of this API can be trusted is
- when using within mouse handling callbacks. In these callbacks we work with the state
- that was provided directly by the windowing system. Anywhere else it might not reflect what
- user wrongly expects. We might not always receive a matching mouse release for a press event
- (e.g. When dismissing a popup window on X11. Or when dnd enter Qt application with mouse
- button down, we update mouse_buttons and then dnd leaves Qt application and does a drop
- somewhere else) and hence mouseButtons() will be out-of-sync from users perspective, see
- for example QTBUG-33161. BUT THIS IS NOT HOW THE API IS SUPPOSED TO BE USED. Since the only
- safe place to use this API is from mouse event handlers, we might as well deprecate it and
- pass down the button state if we are not already doing that everywhere where it matters.
-
- b) Qt framework developers:
-
- We see users complaining, we start adding hacks everywhere just to keep buttons in sync ;)
- There are corner cases that can not be solved and adding this kind of hacks is never ending
- task.
-
- - Real mouse events, tablet mouse events, etc: all go through QGuiApplication::processMouseEvent,
- and all share mouse_buttons. What if we want to support multiple mice in future? The API must
- go.
-
- - Motivation why this API is public is not clear. Could the same be achieved by a user by
- installing an event filter?
+ This function updates an internal state to keep the source compatibility.
+ ### Qt 6 - Won't need after QTBUG-73829
*/
static void updateMouseAndModifierButtonState(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
{
@@ -4017,32 +4044,26 @@ void QGuiApplicationPrivate::notifyDragStarted(const QDrag *drag)
}
#endif
-const QColorProfile *QGuiApplicationPrivate::colorProfileForA8Text()
+const QColorTrcLut *QGuiApplicationPrivate::colorProfileForA8Text()
{
#ifdef Q_OS_WIN
- QColorProfile *result = m_a8ColorProfile.load();
- if (!result){
- QColorProfile *cs = QColorProfile::fromGamma(2.31); // This is a hard-coded thing for Windows text rendering
- if (!m_a8ColorProfile.testAndSetRelease(0, cs))
- delete cs;
- result = m_a8ColorProfile.load();
+ if (!m_a8ColorProfile){
+ QColorTrcLut *cs = QColorTrcLut::fromGamma(2.31); // This is a hard-coded thing for Windows text rendering
+ m_a8ColorProfile.reset(cs);
}
- return result;
+ return m_a8ColorProfile.get();
#else
return colorProfileForA32Text();
#endif
}
-const QColorProfile *QGuiApplicationPrivate::colorProfileForA32Text()
+const QColorTrcLut *QGuiApplicationPrivate::colorProfileForA32Text()
{
- QColorProfile *result = m_a32ColorProfile.load();
- if (!result){
- QColorProfile *cs = QColorProfile::fromGamma(fontSmoothingGamma);
- if (!m_a32ColorProfile.testAndSetRelease(0, cs))
- delete cs;
- result = m_a32ColorProfile.load();
+ if (!m_a32ColorProfile) {
+ QColorTrcLut *cs = QColorTrcLut::fromGamma(fontSmoothingGamma);
+ m_a32ColorProfile.reset(cs);
}
- return result;
+ return m_a32ColorProfile.get();
}
void QGuiApplicationPrivate::_q_updateFocusObject(QObject *object)
diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h
index 02dffef0fe..5ea72fa0f6 100644
--- a/src/gui/kernel/qguiapplication.h
+++ b/src/gui/kernel/qguiapplication.h
@@ -86,7 +86,7 @@ public:
#else
QGuiApplication(int &argc, char **argv, int = ApplicationFlags);
#endif
- virtual ~QGuiApplication();
+ ~QGuiApplication();
static void setApplicationDisplayName(const QString &name);
static QString applicationDisplayName();
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 482d45e5c3..2ecde0354a 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -55,6 +55,7 @@
#include <QtGui/qguiapplication.h>
#include <QtCore/QPointF>
+#include <QtCore/QSharedPointer>
#include <QtCore/private/qcoreapplication_p.h>
#include <QtCore/private/qthread_p.h>
@@ -66,7 +67,7 @@
QT_BEGIN_NAMESPACE
-class QColorProfile;
+class QColorTrcLut;
class QPlatformIntegration;
class QPlatformTheme;
class QPlatformDragQtResponse;
@@ -91,6 +92,7 @@ public:
virtual void notifyLayoutDirectionChange();
virtual void notifyActiveWindowChange(QWindow *previous);
+ void addQtOptions(QList<QCommandLineOption> *options) override;
virtual bool shouldQuit() override;
bool shouldQuitInternal(const QWindowList &processedWindows);
@@ -112,9 +114,9 @@ public:
static QAbstractEventDispatcher *qt_qpa_core_dispatcher()
{
if (QCoreApplication::instance())
- return QCoreApplication::instance()->d_func()->threadData->eventDispatcher.load();
+ return QCoreApplication::instance()->d_func()->threadData->eventDispatcher.loadRelaxed();
else
- return 0;
+ return nullptr;
}
static void processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e);
@@ -171,7 +173,11 @@ public:
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
#endif
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ static bool processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, qintptr *result);
+#else
static bool processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result);
+#endif
static bool sendQWindowEventToQPlatformWindow(QWindow *window, QEvent *event);
@@ -204,7 +210,7 @@ public:
static void showModalWindow(QWindow *window);
static void hideModalWindow(QWindow *window);
static void updateBlockedStatus(QWindow *window);
- virtual bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = 0) const;
+ virtual bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = nullptr) const;
virtual bool popupActive() { return false; }
static ulong mousePressTime;
@@ -298,8 +304,8 @@ public:
static QInputDeviceManager *inputDeviceManager();
- const QColorProfile *colorProfileForA8Text();
- const QColorProfile *colorProfileForA32Text();
+ const QColorTrcLut *colorProfileForA8Text();
+ const QColorTrcLut *colorProfileForA32Text();
// hook reimplemented in QApplication to apply the QStyle function on the QIcon
virtual QPixmap applyQIconStyleHelper(QIcon::Mode, const QPixmap &basePixmap) const { return basePixmap; }
@@ -310,6 +316,8 @@ public:
static void setApplicationState(Qt::ApplicationState state, bool forcePropagate = false);
+ static void resetCachedDevicePixelRatio();
+
protected:
virtual void notifyThemeChanged();
virtual void sendApplicationPaletteChange(bool toAllWidgets = false, const char *className = nullptr);
@@ -324,12 +332,16 @@ private:
static QGuiApplicationPrivate *self;
static QTouchDevice *m_fakeTouchDevice;
static int m_fakeMouseSourcePointId;
- QAtomicPointer<QColorProfile> m_a8ColorProfile;
- QAtomicPointer<QColorProfile> m_a32ColorProfile;
+ QSharedPointer<QColorTrcLut> m_a8ColorProfile;
+ QSharedPointer<QColorTrcLut> m_a32ColorProfile;
bool ownGlobalShareContext;
static QInputDeviceManager *m_inputDeviceManager;
+
+ // Cache the maximum device pixel ratio, to iterate through the screen list
+ // only the first time it's required, or when devices are added or removed.
+ static qreal m_maxDevicePixelRatio;
};
Q_GUI_EXPORT uint qHash(const QGuiApplicationPrivate::ActiveTouchPointsKey &k);
diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index 525e3fe78e..6e89f85746 100644
--- a/src/gui/kernel/qhighdpiscaling_p.h
+++ b/src/gui/kernel/qhighdpiscaling_p.h
@@ -259,6 +259,8 @@ public:
static inline QPoint origin(const QPlatformScreen *) { return QPoint(); }
static inline QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *) { return pos; }
static inline QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *) { return pos; }
+ static inline QPoint mapPositionToGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window) { return pos; }
+ static inline QPoint mapPositionFromGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window) { return pos; }
static inline QDpi logicalDpi() { return QDpi(-1,-1); }
};
diff --git a/src/gui/kernel/qinputdevicemanager.cpp b/src/gui/kernel/qinputdevicemanager.cpp
index 6e4e5a9c93..11442407e1 100644
--- a/src/gui/kernel/qinputdevicemanager.cpp
+++ b/src/gui/kernel/qinputdevicemanager.cpp
@@ -75,13 +75,13 @@ int QInputDeviceManager::deviceCount(DeviceType type) const
int QInputDeviceManagerPrivate::deviceCount(QInputDeviceManager::DeviceType type) const
{
- return m_deviceCount.value(type);
+ return m_deviceCount[type];
}
void QInputDeviceManagerPrivate::setDeviceCount(QInputDeviceManager::DeviceType type, int count)
{
Q_Q(QInputDeviceManager);
- if (m_deviceCount.value(type) != count) {
+ if (m_deviceCount[type] != count) {
m_deviceCount[type] = count;
emit q->deviceListChanged(type);
}
diff --git a/src/gui/kernel/qinputdevicemanager_p.h b/src/gui/kernel/qinputdevicemanager_p.h
index 74494d712b..1d20b102e3 100644
--- a/src/gui/kernel/qinputdevicemanager_p.h
+++ b/src/gui/kernel/qinputdevicemanager_p.h
@@ -69,7 +69,9 @@ public:
DeviceTypePointer,
DeviceTypeKeyboard,
DeviceTypeTouch,
- DeviceTypeTablet
+ DeviceTypeTablet,
+
+ NumDeviceTypes
};
QInputDeviceManager(QObject *parent = nullptr);
diff --git a/src/gui/kernel/qinputdevicemanager_p_p.h b/src/gui/kernel/qinputdevicemanager_p_p.h
index 0a91252fbc..871f9315c3 100644
--- a/src/gui/kernel/qinputdevicemanager_p_p.h
+++ b/src/gui/kernel/qinputdevicemanager_p_p.h
@@ -52,10 +52,11 @@
//
#include <QtGui/private/qtguiglobal_p.h>
-#include <QtCore/qmap.h>
#include <private/qobject_p.h>
#include "qinputdevicemanager_p.h"
+#include <array>
+
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QInputDeviceManagerPrivate : public QObjectPrivate
@@ -68,7 +69,7 @@ public:
int deviceCount(QInputDeviceManager::DeviceType type) const;
void setDeviceCount(QInputDeviceManager::DeviceType type, int count);
- QMap<QInputDeviceManager::DeviceType, int> m_deviceCount;
+ std::array<int, QInputDeviceManager::NumDeviceTypes> m_deviceCount;
Qt::KeyboardModifiers keyboardModifiers;
};
diff --git a/src/gui/kernel/qinputmethod_p.h b/src/gui/kernel/qinputmethod_p.h
index 0c2b739d92..5657edeb4e 100644
--- a/src/gui/kernel/qinputmethod_p.h
+++ b/src/gui/kernel/qinputmethod_p.h
@@ -67,7 +67,7 @@ class QInputMethodPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QInputMethod)
public:
- inline QInputMethodPrivate() : testContext(0)
+ inline QInputMethodPrivate() : testContext(nullptr)
{}
QPlatformInputContext *platformInputContext() const
{
diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h
index aeec7b7414..8364557020 100644
--- a/src/gui/kernel/qkeymapper_p.h
+++ b/src/gui/kernel/qkeymapper_p.h
@@ -76,7 +76,7 @@ public:
private:
friend QKeyMapperPrivate *qt_keymapper_private();
Q_DECLARE_PRIVATE(QKeyMapper)
- Q_DISABLE_COPY(QKeyMapper)
+ Q_DISABLE_COPY_MOVE(QKeyMapper)
};
struct KeyboardLayoutItem;
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index a428da8ca4..2a86b340af 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -46,9 +46,6 @@
#include "qdebug.h"
#include <QtCore/qhashfunctions.h>
-#ifndef QT_NO_REGEXP
-# include "qregexp.h"
-#endif
#ifndef QT_NO_DATASTREAM
# include "qdatastream.h"
#endif
@@ -1221,10 +1218,12 @@ QString QKeySequence::encodeString(int key)
static inline void addKey(QString &str, const QString &theKey, QKeySequence::SequenceFormat format)
{
if (!str.isEmpty()) {
- if (format == QKeySequence::NativeText)
+ if (format == QKeySequence::NativeText) {
+ //: Key separator in shortcut string
str += QCoreApplication::translate("QShortcut", "+");
- else
+ } else {
str += QLatin1Char('+');
+ }
}
str += theKey;
@@ -1464,7 +1463,7 @@ bool QKeySequence::operator==(const QKeySequence &other) const
Calculates the hash value of \a key, using
\a seed to seed the calculation.
*/
-uint qHash(const QKeySequence &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QKeySequence &key, uint seed) noexcept
{
return qHashRange(key.d->key, key.d->key + QKeySequencePrivate::MaxKeyCount, seed);
}
@@ -1519,7 +1518,7 @@ bool QKeySequence::operator< (const QKeySequence &other) const
*/
bool QKeySequence::isDetached() const
{
- return d->ref.load() == 1;
+ return d->ref.loadRelaxed() == 1;
}
/*!
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
index 65f3a93d9c..3dcbbe5941 100644
--- a/src/gui/kernel/qkeysequence.h
+++ b/src/gui/kernel/qkeysequence.h
@@ -66,7 +66,7 @@ void qt_set_sequence_auto_mnemonic(bool b);
class QVariant;
class QKeySequencePrivate;
-Q_GUI_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QKeySequence &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_GUI_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QKeySequence &key, uint seed = 0) noexcept;
class Q_GUI_EXPORT QKeySequence
{
@@ -186,10 +186,8 @@ public:
operator QVariant() const;
int operator[](uint i) const;
QKeySequence &operator=(const QKeySequence &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QKeySequence &operator=(QKeySequence &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
- void swap(QKeySequence &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ QKeySequence &operator=(QKeySequence &&other) noexcept { swap(other); return *this; }
+ void swap(QKeySequence &other) noexcept { qSwap(d, other.d); }
bool operator==(const QKeySequence &other) const;
inline bool operator!= (const QKeySequence &other) const
@@ -214,7 +212,7 @@ private:
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QKeySequence &ks);
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &in, QKeySequence &ks);
- friend Q_GUI_EXPORT uint qHash(const QKeySequence &key, uint seed) Q_DECL_NOTHROW;
+ friend Q_GUI_EXPORT uint qHash(const QKeySequence &key, uint seed) noexcept;
friend class QShortcutMap;
friend class QShortcut;
diff --git a/src/gui/kernel/qoffscreensurface.h b/src/gui/kernel/qoffscreensurface.h
index 9d4839cb25..1b9e7c00ca 100644
--- a/src/gui/kernel/qoffscreensurface.h
+++ b/src/gui/kernel/qoffscreensurface.h
@@ -60,7 +60,7 @@ public:
// ### Qt 6: merge overloads
explicit QOffscreenSurface(QScreen *screen, QObject *parent);
explicit QOffscreenSurface(QScreen *screen = nullptr);
- virtual ~QOffscreenSurface();
+ ~QOffscreenSurface();
SurfaceType surfaceType() const override;
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 9a6f879431..a3b2ea5f86 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -414,15 +414,14 @@ int QOpenGLContextPrivate::maxTextureSize()
/*!
Returns the last context which called makeCurrent in the current thread,
- or 0, if no context is current.
+ or \nullptr, if no context is current.
*/
QOpenGLContext* QOpenGLContext::currentContext()
{
QGuiGLThreadContext *threadContext = qwindow_context_storage()->localData();
- if (threadContext) {
+ if (threadContext)
return threadContext->context;
- }
- return 0;
+ return nullptr;
}
/*!
@@ -788,7 +787,7 @@ QOpenGLExtraFunctions *QOpenGLContext::extraFunctions() const
to the non-template function.
Note that requests for function objects of other versions or profiles can fail and
- in doing so will return a null pointer. Situations in which creation of the functions
+ in doing so will return \nullptr. Situations in which creation of the functions
object can fail are if the request cannot be satisfied due to asking for functions
that are not in the version or profile of this context. For example:
@@ -1236,7 +1235,8 @@ void QOpenGLContext::deleteQGLContext()
Returns the platform-specific handle for the OpenGL implementation that
is currently in use. (for example, a HMODULE on Windows)
- On platforms that do not use dynamic GL switch the return value is null.
+ On platforms that do not use dynamic GL switching, the return value
+ is \nullptr.
The library might be GL-only, meaning that windowing system interface
functions (for example EGL) may live in another, separate library.
@@ -1330,7 +1330,7 @@ bool QOpenGLContext::supportsThreadedOpenGL()
\since 5.5
Returns the application-wide shared OpenGL context, if present.
- Otherwise, returns a null pointer.
+ Otherwise, returns \nullptr.
This is useful if you need to upload OpenGL objects (buffers, textures,
etc.) before creating or showing a QOpenGLWidget or QQuickWidget.
@@ -1634,7 +1634,7 @@ QOpenGLMultiGroupSharedResource::~QOpenGLMultiGroupSharedResource()
active.deref();
}
#ifndef QT_NO_DEBUG
- if (active.load() != 0) {
+ if (active.loadRelaxed() != 0) {
qWarning("QtGui: Resources are still available at program shutdown.\n"
" This is possibly caused by a leaked QOpenGLWidget, \n"
" QOpenGLFramebufferObject or QOpenGLPixelBuffer.");
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index 4f2f951d61..c6ad893ee6 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -97,7 +97,7 @@ private:
friend class QOpenGLContextGroupPrivate;
friend class QOpenGLMultiGroupSharedResource;
- Q_DISABLE_COPY(QOpenGLSharedResource)
+ Q_DISABLE_COPY_MOVE(QOpenGLSharedResource)
};
class Q_GUI_EXPORT QOpenGLSharedResourceGuard : public QOpenGLSharedResource
@@ -131,7 +131,7 @@ class Q_GUI_EXPORT QOpenGLContextGroupPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QOpenGLContextGroup)
public:
QOpenGLContextGroupPrivate()
- : m_context(0)
+ : m_context(nullptr)
, m_mutex(QMutex::Recursive)
, m_refs(0)
{
@@ -198,20 +198,20 @@ class Q_GUI_EXPORT QOpenGLContextPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QOpenGLContext)
public:
QOpenGLContextPrivate()
- : qGLContextHandle(0)
- , qGLContextDeleteFunction(0)
- , platformGLContext(0)
- , shareContext(0)
- , shareGroup(0)
- , screen(0)
- , surface(0)
- , functions(0)
- , textureFunctions(0)
+ : qGLContextHandle(nullptr)
+ , qGLContextDeleteFunction(nullptr)
+ , platformGLContext(nullptr)
+ , shareContext(nullptr)
+ , shareGroup(nullptr)
+ , screen(nullptr)
+ , surface(nullptr)
+ , functions(nullptr)
+ , textureFunctions(nullptr)
, max_texture_size(-1)
, workaround_brokenFBOReadBack(false)
, workaround_brokenTexSubImage(false)
, workaround_missingPrecisionQualifiers(false)
- , active_engine(0)
+ , active_engine(nullptr)
, qgl_current_fbo_invalid(false)
, qgl_current_fbo(nullptr)
, defaultFboRedirect(0)
@@ -219,7 +219,7 @@ public:
requestedFormat = QSurfaceFormat::defaultFormat();
}
- virtual ~QOpenGLContextPrivate()
+ ~QOpenGLContextPrivate()
{
//do not delete the QOpenGLContext handle here as it is deleted in
//QWidgetPrivate::deleteTLSysExtra()
diff --git a/src/gui/kernel/qopenglwindow.cpp b/src/gui/kernel/qopenglwindow.cpp
index 8b052d92ae..022a47c919 100644
--- a/src/gui/kernel/qopenglwindow.cpp
+++ b/src/gui/kernel/qopenglwindow.cpp
@@ -440,7 +440,7 @@ void QOpenGLWindow::makeCurrent()
d->context->makeCurrent(this);
} else {
if (!d->offscreenSurface) {
- d->offscreenSurface.reset(new QOffscreenSurface);
+ d->offscreenSurface.reset(new QOffscreenSurface(screen()));
d->offscreenSurface->setFormat(d->context->format());
d->offscreenSurface->create();
}
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index c6805dd4e6..61dccd77ac 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -830,7 +830,7 @@ bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const
*/
void QPalette::detach()
{
- if (d->ref.load() != 1) {
+ if (d->ref.loadRelaxed() != 1) {
QPalettePrivate *x = new QPalettePrivate;
for(int grp = 0; grp < (int)NColorGroups; grp++) {
for(int role = 0; role < (int)NColorRoles; role++)
@@ -941,7 +941,8 @@ qint64 QPalette::cacheKey() const
}
/*!
- Returns a new QPalette that has attributes copied from \a other.
+ Returns a new QPalette that is a union of this instance and \a other.
+ Color roles set in this instance take precedence.
*/
QPalette QPalette::resolve(const QPalette &other) const
{
@@ -959,6 +960,7 @@ QPalette QPalette::resolve(const QPalette &other) const
if (!(data.resolve_mask & (1<<role)))
for(int grp = 0; grp < (int)NColorGroups; grp++)
palette.d->br[grp][role] = other.d->br[grp][role];
+ palette.data.resolve_mask |= other.data.resolve_mask;
return palette;
}
@@ -981,7 +983,7 @@ QPalette QPalette::resolve(const QPalette &other) const
#ifndef QT_NO_DATASTREAM
static const int NumOldRoles = 7;
-static const int oldRoles[7] = { QPalette::Foreground, QPalette::Background, QPalette::Light,
+static const int oldRoles[7] = { QPalette::WindowText, QPalette::Window, QPalette::Light,
QPalette::Dark, QPalette::Mid, QPalette::Text, QPalette::Base };
/*!
@@ -1207,7 +1209,7 @@ QDebug operator<<(QDebug dbg, const QPalette &p)
QDebugStateSaver saver(dbg);
QDebug nospace = dbg.nospace();
const uint mask = p.resolve();
- nospace << "QPalette(resolve=" << hex << showbase << mask << ',';
+ nospace << "QPalette(resolve=" << Qt::hex << Qt::showbase << mask << ',';
for (int role = 0; role < (int)QPalette::NColorRoles; ++role) {
if (mask & (1<<role)) {
if (role)
@@ -1223,7 +1225,7 @@ QDebug operator<<(QDebug dbg, const QPalette &p)
nospace << ']';
}
}
- nospace << ')' << noshowbase << dec;
+ nospace << ')' << Qt::noshowbase << Qt::dec;
return dbg;
}
#endif
diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h
index 071eddbc4d..d3a840d9ad 100644
--- a/src/gui/kernel/qpalette.h
+++ b/src/gui/kernel/qpalette.h
@@ -67,18 +67,16 @@ public:
QPalette(const QPalette &palette);
~QPalette();
QPalette &operator=(const QPalette &palette);
-#ifdef Q_COMPILER_RVALUE_REFS
- QPalette(QPalette &&other) Q_DECL_NOTHROW
+ QPalette(QPalette &&other) noexcept
: d(other.d), data(other.data)
{ other.d = nullptr; }
- inline QPalette &operator=(QPalette &&other) Q_DECL_NOEXCEPT
+ inline QPalette &operator=(QPalette &&other) noexcept
{
for_faster_swapping_dont_use = other.for_faster_swapping_dont_use;
qSwap(d, other.d); return *this;
}
-#endif
- void swap(QPalette &other) Q_DECL_NOEXCEPT
+ void swap(QPalette &other) noexcept
{
qSwap(d, other.d);
qSwap(for_faster_swapping_dont_use, other.for_faster_swapping_dont_use);
@@ -98,7 +96,10 @@ public:
ToolTipBase, ToolTipText,
PlaceholderText,
NColorRoles = PlaceholderText + 1,
- Foreground = WindowText, Background = Window
+#if QT_DEPRECATED_SINCE(5, 13)
+ Foreground Q_DECL_ENUMERATOR_DEPRECATED_X("Use QPalette::WindowText instead") = WindowText,
+ Background Q_DECL_ENUMERATOR_DEPRECATED_X("Use QPalette::Window instead") = Window
+#endif
};
Q_ENUM(ColorRole)
@@ -121,7 +122,6 @@ public:
inline const QColor &color(ColorRole cr) const { return color(Current, cr); }
inline const QBrush &brush(ColorRole cr) const { return brush(Current, cr); }
- inline const QBrush &foreground() const { return brush(WindowText); }
inline const QBrush &windowText() const { return brush(WindowText); }
inline const QBrush &button() const { return brush(Button); }
inline const QBrush &light() const { return brush(Light); }
@@ -132,7 +132,6 @@ public:
inline const QBrush &alternateBase() const { return brush(AlternateBase); }
inline const QBrush &toolTipBase() const { return brush(ToolTipBase); }
inline const QBrush &toolTipText() const { return brush(ToolTipText); }
- inline const QBrush &background() const { return brush(Window); }
inline const QBrush &window() const { return brush(Window); }
inline const QBrush &midlight() const { return brush(Midlight); }
inline const QBrush &brightText() const { return brush(BrightText); }
@@ -143,6 +142,12 @@ public:
inline const QBrush &link() const { return brush(Link); }
inline const QBrush &linkVisited() const { return brush(LinkVisited); }
inline const QBrush &placeholderText() const { return brush(PlaceholderText); }
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QPalette::windowText() instead")
+ inline const QBrush &foreground() const { return windowText(); }
+ QT_DEPRECATED_X("Use QPalette::window() instead")
+ inline const QBrush &background() const { return window(); }
+#endif
bool operator==(const QPalette &p) const;
inline bool operator!=(const QPalette &p) const { return !(operator==(p)); }
diff --git a/src/gui/kernel/qpixelformat.h b/src/gui/kernel/qpixelformat.h
index 6b2d6a6ac7..a041a39fc1 100644
--- a/src/gui/kernel/qpixelformat.h
+++ b/src/gui/kernel/qpixelformat.h
@@ -95,7 +95,7 @@ class QPixelFormat
Q_STATIC_ASSERT(uint(TotalFieldWidthByWidths) == uint(TotalFieldWidthByOffsets));
Q_STATIC_ASSERT(uint(TotalFieldWidthByWidths) == 8 * sizeof(quint64));
- Q_DECL_CONSTEXPR inline uchar get(Field offset, FieldWidth width) const Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR inline uchar get(Field offset, FieldWidth width) const noexcept
{ return uchar((data >> uint(offset)) & ((Q_UINT64_C(1) << uint(width)) - Q_UINT64_C(1))); }
Q_DECL_CONSTEXPR static inline quint64 set(Field offset, FieldWidth width, uchar value)
{ return (quint64(value) & ((Q_UINT64_C(1) << uint(width)) - Q_UINT64_C(1))) << uint(offset); }
@@ -160,7 +160,7 @@ public:
CurrentSystemEndian
};
- Q_DECL_CONSTEXPR inline QPixelFormat() Q_DECL_NOTHROW : data(0) {}
+ Q_DECL_CONSTEXPR inline QPixelFormat() noexcept : data(0) {}
Q_DECL_CONSTEXPR inline QPixelFormat(ColorModel colorModel,
uchar firstSize,
uchar secondSize,
@@ -173,47 +173,47 @@ public:
AlphaPremultiplied premultiplied,
TypeInterpretation typeInterpretation,
ByteOrder byteOrder = CurrentSystemEndian,
- uchar subEnum = 0) Q_DECL_NOTHROW;
+ uchar subEnum = 0) noexcept;
- Q_DECL_CONSTEXPR inline ColorModel colorModel() const Q_DECL_NOTHROW { return ColorModel(get(ModelField, ModelFieldWidth)); }
- Q_DECL_CONSTEXPR inline uchar channelCount() const Q_DECL_NOTHROW { return (get(FirstField, FirstFieldWidth) > 0) +
+ Q_DECL_CONSTEXPR inline ColorModel colorModel() const noexcept { return ColorModel(get(ModelField, ModelFieldWidth)); }
+ Q_DECL_CONSTEXPR inline uchar channelCount() const noexcept { return (get(FirstField, FirstFieldWidth) > 0) +
(get(SecondField, SecondFieldWidth) > 0) +
(get(ThirdField, ThirdFieldWidth) > 0) +
(get(FourthField, FourthFieldWidth) > 0) +
(get(FifthField, FifthFieldWidth) > 0) +
(get(AlphaField, AlphaFieldWidth) > 0); }
- Q_DECL_CONSTEXPR inline uchar redSize() const Q_DECL_NOTHROW { return get(FirstField, FirstFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar greenSize() const Q_DECL_NOTHROW { return get(SecondField, SecondFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar blueSize() const Q_DECL_NOTHROW { return get(ThirdField, ThirdFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar redSize() const noexcept { return get(FirstField, FirstFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar greenSize() const noexcept { return get(SecondField, SecondFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar blueSize() const noexcept { return get(ThirdField, ThirdFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar cyanSize() const Q_DECL_NOTHROW { return get(FirstField, FirstFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar magentaSize() const Q_DECL_NOTHROW { return get(SecondField, SecondFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar yellowSize() const Q_DECL_NOTHROW { return get(ThirdField, ThirdFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar blackSize() const Q_DECL_NOTHROW { return get(FourthField, FourthFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar cyanSize() const noexcept { return get(FirstField, FirstFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar magentaSize() const noexcept { return get(SecondField, SecondFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar yellowSize() const noexcept { return get(ThirdField, ThirdFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar blackSize() const noexcept { return get(FourthField, FourthFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar hueSize() const Q_DECL_NOTHROW { return get(FirstField, FirstFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar saturationSize() const Q_DECL_NOTHROW { return get(SecondField, SecondFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar lightnessSize() const Q_DECL_NOTHROW { return get(ThirdField, ThirdFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar brightnessSize() const Q_DECL_NOTHROW { return get(ThirdField, ThirdFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar hueSize() const noexcept { return get(FirstField, FirstFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar saturationSize() const noexcept { return get(SecondField, SecondFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar lightnessSize() const noexcept { return get(ThirdField, ThirdFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar brightnessSize() const noexcept { return get(ThirdField, ThirdFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar alphaSize() const Q_DECL_NOTHROW { return get(AlphaField, AlphaFieldWidth); }
+ Q_DECL_CONSTEXPR inline uchar alphaSize() const noexcept { return get(AlphaField, AlphaFieldWidth); }
- Q_DECL_CONSTEXPR inline uchar bitsPerPixel() const Q_DECL_NOTHROW { return get(FirstField, FirstFieldWidth) +
+ Q_DECL_CONSTEXPR inline uchar bitsPerPixel() const noexcept { return get(FirstField, FirstFieldWidth) +
get(SecondField, SecondFieldWidth) +
get(ThirdField, ThirdFieldWidth) +
get(FourthField, FourthFieldWidth) +
get(FifthField, FifthFieldWidth) +
get(AlphaField, AlphaFieldWidth); }
- Q_DECL_CONSTEXPR inline AlphaUsage alphaUsage() const Q_DECL_NOTHROW { return AlphaUsage(get(AlphaUsageField, AlphaUsageFieldWidth)); }
- Q_DECL_CONSTEXPR inline AlphaPosition alphaPosition() const Q_DECL_NOTHROW { return AlphaPosition(get(AlphaPositionField, AlphaPositionFieldWidth)); }
- Q_DECL_CONSTEXPR inline AlphaPremultiplied premultiplied() const Q_DECL_NOTHROW { return AlphaPremultiplied(get(PremulField, PremulFieldWidth)); }
- Q_DECL_CONSTEXPR inline TypeInterpretation typeInterpretation() const Q_DECL_NOTHROW { return TypeInterpretation(get(TypeInterpretationField, TypeInterpretationFieldWidth)); }
- Q_DECL_CONSTEXPR inline ByteOrder byteOrder() const Q_DECL_NOTHROW { return ByteOrder(get(ByteOrderField, ByteOrderFieldWidth)); }
+ Q_DECL_CONSTEXPR inline AlphaUsage alphaUsage() const noexcept { return AlphaUsage(get(AlphaUsageField, AlphaUsageFieldWidth)); }
+ Q_DECL_CONSTEXPR inline AlphaPosition alphaPosition() const noexcept { return AlphaPosition(get(AlphaPositionField, AlphaPositionFieldWidth)); }
+ Q_DECL_CONSTEXPR inline AlphaPremultiplied premultiplied() const noexcept { return AlphaPremultiplied(get(PremulField, PremulFieldWidth)); }
+ Q_DECL_CONSTEXPR inline TypeInterpretation typeInterpretation() const noexcept { return TypeInterpretation(get(TypeInterpretationField, TypeInterpretationFieldWidth)); }
+ Q_DECL_CONSTEXPR inline ByteOrder byteOrder() const noexcept { return ByteOrder(get(ByteOrderField, ByteOrderFieldWidth)); }
- Q_DECL_CONSTEXPR inline YUVLayout yuvLayout() const Q_DECL_NOTHROW { return YUVLayout(get(SubEnumField, SubEnumFieldWidth)); }
- Q_DECL_CONSTEXPR inline uchar subEnum() const Q_DECL_NOTHROW { return get(SubEnumField, SubEnumFieldWidth); }
+ Q_DECL_CONSTEXPR inline YUVLayout yuvLayout() const noexcept { return YUVLayout(get(SubEnumField, SubEnumFieldWidth)); }
+ Q_DECL_CONSTEXPR inline uchar subEnum() const noexcept { return get(SubEnumField, SubEnumFieldWidth); }
private:
Q_DECL_CONSTEXPR static inline ByteOrder resolveByteOrder(ByteOrder bo)
@@ -255,7 +255,7 @@ QPixelFormat::QPixelFormat(ColorModel mdl,
AlphaPremultiplied premult,
TypeInterpretation typeInterp,
ByteOrder b_order,
- uchar s_enum) Q_DECL_NOTHROW
+ uchar s_enum) noexcept
: data(set(ModelField, ModelFieldWidth, uchar(mdl)) |
set(FirstField, FirstFieldWidth, firstSize) |
set(SecondField, SecondFieldWidth, secondSize) |
@@ -280,7 +280,7 @@ Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatRgba(uchar red,
QPixelFormat::AlphaUsage usage,
QPixelFormat::AlphaPosition position,
QPixelFormat::AlphaPremultiplied pmul=QPixelFormat::NotPremultiplied,
- QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) Q_DECL_NOTHROW
+ QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) noexcept
{
return QPixelFormat(QPixelFormat::RGB,
red,
@@ -296,7 +296,7 @@ Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatRgba(uchar red,
}
Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatGrayscale(uchar channelSize,
- QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) Q_DECL_NOTHROW
+ QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) noexcept
{
return QPixelFormat(QPixelFormat::Grayscale,
channelSize,
@@ -312,7 +312,7 @@ Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatGrayscale(uchar channelSize,
}
Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatAlpha(uchar channelSize,
- QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) Q_DECL_NOTHROW
+ QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) noexcept
{
return QPixelFormat(QPixelFormat::Alpha,
0,
@@ -331,7 +331,7 @@ Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatCmyk(uchar channelSize,
uchar alfa=0,
QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha,
QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning,
- QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) Q_DECL_NOTHROW
+ QPixelFormat::TypeInterpretation typeInt=QPixelFormat::UnsignedInteger) noexcept
{
return QPixelFormat(QPixelFormat::CMYK,
channelSize,
@@ -350,7 +350,7 @@ Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatHsl(uchar channelSize,
uchar alfa=0,
QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha,
QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning,
- QPixelFormat::TypeInterpretation typeInt=QPixelFormat::FloatingPoint) Q_DECL_NOTHROW
+ QPixelFormat::TypeInterpretation typeInt=QPixelFormat::FloatingPoint) noexcept
{
return QPixelFormat(QPixelFormat::HSL,
channelSize,
@@ -369,7 +369,7 @@ Q_DECL_CONSTEXPR inline QPixelFormat qPixelFormatHsv(uchar channelSize,
uchar alfa=0,
QPixelFormat::AlphaUsage usage=QPixelFormat::IgnoresAlpha,
QPixelFormat::AlphaPosition position=QPixelFormat::AtBeginning,
- QPixelFormat::TypeInterpretation typeInt=QPixelFormat::FloatingPoint) Q_DECL_NOTHROW
+ QPixelFormat::TypeInterpretation typeInt=QPixelFormat::FloatingPoint) noexcept
{
return QPixelFormat(QPixelFormat::HSV,
channelSize,
diff --git a/src/gui/kernel/qplatformclipboard.h b/src/gui/kernel/qplatformclipboard.h
index 60733b0a9f..3220201720 100644
--- a/src/gui/kernel/qplatformclipboard.h
+++ b/src/gui/kernel/qplatformclipboard.h
@@ -61,6 +61,9 @@ QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QPlatformClipboard
{
public:
+ Q_DISABLE_COPY_MOVE(QPlatformClipboard)
+
+ QPlatformClipboard() = default;
virtual ~QPlatformClipboard();
virtual QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard);
diff --git a/src/gui/kernel/qplatformcursor.cpp b/src/gui/kernel/qplatformcursor.cpp
index 76e38ab12d..49eff2ad23 100644
--- a/src/gui/kernel/qplatformcursor.cpp
+++ b/src/gui/kernel/qplatformcursor.cpp
@@ -89,7 +89,7 @@ QT_BEGIN_NAMESPACE
set or the system default cursor should take effect.
\a window is a pointer to the window currently displayed at QCursor::pos(). Note
- that this may be 0 if the current position is not occupied by a displayed widget.
+ that this may be \nullptr if the current position is not occupied by a displayed widget.
\sa QCursor::pos()
*/
diff --git a/src/gui/kernel/qplatformcursor.h b/src/gui/kernel/qplatformcursor.h
index 40e8a562f8..f36a73c861 100644
--- a/src/gui/kernel/qplatformcursor.h
+++ b/src/gui/kernel/qplatformcursor.h
@@ -78,6 +78,8 @@ private:
class Q_GUI_EXPORT QPlatformCursor : public QObject {
public:
+ Q_DISABLE_COPY_MOVE(QPlatformCursor)
+
enum Capability {
OverrideCursor = 0x1
};
diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp
index 628ad06478..4bee153489 100644
--- a/src/gui/kernel/qplatformdialoghelper.cpp
+++ b/src/gui/kernel/qplatformdialoghelper.cpp
@@ -41,6 +41,9 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QVariant>
+#if QT_CONFIG(regularexpression)
+#include <QtCore/QRegularExpression>
+#endif
#include <QtCore/QSharedData>
#if QT_CONFIG(settings)
#include <QtCore/QSettings>
@@ -63,6 +66,18 @@ QT_BEGIN_NAMESPACE
*/
+/*!
+ \enum QPlatformDialogHelper::StyleHint
+
+ This enum type specifies platform-specific style hints.
+
+ \value DialogIsQtWindow Indicates that a platform-specific dialog is implemented
+ as in-process Qt window. It allows to prevent blocking the
+ dialog by an invisible proxy Qt dialog.
+
+ \sa styleHint()
+*/
+
static const int buttonRoleLayouts[2][6][14] =
{
// Qt::Horizontal
@@ -767,19 +782,24 @@ void QPlatformFileDialogHelper::setOptions(const QSharedPointer<QFileDialogOptio
m_options = options;
}
-const char *QPlatformFileDialogHelper::filterRegExp =
+const char QPlatformFileDialogHelper::filterRegExp[] =
"^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$";
// Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)"
QStringList QPlatformFileDialogHelper::cleanFilterList(const QString &filter)
{
- QRegExp regexp(QString::fromLatin1(filterRegExp));
+#if QT_CONFIG(regularexpression)
+ QRegularExpression regexp(QString::fromLatin1(filterRegExp));
Q_ASSERT(regexp.isValid());
QString f = filter;
- int i = regexp.indexIn(f);
- if (i >= 0)
- f = regexp.cap(2);
+ QRegularExpressionMatch match;
+ filter.indexOf(regexp, 0, &match);
+ if (match.hasMatch())
+ f = match.captured(2);
return f.split(QLatin1Char(' '), QString::SkipEmptyParts);
+#else
+ return QStringList();
+#endif
}
// Message dialog
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
index bfcb658172..ba800a696f 100644
--- a/src/gui/kernel/qplatformdialoghelper.h
+++ b/src/gui/kernel/qplatformdialoghelper.h
@@ -80,6 +80,7 @@ class Q_GUI_EXPORT QPlatformDialogHelper : public QObject
Q_OBJECT
public:
enum StyleHint {
+ DialogIsQtWindow
};
enum DialogCode { Rejected, Accepted };
@@ -153,7 +154,7 @@ public:
Q_ENUM(ButtonLayout)
QPlatformDialogHelper();
- virtual ~QPlatformDialogHelper();
+ ~QPlatformDialogHelper();
virtual QVariant styleHint(StyleHint hint) const;
@@ -317,7 +318,9 @@ public:
ShowDirsOnly = 0x00000001,
DontResolveSymlinks = 0x00000002,
DontConfirmOverwrite = 0x00000004,
- DontUseSheet = 0x00000008,
+#if QT_DEPRECATED_SINCE(5, 14)
+ DontUseSheet Q_DECL_ENUMERATOR_DEPRECATED = 0x00000008,
+#endif
DontUseNativeDialog = 0x00000010,
ReadOnly = 0x00000020,
HideNameFilterDetails = 0x00000040,
@@ -413,7 +416,7 @@ public:
void setOptions(const QSharedPointer<QFileDialogOptions> &options);
static QStringList cleanFilterList(const QString &filter);
- static const char *filterRegExp;
+ static const char filterRegExp[];
Q_SIGNALS:
void fileSelected(const QUrl &file);
diff --git a/src/gui/kernel/qplatformdrag.h b/src/gui/kernel/qplatformdrag.h
index 9d4e352b4b..0c99539357 100644
--- a/src/gui/kernel/qplatformdrag.h
+++ b/src/gui/kernel/qplatformdrag.h
@@ -91,6 +91,8 @@ class Q_GUI_EXPORT QPlatformDrag
{
Q_DECLARE_PRIVATE(QPlatformDrag)
public:
+ Q_DISABLE_COPY_MOVE(QPlatformDrag)
+
QPlatformDrag();
virtual ~QPlatformDrag();
@@ -108,8 +110,6 @@ public:
private:
QPlatformDragPrivate *d_ptr;
-
- Q_DISABLE_COPY(QPlatformDrag)
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformgraphicsbuffer.cpp b/src/gui/kernel/qplatformgraphicsbuffer.cpp
index d361a8fc12..73ec033e19 100644
--- a/src/gui/kernel/qplatformgraphicsbuffer.cpp
+++ b/src/gui/kernel/qplatformgraphicsbuffer.cpp
@@ -184,7 +184,7 @@ void QPlatformGraphicsBuffer::unlock()
\fn QPlatformGraphicsBuffer::doLock(AccessTypes access, const QRect &rect = QRect())
This function should be reimplemented by subclasses. If one of the \a
- access types specified can not be locked, then all should fail and this
+ access types specified cannot be locked, then all should fail and this
function should return false.
\a rect is the subrect which is desired to be locked. This
diff --git a/src/gui/kernel/qplatformgraphicsbuffer.h b/src/gui/kernel/qplatformgraphicsbuffer.h
index 11566e1201..9004116ea4 100644
--- a/src/gui/kernel/qplatformgraphicsbuffer.h
+++ b/src/gui/kernel/qplatformgraphicsbuffer.h
@@ -80,7 +80,7 @@ public:
};
Q_ENUM(Origin);
- virtual ~QPlatformGraphicsBuffer();
+ ~QPlatformGraphicsBuffer();
AccessTypes isLocked() const { return m_lock_access; }
bool lock(AccessTypes access, const QRect &rect = QRect());
diff --git a/src/gui/kernel/qplatforminputcontext.h b/src/gui/kernel/qplatforminputcontext.h
index 26d40cd2c6..ad0e5bcf35 100644
--- a/src/gui/kernel/qplatforminputcontext.h
+++ b/src/gui/kernel/qplatforminputcontext.h
@@ -67,7 +67,7 @@ public:
};
QPlatformInputContext();
- virtual ~QPlatformInputContext();
+ ~QPlatformInputContext();
virtual bool isValid() const;
virtual bool hasCapability(Capability capability) const;
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index ac4d12b024..490cfc6178 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -291,7 +291,7 @@ QPlatformPixmap *QPlatformIntegration::createPlatformPixmap(QPlatformPixmap::Pix
platform implementation is responsible for querying the configuriation from the provided
native context.
- Returns a pointer to a QPlatformOpenGLContext instance or \c NULL if the context could
+ Returns a pointer to a QPlatformOpenGLContext instance or \nullptr if the context could
not be created.
\sa QOpenGLContext
@@ -462,42 +462,6 @@ QList<int> QPlatformIntegration::possibleKeys(const QKeyEvent *) const
return QList<int>();
}
-/*!
- \deprecated Use QWindowSystemInterface::handleScreenAdded instead.
-*/
-void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary)
-{
- QWindowSystemInterface::handleScreenAdded(ps, isPrimary);
-}
-
-/*!
- \deprecated Use QWindowSystemInterface::handleScreenRemoved instead.
-*/
-void QPlatformIntegration::removeScreen(QScreen *screen)
-{
- const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list.at(0) == screen);
- QGuiApplicationPrivate::screen_list.removeOne(screen);
-
- if (wasPrimary && qGuiApp && !QGuiApplicationPrivate::screen_list.isEmpty())
- emit qGuiApp->primaryScreenChanged(QGuiApplicationPrivate::screen_list.at(0));
-}
-
-/*!
- \deprecated Use QWindowSystemInterface::handleScreenRemoved instead.
-*/
-void QPlatformIntegration::destroyScreen(QPlatformScreen *platformScreen)
-{
- QWindowSystemInterface::handleScreenRemoved(platformScreen);
-}
-
-/*!
- \deprecated Use QWindowSystemInterface::handlePrimaryScreenChanged instead.
-*/
-void QPlatformIntegration::setPrimaryScreen(QPlatformScreen *newPrimary)
-{
- QWindowSystemInterface::handlePrimaryScreenChanged(newPrimary);
-}
-
QStringList QPlatformIntegration::themeNames() const
{
return QStringList();
@@ -602,7 +566,7 @@ void QPlatformIntegration::setApplicationIcon(const QIcon &icon) const
pointer to the instance for which a platform-specific backend needs to be
created.
- Returns a pointer to a QPlatformOpenGLContext instance or \c NULL if the context could
+ Returns a pointer to a QPlatformOpenGLContext instance or \nullptr if the context could
not be created.
\sa QVulkanInstance
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 1179daeb32..b764bd2617 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -84,6 +84,8 @@ class QVulkanInstance;
class Q_GUI_EXPORT QPlatformIntegration
{
public:
+ Q_DISABLE_COPY_MOVE(QPlatformIntegration)
+
enum Capability {
ThreadedPixmaps = 1,
OpenGL,
@@ -112,7 +114,7 @@ public:
virtual QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const;
virtual QPlatformWindow *createPlatformWindow(QWindow *window) const = 0;
- virtual QPlatformWindow *createForeignWindow(QWindow *, WId) const { return 0; }
+ virtual QPlatformWindow *createForeignWindow(QWindow *, WId) const { return nullptr; }
virtual QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const = 0;
#ifndef QT_NO_OPENGL
virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
@@ -190,10 +192,6 @@ public:
#endif
virtual void setApplicationIcon(const QIcon &icon) const;
-#if QT_DEPRECATED_SINCE(5, 12)
- QT_DEPRECATED_X("Use QWindowSystemInterface::handleScreenRemoved") void removeScreen(QScreen *screen);
-#endif
-
virtual void beep() const;
#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
@@ -201,11 +199,7 @@ public:
#endif
protected:
-#if QT_DEPRECATED_SINCE(5, 12)
- QT_DEPRECATED_X("Use QWindowSystemInterface::handleScreenAdded") void screenAdded(QPlatformScreen *screen, bool isPrimary = false);
- QT_DEPRECATED_X("Use QWindowSystemInterface::handleScreenRemoved") void destroyScreen(QPlatformScreen *screen);
- QT_DEPRECATED_X("Use QWindowSystemInterface::handlePrimaryScreenChanged") void setPrimaryScreen(QPlatformScreen *newPrimary);
-#endif
+ QPlatformIntegration() = default;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index 21ae75ba8f..9c5876550a 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -62,10 +62,6 @@ QPlatformScreen::~QPlatformScreen()
Q_D(QPlatformScreen);
if (d->screen) {
qWarning("Manually deleting a QPlatformScreen. Call QWindowSystemInterface::handleScreenRemoved instead.");
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- QGuiApplicationPrivate::platformIntegration()->removeScreen(d->screen);
-QT_WARNING_POP
delete d->screen;
}
}
diff --git a/src/gui/kernel/qplatformscreen.h b/src/gui/kernel/qplatformscreen.h
index e9d64c8a29..b9ecc80320 100644
--- a/src/gui/kernel/qplatformscreen.h
+++ b/src/gui/kernel/qplatformscreen.h
@@ -80,6 +80,8 @@ class Q_GUI_EXPORT QPlatformScreen
Q_DECLARE_PRIVATE(QPlatformScreen)
public:
+ Q_DISABLE_COPY_MOVE(QPlatformScreen)
+
enum SubpixelAntialiasingType { // copied from qfontengine_p.h since we can't include private headers
Subpixel_None,
Subpixel_RGB,
@@ -164,8 +166,6 @@ protected:
QScopedPointer<QPlatformScreenPrivate> d_ptr;
private:
- Q_DISABLE_COPY(QPlatformScreen)
-
friend class QScreenPrivate;
};
diff --git a/src/gui/kernel/qplatformservices.h b/src/gui/kernel/qplatformservices.h
index 339bbfde3f..5de96cfa7d 100644
--- a/src/gui/kernel/qplatformservices.h
+++ b/src/gui/kernel/qplatformservices.h
@@ -58,6 +58,8 @@ class QUrl;
class Q_GUI_EXPORT QPlatformServices
{
public:
+ Q_DISABLE_COPY_MOVE(QPlatformServices)
+
QPlatformServices();
virtual ~QPlatformServices() { }
diff --git a/src/gui/kernel/qplatformsessionmanager.h b/src/gui/kernel/qplatformsessionmanager.h
index ca7cab389b..c6c3984816 100644
--- a/src/gui/kernel/qplatformsessionmanager.h
+++ b/src/gui/kernel/qplatformsessionmanager.h
@@ -64,6 +64,8 @@ QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QPlatformSessionManager
{
public:
+ Q_DISABLE_COPY_MOVE(QPlatformSessionManager)
+
explicit QPlatformSessionManager(const QString &id, const QString &key);
virtual ~QPlatformSessionManager();
@@ -101,8 +103,6 @@ private:
QStringList m_restartCommand;
QStringList m_discardCommand;
QSessionManager::RestartHint m_restartHint;
-
- Q_DISABLE_COPY(QPlatformSessionManager)
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformsurface.h b/src/gui/kernel/qplatformsurface.h
index 4d8854fb40..475f3ef330 100644
--- a/src/gui/kernel/qplatformsurface.h
+++ b/src/gui/kernel/qplatformsurface.h
@@ -65,6 +65,8 @@ class QDebug;
class Q_GUI_EXPORT QPlatformSurface
{
public:
+ Q_DISABLE_COPY_MOVE(QPlatformSurface)
+
virtual ~QPlatformSurface();
virtual QSurfaceFormat format() const = 0;
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 1d6049a98d..356c4ea3ea 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -76,6 +76,8 @@ class Q_GUI_EXPORT QPlatformTheme
{
Q_DECLARE_PRIVATE(QPlatformTheme)
public:
+ Q_DISABLE_COPY_MOVE(QPlatformTheme)
+
enum ThemeHint {
CursorFlashTime,
KeyboardInputInterval,
@@ -307,7 +309,7 @@ public:
virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
virtual QIcon fileIcon(const QFileInfo &fileInfo,
- QPlatformTheme::IconOptions iconOptions = 0) const;
+ QPlatformTheme::IconOptions iconOptions = nullptr) const;
virtual QIconEngine *createIconEngine(const QString &iconName) const;
#ifndef QT_NO_SHORTCUT
@@ -324,8 +326,6 @@ public:
protected:
explicit QPlatformTheme(QPlatformThemePrivate *priv);
QScopedPointer<QPlatformThemePrivate> d_ptr;
-private:
- Q_DISABLE_COPY(QPlatformTheme)
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 835c04a5df..4e95751397 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -90,11 +90,11 @@ QWindow *QPlatformWindow::window() const
}
/*!
- Returns the parent platform window (or 0 if orphan).
+ Returns the parent platform window (or \nullptr if orphan).
*/
QPlatformWindow *QPlatformWindow::parent() const
{
- return window()->parent() ? window()->parent()->handle() : 0;
+ return window()->parent() ? window()->parent()->handle() : nullptr;
}
/*!
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index 075ac0f82b..4d48cc2f13 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -71,6 +71,8 @@ class Q_GUI_EXPORT QPlatformWindow : public QPlatformSurface
{
Q_DECLARE_PRIVATE(QPlatformWindow)
public:
+ Q_DISABLE_COPY_MOVE(QPlatformWindow)
+
explicit QPlatformWindow(QWindow *window);
~QPlatformWindow() override;
@@ -164,8 +166,6 @@ protected:
static QSize constrainWindowSize(const QSize &size);
QScopedPointer<QPlatformWindowPrivate> d_ptr;
-private:
- Q_DISABLE_COPY(QPlatformWindow)
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index f208eb02be..c79f597414 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -106,9 +106,18 @@ void QScreenPrivate::setPlatformScreen(QPlatformScreen *screen)
*/
QScreen::~QScreen()
{
- if (!qApp)
+ // Remove screen
+ const bool wasPrimary = QGuiApplication::primaryScreen() == this;
+ QGuiApplicationPrivate::screen_list.removeOne(this);
+ QGuiApplicationPrivate::resetCachedDevicePixelRatio();
+
+ if (!qGuiApp)
return;
+ QScreen *newPrimaryScreen = QGuiApplication::primaryScreen();
+ if (wasPrimary && newPrimaryScreen)
+ emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
+
// Allow clients to manage windows that are affected by the screen going
// away, before we fall back to moving them to the primary screen.
emit qApp->screenRemoved(this);
@@ -116,11 +125,8 @@ QScreen::~QScreen()
if (QGuiApplication::closingDown())
return;
- QScreen *primaryScreen = QGuiApplication::primaryScreen();
- if (this == primaryScreen)
- return;
-
- bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle());
+ bool movingFromVirtualSibling = newPrimaryScreen
+ && newPrimaryScreen->handle()->virtualSiblings().contains(handle());
// Move any leftover windows to the primary screen
const auto allWindows = QGuiApplication::allWindows();
@@ -129,7 +135,7 @@ QScreen::~QScreen()
continue;
const bool wasVisible = window->isVisible();
- window->setScreen(primaryScreen);
+ window->setScreen(newPrimaryScreen);
// Re-show window if moved from a virtual sibling screen. Otherwise
// leave it up to the application developer to show the window.
@@ -762,7 +768,7 @@ QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height)
static inline void formatRect(QDebug &debug, const QRect r)
{
debug << r.width() << 'x' << r.height()
- << forcesign << r.x() << r.y() << noforcesign;
+ << Qt::forcesign << r.x() << r.y() << Qt::noforcesign;
}
Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen)
diff --git a/src/gui/kernel/qscreen_p.h b/src/gui/kernel/qscreen_p.h
index f31658355b..e5988ff829 100644
--- a/src/gui/kernel/qscreen_p.h
+++ b/src/gui/kernel/qscreen_p.h
@@ -64,12 +64,6 @@ class QScreenPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QScreen)
public:
- QScreenPrivate()
- : platformScreen(0)
- , orientationUpdateMask(0)
- {
- }
-
void setPlatformScreen(QPlatformScreen *screen);
void updateHighDpi()
{
@@ -79,16 +73,16 @@ public:
void updatePrimaryOrientation();
- QPlatformScreen *platformScreen;
+ QPlatformScreen *platformScreen = nullptr;
Qt::ScreenOrientations orientationUpdateMask;
- Qt::ScreenOrientation orientation;
- Qt::ScreenOrientation filteredOrientation;
- Qt::ScreenOrientation primaryOrientation;
+ Qt::ScreenOrientation orientation = Qt::PrimaryOrientation;
+ Qt::ScreenOrientation filteredOrientation = Qt::PrimaryOrientation;
+ Qt::ScreenOrientation primaryOrientation = Qt::LandscapeOrientation;
QRect geometry;
QRect availableGeometry;
- QDpi logicalDpi;
- qreal refreshRate;
+ QDpi logicalDpi = {96, 96};
+ qreal refreshRate = 60;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qsessionmanager.cpp b/src/gui/kernel/qsessionmanager.cpp
index 493a321c74..e5e9c624b2 100644
--- a/src/gui/kernel/qsessionmanager.cpp
+++ b/src/gui/kernel/qsessionmanager.cpp
@@ -123,7 +123,11 @@ QSessionManagerPrivate::QSessionManagerPrivate(const QString &id,
const QString &key)
: QObjectPrivate()
{
- platformSessionManager = QGuiApplicationPrivate::platformIntegration()->createPlatformSessionManager(id, key);
+ if (qApp->testAttribute(Qt::AA_DisableSessionManager)) {
+ platformSessionManager = new QPlatformSessionManager(id, key);
+ } else {
+ platformSessionManager = QGuiApplicationPrivate::platformIntegration()->createPlatformSessionManager(id, key);
+ }
Q_ASSERT_X(platformSessionManager, "Platform session management",
"No platform session management, should use the default implementation");
}
diff --git a/src/gui/kernel/qsessionmanager_p.h b/src/gui/kernel/qsessionmanager_p.h
index 954443430e..d07d9b5eb8 100644
--- a/src/gui/kernel/qsessionmanager_p.h
+++ b/src/gui/kernel/qsessionmanager_p.h
@@ -69,7 +69,7 @@ public:
QSessionManagerPrivate(const QString &id,
const QString &key);
- virtual ~QSessionManagerPrivate();
+ ~QSessionManagerPrivate();
QPlatformSessionManager *platformSessionManager;
};
diff --git a/src/gui/kernel/qshapedpixmapdndwindow_p.h b/src/gui/kernel/qshapedpixmapdndwindow_p.h
index d9a6ea4888..5089be7284 100644
--- a/src/gui/kernel/qshapedpixmapdndwindow_p.h
+++ b/src/gui/kernel/qshapedpixmapdndwindow_p.h
@@ -63,7 +63,7 @@ class QShapedPixmapWindow : public QRasterWindow
{
Q_OBJECT
public:
- explicit QShapedPixmapWindow(QScreen *screen = 0);
+ explicit QShapedPixmapWindow(QScreen *screen = nullptr);
~QShapedPixmapWindow();
void setUseCompositing(bool on) { m_useCompositing = on; }
diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp
index 3bb42c1c0b..0395c1db38 100644
--- a/src/gui/kernel/qshortcutmap.cpp
+++ b/src/gui/kernel/qshortcutmap.cpp
@@ -175,7 +175,7 @@ int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &key, Qt::Short
/*! \internal
Removes a shortcut from the global map.
- If \a owner is 0, all entries in the map with the key sequence specified
+ If \a owner is \nullptr, all entries in the map with the key sequence specified
is removed. If \a key is null, all sequences for \a owner is removed from
the map. If \a id is 0, any identical \a key sequences owned by \a owner
are removed.
@@ -222,7 +222,7 @@ int QShortcutMap::removeShortcut(int id, QObject *owner, const QKeySequence &key
/*! \internal
Changes the enable state of a shortcut to \a enable.
- If \a owner is 0, all entries in the map with the key sequence specified
+ If \a owner is \nullptr, all entries in the map with the key sequence specified
is removed. If \a key is null, all sequences for \a owner is removed from
the map. If \a id is 0, any identical \a key sequences owned by \a owner
are changed.
@@ -260,7 +260,7 @@ int QShortcutMap::setShortcutEnabled(bool enable, int id, QObject *owner, const
/*! \internal
Changes the auto repeat state of a shortcut to \a enable.
- If \a owner is 0, all entries in the map with the key sequence specified
+ If \a owner is \nullptr, all entries in the map with the key sequence specified
is removed. If \a key is null, all sequences for \a owner is removed from
the map. If \a id is 0, any identical \a key sequences owned by \a owner
are changed.
diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp
index 9aab332ef5..bba2a863a9 100644
--- a/src/gui/kernel/qsimpledrag.cpp
+++ b/src/gui/kernel/qsimpledrag.cpp
@@ -48,7 +48,6 @@
#include "qpoint.h"
#include "qbuffer.h"
#include "qimage.h"
-#include "qregexp.h"
#include "qdir.h"
#include "qimagereader.h"
#include "qimagewriter.h"
diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h
index f9e8a83a39..8638b05155 100644
--- a/src/gui/kernel/qsimpledrag_p.h
+++ b/src/gui/kernel/qsimpledrag_p.h
@@ -71,7 +71,7 @@ class QScreen;
class Q_GUI_EXPORT QBasicDrag : public QPlatformDrag, public QObject
{
public:
- virtual ~QBasicDrag();
+ ~QBasicDrag();
virtual Qt::DropAction drag(QDrag *drag) override;
void cancelDrag() override;
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 48060a2c37..9b5b7a6f1e 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -69,29 +69,17 @@ class QStyleHintsPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QStyleHints)
public:
- inline QStyleHintsPrivate()
- : m_mouseDoubleClickInterval(-1)
- , m_mousePressAndHoldInterval(-1)
- , m_startDragDistance(-1)
- , m_startDragTime(-1)
- , m_keyboardInputInterval(-1)
- , m_cursorFlashTime(-1)
- , m_tabFocusBehavior(-1)
- , m_uiEffects(-1)
- , m_wheelScrollLines(-1)
- , m_mouseQuickSelectionThreshold(-1)
- {}
-
- int m_mouseDoubleClickInterval;
- int m_mousePressAndHoldInterval;
- int m_startDragDistance;
- int m_startDragTime;
- int m_keyboardInputInterval;
- int m_cursorFlashTime;
- int m_tabFocusBehavior;
- int m_uiEffects;
- int m_wheelScrollLines;
- int m_mouseQuickSelectionThreshold;
+ int m_mouseDoubleClickInterval = -1;
+ int m_mousePressAndHoldInterval = -1;
+ int m_startDragDistance = -1;
+ int m_startDragTime = -1;
+ int m_keyboardInputInterval = -1;
+ int m_cursorFlashTime = -1;
+ int m_tabFocusBehavior = -1;
+ int m_uiEffects = -1;
+ int m_showShortcutsInContextMenus = -1;
+ int m_wheelScrollLines = -1;
+ int m_mouseQuickSelectionThreshold = -1;
};
/*!
@@ -371,10 +359,25 @@ bool QStyleHints::showIsMaximized() const
\since 5.10
\brief \c true if the platform normally shows shortcut key sequences in
context menus, otherwise \c false.
+
+ Since Qt 5.13, the setShowShortcutsInContextMenus() function can be used to
+ override the platform default.
*/
bool QStyleHints::showShortcutsInContextMenus() const
{
- return themeableHint(QPlatformTheme::ShowShortcutsInContextMenus, QPlatformIntegration::ShowShortcutsInContextMenus).toBool();
+ Q_D(const QStyleHints);
+ return d->m_showShortcutsInContextMenus >= 0
+ ? d->m_showShortcutsInContextMenus != 0
+ : themeableHint(QPlatformTheme::ShowShortcutsInContextMenus, QPlatformIntegration::ShowShortcutsInContextMenus).toBool();
+}
+
+void QStyleHints::setShowShortcutsInContextMenus(bool s)
+{
+ Q_D(QStyleHints);
+ if (s != showShortcutsInContextMenus()) {
+ d->m_showShortcutsInContextMenus = s ? 1 : 0;
+ emit showShortcutsInContextMenusChanged(s);
+ }
}
/*!
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index 7b0683e9b1..9091db9624 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -64,7 +64,7 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_PROPERTY(bool setFocusOnTouchRelease READ setFocusOnTouchRelease STORED false CONSTANT FINAL)
Q_PROPERTY(bool showIsFullScreen READ showIsFullScreen STORED false CONSTANT FINAL)
Q_PROPERTY(bool showIsMaximized READ showIsMaximized STORED false CONSTANT FINAL)
- Q_PROPERTY(bool showShortcutsInContextMenus READ showShortcutsInContextMenus STORED false CONSTANT FINAL)
+ Q_PROPERTY(bool showShortcutsInContextMenus READ showShortcutsInContextMenus WRITE setShowShortcutsInContextMenus NOTIFY showShortcutsInContextMenusChanged FINAL)
Q_PROPERTY(int startDragDistance READ startDragDistance NOTIFY startDragDistanceChanged FINAL)
Q_PROPERTY(int startDragTime READ startDragTime NOTIFY startDragTimeChanged FINAL)
Q_PROPERTY(int startDragVelocity READ startDragVelocity STORED false CONSTANT FINAL)
@@ -93,6 +93,7 @@ public:
bool showIsFullScreen() const;
bool showIsMaximized() const;
bool showShortcutsInContextMenus() const;
+ void setShowShortcutsInContextMenus(bool showShortcutsInContextMenus);
int passwordMaskDelay() const;
QChar passwordMaskCharacter() const;
qreal fontSmoothingGamma() const;
@@ -117,6 +118,7 @@ Q_SIGNALS:
void startDragTimeChanged(int startDragTime);
void tabFocusBehaviorChanged(Qt::TabFocusBehavior tabFocusBehavior);
void useHoverEffectsChanged(bool useHoverEffects);
+ void showShortcutsInContextMenusChanged(bool);
void wheelScrollLinesChanged(int scrollLines);
void mouseQuickSelectionThresholdChanged(int threshold);
diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp
index 1a814ec21f..2e2738ec81 100644
--- a/src/gui/kernel/qsurfaceformat.cpp
+++ b/src/gui/kernel/qsurfaceformat.cpp
@@ -246,7 +246,7 @@ QSurfaceFormat::QSurfaceFormat(QSurfaceFormat::FormatOptions options) :
*/
void QSurfaceFormat::detach()
{
- if (d->ref.load() != 1) {
+ if (d->ref.loadRelaxed() != 1) {
QSurfaceFormatPrivate *newd = new QSurfaceFormatPrivate(d);
if (!d->ref.deref())
delete d;
diff --git a/src/gui/kernel/qt_gui_pch.h b/src/gui/kernel/qt_gui_pch.h
index aa5d3f0572..5e07fa45e7 100644
--- a/src/gui/kernel/qt_gui_pch.h
+++ b/src/gui/kernel/qt_gui_pch.h
@@ -45,37 +45,20 @@
* UNSUPPORTED.
*/
-// from corelib/global/qt_pch.h
+#include "../../corelib/global/qt_pch.h"
+
#if defined __cplusplus
#include <qtguiglobal.h>
-
-
-#ifdef Q_OS_WIN
-# define _POSIX_
-# include <limits.h>
-# undef _POSIX_
-#endif
-
-#include <qcoreapplication.h>
-#include <qlist.h>
-#include <qvariant.h> // All moc genereated code has this include
-#include <qobject.h>
-#include <qregexp.h>
-#include <qstring.h>
-#include <qstringlist.h>
-#if QT_CONFIG(textcodec)
-#include <qtextcodec.h>
-#endif
-
#include <qguiapplication.h>
#include <qbitmap.h>
+#include <qclipboard.h>
#include <qcursor.h>
#include <qevent.h>
+#include <qfont.h>
#include <qimage.h>
#include <qpainter.h>
#include <qpixmap.h>
-#include <qtimer.h>
-
-#include <stdlib.h>
-
+#include <qscreen.h>
+#include <qsurface.h>
+#include <qwindow.h>
#endif
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index a19df4da0f..b71a0c54aa 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -166,7 +166,7 @@ QWindow::QWindow(QScreen *targetScreen)
static QWindow *nonDesktopParent(QWindow *parent)
{
if (parent && parent->type() == Qt::Desktop) {
- qWarning("QWindows can not be reparented into desktop windows");
+ qWarning("QWindows cannot be reparented into desktop windows");
return nullptr;
}
@@ -694,7 +694,8 @@ QWindow *QWindow::parent() const
Sets the \a parent Window. This will lead to the windowing system managing
the clip of the window, so it will be clipped to the \a parent window.
- Setting \a parent to be 0 will make the window become a top level window.
+ Setting \a parent to be \nullptr will make the window become a top level
+ window.
If \a parent is a window created by fromWinId(), then the current window
will be embedded inside \a parent, if the platform supports it.
@@ -1336,16 +1337,18 @@ Qt::WindowStates QWindow::windowStates() const
*/
/*!
- Sets the transient \a parent
+ \property QWindow::transientParent
+ \brief the window for which this window is a transient pop-up
+ \since 5.13
This is a hint to the window manager that this window is a dialog or pop-up
- on behalf of the given window.
+ on behalf of the transient parent.
In order to cause the window to be centered above its transient parent by
default, depending on the window manager, it may also be necessary to call
setFlags() with a suitable \l Qt::WindowType (such as \c Qt::Dialog).
- \sa transientParent(), parent()
+ \sa parent()
*/
void QWindow::setTransientParent(QWindow *parent)
{
@@ -1355,26 +1358,35 @@ void QWindow::setTransientParent(QWindow *parent)
return;
}
if (parent == this) {
- qWarning() << "transient parent" << parent << "can not be same as window";
+ qWarning() << "transient parent" << parent << "cannot be same as window";
return;
}
d->transientParent = parent;
QGuiApplicationPrivate::updateBlockedStatus(this);
+ emit transientParentChanged(parent);
}
-/*!
- Returns the transient parent of the window.
-
- \sa setTransientParent(), parent()
-*/
QWindow *QWindow::transientParent() const
{
Q_D(const QWindow);
return d->transientParent.data();
}
+/*
+ The setter for the QWindow::transientParent property.
+ The only reason this exists is to set the transientParentPropertySet flag
+ so that Qt Quick knows whether it was set programmatically (because of
+ Window declaration context) or because the user set the property.
+*/
+void QWindowPrivate::setTransientParent(QWindow *parent)
+{
+ Q_Q(QWindow);
+ q->setTransientParent(parent);
+ transientParentPropertySet = true;
+}
+
/*!
\enum QWindow::AncestorMode
@@ -2523,7 +2535,12 @@ void QWindow::tabletEvent(QTabletEvent *ev)
Should return true only if the event was handled.
*/
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
+#else
bool QWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
+#endif
{
Q_UNUSED(eventType);
Q_UNUSED(message);
@@ -2832,13 +2849,13 @@ QDebug operator<<(QDebug debug, const QWindow *window)
if (window->isTopLevel())
debug << ", toplevel";
debug << ", " << geometry.width() << 'x' << geometry.height()
- << forcesign << geometry.x() << geometry.y() << noforcesign;
+ << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
const QMargins margins = window->frameMargins();
if (!margins.isNull())
debug << ", margins=" << margins;
debug << ", devicePixelRatio=" << window->devicePixelRatio();
if (const QPlatformWindow *platformWindow = window->handle())
- debug << ", winId=0x" << hex << platformWindow->winId() << dec;
+ debug << ", winId=0x" << Qt::hex << platformWindow->winId() << Qt::dec;
if (const QScreen *screen = window->screen())
debug << ", on " << screen->name();
}
@@ -2864,7 +2881,7 @@ void QWindow::setVulkanInstance(QVulkanInstance *instance)
}
/*!
- \return the associated Vulkan instance or \c null if there is none.
+ \return the associated Vulkan instance if any was set, otherwise \nullptr.
*/
QVulkanInstance *QWindow::vulkanInstance() const
{
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 439e62d0bd..5ee1d00f5b 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -123,6 +123,7 @@ class Q_GUI_EXPORT QWindow : public QObject, public QSurface
Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged REVISION 1)
Q_PROPERTY(Qt::ScreenOrientation contentOrientation READ contentOrientation WRITE reportContentOrientationChange NOTIFY contentOrientationChanged)
Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged REVISION 1)
+ Q_PRIVATE_PROPERTY(QWindow::d_func(), QWindow* transientParent MEMBER transientParent WRITE setTransientParent NOTIFY transientParentChanged REVISION 13)
public:
enum Visibility {
@@ -143,7 +144,7 @@ public:
explicit QWindow(QScreen *screen = nullptr);
explicit QWindow(QWindow *parent);
- virtual ~QWindow();
+ ~QWindow();
void setSurfaceType(SurfaceType surfaceType);
SurfaceType surfaceType() const override;
@@ -336,6 +337,8 @@ Q_SIGNALS:
Q_REVISION(1) void opacityChanged(qreal opacity);
+ Q_REVISION(13) void transientParentChanged(QWindow *transientParent);
+
protected:
virtual void exposeEvent(QExposeEvent *);
virtual void resizeEvent(QResizeEvent *);
@@ -361,7 +364,11 @@ protected:
#if QT_CONFIG(tabletevent)
virtual void tabletEvent(QTabletEvent *);
#endif
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
+#else
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result);
+#endif
QWindow(QWindowPrivate &dd, QWindow *parent);
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 745890f63f..5a7ec518fd 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -77,50 +77,15 @@ public:
QWindowPrivate()
: QObjectPrivate()
- , surfaceType(QWindow::RasterSurface)
- , windowFlags(Qt::Window)
- , parentWindow(0)
- , platformWindow(0)
- , visible(false)
- , visibilityOnDestroy(false)
- , exposed(false)
- , windowState(Qt::WindowNoState)
- , visibility(QWindow::Hidden)
- , resizeEventPending(true)
- , receivedExpose(false)
- , positionPolicy(WindowFrameExclusive)
- , positionAutomatic(true)
- , resizeAutomatic(true)
- , contentOrientation(Qt::PrimaryOrientation)
- , opacity(qreal(1.0))
- , minimumSize(0, 0)
- , maximumSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX)
- , modality(Qt::NonModal)
- , blockedByModalWindow(false)
- , updateRequestPending(false)
- , transientParent(0)
- , topLevelScreen(0)
-#ifndef QT_NO_CURSOR
- , cursor(Qt::ArrowCursor)
- , hasCursor(false)
-#endif
- , compositing(false)
-#if QT_CONFIG(vulkan)
- , vulkanInstance(nullptr)
-#endif
{
isWindow = true;
}
- ~QWindowPrivate()
- {
- }
-
void init(QScreen *targetScreen = nullptr);
void maybeQuitOnLastWindowClosed();
#ifndef QT_NO_CURSOR
- void setCursor(const QCursor *c = 0);
+ void setCursor(const QCursor *c = nullptr);
bool applyCursor();
#endif
@@ -149,6 +114,7 @@ public:
void disconnectFromScreen();
void emitScreenChangedRecursion(QScreen *newScreen);
QScreen *screenForGeometry(const QRect &rect) const;
+ void setTransientParent(QWindow *parent);
virtual void clearFocusObject();
virtual QRectF closestAcceptableGeometry(const QRectF &rect) const;
@@ -163,56 +129,60 @@ public:
static Qt::WindowState effectiveState(Qt::WindowStates);
- QWindow::SurfaceType surfaceType;
- Qt::WindowFlags windowFlags;
- QWindow *parentWindow;
- QPlatformWindow *platformWindow;
- bool visible;
- bool visibilityOnDestroy;
- bool exposed;
+ // ### Qt6: unused
+ virtual bool allowClickThrough(const QPoint &) const { return true; }
+
+ QWindow::SurfaceType surfaceType = QWindow::RasterSurface;
+ Qt::WindowFlags windowFlags = Qt::Window;
+ QWindow *parentWindow = nullptr;
+ QPlatformWindow *platformWindow = nullptr;
+ bool visible= false;
+ bool visibilityOnDestroy = false;
+ bool exposed = false;
QSurfaceFormat requestedFormat;
QString windowTitle;
QString windowFilePath;
QIcon windowIcon;
QRect geometry;
- Qt::WindowStates windowState;
- QWindow::Visibility visibility;
- bool resizeEventPending;
- bool receivedExpose;
- PositionPolicy positionPolicy;
- bool positionAutomatic;
+ Qt::WindowStates windowState = Qt::WindowNoState;
+ QWindow::Visibility visibility = QWindow::Hidden;
+ bool resizeEventPending = true;
+ bool receivedExpose = false;
+ PositionPolicy positionPolicy = WindowFrameExclusive;
+ bool positionAutomatic = true;
// resizeAutomatic suppresses resizing by QPlatformWindow::initialGeometry().
// It also indicates that width/height=0 is acceptable (for example, for
// the QRollEffect widget) and is thus not cleared in setGeometry().
// An alternative approach might be using -1,-1 as a default size.
- bool resizeAutomatic;
- Qt::ScreenOrientation contentOrientation;
- qreal opacity;
+ bool resizeAutomatic = true;
+ Qt::ScreenOrientation contentOrientation = Qt::PrimaryOrientation;
+ qreal opacity= 1;
QRegion mask;
- QSize minimumSize;
- QSize maximumSize;
+ QSize minimumSize = {0, 0};
+ QSize maximumSize = {QWINDOWSIZE_MAX, QWINDOWSIZE_MAX};
QSize baseSize;
QSize sizeIncrement;
- Qt::WindowModality modality;
- bool blockedByModalWindow;
+ Qt::WindowModality modality = Qt::NonModal;
+ bool blockedByModalWindow = false;
- bool updateRequestPending;
+ bool updateRequestPending = false;
+ bool transientParentPropertySet = false;
QPointer<QWindow> transientParent;
QPointer<QScreen> topLevelScreen;
#ifndef QT_NO_CURSOR
- QCursor cursor;
- bool hasCursor;
+ QCursor cursor = {Qt::ArrowCursor};
+ bool hasCursor = false;
#endif
- bool compositing;
+ bool compositing = false;
QElapsedTimer lastComposeTime;
#if QT_CONFIG(vulkan)
- QVulkanInstance *vulkanInstance;
+ QVulkanInstance *vulkanInstance = nullptr;
#endif
};
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index b0f2869128..4b8cb3646a 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -800,6 +800,8 @@ void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrima
else
QGuiApplicationPrivate::screen_list.append(screen);
+ QGuiApplicationPrivate::resetCachedDevicePixelRatio();
+
emit qGuiApp->screenAdded(screen);
if (isPrimary)
@@ -816,11 +818,6 @@ void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrima
*/
void QWindowSystemInterface::handleScreenRemoved(QPlatformScreen *platformScreen)
{
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- QGuiApplicationPrivate::platformIntegration()->removeScreen(platformScreen->screen());
-QT_WARNING_POP
-
// Important to keep this order since the QSceen doesn't own the platform screen
delete platformScreen->screen();
delete platformScreen;
@@ -840,7 +837,7 @@ void QWindowSystemInterface::handlePrimaryScreenChanged(QPlatformScreen *newPrim
if (indexOfScreen == 0)
return;
- QGuiApplicationPrivate::screen_list.swap(0, indexOfScreen);
+ QGuiApplicationPrivate::screen_list.swapItemsAt(0, indexOfScreen);
emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
}
@@ -927,7 +924,11 @@ QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, cons
\note This function can only be called from the GUI thread.
*/
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QWindowSystemInterface::handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, qintptr *result)
+#else
bool QWindowSystemInterface::handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result)
+#endif
{
return QGuiApplicationPrivate::processNativeEvent(window, eventType, message, result);
}
@@ -1114,7 +1115,7 @@ bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFl
} else {
sendWindowSystemEvents(flags);
}
- return QWindowSystemInterfacePrivate::eventAccepted.load() > 0;
+ return QWindowSystemInterfacePrivate::eventAccepted.loadRelaxed() > 0;
}
void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
@@ -1155,7 +1156,7 @@ bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFla
// (excluding flush events). This state can then be
// returned by flushWindowSystemEvents().
if (event->type != QWindowSystemInterfacePrivate::FlushEvents)
- QWindowSystemInterfacePrivate::eventAccepted.store(event->eventAccepted);
+ QWindowSystemInterfacePrivate::eventAccepted.storeRelaxed(event->eventAccepted);
delete event;
}
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index bf98c33a1a..fd70eda9ff 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -230,7 +230,11 @@ public:
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
#endif // QT_CONFIG(draganddrop)
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ static bool handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, qintptr *result);
+#else
static bool handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result);
+#endif
// Changes to the screen
static void handleScreenAdded(QPlatformScreen *screen, bool isPrimary = false);
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index cea02fb8b7..d6513f1836 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -123,7 +123,7 @@ public:
class CloseEvent : public WindowSystemEvent {
public:
- explicit CloseEvent(QWindow *w, bool *a = 0)
+ explicit CloseEvent(QWindow *w, bool *a = nullptr)
: WindowSystemEvent(Close), window(w), accepted(a)
{ }
QPointer<QWindow> window;
@@ -398,7 +398,7 @@ public:
class TabletEnterProximityEvent : public InputEvent {
public:
TabletEnterProximityEvent(ulong time, int device, int pointerType, qint64 uid)
- : InputEvent(0, time, TabletEnterProximity, Qt::NoModifier),
+ : InputEvent(nullptr, time, TabletEnterProximity, Qt::NoModifier),
device(device), pointerType(pointerType), uid(uid) { }
int device;
int pointerType;
@@ -408,7 +408,7 @@ public:
class TabletLeaveProximityEvent : public InputEvent {
public:
TabletLeaveProximityEvent(ulong time, int device, int pointerType, qint64 uid)
- : InputEvent(0, time, TabletLeaveProximity, Qt::NoModifier),
+ : InputEvent(nullptr, time, TabletLeaveProximity, Qt::NoModifier),
device(device), pointerType(pointerType), uid(uid) { }
int device;
int pointerType;
@@ -474,7 +474,7 @@ public:
for (int i = 0; i < impl.size(); ++i)
if (!(impl.at(i)->type & QWindowSystemInterfacePrivate::UserInputEvent))
return impl.takeAt(i);
- return 0;
+ return nullptr;
}
bool nonUserInputEventsQueued()
{
@@ -495,7 +495,7 @@ public:
if (impl.at(i)->type == t)
return impl.at(i);
}
- return 0;
+ return nullptr;
}
void remove(const WindowSystemEvent *e)
{
@@ -508,7 +508,7 @@ public:
}
}
private:
- Q_DISABLE_COPY(WindowSystemEventList)
+ Q_DISABLE_COPY_MOVE(WindowSystemEventList)
};
static WindowSystemEventList windowSystemEventQueue;
diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h
index 6a2a9e5bae..692c29c996 100644
--- a/src/gui/math3d/qgenericmatrix.h
+++ b/src/gui/math3d/qgenericmatrix.h
@@ -351,11 +351,11 @@ QDebug operator<<(QDebug dbg, const QGenericMatrix<N, M, T> &m)
QDebugStateSaver saver(dbg);
dbg.nospace() << "QGenericMatrix<" << N << ", " << M
<< ", " << QTypeInfo<T>::name()
- << ">(" << endl << qSetFieldWidth(10);
+ << ">(" << Qt::endl << qSetFieldWidth(10);
for (int row = 0; row < M; ++row) {
for (int col = 0; col < N; ++col)
dbg << m(row, col);
- dbg << endl;
+ dbg << Qt::endl;
}
dbg << qSetFieldWidth(0) << ')';
return dbg;
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index 045fa210c4..ad4cdfdbf4 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -2037,12 +2037,12 @@ QDebug operator<<(QDebug dbg, const QMatrix4x4 &m)
}
// Output in row-major order because it is more human-readable.
- dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << endl
+ dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << Qt::endl
<< qSetFieldWidth(10)
- << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << endl
- << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << endl
- << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << endl
- << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << endl
+ << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << Qt::endl
+ << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << Qt::endl
+ << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << Qt::endl
+ << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << Qt::endl
<< qSetFieldWidth(0) << ')';
return dbg;
}
diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp
index 987cbe7c12..667d16317f 100644
--- a/src/gui/opengl/qopengl.cpp
+++ b/src/gui/opengl/qopengl.cpp
@@ -54,8 +54,6 @@
#include <QtCore/QFile>
#include <QtCore/QDir>
-#include <set>
-
QT_BEGIN_NAMESPACE
#if defined(QT_OPENGL_3)
@@ -82,7 +80,7 @@ QOpenGLExtensionMatcher::QOpenGLExtensionMatcher()
if (extensionStr) {
QByteArray ba(extensionStr);
QList<QByteArray> extensions = ba.split(' ');
- m_extensions = extensions.toSet();
+ m_extensions = QSet<QByteArray>(extensions.constBegin(), extensions.constEnd());
} else {
#ifdef QT_OPENGL_3
// clear error state
@@ -138,7 +136,7 @@ QDebug operator<<(QDebug d, const QOpenGLConfig::Gpu &g)
d.nospace();
d << "Gpu(";
if (g.isValid()) {
- d << "vendor=" << hex << showbase <<g.vendorId << ", device=" << g.deviceId
+ d << "vendor=" << Qt::hex << Qt::showbase <<g.vendorId << ", device=" << g.deviceId
<< "version=" << g.driverVersion;
} else {
d << 0;
@@ -536,13 +534,4 @@ QOpenGLConfig::Gpu QOpenGLConfig::Gpu::fromContext()
return gpu;
}
-Q_GUI_EXPORT std::set<QByteArray> *qgpu_features(const QString &filename)
-{
- const QSet<QString> features = QOpenGLConfig::gpuFeatures(QOpenGLConfig::Gpu::fromContext(), filename);
- std::set<QByteArray> *result = new std::set<QByteArray>;
- for (const QString &feature : features)
- result->insert(feature.toUtf8());
- return result;
-}
-
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglcustomshaderstage_p.h b/src/gui/opengl/qopenglcustomshaderstage_p.h
index f4a71af88e..ce3e9efd23 100644
--- a/src/gui/opengl/qopenglcustomshaderstage_p.h
+++ b/src/gui/opengl/qopenglcustomshaderstage_p.h
@@ -80,7 +80,7 @@ protected:
private:
QOpenGLCustomShaderStagePrivate* d_ptr;
- Q_DISABLE_COPY(QOpenGLCustomShaderStage)
+ Q_DISABLE_COPY_MOVE(QOpenGLCustomShaderStage)
};
diff --git a/src/gui/opengl/qopengldebug.h b/src/gui/opengl/qopengldebug.h
index 556ec175e1..7363985d60 100644
--- a/src/gui/opengl/qopengldebug.h
+++ b/src/gui/opengl/qopengldebug.h
@@ -110,12 +110,10 @@ public:
QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage);
QOpenGLDebugMessage &operator=(const QOpenGLDebugMessage &debugMessage);
-#ifdef Q_COMPILER_RVALUE_REFS
- QOpenGLDebugMessage &operator=(QOpenGLDebugMessage &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QOpenGLDebugMessage &operator=(QOpenGLDebugMessage &&other) noexcept { swap(other); return *this; }
~QOpenGLDebugMessage();
- void swap(QOpenGLDebugMessage &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QOpenGLDebugMessage &other) noexcept { qSwap(d, other.d); }
Source source() const;
Type type() const;
diff --git a/src/gui/opengl/qopenglengineshadermanager_p.h b/src/gui/opengl/qopenglengineshadermanager_p.h
index d43788d777..14c79f5de3 100644
--- a/src/gui/opengl/qopenglengineshadermanager_p.h
+++ b/src/gui/opengl/qopenglengineshadermanager_p.h
@@ -370,7 +370,7 @@ private:
class QOpenGLEngineShaderProg
{
public:
- QOpenGLEngineShaderProg() : program(0) {}
+ QOpenGLEngineShaderProg() : program(nullptr) {}
~QOpenGLEngineShaderProg() {
if (program)
diff --git a/src/gui/opengl/qopengles2ext.h b/src/gui/opengl/qopengles2ext.h
index 8ff50a924e..8517e24267 100644
--- a/src/gui/opengl/qopengles2ext.h
+++ b/src/gui/opengl/qopengles2ext.h
@@ -1,5 +1,5 @@
-#ifndef __gl2ext_h_
-#define __gl2ext_h_ 1
+#ifndef __gles2_gl2ext_h_
+#define __gles2_gl2ext_h_ 1
#if 0
#pragma qt_no_master_include
@@ -25,7 +25,7 @@ typedef struct __GLsync *GLsync;
#endif
/*
-** Copyright (c) 2013-2017 The Khronos Group Inc.
+** Copyright (c) 2013-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -57,7 +57,7 @@ typedef struct __GLsync *GLsync;
#define GL_APIENTRYP GL_APIENTRY*
#endif
-/* Generated on date 20170331 */
+/* Generated on date 20190228 */
/* Generated C header for:
* API: gles2
@@ -178,6 +178,16 @@ GL_APICALL void GL_APIENTRY glGetPointervKHR (GLenum pname, void **params);
#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
#endif /* GL_KHR_no_error */
+#ifndef GL_KHR_parallel_shader_compile
+#define GL_KHR_parallel_shader_compile 1
+#define GL_MAX_SHADER_COMPILER_THREADS_KHR 0x91B0
+#define GL_COMPLETION_STATUS_KHR 0x91B1
+typedef void (GL_APIENTRYP PFNGLMAXSHADERCOMPILERTHREADSKHRPROC) (GLuint count);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMaxShaderCompilerThreadsKHR (GLuint count);
+#endif
+#endif /* GL_KHR_parallel_shader_compile */
+
#ifndef GL_KHR_robust_buffer_access_behavior
#define GL_KHR_robust_buffer_access_behavior 1
#endif /* GL_KHR_robust_buffer_access_behavior */
@@ -343,12 +353,12 @@ GL_APICALL GLboolean GL_APIENTRY glIsEnablediOES (GLenum target, GLuint index);
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
-typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexOES (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
-GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexOES (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
#endif
#endif /* GL_OES_draw_elements_base_vertex */
@@ -810,6 +820,22 @@ GL_APICALL void GL_APIENTRY glGetFloati_vOES (GLenum target, GLuint index, GLflo
#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
#endif /* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_framebuffer_multisample_advanced
+#define GL_AMD_framebuffer_multisample_advanced 1
+#define GL_RENDERBUFFER_STORAGE_SAMPLES_AMD 0x91B2
+#define GL_MAX_COLOR_FRAMEBUFFER_SAMPLES_AMD 0x91B3
+#define GL_MAX_COLOR_FRAMEBUFFER_STORAGE_SAMPLES_AMD 0x91B4
+#define GL_MAX_DEPTH_STENCIL_FRAMEBUFFER_SAMPLES_AMD 0x91B5
+#define GL_NUM_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B6
+#define GL_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B7
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC) (GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC) (GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAdvancedAMD (GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glNamedRenderbufferStorageMultisampleAdvancedAMD (GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_AMD_framebuffer_multisample_advanced */
+
#ifndef GL_AMD_performance_monitor
#define GL_AMD_performance_monitor 1
#define GL_COUNTER_TYPE_AMD 0x8BC0
@@ -1070,6 +1096,20 @@ GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei
#define GL_SHADER_BINARY_DMP 0x9250
#endif /* GL_DMP_shader_binary */
+#ifndef GL_EXT_EGL_image_array
+#define GL_EXT_EGL_image_array 1
+#endif /* GL_EXT_EGL_image_array */
+
+#ifndef GL_EXT_EGL_image_storage
+#define GL_EXT_EGL_image_storage 1
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC) (GLenum target, GLeglImageOES image, const GLint* attrib_list);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC) (GLuint texture, GLeglImageOES image, const GLint* attrib_list);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexStorageEXT (GLenum target, GLeglImageOES image, const GLint* attrib_list);
+GL_APICALL void GL_APIENTRY glEGLImageTargetTextureStorageEXT (GLuint texture, GLeglImageOES image, const GLint* attrib_list);
+#endif
+#endif /* GL_EXT_EGL_image_storage */
+
#ifndef GL_EXT_YUV_target
#define GL_EXT_YUV_target 1
#define GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT 0x8BE7
@@ -1141,6 +1181,20 @@ GL_APICALL void GL_APIENTRY glClearTexSubImageEXT (GLuint texture, GLint level,
#endif
#endif /* GL_EXT_clear_texture */
+#ifndef GL_EXT_clip_control
+#define GL_EXT_clip_control 1
+#define GL_LOWER_LEFT_EXT 0x8CA1
+#define GL_UPPER_LEFT_EXT 0x8CA2
+#define GL_NEGATIVE_ONE_TO_ONE_EXT 0x935E
+#define GL_ZERO_TO_ONE_EXT 0x935F
+#define GL_CLIP_ORIGIN_EXT 0x935C
+#define GL_CLIP_DEPTH_MODE_EXT 0x935D
+typedef void (GL_APIENTRYP PFNGLCLIPCONTROLEXTPROC) (GLenum origin, GLenum depth);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glClipControlEXT (GLenum origin, GLenum depth);
+#endif
+#endif /* GL_EXT_clip_control */
+
#ifndef GL_EXT_clip_cull_distance
#define GL_EXT_clip_cull_distance 1
#define GL_MAX_CLIP_DISTANCES_EXT 0x0D32
@@ -1211,6 +1265,11 @@ GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void);
#endif
#endif /* GL_EXT_debug_marker */
+#ifndef GL_EXT_depth_clamp
+#define GL_EXT_depth_clamp 1
+#define GL_DEPTH_CLAMP_EXT 0x864F
+#endif /* GL_EXT_depth_clamp */
+
#ifndef GL_EXT_discard_framebuffer
#define GL_EXT_discard_framebuffer 1
#define GL_COLOR_EXT 0x1800
@@ -1326,12 +1385,10 @@ GL_APICALL GLboolean GL_APIENTRY glIsEnablediEXT (GLenum target, GLuint index);
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
-typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
-GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
#endif
#endif /* GL_EXT_draw_elements_base_vertex */
@@ -1355,6 +1412,17 @@ GL_APICALL void GL_APIENTRY glDrawTransformFeedbackInstancedEXT (GLenum mode, GL
#endif
#endif /* GL_EXT_draw_transform_feedback */
+#ifndef GL_EXT_external_buffer
+#define GL_EXT_external_buffer 1
+typedef void *GLeglClientBufferEXT;
+typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEEXTERNALEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+typedef void (GL_APIENTRYP PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBufferStorageExternalEXT (GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+GL_APICALL void GL_APIENTRY glNamedBufferStorageExternalEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+#endif
+#endif /* GL_EXT_external_buffer */
+
#ifndef GL_EXT_float_blend
#define GL_EXT_float_blend 1
#endif /* GL_EXT_float_blend */
@@ -1433,6 +1501,85 @@ GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr
#endif
#endif /* GL_EXT_map_buffer_range */
+#ifndef GL_EXT_memory_object
+#define GL_EXT_memory_object 1
+#define GL_TEXTURE_TILING_EXT 0x9580
+#define GL_DEDICATED_MEMORY_OBJECT_EXT 0x9581
+#define GL_PROTECTED_MEMORY_OBJECT_EXT 0x959B
+#define GL_NUM_TILING_TYPES_EXT 0x9582
+#define GL_TILING_TYPES_EXT 0x9583
+#define GL_OPTIMAL_TILING_EXT 0x9584
+#define GL_LINEAR_TILING_EXT 0x9585
+#define GL_NUM_DEVICE_UUIDS_EXT 0x9596
+#define GL_DEVICE_UUID_EXT 0x9597
+#define GL_DRIVER_UUID_EXT 0x9598
+#define GL_UUID_SIZE_EXT 16
+typedef void (GL_APIENTRYP PFNGLGETUNSIGNEDBYTEVEXTPROC) (GLenum pname, GLubyte *data);
+typedef void (GL_APIENTRYP PFNGLGETUNSIGNEDBYTEI_VEXTPROC) (GLenum target, GLuint index, GLubyte *data);
+typedef void (GL_APIENTRYP PFNGLDELETEMEMORYOBJECTSEXTPROC) (GLsizei n, const GLuint *memoryObjects);
+typedef GLboolean (GL_APIENTRYP PFNGLISMEMORYOBJECTEXTPROC) (GLuint memoryObject);
+typedef void (GL_APIENTRYP PFNGLCREATEMEMORYOBJECTSEXTPROC) (GLsizei n, GLuint *memoryObjects);
+typedef void (GL_APIENTRYP PFNGLMEMORYOBJECTPARAMETERIVEXTPROC) (GLuint memoryObject, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC) (GLuint memoryObject, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEMEMEXTPROC) (GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM2DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC) (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM3DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC) (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC) (GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetUnsignedBytevEXT (GLenum pname, GLubyte *data);
+GL_APICALL void GL_APIENTRY glGetUnsignedBytei_vEXT (GLenum target, GLuint index, GLubyte *data);
+GL_APICALL void GL_APIENTRY glDeleteMemoryObjectsEXT (GLsizei n, const GLuint *memoryObjects);
+GL_APICALL GLboolean GL_APIENTRY glIsMemoryObjectEXT (GLuint memoryObject);
+GL_APICALL void GL_APIENTRY glCreateMemoryObjectsEXT (GLsizei n, GLuint *memoryObjects);
+GL_APICALL void GL_APIENTRY glMemoryObjectParameterivEXT (GLuint memoryObject, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glGetMemoryObjectParameterivEXT (GLuint memoryObject, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glTexStorageMem2DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTexStorageMem2DMultisampleEXT (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTexStorageMem3DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTexStorageMem3DMultisampleEXT (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glBufferStorageMemEXT (GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem2DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem2DMultisampleEXT (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem3DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem3DMultisampleEXT (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glNamedBufferStorageMemEXT (GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset);
+#endif
+#endif /* GL_EXT_memory_object */
+
+#ifndef GL_EXT_memory_object_fd
+#define GL_EXT_memory_object_fd 1
+#define GL_HANDLE_TYPE_OPAQUE_FD_EXT 0x9586
+typedef void (GL_APIENTRYP PFNGLIMPORTMEMORYFDEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, GLint fd);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportMemoryFdEXT (GLuint memory, GLuint64 size, GLenum handleType, GLint fd);
+#endif
+#endif /* GL_EXT_memory_object_fd */
+
+#ifndef GL_EXT_memory_object_win32
+#define GL_EXT_memory_object_win32 1
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_EXT 0x9587
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT 0x9588
+#define GL_DEVICE_LUID_EXT 0x9599
+#define GL_DEVICE_NODE_MASK_EXT 0x959A
+#define GL_LUID_SIZE_EXT 8
+#define GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT 0x9589
+#define GL_HANDLE_TYPE_D3D12_RESOURCE_EXT 0x958A
+#define GL_HANDLE_TYPE_D3D11_IMAGE_EXT 0x958B
+#define GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT 0x958C
+typedef void (GL_APIENTRYP PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, void *handle);
+typedef void (GL_APIENTRYP PFNGLIMPORTMEMORYWIN32NAMEEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, const void *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportMemoryWin32HandleEXT (GLuint memory, GLuint64 size, GLenum handleType, void *handle);
+GL_APICALL void GL_APIENTRY glImportMemoryWin32NameEXT (GLuint memory, GLuint64 size, GLenum handleType, const void *name);
+#endif
+#endif /* GL_EXT_memory_object_win32 */
+
#ifndef GL_EXT_multi_draw_arrays
#define GL_EXT_multi_draw_arrays 1
typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
@@ -1598,6 +1745,55 @@ GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location,
#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
#endif /* GL_EXT_sRGB_write_control */
+#ifndef GL_EXT_semaphore
+#define GL_EXT_semaphore 1
+#define GL_LAYOUT_GENERAL_EXT 0x958D
+#define GL_LAYOUT_COLOR_ATTACHMENT_EXT 0x958E
+#define GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT 0x958F
+#define GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT 0x9590
+#define GL_LAYOUT_SHADER_READ_ONLY_EXT 0x9591
+#define GL_LAYOUT_TRANSFER_SRC_EXT 0x9592
+#define GL_LAYOUT_TRANSFER_DST_EXT 0x9593
+#define GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT 0x9530
+#define GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT 0x9531
+typedef void (GL_APIENTRYP PFNGLGENSEMAPHORESEXTPROC) (GLsizei n, GLuint *semaphores);
+typedef void (GL_APIENTRYP PFNGLDELETESEMAPHORESEXTPROC) (GLsizei n, const GLuint *semaphores);
+typedef GLboolean (GL_APIENTRYP PFNGLISSEMAPHOREEXTPROC) (GLuint semaphore);
+typedef void (GL_APIENTRYP PFNGLSEMAPHOREPARAMETERUI64VEXTPROC) (GLuint semaphore, GLenum pname, const GLuint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC) (GLuint semaphore, GLenum pname, GLuint64 *params);
+typedef void (GL_APIENTRYP PFNGLWAITSEMAPHOREEXTPROC) (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts);
+typedef void (GL_APIENTRYP PFNGLSIGNALSEMAPHOREEXTPROC) (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *dstLayouts);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGenSemaphoresEXT (GLsizei n, GLuint *semaphores);
+GL_APICALL void GL_APIENTRY glDeleteSemaphoresEXT (GLsizei n, const GLuint *semaphores);
+GL_APICALL GLboolean GL_APIENTRY glIsSemaphoreEXT (GLuint semaphore);
+GL_APICALL void GL_APIENTRY glSemaphoreParameterui64vEXT (GLuint semaphore, GLenum pname, const GLuint64 *params);
+GL_APICALL void GL_APIENTRY glGetSemaphoreParameterui64vEXT (GLuint semaphore, GLenum pname, GLuint64 *params);
+GL_APICALL void GL_APIENTRY glWaitSemaphoreEXT (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts);
+GL_APICALL void GL_APIENTRY glSignalSemaphoreEXT (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *dstLayouts);
+#endif
+#endif /* GL_EXT_semaphore */
+
+#ifndef GL_EXT_semaphore_fd
+#define GL_EXT_semaphore_fd 1
+typedef void (GL_APIENTRYP PFNGLIMPORTSEMAPHOREFDEXTPROC) (GLuint semaphore, GLenum handleType, GLint fd);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportSemaphoreFdEXT (GLuint semaphore, GLenum handleType, GLint fd);
+#endif
+#endif /* GL_EXT_semaphore_fd */
+
+#ifndef GL_EXT_semaphore_win32
+#define GL_EXT_semaphore_win32 1
+#define GL_HANDLE_TYPE_D3D12_FENCE_EXT 0x9594
+#define GL_D3D12_FENCE_VALUE_EXT 0x9595
+typedef void (GL_APIENTRYP PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC) (GLuint semaphore, GLenum handleType, void *handle);
+typedef void (GL_APIENTRYP PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC) (GLuint semaphore, GLenum handleType, const void *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportSemaphoreWin32HandleEXT (GLuint semaphore, GLenum handleType, void *handle);
+GL_APICALL void GL_APIENTRY glImportSemaphoreWin32NameEXT (GLuint semaphore, GLenum handleType, const void *name);
+#endif
+#endif /* GL_EXT_semaphore_win32 */
+
#ifndef GL_EXT_separate_shader_objects
#define GL_EXT_separate_shader_objects 1
#define GL_ACTIVE_PROGRAM_EXT 0x8259
@@ -1703,6 +1899,14 @@ GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLin
#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
#endif /* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_framebuffer_fetch_non_coherent
+#define GL_EXT_shader_framebuffer_fetch_non_coherent 1
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferFetchBarrierEXT (void);
+#endif
+#endif /* GL_EXT_shader_framebuffer_fetch_non_coherent */
+
#ifndef GL_EXT_shader_group_vote
#define GL_EXT_shader_group_vote 1
#endif /* GL_EXT_shader_group_vote */
@@ -1890,18 +2094,42 @@ GL_APICALL void GL_APIENTRY glTexBufferRangeEXT (GLenum target, GLenum internalf
#define GL_TEXTURE_ASTC_DECODE_PRECISION_EXT 0x8F69
#endif /* GL_EXT_texture_compression_astc_decode_mode */
+#ifndef GL_EXT_texture_compression_bptc
+#define GL_EXT_texture_compression_bptc 1
+#define GL_COMPRESSED_RGBA_BPTC_UNORM_EXT 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT 0x8E8F
+#endif /* GL_EXT_texture_compression_bptc */
+
#ifndef GL_EXT_texture_compression_dxt1
#define GL_EXT_texture_compression_dxt1 1
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#endif /* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_rgtc
+#define GL_EXT_texture_compression_rgtc 1
+#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#endif /* GL_EXT_texture_compression_rgtc */
+
#ifndef GL_EXT_texture_compression_s3tc
#define GL_EXT_texture_compression_s3tc 1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#endif /* GL_EXT_texture_compression_s3tc */
+#ifndef GL_EXT_texture_compression_s3tc_srgb
+#define GL_EXT_texture_compression_s3tc_srgb 1
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#endif /* GL_EXT_texture_compression_s3tc_srgb */
+
#ifndef GL_EXT_texture_cube_map_array
#define GL_EXT_texture_cube_map_array 1
#define GL_TEXTURE_CUBE_MAP_ARRAY_EXT 0x9009
@@ -1923,12 +2151,24 @@ GL_APICALL void GL_APIENTRY glTexBufferRangeEXT (GLenum target, GLenum internalf
#ifndef GL_EXT_texture_filter_minmax
#define GL_EXT_texture_filter_minmax 1
+#define GL_TEXTURE_REDUCTION_MODE_EXT 0x9366
+#define GL_WEIGHTED_AVERAGE_EXT 0x9367
#endif /* GL_EXT_texture_filter_minmax */
#ifndef GL_EXT_texture_format_BGRA8888
#define GL_EXT_texture_format_BGRA8888 1
#endif /* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_sRGB_override
+#define GL_EXT_texture_format_sRGB_override 1
+#define GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT 0x8FBF
+#endif /* GL_EXT_texture_format_sRGB_override */
+
+#ifndef GL_EXT_texture_mirror_clamp_to_edge
+#define GL_EXT_texture_mirror_clamp_to_edge 1
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#endif /* GL_EXT_texture_mirror_clamp_to_edge */
+
#ifndef GL_EXT_texture_norm16
#define GL_EXT_texture_norm16 1
#define GL_R16_EXT 0x822A
@@ -1938,6 +2178,10 @@ GL_APICALL void GL_APIENTRY glTexBufferRangeEXT (GLenum target, GLenum internalf
#define GL_RGB16_SNORM_EXT 0x8F9A
#endif /* GL_EXT_texture_norm16 */
+#ifndef GL_EXT_texture_query_lod
+#define GL_EXT_texture_query_lod 1
+#endif /* GL_EXT_texture_query_lod */
+
#ifndef GL_EXT_texture_rg
#define GL_EXT_texture_rg 1
#define GL_RED_EXT 0x1903
@@ -2019,6 +2263,16 @@ GL_APICALL void GL_APIENTRY glTextureViewEXT (GLuint texture, GLenum target, GLu
#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
#endif /* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_win32_keyed_mutex
+#define GL_EXT_win32_keyed_mutex 1
+typedef GLboolean (GL_APIENTRYP PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC) (GLuint memory, GLuint64 key, GLuint timeout);
+typedef GLboolean (GL_APIENTRYP PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC) (GLuint memory, GLuint64 key);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLboolean GL_APIENTRY glAcquireKeyedMutexWin32EXT (GLuint memory, GLuint64 key, GLuint timeout);
+GL_APICALL GLboolean GL_APIENTRY glReleaseKeyedMutexWin32EXT (GLuint memory, GLuint64 key);
+#endif
+#endif /* GL_EXT_win32_keyed_mutex */
+
#ifndef GL_EXT_window_rectangles
#define GL_EXT_window_rectangles 1
#define GL_INCLUSIVE_EXT 0x8F10
@@ -2121,6 +2375,11 @@ GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target,
#define GL_CUBIC_MIPMAP_LINEAR_IMG 0x913B
#endif /* GL_IMG_texture_filter_cubic */
+#ifndef GL_INTEL_blackhole_render
+#define GL_INTEL_blackhole_render 1
+#define GL_BLACKHOLE_RENDER_INTEL 0x83FC
+#endif /* GL_INTEL_blackhole_render */
+
#ifndef GL_INTEL_conservative_rasterization
#define GL_INTEL_conservative_rasterization 1
#define GL_CONSERVATIVE_RASTERIZATION_INTEL 0x83FE
@@ -2163,7 +2422,7 @@ typedef void (GL_APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle);
typedef void (GL_APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId);
typedef void (GL_APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId);
typedef void (GL_APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
-typedef void (GL_APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+typedef void (GL_APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, void *data, GLuint *bytesWritten);
typedef void (GL_APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId);
typedef void (GL_APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
#ifdef GL_GLEXT_PROTOTYPES
@@ -2174,12 +2433,22 @@ GL_APICALL void GL_APIENTRY glEndPerfQueryINTEL (GLuint queryHandle);
GL_APICALL void GL_APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId);
GL_APICALL void GL_APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId);
GL_APICALL void GL_APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
-GL_APICALL void GL_APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+GL_APICALL void GL_APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, void *data, GLuint *bytesWritten);
GL_APICALL void GL_APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId);
GL_APICALL void GL_APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
#endif
#endif /* GL_INTEL_performance_query */
+#ifndef GL_MESA_framebuffer_flip_y
+#define GL_MESA_framebuffer_flip_y 1
+#define GL_FRAMEBUFFER_FLIP_Y_MESA 0x8BBB
+#endif /* GL_MESA_framebuffer_flip_y */
+
+#ifndef GL_MESA_program_binary_formats
+#define GL_MESA_program_binary_formats 1
+#define GL_PROGRAM_BINARY_FORMAT_MESA 0x875F
+#endif /* GL_MESA_program_binary_formats */
+
#ifndef GL_MESA_shader_integer_functions
#define GL_MESA_shader_integer_functions 1
#endif /* GL_MESA_shader_integer_functions */
@@ -2284,6 +2553,27 @@ GL_APICALL void GL_APIENTRY glBlendBarrierNV (void);
#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285
#endif /* GL_NV_blend_equation_advanced_coherent */
+#ifndef GL_NV_blend_minmax_factor
+#define GL_NV_blend_minmax_factor 1
+#define GL_FACTOR_MIN_AMD 0x901C
+#define GL_FACTOR_MAX_AMD 0x901D
+#endif /* GL_NV_blend_minmax_factor */
+
+#ifndef GL_NV_clip_space_w_scaling
+#define GL_NV_clip_space_w_scaling 1
+#define GL_VIEWPORT_POSITION_W_SCALE_NV 0x937C
+#define GL_VIEWPORT_POSITION_W_SCALE_X_COEFF_NV 0x937D
+#define GL_VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV 0x937E
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPOSITIONWSCALENVPROC) (GLuint index, GLfloat xcoeff, GLfloat ycoeff);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportPositionWScaleNV (GLuint index, GLfloat xcoeff, GLfloat ycoeff);
+#endif
+#endif /* GL_NV_clip_space_w_scaling */
+
+#ifndef GL_NV_compute_shader_derivatives
+#define GL_NV_compute_shader_derivatives 1
+#endif /* GL_NV_compute_shader_derivatives */
+
#ifndef GL_NV_conditional_render
#define GL_NV_conditional_render 1
#define GL_QUERY_WAIT_NV 0x8E13
@@ -2310,6 +2600,11 @@ GL_APICALL void GL_APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybit
#endif
#endif /* GL_NV_conservative_raster */
+#ifndef GL_NV_conservative_raster_pre_snap
+#define GL_NV_conservative_raster_pre_snap 1
+#define GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_NV 0x9550
+#endif /* GL_NV_conservative_raster_pre_snap */
+
#ifndef GL_NV_conservative_raster_pre_snap_triangles
#define GL_NV_conservative_raster_pre_snap_triangles 1
#define GL_CONSERVATIVE_RASTER_MODE_NV 0x954D
@@ -2655,6 +2950,34 @@ GL_APICALL void GL_APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum
#endif
#endif /* GL_NV_internalformat_sample_query */
+#ifndef GL_NV_memory_attachment
+#define GL_NV_memory_attachment 1
+#define GL_ATTACHED_MEMORY_OBJECT_NV 0x95A4
+#define GL_ATTACHED_MEMORY_OFFSET_NV 0x95A5
+#define GL_MEMORY_ATTACHABLE_ALIGNMENT_NV 0x95A6
+#define GL_MEMORY_ATTACHABLE_SIZE_NV 0x95A7
+#define GL_MEMORY_ATTACHABLE_NV 0x95A8
+#define GL_DETACHED_MEMORY_INCARNATION_NV 0x95A9
+#define GL_DETACHED_TEXTURES_NV 0x95AA
+#define GL_DETACHED_BUFFERS_NV 0x95AB
+#define GL_MAX_DETACHED_TEXTURES_NV 0x95AC
+#define GL_MAX_DETACHED_BUFFERS_NV 0x95AD
+typedef void (GL_APIENTRYP PFNGLGETMEMORYOBJECTDETACHEDRESOURCESUIVNVPROC) (GLuint memory, GLenum pname, GLint first, GLsizei count, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLRESETMEMORYOBJECTPARAMETERNVPROC) (GLuint memory, GLenum pname);
+typedef void (GL_APIENTRYP PFNGLTEXATTACHMEMORYNVPROC) (GLenum target, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLBUFFERATTACHMEMORYNVPROC) (GLenum target, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTUREATTACHMEMORYNVPROC) (GLuint texture, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLNAMEDBUFFERATTACHMEMORYNVPROC) (GLuint buffer, GLuint memory, GLuint64 offset);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetMemoryObjectDetachedResourcesuivNV (GLuint memory, GLenum pname, GLint first, GLsizei count, GLuint *params);
+GL_APICALL void GL_APIENTRY glResetMemoryObjectParameterNV (GLuint memory, GLenum pname);
+GL_APICALL void GL_APIENTRY glTexAttachMemoryNV (GLenum target, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glBufferAttachMemoryNV (GLenum target, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureAttachMemoryNV (GLuint texture, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glNamedBufferAttachMemoryNV (GLuint buffer, GLuint memory, GLuint64 offset);
+#endif
+#endif /* GL_NV_memory_attachment */
+
#ifndef GL_NV_non_square_matrices
#define GL_NV_non_square_matrices 1
#define GL_FLOAT_MAT2x3_NV 0x8B65
@@ -2681,6 +3004,7 @@ GL_APICALL void GL_APIENTRY glUniformMatrix4x3fvNV (GLint location, GLsizei coun
#ifndef GL_NV_path_rendering
#define GL_NV_path_rendering 1
+typedef double GLdouble;
#define GL_PATH_FORMAT_SVG_NV 0x9070
#define GL_PATH_FORMAT_PS_NV 0x9071
#define GL_STANDARD_FONT_NAME_NV 0x9072
@@ -2891,6 +3215,25 @@ typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathNa
typedef GLenum (GL_APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
typedef void (GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLMATRIXFRUSTUMEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOADDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULTFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULTDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXORTHOEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (GL_APIENTRYP PFNGLMATRIXPOPEXTPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLMATRIXPUSHEXTPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLMATRIXROTATEFEXTPROC) (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLMATRIXROTATEDEXTPROC) (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GL_APIENTRYP PFNGLMATRIXSCALEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLMATRIXSCALEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GL_APIENTRYP PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL GLuint GL_APIENTRY glGenPathsNV (GLsizei range);
GL_APICALL void GL_APIENTRY glDeletePathsNV (GLuint path, GLsizei range);
@@ -2949,6 +3292,25 @@ GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLe
GL_APICALL GLenum GL_APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
GL_APICALL void GL_APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glMatrixFrustumEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GL_APICALL void GL_APIENTRY glMatrixLoadIdentityEXT (GLenum mode);
+GL_APICALL void GL_APIENTRY glMatrixLoadTransposefEXT (GLenum mode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadTransposedEXT (GLenum mode, const GLdouble *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadfEXT (GLenum mode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoaddEXT (GLenum mode, const GLdouble *m);
+GL_APICALL void GL_APIENTRY glMatrixMultTransposefEXT (GLenum mode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMultTransposedEXT (GLenum mode, const GLdouble *m);
+GL_APICALL void GL_APIENTRY glMatrixMultfEXT (GLenum mode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMultdEXT (GLenum mode, const GLdouble *m);
+GL_APICALL void GL_APIENTRY glMatrixOrthoEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GL_APICALL void GL_APIENTRY glMatrixPopEXT (GLenum mode);
+GL_APICALL void GL_APIENTRY glMatrixPushEXT (GLenum mode);
+GL_APICALL void GL_APIENTRY glMatrixRotatefEXT (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glMatrixRotatedEXT (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+GL_APICALL void GL_APIENTRY glMatrixScalefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glMatrixScaledEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+GL_APICALL void GL_APIENTRY glMatrixTranslatefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glMatrixTranslatedEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
#endif
#endif /* GL_NV_path_rendering */
@@ -2957,6 +3319,14 @@ GL_APICALL void GL_APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum pro
#define GL_SHARED_EDGE_NV 0xC0
#endif /* GL_NV_path_rendering_shared_edge */
+#ifndef GL_NV_pixel_buffer_object
+#define GL_NV_pixel_buffer_object 1
+#define GL_PIXEL_PACK_BUFFER_NV 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_NV 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_NV 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_NV 0x88EF
+#endif /* GL_NV_pixel_buffer_object */
+
#ifndef GL_NV_polygon_mode
#define GL_NV_polygon_mode 1
#define GL_POLYGON_MODE_NV 0x0B40
@@ -3034,6 +3404,18 @@ GL_APICALL void GL_APIENTRY glResolveDepthValuesNV (void);
#define GL_NV_sample_mask_override_coverage 1
#endif /* GL_NV_sample_mask_override_coverage */
+#ifndef GL_NV_scissor_exclusive
+#define GL_NV_scissor_exclusive 1
+#define GL_SCISSOR_TEST_EXCLUSIVE_NV 0x9555
+#define GL_SCISSOR_BOX_EXCLUSIVE_NV 0x9556
+typedef void (GL_APIENTRYP PFNGLSCISSOREXCLUSIVENVPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSCISSOREXCLUSIVEARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glScissorExclusiveNV (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glScissorExclusiveArrayvNV (GLuint first, GLsizei count, const GLint *v);
+#endif
+#endif /* GL_NV_scissor_exclusive */
+
#ifndef GL_NV_shader_atomic_fp16_vector
#define GL_NV_shader_atomic_fp16_vector 1
#endif /* GL_NV_shader_atomic_fp16_vector */
@@ -3052,6 +3434,10 @@ GL_APICALL void GL_APIENTRY glResolveDepthValuesNV (void);
#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5
#endif /* GL_NV_shadow_samplers_cube */
+#ifndef GL_NV_stereo_view_rendering
+#define GL_NV_stereo_view_rendering 1
+#endif /* GL_NV_stereo_view_rendering */
+
#ifndef GL_NV_texture_border_clamp
#define GL_NV_texture_border_clamp 1
#define GL_TEXTURE_BORDER_COLOR_NV 0x1004
@@ -3148,6 +3534,10 @@ GL_APICALL void GL_APIENTRY glFramebufferTextureMultisampleMultiviewOVR (GLenum
#endif
#endif /* GL_OVR_multiview_multisampled_render_to_texture */
+#ifndef GL_QCOM_YUV_texture_gather
+#define GL_QCOM_YUV_texture_gather 1
+#endif /* GL_QCOM_YUV_texture_gather */
+
#ifndef GL_QCOM_alpha_test
#define GL_QCOM_alpha_test 1
#define GL_ALPHA_TEST_QCOM 0x0BC0
@@ -3245,6 +3635,38 @@ GL_APICALL void GL_APIENTRY glFramebufferFoveationParametersQCOM (GLuint framebu
#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
#endif /* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_shader_framebuffer_fetch_noncoherent
+#define GL_QCOM_shader_framebuffer_fetch_noncoherent 1
+#define GL_FRAMEBUFFER_FETCH_NONCOHERENT_QCOM 0x96A2
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERFETCHBARRIERQCOMPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferFetchBarrierQCOM (void);
+#endif
+#endif /* GL_QCOM_shader_framebuffer_fetch_noncoherent */
+
+#ifndef GL_QCOM_shader_framebuffer_fetch_rate
+#define GL_QCOM_shader_framebuffer_fetch_rate 1
+#endif /* GL_QCOM_shader_framebuffer_fetch_rate */
+
+#ifndef GL_QCOM_texture_foveated
+#define GL_QCOM_texture_foveated 1
+#define GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM 0x8BFB
+#define GL_TEXTURE_FOVEATED_MIN_PIXEL_DENSITY_QCOM 0x8BFC
+#define GL_TEXTURE_FOVEATED_FEATURE_QUERY_QCOM 0x8BFD
+#define GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM 0x8BFE
+#define GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM 0x8BFF
+typedef void (GL_APIENTRYP PFNGLTEXTUREFOVEATIONPARAMETERSQCOMPROC) (GLuint texture, GLuint layer, GLuint focalPoint, GLfloat focalX, GLfloat focalY, GLfloat gainX, GLfloat gainY, GLfloat foveaArea);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTextureFoveationParametersQCOM (GLuint texture, GLuint layer, GLuint focalPoint, GLfloat focalX, GLfloat focalY, GLfloat gainX, GLfloat gainY, GLfloat foveaArea);
+#endif
+#endif /* GL_QCOM_texture_foveated */
+
+#ifndef GL_QCOM_texture_foveated_subsampled_layout
+#define GL_QCOM_texture_foveated_subsampled_layout 1
+#define GL_FOVEATION_SUBSAMPLED_LAYOUT_METHOD_BIT_QCOM 0x00000004
+#define GL_MAX_SHADER_SUBSAMPLED_IMAGE_UNITS_QCOM 0x8FA1
+#endif /* GL_QCOM_texture_foveated_subsampled_layout */
+
#ifndef GL_QCOM_tiled_rendering
#define GL_QCOM_tiled_rendering 1
#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
diff --git a/src/gui/opengl/qopenglext.h b/src/gui/opengl/qopenglext.h
index 856adb679e..e3f9205619 100644
--- a/src/gui/opengl/qopenglext.h
+++ b/src/gui/opengl/qopenglext.h
@@ -12,7 +12,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2017 The Khronos Group Inc.
+** Copyright (c) 2013-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -57,7 +57,7 @@ extern "C" {
#define GLAPI extern
#endif
-#define GL_GLEXT_VERSION 20170325
+#define GL_GLEXT_VERSION 20190228
/* Generated C header for:
* API: gl
@@ -359,15 +359,17 @@ GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *m);
#define GL_TEXTURE_FILTER_CONTROL 0x8500
#define GL_DEPTH_TEXTURE_MODE 0x884B
#define GL_COMPARE_R_TO_TEXTURE 0x884E
-#define GL_FUNC_ADD 0x8006
-#define GL_FUNC_SUBTRACT 0x800A
-#define GL_FUNC_REVERSE_SUBTRACT 0x800B
-#define GL_MIN 0x8007
-#define GL_MAX 0x8008
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_EQUATION 0x8009
#define GL_CONSTANT_COLOR 0x8001
#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
#define GL_CONSTANT_ALPHA 0x8003
#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount);
@@ -468,9 +470,14 @@ GLAPI void APIENTRY glBlendEquation (GLenum mode);
#ifndef GL_VERSION_1_5
#define GL_VERSION_1_5 1
-#include <stddef.h>
-typedef ptrdiff_t GLsizeiptr;
-typedef ptrdiff_t GLintptr;
+#ifdef _WIN64
+typedef signed long long int GLsizeiptr;
+typedef signed long long int GLintptr;
+#else
+typedef signed long int GLsizeiptr;
+typedef signed long int GLintptr;
+#endif
+
#define GL_BUFFER_SIZE 0x8764
#define GL_BUFFER_USAGE 0x8765
#define GL_QUERY_COUNTER_BITS 0x8864
@@ -2867,6 +2874,42 @@ GLAPI void APIENTRY glTextureBarrier (void);
#endif
#endif /* GL_VERSION_4_5 */
+#ifndef GL_VERSION_4_6
+#define GL_VERSION_4_6 1
+#define GL_SHADER_BINARY_FORMAT_SPIR_V 0x9551
+#define GL_SPIR_V_BINARY 0x9552
+#define GL_PARAMETER_BUFFER 0x80EE
+#define GL_PARAMETER_BUFFER_BINDING 0x80EF
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008
+#define GL_VERTICES_SUBMITTED 0x82EE
+#define GL_PRIMITIVES_SUBMITTED 0x82EF
+#define GL_VERTEX_SHADER_INVOCATIONS 0x82F0
+#define GL_TESS_CONTROL_SHADER_PATCHES 0x82F1
+#define GL_TESS_EVALUATION_SHADER_INVOCATIONS 0x82F2
+#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED 0x82F3
+#define GL_FRAGMENT_SHADER_INVOCATIONS 0x82F4
+#define GL_COMPUTE_SHADER_INVOCATIONS 0x82F5
+#define GL_CLIPPING_INPUT_PRIMITIVES 0x82F6
+#define GL_CLIPPING_OUTPUT_PRIMITIVES 0x82F7
+#define GL_POLYGON_OFFSET_CLAMP 0x8E1B
+#define GL_SPIR_V_EXTENSIONS 0x9553
+#define GL_NUM_SPIR_V_EXTENSIONS 0x9554
+#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF
+#define GL_TRANSFORM_FEEDBACK_OVERFLOW 0x82EC
+#define GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW 0x82ED
+typedef void (APIENTRYP PFNGLSPECIALIZESHADERPROC) (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC) (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC) (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETCLAMPPROC) (GLfloat factor, GLfloat units, GLfloat clamp);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSpecializeShader (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue);
+GLAPI void APIENTRY glMultiDrawArraysIndirectCount (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirectCount (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+GLAPI void APIENTRY glPolygonOffsetClamp (GLfloat factor, GLfloat units, GLfloat clamp);
+#endif
+#endif /* GL_VERSION_4_6 */
+
#ifndef GL_ARB_ES2_compatibility
#define GL_ARB_ES2_compatibility 1
#endif /* GL_ARB_ES2_compatibility */
@@ -3470,8 +3513,6 @@ typedef unsigned short GLhalfARB;
#ifndef GL_ARB_imaging
#define GL_ARB_imaging 1
-#define GL_BLEND_COLOR 0x8005
-#define GL_BLEND_EQUATION 0x8009
#define GL_CONVOLUTION_1D 0x8010
#define GL_CONVOLUTION_2D 0x8011
#define GL_SEPARABLE_2D 0x8012
@@ -3608,11 +3649,11 @@ GLAPI void APIENTRY glResetMinmax (GLenum target);
#define GL_ARB_indirect_parameters 1
#define GL_PARAMETER_BUFFER_ARB 0x80EE
#define GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF
-typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
-typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
#ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glMultiDrawArraysIndirectCountARB (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
-GLAPI void APIENTRY glMultiDrawElementsIndirectCountARB (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawArraysIndirectCountARB (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirectCountARB (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
#endif
#endif /* GL_ARB_indirect_parameters */
@@ -3632,6 +3673,25 @@ GLAPI void APIENTRY glVertexAttribDivisorARB (GLuint index, GLuint divisor);
#ifndef GL_ARB_internalformat_query2
#define GL_ARB_internalformat_query2 1
#define GL_SRGB_DECODE_ARB 0x8299
+#define GL_VIEW_CLASS_EAC_R11 0x9383
+#define GL_VIEW_CLASS_EAC_RG11 0x9384
+#define GL_VIEW_CLASS_ETC2_RGB 0x9385
+#define GL_VIEW_CLASS_ETC2_RGBA 0x9386
+#define GL_VIEW_CLASS_ETC2_EAC_RGBA 0x9387
+#define GL_VIEW_CLASS_ASTC_4x4_RGBA 0x9388
+#define GL_VIEW_CLASS_ASTC_5x4_RGBA 0x9389
+#define GL_VIEW_CLASS_ASTC_5x5_RGBA 0x938A
+#define GL_VIEW_CLASS_ASTC_6x5_RGBA 0x938B
+#define GL_VIEW_CLASS_ASTC_6x6_RGBA 0x938C
+#define GL_VIEW_CLASS_ASTC_8x5_RGBA 0x938D
+#define GL_VIEW_CLASS_ASTC_8x6_RGBA 0x938E
+#define GL_VIEW_CLASS_ASTC_8x8_RGBA 0x938F
+#define GL_VIEW_CLASS_ASTC_10x5_RGBA 0x9390
+#define GL_VIEW_CLASS_ASTC_10x6_RGBA 0x9391
+#define GL_VIEW_CLASS_ASTC_10x8_RGBA 0x9392
+#define GL_VIEW_CLASS_ASTC_10x10_RGBA 0x9393
+#define GL_VIEW_CLASS_ASTC_12x10_RGBA 0x9394
+#define GL_VIEW_CLASS_ASTC_12x12_RGBA 0x9395
#endif /* GL_ARB_internalformat_query2 */
#ifndef GL_ARB_invalidate_subdata
@@ -3889,6 +3949,10 @@ GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params);
#define GL_COORD_REPLACE_ARB 0x8862
#endif /* GL_ARB_point_sprite */
+#ifndef GL_ARB_polygon_offset_clamp
+#define GL_ARB_polygon_offset_clamp 1
+#endif /* GL_ARB_polygon_offset_clamp */
+
#ifndef GL_ARB_post_depth_coverage
#define GL_ARB_post_depth_coverage 1
#endif /* GL_ARB_post_depth_coverage */
@@ -4287,6 +4351,10 @@ GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xo
#define GL_ARB_sparse_texture_clamp 1
#endif /* GL_ARB_sparse_texture_clamp */
+#ifndef GL_ARB_spirv_extensions
+#define GL_ARB_spirv_extensions 1
+#endif /* GL_ARB_spirv_extensions */
+
#ifndef GL_ARB_stencil_texturing
#define GL_ARB_stencil_texturing 1
#endif /* GL_ARB_stencil_texturing */
@@ -4439,6 +4507,10 @@ GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void
#define GL_DOT3_RGBA_ARB 0x86AF
#endif /* GL_ARB_texture_env_dot3 */
+#ifndef GL_ARB_texture_filter_anisotropic
+#define GL_ARB_texture_filter_anisotropic 1
+#endif /* GL_ARB_texture_filter_anisotropic */
+
#ifndef GL_ARB_texture_filter_minmax
#define GL_ARB_texture_filter_minmax 1
#define GL_TEXTURE_REDUCTION_MODE_ARB 0x9366
@@ -4944,6 +5016,16 @@ GLAPI void APIENTRY glBlendBarrierKHR (void);
#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
#endif /* GL_KHR_no_error */
+#ifndef GL_KHR_parallel_shader_compile
+#define GL_KHR_parallel_shader_compile 1
+#define GL_MAX_SHADER_COMPILER_THREADS_KHR 0x91B0
+#define GL_COMPLETION_STATUS_KHR 0x91B1
+typedef void (APIENTRYP PFNGLMAXSHADERCOMPILERTHREADSKHRPROC) (GLuint count);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMaxShaderCompilerThreadsKHR (GLuint count);
+#endif
+#endif /* GL_KHR_parallel_shader_compile */
+
#ifndef GL_KHR_robust_buffer_access_behavior
#define GL_KHR_robust_buffer_access_behavior 1
#endif /* GL_KHR_robust_buffer_access_behavior */
@@ -5384,6 +5466,22 @@ GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRG
#endif
#endif /* GL_AMD_draw_buffers_blend */
+#ifndef GL_AMD_framebuffer_multisample_advanced
+#define GL_AMD_framebuffer_multisample_advanced 1
+#define GL_RENDERBUFFER_STORAGE_SAMPLES_AMD 0x91B2
+#define GL_MAX_COLOR_FRAMEBUFFER_SAMPLES_AMD 0x91B3
+#define GL_MAX_COLOR_FRAMEBUFFER_STORAGE_SAMPLES_AMD 0x91B4
+#define GL_MAX_DEPTH_STENCIL_FRAMEBUFFER_SAMPLES_AMD 0x91B5
+#define GL_NUM_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B6
+#define GL_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B7
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC) (GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC) (GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRenderbufferStorageMultisampleAdvancedAMD (GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleAdvancedAMD (GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_AMD_framebuffer_multisample_advanced */
+
#ifndef GL_AMD_framebuffer_sample_positions
#define GL_AMD_framebuffer_sample_positions 1
#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F
@@ -5423,6 +5521,10 @@ GLAPI void APIENTRY glGetNamedFramebufferParameterfvAMD (GLuint framebuffer, GLe
#define GL_FLOAT16_MAT4x3_AMD 0x91CD
#endif /* GL_AMD_gpu_shader_half_float */
+#ifndef GL_AMD_gpu_shader_int16
+#define GL_AMD_gpu_shader_int16 1
+#endif /* GL_AMD_gpu_shader_int16 */
+
#ifndef GL_AMD_gpu_shader_int64
#define GL_AMD_gpu_shader_int64 1
typedef int64_t GLint64EXT;
@@ -5644,6 +5746,14 @@ GLAPI void APIENTRY glSetMultisamplefvAMD (GLenum pname, GLuint index, const GLf
#define GL_AMD_shader_explicit_vertex_parameter 1
#endif /* GL_AMD_shader_explicit_vertex_parameter */
+#ifndef GL_AMD_shader_gpu_shader_half_float_fetch
+#define GL_AMD_shader_gpu_shader_half_float_fetch 1
+#endif /* GL_AMD_shader_gpu_shader_half_float_fetch */
+
+#ifndef GL_AMD_shader_image_load_store_lod
+#define GL_AMD_shader_image_load_store_lod 1
+#endif /* GL_AMD_shader_image_load_store_lod */
+
#ifndef GL_AMD_shader_stencil_export
#define GL_AMD_shader_stencil_export 1
#endif /* GL_AMD_shader_stencil_export */
@@ -5683,6 +5793,10 @@ GLAPI void APIENTRY glStencilOpValueAMD (GLenum face, GLuint value);
#endif
#endif /* GL_AMD_stencil_operation_extended */
+#ifndef GL_AMD_texture_gather_bias_lod
+#define GL_AMD_texture_gather_bias_lod 1
+#endif /* GL_AMD_texture_gather_bias_lod */
+
#ifndef GL_AMD_texture_texture4
#define GL_AMD_texture_texture4 1
#endif /* GL_AMD_texture_texture4 */
@@ -6383,6 +6497,17 @@ GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum pname, GLfloat param);
#define GL_422_REV_AVERAGE_EXT 0x80CF
#endif /* GL_EXT_422_pixels */
+#ifndef GL_EXT_EGL_image_storage
+#define GL_EXT_EGL_image_storage 1
+typedef void *GLeglImageOES;
+typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC) (GLenum target, GLeglImageOES image, const GLint* attrib_list);
+typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC) (GLuint texture, GLeglImageOES image, const GLint* attrib_list);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glEGLImageTargetTexStorageEXT (GLenum target, GLeglImageOES image, const GLint* attrib_list);
+GLAPI void APIENTRY glEGLImageTargetTextureStorageEXT (GLuint texture, GLeglImageOES image, const GLint* attrib_list);
+#endif
+#endif /* GL_EXT_EGL_image_storage */
+
#ifndef GL_EXT_abgr
#define GL_EXT_abgr 1
#define GL_ABGR_EXT 0x8000
@@ -7234,6 +7359,17 @@ GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint en
#endif
#endif /* GL_EXT_draw_range_elements */
+#ifndef GL_EXT_external_buffer
+#define GL_EXT_external_buffer 1
+typedef void *GLeglClientBufferEXT;
+typedef void (APIENTRYP PFNGLBUFFERSTORAGEEXTERNALEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferStorageExternalEXT (GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+GLAPI void APIENTRY glNamedBufferStorageExternalEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+#endif
+#endif /* GL_EXT_external_buffer */
+
#ifndef GL_EXT_fog_coord
#define GL_EXT_fog_coord 1
#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
@@ -7577,6 +7713,89 @@ GLAPI void APIENTRY glTextureMaterialEXT (GLenum face, GLenum mode);
#endif
#endif /* GL_EXT_light_texture */
+#ifndef GL_EXT_memory_object
+#define GL_EXT_memory_object 1
+#define GL_TEXTURE_TILING_EXT 0x9580
+#define GL_DEDICATED_MEMORY_OBJECT_EXT 0x9581
+#define GL_PROTECTED_MEMORY_OBJECT_EXT 0x959B
+#define GL_NUM_TILING_TYPES_EXT 0x9582
+#define GL_TILING_TYPES_EXT 0x9583
+#define GL_OPTIMAL_TILING_EXT 0x9584
+#define GL_LINEAR_TILING_EXT 0x9585
+#define GL_NUM_DEVICE_UUIDS_EXT 0x9596
+#define GL_DEVICE_UUID_EXT 0x9597
+#define GL_DRIVER_UUID_EXT 0x9598
+#define GL_UUID_SIZE_EXT 16
+typedef void (APIENTRYP PFNGLGETUNSIGNEDBYTEVEXTPROC) (GLenum pname, GLubyte *data);
+typedef void (APIENTRYP PFNGLGETUNSIGNEDBYTEI_VEXTPROC) (GLenum target, GLuint index, GLubyte *data);
+typedef void (APIENTRYP PFNGLDELETEMEMORYOBJECTSEXTPROC) (GLsizei n, const GLuint *memoryObjects);
+typedef GLboolean (APIENTRYP PFNGLISMEMORYOBJECTEXTPROC) (GLuint memoryObject);
+typedef void (APIENTRYP PFNGLCREATEMEMORYOBJECTSEXTPROC) (GLsizei n, GLuint *memoryObjects);
+typedef void (APIENTRYP PFNGLMEMORYOBJECTPARAMETERIVEXTPROC) (GLuint memoryObject, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC) (GLuint memoryObject, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLTEXSTORAGEMEM2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXSTORAGEMEM3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLBUFFERSTORAGEMEMEXTPROC) (GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGEMEM2DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC) (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGEMEM3DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC) (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC) (GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXSTORAGEMEM1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGEMEM1DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLuint memory, GLuint64 offset);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetUnsignedBytevEXT (GLenum pname, GLubyte *data);
+GLAPI void APIENTRY glGetUnsignedBytei_vEXT (GLenum target, GLuint index, GLubyte *data);
+GLAPI void APIENTRY glDeleteMemoryObjectsEXT (GLsizei n, const GLuint *memoryObjects);
+GLAPI GLboolean APIENTRY glIsMemoryObjectEXT (GLuint memoryObject);
+GLAPI void APIENTRY glCreateMemoryObjectsEXT (GLsizei n, GLuint *memoryObjects);
+GLAPI void APIENTRY glMemoryObjectParameterivEXT (GLuint memoryObject, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glGetMemoryObjectParameterivEXT (GLuint memoryObject, GLenum pname, GLint *params);
+GLAPI void APIENTRY glTexStorageMem2DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTexStorageMem2DMultisampleEXT (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTexStorageMem3DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTexStorageMem3DMultisampleEXT (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glBufferStorageMemEXT (GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTextureStorageMem2DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTextureStorageMem2DMultisampleEXT (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTextureStorageMem3DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTextureStorageMem3DMultisampleEXT (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glNamedBufferStorageMemEXT (GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTexStorageMem1DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTextureStorageMem1DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLuint memory, GLuint64 offset);
+#endif
+#endif /* GL_EXT_memory_object */
+
+#ifndef GL_EXT_memory_object_fd
+#define GL_EXT_memory_object_fd 1
+#define GL_HANDLE_TYPE_OPAQUE_FD_EXT 0x9586
+typedef void (APIENTRYP PFNGLIMPORTMEMORYFDEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, GLint fd);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glImportMemoryFdEXT (GLuint memory, GLuint64 size, GLenum handleType, GLint fd);
+#endif
+#endif /* GL_EXT_memory_object_fd */
+
+#ifndef GL_EXT_memory_object_win32
+#define GL_EXT_memory_object_win32 1
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_EXT 0x9587
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT 0x9588
+#define GL_DEVICE_LUID_EXT 0x9599
+#define GL_DEVICE_NODE_MASK_EXT 0x959A
+#define GL_LUID_SIZE_EXT 8
+#define GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT 0x9589
+#define GL_HANDLE_TYPE_D3D12_RESOURCE_EXT 0x958A
+#define GL_HANDLE_TYPE_D3D11_IMAGE_EXT 0x958B
+#define GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT 0x958C
+typedef void (APIENTRYP PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, void *handle);
+typedef void (APIENTRYP PFNGLIMPORTMEMORYWIN32NAMEEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, const void *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glImportMemoryWin32HandleEXT (GLuint memory, GLuint64 size, GLenum handleType, void *handle);
+GLAPI void APIENTRY glImportMemoryWin32NameEXT (GLuint memory, GLuint64 size, GLenum handleType, const void *name);
+#endif
+#endif /* GL_EXT_memory_object_win32 */
+
#ifndef GL_EXT_misc_attribute
#define GL_EXT_misc_attribute 1
#endif /* GL_EXT_misc_attribute */
@@ -7818,6 +8037,55 @@ GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei
#endif
#endif /* GL_EXT_secondary_color */
+#ifndef GL_EXT_semaphore
+#define GL_EXT_semaphore 1
+#define GL_LAYOUT_GENERAL_EXT 0x958D
+#define GL_LAYOUT_COLOR_ATTACHMENT_EXT 0x958E
+#define GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT 0x958F
+#define GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT 0x9590
+#define GL_LAYOUT_SHADER_READ_ONLY_EXT 0x9591
+#define GL_LAYOUT_TRANSFER_SRC_EXT 0x9592
+#define GL_LAYOUT_TRANSFER_DST_EXT 0x9593
+#define GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT 0x9530
+#define GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT 0x9531
+typedef void (APIENTRYP PFNGLGENSEMAPHORESEXTPROC) (GLsizei n, GLuint *semaphores);
+typedef void (APIENTRYP PFNGLDELETESEMAPHORESEXTPROC) (GLsizei n, const GLuint *semaphores);
+typedef GLboolean (APIENTRYP PFNGLISSEMAPHOREEXTPROC) (GLuint semaphore);
+typedef void (APIENTRYP PFNGLSEMAPHOREPARAMETERUI64VEXTPROC) (GLuint semaphore, GLenum pname, const GLuint64 *params);
+typedef void (APIENTRYP PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC) (GLuint semaphore, GLenum pname, GLuint64 *params);
+typedef void (APIENTRYP PFNGLWAITSEMAPHOREEXTPROC) (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts);
+typedef void (APIENTRYP PFNGLSIGNALSEMAPHOREEXTPROC) (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *dstLayouts);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenSemaphoresEXT (GLsizei n, GLuint *semaphores);
+GLAPI void APIENTRY glDeleteSemaphoresEXT (GLsizei n, const GLuint *semaphores);
+GLAPI GLboolean APIENTRY glIsSemaphoreEXT (GLuint semaphore);
+GLAPI void APIENTRY glSemaphoreParameterui64vEXT (GLuint semaphore, GLenum pname, const GLuint64 *params);
+GLAPI void APIENTRY glGetSemaphoreParameterui64vEXT (GLuint semaphore, GLenum pname, GLuint64 *params);
+GLAPI void APIENTRY glWaitSemaphoreEXT (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts);
+GLAPI void APIENTRY glSignalSemaphoreEXT (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *dstLayouts);
+#endif
+#endif /* GL_EXT_semaphore */
+
+#ifndef GL_EXT_semaphore_fd
+#define GL_EXT_semaphore_fd 1
+typedef void (APIENTRYP PFNGLIMPORTSEMAPHOREFDEXTPROC) (GLuint semaphore, GLenum handleType, GLint fd);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glImportSemaphoreFdEXT (GLuint semaphore, GLenum handleType, GLint fd);
+#endif
+#endif /* GL_EXT_semaphore_fd */
+
+#ifndef GL_EXT_semaphore_win32
+#define GL_EXT_semaphore_win32 1
+#define GL_HANDLE_TYPE_D3D12_FENCE_EXT 0x9594
+#define GL_D3D12_FENCE_VALUE_EXT 0x9595
+typedef void (APIENTRYP PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC) (GLuint semaphore, GLenum handleType, void *handle);
+typedef void (APIENTRYP PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC) (GLuint semaphore, GLenum handleType, const void *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glImportSemaphoreWin32HandleEXT (GLuint semaphore, GLenum handleType, void *handle);
+GLAPI void APIENTRY glImportSemaphoreWin32NameEXT (GLuint semaphore, GLenum handleType, const void *name);
+#endif
+#endif /* GL_EXT_semaphore_win32 */
+
#ifndef GL_EXT_separate_shader_objects
#define GL_EXT_separate_shader_objects 1
#define GL_ACTIVE_PROGRAM_EXT 0x8B8D
@@ -7838,6 +8106,19 @@ GLAPI GLuint APIENTRY glCreateShaderProgramEXT (GLenum type, const GLchar *strin
#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
#endif /* GL_EXT_separate_specular_color */
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_EXT_shader_framebuffer_fetch 1
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+#endif /* GL_EXT_shader_framebuffer_fetch */
+
+#ifndef GL_EXT_shader_framebuffer_fetch_non_coherent
+#define GL_EXT_shader_framebuffer_fetch_non_coherent 1
+typedef void (APIENTRYP PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFramebufferFetchBarrierEXT (void);
+#endif
+#endif /* GL_EXT_shader_framebuffer_fetch_non_coherent */
+
#ifndef GL_EXT_shader_image_load_formatted
#define GL_EXT_shader_image_load_formatted 1
#endif /* GL_EXT_shader_image_load_formatted */
@@ -8138,6 +8419,8 @@ GLAPI void APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint
#ifndef GL_EXT_texture_filter_minmax
#define GL_EXT_texture_filter_minmax 1
+#define GL_TEXTURE_REDUCTION_MODE_EXT 0x9366
+#define GL_WEIGHTED_AVERAGE_EXT 0x9367
#endif /* GL_EXT_texture_filter_minmax */
#ifndef GL_EXT_texture_integer
@@ -8272,6 +8555,11 @@ GLAPI void APIENTRY glTextureNormalEXT (GLenum mode);
#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
#endif /* GL_EXT_texture_sRGB */
+#ifndef GL_EXT_texture_sRGB_R8
+#define GL_EXT_texture_sRGB_R8 1
+#define GL_SR8_EXT 0x8FBD
+#endif /* GL_EXT_texture_sRGB_R8 */
+
#ifndef GL_EXT_texture_sRGB_decode
#define GL_EXT_texture_sRGB_decode 1
#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
@@ -8684,6 +8972,16 @@ GLAPI void APIENTRY glVertexWeightPointerEXT (GLint size, GLenum type, GLsizei s
#endif
#endif /* GL_EXT_vertex_weighting */
+#ifndef GL_EXT_win32_keyed_mutex
+#define GL_EXT_win32_keyed_mutex 1
+typedef GLboolean (APIENTRYP PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC) (GLuint memory, GLuint64 key, GLuint timeout);
+typedef GLboolean (APIENTRYP PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC) (GLuint memory, GLuint64 key);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAcquireKeyedMutexWin32EXT (GLuint memory, GLuint64 key, GLuint timeout);
+GLAPI GLboolean APIENTRY glReleaseKeyedMutexWin32EXT (GLuint memory, GLuint64 key);
+#endif
+#endif /* GL_EXT_win32_keyed_mutex */
+
#ifndef GL_EXT_window_rectangles
#define GL_EXT_window_rectangles 1
#define GL_INCLUSIVE_EXT 0x8F10
@@ -8875,6 +9173,11 @@ GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRG
#define GL_INTERLACE_READ_INGR 0x8568
#endif /* GL_INGR_interlace_read */
+#ifndef GL_INTEL_blackhole_render
+#define GL_INTEL_blackhole_render 1
+#define GL_BLACKHOLE_RENDER_INTEL 0x83FC
+#endif /* GL_INTEL_blackhole_render */
+
#ifndef GL_INTEL_conservative_rasterization
#define GL_INTEL_conservative_rasterization 1
#define GL_CONSERVATIVE_RASTERIZATION_INTEL 0x83FE
@@ -8956,7 +9259,7 @@ typedef void (APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle);
typedef void (APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId);
typedef void (APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId);
typedef void (APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
-typedef void (APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+typedef void (APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, void *data, GLuint *bytesWritten);
typedef void (APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId);
typedef void (APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
#ifdef GL_GLEXT_PROTOTYPES
@@ -8967,7 +9270,7 @@ GLAPI void APIENTRY glEndPerfQueryINTEL (GLuint queryHandle);
GLAPI void APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId);
GLAPI void APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId);
GLAPI void APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
-GLAPI void APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+GLAPI void APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, void *data, GLuint *bytesWritten);
GLAPI void APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId);
GLAPI void APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
#endif
@@ -8988,6 +9291,11 @@ GLAPI void APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLen
#define GL_PACK_INVERT_MESA 0x8758
#endif /* GL_MESA_pack_invert */
+#ifndef GL_MESA_program_binary_formats
+#define GL_MESA_program_binary_formats 1
+#define GL_PROGRAM_BINARY_FORMAT_MESA 0x875F
+#endif /* GL_MESA_program_binary_formats */
+
#ifndef GL_MESA_resize_buffers
#define GL_MESA_resize_buffers 1
typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void);
@@ -9000,6 +9308,13 @@ GLAPI void APIENTRY glResizeBuffersMESA (void);
#define GL_MESA_shader_integer_functions 1
#endif /* GL_MESA_shader_integer_functions */
+#ifndef GL_MESA_tile_raster_order
+#define GL_MESA_tile_raster_order 1
+#define GL_TILE_RASTER_ORDER_FIXED_MESA 0x8BB8
+#define GL_TILE_RASTER_ORDER_INCREASING_X_MESA 0x8BB9
+#define GL_TILE_RASTER_ORDER_INCREASING_Y_MESA 0x8BBA
+#endif /* GL_MESA_tile_raster_order */
+
#ifndef GL_MESA_window_pos
#define GL_MESA_window_pos 1
typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
@@ -9226,6 +9541,10 @@ GLAPI void APIENTRY glBlendBarrierNV (void);
#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285
#endif /* GL_NV_blend_equation_advanced_coherent */
+#ifndef GL_NV_blend_minmax_factor
+#define GL_NV_blend_minmax_factor 1
+#endif /* GL_NV_blend_minmax_factor */
+
#ifndef GL_NV_blend_square
#define GL_NV_blend_square 1
#endif /* GL_NV_blend_square */
@@ -9306,6 +9625,10 @@ GLAPI void APIENTRY glCallCommandListNV (GLuint list);
#define GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC
#endif /* GL_NV_compute_program5 */
+#ifndef GL_NV_compute_shader_derivatives
+#define GL_NV_compute_shader_derivatives 1
+#endif /* GL_NV_compute_shader_derivatives */
+
#ifndef GL_NV_conditional_render
#define GL_NV_conditional_render 1
#define GL_QUERY_WAIT_NV 0x8E13
@@ -9343,6 +9666,11 @@ GLAPI void APIENTRY glConservativeRasterParameterfNV (GLenum pname, GLfloat valu
#endif
#endif /* GL_NV_conservative_raster_dilate */
+#ifndef GL_NV_conservative_raster_pre_snap
+#define GL_NV_conservative_raster_pre_snap 1
+#define GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_NV 0x9550
+#endif /* GL_NV_conservative_raster_pre_snap */
+
#ifndef GL_NV_conservative_raster_pre_snap_triangles
#define GL_NV_conservative_raster_pre_snap_triangles 1
#define GL_CONSERVATIVE_RASTER_MODE_NV 0x954D
@@ -9354,6 +9682,10 @@ GLAPI void APIENTRY glConservativeRasterParameteriNV (GLenum pname, GLint param)
#endif
#endif /* GL_NV_conservative_raster_pre_snap_triangles */
+#ifndef GL_NV_conservative_raster_underestimation
+#define GL_NV_conservative_raster_underestimation 1
+#endif /* GL_NV_conservative_raster_underestimation */
+
#ifndef GL_NV_copy_depth_to_color
#define GL_NV_copy_depth_to_color 1
#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
@@ -9595,6 +9927,10 @@ GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, cons
#define GL_NV_fragment_program_option 1
#endif /* GL_NV_fragment_program_option */
+#ifndef GL_NV_fragment_shader_barycentric
+#define GL_NV_fragment_shader_barycentric 1
+#endif /* GL_NV_fragment_shader_barycentric */
+
#ifndef GL_NV_fragment_shader_interlock
#define GL_NV_fragment_shader_interlock 1
#endif /* GL_NV_fragment_shader_interlock */
@@ -9662,7 +9998,7 @@ GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachmen
#define GL_PER_GPU_STORAGE_NV 0x9548
#define GL_MULTICAST_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9549
typedef void (APIENTRYP PFNGLRENDERGPUMASKNVPROC) (GLbitfield mask);
-typedef void (APIENTRYP PFNGLMULTICASTBUFFERSUBDATANVPROC) (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+typedef void (APIENTRYP PFNGLMULTICASTBUFFERSUBDATANVPROC) (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
typedef void (APIENTRYP PFNGLMULTICASTCOPYBUFFERSUBDATANVPROC) (GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
typedef void (APIENTRYP PFNGLMULTICASTCOPYIMAGESUBDATANVPROC) (GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
typedef void (APIENTRYP PFNGLMULTICASTBLITFRAMEBUFFERNVPROC) (GLuint srcGpu, GLuint dstGpu, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
@@ -9675,7 +10011,7 @@ typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTI64VNVPROC) (GLuint gpu, GLu
typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTUI64VNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLuint64 *params);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glRenderGpuMaskNV (GLbitfield mask);
-GLAPI void APIENTRY glMulticastBufferSubDataNV (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+GLAPI void APIENTRY glMulticastBufferSubDataNV (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
GLAPI void APIENTRY glMulticastCopyBufferSubDataNV (GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
GLAPI void APIENTRY glMulticastCopyImageSubDataNV (GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
GLAPI void APIENTRY glMulticastBlitFramebufferNV (GLuint srcGpu, GLuint dstGpu, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
@@ -9879,6 +10215,96 @@ GLAPI void APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum interna
#define GL_MAX_SPOT_EXPONENT_NV 0x8505
#endif /* GL_NV_light_max_exponent */
+#ifndef GL_NV_memory_attachment
+#define GL_NV_memory_attachment 1
+#define GL_ATTACHED_MEMORY_OBJECT_NV 0x95A4
+#define GL_ATTACHED_MEMORY_OFFSET_NV 0x95A5
+#define GL_MEMORY_ATTACHABLE_ALIGNMENT_NV 0x95A6
+#define GL_MEMORY_ATTACHABLE_SIZE_NV 0x95A7
+#define GL_MEMORY_ATTACHABLE_NV 0x95A8
+#define GL_DETACHED_MEMORY_INCARNATION_NV 0x95A9
+#define GL_DETACHED_TEXTURES_NV 0x95AA
+#define GL_DETACHED_BUFFERS_NV 0x95AB
+#define GL_MAX_DETACHED_TEXTURES_NV 0x95AC
+#define GL_MAX_DETACHED_BUFFERS_NV 0x95AD
+typedef void (APIENTRYP PFNGLGETMEMORYOBJECTDETACHEDRESOURCESUIVNVPROC) (GLuint memory, GLenum pname, GLint first, GLsizei count, GLuint *params);
+typedef void (APIENTRYP PFNGLRESETMEMORYOBJECTPARAMETERNVPROC) (GLuint memory, GLenum pname);
+typedef void (APIENTRYP PFNGLTEXATTACHMEMORYNVPROC) (GLenum target, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLBUFFERATTACHMEMORYNVPROC) (GLenum target, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXTUREATTACHMEMORYNVPROC) (GLuint texture, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERATTACHMEMORYNVPROC) (GLuint buffer, GLuint memory, GLuint64 offset);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetMemoryObjectDetachedResourcesuivNV (GLuint memory, GLenum pname, GLint first, GLsizei count, GLuint *params);
+GLAPI void APIENTRY glResetMemoryObjectParameterNV (GLuint memory, GLenum pname);
+GLAPI void APIENTRY glTexAttachMemoryNV (GLenum target, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glBufferAttachMemoryNV (GLenum target, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTextureAttachMemoryNV (GLuint texture, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glNamedBufferAttachMemoryNV (GLuint buffer, GLuint memory, GLuint64 offset);
+#endif
+#endif /* GL_NV_memory_attachment */
+
+#ifndef GL_NV_mesh_shader
+#define GL_NV_mesh_shader 1
+#define GL_MESH_SHADER_NV 0x9559
+#define GL_TASK_SHADER_NV 0x955A
+#define GL_MAX_MESH_UNIFORM_BLOCKS_NV 0x8E60
+#define GL_MAX_MESH_TEXTURE_IMAGE_UNITS_NV 0x8E61
+#define GL_MAX_MESH_IMAGE_UNIFORMS_NV 0x8E62
+#define GL_MAX_MESH_UNIFORM_COMPONENTS_NV 0x8E63
+#define GL_MAX_MESH_ATOMIC_COUNTER_BUFFERS_NV 0x8E64
+#define GL_MAX_MESH_ATOMIC_COUNTERS_NV 0x8E65
+#define GL_MAX_MESH_SHADER_STORAGE_BLOCKS_NV 0x8E66
+#define GL_MAX_COMBINED_MESH_UNIFORM_COMPONENTS_NV 0x8E67
+#define GL_MAX_TASK_UNIFORM_BLOCKS_NV 0x8E68
+#define GL_MAX_TASK_TEXTURE_IMAGE_UNITS_NV 0x8E69
+#define GL_MAX_TASK_IMAGE_UNIFORMS_NV 0x8E6A
+#define GL_MAX_TASK_UNIFORM_COMPONENTS_NV 0x8E6B
+#define GL_MAX_TASK_ATOMIC_COUNTER_BUFFERS_NV 0x8E6C
+#define GL_MAX_TASK_ATOMIC_COUNTERS_NV 0x8E6D
+#define GL_MAX_TASK_SHADER_STORAGE_BLOCKS_NV 0x8E6E
+#define GL_MAX_COMBINED_TASK_UNIFORM_COMPONENTS_NV 0x8E6F
+#define GL_MAX_MESH_WORK_GROUP_INVOCATIONS_NV 0x95A2
+#define GL_MAX_TASK_WORK_GROUP_INVOCATIONS_NV 0x95A3
+#define GL_MAX_MESH_TOTAL_MEMORY_SIZE_NV 0x9536
+#define GL_MAX_TASK_TOTAL_MEMORY_SIZE_NV 0x9537
+#define GL_MAX_MESH_OUTPUT_VERTICES_NV 0x9538
+#define GL_MAX_MESH_OUTPUT_PRIMITIVES_NV 0x9539
+#define GL_MAX_TASK_OUTPUT_COUNT_NV 0x953A
+#define GL_MAX_DRAW_MESH_TASKS_COUNT_NV 0x953D
+#define GL_MAX_MESH_VIEWS_NV 0x9557
+#define GL_MESH_OUTPUT_PER_VERTEX_GRANULARITY_NV 0x92DF
+#define GL_MESH_OUTPUT_PER_PRIMITIVE_GRANULARITY_NV 0x9543
+#define GL_MAX_MESH_WORK_GROUP_SIZE_NV 0x953B
+#define GL_MAX_TASK_WORK_GROUP_SIZE_NV 0x953C
+#define GL_MESH_WORK_GROUP_SIZE_NV 0x953E
+#define GL_TASK_WORK_GROUP_SIZE_NV 0x953F
+#define GL_MESH_VERTICES_OUT_NV 0x9579
+#define GL_MESH_PRIMITIVES_OUT_NV 0x957A
+#define GL_MESH_OUTPUT_TYPE_NV 0x957B
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_MESH_SHADER_NV 0x959C
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TASK_SHADER_NV 0x959D
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_MESH_SHADER_NV 0x959E
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TASK_SHADER_NV 0x959F
+#define GL_REFERENCED_BY_MESH_SHADER_NV 0x95A0
+#define GL_REFERENCED_BY_TASK_SHADER_NV 0x95A1
+#define GL_MESH_SUBROUTINE_NV 0x957C
+#define GL_TASK_SUBROUTINE_NV 0x957D
+#define GL_MESH_SUBROUTINE_UNIFORM_NV 0x957E
+#define GL_TASK_SUBROUTINE_UNIFORM_NV 0x957F
+#define GL_MESH_SHADER_BIT_NV 0x00000040
+#define GL_TASK_SHADER_BIT_NV 0x00000080
+typedef void (APIENTRYP PFNGLDRAWMESHTASKSNVPROC) (GLuint first, GLuint count);
+typedef void (APIENTRYP PFNGLDRAWMESHTASKSINDIRECTNVPROC) (GLintptr indirect);
+typedef void (APIENTRYP PFNGLMULTIDRAWMESHTASKSINDIRECTNVPROC) (GLintptr indirect, GLsizei drawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWMESHTASKSINDIRECTCOUNTNVPROC) (GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawMeshTasksNV (GLuint first, GLuint count);
+GLAPI void APIENTRY glDrawMeshTasksIndirectNV (GLintptr indirect);
+GLAPI void APIENTRY glMultiDrawMeshTasksIndirectNV (GLintptr indirect, GLsizei drawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawMeshTasksIndirectCountNV (GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+#endif
+#endif /* GL_NV_mesh_shader */
+
#ifndef GL_NV_multisample_coverage
#define GL_NV_multisample_coverage 1
#endif /* GL_NV_multisample_coverage */
@@ -10306,6 +10732,32 @@ GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint index);
#endif
#endif /* GL_NV_primitive_restart */
+#ifndef GL_NV_query_resource
+#define GL_NV_query_resource 1
+#define GL_QUERY_RESOURCE_TYPE_VIDMEM_ALLOC_NV 0x9540
+#define GL_QUERY_RESOURCE_MEMTYPE_VIDMEM_NV 0x9542
+#define GL_QUERY_RESOURCE_SYS_RESERVED_NV 0x9544
+#define GL_QUERY_RESOURCE_TEXTURE_NV 0x9545
+#define GL_QUERY_RESOURCE_RENDERBUFFER_NV 0x9546
+#define GL_QUERY_RESOURCE_BUFFEROBJECT_NV 0x9547
+typedef GLint (APIENTRYP PFNGLQUERYRESOURCENVPROC) (GLenum queryType, GLint tagId, GLuint bufSize, GLint *buffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLint APIENTRY glQueryResourceNV (GLenum queryType, GLint tagId, GLuint bufSize, GLint *buffer);
+#endif
+#endif /* GL_NV_query_resource */
+
+#ifndef GL_NV_query_resource_tag
+#define GL_NV_query_resource_tag 1
+typedef void (APIENTRYP PFNGLGENQUERYRESOURCETAGNVPROC) (GLsizei n, GLint *tagIds);
+typedef void (APIENTRYP PFNGLDELETEQUERYRESOURCETAGNVPROC) (GLsizei n, const GLint *tagIds);
+typedef void (APIENTRYP PFNGLQUERYRESOURCETAGNVPROC) (GLint tagId, const GLchar *tagString);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueryResourceTagNV (GLsizei n, GLint *tagIds);
+GLAPI void APIENTRY glDeleteQueryResourceTagNV (GLsizei n, const GLint *tagIds);
+GLAPI void APIENTRY glQueryResourceTagNV (GLint tagId, const GLchar *tagString);
+#endif
+#endif /* GL_NV_query_resource_tag */
+
#ifndef GL_NV_register_combiners
#define GL_NV_register_combiners 1
#define GL_REGISTER_COMBINERS_NV 0x8522
@@ -10398,6 +10850,11 @@ GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname,
#endif
#endif /* GL_NV_register_combiners2 */
+#ifndef GL_NV_representative_fragment_test
+#define GL_NV_representative_fragment_test 1
+#define GL_REPRESENTATIVE_FRAGMENT_TEST_NV 0x937F
+#endif /* GL_NV_representative_fragment_test */
+
#ifndef GL_NV_robustness_video_memory_purge
#define GL_NV_robustness_video_memory_purge 1
#define GL_PURGED_CONTEXT_RESET_NV 0x92BB
@@ -10427,6 +10884,18 @@ GLAPI void APIENTRY glResolveDepthValuesNV (void);
#define GL_NV_sample_mask_override_coverage 1
#endif /* GL_NV_sample_mask_override_coverage */
+#ifndef GL_NV_scissor_exclusive
+#define GL_NV_scissor_exclusive 1
+#define GL_SCISSOR_TEST_EXCLUSIVE_NV 0x9555
+#define GL_SCISSOR_BOX_EXCLUSIVE_NV 0x9556
+typedef void (APIENTRYP PFNGLSCISSOREXCLUSIVENVPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLSCISSOREXCLUSIVEARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glScissorExclusiveNV (GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glScissorExclusiveArrayvNV (GLuint first, GLsizei count, const GLint *v);
+#endif
+#endif /* GL_NV_scissor_exclusive */
+
#ifndef GL_NV_shader_atomic_counters
#define GL_NV_shader_atomic_counters 1
#endif /* GL_NV_shader_atomic_counters */
@@ -10491,6 +10960,10 @@ GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLs
#define GL_NV_shader_storage_buffer_object 1
#endif /* GL_NV_shader_storage_buffer_object */
+#ifndef GL_NV_shader_texture_footprint
+#define GL_NV_shader_texture_footprint 1
+#endif /* GL_NV_shader_texture_footprint */
+
#ifndef GL_NV_shader_thread_group
#define GL_NV_shader_thread_group 1
#define GL_WARP_SIZE_NV 0x9339
@@ -10502,6 +10975,47 @@ GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLs
#define GL_NV_shader_thread_shuffle 1
#endif /* GL_NV_shader_thread_shuffle */
+#ifndef GL_NV_shading_rate_image
+#define GL_NV_shading_rate_image 1
+#define GL_SHADING_RATE_IMAGE_NV 0x9563
+#define GL_SHADING_RATE_NO_INVOCATIONS_NV 0x9564
+#define GL_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV 0x9565
+#define GL_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV 0x9566
+#define GL_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV 0x9567
+#define GL_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV 0x9568
+#define GL_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV 0x9569
+#define GL_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV 0x956A
+#define GL_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV 0x956B
+#define GL_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV 0x956C
+#define GL_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV 0x956D
+#define GL_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV 0x956E
+#define GL_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV 0x956F
+#define GL_SHADING_RATE_IMAGE_BINDING_NV 0x955B
+#define GL_SHADING_RATE_IMAGE_TEXEL_WIDTH_NV 0x955C
+#define GL_SHADING_RATE_IMAGE_TEXEL_HEIGHT_NV 0x955D
+#define GL_SHADING_RATE_IMAGE_PALETTE_SIZE_NV 0x955E
+#define GL_MAX_COARSE_FRAGMENT_SAMPLES_NV 0x955F
+#define GL_SHADING_RATE_SAMPLE_ORDER_DEFAULT_NV 0x95AE
+#define GL_SHADING_RATE_SAMPLE_ORDER_PIXEL_MAJOR_NV 0x95AF
+#define GL_SHADING_RATE_SAMPLE_ORDER_SAMPLE_MAJOR_NV 0x95B0
+typedef void (APIENTRYP PFNGLBINDSHADINGRATEIMAGENVPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLGETSHADINGRATEIMAGEPALETTENVPROC) (GLuint viewport, GLuint entry, GLenum *rate);
+typedef void (APIENTRYP PFNGLGETSHADINGRATESAMPLELOCATIONIVNVPROC) (GLenum rate, GLuint samples, GLuint index, GLint *location);
+typedef void (APIENTRYP PFNGLSHADINGRATEIMAGEBARRIERNVPROC) (GLboolean synchronize);
+typedef void (APIENTRYP PFNGLSHADINGRATEIMAGEPALETTENVPROC) (GLuint viewport, GLuint first, GLsizei count, const GLenum *rates);
+typedef void (APIENTRYP PFNGLSHADINGRATESAMPLEORDERNVPROC) (GLenum order);
+typedef void (APIENTRYP PFNGLSHADINGRATESAMPLEORDERCUSTOMNVPROC) (GLenum rate, GLuint samples, const GLint *locations);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindShadingRateImageNV (GLuint texture);
+GLAPI void APIENTRY glGetShadingRateImagePaletteNV (GLuint viewport, GLuint entry, GLenum *rate);
+GLAPI void APIENTRY glGetShadingRateSampleLocationivNV (GLenum rate, GLuint samples, GLuint index, GLint *location);
+GLAPI void APIENTRY glShadingRateImageBarrierNV (GLboolean synchronize);
+GLAPI void APIENTRY glShadingRateImagePaletteNV (GLuint viewport, GLuint first, GLsizei count, const GLenum *rates);
+GLAPI void APIENTRY glShadingRateSampleOrderNV (GLenum order);
+GLAPI void APIENTRY glShadingRateSampleOrderCustomNV (GLenum rate, GLuint samples, const GLint *locations);
+#endif
+#endif /* GL_NV_shading_rate_image */
+
#ifndef GL_NV_stereo_view_rendering
#define GL_NV_stereo_view_rendering 1
#endif /* GL_NV_stereo_view_rendering */
@@ -10582,6 +11096,10 @@ GLAPI void APIENTRY glTextureImage3DMultisampleCoverageNV (GLuint texture, GLenu
#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8
#endif /* GL_NV_texture_rectangle */
+#ifndef GL_NV_texture_rectangle_compressed
+#define GL_NV_texture_rectangle_compressed 1
+#endif /* GL_NV_texture_rectangle_compressed */
+
#ifndef GL_NV_texture_shader
#define GL_NV_texture_shader 1
#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C
@@ -10808,6 +11326,14 @@ GLAPI void APIENTRY glVDPAUUnmapSurfacesNV (GLsizei numSurface, const GLvdpauSur
#endif
#endif /* GL_NV_vdpau_interop */
+#ifndef GL_NV_vdpau_interop2
+#define GL_NV_vdpau_interop2 1
+typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACEWITHPICTURESTRUCTURENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames, GLboolean isFrameStructure);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceWithPictureStructureNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames, GLboolean isFrameStructure);
+#endif
+#endif /* GL_NV_vdpau_interop2 */
+
#ifndef GL_NV_vertex_array_range
#define GL_NV_vertex_array_range 1
#define GL_VERTEX_ARRAY_RANGE_NV 0x851D
diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h
index af8ee8201d..137f1e831f 100644
--- a/src/gui/opengl/qopenglextensions_p.h
+++ b/src/gui/opengl/qopenglextensions_p.h
@@ -107,7 +107,7 @@ public:
QOpenGLExtensionsPrivate *d() const;
private:
- static bool isInitialized(const QOpenGLFunctionsPrivate *d) { return d != 0; }
+ static bool isInitialized(const QOpenGLFunctionsPrivate *d) { return d != nullptr; }
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLExtensions::OpenGLExtensions)
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index cae3d516c4..5d30891565 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -183,7 +183,7 @@ QT_BEGIN_NAMESPACE
*/
void QOpenGLFramebufferObjectFormat::detach()
{
- if (d->ref.load() != 1) {
+ if (d->ref.loadRelaxed() != 1) {
QOpenGLFramebufferObjectFormatPrivate *newd
= new QOpenGLFramebufferObjectFormatPrivate(d);
if (!d->ref.deref())
@@ -249,7 +249,7 @@ QOpenGLFramebufferObjectFormat::~QOpenGLFramebufferObjectFormat()
If the desired amount of samples per pixel is not supported by the hardware
then the maximum number of samples per pixel will be used. Note that
- multisample framebuffer objects can not be bound as textures. Also, the
+ multisample framebuffer objects cannot be bound as textures. Also, the
\c{GL_EXT_framebuffer_multisample} extension is required to create a
framebuffer with more than one sample per pixel.
diff --git a/src/gui/opengl/qopenglframebufferobject_p.h b/src/gui/opengl/qopenglframebufferobject_p.h
index 778a38b823..644bb6c59b 100644
--- a/src/gui/opengl/qopenglframebufferobject_p.h
+++ b/src/gui/opengl/qopenglframebufferobject_p.h
@@ -109,8 +109,8 @@ public:
class QOpenGLFramebufferObjectPrivate
{
public:
- QOpenGLFramebufferObjectPrivate() : fbo_guard(0), depth_buffer_guard(0)
- , stencil_buffer_guard(0)
+ QOpenGLFramebufferObjectPrivate() : fbo_guard(nullptr), depth_buffer_guard(nullptr)
+ , stencil_buffer_guard(nullptr)
, valid(false) {}
~QOpenGLFramebufferObjectPrivate() {}
@@ -135,9 +135,9 @@ public:
QOpenGLExtensions funcs;
struct ColorAttachment {
- ColorAttachment() : internalFormat(0), guard(0) { }
+ ColorAttachment() : internalFormat(0), guard(nullptr) { }
ColorAttachment(const QSize &size, GLenum internalFormat)
- : size(size), internalFormat(internalFormat), guard(0) { }
+ : size(size), internalFormat(internalFormat), guard(nullptr) { }
QSize size;
GLenum internalFormat;
QOpenGLSharedResourceGuard *guard;
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index 92770cb55f..8ec814296a 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -206,7 +206,8 @@ QOpenGLFunctions::QOpenGLFunctions()
/*!
Constructs a function resolver for \a context. If \a context
- is null, then the resolver will be created for the current QOpenGLContext.
+ is \nullptr, then the resolver will be created for the current
+ QOpenGLContext.
The context or another context in the group must be current.
@@ -5035,8 +5036,8 @@ QOpenGLExtraFunctions::QOpenGLExtraFunctions()
}
/*!
- Constructs a function resolver for context. If \a context is null, then
- the resolver will be created for the current QOpenGLContext.
+ Constructs a function resolver for context. If \a context is \nullptr,
+ then the resolver will be created for the current QOpenGLContext.
The context or another context in the group must be current.
diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h
index 00287b0665..4554291bbd 100644
--- a/src/gui/opengl/qopenglfunctions.h
+++ b/src/gui/opengl/qopenglfunctions.h
@@ -228,26 +228,8 @@ struct QOpenGLFunctionsPrivate;
#undef glTexLevelParameteriv
#if defined(Q_CLANG_QDOC)
-#undef GLint
-typedef int GLint;
-#undef GLsizei
-typedef int GLsizei;
-#undef GLuint
-typedef unsigned int GLuint;
-#undef GLubyte
-typedef unsigned int GLubyte;
-#undef GLenum
-typedef unsigned int GLenum;
#undef GLbitfield
typedef unsigned int GLbitfield;
-#undef GLfloat
-typedef float GLfloat;
-#undef GLclampf
-typedef float GLclampf;
-#undef GLboolean
-typedef bool GLboolean;
-#undef GLvoid
-typedef void GLvoid;
#undef GLchar
typedef char GLchar;
#endif
diff --git a/src/gui/opengl/qopenglfunctions_1_0.cpp b/src/gui/opengl/qopenglfunctions_1_0.cpp
index 4235c9a339..f017c68fd9 100644
--- a/src/gui/opengl/qopenglfunctions_1_0.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_0.cpp
@@ -76,11 +76,11 @@ QOpenGLFunctions_1_0::~QOpenGLFunctions_1_0()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_1_1.cpp b/src/gui/opengl/qopenglfunctions_1_1.cpp
index 7d09bb40c1..a819d499f8 100644
--- a/src/gui/opengl/qopenglfunctions_1_1.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_1.cpp
@@ -78,19 +78,19 @@ QOpenGLFunctions_1_1::~QOpenGLFunctions_1_1()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_1_2.cpp b/src/gui/opengl/qopenglfunctions_1_2.cpp
index 94a9d64660..61db2b4e0f 100644
--- a/src/gui/opengl/qopenglfunctions_1_2.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_2.cpp
@@ -80,27 +80,27 @@ QOpenGLFunctions_1_2::~QOpenGLFunctions_1_2()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_1_3.cpp b/src/gui/opengl/qopenglfunctions_1_3.cpp
index 972ef9ff70..acc223ea74 100644
--- a/src/gui/opengl/qopenglfunctions_1_3.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_3.cpp
@@ -82,35 +82,35 @@ QOpenGLFunctions_1_3::~QOpenGLFunctions_1_3()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_1_4.cpp b/src/gui/opengl/qopenglfunctions_1_4.cpp
index 4b78253301..8e2349dc08 100644
--- a/src/gui/opengl/qopenglfunctions_1_4.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_4.cpp
@@ -84,43 +84,43 @@ QOpenGLFunctions_1_4::~QOpenGLFunctions_1_4()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_1_5.cpp b/src/gui/opengl/qopenglfunctions_1_5.cpp
index 2a0820d0cb..cd81cf8b35 100644
--- a/src/gui/opengl/qopenglfunctions_1_5.cpp
+++ b/src/gui/opengl/qopenglfunctions_1_5.cpp
@@ -85,47 +85,47 @@ QOpenGLFunctions_1_5::~QOpenGLFunctions_1_5()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_2_0.cpp b/src/gui/opengl/qopenglfunctions_2_0.cpp
index 212723aa00..97a8c72fa6 100644
--- a/src/gui/opengl/qopenglfunctions_2_0.cpp
+++ b/src/gui/opengl/qopenglfunctions_2_0.cpp
@@ -87,51 +87,51 @@ QOpenGLFunctions_2_0::~QOpenGLFunctions_2_0()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_2_1.cpp b/src/gui/opengl/qopenglfunctions_2_1.cpp
index b8b255014c..00bdc1bbba 100644
--- a/src/gui/opengl/qopenglfunctions_2_1.cpp
+++ b/src/gui/opengl/qopenglfunctions_2_1.cpp
@@ -88,55 +88,55 @@ QOpenGLFunctions_2_1::~QOpenGLFunctions_2_1()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_3_0.cpp b/src/gui/opengl/qopenglfunctions_3_0.cpp
index 4972c03b1e..2c239dba1f 100644
--- a/src/gui/opengl/qopenglfunctions_3_0.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_0.cpp
@@ -90,59 +90,59 @@ QOpenGLFunctions_3_0::~QOpenGLFunctions_3_0()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_3_1.cpp b/src/gui/opengl/qopenglfunctions_3_1.cpp
index 9328f5ca89..f62f555c8e 100644
--- a/src/gui/opengl/qopenglfunctions_3_1.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_1.cpp
@@ -84,43 +84,43 @@ QOpenGLFunctions_3_1::~QOpenGLFunctions_3_1()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_3_2_compatibility.cpp b/src/gui/opengl/qopenglfunctions_3_2_compatibility.cpp
index 709f65edf8..ba7be2d893 100644
--- a/src/gui/opengl/qopenglfunctions_3_2_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_2_compatibility.cpp
@@ -92,67 +92,67 @@ QOpenGLFunctions_3_2_Compatibility::~QOpenGLFunctions_3_2_Compatibility()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_3_2_core.cpp b/src/gui/opengl/qopenglfunctions_3_2_core.cpp
index 02c0c78b01..4c1e3eb3da 100644
--- a/src/gui/opengl/qopenglfunctions_3_2_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_2_core.cpp
@@ -85,47 +85,47 @@ QOpenGLFunctions_3_2_Core::~QOpenGLFunctions_3_2_Core()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_3_3_compatibility.cpp b/src/gui/opengl/qopenglfunctions_3_3_compatibility.cpp
index b034391c86..c750c6e0cc 100644
--- a/src/gui/opengl/qopenglfunctions_3_3_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_3_compatibility.cpp
@@ -93,75 +93,75 @@ QOpenGLFunctions_3_3_Compatibility::~QOpenGLFunctions_3_3_Compatibility()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
if (d_3_3_Deprecated) {
d_3_3_Deprecated->refs.deref();
- Q_ASSERT(d_3_3_Deprecated->refs.load());
+ Q_ASSERT(d_3_3_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_3_3_core.cpp b/src/gui/opengl/qopenglfunctions_3_3_core.cpp
index 7779d92b6a..5723509e32 100644
--- a/src/gui/opengl/qopenglfunctions_3_3_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_3_3_core.cpp
@@ -86,51 +86,51 @@ QOpenGLFunctions_3_3_Core::~QOpenGLFunctions_3_3_Core()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_0_compatibility.cpp b/src/gui/opengl/qopenglfunctions_4_0_compatibility.cpp
index 4fe4526efc..6ae7643eb5 100644
--- a/src/gui/opengl/qopenglfunctions_4_0_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_0_compatibility.cpp
@@ -94,79 +94,79 @@ QOpenGLFunctions_4_0_Compatibility::~QOpenGLFunctions_4_0_Compatibility()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
if (d_3_3_Deprecated) {
d_3_3_Deprecated->refs.deref();
- Q_ASSERT(d_3_3_Deprecated->refs.load());
+ Q_ASSERT(d_3_3_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_0_core.cpp b/src/gui/opengl/qopenglfunctions_4_0_core.cpp
index 4e4e8cc547..cd4fdb8b2b 100644
--- a/src/gui/opengl/qopenglfunctions_4_0_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_0_core.cpp
@@ -87,55 +87,55 @@ QOpenGLFunctions_4_0_Core::~QOpenGLFunctions_4_0_Core()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_1_compatibility.cpp b/src/gui/opengl/qopenglfunctions_4_1_compatibility.cpp
index 41ecb4672a..d104c74bc2 100644
--- a/src/gui/opengl/qopenglfunctions_4_1_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_1_compatibility.cpp
@@ -95,83 +95,83 @@ QOpenGLFunctions_4_1_Compatibility::~QOpenGLFunctions_4_1_Compatibility()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_4_1_Core) {
d_4_1_Core->refs.deref();
- Q_ASSERT(d_4_1_Core->refs.load());
+ Q_ASSERT(d_4_1_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
if (d_3_3_Deprecated) {
d_3_3_Deprecated->refs.deref();
- Q_ASSERT(d_3_3_Deprecated->refs.load());
+ Q_ASSERT(d_3_3_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_1_core.cpp b/src/gui/opengl/qopenglfunctions_4_1_core.cpp
index 5a1e1eb42f..7527aba620 100644
--- a/src/gui/opengl/qopenglfunctions_4_1_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_1_core.cpp
@@ -88,59 +88,59 @@ QOpenGLFunctions_4_1_Core::~QOpenGLFunctions_4_1_Core()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_4_1_Core) {
d_4_1_Core->refs.deref();
- Q_ASSERT(d_4_1_Core->refs.load());
+ Q_ASSERT(d_4_1_Core->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_2_compatibility.cpp b/src/gui/opengl/qopenglfunctions_4_2_compatibility.cpp
index fcc049c67b..a5b1b37495 100644
--- a/src/gui/opengl/qopenglfunctions_4_2_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_2_compatibility.cpp
@@ -96,87 +96,87 @@ QOpenGLFunctions_4_2_Compatibility::~QOpenGLFunctions_4_2_Compatibility()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_4_1_Core) {
d_4_1_Core->refs.deref();
- Q_ASSERT(d_4_1_Core->refs.load());
+ Q_ASSERT(d_4_1_Core->refs.loadRelaxed());
}
if (d_4_2_Core) {
d_4_2_Core->refs.deref();
- Q_ASSERT(d_4_2_Core->refs.load());
+ Q_ASSERT(d_4_2_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
if (d_3_3_Deprecated) {
d_3_3_Deprecated->refs.deref();
- Q_ASSERT(d_3_3_Deprecated->refs.load());
+ Q_ASSERT(d_3_3_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_2_core.cpp b/src/gui/opengl/qopenglfunctions_4_2_core.cpp
index fdfb4db455..1381236926 100644
--- a/src/gui/opengl/qopenglfunctions_4_2_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_2_core.cpp
@@ -89,63 +89,63 @@ QOpenGLFunctions_4_2_Core::~QOpenGLFunctions_4_2_Core()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_4_1_Core) {
d_4_1_Core->refs.deref();
- Q_ASSERT(d_4_1_Core->refs.load());
+ Q_ASSERT(d_4_1_Core->refs.loadRelaxed());
}
if (d_4_2_Core) {
d_4_2_Core->refs.deref();
- Q_ASSERT(d_4_2_Core->refs.load());
+ Q_ASSERT(d_4_2_Core->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_3_compatibility.cpp b/src/gui/opengl/qopenglfunctions_4_3_compatibility.cpp
index 131ebc810f..5c0c711d1c 100644
--- a/src/gui/opengl/qopenglfunctions_4_3_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_3_compatibility.cpp
@@ -97,91 +97,91 @@ QOpenGLFunctions_4_3_Compatibility::~QOpenGLFunctions_4_3_Compatibility()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_4_1_Core) {
d_4_1_Core->refs.deref();
- Q_ASSERT(d_4_1_Core->refs.load());
+ Q_ASSERT(d_4_1_Core->refs.loadRelaxed());
}
if (d_4_2_Core) {
d_4_2_Core->refs.deref();
- Q_ASSERT(d_4_2_Core->refs.load());
+ Q_ASSERT(d_4_2_Core->refs.loadRelaxed());
}
if (d_4_3_Core) {
d_4_3_Core->refs.deref();
- Q_ASSERT(d_4_3_Core->refs.load());
+ Q_ASSERT(d_4_3_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
if (d_3_3_Deprecated) {
d_3_3_Deprecated->refs.deref();
- Q_ASSERT(d_3_3_Deprecated->refs.load());
+ Q_ASSERT(d_3_3_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_3_core.cpp b/src/gui/opengl/qopenglfunctions_4_3_core.cpp
index 95e2d7bc43..34460b841e 100644
--- a/src/gui/opengl/qopenglfunctions_4_3_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_3_core.cpp
@@ -90,67 +90,67 @@ QOpenGLFunctions_4_3_Core::~QOpenGLFunctions_4_3_Core()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_4_1_Core) {
d_4_1_Core->refs.deref();
- Q_ASSERT(d_4_1_Core->refs.load());
+ Q_ASSERT(d_4_1_Core->refs.loadRelaxed());
}
if (d_4_2_Core) {
d_4_2_Core->refs.deref();
- Q_ASSERT(d_4_2_Core->refs.load());
+ Q_ASSERT(d_4_2_Core->refs.loadRelaxed());
}
if (d_4_3_Core) {
d_4_3_Core->refs.deref();
- Q_ASSERT(d_4_3_Core->refs.load());
+ Q_ASSERT(d_4_3_Core->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_4_compatibility.cpp b/src/gui/opengl/qopenglfunctions_4_4_compatibility.cpp
index 5c7170b8fa..907994a3c4 100644
--- a/src/gui/opengl/qopenglfunctions_4_4_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_4_compatibility.cpp
@@ -97,95 +97,95 @@ QOpenGLFunctions_4_4_Compatibility::~QOpenGLFunctions_4_4_Compatibility()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_4_1_Core) {
d_4_1_Core->refs.deref();
- Q_ASSERT(d_4_1_Core->refs.load());
+ Q_ASSERT(d_4_1_Core->refs.loadRelaxed());
}
if (d_4_2_Core) {
d_4_2_Core->refs.deref();
- Q_ASSERT(d_4_2_Core->refs.load());
+ Q_ASSERT(d_4_2_Core->refs.loadRelaxed());
}
if (d_4_3_Core) {
d_4_3_Core->refs.deref();
- Q_ASSERT(d_4_3_Core->refs.load());
+ Q_ASSERT(d_4_3_Core->refs.loadRelaxed());
}
if (d_4_4_Core) {
d_4_4_Core->refs.deref();
- Q_ASSERT(d_4_4_Core->refs.load());
+ Q_ASSERT(d_4_4_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
if (d_3_3_Deprecated) {
d_3_3_Deprecated->refs.deref();
- Q_ASSERT(d_3_3_Deprecated->refs.load());
+ Q_ASSERT(d_3_3_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_4_core.cpp b/src/gui/opengl/qopenglfunctions_4_4_core.cpp
index 54833f9058..76c0323f6d 100644
--- a/src/gui/opengl/qopenglfunctions_4_4_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_4_core.cpp
@@ -91,71 +91,71 @@ QOpenGLFunctions_4_4_Core::~QOpenGLFunctions_4_4_Core()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_4_1_Core) {
d_4_1_Core->refs.deref();
- Q_ASSERT(d_4_1_Core->refs.load());
+ Q_ASSERT(d_4_1_Core->refs.loadRelaxed());
}
if (d_4_2_Core) {
d_4_2_Core->refs.deref();
- Q_ASSERT(d_4_2_Core->refs.load());
+ Q_ASSERT(d_4_2_Core->refs.loadRelaxed());
}
if (d_4_3_Core) {
d_4_3_Core->refs.deref();
- Q_ASSERT(d_4_3_Core->refs.load());
+ Q_ASSERT(d_4_3_Core->refs.loadRelaxed());
}
if (d_4_4_Core) {
d_4_4_Core->refs.deref();
- Q_ASSERT(d_4_4_Core->refs.load());
+ Q_ASSERT(d_4_4_Core->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_5_compatibility.cpp b/src/gui/opengl/qopenglfunctions_4_5_compatibility.cpp
index f9d2bb9ceb..c415bb06ff 100644
--- a/src/gui/opengl/qopenglfunctions_4_5_compatibility.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_5_compatibility.cpp
@@ -99,103 +99,103 @@ QOpenGLFunctions_4_5_Compatibility::~QOpenGLFunctions_4_5_Compatibility()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_4_1_Core) {
d_4_1_Core->refs.deref();
- Q_ASSERT(d_4_1_Core->refs.load());
+ Q_ASSERT(d_4_1_Core->refs.loadRelaxed());
}
if (d_4_2_Core) {
d_4_2_Core->refs.deref();
- Q_ASSERT(d_4_2_Core->refs.load());
+ Q_ASSERT(d_4_2_Core->refs.loadRelaxed());
}
if (d_4_3_Core) {
d_4_3_Core->refs.deref();
- Q_ASSERT(d_4_3_Core->refs.load());
+ Q_ASSERT(d_4_3_Core->refs.loadRelaxed());
}
if (d_4_4_Core) {
d_4_4_Core->refs.deref();
- Q_ASSERT(d_4_4_Core->refs.load());
+ Q_ASSERT(d_4_4_Core->refs.loadRelaxed());
}
if (d_4_5_Core) {
d_4_5_Core->refs.deref();
- Q_ASSERT(d_4_5_Core->refs.load());
+ Q_ASSERT(d_4_5_Core->refs.loadRelaxed());
}
if (d_1_0_Deprecated) {
d_1_0_Deprecated->refs.deref();
- Q_ASSERT(d_1_0_Deprecated->refs.load());
+ Q_ASSERT(d_1_0_Deprecated->refs.loadRelaxed());
}
if (d_1_1_Deprecated) {
d_1_1_Deprecated->refs.deref();
- Q_ASSERT(d_1_1_Deprecated->refs.load());
+ Q_ASSERT(d_1_1_Deprecated->refs.loadRelaxed());
}
if (d_1_2_Deprecated) {
d_1_2_Deprecated->refs.deref();
- Q_ASSERT(d_1_2_Deprecated->refs.load());
+ Q_ASSERT(d_1_2_Deprecated->refs.loadRelaxed());
}
if (d_1_3_Deprecated) {
d_1_3_Deprecated->refs.deref();
- Q_ASSERT(d_1_3_Deprecated->refs.load());
+ Q_ASSERT(d_1_3_Deprecated->refs.loadRelaxed());
}
if (d_1_4_Deprecated) {
d_1_4_Deprecated->refs.deref();
- Q_ASSERT(d_1_4_Deprecated->refs.load());
+ Q_ASSERT(d_1_4_Deprecated->refs.loadRelaxed());
}
if (d_3_3_Deprecated) {
d_3_3_Deprecated->refs.deref();
- Q_ASSERT(d_3_3_Deprecated->refs.load());
+ Q_ASSERT(d_3_3_Deprecated->refs.loadRelaxed());
}
if (d_4_5_Deprecated) {
d_4_5_Deprecated->refs.deref();
- Q_ASSERT(d_4_5_Deprecated->refs.load());
+ Q_ASSERT(d_4_5_Deprecated->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglfunctions_4_5_core.cpp b/src/gui/opengl/qopenglfunctions_4_5_core.cpp
index a47ebb9ee9..4dfac3579c 100644
--- a/src/gui/opengl/qopenglfunctions_4_5_core.cpp
+++ b/src/gui/opengl/qopenglfunctions_4_5_core.cpp
@@ -92,75 +92,75 @@ QOpenGLFunctions_4_5_Core::~QOpenGLFunctions_4_5_Core()
{
if (d_1_0_Core) {
d_1_0_Core->refs.deref();
- Q_ASSERT(d_1_0_Core->refs.load());
+ Q_ASSERT(d_1_0_Core->refs.loadRelaxed());
}
if (d_1_1_Core) {
d_1_1_Core->refs.deref();
- Q_ASSERT(d_1_1_Core->refs.load());
+ Q_ASSERT(d_1_1_Core->refs.loadRelaxed());
}
if (d_1_2_Core) {
d_1_2_Core->refs.deref();
- Q_ASSERT(d_1_2_Core->refs.load());
+ Q_ASSERT(d_1_2_Core->refs.loadRelaxed());
}
if (d_1_3_Core) {
d_1_3_Core->refs.deref();
- Q_ASSERT(d_1_3_Core->refs.load());
+ Q_ASSERT(d_1_3_Core->refs.loadRelaxed());
}
if (d_1_4_Core) {
d_1_4_Core->refs.deref();
- Q_ASSERT(d_1_4_Core->refs.load());
+ Q_ASSERT(d_1_4_Core->refs.loadRelaxed());
}
if (d_1_5_Core) {
d_1_5_Core->refs.deref();
- Q_ASSERT(d_1_5_Core->refs.load());
+ Q_ASSERT(d_1_5_Core->refs.loadRelaxed());
}
if (d_2_0_Core) {
d_2_0_Core->refs.deref();
- Q_ASSERT(d_2_0_Core->refs.load());
+ Q_ASSERT(d_2_0_Core->refs.loadRelaxed());
}
if (d_2_1_Core) {
d_2_1_Core->refs.deref();
- Q_ASSERT(d_2_1_Core->refs.load());
+ Q_ASSERT(d_2_1_Core->refs.loadRelaxed());
}
if (d_3_0_Core) {
d_3_0_Core->refs.deref();
- Q_ASSERT(d_3_0_Core->refs.load());
+ Q_ASSERT(d_3_0_Core->refs.loadRelaxed());
}
if (d_3_1_Core) {
d_3_1_Core->refs.deref();
- Q_ASSERT(d_3_1_Core->refs.load());
+ Q_ASSERT(d_3_1_Core->refs.loadRelaxed());
}
if (d_3_2_Core) {
d_3_2_Core->refs.deref();
- Q_ASSERT(d_3_2_Core->refs.load());
+ Q_ASSERT(d_3_2_Core->refs.loadRelaxed());
}
if (d_3_3_Core) {
d_3_3_Core->refs.deref();
- Q_ASSERT(d_3_3_Core->refs.load());
+ Q_ASSERT(d_3_3_Core->refs.loadRelaxed());
}
if (d_4_0_Core) {
d_4_0_Core->refs.deref();
- Q_ASSERT(d_4_0_Core->refs.load());
+ Q_ASSERT(d_4_0_Core->refs.loadRelaxed());
}
if (d_4_1_Core) {
d_4_1_Core->refs.deref();
- Q_ASSERT(d_4_1_Core->refs.load());
+ Q_ASSERT(d_4_1_Core->refs.loadRelaxed());
}
if (d_4_2_Core) {
d_4_2_Core->refs.deref();
- Q_ASSERT(d_4_2_Core->refs.load());
+ Q_ASSERT(d_4_2_Core->refs.loadRelaxed());
}
if (d_4_3_Core) {
d_4_3_Core->refs.deref();
- Q_ASSERT(d_4_3_Core->refs.load());
+ Q_ASSERT(d_4_3_Core->refs.loadRelaxed());
}
if (d_4_4_Core) {
d_4_4_Core->refs.deref();
- Q_ASSERT(d_4_4_Core->refs.load());
+ Q_ASSERT(d_4_4_Core->refs.loadRelaxed());
}
if (d_4_5_Core) {
d_4_5_Core->refs.deref();
- Q_ASSERT(d_4_5_Core->refs.load());
+ Q_ASSERT(d_4_5_Core->refs.loadRelaxed());
}
}
diff --git a/src/gui/opengl/qopenglgradientcache_p.h b/src/gui/opengl/qopenglgradientcache_p.h
index cbdbbb0c54..1d34223bdd 100644
--- a/src/gui/opengl/qopenglgradientcache_p.h
+++ b/src/gui/opengl/qopenglgradientcache_p.h
@@ -66,7 +66,7 @@ class QOpenGL2GradientCache : public QOpenGLSharedResource
struct CacheInfo
{
inline CacheInfo(QGradientStops s, qreal op, QGradient::InterpolationMode mode) :
- stops(qMove(s)), opacity(op), interpolationMode(mode) {}
+ stops(std::move(s)), opacity(op), interpolationMode(mode) {}
GLuint texId;
QGradientStops stops;
diff --git a/src/gui/opengl/qopenglpaintdevice.h b/src/gui/opengl/qopenglpaintdevice.h
index 300002a9c1..54118f2926 100644
--- a/src/gui/opengl/qopenglpaintdevice.h
+++ b/src/gui/opengl/qopenglpaintdevice.h
@@ -59,7 +59,7 @@ public:
QOpenGLPaintDevice();
explicit QOpenGLPaintDevice(const QSize &size);
QOpenGLPaintDevice(int width, int height);
- virtual ~QOpenGLPaintDevice();
+ ~QOpenGLPaintDevice();
int devType() const override { return QInternal::OpenGL; }
QPaintEngine *paintEngine() const override;
diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp
index 001cb839fa..042b9ebd79 100644
--- a/src/gui/opengl/qopenglpaintengine.cpp
+++ b/src/gui/opengl/qopenglpaintengine.cpp
@@ -1574,14 +1574,15 @@ void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, c
case QImage::Format_Alpha8:
if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats)) {
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::AlphaImageSrc);
- bindOption = QOpenGLTextureUploader::UseRedFor8BitBindOption;
+ bindOption = QOpenGLTextureUploader::UseRedForAlphaAndLuminanceBindOption;
} else
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
break;
case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats)) {
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::GrayscaleImageSrc);
- bindOption = QOpenGLTextureUploader::UseRedFor8BitBindOption;
+ bindOption = QOpenGLTextureUploader::UseRedForAlphaAndLuminanceBindOption;
} else
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
break;
diff --git a/src/gui/opengl/qopenglpaintengine_p.h b/src/gui/opengl/qopenglpaintengine_p.h
index 0541ce6168..81f17572b2 100644
--- a/src/gui/opengl/qopenglpaintengine_p.h
+++ b/src/gui/opengl/qopenglpaintengine_p.h
@@ -166,7 +166,7 @@ public:
bool shouldDrawCachedGlyphs(QFontEngine *, const QTransform &) const override;
private:
- Q_DISABLE_COPY(QOpenGL2PaintEngineEx)
+ Q_DISABLE_COPY_MOVE(QOpenGL2PaintEngineEx)
friend class QOpenGLEngineShaderManager;
};
@@ -187,9 +187,9 @@ public:
QOpenGL2PaintEngineExPrivate(QOpenGL2PaintEngineEx *q_ptr) :
q(q_ptr),
- shaderManager(0),
+ shaderManager(nullptr),
width(0), height(0),
- ctx(0),
+ ctx(nullptr),
useSystemClip(true),
elementIndicesVBOId(0),
opacityArray(0),
@@ -361,9 +361,9 @@ void QOpenGL2PaintEngineExPrivate::uploadData(unsigned int arrayIndex, const GLf
opacityBuffer.allocate(data, count * sizeof(float));
}
if (arrayIndex == QT_OPACITY_ATTR)
- funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, 0);
+ funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
else
- funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
} else {
// If we already uploaded the data we don't have to do it again
if (data == vertexAttribPointers[arrayIndex])
diff --git a/src/gui/opengl/qopenglpixeltransferoptions.h b/src/gui/opengl/qopenglpixeltransferoptions.h
index 2fc52b82d8..195543ae90 100644
--- a/src/gui/opengl/qopenglpixeltransferoptions.h
+++ b/src/gui/opengl/qopenglpixeltransferoptions.h
@@ -55,14 +55,12 @@ class Q_GUI_EXPORT QOpenGLPixelTransferOptions
public:
QOpenGLPixelTransferOptions();
QOpenGLPixelTransferOptions(const QOpenGLPixelTransferOptions &);
-#ifdef Q_COMPILER_RVALUE_REFS
- QOpenGLPixelTransferOptions &operator=(QOpenGLPixelTransferOptions &&other) Q_DECL_NOTHROW
+ QOpenGLPixelTransferOptions &operator=(QOpenGLPixelTransferOptions &&other) noexcept
{ swap(other); return *this; }
-#endif
QOpenGLPixelTransferOptions &operator=(const QOpenGLPixelTransferOptions &);
~QOpenGLPixelTransferOptions();
- void swap(QOpenGLPixelTransferOptions &other) Q_DECL_NOTHROW
+ void swap(QOpenGLPixelTransferOptions &other) noexcept
{ data.swap(other.data); }
void setAlignment(int alignment);
diff --git a/src/gui/opengl/qopenglqueryhelper_p.h b/src/gui/opengl/qopenglqueryhelper_p.h
index 60dbf9c743..ad91ca9f96 100644
--- a/src/gui/opengl/qopenglqueryhelper_p.h
+++ b/src/gui/opengl/qopenglqueryhelper_p.h
@@ -65,18 +65,18 @@ class QOpenGLQueryHelper
{
public:
QOpenGLQueryHelper(QOpenGLContext *context)
- : GetQueryObjectuiv(0),
- GetQueryObjectiv(0),
- GetQueryiv(0),
- EndQuery(0),
- BeginQuery(0),
- IsQuery(0),
- DeleteQueries(0),
- GenQueries(0),
- GetInteger64v(0),
- GetQueryObjectui64v(0),
- GetQueryObjecti64v(0),
- QueryCounter(0)
+ : GetQueryObjectuiv(nullptr),
+ GetQueryObjectiv(nullptr),
+ GetQueryiv(nullptr),
+ EndQuery(nullptr),
+ BeginQuery(nullptr),
+ IsQuery(nullptr),
+ DeleteQueries(nullptr),
+ GenQueries(nullptr),
+ GetInteger64v(nullptr),
+ GetQueryObjectui64v(nullptr),
+ GetQueryObjecti64v(nullptr),
+ QueryCounter(nullptr)
{
Q_ASSERT(context);
diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp
index c39177080d..f225d5dc75 100644
--- a/src/gui/opengl/qopenglshaderprogram.cpp
+++ b/src/gui/opengl/qopenglshaderprogram.cpp
@@ -3667,7 +3667,8 @@ QVector<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const
Language (GLSL) are supported on this system; false otherwise.
The \a context is used to resolve the GLSL extensions.
- If \a context is null, then QOpenGLContext::currentContext() is used.
+ If \a context is \nullptr, then QOpenGLContext::currentContext()
+ is used.
*/
bool QOpenGLShaderProgram::hasOpenGLShaderPrograms(QOpenGLContext *context)
{
@@ -3694,7 +3695,8 @@ void QOpenGLShaderProgram::shaderDestroyed()
this system; false otherwise.
The \a context is used to resolve the GLSL extensions.
- If \a context is null, then QOpenGLContext::currentContext() is used.
+ If \a context is \nullptr, then QOpenGLContext::currentContext()
+ is used.
*/
bool QOpenGLShader::hasOpenGLShaders(ShaderType type, QOpenGLContext *context)
{
diff --git a/src/gui/opengl/qopenglshaderprogram.h b/src/gui/opengl/qopenglshaderprogram.h
index 84eb8d6956..c79101fd4d 100644
--- a/src/gui/opengl/qopenglshaderprogram.h
+++ b/src/gui/opengl/qopenglshaderprogram.h
@@ -50,13 +50,6 @@
#include <QtGui/qvector4d.h>
#include <QtGui/qmatrix4x4.h>
-#if defined(Q_CLANG_QDOC)
-#undef GLint
-typedef int GLint;
-#undef GLfloat
-typedef double GLfloat;
-#endif
-
QT_BEGIN_NAMESPACE
@@ -80,7 +73,7 @@ public:
Q_DECLARE_FLAGS(ShaderType, ShaderTypeBit)
explicit QOpenGLShader(QOpenGLShader::ShaderType type, QObject *parent = nullptr);
- virtual ~QOpenGLShader();
+ ~QOpenGLShader();
QOpenGLShader::ShaderType shaderType() const;
@@ -115,7 +108,7 @@ class Q_GUI_EXPORT QOpenGLShaderProgram : public QObject
Q_OBJECT
public:
explicit QOpenGLShaderProgram(QObject *parent = nullptr);
- virtual ~QOpenGLShaderProgram();
+ ~QOpenGLShaderProgram();
bool addShader(QOpenGLShader *shader);
void removeShader(QOpenGLShader *shader);
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index 5b7956d31e..61a6202017 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -1467,6 +1467,122 @@ void QOpenGLTexturePrivate::setData(int mipLevel, int layer, int layerCount, QOp
}
}
+void QOpenGLTexturePrivate::setData(int xOffset, int yOffset, int zOffset, int width, int height, int depth,
+ int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
+ QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ Q_UNUSED(yOffset);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(height);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
+ xOffset, width,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target1DArray:
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(yOffset);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(height);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
+ xOffset, layer,
+ width,
+ layerCount,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target2D:
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
+ xOffset, yOffset,
+ width, height,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target2DArray:
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ xOffset, yOffset, layer,
+ width, height, layerCount,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target3D:
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ xOffset, yOffset, zOffset,
+ width, height, depth,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::TargetCubeMap:
+ Q_UNUSED(layer);
+ Q_UNUSED(layerCount);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
+ xOffset, yOffset,
+ width, height,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::TargetCubeMapArray: {
+ Q_UNUSED(zOffset);
+ Q_UNUSED(depth);
+ int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
+ int layerFace = 6 * layer + faceIndex;
+ texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ xOffset, yOffset, layerFace,
+ width, height,
+ layerCount,
+ sourceFormat, sourceType, data, options);
+ break;
+ }
+
+ case QOpenGLTexture::TargetRectangle:
+ Q_UNUSED(mipLevel);
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0,
+ xOffset, yOffset,
+ width, height,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ case QOpenGLTexture::TargetBuffer:
+ // We don't upload pixel data for these targets
+ qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload");
+ break;
+ }
+
+ // If requested perform automatic mip map generation
+ if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
+ Q_Q(QOpenGLTexture);
+ q->generateMipMaps();
+ }
+}
+
+
void QOpenGLTexturePrivate::setCompressedData(int mipLevel, int layer, int layerCount,
QOpenGLTexture::CubeMapFace cubeFace,
int dataSize, const void *data,
@@ -3380,6 +3496,153 @@ void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType,
d->setData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
}
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ 0, 0, 1,
+ QOpenGLTexture::CubeMapPositiveX, sourceFormat,
+ sourceType, data, options);
+}
+
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image. The mip map level the sub image we want to
+ update is specified with \a mipLevel.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ mipLevel, 0, 1,
+ QOpenGLTexture::CubeMapPositiveX, sourceFormat,
+ sourceType, data, options);
+}
+
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image. The mip map level and layerof the sub image we want to
+ update are specified with \a mipLevel and \a layer.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ mipLevel, layer, 1,
+ QOpenGLTexture::CubeMapPositiveX, sourceFormat,
+ sourceType, data, options);
+}
+
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image.The mip map level, layer and cube map face of the sub
+ image we want to update are specified with \a mipLevel, \a layer and \a
+ face.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ CubeMapFace face,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ mipLevel, layer, 1,
+ face, sourceFormat,
+ sourceType, data, options);
+}
+
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image.The mip map level, starting layer, cube map face and
+ number of layers of the sub image we want to update are specified with \a
+ mipLevel, \a layer, \a face and \a layerCount.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ CubeMapFace face, int layerCount,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ mipLevel, layer, layerCount,
+ face, sourceFormat,
+ sourceType, data, options);
+}
+
#if QT_DEPRECATED_SINCE(5, 3)
/*!
\obsolete
@@ -4114,7 +4377,7 @@ QOpenGLTexture::DepthStencilMode QOpenGLTexture::depthStencilMode() const
*/
-/*
+/*!
\since 5.5
Sets the texture comparison function on this texture to \a function. The texture
diff --git a/src/gui/opengl/qopengltexture.h b/src/gui/opengl/qopengltexture.h
index c0c5283374..7d984babc8 100644
--- a/src/gui/opengl/qopengltexture.h
+++ b/src/gui/opengl/qopengltexture.h
@@ -485,6 +485,32 @@ public:
void setData(PixelFormat sourceFormat, PixelType sourceType,
const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth, int mipLevel,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ CubeMapFace cubeFace,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ CubeMapFace cubeFace, int layerCount,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+
// Compressed data upload
// ### Qt 6: remove the non-const void * overloads
#if QT_DEPRECATED_SINCE(5, 3)
diff --git a/src/gui/opengl/qopengltexture_p.h b/src/gui/opengl/qopengltexture_p.h
index f7694f77bc..9f3457ad0a 100644
--- a/src/gui/opengl/qopengltexture_p.h
+++ b/src/gui/opengl/qopengltexture_p.h
@@ -101,6 +101,10 @@ public:
void setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
const void *data, const QOpenGLPixelTransferOptions * const options);
+ void setData(int xOffset, int yOffset, int zOffset, int width, int height, int depth,
+ int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
+ QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options);
void setCompressedData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
int dataSize, const void *data,
const QOpenGLPixelTransferOptions * const options);
diff --git a/src/gui/opengl/qopengltextureglyphcache_p.h b/src/gui/opengl/qopengltextureglyphcache_p.h
index 598cb00ee5..aed128cf9e 100644
--- a/src/gui/opengl/qopengltextureglyphcache_p.h
+++ b/src/gui/opengl/qopengltextureglyphcache_p.h
@@ -139,7 +139,7 @@ public:
inline void setPaintEnginePrivate(QOpenGL2PaintEngineExPrivate *p) { pex = p; }
- inline const QOpenGLContextGroup *contextGroup() const { return m_textureResource ? m_textureResource->group() : 0; }
+ inline const QOpenGLContextGroup *contextGroup() const { return m_textureResource ? m_textureResource->group() : nullptr; }
inline int serialNumber() const { return m_serialNumber; }
diff --git a/src/gui/opengl/qopengltexturehelper_p.h b/src/gui/opengl/qopengltexturehelper_p.h
index 00f6f9e5aa..62d0125daf 100644
--- a/src/gui/opengl/qopengltexturehelper_p.h
+++ b/src/gui/opengl/qopengltexturehelper_p.h
@@ -167,7 +167,7 @@ public:
inline void glTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
- const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = 0)
+ const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = nullptr)
{
if (options) {
QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
@@ -181,7 +181,7 @@ public:
inline void glTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLenum format, GLenum type,
- const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = 0)
+ const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = nullptr)
{
if (options) {
QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
@@ -195,7 +195,7 @@ public:
inline void glTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset,
GLsizei width, GLenum format, GLenum type,
- const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = 0)
+ const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = nullptr)
{
if (options) {
QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
@@ -222,7 +222,7 @@ public:
inline void glCompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
GLint xoffset, GLsizei width,
GLenum format, GLsizei imageSize, const GLvoid *bits,
- const QOpenGLPixelTransferOptions * const options = 0)
+ const QOpenGLPixelTransferOptions * const options = nullptr)
{
if (options) {
QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
@@ -238,7 +238,7 @@ public:
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLsizei imageSize, const GLvoid *bits,
- const QOpenGLPixelTransferOptions * const options = 0)
+ const QOpenGLPixelTransferOptions * const options = nullptr)
{
if (options) {
QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
@@ -254,7 +254,7 @@ public:
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, const GLvoid *bits,
- const QOpenGLPixelTransferOptions * const options = 0)
+ const QOpenGLPixelTransferOptions * const options = nullptr)
{
if (options) {
QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
@@ -269,7 +269,7 @@ public:
inline void glCompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
GLenum internalFormat, GLsizei width,
GLint border, GLsizei imageSize, const GLvoid *bits,
- const QOpenGLPixelTransferOptions * const options = 0)
+ const QOpenGLPixelTransferOptions * const options = nullptr)
{
if (options) {
QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
@@ -284,7 +284,7 @@ public:
inline void glCompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLint border, GLsizei imageSize, const GLvoid *bits,
- const QOpenGLPixelTransferOptions * const options = 0)
+ const QOpenGLPixelTransferOptions * const options = nullptr)
{
if (options) {
@@ -300,7 +300,7 @@ public:
inline void glCompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLsizei imageSize, const GLvoid *bits,
- const QOpenGLPixelTransferOptions * const options = 0)
+ const QOpenGLPixelTransferOptions * const options = nullptr)
{
if (options) {
QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
diff --git a/src/gui/opengl/qopengltextureuploader.cpp b/src/gui/opengl/qopengltextureuploader.cpp
index 47f657e404..d9d5403cf3 100644
--- a/src/gui/opengl/qopengltextureuploader.cpp
+++ b/src/gui/opengl/qopengltextureuploader.cpp
@@ -116,7 +116,7 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
const bool isOpenGLES3orBetter = context->isOpenGLES() && context->format().majorVersion() >= 3;
const bool sRgbBinding = (options & SRgbBindOption);
Q_ASSERT(isOpenGL12orBetter || context->isOpenGLES());
- Q_ASSERT((options & (SRgbBindOption | UseRedFor8BitBindOption)) != (SRgbBindOption | UseRedFor8BitBindOption));
+ Q_ASSERT((options & (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption)) != (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption));
switch (image.format()) {
case QImage::Format_RGB32:
@@ -222,7 +222,7 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
if (sRgbBinding) {
// Always needs conversion
break;
- } else if (options & UseRedFor8BitBindOption) {
+ } else if (options & UseRedForAlphaAndLuminanceBindOption) {
externalFormat = internalFormat = GL_RED;
pixelType = GL_UNSIGNED_BYTE;
targetFormat = image.format();
@@ -232,7 +232,7 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
if (sRgbBinding) {
// Always needs conversion
break;
- } else if (options & UseRedFor8BitBindOption) {
+ } else if (options & UseRedForAlphaAndLuminanceBindOption) {
externalFormat = internalFormat = GL_RED;
pixelType = GL_UNSIGNED_BYTE;
targetFormat = image.format();
@@ -254,7 +254,7 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
if (sRgbBinding) {
// Always needs conversion
break;
- } else if (options & UseRedFor8BitBindOption) {
+ } else if (options & UseRedForAlphaAndLuminanceBindOption) {
externalFormat = internalFormat = GL_RED;
pixelType = GL_UNSIGNED_BYTE;
targetFormat = image.format();
@@ -272,6 +272,28 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
targetFormat = image.format();
}
break;
+ case QImage::Format_Grayscale16:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (options & UseRedForAlphaAndLuminanceBindOption) {
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_SHORT;
+ targetFormat = image.format();
+ } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
+ externalFormat = internalFormat = GL_LUMINANCE;
+ pixelType = GL_UNSIGNED_SHORT;
+ targetFormat = image.format();
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_SHORT;
+ targetFormat = image.format();
+ }
+ break;
default:
break;
}
diff --git a/src/gui/opengl/qopengltextureuploader_p.h b/src/gui/opengl/qopengltextureuploader_p.h
index d758b3787b..0dcf709d7e 100644
--- a/src/gui/opengl/qopengltextureuploader_p.h
+++ b/src/gui/opengl/qopengltextureuploader_p.h
@@ -65,7 +65,7 @@ public:
enum BindOption {
NoBindOption = 0x0000,
PremultipliedAlphaBindOption = 0x0001,
- UseRedFor8BitBindOption = 0x0002,
+ UseRedForAlphaAndLuminanceBindOption = 0x0002,
SRgbBindOption = 0x0004,
PowerOfTwoBindOption = 0x0008
};
diff --git a/src/gui/opengl/qopenglversionfunctions.h b/src/gui/opengl/qopenglversionfunctions.h
index 3af1ed0466..aa6e49b9ae 100644
--- a/src/gui/opengl/qopenglversionfunctions.h
+++ b/src/gui/opengl/qopenglversionfunctions.h
@@ -97,7 +97,7 @@ struct QOpenGLVersionStatus
OpenGLStatus status;
};
-inline uint qHash(const QOpenGLVersionStatus &v, uint seed = 0) Q_DECL_NOTHROW
+inline uint qHash(const QOpenGLVersionStatus &v, uint seed = 0) noexcept
{
return qHash(static_cast<int>(v.status * 1000)
+ v.version.first * 100 + v.version.second * 10, seed);
@@ -214,6 +214,7 @@ public:
virtual bool initializeOpenGLFunctions();
+ Q_DISABLE_COPY(QAbstractOpenGLFunctions)
Q_DECLARE_PRIVATE(QAbstractOpenGLFunctions)
protected:
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index a90abed4c0..972cf387ff 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -8,7 +8,15 @@ HEADERS += \
painting/qbrush.h \
painting/qcolor.h \
painting/qcolor_p.h \
- painting/qcolorprofile_p.h \
+ painting/qcolormatrix_p.h \
+ painting/qcolorspace.h \
+ painting/qcolorspace_p.h \
+ painting/qcolortransferfunction_p.h \
+ painting/qcolortransfertable_p.h \
+ painting/qcolortransform.h \
+ painting/qcolortransform_p.h \
+ painting/qcolortrc_p.h \
+ painting/qcolortrclut_p.h \
painting/qcosmeticstroker_p.h \
painting/qdatabuffer_p.h \
painting/qdrawhelper_p.h \
@@ -17,6 +25,7 @@ HEADERS += \
painting/qemulationpaintengine_p.h \
painting/qfixed_p.h \
painting/qgrayraster_p.h \
+ painting/qicc_p.h \
painting/qmatrix.h \
painting/qmemrotate_p.h \
painting/qoutlinemapper_p.h \
@@ -64,12 +73,15 @@ SOURCES += \
painting/qblittable.cpp \
painting/qbrush.cpp \
painting/qcolor.cpp \
- painting/qcolorprofile.cpp \
+ painting/qcolorspace.cpp \
+ painting/qcolortransform.cpp \
+ painting/qcolortrclut.cpp \
painting/qcompositionfunctions.cpp \
painting/qcosmeticstroker.cpp \
painting/qdrawhelper.cpp \
painting/qemulationpaintengine.cpp \
painting/qgrayraster.c \
+ painting/qicc.cpp \
painting/qimagescale.cpp \
painting/qmatrix.cpp \
painting/qmemrotate.cpp \
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index d935deb4d6..3fab903c4d 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -208,7 +208,7 @@ static bool isRasterSurface(QWindow *window)
The \a window must either be the top level window represented by
this backingstore, or a non-transient child of that window. Passing
- \c nullptr falls back to using the backingstore's top level window.
+ \nullptr falls back to using the backingstore's top level window.
If the \a window is a child window, the \a region should be in child window
coordinates, and the \a offset should be the child window's offset in relation
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index 2dd5144e40..348eceb47f 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -187,19 +187,11 @@ void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl,
#endif
if (const_alpha == 256) {
- if (w <= 64) {
- while (h--) {
- QT_MEMCPY_USHORT(dst, src, w);
- dst += dbpl;
- src += sbpl;
- }
- } else {
- int length = w << 1;
- while (h--) {
- memcpy(dst, src, length);
- dst += dbpl;
- src += sbpl;
- }
+ int length = w << 1;
+ while (h--) {
+ memcpy(dst, src, length);
+ dst += dbpl;
+ src += sbpl;
}
} else if (const_alpha != 0) {
quint16 *d = (quint16 *) dst;
diff --git a/src/gui/painting/qblendfunctions_p.h b/src/gui/painting/qblendfunctions_p.h
index dc7a4dfe8c..080da98ec4 100644
--- a/src/gui/painting/qblendfunctions_p.h
+++ b/src/gui/painting/qblendfunctions_p.h
@@ -65,71 +65,42 @@ void qt_scale_image_16bit(uchar *destPixels, int dbpl,
const QRect &clip,
T blender)
{
- qreal sx = targetRect.width() / (qreal) srcRect.width();
- qreal sy = targetRect.height() / (qreal) srcRect.height();
+ qreal sx = srcRect.width() / (qreal) targetRect.width();
+ qreal sy = srcRect.height() / (qreal) targetRect.height();
- int ix = 0x00010000 / sx;
- int iy = 0x00010000 / sy;
+ const int ix = 0x00010000 * sx;
+ const int iy = 0x00010000 * sy;
-// qDebug() << "scale:" << endl
-// << " - target" << targetRect << endl
-// << " - source" << srcRect << endl
-// << " - clip" << clip << endl
+// qDebug() << "scale:" << Qt::endl
+// << " - target" << targetRect << Qt::endl
+// << " - source" << srcRect << Qt::endl
+// << " - clip" << clip << Qt::endl
// << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
- int cx1 = clip.x();
- int cx2 = clip.x() + clip.width();
- int cy1 = clip.top();
- int cy2 = clip.y() + clip.height();
-
- int tx1 = qRound(targetRect.left());
- int tx2 = qRound(targetRect.right());
- int ty1 = qRound(targetRect.top());
- int ty2 = qRound(targetRect.bottom());
-
- if (tx2 < tx1)
- qSwap(tx2, tx1);
-
- if (ty2 < ty1)
- qSwap(ty2, ty1);
-
- if (tx1 < cx1)
- tx1 = cx1;
-
- if (tx2 >= cx2)
- tx2 = cx2;
-
- if (tx1 >= tx2)
+ QRect tr = targetRect.normalized().toRect();
+ tr = tr.intersected(clip);
+ if (tr.isEmpty())
return;
-
- if (ty1 < cy1)
- ty1 = cy1;
-
- if (ty2 >= cy2)
- ty2 = cy2;
-
- if (ty1 >= ty2)
- return;
-
- int h = ty2 - ty1;
- int w = tx2 - tx1;
-
+ const int tx1 = tr.left();
+ const int ty1 = tr.top();
+ int h = tr.height();
+ int w = tr.width();
quint32 basex;
quint32 srcy;
if (sx < 0) {
- int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
+ int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * sx * 65536) + 1;
basex = quint32(srcRect.right() * 65536) + dstx;
} else {
- int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
+ int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * sx * 65536) - 1;
basex = quint32(srcRect.left() * 65536) + dstx;
}
if (sy < 0) {
- int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
+ int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * sy * 65536) + 1;
srcy = quint32(srcRect.bottom() * 65536) + dsty;
} else {
- int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
+ int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * sy * 65536) - 1;
srcy = quint32(srcRect.top() * 65536) + dsty;
}
@@ -185,72 +156,42 @@ template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl,
const QRect &clip,
T blender)
{
- qreal sx = targetRect.width() / (qreal) srcRect.width();
- qreal sy = targetRect.height() / (qreal) srcRect.height();
+ qreal sx = srcRect.width() / (qreal) targetRect.width();
+ qreal sy = srcRect.height() / (qreal) targetRect.height();
- int ix = 0x00010000 / sx;
- int iy = 0x00010000 / sy;
+ const int ix = 0x00010000 * sx;
+ const int iy = 0x00010000 * sy;
-// qDebug() << "scale:" << endl
-// << " - target" << targetRect << endl
-// << " - source" << srcRect << endl
-// << " - clip" << clip << endl
+// qDebug() << "scale:" << Qt::endl
+// << " - target" << targetRect << Qt::endl
+// << " - source" << srcRect << Qt::endl
+// << " - clip" << clip << Qt::endl
// << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
- int cx1 = clip.x();
- int cx2 = clip.x() + clip.width();
- int cy1 = clip.top();
- int cy2 = clip.y() + clip.height();
-
- int tx1 = qRound(targetRect.left());
- int tx2 = qRound(targetRect.right());
- int ty1 = qRound(targetRect.top());
- int ty2 = qRound(targetRect.bottom());
-
- if (tx2 < tx1)
- qSwap(tx2, tx1);
-
- if (ty2 < ty1)
- qSwap(ty2, ty1);
-
- if (tx1 < cx1)
- tx1 = cx1;
-
- if (tx2 >= cx2)
- tx2 = cx2;
-
- if (tx1 >= tx2)
- return;
-
- if (ty1 < cy1)
- ty1 = cy1;
-
- if (ty2 >= cy2)
- ty2 = cy2;
-
- if (ty1 >= ty2)
- return;
-
- int h = ty2 - ty1;
- int w = tx2 - tx1;
- if (!w || !h)
+ QRect tr = targetRect.normalized().toRect();
+ tr = tr.intersected(clip);
+ if (tr.isEmpty())
return;
+ const int tx1 = tr.left();
+ const int ty1 = tr.top();
+ int h = tr.height();
+ int w = tr.width();
quint32 basex;
quint32 srcy;
if (sx < 0) {
- int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
+ int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * sx * 65536) + 1;
basex = quint32(srcRect.right() * 65536) + dstx;
} else {
- int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
+ int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * sx * 65536) - 1;
basex = quint32(srcRect.left() * 65536) + dstx;
}
if (sy < 0) {
- int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
+ int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * sy * 65536) + 1;
srcy = quint32(srcRect.bottom() * 65536) + dsty;
} else {
- int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
+ int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * sy * 65536) - 1;
srcy = quint32(srcRect.top() * 65536) + dsty;
}
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index d071f665bb..abb3268dfa 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -111,7 +111,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapForBrush(int brushStyle, bool invert)
QString key = QLatin1String("$qt-brush$")
% HexString<uint>(brushStyle)
% QLatin1Char(invert ? '1' : '0');
- if (!QPixmapCache::find(key, pm)) {
+ if (!QPixmapCache::find(key, &pm)) {
pm = QBitmap::fromData(QSize(8, 8), qt_patternForBrush(brushStyle, invert),
QImage::Format_MonoLSB);
QPixmapCache::insert(key, pm);
@@ -352,7 +352,7 @@ public:
QBrushData *brush;
QNullBrushData() : brush(new QBrushData)
{
- brush->ref.store(1);
+ brush->ref.storeRelaxed(1);
brush->style = Qt::BrushStyle(0);
brush->color = Qt::black;
}
@@ -411,7 +411,7 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style)
d.reset(new QBrushData);
break;
}
- d->ref.store(1);
+ d->ref.storeRelaxed(1);
d->style = style;
d->color = color;
}
@@ -585,7 +585,7 @@ static Q_DECL_CONSTEXPR inline bool use_same_brushdata(Qt::BrushStyle lhs, Qt::B
void QBrush::detach(Qt::BrushStyle newStyle)
{
- if (use_same_brushdata(newStyle, d->style) && d->ref.load() == 1) {
+ if (use_same_brushdata(newStyle, d->style) && d->ref.loadRelaxed() == 1) {
d->style = newStyle;
return;
}
@@ -625,7 +625,7 @@ void QBrush::detach(Qt::BrushStyle newStyle)
x.reset(new QBrushData);
break;
}
- x->ref.store(1); // must be first lest the QBrushDataPointerDeleter turns into a no-op
+ x->ref.storeRelaxed(1); // must be first lest the QBrushDataPointerDeleter turns into a no-op
x->style = newStyle;
x->color = d->color;
x->transform = d->transform;
@@ -1140,11 +1140,11 @@ QDataStream &operator>>(QDataStream &s, QBrush &b)
if (s.version() >= QDataStream::Qt_5_5) {
QImage img;
s >> img;
- b.setTextureImage(qMove(img));
+ b.setTextureImage(std::move(img));
} else {
QPixmap pm;
s >> pm;
- b.setTexture(qMove(pm));
+ b.setTexture(std::move(pm));
}
} else if (style == Qt::LinearGradientPattern
|| style == Qt::RadialGradientPattern
@@ -1385,22 +1385,29 @@ QGradient::QGradient(Preset preset)
setCoordinateMode(ObjectMode);
setSpread(PadSpread);
- const QJsonValue start = presetData[QLatin1Literal("start")];
- const QJsonValue end = presetData[QLatin1Literal("end")];
- m_data.linear.x1 = start[QLatin1Literal("x")].toDouble();
- m_data.linear.y1 = start[QLatin1Literal("y")].toDouble();
- m_data.linear.x2 = end[QLatin1Literal("x")].toDouble();
- m_data.linear.y2 = end[QLatin1Literal("y")].toDouble();
+ const QJsonValue start = presetData[QLatin1String("start")];
+ const QJsonValue end = presetData[QLatin1String("end")];
+ m_data.linear.x1 = start[QLatin1String("x")].toDouble();
+ m_data.linear.y1 = start[QLatin1String("y")].toDouble();
+ m_data.linear.x2 = end[QLatin1String("x")].toDouble();
+ m_data.linear.y2 = end[QLatin1String("y")].toDouble();
for (const QJsonValue &stop : presetData[QLatin1String("stops")].toArray()) {
- setColorAt(stop[QLatin1Literal("position")].toDouble(),
- QColor(QRgb(stop[QLatin1Literal("color")].toInt())));
+ setColorAt(stop[QLatin1String("position")].toDouble(),
+ QColor(QRgb(stop[QLatin1String("color")].toInt())));
}
cachedPresets.insert(preset, *this);
}
}
+/*!
+ \internal
+*/
+QGradient::~QGradient()
+{
+}
+
QT_END_NAMESPACE
static void initGradientPresets() { Q_INIT_RESOURCE(qmake_webgradients); }
Q_CONSTRUCTOR_FUNCTION(initGradientPresets);
@@ -1785,6 +1792,12 @@ QLinearGradient::QLinearGradient(qreal xStart, qreal yStart, qreal xFinalStop, q
{
}
+/*!
+ \internal
+*/
+QLinearGradient::~QLinearGradient()
+{
+}
/*!
Returns the start point of this linear gradient in logical coordinates.
@@ -2056,6 +2069,13 @@ QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal centerRadius, qreal f
}
/*!
+ \internal
+*/
+QRadialGradient::~QRadialGradient()
+{
+}
+
+/*!
Returns the center of this radial gradient in logical coordinates.
\sa QGradient::stops()
@@ -2301,6 +2321,13 @@ QConicalGradient::QConicalGradient(qreal cx, qreal cy, qreal angle)
{
}
+/*!
+ \internal
+*/
+QConicalGradient::~QConicalGradient()
+{
+}
+
/*!
Constructs a conical with center at (0, 0) starting the
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index aee51c526d..6a4ffab1c5 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -79,11 +79,9 @@ public:
~QBrush();
QBrush &operator=(const QBrush &brush);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QBrush &operator=(QBrush &&other) Q_DECL_NOEXCEPT
+ inline QBrush &operator=(QBrush &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- inline void swap(QBrush &other) Q_DECL_NOEXCEPT
+ inline void swap(QBrush &other) noexcept
{ qSwap(d, other.d); }
operator QVariant() const;
@@ -161,7 +159,7 @@ inline Qt::BrushStyle QBrush::style() const { return d->style; }
inline const QColor &QBrush::color() const { return d->color; }
inline const QMatrix &QBrush::matrix() const { return d->transform.toAffine(); }
inline QTransform QBrush::transform() const { return d->transform; }
-inline bool QBrush::isDetached() const { return d->ref.load() == 1; }
+inline bool QBrush::isDetached() const { return d->ref.loadRelaxed() == 1; }
/*******************************************************************************
@@ -373,11 +371,14 @@ public:
GagarinView = 178,
FabledSunset = 179,
PerfectBlue = 180,
+
+ NumPresets
};
Q_ENUM(Preset)
QGradient();
QGradient(Preset);
+ ~QGradient();
Type type() const { return m_type; }
@@ -431,6 +432,7 @@ public:
QLinearGradient();
QLinearGradient(const QPointF &start, const QPointF &finalStop);
QLinearGradient(qreal xStart, qreal yStart, qreal xFinalStop, qreal yFinalStop);
+ ~QLinearGradient();
QPointF start() const;
void setStart(const QPointF &start);
@@ -455,6 +457,8 @@ public:
QRadialGradient(const QPointF &center, qreal centerRadius, const QPointF &focalPoint, qreal focalRadius);
QRadialGradient(qreal cx, qreal cy, qreal centerRadius, qreal fx, qreal fy, qreal focalRadius);
+ ~QRadialGradient();
+
QPointF center() const;
void setCenter(const QPointF &center);
inline void setCenter(qreal x, qreal y) { setCenter(QPointF(x, y)); }
@@ -480,6 +484,7 @@ public:
QConicalGradient();
QConicalGradient(const QPointF &center, qreal startAngle);
QConicalGradient(qreal cx, qreal cy, qreal startAngle);
+ ~QConicalGradient();
QPointF center() const;
void setCenter(const QPointF &center);
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index e5bac84df9..6cbc30e79a 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -39,6 +39,7 @@
#include "qcolor.h"
#include "qcolor_p.h"
+#include "qfloat16.h"
#include "qnamespace.h"
#include "qdatastream.h"
#include "qvariant.h"
@@ -494,6 +495,14 @@ static QStringList get_colornames()
with this value, a pixel value will be used that is appropriate for the
underlying pixel format in use.
+ \section1 The Extended RGB Color Model
+
+ The extended RGB color model, also known as the scRGB color space,
+ is the same the RGB color model except it allows values under 0.0,
+ and over 1.0. This makes it possible to represent colors that would
+ otherwise be outside the range of the RGB colorspace but still use
+ the same values for colors inside the RGB colorspace.
+
\section1 The HSV Color Model
The RGB model is hardware-oriented. Its representation is close to
@@ -603,12 +612,13 @@ static QStringList get_colornames()
/*!
\enum QColor::Spec
- The type of color specified, either RGB, HSV, CMYK or HSL.
+ The type of color specified, either RGB, extended RGB, HSV, CMYK or HSL.
\value Rgb
\value Hsv
\value Cmyk
\value Hsl
+ \value ExtendedRgb
\value Invalid
\sa spec(), convertTo()
@@ -653,7 +663,7 @@ static QStringList get_colornames()
\sa isValid(), {QColor#Predefined Colors}{Predefined Colors}
*/
-QColor::QColor(Qt::GlobalColor color) Q_DECL_NOTHROW
+QColor::QColor(Qt::GlobalColor color) noexcept
{
#define QRGB(r, g, b) \
QRgb(((0xffu << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff)))
@@ -728,7 +738,7 @@ QColor::QColor(Qt::GlobalColor color) Q_DECL_NOTHROW
\sa fromRgb(), isValid()
*/
-QColor::QColor(QRgb color) Q_DECL_NOTHROW
+QColor::QColor(QRgb color) noexcept
{
cspec = Rgb;
ct.argb.alpha = 0xffff;
@@ -746,7 +756,7 @@ QColor::QColor(QRgb color) Q_DECL_NOTHROW
\sa fromRgba64()
*/
-QColor::QColor(QRgba64 rgba64) Q_DECL_NOTHROW
+QColor::QColor(QRgba64 rgba64) noexcept
{
setRgba64(rgba64);
}
@@ -760,7 +770,7 @@ QColor::QColor(QRgba64 rgba64) Q_DECL_NOTHROW
becomes a valid color by accident.
*/
-QColor::QColor(Spec spec) Q_DECL_NOTHROW
+QColor::QColor(Spec spec) noexcept
{
switch (spec) {
case Invalid:
@@ -778,6 +788,10 @@ QColor::QColor(Spec spec) Q_DECL_NOTHROW
case Hsl:
setHsl(0, 0, 0, 0);
break;
+ case ExtendedRgb:
+ cspec = spec;
+ setRgbF(0, 0, 0, 0);
+ break;
}
}
@@ -933,7 +947,7 @@ bool QColor::isValidColor(const QString &name)
\overload
\since 5.10
*/
-bool QColor::isValidColor(QStringView name) Q_DECL_NOTHROW
+bool QColor::isValidColor(QStringView name) noexcept
{
return name.size() && QColor().setColorFromString(name);
}
@@ -942,7 +956,7 @@ bool QColor::isValidColor(QStringView name) Q_DECL_NOTHROW
\overload
\since 5.8
*/
-bool QColor::isValidColor(QLatin1String name) Q_DECL_NOTHROW
+bool QColor::isValidColor(QLatin1String name) noexcept
{
return name.size() && QColor().setColorFromString(name);
}
@@ -1211,6 +1225,17 @@ void QColor::setHsl(int h, int s, int l, int a)
ct.ahsl.pad = 0;
}
+static inline qfloat16 &castF16(quint16 &v)
+{
+ // this works because qfloat16 internally is a quint16
+ return *reinterpret_cast<qfloat16 *>(&v);
+}
+
+static inline const qfloat16 &castF16(const quint16 &v)
+{
+ return *reinterpret_cast<const qfloat16 *>(&v);
+}
+
/*!
Sets the contents pointed to by \a r, \a g, \a b, and \a a, to the red,
green, blue, and alpha-channel (transparency) components of the color's
@@ -1226,18 +1251,27 @@ void QColor::getRgbF(qreal *r, qreal *g, qreal *b, qreal *a) const
if (!r || !g || !b)
return;
- if (cspec != Invalid && cspec != Rgb) {
+ if (cspec == Invalid)
+ return;
+
+ if (cspec != Rgb && cspec != ExtendedRgb) {
toRgb().getRgbF(r, g, b, a);
return;
}
- *r = ct.argb.red / qreal(USHRT_MAX);
- *g = ct.argb.green / qreal(USHRT_MAX);
- *b = ct.argb.blue / qreal(USHRT_MAX);
-
- if (a)
- *a = ct.argb.alpha / qreal(USHRT_MAX);
-
+ if (cspec == Rgb) {
+ *r = ct.argb.red / qreal(USHRT_MAX);
+ *g = ct.argb.green / qreal(USHRT_MAX);
+ *b = ct.argb.blue / qreal(USHRT_MAX);
+ if (a)
+ *a = ct.argb.alpha / qreal(USHRT_MAX);
+ } else {
+ *r = castF16(ct.argbExtended.redF16);
+ *g = castF16(ct.argbExtended.greenF16);
+ *b = castF16(ct.argbExtended.blueF16);
+ if (a)
+ *a = castF16(ct.argbExtended.alphaF16);
+ }
}
/*!
@@ -1274,26 +1308,35 @@ void QColor::getRgb(int *r, int *g, int *b, int *a) const
Sets the color channels of this color to \a r (red), \a g (green),
\a b (blue) and \a a (alpha, transparency).
- All values must be in the range 0.0-1.0.
+ The alpha value must be in the range 0.0-1.0.
+ If any of the other values are outside the range of 0.0-1.0 the
+ color model will be set as \c ExtendedRgb.
\sa rgb(), getRgbF(), setRgb()
*/
void QColor::setRgbF(qreal r, qreal g, qreal b, qreal a)
{
- if (r < qreal(0.0) || r > qreal(1.0)
- || g < qreal(0.0) || g > qreal(1.0)
- || b < qreal(0.0) || b > qreal(1.0)
- || a < qreal(0.0) || a > qreal(1.0)) {
- qWarning("QColor::setRgbF: RGB parameters out of range");
+ if (a < qreal(0.0) || a > qreal(1.0)) {
+ qWarning("QColor::setRgbF: Alpha parameter is out of range");
invalidate();
return;
}
-
+ if (r < qreal(0.0) || r > qreal(1.0) ||
+ g < qreal(0.0) || g > qreal(1.0) ||
+ b < qreal(0.0) || b > qreal(1.0) || cspec == ExtendedRgb) {
+ cspec = ExtendedRgb;
+ castF16(ct.argbExtended.redF16) = qfloat16(r);
+ castF16(ct.argbExtended.greenF16) = qfloat16(g);
+ castF16(ct.argbExtended.blueF16) = qfloat16(b);
+ castF16(ct.argbExtended.alphaF16) = qfloat16(a);
+ ct.argbExtended.pad = 0;
+ return;
+ }
cspec = Rgb;
- ct.argb.alpha = qRound(a * USHRT_MAX);
ct.argb.red = qRound(r * USHRT_MAX);
ct.argb.green = qRound(g * USHRT_MAX);
ct.argb.blue = qRound(b * USHRT_MAX);
+ ct.argb.alpha = qRound(a * USHRT_MAX);
ct.argb.pad = 0;
}
@@ -1306,7 +1349,7 @@ void QColor::setRgbF(qreal r, qreal g, qreal b, qreal a)
*/
void QColor::setRgb(int r, int g, int b, int a)
{
- if ((uint)r > 255 || (uint)g > 255 || (uint)b > 255 || (uint)a > 255) {
+ if (!isRgbaValid(r, g, b, a)) {
qWarning("QColor::setRgb: RGB parameters out of range");
invalidate();
return;
@@ -1330,7 +1373,7 @@ void QColor::setRgb(int r, int g, int b, int a)
\sa setRgba(), rgb(), rgba64()
*/
-QRgb QColor::rgba() const Q_DECL_NOTHROW
+QRgb QColor::rgba() const noexcept
{
if (cspec != Invalid && cspec != Rgb)
return toRgb().rgba();
@@ -1342,7 +1385,7 @@ QRgb QColor::rgba() const Q_DECL_NOTHROW
\sa rgba(), rgb(), setRgba64()
*/
-void QColor::setRgba(QRgb rgba) Q_DECL_NOTHROW
+void QColor::setRgba(QRgb rgba) noexcept
{
cspec = Rgb;
ct.argb.alpha = qAlpha(rgba) * 0x101;
@@ -1362,7 +1405,7 @@ void QColor::setRgba(QRgb rgba) Q_DECL_NOTHROW
\sa setRgba64(), rgba(), rgb()
*/
-QRgba64 QColor::rgba64() const Q_DECL_NOTHROW
+QRgba64 QColor::rgba64() const noexcept
{
if (cspec != Invalid && cspec != Rgb)
return toRgb().rgba64();
@@ -1376,7 +1419,7 @@ QRgba64 QColor::rgba64() const Q_DECL_NOTHROW
\sa setRgba(), rgba64()
*/
-void QColor::setRgba64(QRgba64 rgba) Q_DECL_NOTHROW
+void QColor::setRgba64(QRgba64 rgba) noexcept
{
cspec = Rgb;
ct.argb.alpha = rgba.alpha();
@@ -1393,7 +1436,7 @@ void QColor::setRgba64(QRgba64 rgba) Q_DECL_NOTHROW
\sa getRgb(), rgba()
*/
-QRgb QColor::rgb() const Q_DECL_NOTHROW
+QRgb QColor::rgb() const noexcept
{
if (cspec != Invalid && cspec != Rgb)
return toRgb().rgb();
@@ -1405,7 +1448,7 @@ QRgb QColor::rgb() const Q_DECL_NOTHROW
Sets the RGB value to \a rgb. The alpha value is set to opaque.
*/
-void QColor::setRgb(QRgb rgb) Q_DECL_NOTHROW
+void QColor::setRgb(QRgb rgb) noexcept
{
cspec = Rgb;
ct.argb.alpha = 0xffff;
@@ -1420,8 +1463,12 @@ void QColor::setRgb(QRgb rgb) Q_DECL_NOTHROW
\sa setAlpha(), alphaF(), {QColor#Alpha-Blended Drawing}{Alpha-Blended Drawing}
*/
-int QColor::alpha() const Q_DECL_NOTHROW
-{ return ct.argb.alpha >> 8; }
+int QColor::alpha() const noexcept
+{
+ if (cspec == ExtendedRgb)
+ return qRound(qreal(castF16(ct.argbExtended.alphaF16)) * 255);
+ return ct.argb.alpha >> 8;
+}
/*!
@@ -1434,6 +1481,11 @@ int QColor::alpha() const Q_DECL_NOTHROW
void QColor::setAlpha(int alpha)
{
QCOLOR_INT_RANGE_CHECK("QColor::setAlpha", alpha);
+ if (cspec == ExtendedRgb) {
+ constexpr qreal f = qreal(1.0) / 255;
+ castF16(ct.argbExtended.alphaF16) = alpha * f;
+ return;
+ }
ct.argb.alpha = alpha * 0x101;
}
@@ -1442,8 +1494,12 @@ void QColor::setAlpha(int alpha)
\sa setAlphaF(), alpha(), {QColor#Alpha-Blended Drawing}{Alpha-Blended Drawing}
*/
-qreal QColor::alphaF() const Q_DECL_NOTHROW
-{ return ct.argb.alpha / qreal(USHRT_MAX); }
+qreal QColor::alphaF() const noexcept
+{
+ if (cspec == ExtendedRgb)
+ return castF16(ct.argbExtended.alphaF16);
+ return ct.argb.alpha / qreal(USHRT_MAX);
+}
/*!
Sets the alpha of this color to \a alpha. qreal alpha is specified in the
@@ -1455,6 +1511,10 @@ qreal QColor::alphaF() const Q_DECL_NOTHROW
void QColor::setAlphaF(qreal alpha)
{
QCOLOR_REAL_RANGE_CHECK("QColor::setAlphaF", alpha);
+ if (cspec == ExtendedRgb) {
+ castF16(ct.argbExtended.alphaF16) = alpha;
+ return;
+ }
qreal tmp = alpha * USHRT_MAX;
ct.argb.alpha = qRound(tmp);
}
@@ -1465,7 +1525,7 @@ void QColor::setAlphaF(qreal alpha)
\sa setRed(), redF(), getRgb()
*/
-int QColor::red() const Q_DECL_NOTHROW
+int QColor::red() const noexcept
{
if (cspec != Invalid && cspec != Rgb)
return toRgb().red();
@@ -1492,7 +1552,7 @@ void QColor::setRed(int red)
\sa setGreen(), greenF(), getRgb()
*/
-int QColor::green() const Q_DECL_NOTHROW
+int QColor::green() const noexcept
{
if (cspec != Invalid && cspec != Rgb)
return toRgb().green();
@@ -1520,7 +1580,7 @@ void QColor::setGreen(int green)
\sa setBlue(), blueF(), getRgb()
*/
-int QColor::blue() const Q_DECL_NOTHROW
+int QColor::blue() const noexcept
{
if (cspec != Invalid && cspec != Rgb)
return toRgb().blue();
@@ -1548,27 +1608,31 @@ void QColor::setBlue(int blue)
\sa setRedF(), red(), getRgbF()
*/
-qreal QColor::redF() const Q_DECL_NOTHROW
+qreal QColor::redF() const noexcept
{
- if (cspec != Invalid && cspec != Rgb)
- return toRgb().redF();
- return ct.argb.red / qreal(USHRT_MAX);
+ if (cspec == Rgb || cspec == Invalid)
+ return ct.argb.red / qreal(USHRT_MAX);
+ if (cspec == ExtendedRgb)
+ return castF16(ct.argbExtended.redF16);
+
+ return toRgb().redF();
}
/*!
- Sets the red color component of this color to \a red. Float components
- are specified in the range 0.0-1.0.
+ Sets the red color component of this color to \a red. If \a red lies outside
+ the 0.0-1.0 range, the color model will be changed to \c ExtendedRgb.
\sa redF(), red(), setRgbF()
*/
void QColor::setRedF(qreal red)
{
- QCOLOR_REAL_RANGE_CHECK("QColor::setRedF", red);
- if (cspec != Rgb)
- setRgbF(red, greenF(), blueF(), alphaF());
- else
+ if (cspec == Rgb && red >= qreal(0.0) && red <= qreal(1.0))
ct.argb.red = qRound(red * USHRT_MAX);
+ else if (cspec == ExtendedRgb)
+ castF16(ct.argbExtended.redF16) = red;
+ else
+ setRgbF(red, greenF(), blueF(), alphaF());
}
/*!
@@ -1576,27 +1640,31 @@ void QColor::setRedF(qreal red)
\sa setGreenF(), green(), getRgbF()
*/
-qreal QColor::greenF() const Q_DECL_NOTHROW
+qreal QColor::greenF() const noexcept
{
- if (cspec != Invalid && cspec != Rgb)
- return toRgb().greenF();
- return ct.argb.green / qreal(USHRT_MAX);
+ if (cspec == Rgb || cspec == Invalid)
+ return ct.argb.green / qreal(USHRT_MAX);
+ if (cspec == ExtendedRgb)
+ return castF16(ct.argbExtended.greenF16);
+
+ return toRgb().greenF();
}
/*!
- Sets the green color component of this color to \a green. Float components
- are specified in the range 0.0-1.0.
+ Sets the green color component of this color to \a green. If \a green lies outside
+ the 0.0-1.0 range, the color model will be changed to \c ExtendedRgb.
\sa greenF(), green(), setRgbF()
*/
void QColor::setGreenF(qreal green)
{
- QCOLOR_REAL_RANGE_CHECK("QColor::setGreenF", green);
- if (cspec != Rgb)
- setRgbF(redF(), green, blueF(), alphaF());
- else
+ if (cspec == Rgb && green >= qreal(0.0) && green <= qreal(1.0))
ct.argb.green = qRound(green * USHRT_MAX);
+ else if (cspec == ExtendedRgb)
+ castF16(ct.argbExtended.greenF16) = green;
+ else
+ setRgbF(redF(), green, blueF(), alphaF());
}
/*!
@@ -1604,26 +1672,29 @@ void QColor::setGreenF(qreal green)
\sa setBlueF(), blue(), getRgbF()
*/
-qreal QColor::blueF() const Q_DECL_NOTHROW
+qreal QColor::blueF() const noexcept
{
- if (cspec != Invalid && cspec != Rgb)
- return toRgb().blueF();
- return ct.argb.blue / qreal(USHRT_MAX);
+ if (cspec == Rgb || cspec == Invalid)
+ return ct.argb.blue / qreal(USHRT_MAX);
+ if (cspec == ExtendedRgb)
+ return castF16(ct.argbExtended.blueF16);
+
+ return toRgb().blueF();
}
/*!
- Sets the blue color component of this color to \a blue. Float components
- are specified in the range 0.0-1.0.
-
+ Sets the blue color component of this color to \a blue. If \a blue lies outside
+ the 0.0-1.0 range, the color model will be changed to \c ExtendedRgb.
\sa blueF(), blue(), setRgbF()
*/
void QColor::setBlueF(qreal blue)
{
- QCOLOR_REAL_RANGE_CHECK("QColor::setBlueF", blue);
- if (cspec != Rgb)
- setRgbF(redF(), greenF(), blue, alphaF());
- else
+ if (cspec == Rgb && blue >= qreal(0.0) && blue <= qreal(1.0))
ct.argb.blue = qRound(blue * USHRT_MAX);
+ else if (cspec == ExtendedRgb)
+ castF16(ct.argbExtended.blueF16) = blue;
+ else
+ setRgbF(redF(), greenF(), blue, alphaF());
}
/*!
@@ -1634,7 +1705,7 @@ void QColor::setBlueF(qreal blue)
\sa hsvHue(), hslHue(), hueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color Model}
*/
-int QColor::hue() const Q_DECL_NOTHROW
+int QColor::hue() const noexcept
{
return hsvHue();
}
@@ -1644,7 +1715,7 @@ int QColor::hue() const Q_DECL_NOTHROW
\sa hueF(), hslHue(), getHsv(), {QColor#The HSV Color Model}{The HSV Color Model}
*/
-int QColor::hsvHue() const Q_DECL_NOTHROW
+int QColor::hsvHue() const noexcept
{
if (cspec != Invalid && cspec != Hsv)
return toHsv().hue();
@@ -1660,7 +1731,7 @@ int QColor::hsvHue() const Q_DECL_NOTHROW
Model}
*/
-int QColor::saturation() const Q_DECL_NOTHROW
+int QColor::saturation() const noexcept
{
return hsvSaturation();
}
@@ -1670,7 +1741,7 @@ int QColor::saturation() const Q_DECL_NOTHROW
\sa saturationF(), hslSaturation(), getHsv(), {QColor#The HSV Color Model}{The HSV Color Model}
*/
-int QColor::hsvSaturation() const Q_DECL_NOTHROW
+int QColor::hsvSaturation() const noexcept
{
if (cspec != Invalid && cspec != Hsv)
return toHsv().saturation();
@@ -1682,7 +1753,7 @@ int QColor::hsvSaturation() const Q_DECL_NOTHROW
\sa valueF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color Model}
*/
-int QColor::value() const Q_DECL_NOTHROW
+int QColor::value() const noexcept
{
if (cspec != Invalid && cspec != Hsv)
return toHsv().value();
@@ -1696,7 +1767,7 @@ int QColor::value() const Q_DECL_NOTHROW
\sa hsvHueF(), hslHueF(), hue(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color Model}
*/
-qreal QColor::hueF() const Q_DECL_NOTHROW
+qreal QColor::hueF() const noexcept
{
return hsvHueF();
}
@@ -1707,7 +1778,7 @@ qreal QColor::hueF() const Q_DECL_NOTHROW
\sa hue(), hslHueF(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color
Model}
*/
-qreal QColor::hsvHueF() const Q_DECL_NOTHROW
+qreal QColor::hsvHueF() const noexcept
{
if (cspec != Invalid && cspec != Hsv)
return toHsv().hueF();
@@ -1722,7 +1793,7 @@ qreal QColor::hsvHueF() const Q_DECL_NOTHROW
\sa hsvSaturationF(), hslSaturationF(), saturation(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color
Model}
*/
-qreal QColor::saturationF() const Q_DECL_NOTHROW
+qreal QColor::saturationF() const noexcept
{
return hsvSaturationF();
}
@@ -1732,7 +1803,7 @@ qreal QColor::saturationF() const Q_DECL_NOTHROW
\sa saturation(), hslSaturationF(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color Model}
*/
-qreal QColor::hsvSaturationF() const Q_DECL_NOTHROW
+qreal QColor::hsvSaturationF() const noexcept
{
if (cspec != Invalid && cspec != Hsv)
return toHsv().saturationF();
@@ -1744,7 +1815,7 @@ qreal QColor::hsvSaturationF() const Q_DECL_NOTHROW
\sa value(), getHsvF(), {QColor#The HSV Color Model}{The HSV Color Model}
*/
-qreal QColor::valueF() const Q_DECL_NOTHROW
+qreal QColor::valueF() const noexcept
{
if (cspec != Invalid && cspec != Hsv)
return toHsv().valueF();
@@ -1758,7 +1829,7 @@ qreal QColor::valueF() const Q_DECL_NOTHROW
\sa hslHueF(), hsvHue(), getHsl(), {QColor#The HSL Color Model}{The HSL Color Model}
*/
-int QColor::hslHue() const Q_DECL_NOTHROW
+int QColor::hslHue() const noexcept
{
if (cspec != Invalid && cspec != Hsl)
return toHsl().hslHue();
@@ -1772,7 +1843,7 @@ int QColor::hslHue() const Q_DECL_NOTHROW
\sa hslSaturationF(), hsvSaturation(), getHsl(), {QColor#The HSL Color Model}{The HSL Color Model}
*/
-int QColor::hslSaturation() const Q_DECL_NOTHROW
+int QColor::hslSaturation() const noexcept
{
if (cspec != Invalid && cspec != Hsl)
return toHsl().hslSaturation();
@@ -1786,7 +1857,7 @@ int QColor::hslSaturation() const Q_DECL_NOTHROW
\sa lightnessF(), getHsl()
*/
-int QColor::lightness() const Q_DECL_NOTHROW
+int QColor::lightness() const noexcept
{
if (cspec != Invalid && cspec != Hsl)
return toHsl().lightness();
@@ -1800,7 +1871,7 @@ int QColor::lightness() const Q_DECL_NOTHROW
\sa hslHue(), hsvHueF(), getHslF()
*/
-qreal QColor::hslHueF() const Q_DECL_NOTHROW
+qreal QColor::hslHueF() const noexcept
{
if (cspec != Invalid && cspec != Hsl)
return toHsl().hslHueF();
@@ -1814,7 +1885,7 @@ qreal QColor::hslHueF() const Q_DECL_NOTHROW
\sa hslSaturation(), hsvSaturationF(), getHslF(), {QColor#The HSL Color Model}{The HSL Color Model}
*/
-qreal QColor::hslSaturationF() const Q_DECL_NOTHROW
+qreal QColor::hslSaturationF() const noexcept
{
if (cspec != Invalid && cspec != Hsl)
return toHsl().hslSaturationF();
@@ -1828,7 +1899,7 @@ qreal QColor::hslSaturationF() const Q_DECL_NOTHROW
\sa value(), getHslF()
*/
-qreal QColor::lightnessF() const Q_DECL_NOTHROW
+qreal QColor::lightnessF() const noexcept
{
if (cspec != Invalid && cspec != Hsl)
return toHsl().lightnessF();
@@ -1840,7 +1911,7 @@ qreal QColor::lightnessF() const Q_DECL_NOTHROW
\sa cyanF(), getCmyk(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-int QColor::cyan() const Q_DECL_NOTHROW
+int QColor::cyan() const noexcept
{
if (cspec != Invalid && cspec != Cmyk)
return toCmyk().cyan();
@@ -1852,7 +1923,7 @@ int QColor::cyan() const Q_DECL_NOTHROW
\sa magentaF(), getCmyk(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-int QColor::magenta() const Q_DECL_NOTHROW
+int QColor::magenta() const noexcept
{
if (cspec != Invalid && cspec != Cmyk)
return toCmyk().magenta();
@@ -1864,7 +1935,7 @@ int QColor::magenta() const Q_DECL_NOTHROW
\sa yellowF(), getCmyk(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-int QColor::yellow() const Q_DECL_NOTHROW
+int QColor::yellow() const noexcept
{
if (cspec != Invalid && cspec != Cmyk)
return toCmyk().yellow();
@@ -1877,7 +1948,7 @@ int QColor::yellow() const Q_DECL_NOTHROW
\sa blackF(), getCmyk(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-int QColor::black() const Q_DECL_NOTHROW
+int QColor::black() const noexcept
{
if (cspec != Invalid && cspec != Cmyk)
return toCmyk().black();
@@ -1889,7 +1960,7 @@ int QColor::black() const Q_DECL_NOTHROW
\sa cyan(), getCmykF(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-qreal QColor::cyanF() const Q_DECL_NOTHROW
+qreal QColor::cyanF() const noexcept
{
if (cspec != Invalid && cspec != Cmyk)
return toCmyk().cyanF();
@@ -1901,7 +1972,7 @@ qreal QColor::cyanF() const Q_DECL_NOTHROW
\sa magenta(), getCmykF(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-qreal QColor::magentaF() const Q_DECL_NOTHROW
+qreal QColor::magentaF() const noexcept
{
if (cspec != Invalid && cspec != Cmyk)
return toCmyk().magentaF();
@@ -1913,7 +1984,7 @@ qreal QColor::magentaF() const Q_DECL_NOTHROW
\sa yellow(), getCmykF(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-qreal QColor::yellowF() const Q_DECL_NOTHROW
+qreal QColor::yellowF() const noexcept
{
if (cspec != Invalid && cspec != Cmyk)
return toCmyk().yellowF();
@@ -1925,7 +1996,7 @@ qreal QColor::yellowF() const Q_DECL_NOTHROW
\sa black(), getCmykF(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-qreal QColor::blackF() const Q_DECL_NOTHROW
+qreal QColor::blackF() const noexcept
{
if (cspec != Invalid && cspec != Cmyk)
return toCmyk().blackF();
@@ -1933,18 +2004,43 @@ qreal QColor::blackF() const Q_DECL_NOTHROW
}
/*!
+ Create and returns an extended RGB QColor based on this color.
+ \since 5.14
+
+ \sa toRgb, convertTo()
+*/
+QColor QColor::toExtendedRgb() const noexcept
+{
+ if (!isValid() || cspec == ExtendedRgb)
+ return *this;
+ if (cspec != Rgb)
+ return toRgb().toExtendedRgb();
+
+ constexpr qreal f = qreal(1.0) / USHRT_MAX;
+ QColor color;
+ color.cspec = ExtendedRgb;
+ castF16(color.ct.argbExtended.alphaF16) = qfloat16(ct.argb.alpha * f);
+ castF16(color.ct.argbExtended.redF16) = qfloat16(ct.argb.red * f);
+ castF16(color.ct.argbExtended.greenF16) = qfloat16(ct.argb.green * f);
+ castF16(color.ct.argbExtended.blueF16) = qfloat16(ct.argb.blue * f);
+ color.ct.argbExtended.pad = 0;
+ return color;
+}
+
+/*!
Create and returns an RGB QColor based on this color.
\sa fromRgb(), convertTo(), isValid()
*/
-QColor QColor::toRgb() const Q_DECL_NOTHROW
+QColor QColor::toRgb() const noexcept
{
if (!isValid() || cspec == Rgb)
return *this;
QColor color;
color.cspec = Rgb;
- color.ct.argb.alpha = ct.argb.alpha;
+ if (cspec != ExtendedRgb)
+ color.ct.argb.alpha = ct.argb.alpha;
color.ct.argb.pad = 0;
switch (cspec) {
@@ -2066,6 +2162,12 @@ QColor QColor::toRgb() const Q_DECL_NOTHROW
color.ct.argb.blue = qRound((qreal(1.0) - (y * (qreal(1.0) - k) + k)) * USHRT_MAX);
break;
}
+ case ExtendedRgb:
+ color.ct.argb.alpha = qRound(USHRT_MAX * qreal(castF16(ct.argbExtended.alphaF16)));
+ color.ct.argb.red = qRound(USHRT_MAX * qBound(qreal(0.0), qreal(castF16(ct.argbExtended.redF16)), qreal(1.0)));
+ color.ct.argb.green = qRound(USHRT_MAX * qBound(qreal(0.0), qreal(castF16(ct.argbExtended.greenF16)), qreal(1.0)));
+ color.ct.argb.blue = qRound(USHRT_MAX * qBound(qreal(0.0), qreal(castF16(ct.argbExtended.blueF16)), qreal(1.0)));
+ break;
default:
break;
}
@@ -2083,7 +2185,7 @@ QColor QColor::toRgb() const Q_DECL_NOTHROW
\sa fromHsv(), convertTo(), isValid(), {QColor#The HSV Color Model}{The HSV Color Model}
*/
-QColor QColor::toHsv() const Q_DECL_NOTHROW
+QColor QColor::toHsv() const noexcept
{
if (!isValid() || cspec == Hsv)
return *this;
@@ -2134,7 +2236,7 @@ QColor QColor::toHsv() const Q_DECL_NOTHROW
\sa fromHsl(), convertTo(), isValid(), {QColor#The HSL Color Model}{The HSL Color Model}
*/
-QColor QColor::toHsl() const Q_DECL_NOTHROW
+QColor QColor::toHsl() const noexcept
{
if (!isValid() || cspec == Hsl)
return *this;
@@ -2190,7 +2292,7 @@ QColor QColor::toHsl() const Q_DECL_NOTHROW
\sa fromCmyk(), convertTo(), isValid(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-QColor QColor::toCmyk() const Q_DECL_NOTHROW
+QColor QColor::toCmyk() const noexcept
{
if (!isValid() || cspec == Cmyk)
return *this;
@@ -2231,13 +2333,15 @@ QColor QColor::toCmyk() const Q_DECL_NOTHROW
return color;
}
-QColor QColor::convertTo(QColor::Spec colorSpec) const Q_DECL_NOTHROW
+QColor QColor::convertTo(QColor::Spec colorSpec) const noexcept
{
if (colorSpec == cspec)
return *this;
switch (colorSpec) {
case Rgb:
return toRgb();
+ case ExtendedRgb:
+ return toExtendedRgb();
case Hsv:
return toHsv();
case Cmyk:
@@ -2262,7 +2366,7 @@ QColor QColor::convertTo(QColor::Spec colorSpec) const Q_DECL_NOTHROW
\sa fromRgba(), fromRgbF(), toRgb(), isValid()
*/
-QColor QColor::fromRgb(QRgb rgb) Q_DECL_NOTHROW
+QColor QColor::fromRgb(QRgb rgb) noexcept
{
return fromRgb(qRed(rgb), qGreen(rgb), qBlue(rgb));
}
@@ -2278,7 +2382,7 @@ QColor QColor::fromRgb(QRgb rgb) Q_DECL_NOTHROW
\sa fromRgb(), fromRgba64(), isValid()
*/
-QColor QColor::fromRgba(QRgb rgba) Q_DECL_NOTHROW
+QColor QColor::fromRgba(QRgb rgba) noexcept
{
return fromRgb(qRed(rgba), qGreen(rgba), qBlue(rgba), qAlpha(rgba));
}
@@ -2294,10 +2398,7 @@ QColor QColor::fromRgba(QRgb rgba) Q_DECL_NOTHROW
*/
QColor QColor::fromRgb(int r, int g, int b, int a)
{
- if (r < 0 || r > 255
- || g < 0 || g > 255
- || b < 0 || b > 255
- || a < 0 || a > 255) {
+ if (!isRgbaValid(r, g, b, a)) {
qWarning("QColor::fromRgb: RGB parameters out of range");
return QColor();
}
@@ -2317,20 +2418,32 @@ QColor QColor::fromRgb(int r, int g, int b, int a)
color values, \a r (red), \a g (green), \a b (blue), and \a a
(alpha-channel, i.e. transparency).
- All the values must be in the range 0.0-1.0.
+ The alpha value must be in the range 0.0-1.0.
+ If any of the other values are outside the range of 0.0-1.0 the
+ color model will be set as \c ExtendedRgb.
\sa fromRgb(), fromRgba64(), toRgb(), isValid()
*/
QColor QColor::fromRgbF(qreal r, qreal g, qreal b, qreal a)
{
- if (r < qreal(0.0) || r > qreal(1.0)
- || g < qreal(0.0) || g > qreal(1.0)
- || b < qreal(0.0) || b > qreal(1.0)
- || a < qreal(0.0) || a > qreal(1.0)) {
- qWarning("QColor::fromRgbF: RGB parameters out of range");
+ if (a < qreal(0.0) || a > qreal(1.0)) {
+ qWarning("QColor::fromRgbF: Alpha parameter out of range");
return QColor();
}
+ if (r < qreal(0.0) || r > qreal(1.0)
+ || g < qreal(0.0) || g > qreal(1.0)
+ || b < qreal(0.0) || b > qreal(1.0)) {
+ QColor color;
+ color.cspec = ExtendedRgb;
+ castF16(color.ct.argbExtended.alphaF16) = qfloat16(a);
+ castF16(color.ct.argbExtended.redF16) = qfloat16(r);
+ castF16(color.ct.argbExtended.greenF16) = qfloat16(g);
+ castF16(color.ct.argbExtended.blueF16) = qfloat16(b);
+ color.ct.argbExtended.pad = 0;
+ return color;
+ }
+
QColor color;
color.cspec = Rgb;
color.ct.argb.alpha = qRound(a * USHRT_MAX);
@@ -2351,7 +2464,7 @@ QColor QColor::fromRgbF(qreal r, qreal g, qreal b, qreal a)
\sa fromRgb(), fromRgbF(), toRgb(), isValid()
*/
-QColor QColor::fromRgba64(ushort r, ushort g, ushort b, ushort a) Q_DECL_NOTHROW
+QColor QColor::fromRgba64(ushort r, ushort g, ushort b, ushort a) noexcept
{
QColor color;
color.setRgba64(qRgba64(r, g, b, a));
@@ -2366,7 +2479,7 @@ QColor QColor::fromRgba64(ushort r, ushort g, ushort b, ushort a) Q_DECL_NOTHROW
\sa fromRgb(), fromRgbF(), toRgb(), isValid()
*/
-QColor QColor::fromRgba64(QRgba64 rgba64) Q_DECL_NOTHROW
+QColor QColor::fromRgba64(QRgba64 rgba64) noexcept
{
QColor color;
color.setRgba64(rgba64);
@@ -2500,6 +2613,15 @@ QColor QColor::fromHslF(qreal h, qreal s, qreal l, qreal a)
return color;
}
+/*!
+ \obsolete
+
+ Use the \c const overload instead.
+*/
+void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a)
+{
+ const_cast<const QColor *>(this)->getCmyk(c, m, y, k, a);
+}
/*!
Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the
@@ -2511,7 +2633,7 @@ QColor QColor::fromHslF(qreal h, qreal s, qreal l, qreal a)
\sa setCmyk(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a)
+void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a) const
{
if (!c || !m || !y || !k)
return;
@@ -2531,6 +2653,16 @@ void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a)
}
/*!
+ \obsolete
+
+ Use the \c const overload instead.
+*/
+void QColor::getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a)
+{
+ const_cast<const QColor *>(this)->getCmykF(c, m, y, k, a);
+}
+
+/*!
Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the
cyan, magenta, yellow, black, and alpha-channel (transparency) components
of the color's CMYK value.
@@ -2540,7 +2672,7 @@ void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a)
\sa setCmykF(), {QColor#The CMYK Color Model}{The CMYK Color Model}
*/
-void QColor::getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a)
+void QColor::getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a) const
{
if (!c || !m || !y || !k)
return;
@@ -2689,18 +2821,13 @@ QColor QColor::fromCmykF(qreal c, qreal m, qreal y, qreal k, qreal a)
recommend using the darker() function for this purpose. If the \a factor
is 0 or negative, the return value is unspecified.
- The function converts the current RGB color to HSV, multiplies the value
- (V) component by \a factor and converts the color back to RGB.
+ The function converts the current color to HSV, multiplies the value
+ (V) component by \a factor and converts the color back to it's original
+ color spec.
\sa darker(), isValid()
*/
-
-/*!
- \obsolete
-
- Use lighter(\a factor) instead.
-*/
-QColor QColor::light(int factor) const Q_DECL_NOTHROW
+QColor QColor::lighter(int factor) const noexcept
{
if (factor <= 0) // invalid lightness factor
return *this;
@@ -2739,18 +2866,13 @@ QColor QColor::light(int factor) const Q_DECL_NOTHROW
but we recommend using the lighter() function for this purpose. If the
\a factor is 0 or negative, the return value is unspecified.
- The function converts the current RGB color to HSV, divides the value (V)
- component by \a factor and converts the color back to RGB.
+ The function converts the current color to HSV, divides the value (V)
+ component by \a factor and converts the color back to it's original
+ color spec.
\sa lighter(), isValid()
*/
-
-/*!
- \obsolete
-
- Use darker(\a factor) instead.
-*/
-QColor QColor::dark(int factor) const Q_DECL_NOTHROW
+QColor QColor::darker(int factor) const noexcept
{
if (factor <= 0) // invalid darkness factor
return *this;
@@ -2764,11 +2886,33 @@ QColor QColor::dark(int factor) const Q_DECL_NOTHROW
return hsv.convertTo(cspec);
}
+#if QT_DEPRECATED_SINCE(5, 13)
+/*!
+ \obsolete
+
+ Use lighter(\a factor) instead.
+*/
+QColor QColor::light(int factor) const noexcept
+{
+ return lighter(factor);
+}
+
+/*!
+ \obsolete
+
+ Use darker(\a factor) instead.
+*/
+QColor QColor::dark(int factor) const noexcept
+{
+ return darker(factor);
+}
+#endif
+
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
/*!
Assigns a copy of \a color to this color, and returns a reference to it.
*/
-QColor &QColor::operator=(const QColor &color) Q_DECL_NOTHROW
+QColor &QColor::operator=(const QColor &color) noexcept
{
cspec = color.cspec;
ct.argb = color.ct.argb;
@@ -2779,7 +2923,7 @@ QColor &QColor::operator=(const QColor &color) Q_DECL_NOTHROW
/*! \overload
Assigns a copy of \a color and returns a reference to this color.
*/
-QColor &QColor::operator=(Qt::GlobalColor color) Q_DECL_NOTHROW
+QColor &QColor::operator=(Qt::GlobalColor color) noexcept
{
return operator=(QColor(color));
}
@@ -2788,7 +2932,7 @@ QColor &QColor::operator=(Qt::GlobalColor color) Q_DECL_NOTHROW
Returns \c true if this color has the same RGB and alpha values as \a color;
otherwise returns \c false.
*/
-bool QColor::operator==(const QColor &color) const Q_DECL_NOTHROW
+bool QColor::operator==(const QColor &color) const noexcept
{
if (cspec == Hsl && cspec == color.cspec) {
return (ct.argb.alpha == color.ct.argb.alpha
@@ -2815,7 +2959,7 @@ bool QColor::operator==(const QColor &color) const Q_DECL_NOTHROW
Returns \c true if this color has a different RGB and alpha values from
\a color; otherwise returns \c false.
*/
-bool QColor::operator!=(const QColor &color) const Q_DECL_NOTHROW
+bool QColor::operator!=(const QColor &color) const noexcept
{ return !operator==(color); }
@@ -2832,7 +2976,7 @@ QColor::operator QVariant() const
Marks the color as invalid and sets all components to zero (alpha is set
to fully opaque for compatibility with Qt 3).
*/
-void QColor::invalidate() Q_DECL_NOTHROW
+void QColor::invalidate() noexcept
{
cspec = Invalid;
ct.argb.alpha = USHRT_MAX;
@@ -2854,6 +2998,8 @@ QDebug operator<<(QDebug dbg, const QColor &c)
dbg.nospace() << "QColor(Invalid)";
else if (c.spec() == QColor::Rgb)
dbg.nospace() << "QColor(ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ')';
+ else if (c.spec() == QColor::ExtendedRgb)
+ dbg.nospace() << "QColor(Ext. ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ')';
else if (c.spec() == QColor::Hsv)
dbg.nospace() << "QColor(AHSV " << c.alphaF() << ", " << c.hueF() << ", " << c.saturationF() << ", " << c.valueF() << ')';
else if (c.spec() == QColor::Cmyk)
diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h
index f7a9e9db59..723b9fce73 100644
--- a/src/gui/painting/qcolor.h
+++ b/src/gui/painting/qcolor.h
@@ -64,35 +64,43 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QColor &);
class Q_GUI_EXPORT QColor
{
public:
- enum Spec { Invalid, Rgb, Hsv, Cmyk, Hsl };
+ enum Spec { Invalid, Rgb, Hsv, Cmyk, Hsl, ExtendedRgb };
enum NameFormat { HexRgb, HexArgb };
- inline QColor() Q_DECL_NOTHROW;
- QColor(Qt::GlobalColor color) Q_DECL_NOTHROW;
- inline QColor(int r, int g, int b, int a = 255);
- QColor(QRgb rgb) Q_DECL_NOTHROW;
- QColor(QRgba64 rgba64) Q_DECL_NOTHROW;
+ Q_DECL_CONSTEXPR QColor() noexcept
+ : cspec(Invalid), ct(USHRT_MAX, 0, 0, 0, 0) {}
+ QColor(Qt::GlobalColor color) noexcept;
+ Q_DECL_CONSTEXPR QColor(int r, int g, int b, int a = 255) noexcept
+ : cspec(isRgbaValid(r, g, b, a) ? Rgb : Invalid),
+ ct(cspec == Rgb ? a * 0x0101 : 0,
+ cspec == Rgb ? r * 0x0101 : 0,
+ cspec == Rgb ? g * 0x0101 : 0,
+ cspec == Rgb ? b * 0x0101 : 0,
+ 0) {}
+ QColor(QRgb rgb) noexcept;
+ QColor(QRgba64 rgba64) noexcept;
#if QT_STRINGVIEW_LEVEL < 2
inline QColor(const QString& name);
#endif
explicit inline QColor(QStringView name);
inline QColor(const char *aname) : QColor(QLatin1String(aname)) {}
inline QColor(QLatin1String name);
- QColor(Spec spec) Q_DECL_NOTHROW;
+ QColor(Spec spec) noexcept;
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- inline QColor(const QColor &color) Q_DECL_NOTHROW; // ### Qt 6: remove all of these, the trivial ones are fine.
-# ifdef Q_COMPILER_RVALUE_REFS
- QColor(QColor &&other) Q_DECL_NOTHROW : cspec(other.cspec), ct(other.ct) {}
- QColor &operator=(QColor &&other) Q_DECL_NOTHROW
+ // ### Qt 6: remove all of these, the trivial ones are fine.
+ Q_DECL_CONSTEXPR QColor(const QColor &color) noexcept
+ : cspec(color.cspec), ct(color.ct)
+ {}
+ Q_DECL_CONSTEXPR QColor(QColor &&other) noexcept : cspec(other.cspec), ct(other.ct) {}
+ QColor &operator=(QColor &&other) noexcept
{ cspec = other.cspec; ct = other.ct; return *this; }
-# endif
- QColor &operator=(const QColor &) Q_DECL_NOTHROW;
+ QColor &operator=(const QColor &) noexcept;
#endif // Qt < 6
- QColor &operator=(Qt::GlobalColor color) Q_DECL_NOTHROW;
+ QColor &operator=(Qt::GlobalColor color) noexcept;
- bool isValid() const Q_DECL_NOTHROW;
+ bool isValid() const noexcept;
// ### Qt 6: merge overloads
QString name() const;
@@ -106,25 +114,25 @@ public:
static QStringList colorNames();
- inline Spec spec() const Q_DECL_NOTHROW
+ inline Spec spec() const noexcept
{ return cspec; }
- int alpha() const Q_DECL_NOTHROW;
+ int alpha() const noexcept;
void setAlpha(int alpha);
- qreal alphaF() const Q_DECL_NOTHROW;
+ qreal alphaF() const noexcept;
void setAlphaF(qreal alpha);
- int red() const Q_DECL_NOTHROW;
- int green() const Q_DECL_NOTHROW;
- int blue() const Q_DECL_NOTHROW;
+ int red() const noexcept;
+ int green() const noexcept;
+ int blue() const noexcept;
void setRed(int red);
void setGreen(int green);
void setBlue(int blue);
- qreal redF() const Q_DECL_NOTHROW;
- qreal greenF() const Q_DECL_NOTHROW;
- qreal blueF() const Q_DECL_NOTHROW;
+ qreal redF() const noexcept;
+ qreal greenF() const noexcept;
+ qreal blueF() const noexcept;
void setRedF(qreal red);
void setGreenF(qreal green);
void setBlueF(qreal blue);
@@ -135,26 +143,26 @@ public:
void getRgbF(qreal *r, qreal *g, qreal *b, qreal *a = nullptr) const;
void setRgbF(qreal r, qreal g, qreal b, qreal a = 1.0);
- QRgba64 rgba64() const Q_DECL_NOTHROW;
- void setRgba64(QRgba64 rgba) Q_DECL_NOTHROW;
+ QRgba64 rgba64() const noexcept;
+ void setRgba64(QRgba64 rgba) noexcept;
- QRgb rgba() const Q_DECL_NOTHROW;
- void setRgba(QRgb rgba) Q_DECL_NOTHROW;
+ QRgb rgba() const noexcept;
+ void setRgba(QRgb rgba) noexcept;
- QRgb rgb() const Q_DECL_NOTHROW;
- void setRgb(QRgb rgb) Q_DECL_NOTHROW;
+ QRgb rgb() const noexcept;
+ void setRgb(QRgb rgb) noexcept;
- int hue() const Q_DECL_NOTHROW; // 0 <= hue < 360
- int saturation() const Q_DECL_NOTHROW;
- int hsvHue() const Q_DECL_NOTHROW; // 0 <= hue < 360
- int hsvSaturation() const Q_DECL_NOTHROW;
- int value() const Q_DECL_NOTHROW;
+ int hue() const noexcept; // 0 <= hue < 360
+ int saturation() const noexcept;
+ int hsvHue() const noexcept; // 0 <= hue < 360
+ int hsvSaturation() const noexcept;
+ int value() const noexcept;
- qreal hueF() const Q_DECL_NOTHROW; // 0.0 <= hueF < 360.0
- qreal saturationF() const Q_DECL_NOTHROW;
- qreal hsvHueF() const Q_DECL_NOTHROW; // 0.0 <= hueF < 360.0
- qreal hsvSaturationF() const Q_DECL_NOTHROW;
- qreal valueF() const Q_DECL_NOTHROW;
+ qreal hueF() const noexcept; // 0.0 <= hueF < 360.0
+ qreal saturationF() const noexcept;
+ qreal hsvHueF() const noexcept; // 0.0 <= hueF < 360.0
+ qreal hsvSaturationF() const noexcept;
+ qreal valueF() const noexcept;
void getHsv(int *h, int *s, int *v, int *a = nullptr) const;
void setHsv(int h, int s, int v, int a = 255);
@@ -162,29 +170,31 @@ public:
void getHsvF(qreal *h, qreal *s, qreal *v, qreal *a = nullptr) const;
void setHsvF(qreal h, qreal s, qreal v, qreal a = 1.0);
- int cyan() const Q_DECL_NOTHROW;
- int magenta() const Q_DECL_NOTHROW;
- int yellow() const Q_DECL_NOTHROW;
- int black() const Q_DECL_NOTHROW;
+ int cyan() const noexcept;
+ int magenta() const noexcept;
+ int yellow() const noexcept;
+ int black() const noexcept;
- qreal cyanF() const Q_DECL_NOTHROW;
- qreal magentaF() const Q_DECL_NOTHROW;
- qreal yellowF() const Q_DECL_NOTHROW;
- qreal blackF() const Q_DECL_NOTHROW;
+ qreal cyanF() const noexcept;
+ qreal magentaF() const noexcept;
+ qreal yellowF() const noexcept;
+ qreal blackF() const noexcept;
- void getCmyk(int *c, int *m, int *y, int *k, int *a = nullptr);
+ void getCmyk(int *c, int *m, int *y, int *k, int *a = nullptr); // ### Qt 6: remove
+ void getCmyk(int *c, int *m, int *y, int *k, int *a = nullptr) const;
void setCmyk(int c, int m, int y, int k, int a = 255);
- void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = nullptr);
+ void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = nullptr); // ### Qt 6: remove
+ void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = nullptr) const;
void setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a = 1.0);
- int hslHue() const Q_DECL_NOTHROW; // 0 <= hue < 360
- int hslSaturation() const Q_DECL_NOTHROW;
- int lightness() const Q_DECL_NOTHROW;
+ int hslHue() const noexcept; // 0 <= hue < 360
+ int hslSaturation() const noexcept;
+ int lightness() const noexcept;
- qreal hslHueF() const Q_DECL_NOTHROW; // 0.0 <= hueF < 360.0
- qreal hslSaturationF() const Q_DECL_NOTHROW;
- qreal lightnessF() const Q_DECL_NOTHROW;
+ qreal hslHueF() const noexcept; // 0.0 <= hueF < 360.0
+ qreal hslSaturationF() const noexcept;
+ qreal lightnessF() const noexcept;
void getHsl(int *h, int *s, int *l, int *a = nullptr) const;
void setHsl(int h, int s, int l, int a = 255);
@@ -192,21 +202,22 @@ public:
void getHslF(qreal *h, qreal *s, qreal *l, qreal *a = nullptr) const;
void setHslF(qreal h, qreal s, qreal l, qreal a = 1.0);
- QColor toRgb() const Q_DECL_NOTHROW;
- QColor toHsv() const Q_DECL_NOTHROW;
- QColor toCmyk() const Q_DECL_NOTHROW;
- QColor toHsl() const Q_DECL_NOTHROW;
+ QColor toRgb() const noexcept;
+ QColor toHsv() const noexcept;
+ QColor toCmyk() const noexcept;
+ QColor toHsl() const noexcept;
+ QColor toExtendedRgb() const noexcept;
- Q_REQUIRED_RESULT QColor convertTo(Spec colorSpec) const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT QColor convertTo(Spec colorSpec) const noexcept;
- static QColor fromRgb(QRgb rgb) Q_DECL_NOTHROW;
- static QColor fromRgba(QRgb rgba) Q_DECL_NOTHROW;
+ static QColor fromRgb(QRgb rgb) noexcept;
+ static QColor fromRgba(QRgb rgba) noexcept;
static QColor fromRgb(int r, int g, int b, int a = 255);
static QColor fromRgbF(qreal r, qreal g, qreal b, qreal a = 1.0);
- static QColor fromRgba64(ushort r, ushort g, ushort b, ushort a = USHRT_MAX) Q_DECL_NOTHROW;
- static QColor fromRgba64(QRgba64 rgba) Q_DECL_NOTHROW;
+ static QColor fromRgba64(ushort r, ushort g, ushort b, ushort a = USHRT_MAX) noexcept;
+ static QColor fromRgba64(QRgba64 rgba) noexcept;
static QColor fromHsv(int h, int s, int v, int a = 255);
static QColor fromHsvF(qreal h, qreal s, qreal v, qreal a = 1.0);
@@ -217,30 +228,44 @@ public:
static QColor fromHsl(int h, int s, int l, int a = 255);
static QColor fromHslF(qreal h, qreal s, qreal l, qreal a = 1.0);
- Q_REQUIRED_RESULT QColor light(int f = 150) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT QColor lighter(int f = 150) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT QColor dark(int f = 200) const Q_DECL_NOTHROW;
- Q_REQUIRED_RESULT QColor darker(int f = 200) const Q_DECL_NOTHROW;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QColor::lighter() instead")
+ Q_REQUIRED_RESULT QColor light(int f = 150) const noexcept;
+ QT_DEPRECATED_X("Use QColor::darker() instead")
+ Q_REQUIRED_RESULT QColor dark(int f = 200) const noexcept;
+#endif
+ Q_REQUIRED_RESULT QColor lighter(int f = 150) const noexcept;
+ Q_REQUIRED_RESULT QColor darker(int f = 200) const noexcept;
- bool operator==(const QColor &c) const Q_DECL_NOTHROW;
- bool operator!=(const QColor &c) const Q_DECL_NOTHROW;
+ bool operator==(const QColor &c) const noexcept;
+ bool operator!=(const QColor &c) const noexcept;
operator QVariant() const;
#if QT_STRINGVIEW_LEVEL < 2
static bool isValidColor(const QString &name);
#endif
- static bool isValidColor(QStringView) Q_DECL_NOTHROW;
- static bool isValidColor(QLatin1String) Q_DECL_NOTHROW;
+ static bool isValidColor(QStringView) noexcept;
+ static bool isValidColor(QLatin1String) noexcept;
private:
- void invalidate() Q_DECL_NOTHROW;
+ void invalidate() noexcept;
template <typename String>
bool setColorFromString(String name);
+ static Q_DECL_CONSTEXPR bool isRgbaValid(int r, int g, int b, int a = 255) noexcept Q_DECL_CONST_FUNCTION
+ {
+ return uint(r) <= 255 && uint(g) <= 255 && uint(b) <= 255 && uint(a) <= 255;
+ }
+
Spec cspec;
- union {
+ union CT {
+#ifdef Q_COMPILER_UNIFORM_INIT
+ CT() {} // doesn't init anything, thus can't be constexpr
+ Q_DECL_CONSTEXPR explicit CT(ushort a1, ushort a2, ushort a3, ushort a4, ushort a5) noexcept
+ : array{a1, a2, a3, a4, a5} {}
+#endif
struct {
ushort alpha;
ushort red;
@@ -269,6 +294,13 @@ private:
ushort lightness;
ushort pad;
} ahsl;
+ struct {
+ ushort alphaF16;
+ ushort redF16;
+ ushort greenF16;
+ ushort blueF16;
+ ushort pad;
+ } argbExtended;
ushort array[5];
} ct;
@@ -280,12 +312,6 @@ private:
};
Q_DECLARE_TYPEINFO(QColor, QT_VERSION >= QT_VERSION_CHECK(6,0,0) ? Q_MOVABLE_TYPE : Q_RELOCATABLE_TYPE);
-inline QColor::QColor() Q_DECL_NOTHROW
-{ invalidate(); }
-
-inline QColor::QColor(int r, int g, int b, int a)
-{ setRgb(r, g, b, a); }
-
inline QColor::QColor(QLatin1String aname)
{ setNamedColor(aname); }
@@ -297,21 +323,9 @@ inline QColor::QColor(const QString& aname)
{ setNamedColor(aname); }
#endif
-#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
-inline QColor::QColor(const QColor &acolor) Q_DECL_NOTHROW
- : cspec(acolor.cspec)
-{ ct.argb = acolor.ct.argb; }
-#endif
-
-inline bool QColor::isValid() const Q_DECL_NOTHROW
+inline bool QColor::isValid() const noexcept
{ return cspec != Invalid; }
-inline QColor QColor::lighter(int f) const Q_DECL_NOTHROW
-{ return light(f); }
-
-inline QColor QColor::darker(int f) const Q_DECL_NOTHROW
-{ return dark(f); }
-
QT_END_NAMESPACE
#endif // QCOLOR_H
diff --git a/src/gui/painting/qcolormatrix_p.h b/src/gui/painting/qcolormatrix_p.h
new file mode 100644
index 0000000000..66db95df7e
--- /dev/null
+++ b/src/gui/painting/qcolormatrix_p.h
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORMATRIX_H
+#define QCOLORMATRIX_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/qpoint.h>
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+// An abstract 3 value color
+class QColorVector
+{
+public:
+ QColorVector() = default;
+ Q_DECL_CONSTEXPR QColorVector(float x, float y, float z) : x(x), y(y), z(z), _unused(0.0f) { }
+ explicit Q_DECL_CONSTEXPR QColorVector(const QPointF &chr) // from XY chromaticity
+ : x(chr.x() / chr.y())
+ , y(1.0f)
+ , z((1.0 - chr.x() - chr.y()) / chr.y())
+ , _unused(0.0f)
+ { }
+ float x; // X, x or red
+ float y; // Y, y or green
+ float z; // Z, Y or blue
+ float _unused;
+
+ friend inline bool operator==(const QColorVector &v1, const QColorVector &v2);
+ friend inline bool operator!=(const QColorVector &v1, const QColorVector &v2);
+ bool isNull() const
+ {
+ return !x && !y && !z;
+ }
+
+ static Q_DECL_CONSTEXPR QColorVector null() { return QColorVector(0.0f, 0.0f, 0.0f); }
+ static bool isValidChromaticity(const QPointF &chr)
+ {
+ if (chr.x() < qreal(0.0) || chr.x() > qreal(1.0))
+ return false;
+ if (chr.y() <= qreal(0.0) || chr.y() > qreal(1.0))
+ return false;
+ if (chr.x() + chr.y() > qreal(1.0))
+ return false;
+ return true;
+ }
+
+ // Common whitepoints:
+ static Q_DECL_CONSTEXPR QPointF D50Chromaticity() { return QPointF(0.34567, 0.35850); }
+ static Q_DECL_CONSTEXPR QPointF D65Chromaticity() { return QPointF(0.31271, 0.32902); }
+ static Q_DECL_CONSTEXPR QColorVector D50() { return QColorVector(D50Chromaticity()); }
+ static Q_DECL_CONSTEXPR QColorVector D65() { return QColorVector(D65Chromaticity()); }
+};
+
+inline bool operator==(const QColorVector &v1, const QColorVector &v2)
+{
+ return (std::abs(v1.x - v2.x) < (1.0f / 2048.0f))
+ && (std::abs(v1.y - v2.y) < (1.0f / 2048.0f))
+ && (std::abs(v1.z - v2.z) < (1.0f / 2048.0f));
+}
+
+inline bool operator!=(const QColorVector &v1, const QColorVector &v2)
+{
+ return !(v1 == v2);
+}
+
+
+// A matrix mapping 3 value colors.
+// Not using QMatrix because only floats are needed and performance is critical.
+class QColorMatrix
+{
+public:
+ // We are storing the matrix transposed as that is more convenient:
+ QColorVector r;
+ QColorVector g;
+ QColorVector b;
+
+ friend inline bool operator==(const QColorMatrix &m1, const QColorMatrix &m2);
+ friend inline bool operator!=(const QColorMatrix &m1, const QColorMatrix &m2);
+
+ bool isNull() const
+ {
+ return r.isNull() && g.isNull() && b.isNull();
+ }
+ bool isValid() const
+ {
+ // A color matrix must be invertible
+ float det = r.x * (b.z * g.y - g.z * b.y) -
+ r.y * (b.z * g.x - g.z * b.x) +
+ r.z * (b.y * g.x - g.y * b.x);
+ return !qFuzzyIsNull(det);
+ }
+
+ QColorMatrix inverted() const
+ {
+ float det = r.x * (b.z * g.y - g.z * b.y) -
+ r.y * (b.z * g.x - g.z * b.x) +
+ r.z * (b.y * g.x - g.y * b.x);
+ det = 1.0f / det;
+ QColorMatrix inv;
+ inv.r.x = (g.y * b.z - b.y * g.z) * det;
+ inv.r.y = (b.y * r.z - r.y * b.z) * det;
+ inv.r.z = (r.y * g.z - g.y * r.z) * det;
+ inv.g.x = (b.x * g.z - g.x * b.z) * det;
+ inv.g.y = (r.x * b.z - b.x * r.z) * det;
+ inv.g.z = (g.x * r.z - r.x * g.z) * det;
+ inv.b.x = (g.x * b.y - b.x * g.y) * det;
+ inv.b.y = (b.x * r.y - r.x * b.y) * det;
+ inv.b.z = (r.x * g.y - g.x * r.y) * det;
+ return inv;
+ }
+ QColorMatrix operator*(const QColorMatrix &o) const
+ {
+ QColorMatrix comb;
+ comb.r.x = r.x * o.r.x + g.x * o.r.y + b.x * o.r.z;
+ comb.g.x = r.x * o.g.x + g.x * o.g.y + b.x * o.g.z;
+ comb.b.x = r.x * o.b.x + g.x * o.b.y + b.x * o.b.z;
+
+ comb.r.y = r.y * o.r.x + g.y * o.r.y + b.y * o.r.z;
+ comb.g.y = r.y * o.g.x + g.y * o.g.y + b.y * o.g.z;
+ comb.b.y = r.y * o.b.x + g.y * o.b.y + b.y * o.b.z;
+
+ comb.r.z = r.z * o.r.x + g.z * o.r.y + b.z * o.r.z;
+ comb.g.z = r.z * o.g.x + g.z * o.g.y + b.z * o.g.z;
+ comb.b.z = r.z * o.b.x + g.z * o.b.y + b.z * o.b.z;
+ return comb;
+
+ }
+ QColorVector map(const QColorVector &c) const
+ {
+ return QColorVector { c.x * r.x + c.y * g.x + c.z * b.x,
+ c.x * r.y + c.y * g.y + c.z * b.y,
+ c.x * r.z + c.y * g.z + c.z * b.z };
+ }
+ QColorMatrix transposed() const
+ {
+ return QColorMatrix { { r.x, g.x, b.x },
+ { r.y, g.y, b.y },
+ { r.z, g.z, b.z } };
+ }
+
+ static QColorMatrix null()
+ {
+ return { QColorVector::null(), QColorVector::null(), QColorVector::null() };
+ }
+ static QColorMatrix identity()
+ {
+ return { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
+ }
+ static QColorMatrix fromScale(QColorVector v)
+ {
+ return QColorMatrix { { v.x, 0.0f, 0.0f },
+ { 0.0f, v.y, 0.0f },
+ { 0.0f, 0.0f, v.z } };
+ }
+ // These are used to recognize matrices from ICC profiles:
+ static QColorMatrix toXyzFromSRgb()
+ {
+ return QColorMatrix { { 0.4360217452f, 0.2224751115f, 0.0139281144f },
+ { 0.3851087987f, 0.7169067264f, 0.0971015394f },
+ { 0.1430812478f, 0.0606181994f, 0.7141585946f } };
+ }
+ static QColorMatrix toXyzFromAdobeRgb()
+ {
+ return QColorMatrix { { 0.6097189188f, 0.3111021519f, 0.0194766335f },
+ { 0.2052682191f, 0.6256770492f, 0.0608891509f },
+ { 0.1492247432f, 0.0632209629f, 0.7448224425f } };
+ }
+ static QColorMatrix toXyzFromDciP3D65()
+ {
+ return QColorMatrix { { 0.5150973201f, 0.2411795557f, -0.0010491034f },
+ { 0.2919696569f, 0.6922441125f, 0.0418830328f },
+ { 0.1571449190f, 0.0665764511f, 0.7843542695f } };
+ }
+ static QColorMatrix toXyzFromProPhotoRgb()
+ {
+ return QColorMatrix { { 0.7976672649f, 0.2880374491f, 0.0000000000f },
+ { 0.1351922452f, 0.7118769884f, 0.0000000000f },
+ { 0.0313525312f, 0.0000856627f, 0.8251883388f } };
+ }
+ static QColorMatrix toXyzFromBt2020()
+ {
+ return QColorMatrix { { 0.6506130099f, 0.2695676684f, -0.0018652577f },
+ { 0.1865101457f, 0.6840794086f, 0.0172256753f },
+ { 0.1270887405f, 0.0463530831f, 0.8098278046f } };
+ }
+};
+
+inline bool operator==(const QColorMatrix &m1, const QColorMatrix &m2)
+{
+ return (m1.r == m2.r) && (m1.g == m2.g) && (m1.b == m2.b);
+}
+
+inline bool operator!=(const QColorMatrix &m1, const QColorMatrix &m2)
+{
+ return !(m1 == m2);
+}
+
+QT_END_NAMESPACE
+
+#endif // QCOLORMATRIX_P_H
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
new file mode 100644
index 0000000000..8d3bbbe412
--- /dev/null
+++ b/src/gui/painting/qcolorspace.cpp
@@ -0,0 +1,744 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcolorspace.h"
+#include "qcolorspace_p.h"
+
+#include "qcolortransform.h"
+#include "qcolormatrix_p.h"
+#include "qcolortransferfunction_p.h"
+#include "qcolortransform_p.h"
+#include "qicc_p.h"
+
+#include <qmath.h>
+#include <qtransform.h>
+
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QBasicMutex QColorSpacePrivate::s_lutWriteLock;
+
+QColorSpacePrimaries::QColorSpacePrimaries(QColorSpace::Gamut gamut)
+{
+ switch (gamut) {
+ case QColorSpace::Gamut::SRgb:
+ redPoint = QPointF(0.640, 0.330);
+ greenPoint = QPointF(0.300, 0.600);
+ bluePoint = QPointF(0.150, 0.060);
+ whitePoint = QColorVector::D65Chromaticity();
+ break;
+ case QColorSpace::Gamut::DciP3D65:
+ redPoint = QPointF(0.680, 0.320);
+ greenPoint = QPointF(0.265, 0.690);
+ bluePoint = QPointF(0.150, 0.060);
+ whitePoint = QColorVector::D65Chromaticity();
+ break;
+ case QColorSpace::Gamut::Bt2020:
+ redPoint = QPointF(0.708, 0.292);
+ greenPoint = QPointF(0.190, 0.797);
+ bluePoint = QPointF(0.131, 0.046);
+ whitePoint = QColorVector::D65Chromaticity();
+ break;
+ case QColorSpace::Gamut::AdobeRgb:
+ redPoint = QPointF(0.640, 0.330);
+ greenPoint = QPointF(0.210, 0.710);
+ bluePoint = QPointF(0.150, 0.060);
+ whitePoint = QColorVector::D65Chromaticity();
+ break;
+ case QColorSpace::Gamut::ProPhotoRgb:
+ redPoint = QPointF(0.7347, 0.2653);
+ greenPoint = QPointF(0.1596, 0.8404);
+ bluePoint = QPointF(0.0366, 0.0001);
+ whitePoint = QColorVector::D50Chromaticity();
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+}
+
+bool QColorSpacePrimaries::areValid() const
+{
+ if (!QColorVector::isValidChromaticity(redPoint))
+ return false;
+ if (!QColorVector::isValidChromaticity(greenPoint))
+ return false;
+ if (!QColorVector::isValidChromaticity(bluePoint))
+ return false;
+ if (!QColorVector::isValidChromaticity(whitePoint))
+ return false;
+ return true;
+}
+
+QColorMatrix QColorSpacePrimaries::toXyzMatrix() const
+{
+ // This converts to XYZ in some undefined scale.
+ QColorMatrix toXyz = { QColorVector(redPoint),
+ QColorVector(greenPoint),
+ QColorVector(bluePoint) };
+
+ // Since the white point should be (1.0, 1.0, 1.0) in the
+ // input, we can figure out the scale by using the
+ // inverse conversion on the white point.
+ QColorVector wXyz(whitePoint);
+ QColorVector whiteScale = toXyz.inverted().map(wXyz);
+
+ // Now we have scaled conversion to XYZ relative to the given whitepoint
+ toXyz = toXyz * QColorMatrix::fromScale(whiteScale);
+
+ // But we want a conversion to XYZ relative to D50
+ QColorVector wXyzD50 = QColorVector::D50();
+
+ if (wXyz != wXyzD50) {
+ // Do chromatic adaptation to map our white point to XYZ D50.
+
+ // The Bradford method chromatic adaptation matrix:
+ QColorMatrix abrad = { { 0.8951f, -0.7502f, 0.0389f },
+ { 0.2664f, 1.7135f, -0.0685f },
+ { -0.1614f, 0.0367f, 1.0296f } };
+ QColorMatrix abradinv = { { 0.9869929f, 0.4323053f, -0.0085287f },
+ { -0.1470543f, 0.5183603f, 0.0400428f },
+ { 0.1599627f, 0.0492912f, 0.9684867f } };
+
+ QColorVector srcCone = abrad.map(wXyz);
+ QColorVector dstCone = abrad.map(wXyzD50);
+
+ QColorMatrix wToD50 = { { dstCone.x / srcCone.x, 0, 0 },
+ { 0, dstCone.y / srcCone.y, 0 },
+ { 0, 0, dstCone.z / srcCone.z } };
+
+
+ QColorMatrix chromaticAdaptation = abradinv * (wToD50 * abrad);
+ toXyz = chromaticAdaptation * toXyz;
+ }
+
+ return toXyz;
+}
+
+QColorSpacePrivate::QColorSpacePrivate()
+ : id(QColorSpace::Unknown)
+ , gamut(QColorSpace::Gamut::Custom)
+ , transferFunction(QColorSpace::TransferFunction::Custom)
+ , gamma(0.0f)
+ , whitePoint(QColorVector::null())
+ , toXyz(QColorMatrix::null())
+{
+}
+
+QColorSpacePrivate::QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId)
+ : id(colorSpaceId)
+{
+ switch (colorSpaceId) {
+ case QColorSpace::Undefined:
+ gamut = QColorSpace::Gamut::Custom;
+ transferFunction = QColorSpace::TransferFunction::Custom;
+ gamma = 0.0f;
+ description = QStringLiteral("Undefined");
+ break;
+ case QColorSpace::SRgb:
+ gamut = QColorSpace::Gamut::SRgb;
+ transferFunction = QColorSpace::TransferFunction::SRgb;
+ gamma = 2.31f; // ?
+ description = QStringLiteral("sRGB");
+ break;
+ case QColorSpace::SRgbLinear:
+ gamut = QColorSpace::Gamut::SRgb;
+ transferFunction = QColorSpace::TransferFunction::Linear;
+ gamma = 1.0f;
+ description = QStringLiteral("Linear sRGB");
+ break;
+ case QColorSpace::AdobeRgb:
+ gamut = QColorSpace::Gamut::AdobeRgb;
+ transferFunction = QColorSpace::TransferFunction::Gamma;
+ gamma = 2.19921875f; // Not quite 2.2, see https://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf
+ description = QStringLiteral("Adobe RGB");
+ break;
+ case QColorSpace::DisplayP3:
+ gamut = QColorSpace::Gamut::DciP3D65;
+ transferFunction = QColorSpace::TransferFunction::SRgb;
+ gamma = 2.31f; // ?
+ description = QStringLiteral("Display P3");
+ break;
+ case QColorSpace::ProPhotoRgb:
+ gamut = QColorSpace::Gamut::ProPhotoRgb;
+ transferFunction = QColorSpace::TransferFunction::ProPhotoRgb;
+ gamma = 1.8f;
+ description = QStringLiteral("ProPhoto RGB");
+ break;
+ case QColorSpace::Bt2020:
+ gamut = QColorSpace::Gamut::Bt2020;
+ transferFunction = QColorSpace::TransferFunction::Bt2020;
+ gamma = 2.1f; // ?
+ description = QStringLiteral("BT.2020");
+ break;
+ case QColorSpace::Unknown:
+ qWarning("Can not create an unknown color space");
+ Q_FALLTHROUGH();
+ default:
+ Q_UNREACHABLE();
+ }
+ initialize();
+}
+
+QColorSpacePrivate::QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma)
+ : gamut(gamut)
+ , transferFunction(fun)
+ , gamma(gamma)
+{
+ if (!identifyColorSpace())
+ id = QColorSpace::Unknown;
+ initialize();
+}
+
+QColorSpacePrivate::QColorSpacePrivate(const QColorSpacePrimaries &primaries,
+ QColorSpace::TransferFunction fun,
+ float gamma)
+ : gamut(QColorSpace::Gamut::Custom)
+ , transferFunction(fun)
+ , gamma(gamma)
+{
+ Q_ASSERT(primaries.areValid());
+ toXyz = primaries.toXyzMatrix();
+ whitePoint = QColorVector(primaries.whitePoint);
+ if (!identifyColorSpace())
+ id = QColorSpace::Unknown;
+ setTransferFunction();
+}
+
+bool QColorSpacePrivate::identifyColorSpace()
+{
+ switch (gamut) {
+ case QColorSpace::Gamut::SRgb:
+ if (transferFunction == QColorSpace::TransferFunction::SRgb) {
+ id = QColorSpace::SRgb;
+ description = QStringLiteral("sRGB");
+ return true;
+ }
+ if (transferFunction == QColorSpace::TransferFunction::Linear) {
+ id = QColorSpace::SRgbLinear;
+ description = QStringLiteral("Linear sRGB");
+ return true;
+ }
+ break;
+ case QColorSpace::Gamut::AdobeRgb:
+ if (transferFunction == QColorSpace::TransferFunction::Gamma) {
+ if (qAbs(gamma - 2.19921875f) < (1/1024.0f)) {
+ id = QColorSpace::AdobeRgb;
+ description = QStringLiteral("Adobe RGB");
+ return true;
+ }
+ }
+ break;
+ case QColorSpace::Gamut::DciP3D65:
+ if (transferFunction == QColorSpace::TransferFunction::SRgb) {
+ id = QColorSpace::DisplayP3;
+ description = QStringLiteral("Display P3");
+ return true;
+ }
+ break;
+ case QColorSpace::Gamut::ProPhotoRgb:
+ if (transferFunction == QColorSpace::TransferFunction::ProPhotoRgb) {
+ id = QColorSpace::ProPhotoRgb;
+ description = QStringLiteral("ProPhoto RGB");
+ return true;
+ }
+ if (transferFunction == QColorSpace::TransferFunction::Gamma) {
+ // ProPhoto RGB's curve is effectively gamma 1.8 for 8bit precision.
+ if (qAbs(gamma - 1.8f) < (1/1024.0f)) {
+ id = QColorSpace::ProPhotoRgb;
+ description = QStringLiteral("ProPhoto RGB");
+ return true;
+ }
+ }
+ break;
+ case QColorSpace::Gamut::Bt2020:
+ if (transferFunction == QColorSpace::TransferFunction::Bt2020) {
+ id = QColorSpace::Bt2020;
+ description = QStringLiteral("BT.2020");
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+void QColorSpacePrivate::initialize()
+{
+ setToXyzMatrix();
+ setTransferFunction();
+}
+
+void QColorSpacePrivate::setToXyzMatrix()
+{
+ if (gamut == QColorSpace::Gamut::Custom) {
+ toXyz = QColorMatrix::null();
+ whitePoint = QColorVector::D50();
+ return;
+ }
+ QColorSpacePrimaries primaries(gamut);
+ toXyz = primaries.toXyzMatrix();
+ whitePoint = QColorVector(primaries.whitePoint);
+}
+
+void QColorSpacePrivate::setTransferFunction()
+{
+ switch (transferFunction) {
+ case QColorSpace::TransferFunction::Linear:
+ trc[0].m_type = QColorTrc::Type::Function;
+ trc[0].m_fun = QColorTransferFunction();
+ break;
+ case QColorSpace::TransferFunction::Gamma:
+ trc[0].m_type = QColorTrc::Type::Function;
+ trc[0].m_fun = QColorTransferFunction::fromGamma(gamma);
+ break;
+ case QColorSpace::TransferFunction::SRgb:
+ trc[0].m_type = QColorTrc::Type::Function;
+ trc[0].m_fun = QColorTransferFunction::fromSRgb();
+ break;
+ case QColorSpace::TransferFunction::ProPhotoRgb:
+ trc[0].m_type = QColorTrc::Type::Function;
+ trc[0].m_fun = QColorTransferFunction::fromProPhotoRgb();
+ break;
+ case QColorSpace::TransferFunction::Bt2020:
+ trc[0].m_type = QColorTrc::Type::Function;
+ trc[0].m_fun = QColorTransferFunction::fromBt2020();
+ break;
+ case QColorSpace::TransferFunction::Custom:
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ trc[1] = trc[0];
+ trc[2] = trc[0];
+}
+
+QColorTransform QColorSpacePrivate::transformationToColorSpace(const QColorSpacePrivate *out) const
+{
+ Q_ASSERT(out);
+ QColorTransform combined;
+ combined.d_ptr.reset(new QColorTransformPrivate);
+ combined.d_ptr->colorSpaceIn = this;
+ combined.d_ptr->colorSpaceOut = out;
+ combined.d_ptr->colorMatrix = out->toXyz.inverted() * toXyz;
+ return combined;
+}
+
+/*!
+ \class QColorSpace
+ \brief The QColorSpace class provides a color space abstraction.
+ \since 5.14
+
+ \ingroup painting
+ \ingroup appearance
+ \inmodule QtGui
+
+ Color values can be interpreted in different ways, and based on the interpretation
+ can live in different spaces. We call this \e {color spaces}.
+
+ QColorSpace provides access to creating several predefined color spaces and
+ can generate QColorTransforms for converting colors from one color space to
+ another.
+
+ QColorSpace can also represent color spaces defined by ICC profiles or embedded
+ in images, that do not otherwise fit the predefined color spaces.
+
+ A color space can generally speaking be conceived as a combination of a transfer
+ function and a gamut. The gamut defines which colors the color space can represent.
+ A color space that can represent a wider range of colors is also known as a
+ wide-gamut color space. The gamut is defined by three primary colors that represent
+ exactly how red, green, and blue look in this particular color space, and a white
+ color that represents where and how bright pure white is.
+
+ The transfer function or gamma curve determines how each component in the
+ color space is encoded. These are used because human perception does not operate
+ linearly, and the transfer functions try to ensure that colors will seem evenly
+ spaced to human eyes.
+*/
+
+
+/*!
+ \enum QColorSpace::ColorSpaceId
+
+ Predefined color spaces.
+
+ \value Undefined An empty, invalid or unsupported color space.
+ \value Unknown A valid color space that doesn't match any of the predefined color spaces.
+ \value SRgb The sRGB color space, which Qt operates in by default. It is a close approximation
+ of how most classic monitors operate, and a mode most software and hardware support.
+ \l{http://www.color.org/chardata/rgb/srgb.xalter}{ICC registration of sRGB}.
+ \value SRgbLinear The sRGB color space with linear gamma. Useful for gamma-corrected blending.
+ \value AdobeRgb The Adobe RGB color space is a classic wide-gamut color space, using a gamma of 2.2.
+ \l{http://www.color.org/chardata/rgb/adobergb.xalter}{ICC registration of Adobe RGB (1998)}
+ \value DisplayP3 A color-space using the primaries of DCI-P3, but with the whitepoint and transfer
+ function of sRGB. Common in modern wide-gamut screens.
+ \l{http://www.color.org/chardata/rgb/DCIP3.xalter}{ICC registration of DCI-P3}
+ \value ProPhotoRgb The Pro Photo RGB color space, also known as ROMM RGB is a very wide gamut color space.
+ \l{http://www.color.org/chardata/rgb/rommrgb.xalter}{ICC registration of ROMM RGB}
+ \value Bt2020 BT.2020 also known as Rec.2020 is the color space of HDR TVs.
+ \l{http://www.color.org/chardata/rgb/BT2020.xalter}{ICC registration of BT.2020}
+*/
+
+/*!
+ \enum QColorSpace::Gamut
+
+ Predefined gamuts, or sets of primary colors.
+
+ \value Custom The gamut is undefined or does not match any predefined sets.
+ \value SRgb The sRGB gamut
+ \value AdobeRgb The Adobe RGB gamut
+ \value DciP3D65 The DCI-P3 gamut with the D65 whitepoint
+ \value ProPhotoRgb The ProPhoto RGB gamut with the D50 whitepoint
+ \value Bt2020 The BT.2020 gamut
+*/
+
+/*!
+ \enum QColorSpace::TransferFunction
+
+ Predefined transfer functions or gamma curves.
+
+ \value Custom The custom or null transfer function
+ \value Linear The linear transfer functions
+ \value Gamma A transfer function that is a real gamma curve based on the value of gamma()
+ \value SRgb The sRGB transfer function, composed of linear and gamma parts
+ \value ProPhotoRgb The ProPhoto RGB transfer function, composed of linear and gamma parts
+ \value Bt2020 The BT.2020 transfer function, composed of linear and gamma parts
+*/
+
+/*!
+ Creates a new colorspace object that represents \a colorSpaceId.
+ */
+QColorSpace::QColorSpace(QColorSpace::ColorSpaceId colorSpaceId)
+{
+ static QExplicitlySharedDataPointer<QColorSpacePrivate> predefinedColorspacePrivates[QColorSpace::Bt2020];
+ if (colorSpaceId <= QColorSpace::Unknown) {
+ if (!predefinedColorspacePrivates[0])
+ predefinedColorspacePrivates[0] = new QColorSpacePrivate(QColorSpace::Undefined);
+ d_ptr = predefinedColorspacePrivates[0]; // unknown and undefined both returns the static undefined colorspace.
+ } else {
+ if (!predefinedColorspacePrivates[colorSpaceId - 1])
+ predefinedColorspacePrivates[colorSpaceId - 1] = new QColorSpacePrivate(colorSpaceId);
+ d_ptr = predefinedColorspacePrivates[colorSpaceId - 1];
+ }
+
+ Q_ASSERT(colorSpaceId == QColorSpace::Undefined || isValid());
+}
+
+/*!
+ Creates a custom color space with the gamut \a gamut, using the transfer function \a fun and
+ optionally \a gamma.
+ */
+QColorSpace::QColorSpace(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma)
+ : d_ptr(new QColorSpacePrivate(gamut, fun, gamma))
+{
+}
+
+/*!
+ Creates a custom color space with the gamut \a gamut, using a gamma transfer function of
+ \a gamma.
+ */
+QColorSpace::QColorSpace(QColorSpace::Gamut gamut, float gamma)
+ : d_ptr(new QColorSpacePrivate(gamut, TransferFunction::Gamma, gamma))
+{
+}
+
+/*!
+ Creates a custom colorspace with a gamut based on the chromaticities of the primary colors \a whitePoint,
+ \a redPoint, \a greenPoint and \a bluePoint, and using the transfer function \a fun and optionally \a gamma.
+ */
+QColorSpace::QColorSpace(const QPointF &whitePoint, const QPointF &redPoint,
+ const QPointF &greenPoint, const QPointF &bluePoint,
+ QColorSpace::TransferFunction fun, float gamma)
+{
+ QColorSpacePrimaries primaries(whitePoint, redPoint, greenPoint, bluePoint);
+ if (!primaries.areValid()) {
+ qWarning() << "QColorSpace attempted constructed from invalid primaries:" << whitePoint << redPoint << greenPoint << bluePoint;
+ d_ptr = QColorSpace(QColorSpace::Undefined).d_ptr;
+ return;
+ }
+ d_ptr = new QColorSpacePrivate(primaries, fun, gamma);
+}
+
+QColorSpace::~QColorSpace()
+{
+}
+
+QColorSpace::QColorSpace(QColorSpace &&colorSpace)
+ : d_ptr(std::move(colorSpace.d_ptr))
+{
+}
+
+QColorSpace::QColorSpace(const QColorSpace &colorSpace)
+ : d_ptr(colorSpace.d_ptr)
+{
+}
+
+QColorSpace &QColorSpace::operator=(QColorSpace &&colorSpace)
+{
+ d_ptr = std::move(colorSpace.d_ptr);
+ return *this;
+}
+
+QColorSpace &QColorSpace::operator=(const QColorSpace &colorSpace)
+{
+ d_ptr = colorSpace.d_ptr;
+ return *this;
+}
+
+/*!
+ Returns the id of the predefined color space this object
+ represents or \c Unknown if it doesn't match any of them.
+*/
+QColorSpace::ColorSpaceId QColorSpace::colorSpaceId() const noexcept
+{
+ return d_ptr->id;
+}
+
+/*!
+ Returns the predefined gamut of the color space
+ or \c Gamut::Custom if it doesn't match any of them.
+*/
+QColorSpace::Gamut QColorSpace::gamut() const noexcept
+{
+ return d_ptr->gamut;
+}
+
+/*!
+ Returns the predefined transfer function of the color space
+ or \c TransferFunction::Custom if it doesn't match any of them.
+
+ \sa gamma()
+*/
+QColorSpace::TransferFunction QColorSpace::transferFunction() const noexcept
+{
+ return d_ptr->transferFunction;
+}
+
+/*!
+ Returns the gamma value of color spaces with \c TransferFunction::Gamma,
+ an approximate gamma value for other predefined color spaces, or
+ 0.0 if no approximate gamma is known.
+
+ \sa transferFunction()
+*/
+float QColorSpace::gamma() const noexcept
+{
+ return d_ptr->gamma;
+}
+
+/*!
+ Returns an ICC profile representing the color space.
+
+ If the color space was generated from an ICC profile, that profile
+ is returned, otherwise one is generated.
+
+ \note Even invalid color spaces may return the ICC profile if they
+ were generated from one, to allow applications to implement wider
+ support themselves.
+
+ \sa fromIccProfile()
+*/
+QByteArray QColorSpace::iccProfile() const
+{
+ if (!d_ptr->iccProfile.isEmpty())
+ return d_ptr->iccProfile;
+ if (!isValid())
+ return QByteArray();
+ return QIcc::toIccProfile(*this);
+}
+
+/*!
+ Creates a QColorSpace from ICC profile \a iccProfile.
+
+ \note Not all ICC profiles are supported. QColorSpace only supports
+ RGB-XYZ ICC profiles that are three-component matrix-based.
+
+ If the ICC profile is not supported an invalid QColorSpace is returned
+ where you can still read the original ICC profile using iccProfile().
+
+ \sa iccProfile()
+*/
+QColorSpace QColorSpace::fromIccProfile(const QByteArray &iccProfile)
+{
+ QColorSpace colorSpace;
+ if (QIcc::fromIccProfile(iccProfile, &colorSpace))
+ return colorSpace;
+ colorSpace.d_ptr->id = QColorSpace::Undefined;
+ colorSpace.d_ptr->iccProfile = iccProfile;
+ return colorSpace;
+}
+
+/*!
+ Returns \c true if the color space is valid.
+*/
+bool QColorSpace::isValid() const noexcept
+{
+ return d_ptr->id != QColorSpace::Undefined && d_ptr->toXyz.isValid()
+ && d_ptr->trc[0].isValid() && d_ptr->trc[1].isValid() && d_ptr->trc[2].isValid();
+}
+
+/*!
+ \relates QColorSpace
+ Returns \c true if colorspace \a colorSpace1 is equal to colorspace \a colorSpace2;
+ otherwise returns \c false
+*/
+bool operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2)
+{
+ if (colorSpace1.d_ptr == colorSpace2.d_ptr)
+ return true;
+
+ if (colorSpace1.colorSpaceId() == QColorSpace::Undefined && colorSpace2.colorSpaceId() == QColorSpace::Undefined)
+ return colorSpace1.d_ptr->iccProfile == colorSpace2.d_ptr->iccProfile;
+
+ if (colorSpace1.colorSpaceId() != QColorSpace::Unknown && colorSpace2.colorSpaceId() != QColorSpace::Unknown)
+ return colorSpace1.colorSpaceId() == colorSpace2.colorSpaceId();
+
+ if (colorSpace1.gamut() != QColorSpace::Gamut::Custom && colorSpace2.gamut() != QColorSpace::Gamut::Custom) {
+ if (colorSpace1.gamut() != colorSpace2.gamut())
+ return false;
+ } else {
+ if (colorSpace1.d_ptr->toXyz != colorSpace2.d_ptr->toXyz)
+ return false;
+ }
+
+ if (colorSpace1.transferFunction() != QColorSpace::TransferFunction::Custom &&
+ colorSpace2.transferFunction() != QColorSpace::TransferFunction::Custom) {
+ if (colorSpace1.transferFunction() != colorSpace2.transferFunction())
+ return false;
+ if (colorSpace1.transferFunction() == QColorSpace::TransferFunction::Gamma)
+ return colorSpace1.gamma() == colorSpace2.gamma();
+ return true;
+ }
+
+ if (colorSpace1.d_ptr->trc[0] != colorSpace2.d_ptr->trc[0] ||
+ colorSpace1.d_ptr->trc[1] != colorSpace2.d_ptr->trc[1] ||
+ colorSpace1.d_ptr->trc[2] != colorSpace2.d_ptr->trc[2])
+ return false;
+
+ return true;
+}
+
+/*!
+ \fn bool operator!=(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2)
+ \relates QColorSpace
+
+ Returns \c true if colorspace \a colorSpace1 is not equal to colorspace \a colorSpace2;
+ otherwise returns \c false
+*/
+
+/*!
+ Generates and returns a color space transformation from this color space to
+ \a colorspace.
+*/
+QColorTransform QColorSpace::transformationToColorSpace(const QColorSpace &colorspace) const
+{
+ if (!isValid() || !colorspace.isValid())
+ return QColorTransform();
+
+ return d_ptr->transformationToColorSpace(colorspace.d_ptr.constData());
+}
+
+/*!
+ \internal
+*/
+QColorSpacePrivate *QColorSpace::d_func()
+{
+ d_ptr.detach();
+ return d_ptr.data();
+}
+
+/*!
+ \fn const QColorSpacePrivate* QColorSpacePrivate::d_func() const
+ \internal
+*/
+
+/*****************************************************************************
+ QColorSpace stream functions
+ *****************************************************************************/
+#if !defined(QT_NO_DATASTREAM)
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QColorSpace &colorSpace)
+ \relates QColorSpace
+
+ Writes the given \a colorSpace to the given \a stream as an ICC profile.
+
+ \sa QColorSpace::iccProfile(), {Serializing Qt Data Types}
+*/
+
+QDataStream &operator<<(QDataStream &s, const QColorSpace &image)
+{
+ s << image.iccProfile();
+ return s;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QColorSpace &colorSpace)
+ \relates QColorSpace
+
+ Reads a color space from the given \a stream and stores it in the given
+ \a colorSpace.
+
+ \sa QColorSpace::fromIccProfile(), {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &s, QColorSpace &colorSpace)
+{
+ QByteArray iccProfile;
+ s >> iccProfile;
+ colorSpace = QColorSpace::fromIccProfile(iccProfile);
+ return s;
+}
+#endif // QT_NO_DATASTREAM
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QColorSpace &colorSpace)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ dbg << "QColorSpace(";
+ dbg << colorSpace.colorSpaceId() << ", " << colorSpace.gamut() << ", " << colorSpace.transferFunction();
+ dbg << ", gamma=" << colorSpace.gamma();
+ dbg << ')';
+ return dbg;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolorspace.h b/src/gui/painting/qcolorspace.h
new file mode 100644
index 0000000000..56676826a9
--- /dev/null
+++ b/src/gui/painting/qcolorspace.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORSPACE_H
+#define QCOLORSPACE_H
+
+#include <QtGui/qtguiglobal.h>
+#include <QtGui/qcolortransform.h>
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_NAMESPACE
+
+class QColorSpacePrivate;
+
+class Q_GUI_EXPORT QColorSpace
+{
+ Q_GADGET
+public:
+ enum ColorSpaceId {
+ Undefined = 0,
+ Unknown = 1,
+ SRgb,
+ SRgbLinear,
+ AdobeRgb,
+ DisplayP3,
+ ProPhotoRgb,
+ Bt2020,
+ };
+ Q_ENUM(ColorSpaceId)
+ enum class Gamut {
+ Custom = 0,
+ SRgb,
+ AdobeRgb,
+ DciP3D65,
+ ProPhotoRgb,
+ Bt2020,
+ };
+ Q_ENUM(Gamut)
+ enum class TransferFunction {
+ Custom = 0,
+ Linear,
+ Gamma,
+ SRgb,
+ ProPhotoRgb,
+ Bt2020,
+ };
+ Q_ENUM(TransferFunction)
+
+ QColorSpace(ColorSpaceId colorSpaceId = Undefined);
+ QColorSpace(Gamut gamut, TransferFunction fun, float gamma = 0.0f);
+ QColorSpace(Gamut gamut, float gamma);
+ QColorSpace(const QPointF &whitePoint, const QPointF &redPoint,
+ const QPointF &greenPoint, const QPointF &bluePoint,
+ TransferFunction fun, float gamma = 0.0f);
+ ~QColorSpace();
+
+ QColorSpace(QColorSpace &&colorSpace);
+ QColorSpace(const QColorSpace &colorSpace);
+ QColorSpace &operator=(QColorSpace &&colorSpace);
+ QColorSpace &operator=(const QColorSpace &colorSpace);
+
+ ColorSpaceId colorSpaceId() const noexcept;
+ Gamut gamut() const noexcept;
+ TransferFunction transferFunction() const noexcept;
+ float gamma() const noexcept;
+
+ bool isValid() const noexcept;
+
+ friend Q_GUI_EXPORT bool operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2);
+ friend inline bool operator!=(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2);
+
+ static QColorSpace fromIccProfile(const QByteArray &iccProfile);
+ QByteArray iccProfile() const;
+
+ QColorTransform transformationToColorSpace(const QColorSpace &colorspace) const;
+
+ QColorSpacePrivate *d_func();
+ inline const QColorSpacePrivate *d_func() const { return d_ptr.constData(); }
+
+private:
+ friend class QColorSpacePrivate;
+ QExplicitlySharedDataPointer<QColorSpacePrivate> d_ptr;
+};
+
+bool Q_GUI_EXPORT operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2);
+inline bool operator!=(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2)
+{
+ return !(colorSpace1 == colorSpace2);
+}
+
+// QColorSpace stream functions
+#if !defined(QT_NO_DATASTREAM)
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QColorSpace &);
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QColorSpace &);
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QColorSpace &);
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QCOLORSPACE_P_H
diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h
new file mode 100644
index 0000000000..95e0655d0c
--- /dev/null
+++ b/src/gui/painting/qcolorspace_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORSPACE_P_H
+#define QCOLORSPACE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qcolorspace.h"
+#include "qcolormatrix_p.h"
+#include "qcolortrc_p.h"
+#include "qcolortrclut_p.h"
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QColorSpacePrimaries
+{
+public:
+ QColorSpacePrimaries() = default;
+ QColorSpacePrimaries(QColorSpace::Gamut gamut);
+ QColorSpacePrimaries(QPointF whitePoint,
+ QPointF redPoint,
+ QPointF greenPoint,
+ QPointF bluePoint)
+ : whitePoint(whitePoint)
+ , redPoint(redPoint)
+ , greenPoint(greenPoint)
+ , bluePoint(bluePoint)
+ { }
+
+ QColorMatrix toXyzMatrix() const;
+ bool areValid() const;
+
+ QPointF whitePoint;
+ QPointF redPoint;
+ QPointF greenPoint;
+ QPointF bluePoint;
+};
+
+class QColorSpacePrivate : public QSharedData
+{
+public:
+ QColorSpacePrivate();
+ QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId);
+ QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma);
+ QColorSpacePrivate(const QColorSpacePrimaries &primaries, QColorSpace::TransferFunction fun, float gamma);
+ QColorSpacePrivate(const QColorSpacePrivate &other) = default;
+
+ void initialize();
+ void setToXyzMatrix();
+ void setTransferFunction();
+ bool identifyColorSpace();
+ QColorTransform transformationToColorSpace(const QColorSpacePrivate *out) const;
+
+ QColorSpace::ColorSpaceId id;
+ QColorSpace::Gamut gamut;
+ QColorSpace::TransferFunction transferFunction;
+ float gamma;
+ QColorVector whitePoint;
+
+ QColorTrc trc[3];
+ QColorMatrix toXyz;
+
+ QString description;
+ QByteArray iccProfile;
+
+ static QBasicMutex s_lutWriteLock;
+ struct LUT {
+ LUT() = default;
+ ~LUT() = default;
+ LUT(const LUT &other)
+ {
+ if (other.generated.loadAcquire()) {
+ table[0] = other.table[0];
+ table[1] = other.table[1];
+ table[2] = other.table[2];
+ generated.storeRelaxed(1);
+ }
+ }
+ QSharedPointer<QColorTrcLut> &operator[](int i) { return table[i]; }
+ const QSharedPointer<QColorTrcLut> &operator[](int i) const { return table[i]; }
+ QSharedPointer<QColorTrcLut> table[3];
+ QAtomicInt generated;
+ } mutable lut;
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOLORSPACE_P_H
diff --git a/src/gui/painting/qcolortransferfunction_p.h b/src/gui/painting/qcolortransferfunction_p.h
new file mode 100644
index 0000000000..fd7cfa2b2b
--- /dev/null
+++ b/src/gui/painting/qcolortransferfunction_p.h
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORTRANSFERFUNCTION_P_H
+#define QCOLORTRANSFERFUNCTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+// Defines a ICC parametric curve type 4
+class Q_GUI_EXPORT QColorTransferFunction
+{
+public:
+ QColorTransferFunction() noexcept
+ : m_a(1.0f), m_b(0.0f), m_c(1.0f), m_d(0.0f), m_e(0.0f), m_f(0.0f), m_g(1.0f), m_flags(0)
+ { }
+ QColorTransferFunction(float a, float b, float c, float d, float e, float f, float g) noexcept
+ : m_a(a), m_b(b), m_c(c), m_d(d), m_e(e), m_f(f), m_g(g), m_flags(0)
+ { }
+
+ bool isGamma() const
+ {
+ updateHints();
+ return m_flags & quint32(Hints::IsGamma);
+ }
+ bool isLinear() const
+ {
+ updateHints();
+ return m_flags & quint32(Hints::IsLinear);
+ }
+ bool isSRgb() const
+ {
+ updateHints();
+ return m_flags & quint32(Hints::IsSRgb);
+ }
+
+ float apply(float x) const
+ {
+ if (x < m_d)
+ return m_c * x + m_f;
+ else
+ return std::pow(m_a * x + m_b, m_g) + m_e;
+ }
+
+ QColorTransferFunction inverted() const
+ {
+ float a, b, c, d, e, f, g;
+
+ d = m_c * m_d + m_f;
+
+ if (!qFuzzyIsNull(m_c)) {
+ c = 1.0f / m_c;
+ f = -m_f / m_c;
+ } else {
+ c = 0.0f;
+ f = 0.0f;
+ }
+
+ if (!qFuzzyIsNull(m_a) && !qFuzzyIsNull(m_g)) {
+ a = std::pow(1.0f / m_a, m_g);
+ b = -a * m_e;
+ e = -m_b / m_a;
+ g = 1.0f / m_g;
+ } else {
+ a = 0.0f;
+ b = 0.0f;
+ e = 1.0f;
+ g = 1.0f;
+ }
+
+ return QColorTransferFunction(a, b, c, d, e, f, g);
+ }
+
+ // A few predefined curves:
+ static QColorTransferFunction fromGamma(float gamma)
+ {
+ return QColorTransferFunction(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, gamma);
+ }
+ static QColorTransferFunction fromSRgb()
+ {
+ return QColorTransferFunction(1.0f / 1.055f, 0.055f / 1.055f, 1.0f / 12.92f, 0.04045f, 0.0f, 0.0f, 2.4f);
+ }
+ static QColorTransferFunction fromBt2020()
+ {
+ return QColorTransferFunction(1.0f / 1.0993f, 0.0993f / 1.0993f, 1.0f / 4.5f, 0.08145f, 0.0f, 0.0f, 2.2f);
+ }
+ static QColorTransferFunction fromProPhotoRgb()
+ {
+ return QColorTransferFunction(1.0f, 0.0f, 1.0f / 16.0f, 16.0f / 512.0f, 0.0f, 0.0f, 1.8f);
+ }
+ bool matches(const QColorTransferFunction &o) const
+ {
+ return paramCompare(m_a, o.m_a) && paramCompare(m_b, o.m_b)
+ && paramCompare(m_c, o.m_c) && paramCompare(m_d, o.m_d)
+ && paramCompare(m_e, o.m_e) && paramCompare(m_f, o.m_f)
+ && paramCompare(m_g, o.m_g);
+ }
+ friend inline bool operator==(const QColorTransferFunction &f1, const QColorTransferFunction &f2);
+ friend inline bool operator!=(const QColorTransferFunction &f1, const QColorTransferFunction &f2);
+
+ float m_a;
+ float m_b;
+ float m_c;
+ float m_d;
+ float m_e;
+ float m_f;
+ float m_g;
+
+private:
+ static inline bool paramCompare(float p1, float p2)
+ {
+ // Much fuzzier than fuzzy compare.
+ // It tries match parameters that has been passed through a 8.8
+ // fixed point form.
+ return (qAbs(p1 - p2) <= (1.0f / 512.0f));
+ }
+
+ void updateHints() const
+ {
+ if (m_flags & quint32(Hints::Calculated))
+ return;
+ // We do not consider the case with m_d = 1.0f linear or simple,
+ // since it wouldn't be linear for applyExtended().
+ bool simple = paramCompare(m_a, 1.0f) && paramCompare(m_b, 0.0f)
+ && paramCompare(m_d, 0.0f)
+ && paramCompare(m_e, 0.0f);
+ if (simple) {
+ m_flags |= quint32(Hints::IsGamma);
+ if (qFuzzyCompare(m_g, 1.0f))
+ m_flags |= quint32(Hints::IsLinear);
+ } else {
+ if (*this == fromSRgb())
+ m_flags |= quint32(Hints::IsSRgb);
+ }
+ m_flags |= quint32(Hints::Calculated);
+ }
+ enum class Hints : quint32 {
+ Calculated = 1,
+ IsGamma = 2,
+ IsLinear = 4,
+ IsSRgb = 8
+ };
+ mutable quint32 m_flags;
+};
+
+inline bool operator==(const QColorTransferFunction &f1, const QColorTransferFunction &f2)
+{
+ return f1.matches(f2);
+}
+inline bool operator!=(const QColorTransferFunction &f1, const QColorTransferFunction &f2)
+{
+ return !f1.matches(f2);
+}
+
+QT_END_NAMESPACE
+
+#endif // QCOLORTRANSFERFUNCTION_P_H
diff --git a/src/gui/painting/qcolortransfertable_p.h b/src/gui/painting/qcolortransfertable_p.h
new file mode 100644
index 0000000000..c8b2f7bd92
--- /dev/null
+++ b/src/gui/painting/qcolortransfertable_p.h
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORTRANSFERTABLE_P_H
+#define QCOLORTRANSFERTABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include "qcolortransferfunction_p.h"
+
+#include <QVector>
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+// Defines either an ICC TRC 'curve' or a lut8/lut16 A or B table
+class Q_GUI_EXPORT QColorTransferTable
+{
+public:
+ QColorTransferTable() noexcept
+ : m_tableSize(0)
+ { }
+ QColorTransferTable(uint32_t size, const QVector<uint8_t> &table) noexcept
+ : m_tableSize(size)
+ , m_table8(table)
+ { }
+ QColorTransferTable(uint32_t size, const QVector<uint16_t> &table) noexcept
+ : m_tableSize(size)
+ , m_table16(table)
+ { }
+
+ bool isValid() const
+ {
+ if (m_tableSize < 2)
+ return false;
+
+#if !defined(QT_NO_DEBUG)
+ // The table must describe an injective curve:
+ if (!m_table8.isEmpty()) {
+ uint8_t val = 0;
+ for (uint i = 0; i < m_tableSize; ++i) {
+ Q_ASSERT(m_table8[i] >= val);
+ val = m_table8[i];
+ }
+ }
+ if (!m_table16.isEmpty()) {
+ uint16_t val = 0;
+ for (uint i = 0; i < m_tableSize; ++i) {
+ Q_ASSERT(m_table16[i] >= val);
+ val = m_table16[i];
+ }
+ }
+#endif
+ return !m_table8.isEmpty() || !m_table16.isEmpty();
+ }
+
+ float apply(float x) const
+ {
+ x = std::min(std::max(x, 0.0f), 1.0f);
+ x *= m_tableSize - 1;
+ uint32_t lo = (int)std::floor(x);
+ uint32_t hi = std::min(lo + 1, m_tableSize);
+ float frac = x - lo;
+ if (!m_table16.isEmpty())
+ return (m_table16[lo] * (1.0f - frac) + m_table16[hi] * frac) * (1.0f/65535.0f);
+ if (!m_table8.isEmpty())
+ return (m_table8[lo] * (1.0f - frac) + m_table8[hi] * frac) * (1.0f/255.0f);
+ return x;
+ }
+
+ // Apply inverse, optimized by giving a previous result a value < x.
+ float applyInverse(float x, float resultLargerThan = 0.0f) const
+ {
+ Q_ASSERT(resultLargerThan >= 0.0f && resultLargerThan <= 1.0f);
+ if (x <= 0.0f)
+ return 0.0f;
+ if (x >= 1.0f)
+ return 1.0f;
+ if (!m_table16.isEmpty()) {
+ float v = x * 65535.0f;
+ uint i = std::floor(resultLargerThan * (m_tableSize - 1)) + 1;
+ for ( ; i < m_tableSize; ++i) {
+ if (m_table16[i] > v)
+ break;
+ }
+ if (i >= m_tableSize - 1)
+ return 1.0f;
+ float y1 = m_table16[i - 1];
+ float y2 = m_table16[i];
+ Q_ASSERT(x >= y1 && x < y2);
+ float fr = (v - y1) / (y2 - y1);
+ return (i + fr) * (1.0f / (m_tableSize - 1));
+
+ }
+ if (!m_table8.isEmpty()) {
+ float v = x * 255.0f;
+ uint i = std::floor(resultLargerThan * (m_tableSize - 1)) + 1;
+ for ( ; i < m_tableSize; ++i) {
+ if (m_table8[i] > v)
+ break;
+ }
+ if (i >= m_tableSize - 1)
+ return 1.0f;
+ float y1 = m_table8[i - 1];
+ float y2 = m_table8[i];
+ Q_ASSERT(x >= y1 && x < y2);
+ float fr = (v - y1) / (y2 - y1);
+ return (i + fr) * (1.0f / (m_tableSize - 1));
+ }
+ return x;
+ }
+
+ bool asColorTransferFunction(QColorTransferFunction *transferFn)
+ {
+ Q_ASSERT(isValid());
+ Q_ASSERT(transferFn);
+ if (!m_table8.isEmpty() && (m_table8[0] != 0 || m_table8[m_tableSize - 1] != 255))
+ return false;
+ if (!m_table16.isEmpty() && (m_table16[0] != 0 || m_table16[m_tableSize - 1] != 65535))
+ return false;
+ if (m_tableSize == 2) {
+ *transferFn = QColorTransferFunction(); // Linear
+ return true;
+ }
+ // The following heuristics are based on those from Skia:
+ if (m_tableSize == 26 && !m_table16.isEmpty()) {
+ // code.facebook.com/posts/411525055626587/under-the-hood-improving-facebook-photos
+ if (m_table16[6] != 3062)
+ return false;
+ if (m_table16[12] != 12824)
+ return false;
+ if (m_table16[18] != 31237)
+ return false;
+ *transferFn = QColorTransferFunction::fromSRgb();
+ return true;
+ }
+ if (m_tableSize == 1024 && !m_table16.isEmpty()) {
+ // HP and Canon sRGB gamma tables:
+ if (m_table16[257] != 3366)
+ return false;
+ if (m_table16[513] != 14116)
+ return false;
+ if (m_table16[768] != 34318)
+ return false;
+ *transferFn = QColorTransferFunction::fromSRgb();
+ return true;
+ }
+ if (m_tableSize == 4096 && !m_table16.isEmpty()) {
+ // Nikon, Epson, and lcms2 sRGB gamma tables:
+ if (m_table16[515] != 960)
+ return false;
+ if (m_table16[1025] != 3342)
+ return false;
+ if (m_table16[2051] != 14079)
+ return false;
+ *transferFn = QColorTransferFunction::fromSRgb();
+ return true;
+ }
+ return false;
+ }
+ friend inline bool operator!=(const QColorTransferTable &t1, const QColorTransferTable &t2);
+ friend inline bool operator==(const QColorTransferTable &t1, const QColorTransferTable &t2);
+
+ uint32_t m_tableSize;
+ QVector<uint8_t> m_table8;
+ QVector<uint16_t> m_table16;
+};
+
+inline bool operator!=(const QColorTransferTable &t1, const QColorTransferTable &t2)
+{
+ if (t1.m_tableSize != t2.m_tableSize)
+ return true;
+ if (t1.m_table8.isEmpty() != t2.m_table8.isEmpty())
+ return true;
+ if (t1.m_table16.isEmpty() != t2.m_table16.isEmpty())
+ return true;
+ if (!t1.m_table8.isEmpty()) {
+ for (quint32 i = 0; i < t1.m_tableSize; ++i) {
+ if (t1.m_table8[i] != t2.m_table8[i])
+ return true;
+ }
+ }
+ if (!t1.m_table16.isEmpty()) {
+ for (quint32 i = 0; i < t1.m_tableSize; ++i) {
+ if (t1.m_table16[i] != t2.m_table16[i])
+ return true;
+ }
+ }
+ return false;
+}
+
+inline bool operator==(const QColorTransferTable &t1, const QColorTransferTable &t2)
+{
+ return !(t1 != t2);
+}
+
+QT_END_NAMESPACE
+
+#endif // QCOLORTRANSFERTABLE_P_H
diff --git a/src/gui/painting/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp
new file mode 100644
index 0000000000..de08bf4221
--- /dev/null
+++ b/src/gui/painting/qcolortransform.cpp
@@ -0,0 +1,703 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qcolortransform.h"
+#include "qcolortransform_p.h"
+
+#include "qcolormatrix_p.h"
+#include "qcolorspace_p.h"
+#include "qcolortrc_p.h"
+#include "qcolortrclut_p.h"
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qmath.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qtransform.h>
+#include <QtCore/private/qsimd_p.h>
+
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QColorTrcLut *lutFromTrc(const QColorTrc &trc)
+{
+ if (trc.m_type == QColorTrc::Type::Table)
+ return QColorTrcLut::fromTransferTable(trc.m_table);
+ if (trc.m_type == QColorTrc::Type::Function)
+ return QColorTrcLut::fromTransferFunction(trc.m_fun);
+ qWarning() << "TRC uninitialized";
+ return nullptr;
+}
+
+void QColorTransformPrivate::updateLutsIn() const
+{
+ if (colorSpaceIn->lut.generated.loadAcquire())
+ return;
+ QMutexLocker lock(&QColorSpacePrivate::s_lutWriteLock);
+ if (colorSpaceIn->lut.generated.loadRelaxed())
+ return;
+
+ for (int i = 0; i < 3; ++i) {
+ if (!colorSpaceIn->trc[i].isValid())
+ return;
+ }
+
+ if (colorSpaceIn->trc[0] == colorSpaceIn->trc[1] && colorSpaceIn->trc[0] == colorSpaceIn->trc[2]) {
+ colorSpaceIn->lut[0].reset(lutFromTrc(colorSpaceIn->trc[0]));
+ colorSpaceIn->lut[1] = colorSpaceIn->lut[0];
+ colorSpaceIn->lut[2] = colorSpaceIn->lut[0];
+ } else {
+ for (int i = 0; i < 3; ++i)
+ colorSpaceIn->lut[i].reset(lutFromTrc(colorSpaceIn->trc[i]));
+ }
+
+ colorSpaceIn->lut.generated.storeRelease(1);
+}
+
+void QColorTransformPrivate::updateLutsOut() const
+{
+ if (colorSpaceOut->lut.generated.loadAcquire())
+ return;
+ QMutexLocker lock(&QColorSpacePrivate::s_lutWriteLock);
+ if (colorSpaceOut->lut.generated.loadRelaxed())
+ return;
+ for (int i = 0; i < 3; ++i) {
+ if (!colorSpaceOut->trc[i].isValid())
+ return;
+ }
+
+ if (colorSpaceOut->trc[0] == colorSpaceOut->trc[1] && colorSpaceOut->trc[0] == colorSpaceOut->trc[2]) {
+ colorSpaceOut->lut[0].reset(lutFromTrc(colorSpaceOut->trc[0]));
+ colorSpaceOut->lut[1] = colorSpaceOut->lut[0];
+ colorSpaceOut->lut[2] = colorSpaceOut->lut[0];
+ } else {
+ for (int i = 0; i < 3; ++i)
+ colorSpaceOut->lut[i].reset(lutFromTrc(colorSpaceOut->trc[i]));
+ }
+
+ colorSpaceOut->lut.generated.storeRelease(1);
+}
+
+/*!
+ \class QColorTransform
+ \brief The QColorTransform class is a transformation between color spaces.
+ \since 5.14
+
+ \ingroup painting
+ \ingroup appearance
+ \inmodule QtGui
+
+ QColorTransform is an instantiation of a transformation between color spaces.
+ It can be applied on color and pixels to convert them from one color space to
+ another.
+
+ Setting up a QColorTransform takes some preprocessing, so keeping around
+ QColorTransforms that you need often is recommended, instead of generating
+ them on the fly.
+*/
+
+
+QColorTransform::~QColorTransform() noexcept
+{
+}
+
+/*!
+ Applies the color transformation on the QRgb value \a argb.
+
+ The input should be opaque or unpremultiplied.
+*/
+QRgb QColorTransform::map(const QRgb &argb) const
+{
+ if (!d_ptr)
+ return argb;
+ Q_D(const QColorTransform);
+ constexpr float f = 1.0f / 255.0f;
+ QColorVector c = { qRed(argb) * f, qGreen(argb) * f, qBlue(argb) * f };
+ c.x = d->colorSpaceIn->trc[0].apply(c.x);
+ c.y = d->colorSpaceIn->trc[1].apply(c.y);
+ c.z = d->colorSpaceIn->trc[2].apply(c.z);
+ c = d->colorMatrix.map(c);
+ c.x = std::max(0.0f, std::min(1.0f, c.x));
+ c.y = std::max(0.0f, std::min(1.0f, c.y));
+ c.z = std::max(0.0f, std::min(1.0f, c.z));
+ if (d->colorSpaceOut->lut.generated.loadAcquire()) {
+ c.x = d->colorSpaceOut->lut[0]->fromLinear(c.x);
+ c.y = d->colorSpaceOut->lut[1]->fromLinear(c.y);
+ c.z = d->colorSpaceOut->lut[2]->fromLinear(c.z);
+ } else {
+ c.x = d->colorSpaceOut->trc[0].applyInverse(c.x);
+ c.y = d->colorSpaceOut->trc[1].applyInverse(c.y);
+ c.z = d->colorSpaceOut->trc[2].applyInverse(c.z);
+ }
+
+ return qRgba(c.x * 255 + 0.5f, c.y * 255 + 0.5f, c.z * 255 + 0.5f, qAlpha(argb));
+}
+
+/*!
+ Applies the color transformation on the QRgba64 value \a rgba64.
+
+ The input should be opaque or unpremultiplied.
+*/
+QRgba64 QColorTransform::map(const QRgba64 &rgba64) const
+{
+ if (!d_ptr)
+ return rgba64;
+ Q_D(const QColorTransform);
+ constexpr float f = 1.0f / 65535.0f;
+ QColorVector c = { rgba64.red() * f, rgba64.green() * f, rgba64.blue() * f };
+ c.x = d->colorSpaceIn->trc[0].apply(c.x);
+ c.y = d->colorSpaceIn->trc[1].apply(c.y);
+ c.z = d->colorSpaceIn->trc[2].apply(c.z);
+ c = d->colorMatrix.map(c);
+ c.x = std::max(0.0f, std::min(1.0f, c.x));
+ c.y = std::max(0.0f, std::min(1.0f, c.y));
+ c.z = std::max(0.0f, std::min(1.0f, c.z));
+ if (d->colorSpaceOut->lut.generated.loadAcquire()) {
+ c.x = d->colorSpaceOut->lut[0]->fromLinear(c.x);
+ c.y = d->colorSpaceOut->lut[1]->fromLinear(c.y);
+ c.z = d->colorSpaceOut->lut[2]->fromLinear(c.z);
+ } else {
+ c.x = d->colorSpaceOut->trc[0].applyInverse(c.x);
+ c.y = d->colorSpaceOut->trc[1].applyInverse(c.y);
+ c.z = d->colorSpaceOut->trc[2].applyInverse(c.z);
+ }
+
+ return QRgba64::fromRgba64(c.x * 65535, c.y * 65535, c.z * 65535, rgba64.alpha());
+}
+
+/*!
+ Applies the color transformation on the QColor value \a color.
+
+*/
+QColor QColorTransform::map(const QColor &color) const
+{
+ if (!d_ptr)
+ return color;
+ Q_D(const QColorTransform);
+ QColor clr = color;
+ if (color.spec() != QColor::ExtendedRgb || color.spec() != QColor::Rgb)
+ clr = clr.toRgb();
+
+ QColorVector c = { (float)clr.redF(), (float)clr.greenF(), (float)clr.blueF() };
+ if (clr.spec() == QColor::ExtendedRgb) {
+ c.x = d->colorSpaceIn->trc[0].applyExtended(c.x);
+ c.y = d->colorSpaceIn->trc[1].applyExtended(c.y);
+ c.z = d->colorSpaceIn->trc[2].applyExtended(c.z);
+ } else {
+ c.x = d->colorSpaceIn->trc[0].apply(c.x);
+ c.y = d->colorSpaceIn->trc[1].apply(c.y);
+ c.z = d->colorSpaceIn->trc[2].apply(c.z);
+ }
+ c = d->colorMatrix.map(c);
+ bool inGamut = c.x >= 0.0f && c.x <= 1.0f && c.y >= 0.0f && c.y <= 1.0f && c.z >= 0.0f && c.z <= 1.0f;
+ if (inGamut) {
+ if (d_ptr->colorSpaceOut->lut.generated.loadAcquire()) {
+ c.x = d->colorSpaceOut->lut[0]->fromLinear(c.x);
+ c.y = d->colorSpaceOut->lut[1]->fromLinear(c.y);
+ c.z = d->colorSpaceOut->lut[2]->fromLinear(c.z);
+ } else {
+ c.x = d->colorSpaceOut->trc[0].applyInverse(c.x);
+ c.y = d->colorSpaceOut->trc[1].applyInverse(c.y);
+ c.z = d->colorSpaceOut->trc[2].applyInverse(c.z);
+ }
+ } else {
+ c.x = d->colorSpaceOut->trc[0].applyInverseExtended(c.x);
+ c.y = d->colorSpaceOut->trc[1].applyInverseExtended(c.y);
+ c.z = d->colorSpaceOut->trc[2].applyInverseExtended(c.z);
+ }
+ QColor out;
+ out.setRgbF(c.x, c.y, c.z, color.alphaF());
+ return out;
+}
+
+// Optimized sub-routines for fast block based conversion:
+
+static void applyMatrix(QColorVector *buffer, const qsizetype len, const QColorMatrix &colorMatrix)
+{
+#if defined(__SSE2__)
+ const __m128 minV = _mm_set1_ps(0.0f);
+ const __m128 maxV = _mm_set1_ps(1.0f);
+ const __m128 xMat = _mm_loadu_ps(&colorMatrix.r.x);
+ const __m128 yMat = _mm_loadu_ps(&colorMatrix.g.x);
+ const __m128 zMat = _mm_loadu_ps(&colorMatrix.b.x);
+ for (qsizetype j = 0; j < len; ++j) {
+ __m128 c = _mm_loadu_ps(&buffer[j].x);
+ __m128 cx = _mm_shuffle_ps(c, c, _MM_SHUFFLE(0, 0, 0, 0));
+ __m128 cy = _mm_shuffle_ps(c, c, _MM_SHUFFLE(1, 1, 1, 1));
+ __m128 cz = _mm_shuffle_ps(c, c, _MM_SHUFFLE(2, 2, 2, 2));
+ cx = _mm_mul_ps(cx, xMat);
+ cy = _mm_mul_ps(cy, yMat);
+ cz = _mm_mul_ps(cz, zMat);
+ cx = _mm_add_ps(cx, cy);
+ cx = _mm_add_ps(cx, cz);
+ // Clamp:
+ cx = _mm_min_ps(cx, maxV);
+ cx = _mm_max_ps(cx, minV);
+ _mm_storeu_ps(&buffer[j].x, cx);
+ }
+#else
+ for (int j = 0; j < len; ++j) {
+ const QColorVector cv = colorMatrix.map(buffer[j]);
+ buffer[j].x = std::max(0.0f, std::min(1.0f, cv.x));
+ buffer[j].y = std::max(0.0f, std::min(1.0f, cv.y));
+ buffer[j].z = std::max(0.0f, std::min(1.0f, cv.z));
+ }
+#endif
+}
+
+template<typename T>
+static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr);
+template<typename T>
+static void loadUnpremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr);
+
+#if defined(__SSE2__)
+// Load to [0-alpha] in 4x32 SIMD
+template<typename T>
+static inline void loadP(const T &p, __m128i &v);
+
+template<>
+inline void loadP<QRgb>(const QRgb &p, __m128i &v)
+{
+ v = _mm_cvtsi32_si128(p);
+#if defined(__SSE4_1__)
+ v = _mm_cvtepu8_epi32(v);
+#else
+ v = _mm_unpacklo_epi8(v, _mm_setzero_si128());
+ v = _mm_unpacklo_epi16(v, _mm_setzero_si128());
+#endif
+}
+
+template<>
+inline void loadP<QRgba64>(const QRgba64 &p, __m128i &v)
+{
+ v = _mm_loadl_epi64((const __m128i *)&p);
+#if defined(__SSE4_1__)
+ v = _mm_cvtepu16_epi32(v);
+#else
+ v = _mm_unpacklo_epi16(v, _mm_setzero_si128());
+#endif
+ // Shuffle to ARGB as the template below expects it
+ v = _mm_shuffle_epi32(v, _MM_SHUFFLE(3, 0, 1, 2));
+}
+
+template<typename T>
+static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ const __m128 v4080 = _mm_set1_ps(4080.f);
+ const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
+ for (qsizetype i = 0; i < len; ++i) {
+ __m128i v;
+ loadP<T>(src[i], v);
+ __m128 vf = _mm_cvtepi32_ps(v);
+ // Approximate 1/a:
+ __m128 va = _mm_shuffle_ps(vf, vf, _MM_SHUFFLE(3, 3, 3, 3));
+ __m128 via = _mm_rcp_ps(va);
+ via = _mm_sub_ps(_mm_add_ps(via, via), _mm_mul_ps(via, _mm_mul_ps(via, va)));
+ // v * (1/a)
+ vf = _mm_mul_ps(vf, via);
+
+ // Handle zero alpha
+ __m128 vAlphaMask = _mm_cmpeq_ps(va, _mm_set1_ps(0.0f));
+ vf = _mm_andnot_ps(vAlphaMask, vf);
+
+ // LUT
+ v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
+ const int ridx = _mm_extract_epi16(v, 4);
+ const int gidx = _mm_extract_epi16(v, 2);
+ const int bidx = _mm_extract_epi16(v, 0);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[0]->m_toLinear[ridx], 0);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[1]->m_toLinear[gidx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[2]->m_toLinear[bidx], 4);
+ vf = _mm_mul_ps(_mm_cvtepi32_ps(v), iFF00);
+
+ _mm_storeu_ps(&buffer[i].x, vf);
+ }
+}
+
+// Load to [0-4080] in 4x32 SIMD
+template<typename T>
+static inline void loadPU(const T &p, __m128i &v);
+
+template<>
+inline void loadPU<QRgb>(const QRgb &p, __m128i &v)
+{
+ v = _mm_cvtsi32_si128(p);
+#if defined(__SSE4_1__)
+ v = _mm_cvtepu8_epi32(v);
+#else
+ v = _mm_unpacklo_epi8(v, _mm_setzero_si128());
+ v = _mm_unpacklo_epi16(v, _mm_setzero_si128());
+#endif
+ v = _mm_slli_epi32(v, 4);
+}
+
+template<>
+inline void loadPU<QRgba64>(const QRgba64 &p, __m128i &v)
+{
+ v = _mm_loadl_epi64((const __m128i *)&p);
+ v = _mm_sub_epi16(v, _mm_srli_epi16(v, 8));
+#if defined(__SSE4_1__)
+ v = _mm_cvtepu16_epi32(v);
+#else
+ v = _mm_unpacklo_epi16(v, _mm_setzero_si128());
+#endif
+ v = _mm_srli_epi32(v, 4);
+ // Shuffle to ARGB as the template below expects it
+ v = _mm_shuffle_epi32(v, _MM_SHUFFLE(3, 0, 1, 2));
+}
+
+template<typename T>
+void loadUnpremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
+ for (qsizetype i = 0; i < len; ++i) {
+ __m128i v;
+ loadPU<T>(src[i], v);
+ const int ridx = _mm_extract_epi16(v, 4);
+ const int gidx = _mm_extract_epi16(v, 2);
+ const int bidx = _mm_extract_epi16(v, 0);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[0]->m_toLinear[ridx], 0);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[1]->m_toLinear[gidx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[2]->m_toLinear[bidx], 4);
+ __m128 vf = _mm_mul_ps(_mm_cvtepi32_ps(v), iFF00);
+ _mm_storeu_ps(&buffer[i].x, vf);
+ }
+}
+
+#else
+template<>
+void loadPremultiplied<QRgb>(QColorVector *buffer, const QRgb *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const uint p = src[i];
+ const int a = qAlpha(p);
+ if (a) {
+ const float ia = 4080.0f / a;
+ const int ridx = int(qRed(p) * ia + 0.5f);
+ const int gidx = int(qGreen(p) * ia + 0.5f);
+ const int bidx = int(qBlue(p) * ia + 0.5f);
+ buffer[i].x = d_ptr->colorSpaceIn->lut[0]->m_toLinear[ridx] * (1.0f / (255 * 256));
+ buffer[i].y = d_ptr->colorSpaceIn->lut[1]->m_toLinear[gidx] * (1.0f / (255 * 256));
+ buffer[i].z = d_ptr->colorSpaceIn->lut[2]->m_toLinear[bidx] * (1.0f / (255 * 256));
+ } else {
+ buffer[i].x = buffer[i].y = buffer[i].z = 0.0f;
+ }
+ }
+}
+
+template<>
+void loadPremultiplied<QRgba64>(QColorVector *buffer, const QRgba64 *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const QRgba64 &p = src[i];
+ const int a = p.alpha();
+ if (a) {
+ const float ia = 4080.0f / a;
+ const int ridx = int(p.red() * ia + 0.5f);
+ const int gidx = int(p.green() * ia + 0.5f);
+ const int bidx = int(p.blue() * ia + 0.5f);
+ buffer[i].x = d_ptr->colorSpaceIn->lut[0]->m_toLinear[ridx] * (1.0f / (255 * 256));
+ buffer[i].y = d_ptr->colorSpaceIn->lut[1]->m_toLinear[gidx] * (1.0f / (255 * 256));
+ buffer[i].z = d_ptr->colorSpaceIn->lut[2]->m_toLinear[bidx] * (1.0f / (255 * 256));
+ } else {
+ buffer[i].x = buffer[i].y = buffer[i].z = 0.0f;
+ }
+ }
+}
+
+template<>
+void loadUnpremultiplied<QRgb>(QColorVector *buffer, const QRgb *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const uint p = src[i];
+ buffer[i].x = d_ptr->colorSpaceIn->lut[0]->u8ToLinearF32(qRed(p));
+ buffer[i].y = d_ptr->colorSpaceIn->lut[1]->u8ToLinearF32(qGreen(p));
+ buffer[i].z = d_ptr->colorSpaceIn->lut[2]->u8ToLinearF32(qBlue(p));
+ }
+}
+
+template<>
+void loadUnpremultiplied<QRgba64>(QColorVector *buffer, const QRgba64 *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const QRgba64 &p = src[i];
+ buffer[i].x = d_ptr->colorSpaceIn->lut[0]->u16ToLinearF32(p.red());
+ buffer[i].y = d_ptr->colorSpaceIn->lut[1]->u16ToLinearF32(p.green());
+ buffer[i].z = d_ptr->colorSpaceIn->lut[2]->u16ToLinearF32(p.blue());
+ }
+}
+#endif
+
+static void storePremultiplied(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+#if defined(__SSE2__)
+ const __m128 v4080 = _mm_set1_ps(4080.f);
+ const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = qAlpha(src[i]);
+ __m128 vf = _mm_loadu_ps(&buffer[i].x);
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
+ __m128 va = _mm_set1_ps(a);
+ va = _mm_mul_ps(va, iFF00);
+ const int ridx = _mm_extract_epi16(v, 0);
+ const int gidx = _mm_extract_epi16(v, 2);
+ const int bidx = _mm_extract_epi16(v, 4);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], 4);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], 0);
+ vf = _mm_cvtepi32_ps(v);
+ vf = _mm_mul_ps(vf, va);
+ v = _mm_cvtps_epi32(vf);
+ v = _mm_packs_epi32(v, v);
+ v = _mm_insert_epi16(v, a, 3);
+ v = _mm_packus_epi16(v, v);
+ dst[i] = _mm_cvtsi128_si32(v);
+ }
+#else
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = qAlpha(src[i]);
+ const float fa = a / (255.0f * 256.0f);
+ const float r = d_ptr->colorSpaceOut->lut[0]->m_fromLinear[int(buffer[i].x * 4080.0f + 0.5f)];
+ const float g = d_ptr->colorSpaceOut->lut[1]->m_fromLinear[int(buffer[i].y * 4080.0f + 0.5f)];
+ const float b = d_ptr->colorSpaceOut->lut[2]->m_fromLinear[int(buffer[i].z * 4080.0f + 0.5f)];
+ dst[i] = qRgba(r * fa + 0.5f, g * fa + 0.5f, b * fa + 0.5f, a);
+ }
+#endif
+}
+
+static void storeUnpremultiplied(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+#if defined(__SSE2__)
+ const __m128 v4080 = _mm_set1_ps(4080.f);
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = qAlpha(src[i]);
+ __m128 vf = _mm_loadu_ps(&buffer[i].x);
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
+ const int ridx = _mm_extract_epi16(v, 0);
+ const int gidx = _mm_extract_epi16(v, 2);
+ const int bidx = _mm_extract_epi16(v, 4);
+ v = _mm_setzero_si128();
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], 1);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], 0);
+ v = _mm_add_epi16(v, _mm_set1_epi16(0x80));
+ v = _mm_srli_epi16(v, 8);
+ v = _mm_insert_epi16(v, a, 3);
+ v = _mm_packus_epi16(v, v);
+ dst[i] = _mm_cvtsi128_si32(v);
+ }
+#else
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = d_ptr->colorSpaceOut->lut[0]->u8FromLinearF32(buffer[i].x);
+ const int g = d_ptr->colorSpaceOut->lut[1]->u8FromLinearF32(buffer[i].y);
+ const int b = d_ptr->colorSpaceOut->lut[2]->u8FromLinearF32(buffer[i].z);
+ dst[i] = (src[i] & 0xff000000) | (r << 16) | (g << 8) | (b << 0);
+ }
+#endif
+}
+
+static void storeOpaque(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ Q_UNUSED(src);
+#if defined(__SSE2__)
+ const __m128 v4080 = _mm_set1_ps(4080.f);
+ for (qsizetype i = 0; i < len; ++i) {
+ __m128 vf = _mm_loadu_ps(&buffer[i].x);
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
+ const int ridx = _mm_extract_epi16(v, 0);
+ const int gidx = _mm_extract_epi16(v, 2);
+ const int bidx = _mm_extract_epi16(v, 4);
+ v = _mm_setzero_si128();
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], 1);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], 0);
+ v = _mm_add_epi16(v, _mm_set1_epi16(0x80));
+ v = _mm_srli_epi16(v, 8);
+ v = _mm_insert_epi16(v, 255, 3);
+ v = _mm_packus_epi16(v, v);
+ dst[i] = _mm_cvtsi128_si32(v);
+ }
+#else
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = d_ptr->colorSpaceOut->lut[0]->u8FromLinearF32(buffer[i].x);
+ const int g = d_ptr->colorSpaceOut->lut[1]->u8FromLinearF32(buffer[i].y);
+ const int b = d_ptr->colorSpaceOut->lut[2]->u8FromLinearF32(buffer[i].z);
+ dst[i] = 0xff000000 | (r << 16) | (g << 8) | (b << 0);
+ }
+#endif
+}
+
+static void storePremultiplied(QRgba64 *dst, const QRgba64 *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = src[i].alpha();
+ const float fa = a / (255.0f * 256.0f);
+ const float r = d_ptr->colorSpaceOut->lut[0]->m_fromLinear[int(buffer[i].x * 4080.0f + 0.5f)];
+ const float g = d_ptr->colorSpaceOut->lut[1]->m_fromLinear[int(buffer[i].y * 4080.0f + 0.5f)];
+ const float b = d_ptr->colorSpaceOut->lut[2]->m_fromLinear[int(buffer[i].z * 4080.0f + 0.5f)];
+ dst[i] = qRgba64(r * fa + 0.5f, g * fa + 0.5f, b * fa + 0.5f, a);
+ }
+}
+
+static void storeUnpremultiplied(QRgba64 *dst, const QRgba64 *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = d_ptr->colorSpaceOut->lut[0]->u16FromLinearF32(buffer[i].x);
+ const int g = d_ptr->colorSpaceOut->lut[1]->u16FromLinearF32(buffer[i].y);
+ const int b = d_ptr->colorSpaceOut->lut[2]->u16FromLinearF32(buffer[i].z);
+ dst[i] = qRgba64(r, g, b, src[i].alpha());
+ }
+}
+
+static void storeOpaque(QRgba64 *dst, const QRgba64 *src, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ Q_UNUSED(src);
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = d_ptr->colorSpaceOut->lut[0]->u16FromLinearF32(buffer[i].x);
+ const int g = d_ptr->colorSpaceOut->lut[1]->u16FromLinearF32(buffer[i].y);
+ const int b = d_ptr->colorSpaceOut->lut[2]->u16FromLinearF32(buffer[i].z);
+ dst[i] = qRgba64(r, g, b, 0xFFFF);
+ }
+}
+
+static constexpr qsizetype WorkBlockSize = 256;
+
+template<typename T>
+void QColorTransformPrivate::apply(T *dst, const T *src, qsizetype count, TransformFlags flags) const
+{
+ if (!colorMatrix.isValid())
+ return;
+
+ updateLutsIn();
+ updateLutsOut();
+
+ bool doApplyMatrix = (colorMatrix != QColorMatrix::identity());
+
+ QColorVector buffer[WorkBlockSize];
+ qsizetype i = 0;
+ while (i < count) {
+ const qsizetype len = qMin(count - i, WorkBlockSize);
+ if (flags & InputPremultiplied)
+ loadPremultiplied(buffer, src + i, len, this);
+ else
+ loadUnpremultiplied(buffer, src + i, len, this);
+
+ if (doApplyMatrix)
+ applyMatrix(buffer, len, colorMatrix);
+
+ if (flags & InputOpaque)
+ storeOpaque(dst + i, src + i, buffer, len, this);
+ else if (flags & OutputPremultiplied)
+ storePremultiplied(dst + i, src + i, buffer, len, this);
+ else
+ storeUnpremultiplied(dst + i, src + i, buffer, len, this);
+
+ i += len;
+ }
+}
+
+/*!
+ \internal
+ \enum QColorTransformPrivate::TransformFlag
+
+ Defines how the transform is to be applied.
+
+ \value Unpremultiplied The input and output should both be unpremultiplied.
+ \value InputOpaque The input is guaranteed to be opaque.
+ \value InputPremultiplied The input is premultiplied.
+ \value OutputPremultiplied The output should be premultiplied.
+ \value Premultiplied Both input and output should both be premultiplied.
+*/
+
+/*!
+ \internal
+ Prepares a color transformation for fast application. You do not need to
+ call this explicitly as it will be called implicitly on the first transforms, but
+ if you want predictable performance on the first transforms, you can perform it
+ in advance.
+
+ \sa QColorTransform::map(), apply()
+*/
+void QColorTransformPrivate::prepare()
+{
+ updateLutsIn();
+ updateLutsOut();
+}
+
+/*!
+ \internal
+ Applies the color transformation on \a count QRgb pixels starting from
+ \a src and stores the result in \a dst.
+
+ Thread-safe if prepare() has been called first.
+
+ Assumes unpremultiplied data by default. Set \a flags to change defaults.
+
+ \sa prepare()
+*/
+void QColorTransformPrivate::apply(QRgb *dst, const QRgb *src, qsizetype count, TransformFlags flags) const
+{
+ apply<QRgb>(dst, src, count, flags);
+}
+
+/*!
+ \internal
+ Applies the color transformation on \a count QRgba64 pixels starting from
+ \a src and stores the result in \a dst.
+
+ Thread-safe if prepare() has been called first.
+
+ Assumes unpremultiplied data by default. Set \a flags to change defaults.
+
+ \sa prepare()
+*/
+void QColorTransformPrivate::apply(QRgba64 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const
+{
+ apply<QRgba64>(dst, src, count, flags);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolortransform.h b/src/gui/painting/qcolortransform.h
new file mode 100644
index 0000000000..9274387b97
--- /dev/null
+++ b/src/gui/painting/qcolortransform.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORTRANSFORM_H
+#define QCOLORTRANSFORM_H
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtGui/qrgb.h>
+
+QT_BEGIN_NAMESPACE
+
+class QColor;
+class QRgba64;
+class QColorSpacePrivate;
+class QColorTransformPrivate;
+
+class Q_GUI_EXPORT QColorTransform
+{
+public:
+ QColorTransform() noexcept : d_ptr(nullptr) { }
+ ~QColorTransform() noexcept;
+ QColorTransform(const QColorTransform &colorTransform) noexcept
+ : d_ptr(colorTransform.d_ptr)
+ { }
+ QColorTransform(QColorTransform &&colorTransform) noexcept
+ : d_ptr(std::move(colorTransform.d_ptr))
+ { }
+ QColorTransform &operator=(const QColorTransform &other) noexcept
+ {
+ d_ptr = other.d_ptr;
+ return *this;
+ }
+ QColorTransform &operator=(QColorTransform &&other) noexcept
+ {
+ d_ptr = std::move(other.d_ptr);
+ return *this;
+ }
+
+ bool isNull() const { return d_ptr.isNull(); }
+
+ QRgb map(const QRgb &argb) const;
+ QRgba64 map(const QRgba64 &rgba64) const;
+ QColor map(const QColor &color) const;
+
+private:
+ friend class QColorSpace;
+ friend class QColorSpacePrivate;
+ friend class QImage;
+
+ Q_DECLARE_PRIVATE(QColorTransform)
+ QSharedPointer<QColorTransformPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOLORTRANSFORM_H
diff --git a/src/gui/painting/qcolortransform_p.h b/src/gui/painting/qcolortransform_p.h
new file mode 100644
index 0000000000..74a1e7fe0a
--- /dev/null
+++ b/src/gui/painting/qcolortransform_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORTRANSFORM_P_H
+#define QCOLORTRANSFORM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qcolormatrix_p.h"
+#include "qcolorspace_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QColorTransformPrivate
+{
+public:
+ QColorMatrix colorMatrix;
+ QExplicitlySharedDataPointer<const QColorSpacePrivate> colorSpaceIn;
+ QExplicitlySharedDataPointer<const QColorSpacePrivate> colorSpaceOut;
+
+ void updateLutsIn() const;
+ void updateLutsOut() const;
+ bool simpleGammaCorrection() const;
+
+ void prepare();
+ enum TransformFlag {
+ Unpremultiplied = 0,
+ InputOpaque = 1,
+ InputPremultiplied = 2,
+ OutputPremultiplied = 4,
+ Premultiplied = (InputPremultiplied | OutputPremultiplied)
+ };
+ Q_DECLARE_FLAGS(TransformFlags, TransformFlag)
+
+ void apply(QRgb *dst, const QRgb *src, qsizetype count, TransformFlags flags = Unpremultiplied) const;
+ void apply(QRgba64 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags = Unpremultiplied) const;
+
+ template<typename T>
+ void apply(T *dst, const T *src, qsizetype count, TransformFlags flags) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOLORTRANSFORM_P_H
diff --git a/src/gui/painting/qcolortrc_p.h b/src/gui/painting/qcolortrc_p.h
new file mode 100644
index 0000000000..3ef9d442fc
--- /dev/null
+++ b/src/gui/painting/qcolortrc_p.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORTRC_P_H
+#define QCOLORTRC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include "qcolortransferfunction_p.h"
+#include "qcolortransfertable_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+// Defines an ICC TRC (Tone Reproduction Curve)
+class Q_GUI_EXPORT QColorTrc
+{
+public:
+ QColorTrc() noexcept : m_type(Type::Uninitialized)
+ { }
+ QColorTrc(const QColorTransferFunction &fun) : m_type(Type::Function), m_fun(fun)
+ { }
+ QColorTrc(const QColorTransferTable &table) : m_type(Type::Table), m_table(table)
+ { }
+
+ enum class Type {
+ Uninitialized,
+ Function,
+ Table
+ };
+
+ bool isLinear() const
+ {
+ return m_type == Type::Uninitialized || (m_type == Type::Function && m_fun.isLinear());
+ }
+ bool isValid() const
+ {
+ return m_type != Type::Uninitialized;
+ }
+ float apply(float x) const
+ {
+ if (m_type == Type::Table)
+ return m_table.apply(x);
+ if (m_type == Type::Function)
+ return m_fun.apply(x);
+ return x;
+ }
+ float applyExtended(float x) const
+ {
+ if (x >= 0.0f && x <= 1.0f)
+ return apply(x);
+ if (m_type == Type::Function)
+ return std::copysign(m_fun.apply(std::abs(x)), x);
+ if (m_type == Type::Table)
+ return x < 0.0f ? 0.0f : 1.0f;
+ return x;
+ }
+ float applyInverse(float x) const
+ {
+ if (m_type == Type::Table)
+ return m_table.applyInverse(x);
+ if (m_type == Type::Function)
+ return m_fun.inverted().apply(x);
+ return x;
+ }
+ float applyInverseExtended(float x) const
+ {
+ if (x >= 0.0f && x <= 1.0f)
+ return applyInverse(x);
+ if (m_type == Type::Function)
+ return std::copysign(applyInverse(x), x);
+ if (m_type == Type::Table)
+ return x < 0.0f ? 0.0f : 1.0f;
+ return x;
+ }
+
+ friend inline bool operator!=(const QColorTrc &o1, const QColorTrc &o2);
+ friend inline bool operator==(const QColorTrc &o1, const QColorTrc &o2);
+
+ Type m_type;
+ QColorTransferFunction m_fun;
+ QColorTransferTable m_table;
+};
+
+inline bool operator!=(const QColorTrc &o1, const QColorTrc &o2)
+{
+ if (o1.m_type != o2.m_type)
+ return true;
+ if (o1.m_type == QColorTrc::Type::Function)
+ return o1.m_fun != o2.m_fun;
+ if (o1.m_type == QColorTrc::Type::Table)
+ return o1.m_table != o2.m_table;
+ return false;
+}
+inline bool operator==(const QColorTrc &o1, const QColorTrc &o2)
+{
+ return !(o1 != o2);
+}
+
+QT_END_NAMESPACE
+
+#endif // QCOLORTRC
diff --git a/src/gui/painting/qcolorprofile.cpp b/src/gui/painting/qcolortrclut.cpp
index 3b7b0a248b..268d7252b4 100644
--- a/src/gui/painting/qcolorprofile.cpp
+++ b/src/gui/painting/qcolortrclut.cpp
@@ -37,14 +37,16 @@
**
****************************************************************************/
-#include "qcolorprofile_p.h"
+#include "qcolortrclut_p.h"
+#include "qcolortransferfunction_p.h"
+#include "qcolortransfertable_p.h"
#include <qmath.h>
QT_BEGIN_NAMESPACE
-QColorProfile *QColorProfile::fromGamma(qreal gamma)
+QColorTrcLut *QColorTrcLut::fromGamma(qreal gamma)
{
- QColorProfile *cp = new QColorProfile;
+ QColorTrcLut *cp = new QColorTrcLut;
for (int i = 0; i <= (255 * 16); ++i) {
cp->m_toLinear[i] = ushort(qRound(qPow(i / qreal(255 * 16), gamma) * (255 * 256)));
@@ -54,31 +56,28 @@ QColorProfile *QColorProfile::fromGamma(qreal gamma)
return cp;
}
-static qreal srgbToLinear(qreal v)
+QColorTrcLut *QColorTrcLut::fromTransferFunction(const QColorTransferFunction &fun)
{
- const qreal a = 0.055;
- if (v <= qreal(0.04045))
- return v / qreal(12.92);
- else
- return qPow((v + a) / (qreal(1) + a), qreal(2.4));
-}
+ QColorTrcLut *cp = new QColorTrcLut;
+ QColorTransferFunction inv = fun.inverted();
-static qreal linearToSrgb(qreal v)
-{
- const qreal a = 0.055;
- if (v <= qreal(0.0031308))
- return v * qreal(12.92);
- else
- return (qreal(1) + a) * qPow(v, qreal(1.0 / 2.4)) - a;
+ for (int i = 0; i <= (255 * 16); ++i) {
+ cp->m_toLinear[i] = ushort(qRound(fun.apply(i / qreal(255 * 16)) * (255 * 256)));
+ cp->m_fromLinear[i] = ushort(qRound(inv.apply(i / qreal(255 * 16)) * (255 * 256)));
+ }
+
+ return cp;
}
-QColorProfile *QColorProfile::fromSRgb()
+QColorTrcLut *QColorTrcLut::fromTransferTable(const QColorTransferTable &table)
{
- QColorProfile *cp = new QColorProfile;
+ QColorTrcLut *cp = new QColorTrcLut;
+ float minInverse = 0.0f;
for (int i = 0; i <= (255 * 16); ++i) {
- cp->m_toLinear[i] = ushort(qRound(srgbToLinear(i / qreal(255 * 16)) * (255 * 256)));
- cp->m_fromLinear[i] = ushort(qRound(linearToSrgb(i / qreal(255 * 16)) * (255 * 256)));
+ cp->m_toLinear[i] = ushort(qBound(0, qRound(table.apply(i / qreal(255 * 16)) * (255 * 256)), 65280));
+ minInverse = table.applyInverse(i / qreal(255 * 16), minInverse);
+ cp->m_fromLinear[i] = ushort(qBound(0, qRound(minInverse * (255 * 256)), 65280));
}
return cp;
diff --git a/src/gui/painting/qcolorprofile_p.h b/src/gui/painting/qcolortrclut_p.h
index 425e9abace..76a6a60803 100644
--- a/src/gui/painting/qcolorprofile_p.h
+++ b/src/gui/painting/qcolortrclut_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QCOLORPROFILE_P_H
-#define QCOLORPROFILE_P_H
+#ifndef QCOLORTRCLUT_P_H
+#define QCOLORTRCLUT_P_H
//
// W A R N I N G
@@ -52,21 +52,29 @@
//
#include <QtGui/private/qtguiglobal_p.h>
+#include <QtCore/qsharedpointer.h>
#include <QtGui/qrgb.h>
#include <QtGui/qrgba64.h>
+#include <cmath>
+
#if defined(__SSE2__)
#include <emmintrin.h>
#elif defined(__ARM_NEON__) || defined(__ARM_NEON)
#include <arm_neon.h>
#endif
+
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QColorProfile
+class QColorTransferFunction;
+class QColorTransferTable;
+
+class Q_GUI_EXPORT QColorTrcLut : public QEnableSharedFromThis<QColorTrcLut>
{
public:
- static QColorProfile *fromGamma(qreal gamma);
- static QColorProfile *fromSRgb();
+ static QColorTrcLut *fromGamma(qreal gamma);
+ static QColorTrcLut *fromTransferFunction(const QColorTransferFunction &transfn);
+ static QColorTrcLut *fromTransferTable(const QColorTransferTable &transTable);
// The following methods all convert opaque or unpremultiplied colors:
@@ -121,6 +129,25 @@ public:
return convertWithTable(rgb64, m_toLinear);
}
+ float u8ToLinearF32(int c) const
+ {
+ ushort v = m_toLinear[c << 4];
+ return v * (1.0f / (255*256));
+ }
+
+ float u16ToLinearF32(int c) const
+ {
+ c -= (c >> 8);
+ ushort v = m_toLinear[c >> 4];
+ return v * (1.0f / (255*256));
+ }
+
+ float toLinear(float f) const
+ {
+ ushort v = m_toLinear[(int)(f * (255 * 16) + 0.5f)];
+ return v * (1.0f / (255*256));
+ }
+
QRgb fromLinear64(QRgba64 rgb64) const
{
#if defined(__SSE2__)
@@ -176,8 +203,31 @@ public:
return convertWithTable(rgb64, m_fromLinear);
}
+ int u8FromLinearF32(float f) const
+ {
+ ushort v = m_fromLinear[(int)(f * (255 * 16) + 0.5f)];
+ return (v + 0x80) >> 8;
+ }
+ int u16FromLinearF32(float f) const
+ {
+ ushort v = m_fromLinear[(int)(f * (255 * 16) + 0.5f)];
+ return v + (v >> 8);
+ }
+ float fromLinear(float f) const
+ {
+ ushort v = m_fromLinear[(int)(f * (255 * 16) + 0.5f)];
+ return v * (1.0f / (255*256));
+ }
+
+ // We translate to 0-65280 (255*256) instead to 0-65535 to make simple
+ // shifting an accurate conversion.
+ // We translate from 0-4080 (255*16) for the same speed up, and to keep
+ // the tables small enough to fit in most inner caches.
+ ushort m_toLinear[(255 * 16) + 1]; // [0-4080] -> [0-65280]
+ ushort m_fromLinear[(255 * 16) + 1]; // [0-4080] -> [0-65280]
+
private:
- QColorProfile() { }
+ QColorTrcLut() { }
Q_ALWAYS_INLINE static QRgb convertWithTable(QRgb rgb32, const ushort *table)
{
@@ -230,16 +280,8 @@ private:
return QRgba64::fromRgba64(r, g, b, rgb64.alpha());
#endif
}
-
- // We translate to 0-65280 (255*256) instead to 0-65535 to make simple
- // shifting an accurate conversion.
- // We translate from 0-4080 (255*16) for the same speed up, and to keep
- // the tables small enough to fit in most inner caches.
- ushort m_toLinear[(255 * 16) + 1]; // [0-4080] -> [0-65280]
- ushort m_fromLinear[(255 * 16) + 1]; // [0-4080] -> [0-65280]
-
};
QT_END_NAMESPACE
-#endif // QCOLORPROFILE_P_H
+#endif // QCOLORTRCLUT_P_H
diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp
index 027bf23115..06a849e790 100644
--- a/src/gui/painting/qcompositionfunctions.cpp
+++ b/src/gui/painting/qcompositionfunctions.cpp
@@ -137,6 +137,7 @@ struct Rgba64OperationsBase
{ ::memcpy(dest, src, len * sizeof(Type)); }
};
+#if QT_CONFIG(raster_64bit)
const Rgba64OperationsBase::Type Rgba64OperationsBase::clear = QRgba64::fromRgba64(0);
struct Rgba64OperationsC : public Rgba64OperationsBase
@@ -309,10 +310,8 @@ struct Rgba64OperationsNEON : public Rgba64OperationsBase
return interpolate65535(x, a1, y, a2);
}
};
-
#endif
-typedef Argb32OperationsC Argb32Operations;
#if defined(__SSE2__)
typedef Rgba64OperationsSSE2 Rgba64Operations;
#elif defined(__ARM_NEON__)
@@ -320,6 +319,9 @@ typedef Rgba64OperationsNEON Rgba64Operations;
#else
typedef Rgba64OperationsC Rgba64Operations;
#endif
+#endif // QT_CONFIG(raster_64bit)
+
+typedef Argb32OperationsC Argb32Operations;
/*
result = 0
@@ -343,20 +345,23 @@ void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_
comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
}
-void QT_FASTCALL comp_func_solid_Clear_rgb64(QRgba64 *dest, int length, QRgba64, uint const_alpha)
+void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
{
- comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
+ comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
}
-void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_Clear_rgb64(QRgba64 *dest, int length, QRgba64, uint const_alpha)
{
- comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
+ comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
}
void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int length, uint const_alpha)
{
comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
}
+#endif
+
/*
result = s
@@ -399,36 +404,40 @@ void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint
comp_func_solid_Source_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_Source_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_Source_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_Source_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_Source_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_Source_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_Source_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint)
{
}
-void QT_FASTCALL comp_func_solid_Destination_rgb64(QRgba64 *, int, QRgba64, uint)
+void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint)
{
}
-void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_Destination_rgb64(QRgba64 *, int, QRgba64, uint)
{
}
void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, uint)
{
}
+#endif
/*
result = s + d * sia
@@ -483,20 +492,22 @@ void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color,
comp_func_solid_SourceOver_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_SourceOver_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_SourceOver_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_SourceOver_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_SourceOver_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_SourceOver_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
/*
result = d + s * dia
@@ -542,20 +553,22 @@ void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint co
comp_func_solid_DestinationOver_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_DestinationOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_DestinationOver_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_DestinationOver_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_DestinationOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_DestinationOver_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_DestinationOver_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_DestinationOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_DestinationOver_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
/*
result = s * da
@@ -606,20 +619,22 @@ void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, ui
comp_func_solid_SourceIn_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_SourceIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_SourceIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_SourceIn_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_SourceIn_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_SourceIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_SourceIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_SourceIn_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_SourceIn_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_SourceIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_SourceIn_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
/*
result = d * sa
@@ -665,20 +680,22 @@ void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint colo
comp_func_solid_DestinationIn_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_DestinationIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_DestinationIn_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_DestinationIn_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_DestinationIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_DestinationIn_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_DestinationIn_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_DestinationIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_DestinationIn_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
/*
result = s * dia
@@ -727,20 +744,22 @@ void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, u
comp_func_solid_SourceOut_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_SourceOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_SourceOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_SourceOut_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_SourceOut_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_SourceOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_SourceOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_SourceOut_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_SourceOut_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_SourceOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_SourceOut_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
/*
result = d * sia
@@ -786,20 +805,22 @@ void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint col
comp_func_solid_DestinationOut_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_DestinationOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_DestinationOut_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_DestinationOut_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_DestinationOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_DestinationOut_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_DestinationOut_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_DestinationOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_DestinationOut_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
/*
result = s*da + d*sia
@@ -845,20 +866,22 @@ void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color,
comp_func_solid_SourceAtop_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_SourceAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_SourceAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_SourceAtop_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_SourceAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_SourceAtop_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_SourceAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_SourceAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_SourceAtop_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
/*
result = d*sa + s*dia
@@ -909,20 +932,22 @@ void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint co
comp_func_solid_DestinationAtop_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_DestinationAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_DestinationAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_DestinationAtop_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_DestinationAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_DestinationAtop_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_DestinationAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_DestinationAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_DestinationAtop_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
/*
result = d*sia + s*dia
@@ -969,20 +994,22 @@ void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint co
comp_func_solid_XOR_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_XOR_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_XOR_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_XOR_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_XOR_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_XOR_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_XOR_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_XOR_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_XOR_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
struct QFullCoverage {
inline void store(uint *dest, const uint src) const
@@ -1078,20 +1105,22 @@ void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint c
comp_func_solid_Plus_template<Argb32Operations>(dest, length, color, const_alpha);
}
-void QT_FASTCALL comp_func_solid_Plus_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+void QT_FASTCALL comp_func_Plus(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- comp_func_solid_Plus_template<Rgba64Operations>(dest, length, color, const_alpha);
+ comp_func_Plus_template<Argb32Operations>(dest, src, length, const_alpha);
}
-void QT_FASTCALL comp_func_Plus(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_Plus_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
- comp_func_Plus_template<Argb32Operations>(dest, src, length, const_alpha);
+ comp_func_solid_Plus_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_Plus_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
comp_func_Plus_template<Rgba64Operations>(dest, src, length, const_alpha);
}
+#endif
/*
Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1101,13 +1130,8 @@ static inline int multiply_op(int dst, int src, int da, int sa)
return qt_div_255(src * dst + src * (255 - da) + dst * (255 - sa));
}
-static inline uint multiply_op_rgb64(uint dst, uint src, uint da, uint sa)
-{
- return qt_div_65535(src * dst + src * (65535 - da) + dst * (65535 - sa));
-}
-
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -1129,8 +1153,22 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest,
}
}
+void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Multiply_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
+static inline uint multiply_op_rgb64(uint dst, uint src, uint da, uint sa)
+{
+ return qt_div_65535(src * dst + src * (65535 - da) + dst * (65535 - sa));
+}
+
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void comp_func_solid_Multiply_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -1152,14 +1190,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(QRgba64 *de
}
}
-void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_Multiply_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_solid_Multiply_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1167,9 +1197,10 @@ void QT_FASTCALL comp_func_solid_Multiply_rgb64(QRgba64 *dest, int length, QRgba
else
comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -1189,8 +1220,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *Q_DECL_REST
}
}
+void QT_FASTCALL comp_func_Multiply(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Multiply_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Multiply_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -1210,14 +1250,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(QRgba64 *Q_DECL_R
}
}
-void QT_FASTCALL comp_func_Multiply(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_Multiply_impl(dest, src, length, QFullCoverage());
- else
- comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_Multiply_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1225,13 +1257,14 @@ void QT_FASTCALL comp_func_Multiply_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const Q
else
comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
/*
Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
= Sca + Dca - Sca.Dca
*/
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void comp_func_solid_Screen_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -1253,8 +1286,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, i
}
}
+void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Screen_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void comp_func_solid_Screen_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -1276,14 +1318,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(QRgba64 *dest
}
}
-void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_Screen_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_solid_Screen_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1291,9 +1325,10 @@ void QT_FASTCALL comp_func_solid_Screen_rgb64(QRgba64 *dest, int length, QRgba64
else
comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -1313,8 +1348,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *Q_DECL_RESTRI
}
}
+void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Screen_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Screen_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -1334,14 +1378,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(QRgba64 *Q_DECL_RES
}
}
-void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_Screen_impl(dest, src, length, QFullCoverage());
- else
- comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_Screen_rgb64(QRgba64 *dest, const QRgba64 *src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1349,6 +1385,7 @@ void QT_FASTCALL comp_func_Screen_rgb64(QRgba64 *dest, const QRgba64 *src, int l
else
comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
/*
if 2.Dca < Da
@@ -1365,17 +1402,8 @@ static inline int overlay_op(int dst, int src, int da, int sa)
return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp);
}
-static inline uint overlay_op_rgb64(uint dst, uint src, uint da, uint sa)
-{
- const uint temp = src * (65535 - da) + dst * (65535 - sa);
- if (2 * dst < da)
- return qt_div_65535(2 * src * dst + temp);
- else
- return qt_div_65535(sa * da - 2 * (da - dst) * (sa - src) + temp);
-}
-
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -1397,8 +1425,26 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest,
}
}
+void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Overlay_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
+static inline uint overlay_op_rgb64(uint dst, uint src, uint da, uint sa)
+{
+ const uint temp = src * (65535 - da) + dst * (65535 - sa);
+ if (2 * dst < da)
+ return qt_div_65535(2 * src * dst + temp);
+ else
+ return qt_div_65535(sa * da - 2 * (da - dst) * (sa - src) + temp);
+}
+
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void comp_func_solid_Overlay_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -1420,14 +1466,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(QRgba64 *des
}
}
-void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_Overlay_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_solid_Overlay_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1435,9 +1473,10 @@ void QT_FASTCALL comp_func_solid_Overlay_rgb64(QRgba64 *dest, int length, QRgba6
else
comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -1457,8 +1496,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *Q_DECL_RESTR
}
}
+void QT_FASTCALL comp_func_Overlay(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Overlay_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Overlay_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -1478,14 +1526,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(QRgba64 *Q_DECL_RE
}
}
-void QT_FASTCALL comp_func_Overlay(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_Overlay_impl(dest, src, length, QFullCoverage());
- else
- comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_Overlay_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1493,6 +1533,7 @@ void QT_FASTCALL comp_func_Overlay_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QR
else
comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
/*
Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1503,13 +1544,8 @@ static inline int darken_op(int dst, int src, int da, int sa)
return qt_div_255(qMin(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa));
}
-static inline uint darken_op_rgb64(uint dst, uint src, uint da, uint sa)
-{
- return qt_div_65535(qMin(src * da, dst * sa) + src * (65535 - da) + dst * (65535 - sa));
-}
-
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -1531,8 +1567,22 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, i
}
}
+void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Darken_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
+static inline uint darken_op_rgb64(uint dst, uint src, uint da, uint sa)
+{
+ return qt_div_65535(qMin(src * da, dst * sa) + src * (65535 - da) + dst * (65535 - sa));
+}
+
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void comp_func_solid_Darken_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -1554,14 +1604,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(QRgba64 *dest
}
}
-void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_Darken_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_solid_Darken_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1569,9 +1611,10 @@ void QT_FASTCALL comp_func_solid_Darken_rgb64(QRgba64 *dest, int length, QRgba64
else
comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -1591,8 +1634,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *Q_DECL_RESTRI
}
}
+void QT_FASTCALL comp_func_Darken(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Darken_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Darken_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -1612,14 +1664,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(QRgba64 *Q_DECL_RES
}
}
-void QT_FASTCALL comp_func_Darken(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_Darken_impl(dest, src, length, QFullCoverage());
- else
- comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_Darken_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1627,6 +1671,7 @@ void QT_FASTCALL comp_func_Darken_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRg
else
comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
/*
Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1637,13 +1682,8 @@ static inline int lighten_op(int dst, int src, int da, int sa)
return qt_div_255(qMax(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa));
}
-static inline uint lighten_op_rgb64(uint dst, uint src, uint da, uint sa)
-{
- return qt_div_65535(qMax(src * da, dst * sa) + src * (65535 - da) + dst * (65535 - sa));
-}
-
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -1665,8 +1705,23 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest,
}
}
+void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Lighten_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
+
+#if QT_CONFIG(raster_64bit)
+static inline uint lighten_op_rgb64(uint dst, uint src, uint da, uint sa)
+{
+ return qt_div_65535(qMax(src * da, dst * sa) + src * (65535 - da) + dst * (65535 - sa));
+}
+
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void comp_func_solid_Lighten_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -1688,14 +1743,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(QRgba64 *des
}
}
-void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_Lighten_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_solid_Lighten_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1703,9 +1750,10 @@ void QT_FASTCALL comp_func_solid_Lighten_rgb64(QRgba64 *dest, int length, QRgba6
else
comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -1725,8 +1773,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *Q_DECL_RESTR
}
}
+void QT_FASTCALL comp_func_Lighten(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Lighten_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Lighten_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -1746,14 +1803,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(QRgba64 *Q_DECL_RE
}
}
-void QT_FASTCALL comp_func_Lighten(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_Lighten_impl(dest, src, length, QFullCoverage());
- else
- comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_Lighten_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1761,6 +1810,7 @@ void QT_FASTCALL comp_func_Lighten_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QR
else
comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
/*
if Sca.Da + Dca.Sa >= Sa.Da
@@ -1781,21 +1831,8 @@ static inline int color_dodge_op(int dst, int src, int da, int sa)
return qt_div_255(255 * dst_sa / (255 - 255 * src / sa) + temp);
}
-static inline uint color_dodge_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
-{
- const qint64 sa_da = sa * da;
- const qint64 dst_sa = dst * sa;
- const qint64 src_da = src * da;
-
- const qint64 temp = src * (65535 - da) + dst * (65535 - sa);
- if (src_da + dst_sa >= sa_da)
- return qt_div_65535(sa_da + temp);
- else
- return qt_div_65535(65535 * dst_sa / (65535 - 65535 * src / sa) + temp);
-}
-
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -1817,8 +1854,30 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *des
}
}
+void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_ColorDodge_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
+static inline uint color_dodge_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
+{
+ const qint64 sa_da = sa * da;
+ const qint64 dst_sa = dst * sa;
+ const qint64 src_da = src * da;
+
+ const qint64 temp = src * (65535 - da) + dst * (65535 - sa);
+ if (src_da + dst_sa >= sa_da)
+ return qt_div_65535(sa_da + temp);
+ else
+ return qt_div_65535(65535 * dst_sa / (65535 - 65535 * src / sa) + temp);
+}
+
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void comp_func_solid_ColorDodge_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -1840,14 +1899,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(QRgba64 *
}
}
-void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_ColorDodge_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_solid_ColorDodge_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1855,9 +1906,10 @@ void QT_FASTCALL comp_func_solid_ColorDodge_rgb64(QRgba64 *dest, int length, QRg
else
comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -1877,8 +1929,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *Q_DECL_RE
}
}
+void QT_FASTCALL comp_func_ColorDodge(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_ColorDodge_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_ColorDodge_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -1898,14 +1959,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(QRgba64 *Q_DECL
}
}
-void QT_FASTCALL comp_func_ColorDodge(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_ColorDodge_impl(dest, src, length, QFullCoverage());
- else
- comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_ColorDodge_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1913,6 +1966,7 @@ void QT_FASTCALL comp_func_ColorDodge_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
else
comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
/*
if Sca.Da + Dca.Sa <= Sa.Da
@@ -1933,21 +1987,8 @@ static inline int color_burn_op(int dst, int src, int da, int sa)
return qt_div_255(sa * (src_da + dst_sa - sa_da) / src + temp);
}
-static inline uint color_burn_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
-{
- const qint64 src_da = src * da;
- const qint64 dst_sa = dst * sa;
- const qint64 sa_da = sa * da;
-
- const qint64 temp = src * (65535 - da) + dst * (65535 - sa);
-
- if (src == 0 || src_da + dst_sa <= sa_da)
- return qt_div_65535(temp);
- return qt_div_65535(sa * (src_da + dst_sa - sa_da) / src + temp);
-}
-
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -1969,8 +2010,30 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest
}
}
+void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_ColorBurn_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
+static inline uint color_burn_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
+{
+ const qint64 src_da = src * da;
+ const qint64 dst_sa = dst * sa;
+ const qint64 sa_da = sa * da;
+
+ const qint64 temp = src * (65535 - da) + dst * (65535 - sa);
+
+ if (src == 0 || src_da + dst_sa <= sa_da)
+ return qt_div_65535(temp);
+ return qt_div_65535(sa * (src_da + dst_sa - sa_da) / src + temp);
+}
+
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void comp_func_solid_ColorBurn_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -1992,14 +2055,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(QRgba64 *d
}
}
-void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_ColorBurn_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_solid_ColorBurn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -2007,9 +2062,10 @@ void QT_FASTCALL comp_func_solid_ColorBurn_rgb64(QRgba64 *dest, int length, QRgb
else
comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -2029,8 +2085,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *Q_DECL_RES
}
}
+void QT_FASTCALL comp_func_ColorBurn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_ColorBurn_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_ColorBurn_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -2050,14 +2115,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(QRgba64 *Q_DECL_
}
}
-void QT_FASTCALL comp_func_ColorBurn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_ColorBurn_impl(dest, src, length, QFullCoverage());
- else
- comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_ColorBurn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -2065,6 +2122,7 @@ void QT_FASTCALL comp_func_ColorBurn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
else
comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
/*
if 2.Sca < Sa
@@ -2082,18 +2140,8 @@ static inline uint hardlight_op(int dst, int src, int da, int sa)
return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp);
}
-static inline uint hardlight_op_rgb64(uint dst, uint src, uint da, uint sa)
-{
- const uint temp = src * (65535 - da) + dst * (65535 - sa);
-
- if (2 * src < sa)
- return qt_div_65535(2 * src * dst + temp);
- else
- return qt_div_65535(sa * da - 2 * (da - dst) * (sa - src) + temp);
-}
-
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -2115,8 +2163,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest
}
}
+void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_HardLight_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
+static inline uint hardlight_op_rgb64(uint dst, uint src, uint da, uint sa)
+{
+ const uint temp = src * (65535 - da) + dst * (65535 - sa);
+
+ if (2 * src < sa)
+ return qt_div_65535(2 * src * dst + temp);
+ else
+ return qt_div_65535(sa * da - 2 * (da - dst) * (sa - src) + temp);
+}
+
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void comp_func_solid_HardLight_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -2138,14 +2205,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(QRgba64 *d
}
}
-void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_HardLight_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_solid_HardLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -2153,9 +2212,10 @@ void QT_FASTCALL comp_func_solid_HardLight_rgb64(QRgba64 *dest, int length, QRgb
else
comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -2175,8 +2235,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *Q_DECL_RES
}
}
+void QT_FASTCALL comp_func_HardLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_HardLight_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_HardLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -2196,14 +2265,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(QRgba64 *Q_DECL_
}
}
-void QT_FASTCALL comp_func_HardLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_HardLight_impl(dest, src, length, QFullCoverage());
- else
- comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_HardLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -2211,6 +2272,7 @@ void QT_FASTCALL comp_func_HardLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
else
comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
/*
if 2.Sca <= Sa
@@ -2235,24 +2297,8 @@ static inline int soft_light_op(int dst, int src, int da, int sa)
}
}
-static inline uint soft_light_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
-{
- const qint64 src2 = src << 1;
- const qint64 dst_np = da != 0 ? (65535 * dst) / da : 0;
- const qint64 temp = (src * (65535 - da) + dst * (65535 - sa)) * 65535;
- const qint64 factor = qint64(65535) * 65535;
-
- if (src2 < sa)
- return (dst * (sa * 65535 + (src2 - sa) * (65535 - dst_np)) + temp) / factor;
- else if (4 * dst <= da)
- return (dst * sa * 65535 + da * (src2 - sa) * ((((16 * dst_np - 12 * 65535) * dst_np + 3 * factor) * dst_np) / factor) + temp) / factor;
- else {
- return (dst * sa * 65535 + da * (src2 - sa) * (int(qSqrt(qreal(dst_np * 65535))) - dst_np) + temp) / factor;
- }
-}
-
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -2274,8 +2320,25 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest
}
}
+#if QT_CONFIG(raster_64bit)
+static inline uint soft_light_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
+{
+ const qint64 src2 = src << 1;
+ const qint64 dst_np = da != 0 ? (65535 * dst) / da : 0;
+ const qint64 temp = (src * (65535 - da) + dst * (65535 - sa)) * 65535;
+ const qint64 factor = qint64(65535) * 65535;
+
+ if (src2 < sa)
+ return (dst * (sa * 65535 + (src2 - sa) * (65535 - dst_np)) + temp) / factor;
+ else if (4 * dst <= da)
+ return (dst * sa * 65535 + da * (src2 - sa) * ((((16 * dst_np - 12 * 65535) * dst_np + 3 * factor) * dst_np) / factor) + temp) / factor;
+ else {
+ return (dst * sa * 65535 + da * (src2 - sa) * (int(qSqrt(qreal(dst_np * 65535))) - dst_np) + temp) / factor;
+ }
+}
+
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void comp_func_solid_SoftLight_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -2296,6 +2359,7 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(QRgba64 *d
coverage.store(&dest[i], qRgba64(r, g, b, a));
}
}
+#endif
void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha)
{
@@ -2305,16 +2369,8 @@ void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, u
comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha));
}
-void QT_FASTCALL comp_func_solid_SoftLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -2334,8 +2390,25 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *Q_DECL_RES
}
}
+void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_SoftLight_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
+void QT_FASTCALL comp_func_solid_SoftLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_SoftLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -2355,14 +2428,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(QRgba64 *Q_DECL_
}
}
-void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_SoftLight_impl(dest, src, length, QFullCoverage());
- else
- comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_SoftLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -2370,6 +2435,7 @@ void QT_FASTCALL comp_func_SoftLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
else
comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
/*
Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -2380,13 +2446,8 @@ static inline int difference_op(int dst, int src, int da, int sa)
return src + dst - qt_div_255(2 * qMin(src * da, dst * sa));
}
-static inline uint difference_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
-{
- return src + dst - qt_div_65535(2 * qMin(src * da, dst * sa));
-}
-
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -2408,8 +2469,22 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *des
}
}
+void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Difference_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
+static inline uint difference_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
+{
+ return src + dst - qt_div_65535(2 * qMin(src * da, dst * sa));
+}
+
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void comp_func_solid_Difference_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -2431,14 +2506,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(QRgba64 *
}
}
-void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_Difference_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_solid_Difference_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -2446,9 +2513,10 @@ void QT_FASTCALL comp_func_solid_Difference_rgb64(QRgba64 *dest, int length, QRg
else
comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -2468,8 +2536,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *Q_DECL_RE
}
}
+void QT_FASTCALL comp_func_Difference(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Difference_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Difference_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -2489,14 +2566,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(QRgba64 *Q_DECL
}
}
-void QT_FASTCALL comp_func_Difference(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_Difference_impl(dest, src, length, QFullCoverage());
- else
- comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_Difference_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -2504,12 +2573,13 @@ void QT_FASTCALL comp_func_Difference_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
else
comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
/*
Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
*/
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_impl(uint *dest, int length, uint color, const T &coverage)
+static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(uint *dest, int length, uint color, const T &coverage)
{
int sa = qAlpha(color);
int sr = qRed(color);
@@ -2531,8 +2601,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_imp
}
}
+void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Exclusion_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
{
uint sa = color.alpha();
uint sr = color.red();
@@ -2555,14 +2634,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_imp
}
-void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_solid_Exclusion_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_solid_Exclusion_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
{
if (const_alpha == 255)
@@ -2570,9 +2641,10 @@ void QT_FASTCALL comp_func_solid_Exclusion_rgb64(QRgba64 *dest, int length, QRgb
else
comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+#endif
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
uint d = dest[i];
@@ -2592,8 +2664,17 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *Q_DECL_RES
}
}
+void QT_FASTCALL comp_func_Exclusion(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Exclusion_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
+#if QT_CONFIG(raster_64bit)
template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+static inline void comp_func_Exclusion_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
{
for (int i = 0; i < length; ++i) {
QRgba64 d = dest[i];
@@ -2613,14 +2694,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(QRgba64 *Q_DECL_
}
}
-void QT_FASTCALL comp_func_Exclusion(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- comp_func_Exclusion_impl(dest, src, length, QFullCoverage());
- else
- comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha));
-}
-
void QT_FASTCALL comp_func_Exclusion_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -2628,6 +2701,7 @@ void QT_FASTCALL comp_func_Exclusion_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
else
comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#endif
void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
int length,
@@ -2977,6 +3051,7 @@ CompositionFunctionSolid qt_functionForModeSolid_C[] = {
};
CompositionFunctionSolid64 qt_functionForModeSolid64_C[] = {
+#if QT_CONFIG(raster_64bit)
comp_func_solid_SourceOver_rgb64,
comp_func_solid_DestinationOver_rgb64,
comp_func_solid_Clear_rgb64,
@@ -3001,6 +3076,10 @@ CompositionFunctionSolid64 qt_functionForModeSolid64_C[] = {
comp_func_solid_SoftLight_rgb64,
comp_func_solid_Difference_rgb64,
comp_func_solid_Exclusion_rgb64,
+#else
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#endif
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
@@ -3047,6 +3126,7 @@ CompositionFunction qt_functionForMode_C[] = {
};
CompositionFunction64 qt_functionForMode64_C[] = {
+#if QT_CONFIG(raster_64bit)
comp_func_SourceOver_rgb64,
comp_func_DestinationOver_rgb64,
comp_func_Clear_rgb64,
@@ -3071,6 +3151,10 @@ CompositionFunction64 qt_functionForMode64_C[] = {
comp_func_SoftLight_rgb64,
comp_func_Difference_rgb64,
comp_func_Exclusion_rgb64,
+#else
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#endif
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp
index 436a62d486..0fb89a75b5 100644
--- a/src/gui/painting/qcosmeticstroker.cpp
+++ b/src/gui/painting/qcosmeticstroker.cpp
@@ -289,7 +289,7 @@ void QCosmeticStroker::setup()
drawCaps = state->lastPen.capStyle() != Qt::FlatCap;
if (strokeSelection & FastDraw) {
- color = multiplyAlpha256(state->penData.solid.color, opacity).toArgb32();
+ color = multiplyAlpha256(state->penData.solidColor, opacity).toArgb32();
QRasterBuffer *buffer = state->penData.rasterBuffer;
pixels = (uint *)buffer->buffer();
ppl = buffer->stride<quint32>();
diff --git a/src/gui/painting/qcosmeticstroker_p.h b/src/gui/painting/qcosmeticstroker_p.h
index 082ddee30f..8571b0476a 100644
--- a/src/gui/painting/qcosmeticstroker_p.h
+++ b/src/gui/painting/qcosmeticstroker_p.h
@@ -98,8 +98,8 @@ public:
: state(s),
deviceRect(dr_unclipped),
clip(dr),
- pattern(0),
- reversePattern(0),
+ pattern(nullptr),
+ reversePattern(nullptr),
patternSize(0),
patternLength(0),
patternOffset(0),
diff --git a/src/gui/painting/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h
index 7cac2ac358..181d19da0b 100644
--- a/src/gui/painting/qdatabuffer_p.h
+++ b/src/gui/painting/qdatabuffer_p.h
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
template <typename Type> class QDataBuffer
{
- Q_DISABLE_COPY(QDataBuffer)
+ Q_DISABLE_COPY_MOVE(QDataBuffer)
public:
QDataBuffer(int res)
{
@@ -69,7 +69,7 @@ public:
buffer = (Type*) malloc(capacity * sizeof(Type));
Q_CHECK_PTR(buffer);
} else {
- buffer = 0;
+ buffer = nullptr;
}
siz = 0;
}
@@ -128,7 +128,7 @@ public:
Q_CHECK_PTR(buffer);
} else {
free(buffer);
- buffer = 0;
+ buffer = nullptr;
}
}
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 1f7ab5006c..006befea22 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -43,7 +43,7 @@
#include <qstylehints.h>
#include <qguiapplication.h>
#include <qatomic.h>
-#include <private/qcolorprofile_p.h>
+#include <private/qcolortrclut_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qpainter_p.h>
@@ -55,6 +55,7 @@
#endif
#include <private/qguiapplication_p.h>
#include <private/qrgba64_p.h>
+#include <qendian.h>
#include <qloggingcategory.h>
#include <qmath.h>
@@ -856,6 +857,44 @@ static const QRgba64 *QT_FASTCALL fetchGrayscale8ToRGB64(QRgba64 *buffer, const
return buffer;
}
+static void QT_FASTCALL convertGrayscale16ToRGB32(uint *buffer, int count, const QVector<QRgb> *)
+{
+ for (int i = 0; i < count; ++i) {
+ const uint x = qt_div_257(buffer[i]);
+ buffer[i] = qRgb(x, x, x);
+ }
+}
+
+static const uint *QT_FASTCALL fetchGrayscale16ToRGB32(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ const unsigned short *s = reinterpret_cast<const unsigned short *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ const uint x = qt_div_257(s[i]);
+ buffer[i] = qRgb(x, x, x);
+ }
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL convertGrayscale16ToRGBA64(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ const unsigned short *s = reinterpret_cast<const unsigned short *>(src);
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromRgba64(s[i], s[i], s[i], 65535);
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL fetchGrayscale16ToRGBA64(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ const unsigned short *s = reinterpret_cast<const unsigned short *>(src) + index;
+ for (int i = 0; i < count; ++i) {
+ buffer[i] = QRgba64::fromRgba64(s[i], s[i], s[i], 65535);
+ }
+ return buffer;
+}
+
static void QT_FASTCALL storeARGB32FromARGB32PM(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
{
@@ -1047,18 +1086,8 @@ static const QRgba64 *QT_FASTCALL fetchRGB32ToRGB64(QRgba64 *buffer, const uchar
static const QRgba64 *QT_FASTCALL convertARGB32ToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
-#ifdef __SSE2__
- qConvertARGB32PMToRGBA64PM_sse2<false, false>(buffer, src, count);
- for (int i = 0; i < count; ++i)
- buffer[i] = buffer[i].premultiplied();
-#elif defined(__ARM_NEON__)
- qConvertARGB32PMToRGBA64PM_neon<false, false>(buffer, src, count);
- for (int i = 0; i < count; ++i)
- buffer[i] = buffer[i].premultiplied();
-#else
for (int i = 0; i < count; ++i)
buffer[i] = QRgba64::fromArgb32(src[i]).premultiplied();
-#endif
return buffer;
}
@@ -1088,6 +1117,7 @@ static const QRgba64 *QT_FASTCALL fetchARGB32PMToRGBA64PM(QRgba64 *buffer, const
return convertARGB32PMToRGBA64PM(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr);
}
+#if QT_CONFIG(raster_64bit)
static void convertRGBA64ToRGBA64PM(QRgba64 *buffer, int count)
{
for (int i = 0; i < count; ++i)
@@ -1097,6 +1127,7 @@ static void convertRGBA64ToRGBA64PM(QRgba64 *buffer, int count)
static void convertRGBA64PMToRGBA64PM(QRgba64 *, int)
{
}
+#endif
static const QRgba64 *QT_FASTCALL fetchRGBA64ToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
@@ -1110,18 +1141,8 @@ static const QRgba64 *QT_FASTCALL fetchRGBA64ToRGBA64PM(QRgba64 *buffer, const u
static const QRgba64 *QT_FASTCALL convertRGBA8888ToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
-#ifdef __SSE2__
- qConvertARGB32PMToRGBA64PM_sse2<true, false>(buffer, src, count);
- for (int i = 0; i < count; ++i)
- buffer[i] = buffer[i].premultiplied();
-#elif defined(__ARM_NEON__)
- qConvertARGB32PMToRGBA64PM_neon<true, false>(buffer, src, count);
- for (int i = 0; i < count; ++i)
- buffer[i] = buffer[i].premultiplied();
-#else
for (int i = 0; i < count; ++i)
buffer[i] = QRgba64::fromArgb32(RGBA2ARGB(src[i])).premultiplied();
-#endif
return buffer;
}
@@ -1361,6 +1382,22 @@ static void QT_FASTCALL storeGrayscale8FromARGB32PM(uchar *dest, const uint *src
dest[index + i] = qGray(qUnpremultiply(src[i]));
}
+static void QT_FASTCALL storeGrayscale16FromRGB32(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ unsigned short *d = reinterpret_cast<unsigned short *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = qGray(src[i]) * 257;
+}
+
+static void QT_FASTCALL storeGrayscale16FromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ unsigned short *d = reinterpret_cast<unsigned short *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = qGray(qUnpremultiply(src[i])) * 257;
+}
+
static const uint *QT_FASTCALL fetchRGB64ToRGB32(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
{
@@ -1487,7 +1524,11 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
{ true, true, QPixelLayout::BPP64, nullptr,
convertPassThrough, nullptr,
fetchRGB64ToRGB32, fetchPassThrough64,
- storeRGB64FromRGB32, storeRGB64FromRGB32 } // Format_RGBA64_Premultiplied
+ storeRGB64FromRGB32, storeRGB64FromRGB32 }, // Format_RGBA64_Premultiplied
+ { false, false, QPixelLayout::BPP16, nullptr,
+ convertGrayscale16ToRGB32, convertGrayscale16ToRGBA64,
+ fetchGrayscale16ToRGB32, fetchGrayscale16ToRGBA64,
+ storeGrayscale16FromARGB32PM, storeGrayscale16FromRGB32 } // Format_Grayscale16
};
Q_STATIC_ASSERT(sizeof(qPixelLayouts) / sizeof(*qPixelLayouts) == QImage::NImageFormats);
@@ -1563,6 +1604,16 @@ static void QT_FASTCALL storeRGBA64PMFromRGBA64PM(uchar *dest, const QRgba64 *sr
memcpy(d, src, count * sizeof(QRgba64));
}
+static void QT_FASTCALL storeGray16FromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ quint16 *d = reinterpret_cast<quint16*>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ QRgba64 s = src[i].unpremultiplied();
+ d[i] = qGray(s.red(), s.green(), s.blue());
+ }
+}
+
ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = {
nullptr,
nullptr,
@@ -1591,7 +1642,8 @@ ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = {
storeGenericFromRGBA64PM<QImage::Format_Grayscale8>,
storeRGBX64FromRGBA64PM,
storeRGBA64FromRGBA64PM,
- storeRGBA64PMFromRGBA64PM
+ storeRGBA64PMFromRGBA64PM,
+ storeGray16FromRGBA64PM
};
/*
@@ -1649,22 +1701,6 @@ static uint *QT_FASTCALL destFetchUndefined(uint *buffer, QRasterBuffer *, int,
return buffer;
}
-static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
-{
- const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
- return const_cast<QRgba64 *>(layout->fetchToRGBA64PM(buffer, rasterBuffer->scanLine(y), x, length, nullptr, nullptr));
-}
-
-static QRgba64 * QT_FASTCALL destFetchRGB64(QRgba64 *, QRasterBuffer *rasterBuffer, int x, int y, int)
-{
- return (QRgba64 *)rasterBuffer->scanLine(y) + x;
-}
-
-static QRgba64 * QT_FASTCALL destFetch64Undefined(QRgba64 *buffer, QRasterBuffer *, int, int, int)
-{
- return buffer;
-}
-
static DestFetchProc destFetchProc[QImage::NImageFormats] =
{
0, // Format_Invalid
@@ -1695,8 +1731,26 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
destFetch, // Format_RGBX64
destFetch, // Format_RGBA64
destFetch, // Format_RGBA64_Premultiplied
+ destFetch, // Format_Grayscale16
};
+#if QT_CONFIG(raster_64bit)
+static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+{
+ const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
+ return const_cast<QRgba64 *>(layout->fetchToRGBA64PM(buffer, rasterBuffer->scanLine(y), x, length, nullptr, nullptr));
+}
+
+static QRgba64 * QT_FASTCALL destFetchRGB64(QRgba64 *, QRasterBuffer *rasterBuffer, int x, int y, int)
+{
+ return (QRgba64 *)rasterBuffer->scanLine(y) + x;
+}
+
+static QRgba64 * QT_FASTCALL destFetch64Undefined(QRgba64 *buffer, QRasterBuffer *, int, int, int)
+{
+ return buffer;
+}
+
static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
{
0, // Format_Invalid
@@ -1727,7 +1781,9 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
destFetchRGB64, // Format_RGBX64
destFetch64, // Format_RGBA64
destFetchRGB64, // Format_RGBA64_Premultiplied
+ destFetch64, // Format_Grayscale16
};
+#endif
/*
Returns the color in the mono destination color table
@@ -1835,21 +1891,6 @@ static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, con
store(dest, buffer, x, length, nullptr, nullptr);
}
-static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
-{
- auto store = qStoreFromRGBA64PM[rasterBuffer->format];
- uchar *dest = rasterBuffer->scanLine(y);
- store(dest, buffer, x, length, nullptr, nullptr);
-}
-
-static void QT_FASTCALL destStore64RGBA64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
-{
- QRgba64 *dest = reinterpret_cast<QRgba64*>(rasterBuffer->scanLine(y)) + x;
- for (int i = 0; i < length; ++i) {
- dest[i] = buffer[i].unpremultiplied();
- }
-}
-
static DestStoreProc destStoreProc[QImage::NImageFormats] =
{
0, // Format_Invalid
@@ -1880,8 +1921,25 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] =
destStore, // Format_RGBX64
destStore, // Format_RGBA64
destStore, // Format_RGBA64_Premultiplied
+ destStore, // Format_Grayscale16
};
+#if QT_CONFIG(raster_64bit)
+static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+ auto store = qStoreFromRGBA64PM[rasterBuffer->format];
+ uchar *dest = rasterBuffer->scanLine(y);
+ store(dest, buffer, x, length, nullptr, nullptr);
+}
+
+static void QT_FASTCALL destStore64RGBA64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+ QRgba64 *dest = reinterpret_cast<QRgba64*>(rasterBuffer->scanLine(y)) + x;
+ for (int i = 0; i < length; ++i) {
+ dest[i] = buffer[i].unpremultiplied();
+ }
+}
+
static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
{
0, // Format_Invalid
@@ -1911,8 +1969,10 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
destStore64, // Format_Grayscale8
0, // Format_RGBX64
destStore64RGBA64, // Format_RGBA64
- 0 // Format_RGBA64_Premultiplied
+ 0, // Format_RGBA64_Premultiplied
+ destStore64, // Format_Grayscale16
};
+#endif
/*
Source fetches
@@ -1963,6 +2023,7 @@ static const uint *QT_FASTCALL fetchUntransformedRGB16(uint *buffer, const Opera
return buffer;
}
+#if QT_CONFIG(raster_64bit)
static const QRgba64 *QT_FASTCALL fetchUntransformed64(QRgba64 *buffer, const Operator *,
const QSpanData *data, int y, int x, int length)
{
@@ -1976,6 +2037,7 @@ static const QRgba64 *QT_FASTCALL fetchUntransformedRGBA64PM(QRgba64 *, const Op
const uchar *scanLine = data->texture.scanLine(y);
return reinterpret_cast<const QRgba64 *>(scanLine) + x;
}
+#endif
template<TextureBlendType blendType>
inline void fetchTransformed_pixelBounds(int max, int l1, int l2, int &v)
@@ -2166,6 +2228,7 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *,
return buffer;
}
+#if QT_CONFIG(raster_64bit)
template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */
static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Operator *, const QSpanData *data,
int y, int x, int length)
@@ -2186,6 +2249,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
convertRGBA64ToRGBA64PM(buffer, length);
return buffer;
}
+#endif
/** \internal
interpolate 4 argb pixels with the distx and disty factor.
@@ -3487,6 +3551,7 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
return buffer;
}
+#if QT_CONFIG(raster_64bit)
template<TextureBlendType blendType>
static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint32(QRgba64 *buffer, const QSpanData *data,
int y, int x, int length)
@@ -3807,6 +3872,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
return fetchTransformedBilinear64_uint64<blendType>(buffer, data, y, x, length);
return fetchTransformedBilinear64_uint32<blendType>(buffer, data, y, x, length);
}
+#endif
// FetchUntransformed can have more specialized methods added depending on SIMD features.
static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
@@ -3838,6 +3904,7 @@ static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
fetchUntransformed, // RGBX64
fetchUntransformed, // RGBA64
fetchUntransformed, // RGBA64_Premultiplied
+ fetchUntransformed, // Grayscale16
};
static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = {
@@ -3876,6 +3943,20 @@ static SourceFetchProc sourceFetchAny32[NBlendTypes] = {
fetchTransformedBilinear<BlendTransformedBilinearTiled, QPixelLayout::BPP32> // TransformedBilinearTiled
};
+static inline SourceFetchProc getSourceFetch(TextureBlendType blendType, QImage::Format format)
+{
+ if (format == QImage::Format_RGB32 || format == QImage::Format_ARGB32_Premultiplied)
+ return sourceFetchARGB32PM[blendType];
+ if (blendType == BlendUntransformed || blendType == BlendTiled)
+ return sourceFetchUntransformed[format];
+ if (qPixelLayouts[format].bpp == QPixelLayout::BPP16)
+ return sourceFetchAny16[blendType];
+ if (qPixelLayouts[format].bpp == QPixelLayout::BPP32)
+ return sourceFetchAny32[blendType];
+ return sourceFetchGeneric[blendType];
+}
+
+#if QT_CONFIG(raster_64bit)
static const SourceFetchProc64 sourceFetchGeneric64[NBlendTypes] = {
fetchUntransformed64, // Untransformed
fetchUntransformed64, // Tiled
@@ -3894,25 +3975,13 @@ static const SourceFetchProc64 sourceFetchRGBA64PM[NBlendTypes] = {
fetchTransformedBilinear64<BlendTransformedBilinearTiled> // BilinearTiled
};
-static inline SourceFetchProc getSourceFetch(TextureBlendType blendType, QImage::Format format)
-{
- if (format == QImage::Format_RGB32 || format == QImage::Format_ARGB32_Premultiplied)
- return sourceFetchARGB32PM[blendType];
- if (blendType == BlendUntransformed || blendType == BlendTiled)
- return sourceFetchUntransformed[format];
- if (qPixelLayouts[format].bpp == QPixelLayout::BPP16)
- return sourceFetchAny16[blendType];
- if (qPixelLayouts[format].bpp == QPixelLayout::BPP32)
- return sourceFetchAny32[blendType];
- return sourceFetchGeneric[blendType];
-}
-
static inline SourceFetchProc64 getSourceFetch64(TextureBlendType blendType, QImage::Format format)
{
if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBA64_Premultiplied)
return sourceFetchRGBA64PM[blendType];
return sourceFetchGeneric64[blendType];
}
+#endif
#define FIXPT_BITS 8
@@ -3924,11 +3993,13 @@ static uint qt_gradient_pixel_fixed(const QGradientData *data, int fixed_pos)
return data->colorTable32[qt_gradient_clamp(data, ipos)];
}
+#if QT_CONFIG(raster_64bit)
static const QRgba64& qt_gradient_pixel64_fixed(const QGradientData *data, int fixed_pos)
{
int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS;
return data->colorTable64[qt_gradient_clamp(data, ipos)];
}
+#endif
static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const QSpanData *data)
{
@@ -3962,6 +4033,7 @@ public:
}
};
+#if QT_CONFIG(raster_64bit)
class GradientBase64
{
public:
@@ -3980,6 +4052,7 @@ public:
qt_memfill64((quint64*)buffer, fill, length);
}
};
+#endif
template<class GradientBase, typename BlendType>
static inline const BlendType * QT_FASTCALL qt_fetch_linear_gradient_template(
@@ -4057,11 +4130,13 @@ static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Ope
return qt_fetch_linear_gradient_template<GradientBase32, uint>(buffer, op, data, y, x, length);
}
+#if QT_CONFIG(raster_64bit)
static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data,
int y, int x, int length)
{
return qt_fetch_linear_gradient_template<GradientBase64, QRgba64>(buffer, op, data, y, x, length);
}
+#endif
static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data)
{
@@ -4123,11 +4198,13 @@ const uint * QT_FASTCALL qt_fetch_radial_gradient_plain(uint *buffer, const Oper
static SourceFetchProc qt_fetch_radial_gradient = qt_fetch_radial_gradient_plain;
+#if QT_CONFIG(raster_64bit)
const QRgba64 * QT_FASTCALL qt_fetch_radial_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data,
int y, int x, int length)
{
return qt_fetch_radial_gradient_template<RadialFetchPlain<GradientBase64>, QRgba64>(buffer, op, data, y, x, length);
}
+#endif
template <class GradientBase, typename BlendType>
static inline const BlendType * QT_FASTCALL qt_fetch_conical_gradient_template(
@@ -4186,23 +4263,29 @@ static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Op
return qt_fetch_conical_gradient_template<GradientBase32, uint>(buffer, data, y, x, length);
}
+#if QT_CONFIG(raster_64bit)
static const QRgba64 * QT_FASTCALL qt_fetch_conical_gradient_rgb64(QRgba64 *buffer, const Operator *, const QSpanData *data,
int y, int x, int length)
{
return qt_fetch_conical_gradient_template<GradientBase64, QRgba64>(buffer, data, y, x, length);
}
+#endif
extern CompositionFunctionSolid qt_functionForModeSolid_C[];
extern CompositionFunctionSolid64 qt_functionForModeSolid64_C[];
static const CompositionFunctionSolid *functionForModeSolid = qt_functionForModeSolid_C;
+#if QT_CONFIG(raster_64bit)
static const CompositionFunctionSolid64 *functionForModeSolid64 = qt_functionForModeSolid64_C;
+#endif
extern CompositionFunction qt_functionForMode_C[];
extern CompositionFunction64 qt_functionForMode64_C[];
static const CompositionFunction *functionForMode = qt_functionForMode_C;
+#if QT_CONFIG(raster_64bit)
static const CompositionFunction64 *functionForMode64 = qt_functionForMode64_C;
+#endif
static TextureBlendType getBlendType(const QSpanData *data)
{
@@ -4232,43 +4315,60 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
switch(data->type) {
case QSpanData::Solid:
- solidSource = data->solid.color.isOpaque();
+ solidSource = data->solidColor.isOpaque();
op.srcFetch = 0;
+#if QT_CONFIG(raster_64bit)
op.srcFetch64 = 0;
+#endif
break;
case QSpanData::LinearGradient:
solidSource = !data->gradient.alphaColor;
getLinearGradientValues(&op.linear, data);
op.srcFetch = qt_fetch_linear_gradient;
+#if QT_CONFIG(raster_64bit)
op.srcFetch64 = qt_fetch_linear_gradient_rgb64;
+#endif
break;
case QSpanData::RadialGradient:
solidSource = !data->gradient.alphaColor;
getRadialGradientValues(&op.radial, data);
op.srcFetch = qt_fetch_radial_gradient;
+#if QT_CONFIG(raster_64bit)
op.srcFetch64 = qt_fetch_radial_gradient_rgb64;
+#endif
break;
case QSpanData::ConicalGradient:
solidSource = !data->gradient.alphaColor;
op.srcFetch = qt_fetch_conical_gradient;
+#if QT_CONFIG(raster_64bit)
op.srcFetch64 = qt_fetch_conical_gradient_rgb64;
+#endif
break;
case QSpanData::Texture:
solidSource = !data->texture.hasAlpha;
op.srcFetch = getSourceFetch(getBlendType(data), data->texture.format);
+#if QT_CONFIG(raster_64bit)
op.srcFetch64 = getSourceFetch64(getBlendType(data), data->texture.format);;
+#endif
break;
default:
Q_UNREACHABLE();
break;
}
+#if !QT_CONFIG(raster_64bit)
+ op.srcFetch64 = 0;
+#endif
op.mode = data->rasterBuffer->compositionMode;
if (op.mode == QPainter::CompositionMode_SourceOver && solidSource)
op.mode = QPainter::CompositionMode_Source;
op.destFetch = destFetchProc[data->rasterBuffer->format];
+#if QT_CONFIG(raster_64bit)
op.destFetch64 = destFetchProc64[data->rasterBuffer->format];
+#else
+ op.destFetch64 = 0;
+#endif
if (op.mode == QPainter::CompositionMode_Source &&
(data->type != QSpanData::Texture || data->texture.const_alpha == 256)) {
const QSpan *lastSpan = spans + spanCount;
@@ -4280,44 +4380,90 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
}
++spans;
}
- if (!alphaSpans) {
+ if (!alphaSpans && spanCount > 0) {
// If all spans are opaque we do not need to fetch dest.
// But don't clear passthrough destFetch as they are just as fast and save destStore.
if (op.destFetch != destFetchARGB32P)
op.destFetch = destFetchUndefined;
+#if QT_CONFIG(raster_64bit)
if (op.destFetch64 != destFetchRGB64)
op.destFetch64 = destFetch64Undefined;
+#endif
}
}
op.destStore = destStoreProc[data->rasterBuffer->format];
- op.destStore64 = destStoreProc64[data->rasterBuffer->format];
-
op.funcSolid = functionForModeSolid[op.mode];
- op.funcSolid64 = functionForModeSolid64[op.mode];
op.func = functionForMode[op.mode];
+#if QT_CONFIG(raster_64bit)
+ op.destStore64 = destStoreProc64[data->rasterBuffer->format];
+ op.funcSolid64 = functionForModeSolid64[op.mode];
op.func64 = functionForMode64[op.mode];
+#else
+ op.destStore64 = 0;
+ op.funcSolid64 = 0;
+ op.func64 = 0;
+#endif
return op;
}
+static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP bpp, int x, int y, int length)
+{
+ switch (bpp) {
+ case QPixelLayout::BPP64: {
+ quint64 *dest = reinterpret_cast<quint64 *>(rasterBuffer->scanLine(y)) + x;
+ qt_memfill_template(dest + 1, dest[0], length - 1);
+ break;
+ }
+ case QPixelLayout::BPP32: {
+ quint32 *dest = reinterpret_cast<quint32 *>(rasterBuffer->scanLine(y)) + x;
+ qt_memfill_template(dest + 1, dest[0], length - 1);
+ break;
+ }
+ case QPixelLayout::BPP24: {
+ quint24 *dest = reinterpret_cast<quint24 *>(rasterBuffer->scanLine(y)) + x;
+ qt_memfill_template(dest + 1, dest[0], length - 1);
+ break;
+ }
+ case QPixelLayout::BPP16: {
+ quint16 *dest = reinterpret_cast<quint16 *>(rasterBuffer->scanLine(y)) + x;
+ qt_memfill_template(dest + 1, dest[0], length - 1);
+ break;
+ }
+ case QPixelLayout::BPP8: {
+ uchar *dest = rasterBuffer->scanLine(y) + x;
+ memset(dest + 1, dest[0], length - 1);
+ break;
+ }
+ default:
+ Q_UNREACHABLE();
+ }
+}
// -------------------- blend methods ---------------------
-#if !defined(Q_CC_SUN)
-static
-#endif
-void blend_color_generic(int count, const QSpan *spans, void *userData)
+static void blend_color_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
uint buffer[BufferSize];
- Operator op = getOperator(data, spans, count);
- const uint color = data->solid.color.toArgb32();
+ Operator op = getOperator(data, nullptr, 0);
+ const uint color = data->solidColor.toArgb32();
+ bool solidFill = data->rasterBuffer->compositionMode == QPainter::CompositionMode_Source
+ || (data->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver && qAlpha(color) == 255);
+ QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp;
while (count--) {
int x = spans->x;
int length = spans->len;
+ if (solidFill && bpp >= QPixelLayout::BPP8 && spans->coverage == 255 && length) {
+ // If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
+ op.destStore(data->rasterBuffer, x, spans->y, &color, 1);
+ spanfill_from_first(data->rasterBuffer, bpp, x, spans->y, length);
+ length = 0;
+ }
+
while (length) {
int l = qMin(BufferSize, length);
uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans->y, l);
@@ -4335,15 +4481,15 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- const Operator op = getOperator(data, spans, count);
- const uint color = data->solid.color.toArgb32();
+ const Operator op = getOperator(data, nullptr, 0);
+ const uint color = data->solidColor.toArgb32();
if (op.mode == QPainter::CompositionMode_Source) {
// inline for performance
while (count--) {
uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
if (spans->coverage == 255) {
- QT_MEMFILL_UINT(target, spans->len, color);
+ qt_memfill(target, color, spans->len);
} else {
uint c = BYTE_MUL(color, spans->coverage);
int ialpha = 255 - spans->coverage;
@@ -4364,30 +4510,28 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
{
+#if QT_CONFIG(raster_64bit)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, spans, count);
+ Operator op = getOperator(data, nullptr, 0);
if (!op.funcSolid64) {
qCDebug(lcQtGuiDrawHelper, "blend_color_generic_rgb64: unsupported 64bit blend attempted, falling back to 32-bit");
return blend_color_generic(count, spans, userData);
}
alignas(8) QRgba64 buffer[BufferSize];
- const QRgba64 color = data->solid.color;
+ const QRgba64 color = data->solidColor;
bool solidFill = data->rasterBuffer->compositionMode == QPainter::CompositionMode_Source
|| (data->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver && color.isOpaque());
- bool isBpp32 = qPixelLayouts[data->rasterBuffer->format].bpp == QPixelLayout::BPP32;
+ QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp;
while (count--) {
int x = spans->x;
int length = spans->len;
- if (solidFill && isBpp32 && spans->coverage == 255) {
+ if (solidFill && bpp >= QPixelLayout::BPP8 && spans->coverage == 255 && length) {
// If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
- if (length > 0) {
- op.destStore64(data->rasterBuffer, x, spans->y, &color, 1);
- uint *dest = (uint*)data->rasterBuffer->scanLine(spans->y) + x;
- qt_memfill32(dest + 1, dest[0], length - 1);
- length = 0;
- }
+ op.destStore64(data->rasterBuffer, x, spans->y, &color, 1);
+ spanfill_from_first(data->rasterBuffer, bpp, x, spans->y, length);
+ length = 0;
}
while (length) {
@@ -4401,6 +4545,9 @@ void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
}
++spans;
}
+#else
+ blend_color_generic(count, spans, userData);
+#endif
}
static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
@@ -4413,18 +4560,18 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
from qt_gradient_quint16 with minimal overhead.
*/
QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
- if (mode == QPainter::CompositionMode_SourceOver && data->solid.color.isOpaque())
+ if (mode == QPainter::CompositionMode_SourceOver && data->solidColor.isOpaque())
mode = QPainter::CompositionMode_Source;
if (mode == QPainter::CompositionMode_Source) {
// inline for performance
- ushort c = data->solid.color.toRgb16();
+ ushort c = data->solidColor.toRgb16();
for (; count--; spans++) {
if (!spans->len)
continue;
ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
if (spans->coverage == 255) {
- QT_MEMFILL_USHORT(target, spans->len, c);
+ qt_memfill(target, c, spans->len);
} else {
ushort color = BYTE_MUL_RGB16(c, spans->coverage);
int ialpha = 255 - spans->coverage;
@@ -4442,7 +4589,7 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
for (; count--; spans++) {
if (!spans->len)
continue;
- uint color = BYTE_MUL(data->solid.color.toArgb32(), spans->coverage);
+ uint color = BYTE_MUL(data->solidColor.toArgb32(), spans->coverage);
int ialpha = qAlpha(~color);
ushort c = qConvertRgb32To16(color);
ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
@@ -4581,6 +4728,7 @@ public:
}
};
+#if QT_CONFIG(raster_64bit)
class BlendSrcGenericRGB64 : public QBlendBase<QRgba64>
{
public:
@@ -4611,6 +4759,7 @@ public:
op.destStore64(data->rasterBuffer, x, y, dest, len);
}
};
+#endif
static void blend_src_generic(int count, const QSpan *spans, void *userData)
{
@@ -4619,6 +4768,7 @@ static void blend_src_generic(int count, const QSpan *spans, void *userData)
handleSpans(count, spans, data, blend);
}
+#if QT_CONFIG(raster_64bit)
static void blend_src_generic_rgb64(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -4632,6 +4782,7 @@ static void blend_src_generic_rgb64(int count, const QSpan *spans, void *userDat
handleSpans(count, spans, data, blend32);
}
}
+#endif
static void blend_untransformed_generic(int count, const QSpan *spans, void *userData)
{
@@ -4679,6 +4830,7 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use
}
}
+#if QT_CONFIG(raster_64bit)
static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -4728,6 +4880,7 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
}
}
}
+#endif
static void blend_untransformed_argb(int count, const QSpan *spans, void *userData)
{
@@ -4928,6 +5081,7 @@ static void blend_tiled_generic(int count, const QSpan *spans, void *userData)
}
}
+#if QT_CONFIG(raster_64bit)
static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -5023,6 +5177,7 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
++spans;
}
}
+#endif
static void blend_tiled_argb(int count, const QSpan *spans, void *userData)
{
@@ -5199,6 +5354,7 @@ static const ProcessSpans processTextureSpansGeneric[NBlendTypes] = {
blend_src_generic // TransformedBilinearTiled
};
+#if QT_CONFIG(raster_64bit)
static const ProcessSpans processTextureSpansGeneric64[NBlendTypes] = {
blend_untransformed_generic_rgb64, // Untransformed
blend_tiled_generic_rgb64, // Tiled
@@ -5207,6 +5363,7 @@ static const ProcessSpans processTextureSpansGeneric64[NBlendTypes] = {
blend_src_generic_rgb64, // TransformedBilinear
blend_src_generic_rgb64 // TransformedBilinearTiled
};
+#endif
void qBlendTexture(int count, const QSpan *spans, void *userData)
{
@@ -5220,6 +5377,7 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
case QImage::Format_RGB16:
proc = processTextureSpansRGB16[blendType];
break;
+#if QT_CONFIG(raster_64bit)
#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
case QImage::Format_ARGB32:
case QImage::Format_RGBA8888:
@@ -5231,8 +5389,10 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
case QImage::Format_RGBX64:
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_Grayscale16:
proc = processTextureSpansGeneric64[blendType];
break;
+#endif // QT_CONFIG(raster_64bit)
case QImage::Format_Invalid:
Q_UNREACHABLE();
return;
@@ -5243,7 +5403,117 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
proc(count, spans, userData);
}
-template <class DST> Q_STATIC_TEMPLATE_FUNCTION
+static void blend_vertical_gradient_argb(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+
+ LinearGradientValues linear;
+ getLinearGradientValues(&linear, data);
+
+ CompositionFunctionSolid funcSolid =
+ functionForModeSolid[data->rasterBuffer->compositionMode];
+
+ /*
+ The logic for vertical gradient calculations is a mathematically
+ reduced copy of that in fetchLinearGradient() - which is basically:
+
+ qreal ry = data->m22 * (y + 0.5) + data->dy;
+ qreal t = linear.dy*ry + linear.off;
+ t *= (GRADIENT_STOPTABLE_SIZE - 1);
+ quint32 color =
+ qt_gradient_pixel_fixed(&data->gradient,
+ int(t * FIXPT_SIZE));
+
+ This has then been converted to fixed point to improve performance.
+ */
+ const int gss = GRADIENT_STOPTABLE_SIZE - 1;
+ int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
+ int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
+
+ while (count--) {
+ int y = spans->y;
+ int x = spans->x;
+
+ quint32 *dst = (quint32 *)(data->rasterBuffer->scanLine(y)) + x;
+ quint32 color =
+ qt_gradient_pixel_fixed(&data->gradient, yinc * y + off);
+
+ funcSolid(dst, spans->len, color, spans->coverage);
+ ++spans;
+ }
+}
+
+template<ProcessSpans blend_color>
+static void blend_vertical_gradient(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+
+ LinearGradientValues linear;
+ getLinearGradientValues(&linear, data);
+
+ // Based on the same logic as blend_vertical_gradient_argb.
+
+ const int gss = GRADIENT_STOPTABLE_SIZE - 1;
+ int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
+ int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
+
+ while (count--) {
+ int y = spans->y;
+
+#if QT_CONFIG(raster_64bit)
+ data->solidColor = qt_gradient_pixel64_fixed(&data->gradient, yinc * y + off);
+#else
+ data->solidColor = QRgba64::fromArgb32(qt_gradient_pixel_fixed(&data->gradient, yinc * y + off));
+#endif
+ blend_color(1, spans, userData);
+ ++spans;
+ }
+}
+
+void qBlendGradient(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+ bool isVerticalGradient =
+ data->txop <= QTransform::TxScale &&
+ data->type == QSpanData::LinearGradient &&
+ data->gradient.linear.end.x == data->gradient.linear.origin.x;
+ switch (data->rasterBuffer->format) {
+ case QImage::Format_RGB16:
+ if (isVerticalGradient)
+ return blend_vertical_gradient<blend_color_rgb16>(count, spans, userData);
+ return blend_src_generic(count, spans, userData);
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ if (isVerticalGradient)
+ return blend_vertical_gradient_argb(count, spans, userData);
+ return blend_src_generic(count, spans, userData);
+#if QT_CONFIG(raster_64bit)
+#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
+ case QImage::Format_ARGB32:
+ case QImage::Format_RGBA8888:
+#endif
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ if (isVerticalGradient)
+ return blend_vertical_gradient<blend_color_generic_rgb64>(count, spans, userData);
+ return blend_src_generic_rgb64(count, spans, userData);
+#endif // QT_CONFIG(raster_64bit)
+ case QImage::Format_Invalid:
+ break;
+ default:
+ if (isVerticalGradient)
+ return blend_vertical_gradient<blend_color_generic>(count, spans, userData);
+ return blend_src_generic(count, spans, userData);
+ }
+ Q_UNREACHABLE();
+}
+
+template <class DST> static
inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer,
int x, int y, DST color,
const uchar *map,
@@ -5305,103 +5575,6 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer,
}
}
-static void qt_gradient_argb32(int count, const QSpan *spans, void *userData)
-{
- QSpanData *data = reinterpret_cast<QSpanData *>(userData);
-
- bool isVerticalGradient =
- data->txop <= QTransform::TxScale &&
- data->type == QSpanData::LinearGradient &&
- data->gradient.linear.end.x == data->gradient.linear.origin.x;
-
- if (isVerticalGradient) {
- LinearGradientValues linear;
- getLinearGradientValues(&linear, data);
-
- CompositionFunctionSolid funcSolid =
- functionForModeSolid[data->rasterBuffer->compositionMode];
-
- /*
- The logic for vertical gradient calculations is a mathematically
- reduced copy of that in fetchLinearGradient() - which is basically:
-
- qreal ry = data->m22 * (y + 0.5) + data->dy;
- qreal t = linear.dy*ry + linear.off;
- t *= (GRADIENT_STOPTABLE_SIZE - 1);
- quint32 color =
- qt_gradient_pixel_fixed(&data->gradient,
- int(t * FIXPT_SIZE));
-
- This has then been converted to fixed point to improve performance.
- */
- const int gss = GRADIENT_STOPTABLE_SIZE - 1;
- int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
- int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
-
- while (count--) {
- int y = spans->y;
- int x = spans->x;
-
- quint32 *dst = (quint32 *)(data->rasterBuffer->scanLine(y)) + x;
- quint32 color =
- qt_gradient_pixel_fixed(&data->gradient, yinc * y + off);
-
- funcSolid(dst, spans->len, color, spans->coverage);
- ++spans;
- }
-
- } else {
- blend_src_generic(count, spans, userData);
- }
-}
-
-static void qt_gradient_quint16(int count, const QSpan *spans, void *userData)
-{
- QSpanData *data = reinterpret_cast<QSpanData *>(userData);
-
- bool isVerticalGradient =
- data->txop <= QTransform::TxScale &&
- data->type == QSpanData::LinearGradient &&
- data->gradient.linear.end.x == data->gradient.linear.origin.x;
-
- if (isVerticalGradient) {
-
- LinearGradientValues linear;
- getLinearGradientValues(&linear, data);
-
- /*
- The logic for vertical gradient calculations is a mathematically
- reduced copy of that in fetchLinearGradient() - which is basically:
-
- qreal ry = data->m22 * (y + 0.5) + data->dy;
- qreal t = linear.dy*ry + linear.off;
- t *= (GRADIENT_STOPTABLE_SIZE - 1);
- quint32 color =
- qt_gradient_pixel_fixed(&data->gradient,
- int(t * FIXPT_SIZE));
-
- This has then been converted to fixed point to improve performance.
- */
- const int gss = GRADIENT_STOPTABLE_SIZE - 1;
- int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
- int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
-
- // Save the fillData since we overwrite it when setting solid.color.
- QGradientData gradient = data->gradient;
- while (count--) {
- int y = spans->y;
-
- data->solid.color = QRgba64::fromArgb32(qt_gradient_pixel_fixed(&gradient, yinc * y + off));
- blend_color_rgb16(1, spans, userData);
- ++spans;
- }
- data->gradient = gradient;
-
- } else {
- blend_src_generic(count, spans, userData);
- }
-}
-
inline static void qt_bitmapblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
@@ -5439,7 +5612,36 @@ inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer,
map, mapWidth, mapHeight, mapStride);
}
-static inline void alphamapblend_generic(int coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorProfile *colorProfile)
+static inline void grayBlendPixel(quint32 *dst, int coverage, QRgba64 srcLinear, const QColorTrcLut *colorProfile)
+{
+ // Do a gammacorrected gray alphablend...
+ const QRgba64 dstLinear = colorProfile ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst);
+
+ QRgba64 blend = interpolate255(srcLinear, coverage, dstLinear, 255 - coverage);
+
+ *dst = colorProfile ? colorProfile->fromLinear64(blend) : toArgb32(blend);
+}
+
+static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcLinear, quint32 src, const QColorTrcLut *colorProfile)
+{
+ if (coverage == 0) {
+ // nothing
+ } else if (coverage == 255) {
+ *dst = src;
+ } else if (!colorProfile) {
+ *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage);
+ } else {
+ if (*dst >= 0xff000000) {
+ grayBlendPixel(dst, coverage, srcLinear, colorProfile);
+ } else {
+ // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571
+ *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage);
+ }
+ }
+}
+
+#if QT_CONFIG(raster_64bit)
+static inline void alphamapblend_generic(int coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile)
{
if (coverage == 0) {
// nothing
@@ -5474,7 +5676,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
if (color.isTransparent())
return;
- const QColorProfile *colorProfile = nullptr;
+ const QColorTrcLut *colorProfile = nullptr;
if (useGammaCorrection)
colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text();
@@ -5540,6 +5742,85 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
} // for (yp -> bottom)
}
}
+#else
+static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
+ int x, int y, const QRgba64 &color,
+ const uchar *map,
+ int mapWidth, int mapHeight, int mapStride,
+ const QClipData *clip, bool useGammaCorrection)
+{
+ if (color.isTransparent())
+ return;
+
+ const quint32 c = color.toArgb32();
+
+ const QColorTrcLut *colorProfile = nullptr;
+
+ if (useGammaCorrection)
+ colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text();
+
+ QRgba64 srcColor = color;
+ if (colorProfile) {
+ if (color.isOpaque())
+ srcColor = colorProfile->toLinear(srcColor);
+ else
+ srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied();
+ }
+
+ quint32 buffer[BufferSize];
+ const DestFetchProc destFetch = destFetchProc[rasterBuffer->format];
+ const DestStoreProc destStore = destStoreProc[rasterBuffer->format];
+
+ if (!clip) {
+ for (int ly = 0; ly < mapHeight; ++ly) {
+ int i = x;
+ int length = mapWidth;
+ while (length > 0) {
+ int l = qMin(BufferSize, length);
+ quint32 *dest = destFetch(buffer, rasterBuffer, i, y + ly, l);
+ for (int j=0; j < l; ++j) {
+ const int coverage = map[j + (i - x)];
+ alphamapblend_argb32(dest + j, coverage, srcColor, c, colorProfile);
+ }
+ if (destStore)
+ destStore(rasterBuffer, i, y + ly, dest, l);
+ length -= l;
+ i += l;
+ }
+ map += mapStride;
+ }
+ } else {
+ int bottom = qMin(y + mapHeight, rasterBuffer->height());
+
+ int top = qMax(y, 0);
+ map += (top - y) * mapStride;
+
+ const_cast<QClipData *>(clip)->initialize();
+ for (int yp = top; yp<bottom; ++yp) {
+ const QClipData::ClipLine &line = clip->m_clipLines[yp];
+
+ for (int i=0; i<line.count; ++i) {
+ const QSpan &clip = line.spans[i];
+
+ int start = qMax<int>(x, clip.x);
+ int end = qMin<int>(x + mapWidth, clip.x + clip.len);
+ if (end <= start)
+ continue;
+ Q_ASSERT(end - start <= BufferSize);
+ quint32 *dest = destFetch(buffer, rasterBuffer, start, clip.y, end - start);
+
+ for (int xp=start; xp<end; ++xp) {
+ const int coverage = map[xp - x];
+ alphamapblend_argb32(dest + xp - x, coverage, srcColor, color, colorProfile);
+ }
+ if (destStore)
+ destStore(rasterBuffer, start, clip.y, dest, end - start);
+ } // for (i -> line.count)
+ map += mapStride;
+ } // for (yp -> bottom)
+ }
+}
+#endif
static inline void alphamapblend_quint16(int coverage, quint16 *dest, int x, const quint16 srcColor)
{
@@ -5600,44 +5881,6 @@ void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
}
}
-static inline void rgbBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorProfile *colorProfile)
-{
- // Do a gammacorrected RGB alphablend...
- const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst);
-
- QRgba64 blend = rgbBlend(dlinear, slinear, coverage);
-
- *dst = colorProfile ? colorProfile->fromLinear64(blend) : toArgb32(blend);
-}
-
-static inline void grayBlendPixel(quint32 *dst, int coverage, QRgba64 srcLinear, const QColorProfile *colorProfile)
-{
- // Do a gammacorrected gray alphablend...
- const QRgba64 dstLinear = colorProfile ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst);
-
- QRgba64 blend = interpolate255(srcLinear, coverage, dstLinear, 255 - coverage);
-
- *dst = colorProfile ? colorProfile->fromLinear64(blend) : toArgb32(blend);
-}
-
-static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcLinear, quint32 src, const QColorProfile *colorProfile)
-{
- if (coverage == 0) {
- // nothing
- } else if (coverage == 255) {
- *dst = src;
- } else if (!colorProfile) {
- *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage);
- } else {
- if (*dst >= 0xff000000) {
- grayBlendPixel(dst, coverage, srcLinear, colorProfile);
- } else {
- // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571
- *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage);
- }
- }
-}
-
static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
@@ -5650,7 +5893,7 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
if (color.isTransparent())
return;
- const QColorProfile *colorProfile = nullptr;
+ const QColorTrcLut *colorProfile = nullptr;
if (useGammaCorrection)
colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text();
@@ -5706,6 +5949,16 @@ static inline int qRgbAvg(QRgb rgb)
return (qRed(rgb) * 5 + qGreen(rgb) * 6 + qBlue(rgb) * 5) / 16;
}
+static inline void rgbBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorTrcLut *colorProfile)
+{
+ // Do a gammacorrected RGB alphablend...
+ const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst);
+
+ QRgba64 blend = rgbBlend(dlinear, slinear, coverage);
+
+ *dst = colorProfile ? colorProfile->fromLinear64(blend) : toArgb32(blend);
+}
+
static inline QRgb rgbBlend(QRgb d, QRgb s, uint rgbAlpha)
{
#if defined(__SSE2__)
@@ -5746,7 +5999,8 @@ static inline QRgb rgbBlend(QRgb d, QRgb s, uint rgbAlpha)
#endif
}
-static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorProfile *colorProfile)
+#if QT_CONFIG(raster_64bit)
+static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile)
{
if (coverage == 0xff000000) {
// nothing
@@ -5767,8 +6021,9 @@ static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, co
}
}
}
+#endif
-static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba64 &srcLinear, quint32 src, const QColorProfile *colorProfile)
+static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba64 &srcLinear, quint32 src, const QColorTrcLut *colorProfile)
{
if (coverage == 0xff000000) {
// nothing
@@ -5785,6 +6040,7 @@ static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba
}
}
+#if QT_CONFIG(raster_64bit)
static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uint *src, int mapWidth, int mapHeight, int srcStride,
@@ -5793,7 +6049,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
if (color.isTransparent())
return;
- const QColorProfile *colorProfile = nullptr;
+ const QColorTrcLut *colorProfile = nullptr;
if (useGammaCorrection)
colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
@@ -5859,6 +6115,84 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
} // for (yp -> bottom)
}
}
+#else
+static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
+ int x, int y, const QRgba64 &color,
+ const uint *src, int mapWidth, int mapHeight, int srcStride,
+ const QClipData *clip, bool useGammaCorrection)
+{
+ if (color.isTransparent())
+ return;
+
+ const quint32 c = color.toArgb32();
+
+ const QColorTrcLut *colorProfile = nullptr;
+
+ if (useGammaCorrection)
+ colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
+
+ QRgba64 srcColor = color;
+ if (colorProfile) {
+ if (color.isOpaque())
+ srcColor = colorProfile->toLinear(srcColor);
+ else
+ srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied();
+ }
+
+ quint32 buffer[BufferSize];
+ const DestFetchProc destFetch = destFetchProc[rasterBuffer->format];
+ const DestStoreProc destStore = destStoreProc[rasterBuffer->format];
+
+ if (!clip) {
+ for (int ly = 0; ly < mapHeight; ++ly) {
+ int i = x;
+ int length = mapWidth;
+ while (length > 0) {
+ int l = qMin(BufferSize, length);
+ quint32 *dest = destFetch(buffer, rasterBuffer, i, y + ly, l);
+ for (int j=0; j < l; ++j) {
+ const uint coverage = src[j + (i - x)];
+ alphargbblend_argb32(dest + j, coverage, srcColor, c, colorProfile);
+ }
+ if (destStore)
+ destStore(rasterBuffer, i, y + ly, dest, l);
+ length -= l;
+ i += l;
+ }
+ src += srcStride;
+ }
+ } else {
+ int bottom = qMin(y + mapHeight, rasterBuffer->height());
+
+ int top = qMax(y, 0);
+ src += (top - y) * srcStride;
+
+ const_cast<QClipData *>(clip)->initialize();
+ for (int yp = top; yp<bottom; ++yp) {
+ const QClipData::ClipLine &line = clip->m_clipLines[yp];
+
+ for (int i=0; i<line.count; ++i) {
+ const QSpan &clip = line.spans[i];
+
+ int start = qMax<int>(x, clip.x);
+ int end = qMin<int>(x + mapWidth, clip.x + clip.len);
+ if (end <= start)
+ continue;
+ Q_ASSERT(end - start <= BufferSize);
+ quint32 *dest = destFetch(buffer, rasterBuffer, start, clip.y, end - start);
+
+ for (int xp=start; xp<end; ++xp) {
+ const uint coverage = src[xp - x];
+ alphargbblend_argb32(dest + xp - start, coverage, srcColor, c, colorProfile);
+ }
+ if (destStore)
+ destStore(rasterBuffer, start, clip.y, dest, end - start);
+ } // for (i -> line.count)
+ src += srcStride;
+ } // for (yp -> bottom)
+ }
+}
+#endif
static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
@@ -5870,7 +6204,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
const quint32 c = color.toArgb32();
- const QColorProfile *colorProfile = nullptr;
+ const QColorTrcLut *colorProfile = nullptr;
if (useGammaCorrection)
colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
@@ -6022,29 +6356,25 @@ static void qt_rectfill_quint64(QRasterBuffer *rasterBuffer,
DrawHelper qDrawHelper[QImage::NImageFormats] =
{
// Format_Invalid,
- { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
// Format_Mono,
{
blend_color_generic,
- blend_src_generic,
0, 0, 0, 0
},
// Format_MonoLSB,
{
blend_color_generic,
- blend_src_generic,
0, 0, 0, 0
},
// Format_Indexed8,
{
blend_color_generic,
- blend_src_generic,
0, 0, 0, 0
},
// Format_RGB32,
{
blend_color_argb,
- qt_gradient_argb32,
qt_bitmapblit_argb32,
qt_alphamapblit_argb32,
qt_alphargbblit_argb32,
@@ -6053,7 +6383,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB32,
{
blend_color_generic,
- blend_src_generic,
qt_bitmapblit_argb32,
qt_alphamapblit_argb32,
qt_alphargbblit_argb32,
@@ -6062,7 +6391,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB32_Premultiplied
{
blend_color_argb,
- qt_gradient_argb32,
qt_bitmapblit_argb32,
qt_alphamapblit_argb32,
qt_alphargbblit_argb32,
@@ -6071,7 +6399,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB16
{
blend_color_rgb16,
- qt_gradient_quint16,
qt_bitmapblit_quint16,
qt_alphamapblit_quint16,
qt_alphargbblit_generic,
@@ -6080,7 +6407,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB8565_Premultiplied
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6089,7 +6415,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB666
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6098,7 +6423,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB6666_Premultiplied
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6107,7 +6431,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB555
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6116,7 +6439,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB8555_Premultiplied
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6125,7 +6447,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB888
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6134,7 +6455,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB444
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6143,7 +6463,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_ARGB4444_Premultiplied
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6152,7 +6471,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGBX8888
{
blend_color_generic,
- blend_src_generic,
qt_bitmapblit_rgba8888,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6161,7 +6479,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGBA8888
{
blend_color_generic,
- blend_src_generic,
qt_bitmapblit_rgba8888,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6170,7 +6487,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB8888_Premultiplied
{
blend_color_generic,
- blend_src_generic,
qt_bitmapblit_rgba8888,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6179,7 +6495,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_BGR30
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderBGR>,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6188,7 +6503,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_A2BGR30_Premultiplied
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderBGR>,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6197,7 +6511,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGB30
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderRGB>,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6206,7 +6519,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_A2RGB30_Premultiplied
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
qt_bitmapblit_rgb30<PixelOrderRGB>,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6215,7 +6527,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_Alpha8
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6224,7 +6535,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_Grayscale8
{
blend_color_generic,
- blend_src_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6233,7 +6543,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGBX64
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6242,7 +6551,6 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGBA64
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
@@ -6251,82 +6559,98 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
// Format_RGBA64_Premultiplied
{
blend_color_generic_rgb64,
- blend_src_generic_rgb64,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
qt_rectfill_quint64
},
+ // Format_Grayscale16
+ {
+ blend_color_generic_rgb64,
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_quint16
+ },
};
-#if defined(Q_CC_MSVC) && !defined(_MIPS_)
-template <class T>
-inline void qt_memfill_template(T *dest, T color, int count)
+#if !defined(__SSE2__)
+void qt_memfill64(quint64 *dest, quint64 color, qsizetype count)
{
- while (count--)
- *dest++ = color;
+ qt_memfill_template<quint64>(dest, color, count);
}
+#endif
-#else
-
-template <class T>
-inline void qt_memfill_template(T *dest, T color, int count)
+#if defined(QT_COMPILER_SUPPORTS_SSSE3) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
+__attribute__((optimize("no-tree-vectorize")))
+#endif
+void qt_memfill24(quint24 *dest, quint24 color, qsizetype count)
{
- int n = (count + 7) / 8;
- switch (count & 0x07)
- {
- case 0: do { *dest++ = color; Q_FALLTHROUGH();
- case 7: *dest++ = color; Q_FALLTHROUGH();
- case 6: *dest++ = color; Q_FALLTHROUGH();
- case 5: *dest++ = color; Q_FALLTHROUGH();
- case 4: *dest++ = color; Q_FALLTHROUGH();
- case 3: *dest++ = color; Q_FALLTHROUGH();
- case 2: *dest++ = color; Q_FALLTHROUGH();
- case 1: *dest++ = color;
- } while (--n > 0);
- }
-}
+# ifdef QT_COMPILER_SUPPORTS_SSSE3
+ extern void qt_memfill24_ssse3(quint24 *, quint24, qsizetype);
+ if (qCpuHasFeature(SSSE3))
+ return qt_memfill24_ssse3(dest, color, count);
+# endif
-template <>
-inline void qt_memfill_template(quint16 *dest, quint16 value, int count)
-{
- if (count < 3) {
- switch (count) {
- case 2: *dest++ = value; Q_FALLTHROUGH();
- case 1: *dest = value;
- }
+ const quint32 v = color;
+ quint24 *end = dest + count;
+
+ // prolog: align dest to 32bit
+ while ((quintptr(dest) & 0x3) && dest < end) {
+ *dest++ = v;
+ }
+ if (dest >= end)
return;
+
+ const uint val1 = qFromBigEndian((v << 8) | (v >> 16));
+ const uint val2 = qFromBigEndian((v << 16) | (v >> 8));
+ const uint val3 = qFromBigEndian((v << 24) | (v >> 0));
+
+ for ( ; dest <= (end - 4); dest += 4) {
+ quint32 *dst = reinterpret_cast<quint32 *>(dest);
+ dst[0] = val1;
+ dst[1] = val2;
+ dst[2] = val3;
}
- const int align = (quintptr)(dest) & 0x3;
- switch (align) {
- case 2: *dest++ = value; --count;
+ // less than 4px left
+ switch (end - dest) {
+ case 3:
+ *dest++ = v;
+ Q_FALLTHROUGH();
+ case 2:
+ *dest++ = v;
+ Q_FALLTHROUGH();
+ case 1:
+ *dest++ = v;
+ }
+}
+
+void qt_memfill16(quint16 *dest, quint16 value, qsizetype count)
+{
+ const int align = quintptr(dest) & 0x3;
+ if (align) {
+ *dest++ = value;
+ --count;
}
- const quint32 value32 = (value << 16) | value;
- qt_memfill(reinterpret_cast<quint32*>(dest), value32, count / 2);
if (count & 0x1)
dest[count - 1] = value;
-}
-#endif
-void qt_memfill64(quint64 *dest, quint64 color, int count)
-{
- qt_memfill_template<quint64>(dest, color, count);
+ const quint32 value32 = (value << 16) | value;
+ qt_memfill32(reinterpret_cast<quint32*>(dest), value32, count / 2);
}
-#if !defined(__SSE2__)
-void qt_memfill16(quint16 *dest, quint16 color, int count)
-{
- qt_memfill_template<quint16>(dest, color, count);
-}
-#endif
#if !defined(__SSE2__) && !defined(__ARM_NEON__) && !defined(__MIPS_DSP__)
-void qt_memfill32(quint32 *dest, quint32 color, int count)
+void qt_memfill32(quint32 *dest, quint32 color, qsizetype count)
{
qt_memfill_template<quint32>(dest, color, count);
}
#endif
+#ifdef __SSE2__
+decltype(qt_memfill32_sse2) *qt_memfill32 = nullptr;
+decltype(qt_memfill64_sse2) *qt_memfill64 = nullptr;
+#endif
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
template<QtPixelOrder> void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count, const QVector<QRgb> *, QDitherInfo *);
@@ -6340,6 +6664,10 @@ static void qInitDrawhelperFunctions()
qInitBlendFunctions();
#ifdef __SSE2__
+# ifndef __AVX2__
+ qt_memfill32 = qt_memfill32_sse2;
+ qt_memfill64 = qt_memfill64_sse2;
+# endif
qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2;
qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2;
qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2;
@@ -6416,6 +6744,14 @@ static void qInitDrawhelperFunctions()
const QVector<QRgb> *, QDitherInfo *);
extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_sse4(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_sse4(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_sse4(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_sse4(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_sse4(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL storeARGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL storeRGBA8888FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
@@ -6428,10 +6764,18 @@ static void qInitDrawhelperFunctions()
const QVector<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL destStore64ARGB32_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
extern void QT_FASTCALL destStore64RGBA8888_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
+# ifndef __AVX2__
qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_sse4;
+ qPixelLayouts[QImage::Format_ARGB32].fetchToRGBA64PM = fetchARGB32ToRGBA64PM_sse4;
+ qPixelLayouts[QImage::Format_ARGB32].convertToRGBA64PM = convertARGB32ToRGBA64PM_sse4;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_sse4;
+ qPixelLayouts[QImage::Format_RGBA8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_sse4;
+ qPixelLayouts[QImage::Format_RGBX8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_sse4;
+ qPixelLayouts[QImage::Format_RGBX8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_sse4;
+# endif
qPixelLayouts[QImage::Format_ARGB32].storeFromARGB32PM = storeARGB32FromARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBA8888].storeFromARGB32PM = storeRGBA8888FromARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBX8888].storeFromARGB32PM = storeRGBXFromARGB32PM_sse4;
@@ -6439,13 +6783,17 @@ static void qInitDrawhelperFunctions()
qPixelLayouts[QImage::Format_A2RGB30_Premultiplied].storeFromARGB32PM = storeA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>;
qStoreFromRGBA64PM[QImage::Format_ARGB32] = storeARGB32FromRGBA64PM_sse4;
qStoreFromRGBA64PM[QImage::Format_RGBA8888] = storeRGBA8888FromRGBA64PM_sse4;
+#if QT_CONFIG(raster_64bit)
destStoreProc64[QImage::Format_ARGB32] = destStore64ARGB32_sse4;
destStoreProc64[QImage::Format_RGBA8888] = destStore64RGBA8888_sse4;
+#endif
}
#endif
#if defined(QT_COMPILER_SUPPORTS_AVX2)
if (qCpuHasFeature(ArchHaswell)) {
+ qt_memfill32 = qt_memfill32_avx2;
+ qt_memfill64 = qt_memfill64_avx2;
extern void qt_blend_rgb32_on_rgb32_avx2(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h, int const_alpha);
@@ -6462,18 +6810,19 @@ static void qInitDrawhelperFunctions()
qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_avx2;
extern void QT_FASTCALL comp_func_Source_avx2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
- extern void QT_FASTCALL comp_func_Source_rgb64_avx2(QRgba64 *destPixels, const QRgba64 *srcPixels, int length, uint const_alpha);
extern void QT_FASTCALL comp_func_SourceOver_avx2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
- extern void QT_FASTCALL comp_func_SourceOver_rgb64_avx2(QRgba64 *destPixels, const QRgba64 *srcPixels, int length, uint const_alpha);
extern void QT_FASTCALL comp_func_solid_SourceOver_avx2(uint *destPixels, int length, uint color, uint const_alpha);
- extern void QT_FASTCALL comp_func_solid_SourceOver_rgb64_avx2(QRgba64 *destPixels, int length, QRgba64 color, uint const_alpha);
-
qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_avx2;
- qt_functionForMode64_C[QPainter::CompositionMode_Source] = comp_func_Source_rgb64_avx2;
qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_avx2;
- qt_functionForMode64_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_rgb64_avx2;
qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_avx2;
+#if QT_CONFIG(raster_64bit)
+ extern void QT_FASTCALL comp_func_Source_rgb64_avx2(QRgba64 *destPixels, const QRgba64 *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_SourceOver_rgb64_avx2(QRgba64 *destPixels, const QRgba64 *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_solid_SourceOver_rgb64_avx2(QRgba64 *destPixels, int length, QRgba64 color, uint const_alpha);
+ qt_functionForMode64_C[QPainter::CompositionMode_Source] = comp_func_Source_rgb64_avx2;
+ qt_functionForMode64_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_rgb64_avx2;
qt_functionForModeSolid64_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_rgb64_avx2;
+#endif
extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_scale_helper_avx2(uint *b, uint *end, const QTextureData &image,
int &fx, int &fy, int fdx, int /*fdy*/);
@@ -6485,6 +6834,28 @@ static void qInitDrawhelperFunctions()
bilinearFastTransformHelperARGB32PM[0][SimpleScaleTransform] = fetchTransformedBilinearARGB32PM_simple_scale_helper_avx2;
bilinearFastTransformHelperARGB32PM[0][DownscaleTransform] = fetchTransformedBilinearARGB32PM_downscale_helper_avx2;
bilinearFastTransformHelperARGB32PM[0][FastRotateTransform] = fetchTransformedBilinearARGB32PM_fast_rotate_helper_avx2;
+
+ extern void QT_FASTCALL convertARGB32ToARGB32PM_avx2(uint *buffer, int count, const QVector<QRgb> *);
+ extern void QT_FASTCALL convertRGBA8888ToARGB32PM_avx2(uint *buffer, int count, const QVector<QRgb> *);
+ extern const uint *QT_FASTCALL fetchARGB32ToARGB32PM_avx2(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_avx2(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_avx2;
+ qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_avx2;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_avx2;
+ qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_avx2;
+
+#if QT_CONFIG(raster_64bit)
+ extern const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_avx2(QRgba64 *, const uint *, int, const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_avx2(QRgba64 *, const uint *, int count, const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_avx2(QRgba64 *, const uchar *, int, int, const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_avx2(QRgba64 *, const uchar *, int, int, const QVector<QRgb> *, QDitherInfo *);
+ qPixelLayouts[QImage::Format_ARGB32].convertToRGBA64PM = convertARGB32ToRGBA64PM_avx2;
+ qPixelLayouts[QImage::Format_RGBX8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_avx2;
+ qPixelLayouts[QImage::Format_ARGB32].fetchToRGBA64PM = fetchARGB32ToRGBA64PM_avx2;
+ qPixelLayouts[QImage::Format_RGBX8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_avx2;
+#endif
}
#endif
@@ -6520,6 +6891,14 @@ static void qInitDrawhelperFunctions()
const QVector<QRgb> *, QDitherInfo *);
extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_neon(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_neon(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_neon(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_neon(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_neon(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL storeARGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL storeRGBA8888FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
@@ -6529,10 +6908,16 @@ static void qInitDrawhelperFunctions()
qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_neon;
qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_neon;
qPixelLayouts[QImage::Format_ARGB32].storeFromARGB32PM = storeARGB32FromARGB32PM_neon;
+ qPixelLayouts[QImage::Format_ARGB32].fetchToRGBA64PM = fetchARGB32ToRGBA64PM_neon;
+ qPixelLayouts[QImage::Format_ARGB32].convertToRGBA64PM = convertARGB32ToRGBA64PM_neon;
qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_neon;
qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_neon;
qPixelLayouts[QImage::Format_RGBA8888].storeFromARGB32PM = storeRGBA8888FromARGB32PM_neon;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_neon;
+ qPixelLayouts[QImage::Format_RGBA8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_neon;
qPixelLayouts[QImage::Format_RGBX8888].storeFromARGB32PM = storeRGBXFromARGB32PM_neon;
+ qPixelLayouts[QImage::Format_RGBX8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_neon;
+ qPixelLayouts[QImage::Format_RGBX8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_neon;
#endif
#if defined(ENABLE_PIXMAN_DRAWHELPERS)
diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp
index ec6643deed..fb50cb6a50 100644
--- a/src/gui/painting/qdrawhelper_avx2.cpp
+++ b/src/gui/painting/qdrawhelper_avx2.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -38,6 +39,7 @@
****************************************************************************/
#include "qdrawhelper_p.h"
+#include "qdrawhelper_x86_p.h"
#include "qdrawingprimitive_sse2_p.h"
#include "qrgba64_p.h"
@@ -53,7 +55,8 @@ enum {
// Vectorized blend functions:
// See BYTE_MUL_SSE2 for details.
-inline static void BYTE_MUL_AVX2(__m256i &pixelVector, const __m256i &alphaChannel, const __m256i &colorMask, const __m256i &half)
+inline static void Q_DECL_VECTORCALL
+BYTE_MUL_AVX2(__m256i &pixelVector, __m256i alphaChannel, __m256i colorMask, __m256i half)
{
__m256i pixelVectorAG = _mm256_srli_epi16(pixelVector, 8);
__m256i pixelVectorRB = _mm256_and_si256(pixelVector, colorMask);
@@ -72,7 +75,8 @@ inline static void BYTE_MUL_AVX2(__m256i &pixelVector, const __m256i &alphaChann
pixelVector = _mm256_or_si256(pixelVectorAG, pixelVectorRB);
}
-inline static void BYTE_MUL_RGB64_AVX2(__m256i &pixelVector, const __m256i &alphaChannel, const __m256i &colorMask, const __m256i &half)
+inline static void Q_DECL_VECTORCALL
+BYTE_MUL_RGB64_AVX2(__m256i &pixelVector, __m256i alphaChannel, __m256i colorMask, __m256i half)
{
__m256i pixelVectorAG = _mm256_srli_epi32(pixelVector, 16);
__m256i pixelVectorRB = _mm256_and_si256(pixelVector, colorMask);
@@ -92,7 +96,8 @@ inline static void BYTE_MUL_RGB64_AVX2(__m256i &pixelVector, const __m256i &alph
}
// See INTERPOLATE_PIXEL_255_SSE2 for details.
-inline static void INTERPOLATE_PIXEL_255_AVX2(const __m256i &srcVector, __m256i &dstVector, const __m256i &alphaChannel, const __m256i &oneMinusAlphaChannel, const __m256i &colorMask, const __m256i &half)
+inline static void Q_DECL_VECTORCALL
+INTERPOLATE_PIXEL_255_AVX2(__m256i srcVector, __m256i &dstVector, __m256i alphaChannel, __m256i oneMinusAlphaChannel, __m256i colorMask, __m256i half)
{
const __m256i srcVectorAG = _mm256_srli_epi16(srcVector, 8);
const __m256i dstVectorAG = _mm256_srli_epi16(dstVector, 8);
@@ -114,7 +119,8 @@ inline static void INTERPOLATE_PIXEL_255_AVX2(const __m256i &srcVector, __m256i
dstVector = _mm256_or_si256(finalAG, finalRB);
}
-inline static void INTERPOLATE_PIXEL_RGB64_AVX2(const __m256i &srcVector, __m256i &dstVector, const __m256i &alphaChannel, const __m256i &oneMinusAlphaChannel, const __m256i &colorMask, const __m256i &half)
+inline static void Q_DECL_VECTORCALL
+INTERPOLATE_PIXEL_RGB64_AVX2(__m256i srcVector, __m256i &dstVector, __m256i alphaChannel, __m256i oneMinusAlphaChannel, __m256i colorMask, __m256i half)
{
const __m256i srcVectorAG = _mm256_srli_epi32(srcVector, 16);
const __m256i dstVectorAG = _mm256_srli_epi32(dstVector, 16);
@@ -138,7 +144,7 @@ inline static void INTERPOLATE_PIXEL_RGB64_AVX2(const __m256i &srcVector, __m256
// See BLEND_SOURCE_OVER_ARGB32_SSE2 for details.
-inline static void BLEND_SOURCE_OVER_ARGB32_AVX2(quint32 *dst, const quint32 *src, const int length)
+inline static void Q_DECL_VECTORCALL BLEND_SOURCE_OVER_ARGB32_AVX2(quint32 *dst, const quint32 *src, const int length)
{
const __m256i half = _mm256_set1_epi16(0x80);
const __m256i one = _mm256_set1_epi16(0xff);
@@ -209,7 +215,8 @@ inline static void BLEND_SOURCE_OVER_ARGB32_AVX2(quint32 *dst, const quint32 *sr
// See BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2 for details.
-inline static void BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_AVX2(quint32 *dst, const quint32 *src, const int length, const int const_alpha)
+inline static void Q_DECL_VECTORCALL
+BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_AVX2(quint32 *dst, const quint32 *src, const int length, const int const_alpha)
{
int x = 0;
@@ -316,6 +323,66 @@ void qt_blend_rgb32_on_rgb32_avx2(uchar *destPixels, int dbpl,
}
}
+static Q_NEVER_INLINE
+void Q_DECL_VECTORCALL qt_memfillXX_avx2(uchar *dest, __m256i value256, qsizetype bytes)
+{
+ __m128i value128 = _mm256_castsi256_si128(value256);
+
+ // main body
+ __m256i *dst256 = reinterpret_cast<__m256i *>(dest);
+ uchar *end = dest + bytes;
+ while (reinterpret_cast<uchar *>(dst256 + 4) <= end) {
+ _mm256_storeu_si256(dst256 + 0, value256);
+ _mm256_storeu_si256(dst256 + 1, value256);
+ _mm256_storeu_si256(dst256 + 2, value256);
+ _mm256_storeu_si256(dst256 + 3, value256);
+ dst256 += 4;
+ }
+
+ // first epilogue: fewer than 128 bytes / 32 entries
+ bytes = end - reinterpret_cast<uchar *>(dst256);
+ switch (bytes / sizeof(value256)) {
+ case 3: _mm256_storeu_si256(dst256++, value256); Q_FALLTHROUGH();
+ case 2: _mm256_storeu_si256(dst256++, value256); Q_FALLTHROUGH();
+ case 1: _mm256_storeu_si256(dst256++, value256);
+ }
+
+ // second epilogue: fewer than 32 bytes
+ __m128i *dst128 = reinterpret_cast<__m128i *>(dst256);
+ if (bytes & sizeof(value128))
+ _mm_storeu_si128(dst128++, value128);
+
+ // third epilogue: fewer than 16 bytes
+ if (bytes & 8)
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(end - 8), value128);
+}
+
+void qt_memfill64_avx2(quint64 *dest, quint64 value, qsizetype count)
+{
+#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
+ // work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80820
+ __m128i value64 = _mm_set_epi64x(0, value); // _mm_cvtsi64_si128(value);
+# ifdef Q_PROCESSOR_X86_64
+ asm ("" : "+x" (value64));
+# endif
+ __m256i value256 = _mm256_broadcastq_epi64(value64);
+#else
+ __m256i value256 = _mm256_set1_epi64x(value);
+#endif
+
+ qt_memfillXX_avx2(reinterpret_cast<uchar *>(dest), value256, count * sizeof(quint64));
+}
+
+void qt_memfill32_avx2(quint32 *dest, quint32 value, qsizetype count)
+{
+ if (count % 2) {
+ // odd number of pixels, round to even
+ *dest++ = value;
+ --count;
+ }
+ qt_memfillXX_avx2(reinterpret_cast<uchar *>(dest), _mm256_set1_epi32(value), count * sizeof(quint32));
+}
+
void QT_FASTCALL comp_func_SourceOver_avx2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha)
{
Q_ASSERT(const_alpha < 256);
@@ -329,6 +396,7 @@ void QT_FASTCALL comp_func_SourceOver_avx2(uint *destPixels, const uint *srcPixe
BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_AVX2(dst, src, length, const_alpha);
}
+#if QT_CONFIG(raster_64bit)
void QT_FASTCALL comp_func_SourceOver_rgb64_avx2(QRgba64 *dst, const QRgba64 *src, int length, uint const_alpha)
{
Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
@@ -386,6 +454,7 @@ void QT_FASTCALL comp_func_SourceOver_rgb64_avx2(QRgba64 *dst, const QRgba64 *sr
blend_pixel(dst[x], src[x], const_alpha);
}
}
+#endif
void QT_FASTCALL comp_func_Source_avx2(uint *dst, const uint *src, int length, uint const_alpha)
{
@@ -418,6 +487,7 @@ void QT_FASTCALL comp_func_Source_avx2(uint *dst, const uint *src, int length, u
}
}
+#if QT_CONFIG(raster_64bit)
void QT_FASTCALL comp_func_Source_rgb64_avx2(QRgba64 *dst, const QRgba64 *src, int length, uint const_alpha)
{
Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
@@ -450,6 +520,7 @@ void QT_FASTCALL comp_func_Source_rgb64_avx2(QRgba64 *dst, const QRgba64 *src, i
dst[x] = interpolate65535(src[x], ca, dst[x], cia);
}
}
+#endif
void QT_FASTCALL comp_func_solid_SourceOver_avx2(uint *destPixels, int length, uint color, uint const_alpha)
{
@@ -482,6 +553,7 @@ void QT_FASTCALL comp_func_solid_SourceOver_avx2(uint *destPixels, int length, u
}
}
+#if QT_CONFIG(raster_64bit)
void QT_FASTCALL comp_func_solid_SourceOver_rgb64_avx2(QRgba64 *destPixels, int length, QRgba64 color, uint const_alpha)
{
Q_ASSERT(const_alpha < 256); // const_alpha is in [0-255]
@@ -512,6 +584,7 @@ void QT_FASTCALL comp_func_solid_SourceOver_rgb64_avx2(QRgba64 *destPixels, int
destPixels[x] = color + multiplyAlpha65535(destPixels[x], minusAlphaOfColor);
}
}
+#endif
#define interpolate_4_pixels_16_avx2(tlr1, tlr2, blr1, blr2, distx, disty, colorMask, v_256, b) \
{ \
@@ -928,6 +1001,233 @@ void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper_avx2(uint *
}
}
+static inline __m256i epilogueMaskFromCount(qsizetype count)
+{
+ Q_ASSERT(count > 0);
+ static const __m256i offsetMask = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7);
+ return _mm256_add_epi32(offsetMask, _mm256_set1_epi32(-count));
+}
+
+template<bool RGBA>
+static void convertARGBToARGB32PM_avx2(uint *buffer, const uint *src, qsizetype count)
+{
+ qsizetype i = 0;
+ const __m256i alphaMask = _mm256_set1_epi32(0xff000000);
+ const __m256i rgbaMask = _mm256_broadcastsi128_si256(_mm_setr_epi8(2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15));
+ const __m256i shuffleMask = _mm256_broadcastsi128_si256(_mm_setr_epi8(6, 7, 6, 7, 6, 7, 6, 7, 14, 15, 14, 15, 14, 15, 14, 15));
+ const __m256i half = _mm256_set1_epi16(0x0080);
+ const __m256i zero = _mm256_setzero_si256();
+
+ for (; i < count - 7; i += 8) {
+ __m256i srcVector = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + i));
+ if (!_mm256_testz_si256(srcVector, alphaMask)) {
+ // keep the two _mm_test[zc]_siXXX next to each other
+ bool cf = _mm256_testc_si256(srcVector, alphaMask);
+ if (RGBA)
+ srcVector = _mm256_shuffle_epi8(srcVector, rgbaMask);
+ if (!cf) {
+ __m256i src1 = _mm256_unpacklo_epi8(srcVector, zero);
+ __m256i src2 = _mm256_unpackhi_epi8(srcVector, zero);
+ __m256i alpha1 = _mm256_shuffle_epi8(src1, shuffleMask);
+ __m256i alpha2 = _mm256_shuffle_epi8(src2, shuffleMask);
+ src1 = _mm256_mullo_epi16(src1, alpha1);
+ src2 = _mm256_mullo_epi16(src2, alpha2);
+ src1 = _mm256_add_epi16(src1, _mm256_srli_epi16(src1, 8));
+ src2 = _mm256_add_epi16(src2, _mm256_srli_epi16(src2, 8));
+ src1 = _mm256_add_epi16(src1, half);
+ src2 = _mm256_add_epi16(src2, half);
+ src1 = _mm256_srli_epi16(src1, 8);
+ src2 = _mm256_srli_epi16(src2, 8);
+ src1 = _mm256_blend_epi16(src1, alpha1, 0x88);
+ src2 = _mm256_blend_epi16(src2, alpha2, 0x88);
+ srcVector = _mm256_packus_epi16(src1, src2);
+ _mm256_storeu_si256(reinterpret_cast<__m256i *>(buffer + i), srcVector);
+ } else {
+ if (buffer != src || RGBA)
+ _mm256_storeu_si256(reinterpret_cast<__m256i *>(buffer + i), srcVector);
+ }
+ } else {
+ _mm256_storeu_si256(reinterpret_cast<__m256i *>(buffer + i), zero);
+ }
+ }
+
+ if (i < count) {
+ const __m256i epilogueMask = epilogueMaskFromCount(count - i);
+ __m256i srcVector = _mm256_maskload_epi32(reinterpret_cast<const int *>(src + i), epilogueMask);
+ const __m256i epilogueAlphaMask = _mm256_blendv_epi8(_mm256_setzero_si256(), alphaMask, epilogueMask);
+
+ if (!_mm256_testz_si256(srcVector, epilogueAlphaMask)) {
+ // keep the two _mm_test[zc]_siXXX next to each other
+ bool cf = _mm256_testc_si256(srcVector, epilogueAlphaMask);
+ if (RGBA)
+ srcVector = _mm256_shuffle_epi8(srcVector, rgbaMask);
+ if (!cf) {
+ __m256i src1 = _mm256_unpacklo_epi8(srcVector, zero);
+ __m256i src2 = _mm256_unpackhi_epi8(srcVector, zero);
+ __m256i alpha1 = _mm256_shuffle_epi8(src1, shuffleMask);
+ __m256i alpha2 = _mm256_shuffle_epi8(src2, shuffleMask);
+ src1 = _mm256_mullo_epi16(src1, alpha1);
+ src2 = _mm256_mullo_epi16(src2, alpha2);
+ src1 = _mm256_add_epi16(src1, _mm256_srli_epi16(src1, 8));
+ src2 = _mm256_add_epi16(src2, _mm256_srli_epi16(src2, 8));
+ src1 = _mm256_add_epi16(src1, half);
+ src2 = _mm256_add_epi16(src2, half);
+ src1 = _mm256_srli_epi16(src1, 8);
+ src2 = _mm256_srli_epi16(src2, 8);
+ src1 = _mm256_blend_epi16(src1, alpha1, 0x88);
+ src2 = _mm256_blend_epi16(src2, alpha2, 0x88);
+ srcVector = _mm256_packus_epi16(src1, src2);
+ _mm256_maskstore_epi32(reinterpret_cast<int *>(buffer + i), epilogueMask, srcVector);
+ } else {
+ if (buffer != src || RGBA)
+ _mm256_maskstore_epi32(reinterpret_cast<int *>(buffer + i), epilogueMask, srcVector);
+ }
+ } else {
+ _mm256_maskstore_epi32(reinterpret_cast<int *>(buffer + i), epilogueMask, zero);
+ }
+ }
+}
+
+void QT_FASTCALL convertARGB32ToARGB32PM_avx2(uint *buffer, int count, const QVector<QRgb> *)
+{
+ convertARGBToARGB32PM_avx2<false>(buffer, buffer, count);
+}
+
+void QT_FASTCALL convertRGBA8888ToARGB32PM_avx2(uint *buffer, int count, const QVector<QRgb> *)
+{
+ convertARGBToARGB32PM_avx2<true>(buffer, buffer, count);
+}
+
+const uint *QT_FASTCALL fetchARGB32ToARGB32PM_avx2(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToARGB32PM_avx2<false>(buffer, reinterpret_cast<const uint *>(src) + index, count);
+ return buffer;
+}
+
+const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_avx2(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToARGB32PM_avx2<true>(buffer, reinterpret_cast<const uint *>(src) + index, count);
+ return buffer;
+}
+
+template<bool RGBA>
+static void convertARGBToRGBA64PM_avx2(QRgba64 *buffer, const uint *src, qsizetype count)
+{
+ qsizetype i = 0;
+ const __m256i alphaMask = _mm256_set1_epi32(0xff000000);
+ const __m256i rgbaMask = _mm256_broadcastsi128_si256(_mm_setr_epi8(2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15));
+ const __m256i shuffleMask = _mm256_broadcastsi128_si256(_mm_setr_epi8(6, 7, 6, 7, 6, 7, 6, 7, 14, 15, 14, 15, 14, 15, 14, 15));
+ const __m256i zero = _mm256_setzero_si256();
+
+ for (; i < count - 7; i += 8) {
+ __m256i dst1, dst2;
+ __m256i srcVector = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + i));
+ if (!_mm256_testz_si256(srcVector, alphaMask)) {
+ // keep the two _mm_test[zc]_siXXX next to each other
+ bool cf = _mm256_testc_si256(srcVector, alphaMask);
+ if (!RGBA)
+ srcVector = _mm256_shuffle_epi8(srcVector, rgbaMask);
+
+ // The two unpack instructions unpack the low and upper halves of
+ // each 128-bit half of the 256-bit register. Here's the tracking
+ // of what's where: (p is 32-bit, P is 64-bit)
+ // as loaded: [ p1, p2, p3, p4; p5, p6, p7, p8 ]
+ // after permute4x64 [ p1, p2, p5, p6; p3, p4, p7, p8 ]
+ // after unpacklo/hi [ P1, P2; P3, P4 ] [ P5, P6; P7, P8 ]
+ srcVector = _mm256_permute4x64_epi64(srcVector, _MM_SHUFFLE(3, 1, 2, 0));
+
+ const __m256i src1 = _mm256_unpacklo_epi8(srcVector, srcVector);
+ const __m256i src2 = _mm256_unpackhi_epi8(srcVector, srcVector);
+ if (!cf) {
+ const __m256i alpha1 = _mm256_shuffle_epi8(src1, shuffleMask);
+ const __m256i alpha2 = _mm256_shuffle_epi8(src2, shuffleMask);
+ dst1 = _mm256_mulhi_epu16(src1, alpha1);
+ dst2 = _mm256_mulhi_epu16(src2, alpha2);
+ dst1 = _mm256_add_epi16(dst1, _mm256_srli_epi16(dst1, 15));
+ dst2 = _mm256_add_epi16(dst2, _mm256_srli_epi16(dst2, 15));
+ dst1 = _mm256_blend_epi16(dst1, src1, 0x88);
+ dst2 = _mm256_blend_epi16(dst2, src2, 0x88);
+ } else {
+ dst1 = src1;
+ dst2 = src2;
+ }
+ } else {
+ dst1 = dst2 = zero;
+ }
+ _mm256_storeu_si256(reinterpret_cast<__m256i *>(buffer + i), dst1);
+ _mm256_storeu_si256(reinterpret_cast<__m256i *>(buffer + i) + 1, dst2);
+ }
+
+ if (i < count) {
+ __m256i epilogueMask = epilogueMaskFromCount(count - i);
+ const __m256i epilogueAlphaMask = _mm256_blendv_epi8(_mm256_setzero_si256(), alphaMask, epilogueMask);
+ __m256i dst1, dst2;
+ __m256i srcVector = _mm256_maskload_epi32(reinterpret_cast<const int *>(src + i), epilogueMask);
+
+ if (!_mm256_testz_si256(srcVector, epilogueAlphaMask)) {
+ // keep the two _mm_test[zc]_siXXX next to each other
+ bool cf = _mm256_testc_si256(srcVector, epilogueAlphaMask);
+ if (!RGBA)
+ srcVector = _mm256_shuffle_epi8(srcVector, rgbaMask);
+ srcVector = _mm256_permute4x64_epi64(srcVector, _MM_SHUFFLE(3, 1, 2, 0));
+ const __m256i src1 = _mm256_unpacklo_epi8(srcVector, srcVector);
+ const __m256i src2 = _mm256_unpackhi_epi8(srcVector, srcVector);
+ if (!cf) {
+ const __m256i alpha1 = _mm256_shuffle_epi8(src1, shuffleMask);
+ const __m256i alpha2 = _mm256_shuffle_epi8(src2, shuffleMask);
+ dst1 = _mm256_mulhi_epu16(src1, alpha1);
+ dst2 = _mm256_mulhi_epu16(src2, alpha2);
+ dst1 = _mm256_add_epi16(dst1, _mm256_srli_epi16(dst1, 15));
+ dst2 = _mm256_add_epi16(dst2, _mm256_srli_epi16(dst2, 15));
+ dst1 = _mm256_blend_epi16(dst1, src1, 0x88);
+ dst2 = _mm256_blend_epi16(dst2, src2, 0x88);
+ } else {
+ dst1 = src1;
+ dst2 = src2;
+ }
+ } else {
+ dst1 = dst2 = zero;
+ }
+ epilogueMask = _mm256_permute4x64_epi64(epilogueMask, _MM_SHUFFLE(3, 1, 2, 0));
+ _mm256_maskstore_epi64(reinterpret_cast<qint64 *>(buffer + i),
+ _mm256_unpacklo_epi32(epilogueMask, epilogueMask),
+ dst1);
+ _mm256_maskstore_epi64(reinterpret_cast<qint64 *>(buffer + i + 4),
+ _mm256_unpackhi_epi32(epilogueMask, epilogueMask),
+ dst2);
+ }
+}
+
+const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_avx2(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToRGBA64PM_avx2<false>(buffer, src, count);
+ return buffer;
+}
+
+const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_avx2(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToRGBA64PM_avx2<true>(buffer, src, count);
+ return buffer;
+}
+
+const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_avx2(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToRGBA64PM_avx2<false>(buffer, reinterpret_cast<const uint *>(src) + index, count);
+ return buffer;
+}
+
+const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_avx2(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToRGBA64PM_avx2<true>(buffer, reinterpret_cast<const uint *>(src) + index, count);
+ return buffer;
+}
+
QT_END_NAMESPACE
#endif
diff --git a/src/gui/painting/qdrawhelper_mips_dsp.cpp b/src/gui/painting/qdrawhelper_mips_dsp.cpp
index e92a6606de..17597deb1d 100644
--- a/src/gui/painting/qdrawhelper_mips_dsp.cpp
+++ b/src/gui/painting/qdrawhelper_mips_dsp.cpp
@@ -43,7 +43,7 @@
QT_BEGIN_NAMESPACE
-void qt_memfill32(quint32 *dest, quint32 color, int count)
+void qt_memfill32(quint32 *dest, quint32 color, qsizetype count)
{
qt_memfill32_asm_mips_dsp(dest, color, count);
}
diff --git a/src/gui/painting/qdrawhelper_mips_dsp_p.h b/src/gui/painting/qdrawhelper_mips_dsp_p.h
index 36c4af2732..a3d0410274 100644
--- a/src/gui/painting/qdrawhelper_mips_dsp_p.h
+++ b/src/gui/painting/qdrawhelper_mips_dsp_p.h
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
#if defined(QT_COMPILER_SUPPORTS_MIPS_DSP)
-extern "C" void qt_memfill32_asm_mips_dsp(quint32 *dest, quint32 value, int count);
+extern "C" void qt_memfill32_asm_mips_dsp(quint32 *dest, quint32 value, qsizetype count);
extern "C" void comp_func_SourceOver_asm_mips_dsp(uint *dest, const uint *src, int length, uint const_alpha);
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 3fbd651f96..8196a87b24 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -47,7 +47,7 @@
QT_BEGIN_NAMESPACE
-void qt_memfill32(quint32 *dest, quint32 value, int count)
+void qt_memfill32(quint32 *dest, quint32 value, qsizetype count)
{
const int epilogueSize = count % 16;
#if defined(Q_CC_GHS) || defined(Q_CC_MSVC)
@@ -802,7 +802,7 @@ void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer, int x, int
void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha)
{
if ((const_alpha & qAlpha(color)) == 255) {
- QT_MEMFILL_UINT(destPixels, length, color);
+ qt_memfill32(destPixels, color, length);
} else {
if (const_alpha != 255)
color = BYTE_MUL(color, const_alpha);
@@ -1160,6 +1160,72 @@ static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int
}
}
+template<bool RGBA>
+static inline void convertARGB32ToRGBA64PM_neon(QRgba64 *buffer, const uint *src, int count)
+{
+ if (count <= 0)
+ return;
+
+ const uint8x8_t shuffleMask = { 3, 3, 3, 3, 7, 7, 7, 7};
+ const uint64x2_t blendMask = vdupq_n_u64(Q_UINT64_C(0xffff000000000000));
+
+ int i = 0;
+ for (; i < count-3; i += 4) {
+ uint32x4_t vs32 = vld1q_u32(src + i);
+ uint32x4_t alphaVector = vshrq_n_u32(vs32, 24);
+#if defined(Q_PROCESSOR_ARM_64)
+ uint32_t alphaSum = vaddvq_u32(alphaVector);
+#else
+ // no vaddvq_u32
+ uint32x2_t tmp = vpadd_u32(vget_low_u32(alphaVector), vget_high_u32(alphaVector));
+ uint32_t alphaSum = vget_lane_u32(vpadd_u32(tmp, tmp), 0);
+#endif
+ if (alphaSum) {
+ if (!RGBA)
+ vs32 = vrgba2argb(vs32);
+ const uint8x16_t vs8 = vreinterpretq_u8_u32(vs32);
+ const uint8x16x2_t v = vzipq_u8(vs8, vs8);
+ if (alphaSum != 255 * 4) {
+ const uint8x8_t s1 = vreinterpret_u8_u32(vget_low_u32(vs32));
+ const uint8x8_t s2 = vreinterpret_u8_u32(vget_high_u32(vs32));
+ const uint8x8_t alpha1 = vtbl1_u8(s1, shuffleMask);
+ const uint8x8_t alpha2 = vtbl1_u8(s2, shuffleMask);
+ uint16x8_t src1 = vmull_u8(s1, alpha1);
+ uint16x8_t src2 = vmull_u8(s2, alpha2);
+ // convert from 0->(255x255) to 0->(255x257)
+ src1 = vsraq_n_u16(src1, src1, 7);
+ src2 = vsraq_n_u16(src2, src2, 7);
+
+ // now restore alpha from the trivial conversion
+ const uint64x2_t d1 = vbslq_u64(blendMask, vreinterpretq_u64_u8(v.val[0]), vreinterpretq_u64_u16(src1));
+ const uint64x2_t d2 = vbslq_u64(blendMask, vreinterpretq_u64_u8(v.val[1]), vreinterpretq_u64_u16(src2));
+
+ vst1q_u16((uint16_t *)buffer, vreinterpretq_u16_u64(d1));
+ buffer += 2;
+ vst1q_u16((uint16_t *)buffer, vreinterpretq_u16_u64(d2));
+ buffer += 2;
+ } else {
+ vst1q_u16((uint16_t *)buffer, vreinterpretq_u16_u8(v.val[0]));
+ buffer += 2;
+ vst1q_u16((uint16_t *)buffer, vreinterpretq_u16_u8(v.val[1]));
+ buffer += 2;
+ }
+ } else {
+ vst1q_u16((uint16_t *)buffer, vdupq_n_u16(0));
+ buffer += 2;
+ vst1q_u16((uint16_t *)buffer, vdupq_n_u16(0));
+ buffer += 2;
+ }
+ }
+
+ SIMD_EPILOGUE(i, count, 3) {
+ uint s = src[i];
+ if (RGBA)
+ s = RGBA2ARGB(s);
+ *buffer++ = QRgba64::fromArgb32(s).premultiplied();
+ }
+}
+
static inline float32x4_t reciprocal_mul_ps(float32x4_t a, float mul)
{
float32x4_t ia = vrecpeq_f32(a); // estimate 1/a
@@ -1269,6 +1335,34 @@ const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_neon(uint *buffer, const uchar *
return buffer;
}
+const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_neon(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGB32ToRGBA64PM_neon<false>(buffer, src, count);
+ return buffer;
+}
+
+const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_neon(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGB32ToRGBA64PM_neon<true>(buffer, src, count);
+ return buffer;
+}
+
+const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_neon(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGB32ToRGBA64PM_neon<false>(buffer, reinterpret_cast<const uint *>(src) + index, count);
+ return buffer;
+}
+
+const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_neon(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGB32ToRGBA64PM_neon<true>(buffer, reinterpret_cast<const uint *>(src) + index, count);
+ return buffer;
+}
+
void QT_FASTCALL storeRGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
{
diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h
index 40475a9bde..19e1f21a3b 100644
--- a/src/gui/painting/qdrawhelper_neon_p.h
+++ b/src/gui/painting/qdrawhelper_neon_p.h
@@ -123,7 +123,7 @@ void qt_transform_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
const QTransform &targetRectTransform,
int const_alpha);
-void qt_memfill32_neon(quint32 *dest, quint32 value, int count);
+void qt_memfill32_neon(quint32 *dest, quint32 value, qsizetype count);
void qt_memrotate90_16_neon(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index fb08261205..9c5d525722 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -69,14 +69,18 @@
QT_BEGIN_NAMESPACE
#if defined(Q_CC_GNU)
-# define Q_STATIC_TEMPLATE_FUNCTION static
# define Q_DECL_RESTRICT __restrict__
+# if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
+# define Q_DECL_VECTORCALL __attribute__((sseregparm,regparm(3)))
+# else
+# define Q_DECL_VECTORCALL
+# endif
#elif defined(Q_CC_MSVC)
-# define Q_STATIC_TEMPLATE_FUNCTION static
# define Q_DECL_RESTRICT __restrict
+# define Q_DECL_VECTORCALL __vectorcall
#else
-# define Q_STATIC_TEMPLATE_FUNCTION static
# define Q_DECL_RESTRICT
+# define Q_DECL_VECTORCALL
#endif
static const uint AMASK = 0xff000000;
@@ -149,7 +153,6 @@ typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uc
struct DrawHelper {
ProcessSpans blendColor;
- ProcessSpans blendGradient;
BitmapBlitFunc bitmapBlit;
AlphamapBlitFunc alphamapBlit;
AlphaRGBBlitFunc alphaRGBBlit;
@@ -162,10 +165,33 @@ extern SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::N
extern DrawHelper qDrawHelper[QImage::NImageFormats];
+struct quint24 {
+ quint24() = default;
+ quint24(uint value)
+ {
+ data[0] = uchar(value >> 16);
+ data[1] = uchar(value >> 8);
+ data[2] = uchar(value);
+ }
+ operator uint() const
+ {
+ return data[2] | (data[1] << 8) | (data[0] << 16);
+ }
+
+ uchar data[3];
+};
+
+void qBlendGradient(int count, const QSpan *spans, void *userData);
void qBlendTexture(int count, const QSpan *spans, void *userData);
-extern void qt_memfill64(quint64 *dest, quint64 value, int count);
-extern void qt_memfill32(quint32 *dest, quint32 value, int count);
-extern void qt_memfill16(quint16 *dest, quint16 value, int count);
+#ifdef __SSE2__
+extern void (*qt_memfill64)(quint64 *dest, quint64 value, qsizetype count);
+extern void (*qt_memfill32)(quint32 *dest, quint32 value, qsizetype count);
+#else
+extern void qt_memfill64(quint64 *dest, quint64 value, qsizetype count);
+extern void qt_memfill32(quint32 *dest, quint32 value, qsizetype count);
+#endif
+extern void qt_memfill24(quint24 *dest, quint24 value, qsizetype count);
+extern void qt_memfill16(quint16 *dest, quint16 value, qsizetype count);
typedef void (QT_FASTCALL *CompositionFunction)(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha);
typedef void (QT_FASTCALL *CompositionFunction64)(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha);
@@ -222,11 +248,6 @@ struct Operator
class QRasterPaintEngine;
-struct QSolidData
-{
- QRgba64 color;
-};
-
struct QLinearGradientData
{
struct {
@@ -275,7 +296,9 @@ struct QGradientData
#define GRADIENT_STOPTABLE_SIZE 1024
#define GRADIENT_STOPTABLE_SIZE_SHIFT 10
+#if QT_CONFIG(raster_64bit)
const QRgba64 *colorTable64; //[GRADIENT_STOPTABLE_SIZE];
+#endif
const QRgb *colorTable32; //[GRADIENT_STOPTABLE_SIZE];
uint alphaColor : 1;
@@ -307,7 +330,7 @@ struct QTextureData
struct QSpanData
{
- QSpanData() : tempImage(0) {}
+ QSpanData() : tempImage(nullptr) {}
~QSpanData() { delete tempImage; }
QRasterBuffer *rasterBuffer;
@@ -331,8 +354,8 @@ struct QSpanData
int fast_matrix : 1;
bool bilinear;
QImage *tempImage;
+ QRgba64 solidColor;
union {
- QSolidData solid;
QGradientData gradient;
QTextureData texture;
};
@@ -381,11 +404,13 @@ static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos)
return data->colorTable32[qt_gradient_clamp(data, ipos)];
}
+#if QT_CONFIG(raster_64bit)
static inline const QRgba64& qt_gradient_pixel64(const QGradientData *data, qreal pos)
{
int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5));
return data->colorTable64[qt_gradient_clamp(data, ipos)];
}
+#endif
static inline qreal qRadialDeterminant(qreal a, qreal b, qreal c)
{
@@ -858,6 +883,8 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) {
// qt_div_255 is a fast rounded division by 255 using an approximation that is accurate for all positive 16-bit integers
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
+static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_257_floor(uint x) { return (x - (x >> 8)) >> 8; }
+static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_257(uint x) { return qt_div_257_floor(x + 128); }
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; }
static Q_ALWAYS_INLINE uint qAlphaRgb30(uint c)
@@ -868,76 +895,63 @@ static Q_ALWAYS_INLINE uint qAlphaRgb30(uint c)
return a;
}
-struct quint24 {
- quint24() = default;
- quint24(uint value);
- operator uint() const;
- uchar data[3];
-};
-
-inline quint24::quint24(uint value)
+template <class T> inline void qt_memfill_template(T *dest, T color, qsizetype count)
{
- data[0] = uchar(value >> 16);
- data[1] = uchar(value >> 8);
- data[2] = uchar(value);
+ if (!count)
+ return;
+
+ qsizetype n = (count + 7) / 8;
+ switch (count & 0x07)
+ {
+ case 0: do { *dest++ = color; Q_FALLTHROUGH();
+ case 7: *dest++ = color; Q_FALLTHROUGH();
+ case 6: *dest++ = color; Q_FALLTHROUGH();
+ case 5: *dest++ = color; Q_FALLTHROUGH();
+ case 4: *dest++ = color; Q_FALLTHROUGH();
+ case 3: *dest++ = color; Q_FALLTHROUGH();
+ case 2: *dest++ = color; Q_FALLTHROUGH();
+ case 1: *dest++ = color;
+ } while (--n > 0);
+ }
}
-inline quint24::operator uint() const
+template <class T> inline void qt_memfill(T *dest, T value, qsizetype count)
{
- return data[2] | (data[1] << 8) | (data[0] << 16);
+ qt_memfill_template(dest, value, count);
}
-template <class T> Q_STATIC_TEMPLATE_FUNCTION
-void qt_memfill(T *dest, T value, int count);
-
-template<> inline void qt_memfill(quint64 *dest, quint64 color, int count)
+template<> inline void qt_memfill(quint64 *dest, quint64 color, qsizetype count)
{
qt_memfill64(dest, color, count);
}
-template<> inline void qt_memfill(quint32 *dest, quint32 color, int count)
+template<> inline void qt_memfill(quint32 *dest, quint32 color, qsizetype count)
{
qt_memfill32(dest, color, count);
}
-template<> inline void qt_memfill(quint16 *dest, quint16 color, int count)
+template<> inline void qt_memfill(quint24 *dest, quint24 color, qsizetype count)
{
- qt_memfill16(dest, color, count);
+ qt_memfill24(dest, color, count);
}
-template<> inline void qt_memfill(quint8 *dest, quint8 color, int count)
+template<> inline void qt_memfill(quint16 *dest, quint16 color, qsizetype count)
{
- memset(dest, color, count);
+ qt_memfill16(dest, color, count);
}
-template <class T>
-inline void qt_memfill(T *dest, T value, int count)
+template<> inline void qt_memfill(quint8 *dest, quint8 color, qsizetype count)
{
- if (!count)
- return;
-
- int n = (count + 7) / 8;
- switch (count & 0x07)
- {
- case 0: do { *dest++ = value; Q_FALLTHROUGH();
- case 7: *dest++ = value; Q_FALLTHROUGH();
- case 6: *dest++ = value; Q_FALLTHROUGH();
- case 5: *dest++ = value; Q_FALLTHROUGH();
- case 4: *dest++ = value; Q_FALLTHROUGH();
- case 3: *dest++ = value; Q_FALLTHROUGH();
- case 2: *dest++ = value; Q_FALLTHROUGH();
- case 1: *dest++ = value;
- } while (--n > 0);
- }
+ memset(dest, color, count);
}
-template <class T> Q_STATIC_TEMPLATE_FUNCTION
+template <class T> static
inline void qt_rectfill(T *dest, T value,
int x, int y, int width, int height, qsizetype stride)
{
char *d = reinterpret_cast<char*>(dest + x) + y * stride;
if (uint(stride) == (width * sizeof(T))) {
- qt_memfill(reinterpret_cast<T*>(d), value, width * height);
+ qt_memfill(reinterpret_cast<T*>(d), value, qsizetype(width) * height);
} else {
for (int j = 0; j < height; ++j) {
dest = reinterpret_cast<T*>(d);
@@ -947,52 +961,6 @@ inline void qt_rectfill(T *dest, T value,
}
}
-#define QT_MEMFILL_UINT(dest, length, color) \
- qt_memfill<quint32>(dest, color, length);
-
-#define QT_MEMFILL_USHORT(dest, length, color) \
- qt_memfill<quint16>(dest, color, length);
-
-#define QT_MEMCPY_REV_UINT(dest, src, length) \
-do { \
- /* Duff's device */ \
- uint *_d = (uint*)(dest) + length; \
- const uint *_s = (uint*)(src) + length; \
- int n = ((length) + 7) / 8; \
- switch ((length) & 0x07) \
- { \
- case 0: do { *--_d = *--_s; Q_FALLTHROUGH(); \
- case 7: *--_d = *--_s; Q_FALLTHROUGH(); \
- case 6: *--_d = *--_s; Q_FALLTHROUGH(); \
- case 5: *--_d = *--_s; Q_FALLTHROUGH(); \
- case 4: *--_d = *--_s; Q_FALLTHROUGH(); \
- case 3: *--_d = *--_s; Q_FALLTHROUGH(); \
- case 2: *--_d = *--_s; Q_FALLTHROUGH(); \
- case 1: *--_d = *--_s; \
- } while (--n > 0); \
- } \
-} while (false)
-
-#define QT_MEMCPY_USHORT(dest, src, length) \
-do { \
- /* Duff's device */ \
- ushort *_d = (ushort*)(dest); \
- const ushort *_s = (const ushort*)(src); \
- int n = ((length) + 7) / 8; \
- switch ((length) & 0x07) \
- { \
- case 0: do { *_d++ = *_s++; Q_FALLTHROUGH(); \
- case 7: *_d++ = *_s++; Q_FALLTHROUGH(); \
- case 6: *_d++ = *_s++; Q_FALLTHROUGH(); \
- case 5: *_d++ = *_s++; Q_FALLTHROUGH(); \
- case 4: *_d++ = *_s++; Q_FALLTHROUGH(); \
- case 3: *_d++ = *_s++; Q_FALLTHROUGH(); \
- case 2: *_d++ = *_s++; Q_FALLTHROUGH(); \
- case 1: *_d++ = *_s++; \
- } while (--n > 0); \
- } \
-} while (false)
-
inline ushort qConvertRgb32To16(uint c)
{
return (((c) >> 3) & 0x001f)
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp
index 3212ffdd2d..c82f41ec88 100644
--- a/src/gui/painting/qdrawhelper_sse2.cpp
+++ b/src/gui/painting/qdrawhelper_sse2.cpp
@@ -233,19 +233,71 @@ void QT_FASTCALL comp_func_Source_sse2(uint *dst, const uint *src, int length, u
}
}
-void qt_memfill32(quint32 *dest, quint32 value, int count)
+#ifndef __AVX2__
+static Q_NEVER_INLINE
+void Q_DECL_VECTORCALL qt_memfillXX_aligned(void *dest, __m128i value128, quintptr bytecount)
{
- if (count < 7) {
+ __m128i *dst128 = reinterpret_cast<__m128i *>(dest);
+ __m128i *end128 = reinterpret_cast<__m128i *>(static_cast<uchar *>(dest) + bytecount);
+
+ while (dst128 + 4 <= end128) {
+ _mm_store_si128(dst128 + 0, value128);
+ _mm_store_si128(dst128 + 1, value128);
+ _mm_store_si128(dst128 + 2, value128);
+ _mm_store_si128(dst128 + 3, value128);
+ dst128 += 4;
+ }
+
+ bytecount %= 4 * sizeof(__m128i);
+ switch (bytecount / sizeof(__m128i)) {
+ case 3: _mm_store_si128(dst128++, value128); Q_FALLTHROUGH();
+ case 2: _mm_store_si128(dst128++, value128); Q_FALLTHROUGH();
+ case 1: _mm_store_si128(dst128++, value128);
+ }
+}
+
+void qt_memfill64_sse2(quint64 *dest, quint64 value, qsizetype count)
+{
+ quintptr misaligned = quintptr(dest) % sizeof(__m128i);
+ if (misaligned && count) {
+#if defined(Q_PROCESSOR_X86_32)
+ // Before SSE came out, the alignment of the stack used to be only 4
+ // bytes and some OS/ABIs (notably, code generated by MSVC) still only
+ // align to that. In any case, we cannot count on the alignment of
+ // quint64 to be 8 -- see QtPrivate::AlignOf_WorkaroundForI386Abi in
+ // qglobal.h.
+ //
+ // If the pointer is not aligned to at least 8 bytes, then we'll never
+ // in turn hit a multiple of 16 for the qt_memfillXX_aligned call
+ // below.
+ if (Q_UNLIKELY(misaligned % sizeof(quint64)))
+ return qt_memfill_template(dest, value, count);
+#endif
+
+ *dest++ = value;
+ --count;
+ }
+
+ if (count % 2) {
+ dest[count - 1] = value;
+ --count;
+ }
+
+ qt_memfillXX_aligned(dest, _mm_set1_epi64x(value), count * sizeof(quint64));
+}
+
+void qt_memfill32_sse2(quint32 *dest, quint32 value, qsizetype count)
+{
+ if (count < 4) {
+ // this simplifies the code below: the first switch can fall through
+ // without checking the value of count
switch (count) {
- case 6: *dest++ = value; Q_FALLTHROUGH();
- case 5: *dest++ = value; Q_FALLTHROUGH();
- case 4: *dest++ = value; Q_FALLTHROUGH();
case 3: *dest++ = value; Q_FALLTHROUGH();
case 2: *dest++ = value; Q_FALLTHROUGH();
case 1: *dest = value;
}
return;
- };
+ }
const int align = (quintptr)(dest) & 0xf;
switch (align) {
@@ -263,25 +315,9 @@ void qt_memfill32(quint32 *dest, quint32 value, int count)
}
}
- int count128 = count / 4;
- __m128i *dst128 = reinterpret_cast<__m128i*>(dest);
- __m128i *end128 = dst128 + count128;
- const __m128i value128 = _mm_set_epi32(value, value, value, value);
-
- while (dst128 + 3 < end128) {
- _mm_stream_si128(dst128 + 0, value128);
- _mm_stream_si128(dst128 + 1, value128);
- _mm_stream_si128(dst128 + 2, value128);
- _mm_stream_si128(dst128 + 3, value128);
- dst128 += 4;
- }
-
- switch (count128 & 0x3) {
- case 3: _mm_stream_si128(dst128++, value128); Q_FALLTHROUGH();
- case 2: _mm_stream_si128(dst128++, value128); Q_FALLTHROUGH();
- case 1: _mm_stream_si128(dst128++, value128);
- }
+ qt_memfillXX_aligned(dest, _mm_set1_epi32(value), count * sizeof(quint32));
}
+#endif // !__AVX2__
void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha)
{
@@ -314,28 +350,6 @@ void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, u
}
}
-void qt_memfill16(quint16 *dest, quint16 value, int count)
-{
- if (count < 3) {
- switch (count) {
- case 2: *dest++ = value; Q_FALLTHROUGH();
- case 1: *dest = value;
- }
- return;
- }
-
- const int align = (quintptr)(dest) & 0x3;
- switch (align) {
- case 2: *dest++ = value; --count;
- }
-
- const quint32 value32 = (value << 16) | value;
- qt_memfill32(reinterpret_cast<quint32*>(dest), value32, count / 2);
-
- if (count & 0x1)
- dest[count - 1] = value;
-}
-
void qt_bitmapblit32_sse2_base(QRasterBuffer *rasterBuffer, int x, int y,
quint32 color,
const uchar *src, int width, int height, int stride)
@@ -440,30 +454,30 @@ public:
union Vect_buffer_i { Int32x4 v; int i[4]; };
union Vect_buffer_f { Float32x4 v; float f[4]; };
- static inline Float32x4 v_dup(float x) { return _mm_set1_ps(x); }
- static inline Float32x4 v_dup(double x) { return _mm_set1_ps(x); }
- static inline Int32x4 v_dup(int x) { return _mm_set1_epi32(x); }
- static inline Int32x4 v_dup(uint x) { return _mm_set1_epi32(x); }
+ static inline Float32x4 Q_DECL_VECTORCALL v_dup(float x) { return _mm_set1_ps(x); }
+ static inline Float32x4 Q_DECL_VECTORCALL v_dup(double x) { return _mm_set1_ps(x); }
+ static inline Int32x4 Q_DECL_VECTORCALL v_dup(int x) { return _mm_set1_epi32(x); }
+ static inline Int32x4 Q_DECL_VECTORCALL v_dup(uint x) { return _mm_set1_epi32(x); }
- static inline Float32x4 v_add(Float32x4 a, Float32x4 b) { return _mm_add_ps(a, b); }
- static inline Int32x4 v_add(Int32x4 a, Int32x4 b) { return _mm_add_epi32(a, b); }
+ static inline Float32x4 Q_DECL_VECTORCALL v_add(Float32x4 a, Float32x4 b) { return _mm_add_ps(a, b); }
+ static inline Int32x4 Q_DECL_VECTORCALL v_add(Int32x4 a, Int32x4 b) { return _mm_add_epi32(a, b); }
- static inline Float32x4 v_max(Float32x4 a, Float32x4 b) { return _mm_max_ps(a, b); }
- static inline Float32x4 v_min(Float32x4 a, Float32x4 b) { return _mm_min_ps(a, b); }
- static inline Int32x4 v_min_16(Int32x4 a, Int32x4 b) { return _mm_min_epi16(a, b); }
+ static inline Float32x4 Q_DECL_VECTORCALL v_max(Float32x4 a, Float32x4 b) { return _mm_max_ps(a, b); }
+ static inline Float32x4 Q_DECL_VECTORCALL v_min(Float32x4 a, Float32x4 b) { return _mm_min_ps(a, b); }
+ static inline Int32x4 Q_DECL_VECTORCALL v_min_16(Int32x4 a, Int32x4 b) { return _mm_min_epi16(a, b); }
- static inline Int32x4 v_and(Int32x4 a, Int32x4 b) { return _mm_and_si128(a, b); }
+ static inline Int32x4 Q_DECL_VECTORCALL v_and(Int32x4 a, Int32x4 b) { return _mm_and_si128(a, b); }
- static inline Float32x4 v_sub(Float32x4 a, Float32x4 b) { return _mm_sub_ps(a, b); }
- static inline Int32x4 v_sub(Int32x4 a, Int32x4 b) { return _mm_sub_epi32(a, b); }
+ static inline Float32x4 Q_DECL_VECTORCALL v_sub(Float32x4 a, Float32x4 b) { return _mm_sub_ps(a, b); }
+ static inline Int32x4 Q_DECL_VECTORCALL v_sub(Int32x4 a, Int32x4 b) { return _mm_sub_epi32(a, b); }
- static inline Float32x4 v_mul(Float32x4 a, Float32x4 b) { return _mm_mul_ps(a, b); }
+ static inline Float32x4 Q_DECL_VECTORCALL v_mul(Float32x4 a, Float32x4 b) { return _mm_mul_ps(a, b); }
- static inline Float32x4 v_sqrt(Float32x4 x) { return _mm_sqrt_ps(x); }
+ static inline Float32x4 Q_DECL_VECTORCALL v_sqrt(Float32x4 x) { return _mm_sqrt_ps(x); }
- static inline Int32x4 v_toInt(Float32x4 x) { return _mm_cvttps_epi32(x); }
+ static inline Int32x4 Q_DECL_VECTORCALL v_toInt(Float32x4 x) { return _mm_cvttps_epi32(x); }
- static inline Int32x4 v_greaterOrEqual(Float32x4 a, Float32x4 b) { return _mm_castps_si128(_mm_cmpgt_ps(a, b)); }
+ static inline Int32x4 Q_DECL_VECTORCALL v_greaterOrEqual(Float32x4 a, Float32x4 b) { return _mm_castps_si128(_mm_cmpgt_ps(a, b)); }
};
const uint * QT_FASTCALL qt_fetch_radial_gradient_sse2(uint *buffer, const Operator *op, const QSpanData *data,
diff --git a/src/gui/painting/qdrawhelper_sse4.cpp b/src/gui/painting/qdrawhelper_sse4.cpp
index 9daaaecc98..68d887ae6d 100644
--- a/src/gui/painting/qdrawhelper_sse4.cpp
+++ b/src/gui/painting/qdrawhelper_sse4.cpp
@@ -45,6 +45,7 @@
QT_BEGIN_NAMESPACE
+#ifndef __AVX2__
template<bool RGBA>
static void convertARGBToARGB32PM_sse4(uint *buffer, const uint *src, int count)
{
@@ -94,7 +95,55 @@ static void convertARGBToARGB32PM_sse4(uint *buffer, const uint *src, int count)
}
}
-static inline __m128 reciprocal_mul_ps(__m128 a, float mul)
+template<bool RGBA>
+static void convertARGBToRGBA64PM_sse4(QRgba64 *buffer, const uint *src, int count)
+{
+ int i = 0;
+ const __m128i alphaMask = _mm_set1_epi32(0xff000000);
+ const __m128i rgbaMask = _mm_setr_epi8(2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15);
+ const __m128i shuffleMask = _mm_setr_epi8(6, 7, 6, 7, 6, 7, 6, 7, 14, 15, 14, 15, 14, 15, 14, 15);
+ const __m128i zero = _mm_setzero_si128();
+
+ for (; i < count - 3; i += 4) {
+ __m128i srcVector = _mm_loadu_si128((const __m128i *)&src[i]);
+ if (!_mm_testz_si128(srcVector, alphaMask)) {
+ bool cf = _mm_testc_si128(srcVector, alphaMask);
+
+ if (!RGBA)
+ srcVector = _mm_shuffle_epi8(srcVector, rgbaMask);
+ const __m128i src1 = _mm_unpacklo_epi8(srcVector, srcVector);
+ const __m128i src2 = _mm_unpackhi_epi8(srcVector, srcVector);
+ if (!cf) {
+ __m128i alpha1 = _mm_shuffle_epi8(src1, shuffleMask);
+ __m128i alpha2 = _mm_shuffle_epi8(src2, shuffleMask);
+ __m128i dst1 = _mm_mulhi_epu16(src1, alpha1);
+ __m128i dst2 = _mm_mulhi_epu16(src2, alpha2);
+ // Map 0->0xfffe to 0->0xffff
+ dst1 = _mm_add_epi16(dst1, _mm_srli_epi16(dst1, 15));
+ dst2 = _mm_add_epi16(dst2, _mm_srli_epi16(dst2, 15));
+ // correct alpha value:
+ dst1 = _mm_blend_epi16(dst1, src1, 0x88);
+ dst2 = _mm_blend_epi16(dst2, src2, 0x88);
+ _mm_storeu_si128((__m128i *)&buffer[i], dst1);
+ _mm_storeu_si128((__m128i *)&buffer[i + 2], dst2);
+ } else {
+ _mm_storeu_si128((__m128i *)&buffer[i], src1);
+ _mm_storeu_si128((__m128i *)&buffer[i + 2], src2);
+ }
+ } else {
+ _mm_storeu_si128((__m128i *)&buffer[i], zero);
+ _mm_storeu_si128((__m128i *)&buffer[i + 2], zero);
+ }
+ }
+
+ SIMD_EPILOGUE(i, count, 3) {
+ const uint s = RGBA ? RGBA2ARGB(src[i]) : src[i];
+ buffer[i] = QRgba64::fromArgb32(s).premultiplied();
+ }
+}
+#endif // __AVX2__
+
+static inline __m128 Q_DECL_VECTORCALL reciprocal_mul_ps(__m128 a, float mul)
{
__m128 ia = _mm_rcp_ps(a); // Approximate 1/a
// Improve precision of ia using Newton-Raphson
@@ -277,6 +326,7 @@ static inline void convertARGBFromRGBA64PM_sse4(uint *buffer, const QRgba64 *src
}
}
+#ifndef __AVX2__
void QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, int count, const QVector<QRgb> *)
{
convertARGBToARGB32PM_sse4<false>(buffer, buffer, count);
@@ -287,6 +337,20 @@ void QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, int count, const Q
convertARGBToARGB32PM_sse4<true>(buffer, buffer, count);
}
+const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_sse4(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToRGBA64PM_sse4<false>(buffer, src, count);
+ return buffer;
+}
+
+const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_sse4(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToRGBA64PM_sse4<true>(buffer, src, count);
+ return buffer;
+}
+
const uint *QT_FASTCALL fetchARGB32ToARGB32PM_sse4(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
{
@@ -301,6 +365,21 @@ const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_sse4(uint *buffer, const uchar *
return buffer;
}
+const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_sse4(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToRGBA64PM_sse4<false>(buffer, reinterpret_cast<const uint *>(src) + index, count);
+ return buffer;
+}
+
+const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_sse4(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToRGBA64PM_sse4<true>(buffer, reinterpret_cast<const uint *>(src) + index, count);
+ return buffer;
+}
+#endif // __AVX2__
+
void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
{
@@ -338,6 +417,7 @@ void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4(uchar *dest, const uint *src, i
d[i] = qConvertArgb32ToA2rgb30_sse4<PixelOrder>(src[i]);
}
+#if QT_CONFIG(raster_64bit)
void QT_FASTCALL destStore64ARGB32_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
{
uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
@@ -349,6 +429,7 @@ void QT_FASTCALL destStore64RGBA8888_sse4(QRasterBuffer *rasterBuffer, int x, in
uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
convertARGBFromRGBA64PM_sse4<true>(dest, buffer, length);
}
+#endif
void QT_FASTCALL storeARGB32FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
diff --git a/src/gui/painting/qdrawhelper_ssse3.cpp b/src/gui/painting/qdrawhelper_ssse3.cpp
index 42d760d5cc..35d61c3e6c 100644
--- a/src/gui/painting/qdrawhelper_ssse3.cpp
+++ b/src/gui/painting/qdrawhelper_ssse3.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -79,55 +80,58 @@ QT_BEGIN_NAMESPACE
// The computation being done is:
// result = s + d * (1-alpha)
// with shortcuts if fully opaque or fully transparent.
-#define BLEND_SOURCE_OVER_ARGB32_SSSE3(dst, src, length, nullVector, half, one, colorMask, alphaMask) { \
- int x = 0; \
-\
- /* First, get dst aligned. */ \
- ALIGNMENT_PROLOGUE_16BYTES(dst, x, length) { \
- blend_pixel(dst[x], src[x]); \
- } \
-\
- const int minusOffsetToAlignSrcOn16Bytes = (reinterpret_cast<quintptr>(&(src[x])) >> 2) & 0x3;\
-\
- if (!minusOffsetToAlignSrcOn16Bytes) {\
- /* src is aligned, usual algorithm but with aligned operations.\
- See the SSE2 version for more documentation on the algorithm itself. */\
- const __m128i alphaShuffleMask = _mm_set_epi8(char(0xff),15,char(0xff),15,char(0xff),11,char(0xff),11,char(0xff),7,char(0xff),7,char(0xff),3,char(0xff),3);\
- for (; x < length-3; x += 4) { \
- const __m128i srcVector = _mm_load_si128((const __m128i *)&src[x]); \
- const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \
- if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \
- _mm_store_si128((__m128i *)&dst[x], srcVector); \
- } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \
- __m128i alphaChannel = _mm_shuffle_epi8(srcVector, alphaShuffleMask); \
- alphaChannel = _mm_sub_epi16(one, alphaChannel); \
- const __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]); \
- __m128i destMultipliedByOneMinusAlpha; \
- BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \
- const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \
- _mm_store_si128((__m128i *)&dst[x], result); \
- } \
- } /* end for() */\
- } else if ((length - x) >= 8) {\
- /* We use two vectors to extract the src: prevLoaded for the first pixels, lastLoaded for the current pixels. */\
- __m128i srcVectorPrevLoaded = _mm_load_si128((const __m128i *)&src[x - minusOffsetToAlignSrcOn16Bytes]);\
- const int palignrOffset = minusOffsetToAlignSrcOn16Bytes << 2;\
-\
- const __m128i alphaShuffleMask = _mm_set_epi8(char(0xff),15,char(0xff),15,char(0xff),11,char(0xff),11,char(0xff),7,char(0xff),7,char(0xff),3,char(0xff),3);\
- switch (palignrOffset) {\
- case 4:\
- BLENDING_LOOP(4, length)\
- break;\
- case 8:\
- BLENDING_LOOP(8, length)\
- break;\
- case 12:\
- BLENDING_LOOP(12, length)\
- break;\
- }\
- }\
- for (; x < length; ++x) \
- blend_pixel(dst[x], src[x]); \
+static inline void Q_DECL_VECTORCALL
+BLEND_SOURCE_OVER_ARGB32_SSSE3(quint32 *dst, const quint32 *src, int length,
+ __m128i nullVector, __m128i half, __m128i one, __m128i colorMask, __m128i alphaMask)
+{
+ int x = 0;
+
+ /* First, get dst aligned. */
+ ALIGNMENT_PROLOGUE_16BYTES(dst, x, length) {
+ blend_pixel(dst[x], src[x]);
+ }
+
+ const int minusOffsetToAlignSrcOn16Bytes = (reinterpret_cast<quintptr>(&(src[x])) >> 2) & 0x3;
+
+ if (!minusOffsetToAlignSrcOn16Bytes) {
+ /* src is aligned, usual algorithm but with aligned operations.
+ See the SSE2 version for more documentation on the algorithm itself. */
+ const __m128i alphaShuffleMask = _mm_set_epi8(char(0xff),15,char(0xff),15,char(0xff),11,char(0xff),11,char(0xff),7,char(0xff),7,char(0xff),3,char(0xff),3);
+ for (; x < length-3; x += 4) {
+ const __m128i srcVector = _mm_load_si128((const __m128i *)&src[x]);
+ const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask);
+ if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) {
+ _mm_store_si128((__m128i *)&dst[x], srcVector);
+ } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) {
+ __m128i alphaChannel = _mm_shuffle_epi8(srcVector, alphaShuffleMask);
+ alphaChannel = _mm_sub_epi16(one, alphaChannel);
+ const __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]);
+ __m128i destMultipliedByOneMinusAlpha;
+ BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half);
+ const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha);
+ _mm_store_si128((__m128i *)&dst[x], result);
+ }
+ } /* end for() */
+ } else if ((length - x) >= 8) {
+ /* We use two vectors to extract the src: prevLoaded for the first pixels, lastLoaded for the current pixels. */
+ __m128i srcVectorPrevLoaded = _mm_load_si128((const __m128i *)&src[x - minusOffsetToAlignSrcOn16Bytes]);
+ const int palignrOffset = minusOffsetToAlignSrcOn16Bytes << 2;
+
+ const __m128i alphaShuffleMask = _mm_set_epi8(char(0xff),15,char(0xff),15,char(0xff),11,char(0xff),11,char(0xff),7,char(0xff),7,char(0xff),3,char(0xff),3);
+ switch (palignrOffset) {
+ case 4:
+ BLENDING_LOOP(4, length)
+ break;
+ case 8:
+ BLENDING_LOOP(8, length)
+ break;
+ case 12:
+ BLENDING_LOOP(12, length)
+ break;
+ }
+ }
+ for (; x < length; ++x)
+ blend_pixel(dst[x], src[x]);
}
void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl,
@@ -185,6 +189,71 @@ const uint * QT_FASTCALL qt_fetchUntransformed_888_ssse3(uint *buffer, const Ope
return buffer;
}
+void qt_memfill24_ssse3(quint24 *dest, quint24 color, qsizetype count)
+{
+ // LCM of 12 and 16 bytes is 48 bytes (16 px)
+ quint32 v = color;
+ __m128i m = _mm_cvtsi32_si128(v);
+ quint24 *end = dest + count;
+
+ constexpr uchar x = 2, y = 1, z = 0;
+ Q_DECL_ALIGN(__m128i) static const uchar
+ shuffleMask[16 + 1] = { x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y };
+
+ __m128i mval1 = _mm_shuffle_epi8(m, _mm_load_si128(reinterpret_cast<const __m128i *>(shuffleMask)));
+ __m128i mval2 = _mm_shuffle_epi8(m, _mm_loadu_si128(reinterpret_cast<const __m128i *>(shuffleMask + 1)));
+ __m128i mval3 = _mm_alignr_epi8(mval2, mval1, 2);
+
+ for ( ; dest + 16 <= end; dest += 16) {
+#ifdef __AVX__
+ // Store using 32-byte AVX instruction
+ __m256 mval12 = _mm256_castps128_ps256(_mm_castsi128_ps(mval1));
+ mval12 = _mm256_insertf128_ps(mval12, _mm_castsi128_ps(mval2), 1);
+ _mm256_storeu_ps(reinterpret_cast<float *>(dest), mval12);
+#else
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dest) + 0, mval1);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dest) + 1, mval2);
+#endif
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dest) + 2, mval3);
+ }
+
+ if (count < 3) {
+ if (count > 1)
+ end[-2] = v;
+ if (count)
+ end[-1] = v;
+ return;
+ }
+
+ // less than 16px/48B left
+ uchar *ptr = reinterpret_cast<uchar *>(dest);
+ uchar *ptr_end = reinterpret_cast<uchar *>(end);
+ qptrdiff left = ptr_end - ptr;
+ if (left >= 24) {
+ // 8px/24B or more left
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(ptr) + 0, mval1);
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(ptr) + 1, mval2);
+ ptr += 24;
+ left -= 24;
+ }
+
+ // less than 8px/24B left
+
+ if (left >= 16) {
+ // but more than 5px/15B left
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(ptr) , mval1);
+ } else if (left >= 8) {
+ // but more than 2px/6B left
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(ptr), mval1);
+ }
+
+ if (left) {
+ // 1 or 2px left
+ // store 8 bytes ending with the right values (will overwrite a bit)
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(ptr_end - 8), mval2);
+ }
+}
+
QT_END_NAMESPACE
#endif // QT_COMPILER_SUPPORTS_SSSE3
diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h
index cefc213999..5749d8c9fb 100644
--- a/src/gui/painting/qdrawhelper_x86_p.h
+++ b/src/gui/painting/qdrawhelper_x86_p.h
@@ -57,8 +57,8 @@
QT_BEGIN_NAMESPACE
#ifdef __SSE2__
-void qt_memfill32(quint32 *dest, quint32 value, int count);
-void qt_memfill16(quint16 *dest, quint16 value, int count);
+void qt_memfill64_sse2(quint64 *dest, quint64 value, qsizetype count);
+void qt_memfill32_sse2(quint32 *dest, quint32 value, qsizetype count);
void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y,
const QRgba64 &color,
const uchar *src, int width, int height, int stride);
@@ -79,6 +79,9 @@ void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
extern CompositionFunction qt_functionForMode_SSE2[];
extern CompositionFunctionSolid qt_functionForModeSolid_SSE2[];
+
+void qt_memfill64_avx2(quint64 *dest, quint64 value, qsizetype count);
+void qt_memfill32_avx2(quint32 *dest, quint32 value, qsizetype count);
#endif // __SSE2__
static const int numCompositionFunctions = 38;
diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h
index b237ea1611..cc8d230fa8 100644
--- a/src/gui/painting/qdrawingprimitive_sse2_p.h
+++ b/src/gui/painting/qdrawingprimitive_sse2_p.h
@@ -42,7 +42,7 @@
#include <QtGui/private/qtguiglobal_p.h>
#include <private/qsimd_p.h>
-#include "qdrawhelper_p.h"
+#include "qdrawhelper_x86_p.h"
#include "qrgba64_p.h"
#ifdef __SSE2__
@@ -232,7 +232,7 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
#if QT_COMPILER_SUPPORTS_HERE(SSE4_1)
QT_FUNCTION_TARGET(SSE2)
-Q_ALWAYS_INLINE void reciprocal_mul_ss(__m128 &ia, const __m128 a, float mul)
+Q_ALWAYS_INLINE void Q_DECL_VECTORCALL reciprocal_mul_ss(__m128 &ia, const __m128 a, float mul)
{
ia = _mm_rcp_ss(a); // Approximate 1/a
// Improve precision of ia using Newton-Raphson
diff --git a/src/gui/painting/qicc.cpp b/src/gui/painting/qicc.cpp
new file mode 100644
index 0000000000..d88b005782
--- /dev/null
+++ b/src/gui/painting/qicc.cpp
@@ -0,0 +1,669 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qicc_p.h"
+
+#include <qbuffer.h>
+#include <qbytearray.h>
+#include <qdatastream.h>
+#include <qloggingcategory.h>
+#include <qendian.h>
+
+#include "qcolorspace_p.h"
+#include "qcolortrc_p.h"
+
+QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcIcc, "qt.gui.icc")
+
+struct ICCProfileHeader
+{
+ quint32_be profileSize;
+
+ quint32_be preferredCmmType;
+
+ quint32_be profileVersion;
+ quint32_be profileClass;
+ quint32_be inputColorSpace;
+ quint32_be pcs;
+ quint32_be datetime[3];
+ quint32_be signature;
+ quint32_be platformSignature;
+ quint32_be flags;
+ quint32_be deviceManufacturer;
+ quint32_be deviceModel;
+ quint32_be deviceAttributes[2];
+
+ quint32_be renderingIntent;
+ qint32_be illuminantXyz[3];
+
+ quint32_be creatorSignature;
+ quint32_be profileId[4];
+
+ quint32_be reserved[7];
+
+// Technically after the header, but easier to include here:
+ quint32_be tagCount;
+};
+
+constexpr quint32 IccTag(uchar a, uchar b, uchar c, uchar d)
+{
+ return (a << 24) | (b << 16) | (c << 8) | d;
+}
+
+enum class ProfileClass : quint32 {
+ Input = IccTag('s', 'c', 'r', 'n'),
+ Display = IccTag('m', 'n', 't', 'r'),
+ // Not supported:
+ Output = IccTag('p', 'r', 't', 'r'),
+ ColorSpace = IccTag('s', 'p', 'a', 'c'),
+};
+
+enum class Tag : quint32 {
+ acsp = IccTag('a', 'c', 's', 'p'),
+ RGB_ = IccTag('R', 'G', 'B', ' '),
+ XYZ_ = IccTag('X', 'Y', 'Z', ' '),
+ rXYZ = IccTag('r', 'X', 'Y', 'Z'),
+ gXYZ = IccTag('g', 'X', 'Y', 'Z'),
+ bXYZ = IccTag('b', 'X', 'Y', 'Z'),
+ rTRC = IccTag('r', 'T', 'R', 'C'),
+ gTRC = IccTag('g', 'T', 'R', 'C'),
+ bTRC = IccTag('b', 'T', 'R', 'C'),
+ A2B0 = IccTag('A', '2', 'B', '0'),
+ A2B1 = IccTag('A', '2', 'B', '1'),
+ B2A0 = IccTag('B', '2', 'A', '0'),
+ B2A1 = IccTag('B', '2', 'A', '1'),
+ desc = IccTag('d', 'e', 's', 'c'),
+ text = IccTag('t', 'e', 'x', 't'),
+ cprt = IccTag('c', 'p', 'r', 't'),
+ curv = IccTag('c', 'u', 'r', 'v'),
+ para = IccTag('p', 'a', 'r', 'a'),
+ wtpt = IccTag('w', 't', 'p', 't'),
+ bkpt = IccTag('b', 'k', 'p', 't'),
+ mft1 = IccTag('m', 'f', 't', '1'),
+ mft2 = IccTag('m', 'f', 't', '2'),
+ mAB_ = IccTag('m', 'A', 'B', ' '),
+ mBA_ = IccTag('m', 'B', 'A', ' '),
+ chad = IccTag('c', 'h', 'a', 'd'),
+ sf32 = IccTag('s', 'f', '3', '2'),
+
+ // Apple extensions for ICCv2:
+ aarg = IccTag('a', 'a', 'r', 'g'),
+ aagg = IccTag('a', 'a', 'g', 'g'),
+ aabg = IccTag('a', 'a', 'b', 'g'),
+};
+
+inline uint qHash(const Tag &key, uint seed = 0)
+{
+ return qHash(quint32(key), seed);
+}
+
+namespace QIcc {
+
+struct TagTableEntry
+{
+ quint32_be signature;
+ quint32_be offset;
+ quint32_be size;
+};
+
+struct GenericTagData {
+ quint32_be type;
+ quint32_be null;
+};
+
+struct XYZTagData : GenericTagData {
+ qint32_be fixedX;
+ qint32_be fixedY;
+ qint32_be fixedZ;
+};
+
+struct CurvTagData : GenericTagData {
+ quint32_be valueCount;
+ quint16_be value[1];
+};
+
+struct ParaTagData : GenericTagData {
+ quint16_be curveType;
+ quint16_be null2;
+ quint32_be parameter[1];
+};
+
+// For both mAB and mBA
+struct mABTagData : GenericTagData {
+ quint8 inputChannels;
+ quint8 outputChannels;
+ quint8 padding[2];
+ quint32_be bCurvesOffset;
+ quint32_be matrixOffset;
+ quint32_be mCurvesOffset;
+ quint32_be clutOffset;
+ quint32_be aCurvesOffset;
+};
+
+struct Sf32TagData : GenericTagData {
+ quint32_be value[1];
+};
+
+static int toFixedS1516(float x)
+{
+ return int(x * 65536.0f + 0.5f);
+}
+
+static float fromFixedS1516(int x)
+{
+ return x * (1.0f / 65536.0f);
+}
+
+QColorVector fromXyzData(const XYZTagData *xyz)
+{
+ const float x = fromFixedS1516(xyz->fixedX);
+ const float y = fromFixedS1516(xyz->fixedY);
+ const float z = fromFixedS1516(xyz->fixedZ);
+ qCDebug(lcIcc) << "XYZ_ " << x << y << z;
+
+ return QColorVector(x, y, z);
+}
+
+static bool isValidIccProfile(const ICCProfileHeader &header)
+{
+ if (header.signature != uint(Tag::acsp)) {
+ qCWarning(lcIcc, "Failed ICC signature test");
+ return false;
+ }
+ if (header.profileSize < (sizeof(ICCProfileHeader) + header.tagCount * sizeof(TagTableEntry))) {
+ qCWarning(lcIcc, "Failed basic size sanity");
+ return false;
+ }
+
+ if (header.profileClass != uint(ProfileClass::Input)
+ && header.profileClass != uint(ProfileClass::Display)) {
+ qCWarning(lcIcc, "Unsupported ICC profile class %x", quint32(header.profileClass));
+ return false;
+ }
+ if (header.inputColorSpace != 0x52474220 /* 'RGB '*/) {
+ qCWarning(lcIcc, "Unsupported ICC input color space %x", quint32(header.inputColorSpace));
+ return false;
+ }
+ if (header.pcs != 0x58595a20 /* 'XYZ '*/) {
+ // ### support PCSLAB
+ qCWarning(lcIcc, "Unsupported ICC profile connection space %x", quint32(header.pcs));
+ return false;
+ }
+
+ QColorVector illuminant;
+ illuminant.x = fromFixedS1516(header.illuminantXyz[0]);
+ illuminant.y = fromFixedS1516(header.illuminantXyz[1]);
+ illuminant.z = fromFixedS1516(header.illuminantXyz[2]);
+ if (illuminant != QColorVector::D50()) {
+ qCWarning(lcIcc, "Invalid ICC illuminant");
+ return false;
+ }
+
+ return true;
+}
+
+static int writeColorTrc(QDataStream &stream, const QColorTrc &trc)
+{
+ if (trc.isLinear()) {
+ stream << uint(Tag::curv) << uint(0);
+ stream << uint(0);
+ return 12;
+ }
+
+ if (trc.m_type == QColorTrc::Type::Function) {
+ const QColorTransferFunction &fun = trc.m_fun;
+ stream << uint(Tag::para) << uint(0);
+ if (fun.isGamma()) {
+ stream << ushort(0) << ushort(0);
+ stream << toFixedS1516(fun.m_g);
+ return 12 + 4;
+ }
+ bool type3 = qFuzzyIsNull(fun.m_e) && qFuzzyIsNull(fun.m_f);
+ stream << ushort(type3 ? 3 : 4) << ushort(0);
+ stream << toFixedS1516(fun.m_g);
+ stream << toFixedS1516(fun.m_a);
+ stream << toFixedS1516(fun.m_b);
+ stream << toFixedS1516(fun.m_c);
+ stream << toFixedS1516(fun.m_d);
+ if (type3)
+ return 12 + 5 * 4;
+ stream << toFixedS1516(fun.m_e);
+ stream << toFixedS1516(fun.m_f);
+ return 12 + 7 * 4;
+ }
+
+ Q_ASSERT(trc.m_type == QColorTrc::Type::Table);
+ stream << uint(Tag::curv) << uint(0);
+ stream << uint(trc.m_table.m_tableSize);
+ if (!trc.m_table.m_table16.isEmpty()) {
+ for (uint i = 0; i < trc.m_table.m_tableSize; ++i) {
+ stream << ushort(trc.m_table.m_table16[i]);
+ }
+ } else {
+ for (uint i = 0; i < trc.m_table.m_tableSize; ++i) {
+ stream << ushort(trc.m_table.m_table8[i] * 257U);
+ }
+ }
+ return 12 + 2 * trc.m_table.m_tableSize;
+}
+
+QByteArray toIccProfile(const QColorSpace &space)
+{
+ if (!space.isValid())
+ return QByteArray();
+
+ const QColorSpacePrivate *spaceDPtr = space.d_func();
+
+ constexpr int tagCount = 9;
+ constexpr uint profileDataOffset = 128 + 4 + 12 * tagCount;
+ constexpr uint variableTagTableOffsets = 128 + 4 + 12 * 5;
+ uint currentOffset = 0;
+ uint rTrcOffset, gTrcOffset, bTrcOffset;
+ uint rTrcSize, gTrcSize, bTrcSize;
+ uint descOffset, descSize;
+
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QDataStream stream(&buffer);
+
+ // Profile header:
+ stream << uint(0); // Size, we will update this later
+ stream << uint(0);
+ stream << uint(0x02400000); // Version 2.4 (note we use 'para' from version 4)
+ stream << uint(ProfileClass::Display);
+ stream << uint(Tag::RGB_);
+ stream << uint(Tag::XYZ_);
+ stream << uint(0) << uint(0) << uint(0);
+ stream << uint(Tag::acsp);
+ stream << uint(0) << uint(0) << uint(0);
+ stream << uint(0) << uint(0) << uint(0);
+ stream << uint(1); // Rendering intent
+ stream << uint(0x0000f6d6); // D50 X
+ stream << uint(0x00010000); // D50 Y
+ stream << uint(0x0000d32d); // D50 Z
+ stream << IccTag('Q','t', QT_VERSION_MAJOR, QT_VERSION_MINOR);
+ stream << uint(0) << uint(0) << uint(0) << uint(0);
+ stream << uint(0) << uint(0) << uint(0) << uint(0) << uint(0) << uint(0) << uint(0);
+
+ // Tag table:
+ stream << uint(tagCount);
+ stream << uint(Tag::rXYZ) << uint(profileDataOffset + 00) << uint(20);
+ stream << uint(Tag::gXYZ) << uint(profileDataOffset + 20) << uint(20);
+ stream << uint(Tag::bXYZ) << uint(profileDataOffset + 40) << uint(20);
+ stream << uint(Tag::wtpt) << uint(profileDataOffset + 60) << uint(20);
+ stream << uint(Tag::cprt) << uint(profileDataOffset + 80) << uint(12);
+ // From here the offset and size will be updated later:
+ stream << uint(Tag::rTRC) << uint(0) << uint(0);
+ stream << uint(Tag::gTRC) << uint(0) << uint(0);
+ stream << uint(Tag::bTRC) << uint(0) << uint(0);
+ stream << uint(Tag::desc) << uint(0) << uint(0);
+ // TODO: consider adding 'chad' tag (required in ICC >=4 when we have non-D50 whitepoint)
+ currentOffset = profileDataOffset;
+
+ // Tag data:
+ stream << uint(Tag::XYZ_) << uint(0);
+ stream << toFixedS1516(spaceDPtr->toXyz.r.x);
+ stream << toFixedS1516(spaceDPtr->toXyz.r.y);
+ stream << toFixedS1516(spaceDPtr->toXyz.r.z);
+ stream << uint(Tag::XYZ_) << uint(0);
+ stream << toFixedS1516(spaceDPtr->toXyz.g.x);
+ stream << toFixedS1516(spaceDPtr->toXyz.g.y);
+ stream << toFixedS1516(spaceDPtr->toXyz.g.z);
+ stream << uint(Tag::XYZ_) << uint(0);
+ stream << toFixedS1516(spaceDPtr->toXyz.b.x);
+ stream << toFixedS1516(spaceDPtr->toXyz.b.y);
+ stream << toFixedS1516(spaceDPtr->toXyz.b.z);
+ stream << uint(Tag::XYZ_) << uint(0);
+ stream << toFixedS1516(spaceDPtr->whitePoint.x);
+ stream << toFixedS1516(spaceDPtr->whitePoint.y);
+ stream << toFixedS1516(spaceDPtr->whitePoint.z);
+ stream << uint(Tag::text) << uint(0);
+ stream << uint(IccTag('N', '/', 'A', '\0'));
+ currentOffset += 92;
+
+ // From now on the data is variable sized:
+ rTrcOffset = currentOffset;
+ rTrcSize = writeColorTrc(stream, spaceDPtr->trc[0]);
+ currentOffset += rTrcSize;
+ if (spaceDPtr->trc[0] == spaceDPtr->trc[1]) {
+ gTrcOffset = rTrcOffset;
+ gTrcSize = rTrcSize;
+ } else {
+ gTrcOffset = currentOffset;
+ gTrcSize = writeColorTrc(stream, spaceDPtr->trc[1]);
+ currentOffset += gTrcSize;
+ }
+ if (spaceDPtr->trc[0] == spaceDPtr->trc[2]) {
+ bTrcOffset = rTrcOffset;
+ bTrcSize = rTrcSize;
+ } else {
+ bTrcOffset = currentOffset;
+ bTrcSize = writeColorTrc(stream, spaceDPtr->trc[2]);
+ currentOffset += bTrcSize;
+ }
+
+ descOffset = currentOffset;
+ QByteArray description = spaceDPtr->description.toUtf8();
+ stream << uint(Tag::desc) << uint(0);
+ stream << uint(description.size() + 1);
+ stream.writeRawData(description.constData(), description.size() + 1);
+ stream << uint(0) << uint(0);
+ stream << ushort(0) << uchar(0);
+ QByteArray macdesc(67, '\0');
+ stream.writeRawData(macdesc.constData(), 67);
+ descSize = 90 + description.size() + 1;
+ currentOffset += descSize;
+
+ buffer.close();
+ QByteArray iccProfile = buffer.buffer();
+ // Now write final size
+ *(quint32_be *)iccProfile.data() = iccProfile.size();
+ // And the final indices and sizes of variable size tags:
+ *(quint32_be *)(iccProfile.data() + variableTagTableOffsets + 4) = rTrcOffset;
+ *(quint32_be *)(iccProfile.data() + variableTagTableOffsets + 8) = rTrcSize;
+ *(quint32_be *)(iccProfile.data() + variableTagTableOffsets + 12 + 4) = gTrcOffset;
+ *(quint32_be *)(iccProfile.data() + variableTagTableOffsets + 12 + 8) = gTrcSize;
+ *(quint32_be *)(iccProfile.data() + variableTagTableOffsets + 2 * 12 + 4) = bTrcOffset;
+ *(quint32_be *)(iccProfile.data() + variableTagTableOffsets + 2 * 12 + 8) = bTrcSize;
+ *(quint32_be *)(iccProfile.data() + variableTagTableOffsets + 3 * 12 + 4) = descOffset;
+ *(quint32_be *)(iccProfile.data() + variableTagTableOffsets + 3 * 12 + 8) = descSize;
+
+#if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS)
+ const ICCProfileHeader *iccHeader = (const ICCProfileHeader *)iccProfile.constData();
+ Q_ASSERT(qsizetype(iccHeader->profileSize) == qsizetype(iccProfile.size()));
+ Q_ASSERT(isValidIccProfile(*iccHeader));
+#endif
+
+ return iccProfile;
+}
+
+bool parseTRC(const GenericTagData *trcData, QColorTrc &gamma)
+{
+ if (trcData->type == quint32(Tag::curv)) {
+ const CurvTagData *curv = reinterpret_cast<const CurvTagData *>(trcData);
+ qCDebug(lcIcc) << "curv" << uint(curv->valueCount);
+ if (curv->valueCount == 0) {
+ gamma.m_type = QColorTrc::Type::Function;
+ gamma.m_fun = QColorTransferFunction(); // Linear
+ } else if (curv->valueCount == 1) {
+ float g = curv->value[0] * (1.0f / 256.0f);
+ qCDebug(lcIcc) << g;
+ gamma.m_type = QColorTrc::Type::Function;
+ gamma.m_fun = QColorTransferFunction::fromGamma(g);
+ } else {
+ QVector<quint16> tabl;
+ tabl.resize(curv->valueCount);
+ for (uint i = 0; i < curv->valueCount; ++i)
+ tabl[i] = curv->value[i];
+ QColorTransferTable table = QColorTransferTable(curv->valueCount, std::move(tabl));
+ QColorTransferFunction curve;
+ if (!table.asColorTransferFunction(&curve)) {
+ gamma.m_type = QColorTrc::Type::Table;
+ gamma.m_table = table;
+ } else {
+ qCDebug(lcIcc) << "Detected curv table as function";
+ gamma.m_type = QColorTrc::Type::Function;
+ gamma.m_fun = curve;
+ }
+ }
+ return true;
+ }
+ if (trcData->type == quint32(Tag::para)) {
+ const ParaTagData *para = reinterpret_cast<const ParaTagData *>(trcData);
+ qCDebug(lcIcc) << "para" << uint(para->curveType);
+ switch (para->curveType) {
+ case 0: {
+ float g = fromFixedS1516(para->parameter[0]);
+ qCDebug(lcIcc) << g;
+ gamma.m_type = QColorTrc::Type::Function;
+ gamma.m_fun = QColorTransferFunction::fromGamma(g);
+ break;
+ }
+ case 1: {
+ float g = fromFixedS1516(para->parameter[0]);
+ float a = fromFixedS1516(para->parameter[1]);
+ float b = fromFixedS1516(para->parameter[2]);
+ float d = -b / a;
+ qCDebug(lcIcc) << g << a << b;
+ gamma.m_type = QColorTrc::Type::Function;
+ gamma.m_fun = QColorTransferFunction(a, b, 0.0f, d, 0.0f, 0.0f, g);
+ break;
+ }
+ case 2: {
+ float g = fromFixedS1516(para->parameter[0]);
+ float a = fromFixedS1516(para->parameter[1]);
+ float b = fromFixedS1516(para->parameter[2]);
+ float c = fromFixedS1516(para->parameter[3]);
+ float d = -b / a;
+ qCDebug(lcIcc) << g << a << b << c;
+ gamma.m_type = QColorTrc::Type::Function;
+ gamma.m_fun = QColorTransferFunction(a, b, 0.0f, d, c, c, g);
+ break;
+ }
+ case 3: {
+ float g = fromFixedS1516(para->parameter[0]);
+ float a = fromFixedS1516(para->parameter[1]);
+ float b = fromFixedS1516(para->parameter[2]);
+ float c = fromFixedS1516(para->parameter[3]);
+ float d = fromFixedS1516(para->parameter[4]);
+ qCDebug(lcIcc) << g << a << b << c << d;
+ gamma.m_type = QColorTrc::Type::Function;
+ gamma.m_fun = QColorTransferFunction(a, b, c, d, 0.0f, 0.0f, g);
+ break;
+ }
+ case 4: {
+ float g = fromFixedS1516(para->parameter[0]);
+ float a = fromFixedS1516(para->parameter[1]);
+ float b = fromFixedS1516(para->parameter[2]);
+ float c = fromFixedS1516(para->parameter[3]);
+ float d = fromFixedS1516(para->parameter[4]);
+ float e = fromFixedS1516(para->parameter[5]);
+ float f = fromFixedS1516(para->parameter[6]);
+ qCDebug(lcIcc) << g << a << b << c << d << e << f;
+ gamma.m_type = QColorTrc::Type::Function;
+ gamma.m_fun = QColorTransferFunction(a, b, c, d, e, f, g);
+ break;
+ }
+ default:
+ qCWarning(lcIcc) << "Unknown para type" << uint(para->curveType);
+ return false;
+ }
+ return true;
+ }
+ qCWarning(lcIcc) << "Invalid TRC data type";
+ return false;
+}
+
+bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace)
+{
+ if (data.size() < qsizetype(sizeof(ICCProfileHeader))) {
+ qCWarning(lcIcc) << "fromIccProfile: failed size sanity 1";
+ return false;
+ }
+ const ICCProfileHeader *header = (const ICCProfileHeader *)data.constData();
+ if (!isValidIccProfile(*header)) {
+ qCWarning(lcIcc) << "fromIccProfile: failed general sanity check";
+ return false;
+ }
+ if (qsizetype(header->profileSize) > data.size()) {
+ qCWarning(lcIcc) << "fromIccProfile: failed size sanity 2";
+ return false;
+ }
+
+ // Read tag index
+ const TagTableEntry *tagTable = (const TagTableEntry *)(data.constData() + sizeof(ICCProfileHeader));
+ const qsizetype offsetToData = sizeof(ICCProfileHeader) + header->tagCount * sizeof(TagTableEntry);
+
+ QHash<Tag, quint32> tagIndex;
+ for (uint i = 0; i < header->tagCount; ++i) {
+ // Sanity check tag sizes and offsets:
+ if (qsizetype(tagTable[i].offset) < offsetToData) {
+ qCWarning(lcIcc) << "fromIccProfile: failed tag offset sanity 1";
+ return false;
+ }
+ // Checked separately from (+ size) to handle overflow.
+ if (tagTable[i].offset > header->profileSize) {
+ qCWarning(lcIcc) << "fromIccProfile: failed tag offset sanity 2";
+ return false;
+ }
+ if ((tagTable[i].offset + tagTable[i].size) > header->profileSize) {
+ qCWarning(lcIcc) << "fromIccProfile: failed tag offset + size sanity";
+ return false;
+ }
+// printf("'%4s' %d %d\n", (const char *)&tagTable[i].signature,
+// quint32(tagTable[i].offset),
+// quint32(tagTable[i].size));
+ tagIndex.insert(Tag(quint32(tagTable[i].signature)), tagTable[i].offset);
+ }
+ // Check the profile is three-component matrix based (what we currently support):
+ if (!tagIndex.contains(Tag::rXYZ) || !tagIndex.contains(Tag::gXYZ) || !tagIndex.contains(Tag::bXYZ) ||
+ !tagIndex.contains(Tag::rTRC) || !tagIndex.contains(Tag::gTRC) || !tagIndex.contains(Tag::bTRC) ||
+ !tagIndex.contains(Tag::wtpt)) {
+ qCWarning(lcIcc) << "fromIccProfile: Unsupported ICC profile - not three component matrix based";
+ return false;
+ }
+
+ // Parse XYZ tags
+ const XYZTagData *rXyz = (const XYZTagData *)(data.constData() + tagIndex[Tag::rXYZ]);
+ const XYZTagData *gXyz = (const XYZTagData *)(data.constData() + tagIndex[Tag::gXYZ]);
+ const XYZTagData *bXyz = (const XYZTagData *)(data.constData() + tagIndex[Tag::bXYZ]);
+ const XYZTagData *wXyz = (const XYZTagData *)(data.constData() + tagIndex[Tag::wtpt]);
+ if (rXyz->type != quint32(Tag::XYZ_) || gXyz->type != quint32(Tag::XYZ_) ||
+ wXyz->type != quint32(Tag::XYZ_) || wXyz->type != quint32(Tag::XYZ_)) {
+ qCWarning(lcIcc) << "fromIccProfile: Bad XYZ data type";
+ return false;
+ }
+ QColorSpacePrivate *colorspaceDPtr = colorSpace->d_func();
+
+ colorspaceDPtr->toXyz.r = fromXyzData(rXyz);
+ colorspaceDPtr->toXyz.g = fromXyzData(gXyz);
+ colorspaceDPtr->toXyz.b = fromXyzData(bXyz);
+ QColorVector whitePoint = fromXyzData(wXyz);
+ colorspaceDPtr->whitePoint = whitePoint;
+
+ colorspaceDPtr->gamut = QColorSpace::Gamut::Custom;
+ if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromSRgb()) {
+ qCDebug(lcIcc) << "fromIccProfile: sRGB gamut detected";
+ colorspaceDPtr->gamut = QColorSpace::Gamut::SRgb;
+ } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromAdobeRgb()) {
+ qCDebug(lcIcc) << "fromIccProfile: Adobe RGB gamut detected";
+ colorspaceDPtr->gamut = QColorSpace::Gamut::AdobeRgb;
+ } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromDciP3D65()) {
+ qCDebug(lcIcc) << "fromIccProfile: DCI-P3 D65 gamut detected";
+ colorspaceDPtr->gamut = QColorSpace::Gamut::DciP3D65;
+ } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromBt2020()) {
+ qCDebug(lcIcc) << "fromIccProfile: BT.2020 gamut detected";
+ colorspaceDPtr->gamut = QColorSpace::Gamut::Bt2020;
+ }
+ if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromProPhotoRgb()) {
+ qCDebug(lcIcc) << "fromIccProfile: ProPhoto RGB gamut detected";
+ colorspaceDPtr->gamut = QColorSpace::Gamut::ProPhotoRgb;
+ }
+ // Reset the matrix to our canonical values:
+ if (colorspaceDPtr->gamut != QColorSpace::Gamut::Custom)
+ colorspaceDPtr->setToXyzMatrix();
+
+ // Parse TRC tags
+ const GenericTagData *rTrc;
+ const GenericTagData *gTrc;
+ const GenericTagData *bTrc;
+ if (tagIndex.contains(Tag::aarg) && tagIndex.contains(Tag::aagg) && tagIndex.contains(Tag::aabg)) {
+ // Apple extension for parametric version of TRCs in ICCv2:
+ rTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::aarg]);
+ gTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::aagg]);
+ bTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::aabg]);
+ } else {
+ rTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::rTRC]);
+ gTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::gTRC]);
+ bTrc = (const GenericTagData *)(data.constData() + tagIndex[Tag::bTRC]);
+ }
+
+ QColorTrc rCurve;
+ QColorTrc gCurve;
+ QColorTrc bCurve;
+ if (!parseTRC(rTrc, rCurve))
+ return false;
+ if (!parseTRC(gTrc, gCurve))
+ return false;
+ if (!parseTRC(bTrc, bCurve))
+ return false;
+ if (rCurve == gCurve && gCurve == bCurve && rCurve.m_type == QColorTrc::Type::Function) {
+ if (rCurve.m_fun.isLinear()) {
+ qCDebug(lcIcc) << "fromIccProfile: Linear gamma detected";
+ colorspaceDPtr->trc[0] = QColorTransferFunction();
+ colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Linear;
+ colorspaceDPtr->gamma = 1.0f;
+ } else if (rCurve.m_fun.isGamma()) {
+ qCDebug(lcIcc) << "fromIccProfile: Simple gamma detected";
+ colorspaceDPtr->trc[0] = QColorTransferFunction::fromGamma(rCurve.m_fun.m_g);
+ colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Gamma;
+ colorspaceDPtr->gamma = rCurve.m_fun.m_g;
+ } else if (rCurve.m_fun.isSRgb()) {
+ qCDebug(lcIcc) << "fromIccProfile: sRGB gamma detected";
+ colorspaceDPtr->trc[0] = QColorTransferFunction::fromSRgb();
+ colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::SRgb;
+ } else {
+ colorspaceDPtr->trc[0] = rCurve;
+ colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Custom;
+ }
+
+ colorspaceDPtr->trc[1] = colorspaceDPtr->trc[0];
+ colorspaceDPtr->trc[2] = colorspaceDPtr->trc[0];
+ } else {
+ colorspaceDPtr->trc[0] = rCurve;
+ colorspaceDPtr->trc[1] = gCurve;
+ colorspaceDPtr->trc[2] = bCurve;
+ colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Custom;
+ }
+
+ // FIXME: try to parse the description..
+
+ if (!colorspaceDPtr->identifyColorSpace())
+ colorspaceDPtr->id = QColorSpace::Unknown;
+ else
+ qCDebug(lcIcc) << "fromIccProfile: Named colorspace detected: " << colorSpace->colorSpaceId();
+
+ colorspaceDPtr->iccProfile = data;
+
+ return true;
+}
+
+} // namespace QIcc
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qicc_p.h b/src/gui/painting/qicc_p.h
new file mode 100644
index 0000000000..c3220391f4
--- /dev/null
+++ b/src/gui/painting/qicc_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QICC_P_H
+#define QICC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qbytearray.h>
+#include <QtGui/qtguiglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QColorSpace;
+
+namespace QIcc {
+
+Q_GUI_EXPORT bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace);
+Q_GUI_EXPORT QByteArray toIccProfile(const QColorSpace &space);
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QICC_P_H
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 8a5274bd37..0d7205b483 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -528,6 +528,7 @@ static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *des
}
}
+#if QT_CONFIG(raster_64bit)
static void qt_qimageScaleRgba64_up_x_down_y(QImageScaleInfo *isi, QRgba64 *dest,
int dw, int dh, int dow, int sow);
@@ -728,6 +729,7 @@ static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
}
}
}
+#endif
static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
int dw, int dh, int dow, int sow);
@@ -945,10 +947,13 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
return QImage();
}
+#if QT_CONFIG(raster_64bit)
if (src.depth() > 32)
qt_qimageScaleRgba64(scaleinfo, (QRgba64 *)buffer.scanLine(0),
dw, dh, dw, src.bytesPerLine() / 8);
- else if (src.hasAlphaChannel())
+ else
+#endif
+ if (src.hasAlphaChannel())
qt_qimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
dw, dh, dw, src.bytesPerLine() / 4);
else
diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp
index 34d6b3882e..5861a2e2ff 100644
--- a/src/gui/painting/qimagescale_sse4.cpp
+++ b/src/gui/painting/qimagescale_sse4.cpp
@@ -39,6 +39,7 @@
#include "qimagescale_p.h"
#include "qimage.h"
+#include <private/qdrawhelper_x86_p.h>
#include <private/qsimd_p.h>
#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
@@ -47,7 +48,8 @@ QT_BEGIN_NAMESPACE
using namespace QImageScale;
-inline static __m128i qt_qimageScaleAARGBA_helper(const unsigned int *pix, int xyap, int Cxy, int step, const __m128i vxyap, const __m128i vCxy)
+inline static __m128i Q_DECL_VECTORCALL
+qt_qimageScaleAARGBA_helper(const unsigned int *pix, int xyap, int Cxy, int step, const __m128i vxyap, const __m128i vCxy)
{
__m128i vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
__m128i vx = _mm_mullo_epi32(vpix, vxyap);
diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp
index 24b33243da..b1f01332b6 100644
--- a/src/gui/painting/qmatrix.cpp
+++ b/src/gui/painting/qmatrix.cpp
@@ -248,7 +248,7 @@ QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
/*!
Constructs a matrix that is a copy of the given \a matrix.
*/
-QMatrix::QMatrix(const QMatrix &matrix) Q_DECL_NOTHROW
+QMatrix::QMatrix(const QMatrix &matrix) noexcept
: _m11(matrix._m11)
, _m12(matrix._m12)
, _m21(matrix._m21)
@@ -989,7 +989,7 @@ bool QMatrix::operator==(const QMatrix &m) const
Returns the hash value for \a key, using
\a seed to seed the calculation.
*/
-uint qHash(const QMatrix &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QMatrix &key, uint seed) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.m11());
@@ -1068,7 +1068,7 @@ QMatrix QMatrix::operator *(const QMatrix &m) const
/*!
Assigns the given \a matrix's values to this matrix.
*/
-QMatrix &QMatrix::operator=(const QMatrix &matrix) Q_DECL_NOTHROW
+QMatrix &QMatrix::operator=(const QMatrix &matrix) noexcept
{
_m11 = matrix._m11;
_m12 = matrix._m12;
diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h
index d8a4fcfb1c..a167260ade 100644
--- a/src/gui/painting/qmatrix.h
+++ b/src/gui/painting/qmatrix.h
@@ -64,12 +64,12 @@ public:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
// ### Qt 6: remove; the compiler-generated ones are fine!
- QMatrix &operator=(QMatrix &&other) Q_DECL_NOTHROW // = default
+ QMatrix &operator=(QMatrix &&other) noexcept // = default
{ memcpy(static_cast<void *>(this), static_cast<void *>(&other), sizeof(QMatrix)); return *this; }
- QMatrix &operator=(const QMatrix &) Q_DECL_NOTHROW; // = default
- QMatrix(QMatrix &&other) Q_DECL_NOTHROW // = default
+ QMatrix &operator=(const QMatrix &) noexcept; // = default
+ QMatrix(QMatrix &&other) noexcept // = default
{ memcpy(static_cast<void *>(this), static_cast<void *>(&other), sizeof(QMatrix)); }
- QMatrix(const QMatrix &other) Q_DECL_NOTHROW; // = default
+ QMatrix(const QMatrix &other) noexcept; // = default
#endif
void setMatrix(qreal m11, qreal m12, qreal m21, qreal m22,
@@ -140,7 +140,7 @@ private:
};
Q_DECLARE_TYPEINFO(QMatrix, Q_MOVABLE_TYPE);
-Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QMatrix &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QMatrix &key, uint seed = 0) noexcept;
// mathematical semantics
inline QPoint operator*(const QPoint &p, const QMatrix &m)
diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp
index 43aeff3268..9cb787fb2c 100644
--- a/src/gui/painting/qmemrotate.cpp
+++ b/src/gui/painting/qmemrotate.cpp
@@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
static const int tileSize = 32;
template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
+static
inline void qt_memrotate90_tiled(const T *src, int w, int h, int sstride, T *dest, int dstride)
{
sstride /= sizeof(T);
@@ -103,7 +103,7 @@ inline void qt_memrotate90_tiled(const T *src, int w, int h, int sstride, T *des
}
template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
+static
inline void qt_memrotate90_tiled_unpacked(const T *src, int w, int h, int sstride, T *dest,
int dstride)
{
@@ -131,7 +131,7 @@ inline void qt_memrotate90_tiled_unpacked(const T *src, int w, int h, int sstrid
}
template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
+static
inline void qt_memrotate270_tiled(const T *src, int w, int h, int sstride, T *dest, int dstride)
{
sstride /= sizeof(T);
@@ -190,7 +190,7 @@ inline void qt_memrotate270_tiled(const T *src, int w, int h, int sstride, T *de
}
template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
+static
inline void qt_memrotate270_tiled_unpacked(const T *src, int w, int h, int sstride, T *dest,
int dstride)
{
@@ -219,7 +219,7 @@ inline void qt_memrotate270_tiled_unpacked(const T *src, int w, int h, int sstri
template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
+static
inline void qt_memrotate90_template(const T *src, int srcWidth, int srcHeight, int srcStride,
T *dest, int dstStride)
{
@@ -246,7 +246,7 @@ inline void qt_memrotate90_template<quint64>(const quint64 *src, int w, int h, i
}
template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
+static
inline void qt_memrotate180_template(const T *src, int w, int h, int sstride, T *dest, int dstride)
{
const char *s = (const char*)(src) + (h - 1) * sstride;
@@ -261,7 +261,7 @@ inline void qt_memrotate180_template(const T *src, int w, int h, int sstride, T
}
template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
+static
inline void qt_memrotate270_template(const T *src, int srcWidth, int srcHeight, int srcStride,
T *dest, int dstStride)
{
diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index b2d02182c3..2074f98069 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -42,6 +42,7 @@
#include "qbezier_p.h"
#include "qmath.h"
#include "qpainterpath_p.h"
+#include "qscopedvaluerollback.h"
#include <stdlib.h>
@@ -354,7 +355,7 @@ void QOutlineMapper::clipElements(const QPointF *elements,
// instead of going through convenience functionallity, but since
// this part of code hardly every used, it shouldn't matter.
- m_in_clip_elements = true;
+ QScopedValueRollback<bool> in_clip_elements(m_in_clip_elements, true);
QPainterPath path;
@@ -397,8 +398,6 @@ void QOutlineMapper::clipElements(const QPointF *elements,
convertPath(clippedPath);
m_transform = oldTransform;
}
-
- m_in_clip_elements = false;
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qoutlinemapper_p.h b/src/gui/painting/qoutlinemapper_p.h
index 71999fbdee..04a68797c2 100644
--- a/src/gui/painting/qoutlinemapper_p.h
+++ b/src/gui/painting/qoutlinemapper_p.h
@@ -180,13 +180,13 @@ public:
QT_FT_Outline *outline() {
if (m_valid)
return &m_outline;
- return 0;
+ return nullptr;
}
QT_FT_Outline *convertPath(const QPainterPath &path);
QT_FT_Outline *convertPath(const QVectorPath &path);
- inline QPainterPath::ElementType *elementTypes() const { return m_element_types.size() == 0 ? 0 : m_element_types.data(); }
+ inline QPainterPath::ElementType *elementTypes() const { return m_element_types.size() == 0 ? nullptr : m_element_types.data(); }
public:
QDataBuffer<QPainterPath::ElementType> m_element_types;
diff --git a/src/gui/painting/qpagelayout.h b/src/gui/painting/qpagelayout.h
index b41689d33b..7ee0ce7a76 100644
--- a/src/gui/painting/qpagelayout.h
+++ b/src/gui/painting/qpagelayout.h
@@ -82,13 +82,11 @@ public:
const QMarginsF &margins, Unit units = Point,
const QMarginsF &minMargins = QMarginsF(0, 0, 0, 0));
QPageLayout(const QPageLayout &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QPageLayout &operator=(QPageLayout &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QPageLayout &operator=(QPageLayout &&other) noexcept { swap(other); return *this; }
QPageLayout &operator=(const QPageLayout &other);
~QPageLayout();
- void swap(QPageLayout &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QPageLayout &other) noexcept { qSwap(d, other.d); }
friend Q_GUI_EXPORT bool operator==(const QPageLayout &lhs, const QPageLayout &rhs);
bool isEquivalentTo(const QPageLayout &other) const;
diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h
index 82054824b4..133274760f 100644
--- a/src/gui/painting/qpagesize.h
+++ b/src/gui/painting/qpagesize.h
@@ -236,14 +236,12 @@ public:
const QString &name = QString(),
SizeMatchPolicy matchPolicy = FuzzyMatch);
QPageSize(const QPageSize &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QPageSize &operator=(QPageSize &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QPageSize &operator=(QPageSize &&other) noexcept { swap(other); return *this; }
QPageSize &operator=(const QPageSize &other);
~QPageSize();
- void swap(QPageSize &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QPageSize &other) noexcept { qSwap(d, other.d); }
friend Q_GUI_EXPORT bool operator==(const QPageSize &lhs, const QPageSize &rhs);
bool isEquivalentTo(const QPageSize &other) const;
diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp
index faaa316085..0ddfba6ee9 100644
--- a/src/gui/painting/qpaintdevice.cpp
+++ b/src/gui/painting/qpaintdevice.cpp
@@ -41,7 +41,7 @@
QT_BEGIN_NAMESPACE
-QPaintDevice::QPaintDevice() Q_DECL_NOEXCEPT
+QPaintDevice::QPaintDevice() noexcept
{
reserved = 0;
painters = 0;
diff --git a/src/gui/painting/qpaintdevice.h b/src/gui/painting/qpaintdevice.h
index 9458b4ba9a..5f8dad205d 100644
--- a/src/gui/painting/qpaintdevice.h
+++ b/src/gui/painting/qpaintdevice.h
@@ -90,7 +90,7 @@ public:
static inline qreal devicePixelRatioFScale() { return 0x10000; }
protected:
- QPaintDevice() Q_DECL_NOEXCEPT;
+ QPaintDevice() noexcept;
virtual int metric(PaintDeviceMetric metric) const;
virtual void initPainter(QPainter *painter) const;
virtual QPaintDevice *redirected(QPoint *offset) const;
diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h
index 8ac3fcff5c..40b9474165 100644
--- a/src/gui/painting/qpaintengine_p.h
+++ b/src/gui/painting/qpaintengine_p.h
@@ -65,7 +65,7 @@ class Q_GUI_EXPORT QPaintEnginePrivate
{
Q_DECLARE_PUBLIC(QPaintEngine)
public:
- QPaintEnginePrivate() : pdev(0), q_ptr(0), currentClipDevice(0), hasSystemTransform(0),
+ QPaintEnginePrivate() : pdev(nullptr), q_ptr(nullptr), currentClipDevice(nullptr), hasSystemTransform(0),
hasSystemViewport(0) {}
virtual ~QPaintEnginePrivate();
@@ -138,8 +138,8 @@ public:
static QPaintEnginePrivate *get(QPaintEngine *paintEngine) { return paintEngine->d_func(); }
- virtual QPaintEngine *aggregateEngine() { return 0; }
- virtual Qt::HANDLE nativeHandle() { return 0; }
+ virtual QPaintEngine *aggregateEngine() { return nullptr; }
+ virtual Qt::HANDLE nativeHandle() { return nullptr; }
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 76c5842f58..64183c2be6 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -555,35 +555,6 @@ bool QRasterPaintEngine::end()
/*!
\internal
*/
-void QRasterPaintEngine::releaseBuffer()
-{
- Q_D(QRasterPaintEngine);
- d->rasterBuffer.reset(new QRasterBuffer);
-}
-
-/*!
- \internal
-*/
-QSize QRasterPaintEngine::size() const
-{
- Q_D(const QRasterPaintEngine);
- return QSize(d->rasterBuffer->width(), d->rasterBuffer->height());
-}
-
-/*!
- \internal
-*/
-#ifndef QT_NO_DEBUG
-void QRasterPaintEngine::saveBuffer(const QString &s) const
-{
- Q_D(const QRasterPaintEngine);
- d->rasterBuffer->bufferImage().save(s, "PNG");
-}
-#endif
-
-/*!
- \internal
-*/
void QRasterPaintEngine::updateMatrix(const QTransform &matrix)
{
QRasterPaintEngineState *s = state();
@@ -873,7 +844,7 @@ void QRasterPaintEngine::updateRasterState()
&& s->intOpacity == 256
&& (mode == QPainter::CompositionMode_Source
|| (mode == QPainter::CompositionMode_SourceOver
- && s->penData.solid.color.isOpaque()));
+ && s->penData.solidColor.isOpaque()));
}
s->dirty = 0;
@@ -927,7 +898,7 @@ void QRasterPaintEngine::renderHintsChanged()
QRasterPaintEngineState *s = state();
#ifdef QT_DEBUG_DRAW
- qDebug() << "QRasterPaintEngine::renderHintsChanged()" << hex << s->renderHints;
+ qDebug() << "QRasterPaintEngine::renderHintsChanged()" << Qt::hex << s->renderHints;
#endif
bool was_aa = s->flags.antialiased;
@@ -1536,9 +1507,9 @@ static void fillRect_normalized(const QRect &r, QSpanData *data,
if (data->fillRect && (mode == QPainter::CompositionMode_Source
|| (mode == QPainter::CompositionMode_SourceOver
- && data->solid.color.isOpaque())))
+ && data->solidColor.isOpaque())))
{
- data->fillRect(data->rasterBuffer, x1, y1, width, height, data->solid.color);
+ data->fillRect(data->rasterBuffer, x1, y1, width, height, data->solidColor);
return;
}
}
@@ -1774,7 +1745,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
QRectF rf = path.controlPointRect();
qDebug() << "QRasterPaintEngine::fill(): "
<< "size=" << path.elementCount()
- << ", hints=" << hex << path.hints()
+ << ", hints=" << Qt::hex << path.hints()
<< rf << brush;
#endif
@@ -1900,9 +1871,9 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color)
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
- d->solid_color_filler.solid.color = qPremultiply(combineAlpha256(color.rgba64(), s->intOpacity));
+ d->solid_color_filler.solidColor = qPremultiply(combineAlpha256(color.rgba64(), s->intOpacity));
- if (d->solid_color_filler.solid.color.isTransparent()
+ if (d->solid_color_filler.solidColor.isTransparent()
&& s->composition_mode == QPainter::CompositionMode_SourceOver) {
return;
}
@@ -2356,14 +2327,14 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
case QImage::Format_A2BGR30_Premultiplied:
case QImage::Format_A2RGB30_Premultiplied:
// Combine premultiplied color with the opacity set on the painter.
- d->solid_color_filler.solid.color = multiplyAlpha256(QRgba64::fromArgb32(color), s->intOpacity);
+ d->solid_color_filler.solidColor = multiplyAlpha256(QRgba64::fromArgb32(color), s->intOpacity);
break;
default:
- d->solid_color_filler.solid.color = qPremultiply(combineAlpha256(QRgba64::fromArgb32(color), s->intOpacity));
+ d->solid_color_filler.solidColor = qPremultiply(combineAlpha256(QRgba64::fromArgb32(color), s->intOpacity));
break;
}
- if (d->solid_color_filler.solid.color.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver)
+ if (d->solid_color_filler.solidColor.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver)
return;
d->solid_color_filler.clip = d->clip();
@@ -2713,20 +2684,20 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
if (unclipped) {
if (depth == 1) {
if (s->penData.bitmapBlit) {
- s->penData.bitmapBlit(rb, rx, ry, s->penData.solid.color,
+ s->penData.bitmapBlit(rb, rx, ry, s->penData.solidColor,
scanline, w, h, bpl);
return;
}
} else if (depth == 8) {
if (s->penData.alphamapBlit) {
- s->penData.alphamapBlit(rb, rx, ry, s->penData.solid.color,
+ s->penData.alphamapBlit(rb, rx, ry, s->penData.solidColor,
scanline, w, h, bpl, 0, useGammaCorrection);
return;
}
} else if (depth == 32) {
// (A)RGB Alpha mask where the alpha component is not used.
if (s->penData.alphaRGBBlit) {
- s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solid.color,
+ s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solidColor,
(const uint *) scanline, w, h, bpl / 4, 0, useGammaCorrection);
return;
}
@@ -2755,10 +2726,10 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
ry = ny;
}
if (depth == 8)
- s->penData.alphamapBlit(rb, rx, ry, s->penData.solid.color,
+ s->penData.alphamapBlit(rb, rx, ry, s->penData.solidColor,
scanline, w, h, bpl, clip, useGammaCorrection);
else if (depth == 32)
- s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solid.color,
+ s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solidColor,
(const uint *) scanline, w, h, bpl / 4, clip, useGammaCorrection);
return;
}
@@ -3436,7 +3407,7 @@ bool QRasterPaintEngine::requiresPretransformedGlyphPositions(QFontEngine *fontE
}
/*!
- Indicates whether glyph caching is supported by the font engine
+ Returns whether glyph caching is supported by the font engine
\a fontEngine with the given transform \a m applied.
*/
bool QRasterPaintEngine::shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &m) const
@@ -3835,7 +3806,6 @@ QImage::Format QRasterBuffer::prepare(QImage *image)
bytes_per_line = image->bytesPerLine();
format = image->format();
- drawHelper = qDrawHelper + format;
if (image->depth() == 1 && image->colorTable().size() == 2) {
monoDestinationWithClut = true;
const QVector<QRgb> colorTable = image->colorTable();
@@ -3846,11 +3816,6 @@ QImage::Format QRasterBuffer::prepare(QImage *image)
return format;
}
-void QRasterBuffer::resetBuffer(int val)
-{
- memset(m_buffer, val, m_height*bytes_per_line);
-}
-
QClipData::QClipData(int height)
{
clipSpanHeight = height;
@@ -3883,51 +3848,15 @@ void QClipData::initialize()
Q_CHECK_PTR(m_clipLines);
QT_TRY {
- m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan));
allocated = clipSpanHeight;
- Q_CHECK_PTR(m_spans);
-
QT_TRY {
- if (hasRectClip) {
- int y = 0;
- while (y < ymin) {
- m_clipLines[y].spans = 0;
- m_clipLines[y].count = 0;
- ++y;
- }
-
- const int len = clipRect.width();
- count = 0;
- while (y < ymax) {
- QSpan *span = m_spans + count;
- span->x = xmin;
- span->len = len;
- span->y = y;
- span->coverage = 255;
- ++count;
-
- m_clipLines[y].spans = span;
- m_clipLines[y].count = 1;
- ++y;
- }
-
- while (y < clipSpanHeight) {
- m_clipLines[y].spans = 0;
- m_clipLines[y].count = 0;
- ++y;
- }
- } else if (hasRegionClip) {
-
+ if (hasRegionClip) {
const auto rects = clipRegion.begin();
const int numRects = clipRegion.rectCount();
-
- { // resize
- const int maxSpans = (ymax - ymin) * numRects;
- if (maxSpans > allocated) {
- m_spans = q_check_ptr((QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan)));
- allocated = maxSpans;
- }
- }
+ const int maxSpans = (ymax - ymin) * numRects;
+ allocated = qMax(allocated, maxSpans);
+ m_spans = (QSpan *)malloc(allocated * sizeof(QSpan));
+ Q_CHECK_PTR(m_spans);
int y = 0;
int firstInBand = 0;
@@ -3974,6 +3903,40 @@ void QClipData::initialize()
++y;
}
+ return;
+ }
+
+ m_spans = (QSpan *)malloc(allocated * sizeof(QSpan));
+ Q_CHECK_PTR(m_spans);
+
+ if (hasRectClip) {
+ int y = 0;
+ while (y < ymin) {
+ m_clipLines[y].spans = 0;
+ m_clipLines[y].count = 0;
+ ++y;
+ }
+
+ const int len = clipRect.width();
+ count = 0;
+ while (y < ymax) {
+ QSpan *span = m_spans + count;
+ span->x = xmin;
+ span->len = len;
+ span->y = y;
+ span->coverage = 255;
+ ++count;
+
+ m_clipLines[y].spans = span;
+ m_clipLines[y].count = 1;
+ ++y;
+ }
+
+ while (y < clipSpanHeight) {
+ m_clipLines[y].spans = 0;
+ m_clipLines[y].count = 0;
+ ++y;
+ }
}
} QT_CATCH(...) {
free(m_spans); // have to free m_spans again or someone might think that we were successfully initialized.
@@ -4279,55 +4242,13 @@ static void qt_span_clip(int count, const QSpan *spans, void *userData)
}
}
-#ifndef QT_NO_DEBUG
-QImage QRasterBuffer::bufferImage() const
-{
- QImage image(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
-
- for (int y = 0; y < m_height; ++y) {
- uint *span = (uint *)const_cast<QRasterBuffer *>(this)->scanLine(y);
-
- for (int x=0; x<m_width; ++x) {
- uint argb = span[x];
- image.setPixel(x, y, argb);
- }
- }
- return image;
-}
-#endif
-
-
-void QRasterBuffer::flushToARGBImage(QImage *target) const
-{
- int w = qMin(m_width, target->width());
- int h = qMin(m_height, target->height());
-
- for (int y=0; y<h; ++y) {
- uint *sourceLine = (uint *)const_cast<QRasterBuffer *>(this)->scanLine(y);
- QRgb *dest = (QRgb *) target->scanLine(y);
- for (int x=0; x<w; ++x) {
- QRgb pixel = sourceLine[x];
- int alpha = qAlpha(pixel);
- if (!alpha) {
- dest[x] = 0;
- } else {
- dest[x] = (alpha << 24)
- | ((255*qRed(pixel)/alpha) << 16)
- | ((255*qGreen(pixel)/alpha) << 8)
- | ((255*qBlue(pixel)/alpha) << 0);
- }
- }
- }
-}
-
-
class QGradientCache
{
public:
struct CacheInfo : QSpanData::Pinnable
{
inline CacheInfo(QGradientStops s, int op, QGradient::InterpolationMode mode) :
- stops(qMove(s)), opacity(op), interpolationMode(mode) {}
+ stops(std::move(s)), opacity(op), interpolationMode(mode) {}
QRgba64 buffer64[GRADIENT_STOPTABLE_SIZE];
QRgb buffer32[GRADIENT_STOPTABLE_SIZE];
QGradientStops stops;
@@ -4600,8 +4521,8 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
case Qt::SolidPattern: {
type = Solid;
QColor c = qbrush_color(brush);
- solid.color = qPremultiply(combineAlpha256(c.rgba64(), alpha));
- if (solid.color.isTransparent() && compositionMode == QPainter::CompositionMode_SourceOver)
+ solidColor = qPremultiply(combineAlpha256(c.rgba64(), alpha));
+ if (solidColor.isTransparent() && compositionMode == QPainter::CompositionMode_SourceOver)
type = None;
break;
}
@@ -4614,7 +4535,9 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
auto cacheInfo = qt_gradient_cache()->getBuffer(*g, alpha);
gradient.colorTable32 = cacheInfo->buffer32;
+#if QT_CONFIG(raster_64bit)
gradient.colorTable64 = cacheInfo->buffer64;
+#endif
cachedGradient = std::move(cacheInfo);
gradient.spread = g->spread();
@@ -4636,7 +4559,9 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
auto cacheInfo = qt_gradient_cache()->getBuffer(*g, alpha);
gradient.colorTable32 = cacheInfo->buffer32;
+#if QT_CONFIG(raster_64bit)
gradient.colorTable64 = cacheInfo->buffer64;
+#endif
cachedGradient = std::move(cacheInfo);
gradient.spread = g->spread();
@@ -4662,7 +4587,9 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
auto cacheInfo = qt_gradient_cache()->getBuffer(*g, alpha);
gradient.colorTable32 = cacheInfo->buffer32;
+#if QT_CONFIG(raster_64bit)
gradient.colorTable64 = cacheInfo->buffer64;
+#endif
cachedGradient = std::move(cacheInfo);
gradient.spread = QGradient::RepeatSpread;
@@ -4727,17 +4654,19 @@ void QSpanData::adjustSpanMethods()
case None:
unclipped_blend = 0;
break;
- case Solid:
- unclipped_blend = rasterBuffer->drawHelper->blendColor;
- bitmapBlit = rasterBuffer->drawHelper->bitmapBlit;
- alphamapBlit = rasterBuffer->drawHelper->alphamapBlit;
- alphaRGBBlit = rasterBuffer->drawHelper->alphaRGBBlit;
- fillRect = rasterBuffer->drawHelper->fillRect;
+ case Solid: {
+ const DrawHelper &drawHelper = qDrawHelper[rasterBuffer->format];
+ unclipped_blend = drawHelper.blendColor;
+ bitmapBlit = drawHelper.bitmapBlit;
+ alphamapBlit = drawHelper.alphamapBlit;
+ alphaRGBBlit = drawHelper.alphaRGBBlit;
+ fillRect = drawHelper.fillRect;
break;
+ }
case LinearGradient:
case RadialGradient:
case ConicalGradient:
- unclipped_blend = rasterBuffer->drawHelper->blendGradient;
+ unclipped_blend = qBlendGradient;
break;
case Texture:
unclipped_blend = qBlendTexture;
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 6132366936..ec4a35087a 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -208,15 +208,6 @@ public:
ClipType clipType() const;
QRect clipBoundingRect() const;
- void releaseBuffer();
-
- QSize size() const;
-
-#ifndef QT_NO_DEBUG
- void saveBuffer(const QString &s) const;
-#endif
-
-
#ifdef Q_OS_WIN
void setDC(HDC hdc);
HDC getDC() const;
@@ -435,27 +426,16 @@ inline void QClipData::appendSpans(const QSpan *s, int num)
class QRasterBuffer
{
public:
- QRasterBuffer() : m_width(0), m_height(0), m_buffer(0) { init(); }
+ QRasterBuffer() : m_width(0), m_height(0), m_buffer(nullptr) { init(); }
~QRasterBuffer();
void init();
QImage::Format prepare(QImage *image);
- QImage::Format prepare(QPixmap *pix);
- void prepare(int w, int h);
- void prepareBuffer(int w, int h);
-
- void resetBuffer(int val=0);
uchar *scanLine(int y) { Q_ASSERT(y>=0); Q_ASSERT(y<m_height); return m_buffer + y * qsizetype(bytes_per_line); }
-#ifndef QT_NO_DEBUG
- QImage bufferImage() const;
-#endif
-
- void flushToARGBImage(QImage *image) const;
-
int width() const { return m_width; }
int height() const { return m_height; }
int bytesPerLine() const { return bytes_per_line; }
@@ -471,7 +451,6 @@ public:
QPainter::CompositionMode compositionMode;
QImage::Format format;
- DrawHelper *drawHelper;
QImage colorizeBitmap(const QImage &image, const QColor &color);
private:
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index f4cbf15fc7..8314e8bc8a 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -140,7 +140,7 @@ QDebug Q_GUI_EXPORT &operator<<(QDebug &s, const QVectorPath &path)
QDebugStateSaver saver(s);
QRectF rf = path.controlPointRect();
s << "QVectorPath(size:" << path.elementCount()
- << " hints:" << hex << path.hints()
+ << " hints:" << Qt::hex << path.hints()
<< rf << ')';
return s;
}
@@ -439,6 +439,9 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
}
}
+ if (d->activeStroker == &d->stroker)
+ d->stroker.setForceOpen(path.hasExplicitOpen());
+
const QPainterPath::ElementType *types = path.elements();
const qreal *points = path.points();
int pointCount = path.elementCount();
@@ -1097,7 +1100,7 @@ bool QPaintEngineEx::shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTran
}(), 2);
qreal pixelSize = fontEngine->fontDef.pixelSize;
- return (pixelSize * pixelSize * qAbs(m.determinant())) < maxCachedGlyphSizeSquared;
+ return (pixelSize * pixelSize * qAbs(m.determinant())) <= maxCachedGlyphSizeSquared;
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index b70b29e54e..84b34e390b 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -283,7 +283,7 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
Q_ASSERT(q->d_ptr->state);
// Now initialize the painter with correct widget properties.
- q->initFrom(pdev);
+ q->d_ptr->initFrom(pdev);
QPoint offset;
pdev->redirected(&offset);
offset += q->d_ptr->engine->coordinateOffset();
@@ -1437,6 +1437,13 @@ void QPainterPrivate::updateState(QPainterState *newState)
by slightly less than half a pixel. Also will treat default constructed pens
as cosmetic. Potentially useful when porting a Qt 4 application to Qt 5.
+ \value LosslessImageRendering Use a lossless image rendering, whenever possible.
+ Currently, this hint is only used when QPainter is employed to output a PDF
+ file through QPrinter or QPdfWriter, where drawImage()/drawPixmap() calls
+ will encode images using a lossless compression algorithm instead of lossy
+ JPEG compression.
+ This value was added in Qt 5.13.
+
\sa renderHints(), setRenderHint(), {QPainter#Rendering
Quality}{Rendering Quality}, {Concentric Circles Example}
@@ -1514,7 +1521,7 @@ QPainter::~QPainter()
/*!
Returns the paint device on which this painter is currently
- painting, or 0 if the painter is not active.
+ painting, or \nullptr if the painter is not active.
\sa isActive()
*/
@@ -1540,6 +1547,7 @@ bool QPainter::isActive() const
return d->engine;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
Initializes the painters pen, background and font to the same as
the given \a device.
@@ -1552,23 +1560,29 @@ void QPainter::initFrom(const QPaintDevice *device)
{
Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
Q_D(QPainter);
- if (!d->engine) {
+ d->initFrom(device);
+}
+#endif
+
+void QPainterPrivate::initFrom(const QPaintDevice *device)
+{
+ if (!engine) {
qWarning("QPainter::initFrom: Painter not active, aborted");
return;
}
- device->initPainter(this);
+ Q_Q(QPainter);
+ device->initPainter(q);
- if (d->extended) {
- d->extended->penChanged();
- } else if (d->engine) {
- d->engine->setDirty(QPaintEngine::DirtyPen);
- d->engine->setDirty(QPaintEngine::DirtyBrush);
- d->engine->setDirty(QPaintEngine::DirtyFont);
+ if (extended) {
+ extended->penChanged();
+ } else if (engine) {
+ engine->setDirty(QPaintEngine::DirtyPen);
+ engine->setDirty(QPaintEngine::DirtyBrush);
+ engine->setDirty(QPaintEngine::DirtyFont);
}
}
-
/*!
Saves the current painter state (pushes the state onto a stack). A
save() must be followed by a corresponding restore(); the end()
@@ -1835,7 +1849,7 @@ bool QPainter::begin(QPaintDevice *pd)
// Copy painter properties from original paint device,
// required for QPixmap::grabWidget()
if (d->original_device->devType() == QInternal::Widget) {
- initFrom(d->original_device);
+ d->initFrom(d->original_device);
} else {
d->state->layoutDirection = Qt::LayoutDirectionAuto;
// make sure we have a font compatible with the paintdevice
@@ -2878,6 +2892,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
d->updateState(d->state);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\since 4.2
\obsolete
@@ -2972,7 +2987,10 @@ void QPainter::setMatrix(const QMatrix &matrix, bool combine)
const QMatrix &QPainter::matrix() const
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return worldMatrix();
+QT_WARNING_POP
}
@@ -3041,7 +3059,7 @@ void QPainter::resetMatrix()
{
resetTransform();
}
-
+#endif
/*!
\since 4.2
@@ -3092,6 +3110,7 @@ bool QPainter::worldMatrixEnabled() const
return d->state->WxF;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -3117,6 +3136,7 @@ bool QPainter::matrixEnabled() const
{
return worldMatrixEnabled();
}
+#endif
/*!
Scales the coordinate system by (\a{sx}, \a{sy}).
@@ -4175,6 +4195,7 @@ void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius,
Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -4202,6 +4223,10 @@ void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
Draws the rectangle \a r with rounded corners.
*/
+void QPainter::drawRoundRect(const QRect &rect, int xRnd, int yRnd)
+{
+ drawRoundedRect(QRectF(rect), xRnd, yRnd, Qt::RelativeSize);
+}
/*!
\obsolete
@@ -4212,6 +4237,11 @@ void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
*/
+void QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
+{
+ drawRoundedRect(QRectF(x, y, w, h), xRnd, yRnd, Qt::RelativeSize);
+}
+#endif
/*!
\fn void QPainter::drawEllipse(const QRectF &rectangle)
@@ -6203,7 +6233,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
% HexString<qreal>(pen.widthF());
QPixmap pixmap;
- if (QPixmapCache::find(key, pixmap))
+ if (QPixmapCache::find(key, &pixmap))
return pixmap;
const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
@@ -7371,6 +7401,7 @@ void QPainter::setViewTransformEnabled(bool enable)
d->updateMatrix();
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\threadsafe
@@ -7451,6 +7482,7 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
Q_UNUSED(offset)
return 0;
}
+#endif
void qt_format_text(const QFont &fnt, const QRectF &_r,
int tf, const QString& str, QRectF *brect,
@@ -8060,6 +8092,7 @@ QFont QPaintEngineState::font() const
return static_cast<const QPainterState *>(this)->font;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\since 4.2
\obsolete
@@ -8082,6 +8115,7 @@ QMatrix QPaintEngineState::matrix() const
return st->matrix.toAffine();
}
+#endif
/*!
\since 4.3
@@ -8321,7 +8355,7 @@ void QPainter::resetTransform()
d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
d->state->worldMatrix = QTransform();
- setMatrixEnabled(false);
+ setWorldMatrixEnabled(false);
setViewTransformEnabled(false);
if (d->extended)
d->extended->transformChanged();
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index 482f5fb63d..843f24e3e1 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -91,7 +91,8 @@ public:
SmoothPixmapTransform = 0x04,
HighQualityAntialiasing = 0x08,
NonCosmeticDefaultPen = 0x10,
- Qt4CompatiblePainting = 0x20
+ Qt4CompatiblePainting = 0x20,
+ LosslessImageRendering = 0x40,
};
Q_FLAG(RenderHint)
@@ -131,7 +132,10 @@ public:
bool end();
bool isActive() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use begin(QPaintDevice*) instead")
void initFrom(const QPaintDevice *device);
+#endif
enum CompositionMode {
CompositionMode_SourceOver,
@@ -231,28 +235,40 @@ public:
void restore();
// XForm functions
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use setTransform() instead")
void setMatrix(const QMatrix &matrix, bool combine = false);
+ QT_DEPRECATED_X("Use transform() instead")
const QMatrix &matrix() const;
+ QT_DEPRECATED_X("Use deviceTransform() instead")
const QMatrix &deviceMatrix() const;
+ QT_DEPRECATED_X("Use resetTransform() instead")
void resetMatrix();
+#endif
void setTransform(const QTransform &transform, bool combine = false);
const QTransform &transform() const;
const QTransform &deviceTransform() const;
void resetTransform();
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use setWorldTransform() instead")
void setWorldMatrix(const QMatrix &matrix, bool combine = false);
+ QT_DEPRECATED_X("Use worldTransform() instead")
const QMatrix &worldMatrix() const;
+ QT_DEPRECATED_X("Use combinedTransform() instead")
+ QMatrix combinedMatrix() const;
+ QT_DEPRECATED_X("Use setWorldMatrixEnabled() instead")
+ void setMatrixEnabled(bool enabled);
+ QT_DEPRECATED_X("Use worldMatrixEnabled() instead")
+ bool matrixEnabled() const;
+#endif
void setWorldTransform(const QTransform &matrix, bool combine = false);
const QTransform &worldTransform() const;
- QMatrix combinedMatrix() const;
QTransform combinedTransform() const;
- void setMatrixEnabled(bool enabled);
- bool matrixEnabled() const;
-
void setWorldMatrixEnabled(bool enabled);
bool worldMatrixEnabled() const;
@@ -354,9 +370,14 @@ public:
inline void drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
Qt::SizeMode mode = Qt::AbsoluteSize);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use drawRoundedRect(..., Qt::RelativeSize) instead")
void drawRoundRect(const QRectF &r, int xround = 25, int yround = 25);
- inline void drawRoundRect(int x, int y, int w, int h, int = 25, int = 25);
- inline void drawRoundRect(const QRect &r, int xround = 25, int yround = 25);
+ QT_DEPRECATED_X("Use drawRoundedRect(..., Qt::RelativeSize) instead")
+ void drawRoundRect(int x, int y, int w, int h, int = 25, int = 25);
+ QT_DEPRECATED_X("Use drawRoundedRect(..., Qt::RelativeSize) instead")
+ void drawRoundRect(const QRect &r, int xround = 25, int yround = 25);
+#endif
void drawTiledPixmap(const QRectF &rect, const QPixmap &pm, const QPointF &offset = QPointF());
inline void drawTiledPixmap(int x, int y, int w, int h, const QPixmap &, int sx=0, int sy=0);
@@ -463,10 +484,15 @@ public:
QPaintEngine *paintEngine() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QWidget::render() instead")
static void setRedirected(const QPaintDevice *device, QPaintDevice *replacement,
const QPoint& offset = QPoint());
+ QT_DEPRECATED_X("Use QWidget::render() instead")
static QPaintDevice *redirected(const QPaintDevice *device, QPoint *offset = nullptr);
+ QT_DEPRECATED_X("Use QWidget::render() instead")
static void restoreRedirected(const QPaintDevice *device);
+#endif
void beginNativePainting();
void endNativePainting();
@@ -628,16 +654,6 @@ inline void QPainter::drawPoints(const QPolygon &points)
drawPoints(points.constData(), points.size());
}
-inline void QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
-{
- drawRoundRect(QRectF(x, y, w, h), xRnd, yRnd);
-}
-
-inline void QPainter::drawRoundRect(const QRect &rect, int xRnd, int yRnd)
-{
- drawRoundRect(QRectF(rect), xRnd, yRnd);
-}
-
inline void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
Qt::SizeMode mode)
{
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 2d44577310..29d4880eb9 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -51,8 +51,11 @@
// We mean it.
//
+#include <QtCore/qvarlengtharray.h>
#include <QtGui/private/qtguiglobal_p.h>
#include "QtGui/qbrush.h"
+#include "QtGui/qcolorspace.h"
+#include "QtGui/qcolortransform.h"
#include "QtGui/qfont.h"
#include "QtGui/qpen.h"
#include "QtGui/qregion.h"
@@ -190,9 +193,9 @@ class QPainterPrivate
Q_DECLARE_PUBLIC(QPainter)
public:
QPainterPrivate(QPainter *painter)
- : q_ptr(painter), d_ptrs(0), state(0), dummyState(0), txinv(0), inDestructor(false), d_ptrs_size(0),
- refcount(1), device(0), original_device(0), helper_device(0), engine(0), emulationEngine(0),
- extended(0)
+ : q_ptr(painter), d_ptrs(nullptr), state(nullptr), dummyState(nullptr), txinv(0), inDestructor(false), d_ptrs_size(0),
+ refcount(1), device(nullptr), original_device(nullptr), helper_device(nullptr), engine(nullptr), emulationEngine(nullptr),
+ extended(nullptr)
{
}
@@ -202,7 +205,7 @@ public:
QPainterPrivate **d_ptrs;
QPainterState *state;
- QVector<QPainterState*> states;
+ QVarLengthArray<QPainterState *, 8> states;
mutable QPainterDummyState *dummyState;
@@ -253,6 +256,7 @@ public:
QTransform hidpiScaleTransform() const;
static bool attachPainterPrivate(QPainter *q, QPaintDevice *pdev);
void detachPainterPrivate(QPainter *q);
+ void initFrom(const QPaintDevice *device);
QPaintDevice *device;
QPaintDevice *original_device;
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 9b82b768d4..70ad6bdc97 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -93,7 +93,7 @@ struct QPainterPathPrivateDeleter
{
static inline void cleanup(QPainterPathPrivate *d)
{
- // note - we must up-cast to QPainterPathData since QPainterPathPrivate
+ // note - we must downcast to QPainterPathData since QPainterPathPrivate
// has a non-virtual destructor!
if (d && !d->ref.deref())
delete static_cast<QPainterPathData *>(d);
@@ -545,7 +545,7 @@ void QPainterPath::setElementPositionAt(int i, qreal x, qreal y)
/*!
Constructs an empty QPainterPath object.
*/
-QPainterPath::QPainterPath() Q_DECL_NOEXCEPT
+QPainterPath::QPainterPath() noexcept
: d_ptr(0)
{
}
@@ -578,7 +578,7 @@ QPainterPath::QPainterPath(const QPointF &startPoint)
void QPainterPath::detach()
{
- if (d_ptr->ref.load() != 1)
+ if (d_ptr->ref.loadRelaxed() != 1)
detach_helper();
setDirty(true);
}
@@ -647,6 +647,55 @@ QPainterPath::~QPainterPath()
}
/*!
+ Clears the path elements stored.
+
+ This allows the path to reuse previous memory allocations.
+
+ \sa reserve(), capacity()
+ \since 5.13
+*/
+void QPainterPath::clear()
+{
+ if (!d_ptr)
+ return;
+
+ detach();
+ d_func()->clear();
+}
+
+/*!
+ Reserves a given amount of elements in QPainterPath's internal memory.
+
+ Attempts to allocate memory for at least \a size elements.
+
+ \sa clear(), capacity(), QVector::reserve()
+ \since 5.13
+*/
+void QPainterPath::reserve(int size)
+{
+ Q_D(QPainterPath);
+ if ((!d && size > 0) || (d && d->elements.capacity() < size)) {
+ detach();
+ d->elements.reserve(size);
+ }
+}
+
+/*!
+ Returns the number of elements allocated by the QPainterPath.
+
+ \sa clear(), reserve()
+ \since 5.13
+*/
+int QPainterPath::capacity() const
+{
+ Q_D(QPainterPath);
+ if (d)
+ return d->elements.capacity();
+
+ return 0;
+}
+
+/*!
Closes the current subpath by drawing a line to the beginning of
the subpath, automatically starting a new path. The current point
of the new path is (0, 0).
@@ -2286,13 +2335,19 @@ static inline bool epsilonCompare(const QPointF &a, const QPointF &b, const QSiz
bool QPainterPath::operator==(const QPainterPath &path) const
{
QPainterPathData *d = reinterpret_cast<QPainterPathData *>(d_func());
- if (path.d_func() == d)
+ QPainterPathData *other_d = path.d_func();
+ if (other_d == d)
return true;
- else if (!d || !path.d_func())
+ else if (!d || !other_d) {
+ if (!d && other_d->elements.empty() && other_d->fillRule == Qt::OddEvenFill)
+ return true;
+ if (!other_d && d && d->elements.empty() && d->fillRule == Qt::OddEvenFill)
+ return true;
return false;
- else if (d->fillRule != path.d_func()->fillRule)
+ }
+ else if (d->fillRule != other_d->fillRule)
return false;
- else if (d->elements.size() != path.d_func()->elements.size())
+ else if (d->elements.size() != other_d->elements.size())
return false;
const qreal qt_epsilon = sizeof(qreal) == sizeof(double) ? 1e-12 : qreal(1e-5);
@@ -2302,8 +2357,8 @@ bool QPainterPath::operator==(const QPainterPath &path) const
epsilon.rheight() *= qt_epsilon;
for (int i = 0; i < d->elements.size(); ++i)
- if (d->elements.at(i).type != path.d_func()->elements.at(i).type
- || !epsilonCompare(d->elements.at(i), path.d_func()->elements.at(i), epsilon))
+ if (d->elements.at(i).type != other_d->elements.at(i).type
+ || !epsilonCompare(d->elements.at(i), other_d->elements.at(i), epsilon))
return false;
return true;
@@ -3206,6 +3261,7 @@ void QPainterPath::addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadi
Adds the given rectangle \a x, \a y, \a w, \a h with rounded corners to the path.
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -3272,6 +3328,17 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd)
\sa addRoundedRect()
*/
+void QPainterPath::addRoundRect(const QRectF &rect,
+ int roundness)
+{
+ int xRnd = roundness;
+ int yRnd = roundness;
+ if (rect.width() > rect.height())
+ xRnd = int(roundness * rect.height()/rect.width());
+ else
+ yRnd = int(roundness * rect.width()/rect.height());
+ addRoundedRect(rect, xRnd, yRnd, Qt::RelativeSize);
+}
/*!
\obsolete
@@ -3288,6 +3355,11 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd)
\sa addRoundedRect()
*/
+void QPainterPath::addRoundRect(qreal x, qreal y, qreal w, qreal h,
+ int xRnd, int yRnd)
+{
+ addRoundedRect(QRectF(x, y, w, h), xRnd, yRnd, Qt::RelativeSize);
+}
/*!
\obsolete
@@ -3307,6 +3379,12 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd)
\sa addRoundedRect()
*/
+void QPainterPath::addRoundRect(qreal x, qreal y, qreal w, qreal h,
+ int roundness)
+{
+ addRoundedRect(QRectF(x, y, w, h), roundness, Qt::RelativeSize);
+}
+#endif
/*!
\since 4.3
@@ -3361,6 +3439,7 @@ QPainterPath QPainterPath::subtracted(const QPainterPath &p) const
return clipper.clip(QPathClipper::BoolSub);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\since 4.3
\obsolete
@@ -3373,6 +3452,7 @@ QPainterPath QPainterPath::subtractedInverted(const QPainterPath &p) const
{
return p.subtracted(*this);
}
+#endif
/*!
\since 4.4
@@ -3438,8 +3518,7 @@ void QPainterPath::setDirty(bool dirty)
{
d_func()->dirtyBounds = dirty;
d_func()->dirtyControlBounds = dirty;
- delete d_func()->pathConverter;
- d_func()->pathConverter = 0;
+ d_func()->pathConverter.reset();
d_func()->convex = false;
}
@@ -3515,10 +3594,10 @@ void QPainterPath::computeControlPointRect() const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug s, const QPainterPath &p)
{
- s.nospace() << "QPainterPath: Element count=" << p.elementCount() << endl;
+ s.nospace() << "QPainterPath: Element count=" << p.elementCount() << Qt::endl;
const char *types[] = {"MoveTo", "LineTo", "CurveTo", "CurveToData"};
for (int i=0; i<p.elementCount(); ++i) {
- s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ')' << endl;
+ s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ')' << Qt::endl;
}
return s;
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index db39c1c5a0..ed5be667b7 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -88,16 +88,19 @@ public:
inline bool operator!=(const Element &e) const { return !operator==(e); }
};
- QPainterPath() Q_DECL_NOEXCEPT;
+ QPainterPath() noexcept;
explicit QPainterPath(const QPointF &startPoint);
QPainterPath(const QPainterPath &other);
QPainterPath &operator=(const QPainterPath &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QPainterPath &operator=(QPainterPath &&other) Q_DECL_NOEXCEPT
+ inline QPainterPath &operator=(QPainterPath &&other) noexcept
{ qSwap(d_ptr, other.d_ptr); return *this; }
-#endif
~QPainterPath();
- inline void swap(QPainterPath &other) Q_DECL_NOEXCEPT { d_ptr.swap(other.d_ptr); }
+
+ inline void swap(QPainterPath &other) noexcept { d_ptr.swap(other.d_ptr); }
+
+ void clear();
+ void reserve(int size);
+ int capacity() const;
void closeSubpath();
@@ -138,12 +141,18 @@ public:
qreal xRadius, qreal yRadius,
Qt::SizeMode mode = Qt::AbsoluteSize);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use addRoundedRect(..., Qt::RelativeSize) instead")
void addRoundRect(const QRectF &rect, int xRnd, int yRnd);
- inline void addRoundRect(qreal x, qreal y, qreal w, qreal h,
- int xRnd, int yRnd);
- inline void addRoundRect(const QRectF &rect, int roundness);
- inline void addRoundRect(qreal x, qreal y, qreal w, qreal h,
- int roundness);
+ QT_DEPRECATED_X("Use addRoundedRect(..., Qt::RelativeSize) instead")
+ void addRoundRect(qreal x, qreal y, qreal w, qreal h,
+ int xRnd, int yRnd);
+ QT_DEPRECATED_X("Use addRoundedRect(..., Qt::RelativeSize) instead")
+ void addRoundRect(const QRectF &rect, int roundness);
+ QT_DEPRECATED_X("Use addRoundedRect(..., Qt::RelativeSize) instead")
+ void addRoundRect(qreal x, qreal y, qreal w, qreal h,
+ int roundness);
+#endif
void connectPath(const QPainterPath &path);
@@ -188,7 +197,10 @@ public:
Q_REQUIRED_RESULT QPainterPath united(const QPainterPath &r) const;
Q_REQUIRED_RESULT QPainterPath intersected(const QPainterPath &r) const;
Q_REQUIRED_RESULT QPainterPath subtracted(const QPainterPath &r) const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use r.subtracted() instead")
Q_REQUIRED_RESULT QPainterPath subtractedInverted(const QPainterPath &r) const;
+#endif
Q_REQUIRED_RESULT QPainterPath simplified() const;
@@ -333,30 +345,6 @@ inline void QPainterPath::addRoundedRect(qreal x, qreal y, qreal w, qreal h,
addRoundedRect(QRectF(x, y, w, h), xRadius, yRadius, mode);
}
-inline void QPainterPath::addRoundRect(qreal x, qreal y, qreal w, qreal h,
- int xRnd, int yRnd)
-{
- addRoundRect(QRectF(x, y, w, h), xRnd, yRnd);
-}
-
-inline void QPainterPath::addRoundRect(const QRectF &rect,
- int roundness)
-{
- int xRnd = roundness;
- int yRnd = roundness;
- if (rect.width() > rect.height())
- xRnd = int(roundness * rect.height()/rect.width());
- else
- yRnd = int(roundness * rect.width()/rect.height());
- addRoundRect(rect, xRnd, yRnd);
-}
-
-inline void QPainterPath::addRoundRect(qreal x, qreal y, qreal w, qreal h,
- int roundness)
-{
- addRoundRect(QRectF(x, y, w, h), roundness);
-}
-
inline void QPainterPath::addText(qreal x, qreal y, const QFont &f, const QString &text)
{
addText(QPointF(x, y), f, text);
diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h
index 92d9a4ea66..22bdbde2a9 100644
--- a/src/gui/painting/qpainterpath_p.h
+++ b/src/gui/painting/qpainterpath_p.h
@@ -62,8 +62,11 @@
#include <private/qvectorpath_p.h>
#include <private/qstroker_p.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
+// ### Qt 6: merge with QPainterPathData
class QPainterPathPrivate
{
public:
@@ -80,7 +83,19 @@ public:
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPainterPath &);
#endif
- QPainterPathPrivate() : ref(1) {}
+ QPainterPathPrivate() noexcept
+ : ref(1)
+ {
+ }
+
+ QPainterPathPrivate(const QPainterPathPrivate &other) noexcept
+ : ref(1),
+ elements(other.elements)
+ {
+ }
+
+ QPainterPathPrivate &operator=(const QPainterPathPrivate &) = delete;
+ ~QPainterPathPrivate() = default;
private:
QAtomicInt ref;
@@ -157,7 +172,7 @@ public:
QVectorPath path;
private:
- Q_DISABLE_COPY(QVectorPathConverter)
+ Q_DISABLE_COPY_MOVE(QVectorPathConverter)
};
class QPainterPathData : public QPainterPathPrivate
@@ -166,38 +181,39 @@ public:
QPainterPathData() :
cStart(0),
fillRule(Qt::OddEvenFill),
+ require_moveTo(false),
dirtyBounds(false),
dirtyControlBounds(false),
- pathConverter(0)
+ convex(false),
+ pathConverter(nullptr)
{
- require_moveTo = false;
- convex = false;
}
QPainterPathData(const QPainterPathData &other) :
- QPainterPathPrivate(), cStart(other.cStart), fillRule(other.fillRule),
+ QPainterPathPrivate(other),
+ cStart(other.cStart),
+ fillRule(other.fillRule),
bounds(other.bounds),
controlBounds(other.controlBounds),
+ require_moveTo(false),
dirtyBounds(other.dirtyBounds),
dirtyControlBounds(other.dirtyControlBounds),
convex(other.convex),
- pathConverter(0)
+ pathConverter(nullptr)
{
- require_moveTo = false;
- elements = other.elements;
}
- ~QPainterPathData() {
- delete pathConverter;
- }
+ QPainterPathData &operator=(const QPainterPathData &) = delete;
+ ~QPainterPathData() = default;
inline bool isClosed() const;
inline void close();
inline void maybeMoveTo();
+ inline void clear();
const QVectorPath &vectorPath() {
if (!pathConverter)
- pathConverter = new QVectorPathConverter(elements, fillRule, convex);
+ pathConverter.reset(new QVectorPathConverter(elements, fillRule, convex));
return pathConverter->path;
}
@@ -212,7 +228,7 @@ public:
uint dirtyControlBounds : 1;
uint convex : 1;
- QVectorPathConverter *pathConverter;
+ std::unique_ptr<QVectorPathConverter> pathConverter;
};
@@ -265,7 +281,7 @@ inline bool QPainterPathData::isClosed() const
inline void QPainterPathData::close()
{
- Q_ASSERT(ref.load() == 1);
+ Q_ASSERT(ref.loadRelaxed() == 1);
require_moveTo = true;
const QPainterPath::Element &first = elements.at(cStart);
QPainterPath::Element &last = elements.last();
@@ -290,6 +306,24 @@ inline void QPainterPathData::maybeMoveTo()
}
}
+inline void QPainterPathData::clear()
+{
+ Q_ASSERT(ref.loadRelaxed() == 1);
+
+ elements.clear();
+
+ cStart = 0;
+
+ bounds = {};
+ controlBounds = {};
+
+ require_moveTo = false;
+ dirtyBounds = false;
+ dirtyControlBounds = false;
+ convex = false;
+
+ pathConverter.reset();
+}
#define KAPPA qreal(0.5522847498)
diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h
index 64e684e1ad..9444a87b71 100644
--- a/src/gui/painting/qpathclipper_p.h
+++ b/src/gui/painting/qpathclipper_p.h
@@ -82,11 +82,11 @@ public:
bool intersect();
bool contains();
- static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
+ static bool pathToRect(const QPainterPath &path, QRectF *rect = nullptr);
static QPainterPath intersect(const QPainterPath &path, const QRectF &rect);
private:
- Q_DISABLE_COPY(QPathClipper)
+ Q_DISABLE_COPY_MOVE(QPathClipper)
enum ClipperMode {
ClipMode, // do the full clip
@@ -394,7 +394,7 @@ inline const QPathSegments::Intersection *QPathSegments::intersectionAt(int inde
{
const int intersection = m_segments.at(index).intersection;
if (intersection < 0)
- return 0;
+ return nullptr;
else
return &m_intersections.at(intersection);
}
@@ -428,12 +428,12 @@ inline int QWingedEdge::edgeCount() const
inline QPathEdge *QWingedEdge::edge(int edge)
{
- return edge < 0 ? 0 : &m_edges.at(edge);
+ return edge < 0 ? nullptr : &m_edges.at(edge);
}
inline const QPathEdge *QWingedEdge::edge(int edge) const
{
- return edge < 0 ? 0 : &m_edges.at(edge);
+ return edge < 0 ? nullptr : &m_edges.at(edge);
}
inline int QWingedEdge::vertexCount() const
@@ -449,12 +449,12 @@ inline int QWingedEdge::addVertex(const QPointF &p)
inline QPathVertex *QWingedEdge::vertex(int vertex)
{
- return vertex < 0 ? 0 : &m_vertices.at(vertex);
+ return vertex < 0 ? nullptr : &m_vertices.at(vertex);
}
inline const QPathVertex *QWingedEdge::vertex(int vertex) const
{
- return vertex < 0 ? 0 : &m_vertices.at(vertex);
+ return vertex < 0 ? nullptr : &m_vertices.at(vertex);
}
inline QPathEdge::Traversal QWingedEdge::flip(QPathEdge::Traversal traversal)
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index ae3df6f9ec..25d488961c 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -856,7 +856,6 @@ void QPdfEngine::drawRects (const QRectF *rects, int rectCount)
if (!d->hasPen && !d->hasBrush)
return;
- QBrush penBrush = d->pen.brush();
if (d->simplePen || !d->hasPen) {
// draw strokes natively in this case for better output
if(!d->simplePen && !d->stroker.matrix.isIdentity())
@@ -949,7 +948,8 @@ void QPdfEngine::drawPixmap (const QRectF &rectangle, const QPixmap &pixmap, con
QPixmap pm = sourceRect != pixmap.rect() ? pixmap.copy(sourceRect) : pixmap;
QImage image = pm.toImage();
bool bitmap = true;
- const int object = d->addImage(image, &bitmap, pm.cacheKey());
+ const bool lossless = painter()->testRenderHint(QPainter::LosslessImageRendering);
+ const int object = d->addImage(image, &bitmap, lossless, pm.cacheKey());
if (object < 0)
return;
@@ -988,7 +988,8 @@ void QPdfEngine::drawImage(const QRectF &rectangle, const QImage &image, const Q
QRect sourceRect = sr.toRect();
QImage im = sourceRect != image.rect() ? image.copy(sourceRect) : image;
bool bitmap = true;
- const int object = d->addImage(im, &bitmap, im.cacheKey());
+ const bool lossless = painter()->testRenderHint(QPainter::LosslessImageRendering);
+ const int object = d->addImage(im, &bitmap, lossless, im.cacheKey());
if (object < 0)
return;
@@ -1541,7 +1542,7 @@ bool QPdfEngine::end()
Q_D(QPdfEngine);
d->writeTail();
- d->stream->unsetDevice();
+ d->stream->setDevice(nullptr);
qDeleteAll(d->fonts);
d->fonts.clear();
@@ -1670,19 +1671,19 @@ int QPdfEnginePrivate::writeXmpMetaData()
const QDateTime now = QDateTime::currentDateTime();
const QDate date = now.date();
const QTime time = now.time();
-
- QString timeStr;
- timeStr.sprintf("%d-%02d-%02dT%02d:%02d:%02d", date.year(), date.month(), date.day(),
- time.hour(), time.minute(), time.second());
+ const QString timeStr =
+ QString::asprintf("%d-%02d-%02dT%02d:%02d:%02d",
+ date.year(), date.month(), date.day(),
+ time.hour(), time.minute(), time.second());
const int offset = now.offsetFromUtc();
const int hours = (offset / 60) / 60;
const int mins = (offset / 60) % 60;
QString tzStr;
if (offset < 0)
- tzStr.sprintf("-%02d:%02d", -hours, -mins);
+ tzStr = QString::asprintf("-%02d:%02d", -hours, -mins);
else if (offset > 0)
- tzStr.sprintf("+%02d:%02d", hours , mins);
+ tzStr = QString::asprintf("+%02d:%02d", hours , mins);
else
tzStr = QLatin1String("Z");
@@ -2633,6 +2634,8 @@ int QPdfEnginePrivate::addConstantAlphaObject(int brushAlpha, int penAlpha)
int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor, int *gStateObject)
{
+ Q_Q(QPdfEngine);
+
int paintType = 2; // Uncolored tiling
int w = 8;
int h = 8;
@@ -2662,7 +2665,8 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
return 0;
QImage image = brush.textureImage();
bool bitmap = true;
- imageObject = addImage(image, &bitmap, image.cacheKey());
+ const bool lossless = q->painter()->testRenderHint(QPainter::LosslessImageRendering);
+ imageObject = addImage(image, &bitmap, lossless, image.cacheKey());
if (imageObject != -1) {
QImage::Format f = image.format();
if (f != QImage::Format_MonoLSB && f != QImage::Format_Mono) {
@@ -2724,7 +2728,7 @@ static inline bool is_monochrome(const QVector<QRgb> &colorTable)
/*!
* Adds an image to the pdf and return the pdf-object id. Returns -1 if adding the image failed.
*/
-int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_no)
+int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless, qint64 serial_no)
{
if (img.isNull())
return -1;
@@ -2785,7 +2789,7 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_n
bool hasAlpha = false;
bool hasMask = false;
- if (QImageWriter::supportedImageFormats().contains("jpeg") && !grayscale) {
+ if (QImageWriter::supportedImageFormats().contains("jpeg") && !grayscale && !lossless) {
QBuffer buffer(&imageData);
QImageWriter writer(&buffer, "jpeg");
writer.setQuality(94);
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index e2526de67d..e337c61f64 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -242,7 +242,7 @@ public:
void writeHeader();
void writeTail();
- int addImage(const QImage &image, bool *bitmap, qint64 serial_no);
+ int addImage(const QImage &image, bool *bitmap, bool lossless, qint64 serial_no);
int addConstantAlphaObject(int brushAlpha, int penAlpha = 255);
int addBrushPattern(const QTransform &matrix, bool *specifyColor, int *gStateObject);
diff --git a/src/gui/painting/qpdfwriter.cpp b/src/gui/painting/qpdfwriter.cpp
index 6c85d65538..7f18ce42be 100644
--- a/src/gui/painting/qpdfwriter.cpp
+++ b/src/gui/painting/qpdfwriter.cpp
@@ -76,7 +76,7 @@ public:
: QPagedPaintDevicePrivate(), pd(d)
{}
- virtual ~QPdfPagedPaintDevicePrivate()
+ ~QPdfPagedPaintDevicePrivate()
{}
bool setPageLayout(const QPageLayout &newPageLayout) override
@@ -379,6 +379,9 @@ int QPdfWriter::resolution() const
*/
#endif
+#if QT_DEPRECATED_SINCE(5, 14)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
/*!
\reimp
@@ -404,6 +407,8 @@ void QPdfWriter::setPageSizeMM(const QSizeF &size)
{
setPageSize(QPageSize(size, QPageSize::Millimeter));
}
+QT_WARNING_POP
+#endif
/*!
\internal
@@ -427,6 +432,9 @@ bool QPdfWriter::newPage()
}
+#if QT_DEPRECATED_SINCE(5, 14)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
/*!
\reimp
@@ -438,6 +446,8 @@ void QPdfWriter::setMargins(const Margins &m)
{
setPageMargins(QMarginsF(m.left, m.top, m.right, m.bottom), QPageLayout::Millimeter);
}
+QT_WARNING_POP
+#endif
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpdfwriter.h b/src/gui/painting/qpdfwriter.h
index b260805b2b..668081e008 100644
--- a/src/gui/painting/qpdfwriter.h
+++ b/src/gui/painting/qpdfwriter.h
@@ -86,10 +86,14 @@ public:
using QPagedPaintDevice::setPageSize;
#endif
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_X("Use setPageSize(QPageSize(id)) instead")
void setPageSize(PageSize size) override;
+ QT_DEPRECATED_X("Use setPageSize(QPageSize(size, QPageSize::Millimeter)) instead")
void setPageSizeMM(const QSizeF &size) override;
-
+ QT_DEPRECATED_X("Use setPageMargins(QMarginsF(l, t, r, b), QPageLayout::Millimeter) instead")
void setMargins(const Margins &m) override;
+#endif
protected:
QPaintEngine *paintEngine() const override;
diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp
index 778c770b82..dc6e3e04d0 100644
--- a/src/gui/painting/qpen.cpp
+++ b/src/gui/painting/qpen.cpp
@@ -322,7 +322,7 @@ QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle s, Qt::PenCapStyle c,
Constructs a pen that is a copy of the given \a pen.
*/
-QPen::QPen(const QPen &p) Q_DECL_NOTHROW
+QPen::QPen(const QPen &p) noexcept
{
d = p.d;
if (d)
@@ -363,13 +363,13 @@ QPen::~QPen()
void QPen::detach()
{
- if (d->ref.load() == 1)
+ if (d->ref.loadRelaxed() == 1)
return;
QPenData *x = new QPenData(*static_cast<QPenData *>(d));
if (!d->ref.deref())
delete d;
- x->ref.store(1);
+ x->ref.storeRelaxed(1);
d = x;
}
@@ -381,7 +381,7 @@ void QPen::detach()
this pen.
*/
-QPen &QPen::operator=(const QPen &p) Q_DECL_NOTHROW
+QPen &QPen::operator=(const QPen &p) noexcept
{
QPen(p).swap(*this);
return *this;
@@ -885,7 +885,7 @@ bool QPen::operator==(const QPen &p) const
bool QPen::isDetached()
{
- return d->ref.load() == 1;
+ return d->ref.loadRelaxed() == 1;
}
diff --git a/src/gui/painting/qpen.h b/src/gui/painting/qpen.h
index 03abfb3d7d..10b11d1d85 100644
--- a/src/gui/painting/qpen.h
+++ b/src/gui/painting/qpen.h
@@ -65,18 +65,16 @@ public:
QPen(const QColor &color);
QPen(const QBrush &brush, qreal width, Qt::PenStyle s = Qt::SolidLine,
Qt::PenCapStyle c = Qt::SquareCap, Qt::PenJoinStyle j = Qt::BevelJoin);
- QPen(const QPen &pen) Q_DECL_NOTHROW;
+ QPen(const QPen &pen) noexcept;
~QPen();
- QPen &operator=(const QPen &pen) Q_DECL_NOTHROW;
-#ifdef Q_COMPILER_RVALUE_REFS
- QPen(QPen &&other) Q_DECL_NOTHROW
+ QPen &operator=(const QPen &pen) noexcept;
+ QPen(QPen &&other) noexcept
: d(other.d) { other.d = nullptr; }
- QPen &operator=(QPen &&other) Q_DECL_NOTHROW
+ QPen &operator=(QPen &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- void swap(QPen &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QPen &other) noexcept { qSwap(d, other.d); }
Qt::PenStyle style() const;
void setStyle(Qt::PenStyle);
diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h
index de5ba964dc..414d2bf0de 100644
--- a/src/gui/painting/qplatformbackingstore.h
+++ b/src/gui/painting/qplatformbackingstore.h
@@ -85,7 +85,7 @@ public:
};
Q_DECLARE_FLAGS(Flags, Flag)
- explicit QPlatformTextureList(QObject *parent = 0);
+ explicit QPlatformTextureList(QObject *parent = nullptr);
~QPlatformTextureList();
int count() const;
@@ -99,7 +99,7 @@ public:
bool isLocked() const;
void appendTexture(void *source, GLuint textureId, const QRect &geometry,
- const QRect &clipRect = QRect(), Flags flags = 0);
+ const QRect &clipRect = QRect(), Flags flags = nullptr);
void clear();
Q_SIGNALS:
diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h
index 8e74a499fd..93fab55aa1 100644
--- a/src/gui/painting/qpolygon.h
+++ b/src/gui/painting/qpolygon.h
@@ -60,18 +60,14 @@ public:
inline ~QPolygon() {}
inline explicit QPolygon(int size);
inline /*implicit*/ QPolygon(const QVector<QPoint> &v) : QVector<QPoint>(v) {}
-#ifdef Q_COMPILER_RVALUE_REFS
- /*implicit*/ QPolygon(QVector<QPoint> &&v) Q_DECL_NOTHROW : QVector<QPoint>(std::move(v)) {}
-#endif
+ /*implicit*/ QPolygon(QVector<QPoint> &&v) noexcept : QVector<QPoint>(std::move(v)) {}
QPolygon(const QRect &r, bool closed=false);
QPolygon(int nPoints, const int *points);
QPolygon(const QPolygon &other) : QVector<QPoint>(other) {}
-#ifdef Q_COMPILER_RVALUE_REFS
- QPolygon(QPolygon &&other) Q_DECL_NOTHROW : QVector<QPoint>(std::move(other)) {}
- QPolygon &operator=(QPolygon &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QPolygon(QPolygon &&other) noexcept : QVector<QPoint>(std::move(other)) {}
+ QPolygon &operator=(QPolygon &&other) noexcept { swap(other); return *this; }
QPolygon &operator=(const QPolygon &other) { QVector<QPoint>::operator=(other); return *this; }
- void swap(QPolygon &other) Q_DECL_NOTHROW { QVector<QPoint>::swap(other); } // prevent QVector<QPoint><->QPolygon swaps
+ void swap(QPolygon &other) noexcept { QVector<QPoint>::swap(other); } // prevent QVector<QPoint><->QPolygon swaps
operator QVariant() const;
@@ -145,16 +141,12 @@ public:
inline ~QPolygonF() {}
inline explicit QPolygonF(int size);
inline /*implicit*/ QPolygonF(const QVector<QPointF> &v) : QVector<QPointF>(v) {}
-#ifdef Q_COMPILER_RVALUE_REFS
- /* implicit */ QPolygonF(QVector<QPointF> &&v) Q_DECL_NOTHROW : QVector<QPointF>(std::move(v)) {}
-#endif
+ /* implicit */ QPolygonF(QVector<QPointF> &&v) noexcept : QVector<QPointF>(std::move(v)) {}
QPolygonF(const QRectF &r);
/*implicit*/ QPolygonF(const QPolygon &a);
inline QPolygonF(const QPolygonF &a) : QVector<QPointF>(a) {}
-#ifdef Q_COMPILER_RVALUE_REFS
- QPolygonF(QPolygonF &&other) Q_DECL_NOTHROW : QVector<QPointF>(std::move(other)) {}
- QPolygonF &operator=(QPolygonF &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QPolygonF(QPolygonF &&other) noexcept : QVector<QPointF>(std::move(other)) {}
+ QPolygonF &operator=(QPolygonF &&other) noexcept { swap(other); return *this; }
QPolygonF &operator=(const QPolygonF &other) { QVector<QPointF>::operator=(other); return *this; }
inline void swap(QPolygonF &other) { QVector<QPointF>::swap(other); } // prevent QVector<QPointF><->QPolygonF swaps
diff --git a/src/gui/painting/qrbtree_p.h b/src/gui/painting/qrbtree_p.h
index d3ee23a91c..42e88889a1 100644
--- a/src/gui/painting/qrbtree_p.h
+++ b/src/gui/painting/qrbtree_p.h
@@ -60,7 +60,7 @@ struct QRBTree
{
struct Node
{
- inline Node() : parent(0), left(0), right(0), red(true) { }
+ inline Node() : parent(nullptr), left(nullptr), right(nullptr), red(true) { }
inline ~Node() {if (left) delete left; if (right) delete right;}
T data;
Node *parent;
@@ -69,7 +69,7 @@ struct QRBTree
bool red;
};
- inline QRBTree() : root(0), freeList(0) { }
+ inline QRBTree() : root(nullptr), freeList(nullptr) { }
inline ~QRBTree();
inline void clear();
@@ -120,7 +120,7 @@ inline QRBTree<T>::~QRBTree()
while (freeList) {
// Avoid recursively calling the destructor, as this list may become large.
Node *next = freeList->right;
- freeList->right = 0;
+ freeList->right = nullptr;
delete freeList;
freeList = next;
}
@@ -131,7 +131,7 @@ inline void QRBTree<T>::clear()
{
if (root)
delete root;
- root = 0;
+ root = nullptr;
}
template <class T>
@@ -359,7 +359,7 @@ void QRBTree<T>::detach(Node *node) // call this before removing a node.
ref = child;
if (child)
child->parent = node->parent;
- node->left = node->right = node->parent = 0;
+ node->left = node->right = node->parent = nullptr;
}
// 'node' must be black. rebalance will reduce the depth of black nodes by one in the sibling tree.
@@ -513,7 +513,7 @@ inline void QRBTree<T>::deleteNode(Node *&node)
detach(node);
node->right = freeList;
freeList = node;
- node = 0;
+ node = nullptr;
}
template <class T>
@@ -522,7 +522,7 @@ inline typename QRBTree<T>::Node *QRBTree<T>::newNode()
if (freeList) {
Node *node = freeList;
freeList = freeList->right;
- node->parent = node->left = node->right = 0;
+ node->parent = node->left = node->right = nullptr;
node->red = true;
return node;
}
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 77718ce747..51eed962f0 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -1287,10 +1287,10 @@ struct QRegionPrivate {
}
}
- const QRect *begin() const Q_DECL_NOTHROW
+ const QRect *begin() const noexcept
{ return numRects == 1 ? &extents : rects.data(); } // avoid vectorize()
- const QRect *end() const Q_DECL_NOTHROW
+ const QRect *end() const noexcept
{ return begin() + numRects; }
inline void append(const QRect *r);
@@ -4321,7 +4321,7 @@ QRegion QRegion::xored(const QRegion &r) const
}
}
-QRect QRegion::boundingRect() const Q_DECL_NOTHROW
+QRect QRegion::boundingRect() const noexcept
{
if (isEmpty())
return QRect();
@@ -4379,12 +4379,12 @@ QVector<QRect> QRegion::rects() const
}
#endif
-QRegion::const_iterator QRegion::begin() const Q_DECL_NOTHROW
+QRegion::const_iterator QRegion::begin() const noexcept
{
return d->qt_rgn ? d->qt_rgn->begin() : nullptr;
}
-QRegion::const_iterator QRegion::end() const Q_DECL_NOTHROW
+QRegion::const_iterator QRegion::end() const noexcept
{
return d->qt_rgn ? d->qt_rgn->end() : nullptr;
}
@@ -4421,7 +4421,7 @@ void QRegion::setRects(const QRect *rects, int num)
}
}
-int QRegion::rectCount() const Q_DECL_NOTHROW
+int QRegion::rectCount() const noexcept
{
return (d->qt_rgn ? d->qt_rgn->numRects : 0);
}
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index 9fe6ed5675..54de916198 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -69,30 +69,28 @@ public:
QRegion(const QRect &r, RegionType t = Rectangle);
QRegion(const QPolygon &pa, Qt::FillRule fillRule = Qt::OddEvenFill);
QRegion(const QRegion &region);
- QRegion(QRegion &&other) Q_DECL_NOTHROW
+ QRegion(QRegion &&other) noexcept
: d(other.d) { other.d = const_cast<QRegionData*>(&shared_empty); }
QRegion(const QBitmap &bitmap);
~QRegion();
QRegion &operator=(const QRegion &);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QRegion &operator=(QRegion &&other) Q_DECL_NOEXCEPT
+ inline QRegion &operator=(QRegion &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- inline void swap(QRegion &other) Q_DECL_NOEXCEPT { qSwap(d, other.d); }
+ inline void swap(QRegion &other) noexcept { qSwap(d, other.d); }
bool isEmpty() const;
bool isNull() const;
typedef const QRect *const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- const_iterator begin() const Q_DECL_NOTHROW;
- const_iterator cbegin() const Q_DECL_NOTHROW { return begin(); }
- const_iterator end() const Q_DECL_NOTHROW;
- const_iterator cend() const Q_DECL_NOTHROW { return end(); }
- const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
- const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return rbegin(); }
- const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
- const_reverse_iterator crend() const Q_DECL_NOTHROW { return rend(); }
+ const_iterator begin() const noexcept;
+ const_iterator cbegin() const noexcept { return begin(); }
+ const_iterator end() const noexcept;
+ const_iterator cend() const noexcept { return end(); }
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const noexcept { return rend(); }
bool contains(const QPoint &p) const;
bool contains(const QRect &r) const;
@@ -121,13 +119,13 @@ public:
bool intersects(const QRegion &r) const;
bool intersects(const QRect &r) const;
- QRect boundingRect() const Q_DECL_NOTHROW;
+ QRect boundingRect() const noexcept;
#if QT_DEPRECATED_SINCE(5, 11)
QT_DEPRECATED_X("Use begin()/end() instead")
QVector<QRect> rects() const;
#endif
void setRects(const QRect *rect, int num);
- int rectCount() const Q_DECL_NOTHROW;
+ int rectCount() const noexcept;
#ifdef Q_COMPILER_MANGLES_RETURN_TYPE
// ### Qt 6: remove these, they're kept for MSVC compat
const QRegion operator|(const QRegion &r) const;
diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h
index 0e5344cacb..0e0b567890 100644
--- a/src/gui/painting/qrgba64.h
+++ b/src/gui/painting/qrgba64.h
@@ -118,7 +118,27 @@ public:
Q_DECL_CONSTEXPR quint8 alpha8() const { return div_257(alpha()); }
Q_DECL_CONSTEXPR uint toArgb32() const
{
+#if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304
+ quint64 br = rgba & Q_UINT64_C(0xffff0000ffff);
+ quint64 ag = (rgba >> 16) & Q_UINT64_C(0xffff0000ffff);
+ br += Q_UINT64_C(0x8000000080);
+ ag += Q_UINT64_C(0x8000000080);
+ br = (br - ((br >> 8) & Q_UINT64_C(0xffff0000ffff))) >> 8;
+ ag = (ag - ((ag >> 8) & Q_UINT64_C(0xffff0000ffff)));
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ return ((br << 24) & 0xff000000)
+ | ((ag >> 24) & 0xff0000)
+ | ((br >> 24) & 0xff00)
+ | ((ag >> 8) & 0xff);
+#else
+ return ((ag >> 16) & 0xff000000)
+ | ((br << 16) & 0xff0000)
+ | (ag & 0xff00)
+ | ((br >> 32) & 0xff);
+#endif
+#else
return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8());
+#endif
}
Q_DECL_CONSTEXPR ushort toRgb16() const
{
@@ -131,11 +151,20 @@ public:
return *this;
if (isTransparent())
return QRgba64::fromRgba64(0);
- const quint32 a = alpha();
- const quint16 r = div_65535(red() * a);
- const quint16 g = div_65535(green() * a);
- const quint16 b = div_65535(blue() * a);
- return fromRgba64(r, g, b, quint16(a));
+ const quint64 a = alpha();
+ quint64 br = (rgba & Q_UINT64_C(0xffff0000ffff)) * a;
+ quint64 ag = ((rgba >> 16) & Q_UINT64_C(0xffff0000ffff)) * a;
+ br = (br + ((br >> 16) & Q_UINT64_C(0xffff0000ffff)) + Q_UINT64_C(0x800000008000));
+ ag = (ag + ((ag >> 16) & Q_UINT64_C(0xffff0000ffff)) + Q_UINT64_C(0x800000008000));
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ ag = ag & Q_UINT64_C(0xffff0000ffff0000);
+ br = (br >> 16) & Q_UINT64_C(0xffff00000000);
+ return fromRgba64(a | br | ag);
+#else
+ br = (br >> 16) & Q_UINT64_C(0xffff0000ffff);
+ ag = ag & Q_UINT64_C(0xffff0000);
+ return fromRgba64((a << 48) | br | ag);
+#endif
}
Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied() const
@@ -163,7 +192,6 @@ private:
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE quint8 div_257_floor(uint x) { return quint8((x - (x >> 8)) >> 8); }
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE quint8 div_257(quint16 x) { return div_257_floor(x + 128U); }
- static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE quint16 div_65535(uint x) { return quint16((x + (x>>16) + 0x8000U) >> 16); }
Q_DECL_RELAXED_CONSTEXPR Q_ALWAYS_INLINE QRgba64 unpremultiplied_32bit() const
{
if (isOpaque() || isTransparent())
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index 43dd191be8..271d3ba6bf 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -173,15 +173,12 @@ template <class Iterator> bool qt_stroke_side(Iterator *it, QStroker *stroker,
bool capFirst, QLineF *startTangent);
/*******************************************************************************
- * QLineF::angle gives us the smalles angle between two lines. Here we
- * want to identify the line's angle direction on the unit circle.
+ * QLineF::angleTo gives us the angle between two lines with respecting the direction.
+ * Here we want to identify the line's angle direction on the unit circle.
*/
static inline qreal adapted_angle_on_x(const QLineF &line)
{
- qreal angle = line.angle(QLineF(0, 0, 1, 0));
- if (line.dy() > 0)
- angle = 360 - angle;
- return angle;
+ return QLineF(0, 0, 1, 0).angleTo(line);
}
QStrokerOps::QStrokerOps()
@@ -369,7 +366,8 @@ void QStrokerOps::strokeEllipse(const QRectF &rect, void *data, const QTransform
QStroker::QStroker()
: m_capStyle(SquareJoin), m_joinStyle(FlatJoin),
m_back1X(0), m_back1Y(0),
- m_back2X(0), m_back2Y(0)
+ m_back2X(0), m_back2Y(0),
+ m_forceOpen(false)
{
m_strokeWidth = qt_real_to_fixed(1);
m_miterLimit = qt_real_to_fixed(2);
@@ -458,7 +456,7 @@ void QStroker::joinPoints(qfixed focal_x, qfixed focal_y, const QLineF &nextLine
QLineF prevLine(qt_fixed_to_real(m_back2X), qt_fixed_to_real(m_back2Y),
qt_fixed_to_real(m_back1X), qt_fixed_to_real(m_back1Y));
QPointF isect;
- QLineF::IntersectType type = prevLine.intersect(nextLine, &isect);
+ QLineF::IntersectionType type = prevLine.intersects(nextLine, &isect);
if (join == FlatJoin) {
QLineF shortCut(prevLine.p2(), nextLine.p1());
@@ -749,7 +747,7 @@ template <class Iterator> bool qt_stroke_side(Iterator *it,
}
}
- if (start == prev) {
+ if (start == prev && !stroker->forceOpen()) {
// closed subpath, join first and last point
#ifdef QPP_STROKE_DEBUG
qDebug("\n ---> (side) closed subpath");
diff --git a/src/gui/painting/qstroker_p.h b/src/gui/painting/qstroker_p.h
index 59e4cc6a7b..f107b6eb20 100644
--- a/src/gui/painting/qstroker_p.h
+++ b/src/gui/painting/qstroker_p.h
@@ -223,6 +223,9 @@ public:
void setMiterLimit(qfixed length) { m_miterLimit = length; }
qfixed miterLimit() const { return m_miterLimit; }
+ void setForceOpen(bool state) { m_forceOpen = state; }
+ bool forceOpen() { return m_forceOpen; }
+
void joinPoints(qfixed x, qfixed y, const QLineF &nextLine, LineJoinMode join);
inline void emitMoveTo(qfixed x, qfixed y);
inline void emitLineTo(qfixed x, qfixed y);
@@ -248,6 +251,8 @@ protected:
qfixed m_back2X;
qfixed m_back2Y;
+
+ bool m_forceOpen;
};
class Q_GUI_EXPORT QDashStroker : public QStrokerOps
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 99b04aaba6..e8c47df21c 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -73,7 +73,7 @@ int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const
if (path.isEmpty())
break;
- images[numImages++] = qMove(img);
+ images[numImages++] = std::move(img);
} else {
bool found = false;
for (int j = 0; j < numImages; ++j) {
@@ -83,7 +83,7 @@ int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const
}
}
if (!found)
- images[numImages++] = qMove(img);
+ images[numImages++] = std::move(img);
}
}
@@ -285,6 +285,8 @@ QImageTextureGlyphCache::~QImageTextureGlyphCache()
void QImageTextureGlyphCache::resizeTextureData(int width, int height)
{
m_image = m_image.copy(0, 0, width, height);
+ // Regions not part of the copy are initialized to 0, and that is just what
+ // we need.
}
void QImageTextureGlyphCache::createTextureData(int width, int height)
@@ -305,6 +307,12 @@ void QImageTextureGlyphCache::createTextureData(int width, int height)
default:
Q_UNREACHABLE();
}
+
+ // Regions not touched by the glyphs must be initialized to 0. (such
+ // locations may in fact be sampled with styled (shifted) text materials)
+ // When resizing, the QImage copy() does this implicitly but the initial
+ // contents must be zeroed out explicitly here.
+ m_image.fill(0);
}
void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subPixelPosition)
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index 3da28872b1..1e83ab46d1 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -75,7 +75,7 @@ class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache
{
public:
QTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix)
- : QFontEngineGlyphCache(format, matrix), m_current_fontengine(0),
+ : QFontEngineGlyphCache(format, matrix), m_current_fontengine(nullptr),
m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0)
{ }
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 040d33fc2a..7696da7d45 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -265,7 +265,9 @@ QTransform::QTransform()
, m_13(0), m_23(0), m_33(1)
, m_type(TxNone)
, m_dirty(TxNone)
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
, d(nullptr)
+#endif
{
}
@@ -284,7 +286,9 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h13,
, m_13(h13), m_23(h23), m_33(h33)
, m_type(TxNone)
, m_dirty(TxProject)
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
, d(nullptr)
+#endif
{
}
@@ -301,7 +305,9 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h21,
, m_13(0), m_23(0), m_33(1)
, m_type(TxNone)
, m_dirty(TxShear)
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
, d(nullptr)
+#endif
{
}
@@ -317,7 +323,9 @@ QTransform::QTransform(const QMatrix &mtx)
m_13(0), m_23(0), m_33(1)
, m_type(TxNone)
, m_dirty(TxShear)
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
, d(nullptr)
+#endif
{
}
@@ -795,7 +803,7 @@ bool QTransform::operator==(const QTransform &o) const
Returns the hash value for \a key, using
\a seed to seed the calculation.
*/
-uint qHash(const QTransform &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QTransform &key, uint seed) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.m11());
@@ -1021,7 +1029,7 @@ QTransform QTransform::operator*(const QTransform &m) const
/*!
Assigns the given \a matrix's values to this matrix.
*/
-QTransform & QTransform::operator=(const QTransform &matrix) Q_DECL_NOTHROW
+QTransform & QTransform::operator=(const QTransform &matrix) noexcept
{
affine._m11 = matrix.affine._m11;
affine._m12 = matrix.affine._m12;
@@ -1517,8 +1525,23 @@ QRegion QTransform::map(const QRegion &r) const
return copy;
}
- if (t == TxScale && r.rectCount() == 1)
- return QRegion(mapRect(r.boundingRect()));
+ if (t == TxScale) {
+ QRegion res;
+ if (m11() < 0 || m22() < 0) {
+ for (const QRect &rect : r)
+ res += mapRect(rect);
+ } else {
+ QVarLengthArray<QRect, 32> rects;
+ rects.reserve(r.rectCount());
+ for (const QRect &rect : r) {
+ QRect nr = mapRect(rect);
+ if (!nr.isEmpty())
+ rects.append(nr);
+ }
+ res.setRects(rects.constData(), rects.count());
+ }
+ return res;
+ }
QPainterPath p = map(qt_regionToPath(r));
return p.toFillPolygon(QTransform()).toPolygon();
@@ -2144,13 +2167,14 @@ QTransform::operator QVariant() const
\sa inverted()
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\fn qreal QTransform::det() const
\obsolete
Returns the matrix's determinant. Use determinant() instead.
*/
-
+#endif
/*!
\fn qreal QTransform::m11() const
diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h
index 63c4a241c1..b220770144 100644
--- a/src/gui/painting/qtransform.h
+++ b/src/gui/painting/qtransform.h
@@ -77,13 +77,13 @@ public:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
// ### Qt 6: remove; the compiler-generated ones are fine!
- QTransform &operator=(QTransform &&other) Q_DECL_NOTHROW // = default
+ QTransform &operator=(QTransform &&other) noexcept // = default
{ memcpy(static_cast<void *>(this), static_cast<void *>(&other), sizeof(QTransform)); return *this; }
- QTransform &operator=(const QTransform &) Q_DECL_NOTHROW; // = default
- QTransform(QTransform &&other) Q_DECL_NOTHROW // = default
+ QTransform &operator=(const QTransform &) noexcept; // = default
+ QTransform(QTransform &&other) noexcept // = default
: affine(Qt::Uninitialized)
{ memcpy(static_cast<void *>(this), static_cast<void *>(&other), sizeof(QTransform)); }
- QTransform(const QTransform &other) Q_DECL_NOTHROW // = default
+ QTransform(const QTransform &other) noexcept // = default
: affine(Qt::Uninitialized)
{ memcpy(static_cast<void *>(this), static_cast<const void *>(&other), sizeof(QTransform)); }
#endif
@@ -98,7 +98,10 @@ public:
TransformationType type() const;
inline qreal determinant() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use determinant() instead")
qreal det() const;
+#endif
qreal m11() const;
qreal m12() const;
@@ -173,7 +176,9 @@ private:
, m_13(h13), m_23(h23), m_33(h33)
, m_type(TxNone)
, m_dirty(TxProject)
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
, d(nullptr)
+#endif
{
}
inline QTransform(bool)
@@ -181,7 +186,9 @@ private:
, m_13(0), m_23(0), m_33(1)
, m_type(TxNone)
, m_dirty(TxNone)
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
, d(nullptr)
+#endif
{
}
inline TransformationType inline_type() const;
@@ -199,7 +206,7 @@ private:
};
Q_DECLARE_TYPEINFO(QTransform, Q_MOVABLE_TYPE);
-Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QTransform &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QTransform &key, uint seed = 0) noexcept;
/******* inlines *****/
inline QTransform::TransformationType QTransform::inline_type() const
@@ -242,10 +249,12 @@ inline qreal QTransform::determinant() const
return affine._m11*(m_33*affine._m22-affine._dy*m_23) -
affine._m21*(m_33*affine._m12-affine._dy*m_13)+affine._dx*(m_23*affine._m12-affine._m22*m_13);
}
+#if QT_DEPRECATED_SINCE(5, 13)
inline qreal QTransform::det() const
{
return determinant();
}
+#endif
inline qreal QTransform::m11() const
{
return affine._m11;
diff --git a/src/gui/painting/qtriangulator_p.h b/src/gui/painting/qtriangulator_p.h
index 8f043fc925..177e5e66ed 100644
--- a/src/gui/painting/qtriangulator_p.h
+++ b/src/gui/painting/qtriangulator_p.h
@@ -57,7 +57,7 @@
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QVertexIndexVector
+class QVertexIndexVector
{
public:
enum Type {
@@ -93,17 +93,6 @@ public:
return indices16.size();
}
- inline QVertexIndexVector &operator = (const QVertexIndexVector &other)
- {
- if (t == UnsignedInt)
- indices32 = other.indices32;
- else
- indices16 = other.indices16;
-
- t = other.t;
- return *this;
- }
-
private:
Type t;
@@ -111,23 +100,15 @@ private:
QVector<quint16> indices16;
};
-struct Q_GUI_EXPORT QTriangleSet
+struct QTriangleSet
{
- inline QTriangleSet() { }
- inline QTriangleSet(const QTriangleSet &other) : vertices(other.vertices), indices(other.indices) { }
- QTriangleSet &operator = (const QTriangleSet &other) {vertices = other.vertices; indices = other.indices; return *this;}
-
// The vertices of a triangle are given by: (x[i[n]], y[i[n]]), (x[j[n]], y[j[n]]), (x[k[n]], y[k[n]]), n = 0, 1, ...
QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...]
QVertexIndexVector indices; // [i[0], j[0], k[0], i[1], j[1], k[1], i[2], ...]
};
-struct Q_GUI_EXPORT QPolylineSet
+struct QPolylineSet
{
- inline QPolylineSet() { }
- inline QPolylineSet(const QPolylineSet &other) : vertices(other.vertices), indices(other.indices) { }
- QPolylineSet &operator = (const QPolylineSet &other) {vertices = other.vertices; indices = other.indices; return *this;}
-
QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...]
QVertexIndexVector indices; // End of polyline is marked with -1.
};
diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h
index d1b08ed423..df5772d4cc 100644
--- a/src/gui/painting/qvectorpath_p.h
+++ b/src/gui/painting/qvectorpath_p.h
@@ -99,13 +99,14 @@ public:
// Shape rendering specifiers...
OddEvenFill = 0x1000,
WindingFill = 0x2000,
- ImplicitClose = 0x4000
+ ImplicitClose = 0x4000,
+ ExplicitOpen = 0x8000
};
// ### Falcon: introduca a struct XY for points so lars is not so confused...
QVectorPath(const qreal *points,
int count,
- const QPainterPath::ElementType *elements = 0,
+ const QPainterPath::ElementType *elements = nullptr,
uint hints = ArbitraryShapeHint)
: m_elements(elements),
m_points(points),
@@ -124,14 +125,15 @@ public:
inline bool isCacheable() const { return m_hints & ShouldUseCacheHint; }
inline bool hasImplicitClose() const { return m_hints & ImplicitClose; }
+ inline bool hasExplicitOpen() const { return m_hints & ExplicitOpen; }
inline bool hasWindingFill() const { return m_hints & WindingFill; }
- inline void makeCacheable() const { m_hints |= ShouldUseCacheHint; m_cache = 0; }
+ inline void makeCacheable() const { m_hints |= ShouldUseCacheHint; m_cache = nullptr; }
inline uint hints() const { return m_hints; }
inline const QPainterPath::ElementType *elements() const { return m_elements; }
inline const qreal *points() const { return m_points; }
- inline bool isEmpty() const { return m_points == 0; }
+ inline bool isEmpty() const { return m_points == nullptr; }
inline int elementCount() const { return m_count; }
inline const QPainterPath convertToPainterPath() const;
@@ -142,7 +144,7 @@ public:
case QPaintEngine::ConvexMode: return ConvexPolygonHint | ImplicitClose;
case QPaintEngine::OddEvenMode: return PolygonHint | OddEvenFill | ImplicitClose;
case QPaintEngine::WindingMode: return PolygonHint | WindingFill | ImplicitClose;
- case QPaintEngine::PolylineMode: return PolygonHint;
+ case QPaintEngine::PolylineMode: return PolygonHint | ExplicitOpen;
default: return 0;
}
}
@@ -163,7 +165,7 @@ public:
return e;
e = e->next;
}
- return 0;
+ return nullptr;
}
template <typename T> static inline bool isRect(const T *pts, int elementCount) {
@@ -194,7 +196,7 @@ public:
private:
- Q_DISABLE_COPY(QVectorPath)
+ Q_DISABLE_COPY_MOVE(QVectorPath)
const QPainterPath::ElementType *m_elements;
const qreal *m_points;
diff --git a/src/gui/platform/platform.pri b/src/gui/platform/platform.pri
new file mode 100644
index 0000000000..1fe2db81b0
--- /dev/null
+++ b/src/gui/platform/platform.pri
@@ -0,0 +1 @@
+wasm:include(wasm/wasm.pri)
diff --git a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
new file mode 100644
index 0000000000..83f9415c69
--- /dev/null
+++ b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmlocalfileaccess_p.h"
+#include <private/qstdweb_p.h>
+#include <emscripten.h>
+#include <emscripten/bind.h>
+#include <emscripten/html5.h>
+#include <emscripten/val.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QWasmLocalFileAccess {
+
+void streamFile(const qstdweb::File &file, uint32_t offset, uint32_t length, char *buffer, const std::function<void ()> &completed)
+{
+ // Read file in chunks in order to avoid holding two copies in memory at the same time
+ const uint32_t chunkSize = 256 * 1024;
+ const uint32_t end = offset + length;
+ // assert end < file.size
+ auto fileReader = std::make_shared<qstdweb::FileReader>();
+
+ auto chunkCompleted = std::make_shared<std::function<void (uint32_t, char *buffer)>>();
+ *chunkCompleted = [=](uint32_t chunkBegin, char *chunkBuffer) mutable {
+
+ // Copy current chunk from JS memory to Wasm memory
+ qstdweb::ArrayBuffer result = fileReader->result();
+ qstdweb::Uint8Array(result).copyTo(chunkBuffer);
+
+ // Read next chunk if not at buffer end
+ uint32_t nextChunkBegin = std::min(chunkBegin + result.byteLength(), end);
+ uint32_t nextChunkEnd = std::min(nextChunkBegin + chunkSize, end);
+ if (nextChunkBegin == end) {
+ completed();
+ chunkCompleted.reset();
+ return;
+ }
+ char *nextChunkBuffer = chunkBuffer + result.byteLength();
+ fileReader->onLoad([=]() { (*chunkCompleted)(nextChunkBegin, nextChunkBuffer); });
+ qstdweb::Blob blob = file.slice(nextChunkBegin, nextChunkEnd);
+ fileReader->readAsArrayBuffer(blob);
+ };
+
+ // Read first chunk. First iteration is a dummy iteration with no available data.
+ (*chunkCompleted)(offset, buffer);
+}
+
+void streamFile(const qstdweb::File &file, char *buffer, const std::function<void ()> &completed)
+{
+ streamFile(file, 0, file.size(), buffer, completed);
+}
+
+void readFiles(const qstdweb::FileList &fileList,
+ const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
+ const std::function<void ()> &fileDataReady)
+{
+ auto readFile = std::make_shared<std::function<void(int)>>();
+
+ *readFile = [=](int fileIndex) mutable {
+ // Stop when all files have been processed
+ if (fileIndex >= fileList.length()) {
+ readFile.reset();
+ return;
+ }
+
+ const qstdweb::File file = fileList[fileIndex];
+
+ // Ask caller if the file should be accepted
+ char *buffer = acceptFile(file.size(), file.name());
+ if (buffer == nullptr) {
+ (*readFile)(fileIndex + 1);
+ return;
+ }
+
+ // Read file data into caller-provided buffer
+ streamFile(file, buffer, [=]() {
+ fileDataReady();
+ (*readFile)(fileIndex + 1);
+ });
+ };
+
+ (*readFile)(0);
+}
+
+typedef std::function<void (const qstdweb::FileList &fileList)> OpenFileDialogCallback;
+void openFileDialog(const std::string &accept, FileSelectMode fileSelectMode,
+ const OpenFileDialogCallback &filesSelected)
+{
+ // Create file input html element which will display a native file dialog
+ // and call back to our onchange handler once the user has selected
+ // one or more files.
+ emscripten::val document = emscripten::val::global("document");
+ emscripten::val input = document.call<emscripten::val>("createElement", std::string("input"));
+ input.set("type", "file");
+ input.set("style", "display:none");
+ input.set("accept", emscripten::val(accept));
+ input.set("multiple", emscripten::val(fileSelectMode == MultipleFiles));
+
+ // Note: there is no event in case the user cancels the file dialog.
+ static std::unique_ptr<qstdweb::EventCallback> changeEvent;
+ auto callback = [=]() { filesSelected(qstdweb::FileList(input["files"])); };
+ changeEvent.reset(new qstdweb::EventCallback(input, "change", callback));
+
+ // Activate file input
+ emscripten::val body = document["body"];
+ body.call<void>("appendChild", input);
+ input.call<void>("click");
+ body.call<void>("removeChild", input);
+}
+
+void openFiles(const std::string &accept, FileSelectMode fileSelectMode,
+ const std::function<void (int fileCount)> &fileDialogClosed,
+ const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
+ const std::function<void()> &fileDataReady)
+{
+ openFileDialog(accept, fileSelectMode, [=](const qstdweb::FileList &files) {
+ fileDialogClosed(files.length());
+ readFiles(files, acceptFile, fileDataReady);
+ });
+}
+
+void openFile(const std::string &accept,
+ const std::function<void (bool fileSelected)> &fileDialogClosed,
+ const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
+ const std::function<void()> &fileDataReady)
+{
+ auto fileDialogClosedWithInt = [=](int fileCount) { fileDialogClosed(fileCount != 0); };
+ openFiles(accept, FileSelectMode::SingleFile, fileDialogClosedWithInt, acceptFile, fileDataReady);
+}
+
+} // namespace QWasmLocalFileAccess
+
+QT_END_NAMESPACE
diff --git a/src/gui/platform/wasm/qwasmlocalfileaccess_p.h b/src/gui/platform/wasm/qwasmlocalfileaccess_p.h
new file mode 100644
index 0000000000..794db8d9b2
--- /dev/null
+++ b/src/gui/platform/wasm/qwasmlocalfileaccess_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMLOCALFILEACCESS_P_H
+#define QWASMLOCALFILEACCESS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qglobal.h>
+#include <cstdint>
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+namespace QWasmLocalFileAccess {
+
+enum FileSelectMode { SingleFile, MultipleFiles };
+
+void openFiles(const std::string &accept, FileSelectMode fileSelectMode,
+ const std::function<void (int fileCount)> &fileDialogClosed,
+ const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
+ const std::function<void()> &fileDataReady);
+
+void openFile(const std::string &accept,
+ const std::function<void (bool fileSelected)> &fileDialogClosed,
+ const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
+ const std::function<void()> &fileDataReady);
+
+} // namespace QWasmLocalFileAccess
+
+QT_END_NAMESPACE
+
+#endif // QWASMLOCALFILEACCESS_P_H
diff --git a/src/gui/platform/wasm/wasm.pri b/src/gui/platform/wasm/wasm.pri
new file mode 100644
index 0000000000..1b5d7eadb5
--- /dev/null
+++ b/src/gui/platform/wasm/wasm.pri
@@ -0,0 +1,3 @@
+INCLUDEDIR += $$PWD
+HEADERS += $$PWD/qwasmlocalfileaccess_p.h
+SOURCES += $$PWD/qwasmlocalfileaccess.cpp
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
new file mode 100644
index 0000000000..8cd4813723
--- /dev/null
+++ b/src/gui/rhi/qrhi.cpp
@@ -0,0 +1,4891 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrhi_p_p.h"
+#include <qmath.h>
+
+#include "qrhinull_p_p.h"
+#ifndef QT_NO_OPENGL
+#include "qrhigles2_p_p.h"
+#endif
+#if QT_CONFIG(vulkan)
+#include "qrhivulkan_p_p.h"
+#endif
+#ifdef Q_OS_WIN
+#include "qrhid3d11_p_p.h"
+#endif
+//#ifdef Q_OS_DARWIN
+#ifdef Q_OS_MACOS
+#include "qrhimetal_p_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QRhi
+ \inmodule QtRhi
+
+ \brief Accelerated 2D/3D graphics API abstraction.
+
+ The Qt Rendering Hardware Interface is an abstraction for hardware accelerated
+ graphics APIs, such as, \l{https://www.khronos.org/opengl/}{OpenGL},
+ \l{https://www.khronos.org/opengles/}{OpenGL ES},
+ \l{https://docs.microsoft.com/en-us/windows/desktop/direct3d}{Direct3D},
+ \l{https://developer.apple.com/metal/}{Metal}, and
+ \l{https://www.khronos.org/vulkan/}{Vulkan}.
+
+ Some of the main design goals are:
+
+ \list
+
+ \li Simple, minimal, understandable, extensible. Follow the proven path of the
+ Qt Quick scenegraph.
+
+ \li Aim to be a product - and in the bigger picture, part of a product (Qt) -
+ that is usable out of the box both by internal (such as, Qt Quick) and,
+ eventually, external users.
+
+ \li Not a complete 1:1 wrapper for any of the underlying APIs. The feature set
+ is tuned towards the needs of Qt's 2D and 3D offering (QPainter, Qt Quick, Qt
+ 3D Studio). Iterate and evolve in a sustainable manner.
+
+ \li Intrinsically cross-platform, without reinventing: abstracting
+ cross-platform aspects of certain APIs (such as, OpenGL context creation and
+ windowing system interfaces, Vulkan instance and surface management) is not in
+ scope here. These are delegated to the existing QtGui facilities (QWindow,
+ QOpenGLContext, QVulkanInstance) and its backing QPA architecture.
+
+ \endlist
+
+ Each QRhi instance is backed by a backend for a specific graphics API. The
+ selection of the backend is a run time choice and is up to the application
+ or library that creates the QRhi instance. Some backends are available on
+ multiple platforms (OpenGL, Vulkan, Null), while APIs specific to a given
+ platform are only available when running on the platform in question (Metal
+ on macOS/iOS/tvOS, Direct3D on Windows).
+
+ The available backends currently are:
+
+ \list
+
+ \li OpenGL 2.1 or OpenGL ES 2.0 or newer. Some extensions are utilized when
+ present, for example to enable multisample framebuffers.
+
+ \li Direct3D 11.1
+
+ \li Metal
+
+ \li Vulkan 1.0, optionally with some extensions that are part of Vulkan 1.1
+
+ \li Null - A "dummy" backend that issues no graphics calls at all.
+
+ \endlist
+
+ In order to allow shader code to be written once in Qt applications and
+ libraries, all shaders are expected to be written in a single language
+ which is then compiled into SPIR-V. Versions for various shading language
+ are then generated from that, together with reflection information (inputs,
+ outputs, shader resources). This is then packed into easily and efficiently
+ serializable QShader instances. The compilers and tools to generate such
+ shaders are not part of QRhi, but the core classes for using such shaders,
+ QShader and QShaderDescription, are.
+
+ \section2 Design Fundamentals
+
+ A QRhi cannot be instantiated directly. Instead, use the create()
+ function. Delete the QRhi instance normally to release the graphics device.
+
+ \section3 Resources
+
+ Instances of classes deriving from QRhiResource, such as, QRhiBuffer,
+ QRhiTexture, etc., encapsulate zero, one, or more native graphics
+ resources. Instances of such classes are always created via the \c new
+ functions of the QRhi, such as, newBuffer(), newTexture(),
+ newTextureRenderTarget(), newSwapChain().
+
+ \badcode
+ vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ if (!vbuf->build()) { error }
+ ...
+ delete vbuf;
+ \endcode
+
+ \list
+
+ \li The returned value from both create() and functions like newBuffer() is
+ owned by the caller.
+
+ \li Just creating a QRhiResource subclass never allocates or initializes any
+ native resources. That is only done when calling the \c build function of a
+ subclass, for example, QRhiBuffer::build() or QRhiTexture::build().
+
+ \li The exception is
+ QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() and
+ QRhiSwapChain::newCompatibleRenderPassDescriptor(). There is no \c build
+ operation for these and the returned object is immediately active.
+
+ \li The resource objects themselves are treated as immutable: once a
+ resource is built, changing any parameters via the setters, such as,
+ QRhiTexture::setPixelSize(), has no effect, unless the underlying native
+ resource is released and \c build is called again. See more about resource
+ reuse in the sections below.
+
+ \li The underlying native resources are scheduled for releasing by the
+ QRhiResource destructor, or by calling QRhiResource::release(). Backends
+ often queue release requests and defer executing them to an unspecified
+ time, this is hidden from the applications. This way applications do not
+ have to worry about releasing native resources that may still be in use by
+ an in-flight frame.
+
+ \li Note that this does not mean that a QRhiResource can freely be
+ destroyed or release()'d within a frame (that is, in a
+ \l{QRhiCommandBuffer::beginFrame()}{beginFrame()} -
+ \l{QRhiCommandBuffer::endFrame()}{endFrame()} section). As a general rule,
+ all referenced QRhiResource objects must stay unchanged until the frame is
+ submitted by calling \l{QRhiCommandBuffer::endFrame()}{endFrame()}. To ease
+ this, QRhiResource::releaseAndDestroyLater() is provided as a convenience.
+
+ \endlist
+
+ \section3 Command buffers and deferred command execution
+
+ Regardless of the design and capabilities of the underlying graphics API,
+ all QRhi backends implement some level of command buffers. No
+ QRhiCommandBuffer function issues any native bind or draw command (such as,
+ \c glDrawElements) directly. Commands are always recorded in a queue,
+ either native or provided by the QRhi backend. The command buffer is
+ submitted, and so execution starts only upon QRhi::endFrame() or
+ QRhi::finish().
+
+ The deferred nature has consequences for some types of objects. For example,
+ writing to a dynamic buffer multiple times within a frame, in case such
+ buffers are backed by host-visible memory, will result in making the
+ results of all writes are visible to all draw calls in the command buffer
+ of the frame, regardless of when the dynamic buffer update was recorded
+ relative to a draw call.
+
+ Furthermore, instances of QRhiResource subclasses must be treated immutable
+ within a frame in which they are referenced in any way. Create or rebuild
+ all resources upfront, before starting to record commands for the next
+ frame. Reusing a QRhiResource instance within a frame (by rebuilding it and
+ then referencing it again in the same \c{beginFrame - endFrame} section)
+ should be avoided as it may lead to unexpected results, depending on the
+ backend.
+
+ As a general rule, all referenced QRhiResource objects must stay valid and
+ unmodified until the frame is submitted by calling
+ \l{QRhiCommandBuffer::endFrame()}{endFrame()}. On the other hand, calling
+ \l{QRhiResource::release()}{release()} or destroying the QRhiResource are
+ always safe once the frame is submitted, regardless of the status of the
+ underlying native resources (which may still be in use by the GPU - but
+ that is taken care of internally).
+
+ Unlike APIs like OpenGL, upload and copy type of commands cannot be mixed
+ with draw commands. The typical renderer will involve a sequence similar to
+ the following: \c{(re)build resources} - \c{begin frame} - \c{record
+ uploads and copies} - \c{start renderpass} - \c{record draw calls} - \c{end
+ renderpass} - \c{end frame}. Recording copy type of operations happens via
+ QRhiResourceUpdateBatch. Such operations are committed typically on
+ \l{QRhiCommandBuffer::beginPass()}{beginPass()}.
+
+ When working with legacy rendering engines designed for OpenGL, the
+ migration to QRhi often involves redesigning from having a single \c render
+ step (that performs copies and uploads, clears buffers, and issues draw
+ calls, all mixed together) to a clearly separated, two phase \c prepare -
+ \c render setup where the \c render step only starts a renderpass and
+ records draw calls, while all resource creation and queuing of updates,
+ uploads and copies happens beforehand, in the \c prepare step.
+
+ QRhi does not at the moment allow freely creating and submitting command
+ buffers. This may be lifted in the future to some extent, in particular if
+ compute support is introduced, but the model of well defined
+ \c{frame-start} and \c{frame-end} points, combined with a dedicated,
+ "frame" command buffer, where \c{frame-end} implies presenting, is going to
+ remain the primary way of operating since this is what fits Qt's various UI
+ technologies best.
+
+ \section3 Threading
+
+ A QRhi instance and the associated resources can be created and used on any
+ thread but all usage must be limited to that one single thread. When
+ rendering to multiple QWindows in an application, having a dedicated thread
+ and QRhi instance for each window is often advisable, as this can eliminate
+ issues with unexpected throttling caused by presenting to multiple windows.
+ Conceptually that is then the same as how Qt Quick scene graph's threaded
+ render loop operates when working directly with OpenGL: one thread for each
+ window, one QOpenGLContext for each thread. When moving onto QRhi,
+ QOpenGLContext is replaced by QRhi, making the migration straightforward.
+
+ When it comes to externally created native objects, such as OpenGL contexts
+ passed in via QRhiGles2NativeHandles, it is up to the application to ensure
+ they are not misused by other threads.
+
+ Resources are not shareable between QRhi instances. This is an intentional
+ choice since QRhi hides most queue, command buffer, and resource
+ synchronization related tasks, and provides no API for them. Safe and
+ efficient concurrent use of graphics resources from multiple threads is
+ tied to those concepts, however, and is thus a topic that is currently out
+ of scope, but may be introduced in the future.
+
+ \section3 Resource synchronization
+
+ QRhi does not expose APIs for resource barriers or image layout
+ transitions. Such synchronization is done implicitly by the backends, where
+ applicable (for example, Vulkan), by tracking resource usage as necessary.
+
+ \section3 Resource reuse
+
+ From the user's point of view a QRhiResource is reusable immediately after
+ calling QRhiResource::release(). With the exception of swapchains, calling
+ \c build() on an already built object does an implicit \c release(). This
+ provides a handy shortcut to reuse a QRhiResource instance with different
+ parameters, with a new native graphics object underneath.
+
+ The importance of reusing the same object lies in the fact that some
+ objects reference other objects: for example, a QRhiShaderResourceBindings
+ can reference QRhiBuffer, QRhiTexture, and QRhiSampler instances. If in a
+ later frame one of these buffers need to be resized or a sampler parameter
+ needs changing, destroying and creating a whole new QRhiBuffer or
+ QRhiSampler would invalidate all references to the old instance. By just
+ changing the appropriate parameters via QRhiBuffer::setSize() or similar
+ and then calling QRhiBuffer::build(), everything works as expected and
+ there is no need to touch the QRhiShaderResourceBindings at all, even
+ though there is a good chance that under the hood the QRhiBuffer is now
+ backed by a whole new native buffer.
+
+ \badcode
+ ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
+ ubuf->build();
+
+ srb = rhi->newShaderResourceBindings()
+ srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
+ });
+ srb->build();
+
+ ...
+
+ // now in a later frame we need to grow the buffer to a larger size
+ ubuf->setSize(512);
+ ubuf->build(); // same as ubuf->release(); ubuf->build();
+
+ // that's it, srb needs no changes whatsoever
+ \endcode
+
+ \section3 Pooled objects
+
+ In addition to resources, there are pooled objects as well, such as,
+ QRhiResourceUpdateBatch. An instance is retrieved via a \c next function,
+ such as, nextResourceUpdateBatch(). The caller does not own the returned
+ instance in this case. The only valid way of operating here is calling
+ functions on the QRhiResourceUpdateBatch and then passing it to
+ QRhiCommandBuffer::beginPass() or QRhiCommandBuffer::endPass(). These
+ functions take care of returning the batch to the pool. Alternatively, a
+ batch can be "canceled" and returned to the pool without processing by
+ calling QRhiResourceUpdateBatch::release().
+
+ A typical pattern is thus:
+
+ \badcode
+ QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
+ ...
+ resUpdates->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
+ if (!image.isNull()) {
+ resUpdates->uploadTexture(texture, image);
+ image = QImage();
+ }
+ ...
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ cb->beginPass(swapchain->currentFrameRenderTarget(), clearCol, clearDs, resUpdates);
+ \endcode
+
+ \section3 Swapchain specifics
+
+ QRhiSwapChain features some special semantics due to the peculiar nature of
+ swapchains.
+
+ \list
+
+ \li It has no \c build but rather a QRhiSwapChain::buildOrResize().
+ Repeatedly calling this function is \b not the same as calling
+ QRhiSwapChain::release() followed by QRhiSwapChain::buildOrResize(). This
+ is because swapchains often have ways to handle the case where buffers need
+ to be resized in a manner that is more efficient than a brute force
+ destroying and recreating from scratch.
+
+ \li An active QRhiSwapChain must be released by calling
+ \l{QRhiSwapChain::release()}{release()}, or by destroying the object, before
+ the QWindow's underlying QPlatformWindow, and so the associated native
+ window object, is destroyed. It should not be postponed because releasing
+ the swapchain may become problematic (and with some APIs, like Vulkan, is
+ explicitly disallowed) when the native window is not around anymore, for
+ example because the QPlatformWindow got destroyed upon getting a
+ QWindow::close(). Therefore, releasing the swapchain must happen whenever
+ the targeted QWindow sends the
+ QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed event. If the event does
+ not arrive before the destruction of the QWindow - this can happen when
+ using QCoreApplication::quit() -, then check QWindow::handle() after the
+ event loop exits and invoke the swapchain release when non-null (meaning
+ the underlying native window is still around).
+
+ \endlist
+
+ \section3 Ownership
+
+ The general rule is no ownership transfer. Creating a QRhi with an already
+ existing graphics device does not mean the QRhi takes ownership of the
+ device object. Similarly, ownership is not given away when a device or
+ texture object is "exported" via QRhi::nativeHandles() or
+ QRhiTexture::nativeHandles(). Most importantly, passing pointers in structs
+ and via setters does not transfer ownership.
+ */
+
+/*!
+ \enum QRhi::Implementation
+ Describes which graphics API-specific backend gets used by a QRhi instance.
+
+ \value Null
+ \value Vulkan
+ \value OpenGLES2
+ \value D3D11
+ \value Metal
+ */
+
+/*!
+ \enum QRhi::Flag
+ Describes what special features to enable.
+
+ \value EnableProfiling Enables gathering timing (CPU, GPU) and resource
+ (QRhiBuffer, QRhiTexture, etc.) information and additional metadata. See
+ QRhiProfiler. Avoid enabling in production builds as it may involve a
+ performance penalty.
+
+ \value EnableDebugMarkers Enables debug marker groups. Without this frame
+ debugging features like making debug groups and custom resource name
+ visible in external GPU debugging tools will not be available and functions
+ like QRhiCommandBuffer::debugMarkBegin() will become a no-op. Avoid
+ enabling in production builds as it may involve a performance penalty.
+ */
+
+/*!
+ \enum QRhi::FrameOpResult
+ Describes the result of operations that can have a soft failure.
+
+ \value FrameOpSuccess Success
+
+ \value FrameOpError Unspecified error
+
+ \value FrameOpSwapChainOutOfDate The swapchain is in an inconsistent state
+ internally. This can be recoverable by attempting to repeat the operation
+ (such as, beginFrame()) later.
+
+ \value FrameOpDeviceLost The graphics device was lost. This can be
+ recoverable by attempting to repeat the operation (such as, beginFrame())
+ and releasing and reinitializing all objects backed by native graphics
+ resources.
+ */
+
+/*!
+ \enum QRhi::Feature
+ Flag values to indicate what features are supported by the backend currently in use.
+
+ \value MultisampleTexture Indicates that textures with a sample count larger
+ than 1 are supported.
+
+ \value MultisampleRenderBuffer Indicates that renderbuffers with a sample
+ count larger than 1 are supported.
+
+ \value DebugMarkers Indicates that debug marker groups (and so
+ QRhiCommandBuffer::debugMarkBegin()) are supported.
+
+ \value Timestamps Indicates that command buffer timestamps are supported.
+ Relevant for QRhiProfiler::gpuFrameTimes().
+
+ \value Instancing Indicates that instanced drawing is supported.
+
+ \value CustomInstanceStepRate Indicates that instance step rates other than
+ 1 are supported.
+
+ \value PrimitiveRestart Indicates that restarting the assembly of
+ primitives when encountering an index value of 0xFFFF
+ (\l{QRhiCommandBuffer::IndexUInt16}{IndexUInt16}) or 0xFFFFFFFF
+ (\l{QRhiCommandBuffer::IndexUInt32}{IndexUInt32}) is enabled, for certain
+ primitive topologies at least. QRhi will try to enable this with all
+ backends, but in some cases it will not be supported. Dynamically
+ controlling primitive restart is not possible since with some APIs
+ primitive restart with a fixed index is always on. Applications must assume
+ that whenever this feature is reported as supported, the above mentioned
+ index values \c may be treated specially, depending on the topology. The
+ only two topologies where primitive restart is guaranteed to behave
+ identically across backends, as long as this feature is reported as
+ supported, are \l{QRhiGraphicsPipeline::LineStrip}{LineStrip} and
+ \l{QRhiGraphicsPipeline::TriangleStrip}{TriangleStrip}.
+
+ \value NonDynamicUniformBuffers Indicates that creating buffers with the
+ usage \l{QRhiBuffer::UniformBuffer}{UniformBuffer} and the types
+ \l{QRhiBuffer::Immutable}{Immutable} or \l{QRhiBuffer::Static}{Static} is
+ supported. When reported as unsupported, uniform (constant) buffers must be
+ created as \l{QRhiBuffer::Dynamic}{Dynamic}. (which is recommended
+ regardless)
+
+ \value NonFourAlignedEffectiveIndexBufferOffset Indicates that effective
+ index buffer offsets (\c{indexOffset + firstIndex * indexComponentSize})
+ that are not 4 byte aligned are supported. When not supported, attempting
+ to issue a \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} with a
+ non-aligned effective offset may lead to unspecified behavior.
+
+ \value NPOTTextureRepeat Indicates that the \l{QRhiSampler::Repeat}{Repeat}
+ mode is supported for textures with a non-power-of-two size.
+
+ \value RedOrAlpha8IsRed Indicates that the
+ \l{QRhiTexture::RED_OR_ALPHA8}{RED_OR_ALPHA8} format maps to a one
+ component 8-bit \c red format. This is the case for all backends except
+ OpenGL, where \c{GL_ALPHA}, a one component 8-bit \c alpha format, is used
+ instead. This is relevant for shader code that samples from the texture.
+
+ \value ElementIndexUint Indicates that 32-bit unsigned integer elements are
+ supported in the index buffer. In practice this is true everywhere except
+ when running on plain OpenGL ES 2.0 implementations without the necessary
+ extension. When false, only 16-bit unsigned elements are supported in the
+ index buffer.
+ */
+
+/*!
+ \enum QRhi::BeginFrameFlag
+ Flag values for QRhi::beginFrame()
+ */
+
+/*!
+ \enum QRhi::EndFrameFlag
+ Flag values for QRhi::endFrame()
+
+ \value SkipPresent Specifies that no present command is to be queued or no
+ swapBuffers call is to be made. This way no image is presented. Generating
+ multiple frames with all having this flag set is not recommended (except,
+ for example, for benchmarking purposes - but keep in mind that backends may
+ behave differently when it comes to waiting for command completion without
+ presenting so the results are not comparable between them)
+ */
+
+/*!
+ \enum QRhi::ResourceLimit
+ Describes the resource limit to query.
+
+ \value TextureSizeMin Minimum texture width and height. This is typically
+ 1. The minimum texture size is handled gracefully, meaning attempting to
+ create a texture with an empty size will instead create a texture with the
+ minimum size.
+
+ \value TextureSizeMax Maximum texture width and height. This depends on the
+ graphics API and sometimes the platform or implementation as well.
+ Typically the value is in the range 4096 - 16384. Attempting to create
+ textures larger than this is expected to fail.
+
+ \value MaxColorAttachments The maximum number of color attachments for a
+ QRhiTextureRenderTarget, in case multiple render targets are supported. When
+ MRT is not supported, the value is 1. Otherwise this is typically 8, but
+ watch out for the fact that OpenGL only mandates 4 as the minimum, and that
+ is what some OpenGL ES implementations provide.
+
+ \value FramesInFlight The number of frames the backend may keep "in
+ flight". The value has no relevance, and is unspecified, with backends like
+ OpenGL and Direct3D 11. With backends like Vulkan or Metal, it is the
+ responsibility of QRhi to block whenever starting a new frame and finding
+ the CPU is already \c{N - 1} frames ahead of the GPU (because the command
+ buffer submitted in frame no. \c{current} - \c{N} has not yet completed).
+ The value N is what is returned from here, and is typically 2. This can be
+ relevant to applications that integrate rendering done directly with the
+ graphics API, as such rendering code may want to perform double (if the
+ value is 2) buffering for resources, such as, buffers, similarly to the
+ QRhi backends themselves. The current frame slot index (a value running 0,
+ 1, .., N-1, then wrapping around) is retrievable from
+ QRhi::currentFrameSlot().
+ */
+
+/*!
+ \class QRhiInitParams
+ \inmodule QtRhi
+ \brief Base class for backend-specific initialization parameters.
+
+ Contains fields that are relevant to all backends.
+ */
+
+/*!
+ \class QRhiDepthStencilClearValue
+ \inmodule QtRhi
+ \brief Specifies clear values for a depth or stencil buffer.
+ */
+
+/*!
+ \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue()
+
+ Constructs a depth/stencil clear value with depth clear value 1.0f and
+ stencil clear value 0.
+ */
+
+/*!
+ Constructs a depth/stencil clear value with depth clear value \a d and
+ stencil clear value \a s.
+ */
+QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
+ : m_d(d),
+ m_s(s)
+{
+}
+
+/*!
+ \return \c true if the values in the two QRhiDepthStencilClearValue objects
+ \a a and \a b are equal.
+
+ \relates QRhiDepthStencilClearValue
+ */
+bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW
+{
+ return a.depthClearValue() == b.depthClearValue()
+ && a.stencilClearValue() == b.stencilClearValue();
+}
+
+/*!
+ \return \c false if the values in the two QRhiDepthStencilClearValue
+ objects \a a and \a b are equal; otherwise returns \c true.
+
+ \relates QRhiDepthStencilClearValue
+*/
+bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW
+{
+ return !(a == b);
+}
+
+/*!
+ \return the hash value for \a v, using \a seed to seed the calculation.
+
+ \relates QRhiDepthStencilClearValue
+ */
+uint qHash(const QRhiDepthStencilClearValue &v, uint seed) Q_DECL_NOTHROW
+{
+ return seed * (qFloor(v.depthClearValue() * 100) + v.stencilClearValue());
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QRhiDepthStencilClearValue(depth-clear=" << v.depthClearValue()
+ << " stencil-clear=" << v.stencilClearValue()
+ << ')';
+ return dbg;
+}
+#endif
+
+/*!
+ \class QRhiViewport
+ \inmodule QtRhi
+ \brief Specifies a viewport rectangle.
+
+ Used with QRhiCommandBuffer::setViewport().
+
+ \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
+ bottom-left.
+
+ Typical usage is like the following:
+
+ \badcode
+ const QSize outputSizeInPixels = swapchain->currentPixelSize();
+ const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
+ cb->beginPass(swapchain->currentFrameRenderTarget(), { 0, 0, 0, 1 }, { 1, 0 });
+ cb->setGraphicsPipeline(ps);
+ cb->setViewport(viewport);
+ ...
+ \endcode
+
+ \sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
+ */
+
+/*!
+ \fn QRhiViewport::QRhiViewport()
+
+ Constructs a viewport description with an empty rectangle and a depth range
+ of 0.0f - 1.0f.
+
+ \sa QRhi::clipSpaceCorrMatrix()
+ */
+
+/*!
+ Constructs a viewport description with the rectangle specified by \a x, \a
+ y, \a w, \a h and the depth range \a minDepth and \a maxDepth.
+
+ \note x and y are assumed to be the bottom-left position.
+
+ \sa QRhi::clipSpaceCorrMatrix()
+ */
+QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, float maxDepth)
+ : m_rect { { x, y, w, h } },
+ m_minDepth(minDepth),
+ m_maxDepth(maxDepth)
+{
+}
+
+/*!
+ \return \c true if the values in the two QRhiViewport objects
+ \a a and \a b are equal.
+
+ \relates QRhiViewport
+ */
+bool operator==(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW
+{
+ return a.viewport() == b.viewport()
+ && a.minDepth() == b.minDepth()
+ && a.maxDepth() == b.maxDepth();
+}
+
+/*!
+ \return \c false if the values in the two QRhiViewport
+ objects \a a and \a b are equal; otherwise returns \c true.
+
+ \relates QRhiViewport
+*/
+bool operator!=(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW
+{
+ return !(a == b);
+}
+
+/*!
+ \return the hash value for \a v, using \a seed to seed the calculation.
+
+ \relates QRhiViewport
+ */
+uint qHash(const QRhiViewport &v, uint seed) Q_DECL_NOTHROW
+{
+ const std::array<float, 4> r = v.viewport();
+ return seed + r[0] + r[1] + r[2] + r[3] + qFloor(v.minDepth() * 100) + qFloor(v.maxDepth() * 100);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiViewport &v)
+{
+ QDebugStateSaver saver(dbg);
+ const std::array<float, 4> r = v.viewport();
+ dbg.nospace() << "QRhiViewport(bottom-left-x=" << r[0]
+ << " bottom-left-y=" << r[1]
+ << " width=" << r[2]
+ << " height=" << r[3]
+ << " minDepth=" << v.minDepth()
+ << " maxDepth=" << v.maxDepth()
+ << ')';
+ return dbg;
+}
+#endif
+
+/*!
+ \class QRhiScissor
+ \inmodule QtRhi
+ \brief Specifies a scissor rectangle.
+
+ Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
+ only possible with a QRhiGraphicsPipeline that has
+ QRhiGraphicsPipeline::UsesScissor set.
+
+ \note QRhi assumes OpenGL-style scissor coordinates, meaning x and y are
+ bottom-left.
+
+ \sa QRhiCommandBuffer::setScissor(), QRhiViewport
+ */
+
+/*!
+ \fn QRhiScissor::QRhiScissor()
+
+ Constructs an empty scissor.
+ */
+
+/*!
+ Constructs a scissor with the rectangle specified by \a x, \a y, \a w, and
+ \a h.
+
+ \note x and y are assumed to be the bottom-left position.
+ */
+QRhiScissor::QRhiScissor(int x, int y, int w, int h)
+ : m_rect { { x, y, w, h } }
+{
+}
+
+/*!
+ \return \c true if the values in the two QRhiScissor objects
+ \a a and \a b are equal.
+
+ \relates QRhiScissor
+ */
+bool operator==(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW
+{
+ return a.scissor() == b.scissor();
+}
+
+/*!
+ \return \c false if the values in the two QRhiScissor
+ objects \a a and \a b are equal; otherwise returns \c true.
+
+ \relates QRhiScissor
+*/
+bool operator!=(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW
+{
+ return !(a == b);
+}
+
+/*!
+ \return the hash value for \a v, using \a seed to seed the calculation.
+
+ \relates QRhiScissor
+ */
+uint qHash(const QRhiScissor &v, uint seed) Q_DECL_NOTHROW
+{
+ const std::array<int, 4> r = v.scissor();
+ return seed + r[0] + r[1] + r[2] + r[3];
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiScissor &s)
+{
+ QDebugStateSaver saver(dbg);
+ const std::array<int, 4> r = s.scissor();
+ dbg.nospace() << "QRhiScissor(bottom-left-x=" << r[0]
+ << " bottom-left-y=" << r[1]
+ << " width=" << r[2]
+ << " height=" << r[3]
+ << ')';
+ return dbg;
+}
+#endif
+
+/*!
+ \class QRhiVertexInputBinding
+ \inmodule QtRhi
+ \brief Describes a vertex input binding.
+
+ Specifies the stride (in bytes, must be a multiple of 4), the
+ classification and optionally the instance step rate.
+
+ As an example, assume a vertex shader with the following inputs:
+
+ \badcode
+ layout(location = 0) in vec4 position;
+ layout(location = 1) in vec2 texcoord;
+ \endcode
+
+ Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
+ component texture coordinates \c{(u, v)} are provided in a non-interleaved
+ format in a buffer (or separate buffers even). Definining two bindings
+ could then be done like this:
+
+ \badcode
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ \endcode
+
+ Only the stride is interesting here since instancing is not used. The
+ binding number is given by the index of the QRhiVertexInputBinding
+ element in the bindings vector of the QRhiVertexInputLayout.
+
+ Once a graphics pipeline with this vertex input layout is bound, the vertex
+ inputs could be set up like the following for drawing a cube with 36
+ vertices, assuming we have a single buffer with first the positions and
+ then the texture coordinates:
+
+ \badcode
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { cubeBuf, 0 },
+ { cubeBuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ \endcode
+
+ Note how the index defined by \c {startBinding + i}, where \c i is the
+ index in the second argument of
+ \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}, matches the
+ index of the corresponding entry in the \c bindings vector of the
+ QRhiVertexInputLayout.
+
+ \note the stride must always be a multiple of 4.
+
+ \sa QRhiCommandBuffer::setVertexInput()
+ */
+
+/*!
+ \enum QRhiVertexInputBinding::Classification
+ Describes the input data classification.
+
+ \value PerVertex Data is per-vertex
+ \value PerInstance Data is per-instance
+ */
+
+/*!
+ \fn QRhiVertexInputBinding::QRhiVertexInputBinding()
+
+ Constructs a default vertex input binding description.
+ */
+
+/*!
+ Constructs a vertex input binding description with the specified \a stride,
+ classification \a cls, and instance step rate \a stepRate.
+
+ \note \a stepRate other than 1 is only supported when
+ QRhi::CustomInstanceStepRate is reported to be supported.
+ */
+QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, int stepRate)
+ : m_stride(stride),
+ m_classification(cls),
+ m_instanceStepRate(stepRate)
+{
+}
+
+/*!
+ \return \c true if the values in the two QRhiVertexInputBinding objects
+ \a a and \a b are equal.
+
+ \relates QRhiVertexInputBinding
+ */
+bool operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW
+{
+ return a.stride() == b.stride()
+ && a.classification() == b.classification()
+ && a.instanceStepRate() == b.instanceStepRate();
+}
+
+/*!
+ \return \c false if the values in the two QRhiVertexInputBinding
+ objects \a a and \a b are equal; otherwise returns \c true.
+
+ \relates QRhiVertexInputBinding
+*/
+bool operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW
+{
+ return !(a == b);
+}
+
+/*!
+ \return the hash value for \a v, using \a seed to seed the calculation.
+
+ \relates QRhiVertexInputBinding
+ */
+uint qHash(const QRhiVertexInputBinding &v, uint seed) Q_DECL_NOTHROW
+{
+ return seed + v.stride() + v.classification();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QRhiVertexInputBinding(stride=" << b.stride()
+ << " cls=" << b.classification()
+ << " step-rate=" << b.instanceStepRate()
+ << ')';
+ return dbg;
+}
+#endif
+
+/*!
+ \class QRhiVertexInputAttribute
+ \inmodule QtRhi
+ \brief Describes a single vertex input element.
+
+ The members specify the binding number, location, format, and offset for a
+ single vertex input element.
+
+ \note For HLSL it is assumed that the vertex shader uses
+ \c{TEXCOORD<location>} as the semantic for each input. Hence no separate
+ semantic name and index.
+
+ As an example, assume a vertex shader with the following inputs:
+
+ \badcode
+ layout(location = 0) in vec4 position;
+ layout(location = 1) in vec2 texcoord;
+ \endcode
+
+ Now let's assume that we have 3 component vertex positions \c{(x, y, z)}
+ and 2 component texture coordinates \c{(u, v)} are provided in a
+ non-interleaved format in a buffer (or separate buffers even). Once two
+ bindings are defined, the attributes could be specified as:
+
+ \badcode
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+ \endcode
+
+ Once a graphics pipeline with this vertex input layout is bound, the vertex
+ inputs could be set up like the following for drawing a cube with 36
+ vertices, assuming we have a single buffer with first the positions and
+ then the texture coordinates:
+
+ \badcode
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { cubeBuf, 0 },
+ { cubeBuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ \endcode
+
+ When working with interleaved data, there will typically be just one
+ binding, with multiple attributes referring to that same buffer binding
+ point:
+
+ \badcode
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
+ });
+ \endcode
+
+ and then:
+
+ \badcode
+ const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ \endcode
+
+ \sa QRhiCommandBuffer::setVertexInput()
+ */
+
+/*!
+ \enum QRhiVertexInputAttribute::Format
+ Specifies the type of the element data.
+
+ \value Float4 Four component float vector
+ \value Float3 Three component float vector
+ \value Float2 Two component float vector
+ \value Float Float
+ \value UNormByte4 Four component normalized unsigned byte vector
+ \value UNormByte2 Two component normalized unsigned byte vector
+ \value UNormByte Normalized unsigned byte
+ */
+
+/*!
+ \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute()
+
+ Constructs a default vertex input attribute description.
+ */
+
+/*!
+ Constructs a vertex input attribute description with the specified \a
+ binding number, \a location, \a format, and \a offset.
+ */
+QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset)
+ : m_binding(binding),
+ m_location(location),
+ m_format(format),
+ m_offset(offset)
+{
+}
+
+/*!
+ \return \c true if the values in the two QRhiVertexInputAttribute objects
+ \a a and \a b are equal.
+
+ \relates QRhiVertexInputAttribute
+ */
+bool operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW
+{
+ return a.binding() == b.binding()
+ && a.location() == b.location()
+ && a.format() == b.format()
+ && a.offset() == b.offset();
+}
+
+/*!
+ \return \c false if the values in the two QRhiVertexInputAttribute
+ objects \a a and \a b are equal; otherwise returns \c true.
+
+ \relates QRhiVertexInputAttribute
+*/
+bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW
+{
+ return !(a == b);
+}
+
+/*!
+ \return the hash value for \a v, using \a seed to seed the calculation.
+
+ \relates QRhiVertexInputAttribute
+ */
+uint qHash(const QRhiVertexInputAttribute &v, uint seed) Q_DECL_NOTHROW
+{
+ return seed + v.binding() + v.location() + v.format() + v.offset();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QRhiVertexInputAttribute(binding=" << a.binding()
+ << " location=" << a.location()
+ << " format=" << a.format()
+ << " offset=" << a.offset()
+ << ')';
+ return dbg;
+}
+#endif
+
+/*!
+ \class QRhiVertexInputLayout
+ \inmodule QtRhi
+ \brief Describes the layout of vertex inputs consumed by a vertex shader.
+
+ The vertex input layout is defined by the collections of
+ QRhiVertexInputBinding and QRhiVertexInputAttribute.
+ */
+
+/*!
+ \fn QRhiVertexInputLayout::QRhiVertexInputLayout()
+
+ Constructs an empty vertex input layout description.
+ */
+
+/*!
+ \return \c true if the values in the two QRhiVertexInputLayout objects
+ \a a and \a b are equal.
+
+ \relates QRhiVertexInputLayout
+ */
+bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW
+{
+ return a.bindings() == b.bindings()
+ && a.attributes() == b.attributes();
+}
+
+/*!
+ \return \c false if the values in the two QRhiVertexInputLayout
+ objects \a a and \a b are equal; otherwise returns \c true.
+
+ \relates QRhiVertexInputLayout
+*/
+bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW
+{
+ return !(a == b);
+}
+
+/*!
+ \return the hash value for \a v, using \a seed to seed the calculation.
+
+ \relates QRhiVertexInputLayout
+ */
+uint qHash(const QRhiVertexInputLayout &v, uint seed) Q_DECL_NOTHROW
+{
+ return qHash(v.bindings(), seed) + qHash(v.attributes(), seed);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.bindings()
+ << " attributes=" << v.attributes()
+ << ')';
+ return dbg;
+}
+#endif
+
+/*!
+ \class QRhiGraphicsShaderStage
+ \inmodule QtRhi
+ \brief Specifies the type and the shader code for a shader stage in the graphics pipeline.
+ */
+
+/*!
+ \enum QRhiGraphicsShaderStage::Type
+ Specifies the type of the shader stage.
+
+ \value Vertex Vertex stage
+ \value Fragment Fragment (pixel) stage
+ */
+
+/*!
+ \fn QRhiGraphicsShaderStage::QRhiGraphicsShaderStage()
+
+ Constructs a shader stage description for the vertex stage with an empty
+ QShader.
+ */
+
+/*!
+ Constructs a shader stage description with the \a type of the stage and the
+ \a shader.
+
+ The shader variant \a v defaults to QShader::StandardShader. A
+ QShader contains multiple source and binary versions of a shader.
+ In addition, it can also contain variants of the shader with slightly
+ modified code. \a v can then be used to select the desired variant.
+ */
+QRhiGraphicsShaderStage::QRhiGraphicsShaderStage(Type type, const QShader &shader, QShader::Variant v)
+ : m_type(type),
+ m_shader(shader),
+ m_shaderVariant(v)
+{
+}
+
+/*!
+ \return \c true if the values in the two QRhiGraphicsShaderStage objects
+ \a a and \a b are equal.
+
+ \relates QRhiGraphicsShaderStage
+ */
+bool operator==(const QRhiGraphicsShaderStage &a, const QRhiGraphicsShaderStage &b) Q_DECL_NOTHROW
+{
+ return a.type() == b.type()
+ && a.shader() == b.shader()
+ && a.shaderVariant() == b.shaderVariant();
+}
+
+/*!
+ \return \c false if the values in the two QRhiGraphicsShaderStage
+ objects \a a and \a b are equal; otherwise returns \c true.
+
+ \relates QRhiGraphicsShaderStage
+*/
+bool operator!=(const QRhiGraphicsShaderStage &a, const QRhiGraphicsShaderStage &b) Q_DECL_NOTHROW
+{
+ return !(a == b);
+}
+
+/*!
+ \return the hash value for \a v, using \a seed to seed the calculation.
+
+ \relates QRhiGraphicsShaderStage
+ */
+uint qHash(const QRhiGraphicsShaderStage &v, uint seed) Q_DECL_NOTHROW
+{
+ return v.type() + qHash(v.shader(), seed) + v.shaderVariant();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiGraphicsShaderStage &s)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QRhiGraphicsShaderStage(type=" << s.type()
+ << " shader=" << s.shader()
+ << " variant=" << s.shaderVariant()
+ << ')';
+ return dbg;
+}
+#endif
+
+/*!
+ \class QRhiColorAttachment
+ \inmodule QtRhi
+ \brief Describes the a single color attachment of a render target.
+
+ A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
+ former, when texture() is set, is used in most cases.
+
+ \note texture() and renderBuffer() cannot be both set (be non-null at the
+ same time).
+
+ Setting renderBuffer instead is recommended only when multisampling is
+ needed. Relying on QRhi::MultisampleRenderBuffer is a better choice than
+ QRhi::MultisampleTexture in practice since the former is available in more
+ run time configurations (e.g. when running on OpenGL ES 3.0 which has no
+ support for multisample textures, but does support multisample
+ renderbuffers).
+
+ When targeting a non-multisample texture, the layer() and level()
+ indicate the targeted layer (face index \c{0-5} for cubemaps) and mip
+ level.
+
+ When texture() or renderBuffer() is multisample, resolveTexture() can be
+ set optionally. When set, samples are resolved automatically into that
+ (non-multisample) texture at the end of the render pass. When rendering
+ into a multisample renderbuffers, this is the only way to get resolved,
+ non-multisample content out of them. Multisample textures allow sampling in
+ shaders so for them this is just one option.
+
+ \note when resolving is enabled, the multisample data may not be written
+ out at all. This means that the multisample texture() must not be used
+ afterwards with shaders for sampling when resolveTexture() is set.
+ */
+
+/*!
+ \fn QRhiColorAttachment::QRhiColorAttachment()
+
+ Constructs an empty color attachment description.
+ */
+
+/*!
+ Constructs a color attachment description that specifies \a texture as the
+ associated color buffer.
+ */
+QRhiColorAttachment::QRhiColorAttachment(QRhiTexture *texture)
+ : m_texture(texture)
+{
+}
+
+/*!
+ Constructs a color attachment description that specifies \a renderBuffer as
+ the associated color buffer.
+ */
+QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
+ : m_renderBuffer(renderBuffer)
+{
+}
+
+/*!
+ \class QRhiTextureRenderTargetDescription
+ \inmodule QtRhi
+ \brief Describes the color and depth or depth/stencil attachments of a render target.
+
+ A texture render target has zero or more textures as color attachments,
+ zero or one renderbuffer as combined depth/stencil buffer or zero or one
+ texture as depth buffer.
+
+ \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
+ non-null at the same time).
+ */
+
+/*!
+ \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription()
+
+ Constructs an empty texture render target description.
+ */
+
+/*!
+ Constructs a texture render target description with one attachment
+ described by \a colorAttachment.
+ */
+QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment)
+{
+ m_colorAttachments.append(colorAttachment);
+}
+
+/*!
+ Constructs a texture render target description with two attachments, a
+ color attachment described by \a colorAttachment, and a depth/stencil
+ attachment with \a depthStencilBuffer.
+ */
+QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
+ QRhiRenderBuffer *depthStencilBuffer)
+ : m_depthStencilBuffer(depthStencilBuffer)
+{
+ m_colorAttachments.append(colorAttachment);
+}
+
+/*!
+ Constructs a texture render target description with two attachments, a
+ color attachment described by \a colorAttachment, and a depth attachment
+ with \a depthTexture.
+
+ \note \a depthTexture must have a suitable format, such as QRhiTexture::D16
+ or QRhiTexture::D32F.
+ */
+QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment,
+ QRhiTexture *depthTexture)
+ : m_depthTexture(depthTexture)
+{
+ m_colorAttachments.append(colorAttachment);
+}
+
+/*!
+ \class QRhiTextureSubresourceUploadDescription
+ \inmodule QtRhi
+ \brief Describes the source for one mip level in a layer in a texture upload operation.
+
+ The source content is specified either as a QImage or as a raw blob. The
+ former is only allowed for uncompressed textures with a format that can be
+ mapped to QImage, while the latter is supported for all formats, including
+ floating point and compressed.
+
+ \note image() and data() cannot be both set at the same time.
+
+ destinationTopLeft() specifies the top-left corner of the target
+ rectangle. Defaults to (0, 0).
+
+ An empty sourceSize() (the default) indicates that size is assumed to be
+ the size of the subresource. With QImage-based uploads this implies that
+ the size of the source image() must match the subresource. When providing
+ raw data instead, sufficient number of bytes must be provided in data().
+
+ \note With compressed textures the first upload must always match the
+ subresource size due to graphics API limitations with some backends.
+
+ sourceTopLeft() is supported only for QImage-based uploads, and specifies
+ the top-left corner of the source rectangle.
+
+ \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
+ internally, depending on the format and the backend.
+
+ When providing raw data, the stride (row pitch, row length in bytes) of the
+ provided data must be equal to \c{width * pixelSize} where \c pixelSize is
+ the number of bytes used for one pixel, and there must be no additional
+ padding between rows. There is no row start alignment requirement.
+
+ \note The format of the source data must be compatible with the texture
+ format. With many graphics APIs the data is copied as-is into a staging
+ buffer, there is no intermediate format conversion provided by QRhi. This
+ applies to floating point formats as well, with, for example, RGBA16F
+ requiring half floats in the source data.
+ */
+
+/*!
+ \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription()
+
+ Constructs an empty subresource description.
+
+ \note an empty QRhiTextureSubresourceUploadDescription is not useful on its
+ own and should not be submitted to a QRhiTextureUploadEntry. At minimum
+ image or data must be set first.
+ */
+
+/*!
+ Constructs a mip level description with a \a image.
+
+ The \l{QImage::size()}{size} of \a image must match the size of the mip
+ level. For level 0 that is the \l{QRhiTexture::pixelSize()}{texture size}.
+
+ The bit depth of \a image must be compatible with the
+ \l{QRhiTexture::Format}{texture format}.
+
+ To describe a partial upload, call setSourceSize(), setSourceTopLeft(), or
+ setDestinationTopLeft() afterwards.
+ */
+QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const QImage &image)
+ : m_image(image)
+{
+}
+
+/*!
+ Constructs a mip level description with the image data is specified by \a
+ data and \a size. This is suitable for floating point and compressed
+ formats as well.
+
+ \a data can safely be destroyed or changed once this function returns.
+ */
+QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, int size)
+ : m_data(reinterpret_cast<const char *>(data), size)
+{
+}
+
+/*!
+ \class QRhiTextureUploadEntry
+ \inmodule QtRhi
+ \brief Describes one layer (face for cubemaps) in a texture upload operation.
+ */
+
+/*!
+ \fn QRhiTextureUploadEntry::QRhiTextureUploadEntry()
+
+ Constructs an empty QRhiTextureUploadEntry targeting layer 0 and level 0.
+
+ \note an empty QRhiTextureUploadEntry should not be submitted without
+ setting a QRhiTextureSubresourceUploadDescription via setDescription()
+ first.
+ */
+
+/*!
+ Constructs a QRhiTextureUploadEntry targeting the given \a layer and mip
+ \a level, with the subresource contents described by \a desc.
+ */
+QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
+ const QRhiTextureSubresourceUploadDescription &desc)
+ : m_layer(layer),
+ m_level(level),
+ m_desc(desc)
+{
+}
+
+/*!
+ \class QRhiTextureUploadDescription
+ \inmodule QtRhi
+ \brief Describes a texture upload operation.
+
+ Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
+ variants: one taking a QImage and one taking a
+ QRhiTextureUploadDescription. The former is a convenience version,
+ internally creating a QRhiTextureUploadDescription with a single image
+ targeting level 0 for layer 0. However, when cubemaps, pre-generated mip
+ images, or compressed textures are involved, applications will have to work
+ directly with this class instead.
+
+ QRhiTextureUploadDescription also enables specifying batched uploads, which
+ are useful for example when generating an atlas or glyph cache texture:
+ multiple, partial uploads for the same subresource (meaning the same layer
+ and level) are supported, and can be, depending on the backend and the
+ underlying graphics API, more efficient when batched into the same
+ QRhiTextureUploadDescription as opposed to issuing individual
+ \l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} commands for
+ each of them.
+
+ \note Cubemaps have one layer for each of the six faces in the order +X,
+ -X, +Y, -Y, +Z, -Z.
+
+ For example, specifying the faces of a cubemap could look like the following:
+
+ \badcode
+ QImage faces[6];
+ ...
+ QVector<QRhiTextureUploadEntry> entries;
+ for (int i = 0; i < 6; ++i)
+ entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
+ QRhiTextureUploadDescription desc(entries);
+ resourceUpdates->uploadTexture(texture, desc);
+ \endcode
+
+ Another example that specifies mip images for a compressed texture:
+
+ \badcode
+ QRhiTextureUploadDescription desc;
+ const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
+ for (int level = 0; level < mipCount; ++level) {
+ const QByteArray compressedDataForLevel = ..
+ desc.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
+ }
+ resourceUpdates->uploadTexture(compressedTexture, desc);
+ \endcode
+
+ With partial uploads targeting the same subresource, it is recommended to
+ batch them into a single upload request, whenever possible:
+
+ \badcode
+ QRhiTextureSubresourceUploadDescription subresDesc(image);
+ subresDesc.setSourceSize(QSize(10, 10));
+ subResDesc.setDestinationTopLeft(QPoint(50, 40));
+ QRhiTextureUploadEntry entry(0, 0, subresDesc); // layer 0, level 0
+
+ QRhiTextureSubresourceUploadDescription subresDesc2(image);
+ subresDesc2.setSourceSize(QSize(30, 40));
+ subResDesc2.setDestinationTopLeft(QPoint(100, 200));
+ QRhiTextureUploadEntry entry2(0, 0, subresDesc2); // layer 0, level 0, i.e. same subresource
+
+ QRhiTextureUploadDescription desc({ entry, entry2});
+ resourceUpdates->uploadTexture(texture, desc);
+ \endcode
+ */
+
+/*!
+ \fn QRhiTextureUploadDescription::QRhiTextureUploadDescription()
+
+ Constructs an empty texture upload description.
+ */
+
+/*!
+ Constructs a texture upload description with a single subresource upload
+ described by \a entry.
+ */
+QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry)
+{
+ m_entries.append(entry);
+}
+
+/*!
+ Constructs a texture upload description with the specified list of \a entries.
+
+ \note \a entries can also contain multiple QRhiTextureUploadEntry elements
+ with the the same layer and level. This makes sense when those uploads are
+ partial, meaning their subresource description has a source size or image
+ smaller than the subresource dimensions, and can be more efficient than
+ issuing separate uploadTexture()'s.
+ */
+QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QVector<QRhiTextureUploadEntry> &entries)
+ : m_entries(entries)
+{
+}
+
+/*!
+ Adds \a entry to the list of subresource uploads.
+ */
+void QRhiTextureUploadDescription::append(const QRhiTextureUploadEntry &entry)
+{
+ m_entries.append(entry);
+}
+
+/*!
+ \class QRhiTextureCopyDescription
+ \inmodule QtRhi
+ \brief Describes a texture-to-texture copy operation.
+
+ An empty pixelSize() indicates that the entire subresource is to be copied.
+ A default constructed copy description therefore leads to copying the
+ entire subresource at level 0 of layer 0.
+
+ \note The source texture must be created with
+ QRhiTexture::UsedAsTransferSource.
+
+ \note The source and destination rectangles defined by pixelSize(),
+ sourceTopLeft(), and destinationTopLeft() must fit the source and
+ destination textures, respectively. The behavior is undefined otherwise.
+ */
+
+/*!
+ \fn QRhiTextureCopyDescription::QRhiTextureCopyDescription()
+
+ Constructs an empty texture copy description.
+ */
+
+/*!
+ \class QRhiReadbackDescription
+ \inmodule QtRhi
+ \brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
+
+ The source of the readback operation is either a QRhiTexture or the
+ current backbuffer of the currently targeted QRhiSwapChain. When
+ texture() is not set, the swapchain is used. Otherwise the specified
+ QRhiTexture is treated as the source.
+
+ \note Textures used in readbacks must be created with
+ QRhiTexture::UsedAsTransferSource.
+
+ \note Swapchains used in readbacks must be created with
+ QRhiSwapChain::UsedAsTransferSource.
+
+ layer() and level() are only applicable when the source is a QRhiTexture.
+
+ \note Multisample textures cannot be read back. Readbacks are supported for
+ multisample swapchain buffers however.
+ */
+
+/*!
+ \fn QRhiReadbackDescription::QRhiReadbackDescription()
+
+ Constructs an empty texture readback description.
+
+ \note The source texture is set to null by default, which is still a valid
+ readback: it specifies that the backbuffer of the current swapchain is to
+ be read back. (current meaning the frame's target swapchain at the time of
+ committing the QRhiResourceUpdateBatch with the
+ \l{QRhiResourceUpdateBatch::readBackTexture()}{texture readback} on it)
+ */
+
+/*!
+ Constructs an texture readback description that specifies that level 0 of
+ layer 0 of \a texture is to be read back.
+
+ \note \a texture can also be null in which case this constructor is
+ identical to the argumentless variant.
+ */
+QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
+ : m_texture(texture)
+{
+}
+
+/*!
+ \class QRhiReadbackResult
+ \inmodule QtRhi
+ \brief Describes the results of a potentially asynchronous readback operation.
+
+ When \l completed is set, the function is invoked when the \l data is
+ available. \l format and \l pixelSize are set upon completion together with
+ \l data.
+ */
+
+/*!
+ \class QRhiNativeHandles
+ \inmodule QtRhi
+ \brief Base class for classes exposing backend-specific collections of native resource objects.
+ */
+
+/*!
+ \class QRhiResource
+ \inmodule QtRhi
+ \brief Base class for classes encapsulating native resource objects.
+ */
+
+/*!
+ \fn QRhiResource::Type QRhiResource::resourceType() const
+
+ \return the type of the resource.
+ */
+
+/*!
+ \internal
+ */
+QRhiResource::QRhiResource(QRhiImplementation *rhi)
+ : m_rhi(rhi)
+{
+ m_id = QRhiGlobalObjectIdGenerator::newId();
+}
+
+/*!
+ Destructor.
+
+ Releases (or requests deferred releasing of) the underlying native graphics
+ resources, if there are any.
+
+ \note Resources referenced by commands for the current frame should not be
+ released until the frame is submitted by QRhi::endFrame().
+
+ \sa release()
+ */
+QRhiResource::~QRhiResource()
+{
+ // release() cannot be called here, it being virtual; it is up to the
+ // subclasses to do that.
+}
+
+/*!
+ \fn void QRhiResource::release()
+
+ Releases (or requests deferred releasing of) the underlying native graphics
+ resources. Safe to call multiple times, subsequent invocations will be a
+ no-op then.
+
+ Once release() is called, the QRhiResource instance can be reused, by
+ calling \c build() again. That will then result in creating new native
+ graphics resources underneath.
+
+ \note Resources referenced by commands for the current frame should not be
+ released until the frame is submitted by QRhi::endFrame().
+
+ The QRhiResource destructor also performs the same task, so calling this
+ function is not necessary before destroying a QRhiResource.
+
+ \sa releaseAndDestroyLater()
+ */
+
+/*!
+ When called without a frame being recorded, this function is equivalent to
+ deleting the object. Between a QRhi::beginFrame() and QRhi::endFrame()
+ however the behavior is different: the QRhiResource will not be destroyed
+ until the frame is submitted via QRhi::endFrame(), thus satisfying the QRhi
+ requirement of not altering QRhiResource objects that are referenced by the
+ frame being recorded.
+
+ \sa release()
+ */
+void QRhiResource::releaseAndDestroyLater()
+{
+ m_rhi->addReleaseAndDestroyLater(this);
+}
+
+/*!
+ \return the currently set object name. By default the name is empty.
+ */
+QByteArray QRhiResource::name() const
+{
+ return m_objectName;
+}
+
+/*!
+ Sets a \a name for the object.
+
+ This has two uses: to get descriptive names for the native graphics
+ resources visible in graphics debugging tools, such as
+ \l{https://renderdoc.org/}{RenderDoc} and
+ \l{https://developer.apple.com/xcode/}{XCode}, and in the output stream of
+ QRhiProfiler.
+
+ When it comes to naming native objects by relaying the name via the
+ appropriate graphics API, note that the name is ignored when
+ QRhi::DebugMarkers are not supported, and may, depending on the backend,
+ also be ignored when QRhi::EnableDebugMarkers is not set.
+
+ \note The name may be ignored for objects other than buffers,
+ renderbuffers, and textures, depending on the backend.
+
+ \note The name may be modified. For slotted resources, such as a QRhiBuffer
+ backed by multiple native buffers, QRhi will append a suffix to make the
+ underlying native buffers easily distinguishable from each other.
+ */
+void QRhiResource::setName(const QByteArray &name)
+{
+ m_objectName = name;
+ m_objectName.replace(',', '_'); // cannot contain comma for QRhiProfiler
+}
+
+/*!
+ \return the global, unique identifier of this QRhiResource.
+
+ User code rarely needs to deal with the value directly. It is used
+ internally for tracking and bookkeeping purposes.
+ */
+quint64 QRhiResource::globalResourceId() const
+{
+ return m_id;
+}
+
+/*!
+ \class QRhiBuffer
+ \inmodule QtRhi
+ \brief Vertex, index, or uniform (constant) buffer resource.
+ */
+
+/*!
+ \enum QRhiBuffer::Type
+ Specifies storage type of buffer resource.
+
+ \value Immutable Indicates that the data is not expected to change ever
+ after the initial upload. Under the hood such buffer resources are
+ typically placed in device local (GPU) memory (on systems where
+ applicable). Uploading new data is possible, but may be expensive. The
+ upload typically happens by copying to a separate, host visible staging
+ buffer from which a GPU buffer-to-buffer copy is issued into the actual
+ GPU-only buffer.
+
+ \value Static Indicates that the data is expected to change only
+ infrequently. Typically placed in device local (GPU) memory, where
+ applicable. On backends where host visible staging buffers are used for
+ uploading, the staging buffers are kept around for this type, unlike with
+ Immutable, so subsequent uploads do not suffer in performance. Frequent
+ updates, especially updates in consecutive frames, should be avoided.
+
+ \value Dynamic Indicates that the data is expected to change frequently.
+ Not recommended for large buffers. Typically backed by host visible memory
+ in 2 copies in order to allow for changing without stalling the graphics
+ pipeline. The double buffering is managed transparently to the applications
+ and is not exposed in the API here in any form. This is the recommended,
+ and, with some backends, the only possible, type for buffers with
+ UniformBuffer usage.
+ */
+
+/*!
+ \enum QRhiBuffer::UsageFlag
+ Flag values to specify how the buffer is going to be used.
+
+ \value VertexBuffer Vertex buffer
+ \value IndexBuffer Index buffer
+ \value UniformBuffer Uniform (constant) buffer
+ */
+
+/*!
+ \fn void QRhiBuffer::setSize(int sz)
+
+ Sets the size of the buffer in bytes. The size is normally specified in
+ QRhi::newBuffer() so this function is only used when the size has to be
+ changed. As with other setters, the size only takes effect when calling
+ build(), and for already built buffers this involves releasing the previous
+ native resource and creating new ones under the hood.
+
+ Backends may choose to allocate buffers bigger than \a sz in order to
+ fulfill alignment requirements. This is hidden from the applications and
+ size() will always report the size requested in \a sz.
+ */
+
+/*!
+ \internal
+ */
+QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, int size_)
+ : QRhiResource(rhi),
+ m_type(type_), m_usage(usage_), m_size(size_)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiBuffer::resourceType() const
+{
+ return Buffer;
+}
+
+/*!
+ \fn bool QRhiBuffer::build()
+
+ Creates the corresponding native graphics resources. If there are already
+ resources present due to an earlier build() with no corresponding
+ release(), then release() is called implicitly first.
+
+ \return \c true when successful, \c false when a graphics operation failed.
+ Regardless of the return value, calling release() is always safe.
+ */
+
+/*!
+ \class QRhiRenderBuffer
+ \inmodule QtRhi
+ \brief Renderbuffer resource.
+
+ Renderbuffers cannot be sampled or read but have some benefits over
+ textures in some cases:
+
+ A DepthStencil renderbuffer may be lazily allocated and be backed by
+ transient memory with some APIs. On some platforms this may mean the
+ depth/stencil buffer uses no physical backing at all.
+
+ Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
+ supported even when QRhi::MultisampleTexture is not.
+
+ How the renderbuffer is implemented by a backend is not exposed to the
+ applications. In some cases it may be backed by ordinary textures, while in
+ others there may be a different kind of native resource used.
+ */
+
+/*!
+ \enum QRhiRenderBuffer::Type
+ Specifies the type of the renderbuffer
+
+ \value DepthStencil Combined depth/stencil
+ \value Color Color
+ */
+
+/*!
+ \enum QRhiRenderBuffer::Flag
+ Flag values for flags() and setFlags()
+
+ \value UsedWithSwapChainOnly For DepthStencil renderbuffers this indicates
+ that the renderbuffer is only used in combination with a QRhiSwapChain and
+ never in other ways. Relevant with some backends, while others ignore it.
+ With OpenGL where a separate windowing system interface API is in use (EGL,
+ GLX, etc.), the flag is important since it avoids creating any actual
+ resource as there is already a windowing system provided depth/stencil
+ buffer as requested by QSurfaceFormat.
+ */
+
+/*!
+ \internal
+ */
+QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
+ int sampleCount_, Flags flags_)
+ : QRhiResource(rhi),
+ m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiRenderBuffer::resourceType() const
+{
+ return RenderBuffer;
+}
+
+/*!
+ \fn bool QRhiRenderBuffer::build()
+
+ Creates the corresponding native graphics resources. If there are already
+ resources present due to an earlier build() with no corresponding
+ release(), then release() is called implicitly first.
+
+ \return \c true when successful, \c false when a graphics operation failed.
+ Regardless of the return value, calling release() is always safe.
+ */
+
+/*!
+ \fn QRhiTexture::Format QRhiRenderBuffer::backingFormat() const
+
+ \internal
+ */
+
+/*!
+ \class QRhiTexture
+ \inmodule QtRhi
+ \brief Texture resource.
+ */
+
+/*!
+ \enum QRhiTexture::Flag
+
+ Flag values to specify how the texture is going to be used. Not honoring
+ the flags set before build() and attempting to use the texture in ways that
+ was not declared upfront can lead to unspecified behavior or decreased
+ performance depending on the backend and the underlying graphics API.
+
+ \value RenderTarget The texture going to be used in combination with
+ QRhiTextureRenderTarget.
+
+ \value CubeMap The texture is a cubemap. Such textures have 6 layers, one
+ for each face in the order of +X, -X, +Y, -Y, +Z, -Z. Cubemap textures
+ cannot be multisample.
+
+ \value MipMapped The texture has mipmaps. The appropriate mip count is
+ calculated automatically and can also be retrieved via
+ QRhi::mipLevelsForSize(). The images for the mip levels have to be
+ provided in the texture uploaded or generated via
+ QRhiResourceUpdateBatch::generateMips(). Multisample textures cannot have
+ mipmaps.
+
+ \value sRGB Use an sRGB format.
+
+ \value UsedAsTransferSource The texture is used as the source of a texture
+ copy or readback, meaning the texture is given as the source in
+ QRhiResourceUpdateBatch::copyTexture() or
+ QRhiResourceUpdateBatch::readBackTexture().
+
+ \value UsedWithGenerateMips The texture is going to be used with
+ QRhiResourceUpdateBatch::generateMips().
+ */
+
+/*!
+ \enum QRhiTexture::Format
+
+ Specifies the texture format. See also QRhi::isTextureFormatSupported() and
+ note that flags() can modify the format when QRhiTexture::sRGB is set.
+
+ \value UnknownFormat Not a valid format. This cannot be passed to setFormat().
+
+ \value RGBA8 Four component, unsigned normalized 8 bit per component. Always supported.
+
+ \value BGRA8 Four component, unsigned normalized 8 bit per component.
+
+ \value R8 One component, unsigned normalized 8 bit.
+
+ \value R16 One component, unsigned normalized 16 bit.
+
+ \value RED_OR_ALPHA8 Either same as R8, or is a similar format with the component swizzled to alpha,
+ depending on \l{QRhi::RedOrAlpha8IsRed}{RedOrAlpha8IsRed}.
+
+ \value RGBA16F Four components, 16-bit float per component.
+
+ \value RGBA32F Four components, 32-bit float per component.
+
+ \value D16 16-bit depth (normalized unsigned integer)
+
+ \value D32F 32-bit depth (32-bit float)
+
+ \value BC1
+ \value BC2
+ \value BC3
+ \value BC4
+ \value BC5
+ \value BC6H
+ \value BC7
+
+ \value ETC2_RGB8
+ \value ETC2_RGB8A1
+ \value ETC2_RGBA8
+
+ \value ASTC_4x4
+ \value ASTC_5x4
+ \value ASTC_5x5
+ \value ASTC_6x5
+ \value ASTC_6x6
+ \value ASTC_8x5
+ \value ASTC_8x6
+ \value ASTC_8x8
+ \value ASTC_10x5
+ \value ASTC_10x6
+ \value ASTC_10x8
+ \value ASTC_10x10
+ \value ASTC_12x10
+ \value ASTC_12x12
+ */
+
+/*!
+ \internal
+ */
+QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_,
+ int sampleCount_, Flags flags_)
+ : QRhiResource(rhi),
+ m_format(format_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiTexture::resourceType() const
+{
+ return Texture;
+}
+
+/*!
+ \fn bool QRhiTexture::build()
+
+ Creates the corresponding native graphics resources. If there are already
+ resources present due to an earlier build() with no corresponding
+ release(), then release() is called implicitly first.
+
+ \return \c true when successful, \c false when a graphics operation failed.
+ Regardless of the return value, calling release() is always safe.
+ */
+
+/*!
+ \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
+ QRhiVulkanTextureNativeHandles. The returned value is null when exposing
+ the underlying native resources is not supported by the backend.
+
+ \sa QRhiVulkanTextureNativeHandles, QRhiD3D11TextureNativeHandles,
+ QRhiMetalTextureNativeHandles, QRhiGles2TextureNativeHandles
+ */
+const QRhiNativeHandles *QRhiTexture::nativeHandles()
+{
+ return nullptr;
+}
+
+/*!
+ Similar to build() except that no new native textures are created. Instead,
+ the texture from \a src is used.
+
+ This allows importing an existing native texture object (which must belong
+ to the same device or sharing context, depending on the graphics API) from
+ an external graphics engine.
+
+ \note format(), pixelSize(), sampleCount(), and flags() must still be set
+ correctly. Passing incorrect sizes and other values to QRhi::newTexture()
+ and then following it with a buildFrom() expecting that the native texture
+ object alone is sufficient to deduce such values is \b wrong and will lead
+ to problems.
+
+ \note QRhiTexture does not take ownership of the texture object. release()
+ does not free the object or any associated memory.
+
+ The opposite of this operation, exposing a QRhiTexture-created native
+ texture object to a foreign engine, is possible via nativeHandles().
+
+ \sa QRhiVulkanTextureNativeHandles, QRhiD3D11TextureNativeHandles,
+ QRhiMetalTextureNativeHandles, QRhiGles2TextureNativeHandles
+ */
+bool QRhiTexture::buildFrom(const QRhiNativeHandles *src)
+{
+ Q_UNUSED(src);
+ return false;
+}
+
+/*!
+ \class QRhiSampler
+ \inmodule QtRhi
+ \brief Sampler resource.
+ */
+
+/*!
+ \enum QRhiSampler::Filter
+ Specifies the minification, magnification, or mipmap filtering
+
+ \value None Applicable only for mipmapMode(), indicates no mipmaps to be used
+ \value Nearest
+ \value Linear
+ */
+
+/*!
+ \enum QRhiSampler::AddressMode
+ Specifies the addressing mode
+
+ \value Repeat
+ \value ClampToEdge
+ \value Border
+ \value Mirror
+ \value MirrorOnce
+ */
+
+/*!
+ \enum QRhiSampler::CompareOp
+ Specifies the texture comparison function.
+
+ \value Never (default)
+ \value Less
+ \value Equal
+ \value LessOrEqual
+ \value Greater
+ \value NotEqual
+ \value GreaterOrEqual
+ \value Always
+ */
+
+/*!
+ \internal
+ */
+QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
+ Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
+ AddressMode u_, AddressMode v_)
+ : QRhiResource(rhi),
+ m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
+ m_addressU(u_), m_addressV(v_),
+ m_addressW(QRhiSampler::ClampToEdge),
+ m_compareOp(QRhiSampler::Never)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiSampler::resourceType() const
+{
+ return Sampler;
+}
+
+/*!
+ \class QRhiRenderPassDescriptor
+ \inmodule QtRhi
+ \brief Render pass resource.
+ */
+
+/*!
+ \internal
+ */
+QRhiRenderPassDescriptor::QRhiRenderPassDescriptor(QRhiImplementation *rhi)
+ : QRhiResource(rhi)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
+{
+ return RenderPassDescriptor;
+}
+
+/*!
+ \class QRhiRenderTarget
+ \inmodule QtRhi
+ \brief Represents an onscreen (swapchain) or offscreen (texture) render target.
+ */
+
+/*!
+ \internal
+ */
+QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
+ : QRhiResource(rhi)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiRenderTarget::resourceType() const
+{
+ return RenderTarget;
+}
+
+/*!
+ \fn QSize QRhiRenderTarget::pixelSize() const
+
+ \return the size in pixels.
+ */
+
+/*!
+ \fn float QRhiRenderTarget::devicePixelRatio() const
+
+ \return the device pixel ratio. For QRhiTextureRenderTarget this is always
+ 1. For targets retrieved from a QRhiSwapChain the value reflects the
+ \l{QWindow::devicePixelRatio()}{device pixel ratio} of the targeted
+ QWindow.
+ */
+
+/*!
+ \class QRhiTextureRenderTarget
+ \inmodule QtRhi
+ \brief Texture render target resource.
+
+ A texture render target allows rendering into one or more textures,
+ optionally with a depth texture or depth/stencil renderbuffer.
+
+ \note Textures used in combination with QRhiTextureRenderTarget must be
+ created with the QRhiTexture::RenderTarget flag.
+
+ The simplest example of creating a render target with a texture as its
+ single color attachment:
+
+ \badcode
+ texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
+ texture->build();
+ rt = rhi->newTextureRenderTarget({ texture });
+ rp = rt->newCompatibleRenderPassDescriptor();
+ rt->setRenderPassDescriptor(rt);
+ rt->build();
+ // rt can now be used with beginPass()
+ \endcode
+ */
+
+/*!
+ \enum QRhiTextureRenderTarget::Flag
+
+ Flag values describing the load/store behavior for the render target. The
+ load/store behavior may be baked into native resources under the hood,
+ depending on the backend, and therefore it needs to be known upfront and
+ cannot be changed without rebuilding (and so releasing and creating new
+ native resources).
+
+ \value PreserveColorContents Indicates that the contents of the color
+ attachments is to be loaded when starting a render pass, instead of
+ clearing. This is potentially more expensive, especially on mobile (tiled)
+ GPUs, but allows preserving the existing contents between passes.
+
+ \value PreserveDepthStencilContents Indicates that the contents of the
+ depth texture is to be loaded when starting a render pass, instead
+ clearing. Only applicable when a texture is used as the depth buffer
+ (QRhiTextureRenderTargetDescription::depthTexture() is set) because
+ depth/stencil renderbuffers may not have any physical backing and data may
+ not be written out in the first place.
+ */
+
+/*!
+ \internal
+ */
+QRhiTextureRenderTarget::QRhiTextureRenderTarget(QRhiImplementation *rhi,
+ const QRhiTextureRenderTargetDescription &desc_,
+ Flags flags_)
+ : QRhiRenderTarget(rhi),
+ m_desc(desc_),
+ m_flags(flags_)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
+{
+ return TextureRenderTarget;
+}
+
+/*!
+ \fn QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()
+
+ \return a new QRhiRenderPassDescriptor that is compatible with this render
+ target.
+
+ The returned value is used in two ways: it can be passed to
+ setRenderPassDescriptor() and
+ QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
+ describes the attachments (color, depth/stencil) and the load/store
+ behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
+ be used in combination with a render target that has the same
+ QRhiRenderPassDescriptor set.
+
+ Two QRhiTextureRenderTarget instances can share the same render pass
+ descriptor as long as they have the same number and type of attachments.
+ The associated QRhiTexture or QRhiRenderBuffer instances are not part of
+ the render pass descriptor so those can differ in the two
+ QRhiTextureRenderTarget intances.
+
+ \note resources, such as QRhiTexture instances, referenced in description()
+ must already be built
+
+ \sa build()
+ */
+
+/*!
+ \fn bool QRhiTextureRenderTarget::build()
+
+ Creates the corresponding native graphics resources. If there are already
+ resources present due to an earlier build() with no corresponding
+ release(), then release() is called implicitly first.
+
+ \note renderPassDescriptor() must be set before calling build(). To obtain
+ a QRhiRenderPassDescriptor compatible with the render target, call
+ newCompatibleRenderPassDescriptor() before build() but after setting all
+ other parameters, such as description() and flags(). To save resources,
+ reuse the same QRhiRenderPassDescriptor with multiple
+ QRhiTextureRenderTarget instances, whenever possible. Sharing the same
+ render pass descriptor is only possible when the render targets have the
+ same number and type of attachments (the actual textures can differ) and
+ the same flags.
+
+ \note resources, such as QRhiTexture instances, referenced in description()
+ must already be built
+
+ \return \c true when successful, \c false when a graphics operation failed.
+ Regardless of the return value, calling release() is always safe.
+ */
+
+/*!
+ \class QRhiShaderResourceBindings
+ \inmodule QtRhi
+ \brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
+
+ A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
+ objects, each of which describe a single binding.
+
+ Take a fragment shader with the following interface:
+
+ \badcode
+ layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ int flip;
+ } ubuf;
+
+ layout(binding = 1) uniform sampler2D tex;
+ \endcode
+
+ To make resources visible to the shader, the following
+ QRhiShaderResourceBindings could be created and then passed to
+ QRhiGraphicsPipeline::setShaderResourceBindings():
+
+ \badcode
+ srb = rhi->newShaderResourceBindings();
+ srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
+ });
+ srb->build();
+ ...
+ ps = rhi->newGraphicsPipeline();
+ ...
+ ps->setShaderResourceBindings(srb);
+ ps->build();
+ ...
+ cb->setGraphicsPipeline(ps);
+ cb->setShaderResources(); // binds srb
+ \endcode
+
+ This assumes that \c ubuf is a QRhiBuffer, \c texture is a QRhiTexture,
+ while \a sampler is a QRhiSampler. The example also assumes that the
+ uniform block is present in the vertex shader as well so the same buffer is
+ made visible to the vertex stage too.
+
+ \section3 Advanced usage
+
+ Building on the above example, let's assume that a pass now needs to use
+ the exact same pipeline and shaders with a different texture. Creating a
+ whole separate QRhiGraphicsPipeline just for this would be an overkill.
+ This is why QRhiCommandBuffer::setShaderResources() allows specifying a \a
+ srb argument. As long as the layouts (so the number of bindings and the
+ binding points) match between two QRhiShaderResourceBindings, they can both
+ be used with the same pipeline, assuming the pipeline was built with one of
+ them in the first place.
+
+ Creating and then using a new \c srb2 that is very similar to \c srb with
+ the exception of referencing another texture could be implemented like the
+ following:
+
+ \badcode
+ srb2 = rhi->newShaderResourceBindings();
+ QVector<QRhiShaderResourceBinding> bindings = srb->bindings();
+ bindings[1] = QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, anotherTexture, sampler);
+ srb2->setBindings(bindings);
+ srb2->build();
+ ...
+ cb->setGraphicsPipeline(ps);
+ cb->setShaderResources(srb2); // binds srb2
+ \endcode
+ */
+
+/*!
+ \internal
+ */
+QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
+ : QRhiResource(rhi)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
+{
+ return ShaderResourceBindings;
+}
+
+/*!
+ \return \c true if the layout is compatible with \a other. The layout does
+ not include the actual resource (such as, buffer or texture) and related
+ parameters (such as, offset or size). It does include the binding point,
+ pipeline stage, and resource type, however. The number and order of the
+ bindings must also match in order to be compatible.
+
+ When there is a QRhiGraphicsPipeline created with this
+ QRhiShaderResourceBindings, and the function returns \c true, \a other can
+ then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
+ be used with the pipeline in place of this QRhiShaderResourceBindings.
+
+ This function can be called before build() as well. The bindings must
+ already be set via setBindings() however.
+ */
+bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
+{
+ const int count = m_bindings.count();
+ if (count != other->m_bindings.count())
+ return false;
+
+ for (int i = 0; i < count; ++i) {
+ if (!m_bindings[i].isLayoutCompatible(other->m_bindings.at(i)))
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \class QRhiShaderResourceBinding
+ \inmodule QtRhi
+ \brief Describes the shader resource for a single binding point.
+
+ A QRhiShaderResourceBinding cannot be constructed directly. Instead, use
+ the static functions uniformBuffer(), sampledTexture() to get an instance.
+ */
+
+/*!
+ \enum QRhiShaderResourceBinding::Type
+ Specifies type of the shader resource bound to a binding point
+
+ \value UniformBuffer Uniform buffer
+ \value SampledTexture Combined image sampler
+ */
+
+/*!
+ \enum QRhiShaderResourceBinding::StageFlag
+ Flag values to indicate which stages the shader resource is visible in
+
+ \value VertexStage Vertex stage
+ \value FragmentStage Fragment (pixel) stage
+ */
+
+/*!
+ \internal
+ */
+QRhiShaderResourceBinding::QRhiShaderResourceBinding()
+ : d(new QRhiShaderResourceBindingPrivate)
+{
+}
+
+/*!
+ \internal
+ */
+void QRhiShaderResourceBinding::detach()
+{
+ qAtomicDetach(d);
+}
+
+/*!
+ \internal
+ */
+QRhiShaderResourceBinding::QRhiShaderResourceBinding(const QRhiShaderResourceBinding &other)
+ : d(other.d)
+{
+ d->ref.ref();
+}
+
+/*!
+ \internal
+ */
+QRhiShaderResourceBinding &QRhiShaderResourceBinding::operator=(const QRhiShaderResourceBinding &other)
+{
+ qAtomicAssign(d, other.d);
+ return *this;
+}
+
+/*!
+ Destructor.
+ */
+QRhiShaderResourceBinding::~QRhiShaderResourceBinding()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+/*!
+ \return \c true if the layout is compatible with \a other. The layout does not
+ include the actual resource (such as, buffer or texture) and related
+ parameters (such as, offset or size).
+
+ For example, \c a and \c b below are not equal, but are compatible layout-wise:
+
+ \badcode
+ auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
+ auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
+ \endcode
+ */
+bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
+{
+ return (d == other.d)
+ || (d->binding == other.d->binding && d->stage == other.d->stage && d->type == other.d->type);
+}
+
+/*!
+ \return a shader resource binding for the given binding number, pipeline
+ stages, and buffer specified by \a binding, \a stage, and \a buf.
+ */
+QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
+ int binding, StageFlags stage, QRhiBuffer *buf)
+{
+ QRhiShaderResourceBinding b;
+ QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
+ Q_ASSERT(d->ref.load() == 1);
+ d->binding = binding;
+ d->stage = stage;
+ d->type = UniformBuffer;
+ d->u.ubuf.buf = buf;
+ d->u.ubuf.offset = 0;
+ d->u.ubuf.maybeSize = 0; // entire buffer
+ d->u.ubuf.hasDynamicOffset = false;
+ return b;
+}
+
+/*!
+ \return a shader resource binding for the given binding number, pipeline
+ stages, and buffer specified by \a binding, \a stage, and \a buf. This
+ overload binds a region only, as specified by \a offset and \a size.
+
+ \note It is up to the user to ensure the offset is aligned to
+ QRhi::ubufAlignment().
+
+ \note \a size must be greater than 0.
+ */
+QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
+ int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
+{
+ Q_ASSERT(size > 0);
+ QRhiShaderResourceBinding b;
+ QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
+ Q_ASSERT(d->ref.load() == 1);
+ d->binding = binding;
+ d->stage = stage;
+ d->type = UniformBuffer;
+ d->u.ubuf.buf = buf;
+ d->u.ubuf.offset = offset;
+ d->u.ubuf.maybeSize = size;
+ d->u.ubuf.hasDynamicOffset = false;
+ return b;
+}
+
+/*!
+ \return a shader resource binding for the given binding number, pipeline
+ stages, and buffer specified by \a binding, \a stage, and \a buf. The
+ uniform buffer is assumed to have dynamic offset. The dynamic offset can be
+ specified in QRhiCommandBuffer::setShaderResources(), thus allowing using
+ varying offset values without creating new bindings for the buffer. The
+ size of the bound region is specified by \a size. Like with non-dynamic
+ offsets, \c{offset + size} cannot exceed the size of \a buf.
+ */
+QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
+ int binding, StageFlags stage, QRhiBuffer *buf, int size)
+{
+ QRhiShaderResourceBinding b;
+ QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
+ Q_ASSERT(d->ref.load() == 1);
+ d->binding = binding;
+ d->stage = stage;
+ d->type = UniformBuffer;
+ d->u.ubuf.buf = buf;
+ d->u.ubuf.offset = 0;
+ d->u.ubuf.maybeSize = size;
+ d->u.ubuf.hasDynamicOffset = true;
+ return b;
+}
+
+/*!
+ \return a shader resource binding for the given binding number, pipeline
+ stages, texture, and sampler specified by \a binding, \a stage, \a tex,
+ \a sampler.
+ */
+QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
+ int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
+{
+ QRhiShaderResourceBinding b;
+ QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
+ Q_ASSERT(d->ref.load() == 1);
+ d->binding = binding;
+ d->stage = stage;
+ d->type = SampledTexture;
+ d->u.stex.tex = tex;
+ d->u.stex.sampler = sampler;
+ return b;
+}
+
+/*!
+ \return \c true if the contents of the two QRhiShaderResourceBinding
+ objects \a a and \a b are equal. This includes the resources (buffer,
+ texture) and related parameters (offset, size) as well. To only compare
+ layouts (binding point, pipeline stage, resource type), use
+ \l{QRhiShaderResourceBinding::isLayoutCompatible()}{isLayoutCompatible()}
+ instead.
+
+ \relates QRhiShaderResourceBinding
+ */
+bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW
+{
+ if (a.d == b.d)
+ return true;
+
+ if (a.d->binding != b.d->binding
+ || a.d->stage != b.d->stage
+ || a.d->type != b.d->type)
+ {
+ return false;
+ }
+
+ switch (a.d->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ if (a.d->u.ubuf.buf != b.d->u.ubuf.buf
+ || a.d->u.ubuf.offset != b.d->u.ubuf.offset
+ || a.d->u.ubuf.maybeSize != b.d->u.ubuf.maybeSize)
+ {
+ return false;
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ if (a.d->u.stex.tex != b.d->u.stex.tex
+ || a.d->u.stex.sampler != b.d->u.stex.sampler)
+ {
+ return false;
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \return \c false if all the bindings in the two QRhiShaderResourceBinding
+ objects \a a and \a b are equal; otherwise returns \c true.
+
+ \relates QRhiShaderResourceBinding
+ */
+bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW
+{
+ return !(a == b);
+}
+
+/*!
+ \return the hash value for \a b, using \a seed to seed the calculation.
+
+ \relates QRhiShaderResourceBinding
+ */
+uint qHash(const QRhiShaderResourceBinding &b, uint seed) Q_DECL_NOTHROW
+{
+ const char *u = reinterpret_cast<const char *>(&b.d->u);
+ return seed + b.d->binding + 10 * b.d->stage + 100 * b.d->type
+ + qHash(QByteArray::fromRawData(u, sizeof(b.d->u)), seed);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
+{
+ const QRhiShaderResourceBindingPrivate *d = b.d;
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QRhiShaderResourceBinding("
+ << "binding=" << d->binding
+ << " stage=" << d->stage
+ << " type=" << d->type;
+ switch (d->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ dbg.nospace() << " UniformBuffer("
+ << "buffer=" << d->u.ubuf.buf
+ << " offset=" << d->u.ubuf.offset
+ << " maybeSize=" << d->u.ubuf.maybeSize
+ << ')';
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ dbg.nospace() << " SampledTexture("
+ << "texture=" << d->u.stex.tex
+ << " sampler=" << d->u.stex.sampler
+ << ')';
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ dbg.nospace() << ')';
+ return dbg;
+}
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QRhiShaderResourceBindings("
+ << srb.m_bindings
+ << ')';
+ return dbg;
+}
+#endif
+
+/*!
+ \class QRhiGraphicsPipeline
+ \inmodule QtRhi
+ \brief Graphics pipeline state resource.
+
+ \note Setting the shader resource bindings is mandatory. The referenced
+ QRhiShaderResourceBindings must already be built by the time build() is
+ called.
+
+ \note Setting the render pass descriptor is mandatory. To obtain a
+ QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
+ use either QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() or
+ QRhiSwapChain::newCompatibleRenderPassDescriptor().
+
+ \note Setting the vertex input layout is mandatory.
+
+ \note Setting the shader stages is mandatory.
+
+ \note sampleCount() defaults to 1 and must match the sample count of the
+ render target's color and depth stencil attachments.
+
+ \note The depth test, depth write, and stencil test are disabled by
+ default.
+
+ \note stencilReadMask() and stencilWriteMask() apply to both faces. They
+ both default to 0xFF.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setTargetBlends(const QVector<TargetBlend> &blends)
+
+ Sets the blend specification for color attachments. Each element in \a
+ blends corresponds to a color attachment of the render target.
+
+ By default no blends are set, which is a shortcut to disabling blending and
+ enabling color write for all four channels.
+ */
+
+/*!
+ \enum QRhiGraphicsPipeline::Flag
+
+ Flag values for describing the dynamic state of the pipeline. The viewport is always dynamic.
+
+ \value UsesBlendConstants Indicates that a blend color constant will be set
+ via QRhiCommandBuffer::setBlendConstants()
+
+ \value UsesStencilRef Indicates that a stencil reference value will be set
+ via QRhiCommandBuffer::setStencilRef()
+
+ \value UsesScissor Indicates that a scissor rectangle will be set via
+ QRhiCommandBuffer::setScissor()
+ */
+
+/*!
+ \enum QRhiGraphicsPipeline::Topology
+ Specifies the primitive topology
+
+ \value Triangles (default)
+ \value TriangleStrip
+ \value Lines
+ \value LineStrip
+ \value Points
+ */
+
+/*!
+ \enum QRhiGraphicsPipeline::CullMode
+ Specifies the culling mode
+
+ \value None No culling (default)
+ \value Front Cull front faces
+ \value Back Cull back faces
+ */
+
+/*!
+ \enum QRhiGraphicsPipeline::FrontFace
+ Specifies the front face winding order
+
+ \value CCW Counter clockwise (default)
+ \value CW Clockwise
+ */
+
+/*!
+ \enum QRhiGraphicsPipeline::ColorMaskComponent
+ Flag values for specifying the color write mask
+
+ \value R
+ \value G
+ \value B
+ \value A
+ */
+
+/*!
+ \enum QRhiGraphicsPipeline::BlendFactor
+ Specifies the blend factor
+
+ \value Zero
+ \value One
+ \value SrcColor
+ \value OneMinusSrcColor
+ \value DstColor
+ \value OneMinusDstColor
+ \value SrcAlpha
+ \value OneMinusSrcAlpha
+ \value DstAlpha
+ \value OneMinusDstAlpha
+ \value ConstantColor
+ \value OneMinusConstantColor
+ \value ConstantAlpha
+ \value OneMinusConstantAlpha
+ \value SrcAlphaSaturate
+ \value Src1Color
+ \value OneMinusSrc1Color
+ \value Src1Alpha
+ \value OneMinusSrc1Alpha
+ */
+
+/*!
+ \enum QRhiGraphicsPipeline::BlendOp
+ Specifies the blend operation
+
+ \value Add
+ \value Subtract
+ \value ReverseSubtract
+ \value Min
+ \value Max
+ */
+
+/*!
+ \enum QRhiGraphicsPipeline::CompareOp
+ Specifies the depth or stencil comparison function
+
+ \value Never
+ \value Less (default for depth)
+ \value Equal
+ \value LessOrEqual
+ \value Greater
+ \value NotEqual
+ \value GreaterOrEqual
+ \value Always (default for stencil)
+ */
+
+/*!
+ \enum QRhiGraphicsPipeline::StencilOp
+ Specifies the stencil operation
+
+ \value StencilZero
+ \value Keep (default)
+ \value Replace
+ \value IncrementAndClamp
+ \value DecrementAndClamp
+ \value Invert
+ \value IncrementAndWrap
+ \value DecrementAndWrap
+ */
+
+/*!
+ \class QRhiGraphicsPipeline::TargetBlend
+ \inmodule QtRhi
+ \brief Describes the blend state for one color attachment.
+
+ Defaults to color write enabled, blending disabled. The blend values are
+ set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
+ OneMinusSrcAlpha) by default.
+ */
+
+/*!
+ \class QRhiGraphicsPipeline::StencilOpState
+ \inmodule QtRhi
+ \brief Describes the stencil operation state.
+ */
+
+/*!
+ \internal
+ */
+QRhiGraphicsPipeline::QRhiGraphicsPipeline(QRhiImplementation *rhi)
+ : QRhiResource(rhi)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
+{
+ return GraphicsPipeline;
+}
+
+/*!
+ \fn bool QRhiGraphicsPipeline::build()
+
+ Creates the corresponding native graphics resources. If there are already
+ resources present due to an earlier build() with no corresponding
+ release(), then release() is called implicitly first.
+
+ \return \c true when successful, \c false when a graphics operation failed.
+ Regardless of the return value, calling release() is always safe.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
+
+ Enables or disables depth testing. Both depth test and the writing out of
+ depth data are disabled by default.
+
+ \sa setDepthWrite()
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
+
+ Controls the writing out of depth data into the depth buffer. By default
+ this is disabled. Depth write is typically enabled together with the depth
+ test.
+
+ \note Enabling depth write without having depth testing enabled may not
+ lead to the desired result, and should be avoided.
+
+ \sa setDepthTest()
+ */
+
+/*!
+ \class QRhiSwapChain
+ \inmodule QtRhi
+ \brief Swapchain resource.
+
+ A swapchain enables presenting rendering results to a surface. A swapchain
+ is typically backed by a set of color buffers. Of these, one is displayed
+ at a time.
+
+ Below is a typical pattern for creating and managing a swapchain and some
+ associated resources in order to render onto a QWindow:
+
+ \badcode
+ void init()
+ {
+ sc = rhi->newSwapChain();
+ ds = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
+ QSize(), // no need to set the size yet
+ 1,
+ QRhiRenderBuffer::UsedWithSwapChainOnly);
+ sc->setWindow(window);
+ sc->setDepthStencil(ds);
+ rp = sc->newCompatibleRenderPassDescriptor();
+ sc->setRenderPassDescriptor(rp);
+ resizeSwapChain();
+ }
+
+ void resizeSwapChain()
+ {
+ const QSize outputSize = sc->surfacePixelSize();
+ ds->setPixelSize(outputSize);
+ ds->build();
+ hasSwapChain = sc->buildOrResize();
+ }
+
+ void render()
+ {
+ if (!hasSwapChain || notExposed)
+ return;
+
+ if (sc->currentPixelSize() != sc->surfacePixelSize() || newlyExposed) {
+ resizeSwapChain();
+ if (!hasSwapChain)
+ return;
+ newlyExposed = false;
+ }
+
+ rhi->beginFrame(sc);
+ // ...
+ rhi->endFrame(sc);
+ }
+ \endcode
+
+ Avoid relying on QWindow resize events to resize swapchains, especially
+ considering that surface sizes may not always fully match the QWindow
+ reported dimensions. The safe, cross-platform approach is to do the check
+ via surfacePixelSize() whenever starting a new frame.
+
+ Releasing the swapchain must happen while the QWindow and the underlying
+ native window is fully up and running. Building on the previous example:
+
+ \badcode
+ void releaseSwapChain()
+ {
+ if (hasSwapChain) {
+ sc->release();
+ hasSwapChain = false;
+ }
+ }
+
+ // assuming Window is our QWindow subclass
+ bool Window::event(QEvent *e)
+ {
+ switch (e->type()) {
+ case QEvent::UpdateRequest: // for QWindow::requestUpdate()
+ render();
+ break;
+ case QEvent::PlatformSurface:
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ releaseSwapChain();
+ break;
+ default:
+ break;
+ }
+ return QWindow::event(e);
+ }
+ \endcode
+
+ Initializing the swapchain and starting to render the first frame cannot
+ start at any time. The safe, cross-platform approach is to rely on expose
+ events. QExposeEvent is a loosely specified event that is sent whenever a
+ window gets mapped, obscured, and resized, depending on the platform.
+
+ \badcode
+ void Window::exposeEvent(QExposeEvent *)
+ {
+ // initialize and start rendering when the window becomes usable for graphics purposes
+ if (isExposed() && !running) {
+ running = true;
+ init();
+ }
+
+ // stop pushing frames when not exposed or size becomes 0
+ if ((!isExposed() || (hasSwapChain && sc->surfacePixelSize().isEmpty())) && running)
+ notExposed = true;
+
+ // continue when exposed again and the surface has a valid size
+ if (isExposed() && running && notExposed && !sc->surfacePixelSize().isEmpty()) {
+ notExposed = false;
+ newlyExposed = true;
+ }
+
+ if (isExposed() && !sc->surfacePixelSize().isEmpty())
+ render();
+ }
+ \endcode
+
+ Once the rendering has started, a simple way to request a new frame is
+ QWindow::requestUpdate(). While on some platforms this is merely a small
+ timer, on others it has a specific implementation: for instance on macOS or
+ iOS it may be backed by
+ \l{https://developer.apple.com/documentation/corevideo/cvdisplaylink?language=objc}{CVDisplayLink}.
+ The example above is already prepared for update requests by handling
+ QEvent::UpdateRequest.
+
+ While acting as a QRhiRenderTarget, QRhiSwapChain also manages a
+ QRhiCommandBuffer. Calling QRhi::endFrame() submits the recorded commands
+ and also enqueues a \c present request. The default behavior is to do this
+ with a swap interval of 1, meaning synchronizing to the display's vertical
+ refresh is enabled. Thus the rendering thread calling beginFrame() and
+ endFrame() will get throttled to vsync. On some backends this can be
+ disabled by passing QRhiSwapChain:NoVSync in flags().
+
+ Multisampling (MSAA) is handled transparently to the applications when
+ requested via setSampleCount(). Where applicable, QRhiSwapChain will take
+ care of creating additional color buffers and issuing a multisample resolve
+ command at the end of a frame. For OpenGL, it is necessary to request the
+ appropriate sample count also via QSurfaceFormat, by calling
+ QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
+ */
+
+/*!
+ \enum QRhiSwapChain::Flag
+ Flag values to describe swapchain properties
+
+ \value SurfaceHasPreMulAlpha Indicates that the target surface has
+ transparency with premultiplied alpha.
+
+ \value SurfaceHasNonPreMulAlpha Indicates the target surface has
+ transparencyt with non-premultiplied alpha.
+
+ \value sRGB Requests to pick an sRGB format for the swapchain and/or its
+ render target views, where applicable. Note that this implies that sRGB
+ framebuffer update and blending will get enabled for all content targeting
+ this swapchain, and opting out is not possible. For OpenGL, set
+ \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the QSurfaceFormat of
+ the QWindow in addition.
+
+ \value UsedAsTransferSource Indicates the the swapchain will be used as the
+ source of a readback in QRhiResourceUpdateBatch::readBackTexture().
+
+ \value NoVSync Requests disabling waiting for vertical sync, also avoiding
+ throttling the rendering thread. The behavior is backend specific and
+ applicable only where it is possible to control this. Some may ignore the
+ request altogether. For OpenGL, try instead setting the swap interval to 0
+ on the QWindow via QSurfaceFormat::setSwapInterval().
+
+ \value MinimalBufferCount Requests creating the swapchain with the minimum
+ number of buffers, which is in practice 2, unless the graphics
+ implementation has a higher minimum number than that. Only applicable with
+ backends where such control is available via the graphics API, for example,
+ Vulkan. By default it is up to the backend to decide what number of buffers
+ it requests (in practice this is almost always either 2 or 3), and it is
+ not the applications' concern. However, on Vulkan for instance the backend
+ will likely prefer the higher number (3), for example to avoid odd
+ performance issues with some Vulkan implementations on mobile devices. It
+ could be that on some platforms it can prove to be beneficial to force the
+ lower buffer count (2), so this flag allows forcing that. Note that all
+ this has no effect on the number of frames kept in flight, so the CPU
+ (QRhi) will still prepare frames at most \c{N - 1} frames ahead of the GPU,
+ even when the swapchain image buffer count larger than \c N. (\c{N} =
+ QRhi::FramesInFlight and typically 2).
+ */
+
+/*!
+ \internal
+ */
+QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
+ : QRhiResource(rhi)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiSwapChain::resourceType() const
+{
+ return SwapChain;
+}
+
+/*!
+ \fn QSize QRhiSwapChain::currentPixelSize() const
+
+ \return the size with which the swapchain was last successfully built. Use
+ this to decide if buildOrResize() needs to be called again: if
+ \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be
+ resized.
+
+ \sa surfacePixelSize()
+ */
+
+/*!
+ \fn QSize QRhiSwapChain::surfacePixelSize()
+
+ \return The size of the window's associated surface or layer. Do not assume
+ this is the same as QWindow::size() * QWindow::devicePixelRatio().
+
+ Can be called before buildOrResize() (but with window() already set), which
+ allows setting the correct size for the depth-stencil buffer that is then
+ used together with the swapchain's color buffers. Also used in combination
+ with currentPixelSize() to detect size changes.
+
+ \sa currentPixelSize()
+ */
+
+/*!
+ \fn QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer()
+
+ \return a command buffer on which rendering commands can be recorded. Only
+ valid within a QRhi::beginFrame() - QRhi::endFrame() block where
+ beginFrame() was called with this swapchain.
+
+ \note the value must not be cached and reused between frames
+*/
+
+/*!
+ \fn QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget()
+
+ \return a render target that can used with beginPass() in order to render
+ the the swapchain's current backbuffer. Only valid within a
+ QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
+ with this swapchain.
+
+ \note the value must not be cached and reused between frames
+ */
+
+/*!
+ \fn bool QRhiSwapChain::buildOrResize()
+
+ Creates the swapchain if not already done and resizes the swapchain buffers
+ to match the current size of the targeted surface. Call this whenever the
+ size of the target surface is different than before.
+
+ \note call release() only when the swapchain needs to be released
+ completely, typically upon
+ QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. To perform resizing, just
+ call buildOrResize().
+
+ \return \c true when successful, \c false when a graphics operation failed.
+ Regardless of the return value, calling release() is always safe.
+ */
+
+/*!
+ \class QRhiCommandBuffer
+ \inmodule QtRhi
+ \brief Command buffer resource.
+
+ Not creatable by applications at the moment. The only ways to obtain a
+ valid QRhiCommandBuffer are to get it from the targeted swapchain via
+ QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
+ completely offscreen, initializing one via QRhi::beginOffscreenFrame().
+ */
+
+/*!
+ \enum QRhiCommandBuffer::IndexFormat
+ Specifies the index data type
+
+ \value IndexUInt16 Unsigned 16-bit (quint16)
+ \value IndexUInt32 Unsigned 32-bit (quint32)
+ */
+
+/*!
+ \typedef QRhiCommandBuffer::DynamicOffset
+
+ Synonym for QPair<int, quint32>. The first entry is the binding, the second
+ is the offset in the buffer.
+*/
+
+/*!
+ \typedef QRhiCommandBuffer::VertexInput
+
+ Synonym for QPair<QRhiBuffer *, quint32>. The second entry is an offset in
+ the buffer specified by the first.
+*/
+
+/*!
+ \internal
+ */
+QRhiCommandBuffer::QRhiCommandBuffer(QRhiImplementation *rhi)
+ : QRhiResource(rhi)
+{
+}
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiCommandBuffer::resourceType() const
+{
+ return CommandBuffer;
+}
+
+QRhiImplementation::~QRhiImplementation()
+{
+ qDeleteAll(resUpdPool);
+
+ // Be nice and show something about leaked stuff. Though we may not get
+ // this far with some backends where the allocator or the api may check
+ // and freak out for unfreed graphics objects in the derived dtor already.
+#ifndef QT_NO_DEBUG
+ if (!resources.isEmpty()) {
+ qWarning("QRhi %p going down with %d unreleased resources. This is not nice.",
+ q, resources.count());
+ for (QRhiResource *res : qAsConst(resources)) {
+ qWarning(" Resource %p (%s)", res, res->m_objectName.constData());
+ res->m_rhi = nullptr;
+ }
+ }
+#endif
+}
+
+bool QRhiImplementation::isCompressedFormat(QRhiTexture::Format format) const
+{
+ return (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
+ || (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
+ || (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12);
+}
+
+void QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
+ quint32 *bpl, quint32 *byteSize,
+ QSize *blockDim) const
+{
+ int xdim = 4;
+ int ydim = 4;
+ quint32 blockSize = 0;
+
+ switch (format) {
+ case QRhiTexture::BC1:
+ blockSize = 8;
+ break;
+ case QRhiTexture::BC2:
+ blockSize = 16;
+ break;
+ case QRhiTexture::BC3:
+ blockSize = 16;
+ break;
+ case QRhiTexture::BC4:
+ blockSize = 8;
+ break;
+ case QRhiTexture::BC5:
+ blockSize = 16;
+ break;
+ case QRhiTexture::BC6H:
+ blockSize = 16;
+ break;
+ case QRhiTexture::BC7:
+ blockSize = 16;
+ break;
+
+ case QRhiTexture::ETC2_RGB8:
+ blockSize = 8;
+ break;
+ case QRhiTexture::ETC2_RGB8A1:
+ blockSize = 8;
+ break;
+ case QRhiTexture::ETC2_RGBA8:
+ blockSize = 16;
+ break;
+
+ case QRhiTexture::ASTC_4x4:
+ blockSize = 16;
+ break;
+ case QRhiTexture::ASTC_5x4:
+ blockSize = 16;
+ xdim = 5;
+ break;
+ case QRhiTexture::ASTC_5x5:
+ blockSize = 16;
+ xdim = ydim = 5;
+ break;
+ case QRhiTexture::ASTC_6x5:
+ blockSize = 16;
+ xdim = 6;
+ ydim = 5;
+ break;
+ case QRhiTexture::ASTC_6x6:
+ blockSize = 16;
+ xdim = ydim = 6;
+ break;
+ case QRhiTexture::ASTC_8x5:
+ blockSize = 16;
+ xdim = 8;
+ ydim = 5;
+ break;
+ case QRhiTexture::ASTC_8x6:
+ blockSize = 16;
+ xdim = 8;
+ ydim = 6;
+ break;
+ case QRhiTexture::ASTC_8x8:
+ blockSize = 16;
+ xdim = ydim = 8;
+ break;
+ case QRhiTexture::ASTC_10x5:
+ blockSize = 16;
+ xdim = 10;
+ ydim = 5;
+ break;
+ case QRhiTexture::ASTC_10x6:
+ blockSize = 16;
+ xdim = 10;
+ ydim = 6;
+ break;
+ case QRhiTexture::ASTC_10x8:
+ blockSize = 16;
+ xdim = 10;
+ ydim = 8;
+ break;
+ case QRhiTexture::ASTC_10x10:
+ blockSize = 16;
+ xdim = ydim = 10;
+ break;
+ case QRhiTexture::ASTC_12x10:
+ blockSize = 16;
+ xdim = 12;
+ ydim = 10;
+ break;
+ case QRhiTexture::ASTC_12x12:
+ blockSize = 16;
+ xdim = ydim = 12;
+ break;
+
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ const quint32 wblocks = (size.width() + xdim - 1) / xdim;
+ const quint32 hblocks = (size.height() + ydim - 1) / ydim;
+
+ if (bpl)
+ *bpl = wblocks * blockSize;
+ if (byteSize)
+ *byteSize = wblocks * hblocks * blockSize;
+ if (blockDim)
+ *blockDim = QSize(xdim, ydim);
+}
+
+void QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSize &size,
+ quint32 *bpl, quint32 *byteSize) const
+{
+ if (isCompressedFormat(format)) {
+ compressedFormatInfo(format, size, bpl, byteSize, nullptr);
+ return;
+ }
+
+ quint32 bpc = 0;
+ switch (format) {
+ case QRhiTexture::RGBA8:
+ bpc = 4;
+ break;
+ case QRhiTexture::BGRA8:
+ bpc = 4;
+ break;
+ case QRhiTexture::R8:
+ bpc = 1;
+ break;
+ case QRhiTexture::R16:
+ bpc = 2;
+ break;
+ case QRhiTexture::RED_OR_ALPHA8:
+ bpc = 1;
+ break;
+
+ case QRhiTexture::RGBA16F:
+ bpc = 8;
+ break;
+ case QRhiTexture::RGBA32F:
+ bpc = 16;
+ break;
+
+ case QRhiTexture::D16:
+ bpc = 2;
+ break;
+ case QRhiTexture::D32F:
+ bpc = 4;
+ break;
+
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ if (bpl)
+ *bpl = size.width() * bpc;
+ if (byteSize)
+ *byteSize = size.width() * size.height() * bpc;
+}
+
+// Approximate because it excludes subresource alignment or multisampling.
+quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize,
+ int mipCount, int layerCount)
+{
+ quint32 approxSize = 0;
+ for (int level = 0; level < mipCount; ++level) {
+ quint32 byteSize = 0;
+ const QSize size(qFloor(float(qMax(1, baseSize.width() >> level))),
+ qFloor(float(qMax(1, baseSize.height() >> level))));
+ textureFormatInfo(format, size, nullptr, &byteSize);
+ approxSize += byteSize;
+ }
+ approxSize *= layerCount;
+ return approxSize;
+}
+
+/*!
+ \internal
+ */
+QRhi::QRhi()
+{
+}
+
+/*!
+ Destructor. Destroys the backend and releases resources.
+ */
+QRhi::~QRhi()
+{
+ if (!d)
+ return;
+
+ qDeleteAll(d->pendingReleaseAndDestroyResources);
+ d->pendingReleaseAndDestroyResources.clear();
+
+ runCleanup();
+
+ d->destroy();
+ delete d;
+}
+
+/*!
+ \return a new QRhi instance with a backend for the graphics API specified by \a impl.
+
+ \a params must point to an instance of one of the backend-specific
+ subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
+ QRhiMetalInitParams, QRhiD3D11InitParams, QRhiGles2InitParams. See these
+ classes for examples on creating a QRhi.
+
+ \a flags is optional. It is used to enable profile and debug related
+ features that are potentially expensive and should only be used during
+ development.
+ */
+QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
+{
+ QScopedPointer<QRhi> r(new QRhi);
+
+ switch (impl) {
+ case Null:
+ r->d = new QRhiNull(static_cast<QRhiNullInitParams *>(params));
+ break;
+ case Vulkan:
+#if QT_CONFIG(vulkan)
+ r->d = new QRhiVulkan(static_cast<QRhiVulkanInitParams *>(params),
+ static_cast<QRhiVulkanNativeHandles *>(importDevice));
+ break;
+#else
+ qWarning("This build of Qt has no Vulkan support");
+ break;
+#endif
+ case OpenGLES2:
+#ifndef QT_NO_OPENGL
+ r->d = new QRhiGles2(static_cast<QRhiGles2InitParams *>(params),
+ static_cast<QRhiGles2NativeHandles *>(importDevice));
+ break;
+#else
+ qWarning("This build of Qt has no OpenGL support");
+ break;
+#endif
+ case D3D11:
+#ifdef Q_OS_WIN
+ r->d = new QRhiD3D11(static_cast<QRhiD3D11InitParams *>(params),
+ static_cast<QRhiD3D11NativeHandles *>(importDevice));
+ break;
+#else
+ qWarning("This platform has no Direct3D 11 support");
+ break;
+#endif
+ case Metal:
+//#ifdef Q_OS_DARWIN
+#ifdef Q_OS_MACOS
+ r->d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
+ static_cast<QRhiMetalNativeHandles *>(importDevice));
+ break;
+#else
+ qWarning("This platform has no Metal support");
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (r->d) {
+ r->d->q = r.data();
+ if (flags.testFlag(EnableProfiling)) {
+ QRhiProfilerPrivate *profD = QRhiProfilerPrivate::get(&r->d->profiler);
+ profD->rhiDWhenEnabled = r->d;
+ }
+ r->d->debugMarkers = flags.testFlag(EnableDebugMarkers);
+ if (r->d->create(flags)) {
+ r->d->implType = impl;
+ r->d->implThread = QThread::currentThread();
+ return r.take();
+ }
+ }
+
+ return nullptr;
+}
+
+/*!
+ \return the backend type for this QRhi.
+ */
+QRhi::Implementation QRhi::backend() const
+{
+ return d->implType;
+}
+
+/*!
+ \return the thread on which the QRhi was \l{QRhi::create()}{initialized}.
+ */
+QThread *QRhi::thread() const
+{
+ return d->implThread;
+}
+
+/*!
+ Registers a \a callback that is invoked either when the QRhi is destroyed,
+ or when runCleanup() is called.
+
+ The callback will run with the graphics resource still available, so this
+ provides an opportunity for the application to cleanly release QRhiResource
+ instances belonging to the QRhi. This is particularly useful for managing
+ the lifetime of resources stored in \c cache type of objects, where the
+ cache holds QRhiResources or objects containing QRhiResources.
+
+ \sa runCleanup(), ~QRhi()
+ */
+void QRhi::addCleanupCallback(const CleanupCallback &callback)
+{
+ d->addCleanupCallback(callback);
+}
+
+/*!
+ Invokes all registered cleanup functions. The list of cleanup callbacks it
+ then cleared. Normally destroying the QRhi does this automatically, but
+ sometimes it can be useful to trigger cleanup in order to release all
+ cached, non-essential resources.
+
+ \sa addCleanupCallback()
+ */
+void QRhi::runCleanup()
+{
+ for (const CleanupCallback &f : qAsConst(d->cleanupCallbacks))
+ f(this);
+
+ d->cleanupCallbacks.clear();
+}
+
+/*!
+ \class QRhiResourceUpdateBatch
+ \inmodule QtRhi
+ \brief Records upload and copy type of operations.
+
+ With QRhi it is no longer possible to perform copy type of operations at
+ arbitrary times. Instead, all such operations are recorded into batches
+ that are then passed, most commonly, to QRhiCommandBuffer::beginPass().
+ What then happens under the hood is hidden from the application: the
+ underlying implementations can defer and implement these operations in
+ various different ways.
+
+ A resource update batch owns no graphics resources and does not perform any
+ actual operations on its own. It should rather be viewed as a command
+ buffer for update, upload, and copy type of commands.
+
+ To get an available, empty batch from the pool, call
+ QRhi::nextResourceUpdateBatch().
+ */
+
+/*!
+ \internal
+ */
+QRhiResourceUpdateBatch::QRhiResourceUpdateBatch(QRhiImplementation *rhi)
+ : d(new QRhiResourceUpdateBatchPrivate)
+{
+ d->q = this;
+ d->rhi = rhi;
+}
+
+QRhiResourceUpdateBatch::~QRhiResourceUpdateBatch()
+{
+ delete d;
+}
+
+/*!
+ \return the batch to the pool. This should only be used when the batch is
+ not passed to one of QRhiCommandBuffer::beginPass(),
+ QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate()
+ because these implicitly call release().
+
+ \note QRhiResourceUpdateBatch instances must never by \c deleted by
+ applications.
+ */
+void QRhiResourceUpdateBatch::release()
+{
+ d->free();
+}
+
+/*!
+ Copies all queued operations from the \a other batch into this one.
+
+ \note \a other is not changed in any way, typically it will still need a
+ release()
+
+ This allows for a convenient pattern where resource updates that are
+ already known during the initialization step are collected into a batch
+ that is then merged into another when starting to first render pass later
+ on:
+
+ \badcode
+ void init()
+ {
+ ...
+ initialUpdates = rhi->nextResourceUpdateBatch();
+ initialUpdates->uploadStaticBuffer(vbuf, vertexData);
+ initialUpdates->uploadStaticBuffer(ibuf, indexData);
+ ...
+ }
+
+ void render()
+ {
+ ...
+ QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
+ if (initialUpdates) {
+ resUpdates->merge(initialUpdates);
+ initialUpdates->release();
+ initialUpdates = nullptr;
+ }
+ resUpdates->updateDynamicBuffer(...);
+ ...
+ cb->beginPass(rt, clearCol, clearDs, resUpdates);
+ }
+ \endcode
+ */
+void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
+{
+ d->merge(other->d);
+}
+
+/*!
+ Enqueues updating a region of a QRhiBuffer \a buf created with the type
+ QRhiBuffer::Dynamic.
+
+ The region is specified \a offset and \a size. The actual bytes to write
+ are specified by \a data which must have at least \a size bytes available.
+ \a data can safely be destroyed or changed once this function returns.
+
+ \note If host writes are involved, which is the case with
+ updateDynamicBuffer() typically as such buffers are backed by host visible
+ memory with most backends, they may accumulate within a frame. Thus pass 1
+ reading a region changed by a batch passed to pass 2 may see the changes
+ specified in pass 2's update batch.
+
+ \note QRhi transparently manages double buffering in order to prevent
+ stalling the graphics pipeline. The fact that a QRhiBuffer may have
+ multiple native underneath can be safely ignored when using the QRhi and
+ QRhiResourceUpdateBatch.
+ */
+void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, int offset, int size, const void *data)
+{
+ if (size > 0)
+ d->dynamicBufferUpdates.append({ buf, offset, size, data });
+}
+
+/*!
+ Enqueues updating a region of a QRhiBuffer \a buf created with the type
+ QRhiBuffer::Immutable or QRhiBuffer::Static.
+
+ The region is specified \a offset and \a size. The actual bytes to write
+ are specified by \a data which must have at least \a size bytes available.
+ \a data can safely be destroyed or changed once this function returns.
+ */
+void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, int offset, int size, const void *data)
+{
+ if (size > 0)
+ d->staticBufferUploads.append({ buf, offset, size, data });
+}
+
+/*!
+ Enqueues updating the entire QRhiBuffer \a buf created with the type
+ QRhiBuffer::Immutable or QRhiBuffer::Static.
+ */
+void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
+{
+ if (buf->size() > 0)
+ d->staticBufferUploads.append({ buf, 0, 0, data });
+}
+
+/*!
+ Enqueues uploading the image data for one or more mip levels in one or more
+ layers of the texture \a tex.
+
+ The details of the copy (source QImage or compressed texture data, regions,
+ target layers and levels) are described in \a desc.
+ */
+void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
+{
+ if (!desc.entries().isEmpty())
+ d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::textureUpload(tex, desc));
+}
+
+/*!
+ Enqueues uploading the image data for mip level 0 of layer 0 of the texture
+ \a tex.
+
+ \a tex must have an uncompressed format. Its format must also be compatible
+ with the QImage::format() of \a image. The source data is given in \a
+ image.
+ */
+void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)
+{
+ uploadTexture(tex, QRhiTextureUploadEntry(0, 0, image));
+}
+
+/*!
+ Enqueues a texture-to-texture copy operation from \a src into \a dst as
+ described by \a desc.
+
+ \note The source texture \a src must be created with
+ QRhiTexture::UsedAsTransferSource.
+ */
+void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
+{
+ d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::textureCopy(dst, src, desc));
+}
+
+/*!
+ Enqueues a texture-to-host copy operation as described by \a rb.
+
+ Normally \a rb will specify a QRhiTexture as the source. However, when the
+ swapchain in the current frame was created with
+ QRhiSwapChain::UsedAsTransferSource, it can also be the source of the
+ readback. For this, leave the texture set to null in \a rb.
+
+ Unlike other operations, the results here need to be processed by the
+ application. Therefore, \a result provides not just the data but also a
+ callback as operations on the batch are asynchronous by nature:
+
+ \badcode
+ beginFrame(sc);
+ beginPass
+ ...
+ QRhiReadbackResult *rbResult = new QRhiReadbackResult;
+ rbResult->completed = [rbResult] {
+ {
+ const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
+ const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
+ QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
+ image.save("result.png");
+ }
+ delete rbResult;
+ };
+ u = nextResourceUpdateBatch();
+ QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
+ u->readBackTexture(rb, rbResult);
+ endPass(u);
+ endFrame(sc);
+ \endcode
+
+ \note The texture must be created with QRhiTexture::UsedAsTransferSource.
+
+ \note Multisample textures cannot be read back.
+
+ \note The readback returns raw byte data, in order to allow the applications
+ to interpret it in any way they see fit. Be aware of the blending settings
+ of rendering code: if the blending is set up to rely on premultiplied alpha,
+ the results of the readback must also be interpreted as Premultiplied.
+
+ \note When interpreting the resulting raw data, be aware that the readback
+ happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
+ maps therefore to byte ordered QImage formats, such as,
+ QImage::Format_RGBA8888.
+ */
+void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
+{
+ d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::textureRead(rb, result));
+}
+
+/*!
+ Enqueues a mipmap generation operation for the specified \a layer of texture
+ \a tex.
+
+ \note The texture must be created with QRhiTexture::MipMapped and
+ QRhiTexture::UsedWithGenerateMips.
+ */
+void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex, int layer)
+{
+ d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::textureMipGen(tex, layer));
+}
+
+/*!
+ \return an available, empty batch to which copy type of operations can be
+ recorded.
+
+ \note the return value is not owned by the caller and must never be
+ destroyed. Instead, the batch is returned the the pool for reuse by passing
+ it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
+ QRhiCommandBuffer::resourceUpdate(), or by calling
+ QRhiResourceUpdateBatch::release() on it.
+
+ \note Can be called outside beginFrame() - endFrame() as well since a batch
+ instance just collects data on its own, it does not perform any operations.
+ */
+QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
+{
+ auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
+ for (int i = 0, ie = d->resUpdPoolMap.count(); i != ie; ++i) {
+ if (!d->resUpdPoolMap.testBit(i)) {
+ d->resUpdPoolMap.setBit(i);
+ QRhiResourceUpdateBatch *u = d->resUpdPool[i];
+ QRhiResourceUpdateBatchPrivate::get(u)->poolIndex = i;
+ return u;
+ }
+ }
+ return nullptr;
+ };
+
+ QRhiResourceUpdateBatch *u = nextFreeBatch();
+ if (!u) {
+ const int oldSize = d->resUpdPool.count();
+ const int newSize = oldSize + 4;
+ d->resUpdPool.resize(newSize);
+ d->resUpdPoolMap.resize(newSize);
+ for (int i = oldSize; i < newSize; ++i)
+ d->resUpdPool[i] = new QRhiResourceUpdateBatch(d);
+ u = nextFreeBatch();
+ Q_ASSERT(u);
+ }
+
+ return u;
+}
+
+void QRhiResourceUpdateBatchPrivate::free()
+{
+ Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
+
+ dynamicBufferUpdates.clear();
+ staticBufferUploads.clear();
+ textureOps.clear();
+
+ rhi->resUpdPoolMap.clearBit(poolIndex);
+ poolIndex = -1;
+}
+
+void QRhiResourceUpdateBatchPrivate::merge(QRhiResourceUpdateBatchPrivate *other)
+{
+ dynamicBufferUpdates += other->dynamicBufferUpdates;
+ staticBufferUploads += other->staticBufferUploads;
+ textureOps += other->textureOps;
+}
+
+/*!
+ Sometimes committing resource updates is necessary without starting a
+ render pass. Not often needed, updates should typically be passed to
+ beginPass (or endPass, in case of readbacks) instead.
+
+ \note Cannot be called inside a pass.
+ */
+void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
+{
+ if (resourceUpdates)
+ m_rhi->resourceUpdate(this, resourceUpdates);
+}
+
+/*!
+ Records starting a new render pass targeting the render target \a rt.
+
+ \a resourceUpdates, when not null, specifies a resource update batch that
+ is to be committed and then released.
+
+ The color and depth/stencil buffers of the render target are normally
+ cleared. The clear values are specified in \a colorClearValue and \a
+ depthStencilClearValue. The exception is when the render target was created
+ with QRhiTextureRenderTarget::PreserveColorContents and/or
+ QRhiTextureRenderTarget::PreserveDepthStencilContents. The clear values are
+ ignored then.
+
+ \note Enabling preserved color or depth contents leads to decreased
+ performance depending on the underlying hardware. Mobile GPUs with tiled
+ architecture benefit from not having to reload the previous contents into
+ the tile buffer. Similarly, a QRhiTextureRenderTarget with a QRhiTexture as
+ the depth buffer is less efficient than a QRhiRenderBuffer since using a
+ depth texture triggers requiring writing the data out to it, while with
+ renderbuffers this is not needed (as the API does not allow sampling or
+ reading from a renderbuffer).
+
+ \note Do not assume that any state or resource bindings persist between
+ passes.
+
+ \note The QRhiCommandBuffer's \c set and \c draw functions can only be
+ called inside a pass. Also, with the exception of setGraphicsPipeline(),
+ they expect to have a pipeline set already on the command buffer.
+ Unspecified issues may arise otherwise, depending on the backend.
+ */
+void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates)
+{
+ m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates);
+}
+
+/*!
+ Records ending the current render pass.
+
+ \a resourceUpdates, when not null, specifies a resource update batch that
+ is to be committed and then released.
+ */
+void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
+{
+ m_rhi->endPass(this, resourceUpdates);
+}
+
+/*!
+ Records setting a new graphics pipeline \a ps.
+
+ \note This function must be called before recording other \c set or \c draw
+ commands on the command buffer.
+
+ \note QRhi will optimize out unnecessary invocations within a pass, so
+ therefore overoptimizing to avoid calls to this function is not necessary
+ on the applications' side.
+
+ \note This function can only be called inside a pass, meaning between a
+ beginPass() end endPass() call.
+ */
+void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
+{
+ m_rhi->setGraphicsPipeline(this, ps);
+}
+
+/*!
+ Records binding a set of shader resources, such as, uniform buffers or
+ textures, that are made visible to one or more shader stages.
+
+ \a srb can be null in which case the current graphics pipeline's associated
+ QRhiGraphicsPipeline::shaderResourceBindings() is used. When \a srb is
+ non-null, it must be
+ \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible},
+ meaning the layout (number of bindings, the type and binding number of each
+ binding) must fully match the QRhiShaderResourceBindings that was
+ associated with the pipeline at the time of calling
+ QRhiGraphicsPipeline::build().
+
+ There are cases when a seemingly unnecessary setShaderResources() call is
+ mandatory: when rebuilding a resource referenced from \a srb, for example
+ changing the size of a QRhiBuffer followed by a QRhiBuffer::build(), this
+ is the place where associated native objects (such as descriptor sets in
+ case of Vulkan) are updated to refer to the current native resources that
+ back the QRhiBuffer, QRhiTexture, QRhiSampler objects referenced from \a
+ srb. In this case setShaderResources() must be called even if \a srb is
+ the same as in the last call.
+
+ \a dynamicOffsets allows specifying buffer offsets for uniform buffers that
+ were associated with \a srb via
+ QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
+ different from providing the offset in the \a srb itself: dynamic offsets
+ do not require building a new QRhiShaderResourceBindings for every
+ different offset, can avoid writing the underlying descriptors (with
+ backends where applicable), and so they may be more efficient. Each element
+ of \a dynamicOffsets is a \c binding - \c offset pair.
+ \a dynamicOffsetCount specifies the number of elements in \a dynamicOffsets.
+
+ \note All offsets in \a dynamicOffsets must be byte aligned to the value
+ returned from QRhi::ubufAlignment().
+
+ \note QRhi will optimize out unnecessary invocations within a pass (taking
+ the conditions described above into account), so therefore overoptimizing
+ to avoid calls to this function is not necessary on the applications' side.
+
+ \note This function can only be called inside a pass, meaning between a
+ beginPass() end endPass() call.
+ */
+void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const DynamicOffset *dynamicOffsets)
+{
+ m_rhi->setShaderResources(this, srb, dynamicOffsetCount, dynamicOffsets);
+}
+
+/*!
+ Records vertex input bindings.
+
+ The index buffer used by subsequent drawIndexed() commands is specified by
+ \a indexBuf, \a indexOffset, and \a indexFormat. \a indexBuf can be set to
+ null when indexed drawing is not needed.
+
+ Vertex buffer bindings are batched. \a startBinding specifies the first
+ binding number. The recorded command then binds each buffer from \a
+ bindings to the binding point \c{startBinding + i} where \c i is the index
+ in \a bindings. Each element in \a bindings specifies a QRhiBuffer and an
+ offset.
+
+ Superfluous vertex input and index changes in the same pass are ignored
+ automatically with most backends and therefore applications do not need to
+ overoptimize to avoid calls to this function.
+
+ \note This function can only be called inside a pass, meaning between a
+ beginPass() end endPass() call.
+
+ As a simple example, take a vertex shader with two inputs:
+
+ \badcode
+ layout(location = 0) in vec4 position;
+ layout(location = 1) in vec3 color;
+ \endcode
+
+ and assume we have the data available in interleaved format, using only 2
+ floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
+ this shader can then be created using the input layout:
+
+ \badcode
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+ \endcode
+
+ Here there is one buffer binding (binding number 0), with two inputs
+ referencing it. When recording the pass, once the pipeline is set, the
+ vertex bindings can be specified simply like the following (using C++11
+ initializer syntax), assuming vbuf is the QRhiBuffer with all the
+ interleaved position+color data:
+
+ \badcode
+ const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ \endcode
+ */
+void QRhiCommandBuffer::setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ IndexFormat indexFormat)
+{
+ m_rhi->setVertexInput(this, startBinding, bindingCount, bindings, indexBuf, indexOffset, indexFormat);
+}
+
+/*!
+ Records setting the active viewport rectangle specified in \a viewport.
+
+ With backends where the underlying graphics API has scissoring always
+ enabled, this function also sets the scissor to match the viewport whenever
+ the active QRhiGraphicsPipeline does not have
+ \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set.
+
+ \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
+ bottom-left.
+
+ \note This function can only be called inside a pass, meaning between a
+ beginPass() end endPass() call.
+ */
+void QRhiCommandBuffer::setViewport(const QRhiViewport &viewport)
+{
+ m_rhi->setViewport(this, viewport);
+}
+
+/*!
+ Records setting the active scissor rectangle specified in \a scissor.
+
+ This can only be called when the bound pipeline has
+ \l{QRhiGraphicsPipeline::UsesScissor}{UsesScissor} set. When the flag is
+ set on the active pipeline, this function must be called because scissor
+ testing will get enabled and so a scissor rectangle must be provided.
+
+ \note QRhi assumes OpenGL-style viewport coordinates, meaning x and y are
+ bottom-left.
+
+ \note This function can only be called inside a pass, meaning between a
+ beginPass() end endPass() call.
+ */
+void QRhiCommandBuffer::setScissor(const QRhiScissor &scissor)
+{
+ m_rhi->setScissor(this, scissor);
+}
+
+/*!
+ Records setting the active blend constants to \a c.
+
+ This can only be called when the bound pipeline has
+ QRhiGraphicsPipeline::UsesBlendConstants set.
+
+ \note This function can only be called inside a pass, meaning between a
+ beginPass() end endPass() call.
+ */
+void QRhiCommandBuffer::setBlendConstants(const QColor &c)
+{
+ m_rhi->setBlendConstants(this, c);
+}
+
+/*!
+ Records setting the active stencil reference value to \a refValue.
+
+ This can only be called when the bound pipeline has
+ QRhiGraphicsPipeline::UsesStencilRef set.
+
+ \note This function can only be called inside a pass, meaning between a
+ beginPass() end endPass() call.
+ */
+void QRhiCommandBuffer::setStencilRef(quint32 refValue)
+{
+ m_rhi->setStencilRef(this, refValue);
+}
+
+/*!
+ Records a non-indexed draw.
+
+ The number of vertices is specified in \a vertexCount. For instanced
+ drawing set \a instanceCount to a value other than 1. \a firstVertex is
+ the index of the first vertex to draw. \a firstInstance is the instance ID
+ of the first instance to draw.
+
+ \note This function can only be called inside a pass, meaning between a
+ beginPass() end endPass() call.
+ */
+void QRhiCommandBuffer::draw(quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
+{
+ m_rhi->draw(this, vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
+/*!
+ Records an indexed draw.
+
+ The number of vertices is specified in \a indexCount. \a firstIndex is the
+ base index. The effective offset in the index buffer is given by
+ \c{indexOffset + firstIndex * n} where \c n is 2 or 4 depending on the
+ index element type. \c indexOffset is specified in setVertexInput().
+
+ \note The effective offset in the index buffer must be 4 byte aligned with
+ some backends (for example, Metal). With these backends the
+ \l{QRhi::NonFourAlignedEffectiveIndexBufferOffset}{NonFourAlignedEffectiveIndexBufferOffset}
+ feature will be reported as not-supported.
+
+ For instanced drawing set \a instanceCount to a value other than 1. \a
+ firstInstance is the instance ID of the first instance to draw.
+
+ \a vertexOffset is added to the vertex index.
+
+ \note This function can only be called inside a pass, meaning between a
+ beginPass() end endPass() call.
+ */
+void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance)
+{
+ m_rhi->drawIndexed(this, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
+}
+
+/*!
+ Records a named debug group on the command buffer. This is shown in
+ graphics debugging tools such as \l{https://renderdoc.org/}{RenderDoc} and
+ \l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
+ indicated by debugMarkEnd().
+
+ \note Ignored when QRhi::DebugMarkers are not supported or
+ QRhi::EnableDebugMarkers is not set.
+
+ \note Can be called anywhere within the frame, both inside and outside of passes.
+ */
+void QRhiCommandBuffer::debugMarkBegin(const QByteArray &name)
+{
+ m_rhi->debugMarkBegin(this, name);
+}
+
+/*!
+ Records the end of a debug group.
+
+ \note Ignored when QRhi::DebugMarkers are not supported or
+ QRhi::EnableDebugMarkers is not set.
+
+ \note Can be called anywhere within the frame, both inside and outside of passes.
+ */
+void QRhiCommandBuffer::debugMarkEnd()
+{
+ m_rhi->debugMarkEnd(this);
+}
+
+/*!
+ Inserts a debug message \a msg into the command stream.
+
+ \note Ignored when QRhi::DebugMarkers are not supported or
+ QRhi::EnableDebugMarkers is not set.
+
+ \note With some backends debugMarkMsg() is only supported inside a pass and
+ is ignored when called outside a pass. With others it is recorded anywhere
+ within the frame.
+ */
+void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
+{
+ m_rhi->debugMarkMsg(this, msg);
+}
+
+/*!
+ \return a pointer to a backend-specific QRhiNativeHandles subclass, such as
+ QRhiVulkanCommandBufferNativeHandles. The returned value is null when
+ exposing the underlying native resources is not supported by, or not
+ applicable to, the backend.
+
+ \sa QRhiVulkanCommandBufferNativeHandles,
+ QRhiMetalCommandBufferNativeHandles, beginExternal(), endExternal()
+ */
+const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
+{
+ return m_rhi->nativeHandles(this);
+}
+
+/*!
+ To be called when the application before the application is about to
+ enqueue commands to the current pass' command buffer by calling graphics
+ API functions directly.
+
+ With Vulkan or Metal one can query the native command buffer or encoder
+ objects via nativeHandles() and enqueue commands to them. With OpenGL or
+ Direct3D 11 the (device) context can be retrieved from
+ QRhi::nativeHandles(). However, this must never be done without ensuring
+ the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
+ wrapping any externally added command recording between beginExternal() and
+ endExternal(). Conceptually this is the same as QPainter's
+ \l{QPainter::beginNativePainting()}{beginNativePainting()} and
+ \l{QPainter::endNativePainting()}{endNativePainting()} functions.
+
+ For OpenGL in particular, this function has an additional task: it makes
+ sure the context is made current on the current thread.
+
+ \note Once beginExternal() is called, no other render pass specific
+ functions (\c set* or \c draw*) must be called on the
+ QRhiCommandBuffer until endExternal().
+
+ \sa endExternal(), nativeHandles()
+ */
+void QRhiCommandBuffer::beginExternal()
+{
+ m_rhi->beginExternal(this);
+}
+
+/*!
+ To be called once the externally added commands are recorded to the command
+ buffer or context.
+
+ \note All QRhiCommandBuffer state must be assumed as invalid after calling
+ this function. Pipelines, vertex and index buffers, and other state must be
+ set again if more draw calls are recorded after the external commands.
+
+ \sa beginExternal(), nativeHandles()
+ */
+void QRhiCommandBuffer::endExternal()
+{
+ m_rhi->endExternal(this);
+}
+
+/*!
+ \return the value (typically an offset) \a v aligned to the uniform buffer
+ alignment given by by ubufAlignment().
+ */
+int QRhi::ubufAligned(int v) const
+{
+ const int byteAlign = ubufAlignment();
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+/*!
+ \return the number of mip levels for a given \a size.
+ */
+int QRhi::mipLevelsForSize(const QSize &size) const
+{
+ return qFloor(std::log2(qMax(size.width(), size.height()))) + 1;
+}
+
+/*!
+ \return the texture image size for a given \a mipLevel, calculated based on
+ the level 0 size given in \a baseLevelSize.
+ */
+QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize) const
+{
+ const int w = qMax(1, baseLevelSize.width() >> mipLevel);
+ const int h = qMax(1, baseLevelSize.height() >> mipLevel);
+ return QSize(w, h);
+}
+
+/*!
+ \return \c true if the underlying graphics API has the Y axis pointing up
+ in framebuffers and images.
+
+ In practice this is \c true for OpenGL only.
+ */
+bool QRhi::isYUpInFramebuffer() const
+{
+ return d->isYUpInFramebuffer();
+}
+
+/*!
+ \return \c true if the underlying graphics API has the Y axis pointing up
+ in its normalized device coordinate system.
+
+ In practice this is \c false for Vulkan only.
+
+ \note clipSpaceCorrMatrix() includes the corresponding adjustment (to make
+ Y point up) in its returned matrix.
+ */
+bool QRhi::isYUpInNDC() const
+{
+ return d->isYUpInNDC();
+}
+
+/*!
+ \return \c true if the underlying graphics API uses depth 0 - 1 in clip
+ space.
+
+ In practice this is \c false for OpenGL only.
+
+ \note clipSpaceCorrMatrix() includes the corresponding adjustment in its
+ returned matrix.
+ */
+bool QRhi::isClipDepthZeroToOne() const
+{
+ return d->isClipDepthZeroToOne();
+}
+
+/*!
+ \return a matrix that can be used to allow applications keep using
+ OpenGL-targeted vertex data and perspective projection matrices (such as,
+ the ones generated by QMatrix4x4::perspective()), regardless of the
+ backend. Once \c{this_matrix * mvp} is used instead of just \c mvp, vertex
+ data with Y up and viewports with depth range 0 - 1 can be used without
+ considering what backend and so graphics API is going to be used at run
+ time.
+
+ See
+ \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
+ page} for a discussion of the topic from Vulkan perspective.
+ */
+QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
+{
+ return d->clipSpaceCorrMatrix();
+}
+
+/*!
+ \return \c true if the specified texture \a format modified by \a flags is
+ supported.
+
+ The query is supported both for uncompressed and compressed formats.
+ */
+bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
+{
+ return d->isTextureFormatSupported(format, flags);
+}
+
+/*!
+ \return \c true if the specified \a feature is supported
+ */
+bool QRhi::isFeatureSupported(QRhi::Feature feature) const
+{
+ return d->isFeatureSupported(feature);
+}
+
+/*!
+ \return the value for the specified resource \a limit.
+
+ The values are expected to be queried by the backends upon initialization,
+ meaning calling this function is a light operation.
+ */
+int QRhi::resourceLimit(ResourceLimit limit) const
+{
+ return d->resourceLimit(limit);
+}
+
+/*!
+ \return a pointer to the backend-specific collection of native objects
+ for the device, context, and similar concepts used by the backend.
+
+ Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
+ QRhiGles2NativeHandles, QRhiMetalNativeHandles as appropriate.
+
+ \note No ownership is transferred, neither for the returned pointer nor for
+ any native objects.
+ */
+const QRhiNativeHandles *QRhi::nativeHandles()
+{
+ return d->nativeHandles();
+}
+
+/*!
+ \return the associated QRhiProfiler instance.
+
+ An instance is always available for each QRhi, but it is not very useful
+ without EnableProfiling because no data is collected without setting the
+ flag upon creation.
+ */
+QRhiProfiler *QRhi::profiler()
+{
+ return &d->profiler;
+}
+
+/*!
+ \return a new graphics pipeline resource.
+
+ \sa QRhiResource::release()
+ */
+QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
+{
+ return d->createGraphicsPipeline();
+}
+
+/*!
+ \return a new shader resource binding collection resource.
+
+ \sa QRhiResource::release()
+ */
+QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
+{
+ return d->createShaderResourceBindings();
+}
+
+/*!
+ \return a new buffer with the specified \a type, \a usage, and \a size.
+
+ \note Some \a usage and \a type combinations may not be supported by all
+ backends. See \l{QRhi::NonDynamicUniformBuffers}{the feature flags}.
+
+ \sa QRhiResource::release()
+ */
+QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ int size)
+{
+ return d->createBuffer(type, usage, size);
+}
+
+/*!
+ \return a new renderbuffer with the specified \a type, \a pixelSize, \a
+ sampleCount, and \a flags.
+
+ \sa QRhiResource::release()
+ */
+QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags)
+{
+ return d->createRenderBuffer(type, pixelSize, sampleCount, flags);
+}
+
+/*!
+ \return a new texture with the specified \a format, \a pixelSize, \a
+ sampleCount, and \a flags.
+
+ \note \a format specifies the requested internal and external format,
+ meaning the data to be uploaded to the texture will need to be in a
+ compatible format, while the native texture may (but is not guaranteed to,
+ in case of OpenGL at least) use this format internally.
+
+ \sa QRhiResource::release()
+ */
+QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiTexture::Flags flags)
+{
+ return d->createTexture(format, pixelSize, sampleCount, flags);
+}
+
+/*!
+ \return a new sampler with the specified magnification filter \a magFilter,
+ minification filter \a minFilter, mipmapping mode \a mipmapMpde, and S/T
+ addressing modes \a u and \a v.
+
+ \sa QRhiResource::release()
+ */
+QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v)
+{
+ return d->createSampler(magFilter, minFilter, mipmapMode, u, v);
+}
+
+/*!
+ \return a new texture render target with color and depth/stencil
+ attachments given in \a desc, and with the specified \a flags.
+
+ \sa QRhiResource::release()
+ */
+
+QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags)
+{
+ return d->createTextureRenderTarget(desc, flags);
+}
+
+/*!
+ \return a new swapchain.
+
+ \sa QRhiResource::release(), QRhiSwapChain::buildOrResize()
+ */
+QRhiSwapChain *QRhi::newSwapChain()
+{
+ return d->createSwapChain();
+}
+
+/*!
+ Starts a new frame targeting the next available buffer of \a swapChain.
+
+ The high level pattern of rendering into a QWindow using a swapchain:
+
+ \list
+
+ \li Create a swapchain.
+
+ \li Call QRhiSwapChain::buildOrResize() whenever the surface size is
+ different than before.
+
+ \li Call QRhiSwapChain::release() on
+ QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
+
+ \li Then on every frame:
+ \badcode
+ beginFrame(sc);
+ updates = nextResourceUpdateBatch();
+ updates->...
+ QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
+ cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
+ ...
+ cb->endPass();
+ ... // more passes as necessary
+ endFrame(sc);
+ \endcode
+
+ \endlist
+
+ \a flags is currently unused.
+
+ \sa endFrame()
+ */
+QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
+{
+ if (d->inFrame)
+ qWarning("Attempted to call beginFrame() within a still active frame; ignored");
+
+ QRhi::FrameOpResult r = !d->inFrame ? d->beginFrame(swapChain, flags) : FrameOpSuccess;
+ if (r == FrameOpSuccess)
+ d->inFrame = true;
+
+ return r;
+}
+
+/*!
+ Ends, commits, and presents a frame that was started in the last
+ beginFrame() on \a swapChain.
+
+ Double (or triple) buffering is managed internally by the QRhiSwapChain and
+ QRhi.
+
+ \a flags can optionally be used to change the behavior in certain ways.
+ Passing QRhi::SkipPresent skips queuing the Present command or calling
+ swapBuffers.
+
+ \sa beginFrame()
+ */
+QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
+{
+ if (!d->inFrame)
+ qWarning("Attempted to call endFrame() without an active frame; ignored");
+
+ QRhi::FrameOpResult r = d->inFrame ? d->endFrame(swapChain, flags) : FrameOpSuccess;
+ d->inFrame = false;
+ // releaseAndDestroyLater is a high level QRhi concept the backends know
+ // nothing about - handle it here.
+ qDeleteAll(d->pendingReleaseAndDestroyResources);
+ d->pendingReleaseAndDestroyResources.clear();
+
+ return r;
+}
+
+/*!
+ \return true when there is an active frame, meaning there was a
+ beginFrame() (or beginOffscreenFrame()) with no corresponding endFrame()
+ (or endOffscreenFrame()) yet.
+
+ \sa currentFrameSlot(), beginFrame(), endFrame()
+ */
+bool QRhi::isRecordingFrame() const
+{
+ return d->inFrame;
+}
+
+/*!
+ \return the current frame slot index while recording a frame. Unspecified
+ when called outside an active frame (that is, when isRecordingFrame() is \c
+ false).
+
+ With backends like Vulkan or Metal, it is the responsibility of the QRhi
+ backend to block whenever starting a new frame and finding the CPU is
+ already \c{FramesInFlight - 1} frames ahead of the GPU (because the command
+ buffer submitted in frame no. \c{current} - \c{FramesInFlight} has not yet
+ completed).
+
+ Resources that tend to change between frames (such as, the native buffer
+ object backing a QRhiBuffer with type QRhiBuffer::Dynamic) exist in
+ multiple versions, so that each frame, that can be submitted while a
+ previous one is still being processed, works with its own copy, thus
+ avoiding the need to stall the pipeline when preparing the frame. (The
+ contents of a resource that may still be in use in the GPU should not be
+ touched, but simply always waiting for the previous frame to finish would
+ reduce GPU utilization and ultimately, performance and efficiency.)
+
+ Conceptually this is somewhat similar to copy-on-write schemes used by some
+ C++ containers and other types. It may also be similar to what an OpenGL or
+ Direct 3D 11 implementation performs internally for certain type of objects.
+
+ In practice, such double (or tripple) buffering resources is realized in
+ the Vulkan, Metal, and similar QRhi backends by having a fixed number of
+ native resource (such as, VkBuffer) \c slots behind a QRhiResource. That
+ can then be indexed by a frame slot index running 0, 1, ..,
+ FramesInFlight-1, and then wrapping around.
+
+ All this is managed transparently to the users of QRhi. However,
+ applications that integrate rendering done directly with the graphics API
+ may want to perform a similar double or tripple buffering of their own
+ graphics resources. That is then most easily achieved by knowing the values
+ of the maximum number of in-flight frames (retrievable via resourceLimit())
+ and the current frame (slot) index (returned by this function).
+
+ \sa isRecordingFrame(), beginFrame(), endFrame()
+ */
+int QRhi::currentFrameSlot() const
+{
+ return d->currentFrameSlot;
+}
+
+/*!
+ Starts a new offscreen frame. Provides a command buffer suitable for
+ recording rendering commands in \a cb.
+
+ \note The QRhiCommandBuffer stored to *cb is not owned by the caller.
+
+ Rendering without a swapchain is possible as well. The typical use case is
+ to use it in completely offscreen applications, e.g. to generate image
+ sequences by rendering and reading back without ever showing a window.
+
+ Usage in on-screen applications (so beginFrame, endFrame,
+ beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) is possible too
+ but it does reduce parallelism so it should be done only infrequently.
+
+ Offscreen frames do not let the CPU - potentially - generate another frame
+ while the GPU is still processing the previous one. This has the side
+ effect that if readbacks are scheduled, the results are guaranteed to be
+ available once endOffscreenFrame() returns. That is not the case with
+ frames targeting a swapchain.
+
+ The skeleton of rendering a frame without a swapchain and then reading the
+ frame contents back could look like the following:
+
+ \badcode
+ QRhiReadbackResult rbResult;
+ QRhiCommandBuffer *cb;
+ beginOffscreenFrame(&cb);
+ beginPass
+ ...
+ u = nextResourceUpdateBatch();
+ u->readBackTexture(rb, &rbResult);
+ endPass(u);
+ endOffscreenFrame();
+ // image data available in rbResult
+ \endcode
+
+ \sa endOffscreenFrame()
+ */
+QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb)
+{
+ if (d->inFrame)
+ qWarning("Attempted to call beginOffscreenFrame() within a still active frame; ignored");
+
+ QRhi::FrameOpResult r = !d->inFrame ? d->beginOffscreenFrame(cb) : FrameOpSuccess;
+ if (r == FrameOpSuccess)
+ d->inFrame = true;
+
+ return r;
+}
+
+/*!
+ Ends and waits for the offscreen frame.
+
+ \sa beginOffscreenFrame()
+ */
+QRhi::FrameOpResult QRhi::endOffscreenFrame()
+{
+ if (!d->inFrame)
+ qWarning("Attempted to call endOffscreenFrame() without an active frame; ignored");
+
+ QRhi::FrameOpResult r = d->inFrame ? d->endOffscreenFrame() : FrameOpSuccess;
+ d->inFrame = false;
+ qDeleteAll(d->pendingReleaseAndDestroyResources);
+ d->pendingReleaseAndDestroyResources.clear();
+
+ return r;
+}
+
+/*!
+ Waits for any work on the graphics queue (where applicable) to complete,
+ then executes all deferred operations, like completing readbacks and
+ resource releases. Can be called inside and outside of a frame, but not
+ inside a pass. Inside a frame it implies submitting any work on the
+ command buffer.
+
+ \note Avoid this function. One case where it may be needed is when the
+ results of an enqueued readback in a swapchain-based frame are needed at a
+ fixed given point and so waiting for the results is desired.
+ */
+QRhi::FrameOpResult QRhi::finish()
+{
+ return d->finish();
+}
+
+/*!
+ \return the list of supported sample counts.
+
+ A typical example would be (1, 2, 4, 8).
+
+ With some backend this list of supported values is fixed in advance, while
+ with some others the (physical) device properties indicate what is
+ supported at run time.
+ */
+QVector<int> QRhi::supportedSampleCounts() const
+{
+ return d->supportedSampleCounts();
+}
+
+/*!
+ \return the minimum uniform buffer offset alignment in bytes. This is
+ typically 256.
+
+ Attempting to bind a uniform buffer region with an offset not aligned to
+ this value will lead to failures depending on the backend and the
+ underlying graphics API.
+
+ \sa ubufAligned()
+ */
+int QRhi::ubufAlignment() const
+{
+ return d->ubufAlignment();
+}
+
+QRhiGlobalObjectIdGenerator::Type QRhiGlobalObjectIdGenerator::newId()
+{
+ static QRhiGlobalObjectIdGenerator inst;
+ return ++inst.counter;
+}
+
+bool QRhiPassResourceTracker::isEmpty() const
+{
+ return m_buffers.isEmpty() && m_textures.isEmpty();
+}
+
+void QRhiPassResourceTracker::reset()
+{
+ m_buffers.clear();
+ m_textures.clear();
+}
+
+static inline QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResourceTracker::BufferStage a,
+ QRhiPassResourceTracker::BufferStage b)
+{
+ return QRhiPassResourceTracker::BufferStage(qMin(int(a), int(b)));
+}
+
+void QRhiPassResourceTracker::registerBufferOnce(QRhiBuffer *buf, int slot, BufferAccess access, BufferStage stage,
+ const UsageState &stateAtPassBegin)
+{
+ auto it = std::find_if(m_buffers.begin(), m_buffers.end(), [buf](const Buffer &b) { return b.buf == buf; });
+ if (it != m_buffers.end()) {
+ if (it->access != access) {
+ const QByteArray name = buf->name();
+ qWarning("Buffer %p (%s) used with different accesses within the same pass, this is not allowed.",
+ buf, name.constData());
+ return;
+ }
+ if (it->stage != stage)
+ it->stage = earlierStage(it->stage, stage);
+ // Multiple registrations of the same buffer is fine as long is it is
+ // a compatible usage. stateAtPassBegin is not actually the state at
+ // pass begin in the second, third, etc. invocation but that's fine
+ // since we'll just return here.
+ return;
+ }
+
+ Buffer b;
+ b.buf = buf;
+ b.slot = slot;
+ b.access = access;
+ b.stage = stage;
+ b.stateAtPassBegin = stateAtPassBegin;
+ m_buffers.append(b);
+}
+
+static inline QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a,
+ QRhiPassResourceTracker::TextureStage b)
+{
+ return QRhiPassResourceTracker::TextureStage(qMin(int(a), int(b)));
+}
+
+void QRhiPassResourceTracker::registerTextureOnce(QRhiTexture *tex, TextureAccess access, TextureStage stage,
+ const UsageState &stateAtPassBegin)
+{
+ auto it = std::find_if(m_textures.begin(), m_textures.end(), [tex](const Texture &t) { return t.tex == tex; });
+ if (it != m_textures.end()) {
+ if (it->access != access) {
+ const QByteArray name = tex->name();
+ qWarning("Texture %p (%s) used with different accesses within the same pass, this is not allowed.",
+ tex, name.constData());
+ }
+ if (it->stage != stage)
+ it->stage = earlierStage(it->stage, stage);
+ // Multiple registrations of the same texture is fine as long is it is
+ // a compatible usage. stateAtPassBegin is not actually the state at
+ // pass begin in the second, third, etc. invocation but that's fine
+ // since we'll just return here.
+ return;
+ }
+
+ Texture t;
+ t.tex = tex;
+ t.access = access;
+ t.stage = stage;
+ t.stateAtPassBegin = stateAtPassBegin;
+ m_textures.append(t);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
new file mode 100644
index 0000000000..a0f57819e4
--- /dev/null
+++ b/src/gui/rhi/qrhi_p.h
@@ -0,0 +1,1375 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHI_H
+#define QRHI_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qtguiglobal.h>
+#include <QSize>
+#include <QMatrix4x4>
+#include <QVector>
+#include <QThread>
+#include <QColor>
+#include <QImage>
+#include <functional>
+#include <array>
+#include <private/qshader_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+class QRhiImplementation;
+class QRhiBuffer;
+class QRhiRenderBuffer;
+class QRhiTexture;
+class QRhiSampler;
+class QRhiCommandBuffer;
+class QRhiResourceUpdateBatch;
+class QRhiResourceUpdateBatchPrivate;
+class QRhiProfiler;
+class QRhiShaderResourceBindingPrivate;
+
+class Q_GUI_EXPORT QRhiDepthStencilClearValue
+{
+public:
+ QRhiDepthStencilClearValue() = default;
+ QRhiDepthStencilClearValue(float d, quint32 s);
+
+ float depthClearValue() const { return m_d; }
+ void setDepthClearValue(float d) { m_d = d; }
+
+ quint32 stencilClearValue() const { return m_s; }
+ void setStencilClearValue(quint32 s) { m_s = s; }
+
+private:
+ float m_d = 1.0f;
+ quint32 m_s = 0;
+};
+
+Q_DECLARE_TYPEINFO(QRhiDepthStencilClearValue, Q_MOVABLE_TYPE);
+
+Q_GUI_EXPORT bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QRhiDepthStencilClearValue &v, uint seed = 0) Q_DECL_NOTHROW;
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiDepthStencilClearValue &);
+#endif
+
+class Q_GUI_EXPORT QRhiViewport
+{
+public:
+ QRhiViewport() = default;
+ QRhiViewport(float x, float y, float w, float h, float minDepth = 0.0f, float maxDepth = 1.0f);
+
+ std::array<float, 4> viewport() const { return m_rect; }
+ void setViewport(float x, float y, float w, float h) {
+ m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h;
+ }
+
+ float minDepth() const { return m_minDepth; }
+ void setMinDepth(float minDepth) { m_minDepth = minDepth; }
+
+ float maxDepth() const { return m_maxDepth; }
+ void setMaxDepth(float maxDepth) { m_maxDepth = maxDepth; }
+
+private:
+ std::array<float, 4> m_rect { { 0.0f, 0.0f, 0.0f, 0.0f } };
+ float m_minDepth = 0.0f;
+ float m_maxDepth = 1.0f;
+};
+
+Q_DECLARE_TYPEINFO(QRhiViewport, Q_MOVABLE_TYPE);
+
+Q_GUI_EXPORT bool operator==(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator!=(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QRhiViewport &v, uint seed = 0) Q_DECL_NOTHROW;
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiViewport &);
+#endif
+
+class Q_GUI_EXPORT QRhiScissor
+{
+public:
+ QRhiScissor() = default;
+ QRhiScissor(int x, int y, int w, int h);
+
+ std::array<int, 4> scissor() const { return m_rect; }
+ void setScissor(int x, int y, int w, int h) {
+ m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h;
+ }
+
+private:
+ std::array<int, 4> m_rect { { 0, 0, 0, 0 } };
+};
+
+Q_DECLARE_TYPEINFO(QRhiScissor, Q_MOVABLE_TYPE);
+
+Q_GUI_EXPORT bool operator==(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator!=(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QRhiScissor &v, uint seed = 0) Q_DECL_NOTHROW;
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiScissor &);
+#endif
+
+class Q_GUI_EXPORT QRhiVertexInputBinding
+{
+public:
+ enum Classification {
+ PerVertex,
+ PerInstance
+ };
+
+ QRhiVertexInputBinding() = default;
+ QRhiVertexInputBinding(quint32 stride, Classification cls = PerVertex, int stepRate = 1);
+
+ quint32 stride() const { return m_stride; }
+ void setStride(quint32 s) { m_stride = s; }
+
+ Classification classification() const { return m_classification; }
+ void setClassification(Classification c) { m_classification = c; }
+
+ int instanceStepRate() const { return m_instanceStepRate; }
+ void setInstanceStepRate(int rate) { m_instanceStepRate = rate; }
+
+private:
+ quint32 m_stride = 0;
+ Classification m_classification = PerVertex;
+ int m_instanceStepRate = 1;
+};
+
+Q_DECLARE_TYPEINFO(QRhiVertexInputBinding, Q_MOVABLE_TYPE);
+
+Q_GUI_EXPORT bool operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QRhiVertexInputBinding &v, uint seed = 0) Q_DECL_NOTHROW;
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputBinding &);
+#endif
+
+class Q_GUI_EXPORT QRhiVertexInputAttribute
+{
+public:
+ enum Format {
+ Float4,
+ Float3,
+ Float2,
+ Float,
+ UNormByte4,
+ UNormByte2,
+ UNormByte
+ };
+
+ QRhiVertexInputAttribute() = default;
+ QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset);
+
+ int binding() const { return m_binding; }
+ void setBinding(int b) { m_binding = b; }
+
+ int location() const { return m_location; }
+ void setLocation(int loc) { m_location = loc; }
+
+ Format format() const { return m_format; }
+ void setFormt(Format f) { m_format = f; }
+
+ quint32 offset() const { return m_offset; }
+ void setOffset(quint32 ofs) { m_offset = ofs; }
+
+private:
+ int m_binding = 0;
+ int m_location = 0;
+ Format m_format = Float4;
+ quint32 m_offset = 0;
+};
+
+Q_DECLARE_TYPEINFO(QRhiVertexInputAttribute, Q_MOVABLE_TYPE);
+
+Q_GUI_EXPORT bool operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QRhiVertexInputAttribute &v, uint seed = 0) Q_DECL_NOTHROW;
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputAttribute &);
+#endif
+
+class Q_GUI_EXPORT QRhiVertexInputLayout
+{
+public:
+ QRhiVertexInputLayout() = default;
+
+ QVector<QRhiVertexInputBinding> bindings() const { return m_bindings; }
+ void setBindings(const QVector<QRhiVertexInputBinding> &v) { m_bindings = v; }
+
+ QVector<QRhiVertexInputAttribute> attributes() const { return m_attributes; }
+ void setAttributes(const QVector<QRhiVertexInputAttribute> &v) { m_attributes = v; }
+
+private:
+ QVector<QRhiVertexInputBinding> m_bindings;
+ QVector<QRhiVertexInputAttribute> m_attributes;
+};
+
+Q_DECLARE_TYPEINFO(QRhiVertexInputLayout, Q_MOVABLE_TYPE);
+
+Q_GUI_EXPORT bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QRhiVertexInputLayout &v, uint seed = 0) Q_DECL_NOTHROW;
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &);
+#endif
+
+class Q_GUI_EXPORT QRhiGraphicsShaderStage
+{
+public:
+ enum Type {
+ Vertex,
+ Fragment
+ };
+
+ QRhiGraphicsShaderStage() = default;
+ QRhiGraphicsShaderStage(Type type, const QShader &shader,
+ QShader::Variant v = QShader::StandardShader);
+
+ Type type() const { return m_type; }
+ void setType(Type t) { m_type = t; }
+
+ QShader shader() const { return m_shader; }
+ void setShader(const QShader &s) { m_shader = s; }
+
+ QShader::Variant shaderVariant() const { return m_shaderVariant; }
+ void setShaderVariant(QShader::Variant v) { m_shaderVariant = v; }
+
+private:
+ Type m_type = Vertex;
+ QShader m_shader;
+ QShader::Variant m_shaderVariant = QShader::StandardShader;
+};
+
+Q_DECLARE_TYPEINFO(QRhiGraphicsShaderStage, Q_MOVABLE_TYPE);
+
+Q_GUI_EXPORT bool operator==(const QRhiGraphicsShaderStage &a, const QRhiGraphicsShaderStage &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator!=(const QRhiGraphicsShaderStage &a, const QRhiGraphicsShaderStage &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QRhiGraphicsShaderStage &s, uint seed = 0) Q_DECL_NOTHROW;
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiGraphicsShaderStage &);
+#endif
+
+class Q_GUI_EXPORT QRhiShaderResourceBinding
+{
+public:
+ enum Type {
+ UniformBuffer,
+ SampledTexture
+ };
+
+ enum StageFlag {
+ VertexStage = 1 << 0,
+ FragmentStage = 1 << 1
+ };
+ Q_DECLARE_FLAGS(StageFlags, StageFlag)
+
+ QRhiShaderResourceBinding();
+ QRhiShaderResourceBinding(const QRhiShaderResourceBinding &other);
+ QRhiShaderResourceBinding &operator=(const QRhiShaderResourceBinding &other);
+ ~QRhiShaderResourceBinding();
+ void detach();
+
+ bool isLayoutCompatible(const QRhiShaderResourceBinding &other) const;
+
+ static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf);
+ static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size);
+ static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, int size);
+ static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler);
+
+private:
+ QRhiShaderResourceBindingPrivate *d;
+ friend class QRhiShaderResourceBindingPrivate;
+ friend Q_GUI_EXPORT bool operator==(const QRhiShaderResourceBinding &, const QRhiShaderResourceBinding &) Q_DECL_NOTHROW;
+ friend Q_GUI_EXPORT bool operator!=(const QRhiShaderResourceBinding &, const QRhiShaderResourceBinding &) Q_DECL_NOTHROW;
+ friend Q_GUI_EXPORT uint qHash(const QRhiShaderResourceBinding &, uint) Q_DECL_NOTHROW;
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBinding &);
+#endif
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiShaderResourceBinding::StageFlags)
+
+Q_GUI_EXPORT bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QRhiShaderResourceBinding &b, uint seed = 0) Q_DECL_NOTHROW;
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBinding &);
+#endif
+
+class Q_GUI_EXPORT QRhiColorAttachment
+{
+public:
+ QRhiColorAttachment() = default;
+ QRhiColorAttachment(QRhiTexture *texture);
+ QRhiColorAttachment(QRhiRenderBuffer *renderBuffer);
+
+ QRhiTexture *texture() const { return m_texture; }
+ void setTexture(QRhiTexture *tex) { m_texture = tex; }
+
+ QRhiRenderBuffer *renderBuffer() const { return m_renderBuffer; }
+ void setRenderBuffer(QRhiRenderBuffer *rb) { m_renderBuffer = rb; }
+
+ int layer() const { return m_layer; }
+ void setLayer(int layer) { m_layer = layer; }
+
+ int level() const { return m_level; }
+ void setLevel(int level) { m_level = level; }
+
+ QRhiTexture *resolveTexture() const { return m_resolveTexture; }
+ void setResolveTexture(QRhiTexture *tex) { m_resolveTexture = tex; }
+
+ int resolveLayer() const { return m_resolveLayer; }
+ void setResolveLayer(int layer) { m_resolveLayer = layer; }
+
+ int resolveLevel() const { return m_resolveLevel; }
+ void setResolveLevel(int level) { m_resolveLevel = level; }
+
+private:
+ QRhiTexture *m_texture = nullptr;
+ QRhiRenderBuffer *m_renderBuffer = nullptr;
+ int m_layer = 0;
+ int m_level = 0;
+ QRhiTexture *m_resolveTexture = nullptr;
+ int m_resolveLayer = 0;
+ int m_resolveLevel = 0;
+};
+
+Q_DECLARE_TYPEINFO(QRhiColorAttachment, Q_MOVABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiTextureRenderTargetDescription
+{
+public:
+ QRhiTextureRenderTargetDescription() = default;
+ QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment);
+ QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiRenderBuffer *depthStencilBuffer);
+ QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiTexture *depthTexture);
+
+ QVector<QRhiColorAttachment> colorAttachments() const { return m_colorAttachments; }
+ void setColorAttachments(const QVector<QRhiColorAttachment> &att) { m_colorAttachments = att; }
+
+ QRhiRenderBuffer *depthStencilBuffer() const { return m_depthStencilBuffer; }
+ void setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer) { m_depthStencilBuffer = renderBuffer; }
+
+ QRhiTexture *depthTexture() const { return m_depthTexture; }
+ void setDepthTexture(QRhiTexture *texture) { m_depthTexture = texture; }
+
+private:
+ QVector<QRhiColorAttachment> m_colorAttachments;
+ QRhiRenderBuffer *m_depthStencilBuffer = nullptr;
+ QRhiTexture *m_depthTexture = nullptr;
+};
+
+Q_DECLARE_TYPEINFO(QRhiTextureRenderTargetDescription, Q_MOVABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiTextureSubresourceUploadDescription
+{
+public:
+ QRhiTextureSubresourceUploadDescription() = default;
+ QRhiTextureSubresourceUploadDescription(const QImage &image);
+ QRhiTextureSubresourceUploadDescription(const void *data, int size);
+
+ QImage image() const { return m_image; }
+ void setImage(const QImage &image) { m_image = image; }
+
+ QByteArray data() const { return m_data; }
+ void setData(const QByteArray &data) { m_data = data; }
+
+ QPoint destinationTopLeft() const { return m_destinationTopLeft; }
+ void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
+
+ QSize sourceSize() const { return m_sourceSize; }
+ void setSourceSize(const QSize &size) { m_sourceSize = size; }
+
+ QPoint sourceTopLeft() const { return m_sourceTopLeft; }
+ void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
+
+private:
+ QImage m_image;
+ QByteArray m_data;
+ QPoint m_destinationTopLeft;
+ QSize m_sourceSize;
+ QPoint m_sourceTopLeft;
+};
+
+Q_DECLARE_TYPEINFO(QRhiTextureSubresourceUploadDescription, Q_MOVABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiTextureUploadEntry
+{
+public:
+ QRhiTextureUploadEntry() = default;
+ QRhiTextureUploadEntry(int layer, int level, const QRhiTextureSubresourceUploadDescription &desc);
+
+ int layer() const { return m_layer; }
+ void setLayer(int layer) { m_layer = layer; }
+
+ int level() const { return m_level; }
+ void setLevel(int level) { m_level = level; }
+
+ QRhiTextureSubresourceUploadDescription description() const { return m_desc; }
+ void setDescription(const QRhiTextureSubresourceUploadDescription &desc) { m_desc = desc; }
+
+private:
+ int m_layer = 0;
+ int m_level = 0;
+ QRhiTextureSubresourceUploadDescription m_desc;
+};
+
+Q_DECLARE_TYPEINFO(QRhiTextureUploadEntry, Q_MOVABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiTextureUploadDescription
+{
+public:
+ QRhiTextureUploadDescription() = default;
+ QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry);
+ QRhiTextureUploadDescription(const QVector<QRhiTextureUploadEntry> &entries);
+
+ QVector<QRhiTextureUploadEntry> entries() const { return m_entries; }
+ void setEntries(const QVector<QRhiTextureUploadEntry> &entries) { m_entries = entries; }
+ void append(const QRhiTextureUploadEntry &entry);
+
+private:
+ QVector<QRhiTextureUploadEntry> m_entries;
+};
+
+Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription, Q_MOVABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiTextureCopyDescription
+{
+public:
+ QRhiTextureCopyDescription() = default;
+
+ QSize pixelSize() const { return m_pixelSize; }
+ void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
+
+ int sourceLayer() const { return m_sourceLayer; }
+ void setSourceLayer(int layer) { m_sourceLayer = layer; }
+
+ int sourceLevel() const { return m_sourceLevel; }
+ void setSourceLevel(int level) { m_sourceLevel = level; }
+
+ QPoint sourceTopLeft() const { return m_sourceTopLeft; }
+ void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
+
+ int destinationLayer() const { return m_destinationLayer; }
+ void setDestinationLayer(int layer) { m_destinationLayer = layer; }
+
+ int destinationLevel() const { return m_destinationLevel; }
+ void setDestinationLevel(int level) { m_destinationLevel = level; }
+
+ QPoint destinationTopLeft() const { return m_destinationTopLeft; }
+ void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
+
+private:
+ QSize m_pixelSize;
+ int m_sourceLayer = 0;
+ int m_sourceLevel = 0;
+ QPoint m_sourceTopLeft;
+ int m_destinationLayer = 0;
+ int m_destinationLevel = 0;
+ QPoint m_destinationTopLeft;
+};
+
+Q_DECLARE_TYPEINFO(QRhiTextureCopyDescription, Q_MOVABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiReadbackDescription
+{
+public:
+ QRhiReadbackDescription() = default;
+ QRhiReadbackDescription(QRhiTexture *texture);
+
+ QRhiTexture *texture() const { return m_texture; }
+ void setTexture(QRhiTexture *tex) { m_texture = tex; }
+
+ int layer() const { return m_layer; }
+ void setLayer(int layer) { m_layer = layer; }
+
+ int level() const { return m_level; }
+ void setLevel(int level) { m_level = level; }
+
+private:
+ QRhiTexture *m_texture = nullptr;
+ int m_layer = 0;
+ int m_level = 0;
+};
+
+Q_DECLARE_TYPEINFO(QRhiReadbackDescription, Q_MOVABLE_TYPE);
+
+struct Q_GUI_EXPORT QRhiNativeHandles
+{
+};
+
+class Q_GUI_EXPORT QRhiResource
+{
+public:
+ enum Type {
+ Buffer,
+ Texture,
+ Sampler,
+ RenderBuffer,
+ RenderPassDescriptor,
+ RenderTarget,
+ TextureRenderTarget,
+ ShaderResourceBindings,
+ GraphicsPipeline,
+ SwapChain,
+ CommandBuffer
+ };
+
+ virtual ~QRhiResource();
+
+ virtual Type resourceType() const = 0;
+
+ virtual void release() = 0;
+ void releaseAndDestroyLater();
+
+ QByteArray name() const;
+ void setName(const QByteArray &name);
+
+ quint64 globalResourceId() const;
+
+protected:
+ QRhiResource(QRhiImplementation *rhi);
+ Q_DISABLE_COPY(QRhiResource)
+ friend class QRhiImplementation;
+ QRhiImplementation *m_rhi = nullptr;
+ quint64 m_id;
+ QByteArray m_objectName;
+};
+
+class Q_GUI_EXPORT QRhiBuffer : public QRhiResource
+{
+public:
+ enum Type {
+ Immutable,
+ Static,
+ Dynamic
+ };
+
+ enum UsageFlag {
+ VertexBuffer = 1 << 0,
+ IndexBuffer = 1 << 1,
+ UniformBuffer = 1 << 2
+ };
+ Q_DECLARE_FLAGS(UsageFlags, UsageFlag)
+
+ QRhiResource::Type resourceType() const override;
+
+ Type type() const { return m_type; }
+ void setType(Type t) { m_type = t; }
+
+ UsageFlags usage() const { return m_usage; }
+ void setUsage(UsageFlags u) { m_usage = u; }
+
+ int size() const { return m_size; }
+ void setSize(int sz) { m_size = sz; }
+
+ virtual bool build() = 0;
+
+protected:
+ QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, int size_);
+ Type m_type;
+ UsageFlags m_usage;
+ int m_size;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiBuffer::UsageFlags)
+
+class Q_GUI_EXPORT QRhiTexture : public QRhiResource
+{
+public:
+ enum Flag {
+ RenderTarget = 1 << 0,
+ CubeMap = 1 << 2,
+ MipMapped = 1 << 3,
+ sRGB = 1 << 4,
+ UsedAsTransferSource = 1 << 5,
+ UsedWithGenerateMips = 1 << 6
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ enum Format {
+ UnknownFormat,
+
+ RGBA8,
+ BGRA8,
+ R8,
+ R16,
+ RED_OR_ALPHA8,
+
+ RGBA16F,
+ RGBA32F,
+
+ D16,
+ D32F,
+
+ BC1,
+ BC2,
+ BC3,
+ BC4,
+ BC5,
+ BC6H,
+ BC7,
+
+ ETC2_RGB8,
+ ETC2_RGB8A1,
+ ETC2_RGBA8,
+
+ ASTC_4x4,
+ ASTC_5x4,
+ ASTC_5x5,
+ ASTC_6x5,
+ ASTC_6x6,
+ ASTC_8x5,
+ ASTC_8x6,
+ ASTC_8x8,
+ ASTC_10x5,
+ ASTC_10x6,
+ ASTC_10x8,
+ ASTC_10x10,
+ ASTC_12x10,
+ ASTC_12x12
+ };
+
+ QRhiResource::Type resourceType() const override;
+
+ Format format() const { return m_format; }
+ void setFormat(Format fmt) { m_format = fmt; }
+
+ QSize pixelSize() const { return m_pixelSize; }
+ void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ int sampleCount() const { return m_sampleCount; }
+ void setSampleCount(int s) { m_sampleCount = s; }
+
+ virtual bool build() = 0;
+ virtual const QRhiNativeHandles *nativeHandles();
+ virtual bool buildFrom(const QRhiNativeHandles *src);
+
+protected:
+ QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_,
+ int sampleCount_, Flags flags_);
+ Format m_format;
+ QSize m_pixelSize;
+ int m_sampleCount;
+ Flags m_flags;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTexture::Flags)
+
+class Q_GUI_EXPORT QRhiSampler : public QRhiResource
+{
+public:
+ enum Filter {
+ None,
+ Nearest,
+ Linear
+ };
+
+ enum AddressMode {
+ Repeat,
+ ClampToEdge,
+ Border,
+ Mirror,
+ MirrorOnce
+ };
+
+ enum CompareOp {
+ Never,
+ Less,
+ Equal,
+ LessOrEqual,
+ Greater,
+ NotEqual,
+ GreaterOrEqual,
+ Always
+ };
+
+ QRhiResource::Type resourceType() const override;
+
+ Filter magFilter() const { return m_magFilter; }
+ void setMagFilter(Filter f) { m_magFilter = f; }
+
+ Filter minFilter() const { return m_minFilter; }
+ void setMinFilter(Filter f) { m_minFilter = f; }
+
+ Filter mipmapMode() const { return m_mipmapMode; }
+ void setMipmapMode(Filter f) { m_mipmapMode = f; }
+
+ AddressMode addressU() const { return m_addressU; }
+ void setAddressU(AddressMode mode) { m_addressU = mode; }
+
+ AddressMode addressV() const { return m_addressV; }
+ void setAddressV(AddressMode mode) { m_addressV = mode; }
+
+ AddressMode addressW() const { return m_addressW; }
+ void setAddressW(AddressMode mode) { m_addressW = mode; }
+
+ CompareOp textureCompareOp() const { return m_compareOp; }
+ void setTextureCompareOp(CompareOp op) { m_compareOp = op; }
+
+ virtual bool build() = 0;
+
+protected:
+ QRhiSampler(QRhiImplementation *rhi,
+ Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
+ AddressMode u_, AddressMode v_);
+ Filter m_magFilter;
+ Filter m_minFilter;
+ Filter m_mipmapMode;
+ AddressMode m_addressU;
+ AddressMode m_addressV;
+ AddressMode m_addressW;
+ CompareOp m_compareOp;
+};
+
+class Q_GUI_EXPORT QRhiRenderBuffer : public QRhiResource
+{
+public:
+ enum Type {
+ DepthStencil,
+ Color
+ };
+
+ enum Flag {
+ UsedWithSwapChainOnly = 1 << 0
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QRhiResource::Type resourceType() const override;
+
+ Type type() const { return m_type; }
+ void setType(Type t) { m_type = t; }
+
+ QSize pixelSize() const { return m_pixelSize; }
+ void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
+
+ int sampleCount() const { return m_sampleCount; }
+ void setSampleCount(int s) { m_sampleCount = s; }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags h) { m_flags = h; }
+
+ virtual bool build() = 0;
+
+ virtual QRhiTexture::Format backingFormat() const = 0;
+
+protected:
+ QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
+ int sampleCount_, Flags flags_);
+ Type m_type;
+ QSize m_pixelSize;
+ int m_sampleCount;
+ Flags m_flags;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiRenderBuffer::Flags)
+
+class Q_GUI_EXPORT QRhiRenderPassDescriptor : public QRhiResource
+{
+public:
+ QRhiResource::Type resourceType() const override;
+
+protected:
+ QRhiRenderPassDescriptor(QRhiImplementation *rhi);
+};
+
+class Q_GUI_EXPORT QRhiRenderTarget : public QRhiResource
+{
+public:
+ QRhiResource::Type resourceType() const override;
+
+ virtual QSize pixelSize() const = 0;
+ virtual float devicePixelRatio() const = 0;
+ virtual int sampleCount() const = 0;
+
+ QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
+ void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
+
+protected:
+ QRhiRenderTarget(QRhiImplementation *rhi);
+ QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
+};
+
+class Q_GUI_EXPORT QRhiTextureRenderTarget : public QRhiRenderTarget
+{
+public:
+ enum Flag {
+ PreserveColorContents = 1 << 0,
+ PreserveDepthStencilContents = 1 << 1
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QRhiResource::Type resourceType() const override;
+
+ QRhiTextureRenderTargetDescription description() const { return m_desc; }
+ void setDescription(const QRhiTextureRenderTargetDescription &desc) { m_desc = desc; }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0;
+
+ virtual bool build() = 0;
+
+protected:
+ QRhiTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc_, Flags flags_);
+ QRhiTextureRenderTargetDescription m_desc;
+ Flags m_flags;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTextureRenderTarget::Flags)
+
+class Q_GUI_EXPORT QRhiShaderResourceBindings : public QRhiResource
+{
+public:
+ QRhiResource::Type resourceType() const override;
+
+ QVector<QRhiShaderResourceBinding> bindings() const { return m_bindings; }
+ void setBindings(const QVector<QRhiShaderResourceBinding> &b) { m_bindings = b; }
+
+ bool isLayoutCompatible(const QRhiShaderResourceBindings *other) const;
+
+ virtual bool build() = 0;
+
+protected:
+ QRhiShaderResourceBindings(QRhiImplementation *rhi);
+ QVector<QRhiShaderResourceBinding> m_bindings;
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
+#endif
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
+#endif
+
+class Q_GUI_EXPORT QRhiGraphicsPipeline : public QRhiResource
+{
+public:
+ enum Flag {
+ UsesBlendConstants = 1 << 0,
+ UsesStencilRef = 1 << 1,
+ UsesScissor = 1 << 2
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ enum Topology {
+ Triangles,
+ TriangleStrip,
+ Lines,
+ LineStrip,
+ Points
+ };
+
+ enum CullMode {
+ None,
+ Front,
+ Back
+ };
+
+ enum FrontFace {
+ CCW,
+ CW
+ };
+
+ enum ColorMaskComponent {
+ R = 1 << 0,
+ G = 1 << 1,
+ B = 1 << 2,
+ A = 1 << 3
+ };
+ Q_DECLARE_FLAGS(ColorMask, ColorMaskComponent)
+
+ enum BlendFactor {
+ Zero,
+ One,
+ SrcColor,
+ OneMinusSrcColor,
+ DstColor,
+ OneMinusDstColor,
+ SrcAlpha,
+ OneMinusSrcAlpha,
+ DstAlpha,
+ OneMinusDstAlpha,
+ ConstantColor,
+ OneMinusConstantColor,
+ ConstantAlpha,
+ OneMinusConstantAlpha,
+ SrcAlphaSaturate,
+ Src1Color,
+ OneMinusSrc1Color,
+ Src1Alpha,
+ OneMinusSrc1Alpha
+ };
+
+ enum BlendOp {
+ Add,
+ Subtract,
+ ReverseSubtract,
+ Min,
+ Max
+ };
+
+ struct TargetBlend {
+ ColorMask colorWrite = ColorMask(0xF); // R | G | B | A
+ bool enable = false;
+ BlendFactor srcColor = One;
+ BlendFactor dstColor = OneMinusSrcAlpha;
+ BlendOp opColor = Add;
+ BlendFactor srcAlpha = One;
+ BlendFactor dstAlpha = OneMinusSrcAlpha;
+ BlendOp opAlpha = Add;
+ };
+
+ enum CompareOp {
+ Never,
+ Less,
+ Equal,
+ LessOrEqual,
+ Greater,
+ NotEqual,
+ GreaterOrEqual,
+ Always
+ };
+
+ enum StencilOp {
+ StencilZero,
+ Keep,
+ Replace,
+ IncrementAndClamp,
+ DecrementAndClamp,
+ Invert,
+ IncrementAndWrap,
+ DecrementAndWrap
+ };
+
+ struct StencilOpState {
+ StencilOp failOp = Keep;
+ StencilOp depthFailOp = Keep;
+ StencilOp passOp = Keep;
+ CompareOp compareOp = Always;
+ };
+
+ QRhiResource::Type resourceType() const override;
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ Topology topology() const { return m_topology; }
+ void setTopology(Topology t) { m_topology = t; }
+
+ CullMode cullMode() const { return m_cullMode; }
+ void setCullMode(CullMode mode) { m_cullMode = mode; }
+
+ FrontFace frontFace() const { return m_frontFace; }
+ void setFrontFace(FrontFace f) { m_frontFace = f; }
+
+ QVector<TargetBlend> targetBlends() const { return m_targetBlends; }
+ void setTargetBlends(const QVector<TargetBlend> &blends) { m_targetBlends = blends; }
+
+ bool hasDepthTest() const { return m_depthTest; }
+ void setDepthTest(bool enable) { m_depthTest = enable; }
+
+ bool hasDepthWrite() const { return m_depthWrite; }
+ void setDepthWrite(bool enable) { m_depthWrite = enable; }
+
+ CompareOp depthOp() const { return m_depthOp; }
+ void setDepthOp(CompareOp op) { m_depthOp = op; }
+
+ bool hasStencilTest() const { return m_stencilTest; }
+ void setStencilTest(bool enable) { m_stencilTest = enable; }
+
+ StencilOpState stencilFront() const { return m_stencilFront; }
+ void setStencilFront(const StencilOpState &state) { m_stencilFront = state; }
+
+ StencilOpState stencilBack() const { return m_stencilBack; }
+ void setStencilBack(const StencilOpState &state) { m_stencilBack = state; }
+
+ quint32 stencilReadMask() const { return m_stencilReadMask; }
+ void setStencilReadMask(quint32 mask) { m_stencilReadMask = mask; }
+
+ quint32 stencilWriteMask() const { return m_stencilWriteMask; }
+ void setStencilWriteMask(quint32 mask) { m_stencilWriteMask = mask; }
+
+ int sampleCount() const { return m_sampleCount; }
+ void setSampleCount(int s) { m_sampleCount = s; }
+
+ QVector<QRhiGraphicsShaderStage> shaderStages() const { return m_shaderStages; }
+ void setShaderStages(const QVector<QRhiGraphicsShaderStage> &stages) { m_shaderStages = stages; }
+
+ QRhiVertexInputLayout vertexInputLayout() const { return m_vertexInputLayout; }
+ void setVertexInputLayout(const QRhiVertexInputLayout &layout) { m_vertexInputLayout = layout; }
+
+ QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; }
+ void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; }
+
+ QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
+ void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
+
+ virtual bool build() = 0;
+
+protected:
+ QRhiGraphicsPipeline(QRhiImplementation *rhi);
+ Flags m_flags;
+ Topology m_topology = Triangles;
+ CullMode m_cullMode = None;
+ FrontFace m_frontFace = CCW;
+ QVector<TargetBlend> m_targetBlends;
+ bool m_depthTest = false;
+ bool m_depthWrite = false;
+ CompareOp m_depthOp = Less;
+ bool m_stencilTest = false;
+ StencilOpState m_stencilFront;
+ StencilOpState m_stencilBack;
+ quint32 m_stencilReadMask = 0xFF;
+ quint32 m_stencilWriteMask = 0xFF;
+ int m_sampleCount = 1;
+ QVector<QRhiGraphicsShaderStage> m_shaderStages;
+ QRhiVertexInputLayout m_vertexInputLayout;
+ QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
+ QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::Flags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::ColorMask)
+Q_DECLARE_TYPEINFO(QRhiGraphicsPipeline::TargetBlend, Q_MOVABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiSwapChain : public QRhiResource
+{
+public:
+ enum Flag {
+ SurfaceHasPreMulAlpha = 1 << 0,
+ SurfaceHasNonPreMulAlpha = 1 << 1,
+ sRGB = 1 << 2,
+ UsedAsTransferSource = 1 << 3,
+ NoVSync = 1 << 4,
+ MinimalBufferCount = 1 << 5
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QRhiResource::Type resourceType() const override;
+
+ QWindow *window() const { return m_window; }
+ void setWindow(QWindow *window) { m_window = window; }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ QRhiRenderBuffer *depthStencil() const { return m_depthStencil; }
+ void setDepthStencil(QRhiRenderBuffer *ds) { m_depthStencil = ds; }
+
+ int sampleCount() const { return m_sampleCount; }
+ void setSampleCount(int samples) { m_sampleCount = samples; }
+
+ QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
+ void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
+
+ QSize currentPixelSize() const { return m_currentPixelSize; }
+
+ virtual QRhiCommandBuffer *currentFrameCommandBuffer() = 0;
+ virtual QRhiRenderTarget *currentFrameRenderTarget() = 0;
+ virtual QSize surfacePixelSize() = 0;
+ virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0;
+ virtual bool buildOrResize() = 0;
+
+protected:
+ QRhiSwapChain(QRhiImplementation *rhi);
+ QWindow *m_window = nullptr;
+ Flags m_flags;
+ QRhiRenderBuffer *m_depthStencil = nullptr;
+ int m_sampleCount = 1;
+ QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
+ QSize m_currentPixelSize;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags)
+
+class Q_GUI_EXPORT QRhiCommandBuffer : public QRhiResource
+{
+public:
+ enum IndexFormat {
+ IndexUInt16,
+ IndexUInt32
+ };
+
+ QRhiResource::Type resourceType() const override;
+
+ void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates);
+
+ void beginPass(QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates = nullptr);
+ void endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
+
+ void setGraphicsPipeline(QRhiGraphicsPipeline *ps);
+ using DynamicOffset = QPair<int, quint32>; // binding, offset
+ void setShaderResources(QRhiShaderResourceBindings *srb = nullptr,
+ int dynamicOffsetCount = 0,
+ const DynamicOffset *dynamicOffsets = nullptr);
+ using VertexInput = QPair<QRhiBuffer *, quint32>; // buffer, offset
+ void setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
+ QRhiBuffer *indexBuf = nullptr, quint32 indexOffset = 0,
+ IndexFormat indexFormat = IndexUInt16);
+
+ void setViewport(const QRhiViewport &viewport);
+ void setScissor(const QRhiScissor &scissor);
+ void setBlendConstants(const QColor &c);
+ void setStencilRef(quint32 refValue);
+
+ void draw(quint32 vertexCount,
+ quint32 instanceCount = 1,
+ quint32 firstVertex = 0,
+ quint32 firstInstance = 0);
+
+ void drawIndexed(quint32 indexCount,
+ quint32 instanceCount = 1,
+ quint32 firstIndex = 0,
+ qint32 vertexOffset = 0,
+ quint32 firstInstance = 0);
+
+ void debugMarkBegin(const QByteArray &name);
+ void debugMarkEnd();
+ void debugMarkMsg(const QByteArray &msg);
+
+ const QRhiNativeHandles *nativeHandles();
+ void beginExternal();
+ void endExternal();
+
+protected:
+ QRhiCommandBuffer(QRhiImplementation *rhi);
+};
+
+struct Q_GUI_EXPORT QRhiReadbackResult
+{
+ std::function<void()> completed = nullptr;
+ QRhiTexture::Format format;
+ QSize pixelSize;
+ QByteArray data;
+}; // non-movable due to the std::function
+
+class Q_GUI_EXPORT QRhiResourceUpdateBatch
+{
+public:
+ ~QRhiResourceUpdateBatch();
+
+ void release();
+
+ void merge(QRhiResourceUpdateBatch *other);
+
+ void updateDynamicBuffer(QRhiBuffer *buf, int offset, int size, const void *data);
+ void uploadStaticBuffer(QRhiBuffer *buf, int offset, int size, const void *data);
+ void uploadStaticBuffer(QRhiBuffer *buf, const void *data);
+ void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc);
+ void uploadTexture(QRhiTexture *tex, const QImage &image);
+ void copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc = QRhiTextureCopyDescription());
+ void readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result);
+ void generateMips(QRhiTexture *tex, int layer = 0);
+
+private:
+ QRhiResourceUpdateBatch(QRhiImplementation *rhi);
+ Q_DISABLE_COPY(QRhiResourceUpdateBatch)
+ QRhiResourceUpdateBatchPrivate *d;
+ friend class QRhiResourceUpdateBatchPrivate;
+ friend class QRhi;
+};
+
+struct Q_GUI_EXPORT QRhiInitParams
+{
+};
+
+class Q_GUI_EXPORT QRhi
+{
+public:
+ enum Implementation {
+ Null,
+ Vulkan,
+ OpenGLES2,
+ D3D11,
+ Metal
+ };
+
+ enum Flag {
+ EnableProfiling = 1 << 0,
+ EnableDebugMarkers = 1 << 1
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ enum FrameOpResult {
+ FrameOpSuccess = 0,
+ FrameOpError,
+ FrameOpSwapChainOutOfDate,
+ FrameOpDeviceLost
+ };
+
+ enum Feature {
+ MultisampleTexture = 1,
+ MultisampleRenderBuffer,
+ DebugMarkers,
+ Timestamps,
+ Instancing,
+ CustomInstanceStepRate,
+ PrimitiveRestart,
+ NonDynamicUniformBuffers,
+ NonFourAlignedEffectiveIndexBufferOffset,
+ NPOTTextureRepeat,
+ RedOrAlpha8IsRed,
+ ElementIndexUint
+ };
+
+ enum BeginFrameFlag {
+ };
+ Q_DECLARE_FLAGS(BeginFrameFlags, BeginFrameFlag)
+
+ enum EndFrameFlag {
+ SkipPresent = 1 << 0
+ };
+ Q_DECLARE_FLAGS(EndFrameFlags, EndFrameFlag)
+
+ enum ResourceLimit {
+ TextureSizeMin = 1,
+ TextureSizeMax,
+ MaxColorAttachments,
+ FramesInFlight
+ };
+
+ ~QRhi();
+
+ static QRhi *create(Implementation impl,
+ QRhiInitParams *params,
+ Flags flags = Flags(),
+ QRhiNativeHandles *importDevice = nullptr);
+
+ Implementation backend() const;
+ QThread *thread() const;
+
+ using CleanupCallback = std::function<void(QRhi *)>;
+ void addCleanupCallback(const CleanupCallback &callback);
+ void runCleanup();
+
+ QRhiGraphicsPipeline *newGraphicsPipeline();
+ QRhiShaderResourceBindings *newShaderResourceBindings();
+
+ QRhiBuffer *newBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ int size);
+
+ QRhiRenderBuffer *newRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount = 1,
+ QRhiRenderBuffer::Flags flags = QRhiRenderBuffer::Flags());
+
+ QRhiTexture *newTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int sampleCount = 1,
+ QRhiTexture::Flags flags = QRhiTexture::Flags());
+
+ QRhiSampler *newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v);
+
+ QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags = QRhiTextureRenderTarget::Flags());
+
+ QRhiSwapChain *newSwapChain();
+ FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags = BeginFrameFlags());
+ FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags = EndFrameFlags());
+ bool isRecordingFrame() const;
+ int currentFrameSlot() const;
+
+ FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb);
+ FrameOpResult endOffscreenFrame();
+
+ QRhi::FrameOpResult finish();
+
+ QRhiResourceUpdateBatch *nextResourceUpdateBatch();
+
+ QVector<int> supportedSampleCounts() const;
+
+ int ubufAlignment() const;
+ int ubufAligned(int v) const;
+
+ int mipLevelsForSize(const QSize &size) const;
+ QSize sizeForMipLevel(int mipLevel, const QSize &baseLevelSize) const;
+
+ bool isYUpInFramebuffer() const;
+ bool isYUpInNDC() const;
+ bool isClipDepthZeroToOne() const;
+
+ QMatrix4x4 clipSpaceCorrMatrix() const;
+
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = QRhiTexture::Flags()) const;
+ bool isFeatureSupported(QRhi::Feature feature) const;
+ int resourceLimit(ResourceLimit limit) const;
+
+ const QRhiNativeHandles *nativeHandles();
+
+ QRhiProfiler *profiler();
+
+ static const int MAX_LAYERS = 6; // cubemaps only
+ static const int MAX_LEVELS = 16; // a width and/or height of 65536 should be enough for everyone
+
+protected:
+ QRhi();
+
+private:
+ Q_DISABLE_COPY(QRhi)
+ QRhiImplementation *d = nullptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::Flags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::BeginFrameFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::EndFrameFlags)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
new file mode 100644
index 0000000000..7c110431fb
--- /dev/null
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -0,0 +1,544 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHI_P_H
+#define QRHI_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrhi_p.h"
+#include "qrhiprofiler_p_p.h"
+#include <QBitArray>
+#include <QAtomicInt>
+#include <QAtomicInteger>
+
+QT_BEGIN_NAMESPACE
+
+#define QRHI_RES(t, x) static_cast<t *>(x)
+#define QRHI_RES_RHI(t) t *rhiD = static_cast<t *>(m_rhi)
+#define QRHI_PROF QRhiProfilerPrivate *rhiP = m_rhi->profilerPrivateOrNull()
+#define QRHI_PROF_F(f) for (bool qrhip_enabled = rhiP != nullptr; qrhip_enabled; qrhip_enabled = false) rhiP->f
+
+class QRhiImplementation
+{
+public:
+ virtual ~QRhiImplementation();
+
+ virtual bool create(QRhi::Flags flags) = 0;
+ virtual void destroy() = 0;
+
+ virtual QRhiGraphicsPipeline *createGraphicsPipeline() = 0;
+ virtual QRhiShaderResourceBindings *createShaderResourceBindings() = 0;
+ virtual QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ int size) = 0;
+ virtual QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags) = 0;
+ virtual QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiTexture::Flags flags) = 0;
+ virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) = 0;
+
+ virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) = 0;
+
+ virtual QRhiSwapChain *createSwapChain() = 0;
+ virtual QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) = 0;
+ virtual QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) = 0;
+ virtual QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) = 0;
+ virtual QRhi::FrameOpResult endOffscreenFrame() = 0;
+ virtual QRhi::FrameOpResult finish() = 0;
+
+ virtual void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
+
+ virtual void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates) = 0;
+ virtual void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
+
+ virtual void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) = 0;
+
+ virtual void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) = 0;
+
+ virtual void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) = 0;
+
+ virtual void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) = 0;
+ virtual void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) = 0;
+ virtual void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) = 0;
+ virtual void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) = 0;
+
+ virtual void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) = 0;
+ virtual void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) = 0;
+
+ virtual void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) = 0;
+ virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0;
+ virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0;
+
+ virtual const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) = 0;
+ virtual void beginExternal(QRhiCommandBuffer *cb) = 0;
+ virtual void endExternal(QRhiCommandBuffer *cb) = 0;
+
+ virtual QVector<int> supportedSampleCounts() const = 0;
+ virtual int ubufAlignment() const = 0;
+ virtual bool isYUpInFramebuffer() const = 0;
+ virtual bool isYUpInNDC() const = 0;
+ virtual bool isClipDepthZeroToOne() const = 0;
+ virtual QMatrix4x4 clipSpaceCorrMatrix() const = 0;
+ virtual bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const = 0;
+ virtual bool isFeatureSupported(QRhi::Feature feature) const = 0;
+ virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
+ virtual const QRhiNativeHandles *nativeHandles() = 0;
+ virtual void sendVMemStatsToProfiler() = 0;
+
+ bool isCompressedFormat(QRhiTexture::Format format) const;
+ void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
+ quint32 *bpl, quint32 *byteSize,
+ QSize *blockDim) const;
+ void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
+ quint32 *bpl, quint32 *byteSize) const;
+ quint32 approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize,
+ int mipCount, int layerCount);
+
+ QRhiProfilerPrivate *profilerPrivateOrNull()
+ {
+ // return null when QRhi::EnableProfiling was not set
+ QRhiProfilerPrivate *p = QRhiProfilerPrivate::get(&profiler);
+ return p->rhiDWhenEnabled ? p : nullptr;
+ }
+
+ // only really care about resources that own native graphics resources underneath
+ void registerResource(QRhiResource *res)
+ {
+ resources.insert(res);
+ }
+
+ void unregisterResource(QRhiResource *res)
+ {
+ resources.remove(res);
+ }
+
+ QSet<QRhiResource *> activeResources() const
+ {
+ return resources;
+ }
+
+ void addReleaseAndDestroyLater(QRhiResource *res)
+ {
+ if (inFrame)
+ pendingReleaseAndDestroyResources.insert(res);
+ else
+ delete res;
+ }
+
+ void addCleanupCallback(const QRhi::CleanupCallback &callback)
+ {
+ cleanupCallbacks.append(callback);
+ }
+
+ QRhi *q;
+
+protected:
+ bool debugMarkers = false;
+ int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
+
+private:
+ QRhi::Implementation implType;
+ QThread *implThread;
+ QRhiProfiler profiler;
+ QVector<QRhiResourceUpdateBatch *> resUpdPool;
+ QBitArray resUpdPoolMap;
+ QSet<QRhiResource *> resources;
+ QSet<QRhiResource *> pendingReleaseAndDestroyResources;
+ QVector<QRhi::CleanupCallback> cleanupCallbacks;
+ bool inFrame = false;
+
+ friend class QRhi;
+ friend class QRhiResourceUpdateBatchPrivate;
+};
+
+template<typename T, size_t N>
+bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, N> &r,
+ T *x, T *y, T *w, T *h)
+{
+ // x,y are bottom-left in QRhiScissor and QRhiViewport but top-left in
+ // Vulkan/Metal/D3D. We also need proper clamping since some
+ // validation/debug layers are allergic to out of bounds scissor or
+ // viewport rects.
+
+ const T outputWidth = outputSize.width();
+ const T outputHeight = outputSize.height();
+ const T inputWidth = r[2];
+ const T inputHeight = r[3];
+
+ *x = qMax<T>(0, r[0]);
+ *y = qMax<T>(0, outputHeight - (r[1] + inputHeight));
+ *w = inputWidth;
+ *h = inputHeight;
+
+ if (*x >= outputWidth || *y >= outputHeight)
+ return false;
+
+ if (*x + *w > outputWidth)
+ *w = outputWidth - *x;
+ if (*y + *h > outputHeight)
+ *h = outputHeight - *y;
+
+ return true;
+}
+
+class QRhiResourceUpdateBatchPrivate
+{
+public:
+ struct DynamicBufferUpdate {
+ DynamicBufferUpdate() { }
+ DynamicBufferUpdate(QRhiBuffer *buf_, int offset_, int size_, const void *data_)
+ : buf(buf_), offset(offset_), data(reinterpret_cast<const char *>(data_), size_)
+ { }
+
+ QRhiBuffer *buf = nullptr;
+ int offset = 0;
+ QByteArray data;
+ };
+
+ struct StaticBufferUpload {
+ StaticBufferUpload() { }
+ StaticBufferUpload(QRhiBuffer *buf_, int offset_, int size_, const void *data_)
+ : buf(buf_), offset(offset_), data(reinterpret_cast<const char *>(data_), size_ ? size_ : buf_->size())
+ { }
+
+ QRhiBuffer *buf = nullptr;
+ int offset = 0;
+ QByteArray data;
+ };
+
+ struct TextureOp {
+ enum Type {
+ Upload,
+ Copy,
+ Read,
+ MipGen
+ };
+ Type type;
+ struct SUpload {
+ QRhiTexture *tex = nullptr;
+ // Specifying multiple uploads for a subresource must be supported.
+ // In the backend this can then end up, where applicable, as a
+ // single, batched copy operation with only one set of barriers.
+ // This helps when doing for example glyph cache fills.
+ QVector<QRhiTextureSubresourceUploadDescription> subresDesc[QRhi::MAX_LAYERS][QRhi::MAX_LEVELS];
+ } upload;
+ struct SCopy {
+ QRhiTexture *dst = nullptr;
+ QRhiTexture *src = nullptr;
+ QRhiTextureCopyDescription desc;
+ } copy;
+ struct SRead {
+ QRhiReadbackDescription rb;
+ QRhiReadbackResult *result;
+ } read;
+ struct SMipGen {
+ QRhiTexture *tex = nullptr;
+ int layer = 0;
+ } mipgen;
+
+ static TextureOp textureUpload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
+ {
+ TextureOp op;
+ op.type = Upload;
+ op.upload.tex = tex;
+ const QVector<QRhiTextureUploadEntry> &entries(desc.entries());
+ for (const QRhiTextureUploadEntry &entry : entries)
+ op.upload.subresDesc[entry.layer()][entry.level()].append(entry.description());
+ return op;
+ }
+
+ static TextureOp textureCopy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
+ {
+ TextureOp op;
+ op.type = Copy;
+ op.copy.dst = dst;
+ op.copy.src = src;
+ op.copy.desc = desc;
+ return op;
+ }
+
+ static TextureOp textureRead(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
+ {
+ TextureOp op;
+ op.type = Read;
+ op.read.rb = rb;
+ op.read.result = result;
+ return op;
+ }
+
+ static TextureOp textureMipGen(QRhiTexture *tex, int layer)
+ {
+ TextureOp op;
+ op.type = MipGen;
+ op.mipgen.tex = tex;
+ op.mipgen.layer = layer;
+ return op;
+ }
+ };
+
+ QVector<DynamicBufferUpdate> dynamicBufferUpdates;
+ QVector<StaticBufferUpload> staticBufferUploads;
+ QVector<TextureOp> textureOps;
+
+ QRhiResourceUpdateBatch *q = nullptr;
+ QRhiImplementation *rhi = nullptr;
+ int poolIndex = -1;
+
+ void free();
+ void merge(QRhiResourceUpdateBatchPrivate *other);
+
+ static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
+};
+
+Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::StaticBufferUpload, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::TextureOp, Q_MOVABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiShaderResourceBindingPrivate
+{
+public:
+ QRhiShaderResourceBindingPrivate()
+ : ref(1)
+ {
+ }
+
+ QRhiShaderResourceBindingPrivate(const QRhiShaderResourceBindingPrivate *other)
+ : ref(1),
+ binding(other->binding),
+ stage(other->stage),
+ type(other->type),
+ u(other->u)
+ {
+ }
+
+ static QRhiShaderResourceBindingPrivate *get(QRhiShaderResourceBinding *s) { return s->d; }
+ static const QRhiShaderResourceBindingPrivate *get(const QRhiShaderResourceBinding *s) { return s->d; }
+
+ QAtomicInt ref;
+ int binding;
+ QRhiShaderResourceBinding::StageFlags stage;
+ QRhiShaderResourceBinding::Type type;
+ struct UniformBufferData {
+ QRhiBuffer *buf;
+ int offset;
+ int maybeSize;
+ bool hasDynamicOffset;
+ };
+ struct SampledTextureData {
+ QRhiTexture *tex;
+ QRhiSampler *sampler;
+ };
+ union {
+ UniformBufferData ubuf;
+ SampledTextureData stex;
+ } u;
+};
+
+template<typename T>
+struct QRhiBatchedBindings
+{
+ void feed(int binding, T resource) { // binding must be strictly increasing
+ if (curBinding == -1 || binding > curBinding + 1) {
+ finish();
+ curBatch.startBinding = binding;
+ curBatch.resources.clear();
+ curBatch.resources.append(resource);
+ } else {
+ Q_ASSERT(binding == curBinding + 1);
+ curBatch.resources.append(resource);
+ }
+ curBinding = binding;
+ }
+
+ void finish() {
+ if (!curBatch.resources.isEmpty())
+ batches.append(curBatch);
+ }
+
+ void clear() {
+ batches.clear();
+ curBatch.resources.clear();
+ curBinding = -1;
+ }
+
+ struct Batch {
+ uint startBinding;
+ QVarLengthArray<T, 4> resources;
+
+ bool operator==(const Batch &other) const
+ {
+ return startBinding == other.startBinding && resources == other.resources;
+ }
+
+ bool operator!=(const Batch &other) const
+ {
+ return !operator==(other);
+ }
+ };
+
+ QVarLengthArray<Batch, 4> batches; // sorted by startBinding
+
+ bool operator==(const QRhiBatchedBindings<T> &other) const
+ {
+ return batches == other.batches;
+ }
+
+ bool operator!=(const QRhiBatchedBindings<T> &other) const
+ {
+ return !operator==(other);
+ }
+
+private:
+ Batch curBatch;
+ int curBinding = -1;
+};
+
+class QRhiGlobalObjectIdGenerator
+{
+public:
+#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+ using Type = quint64;
+#else
+ using Type = quint32;
+#endif
+ static Type newId();
+
+private:
+ QAtomicInteger<Type> counter;
+};
+
+class QRhiPassResourceTracker
+{
+public:
+ bool isEmpty() const;
+ void reset();
+
+ struct UsageState {
+ int layout;
+ int access;
+ int stage;
+ };
+
+ enum BufferStage {
+ BufVertexInputStage,
+ BufVertexStage,
+ BufFragmentStage
+ };
+
+ enum BufferAccess {
+ BufVertexInput,
+ BufIndexRead,
+ BufUniformRead
+ };
+
+ void registerBufferOnce(QRhiBuffer *buf, int slot, BufferAccess access, BufferStage stage,
+ const UsageState &stateAtPassBegin);
+
+ enum TextureStage {
+ TexVertexStage,
+ TexFragmentStage,
+ TexColorOutputStage,
+ TexDepthOutputStage
+ };
+
+ enum TextureAccess {
+ TexSample,
+ TexColorOutput,
+ TexDepthOutput
+ };
+
+ void registerTextureOnce(QRhiTexture *tex, TextureAccess access, TextureStage stage,
+ const UsageState &stateAtPassBegin);
+
+ struct Buffer {
+ QRhiBuffer *buf;
+ int slot;
+ BufferAccess access;
+ BufferStage stage;
+ UsageState stateAtPassBegin;
+ };
+ const QVector<Buffer> *buffers() const { return &m_buffers; }
+
+ struct Texture {
+ QRhiTexture *tex;
+ TextureAccess access;
+ TextureStage stage;
+ UsageState stateAtPassBegin;
+ };
+ const QVector<Texture> *textures() const { return &m_textures; }
+
+private:
+ QVector<Buffer> m_buffers;
+ QVector<Texture> m_textures;
+};
+
+Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Texture, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
new file mode 100644
index 0000000000..07e67d95d9
--- /dev/null
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -0,0 +1,3388 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrhid3d11_p_p.h"
+#include "qshader_p.h"
+#include <QWindow>
+#include <QOperatingSystemVersion>
+#include <qmath.h>
+
+#include <d3dcompiler.h>
+#include <comdef.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Direct3D 11 backend. Provides a double-buffered flip model (FLIP_DISCARD)
+ swapchain. Textures and "static" buffers are USAGE_DEFAULT, leaving it to
+ UpdateSubResource to upload the data in any way it sees fit. "Dynamic"
+ buffers are USAGE_DYNAMIC and updating is done by mapping with WRITE_DISCARD.
+ (so here QRhiBuffer keeps a copy of the buffer contents and all of it is
+ memcpy'd every time, leaving the rest (juggling with the memory area Map
+ returns) to the driver).
+*/
+
+/*!
+ \class QRhiD3D11InitParams
+ \inmodule QtRhi
+ \brief Direct3D 11 specific initialization parameters.
+
+ A D3D11-based QRhi needs no special parameters for initialization. If
+ desired, enableDebugLayer can be set to \c true to enable the Direct3D
+ debug layer. This can be useful during development, but should be avoided
+ in production builds.
+
+ \badcode
+ QRhiD3D11InitParams params;
+ params.enableDebugLayer = true;
+ rhi = QRhi::create(QRhi::D3D11, &params);
+ \endcode
+
+ \note QRhiSwapChain should only be used in combination with QWindow
+ instances that have their surface type set to QSurface::OpenGLSurface.
+ There are currently no Direct3D specifics in the Windows platform support
+ of Qt and therefore there is no separate QSurface type available.
+
+ \section2 Working with existing Direct3D 11 devices
+
+ When interoperating with another graphics engine, it may be necessary to
+ get a QRhi instance that uses the same Direct3D device. This can be
+ achieved by passing a pointer to a QRhiD3D11NativeHandles to
+ QRhi::create(). Both the device and the device context must be set to a
+ non-null value then.
+
+ The QRhi does not take ownership of any of the external objects.
+
+ \note QRhi works with immediate contexts only. Deferred contexts are not
+ used in any way.
+
+ \note Regardless of using an imported or a QRhi-created device context, the
+ \c ID3D11DeviceContext1 interface (Direct3D 11.1) must be supported.
+ Initialization will fail otherwise.
+ */
+
+/*!
+ \class QRhiD3D11NativeHandles
+ \inmodule QtRhi
+ \brief Holds the D3D device and device context used by the QRhi.
+
+ \note The class uses \c{void *} as the type since including the COM-based
+ \c{d3d11.h} headers is not acceptable here. The actual types are
+ \c{ID3D11Device *} and \c{ID3D11DeviceContext *}.
+ */
+
+/*!
+ \class QRhiD3D11TextureNativeHandles
+ \inmodule QtRhi
+ \brief Holds the D3D texture object that is backing a QRhiTexture instance.
+
+ \note The class uses \c{void *} as the type since including the COM-based
+ \c{d3d11.h} headers is not acceptable here. The actual type is
+ \c{ID3D11Texture2D *}.
+ */
+
+QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice)
+ : ofr(this)
+{
+ debugLayer = params->enableDebugLayer;
+ importedDevice = importDevice != nullptr;
+ if (importedDevice) {
+ dev = reinterpret_cast<ID3D11Device *>(importDevice->dev);
+ if (dev) {
+ ID3D11DeviceContext *ctx = reinterpret_cast<ID3D11DeviceContext *>(importDevice->context);
+ if (SUCCEEDED(ctx->QueryInterface(IID_ID3D11DeviceContext1, reinterpret_cast<void **>(&context)))) {
+ // get rid of the ref added by QueryInterface
+ ctx->Release();
+ } else {
+ qWarning("ID3D11DeviceContext1 not supported by context, cannot import");
+ importedDevice = false;
+ }
+ } else {
+ qWarning("No ID3D11Device given, cannot import");
+ importedDevice = false;
+ }
+ }
+}
+
+static QString comErrorMessage(HRESULT hr)
+{
+#ifndef Q_OS_WINRT
+ const _com_error comError(hr);
+#else
+ const _com_error comError(hr, nullptr);
+#endif
+ QString result = QLatin1String("Error 0x") + QString::number(ulong(hr), 16);
+ if (const wchar_t *msg = comError.ErrorMessage())
+ result += QLatin1String(": ") + QString::fromWCharArray(msg);
+ return result;
+}
+
+static inline uint aligned(uint v, uint byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+bool QRhiD3D11::create(QRhi::Flags flags)
+{
+ Q_UNUSED(flags);
+
+ uint devFlags = 0;
+ if (debugLayer)
+ devFlags |= D3D11_CREATE_DEVICE_DEBUG;
+
+ HRESULT hr;
+#if !defined(Q_CC_MINGW)
+ hasDxgi2 = QOperatingSystemVersion::current() > QOperatingSystemVersion::Windows7;
+ if (hasDxgi2)
+ hr = CreateDXGIFactory2(0, IID_IDXGIFactory2, reinterpret_cast<void **>(&dxgiFactory));
+ else
+#endif
+ hr = CreateDXGIFactory1(IID_IDXGIFactory1, reinterpret_cast<void **>(&dxgiFactory));
+
+ if (FAILED(hr)) {
+ qWarning("Failed to create DXGI factory: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+
+ if (!importedDevice) {
+ IDXGIAdapter1 *adapterToUse = nullptr;
+ IDXGIAdapter1 *adapter;
+ int requestedAdapterIndex = -1;
+ if (qEnvironmentVariableIsSet("QT_D3D_ADAPTER_INDEX"))
+ requestedAdapterIndex = qEnvironmentVariableIntValue("QT_D3D_ADAPTER_INDEX");
+ for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
+ DXGI_ADAPTER_DESC1 desc;
+ adapter->GetDesc1(&desc);
+ const QString name = QString::fromUtf16((char16_t *) desc.Description);
+ qDebug("Adapter %d: '%s' (flags 0x%x)", adapterIndex, qPrintable(name), desc.Flags);
+ if (!adapterToUse && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
+ adapterToUse = adapter;
+ qDebug(" using this adapter");
+ } else {
+ adapter->Release();
+ }
+ }
+ if (!adapterToUse) {
+ qWarning("No adapter");
+ return false;
+ }
+
+ ID3D11DeviceContext *ctx = nullptr;
+ HRESULT hr = D3D11CreateDevice(adapterToUse, D3D_DRIVER_TYPE_UNKNOWN, nullptr, devFlags,
+ nullptr, 0, D3D11_SDK_VERSION,
+ &dev, &featureLevel, &ctx);
+ adapterToUse->Release();
+ if (FAILED(hr)) {
+ qWarning("Failed to create D3D11 device and context: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ if (SUCCEEDED(ctx->QueryInterface(IID_ID3D11DeviceContext1, reinterpret_cast<void **>(&context)))) {
+ ctx->Release();
+ } else {
+ qWarning("ID3D11DeviceContext1 not supported");
+ return false;
+ }
+ } else {
+ Q_ASSERT(dev && context);
+ featureLevel = dev->GetFeatureLevel();
+ }
+
+ if (FAILED(context->QueryInterface(IID_ID3DUserDefinedAnnotation, reinterpret_cast<void **>(&annotations))))
+ annotations = nullptr;
+
+ nativeHandlesStruct.dev = dev;
+ nativeHandlesStruct.context = context;
+
+ return true;
+}
+
+void QRhiD3D11::destroy()
+{
+ finishActiveReadbacks();
+
+ if (annotations) {
+ annotations->Release();
+ annotations = nullptr;
+ }
+
+ if (!importedDevice) {
+ if (context) {
+ context->Release();
+ context = nullptr;
+ }
+ if (dev) {
+ dev->Release();
+ dev = nullptr;
+ }
+ }
+
+ if (dxgiFactory) {
+ dxgiFactory->Release();
+ dxgiFactory = nullptr;
+ }
+}
+
+void QRhiD3D11::reportLiveObjects(ID3D11Device *device)
+{
+ // this works only when params.enableDebugLayer was true
+ ID3D11Debug *debug;
+ if (SUCCEEDED(device->QueryInterface(IID_ID3D11Debug, reinterpret_cast<void **>(&debug)))) {
+ debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
+ debug->Release();
+ }
+}
+
+QVector<int> QRhiD3D11::supportedSampleCounts() const
+{
+ return { 1, 2, 4, 8 };
+}
+
+DXGI_SAMPLE_DESC QRhiD3D11::effectiveSampleCount(int sampleCount) const
+{
+ DXGI_SAMPLE_DESC desc;
+ desc.Count = 1;
+ desc.Quality = 0;
+
+ // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
+ int s = qBound(1, sampleCount, 64);
+
+ if (!supportedSampleCounts().contains(s)) {
+ qWarning("Attempted to set unsupported sample count %d", sampleCount);
+ return desc;
+ }
+
+ desc.Count = s;
+ if (s > 1)
+ desc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
+ else
+ desc.Quality = 0;
+
+ return desc;
+}
+
+QRhiSwapChain *QRhiD3D11::createSwapChain()
+{
+ return new QD3D11SwapChain(this);
+}
+
+QRhiBuffer *QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+{
+ return new QD3D11Buffer(this, type, usage, size);
+}
+
+int QRhiD3D11::ubufAlignment() const
+{
+ return 256;
+}
+
+bool QRhiD3D11::isYUpInFramebuffer() const
+{
+ return false;
+}
+
+bool QRhiD3D11::isYUpInNDC() const
+{
+ return true;
+}
+
+bool QRhiD3D11::isClipDepthZeroToOne() const
+{
+ return true;
+}
+
+QMatrix4x4 QRhiD3D11::clipSpaceCorrMatrix() const
+{
+ // Like with Vulkan, but Y is already good.
+
+ static QMatrix4x4 m;
+ if (m.isIdentity()) {
+ // NB the ctor takes row-major
+ m = QMatrix4x4(1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 0.5f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ return m;
+}
+
+bool QRhiD3D11::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
+{
+ Q_UNUSED(flags);
+
+ if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
+ return false;
+
+ return true;
+}
+
+bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
+{
+ switch (feature) {
+ case QRhi::MultisampleTexture:
+ return true;
+ case QRhi::MultisampleRenderBuffer:
+ return true;
+ case QRhi::DebugMarkers:
+ return annotations != nullptr;
+ case QRhi::Timestamps:
+ return true;
+ case QRhi::Instancing:
+ return true;
+ case QRhi::CustomInstanceStepRate:
+ return true;
+ case QRhi::PrimitiveRestart:
+ return true;
+ case QRhi::NonDynamicUniformBuffers:
+ return false; // because UpdateSubresource cannot deal with this
+ case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
+ return true;
+ case QRhi::NPOTTextureRepeat:
+ return true;
+ case QRhi::RedOrAlpha8IsRed:
+ return true;
+ case QRhi::ElementIndexUint:
+ return true;
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
+}
+
+int QRhiD3D11::resourceLimit(QRhi::ResourceLimit limit) const
+{
+ switch (limit) {
+ case QRhi::TextureSizeMin:
+ return 1;
+ case QRhi::TextureSizeMax:
+ return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ case QRhi::MaxColorAttachments:
+ return 8;
+ case QRhi::FramesInFlight:
+ return 2; // dummy
+ default:
+ Q_UNREACHABLE();
+ return 0;
+ }
+}
+
+const QRhiNativeHandles *QRhiD3D11::nativeHandles()
+{
+ return &nativeHandlesStruct;
+}
+
+void QRhiD3D11::sendVMemStatsToProfiler()
+{
+ // nothing to do here
+}
+
+QRhiRenderBuffer *QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags)
+{
+ return new QD3D11RenderBuffer(this, type, pixelSize, sampleCount, flags);
+}
+
+QRhiTexture *QRhiD3D11::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
+ int sampleCount, QRhiTexture::Flags flags)
+{
+ return new QD3D11Texture(this, format, pixelSize, sampleCount, flags);
+}
+
+QRhiSampler *QRhiD3D11::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+{
+ return new QD3D11Sampler(this, magFilter, minFilter, mipmapMode, u, v);
+}
+
+QRhiTextureRenderTarget *QRhiD3D11::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags)
+{
+ return new QD3D11TextureRenderTarget(this, desc, flags);
+}
+
+QRhiGraphicsPipeline *QRhiD3D11::createGraphicsPipeline()
+{
+ return new QD3D11GraphicsPipeline(this);
+}
+
+QRhiShaderResourceBindings *QRhiD3D11::createShaderResourceBindings()
+{
+ return new QD3D11ShaderResourceBindings(this);
+}
+
+void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps)
+{
+ Q_ASSERT(inPass);
+
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ QD3D11GraphicsPipeline *psD = QRHI_RES(QD3D11GraphicsPipeline, ps);
+ const bool pipelineChanged = cbD->currentPipeline != ps || cbD->currentPipelineGeneration != psD->generation;
+
+ if (pipelineChanged) {
+ cbD->currentPipeline = ps;
+ cbD->currentPipelineGeneration = psD->generation;
+
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::BindGraphicsPipeline;
+ cmd.args.bindGraphicsPipeline.ps = psD;
+ cbD->commands.append(cmd);
+ }
+}
+
+void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
+{
+ Q_ASSERT(inPass);
+
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ Q_ASSERT(cbD->currentPipeline);
+
+ if (!srb)
+ srb = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline)->m_shaderResourceBindings;
+
+ QD3D11ShaderResourceBindings *srbD = QRHI_RES(QD3D11ShaderResourceBindings, srb);
+
+ bool hasDynamicOffsetInSrb = false;
+ bool srbUpdate = false;
+ for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->sortedBindings[i]);
+ QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ {
+ QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf);
+ if (bufD->m_type == QRhiBuffer::Dynamic)
+ executeBufferHostWritesForCurrentFrame(bufD);
+
+ if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
+ srbUpdate = true;
+ bd.ubuf.id = bufD->m_id;
+ bd.ubuf.generation = bufD->generation;
+ }
+
+ if (b->u.ubuf.hasDynamicOffset)
+ hasDynamicOffsetInSrb = true;
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ {
+ QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex);
+ QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler);
+ if (texD->generation != bd.stex.texGeneration
+ || texD->m_id != bd.stex.texId
+ || samplerD->generation != bd.stex.samplerGeneration
+ || samplerD->m_id != bd.stex.samplerId)
+ {
+ srbUpdate = true;
+ bd.stex.texId = texD->m_id;
+ bd.stex.texGeneration = texD->generation;
+ bd.stex.samplerId = samplerD->m_id;
+ bd.stex.samplerGeneration = samplerD->generation;
+ }
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+
+ if (srbUpdate)
+ updateShaderResourceBindings(srbD);
+
+ const bool srbChanged = cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation;
+
+ if (srbChanged || srbUpdate || hasDynamicOffsetInSrb) {
+ cbD->currentSrb = srb;
+ cbD->currentSrbGeneration = srbD->generation;
+
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::BindShaderResources;
+ cmd.args.bindShaderResources.srb = srbD;
+ // dynamic offsets have to be applied at the time of executing the bind
+ // operations, not here
+ cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbUpdate && hasDynamicOffsetInSrb;
+ cmd.args.bindShaderResources.dynamicOffsetCount = 0;
+ if (hasDynamicOffsetInSrb) {
+ if (dynamicOffsetCount < QD3D11CommandBuffer::Command::MAX_UBUF_BINDINGS) {
+ cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
+ uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
+ for (int i = 0; i < dynamicOffsetCount; ++i) {
+ const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
+ const uint binding = dynOfs.first;
+ Q_ASSERT(aligned(dynOfs.second, 256) == dynOfs.second);
+ const uint offsetInConstants = dynOfs.second / 16;
+ *p++ = binding;
+ *p++ = offsetInConstants;
+ }
+ } else {
+ qWarning("Too many dynamic offsets (%d, max is %d)",
+ dynamicOffsetCount, QD3D11CommandBuffer::Command::MAX_UBUF_BINDINGS);
+ }
+ }
+
+ cbD->commands.append(cmd);
+ }
+}
+
+void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
+{
+ Q_ASSERT(inPass);
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+
+ bool needsBindVBuf = false;
+ for (int i = 0; i < bindingCount; ++i) {
+ const int inputSlot = startBinding + i;
+ QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first);
+ Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
+ if (bufD->m_type == QRhiBuffer::Dynamic)
+ executeBufferHostWritesForCurrentFrame(bufD);
+
+ if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
+ || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
+ {
+ needsBindVBuf = true;
+ cbD->currentVertexBuffers[inputSlot] = bufD->buffer;
+ cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
+ }
+ }
+
+ if (needsBindVBuf) {
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::BindVertexBuffers;
+ cmd.args.bindVertexBuffers.startSlot = startBinding;
+ cmd.args.bindVertexBuffers.slotCount = bindingCount;
+ const QVector<QRhiVertexInputBinding> inputBindings =
+ QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline)->m_vertexInputLayout.bindings();
+ for (int i = 0, ie = qMin(bindingCount, inputBindings.count()); i != ie; ++i) {
+ QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first);
+ cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer;
+ cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second;
+ cmd.args.bindVertexBuffers.strides[i] = inputBindings[i].stride();
+ }
+ cbD->commands.append(cmd);
+ }
+
+ if (indexBuf) {
+ QD3D11Buffer *ibufD = QRHI_RES(QD3D11Buffer, indexBuf);
+ Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
+ if (ibufD->m_type == QRhiBuffer::Dynamic)
+ executeBufferHostWritesForCurrentFrame(ibufD);
+
+ const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
+ : DXGI_FORMAT_R32_UINT;
+ if (cbD->currentIndexBuffer != ibufD->buffer
+ || cbD->currentIndexOffset != indexOffset
+ || cbD->currentIndexFormat != dxgiFormat)
+ {
+ cbD->currentIndexBuffer = ibufD->buffer;
+ cbD->currentIndexOffset = indexOffset;
+ cbD->currentIndexFormat = dxgiFormat;
+
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::BindIndexBuffer;
+ cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
+ cmd.args.bindIndexBuffer.offset = indexOffset;
+ cmd.args.bindIndexBuffer.format = dxgiFormat;
+ cbD->commands.append(cmd);
+ }
+ }
+}
+
+void QRhiD3D11::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
+{
+ Q_ASSERT(inPass);
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ Q_ASSERT(cbD->currentTarget);
+ const QSize outputSize = cbD->currentTarget->pixelSize();
+
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::Viewport;
+
+ // d3d expects top-left, QRhiViewport is bottom-left
+ float x, y, w, h;
+ if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h))
+ return;
+
+ cmd.args.viewport.x = x;
+ cmd.args.viewport.y = y;
+ cmd.args.viewport.w = w;
+ cmd.args.viewport.h = h;
+ cmd.args.viewport.d0 = viewport.minDepth();
+ cmd.args.viewport.d1 = viewport.maxDepth();
+ cbD->commands.append(cmd);
+}
+
+void QRhiD3D11::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
+{
+ Q_ASSERT(inPass);
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ Q_ASSERT(cbD->currentTarget);
+ const QSize outputSize = cbD->currentTarget->pixelSize();
+
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::Scissor;
+
+ // d3d expects top-left, QRhiScissor is bottom-left
+ int x, y, w, h;
+ if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h))
+ return;
+
+ cmd.args.scissor.x = x;
+ cmd.args.scissor.y = y;
+ cmd.args.scissor.w = w;
+ cmd.args.scissor.h = h;
+ cbD->commands.append(cmd);
+}
+
+void QRhiD3D11::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
+{
+ Q_ASSERT(inPass);
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::BlendConstants;
+ cmd.args.blendConstants.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline);
+ cmd.args.blendConstants.c[0] = c.redF();
+ cmd.args.blendConstants.c[1] = c.greenF();
+ cmd.args.blendConstants.c[2] = c.blueF();
+ cmd.args.blendConstants.c[3] = c.alphaF();
+ cbD->commands.append(cmd);
+}
+
+void QRhiD3D11::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
+{
+ Q_ASSERT(inPass);
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::StencilRef;
+ cmd.args.stencilRef.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline);
+ cmd.args.stencilRef.ref = refValue;
+ cbD->commands.append(cmd);
+}
+
+void QRhiD3D11::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
+{
+ Q_ASSERT(inPass);
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::Draw;
+ cmd.args.draw.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline);
+ cmd.args.draw.vertexCount = vertexCount;
+ cmd.args.draw.instanceCount = instanceCount;
+ cmd.args.draw.firstVertex = firstVertex;
+ cmd.args.draw.firstInstance = firstInstance;
+ cbD->commands.append(cmd);
+}
+
+void QRhiD3D11::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
+{
+ Q_ASSERT(inPass);
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::DrawIndexed;
+ cmd.args.drawIndexed.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentPipeline);
+ cmd.args.drawIndexed.indexCount = indexCount;
+ cmd.args.drawIndexed.instanceCount = instanceCount;
+ cmd.args.drawIndexed.firstIndex = firstIndex;
+ cmd.args.drawIndexed.vertexOffset = vertexOffset;
+ cmd.args.drawIndexed.firstInstance = firstInstance;
+ cbD->commands.append(cmd);
+}
+
+void QRhiD3D11::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
+{
+ if (!debugMarkers || !annotations)
+ return;
+
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::DebugMarkBegin;
+ strncpy(cmd.args.debugMark.s, name.constData(), sizeof(cmd.args.debugMark.s));
+ cmd.args.debugMark.s[sizeof(cmd.args.debugMark.s) - 1] = '\0';
+ cbD->commands.append(cmd);
+}
+
+void QRhiD3D11::debugMarkEnd(QRhiCommandBuffer *cb)
+{
+ if (!debugMarkers || !annotations)
+ return;
+
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::DebugMarkEnd;
+ cbD->commands.append(cmd);
+}
+
+void QRhiD3D11::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
+{
+ if (!debugMarkers || !annotations)
+ return;
+
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::DebugMarkMsg;
+ strncpy(cmd.args.debugMark.s, msg.constData(), sizeof(cmd.args.debugMark.s));
+ cmd.args.debugMark.s[sizeof(cmd.args.debugMark.s) - 1] = '\0';
+ cbD->commands.append(cmd);
+}
+
+const QRhiNativeHandles *QRhiD3D11::nativeHandles(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+ return nullptr;
+}
+
+void QRhiD3D11::beginExternal(QRhiCommandBuffer *cb)
+{
+ Q_ASSERT(inPass);
+ Q_UNUSED(cb);
+ flushCommandBuffer();
+}
+
+void QRhiD3D11::endExternal(QRhiCommandBuffer *cb)
+{
+ Q_ASSERT(inPass);
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ Q_ASSERT(cbD->currentTarget);
+ Q_ASSERT(cbD->commands.isEmpty());
+ cbD->resetCachedState();
+ enqueueSetRenderTarget(cbD, cbD->currentTarget);
+}
+
+QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
+{
+ Q_UNUSED(flags);
+
+ Q_ASSERT(!inFrame);
+ inFrame = true;
+
+ QD3D11SwapChain *swapChainD = QRHI_RES(QD3D11SwapChain, swapChain);
+ contextState.currentSwapChain = swapChainD;
+ const int currentFrameSlot = swapChainD->currentFrameSlot;
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+
+ if (swapChainD->timestampActive[currentFrameSlot]) {
+ ID3D11Query *tsDisjoint = swapChainD->timestampDisjointQuery[currentFrameSlot];
+ const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
+ ID3D11Query *tsStart = swapChainD->timestampQuery[tsIdx];
+ ID3D11Query *tsEnd = swapChainD->timestampQuery[tsIdx + 1];
+ quint64 timestamps[2];
+ D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
+ bool ok = true;
+ ok &= context->GetData(tsDisjoint, &dj, sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
+ ok &= context->GetData(tsEnd, &timestamps[1], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
+ // this above is often not ready, not even in frame_where_recorded+2,
+ // not clear why. so make the whole thing async and do not touch the
+ // queries until they are finally all available in frame this+2 or
+ // this+4 or ...
+ ok &= context->GetData(tsStart, &timestamps[0], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
+ if (ok) {
+ if (!dj.Disjoint && dj.Frequency) {
+ const float elapsedMs = (timestamps[1] - timestamps[0]) / float(dj.Frequency) * 1000.0f;
+ // finally got a value, just report it, the profiler cares about min/max/avg anyway
+ QRHI_PROF_F(swapChainFrameGpuTime(swapChain, elapsedMs));
+ }
+ swapChainD->timestampActive[currentFrameSlot] = false;
+ } // else leave timestampActive set to true, will retry in a subsequent beginFrame
+ }
+
+ swapChainD->cb.resetState();
+
+ swapChainD->rt.d.rtv[0] = swapChainD->sampleDesc.Count > 1 ?
+ swapChainD->msaaRtv[currentFrameSlot] : swapChainD->rtv[currentFrameSlot];
+ swapChainD->rt.d.dsv = swapChainD->ds ? swapChainD->ds->dsv : nullptr;
+
+ QRHI_PROF_F(beginSwapChainFrame(swapChain));
+
+ finishActiveReadbacks();
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags)
+{
+ Q_ASSERT(inFrame);
+ inFrame = false;
+
+ QD3D11SwapChain *swapChainD = QRHI_RES(QD3D11SwapChain, swapChain);
+ Q_ASSERT(contextState.currentSwapChain = swapChainD);
+ const int currentFrameSlot = swapChainD->currentFrameSlot;
+
+ ID3D11Query *tsDisjoint = swapChainD->timestampDisjointQuery[currentFrameSlot];
+ const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
+ ID3D11Query *tsStart = swapChainD->timestampQuery[tsIdx];
+ ID3D11Query *tsEnd = swapChainD->timestampQuery[tsIdx + 1];
+ const bool recordTimestamps = tsDisjoint && tsStart && tsEnd && !swapChainD->timestampActive[currentFrameSlot];
+
+ // send all commands to the context
+ if (recordTimestamps)
+ executeCommandBuffer(&swapChainD->cb, swapChainD);
+ else
+ executeCommandBuffer(&swapChainD->cb);
+
+ if (swapChainD->sampleDesc.Count > 1) {
+ context->ResolveSubresource(swapChainD->tex[currentFrameSlot], 0,
+ swapChainD->msaaTex[currentFrameSlot], 0,
+ swapChainD->colorFormat);
+ }
+
+ // this is here because we want to include the time spent on the resolve as well
+ if (recordTimestamps) {
+ context->End(tsEnd);
+ context->End(tsDisjoint);
+ swapChainD->timestampActive[currentFrameSlot] = true;
+ }
+
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+ // this must be done before the Present
+ QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
+
+ if (!flags.testFlag(QRhi::SkipPresent)) {
+ const UINT presentFlags = 0;
+ HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
+ if (FAILED(hr))
+ qWarning("Failed to present: %s", qPrintable(comErrorMessage(hr)));
+
+ // move on to the next buffer
+ swapChainD->currentFrameSlot = (swapChainD->currentFrameSlot + 1) % QD3D11SwapChain::BUFFER_COUNT;
+ } else {
+ context->Flush();
+ }
+
+ swapChainD->frameCount += 1;
+ contextState.currentSwapChain = nullptr;
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiD3D11::beginOffscreenFrame(QRhiCommandBuffer **cb)
+{
+ Q_ASSERT(!inFrame);
+ inFrame = true;
+ ofr.active = true;
+
+ ofr.cbWrapper.resetState();
+ *cb = &ofr.cbWrapper;
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiD3D11::endOffscreenFrame()
+{
+ Q_ASSERT(inFrame && ofr.active);
+ inFrame = false;
+ ofr.active = false;
+
+ executeCommandBuffer(&ofr.cbWrapper);
+
+ finishActiveReadbacks();
+
+ return QRhi::FrameOpSuccess;
+}
+
+static inline DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
+{
+ const bool srgb = flags.testFlag(QRhiTexture::sRGB);
+ switch (format) {
+ case QRhiTexture::RGBA8:
+ return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
+ case QRhiTexture::BGRA8:
+ return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
+ case QRhiTexture::R8:
+ return DXGI_FORMAT_R8_UNORM;
+ case QRhiTexture::R16:
+ return DXGI_FORMAT_R16_UNORM;
+ case QRhiTexture::RED_OR_ALPHA8:
+ return DXGI_FORMAT_R8_UNORM;
+
+ case QRhiTexture::RGBA16F:
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+ case QRhiTexture::RGBA32F:
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+
+ case QRhiTexture::D16:
+ return DXGI_FORMAT_R16_TYPELESS;
+ case QRhiTexture::D32F:
+ return DXGI_FORMAT_R32_TYPELESS;
+
+ case QRhiTexture::BC1:
+ return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
+ case QRhiTexture::BC2:
+ return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
+ case QRhiTexture::BC3:
+ return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
+ case QRhiTexture::BC4:
+ return DXGI_FORMAT_BC4_UNORM;
+ case QRhiTexture::BC5:
+ return DXGI_FORMAT_BC5_UNORM;
+ case QRhiTexture::BC6H:
+ return DXGI_FORMAT_BC6H_UF16;
+ case QRhiTexture::BC7:
+ return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
+
+ case QRhiTexture::ETC2_RGB8:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ETC2_RGB8A1:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ETC2_RGBA8:
+ qWarning("QRhiD3D11 does not support ETC2 textures");
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ case QRhiTexture::ASTC_4x4:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_5x4:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_5x5:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_6x5:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_6x6:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_8x5:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_8x6:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_8x8:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_10x5:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_10x6:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_10x8:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_10x10:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_12x10:
+ Q_FALLTHROUGH();
+ case QRhiTexture::ASTC_12x12:
+ qWarning("QRhiD3D11 does not support ASTC textures");
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ default:
+ Q_UNREACHABLE();
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+ }
+}
+
+static inline QRhiTexture::Format colorTextureFormatFromDxgiFormat(DXGI_FORMAT format, QRhiTexture::Flags *flags)
+{
+ switch (format) {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return QRhiTexture::RGBA8;
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ if (flags)
+ (*flags) |= QRhiTexture::sRGB;
+ return QRhiTexture::RGBA8;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return QRhiTexture::BGRA8;
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ if (flags)
+ (*flags) |= QRhiTexture::sRGB;
+ return QRhiTexture::BGRA8;
+ case DXGI_FORMAT_R8_UNORM:
+ return QRhiTexture::R8;
+ case DXGI_FORMAT_R16_UNORM:
+ return QRhiTexture::R16;
+ default: // this cannot assert, must warn and return unknown
+ qWarning("DXGI_FORMAT %d is not a recognized uncompressed color format", format);
+ break;
+ }
+ return QRhiTexture::UnknownFormat;
+}
+
+static inline bool isDepthTextureFormat(QRhiTexture::Format format)
+{
+ switch (format) {
+ case QRhiTexture::Format::D16:
+ Q_FALLTHROUGH();
+ case QRhiTexture::Format::D32F:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+QRhi::FrameOpResult QRhiD3D11::finish()
+{
+ Q_ASSERT(!inPass);
+
+ if (inFrame)
+ flushCommandBuffer();
+
+ finishActiveReadbacks();
+
+ return QRhi::FrameOpSuccess;
+}
+
+void QRhiD3D11::flushCommandBuffer()
+{
+ if (ofr.active) {
+ Q_ASSERT(!contextState.currentSwapChain);
+ executeCommandBuffer(&ofr.cbWrapper);
+ ofr.cbWrapper.resetCommands();
+ } else {
+ Q_ASSERT(contextState.currentSwapChain);
+ executeCommandBuffer(&contextState.currentSwapChain->cb); // no timestampSwapChain, in order to avoid timestamp mess
+ contextState.currentSwapChain->cb.resetCommands();
+ }
+}
+
+void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
+ int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
+{
+ UINT subres = D3D11CalcSubresource(level, layer, texD->mipLevelCount);
+ const QPoint dp = subresDesc.destinationTopLeft();
+ D3D11_BOX box;
+ box.front = 0;
+ // back, right, bottom are exclusive
+ box.back = 1;
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::UpdateSubRes;
+ cmd.args.updateSubRes.dst = texD->tex;
+ cmd.args.updateSubRes.dstSubRes = subres;
+
+ bool cmdValid = true;
+ if (!subresDesc.image().isNull()) {
+ QImage img = subresDesc.image();
+ QSize size = img.size();
+ int bpl = img.bytesPerLine();
+ if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
+ const QPoint sp = subresDesc.sourceTopLeft();
+ if (!subresDesc.sourceSize().isEmpty())
+ size = subresDesc.sourceSize();
+ if (img.depth() == 32) {
+ const int offset = sp.y() * img.bytesPerLine() + sp.x() * 4;
+ cmd.args.updateSubRes.src = cbD->retainImage(img) + offset;
+ } else {
+ img = img.copy(sp.x(), sp.y(), size.width(), size.height());
+ bpl = img.bytesPerLine();
+ cmd.args.updateSubRes.src = cbD->retainImage(img);
+ }
+ } else {
+ cmd.args.updateSubRes.src = cbD->retainImage(img);
+ }
+ box.left = dp.x();
+ box.top = dp.y();
+ box.right = dp.x() + size.width();
+ box.bottom = dp.y() + size.height();
+ cmd.args.updateSubRes.hasDstBox = true;
+ cmd.args.updateSubRes.dstBox = box;
+ cmd.args.updateSubRes.srcRowPitch = bpl;
+ } else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
+ const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
+ : subresDesc.sourceSize();
+ quint32 bpl = 0;
+ QSize blockDim;
+ compressedFormatInfo(texD->m_format, size, &bpl, nullptr, &blockDim);
+ // Everything must be a multiple of the block width and
+ // height, so e.g. a mip level of size 2x2 will be 4x4 when it
+ // comes to the actual data.
+ box.left = aligned(dp.x(), blockDim.width());
+ box.top = aligned(dp.y(), blockDim.height());
+ box.right = aligned(dp.x() + size.width(), blockDim.width());
+ box.bottom = aligned(dp.y() + size.height(), blockDim.height());
+ cmd.args.updateSubRes.hasDstBox = true;
+ cmd.args.updateSubRes.dstBox = box;
+ cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
+ cmd.args.updateSubRes.srcRowPitch = bpl;
+ } else if (!subresDesc.data().isEmpty()) {
+ const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
+ : subresDesc.sourceSize();
+ quint32 bpl = 0;
+ QSize blockDim;
+ textureFormatInfo(texD->m_format, size, &bpl, nullptr);
+ box.left = dp.x();
+ box.top = dp.y();
+ box.right = dp.x() + size.width();
+ box.bottom = dp.y() + size.height();
+ cmd.args.updateSubRes.hasDstBox = true;
+ cmd.args.updateSubRes.dstBox = box;
+ cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
+ cmd.args.updateSubRes.srcRowPitch = bpl;
+ } else {
+ qWarning("Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
+ cmdValid = false;
+ }
+ if (cmdValid)
+ cbD->commands.append(cmd);
+}
+
+void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+
+ for (const QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate &u : ud->dynamicBufferUpdates) {
+ QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, u.buf);
+ Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
+ memcpy(bufD->dynBuf.data() + u.offset, u.data.constData(), u.data.size());
+ bufD->hasPendingDynamicUpdates = true;
+ }
+
+ for (const QRhiResourceUpdateBatchPrivate::StaticBufferUpload &u : ud->staticBufferUploads) {
+ QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, u.buf);
+ Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
+ Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::UpdateSubRes;
+ cmd.args.updateSubRes.dst = bufD->buffer;
+ cmd.args.updateSubRes.dstSubRes = 0;
+ cmd.args.updateSubRes.src = cbD->retainData(u.data);
+ cmd.args.updateSubRes.srcRowPitch = 0;
+ // Specify the region (even when offset is 0 and all data is provided)
+ // since the ID3D11Buffer's size is rounded up to be a multiple of 256
+ // while the data we have has the original size.
+ D3D11_BOX box;
+ box.left = u.offset;
+ box.top = box.front = 0;
+ box.back = box.bottom = 1;
+ box.right = u.offset + u.data.size(); // no -1: right, bottom, back are exclusive, see D3D11_BOX doc
+ cmd.args.updateSubRes.hasDstBox = true;
+ cmd.args.updateSubRes.dstBox = box;
+ cbD->commands.append(cmd);
+ }
+
+ for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
+ if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
+ QD3D11Texture *texD = QRHI_RES(QD3D11Texture, u.upload.tex);
+ for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
+ for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.upload.subresDesc[layer][level]))
+ enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
+ }
+ }
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Copy) {
+ Q_ASSERT(u.copy.src && u.copy.dst);
+ QD3D11Texture *srcD = QRHI_RES(QD3D11Texture, u.copy.src);
+ QD3D11Texture *dstD = QRHI_RES(QD3D11Texture, u.copy.dst);
+ UINT srcSubRes = D3D11CalcSubresource(u.copy.desc.sourceLevel(), u.copy.desc.sourceLayer(), srcD->mipLevelCount);
+ UINT dstSubRes = D3D11CalcSubresource(u.copy.desc.destinationLevel(), u.copy.desc.destinationLayer(), dstD->mipLevelCount);
+ const QPoint dp = u.copy.desc.destinationTopLeft();
+ const QSize size = u.copy.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.copy.desc.pixelSize();
+ const QPoint sp = u.copy.desc.sourceTopLeft();
+ D3D11_BOX srcBox;
+ srcBox.left = sp.x();
+ srcBox.top = sp.y();
+ srcBox.front = 0;
+ // back, right, bottom are exclusive
+ srcBox.right = srcBox.left + size.width();
+ srcBox.bottom = srcBox.top + size.height();
+ srcBox.back = 1;
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes;
+ cmd.args.copySubRes.dst = dstD->tex;
+ cmd.args.copySubRes.dstSubRes = dstSubRes;
+ cmd.args.copySubRes.dstX = dp.x();
+ cmd.args.copySubRes.dstY = dp.y();
+ cmd.args.copySubRes.src = srcD->tex;
+ cmd.args.copySubRes.srcSubRes = srcSubRes;
+ cmd.args.copySubRes.hasSrcBox = true;
+ cmd.args.copySubRes.srcBox = srcBox;
+ cbD->commands.append(cmd);
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) {
+ ActiveReadback aRb;
+ aRb.desc = u.read.rb;
+ aRb.result = u.read.result;
+
+ ID3D11Resource *src;
+ DXGI_FORMAT dxgiFormat;
+ QSize pixelSize;
+ QRhiTexture::Format format;
+ UINT subres = 0;
+ QD3D11Texture *texD = QRHI_RES(QD3D11Texture, u.read.rb.texture());
+ QD3D11SwapChain *swapChainD = nullptr;
+
+ if (texD) {
+ if (texD->sampleDesc.Count > 1) {
+ qWarning("Multisample texture cannot be read back");
+ continue;
+ }
+ src = texD->tex;
+ dxgiFormat = texD->dxgiFormat;
+ pixelSize = u.read.rb.level() > 0 ? q->sizeForMipLevel(u.read.rb.level(), texD->m_pixelSize) : texD->m_pixelSize;
+ format = texD->m_format;
+ subres = D3D11CalcSubresource(u.read.rb.level(), u.read.rb.layer(), texD->mipLevelCount);
+ } else {
+ Q_ASSERT(contextState.currentSwapChain);
+ swapChainD = QRHI_RES(QD3D11SwapChain, contextState.currentSwapChain);
+ if (swapChainD->sampleDesc.Count > 1) {
+ // Unlike with textures, reading back a multisample swapchain image
+ // has to be supported. Insert a resolve.
+ QD3D11CommandBuffer::Command rcmd;
+ rcmd.cmd = QD3D11CommandBuffer::Command::ResolveSubRes;
+ rcmd.args.resolveSubRes.dst = swapChainD->tex[swapChainD->currentFrameSlot];
+ rcmd.args.resolveSubRes.dstSubRes = 0;
+ rcmd.args.resolveSubRes.src = swapChainD->msaaTex[swapChainD->currentFrameSlot];
+ rcmd.args.resolveSubRes.srcSubRes = 0;
+ rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
+ cbD->commands.append(rcmd);
+ }
+ src = swapChainD->tex[swapChainD->currentFrameSlot];
+ dxgiFormat = swapChainD->colorFormat;
+ pixelSize = swapChainD->pixelSize;
+ format = colorTextureFormatFromDxgiFormat(dxgiFormat, nullptr);
+ if (format == QRhiTexture::UnknownFormat)
+ continue;
+ }
+ quint32 bufSize = 0;
+ quint32 bpl = 0;
+ textureFormatInfo(format, pixelSize, &bpl, &bufSize);
+
+ D3D11_TEXTURE2D_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.Width = pixelSize.width();
+ desc.Height = pixelSize.height();
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = dxgiFormat;
+ desc.SampleDesc.Count = 1;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ ID3D11Texture2D *stagingTex;
+ HRESULT hr = dev->CreateTexture2D(&desc, nullptr, &stagingTex);
+ if (FAILED(hr)) {
+ qWarning("Failed to create readback staging texture: %s", qPrintable(comErrorMessage(hr)));
+ return;
+ }
+ QRHI_PROF_F(newReadbackBuffer(quint64(quintptr(stagingTex)),
+ texD ? static_cast<QRhiResource *>(texD) : static_cast<QRhiResource *>(swapChainD),
+ bufSize));
+
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes;
+ cmd.args.copySubRes.dst = stagingTex;
+ cmd.args.copySubRes.dstSubRes = 0;
+ cmd.args.copySubRes.dstX = 0;
+ cmd.args.copySubRes.dstY = 0;
+ cmd.args.copySubRes.src = src;
+ cmd.args.copySubRes.srcSubRes = subres;
+ cmd.args.copySubRes.hasSrcBox = false;
+ cbD->commands.append(cmd);
+
+ aRb.stagingTex = stagingTex;
+ aRb.bufSize = bufSize;
+ aRb.bpl = bpl;
+ aRb.pixelSize = pixelSize;
+ aRb.format = format;
+
+ activeReadbacks.append(aRb);
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::MipGen) {
+ Q_ASSERT(u.mipgen.tex->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::GenMip;
+ cmd.args.genMip.srv = QRHI_RES(QD3D11Texture, u.mipgen.tex)->srv;
+ cbD->commands.append(cmd);
+ }
+ }
+
+ ud->free();
+}
+
+void QRhiD3D11::finishActiveReadbacks()
+{
+ QVarLengthArray<std::function<void()>, 4> completedCallbacks;
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+
+ for (int i = activeReadbacks.count() - 1; i >= 0; --i) {
+ const QRhiD3D11::ActiveReadback &aRb(activeReadbacks[i]);
+ aRb.result->format = aRb.format;
+ aRb.result->pixelSize = aRb.pixelSize;
+ aRb.result->data.resize(aRb.bufSize);
+
+ D3D11_MAPPED_SUBRESOURCE mp;
+ HRESULT hr = context->Map(aRb.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
+ if (FAILED(hr)) {
+ qWarning("Failed to map readback staging texture: %s", qPrintable(comErrorMessage(hr)));
+ aRb.stagingTex->Release();
+ continue;
+ }
+ // nothing says the rows are tightly packed in the texture, must take
+ // the stride into account
+ char *dst = aRb.result->data.data();
+ char *src = static_cast<char *>(mp.pData);
+ for (int y = 0, h = aRb.pixelSize.height(); y != h; ++y) {
+ memcpy(dst, src, aRb.bpl);
+ dst += aRb.bpl;
+ src += mp.RowPitch;
+ }
+ context->Unmap(aRb.stagingTex, 0);
+
+ aRb.stagingTex->Release();
+ QRHI_PROF_F(releaseReadbackBuffer(quint64(quintptr(aRb.stagingTex))));
+
+ if (aRb.result->completed)
+ completedCallbacks.append(aRb.result->completed);
+
+ activeReadbacks.removeAt(i);
+ }
+
+ for (auto f : completedCallbacks)
+ f();
+}
+
+static inline QD3D11RenderTargetData *rtData(QRhiRenderTarget *rt)
+{
+ switch (rt->resourceType()) {
+ case QRhiResource::RenderTarget:
+ return &QRHI_RES(QD3D11ReferenceRenderTarget, rt)->d;
+ case QRhiResource::TextureRenderTarget:
+ return &QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
+ default:
+ Q_UNREACHABLE();
+ return nullptr;
+ }
+}
+
+void QRhiD3D11::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inFrame && !inPass);
+
+ enqueueResourceUpdates(cb, resourceUpdates);
+}
+
+void QRhiD3D11::enqueueSetRenderTarget(QD3D11CommandBuffer *cbD, QRhiRenderTarget *rt)
+{
+ QD3D11CommandBuffer::Command fbCmd;
+ fbCmd.cmd = QD3D11CommandBuffer::Command::SetRenderTarget;
+ fbCmd.args.setRenderTarget.rt = rt;
+ cbD->commands.append(fbCmd);
+}
+
+void QRhiD3D11::beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inFrame && !inPass);
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cb, resourceUpdates);
+
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ bool wantsColorClear = true;
+ bool wantsDsClear = true;
+ QD3D11RenderTargetData *rtD = rtData(rt);
+ if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
+ QD3D11TextureRenderTarget *rtTex = QRHI_RES(QD3D11TextureRenderTarget, rt);
+ wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
+ wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
+ }
+ enqueueSetRenderTarget(cbD, rt);
+
+ QD3D11CommandBuffer::Command clearCmd;
+ clearCmd.cmd = QD3D11CommandBuffer::Command::Clear;
+ clearCmd.args.clear.rt = rt;
+ clearCmd.args.clear.mask = 0;
+ if (rtD->colorAttCount && wantsColorClear)
+ clearCmd.args.clear.mask |= QD3D11CommandBuffer::Command::Color;
+ if (rtD->dsAttCount && wantsDsClear)
+ clearCmd.args.clear.mask |= QD3D11CommandBuffer::Command::Depth | QD3D11CommandBuffer::Command::Stencil;
+
+ clearCmd.args.clear.c[0] = colorClearValue.redF();
+ clearCmd.args.clear.c[1] = colorClearValue.greenF();
+ clearCmd.args.clear.c[2] = colorClearValue.blueF();
+ clearCmd.args.clear.c[3] = colorClearValue.alphaF();
+ clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
+ clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
+ cbD->commands.append(clearCmd);
+
+ cbD->currentTarget = rt;
+
+ inPass = true;
+}
+
+void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inPass);
+ inPass = false;
+
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
+ QD3D11TextureRenderTarget *rtTex = QRHI_RES(QD3D11TextureRenderTarget, cbD->currentTarget);
+ const QVector<QRhiColorAttachment> colorAttachments = rtTex->m_desc.colorAttachments();
+ for (int att = 0, attCount = colorAttachments.count(); att != attCount; ++att) {
+ const QRhiColorAttachment &colorAtt(colorAttachments[att]);
+ if (!colorAtt.resolveTexture())
+ continue;
+
+ QD3D11Texture *dstTexD = QRHI_RES(QD3D11Texture, colorAtt.resolveTexture());
+ QD3D11Texture *srcTexD = QRHI_RES(QD3D11Texture, colorAtt.texture());
+ QD3D11RenderBuffer *srcRbD = QRHI_RES(QD3D11RenderBuffer, colorAtt.renderBuffer());
+ Q_ASSERT(srcTexD || srcRbD);
+ QD3D11CommandBuffer::Command cmd;
+ cmd.cmd = QD3D11CommandBuffer::Command::ResolveSubRes;
+ cmd.args.resolveSubRes.dst = dstTexD->tex;
+ cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(colorAtt.resolveLevel(),
+ colorAtt.resolveLayer(),
+ dstTexD->mipLevelCount);
+ if (srcTexD) {
+ cmd.args.resolveSubRes.src = srcTexD->tex;
+ if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
+ qWarning("Resolve source and destination formats do not match");
+ continue;
+ }
+ if (srcTexD->sampleDesc.Count <= 1) {
+ qWarning("Cannot resolve a non-multisample texture");
+ continue;
+ }
+ if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
+ qWarning("Resolve source and destination sizes do not match");
+ continue;
+ }
+ } else {
+ cmd.args.resolveSubRes.src = srcRbD->tex;
+ if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
+ qWarning("Resolve source and destination formats do not match");
+ continue;
+ }
+ if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
+ qWarning("Resolve source and destination sizes do not match");
+ continue;
+ }
+ }
+ cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, colorAtt.layer(), 1);
+ cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
+ cbD->commands.append(cmd);
+ }
+ }
+
+ cbD->currentTarget = nullptr;
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cb, resourceUpdates);
+}
+
+void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
+{
+ srbD->vsubufs.clear();
+ srbD->vsubufoffsets.clear();
+ srbD->vsubufsizes.clear();
+
+ srbD->fsubufs.clear();
+ srbD->fsubufoffsets.clear();
+ srbD->fsubufsizes.clear();
+
+ srbD->vssamplers.clear();
+ srbD->vsshaderresources.clear();
+
+ srbD->fssamplers.clear();
+ srbD->fsshaderresources.clear();
+
+ for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->sortedBindings[i]);
+ QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ {
+ QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf);
+ Q_ASSERT(aligned(b->u.ubuf.offset, 256) == b->u.ubuf.offset);
+ bd.ubuf.id = bufD->m_id;
+ bd.ubuf.generation = bufD->generation;
+ // dynamic ubuf offsets are not considered here, those are baked in
+ // at a later stage, which is good as vsubufoffsets and friends are
+ // per-srb, not per-setShaderResources call
+ const uint offsetInConstants = b->u.ubuf.offset / 16;
+ // size must be 16 mult. (in constants, i.e. multiple of 256 bytes).
+ // We can round up if needed since the buffers's actual size
+ // (ByteWidth) is always a multiple of 256.
+ const uint sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256) / 16;
+ if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
+ srbD->vsubufs.feed(b->binding, bufD->buffer);
+ srbD->vsubufoffsets.feed(b->binding, offsetInConstants);
+ srbD->vsubufsizes.feed(b->binding, sizeInConstants);
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
+ srbD->fsubufs.feed(b->binding, bufD->buffer);
+ srbD->fsubufoffsets.feed(b->binding, offsetInConstants);
+ srbD->fsubufsizes.feed(b->binding, sizeInConstants);
+ }
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ {
+ // A sampler with binding N is mapped to a HLSL sampler and texture
+ // with registers sN and tN by SPIRV-Cross.
+ QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex);
+ QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler);
+ bd.stex.texId = texD->m_id;
+ bd.stex.texGeneration = texD->generation;
+ bd.stex.samplerId = samplerD->m_id;
+ bd.stex.samplerGeneration = samplerD->generation;
+ if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
+ srbD->vssamplers.feed(b->binding, samplerD->samplerState);
+ srbD->vsshaderresources.feed(b->binding, texD->srv);
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
+ srbD->fssamplers.feed(b->binding, samplerD->samplerState);
+ srbD->fsshaderresources.feed(b->binding, texD->srv);
+ }
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+
+ srbD->vsubufs.finish();
+ srbD->vsubufoffsets.finish();
+ srbD->vsubufsizes.finish();
+
+ srbD->fsubufs.finish();
+ srbD->fsubufoffsets.finish();
+ srbD->fsubufsizes.finish();
+
+ srbD->vssamplers.finish();
+ srbD->vsshaderresources.finish();
+
+ srbD->fssamplers.finish();
+ srbD->fsshaderresources.finish();
+}
+
+void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD)
+{
+ if (!bufD->hasPendingDynamicUpdates)
+ return;
+
+ Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
+ bufD->hasPendingDynamicUpdates = false;
+ D3D11_MAPPED_SUBRESOURCE mp;
+ HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
+ if (SUCCEEDED(hr)) {
+ memcpy(mp.pData, bufD->dynBuf.constData(), bufD->dynBuf.size());
+ context->Unmap(bufD->buffer, 0);
+ } else {
+ qWarning("Failed to map buffer: %s", qPrintable(comErrorMessage(hr)));
+ }
+}
+
+void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
+ const uint *dynOfsPairs, int dynOfsPairCount,
+ bool offsetOnlyChange)
+{
+ if (!offsetOnlyChange) {
+ for (const auto &batch : srbD->vssamplers.batches)
+ context->VSSetSamplers(batch.startBinding, batch.resources.count(), batch.resources.constData());
+
+ for (const auto &batch : srbD->vsshaderresources.batches) {
+ context->VSSetShaderResources(batch.startBinding, batch.resources.count(), batch.resources.constData());
+ contextState.vsHighestActiveSrvBinding = qMax<int>(contextState.vsHighestActiveSrvBinding,
+ batch.startBinding + batch.resources.count() - 1);
+ }
+
+ for (const auto &batch : srbD->fssamplers.batches)
+ context->PSSetSamplers(batch.startBinding, batch.resources.count(), batch.resources.constData());
+
+ for (const auto &batch : srbD->fsshaderresources.batches) {
+ context->PSSetShaderResources(batch.startBinding, batch.resources.count(), batch.resources.constData());
+ contextState.fsHighestActiveSrvBinding = qMax<int>(contextState.fsHighestActiveSrvBinding,
+ batch.startBinding + batch.resources.count() - 1);
+ }
+ }
+
+ for (int i = 0, ie = srbD->vsubufs.batches.count(); i != ie; ++i) {
+ if (!dynOfsPairCount) {
+ context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
+ srbD->vsubufs.batches[i].resources.count(),
+ srbD->vsubufs.batches[i].resources.constData(),
+ srbD->vsubufoffsets.batches[i].resources.constData(),
+ srbD->vsubufsizes.batches[i].resources.constData());
+ } else {
+ const UINT count = srbD->vsubufs.batches[i].resources.count();
+ const UINT startBinding = srbD->vsubufs.batches[i].startBinding;
+ QVarLengthArray<UINT, 4> offsets = srbD->vsubufoffsets.batches[i].resources;
+ for (UINT b = 0; b < count; ++b) {
+ for (int di = 0; di < dynOfsPairCount; ++di) {
+ const uint binding = dynOfsPairs[2 * di];
+ if (binding == startBinding + b) {
+ const uint offsetInConstants = dynOfsPairs[2 * di + 1];
+ offsets[b] = offsetInConstants;
+ break;
+ }
+ }
+ }
+ context->VSSetConstantBuffers1(startBinding,
+ count,
+ srbD->vsubufs.batches[i].resources.constData(),
+ offsets.constData(),
+ srbD->vsubufsizes.batches[i].resources.constData());
+ }
+ }
+
+ for (int i = 0, ie = srbD->fsubufs.batches.count(); i != ie; ++i) {
+ if (!dynOfsPairCount) {
+ context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
+ srbD->fsubufs.batches[i].resources.count(),
+ srbD->fsubufs.batches[i].resources.constData(),
+ srbD->fsubufoffsets.batches[i].resources.constData(),
+ srbD->fsubufsizes.batches[i].resources.constData());
+ } else {
+ const UINT count = srbD->fsubufs.batches[i].resources.count();
+ const UINT startBinding = srbD->fsubufs.batches[i].startBinding;
+ QVarLengthArray<UINT, 4> offsets = srbD->fsubufoffsets.batches[i].resources;
+ for (UINT b = 0; b < count; ++b) {
+ for (int di = 0; di < dynOfsPairCount; ++di) {
+ const uint binding = dynOfsPairs[2 * di];
+ if (binding == startBinding + b) {
+ const uint offsetInConstants = dynOfsPairs[2 * di + 1];
+ offsets[b] = offsetInConstants;
+ break;
+ }
+ }
+ }
+ context->PSSetConstantBuffers1(startBinding,
+ count,
+ srbD->fsubufs.batches[i].resources.constData(),
+ offsets.constData(),
+ srbD->fsubufsizes.batches[i].resources.constData());
+ }
+ }
+}
+
+void QRhiD3D11::setRenderTarget(QRhiRenderTarget *rt)
+{
+ // The new output cannot be bound as input from the previous frame,
+ // otherwise the debug layer complains. Avoid this.
+ const int nullsrvCount = qMax(contextState.vsHighestActiveSrvBinding, contextState.fsHighestActiveSrvBinding) + 1;
+ if (nullsrvCount > 0) {
+ QVarLengthArray<ID3D11ShaderResourceView *,
+ D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nullsrvs(nullsrvCount);
+ for (int i = 0; i < nullsrvs.count(); ++i)
+ nullsrvs[i] = nullptr;
+ if (contextState.vsHighestActiveSrvBinding >= 0) {
+ context->VSSetShaderResources(0, contextState.vsHighestActiveSrvBinding + 1, nullsrvs.constData());
+ contextState.vsHighestActiveSrvBinding = -1;
+ }
+ if (contextState.fsHighestActiveSrvBinding >= 0) {
+ context->PSSetShaderResources(0, contextState.fsHighestActiveSrvBinding + 1, nullsrvs.constData());
+ contextState.fsHighestActiveSrvBinding = -1;
+ }
+ }
+ QD3D11RenderTargetData *rtD = rtData(rt);
+ context->OMSetRenderTargets(rtD->colorAttCount, rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
+}
+
+void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain)
+{
+ quint32 stencilRef = 0;
+ float blendConstants[] = { 1, 1, 1, 1 };
+
+ if (timestampSwapChain) {
+ const int currentFrameSlot = timestampSwapChain->currentFrameSlot;
+ ID3D11Query *tsDisjoint = timestampSwapChain->timestampDisjointQuery[currentFrameSlot];
+ const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
+ ID3D11Query *tsStart = timestampSwapChain->timestampQuery[tsIdx];
+ if (tsDisjoint && tsStart && !timestampSwapChain->timestampActive[currentFrameSlot]) {
+ // The timestamps seem to include vsync time with Present(1), except
+ // when running on a non-primary gpu. This is not ideal. So try working
+ // it around by issuing a semi-fake OMSetRenderTargets early and
+ // writing the first timestamp only afterwards.
+ context->Begin(tsDisjoint);
+ setRenderTarget(&timestampSwapChain->rt);
+ context->End(tsStart); // just record a timestamp, no Begin needed
+ }
+ }
+
+ for (const QD3D11CommandBuffer::Command &cmd : qAsConst(cbD->commands)) {
+ switch (cmd.cmd) {
+ case QD3D11CommandBuffer::Command::SetRenderTarget:
+ setRenderTarget(cmd.args.setRenderTarget.rt);
+ break;
+ case QD3D11CommandBuffer::Command::Clear:
+ {
+ QD3D11RenderTargetData *rtD = rtData(cmd.args.clear.rt);
+ if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Color) {
+ for (int i = 0; i < rtD->colorAttCount; ++i)
+ context->ClearRenderTargetView(rtD->rtv[i], cmd.args.clear.c);
+ }
+ uint ds = 0;
+ if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Depth)
+ ds |= D3D11_CLEAR_DEPTH;
+ if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
+ ds |= D3D11_CLEAR_STENCIL;
+ if (ds)
+ context->ClearDepthStencilView(rtD->dsv, ds, cmd.args.clear.d, cmd.args.clear.s);
+ }
+ break;
+ case QD3D11CommandBuffer::Command::Viewport:
+ {
+ D3D11_VIEWPORT v;
+ v.TopLeftX = cmd.args.viewport.x;
+ v.TopLeftY = cmd.args.viewport.y;
+ v.Width = cmd.args.viewport.w;
+ v.Height = cmd.args.viewport.h;
+ v.MinDepth = cmd.args.viewport.d0;
+ v.MaxDepth = cmd.args.viewport.d1;
+ context->RSSetViewports(1, &v);
+ }
+ break;
+ case QD3D11CommandBuffer::Command::Scissor:
+ {
+ D3D11_RECT r;
+ r.left = cmd.args.scissor.x;
+ r.top = cmd.args.scissor.y;
+ // right and bottom are exclusive
+ r.right = cmd.args.scissor.x + cmd.args.scissor.w;
+ r.bottom = cmd.args.scissor.y + cmd.args.scissor.h;
+ context->RSSetScissorRects(1, &r);
+ }
+ break;
+ case QD3D11CommandBuffer::Command::BindVertexBuffers:
+ context->IASetVertexBuffers(cmd.args.bindVertexBuffers.startSlot,
+ cmd.args.bindVertexBuffers.slotCount,
+ cmd.args.bindVertexBuffers.buffers,
+ cmd.args.bindVertexBuffers.strides,
+ cmd.args.bindVertexBuffers.offsets);
+ break;
+ case QD3D11CommandBuffer::Command::BindIndexBuffer:
+ context->IASetIndexBuffer(cmd.args.bindIndexBuffer.buffer,
+ cmd.args.bindIndexBuffer.format,
+ cmd.args.bindIndexBuffer.offset);
+ break;
+ case QD3D11CommandBuffer::Command::BindGraphicsPipeline:
+ {
+ QD3D11GraphicsPipeline *psD = cmd.args.bindGraphicsPipeline.ps;
+ context->VSSetShader(psD->vs, nullptr, 0);
+ context->PSSetShader(psD->fs, nullptr, 0);
+ context->IASetPrimitiveTopology(psD->d3dTopology);
+ context->IASetInputLayout(psD->inputLayout);
+ context->OMSetDepthStencilState(psD->dsState, stencilRef);
+ context->OMSetBlendState(psD->blendState, blendConstants, 0xffffffff);
+ context->RSSetState(psD->rastState);
+ }
+ break;
+ case QD3D11CommandBuffer::Command::BindShaderResources:
+ bindShaderResources(cmd.args.bindShaderResources.srb,
+ cmd.args.bindShaderResources.dynamicOffsetPairs,
+ cmd.args.bindShaderResources.dynamicOffsetCount,
+ cmd.args.bindShaderResources.offsetOnlyChange);
+ break;
+ case QD3D11CommandBuffer::Command::StencilRef:
+ stencilRef = cmd.args.stencilRef.ref;
+ context->OMSetDepthStencilState(cmd.args.stencilRef.ps->dsState, stencilRef);
+ break;
+ case QD3D11CommandBuffer::Command::BlendConstants:
+ memcpy(blendConstants, cmd.args.blendConstants.c, 4 * sizeof(float));
+ context->OMSetBlendState(cmd.args.blendConstants.ps->blendState, blendConstants, 0xffffffff);
+ break;
+ case QD3D11CommandBuffer::Command::Draw:
+ if (cmd.args.draw.ps) {
+ if (cmd.args.draw.instanceCount == 1)
+ context->Draw(cmd.args.draw.vertexCount, cmd.args.draw.firstVertex);
+ else
+ context->DrawInstanced(cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
+ cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
+ } else {
+ qWarning("No graphics pipeline active for draw; ignored");
+ }
+ break;
+ case QD3D11CommandBuffer::Command::DrawIndexed:
+ if (cmd.args.drawIndexed.ps) {
+ if (cmd.args.drawIndexed.instanceCount == 1)
+ context->DrawIndexed(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.firstIndex,
+ cmd.args.drawIndexed.vertexOffset);
+ else
+ context->DrawIndexedInstanced(cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
+ cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
+ cmd.args.drawIndexed.firstInstance);
+ } else {
+ qWarning("No graphics pipeline active for drawIndexed; ignored");
+ }
+ break;
+ case QD3D11CommandBuffer::Command::UpdateSubRes:
+ context->UpdateSubresource(cmd.args.updateSubRes.dst, cmd.args.updateSubRes.dstSubRes,
+ cmd.args.updateSubRes.hasDstBox ? &cmd.args.updateSubRes.dstBox : nullptr,
+ cmd.args.updateSubRes.src, cmd.args.updateSubRes.srcRowPitch, 0);
+ break;
+ case QD3D11CommandBuffer::Command::CopySubRes:
+ context->CopySubresourceRegion(cmd.args.copySubRes.dst, cmd.args.copySubRes.dstSubRes,
+ cmd.args.copySubRes.dstX, cmd.args.copySubRes.dstY, 0,
+ cmd.args.copySubRes.src, cmd.args.copySubRes.srcSubRes,
+ cmd.args.copySubRes.hasSrcBox ? &cmd.args.copySubRes.srcBox : nullptr);
+ break;
+ case QD3D11CommandBuffer::Command::ResolveSubRes:
+ context->ResolveSubresource(cmd.args.resolveSubRes.dst, cmd.args.resolveSubRes.dstSubRes,
+ cmd.args.resolveSubRes.src, cmd.args.resolveSubRes.srcSubRes,
+ cmd.args.resolveSubRes.format);
+ break;
+ case QD3D11CommandBuffer::Command::GenMip:
+ context->GenerateMips(cmd.args.genMip.srv);
+ break;
+ case QD3D11CommandBuffer::Command::DebugMarkBegin:
+ annotations->BeginEvent(reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
+ break;
+ case QD3D11CommandBuffer::Command::DebugMarkEnd:
+ annotations->EndEvent();
+ break;
+ case QD3D11CommandBuffer::Command::DebugMarkMsg:
+ annotations->SetMarker(reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+QD3D11Buffer::QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+ : QRhiBuffer(rhi, type, usage, size)
+{
+}
+
+QD3D11Buffer::~QD3D11Buffer()
+{
+ release();
+}
+
+void QD3D11Buffer::release()
+{
+ if (!buffer)
+ return;
+
+ dynBuf.clear();
+
+ buffer->Release();
+ buffer = nullptr;
+
+ QRHI_RES_RHI(QRhiD3D11);
+ QRHI_PROF;
+ QRHI_PROF_F(releaseBuffer(this));
+ rhiD->unregisterResource(this);
+}
+
+static inline uint toD3DBufferUsage(QRhiBuffer::UsageFlags usage)
+{
+ int u = 0;
+ if (usage.testFlag(QRhiBuffer::VertexBuffer))
+ u |= D3D11_BIND_VERTEX_BUFFER;
+ if (usage.testFlag(QRhiBuffer::IndexBuffer))
+ u |= D3D11_BIND_INDEX_BUFFER;
+ if (usage.testFlag(QRhiBuffer::UniformBuffer))
+ u |= D3D11_BIND_CONSTANT_BUFFER;
+ return u;
+}
+
+bool QD3D11Buffer::build()
+{
+ if (buffer)
+ release();
+
+ const int nonZeroSize = m_size <= 0 ? 256 : m_size;
+ const int roundedSize = m_usage.testFlag(QRhiBuffer::UniformBuffer) ? aligned(nonZeroSize, 256) : nonZeroSize;
+
+ D3D11_BUFFER_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.ByteWidth = roundedSize;
+ desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
+ desc.BindFlags = toD3DBufferUsage(m_usage);
+ desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
+
+ QRHI_RES_RHI(QRhiD3D11);
+ HRESULT hr = rhiD->dev->CreateBuffer(&desc, nullptr, &buffer);
+ if (FAILED(hr)) {
+ qWarning("Failed to create buffer: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+
+ if (m_type == Dynamic) {
+ dynBuf.resize(m_size);
+ hasPendingDynamicUpdates = false;
+ }
+
+ if (!m_objectName.isEmpty())
+ buffer->SetPrivateData(WKPDID_D3DDebugObjectName, m_objectName.size(), m_objectName.constData());
+
+ QRHI_PROF;
+ QRHI_PROF_F(newBuffer(this, roundedSize, m_type == Dynamic ? 2 : 1, m_type == Dynamic ? 1 : 0));
+
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QD3D11RenderBuffer::QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags)
+ : QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
+{
+}
+
+QD3D11RenderBuffer::~QD3D11RenderBuffer()
+{
+ release();
+}
+
+void QD3D11RenderBuffer::release()
+{
+ if (!tex)
+ return;
+
+ if (dsv) {
+ dsv->Release();
+ dsv = nullptr;
+ }
+
+ if (rtv) {
+ rtv->Release();
+ rtv = nullptr;
+ }
+
+ tex->Release();
+ tex = nullptr;
+
+ QRHI_RES_RHI(QRhiD3D11);
+ QRHI_PROF;
+ QRHI_PROF_F(releaseRenderBuffer(this));
+ rhiD->unregisterResource(this);
+}
+
+bool QD3D11RenderBuffer::build()
+{
+ if (tex)
+ release();
+
+ if (m_pixelSize.isEmpty())
+ return false;
+
+ QRHI_RES_RHI(QRhiD3D11);
+ sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
+
+ D3D11_TEXTURE2D_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.Width = m_pixelSize.width();
+ desc.Height = m_pixelSize.height();
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.SampleDesc = sampleDesc;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+
+ if (m_type == Color) {
+ dxgiFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.Format = dxgiFormat;
+ desc.BindFlags = D3D11_BIND_RENDER_TARGET;
+ HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex);
+ if (FAILED(hr)) {
+ qWarning("Failed to create color renderbuffer: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ memset(&rtvDesc, 0, sizeof(rtvDesc));
+ rtvDesc.Format = dxgiFormat;
+ rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
+ : D3D11_RTV_DIMENSION_TEXTURE2D;
+ hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
+ if (FAILED(hr)) {
+ qWarning("Failed to create rtv: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ } else if (m_type == DepthStencil) {
+ dxgiFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ desc.Format = dxgiFormat;
+ desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+ HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex);
+ if (FAILED(hr)) {
+ qWarning("Failed to create depth-stencil buffer: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ memset(&dsvDesc, 0, sizeof(dsvDesc));
+ dsvDesc.Format = dxgiFormat;
+ dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
+ : D3D11_DSV_DIMENSION_TEXTURE2D;
+ hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
+ if (FAILED(hr)) {
+ qWarning("Failed to create dsv: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ if (!m_objectName.isEmpty())
+ tex->SetPrivateData(WKPDID_D3DDebugObjectName, m_objectName.size(), m_objectName.constData());
+
+ QRHI_PROF;
+ QRHI_PROF_F(newRenderBuffer(this, false, false, sampleDesc.Count));
+
+ rhiD->registerResource(this);
+ return true;
+}
+
+QRhiTexture::Format QD3D11RenderBuffer::backingFormat() const
+{
+ return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
+}
+
+QD3D11Texture::QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, sampleCount, flags)
+{
+}
+
+QD3D11Texture::~QD3D11Texture()
+{
+ release();
+}
+
+void QD3D11Texture::release()
+{
+ if (!tex)
+ return;
+
+ if (srv) {
+ srv->Release();
+ srv = nullptr;
+ }
+
+ if (owns)
+ tex->Release();
+
+ tex = nullptr;
+
+ QRHI_RES_RHI(QRhiD3D11);
+ QRHI_PROF;
+ QRHI_PROF_F(releaseTexture(this));
+ rhiD->unregisterResource(this);
+}
+
+static inline DXGI_FORMAT toD3DDepthTextureSRVFormat(QRhiTexture::Format format)
+{
+ switch (format) {
+ case QRhiTexture::Format::D16:
+ return DXGI_FORMAT_R16_FLOAT;
+ case QRhiTexture::Format::D32F:
+ return DXGI_FORMAT_R32_FLOAT;
+ default:
+ Q_UNREACHABLE();
+ return DXGI_FORMAT_R32_FLOAT;
+ }
+}
+
+static inline DXGI_FORMAT toD3DDepthTextureDSVFormat(QRhiTexture::Format format)
+{
+ switch (format) {
+ case QRhiTexture::Format::D16:
+ return DXGI_FORMAT_D16_UNORM;
+ case QRhiTexture::Format::D32F:
+ return DXGI_FORMAT_D32_FLOAT;
+ default:
+ Q_UNREACHABLE();
+ return DXGI_FORMAT_D32_FLOAT;
+ }
+}
+
+bool QD3D11Texture::prepareBuild(QSize *adjustedSize)
+{
+ if (tex)
+ release();
+
+ const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
+ const bool isDepth = isDepthTextureFormat(m_format);
+ const bool isCube = m_flags.testFlag(CubeMap);
+ const bool hasMipMaps = m_flags.testFlag(MipMapped);
+
+ QRHI_RES_RHI(QRhiD3D11);
+ dxgiFormat = toD3DTextureFormat(m_format, m_flags);
+ mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
+ sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
+ if (sampleDesc.Count > 1) {
+ if (isCube) {
+ qWarning("Cubemap texture cannot be multisample");
+ return false;
+ }
+ if (hasMipMaps) {
+ qWarning("Multisample texture cannot have mipmaps");
+ return false;
+ }
+ }
+ if (isDepth && hasMipMaps) {
+ qWarning("Depth texture cannot have mipmaps");
+ return false;
+ }
+
+ if (adjustedSize)
+ *adjustedSize = size;
+
+ return true;
+}
+
+bool QD3D11Texture::finishBuild()
+{
+ QRHI_RES_RHI(QRhiD3D11);
+ const bool isDepth = isDepthTextureFormat(m_format);
+ const bool isCube = m_flags.testFlag(CubeMap);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ memset(&srvDesc, 0, sizeof(srvDesc));
+ srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
+ if (isCube) {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ srvDesc.TextureCube.MipLevels = mipLevelCount;
+ } else {
+ if (sampleDesc.Count > 1) {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ } else {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MipLevels = mipLevelCount;
+ }
+ }
+
+ HRESULT hr = rhiD->dev->CreateShaderResourceView(tex, &srvDesc, &srv);
+ if (FAILED(hr)) {
+ qWarning("Failed to create srv: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+
+ nativeHandlesStruct.texture = tex;
+
+ generation += 1;
+ return true;
+}
+
+bool QD3D11Texture::build()
+{
+ QSize size;
+ if (!prepareBuild(&size))
+ return false;
+
+ const bool isDepth = isDepthTextureFormat(m_format);
+ const bool isCube = m_flags.testFlag(CubeMap);
+
+ uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
+ uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
+ if (m_flags.testFlag(RenderTarget)) {
+ if (isDepth)
+ bindFlags |= D3D11_BIND_DEPTH_STENCIL;
+ else
+ bindFlags |= D3D11_BIND_RENDER_TARGET;
+ }
+ if (m_flags.testFlag(UsedWithGenerateMips)) {
+ if (isDepth) {
+ qWarning("Depth texture cannot have mipmaps generated");
+ return false;
+ }
+ bindFlags |= D3D11_BIND_RENDER_TARGET;
+ miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
+ }
+
+ D3D11_TEXTURE2D_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.Width = size.width();
+ desc.Height = size.height();
+ desc.MipLevels = mipLevelCount;
+ desc.ArraySize = isCube ? 6 : 1;
+ desc.Format = dxgiFormat;
+ desc.SampleDesc = sampleDesc;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = bindFlags;
+ desc.MiscFlags = miscFlags;
+
+ QRHI_RES_RHI(QRhiD3D11);
+ HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex);
+ if (FAILED(hr)) {
+ qWarning("Failed to create texture: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+
+ if (!finishBuild())
+ return false;
+
+ if (!m_objectName.isEmpty())
+ tex->SetPrivateData(WKPDID_D3DDebugObjectName, m_objectName.size(), m_objectName.constData());
+
+ QRHI_PROF;
+ QRHI_PROF_F(newTexture(this, true, mipLevelCount, isCube ? 6 : 1, sampleDesc.Count));
+
+ owns = true;
+ rhiD->registerResource(this);
+ return true;
+}
+
+bool QD3D11Texture::buildFrom(const QRhiNativeHandles *src)
+{
+ const QRhiD3D11TextureNativeHandles *h = static_cast<const QRhiD3D11TextureNativeHandles *>(src);
+ if (!h || !h->texture)
+ return false;
+
+ if (!prepareBuild())
+ return false;
+
+ tex = static_cast<ID3D11Texture2D *>(h->texture);
+
+ if (!finishBuild())
+ return false;
+
+ QRHI_PROF;
+ QRHI_PROF_F(newTexture(this, false, mipLevelCount, m_flags.testFlag(CubeMap) ? 6 : 1, sampleDesc.Count));
+
+ owns = false;
+ QRHI_RES_RHI(QRhiD3D11);
+ rhiD->registerResource(this);
+ return true;
+}
+
+const QRhiNativeHandles *QD3D11Texture::nativeHandles()
+{
+ return &nativeHandlesStruct;
+}
+
+QD3D11Sampler::QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+{
+}
+
+QD3D11Sampler::~QD3D11Sampler()
+{
+ release();
+}
+
+void QD3D11Sampler::release()
+{
+ if (!samplerState)
+ return;
+
+ samplerState->Release();
+ samplerState = nullptr;
+
+ QRHI_RES_RHI(QRhiD3D11);
+ rhiD->unregisterResource(this);
+}
+
+static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
+{
+ if (minFilter == QRhiSampler::Nearest) {
+ if (magFilter == QRhiSampler::Nearest) {
+ if (mipFilter == QRhiSampler::Linear)
+ return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
+ else
+ return D3D11_FILTER_MIN_MAG_MIP_POINT;
+ } else {
+ if (mipFilter == QRhiSampler::Linear)
+ return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
+ else
+ return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
+ }
+ } else {
+ if (magFilter == QRhiSampler::Nearest) {
+ if (mipFilter == QRhiSampler::Linear)
+ return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
+ else
+ return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
+ } else {
+ if (mipFilter == QRhiSampler::Linear)
+ return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ else
+ return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
+ }
+ }
+
+ Q_UNREACHABLE();
+ return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+}
+
+static inline D3D11_TEXTURE_ADDRESS_MODE toD3DAddressMode(QRhiSampler::AddressMode m)
+{
+ switch (m) {
+ case QRhiSampler::Repeat:
+ return D3D11_TEXTURE_ADDRESS_WRAP;
+ case QRhiSampler::ClampToEdge:
+ return D3D11_TEXTURE_ADDRESS_CLAMP;
+ case QRhiSampler::Border:
+ return D3D11_TEXTURE_ADDRESS_BORDER;
+ case QRhiSampler::Mirror:
+ return D3D11_TEXTURE_ADDRESS_MIRROR;
+ case QRhiSampler::MirrorOnce:
+ return D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;
+ default:
+ Q_UNREACHABLE();
+ return D3D11_TEXTURE_ADDRESS_CLAMP;
+ }
+}
+
+static inline D3D11_COMPARISON_FUNC toD3DTextureComparisonFunc(QRhiSampler::CompareOp op)
+{
+ switch (op) {
+ case QRhiSampler::Never:
+ return D3D11_COMPARISON_NEVER;
+ case QRhiSampler::Less:
+ return D3D11_COMPARISON_LESS;
+ case QRhiSampler::Equal:
+ return D3D11_COMPARISON_EQUAL;
+ case QRhiSampler::LessOrEqual:
+ return D3D11_COMPARISON_LESS_EQUAL;
+ case QRhiSampler::Greater:
+ return D3D11_COMPARISON_GREATER;
+ case QRhiSampler::NotEqual:
+ return D3D11_COMPARISON_NOT_EQUAL;
+ case QRhiSampler::GreaterOrEqual:
+ return D3D11_COMPARISON_GREATER_EQUAL;
+ case QRhiSampler::Always:
+ return D3D11_COMPARISON_ALWAYS;
+ default:
+ Q_UNREACHABLE();
+ return D3D11_COMPARISON_NEVER;
+ }
+}
+
+bool QD3D11Sampler::build()
+{
+ if (samplerState)
+ release();
+
+ D3D11_SAMPLER_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
+ if (m_compareOp != Never)
+ desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
+ desc.AddressU = toD3DAddressMode(m_addressU);
+ desc.AddressV = toD3DAddressMode(m_addressV);
+ desc.AddressW = toD3DAddressMode(m_addressW);
+ desc.MaxAnisotropy = 1.0f;
+ desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
+ desc.MaxLOD = m_mipmapMode == None ? 0.0f : 1000.0f;
+
+ QRHI_RES_RHI(QRhiD3D11);
+ HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
+ if (FAILED(hr)) {
+ qWarning("Failed to create sampler state: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+// dummy, no Vulkan-style RenderPass+Framebuffer concept here
+QD3D11RenderPassDescriptor::QD3D11RenderPassDescriptor(QRhiImplementation *rhi)
+ : QRhiRenderPassDescriptor(rhi)
+{
+}
+
+QD3D11RenderPassDescriptor::~QD3D11RenderPassDescriptor()
+{
+ release();
+}
+
+void QD3D11RenderPassDescriptor::release()
+{
+ // nothing to do here
+}
+
+QD3D11ReferenceRenderTarget::QD3D11ReferenceRenderTarget(QRhiImplementation *rhi)
+ : QRhiRenderTarget(rhi),
+ d(rhi)
+{
+}
+
+QD3D11ReferenceRenderTarget::~QD3D11ReferenceRenderTarget()
+{
+ release();
+}
+
+void QD3D11ReferenceRenderTarget::release()
+{
+ // nothing to do here
+}
+
+QSize QD3D11ReferenceRenderTarget::pixelSize() const
+{
+ return d.pixelSize;
+}
+
+float QD3D11ReferenceRenderTarget::devicePixelRatio() const
+{
+ return d.dpr;
+}
+
+int QD3D11ReferenceRenderTarget::sampleCount() const
+{
+ return d.sampleCount;
+}
+
+QD3D11TextureRenderTarget::QD3D11TextureRenderTarget(QRhiImplementation *rhi,
+ const QRhiTextureRenderTargetDescription &desc,
+ Flags flags)
+ : QRhiTextureRenderTarget(rhi, desc, flags),
+ d(rhi)
+{
+ for (int i = 0; i < QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS; ++i) {
+ ownsRtv[i] = false;
+ rtv[i] = nullptr;
+ }
+}
+
+QD3D11TextureRenderTarget::~QD3D11TextureRenderTarget()
+{
+ release();
+}
+
+void QD3D11TextureRenderTarget::release()
+{
+ QRHI_RES_RHI(QRhiD3D11);
+
+ if (!rtv[0] && !dsv)
+ return;
+
+ if (dsv) {
+ if (ownsDsv)
+ dsv->Release();
+ dsv = nullptr;
+ }
+
+ for (int i = 0; i < QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS; ++i) {
+ if (rtv[i]) {
+ if (ownsRtv[i])
+ rtv[i]->Release();
+ rtv[i] = nullptr;
+ }
+ }
+
+ rhiD->unregisterResource(this);
+}
+
+QRhiRenderPassDescriptor *QD3D11TextureRenderTarget::newCompatibleRenderPassDescriptor()
+{
+ return new QD3D11RenderPassDescriptor(m_rhi);
+}
+
+bool QD3D11TextureRenderTarget::build()
+{
+ if (rtv[0] || dsv)
+ release();
+
+ const QVector<QRhiColorAttachment> colorAttachments = m_desc.colorAttachments();
+ Q_ASSERT(!colorAttachments.isEmpty() || m_desc.depthTexture());
+ Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
+ const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
+
+ QRHI_RES_RHI(QRhiD3D11);
+
+ d.colorAttCount = colorAttachments.count();
+ for (int i = 0; i < d.colorAttCount; ++i) {
+ QRhiTexture *texture = colorAttachments[i].texture();
+ QRhiRenderBuffer *rb = colorAttachments[i].renderBuffer();
+ Q_ASSERT(texture || rb);
+ if (texture) {
+ QD3D11Texture *texD = QRHI_RES(QD3D11Texture, texture);
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ memset(&rtvDesc, 0, sizeof(rtvDesc));
+ rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
+ if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = colorAttachments[i].level();
+ rtvDesc.Texture2DArray.FirstArraySlice = colorAttachments[i].layer();
+ rtvDesc.Texture2DArray.ArraySize = 1;
+ } else {
+ if (texD->sampleDesc.Count > 1) {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+ } else {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = colorAttachments[i].level();
+ }
+ }
+ HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->tex, &rtvDesc, &rtv[i]);
+ if (FAILED(hr)) {
+ qWarning("Failed to create rtv: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ ownsRtv[i] = true;
+ if (i == 0) {
+ d.pixelSize = texD->pixelSize();
+ d.sampleCount = texD->sampleDesc.Count;
+ }
+ } else if (rb) {
+ QD3D11RenderBuffer *rbD = QRHI_RES(QD3D11RenderBuffer, rb);
+ ownsRtv[i] = false;
+ rtv[i] = rbD->rtv;
+ if (i == 0) {
+ d.pixelSize = rbD->pixelSize();
+ d.sampleCount = rbD->sampleDesc.Count;
+ }
+ }
+ }
+ d.dpr = 1;
+
+ if (hasDepthStencil) {
+ if (m_desc.depthTexture()) {
+ ownsDsv = true;
+ QD3D11Texture *depthTexD = QRHI_RES(QD3D11Texture, m_desc.depthTexture());
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ memset(&dsvDesc, 0, sizeof(dsvDesc));
+ dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
+ dsvDesc.ViewDimension = depthTexD->sampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
+ : D3D11_DSV_DIMENSION_TEXTURE2D;
+ HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
+ if (FAILED(hr)) {
+ qWarning("Failed to create dsv: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ if (d.colorAttCount == 0) {
+ d.pixelSize = depthTexD->pixelSize();
+ d.sampleCount = depthTexD->sampleDesc.Count;
+ }
+ } else {
+ ownsDsv = false;
+ QD3D11RenderBuffer *depthRbD = QRHI_RES(QD3D11RenderBuffer, m_desc.depthStencilBuffer());
+ dsv = depthRbD->dsv;
+ if (d.colorAttCount == 0) {
+ d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
+ d.sampleCount = depthRbD->sampleDesc.Count;
+ }
+ }
+ d.dsAttCount = 1;
+ } else {
+ d.dsAttCount = 0;
+ }
+
+ for (int i = 0; i < QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS; ++i)
+ d.rtv[i] = i < d.colorAttCount ? rtv[i] : nullptr;
+
+ d.dsv = dsv;
+ d.rp = QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
+
+ rhiD->registerResource(this);
+ return true;
+}
+
+QSize QD3D11TextureRenderTarget::pixelSize() const
+{
+ return d.pixelSize;
+}
+
+float QD3D11TextureRenderTarget::devicePixelRatio() const
+{
+ return d.dpr;
+}
+
+int QD3D11TextureRenderTarget::sampleCount() const
+{
+ return d.sampleCount;
+}
+
+QD3D11ShaderResourceBindings::QD3D11ShaderResourceBindings(QRhiImplementation *rhi)
+ : QRhiShaderResourceBindings(rhi)
+{
+}
+
+QD3D11ShaderResourceBindings::~QD3D11ShaderResourceBindings()
+{
+ release();
+}
+
+void QD3D11ShaderResourceBindings::release()
+{
+ sortedBindings.clear();
+}
+
+bool QD3D11ShaderResourceBindings::build()
+{
+ if (!sortedBindings.isEmpty())
+ release();
+
+ sortedBindings = m_bindings;
+ std::sort(sortedBindings.begin(), sortedBindings.end(),
+ [](const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
+ {
+ return QRhiShaderResourceBindingPrivate::get(&a)->binding < QRhiShaderResourceBindingPrivate::get(&b)->binding;
+ });
+
+ boundResourceData.resize(sortedBindings.count());
+
+ QRHI_RES_RHI(QRhiD3D11);
+ rhiD->updateShaderResourceBindings(this);
+
+ generation += 1;
+ return true;
+}
+
+QD3D11GraphicsPipeline::QD3D11GraphicsPipeline(QRhiImplementation *rhi)
+ : QRhiGraphicsPipeline(rhi)
+{
+}
+
+QD3D11GraphicsPipeline::~QD3D11GraphicsPipeline()
+{
+ release();
+}
+
+void QD3D11GraphicsPipeline::release()
+{
+ QRHI_RES_RHI(QRhiD3D11);
+
+ if (!dsState)
+ return;
+
+ dsState->Release();
+ dsState = nullptr;
+
+ if (blendState) {
+ blendState->Release();
+ blendState = nullptr;
+ }
+
+ if (inputLayout) {
+ inputLayout->Release();
+ inputLayout = nullptr;
+ }
+
+ if (rastState) {
+ rastState->Release();
+ rastState = nullptr;
+ }
+
+ if (vs) {
+ vs->Release();
+ vs = nullptr;
+ }
+
+ if (fs) {
+ fs->Release();
+ fs = nullptr;
+ }
+
+ rhiD->unregisterResource(this);
+}
+
+static inline D3D11_CULL_MODE toD3DCullMode(QRhiGraphicsPipeline::CullMode c)
+{
+ switch (c) {
+ case QRhiGraphicsPipeline::None:
+ return D3D11_CULL_NONE;
+ case QRhiGraphicsPipeline::Front:
+ return D3D11_CULL_FRONT;
+ case QRhiGraphicsPipeline::Back:
+ return D3D11_CULL_BACK;
+ default:
+ Q_UNREACHABLE();
+ return D3D11_CULL_NONE;
+ }
+}
+
+static inline D3D11_COMPARISON_FUNC toD3DCompareOp(QRhiGraphicsPipeline::CompareOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::Never:
+ return D3D11_COMPARISON_NEVER;
+ case QRhiGraphicsPipeline::Less:
+ return D3D11_COMPARISON_LESS;
+ case QRhiGraphicsPipeline::Equal:
+ return D3D11_COMPARISON_EQUAL;
+ case QRhiGraphicsPipeline::LessOrEqual:
+ return D3D11_COMPARISON_LESS_EQUAL;
+ case QRhiGraphicsPipeline::Greater:
+ return D3D11_COMPARISON_GREATER;
+ case QRhiGraphicsPipeline::NotEqual:
+ return D3D11_COMPARISON_NOT_EQUAL;
+ case QRhiGraphicsPipeline::GreaterOrEqual:
+ return D3D11_COMPARISON_GREATER_EQUAL;
+ case QRhiGraphicsPipeline::Always:
+ return D3D11_COMPARISON_ALWAYS;
+ default:
+ Q_UNREACHABLE();
+ return D3D11_COMPARISON_ALWAYS;
+ }
+}
+
+static inline D3D11_STENCIL_OP toD3DStencilOp(QRhiGraphicsPipeline::StencilOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::StencilZero:
+ return D3D11_STENCIL_OP_ZERO;
+ case QRhiGraphicsPipeline::Keep:
+ return D3D11_STENCIL_OP_KEEP;
+ case QRhiGraphicsPipeline::Replace:
+ return D3D11_STENCIL_OP_REPLACE;
+ case QRhiGraphicsPipeline::IncrementAndClamp:
+ return D3D11_STENCIL_OP_INCR_SAT;
+ case QRhiGraphicsPipeline::DecrementAndClamp:
+ return D3D11_STENCIL_OP_DECR_SAT;
+ case QRhiGraphicsPipeline::Invert:
+ return D3D11_STENCIL_OP_INVERT;
+ case QRhiGraphicsPipeline::IncrementAndWrap:
+ return D3D11_STENCIL_OP_INCR;
+ case QRhiGraphicsPipeline::DecrementAndWrap:
+ return D3D11_STENCIL_OP_DECR;
+ default:
+ Q_UNREACHABLE();
+ return D3D11_STENCIL_OP_KEEP;
+ }
+}
+
+static inline DXGI_FORMAT toD3DAttributeFormat(QRhiVertexInputAttribute::Format format)
+{
+ switch (format) {
+ case QRhiVertexInputAttribute::Float4:
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ case QRhiVertexInputAttribute::Float3:
+ return DXGI_FORMAT_R32G32B32_FLOAT;
+ case QRhiVertexInputAttribute::Float2:
+ return DXGI_FORMAT_R32G32_FLOAT;
+ case QRhiVertexInputAttribute::Float:
+ return DXGI_FORMAT_R32_FLOAT;
+ case QRhiVertexInputAttribute::UNormByte4:
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+ case QRhiVertexInputAttribute::UNormByte2:
+ return DXGI_FORMAT_R8G8_UNORM;
+ case QRhiVertexInputAttribute::UNormByte:
+ return DXGI_FORMAT_R8_UNORM;
+ default:
+ Q_UNREACHABLE();
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ }
+}
+
+static inline D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topology t)
+{
+ switch (t) {
+ case QRhiGraphicsPipeline::Triangles:
+ return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ case QRhiGraphicsPipeline::TriangleStrip:
+ return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+ case QRhiGraphicsPipeline::Lines:
+ return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
+ case QRhiGraphicsPipeline::LineStrip:
+ return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
+ case QRhiGraphicsPipeline::Points:
+ return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
+ default:
+ Q_UNREACHABLE();
+ return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ }
+}
+
+static inline uint toD3DColorWriteMask(QRhiGraphicsPipeline::ColorMask c)
+{
+ uint f = 0;
+ if (c.testFlag(QRhiGraphicsPipeline::R))
+ f |= D3D11_COLOR_WRITE_ENABLE_RED;
+ if (c.testFlag(QRhiGraphicsPipeline::G))
+ f |= D3D11_COLOR_WRITE_ENABLE_GREEN;
+ if (c.testFlag(QRhiGraphicsPipeline::B))
+ f |= D3D11_COLOR_WRITE_ENABLE_BLUE;
+ if (c.testFlag(QRhiGraphicsPipeline::A))
+ f |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
+ return f;
+}
+
+static inline D3D11_BLEND toD3DBlendFactor(QRhiGraphicsPipeline::BlendFactor f)
+{
+ switch (f) {
+ case QRhiGraphicsPipeline::Zero:
+ return D3D11_BLEND_ZERO;
+ case QRhiGraphicsPipeline::One:
+ return D3D11_BLEND_ONE;
+ case QRhiGraphicsPipeline::SrcColor:
+ return D3D11_BLEND_SRC_COLOR;
+ case QRhiGraphicsPipeline::OneMinusSrcColor:
+ return D3D11_BLEND_INV_SRC_COLOR;
+ case QRhiGraphicsPipeline::DstColor:
+ return D3D11_BLEND_DEST_COLOR;
+ case QRhiGraphicsPipeline::OneMinusDstColor:
+ return D3D11_BLEND_INV_DEST_COLOR;
+ case QRhiGraphicsPipeline::SrcAlpha:
+ return D3D11_BLEND_SRC_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusSrcAlpha:
+ return D3D11_BLEND_INV_SRC_ALPHA;
+ case QRhiGraphicsPipeline::DstAlpha:
+ return D3D11_BLEND_DEST_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusDstAlpha:
+ return D3D11_BLEND_INV_DEST_ALPHA;
+ case QRhiGraphicsPipeline::ConstantColor:
+ Q_FALLTHROUGH();
+ case QRhiGraphicsPipeline::ConstantAlpha:
+ return D3D11_BLEND_BLEND_FACTOR;
+ case QRhiGraphicsPipeline::OneMinusConstantColor:
+ Q_FALLTHROUGH();
+ case QRhiGraphicsPipeline::OneMinusConstantAlpha:
+ return D3D11_BLEND_INV_BLEND_FACTOR;
+ case QRhiGraphicsPipeline::SrcAlphaSaturate:
+ return D3D11_BLEND_SRC_ALPHA_SAT;
+ case QRhiGraphicsPipeline::Src1Color:
+ return D3D11_BLEND_SRC1_COLOR;
+ case QRhiGraphicsPipeline::OneMinusSrc1Color:
+ return D3D11_BLEND_INV_SRC1_COLOR;
+ case QRhiGraphicsPipeline::Src1Alpha:
+ return D3D11_BLEND_SRC1_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
+ return D3D11_BLEND_INV_SRC1_ALPHA;
+ default:
+ Q_UNREACHABLE();
+ return D3D11_BLEND_ZERO;
+ }
+}
+
+static inline D3D11_BLEND_OP toD3DBlendOp(QRhiGraphicsPipeline::BlendOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::Add:
+ return D3D11_BLEND_OP_ADD;
+ case QRhiGraphicsPipeline::Subtract:
+ return D3D11_BLEND_OP_SUBTRACT;
+ case QRhiGraphicsPipeline::ReverseSubtract:
+ return D3D11_BLEND_OP_REV_SUBTRACT;
+ case QRhiGraphicsPipeline::Min:
+ return D3D11_BLEND_OP_MIN;
+ case QRhiGraphicsPipeline::Max:
+ return D3D11_BLEND_OP_MAX;
+ default:
+ Q_UNREACHABLE();
+ return D3D11_BLEND_OP_ADD;
+ }
+}
+
+static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error)
+{
+ QShaderCode dxbc = shader.shader({ QShader::DxbcShader, 50, shaderVariant });
+ if (!dxbc.shader().isEmpty())
+ return dxbc.shader();
+
+ QShaderCode hlslSource = shader.shader({ QShader::HlslShader, 50, shaderVariant });
+ if (hlslSource.shader().isEmpty()) {
+ qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader;
+ return QByteArray();
+ }
+
+ const char *target;
+ switch (shader.stage()) {
+ case QShader::VertexStage:
+ target = "vs_5_0";
+ break;
+ case QShader::TessellationControlStage:
+ target = "hs_5_0";
+ break;
+ case QShader::TessellationEvaluationStage:
+ target = "ds_5_0";
+ break;
+ case QShader::GeometryStage:
+ target = "gs_5_0";
+ break;
+ case QShader::FragmentStage:
+ target = "ps_5_0";
+ break;
+ case QShader::ComputeStage:
+ target = "cs_5_0";
+ break;
+ default:
+ Q_UNREACHABLE();
+ return QByteArray();
+ }
+
+ ID3DBlob *bytecode = nullptr;
+ ID3DBlob *errors = nullptr;
+ HRESULT hr = D3DCompile(hlslSource.shader().constData(), hlslSource.shader().size(),
+ nullptr, nullptr, nullptr,
+ hlslSource.entryPoint().constData(), target, 0, 0, &bytecode, &errors);
+ if (FAILED(hr) || !bytecode) {
+ qWarning("HLSL shader compilation failed: 0x%x", uint(hr));
+ if (errors) {
+ *error = QString::fromUtf8(static_cast<const char *>(errors->GetBufferPointer()),
+ errors->GetBufferSize());
+ errors->Release();
+ }
+ return QByteArray();
+ }
+
+ QByteArray result;
+ result.resize(bytecode->GetBufferSize());
+ memcpy(result.data(), bytecode->GetBufferPointer(), result.size());
+ bytecode->Release();
+ return result;
+}
+
+bool QD3D11GraphicsPipeline::build()
+{
+ if (dsState)
+ release();
+
+ QRHI_RES_RHI(QRhiD3D11);
+
+ D3D11_RASTERIZER_DESC rastDesc;
+ memset(&rastDesc, 0, sizeof(rastDesc));
+ rastDesc.FillMode = D3D11_FILL_SOLID;
+ rastDesc.CullMode = toD3DCullMode(m_cullMode);
+ rastDesc.FrontCounterClockwise = m_frontFace == CCW;
+ rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
+ rastDesc.MultisampleEnable = rhiD->effectiveSampleCount(m_sampleCount).Count > 1;
+ HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
+ if (FAILED(hr)) {
+ qWarning("Failed to create rasterizer state: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+
+ D3D11_DEPTH_STENCIL_DESC dsDesc;
+ memset(&dsDesc, 0, sizeof(dsDesc));
+ dsDesc.DepthEnable = m_depthTest;
+ dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
+ dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
+ dsDesc.StencilEnable = m_stencilTest;
+ if (m_stencilTest) {
+ dsDesc.StencilReadMask = m_stencilReadMask;
+ dsDesc.StencilWriteMask = m_stencilWriteMask;
+ dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
+ dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
+ dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
+ dsDesc.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
+ dsDesc.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
+ dsDesc.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
+ dsDesc.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
+ dsDesc.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
+ }
+ hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
+ if (FAILED(hr)) {
+ qWarning("Failed to create depth-stencil state: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+
+ D3D11_BLEND_DESC blendDesc;
+ memset(&blendDesc, 0, sizeof(blendDesc));
+ blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
+ for (int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
+ const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
+ D3D11_RENDER_TARGET_BLEND_DESC blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.BlendEnable = b.enable;
+ blend.SrcBlend = toD3DBlendFactor(b.srcColor);
+ blend.DestBlend = toD3DBlendFactor(b.dstColor);
+ blend.BlendOp = toD3DBlendOp(b.opColor);
+ blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha);
+ blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha);
+ blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
+ blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
+ blendDesc.RenderTarget[i] = blend;
+ }
+ if (m_targetBlends.isEmpty()) {
+ D3D11_RENDER_TARGET_BLEND_DESC blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
+ blendDesc.RenderTarget[0] = blend;
+ }
+ hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
+ if (FAILED(hr)) {
+ qWarning("Failed to create blend state: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+
+ QByteArray vsByteCode;
+ for (const QRhiGraphicsShaderStage &shaderStage : qAsConst(m_shaderStages)) {
+ QString error;
+ QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error);
+ if (bytecode.isEmpty()) {
+ qWarning("HLSL shader compilation failed: %s", qPrintable(error));
+ return false;
+ }
+ switch (shaderStage.type()) {
+ case QRhiGraphicsShaderStage::Vertex:
+ hr = rhiD->dev->CreateVertexShader(bytecode.constData(), bytecode.size(), nullptr, &vs);
+ if (FAILED(hr)) {
+ qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ vsByteCode = bytecode;
+ break;
+ case QRhiGraphicsShaderStage::Fragment:
+ hr = rhiD->dev->CreatePixelShader(bytecode.constData(), bytecode.size(), nullptr, &fs);
+ if (FAILED(hr)) {
+ qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ d3dTopology = toD3DTopology(m_topology);
+
+ if (!vsByteCode.isEmpty()) {
+ const QVector<QRhiVertexInputBinding> bindings = m_vertexInputLayout.bindings();
+ const QVector<QRhiVertexInputAttribute> attributes = m_vertexInputLayout.attributes();
+ QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> inputDescs;
+ for (const QRhiVertexInputAttribute &attribute : attributes) {
+ D3D11_INPUT_ELEMENT_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ // the output from SPIRV-Cross uses TEXCOORD<location> as the semantic
+ desc.SemanticName = "TEXCOORD";
+ desc.SemanticIndex = attribute.location();
+ desc.Format = toD3DAttributeFormat(attribute.format());
+ desc.InputSlot = attribute.binding();
+ desc.AlignedByteOffset = attribute.offset();
+ const QRhiVertexInputBinding &binding(bindings[attribute.binding()]);
+ if (binding.classification() == QRhiVertexInputBinding::PerInstance) {
+ desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
+ desc.InstanceDataStepRate = binding.instanceStepRate();
+ } else {
+ desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
+ }
+ inputDescs.append(desc);
+ }
+ hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), inputDescs.count(), vsByteCode, vsByteCode.size(), &inputLayout);
+ if (FAILED(hr)) {
+ qWarning("Failed to create input layout: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ }
+
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QD3D11CommandBuffer::QD3D11CommandBuffer(QRhiImplementation *rhi)
+ : QRhiCommandBuffer(rhi)
+{
+ resetState();
+}
+
+QD3D11CommandBuffer::~QD3D11CommandBuffer()
+{
+ release();
+}
+
+void QD3D11CommandBuffer::release()
+{
+ // nothing to do here
+}
+
+QD3D11SwapChain::QD3D11SwapChain(QRhiImplementation *rhi)
+ : QRhiSwapChain(rhi),
+ rt(rhi),
+ cb(rhi)
+{
+ for (int i = 0; i < BUFFER_COUNT; ++i) {
+ tex[i] = nullptr;
+ rtv[i] = nullptr;
+ msaaTex[i] = nullptr;
+ msaaRtv[i] = nullptr;
+ timestampActive[i] = false;
+ timestampDisjointQuery[i] = nullptr;
+ timestampQuery[2 * i] = nullptr;
+ timestampQuery[2 * i + 1] = nullptr;
+ }
+}
+
+QD3D11SwapChain::~QD3D11SwapChain()
+{
+ release();
+}
+
+void QD3D11SwapChain::releaseBuffers()
+{
+ for (int i = 0; i < BUFFER_COUNT; ++i) {
+ if (rtv[i]) {
+ rtv[i]->Release();
+ rtv[i] = nullptr;
+ }
+ if (tex[i]) {
+ tex[i]->Release();
+ tex[i] = nullptr;
+ }
+ if (msaaRtv[i]) {
+ msaaRtv[i]->Release();
+ msaaRtv[i] = nullptr;
+ }
+ if (msaaTex[i]) {
+ msaaTex[i]->Release();
+ msaaTex[i] = nullptr;
+ }
+ }
+}
+
+void QD3D11SwapChain::release()
+{
+ if (!swapChain)
+ return;
+
+ releaseBuffers();
+
+ for (int i = 0; i < BUFFER_COUNT; ++i) {
+ if (timestampDisjointQuery[i]) {
+ timestampDisjointQuery[i]->Release();
+ timestampDisjointQuery[i] = nullptr;
+ }
+ for (int j = 0; j < 2; ++j) {
+ const int idx = BUFFER_COUNT * i + j;
+ if (timestampQuery[idx]) {
+ timestampQuery[idx]->Release();
+ timestampQuery[idx] = nullptr;
+ }
+ }
+ }
+
+ swapChain->Release();
+ swapChain = nullptr;
+
+ QRHI_PROF;
+ QRHI_PROF_F(releaseSwapChain(this));
+
+ QRHI_RES_RHI(QRhiD3D11);
+ rhiD->unregisterResource(this);
+}
+
+QRhiCommandBuffer *QD3D11SwapChain::currentFrameCommandBuffer()
+{
+ return &cb;
+}
+
+QRhiRenderTarget *QD3D11SwapChain::currentFrameRenderTarget()
+{
+ return &rt;
+}
+
+QSize QD3D11SwapChain::surfacePixelSize()
+{
+ Q_ASSERT(m_window);
+ return m_window->size() * m_window->devicePixelRatio();
+}
+
+QRhiRenderPassDescriptor *QD3D11SwapChain::newCompatibleRenderPassDescriptor()
+{
+ return new QD3D11RenderPassDescriptor(m_rhi);
+}
+
+bool QD3D11SwapChain::newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
+ ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const
+{
+ D3D11_TEXTURE2D_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.Width = size.width();
+ desc.Height = size.height();
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = format;
+ desc.SampleDesc = sampleDesc;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_RENDER_TARGET;
+
+ QRHI_RES_RHI(QRhiD3D11);
+ HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, tex);
+ if (FAILED(hr)) {
+ qWarning("Failed to create color buffer texture: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ memset(&rtvDesc, 0, sizeof(rtvDesc));
+ rtvDesc.Format = format;
+ rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
+ hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
+ if (FAILED(hr)) {
+ qWarning("Failed to create color buffer rtv: %s", qPrintable(comErrorMessage(hr)));
+ (*tex)->Release();
+ *tex = nullptr;
+ return false;
+ }
+
+ return true;
+}
+
+bool QD3D11SwapChain::buildOrResize()
+{
+ // Can be called multiple times due to window resizes - that is not the
+ // same as a simple release+build (as with other resources). Just need to
+ // resize the buffers then.
+
+ const bool needsRegistration = !window || window != m_window;
+
+ // except if the window actually changes
+ if (window && window != m_window)
+ release();
+
+ window = m_window;
+ m_currentPixelSize = surfacePixelSize();
+ pixelSize = m_currentPixelSize;
+
+ if (pixelSize.isEmpty())
+ return false;
+
+ colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+ const DXGI_FORMAT srgbAdjustedFormat = m_flags.testFlag(sRGB) ?
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ const UINT swapChainFlags = 0;
+
+ QRHI_RES_RHI(QRhiD3D11);
+ if (!swapChain) {
+ HWND hwnd = reinterpret_cast<HWND>(window->winId());
+ sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
+
+ // We use FLIP_DISCARD which implies a buffer count of 2 (as opposed to the
+ // old DISCARD with back buffer count == 1). This makes no difference for
+ // the rest of the stuff except that automatic MSAA is unsupported and
+ // needs to be implemented via a custom multisample render target and an
+ // explicit resolve.
+
+ HRESULT hr;
+ if (rhiD->hasDxgi2) {
+ DXGI_SWAP_CHAIN_DESC1 desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.Width = pixelSize.width();
+ desc.Height = pixelSize.height();
+ desc.Format = colorFormat;
+ desc.SampleDesc.Count = 1;
+ desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ desc.BufferCount = BUFFER_COUNT;
+ desc.Scaling = DXGI_SCALING_STRETCH;
+ desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ if (m_flags.testFlag(SurfaceHasPreMulAlpha))
+ desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
+ else if (m_flags.testFlag(SurfaceHasNonPreMulAlpha))
+ desc.AlphaMode = DXGI_ALPHA_MODE_STRAIGHT;
+ desc.Flags = swapChainFlags;
+
+ IDXGISwapChain1 *sc1;
+ hr = static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory)->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
+ nullptr, nullptr, &sc1);
+ if (SUCCEEDED(hr))
+ swapChain = sc1;
+ } else {
+ // Windows 7
+ DXGI_SWAP_CHAIN_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.BufferDesc.Width = pixelSize.width();
+ desc.BufferDesc.Height = pixelSize.height();
+ desc.BufferDesc.RefreshRate.Numerator = 60;
+ desc.BufferDesc.RefreshRate.Denominator = 1;
+ desc.BufferDesc.Format = colorFormat;
+ desc.SampleDesc.Count = 1;
+ desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ desc.BufferCount = BUFFER_COUNT;
+ desc.OutputWindow = hwnd;
+ desc.Windowed = true;
+ desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ desc.Flags = swapChainFlags;
+
+ hr = rhiD->dxgiFactory->CreateSwapChain(rhiD->dev, &desc, &swapChain);
+ }
+ if (FAILED(hr)) {
+ qWarning("Failed to create D3D11 swapchain: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ } else {
+ releaseBuffers();
+ HRESULT hr = swapChain->ResizeBuffers(2, pixelSize.width(), pixelSize.height(), colorFormat, swapChainFlags);
+ if (FAILED(hr)) {
+ qWarning("Failed to resize D3D11 swapchain: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ }
+
+ for (int i = 0; i < BUFFER_COUNT; ++i) {
+ HRESULT hr = swapChain->GetBuffer(0, IID_ID3D11Texture2D, reinterpret_cast<void **>(&tex[i]));
+ if (FAILED(hr)) {
+ qWarning("Failed to query swapchain buffer %d: %s", i, qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ memset(&rtvDesc, 0, sizeof(rtvDesc));
+ rtvDesc.Format = srgbAdjustedFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ hr = rhiD->dev->CreateRenderTargetView(tex[i], &rtvDesc, &rtv[i]);
+ if (FAILED(hr)) {
+ qWarning("Failed to create rtv for swapchain buffer %d: %s", i, qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ if (sampleDesc.Count > 1) {
+ if (!newColorBuffer(pixelSize, srgbAdjustedFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
+ return false;
+ }
+ }
+
+ if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
+ qWarning("Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
+ m_depthStencil->sampleCount(), m_sampleCount);
+ }
+ if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
+ qWarning("Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
+ m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
+ pixelSize.width(), pixelSize.height());
+ }
+
+ currentFrameSlot = 0;
+ frameCount = 0;
+ ds = m_depthStencil ? QRHI_RES(QD3D11RenderBuffer, m_depthStencil) : nullptr;
+ swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
+
+ QD3D11ReferenceRenderTarget *rtD = QRHI_RES(QD3D11ReferenceRenderTarget, &rt);
+ rtD->d.rp = QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
+ rtD->d.pixelSize = pixelSize;
+ rtD->d.dpr = window->devicePixelRatio();
+ rtD->d.sampleCount = sampleDesc.Count;
+ rtD->d.colorAttCount = 1;
+ rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
+
+ QRHI_PROF;
+ QRHI_PROF_F(resizeSwapChain(this, BUFFER_COUNT, sampleDesc.Count > 1 ? BUFFER_COUNT : 0, sampleDesc.Count));
+ if (rhiP) {
+ D3D11_QUERY_DESC queryDesc;
+ memset(&queryDesc, 0, sizeof(queryDesc));
+ for (int i = 0; i < BUFFER_COUNT; ++i) {
+ if (!timestampDisjointQuery[i]) {
+ queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
+ HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &timestampDisjointQuery[i]);
+ if (FAILED(hr)) {
+ qWarning("Failed to create timestamp disjoint query: %s", qPrintable(comErrorMessage(hr)));
+ break;
+ }
+ }
+ queryDesc.Query = D3D11_QUERY_TIMESTAMP;
+ for (int j = 0; j < 2; ++j) {
+ const int idx = BUFFER_COUNT * i + j; // one pair per buffer (frame)
+ if (!timestampQuery[idx]) {
+ HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &timestampQuery[idx]);
+ if (FAILED(hr)) {
+ qWarning("Failed to create timestamp query: %s", qPrintable(comErrorMessage(hr)));
+ break;
+ }
+ }
+ }
+ }
+ // timestamp queries are optional so we can go on even if they failed
+ }
+
+ if (needsRegistration)
+ rhiD->registerResource(this);
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhid3d11_p.h b/src/gui/rhi/qrhid3d11_p.h
new file mode 100644
index 0000000000..3e2e492d9c
--- /dev/null
+++ b/src/gui/rhi/qrhid3d11_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHID3D11_H
+#define QRHID3D11_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qrhi_p.h>
+
+// no d3d includes here, to prevent precompiled header mess (due to this being
+// a public header)
+
+QT_BEGIN_NAMESPACE
+
+struct Q_GUI_EXPORT QRhiD3D11InitParams : public QRhiInitParams
+{
+ bool enableDebugLayer = false;
+};
+
+struct Q_GUI_EXPORT QRhiD3D11NativeHandles : public QRhiNativeHandles
+{
+ void *dev = nullptr;
+ void *context = nullptr;
+};
+
+struct Q_GUI_EXPORT QRhiD3D11TextureNativeHandles : public QRhiNativeHandles
+{
+ void *texture = nullptr; // ID3D11Texture2D*
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
new file mode 100644
index 0000000000..fd5247b0b4
--- /dev/null
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -0,0 +1,624 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHID3D11_P_H
+#define QRHID3D11_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrhid3d11_p.h"
+#include "qrhi_p_p.h"
+#include "qshaderdescription_p.h"
+#include <QWindow>
+
+#include <d3d11_1.h>
+#include <dxgi1_3.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QD3D11Buffer : public QRhiBuffer
+{
+ QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
+ ~QD3D11Buffer();
+ void release() override;
+ bool build() override;
+
+ ID3D11Buffer *buffer = nullptr;
+ QByteArray dynBuf;
+ bool hasPendingDynamicUpdates = false;
+ uint generation = 0;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11RenderBuffer : public QRhiRenderBuffer
+{
+ QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags);
+ ~QD3D11RenderBuffer();
+ void release() override;
+ bool build() override;
+ QRhiTexture::Format backingFormat() const override;
+
+ ID3D11Texture2D *tex = nullptr;
+ ID3D11DepthStencilView *dsv = nullptr;
+ ID3D11RenderTargetView *rtv = nullptr;
+ DXGI_FORMAT dxgiFormat;
+ DXGI_SAMPLE_DESC sampleDesc;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11Texture : public QRhiTexture
+{
+ QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ int sampleCount, Flags flags);
+ ~QD3D11Texture();
+ void release() override;
+ bool build() override;
+ bool buildFrom(const QRhiNativeHandles *src) override;
+ const QRhiNativeHandles *nativeHandles() override;
+
+ bool prepareBuild(QSize *adjustedSize = nullptr);
+ bool finishBuild();
+
+ ID3D11Texture2D *tex = nullptr;
+ bool owns = true;
+ ID3D11ShaderResourceView *srv = nullptr;
+ DXGI_FORMAT dxgiFormat;
+ uint mipLevelCount = 0;
+ DXGI_SAMPLE_DESC sampleDesc;
+ QRhiD3D11TextureNativeHandles nativeHandlesStruct;
+ uint generation = 0;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11Sampler : public QRhiSampler
+{
+ QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v);
+ ~QD3D11Sampler();
+ void release() override;
+ bool build() override;
+
+ ID3D11SamplerState *samplerState = nullptr;
+ uint generation = 0;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11RenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QD3D11RenderPassDescriptor(QRhiImplementation *rhi);
+ ~QD3D11RenderPassDescriptor();
+ void release() override;
+};
+
+struct QD3D11RenderTargetData
+{
+ QD3D11RenderTargetData(QRhiImplementation *)
+ {
+ for (int i = 0; i < MAX_COLOR_ATTACHMENTS; ++i)
+ rtv[i] = nullptr;
+ }
+
+ QD3D11RenderPassDescriptor *rp = nullptr;
+ QSize pixelSize;
+ float dpr = 1;
+ int sampleCount = 1;
+ int colorAttCount = 0;
+ int dsAttCount = 0;
+
+ static const int MAX_COLOR_ATTACHMENTS = 8;
+ ID3D11RenderTargetView *rtv[MAX_COLOR_ATTACHMENTS];
+ ID3D11DepthStencilView *dsv = nullptr;
+};
+
+struct QD3D11ReferenceRenderTarget : public QRhiRenderTarget
+{
+ QD3D11ReferenceRenderTarget(QRhiImplementation *rhi);
+ ~QD3D11ReferenceRenderTarget();
+ void release() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QD3D11RenderTargetData d;
+};
+
+struct QD3D11TextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
+ ~QD3D11TextureRenderTarget();
+ void release() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool build() override;
+
+ QD3D11RenderTargetData d;
+ bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
+ ID3D11RenderTargetView *rtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
+ bool ownsDsv = false;
+ ID3D11DepthStencilView *dsv = nullptr;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QD3D11ShaderResourceBindings(QRhiImplementation *rhi);
+ ~QD3D11ShaderResourceBindings();
+ void release() override;
+ bool build() override;
+
+ QVector<QRhiShaderResourceBinding> sortedBindings;
+ uint generation = 0;
+
+ // Keep track of the generation number of each referenced QRhi* to be able
+ // to detect that the batched bindings are out of date.
+ struct BoundUniformBufferData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundSampledTextureData {
+ quint64 texId;
+ uint texGeneration;
+ quint64 samplerId;
+ uint samplerGeneration;
+ };
+ struct BoundResourceData {
+ union {
+ BoundUniformBufferData ubuf;
+ BoundSampledTextureData stex;
+ };
+ };
+ QVector<BoundResourceData> boundResourceData;
+
+ QRhiBatchedBindings<ID3D11Buffer *> vsubufs;
+ QRhiBatchedBindings<UINT> vsubufoffsets;
+ QRhiBatchedBindings<UINT> vsubufsizes;
+
+ QRhiBatchedBindings<ID3D11Buffer *> fsubufs;
+ QRhiBatchedBindings<UINT> fsubufoffsets;
+ QRhiBatchedBindings<UINT> fsubufsizes;
+
+ QRhiBatchedBindings<ID3D11SamplerState *> vssamplers;
+ QRhiBatchedBindings<ID3D11ShaderResourceView *> vsshaderresources;
+
+ QRhiBatchedBindings<ID3D11SamplerState *> fssamplers;
+ QRhiBatchedBindings<ID3D11ShaderResourceView *> fsshaderresources;
+
+ friend class QRhiD3D11;
+};
+
+Q_DECLARE_TYPEINFO(QD3D11ShaderResourceBindings::BoundResourceData, Q_MOVABLE_TYPE);
+
+struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QD3D11GraphicsPipeline(QRhiImplementation *rhi);
+ ~QD3D11GraphicsPipeline();
+ void release() override;
+ bool build() override;
+
+ ID3D11DepthStencilState *dsState = nullptr;
+ ID3D11BlendState *blendState = nullptr;
+ ID3D11VertexShader *vs = nullptr;
+ ID3D11PixelShader *fs = nullptr;
+ ID3D11InputLayout *inputLayout = nullptr;
+ D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ ID3D11RasterizerState *rastState = nullptr;
+ uint generation = 0;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11SwapChain;
+
+struct QD3D11CommandBuffer : public QRhiCommandBuffer
+{
+ QD3D11CommandBuffer(QRhiImplementation *rhi);
+ ~QD3D11CommandBuffer();
+ void release() override;
+
+ struct Command {
+ enum Cmd {
+ SetRenderTarget,
+ Clear,
+ Viewport,
+ Scissor,
+ BindVertexBuffers,
+ BindIndexBuffer,
+ BindGraphicsPipeline,
+ BindShaderResources,
+ StencilRef,
+ BlendConstants,
+ Draw,
+ DrawIndexed,
+ UpdateSubRes,
+ CopySubRes,
+ ResolveSubRes,
+ GenMip,
+ DebugMarkBegin,
+ DebugMarkEnd,
+ DebugMarkMsg
+ };
+ enum ClearFlag { Color = 1, Depth = 2, Stencil = 4 };
+ Cmd cmd;
+
+ static const int MAX_UBUF_BINDINGS = 32; // should be D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT but 128 is a waste of space for our purposes
+
+ // QRhi*/QD3D11* references should be kept at minimum (so no
+ // QRhiTexture/Buffer/etc. pointers).
+ union {
+ struct {
+ QRhiRenderTarget *rt;
+ } setRenderTarget;
+ struct {
+ QRhiRenderTarget *rt;
+ int mask;
+ float c[4];
+ float d;
+ quint32 s;
+ } clear;
+ struct {
+ float x, y, w, h;
+ float d0, d1;
+ } viewport;
+ struct {
+ int x, y, w, h;
+ } scissor;
+ struct {
+ int startSlot;
+ int slotCount;
+ ID3D11Buffer *buffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ UINT offsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ UINT strides[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ } bindVertexBuffers;
+ struct {
+ ID3D11Buffer *buffer;
+ quint32 offset;
+ DXGI_FORMAT format;
+ } bindIndexBuffer;
+ struct {
+ QD3D11GraphicsPipeline *ps;
+ } bindGraphicsPipeline;
+ struct {
+ QD3D11ShaderResourceBindings *srb;
+ bool offsetOnlyChange;
+ int dynamicOffsetCount;
+ uint dynamicOffsetPairs[MAX_UBUF_BINDINGS * 2]; // binding, offsetInConstants
+ } bindShaderResources;
+ struct {
+ QD3D11GraphicsPipeline *ps;
+ quint32 ref;
+ } stencilRef;
+ struct {
+ QD3D11GraphicsPipeline *ps;
+ float c[4];
+ } blendConstants;
+ struct {
+ QD3D11GraphicsPipeline *ps;
+ quint32 vertexCount;
+ quint32 instanceCount;
+ quint32 firstVertex;
+ quint32 firstInstance;
+ } draw;
+ struct {
+ QD3D11GraphicsPipeline *ps;
+ quint32 indexCount;
+ quint32 instanceCount;
+ quint32 firstIndex;
+ qint32 vertexOffset;
+ quint32 firstInstance;
+ } drawIndexed;
+ struct {
+ ID3D11Resource *dst;
+ UINT dstSubRes;
+ bool hasDstBox;
+ D3D11_BOX dstBox;
+ const void *src; // must come from retain*()
+ UINT srcRowPitch;
+ } updateSubRes;
+ struct {
+ ID3D11Resource *dst;
+ UINT dstSubRes;
+ UINT dstX;
+ UINT dstY;
+ ID3D11Resource *src;
+ UINT srcSubRes;
+ bool hasSrcBox;
+ D3D11_BOX srcBox;
+ } copySubRes;
+ struct {
+ ID3D11Resource *dst;
+ UINT dstSubRes;
+ ID3D11Resource *src;
+ UINT srcSubRes;
+ DXGI_FORMAT format;
+ } resolveSubRes;
+ struct {
+ ID3D11ShaderResourceView *srv;
+ } genMip;
+ struct {
+ char s[64];
+ } debugMark;
+ } args;
+ };
+
+ QVector<Command> commands;
+ QRhiRenderTarget *currentTarget;
+ QRhiGraphicsPipeline *currentPipeline;
+ uint currentPipelineGeneration;
+ QRhiShaderResourceBindings *currentSrb;
+ uint currentSrbGeneration;
+ ID3D11Buffer *currentIndexBuffer;
+ quint32 currentIndexOffset;
+ DXGI_FORMAT currentIndexFormat;
+ ID3D11Buffer *currentVertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+
+ QVector<QByteArray> dataRetainPool;
+ QVector<QImage> imageRetainPool;
+
+ // relies heavily on implicit sharing (no copies of the actual data will be made)
+ const uchar *retainData(const QByteArray &data) {
+ dataRetainPool.append(data);
+ return reinterpret_cast<const uchar *>(dataRetainPool.constLast().constData());
+ }
+ const uchar *retainImage(const QImage &image) {
+ imageRetainPool.append(image);
+ return imageRetainPool.constLast().constBits();
+ }
+ void resetCommands() {
+ commands.clear();
+ dataRetainPool.clear();
+ imageRetainPool.clear();
+ }
+ void resetState() {
+ resetCommands();
+ currentTarget = nullptr;
+ resetCachedState();
+ }
+ void resetCachedState() {
+ currentPipeline = nullptr;
+ currentPipelineGeneration = 0;
+ currentSrb = nullptr;
+ currentSrbGeneration = 0;
+ currentIndexBuffer = nullptr;
+ currentIndexOffset = 0;
+ currentIndexFormat = DXGI_FORMAT_R16_UINT;
+ memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
+ memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
+ }
+};
+
+Q_DECLARE_TYPEINFO(QD3D11CommandBuffer::Command, Q_MOVABLE_TYPE);
+
+struct QD3D11SwapChain : public QRhiSwapChain
+{
+ QD3D11SwapChain(QRhiImplementation *rhi);
+ ~QD3D11SwapChain();
+ void release() override;
+
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+
+ QSize surfacePixelSize() override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool buildOrResize() override;
+
+ void releaseBuffers();
+ bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
+ ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const;
+
+ QWindow *window = nullptr;
+ QSize pixelSize;
+ QD3D11ReferenceRenderTarget rt;
+ QD3D11CommandBuffer cb;
+ DXGI_FORMAT colorFormat;
+ IDXGISwapChain *swapChain = nullptr;
+ static const int BUFFER_COUNT = 2;
+ ID3D11Texture2D *tex[BUFFER_COUNT];
+ ID3D11RenderTargetView *rtv[BUFFER_COUNT];
+ ID3D11Texture2D *msaaTex[BUFFER_COUNT];
+ ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
+ DXGI_SAMPLE_DESC sampleDesc;
+ int currentFrameSlot = 0;
+ int frameCount = 0;
+ QD3D11RenderBuffer *ds = nullptr;
+ bool timestampActive[BUFFER_COUNT];
+ ID3D11Query *timestampDisjointQuery[BUFFER_COUNT];
+ ID3D11Query *timestampQuery[BUFFER_COUNT * 2];
+ UINT swapInterval = 1;
+};
+
+class QRhiD3D11 : public QRhiImplementation
+{
+public:
+ QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice = nullptr);
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ int size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
+ QRhi::FrameOpResult endOffscreenFrame() override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+
+ QVector<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ void sendVMemStatsToProfiler() override;
+
+ void flushCommandBuffer();
+ void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
+ int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
+ void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
+ void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD);
+ void executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD);
+ void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
+ const uint *dynOfsPairs, int dynOfsPairCount,
+ bool offsetOnlyChange);
+ void setRenderTarget(QRhiRenderTarget *rt);
+ void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr);
+ DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const;
+ void finishActiveReadbacks();
+ void enqueueSetRenderTarget(QD3D11CommandBuffer *cbD, QRhiRenderTarget *rt);
+ void reportLiveObjects(ID3D11Device *device);
+
+ bool debugLayer = false;
+ bool importedDevice = false;
+ ID3D11Device *dev = nullptr;
+ ID3D11DeviceContext1 *context = nullptr;
+ D3D_FEATURE_LEVEL featureLevel;
+ ID3DUserDefinedAnnotation *annotations = nullptr;
+ IDXGIFactory1 *dxgiFactory = nullptr;
+ bool hasDxgi2 = false;
+ QRhiD3D11NativeHandles nativeHandlesStruct;
+
+ bool inFrame = false;
+ bool inPass = false;
+
+ struct {
+ int vsHighestActiveSrvBinding = -1;
+ int fsHighestActiveSrvBinding = -1;
+ QD3D11SwapChain *currentSwapChain = nullptr;
+ } contextState;
+
+ struct OffscreenFrame {
+ OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
+ bool active = false;
+ QD3D11CommandBuffer cbWrapper;
+ } ofr;
+
+ struct ActiveReadback {
+ QRhiReadbackDescription desc;
+ QRhiReadbackResult *result;
+ ID3D11Texture2D *stagingTex;
+ quint32 bufSize;
+ quint32 bpl;
+ QSize pixelSize;
+ QRhiTexture::Format format;
+ };
+ QVector<ActiveReadback> activeReadbacks;
+};
+
+Q_DECLARE_TYPEINFO(QRhiD3D11::ActiveReadback, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
new file mode 100644
index 0000000000..0c89a9284f
--- /dev/null
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -0,0 +1,2975 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrhigles2_p_p.h"
+#include <QWindow>
+#include <QOffscreenSurface>
+#include <QOpenGLContext>
+#include <QtGui/private/qopenglextensions_p.h>
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ OpenGL backend. Binding vertex attribute locations and decomposing uniform
+ buffers into uniforms are handled transparently to the application via the
+ reflection data (QShaderDescription). Real uniform buffers are never used,
+ regardless of the GLSL version. Textures and buffers feature no special logic,
+ it's all just glTexSubImage2D and glBufferSubData (with "dynamic" buffers set
+ to GL_DYNAMIC_DRAW). The swapchain and the associated renderbuffer for
+ depth-stencil will be dummies since we have no control over the underlying
+ buffers here. While we try to keep this backend clean GLES 2.0, some GL(ES)
+ 3.0 features like multisample renderbuffers and blits are used when available.
+*/
+
+/*!
+ \class QRhiGles2InitParams
+ \inmodule QtRhi
+ \brief OpenGL specific initialization parameters.
+
+ An OpenGL-based QRhi needs an already created QOffscreenSurface at minimum.
+ Additionally, while optional, it is recommended that the QWindow the first
+ QRhiSwapChain will target is passed in as well.
+
+ \badcode
+ QOffscreenSurface *fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ QRhiGles2InitParams params;
+ params.fallbackSurface = fallbackSurface;
+ params.window = window;
+ rhi = QRhi::create(QRhi::OpenGLES2, &params);
+ \endcode
+
+ By default QRhi creates a QOpenGLContext on its own. This approach works
+ well in most cases, included threaded scenarios, where there is a dedicated
+ QRhi for each rendering thread. As there will be a QOpenGLContext for each
+ QRhi, the OpenGL context requirements (a context can only be current on one
+ thread) are satisfied. The implicitly created context is destroyed
+ automatically together with the QRhi.
+
+ The QSurfaceFormat for the context is specified in \l format. The
+ constructor sets this to QSurfaceFormat::defaultFormat() so applications
+ that use QSurfaceFormat::setDefaultFormat() do not need to set the format
+ again.
+
+ \note The depth and stencil buffer sizes are set automatically to 24 and 8
+ when no size was explicitly set for these buffers in \l format. As there
+ are possible adjustments to \l format, applications can use
+ adjustedFormat() to query the effective format that is passed to
+ QOpenGLContext::setFormat() internally.
+
+ A QOffscreenSurface has to be specified in \l fallbackSurface. In order to
+ prevent mistakes in threaded situations, this is never created
+ automatically by the QRhi since, like QWindow, QOffscreenSurface can only
+ be created on the gui/main thread.
+
+ As a convenience, applications can use newFallbackSurface() which creates
+ and returns a QOffscreenSurface that is compatible with the QOpenGLContext
+ that is going to be created by the QRhi afterwards. Note that the ownership
+ of the returned QOffscreenSurface is transferred to the caller and the QRhi
+ will not destroy it.
+
+ \note QRhiSwapChain can only target QWindow instances that have their
+ surface type set to QSurface::OpenGLSurface.
+
+ \note \l window is optional. It is recommended to specify it whenever
+ possible, in order to avoid problems on multi-adapter and multi-screen
+ systems. When \l window is not set, the very first
+ QOpenGLContext::makeCurrent() happens with \l fallbackSurface which may be
+ an invisible window on some platforms (for example, Windows) and that may
+ trigger unexpected problems in some cases.
+
+ \section2 Working with existing OpenGL contexts
+
+ When interoperating with another graphics engine, it may be necessary to
+ get a QRhi instance that uses the same OpenGL context. This can be achieved
+ by passing a pointer to a QRhiGles2NativeHandles to QRhi::create(). The
+ \l{QRhiGles2NativeHandles::context}{context} must be set to a non-null
+ value.
+
+ An alternative approach is to create a QOpenGLContext that
+ \l{QOpenGLContext::setShareContext()}{shares resources} with the other
+ engine's context and passing in that context via QRhiGles2NativeHandles.
+
+ The QRhi does not take ownership of the QOpenGLContext passed in via
+ QRhiGles2NativeHandles.
+ */
+
+/*!
+ \class QRhiGles2NativeHandles
+ \inmodule QtRhi
+ \brief Holds the OpenGL context used by the QRhi.
+ */
+
+/*!
+ \class QRhiGles2TextureNativeHandles
+ \inmodule QtRhi
+ \brief Holds the OpenGL texture object that is backing a QRhiTexture instance.
+ */
+
+#ifndef GL_BGRA
+#define GL_BGRA 0x80E1
+#endif
+
+#ifndef GL_R8
+#define GL_R8 0x8229
+#endif
+
+#ifndef GL_R16
+#define GL_R16 0x822A
+#endif
+
+#ifndef GL_RED
+#define GL_RED 0x1903
+#endif
+
+#ifndef GL_RGBA8
+#define GL_RGBA8 0x8058
+#endif
+
+#ifndef GL_RGBA32F
+#define GL_RGBA32F 0x8814
+#endif
+
+#ifndef GL_RGBA16F
+#define GL_RGBA16F 0x881A
+#endif
+
+#ifndef GL_HALF_FLOAT
+#define GL_HALF_FLOAT 0x140B
+#endif
+
+#ifndef GL_DEPTH_COMPONENT16
+#define GL_DEPTH_COMPONENT16 0x81A5
+#endif
+
+#ifndef GL_DEPTH_COMPONENT32F
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#endif
+
+#ifndef GL_DEPTH24_STENCIL8
+#define GL_DEPTH24_STENCIL8 0x88F0
+#endif
+
+#ifndef GL_PRIMITIVE_RESTART_FIXED_INDEX
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#endif
+
+#ifndef GL_FRAMEBUFFER_SRGB
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#endif
+
+#ifndef GL_READ_FRAMEBUFFER
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#endif
+
+#ifndef GL_DRAW_FRAMEBUFFER
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#endif
+
+#ifndef GL_MAX_DRAW_BUFFERS
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#endif
+
+#ifndef GL_TEXTURE_COMPARE_MODE
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#endif
+
+#ifndef GL_COMPARE_REF_TO_TEXTURE
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#endif
+
+#ifndef GL_TEXTURE_COMPARE_FUNC
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#endif
+
+#ifndef GL_MAX_SAMPLES
+#define GL_MAX_SAMPLES 0x8D57
+#endif
+
+/*!
+ Constructs a new QRhiGles2InitParams.
+
+ \l format is set to QSurfaceFormat::defaultFormat().
+ */
+QRhiGles2InitParams::QRhiGles2InitParams()
+{
+ format = QSurfaceFormat::defaultFormat();
+}
+
+/*!
+ \return the QSurfaceFormat that will be set on the QOpenGLContext before
+ calling QOpenGLContext::create(). This format is based on \a format, but
+ may be adjusted. Applicable only when QRhi creates the context.
+ Applications are advised to set this format on their QWindow in order to
+ avoid potential BAD_MATCH failures.
+ */
+QSurfaceFormat QRhiGles2InitParams::adjustedFormat(const QSurfaceFormat &format)
+{
+ QSurfaceFormat fmt = format;
+
+ if (fmt.depthBufferSize() == -1)
+ fmt.setDepthBufferSize(24);
+ if (fmt.stencilBufferSize() == -1)
+ fmt.setStencilBufferSize(8);
+
+ return fmt;
+}
+
+/*!
+ \return a new QOffscreenSurface that can be used with a QRhi by passing it
+ via a QRhiGles2InitParams.
+
+ \a format is adjusted as appropriate in order to avoid having problems
+ afterwards due to an incompatible context and surface.
+
+ \note This function must only be called on the gui/main thread.
+
+ \note It is the application's responsibility to destroy the returned
+ QOffscreenSurface on the gui/main thread once the associated QRhi has been
+ destroyed. The QRhi will not destroy the QOffscreenSurface.
+ */
+QOffscreenSurface *QRhiGles2InitParams::newFallbackSurface(const QSurfaceFormat &format)
+{
+ QSurfaceFormat fmt = adjustedFormat(format);
+
+ // To resolve all fields in the format as much as possible, create a context.
+ // This may be heavy, but allows avoiding BAD_MATCH on some systems.
+ QOpenGLContext tempContext;
+ tempContext.setFormat(fmt);
+ if (tempContext.create())
+ fmt = tempContext.format();
+ else
+ qWarning("QRhiGles2: Failed to create temporary context");
+
+ QOffscreenSurface *s = new QOffscreenSurface;
+ s->setFormat(fmt);
+ s->create();
+
+ return s;
+}
+
+QRhiGles2::QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *importDevice)
+ : ofr(this)
+{
+ requestedFormat = QRhiGles2InitParams::adjustedFormat(params->format);
+ fallbackSurface = params->fallbackSurface;
+ maybeWindow = params->window; // may be null
+
+ importedContext = importDevice != nullptr;
+ if (importedContext) {
+ ctx = importDevice->context;
+ if (!ctx) {
+ qWarning("No OpenGL context given, cannot import");
+ importedContext = false;
+ }
+ }
+}
+
+bool QRhiGles2::ensureContext(QSurface *surface) const
+{
+ bool nativeWindowGone = false;
+ if (surface && surface->surfaceClass() == QSurface::Window && !surface->surfaceHandle()) {
+ surface = fallbackSurface;
+ nativeWindowGone = true;
+ }
+
+ if (!surface)
+ surface = fallbackSurface;
+
+ if (needsMakeCurrent)
+ needsMakeCurrent = false;
+ else if (!nativeWindowGone && QOpenGLContext::currentContext() == ctx && (surface == fallbackSurface || ctx->surface() == surface))
+ return true;
+
+ if (!ctx->makeCurrent(surface)) {
+ qWarning("QRhiGles2: Failed to make context current. Expect bad things to happen.");
+ return false;
+ }
+
+ return true;
+}
+
+bool QRhiGles2::create(QRhi::Flags flags)
+{
+ Q_UNUSED(flags);
+ Q_ASSERT(fallbackSurface);
+
+ if (!importedContext) {
+ ctx = new QOpenGLContext;
+ ctx->setFormat(requestedFormat);
+ if (!ctx->create()) {
+ qWarning("QRhiGles2: Failed to create context");
+ delete ctx;
+ ctx = nullptr;
+ return false;
+ }
+ qDebug() << "Created OpenGL context" << ctx->format();
+ }
+
+ if (!ensureContext(maybeWindow ? maybeWindow : fallbackSurface)) // see 'window' discussion in QRhiGles2InitParams comments
+ return false;
+
+ f = static_cast<QOpenGLExtensions *>(ctx->extraFunctions());
+
+ const char *vendor = reinterpret_cast<const char *>(f->glGetString(GL_VENDOR));
+ const char *renderer = reinterpret_cast<const char *>(f->glGetString(GL_RENDERER));
+ const char *version = reinterpret_cast<const char *>(f->glGetString(GL_VERSION));
+ if (vendor && renderer && version)
+ qDebug("OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version);
+
+ const QSurfaceFormat actualFormat = ctx->format();
+
+ caps.ctxMajor = actualFormat.majorVersion();
+ caps.ctxMinor = actualFormat.minorVersion();
+
+ GLint n = 0;
+ f->glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &n);
+ supportedCompressedFormats.resize(n);
+ if (n > 0)
+ f->glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, supportedCompressedFormats.data());
+
+ f->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.maxTextureSize);
+
+ if (caps.ctxMajor >= 3 || actualFormat.renderableType() == QSurfaceFormat::OpenGL) {
+ f->glGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.maxDrawBuffers);
+ f->glGetIntegerv(GL_MAX_SAMPLES, &caps.maxSamples);
+ caps.maxSamples = qMax(1, caps.maxSamples);
+ } else {
+ caps.maxDrawBuffers = 1;
+ caps.maxSamples = 1;
+ }
+
+ caps.msaaRenderBuffer = f->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
+ && f->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
+
+ caps.npotTexture = f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
+ caps.npotTextureRepeat = f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
+
+ caps.gles = actualFormat.renderableType() == QSurfaceFormat::OpenGLES;
+ if (caps.gles)
+ caps.fixedIndexPrimitiveRestart = caps.ctxMajor >= 3;
+ else
+ caps.fixedIndexPrimitiveRestart = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
+
+ if (caps.fixedIndexPrimitiveRestart)
+ f->glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
+
+ caps.bgraExternalFormat = f->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat);
+ caps.bgraInternalFormat = caps.bgraExternalFormat && caps.gles;
+ caps.r8Format = f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats);
+ caps.r16Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats);
+ caps.floatFormats = caps.ctxMajor >= 3;
+ caps.depthTexture = caps.ctxMajor >= 3;
+ caps.packedDepthStencil = f->hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil);
+ caps.srgbCapableDefaultFramebuffer = f->hasOpenGLExtension(QOpenGLExtensions::SRGBFrameBuffer);
+ caps.coreProfile = actualFormat.profile() == QSurfaceFormat::CoreProfile;
+ caps.uniformBuffers = caps.ctxMajor >= 3 && (caps.gles || caps.ctxMinor >= 1);
+ caps.elementIndexUint = f->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint);
+
+ nativeHandlesStruct.context = ctx;
+
+ return true;
+}
+
+void QRhiGles2::destroy()
+{
+ if (!f)
+ return;
+
+ ensureContext();
+ executeDeferredReleases();
+
+ if (!importedContext) {
+ delete ctx;
+ ctx = nullptr;
+ }
+
+ f = nullptr;
+}
+
+void QRhiGles2::executeDeferredReleases()
+{
+ for (int i = releaseQueue.count() - 1; i >= 0; --i) {
+ const QRhiGles2::DeferredReleaseEntry &e(releaseQueue[i]);
+ switch (e.type) {
+ case QRhiGles2::DeferredReleaseEntry::Buffer:
+ f->glDeleteBuffers(1, &e.buffer.buffer);
+ break;
+ case QRhiGles2::DeferredReleaseEntry::Pipeline:
+ f->glDeleteProgram(e.pipeline.program);
+ break;
+ case QRhiGles2::DeferredReleaseEntry::Texture:
+ f->glDeleteTextures(1, &e.texture.texture);
+ break;
+ case QRhiGles2::DeferredReleaseEntry::RenderBuffer:
+ f->glDeleteRenderbuffers(1, &e.renderbuffer.renderbuffer);
+ f->glDeleteRenderbuffers(1, &e.renderbuffer.renderbuffer2);
+ break;
+ case QRhiGles2::DeferredReleaseEntry::TextureRenderTarget:
+ f->glDeleteFramebuffers(1, &e.textureRenderTarget.framebuffer);
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ releaseQueue.removeAt(i);
+ }
+}
+
+QVector<int> QRhiGles2::supportedSampleCounts() const
+{
+ if (supportedSampleCountList.isEmpty()) {
+ // 1, 2, 4, 8, ...
+ for (int i = 1; i <= caps.maxSamples; i *= 2)
+ supportedSampleCountList.append(i);
+ }
+ return supportedSampleCountList;
+}
+
+int QRhiGles2::effectiveSampleCount(int sampleCount) const
+{
+ // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
+ const int s = qBound(1, sampleCount, 64);
+ if (!supportedSampleCounts().contains(s)) {
+ qWarning("Attempted to set unsupported sample count %d", sampleCount);
+ return 1;
+ }
+ return s;
+}
+
+QRhiSwapChain *QRhiGles2::createSwapChain()
+{
+ return new QGles2SwapChain(this);
+}
+
+QRhiBuffer *QRhiGles2::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+{
+ return new QGles2Buffer(this, type, usage, size);
+}
+
+int QRhiGles2::ubufAlignment() const
+{
+ return 256;
+}
+
+bool QRhiGles2::isYUpInFramebuffer() const
+{
+ return true;
+}
+
+bool QRhiGles2::isYUpInNDC() const
+{
+ return true;
+}
+
+bool QRhiGles2::isClipDepthZeroToOne() const
+{
+ return false;
+}
+
+QMatrix4x4 QRhiGles2::clipSpaceCorrMatrix() const
+{
+ return QMatrix4x4(); // identity
+}
+
+static inline GLenum toGlCompressedTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
+{
+ const bool srgb = flags.testFlag(QRhiTexture::sRGB);
+ switch (format) {
+ case QRhiTexture::BC1:
+ return srgb ? 0x8C4C : 0x83F0;
+ case QRhiTexture::BC3:
+ return srgb ? 0x8C4E : 0x83F2;
+ case QRhiTexture::BC5:
+ return srgb ? 0x8C4F : 0x83F3;
+
+ case QRhiTexture::ETC2_RGB8:
+ return srgb ? 0x9275 : 0x9274;
+ case QRhiTexture::ETC2_RGB8A1:
+ return srgb ? 0x9277 : 0x9276;
+ case QRhiTexture::ETC2_RGBA8:
+ return srgb ? 0x9279 : 0x9278;
+
+ case QRhiTexture::ASTC_4x4:
+ return srgb ? 0x93D0 : 0x93B0;
+ case QRhiTexture::ASTC_5x4:
+ return srgb ? 0x93D1 : 0x93B1;
+ case QRhiTexture::ASTC_5x5:
+ return srgb ? 0x93D2 : 0x93B2;
+ case QRhiTexture::ASTC_6x5:
+ return srgb ? 0x93D3 : 0x93B3;
+ case QRhiTexture::ASTC_6x6:
+ return srgb ? 0x93D4 : 0x93B4;
+ case QRhiTexture::ASTC_8x5:
+ return srgb ? 0x93D5 : 0x93B5;
+ case QRhiTexture::ASTC_8x6:
+ return srgb ? 0x93D6 : 0x93B6;
+ case QRhiTexture::ASTC_8x8:
+ return srgb ? 0x93D7 : 0x93B7;
+ case QRhiTexture::ASTC_10x5:
+ return srgb ? 0x93D8 : 0x93B8;
+ case QRhiTexture::ASTC_10x6:
+ return srgb ? 0x93D9 : 0x93B9;
+ case QRhiTexture::ASTC_10x8:
+ return srgb ? 0x93DA : 0x93BA;
+ case QRhiTexture::ASTC_10x10:
+ return srgb ? 0x93DB : 0x93BB;
+ case QRhiTexture::ASTC_12x10:
+ return srgb ? 0x93DC : 0x93BC;
+ case QRhiTexture::ASTC_12x12:
+ return srgb ? 0x93DD : 0x93BD;
+
+ default:
+ return 0; // this is reachable, just return an invalid format
+ }
+}
+
+bool QRhiGles2::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
+{
+ if (isCompressedFormat(format))
+ return supportedCompressedFormats.contains(toGlCompressedTextureFormat(format, flags));
+
+ switch (format) {
+ case QRhiTexture::D16:
+ Q_FALLTHROUGH();
+ case QRhiTexture::D32F:
+ return caps.depthTexture;
+
+ case QRhiTexture::BGRA8:
+ return caps.bgraExternalFormat;
+
+ case QRhiTexture::R8:
+ return caps.r8Format;
+
+ case QRhiTexture::R16:
+ return caps.r16Format;
+
+ case QRhiTexture::RGBA16F:
+ Q_FALLTHROUGH();
+ case QRhiTexture::RGBA32F:
+ return caps.floatFormats;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const
+{
+ switch (feature) {
+ case QRhi::MultisampleTexture:
+ return false;
+ case QRhi::MultisampleRenderBuffer:
+ return caps.msaaRenderBuffer;
+ case QRhi::DebugMarkers:
+ return false;
+ case QRhi::Timestamps:
+ return false;
+ case QRhi::Instancing:
+ return false;
+ case QRhi::CustomInstanceStepRate:
+ return false;
+ case QRhi::PrimitiveRestart:
+ return caps.fixedIndexPrimitiveRestart;
+ case QRhi::NonDynamicUniformBuffers:
+ return true;
+ case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
+ return true;
+ case QRhi::NPOTTextureRepeat:
+ return caps.npotTextureRepeat;
+ case QRhi::RedOrAlpha8IsRed:
+ return caps.coreProfile;
+ case QRhi::ElementIndexUint:
+ return caps.elementIndexUint;
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
+}
+
+int QRhiGles2::resourceLimit(QRhi::ResourceLimit limit) const
+{
+ switch (limit) {
+ case QRhi::TextureSizeMin:
+ return 1;
+ case QRhi::TextureSizeMax:
+ return caps.maxTextureSize;
+ case QRhi::MaxColorAttachments:
+ return caps.maxDrawBuffers;
+ case QRhi::FramesInFlight:
+ return 2; // dummy
+ default:
+ Q_UNREACHABLE();
+ return 0;
+ }
+}
+
+const QRhiNativeHandles *QRhiGles2::nativeHandles()
+{
+ return &nativeHandlesStruct;
+}
+
+void QRhiGles2::sendVMemStatsToProfiler()
+{
+ // nothing to do here
+}
+
+QRhiRenderBuffer *QRhiGles2::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags)
+{
+ return new QGles2RenderBuffer(this, type, pixelSize, sampleCount, flags);
+}
+
+QRhiTexture *QRhiGles2::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
+ int sampleCount, QRhiTexture::Flags flags)
+{
+ return new QGles2Texture(this, format, pixelSize, sampleCount, flags);
+}
+
+QRhiSampler *QRhiGles2::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+{
+ return new QGles2Sampler(this, magFilter, minFilter, mipmapMode, u, v);
+}
+
+QRhiTextureRenderTarget *QRhiGles2::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags)
+{
+ return new QGles2TextureRenderTarget(this, desc, flags);
+}
+
+QRhiGraphicsPipeline *QRhiGles2::createGraphicsPipeline()
+{
+ return new QGles2GraphicsPipeline(this);
+}
+
+QRhiShaderResourceBindings *QRhiGles2::createShaderResourceBindings()
+{
+ return new QGles2ShaderResourceBindings(this);
+}
+
+void QRhiGles2::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps)
+{
+ Q_ASSERT(inPass);
+
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+ QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, ps);
+ const bool pipelineChanged = cbD->currentPipeline != ps || cbD->currentPipelineGeneration != psD->generation;
+
+ if (pipelineChanged) {
+ cbD->currentPipeline = ps;
+ cbD->currentPipelineGeneration = psD->generation;
+
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::BindGraphicsPipeline;
+ cmd.args.bindGraphicsPipeline.ps = ps;
+ cbD->commands.append(cmd);
+ }
+}
+
+void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
+{
+ Q_ASSERT(inPass);
+
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+ Q_ASSERT(cbD->currentPipeline);
+
+ if (!srb)
+ srb = QRHI_RES(QGles2GraphicsPipeline, cbD->currentPipeline)->m_shaderResourceBindings;
+
+ QGles2ShaderResourceBindings *srbD = QRHI_RES(QGles2ShaderResourceBindings, srb);
+ bool hasDynamicOffsetInSrb = false;
+ for (int i = 0, ie = srbD->m_bindings.count(); i != ie; ++i) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->m_bindings[i]);
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ if (b->u.ubuf.hasDynamicOffset)
+ hasDynamicOffsetInSrb = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ const bool srbChanged = cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation;
+
+ if (srbChanged || hasDynamicOffsetInSrb) {
+ cbD->currentSrb = srb;
+ cbD->currentSrbGeneration = srbD->generation;
+
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::BindShaderResources;
+ cmd.args.bindShaderResources.ps = cbD->currentPipeline;
+ cmd.args.bindShaderResources.srb = srb;
+ cmd.args.bindShaderResources.dynamicOffsetCount = 0;
+ if (hasDynamicOffsetInSrb) {
+ if (dynamicOffsetCount < QGles2CommandBuffer::Command::MAX_UBUF_BINDINGS) {
+ cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount;
+ uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
+ for (int i = 0; i < dynamicOffsetCount; ++i) {
+ const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
+ *p++ = dynOfs.first;
+ *p++ = dynOfs.second;
+ }
+ } else {
+ qWarning("Too many dynamic offsets (%d, max is %d)",
+ dynamicOffsetCount, QGles2CommandBuffer::Command::MAX_UBUF_BINDINGS);
+ }
+ }
+ cbD->commands.append(cmd);
+ }
+}
+
+void QRhiGles2::setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
+{
+ Q_ASSERT(inPass);
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+
+ for (int i = 0; i < bindingCount; ++i) {
+ QRhiBuffer *buf = bindings[i].first;
+ quint32 ofs = bindings[i].second;
+ QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, buf);
+ Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::BindVertexBuffer;
+ cmd.args.bindVertexBuffer.ps = cbD->currentPipeline;
+ cmd.args.bindVertexBuffer.buffer = bufD->buffer;
+ cmd.args.bindVertexBuffer.offset = ofs;
+ cmd.args.bindVertexBuffer.binding = startBinding + i;
+ cbD->commands.append(cmd);
+ }
+
+ if (indexBuf) {
+ QGles2Buffer *ibufD = QRHI_RES(QGles2Buffer, indexBuf);
+ Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::BindIndexBuffer;
+ cmd.args.bindIndexBuffer.buffer = ibufD->buffer;
+ cmd.args.bindIndexBuffer.offset = indexOffset;
+ cmd.args.bindIndexBuffer.type = indexFormat == QRhiCommandBuffer::IndexUInt16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+ cbD->commands.append(cmd);
+ }
+}
+
+void QRhiGles2::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
+{
+ Q_ASSERT(inPass);
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::Viewport;
+ const std::array<float, 4> r = viewport.viewport();
+ cmd.args.viewport.x = qMax(0.0f, r[0]);
+ cmd.args.viewport.y = qMax(0.0f, r[1]);
+ cmd.args.viewport.w = r[2];
+ cmd.args.viewport.h = r[3];
+ cmd.args.viewport.d0 = viewport.minDepth();
+ cmd.args.viewport.d1 = viewport.maxDepth();
+ QRHI_RES(QGles2CommandBuffer, cb)->commands.append(cmd);
+}
+
+void QRhiGles2::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
+{
+ Q_ASSERT(inPass);
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::Scissor;
+ const std::array<int, 4> r = scissor.scissor();
+ cmd.args.scissor.x = qMax(0, r[0]);
+ cmd.args.scissor.y = qMax(0, r[1]);
+ cmd.args.scissor.w = r[2];
+ cmd.args.scissor.h = r[3];
+ QRHI_RES(QGles2CommandBuffer, cb)->commands.append(cmd);
+}
+
+void QRhiGles2::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
+{
+ Q_ASSERT(inPass);
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::BlendConstants;
+ cmd.args.blendConstants.r = c.redF();
+ cmd.args.blendConstants.g = c.greenF();
+ cmd.args.blendConstants.b = c.blueF();
+ cmd.args.blendConstants.a = c.alphaF();
+ QRHI_RES(QGles2CommandBuffer, cb)->commands.append(cmd);
+}
+
+void QRhiGles2::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
+{
+ Q_ASSERT(inPass);
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::StencilRef;
+ cmd.args.stencilRef.ref = refValue;
+ cmd.args.stencilRef.ps = cbD->currentPipeline;
+ cbD->commands.append(cmd);
+}
+
+void QRhiGles2::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
+{
+ Q_ASSERT(inPass);
+ Q_UNUSED(instanceCount); // no instancing
+ Q_UNUSED(firstInstance);
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::Draw;
+ cmd.args.draw.ps = cbD->currentPipeline;
+ cmd.args.draw.vertexCount = vertexCount;
+ cmd.args.draw.firstVertex = firstVertex;
+ cbD->commands.append(cmd);
+}
+
+void QRhiGles2::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
+{
+ Q_ASSERT(inPass);
+ Q_UNUSED(instanceCount); // no instancing
+ Q_UNUSED(firstInstance);
+ Q_UNUSED(vertexOffset); // no glDrawElementsBaseVertex
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::DrawIndexed;
+ cmd.args.drawIndexed.ps = cbD->currentPipeline;
+ cmd.args.drawIndexed.indexCount = indexCount;
+ cmd.args.drawIndexed.firstIndex = firstIndex;
+ cbD->commands.append(cmd);
+}
+
+void QRhiGles2::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
+{
+ if (!debugMarkers)
+ return;
+
+ Q_UNUSED(cb);
+ Q_UNUSED(name);
+}
+
+void QRhiGles2::debugMarkEnd(QRhiCommandBuffer *cb)
+{
+ if (!debugMarkers)
+ return;
+
+ Q_UNUSED(cb);
+}
+
+void QRhiGles2::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
+{
+ if (!debugMarkers)
+ return;
+
+ Q_UNUSED(cb);
+ Q_UNUSED(msg);
+}
+
+const QRhiNativeHandles *QRhiGles2::nativeHandles(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+ return nullptr;
+}
+
+void QRhiGles2::beginExternal(QRhiCommandBuffer *cb)
+{
+ Q_ASSERT(inPass);
+ Q_UNUSED(cb);
+ flushCommandBuffer(); // also ensures the context is current
+}
+
+void QRhiGles2::endExternal(QRhiCommandBuffer *cb)
+{
+ Q_ASSERT(inPass);
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+ Q_ASSERT(cbD->currentTarget);
+ Q_ASSERT(cbD->commands.isEmpty());
+ cbD->resetCachedState();
+ enqueueBindFramebuffer(cbD->currentTarget, cbD);
+}
+
+static void addBoundaryCommand(QGles2CommandBuffer *cb, QGles2CommandBuffer::Command::Cmd type)
+{
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = type;
+ cb->commands.append(cmd);
+}
+
+QRhi::FrameOpResult QRhiGles2::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
+{
+ Q_UNUSED(flags);
+ Q_ASSERT(!inFrame);
+
+ QGles2SwapChain *swapChainD = QRHI_RES(QGles2SwapChain, swapChain);
+ if (!ensureContext(swapChainD->surface))
+ return QRhi::FrameOpError;
+
+ inFrame = true;
+ currentSwapChain = swapChainD;
+
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+ QRHI_PROF_F(beginSwapChainFrame(swapChain));
+
+ executeDeferredReleases();
+ swapChainD->cb.resetState();
+
+ addBoundaryCommand(&swapChainD->cb, QGles2CommandBuffer::Command::BeginFrame);
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiGles2::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags)
+{
+ Q_ASSERT(inFrame);
+ inFrame = false;
+
+ QGles2SwapChain *swapChainD = QRHI_RES(QGles2SwapChain, swapChain);
+ Q_ASSERT(currentSwapChain == swapChainD);
+
+ addBoundaryCommand(&swapChainD->cb, QGles2CommandBuffer::Command::EndFrame);
+
+ if (!ensureContext(swapChainD->surface))
+ return QRhi::FrameOpError;
+
+ executeCommandBuffer(&swapChainD->cb);
+
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+ // this must be done before the swap
+ QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
+
+ if (swapChainD->surface && !flags.testFlag(QRhi::SkipPresent)) {
+ ctx->swapBuffers(swapChainD->surface);
+ needsMakeCurrent = true;
+ } else {
+ f->glFlush();
+ }
+
+ swapChainD->frameCount += 1;
+ currentSwapChain = nullptr;
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb)
+{
+ Q_ASSERT(!inFrame);
+
+ if (!ensureContext())
+ return QRhi::FrameOpError;
+
+ inFrame = true;
+ ofr.active = true;
+
+ executeDeferredReleases();
+ ofr.cbWrapper.resetState();
+
+ addBoundaryCommand(&ofr.cbWrapper, QGles2CommandBuffer::Command::BeginFrame);
+ *cb = &ofr.cbWrapper;
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiGles2::endOffscreenFrame()
+{
+ Q_ASSERT(inFrame && ofr.active);
+ inFrame = false;
+ ofr.active = false;
+
+ addBoundaryCommand(&ofr.cbWrapper, QGles2CommandBuffer::Command::EndFrame);
+
+ if (!ensureContext())
+ return QRhi::FrameOpError;
+
+ executeCommandBuffer(&ofr.cbWrapper);
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiGles2::finish()
+{
+ Q_ASSERT(!inPass); // because that's what the QRhi docs say, even though not required by this backend
+ return inFrame ? flushCommandBuffer() : QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiGles2::flushCommandBuffer()
+{
+ if (ofr.active) {
+ Q_ASSERT(!currentSwapChain);
+ if (!ensureContext())
+ return QRhi::FrameOpError;
+ executeCommandBuffer(&ofr.cbWrapper);
+ ofr.cbWrapper.resetCommands();
+ } else {
+ Q_ASSERT(currentSwapChain);
+ if (!ensureContext(currentSwapChain->surface))
+ return QRhi::FrameOpError;
+ executeCommandBuffer(&currentSwapChain->cb);
+ currentSwapChain->cb.resetCommands();
+ }
+ return QRhi::FrameOpSuccess;
+}
+
+void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD,
+ int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
+{
+ const bool isCompressed = isCompressedFormat(texD->m_format);
+ const bool isCubeMap = texD->m_flags.testFlag(QRhiTexture::CubeMap);
+ const GLenum faceTargetBase = isCubeMap ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
+ const QPoint dp = subresDesc.destinationTopLeft();
+ const QByteArray rawData = subresDesc.data();
+ if (!subresDesc.image().isNull()) {
+ QImage img = subresDesc.image();
+ QSize size = img.size();
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::SubImage;
+ if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
+ const QPoint sp = subresDesc.sourceTopLeft();
+ if (!subresDesc.sourceSize().isEmpty())
+ size = subresDesc.sourceSize();
+ img = img.copy(sp.x(), sp.y(), size.width(), size.height());
+ }
+ cmd.args.subImage.target = texD->target;
+ cmd.args.subImage.texture = texD->texture;
+ cmd.args.subImage.faceTarget = faceTargetBase + layer;
+ cmd.args.subImage.level = level;
+ cmd.args.subImage.dx = dp.x();
+ cmd.args.subImage.dy = dp.y();
+ cmd.args.subImage.w = size.width();
+ cmd.args.subImage.h = size.height();
+ cmd.args.subImage.glformat = texD->glformat;
+ cmd.args.subImage.gltype = texD->gltype;
+ cmd.args.subImage.rowStartAlign = 4;
+ cmd.args.subImage.data = cbD->retainImage(img);
+ cbD->commands.append(cmd);
+ } else if (!rawData.isEmpty() && isCompressed) {
+ const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
+ : subresDesc.sourceSize();
+ if (texD->specified) {
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::CompressedSubImage;
+ cmd.args.compressedSubImage.target = texD->target;
+ cmd.args.compressedSubImage.texture = texD->texture;
+ cmd.args.compressedSubImage.faceTarget = faceTargetBase + layer;
+ cmd.args.compressedSubImage.level = level;
+ cmd.args.compressedSubImage.dx = dp.x();
+ cmd.args.compressedSubImage.dy = dp.y();
+ cmd.args.compressedSubImage.w = size.width();
+ cmd.args.compressedSubImage.h = size.height();
+ cmd.args.compressedSubImage.glintformat = texD->glintformat;
+ cmd.args.compressedSubImage.size = rawData.size();
+ cmd.args.compressedSubImage.data = cbD->retainData(rawData);
+ cbD->commands.append(cmd);
+ } else {
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::CompressedImage;
+ cmd.args.compressedImage.target = texD->target;
+ cmd.args.compressedImage.texture = texD->texture;
+ cmd.args.compressedImage.faceTarget = faceTargetBase + layer;
+ cmd.args.compressedImage.level = level;
+ cmd.args.compressedImage.glintformat = texD->glintformat;
+ cmd.args.compressedImage.w = size.width();
+ cmd.args.compressedImage.h = size.height();
+ cmd.args.compressedImage.size = rawData.size();
+ cmd.args.compressedImage.data = cbD->retainData(rawData);
+ cbD->commands.append(cmd);
+ }
+ } else if (!rawData.isEmpty()) {
+ const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
+ : subresDesc.sourceSize();
+ quint32 bpl = 0;
+ textureFormatInfo(texD->m_format, size, &bpl, nullptr);
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::SubImage;
+ cmd.args.subImage.target = texD->target;
+ cmd.args.subImage.texture = texD->texture;
+ cmd.args.subImage.faceTarget = faceTargetBase + layer;
+ cmd.args.subImage.level = level;
+ cmd.args.subImage.dx = dp.x();
+ cmd.args.subImage.dy = dp.y();
+ cmd.args.subImage.w = size.width();
+ cmd.args.subImage.h = size.height();
+ cmd.args.subImage.glformat = texD->glformat;
+ cmd.args.subImage.gltype = texD->gltype;
+ // Default unpack alignment (row start aligment
+ // requirement) is 4. QImage guarantees 4 byte aligned
+ // row starts, but our raw data here does not.
+ cmd.args.subImage.rowStartAlign = (bpl & 3) ? 1 : 4;
+ cmd.args.subImage.data = cbD->retainData(rawData);
+ cbD->commands.append(cmd);
+ } else {
+ qWarning("Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
+ }
+}
+
+void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+ QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
+
+ for (const QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate &u : ud->dynamicBufferUpdates) {
+ QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf);
+ Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
+ if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
+ memcpy(bufD->ubuf.data() + u.offset, u.data.constData(), u.data.size());
+ } else {
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::BufferSubData;
+ cmd.args.bufferSubData.target = bufD->target;
+ cmd.args.bufferSubData.buffer = bufD->buffer;
+ cmd.args.bufferSubData.offset = u.offset;
+ cmd.args.bufferSubData.size = u.data.size();
+ cmd.args.bufferSubData.data = cbD->retainData(u.data);
+ cbD->commands.append(cmd);
+ }
+ }
+
+ for (const QRhiResourceUpdateBatchPrivate::StaticBufferUpload &u : ud->staticBufferUploads) {
+ QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf);
+ Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
+ Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
+ if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
+ memcpy(bufD->ubuf.data() + u.offset, u.data.constData(), u.data.size());
+ } else {
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::BufferSubData;
+ cmd.args.bufferSubData.target = bufD->target;
+ cmd.args.bufferSubData.buffer = bufD->buffer;
+ cmd.args.bufferSubData.offset = u.offset;
+ cmd.args.bufferSubData.size = u.data.size();
+ cmd.args.bufferSubData.data = cbD->retainData(u.data);
+ cbD->commands.append(cmd);
+ }
+ }
+
+ for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
+ if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
+ QGles2Texture *texD = QRHI_RES(QGles2Texture, u.upload.tex);
+ for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
+ for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.upload.subresDesc[layer][level]))
+ enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
+ }
+ }
+ texD->specified = true;
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Copy) {
+ Q_ASSERT(u.copy.src && u.copy.dst);
+ QGles2Texture *srcD = QRHI_RES(QGles2Texture, u.copy.src);
+ QGles2Texture *dstD = QRHI_RES(QGles2Texture, u.copy.dst);
+
+ const QSize size = u.copy.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.copy.desc.pixelSize();
+ // do not translate coordinates, even if sp is bottom-left from gl's pov
+ const QPoint sp = u.copy.desc.sourceTopLeft();
+ const QPoint dp = u.copy.desc.destinationTopLeft();
+
+ const GLenum srcFaceTargetBase = srcD->m_flags.testFlag(QRhiTexture::CubeMap)
+ ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : srcD->target;
+ const GLenum dstFaceTargetBase = dstD->m_flags.testFlag(QRhiTexture::CubeMap)
+ ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : dstD->target;
+
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::CopyTex;
+
+ cmd.args.copyTex.srcFaceTarget = srcFaceTargetBase + u.copy.desc.sourceLayer();
+ cmd.args.copyTex.srcTexture = srcD->texture;
+ cmd.args.copyTex.srcLevel = u.copy.desc.sourceLevel();
+ cmd.args.copyTex.srcX = sp.x();
+ cmd.args.copyTex.srcY = sp.y();
+
+ cmd.args.copyTex.dstTarget = dstD->target;
+ cmd.args.copyTex.dstTexture = dstD->texture;
+ cmd.args.copyTex.dstFaceTarget = dstFaceTargetBase + u.copy.desc.destinationLayer();
+ cmd.args.copyTex.dstLevel = u.copy.desc.destinationLevel();
+ cmd.args.copyTex.dstX = dp.x();
+ cmd.args.copyTex.dstY = dp.y();
+
+ cmd.args.copyTex.w = size.width();
+ cmd.args.copyTex.h = size.height();
+
+ cbD->commands.append(cmd);
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) {
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::ReadPixels;
+ cmd.args.readPixels.result = u.read.result;
+ QGles2Texture *texD = QRHI_RES(QGles2Texture, u.read.rb.texture());
+ cmd.args.readPixels.texture = texD ? texD->texture : 0;
+ if (texD) {
+ cmd.args.readPixels.w = texD->m_pixelSize.width();
+ cmd.args.readPixels.h = texD->m_pixelSize.height();
+ cmd.args.readPixels.format = texD->m_format;
+ const GLenum faceTargetBase = texD->m_flags.testFlag(QRhiTexture::CubeMap)
+ ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
+ cmd.args.readPixels.readTarget = faceTargetBase + u.read.rb.layer();
+ cmd.args.readPixels.level = u.read.rb.level();
+ }
+ cbD->commands.append(cmd);
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::MipGen) {
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::GenMip;
+ QGles2Texture *texD = QRHI_RES(QGles2Texture, u.mipgen.tex);
+ cmd.args.genMip.target = texD->target;
+ cmd.args.genMip.texture = texD->texture;
+ cbD->commands.append(cmd);
+ }
+ }
+
+ ud->free();
+}
+
+static inline GLenum toGlTopology(QRhiGraphicsPipeline::Topology t)
+{
+ switch (t) {
+ case QRhiGraphicsPipeline::Triangles:
+ return GL_TRIANGLES;
+ case QRhiGraphicsPipeline::TriangleStrip:
+ return GL_TRIANGLE_STRIP;
+ case QRhiGraphicsPipeline::Lines:
+ return GL_LINES;
+ case QRhiGraphicsPipeline::LineStrip:
+ return GL_LINE_STRIP;
+ case QRhiGraphicsPipeline::Points:
+ return GL_POINTS;
+ default:
+ Q_UNREACHABLE();
+ return GL_TRIANGLES;
+ }
+}
+
+static inline GLenum toGlCullMode(QRhiGraphicsPipeline::CullMode c)
+{
+ switch (c) {
+ case QRhiGraphicsPipeline::Front:
+ return GL_FRONT;
+ case QRhiGraphicsPipeline::Back:
+ return GL_BACK;
+ default:
+ Q_UNREACHABLE();
+ return GL_BACK;
+ }
+}
+
+static inline GLenum toGlFrontFace(QRhiGraphicsPipeline::FrontFace f)
+{
+ switch (f) {
+ case QRhiGraphicsPipeline::CCW:
+ return GL_CCW;
+ case QRhiGraphicsPipeline::CW:
+ return GL_CW;
+ default:
+ Q_UNREACHABLE();
+ return GL_CCW;
+ }
+}
+
+static inline GLenum toGlBlendFactor(QRhiGraphicsPipeline::BlendFactor f)
+{
+ switch (f) {
+ case QRhiGraphicsPipeline::Zero:
+ return GL_ZERO;
+ case QRhiGraphicsPipeline::One:
+ return GL_ONE;
+ case QRhiGraphicsPipeline::SrcColor:
+ return GL_SRC_COLOR;
+ case QRhiGraphicsPipeline::OneMinusSrcColor:
+ return GL_ONE_MINUS_SRC_COLOR;
+ case QRhiGraphicsPipeline::DstColor:
+ return GL_DST_COLOR;
+ case QRhiGraphicsPipeline::OneMinusDstColor:
+ return GL_ONE_MINUS_DST_COLOR;
+ case QRhiGraphicsPipeline::SrcAlpha:
+ return GL_SRC_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusSrcAlpha:
+ return GL_ONE_MINUS_SRC_ALPHA;
+ case QRhiGraphicsPipeline::DstAlpha:
+ return GL_DST_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusDstAlpha:
+ return GL_ONE_MINUS_DST_ALPHA;
+ case QRhiGraphicsPipeline::ConstantColor:
+ return GL_CONSTANT_COLOR;
+ case QRhiGraphicsPipeline::OneMinusConstantColor:
+ return GL_ONE_MINUS_CONSTANT_COLOR;
+ case QRhiGraphicsPipeline::ConstantAlpha:
+ return GL_CONSTANT_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusConstantAlpha:
+ return GL_ONE_MINUS_CONSTANT_ALPHA;
+ case QRhiGraphicsPipeline::SrcAlphaSaturate:
+ return GL_SRC_ALPHA_SATURATE;
+ case QRhiGraphicsPipeline::Src1Color:
+ Q_FALLTHROUGH();
+ case QRhiGraphicsPipeline::OneMinusSrc1Color:
+ Q_FALLTHROUGH();
+ case QRhiGraphicsPipeline::Src1Alpha:
+ Q_FALLTHROUGH();
+ case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
+ qWarning("Unsupported blend factor %d", f);
+ return GL_ZERO;
+ default:
+ Q_UNREACHABLE();
+ return GL_ZERO;
+ }
+}
+
+static inline GLenum toGlBlendOp(QRhiGraphicsPipeline::BlendOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::Add:
+ return GL_FUNC_ADD;
+ case QRhiGraphicsPipeline::Subtract:
+ return GL_FUNC_SUBTRACT;
+ case QRhiGraphicsPipeline::ReverseSubtract:
+ return GL_FUNC_REVERSE_SUBTRACT;
+ case QRhiGraphicsPipeline::Min:
+ return GL_MIN;
+ case QRhiGraphicsPipeline::Max:
+ return GL_MAX;
+ default:
+ Q_UNREACHABLE();
+ return GL_FUNC_ADD;
+ }
+}
+
+static inline GLenum toGlCompareOp(QRhiGraphicsPipeline::CompareOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::Never:
+ return GL_NEVER;
+ case QRhiGraphicsPipeline::Less:
+ return GL_LESS;
+ case QRhiGraphicsPipeline::Equal:
+ return GL_EQUAL;
+ case QRhiGraphicsPipeline::LessOrEqual:
+ return GL_LEQUAL;
+ case QRhiGraphicsPipeline::Greater:
+ return GL_GREATER;
+ case QRhiGraphicsPipeline::NotEqual:
+ return GL_NOTEQUAL;
+ case QRhiGraphicsPipeline::GreaterOrEqual:
+ return GL_GEQUAL;
+ case QRhiGraphicsPipeline::Always:
+ return GL_ALWAYS;
+ default:
+ Q_UNREACHABLE();
+ return GL_ALWAYS;
+ }
+}
+
+static inline GLenum toGlStencilOp(QRhiGraphicsPipeline::StencilOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::StencilZero:
+ return GL_ZERO;
+ case QRhiGraphicsPipeline::Keep:
+ return GL_KEEP;
+ case QRhiGraphicsPipeline::Replace:
+ return GL_REPLACE;
+ case QRhiGraphicsPipeline::IncrementAndClamp:
+ return GL_INCR;
+ case QRhiGraphicsPipeline::DecrementAndClamp:
+ return GL_DECR;
+ case QRhiGraphicsPipeline::Invert:
+ return GL_INVERT;
+ case QRhiGraphicsPipeline::IncrementAndWrap:
+ return GL_INCR_WRAP;
+ case QRhiGraphicsPipeline::DecrementAndWrap:
+ return GL_DECR_WRAP;
+ default:
+ Q_UNREACHABLE();
+ return GL_KEEP;
+ }
+}
+
+static inline GLenum toGlMinFilter(QRhiSampler::Filter f, QRhiSampler::Filter m)
+{
+ switch (f) {
+ case QRhiSampler::Nearest:
+ if (m == QRhiSampler::None)
+ return GL_NEAREST;
+ else
+ return m == QRhiSampler::Nearest ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR;
+ case QRhiSampler::Linear:
+ if (m == QRhiSampler::None)
+ return GL_LINEAR;
+ else
+ return m == QRhiSampler::Nearest ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR;
+ default:
+ Q_UNREACHABLE();
+ return GL_LINEAR;
+ }
+}
+
+static inline GLenum toGlMagFilter(QRhiSampler::Filter f)
+{
+ switch (f) {
+ case QRhiSampler::Nearest:
+ return GL_NEAREST;
+ case QRhiSampler::Linear:
+ return GL_LINEAR;
+ default:
+ Q_UNREACHABLE();
+ return GL_LINEAR;
+ }
+}
+
+static inline GLenum toGlWrapMode(QRhiSampler::AddressMode m)
+{
+ switch (m) {
+ case QRhiSampler::Repeat:
+ return GL_REPEAT;
+ case QRhiSampler::ClampToEdge:
+ return GL_CLAMP_TO_EDGE;
+ case QRhiSampler::Mirror:
+ return GL_MIRRORED_REPEAT;
+ case QRhiSampler::MirrorOnce:
+ Q_FALLTHROUGH();
+ case QRhiSampler::Border:
+ qWarning("Unsupported wrap mode %d", m);
+ return GL_CLAMP_TO_EDGE;
+ default:
+ Q_UNREACHABLE();
+ return GL_CLAMP_TO_EDGE;
+ }
+}
+
+static inline GLenum toGlTextureCompareFunc(QRhiSampler::CompareOp op)
+{
+ switch (op) {
+ case QRhiSampler::Never:
+ return GL_NEVER;
+ case QRhiSampler::Less:
+ return GL_LESS;
+ case QRhiSampler::Equal:
+ return GL_EQUAL;
+ case QRhiSampler::LessOrEqual:
+ return GL_LEQUAL;
+ case QRhiSampler::Greater:
+ return GL_GREATER;
+ case QRhiSampler::NotEqual:
+ return GL_NOTEQUAL;
+ case QRhiSampler::GreaterOrEqual:
+ return GL_GEQUAL;
+ case QRhiSampler::Always:
+ return GL_ALWAYS;
+ default:
+ Q_UNREACHABLE();
+ return GL_NEVER;
+ }
+}
+
+void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
+{
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+ GLenum indexType = GL_UNSIGNED_SHORT;
+ quint32 indexStride = sizeof(quint16);
+ quint32 indexOffset = 0;
+
+ for (const QGles2CommandBuffer::Command &cmd : qAsConst(cbD->commands)) {
+ switch (cmd.cmd) {
+ case QGles2CommandBuffer::Command::BeginFrame:
+ if (caps.coreProfile) {
+ if (!vao)
+ f->glGenVertexArrays(1, &vao);
+ f->glBindVertexArray(vao);
+ }
+ break;
+ case QGles2CommandBuffer::Command::EndFrame:
+ if (vao)
+ f->glBindVertexArray(0);
+ break;
+ case QGles2CommandBuffer::Command::Viewport:
+ f->glViewport(cmd.args.viewport.x, cmd.args.viewport.y, cmd.args.viewport.w, cmd.args.viewport.h);
+ f->glDepthRangef(cmd.args.viewport.d0, cmd.args.viewport.d1);
+ break;
+ case QGles2CommandBuffer::Command::Scissor:
+ f->glScissor(cmd.args.scissor.x, cmd.args.scissor.y, cmd.args.scissor.w, cmd.args.scissor.h);
+ break;
+ case QGles2CommandBuffer::Command::BlendConstants:
+ f->glBlendColor(cmd.args.blendConstants.r, cmd.args.blendConstants.g, cmd.args.blendConstants.b, cmd.args.blendConstants.a);
+ break;
+ case QGles2CommandBuffer::Command::StencilRef:
+ {
+ QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.stencilRef.ps);
+ if (psD) {
+ f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), cmd.args.stencilRef.ref, psD->m_stencilReadMask);
+ f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), cmd.args.stencilRef.ref, psD->m_stencilReadMask);
+ } else {
+ qWarning("No graphics pipeline active for setStencilRef; ignored");
+ }
+ }
+ break;
+ case QGles2CommandBuffer::Command::BindVertexBuffer:
+ {
+ QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.bindVertexBuffer.ps);
+ if (psD) {
+ const QVector<QRhiVertexInputBinding> bindings = psD->m_vertexInputLayout.bindings();
+ const QVector<QRhiVertexInputAttribute> attributes = psD->m_vertexInputLayout.attributes();
+ for (const QRhiVertexInputAttribute &a : attributes) {
+ if (a.binding() != cmd.args.bindVertexBuffer.binding)
+ continue;
+
+ // we do not support more than one vertex buffer
+ f->glBindBuffer(GL_ARRAY_BUFFER, cmd.args.bindVertexBuffer.buffer);
+
+ const int stride = bindings[a.binding()].stride();
+ int size = 1;
+ GLenum type = GL_FLOAT;
+ bool normalize = false;
+ switch (a.format()) {
+ case QRhiVertexInputAttribute::Float4:
+ type = GL_FLOAT;
+ size = 4;
+ break;
+ case QRhiVertexInputAttribute::Float3:
+ type = GL_FLOAT;
+ size = 3;
+ break;
+ case QRhiVertexInputAttribute::Float2:
+ type = GL_FLOAT;
+ size = 2;
+ break;
+ case QRhiVertexInputAttribute::Float:
+ type = GL_FLOAT;
+ size = 1;
+ break;
+ case QRhiVertexInputAttribute::UNormByte4:
+ type = GL_UNSIGNED_BYTE;
+ normalize = true;
+ size = 4;
+ break;
+ case QRhiVertexInputAttribute::UNormByte2:
+ type = GL_UNSIGNED_BYTE;
+ normalize = true;
+ size = 2;
+ break;
+ case QRhiVertexInputAttribute::UNormByte:
+ type = GL_UNSIGNED_BYTE;
+ normalize = true;
+ size = 1;
+ break;
+ default:
+ break;
+ }
+ quint32 ofs = a.offset() + cmd.args.bindVertexBuffer.offset;
+ f->glVertexAttribPointer(a.location(), size, type, normalize, stride,
+ reinterpret_cast<const GLvoid *>(quintptr(ofs)));
+ f->glEnableVertexAttribArray(a.location());
+ }
+ } else {
+ qWarning("No graphics pipeline active for setVertexInput; ignored");
+ }
+ }
+ break;
+ case QGles2CommandBuffer::Command::BindIndexBuffer:
+ indexType = cmd.args.bindIndexBuffer.type;
+ indexStride = indexType == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32);
+ indexOffset = cmd.args.bindIndexBuffer.offset;
+ f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cmd.args.bindIndexBuffer.buffer);
+ break;
+ case QGles2CommandBuffer::Command::Draw:
+ {
+ QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.draw.ps);
+ if (psD)
+ f->glDrawArrays(psD->drawMode, cmd.args.draw.firstVertex, cmd.args.draw.vertexCount);
+ else
+ qWarning("No graphics pipeline active for draw; ignored");
+ }
+ break;
+ case QGles2CommandBuffer::Command::DrawIndexed:
+ {
+ QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.drawIndexed.ps);
+ if (psD) {
+ quint32 ofs = cmd.args.drawIndexed.firstIndex * indexStride + indexOffset;
+ f->glDrawElements(psD->drawMode,
+ cmd.args.drawIndexed.indexCount,
+ indexType,
+ reinterpret_cast<const GLvoid *>(quintptr(ofs)));
+ } else {
+ qWarning("No graphics pipeline active for drawIndexed; ignored");
+ }
+ }
+ break;
+ case QGles2CommandBuffer::Command::BindGraphicsPipeline:
+ executeBindGraphicsPipeline(cmd.args.bindGraphicsPipeline.ps);
+ break;
+ case QGles2CommandBuffer::Command::BindShaderResources:
+ bindShaderResources(cmd.args.bindShaderResources.ps,
+ cmd.args.bindShaderResources.srb,
+ cmd.args.bindShaderResources.dynamicOffsetPairs,
+ cmd.args.bindShaderResources.dynamicOffsetCount);
+ break;
+ case QGles2CommandBuffer::Command::BindFramebuffer:
+ if (cmd.args.bindFramebuffer.fbo) {
+ f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.bindFramebuffer.fbo);
+ if (caps.maxDrawBuffers > 1) {
+ const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
+ QVarLengthArray<GLenum, 8> bufs;
+ for (int i = 0; i < colorAttCount; ++i)
+ bufs.append(GL_COLOR_ATTACHMENT0 + i);
+ f->glDrawBuffers(colorAttCount, bufs.constData());
+ }
+ } else {
+ f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
+ if (caps.maxDrawBuffers > 1) {
+ GLenum bufs = GL_BACK;
+ f->glDrawBuffers(1, &bufs);
+ }
+ }
+ if (caps.srgbCapableDefaultFramebuffer) {
+ if (cmd.args.bindFramebuffer.srgb)
+ f->glEnable(GL_FRAMEBUFFER_SRGB);
+ else
+ f->glDisable(GL_FRAMEBUFFER_SRGB);
+ }
+ break;
+ case QGles2CommandBuffer::Command::Clear:
+ f->glDisable(GL_SCISSOR_TEST);
+ if (cmd.args.clear.mask & GL_COLOR_BUFFER_BIT) {
+ f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ f->glClearColor(cmd.args.clear.c[0], cmd.args.clear.c[1], cmd.args.clear.c[2], cmd.args.clear.c[3]);
+ }
+ if (cmd.args.clear.mask & GL_DEPTH_BUFFER_BIT) {
+ f->glDepthMask(GL_TRUE);
+ f->glClearDepthf(cmd.args.clear.d);
+ }
+ if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT)
+ f->glClearStencil(cmd.args.clear.s);
+ f->glClear(cmd.args.clear.mask);
+ break;
+ case QGles2CommandBuffer::Command::BufferSubData:
+ f->glBindBuffer(cmd.args.bufferSubData.target, cmd.args.bufferSubData.buffer);
+ f->glBufferSubData(cmd.args.bufferSubData.target, cmd.args.bufferSubData.offset, cmd.args.bufferSubData.size,
+ cmd.args.bufferSubData.data);
+ break;
+ case QGles2CommandBuffer::Command::CopyTex:
+ {
+ GLuint fbo;
+ f->glGenFramebuffers(1, &fbo);
+ f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
+ f->glBindTexture(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstTexture);
+ f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
+ cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
+ cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
+ cmd.args.copyTex.w, cmd.args.copyTex.h);
+ f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
+ f->glDeleteFramebuffers(1, &fbo);
+ }
+ break;
+ case QGles2CommandBuffer::Command::ReadPixels:
+ {
+ QRhiReadbackResult *result = cmd.args.readPixels.result;
+ GLuint tex = cmd.args.readPixels.texture;
+ GLuint fbo = 0;
+ if (tex) {
+ result->pixelSize = QSize(cmd.args.readPixels.w, cmd.args.readPixels.h);
+ result->format = cmd.args.readPixels.format;
+ f->glGenFramebuffers(1, &fbo);
+ f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ cmd.args.readPixels.readTarget, cmd.args.readPixels.texture, cmd.args.readPixels.level);
+ } else {
+ result->pixelSize = currentSwapChain->pixelSize;
+ result->format = QRhiTexture::RGBA8;
+ // readPixels handles multisample resolving implicitly
+ }
+ result->data.resize(result->pixelSize.width() * result->pixelSize.height() * 4);
+ // With GLES (2.0?) GL_RGBA is the only mandated readback format, so stick with it.
+ f->glReadPixels(0, 0, result->pixelSize.width(), result->pixelSize.height(),
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ result->data.data());
+ if (fbo) {
+ f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
+ f->glDeleteFramebuffers(1, &fbo);
+ }
+ if (result->completed)
+ result->completed();
+ }
+ break;
+ case QGles2CommandBuffer::Command::SubImage:
+ f->glBindTexture(cmd.args.subImage.target, cmd.args.subImage.texture);
+ if (cmd.args.subImage.rowStartAlign != 4)
+ f->glPixelStorei(GL_UNPACK_ALIGNMENT, cmd.args.subImage.rowStartAlign);
+ f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
+ cmd.args.subImage.dx, cmd.args.subImage.dy,
+ cmd.args.subImage.w, cmd.args.subImage.h,
+ cmd.args.subImage.glformat, cmd.args.subImage.gltype,
+ cmd.args.subImage.data);
+ if (cmd.args.subImage.rowStartAlign != 4)
+ f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ break;
+ case QGles2CommandBuffer::Command::CompressedImage:
+ f->glBindTexture(cmd.args.compressedImage.target, cmd.args.compressedImage.texture);
+ f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
+ cmd.args.compressedImage.glintformat,
+ cmd.args.compressedImage.w, cmd.args.compressedImage.h, 0,
+ cmd.args.compressedImage.size, cmd.args.compressedImage.data);
+ break;
+ case QGles2CommandBuffer::Command::CompressedSubImage:
+ f->glBindTexture(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.texture);
+ f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
+ cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
+ cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h,
+ cmd.args.compressedSubImage.glintformat,
+ cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
+ break;
+ case QGles2CommandBuffer::Command::BlitFromRenderbuffer:
+ {
+ GLuint fbo[2];
+ f->glGenFramebuffers(2, fbo);
+ f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo[0]);
+ f->glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, cmd.args.blitFromRb.renderbuffer);
+ f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]);
+
+ f->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromRb.target,
+ cmd.args.blitFromRb.texture, cmd.args.blitFromRb.dstLevel);
+ f->glBlitFramebuffer(0, 0, cmd.args.blitFromRb.w, cmd.args.blitFromRb.h,
+ 0, 0, cmd.args.blitFromRb.w, cmd.args.blitFromRb.h,
+ GL_COLOR_BUFFER_BIT,
+ GL_LINEAR);
+ f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
+ }
+ break;
+ case QGles2CommandBuffer::Command::GenMip:
+ f->glBindTexture(cmd.args.genMip.target, cmd.args.genMip.texture);
+ f->glGenerateMipmap(cmd.args.genMip.target);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void QRhiGles2::executeBindGraphicsPipeline(QRhiGraphicsPipeline *ps)
+{
+ QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, ps);
+
+ // No state tracking logic as of now. Could introduce something to reduce
+ // the number of gl* calls (when using and changing between multiple
+ // pipelines), but then begin/endExternal() should invalidate the cached
+ // state as appropriate.
+
+ if (psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor))
+ f->glEnable(GL_SCISSOR_TEST);
+ else
+ f->glDisable(GL_SCISSOR_TEST);
+ if (psD->m_cullMode == QRhiGraphicsPipeline::None) {
+ f->glDisable(GL_CULL_FACE);
+ } else {
+ f->glEnable(GL_CULL_FACE);
+ f->glCullFace(toGlCullMode(psD->m_cullMode));
+ }
+ f->glFrontFace(toGlFrontFace(psD->m_frontFace));
+ if (!psD->m_targetBlends.isEmpty()) {
+ const QRhiGraphicsPipeline::TargetBlend &blend(psD->m_targetBlends.first()); // no MRT
+ GLboolean wr = blend.colorWrite.testFlag(QRhiGraphicsPipeline::R);
+ GLboolean wg = blend.colorWrite.testFlag(QRhiGraphicsPipeline::G);
+ GLboolean wb = blend.colorWrite.testFlag(QRhiGraphicsPipeline::B);
+ GLboolean wa = blend.colorWrite.testFlag(QRhiGraphicsPipeline::A);
+ f->glColorMask(wr, wg, wb, wa);
+ if (blend.enable) {
+ f->glEnable(GL_BLEND);
+ f->glBlendFuncSeparate(toGlBlendFactor(blend.srcColor),
+ toGlBlendFactor(blend.dstColor),
+ toGlBlendFactor(blend.srcAlpha),
+ toGlBlendFactor(blend.dstAlpha));
+ f->glBlendEquationSeparate(toGlBlendOp(blend.opColor), toGlBlendOp(blend.opAlpha));
+ } else {
+ f->glDisable(GL_BLEND);
+ }
+ } else {
+ f->glDisable(GL_BLEND);
+ }
+ if (psD->m_depthTest)
+ f->glEnable(GL_DEPTH_TEST);
+ else
+ f->glDisable(GL_DEPTH_TEST);
+ if (psD->m_depthWrite)
+ f->glDepthMask(GL_TRUE);
+ else
+ f->glDepthMask(GL_FALSE);
+ f->glDepthFunc(toGlCompareOp(psD->m_depthOp));
+ if (psD->m_stencilTest) {
+ f->glEnable(GL_STENCIL_TEST);
+ f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), 0, psD->m_stencilReadMask);
+ f->glStencilOpSeparate(GL_FRONT,
+ toGlStencilOp(psD->m_stencilFront.failOp),
+ toGlStencilOp(psD->m_stencilFront.depthFailOp),
+ toGlStencilOp(psD->m_stencilFront.passOp));
+ f->glStencilMaskSeparate(GL_FRONT, psD->m_stencilWriteMask);
+ f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), 0, psD->m_stencilReadMask);
+ f->glStencilOpSeparate(GL_BACK,
+ toGlStencilOp(psD->m_stencilBack.failOp),
+ toGlStencilOp(psD->m_stencilBack.depthFailOp),
+ toGlStencilOp(psD->m_stencilBack.passOp));
+ f->glStencilMaskSeparate(GL_BACK, psD->m_stencilWriteMask);
+ } else {
+ f->glDisable(GL_STENCIL_TEST);
+ }
+
+ f->glUseProgram(psD->program);
+}
+
+void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *ps, QRhiShaderResourceBindings *srb,
+ const uint *dynOfsPairs, int dynOfsCount)
+{
+ QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, ps);
+ QGles2ShaderResourceBindings *srbD = QRHI_RES(QGles2ShaderResourceBindings, srb);
+ int texUnit = 0;
+
+ for (int i = 0, ie = srbD->m_bindings.count(); i != ie; ++i) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->m_bindings[i]);
+
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ {
+ int viewOffset = b->u.ubuf.offset;
+ if (dynOfsCount) {
+ for (int j = 0; j < dynOfsCount; ++j) {
+ if (dynOfsPairs[2 * j] == uint(b->binding)) {
+ viewOffset = dynOfsPairs[2 * j + 1];
+ break;
+ }
+ }
+ }
+ QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.ubuf.buf);
+ const QByteArray bufView = QByteArray::fromRawData(bufD->ubuf.constData() + viewOffset,
+ b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size);
+ for (QGles2GraphicsPipeline::Uniform &uniform : psD->uniforms) {
+ if (uniform.binding == b->binding) {
+ // in a uniform buffer everything is at least 4 byte aligned
+ // so this should not cause unaligned reads
+ const void *src = bufView.constData() + uniform.offset;
+
+ switch (uniform.type) {
+ case QShaderDescription::Float:
+ f->glUniform1f(uniform.glslLocation, *reinterpret_cast<const float *>(src));
+ break;
+ case QShaderDescription::Vec2:
+ f->glUniform2fv(uniform.glslLocation, 1, reinterpret_cast<const float *>(src));
+ break;
+ case QShaderDescription::Vec3:
+ f->glUniform3fv(uniform.glslLocation, 1, reinterpret_cast<const float *>(src));
+ break;
+ case QShaderDescription::Vec4:
+ f->glUniform4fv(uniform.glslLocation, 1, reinterpret_cast<const float *>(src));
+ break;
+ case QShaderDescription::Mat2:
+ f->glUniformMatrix2fv(uniform.glslLocation, 1, GL_FALSE, reinterpret_cast<const float *>(src));
+ break;
+ case QShaderDescription::Mat3:
+ f->glUniformMatrix3fv(uniform.glslLocation, 1, GL_FALSE, reinterpret_cast<const float *>(src));
+ break;
+ case QShaderDescription::Mat4:
+ f->glUniformMatrix4fv(uniform.glslLocation, 1, GL_FALSE, reinterpret_cast<const float *>(src));
+ break;
+ case QShaderDescription::Int:
+ f->glUniform1i(uniform.glslLocation, *reinterpret_cast<const qint32 *>(src));
+ break;
+ case QShaderDescription::Int2:
+ f->glUniform2iv(uniform.glslLocation, 1, reinterpret_cast<const qint32 *>(src));
+ break;
+ case QShaderDescription::Int3:
+ f->glUniform3iv(uniform.glslLocation, 1, reinterpret_cast<const qint32 *>(src));
+ break;
+ case QShaderDescription::Int4:
+ f->glUniform4iv(uniform.glslLocation, 1, reinterpret_cast<const qint32 *>(src));
+ break;
+ // ### more types
+ default:
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ {
+ QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.stex.tex);
+ QGles2Sampler *samplerD = QRHI_RES(QGles2Sampler, b->u.stex.sampler);
+
+ for (QGles2GraphicsPipeline::Sampler &sampler : psD->samplers) {
+ if (sampler.binding == b->binding) {
+ f->glActiveTexture(GL_TEXTURE0 + texUnit);
+ f->glBindTexture(texD->target, texD->texture);
+
+ if (texD->samplerState != samplerD->d) {
+ f->glTexParameteri(texD->target, GL_TEXTURE_MIN_FILTER, samplerD->d.glminfilter);
+ f->glTexParameteri(texD->target, GL_TEXTURE_MAG_FILTER, samplerD->d.glmagfilter);
+ f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_S, samplerD->d.glwraps);
+ f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_T, samplerD->d.glwrapt);
+ // 3D textures not supported by GLES 2.0 or by us atm...
+ //f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_R, samplerD->d.glwrapr);
+ if (samplerD->d.gltexcomparefunc != GL_NEVER) {
+ f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_FUNC, samplerD->d.gltexcomparefunc);
+ } else {
+ f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ }
+ texD->samplerState = samplerD->d;
+ }
+
+ f->glUniform1i(sampler.glslLocation, texUnit);
+ ++texUnit;
+ }
+ }
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+
+ if (texUnit > 1)
+ f->glActiveTexture(GL_TEXTURE0);
+}
+
+void QRhiGles2::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inFrame && !inPass);
+
+ enqueueResourceUpdates(cb, resourceUpdates);
+}
+
+QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD,
+ bool *wantsColorClear, bool *wantsDsClear)
+{
+ QGles2RenderTargetData *rtD = nullptr;
+ QGles2CommandBuffer::Command fbCmd;
+ fbCmd.cmd = QGles2CommandBuffer::Command::BindFramebuffer;
+ switch (rt->resourceType()) {
+ case QRhiResource::RenderTarget:
+ rtD = &QRHI_RES(QGles2ReferenceRenderTarget, rt)->d;
+ if (wantsColorClear)
+ *wantsColorClear = true;
+ if (wantsDsClear)
+ *wantsDsClear = true;
+ fbCmd.args.bindFramebuffer.fbo = 0;
+ fbCmd.args.bindFramebuffer.colorAttCount = 1;
+ break;
+ case QRhiResource::TextureRenderTarget:
+ {
+ QGles2TextureRenderTarget *rtTex = QRHI_RES(QGles2TextureRenderTarget, rt);
+ rtD = &rtTex->d;
+ if (wantsColorClear)
+ *wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
+ if (wantsDsClear)
+ *wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
+ fbCmd.args.bindFramebuffer.fbo = rtTex->framebuffer;
+ fbCmd.args.bindFramebuffer.colorAttCount = rtD->colorAttCount;
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ fbCmd.args.bindFramebuffer.srgb = rtD->srgbUpdateAndBlend;
+ cbD->commands.append(fbCmd);
+ return rtD;
+}
+
+void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inFrame && !inPass);
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cb, resourceUpdates);
+
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+ bool wantsColorClear, wantsDsClear;
+ QGles2RenderTargetData *rtD = enqueueBindFramebuffer(rt, cbD, &wantsColorClear, &wantsDsClear);
+
+ QGles2CommandBuffer::Command clearCmd;
+ clearCmd.cmd = QGles2CommandBuffer::Command::Clear;
+ clearCmd.args.clear.mask = 0;
+ if (rtD->colorAttCount && wantsColorClear)
+ clearCmd.args.clear.mask |= GL_COLOR_BUFFER_BIT;
+ if (rtD->dsAttCount && wantsDsClear)
+ clearCmd.args.clear.mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
+ clearCmd.args.clear.c[0] = colorClearValue.redF();
+ clearCmd.args.clear.c[1] = colorClearValue.greenF();
+ clearCmd.args.clear.c[2] = colorClearValue.blueF();
+ clearCmd.args.clear.c[3] = colorClearValue.alphaF();
+ clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
+ clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
+ cbD->commands.append(clearCmd);
+
+ cbD->currentTarget = rt;
+
+ inPass = true;
+}
+
+void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inPass);
+ inPass = false;
+
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+ if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
+ QGles2TextureRenderTarget *rtTex = QRHI_RES(QGles2TextureRenderTarget, cbD->currentTarget);
+ const QVector<QRhiColorAttachment> colorAttachments = rtTex->m_desc.colorAttachments();
+ if (!colorAttachments.isEmpty()) {
+ // handle only 1 color attachment and only (msaa) renderbuffer
+ const QRhiColorAttachment &colorAtt(colorAttachments[0]);
+ if (colorAtt.resolveTexture()) {
+ Q_ASSERT(colorAtt.renderBuffer());
+ QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, colorAtt.renderBuffer());
+ const QSize size = colorAtt.resolveTexture()->pixelSize();
+ if (rbD->pixelSize() != size) {
+ qWarning("Resolve source (%dx%d) and target (%dx%d) size does not match",
+ rbD->pixelSize().width(), rbD->pixelSize().height(), size.width(), size.height());
+ }
+ QGles2CommandBuffer::Command cmd;
+ cmd.cmd = QGles2CommandBuffer::Command::BlitFromRenderbuffer;
+ cmd.args.blitFromRb.renderbuffer = rbD->renderbuffer;
+ cmd.args.blitFromRb.w = size.width();
+ cmd.args.blitFromRb.h = size.height();
+ QGles2Texture *colorTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
+ const GLenum faceTargetBase = colorTexD->m_flags.testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ : colorTexD->target;
+ cmd.args.blitFromRb.target = faceTargetBase + colorAtt.resolveLayer();
+ cmd.args.blitFromRb.texture = colorTexD->texture;
+ cmd.args.blitFromRb.dstLevel = colorAtt.resolveLevel();
+ cbD->commands.append(cmd);
+ }
+ }
+ }
+
+ cbD->currentTarget = nullptr;
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cb, resourceUpdates);
+}
+
+QGles2Buffer::QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+ : QRhiBuffer(rhi, type, usage, size)
+{
+}
+
+QGles2Buffer::~QGles2Buffer()
+{
+ release();
+}
+
+void QGles2Buffer::release()
+{
+ if (!buffer)
+ return;
+
+ QRhiGles2::DeferredReleaseEntry e;
+ e.type = QRhiGles2::DeferredReleaseEntry::Buffer;
+
+ e.buffer.buffer = buffer;
+
+ buffer = 0;
+
+ QRHI_RES_RHI(QRhiGles2);
+ rhiD->releaseQueue.append(e);
+ QRHI_PROF;
+ QRHI_PROF_F(releaseBuffer(this));
+ rhiD->unregisterResource(this);
+}
+
+bool QGles2Buffer::build()
+{
+ if (buffer)
+ release();
+
+ QRHI_RES_RHI(QRhiGles2);
+ QRHI_PROF;
+
+ if (m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
+ if (m_usage.testFlag(QRhiBuffer::VertexBuffer) || m_usage.testFlag(QRhiBuffer::IndexBuffer)) {
+ qWarning("Uniform buffer: multiple usages specified, this is not supported by the OpenGL backend");
+ return false;
+ }
+ ubuf.resize(m_size);
+ QRHI_PROF_F(newBuffer(this, m_size, 0, 1));
+ return true;
+ }
+
+ if (!rhiD->ensureContext())
+ return false;
+
+ if (m_usage.testFlag(QRhiBuffer::VertexBuffer)) {
+ if (m_usage.testFlag(QRhiBuffer::IndexBuffer)) {
+ qWarning("Vertex buffer: multiple usages specified, this is not supported by the OpenGL backend");
+ return false;
+ }
+ target = GL_ARRAY_BUFFER;
+ }
+ if (m_usage.testFlag(QRhiBuffer::IndexBuffer))
+ target = GL_ELEMENT_ARRAY_BUFFER;
+
+ rhiD->f->glGenBuffers(1, &buffer);
+ rhiD->f->glBindBuffer(target, buffer);
+ rhiD->f->glBufferData(target, m_size, nullptr, m_type == Dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+
+ QRHI_PROF_F(newBuffer(this, m_size, 1, 0));
+ rhiD->registerResource(this);
+ return true;
+}
+
+QGles2RenderBuffer::QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags)
+ : QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
+{
+}
+
+QGles2RenderBuffer::~QGles2RenderBuffer()
+{
+ release();
+}
+
+void QGles2RenderBuffer::release()
+{
+ if (!renderbuffer)
+ return;
+
+ QRhiGles2::DeferredReleaseEntry e;
+ e.type = QRhiGles2::DeferredReleaseEntry::RenderBuffer;
+
+ e.renderbuffer.renderbuffer = renderbuffer;
+ e.renderbuffer.renderbuffer2 = stencilRenderbuffer;
+
+ renderbuffer = 0;
+ stencilRenderbuffer = 0;
+
+ QRHI_RES_RHI(QRhiGles2);
+ rhiD->releaseQueue.append(e);
+ QRHI_PROF;
+ QRHI_PROF_F(releaseRenderBuffer(this));
+ rhiD->unregisterResource(this);
+}
+
+bool QGles2RenderBuffer::build()
+{
+ if (renderbuffer)
+ release();
+
+ QRHI_RES_RHI(QRhiGles2);
+ QRHI_PROF;
+ samples = rhiD->effectiveSampleCount(m_sampleCount);
+
+ if (m_flags.testFlag(UsedWithSwapChainOnly)) {
+ if (m_type == DepthStencil) {
+ QRHI_PROF_F(newRenderBuffer(this, false, true, samples));
+ return true;
+ }
+
+ qWarning("RenderBuffer: UsedWithSwapChainOnly is meaningless in combination with Color");
+ }
+
+ if (m_pixelSize.isEmpty())
+ return false;
+
+ if (!rhiD->ensureContext())
+ return false;
+
+ rhiD->f->glGenRenderbuffers(1, &renderbuffer);
+ rhiD->f->glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+
+ switch (m_type) {
+ case QRhiRenderBuffer::DepthStencil:
+ if (rhiD->caps.msaaRenderBuffer && samples > 1) {
+ rhiD->f->glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8,
+ m_pixelSize.width(), m_pixelSize.height());
+ } else {
+ if (rhiD->caps.packedDepthStencil) {
+ rhiD->f->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
+ m_pixelSize.width(), m_pixelSize.height());
+ stencilRenderbuffer = 0;
+ } else {
+ rhiD->f->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_ATTACHMENT,
+ m_pixelSize.width(), m_pixelSize.height());
+ rhiD->f->glGenRenderbuffers(1, &stencilRenderbuffer);
+ rhiD->f->glBindRenderbuffer(GL_RENDERBUFFER, stencilRenderbuffer);
+ rhiD->f->glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_ATTACHMENT,
+ m_pixelSize.width(), m_pixelSize.height());
+ }
+ }
+ QRHI_PROF_F(newRenderBuffer(this, false, false, samples));
+ break;
+ case QRhiRenderBuffer::Color:
+ if (rhiD->caps.msaaRenderBuffer && samples > 1)
+ rhiD->f->glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8,
+ m_pixelSize.width(), m_pixelSize.height());
+ else
+ rhiD->f->glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8,
+ m_pixelSize.width(), m_pixelSize.height());
+ QRHI_PROF_F(newRenderBuffer(this, false, false, samples));
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ rhiD->registerResource(this);
+ return true;
+}
+
+QRhiTexture::Format QGles2RenderBuffer::backingFormat() const
+{
+ return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
+}
+
+QGles2Texture::QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, sampleCount, flags)
+{
+}
+
+QGles2Texture::~QGles2Texture()
+{
+ release();
+}
+
+void QGles2Texture::release()
+{
+ if (!texture)
+ return;
+
+ QRhiGles2::DeferredReleaseEntry e;
+ e.type = QRhiGles2::DeferredReleaseEntry::Texture;
+
+ e.texture.texture = texture;
+
+ texture = 0;
+ specified = false;
+ nativeHandlesStruct.texture = 0;
+
+ QRHI_RES_RHI(QRhiGles2);
+ if (owns)
+ rhiD->releaseQueue.append(e);
+ QRHI_PROF;
+ QRHI_PROF_F(releaseTexture(this));
+ rhiD->unregisterResource(this);
+}
+
+static inline bool isPowerOfTwo(int x)
+{
+ // Assumption: x >= 1
+ return x == (x & -x);
+}
+
+bool QGles2Texture::prepareBuild(QSize *adjustedSize)
+{
+ if (texture)
+ release();
+
+ QRHI_RES_RHI(QRhiGles2);
+ if (!rhiD->ensureContext())
+ return false;
+
+ QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
+ if (!rhiD->caps.npotTexture && (!isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height())))
+ size = QSize(qNextPowerOfTwo(size.width()), qNextPowerOfTwo(size.height()));
+
+ const bool isCube = m_flags.testFlag(CubeMap);
+ const bool hasMipMaps = m_flags.testFlag(MipMapped);
+ const bool isCompressed = rhiD->isCompressedFormat(m_format);
+
+ target = isCube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
+ mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
+ gltype = GL_UNSIGNED_BYTE;
+
+ if (isCompressed) {
+ glintformat = toGlCompressedTextureFormat(m_format, m_flags);
+ if (!glintformat) {
+ qWarning("Compressed format %d not mappable to GL compressed format", m_format);
+ return false;
+ }
+ glformat = GL_RGBA;
+ } else {
+ switch (m_format) {
+ case QRhiTexture::RGBA8:
+ glintformat = GL_RGBA;
+ glformat = GL_RGBA;
+ break;
+ case QRhiTexture::BGRA8:
+ glintformat = rhiD->caps.bgraInternalFormat ? GL_BGRA : GL_RGBA;
+ glformat = GL_BGRA;
+ break;
+ case QRhiTexture::R16:
+ glintformat = GL_R16;
+ glformat = GL_RED;
+ gltype = GL_UNSIGNED_SHORT;
+ break;
+ case QRhiTexture::R8:
+ glintformat = GL_R8;
+ glformat = GL_RED;
+ break;
+ case QRhiTexture::RED_OR_ALPHA8:
+ glintformat = rhiD->caps.coreProfile ? GL_R8 : GL_ALPHA;
+ glformat = rhiD->caps.coreProfile ? GL_RED : GL_ALPHA;
+ break;
+ case QRhiTexture::RGBA16F:
+ glintformat = GL_RGBA16F;
+ glformat = GL_RGBA;
+ gltype = GL_HALF_FLOAT;
+ break;
+ case QRhiTexture::RGBA32F:
+ glintformat = GL_RGBA32F;
+ glformat = GL_RGBA;
+ gltype = GL_FLOAT;
+ break;
+ case QRhiTexture::D16:
+ glintformat = GL_DEPTH_COMPONENT16;
+ glformat = GL_DEPTH_COMPONENT;
+ gltype = GL_UNSIGNED_SHORT;
+ break;
+ case QRhiTexture::D32F:
+ glintformat = GL_DEPTH_COMPONENT32F;
+ glformat = GL_DEPTH_COMPONENT;
+ gltype = GL_FLOAT;
+ break;
+ default:
+ Q_UNREACHABLE();
+ glintformat = GL_RGBA;
+ glformat = GL_RGBA;
+ break;
+ }
+ }
+
+ samplerState = QGles2SamplerData();
+
+ if (adjustedSize)
+ *adjustedSize = size;
+
+ return true;
+}
+
+bool QGles2Texture::build()
+{
+ QSize size;
+ if (!prepareBuild(&size))
+ return false;
+
+ QRHI_RES_RHI(QRhiGles2);
+ rhiD->f->glGenTextures(1, &texture);
+
+ const bool isCube = m_flags.testFlag(CubeMap);
+ const bool hasMipMaps = m_flags.testFlag(MipMapped);
+ const bool isCompressed = rhiD->isCompressedFormat(m_format);
+ if (!isCompressed) {
+ rhiD->f->glBindTexture(target, texture);
+ if (hasMipMaps || isCube) {
+ const GLenum faceTargetBase = isCube ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
+ for (int layer = 0, layerCount = isCube ? 6 : 1; layer != layerCount; ++layer) {
+ for (int level = 0; level != mipLevelCount; ++level) {
+ const QSize mipSize = rhiD->q->sizeForMipLevel(level, size);
+ rhiD->f->glTexImage2D(faceTargetBase + layer, level, glintformat,
+ mipSize.width(), mipSize.height(), 0,
+ glformat, gltype, nullptr);
+ }
+ }
+ } else {
+ rhiD->f->glTexImage2D(target, 0, glintformat, size.width(), size.height(), 0, glformat, gltype, nullptr);
+ }
+ specified = true;
+ } else {
+ // Cannot use glCompressedTexImage2D without valid data, so defer.
+ // Compressed textures will not be used as render targets so this is
+ // not an issue.
+ specified = false;
+ }
+
+ QRHI_PROF;
+ QRHI_PROF_F(newTexture(this, true, mipLevelCount, isCube ? 6 : 1, 1));
+
+ owns = true;
+ nativeHandlesStruct.texture = texture;
+
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+bool QGles2Texture::buildFrom(const QRhiNativeHandles *src)
+{
+ const QRhiGles2TextureNativeHandles *h = static_cast<const QRhiGles2TextureNativeHandles *>(src);
+ if (!h || !h->texture)
+ return false;
+
+ if (!prepareBuild())
+ return false;
+
+ texture = h->texture;
+ specified = true;
+
+ QRHI_RES_RHI(QRhiGles2);
+ QRHI_PROF;
+ QRHI_PROF_F(newTexture(this, false, mipLevelCount, m_flags.testFlag(CubeMap) ? 6 : 1, 1));
+
+ owns = false;
+ nativeHandlesStruct.texture = texture;
+
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+const QRhiNativeHandles *QGles2Texture::nativeHandles()
+{
+ return &nativeHandlesStruct;
+}
+
+QGles2Sampler::QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+{
+}
+
+QGles2Sampler::~QGles2Sampler()
+{
+ release();
+}
+
+void QGles2Sampler::release()
+{
+ // nothing to do here
+}
+
+bool QGles2Sampler::build()
+{
+ d.glminfilter = toGlMinFilter(m_minFilter, m_mipmapMode);
+ d.glmagfilter = toGlMagFilter(m_magFilter);
+ d.glwraps = toGlWrapMode(m_addressU);
+ d.glwrapt = toGlWrapMode(m_addressV);
+ d.glwrapr = toGlWrapMode(m_addressW);
+ d.gltexcomparefunc = toGlTextureCompareFunc(m_compareOp);
+
+ generation += 1;
+ return true;
+}
+
+// dummy, no Vulkan-style RenderPass+Framebuffer concept here
+QGles2RenderPassDescriptor::QGles2RenderPassDescriptor(QRhiImplementation *rhi)
+ : QRhiRenderPassDescriptor(rhi)
+{
+}
+
+QGles2RenderPassDescriptor::~QGles2RenderPassDescriptor()
+{
+ release();
+}
+
+void QGles2RenderPassDescriptor::release()
+{
+ // nothing to do here
+}
+
+QGles2ReferenceRenderTarget::QGles2ReferenceRenderTarget(QRhiImplementation *rhi)
+ : QRhiRenderTarget(rhi),
+ d(rhi)
+{
+}
+
+QGles2ReferenceRenderTarget::~QGles2ReferenceRenderTarget()
+{
+ release();
+}
+
+void QGles2ReferenceRenderTarget::release()
+{
+ // nothing to do here
+}
+
+QSize QGles2ReferenceRenderTarget::pixelSize() const
+{
+ return d.pixelSize;
+}
+
+float QGles2ReferenceRenderTarget::devicePixelRatio() const
+{
+ return d.dpr;
+}
+
+int QGles2ReferenceRenderTarget::sampleCount() const
+{
+ return d.sampleCount;
+}
+
+QGles2TextureRenderTarget::QGles2TextureRenderTarget(QRhiImplementation *rhi,
+ const QRhiTextureRenderTargetDescription &desc,
+ Flags flags)
+ : QRhiTextureRenderTarget(rhi, desc, flags),
+ d(rhi)
+{
+}
+
+QGles2TextureRenderTarget::~QGles2TextureRenderTarget()
+{
+ release();
+}
+
+void QGles2TextureRenderTarget::release()
+{
+ if (!framebuffer)
+ return;
+
+ QRhiGles2::DeferredReleaseEntry e;
+ e.type = QRhiGles2::DeferredReleaseEntry::TextureRenderTarget;
+
+ e.textureRenderTarget.framebuffer = framebuffer;
+
+ framebuffer = 0;
+
+ QRHI_RES_RHI(QRhiGles2);
+ rhiD->releaseQueue.append(e);
+
+ rhiD->unregisterResource(this);
+}
+
+QRhiRenderPassDescriptor *QGles2TextureRenderTarget::newCompatibleRenderPassDescriptor()
+{
+ return new QGles2RenderPassDescriptor(m_rhi);
+}
+
+bool QGles2TextureRenderTarget::build()
+{
+ QRHI_RES_RHI(QRhiGles2);
+
+ if (framebuffer)
+ release();
+
+ const QVector<QRhiColorAttachment> colorAttachments = m_desc.colorAttachments();
+ Q_ASSERT(!colorAttachments.isEmpty() || m_desc.depthTexture());
+ Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
+ const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
+
+ if (colorAttachments.count() > rhiD->caps.maxDrawBuffers)
+ qWarning("QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)",
+ colorAttachments.count(), rhiD->caps.maxDrawBuffers);
+ if (m_desc.depthTexture() && !rhiD->caps.depthTexture)
+ qWarning("QGles2TextureRenderTarget: Depth texture is not supported and will be ignored");
+
+ if (!rhiD->ensureContext())
+ return false;
+
+ rhiD->f->glGenFramebuffers(1, &framebuffer);
+ rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+
+ d.colorAttCount = colorAttachments.count();
+ for (int i = 0; i < d.colorAttCount; ++i) {
+ const QRhiColorAttachment &colorAtt(colorAttachments[i]);
+ QRhiTexture *texture = colorAtt.texture();
+ QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
+ Q_ASSERT(texture || renderBuffer);
+ if (texture) {
+ QGles2Texture *texD = QRHI_RES(QGles2Texture, texture);
+ Q_ASSERT(texD->texture && texD->specified);
+ const GLenum faceTargetBase = texD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
+ rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, faceTargetBase + colorAtt.layer(), texD->texture, colorAtt.level());
+ if (i == 0) {
+ d.pixelSize = texD->pixelSize();
+ d.sampleCount = 1;
+ }
+ } else if (renderBuffer) {
+ QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, renderBuffer);
+ rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, rbD->renderbuffer);
+ if (i == 0) {
+ d.pixelSize = rbD->pixelSize();
+ d.sampleCount = rbD->samples;
+ }
+ }
+ }
+
+ if (hasDepthStencil) {
+ if (m_desc.depthStencilBuffer()) {
+ QGles2RenderBuffer *depthRbD = QRHI_RES(QGles2RenderBuffer, m_desc.depthStencilBuffer());
+ rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRbD->renderbuffer);
+ if (depthRbD->stencilRenderbuffer)
+ rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRbD->stencilRenderbuffer);
+ else // packed
+ rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRbD->renderbuffer);
+ if (d.colorAttCount == 0) {
+ d.pixelSize = depthRbD->pixelSize();
+ d.sampleCount = depthRbD->samples;
+ }
+ } else {
+ QGles2Texture *depthTexD = QRHI_RES(QGles2Texture, m_desc.depthTexture());
+ rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexD->texture, 0);
+ if (d.colorAttCount == 0) {
+ d.pixelSize = depthTexD->pixelSize();
+ d.sampleCount = 1;
+ }
+ }
+ d.dsAttCount = 1;
+ } else {
+ d.dsAttCount = 0;
+ }
+
+ d.dpr = 1;
+ d.rp = QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
+
+ GLenum status = rhiD->f->glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_NO_ERROR && status != GL_FRAMEBUFFER_COMPLETE) {
+ qWarning("Framebuffer incomplete: 0x%x", status);
+ return false;
+ }
+
+ rhiD->registerResource(this);
+ return true;
+}
+
+QSize QGles2TextureRenderTarget::pixelSize() const
+{
+ return d.pixelSize;
+}
+
+float QGles2TextureRenderTarget::devicePixelRatio() const
+{
+ return d.dpr;
+}
+
+int QGles2TextureRenderTarget::sampleCount() const
+{
+ return d.sampleCount;
+}
+
+QGles2ShaderResourceBindings::QGles2ShaderResourceBindings(QRhiImplementation *rhi)
+ : QRhiShaderResourceBindings(rhi)
+{
+}
+
+QGles2ShaderResourceBindings::~QGles2ShaderResourceBindings()
+{
+ release();
+}
+
+void QGles2ShaderResourceBindings::release()
+{
+ // nothing to do here
+}
+
+bool QGles2ShaderResourceBindings::build()
+{
+ generation += 1;
+ return true;
+}
+
+QGles2GraphicsPipeline::QGles2GraphicsPipeline(QRhiImplementation *rhi)
+ : QRhiGraphicsPipeline(rhi)
+{
+}
+
+QGles2GraphicsPipeline::~QGles2GraphicsPipeline()
+{
+ release();
+}
+
+void QGles2GraphicsPipeline::release()
+{
+ if (!program)
+ return;
+
+ QRhiGles2::DeferredReleaseEntry e;
+ e.type = QRhiGles2::DeferredReleaseEntry::Pipeline;
+
+ e.pipeline.program = program;
+
+ program = 0;
+ uniforms.clear();
+ samplers.clear();
+
+ QRHI_RES_RHI(QRhiGles2);
+ rhiD->releaseQueue.append(e);
+
+ rhiD->unregisterResource(this);
+}
+
+bool QGles2GraphicsPipeline::build()
+{
+ QRHI_RES_RHI(QRhiGles2);
+
+ if (program)
+ release();
+
+ if (!rhiD->ensureContext())
+ return false;
+
+ drawMode = toGlTopology(m_topology);
+
+ program = rhiD->f->glCreateProgram();
+
+ int sourceVer = 0;
+ for (const QRhiGraphicsShaderStage &shaderStage : qAsConst(m_shaderStages)) {
+ const bool isVertex = shaderStage.type() == QRhiGraphicsShaderStage::Vertex;
+ const bool isFragment = shaderStage.type() == QRhiGraphicsShaderStage::Fragment;
+ if (!isVertex && !isFragment)
+ continue;
+
+ GLuint shader = rhiD->f->glCreateShader(isVertex ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER);
+ const QShader bakedShader = shaderStage.shader();
+ QVector<int> versionsToTry;
+ QByteArray source;
+ if (rhiD->caps.gles) {
+ if (rhiD->caps.ctxMajor > 3 || (rhiD->caps.ctxMajor == 3 && rhiD->caps.ctxMinor >= 2)) {
+ versionsToTry << 320 << 310 << 300 << 100;
+ } else if (rhiD->caps.ctxMajor == 3 && rhiD->caps.ctxMinor == 1) {
+ versionsToTry << 310 << 300 << 100;
+ } else if (rhiD->caps.ctxMajor == 3 && rhiD->caps.ctxMinor == 0) {
+ versionsToTry << 300 << 100;
+ } else {
+ versionsToTry << 100;
+ }
+ for (int v : versionsToTry) {
+ QShaderVersion ver(v, QShaderVersion::GlslEs);
+ source = bakedShader.shader({ QShader::GlslShader, ver, shaderStage.shaderVariant() }).shader();
+ if (!source.isEmpty()) {
+ sourceVer = v;
+ break;
+ }
+ }
+ } else {
+ if (rhiD->caps.ctxMajor > 4 || (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor >= 6)) {
+ versionsToTry << 460 << 450 << 440 << 430 << 420 << 410 << 400 << 330 << 150;
+ } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 5) {
+ versionsToTry << 450 << 440 << 430 << 420 << 410 << 400 << 330 << 150;
+ } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 4) {
+ versionsToTry << 440 << 430 << 420 << 410 << 400 << 330 << 150;
+ } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 3) {
+ versionsToTry << 430 << 420 << 410 << 400 << 330 << 150;
+ } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 2) {
+ versionsToTry << 420 << 410 << 400 << 330 << 150;
+ } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 1) {
+ versionsToTry << 410 << 400 << 330 << 150;
+ } else if (rhiD->caps.ctxMajor == 4 && rhiD->caps.ctxMinor == 0) {
+ versionsToTry << 400 << 330 << 150;
+ } else if (rhiD->caps.ctxMajor == 3 && rhiD->caps.ctxMinor == 3) {
+ versionsToTry << 330 << 150;
+ } else if (rhiD->caps.ctxMajor == 3 && rhiD->caps.ctxMinor == 2) {
+ versionsToTry << 150;
+ }
+ if (!rhiD->caps.coreProfile)
+ versionsToTry << 120;
+ for (int v : versionsToTry) {
+ source = bakedShader.shader({ QShader::GlslShader, v, shaderStage.shaderVariant() }).shader();
+ if (!source.isEmpty()) {
+ sourceVer = v;
+ break;
+ }
+ }
+ }
+ if (source.isEmpty()) {
+ qWarning() << "No GLSL shader code found (versions tried: " << versionsToTry
+ << ") in baked shader" << bakedShader;
+ return false;
+ }
+
+ const char *srcStr = source.constData();
+ const GLint srcLength = source.count();
+ rhiD->f->glShaderSource(shader, 1, &srcStr, &srcLength);
+ rhiD->f->glCompileShader(shader);
+ GLint compiled = 0;
+ rhiD->f->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ GLint infoLogLength = 0;
+ rhiD->f->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+ QByteArray log;
+ if (infoLogLength > 1) {
+ GLsizei length = 0;
+ log.resize(infoLogLength);
+ rhiD->f->glGetShaderInfoLog(shader, infoLogLength, &length, log.data());
+ }
+ qWarning("Failed to compile shader: %s\nSource was:\n%s", log.constData(), source.constData());
+ return false;
+ }
+
+ rhiD->f->glAttachShader(program, shader);
+ rhiD->f->glDeleteShader(shader);
+
+ if (isVertex)
+ vsDesc = bakedShader.description();
+ else
+ fsDesc = bakedShader.description();
+ }
+
+ // not very useful atm since we assume the qsb-generated GLSL shaders never use uniform blocks
+ canUseUniformBuffers = rhiD->caps.uniformBuffers && sourceVer >= 140;
+
+ for (auto inVar : vsDesc.inputVariables()) {
+ const QByteArray name = inVar.name.toUtf8();
+ rhiD->f->glBindAttribLocation(program, inVar.location, name.constData());
+ }
+
+ rhiD->f->glLinkProgram(program);
+ GLint linked = 0;
+ rhiD->f->glGetProgramiv(program, GL_LINK_STATUS, &linked);
+ if (!linked) {
+ GLint infoLogLength = 0;
+ rhiD->f->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
+ QByteArray log;
+ if (infoLogLength > 1) {
+ GLsizei length = 0;
+ log.resize(infoLogLength);
+ rhiD->f->glGetProgramInfoLog(program, infoLogLength, &length, log.data());
+ }
+ qWarning("Failed to link shader program: %s", log.constData());
+ return false;
+ }
+
+ auto lookupUniforms = [this, rhiD](const QShaderDescription::UniformBlock &ub) {
+ const QByteArray prefix = ub.structName.toUtf8() + '.';
+ for (const QShaderDescription::BlockVariable &blockMember : ub.members) {
+ // ### no array support for now
+ Uniform uniform;
+ uniform.type = blockMember.type;
+ const QByteArray name = prefix + blockMember.name.toUtf8();
+ uniform.glslLocation = rhiD->f->glGetUniformLocation(program, name.constData());
+ if (uniform.glslLocation >= 0) {
+ uniform.binding = ub.binding;
+ uniform.offset = blockMember.offset;
+ uniform.size = blockMember.size;
+ uniforms.append(uniform);
+ }
+ }
+ };
+
+ for (const QShaderDescription::UniformBlock &ub : vsDesc.uniformBlocks())
+ lookupUniforms(ub);
+
+ for (const QShaderDescription::UniformBlock &ub : fsDesc.uniformBlocks())
+ lookupUniforms(ub);
+
+ auto lookupSamplers = [this, rhiD](const QShaderDescription::InOutVariable &v) {
+ Sampler sampler;
+ const QByteArray name = v.name.toUtf8();
+ sampler.glslLocation = rhiD->f->glGetUniformLocation(program, name.constData());
+ if (sampler.glslLocation >= 0) {
+ sampler.binding = v.binding;
+ samplers.append(sampler);
+ }
+ };
+
+ for (const QShaderDescription::InOutVariable &v : vsDesc.combinedImageSamplers())
+ lookupSamplers(v);
+
+ for (const QShaderDescription::InOutVariable &v : fsDesc.combinedImageSamplers())
+ lookupSamplers(v);
+
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QGles2CommandBuffer::QGles2CommandBuffer(QRhiImplementation *rhi)
+ : QRhiCommandBuffer(rhi)
+{
+ resetState();
+}
+
+QGles2CommandBuffer::~QGles2CommandBuffer()
+{
+ release();
+}
+
+void QGles2CommandBuffer::release()
+{
+ // nothing to do here
+}
+
+QGles2SwapChain::QGles2SwapChain(QRhiImplementation *rhi)
+ : QRhiSwapChain(rhi),
+ rt(rhi),
+ cb(rhi)
+{
+}
+
+QGles2SwapChain::~QGles2SwapChain()
+{
+ release();
+}
+
+void QGles2SwapChain::release()
+{
+ QRHI_PROF;
+ QRHI_PROF_F(releaseSwapChain(this));
+}
+
+QRhiCommandBuffer *QGles2SwapChain::currentFrameCommandBuffer()
+{
+ return &cb;
+}
+
+QRhiRenderTarget *QGles2SwapChain::currentFrameRenderTarget()
+{
+ return &rt;
+}
+
+QSize QGles2SwapChain::surfacePixelSize()
+{
+ Q_ASSERT(m_window);
+ return m_window->size() * m_window->devicePixelRatio();
+}
+
+QRhiRenderPassDescriptor *QGles2SwapChain::newCompatibleRenderPassDescriptor()
+{
+ return new QGles2RenderPassDescriptor(m_rhi);
+}
+
+bool QGles2SwapChain::buildOrResize()
+{
+ surface = m_window;
+ m_currentPixelSize = surfacePixelSize();
+ pixelSize = m_currentPixelSize;
+
+ rt.d.rp = QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
+ rt.d.pixelSize = pixelSize;
+ rt.d.dpr = m_window->devicePixelRatio();
+ rt.d.sampleCount = qBound(1, m_sampleCount, 64);
+ rt.d.colorAttCount = 1;
+ rt.d.dsAttCount = m_depthStencil ? 1 : 0;
+ rt.d.srgbUpdateAndBlend = m_flags.testFlag(QRhiSwapChain::sRGB);
+
+ frameCount = 0;
+
+ QRHI_PROF;
+ // make something up
+ QRHI_PROF_F(resizeSwapChain(this, 2, m_sampleCount > 1 ? 2 : 0, m_sampleCount));
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhigles2_p.h b/src/gui/rhi/qrhigles2_p.h
new file mode 100644
index 0000000000..7f7c8b4c40
--- /dev/null
+++ b/src/gui/rhi/qrhigles2_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHIGLES2_H
+#define QRHIGLES2_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qrhi_p.h>
+#include <QtGui/qsurfaceformat.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+class QOffscreenSurface;
+class QWindow;
+
+struct Q_GUI_EXPORT QRhiGles2InitParams : public QRhiInitParams
+{
+ QRhiGles2InitParams();
+
+ QSurfaceFormat format;
+ QOffscreenSurface *fallbackSurface = nullptr;
+ QWindow *window = nullptr;
+
+ static QOffscreenSurface *newFallbackSurface(const QSurfaceFormat &format = QSurfaceFormat::defaultFormat());
+ static QSurfaceFormat adjustedFormat(const QSurfaceFormat &format = QSurfaceFormat::defaultFormat());
+};
+
+struct Q_GUI_EXPORT QRhiGles2NativeHandles : public QRhiNativeHandles
+{
+ QOpenGLContext *context = nullptr;
+};
+
+struct Q_GUI_EXPORT QRhiGles2TextureNativeHandles : public QRhiNativeHandles
+{
+ uint texture = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h
new file mode 100644
index 0000000000..d1a8a1fadf
--- /dev/null
+++ b/src/gui/rhi/qrhigles2_p_p.h
@@ -0,0 +1,695 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHIGLES2_P_H
+#define QRHIGLES2_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrhigles2_p.h"
+#include "qrhi_p_p.h"
+#include "qshaderdescription_p.h"
+#include <qopengl.h>
+#include <QSurface>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLExtensions;
+
+struct QGles2Buffer : public QRhiBuffer
+{
+ QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
+ ~QGles2Buffer();
+ void release() override;
+ bool build() override;
+
+ GLuint buffer = 0;
+ GLenum target;
+ QByteArray ubuf;
+ friend class QRhiGles2;
+};
+
+struct QGles2RenderBuffer : public QRhiRenderBuffer
+{
+ QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags);
+ ~QGles2RenderBuffer();
+ void release() override;
+ bool build() override;
+ QRhiTexture::Format backingFormat() const override;
+
+ GLuint renderbuffer = 0;
+ GLuint stencilRenderbuffer = 0; // when packed depth-stencil not supported
+ int samples;
+ friend class QRhiGles2;
+};
+
+struct QGles2SamplerData
+{
+ GLenum glminfilter = 0;
+ GLenum glmagfilter = 0;
+ GLenum glwraps = 0;
+ GLenum glwrapt = 0;
+ GLenum glwrapr = 0;
+ GLenum gltexcomparefunc = 0;
+};
+
+inline bool operator==(const QGles2SamplerData &a, const QGles2SamplerData &b)
+{
+ return a.glminfilter == b.glminfilter
+ && a.glmagfilter == b.glmagfilter
+ && a.glwraps == b.glwraps
+ && a.glwrapt == b.glwrapt
+ && a.glwrapr == b.glwrapr
+ && a.gltexcomparefunc == b.gltexcomparefunc;
+}
+
+inline bool operator!=(const QGles2SamplerData &a, const QGles2SamplerData &b)
+{
+ return !(a == b);
+}
+
+struct QGles2Texture : public QRhiTexture
+{
+ QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ int sampleCount, Flags flags);
+ ~QGles2Texture();
+ void release() override;
+ bool build() override;
+ bool buildFrom(const QRhiNativeHandles *src) override;
+ const QRhiNativeHandles *nativeHandles() override;
+
+ bool prepareBuild(QSize *adjustedSize = nullptr);
+
+ GLuint texture = 0;
+ bool owns = true;
+ GLenum target;
+ GLenum glintformat;
+ GLenum glformat;
+ GLenum gltype;
+ QGles2SamplerData samplerState;
+ bool specified = false;
+ int mipLevelCount = 0;
+ QRhiGles2TextureNativeHandles nativeHandlesStruct;
+
+ uint generation = 0;
+ friend class QRhiGles2;
+};
+
+struct QGles2Sampler : public QRhiSampler
+{
+ QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v);
+ ~QGles2Sampler();
+ void release() override;
+ bool build() override;
+
+ QGles2SamplerData d;
+ uint generation = 0;
+ friend class QRhiGles2;
+};
+
+struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QGles2RenderPassDescriptor(QRhiImplementation *rhi);
+ ~QGles2RenderPassDescriptor();
+ void release() override;
+};
+
+struct QGles2RenderTargetData
+{
+ QGles2RenderTargetData(QRhiImplementation *) { }
+
+ QGles2RenderPassDescriptor *rp = nullptr;
+ QSize pixelSize;
+ float dpr = 1;
+ int sampleCount = 1;
+ int colorAttCount = 0;
+ int dsAttCount = 0;
+ bool srgbUpdateAndBlend = false;
+};
+
+struct QGles2ReferenceRenderTarget : public QRhiRenderTarget
+{
+ QGles2ReferenceRenderTarget(QRhiImplementation *rhi);
+ ~QGles2ReferenceRenderTarget();
+ void release() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QGles2RenderTargetData d;
+};
+
+struct QGles2TextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QGles2TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
+ ~QGles2TextureRenderTarget();
+ void release() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool build() override;
+
+ QGles2RenderTargetData d;
+ GLuint framebuffer = 0;
+ friend class QRhiGles2;
+};
+
+struct QGles2ShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QGles2ShaderResourceBindings(QRhiImplementation *rhi);
+ ~QGles2ShaderResourceBindings();
+ void release() override;
+ bool build() override;
+
+ uint generation = 0;
+ friend class QRhiGles2;
+};
+
+struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QGles2GraphicsPipeline(QRhiImplementation *rhi);
+ ~QGles2GraphicsPipeline();
+ void release() override;
+ bool build() override;
+
+ GLuint program = 0;
+ GLenum drawMode = GL_TRIANGLES;
+ QShaderDescription vsDesc;
+ QShaderDescription fsDesc;
+ bool canUseUniformBuffers = false;
+
+ struct Uniform {
+ QShaderDescription::VariableType type;
+ int glslLocation;
+ int binding;
+ uint offset;
+ int size;
+ };
+ QVector<Uniform> uniforms;
+
+ struct Sampler {
+ int glslLocation;
+ int binding;
+ };
+ QVector<Sampler> samplers;
+
+ uint generation = 0;
+ friend class QRhiGles2;
+};
+
+Q_DECLARE_TYPEINFO(QGles2GraphicsPipeline::Uniform, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QGles2GraphicsPipeline::Sampler, Q_MOVABLE_TYPE);
+
+struct QGles2CommandBuffer : public QRhiCommandBuffer
+{
+ QGles2CommandBuffer(QRhiImplementation *rhi);
+ ~QGles2CommandBuffer();
+ void release() override;
+
+ struct Command {
+ enum Cmd {
+ BeginFrame,
+ EndFrame,
+ Viewport,
+ Scissor,
+ BlendConstants,
+ StencilRef,
+ BindVertexBuffer,
+ BindIndexBuffer,
+ Draw,
+ DrawIndexed,
+ BindGraphicsPipeline,
+ BindShaderResources,
+ BindFramebuffer,
+ Clear,
+ BufferData,
+ BufferSubData,
+ CopyTex,
+ ReadPixels,
+ SubImage,
+ CompressedImage,
+ CompressedSubImage,
+ BlitFromRenderbuffer,
+ GenMip
+ };
+ Cmd cmd;
+
+ static const int MAX_UBUF_BINDINGS = 32; // should be more than enough
+
+ // QRhi*/QGles2* references should be kept at minimum (so no
+ // QRhiTexture/Buffer/etc. pointers).
+ union {
+ struct {
+ float x, y, w, h;
+ float d0, d1;
+ } viewport;
+ struct {
+ int x, y, w, h;
+ } scissor;
+ struct {
+ float r, g, b, a;
+ } blendConstants;
+ struct {
+ quint32 ref;
+ QRhiGraphicsPipeline *ps;
+ } stencilRef;
+ struct {
+ QRhiGraphicsPipeline *ps;
+ GLuint buffer;
+ quint32 offset;
+ int binding;
+ } bindVertexBuffer;
+ struct {
+ GLuint buffer;
+ quint32 offset;
+ GLenum type;
+ } bindIndexBuffer;
+ struct {
+ QRhiGraphicsPipeline *ps;
+ quint32 vertexCount;
+ quint32 firstVertex;
+ } draw;
+ struct {
+ QRhiGraphicsPipeline *ps;
+ quint32 indexCount;
+ quint32 firstIndex;
+ } drawIndexed;
+ struct {
+ QRhiGraphicsPipeline *ps;
+ } bindGraphicsPipeline;
+ struct {
+ QRhiGraphicsPipeline *ps;
+ QRhiShaderResourceBindings *srb;
+ int dynamicOffsetCount;
+ uint dynamicOffsetPairs[MAX_UBUF_BINDINGS * 2]; // binding, offsetInConstants
+ } bindShaderResources;
+ struct {
+ GLbitfield mask;
+ float c[4];
+ float d;
+ quint32 s;
+ } clear;
+ struct {
+ GLuint fbo;
+ bool srgb;
+ int colorAttCount;
+ } bindFramebuffer;
+ struct {
+ GLenum target;
+ GLuint buffer;
+ int offset;
+ int size;
+ const void *data; // must come from retainData()
+ } bufferSubData;
+ struct {
+ GLenum srcFaceTarget;
+ GLuint srcTexture;
+ int srcLevel;
+ int srcX;
+ int srcY;
+ GLenum dstTarget;
+ GLuint dstTexture;
+ GLenum dstFaceTarget;
+ int dstLevel;
+ int dstX;
+ int dstY;
+ int w;
+ int h;
+ } copyTex;
+ struct {
+ QRhiReadbackResult *result;
+ GLuint texture;
+ int w;
+ int h;
+ QRhiTexture::Format format;
+ GLenum readTarget;
+ int level;
+ } readPixels;
+ struct {
+ GLenum target;
+ GLuint texture;
+ GLenum faceTarget;
+ int level;
+ int dx;
+ int dy;
+ int w;
+ int h;
+ GLenum glformat;
+ GLenum gltype;
+ int rowStartAlign;
+ const void *data; // must come from retainImage()
+ } subImage;
+ struct {
+ GLenum target;
+ GLuint texture;
+ GLenum faceTarget;
+ int level;
+ GLenum glintformat;
+ int w;
+ int h;
+ int size;
+ const void *data; // must come from retainData()
+ } compressedImage;
+ struct {
+ GLenum target;
+ GLuint texture;
+ GLenum faceTarget;
+ int level;
+ int dx;
+ int dy;
+ int w;
+ int h;
+ GLenum glintformat;
+ int size;
+ const void *data; // must come from retainData()
+ } compressedSubImage;
+ struct {
+ GLuint renderbuffer;
+ int w;
+ int h;
+ GLenum target;
+ GLuint texture;
+ int dstLevel;
+ } blitFromRb;
+ struct {
+ GLenum target;
+ GLuint texture;
+ } genMip;
+ } args;
+ };
+
+ QVector<Command> commands;
+ QRhiRenderTarget *currentTarget;
+ QRhiGraphicsPipeline *currentPipeline;
+ uint currentPipelineGeneration;
+ QRhiShaderResourceBindings *currentSrb;
+ uint currentSrbGeneration;
+
+ QVector<QByteArray> dataRetainPool;
+ QVector<QImage> imageRetainPool;
+
+ // relies heavily on implicit sharing (no copies of the actual data will be made)
+ const void *retainData(const QByteArray &data) {
+ dataRetainPool.append(data);
+ return dataRetainPool.constLast().constData();
+ }
+ const void *retainImage(const QImage &image) {
+ imageRetainPool.append(image);
+ return imageRetainPool.constLast().constBits();
+ }
+ void resetCommands() {
+ commands.clear();
+ dataRetainPool.clear();
+ imageRetainPool.clear();
+ }
+ void resetState() {
+ resetCommands();
+ currentTarget = nullptr;
+ resetCachedState();
+ }
+ void resetCachedState() {
+ currentPipeline = nullptr;
+ currentPipelineGeneration = 0;
+ currentSrb = nullptr;
+ currentSrbGeneration = 0;
+ }
+};
+
+Q_DECLARE_TYPEINFO(QGles2CommandBuffer::Command, Q_MOVABLE_TYPE);
+
+struct QGles2SwapChain : public QRhiSwapChain
+{
+ QGles2SwapChain(QRhiImplementation *rhi);
+ ~QGles2SwapChain();
+ void release() override;
+
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+
+ QSize surfacePixelSize() override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool buildOrResize() override;
+
+ QSurface *surface = nullptr;
+ QSize pixelSize;
+ QGles2ReferenceRenderTarget rt;
+ QGles2CommandBuffer cb;
+ int frameCount = 0;
+};
+
+class QRhiGles2 : public QRhiImplementation
+{
+public:
+ QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *importDevice = nullptr);
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ int size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
+ QRhi::FrameOpResult endOffscreenFrame() override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+
+ QVector<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ void sendVMemStatsToProfiler() override;
+
+ bool ensureContext(QSurface *surface = nullptr) const;
+ void executeDeferredReleases();
+ QRhi::FrameOpResult flushCommandBuffer();
+ void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD,
+ int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
+ void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
+ void executeCommandBuffer(QRhiCommandBuffer *cb);
+ void executeBindGraphicsPipeline(QRhiGraphicsPipeline *ps);
+ void bindShaderResources(QRhiGraphicsPipeline *ps, QRhiShaderResourceBindings *srb,
+ const uint *dynOfsPairs, int dynOfsCount);
+ QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD,
+ bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr);
+ int effectiveSampleCount(int sampleCount) const;
+
+ QOpenGLContext *ctx = nullptr;
+ bool importedContext = false;
+ QSurfaceFormat requestedFormat;
+ QSurface *fallbackSurface = nullptr;
+ QWindow *maybeWindow = nullptr;
+ mutable bool needsMakeCurrent = false;
+ QOpenGLExtensions *f = nullptr;
+ uint vao = 0;
+ struct Caps {
+ Caps()
+ : ctxMajor(2),
+ ctxMinor(0),
+ maxTextureSize(2048),
+ maxDrawBuffers(4),
+ msaaRenderBuffer(false),
+ npotTexture(true),
+ npotTextureRepeat(true),
+ gles(false),
+ fixedIndexPrimitiveRestart(false),
+ bgraExternalFormat(false),
+ bgraInternalFormat(false),
+ r8Format(false),
+ r16Format(false),
+ floatFormats(false),
+ depthTexture(false),
+ packedDepthStencil(false),
+ srgbCapableDefaultFramebuffer(false),
+ coreProfile(false),
+ uniformBuffers(false),
+ elementIndexUint(false)
+ { }
+ int ctxMajor;
+ int ctxMinor;
+ int maxTextureSize;
+ int maxDrawBuffers;
+ int maxSamples;
+ // Multisample fb and blit are supported (GLES 3.0 or OpenGL 3.x). Not
+ // the same as multisample textures!
+ uint msaaRenderBuffer : 1;
+ uint npotTexture : 1;
+ uint npotTextureRepeat : 1;
+ uint gles : 1;
+ uint fixedIndexPrimitiveRestart : 1;
+ uint bgraExternalFormat : 1;
+ uint bgraInternalFormat : 1;
+ uint r8Format : 1;
+ uint r16Format : 1;
+ uint floatFormats : 1;
+ uint depthTexture : 1;
+ uint packedDepthStencil : 1;
+ uint srgbCapableDefaultFramebuffer : 1;
+ uint coreProfile : 1;
+ uint uniformBuffers : 1;
+ uint elementIndexUint : 1;
+ } caps;
+ bool inFrame = false;
+ bool inPass = false;
+ QGles2SwapChain *currentSwapChain = nullptr;
+ QVector<GLint> supportedCompressedFormats;
+ mutable QVector<int> supportedSampleCountList;
+ QRhiGles2NativeHandles nativeHandlesStruct;
+
+ struct DeferredReleaseEntry {
+ enum Type {
+ Buffer,
+ Pipeline,
+ Texture,
+ RenderBuffer,
+ TextureRenderTarget
+ };
+ Type type;
+ union {
+ struct {
+ GLuint buffer;
+ } buffer;
+ struct {
+ GLuint program;
+ } pipeline;
+ struct {
+ GLuint texture;
+ } texture;
+ struct {
+ GLuint renderbuffer;
+ GLuint renderbuffer2;
+ } renderbuffer;
+ struct {
+ GLuint framebuffer;
+ } textureRenderTarget;
+ };
+ };
+ QVector<DeferredReleaseEntry> releaseQueue;
+
+ struct OffscreenFrame {
+ OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
+ bool active = false;
+ QGles2CommandBuffer cbWrapper;
+ } ofr;
+};
+
+Q_DECLARE_TYPEINFO(QRhiGles2::DeferredReleaseEntry, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
new file mode 100644
index 0000000000..8739a42738
--- /dev/null
+++ b/src/gui/rhi/qrhimetal.mm
@@ -0,0 +1,3249 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrhimetal_p_p.h"
+#include "qshader_p.h"
+#include <QGuiApplication>
+#include <QWindow>
+#include <qmath.h>
+
+#ifdef Q_OS_MACOS
+#include <AppKit/AppKit.h>
+#endif
+
+#include <Metal/Metal.h>
+#include <QuartzCore/CAMetalLayer.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Metal backend. Double buffers and throttles to vsync. "Dynamic" buffers are
+ Shared (host visible) and duplicated (due to 2 frames in flight), "static"
+ are Managed on macOS and Shared on iOS/tvOS, and still duplicated.
+ "Immutable" is like "static" but with only one native buffer underneath.
+ Textures are Private (device local) and a host visible staging buffer is
+ used to upload data to them. Does not rely on strong objects refs from
+ command buffers (hence uses commandBufferWithUnretainedReferences), but
+ does rely on automatic dependency tracking between encoders (hence no
+ MTLResourceHazardTrackingModeUntracked atm).
+*/
+
+#if __has_feature(objc_arc)
+#error ARC not supported
+#endif
+
+// Note: we expect everything here pass the Metal API validation when running
+// in Debug mode in XCode. Some of the issues that break validation are not
+// obvious and not visible when running outside XCode.
+//
+// An exception is the nextDrawable Called Early blah blah warning, which is
+// plain and simply false.
+
+/*!
+ \class QRhiMetalInitParams
+ \inmodule QtRhi
+ \brief Metal specific initialization parameters.
+
+ A Metal-based QRhi needs no special parameters for initialization.
+
+ \badcode
+ QRhiMetalInitParams params;
+ rhi = QRhi::create(QRhi::Metal, &params);
+ \endcode
+
+ \note Metal API validation cannot be enabled by the application. Instead,
+ run the debug build of the application in XCode. Generating a
+ \c{.xcodeproj} file via \c{qmake -spec macx-xcode} provides a convenient
+ way to enable this.
+
+ \note QRhiSwapChain can only target QWindow instances that have their
+ surface type set to QSurface::MetalSurface.
+
+ \section2 Working with existing Metal devices
+
+ When interoperating with another graphics engine, it may be necessary to
+ get a QRhi instance that uses the same Metal device. This can be achieved
+ by passing a pointer to a QRhiMetalNativeHandles to QRhi::create(). The
+ device must be set to a non-null value then. Optionally, a command queue
+ object can be specified as well.
+
+ The QRhi does not take ownership of any of the external objects.
+ */
+
+/*!
+ \class QRhiMetalNativeHandles
+ \inmodule QtRhi
+ \brief Holds the Metal device used by the QRhi.
+
+ \note The class uses \c{void *} as the type since including the Objective C
+ headers is not acceptable here. The actual types are \c{id<MTLDevice>} and
+ \c{id<MTLCommandQueue>}.
+ */
+
+/*!
+ \class QRhiMetalTextureNativeHandles
+ \inmodule QtRhi
+ \brief Holds the Metal texture object that is backing a QRhiTexture instance.
+
+ \note The class uses \c{void *} as the type since including the Objective C
+ headers is not acceptable here. The actual type is \c{id<MTLTexture>}.
+ */
+
+/*!
+ \class QRhiMetalCommandBufferNativeHandles
+ \inmodule QtRhi
+ \brief Holds the MTLCommandBuffer and MTLRenderCommandEncoder objects that are backing a QRhiCommandBuffer.
+
+ \note The command buffer object is only guaranteed to be valid while
+ recording a frame, that is, between a \l{QRhi::beginFrame()}{beginFrame()}
+ - \l{QRhi::endFrame()}{endFrame()} or
+ \l{QRhi::beginOffscreenFrame()}{beginOffscreenFrame()} -
+ \l{QRhi::endOffsrceenFrame()}{endOffscreenFrame()} pair.
+
+ \note The command encoder is only valid while recording a pass, that is,
+ between \l{QRhiCommandBuffer::beginPass()} -
+ \l{QRhiCommandBuffer::endPass()}.
+ */
+
+struct QRhiMetalData
+{
+ QRhiMetalData(QRhiImplementation *rhi) : ofr(rhi) { }
+
+ id<MTLDevice> dev = nil;
+ id<MTLCommandQueue> cmdQueue = nil;
+
+ MTLRenderPassDescriptor *createDefaultRenderPass(bool hasDepthStencil,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ int colorAttCount);
+ id<MTLLibrary> createMetalLib(const QShader &shader, QShader::Variant shaderVariant,
+ QString *error, QByteArray *entryPoint);
+ id<MTLFunction> createMSLShaderFunction(id<MTLLibrary> lib, const QByteArray &entryPoint);
+
+ struct DeferredReleaseEntry {
+ enum Type {
+ Buffer,
+ RenderBuffer,
+ Texture,
+ Sampler,
+ StagingBuffer
+ };
+ Type type;
+ int lastActiveFrameSlot; // -1 if not used otherwise 0..FRAMES_IN_FLIGHT-1
+ union {
+ struct {
+ id<MTLBuffer> buffers[QMTL_FRAMES_IN_FLIGHT];
+ } buffer;
+ struct {
+ id<MTLTexture> texture;
+ } renderbuffer;
+ struct {
+ id<MTLTexture> texture;
+ id<MTLBuffer> stagingBuffers[QMTL_FRAMES_IN_FLIGHT];
+ } texture;
+ struct {
+ id<MTLSamplerState> samplerState;
+ } sampler;
+ struct {
+ id<MTLBuffer> buffer;
+ } stagingBuffer;
+ };
+ };
+ QVector<DeferredReleaseEntry> releaseQueue;
+
+ struct OffscreenFrame {
+ OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
+ bool active = false;
+ QMetalCommandBuffer cbWrapper;
+ } ofr;
+
+ struct ActiveReadback {
+ int activeFrameSlot = -1;
+ QRhiReadbackDescription desc;
+ QRhiReadbackResult *result;
+ id<MTLBuffer> buf;
+ quint32 bufSize;
+ QSize pixelSize;
+ QRhiTexture::Format format;
+ };
+ QVector<ActiveReadback> activeReadbacks;
+
+ API_AVAILABLE(macos(10.13), ios(11.0)) MTLCaptureManager *captureMgr;
+ API_AVAILABLE(macos(10.13), ios(11.0)) id<MTLCaptureScope> captureScope = nil;
+
+ static const int TEXBUF_ALIGN = 256; // probably not accurate
+};
+
+Q_DECLARE_TYPEINFO(QRhiMetalData::DeferredReleaseEntry, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiMetalData::ActiveReadback, Q_MOVABLE_TYPE);
+
+struct QMetalBufferData
+{
+ bool managed;
+ id<MTLBuffer> buf[QMTL_FRAMES_IN_FLIGHT];
+ QVector<QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate> pendingUpdates[QMTL_FRAMES_IN_FLIGHT];
+};
+
+struct QMetalRenderBufferData
+{
+ MTLPixelFormat format;
+ id<MTLTexture> tex = nil;
+};
+
+struct QMetalTextureData
+{
+ MTLPixelFormat format;
+ id<MTLTexture> tex = nil;
+ id<MTLBuffer> stagingBuf[QMTL_FRAMES_IN_FLIGHT];
+ bool owns = true;
+};
+
+struct QMetalSamplerData
+{
+ id<MTLSamplerState> samplerState = nil;
+};
+
+struct QMetalCommandBufferData
+{
+ id<MTLCommandBuffer> cb;
+ id<MTLRenderCommandEncoder> currentPassEncoder;
+ MTLRenderPassDescriptor *currentPassRpDesc;
+ int currentFirstVertexBinding;
+ QRhiBatchedBindings<id<MTLBuffer> > currentVertexInputsBuffers;
+ QRhiBatchedBindings<NSUInteger> currentVertexInputOffsets;
+};
+
+struct QMetalRenderTargetData
+{
+ QSize pixelSize;
+ float dpr = 1;
+ int sampleCount = 1;
+ int colorAttCount = 0;
+ int dsAttCount = 0;
+
+ struct ColorAtt {
+ bool needsDrawableForTex = false;
+ id<MTLTexture> tex = nil;
+ int layer = 0;
+ int level = 0;
+ bool needsDrawableForResolveTex = false;
+ id<MTLTexture> resolveTex = nil;
+ int resolveLayer = 0;
+ int resolveLevel = 0;
+ };
+
+ struct {
+ ColorAtt colorAtt[QMetalRenderPassDescriptor::MAX_COLOR_ATTACHMENTS];
+ id<MTLTexture> dsTex = nil;
+ bool hasStencil = false;
+ bool depthNeedsStore = false;
+ } fb;
+};
+
+struct QMetalGraphicsPipelineData
+{
+ id<MTLRenderPipelineState> ps = nil;
+ id<MTLDepthStencilState> ds = nil;
+ MTLPrimitiveType primitiveType;
+ MTLWinding winding;
+ MTLCullMode cullMode;
+ id<MTLLibrary> vsLib = nil;
+ id<MTLFunction> vsFunc = nil;
+ id<MTLLibrary> fsLib = nil;
+ id<MTLFunction> fsFunc = nil;
+};
+
+struct QMetalSwapChainData
+{
+ CAMetalLayer *layer = nullptr;
+ id<CAMetalDrawable> curDrawable;
+ dispatch_semaphore_t sem[QMTL_FRAMES_IN_FLIGHT];
+ MTLRenderPassDescriptor *rp = nullptr;
+ id<MTLTexture> msaaTex[QMTL_FRAMES_IN_FLIGHT];
+ QRhiTexture::Format rhiColorFormat;
+ MTLPixelFormat colorFormat;
+};
+
+QRhiMetal::QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice)
+{
+ Q_UNUSED(params);
+
+ d = new QRhiMetalData(this);
+
+ importedDevice = importDevice != nullptr;
+ if (importedDevice) {
+ if (d->dev) {
+ d->dev = (id<MTLDevice>) importDevice->dev;
+ importedCmdQueue = importDevice->cmdQueue != nullptr;
+ if (importedCmdQueue)
+ d->cmdQueue = (id<MTLCommandQueue>) importDevice->cmdQueue;
+ } else {
+ qWarning("No MTLDevice given, cannot import");
+ importedDevice = false;
+ }
+ }
+}
+
+QRhiMetal::~QRhiMetal()
+{
+ delete d;
+}
+
+static inline uint aligned(uint v, uint byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+bool QRhiMetal::create(QRhi::Flags flags)
+{
+ Q_UNUSED(flags);
+
+ if (importedDevice)
+ [d->dev retain];
+ else
+ d->dev = MTLCreateSystemDefaultDevice();
+
+ qDebug("Metal device: %s", qPrintable(QString::fromNSString([d->dev name])));
+
+ if (importedCmdQueue)
+ [d->cmdQueue retain];
+ else
+ d->cmdQueue = [d->dev newCommandQueue];
+
+ if (@available(macOS 10.13, iOS 11.0, *)) {
+ d->captureMgr = [MTLCaptureManager sharedCaptureManager];
+ // Have a custom capture scope as well which then shows up in XCode as
+ // an option when capturing, and becomes especially useful when having
+ // multiple windows with multiple QRhis.
+ d->captureScope = [d->captureMgr newCaptureScopeWithCommandQueue: d->cmdQueue];
+ const QString label = QString::asprintf("Qt capture scope for QRhi %p", this);
+ d->captureScope.label = label.toNSString();
+ }
+
+#if defined(Q_OS_MACOS)
+ caps.maxTextureSize = 16384;
+#elif defined(Q_OS_TVOS)
+ if ([d->dev supportsFeatureSet: MTLFeatureSet(30003)]) // MTLFeatureSet_tvOS_GPUFamily2_v1
+ caps.maxTextureSize = 16384;
+ else
+ caps.maxTextureSize = 8192;
+#elif defined(Q_OS_IOS)
+ // welcome to feature set hell
+ if ([d->dev supportsFeatureSet: MTLFeatureSet(16)] // MTLFeatureSet_iOS_GPUFamily5_v1
+ || [d->dev supportsFeatureSet: MTLFeatureSet(11)] // MTLFeatureSet_iOS_GPUFamily4_v1
+ || [d->dev supportsFeatureSet: MTLFeatureSet(4)]) // MTLFeatureSet_iOS_GPUFamily3_v1
+ {
+ caps.maxTextureSize = 16384;
+ } else if ([d->dev supportsFeatureSet: MTLFeatureSet(3)] // MTLFeatureSet_iOS_GPUFamily2_v2
+ || [d->dev supportsFeatureSet: MTLFeatureSet(2)]) // MTLFeatureSet_iOS_GPUFamily1_v2
+ {
+ caps.maxTextureSize = 8192;
+ } else {
+ caps.maxTextureSize = 4096;
+ }
+#endif
+
+ nativeHandlesStruct.dev = d->dev;
+ nativeHandlesStruct.cmdQueue = d->cmdQueue;
+
+ return true;
+}
+
+void QRhiMetal::destroy()
+{
+ executeDeferredReleases(true);
+ finishActiveReadbacks(true);
+
+ if (@available(macOS 10.13, iOS 11.0, *)) {
+ [d->captureScope release];
+ d->captureScope = nil;
+ }
+
+ [d->cmdQueue release];
+ if (!importedCmdQueue)
+ d->cmdQueue = nil;
+
+ [d->dev release];
+ if (!importedDevice)
+ d->dev = nil;
+}
+
+QVector<int> QRhiMetal::supportedSampleCounts() const
+{
+ return { 1, 2, 4, 8 };
+}
+
+int QRhiMetal::effectiveSampleCount(int sampleCount) const
+{
+ // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
+ const int s = qBound(1, sampleCount, 64);
+ if (!supportedSampleCounts().contains(s)) {
+ qWarning("Attempted to set unsupported sample count %d", sampleCount);
+ return 1;
+ }
+ return s;
+}
+
+QRhiSwapChain *QRhiMetal::createSwapChain()
+{
+ return new QMetalSwapChain(this);
+}
+
+QRhiBuffer *QRhiMetal::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+{
+ return new QMetalBuffer(this, type, usage, size);
+}
+
+int QRhiMetal::ubufAlignment() const
+{
+ return 256;
+}
+
+bool QRhiMetal::isYUpInFramebuffer() const
+{
+ return false;
+}
+
+bool QRhiMetal::isYUpInNDC() const
+{
+ return true;
+}
+
+bool QRhiMetal::isClipDepthZeroToOne() const
+{
+ return true;
+}
+
+QMatrix4x4 QRhiMetal::clipSpaceCorrMatrix() const
+{
+ // depth range 0..1
+ static QMatrix4x4 m;
+ if (m.isIdentity()) {
+ // NB the ctor takes row-major
+ m = QMatrix4x4(1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 0.5f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ return m;
+}
+
+bool QRhiMetal::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
+{
+ Q_UNUSED(flags);
+
+#ifdef Q_OS_MACOS
+ if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
+ return false;
+ if (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12)
+ return false;
+#else
+ if (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
+ return false;
+#endif
+
+ return true;
+}
+
+bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const
+{
+ switch (feature) {
+ case QRhi::MultisampleTexture:
+ return true;
+ case QRhi::MultisampleRenderBuffer:
+ return true;
+ case QRhi::DebugMarkers:
+ return true;
+ case QRhi::Timestamps:
+ return false;
+ case QRhi::Instancing:
+ return true;
+ case QRhi::CustomInstanceStepRate:
+ return true;
+ case QRhi::PrimitiveRestart:
+ return true;
+ case QRhi::NonDynamicUniformBuffers:
+ return true;
+ case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
+ return false;
+ case QRhi::NPOTTextureRepeat:
+ return true;
+ case QRhi::RedOrAlpha8IsRed:
+ return true;
+ case QRhi::ElementIndexUint:
+ return true;
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
+}
+
+int QRhiMetal::resourceLimit(QRhi::ResourceLimit limit) const
+{
+ switch (limit) {
+ case QRhi::TextureSizeMin:
+ return 1;
+ case QRhi::TextureSizeMax:
+ return caps.maxTextureSize;
+ case QRhi::MaxColorAttachments:
+ return 8;
+ case QRhi::FramesInFlight:
+ return QMTL_FRAMES_IN_FLIGHT;
+ default:
+ Q_UNREACHABLE();
+ return 0;
+ }
+}
+
+const QRhiNativeHandles *QRhiMetal::nativeHandles()
+{
+ return &nativeHandlesStruct;
+}
+
+void QRhiMetal::sendVMemStatsToProfiler()
+{
+ // nothing to do here
+}
+
+QRhiRenderBuffer *QRhiMetal::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags)
+{
+ return new QMetalRenderBuffer(this, type, pixelSize, sampleCount, flags);
+}
+
+QRhiTexture *QRhiMetal::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
+ int sampleCount, QRhiTexture::Flags flags)
+{
+ return new QMetalTexture(this, format, pixelSize, sampleCount, flags);
+}
+
+QRhiSampler *QRhiMetal::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+{
+ return new QMetalSampler(this, magFilter, minFilter, mipmapMode, u, v);
+}
+
+QRhiTextureRenderTarget *QRhiMetal::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags)
+{
+ return new QMetalTextureRenderTarget(this, desc, flags);
+}
+
+QRhiGraphicsPipeline *QRhiMetal::createGraphicsPipeline()
+{
+ return new QMetalGraphicsPipeline(this);
+}
+
+QRhiShaderResourceBindings *QRhiMetal::createShaderResourceBindings()
+{
+ return new QMetalShaderResourceBindings(this);
+}
+
+void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD, QMetalCommandBuffer *cbD,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets,
+ bool offsetOnlyChange)
+{
+ static const int KNOWN_STAGES = 2;
+ struct {
+ QRhiBatchedBindings<id<MTLBuffer> > buffers;
+ QRhiBatchedBindings<NSUInteger> bufferOffsets;
+ QRhiBatchedBindings<id<MTLTexture> > textures;
+ QRhiBatchedBindings<id<MTLSamplerState> > samplers;
+ } res[KNOWN_STAGES];
+
+ for (const QRhiShaderResourceBinding &binding : qAsConst(srbD->sortedBindings)) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&binding);
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ {
+ QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, b->u.ubuf.buf);
+ id<MTLBuffer> mtlbuf = bufD->d->buf[bufD->m_type == QRhiBuffer::Immutable ? 0 : currentFrameSlot];
+ uint offset = b->u.ubuf.offset;
+ for (int i = 0; i < dynamicOffsetCount; ++i) {
+ const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
+ if (dynOfs.first == b->binding) {
+ offset = dynOfs.second;
+ break;
+ }
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
+ res[0].buffers.feed(b->binding, mtlbuf);
+ res[0].bufferOffsets.feed(b->binding, offset);
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
+ res[1].buffers.feed(b->binding, mtlbuf);
+ res[1].bufferOffsets.feed(b->binding, offset);
+ }
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ {
+ QMetalTexture *texD = QRHI_RES(QMetalTexture, b->u.stex.tex);
+ QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b->u.stex.sampler);
+ if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
+ res[0].textures.feed(b->binding, texD->d->tex);
+ res[0].samplers.feed(b->binding, samplerD->d->samplerState);
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
+ res[1].textures.feed(b->binding, texD->d->tex);
+ res[1].samplers.feed(b->binding, samplerD->d->samplerState);
+ }
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+
+ for (int idx = 0; idx < KNOWN_STAGES; ++idx) {
+ res[idx].buffers.finish();
+ res[idx].bufferOffsets.finish();
+
+ for (int i = 0, ie = res[idx].buffers.batches.count(); i != ie; ++i) {
+ const auto &bufferBatch(res[idx].buffers.batches[i]);
+ const auto &offsetBatch(res[idx].bufferOffsets.batches[i]);
+ switch (idx) {
+ case 0:
+ [cbD->d->currentPassEncoder setVertexBuffers: bufferBatch.resources.constData()
+ offsets: offsetBatch.resources.constData()
+ withRange: NSMakeRange(bufferBatch.startBinding, bufferBatch.resources.count())];
+ break;
+ case 1:
+ [cbD->d->currentPassEncoder setFragmentBuffers: bufferBatch.resources.constData()
+ offsets: offsetBatch.resources.constData()
+ withRange: NSMakeRange(bufferBatch.startBinding, bufferBatch.resources.count())];
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+
+ if (offsetOnlyChange)
+ continue;
+
+ res[idx].textures.finish();
+ res[idx].samplers.finish();
+
+ for (int i = 0, ie = res[idx].textures.batches.count(); i != ie; ++i) {
+ const auto &batch(res[idx].textures.batches[i]);
+ switch (idx) {
+ case 0:
+ [cbD->d->currentPassEncoder setVertexTextures: batch.resources.constData()
+ withRange: NSMakeRange(batch.startBinding, batch.resources.count())];
+ break;
+ case 1:
+ [cbD->d->currentPassEncoder setFragmentTextures: batch.resources.constData()
+ withRange: NSMakeRange(batch.startBinding, batch.resources.count())];
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+ for (int i = 0, ie = res[idx].samplers.batches.count(); i != ie; ++i) {
+ const auto &batch(res[idx].samplers.batches[i]);
+ switch (idx) {
+ case 0:
+ [cbD->d->currentPassEncoder setVertexSamplerStates: batch.resources.constData()
+ withRange: NSMakeRange(batch.startBinding, batch.resources.count())];
+ break;
+ case 1:
+ [cbD->d->currentPassEncoder setFragmentSamplerStates: batch.resources.constData()
+ withRange: NSMakeRange(batch.startBinding, batch.resources.count())];
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+ }
+}
+
+void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps)
+{
+ Q_ASSERT(inPass);
+
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ QMetalGraphicsPipeline *psD = QRHI_RES(QMetalGraphicsPipeline, ps);
+
+ if (cbD->currentPipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
+ cbD->currentPipeline = ps;
+ cbD->currentPipelineGeneration = psD->generation;
+
+ [cbD->d->currentPassEncoder setRenderPipelineState: psD->d->ps];
+ [cbD->d->currentPassEncoder setDepthStencilState: psD->d->ds];
+ [cbD->d->currentPassEncoder setCullMode: psD->d->cullMode];
+ [cbD->d->currentPassEncoder setFrontFacingWinding: psD->d->winding];
+ }
+
+ psD->lastActiveFrameSlot = currentFrameSlot;
+}
+
+void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
+{
+ Q_ASSERT(inPass);
+
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ Q_ASSERT(cbD->currentPipeline);
+ if (!srb)
+ srb = QRHI_RES(QMetalGraphicsPipeline, cbD->currentPipeline)->m_shaderResourceBindings;
+
+ QMetalShaderResourceBindings *srbD = QRHI_RES(QMetalShaderResourceBindings, srb);
+ bool hasSlottedResourceInSrb = false;
+ bool hasDynamicOffsetInSrb = false;
+ bool resNeedsRebind = false;
+
+ // do buffer writes, figure out if we need to rebind, and mark as in-use
+ for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->sortedBindings[i]);
+ QMetalShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ {
+ QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, b->u.ubuf.buf);
+ Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
+ executeBufferHostWritesForCurrentFrame(bufD);
+ if (bufD->m_type != QRhiBuffer::Immutable)
+ hasSlottedResourceInSrb = true;
+ if (b->u.ubuf.hasDynamicOffset)
+ hasDynamicOffsetInSrb = true;
+ if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
+ resNeedsRebind = true;
+ bd.ubuf.id = bufD->m_id;
+ bd.ubuf.generation = bufD->generation;
+ }
+ bufD->lastActiveFrameSlot = currentFrameSlot;
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ {
+ QMetalTexture *texD = QRHI_RES(QMetalTexture, b->u.stex.tex);
+ QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b->u.stex.sampler);
+ if (texD->generation != bd.stex.texGeneration
+ || texD->m_id != bd.stex.texId
+ || samplerD->generation != bd.stex.samplerGeneration
+ || samplerD->m_id != bd.stex.samplerId)
+ {
+ resNeedsRebind = true;
+ bd.stex.texId = texD->m_id;
+ bd.stex.texGeneration = texD->generation;
+ bd.stex.samplerId = samplerD->m_id;
+ bd.stex.samplerGeneration = samplerD->generation;
+ }
+ texD->lastActiveFrameSlot = currentFrameSlot;
+ samplerD->lastActiveFrameSlot = currentFrameSlot;
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+
+ // make sure the resources for the correct slot get bound
+ const int resSlot = hasSlottedResourceInSrb ? currentFrameSlot : 0;
+ if (hasSlottedResourceInSrb && cbD->currentResSlot != resSlot)
+ resNeedsRebind = true;
+
+ const bool srbChange = cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation;
+
+ // dynamic uniform buffer offsets always trigger a rebind
+ if (hasDynamicOffsetInSrb || resNeedsRebind || srbChange) {
+ cbD->currentSrb = srb;
+ cbD->currentSrbGeneration = srbD->generation;
+ cbD->currentResSlot = resSlot;
+
+ const bool offsetOnlyChange = hasDynamicOffsetInSrb && !resNeedsRebind && !srbChange;
+ enqueueShaderResourceBindings(srbD, cbD, dynamicOffsetCount, dynamicOffsets, offsetOnlyChange);
+ }
+}
+
+void QRhiMetal::setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
+{
+ Q_ASSERT(inPass);
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ Q_ASSERT(cbD->currentPipeline);
+
+ QRhiBatchedBindings<id<MTLBuffer> > buffers;
+ QRhiBatchedBindings<NSUInteger> offsets;
+ for (int i = 0; i < bindingCount; ++i) {
+ QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, bindings[i].first);
+ executeBufferHostWritesForCurrentFrame(bufD);
+ bufD->lastActiveFrameSlot = currentFrameSlot;
+ id<MTLBuffer> mtlbuf = bufD->d->buf[bufD->m_type == QRhiBuffer::Immutable ? 0 : currentFrameSlot];
+ buffers.feed(startBinding + i, mtlbuf);
+ offsets.feed(startBinding + i, bindings[i].second);
+ }
+ buffers.finish();
+ offsets.finish();
+
+ // same binding space for vertex and constant buffers - work it around
+ QRhiShaderResourceBindings *srb = cbD->currentSrb;
+ // There's nothing guaranteeing setShaderResources() was called before
+ // setVertexInput()... but whatever srb will get bound will have to be
+ // layout-compatible anyways so maxBinding is the same.
+ if (!srb)
+ srb = cbD->currentPipeline->shaderResourceBindings();
+ const int firstVertexBinding = QRHI_RES(QMetalShaderResourceBindings, srb)->maxBinding + 1;
+
+ if (firstVertexBinding != cbD->d->currentFirstVertexBinding
+ || buffers != cbD->d->currentVertexInputsBuffers
+ || offsets != cbD->d->currentVertexInputOffsets)
+ {
+ cbD->d->currentFirstVertexBinding = firstVertexBinding;
+ cbD->d->currentVertexInputsBuffers = buffers;
+ cbD->d->currentVertexInputOffsets = offsets;
+
+ for (int i = 0, ie = buffers.batches.count(); i != ie; ++i) {
+ const auto &bufferBatch(buffers.batches[i]);
+ const auto &offsetBatch(offsets.batches[i]);
+ [cbD->d->currentPassEncoder setVertexBuffers:
+ bufferBatch.resources.constData()
+ offsets: offsetBatch.resources.constData()
+ withRange: NSMakeRange(firstVertexBinding + bufferBatch.startBinding, bufferBatch.resources.count())];
+ }
+ }
+
+ if (indexBuf) {
+ QMetalBuffer *ibufD = QRHI_RES(QMetalBuffer, indexBuf);
+ executeBufferHostWritesForCurrentFrame(ibufD);
+ ibufD->lastActiveFrameSlot = currentFrameSlot;
+ cbD->currentIndexBuffer = indexBuf;
+ cbD->currentIndexOffset = indexOffset;
+ cbD->currentIndexFormat = indexFormat;
+ } else {
+ cbD->currentIndexBuffer = nullptr;
+ }
+}
+
+void QRhiMetal::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
+{
+ Q_ASSERT(inPass);
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ Q_ASSERT(cbD->currentPipeline && cbD->currentTarget);
+ const QSize outputSize = cbD->currentTarget->pixelSize();
+
+ // x,y is top-left in MTLViewportRect but bottom-left in QRhiViewport
+ float x, y, w, h;
+ if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h))
+ return;
+
+ MTLViewport vp;
+ vp.originX = x;
+ vp.originY = y;
+ vp.width = w;
+ vp.height = h;
+ vp.znear = viewport.minDepth();
+ vp.zfar = viewport.maxDepth();
+
+ [cbD->d->currentPassEncoder setViewport: vp];
+
+ if (!QRHI_RES(QMetalGraphicsPipeline, cbD->currentPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
+ MTLScissorRect s;
+ s.x = x;
+ s.y = y;
+ s.width = w;
+ s.height = h;
+ [cbD->d->currentPassEncoder setScissorRect: s];
+ }
+}
+
+void QRhiMetal::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
+{
+ Q_ASSERT(inPass);
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ Q_ASSERT(cbD->currentPipeline && cbD->currentTarget);
+ Q_ASSERT(QRHI_RES(QMetalGraphicsPipeline, cbD->currentPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor));
+ const QSize outputSize = cbD->currentTarget->pixelSize();
+
+ // x,y is top-left in MTLScissorRect but bottom-left in QRhiScissor
+ int x, y, w, h;
+ if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h))
+ return;
+
+ MTLScissorRect s;
+ s.x = x;
+ s.y = y;
+ s.width = w;
+ s.height = h;
+
+ [cbD->d->currentPassEncoder setScissorRect: s];
+}
+
+void QRhiMetal::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
+{
+ Q_ASSERT(inPass);
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ [cbD->d->currentPassEncoder setBlendColorRed: c.redF() green: c.greenF() blue: c.blueF() alpha: c.alphaF()];
+}
+
+void QRhiMetal::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
+{
+ Q_ASSERT(inPass);
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ [cbD->d->currentPassEncoder setStencilReferenceValue: refValue];
+}
+
+void QRhiMetal::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
+{
+ Q_ASSERT(inPass);
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ [cbD->d->currentPassEncoder drawPrimitives:
+ QRHI_RES(QMetalGraphicsPipeline, cbD->currentPipeline)->d->primitiveType
+ vertexStart: firstVertex vertexCount: vertexCount instanceCount: instanceCount baseInstance: firstInstance];
+}
+
+void QRhiMetal::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
+{
+ Q_ASSERT(inPass);
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ if (!cbD->currentIndexBuffer)
+ return;
+
+ const quint32 indexOffset = cbD->currentIndexOffset + firstIndex * (cbD->currentIndexFormat == QRhiCommandBuffer::IndexUInt16 ? 2 : 4);
+ Q_ASSERT(indexOffset == aligned(indexOffset, 4));
+
+ QMetalBuffer *ibufD = QRHI_RES(QMetalBuffer, cbD->currentIndexBuffer);
+ id<MTLBuffer> mtlbuf = ibufD->d->buf[ibufD->m_type == QRhiBuffer::Immutable ? 0 : currentFrameSlot];
+
+ [cbD->d->currentPassEncoder drawIndexedPrimitives: QRHI_RES(QMetalGraphicsPipeline, cbD->currentPipeline)->d->primitiveType
+ indexCount: indexCount
+ indexType: cbD->currentIndexFormat == QRhiCommandBuffer::IndexUInt16 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
+ indexBuffer: mtlbuf
+ indexBufferOffset: indexOffset
+ instanceCount: instanceCount
+ baseVertex: vertexOffset
+ baseInstance: firstInstance];
+}
+
+void QRhiMetal::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
+{
+ if (!debugMarkers)
+ return;
+
+ NSString *str = [NSString stringWithUTF8String: name.constData()];
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ if (inPass) {
+ [cbD->d->currentPassEncoder pushDebugGroup: str];
+ } else {
+ if (@available(macOS 10.13, iOS 11.0, *))
+ [cbD->d->cb pushDebugGroup: str];
+ }
+}
+
+void QRhiMetal::debugMarkEnd(QRhiCommandBuffer *cb)
+{
+ if (!debugMarkers)
+ return;
+
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ if (inPass) {
+ [cbD->d->currentPassEncoder popDebugGroup];
+ } else {
+ if (@available(macOS 10.13, iOS 11.0, *))
+ [cbD->d->cb popDebugGroup];
+ }
+}
+
+void QRhiMetal::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
+{
+ if (!debugMarkers)
+ return;
+
+ if (inPass) {
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ [cbD->d->currentPassEncoder insertDebugSignpost: [NSString stringWithUTF8String: msg.constData()]];
+ }
+}
+
+const QRhiNativeHandles *QRhiMetal::nativeHandles(QRhiCommandBuffer *cb)
+{
+ return QRHI_RES(QMetalCommandBuffer, cb)->nativeHandles();
+}
+
+void QRhiMetal::beginExternal(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+}
+
+void QRhiMetal::endExternal(QRhiCommandBuffer *cb)
+{
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ cbD->resetPerPassCachedState();
+}
+
+QRhi::FrameOpResult QRhiMetal::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
+{
+ Q_UNUSED(flags);
+ Q_ASSERT(!inFrame);
+ inFrame = true;
+
+ QMetalSwapChain *swapChainD = QRHI_RES(QMetalSwapChain, swapChain);
+
+ // This is a bit messed up since for this swapchain we want to wait for the
+ // commands+present to complete, while for others just for the commands
+ // (for this same frame slot) but not sure how to do that in a sane way so
+ // wait for full cb completion for now.
+ for (QMetalSwapChain *sc : qAsConst(swapchains)) {
+ dispatch_semaphore_t sem = sc->d->sem[swapChainD->currentFrameSlot];
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ if (sc != swapChainD)
+ dispatch_semaphore_signal(sem);
+ }
+
+ currentSwapChain = swapChainD;
+ currentFrameSlot = swapChainD->currentFrameSlot;
+ if (swapChainD->ds)
+ swapChainD->ds->lastActiveFrameSlot = currentFrameSlot;
+
+ if (@available(macOS 10.13, iOS 11.0, *))
+ [d->captureScope beginScope];
+
+ // Do not let the command buffer mess with the refcount of objects. We do
+ // have a proper render loop and will manage lifetimes similarly to other
+ // backends (Vulkan).
+ swapChainD->cbWrapper.d->cb = [d->cmdQueue commandBufferWithUnretainedReferences];
+
+ QMetalRenderTargetData::ColorAtt colorAtt;
+ if (swapChainD->samples > 1) {
+ colorAtt.tex = swapChainD->d->msaaTex[currentFrameSlot];
+ colorAtt.needsDrawableForResolveTex = true;
+ } else {
+ colorAtt.needsDrawableForTex = true;
+ }
+
+ swapChainD->rtWrapper.d->fb.colorAtt[0] = colorAtt;
+ swapChainD->rtWrapper.d->fb.dsTex = swapChainD->ds ? swapChainD->ds->d->tex : nil;
+ swapChainD->rtWrapper.d->fb.hasStencil = swapChainD->ds ? true : false;
+ swapChainD->rtWrapper.d->fb.depthNeedsStore = false;
+
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+ QRHI_PROF_F(beginSwapChainFrame(swapChain));
+
+ executeDeferredReleases();
+ swapChainD->cbWrapper.resetState();
+ finishActiveReadbacks();
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiMetal::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags)
+{
+ Q_ASSERT(inFrame);
+ inFrame = false;
+
+ QMetalSwapChain *swapChainD = QRHI_RES(QMetalSwapChain, swapChain);
+ Q_ASSERT(currentSwapChain == swapChainD);
+
+ const bool needsPresent = !flags.testFlag(QRhi::SkipPresent);
+ if (needsPresent)
+ [swapChainD->cbWrapper.d->cb presentDrawable: swapChainD->d->curDrawable];
+
+ __block int thisFrameSlot = currentFrameSlot;
+ [swapChainD->cbWrapper.d->cb addCompletedHandler: ^(id<MTLCommandBuffer>) {
+ dispatch_semaphore_signal(swapChainD->d->sem[thisFrameSlot]);
+ }];
+
+ [swapChainD->cbWrapper.d->cb commit];
+
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+ QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
+
+ if (@available(macOS 10.13, iOS 11.0, *))
+ [d->captureScope endScope];
+
+ if (needsPresent)
+ swapChainD->currentFrameSlot = (swapChainD->currentFrameSlot + 1) % QMTL_FRAMES_IN_FLIGHT;
+
+ swapChainD->frameCount += 1;
+ currentSwapChain = nullptr;
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiMetal::beginOffscreenFrame(QRhiCommandBuffer **cb)
+{
+ Q_ASSERT(!inFrame);
+ inFrame = true;
+
+ currentFrameSlot = (currentFrameSlot + 1) % QMTL_FRAMES_IN_FLIGHT;
+ if (swapchains.count() > 1) {
+ for (QMetalSwapChain *sc : qAsConst(swapchains)) {
+ // wait+signal is the general pattern to ensure the commands for a
+ // given frame slot have completed (if sem is 1, we go 0 then 1; if
+ // sem is 0 we go -1, block, completion increments to 0, then us to 1)
+ dispatch_semaphore_t sem = sc->d->sem[currentFrameSlot];
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ dispatch_semaphore_signal(sem);
+ }
+ }
+
+ d->ofr.active = true;
+ *cb = &d->ofr.cbWrapper;
+ d->ofr.cbWrapper.d->cb = [d->cmdQueue commandBufferWithUnretainedReferences];
+
+ executeDeferredReleases();
+ d->ofr.cbWrapper.resetState();
+ finishActiveReadbacks();
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiMetal::endOffscreenFrame()
+{
+ Q_ASSERT(d->ofr.active);
+ d->ofr.active = false;
+ Q_ASSERT(inFrame);
+ inFrame = false;
+
+ [d->ofr.cbWrapper.d->cb commit];
+
+ // offscreen frames wait for completion, unlike swapchain ones
+ [d->ofr.cbWrapper.d->cb waitUntilCompleted];
+
+ finishActiveReadbacks(true);
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiMetal::finish()
+{
+ Q_ASSERT(!inPass);
+
+ id<MTLCommandBuffer> cb = nil;
+ QMetalSwapChain *swapChainD = nullptr;
+ if (inFrame) {
+ if (d->ofr.active) {
+ Q_ASSERT(!currentSwapChain);
+ cb = d->ofr.cbWrapper.d->cb;
+ } else {
+ Q_ASSERT(currentSwapChain);
+ swapChainD = currentSwapChain;
+ cb = swapChainD->cbWrapper.d->cb;
+ }
+ }
+
+ for (QMetalSwapChain *sc : qAsConst(swapchains)) {
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ if (currentSwapChain && sc == currentSwapChain && i == currentFrameSlot) {
+ // no wait as this is the thing we're going to be commit below and
+ // beginFrame decremented sem already and going to be signaled by endFrame
+ continue;
+ }
+ dispatch_semaphore_t sem = sc->d->sem[i];
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ dispatch_semaphore_signal(sem);
+ }
+ }
+
+ if (cb) {
+ [cb commit];
+ [cb waitUntilCompleted];
+ }
+
+ if (inFrame) {
+ if (d->ofr.active)
+ d->ofr.cbWrapper.d->cb = [d->cmdQueue commandBufferWithUnretainedReferences];
+ else
+ swapChainD->cbWrapper.d->cb = [d->cmdQueue commandBufferWithUnretainedReferences];
+ }
+
+ executeDeferredReleases(true);
+
+ finishActiveReadbacks(true);
+
+ return QRhi::FrameOpSuccess;
+}
+
+MTLRenderPassDescriptor *QRhiMetalData::createDefaultRenderPass(bool hasDepthStencil,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ int colorAttCount)
+{
+ MTLRenderPassDescriptor *rp = [MTLRenderPassDescriptor renderPassDescriptor];
+ MTLClearColor c = MTLClearColorMake(colorClearValue.redF(), colorClearValue.greenF(), colorClearValue.blueF(),
+ colorClearValue.alphaF());
+
+ for (int i = 0; i < colorAttCount; ++i) {
+ rp.colorAttachments[i].loadAction = MTLLoadActionClear;
+ rp.colorAttachments[i].storeAction = MTLStoreActionStore;
+ rp.colorAttachments[i].clearColor = c;
+ }
+
+ if (hasDepthStencil) {
+ rp.depthAttachment.loadAction = MTLLoadActionClear;
+ rp.depthAttachment.storeAction = MTLStoreActionDontCare;
+ rp.stencilAttachment.loadAction = MTLLoadActionClear;
+ rp.stencilAttachment.storeAction = MTLStoreActionDontCare;
+ rp.depthAttachment.clearDepth = depthStencilClearValue.depthClearValue();
+ rp.stencilAttachment.clearStencil = depthStencilClearValue.stencilClearValue();
+ }
+
+ return rp;
+}
+
+qsizetype QRhiMetal::subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const
+{
+ qsizetype size = 0;
+ const qsizetype imageSizeBytes = subresDesc.image().isNull() ?
+ subresDesc.data().size() : subresDesc.image().sizeInBytes();
+ if (imageSizeBytes > 0)
+ size += aligned(imageSizeBytes, QRhiMetalData::TEXBUF_ALIGN);
+ return size;
+}
+
+void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEncPtr,
+ int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc,
+ qsizetype *curOfs)
+{
+ const QPoint dp = subresDesc.destinationTopLeft();
+ const QByteArray rawData = subresDesc.data();
+ QImage img = subresDesc.image();
+ id<MTLBlitCommandEncoder> blitEnc = (id<MTLBlitCommandEncoder>) blitEncPtr;
+
+ if (!img.isNull()) {
+ const qsizetype fullImageSizeBytes = img.sizeInBytes();
+ int w = img.width();
+ int h = img.height();
+ int bpl = img.bytesPerLine();
+ int srcOffset = 0;
+
+ if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
+ const int sx = subresDesc.sourceTopLeft().x();
+ const int sy = subresDesc.sourceTopLeft().y();
+ if (!subresDesc.sourceSize().isEmpty()) {
+ w = subresDesc.sourceSize().width();
+ h = subresDesc.sourceSize().height();
+ }
+ if (img.depth() == 32) {
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, img.constBits(), fullImageSizeBytes);
+ srcOffset = sy * bpl + sx * 4;
+ // bpl remains set to the original image's row stride
+ } else {
+ img = img.copy(sx, sy, w, h);
+ bpl = img.bytesPerLine();
+ Q_ASSERT(img.sizeInBytes() <= fullImageSizeBytes);
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, img.constBits(), img.sizeInBytes());
+ }
+ } else {
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, img.constBits(), fullImageSizeBytes);
+ }
+
+ [blitEnc copyFromBuffer: texD->d->stagingBuf[currentFrameSlot]
+ sourceOffset: *curOfs + srcOffset
+ sourceBytesPerRow: bpl
+ sourceBytesPerImage: 0
+ sourceSize: MTLSizeMake(w, h, 1)
+ toTexture: texD->d->tex
+ destinationSlice: layer
+ destinationLevel: level
+ destinationOrigin: MTLOriginMake(dp.x(), dp.y(), 0)
+ options: MTLBlitOptionNone];
+
+ *curOfs += aligned(fullImageSizeBytes, QRhiMetalData::TEXBUF_ALIGN);
+ } else if (!rawData.isEmpty() && isCompressedFormat(texD->m_format)) {
+ const QSize subresSize = q->sizeForMipLevel(level, texD->m_pixelSize);
+ const int subresw = subresSize.width();
+ const int subresh = subresSize.height();
+ int w, h;
+ if (subresDesc.sourceSize().isEmpty()) {
+ w = subresw;
+ h = subresh;
+ } else {
+ w = subresDesc.sourceSize().width();
+ h = subresDesc.sourceSize().height();
+ }
+
+ quint32 bpl = 0;
+ QSize blockDim;
+ compressedFormatInfo(texD->m_format, QSize(w, h), &bpl, nullptr, &blockDim);
+
+ const int dx = aligned(dp.x(), blockDim.width());
+ const int dy = aligned(dp.y(), blockDim.height());
+ if (dx + w != subresw)
+ w = aligned(w, blockDim.width());
+ if (dy + h != subresh)
+ h = aligned(h, blockDim.height());
+
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, rawData.constData(), rawData.size());
+
+ [blitEnc copyFromBuffer: texD->d->stagingBuf[currentFrameSlot]
+ sourceOffset: *curOfs
+ sourceBytesPerRow: bpl
+ sourceBytesPerImage: 0
+ sourceSize: MTLSizeMake(w, h, 1)
+ toTexture: texD->d->tex
+ destinationSlice: layer
+ destinationLevel: level
+ destinationOrigin: MTLOriginMake(dx, dy, 0)
+ options: MTLBlitOptionNone];
+
+ *curOfs += aligned(rawData.size(), QRhiMetalData::TEXBUF_ALIGN);
+ } else if (!rawData.isEmpty()) {
+ const QSize subresSize = q->sizeForMipLevel(level, texD->m_pixelSize);
+ const int subresw = subresSize.width();
+ const int subresh = subresSize.height();
+ int w, h;
+ if (subresDesc.sourceSize().isEmpty()) {
+ w = subresw;
+ h = subresh;
+ } else {
+ w = subresDesc.sourceSize().width();
+ h = subresDesc.sourceSize().height();
+ }
+
+ quint32 bpl = 0;
+ textureFormatInfo(texD->m_format, QSize(w, h), &bpl, nullptr);
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, rawData.constData(), rawData.size());
+
+ [blitEnc copyFromBuffer: texD->d->stagingBuf[currentFrameSlot]
+ sourceOffset: *curOfs
+ sourceBytesPerRow: bpl
+ sourceBytesPerImage: 0
+ sourceSize: MTLSizeMake(w, h, 1)
+ toTexture: texD->d->tex
+ destinationSlice: layer
+ destinationLevel: level
+ destinationOrigin: MTLOriginMake(dp.x(), dp.y(), 0)
+ options: MTLBlitOptionNone];
+
+ *curOfs += aligned(rawData.size(), QRhiMetalData::TEXBUF_ALIGN);
+ } else {
+ qWarning("Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
+ }
+}
+
+void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+
+ for (const QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate &u : ud->dynamicBufferUpdates) {
+ QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, u.buf);
+ Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
+ bufD->d->pendingUpdates[i].append(u);
+ }
+
+ for (const QRhiResourceUpdateBatchPrivate::StaticBufferUpload &u : ud->staticBufferUploads) {
+ QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, u.buf);
+ Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
+ Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
+ for (int i = 0, ie = bufD->m_type == QRhiBuffer::Immutable ? 1 : QMTL_FRAMES_IN_FLIGHT; i != ie; ++i)
+ bufD->d->pendingUpdates[i].append({ u.buf, u.offset, u.data.size(), u.data.constData() });
+ }
+
+ id<MTLBlitCommandEncoder> blitEnc = nil;
+ auto ensureBlit = [&blitEnc, cbD, this] {
+ if (!blitEnc) {
+ blitEnc = [cbD->d->cb blitCommandEncoder];
+ if (debugMarkers)
+ [blitEnc pushDebugGroup: @"Texture upload/copy"];
+ }
+ };
+
+ for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
+ if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
+ QMetalTexture *utexD = QRHI_RES(QMetalTexture, u.upload.tex);
+ qsizetype stagingSize = 0;
+ for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
+ for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.upload.subresDesc[layer][level]))
+ stagingSize += subresUploadByteSize(subresDesc);
+ }
+ }
+
+ ensureBlit();
+ Q_ASSERT(!utexD->d->stagingBuf[currentFrameSlot]);
+ utexD->d->stagingBuf[currentFrameSlot] = [d->dev newBufferWithLength: stagingSize
+ options: MTLResourceStorageModeShared];
+ QRHI_PROF_F(newTextureStagingArea(utexD, currentFrameSlot, stagingSize));
+
+ void *mp = [utexD->d->stagingBuf[currentFrameSlot] contents];
+ qsizetype curOfs = 0;
+ for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
+ for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.upload.subresDesc[layer][level]))
+ enqueueSubresUpload(utexD, mp, blitEnc, layer, level, subresDesc, &curOfs);
+ }
+ }
+
+ utexD->lastActiveFrameSlot = currentFrameSlot;
+
+ QRhiMetalData::DeferredReleaseEntry e;
+ e.type = QRhiMetalData::DeferredReleaseEntry::StagingBuffer;
+ e.lastActiveFrameSlot = currentFrameSlot;
+ e.stagingBuffer.buffer = utexD->d->stagingBuf[currentFrameSlot];
+ utexD->d->stagingBuf[currentFrameSlot] = nil;
+ d->releaseQueue.append(e);
+ QRHI_PROF_F(releaseTextureStagingArea(utexD, currentFrameSlot));
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Copy) {
+ Q_ASSERT(u.copy.src && u.copy.dst);
+ QMetalTexture *srcD = QRHI_RES(QMetalTexture, u.copy.src);
+ QMetalTexture *dstD = QRHI_RES(QMetalTexture, u.copy.dst);
+ const QPoint dp = u.copy.desc.destinationTopLeft();
+ const QSize size = u.copy.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.copy.desc.pixelSize();
+ const QPoint sp = u.copy.desc.sourceTopLeft();
+
+ ensureBlit();
+ [blitEnc copyFromTexture: srcD->d->tex
+ sourceSlice: u.copy.desc.sourceLayer()
+ sourceLevel: u.copy.desc.sourceLevel()
+ sourceOrigin: MTLOriginMake(sp.x(), sp.y(), 0)
+ sourceSize: MTLSizeMake(size.width(), size.height(), 1)
+ toTexture: dstD->d->tex
+ destinationSlice: u.copy.desc.destinationLayer()
+ destinationLevel: u.copy.desc.destinationLevel()
+ destinationOrigin: MTLOriginMake(dp.x(), dp.y(), 0)];
+
+ srcD->lastActiveFrameSlot = dstD->lastActiveFrameSlot = currentFrameSlot;
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) {
+ QRhiMetalData::ActiveReadback aRb;
+ aRb.activeFrameSlot = currentFrameSlot;
+ aRb.desc = u.read.rb;
+ aRb.result = u.read.result;
+
+ QMetalTexture *texD = QRHI_RES(QMetalTexture, u.read.rb.texture());
+ QMetalSwapChain *swapChainD = nullptr;
+ id<MTLTexture> src;
+ QSize srcSize;
+ if (texD) {
+ if (texD->samples > 1) {
+ qWarning("Multisample texture cannot be read back");
+ continue;
+ }
+ aRb.pixelSize = u.read.rb.level() > 0 ? q->sizeForMipLevel(u.read.rb.level(), texD->m_pixelSize)
+ : texD->m_pixelSize;
+ aRb.format = texD->m_format;
+ src = texD->d->tex;
+ srcSize = texD->m_pixelSize;
+ texD->lastActiveFrameSlot = currentFrameSlot;
+ } else {
+ Q_ASSERT(currentSwapChain);
+ swapChainD = QRHI_RES(QMetalSwapChain, currentSwapChain);
+ aRb.pixelSize = swapChainD->pixelSize;
+ aRb.format = swapChainD->d->rhiColorFormat;
+ // Multisample swapchains need nothing special since resolving
+ // happens when ending a renderpass.
+ const QMetalRenderTargetData::ColorAtt &colorAtt(swapChainD->rtWrapper.d->fb.colorAtt[0]);
+ src = colorAtt.resolveTex ? colorAtt.resolveTex : colorAtt.tex;
+ srcSize = swapChainD->rtWrapper.d->pixelSize;
+ }
+
+ quint32 bpl = 0;
+ textureFormatInfo(aRb.format, aRb.pixelSize, &bpl, &aRb.bufSize);
+ aRb.buf = [d->dev newBufferWithLength: aRb.bufSize options: MTLResourceStorageModeShared];
+
+ QRHI_PROF_F(newReadbackBuffer(quint64(quintptr(aRb.buf)),
+ texD ? static_cast<QRhiResource *>(texD) : static_cast<QRhiResource *>(swapChainD),
+ aRb.bufSize));
+
+ ensureBlit();
+ [blitEnc copyFromTexture: src
+ sourceSlice: u.read.rb.layer()
+ sourceLevel: u.read.rb.level()
+ sourceOrigin: MTLOriginMake(0, 0, 0)
+ sourceSize: MTLSizeMake(srcSize.width(), srcSize.height(), 1)
+ toBuffer: aRb.buf
+ destinationOffset: 0
+ destinationBytesPerRow: bpl
+ destinationBytesPerImage: 0
+ options: MTLBlitOptionNone];
+
+ d->activeReadbacks.append(aRb);
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::MipGen) {
+ QMetalTexture *utexD = QRHI_RES(QMetalTexture, u.mipgen.tex);
+ ensureBlit();
+ [blitEnc generateMipmapsForTexture: utexD->d->tex];
+ utexD->lastActiveFrameSlot = currentFrameSlot;
+ }
+ }
+
+ if (blitEnc) {
+ if (debugMarkers)
+ [blitEnc popDebugGroup];
+ [blitEnc endEncoding];
+ }
+
+ ud->free();
+}
+
+void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
+{
+ const int idx = bufD->m_type == QRhiBuffer::Immutable ? 0 : currentFrameSlot;
+ QVector<QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate> &updates(bufD->d->pendingUpdates[idx]);
+ if (updates.isEmpty())
+ return;
+
+ void *p = [bufD->d->buf[idx] contents];
+ int changeBegin = -1;
+ int changeEnd = -1;
+ for (const QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate &u : updates) {
+ Q_ASSERT(bufD == QRHI_RES(QMetalBuffer, u.buf));
+ memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), u.data.size());
+ if (changeBegin == -1 || u.offset < changeBegin)
+ changeBegin = u.offset;
+ if (changeEnd == -1 || u.offset + u.data.size() > changeEnd)
+ changeEnd = u.offset + u.data.size();
+ }
+ if (changeBegin >= 0 && bufD->d->managed)
+ [bufD->d->buf[idx] didModifyRange: NSMakeRange(changeBegin, changeEnd - changeBegin)];
+
+ updates.clear();
+}
+
+void QRhiMetal::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inFrame && !inPass);
+
+ enqueueResourceUpdates(cb, resourceUpdates);
+}
+
+void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inFrame && !inPass);
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cb, resourceUpdates);
+
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+
+ QMetalRenderTargetData *rtD = nullptr;
+ switch (rt->resourceType()) {
+ case QRhiResource::RenderTarget:
+ rtD = QRHI_RES(QMetalReferenceRenderTarget, rt)->d;
+ cbD->d->currentPassRpDesc = d->createDefaultRenderPass(rtD->dsAttCount, colorClearValue, depthStencilClearValue, rtD->colorAttCount);
+ if (rtD->colorAttCount) {
+ QMetalRenderTargetData::ColorAtt &color0(rtD->fb.colorAtt[0]);
+ if (color0.needsDrawableForTex || color0.needsDrawableForResolveTex) {
+ Q_ASSERT(currentSwapChain);
+ QMetalSwapChain *swapChainD = QRHI_RES(QMetalSwapChain, currentSwapChain);
+ swapChainD->d->curDrawable = [swapChainD->d->layer nextDrawable];
+ if (!swapChainD->d->curDrawable) {
+ qWarning("No drawable");
+ return;
+ }
+ id<MTLTexture> scTex = swapChainD->d->curDrawable.texture;
+ if (color0.needsDrawableForTex) {
+ color0.tex = scTex;
+ color0.needsDrawableForTex = false;
+ } else {
+ color0.resolveTex = scTex;
+ color0.needsDrawableForResolveTex = false;
+ }
+ }
+ }
+ break;
+ case QRhiResource::TextureRenderTarget:
+ {
+ QMetalTextureRenderTarget *rtTex = QRHI_RES(QMetalTextureRenderTarget, rt);
+ rtD = rtTex->d;
+ cbD->d->currentPassRpDesc = d->createDefaultRenderPass(rtD->dsAttCount, colorClearValue, depthStencilClearValue, rtD->colorAttCount);
+ if (rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents)) {
+ for (int i = 0; i < rtD->colorAttCount; ++i)
+ cbD->d->currentPassRpDesc.colorAttachments[i].loadAction = MTLLoadActionLoad;
+ }
+ if (rtD->dsAttCount && rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents)) {
+ cbD->d->currentPassRpDesc.depthAttachment.loadAction = MTLLoadActionLoad;
+ cbD->d->currentPassRpDesc.stencilAttachment.loadAction = MTLLoadActionLoad;
+ }
+ const QVector<QRhiColorAttachment> colorAttachments = rtTex->m_desc.colorAttachments();
+ for (const QRhiColorAttachment &colorAttachment : colorAttachments) {
+ if (colorAttachment.texture())
+ QRHI_RES(QMetalTexture, colorAttachment.texture())->lastActiveFrameSlot = currentFrameSlot;
+ else if (colorAttachment.renderBuffer())
+ QRHI_RES(QMetalRenderBuffer, colorAttachment.renderBuffer())->lastActiveFrameSlot = currentFrameSlot;
+ if (colorAttachment.resolveTexture())
+ QRHI_RES(QMetalTexture, colorAttachment.resolveTexture())->lastActiveFrameSlot = currentFrameSlot;
+ }
+ if (rtTex->m_desc.depthStencilBuffer())
+ QRHI_RES(QMetalRenderBuffer, rtTex->m_desc.depthStencilBuffer())->lastActiveFrameSlot = currentFrameSlot;
+ if (rtTex->m_desc.depthTexture())
+ QRHI_RES(QMetalTexture, rtTex->m_desc.depthTexture())->lastActiveFrameSlot = currentFrameSlot;
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ for (int i = 0; i < rtD->colorAttCount; ++i) {
+ cbD->d->currentPassRpDesc.colorAttachments[i].texture = rtD->fb.colorAtt[i].tex;
+ cbD->d->currentPassRpDesc.colorAttachments[i].slice = rtD->fb.colorAtt[i].layer;
+ cbD->d->currentPassRpDesc.colorAttachments[i].level = rtD->fb.colorAtt[i].level;
+ if (rtD->fb.colorAtt[i].resolveTex) {
+ cbD->d->currentPassRpDesc.colorAttachments[i].storeAction = MTLStoreActionMultisampleResolve;
+ cbD->d->currentPassRpDesc.colorAttachments[i].resolveTexture = rtD->fb.colorAtt[i].resolveTex;
+ cbD->d->currentPassRpDesc.colorAttachments[i].resolveSlice = rtD->fb.colorAtt[i].resolveLayer;
+ cbD->d->currentPassRpDesc.colorAttachments[i].resolveLevel = rtD->fb.colorAtt[i].resolveLevel;
+ }
+ }
+
+ if (rtD->dsAttCount) {
+ Q_ASSERT(rtD->fb.dsTex);
+ cbD->d->currentPassRpDesc.depthAttachment.texture = rtD->fb.dsTex;
+ cbD->d->currentPassRpDesc.stencilAttachment.texture = rtD->fb.hasStencil ? rtD->fb.dsTex : nil;
+ if (rtD->fb.depthNeedsStore) // Depth/Stencil is set to DontCare by default, override if needed
+ cbD->d->currentPassRpDesc.depthAttachment.storeAction = MTLStoreActionStore;
+ }
+
+ cbD->d->currentPassEncoder = [cbD->d->cb renderCommandEncoderWithDescriptor: cbD->d->currentPassRpDesc];
+
+ cbD->resetPerPassState();
+
+ cbD->currentTarget = rt;
+ inPass = true;
+}
+
+void QRhiMetal::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inPass);
+ inPass = false;
+
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ [cbD->d->currentPassEncoder endEncoding];
+
+ cbD->currentTarget = nullptr;
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cb, resourceUpdates);
+}
+
+static void qrhimtl_releaseBuffer(const QRhiMetalData::DeferredReleaseEntry &e)
+{
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
+ [e.buffer.buffers[i] release];
+}
+
+static void qrhimtl_releaseRenderBuffer(const QRhiMetalData::DeferredReleaseEntry &e)
+{
+ [e.renderbuffer.texture release];
+}
+
+static void qrhimtl_releaseTexture(const QRhiMetalData::DeferredReleaseEntry &e)
+{
+ [e.texture.texture release];
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
+ [e.texture.stagingBuffers[i] release];
+}
+
+static void qrhimtl_releaseSampler(const QRhiMetalData::DeferredReleaseEntry &e)
+{
+ [e.sampler.samplerState release];
+}
+
+void QRhiMetal::executeDeferredReleases(bool forced)
+{
+ for (int i = d->releaseQueue.count() - 1; i >= 0; --i) {
+ const QRhiMetalData::DeferredReleaseEntry &e(d->releaseQueue[i]);
+ if (forced || currentFrameSlot == e.lastActiveFrameSlot || e.lastActiveFrameSlot < 0) {
+ switch (e.type) {
+ case QRhiMetalData::DeferredReleaseEntry::Buffer:
+ qrhimtl_releaseBuffer(e);
+ break;
+ case QRhiMetalData::DeferredReleaseEntry::RenderBuffer:
+ qrhimtl_releaseRenderBuffer(e);
+ break;
+ case QRhiMetalData::DeferredReleaseEntry::Texture:
+ qrhimtl_releaseTexture(e);
+ break;
+ case QRhiMetalData::DeferredReleaseEntry::Sampler:
+ qrhimtl_releaseSampler(e);
+ break;
+ case QRhiMetalData::DeferredReleaseEntry::StagingBuffer:
+ [e.stagingBuffer.buffer release];
+ break;
+ default:
+ break;
+ }
+ d->releaseQueue.removeAt(i);
+ }
+ }
+}
+
+void QRhiMetal::finishActiveReadbacks(bool forced)
+{
+ QVarLengthArray<std::function<void()>, 4> completedCallbacks;
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+
+ for (int i = d->activeReadbacks.count() - 1; i >= 0; --i) {
+ const QRhiMetalData::ActiveReadback &aRb(d->activeReadbacks[i]);
+ if (forced || currentFrameSlot == aRb.activeFrameSlot || aRb.activeFrameSlot < 0) {
+ aRb.result->format = aRb.format;
+ aRb.result->pixelSize = aRb.pixelSize;
+ aRb.result->data.resize(aRb.bufSize);
+ void *p = [aRb.buf contents];
+ memcpy(aRb.result->data.data(), p, aRb.bufSize);
+ [aRb.buf release];
+
+ QRHI_PROF_F(releaseReadbackBuffer(quint64(quintptr(aRb.buf))));
+
+ if (aRb.result->completed)
+ completedCallbacks.append(aRb.result->completed);
+
+ d->activeReadbacks.removeAt(i);
+ }
+ }
+
+ for (auto f : completedCallbacks)
+ f();
+}
+
+QMetalBuffer::QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+ : QRhiBuffer(rhi, type, usage, size),
+ d(new QMetalBufferData)
+{
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
+ d->buf[i] = nil;
+}
+
+QMetalBuffer::~QMetalBuffer()
+{
+ release();
+ delete d;
+}
+
+void QMetalBuffer::release()
+{
+ if (!d->buf[0])
+ return;
+
+ QRhiMetalData::DeferredReleaseEntry e;
+ e.type = QRhiMetalData::DeferredReleaseEntry::Buffer;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ e.buffer.buffers[i] = d->buf[i];
+ d->buf[i] = nil;
+ d->pendingUpdates[i].clear();
+ }
+
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->d->releaseQueue.append(e);
+ QRHI_PROF;
+ QRHI_PROF_F(releaseBuffer(this));
+ rhiD->unregisterResource(this);
+}
+
+bool QMetalBuffer::build()
+{
+ if (d->buf[0])
+ release();
+
+ const int nonZeroSize = m_size <= 0 ? 256 : m_size;
+ const int roundedSize = m_usage.testFlag(QRhiBuffer::UniformBuffer) ? aligned(nonZeroSize, 256) : nonZeroSize;
+
+ d->managed = false;
+ MTLResourceOptions opts = MTLResourceStorageModeShared;
+#ifdef Q_OS_MACOS
+ if (m_type != Dynamic) {
+ opts = MTLResourceStorageModeManaged;
+ d->managed = true;
+ }
+#endif
+
+ QRHI_RES_RHI(QRhiMetal);
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ // Immutable only has buf[0] and pendingUpdates[0] in use.
+ // Static and Dynamic use all.
+ if (i == 0 || m_type != Immutable) {
+ d->buf[i] = [rhiD->d->dev newBufferWithLength: roundedSize options: opts];
+ d->pendingUpdates[i].reserve(16);
+ if (!m_objectName.isEmpty()) {
+ if (m_type == Immutable) {
+ d->buf[i].label = [NSString stringWithUTF8String: m_objectName.constData()];
+ } else {
+ const QByteArray name = m_objectName + '/' + QByteArray::number(i);
+ d->buf[i].label = [NSString stringWithUTF8String: name.constData()];
+ }
+ }
+ }
+ }
+
+ QRHI_PROF;
+ QRHI_PROF_F(newBuffer(this, roundedSize, m_type == Immutable ? 1 : QMTL_FRAMES_IN_FLIGHT, 0));
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QMetalRenderBuffer::QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags)
+ : QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags),
+ d(new QMetalRenderBufferData)
+{
+}
+
+QMetalRenderBuffer::~QMetalRenderBuffer()
+{
+ release();
+ delete d;
+}
+
+void QMetalRenderBuffer::release()
+{
+ if (!d->tex)
+ return;
+
+ QRhiMetalData::DeferredReleaseEntry e;
+ e.type = QRhiMetalData::DeferredReleaseEntry::RenderBuffer;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ e.renderbuffer.texture = d->tex;
+ d->tex = nil;
+
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->d->releaseQueue.append(e);
+ QRHI_PROF;
+ QRHI_PROF_F(releaseRenderBuffer(this));
+ rhiD->unregisterResource(this);
+}
+
+bool QMetalRenderBuffer::build()
+{
+ if (d->tex)
+ release();
+
+ if (m_pixelSize.isEmpty())
+ return false;
+
+ QRHI_RES_RHI(QRhiMetal);
+ samples = rhiD->effectiveSampleCount(m_sampleCount);
+
+ MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init];
+ desc.textureType = samples > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
+ desc.width = m_pixelSize.width();
+ desc.height = m_pixelSize.height();
+ if (samples > 1)
+ desc.sampleCount = samples;
+ desc.resourceOptions = MTLResourceStorageModePrivate;
+ desc.usage = MTLTextureUsageRenderTarget;
+
+ bool transientBacking = false;
+ switch (m_type) {
+ case DepthStencil:
+#ifdef Q_OS_MACOS
+ desc.storageMode = MTLStorageModePrivate;
+#else
+ desc.storageMode = MTLResourceStorageModeMemoryless;
+ transientBacking = true;
+#endif
+ d->format = rhiD->d->dev.depth24Stencil8PixelFormatSupported
+ ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
+ desc.pixelFormat = d->format;
+ break;
+ case Color:
+ desc.storageMode = MTLStorageModePrivate;
+ d->format = MTLPixelFormatRGBA8Unorm;
+ desc.pixelFormat = d->format;
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ d->tex = [rhiD->d->dev newTextureWithDescriptor: desc];
+ [desc release];
+
+ if (!m_objectName.isEmpty())
+ d->tex.label = [NSString stringWithUTF8String: m_objectName.constData()];
+
+ QRHI_PROF;
+ QRHI_PROF_F(newRenderBuffer(this, transientBacking, false, samples));
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QRhiTexture::Format QMetalRenderBuffer::backingFormat() const
+{
+ return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
+}
+
+QMetalTexture::QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, sampleCount, flags),
+ d(new QMetalTextureData)
+{
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
+ d->stagingBuf[i] = nil;
+}
+
+QMetalTexture::~QMetalTexture()
+{
+ release();
+ delete d;
+}
+
+void QMetalTexture::release()
+{
+ if (!d->tex)
+ return;
+
+ QRhiMetalData::DeferredReleaseEntry e;
+ e.type = QRhiMetalData::DeferredReleaseEntry::Texture;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ e.texture.texture = d->owns ? d->tex : nil;
+ d->tex = nil;
+ nativeHandlesStruct.texture = nullptr;
+
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ e.texture.stagingBuffers[i] = d->stagingBuf[i];
+ d->stagingBuf[i] = nil;
+ }
+
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->d->releaseQueue.append(e);
+ QRHI_PROF;
+ QRHI_PROF_F(releaseTexture(this));
+ rhiD->unregisterResource(this);
+}
+
+static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
+{
+ const bool srgb = flags.testFlag(QRhiTexture::sRGB);
+ switch (format) {
+ case QRhiTexture::RGBA8:
+ return srgb ? MTLPixelFormatRGBA8Unorm_sRGB : MTLPixelFormatRGBA8Unorm;
+ case QRhiTexture::BGRA8:
+ return srgb ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm;
+ case QRhiTexture::R8:
+#ifdef Q_OS_MACOS
+ return MTLPixelFormatR8Unorm;
+#else
+ return srgb ? MTLPixelFormatR8Unorm_sRGB : MTLPixelFormatR8Unorm;
+#endif
+ case QRhiTexture::R16:
+ return MTLPixelFormatR16Unorm;
+ case QRhiTexture::RED_OR_ALPHA8:
+ return MTLPixelFormatR8Unorm;
+
+ case QRhiTexture::RGBA16F:
+ return MTLPixelFormatRGBA16Float;
+ case QRhiTexture::RGBA32F:
+ return MTLPixelFormatRGBA32Float;
+
+ case QRhiTexture::D16:
+#ifdef Q_OS_MACOS
+ return MTLPixelFormatDepth16Unorm;
+#else
+ return MTLPixelFormatDepth32Float;
+#endif
+ case QRhiTexture::D32F:
+ return MTLPixelFormatDepth32Float;
+
+#ifdef Q_OS_MACOS
+ case QRhiTexture::BC1:
+ return srgb ? MTLPixelFormatBC1_RGBA_sRGB : MTLPixelFormatBC1_RGBA;
+ case QRhiTexture::BC2:
+ return srgb ? MTLPixelFormatBC2_RGBA_sRGB : MTLPixelFormatBC2_RGBA;
+ case QRhiTexture::BC3:
+ return srgb ? MTLPixelFormatBC3_RGBA_sRGB : MTLPixelFormatBC3_RGBA;
+ case QRhiTexture::BC4:
+ return MTLPixelFormatBC4_RUnorm;
+ case QRhiTexture::BC5:
+ qWarning("QRhiMetal does not support BC5");
+ return MTLPixelFormatRGBA8Unorm;
+ case QRhiTexture::BC6H:
+ return MTLPixelFormatBC6H_RGBUfloat;
+ case QRhiTexture::BC7:
+ return srgb ? MTLPixelFormatBC7_RGBAUnorm_sRGB : MTLPixelFormatBC7_RGBAUnorm;
+#else
+ case QRhiTexture::BC1:
+ case QRhiTexture::BC2:
+ case QRhiTexture::BC3:
+ case QRhiTexture::BC4:
+ case QRhiTexture::BC5:
+ case QRhiTexture::BC6H:
+ case QRhiTexture::BC7:
+ qWarning("QRhiMetal: BCx compression not supported on this platform");
+ return MTLPixelFormatRGBA8Unorm;
+#endif
+
+#ifndef Q_OS_MACOS
+ case QRhiTexture::ETC2_RGB8:
+ return srgb ? MTLPixelFormatETC2_RGB8_sRGB : MTLPixelFormatETC2_RGB8;
+ case QRhiTexture::ETC2_RGB8A1:
+ return srgb ? MTLPixelFormatETC2_RGB8A1_sRGB : MTLPixelFormatETC2_RGB8A1;
+ case QRhiTexture::ETC2_RGBA8:
+ return srgb ? MTLPixelFormatEAC_RGBA8_sRGB : MTLPixelFormatEAC_RGBA8;
+
+ case QRhiTexture::ASTC_4x4:
+ return srgb ? MTLPixelFormatASTC_4x4_sRGB : MTLPixelFormatASTC_4x4_LDR;
+ case QRhiTexture::ASTC_5x4:
+ return srgb ? MTLPixelFormatASTC_5x4_sRGB : MTLPixelFormatASTC_5x4_LDR;
+ case QRhiTexture::ASTC_5x5:
+ return srgb ? MTLPixelFormatASTC_5x5_sRGB : MTLPixelFormatASTC_5x5_LDR;
+ case QRhiTexture::ASTC_6x5:
+ return srgb ? MTLPixelFormatASTC_6x5_sRGB : MTLPixelFormatASTC_6x5_LDR;
+ case QRhiTexture::ASTC_6x6:
+ return srgb ? MTLPixelFormatASTC_6x6_sRGB : MTLPixelFormatASTC_6x6_LDR;
+ case QRhiTexture::ASTC_8x5:
+ return srgb ? MTLPixelFormatASTC_8x5_sRGB : MTLPixelFormatASTC_8x5_LDR;
+ case QRhiTexture::ASTC_8x6:
+ return srgb ? MTLPixelFormatASTC_8x6_sRGB : MTLPixelFormatASTC_8x6_LDR;
+ case QRhiTexture::ASTC_8x8:
+ return srgb ? MTLPixelFormatASTC_8x8_sRGB : MTLPixelFormatASTC_8x8_LDR;
+ case QRhiTexture::ASTC_10x5:
+ return srgb ? MTLPixelFormatASTC_10x5_sRGB : MTLPixelFormatASTC_10x5_LDR;
+ case QRhiTexture::ASTC_10x6:
+ return srgb ? MTLPixelFormatASTC_10x6_sRGB : MTLPixelFormatASTC_10x6_LDR;
+ case QRhiTexture::ASTC_10x8:
+ return srgb ? MTLPixelFormatASTC_10x8_sRGB : MTLPixelFormatASTC_10x8_LDR;
+ case QRhiTexture::ASTC_10x10:
+ return srgb ? MTLPixelFormatASTC_10x10_sRGB : MTLPixelFormatASTC_10x10_LDR;
+ case QRhiTexture::ASTC_12x10:
+ return srgb ? MTLPixelFormatASTC_12x10_sRGB : MTLPixelFormatASTC_12x10_LDR;
+ case QRhiTexture::ASTC_12x12:
+ return srgb ? MTLPixelFormatASTC_12x12_sRGB : MTLPixelFormatASTC_12x12_LDR;
+#else
+ case QRhiTexture::ETC2_RGB8:
+ case QRhiTexture::ETC2_RGB8A1:
+ case QRhiTexture::ETC2_RGBA8:
+ qWarning("QRhiMetal: ETC2 compression not supported on this platform");
+ return MTLPixelFormatRGBA8Unorm;
+
+ case QRhiTexture::ASTC_4x4:
+ case QRhiTexture::ASTC_5x4:
+ case QRhiTexture::ASTC_5x5:
+ case QRhiTexture::ASTC_6x5:
+ case QRhiTexture::ASTC_6x6:
+ case QRhiTexture::ASTC_8x5:
+ case QRhiTexture::ASTC_8x6:
+ case QRhiTexture::ASTC_8x8:
+ case QRhiTexture::ASTC_10x5:
+ case QRhiTexture::ASTC_10x6:
+ case QRhiTexture::ASTC_10x8:
+ case QRhiTexture::ASTC_10x10:
+ case QRhiTexture::ASTC_12x10:
+ case QRhiTexture::ASTC_12x12:
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatRGBA8Unorm;
+#endif
+
+ default:
+ Q_UNREACHABLE();
+ return MTLPixelFormatRGBA8Unorm;
+ }
+}
+
+bool QMetalTexture::prepareBuild(QSize *adjustedSize)
+{
+ if (d->tex)
+ release();
+
+ const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
+ const bool isCube = m_flags.testFlag(CubeMap);
+ const bool hasMipMaps = m_flags.testFlag(MipMapped);
+
+ QRHI_RES_RHI(QRhiMetal);
+ d->format = toMetalTextureFormat(m_format, m_flags);
+ mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
+ samples = rhiD->effectiveSampleCount(m_sampleCount);
+ if (samples > 1) {
+ if (isCube) {
+ qWarning("Cubemap texture cannot be multisample");
+ return false;
+ }
+ if (hasMipMaps) {
+ qWarning("Multisample texture cannot have mipmaps");
+ return false;
+ }
+ }
+
+ if (adjustedSize)
+ *adjustedSize = size;
+
+ return true;
+}
+
+bool QMetalTexture::build()
+{
+ QSize size;
+ if (!prepareBuild(&size))
+ return false;
+
+ MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init];
+
+ const bool isCube = m_flags.testFlag(CubeMap);
+ if (isCube)
+ desc.textureType = MTLTextureTypeCube;
+ else
+ desc.textureType = samples > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
+ desc.pixelFormat = d->format;
+ desc.width = size.width();
+ desc.height = size.height();
+ desc.mipmapLevelCount = mipLevelCount;
+ if (samples > 1)
+ desc.sampleCount = samples;
+ desc.resourceOptions = MTLResourceStorageModePrivate;
+ desc.storageMode = MTLStorageModePrivate;
+ desc.usage = MTLTextureUsageShaderRead;
+ if (m_flags.testFlag(RenderTarget))
+ desc.usage |= MTLTextureUsageRenderTarget;
+
+ QRHI_RES_RHI(QRhiMetal);
+ d->tex = [rhiD->d->dev newTextureWithDescriptor: desc];
+ [desc release];
+
+ if (!m_objectName.isEmpty())
+ d->tex.label = [NSString stringWithUTF8String: m_objectName.constData()];
+
+ d->owns = true;
+ nativeHandlesStruct.texture = d->tex;
+
+ QRHI_PROF;
+ QRHI_PROF_F(newTexture(this, true, mipLevelCount, isCube ? 6 : 1, samples));
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+bool QMetalTexture::buildFrom(const QRhiNativeHandles *src)
+{
+ const QRhiMetalTextureNativeHandles *h = static_cast<const QRhiMetalTextureNativeHandles *>(src);
+ if (!h || !h->texture)
+ return false;
+
+ if (!prepareBuild())
+ return false;
+
+ d->tex = (id<MTLTexture>) h->texture;
+
+ d->owns = false;
+ nativeHandlesStruct.texture = d->tex;
+
+ QRHI_PROF;
+ QRHI_PROF_F(newTexture(this, false, mipLevelCount, m_flags.testFlag(CubeMap) ? 6 : 1, samples));
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->registerResource(this);
+ return true;
+}
+
+const QRhiNativeHandles *QMetalTexture::nativeHandles()
+{
+ return &nativeHandlesStruct;
+}
+
+QMetalSampler::QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v),
+ d(new QMetalSamplerData)
+{
+}
+
+QMetalSampler::~QMetalSampler()
+{
+ release();
+ delete d;
+}
+
+void QMetalSampler::release()
+{
+ if (!d->samplerState)
+ return;
+
+ QRhiMetalData::DeferredReleaseEntry e;
+ e.type = QRhiMetalData::DeferredReleaseEntry::Sampler;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ e.sampler.samplerState = d->samplerState;
+ d->samplerState = nil;
+
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->d->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+}
+
+static inline MTLSamplerMinMagFilter toMetalFilter(QRhiSampler::Filter f)
+{
+ switch (f) {
+ case QRhiSampler::Nearest:
+ return MTLSamplerMinMagFilterNearest;
+ case QRhiSampler::Linear:
+ return MTLSamplerMinMagFilterLinear;
+ default:
+ Q_UNREACHABLE();
+ return MTLSamplerMinMagFilterNearest;
+ }
+}
+
+static inline MTLSamplerMipFilter toMetalMipmapMode(QRhiSampler::Filter f)
+{
+ switch (f) {
+ case QRhiSampler::None:
+ return MTLSamplerMipFilterNotMipmapped;
+ case QRhiSampler::Nearest:
+ return MTLSamplerMipFilterNearest;
+ case QRhiSampler::Linear:
+ return MTLSamplerMipFilterLinear;
+ default:
+ Q_UNREACHABLE();
+ return MTLSamplerMipFilterNotMipmapped;
+ }
+}
+
+static inline MTLSamplerAddressMode toMetalAddressMode(QRhiSampler::AddressMode m)
+{
+ switch (m) {
+ case QRhiSampler::Repeat:
+ return MTLSamplerAddressModeRepeat;
+ case QRhiSampler::ClampToEdge:
+ return MTLSamplerAddressModeClampToEdge;
+ case QRhiSampler::Border:
+ return MTLSamplerAddressModeClampToBorderColor;
+ case QRhiSampler::Mirror:
+ return MTLSamplerAddressModeMirrorRepeat;
+ case QRhiSampler::MirrorOnce:
+ return MTLSamplerAddressModeMirrorClampToEdge;
+ default:
+ Q_UNREACHABLE();
+ return MTLSamplerAddressModeClampToEdge;
+ }
+}
+
+static inline MTLCompareFunction toMetalTextureCompareFunction(QRhiSampler::CompareOp op)
+{
+ switch (op) {
+ case QRhiSampler::Never:
+ return MTLCompareFunctionNever;
+ case QRhiSampler::Less:
+ return MTLCompareFunctionLess;
+ case QRhiSampler::Equal:
+ return MTLCompareFunctionEqual;
+ case QRhiSampler::LessOrEqual:
+ return MTLCompareFunctionLessEqual;
+ case QRhiSampler::Greater:
+ return MTLCompareFunctionGreater;
+ case QRhiSampler::NotEqual:
+ return MTLCompareFunctionNotEqual;
+ case QRhiSampler::GreaterOrEqual:
+ return MTLCompareFunctionGreaterEqual;
+ case QRhiSampler::Always:
+ return MTLCompareFunctionAlways;
+ default:
+ Q_UNREACHABLE();
+ return MTLCompareFunctionNever;
+ }
+}
+
+bool QMetalSampler::build()
+{
+ if (d->samplerState)
+ release();
+
+ MTLSamplerDescriptor *desc = [[MTLSamplerDescriptor alloc] init];
+ desc.minFilter = toMetalFilter(m_minFilter);
+ desc.magFilter = toMetalFilter(m_magFilter);
+ desc.mipFilter = toMetalMipmapMode(m_mipmapMode);
+ desc.sAddressMode = toMetalAddressMode(m_addressU);
+ desc.tAddressMode = toMetalAddressMode(m_addressV);
+ desc.rAddressMode = toMetalAddressMode(m_addressW);
+ desc.compareFunction = toMetalTextureCompareFunction(m_compareOp);
+
+ QRHI_RES_RHI(QRhiMetal);
+ d->samplerState = [rhiD->d->dev newSamplerStateWithDescriptor: desc];
+ [desc release];
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+// dummy, no Vulkan-style RenderPass+Framebuffer concept here.
+// We do have MTLRenderPassDescriptor of course, but it will be created on the fly for each pass.
+QMetalRenderPassDescriptor::QMetalRenderPassDescriptor(QRhiImplementation *rhi)
+ : QRhiRenderPassDescriptor(rhi)
+{
+}
+
+QMetalRenderPassDescriptor::~QMetalRenderPassDescriptor()
+{
+ release();
+}
+
+void QMetalRenderPassDescriptor::release()
+{
+ // nothing to do here
+}
+
+QMetalReferenceRenderTarget::QMetalReferenceRenderTarget(QRhiImplementation *rhi)
+ : QRhiRenderTarget(rhi),
+ d(new QMetalRenderTargetData)
+{
+}
+
+QMetalReferenceRenderTarget::~QMetalReferenceRenderTarget()
+{
+ release();
+ delete d;
+}
+
+void QMetalReferenceRenderTarget::release()
+{
+ // nothing to do here
+}
+
+QSize QMetalReferenceRenderTarget::pixelSize() const
+{
+ return d->pixelSize;
+}
+
+float QMetalReferenceRenderTarget::devicePixelRatio() const
+{
+ return d->dpr;
+}
+
+int QMetalReferenceRenderTarget::sampleCount() const
+{
+ return d->sampleCount;
+}
+
+QMetalTextureRenderTarget::QMetalTextureRenderTarget(QRhiImplementation *rhi,
+ const QRhiTextureRenderTargetDescription &desc,
+ Flags flags)
+ : QRhiTextureRenderTarget(rhi, desc, flags),
+ d(new QMetalRenderTargetData)
+{
+}
+
+QMetalTextureRenderTarget::~QMetalTextureRenderTarget()
+{
+ release();
+ delete d;
+}
+
+void QMetalTextureRenderTarget::release()
+{
+ // nothing to do here
+}
+
+QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDescriptor()
+{
+ const QVector<QRhiColorAttachment> colorAttachments = m_desc.colorAttachments();
+ QMetalRenderPassDescriptor *rpD = new QMetalRenderPassDescriptor(m_rhi);
+ rpD->colorAttachmentCount = colorAttachments.count();
+ rpD->hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
+
+ for (int i = 0, ie = colorAttachments.count(); i != ie; ++i) {
+ QMetalTexture *texD = QRHI_RES(QMetalTexture, colorAttachments[i].texture());
+ QMetalRenderBuffer *rbD = QRHI_RES(QMetalRenderBuffer, colorAttachments[i].renderBuffer());
+ rpD->colorFormat[i] = texD ? texD->d->format : rbD->d->format;
+ }
+
+ if (m_desc.depthTexture())
+ rpD->dsFormat = QRHI_RES(QMetalTexture, m_desc.depthTexture())->d->format;
+ else if (m_desc.depthStencilBuffer())
+ rpD->dsFormat = QRHI_RES(QMetalRenderBuffer, m_desc.depthStencilBuffer())->d->format;
+
+ return rpD;
+}
+
+bool QMetalTextureRenderTarget::build()
+{
+ const QVector<QRhiColorAttachment> colorAttachments = m_desc.colorAttachments();
+ Q_ASSERT(!colorAttachments.isEmpty() || m_desc.depthTexture());
+ Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
+ const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
+
+ d->colorAttCount = colorAttachments.count();
+ for (int i = 0; i < d->colorAttCount; ++i) {
+ QMetalTexture *texD = QRHI_RES(QMetalTexture, colorAttachments[i].texture());
+ QMetalRenderBuffer *rbD = QRHI_RES(QMetalRenderBuffer, colorAttachments[i].renderBuffer());
+ Q_ASSERT(texD || rbD);
+ id<MTLTexture> dst = nil;
+ if (texD) {
+ dst = texD->d->tex;
+ if (i == 0) {
+ d->pixelSize = texD->pixelSize();
+ d->sampleCount = texD->samples;
+ }
+ } else if (rbD) {
+ dst = rbD->d->tex;
+ if (i == 0) {
+ d->pixelSize = rbD->pixelSize();
+ d->sampleCount = rbD->samples;
+ }
+ }
+ QMetalRenderTargetData::ColorAtt colorAtt;
+ colorAtt.tex = dst;
+ colorAtt.layer = colorAttachments[i].layer();
+ colorAtt.level = colorAttachments[i].level();
+ QMetalTexture *resTexD = QRHI_RES(QMetalTexture, colorAttachments[i].resolveTexture());
+ colorAtt.resolveTex = resTexD ? resTexD->d->tex : nil;
+ colorAtt.resolveLayer = colorAttachments[i].resolveLayer();
+ colorAtt.resolveLevel = colorAttachments[i].resolveLevel();
+ d->fb.colorAtt[i] = colorAtt;
+ }
+ d->dpr = 1;
+
+ if (hasDepthStencil) {
+ if (m_desc.depthTexture()) {
+ QMetalTexture *depthTexD = QRHI_RES(QMetalTexture, m_desc.depthTexture());
+ d->fb.dsTex = depthTexD->d->tex;
+ d->fb.hasStencil = false;
+ d->fb.depthNeedsStore = true;
+ if (d->colorAttCount == 0) {
+ d->pixelSize = depthTexD->pixelSize();
+ d->sampleCount = depthTexD->samples;
+ }
+ } else {
+ QMetalRenderBuffer *depthRbD = QRHI_RES(QMetalRenderBuffer, m_desc.depthStencilBuffer());
+ d->fb.dsTex = depthRbD->d->tex;
+ d->fb.hasStencil = true;
+ d->fb.depthNeedsStore = false;
+ if (d->colorAttCount == 0) {
+ d->pixelSize = depthRbD->pixelSize();
+ d->sampleCount = depthRbD->samples;
+ }
+ }
+ d->dsAttCount = 1;
+ } else {
+ d->dsAttCount = 0;
+ }
+
+ return true;
+}
+
+QSize QMetalTextureRenderTarget::pixelSize() const
+{
+ return d->pixelSize;
+}
+
+float QMetalTextureRenderTarget::devicePixelRatio() const
+{
+ return d->dpr;
+}
+
+int QMetalTextureRenderTarget::sampleCount() const
+{
+ return d->sampleCount;
+}
+
+QMetalShaderResourceBindings::QMetalShaderResourceBindings(QRhiImplementation *rhi)
+ : QRhiShaderResourceBindings(rhi)
+{
+}
+
+QMetalShaderResourceBindings::~QMetalShaderResourceBindings()
+{
+ release();
+}
+
+void QMetalShaderResourceBindings::release()
+{
+ sortedBindings.clear();
+ maxBinding = -1;
+}
+
+bool QMetalShaderResourceBindings::build()
+{
+ if (!sortedBindings.isEmpty())
+ release();
+
+ sortedBindings = m_bindings;
+ std::sort(sortedBindings.begin(), sortedBindings.end(),
+ [](const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
+ {
+ return QRhiShaderResourceBindingPrivate::get(&a)->binding < QRhiShaderResourceBindingPrivate::get(&b)->binding;
+ });
+ if (!sortedBindings.isEmpty())
+ maxBinding = QRhiShaderResourceBindingPrivate::get(&sortedBindings.last())->binding;
+ else
+ maxBinding = -1;
+
+ boundResourceData.resize(sortedBindings.count());
+
+ for (int i = 0, ie = sortedBindings.count(); i != ie; ++i) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&sortedBindings[i]);
+ QMetalShaderResourceBindings::BoundResourceData &bd(boundResourceData[i]);
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ {
+ QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, b->u.ubuf.buf);
+ bd.ubuf.id = bufD->m_id;
+ bd.ubuf.generation = bufD->generation;
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ {
+ QMetalTexture *texD = QRHI_RES(QMetalTexture, b->u.stex.tex);
+ QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b->u.stex.sampler);
+ bd.stex.texId = texD->m_id;
+ bd.stex.texGeneration = texD->generation;
+ bd.stex.samplerId = samplerD->m_id;
+ bd.stex.samplerGeneration = samplerD->generation;
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+
+ generation += 1;
+ return true;
+}
+
+QMetalGraphicsPipeline::QMetalGraphicsPipeline(QRhiImplementation *rhi)
+ : QRhiGraphicsPipeline(rhi),
+ d(new QMetalGraphicsPipelineData)
+{
+}
+
+QMetalGraphicsPipeline::~QMetalGraphicsPipeline()
+{
+ release();
+ delete d;
+}
+
+void QMetalGraphicsPipeline::release()
+{
+ QRHI_RES_RHI(QRhiMetal);
+
+ if (!d->ps)
+ return;
+
+ if (d->ps) {
+ [d->ps release];
+ d->ps = nil;
+ }
+
+ if (d->ds) {
+ [d->ds release];
+ d->ds = nil;
+ }
+
+ if (d->vsFunc) {
+ [d->vsFunc release];
+ d->vsFunc = nil;
+ }
+ if (d->vsLib) {
+ [d->vsLib release];
+ d->vsLib = nil;
+ }
+
+ if (d->fsFunc) {
+ [d->fsFunc release];
+ d->fsFunc = nil;
+ }
+ if (d->fsLib) {
+ [d->fsLib release];
+ d->fsLib = nil;
+ }
+
+ rhiD->unregisterResource(this);
+}
+
+static inline MTLVertexFormat toMetalAttributeFormat(QRhiVertexInputAttribute::Format format)
+{
+ switch (format) {
+ case QRhiVertexInputAttribute::Float4:
+ return MTLVertexFormatFloat4;
+ case QRhiVertexInputAttribute::Float3:
+ return MTLVertexFormatFloat3;
+ case QRhiVertexInputAttribute::Float2:
+ return MTLVertexFormatFloat2;
+ case QRhiVertexInputAttribute::Float:
+ return MTLVertexFormatFloat;
+ case QRhiVertexInputAttribute::UNormByte4:
+ return MTLVertexFormatUChar4Normalized;
+ case QRhiVertexInputAttribute::UNormByte2:
+ return MTLVertexFormatUChar2Normalized;
+ case QRhiVertexInputAttribute::UNormByte:
+ if (@available(macOS 10.13, iOS 11.0, *))
+ return MTLVertexFormatUCharNormalized;
+ else
+ Q_UNREACHABLE();
+ default:
+ Q_UNREACHABLE();
+ return MTLVertexFormatFloat4;
+ }
+}
+
+static inline MTLBlendFactor toMetalBlendFactor(QRhiGraphicsPipeline::BlendFactor f)
+{
+ switch (f) {
+ case QRhiGraphicsPipeline::Zero:
+ return MTLBlendFactorZero;
+ case QRhiGraphicsPipeline::One:
+ return MTLBlendFactorOne;
+ case QRhiGraphicsPipeline::SrcColor:
+ return MTLBlendFactorSourceColor;
+ case QRhiGraphicsPipeline::OneMinusSrcColor:
+ return MTLBlendFactorOneMinusSourceColor;
+ case QRhiGraphicsPipeline::DstColor:
+ return MTLBlendFactorDestinationColor;
+ case QRhiGraphicsPipeline::OneMinusDstColor:
+ return MTLBlendFactorOneMinusDestinationColor;
+ case QRhiGraphicsPipeline::SrcAlpha:
+ return MTLBlendFactorSourceAlpha;
+ case QRhiGraphicsPipeline::OneMinusSrcAlpha:
+ return MTLBlendFactorOneMinusSourceAlpha;
+ case QRhiGraphicsPipeline::DstAlpha:
+ return MTLBlendFactorDestinationAlpha;
+ case QRhiGraphicsPipeline::OneMinusDstAlpha:
+ return MTLBlendFactorOneMinusDestinationAlpha;
+ case QRhiGraphicsPipeline::ConstantColor:
+ return MTLBlendFactorBlendColor;
+ case QRhiGraphicsPipeline::ConstantAlpha:
+ return MTLBlendFactorBlendAlpha;
+ case QRhiGraphicsPipeline::OneMinusConstantColor:
+ return MTLBlendFactorOneMinusBlendColor;
+ case QRhiGraphicsPipeline::OneMinusConstantAlpha:
+ return MTLBlendFactorOneMinusBlendAlpha;
+ case QRhiGraphicsPipeline::SrcAlphaSaturate:
+ return MTLBlendFactorSourceAlphaSaturated;
+ case QRhiGraphicsPipeline::Src1Color:
+ return MTLBlendFactorSource1Color;
+ case QRhiGraphicsPipeline::OneMinusSrc1Color:
+ return MTLBlendFactorOneMinusSource1Color;
+ case QRhiGraphicsPipeline::Src1Alpha:
+ return MTLBlendFactorSource1Alpha;
+ case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
+ return MTLBlendFactorOneMinusSource1Alpha;
+ default:
+ Q_UNREACHABLE();
+ return MTLBlendFactorZero;
+ }
+}
+
+static inline MTLBlendOperation toMetalBlendOp(QRhiGraphicsPipeline::BlendOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::Add:
+ return MTLBlendOperationAdd;
+ case QRhiGraphicsPipeline::Subtract:
+ return MTLBlendOperationSubtract;
+ case QRhiGraphicsPipeline::ReverseSubtract:
+ return MTLBlendOperationReverseSubtract;
+ case QRhiGraphicsPipeline::Min:
+ return MTLBlendOperationMin;
+ case QRhiGraphicsPipeline::Max:
+ return MTLBlendOperationMax;
+ default:
+ Q_UNREACHABLE();
+ return MTLBlendOperationAdd;
+ }
+}
+
+static inline uint toMetalColorWriteMask(QRhiGraphicsPipeline::ColorMask c)
+{
+ uint f = 0;
+ if (c.testFlag(QRhiGraphicsPipeline::R))
+ f |= MTLColorWriteMaskRed;
+ if (c.testFlag(QRhiGraphicsPipeline::G))
+ f |= MTLColorWriteMaskGreen;
+ if (c.testFlag(QRhiGraphicsPipeline::B))
+ f |= MTLColorWriteMaskBlue;
+ if (c.testFlag(QRhiGraphicsPipeline::A))
+ f |= MTLColorWriteMaskAlpha;
+ return f;
+}
+
+static inline MTLCompareFunction toMetalCompareOp(QRhiGraphicsPipeline::CompareOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::Never:
+ return MTLCompareFunctionNever;
+ case QRhiGraphicsPipeline::Less:
+ return MTLCompareFunctionLess;
+ case QRhiGraphicsPipeline::Equal:
+ return MTLCompareFunctionEqual;
+ case QRhiGraphicsPipeline::LessOrEqual:
+ return MTLCompareFunctionLessEqual;
+ case QRhiGraphicsPipeline::Greater:
+ return MTLCompareFunctionGreater;
+ case QRhiGraphicsPipeline::NotEqual:
+ return MTLCompareFunctionNotEqual;
+ case QRhiGraphicsPipeline::GreaterOrEqual:
+ return MTLCompareFunctionGreaterEqual;
+ case QRhiGraphicsPipeline::Always:
+ return MTLCompareFunctionAlways;
+ default:
+ Q_UNREACHABLE();
+ return MTLCompareFunctionAlways;
+ }
+}
+
+static inline MTLStencilOperation toMetalStencilOp(QRhiGraphicsPipeline::StencilOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::StencilZero:
+ return MTLStencilOperationZero;
+ case QRhiGraphicsPipeline::Keep:
+ return MTLStencilOperationKeep;
+ case QRhiGraphicsPipeline::Replace:
+ return MTLStencilOperationReplace;
+ case QRhiGraphicsPipeline::IncrementAndClamp:
+ return MTLStencilOperationIncrementClamp;
+ case QRhiGraphicsPipeline::DecrementAndClamp:
+ return MTLStencilOperationDecrementClamp;
+ case QRhiGraphicsPipeline::Invert:
+ return MTLStencilOperationInvert;
+ case QRhiGraphicsPipeline::IncrementAndWrap:
+ return MTLStencilOperationIncrementWrap;
+ case QRhiGraphicsPipeline::DecrementAndWrap:
+ return MTLStencilOperationDecrementWrap;
+ default:
+ Q_UNREACHABLE();
+ return MTLStencilOperationKeep;
+ }
+}
+
+static inline MTLPrimitiveType toMetalPrimitiveType(QRhiGraphicsPipeline::Topology t)
+{
+ switch (t) {
+ case QRhiGraphicsPipeline::Triangles:
+ return MTLPrimitiveTypeTriangle;
+ case QRhiGraphicsPipeline::TriangleStrip:
+ return MTLPrimitiveTypeTriangleStrip;
+ case QRhiGraphicsPipeline::Lines:
+ return MTLPrimitiveTypeLine;
+ case QRhiGraphicsPipeline::LineStrip:
+ return MTLPrimitiveTypeLineStrip;
+ case QRhiGraphicsPipeline::Points:
+ return MTLPrimitiveTypePoint;
+ default:
+ Q_UNREACHABLE();
+ return MTLPrimitiveTypeTriangle;
+ }
+}
+
+static inline MTLCullMode toMetalCullMode(QRhiGraphicsPipeline::CullMode c)
+{
+ switch (c) {
+ case QRhiGraphicsPipeline::None:
+ return MTLCullModeNone;
+ case QRhiGraphicsPipeline::Front:
+ return MTLCullModeFront;
+ case QRhiGraphicsPipeline::Back:
+ return MTLCullModeBack;
+ default:
+ Q_UNREACHABLE();
+ return MTLCullModeNone;
+ }
+}
+
+id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Variant shaderVariant,
+ QString *error, QByteArray *entryPoint)
+{
+ QShaderCode mtllib = shader.shader({ QShader::MetalLibShader, 12, shaderVariant });
+ if (!mtllib.shader().isEmpty()) {
+ dispatch_data_t data = dispatch_data_create(mtllib.shader().constData(),
+ mtllib.shader().size(),
+ dispatch_get_global_queue(0, 0),
+ DISPATCH_DATA_DESTRUCTOR_DEFAULT);
+ NSError *err = nil;
+ id<MTLLibrary> lib = [dev newLibraryWithData: data error: &err];
+ dispatch_release(data);
+ if (!err) {
+ *entryPoint = mtllib.entryPoint();
+ return lib;
+ } else {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ qWarning("Failed to load metallib from baked shader: %s", qPrintable(msg));
+ }
+ }
+
+ QShaderCode mslSource = shader.shader({ QShader::MslShader, 12, shaderVariant });
+ if (mslSource.shader().isEmpty()) {
+ qWarning() << "No MSL 1.2 code found in baked shader" << shader;
+ return nil;
+ }
+
+ NSString *src = [NSString stringWithUTF8String: mslSource.shader().constData()];
+ MTLCompileOptions *opts = [[MTLCompileOptions alloc] init];
+ opts.languageVersion = MTLLanguageVersion1_2;
+ NSError *err = nil;
+ id<MTLLibrary> lib = [dev newLibraryWithSource: src options: opts error: &err];
+ [opts release];
+ // src is autoreleased
+
+ if (err) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ *error = msg;
+ return nil;
+ }
+
+ *entryPoint = mslSource.entryPoint();
+ return lib;
+}
+
+id<MTLFunction> QRhiMetalData::createMSLShaderFunction(id<MTLLibrary> lib, const QByteArray &entryPoint)
+{
+ NSString *name = [NSString stringWithUTF8String: entryPoint.constData()];
+ id<MTLFunction> f = [lib newFunctionWithName: name];
+ [name release];
+ return f;
+}
+
+bool QMetalGraphicsPipeline::build()
+{
+ if (d->ps)
+ release();
+
+ QRHI_RES_RHI(QRhiMetal);
+
+ // same binding space for vertex and constant buffers - work it around
+ const int firstVertexBinding = QRHI_RES(QMetalShaderResourceBindings, m_shaderResourceBindings)->maxBinding + 1;
+
+ MTLVertexDescriptor *inputLayout = [MTLVertexDescriptor vertexDescriptor];
+ const QVector<QRhiVertexInputAttribute> attributes = m_vertexInputLayout.attributes();
+ for (const QRhiVertexInputAttribute &attribute : attributes) {
+ const int loc = attribute.location();
+ inputLayout.attributes[loc].format = toMetalAttributeFormat(attribute.format());
+ inputLayout.attributes[loc].offset = attribute.offset();
+ inputLayout.attributes[loc].bufferIndex = firstVertexBinding + attribute.binding();
+ }
+ const QVector<QRhiVertexInputBinding> bindings = m_vertexInputLayout.bindings();
+ for (int i = 0, ie = bindings.count(); i != ie; ++i) {
+ const QRhiVertexInputBinding &binding(bindings[i]);
+ const int layoutIdx = firstVertexBinding + i;
+ inputLayout.layouts[layoutIdx].stepFunction =
+ binding.classification() == QRhiVertexInputBinding::PerInstance
+ ? MTLVertexStepFunctionPerInstance : MTLVertexStepFunctionPerVertex;
+ inputLayout.layouts[layoutIdx].stepRate = binding.instanceStepRate();
+ inputLayout.layouts[layoutIdx].stride = binding.stride();
+ }
+
+ MTLRenderPipelineDescriptor *rpDesc = [[MTLRenderPipelineDescriptor alloc] init];
+
+ rpDesc.vertexDescriptor = inputLayout;
+
+ if (@available(macOS 10.13, iOS 11.0, *)) {
+ // Everything is immutable because we can guarantee that "neither the
+ // CPU nor the GPU will modify a buffer's contents between the time the
+ // buffer is set in a function's argument table and the time its
+ // associated command buffer completes execution" (as that's the point
+ // of our Vulkan-style buffer juggling in the first place).
+ const int vertexBufferCount = firstVertexBinding + bindings.count(); // cbuf + vbuf
+ const int fragmentBufferCount = firstVertexBinding; // cbuf
+ for (int i = 0; i < vertexBufferCount; ++i)
+ rpDesc.vertexBuffers[i].mutability = MTLMutabilityImmutable;
+ for (int i = 0; i < fragmentBufferCount; ++i)
+ rpDesc.fragmentBuffers[i].mutability = MTLMutabilityImmutable;
+ }
+
+ for (const QRhiGraphicsShaderStage &shaderStage : qAsConst(m_shaderStages)) {
+ QString error;
+ QByteArray entryPoint;
+ id<MTLLibrary> lib = rhiD->d->createMetalLib(shaderStage.shader(), shaderStage.shaderVariant(), &error, &entryPoint);
+ if (!lib) {
+ qWarning("MSL shader compilation failed: %s", qPrintable(error));
+ return false;
+ }
+ id<MTLFunction> func = rhiD->d->createMSLShaderFunction(lib, entryPoint);
+ if (!func) {
+ qWarning("MSL function for entry point %s not found", entryPoint.constData());
+ [lib release];
+ return false;
+ }
+ switch (shaderStage.type()) {
+ case QRhiGraphicsShaderStage::Vertex:
+ rpDesc.vertexFunction = func;
+ d->vsLib = lib;
+ d->vsFunc = func;
+ break;
+ case QRhiGraphicsShaderStage::Fragment:
+ rpDesc.fragmentFunction = func;
+ d->fsLib = lib;
+ d->fsFunc = func;
+ break;
+ default:
+ [func release];
+ [lib release];
+ break;
+ }
+ }
+
+ QMetalRenderPassDescriptor *rpD = QRHI_RES(QMetalRenderPassDescriptor, m_renderPassDesc);
+
+ if (rpD->colorAttachmentCount) {
+ // defaults when no targetBlends are provided
+ rpDesc.colorAttachments[0].pixelFormat = MTLPixelFormat(rpD->colorFormat[0]);
+ rpDesc.colorAttachments[0].writeMask = MTLColorWriteMaskAll;
+ rpDesc.colorAttachments[0].blendingEnabled = false;
+
+ Q_ASSERT(m_targetBlends.count() == rpD->colorAttachmentCount
+ || (m_targetBlends.isEmpty() && rpD->colorAttachmentCount == 1));
+
+ for (int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
+ const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
+ rpDesc.colorAttachments[i].pixelFormat = MTLPixelFormat(rpD->colorFormat[i]);
+ rpDesc.colorAttachments[i].blendingEnabled = b.enable;
+ rpDesc.colorAttachments[i].sourceRGBBlendFactor = toMetalBlendFactor(b.srcColor);
+ rpDesc.colorAttachments[i].destinationRGBBlendFactor = toMetalBlendFactor(b.dstColor);
+ rpDesc.colorAttachments[i].rgbBlendOperation = toMetalBlendOp(b.opColor);
+ rpDesc.colorAttachments[i].sourceAlphaBlendFactor = toMetalBlendFactor(b.srcAlpha);
+ rpDesc.colorAttachments[i].destinationAlphaBlendFactor = toMetalBlendFactor(b.dstAlpha);
+ rpDesc.colorAttachments[i].alphaBlendOperation = toMetalBlendOp(b.opAlpha);
+ rpDesc.colorAttachments[i].writeMask = toMetalColorWriteMask(b.colorWrite);
+ }
+ }
+
+ if (rpD->hasDepthStencil) {
+ // Must only be set when a depth-stencil buffer will actually be bound,
+ // validation blows up otherwise.
+ MTLPixelFormat fmt = MTLPixelFormat(rpD->dsFormat);
+ rpDesc.depthAttachmentPixelFormat = fmt;
+ if (fmt != MTLPixelFormatDepth16Unorm && fmt != MTLPixelFormatDepth32Float)
+ rpDesc.stencilAttachmentPixelFormat = fmt;
+ }
+
+ rpDesc.sampleCount = rhiD->effectiveSampleCount(m_sampleCount);
+
+ NSError *err = nil;
+ d->ps = [rhiD->d->dev newRenderPipelineStateWithDescriptor: rpDesc error: &err];
+ if (!d->ps) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ qWarning("Failed to create render pipeline state: %s", qPrintable(msg));
+ [rpDesc release];
+ return false;
+ }
+ [rpDesc release];
+
+ MTLDepthStencilDescriptor *dsDesc = [[MTLDepthStencilDescriptor alloc] init];
+ dsDesc.depthCompareFunction = m_depthTest ? toMetalCompareOp(m_depthOp) : MTLCompareFunctionAlways;
+ dsDesc.depthWriteEnabled = m_depthWrite;
+ if (m_stencilTest) {
+ dsDesc.frontFaceStencil = [[MTLStencilDescriptor alloc] init];
+ dsDesc.frontFaceStencil.stencilFailureOperation = toMetalStencilOp(m_stencilFront.failOp);
+ dsDesc.frontFaceStencil.depthFailureOperation = toMetalStencilOp(m_stencilFront.depthFailOp);
+ dsDesc.frontFaceStencil.depthStencilPassOperation = toMetalStencilOp(m_stencilFront.passOp);
+ dsDesc.frontFaceStencil.stencilCompareFunction = toMetalCompareOp(m_stencilFront.compareOp);
+ dsDesc.frontFaceStencil.readMask = m_stencilReadMask;
+ dsDesc.frontFaceStencil.writeMask = m_stencilWriteMask;
+
+ dsDesc.backFaceStencil = [[MTLStencilDescriptor alloc] init];
+ dsDesc.backFaceStencil.stencilFailureOperation = toMetalStencilOp(m_stencilBack.failOp);
+ dsDesc.backFaceStencil.depthFailureOperation = toMetalStencilOp(m_stencilBack.depthFailOp);
+ dsDesc.backFaceStencil.depthStencilPassOperation = toMetalStencilOp(m_stencilBack.passOp);
+ dsDesc.backFaceStencil.stencilCompareFunction = toMetalCompareOp(m_stencilBack.compareOp);
+ dsDesc.backFaceStencil.readMask = m_stencilReadMask;
+ dsDesc.backFaceStencil.writeMask = m_stencilWriteMask;
+ }
+
+ d->ds = [rhiD->d->dev newDepthStencilStateWithDescriptor: dsDesc];
+ [dsDesc release];
+
+ d->primitiveType = toMetalPrimitiveType(m_topology);
+ d->winding = m_frontFace == CCW ? MTLWindingCounterClockwise : MTLWindingClockwise;
+ d->cullMode = toMetalCullMode(m_cullMode);
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QMetalCommandBuffer::QMetalCommandBuffer(QRhiImplementation *rhi)
+ : QRhiCommandBuffer(rhi),
+ d(new QMetalCommandBufferData)
+{
+ resetState();
+}
+
+QMetalCommandBuffer::~QMetalCommandBuffer()
+{
+ release();
+ delete d;
+}
+
+void QMetalCommandBuffer::release()
+{
+ // nothing to do here, we do not own the MTL cb object
+}
+
+const QRhiNativeHandles *QMetalCommandBuffer::nativeHandles()
+{
+ nativeHandlesStruct.commandBuffer = d->cb;
+ nativeHandlesStruct.encoder = d->currentPassEncoder;
+ return &nativeHandlesStruct;
+}
+
+void QMetalCommandBuffer::resetState()
+{
+ d->currentPassEncoder = nil;
+ d->currentPassRpDesc = nil;
+ resetPerPassState();
+}
+
+void QMetalCommandBuffer::resetPerPassState()
+{
+ currentTarget = nullptr;
+ resetPerPassCachedState();
+}
+
+void QMetalCommandBuffer::resetPerPassCachedState()
+{
+ currentPipeline = nullptr;
+ currentPipelineGeneration = 0;
+ currentSrb = nullptr;
+ currentSrbGeneration = 0;
+ currentResSlot = -1;
+ currentIndexBuffer = nullptr;
+
+ d->currentFirstVertexBinding = -1;
+ d->currentVertexInputsBuffers.clear();
+ d->currentVertexInputOffsets.clear();
+}
+
+QMetalSwapChain::QMetalSwapChain(QRhiImplementation *rhi)
+ : QRhiSwapChain(rhi),
+ rtWrapper(rhi),
+ cbWrapper(rhi),
+ d(new QMetalSwapChainData)
+{
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ d->sem[i] = nullptr;
+ d->msaaTex[i] = nil;
+ }
+}
+
+QMetalSwapChain::~QMetalSwapChain()
+{
+ release();
+ delete d;
+}
+
+void QMetalSwapChain::release()
+{
+ if (!d->layer)
+ return;
+
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ if (d->sem[i]) {
+ // the semaphores cannot be released if they do not have the initial value
+ dispatch_semaphore_wait(d->sem[i], DISPATCH_TIME_FOREVER);
+ dispatch_semaphore_signal(d->sem[i]);
+
+ dispatch_release(d->sem[i]);
+ d->sem[i] = nullptr;
+ }
+ }
+
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ [d->msaaTex[i] release];
+ d->msaaTex[i] = nil;
+ }
+
+ d->layer = nullptr;
+
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->swapchains.remove(this);
+
+ QRHI_PROF;
+ QRHI_PROF_F(releaseSwapChain(this));
+
+ rhiD->unregisterResource(this);
+}
+
+QRhiCommandBuffer *QMetalSwapChain::currentFrameCommandBuffer()
+{
+ return &cbWrapper;
+}
+
+QRhiRenderTarget *QMetalSwapChain::currentFrameRenderTarget()
+{
+ return &rtWrapper;
+}
+
+QSize QMetalSwapChain::surfacePixelSize()
+{
+ // may be called before build, must not access other than m_*
+
+ NSView *v = (NSView *) m_window->winId();
+ if (v) {
+ CAMetalLayer *layer = (CAMetalLayer *) [v layer];
+ if (layer) {
+ CGSize size = [layer drawableSize];
+ return QSize(size.width, size.height);
+ }
+ }
+ return QSize();
+}
+
+QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor()
+{
+ chooseFormats(); // ensure colorFormat and similar are filled out
+
+ QRHI_RES_RHI(QRhiMetal);
+ QMetalRenderPassDescriptor *rpD = new QMetalRenderPassDescriptor(m_rhi);
+ rpD->colorAttachmentCount = 1;
+ rpD->hasDepthStencil = m_depthStencil != nullptr;
+
+ rpD->colorFormat[0] = d->colorFormat;
+
+ // m_depthStencil may not be built yet so cannot rely on computed fields in it
+ rpD->dsFormat = rhiD->d->dev.depth24Stencil8PixelFormatSupported
+ ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
+
+ return rpD;
+}
+
+void QMetalSwapChain::chooseFormats()
+{
+ QRHI_RES_RHI(QRhiMetal);
+ samples = rhiD->effectiveSampleCount(m_sampleCount);
+ // pick a format that is allowed for CAMetalLayer.pixelFormat
+ d->colorFormat = m_flags.testFlag(sRGB) ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm;
+ d->rhiColorFormat = QRhiTexture::BGRA8;
+}
+
+bool QMetalSwapChain::buildOrResize()
+{
+ Q_ASSERT(m_window);
+
+ const bool needsRegistration = !window || window != m_window;
+
+ if (window && window != m_window)
+ release();
+ // else no release(), this is intentional
+
+ QRHI_RES_RHI(QRhiMetal);
+ if (needsRegistration)
+ rhiD->swapchains.insert(this);
+
+ window = m_window;
+
+ if (window->surfaceType() != QSurface::MetalSurface) {
+ qWarning("QMetalSwapChain only supports MetalSurface windows");
+ return false;
+ }
+
+ NSView *v = (NSView *) window->winId();
+ d->layer = (CAMetalLayer *) [v layer];
+ Q_ASSERT(d->layer);
+
+ chooseFormats();
+ if (d->colorFormat != d->layer.pixelFormat)
+ d->layer.pixelFormat = d->colorFormat;
+
+ if (m_flags.testFlag(UsedAsTransferSource))
+ d->layer.framebufferOnly = NO;
+
+#ifdef Q_OS_MACOS
+ if (m_flags.testFlag(NoVSync)) {
+ if (@available(macOS 10.13, *))
+ d->layer.displaySyncEnabled = NO;
+ }
+#endif
+
+ m_currentPixelSize = surfacePixelSize();
+ pixelSize = m_currentPixelSize;
+
+ [d->layer setDevice: rhiD->d->dev];
+
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ if (!d->sem[i])
+ d->sem[i] = dispatch_semaphore_create(QMTL_FRAMES_IN_FLIGHT - 1);
+ }
+
+ currentFrameSlot = 0;
+ frameCount = 0;
+
+ ds = m_depthStencil ? QRHI_RES(QMetalRenderBuffer, m_depthStencil) : nullptr;
+ if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
+ qWarning("Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
+ m_depthStencil->sampleCount(), m_sampleCount);
+ }
+ if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
+ qWarning("Depth-stencil buffer's size (%dx%d) does not match the layer size (%dx%d). Expect problems.",
+ m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
+ pixelSize.width(), pixelSize.height());
+ }
+
+ rtWrapper.d->pixelSize = pixelSize;
+ rtWrapper.d->dpr = window->devicePixelRatio();
+ rtWrapper.d->sampleCount = samples;
+ rtWrapper.d->colorAttCount = 1;
+ rtWrapper.d->dsAttCount = ds ? 1 : 0;
+
+ qDebug("got CAMetalLayer, size %dx%d", pixelSize.width(), pixelSize.height());
+
+ if (samples > 1) {
+ MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init];
+ desc.textureType = MTLTextureType2DMultisample;
+ desc.pixelFormat = d->colorFormat;
+ desc.width = pixelSize.width();
+ desc.height = pixelSize.height();
+ desc.sampleCount = samples;
+ desc.resourceOptions = MTLResourceStorageModePrivate;
+ desc.storageMode = MTLStorageModePrivate;
+ desc.usage = MTLTextureUsageRenderTarget;
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ [d->msaaTex[i] release];
+ d->msaaTex[i] = [rhiD->d->dev newTextureWithDescriptor: desc];
+ }
+ [desc release];
+ }
+
+ QRHI_PROF;
+ QRHI_PROF_F(resizeSwapChain(this, QMTL_FRAMES_IN_FLIGHT, samples > 1 ? QMTL_FRAMES_IN_FLIGHT : 0, samples));
+
+ if (needsRegistration)
+ rhiD->registerResource(this);
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhimetal_p.h b/src/gui/rhi/qrhimetal_p.h
new file mode 100644
index 0000000000..094801c58c
--- /dev/null
+++ b/src/gui/rhi/qrhimetal_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHIMETAL_H
+#define QRHIMETAL_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qrhi_p.h>
+
+// no Metal includes here, the user code may be plain C++
+
+QT_BEGIN_NAMESPACE
+
+struct Q_GUI_EXPORT QRhiMetalInitParams : public QRhiInitParams
+{
+};
+
+struct Q_GUI_EXPORT QRhiMetalNativeHandles : public QRhiNativeHandles
+{
+ void *dev = nullptr; // id<MTLDevice>
+ void *cmdQueue = nullptr; // id<MTLCommandQueue>
+};
+
+struct Q_GUI_EXPORT QRhiMetalTextureNativeHandles : public QRhiNativeHandles
+{
+ void *texture = nullptr; // id<MTLTexture>
+};
+
+struct Q_GUI_EXPORT QRhiMetalCommandBufferNativeHandles : public QRhiNativeHandles
+{
+ void *commandBuffer = nullptr; // id<MTLCommandBuffer>
+ void *encoder = nullptr; // id<MTLRenderCommandEncoder>
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
new file mode 100644
index 0000000000..039a5bdbf6
--- /dev/null
+++ b/src/gui/rhi/qrhimetal_p_p.h
@@ -0,0 +1,410 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHIMETAL_P_H
+#define QRHIMETAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrhimetal_p.h"
+#include "qrhi_p_p.h"
+#include <QWindow>
+
+QT_BEGIN_NAMESPACE
+
+static const int QMTL_FRAMES_IN_FLIGHT = 2;
+
+// have to hide the ObjC stuff, this header cannot contain MTL* at all
+struct QMetalBufferData;
+
+struct QMetalBuffer : public QRhiBuffer
+{
+ QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
+ ~QMetalBuffer();
+ void release() override;
+ bool build() override;
+
+ QMetalBufferData *d;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+ friend struct QMetalShaderResourceBindings;
+};
+
+struct QMetalRenderBufferData;
+
+struct QMetalRenderBuffer : public QRhiRenderBuffer
+{
+ QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags);
+ ~QMetalRenderBuffer();
+ void release() override;
+ bool build() override;
+ QRhiTexture::Format backingFormat() const override;
+
+ QMetalRenderBufferData *d;
+ int samples = 1;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+};
+
+struct QMetalTextureData;
+
+struct QMetalTexture : public QRhiTexture
+{
+ QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ int sampleCount, Flags flags);
+ ~QMetalTexture();
+ void release() override;
+ bool build() override;
+ bool buildFrom(const QRhiNativeHandles *src) override;
+ const QRhiNativeHandles *nativeHandles() override;
+
+ bool prepareBuild(QSize *adjustedSize = nullptr);
+
+ QMetalTextureData *d;
+ QRhiMetalTextureNativeHandles nativeHandlesStruct;
+ int mipLevelCount = 0;
+ int samples = 1;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+ friend struct QMetalShaderResourceBindings;
+};
+
+struct QMetalSamplerData;
+
+struct QMetalSampler : public QRhiSampler
+{
+ QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v);
+ ~QMetalSampler();
+ void release() override;
+ bool build() override;
+
+ QMetalSamplerData *d;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+ friend struct QMetalShaderResourceBindings;
+};
+
+struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QMetalRenderPassDescriptor(QRhiImplementation *rhi);
+ ~QMetalRenderPassDescriptor();
+ void release() override;
+
+ // there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass()
+
+ // but the things needed for the render pipeline descriptor have to be provided
+ static const int MAX_COLOR_ATTACHMENTS = 8;
+ int colorAttachmentCount = 0;
+ bool hasDepthStencil = false;
+ int colorFormat[MAX_COLOR_ATTACHMENTS];
+ int dsFormat;
+};
+
+struct QMetalRenderTargetData;
+
+struct QMetalReferenceRenderTarget : public QRhiRenderTarget
+{
+ QMetalReferenceRenderTarget(QRhiImplementation *rhi);
+ ~QMetalReferenceRenderTarget();
+ void release() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QMetalRenderTargetData *d;
+};
+
+struct QMetalTextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QMetalTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
+ ~QMetalTextureRenderTarget();
+ void release() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool build() override;
+
+ QMetalRenderTargetData *d;
+ friend class QRhiMetal;
+};
+
+struct QMetalShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QMetalShaderResourceBindings(QRhiImplementation *rhi);
+ ~QMetalShaderResourceBindings();
+ void release() override;
+ bool build() override;
+
+ QVector<QRhiShaderResourceBinding> sortedBindings;
+ int maxBinding = -1;
+
+ struct BoundUniformBufferData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundSampledTextureData {
+ quint64 texId;
+ uint texGeneration;
+ quint64 samplerId;
+ uint samplerGeneration;
+ };
+ struct BoundResourceData {
+ union {
+ BoundUniformBufferData ubuf;
+ BoundSampledTextureData stex;
+ };
+ };
+ QVector<BoundResourceData> boundResourceData;
+
+ uint generation = 0;
+ friend class QRhiMetal;
+};
+
+struct QMetalGraphicsPipelineData;
+
+struct QMetalGraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QMetalGraphicsPipeline(QRhiImplementation *rhi);
+ ~QMetalGraphicsPipeline();
+ void release() override;
+ bool build() override;
+
+ QMetalGraphicsPipelineData *d;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+};
+
+struct QMetalCommandBufferData;
+struct QMetalSwapChain;
+
+struct QMetalCommandBuffer : public QRhiCommandBuffer
+{
+ QMetalCommandBuffer(QRhiImplementation *rhi);
+ ~QMetalCommandBuffer();
+ void release() override;
+
+ QMetalCommandBufferData *d = nullptr;
+ QRhiMetalCommandBufferNativeHandles nativeHandlesStruct;
+
+ QRhiRenderTarget *currentTarget;
+ QRhiGraphicsPipeline *currentPipeline;
+ uint currentPipelineGeneration;
+ QRhiShaderResourceBindings *currentSrb;
+ uint currentSrbGeneration;
+ int currentResSlot;
+ QRhiBuffer *currentIndexBuffer;
+ quint32 currentIndexOffset;
+ QRhiCommandBuffer::IndexFormat currentIndexFormat;
+
+ const QRhiNativeHandles *nativeHandles();
+ void resetState();
+ void resetPerPassState();
+ void resetPerPassCachedState();
+};
+
+struct QMetalSwapChainData;
+
+struct QMetalSwapChain : public QRhiSwapChain
+{
+ QMetalSwapChain(QRhiImplementation *rhi);
+ ~QMetalSwapChain();
+ void release() override;
+
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+ QSize surfacePixelSize() override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+
+ bool buildOrResize() override;
+
+ void chooseFormats();
+
+ QWindow *window = nullptr;
+ QSize pixelSize;
+ int currentFrameSlot = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1
+ int frameCount = 0;
+ int samples = 1;
+ QMetalReferenceRenderTarget rtWrapper;
+ QMetalCommandBuffer cbWrapper;
+ QMetalRenderBuffer *ds = nullptr;
+ QMetalSwapChainData *d = nullptr;
+};
+
+struct QRhiMetalData;
+
+class QRhiMetal : public QRhiImplementation
+{
+public:
+ QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice = nullptr);
+ ~QRhiMetal();
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ int size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
+ QRhi::FrameOpResult endOffscreenFrame() override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+
+ QVector<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ void sendVMemStatsToProfiler() override;
+
+ void executeDeferredReleases(bool forced = false);
+ void finishActiveReadbacks(bool forced = false);
+ qsizetype subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
+ void enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEncPtr,
+ int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc,
+ qsizetype *curOfs);
+ void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
+ void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
+ void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD, QMetalCommandBuffer *cbD,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets,
+ bool offsetOnlyChange);
+ int effectiveSampleCount(int sampleCount) const;
+
+ bool importedDevice = false;
+ bool importedCmdQueue = false;
+ bool inFrame = false;
+ bool inPass = false;
+ QMetalSwapChain *currentSwapChain = nullptr;
+ QSet<QMetalSwapChain *> swapchains;
+ QRhiMetalNativeHandles nativeHandlesStruct;
+
+ struct {
+ int maxTextureSize = 4096;
+ } caps;
+
+ QRhiMetalData *d = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp
new file mode 100644
index 0000000000..ad7b74a5c3
--- /dev/null
+++ b/src/gui/rhi/qrhinull.cpp
@@ -0,0 +1,709 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrhinull_p_p.h"
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QRhiNullInitParams
+ \inmodule QtRhi
+ \brief Null backend specific initialization parameters.
+
+ A Null QRhi needs no special parameters for initialization.
+
+ \badcode
+ QRhiNullInitParams params;
+ rhi = QRhi::create(QRhi::Null, &params);
+ \endcode
+
+ The Null backend does not issue any graphics calls and creates no
+ resources. All QRhi operations will succeed as normal so applications can
+ still be run, albeit potentially at an unthrottled speed, depending on
+ their frame rendering strategy. The backend reports resources to
+ QRhiProfiler as usual.
+ */
+
+/*!
+ \class QRhiNullNativeHandles
+ \inmodule QtRhi
+ \brief Empty.
+ */
+
+/*!
+ \class QRhiNullTextureNativeHandles
+ \inmodule QtRhi
+ \brief Empty.
+ */
+
+QRhiNull::QRhiNull(QRhiNullInitParams *params)
+ : offscreenCommandBuffer(this)
+{
+ Q_UNUSED(params);
+}
+
+bool QRhiNull::create(QRhi::Flags flags)
+{
+ Q_UNUSED(flags);
+ return true;
+}
+
+void QRhiNull::destroy()
+{
+}
+
+QVector<int> QRhiNull::supportedSampleCounts() const
+{
+ return { 1 };
+}
+
+QRhiSwapChain *QRhiNull::createSwapChain()
+{
+ return new QNullSwapChain(this);
+}
+
+QRhiBuffer *QRhiNull::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+{
+ return new QNullBuffer(this, type, usage, size);
+}
+
+int QRhiNull::ubufAlignment() const
+{
+ return 256;
+}
+
+bool QRhiNull::isYUpInFramebuffer() const
+{
+ return false;
+}
+
+bool QRhiNull::isYUpInNDC() const
+{
+ return true;
+}
+
+bool QRhiNull::isClipDepthZeroToOne() const
+{
+ return true;
+}
+
+QMatrix4x4 QRhiNull::clipSpaceCorrMatrix() const
+{
+ return QMatrix4x4(); // identity
+}
+
+bool QRhiNull::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
+{
+ Q_UNUSED(format);
+ Q_UNUSED(flags);
+ return true;
+}
+
+bool QRhiNull::isFeatureSupported(QRhi::Feature feature) const
+{
+ Q_UNUSED(feature);
+ return true;
+}
+
+int QRhiNull::resourceLimit(QRhi::ResourceLimit limit) const
+{
+ switch (limit) {
+ case QRhi::TextureSizeMin:
+ return 1;
+ case QRhi::TextureSizeMax:
+ return 16384;
+ case QRhi::MaxColorAttachments:
+ return 8;
+ case QRhi::FramesInFlight:
+ return 2; // dummy
+ default:
+ Q_UNREACHABLE();
+ return 0;
+ }
+}
+
+const QRhiNativeHandles *QRhiNull::nativeHandles()
+{
+ return &nativeHandlesStruct;
+}
+
+void QRhiNull::sendVMemStatsToProfiler()
+{
+ // nothing to do here
+}
+
+QRhiRenderBuffer *QRhiNull::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags)
+{
+ return new QNullRenderBuffer(this, type, pixelSize, sampleCount, flags);
+}
+
+QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
+ int sampleCount, QRhiTexture::Flags flags)
+{
+ return new QNullTexture(this, format, pixelSize, sampleCount, flags);
+}
+
+QRhiSampler *QRhiNull::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+{
+ return new QNullSampler(this, magFilter, minFilter, mipmapMode, u, v);
+}
+
+QRhiTextureRenderTarget *QRhiNull::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags)
+{
+ return new QNullTextureRenderTarget(this, desc, flags);
+}
+
+QRhiGraphicsPipeline *QRhiNull::createGraphicsPipeline()
+{
+ return new QNullGraphicsPipeline(this);
+}
+
+QRhiShaderResourceBindings *QRhiNull::createShaderResourceBindings()
+{
+ return new QNullShaderResourceBindings(this);
+}
+
+void QRhiNull::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(ps);
+}
+
+void QRhiNull::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(srb);
+ Q_UNUSED(dynamicOffsetCount);
+ Q_UNUSED(dynamicOffsets);
+}
+
+void QRhiNull::setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(startBinding);
+ Q_UNUSED(bindingCount);
+ Q_UNUSED(bindings);
+ Q_UNUSED(indexBuf);
+ Q_UNUSED(indexOffset);
+ Q_UNUSED(indexFormat);
+}
+
+void QRhiNull::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(viewport);
+}
+
+void QRhiNull::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(scissor);
+}
+
+void QRhiNull::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(c);
+}
+
+void QRhiNull::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(refValue);
+}
+
+void QRhiNull::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(vertexCount);
+ Q_UNUSED(instanceCount);
+ Q_UNUSED(firstVertex);
+ Q_UNUSED(firstInstance);
+}
+
+void QRhiNull::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(indexCount);
+ Q_UNUSED(instanceCount);
+ Q_UNUSED(firstIndex);
+ Q_UNUSED(vertexOffset);
+ Q_UNUSED(firstInstance);
+}
+
+void QRhiNull::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(name);
+}
+
+void QRhiNull::debugMarkEnd(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+}
+
+void QRhiNull::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
+{
+ Q_UNUSED(cb);
+ Q_UNUSED(msg);
+}
+
+const QRhiNativeHandles *QRhiNull::nativeHandles(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+ return nullptr;
+}
+
+void QRhiNull::beginExternal(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+}
+
+void QRhiNull::endExternal(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+}
+
+QRhi::FrameOpResult QRhiNull::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
+{
+ Q_UNUSED(flags);
+ currentSwapChain = swapChain;
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+ QRHI_PROF_F(beginSwapChainFrame(swapChain));
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiNull::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags)
+{
+ Q_UNUSED(flags);
+ QNullSwapChain *swapChainD = QRHI_RES(QNullSwapChain, swapChain);
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+ QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
+ QRHI_PROF_F(swapChainFrameGpuTime(swapChain, 0.000666f));
+ swapChainD->frameCount += 1;
+ currentSwapChain = nullptr;
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiNull::beginOffscreenFrame(QRhiCommandBuffer **cb)
+{
+ *cb = &offscreenCommandBuffer;
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiNull::endOffscreenFrame()
+{
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiNull::finish()
+{
+ return QRhi::FrameOpSuccess;
+}
+
+void QRhiNull::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_UNUSED(cb);
+ QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
+ for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
+ if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) {
+ QRhiReadbackResult *result = u.read.result;
+ QRhiTexture *tex = u.read.rb.texture();
+ if (tex) {
+ result->format = tex->format();
+ result->pixelSize = q->sizeForMipLevel(u.read.rb.level(), tex->pixelSize());
+ } else {
+ Q_ASSERT(currentSwapChain);
+ result->format = QRhiTexture::RGBA8;
+ result->pixelSize = currentSwapChain->currentPixelSize();
+ }
+ quint32 byteSize = 0;
+ textureFormatInfo(result->format, result->pixelSize, nullptr, &byteSize);
+ result->data.fill(0, byteSize);
+ if (result->completed)
+ result->completed();
+ }
+ }
+ ud->free();
+}
+
+void QRhiNull::beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_UNUSED(rt);
+ Q_UNUSED(colorClearValue);
+ Q_UNUSED(depthStencilClearValue);
+ if (resourceUpdates)
+ resourceUpdate(cb, resourceUpdates);
+}
+
+void QRhiNull::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ if (resourceUpdates)
+ resourceUpdate(cb, resourceUpdates);
+}
+
+QNullBuffer::QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+ : QRhiBuffer(rhi, type, usage, size)
+{
+}
+
+QNullBuffer::~QNullBuffer()
+{
+ release();
+}
+
+void QNullBuffer::release()
+{
+ QRHI_PROF;
+ QRHI_PROF_F(releaseBuffer(this));
+}
+
+bool QNullBuffer::build()
+{
+ QRHI_PROF;
+ QRHI_PROF_F(newBuffer(this, m_size, 1, 0));
+ return true;
+}
+
+QNullRenderBuffer::QNullRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags)
+ : QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
+{
+}
+
+QNullRenderBuffer::~QNullRenderBuffer()
+{
+ release();
+}
+
+void QNullRenderBuffer::release()
+{
+ QRHI_PROF;
+ QRHI_PROF_F(releaseRenderBuffer(this));
+}
+
+bool QNullRenderBuffer::build()
+{
+ QRHI_PROF;
+ QRHI_PROF_F(newRenderBuffer(this, false, false, 1));
+ return true;
+}
+
+QRhiTexture::Format QNullRenderBuffer::backingFormat() const
+{
+ return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
+}
+
+QNullTexture::QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, sampleCount, flags)
+{
+}
+
+QNullTexture::~QNullTexture()
+{
+ release();
+}
+
+void QNullTexture::release()
+{
+ QRHI_PROF;
+ QRHI_PROF_F(releaseTexture(this));
+}
+
+bool QNullTexture::build()
+{
+ const bool isCube = m_flags.testFlag(CubeMap);
+ const bool hasMipMaps = m_flags.testFlag(MipMapped);
+ QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
+ const int mipLevelCount = hasMipMaps ? qCeil(log2(qMax(size.width(), size.height()))) + 1 : 1;
+ QRHI_PROF;
+ QRHI_PROF_F(newTexture(this, true, mipLevelCount, isCube ? 6 : 1, 1));
+ return true;
+}
+
+bool QNullTexture::buildFrom(const QRhiNativeHandles *src)
+{
+ Q_UNUSED(src);
+ const bool isCube = m_flags.testFlag(CubeMap);
+ const bool hasMipMaps = m_flags.testFlag(MipMapped);
+ QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
+ const int mipLevelCount = hasMipMaps ? qCeil(log2(qMax(size.width(), size.height()))) + 1 : 1;
+ QRHI_PROF;
+ QRHI_PROF_F(newTexture(this, false, mipLevelCount, isCube ? 6 : 1, 1));
+ return true;
+}
+
+const QRhiNativeHandles *QNullTexture::nativeHandles()
+{
+ return &nativeHandlesStruct;
+}
+
+QNullSampler::QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+{
+}
+
+QNullSampler::~QNullSampler()
+{
+ release();
+}
+
+void QNullSampler::release()
+{
+}
+
+bool QNullSampler::build()
+{
+ return true;
+}
+
+QNullRenderPassDescriptor::QNullRenderPassDescriptor(QRhiImplementation *rhi)
+ : QRhiRenderPassDescriptor(rhi)
+{
+}
+
+QNullRenderPassDescriptor::~QNullRenderPassDescriptor()
+{
+ release();
+}
+
+void QNullRenderPassDescriptor::release()
+{
+}
+
+QNullReferenceRenderTarget::QNullReferenceRenderTarget(QRhiImplementation *rhi)
+ : QRhiRenderTarget(rhi),
+ d(rhi)
+{
+}
+
+QNullReferenceRenderTarget::~QNullReferenceRenderTarget()
+{
+ release();
+}
+
+void QNullReferenceRenderTarget::release()
+{
+}
+
+QSize QNullReferenceRenderTarget::pixelSize() const
+{
+ return d.pixelSize;
+}
+
+float QNullReferenceRenderTarget::devicePixelRatio() const
+{
+ return d.dpr;
+}
+
+int QNullReferenceRenderTarget::sampleCount() const
+{
+ return 1;
+}
+
+QNullTextureRenderTarget::QNullTextureRenderTarget(QRhiImplementation *rhi,
+ const QRhiTextureRenderTargetDescription &desc,
+ Flags flags)
+ : QRhiTextureRenderTarget(rhi, desc, flags),
+ d(rhi)
+{
+}
+
+QNullTextureRenderTarget::~QNullTextureRenderTarget()
+{
+ release();
+}
+
+void QNullTextureRenderTarget::release()
+{
+}
+
+QRhiRenderPassDescriptor *QNullTextureRenderTarget::newCompatibleRenderPassDescriptor()
+{
+ return new QNullRenderPassDescriptor(m_rhi);
+}
+
+bool QNullTextureRenderTarget::build()
+{
+ d.rp = QRHI_RES(QNullRenderPassDescriptor, m_renderPassDesc);
+ const QVector<QRhiColorAttachment> colorAttachments = m_desc.colorAttachments();
+ if (!colorAttachments.isEmpty()) {
+ QRhiTexture *tex = colorAttachments.first().texture();
+ QRhiRenderBuffer *rb = colorAttachments.first().renderBuffer();
+ d.pixelSize = tex ? tex->pixelSize() : rb->pixelSize();
+ } else if (m_desc.depthStencilBuffer()) {
+ d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
+ } else if (m_desc.depthTexture()) {
+ d.pixelSize = m_desc.depthTexture()->pixelSize();
+ }
+ return true;
+}
+
+QSize QNullTextureRenderTarget::pixelSize() const
+{
+ return d.pixelSize;
+}
+
+float QNullTextureRenderTarget::devicePixelRatio() const
+{
+ return d.dpr;
+}
+
+int QNullTextureRenderTarget::sampleCount() const
+{
+ return 1;
+}
+
+QNullShaderResourceBindings::QNullShaderResourceBindings(QRhiImplementation *rhi)
+ : QRhiShaderResourceBindings(rhi)
+{
+}
+
+QNullShaderResourceBindings::~QNullShaderResourceBindings()
+{
+ release();
+}
+
+void QNullShaderResourceBindings::release()
+{
+}
+
+bool QNullShaderResourceBindings::build()
+{
+ return true;
+}
+
+QNullGraphicsPipeline::QNullGraphicsPipeline(QRhiImplementation *rhi)
+ : QRhiGraphicsPipeline(rhi)
+{
+}
+
+QNullGraphicsPipeline::~QNullGraphicsPipeline()
+{
+ release();
+}
+
+void QNullGraphicsPipeline::release()
+{
+}
+
+bool QNullGraphicsPipeline::build()
+{
+ return true;
+}
+
+QNullCommandBuffer::QNullCommandBuffer(QRhiImplementation *rhi)
+ : QRhiCommandBuffer(rhi)
+{
+}
+
+QNullCommandBuffer::~QNullCommandBuffer()
+{
+ release();
+}
+
+void QNullCommandBuffer::release()
+{
+ // nothing to do here
+}
+
+QNullSwapChain::QNullSwapChain(QRhiImplementation *rhi)
+ : QRhiSwapChain(rhi),
+ rt(rhi),
+ cb(rhi)
+{
+}
+
+QNullSwapChain::~QNullSwapChain()
+{
+ release();
+}
+
+void QNullSwapChain::release()
+{
+ QRHI_PROF;
+ QRHI_PROF_F(releaseSwapChain(this));
+}
+
+QRhiCommandBuffer *QNullSwapChain::currentFrameCommandBuffer()
+{
+ return &cb;
+}
+
+QRhiRenderTarget *QNullSwapChain::currentFrameRenderTarget()
+{
+ return &rt;
+}
+
+QSize QNullSwapChain::surfacePixelSize()
+{
+ return QSize(1280, 720);
+}
+
+QRhiRenderPassDescriptor *QNullSwapChain::newCompatibleRenderPassDescriptor()
+{
+ return new QNullRenderPassDescriptor(m_rhi);
+}
+
+bool QNullSwapChain::buildOrResize()
+{
+ m_currentPixelSize = surfacePixelSize();
+ rt.d.rp = QRHI_RES(QNullRenderPassDescriptor, m_renderPassDesc);
+ rt.d.pixelSize = m_currentPixelSize;
+ frameCount = 0;
+ QRHI_PROF;
+ QRHI_PROF_F(resizeSwapChain(this, 1, 0, 1));
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhinull_p.h b/src/gui/rhi/qrhinull_p.h
new file mode 100644
index 0000000000..7d3ce5dbf1
--- /dev/null
+++ b/src/gui/rhi/qrhinull_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHINULL_H
+#define QRHINULL_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qrhi_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct Q_GUI_EXPORT QRhiNullInitParams : public QRhiInitParams
+{
+};
+
+struct Q_GUI_EXPORT QRhiNullNativeHandles : public QRhiNativeHandles
+{
+};
+
+struct Q_GUI_EXPORT QRhiNullTextureNativeHandles : public QRhiNativeHandles
+{
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhinull_p_p.h b/src/gui/rhi/qrhinull_p_p.h
new file mode 100644
index 0000000000..da48b72656
--- /dev/null
+++ b/src/gui/rhi/qrhinull_p_p.h
@@ -0,0 +1,279 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHINULL_P_H
+#define QRHINULL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrhinull_p.h"
+#include "qrhi_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QNullBuffer : public QRhiBuffer
+{
+ QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
+ ~QNullBuffer();
+ void release() override;
+ bool build() override;
+};
+
+struct QNullRenderBuffer : public QRhiRenderBuffer
+{
+ QNullRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags);
+ ~QNullRenderBuffer();
+ void release() override;
+ bool build() override;
+ QRhiTexture::Format backingFormat() const override;
+};
+
+struct QNullTexture : public QRhiTexture
+{
+ QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ int sampleCount, Flags flags);
+ ~QNullTexture();
+ void release() override;
+ bool build() override;
+ bool buildFrom(const QRhiNativeHandles *src) override;
+ const QRhiNativeHandles *nativeHandles() override;
+
+ QRhiNullTextureNativeHandles nativeHandlesStruct;
+};
+
+struct QNullSampler : public QRhiSampler
+{
+ QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v);
+ ~QNullSampler();
+ void release() override;
+ bool build() override;
+};
+
+struct QNullRenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QNullRenderPassDescriptor(QRhiImplementation *rhi);
+ ~QNullRenderPassDescriptor();
+ void release() override;
+};
+
+struct QNullRenderTargetData
+{
+ QNullRenderTargetData(QRhiImplementation *) { }
+
+ QNullRenderPassDescriptor *rp = nullptr;
+ QSize pixelSize;
+ float dpr = 1;
+};
+
+struct QNullReferenceRenderTarget : public QRhiRenderTarget
+{
+ QNullReferenceRenderTarget(QRhiImplementation *rhi);
+ ~QNullReferenceRenderTarget();
+ void release() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QNullRenderTargetData d;
+};
+
+struct QNullTextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QNullTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
+ ~QNullTextureRenderTarget();
+ void release() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool build() override;
+
+ QNullRenderTargetData d;
+};
+
+struct QNullShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QNullShaderResourceBindings(QRhiImplementation *rhi);
+ ~QNullShaderResourceBindings();
+ void release() override;
+ bool build() override;
+};
+
+struct QNullGraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QNullGraphicsPipeline(QRhiImplementation *rhi);
+ ~QNullGraphicsPipeline();
+ void release() override;
+ bool build() override;
+};
+
+struct QNullCommandBuffer : public QRhiCommandBuffer
+{
+ QNullCommandBuffer(QRhiImplementation *rhi);
+ ~QNullCommandBuffer();
+ void release() override;
+};
+
+struct QNullSwapChain : public QRhiSwapChain
+{
+ QNullSwapChain(QRhiImplementation *rhi);
+ ~QNullSwapChain();
+ void release() override;
+
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+
+ QSize surfacePixelSize() override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool buildOrResize() override;
+
+ QNullReferenceRenderTarget rt;
+ QNullCommandBuffer cb;
+ int frameCount = 0;
+};
+
+class QRhiNull : public QRhiImplementation
+{
+public:
+ QRhiNull(QRhiNullInitParams *params);
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ int size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
+ QRhi::FrameOpResult endOffscreenFrame() override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+
+ QVector<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ void sendVMemStatsToProfiler() override;
+
+ QRhiNullNativeHandles nativeHandlesStruct;
+ QRhiSwapChain *currentSwapChain = nullptr;
+ QNullCommandBuffer offscreenCommandBuffer;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhiprofiler.cpp b/src/gui/rhi/qrhiprofiler.cpp
new file mode 100644
index 0000000000..15e3007d49
--- /dev/null
+++ b/src/gui/rhi/qrhiprofiler.cpp
@@ -0,0 +1,603 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrhiprofiler_p_p.h"
+#include "qrhi_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QRhiProfiler
+ \inmodule QtRhi
+
+ \brief Collects resource and timing information from an active QRhi.
+
+ A QRhiProfiler is present for each QRhi. Query it via QRhi::profiler(). The
+ profiler is active only when the QRhi was created with
+ QRhi::EnableProfiling. No data is collected otherwise.
+
+ \note GPU timings are only available when QRhi indicates that
+ QRhi::Timestamps is supported.
+
+ Besides collecting data from the QRhi implementations, some additional
+ values are calculated. For example, for textures and similar resources the
+ profiler gives an estimate of the complete amount of memory the resource
+ needs.
+
+ \section2 Output Format
+
+ The output is comma-separated text. Each line has a number of
+ comma-separated entries and each line ends with a comma.
+
+ For example:
+
+ \badcode
+ 1,0,140446057946208,Triangle vbuf,type,0,usage,1,logical_size,84,effective_size,84,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
+ 1,0,140446057947376,Triangle ubuf,type,2,usage,4,logical_size,68,effective_size,256,backing_gpu_buf_count,2,backing_cpu_buf_count,0,
+ 1,1,140446057950416,,type,0,usage,1,logical_size,112,effective_size,112,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
+ 1,1,140446057950544,,type,0,usage,2,logical_size,12,effective_size,12,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
+ 1,1,140446057947440,,type,2,usage,4,logical_size,68,effective_size,256,backing_gpu_buf_count,2,backing_cpu_buf_count,0,
+ 1,1,140446057984784,Cube vbuf (textured),type,0,usage,1,logical_size,720,effective_size,720,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
+ 1,1,140446057982528,Cube ubuf (textured),type,2,usage,4,logical_size,68,effective_size,256,backing_gpu_buf_count,2,backing_cpu_buf_count,0,
+ 7,8,140446058913648,Qt texture,width,256,height,256,format,1,owns_native_resource,1,mip_count,9,layer_count,1,effective_sample_count,1,approx_byte_size,349524,
+ 1,8,140446058795856,Cube vbuf (textured with offscreen),type,0,usage,1,logical_size,720,effective_size,720,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
+ 1,8,140446058947920,Cube ubuf (textured with offscreen),type,2,usage,4,logical_size,68,effective_size,256,backing_gpu_buf_count,2,backing_cpu_buf_count,0,
+ 7,8,140446058794928,Texture for offscreen content,width,512,height,512,format,1,owns_native_resource,1,mip_count,1,layer_count,1,effective_sample_count,1,approx_byte_size,1048576,
+ 1,8,140446058963904,Triangle vbuf,type,0,usage,1,logical_size,84,effective_size,84,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
+ 1,8,140446058964560,Triangle ubuf,type,2,usage,4,logical_size,68,effective_size,256,backing_gpu_buf_count,2,backing_cpu_buf_count,0,
+ 5,9,140446057945392,,type,0,width,1280,height,720,effective_sample_count,1,transient_backing,0,winsys_backing,0,approx_byte_size,3686400,
+ 11,9,140446057944592,,width,1280,height,720,buffer_count,2,msaa_buffer_count,0,effective_sample_count,1,approx_total_byte_size,7372800,
+ 9,9,140446058913648,Qt texture,slot,0,size,262144,
+ 10,9,140446058913648,Qt texture,slot,0,
+ 17,2019,140446057944592,,frames_since_resize,121,min_ms_frame_delta,9,max_ms_frame_delta,33,Favg_ms_frame_delta,16.1167,
+ 18,2019,140446057944592,,frames_since_resize,121,min_ms_frame_build,0,max_ms_frame_build,1,Favg_ms_frame_build,0.00833333,
+ 17,4019,140446057944592,,frames_since_resize,241,min_ms_frame_delta,15,max_ms_frame_delta,17,Favg_ms_frame_delta,16.0583,
+ 18,4019,140446057944592,,frames_since_resize,241,min_ms_frame_build,0,max_ms_frame_build,0,Favg_ms_frame_build,0,
+ 12,5070,140446057944592,,
+ 2,5079,140446057947376,Triangle ubuf,
+ 2,5079,140446057946208,Triangle vbuf,
+ 2,5079,140446057947440,,
+ 2,5079,140446057950544,,
+ 2,5079,140446057950416,,
+ 8,5079,140446058913648,Qt texture,
+ 2,5079,140446057982528,Cube ubuf (textured),
+ 2,5079,140446057984784,Cube vbuf (textured),
+ 2,5079,140446058964560,Triangle ubuf,
+ 2,5079,140446058963904,Triangle vbuf,
+ 8,5079,140446058794928,Texture for offscreen content,
+ 2,5079,140446058947920,Cube ubuf (textured with offscreen),
+ 2,5079,140446058795856,Cube vbuf (textured with offscreen),
+ 6,5079,140446057945392,,
+ \endcode
+
+ Each line starts with \c op, \c timestamp, \c res, \c name where op is a
+ value from StreamOp, timestamp is a recording timestamp in milliseconds
+ (qint64), res is a number (quint64) referring to the QRhiResource the entry
+ refers to, or 0 if not applicable. \c name is the value of
+ QRhiResource::name() and may be empty as well. The \c name will never
+ contain a comma.
+
+ This is followed by any number of \c{key, value} pairs where \c key is an
+ unspecified string and \c value is a number. If \c key starts with \c F, it
+ indicates the value is a float. Otherwise assume that the value is a
+ qint64.
+ */
+
+/*!
+ \enum QRhiProfiler::StreamOp
+ Describes an entry in the profiler's output stream.
+
+ \value NewBuffer A buffer is created
+ \value ReleaseBuffer A buffer is destroyed
+ \value NewBufferStagingArea A staging buffer for buffer upload is created
+ \value ReleaseBufferStagingArea A staging buffer for buffer upload is destroyed
+ \value NewRenderBuffer A renderbuffer is created
+ \value ReleaseRenderBuffer A renderbuffer is destroyed
+ \value NewTexture A texture is created
+ \value ReleaseTexture A texture is destroyed
+ \value NewTextureStagingArea A staging buffer for texture upload is created
+ \value ReleaseTextureStagingArea A staging buffer for texture upload is destroyed
+ \value ResizeSwapChain A swapchain is created or resized
+ \value ReleaseSwapChain A swapchain is destroyed
+ \value NewReadbackBuffer A staging buffer for readback is created
+ \value ReleaseReadbackBuffer A staging buffer for readback is destroyed
+ \value GpuMemAllocStats GPU memory allocator statistics
+ \value GpuFrameTime GPU frame times
+ \value FrameToFrameTime CPU frame-to-frame times
+ \value FrameBuildTime CPU beginFrame-endFrame times
+ */
+
+/*!
+ \class QRhiProfiler::CpuTime
+ \inmodule QtRhi
+ \brief Contains CPU-side frame timings.
+
+ Once sufficient number of frames have been rendered, the minimum, maximum,
+ and average values (in milliseconds) from various measurements are made
+ available in this struct queriable from QRhiProfiler::frameToFrameTimes()
+ and QRhiProfiler::frameBuildTimes().
+
+ \sa QRhiProfiler::setFrameTimingWriteInterval()
+ */
+
+/*!
+ \class QRhiProfiler::GpuTime
+ \inmodule QtRhi
+ \brief Contains GPU-side frame timings.
+
+ Once sufficient number of frames have been rendered, the minimum, maximum,
+ and average values (in milliseconds) calculated from GPU command buffer
+ timestamps are made available in this struct queriable from
+ QRhiProfiler::gpuFrameTimes().
+
+ \sa QRhiProfiler::setFrameTimingWriteInterval()
+ */
+
+/*!
+ \internal
+ */
+QRhiProfiler::QRhiProfiler()
+ : d(new QRhiProfilerPrivate)
+{
+ d->ts.start();
+}
+
+/*!
+ Destructor.
+ */
+QRhiProfiler::~QRhiProfiler()
+{
+ // Flush because there is a high chance we have writes that were made since
+ // the event loop last ran. (esp. relevant for network devices like QTcpSocket)
+ if (d->outputDevice)
+ d->outputDevice->waitForBytesWritten(1000);
+
+ delete d;
+}
+
+/*!
+ Sets the output \a device.
+
+ \note No output will be generated when QRhi::EnableProfiling was not set.
+ */
+void QRhiProfiler::setDevice(QIODevice *device)
+{
+ d->outputDevice = device;
+}
+
+/*!
+ Requests writing a GpuMemAllocStats entry into the output, when applicable.
+ Backends that do not support this will ignore the request. This is an
+ explicit request since getting the allocator status and statistics may be
+ an expensive operation.
+ */
+void QRhiProfiler::addVMemAllocatorStats()
+{
+ if (d->rhiDWhenEnabled)
+ d->rhiDWhenEnabled->sendVMemStatsToProfiler();
+}
+
+/*!
+ \return the currently set frame timing writeout interval.
+ */
+int QRhiProfiler::frameTimingWriteInterval() const
+{
+ return d->frameTimingWriteInterval;
+}
+
+/*!
+ Sets the number of frames that need to be rendered before the collected CPU
+ and GPU timings are processed (min, max, average are calculated) to \a
+ frameCount.
+
+ The default value is 120.
+ */
+void QRhiProfiler::setFrameTimingWriteInterval(int frameCount)
+{
+ if (frameCount > 0)
+ d->frameTimingWriteInterval = frameCount;
+}
+
+/*!
+ \return min, max, and avg in milliseconds for the time that elapsed between two
+ QRhi::endFrame() calls.
+
+ \note The values are all 0 until at least frameTimingWriteInterval() frames
+ have been rendered.
+ */
+QRhiProfiler::CpuTime QRhiProfiler::frameToFrameTimes(QRhiSwapChain *sc) const
+{
+ auto it = d->swapchains.constFind(sc);
+ if (it != d->swapchains.constEnd())
+ return it->frameToFrameTime;
+
+ return QRhiProfiler::CpuTime();
+}
+
+/*!
+ \return min, max, and avg in milliseconds for the time that elapsed between
+ a QRhi::beginFrame() and QRhi::endFrame().
+
+ \note The values are all 0 until at least frameTimingWriteInterval() frames
+ have been rendered.
+ */
+QRhiProfiler::CpuTime QRhiProfiler::frameBuildTimes(QRhiSwapChain *sc) const
+{
+ auto it = d->swapchains.constFind(sc);
+ if (it != d->swapchains.constEnd())
+ return it->beginToEndFrameTime;
+
+ return QRhiProfiler::CpuTime();
+}
+
+/*!
+ \return min, max, and avg in milliseconds for the GPU time that is spent on
+ one frame.
+
+ \note The values are all 0 until at least frameTimingWriteInterval() frames
+ have been rendered.
+
+ The GPU times should only be compared between runs on the same GPU of the
+ same system with the same backend. Comparing times for different graphics
+ cards or for different backends can give misleading results. The numbers are
+ not meant to be comparable that way.
+
+ \note Some backends have no support for this, and even for those that have,
+ it is not guaranteed that the driver will support it at run time. Support
+ can be checked via QRhi::Timestamps.
+ */
+QRhiProfiler::GpuTime QRhiProfiler::gpuFrameTimes(QRhiSwapChain *sc) const
+{
+ auto it = d->swapchains.constFind(sc);
+ if (it != d->swapchains.constEnd())
+ return it->gpuFrameTime;
+
+ return QRhiProfiler::GpuTime();
+}
+
+void QRhiProfilerPrivate::startEntry(QRhiProfiler::StreamOp op, qint64 timestamp, QRhiResource *res)
+{
+ buf.clear();
+ buf.append(QByteArray::number(op));
+ buf.append(',');
+ buf.append(QByteArray::number(timestamp));
+ buf.append(',');
+ buf.append(QByteArray::number(quint64(quintptr(res))));
+ buf.append(',');
+ if (res)
+ buf.append(res->name());
+ buf.append(',');
+}
+
+void QRhiProfilerPrivate::writeInt(const char *key, qint64 v)
+{
+ Q_ASSERT(key[0] != 'F');
+ buf.append(key);
+ buf.append(',');
+ buf.append(QByteArray::number(v));
+ buf.append(',');
+}
+
+void QRhiProfilerPrivate::writeFloat(const char *key, float f)
+{
+ Q_ASSERT(key[0] == 'F');
+ buf.append(key);
+ buf.append(',');
+ buf.append(QByteArray::number(f));
+ buf.append(',');
+}
+
+void QRhiProfilerPrivate::endEntry()
+{
+ buf.append('\n');
+ outputDevice->write(buf);
+}
+
+void QRhiProfilerPrivate::newBuffer(QRhiBuffer *buf, quint32 realSize, int backingGpuBufCount, int backingCpuBufCount)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::NewBuffer, ts.elapsed(), buf);
+ writeInt("type", buf->type());
+ writeInt("usage", buf->usage());
+ writeInt("logical_size", buf->size());
+ writeInt("effective_size", realSize);
+ writeInt("backing_gpu_buf_count", backingGpuBufCount);
+ writeInt("backing_cpu_buf_count", backingCpuBufCount);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::releaseBuffer(QRhiBuffer *buf)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::ReleaseBuffer, ts.elapsed(), buf);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::newBufferStagingArea(QRhiBuffer *buf, int slot, quint32 size)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::NewBufferStagingArea, ts.elapsed(), buf);
+ writeInt("slot", slot);
+ writeInt("size", size);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::releaseBufferStagingArea(QRhiBuffer *buf, int slot)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::ReleaseBufferStagingArea, ts.elapsed(), buf);
+ writeInt("slot", slot);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::newRenderBuffer(QRhiRenderBuffer *rb, bool transientBacking, bool winSysBacking, int sampleCount)
+{
+ if (!outputDevice)
+ return;
+
+ const QRhiRenderBuffer::Type type = rb->type();
+ const QSize sz = rb->pixelSize();
+ // just make up something, ds is likely D24S8 while color is RGBA8 or similar
+ const QRhiTexture::Format assumedFormat = type == QRhiRenderBuffer::DepthStencil ? QRhiTexture::D32F : QRhiTexture::RGBA8;
+ quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(assumedFormat, sz, 1, 1);
+ if (sampleCount > 1)
+ byteSize *= sampleCount;
+
+ startEntry(QRhiProfiler::NewRenderBuffer, ts.elapsed(), rb);
+ writeInt("type", type);
+ writeInt("width", sz.width());
+ writeInt("height", sz.height());
+ writeInt("effective_sample_count", sampleCount);
+ writeInt("transient_backing", transientBacking);
+ writeInt("winsys_backing", winSysBacking);
+ writeInt("approx_byte_size", byteSize);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::releaseRenderBuffer(QRhiRenderBuffer *rb)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::ReleaseRenderBuffer, ts.elapsed(), rb);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::newTexture(QRhiTexture *tex, bool owns, int mipCount, int layerCount, int sampleCount)
+{
+ if (!outputDevice)
+ return;
+
+ const QRhiTexture::Format format = tex->format();
+ const QSize sz = tex->pixelSize();
+ quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(format, sz, mipCount, layerCount);
+ if (sampleCount > 1)
+ byteSize *= sampleCount;
+
+ startEntry(QRhiProfiler::NewTexture, ts.elapsed(), tex);
+ writeInt("width", sz.width());
+ writeInt("height", sz.height());
+ writeInt("format", format);
+ writeInt("owns_native_resource", owns);
+ writeInt("mip_count", mipCount);
+ writeInt("layer_count", layerCount);
+ writeInt("effective_sample_count", sampleCount);
+ writeInt("approx_byte_size", byteSize);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::releaseTexture(QRhiTexture *tex)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::ReleaseTexture, ts.elapsed(), tex);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::newTextureStagingArea(QRhiTexture *tex, int slot, quint32 size)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::NewTextureStagingArea, ts.elapsed(), tex);
+ writeInt("slot", slot);
+ writeInt("size", size);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::releaseTextureStagingArea(QRhiTexture *tex, int slot)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::ReleaseTextureStagingArea, ts.elapsed(), tex);
+ writeInt("slot", slot);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::resizeSwapChain(QRhiSwapChain *sc, int bufferCount, int msaaBufferCount, int sampleCount)
+{
+ if (!outputDevice)
+ return;
+
+ const QSize sz = sc->currentPixelSize();
+ quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(QRhiTexture::BGRA8, sz, 1, 1);
+ byteSize = byteSize * bufferCount + byteSize * msaaBufferCount * sampleCount;
+
+ startEntry(QRhiProfiler::ResizeSwapChain, ts.elapsed(), sc);
+ writeInt("width", sz.width());
+ writeInt("height", sz.height());
+ writeInt("buffer_count", bufferCount);
+ writeInt("msaa_buffer_count", msaaBufferCount);
+ writeInt("effective_sample_count", sampleCount);
+ writeInt("approx_total_byte_size", byteSize);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::releaseSwapChain(QRhiSwapChain *sc)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::ReleaseSwapChain, ts.elapsed(), sc);
+ endEntry();
+}
+
+template<typename T>
+void calcTiming(QVector<T> *vec, T *minDelta, T *maxDelta, float *avgDelta)
+{
+ if (vec->isEmpty())
+ return;
+
+ *minDelta = *maxDelta = 0;
+ float totalDelta = 0;
+ for (T delta : qAsConst(*vec)) {
+ totalDelta += float(delta);
+ if (*minDelta == 0 || delta < *minDelta)
+ *minDelta = delta;
+ if (*maxDelta == 0 || delta > *maxDelta)
+ *maxDelta = delta;
+ }
+ *avgDelta = totalDelta / vec->count();
+
+ vec->clear();
+}
+
+void QRhiProfilerPrivate::beginSwapChainFrame(QRhiSwapChain *sc)
+{
+ Sc &scd(swapchains[sc]);
+ scd.beginToEndTimer.start();
+}
+
+void QRhiProfilerPrivate::endSwapChainFrame(QRhiSwapChain *sc, int frameCount)
+{
+ Sc &scd(swapchains[sc]);
+ if (!scd.frameToFrameRunning) {
+ scd.frameToFrameTimer.start();
+ scd.frameToFrameRunning = true;
+ return;
+ }
+
+ scd.frameToFrameSamples.append(scd.frameToFrameTimer.restart());
+ if (scd.frameToFrameSamples.count() >= frameTimingWriteInterval) {
+ calcTiming(&scd.frameToFrameSamples,
+ &scd.frameToFrameTime.minTime, &scd.frameToFrameTime.maxTime, &scd.frameToFrameTime.avgTime);
+ if (outputDevice) {
+ startEntry(QRhiProfiler::FrameToFrameTime, ts.elapsed(), sc);
+ writeInt("frames_since_resize", frameCount);
+ writeInt("min_ms_frame_delta", scd.frameToFrameTime.minTime);
+ writeInt("max_ms_frame_delta", scd.frameToFrameTime.maxTime);
+ writeFloat("Favg_ms_frame_delta", scd.frameToFrameTime.avgTime);
+ endEntry();
+ }
+ }
+
+ scd.beginToEndSamples.append(scd.beginToEndTimer.elapsed());
+ if (scd.beginToEndSamples.count() >= frameTimingWriteInterval) {
+ calcTiming(&scd.beginToEndSamples,
+ &scd.beginToEndFrameTime.minTime, &scd.beginToEndFrameTime.maxTime, &scd.beginToEndFrameTime.avgTime);
+ if (outputDevice) {
+ startEntry(QRhiProfiler::FrameBuildTime, ts.elapsed(), sc);
+ writeInt("frames_since_resize", frameCount);
+ writeInt("min_ms_frame_build", scd.beginToEndFrameTime.minTime);
+ writeInt("max_ms_frame_build", scd.beginToEndFrameTime.maxTime);
+ writeFloat("Favg_ms_frame_build", scd.beginToEndFrameTime.avgTime);
+ endEntry();
+ }
+ }
+}
+
+void QRhiProfilerPrivate::swapChainFrameGpuTime(QRhiSwapChain *sc, float gpuTime)
+{
+ Sc &scd(swapchains[sc]);
+ scd.gpuFrameSamples.append(gpuTime);
+ if (scd.gpuFrameSamples.count() >= frameTimingWriteInterval) {
+ calcTiming(&scd.gpuFrameSamples,
+ &scd.gpuFrameTime.minTime, &scd.gpuFrameTime.maxTime, &scd.gpuFrameTime.avgTime);
+ if (outputDevice) {
+ startEntry(QRhiProfiler::GpuFrameTime, ts.elapsed(), sc);
+ writeFloat("Fmin_ms_gpu_frame_time", scd.gpuFrameTime.minTime);
+ writeFloat("Fmax_ms_gpu_frame_time", scd.gpuFrameTime.maxTime);
+ writeFloat("Favg_ms_gpu_frame_time", scd.gpuFrameTime.avgTime);
+ endEntry();
+ }
+ }
+}
+
+void QRhiProfilerPrivate::newReadbackBuffer(quint64 id, QRhiResource *src, quint32 size)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::NewReadbackBuffer, ts.elapsed(), src);
+ writeInt("id", id);
+ writeInt("size", size);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::releaseReadbackBuffer(quint64 id)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::ReleaseReadbackBuffer, ts.elapsed(), nullptr);
+ writeInt("id", id);
+ endEntry();
+}
+
+void QRhiProfilerPrivate::vmemStat(int realAllocCount, int subAllocCount, quint32 totalSize, quint32 unusedSize)
+{
+ if (!outputDevice)
+ return;
+
+ startEntry(QRhiProfiler::GpuMemAllocStats, ts.elapsed(), nullptr);
+ writeInt("real_alloc_count", realAllocCount);
+ writeInt("sub_alloc_count", subAllocCount);
+ writeInt("total_size", totalSize);
+ writeInt("unused_size", unusedSize);
+ endEntry();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhiprofiler_p.h b/src/gui/rhi/qrhiprofiler_p.h
new file mode 100644
index 0000000000..89fd0a8798
--- /dev/null
+++ b/src/gui/rhi/qrhiprofiler_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHIPROFILER_H
+#define QRHIPROFILER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qrhi_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRhiProfilerPrivate;
+class QIODevice;
+
+class Q_GUI_EXPORT QRhiProfiler
+{
+public:
+ enum StreamOp {
+ NewBuffer = 1,
+ ReleaseBuffer,
+ NewBufferStagingArea,
+ ReleaseBufferStagingArea,
+ NewRenderBuffer,
+ ReleaseRenderBuffer,
+ NewTexture,
+ ReleaseTexture,
+ NewTextureStagingArea,
+ ReleaseTextureStagingArea,
+ ResizeSwapChain,
+ ReleaseSwapChain,
+ NewReadbackBuffer,
+ ReleaseReadbackBuffer,
+ GpuMemAllocStats,
+ GpuFrameTime,
+ FrameToFrameTime,
+ FrameBuildTime
+ };
+
+ ~QRhiProfiler();
+
+ void setDevice(QIODevice *device);
+
+ void addVMemAllocatorStats();
+
+ int frameTimingWriteInterval() const;
+ void setFrameTimingWriteInterval(int frameCount);
+
+ struct CpuTime {
+ qint64 minTime = 0;
+ qint64 maxTime = 0;
+ float avgTime = 0;
+ };
+
+ struct GpuTime {
+ float minTime = 0;
+ float maxTime = 0;
+ float avgTime = 0;
+ };
+
+ CpuTime frameToFrameTimes(QRhiSwapChain *sc) const;
+ CpuTime frameBuildTimes(QRhiSwapChain *sc) const; // beginFrame - endFrame
+ GpuTime gpuFrameTimes(QRhiSwapChain *sc) const;
+
+private:
+ Q_DISABLE_COPY(QRhiProfiler)
+ QRhiProfiler();
+ QRhiProfilerPrivate *d;
+ friend class QRhiImplementation;
+ friend class QRhiProfilerPrivate;
+};
+
+Q_DECLARE_TYPEINFO(QRhiProfiler::CpuTime, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiProfiler::GpuTime, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhiprofiler_p_p.h b/src/gui/rhi/qrhiprofiler_p_p.h
new file mode 100644
index 0000000000..49c6bd78ed
--- /dev/null
+++ b/src/gui/rhi/qrhiprofiler_p_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHIPROFILER_P_H
+#define QRHIPROFILER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrhiprofiler_p.h"
+#include <QElapsedTimer>
+#include <QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QRhiProfilerPrivate
+{
+public:
+ static QRhiProfilerPrivate *get(QRhiProfiler *p) { return p->d; }
+
+ void newBuffer(QRhiBuffer *buf, quint32 realSize, int backingGpuBufCount, int backingCpuBufCount);
+ void releaseBuffer(QRhiBuffer *buf);
+ void newBufferStagingArea(QRhiBuffer *buf, int slot, quint32 size);
+ void releaseBufferStagingArea(QRhiBuffer *buf, int slot);
+
+ void newRenderBuffer(QRhiRenderBuffer *rb, bool transientBacking, bool winSysBacking, int sampleCount);
+ void releaseRenderBuffer(QRhiRenderBuffer *rb);
+
+ void newTexture(QRhiTexture *tex, bool owns, int mipCount, int layerCount, int sampleCount);
+ void releaseTexture(QRhiTexture *tex);
+ void newTextureStagingArea(QRhiTexture *tex, int slot, quint32 size);
+ void releaseTextureStagingArea(QRhiTexture *tex, int slot);
+
+ void resizeSwapChain(QRhiSwapChain *sc, int bufferCount, int msaaBufferCount, int sampleCount);
+ void releaseSwapChain(QRhiSwapChain *sc);
+
+ void beginSwapChainFrame(QRhiSwapChain *sc);
+ void endSwapChainFrame(QRhiSwapChain *sc, int frameCount);
+ void swapChainFrameGpuTime(QRhiSwapChain *sc, float gpuTimeMs);
+
+ void newReadbackBuffer(quint64 id, QRhiResource *src, quint32 size);
+ void releaseReadbackBuffer(quint64 id);
+
+ void vmemStat(int realAllocCount, int subAllocCount, quint32 totalSize, quint32 unusedSize);
+
+ void startEntry(QRhiProfiler::StreamOp op, qint64 timestamp, QRhiResource *res);
+ void writeInt(const char *key, qint64 v);
+ void writeFloat(const char *key, float f);
+ void endEntry();
+
+ QRhiImplementation *rhiDWhenEnabled = nullptr;
+ QIODevice *outputDevice = nullptr;
+ QElapsedTimer ts;
+ QByteArray buf;
+ static const int DEFAULT_FRAME_TIMING_WRITE_INTERVAL = 120; // frames
+ int frameTimingWriteInterval = DEFAULT_FRAME_TIMING_WRITE_INTERVAL;
+ struct Sc {
+ Sc() {
+ frameToFrameSamples.reserve(DEFAULT_FRAME_TIMING_WRITE_INTERVAL);
+ beginToEndSamples.reserve(DEFAULT_FRAME_TIMING_WRITE_INTERVAL);
+ gpuFrameSamples.reserve(DEFAULT_FRAME_TIMING_WRITE_INTERVAL);
+ }
+ QElapsedTimer frameToFrameTimer;
+ bool frameToFrameRunning = false;
+ QElapsedTimer beginToEndTimer;
+ QVector<qint64> frameToFrameSamples;
+ QVector<qint64> beginToEndSamples;
+ QVector<float> gpuFrameSamples;
+ QRhiProfiler::CpuTime frameToFrameTime;
+ QRhiProfiler::CpuTime beginToEndFrameTime;
+ QRhiProfiler::GpuTime gpuFrameTime;
+ };
+ QHash<QRhiSwapChain *, Sc> swapchains;
+};
+
+Q_DECLARE_TYPEINFO(QRhiProfilerPrivate::Sc, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
new file mode 100644
index 0000000000..1f80df6d0d
--- /dev/null
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -0,0 +1,5681 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrhivulkan_p_p.h"
+#include "qrhivulkanext_p.h"
+
+#define VMA_IMPLEMENTATION
+#define VMA_STATIC_VULKAN_FUNCTIONS 0
+#define VMA_RECORDING_ENABLED 0
+#define VMA_DEDICATED_ALLOCATION 0
+#ifdef QT_DEBUG
+#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1
+#endif
+#include "vk_mem_alloc.h"
+
+#include <qmath.h>
+#include <QVulkanFunctions>
+#include <QVulkanWindow>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Vulkan 1.0 backend. Provides a double-buffered swapchain that throttles the
+ rendering thread to vsync. Textures and "static" buffers are device local,
+ and a separate, host visible staging buffer is used to upload data to them.
+ "Dynamic" buffers are in host visible memory and are duplicated (since there
+ can be 2 frames in flight). This is handled transparently to the application.
+*/
+
+/*!
+ \class QRhiVulkanInitParams
+ \inmodule QtRhi
+ \brief Vulkan specific initialization parameters.
+
+ A Vulkan-based QRhi needs at minimum a valid QVulkanInstance. It is up to
+ the user to ensure this is available and initialized. This is typically
+ done in main() similarly to the following:
+
+ \badcode
+ int main(int argc, char **argv)
+ {
+ ...
+
+ 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
+ inst.setExtensions(QByteArrayList()
+ << "VK_KHR_get_physical_device_properties2");
+ if (!inst.create())
+ qFatal("Vulkan not available");
+
+ ...
+ }
+ \endcode
+
+ The example here has two optional aspects: it enables the
+ \l{https://github.com/KhronosGroup/Vulkan-ValidationLayers}{Vulkan
+ validation layers}, when they are available, and also enables the
+ VK_KHR_get_physical_device_properties2 extension (part of Vulkan 1.1), when
+ available. The former is useful during the development phase (remember that
+ QVulkanInstance conveniently redirects messages and warnings to qDebug).
+ Avoid enabling it in production builds, however. The latter is important in
+ order to make QRhi::CustomInstanceStepRate available with Vulkan since
+ VK_EXT_vertex_attribute_divisor (part of Vulkan 1.1) depends on it. It can
+ be omitted when instanced drawing with a non-one step rate is not used.
+
+ Once this is done, a Vulkan-based QRhi can be created by passing the
+ instance and a QWindow with its surface type set to
+ QSurface::VulkanSurface:
+
+ \badcode
+ QRhiVulkanInitParams params;
+ params.inst = vulkanInstance;
+ params.window = window;
+ rhi = QRhi::create(QRhi::Vulkan, &params);
+ \endcode
+
+ The window is optional and can be omitted. This is not recommended however
+ because there is then no way to ensure presenting is supported while
+ choosing a graphics queue.
+
+ \note Even when a window is specified, QRhiSwapChain objects can be created
+ for other windows as well, as long as they all have their
+ QWindow::surfaceType() set to QSurface::VulkanSurface.
+
+ \section2 Working with existing Vulkan devices
+
+ When interoperating with another graphics engine, it may be necessary to
+ get a QRhi instance that uses the same Vulkan device. This can be achieved
+ by passing a pointer to a QRhiVulkanNativeHandles to QRhi::create().
+
+ The physical device and device object must then be set to a non-null value.
+ In addition, either the graphics queue family index or the graphics queue
+ object itself is required. Prefer the former, whenever possible since
+ deducing the index is not possible afterwards. Optionally, an existing
+ command pool object can be specified as well, and, also optionally,
+ vmemAllocator can be used to share the same
+ \l{https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator}{Vulkan
+ memory allocator} between two QRhi instances.
+
+ The QRhi does not take ownership of any of the external objects.
+ */
+
+/*!
+ \class QRhiVulkanNativeHandles
+ \inmodule QtRhi
+ \brief Collects device, queue, and other Vulkan objects that are used by the QRhi.
+
+ \note Ownership of the Vulkan objects is never transferred.
+ */
+
+/*!
+ \class QRhiVulkanTextureNativeHandles
+ \inmodule QtRhi
+ \brief Holds the Vulkan image object that is backing a QRhiTexture.
+
+ Importing and exporting Vulkan image objects that back a QRhiTexture when
+ running with the Vulkan backend is supported via this class. Ownership of
+ the Vulkan object is never transferred.
+
+ \note Memory allocation details are not exposed. This is intentional since
+ memory is typically suballocated from a bigger chunk of VkDeviceMemory, and
+ exposing the allocator details is not desirable for now.
+ */
+
+/*!
+ \class QRhiVulkanCommandBufferNativeHandles
+ \inmodule QtRhi
+ \brief Holds the Vulkan command buffer object that is backing a QRhiCommandBuffer.
+
+ \note The Vulkan command buffer object is only guaranteed to be valid, and
+ in recording state, while recording a frame. That is, between a
+ \l{QRhi::beginFrame()}{beginFrame()} - \l{QRhi::endFrame()}{endFrame()} or
+ \l{QRhi::beginOffscreenFrame()}{beginOffscreenFrame()} -
+ \l{QRhi::endOffsrceenFrame()}{endOffscreenFrame()} pair.
+ */
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+static QVulkanInstance *globalVulkanInstance;
+
+static void VKAPI_PTR wrap_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties)
+{
+ globalVulkanInstance->functions()->vkGetPhysicalDeviceProperties(physicalDevice, pProperties);
+}
+
+static void VKAPI_PTR wrap_vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties)
+{
+ globalVulkanInstance->functions()->vkGetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
+}
+
+static VkResult VKAPI_PTR wrap_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory)
+{
+ return globalVulkanInstance->deviceFunctions(device)->vkAllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
+}
+
+void VKAPI_PTR wrap_vkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator)
+{
+ globalVulkanInstance->deviceFunctions(device)->vkFreeMemory(device, memory, pAllocator);
+}
+
+VkResult VKAPI_PTR wrap_vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData)
+{
+ return globalVulkanInstance->deviceFunctions(device)->vkMapMemory(device, memory, offset, size, flags, ppData);
+}
+
+void VKAPI_PTR wrap_vkUnmapMemory(VkDevice device, VkDeviceMemory memory)
+{
+ globalVulkanInstance->deviceFunctions(device)->vkUnmapMemory(device, memory);
+}
+
+VkResult VKAPI_PTR wrap_vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges)
+{
+ return globalVulkanInstance->deviceFunctions(device)->vkFlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+}
+
+VkResult VKAPI_PTR wrap_vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges)
+{
+ return globalVulkanInstance->deviceFunctions(device)->vkInvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+}
+
+VkResult VKAPI_PTR wrap_vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset)
+{
+ return globalVulkanInstance->deviceFunctions(device)->vkBindBufferMemory(device, buffer, memory, memoryOffset);
+}
+
+VkResult VKAPI_PTR wrap_vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset)
+{
+ return globalVulkanInstance->deviceFunctions(device)->vkBindImageMemory(device, image, memory, memoryOffset);
+}
+
+void VKAPI_PTR wrap_vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements)
+{
+ globalVulkanInstance->deviceFunctions(device)->vkGetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
+}
+
+void VKAPI_PTR wrap_vkGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements)
+{
+ globalVulkanInstance->deviceFunctions(device)->vkGetImageMemoryRequirements(device, image, pMemoryRequirements);
+}
+
+VkResult VKAPI_PTR wrap_vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer)
+{
+ return globalVulkanInstance->deviceFunctions(device)->vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
+}
+
+void VKAPI_PTR wrap_vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator)
+{
+ globalVulkanInstance->deviceFunctions(device)->vkDestroyBuffer(device, buffer, pAllocator);
+}
+
+VkResult VKAPI_PTR wrap_vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage)
+{
+ return globalVulkanInstance->deviceFunctions(device)->vkCreateImage(device, pCreateInfo, pAllocator, pImage);
+}
+
+void VKAPI_PTR wrap_vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator)
+{
+ globalVulkanInstance->deviceFunctions(device)->vkDestroyImage(device, image, pAllocator);
+}
+
+static inline VmaAllocation toVmaAllocation(QVkAlloc a)
+{
+ return reinterpret_cast<VmaAllocation>(a);
+}
+
+static inline VmaAllocator toVmaAllocator(QVkAllocator a)
+{
+ return reinterpret_cast<VmaAllocator>(a);
+}
+
+QRhiVulkan::QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *importDevice)
+ : ofr(this)
+{
+ inst = params->inst;
+ maybeWindow = params->window; // may be null
+
+ importedDevice = importDevice != nullptr;
+ if (importedDevice) {
+ physDev = importDevice->physDev;
+ dev = importDevice->dev;
+ if (physDev && dev) {
+ gfxQueueFamilyIdx = importDevice->gfxQueueFamilyIdx;
+ gfxQueue = importDevice->gfxQueue;
+ if (importDevice->cmdPool) {
+ importedCmdPool = true;
+ cmdPool = importDevice->cmdPool;
+ }
+ if (importDevice->vmemAllocator) {
+ importedAllocator = true;
+ allocator = importDevice->vmemAllocator;
+ }
+ } else {
+ qWarning("No (physical) Vulkan device is given, cannot import");
+ importedDevice = false;
+ }
+ }
+}
+
+static bool qvk_debug_filter(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object,
+ size_t location, int32_t messageCode, const char *pLayerPrefix, const char *pMessage)
+{
+ Q_UNUSED(flags);
+ Q_UNUSED(objectType);
+ Q_UNUSED(object);
+ Q_UNUSED(location);
+ Q_UNUSED(messageCode);
+ Q_UNUSED(pLayerPrefix);
+
+ // Filter out certain misleading validation layer messages, as per
+ // VulkanMemoryAllocator documentation.
+ if (strstr(pMessage, "Mapping an image with layout")
+ && strstr(pMessage, "can result in undefined behavior if this memory is used by the device"))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool QRhiVulkan::create(QRhi::Flags flags)
+{
+ Q_UNUSED(flags);
+ Q_ASSERT(inst);
+
+ globalVulkanInstance = inst; // assume this will not change during the lifetime of the entire application
+
+ f = inst->functions();
+
+ QVector<VkQueueFamilyProperties> queueFamilyProps;
+ auto queryQueueFamilyProps = [this, &queueFamilyProps] {
+ uint32_t queueCount = 0;
+ f->vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
+ queueFamilyProps.resize(queueCount);
+ f->vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueFamilyProps.data());
+ };
+
+ if (!importedDevice) {
+ uint32_t physDevCount = 0;
+ f->vkEnumeratePhysicalDevices(inst->vkInstance(), &physDevCount, nullptr);
+ if (!physDevCount) {
+ qWarning("No physical devices");
+ return false;
+ }
+ QVarLengthArray<VkPhysicalDevice, 4> physDevs(physDevCount);
+ VkResult err = f->vkEnumeratePhysicalDevices(inst->vkInstance(), &physDevCount, physDevs.data());
+ if (err != VK_SUCCESS || !physDevCount) {
+ qWarning("Failed to enumerate physical devices: %d", err);
+ return false;
+ }
+ int physDevIndex = -1;
+ int requestedPhysDevIndex = -1;
+ if (qEnvironmentVariableIsSet("QT_VK_PHYSICAL_DEVICE_INDEX"))
+ requestedPhysDevIndex = qEnvironmentVariableIntValue("QT_VK_PHYSICAL_DEVICE_INDEX");
+ for (uint32_t i = 0; i < physDevCount; ++i) {
+ f->vkGetPhysicalDeviceProperties(physDevs[i], &physDevProperties);
+ qDebug("Physical device %d: '%s' %d.%d.%d", i,
+ physDevProperties.deviceName,
+ VK_VERSION_MAJOR(physDevProperties.driverVersion),
+ VK_VERSION_MINOR(physDevProperties.driverVersion),
+ VK_VERSION_PATCH(physDevProperties.driverVersion));
+ if (physDevIndex < 0 && (requestedPhysDevIndex < 0 || requestedPhysDevIndex == int(i))) {
+ physDevIndex = i;
+ qDebug(" using this physical device");
+ }
+ }
+ if (physDevIndex < 0) {
+ qWarning("No matching physical device");
+ return false;
+ }
+ physDev = physDevs[physDevIndex];
+
+ queryQueueFamilyProps();
+
+ gfxQueue = VK_NULL_HANDLE;
+ gfxQueueFamilyIdx = -1;
+ int presQueueFamilyIdx = -1;
+ for (int i = 0; i < queueFamilyProps.count(); ++i) {
+ qDebug("queue family %d: flags=0x%x count=%d", i, queueFamilyProps[i].queueFlags, queueFamilyProps[i].queueCount);
+ if (gfxQueueFamilyIdx == -1
+ && (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
+ && (!maybeWindow || inst->supportsPresent(physDev, i, maybeWindow)))
+ {
+ gfxQueueFamilyIdx = i;
+ }
+ }
+ if (gfxQueueFamilyIdx != -1) {
+ presQueueFamilyIdx = gfxQueueFamilyIdx;
+ } else {
+ // ###
+ qWarning("No graphics queue that can present. This is not supported atm.");
+ }
+ if (gfxQueueFamilyIdx == -1) {
+ qWarning("No graphics queue family found");
+ return false;
+ }
+ if (presQueueFamilyIdx == -1) {
+ qWarning("No present queue family found");
+ return false;
+ }
+
+ VkDeviceQueueCreateInfo queueInfo[2];
+ const float prio[] = { 0 };
+ memset(queueInfo, 0, sizeof(queueInfo));
+ queueInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueInfo[0].queueFamilyIndex = gfxQueueFamilyIdx;
+ queueInfo[0].queueCount = 1;
+ queueInfo[0].pQueuePriorities = prio;
+ if (gfxQueueFamilyIdx != presQueueFamilyIdx) {
+ queueInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueInfo[1].queueFamilyIndex = presQueueFamilyIdx;
+ queueInfo[1].queueCount = 1;
+ queueInfo[1].pQueuePriorities = prio;
+ }
+
+ QVector<const char *> devLayers;
+ if (inst->layers().contains("VK_LAYER_LUNARG_standard_validation"))
+ devLayers.append("VK_LAYER_LUNARG_standard_validation");
+
+ uint32_t devExtCount = 0;
+ f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, nullptr);
+ QVector<VkExtensionProperties> devExts(devExtCount);
+ f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, devExts.data());
+ qDebug("%d device extensions available", devExts.count());
+
+ QVector<const char *> requestedDevExts;
+ requestedDevExts.append("VK_KHR_swapchain");
+
+ debugMarkersAvailable = false;
+ vertexAttribDivisorAvailable = false;
+ for (const VkExtensionProperties &ext : devExts) {
+ if (!strcmp(ext.extensionName, VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
+ requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
+ debugMarkersAvailable = true;
+ } else if (!strcmp(ext.extensionName, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
+ if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
+ requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
+ vertexAttribDivisorAvailable = true;
+ }
+ }
+ }
+
+ VkDeviceCreateInfo devInfo;
+ memset(&devInfo, 0, sizeof(devInfo));
+ devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ devInfo.queueCreateInfoCount = gfxQueueFamilyIdx == presQueueFamilyIdx ? 1 : 2;
+ devInfo.pQueueCreateInfos = queueInfo;
+ devInfo.enabledLayerCount = devLayers.count();
+ devInfo.ppEnabledLayerNames = devLayers.constData();
+ devInfo.enabledExtensionCount = requestedDevExts.count();
+ devInfo.ppEnabledExtensionNames = requestedDevExts.constData();
+
+ err = f->vkCreateDevice(physDev, &devInfo, nullptr, &dev);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create device: %d", err);
+ return false;
+ }
+ }
+
+ df = inst->deviceFunctions(dev);
+
+ if (!importedCmdPool) {
+ VkCommandPoolCreateInfo poolInfo;
+ memset(&poolInfo, 0, sizeof(poolInfo));
+ poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ poolInfo.queueFamilyIndex = gfxQueueFamilyIdx;
+ VkResult err = df->vkCreateCommandPool(dev, &poolInfo, nullptr, &cmdPool);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create command pool: %d", err);
+ return false;
+ }
+ }
+
+ if (gfxQueueFamilyIdx != -1) {
+ // Will use one queue always, including when multiple QRhis use the
+ // same device. This has significant consequences, and cannot easily be
+ // changed (e.g. think pipeline barriers which create a dependency
+ // between commands submitted to a queue - with multiple queues
+ // additional synchronization would be needed)
+
+ if (!gfxQueue)
+ df->vkGetDeviceQueue(dev, gfxQueueFamilyIdx, 0, &gfxQueue);
+
+ if (queueFamilyProps.isEmpty())
+ queryQueueFamilyProps();
+
+ timestampValidBits = queueFamilyProps[gfxQueueFamilyIdx].timestampValidBits;
+ }
+
+ f->vkGetPhysicalDeviceProperties(physDev, &physDevProperties);
+ ubufAlign = physDevProperties.limits.minUniformBufferOffsetAlignment;
+ // helps little with an optimal offset of 1 (on some drivers) when the spec
+ // elsewhere states that the minimum bufferOffset is 4...
+ texbufAlign = qMax<VkDeviceSize>(4, physDevProperties.limits.optimalBufferCopyOffsetAlignment);
+
+ if (!importedAllocator) {
+ VmaVulkanFunctions afuncs;
+ afuncs.vkGetPhysicalDeviceProperties = wrap_vkGetPhysicalDeviceProperties;
+ afuncs.vkGetPhysicalDeviceMemoryProperties = wrap_vkGetPhysicalDeviceMemoryProperties;
+ afuncs.vkAllocateMemory = wrap_vkAllocateMemory;
+ afuncs.vkFreeMemory = wrap_vkFreeMemory;
+ afuncs.vkMapMemory = wrap_vkMapMemory;
+ afuncs.vkUnmapMemory = wrap_vkUnmapMemory;
+ afuncs.vkFlushMappedMemoryRanges = wrap_vkFlushMappedMemoryRanges;
+ afuncs.vkInvalidateMappedMemoryRanges = wrap_vkInvalidateMappedMemoryRanges;
+ afuncs.vkBindBufferMemory = wrap_vkBindBufferMemory;
+ afuncs.vkBindImageMemory = wrap_vkBindImageMemory;
+ afuncs.vkGetBufferMemoryRequirements = wrap_vkGetBufferMemoryRequirements;
+ afuncs.vkGetImageMemoryRequirements = wrap_vkGetImageMemoryRequirements;
+ afuncs.vkCreateBuffer = wrap_vkCreateBuffer;
+ afuncs.vkDestroyBuffer = wrap_vkDestroyBuffer;
+ afuncs.vkCreateImage = wrap_vkCreateImage;
+ afuncs.vkDestroyImage = wrap_vkDestroyImage;
+
+ VmaAllocatorCreateInfo allocatorInfo;
+ memset(&allocatorInfo, 0, sizeof(allocatorInfo));
+ allocatorInfo.physicalDevice = physDev;
+ allocatorInfo.device = dev;
+ allocatorInfo.pVulkanFunctions = &afuncs;
+ VmaAllocator vmaallocator;
+ VkResult err = vmaCreateAllocator(&allocatorInfo, &vmaallocator);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create allocator: %d", err);
+ return false;
+ }
+ allocator = vmaallocator;
+ }
+
+ inst->installDebugOutputFilter(qvk_debug_filter);
+
+ VkDescriptorPool pool;
+ VkResult err = createDescriptorPool(&pool);
+ if (err == VK_SUCCESS)
+ descriptorPools.append(pool);
+ else
+ qWarning("Failed to create initial descriptor pool: %d", err);
+
+ VkQueryPoolCreateInfo timestampQueryPoolInfo;
+ memset(&timestampQueryPoolInfo, 0, sizeof(timestampQueryPoolInfo));
+ timestampQueryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
+ timestampQueryPoolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;
+ timestampQueryPoolInfo.queryCount = QVK_MAX_ACTIVE_TIMESTAMP_PAIRS * 2;
+ err = df->vkCreateQueryPool(dev, &timestampQueryPoolInfo, nullptr, &timestampQueryPool);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create timestamp query pool: %d", err);
+ return false;
+ }
+ timestampQueryPoolMap.resize(QVK_MAX_ACTIVE_TIMESTAMP_PAIRS); // 1 bit per pair
+ timestampQueryPoolMap.fill(false);
+
+ if (debugMarkersAvailable) {
+ vkCmdDebugMarkerBegin = reinterpret_cast<PFN_vkCmdDebugMarkerBeginEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerBeginEXT"));
+ vkCmdDebugMarkerEnd = reinterpret_cast<PFN_vkCmdDebugMarkerEndEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerEndEXT"));
+ vkCmdDebugMarkerInsert = reinterpret_cast<PFN_vkCmdDebugMarkerInsertEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerInsertEXT"));
+ vkDebugMarkerSetObjectName = reinterpret_cast<PFN_vkDebugMarkerSetObjectNameEXT>(f->vkGetDeviceProcAddr(dev, "vkDebugMarkerSetObjectNameEXT"));
+ }
+
+ nativeHandlesStruct.physDev = physDev;
+ nativeHandlesStruct.dev = dev;
+ nativeHandlesStruct.gfxQueueFamilyIdx = gfxQueueFamilyIdx;
+ nativeHandlesStruct.gfxQueue = gfxQueue;
+ nativeHandlesStruct.cmdPool = cmdPool;
+ nativeHandlesStruct.vmemAllocator = allocator;
+
+ return true;
+}
+
+void QRhiVulkan::destroy()
+{
+ if (!df)
+ return;
+
+ df->vkDeviceWaitIdle(dev);
+
+ executeDeferredReleases(true);
+ finishActiveReadbacks(true);
+
+ if (ofr.cmdFence) {
+ df->vkDestroyFence(dev, ofr.cmdFence, nullptr);
+ ofr.cmdFence = VK_NULL_HANDLE;
+ }
+
+ if (ofr.cbWrapper.cb) {
+ df->vkFreeCommandBuffers(dev, cmdPool, 1, &ofr.cbWrapper.cb);
+ ofr.cbWrapper.cb = VK_NULL_HANDLE;
+ }
+
+ if (pipelineCache) {
+ df->vkDestroyPipelineCache(dev, pipelineCache, nullptr);
+ pipelineCache = VK_NULL_HANDLE;
+ }
+
+ for (const DescriptorPoolData &pool : descriptorPools)
+ df->vkDestroyDescriptorPool(dev, pool.pool, nullptr);
+
+ descriptorPools.clear();
+
+ if (timestampQueryPool) {
+ df->vkDestroyQueryPool(dev, timestampQueryPool, nullptr);
+ timestampQueryPool = VK_NULL_HANDLE;
+ }
+
+ if (!importedAllocator && allocator) {
+ vmaDestroyAllocator(toVmaAllocator(allocator));
+ allocator = nullptr;
+ }
+
+ if (!importedCmdPool && cmdPool) {
+ df->vkDestroyCommandPool(dev, cmdPool, nullptr);
+ cmdPool = VK_NULL_HANDLE;
+ }
+
+ if (!importedDevice && dev) {
+ df->vkDestroyDevice(dev, nullptr);
+ inst->resetDeviceFunctions(dev);
+ dev = VK_NULL_HANDLE;
+ }
+
+ f = nullptr;
+ df = nullptr;
+}
+
+VkResult QRhiVulkan::createDescriptorPool(VkDescriptorPool *pool)
+{
+ VkDescriptorPoolSize descPoolSizes[] = {
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, QVK_UNIFORM_BUFFERS_PER_POOL },
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, QVK_UNIFORM_BUFFERS_PER_POOL },
+ { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, QVK_COMBINED_IMAGE_SAMPLERS_PER_POOL }
+ };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ // Do not enable vkFreeDescriptorSets - sets are never freed on their own
+ // (good so no trouble with fragmentation), they just deref their pool
+ // which is then reset at some point (or not).
+ descPoolInfo.flags = 0;
+ descPoolInfo.maxSets = QVK_DESC_SETS_PER_POOL;
+ descPoolInfo.poolSizeCount = sizeof(descPoolSizes) / sizeof(descPoolSizes[0]);
+ descPoolInfo.pPoolSizes = descPoolSizes;
+ return df->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, pool);
+}
+
+bool QRhiVulkan::allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, VkDescriptorSet *result, int *resultPoolIndex)
+{
+ auto tryAllocate = [this, allocInfo, result](int poolIndex) {
+ allocInfo->descriptorPool = descriptorPools[poolIndex].pool;
+ VkResult r = df->vkAllocateDescriptorSets(dev, allocInfo, result);
+ if (r == VK_SUCCESS)
+ descriptorPools[poolIndex].refCount += 1;
+ return r;
+ };
+
+ int lastPoolIdx = descriptorPools.count() - 1;
+ for (int i = lastPoolIdx; i >= 0; --i) {
+ if (descriptorPools[i].refCount == 0) {
+ df->vkResetDescriptorPool(dev, descriptorPools[i].pool, 0);
+ descriptorPools[i].allocedDescSets = 0;
+ }
+ if (descriptorPools[i].allocedDescSets + allocInfo->descriptorSetCount <= QVK_DESC_SETS_PER_POOL) {
+ VkResult err = tryAllocate(i);
+ if (err == VK_SUCCESS) {
+ descriptorPools[i].allocedDescSets += allocInfo->descriptorSetCount;
+ *resultPoolIndex = i;
+ return true;
+ }
+ }
+ }
+
+ VkDescriptorPool newPool;
+ VkResult poolErr = createDescriptorPool(&newPool);
+ if (poolErr == VK_SUCCESS) {
+ descriptorPools.append(newPool);
+ lastPoolIdx = descriptorPools.count() - 1;
+ VkResult err = tryAllocate(lastPoolIdx);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to allocate descriptor set from new pool too, giving up: %d", err);
+ return false;
+ }
+ descriptorPools[lastPoolIdx].allocedDescSets += allocInfo->descriptorSetCount;
+ *resultPoolIndex = lastPoolIdx;
+ return true;
+ } else {
+ qWarning("Failed to allocate new descriptor pool: %d", poolErr);
+ return false;
+ }
+}
+
+static inline VkFormat toVkTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
+{
+ const bool srgb = flags.testFlag(QRhiTexture::sRGB);
+ switch (format) {
+ case QRhiTexture::RGBA8:
+ return srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
+ case QRhiTexture::BGRA8:
+ return srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
+ case QRhiTexture::R8:
+ return srgb ? VK_FORMAT_R8_SRGB : VK_FORMAT_R8_UNORM;
+ case QRhiTexture::R16:
+ return VK_FORMAT_R16_UNORM;
+ case QRhiTexture::RED_OR_ALPHA8:
+ return VK_FORMAT_R8_UNORM;
+
+ case QRhiTexture::RGBA16F:
+ return VK_FORMAT_R16G16B16A16_SFLOAT;
+ case QRhiTexture::RGBA32F:
+ return VK_FORMAT_R32G32B32A32_SFLOAT;
+
+ case QRhiTexture::D16:
+ return VK_FORMAT_D16_UNORM;
+ case QRhiTexture::D32F:
+ return VK_FORMAT_D32_SFLOAT;
+
+ case QRhiTexture::BC1:
+ return srgb ? VK_FORMAT_BC1_RGB_SRGB_BLOCK : VK_FORMAT_BC1_RGB_UNORM_BLOCK;
+ case QRhiTexture::BC2:
+ return srgb ? VK_FORMAT_BC2_SRGB_BLOCK : VK_FORMAT_BC2_UNORM_BLOCK;
+ case QRhiTexture::BC3:
+ return srgb ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK;
+ case QRhiTexture::BC4:
+ return VK_FORMAT_BC4_UNORM_BLOCK;
+ case QRhiTexture::BC5:
+ return VK_FORMAT_BC5_UNORM_BLOCK;
+ case QRhiTexture::BC6H:
+ return VK_FORMAT_BC6H_UFLOAT_BLOCK;
+ case QRhiTexture::BC7:
+ return srgb ? VK_FORMAT_BC7_SRGB_BLOCK : VK_FORMAT_BC7_UNORM_BLOCK;
+
+ case QRhiTexture::ETC2_RGB8:
+ return srgb ? VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
+ case QRhiTexture::ETC2_RGB8A1:
+ return srgb ? VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
+ case QRhiTexture::ETC2_RGBA8:
+ return srgb ? VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
+
+ case QRhiTexture::ASTC_4x4:
+ return srgb ? VK_FORMAT_ASTC_4x4_SRGB_BLOCK : VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
+ case QRhiTexture::ASTC_5x4:
+ return srgb ? VK_FORMAT_ASTC_5x4_SRGB_BLOCK : VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
+ case QRhiTexture::ASTC_5x5:
+ return srgb ? VK_FORMAT_ASTC_5x5_SRGB_BLOCK : VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
+ case QRhiTexture::ASTC_6x5:
+ return srgb ? VK_FORMAT_ASTC_6x5_SRGB_BLOCK : VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
+ case QRhiTexture::ASTC_6x6:
+ return srgb ? VK_FORMAT_ASTC_6x6_SRGB_BLOCK : VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
+ case QRhiTexture::ASTC_8x5:
+ return srgb ? VK_FORMAT_ASTC_8x5_SRGB_BLOCK : VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
+ case QRhiTexture::ASTC_8x6:
+ return srgb ? VK_FORMAT_ASTC_8x6_SRGB_BLOCK : VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
+ case QRhiTexture::ASTC_8x8:
+ return srgb ? VK_FORMAT_ASTC_8x8_SRGB_BLOCK : VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
+ case QRhiTexture::ASTC_10x5:
+ return srgb ? VK_FORMAT_ASTC_10x5_SRGB_BLOCK : VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
+ case QRhiTexture::ASTC_10x6:
+ return srgb ? VK_FORMAT_ASTC_10x6_SRGB_BLOCK : VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
+ case QRhiTexture::ASTC_10x8:
+ return srgb ? VK_FORMAT_ASTC_10x8_SRGB_BLOCK : VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
+ case QRhiTexture::ASTC_10x10:
+ return srgb ? VK_FORMAT_ASTC_10x10_SRGB_BLOCK : VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
+ case QRhiTexture::ASTC_12x10:
+ return srgb ? VK_FORMAT_ASTC_12x10_SRGB_BLOCK : VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
+ case QRhiTexture::ASTC_12x12:
+ return srgb ? VK_FORMAT_ASTC_12x12_SRGB_BLOCK : VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
+
+ default:
+ Q_UNREACHABLE();
+ return VK_FORMAT_R8G8B8A8_UNORM;
+ }
+}
+
+static inline QRhiTexture::Format colorTextureFormatFromVkFormat(VkFormat format, QRhiTexture::Flags *flags)
+{
+ switch (format) {
+ case VK_FORMAT_R8G8B8A8_UNORM:
+ return QRhiTexture::RGBA8;
+ case VK_FORMAT_R8G8B8A8_SRGB:
+ if (flags)
+ (*flags) |= QRhiTexture::sRGB;
+ return QRhiTexture::RGBA8;
+ case VK_FORMAT_B8G8R8A8_UNORM:
+ return QRhiTexture::BGRA8;
+ case VK_FORMAT_B8G8R8A8_SRGB:
+ if (flags)
+ (*flags) |= QRhiTexture::sRGB;
+ return QRhiTexture::BGRA8;
+ case VK_FORMAT_R8_UNORM:
+ return QRhiTexture::R8;
+ case VK_FORMAT_R8_SRGB:
+ if (flags)
+ (*flags) |= QRhiTexture::sRGB;
+ return QRhiTexture::R8;
+ case VK_FORMAT_R16_UNORM:
+ return QRhiTexture::R16;
+ default: // this cannot assert, must warn and return unknown
+ qWarning("VkFormat %d is not a recognized uncompressed color format", format);
+ break;
+ }
+ return QRhiTexture::UnknownFormat;
+}
+
+static inline bool isDepthTextureFormat(QRhiTexture::Format format)
+{
+ switch (format) {
+ case QRhiTexture::Format::D16:
+ Q_FALLTHROUGH();
+ case QRhiTexture::Format::D32F:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+// Transient images ("render buffers") backed by lazily allocated memory are
+// managed manually without going through vk_mem_alloc since it does not offer
+// any support for such images. This should be ok since in practice there
+// should be very few of such images.
+
+uint32_t QRhiVulkan::chooseTransientImageMemType(VkImage img, uint32_t startIndex)
+{
+ VkPhysicalDeviceMemoryProperties physDevMemProps;
+ f->vkGetPhysicalDeviceMemoryProperties(physDev, &physDevMemProps);
+
+ VkMemoryRequirements memReq;
+ df->vkGetImageMemoryRequirements(dev, img, &memReq);
+ uint32_t memTypeIndex = uint32_t(-1);
+
+ if (memReq.memoryTypeBits) {
+ // Find a device local + lazily allocated, or at least device local memtype.
+ const VkMemoryType *memType = physDevMemProps.memoryTypes;
+ bool foundDevLocal = false;
+ for (uint32_t i = startIndex; i < physDevMemProps.memoryTypeCount; ++i) {
+ if (memReq.memoryTypeBits & (1 << i)) {
+ if (memType[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
+ if (!foundDevLocal) {
+ foundDevLocal = true;
+ memTypeIndex = i;
+ }
+ if (memType[i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
+ memTypeIndex = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return memTypeIndex;
+}
+
+bool QRhiVulkan::createTransientImage(VkFormat format,
+ const QSize &pixelSize,
+ VkImageUsageFlags usage,
+ VkImageAspectFlags aspectMask,
+ VkSampleCountFlagBits samples,
+ VkDeviceMemory *mem,
+ VkImage *images,
+ VkImageView *views,
+ int count)
+{
+ VkMemoryRequirements memReq;
+ VkResult err;
+
+ for (int i = 0; i < count; ++i) {
+ VkImageCreateInfo imgInfo;
+ memset(&imgInfo, 0, sizeof(imgInfo));
+ imgInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imgInfo.imageType = VK_IMAGE_TYPE_2D;
+ imgInfo.format = format;
+ imgInfo.extent.width = pixelSize.width();
+ imgInfo.extent.height = pixelSize.height();
+ imgInfo.extent.depth = 1;
+ imgInfo.mipLevels = imgInfo.arrayLayers = 1;
+ imgInfo.samples = samples;
+ imgInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ imgInfo.usage = usage | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
+ imgInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ err = df->vkCreateImage(dev, &imgInfo, nullptr, images + i);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create image: %d", err);
+ return false;
+ }
+
+ // Assume the reqs are the same since the images are same in every way.
+ // Still, call GetImageMemReq for every image, in order to prevent the
+ // validation layer from complaining.
+ df->vkGetImageMemoryRequirements(dev, images[i], &memReq);
+ }
+
+ VkMemoryAllocateInfo memInfo;
+ memset(&memInfo, 0, sizeof(memInfo));
+ memInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ memInfo.allocationSize = aligned(memReq.size, memReq.alignment) * count;
+
+ uint32_t startIndex = 0;
+ do {
+ memInfo.memoryTypeIndex = chooseTransientImageMemType(images[0], startIndex);
+ if (memInfo.memoryTypeIndex == uint32_t(-1)) {
+ qWarning("No suitable memory type found");
+ return false;
+ }
+ startIndex = memInfo.memoryTypeIndex + 1;
+ err = df->vkAllocateMemory(dev, &memInfo, nullptr, mem);
+ if (err != VK_SUCCESS && err != VK_ERROR_OUT_OF_DEVICE_MEMORY) {
+ qWarning("Failed to allocate image memory: %d", err);
+ return false;
+ }
+ } while (err != VK_SUCCESS);
+
+ VkDeviceSize ofs = 0;
+ for (int i = 0; i < count; ++i) {
+ err = df->vkBindImageMemory(dev, images[i], *mem, ofs);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to bind image memory: %d", err);
+ return false;
+ }
+ ofs += aligned(memReq.size, memReq.alignment);
+
+ VkImageViewCreateInfo imgViewInfo;
+ memset(&imgViewInfo, 0, sizeof(imgViewInfo));
+ imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ imgViewInfo.image = images[i];
+ imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ imgViewInfo.format = format;
+ imgViewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ imgViewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ imgViewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ imgViewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ imgViewInfo.subresourceRange.aspectMask = aspectMask;
+ imgViewInfo.subresourceRange.levelCount = imgViewInfo.subresourceRange.layerCount = 1;
+
+ err = df->vkCreateImageView(dev, &imgViewInfo, nullptr, views + i);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create image view: %d", err);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+VkFormat QRhiVulkan::optimalDepthStencilFormat()
+{
+ if (optimalDsFormat != VK_FORMAT_UNDEFINED)
+ return optimalDsFormat;
+
+ const VkFormat dsFormatCandidates[] = {
+ VK_FORMAT_D24_UNORM_S8_UINT,
+ VK_FORMAT_D32_SFLOAT_S8_UINT,
+ VK_FORMAT_D16_UNORM_S8_UINT
+ };
+ const int dsFormatCandidateCount = sizeof(dsFormatCandidates) / sizeof(VkFormat);
+ int dsFormatIdx = 0;
+ while (dsFormatIdx < dsFormatCandidateCount) {
+ optimalDsFormat = dsFormatCandidates[dsFormatIdx];
+ VkFormatProperties fmtProp;
+ f->vkGetPhysicalDeviceFormatProperties(physDev, optimalDsFormat, &fmtProp);
+ if (fmtProp.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
+ break;
+ ++dsFormatIdx;
+ }
+ if (dsFormatIdx == dsFormatCandidateCount)
+ qWarning("Failed to find an optimal depth-stencil format");
+
+ return optimalDsFormat;
+}
+
+bool QRhiVulkan::createDefaultRenderPass(VkRenderPass *rp, bool hasDepthStencil, VkSampleCountFlagBits samples, VkFormat colorFormat)
+{
+ VkAttachmentDescription attDesc[3];
+ memset(attDesc, 0, sizeof(attDesc));
+
+ // attachment list layout is color (1), ds (0-1), resolve (0-1)
+
+ attDesc[0].format = colorFormat;
+ attDesc[0].samples = samples;
+ attDesc[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attDesc[0].storeOp = samples > VK_SAMPLE_COUNT_1_BIT ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
+ attDesc[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attDesc[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc[0].finalLayout = samples > VK_SAMPLE_COUNT_1_BIT ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+ // clear on load + no store + lazy alloc + transient image should play
+ // nicely with tiled GPUs (no physical backing necessary for ds buffer)
+ attDesc[1].format = optimalDepthStencilFormat();
+ attDesc[1].samples = samples;
+ attDesc[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attDesc[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attDesc[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ if (samples > VK_SAMPLE_COUNT_1_BIT) {
+ attDesc[2].format = colorFormat;
+ attDesc[2].samples = VK_SAMPLE_COUNT_1_BIT;
+ attDesc[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attDesc[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attDesc[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attDesc[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc[2].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ }
+
+ VkAttachmentReference colorRef = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
+ VkAttachmentReference dsRef = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
+ VkAttachmentReference resolveRef = { 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
+
+ VkSubpassDescription subpassDesc;
+ memset(&subpassDesc, 0, sizeof(subpassDesc));
+ subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpassDesc.colorAttachmentCount = 1;
+ subpassDesc.pColorAttachments = &colorRef;
+ subpassDesc.pDepthStencilAttachment = hasDepthStencil ? &dsRef : nullptr;
+
+ // Replace the first implicit dep (TOP_OF_PIPE / ALL_COMMANDS) with our own.
+ VkSubpassDependency subpassDep;
+ memset(&subpassDep, 0, sizeof(subpassDep));
+ subpassDep.srcSubpass = VK_SUBPASS_EXTERNAL;
+ subpassDep.dstSubpass = 0;
+ subpassDep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ subpassDep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ subpassDep.srcAccessMask = 0;
+ subpassDep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ VkRenderPassCreateInfo rpInfo;
+ memset(&rpInfo, 0, sizeof(rpInfo));
+ rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ rpInfo.attachmentCount = 1;
+ rpInfo.pAttachments = attDesc;
+ rpInfo.subpassCount = 1;
+ rpInfo.pSubpasses = &subpassDesc;
+ rpInfo.dependencyCount = 1;
+ rpInfo.pDependencies = &subpassDep;
+
+ if (hasDepthStencil)
+ rpInfo.attachmentCount += 1;
+
+ if (samples > VK_SAMPLE_COUNT_1_BIT) {
+ rpInfo.attachmentCount += 1;
+ subpassDesc.pResolveAttachments = &resolveRef;
+ }
+
+ VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, rp);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create renderpass: %d", err);
+ return false;
+ }
+
+ return true;
+}
+
+bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp,
+ const QVector<QRhiColorAttachment> &colorAttachments,
+ bool preserveColor,
+ bool preserveDs,
+ QRhiRenderBuffer *depthStencilBuffer,
+ QRhiTexture *depthTexture)
+{
+ QVarLengthArray<VkAttachmentDescription, 8> attDescs;
+ QVarLengthArray<VkAttachmentReference, 8> colorRefs;
+ QVarLengthArray<VkAttachmentReference, 8> resolveRefs;
+ const int colorAttCount = colorAttachments.count();
+
+ // attachment list layout is color (0-8), ds (0-1), resolve (0-8)
+
+ for (int i = 0; i < colorAttCount; ++i) {
+ QVkTexture *texD = QRHI_RES(QVkTexture, colorAttachments[i].texture());
+ QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, colorAttachments[i].renderBuffer());
+ Q_ASSERT(texD || rbD);
+ const VkFormat vkformat = texD ? texD->vkformat : rbD->vkformat;
+ const VkSampleCountFlagBits samples = texD ? texD->samples : rbD->samples;
+
+ VkAttachmentDescription attDesc;
+ memset(&attDesc, 0, sizeof(attDesc));
+ attDesc.format = vkformat;
+ attDesc.samples = samples;
+ attDesc.loadOp = preserveColor ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attDesc.storeOp = colorAttachments[i].resolveTexture() ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
+ attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ // this has to interact correctly with activateTextureRenderTarget(), hence leaving in COLOR_ATT
+ attDesc.initialLayout = preserveColor ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ attDescs.append(attDesc);
+
+ const VkAttachmentReference ref = { uint32_t(attDescs.count() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
+ colorRefs.append(ref);
+ }
+
+ const bool hasDepthStencil = depthStencilBuffer || depthTexture;
+ if (hasDepthStencil) {
+ const VkFormat dsFormat = depthTexture ? QRHI_RES(QVkTexture, depthTexture)->vkformat
+ : QRHI_RES(QVkRenderBuffer, depthStencilBuffer)->vkformat;
+ const VkSampleCountFlagBits samples = depthTexture ? QRHI_RES(QVkTexture, depthTexture)->samples
+ : QRHI_RES(QVkRenderBuffer, depthStencilBuffer)->samples;
+ const VkAttachmentLoadOp loadOp = preserveDs ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
+ const VkAttachmentStoreOp storeOp = depthTexture ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ VkAttachmentDescription attDesc;
+ memset(&attDesc, 0, sizeof(attDesc));
+ attDesc.format = dsFormat;
+ attDesc.samples = samples;
+ attDesc.loadOp = loadOp;
+ attDesc.storeOp = storeOp;
+ attDesc.stencilLoadOp = loadOp;
+ attDesc.stencilStoreOp = storeOp;
+ attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ attDescs.append(attDesc);
+ }
+ VkAttachmentReference dsRef = { uint32_t(attDescs.count() - 1), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
+
+ for (int i = 0; i < colorAttCount; ++i) {
+ if (colorAttachments[i].resolveTexture()) {
+ QVkTexture *rtexD = QRHI_RES(QVkTexture, colorAttachments[i].resolveTexture());
+ if (rtexD->samples > VK_SAMPLE_COUNT_1_BIT)
+ qWarning("Resolving into a multisample texture is not supported");
+
+ VkAttachmentDescription attDesc;
+ memset(&attDesc, 0, sizeof(attDesc));
+ attDesc.format = rtexD->vkformat;
+ attDesc.samples = VK_SAMPLE_COUNT_1_BIT;
+ attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // ignored
+ attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ attDescs.append(attDesc);
+
+ const VkAttachmentReference ref = { uint32_t(attDescs.count() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
+ resolveRefs.append(ref);
+ } else {
+ const VkAttachmentReference ref = { VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
+ resolveRefs.append(ref);
+ }
+ }
+
+ VkSubpassDescription subpassDesc;
+ memset(&subpassDesc, 0, sizeof(subpassDesc));
+ subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpassDesc.colorAttachmentCount = colorRefs.count();
+ Q_ASSERT(colorRefs.count() == resolveRefs.count());
+ subpassDesc.pColorAttachments = !colorRefs.isEmpty() ? colorRefs.constData() : nullptr;
+ subpassDesc.pDepthStencilAttachment = hasDepthStencil ? &dsRef : nullptr;
+ subpassDesc.pResolveAttachments = !resolveRefs.isEmpty() ? resolveRefs.constData() : nullptr;
+
+ VkRenderPassCreateInfo rpInfo;
+ memset(&rpInfo, 0, sizeof(rpInfo));
+ rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ rpInfo.attachmentCount = attDescs.count();
+ rpInfo.pAttachments = attDescs.constData();
+ rpInfo.subpassCount = 1;
+ rpInfo.pSubpasses = &subpassDesc;
+ // don't yet know the correct initial/final access and stage stuff for the
+ // implicit deps at this point, so leave it to the resource tracking to
+ // generate barriers
+
+ VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, rp);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create renderpass: %d", err);
+ return false;
+ }
+
+ return true;
+}
+
+bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain)
+{
+ QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
+ if (swapChainD->pixelSize.isEmpty()) {
+ qWarning("Surface size is 0, cannot create swapchain");
+ return false;
+ }
+
+ df->vkDeviceWaitIdle(dev);
+
+ if (!vkCreateSwapchainKHR) {
+ vkCreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(f->vkGetDeviceProcAddr(dev, "vkCreateSwapchainKHR"));
+ vkDestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(f->vkGetDeviceProcAddr(dev, "vkDestroySwapchainKHR"));
+ vkGetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(f->vkGetDeviceProcAddr(dev, "vkGetSwapchainImagesKHR"));
+ vkAcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(f->vkGetDeviceProcAddr(dev, "vkAcquireNextImageKHR"));
+ vkQueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(f->vkGetDeviceProcAddr(dev, "vkQueuePresentKHR"));
+ if (!vkCreateSwapchainKHR || !vkDestroySwapchainKHR || !vkGetSwapchainImagesKHR || !vkAcquireNextImageKHR || !vkQueuePresentKHR) {
+ qWarning("Swapchain functions not available");
+ return false;
+ }
+ }
+
+ VkSurfaceCapabilitiesKHR surfaceCaps;
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDev, swapChainD->surface, &surfaceCaps);
+ quint32 reqBufferCount;
+ if (swapChainD->m_flags.testFlag(QRhiSwapChain::MinimalBufferCount)) {
+ reqBufferCount = qMax<quint32>(2, surfaceCaps.minImageCount);
+ } else {
+ const quint32 maxBuffers = QVkSwapChain::MAX_BUFFER_COUNT;
+ if (surfaceCaps.maxImageCount)
+ reqBufferCount = qMax(qMin(surfaceCaps.maxImageCount, maxBuffers), surfaceCaps.minImageCount);
+ else
+ reqBufferCount = qMax<quint32>(2, surfaceCaps.minImageCount);
+ }
+
+ VkSurfaceTransformFlagBitsKHR preTransform =
+ (surfaceCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
+ ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
+ : surfaceCaps.currentTransform;
+
+ VkCompositeAlphaFlagBitsKHR compositeAlpha =
+ (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
+ ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
+ : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+
+ if (swapChainD->m_flags.testFlag(QRhiSwapChain::SurfaceHasPreMulAlpha)
+ && (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR))
+ {
+ compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
+ }
+
+ if (swapChainD->m_flags.testFlag(QRhiSwapChain::SurfaceHasNonPreMulAlpha)
+ && (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR))
+ {
+ compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
+ }
+
+ VkImageUsageFlags usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ swapChainD->supportsReadback = (surfaceCaps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+ if (swapChainD->supportsReadback && swapChainD->m_flags.testFlag(QRhiSwapChain::UsedAsTransferSource))
+ usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+
+ VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
+ if (swapChainD->m_flags.testFlag(QRhiSwapChain::NoVSync)) {
+ if (swapChainD->supportedPresentationModes.contains(VK_PRESENT_MODE_MAILBOX_KHR))
+ presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
+ else if (swapChainD->supportedPresentationModes.contains(VK_PRESENT_MODE_IMMEDIATE_KHR))
+ presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
+ }
+
+ // If the surface is different than before, then passing in the old
+ // swapchain associated with the old surface can fail the swapchain
+ // creation. (for example, Android loses the surface when backgrounding and
+ // restoring applications, and it also enforces failing swapchain creation
+ // with VK_ERROR_NATIVE_WINDOW_IN_USE_KHR if the old swapchain is provided)
+ const bool reuseExisting = swapChainD->sc && swapChainD->lastConnectedSurface == swapChainD->surface;
+
+ qDebug("Creating %s swapchain of %u buffers, size %dx%d, presentation mode %d",
+ reuseExisting ? "recycled" : "new",
+ reqBufferCount, swapChainD->pixelSize.width(), swapChainD->pixelSize.height(), presentMode);
+
+ VkSwapchainCreateInfoKHR swapChainInfo;
+ memset(&swapChainInfo, 0, sizeof(swapChainInfo));
+ swapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapChainInfo.surface = swapChainD->surface;
+ swapChainInfo.minImageCount = reqBufferCount;
+ swapChainInfo.imageFormat = swapChainD->colorFormat;
+ swapChainInfo.imageColorSpace = swapChainD->colorSpace;
+ swapChainInfo.imageExtent = VkExtent2D { uint32_t(swapChainD->pixelSize.width()), uint32_t(swapChainD->pixelSize.height()) };
+ swapChainInfo.imageArrayLayers = 1;
+ swapChainInfo.imageUsage = usage;
+ swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapChainInfo.preTransform = preTransform;
+ swapChainInfo.compositeAlpha = compositeAlpha;
+ swapChainInfo.presentMode = presentMode;
+ swapChainInfo.clipped = true;
+ swapChainInfo.oldSwapchain = reuseExisting ? swapChainD->sc : VK_NULL_HANDLE;
+
+ VkSwapchainKHR newSwapChain;
+ VkResult err = vkCreateSwapchainKHR(dev, &swapChainInfo, nullptr, &newSwapChain);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create swapchain: %d", err);
+ return false;
+ }
+
+ if (swapChainD->sc)
+ releaseSwapChainResources(swapChain);
+
+ swapChainD->sc = newSwapChain;
+ swapChainD->lastConnectedSurface = swapChainD->surface;
+
+ quint32 actualSwapChainBufferCount = 0;
+ err = vkGetSwapchainImagesKHR(dev, swapChainD->sc, &actualSwapChainBufferCount, nullptr);
+ if (err != VK_SUCCESS || actualSwapChainBufferCount < 2) {
+ qWarning("Failed to get swapchain images: %d (count=%u)", err, actualSwapChainBufferCount);
+ return false;
+ }
+
+ if (actualSwapChainBufferCount > QVkSwapChain::MAX_BUFFER_COUNT) {
+ qWarning("Too many swapchain buffers (%u)", actualSwapChainBufferCount);
+ return false;
+ }
+ if (actualSwapChainBufferCount != reqBufferCount)
+ qDebug("Actual swapchain buffer count is %u", actualSwapChainBufferCount);
+ swapChainD->bufferCount = actualSwapChainBufferCount;
+
+ VkImage swapChainImages[QVkSwapChain::MAX_BUFFER_COUNT];
+ err = vkGetSwapchainImagesKHR(dev, swapChainD->sc, &actualSwapChainBufferCount, swapChainImages);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to get swapchain images: %d", err);
+ return false;
+ }
+
+ VkImage msaaImages[QVkSwapChain::MAX_BUFFER_COUNT];
+ VkImageView msaaViews[QVkSwapChain::MAX_BUFFER_COUNT];
+ if (swapChainD->samples > VK_SAMPLE_COUNT_1_BIT) {
+ if (!createTransientImage(swapChainD->colorFormat,
+ swapChainD->pixelSize,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ swapChainD->samples,
+ &swapChainD->msaaImageMem,
+ msaaImages,
+ msaaViews,
+ swapChainD->bufferCount))
+ {
+ qWarning("Failed to create transient image for MSAA color buffer");
+ return false;
+ }
+ }
+
+ VkFenceCreateInfo fenceInfo;
+ memset(&fenceInfo, 0, sizeof(fenceInfo));
+ fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+
+ for (int i = 0; i < swapChainD->bufferCount; ++i) {
+ QVkSwapChain::ImageResources &image(swapChainD->imageRes[i]);
+ image.image = swapChainImages[i];
+ if (swapChainD->samples > VK_SAMPLE_COUNT_1_BIT) {
+ image.msaaImage = msaaImages[i];
+ image.msaaImageView = msaaViews[i];
+ }
+
+ VkImageViewCreateInfo imgViewInfo;
+ memset(&imgViewInfo, 0, sizeof(imgViewInfo));
+ imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ imgViewInfo.image = swapChainImages[i];
+ imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ imgViewInfo.format = swapChainD->colorFormat;
+ imgViewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ imgViewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ imgViewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ imgViewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ imgViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ imgViewInfo.subresourceRange.levelCount = imgViewInfo.subresourceRange.layerCount = 1;
+ err = df->vkCreateImageView(dev, &imgViewInfo, nullptr, &image.imageView);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create swapchain image view %d: %d", i, err);
+ return false;
+ }
+ }
+
+ swapChainD->currentImageIndex = 0;
+
+ VkSemaphoreCreateInfo semInfo;
+ memset(&semInfo, 0, sizeof(semInfo));
+ semInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ QVkSwapChain::FrameResources &frame(swapChainD->frameRes[i]);
+
+ frame.imageAcquired = false;
+ frame.imageSemWaitable = false;
+
+ df->vkCreateFence(dev, &fenceInfo, nullptr, &frame.imageFence);
+ frame.imageFenceWaitable = true; // fence was created in signaled state
+
+ df->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.imageSem);
+ df->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.drawSem);
+
+ err = df->vkCreateFence(dev, &fenceInfo, nullptr, &frame.cmdFence);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create command buffer fence: %d", err);
+ return false;
+ }
+ frame.cmdFenceWaitable = true; // fence was created in signaled state
+ }
+
+ swapChainD->currentFrameSlot = 0;
+
+ return true;
+}
+
+void QRhiVulkan::releaseSwapChainResources(QRhiSwapChain *swapChain)
+{
+ QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
+
+ if (swapChainD->sc == VK_NULL_HANDLE)
+ return;
+
+ df->vkDeviceWaitIdle(dev);
+
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ QVkSwapChain::FrameResources &frame(swapChainD->frameRes[i]);
+ if (frame.cmdFence) {
+ if (frame.cmdFenceWaitable)
+ df->vkWaitForFences(dev, 1, &frame.cmdFence, VK_TRUE, UINT64_MAX);
+ df->vkDestroyFence(dev, frame.cmdFence, nullptr);
+ frame.cmdFence = VK_NULL_HANDLE;
+ frame.cmdFenceWaitable = false;
+ }
+ if (frame.imageFence) {
+ if (frame.imageFenceWaitable)
+ df->vkWaitForFences(dev, 1, &frame.imageFence, VK_TRUE, UINT64_MAX);
+ df->vkDestroyFence(dev, frame.imageFence, nullptr);
+ frame.imageFence = VK_NULL_HANDLE;
+ frame.imageFenceWaitable = false;
+ }
+ if (frame.imageSem) {
+ df->vkDestroySemaphore(dev, frame.imageSem, nullptr);
+ frame.imageSem = VK_NULL_HANDLE;
+ }
+ if (frame.drawSem) {
+ df->vkDestroySemaphore(dev, frame.drawSem, nullptr);
+ frame.drawSem = VK_NULL_HANDLE;
+ }
+ if (frame.cmdBuf) {
+ df->vkFreeCommandBuffers(dev, cmdPool, 1, &frame.cmdBuf);
+ frame.cmdBuf = VK_NULL_HANDLE;
+ }
+ }
+
+ for (int i = 0; i < swapChainD->bufferCount; ++i) {
+ QVkSwapChain::ImageResources &image(swapChainD->imageRes[i]);
+ if (image.fb) {
+ df->vkDestroyFramebuffer(dev, image.fb, nullptr);
+ image.fb = VK_NULL_HANDLE;
+ }
+ if (image.imageView) {
+ df->vkDestroyImageView(dev, image.imageView, nullptr);
+ image.imageView = VK_NULL_HANDLE;
+ }
+ if (image.msaaImageView) {
+ df->vkDestroyImageView(dev, image.msaaImageView, nullptr);
+ image.msaaImageView = VK_NULL_HANDLE;
+ }
+ if (image.msaaImage) {
+ df->vkDestroyImage(dev, image.msaaImage, nullptr);
+ image.msaaImage = VK_NULL_HANDLE;
+ }
+ }
+
+ if (swapChainD->msaaImageMem) {
+ df->vkFreeMemory(dev, swapChainD->msaaImageMem, nullptr);
+ swapChainD->msaaImageMem = VK_NULL_HANDLE;
+ }
+
+ vkDestroySwapchainKHR(dev, swapChainD->sc, nullptr);
+ swapChainD->sc = VK_NULL_HANDLE;
+
+ // NB! surface and similar must remain intact
+}
+
+static inline bool checkDeviceLost(VkResult err)
+{
+ if (err == VK_ERROR_DEVICE_LOST) {
+ qWarning("Device lost");
+ return true;
+ }
+ return false;
+}
+
+QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
+{
+ Q_UNUSED(flags);
+ QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
+ QVkSwapChain::FrameResources &frame(swapChainD->frameRes[swapChainD->currentFrameSlot]);
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+
+ if (!frame.imageAcquired) {
+ // Wait if we are too far ahead, i.e. the thread gets throttled based on the presentation rate
+ // (note that we are using FIFO mode -> vsync)
+ if (frame.imageFenceWaitable) {
+ df->vkWaitForFences(dev, 1, &frame.imageFence, VK_TRUE, UINT64_MAX);
+ df->vkResetFences(dev, 1, &frame.imageFence);
+ frame.imageFenceWaitable = false;
+ }
+
+ // move on to next swapchain image
+ VkResult err = vkAcquireNextImageKHR(dev, swapChainD->sc, UINT64_MAX,
+ frame.imageSem, frame.imageFence, &frame.imageIndex);
+ if (err == VK_SUCCESS || err == VK_SUBOPTIMAL_KHR) {
+ swapChainD->currentImageIndex = frame.imageIndex;
+ frame.imageSemWaitable = true;
+ frame.imageAcquired = true;
+ frame.imageFenceWaitable = true;
+ } else if (err == VK_ERROR_OUT_OF_DATE_KHR) {
+ return QRhi::FrameOpSwapChainOutOfDate;
+ } else {
+ if (checkDeviceLost(err))
+ return QRhi::FrameOpDeviceLost;
+ else
+ qWarning("Failed to acquire next swapchain image: %d", err);
+ return QRhi::FrameOpError;
+ }
+ }
+
+ // Make sure the previous commands for the same image have finished. (note
+ // that this is based on the fence from the command buffer submit, nothing
+ // to do with the Present)
+ //
+ // Do this also for any other swapchain's commands with the same frame slot
+ // While this reduces concurrency, it keeps resource usage safe: swapchain
+ // A starting its frame 0, followed by swapchain B starting its own frame 0
+ // will make B wait for A's frame 0 commands, so if a resource is written
+ // in B's frame or when B checks for pending resource releases, that won't
+ // mess up A's in-flight commands (as they are not in flight anymore).
+ waitCommandCompletion(swapChainD->currentFrameSlot);
+
+ // Now is the time to read the timestamps for the previous frame for this slot.
+ if (frame.timestampQueryIndex >= 0) {
+ quint64 timestamp[2] = { 0, 0 };
+ VkResult err = df->vkGetQueryPoolResults(dev, timestampQueryPool, frame.timestampQueryIndex, 2,
+ 2 * sizeof(quint64), timestamp, sizeof(quint64), VK_QUERY_RESULT_64_BIT);
+ timestampQueryPoolMap.clearBit(frame.timestampQueryIndex / 2);
+ frame.timestampQueryIndex = -1;
+ if (err == VK_SUCCESS) {
+ quint64 mask = 0;
+ for (quint64 i = 0; i < timestampValidBits; i += 8)
+ mask |= 0xFFULL << i;
+ const quint64 ts0 = timestamp[0] & mask;
+ const quint64 ts1 = timestamp[1] & mask;
+ const float nsecsPerTick = physDevProperties.limits.timestampPeriod;
+ if (!qFuzzyIsNull(nsecsPerTick)) {
+ const float elapsedMs = float(ts1 - ts0) * nsecsPerTick / 1000000.0f;
+ // now we have the gpu time for the previous frame for this slot, report it
+ // (does not matter that it is not for this frame)
+ QRHI_PROF_F(swapChainFrameGpuTime(swapChain, elapsedMs));
+ }
+ } else {
+ qWarning("Failed to query timestamp: %d", err);
+ }
+ }
+
+ // build new draw command buffer
+ QRhi::FrameOpResult cbres = startCommandBuffer(&frame.cmdBuf);
+ if (cbres != QRhi::FrameOpSuccess)
+ return cbres;
+
+ // when profiling is enabled, pick a free query (pair) from the pool
+ int timestampQueryIdx = -1;
+ if (profilerPrivateOrNull()) {
+ for (int i = 0; i < timestampQueryPoolMap.count(); ++i) {
+ if (!timestampQueryPoolMap.testBit(i)) {
+ timestampQueryPoolMap.setBit(i);
+ timestampQueryIdx = i * 2;
+ break;
+ }
+ }
+ }
+ if (timestampQueryIdx >= 0) {
+ df->vkCmdResetQueryPool(frame.cmdBuf, timestampQueryPool, timestampQueryIdx, 2);
+ // record timestamp at the start of the command buffer
+ df->vkCmdWriteTimestamp(frame.cmdBuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ timestampQueryPool, timestampQueryIdx);
+ frame.timestampQueryIndex = timestampQueryIdx;
+ }
+
+ swapChainD->cbWrapper.cb = frame.cmdBuf;
+ QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
+ swapChainD->rtWrapper.d.fb = image.fb;
+
+ currentFrameSlot = swapChainD->currentFrameSlot;
+ currentSwapChain = swapChainD;
+ if (swapChainD->ds)
+ swapChainD->ds->lastActiveFrameSlot = currentFrameSlot;
+
+ QRHI_PROF_F(beginSwapChainFrame(swapChain));
+
+ prepareNewFrame(&swapChainD->cbWrapper);
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags)
+{
+ Q_ASSERT(inFrame);
+ inFrame = false;
+
+ QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
+ Q_ASSERT(currentSwapChain == swapChainD);
+
+ recordCommandBuffer(&swapChainD->cbWrapper);
+
+ QVkSwapChain::FrameResources &frame(swapChainD->frameRes[swapChainD->currentFrameSlot]);
+ QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
+
+ if (image.transferSource) {
+ // was used in a readback as transfer source, go back to presentable layout
+ VkImageMemoryBarrier presTrans;
+ memset(&presTrans, 0, sizeof(presTrans));
+ presTrans.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ presTrans.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ presTrans.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ presTrans.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ presTrans.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ presTrans.image = image.image;
+ presTrans.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ presTrans.subresourceRange.levelCount = presTrans.subresourceRange.layerCount = 1;
+ df->vkCmdPipelineBarrier(frame.cmdBuf,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &presTrans);
+ image.transferSource = false;
+ }
+
+ // record another timestamp, when enabled
+ if (frame.timestampQueryIndex >= 0) {
+ df->vkCmdWriteTimestamp(frame.cmdBuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ timestampQueryPool, frame.timestampQueryIndex + 1);
+ }
+
+ // stop recording and submit to the queue
+ Q_ASSERT(!frame.cmdFenceWaitable);
+ const bool needsPresent = !flags.testFlag(QRhi::SkipPresent);
+ QRhi::FrameOpResult submitres = endAndSubmitCommandBuffer(frame.cmdBuf,
+ frame.cmdFence,
+ frame.imageSemWaitable ? &frame.imageSem : nullptr,
+ needsPresent ? &frame.drawSem : nullptr);
+ if (submitres != QRhi::FrameOpSuccess)
+ return submitres;
+
+ frame.imageSemWaitable = false;
+ frame.cmdFenceWaitable = true;
+
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+ // this must be done before the Present
+ QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
+
+ if (needsPresent) {
+ // add the Present to the queue
+ VkPresentInfoKHR presInfo;
+ memset(&presInfo, 0, sizeof(presInfo));
+ presInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ presInfo.swapchainCount = 1;
+ presInfo.pSwapchains = &swapChainD->sc;
+ presInfo.pImageIndices = &swapChainD->currentImageIndex;
+ presInfo.waitSemaphoreCount = 1;
+ presInfo.pWaitSemaphores = &frame.drawSem; // gfxQueueFamilyIdx == presQueueFamilyIdx ? &frame.drawSem : &frame.presTransSem;
+
+ VkResult err = vkQueuePresentKHR(gfxQueue, &presInfo);
+ if (err != VK_SUCCESS) {
+ if (err == VK_ERROR_OUT_OF_DATE_KHR) {
+ return QRhi::FrameOpSwapChainOutOfDate;
+ } else if (err != VK_SUBOPTIMAL_KHR) {
+ if (checkDeviceLost(err))
+ return QRhi::FrameOpDeviceLost;
+ else
+ qWarning("Failed to present: %d", err);
+ return QRhi::FrameOpError;
+ }
+ }
+
+ // mark the current swapchain buffer as unused from our side
+ frame.imageAcquired = false;
+ // and move on to the next buffer
+ swapChainD->currentFrameSlot = (swapChainD->currentFrameSlot + 1) % QVK_FRAMES_IN_FLIGHT;
+ }
+
+ swapChainD->frameCount += 1;
+ currentSwapChain = nullptr;
+ return QRhi::FrameOpSuccess;
+}
+
+void QRhiVulkan::prepareNewFrame(QRhiCommandBuffer *cb)
+{
+ Q_ASSERT(!inFrame);
+ inFrame = true;
+
+ // Now is the time to do things for frame N-F, where N is the current one,
+ // F is QVK_FRAMES_IN_FLIGHT, because only here it is guaranteed that that
+ // frame has completed on the GPU (due to the fence wait in beginFrame). To
+ // decide if something is safe to handle now a simple "lastActiveFrameSlot
+ // == currentFrameSlot" is sufficient (remember that e.g. with F==2
+ // currentFrameSlot goes 0, 1, 0, 1, 0, ...)
+ //
+ // With multiple swapchains on the same QRhi things get more convoluted
+ // (and currentFrameSlot strictly alternating is not true anymore) but
+ // beginNonWrapperFrame() solves that by blocking as necessary so the rest
+ // here is safe regardless.
+
+ executeDeferredReleases();
+
+ QRHI_RES(QVkCommandBuffer, cb)->resetState();
+
+ finishActiveReadbacks(); // last, in case the readback-completed callback issues rhi calls
+}
+
+QRhi::FrameOpResult QRhiVulkan::startCommandBuffer(VkCommandBuffer *cb)
+{
+ if (*cb) {
+ df->vkFreeCommandBuffers(dev, cmdPool, 1, cb);
+ *cb = VK_NULL_HANDLE;
+ }
+
+ VkCommandBufferAllocateInfo cmdBufInfo;
+ memset(&cmdBufInfo, 0, sizeof(cmdBufInfo));
+ cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ cmdBufInfo.commandPool = cmdPool;
+ cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ cmdBufInfo.commandBufferCount = 1;
+
+ VkResult err = df->vkAllocateCommandBuffers(dev, &cmdBufInfo, cb);
+ if (err != VK_SUCCESS) {
+ if (checkDeviceLost(err))
+ return QRhi::FrameOpDeviceLost;
+ else
+ qWarning("Failed to allocate frame command buffer: %d", err);
+ return QRhi::FrameOpError;
+ }
+
+ VkCommandBufferBeginInfo cmdBufBeginInfo;
+ memset(&cmdBufBeginInfo, 0, sizeof(cmdBufBeginInfo));
+ cmdBufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+
+ err = df->vkBeginCommandBuffer(*cb, &cmdBufBeginInfo);
+ if (err != VK_SUCCESS) {
+ if (checkDeviceLost(err))
+ return QRhi::FrameOpDeviceLost;
+ else
+ qWarning("Failed to begin frame command buffer: %d", err);
+ return QRhi::FrameOpError;
+ }
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiVulkan::endAndSubmitCommandBuffer(VkCommandBuffer cb, VkFence cmdFence,
+ VkSemaphore *waitSem, VkSemaphore *signalSem)
+{
+ VkResult err = df->vkEndCommandBuffer(cb);
+ if (err != VK_SUCCESS) {
+ if (checkDeviceLost(err))
+ return QRhi::FrameOpDeviceLost;
+ else
+ qWarning("Failed to end frame command buffer: %d", err);
+ return QRhi::FrameOpError;
+ }
+
+ VkSubmitInfo submitInfo;
+ memset(&submitInfo, 0, sizeof(submitInfo));
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &cb;
+ if (waitSem) {
+ submitInfo.waitSemaphoreCount = 1;
+ submitInfo.pWaitSemaphores = waitSem;
+ }
+ if (signalSem) {
+ submitInfo.signalSemaphoreCount = 1;
+ submitInfo.pSignalSemaphores = signalSem;
+ }
+ VkPipelineStageFlags psf = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ submitInfo.pWaitDstStageMask = &psf;
+
+ err = df->vkQueueSubmit(gfxQueue, 1, &submitInfo, cmdFence);
+ if (err != VK_SUCCESS) {
+ if (checkDeviceLost(err))
+ return QRhi::FrameOpDeviceLost;
+ else
+ qWarning("Failed to submit to graphics queue: %d", err);
+ return QRhi::FrameOpError;
+ }
+
+ return QRhi::FrameOpSuccess;
+}
+
+void QRhiVulkan::waitCommandCompletion(int frameSlot)
+{
+ for (QVkSwapChain *sc : qAsConst(swapchains)) {
+ QVkSwapChain::FrameResources &frame(sc->frameRes[frameSlot]);
+ if (frame.cmdFenceWaitable) {
+ df->vkWaitForFences(dev, 1, &frame.cmdFence, VK_TRUE, UINT64_MAX);
+ df->vkResetFences(dev, 1, &frame.cmdFence);
+ frame.cmdFenceWaitable = false;
+ }
+ }
+}
+
+QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb)
+{
+ QRhi::FrameOpResult cbres = startCommandBuffer(&ofr.cbWrapper.cb);
+ if (cbres != QRhi::FrameOpSuccess)
+ return cbres;
+
+ // Switch to the next slot manually. Swapchains do not know about this
+ // which is good. So for example a - unusual but possible - onscreen,
+ // onscreen, offscreen, onscreen, onscreen, onscreen sequence of
+ // begin/endFrame leads to 0, 1, 0, 0, 1, 0. This works because the
+ // offscreen frame is synchronous in the sense that we wait for execution
+ // to complete in endFrame, and so no resources used in that frame are busy
+ // anymore in the next frame.
+ currentFrameSlot = (currentFrameSlot + 1) % QVK_FRAMES_IN_FLIGHT;
+ // except that this gets complicated with multiple swapchains so make sure
+ // any pending commands have finished for the frame slot we are going to use
+ if (swapchains.count() > 1)
+ waitCommandCompletion(currentFrameSlot);
+
+ prepareNewFrame(&ofr.cbWrapper);
+ ofr.active = true;
+
+ *cb = &ofr.cbWrapper;
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiVulkan::endOffscreenFrame()
+{
+ Q_ASSERT(inFrame);
+ inFrame = false;
+ Q_ASSERT(ofr.active);
+ ofr.active = false;
+
+ recordCommandBuffer(&ofr.cbWrapper);
+
+ if (!ofr.cmdFence) {
+ VkFenceCreateInfo fenceInfo;
+ memset(&fenceInfo, 0, sizeof(fenceInfo));
+ fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ VkResult err = df->vkCreateFence(dev, &fenceInfo, nullptr, &ofr.cmdFence);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create command buffer fence: %d", err);
+ return QRhi::FrameOpError;
+ }
+ }
+
+ QRhi::FrameOpResult submitres = endAndSubmitCommandBuffer(ofr.cbWrapper.cb, ofr.cmdFence, nullptr, nullptr);
+ if (submitres != QRhi::FrameOpSuccess)
+ return submitres;
+
+ // wait for completion
+ df->vkWaitForFences(dev, 1, &ofr.cmdFence, VK_TRUE, UINT64_MAX);
+ df->vkResetFences(dev, 1, &ofr.cmdFence);
+
+ // Here we know that executing the host-side reads for this (or any
+ // previous) frame is safe since we waited for completion above.
+ finishActiveReadbacks(true);
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiVulkan::finish()
+{
+ Q_ASSERT(!inPass);
+
+ QVkSwapChain *swapChainD = nullptr;
+ if (inFrame) {
+ // There is either a swapchain or an offscreen frame on-going.
+ // End command recording and submit what we have.
+ VkCommandBuffer cb;
+ if (ofr.active) {
+ Q_ASSERT(!currentSwapChain);
+ recordCommandBuffer(&ofr.cbWrapper);
+ cb = ofr.cbWrapper.cb;
+ } else {
+ Q_ASSERT(currentSwapChain);
+ swapChainD = currentSwapChain;
+ recordCommandBuffer(&swapChainD->cbWrapper);
+ cb = swapChainD->cbWrapper.cb;
+ }
+ QRhi::FrameOpResult submitres = endAndSubmitCommandBuffer(cb, VK_NULL_HANDLE, nullptr, nullptr);
+ if (submitres != QRhi::FrameOpSuccess)
+ return submitres;
+ }
+
+ df->vkQueueWaitIdle(gfxQueue);
+
+ if (inFrame) {
+ // Allocate and begin recording on a new command buffer.
+ if (ofr.active)
+ startCommandBuffer(&ofr.cbWrapper.cb);
+ else
+ startCommandBuffer(&swapChainD->frameRes[swapChainD->currentFrameSlot].cmdBuf);
+ }
+
+ executeDeferredReleases(true);
+ finishActiveReadbacks(true);
+
+ return QRhi::FrameOpSuccess;
+}
+
+static inline QRhiPassResourceTracker::UsageState toPassTrackerUsageState(const QVkBuffer::UsageState &bufUsage)
+{
+ QRhiPassResourceTracker::UsageState u;
+ u.layout = 0; // unused with buffers
+ u.access = bufUsage.access;
+ u.stage = bufUsage.stage;
+ return u;
+}
+
+static inline QRhiPassResourceTracker::UsageState toPassTrackerUsageState(const QVkTexture::UsageState &texUsage)
+{
+ QRhiPassResourceTracker::UsageState u;
+ u.layout = texUsage.layout;
+ u.access = texUsage.access;
+ u.stage = texUsage.stage;
+ return u;
+}
+
+void QRhiVulkan::activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRenderTarget *rtD)
+{
+ rtD->lastActiveFrameSlot = currentFrameSlot;
+ rtD->d.rp->lastActiveFrameSlot = currentFrameSlot;
+ QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]);
+ const QVector<QRhiColorAttachment> colorAttachments = rtD->m_desc.colorAttachments();
+ for (const QRhiColorAttachment &colorAttachment : colorAttachments) {
+ QVkTexture *texD = QRHI_RES(QVkTexture, colorAttachment.texture());
+ QVkTexture *resolveTexD = QRHI_RES(QVkTexture, colorAttachment.resolveTexture());
+ QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, colorAttachment.renderBuffer());
+ if (texD) {
+ trackedRegisterTexture(&passResTracker, texD,
+ QRhiPassResourceTracker::TexColorOutput,
+ QRhiPassResourceTracker::TexColorOutputStage);
+ texD->lastActiveFrameSlot = currentFrameSlot;
+ } else if (rbD) {
+ // Won't register rbD->backingTexture because it cannot be used for
+ // anything in a renderpass, its use makes only sense in
+ // combination with a resolveTexture.
+ rbD->lastActiveFrameSlot = currentFrameSlot;
+ }
+ if (resolveTexD) {
+ trackedRegisterTexture(&passResTracker, resolveTexD,
+ QRhiPassResourceTracker::TexColorOutput,
+ QRhiPassResourceTracker::TexColorOutputStage);
+ resolveTexD->lastActiveFrameSlot = currentFrameSlot;
+ }
+ }
+ if (rtD->m_desc.depthStencilBuffer())
+ QRHI_RES(QVkRenderBuffer, rtD->m_desc.depthStencilBuffer())->lastActiveFrameSlot = currentFrameSlot;
+ if (rtD->m_desc.depthTexture()) {
+ QVkTexture *depthTexD = QRHI_RES(QVkTexture, rtD->m_desc.depthTexture());
+ trackedRegisterTexture(&passResTracker, depthTexD,
+ QRhiPassResourceTracker::TexDepthOutput,
+ QRhiPassResourceTracker::TexDepthOutputStage);
+ depthTexD->lastActiveFrameSlot = currentFrameSlot;
+ }
+}
+
+void QRhiVulkan::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inFrame && !inPass);
+
+ enqueueResourceUpdates(QRHI_RES(QVkCommandBuffer, cb), resourceUpdates);
+}
+
+void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inFrame && !inPass);
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cbD, resourceUpdates);
+
+ // Insert a TransitionPassResources into the command stream, pointing to
+ // the tracker this pass is going to use. That's how we generate the
+ // barriers later during recording the real VkCommandBuffer, right before
+ // the vkCmdBeginRenderPass.
+ enqueueTransitionPassResources(cbD);
+
+ QVkRenderTargetData *rtD = nullptr;
+ switch (rt->resourceType()) {
+ case QRhiResource::RenderTarget:
+ rtD = &QRHI_RES(QVkReferenceRenderTarget, rt)->d;
+ rtD->rp->lastActiveFrameSlot = currentFrameSlot;
+ break;
+ case QRhiResource::TextureRenderTarget:
+ {
+ QVkTextureRenderTarget *rtTex = QRHI_RES(QVkTextureRenderTarget, rt);
+ rtD = &rtTex->d;
+ activateTextureRenderTarget(cbD, rtTex);
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ cbD->currentTarget = rt;
+
+ // No copy operations or image layout transitions allowed after this point
+ // (up until endPass) as we are going to begin the renderpass.
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = rtD->rp->rp;
+ rpBeginInfo.framebuffer = rtD->fb;
+ rpBeginInfo.renderArea.extent.width = rtD->pixelSize.width();
+ rpBeginInfo.renderArea.extent.height = rtD->pixelSize.height();
+
+ QVarLengthArray<VkClearValue, 4> cvs;
+ for (int i = 0; i < rtD->colorAttCount; ++i) {
+ VkClearValue cv;
+ cv.color = { { float(colorClearValue.redF()), float(colorClearValue.greenF()), float(colorClearValue.blueF()),
+ float(colorClearValue.alphaF()) } };
+ cvs.append(cv);
+ }
+ for (int i = 0; i < rtD->dsAttCount; ++i) {
+ VkClearValue cv;
+ cv.depthStencil = { depthStencilClearValue.depthClearValue(), depthStencilClearValue.stencilClearValue() };
+ cvs.append(cv);
+ }
+ for (int i = 0; i < rtD->resolveAttCount; ++i) {
+ VkClearValue cv;
+ cv.color = { { float(colorClearValue.redF()), float(colorClearValue.greenF()), float(colorClearValue.blueF()),
+ float(colorClearValue.alphaF()) } };
+ cvs.append(cv);
+ }
+ rpBeginInfo.clearValueCount = cvs.count();
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::BeginRenderPass;
+ cmd.args.beginRenderPass.desc = rpBeginInfo;
+ cmd.args.beginRenderPass.clearValueIndex = cbD->pools.clearValue.count();
+ cbD->pools.clearValue.append(cvs.constData(), cvs.count());
+ cbD->commands.append(cmd);
+
+ inPass = true;
+}
+
+void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ Q_ASSERT(inPass);
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::EndRenderPass;
+ cbD->commands.append(cmd);
+
+ inPass = false;
+ cbD->currentTarget = nullptr;
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cbD, resourceUpdates);
+}
+
+VkShaderModule QRhiVulkan::createShader(const QByteArray &spirv)
+{
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = spirv.size();
+ shaderInfo.pCode = reinterpret_cast<const quint32 *>(spirv.constData());
+ VkShaderModule shaderModule;
+ VkResult err = df->vkCreateShaderModule(dev, &shaderInfo, nullptr, &shaderModule);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create shader module: %d", err);
+ return VK_NULL_HANDLE;
+ }
+ return shaderModule;
+}
+
+bool QRhiVulkan::ensurePipelineCache()
+{
+ if (pipelineCache)
+ return true;
+
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ VkResult err = df->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &pipelineCache);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create pipeline cache: %d", err);
+ return false;
+ }
+ return true;
+}
+
+void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, int descSetIdx)
+{
+ QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, srb);
+
+ QVarLengthArray<VkDescriptorBufferInfo, 4> bufferInfos;
+ QVarLengthArray<VkDescriptorImageInfo, 4> imageInfos;
+ QVarLengthArray<VkWriteDescriptorSet, 8> writeInfos;
+
+ const bool updateAll = descSetIdx < 0;
+ int frameSlot = updateAll ? 0 : descSetIdx;
+ while (frameSlot < (updateAll ? QVK_FRAMES_IN_FLIGHT : descSetIdx + 1)) {
+ srbD->boundResourceData[frameSlot].resize(srbD->sortedBindings.count());
+ for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->sortedBindings[i]);
+ QVkShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[frameSlot][i]);
+
+ VkWriteDescriptorSet writeInfo;
+ memset(&writeInfo, 0, sizeof(writeInfo));
+ writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ writeInfo.dstSet = srbD->descSets[frameSlot];
+ writeInfo.dstBinding = b->binding;
+ writeInfo.descriptorCount = 1;
+
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ {
+ writeInfo.descriptorType = b->u.ubuf.hasDynamicOffset ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
+ : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ QRhiBuffer *buf = b->u.ubuf.buf;
+ QVkBuffer *bufD = QRHI_RES(QVkBuffer, buf);
+ bd.ubuf.id = bufD->m_id;
+ bd.ubuf.generation = bufD->generation;
+ VkDescriptorBufferInfo bufInfo;
+ bufInfo.buffer = bufD->m_type == QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0];
+ bufInfo.offset = b->u.ubuf.offset;
+ bufInfo.range = b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size;
+ // be nice and assert when we know the vulkan device would die a horrible death due to non-aligned reads
+ Q_ASSERT(aligned(bufInfo.offset, ubufAlign) == bufInfo.offset);
+ bufferInfos.append(bufInfo);
+ writeInfo.pBufferInfo = &bufferInfos.last();
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ {
+ QVkTexture *texD = QRHI_RES(QVkTexture, b->u.stex.tex);
+ QVkSampler *samplerD = QRHI_RES(QVkSampler, b->u.stex.sampler);
+ writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ bd.stex.texId = texD->m_id;
+ bd.stex.texGeneration = texD->generation;
+ bd.stex.samplerId = samplerD->m_id;
+ bd.stex.samplerGeneration = samplerD->generation;
+ VkDescriptorImageInfo imageInfo;
+ imageInfo.sampler = samplerD->sampler;
+ imageInfo.imageView = texD->imageView;
+ imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ imageInfos.append(imageInfo);
+ writeInfo.pImageInfo = &imageInfos.last();
+ }
+ break;
+ default:
+ continue;
+ }
+
+ writeInfos.append(writeInfo);
+ }
+ ++frameSlot;
+ }
+
+ df->vkUpdateDescriptorSets(dev, writeInfos.count(), writeInfos.constData(), 0, nullptr);
+}
+
+static inline bool accessIsWrite(VkAccessFlags access)
+{
+ return (access & VK_ACCESS_SHADER_WRITE_BIT) != 0
+ || (access & VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT) != 0
+ || (access & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) != 0
+ || (access & VK_ACCESS_TRANSFER_WRITE_BIT) != 0
+ || (access & VK_ACCESS_HOST_WRITE_BIT) != 0
+ || (access & VK_ACCESS_MEMORY_WRITE_BIT) != 0;
+}
+
+void QRhiVulkan::trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, int slot,
+ VkAccessFlags access, VkPipelineStageFlags stage)
+{
+ Q_ASSERT(!inPass);
+ Q_ASSERT(access && stage);
+ QVkBuffer::UsageState &s(bufD->usageState[slot]);
+ if (!s.stage) {
+ s.access = access;
+ s.stage = stage;
+ return;
+ }
+
+ if (s.access == access && s.stage == stage) {
+ // No need to flood with unnecessary read-after-read barriers.
+ // Write-after-write is a different matter, however.
+ if (!accessIsWrite(access))
+ return;
+ }
+
+ VkBufferMemoryBarrier bufMemBarrier;
+ memset(&bufMemBarrier, 0, sizeof(bufMemBarrier));
+ bufMemBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+ bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier.srcAccessMask = s.access;
+ bufMemBarrier.dstAccessMask = access;
+ bufMemBarrier.buffer = bufD->buffers[slot];
+ bufMemBarrier.size = VK_WHOLE_SIZE;
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::BufferBarrier;
+ cmd.args.bufferBarrier.srcStageMask = s.stage;
+ cmd.args.bufferBarrier.dstStageMask = stage;
+ cmd.args.bufferBarrier.desc = bufMemBarrier;
+ cbD->commands.append(cmd);
+
+ s.access = access;
+ s.stage = stage;
+}
+
+void QRhiVulkan::trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD,
+ VkImageLayout layout, VkAccessFlags access, VkPipelineStageFlags stage)
+{
+ Q_ASSERT(!inPass);
+ Q_ASSERT(layout && access && stage);
+ QVkTexture::UsageState &s(texD->usageState);
+ if (s.access == access && s.stage == stage && s.layout == layout) {
+ if (!accessIsWrite(access))
+ return;
+ }
+
+ VkImageMemoryBarrier barrier;
+ memset(&barrier, 0, sizeof(barrier));
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.subresourceRange.aspectMask = !isDepthTextureFormat(texD->m_format)
+ ? VK_IMAGE_ASPECT_COLOR_BIT : VK_IMAGE_ASPECT_DEPTH_BIT;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+ barrier.oldLayout = s.layout; // new textures have this set to PREINITIALIZED
+ barrier.newLayout = layout;
+ barrier.srcAccessMask = s.access; // may be 0 but that's fine
+ barrier.dstAccessMask = access;
+ barrier.image = texD->image;
+
+ VkPipelineStageFlags srcStage = s.stage;
+ // stage mask cannot be 0
+ if (!srcStage)
+ srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::ImageBarrier;
+ cmd.args.imageBarrier.srcStageMask = srcStage;
+ cmd.args.imageBarrier.dstStageMask = stage;
+ cmd.args.imageBarrier.desc = barrier;
+ cbD->commands.append(cmd);
+
+ s.layout = layout;
+ s.access = access;
+ s.stage = stage;
+}
+
+void QRhiVulkan::subresourceBarrier(QVkCommandBuffer *cbD, VkImage image,
+ VkImageLayout oldLayout, VkImageLayout newLayout,
+ VkAccessFlags srcAccess, VkAccessFlags dstAccess,
+ VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage,
+ int startLayer, int layerCount,
+ int startLevel, int levelCount)
+{
+ Q_ASSERT(!inPass);
+ 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.baseMipLevel = startLevel;
+ barrier.subresourceRange.levelCount = levelCount;
+ barrier.subresourceRange.baseArrayLayer = startLayer;
+ barrier.subresourceRange.layerCount = layerCount;
+ barrier.oldLayout = oldLayout;
+ barrier.newLayout = newLayout;
+ barrier.srcAccessMask = srcAccess;
+ barrier.dstAccessMask = dstAccess;
+ barrier.image = image;
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::ImageBarrier;
+ cmd.args.imageBarrier.srcStageMask = srcStage;
+ cmd.args.imageBarrier.dstStageMask = dstStage;
+ cmd.args.imageBarrier.desc = barrier;
+ cbD->commands.append(cmd);
+}
+
+VkDeviceSize QRhiVulkan::subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const
+{
+ VkDeviceSize size = 0;
+ const qsizetype imageSizeBytes = subresDesc.image().isNull() ?
+ subresDesc.data().size() : subresDesc.image().sizeInBytes();
+ if (imageSizeBytes > 0)
+ size += aligned(imageSizeBytes, texbufAlign);
+ return size;
+}
+
+void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
+ const QRhiTextureSubresourceUploadDescription &subresDesc,
+ size_t *curOfs, void *mp,
+ BufferImageCopyList *copyInfos)
+{
+ qsizetype copySizeBytes = 0;
+ qsizetype imageSizeBytes = 0;
+ const void *src = nullptr;
+
+ VkBufferImageCopy copyInfo;
+ memset(&copyInfo, 0, sizeof(copyInfo));
+ copyInfo.bufferOffset = *curOfs;
+ copyInfo.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyInfo.imageSubresource.mipLevel = level;
+ copyInfo.imageSubresource.baseArrayLayer = layer;
+ copyInfo.imageSubresource.layerCount = 1;
+ copyInfo.imageExtent.depth = 1;
+
+ const QByteArray rawData = subresDesc.data();
+ const QPoint dp = subresDesc.destinationTopLeft();
+ QImage image = subresDesc.image();
+ if (!image.isNull()) {
+ copySizeBytes = imageSizeBytes = image.sizeInBytes();
+ QSize size = image.size();
+ src = image.constBits();
+ // Scanlines in QImage are 4 byte aligned so bpl must
+ // be taken into account for bufferRowLength.
+ int bpc = qMax(1, image.depth() / 8);
+ // this is in pixels, not bytes, to make it more complicated...
+ copyInfo.bufferRowLength = image.bytesPerLine() / bpc;
+ if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
+ const int sx = subresDesc.sourceTopLeft().x();
+ const int sy = subresDesc.sourceTopLeft().y();
+ if (!subresDesc.sourceSize().isEmpty())
+ size = subresDesc.sourceSize();
+ if (image.depth() == 32) {
+ // The staging buffer will get the full image
+ // regardless, just adjust the vk
+ // buffer-to-image copy start offset.
+ copyInfo.bufferOffset += sy * image.bytesPerLine() + sx * 4;
+ // bufferRowLength remains set to the original image's width
+ } else {
+ image = image.copy(sx, sy, size.width(), size.height());
+ src = image.constBits();
+ // The staging buffer gets the slice only. The rest of the
+ // space reserved for this mip will be unused.
+ copySizeBytes = image.sizeInBytes();
+ bpc = qMax(1, image.depth() / 8);
+ copyInfo.bufferRowLength = image.bytesPerLine() / bpc;
+ }
+ }
+ copyInfo.imageOffset.x = dp.x();
+ copyInfo.imageOffset.y = dp.y();
+ copyInfo.imageExtent.width = size.width();
+ copyInfo.imageExtent.height = size.height();
+ copyInfos->append(copyInfo);
+ } else if (!rawData.isEmpty() && isCompressedFormat(texD->m_format)) {
+ copySizeBytes = imageSizeBytes = rawData.size();
+ src = rawData.constData();
+ QSize size = q->sizeForMipLevel(level, texD->m_pixelSize);
+ const int subresw = size.width();
+ const int subresh = size.height();
+ if (!subresDesc.sourceSize().isEmpty())
+ size = subresDesc.sourceSize();
+ const int w = size.width();
+ const int h = size.height();
+ QSize blockDim;
+ compressedFormatInfo(texD->m_format, QSize(w, h), nullptr, nullptr, &blockDim);
+ // x and y must be multiples of the block width and height
+ copyInfo.imageOffset.x = aligned(dp.x(), blockDim.width());
+ copyInfo.imageOffset.y = aligned(dp.y(), blockDim.height());
+ // width and height must be multiples of the block width and height
+ // or x + width and y + height must equal the subresource width and height
+ copyInfo.imageExtent.width = dp.x() + w == subresw ? w : aligned(w, blockDim.width());
+ copyInfo.imageExtent.height = dp.y() + h == subresh ? h : aligned(h, blockDim.height());
+ copyInfos->append(copyInfo);
+ } else if (!rawData.isEmpty()) {
+ copySizeBytes = imageSizeBytes = rawData.size();
+ src = rawData.constData();
+ QSize size = q->sizeForMipLevel(level, texD->m_pixelSize);
+ if (!subresDesc.sourceSize().isEmpty())
+ size = subresDesc.sourceSize();
+ copyInfo.imageOffset.x = dp.x();
+ copyInfo.imageOffset.y = dp.y();
+ copyInfo.imageExtent.width = size.width();
+ copyInfo.imageExtent.height = size.height();
+ copyInfos->append(copyInfo);
+ } else {
+ qWarning("Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
+ }
+
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, src, copySizeBytes);
+ *curOfs += aligned(imageSizeBytes, texbufAlign);
+}
+
+void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+
+ for (const QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate &u : ud->dynamicBufferUpdates) {
+ QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
+ Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
+ bufD->pendingDynamicUpdates[i].append(u);
+ }
+
+ for (const QRhiResourceUpdateBatchPrivate::StaticBufferUpload &u : ud->staticBufferUploads) {
+ QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
+ Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
+ Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
+
+ if (!bufD->stagingBuffers[currentFrameSlot]) {
+ VkBufferCreateInfo bufferInfo;
+ memset(&bufferInfo, 0, sizeof(bufferInfo));
+ bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ // must cover the entire buffer - this way multiple, partial updates per frame
+ // are supported even when the staging buffer is reused (Static)
+ bufferInfo.size = bufD->m_size;
+ bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+ VmaAllocationCreateInfo allocInfo;
+ memset(&allocInfo, 0, sizeof(allocInfo));
+ allocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+
+ VmaAllocation allocation;
+ VkResult err = vmaCreateBuffer(toVmaAllocator(allocator), &bufferInfo, &allocInfo,
+ &bufD->stagingBuffers[currentFrameSlot], &allocation, nullptr);
+ if (err == VK_SUCCESS) {
+ bufD->stagingAllocations[currentFrameSlot] = allocation;
+ QRHI_PROF_F(newBufferStagingArea(bufD, currentFrameSlot, bufD->m_size));
+ } else {
+ qWarning("Failed to create staging buffer of size %d: %d", bufD->m_size, err);
+ continue;
+ }
+ }
+
+ void *p = nullptr;
+ VmaAllocation a = toVmaAllocation(bufD->stagingAllocations[currentFrameSlot]);
+ VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to map buffer: %d", err);
+ continue;
+ }
+ memcpy(static_cast<uchar *>(p) + u.offset, u.data.constData(), u.data.size());
+ vmaUnmapMemory(toVmaAllocator(allocator), a);
+ vmaFlushAllocation(toVmaAllocator(allocator), a, u.offset, u.data.size());
+
+ trackedBufferBarrier(cbD, bufD, 0,
+ VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkBufferCopy copyInfo;
+ memset(&copyInfo, 0, sizeof(copyInfo));
+ copyInfo.srcOffset = u.offset;
+ copyInfo.dstOffset = u.offset;
+ copyInfo.size = u.data.size();
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::CopyBuffer;
+ cmd.args.copyBuffer.src = bufD->stagingBuffers[currentFrameSlot];
+ cmd.args.copyBuffer.dst = bufD->buffers[0];
+ cmd.args.copyBuffer.desc = copyInfo;
+ cbD->commands.append(cmd);
+
+ // Where's the barrier for read-after-write? (assuming the common case
+ // of binding this buffer as vertex/index, or, less likely, as uniform
+ // buffer, in a renderpass later on) That is handled by the pass
+ // resource tracking: the appropriate pipeline barrier will be
+ // generated and recorded right before the renderpass, that binds this
+ // buffer in one of its commands, gets its BeginRenderPass recorded.
+
+ bufD->lastActiveFrameSlot = currentFrameSlot;
+
+ if (bufD->m_type == QRhiBuffer::Immutable) {
+ QRhiVulkan::DeferredReleaseEntry e;
+ e.type = QRhiVulkan::DeferredReleaseEntry::StagingBuffer;
+ e.lastActiveFrameSlot = currentFrameSlot;
+ e.stagingBuffer.stagingBuffer = bufD->stagingBuffers[currentFrameSlot];
+ e.stagingBuffer.stagingAllocation = bufD->stagingAllocations[currentFrameSlot];
+ bufD->stagingBuffers[currentFrameSlot] = VK_NULL_HANDLE;
+ bufD->stagingAllocations[currentFrameSlot] = nullptr;
+ releaseQueue.append(e);
+ QRHI_PROF_F(releaseBufferStagingArea(bufD, currentFrameSlot));
+ }
+ }
+
+ for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
+ if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
+ QVkTexture *utexD = QRHI_RES(QVkTexture, u.upload.tex);
+ // batch into a single staging buffer and a single CopyBufferToImage with multiple copyInfos
+ VkDeviceSize stagingSize = 0;
+ for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
+ for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.upload.subresDesc[layer][level]))
+ stagingSize += subresUploadByteSize(subresDesc);
+ }
+ }
+
+ Q_ASSERT(!utexD->stagingBuffers[currentFrameSlot]);
+ VkBufferCreateInfo bufferInfo;
+ memset(&bufferInfo, 0, sizeof(bufferInfo));
+ bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ bufferInfo.size = stagingSize;
+ bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+ VmaAllocationCreateInfo allocInfo;
+ memset(&allocInfo, 0, sizeof(allocInfo));
+ allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
+
+ VmaAllocation allocation;
+ VkResult err = vmaCreateBuffer(toVmaAllocator(allocator), &bufferInfo, &allocInfo,
+ &utexD->stagingBuffers[currentFrameSlot], &allocation, nullptr);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create image staging buffer of size %d: %d", int(stagingSize), err);
+ continue;
+ }
+ utexD->stagingAllocations[currentFrameSlot] = allocation;
+ QRHI_PROF_F(newTextureStagingArea(utexD, currentFrameSlot, stagingSize));
+
+ BufferImageCopyList copyInfos;
+ size_t curOfs = 0;
+ void *mp = nullptr;
+ VmaAllocation a = toVmaAllocation(utexD->stagingAllocations[currentFrameSlot]);
+ err = vmaMapMemory(toVmaAllocator(allocator), a, &mp);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to map image data: %d", err);
+ continue;
+ }
+
+ for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
+ for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
+ const QVector<QRhiTextureSubresourceUploadDescription> &srd(u.upload.subresDesc[layer][level]);
+ if (srd.isEmpty())
+ continue;
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(srd)) {
+ prepareUploadSubres(utexD, layer, level,
+ subresDesc, &curOfs, mp, &copyInfos);
+ }
+ }
+ }
+ vmaUnmapMemory(toVmaAllocator(allocator), a);
+ vmaFlushAllocation(toVmaAllocator(allocator), a, 0, stagingSize);
+
+ trackedImageBarrier(cbD, utexD, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::CopyBufferToImage;
+ cmd.args.copyBufferToImage.src = utexD->stagingBuffers[currentFrameSlot];
+ cmd.args.copyBufferToImage.dst = utexD->image;
+ cmd.args.copyBufferToImage.dstLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ cmd.args.copyBufferToImage.count = copyInfos.count();
+ cmd.args.copyBufferToImage.bufferImageCopyIndex = cbD->pools.bufferImageCopy.count();
+ cbD->pools.bufferImageCopy.append(copyInfos.constData(), copyInfos.count());
+ cbD->commands.append(cmd);
+
+ // no reuse of staging, this is intentional
+ QRhiVulkan::DeferredReleaseEntry e;
+ e.type = QRhiVulkan::DeferredReleaseEntry::StagingBuffer;
+ e.lastActiveFrameSlot = currentFrameSlot;
+ e.stagingBuffer.stagingBuffer = utexD->stagingBuffers[currentFrameSlot];
+ e.stagingBuffer.stagingAllocation = utexD->stagingAllocations[currentFrameSlot];
+ utexD->stagingBuffers[currentFrameSlot] = VK_NULL_HANDLE;
+ utexD->stagingAllocations[currentFrameSlot] = nullptr;
+ releaseQueue.append(e);
+ QRHI_PROF_F(releaseTextureStagingArea(utexD, currentFrameSlot));
+
+ // Similarly to buffers, transitioning away from DST is done later,
+ // when a renderpass using the texture is encountered.
+
+ utexD->lastActiveFrameSlot = currentFrameSlot;
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Copy) {
+ Q_ASSERT(u.copy.src && u.copy.dst);
+ if (u.copy.src == u.copy.dst) {
+ qWarning("Texture copy with matching source and destination is not supported");
+ continue;
+ }
+ QVkTexture *srcD = QRHI_RES(QVkTexture, u.copy.src);
+ QVkTexture *dstD = QRHI_RES(QVkTexture, u.copy.dst);
+
+ VkImageCopy region;
+ memset(&region, 0, sizeof(region));
+
+ region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ region.srcSubresource.mipLevel = u.copy.desc.sourceLevel();
+ region.srcSubresource.baseArrayLayer = u.copy.desc.sourceLayer();
+ region.srcSubresource.layerCount = 1;
+
+ region.srcOffset.x = u.copy.desc.sourceTopLeft().x();
+ region.srcOffset.y = u.copy.desc.sourceTopLeft().y();
+
+ region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ region.dstSubresource.mipLevel = u.copy.desc.destinationLevel();
+ region.dstSubresource.baseArrayLayer = u.copy.desc.destinationLayer();
+ region.dstSubresource.layerCount = 1;
+
+ region.dstOffset.x = u.copy.desc.destinationTopLeft().x();
+ region.dstOffset.y = u.copy.desc.destinationTopLeft().y();
+
+ const QSize size = u.copy.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.copy.desc.pixelSize();
+ region.extent.width = size.width();
+ region.extent.height = size.height();
+ region.extent.depth = 1;
+
+ trackedImageBarrier(cbD, srcD, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ trackedImageBarrier(cbD, dstD, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::CopyImage;
+ cmd.args.copyImage.src = srcD->image;
+ cmd.args.copyImage.srcLayout = srcD->usageState.layout;
+ cmd.args.copyImage.dst = dstD->image;
+ cmd.args.copyImage.dstLayout = dstD->usageState.layout;
+ cmd.args.copyImage.desc = region;
+ cbD->commands.append(cmd);
+
+ srcD->lastActiveFrameSlot = dstD->lastActiveFrameSlot = currentFrameSlot;
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) {
+ ActiveReadback aRb;
+ aRb.activeFrameSlot = currentFrameSlot;
+ aRb.desc = u.read.rb;
+ aRb.result = u.read.result;
+
+ QVkTexture *texD = QRHI_RES(QVkTexture, u.read.rb.texture());
+ QVkSwapChain *swapChainD = nullptr;
+ if (texD) {
+ if (texD->samples > VK_SAMPLE_COUNT_1_BIT) {
+ qWarning("Multisample texture cannot be read back");
+ continue;
+ }
+ aRb.pixelSize = u.read.rb.level() > 0 ? q->sizeForMipLevel(u.read.rb.level(), texD->m_pixelSize)
+ : texD->m_pixelSize;
+ aRb.format = texD->m_format;
+ texD->lastActiveFrameSlot = currentFrameSlot;
+ } else {
+ Q_ASSERT(currentSwapChain);
+ swapChainD = QRHI_RES(QVkSwapChain, currentSwapChain);
+ if (!swapChainD->supportsReadback) {
+ qWarning("Swapchain does not support readback");
+ continue;
+ }
+ aRb.pixelSize = swapChainD->pixelSize;
+ aRb.format = colorTextureFormatFromVkFormat(swapChainD->colorFormat, nullptr);
+ if (aRb.format == QRhiTexture::UnknownFormat)
+ continue;
+
+ // Multisample swapchains need nothing special since resolving
+ // happens when ending a renderpass.
+ }
+ textureFormatInfo(aRb.format, aRb.pixelSize, nullptr, &aRb.bufSize);
+
+ // Create a host visible buffer.
+ VkBufferCreateInfo bufferInfo;
+ memset(&bufferInfo, 0, sizeof(bufferInfo));
+ bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ bufferInfo.size = aRb.bufSize;
+ bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+ VmaAllocationCreateInfo allocInfo;
+ memset(&allocInfo, 0, sizeof(allocInfo));
+ allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
+
+ VmaAllocation allocation;
+ VkResult err = vmaCreateBuffer(toVmaAllocator(allocator), &bufferInfo, &allocInfo, &aRb.buf, &allocation, nullptr);
+ if (err == VK_SUCCESS) {
+ aRb.bufAlloc = allocation;
+ QRHI_PROF_F(newReadbackBuffer(quint64(aRb.buf),
+ texD ? static_cast<QRhiResource *>(texD) : static_cast<QRhiResource *>(swapChainD),
+ aRb.bufSize));
+ } else {
+ qWarning("Failed to create readback buffer of size %u: %d", aRb.bufSize, err);
+ continue;
+ }
+
+ // Copy from the (optimal and not host visible) image into the buffer.
+ VkBufferImageCopy copyDesc;
+ memset(&copyDesc, 0, sizeof(copyDesc));
+ copyDesc.bufferOffset = 0;
+ copyDesc.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyDesc.imageSubresource.mipLevel = u.read.rb.level();
+ copyDesc.imageSubresource.baseArrayLayer = u.read.rb.layer();
+ copyDesc.imageSubresource.layerCount = 1;
+ copyDesc.imageExtent.width = aRb.pixelSize.width();
+ copyDesc.imageExtent.height = aRb.pixelSize.height();
+ copyDesc.imageExtent.depth = 1;
+
+ if (texD) {
+ trackedImageBarrier(cbD, texD, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::CopyImageToBuffer;
+ cmd.args.copyImageToBuffer.src = texD->image;
+ cmd.args.copyImageToBuffer.srcLayout = texD->usageState.layout;
+ cmd.args.copyImageToBuffer.dst = aRb.buf;
+ cmd.args.copyImageToBuffer.desc = copyDesc;
+ cbD->commands.append(cmd);
+ } else {
+ // use the swapchain image
+ VkImage image = swapChainD->imageRes[swapChainD->currentImageIndex].image;
+ if (!swapChainD->imageRes[swapChainD->currentImageIndex].transferSource) {
+ subresourceBarrier(cbD, image,
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, 1,
+ 0, 1);
+ swapChainD->imageRes[swapChainD->currentImageIndex].transferSource = true;
+ }
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::CopyImageToBuffer;
+ cmd.args.copyImageToBuffer.src = image;
+ cmd.args.copyImageToBuffer.srcLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ cmd.args.copyImageToBuffer.dst = aRb.buf;
+ cmd.args.copyImageToBuffer.desc = copyDesc;
+ cbD->commands.append(cmd);
+ }
+
+ activeReadbacks.append(aRb);
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::MipGen) {
+ QVkTexture *utexD = QRHI_RES(QVkTexture, u.mipgen.tex);
+ Q_ASSERT(utexD->m_flags.testFlag(QRhiTexture::UsedWithGenerateMips));
+ int w = utexD->m_pixelSize.width();
+ int h = utexD->m_pixelSize.height();
+
+ VkImageLayout origLayout = utexD->usageState.layout;
+ VkAccessFlags origAccess = utexD->usageState.access;
+ VkPipelineStageFlags origStage = utexD->usageState.stage;
+ if (!origStage)
+ origStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+
+ for (uint level = 1; level < utexD->mipLevelCount; ++level) {
+ if (level == 1) {
+ subresourceBarrier(cbD, utexD->image,
+ origLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ origAccess, VK_ACCESS_TRANSFER_READ_BIT,
+ origStage, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ u.mipgen.layer, 1,
+ level - 1, 1);
+ } else {
+ subresourceBarrier(cbD, utexD->image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ u.mipgen.layer, 1,
+ level - 1, 1);
+ }
+
+ subresourceBarrier(cbD, utexD->image,
+ origLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ origAccess, VK_ACCESS_TRANSFER_WRITE_BIT,
+ origStage, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ u.mipgen.layer, 1,
+ level, 1);
+
+ VkImageBlit region;
+ memset(&region, 0, sizeof(region));
+
+ region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ region.srcSubresource.mipLevel = level - 1;
+ region.srcSubresource.baseArrayLayer = u.mipgen.layer;
+ region.srcSubresource.layerCount = 1;
+
+ region.srcOffsets[1].x = qMax(1, w);
+ region.srcOffsets[1].y = qMax(1, h);
+ region.srcOffsets[1].z = 1;
+
+ region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ region.dstSubresource.mipLevel = level;
+ region.dstSubresource.baseArrayLayer = u.mipgen.layer;
+ region.dstSubresource.layerCount = 1;
+
+ region.dstOffsets[1].x = qMax(1, w >> 1);
+ region.dstOffsets[1].y = qMax(1, h >> 1);
+ region.dstOffsets[1].z = 1;
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::BlitImage;
+ cmd.args.blitImage.src = utexD->image;
+ cmd.args.blitImage.srcLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ cmd.args.blitImage.dst = utexD->image;
+ cmd.args.blitImage.dstLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ cmd.args.blitImage.filter = VK_FILTER_LINEAR;
+ cmd.args.blitImage.desc = region;
+ cbD->commands.append(cmd);
+
+ w >>= 1;
+ h >>= 1;
+ }
+
+ if (utexD->mipLevelCount > 1) {
+ subresourceBarrier(cbD, utexD->image,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, origLayout,
+ VK_ACCESS_TRANSFER_READ_BIT, origAccess,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, origStage,
+ u.mipgen.layer, 1,
+ 0, utexD->mipLevelCount - 1);
+ subresourceBarrier(cbD, utexD->image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, origLayout,
+ VK_ACCESS_TRANSFER_WRITE_BIT, origAccess,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, origStage,
+ u.mipgen.layer, 1,
+ utexD->mipLevelCount - 1, 1);
+ }
+
+ utexD->lastActiveFrameSlot = currentFrameSlot;
+ }
+ }
+
+ ud->free();
+}
+
+void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
+{
+ QVector<QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate> &updates(bufD->pendingDynamicUpdates[currentFrameSlot]);
+ if (updates.isEmpty())
+ return;
+
+ Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
+ void *p = nullptr;
+ VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]);
+ // The vmaMap/Unmap are basically a no-op when persistently mapped since it
+ // refcounts; this is great because we don't need to care if the allocation
+ // was created as persistently mapped or not.
+ VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to map buffer: %d", err);
+ return;
+ }
+ int changeBegin = -1;
+ int changeEnd = -1;
+ for (const QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate &u : updates) {
+ Q_ASSERT(bufD == QRHI_RES(QVkBuffer, u.buf));
+ memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), u.data.size());
+ if (changeBegin == -1 || u.offset < changeBegin)
+ changeBegin = u.offset;
+ if (changeEnd == -1 || u.offset + u.data.size() > changeEnd)
+ changeEnd = u.offset + u.data.size();
+ }
+ vmaUnmapMemory(toVmaAllocator(allocator), a);
+ if (changeBegin >= 0)
+ vmaFlushAllocation(toVmaAllocator(allocator), a, changeBegin, changeEnd - changeBegin);
+
+ updates.clear();
+}
+
+static void qrhivk_releaseBuffer(const QRhiVulkan::DeferredReleaseEntry &e, void *allocator)
+{
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ vmaDestroyBuffer(toVmaAllocator(allocator), e.buffer.buffers[i], toVmaAllocation(e.buffer.allocations[i]));
+ vmaDestroyBuffer(toVmaAllocator(allocator), e.buffer.stagingBuffers[i], toVmaAllocation(e.buffer.stagingAllocations[i]));
+ }
+}
+
+static void qrhivk_releaseRenderBuffer(const QRhiVulkan::DeferredReleaseEntry &e, VkDevice dev, QVulkanDeviceFunctions *df)
+{
+ df->vkDestroyImageView(dev, e.renderBuffer.imageView, nullptr);
+ df->vkDestroyImage(dev, e.renderBuffer.image, nullptr);
+ df->vkFreeMemory(dev, e.renderBuffer.memory, nullptr);
+}
+
+static void qrhivk_releaseTexture(const QRhiVulkan::DeferredReleaseEntry &e, VkDevice dev, QVulkanDeviceFunctions *df, void *allocator)
+{
+ df->vkDestroyImageView(dev, e.texture.imageView, nullptr);
+ vmaDestroyImage(toVmaAllocator(allocator), e.texture.image, toVmaAllocation(e.texture.allocation));
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
+ vmaDestroyBuffer(toVmaAllocator(allocator), e.texture.stagingBuffers[i], toVmaAllocation(e.texture.stagingAllocations[i]));
+}
+
+static void qrhivk_releaseSampler(const QRhiVulkan::DeferredReleaseEntry &e, VkDevice dev, QVulkanDeviceFunctions *df)
+{
+ df->vkDestroySampler(dev, e.sampler.sampler, nullptr);
+}
+
+void QRhiVulkan::executeDeferredReleases(bool forced)
+{
+ for (int i = releaseQueue.count() - 1; i >= 0; --i) {
+ const QRhiVulkan::DeferredReleaseEntry &e(releaseQueue[i]);
+ if (forced || currentFrameSlot == e.lastActiveFrameSlot || e.lastActiveFrameSlot < 0) {
+ switch (e.type) {
+ case QRhiVulkan::DeferredReleaseEntry::Pipeline:
+ df->vkDestroyPipeline(dev, e.pipelineState.pipeline, nullptr);
+ df->vkDestroyPipelineLayout(dev, e.pipelineState.layout, nullptr);
+ break;
+ case QRhiVulkan::DeferredReleaseEntry::ShaderResourceBindings:
+ df->vkDestroyDescriptorSetLayout(dev, e.shaderResourceBindings.layout, nullptr);
+ if (e.shaderResourceBindings.poolIndex >= 0) {
+ descriptorPools[e.shaderResourceBindings.poolIndex].refCount -= 1;
+ Q_ASSERT(descriptorPools[e.shaderResourceBindings.poolIndex].refCount >= 0);
+ }
+ break;
+ case QRhiVulkan::DeferredReleaseEntry::Buffer:
+ qrhivk_releaseBuffer(e, allocator);
+ break;
+ case QRhiVulkan::DeferredReleaseEntry::RenderBuffer:
+ qrhivk_releaseRenderBuffer(e, dev, df);
+ break;
+ case QRhiVulkan::DeferredReleaseEntry::Texture:
+ qrhivk_releaseTexture(e, dev, df, allocator);
+ break;
+ case QRhiVulkan::DeferredReleaseEntry::Sampler:
+ qrhivk_releaseSampler(e, dev, df);
+ break;
+ case QRhiVulkan::DeferredReleaseEntry::TextureRenderTarget:
+ df->vkDestroyFramebuffer(dev, e.textureRenderTarget.fb, nullptr);
+ for (int att = 0; att < QVkRenderTargetData::MAX_COLOR_ATTACHMENTS; ++att) {
+ df->vkDestroyImageView(dev, e.textureRenderTarget.rtv[att], nullptr);
+ df->vkDestroyImageView(dev, e.textureRenderTarget.resrtv[att], nullptr);
+ }
+ break;
+ case QRhiVulkan::DeferredReleaseEntry::RenderPass:
+ df->vkDestroyRenderPass(dev, e.renderPass.rp, nullptr);
+ break;
+ case QRhiVulkan::DeferredReleaseEntry::StagingBuffer:
+ vmaDestroyBuffer(toVmaAllocator(allocator), e.stagingBuffer.stagingBuffer, toVmaAllocation(e.stagingBuffer.stagingAllocation));
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ releaseQueue.removeAt(i);
+ }
+ }
+}
+
+void QRhiVulkan::finishActiveReadbacks(bool forced)
+{
+ QVarLengthArray<std::function<void()>, 4> completedCallbacks;
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+
+ for (int i = activeReadbacks.count() - 1; i >= 0; --i) {
+ const QRhiVulkan::ActiveReadback &aRb(activeReadbacks[i]);
+ if (forced || currentFrameSlot == aRb.activeFrameSlot || aRb.activeFrameSlot < 0) {
+ aRb.result->format = aRb.format;
+ aRb.result->pixelSize = aRb.pixelSize;
+ aRb.result->data.resize(aRb.bufSize);
+ void *p = nullptr;
+ VmaAllocation a = toVmaAllocation(aRb.bufAlloc);
+ VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to map readback buffer: %d", err);
+ continue;
+ }
+ memcpy(aRb.result->data.data(), p, aRb.bufSize);
+ vmaUnmapMemory(toVmaAllocator(allocator), a);
+
+ vmaDestroyBuffer(toVmaAllocator(allocator), aRb.buf, a);
+ QRHI_PROF_F(releaseReadbackBuffer(quint64(aRb.buf)));
+
+ if (aRb.result->completed)
+ completedCallbacks.append(aRb.result->completed);
+
+ activeReadbacks.removeAt(i);
+ }
+ }
+
+ for (auto f : completedCallbacks)
+ f();
+}
+
+static struct {
+ VkSampleCountFlagBits mask;
+ int count;
+} qvk_sampleCounts[] = {
+ // keep this sorted by 'count'
+ { VK_SAMPLE_COUNT_1_BIT, 1 },
+ { VK_SAMPLE_COUNT_2_BIT, 2 },
+ { VK_SAMPLE_COUNT_4_BIT, 4 },
+ { VK_SAMPLE_COUNT_8_BIT, 8 },
+ { VK_SAMPLE_COUNT_16_BIT, 16 },
+ { VK_SAMPLE_COUNT_32_BIT, 32 },
+ { VK_SAMPLE_COUNT_64_BIT, 64 }
+};
+
+QVector<int> QRhiVulkan::supportedSampleCounts() const
+{
+ const VkPhysicalDeviceLimits *limits = &physDevProperties.limits;
+ VkSampleCountFlags color = limits->framebufferColorSampleCounts;
+ VkSampleCountFlags depth = limits->framebufferDepthSampleCounts;
+ VkSampleCountFlags stencil = limits->framebufferStencilSampleCounts;
+ QVector<int> result;
+
+ for (size_t i = 0; i < sizeof(qvk_sampleCounts) / sizeof(qvk_sampleCounts[0]); ++i) {
+ if ((color & qvk_sampleCounts[i].mask)
+ && (depth & qvk_sampleCounts[i].mask)
+ && (stencil & qvk_sampleCounts[i].mask))
+ {
+ result.append(qvk_sampleCounts[i].count);
+ }
+ }
+
+ return result;
+}
+
+VkSampleCountFlagBits QRhiVulkan::effectiveSampleCount(int sampleCount)
+{
+ // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
+ sampleCount = qBound(1, sampleCount, 64);
+
+ if (!supportedSampleCounts().contains(sampleCount)) {
+ qWarning("Attempted to set unsupported sample count %d", sampleCount);
+ return VK_SAMPLE_COUNT_1_BIT;
+ }
+
+ for (size_t i = 0; i < sizeof(qvk_sampleCounts) / sizeof(qvk_sampleCounts[0]); ++i) {
+ if (qvk_sampleCounts[i].count == sampleCount)
+ return qvk_sampleCounts[i].mask;
+ }
+
+ Q_UNREACHABLE();
+ return VK_SAMPLE_COUNT_1_BIT;
+}
+
+void QRhiVulkan::enqueueTransitionPassResources(QVkCommandBuffer *cbD)
+{
+ cbD->passResTrackers.append(QRhiPassResourceTracker());
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::TransitionPassResources;
+ cmd.args.transitionResources.trackerIndex = cbD->passResTrackers.count() - 1;
+ cbD->commands.append(cmd);
+ cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1;
+}
+
+void QRhiVulkan::recordCommandBuffer(QVkCommandBuffer *cbD)
+{
+ for (QVkCommandBuffer::Command &cmd : cbD->commands) {
+ switch (cmd.cmd) {
+ case QVkCommandBuffer::Command::CopyBuffer:
+ df->vkCmdCopyBuffer(cbD->cb, cmd.args.copyBuffer.src, cmd.args.copyBuffer.dst,
+ 1, &cmd.args.copyBuffer.desc);
+ break;
+ case QVkCommandBuffer::Command::CopyBufferToImage:
+ df->vkCmdCopyBufferToImage(cbD->cb, cmd.args.copyBufferToImage.src, cmd.args.copyBufferToImage.dst,
+ cmd.args.copyBufferToImage.dstLayout,
+ cmd.args.copyBufferToImage.count,
+ cbD->pools.bufferImageCopy.constData() + cmd.args.copyBufferToImage.bufferImageCopyIndex);
+ break;
+ case QVkCommandBuffer::Command::CopyImage:
+ df->vkCmdCopyImage(cbD->cb, cmd.args.copyImage.src, cmd.args.copyImage.srcLayout,
+ cmd.args.copyImage.dst, cmd.args.copyImage.dstLayout,
+ 1, &cmd.args.copyImage.desc);
+ break;
+ case QVkCommandBuffer::Command::CopyImageToBuffer:
+ df->vkCmdCopyImageToBuffer(cbD->cb, cmd.args.copyImageToBuffer.src, cmd.args.copyImageToBuffer.srcLayout,
+ cmd.args.copyImageToBuffer.dst,
+ 1, &cmd.args.copyImageToBuffer.desc);
+ break;
+ case QVkCommandBuffer::Command::ImageBarrier:
+ df->vkCmdPipelineBarrier(cbD->cb, cmd.args.imageBarrier.srcStageMask, cmd.args.imageBarrier.dstStageMask,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &cmd.args.imageBarrier.desc);
+ break;
+ case QVkCommandBuffer::Command::BufferBarrier:
+ df->vkCmdPipelineBarrier(cbD->cb, cmd.args.bufferBarrier.srcStageMask, cmd.args.bufferBarrier.dstStageMask,
+ 0, 0, nullptr,
+ 1, &cmd.args.bufferBarrier.desc,
+ 0, nullptr);
+ break;
+ case QVkCommandBuffer::Command::BlitImage:
+ df->vkCmdBlitImage(cbD->cb, cmd.args.blitImage.src, cmd.args.blitImage.srcLayout,
+ cmd.args.blitImage.dst, cmd.args.blitImage.dstLayout,
+ 1, &cmd.args.blitImage.desc,
+ cmd.args.blitImage.filter);
+ break;
+ case QVkCommandBuffer::Command::BeginRenderPass:
+ cmd.args.beginRenderPass.desc.pClearValues = cbD->pools.clearValue.constData() + cmd.args.beginRenderPass.clearValueIndex;
+ df->vkCmdBeginRenderPass(cbD->cb, &cmd.args.beginRenderPass.desc, VK_SUBPASS_CONTENTS_INLINE);
+ break;
+ case QVkCommandBuffer::Command::EndRenderPass:
+ df->vkCmdEndRenderPass(cbD->cb);
+ break;
+ case QVkCommandBuffer::Command::BindPipeline:
+ df->vkCmdBindPipeline(cbD->cb, cmd.args.bindPipeline.bindPoint, cmd.args.bindPipeline.pipeline);
+ break;
+ case QVkCommandBuffer::Command::BindDescriptorSet:
+ {
+ const uint32_t *offsets = nullptr;
+ if (cmd.args.bindDescriptorSet.dynamicOffsetCount > 0)
+ offsets = cbD->pools.dynamicOffset.constData() + cmd.args.bindDescriptorSet.dynamicOffsetIndex;
+ df->vkCmdBindDescriptorSets(cbD->cb, cmd.args.bindDescriptorSet.bindPoint,
+ cmd.args.bindDescriptorSet.pipelineLayout,
+ 0, 1, &cmd.args.bindDescriptorSet.descSet,
+ cmd.args.bindDescriptorSet.dynamicOffsetCount,
+ offsets);
+ }
+ break;
+ case QVkCommandBuffer::Command::BindVertexBuffer:
+ df->vkCmdBindVertexBuffers(cbD->cb, cmd.args.bindVertexBuffer.startBinding,
+ cmd.args.bindVertexBuffer.count,
+ cbD->pools.vertexBuffer.constData() + cmd.args.bindVertexBuffer.vertexBufferIndex,
+ cbD->pools.vertexBufferOffset.constData() + cmd.args.bindVertexBuffer.vertexBufferOffsetIndex);
+ break;
+ case QVkCommandBuffer::Command::BindIndexBuffer:
+ df->vkCmdBindIndexBuffer(cbD->cb, cmd.args.bindIndexBuffer.buf,
+ cmd.args.bindIndexBuffer.ofs, cmd.args.bindIndexBuffer.type);
+ break;
+ case QVkCommandBuffer::Command::SetViewport:
+ df->vkCmdSetViewport(cbD->cb, 0, 1, &cmd.args.setViewport.viewport);
+ break;
+ case QVkCommandBuffer::Command::SetScissor:
+ df->vkCmdSetScissor(cbD->cb, 0, 1, &cmd.args.setScissor.scissor);
+ break;
+ case QVkCommandBuffer::Command::SetBlendConstants:
+ df->vkCmdSetBlendConstants(cbD->cb, cmd.args.setBlendConstants.c);
+ break;
+ case QVkCommandBuffer::Command::SetStencilRef:
+ df->vkCmdSetStencilReference(cbD->cb, VK_STENCIL_FRONT_AND_BACK, cmd.args.setStencilRef.ref);
+ break;
+ case QVkCommandBuffer::Command::Draw:
+ df->vkCmdDraw(cbD->cb, cmd.args.draw.vertexCount, cmd.args.draw.instanceCount,
+ cmd.args.draw.firstVertex, cmd.args.draw.firstInstance);
+ break;
+ case QVkCommandBuffer::Command::DrawIndexed:
+ df->vkCmdDrawIndexed(cbD->cb, cmd.args.drawIndexed.indexCount, cmd.args.drawIndexed.instanceCount,
+ cmd.args.drawIndexed.firstIndex, cmd.args.drawIndexed.vertexOffset,
+ cmd.args.drawIndexed.firstInstance);
+ break;
+ case QVkCommandBuffer::Command::DebugMarkerBegin:
+ cmd.args.debugMarkerBegin.marker.pMarkerName =
+ cbD->pools.debugMarkerName[cmd.args.debugMarkerBegin.markerNameIndex].constData();
+ vkCmdDebugMarkerBegin(cbD->cb, &cmd.args.debugMarkerBegin.marker);
+ break;
+ case QVkCommandBuffer::Command::DebugMarkerEnd:
+ vkCmdDebugMarkerEnd(cbD->cb);
+ break;
+ case QVkCommandBuffer::Command::DebugMarkerInsert:
+ vkCmdDebugMarkerInsert(cbD->cb, &cmd.args.debugMarkerInsert.marker);
+ break;
+ case QVkCommandBuffer::Command::TransitionPassResources:
+ recordTransitionPassResources(cbD, cbD->passResTrackers[cmd.args.transitionResources.trackerIndex]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ cbD->resetCommands();
+}
+
+static inline VkAccessFlags toVkAccess(QRhiPassResourceTracker::BufferAccess access)
+{
+ switch (access) {
+ case QRhiPassResourceTracker::BufVertexInput:
+ return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
+ case QRhiPassResourceTracker::BufIndexRead:
+ return VK_ACCESS_INDEX_READ_BIT;
+ case QRhiPassResourceTracker::BufUniformRead:
+ return VK_ACCESS_UNIFORM_READ_BIT;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ return 0;
+}
+
+static inline VkPipelineStageFlags toVkPipelineStage(QRhiPassResourceTracker::BufferStage stage)
+{
+ switch (stage) {
+ case QRhiPassResourceTracker::BufVertexInputStage:
+ return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+ case QRhiPassResourceTracker::BufVertexStage:
+ return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
+ case QRhiPassResourceTracker::BufFragmentStage:
+ return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ return 0;
+}
+
+static inline QVkBuffer::UsageState toVkBufferUsageState(QRhiPassResourceTracker::UsageState usage)
+{
+ QVkBuffer::UsageState u;
+ u.access = usage.access;
+ u.stage = usage.stage;
+ return u;
+}
+
+static inline VkImageLayout toVkLayout(QRhiPassResourceTracker::TextureAccess access)
+{
+ switch (access) {
+ case QRhiPassResourceTracker::TexSample:
+ return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ case QRhiPassResourceTracker::TexColorOutput:
+ return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ case QRhiPassResourceTracker::TexDepthOutput:
+ return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ return VK_IMAGE_LAYOUT_GENERAL;
+}
+
+static inline VkAccessFlags toVkAccess(QRhiPassResourceTracker::TextureAccess access)
+{
+ switch (access) {
+ case QRhiPassResourceTracker::TexSample:
+ return VK_ACCESS_SHADER_READ_BIT;
+ case QRhiPassResourceTracker::TexColorOutput:
+ return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ case QRhiPassResourceTracker::TexDepthOutput:
+ return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ return 0;
+}
+
+static inline VkPipelineStageFlags toVkPipelineStage(QRhiPassResourceTracker::TextureStage stage)
+{
+ switch (stage) {
+ case QRhiPassResourceTracker::TexVertexStage:
+ return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
+ case QRhiPassResourceTracker::TexFragmentStage:
+ return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ case QRhiPassResourceTracker::TexColorOutputStage:
+ return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ case QRhiPassResourceTracker::TexDepthOutputStage:
+ return VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ return 0;
+}
+
+static inline QVkTexture::UsageState toVkTextureUsageState(QRhiPassResourceTracker::UsageState usage)
+{
+ QVkTexture::UsageState u;
+ u.layout = VkImageLayout(usage.layout);
+ u.access = usage.access;
+ u.stage = usage.stage;
+ return u;
+}
+
+void QRhiVulkan::trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
+ QVkBuffer *bufD,
+ int slot,
+ QRhiPassResourceTracker::BufferAccess access,
+ QRhiPassResourceTracker::BufferStage stage)
+{
+ QVkBuffer::UsageState &u(bufD->usageState[slot]);
+ // The last arg will get ignored if this buffer was already used in the
+ // same pass; that's good because u is not the state at pass start anymore
+ // at that point.
+ passResTracker->registerBufferOnce(bufD, slot, access, stage, toPassTrackerUsageState(u));
+ u.access = toVkAccess(access);
+ u.stage = toVkPipelineStage(stage);
+}
+
+void QRhiVulkan::trackedRegisterTexture(QRhiPassResourceTracker *passResTracker,
+ QVkTexture *texD,
+ QRhiPassResourceTracker::TextureAccess access,
+ QRhiPassResourceTracker::TextureStage stage)
+{
+ QVkTexture::UsageState &u(texD->usageState);
+ // The last arg will get ignored if this buffer was already used in the
+ // same pass; that's good because u is not the state at pass start anymore
+ // at that point.
+ passResTracker->registerTextureOnce(texD, access, stage, toPassTrackerUsageState(u));
+ u.layout = toVkLayout(access);
+ u.access = toVkAccess(access);
+ u.stage = toVkPipelineStage(stage);
+}
+
+void QRhiVulkan::recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhiPassResourceTracker &tracker)
+{
+ if (tracker.isEmpty())
+ return;
+
+ const QVector<QRhiPassResourceTracker::Buffer> *buffers = tracker.buffers();
+ for (const QRhiPassResourceTracker::Buffer &b : *buffers) {
+ QVkBuffer *bufD = QRHI_RES(QVkBuffer, b.buf);
+ VkAccessFlags access = toVkAccess(b.access);
+ VkPipelineStageFlags stage = toVkPipelineStage(b.stage);
+ QVkBuffer::UsageState s = toVkBufferUsageState(b.stateAtPassBegin);
+ if (!s.stage)
+ continue;
+ if (s.access == access && s.stage == stage) {
+ if (!accessIsWrite(access))
+ continue;
+ }
+ VkBufferMemoryBarrier bufMemBarrier;
+ memset(&bufMemBarrier, 0, sizeof(bufMemBarrier));
+ bufMemBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+ bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier.srcAccessMask = s.access;
+ bufMemBarrier.dstAccessMask = access;
+ bufMemBarrier.buffer = bufD->buffers[b.slot];
+ bufMemBarrier.size = VK_WHOLE_SIZE;
+ df->vkCmdPipelineBarrier(cbD->cb, s.stage, stage, 0,
+ 0, nullptr,
+ 1, &bufMemBarrier,
+ 0, nullptr);
+ }
+
+ const QVector<QRhiPassResourceTracker::Texture> *textures = tracker.textures();
+ for (const QRhiPassResourceTracker::Texture &t : *textures) {
+ QVkTexture *texD = QRHI_RES(QVkTexture, t.tex);
+ VkImageLayout layout = toVkLayout(t.access);
+ VkAccessFlags access = toVkAccess(t.access);
+ VkPipelineStageFlags stage = toVkPipelineStage(t.stage);
+ QVkTexture::UsageState s = toVkTextureUsageState(t.stateAtPassBegin);
+ if (s.access == access && s.stage == stage && s.layout == layout) {
+ if (!accessIsWrite(access))
+ continue;
+ }
+ VkImageMemoryBarrier barrier;
+ memset(&barrier, 0, sizeof(barrier));
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.subresourceRange.aspectMask = !isDepthTextureFormat(texD->m_format)
+ ? VK_IMAGE_ASPECT_COLOR_BIT : VK_IMAGE_ASPECT_DEPTH_BIT;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+ barrier.oldLayout = s.layout; // new textures have this set to PREINITIALIZED
+ barrier.newLayout = layout;
+ barrier.srcAccessMask = s.access; // may be 0 but that's fine
+ barrier.dstAccessMask = access;
+ barrier.image = texD->image;
+ VkPipelineStageFlags srcStage = s.stage;
+ // stage mask cannot be 0
+ if (!srcStage)
+ srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ df->vkCmdPipelineBarrier(cbD->cb, srcStage, stage, 0,
+ 0, nullptr,
+ 0, nullptr,
+ 1, &barrier);
+ }
+}
+
+QRhiSwapChain *QRhiVulkan::createSwapChain()
+{
+ return new QVkSwapChain(this);
+}
+
+QRhiBuffer *QRhiVulkan::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+{
+ return new QVkBuffer(this, type, usage, size);
+}
+
+int QRhiVulkan::ubufAlignment() const
+{
+ return ubufAlign; // typically 256 (bytes)
+}
+
+bool QRhiVulkan::isYUpInFramebuffer() const
+{
+ return false;
+}
+
+bool QRhiVulkan::isYUpInNDC() const
+{
+ return false;
+}
+
+bool QRhiVulkan::isClipDepthZeroToOne() const
+{
+ return true;
+}
+
+QMatrix4x4 QRhiVulkan::clipSpaceCorrMatrix() const
+{
+ // See https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/
+
+ static QMatrix4x4 m;
+ if (m.isIdentity()) {
+ // NB the ctor takes row-major
+ m = QMatrix4x4(1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 0.5f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ return m;
+}
+
+bool QRhiVulkan::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
+{
+ VkPhysicalDeviceFeatures features;
+ f->vkGetPhysicalDeviceFeatures(physDev, &features);
+
+ // Note that with some SDKs the validation layer gives an odd warning about
+ // BC not being supported, even when our check here succeeds. Not much we
+ // can do about that.
+ if (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7) {
+ if (!features.textureCompressionBC)
+ return false;
+ }
+
+ if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8) {
+ if (!features.textureCompressionETC2)
+ return false;
+ }
+
+ if (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12) {
+ if (!features.textureCompressionASTC_LDR)
+ return false;
+ }
+
+ VkFormat vkformat = toVkTextureFormat(format, flags);
+ VkFormatProperties props;
+ f->vkGetPhysicalDeviceFormatProperties(physDev, vkformat, &props);
+ return (props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0;
+}
+
+bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
+{
+ switch (feature) {
+ case QRhi::MultisampleTexture:
+ return true;
+ case QRhi::MultisampleRenderBuffer:
+ return true;
+ case QRhi::DebugMarkers:
+ return debugMarkersAvailable;
+ case QRhi::Timestamps:
+ return timestampValidBits != 0;
+ case QRhi::Instancing:
+ return true;
+ case QRhi::CustomInstanceStepRate:
+ return vertexAttribDivisorAvailable;
+ case QRhi::PrimitiveRestart:
+ return true;
+ case QRhi::NonDynamicUniformBuffers:
+ return true;
+ case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
+ return true;
+ case QRhi::NPOTTextureRepeat:
+ return true;
+ case QRhi::RedOrAlpha8IsRed:
+ return true;
+ case QRhi::ElementIndexUint:
+ return true;
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
+}
+
+int QRhiVulkan::resourceLimit(QRhi::ResourceLimit limit) const
+{
+ switch (limit) {
+ case QRhi::TextureSizeMin:
+ return 1;
+ case QRhi::TextureSizeMax:
+ return physDevProperties.limits.maxImageDimension2D;
+ case QRhi::MaxColorAttachments:
+ return physDevProperties.limits.maxColorAttachments;
+ case QRhi::FramesInFlight:
+ return QVK_FRAMES_IN_FLIGHT;
+ default:
+ Q_UNREACHABLE();
+ return 0;
+ }
+}
+
+const QRhiNativeHandles *QRhiVulkan::nativeHandles()
+{
+ return &nativeHandlesStruct;
+}
+
+void QRhiVulkan::sendVMemStatsToProfiler()
+{
+ QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+ if (!rhiP)
+ return;
+
+ VmaStats stats;
+ vmaCalculateStats(toVmaAllocator(allocator), &stats);
+ QRHI_PROF_F(vmemStat(stats.total.blockCount, stats.total.allocationCount,
+ stats.total.usedBytes, stats.total.unusedBytes));
+}
+
+QRhiRenderBuffer *QRhiVulkan::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags)
+{
+ return new QVkRenderBuffer(this, type, pixelSize, sampleCount, flags);
+}
+
+QRhiTexture *QRhiVulkan::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
+ int sampleCount, QRhiTexture::Flags flags)
+{
+ return new QVkTexture(this, format, pixelSize, sampleCount, flags);
+}
+
+QRhiSampler *QRhiVulkan::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+{
+ return new QVkSampler(this, magFilter, minFilter, mipmapMode, u, v);
+}
+
+QRhiTextureRenderTarget *QRhiVulkan::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags)
+{
+ return new QVkTextureRenderTarget(this, desc, flags);
+}
+
+QRhiGraphicsPipeline *QRhiVulkan::createGraphicsPipeline()
+{
+ return new QVkGraphicsPipeline(this);
+}
+
+QRhiShaderResourceBindings *QRhiVulkan::createShaderResourceBindings()
+{
+ return new QVkShaderResourceBindings(this);
+}
+
+void QRhiVulkan::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps)
+{
+ Q_ASSERT(inPass);
+ QVkGraphicsPipeline *psD = QRHI_RES(QVkGraphicsPipeline, ps);
+ Q_ASSERT(psD->pipeline);
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+
+ if (cbD->currentPipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::BindPipeline;
+ cmd.args.bindPipeline.bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ cmd.args.bindPipeline.pipeline = psD->pipeline;
+ cbD->commands.append(cmd);
+
+ cbD->currentPipeline = ps;
+ cbD->currentPipelineGeneration = psD->generation;
+ }
+
+ psD->lastActiveFrameSlot = currentFrameSlot;
+}
+
+QRhiPassResourceTracker::BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
+{
+ // pick the earlier stage (as this is going to be dstAccessMask)
+ if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
+ return QRhiPassResourceTracker::BufVertexStage;
+ if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
+ return QRhiPassResourceTracker::BufFragmentStage;
+
+ Q_UNREACHABLE();
+ return QRhiPassResourceTracker::BufVertexStage;
+}
+
+QRhiPassResourceTracker::TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
+{
+ // pick the earlier stage (as this is going to be dstAccessMask)
+ if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
+ return QRhiPassResourceTracker::TexVertexStage;
+ if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
+ return QRhiPassResourceTracker::TexFragmentStage;
+
+ Q_UNREACHABLE();
+ return QRhiPassResourceTracker::TexVertexStage;
+}
+
+void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
+{
+ Q_ASSERT(inPass);
+
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ Q_ASSERT(cbD->currentPipeline);
+ QVkGraphicsPipeline *psD = QRHI_RES(QVkGraphicsPipeline, cbD->currentPipeline);
+
+ if (!srb)
+ srb = psD->m_shaderResourceBindings;
+
+ QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, srb);
+ bool hasSlottedResourceInSrb = false;
+ bool hasDynamicOffsetInSrb = false;
+
+ for (const QRhiShaderResourceBinding &binding : qAsConst(srbD->sortedBindings)) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&binding);
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ if (QRHI_RES(QVkBuffer, b->u.ubuf.buf)->m_type == QRhiBuffer::Dynamic)
+ hasSlottedResourceInSrb = true;
+ if (b->u.ubuf.hasDynamicOffset)
+ hasDynamicOffsetInSrb = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ const int descSetIdx = hasSlottedResourceInSrb ? currentFrameSlot : 0;
+ bool rewriteDescSet = false;
+
+ // Do host writes and mark referenced shader resources as in-use.
+ // Also prepare to ensure the descriptor set we are going to bind refers to up-to-date Vk objects.
+ for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->sortedBindings[i]);
+ QVkShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[descSetIdx][i]);
+ QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]);
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ {
+ QVkBuffer *bufD = QRHI_RES(QVkBuffer, b->u.ubuf.buf);
+ Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
+
+ if (bufD->m_type == QRhiBuffer::Dynamic)
+ executeBufferHostWritesForCurrentFrame(bufD);
+
+ bufD->lastActiveFrameSlot = currentFrameSlot;
+ trackedRegisterBuffer(&passResTracker, bufD, currentFrameSlot,
+ QRhiPassResourceTracker::BufUniformRead,
+ toPassTrackerBufferStage(b->stage));
+
+ // Check both the "local" id (the generation counter) and the
+ // global id. The latter is relevant when a newly allocated
+ // QRhiResource ends up with the same pointer as a previous one.
+ // (and that previous one could have been in an srb...)
+ if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
+ rewriteDescSet = true;
+ bd.ubuf.id = bufD->m_id;
+ bd.ubuf.generation = bufD->generation;
+ }
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ {
+ QVkTexture *texD = QRHI_RES(QVkTexture, b->u.stex.tex);
+ QVkSampler *samplerD = QRHI_RES(QVkSampler, b->u.stex.sampler);
+ texD->lastActiveFrameSlot = currentFrameSlot;
+ samplerD->lastActiveFrameSlot = currentFrameSlot;
+ trackedRegisterTexture(&passResTracker, texD,
+ QRhiPassResourceTracker::TexSample,
+ toPassTrackerTextureStage(b->stage));
+
+ if (texD->generation != bd.stex.texGeneration
+ || texD->m_id != bd.stex.texId
+ || samplerD->generation != bd.stex.samplerGeneration
+ || samplerD->m_id != bd.stex.samplerId)
+ {
+ rewriteDescSet = true;
+ bd.stex.texId = texD->m_id;
+ bd.stex.texGeneration = texD->generation;
+ bd.stex.samplerId = samplerD->m_id;
+ bd.stex.samplerGeneration = samplerD->generation;
+ }
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+
+ // write descriptor sets, if needed
+ if (rewriteDescSet)
+ updateShaderResourceBindings(srb, descSetIdx);
+
+ // make sure the descriptors for the correct slot will get bound.
+ // also, dynamic offsets always need a bind.
+ const bool forceRebind = (hasSlottedResourceInSrb && cbD->currentDescSetSlot != descSetIdx) || hasDynamicOffsetInSrb;
+
+ if (forceRebind || rewriteDescSet || cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation) {
+ QVarLengthArray<uint32_t, 4> dynOfs;
+ if (hasDynamicOffsetInSrb) {
+ // Filling out dynOfs based on the sorted bindings is important
+ // because dynOfs has to be ordered based on the binding numbers,
+ // and neither srb nor dynamicOffsets has any such ordering
+ // requirement.
+ for (const QRhiShaderResourceBinding &binding : qAsConst(srbD->sortedBindings)) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&binding);
+ if (b->type == QRhiShaderResourceBinding::UniformBuffer && b->u.ubuf.hasDynamicOffset) {
+ uint32_t offset = 0;
+ for (int i = 0; i < dynamicOffsetCount; ++i) {
+ const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
+ if (dynOfs.first == b->binding) {
+ offset = dynOfs.second;
+ break;
+ }
+ }
+ dynOfs.append(offset); // use 0 if dynamicOffsets did not contain this binding
+ }
+ }
+ }
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::BindDescriptorSet;
+ cmd.args.bindDescriptorSet.bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ cmd.args.bindDescriptorSet.pipelineLayout = psD->layout;
+ cmd.args.bindDescriptorSet.descSet = srbD->descSets[descSetIdx];
+ cmd.args.bindDescriptorSet.dynamicOffsetCount = dynOfs.count();
+ cmd.args.bindDescriptorSet.dynamicOffsetIndex = cbD->pools.dynamicOffset.count();
+ cbD->pools.dynamicOffset.append(dynOfs.constData(), dynOfs.count());
+ cbD->commands.append(cmd);
+
+ cbD->currentSrb = srb;
+ cbD->currentSrbGeneration = srbD->generation;
+ cbD->currentDescSetSlot = descSetIdx;
+ }
+
+ srbD->lastActiveFrameSlot = currentFrameSlot;
+}
+
+void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
+{
+ Q_ASSERT(inPass);
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]);
+
+ bool needsBindVBuf = false;
+ for (int i = 0; i < bindingCount; ++i) {
+ const int inputSlot = startBinding + i;
+ QVkBuffer *bufD = QRHI_RES(QVkBuffer, bindings[i].first);
+ Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
+ bufD->lastActiveFrameSlot = currentFrameSlot;
+ if (bufD->m_type == QRhiBuffer::Dynamic)
+ executeBufferHostWritesForCurrentFrame(bufD);
+
+ const VkBuffer vkvertexbuf = bufD->buffers[bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0];
+ if (cbD->currentVertexBuffers[inputSlot] != vkvertexbuf
+ || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
+ {
+ needsBindVBuf = true;
+ cbD->currentVertexBuffers[inputSlot] = vkvertexbuf;
+ cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
+ }
+ }
+
+ if (needsBindVBuf) {
+ QVarLengthArray<VkBuffer, 4> bufs;
+ QVarLengthArray<VkDeviceSize, 4> ofs;
+ for (int i = 0; i < bindingCount; ++i) {
+ QVkBuffer *bufD = QRHI_RES(QVkBuffer, bindings[i].first);
+ const int slot = bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0;
+ bufs.append(bufD->buffers[slot]);
+ ofs.append(bindings[i].second);
+ trackedRegisterBuffer(&passResTracker, bufD, slot,
+ QRhiPassResourceTracker::BufVertexInput,
+ QRhiPassResourceTracker::BufVertexInputStage);
+ }
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::BindVertexBuffer;
+ cmd.args.bindVertexBuffer.startBinding = startBinding;
+ cmd.args.bindVertexBuffer.count = bufs.count();
+ cmd.args.bindVertexBuffer.vertexBufferIndex = cbD->pools.vertexBuffer.count();
+ cbD->pools.vertexBuffer.append(bufs.constData(), bufs.count());
+ cmd.args.bindVertexBuffer.vertexBufferOffsetIndex = cbD->pools.vertexBufferOffset.count();
+ cbD->pools.vertexBufferOffset.append(ofs.constData(), ofs.count());
+ cbD->commands.append(cmd);
+ }
+
+ if (indexBuf) {
+ QVkBuffer *ibufD = QRHI_RES(QVkBuffer, indexBuf);
+ Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
+ ibufD->lastActiveFrameSlot = currentFrameSlot;
+ if (ibufD->m_type == QRhiBuffer::Dynamic)
+ executeBufferHostWritesForCurrentFrame(ibufD);
+
+ const int slot = ibufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0;
+ const VkBuffer vkindexbuf = ibufD->buffers[slot];
+ const VkIndexType type = indexFormat == QRhiCommandBuffer::IndexUInt16 ? VK_INDEX_TYPE_UINT16
+ : VK_INDEX_TYPE_UINT32;
+
+ if (cbD->currentIndexBuffer != vkindexbuf
+ || cbD->currentIndexOffset != indexOffset
+ || cbD->currentIndexFormat != type)
+ {
+ cbD->currentIndexBuffer = vkindexbuf;
+ cbD->currentIndexOffset = indexOffset;
+ cbD->currentIndexFormat = type;
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::BindIndexBuffer;
+ cmd.args.bindIndexBuffer.buf = vkindexbuf;
+ cmd.args.bindIndexBuffer.ofs = indexOffset;
+ cmd.args.bindIndexBuffer.type = type;
+ cbD->commands.append(cmd);
+
+ trackedRegisterBuffer(&passResTracker, ibufD, slot,
+ QRhiPassResourceTracker::BufIndexRead,
+ QRhiPassResourceTracker::BufVertexInputStage);
+ }
+ }
+}
+
+void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
+{
+ Q_ASSERT(inPass);
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ Q_ASSERT(cbD->currentPipeline && cbD->currentTarget);
+ const QSize outputSize = cbD->currentTarget->pixelSize();
+
+ // x,y is top-left in VkViewport but bottom-left in QRhiViewport
+ float x, y, w, h;
+ if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h))
+ return;
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::SetViewport;
+ VkViewport *vp = &cmd.args.setViewport.viewport;
+ vp->x = x;
+ vp->y = y;
+ vp->width = w;
+ vp->height = h;
+ vp->minDepth = viewport.minDepth();
+ vp->maxDepth = viewport.maxDepth();
+ cbD->commands.append(cmd);
+
+ if (!QRHI_RES(QVkGraphicsPipeline, cbD->currentPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
+ cmd.cmd = QVkCommandBuffer::Command::SetScissor;
+ VkRect2D *s = &cmd.args.setScissor.scissor;
+ s->offset.x = x;
+ s->offset.y = y;
+ s->extent.width = w;
+ s->extent.height = h;
+ cbD->commands.append(cmd);
+ }
+}
+
+void QRhiVulkan::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
+{
+ Q_ASSERT(inPass);
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ Q_ASSERT(cbD->currentPipeline && cbD->currentTarget);
+ Q_ASSERT(QRHI_RES(QVkGraphicsPipeline, cbD->currentPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor));
+ const QSize outputSize = cbD->currentTarget->pixelSize();
+
+ // x,y is top-left in VkRect2D but bottom-left in QRhiScissor
+ int x, y, w, h;
+ if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h))
+ return;
+
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::SetScissor;
+ VkRect2D *s = &cmd.args.setScissor.scissor;
+ s->offset.x = x;
+ s->offset.y = y;
+ s->extent.width = w;
+ s->extent.height = h;
+ cbD->commands.append(cmd);
+}
+
+void QRhiVulkan::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
+{
+ Q_ASSERT(inPass);
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::SetBlendConstants;
+ cmd.args.setBlendConstants.c[0] = c.redF();
+ cmd.args.setBlendConstants.c[1] = c.greenF();
+ cmd.args.setBlendConstants.c[2] = c.blueF();
+ cmd.args.setBlendConstants.c[3] = c.alphaF();
+ cbD->commands.append(cmd);
+}
+
+void QRhiVulkan::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
+{
+ Q_ASSERT(inPass);
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::SetStencilRef;
+ cmd.args.setStencilRef.ref = refValue;
+ cbD->commands.append(cmd);
+}
+
+void QRhiVulkan::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
+{
+ Q_ASSERT(inPass);
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::Draw;
+ cmd.args.draw.vertexCount = vertexCount;
+ cmd.args.draw.instanceCount = instanceCount;
+ cmd.args.draw.firstVertex = firstVertex;
+ cmd.args.draw.firstInstance = firstInstance;
+ cbD->commands.append(cmd);
+}
+
+void QRhiVulkan::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
+{
+ Q_ASSERT(inPass);
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::DrawIndexed;
+ cmd.args.drawIndexed.indexCount = indexCount;
+ cmd.args.drawIndexed.instanceCount = instanceCount;
+ cmd.args.drawIndexed.firstIndex = firstIndex;
+ cmd.args.drawIndexed.vertexOffset = vertexOffset;
+ cmd.args.drawIndexed.firstInstance = firstInstance;
+ cbD->commands.append(cmd);
+}
+
+void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
+{
+ if (!debugMarkers || !debugMarkersAvailable)
+ return;
+
+ VkDebugMarkerMarkerInfoEXT marker;
+ memset(&marker, 0, sizeof(marker));
+ marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
+
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::DebugMarkerBegin;
+ cmd.args.debugMarkerBegin.marker = marker;
+ cmd.args.debugMarkerBegin.markerNameIndex = cbD->pools.debugMarkerName.count();
+ cbD->pools.debugMarkerName.append(name);
+ cbD->commands.append(cmd);
+}
+
+void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb)
+{
+ if (!debugMarkers || !debugMarkersAvailable)
+ return;
+
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::DebugMarkerEnd;
+ cbD->commands.append(cmd);
+}
+
+void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
+{
+ if (!debugMarkers || !debugMarkersAvailable)
+ return;
+
+ VkDebugMarkerMarkerInfoEXT marker;
+ memset(&marker, 0, sizeof(marker));
+ marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
+ marker.pMarkerName = msg.constData();
+
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ QVkCommandBuffer::Command cmd;
+ cmd.cmd = QVkCommandBuffer::Command::DebugMarkerInsert;
+ cmd.args.debugMarkerInsert.marker = marker;
+ cbD->commands.append(cmd);
+}
+
+const QRhiNativeHandles *QRhiVulkan::nativeHandles(QRhiCommandBuffer *cb)
+{
+ return QRHI_RES(QVkCommandBuffer, cb)->nativeHandles();
+}
+
+void QRhiVulkan::beginExternal(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+}
+
+void QRhiVulkan::endExternal(QRhiCommandBuffer *cb)
+{
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ cbD->resetCachedState();
+}
+
+void QRhiVulkan::setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot)
+{
+ if (!debugMarkers || !debugMarkersAvailable || name.isEmpty())
+ return;
+
+ VkDebugMarkerObjectNameInfoEXT nameInfo;
+ memset(&nameInfo, 0, sizeof(nameInfo));
+ nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
+ nameInfo.objectType = type;
+ nameInfo.object = object;
+ QByteArray decoratedName = name;
+ if (slot >= 0) {
+ decoratedName += '/';
+ decoratedName += QByteArray::number(slot);
+ }
+ nameInfo.pObjectName = decoratedName.constData();
+ vkDebugMarkerSetObjectName(dev, &nameInfo);
+}
+
+static inline VkBufferUsageFlagBits toVkBufferUsage(QRhiBuffer::UsageFlags usage)
+{
+ int u = 0;
+ if (usage.testFlag(QRhiBuffer::VertexBuffer))
+ u |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ if (usage.testFlag(QRhiBuffer::IndexBuffer))
+ u |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
+ if (usage.testFlag(QRhiBuffer::UniformBuffer))
+ u |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ return VkBufferUsageFlagBits(u);
+}
+
+static inline VkFilter toVkFilter(QRhiSampler::Filter f)
+{
+ switch (f) {
+ case QRhiSampler::Nearest:
+ return VK_FILTER_NEAREST;
+ case QRhiSampler::Linear:
+ return VK_FILTER_LINEAR;
+ default:
+ Q_UNREACHABLE();
+ return VK_FILTER_NEAREST;
+ }
+}
+
+static inline VkSamplerMipmapMode toVkMipmapMode(QRhiSampler::Filter f)
+{
+ switch (f) {
+ case QRhiSampler::None:
+ return VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ case QRhiSampler::Nearest:
+ return VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ case QRhiSampler::Linear:
+ return VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ default:
+ Q_UNREACHABLE();
+ return VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ }
+}
+
+static inline VkSamplerAddressMode toVkAddressMode(QRhiSampler::AddressMode m)
+{
+ switch (m) {
+ case QRhiSampler::Repeat:
+ return VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ case QRhiSampler::ClampToEdge:
+ return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ case QRhiSampler::Border:
+ return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+ case QRhiSampler::Mirror:
+ return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
+ case QRhiSampler::MirrorOnce:
+ return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
+ default:
+ Q_UNREACHABLE();
+ return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ }
+}
+
+static inline VkShaderStageFlagBits toVkShaderStage(QRhiGraphicsShaderStage::Type type)
+{
+ switch (type) {
+ case QRhiGraphicsShaderStage::Vertex:
+ return VK_SHADER_STAGE_VERTEX_BIT;
+ case QRhiGraphicsShaderStage::Fragment:
+ return VK_SHADER_STAGE_FRAGMENT_BIT;
+ default:
+ Q_UNREACHABLE();
+ return VK_SHADER_STAGE_VERTEX_BIT;
+ }
+}
+
+static inline VkFormat toVkAttributeFormat(QRhiVertexInputAttribute::Format format)
+{
+ switch (format) {
+ case QRhiVertexInputAttribute::Float4:
+ return VK_FORMAT_R32G32B32A32_SFLOAT;
+ case QRhiVertexInputAttribute::Float3:
+ return VK_FORMAT_R32G32B32_SFLOAT;
+ case QRhiVertexInputAttribute::Float2:
+ return VK_FORMAT_R32G32_SFLOAT;
+ case QRhiVertexInputAttribute::Float:
+ return VK_FORMAT_R32_SFLOAT;
+ case QRhiVertexInputAttribute::UNormByte4:
+ return VK_FORMAT_R8G8B8A8_UNORM;
+ case QRhiVertexInputAttribute::UNormByte2:
+ return VK_FORMAT_R8G8_UNORM;
+ case QRhiVertexInputAttribute::UNormByte:
+ return VK_FORMAT_R8_UNORM;
+ default:
+ Q_UNREACHABLE();
+ return VK_FORMAT_R32G32B32A32_SFLOAT;
+ }
+}
+
+static inline VkPrimitiveTopology toVkTopology(QRhiGraphicsPipeline::Topology t)
+{
+ switch (t) {
+ case QRhiGraphicsPipeline::Triangles:
+ return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ case QRhiGraphicsPipeline::TriangleStrip:
+ return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ case QRhiGraphicsPipeline::Lines:
+ return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
+ case QRhiGraphicsPipeline::LineStrip:
+ return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
+ case QRhiGraphicsPipeline::Points:
+ return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
+ default:
+ Q_UNREACHABLE();
+ return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ }
+}
+
+static inline VkCullModeFlags toVkCullMode(QRhiGraphicsPipeline::CullMode c)
+{
+ switch (c) {
+ case QRhiGraphicsPipeline::None:
+ return VK_CULL_MODE_NONE;
+ case QRhiGraphicsPipeline::Front:
+ return VK_CULL_MODE_FRONT_BIT;
+ case QRhiGraphicsPipeline::Back:
+ return VK_CULL_MODE_BACK_BIT;
+ default:
+ Q_UNREACHABLE();
+ return VK_CULL_MODE_NONE;
+ }
+}
+
+static inline VkFrontFace toVkFrontFace(QRhiGraphicsPipeline::FrontFace f)
+{
+ switch (f) {
+ case QRhiGraphicsPipeline::CCW:
+ return VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ case QRhiGraphicsPipeline::CW:
+ return VK_FRONT_FACE_CLOCKWISE;
+ default:
+ Q_UNREACHABLE();
+ return VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ }
+}
+
+static inline VkColorComponentFlags toVkColorComponents(QRhiGraphicsPipeline::ColorMask c)
+{
+ int f = 0;
+ if (c.testFlag(QRhiGraphicsPipeline::R))
+ f |= VK_COLOR_COMPONENT_R_BIT;
+ if (c.testFlag(QRhiGraphicsPipeline::G))
+ f |= VK_COLOR_COMPONENT_G_BIT;
+ if (c.testFlag(QRhiGraphicsPipeline::B))
+ f |= VK_COLOR_COMPONENT_B_BIT;
+ if (c.testFlag(QRhiGraphicsPipeline::A))
+ f |= VK_COLOR_COMPONENT_A_BIT;
+ return VkColorComponentFlags(f);
+}
+
+static inline VkBlendFactor toVkBlendFactor(QRhiGraphicsPipeline::BlendFactor f)
+{
+ switch (f) {
+ case QRhiGraphicsPipeline::Zero:
+ return VK_BLEND_FACTOR_ZERO;
+ case QRhiGraphicsPipeline::One:
+ return VK_BLEND_FACTOR_ONE;
+ case QRhiGraphicsPipeline::SrcColor:
+ return VK_BLEND_FACTOR_SRC_COLOR;
+ case QRhiGraphicsPipeline::OneMinusSrcColor:
+ return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ case QRhiGraphicsPipeline::DstColor:
+ return VK_BLEND_FACTOR_DST_COLOR;
+ case QRhiGraphicsPipeline::OneMinusDstColor:
+ return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
+ case QRhiGraphicsPipeline::SrcAlpha:
+ return VK_BLEND_FACTOR_SRC_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusSrcAlpha:
+ return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ case QRhiGraphicsPipeline::DstAlpha:
+ return VK_BLEND_FACTOR_DST_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusDstAlpha:
+ return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
+ case QRhiGraphicsPipeline::ConstantColor:
+ return VK_BLEND_FACTOR_CONSTANT_COLOR;
+ case QRhiGraphicsPipeline::OneMinusConstantColor:
+ return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
+ case QRhiGraphicsPipeline::ConstantAlpha:
+ return VK_BLEND_FACTOR_CONSTANT_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusConstantAlpha:
+ return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
+ case QRhiGraphicsPipeline::SrcAlphaSaturate:
+ return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
+ case QRhiGraphicsPipeline::Src1Color:
+ return VK_BLEND_FACTOR_SRC1_COLOR;
+ case QRhiGraphicsPipeline::OneMinusSrc1Color:
+ return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
+ case QRhiGraphicsPipeline::Src1Alpha:
+ return VK_BLEND_FACTOR_SRC1_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
+ return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
+ default:
+ Q_UNREACHABLE();
+ return VK_BLEND_FACTOR_ZERO;
+ }
+}
+
+static inline VkBlendOp toVkBlendOp(QRhiGraphicsPipeline::BlendOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::Add:
+ return VK_BLEND_OP_ADD;
+ case QRhiGraphicsPipeline::Subtract:
+ return VK_BLEND_OP_SUBTRACT;
+ case QRhiGraphicsPipeline::ReverseSubtract:
+ return VK_BLEND_OP_REVERSE_SUBTRACT;
+ case QRhiGraphicsPipeline::Min:
+ return VK_BLEND_OP_MIN;
+ case QRhiGraphicsPipeline::Max:
+ return VK_BLEND_OP_MAX;
+ default:
+ Q_UNREACHABLE();
+ return VK_BLEND_OP_ADD;
+ }
+}
+
+static inline VkCompareOp toVkCompareOp(QRhiGraphicsPipeline::CompareOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::Never:
+ return VK_COMPARE_OP_NEVER;
+ case QRhiGraphicsPipeline::Less:
+ return VK_COMPARE_OP_LESS;
+ case QRhiGraphicsPipeline::Equal:
+ return VK_COMPARE_OP_EQUAL;
+ case QRhiGraphicsPipeline::LessOrEqual:
+ return VK_COMPARE_OP_LESS_OR_EQUAL;
+ case QRhiGraphicsPipeline::Greater:
+ return VK_COMPARE_OP_GREATER;
+ case QRhiGraphicsPipeline::NotEqual:
+ return VK_COMPARE_OP_NOT_EQUAL;
+ case QRhiGraphicsPipeline::GreaterOrEqual:
+ return VK_COMPARE_OP_GREATER_OR_EQUAL;
+ case QRhiGraphicsPipeline::Always:
+ return VK_COMPARE_OP_ALWAYS;
+ default:
+ Q_UNREACHABLE();
+ return VK_COMPARE_OP_ALWAYS;
+ }
+}
+
+static inline VkStencilOp toVkStencilOp(QRhiGraphicsPipeline::StencilOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::StencilZero:
+ return VK_STENCIL_OP_ZERO;
+ case QRhiGraphicsPipeline::Keep:
+ return VK_STENCIL_OP_KEEP;
+ case QRhiGraphicsPipeline::Replace:
+ return VK_STENCIL_OP_REPLACE;
+ case QRhiGraphicsPipeline::IncrementAndClamp:
+ return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
+ case QRhiGraphicsPipeline::DecrementAndClamp:
+ return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
+ case QRhiGraphicsPipeline::Invert:
+ return VK_STENCIL_OP_INVERT;
+ case QRhiGraphicsPipeline::IncrementAndWrap:
+ return VK_STENCIL_OP_INCREMENT_AND_WRAP;
+ case QRhiGraphicsPipeline::DecrementAndWrap:
+ return VK_STENCIL_OP_DECREMENT_AND_WRAP;
+ default:
+ Q_UNREACHABLE();
+ return VK_STENCIL_OP_KEEP;
+ }
+}
+
+static inline void fillVkStencilOpState(VkStencilOpState *dst, const QRhiGraphicsPipeline::StencilOpState &src)
+{
+ dst->failOp = toVkStencilOp(src.failOp);
+ dst->passOp = toVkStencilOp(src.passOp);
+ dst->depthFailOp = toVkStencilOp(src.depthFailOp);
+ dst->compareOp = toVkCompareOp(src.compareOp);
+}
+
+static inline VkDescriptorType toVkDescriptorType(const QRhiShaderResourceBindingPrivate *b)
+{
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ return b->u.ubuf.hasDynamicOffset ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
+ : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ case QRhiShaderResourceBinding::SampledTexture:
+ return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ default:
+ Q_UNREACHABLE();
+ return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ }
+}
+
+static inline VkShaderStageFlags toVkShaderStageFlags(QRhiShaderResourceBinding::StageFlags stage)
+{
+ int s = 0;
+ if (stage.testFlag(QRhiShaderResourceBinding::VertexStage))
+ s |= VK_SHADER_STAGE_VERTEX_BIT;
+ if (stage.testFlag(QRhiShaderResourceBinding::FragmentStage))
+ s |= VK_SHADER_STAGE_FRAGMENT_BIT;
+ return VkShaderStageFlags(s);
+}
+
+static inline VkCompareOp toVkTextureCompareOp(QRhiSampler::CompareOp op)
+{
+ switch (op) {
+ case QRhiSampler::Never:
+ return VK_COMPARE_OP_NEVER;
+ case QRhiSampler::Less:
+ return VK_COMPARE_OP_LESS;
+ case QRhiSampler::Equal:
+ return VK_COMPARE_OP_EQUAL;
+ case QRhiSampler::LessOrEqual:
+ return VK_COMPARE_OP_LESS_OR_EQUAL;
+ case QRhiSampler::Greater:
+ return VK_COMPARE_OP_GREATER;
+ case QRhiSampler::NotEqual:
+ return VK_COMPARE_OP_NOT_EQUAL;
+ case QRhiSampler::GreaterOrEqual:
+ return VK_COMPARE_OP_GREATER_OR_EQUAL;
+ case QRhiSampler::Always:
+ return VK_COMPARE_OP_ALWAYS;
+ default:
+ Q_UNREACHABLE();
+ return VK_COMPARE_OP_NEVER;
+ }
+}
+
+QVkBuffer::QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+ : QRhiBuffer(rhi, type, usage, size)
+{
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ buffers[i] = stagingBuffers[i] = VK_NULL_HANDLE;
+ allocations[i] = stagingAllocations[i] = nullptr;
+ }
+}
+
+QVkBuffer::~QVkBuffer()
+{
+ release();
+}
+
+void QVkBuffer::release()
+{
+ if (!buffers[0])
+ return;
+
+ QRhiVulkan::DeferredReleaseEntry e;
+ e.type = QRhiVulkan::DeferredReleaseEntry::Buffer;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ e.buffer.buffers[i] = buffers[i];
+ e.buffer.allocations[i] = allocations[i];
+ e.buffer.stagingBuffers[i] = stagingBuffers[i];
+ e.buffer.stagingAllocations[i] = stagingAllocations[i];
+
+ buffers[i] = VK_NULL_HANDLE;
+ allocations[i] = nullptr;
+ stagingBuffers[i] = VK_NULL_HANDLE;
+ stagingAllocations[i] = nullptr;
+ pendingDynamicUpdates[i].clear();
+ }
+
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->releaseQueue.append(e);
+
+ QRHI_PROF;
+ QRHI_PROF_F(releaseBuffer(this));
+
+ rhiD->unregisterResource(this);
+}
+
+bool QVkBuffer::build()
+{
+ if (buffers[0])
+ release();
+
+ const int nonZeroSize = m_size <= 0 ? 256 : m_size;
+
+ VkBufferCreateInfo bufferInfo;
+ memset(&bufferInfo, 0, sizeof(bufferInfo));
+ bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ bufferInfo.size = nonZeroSize;
+ bufferInfo.usage = toVkBufferUsage(m_usage);
+
+ VmaAllocationCreateInfo allocInfo;
+ memset(&allocInfo, 0, sizeof(allocInfo));
+
+ if (m_type == Dynamic) {
+#ifndef Q_OS_DARWIN // not for MoltenVK
+ // Keep mapped all the time. Essential f.ex. with some mobile GPUs,
+ // where mapping and unmapping an entire allocation every time updating
+ // a suballocated buffer presents a significant perf. hit.
+ allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+#endif
+ // host visible, frequent changes
+ allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
+ } else {
+ allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+ bufferInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ }
+
+ QRHI_RES_RHI(QRhiVulkan);
+ VkResult err = VK_SUCCESS;
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ buffers[i] = VK_NULL_HANDLE;
+ allocations[i] = nullptr;
+ usageState[i].access = usageState[i].stage = 0;
+ if (i == 0 || m_type == Dynamic) {
+ VmaAllocation allocation;
+ err = vmaCreateBuffer(toVmaAllocator(rhiD->allocator), &bufferInfo, &allocInfo, &buffers[i], &allocation, nullptr);
+ if (err != VK_SUCCESS)
+ break;
+
+ allocations[i] = allocation;
+ if (m_type == Dynamic)
+ pendingDynamicUpdates[i].reserve(16);
+
+ rhiD->setObjectName(uint64_t(buffers[i]), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, m_objectName,
+ m_type == Dynamic ? i : -1);
+ }
+ }
+
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create buffer: %d", err);
+ return false;
+ }
+
+ QRHI_PROF;
+ QRHI_PROF_F(newBuffer(this, nonZeroSize, m_type != Dynamic ? 1 : QVK_FRAMES_IN_FLIGHT, 0));
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QVkRenderBuffer::QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, Flags flags)
+ : QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
+{
+}
+
+QVkRenderBuffer::~QVkRenderBuffer()
+{
+ release();
+ delete backingTexture;
+}
+
+void QVkRenderBuffer::release()
+{
+ if (!memory && !backingTexture)
+ return;
+
+ QRhiVulkan::DeferredReleaseEntry e;
+ e.type = QRhiVulkan::DeferredReleaseEntry::RenderBuffer;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ e.renderBuffer.memory = memory;
+ e.renderBuffer.image = image;
+ e.renderBuffer.imageView = imageView;
+
+ memory = VK_NULL_HANDLE;
+ image = VK_NULL_HANDLE;
+ imageView = VK_NULL_HANDLE;
+
+ if (backingTexture) {
+ Q_ASSERT(backingTexture->lastActiveFrameSlot == -1);
+ backingTexture->lastActiveFrameSlot = e.lastActiveFrameSlot;
+ backingTexture->release();
+ }
+
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->releaseQueue.append(e);
+
+ QRHI_PROF;
+ QRHI_PROF_F(releaseRenderBuffer(this));
+
+ rhiD->unregisterResource(this);
+}
+
+bool QVkRenderBuffer::build()
+{
+ if (memory || backingTexture)
+ release();
+
+ if (m_pixelSize.isEmpty())
+ return false;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ QRHI_PROF;
+ samples = rhiD->effectiveSampleCount(m_sampleCount);
+
+ switch (m_type) {
+ case QRhiRenderBuffer::Color:
+ {
+ if (!backingTexture) {
+ backingTexture = QRHI_RES(QVkTexture, rhiD->createTexture(QRhiTexture::RGBA8,
+ m_pixelSize,
+ m_sampleCount,
+ QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
+ } else {
+ backingTexture->setPixelSize(m_pixelSize);
+ backingTexture->setSampleCount(m_sampleCount);
+ }
+ backingTexture->setName(m_objectName);
+ if (!backingTexture->build())
+ return false;
+ vkformat = backingTexture->vkformat;
+ QRHI_PROF_F(newRenderBuffer(this, false, false, samples));
+ }
+ break;
+ case QRhiRenderBuffer::DepthStencil:
+ vkformat = rhiD->optimalDepthStencilFormat();
+ if (!rhiD->createTransientImage(vkformat,
+ m_pixelSize,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+ VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
+ samples,
+ &memory,
+ &image,
+ &imageView,
+ 1))
+ {
+ return false;
+ }
+ rhiD->setObjectName(uint64_t(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, m_objectName);
+ QRHI_PROF_F(newRenderBuffer(this, true, false, samples));
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ lastActiveFrameSlot = -1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QRhiTexture::Format QVkRenderBuffer::backingFormat() const
+{
+ return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
+}
+
+QVkTexture::QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, sampleCount, flags)
+{
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ stagingBuffers[i] = VK_NULL_HANDLE;
+ stagingAllocations[i] = nullptr;
+ }
+}
+
+QVkTexture::~QVkTexture()
+{
+ release();
+}
+
+void QVkTexture::release()
+{
+ if (!image)
+ return;
+
+ QRhiVulkan::DeferredReleaseEntry e;
+ e.type = QRhiVulkan::DeferredReleaseEntry::Texture;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ e.texture.image = owns ? image : VK_NULL_HANDLE;
+ e.texture.imageView = imageView;
+ e.texture.allocation = owns ? imageAlloc : nullptr;
+
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ e.texture.stagingBuffers[i] = stagingBuffers[i];
+ e.texture.stagingAllocations[i] = stagingAllocations[i];
+
+ stagingBuffers[i] = VK_NULL_HANDLE;
+ stagingAllocations[i] = nullptr;
+ }
+
+ image = VK_NULL_HANDLE;
+ imageView = VK_NULL_HANDLE;
+ imageAlloc = nullptr;
+ nativeHandlesStruct.image = VK_NULL_HANDLE;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->releaseQueue.append(e);
+
+ QRHI_PROF;
+ QRHI_PROF_F(releaseTexture(this));
+
+ rhiD->unregisterResource(this);
+}
+
+bool QVkTexture::prepareBuild(QSize *adjustedSize)
+{
+ if (image)
+ release();
+
+ QRHI_RES_RHI(QRhiVulkan);
+ vkformat = toVkTextureFormat(m_format, m_flags);
+ VkFormatProperties props;
+ rhiD->f->vkGetPhysicalDeviceFormatProperties(rhiD->physDev, vkformat, &props);
+ const bool canSampleOptimal = (props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
+ if (!canSampleOptimal) {
+ qWarning("Texture sampling with optimal tiling for format %d not supported", vkformat);
+ return false;
+ }
+
+ const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
+ const bool isCube = m_flags.testFlag(CubeMap);
+ const bool hasMipMaps = m_flags.testFlag(MipMapped);
+
+ mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
+ const int maxLevels = QRhi::MAX_LEVELS;
+ if (mipLevelCount > maxLevels) {
+ qWarning("Too many mip levels (%d, max is %d), truncating mip chain", mipLevelCount, maxLevels);
+ mipLevelCount = maxLevels;
+ }
+ samples = rhiD->effectiveSampleCount(m_sampleCount);
+ if (samples > VK_SAMPLE_COUNT_1_BIT) {
+ if (isCube) {
+ qWarning("Cubemap texture cannot be multisample");
+ return false;
+ }
+ if (hasMipMaps) {
+ qWarning("Multisample texture cannot have mipmaps");
+ return false;
+ }
+ }
+
+ usageState.layout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ usageState.access = 0;
+ usageState.stage = 0;
+
+ if (adjustedSize)
+ *adjustedSize = size;
+
+ return true;
+}
+
+bool QVkTexture::finishBuild()
+{
+ QRHI_RES_RHI(QRhiVulkan);
+
+ const bool isDepth = isDepthTextureFormat(m_format);
+ const bool isCube = m_flags.testFlag(CubeMap);
+
+ VkImageViewCreateInfo viewInfo;
+ memset(&viewInfo, 0, sizeof(viewInfo));
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.image = image;
+ viewInfo.viewType = isCube ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = vkformat;
+ 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 = isDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
+ viewInfo.subresourceRange.levelCount = mipLevelCount;
+ viewInfo.subresourceRange.layerCount = isCube ? 6 : 1;
+
+ VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &imageView);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create image view: %d", err);
+ return false;
+ }
+
+ nativeHandlesStruct.image = image;
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+
+ return true;
+}
+
+bool QVkTexture::build()
+{
+ QSize size;
+ if (!prepareBuild(&size))
+ return false;
+
+ const bool isRenderTarget = m_flags.testFlag(QRhiTexture::RenderTarget);
+ const bool isDepth = isDepthTextureFormat(m_format);
+ const bool isCube = m_flags.testFlag(CubeMap);
+
+ VkImageCreateInfo imageInfo;
+ memset(&imageInfo, 0, sizeof(imageInfo));
+ imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imageInfo.flags = isCube ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
+ imageInfo.imageType = VK_IMAGE_TYPE_2D;
+ imageInfo.format = vkformat;
+ imageInfo.extent.width = size.width();
+ imageInfo.extent.height = size.height();
+ imageInfo.extent.depth = 1;
+ imageInfo.mipLevels = mipLevelCount;
+ imageInfo.arrayLayers = isCube ? 6 : 1;
+ imageInfo.samples = samples;
+ imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+
+ imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ if (isRenderTarget) {
+ if (isDepth)
+ imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ else
+ imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
+ if (m_flags.testFlag(QRhiTexture::UsedAsTransferSource))
+ imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ if (m_flags.testFlag(QRhiTexture::UsedWithGenerateMips))
+ imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+
+ VmaAllocationCreateInfo allocInfo;
+ memset(&allocInfo, 0, sizeof(allocInfo));
+ allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ VmaAllocation allocation;
+ VkResult err = vmaCreateImage(toVmaAllocator(rhiD->allocator), &imageInfo, &allocInfo, &image, &allocation, nullptr);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create image: %d", err);
+ return false;
+ }
+ imageAlloc = allocation;
+
+ if (!finishBuild())
+ return false;
+
+ rhiD->setObjectName(uint64_t(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, m_objectName);
+
+ QRHI_PROF;
+ QRHI_PROF_F(newTexture(this, true, mipLevelCount, isCube ? 6 : 1, samples));
+
+ owns = true;
+ rhiD->registerResource(this);
+ return true;
+}
+
+bool QVkTexture::buildFrom(const QRhiNativeHandles *src)
+{
+ const QRhiVulkanTextureNativeHandles *h = static_cast<const QRhiVulkanTextureNativeHandles *>(src);
+ if (!h || !h->image)
+ return false;
+
+ if (!prepareBuild())
+ return false;
+
+ image = h->image;
+
+ if (!finishBuild())
+ return false;
+
+ QRHI_PROF;
+ QRHI_PROF_F(newTexture(this, false, mipLevelCount, m_flags.testFlag(CubeMap) ? 6 : 1, samples));
+
+ usageState.layout = h->layout;
+
+ owns = false;
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->registerResource(this);
+ return true;
+}
+
+const QRhiNativeHandles *QVkTexture::nativeHandles()
+{
+ nativeHandlesStruct.layout = usageState.layout;
+ return &nativeHandlesStruct;
+}
+
+QVkSampler::QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+{
+}
+
+QVkSampler::~QVkSampler()
+{
+ release();
+}
+
+void QVkSampler::release()
+{
+ if (!sampler)
+ return;
+
+ QRhiVulkan::DeferredReleaseEntry e;
+ e.type = QRhiVulkan::DeferredReleaseEntry::Sampler;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ e.sampler.sampler = sampler;
+ sampler = VK_NULL_HANDLE;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+}
+
+bool QVkSampler::build()
+{
+ if (sampler)
+ release();
+
+ VkSamplerCreateInfo samplerInfo;
+ memset(&samplerInfo, 0, sizeof(samplerInfo));
+ samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ samplerInfo.magFilter = toVkFilter(m_magFilter);
+ samplerInfo.minFilter = toVkFilter(m_minFilter);
+ samplerInfo.mipmapMode = toVkMipmapMode(m_mipmapMode);
+ samplerInfo.addressModeU = toVkAddressMode(m_addressU);
+ samplerInfo.addressModeV = toVkAddressMode(m_addressV);
+ samplerInfo.addressModeW = toVkAddressMode(m_addressW);
+ samplerInfo.maxAnisotropy = 1.0f;
+ samplerInfo.compareEnable = m_compareOp != Never;
+ samplerInfo.compareOp = toVkTextureCompareOp(m_compareOp);
+ samplerInfo.maxLod = m_mipmapMode == None ? 0.25f : 1000.0f;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ VkResult err = rhiD->df->vkCreateSampler(rhiD->dev, &samplerInfo, nullptr, &sampler);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create sampler: %d", err);
+ return false;
+ }
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QVkRenderPassDescriptor::QVkRenderPassDescriptor(QRhiImplementation *rhi)
+ : QRhiRenderPassDescriptor(rhi)
+{
+}
+
+QVkRenderPassDescriptor::~QVkRenderPassDescriptor()
+{
+ release();
+}
+
+void QVkRenderPassDescriptor::release()
+{
+ if (!rp)
+ return;
+
+ if (!ownsRp) {
+ rp = VK_NULL_HANDLE;
+ return;
+ }
+
+ QRhiVulkan::DeferredReleaseEntry e;
+ e.type = QRhiVulkan::DeferredReleaseEntry::RenderPass;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ e.renderPass.rp = rp;
+
+ rp = VK_NULL_HANDLE;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->releaseQueue.append(e);
+
+ rhiD->unregisterResource(this);
+}
+
+QVkReferenceRenderTarget::QVkReferenceRenderTarget(QRhiImplementation *rhi)
+ : QRhiRenderTarget(rhi)
+{
+}
+
+QVkReferenceRenderTarget::~QVkReferenceRenderTarget()
+{
+ release();
+}
+
+void QVkReferenceRenderTarget::release()
+{
+ // nothing to do here
+}
+
+QSize QVkReferenceRenderTarget::pixelSize() const
+{
+ return d.pixelSize;
+}
+
+float QVkReferenceRenderTarget::devicePixelRatio() const
+{
+ return d.dpr;
+}
+
+int QVkReferenceRenderTarget::sampleCount() const
+{
+ return d.sampleCount;
+}
+
+QVkTextureRenderTarget::QVkTextureRenderTarget(QRhiImplementation *rhi,
+ const QRhiTextureRenderTargetDescription &desc,
+ Flags flags)
+ : QRhiTextureRenderTarget(rhi, desc, flags)
+{
+ for (int att = 0; att < QVkRenderTargetData::MAX_COLOR_ATTACHMENTS; ++att) {
+ rtv[att] = VK_NULL_HANDLE;
+ resrtv[att] = VK_NULL_HANDLE;
+ }
+}
+
+QVkTextureRenderTarget::~QVkTextureRenderTarget()
+{
+ release();
+}
+
+void QVkTextureRenderTarget::release()
+{
+ if (!d.fb)
+ return;
+
+ QRhiVulkan::DeferredReleaseEntry e;
+ e.type = QRhiVulkan::DeferredReleaseEntry::TextureRenderTarget;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ e.textureRenderTarget.fb = d.fb;
+ d.fb = VK_NULL_HANDLE;
+
+ for (int att = 0; att < QVkRenderTargetData::MAX_COLOR_ATTACHMENTS; ++att) {
+ e.textureRenderTarget.rtv[att] = rtv[att];
+ e.textureRenderTarget.resrtv[att] = resrtv[att];
+ rtv[att] = VK_NULL_HANDLE;
+ resrtv[att] = VK_NULL_HANDLE;
+ }
+
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->releaseQueue.append(e);
+
+ rhiD->unregisterResource(this);
+}
+
+QRhiRenderPassDescriptor *QVkTextureRenderTarget::newCompatibleRenderPassDescriptor()
+{
+ // not yet built so cannot rely on data computed in build()
+
+ QRHI_RES_RHI(QRhiVulkan);
+ QVkRenderPassDescriptor *rp = new QVkRenderPassDescriptor(m_rhi);
+ if (!rhiD->createOffscreenRenderPass(&rp->rp,
+ m_desc.colorAttachments(),
+ m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents),
+ m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents),
+ m_desc.depthStencilBuffer(),
+ m_desc.depthTexture()))
+ {
+ delete rp;
+ return nullptr;
+ }
+
+ rp->ownsRp = true;
+ rhiD->registerResource(rp);
+ return rp;
+}
+
+bool QVkTextureRenderTarget::build()
+{
+ if (d.fb)
+ release();
+
+ const QVector<QRhiColorAttachment> colorAttachments = m_desc.colorAttachments();
+ Q_ASSERT(!colorAttachments.isEmpty() || m_desc.depthTexture());
+ Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
+ const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
+
+ QRHI_RES_RHI(QRhiVulkan);
+ QVarLengthArray<VkImageView, 8> views;
+
+ d.colorAttCount = colorAttachments.count();
+ for (int i = 0; i < d.colorAttCount; ++i) {
+ QVkTexture *texD = QRHI_RES(QVkTexture, colorAttachments[i].texture());
+ QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, colorAttachments[i].renderBuffer());
+ Q_ASSERT(texD || rbD);
+ if (texD) {
+ Q_ASSERT(texD->flags().testFlag(QRhiTexture::RenderTarget));
+ VkImageViewCreateInfo viewInfo;
+ memset(&viewInfo, 0, sizeof(viewInfo));
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.image = texD->image;
+ viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = texD->vkformat;
+ 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.baseMipLevel = colorAttachments[i].level();
+ viewInfo.subresourceRange.levelCount = 1;
+ viewInfo.subresourceRange.baseArrayLayer = colorAttachments[i].layer();
+ viewInfo.subresourceRange.layerCount = 1;
+ VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &rtv[i]);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create render target image view: %d", err);
+ return false;
+ }
+ views.append(rtv[i]);
+ if (i == 0) {
+ d.pixelSize = texD->pixelSize();
+ d.sampleCount = texD->samples;
+ }
+ } else if (rbD) {
+ Q_ASSERT(rbD->backingTexture);
+ views.append(rbD->backingTexture->imageView);
+ if (i == 0) {
+ d.pixelSize = rbD->pixelSize();
+ d.sampleCount = rbD->samples;
+ }
+ }
+ }
+ d.dpr = 1;
+
+ if (hasDepthStencil) {
+ if (m_desc.depthTexture()) {
+ QVkTexture *depthTexD = QRHI_RES(QVkTexture, m_desc.depthTexture());
+ views.append(depthTexD->imageView);
+ if (d.colorAttCount == 0) {
+ d.pixelSize = depthTexD->pixelSize();
+ d.sampleCount = depthTexD->samples;
+ }
+ } else {
+ QVkRenderBuffer *depthRbD = QRHI_RES(QVkRenderBuffer, m_desc.depthStencilBuffer());
+ views.append(depthRbD->imageView);
+ if (d.colorAttCount == 0) {
+ d.pixelSize = depthRbD->pixelSize();
+ d.sampleCount = depthRbD->samples;
+ }
+ }
+ d.dsAttCount = 1;
+ } else {
+ d.dsAttCount = 0;
+ }
+
+ d.resolveAttCount = 0;
+ for (int i = 0; i < d.colorAttCount; ++i) {
+ if (colorAttachments[i].resolveTexture()) {
+ QVkTexture *resTexD = QRHI_RES(QVkTexture, colorAttachments[i].resolveTexture());
+ Q_ASSERT(resTexD->flags().testFlag(QRhiTexture::RenderTarget));
+ d.resolveAttCount += 1;
+
+ VkImageViewCreateInfo viewInfo;
+ memset(&viewInfo, 0, sizeof(viewInfo));
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.image = resTexD->image;
+ viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = resTexD->vkformat;
+ 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.baseMipLevel = colorAttachments[i].resolveLevel();
+ viewInfo.subresourceRange.levelCount = 1;
+ viewInfo.subresourceRange.baseArrayLayer = colorAttachments[i].resolveLayer();
+ viewInfo.subresourceRange.layerCount = 1;
+ VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &resrtv[i]);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create render target resolve image view: %d", err);
+ return false;
+ }
+ views.append(resrtv[i]);
+ }
+ }
+
+ if (!m_renderPassDesc)
+ qWarning("QVkTextureRenderTarget: No renderpass descriptor set. See newCompatibleRenderPassDescriptor() and setRenderPassDescriptor().");
+
+ d.rp = QRHI_RES(QVkRenderPassDescriptor, m_renderPassDesc);
+ Q_ASSERT(d.rp && d.rp->rp);
+
+ VkFramebufferCreateInfo fbInfo;
+ memset(&fbInfo, 0, sizeof(fbInfo));
+ fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fbInfo.renderPass = d.rp->rp;
+ fbInfo.attachmentCount = d.colorAttCount + d.dsAttCount + d.resolveAttCount;
+ fbInfo.pAttachments = views.constData();
+ fbInfo.width = d.pixelSize.width();
+ fbInfo.height = d.pixelSize.height();
+ fbInfo.layers = 1;
+
+ VkResult err = rhiD->df->vkCreateFramebuffer(rhiD->dev, &fbInfo, nullptr, &d.fb);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create framebuffer: %d", err);
+ return false;
+ }
+
+ lastActiveFrameSlot = -1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QSize QVkTextureRenderTarget::pixelSize() const
+{
+ return d.pixelSize;
+}
+
+float QVkTextureRenderTarget::devicePixelRatio() const
+{
+ return d.dpr;
+}
+
+int QVkTextureRenderTarget::sampleCount() const
+{
+ return d.sampleCount;
+}
+
+QVkShaderResourceBindings::QVkShaderResourceBindings(QRhiImplementation *rhi)
+ : QRhiShaderResourceBindings(rhi)
+{
+}
+
+QVkShaderResourceBindings::~QVkShaderResourceBindings()
+{
+ release();
+}
+
+void QVkShaderResourceBindings::release()
+{
+ if (!layout)
+ return;
+
+ sortedBindings.clear();
+
+ QRhiVulkan::DeferredReleaseEntry e;
+ e.type = QRhiVulkan::DeferredReleaseEntry::ShaderResourceBindings;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ e.shaderResourceBindings.poolIndex = poolIndex;
+ e.shaderResourceBindings.layout = layout;
+
+ poolIndex = -1;
+ layout = VK_NULL_HANDLE;
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
+ descSets[i] = VK_NULL_HANDLE;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->releaseQueue.append(e);
+
+ rhiD->unregisterResource(this);
+}
+
+bool QVkShaderResourceBindings::build()
+{
+ if (layout)
+ release();
+
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
+ descSets[i] = VK_NULL_HANDLE;
+
+ sortedBindings = m_bindings;
+ std::sort(sortedBindings.begin(), sortedBindings.end(),
+ [](const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
+ {
+ return QRhiShaderResourceBindingPrivate::get(&a)->binding < QRhiShaderResourceBindingPrivate::get(&b)->binding;
+ });
+
+ QVarLengthArray<VkDescriptorSetLayoutBinding, 4> vkbindings;
+ for (const QRhiShaderResourceBinding &binding : qAsConst(sortedBindings)) {
+ const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&binding);
+ VkDescriptorSetLayoutBinding vkbinding;
+ memset(&vkbinding, 0, sizeof(vkbinding));
+ vkbinding.binding = b->binding;
+ vkbinding.descriptorType = toVkDescriptorType(b);
+ vkbinding.descriptorCount = 1; // no array support yet
+ vkbinding.stageFlags = toVkShaderStageFlags(b->stage);
+ vkbindings.append(vkbinding);
+ }
+
+ VkDescriptorSetLayoutCreateInfo layoutInfo;
+ memset(&layoutInfo, 0, sizeof(layoutInfo));
+ layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ layoutInfo.bindingCount = uint32_t(vkbindings.count());
+ layoutInfo.pBindings = vkbindings.constData();
+
+ QRHI_RES_RHI(QRhiVulkan);
+ VkResult err = rhiD->df->vkCreateDescriptorSetLayout(rhiD->dev, &layoutInfo, nullptr, &layout);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create descriptor set layout: %d", err);
+ return false;
+ }
+
+ VkDescriptorSetAllocateInfo allocInfo;
+ memset(&allocInfo, 0, sizeof(allocInfo));
+ allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ allocInfo.descriptorSetCount = QVK_FRAMES_IN_FLIGHT;
+ VkDescriptorSetLayout layouts[QVK_FRAMES_IN_FLIGHT];
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
+ layouts[i] = layout;
+ allocInfo.pSetLayouts = layouts;
+ if (!rhiD->allocateDescriptorSet(&allocInfo, descSets, &poolIndex))
+ return false;
+
+ rhiD->updateShaderResourceBindings(this);
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QVkGraphicsPipeline::QVkGraphicsPipeline(QRhiImplementation *rhi)
+ : QRhiGraphicsPipeline(rhi)
+{
+}
+
+QVkGraphicsPipeline::~QVkGraphicsPipeline()
+{
+ release();
+}
+
+void QVkGraphicsPipeline::release()
+{
+ if (!pipeline && !layout)
+ return;
+
+ QRhiVulkan::DeferredReleaseEntry e;
+ e.type = QRhiVulkan::DeferredReleaseEntry::Pipeline;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+
+ e.pipelineState.pipeline = pipeline;
+ e.pipelineState.layout = layout;
+
+ pipeline = VK_NULL_HANDLE;
+ layout = VK_NULL_HANDLE;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->releaseQueue.append(e);
+
+ rhiD->unregisterResource(this);
+}
+
+bool QVkGraphicsPipeline::build()
+{
+ if (pipeline)
+ release();
+
+ QRHI_RES_RHI(QRhiVulkan);
+ if (!rhiD->ensurePipelineCache())
+ return false;
+
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, m_shaderResourceBindings);
+ Q_ASSERT(m_shaderResourceBindings && srbD->layout);
+ pipelineLayoutInfo.pSetLayouts = &srbD->layout;
+ VkResult err = rhiD->df->vkCreatePipelineLayout(rhiD->dev, &pipelineLayoutInfo, nullptr, &layout);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create pipeline layout: %d", err);
+ return false;
+ }
+
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ QVarLengthArray<VkShaderModule, 4> shaders;
+ QVarLengthArray<VkPipelineShaderStageCreateInfo, 4> shaderStageCreateInfos;
+ for (const QRhiGraphicsShaderStage &shaderStage : m_shaderStages) {
+ const QShader bakedShader = shaderStage.shader();
+ const QShaderCode spirv = bakedShader.shader({ QShader::SpirvShader, 100, shaderStage.shaderVariant() });
+ if (spirv.shader().isEmpty()) {
+ qWarning() << "No SPIR-V 1.0 shader code found in baked shader" << bakedShader;
+ return false;
+ }
+ VkShaderModule shader = rhiD->createShader(spirv.shader());
+ if (shader) {
+ shaders.append(shader);
+ VkPipelineShaderStageCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ shaderInfo.stage = toVkShaderStage(shaderStage.type());
+ shaderInfo.module = shader;
+ shaderInfo.pName = spirv.entryPoint().constData();
+ shaderStageCreateInfos.append(shaderInfo);
+ }
+ }
+ pipelineInfo.stageCount = shaderStageCreateInfos.count();
+ pipelineInfo.pStages = shaderStageCreateInfos.constData();
+
+ const QVector<QRhiVertexInputBinding> bindings = m_vertexInputLayout.bindings();
+ QVarLengthArray<VkVertexInputBindingDescription, 4> vertexBindings;
+ QVarLengthArray<VkVertexInputBindingDivisorDescriptionEXT> nonOneStepRates;
+ for (int i = 0, ie = bindings.count(); i != ie; ++i) {
+ const QRhiVertexInputBinding &binding(bindings[i]);
+ VkVertexInputBindingDescription bindingInfo = {
+ uint32_t(i),
+ binding.stride(),
+ binding.classification() == QRhiVertexInputBinding::PerVertex
+ ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE
+ };
+ if (binding.classification() == QRhiVertexInputBinding::PerInstance
+ && binding.instanceStepRate() != 1)
+ {
+ if (rhiD->vertexAttribDivisorAvailable) {
+ nonOneStepRates.append({ uint32_t(i), uint32_t(binding.instanceStepRate()) });
+ } else {
+ qWarning("QRhiVulkan: Instance step rates other than 1 not supported without "
+ "VK_EXT_vertex_attribute_divisor on the device and "
+ "VK_KHR_get_physical_device_properties2 on the instance");
+ }
+ }
+ vertexBindings.append(bindingInfo);
+ }
+ const QVector<QRhiVertexInputAttribute> attributes = m_vertexInputLayout.attributes();
+ QVarLengthArray<VkVertexInputAttributeDescription, 4> vertexAttributes;
+ for (const QRhiVertexInputAttribute &attribute : attributes) {
+ VkVertexInputAttributeDescription attributeInfo = {
+ uint32_t(attribute.location()),
+ uint32_t(attribute.binding()),
+ toVkAttributeFormat(attribute.format()),
+ attribute.offset()
+ };
+ vertexAttributes.append(attributeInfo);
+ }
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ memset(&vertexInputInfo, 0, sizeof(vertexInputInfo));
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.vertexBindingDescriptionCount = vertexBindings.count();
+ vertexInputInfo.pVertexBindingDescriptions = vertexBindings.constData();
+ vertexInputInfo.vertexAttributeDescriptionCount = vertexAttributes.count();
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttributes.constData();
+ VkPipelineVertexInputDivisorStateCreateInfoEXT divisorInfo;
+ if (!nonOneStepRates.isEmpty()) {
+ memset(&divisorInfo, 0, sizeof(divisorInfo));
+ divisorInfo.sType = VkStructureType(1000190001); // VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT
+ divisorInfo.vertexBindingDivisorCount = nonOneStepRates.count();
+ divisorInfo.pVertexBindingDivisors = nonOneStepRates.constData();
+ vertexInputInfo.pNext = &divisorInfo;
+ }
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ QVarLengthArray<VkDynamicState, 8> dynEnable;
+ dynEnable << VK_DYNAMIC_STATE_VIEWPORT;
+ dynEnable << VK_DYNAMIC_STATE_SCISSOR; // ignore UsesScissor - Vulkan requires a scissor for the viewport always
+ if (m_flags.testFlag(QRhiGraphicsPipeline::UsesBlendConstants))
+ dynEnable << VK_DYNAMIC_STATE_BLEND_CONSTANTS;
+ if (m_flags.testFlag(QRhiGraphicsPipeline::UsesStencilRef))
+ dynEnable << VK_DYNAMIC_STATE_STENCIL_REFERENCE;
+
+ VkPipelineDynamicStateCreateInfo dynamicInfo;
+ memset(&dynamicInfo, 0, sizeof(dynamicInfo));
+ dynamicInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dynamicInfo.dynamicStateCount = dynEnable.count();
+ dynamicInfo.pDynamicStates = dynEnable.constData();
+ pipelineInfo.pDynamicState = &dynamicInfo;
+
+ VkPipelineViewportStateCreateInfo viewportInfo;
+ memset(&viewportInfo, 0, sizeof(viewportInfo));
+ viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ viewportInfo.viewportCount = viewportInfo.scissorCount = 1;
+ pipelineInfo.pViewportState = &viewportInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo inputAsmInfo;
+ memset(&inputAsmInfo, 0, sizeof(inputAsmInfo));
+ inputAsmInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ inputAsmInfo.topology = toVkTopology(m_topology);
+ inputAsmInfo.primitiveRestartEnable = (m_topology == TriangleStrip || m_topology == LineStrip);
+ pipelineInfo.pInputAssemblyState = &inputAsmInfo;
+
+ VkPipelineRasterizationStateCreateInfo rastInfo;
+ memset(&rastInfo, 0, sizeof(rastInfo));
+ rastInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rastInfo.cullMode = toVkCullMode(m_cullMode);
+ rastInfo.frontFace = toVkFrontFace(m_frontFace);
+ rastInfo.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rastInfo;
+
+ VkPipelineMultisampleStateCreateInfo msInfo;
+ memset(&msInfo, 0, sizeof(msInfo));
+ msInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ msInfo.rasterizationSamples = rhiD->effectiveSampleCount(m_sampleCount);
+ pipelineInfo.pMultisampleState = &msInfo;
+
+ VkPipelineDepthStencilStateCreateInfo dsInfo;
+ memset(&dsInfo, 0, sizeof(dsInfo));
+ dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ dsInfo.depthTestEnable = m_depthTest;
+ dsInfo.depthWriteEnable = m_depthWrite;
+ dsInfo.depthCompareOp = toVkCompareOp(m_depthOp);
+ dsInfo.stencilTestEnable = m_stencilTest;
+ if (m_stencilTest) {
+ fillVkStencilOpState(&dsInfo.front, m_stencilFront);
+ dsInfo.front.compareMask = m_stencilReadMask;
+ dsInfo.front.writeMask = m_stencilWriteMask;
+ fillVkStencilOpState(&dsInfo.back, m_stencilBack);
+ dsInfo.back.compareMask = m_stencilReadMask;
+ dsInfo.back.writeMask = m_stencilWriteMask;
+ }
+ pipelineInfo.pDepthStencilState = &dsInfo;
+
+ VkPipelineColorBlendStateCreateInfo blendInfo;
+ memset(&blendInfo, 0, sizeof(blendInfo));
+ blendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ QVarLengthArray<VkPipelineColorBlendAttachmentState, 4> vktargetBlends;
+ for (const QRhiGraphicsPipeline::TargetBlend &b : qAsConst(m_targetBlends)) {
+ VkPipelineColorBlendAttachmentState blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.blendEnable = b.enable;
+ blend.srcColorBlendFactor = toVkBlendFactor(b.srcColor);
+ blend.dstColorBlendFactor = toVkBlendFactor(b.dstColor);
+ blend.colorBlendOp = toVkBlendOp(b.opColor);
+ blend.srcAlphaBlendFactor = toVkBlendFactor(b.srcAlpha);
+ blend.dstAlphaBlendFactor = toVkBlendFactor(b.dstAlpha);
+ blend.alphaBlendOp = toVkBlendOp(b.opAlpha);
+ blend.colorWriteMask = toVkColorComponents(b.colorWrite);
+ vktargetBlends.append(blend);
+ }
+ if (vktargetBlends.isEmpty()) {
+ VkPipelineColorBlendAttachmentState blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
+ | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+ vktargetBlends.append(blend);
+ }
+ blendInfo.attachmentCount = vktargetBlends.count();
+ blendInfo.pAttachments = vktargetBlends.constData();
+ pipelineInfo.pColorBlendState = &blendInfo;
+
+ pipelineInfo.layout = layout;
+
+ Q_ASSERT(m_renderPassDesc && QRHI_RES(const QVkRenderPassDescriptor, m_renderPassDesc)->rp);
+ pipelineInfo.renderPass = QRHI_RES(const QVkRenderPassDescriptor, m_renderPassDesc)->rp;
+
+ err = rhiD->df->vkCreateGraphicsPipelines(rhiD->dev, rhiD->pipelineCache, 1, &pipelineInfo, nullptr, &pipeline);
+
+ for (VkShaderModule shader : shaders)
+ rhiD->df->vkDestroyShaderModule(rhiD->dev, shader, nullptr);
+
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create graphics pipeline: %d", err);
+ return false;
+ }
+
+ lastActiveFrameSlot = -1;
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QVkCommandBuffer::QVkCommandBuffer(QRhiImplementation *rhi)
+ : QRhiCommandBuffer(rhi)
+{
+ resetState();
+}
+
+QVkCommandBuffer::~QVkCommandBuffer()
+{
+ release();
+}
+
+void QVkCommandBuffer::release()
+{
+ // nothing to do here, cb is not owned by us
+}
+
+QVkSwapChain::QVkSwapChain(QRhiImplementation *rhi)
+ : QRhiSwapChain(rhi),
+ rtWrapper(rhi),
+ cbWrapper(rhi)
+{
+}
+
+QVkSwapChain::~QVkSwapChain()
+{
+ release();
+}
+
+void QVkSwapChain::release()
+{
+ if (sc == VK_NULL_HANDLE)
+ return;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->swapchains.remove(this);
+ rhiD->releaseSwapChainResources(this);
+ surface = lastConnectedSurface = VK_NULL_HANDLE;
+
+ QRHI_PROF;
+ QRHI_PROF_F(releaseSwapChain(this));
+
+ rhiD->unregisterResource(this);
+}
+
+QRhiCommandBuffer *QVkSwapChain::currentFrameCommandBuffer()
+{
+ return &cbWrapper;
+}
+
+QRhiRenderTarget *QVkSwapChain::currentFrameRenderTarget()
+{
+ return &rtWrapper;
+}
+
+QSize QVkSwapChain::surfacePixelSize()
+{
+ if (!ensureSurface())
+ return QSize();
+
+ // The size from the QWindow may not exactly match the surface... so if a
+ // size is reported from the surface, use that.
+ VkSurfaceCapabilitiesKHR surfaceCaps;
+ memset(&surfaceCaps, 0, sizeof(surfaceCaps));
+ QRHI_RES_RHI(QRhiVulkan);
+ rhiD->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(rhiD->physDev, surface, &surfaceCaps);
+ VkExtent2D bufferSize = surfaceCaps.currentExtent;
+ if (bufferSize.width == quint32(-1)) {
+ Q_ASSERT(bufferSize.height == quint32(-1));
+ return m_window->size() * m_window->devicePixelRatio();
+ }
+ return QSize(bufferSize.width, bufferSize.height);
+}
+
+QRhiRenderPassDescriptor *QVkSwapChain::newCompatibleRenderPassDescriptor()
+{
+ // not yet built so cannot rely on data computed in buildOrResize()
+
+ if (!ensureSurface()) // make sure sampleCount and colorFormat reflect what was requested
+ return nullptr;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ QVkRenderPassDescriptor *rp = new QVkRenderPassDescriptor(m_rhi);
+ if (!rhiD->createDefaultRenderPass(&rp->rp,
+ m_depthStencil != nullptr,
+ samples,
+ colorFormat))
+ {
+ delete rp;
+ return nullptr;
+ }
+
+ rp->ownsRp = true;
+ rhiD->registerResource(rp);
+ return rp;
+}
+
+static inline bool isSrgbFormat(VkFormat format)
+{
+ switch (format) {
+ case VK_FORMAT_R8_SRGB:
+ Q_FALLTHROUGH();
+ case VK_FORMAT_R8G8_SRGB:
+ Q_FALLTHROUGH();
+ case VK_FORMAT_R8G8B8_SRGB:
+ Q_FALLTHROUGH();
+ case VK_FORMAT_B8G8R8_SRGB:
+ Q_FALLTHROUGH();
+ case VK_FORMAT_R8G8B8A8_SRGB:
+ Q_FALLTHROUGH();
+ case VK_FORMAT_B8G8R8A8_SRGB:
+ Q_FALLTHROUGH();
+ case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool QVkSwapChain::ensureSurface()
+{
+ // Do nothing when already done, however window may change so check the
+ // surface is still the same. Some of the queries below are very expensive
+ // with some implementations so it is important to do the rest only once
+ // per surface.
+
+ Q_ASSERT(m_window);
+ VkSurfaceKHR surf = QVulkanInstance::surfaceForWindow(m_window);
+ if (!surf) {
+ qWarning("Failed to get surface for window");
+ return false;
+ }
+ if (surface == surf)
+ return true;
+
+ surface = surf;
+
+ QRHI_RES_RHI(QRhiVulkan);
+ if (rhiD->gfxQueueFamilyIdx != -1) {
+ if (!rhiD->inst->supportsPresent(rhiD->physDev, rhiD->gfxQueueFamilyIdx, m_window)) {
+ qWarning("Presenting not supported on this window");
+ return false;
+ }
+ }
+
+ if (!rhiD->vkGetPhysicalDeviceSurfaceCapabilitiesKHR) {
+ rhiD->vkGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
+ rhiD->inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
+ rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
+ rhiD->inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfaceFormatsKHR"));
+ rhiD->vkGetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(
+ rhiD->inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfacePresentModesKHR"));
+ if (!rhiD->vkGetPhysicalDeviceSurfaceCapabilitiesKHR
+ || !rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR
+ || !rhiD->vkGetPhysicalDeviceSurfacePresentModesKHR)
+ {
+ qWarning("Physical device surface queries not available");
+ return false;
+ }
+ }
+
+ quint32 formatCount = 0;
+ rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR(rhiD->physDev, surface, &formatCount, nullptr);
+ QVector<VkSurfaceFormatKHR> formats(formatCount);
+ if (formatCount)
+ rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR(rhiD->physDev, surface, &formatCount, formats.data());
+
+ const bool srgbRequested = m_flags.testFlag(sRGB);
+ for (quint32 i = 0; i < formatCount; ++i) {
+ if (formats[i].format != VK_FORMAT_UNDEFINED && srgbRequested == isSrgbFormat(formats[i].format)) {
+ colorFormat = formats[i].format;
+ colorSpace = formats[i].colorSpace;
+ break;
+ }
+ }
+
+ samples = rhiD->effectiveSampleCount(m_sampleCount);
+
+ quint32 presModeCount = 0;
+ rhiD->vkGetPhysicalDeviceSurfacePresentModesKHR(rhiD->physDev, surface, &presModeCount, nullptr);
+ QVector<VkPresentModeKHR> presModes(presModeCount);
+ rhiD->vkGetPhysicalDeviceSurfacePresentModesKHR(rhiD->physDev, surface, &presModeCount, presModes.data());
+ supportedPresentationModes = presModes;
+
+ return true;
+}
+
+bool QVkSwapChain::buildOrResize()
+{
+ QRHI_RES_RHI(QRhiVulkan);
+ const bool needsRegistration = !window || window != m_window;
+
+ // Can be called multiple times due to window resizes - that is not the
+ // same as a simple release+build (as with other resources). Thus no
+ // release() here. See recreateSwapChain().
+
+ // except if the window actually changes
+ if (window && window != m_window)
+ release();
+
+ window = m_window;
+ m_currentPixelSize = surfacePixelSize();
+ pixelSize = m_currentPixelSize;
+
+ if (!rhiD->recreateSwapChain(this)) {
+ qWarning("Failed to create new swapchain");
+ return false;
+ }
+
+ if (needsRegistration)
+ rhiD->swapchains.insert(this);
+
+ if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
+ qWarning("Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
+ m_depthStencil->sampleCount(), m_sampleCount);
+ }
+ if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
+ qWarning("Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
+ m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
+ pixelSize.width(), pixelSize.height());
+ }
+
+ if (!m_renderPassDesc)
+ qWarning("QVkSwapChain: No renderpass descriptor set. See newCompatibleRenderPassDescriptor() and setRenderPassDescriptor().");
+
+ rtWrapper.d.rp = QRHI_RES(QVkRenderPassDescriptor, m_renderPassDesc);
+ Q_ASSERT(rtWrapper.d.rp && rtWrapper.d.rp->rp);
+
+ rtWrapper.d.pixelSize = pixelSize;
+ rtWrapper.d.dpr = window->devicePixelRatio();
+ rtWrapper.d.sampleCount = samples;
+ rtWrapper.d.colorAttCount = 1;
+ if (m_depthStencil) {
+ rtWrapper.d.dsAttCount = 1;
+ ds = QRHI_RES(QVkRenderBuffer, m_depthStencil);
+ } else {
+ rtWrapper.d.dsAttCount = 0;
+ ds = nullptr;
+ }
+ if (samples > VK_SAMPLE_COUNT_1_BIT)
+ rtWrapper.d.resolveAttCount = 1;
+ else
+ rtWrapper.d.resolveAttCount = 0;
+
+ for (int i = 0; i < bufferCount; ++i) {
+ QVkSwapChain::ImageResources &image(imageRes[i]);
+ VkImageView views[3] = { // color, ds, resolve
+ samples > VK_SAMPLE_COUNT_1_BIT ? image.msaaImageView : image.imageView,
+ ds ? ds->imageView : VK_NULL_HANDLE,
+ samples > VK_SAMPLE_COUNT_1_BIT ? image.imageView : VK_NULL_HANDLE
+ };
+
+ VkFramebufferCreateInfo fbInfo;
+ memset(&fbInfo, 0, sizeof(fbInfo));
+ fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fbInfo.renderPass = rtWrapper.d.rp->rp;
+ fbInfo.attachmentCount = rtWrapper.d.colorAttCount + rtWrapper.d.dsAttCount + rtWrapper.d.resolveAttCount;
+ fbInfo.pAttachments = views;
+ fbInfo.width = pixelSize.width();
+ fbInfo.height = pixelSize.height();
+ fbInfo.layers = 1;
+
+ VkResult err = rhiD->df->vkCreateFramebuffer(rhiD->dev, &fbInfo, nullptr, &image.fb);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create framebuffer: %d", err);
+ return false;
+ }
+ }
+
+ frameCount = 0;
+
+ QRHI_PROF;
+ QRHI_PROF_F(resizeSwapChain(this, QVK_FRAMES_IN_FLIGHT, samples > VK_SAMPLE_COUNT_1_BIT ? QVK_FRAMES_IN_FLIGHT : 0, samples));
+
+ if (needsRegistration)
+ rhiD->registerResource(this);
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h
new file mode 100644
index 0000000000..545ef5ad72
--- /dev/null
+++ b/src/gui/rhi/qrhivulkan_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHIVULKAN_H
+#define QRHIVULKAN_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qrhi_p.h>
+#include <QtGui/qvulkaninstance.h> // this is where vulkan.h gets pulled in
+
+QT_BEGIN_NAMESPACE
+
+struct Q_GUI_EXPORT QRhiVulkanInitParams : public QRhiInitParams
+{
+ QVulkanInstance *inst = nullptr;
+ QWindow *window = nullptr;
+};
+
+struct Q_GUI_EXPORT QRhiVulkanNativeHandles : public QRhiNativeHandles
+{
+ VkPhysicalDevice physDev = VK_NULL_HANDLE;
+ VkDevice dev = VK_NULL_HANDLE;
+ int gfxQueueFamilyIdx = -1;
+ VkQueue gfxQueue = VK_NULL_HANDLE;
+ VkCommandPool cmdPool = VK_NULL_HANDLE;
+ void *vmemAllocator = nullptr;
+};
+
+struct Q_GUI_EXPORT QRhiVulkanTextureNativeHandles : public QRhiNativeHandles
+{
+ VkImage image = VK_NULL_HANDLE;
+ VkImageLayout layout = VK_IMAGE_LAYOUT_GENERAL;
+};
+
+struct Q_GUI_EXPORT QRhiVulkanCommandBufferNativeHandles : public QRhiNativeHandles
+{
+ VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
new file mode 100644
index 0000000000..01acc40d58
--- /dev/null
+++ b/src/gui/rhi/qrhivulkan_p_p.h
@@ -0,0 +1,859 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHIVULKAN_P_H
+#define QRHIVULKAN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrhivulkan_p.h"
+#include "qrhi_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QVulkanFunctions;
+class QVulkanDeviceFunctions;
+
+static const int QVK_FRAMES_IN_FLIGHT = 2;
+
+static const int QVK_DESC_SETS_PER_POOL = 128;
+static const int QVK_UNIFORM_BUFFERS_PER_POOL = 256;
+static const int QVK_COMBINED_IMAGE_SAMPLERS_PER_POOL = 256;
+
+static const int QVK_MAX_ACTIVE_TIMESTAMP_PAIRS = 16;
+
+// no vk_mem_alloc.h available here, void* is good enough
+typedef void * QVkAlloc;
+typedef void * QVkAllocator;
+
+struct QVkBuffer : public QRhiBuffer
+{
+ QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
+ ~QVkBuffer();
+ void release() override;
+ bool build() override;
+
+ VkBuffer buffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];
+ QVector<QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate> pendingDynamicUpdates[QVK_FRAMES_IN_FLIGHT];
+ VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
+ struct UsageState {
+ VkAccessFlags access = 0;
+ VkPipelineStageFlags stage = 0;
+ };
+ UsageState usageState[QVK_FRAMES_IN_FLIGHT];
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+ friend class QRhiVulkan;
+};
+
+struct QVkTexture;
+
+struct QVkRenderBuffer : public QRhiRenderBuffer
+{
+ QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, Flags flags);
+ ~QVkRenderBuffer();
+ void release() override;
+ bool build() override;
+ QRhiTexture::Format backingFormat() const override;
+
+ VkDeviceMemory memory = VK_NULL_HANDLE;
+ VkImage image = VK_NULL_HANDLE;
+ VkImageView imageView = VK_NULL_HANDLE;
+ VkSampleCountFlagBits samples;
+ QVkTexture *backingTexture = nullptr;
+ VkFormat vkformat;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiVulkan;
+};
+
+struct QVkTexture : public QRhiTexture
+{
+ QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
+ int sampleCount, Flags flags);
+ ~QVkTexture();
+ void release() override;
+ bool build() override;
+ bool buildFrom(const QRhiNativeHandles *src) override;
+ const QRhiNativeHandles *nativeHandles() override;
+
+ bool prepareBuild(QSize *adjustedSize = nullptr);
+ bool finishBuild();
+
+ VkImage image = VK_NULL_HANDLE;
+ VkImageView imageView = VK_NULL_HANDLE;
+ QVkAlloc imageAlloc = nullptr;
+ VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
+ bool owns = true;
+ QRhiVulkanTextureNativeHandles nativeHandlesStruct;
+ struct UsageState {
+ // no tracking of subresource layouts (some operations can keep
+ // subresources in different layouts for some time, but that does not
+ // need to be kept track of)
+ VkImageLayout layout;
+ VkAccessFlags access;
+ VkPipelineStageFlags stage;
+ };
+ UsageState usageState;
+ VkFormat vkformat;
+ uint mipLevelCount = 0;
+ VkSampleCountFlagBits samples;
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+ friend class QRhiVulkan;
+};
+
+struct QVkSampler : public QRhiSampler
+{
+ QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v);
+ ~QVkSampler();
+ void release() override;
+ bool build() override;
+
+ VkSampler sampler = VK_NULL_HANDLE;
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+ friend class QRhiVulkan;
+};
+
+struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QVkRenderPassDescriptor(QRhiImplementation *rhi);
+ ~QVkRenderPassDescriptor();
+ void release() override;
+
+ VkRenderPass rp = VK_NULL_HANDLE;
+ bool ownsRp = false;
+ int lastActiveFrameSlot = -1;
+};
+
+struct QVkRenderTargetData
+{
+ VkFramebuffer fb = VK_NULL_HANDLE;
+ QVkRenderPassDescriptor *rp = nullptr;
+ QSize pixelSize;
+ float dpr = 1;
+ int sampleCount = 1;
+ int colorAttCount = 0;
+ int dsAttCount = 0;
+ int resolveAttCount = 0;
+ static const int MAX_COLOR_ATTACHMENTS = 8;
+};
+
+struct QVkReferenceRenderTarget : public QRhiRenderTarget
+{
+ QVkReferenceRenderTarget(QRhiImplementation *rhi);
+ ~QVkReferenceRenderTarget();
+ void release() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QVkRenderTargetData d;
+};
+
+struct QVkTextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QVkTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
+ ~QVkTextureRenderTarget();
+ void release() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool build() override;
+
+ QVkRenderTargetData d;
+ VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
+ VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
+ int lastActiveFrameSlot = -1;
+ friend class QRhiVulkan;
+};
+
+struct QVkShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QVkShaderResourceBindings(QRhiImplementation *rhi);
+ ~QVkShaderResourceBindings();
+ void release() override;
+ bool build() override;
+
+ QVector<QRhiShaderResourceBinding> sortedBindings;
+ int poolIndex = -1;
+ VkDescriptorSetLayout layout = VK_NULL_HANDLE;
+ VkDescriptorSet descSets[QVK_FRAMES_IN_FLIGHT]; // multiple sets to support dynamic buffers
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+
+ // Keep track of the generation number of each referenced QRhi* to be able
+ // to detect that the underlying descriptor set became out of date and they
+ // need to be written again with the up-to-date VkBuffer etc. objects.
+ struct BoundUniformBufferData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundSampledTextureData {
+ quint64 texId;
+ uint texGeneration;
+ quint64 samplerId;
+ uint samplerGeneration;
+ };
+ struct BoundResourceData {
+ union {
+ BoundUniformBufferData ubuf;
+ BoundSampledTextureData stex;
+ };
+ };
+ QVector<BoundResourceData> boundResourceData[QVK_FRAMES_IN_FLIGHT];
+
+ friend class QRhiVulkan;
+};
+
+Q_DECLARE_TYPEINFO(QVkShaderResourceBindings::BoundResourceData, Q_MOVABLE_TYPE);
+
+struct QVkGraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QVkGraphicsPipeline(QRhiImplementation *rhi);
+ ~QVkGraphicsPipeline();
+ void release() override;
+ bool build() override;
+
+ VkPipelineLayout layout = VK_NULL_HANDLE;
+ VkPipeline pipeline = VK_NULL_HANDLE;
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+ friend class QRhiVulkan;
+};
+
+struct QVkCommandBuffer : public QRhiCommandBuffer
+{
+ QVkCommandBuffer(QRhiImplementation *rhi);
+ ~QVkCommandBuffer();
+ void release() override;
+
+ VkCommandBuffer cb = VK_NULL_HANDLE;
+ QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct;
+
+ const QRhiNativeHandles *nativeHandles() {
+ nativeHandlesStruct.commandBuffer = cb;
+ return &nativeHandlesStruct;
+ }
+
+ void resetState() {
+ resetCommands();
+ currentTarget = nullptr;
+ resetCachedState();
+ }
+
+ void resetCachedState() {
+ currentPipeline = nullptr;
+ currentPipelineGeneration = 0;
+ currentSrb = nullptr;
+ currentSrbGeneration = 0;
+ currentDescSetSlot = -1;
+ currentIndexBuffer = VK_NULL_HANDLE;
+ currentIndexOffset = 0;
+ currentIndexFormat = VK_INDEX_TYPE_UINT16;
+ memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
+ memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
+ }
+
+ QRhiRenderTarget *currentTarget;
+ QRhiGraphicsPipeline *currentPipeline;
+ uint currentPipelineGeneration;
+ QRhiShaderResourceBindings *currentSrb;
+ uint currentSrbGeneration;
+ int currentDescSetSlot;
+ VkBuffer currentIndexBuffer;
+ quint32 currentIndexOffset;
+ VkIndexType currentIndexFormat;
+ static const int VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32;
+ VkBuffer currentVertexBuffers[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ quint32 currentVertexOffsets[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+
+ struct Command {
+ enum Cmd {
+ CopyBuffer,
+ CopyBufferToImage,
+ CopyImage,
+ CopyImageToBuffer,
+ ImageBarrier,
+ BufferBarrier,
+ BlitImage,
+ BeginRenderPass,
+ EndRenderPass,
+ BindPipeline,
+ BindDescriptorSet,
+ BindVertexBuffer,
+ BindIndexBuffer,
+ SetViewport,
+ SetScissor,
+ SetBlendConstants,
+ SetStencilRef,
+ Draw,
+ DrawIndexed,
+ DebugMarkerBegin,
+ DebugMarkerEnd,
+ DebugMarkerInsert,
+ TransitionPassResources
+ };
+ Cmd cmd;
+
+ union Args {
+ struct {
+ VkBuffer src;
+ VkBuffer dst;
+ VkBufferCopy desc;
+ } copyBuffer;
+ struct {
+ VkBuffer src;
+ VkImage dst;
+ VkImageLayout dstLayout;
+ int count;
+ int bufferImageCopyIndex;
+ } copyBufferToImage;
+ struct {
+ VkImage src;
+ VkImageLayout srcLayout;
+ VkImage dst;
+ VkImageLayout dstLayout;
+ VkImageCopy desc;
+ } copyImage;
+ struct {
+ VkImage src;
+ VkImageLayout srcLayout;
+ VkBuffer dst;
+ VkBufferImageCopy desc;
+ } copyImageToBuffer;
+ struct {
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
+ VkImageMemoryBarrier desc;
+ } imageBarrier;
+ struct {
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
+ VkBufferMemoryBarrier desc;
+ } bufferBarrier;
+ struct {
+ VkImage src;
+ VkImageLayout srcLayout;
+ VkImage dst;
+ VkImageLayout dstLayout;
+ VkFilter filter;
+ VkImageBlit desc;
+ } blitImage;
+ struct {
+ VkRenderPassBeginInfo desc;
+ int clearValueIndex;
+ } beginRenderPass;
+ struct {
+ } endRenderPass;
+ struct {
+ VkPipelineBindPoint bindPoint;
+ VkPipeline pipeline;
+ } bindPipeline;
+ struct {
+ VkPipelineBindPoint bindPoint;
+ VkPipelineLayout pipelineLayout;
+ VkDescriptorSet descSet;
+ int dynamicOffsetCount;
+ int dynamicOffsetIndex;
+ } bindDescriptorSet;
+ struct {
+ int startBinding;
+ int count;
+ int vertexBufferIndex;
+ int vertexBufferOffsetIndex;
+ } bindVertexBuffer;
+ struct {
+ VkBuffer buf;
+ VkDeviceSize ofs;
+ VkIndexType type;
+ } bindIndexBuffer;
+ struct {
+ VkViewport viewport;
+ } setViewport;
+ struct {
+ VkRect2D scissor;
+ } setScissor;
+ struct {
+ float c[4];
+ } setBlendConstants;
+ struct {
+ uint32_t ref;
+ } setStencilRef;
+ struct {
+ uint32_t vertexCount;
+ uint32_t instanceCount;
+ uint32_t firstVertex;
+ uint32_t firstInstance;
+ } draw;
+ struct {
+ uint32_t indexCount;
+ uint32_t instanceCount;
+ uint32_t firstIndex;
+ int32_t vertexOffset;
+ uint32_t firstInstance;
+ } drawIndexed;
+ struct {
+ VkDebugMarkerMarkerInfoEXT marker;
+ int markerNameIndex;
+ } debugMarkerBegin;
+ struct {
+ } debugMarkerEnd;
+ struct {
+ VkDebugMarkerMarkerInfoEXT marker;
+ } debugMarkerInsert;
+ struct {
+ int trackerIndex;
+ } transitionResources;
+ } args;
+ };
+ QVector<Command> commands;
+ QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers;
+ int currentPassResTrackerIndex;
+
+ void resetCommands() {
+ commands.clear();
+ passResTrackers.clear();
+ currentPassResTrackerIndex = -1;
+ resetPools();
+ }
+
+ void resetPools() {
+ pools.clearValue.clear();
+ pools.bufferImageCopy.clear();
+ pools.dynamicOffset.clear();
+ pools.vertexBuffer.clear();
+ pools.vertexBufferOffset.clear();
+ pools.debugMarkerName.clear();
+ }
+
+ struct {
+ QVarLengthArray<VkClearValue, 4> clearValue;
+ QVarLengthArray<VkBufferImageCopy, 16> bufferImageCopy;
+ QVarLengthArray<uint32_t, 4> dynamicOffset;
+ QVarLengthArray<VkBuffer, 4> vertexBuffer;
+ QVarLengthArray<VkDeviceSize, 4> vertexBufferOffset;
+ QVarLengthArray<QByteArray, 4> debugMarkerName;
+ } pools;
+
+ friend class QRhiVulkan;
+};
+
+Q_DECLARE_TYPEINFO(QVkCommandBuffer::Command, Q_MOVABLE_TYPE);
+
+struct QVkSwapChain : public QRhiSwapChain
+{
+ QVkSwapChain(QRhiImplementation *rhi);
+ ~QVkSwapChain();
+ void release() override;
+
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+
+ QSize surfacePixelSize() override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool buildOrResize() override;
+
+ bool ensureSurface();
+
+ static const quint32 MAX_BUFFER_COUNT = 3;
+
+ QWindow *window = nullptr;
+ QSize pixelSize;
+ bool supportsReadback = false;
+ VkSwapchainKHR sc = VK_NULL_HANDLE;
+ int bufferCount = 0;
+ VkSurfaceKHR surface = VK_NULL_HANDLE;
+ VkSurfaceKHR lastConnectedSurface = VK_NULL_HANDLE;
+ VkFormat colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
+ VkColorSpaceKHR colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
+ QVkRenderBuffer *ds = nullptr;
+ VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
+ QVector<VkPresentModeKHR> supportedPresentationModes;
+ VkDeviceMemory msaaImageMem = VK_NULL_HANDLE;
+ QVkReferenceRenderTarget rtWrapper;
+ QVkCommandBuffer cbWrapper;
+
+ struct ImageResources {
+ VkImage image = VK_NULL_HANDLE;
+ VkImageView imageView = VK_NULL_HANDLE;
+ VkFramebuffer fb = VK_NULL_HANDLE;
+ VkImage msaaImage = VK_NULL_HANDLE;
+ VkImageView msaaImageView = VK_NULL_HANDLE;
+ bool transferSource = false;
+ } imageRes[MAX_BUFFER_COUNT];
+
+ struct FrameResources {
+ VkFence imageFence = VK_NULL_HANDLE;
+ bool imageFenceWaitable = false;
+ VkSemaphore imageSem = VK_NULL_HANDLE;
+ VkSemaphore drawSem = VK_NULL_HANDLE;
+ bool imageAcquired = false;
+ bool imageSemWaitable = false;
+ quint32 imageIndex = 0;
+ VkCommandBuffer cmdBuf = VK_NULL_HANDLE;
+ VkFence cmdFence = VK_NULL_HANDLE;
+ bool cmdFenceWaitable = false;
+ int timestampQueryIndex = -1;
+ } frameRes[QVK_FRAMES_IN_FLIGHT];
+
+ quint32 currentImageIndex = 0; // index in imageRes
+ quint32 currentFrameSlot = 0; // index in frameRes
+ int frameCount = 0;
+
+ friend class QRhiVulkan;
+};
+
+class QRhiVulkan : public QRhiImplementation
+{
+public:
+ QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *importDevice = nullptr);
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ int size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
+ QRhi::FrameOpResult endOffscreenFrame() override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+
+ QVector<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ void sendVMemStatsToProfiler() override;
+
+ VkResult createDescriptorPool(VkDescriptorPool *pool);
+ bool allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, VkDescriptorSet *result, int *resultPoolIndex);
+ uint32_t chooseTransientImageMemType(VkImage img, uint32_t startIndex);
+ bool createTransientImage(VkFormat format, const QSize &pixelSize, VkImageUsageFlags usage,
+ VkImageAspectFlags aspectMask, VkSampleCountFlagBits samples,
+ VkDeviceMemory *mem, VkImage *images, VkImageView *views, int count);
+
+ bool recreateSwapChain(QRhiSwapChain *swapChain);
+ void releaseSwapChainResources(QRhiSwapChain *swapChain);
+
+ VkFormat optimalDepthStencilFormat();
+ VkSampleCountFlagBits effectiveSampleCount(int sampleCount);
+ bool createDefaultRenderPass(VkRenderPass *rp,
+ bool hasDepthStencil,
+ VkSampleCountFlagBits samples,
+ VkFormat colorFormat);
+ bool createOffscreenRenderPass(VkRenderPass *rp,
+ const QVector<QRhiColorAttachment> &colorAttachments,
+ bool preserveColor,
+ bool preserveDs,
+ QRhiRenderBuffer *depthStencilBuffer,
+ QRhiTexture *depthTexture);
+ bool ensurePipelineCache();
+ VkShaderModule createShader(const QByteArray &spirv);
+
+ void prepareNewFrame(QRhiCommandBuffer *cb);
+ QRhi::FrameOpResult startCommandBuffer(VkCommandBuffer *cb);
+ QRhi::FrameOpResult endAndSubmitCommandBuffer(VkCommandBuffer cb, VkFence cmdFence,
+ VkSemaphore *waitSem, VkSemaphore *signalSem);
+ void waitCommandCompletion(int frameSlot);
+ VkDeviceSize subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
+ using BufferImageCopyList = QVarLengthArray<VkBufferImageCopy, 16>;
+ void prepareUploadSubres(QVkTexture *texD, int layer, int level,
+ const QRhiTextureSubresourceUploadDescription &subresDesc,
+ size_t *curOfs, void *mp,
+ BufferImageCopyList *copyInfos);
+ void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates);
+ void executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD);
+ void enqueueTransitionPassResources(QVkCommandBuffer *cbD);
+ void recordCommandBuffer(QVkCommandBuffer *cbD);
+ void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
+ QVkBuffer *bufD,
+ int slot,
+ QRhiPassResourceTracker::BufferAccess access,
+ QRhiPassResourceTracker::BufferStage stage);
+ void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker,
+ QVkTexture *texD,
+ QRhiPassResourceTracker::TextureAccess access,
+ QRhiPassResourceTracker::TextureStage stage);
+ void recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhiPassResourceTracker &tracker);
+ void activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRenderTarget *rtD);
+ void executeDeferredReleases(bool forced = false);
+ void finishActiveReadbacks(bool forced = false);
+
+ void setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot = -1);
+ void trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, int slot,
+ VkAccessFlags access, VkPipelineStageFlags stage);
+ void trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD,
+ VkImageLayout layout, VkAccessFlags access, VkPipelineStageFlags stage);
+ void subresourceBarrier(QVkCommandBuffer *cbD, VkImage image,
+ VkImageLayout oldLayout, VkImageLayout newLayout,
+ VkAccessFlags srcAccess, VkAccessFlags dstAccess,
+ VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage,
+ int startLayer, int layerCount,
+ int startLevel, int levelCount);
+ void updateShaderResourceBindings(QRhiShaderResourceBindings *srb, int descSetIdx = -1);
+
+ QVulkanInstance *inst = nullptr;
+ QWindow *maybeWindow = nullptr;
+ bool importedDevice = false;
+ VkPhysicalDevice physDev = VK_NULL_HANDLE;
+ VkDevice dev = VK_NULL_HANDLE;
+ bool importedCmdPool = false;
+ VkCommandPool cmdPool = VK_NULL_HANDLE;
+ int gfxQueueFamilyIdx = -1;
+ VkQueue gfxQueue = VK_NULL_HANDLE;
+ quint32 timestampValidBits = 0;
+ bool importedAllocator = false;
+ QVkAllocator allocator = nullptr;
+ QVulkanFunctions *f = nullptr;
+ QVulkanDeviceFunctions *df = nullptr;
+ VkPhysicalDeviceProperties physDevProperties;
+ VkDeviceSize ubufAlign;
+ VkDeviceSize texbufAlign;
+
+ bool debugMarkersAvailable = false;
+ bool vertexAttribDivisorAvailable = false;
+ PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBegin = nullptr;
+ PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEnd = nullptr;
+ PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsert = nullptr;
+ PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectName = nullptr;
+
+ PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr;
+ PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
+ PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
+ PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
+ PFN_vkQueuePresentKHR vkQueuePresentKHR;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr;
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
+ PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
+
+ VkPipelineCache pipelineCache = VK_NULL_HANDLE;
+ struct DescriptorPoolData {
+ DescriptorPoolData() { }
+ DescriptorPoolData(VkDescriptorPool pool_)
+ : pool(pool_)
+ { }
+ VkDescriptorPool pool = VK_NULL_HANDLE;
+ int refCount = 0;
+ int allocedDescSets = 0;
+ };
+ QVector<DescriptorPoolData> descriptorPools;
+
+ VkQueryPool timestampQueryPool = VK_NULL_HANDLE;
+ QBitArray timestampQueryPoolMap;
+
+ VkFormat optimalDsFormat = VK_FORMAT_UNDEFINED;
+ QMatrix4x4 clipCorrectMatrix;
+
+ bool inFrame = false;
+ bool inPass = false;
+ QVkSwapChain *currentSwapChain = nullptr;
+ QSet<QVkSwapChain *> swapchains;
+ QRhiVulkanNativeHandles nativeHandlesStruct;
+
+ struct OffscreenFrame {
+ OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
+ bool active = false;
+ QVkCommandBuffer cbWrapper;
+ VkFence cmdFence = VK_NULL_HANDLE;
+ } ofr;
+
+ struct ActiveReadback {
+ int activeFrameSlot = -1;
+ QRhiReadbackDescription desc;
+ QRhiReadbackResult *result;
+ VkBuffer buf;
+ QVkAlloc bufAlloc;
+ quint32 bufSize;
+ QSize pixelSize;
+ QRhiTexture::Format format;
+ };
+ QVector<ActiveReadback> activeReadbacks;
+
+ struct DeferredReleaseEntry {
+ enum Type {
+ Pipeline,
+ ShaderResourceBindings,
+ Buffer,
+ RenderBuffer,
+ Texture,
+ Sampler,
+ TextureRenderTarget,
+ RenderPass,
+ StagingBuffer
+ };
+ Type type;
+ int lastActiveFrameSlot; // -1 if not used otherwise 0..FRAMES_IN_FLIGHT-1
+ union {
+ struct {
+ VkPipeline pipeline;
+ VkPipelineLayout layout;
+ } pipelineState;
+ struct {
+ int poolIndex;
+ VkDescriptorSetLayout layout;
+ } shaderResourceBindings;
+ struct {
+ VkBuffer buffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];
+ VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
+ } buffer;
+ struct {
+ VkDeviceMemory memory;
+ VkImage image;
+ VkImageView imageView;
+ } renderBuffer;
+ struct {
+ VkImage image;
+ VkImageView imageView;
+ QVkAlloc allocation;
+ VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
+ } texture;
+ struct {
+ VkSampler sampler;
+ } sampler;
+ struct {
+ VkFramebuffer fb;
+ VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
+ VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
+ } textureRenderTarget;
+ struct {
+ VkRenderPass rp;
+ } renderPass;
+ struct {
+ VkBuffer stagingBuffer;
+ QVkAlloc stagingAllocation;
+ } stagingBuffer;
+ };
+ };
+ QVector<DeferredReleaseEntry> releaseQueue;
+};
+
+Q_DECLARE_TYPEINFO(QRhiVulkan::DescriptorPoolData, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiVulkan::DeferredReleaseEntry, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiVulkan::ActiveReadback, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhivulkanext_p.h b/src/gui/rhi/qrhivulkanext_p.h
new file mode 100644
index 0000000000..67a63e07e0
--- /dev/null
+++ b/src/gui/rhi/qrhivulkanext_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt RHI module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRHIVULKANEXT_P_H
+#define QRHIVULKANEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrhivulkan_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef VK_EXT_vertex_attribute_divisor
+#define VK_EXT_vertex_attribute_divisor 1
+#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
+#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
+
+typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxVertexAttribDivisor;
+} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT;
+
+typedef struct VkVertexInputBindingDivisorDescriptionEXT {
+ uint32_t binding;
+ uint32_t divisor;
+} VkVertexInputBindingDivisorDescriptionEXT;
+
+typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t vertexBindingDivisorCount;
+ const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors;
+} VkPipelineVertexInputDivisorStateCreateInfoEXT;
+#endif // VK_EXT_vertex_attribute_divisor
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qshader.cpp b/src/gui/rhi/qshader.cpp
new file mode 100644
index 0000000000..5569aad639
--- /dev/null
+++ b/src/gui/rhi/qshader.cpp
@@ -0,0 +1,586 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshader_p_p.h"
+#include <QDataStream>
+#include <QBuffer>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QShader
+ \inmodule QtRhi
+ \since 5.14
+
+ \brief Contains multiple versions of a shader translated to multiple shading languages,
+ together with reflection metadata.
+
+ QShader is the entry point to shader code in the graphics API agnostic
+ Qt world. Instead of using GLSL shader sources, as was the custom with Qt
+ 5.x, new graphics systems with backends for multiple graphics APIs, such
+ as, Vulkan, Metal, Direct3D, and OpenGL, take QShader as their input
+ whenever a shader needs to be specified.
+
+ A QShader instance is empty and thus invalid by default. To get a useful
+ instance, the two typical methods are:
+
+ \list
+
+ \li Generate the contents offline, during build time or earlier, using the
+ \c qsb command line tool. The result is a binary file that is shipped with
+ the application, read via QIODevice::readAll(), and then deserialized via
+ fromSerialized(). For more information, see QShaderBaker.
+
+ \li Generate at run time via QShaderBaker. This is an expensive operation,
+ but allows applications to use user-provided or dynamically generated
+ shader source strings.
+
+ \endlist
+
+ When used together with the Qt Rendering Hardware Interface and its
+ classes, like QRhiGraphicsPipeline, no further action is needed from the
+ application's side as these classes are prepared to consume a QShader
+ whenever a shader needs to be specified for a given stage of the graphics
+ pipeline.
+
+ Alternatively, applications can access
+
+ \list
+
+ \li the source or byte code for any of the shading language versions that
+ are included in the QShader,
+
+ \li the name of the entry point for the shader,
+
+ \li the reflection metadata containing a description of the shader's
+ inputs, outputs and resources like uniform blocks. This is essential when
+ an application or framework needs to discover the inputs of a shader at
+ runtime due to not having advance knowledge of the vertex attributes or the
+ layout of the uniform buffers used by the shader.
+
+ \endlist
+
+ QShader makes no assumption about the shading language that was used
+ as the source for generating the various versions and variants that are
+ included in it.
+
+ QShader uses implicit sharing similarly to many core Qt types, and so
+ can be returned or passed by value. Detach happens implicitly when calling
+ a setter.
+
+ For reference, QRhi expects that a QShader suitable for all its
+ backends contains at least the following:
+
+ \list
+
+ \li SPIR-V 1.0 bytecode suitable for Vulkan 1.0 or newer
+
+ \li GLSL/ES 100 source code suitable for OpenGL ES 2.0 or newer
+
+ \li GLSL 120 source code suitable for OpenGL 2.1
+
+ \li HLSL Shader Model 5.0 source code or the corresponding DXBC bytecode suitable for Direct3D 11
+
+ \li Metal Shading Language 1.2 source code or the corresponding bytecode suitable for Metal
+
+ \endlist
+
+ \sa QShaderBaker
+ */
+
+/*!
+ \enum QShader::Stage
+ Describes the stage of the graphics pipeline the shader is suitable for.
+
+ \value VertexStage Vertex shader
+ \value TessellationControlStage Tessellation control (hull) shader
+ \value TessellationEvaluationStage Tessellation evaluation (domain) shader
+ \value GeometryStage Geometry shader
+ \value FragmentStage Fragment (pixel) shader
+ \value ComputeStage Compute shader
+ */
+
+/*!
+ \class QShaderVersion
+ \inmodule QtRhi
+
+ \brief Specifies the shading language version.
+
+ While languages like SPIR-V or the Metal Shading Language use traditional
+ version numbers, shaders for other APIs can use slightly different
+ versioning schemes. All those are mapped to a single version number in
+ here, however. For HLSL, the version refers to the Shader Model version,
+ like 5.0, 5.1, or 6.0. For GLSL an additional flag is needed to choose
+ between GLSL and GLSL/ES.
+
+ Below is a list with the most common examples of shader versions for
+ different graphics APIs:
+
+ \list
+
+ \li Vulkan (SPIR-V): 100
+ \li OpenGL: 120, 330, 440, etc.
+ \li OpenGL ES: 100 with GlslEs, 300 with GlslEs, etc.
+ \li Direct3D: 50, 51, 60
+ \li Metal: 12, 20
+ \endlist
+
+ A default constructed QShaderVersion contains a version of 100 and no
+ flags set.
+ */
+
+/*!
+ \enum QShaderVersion::Flag
+
+ Describes the flags that can be set.
+
+ \value GlslEs Indicates that GLSL/ES is meant in combination with GlslShader
+ */
+
+/*!
+ \class QShaderKey
+ \inmodule QtRhi
+
+ \brief Specifies the shading language, the version with flags, and the variant.
+
+ A default constructed QShaderKey has source set to SpirvShader and
+ sourceVersion set to 100. sourceVariant defaults to StandardShader.
+ */
+
+/*!
+ \enum QShader::Source
+ Describes what kind of shader code an entry contains.
+
+ \value SpirvShader SPIR-V
+ \value GlslShader GLSL
+ \value HlslShader HLSL
+ \value DxbcShader Direct3D bytecode (HLSL compiled by \c fxc)
+ \value MslShader Metal Shading Language
+ \value DxilShader Direct3D bytecode (HLSL compiled by \c dxc)
+ \value MetalLibShader Pre-compiled Metal bytecode
+ */
+
+/*!
+ \enum QShader::Variant
+ Describes what kind of shader code an entry contains.
+
+ \value StandardShader The normal, unmodified version of the shader code.
+ \value BatchableVertexShader Vertex shader rewritten to be suitable for Qt Quick scenegraph batching.
+ */
+
+/*!
+ \class QShaderCode
+ \inmodule QtRhi
+
+ \brief Contains source or binary code for a shader and additional metadata.
+
+ When shader() is empty after retrieving a QShaderCode instance from
+ QShader, it indicates no shader code was found for the requested key.
+ */
+
+static const int QSB_VERSION = 1;
+
+/*!
+ Constructs a new, empty (and thus invalid) QShader instance.
+ */
+QShader::QShader()
+ : d(new QShaderPrivate)
+{
+}
+
+/*!
+ \internal
+ */
+void QShader::detach()
+{
+ qAtomicDetach(d);
+}
+
+/*!
+ \internal
+ */
+QShader::QShader(const QShader &other)
+ : d(other.d)
+{
+ d->ref.ref();
+}
+
+/*!
+ \internal
+ */
+QShader &QShader::operator=(const QShader &other)
+{
+ qAtomicAssign(d, other.d);
+ return *this;
+}
+
+/*!
+ Destructor.
+ */
+QShader::~QShader()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+/*!
+ \return true if the QShader contains at least one shader version.
+ */
+bool QShader::isValid() const
+{
+ return !d->shaders.isEmpty();
+}
+
+/*!
+ \return the pipeline stage the shader is meant for.
+ */
+QShader::Stage QShader::stage() const
+{
+ return d->stage;
+}
+
+/*!
+ Sets the pipeline \a stage.
+ */
+void QShader::setStage(Stage stage)
+{
+ if (stage != d->stage) {
+ detach();
+ d->stage = stage;
+ }
+}
+
+/*!
+ \return the reflection metadata for the shader.
+ */
+QShaderDescription QShader::description() const
+{
+ return d->desc;
+}
+
+/*!
+ Sets the reflection metadata to \a desc.
+ */
+void QShader::setDescription(const QShaderDescription &desc)
+{
+ detach();
+ d->desc = desc;
+}
+
+/*!
+ \return the list of available shader versions
+ */
+QVector<QShaderKey> QShader::availableShaders() const
+{
+ return d->shaders.keys().toVector();
+}
+
+/*!
+ \return the source or binary code for a given shader version specified by \a key.
+ */
+QShaderCode QShader::shader(const QShaderKey &key) const
+{
+ return d->shaders.value(key);
+}
+
+/*!
+ Stores the source or binary \a shader code for a given shader version specified by \a key.
+ */
+void QShader::setShader(const QShaderKey &key, const QShaderCode &shader)
+{
+ if (d->shaders.value(key) == shader)
+ return;
+
+ detach();
+ d->shaders[key] = shader;
+}
+
+/*!
+ Removes the source or binary shader code for a given \a key.
+ Does nothing when not found.
+ */
+void QShader::removeShader(const QShaderKey &key)
+{
+ auto it = d->shaders.find(key);
+ if (it == d->shaders.end())
+ return;
+
+ detach();
+ d->shaders.erase(it);
+}
+
+/*!
+ \return a serialized binary version of all the data held by the
+ QShader, suitable for writing to files or other I/O devices.
+
+ \sa fromSerialized()
+ */
+QByteArray QShader::serialized() const
+{
+ QBuffer buf;
+ QDataStream ds(&buf);
+ ds.setVersion(QDataStream::Qt_5_10);
+ if (!buf.open(QIODevice::WriteOnly))
+ return QByteArray();
+
+ ds << QSB_VERSION;
+ ds << d->stage;
+ ds << d->desc.toBinaryJson();
+ ds << d->shaders.count();
+ for (auto it = d->shaders.cbegin(), itEnd = d->shaders.cend(); it != itEnd; ++it) {
+ const QShaderKey &k(it.key());
+ ds << k.source();
+ ds << k.sourceVersion().version();
+ ds << k.sourceVersion().flags();
+ ds << k.sourceVariant();
+ const QShaderCode &shader(d->shaders.value(k));
+ ds << shader.shader();
+ ds << shader.entryPoint();
+ }
+
+ return qCompress(buf.buffer());
+}
+
+/*!
+ Creates a new QShader instance from the given \a data.
+
+ \sa serialized()
+ */
+QShader QShader::fromSerialized(const QByteArray &data)
+{
+ QByteArray udata = qUncompress(data);
+ QBuffer buf(&udata);
+ QDataStream ds(&buf);
+ ds.setVersion(QDataStream::Qt_5_10);
+ if (!buf.open(QIODevice::ReadOnly))
+ return QShader();
+
+ QShader bs;
+ QShaderPrivate *d = QShaderPrivate::get(&bs);
+ Q_ASSERT(d->ref.load() == 1); // must be detached
+ int intVal;
+ ds >> intVal;
+ if (intVal != QSB_VERSION)
+ return QShader();
+
+ ds >> intVal;
+ d->stage = Stage(intVal);
+ QByteArray descBin;
+ ds >> descBin;
+ d->desc = QShaderDescription::fromBinaryJson(descBin);
+ int count;
+ ds >> count;
+ for (int i = 0; i < count; ++i) {
+ QShaderKey k;
+ ds >> intVal;
+ k.setSource(Source(intVal));
+ QShaderVersion ver;
+ ds >> intVal;
+ ver.setVersion(intVal);
+ ds >> intVal;
+ ver.setFlags(QShaderVersion::Flags(intVal));
+ k.setSourceVersion(ver);
+ ds >> intVal;
+ k.setSourceVariant(Variant(intVal));
+ QShaderCode shader;
+ QByteArray s;
+ ds >> s;
+ shader.setShader(s);
+ ds >> s;
+ shader.setEntryPoint(s);
+ d->shaders[k] = shader;
+ }
+
+ return bs;
+}
+
+QShaderVersion::QShaderVersion(int v, Flags f)
+ : m_version(v), m_flags(f)
+{
+}
+
+QShaderCode::QShaderCode(const QByteArray &code, const QByteArray &entry)
+ : m_shader(code), m_entryPoint(entry)
+{
+}
+
+QShaderKey::QShaderKey(QShader::Source s,
+ const QShaderVersion &sver,
+ QShader::Variant svar)
+ : m_source(s),
+ m_sourceVersion(sver),
+ m_sourceVariant(svar)
+{
+}
+
+/*!
+ Returns \c true if the two QShader objects \a a and \a b are equal,
+ meaning they are for the same stage with matching sets of shader source or
+ binary code.
+
+ \relates QShader
+ */
+bool operator==(const QShader &lhs, const QShader &rhs) Q_DECL_NOTHROW
+{
+ return lhs.d->stage == rhs.d->stage
+ && lhs.d->shaders == rhs.d->shaders;
+ // do not bother with desc, if the shader code is the same, the description must match too
+}
+
+/*!
+ \fn bool operator!=(const QShader &lhs, const QShader &rhs)
+
+ Returns \c false if the values in the two QShader objects \a a and \a b
+ are equal; otherwise returns \c true.
+
+ \relates QShader
+ */
+
+/*!
+ Returns the hash value for \a s, using \a seed to seed the calculation.
+
+ \relates QShader
+ */
+uint qHash(const QShader &s, uint seed) Q_DECL_NOTHROW
+{
+ uint h = s.stage();
+ for (auto it = s.d->shaders.constBegin(), itEnd = s.d->shaders.constEnd(); it != itEnd; ++it)
+ h += qHash(it.key(), seed) + qHash(it.value().shader(), seed);
+ return h;
+}
+
+/*!
+ Returns \c true if the two QShaderVersion objects \a a and \a b are
+ equal.
+
+ \relates QShaderVersion
+ */
+bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) Q_DECL_NOTHROW
+{
+ return lhs.version() == rhs.version() && lhs.flags() == rhs.flags();
+}
+
+/*!
+ \fn bool operator!=(const QShaderVersion &lhs, const QShaderVersion &rhs)
+
+ Returns \c false if the values in the two QShaderVersion objects \a a
+ and \a b are equal; otherwise returns \c true.
+
+ \relates QShaderVersion
+ */
+
+/*!
+ Returns \c true if the two QShaderKey objects \a a and \a b are equal.
+
+ \relates QShaderKey
+ */
+bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) Q_DECL_NOTHROW
+{
+ return lhs.source() == rhs.source() && lhs.sourceVersion() == rhs.sourceVersion()
+ && lhs.sourceVariant() == rhs.sourceVariant();
+}
+
+/*!
+ \fn bool operator!=(const QShaderKey &lhs, const QShaderKey &rhs)
+
+ Returns \c false if the values in the two QShaderKey objects \a a
+ and \a b are equal; otherwise returns \c true.
+
+ \relates QShaderKey
+ */
+
+/*!
+ Returns the hash value for \a k, using \a seed to seed the calculation.
+
+ \relates QShaderKey
+ */
+uint qHash(const QShaderKey &k, uint seed) Q_DECL_NOTHROW
+{
+ return seed + 10 * k.source() + k.sourceVersion().version() + k.sourceVersion().flags() + k.sourceVariant();
+}
+
+/*!
+ Returns \c true if the two QShaderCode objects \a a and \a b are equal.
+
+ \relates QShaderCode
+ */
+bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) Q_DECL_NOTHROW
+{
+ return lhs.shader() == rhs.shader() && lhs.entryPoint() == rhs.entryPoint();
+}
+
+/*!
+ \fn bool operator!=(const QShaderCode &lhs, const QShaderCode &rhs)
+
+ Returns \c false if the values in the two QShaderCode objects \a a
+ and \a b are equal; otherwise returns \c true.
+
+ \relates QShaderCode
+ */
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QShader &bs)
+{
+ const QShaderPrivate *d = bs.d;
+ QDebugStateSaver saver(dbg);
+
+ dbg.nospace() << "QShader("
+ << "stage=" << d->stage
+ << " shaders=" << d->shaders.keys()
+ << " desc.isValid=" << d->desc.isValid()
+ << ')';
+
+ return dbg;
+}
+
+QDebug operator<<(QDebug dbg, const QShaderKey &k)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "ShaderKey(" << k.source()
+ << " " << k.sourceVersion()
+ << " " << k.sourceVariant() << ")";
+ return dbg;
+}
+
+QDebug operator<<(QDebug dbg, const QShaderVersion &v)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "Version(" << v.version() << " " << v.flags() << ")";
+ return dbg;
+}
+#endif // QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
diff --git a/src/gui/rhi/qshader_p.h b/src/gui/rhi/qshader_p.h
new file mode 100644
index 0000000000..12a0a26e12
--- /dev/null
+++ b/src/gui/rhi/qshader_p.h
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADER_P_H
+#define QSHADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qtguiglobal.h>
+#include <private/qshaderdescription_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QShaderPrivate;
+class QShaderKey;
+
+class Q_GUI_EXPORT QShaderVersion
+{
+public:
+ enum Flag {
+ GlslEs = 0x01
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QShaderVersion() = default;
+ QShaderVersion(int v, Flags f = Flags());
+
+ int version() const { return m_version; }
+ void setVersion(int v) { m_version = v; }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+private:
+ int m_version = 100;
+ Flags m_flags;
+ Q_DECL_UNUSED_MEMBER quint64 m_reserved = 0;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderVersion::Flags)
+Q_DECLARE_TYPEINFO(QShaderVersion, Q_MOVABLE_TYPE);
+
+class Q_GUI_EXPORT QShaderCode
+{
+public:
+ QShaderCode() = default;
+ QShaderCode(const QByteArray &code, const QByteArray &entry = QByteArray());
+
+ QByteArray shader() const { return m_shader; }
+ void setShader(const QByteArray &code) { m_shader = code; }
+
+ QByteArray entryPoint() const { return m_entryPoint; }
+ void setEntryPoint(const QByteArray &entry) { m_entryPoint = entry; }
+
+private:
+ QByteArray m_shader;
+ QByteArray m_entryPoint;
+ Q_DECL_UNUSED_MEMBER quint64 m_reserved = 0;
+};
+
+Q_DECLARE_TYPEINFO(QShaderCode, Q_MOVABLE_TYPE);
+
+class Q_GUI_EXPORT QShader
+{
+public:
+ enum Stage {
+ VertexStage = 0,
+ TessellationControlStage,
+ TessellationEvaluationStage,
+ GeometryStage,
+ FragmentStage,
+ ComputeStage
+ };
+
+ enum Source {
+ SpirvShader = 0,
+ GlslShader,
+ HlslShader,
+ DxbcShader, // fxc
+ MslShader,
+ DxilShader, // dxc
+ MetalLibShader // xcrun metal + xcrun metallib
+ };
+
+ enum Variant {
+ StandardShader = 0,
+ BatchableVertexShader
+ };
+
+ QShader();
+ QShader(const QShader &other);
+ QShader &operator=(const QShader &other);
+ ~QShader();
+ void detach();
+
+ bool isValid() const;
+
+ Stage stage() const;
+ void setStage(Stage stage);
+
+ QShaderDescription description() const;
+ void setDescription(const QShaderDescription &desc);
+
+ QVector<QShaderKey> availableShaders() const;
+ QShaderCode shader(const QShaderKey &key) const;
+ void setShader(const QShaderKey &key, const QShaderCode &shader);
+ void removeShader(const QShaderKey &key);
+
+ QByteArray serialized() const;
+ static QShader fromSerialized(const QByteArray &data);
+
+private:
+ QShaderPrivate *d;
+ friend struct QShaderPrivate;
+ friend Q_GUI_EXPORT bool operator==(const QShader &, const QShader &) Q_DECL_NOTHROW;
+ friend Q_GUI_EXPORT uint qHash(const QShader &, uint) Q_DECL_NOTHROW;
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QShader &);
+#endif
+};
+
+class Q_GUI_EXPORT QShaderKey
+{
+public:
+ QShaderKey() = default;
+ QShaderKey(QShader::Source s,
+ const QShaderVersion &sver,
+ QShader::Variant svar = QShader::StandardShader);
+
+ QShader::Source source() const { return m_source; }
+ void setSource(QShader::Source s) { m_source = s; }
+
+ QShaderVersion sourceVersion() const { return m_sourceVersion; }
+ void setSourceVersion(const QShaderVersion &sver) { m_sourceVersion = sver; }
+
+ QShader::Variant sourceVariant() const { return m_sourceVariant; }
+ void setSourceVariant(QShader::Variant svar) { m_sourceVariant = svar; }
+
+private:
+ QShader::Source m_source = QShader::SpirvShader;
+ QShaderVersion m_sourceVersion;
+ QShader::Variant m_sourceVariant = QShader::StandardShader;
+ Q_DECL_UNUSED_MEMBER quint64 m_reserved = 0;
+};
+
+Q_DECLARE_TYPEINFO(QShaderKey, Q_MOVABLE_TYPE);
+
+Q_GUI_EXPORT bool operator==(const QShader &lhs, const QShader &rhs) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QShader &s, uint seed = 0) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShader &lhs, const QShader &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_GUI_EXPORT bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderVersion &lhs, const QShaderVersion &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const QShaderKey &lhs, const QShaderKey &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const QShaderCode &lhs, const QShaderCode &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_GUI_EXPORT uint qHash(const QShaderKey &k, uint seed = 0) Q_DECL_NOTHROW;
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShader &);
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QShaderKey &k);
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QShaderVersion &v);
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qshader_p_p.h b/src/gui/rhi/qshader_p_p.h
new file mode 100644
index 0000000000..6473590e95
--- /dev/null
+++ b/src/gui/rhi/qshader_p_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADER_P_P_H
+#define QSHADER_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qshader_p.h"
+#include <QtCore/QAtomicInt>
+#include <QtCore/QHash>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+struct Q_GUI_EXPORT QShaderPrivate
+{
+ QShaderPrivate()
+ : ref(1)
+ {
+ }
+
+ QShaderPrivate(const QShaderPrivate *other)
+ : ref(1),
+ stage(other->stage),
+ desc(other->desc),
+ shaders(other->shaders)
+ {
+ }
+
+ static QShaderPrivate *get(QShader *s) { return s->d; }
+ static const QShaderPrivate *get(const QShader *s) { return s->d; }
+
+ QAtomicInt ref;
+ QShader::Stage stage = QShader::VertexStage;
+ QShaderDescription desc;
+ QHash<QShaderKey, QShaderCode> shaders;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qshaderdescription.cpp b/src/gui/rhi/qshaderdescription.cpp
new file mode 100644
index 0000000000..ed549b083f
--- /dev/null
+++ b/src/gui/rhi/qshaderdescription.cpp
@@ -0,0 +1,1088 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshaderdescription_p_p.h"
+#include <QDebug>
+#include <QJsonObject>
+#include <QJsonArray>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QShaderDescription
+ \inmodule QtRhi
+ \since 5.14
+
+ \brief Describes the interface of a shader.
+
+ A shader typically has a set of inputs and outputs. A vertex shader for
+ example has a number of input variables and may use one or more uniform
+ buffers to access data (e.g. a modelview matrix) provided by the
+ application. The shader for the fragment stage receives data from the
+ vertex stage (in a simple setup) and may also rely on data from uniform
+ buffers, images, and samplers.
+
+ When it comes to vertex inputs and the layout of the uniform buffers (what
+ are the names of the members? what is there size, offset, and so on),
+ applications and frameworks may need to discover this dynamically at run
+ time. This is typical when the shader is not built-in but provided by an
+ external entity, like the user.
+
+ Modern and lean graphics APIs may no longer provide a way to query shader
+ reflection information at run time. Therefore, such data is now
+ automatically generated by QShaderBaker and is provided as a
+ QShaderDescription object for each and every QShader.
+
+ \section2 Example
+
+ Take the following vertex shader:
+
+ \badcode
+ #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;
+ float opacity;
+ } ubuf;
+
+ out gl_PerVertex { vec4 gl_Position; };
+
+ void main()
+ {
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+ }
+ \endcode
+
+ This shader has two inputs: \c position at location 0 with a type of \c
+ vec4, and \c color at location 1 with a type of \c vec3. It has one output:
+ \c v_color, although this is typically not interesting for applications.
+ What is more important, there is a uniform block at binding 0 with a size
+ of 68 bytes and two members, a 4x4 matrix named \c mvp at offset 0, and a
+ float \c opacity at offset 64.
+
+ All this is described by a QShaderDescription object. QShaderDescription
+ can also be serialized to JSON and binary JSON, and can be deserialized
+ from binary JSON. In practice this is rarely needed since QShader
+ takes care of the associated QShaderDescription automatically, but if the
+ QShaderDescription of the above shader would be written out as JSON, it
+ would look like the following:
+
+ \badcode
+ {
+ "inputs": [
+ {
+ "location": 1,
+ "name": "color",
+ "type": "vec3"
+ },
+ {
+ "location": 0,
+ "name": "position",
+ "type": "vec4"
+ }
+ ],
+ "outputs": [
+ {
+ "location": 0,
+ "name": "v_color",
+ "type": "vec3"
+ }
+ ],
+ "uniformBlocks": [
+ {
+ "binding": 0,
+ "blockName": "buf",
+ "members": [
+ {
+ "matrixStride": 16,
+ "name": "mvp",
+ "offset": 0,
+ "size": 64,
+ "type": "mat4"
+ },
+ {
+ "name": "opacity",
+ "offset": 64,
+ "size": 4,
+ "type": "float"
+ }
+ ],
+ "set": 0,
+ "size": 68,
+ "structName": "ubuf"
+ }
+ ]
+ }
+ \endcode
+
+ The C++ API allows accessing a data structure like the above. For
+ simplicity the inner structs only contain public data members, also
+ considering that their layout is unlikely to change in the future.
+
+ \sa QShaderBaker, QShader
+ */
+
+/*!
+ \enum QShaderDescription::VariableType
+ Represents the type of a variable or block member.
+
+ \value Unknown
+ \value Float
+ \value Vec2
+ \value Vec3
+ \value Vec4
+ \value Mat2
+ \value Mat2x3
+ \value Mat2x4
+ \value Mat3
+ \value Mat3x2
+ \value Mat3x4
+ \value Mat4
+ \value Mat4x2
+ \value Mat4x3
+ \value Int
+ \value Int2
+ \value Int3
+ \value Int4
+ \value Uint
+ \value Uint2
+ \value Uint3
+ \value Uint4
+ \value Bool
+ \value Bool2
+ \value Bool3
+ \value Bool4
+ \value Double
+ \value Double2
+ \value Double3
+ \value Double4
+ \value DMat2
+ \value DMat2x3
+ \value DMat2x4
+ \value DMat3
+ \value DMat3x2
+ \value DMat3x4
+ \value DMat4
+ \value DMat4x2
+ \value DMat4x3
+ \value Sampler1D
+ \value Sampler2D
+ \value Sampler2DMS
+ \value Sampler3D
+ \value SamplerCube
+ \value Sampler1DArray
+ \value Sampler2DArray
+ \value Sampler2DMSArray
+ \value Sampler3DArray
+ \value SamplerCubeArray
+ \value SamplerRect
+ \value SamplerBuffer
+ \value Image1D
+ \value Image2D
+ \value Image2DMS
+ \value Image3D
+ \value ImageCube
+ \value Image1DArray
+ \value Image2DArray
+ \value Image2DMSArray
+ \value Image3DArray
+ \value ImageCubeArray
+ \value ImageRect
+ \value ImageBuffer
+ \value Struct
+ */
+
+/*!
+ \class QShaderDescription::InOutVariable
+ \inmodule QtRhi
+
+ \brief Describes an input or output variable in the shader.
+ */
+
+/*!
+ \class QShaderDescription::BlockVariable
+ \inmodule QtRhi
+
+ \brief Describes a member of a uniform or push constant block.
+ */
+
+/*!
+ \class QShaderDescription::UniformBlock
+ \inmodule QtRhi
+
+ \brief Describes a uniform block.
+
+ \note When translating to shading languages without uniform block support
+ (like GLSL 120 or GLSL/ES 100), uniform blocks are replaced with ordinary
+ uniforms in a struct. The name of the struct, and so the prefix for the
+ uniforms generated from the block members, is given by structName.
+ */
+
+/*!
+ \class QShaderDescription::PushConstantBlock
+ \inmodule QtRhi
+
+ \brief Describes a push constant block.
+ */
+
+/*!
+ \class QShaderDescription::StorageBlock
+ \inmodule QtRhi
+
+ \brief Describes a shader storage block.
+ */
+
+/*!
+ Constructs a new, empty QShaderDescription.
+
+ \note Being empty implies that isValid() returns \c false for the
+ newly constructed instance.
+ */
+QShaderDescription::QShaderDescription()
+ : d(new QShaderDescriptionPrivate)
+{
+}
+
+/*!
+ \internal
+ */
+void QShaderDescription::detach()
+{
+ qAtomicDetach(d);
+}
+
+/*!
+ \internal
+ */
+QShaderDescription::QShaderDescription(const QShaderDescription &other)
+ : d(other.d)
+{
+ d->ref.ref();
+}
+
+/*!
+ \internal
+ */
+QShaderDescription &QShaderDescription::operator=(const QShaderDescription &other)
+{
+ qAtomicAssign(d, other.d);
+ return *this;
+}
+
+/*!
+ Destructor.
+ */
+QShaderDescription::~QShaderDescription()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+/*!
+ \return true if the QShaderDescription contains at least one entry in one of
+ the variable and block lists.
+ */
+bool QShaderDescription::isValid() const
+{
+ return !d->inVars.isEmpty() || !d->outVars.isEmpty()
+ || !d->uniformBlocks.isEmpty() || !d->pushConstantBlocks.isEmpty() || !d->storageBlocks.isEmpty()
+ || !d->combinedImageSamplers.isEmpty() || !d->storageImages.isEmpty();
+}
+
+/*!
+ \return a serialized binary version of the data.
+
+ \sa toJson()
+ */
+QByteArray QShaderDescription::toBinaryJson() const
+{
+ return d->makeDoc().toBinaryData();
+}
+
+/*!
+ \return a serialized JSON text version of the data.
+
+ \note There is no deserialization method provided for JSON text.
+
+ \sa toBinaryJson()
+ */
+QByteArray QShaderDescription::toJson() const
+{
+ return d->makeDoc().toJson();
+}
+
+/*!
+ Deserializes the given binary JSON \a data and returns a new
+ QShaderDescription.
+ */
+QShaderDescription QShaderDescription::fromBinaryJson(const QByteArray &data)
+{
+ QShaderDescription desc;
+ QShaderDescriptionPrivate::get(&desc)->loadDoc(QJsonDocument::fromBinaryData(data));
+ return desc;
+}
+
+/*!
+ \return the list of input variables. This includes vertex inputs (sometimes
+ called attributes) for the vertex stage, and inputs for other stages
+ (sometimes called varyings).
+ */
+QVector<QShaderDescription::InOutVariable> QShaderDescription::inputVariables() const
+{
+ return d->inVars;
+}
+
+/*!
+ \return the list of output variables.
+ */
+QVector<QShaderDescription::InOutVariable> QShaderDescription::outputVariables() const
+{
+ return d->outVars;
+}
+
+/*!
+ \return the list of uniform blocks.
+ */
+QVector<QShaderDescription::UniformBlock> QShaderDescription::uniformBlocks() const
+{
+ return d->uniformBlocks;
+}
+
+/*!
+ \return the list of push constant blocks.
+
+ \note Avoid relying on push constant blocks for shaders that are to be used
+ in combination with the Qt Rendering Hardware Interface since that
+ currently has no support for them.
+ */
+QVector<QShaderDescription::PushConstantBlock> QShaderDescription::pushConstantBlocks() const
+{
+ return d->pushConstantBlocks;
+}
+
+/*!
+ \return the list of shader storage blocks.
+
+ For example, with GLSL/Vulkan shaders as source, the declaration
+
+ \badcode
+ struct Stuff {
+ vec2 a;
+ vec2 b;
+ };
+ layout(std140, binding = 0) buffer StuffSsbo {
+ vec4 whatever;
+ Stuff stuff[];
+ } buf;
+ \endcode
+
+ generates the following: (shown as textual JSON here)
+
+ \badcode
+ "storageBlocks": [ {
+ "binding": 0,
+ "blockName": "StuffSsbo",
+ "instanceName": "buf",
+ "knownSize": 16,
+ "members": [
+ {
+ "name": "whatever",
+ "offset": 0,
+ "size": 16,
+ "type": "vec4"
+ },
+ {
+ "arrayDims": [
+ 0
+ ],
+ "name": "stuff",
+ "offset": 16,
+ "size": 0,
+ "structMembers": [
+ {
+ "name": "a",
+ "offset": 0,
+ "size": 8,
+ "type": "vec2"
+ },
+ {
+ "name": "b",
+ "offset": 8,
+ "size": 8,
+ "type": "vec2"
+ }
+ ],
+ "type": "struct"
+ }
+ ],
+ "set": 0
+ } ]
+ \endcode
+
+ \note The size of the last member in the storage block is undefined. This shows
+ up as \c size 0 and an array dimension of \c{[0]}. The storage block's \c knownSize
+ excludes the size of the last member since that will only be known at run time.
+
+ \note SSBOs are not available with some graphics APIs, such as, OpenGL 2.x or
+ OpenGL ES older than 3.1.
+ */
+QVector<QShaderDescription::StorageBlock> QShaderDescription::storageBlocks() const
+{
+ return d->storageBlocks;
+}
+
+/*!
+ \return the list of combined image samplers
+
+ With GLSL/Vulkan shaders as source a \c{layout(binding = 1) uniform sampler2D tex;}
+ uniform generates the following: (shown as textual JSON here)
+
+ \badcode
+ "combinedImageSamplers": [
+ {
+ "binding": 1,
+ "name": "tex",
+ "set": 0,
+ "type": "sampler2D"
+ }
+ ]
+ \endcode
+
+ This does not mean that other language versions of the shader must also use
+ a combined image sampler, especially considering that the concept may not
+ exist everywhere. For instance, a HLSL version will likely just use a
+ Texture2D and SamplerState object with registers t1 and s1, respectively.
+ */
+QVector<QShaderDescription::InOutVariable> QShaderDescription::combinedImageSamplers() const
+{
+ return d->combinedImageSamplers;
+}
+
+/*!
+ \return the list of image variables.
+
+ These will likely occur in compute shaders. For example,
+ \c{layout (binding = 0, rgba8) uniform readonly image2D inputImage;}
+ generates the following: (shown as textual JSON here)
+
+ \badcode
+ "storageImages": [
+ {
+ "binding": 0,
+ "imageFormat": "rgba8",
+ "name": "inputImage",
+ "set": 0,
+ "type": "image2D"
+ }
+ ]
+ \endcode
+
+ \note Separate image objects are not compatible with some graphics APIs,
+ such as, OpenGL 2.x or OpenGL ES older than 3.1.
+ */
+QVector<QShaderDescription::InOutVariable> QShaderDescription::storageImages() const
+{
+ return d->storageImages;
+}
+
+static struct TypeTab {
+ QString k;
+ QShaderDescription::VariableType v;
+} typeTab[] = {
+ { QLatin1String("float"), QShaderDescription::Float },
+ { QLatin1String("vec2"), QShaderDescription::Vec2 },
+ { QLatin1String("vec3"), QShaderDescription::Vec3 },
+ { QLatin1String("vec4"), QShaderDescription::Vec4 },
+ { QLatin1String("mat2"), QShaderDescription::Mat2 },
+ { QLatin1String("mat3"), QShaderDescription::Mat3 },
+ { QLatin1String("mat4"), QShaderDescription::Mat4 },
+
+ { QLatin1String("struct"), QShaderDescription::Struct },
+
+ { QLatin1String("sampler1D"), QShaderDescription::Sampler1D },
+ { QLatin1String("sampler2D"), QShaderDescription::Sampler2D },
+ { QLatin1String("sampler2DMS"), QShaderDescription::Sampler2DMS },
+ { QLatin1String("sampler3D"), QShaderDescription::Sampler3D },
+ { QLatin1String("samplerCube"), QShaderDescription::SamplerCube },
+ { QLatin1String("sampler1DArray"), QShaderDescription::Sampler1DArray },
+ { QLatin1String("sampler2DArray"), QShaderDescription::Sampler2DArray },
+ { QLatin1String("sampler2DMSArray"), QShaderDescription::Sampler2DMSArray },
+ { QLatin1String("sampler3DArray"), QShaderDescription::Sampler3DArray },
+ { QLatin1String("samplerCubeArray"), QShaderDescription::SamplerCubeArray },
+ { QLatin1String("samplerRect"), QShaderDescription::SamplerRect },
+ { QLatin1String("samplerBuffer"), QShaderDescription::SamplerBuffer },
+
+ { QLatin1String("mat2x3"), QShaderDescription::Mat2x3 },
+ { QLatin1String("mat2x4"), QShaderDescription::Mat2x4 },
+ { QLatin1String("mat3x2"), QShaderDescription::Mat3x2 },
+ { QLatin1String("mat3x4"), QShaderDescription::Mat3x4 },
+ { QLatin1String("mat4x2"), QShaderDescription::Mat4x2 },
+ { QLatin1String("mat4x3"), QShaderDescription::Mat4x3 },
+
+ { QLatin1String("int"), QShaderDescription::Int },
+ { QLatin1String("ivec2"), QShaderDescription::Int2 },
+ { QLatin1String("ivec3"), QShaderDescription::Int3 },
+ { QLatin1String("ivec4"), QShaderDescription::Int4 },
+
+ { QLatin1String("uint"), QShaderDescription::Uint },
+ { QLatin1String("uvec2"), QShaderDescription::Uint2 },
+ { QLatin1String("uvec3"), QShaderDescription::Uint3 },
+ { QLatin1String("uvec4"), QShaderDescription::Uint4 },
+
+ { QLatin1String("bool"), QShaderDescription::Bool },
+ { QLatin1String("bvec2"), QShaderDescription::Bool2 },
+ { QLatin1String("bvec3"), QShaderDescription::Bool3 },
+ { QLatin1String("bvec4"), QShaderDescription::Bool4 },
+
+ { QLatin1String("double"), QShaderDescription::Double },
+ { QLatin1String("dvec2"), QShaderDescription::Double2 },
+ { QLatin1String("dvec3"), QShaderDescription::Double3 },
+ { QLatin1String("dvec4"), QShaderDescription::Double4 },
+ { QLatin1String("dmat2"), QShaderDescription::DMat2 },
+ { QLatin1String("dmat3"), QShaderDescription::DMat3 },
+ { QLatin1String("dmat4"), QShaderDescription::DMat4 },
+ { QLatin1String("dmat2x3"), QShaderDescription::DMat2x3 },
+ { QLatin1String("dmat2x4"), QShaderDescription::DMat2x4 },
+ { QLatin1String("dmat3x2"), QShaderDescription::DMat3x2 },
+ { QLatin1String("dmat3x4"), QShaderDescription::DMat3x4 },
+ { QLatin1String("dmat4x2"), QShaderDescription::DMat4x2 },
+ { QLatin1String("dmat4x3"), QShaderDescription::DMat4x3 },
+
+ { QLatin1String("image1D"), QShaderDescription::Image1D },
+ { QLatin1String("image2D"), QShaderDescription::Image2D },
+ { QLatin1String("image2DMS"), QShaderDescription::Image2DMS },
+ { QLatin1String("image3D"), QShaderDescription::Image3D },
+ { QLatin1String("imageCube"), QShaderDescription::ImageCube },
+ { QLatin1String("image1DArray"), QShaderDescription::Image1DArray },
+ { QLatin1String("image2DArray"), QShaderDescription::Image2DArray },
+ { QLatin1String("image2DMSArray"), QShaderDescription::Image2DMSArray },
+ { QLatin1String("image3DArray"), QShaderDescription::Image3DArray },
+ { QLatin1String("imageCubeArray"), QShaderDescription::ImageCubeArray },
+ { QLatin1String("imageRect"), QShaderDescription::ImageRect },
+ { QLatin1String("imageBuffer"), QShaderDescription::ImageBuffer }
+};
+
+static QString typeStr(const QShaderDescription::VariableType &t)
+{
+ for (size_t i = 0; i < sizeof(typeTab) / sizeof(TypeTab); ++i) {
+ if (typeTab[i].v == t)
+ return typeTab[i].k;
+ }
+ return QString();
+}
+
+static QShaderDescription::VariableType mapType(const QString &t)
+{
+ for (size_t i = 0; i < sizeof(typeTab) / sizeof(TypeTab); ++i) {
+ if (typeTab[i].k == t)
+ return typeTab[i].v;
+ }
+ return QShaderDescription::Unknown;
+}
+
+static struct ImageFormatTab {
+ QString k;
+ QShaderDescription::ImageFormat v;
+} imageFormatTab[] {
+ { QLatin1String("unknown"), QShaderDescription::ImageFormatUnknown },
+ { QLatin1String("rgba32f"), QShaderDescription::ImageFormatRgba32f },
+ { QLatin1String("rgba16"), QShaderDescription::ImageFormatRgba16f },
+ { QLatin1String("r32f"), QShaderDescription::ImageFormatR32f },
+ { QLatin1String("rgba8"), QShaderDescription::ImageFormatRgba8 },
+ { QLatin1String("rgba8_snorm"), QShaderDescription::ImageFormatRgba8Snorm },
+ { QLatin1String("rg32f"), QShaderDescription::ImageFormatRg32f },
+ { QLatin1String("rg16f"), QShaderDescription::ImageFormatRg16f },
+ { QLatin1String("r11f_g11f_b10f"), QShaderDescription::ImageFormatR11fG11fB10f },
+ { QLatin1String("r16f"), QShaderDescription::ImageFormatR16f },
+ { QLatin1String("rgba16"), QShaderDescription::ImageFormatRgba16 },
+ { QLatin1String("rgb10_a2"), QShaderDescription::ImageFormatRgb10A2 },
+ { QLatin1String("rg16"), QShaderDescription::ImageFormatRg16 },
+ { QLatin1String("rg8"), QShaderDescription::ImageFormatRg8 },
+ { QLatin1String("r16"), QShaderDescription::ImageFormatR16 },
+ { QLatin1String("r8"), QShaderDescription::ImageFormatR8 },
+ { QLatin1String("rgba16_snorm"), QShaderDescription::ImageFormatRgba16Snorm },
+ { QLatin1String("rg16_snorm"), QShaderDescription::ImageFormatRg16Snorm },
+ { QLatin1String("rg8_snorm"), QShaderDescription::ImageFormatRg8Snorm },
+ { QLatin1String("r16_snorm"), QShaderDescription::ImageFormatR16Snorm },
+ { QLatin1String("r8_snorm"), QShaderDescription::ImageFormatR8Snorm },
+ { QLatin1String("rgba32i"), QShaderDescription::ImageFormatRgba32i },
+ { QLatin1String("rgba16i"), QShaderDescription::ImageFormatRgba16i },
+ { QLatin1String("rgba8i"), QShaderDescription::ImageFormatRgba8i },
+ { QLatin1String("r32i"), QShaderDescription::ImageFormatR32i },
+ { QLatin1String("rg32i"), QShaderDescription::ImageFormatRg32i },
+ { QLatin1String("rg16i"), QShaderDescription::ImageFormatRg16i },
+ { QLatin1String("rg8i"), QShaderDescription::ImageFormatRg8i },
+ { QLatin1String("r16i"), QShaderDescription::ImageFormatR16i },
+ { QLatin1String("r8i"), QShaderDescription::ImageFormatR8i },
+ { QLatin1String("rgba32ui"), QShaderDescription::ImageFormatRgba32ui },
+ { QLatin1String("rgba16ui"), QShaderDescription::ImageFormatRgba16ui },
+ { QLatin1String("rgba8ui"), QShaderDescription::ImageFormatRgba8ui },
+ { QLatin1String("r32ui"), QShaderDescription::ImageFormatR32ui },
+ { QLatin1String("rgb10_a2ui"), QShaderDescription::ImageFormatRgb10a2ui },
+ { QLatin1String("rg32ui"), QShaderDescription::ImageFormatRg32ui },
+ { QLatin1String("rg16ui"), QShaderDescription::ImageFormatRg16ui },
+ { QLatin1String("rg8ui"), QShaderDescription::ImageFormatRg8ui },
+ { QLatin1String("r16ui"), QShaderDescription::ImageFormatR16ui },
+ { QLatin1String("r8ui"), QShaderDescription::ImageFormatR8ui }
+};
+
+static QString imageFormatStr(const QShaderDescription::ImageFormat &f)
+{
+ for (size_t i = 0; i < sizeof(imageFormatTab) / sizeof(ImageFormatTab); ++i) {
+ if (imageFormatTab[i].v == f)
+ return imageFormatTab[i].k;
+ }
+ return QString();
+}
+
+static QShaderDescription::ImageFormat mapImageFormat(const QString &f)
+{
+ for (size_t i = 0; i < sizeof(imageFormatTab) / sizeof(ImageFormatTab); ++i) {
+ if (imageFormatTab[i].k == f)
+ return imageFormatTab[i].v;
+ }
+ return QShaderDescription::ImageFormatUnknown;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QShaderDescription &sd)
+{
+ const QShaderDescriptionPrivate *d = sd.d;
+ QDebugStateSaver saver(dbg);
+
+ if (sd.isValid()) {
+ dbg.nospace() << "QShaderDescription("
+ << "inVars " << d->inVars
+ << " outVars " << d->outVars
+ << " uniformBlocks " << d->uniformBlocks
+ << " pcBlocks " << d->pushConstantBlocks
+ << " storageBlocks " << d->storageBlocks
+ << " combinedSamplers " << d->combinedImageSamplers
+ << " images " << d->storageImages
+ << ')';
+ } else {
+ dbg.nospace() << "QShaderDescription(null)";
+ }
+
+ return dbg;
+}
+
+QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "InOutVariable(" << typeStr(var.type) << ' ' << var.name;
+ if (var.location >= 0)
+ dbg.nospace() << " location=" << var.location;
+ if (var.binding >= 0)
+ dbg.nospace() << " binding=" << var.binding;
+ if (var.descriptorSet >= 0)
+ dbg.nospace() << " set=" << var.descriptorSet;
+ if (var.imageFormat != QShaderDescription::ImageFormatUnknown)
+ dbg.nospace() << " imageFormat=" << imageFormatStr(var.imageFormat);
+ if (var.imageFlags)
+ dbg.nospace() << " imageFlags=" << var.imageFlags;
+ dbg.nospace() << ')';
+ return dbg;
+}
+
+QDebug operator<<(QDebug dbg, const QShaderDescription::BlockVariable &var)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "BlockVariable(" << typeStr(var.type) << ' ' << var.name
+ << " offset=" << var.offset << " size=" << var.size;
+ if (!var.arrayDims.isEmpty())
+ dbg.nospace() << " array=" << var.arrayDims;
+ if (var.arrayStride)
+ dbg.nospace() << " arrayStride=" << var.arrayStride;
+ if (var.matrixStride)
+ dbg.nospace() << " matrixStride=" << var.matrixStride;
+ if (var.matrixIsRowMajor)
+ dbg.nospace() << " [rowmaj]";
+ if (!var.structMembers.isEmpty())
+ dbg.nospace() << " structMembers=" << var.structMembers;
+ dbg.nospace() << ')';
+ return dbg;
+}
+
+QDebug operator<<(QDebug dbg, const QShaderDescription::UniformBlock &blk)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "UniformBlock(" << blk.blockName << ' ' << blk.structName << " size=" << blk.size;
+ if (blk.binding >= 0)
+ dbg.nospace() << " binding=" << blk.binding;
+ if (blk.descriptorSet >= 0)
+ dbg.nospace() << " set=" << blk.descriptorSet;
+ dbg.nospace() << ' ' << blk.members << ')';
+ return dbg;
+}
+
+QDebug operator<<(QDebug dbg, const QShaderDescription::PushConstantBlock &blk)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "PushConstantBlock(" << blk.name << " size=" << blk.size << ' ' << blk.members << ')';
+ return dbg;
+}
+
+QDebug operator<<(QDebug dbg, const QShaderDescription::StorageBlock &blk)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "StorageBlock(" << blk.blockName << ' ' << blk.instanceName << " knownSize=" << blk.knownSize;
+ if (blk.binding >= 0)
+ dbg.nospace() << " binding=" << blk.binding;
+ if (blk.descriptorSet >= 0)
+ dbg.nospace() << " set=" << blk.descriptorSet;
+ dbg.nospace() << ' ' << blk.members << ')';
+ return dbg;
+}
+#endif
+
+static const QString nameKey = QLatin1String("name");
+static const QString typeKey = QLatin1String("type");
+static const QString locationKey = QLatin1String("location");
+static const QString bindingKey = QLatin1String("binding");
+static const QString setKey = QLatin1String("set");
+static const QString imageFormatKey = QLatin1String("imageFormat");
+static const QString imageFlagsKey = QLatin1String("imageFlags");
+static const QString offsetKey = QLatin1String("offset");
+static const QString arrayDimsKey = QLatin1String("arrayDims");
+static const QString arrayStrideKey = QLatin1String("arrayStride");
+static const QString matrixStrideKey = QLatin1String("matrixStride");
+static const QString matrixRowMajorKey = QLatin1String("matrixRowMajor");
+static const QString structMembersKey = QLatin1String("structMembers");
+static const QString membersKey = QLatin1String("members");
+static const QString inputsKey = QLatin1String("inputs");
+static const QString outputsKey = QLatin1String("outputs");
+static const QString uniformBlocksKey = QLatin1String("uniformBlocks");
+static const QString blockNameKey = QLatin1String("blockName");
+static const QString structNameKey = QLatin1String("structName");
+static const QString instanceNameKey = QLatin1String("instanceName");
+static const QString sizeKey = QLatin1String("size");
+static const QString knownSizeKey = QLatin1String("knownSize");
+static const QString pushConstantBlocksKey = QLatin1String("pushConstantBlocks");
+static const QString storageBlocksKey = QLatin1String("storageBlocks");
+static const QString combinedImageSamplersKey = QLatin1String("combinedImageSamplers");
+static const QString storageImagesKey = QLatin1String("storageImages");
+
+static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v)
+{
+ if (v.location >= 0)
+ (*obj)[locationKey] = v.location;
+ if (v.binding >= 0)
+ (*obj)[bindingKey] = v.binding;
+ if (v.descriptorSet >= 0)
+ (*obj)[setKey] = v.descriptorSet;
+ if (v.imageFormat != QShaderDescription::ImageFormatUnknown)
+ (*obj)[imageFormatKey] = imageFormatStr(v.imageFormat);
+ if (v.imageFlags)
+ (*obj)[imageFlagsKey] = int(v.imageFlags);
+}
+
+static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
+{
+ QJsonObject obj;
+ obj[nameKey] = v.name;
+ obj[typeKey] = typeStr(v.type);
+ addDeco(&obj, v);
+ return obj;
+}
+
+static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v)
+{
+ QJsonObject obj;
+ obj[nameKey] = v.name;
+ obj[typeKey] = typeStr(v.type);
+ obj[offsetKey] = v.offset;
+ obj[sizeKey] = v.size;
+ if (!v.arrayDims.isEmpty()) {
+ QJsonArray dimArr;
+ for (int dim : v.arrayDims)
+ dimArr.append(dim);
+ obj[arrayDimsKey] = dimArr;
+ }
+ if (v.arrayStride)
+ obj[arrayStrideKey] = v.arrayStride;
+ if (v.matrixStride)
+ obj[matrixStrideKey] = v.matrixStride;
+ if (v.matrixIsRowMajor)
+ obj[matrixRowMajorKey] = true;
+ if (!v.structMembers.isEmpty()) {
+ QJsonArray arr;
+ for (const QShaderDescription::BlockVariable &sv : v.structMembers)
+ arr.append(blockMemberObject(sv));
+ obj[structMembersKey] = arr;
+ }
+ return obj;
+}
+
+QJsonDocument QShaderDescriptionPrivate::makeDoc()
+{
+ QJsonObject root;
+
+ QJsonArray jinputs;
+ for (const QShaderDescription::InOutVariable &v : qAsConst(inVars))
+ jinputs.append(inOutObject(v));
+ if (!jinputs.isEmpty())
+ root[inputsKey] = jinputs;
+
+ QJsonArray joutputs;
+ for (const QShaderDescription::InOutVariable &v : qAsConst(outVars))
+ joutputs.append(inOutObject(v));
+ if (!joutputs.isEmpty())
+ root[outputsKey] = joutputs;
+
+ QJsonArray juniformBlocks;
+ for (const QShaderDescription::UniformBlock &b : uniformBlocks) {
+ QJsonObject juniformBlock;
+ juniformBlock[blockNameKey] = b.blockName;
+ juniformBlock[structNameKey] = b.structName;
+ juniformBlock[sizeKey] = b.size;
+ if (b.binding >= 0)
+ juniformBlock[bindingKey] = b.binding;
+ if (b.descriptorSet >= 0)
+ juniformBlock[setKey] = b.descriptorSet;
+ QJsonArray members;
+ for (const QShaderDescription::BlockVariable &v : b.members)
+ members.append(blockMemberObject(v));
+ juniformBlock[membersKey] = members;
+ juniformBlocks.append(juniformBlock);
+ }
+ if (!juniformBlocks.isEmpty())
+ root[uniformBlocksKey] = juniformBlocks;
+
+ QJsonArray jpushConstantBlocks;
+ for (const QShaderDescription::PushConstantBlock &b : pushConstantBlocks) {
+ QJsonObject jpushConstantBlock;
+ jpushConstantBlock[nameKey] = b.name;
+ jpushConstantBlock[sizeKey] = b.size;
+ QJsonArray members;
+ for (const QShaderDescription::BlockVariable &v : b.members)
+ members.append(blockMemberObject(v));
+ jpushConstantBlock[membersKey] = members;
+ jpushConstantBlocks.append(jpushConstantBlock);
+ }
+ if (!jpushConstantBlocks.isEmpty())
+ root[pushConstantBlocksKey] = jpushConstantBlocks;
+
+ QJsonArray jstorageBlocks;
+ for (const QShaderDescription::StorageBlock &b : storageBlocks) {
+ QJsonObject jstorageBlock;
+ jstorageBlock[blockNameKey] = b.blockName;
+ jstorageBlock[instanceNameKey] = b.instanceName;
+ jstorageBlock[knownSizeKey] = b.knownSize;
+ if (b.binding >= 0)
+ jstorageBlock[bindingKey] = b.binding;
+ if (b.descriptorSet >= 0)
+ jstorageBlock[setKey] = b.descriptorSet;
+ QJsonArray members;
+ for (const QShaderDescription::BlockVariable &v : b.members)
+ members.append(blockMemberObject(v));
+ jstorageBlock[membersKey] = members;
+ jstorageBlocks.append(jstorageBlock);
+ }
+ if (!jstorageBlocks.isEmpty())
+ root[storageBlocksKey] = jstorageBlocks;
+
+ QJsonArray jcombinedSamplers;
+ for (const QShaderDescription::InOutVariable &v : qAsConst(combinedImageSamplers)) {
+ QJsonObject sampler;
+ sampler[nameKey] = v.name;
+ sampler[typeKey] = typeStr(v.type);
+ addDeco(&sampler, v);
+ jcombinedSamplers.append(sampler);
+ }
+ if (!jcombinedSamplers.isEmpty())
+ root[combinedImageSamplersKey] = jcombinedSamplers;
+
+ QJsonArray jstorageImages;
+ for (const QShaderDescription::InOutVariable &v : qAsConst(storageImages)) {
+ QJsonObject image;
+ image[nameKey] = v.name;
+ image[typeKey] = typeStr(v.type);
+ addDeco(&image, v);
+ jstorageImages.append(image);
+ }
+ if (!jstorageImages.isEmpty())
+ root[storageImagesKey] = jstorageImages;
+
+ return QJsonDocument(root);
+}
+
+static QShaderDescription::InOutVariable inOutVar(const QJsonObject &obj)
+{
+ QShaderDescription::InOutVariable var;
+ var.name = obj[nameKey].toString();
+ var.type = mapType(obj[typeKey].toString());
+ if (obj.contains(locationKey))
+ var.location = obj[locationKey].toInt();
+ if (obj.contains(bindingKey))
+ var.binding = obj[bindingKey].toInt();
+ if (obj.contains(setKey))
+ var.descriptorSet = obj[setKey].toInt();
+ if (obj.contains(imageFormatKey))
+ var.imageFormat = mapImageFormat(obj[imageFormatKey].toString());
+ if (obj.contains(imageFlagsKey))
+ var.imageFlags = QShaderDescription::ImageFlags(obj[imageFlagsKey].toInt());
+ return var;
+}
+
+static QShaderDescription::BlockVariable blockVar(const QJsonObject &obj)
+{
+ QShaderDescription::BlockVariable var;
+ var.name = obj[nameKey].toString();
+ var.type = mapType(obj[typeKey].toString());
+ var.offset = obj[offsetKey].toInt();
+ var.size = obj[sizeKey].toInt();
+ if (obj.contains(arrayDimsKey)) {
+ QJsonArray dimArr = obj[arrayDimsKey].toArray();
+ for (int i = 0; i < dimArr.count(); ++i)
+ var.arrayDims.append(dimArr.at(i).toInt());
+ }
+ if (obj.contains(arrayStrideKey))
+ var.arrayStride = obj[arrayStrideKey].toInt();
+ if (obj.contains(matrixStrideKey))
+ var.matrixStride = obj[matrixStrideKey].toInt();
+ if (obj.contains(matrixRowMajorKey))
+ var.matrixIsRowMajor = obj[matrixRowMajorKey].toBool();
+ if (obj.contains(structMembersKey)) {
+ QJsonArray arr = obj[structMembersKey].toArray();
+ for (int i = 0; i < arr.count(); ++i)
+ var.structMembers.append(blockVar(arr.at(i).toObject()));
+ }
+ return var;
+}
+
+void QShaderDescriptionPrivate::loadDoc(const QJsonDocument &doc)
+{
+ if (doc.isNull()) {
+ qWarning("QShaderDescription: JSON document is empty");
+ return;
+ }
+
+ Q_ASSERT(ref.load() == 1); // must be detached
+
+ inVars.clear();
+ outVars.clear();
+ uniformBlocks.clear();
+ pushConstantBlocks.clear();
+ storageBlocks.clear();
+ combinedImageSamplers.clear();
+ storageImages.clear();
+
+ QJsonObject root = doc.object();
+
+ if (root.contains(inputsKey)) {
+ QJsonArray inputs = root[inputsKey].toArray();
+ for (int i = 0; i < inputs.count(); ++i)
+ inVars.append(inOutVar(inputs[i].toObject()));
+ }
+
+ if (root.contains(outputsKey)) {
+ QJsonArray outputs = root[outputsKey].toArray();
+ for (int i = 0; i < outputs.count(); ++i)
+ outVars.append(inOutVar(outputs[i].toObject()));
+ }
+
+ if (root.contains(uniformBlocksKey)) {
+ QJsonArray ubs = root[uniformBlocksKey].toArray();
+ for (int i = 0; i < ubs.count(); ++i) {
+ QJsonObject ubObj = ubs[i].toObject();
+ QShaderDescription::UniformBlock ub;
+ ub.blockName = ubObj[blockNameKey].toString();
+ ub.structName = ubObj[structNameKey].toString();
+ ub.size = ubObj[sizeKey].toInt();
+ if (ubObj.contains(bindingKey))
+ ub.binding = ubObj[bindingKey].toInt();
+ if (ubObj.contains(setKey))
+ ub.descriptorSet = ubObj[setKey].toInt();
+ QJsonArray members = ubObj[membersKey].toArray();
+ for (const QJsonValue &member : members)
+ ub.members.append(blockVar(member.toObject()));
+ uniformBlocks.append(ub);
+ }
+ }
+
+ if (root.contains(pushConstantBlocksKey)) {
+ QJsonArray pcs = root[pushConstantBlocksKey].toArray();
+ for (int i = 0; i < pcs.count(); ++i) {
+ QJsonObject pcObj = pcs[i].toObject();
+ QShaderDescription::PushConstantBlock pc;
+ pc.name = pcObj[nameKey].toString();
+ pc.size = pcObj[sizeKey].toInt();
+ QJsonArray members = pcObj[membersKey].toArray();
+ for (const QJsonValue &member : members)
+ pc.members.append(blockVar(member.toObject()));
+ pushConstantBlocks.append(pc);
+ }
+ }
+
+ if (root.contains(storageBlocksKey)) {
+ QJsonArray ubs = root[storageBlocksKey].toArray();
+ for (int i = 0; i < ubs.count(); ++i) {
+ QJsonObject sbObj = ubs[i].toObject();
+ QShaderDescription::StorageBlock sb;
+ sb.blockName = sbObj[blockNameKey].toString();
+ sb.instanceName = sbObj[instanceNameKey].toString();
+ sb.knownSize = sbObj[knownSizeKey].toInt();
+ if (sbObj.contains(bindingKey))
+ sb.binding = sbObj[bindingKey].toInt();
+ if (sbObj.contains(setKey))
+ sb.descriptorSet = sbObj[setKey].toInt();
+ QJsonArray members = sbObj[membersKey].toArray();
+ for (const QJsonValue &member : members)
+ sb.members.append(blockVar(member.toObject()));
+ storageBlocks.append(sb);
+ }
+ }
+
+ if (root.contains(combinedImageSamplersKey)) {
+ QJsonArray samplers = root[combinedImageSamplersKey].toArray();
+ for (int i = 0; i < samplers.count(); ++i)
+ combinedImageSamplers.append(inOutVar(samplers[i].toObject()));
+ }
+
+ if (root.contains(storageImagesKey)) {
+ QJsonArray images = root[storageImagesKey].toArray();
+ for (int i = 0; i < images.count(); ++i)
+ storageImages.append(inOutVar(images[i].toObject()));
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/rhi/qshaderdescription_p.h b/src/gui/rhi/qshaderdescription_p.h
new file mode 100644
index 0000000000..43d4256a63
--- /dev/null
+++ b/src/gui/rhi/qshaderdescription_p.h
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADERDESCRIPTION_H
+#define QSHADERDESCRIPTION_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/QString>
+#include <QtCore/QVector>
+
+QT_BEGIN_NAMESPACE
+
+struct QShaderDescriptionPrivate;
+
+class Q_GUI_EXPORT QShaderDescription
+{
+public:
+ QShaderDescription();
+ QShaderDescription(const QShaderDescription &other);
+ QShaderDescription &operator=(const QShaderDescription &other);
+ ~QShaderDescription();
+ void detach();
+
+ bool isValid() const;
+
+ QByteArray toBinaryJson() const;
+ QByteArray toJson() const;
+
+ static QShaderDescription fromBinaryJson(const QByteArray &data);
+
+ enum VariableType {
+ Unknown = 0,
+
+ // do not reorder
+ Float,
+ Vec2,
+ Vec3,
+ Vec4,
+ Mat2,
+ Mat2x3,
+ Mat2x4,
+ Mat3,
+ Mat3x2,
+ Mat3x4,
+ Mat4,
+ Mat4x2,
+ Mat4x3,
+
+ Int,
+ Int2,
+ Int3,
+ Int4,
+
+ Uint,
+ Uint2,
+ Uint3,
+ Uint4,
+
+ Bool,
+ Bool2,
+ Bool3,
+ Bool4,
+
+ Double,
+ Double2,
+ Double3,
+ Double4,
+ DMat2,
+ DMat2x3,
+ DMat2x4,
+ DMat3,
+ DMat3x2,
+ DMat3x4,
+ DMat4,
+ DMat4x2,
+ DMat4x3,
+
+ Sampler1D,
+ Sampler2D,
+ Sampler2DMS,
+ Sampler3D,
+ SamplerCube,
+ Sampler1DArray,
+ Sampler2DArray,
+ Sampler2DMSArray,
+ Sampler3DArray,
+ SamplerCubeArray,
+ SamplerRect,
+ SamplerBuffer,
+
+ Image1D,
+ Image2D,
+ Image2DMS,
+ Image3D,
+ ImageCube,
+ Image1DArray,
+ Image2DArray,
+ Image2DMSArray,
+ Image3DArray,
+ ImageCubeArray,
+ ImageRect,
+ ImageBuffer,
+
+ Struct
+ };
+
+ enum ImageFormat {
+ // must match SPIR-V's ImageFormat
+ ImageFormatUnknown = 0,
+ ImageFormatRgba32f = 1,
+ ImageFormatRgba16f = 2,
+ ImageFormatR32f = 3,
+ ImageFormatRgba8 = 4,
+ ImageFormatRgba8Snorm = 5,
+ ImageFormatRg32f = 6,
+ ImageFormatRg16f = 7,
+ ImageFormatR11fG11fB10f = 8,
+ ImageFormatR16f = 9,
+ ImageFormatRgba16 = 10,
+ ImageFormatRgb10A2 = 11,
+ ImageFormatRg16 = 12,
+ ImageFormatRg8 = 13,
+ ImageFormatR16 = 14,
+ ImageFormatR8 = 15,
+ ImageFormatRgba16Snorm = 16,
+ ImageFormatRg16Snorm = 17,
+ ImageFormatRg8Snorm = 18,
+ ImageFormatR16Snorm = 19,
+ ImageFormatR8Snorm = 20,
+ ImageFormatRgba32i = 21,
+ ImageFormatRgba16i = 22,
+ ImageFormatRgba8i = 23,
+ ImageFormatR32i = 24,
+ ImageFormatRg32i = 25,
+ ImageFormatRg16i = 26,
+ ImageFormatRg8i = 27,
+ ImageFormatR16i = 28,
+ ImageFormatR8i = 29,
+ ImageFormatRgba32ui = 30,
+ ImageFormatRgba16ui = 31,
+ ImageFormatRgba8ui = 32,
+ ImageFormatR32ui = 33,
+ ImageFormatRgb10a2ui = 34,
+ ImageFormatRg32ui = 35,
+ ImageFormatRg16ui = 36,
+ ImageFormatRg8ui = 37,
+ ImageFormatR16ui = 38,
+ ImageFormatR8ui = 39
+ };
+
+ enum ImageFlag {
+ ReadOnlyImage = 1 << 0,
+ WriteOnlyImage = 1 << 1
+ };
+ Q_DECLARE_FLAGS(ImageFlags, ImageFlag)
+
+ // Optional data (like decorations) usually default to an otherwise invalid value (-1 or 0). This is intentional.
+
+ struct InOutVariable {
+ QString name;
+ VariableType type = Unknown;
+ int location = -1;
+ int binding = -1;
+ int descriptorSet = -1;
+ ImageFormat imageFormat = ImageFormatUnknown;
+ ImageFlags imageFlags;
+ };
+
+ struct BlockVariable {
+ QString name;
+ VariableType type = Unknown;
+ int offset = 0;
+ int size = 0;
+ QVector<int> arrayDims;
+ int arrayStride = 0;
+ int matrixStride = 0;
+ bool matrixIsRowMajor = false;
+ QVector<BlockVariable> structMembers;
+ };
+
+ struct UniformBlock {
+ QString blockName;
+ QString structName; // instanceName
+ int size = 0;
+ int binding = -1;
+ int descriptorSet = -1;
+ QVector<BlockVariable> members;
+ };
+
+ struct PushConstantBlock {
+ QString name;
+ int size = 0;
+ QVector<BlockVariable> members;
+ };
+
+ struct StorageBlock {
+ QString blockName;
+ QString instanceName;
+ int knownSize = 0;
+ int binding = -1;
+ int descriptorSet = -1;
+ QVector<BlockVariable> members;
+ };
+
+ QVector<InOutVariable> inputVariables() const;
+ QVector<InOutVariable> outputVariables() const;
+ QVector<UniformBlock> uniformBlocks() const;
+ QVector<PushConstantBlock> pushConstantBlocks() const;
+ QVector<StorageBlock> storageBlocks() const;
+ QVector<InOutVariable> combinedImageSamplers() const;
+ QVector<InOutVariable> storageImages() const;
+
+private:
+ QShaderDescriptionPrivate *d;
+ friend struct QShaderDescriptionPrivate;
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription &);
+#endif
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderDescription::ImageFlags)
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::InOutVariable &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::BlockVariable &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::UniformBlock &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::PushConstantBlock &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::StorageBlock &);
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qshaderdescription_p_p.h b/src/gui/rhi/qshaderdescription_p_p.h
new file mode 100644
index 0000000000..dbe68d1060
--- /dev/null
+++ b/src/gui/rhi/qshaderdescription_p_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADERDESCRIPTION_P_H
+#define QSHADERDESCRIPTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qshaderdescription_p.h"
+#include <QtCore/QVector>
+#include <QtCore/QAtomicInt>
+#include <QtCore/QJsonDocument>
+
+QT_BEGIN_NAMESPACE
+
+struct Q_GUI_EXPORT QShaderDescriptionPrivate
+{
+ QShaderDescriptionPrivate()
+ : ref(1)
+ {
+ }
+
+ QShaderDescriptionPrivate(const QShaderDescriptionPrivate *other)
+ : ref(1),
+ inVars(other->inVars),
+ outVars(other->outVars),
+ uniformBlocks(other->uniformBlocks),
+ pushConstantBlocks(other->pushConstantBlocks),
+ storageBlocks(other->storageBlocks),
+ combinedImageSamplers(other->combinedImageSamplers),
+ storageImages(other->storageImages)
+ {
+ }
+
+ static QShaderDescriptionPrivate *get(QShaderDescription *desc) { return desc->d; }
+ static const QShaderDescriptionPrivate *get(const QShaderDescription *desc) { return desc->d; }
+
+ QJsonDocument makeDoc();
+ void loadDoc(const QJsonDocument &doc);
+
+ QAtomicInt ref;
+ QVector<QShaderDescription::InOutVariable> inVars;
+ QVector<QShaderDescription::InOutVariable> outVars;
+ QVector<QShaderDescription::UniformBlock> uniformBlocks;
+ QVector<QShaderDescription::PushConstantBlock> pushConstantBlocks;
+ QVector<QShaderDescription::StorageBlock> storageBlocks;
+ QVector<QShaderDescription::InOutVariable> combinedImageSamplers;
+ QVector<QShaderDescription::InOutVariable> storageImages;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/rhi.pri b/src/gui/rhi/rhi.pri
new file mode 100644
index 0000000000..d8607f1024
--- /dev/null
+++ b/src/gui/rhi/rhi.pri
@@ -0,0 +1,57 @@
+HEADERS += \
+ rhi/qrhi_p.h \
+ rhi/qrhi_p_p.h \
+ rhi/qrhiprofiler_p.h \
+ rhi/qrhiprofiler_p_p.h \
+ rhi/qrhinull_p.h \
+ rhi/qrhinull_p_p.h \
+ rhi/qshader_p.h \
+ rhi/qshader_p_p.h \
+ rhi/qshaderdescription_p.h \
+ rhi/qshaderdescription_p_p.h
+
+SOURCES += \
+ rhi/qrhi.cpp \
+ rhi/qrhiprofiler.cpp \
+ rhi/qrhinull.cpp \
+ rhi/qshaderdescription.cpp \
+ rhi/qshader.cpp
+
+qtConfig(opengl) {
+ HEADERS += \
+ rhi/qrhigles2_p.h \
+ rhi/qrhigles2_p_p.h
+ SOURCES += \
+ rhi/qrhigles2.cpp
+}
+
+qtConfig(vulkan) {
+ HEADERS += \
+ rhi/qrhivulkan_p.h \
+ rhi/qrhivulkan_p_p.h
+ SOURCES += \
+ rhi/qrhivulkan.cpp
+}
+
+win32 {
+ HEADERS += \
+ rhi/qrhid3d11_p.h \
+ rhi/qrhid3d11_p_p.h
+ SOURCES += \
+ rhi/qrhid3d11.cpp
+
+ LIBS += -ld3d11 -ldxgi -ldxguid -ld3dcompiler
+}
+
+# darwin {
+macos {
+ HEADERS += \
+ rhi/qrhimetal_p.h \
+ rhi/qrhimetal_p_p.h
+ SOURCES += \
+ rhi/qrhimetal.mm
+
+ LIBS += -framework AppKit -framework Metal
+}
+
+include($$PWD/../../3rdparty/VulkanMemoryAllocator.pri)
diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp
index 2278378613..5263ece87c 100644
--- a/src/gui/text/qabstracttextdocumentlayout.cpp
+++ b/src/gui/text/qabstracttextdocumentlayout.cpp
@@ -41,6 +41,7 @@
#include <qtextformat.h>
#include "qtextdocument_p.h"
#include "qtextengine_p.h"
+#include "qtextlist.h"
#include "qabstracttextdocumentlayout_p.h"
@@ -650,6 +651,36 @@ QTextFormat QAbstractTextDocumentLayout::formatAt(const QPointF &pos) const
}
/*!
+ \since 5.14
+
+ Returns the block (probably a list item) whose \l{QTextBlockFormat::marker()}{marker}
+ is found at the given position \a pos.
+*/
+QTextBlock QAbstractTextDocumentLayout::blockWithMarkerAt(const QPointF &pos) const
+{
+ QTextBlock block = document()->firstBlock();
+ while (block.isValid()) {
+ if (block.blockFormat().marker() != QTextBlockFormat::NoMarker) {
+ QRectF blockBr = blockBoundingRect(block);
+ QTextBlockFormat blockFmt = block.blockFormat();
+ QFontMetrics fm(block.charFormat().font());
+ qreal totalIndent = blockFmt.indent() + blockFmt.leftMargin() + blockFmt.textIndent();
+ if (block.textList())
+ totalIndent += block.textList()->format().indent() * 40;
+ QRectF adjustedBr = blockBr.adjusted(totalIndent - fm.height(), 0, totalIndent - blockBr.width(), fm.height() - blockBr.height());
+ if (adjustedBr.contains(pos)) {
+ //qDebug() << "hit block" << block.text() << blockBr << adjustedBr << "marker" << block.blockFormat().marker()
+ // << "font" << block.charFormat().font() << "adj" << lineHeight << totalIndent;
+ if (block.blockFormat().hasProperty(QTextFormat::BlockMarker))
+ return block;
+ }
+ }
+ block = block.next();
+ }
+ return QTextBlock();
+}
+
+/*!
\fn QRectF QAbstractTextDocumentLayout::frameBoundingRect(QTextFrame *frame) const
Returns the bounding rectangle of \a frame.
diff --git a/src/gui/text/qabstracttextdocumentlayout.h b/src/gui/text/qabstracttextdocumentlayout.h
index 8fea27f772..397dcd37d4 100644
--- a/src/gui/text/qabstracttextdocumentlayout.h
+++ b/src/gui/text/qabstracttextdocumentlayout.h
@@ -87,6 +87,7 @@ public:
QString anchorAt(const QPointF& pos) const;
QString imageAt(const QPointF &pos) const;
QTextFormat formatAt(const QPointF &pos) const;
+ QTextBlock blockWithMarkerAt(const QPointF &pos) const;
virtual int pageCount() const = 0;
virtual QSizeF documentSize() const = 0;
@@ -143,7 +144,9 @@ public:
virtual void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format) = 0;
};
+#ifndef Q_CLANG_QDOC
Q_DECLARE_INTERFACE(QTextObjectInterface, "org.qt-project.Qt.QTextObjectInterface")
+#endif
QT_END_NAMESPACE
diff --git a/src/gui/text/qabstracttextdocumentlayout_p.h b/src/gui/text/qabstracttextdocumentlayout_p.h
index 191c463dc6..d631ce3197 100644
--- a/src/gui/text/qabstracttextdocumentlayout_p.h
+++ b/src/gui/text/qabstracttextdocumentlayout_p.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
struct QTextObjectHandler
{
- QTextObjectHandler() : iface(0) {}
+ QTextObjectHandler() : iface(nullptr) {}
QTextObjectInterface *iface;
QPointer<QObject> component;
};
@@ -71,12 +71,12 @@ public:
Q_DECLARE_PUBLIC(QAbstractTextDocumentLayout)
inline QAbstractTextDocumentLayoutPrivate()
- : paintDevice(0) {}
+ : paintDevice(nullptr) {}
~QAbstractTextDocumentLayoutPrivate();
inline void setDocument(QTextDocument *doc) {
document = doc;
- docPrivate = 0;
+ docPrivate = nullptr;
if (doc)
docPrivate = doc->docHandle();
}
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 325fd26a31..b5489c7ed9 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -67,6 +67,7 @@ struct QCssKnownValue
static const QCssKnownValue properties[NumProperties - 1] = {
{ "-qt-background-role", QtBackgroundRole },
{ "-qt-block-indent", QtBlockIndent },
+ { "-qt-fg-texture-cachekey", QtForegroundTextureCacheKey },
{ "-qt-line-height-type", QtLineHeightType },
{ "-qt-list-indent", QtListIndent },
{ "-qt-list-number-prefix", QtListNumberPrefix },
@@ -115,6 +116,7 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "float", Float },
{ "font", Font },
{ "font-family", FontFamily },
+ { "font-kerning", FontKerning },
{ "font-size", FontSize },
{ "font-style", FontStyle },
{ "font-variant", FontVariant },
@@ -368,6 +370,7 @@ static inline bool isInheritable(Property propertyId)
{
switch (propertyId) {
case Font:
+ case FontKerning:
case FontFamily:
case FontSize:
case FontStyle:
@@ -721,7 +724,8 @@ static ColorData parseColorValue(QCss::Value v)
if (lst.count() != 2)
return ColorData();
- if ((lst.at(0).compare(QLatin1String("palette"), Qt::CaseInsensitive)) == 0) {
+ const QString &identifier = lst.at(0);
+ if ((identifier.compare(QLatin1String("palette"), Qt::CaseInsensitive)) == 0) {
int role = findKnownValue(lst.at(1).trimmed(), values, NumKnownValues);
if (role >= Value_FirstColorRole && role <= Value_LastColorRole)
return (QPalette::ColorRole)(role-Value_FirstColorRole);
@@ -729,8 +733,16 @@ static ColorData parseColorValue(QCss::Value v)
return ColorData();
}
- bool rgb = lst.at(0).startsWith(QLatin1String("rgb"));
- bool rgba = lst.at(0).startsWith(QLatin1String("rgba"));
+ const bool rgb = identifier.startsWith(QLatin1String("rgb"));
+ const bool hsv = !rgb && identifier.startsWith(QLatin1String("hsv"));
+ const bool hsl = !rgb && !hsv && identifier.startsWith(QLatin1String("hsl"));
+
+ if (!rgb && !hsv && !hsl)
+ return ColorData();
+
+ const bool hasAlpha = identifier.size() == 4 && identifier.at(3) == QLatin1Char('a');
+ if (identifier.size() > 3 && !hasAlpha)
+ return ColorData();
Parser p(lst.at(1));
if (!p.testExpr())
@@ -743,7 +755,8 @@ static ColorData parseColorValue(QCss::Value v)
for (int i = 0; i < qMin(tokenCount, 7); i += 2) {
if (colorDigits.at(i).type == Value::Percentage) {
- colorDigits[i].variant = colorDigits.at(i).variant.toReal() * (255. / 100.);
+ const qreal maxRange = (rgb || i != 0) ? 255. : 359.;
+ colorDigits[i].variant = colorDigits.at(i).variant.toReal() * (maxRange / 100.);
colorDigits[i].type = Value::Number;
} else if (colorDigits.at(i).type != Value::Number) {
return ColorData();
@@ -754,20 +767,29 @@ static ColorData parseColorValue(QCss::Value v)
if (tokenCount < 5)
return ColorData();
+ // ### Qt6: replace this with a check and return invalid color when token count does not match
+ if (hasAlpha && tokenCount != 7)
+ qWarning("QCssParser::parseColorValue: Specified color with alpha value but no alpha given: '%s'", qPrintable(lst.join(QLatin1Char(' '))));
+ if (!hasAlpha && tokenCount != 5)
+ qWarning("QCssParser::parseColorValue: Specified color without alpha value but alpha given: '%s'", qPrintable(lst.join(QLatin1Char(' '))));
+
int v1 = colorDigits.at(0).variant.toInt();
int v2 = colorDigits.at(2).variant.toInt();
int v3 = colorDigits.at(4).variant.toInt();
int alpha = 255;
- if (tokenCount >= 7) {
+ if (tokenCount == 7) {
int alphaValue = colorDigits.at(6).variant.toInt();
- if (rgba && alphaValue <= 1)
+ if (alphaValue <= 1)
alpha = colorDigits.at(6).variant.toReal() * 255.;
else
alpha = alphaValue;
}
- return rgb ? QColor::fromRgb(v1, v2, v3, alpha)
- : QColor::fromHsv(v1, v2, v3, alpha);
+ if (rgb)
+ return QColor::fromRgb(v1, v2, v3, alpha);
+ if (hsv)
+ return QColor::fromHsv(v1, v2, v3, alpha);
+ return QColor::fromHsl(v1, v2, v3, alpha);
}
static QColor colorFromData(const ColorData& c, const QPalette &pal)
@@ -1142,6 +1164,19 @@ static bool setFontStyleFromValue(const QCss::Value &value, QFont *font)
return false;
}
+static bool setFontKerningFromValue(const QCss::Value &value, QFont *font)
+{
+ if (value.type != Value::KnownIdentifier)
+ return false ;
+ switch (value.variant.toInt()) {
+ case Value_Normal: font->setKerning(true); return true;
+ case Value_None: font->setKerning(false); return true;
+ case Value_Auto: return true;
+ default: break;
+ }
+ return false;
+}
+
static bool setFontWeightFromValue(const QCss::Value &value, QFont *font)
{
if (value.type == Value::KnownIdentifier) {
@@ -1166,11 +1201,13 @@ static bool setFontWeightFromValue(const QCss::Value &value, QFont *font)
static bool setFontFamilyFromValues(const QVector<QCss::Value> &values, QFont *font, int start = 0)
{
QString family;
+ QStringList families;
bool shouldAddSpace = false;
for (int i = start; i < values.count(); ++i) {
const QCss::Value &v = values.at(i);
if (v.type == Value::TermOperatorComma) {
- family += QLatin1Char(',');
+ families << family;
+ family.clear();
shouldAddSpace = false;
continue;
}
@@ -1182,9 +1219,12 @@ static bool setFontFamilyFromValues(const QVector<QCss::Value> &values, QFont *f
family += str;
shouldAddSpace = true;
}
- if (family.isEmpty())
+ if (!family.isEmpty())
+ families << family;
+ if (families.isEmpty())
return false;
- font->setFamily(family);
+ font->setFamily(families.at(0));
+ font->setFamilies(families);
return true;
}
@@ -1274,6 +1314,7 @@ bool ValueExtractor::extractFont(QFont *font, int *fontSizeAdjustment)
case FontStyle: setFontStyleFromValue(val, font); break;
case FontWeight: setFontWeightFromValue(val, font); break;
case FontFamily: setFontFamilyFromValues(decl.d->values, font); break;
+ case FontKerning: setFontKerningFromValue(val, font); break;
case TextDecoration: setTextDecorationFromValues(decl.d->values, font); break;
case Font: parseShorthandFontProperty(decl.d->values, font, fontSizeAdjustment); break;
case FontVariant: setFontVariantFromValue(val, font); break;
@@ -1968,7 +2009,7 @@ bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node)
}
void StyleSelector::matchRule(NodePtr node, const StyleRule &rule, StyleSheetOrigin origin,
- int depth, QMap<uint, StyleRule> *weightedRules)
+ int depth, QMultiMap<uint, StyleRule> *weightedRules)
{
for (int j = 0; j < rule.selectors.count(); ++j) {
const Selector& selector = rule.selectors.at(j);
@@ -1982,7 +2023,7 @@ void StyleSelector::matchRule(NodePtr node, const StyleRule &rule, StyleSheetOri
newRule.selectors[0] = selector;
}
//We might have rules with the same weight if they came from a rule with several selectors
- weightedRules->insertMulti(weight, newRule);
+ weightedRules->insert(weight, newRule);
}
}
}
@@ -1995,7 +2036,7 @@ QVector<StyleRule> StyleSelector::styleRulesForNode(NodePtr node)
if (styleSheets.isEmpty())
return rules;
- QMap<uint, StyleRule> weightedRules; // (spec, rule) that will be sorted below
+ QMultiMap<uint, StyleRule> weightedRules; // (spec, rule) that will be sorted below
//prune using indexed stylesheet
for (int sheetIdx = 0; sheetIdx < styleSheets.count(); ++sheetIdx) {
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index c1594531ea..b0fa4be682 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -195,6 +195,8 @@ enum Property {
QtListNumberSuffix,
LineHeight,
QtLineHeightType,
+ FontKerning,
+ QtForegroundTextureCacheKey,
NumProperties
};
@@ -466,8 +468,8 @@ struct Q_GUI_EXPORT Declaration
Attachment attachmentValue() const;
int styleFeaturesValue() const;
- bool intValue(int *i, const char *unit = 0) const;
- bool realValue(qreal *r, const char *unit = 0) const;
+ bool intValue(int *i, const char *unit = nullptr) const;
+ bool realValue(qreal *r, const char *unit = nullptr) const;
QSize sizeValue() const;
QRect rectValue() const;
@@ -583,7 +585,7 @@ struct Q_GUI_EXPORT Selector
{
QVector<BasicSelector> basicSelectors;
int specificity() const;
- quint64 pseudoClass(quint64 *negated = 0) const;
+ quint64 pseudoClass(quint64 *negated = nullptr) const;
QString pseudoElement() const;
};
QT_CSS_DECLARE_TYPEINFO(Selector, Q_MOVABLE_TYPE)
@@ -655,7 +657,7 @@ public:
};
QVector<StyleRule> styleRulesForNode(NodePtr node);
- QVector<Declaration> declarationsForNode(NodePtr node, const char *extraPseudo = 0);
+ QVector<Declaration> declarationsForNode(NodePtr node, const char *extraPseudo = nullptr);
virtual bool nodeNameEquals(NodePtr node, const QString& nodeName) const;
virtual QString attribute(NodePtr node, const QString &name) const = 0;
@@ -673,7 +675,7 @@ public:
Qt::CaseSensitivity nameCaseSensitivity;
private:
void matchRule(NodePtr node, const StyleRule &rules, StyleSheetOrigin origin,
- int depth, QMap<uint, StyleRule> *weightedRules);
+ int depth, QMultiMap<uint, StyleRule> *weightedRules);
bool selectorMatches(const Selector &rule, NodePtr node);
bool basicSelectorMatches(const BasicSelector &rule, NodePtr node);
};
@@ -743,7 +745,7 @@ QT_CSS_DECLARE_TYPEINFO(Symbol, Q_MOVABLE_TYPE)
class Q_GUI_EXPORT Scanner
{
public:
- static QString preprocess(const QString &input, bool *hasEscapeSequences = 0);
+ static QString preprocess(const QString &input, bool *hasEscapeSequences = nullptr);
static void scan(const QString &preprocessedInput, QVector<Symbol> *symbols);
};
@@ -844,7 +846,7 @@ struct Q_GUI_EXPORT ValueExtractor
bool extractGeometry(int *w, int *h, int *minw, int *minh, int *maxw, int *maxh);
bool extractPosition(int *l, int *t, int *r, int *b, QCss::Origin *, Qt::Alignment *,
QCss::PositionMode *, Qt::Alignment *);
- bool extractBox(int *margins, int *paddings, int *spacing = 0);
+ bool extractBox(int *margins, int *paddings, int *spacing = nullptr);
bool extractBorder(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii);
bool extractOutline(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii, int *offsets);
bool extractPalette(QBrush *fg, QBrush *sfg, QBrush *sbg, QBrush *abg);
diff --git a/src/gui/text/qcssscanner.cpp b/src/gui/text/qcssscanner.cpp
index 33dc01c8bc..d48cbb71d7 100644
--- a/src/gui/text/qcssscanner.cpp
+++ b/src/gui/text/qcssscanner.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -37,7 +37,7 @@
**
****************************************************************************/
-// auto generated. DO NOT EDIT.
+// auto generated by qtbase/util/lexgen/. DO NOT EDIT.
class QCssScanner_Generated
{
public:
@@ -75,23 +75,23 @@ int QCssScanner_Generated::lex()
// initial state
ch = next();
if (ch.unicode() >= 9 && ch.unicode() <= 10)
- goto state_1;
+ goto state_4;
if (ch.unicode() >= 12 && ch.unicode() <= 13)
- goto state_1;
+ goto state_4;
if (ch.unicode() == 32)
- goto state_1;
+ goto state_4;
if (ch.unicode() == 33) {
token = QCss::EXCLAMATION_SYM;
goto found;
}
if (ch.unicode() == 34)
- goto state_3;
+ goto state_2;
if (ch.unicode() == 35)
- goto state_4;
+ goto state_1;
if (ch.unicode() == 36)
- goto state_5;
- if (ch.unicode() == 39)
goto state_6;
+ if (ch.unicode() == 39)
+ goto state_5;
if (ch.unicode() == 40) {
token = QCss::LPAREN;
goto found;
@@ -101,17 +101,17 @@ int QCssScanner_Generated::lex()
goto found;
}
if (ch.unicode() == 42)
- goto state_9;
+ goto state_8;
if (ch.unicode() == 43)
- goto state_10;
+ goto state_7;
if (ch.unicode() == 44)
- goto state_11;
+ goto state_14;
if (ch.unicode() == 45)
- goto state_12;
- if (ch.unicode() == 46)
goto state_13;
+ if (ch.unicode() == 46)
+ goto state_12;
if (ch.unicode() == 47)
- goto state_14;
+ goto state_11;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
goto state_15;
if (ch.unicode() == 58) {
@@ -123,64 +123,56 @@ int QCssScanner_Generated::lex()
goto found;
}
if (ch.unicode() == 60)
- goto state_18;
+ goto state_20;
if (ch.unicode() == 61) {
token = QCss::EQUAL;
goto found;
}
if (ch.unicode() == 62)
- goto state_20;
+ goto state_18;
if (ch.unicode() == 64)
- goto state_21;
+ goto state_26;
if (ch.unicode() == 91) {
token = QCss::LBRACKET;
goto found;
}
if (ch.unicode() == 92)
- goto state_23;
+ goto state_30;
if (ch.unicode() == 93) {
token = QCss::RBRACKET;
goto found;
}
if (ch.unicode() == 94)
- goto state_25;
+ goto state_28;
if (ch.unicode() == 95)
- goto state_26;
+ goto state_21;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_26;
+ goto state_21;
if (ch.unicode() == 123)
- goto state_27;
+ goto state_22;
if (ch.unicode() == 124)
- goto state_28;
+ goto state_25;
if (ch.unicode() == 125) {
token = QCss::RBRACE;
goto found;
}
if (ch.unicode() == 126)
- goto state_30;
+ goto state_23;
goto out;
state_1:
- lastAcceptingPos = pos;
- token = QCss::S;
ch = next();
- if (ch.unicode() >= 9 && ch.unicode() <= 10)
- goto state_31;
- if (ch.unicode() >= 12 && ch.unicode() <= 13)
+ if (ch.unicode() == 45)
goto state_31;
- if (ch.unicode() == 32)
+ if (ch.unicode() >= 48 && ch.unicode() <= 57)
goto state_31;
- if (ch.unicode() == 43)
- goto state_10;
- if (ch.unicode() == 44)
- goto state_11;
- if (ch.unicode() == 62)
- goto state_20;
- if (ch.unicode() == 123)
- goto state_27;
- if (ch.unicode() == 126)
+ if (ch.unicode() == 92)
goto state_32;
+ if (ch.unicode() == 95)
+ goto state_31;
+ if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
+ goto state_31;
goto out;
- state_3:
+ state_2:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
@@ -204,93 +196,101 @@ int QCssScanner_Generated::lex()
goto state_33;
goto out;
state_4:
+ lastAcceptingPos = pos;
+ token = QCss::S;
ch = next();
- if (ch.unicode() == 45)
- goto state_36;
- if (ch.unicode() >= 48 && ch.unicode() <= 57)
+ if (ch.unicode() >= 9 && ch.unicode() <= 10)
goto state_36;
- if (ch.unicode() == 92)
- goto state_37;
- if (ch.unicode() == 95)
+ if (ch.unicode() >= 12 && ch.unicode() <= 13)
goto state_36;
- if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
+ if (ch.unicode() == 32)
goto state_36;
+ if (ch.unicode() == 43)
+ goto state_7;
+ if (ch.unicode() == 44)
+ goto state_14;
+ if (ch.unicode() == 62)
+ goto state_18;
+ if (ch.unicode() == 123)
+ goto state_22;
+ if (ch.unicode() == 126)
+ goto state_37;
goto out;
state_5:
- ch = next();
- if (ch.unicode() == 61) {
- token = QCss::ENDSWITH;
- goto found;
- }
- goto out;
- state_6:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 11)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 14 && ch.unicode() <= 38)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 39)
- goto state_40;
- if (ch.unicode() >= 40 && ch.unicode() <= 91)
goto state_39;
+ if (ch.unicode() >= 40 && ch.unicode() <= 91)
+ goto state_38;
if (ch.unicode() == 92)
- goto state_41;
+ goto state_40;
if (ch.unicode() >= 93 && ch.unicode() <= 96)
- goto state_39;
+ goto state_38;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 123)
- goto state_39;
+ goto state_38;
goto out;
- state_9:
- lastAcceptingPos = pos;
- token = QCss::STAR;
+ state_6:
ch = next();
if (ch.unicode() == 61) {
- token = QCss::CONTAINS;
+ token = QCss::ENDSWITH;
goto found;
}
goto out;
- state_10:
+ state_7:
lastAcceptingPos = pos;
token = QCss::PLUS;
goto out;
+ state_8:
+ lastAcceptingPos = pos;
+ token = QCss::STAR;
+ ch = next();
+ if (ch.unicode() == 61) {
+ token = QCss::CONTAINS;
+ goto found;
+ }
+ goto out;
state_11:
lastAcceptingPos = pos;
- token = QCss::COMMA;
+ token = QCss::SLASH;
+ ch = next();
+ if (ch.unicode() == 42) {
+ token = handleCommentStart();
+ goto found;
+ }
goto out;
state_12:
lastAcceptingPos = pos;
+ token = QCss::DOT;
+ ch = next();
+ if (ch.unicode() >= 48 && ch.unicode() <= 57)
+ goto state_44;
+ goto out;
+ state_13:
+ lastAcceptingPos = pos;
token = QCss::MINUS;
ch = next();
if (ch.unicode() == 45)
- goto state_43;
+ goto state_45;
if (ch.unicode() == 92)
- goto state_23;
+ goto state_30;
if (ch.unicode() == 95)
- goto state_26;
+ goto state_21;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_26;
- goto out;
- state_13:
- lastAcceptingPos = pos;
- token = QCss::DOT;
- ch = next();
- if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_44;
+ goto state_21;
goto out;
state_14:
lastAcceptingPos = pos;
- token = QCss::SLASH;
- ch = next();
- if (ch.unicode() == 42) {
- token = handleCommentStart();
- goto found;
- }
+ token = QCss::COMMA;
goto out;
state_15:
lastAcceptingPos = pos;
@@ -299,68 +299,70 @@ int QCssScanner_Generated::lex()
if (ch.unicode() == 37)
goto state_46;
if (ch.unicode() == 45)
- goto state_47;
- if (ch.unicode() == 46)
goto state_48;
+ if (ch.unicode() == 46)
+ goto state_47;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
goto state_49;
if (ch.unicode() == 92)
- goto state_50;
- if (ch.unicode() == 95)
goto state_51;
+ if (ch.unicode() == 95)
+ goto state_50;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_51;
+ goto state_50;
goto out;
state_18:
+ lastAcceptingPos = pos;
+ token = QCss::GREATER;
+ goto out;
+ state_20:
ch = next();
if (ch.unicode() == 33)
goto state_52;
goto out;
- state_20:
- lastAcceptingPos = pos;
- token = QCss::GREATER;
- goto out;
state_21:
+ lastAcceptingPos = pos;
+ token = QCss::IDENT;
ch = next();
- if (ch.unicode() == 45)
+ if (ch.unicode() == 40)
goto state_53;
- if (ch.unicode() == 92)
+ if (ch.unicode() == 45)
goto state_54;
- if (ch.unicode() == 95)
+ if (ch.unicode() >= 48 && ch.unicode() <= 57)
+ goto state_54;
+ if (ch.unicode() == 92)
goto state_55;
+ if (ch.unicode() == 95)
+ goto state_54;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_55;
+ goto state_54;
+ goto out;
+ state_22:
+ lastAcceptingPos = pos;
+ token = QCss::LBRACE;
goto out;
state_23:
+ lastAcceptingPos = pos;
+ token = QCss::TILDE;
ch = next();
- if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_56;
- if (ch.unicode() == 11)
- goto state_56;
- if (ch.unicode() >= 14 && ch.unicode() <= 47)
- goto state_56;
- if (ch.unicode() >= 58 && ch.unicode() <= 96)
- goto state_56;
- if (ch.unicode() >= 103)
- goto state_56;
+ if (ch.unicode() == 61) {
+ token = QCss::INCLUDES;
+ goto found;
+ }
goto out;
state_25:
+ lastAcceptingPos = pos;
+ token = QCss::OR;
ch = next();
if (ch.unicode() == 61) {
- token = QCss::BEGINSWITH;
+ token = QCss::DASHMATCH;
goto found;
}
goto out;
state_26:
- lastAcceptingPos = pos;
- token = QCss::IDENT;
ch = next();
- if (ch.unicode() == 40)
- goto state_58;
if (ch.unicode() == 45)
- goto state_59;
- if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_59;
+ goto state_58;
if (ch.unicode() == 92)
goto state_60;
if (ch.unicode() == 95)
@@ -368,52 +370,53 @@ int QCssScanner_Generated::lex()
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
goto state_59;
goto out;
- state_27:
- lastAcceptingPos = pos;
- token = QCss::LBRACE;
- goto out;
state_28:
- lastAcceptingPos = pos;
- token = QCss::OR;
ch = next();
if (ch.unicode() == 61) {
- token = QCss::DASHMATCH;
+ token = QCss::BEGINSWITH;
goto found;
}
goto out;
state_30:
- lastAcceptingPos = pos;
- token = QCss::TILDE;
ch = next();
- if (ch.unicode() == 61) {
- token = QCss::INCLUDES;
- goto found;
- }
+ if (ch.unicode() >= 1 && ch.unicode() <= 9)
+ goto state_62;
+ if (ch.unicode() == 11)
+ goto state_62;
+ if (ch.unicode() >= 14 && ch.unicode() <= 47)
+ goto state_62;
+ if (ch.unicode() >= 58 && ch.unicode() <= 96)
+ goto state_62;
+ if (ch.unicode() >= 103)
+ goto state_62;
goto out;
state_31:
lastAcceptingPos = pos;
- token = QCss::S;
+ token = QCss::HASH;
ch = next();
- if (ch.unicode() >= 9 && ch.unicode() <= 10)
- goto state_31;
- if (ch.unicode() >= 12 && ch.unicode() <= 13)
- goto state_31;
- if (ch.unicode() == 32)
- goto state_31;
- if (ch.unicode() == 43)
- goto state_10;
- if (ch.unicode() == 44)
- goto state_11;
- if (ch.unicode() == 62)
- goto state_20;
- if (ch.unicode() == 123)
- goto state_27;
- if (ch.unicode() == 126)
- goto state_32;
+ if (ch.unicode() == 45)
+ goto state_63;
+ if (ch.unicode() >= 48 && ch.unicode() <= 57)
+ goto state_63;
+ if (ch.unicode() == 92)
+ goto state_64;
+ if (ch.unicode() == 95)
+ goto state_63;
+ if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
+ goto state_63;
goto out;
state_32:
- lastAcceptingPos = pos;
- token = QCss::TILDE;
+ ch = next();
+ if (ch.unicode() >= 1 && ch.unicode() <= 9)
+ goto state_65;
+ if (ch.unicode() == 11)
+ goto state_65;
+ if (ch.unicode() >= 14 && ch.unicode() <= 47)
+ goto state_65;
+ if (ch.unicode() >= 58 && ch.unicode() <= 96)
+ goto state_65;
+ if (ch.unicode() >= 103)
+ goto state_65;
goto out;
state_33:
lastAcceptingPos = pos;
@@ -445,78 +448,75 @@ int QCssScanner_Generated::lex()
state_35:
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_63;
+ goto state_66;
if (ch.unicode() == 10)
- goto state_64;
+ goto state_67;
if (ch.unicode() == 11)
- goto state_63;
+ goto state_66;
if (ch.unicode() == 12)
- goto state_65;
+ goto state_69;
if (ch.unicode() == 13)
- goto state_66;
+ goto state_68;
if (ch.unicode() >= 14 && ch.unicode() <= 47)
- goto state_63;
+ goto state_66;
if (ch.unicode() >= 58 && ch.unicode() <= 96)
- goto state_63;
+ goto state_66;
if (ch.unicode() >= 103)
- goto state_63;
+ goto state_66;
goto out;
state_36:
lastAcceptingPos = pos;
- token = QCss::HASH;
+ token = QCss::S;
ch = next();
- if (ch.unicode() == 45)
- goto state_67;
- if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_67;
- if (ch.unicode() == 92)
- goto state_68;
- if (ch.unicode() == 95)
- goto state_67;
- if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_67;
+ if (ch.unicode() >= 9 && ch.unicode() <= 10)
+ goto state_36;
+ if (ch.unicode() >= 12 && ch.unicode() <= 13)
+ goto state_36;
+ if (ch.unicode() == 32)
+ goto state_36;
+ if (ch.unicode() == 43)
+ goto state_7;
+ if (ch.unicode() == 44)
+ goto state_14;
+ if (ch.unicode() == 62)
+ goto state_18;
+ if (ch.unicode() == 123)
+ goto state_22;
+ if (ch.unicode() == 126)
+ goto state_37;
goto out;
state_37:
- ch = next();
- if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_69;
- if (ch.unicode() == 11)
- goto state_69;
- if (ch.unicode() >= 14 && ch.unicode() <= 47)
- goto state_69;
- if (ch.unicode() >= 58 && ch.unicode() <= 96)
- goto state_69;
- if (ch.unicode() >= 103)
- goto state_69;
+ lastAcceptingPos = pos;
+ token = QCss::TILDE;
goto out;
- state_39:
+ state_38:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 11)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 14 && ch.unicode() <= 38)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 39)
- goto state_40;
- if (ch.unicode() >= 40 && ch.unicode() <= 91)
goto state_39;
+ if (ch.unicode() >= 40 && ch.unicode() <= 91)
+ goto state_38;
if (ch.unicode() == 92)
- goto state_41;
+ goto state_40;
if (ch.unicode() >= 93 && ch.unicode() <= 96)
- goto state_39;
+ goto state_38;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 123)
- goto state_39;
+ goto state_38;
goto out;
- state_40:
+ state_39:
lastAcceptingPos = pos;
token = QCss::STRING;
goto out;
- state_41:
+ state_40:
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
goto state_70;
@@ -525,9 +525,9 @@ int QCssScanner_Generated::lex()
if (ch.unicode() == 11)
goto state_70;
if (ch.unicode() == 12)
- goto state_72;
- if (ch.unicode() == 13)
goto state_73;
+ if (ch.unicode() == 13)
+ goto state_72;
if (ch.unicode() >= 14 && ch.unicode() <= 47)
goto state_70;
if (ch.unicode() >= 58 && ch.unicode() <= 96)
@@ -535,13 +535,6 @@ int QCssScanner_Generated::lex()
if (ch.unicode() >= 103)
goto state_70;
goto out;
- state_43:
- ch = next();
- if (ch.unicode() == 62) {
- token = QCss::CDC;
- goto found;
- }
- goto out;
state_44:
lastAcceptingPos = pos;
token = QCss::NUMBER;
@@ -549,15 +542,22 @@ int QCssScanner_Generated::lex()
if (ch.unicode() == 37)
goto state_46;
if (ch.unicode() == 45)
- goto state_47;
+ goto state_48;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_75;
+ goto state_74;
if (ch.unicode() == 92)
- goto state_50;
- if (ch.unicode() == 95)
goto state_51;
+ if (ch.unicode() == 95)
+ goto state_50;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_51;
+ goto state_50;
+ goto out;
+ state_45:
+ ch = next();
+ if (ch.unicode() == 62) {
+ token = QCss::CDC;
+ goto found;
+ }
goto out;
state_46:
lastAcceptingPos = pos;
@@ -565,17 +565,17 @@ int QCssScanner_Generated::lex()
goto out;
state_47:
ch = next();
- if (ch.unicode() == 92)
- goto state_50;
- if (ch.unicode() == 95)
- goto state_51;
- if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_51;
+ if (ch.unicode() >= 48 && ch.unicode() <= 57)
+ goto state_44;
goto out;
state_48:
ch = next();
- if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_44;
+ if (ch.unicode() == 92)
+ goto state_51;
+ if (ch.unicode() == 95)
+ goto state_50;
+ if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
+ goto state_50;
goto out;
state_49:
lastAcceptingPos = pos;
@@ -584,45 +584,45 @@ int QCssScanner_Generated::lex()
if (ch.unicode() == 37)
goto state_46;
if (ch.unicode() == 45)
- goto state_47;
- if (ch.unicode() == 46)
goto state_48;
+ if (ch.unicode() == 46)
+ goto state_47;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
goto state_49;
if (ch.unicode() == 92)
- goto state_50;
- if (ch.unicode() == 95)
goto state_51;
+ if (ch.unicode() == 95)
+ goto state_50;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_51;
+ goto state_50;
goto out;
state_50:
+ lastAcceptingPos = pos;
+ token = QCss::LENGTH;
ch = next();
- if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_76;
- if (ch.unicode() == 11)
+ if (ch.unicode() == 45)
goto state_76;
- if (ch.unicode() >= 14 && ch.unicode() <= 47)
+ if (ch.unicode() >= 48 && ch.unicode() <= 57)
goto state_76;
- if (ch.unicode() >= 58 && ch.unicode() <= 96)
+ if (ch.unicode() == 92)
+ goto state_77;
+ if (ch.unicode() == 95)
goto state_76;
- if (ch.unicode() >= 103)
+ if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
goto state_76;
goto out;
state_51:
- lastAcceptingPos = pos;
- token = QCss::LENGTH;
ch = next();
- if (ch.unicode() == 45)
- goto state_77;
- if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_77;
- if (ch.unicode() == 92)
+ if (ch.unicode() >= 1 && ch.unicode() <= 9)
+ goto state_78;
+ if (ch.unicode() == 11)
+ goto state_78;
+ if (ch.unicode() >= 14 && ch.unicode() <= 47)
+ goto state_78;
+ if (ch.unicode() >= 58 && ch.unicode() <= 96)
+ goto state_78;
+ if (ch.unicode() >= 103)
goto state_78;
- if (ch.unicode() == 95)
- goto state_77;
- if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_77;
goto out;
state_52:
ch = next();
@@ -630,15 +630,27 @@ int QCssScanner_Generated::lex()
goto state_79;
goto out;
state_53:
+ lastAcceptingPos = pos;
+ token = QCss::FUNCTION;
+ goto out;
+ state_54:
+ lastAcceptingPos = pos;
+ token = QCss::IDENT;
ch = next();
- if (ch.unicode() == 92)
+ if (ch.unicode() == 40)
+ goto state_53;
+ if (ch.unicode() == 45)
goto state_54;
- if (ch.unicode() == 95)
+ if (ch.unicode() >= 48 && ch.unicode() <= 57)
+ goto state_54;
+ if (ch.unicode() == 92)
goto state_55;
+ if (ch.unicode() == 95)
+ goto state_54;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_55;
+ goto state_54;
goto out;
- state_54:
+ state_55:
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
goto state_80;
@@ -651,7 +663,16 @@ int QCssScanner_Generated::lex()
if (ch.unicode() >= 103)
goto state_80;
goto out;
- state_55:
+ state_58:
+ ch = next();
+ if (ch.unicode() == 92)
+ goto state_60;
+ if (ch.unicode() == 95)
+ goto state_59;
+ if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
+ goto state_59;
+ goto out;
+ state_59:
lastAcceptingPos = pos;
token = QCss::ATKEYWORD_SYM;
ch = next();
@@ -666,58 +687,80 @@ int QCssScanner_Generated::lex()
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
goto state_81;
goto out;
- state_56:
+ state_60:
+ ch = next();
+ if (ch.unicode() >= 1 && ch.unicode() <= 9)
+ goto state_83;
+ if (ch.unicode() == 11)
+ goto state_83;
+ if (ch.unicode() >= 14 && ch.unicode() <= 47)
+ goto state_83;
+ if (ch.unicode() >= 58 && ch.unicode() <= 96)
+ goto state_83;
+ if (ch.unicode() >= 103)
+ goto state_83;
+ goto out;
+ state_62:
lastAcceptingPos = pos;
token = QCss::IDENT;
ch = next();
if (ch.unicode() == 40)
- goto state_58;
+ goto state_53;
if (ch.unicode() == 45)
- goto state_59;
+ goto state_54;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_59;
+ goto state_54;
if (ch.unicode() == 92)
- goto state_60;
+ goto state_55;
if (ch.unicode() == 95)
- goto state_59;
+ goto state_54;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_59;
- goto out;
- state_58:
- lastAcceptingPos = pos;
- token = QCss::FUNCTION;
+ goto state_54;
goto out;
- state_59:
+ state_63:
lastAcceptingPos = pos;
- token = QCss::IDENT;
+ token = QCss::HASH;
ch = next();
- if (ch.unicode() == 40)
- goto state_58;
if (ch.unicode() == 45)
- goto state_59;
+ goto state_63;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_59;
+ goto state_63;
if (ch.unicode() == 92)
- goto state_60;
+ goto state_64;
if (ch.unicode() == 95)
- goto state_59;
+ goto state_63;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_59;
+ goto state_63;
goto out;
- state_60:
+ state_64:
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_83;
+ goto state_84;
if (ch.unicode() == 11)
- goto state_83;
+ goto state_84;
if (ch.unicode() >= 14 && ch.unicode() <= 47)
- goto state_83;
+ goto state_84;
if (ch.unicode() >= 58 && ch.unicode() <= 96)
- goto state_83;
+ goto state_84;
if (ch.unicode() >= 103)
- goto state_83;
+ goto state_84;
goto out;
- state_63:
+ state_65:
+ lastAcceptingPos = pos;
+ token = QCss::HASH;
+ ch = next();
+ if (ch.unicode() == 45)
+ goto state_63;
+ if (ch.unicode() >= 48 && ch.unicode() <= 57)
+ goto state_63;
+ if (ch.unicode() == 92)
+ goto state_64;
+ if (ch.unicode() == 95)
+ goto state_63;
+ if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
+ goto state_63;
+ goto out;
+ state_66:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
@@ -740,7 +783,7 @@ int QCssScanner_Generated::lex()
if (ch.unicode() >= 123)
goto state_33;
goto out;
- state_64:
+ state_67:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
@@ -763,12 +806,14 @@ int QCssScanner_Generated::lex()
if (ch.unicode() >= 123)
goto state_33;
goto out;
- state_65:
+ state_68:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
goto state_33;
+ if (ch.unicode() == 10)
+ goto state_85;
if (ch.unicode() == 11)
goto state_33;
if (ch.unicode() >= 14 && ch.unicode() <= 33)
@@ -786,14 +831,12 @@ int QCssScanner_Generated::lex()
if (ch.unicode() >= 123)
goto state_33;
goto out;
- state_66:
+ state_69:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
goto state_33;
- if (ch.unicode() == 10)
- goto state_84;
if (ch.unicode() == 11)
goto state_33;
if (ch.unicode() >= 14 && ch.unicode() <= 33)
@@ -811,191 +854,133 @@ int QCssScanner_Generated::lex()
if (ch.unicode() >= 123)
goto state_33;
goto out;
- state_67:
- lastAcceptingPos = pos;
- token = QCss::HASH;
- ch = next();
- if (ch.unicode() == 45)
- goto state_67;
- if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_67;
- if (ch.unicode() == 92)
- goto state_68;
- if (ch.unicode() == 95)
- goto state_67;
- if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_67;
- goto out;
- state_68:
- ch = next();
- if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_85;
- if (ch.unicode() == 11)
- goto state_85;
- if (ch.unicode() >= 14 && ch.unicode() <= 47)
- goto state_85;
- if (ch.unicode() >= 58 && ch.unicode() <= 96)
- goto state_85;
- if (ch.unicode() >= 103)
- goto state_85;
- goto out;
- state_69:
- lastAcceptingPos = pos;
- token = QCss::HASH;
- ch = next();
- if (ch.unicode() == 45)
- goto state_67;
- if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_67;
- if (ch.unicode() == 92)
- goto state_68;
- if (ch.unicode() == 95)
- goto state_67;
- if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_67;
- goto out;
state_70:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 11)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 14 && ch.unicode() <= 38)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 39)
- goto state_40;
- if (ch.unicode() >= 40 && ch.unicode() <= 91)
goto state_39;
+ if (ch.unicode() >= 40 && ch.unicode() <= 91)
+ goto state_38;
if (ch.unicode() == 92)
- goto state_41;
+ goto state_40;
if (ch.unicode() >= 93 && ch.unicode() <= 96)
- goto state_39;
+ goto state_38;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 123)
- goto state_39;
+ goto state_38;
goto out;
state_71:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 11)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 14 && ch.unicode() <= 38)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 39)
- goto state_40;
- if (ch.unicode() >= 40 && ch.unicode() <= 91)
goto state_39;
+ if (ch.unicode() >= 40 && ch.unicode() <= 91)
+ goto state_38;
if (ch.unicode() == 92)
- goto state_41;
+ goto state_40;
if (ch.unicode() >= 93 && ch.unicode() <= 96)
- goto state_39;
+ goto state_38;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 123)
- goto state_39;
+ goto state_38;
goto out;
state_72:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_39;
+ goto state_38;
+ if (ch.unicode() == 10)
+ goto state_86;
if (ch.unicode() == 11)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 14 && ch.unicode() <= 38)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 39)
- goto state_40;
- if (ch.unicode() >= 40 && ch.unicode() <= 91)
goto state_39;
+ if (ch.unicode() >= 40 && ch.unicode() <= 91)
+ goto state_38;
if (ch.unicode() == 92)
- goto state_41;
+ goto state_40;
if (ch.unicode() >= 93 && ch.unicode() <= 96)
- goto state_39;
+ goto state_38;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 123)
- goto state_39;
+ goto state_38;
goto out;
state_73:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_39;
- if (ch.unicode() == 10)
- goto state_86;
+ goto state_38;
if (ch.unicode() == 11)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 14 && ch.unicode() <= 38)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 39)
- goto state_40;
- if (ch.unicode() >= 40 && ch.unicode() <= 91)
goto state_39;
+ if (ch.unicode() >= 40 && ch.unicode() <= 91)
+ goto state_38;
if (ch.unicode() == 92)
- goto state_41;
+ goto state_40;
if (ch.unicode() >= 93 && ch.unicode() <= 96)
- goto state_39;
+ goto state_38;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 123)
- goto state_39;
+ goto state_38;
goto out;
- state_75:
+ state_74:
lastAcceptingPos = pos;
token = QCss::NUMBER;
ch = next();
if (ch.unicode() == 37)
goto state_46;
if (ch.unicode() == 45)
- goto state_47;
+ goto state_48;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_75;
+ goto state_74;
if (ch.unicode() == 92)
- goto state_50;
- if (ch.unicode() == 95)
goto state_51;
+ if (ch.unicode() == 95)
+ goto state_50;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_51;
+ goto state_50;
goto out;
state_76:
lastAcceptingPos = pos;
token = QCss::LENGTH;
ch = next();
if (ch.unicode() == 45)
- goto state_77;
+ goto state_76;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_77;
+ goto state_76;
if (ch.unicode() == 92)
- goto state_78;
- if (ch.unicode() == 95)
- goto state_77;
- if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_77;
- goto out;
- state_77:
- lastAcceptingPos = pos;
- token = QCss::LENGTH;
- ch = next();
- if (ch.unicode() == 45)
goto state_77;
- if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_77;
- if (ch.unicode() == 92)
- goto state_78;
if (ch.unicode() == 95)
- goto state_77;
+ goto state_76;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_77;
+ goto state_76;
goto out;
- state_78:
+ state_77:
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
goto state_87;
@@ -1008,6 +993,21 @@ int QCssScanner_Generated::lex()
if (ch.unicode() >= 103)
goto state_87;
goto out;
+ state_78:
+ lastAcceptingPos = pos;
+ token = QCss::LENGTH;
+ ch = next();
+ if (ch.unicode() == 45)
+ goto state_76;
+ if (ch.unicode() >= 48 && ch.unicode() <= 57)
+ goto state_76;
+ if (ch.unicode() == 92)
+ goto state_77;
+ if (ch.unicode() == 95)
+ goto state_76;
+ if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
+ goto state_76;
+ goto out;
state_79:
ch = next();
if (ch.unicode() == 45) {
@@ -1017,18 +1017,20 @@ int QCssScanner_Generated::lex()
goto out;
state_80:
lastAcceptingPos = pos;
- token = QCss::ATKEYWORD_SYM;
+ token = QCss::IDENT;
ch = next();
+ if (ch.unicode() == 40)
+ goto state_53;
if (ch.unicode() == 45)
- goto state_81;
+ goto state_54;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_81;
+ goto state_54;
if (ch.unicode() == 92)
- goto state_82;
+ goto state_55;
if (ch.unicode() == 95)
- goto state_81;
+ goto state_54;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_81;
+ goto state_54;
goto out;
state_81:
lastAcceptingPos = pos;
@@ -1060,23 +1062,36 @@ int QCssScanner_Generated::lex()
goto out;
state_83:
lastAcceptingPos = pos;
- token = QCss::IDENT;
+ token = QCss::ATKEYWORD_SYM;
ch = next();
- if (ch.unicode() == 40)
- goto state_58;
if (ch.unicode() == 45)
- goto state_59;
+ goto state_81;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_59;
+ goto state_81;
if (ch.unicode() == 92)
- goto state_60;
+ goto state_82;
if (ch.unicode() == 95)
- goto state_59;
+ goto state_81;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_59;
+ goto state_81;
goto out;
state_84:
lastAcceptingPos = pos;
+ token = QCss::HASH;
+ ch = next();
+ if (ch.unicode() == 45)
+ goto state_63;
+ if (ch.unicode() >= 48 && ch.unicode() <= 57)
+ goto state_63;
+ if (ch.unicode() == 92)
+ goto state_64;
+ if (ch.unicode() == 95)
+ goto state_63;
+ if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
+ goto state_63;
+ goto out;
+ state_85:
+ lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
@@ -1098,58 +1113,43 @@ int QCssScanner_Generated::lex()
if (ch.unicode() >= 123)
goto state_33;
goto out;
- state_85:
- lastAcceptingPos = pos;
- token = QCss::HASH;
- ch = next();
- if (ch.unicode() == 45)
- goto state_67;
- if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_67;
- if (ch.unicode() == 92)
- goto state_68;
- if (ch.unicode() == 95)
- goto state_67;
- if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_67;
- goto out;
state_86:
lastAcceptingPos = pos;
token = QCss::INVALID;
ch = next();
if (ch.unicode() >= 1 && ch.unicode() <= 9)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 11)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 14 && ch.unicode() <= 38)
- goto state_39;
+ goto state_38;
if (ch.unicode() == 39)
- goto state_40;
- if (ch.unicode() >= 40 && ch.unicode() <= 91)
goto state_39;
+ if (ch.unicode() >= 40 && ch.unicode() <= 91)
+ goto state_38;
if (ch.unicode() == 92)
- goto state_41;
+ goto state_40;
if (ch.unicode() >= 93 && ch.unicode() <= 96)
- goto state_39;
+ goto state_38;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_39;
+ goto state_38;
if (ch.unicode() >= 123)
- goto state_39;
+ goto state_38;
goto out;
state_87:
lastAcceptingPos = pos;
token = QCss::LENGTH;
ch = next();
if (ch.unicode() == 45)
- goto state_77;
+ goto state_76;
if (ch.unicode() >= 48 && ch.unicode() <= 57)
- goto state_77;
+ goto state_76;
if (ch.unicode() == 92)
- goto state_78;
- if (ch.unicode() == 95)
goto state_77;
+ if (ch.unicode() == 95)
+ goto state_76;
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256)
- goto state_77;
+ goto state_76;
goto out;
state_89:
lastAcceptingPos = pos;
@@ -1176,4 +1176,3 @@ int QCssScanner_Generated::lex()
}
return token;
}
-
diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp
index 75e2e4e745..17824a5ba1 100644
--- a/src/gui/text/qdistancefield.cpp
+++ b/src/gui/text/qdistancefield.cpp
@@ -782,7 +782,7 @@ bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine)
if (glyph != 0)
im = fe->alphaMapForGlyph(glyph, QFixed(), QTransform());
- Q_ASSERT(fe->ref.load() == 0);
+ Q_ASSERT(fe->ref.loadRelaxed() == 0);
delete fe;
return imageHasNarrowOutlines(im);
@@ -899,6 +899,9 @@ QDistanceField::QDistanceField(int width, int height)
{
}
+QDistanceField &QDistanceField::operator=(const QDistanceField &)
+ = default;
+
QDistanceField::QDistanceField(const QRawFont &font, glyph_t glyph, bool doubleResolution)
{
setGlyph(font, glyph, doubleResolution);
diff --git a/src/gui/text/qdistancefield_p.h b/src/gui/text/qdistancefield_p.h
index c0873cedab..d6d8edd85d 100644
--- a/src/gui/text/qdistancefield_p.h
+++ b/src/gui/text/qdistancefield_p.h
@@ -72,7 +72,7 @@ int Q_GUI_EXPORT QT_DISTANCEFIELD_HIGHGLYPHCOUNT();
class Q_GUI_EXPORT QDistanceFieldData : public QSharedData
{
public:
- QDistanceFieldData() : glyph(0), width(0), height(0), nbytes(0), data(0) {}
+ QDistanceFieldData() : glyph(0), width(0), height(0), nbytes(0), data(nullptr) {}
QDistanceFieldData(const QDistanceFieldData &other);
~QDistanceFieldData();
@@ -94,6 +94,7 @@ public:
QDistanceField(const QRawFont &font, glyph_t glyph, bool doubleResolution = false);
QDistanceField(QFontEngine *fontEngine, glyph_t glyph, bool doubleResolution = false);
QDistanceField(const QPainterPath &path, glyph_t glyph, bool doubleResolution = false);
+ QDistanceField &operator=(const QDistanceField &other);
bool isNull() const;
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index fe4fa4929a..5555422b82 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -116,7 +116,17 @@ bool QFontDef::exactMatch(const QFontDef &other) const
if (stretch != 0 && other.stretch != 0 && stretch != other.stretch)
return false;
+ if (families.size() != other.families.size())
+ return false;
+
QString this_family, this_foundry, other_family, other_foundry;
+ for (int i = 0; i < families.size(); ++i) {
+ QFontDatabase::parseFontName(families.at(i), this_foundry, this_family);
+ QFontDatabase::parseFontName(other.families.at(i), other_foundry, other_family);
+ if (this_family != other_family || this_foundry != other_foundry)
+ return false;
+ }
+
QFontDatabase::parseFontName(family, this_foundry, this_family);
QFontDatabase::parseFontName(other.family, other_foundry, other_family);
@@ -261,6 +271,9 @@ void QFontPrivate::resolve(uint mask, const QFontPrivate *other)
if (! (mask & QFont::FamilyResolved))
request.family = other->request.family;
+ if (!(mask & QFont::FamiliesResolved))
+ request.families = other->request.families;
+
if (! (mask & QFont::StyleNameResolved))
request.styleName = other->request.styleName;
@@ -323,7 +336,7 @@ QFontEngineData::QFontEngineData()
QFontEngineData::~QFontEngineData()
{
- Q_ASSERT(ref.load() == 0);
+ Q_ASSERT(ref.loadRelaxed() == 0);
for (int i = 0; i < QChar::ScriptCount; ++i) {
if (engines[i]) {
if (!engines[i]->ref.deref())
@@ -340,7 +353,7 @@ QFontEngineData::~QFontEngineData()
\class QFont
\reentrant
- \brief The QFont class specifies a font used for drawing text.
+ \brief The QFont class specifies a query for a font used for drawing text.
\ingroup painting
\ingroup appearance
@@ -348,6 +361,7 @@ QFontEngineData::~QFontEngineData()
\ingroup richtext-processing
\inmodule QtGui
+ QFont can be regarded as a query for one or more fonts on the system.
When you create a QFont object you specify various attributes that
you want the font to have. Qt will use the font with the specified
@@ -355,9 +369,15 @@ QFontEngineData::~QFontEngineData()
matching installed font. The attributes of the font that is
actually used are retrievable from a QFontInfo object. If the
window system provides an exact match exactMatch() returns \c true.
- Use QFontMetrics to get measurements, e.g. the pixel length of a
+ Use QFontMetricsF to get measurements, e.g. the pixel length of a
string using QFontMetrics::width().
+ Attributes which are not specifically set will not affect the font
+ selection algorithm, and default values will be preferred instead.
+
+ To load a specific physical font, typically represented by a single file,
+ use QRawFont instead.
+
Note that a QGuiApplication instance must exist before a QFont can be
used. You can set the application's default font with
QGuiApplication::setFont().
@@ -390,8 +410,6 @@ QFontEngineData::~QFontEngineData()
setStyleHint(). The default family (corresponding to the current
style hint) is returned by defaultFamily().
- The font-matching algorithm has a lastResortFamily() and
- lastResortFont() in cases where a suitable match cannot be found.
You can provide substitutions for font family names using
insertSubstitution() and insertSubstitutions(). Substitutions can
be removed with removeSubstitutions(). Use substitute() to retrieve
@@ -419,18 +437,21 @@ QFontEngineData::~QFontEngineData()
\target fontmatching
The font matching algorithm works as follows:
\list 1
- \li The specified font family is searched for.
- \li If not found, the styleHint() is used to select a replacement
- family.
- \li Each replacement font family is searched for.
- \li If none of these are found or there was no styleHint(), "helvetica"
- will be searched for.
- \li If "helvetica" isn't found Qt will try the lastResortFamily().
- \li If the lastResortFamily() isn't found Qt will try the
- lastResortFont() which will always return a name of some kind.
+ \li The specified font families (set by setFamilies()) are searched for.
+ \li If not found, then if set the specified font family exists and can be used to represent
+ the writing system in use, it will be selected.
+ \li If not, a replacement font that supports the writing system is
+ selected. The font matching algorithm will try to find the
+ best match for all the properties set in the QFont. How this is
+ done varies from platform to platform.
+ \li If no font exists on the system that can support the text,
+ then special "missing character" boxes will be shown in its place.
\endlist
- Note that the actual font matching algorithm varies from platform to platform.
+ \note If the selected font, though supporting the writing system in general,
+ is missing glyphs for one or more specific characters, then Qt will try to
+ find a fallback font for this or these particular characters. This feature
+ can be disabled using QFont::NoFontMerging style strategy.
In Windows a request for the "Courier" font is automatically changed to
"Courier New", an improved version of Courier that allows for smooth scaling.
@@ -499,6 +520,7 @@ QFontEngineData::~QFontEngineData()
individually and then considered resolved.
\value FamilyResolved
+ \value FamiliesResolved
\value SizeResolved
\value StyleHintResolved
\value StyleStrategyResolved
@@ -540,14 +562,25 @@ QFontEngineData::~QFontEngineData()
\since 5.2
*/
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
/*!
+ \obsolete
Constructs a font from \a font for use on the paint device \a pd.
*/
QFont::QFont(const QFont &font, QPaintDevice *pd)
+ : QFont(font, static_cast<const QPaintDevice*>(pd))
+{}
+#endif
+
+/*!
+ \since 5.13
+ Constructs a font from \a font for use on the paint device \a pd.
+*/
+QFont::QFont(const QFont &font, const QPaintDevice *pd)
: resolve_mask(font.resolve_mask)
{
- Q_ASSERT(pd != 0);
- int dpi = pd->logicalDpiY();
+ Q_ASSERT(pd);
+ const int dpi = pd->logicalDpiY();
const int screen = 0;
if (font.d->dpi != dpi || font.d->screen != screen ) {
d = new QFontPrivate(*font.d);
@@ -571,7 +604,7 @@ QFont::QFont(QFontPrivate *data)
*/
void QFont::detach()
{
- if (d->ref.load() == 1) {
+ if (d->ref.loadRelaxed() == 1) {
if (d->engineData && !d->engineData->ref.deref())
delete d->engineData;
d->engineData = 0;
@@ -592,7 +625,7 @@ void QFont::detach()
*/
void QFontPrivate::detachButKeepEngineData(QFont *font)
{
- if (font->d->ref.load() == 1)
+ if (font->d->ref.loadRelaxed() == 1)
return;
QFontEngineData *engineData = font->d->engineData;
@@ -1684,6 +1717,7 @@ bool QFont::operator<(const QFont &f) const
if (r1.stretch != r2.stretch) return r1.stretch < r2.stretch;
if (r1.styleHint != r2.styleHint) return r1.styleHint < r2.styleHint;
if (r1.styleStrategy != r2.styleStrategy) return r1.styleStrategy < r2.styleStrategy;
+ if (r1.families != r2.families) return r1.families < r2.families;
if (r1.family != r2.family) return r1.family < r2.family;
if (f.d->capital != d->capital) return f.d->capital < d->capital;
@@ -2049,7 +2083,7 @@ QString QFont::toString() const
\relates QFont
\since 5.3
*/
-uint qHash(const QFont &font, uint seed) Q_DECL_NOTHROW
+uint qHash(const QFont &font, uint seed) noexcept
{
return qHash(QFontPrivate::get(font)->request, seed);
}
@@ -2133,21 +2167,22 @@ void QFont::cacheStatistics()
{
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\fn QString QFont::lastResortFamily() const
- Returns the "last resort" font family name.
+ \obsolete
- The current implementation tries a wide variety of common fonts,
- returning the first one it finds. Is is possible that no family is
- found in which case an empty string is returned.
+ This function is deprecated and is not in use by the font
+ selection algorithm in Qt 5. It always returns "helvetica".
\sa lastResortFont()
*/
QString QFont::lastResortFamily() const
{
- return QString::fromLatin1("helvetica");
+ return QStringLiteral("helvetica");
}
+#endif
extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
QFont::StyleHint styleHint, QChar::Script script);
@@ -2169,34 +2204,66 @@ QString QFont::defaultFamily() const
return QString();
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\fn QString QFont::lastResortFont() const
- Returns a "last resort" font name for the font matching algorithm.
- This is used if the last resort family is not available. It will
- always return a name, if necessary returning something like
- "fixed" or "system".
+ \obsolete
+
+ Deprecated function. Since Qt 5.0, this is not used by the font selection algorithm. For
+ compatibility it remains in the API, but will always return the same value as lastResortFamily().
+*/
+QString QFont::lastResortFont() const
+{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+ return lastResortFamily();
+QT_WARNING_POP
+}
+#endif
- The current implementation tries a wide variety of common fonts,
- returning the first one it finds. The implementation may change
- at any time, but this function will always return a string
- containing something.
+/*!
+ \since 5.13
- It is theoretically possible that there really isn't a
- lastResortFont() in which case Qt will abort with an error
- message. We have not been able to identify a case where this
- happens. Please \l{bughowto.html}{report it as a bug} if
- it does, preferably with a list of the fonts you have installed.
+ Returns the requested font family names, i.e. the names set in the last
+ setFamilies() call or via the constructor. Otherwise it returns an
+ empty list.
- \sa lastResortFamily()
+ \sa setFamily(), setFamilies(), family(), substitutes(), substitute()
*/
-QString QFont::lastResortFont() const
+
+QStringList QFont::families() const
{
- qFatal("QFont::lastResortFont: Cannot find any reasonable font");
- // Shut compiler up
- return QString();
+ return d->request.families;
}
+/*!
+ \since 5.13
+
+ Sets the list of family names for the font. The names are case
+ insensitive and may include a foundry name. The first family in
+ \a families will be set as the main family for the font.
+
+ Each family name entry in \a families may optionally also include a
+ foundry name, e.g. "Helvetica [Cronyx]". If the family is
+ available from more than one foundry and the foundry isn't
+ specified, an arbitrary foundry is chosen. If the family isn't
+ available a family will be set using the \l{QFont}{font matching}
+ algorithm.
+
+ \sa family(), families(), setFamily(), setStyleHint(), QFontInfo
+*/
+
+void QFont::setFamilies(const QStringList &families)
+{
+ if ((resolve_mask & QFont::FamiliesResolved) && d->request.families == families)
+ return;
+ detach();
+ d->request.families = families;
+ resolve_mask |= QFont::FamiliesResolved;
+}
+
+
/*****************************************************************************
QFont stream functions
*****************************************************************************/
@@ -2261,6 +2328,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << (quint8)font.d->request.hintingPreference;
if (s.version() >= QDataStream::Qt_5_6)
s << (quint8)font.d->capital;
+ if (s.version() >= QDataStream::Qt_5_13)
+ s << font.d->request.families;
return s;
}
@@ -2356,6 +2425,11 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
s >> value;
font.d->capital = QFont::Capitalization(value);
}
+ if (s.version() >= QDataStream::Qt_5_13) {
+ QStringList value;
+ s >> value;
+ font.d->request.families = value;
+ }
return s;
}
@@ -2759,7 +2833,7 @@ void QFontCache::clear()
delete data;
} else {
FC_DEBUG("QFontCache::clear: engineData %p still has refcount %d",
- data, data->ref.load());
+ data, data->ref.loadRelaxed());
}
++it;
}
@@ -2783,7 +2857,7 @@ void QFontCache::clear()
delete engine;
} else if (cacheCount == 0) {
FC_DEBUG("QFontCache::clear: engine %p still has refcount %d",
- engine, engine->ref.load());
+ engine, engine->ref.loadRelaxed());
}
it.value().data = 0;
}
@@ -2853,7 +2927,7 @@ void QFontCache::updateHitCountAndTimeStamp(Engine &value)
FC_DEBUG("QFontCache: found font engine\n"
" %p: timestamp %4u hits %3u ref %2d/%2d, type %d",
value.data, value.timestamp, value.hits,
- value.data->ref.load(), engineCacheCount.value(value.data),
+ value.data->ref.loadRelaxed(), engineCacheCount.value(value.data),
value.data->type());
}
@@ -2863,7 +2937,7 @@ void QFontCache::insertEngine(const Key &key, QFontEngine *engine, bool insertMu
Q_ASSERT(key.multi == (engine->type() == QFontEngine::Multi));
#ifdef QFONTCACHE_DEBUG
- FC_DEBUG("QFontCache: inserting new engine %p, refcount %d", engine, engine->ref.load());
+ FC_DEBUG("QFontCache: inserting new engine %p, refcount %d", engine, engine->ref.loadRelaxed());
if (!insertMulti && engineCache.contains(key)) {
FC_DEBUG(" QFontCache already contains engine %p for key=(%g %g %d %d %d)",
engineCache.value(key).data, key.def.pointSize,
@@ -2879,9 +2953,9 @@ void QFontCache::insertEngine(const Key &key, QFontEngine *engine, bool insertMu
data.timestamp = ++current_timestamp;
if (insertMulti)
- engineCache.insertMulti(key, data);
- else
engineCache.insert(key, data);
+ else
+ engineCache.replace(key, data);
// only increase the cost if this is the first time we insert the engine
if (++engineCacheCount[engine] == 1)
increaseCost(engine->cache_cost);
@@ -2952,9 +3026,9 @@ void QFontCache::decreaseCache()
EngineDataCache::ConstIterator it = engineDataCache.constBegin(),
end = engineDataCache.constEnd();
for (; it != end; ++it) {
- FC_DEBUG(" %p: ref %2d", it.value(), int(it.value()->ref.load()));
+ FC_DEBUG(" %p: ref %2d", it.value(), int(it.value()->ref.loadRelaxed()));
- if (it.value()->ref.load() != 1)
+ if (it.value()->ref.loadRelaxed() != 1)
in_use_cost += engine_data_cost;
}
}
@@ -2967,10 +3041,10 @@ void QFontCache::decreaseCache()
for (; it != end; ++it) {
FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, cost %u bytes",
it.value().data, it.value().timestamp, it.value().hits,
- it.value().data->ref.load(), engineCacheCount.value(it.value().data),
+ it.value().data->ref.loadRelaxed(), engineCacheCount.value(it.value().data),
it.value().data->cache_cost);
- if (it.value().data->ref.load() > engineCacheCount.value(it.value().data))
+ if (it.value().data->ref.loadRelaxed() > engineCacheCount.value(it.value().data))
in_use_cost += it.value().data->cache_cost / engineCacheCount.value(it.value().data);
}
@@ -3019,7 +3093,7 @@ void QFontCache::decreaseCache()
// clean out all unused engine data
EngineDataCache::Iterator it = engineDataCache.begin();
while (it != engineDataCache.end()) {
- if (it.value()->ref.load() == 1) {
+ if (it.value()->ref.loadRelaxed() == 1) {
FC_DEBUG(" %p", it.value());
decreaseCost(sizeof(QFontEngineData));
it.value()->ref.deref();
@@ -3047,7 +3121,7 @@ void QFontCache::decreaseCache()
EngineCache::Iterator jt = end;
for ( ; it != end; ++it) {
- if (it.value().data->ref.load() != engineCacheCount.value(it.value().data))
+ if (it.value().data->ref.loadRelaxed() != engineCacheCount.value(it.value().data))
continue;
if (it.value().timestamp < oldest && it.value().hits <= least_popular) {
@@ -3061,7 +3135,7 @@ void QFontCache::decreaseCache()
if (it != end) {
FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, type %d",
it.value().data, it.value().timestamp, it.value().hits,
- it.value().data->ref.load(), engineCacheCount.value(it.value().data),
+ it.value().data->ref.loadRelaxed(), engineCacheCount.value(it.value().data),
it.value().data->type());
QFontEngine *fontEngine = it.value().data;
@@ -3076,7 +3150,7 @@ void QFontCache::decreaseCache()
}
}
// and delete the last occurrence
- Q_ASSERT(fontEngine->ref.load() == 0);
+ Q_ASSERT(fontEngine->ref.loadRelaxed() == 0);
decreaseCost(fontEngine->cache_cost);
delete fontEngine;
engineCacheCount.remove(fontEngine);
@@ -3090,7 +3164,104 @@ void QFontCache::decreaseCache()
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug stream, const QFont &font)
{
- return stream << "QFont(" << font.toString() << ')';
+ QDebugStateSaver saver(stream);
+ stream.nospace().noquote();
+ stream << "QFont(";
+
+ if (stream.verbosity() == QDebug::DefaultVerbosity) {
+ stream << font.toString() << ")";
+ return stream;
+ }
+
+ QString fontDescription;
+ QDebug debug(&fontDescription);
+ debug.nospace();
+
+ QFontPrivate priv;
+ const QFont defaultFont(&priv);
+
+ for (int property = QFont::FamilyResolved; property < QFont::AllPropertiesResolved; property <<= 1) {
+ const bool resolved = (font.resolve_mask & property) != 0;
+ if (!resolved && stream.verbosity() == QDebug::MinimumVerbosity)
+ continue;
+
+ #define QFONT_DEBUG_SKIP_DEFAULT(prop) \
+ if ((font.prop() == defaultFont.prop()) && stream.verbosity() == 1) \
+ continue;
+
+ QDebugStateSaver saver(debug);
+
+ switch (property) {
+ case QFont::FamilyResolved:
+ debug << font.family(); break;
+ case QFont::SizeResolved:
+ if (font.pointSizeF() >= 0)
+ debug << font.pointSizeF() << "pt";
+ else if (font.pixelSize() >= 0)
+ debug << font.pixelSize() << "px";
+ else
+ Q_UNREACHABLE();
+ break;
+ case QFont::StyleHintResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(styleHint);
+ debug.verbosity(1) << font.styleHint(); break;
+ case QFont::StyleStrategyResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(styleStrategy);
+ debug.verbosity(1) << font.styleStrategy(); break;
+ case QFont::WeightResolved:
+ debug.verbosity(1) << QFont::Weight(font.weight()); break;
+ case QFont::StyleResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(style);
+ debug.verbosity(0) << font.style(); break;
+ case QFont::UnderlineResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(underline);
+ debug << "underline=" << font.underline(); break;
+ case QFont::OverlineResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(overline);
+ debug << "overline=" << font.overline(); break;
+ case QFont::StrikeOutResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(strikeOut);
+ debug << "strikeOut=" << font.strikeOut(); break;
+ case QFont::FixedPitchResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(fixedPitch);
+ debug << "fixedPitch=" << font.fixedPitch(); break;
+ case QFont::StretchResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(stretch);
+ debug.verbosity(0) << QFont::Stretch(font.stretch()); break;
+ case QFont::KerningResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(kerning);
+ debug << "kerning=" << font.kerning(); break;
+ case QFont::CapitalizationResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(capitalization);
+ debug.verbosity(0) << font.capitalization(); break;
+ case QFont::LetterSpacingResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(letterSpacing);
+ debug << "letterSpacing=" << font.letterSpacing();
+ debug.verbosity(0) << " (" << font.letterSpacingType() << ")";
+ break;
+ case QFont::HintingPreferenceResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(hintingPreference);
+ debug.verbosity(0) << font.hintingPreference(); break;
+ case QFont::StyleNameResolved:
+ QFONT_DEBUG_SKIP_DEFAULT(styleName);
+ debug << "styleName=" << font.styleName(); break;
+ default:
+ continue;
+ };
+
+ #undef QFONT_DEBUG_SKIP_DEFAULT
+
+ debug << ", ";
+ }
+
+ if (stream.verbosity() > QDebug::MinimumVerbosity)
+ debug.verbosity(0) << "resolveMask=" << QFlags<QFont::ResolveProperties>(font.resolve_mask);
+ else
+ fontDescription.chop(2); // Last ', '
+
+ stream << fontDescription << ')';
+
+ return stream;
}
#endif
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index 9c250c82c3..683aa3bf65 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -147,6 +147,7 @@ public:
Q_ENUM(SpacingType)
enum ResolveProperties {
+ NoPropertiesResolved = 0x0000,
FamilyResolved = 0x0001,
SizeResolved = 0x0002,
StyleHintResolved = 0x0004,
@@ -164,13 +165,18 @@ public:
WordSpacingResolved = 0x4000,
HintingPreferenceResolved = 0x8000,
StyleNameResolved = 0x10000,
- AllPropertiesResolved = 0x1ffff
+ FamiliesResolved = 0x20000,
+ AllPropertiesResolved = 0x3ffff
};
+ Q_ENUM(ResolveProperties)
QFont();
QFont(const QString &family, int pointSize = -1, int weight = -1, bool italic = false);
- QFont(const QFont &, QPaintDevice *pd);
- QFont(const QFont &);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ QFont(const QFont &font, QPaintDevice *pd);
+#endif
+ QFont(const QFont &font, const QPaintDevice *pd);
+ QFont(const QFont &font);
~QFont();
void swap(QFont &other)
@@ -179,6 +185,9 @@ public:
QString family() const;
void setFamily(const QString &);
+ QStringList families() const;
+ void setFamilies(const QStringList &);
+
QString styleName() const;
void setStyleName(const QString &);
@@ -252,10 +261,8 @@ public:
bool operator<(const QFont &) const;
operator QVariant() const;
bool isCopyOf(const QFont &) const;
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QFont &operator=(QFont &&other) Q_DECL_NOEXCEPT
+ inline QFont &operator=(QFont &&other) noexcept
{ qSwap(d, other.d); qSwap(resolve_mask, other.resolve_mask); return *this; }
-#endif
#if QT_DEPRECATED_SINCE(5, 3)
// needed for X11
@@ -282,8 +289,10 @@ public:
static void cacheStatistics();
QString defaultFamily() const;
- QString lastResortFamily() const;
- QString lastResortFont() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED QString lastResortFamily() const;
+ QT_DEPRECATED QString lastResortFont() const;
+#endif
QFont resolve(const QFont &) const;
inline uint resolve() const { return resolve_mask; }
@@ -326,13 +335,17 @@ private:
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QFont &);
#endif
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QFont &);
+#endif
+
QExplicitlySharedDataPointer<QFontPrivate> d;
uint resolve_mask;
};
Q_DECLARE_SHARED(QFont)
-Q_GUI_EXPORT uint qHash(const QFont &font, uint seed = 0) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QFont &font, uint seed = 0) noexcept;
inline bool QFont::bold() const
{ return weight() > Medium; }
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index c5847f532b..466e19e9cc 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -78,6 +78,7 @@ struct QFontDef
}
QString family;
+ QStringList families;
QString styleName;
QStringList fallBackFamilies;
@@ -109,6 +110,7 @@ struct QFontDef
&& styleStrategy == other.styleStrategy
&& ignorePitch == other.ignorePitch && fixedPitch == other.fixedPitch
&& family == other.family
+ && families == other.families
&& styleName == other.styleName
&& hintingPreference == other.hintingPreference
;
@@ -122,6 +124,7 @@ struct QFontDef
if (styleHint != other.styleHint) return styleHint < other.styleHint;
if (styleStrategy != other.styleStrategy) return styleStrategy < other.styleStrategy;
if (family != other.family) return family < other.family;
+ if (families != other.families) return families < other.families;
if (styleName != other.styleName)
return styleName < other.styleName;
if (hintingPreference != other.hintingPreference) return hintingPreference < other.hintingPreference;
@@ -133,20 +136,22 @@ struct QFontDef
}
};
-inline uint qHash(const QFontDef &fd, uint seed = 0) Q_DECL_NOTHROW
+inline uint qHash(const QFontDef &fd, uint seed = 0) noexcept
{
- return qHash(qRound64(fd.pixelSize*10000)) // use only 4 fractional digits
- ^ qHash(fd.weight)
- ^ qHash(fd.style)
- ^ qHash(fd.stretch)
- ^ qHash(fd.styleHint)
- ^ qHash(fd.styleStrategy)
- ^ qHash(fd.ignorePitch)
- ^ qHash(fd.fixedPitch)
- ^ qHash(fd.family, seed)
- ^ qHash(fd.styleName)
- ^ qHash(fd.hintingPreference)
- ;
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, qRound64(fd.pixelSize*10000)); // use only 4 fractional digits
+ seed = hash(seed, fd.weight);
+ seed = hash(seed, fd.style);
+ seed = hash(seed, fd.stretch);
+ seed = hash(seed, fd.styleHint);
+ seed = hash(seed, fd.styleStrategy);
+ seed = hash(seed, fd.ignorePitch);
+ seed = hash(seed, fd.fixedPitch);
+ seed = hash(seed, fd.family);
+ seed = hash(seed, fd.families);
+ seed = hash(seed, fd.styleName);
+ seed = hash(seed, fd.hintingPreference);
+ return seed;
}
class QFontEngineData
@@ -161,7 +166,7 @@ public:
QFontEngine *engines[QChar::ScriptCount];
private:
- Q_DISABLE_COPY(QFontEngineData)
+ Q_DISABLE_COPY_MOVE(QFontEngineData)
};
@@ -262,7 +267,7 @@ public:
// QFontEngine cache
struct Engine {
- Engine() : data(0), timestamp(0), hits(0) { }
+ Engine() : data(nullptr), timestamp(0), hits(0) { }
Engine(QFontEngine *d) : data(d), timestamp(0), hits(0) { }
QFontEngine *data;
@@ -270,7 +275,7 @@ public:
uint hits;
};
- typedef QMap<Key,Engine> EngineCache;
+ typedef QMultiMap<Key,Engine> EngineCache;
EngineCache engineCache;
QHash<QFontEngine *, int> engineCacheCount;
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 008ddad5cd..5350a9c5ec 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -422,7 +422,7 @@ struct FallbacksCacheKey {
QChar::Script script;
};
-inline bool operator==(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
+inline bool operator==(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) noexcept
{
return lhs.script == rhs.script &&
lhs.styleHint == rhs.styleHint &&
@@ -430,12 +430,12 @@ inline bool operator==(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rh
lhs.family == rhs.family;
}
-inline bool operator!=(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
+inline bool operator!=(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) noexcept
{
return !operator==(lhs, rhs);
}
-inline uint qHash(const FallbacksCacheKey &key, uint seed = 0) Q_DECL_NOTHROW
+inline uint qHash(const FallbacksCacheKey &key, uint seed = 0) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.family);
@@ -684,20 +684,21 @@ static QStringList familyList(const QFontDef &req)
{
// list of families to try
QStringList family_list;
- if (req.family.isEmpty())
- return family_list;
- const auto list = req.family.splitRef(QLatin1Char(','));
- const int numFamilies = list.size();
- family_list.reserve(numFamilies);
- for (int i = 0; i < numFamilies; ++i) {
- QStringRef str = list.at(i).trimmed();
- if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
- || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
- str = str.mid(1, str.length() - 2);
- family_list << str.toString();
+ family_list << req.families;
+ if (!req.family.isEmpty()) {
+ const auto list = req.family.splitRef(QLatin1Char(','));
+ const int numFamilies = list.size();
+ family_list.reserve(numFamilies);
+ for (int i = 0; i < numFamilies; ++i) {
+ QStringRef str = list.at(i).trimmed();
+ if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
+ || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
+ str = str.mid(1, str.length() - 2);
+ if (!family_list.contains(str))
+ family_list << str.toString();
+ }
}
-
// append the substitute list for each family in family_list
for (int i = 0, size = family_list.size(); i < size; ++i)
family_list += QFont::substitutes(family_list.at(i));
@@ -792,6 +793,13 @@ QString qt_resolveFontFamilyAlias(const QString &alias)
return alias;
}
+bool qt_isFontFamilyPopulated(const QString &familyName)
+{
+ QFontDatabasePrivate *d = privateDb();
+ QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::RequestFamily);
+ return f != nullptr && f->populated;
+}
+
/*!
Returns a list of alternative fonts for the specified \a family and
\a style and \a script using the \a styleHint given.
@@ -970,7 +978,7 @@ QFontEngine *loadSingleEngine(int script,
if (!engine->supportsScript(QChar::Script(script))) {
qWarning(" OpenType support missing for \"%s\", script %d",
+ qPrintable(def.family), script);
- if (engine->ref.load() == 0)
+ if (engine->ref.loadRelaxed() == 0)
delete engine;
return 0;
}
@@ -2676,9 +2684,8 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
}
QString family_name, foundry_name;
-
- parseFontName(request.family, foundry_name, family_name);
-
+ const QString requestFamily = request.families.size() > 0 ? request.families.at(0) : request.family;
+ parseFontName(requestFamily, foundry_name, family_name);
QtFontDesc desc;
QList<int> blackListed;
int index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed);
@@ -2691,8 +2698,8 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
// Don't pass empty family names to the platform font database, since it will then invoke its own matching
// and we will be out of sync with the matched font.
- if (fontDef.family.isEmpty())
- fontDef.family = desc.family->name;
+ if (fontDef.families.isEmpty() && fontDef.family.isEmpty())
+ fontDef.families = QStringList(desc.family->name);
engine = loadEngine(script, fontDef, desc.family, desc.foundry, desc.style, desc.size);
@@ -2705,13 +2712,13 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
}
if (!engine) {
- if (!request.family.isEmpty()) {
+ if (!requestFamily.isEmpty()) {
QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
if (styleHint == QFont::AnyStyle && request.fixedPitch)
styleHint = QFont::TypeWriter;
QStringList fallbacks = request.fallBackFamilies
- + fallbacksForFamily(request.family,
+ + fallbacksForFamily(requestFamily,
QFont::Style(request.style),
styleHint,
QChar::Script(script));
@@ -2729,7 +2736,7 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
index = match(multi ? QChar::Script_Common : script, def, def.family, QLatin1String(""), &desc, blackListed);
if (index >= 0) {
QFontDef loadDef = def;
- if (loadDef.family.isEmpty())
+ if (loadDef.families.isEmpty() && loadDef.family.isEmpty())
loadDef.family = desc.family->name;
engine = loadEngine(script, loadDef, desc.family, desc.foundry, desc.style, desc.size);
if (engine)
@@ -2770,7 +2777,10 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
// look for the requested font in the engine data cache
// note: fallBackFamilies are not respected in the EngineData cache key;
// join them with the primary selection family to avoid cache misses
- req.family = fallBackFamilies.join(QLatin1Char(','));
+ if (!d->request.family.isEmpty())
+ req.family = fallBackFamilies.join(QLatin1Char(','));
+ if (!d->request.families.isEmpty())
+ req.families = fallBackFamilies;
d->engineData = fontCache->findEngineData(req);
if (!d->engineData) {
@@ -2791,14 +2801,14 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
req.fallBackFamilies = fallBackFamilies;
if (!req.fallBackFamilies.isEmpty())
- req.family = req.fallBackFamilies.takeFirst();
+ req.families = QStringList(req.fallBackFamilies.takeFirst());
// list of families to try
QStringList family_list;
- if (!req.family.isEmpty()) {
+ if (!req.families.isEmpty()) {
// Add primary selection
- family_list << req.family;
+ family_list << req.families.at(0);
// add the default family
QString defaultFamily = QGuiApplication::font().family();
@@ -2812,12 +2822,12 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
for (; !fe && it != end; ++it) {
- req.family = *it;
+ req.families = QStringList(*it);
fe = QFontDatabase::findFont(req, script);
if (fe) {
- if (fe->type() == QFontEngine::Box && !req.family.isEmpty()) {
- if (fe->ref.load() == 0)
+ if (fe->type() == QFontEngine::Box && !req.families.at(0).isEmpty()) {
+ if (fe->ref.loadRelaxed() == 0)
delete fe;
fe = 0;
} else {
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index eb7e416dd1..537d4bcefd 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1022,8 +1022,8 @@ void QFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metr
Returns \c true if the font table idetified by \a tag exists in the font;
returns \c false otherwise.
- If \a buffer is NULL, stores the size of the buffer required for the font table data,
- in bytes, in \a length. If \a buffer is not NULL and the capacity
+ If \a buffer is \nullptr, stores the size of the buffer required for the font table data,
+ in bytes, in \a length. If \a buffer is not \nullptr and the capacity
of the buffer, passed in \a length, is sufficient to store the font table data,
also copies the font table data to \a buffer.
@@ -1059,15 +1059,15 @@ void QFontEngine::setGlyphCache(const void *context, QFontEngineGlyphCache *cach
Q_ASSERT(cache);
GlyphCaches &caches = m_glyphCaches[context];
- for (GlyphCaches::const_iterator it = caches.constBegin(), end = caches.constEnd(); it != end; ++it) {
- if (cache == it->cache.data())
+ for (auto & e : caches) {
+ if (cache == e.cache.data())
return;
}
// Limit the glyph caches to 4 per context. This covers all 90 degree rotations,
// and limits memory use when there is continuous or random rotation
if (caches.size() == 4)
- caches.removeLast();
+ caches.pop_back();
GlyphCacheEntry entry;
entry.cache = cache;
@@ -1081,8 +1081,8 @@ QFontEngineGlyphCache *QFontEngine::glyphCache(const void *context, GlyphFormat
if (caches == m_glyphCaches.cend())
return nullptr;
- for (GlyphCaches::const_iterator it = caches->begin(), end = caches->end(); it != end; ++it) {
- QFontEngineGlyphCache *cache = it->cache.data();
+ for (auto &e : *caches) {
+ QFontEngineGlyphCache *cache = e.cache.data();
if (format == cache->glyphFormat() && qtransform_equals_no_translate(cache->m_transform, transform))
return cache;
}
@@ -1213,7 +1213,7 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
end:
std::sort(kerning_pairs.begin(), kerning_pairs.end());
// for (int i = 0; i < kerning_pairs.count(); ++i)
-// qDebug() << 'i' << i << "left_right" << hex << kerning_pairs.at(i).left_right;
+// qDebug() << 'i' << i << "left_right" << Qt::hex << kerning_pairs.at(i).left_right;
}
@@ -1843,6 +1843,7 @@ QFontEngine *QFontEngineMulti::loadEngine(int at)
QFontDef request(fontDef);
request.styleStrategy |= QFont::NoFontMerging;
request.family = fallbackFamilyAt(at - 1);
+ request.families = QStringList(request.family);
// At this point, the main script of the text has already been considered
// when fetching the list of fallback families from the database, and the
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 708c79c2ae..8dcfd7d66c 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -54,7 +54,6 @@
#include <QtGui/private/qtguiglobal_p.h>
#include "QtCore/qatomic.h"
#include <QtCore/qvarlengtharray.h>
-#include <QtCore/QLinkedList>
#include <QtCore/qhashfunctions.h>
#include "private/qtextengine_p.h"
#include "private/qfont_p.h"
@@ -194,7 +193,7 @@ public:
virtual QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
GlyphFormat neededFormat,
const QTransform &t = QTransform(),
- QPoint *offset = 0);
+ QPoint *offset = nullptr);
virtual void unlockAlphaMapForGlyph();
virtual bool hasInternalCaching() const { return false; }
@@ -224,7 +223,7 @@ public:
virtual qreal minLeftBearing() const;
virtual qreal minRightBearing() const;
- virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = nullptr, qreal *rightBearing = nullptr);
inline bool canRender(uint ucs4) const { return glyphIndex(ucs4) != 0; }
virtual bool canRender(const QChar *str, int len) const;
@@ -234,7 +233,7 @@ public:
virtual int glyphCount() const;
virtual int glyphMargin(GlyphFormat format) { return format == Format_A32 ? 2 : 0; }
- virtual QFontEngine *cloneWithSize(qreal /*pixelSize*/) const { return 0; }
+ virtual QFontEngine *cloneWithSize(qreal /*pixelSize*/) const { return nullptr; }
virtual Qt::HANDLE handle() const;
@@ -292,33 +291,33 @@ public:
Holder() : ptr(nullptr), destroy_func(nullptr) {}
explicit Holder(void *p, qt_destroy_func_t d) : ptr(p), destroy_func(d) {}
~Holder() { if (ptr && destroy_func) destroy_func(ptr); }
- Holder(Holder &&other) Q_DECL_NOTHROW
+ Holder(Holder &&other) noexcept
: ptr(other.ptr),
destroy_func(other.destroy_func)
{
other.ptr = nullptr;
other.destroy_func = nullptr;
}
- Holder &operator=(Holder &&other) Q_DECL_NOTHROW
+ Holder &operator=(Holder &&other) noexcept
{ swap(other); return *this; }
- void swap(Holder &other) Q_DECL_NOTHROW
+ void swap(Holder &other) noexcept
{
qSwap(ptr, other.ptr);
qSwap(destroy_func, other.destroy_func);
}
- void *get() const Q_DECL_NOTHROW { return ptr; }
- void *release() Q_DECL_NOTHROW {
+ void *get() const noexcept { return ptr; }
+ void *release() noexcept {
void *result = ptr;
ptr = nullptr;
destroy_func = nullptr;
return result;
}
- void reset() Q_DECL_NOTHROW { Holder().swap(*this); }
- qt_destroy_func_t get_deleter() const Q_DECL_NOTHROW { return destroy_func; }
+ void reset() noexcept { Holder().swap(*this); }
+ qt_destroy_func_t get_deleter() const noexcept { return destroy_func; }
- bool operator!() const Q_DECL_NOTHROW { return !ptr; }
+ bool operator!() const noexcept { return !ptr; }
};
mutable Holder font_; // \ NOTE: Declared before m_glyphCaches, so font_, face_
@@ -370,7 +369,7 @@ private:
QExplicitlySharedDataPointer<QFontEngineGlyphCache> cache;
bool operator==(const GlyphCacheEntry &other) const { return cache == other.cache; }
};
- typedef QLinkedList<GlyphCacheEntry> GlyphCaches;
+ typedef std::list<GlyphCacheEntry> GlyphCaches;
mutable QHash<const void *, GlyphCaches> m_glyphCaches;
private:
@@ -390,7 +389,7 @@ inline bool operator ==(const QFontEngine::FaceId &f1, const QFontEngine::FaceId
}
inline uint qHash(const QFontEngine::FaceId &f, uint seed = 0)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(f.filename)))
+ noexcept(noexcept(qHash(f.filename)))
{
QtPrivate::QHashCombine hash;
seed = hash(seed, f.filename);
@@ -458,7 +457,7 @@ public:
virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const override;
virtual void doKerning(QGlyphLayout *, ShaperFlags) const override;
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags) override;
- virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0) override;
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = nullptr, qreal *rightBearing = nullptr) override;
virtual QFixed ascent() const override;
virtual QFixed capHeight() const override;
diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp
index 110d512d39..409176d41b 100644
--- a/src/gui/text/qfontengine_qpf2.cpp
+++ b/src/gui/text/qfontengine_qpf2.cpp
@@ -140,9 +140,9 @@ static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr)
}
#if defined(DEBUG_HEADER)
if (length == 1)
- qDebug() << "tag data" << hex << *tagPtr;
+ qDebug() << "tag data" << Qt::hex << *tagPtr;
else if (length == 4)
- qDebug() << "tag data" << hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3];
+ qDebug() << "tag data" << Qt::hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3];
#endif
}
return tagPtr + length;
@@ -367,7 +367,7 @@ bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyp
#if 0 && defined(DEBUG_FONTENGINE)
QChar c(uc);
if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c))
- qDebug() << "glyph for character" << c << '/' << hex << uc << "is" << dec << glyphs[glyph_pos].glyph;
+ qDebug() << "glyph for character" << c << '/' << Qt::hex << uc << "is" << Qt::dec << glyphs[glyph_pos].glyph;
seenGlyphs.insert(c);
#endif
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 407559ad51..c8dc8d676e 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -156,6 +156,8 @@ QFontMetrics::QFontMetrics(const QFont &font)
}
/*!
+ \since 5.13
+ \fn QFontMetrics::QFontMetrics(const QFont &font, const QPaintDevice *paintdevice)
Constructs a font metrics object for \a font and \a paintdevice.
The font metrics will be compatible with the paintdevice passed.
@@ -168,9 +170,21 @@ QFontMetrics::QFontMetrics(const QFont &font)
passed in the constructor at the time it is created, and is not
updated if the font's attributes are changed later.
*/
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \fn QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice)
+ \obsolete
+ Identical to QFontMetrics::QFontMetrics(const QFont &font, const QPaintDevice *paintdevice)
+*/
+
+
QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice)
+#else
+QFontMetrics::QFontMetrics(const QFont &font, const QPaintDevice *paintdevice)
+#endif
{
- int dpi = paintdevice ? paintdevice->logicalDpiY() : qt_defaultDpi();
+ const int dpi = paintdevice ? paintdevice->logicalDpiY() : qt_defaultDpi();
const int screen = 0;
if (font.d->dpi != dpi || font.d->screen != screen ) {
d = new QFontPrivate(*font.d);
@@ -1127,6 +1141,8 @@ QFontMetricsF::QFontMetricsF(const QFont &font)
}
/*!
+ \fn QFontMetricsF::QFontMetricsF(const QFont &font, const QPaintDevice *paintdevice)
+ \since 5.13
Constructs a font metrics object for \a font and \a paintdevice.
The font metrics will be compatible with the paintdevice passed.
@@ -1139,7 +1155,20 @@ QFontMetricsF::QFontMetricsF(const QFont &font)
passed in the constructor at the time it is created, and is not
updated if the font's attributes are changed later.
*/
+
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \fn QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice)
+ \obsolete
+ Identical to QFontMetricsF::QFontMetricsF(const QFont &font, const QPaintDevice *paintdevice)
+*/
+
+
QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice)
+#else
+QFontMetricsF::QFontMetricsF(const QFont &font, const QPaintDevice *paintdevice)
+#endif
{
int dpi = paintdevice ? paintdevice->logicalDpiY() : qt_defaultDpi();
const int screen = 0;
diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h
index b6167a1d47..02ff335e68 100644
--- a/src/gui/text/qfontmetrics.h
+++ b/src/gui/text/qfontmetrics.h
@@ -59,17 +59,27 @@ class Q_GUI_EXPORT QFontMetrics
{
public:
explicit QFontMetrics(const QFont &);
- QFontMetrics(const QFont &, QPaintDevice *pd);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ QFontMetrics(const QFont &font, QPaintDevice *pd);
+#ifndef Q_QDOC
+ // the template is necessary to make QFontMetrics(font,nullptr) and QFontMetrics(font,NULL)
+ // not ambiguous. Implementation detail that should not be documented.
+ template<char = 0>
+#endif
+ QFontMetrics(const QFont &font, const QPaintDevice *pd)
+ : QFontMetrics(font, const_cast<QPaintDevice*>(pd))
+ {}
+#else
+ QFontMetrics(const QFont &font, const QPaintDevice *pd);
+#endif
QFontMetrics(const QFontMetrics &);
~QFontMetrics();
QFontMetrics &operator=(const QFontMetrics &);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QFontMetrics &operator=(QFontMetrics &&other) Q_DECL_NOEXCEPT
+ inline QFontMetrics &operator=(QFontMetrics &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- void swap(QFontMetrics &other) Q_DECL_NOEXCEPT
+ void swap(QFontMetrics &other) noexcept
{ qSwap(d, other.d); }
int ascent() const;
@@ -92,8 +102,11 @@ public:
int rightBearing(QChar) const;
#if QT_DEPRECATED_SINCE(5, 11)
+ QT_DEPRECATED_X("Use QFontMetrics::horizontalAdvance")
int width(const QString &, int len = -1) const;
+ QT_DEPRECATED_X("Use QFontMetrics::horizontalAdvance")
int width(const QString &, int len, int flags) const;
+ QT_DEPRECATED_X("Use QFontMetrics::horizontalAdvance")
int width(QChar) const;
#endif
@@ -137,20 +150,30 @@ Q_DECLARE_SHARED(QFontMetrics)
class Q_GUI_EXPORT QFontMetricsF
{
public:
- explicit QFontMetricsF(const QFont &);
- QFontMetricsF(const QFont &, QPaintDevice *pd);
+ explicit QFontMetricsF(const QFont &font);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ QFontMetricsF(const QFont &font, QPaintDevice *pd);
+#ifndef Q_QDOC
+ // the template is necessary to make QFontMetrics(font,nullptr) and QFontMetrics(font,NULL)
+ // not ambiguous. Implementation detail that should not be documented.
+ template<char = 0>
+#endif
+ QFontMetricsF(const QFont &font, const QPaintDevice *pd)
+ : QFontMetricsF(font, const_cast<QPaintDevice*>(pd))
+ {}
+#else
+ QFontMetricsF(const QFont &font, const QPaintDevice *pd);
+#endif
QFontMetricsF(const QFontMetrics &);
QFontMetricsF(const QFontMetricsF &);
~QFontMetricsF();
QFontMetricsF &operator=(const QFontMetricsF &);
QFontMetricsF &operator=(const QFontMetrics &);
-#ifdef Q_COMPILER_RVALUE_REFS
- inline QFontMetricsF &operator=(QFontMetricsF &&other)
+ inline QFontMetricsF &operator=(QFontMetricsF &&other) noexcept
{ qSwap(d, other.d); return *this; }
-#endif
- void swap(QFontMetricsF &other) { qSwap(d, other.d); }
+ void swap(QFontMetricsF &other) noexcept { qSwap(d, other.d); }
qreal ascent() const;
qreal capHeight() const;
diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h
index 35f60ac961..1d781352f8 100644
--- a/src/gui/text/qfragmentmap_p.h
+++ b/src/gui/text/qfragmentmap_p.h
@@ -216,7 +216,7 @@ private:
template <class Fragment>
QFragmentMapData<Fragment>::QFragmentMapData()
- : fragments(0)
+ : fragments(nullptr)
{
init();
}
diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp
index bd44e11dce..3c16c3bf62 100644
--- a/src/gui/text/qglyphrun.cpp
+++ b/src/gui/text/qglyphrun.cpp
@@ -137,7 +137,7 @@ QGlyphRun::~QGlyphRun()
*/
void QGlyphRun::detach()
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
d.detach();
}
diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h
index 6182c4f749..15e315bea2 100644
--- a/src/gui/text/qglyphrun.h
+++ b/src/gui/text/qglyphrun.h
@@ -66,13 +66,11 @@ public:
QGlyphRun();
QGlyphRun(const QGlyphRun &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QGlyphRun &operator=(QGlyphRun &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QGlyphRun &operator=(QGlyphRun &&other) noexcept { swap(other); return *this; }
QGlyphRun &operator=(const QGlyphRun &other);
~QGlyphRun();
- void swap(QGlyphRun &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QGlyphRun &other) noexcept { qSwap(d, other.d); }
QRawFont rawFont() const;
void setRawFont(const QRawFont &rawFont);
diff --git a/src/gui/text/qglyphrun_p.h b/src/gui/text/qglyphrun_p.h
index 5b6bdad648..465c3c7000 100644
--- a/src/gui/text/qglyphrun_p.h
+++ b/src/gui/text/qglyphrun_p.h
@@ -65,7 +65,7 @@ class QGlyphRunPrivate: public QSharedData
{
public:
QGlyphRunPrivate()
- : flags(0)
+ : flags(nullptr)
, glyphIndexData(glyphIndexes.constData())
, glyphIndexDataSize(0)
, glyphPositionData(glyphPositions.constData())
diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp
index a911014a19..90322b24da 100644
--- a/src/gui/text/qplatformfontdatabase.cpp
+++ b/src/gui/text/qplatformfontdatabase.cpp
@@ -60,6 +60,7 @@ void qt_registerFont(const QString &familyname, const QString &stylename,
void qt_registerFontFamily(const QString &familyName);
void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
+bool qt_isFontFamilyPopulated(const QString &familyName);
/*!
Registers the pre-rendered QPF2 font contained in the given \a dataArray.
@@ -234,7 +235,7 @@ QSupportedWritingSystems::~QSupportedWritingSystems()
*/
void QSupportedWritingSystems::detach()
{
- if (d->ref.load() != 1) {
+ if (d->ref.loadRelaxed() != 1) {
QWritingSystemsPrivate *newd = new QWritingSystemsPrivate(d);
if (!d->ref.deref())
delete d;
@@ -666,6 +667,16 @@ void QPlatformFontDatabase::registerAliasToFontFamily(const QString &familyName,
}
/*!
+ Helper function that returns true if the font family has already been registered and populated.
+
+ \since 5.14
+*/
+bool QPlatformFontDatabase::isFamilyPopulated(const QString &familyName)
+{
+ return qt_isFontFamilyPopulated(familyName);
+}
+
+/*!
\class QPlatformFontDatabase
\since 5.0
\internal
diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h
index f4558129a7..38ba7f10b2 100644
--- a/src/gui/text/qplatformfontdatabase.h
+++ b/src/gui/text/qplatformfontdatabase.h
@@ -139,6 +139,8 @@ public:
static void registerFontFamily(const QString &familyName);
static void registerAliasToFontFamily(const QString &familyName, const QString &alias);
+
+ static bool isFamilyPopulated(const QString &familyName);
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index b2d8bf01af..a060448924 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -322,7 +322,7 @@ bool QRawFont::operator==(const QRawFont &other) const
\relates QRawFont
\since 5.8
*/
-uint qHash(const QRawFont &font, uint seed) Q_DECL_NOTHROW
+uint qHash(const QRawFont &font, uint seed) noexcept
{
return qHash(QRawFontPrivate::get(font)->fontEngine, seed);
}
diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h
index 470f2694e4..c6289d6c93 100644
--- a/src/gui/text/qrawfont.h
+++ b/src/gui/text/qrawfont.h
@@ -79,13 +79,11 @@ public:
qreal pixelSize,
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
QRawFont(const QRawFont &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QRawFont &operator=(QRawFont &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QRawFont &operator=(QRawFont &&other) noexcept { swap(other); return *this; }
QRawFont &operator=(const QRawFont &other);
~QRawFont();
- void swap(QRawFont &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QRawFont &other) noexcept { qSwap(d, other.d); }
bool isValid() const;
@@ -158,7 +156,7 @@ Q_DECLARE_SHARED(QRawFont)
Q_DECLARE_OPERATORS_FOR_FLAGS(QRawFont::LayoutFlags)
-Q_GUI_EXPORT uint qHash(const QRawFont &font, uint seed = 0) Q_DECL_NOTHROW;
+Q_GUI_EXPORT uint qHash(const QRawFont &font, uint seed = 0) noexcept;
inline QVector<QPointF> QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes, QRawFont::LayoutFlags layoutFlags) const
{
diff --git a/src/gui/text/qrawfont_p.h b/src/gui/text/qrawfont_p.h
index 0fc8739bfb..03259a94ed 100644
--- a/src/gui/text/qrawfont_p.h
+++ b/src/gui/text/qrawfont_p.h
@@ -67,9 +67,9 @@ class Q_GUI_EXPORT QRawFontPrivate
{
public:
QRawFontPrivate()
- : fontEngine(0)
+ : fontEngine(nullptr)
, hintingPreference(QFont::PreferDefaultHinting)
- , thread(0)
+ , thread(nullptr)
{}
QRawFontPrivate(const QRawFontPrivate &other)
@@ -78,53 +78,53 @@ public:
, thread(other.thread)
{
#ifndef QT_NO_DEBUG
- Q_ASSERT(fontEngine == 0 || thread == QThread::currentThread());
+ Q_ASSERT(fontEngine == nullptr || thread == QThread::currentThread());
#endif
- if (fontEngine != 0)
+ if (fontEngine != nullptr)
fontEngine->ref.ref();
}
~QRawFontPrivate()
{
#ifndef QT_NO_DEBUG
- Q_ASSERT(ref.load() == 0);
+ Q_ASSERT(ref.loadRelaxed() == 0);
#endif
cleanUp();
}
inline void cleanUp()
{
- setFontEngine(0);
+ setFontEngine(nullptr);
hintingPreference = QFont::PreferDefaultHinting;
}
inline bool isValid() const
{
#ifndef QT_NO_DEBUG
- Q_ASSERT(fontEngine == 0 || thread == QThread::currentThread());
+ Q_ASSERT(fontEngine == nullptr || thread == QThread::currentThread());
#endif
- return fontEngine != 0;
+ return fontEngine != nullptr;
}
inline void setFontEngine(QFontEngine *engine)
{
#ifndef QT_NO_DEBUG
- Q_ASSERT(fontEngine == 0 || thread == QThread::currentThread());
+ Q_ASSERT(fontEngine == nullptr || thread == QThread::currentThread());
#endif
if (fontEngine == engine)
return;
- if (fontEngine != 0) {
+ if (fontEngine != nullptr) {
if (!fontEngine->ref.deref())
delete fontEngine;
#ifndef QT_NO_DEBUG
- thread = 0;
+ thread = nullptr;
#endif
}
fontEngine = engine;
- if (fontEngine != 0) {
+ if (fontEngine != nullptr) {
fontEngine->ref.ref();
#ifndef QT_NO_DEBUG
thread = QThread::currentThread();
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
index dd894f4d32..490e0b6b8f 100644
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -181,7 +181,7 @@ QStaticText::QStaticText(const QStaticText &other)
*/
QStaticText::~QStaticText()
{
- Q_ASSERT(!data || data->ref.load() >= 1);
+ Q_ASSERT(!data || data->ref.loadRelaxed() >= 1);
}
/*!
@@ -189,7 +189,7 @@ QStaticText::~QStaticText()
*/
void QStaticText::detach()
{
- if (data->ref.load() != 1)
+ if (data->ref.loadRelaxed() != 1)
data.detach();
}
diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h
index ada0456b8f..e8c94a6add 100644
--- a/src/gui/text/qstatictext.h
+++ b/src/gui/text/qstatictext.h
@@ -64,13 +64,11 @@ public:
QStaticText();
explicit QStaticText(const QString &text);
QStaticText(const QStaticText &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QStaticText &operator=(QStaticText &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QStaticText &operator=(QStaticText &&other) noexcept { swap(other); return *this; }
QStaticText &operator=(const QStaticText &);
~QStaticText();
- void swap(QStaticText &other) Q_DECL_NOTHROW { qSwap(data, other.data); }
+ void swap(QStaticText &other) noexcept { qSwap(data, other.data); }
void setText(const QString &text);
QString text() const;
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
index 4ec09297c5..8d6792216d 100644
--- a/src/gui/text/qstatictext_p.h
+++ b/src/gui/text/qstatictext_p.h
@@ -80,7 +80,7 @@ class Q_GUI_EXPORT QStaticTextItem
public:
QStaticTextItem() : useBackendOptimizations(false),
userDataNeedsUpdate(0), usesRawFont(0),
- m_fontEngine(0), m_userData(0) {}
+ m_fontEngine(nullptr), m_userData(nullptr) {}
void setUserData(QStaticTextUserData *newUserData)
{
diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp
index 102a776ed3..cf584f6980 100644
--- a/src/gui/text/qsyntaxhighlighter.cpp
+++ b/src/gui/text/qsyntaxhighlighter.cpp
@@ -45,6 +45,7 @@
#include <private/qtextdocument_p.h>
#include <qtextlayout.h>
#include <qpointer.h>
+#include <qscopedvaluerollback.h>
#include <qtextobject.h>
#include <qtextcursor.h>
#include <qdebug.h>
@@ -68,14 +69,14 @@ public:
void reformatBlocks(int from, int charsRemoved, int charsAdded);
void reformatBlock(const QTextBlock &block);
- inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) {
- inReformatBlocks = true;
+ inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation)
+ {
+ QScopedValueRollback<bool> bg(inReformatBlocks, true);
cursor.beginEditBlock();
int from = cursor.position();
cursor.movePosition(operation);
reformatBlocks(from, 0, cursor.position() - from);
cursor.endEditBlock();
- inReformatBlocks = false;
}
inline void _q_delayedRehighlight() {
diff --git a/src/gui/text/qsyntaxhighlighter.h b/src/gui/text/qsyntaxhighlighter.h
index d87f89f0fd..ad0d50a4c0 100644
--- a/src/gui/text/qsyntaxhighlighter.h
+++ b/src/gui/text/qsyntaxhighlighter.h
@@ -64,7 +64,7 @@ class Q_GUI_EXPORT QSyntaxHighlighter : public QObject
public:
explicit QSyntaxHighlighter(QObject *parent);
explicit QSyntaxHighlighter(QTextDocument *parent);
- virtual ~QSyntaxHighlighter();
+ ~QSyntaxHighlighter();
void setDocument(QTextDocument *doc);
QTextDocument *document() const;
diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h
index 1a00b753ad..7cad3cc5e8 100644
--- a/src/gui/text/qtextcursor.h
+++ b/src/gui/text/qtextcursor.h
@@ -73,13 +73,11 @@ public:
explicit QTextCursor(QTextFrame *frame);
explicit QTextCursor(const QTextBlock &block);
QTextCursor(const QTextCursor &cursor);
-#ifdef Q_COMPILER_RVALUE_REFS
- QTextCursor &operator=(QTextCursor &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QTextCursor &operator=(QTextCursor &&other) noexcept { swap(other); return *this; }
QTextCursor &operator=(const QTextCursor &other);
~QTextCursor();
- void swap(QTextCursor &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QTextCursor &other) noexcept { qSwap(d, other.d); }
bool isNull() const;
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index c2020f3f86..2ec3f41f42 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -70,6 +70,12 @@
#include <private/qabstracttextdocumentlayout_p.h>
#include "qpagedpaintdevice.h"
#include "private/qpagedpaintdevice_p.h"
+#if QT_CONFIG(textmarkdownreader)
+#include <private/qtextmarkdownimporter_p.h>
+#endif
+#if QT_CONFIG(textmarkdownwriter)
+#include <private/qtextmarkdownwriter_p.h>
+#endif
#include <limits.h>
@@ -2072,6 +2078,7 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
The icon needs to be converted to one of the supported types first,
for example using QIcon::pixmap.
\value StyleSheetResource The resource contains CSS.
+ \value MarkdownResource The resource contains Markdown.
\value UserResource The first available value for user defined
resource types.
@@ -2463,9 +2470,19 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
if (format.foreground() != defaultCharFormat.foreground()
&& format.foreground().style() != Qt::NoBrush) {
- html += QLatin1String(" color:");
- html += colorValue(format.foreground().color());
- html += QLatin1Char(';');
+ QBrush brush = format.foreground();
+ if (brush.style() == Qt::TexturePattern) {
+ const bool isPixmap = qHasPixmapTexture(brush);
+ const qint64 cacheKey = isPixmap ? brush.texture().cacheKey() : brush.textureImage().cacheKey();
+
+ html += QLatin1String(" -qt-fg-texture-cachekey:");
+ html += QString::number(cacheKey);
+ html += QLatin1String(";");
+ } else {
+ html += QLatin1String(" color:");
+ html += colorValue(brush.color());
+ html += QLatin1Char(';');
+ }
attributesEmitted = true;
}
@@ -2665,10 +2682,10 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
bool closeAnchor = false;
if (format.isAnchor()) {
- const QString name = format.anchorName();
- if (!name.isEmpty()) {
+ const auto names = format.anchorNames();
+ if (!names.isEmpty()) {
html += QLatin1String("<a name=\"");
- html += name.toHtmlEscaped();
+ html += names.constFirst().toHtmlEscaped();
html += QLatin1String("\"></a>");
}
const QString href = format.anchorHref();
@@ -2704,6 +2721,12 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
if (imgFmt.hasProperty(QTextFormat::ImageName))
emitAttribute("src", imgFmt.name());
+ if (imgFmt.hasProperty(QTextFormat::ImageAltText))
+ emitAttribute("alt", imgFmt.stringProperty(QTextFormat::ImageAltText));
+
+ if (imgFmt.hasProperty(QTextFormat::ImageTitle))
+ emitAttribute("title", imgFmt.stringProperty(QTextFormat::ImageTitle));
+
if (imgFmt.hasProperty(QTextFormat::ImageWidth))
emitAttribute("width", QString::number(imgFmt.width()));
@@ -3288,6 +3311,62 @@ QString QTextDocument::toHtml(const QByteArray &encoding) const
#endif // QT_NO_TEXTHTMLPARSER
/*!
+ \since 5.14
+ Returns a string containing a Markdown representation of the document with
+ the given \a features, or an empty string if writing fails for any reason.
+
+ \sa setMarkdown
+*/
+#if QT_CONFIG(textmarkdownwriter)
+QString QTextDocument::toMarkdown(QTextDocument::MarkdownFeatures features) const
+{
+ QString ret;
+ QTextStream s(&ret);
+ QTextMarkdownWriter w(s, features);
+ if (w.writeAll(this))
+ return ret;
+ return QString();
+}
+#endif
+
+/*!
+ \since 5.14
+ Replaces the entire contents of the document with the given
+ Markdown-formatted text in the \a markdown string, with the given
+ \a features supported. By default, all supported GitHub-style
+ Markdown features are included; pass \c MarkdownDialectCommonMark
+ for a more basic parse.
+
+ The Markdown formatting is respected as much as possible; for example,
+ "*bold* text" will produce text where the first word has a font weight that
+ gives it an emphasized appearance.
+
+ Parsing of HTML included in the \a markdown string is handled in the same
+ way as in \l setHtml; however, Markdown formatting inside HTML blocks is
+ not supported.
+
+ Some features of the parser can be enabled or disabled via the \a features
+ argument:
+
+ \value MarkdownNoHTML
+ Any HTML tags in the Markdown text will be discarded
+ \value MarkdownDialectCommonMark
+ The parser supports only the features standardized by CommonMark
+ \value MarkdownDialectGitHub
+ The parser supports the GitHub dialect
+
+ The default is \c MarkdownDialectGitHub.
+
+ The undo/redo history is reset when this function is called.
+*/
+#if QT_CONFIG(textmarkdownreader)
+void QTextDocument::setMarkdown(const QString &markdown, QTextDocument::MarkdownFeatures features)
+{
+ QTextMarkdownImporter(static_cast<QTextMarkdownImporter::Features>(int(features))).import(this, markdown);
+}
+#endif
+
+/*!
Returns a vector of text formats for all the formats used in the document.
*/
QVector<QTextFormat> QTextDocument::allFormats() const
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index c9b22e053b..2fadc40cd2 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -151,6 +151,25 @@ public:
void setHtml(const QString &html);
#endif
+#if QT_CONFIG(textmarkdownwriter) || QT_CONFIG(textmarkdownreader)
+ // Must be in sync with QTextMarkdownImporter::Features, should be in sync with #define MD_FLAG_* in md4c
+ enum MarkdownFeature {
+ MarkdownNoHTML = 0x0020 | 0x0040,
+ MarkdownDialectCommonMark = 0,
+ MarkdownDialectGitHub = 0x0004 | 0x0008 | 0x0400 | 0x0100 | 0x0200 | 0x0800
+ };
+ Q_DECLARE_FLAGS(MarkdownFeatures, MarkdownFeature)
+ Q_FLAG(MarkdownFeatures)
+#endif
+
+#if QT_CONFIG(textmarkdownwriter)
+ QString toMarkdown(MarkdownFeatures features = MarkdownDialectGitHub) const;
+#endif
+
+#if QT_CONFIG(textmarkdownreader)
+ void setMarkdown(const QString &markdown, MarkdownFeatures features = MarkdownDialectGitHub);
+#endif
+
QString toRawText() const;
QString toPlainText() const;
void setPlainText(const QString &text);
@@ -206,12 +225,15 @@ public:
void print(QPagedPaintDevice *printer) const;
enum ResourceType {
+ UnknownResource = 0,
HtmlResource = 1,
ImageResource = 2,
StyleSheetResource = 3,
+ MarkdownResource = 4,
UserResource = 100
};
+ Q_ENUM(ResourceType)
QVariant resource(int type, const QUrl &name) const;
void addResource(int type, const QUrl &name, const QVariant &resource);
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 66e038122c..0e3c8d0e83 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -40,6 +40,7 @@
#include <private/qtools_p.h>
#include <qdebug.h>
+#include <qscopedvaluerollback.h>
#include "qtextdocument_p.h"
#include "qtextdocument.h"
#include <qtextformat.h>
@@ -274,9 +275,10 @@ void QTextDocumentPrivate::clear()
rtFrame = 0;
init();
cursors = oldCursors;
- inContentsChange = true;
- q->contentsChange(0, len, 0);
- inContentsChange = false;
+ {
+ QScopedValueRollback<bool> bg(inContentsChange, true);
+ emit q->contentsChange(0, len, 0);
+ }
if (lout)
lout->documentChanged(0, len, 0);
} QT_CATCH(...) {
@@ -309,9 +311,10 @@ void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)
it->free();
emit q->documentLayoutChanged();
- inContentsChange = true;
- emit q->contentsChange(0, 0, length());
- inContentsChange = false;
+ {
+ QScopedValueRollback<bool> bg(inContentsChange, true);
+ emit q->contentsChange(0, 0, length());
+ }
if (lout)
lout->documentChanged(0, 0, length());
}
@@ -1213,9 +1216,8 @@ void QTextDocumentPrivate::finishEdit()
if (lout && docChangeFrom >= 0) {
if (!inContentsChange) {
- inContentsChange = true;
+ QScopedValueRollback<bool> bg(inContentsChange, true);
emit q->contentsChange(docChangeFrom, docChangeOldLength, docChangeLength);
- inContentsChange = false;
}
lout->documentChanged(docChangeFrom, docChangeOldLength, docChangeLength);
}
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index cad9131fbf..df00fb7d84 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -101,10 +101,10 @@ class QTextBlockData : public QFragment<3>
{
public:
inline void initialize()
- { layout = 0; userData = 0; userState = -1; revision = 0; hidden = 0; }
+ { layout = nullptr; userData = nullptr; userState = -1; revision = 0; hidden = 0; }
void invalidate() const;
inline void free()
- { delete layout; layout = 0; delete userData; userData = 0; }
+ { delete layout; layout = nullptr; delete userData; userData = nullptr; }
mutable int format;
// ##### probably store a QTextEngine * here!
@@ -339,6 +339,7 @@ private:
int lastBlockCount;
public:
+ bool inContentsChange;
QTextOption defaultTextOption;
Qt::CursorMoveStyle defaultCursorMoveStyle;
#ifndef QT_NO_CSSPARSER
@@ -346,7 +347,6 @@ public:
#endif
int maximumBlockCount;
uint needsEnsureMaximumBlockCount : 1;
- uint inContentsChange : 1;
uint blockCursorAdjustment : 1;
QSizeF pageSize;
QString title;
@@ -357,6 +357,7 @@ public:
void mergeCachedResources(const QTextDocumentPrivate *priv);
+ friend struct QTextHtmlParserNode;
friend class QTextHtmlExporter;
friend class QTextCursor;
};
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index 6b3604afb5..1905d9a1b1 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -542,8 +542,10 @@ void QTextHtmlImporter::import()
}
}
- if (currentNode->charFormat.isAnchor() && !currentNode->charFormat.anchorName().isEmpty()) {
- namedAnchors.append(currentNode->charFormat.anchorName());
+ if (currentNode->charFormat.isAnchor()) {
+ const auto names = currentNode->charFormat.anchorNames();
+ if (!names.isEmpty())
+ namedAnchors.append(names.constFirst());
}
if (appendNodeText())
@@ -713,6 +715,10 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes()
case Html_img: {
QTextImageFormat fmt;
fmt.setName(currentNode->imageName);
+ if (!currentNode->text.isEmpty())
+ fmt.setProperty(QTextFormat::ImageTitle, currentNode->text);
+ if (!currentNode->imageAlt.isEmpty())
+ fmt.setProperty(QTextFormat::ImageAltText, currentNode->imageAlt);
fmt.merge(currentNode->charFormat);
diff --git a/src/gui/text/qtextdocumentfragment_p.h b/src/gui/text/qtextdocumentfragment_p.h
index 02a6a429fa..67b0c2c600 100644
--- a/src/gui/text/qtextdocumentfragment_p.h
+++ b/src/gui/text/qtextdocumentfragment_p.h
@@ -109,7 +109,7 @@ public:
uint importedFromPlainText : 1;
private:
- Q_DISABLE_COPY(QTextDocumentFragmentPrivate)
+ Q_DISABLE_COPY_MOVE(QTextDocumentFragmentPrivate)
};
#ifndef QT_NO_TEXTHTMLPARSER
@@ -125,7 +125,7 @@ public:
QTextHtmlImporter(QTextDocument *_doc, const QString &html,
ImportMode mode,
- const QTextDocument *resourceProvider = 0);
+ const QTextDocument *resourceProvider = nullptr);
void import();
@@ -163,7 +163,7 @@ private:
#endif
struct TableCellIterator
{
- inline TableCellIterator(QTextTable *t = 0) : table(t), row(0), column(0) {}
+ inline TableCellIterator(QTextTable *t = nullptr) : table(t), row(0), column(0) {}
inline TableCellIterator &operator++() {
if (atEnd())
@@ -182,7 +182,7 @@ private:
return *this;
}
- inline bool atEnd() const { return table == 0 || row >= table->rows(); }
+ inline bool atEnd() const { return table == nullptr || row >= table->rows(); }
QTextTableCell cell() const { return table->cellAt(row, column); }
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index bed0a2c450..a1b21b111b 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -931,7 +931,10 @@ void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *pain
Q_ASSERT(!fd->sizeDirty);
Q_ASSERT(!fd->layoutDirty);
- const QPointF off = offset + fd->position.toPointF();
+ // floor the offset to avoid painting artefacts when drawing adjacent borders
+ // we later also round table cell heights and widths
+ const QPointF off = QPointF(QPointF(offset + fd->position.toPointF()).toPoint());
+
if (context.clip.isValid()
&& (off.y() > context.clip.bottom() || off.y() + fd->size.height.toReal() < context.clip.top()
|| off.x() > context.clip.right() || off.x() + fd->size.width.toReal() < context.clip.left()))
@@ -970,8 +973,14 @@ void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *pain
if (pageHeight <= 0)
pageHeight = QFIXED_MAX;
- const int tableStartPage = (td->position.y / pageHeight).truncate();
- const int tableEndPage = ((td->position.y + td->size.height) / pageHeight).truncate();
+ QFixed absYPos = td->position.y;
+ QTextFrame *parentFrame = table->parentFrame();
+ while (parentFrame) {
+ absYPos += data(parentFrame)->position.y;
+ parentFrame = parentFrame->parentFrame();
+ }
+ const int tableStartPage = (absYPos / pageHeight).truncate();
+ const int tableEndPage = ((absYPos + td->size.height) / pageHeight).truncate();
qreal border = td->border.toReal();
drawFrameDecoration(painter, frame, fd, context.clip, frameRect);
@@ -1436,6 +1445,21 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
QBrush brush = context.palette.brush(QPalette::Text);
+ bool marker = bl.blockFormat().marker() != QTextBlockFormat::NoMarker;
+ if (marker) {
+ int adj = fontMetrics.lineSpacing() / 6;
+ r.adjust(-adj, 0, -adj, 0);
+ if (bl.blockFormat().marker() == QTextBlockFormat::Checked) {
+ // ### Qt6: render with QStyle / PE_IndicatorCheckBox. We don't currently
+ // have access to that here, because it would be a widget dependency.
+ painter->setPen(QPen(painter->pen().color(), 2));
+ painter->drawLine(r.topLeft(), r.bottomRight());
+ painter->drawLine(r.topRight(), r.bottomLeft());
+ painter->setPen(QPen(painter->pen().color(), 0));
+ }
+ painter->drawRect(r.adjusted(-adj, -adj, adj, adj));
+ }
+
switch (style) {
case QTextListFormat::ListDecimal:
case QTextListFormat::ListLowerAlpha:
@@ -1456,16 +1480,21 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
break;
}
case QTextListFormat::ListSquare:
- painter->fillRect(r, brush);
+ if (!marker)
+ painter->fillRect(r, brush);
break;
case QTextListFormat::ListCircle:
- painter->setPen(QPen(brush, 0));
- painter->drawEllipse(r.translated(0.5, 0.5)); // pixel align for sharper rendering
+ if (!marker) {
+ painter->setPen(QPen(brush, 0));
+ painter->drawEllipse(r.translated(0.5, 0.5)); // pixel align for sharper rendering
+ }
break;
case QTextListFormat::ListDisc:
- painter->setBrush(brush);
- painter->setPen(Qt::NoPen);
- painter->drawEllipse(r);
+ if (!marker) {
+ painter->setBrush(brush);
+ painter->setPen(Qt::NoPen);
+ painter->drawEllipse(r);
+ }
break;
case QTextListFormat::ListStyleUndefined:
break;
@@ -1591,7 +1620,7 @@ QRectF QTextDocumentLayoutPrivate::layoutTable(QTextTable *table, int layoutFrom
for (int i = 0; i < children.count(); ++i) {
QTextFrame *frame = children.at(i);
QTextTableCell cell = table->cellAt(frame->firstPosition());
- td->childFrameMap.insertMulti(cell.row() + cell.column() * rows, frame);
+ td->childFrameMap.insert(cell.row() + cell.column() * rows, frame);
}
}
@@ -1661,7 +1690,8 @@ recalc_minmax_widths:
for (int n = 0; n < cspan; ++n) {
const int col = i + n;
QFixed w = widthToDistribute / (cspan - n);
- td->minWidths[col] = qMax(td->minWidths.at(col), w);
+ // ceil to avoid going below minWidth when rounding all column widths later
+ td->minWidths[col] = qMax(td->minWidths.at(col), w).ceil();
widthToDistribute -= td->minWidths.at(col);
if (widthToDistribute <= 0)
break;
@@ -1767,6 +1797,18 @@ recalc_minmax_widths:
}
}
+ // in order to get a correct border rendering we must ensure that the distance between
+ // two cells is exactly 2 * td->border pixel. we do this by rounding the calculated width
+ // values here.
+ // to minimize the total rounding error we propagate the rounding error for each width
+ // to its successor.
+ QFixed error = 0;
+ for (int i = 0; i < columns; ++i) {
+ QFixed orig = td->widths[i];
+ td->widths[i] = (td->widths[i] - error).round();
+ error = td->widths[i] - orig;
+ }
+
td->columnPositions.resize(columns);
td->columnPositions[0] = leftMargin /*includes table border*/ + cellSpacing + td->border;
@@ -1867,7 +1909,7 @@ relayout:
if (cellRow != r) {
// the last row gets all the remaining space
if (cellRow + rspan - 1 == r)
- td->heights[r] = qMax(td->heights.at(r), heightToDistribute.at(c) - dropDistance);
+ td->heights[r] = qMax(td->heights.at(r), heightToDistribute.at(c) - dropDistance).round();
continue;
}
}
@@ -1888,7 +1930,7 @@ relayout:
td, absoluteTableY,
/*withPageBreaks =*/true);
- const QFixed height = layoutStruct.y + bottomPadding + topPadding;
+ const QFixed height = (layoutStruct.y + bottomPadding + topPadding).round();
if (rspan > 1)
heightToDistribute[c] = height + dropDistance;
diff --git a/src/gui/text/qtextdocumentwriter.cpp b/src/gui/text/qtextdocumentwriter.cpp
index 5ea04fe9e9..193d2c0dd3 100644
--- a/src/gui/text/qtextdocumentwriter.cpp
+++ b/src/gui/text/qtextdocumentwriter.cpp
@@ -51,6 +51,9 @@
#include "qtextdocumentfragment_p.h"
#include "qtextodfwriter_p.h"
+#if QT_CONFIG(textmarkdownwriter)
+#include "qtextmarkdownwriter_p.h"
+#endif
#include <algorithm>
@@ -206,8 +209,8 @@ void QTextDocumentWriter::setDevice (QIODevice *device)
}
/*!
- Returns the device currently assigned, or 0 if no device has been
- assigned.
+ Returns the device currently assigned, or \nullptr if no device
+ has been assigned.
*/
QIODevice *QTextDocumentWriter::device () const
{
@@ -267,10 +270,22 @@ bool QTextDocumentWriter::write(const QTextDocument *document)
}
#endif // QT_NO_TEXTODFWRITER
+#if QT_CONFIG(textmarkdownwriter)
+ if (format == "md" || format == "mkd" || format == "markdown") {
+ if (!d->device->isWritable() && !d->device->open(QIODevice::WriteOnly)) {
+ qWarning("QTextDocumentWriter::write: the device can not be opened for writing");
+ return false;
+ }
+ QTextStream s(d->device);
+ QTextMarkdownWriter writer(s, QTextDocument::MarkdownDialectGitHub);
+ return writer.writeAll(document);
+ }
+#endif // textmarkdownwriter
+
#ifndef QT_NO_TEXTHTMLPARSER
if (format == "html" || format == "htm") {
if (!d->device->isWritable() && ! d->device->open(QIODevice::WriteOnly)) {
- qWarning("QTextDocumentWriter::write: the device can not be opened for writing");
+ qWarning("QTextDocumentWriter::write: the device cannot be opened for writing");
return false;
}
QTextStream ts(d->device);
@@ -284,7 +299,7 @@ bool QTextDocumentWriter::write(const QTextDocument *document)
#endif
if (format == "txt" || format == "plaintext") {
if (!d->device->isWritable() && ! d->device->open(QIODevice::WriteOnly)) {
- qWarning("QTextDocumentWriter::write: the device can not be opened for writing");
+ qWarning("QTextDocumentWriter::write: the device cannot be opened for writing");
return false;
}
QTextStream ts(d->device);
@@ -348,6 +363,7 @@ QTextCodec *QTextDocumentWriter::codec() const
\header \li Format \li Description
\row \li plaintext \li Plain text
\row \li HTML \li HyperText Markup Language
+ \row \li markdown \li Markdown (CommonMark or GitHub dialects)
\row \li ODF \li OpenDocument Format
\endtable
@@ -364,6 +380,9 @@ QList<QByteArray> QTextDocumentWriter::supportedDocumentFormats()
#ifndef QT_NO_TEXTODFWRITER
answer << "ODF";
#endif // QT_NO_TEXTODFWRITER
+#if QT_CONFIG(textmarkdownwriter)
+ answer << "markdown";
+#endif
std::sort(answer.begin(), answer.end());
return answer;
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 2da13289bf..c267ade0c2 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -990,7 +990,7 @@ struct QBidiAlgorithm {
BIDI_DEBUG() << "before implicit level processing:";
IsolatedRunSequenceIterator it(runs, i);
while (!it.atEnd()) {
- BIDI_DEBUG() << " " << *it << hex << text[*it].unicode() << analysis[*it].bidiDirection;
+ BIDI_DEBUG() << " " << *it << Qt::hex << text[*it].unicode() << analysis[*it].bidiDirection;
++it;
}
}
@@ -1003,7 +1003,7 @@ struct QBidiAlgorithm {
BIDI_DEBUG() << "after W4/W5";
IsolatedRunSequenceIterator it(runs, i);
while (!it.atEnd()) {
- BIDI_DEBUG() << " " << *it << hex << text[*it].unicode() << analysis[*it].bidiDirection;
+ BIDI_DEBUG() << " " << *it << Qt::hex << text[*it].unicode() << analysis[*it].bidiDirection;
++it;
}
}
@@ -1089,7 +1089,7 @@ struct QBidiAlgorithm {
if (BidiDebugEnabled) {
BIDI_DEBUG() << ">>>> start bidi, text length" << length;
for (int i = 0; i < length; ++i)
- BIDI_DEBUG() << hex << " (" << i << ")" << text[i].unicode() << text[i].direction();
+ BIDI_DEBUG() << Qt::hex << " (" << i << ")" << text[i].unicode() << text[i].direction();
}
{
@@ -1158,7 +1158,7 @@ struct QBidiAlgorithm {
if (BidiDebugEnabled) {
BIDI_DEBUG() << "final resolved levels:";
for (int i = 0; i < length; ++i)
- BIDI_DEBUG() << " " << i << hex << text[i].unicode() << dec << (int)analysis[i].bidiLevel;
+ BIDI_DEBUG() << " " << i << Qt::hex << text[i].unicode() << Qt::dec << (int)analysis[i].bidiLevel;
}
return true;
@@ -1969,7 +1969,9 @@ const QCharAttributes *QTextEngine::attributes() const
QUnicodeTools::initCharAttributes(reinterpret_cast<const ushort *>(layoutData->string.constData()),
layoutData->string.length(),
scriptItems.data(), scriptItems.size(),
- (QCharAttributes *)layoutData->memory);
+ (QCharAttributes *)layoutData->memory,
+ QUnicodeTools::CharAttributeOptions(QUnicodeTools::DefaultOptionsCompat
+ | QUnicodeTools::HangulLineBreakTailoring));
layoutData->haveCharAttributes = true;
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index e9187ea605..fddda7f2f8 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -304,8 +304,8 @@ class QTextItemInt : public QTextItem
{
public:
inline QTextItemInt()
- : justified(false), underlineStyle(QTextCharFormat::NoUnderline), num_chars(0), chars(0),
- logClusters(0), f(0), fontEngine(0)
+ : justified(false), underlineStyle(QTextCharFormat::NoUnderline), num_chars(0), chars(nullptr),
+ logClusters(nullptr), f(nullptr), fontEngine(nullptr)
{}
QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat());
QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars, int numChars, QFontEngine *fe,
@@ -335,7 +335,7 @@ public:
struct QScriptItem
{
- Q_DECL_CONSTEXPR QScriptItem(int p, QScriptAnalysis a) Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR QScriptItem(int p, QScriptAnalysis a) noexcept
: position(p), analysis(a),
num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1),
glyph_data_offset(0) {}
@@ -348,7 +348,7 @@ struct QScriptItem
QFixed leading;
QFixed width;
int glyph_data_offset;
- Q_DECL_CONSTEXPR QFixed height() const Q_DECL_NOTHROW { return ascent + descent; }
+ Q_DECL_CONSTEXPR QFixed height() const noexcept { return ascent + descent; }
private:
friend class QVector<QScriptItem>;
QScriptItem() {}; // for QVector, don't use
@@ -484,7 +484,7 @@ public:
return end - si->position;
}
- QFontEngine *fontEngine(const QScriptItem &si, QFixed *ascent = 0, QFixed *descent = 0, QFixed *leading = 0) const;
+ QFontEngine *fontEngine(const QScriptItem &si, QFixed *ascent = nullptr, QFixed *descent = nullptr, QFixed *leading = nullptr) const;
QFont font(const QScriptItem &si) const;
inline QFont font() const { return fnt; }
@@ -530,7 +530,7 @@ public:
inline QTextFormatCollection *formatCollection() const {
if (block.docHandle())
return block.docHandle()->formatCollection();
- return specialData ? specialData->formatCollection.data() : 0;
+ return specialData ? specialData->formatCollection.data() : nullptr;
}
QTextCharFormat format(const QScriptItem *si) const;
inline QAbstractTextDocumentLayout *docLayout() const {
@@ -553,8 +553,8 @@ private:
mutable int prevPosition;
mutable int prevLength;
inline void reset() {
- prevFontEngine = 0;
- prevScaledFontEngine = 0;
+ prevFontEngine = nullptr;
+ prevScaledFontEngine = nullptr;
prevScript = -1;
prevPosition = -1;
prevLength = -1;
@@ -684,7 +684,7 @@ Q_DECLARE_TYPEINFO(QTextEngine::ItemDecoration, Q_MOVABLE_TYPE);
struct QTextLineItemIterator
{
QTextLineItemIterator(QTextEngine *eng, int lineNum, const QPointF &pos = QPointF(),
- const QTextLayout::FormatRange *_selection = 0);
+ const QTextLayout::FormatRange *_selection = nullptr);
inline bool atEnd() const { return logicalItem >= nItems - 1; }
inline bool atBeginning() const { return logicalItem <= 0; }
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 919cdf3ff1..090c6cc4ce 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -361,6 +361,12 @@ void QTextFormatPrivate::recalcFont() const
case QTextFormat::FontFamily:
f.setFamily(props.at(i).value.toString());
break;
+ case QTextFormat::FontFamilies:
+ f.setFamilies(props.at(i).value.toStringList());
+ break;
+ case QTextFormat::FontStyleName:
+ f.setStyleName(props.at(i).value.toString());
+ break;
case QTextFormat::FontPointSize:
f.setPointSizeF(props.at(i).value.toReal());
break;
@@ -558,10 +564,24 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value BlockTrailingHorizontalRulerWidth The width of a horizontal ruler element.
\value HeadingLevel The level of a heading, for example 1 corresponds to an HTML H1 tag; otherwise 0.
This enum value has been added in Qt 5.12.
+ \value BlockCodeFence The character that was used in the "fences" around a Markdown code block.
+ If the code block was indented rather than fenced, the block should not have this property.
+ This enum value has been added in Qt 5.14.
+
+ \value BlockQuoteLevel The depth of nested quoting on this block: 1 means the block is a top-level block quote.
+ Blocks that are not block quotes should not have this property.
+ This enum value has been added in Qt 5.14.
+ \value BlockCodeLanguage The programming language in a preformatted or code block.
+ Blocks that do not contain code should not have this property.
+ This enum value has been added in Qt 5.14.
+ \value BlockMarker The \l{QTextBlockFormat::MarkerType}{type of adornment} to be shown alongside the block.
+ This enum value has been added in Qt 5.14.
Character properties
\value FontFamily
+ \value FontFamilies
+ \value FontStyleName
\value FontPointSize
\value FontPixelSize
\value FontSizeAdjustment Specifies the change in size given to the fontsize already set using
@@ -642,7 +662,13 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
Image properties
- \value ImageName
+ \value ImageName The filename or source of the image.
+ \value ImageTitle The title attribute of an HTML image tag, or
+ the quoted string that comes after the URL in a Markdown image link.
+ This enum value has been added in Qt 5.14.
+ \value ImageAltText The alt attribute of an HTML image tag, or
+ the image description in a Markdown image link.
+ This enum value has been added in Qt 5.14.
\value ImageWidth
\value ImageHeight
\value ImageQuality
@@ -1391,6 +1417,41 @@ QTextCharFormat::QTextCharFormat(const QTextFormat &fmt)
\sa font()
*/
+/*!
+ \fn void QTextCharFormat::setFontFamilies(const QStringList &families)
+ \since 5.13
+
+ Sets the text format's font \a families.
+
+ \sa setFont()
+*/
+
+/*!
+ \fn QStringList QTextCharFormat::fontFamilies() const
+ \since 5.13
+
+ Returns the text format's font families.
+
+ \sa font()
+*/
+
+/*!
+ \fn void QTextCharFormat::setFontStyleName(const QString &styleName)
+ \since 5.13
+
+ Sets the text format's font \a styleName.
+
+ \sa setFont(), QFont::setStyleName()
+*/
+
+/*!
+ \fn QStringList QTextCharFormat::fontStyleName() const
+ \since 5.13
+
+ Returns the text format's font style name.
+
+ \sa font(), QFont::styleName()
+*/
/*!
\fn void QTextCharFormat::setFontPointSize(qreal size)
@@ -1744,6 +1805,7 @@ void QTextCharFormat::setUnderlineStyle(UnderlineStyle style)
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\fn void QTextCharFormat::setAnchorName(const QString &name)
\obsolete
@@ -1754,6 +1816,7 @@ void QTextCharFormat::setUnderlineStyle(UnderlineStyle style)
hyperlink, the destination must be set with setAnchorHref() and
the anchor must be enabled with setAnchor().
*/
+#endif
/*!
\fn void QTextCharFormat::setAnchorNames(const QStringList &names)
@@ -1764,6 +1827,7 @@ void QTextCharFormat::setUnderlineStyle(UnderlineStyle style)
the anchor must be enabled with setAnchor().
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\fn QString QTextCharFormat::anchorName() const
\obsolete
@@ -1783,6 +1847,7 @@ QString QTextCharFormat::anchorName() const
return QString();
return prop.toString();
}
+#endif
/*!
\fn QStringList QTextCharFormat::anchorNames() const
@@ -1920,6 +1985,11 @@ void QTextCharFormat::setFont(const QFont &font, FontPropertiesInheritanceBehavi
if (mask & QFont::FamilyResolved)
setFontFamily(font.family());
+ if (mask & QFont::FamiliesResolved)
+ setFontFamilies(font.families());
+ if (mask & QFont::StyleNameResolved)
+ setFontStyleName(font.styleName());
+
if (mask & QFont::SizeResolved) {
const qreal pointSize = font.pointSizeF();
if (pointSize > 0) {
@@ -2277,6 +2347,50 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
/*!
+ \fn void QTextBlockFormat::setMarker(MarkerType marker)
+ \since 5.14
+
+ Sets the type of adornment that should be rendered alongside the paragraph to \a marker.
+ For example, a list item can be adorned with a checkbox, either checked
+ or unchecked, as a replacement for its bullet. The default is \c NoMarker.
+
+ \sa marker()
+*/
+
+
+/*!
+ \fn MarkerType QTextBlockFormat::marker() const
+ \since 5.14
+
+ Returns the paragraph's marker if one has been set, or \c NoMarker if not.
+
+ \sa setMarker()
+*/
+
+
+/*!
+ \since 5.14
+ \enum QTextBlockFormat::MarkerType
+
+ This enum describes the types of markers a list item can have.
+ If a list item (a paragraph for which \l QTextBlock::textList() returns the list)
+ has a marker, it is rendered instead of the normal bullet.
+ In this way, checkable list items can be mixed with plain list items in the
+ same list, overriding the type of bullet specified by the
+ \l QTextListFormat::style() for the entire list.
+
+ \value NoMarker This is the default: the list item's bullet will be shown.
+ \value Unchecked Instead of the list item's bullet, an unchecked checkbox will be shown.
+ \value Checked Instead of the list item's bullet, a checked checkbox will be shown.
+
+ In the future, this may be extended to specify other types of paragraph
+ decorations.
+
+ \sa QTextListFormat::style()
+*/
+
+
+/*!
\fn void QTextBlockFormat::setLineHeight(qreal height, int heightType)
\since 4.8
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index a8e573d5a4..a91461dcae 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -176,6 +176,10 @@ public:
BlockNonBreakableLines = 0x1050,
BlockTrailingHorizontalRulerWidth = 0x1060,
HeadingLevel = 0x1070,
+ BlockQuoteLevel = 0x1080,
+ BlockCodeLanguage = 0x1090,
+ BlockCodeFence = 0x1091,
+ BlockMarker = 0x10A0,
// character properties
FirstFontProperty = 0x1FE0,
@@ -188,6 +192,8 @@ public:
FontStyleStrategy = 0x1FE4,
FontKerning = 0x1FE5,
FontHintingPreference = 0x1FE6,
+ FontFamilies = 0x1FE7,
+ FontStyleName = 0x1FE8,
FontFamily = 0x2000,
FontPointSize = 0x2001,
FontSizeAdjustment = 0x2002,
@@ -248,6 +254,8 @@ public:
// image properties
ImageName = 0x5000,
+ ImageTitle = 0x5001,
+ ImageAltText = 0x5002,
ImageWidth = 0x5010,
ImageHeight = 0x5011,
ImageQuality = 0x5014,
@@ -428,6 +436,16 @@ public:
inline QString fontFamily() const
{ return stringProperty(FontFamily); }
+ inline void setFontFamilies(const QStringList &families)
+ { setProperty(FontFamilies, QVariant(families)); }
+ inline QVariant fontFamilies() const
+ { return property(FontFamilies); }
+
+ inline void setFontStyleName(const QString &styleName)
+ { setProperty(FontStyleName, styleName); }
+ inline QVariant fontStyleName() const
+ { return property(FontStyleName); }
+
inline void setFontPointSize(qreal size)
{ setProperty(FontPointSize, size); }
inline qreal fontPointSize() const
@@ -540,9 +558,13 @@ public:
inline QString anchorHref() const
{ return stringProperty(AnchorHref); }
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use setAnchorNames() instead")
inline void setAnchorName(const QString &name)
{ setAnchorNames(QStringList(name)); }
+ QT_DEPRECATED_X("Use anchorNames() instead")
QString anchorName() const;
+#endif
inline void setAnchorNames(const QStringList &names)
{ setProperty(AnchorName, names); }
@@ -589,6 +611,12 @@ public:
LineDistanceHeight = 4
};
+ enum MarkerType {
+ NoMarker = 0,
+ Unchecked = 1,
+ Checked = 2
+ };
+
QTextBlockFormat();
bool isValid() const { return isBlockFormat(); }
@@ -652,6 +680,11 @@ public:
void setTabPositions(const QList<QTextOption::Tab> &tabs);
QList<QTextOption::Tab> tabPositions() const;
+ inline void setMarker(MarkerType marker)
+ { setProperty(BlockMarker, int(marker)); }
+ inline MarkerType marker() const
+ { return MarkerType(intProperty(BlockMarker)); }
+
protected:
explicit QTextBlockFormat(const QTextFormat &fmt);
friend class QTextFormat;
diff --git a/src/gui/text/qtextformat_p.h b/src/gui/text/qtextformat_p.h
index 3557c17a97..001a243e84 100644
--- a/src/gui/text/qtextformat_p.h
+++ b/src/gui/text/qtextformat_p.h
@@ -104,7 +104,7 @@ public:
private:
QFont defaultFnt;
- Q_DISABLE_COPY(QTextFormatCollection)
+ Q_DISABLE_COPY_MOVE(QTextFormatCollection)
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 5169c0325a..0b1a23f399 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -861,7 +861,8 @@ QString QTextHtmlParser::parseWord()
++pos;
while (pos < len) {
QChar c = txt.at(pos++);
- if (c == QLatin1Char('\''))
+ // Allow for escaped single quotes as they may be part of the string
+ if (c == QLatin1Char('\'') && (txt.length() > 1 && txt.at(pos - 2) != QLatin1Char('\\')))
break;
else
word += c;
@@ -1124,6 +1125,7 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent
margin[QTextHtmlParser::MarginBottom] = 12;
margin[QTextHtmlParser::MarginLeft] = 40;
margin[QTextHtmlParser::MarginRight] = 40;
+ blockFormat.setProperty(QTextFormat::BlockQuoteLevel, 1);
break;
case Html_dl:
margin[QTextHtmlParser::MarginTop] = 8;
@@ -1333,6 +1335,17 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
default: break;
}
break;
+
+ case QCss::QtForegroundTextureCacheKey:
+ {
+ if (resourceProvider != nullptr && resourceProvider->docHandle() != nullptr) {
+ bool ok;
+ qint64 searchKey = decl.d->values.first().variant.toLongLong(&ok);
+ if (ok)
+ applyForegroundImage(searchKey, resourceProvider);
+ }
+ break;
+ }
default: break;
}
}
@@ -1365,6 +1378,37 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
#endif // QT_NO_CSSPARSER
+void QTextHtmlParserNode::applyForegroundImage(qint64 searchKey, const QTextDocument *resourceProvider)
+{
+ QTextDocumentPrivate *priv = resourceProvider->docHandle();
+ for (int i = 0; i < priv->formats.numFormats(); ++i) {
+ QTextCharFormat format = priv->formats.charFormat(i);
+ if (format.isValid()) {
+ QBrush brush = format.foreground();
+ if (brush.style() == Qt::TexturePattern) {
+ const bool isPixmap = qHasPixmapTexture(brush);
+
+ if (isPixmap && QCoreApplication::instance()->thread() != QThread::currentThread()) {
+ qWarning("Can't apply QPixmap outside of GUI thread");
+ return;
+ }
+
+ const qint64 cacheKey = isPixmap ? brush.texture().cacheKey() : brush.textureImage().cacheKey();
+ if (cacheKey == searchKey) {
+ QBrush b;
+ if (isPixmap)
+ b.setTexture(brush.texture());
+ else
+ b.setTextureImage(brush.textureImage());
+ b.setStyle(Qt::TexturePattern);
+ charFormat.setForeground(b);
+ }
+ }
+ }
+ }
+
+}
+
void QTextHtmlParserNode::applyBackgroundImage(const QString &url, const QTextDocument *resourceProvider)
{
if (!url.isEmpty() && resourceProvider) {
@@ -1543,7 +1587,7 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
if (key == QLatin1String("href"))
node->charFormat.setAnchorHref(value);
else if (key == QLatin1String("name"))
- node->charFormat.setAnchorName(value);
+ node->charFormat.setAnchorNames({value});
break;
case Html_img:
if (key == QLatin1String("src") || key == QLatin1String("source")) {
@@ -1554,6 +1598,10 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
} else if (key == QLatin1String("height")) {
node->imageHeight = -2; // register that there is a value for it.
setFloatAttribute(&node->imageHeight, value);
+ } else if (key == QLatin1String("alt")) {
+ node->imageAlt = value;
+ } else if (key == QLatin1String("title")) {
+ node->text = value;
}
break;
case Html_tr:
@@ -1629,6 +1677,10 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
else if (key == QLatin1String("type"))
linkType = value;
break;
+ case Html_pre:
+ if (key == QLatin1String("class") && value.startsWith(QLatin1String("language-")))
+ node->blockFormat.setProperty(QTextFormat::BlockCodeLanguage, value.mid(9));
+ break;
default:
break;
}
@@ -1683,7 +1735,7 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
node->charFormat.setToolTip(value);
} else if (key == QLatin1String("id")) {
node->charFormat.setAnchor(true);
- node->charFormat.setAnchorName(value);
+ node->charFormat.setAnchorNames({value});
}
}
diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h
index 73dac38b82..c174b54a61 100644
--- a/src/gui/text/qtexthtmlparser_p.h
+++ b/src/gui/text/qtexthtmlparser_p.h
@@ -184,6 +184,7 @@ struct QTextHtmlParserNode {
QString textListNumberPrefix;
QString textListNumberSuffix;
QString imageName;
+ QString imageAlt;
qreal imageWidth;
qreal imageHeight;
QTextLength width;
@@ -250,6 +251,7 @@ struct QTextHtmlParserNode {
void setListStyle(const QVector<QCss::Value> &cssValues);
#endif
+ void applyForegroundImage(qint64 cacheKey, const QTextDocument *resourceProvider);
void applyBackgroundImage(const QString &url, const QTextDocument *resourceProvider);
bool hasOnlyWhitespace() const;
diff --git a/src/gui/text/qtextimagehandler_p.h b/src/gui/text/qtextimagehandler_p.h
index 339ef0af4f..fafd394ad3 100644
--- a/src/gui/text/qtextimagehandler_p.h
+++ b/src/gui/text/qtextimagehandler_p.h
@@ -65,7 +65,7 @@ class Q_GUI_EXPORT QTextImageHandler : public QObject,
Q_OBJECT
Q_INTERFACES(QTextObjectInterface)
public:
- explicit QTextImageHandler(QObject *parent = 0);
+ explicit QTextImageHandler(QObject *parent = nullptr);
virtual QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format) override;
virtual void drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format) override;
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index f3f0caa379..a3e194f835 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -344,6 +344,8 @@ QTextLayout::QTextLayout(const QString& text)
}
/*!
+ \since 5.13
+ \fn QTextLayout::QTextLayout(const QString &text, const QFont &font, const QPaintDevice *paintdevice)
Constructs a text layout to lay out the given \a text with the specified
\a font.
@@ -351,11 +353,20 @@ QTextLayout::QTextLayout(const QString& text)
the paint device, \a paintdevice. If \a paintdevice is 0 the
calculations will be done in screen metrics.
*/
-QTextLayout::QTextLayout(const QString& text, const QFont &font, QPaintDevice *paintdevice)
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \fn QTextLayout::QTextLayout(const QString &text, const QFont &font, QPaintDevice *paintdevice)
+ \obsolete
+ Identical to QTextLayout::QTextLayout(const QString &text, const QFont &font, const QPaintDevice *paintdevice)
+*/
+
+QTextLayout::QTextLayout(const QString &text, const QFont &font, QPaintDevice *paintdevice)
+#else
+QTextLayout::QTextLayout(const QString &text, const QFont &font, const QPaintDevice *paintdevice)
+#endif
{
- QFont f(font);
- if (paintdevice)
- f = QFont(font, paintdevice);
+ const QFont f(paintdevice ? QFont(font, paintdevice) : font);
d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f);
}
@@ -1127,8 +1138,6 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang
QPainterPath textDoneRegion;
for (int i = 0; i < selections.size(); ++i) {
FormatRange selection = selections.at(i);
- const QBrush bg = selection.format.background();
-
QPainterPath region;
region.setFillRule(Qt::WindingFill);
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index 67bc75a6b8..a29791534e 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -107,7 +107,19 @@ public:
// does itemization
QTextLayout();
QTextLayout(const QString& text);
- QTextLayout(const QString& text, const QFont &font, QPaintDevice *paintdevice = nullptr);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ QTextLayout(const QString &text, const QFont &font, QPaintDevice *paintdevice = nullptr);
+#ifndef Q_QDOC
+ // the template is necessary to make QTextLayout(font,text,nullptr) and QTextLayout(font,text,NULL)
+ // not ambiguous. Implementation detail that should not be documented.
+ template<char = 0>
+#endif
+ QTextLayout(const QString &text, const QFont &font, const QPaintDevice *paintdevice)
+ : QTextLayout(text, font, const_cast<QPaintDevice*>(paintdevice))
+ {}
+#else
+ QTextLayout(const QString &text, const QFont &font, const QPaintDevice *paintdevice = nullptr);
+#endif
QTextLayout(const QTextBlock &b);
~QTextLayout();
diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp
index bec33d5f4d..5857afa048 100644
--- a/src/gui/text/qtextlist.cpp
+++ b/src/gui/text/qtextlist.cpp
@@ -100,6 +100,7 @@ public:
\sa QTextBlock, QTextListFormat, QTextCursor
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\fn bool QTextList::isEmpty() const
\obsolete
@@ -111,6 +112,7 @@ public:
\sa count()
*/
+#endif
/*! \internal
*/
diff --git a/src/gui/text/qtextlist.h b/src/gui/text/qtextlist.h
index 3967787f03..cfb9f9456f 100644
--- a/src/gui/text/qtextlist.h
+++ b/src/gui/text/qtextlist.h
@@ -59,8 +59,11 @@ public:
int count() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use count() instead")
inline bool isEmpty() const
{ return count() == 0; }
+#endif
QTextBlock item(int i) const;
diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp
new file mode 100644
index 0000000000..b96263f5fc
--- /dev/null
+++ b/src/gui/text/qtextmarkdownimporter.cpp
@@ -0,0 +1,568 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtextmarkdownimporter_p.h"
+#include "qtextdocumentfragment_p.h"
+#include <QLoggingCategory>
+#if QT_CONFIG(regularexpression)
+#include <QRegularExpression>
+#endif
+#include <QTextCursor>
+#include <QTextDocument>
+#include <QTextDocumentFragment>
+#include <QTextList>
+#include <QTextTable>
+#include "../../3rdparty/md4c/md4c.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown")
+
+static const QChar Newline = QLatin1Char('\n');
+static const QChar Space = QLatin1Char(' ');
+
+// TODO maybe eliminate the margins after all views recognize BlockQuoteLevel, CSS can format it, etc.
+static const int BlockQuoteIndent = 40; // pixels, same as in QTextHtmlParserNode::initializeProperties
+
+// --------------------------------------------------------
+// MD4C callback function wrappers
+
+static int CbEnterBlock(MD_BLOCKTYPE type, void *detail, void *userdata)
+{
+ QTextMarkdownImporter *mdi = static_cast<QTextMarkdownImporter *>(userdata);
+ return mdi->cbEnterBlock(int(type), detail);
+}
+
+static int CbLeaveBlock(MD_BLOCKTYPE type, void *detail, void *userdata)
+{
+ QTextMarkdownImporter *mdi = static_cast<QTextMarkdownImporter *>(userdata);
+ return mdi->cbLeaveBlock(int(type), detail);
+}
+
+static int CbEnterSpan(MD_SPANTYPE type, void *detail, void *userdata)
+{
+ QTextMarkdownImporter *mdi = static_cast<QTextMarkdownImporter *>(userdata);
+ return mdi->cbEnterSpan(int(type), detail);
+}
+
+static int CbLeaveSpan(MD_SPANTYPE type, void *detail, void *userdata)
+{
+ QTextMarkdownImporter *mdi = static_cast<QTextMarkdownImporter *>(userdata);
+ return mdi->cbLeaveSpan(int(type), detail);
+}
+
+static int CbText(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size, void *userdata)
+{
+ QTextMarkdownImporter *mdi = static_cast<QTextMarkdownImporter *>(userdata);
+ return mdi->cbText(int(type), text, size);
+}
+
+static void CbDebugLog(const char *msg, void *userdata)
+{
+ Q_UNUSED(userdata)
+ qCDebug(lcMD) << msg;
+}
+
+// MD4C callback function wrappers
+// --------------------------------------------------------
+
+static Qt::Alignment MdAlignment(MD_ALIGN a, Qt::Alignment defaultAlignment = Qt::AlignLeft | Qt::AlignVCenter)
+{
+ switch (a) {
+ case MD_ALIGN_LEFT:
+ return Qt::AlignLeft | Qt::AlignVCenter;
+ case MD_ALIGN_CENTER:
+ return Qt::AlignHCenter | Qt::AlignVCenter;
+ case MD_ALIGN_RIGHT:
+ return Qt::AlignRight | Qt::AlignVCenter;
+ default: // including MD_ALIGN_DEFAULT
+ return defaultAlignment;
+ }
+}
+
+QTextMarkdownImporter::QTextMarkdownImporter(QTextMarkdownImporter::Features features)
+ : m_monoFont(QFontDatabase::systemFont(QFontDatabase::FixedFont))
+ , m_features(features)
+{
+}
+
+void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown)
+{
+ MD_PARSER callbacks = {
+ 0, // abi_version
+ unsigned(m_features),
+ &CbEnterBlock,
+ &CbLeaveBlock,
+ &CbEnterSpan,
+ &CbLeaveSpan,
+ &CbText,
+ &CbDebugLog,
+ nullptr // syntax
+ };
+ m_doc = doc;
+ m_paragraphMargin = m_doc->defaultFont().pointSize() * 2 / 3;
+ m_cursor = new QTextCursor(doc);
+ doc->clear();
+ qCDebug(lcMD) << "default font" << doc->defaultFont() << "mono font" << m_monoFont;
+ QByteArray md = markdown.toUtf8();
+ md_parse(md.constData(), MD_SIZE(md.size()), &callbacks, this);
+ delete m_cursor;
+ m_cursor = nullptr;
+}
+
+int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
+{
+ m_blockType = blockType;
+ switch (blockType) {
+ case MD_BLOCK_P:
+ if (!m_listStack.isEmpty())
+ qCDebug(lcMD, m_listItem ? "P of LI at level %d" : "P continuation inside LI at level %d", m_listStack.count());
+ else
+ qCDebug(lcMD, "P");
+ m_needsInsertBlock = true;
+ break;
+ case MD_BLOCK_QUOTE:
+ ++m_blockQuoteDepth;
+ qCDebug(lcMD, "QUOTE level %d", m_blockQuoteDepth);
+ break;
+ case MD_BLOCK_CODE: {
+ MD_BLOCK_CODE_DETAIL *detail = static_cast<MD_BLOCK_CODE_DETAIL *>(det);
+ m_codeBlock = true;
+ m_blockCodeLanguage = QLatin1String(detail->lang.text, int(detail->lang.size));
+ m_blockCodeFence = detail->fence_char;
+ QString info = QLatin1String(detail->info.text, int(detail->info.size));
+ m_needsInsertBlock = true;
+ if (m_blockQuoteDepth)
+ qCDebug(lcMD, "CODE lang '%s' info '%s' fenced with '%c' inside QUOTE %d", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockCodeFence, m_blockQuoteDepth);
+ else
+ qCDebug(lcMD, "CODE lang '%s' info '%s' fenced with '%c'", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockCodeFence);
+ } break;
+ case MD_BLOCK_H: {
+ MD_BLOCK_H_DETAIL *detail = static_cast<MD_BLOCK_H_DETAIL *>(det);
+ QTextBlockFormat blockFmt;
+ QTextCharFormat charFmt;
+ int sizeAdjustment = 4 - int(detail->level); // H1 to H6: +3 to -2
+ charFmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment);
+ charFmt.setFontWeight(QFont::Bold);
+ blockFmt.setHeadingLevel(int(detail->level));
+ m_needsInsertBlock = false;
+ m_cursor->insertBlock(blockFmt, charFmt);
+ qCDebug(lcMD, "H%d", detail->level);
+ } break;
+ case MD_BLOCK_LI: {
+ m_needsInsertBlock = true;
+ m_listItem = true;
+ MD_BLOCK_LI_DETAIL *detail = static_cast<MD_BLOCK_LI_DETAIL *>(det);
+ m_markerType = detail->is_task ?
+ (detail->task_mark == ' ' ? QTextBlockFormat::Unchecked : QTextBlockFormat::Checked) :
+ QTextBlockFormat::NoMarker;
+ qCDebug(lcMD) << "LI";
+ } break;
+ case MD_BLOCK_UL: {
+ MD_BLOCK_UL_DETAIL *detail = static_cast<MD_BLOCK_UL_DETAIL *>(det);
+ m_listFormat = QTextListFormat();
+ m_listFormat.setIndent(m_listStack.count() + 1);
+ switch (detail->mark) {
+ case '*':
+ m_listFormat.setStyle(QTextListFormat::ListCircle);
+ break;
+ case '+':
+ m_listFormat.setStyle(QTextListFormat::ListSquare);
+ break;
+ default: // including '-'
+ m_listFormat.setStyle(QTextListFormat::ListDisc);
+ break;
+ }
+ qCDebug(lcMD, "UL %c level %d", detail->mark, m_listStack.count());
+ m_needsInsertList = true;
+ } break;
+ case MD_BLOCK_OL: {
+ MD_BLOCK_OL_DETAIL *detail = static_cast<MD_BLOCK_OL_DETAIL *>(det);
+ m_listFormat = QTextListFormat();
+ m_listFormat.setIndent(m_listStack.count() + 1);
+ m_listFormat.setNumberSuffix(QChar::fromLatin1(detail->mark_delimiter));
+ m_listFormat.setStyle(QTextListFormat::ListDecimal);
+ qCDebug(lcMD, "OL xx%d level %d", detail->mark_delimiter, m_listStack.count());
+ m_needsInsertList = true;
+ } break;
+ case MD_BLOCK_TD: {
+ MD_BLOCK_TD_DETAIL *detail = static_cast<MD_BLOCK_TD_DETAIL *>(det);
+ ++m_tableCol;
+ // absolute movement (and storage of m_tableCol) shouldn't be necessary, but
+ // movePosition(QTextCursor::NextCell) doesn't work
+ QTextTableCell cell = m_currentTable->cellAt(m_tableRowCount - 1, m_tableCol);
+ if (!cell.isValid()) {
+ qWarning("malformed table in Markdown input");
+ return 1;
+ }
+ *m_cursor = cell.firstCursorPosition();
+ QTextBlockFormat blockFmt = m_cursor->blockFormat();
+ blockFmt.setAlignment(MdAlignment(detail->align));
+ m_cursor->setBlockFormat(blockFmt);
+ qCDebug(lcMD) << "TD; align" << detail->align << MdAlignment(detail->align) << "col" << m_tableCol;
+ } break;
+ case MD_BLOCK_TH: {
+ ++m_tableColumnCount;
+ ++m_tableCol;
+ if (m_currentTable->columns() < m_tableColumnCount)
+ m_currentTable->appendColumns(1);
+ auto cell = m_currentTable->cellAt(m_tableRowCount - 1, m_tableCol);
+ if (!cell.isValid()) {
+ qWarning("malformed table in Markdown input");
+ return 1;
+ }
+ auto fmt = cell.format();
+ fmt.setFontWeight(QFont::Bold);
+ cell.setFormat(fmt);
+ } break;
+ case MD_BLOCK_TR: {
+ ++m_tableRowCount;
+ m_nonEmptyTableCells.clear();
+ if (m_currentTable->rows() < m_tableRowCount)
+ m_currentTable->appendRows(1);
+ m_tableCol = -1;
+ qCDebug(lcMD) << "TR" << m_currentTable->rows();
+ } break;
+ case MD_BLOCK_TABLE:
+ m_tableColumnCount = 0;
+ m_tableRowCount = 0;
+ m_currentTable = m_cursor->insertTable(1, 1); // we don't know the dimensions yet
+ break;
+ case MD_BLOCK_HR: {
+ qCDebug(lcMD, "HR");
+ QTextBlockFormat blockFmt;
+ blockFmt.setProperty(QTextFormat::BlockTrailingHorizontalRulerWidth, 1);
+ m_cursor->insertBlock(blockFmt, QTextCharFormat());
+ } break;
+ default:
+ break; // nothing to do for now
+ }
+ return 0; // no error
+}
+
+int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail)
+{
+ Q_UNUSED(detail)
+ switch (blockType) {
+ case MD_BLOCK_P:
+ m_listItem = false;
+ break;
+ case MD_BLOCK_UL:
+ case MD_BLOCK_OL:
+ qCDebug(lcMD, "list at level %d ended", m_listStack.count());
+ m_listStack.pop();
+ break;
+ case MD_BLOCK_TR: {
+ // https://github.com/mity/md4c/issues/29
+ // MD4C doesn't tell us explicitly which cells are merged, so merge empty cells
+ // with previous non-empty ones
+ int mergeEnd = -1;
+ int mergeBegin = -1;
+ for (int col = m_tableCol; col >= 0; --col) {
+ if (m_nonEmptyTableCells.contains(col)) {
+ if (mergeEnd >= 0 && mergeBegin >= 0) {
+ qCDebug(lcMD) << "merging cells" << mergeBegin << "to" << mergeEnd << "inclusive, on row" << m_currentTable->rows() - 1;
+ m_currentTable->mergeCells(m_currentTable->rows() - 1, mergeBegin - 1, 1, mergeEnd - mergeBegin + 2);
+ }
+ mergeEnd = -1;
+ mergeBegin = -1;
+ } else {
+ if (mergeEnd < 0)
+ mergeEnd = col;
+ else
+ mergeBegin = col;
+ }
+ }
+ } break;
+ case MD_BLOCK_QUOTE: {
+ qCDebug(lcMD, "QUOTE level %d ended", m_blockQuoteDepth);
+ --m_blockQuoteDepth;
+ m_needsInsertBlock = true;
+ } break;
+ case MD_BLOCK_TABLE:
+ qCDebug(lcMD) << "table ended with" << m_currentTable->columns() << "cols and" << m_currentTable->rows() << "rows";
+ m_currentTable = nullptr;
+ m_cursor->movePosition(QTextCursor::End);
+ break;
+ case MD_BLOCK_LI:
+ qCDebug(lcMD, "LI at level %d ended", m_listStack.count());
+ m_listItem = false;
+ break;
+ case MD_BLOCK_CODE: {
+ m_codeBlock = false;
+ m_blockCodeLanguage.clear();
+ m_blockCodeFence = 0;
+ if (m_blockQuoteDepth)
+ qCDebug(lcMD, "CODE ended inside QUOTE %d", m_blockQuoteDepth);
+ else
+ qCDebug(lcMD, "CODE ended");
+ m_needsInsertBlock = true;
+ } break;
+ case MD_BLOCK_H:
+ m_cursor->setCharFormat(QTextCharFormat());
+ break;
+ default:
+ break;
+ }
+ return 0; // no error
+}
+
+int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det)
+{
+ QTextCharFormat charFmt;
+ switch (spanType) {
+ case MD_SPAN_EM:
+ charFmt.setFontItalic(true);
+ break;
+ case MD_SPAN_STRONG:
+ charFmt.setFontWeight(QFont::Bold);
+ break;
+ case MD_SPAN_A: {
+ MD_SPAN_A_DETAIL *detail = static_cast<MD_SPAN_A_DETAIL *>(det);
+ QString url = QString::fromLatin1(detail->href.text, int(detail->href.size));
+ QString title = QString::fromLatin1(detail->title.text, int(detail->title.size));
+ charFmt.setAnchorHref(url);
+ charFmt.setAnchorNames(QStringList(title));
+ charFmt.setForeground(m_palette.link());
+ qCDebug(lcMD) << "anchor" << url << title;
+ } break;
+ case MD_SPAN_IMG: {
+ m_imageSpan = true;
+ m_imageFormat = QTextImageFormat();
+ MD_SPAN_IMG_DETAIL *detail = static_cast<MD_SPAN_IMG_DETAIL *>(det);
+ m_imageFormat.setName(QString::fromUtf8(detail->src.text, int(detail->src.size)));
+ m_imageFormat.setProperty(QTextFormat::ImageTitle, QString::fromUtf8(detail->title.text, int(detail->title.size)));
+ break;
+ }
+ case MD_SPAN_CODE:
+ charFmt.setFont(m_monoFont);
+ break;
+ case MD_SPAN_DEL:
+ charFmt.setFontStrikeOut(true);
+ break;
+ }
+ m_spanFormatStack.push(charFmt);
+ qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().family() << charFmt.fontWeight()
+ << (charFmt.fontItalic() ? "italic" : "") << charFmt.foreground().color().name();
+ m_cursor->setCharFormat(charFmt);
+ return 0; // no error
+}
+
+int QTextMarkdownImporter::cbLeaveSpan(int spanType, void *detail)
+{
+ Q_UNUSED(detail)
+ QTextCharFormat charFmt;
+ if (!m_spanFormatStack.isEmpty()) {
+ m_spanFormatStack.pop();
+ if (!m_spanFormatStack.isEmpty())
+ charFmt = m_spanFormatStack.top();
+ }
+ m_cursor->setCharFormat(charFmt);
+ qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().family() << charFmt.fontWeight()
+ << (charFmt.fontItalic() ? "italic" : "") << charFmt.foreground().color().name();
+ if (spanType == int(MD_SPAN_IMG))
+ m_imageSpan = false;
+ return 0; // no error
+}
+
+int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
+{
+ if (m_needsInsertBlock)
+ insertBlock();
+#if QT_CONFIG(regularexpression)
+ static const QRegularExpression openingBracket(QStringLiteral("<[a-zA-Z]"));
+ static const QRegularExpression closingBracket(QStringLiteral("(/>|</)"));
+#endif
+ QString s = QString::fromUtf8(text, int(size));
+
+ switch (textType) {
+ case MD_TEXT_NORMAL:
+#if QT_CONFIG(regularexpression)
+ if (m_htmlTagDepth) {
+ m_htmlAccumulator += s;
+ s = QString();
+ }
+#endif
+ break;
+ case MD_TEXT_NULLCHAR:
+ s = QString(QChar(0xFFFD)); // CommonMark-required replacement for null
+ break;
+ case MD_TEXT_BR:
+ s = QString(Newline);
+ break;
+ case MD_TEXT_SOFTBR:
+ s = QString(Space);
+ break;
+ case MD_TEXT_CODE:
+ // We'll see MD_SPAN_CODE too, which will set the char format, and that's enough.
+ break;
+#if QT_CONFIG(texthtmlparser)
+ case MD_TEXT_ENTITY:
+ m_cursor->insertHtml(s);
+ s = QString();
+ break;
+#endif
+ case MD_TEXT_HTML:
+ // count how many tags are opened and how many are closed
+#if QT_CONFIG(regularexpression) && QT_CONFIG(texthtmlparser)
+ {
+ int startIdx = 0;
+ while ((startIdx = s.indexOf(openingBracket, startIdx)) >= 0) {
+ ++m_htmlTagDepth;
+ startIdx += 2;
+ }
+ startIdx = 0;
+ while ((startIdx = s.indexOf(closingBracket, startIdx)) >= 0) {
+ --m_htmlTagDepth;
+ startIdx += 2;
+ }
+ }
+ m_htmlAccumulator += s;
+ if (!m_htmlTagDepth) { // all open tags are now closed
+ qCDebug(lcMD) << "HTML" << m_htmlAccumulator;
+ m_cursor->insertHtml(m_htmlAccumulator);
+ if (m_spanFormatStack.isEmpty())
+ m_cursor->setCharFormat(QTextCharFormat());
+ else
+ m_cursor->setCharFormat(m_spanFormatStack.top());
+ m_htmlAccumulator = QString();
+ }
+#endif
+ s = QString();
+ break;
+ }
+
+ switch (m_blockType) {
+ case MD_BLOCK_TD:
+ m_nonEmptyTableCells.append(m_tableCol);
+ break;
+ default:
+ break;
+ }
+
+ if (m_imageSpan) {
+ // TODO we don't yet support alt text with formatting, because of the cases where m_cursor
+ // already inserted the text above. Rather need to accumulate it in case we need it here.
+ m_imageFormat.setProperty(QTextFormat::ImageAltText, s);
+ qCDebug(lcMD) << "image" << m_imageFormat.name()
+ << "title" << m_imageFormat.stringProperty(QTextFormat::ImageTitle)
+ << "alt" << s << "relative to" << m_doc->baseUrl();
+ m_cursor->insertImage(m_imageFormat);
+ return 0; // no error
+ }
+
+ if (!s.isEmpty())
+ m_cursor->insertText(s);
+ if (m_cursor->currentList()) {
+ // The list item will indent the list item's text, so we don't need indentation on the block.
+ QTextBlockFormat bfmt = m_cursor->blockFormat();
+ bfmt.setIndent(0);
+ m_cursor->setBlockFormat(bfmt);
+ }
+ if (lcMD().isEnabled(QtDebugMsg)) {
+ QTextBlockFormat bfmt = m_cursor->blockFormat();
+ QString debugInfo;
+ if (m_cursor->currentList())
+ debugInfo = QLatin1String("in list at depth ") + QString::number(m_cursor->currentList()->format().indent());
+ if (bfmt.hasProperty(QTextFormat::BlockQuoteLevel))
+ debugInfo += QLatin1String("in blockquote at depth ") +
+ QString::number(bfmt.intProperty(QTextFormat::BlockQuoteLevel));
+ if (bfmt.hasProperty(QTextFormat::BlockCodeLanguage))
+ debugInfo += QLatin1String("in a code block");
+ qCDebug(lcMD) << textType << "in block" << m_blockType << s << qPrintable(debugInfo)
+ << "bindent" << bfmt.indent() << "tindent" << bfmt.textIndent()
+ << "margins" << bfmt.leftMargin() << bfmt.topMargin() << bfmt.bottomMargin() << bfmt.rightMargin();
+ }
+ qCDebug(lcMD) << textType << "in block" << m_blockType << s << "in list?" << m_cursor->currentList()
+ << "indent" << m_cursor->blockFormat().indent();
+ return 0; // no error
+}
+
+/*!
+ Insert a new block based on stored state.
+
+ m_cursor cannot store the state for the _next_ block ahead of time, because
+ m_cursor->setBlockFormat() controls the format of the block that the cursor
+ is already in; so cbLeaveBlock() cannot call setBlockFormat() without
+ altering the block that was just added. Therefore cbLeaveBlock() and the
+ following cbEnterBlock() set variables to remember what formatting should
+ come next, and insertBlock() is called just before the actual text
+ insertion, to create a new block with the right formatting.
+*/
+void QTextMarkdownImporter::insertBlock()
+{
+ QTextCharFormat charFormat;
+ if (!m_spanFormatStack.isEmpty())
+ charFormat = m_spanFormatStack.top();
+ QTextBlockFormat blockFormat;
+ if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) {
+ QTextList *list = m_listStack.top();
+ blockFormat = list->item(list->count() - 1).blockFormat();
+ }
+ if (m_blockQuoteDepth) {
+ blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth);
+ blockFormat.setLeftMargin(BlockQuoteIndent * m_blockQuoteDepth);
+ blockFormat.setRightMargin(BlockQuoteIndent);
+ }
+ if (m_codeBlock) {
+ blockFormat.setProperty(QTextFormat::BlockCodeLanguage, m_blockCodeLanguage);
+ if (m_blockCodeFence)
+ blockFormat.setProperty(QTextFormat::BlockCodeFence, QString(QLatin1Char(m_blockCodeFence)));
+ charFormat.setFont(m_monoFont);
+ } else {
+ blockFormat.setTopMargin(m_paragraphMargin);
+ blockFormat.setBottomMargin(m_paragraphMargin);
+ }
+ if (m_markerType == QTextBlockFormat::NoMarker)
+ blockFormat.clearProperty(QTextFormat::BlockMarker);
+ else
+ blockFormat.setMarker(m_markerType);
+ if (!m_listStack.isEmpty())
+ blockFormat.setIndent(m_listStack.count());
+ m_cursor->insertBlock(blockFormat, charFormat);
+ if (m_needsInsertList) {
+ m_listStack.push(m_cursor->createList(m_listFormat));
+ } else if (!m_listStack.isEmpty() && m_listItem) {
+ m_listStack.top()->add(m_cursor->block());
+ }
+ m_needsInsertList = false;
+ m_needsInsertBlock = false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h
new file mode 100644
index 0000000000..1b8c2ca354
--- /dev/null
+++ b/src/gui/text/qtextmarkdownimporter_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTMARKDOWNIMPORTER_H
+#define QTEXTMARKDOWNIMPORTER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qfont.h>
+#include <QtGui/qtguiglobal.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qtextlist.h>
+#include <QtCore/qstack.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTextCursor;
+class QTextDocument;
+class QTextTable;
+
+class Q_GUI_EXPORT QTextMarkdownImporter
+{
+public:
+ enum Feature {
+ // Must be kept in sync with MD_FLAG_* in md4c.h
+ FeatureCollapseWhitespace = 0x0001, // MD_FLAG_COLLAPSEWHITESPACE
+ FeaturePermissiveATXHeaders = 0x0002, // MD_FLAG_PERMISSIVEATXHEADERS
+ FeaturePermissiveURLAutoLinks = 0x0004, // MD_FLAG_PERMISSIVEURLAUTOLINKS
+ FeaturePermissiveMailAutoLinks = 0x0008, // MD_FLAG_PERMISSIVEEMAILAUTOLINKS
+ FeatureNoIndentedCodeBlocks = 0x0010, // MD_FLAG_NOINDENTEDCODEBLOCKS
+ FeatureNoHTMLBlocks = 0x0020, // MD_FLAG_NOHTMLBLOCKS
+ FeatureNoHTMLSpans = 0x0040, // MD_FLAG_NOHTMLSPANS
+ FeatureTables = 0x0100, // MD_FLAG_TABLES
+ FeatureStrikeThrough = 0x0200, // MD_FLAG_STRIKETHROUGH
+ FeaturePermissiveWWWAutoLinks = 0x0400, // MD_FLAG_PERMISSIVEWWWAUTOLINKS
+ FeatureTasklists = 0x0800, // MD_FLAG_TASKLISTS
+ // composite flags
+ FeaturePermissiveAutoLinks = FeaturePermissiveMailAutoLinks | FeaturePermissiveURLAutoLinks | FeaturePermissiveWWWAutoLinks, // MD_FLAG_PERMISSIVEAUTOLINKS
+ FeatureNoHTML = FeatureNoHTMLBlocks | FeatureNoHTMLSpans, // MD_FLAG_NOHTML
+ DialectCommonMark = 0, // MD_DIALECT_COMMONMARK
+ DialectGitHub = FeaturePermissiveAutoLinks | FeatureTables | FeatureStrikeThrough | FeatureTasklists // MD_DIALECT_GITHUB
+ };
+ Q_DECLARE_FLAGS(Features, Feature)
+
+ QTextMarkdownImporter(Features features);
+
+ void import(QTextDocument *doc, const QString &markdown);
+
+public:
+ // MD4C callbacks
+ int cbEnterBlock(int blockType, void* detail);
+ int cbLeaveBlock(int blockType, void* detail);
+ int cbEnterSpan(int spanType, void* detail);
+ int cbLeaveSpan(int spanType, void* detail);
+ int cbText(int textType, const char* text, unsigned size);
+
+private:
+ void insertBlock();
+
+private:
+ QTextDocument *m_doc = nullptr;
+ QTextCursor *m_cursor = nullptr;
+ QTextTable *m_currentTable = nullptr; // because m_cursor->currentTable() doesn't work
+#if QT_CONFIG(regularexpression)
+ QString m_htmlAccumulator;
+#endif
+ QString m_blockCodeLanguage;
+ QVector<int> m_nonEmptyTableCells; // in the current row
+ QStack<QTextList *> m_listStack;
+ QStack<QTextCharFormat> m_spanFormatStack;
+ QFont m_monoFont;
+ QPalette m_palette;
+#if QT_CONFIG(regularexpression)
+ int m_htmlTagDepth = 0;
+#endif
+ int m_blockQuoteDepth = 0;
+ int m_tableColumnCount = 0;
+ int m_tableRowCount = 0;
+ int m_tableCol = -1; // because relative cell movements (e.g. m_cursor->movePosition(QTextCursor::NextCell)) don't work
+ int m_paragraphMargin = 0;
+ int m_blockType = 0;
+ char m_blockCodeFence = 0;
+ Features m_features;
+ QTextImageFormat m_imageFormat;
+ QTextListFormat m_listFormat;
+ QTextBlockFormat::MarkerType m_markerType = QTextBlockFormat::NoMarker;
+ bool m_needsInsertBlock = false;
+ bool m_needsInsertList = false;
+ bool m_listItem = false; // true from the beginning of LI to the end of the first P
+ bool m_codeBlock = false;
+ bool m_imageSpan = false;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QTextMarkdownImporter::Features)
+
+QT_END_NAMESPACE
+
+#endif // QTEXTMARKDOWNIMPORTER_H
diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp
new file mode 100644
index 0000000000..f351c8d20b
--- /dev/null
+++ b/src/gui/text/qtextmarkdownwriter.cpp
@@ -0,0 +1,559 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtextmarkdownwriter_p.h"
+#include "qtextdocumentlayout_p.h"
+#include "qfontinfo.h"
+#include "qfontmetrics.h"
+#include "qtextdocument_p.h"
+#include "qtextlist.h"
+#include "qtexttable.h"
+#include "qtextcursor.h"
+#include "qtextimagehandler_p.h"
+#include "qloggingcategory.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcMDW, "qt.text.markdown.writer")
+
+static const QChar Space = QLatin1Char(' ');
+static const QChar Newline = QLatin1Char('\n');
+static const QChar LineBreak = QChar(0x2028);
+static const QChar DoubleQuote = QLatin1Char('"');
+static const QChar Backtick = QLatin1Char('`');
+static const QChar Period = QLatin1Char('.');
+
+QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features)
+ : m_stream(stream), m_features(features)
+{
+}
+
+bool QTextMarkdownWriter::writeAll(const QTextDocument *document)
+{
+ writeFrame(document->rootFrame());
+ return true;
+}
+
+void QTextMarkdownWriter::writeTable(const QAbstractItemModel *table)
+{
+ QVector<int> tableColumnWidths(table->columnCount());
+ for (int col = 0; col < table->columnCount(); ++col) {
+ tableColumnWidths[col] = table->headerData(col, Qt::Horizontal).toString().length();
+ for (int row = 0; row < table->rowCount(); ++row) {
+ tableColumnWidths[col] = qMax(tableColumnWidths[col],
+ table->data(table->index(row, col)).toString().length());
+ }
+ }
+
+ // write the header and separator
+ for (int col = 0; col < table->columnCount(); ++col) {
+ QString s = table->headerData(col, Qt::Horizontal).toString();
+ m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space);
+ }
+ m_stream << "|" << Qt::endl;
+ for (int col = 0; col < tableColumnWidths.length(); ++col)
+ m_stream << '|' << QString(tableColumnWidths[col], QLatin1Char('-'));
+ m_stream << '|'<< Qt::endl;
+
+ // write the body
+ for (int row = 0; row < table->rowCount(); ++row) {
+ for (int col = 0; col < table->columnCount(); ++col) {
+ QString s = table->data(table->index(row, col)).toString();
+ m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space);
+ }
+ m_stream << '|'<< Qt::endl;
+ }
+ m_listInfo.clear();
+}
+
+void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
+{
+ Q_ASSERT(frame);
+ const QTextTable *table = qobject_cast<const QTextTable*> (frame);
+ QTextFrame::iterator iterator = frame->begin();
+ QTextFrame *child = nullptr;
+ int tableRow = -1;
+ bool lastWasList = false;
+ QVector<int> tableColumnWidths;
+ if (table) {
+ tableColumnWidths.resize(table->columns());
+ for (int col = 0; col < table->columns(); ++col) {
+ for (int row = 0; row < table->rows(); ++ row) {
+ QTextTableCell cell = table->cellAt(row, col);
+ int cellTextLen = 0;
+ auto it = cell.begin();
+ while (it != cell.end()) {
+ QTextBlock block = it.currentBlock();
+ if (block.isValid())
+ cellTextLen += block.text().length();
+ ++it;
+ }
+ if (cell.columnSpan() == 1 && tableColumnWidths[col] < cellTextLen)
+ tableColumnWidths[col] = cellTextLen;
+ }
+ }
+ }
+ while (!iterator.atEnd()) {
+ if (iterator.currentFrame() && child != iterator.currentFrame())
+ writeFrame(iterator.currentFrame());
+ else { // no frame, it's a block
+ QTextBlock block = iterator.currentBlock();
+ // Look ahead and detect some cases when we should
+ // suppress needless blank lines, when there will be a big change in block format
+ bool nextIsDifferent = false;
+ bool ending = false;
+ {
+ QTextFrame::iterator next = iterator;
+ ++next;
+ if (next.atEnd()) {
+ nextIsDifferent = true;
+ ending = true;
+ } else {
+ QTextBlockFormat format = iterator.currentBlock().blockFormat();
+ QTextBlockFormat nextFormat = next.currentBlock().blockFormat();
+ if (nextFormat.indent() != format.indent() ||
+ nextFormat.property(QTextFormat::BlockCodeLanguage) != format.property(QTextFormat::BlockCodeLanguage))
+ nextIsDifferent = true;
+ }
+ }
+ if (table) {
+ QTextTableCell cell = table->cellAt(block.position());
+ if (tableRow < cell.row()) {
+ if (tableRow == 0) {
+ m_stream << Newline;
+ for (int col = 0; col < tableColumnWidths.length(); ++col)
+ m_stream << '|' << QString(tableColumnWidths[col], QLatin1Char('-'));
+ m_stream << '|';
+ }
+ m_stream << Newline << "|";
+ tableRow = cell.row();
+ }
+ } else if (!block.textList()) {
+ if (lastWasList)
+ m_stream << Newline;
+ }
+ int endingCol = writeBlock(block, !table, table && tableRow == 0, nextIsDifferent);
+ m_doubleNewlineWritten = false;
+ if (table) {
+ QTextTableCell cell = table->cellAt(block.position());
+ int paddingLen = -endingCol;
+ int spanEndCol = cell.column() + cell.columnSpan();
+ for (int col = cell.column(); col < spanEndCol; ++col)
+ paddingLen += tableColumnWidths[col];
+ if (paddingLen > 0)
+ m_stream << QString(paddingLen, Space);
+ for (int col = cell.column(); col < spanEndCol; ++col)
+ m_stream << "|";
+ } else if (m_fencedCodeBlock && ending) {
+ m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space)
+ << m_codeBlockFence << Newline << Newline;
+ m_codeBlockFence.clear();
+ } else if (m_indentedCodeBlock && nextIsDifferent) {
+ m_stream << Newline;
+ } else if (endingCol > 0) {
+ if (block.textList() || block.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
+ m_stream << Newline;
+ } else {
+ m_stream << Newline << Newline;
+ m_doubleNewlineWritten = true;
+ }
+ }
+ lastWasList = block.textList();
+ }
+ child = iterator.currentFrame();
+ ++iterator;
+ }
+ if (table) {
+ m_stream << Newline << Newline;
+ m_doubleNewlineWritten = true;
+ }
+ m_listInfo.clear();
+}
+
+QTextMarkdownWriter::ListInfo QTextMarkdownWriter::listInfo(QTextList *list)
+{
+ if (!m_listInfo.contains(list)) {
+ // decide whether this list is loose or tight
+ ListInfo info;
+ info.loose = false;
+ if (list->count() > 1) {
+ QTextBlock first = list->item(0);
+ QTextBlock last = list->item(list->count() - 1);
+ QTextBlock next = first.next();
+ while (next.isValid()) {
+ if (next == last)
+ break;
+ qCDebug(lcMDW) << "next block in list" << list << next.text() << "part of list?" << next.textList();
+ if (!next.textList()) {
+ // If we find a continuation paragraph, this list is "loose"
+ // because it will need a blank line to separate that paragraph.
+ qCDebug(lcMDW) << "decided list beginning with" << first.text() << "is loose after" << next.text();
+ info.loose = true;
+ break;
+ }
+ next = next.next();
+ }
+ }
+ m_listInfo.insert(list, info);
+ return info;
+ }
+ return m_listInfo.value(list);
+}
+
+static int nearestWordWrapIndex(const QString &s, int before)
+{
+ before = qMin(before, s.length());
+ int fragBegin = qMax(before - 15, 0);
+ if (lcMDW().isDebugEnabled()) {
+ QString frag = s.mid(fragBegin, 30);
+ qCDebug(lcMDW) << frag << before;
+ qCDebug(lcMDW) << QString(before - fragBegin, Period) + QLatin1Char('<');
+ }
+ for (int i = before - 1; i >= 0; --i) {
+ if (s.at(i).isSpace()) {
+ qCDebug(lcMDW) << QString(i - fragBegin, Period) + QLatin1Char('^') << i;
+ return i;
+ }
+ }
+ qCDebug(lcMDW, "not possible");
+ return -1;
+}
+
+static int adjacentBackticksCount(const QString &s)
+{
+ int start = -1, len = s.length();
+ int ret = 0;
+ for (int i = 0; i < len; ++i) {
+ if (s.at(i) == Backtick) {
+ if (start < 0)
+ start = i;
+ } else if (start >= 0) {
+ ret = qMax(ret, i - start);
+ start = -1;
+ }
+ }
+ if (s.at(len - 1) == Backtick)
+ ret = qMax(ret, len - start);
+ return ret;
+}
+
+static void maybeEscapeFirstChar(QString &s)
+{
+ QString sTrimmed = s.trimmed();
+ if (sTrimmed.isEmpty())
+ return;
+ char firstChar = sTrimmed.at(0).toLatin1();
+ if (firstChar == '*' || firstChar == '+' || firstChar == '-') {
+ int i = s.indexOf(QLatin1Char(firstChar));
+ s.insert(i, QLatin1Char('\\'));
+ }
+}
+
+int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat, bool ignoreEmpty)
+{
+ if (block.text().isEmpty() && ignoreEmpty)
+ return 0;
+ const int ColumnLimit = 80;
+ QTextBlockFormat blockFmt = block.blockFormat();
+ bool missedBlankCodeBlockLine = false;
+ if (block.textList()) { // it's a list-item
+ auto fmt = block.textList()->format();
+ const int listLevel = fmt.indent();
+ const int number = block.textList()->itemNumber(block) + 1;
+ QByteArray bullet = " ";
+ bool numeric = false;
+ switch (fmt.style()) {
+ case QTextListFormat::ListDisc:
+ bullet = "-";
+ m_wrappedLineIndent = 2;
+ break;
+ case QTextListFormat::ListCircle:
+ bullet = "*";
+ m_wrappedLineIndent = 2;
+ break;
+ case QTextListFormat::ListSquare:
+ bullet = "+";
+ m_wrappedLineIndent = 2;
+ break;
+ case QTextListFormat::ListStyleUndefined: break;
+ case QTextListFormat::ListDecimal:
+ case QTextListFormat::ListLowerAlpha:
+ case QTextListFormat::ListUpperAlpha:
+ case QTextListFormat::ListLowerRoman:
+ case QTextListFormat::ListUpperRoman:
+ numeric = true;
+ m_wrappedLineIndent = 4;
+ break;
+ }
+ switch (blockFmt.marker()) {
+ case QTextBlockFormat::Checked:
+ bullet += " [x]";
+ break;
+ case QTextBlockFormat::Unchecked:
+ bullet += " [ ]";
+ break;
+ default:
+ break;
+ }
+ int indentFirstLine = (listLevel - 1) * (numeric ? 4 : 2);
+ m_wrappedLineIndent += indentFirstLine;
+ if (m_lastListIndent != listLevel && !m_doubleNewlineWritten && listInfo(block.textList()).loose)
+ m_stream << Newline;
+ m_lastListIndent = listLevel;
+ QString prefix(indentFirstLine, Space);
+ if (numeric) {
+ QString suffix = fmt.numberSuffix();
+ if (suffix.isEmpty())
+ suffix = QString(Period);
+ QString numberStr = QString::number(number) + suffix + Space;
+ if (numberStr.length() == 3)
+ numberStr += Space;
+ prefix += numberStr;
+ } else {
+ prefix += QLatin1String(bullet) + Space;
+ }
+ m_stream << prefix;
+ } else if (blockFmt.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) {
+ m_stream << "- - -\n"; // unambiguous horizontal rule, not an underline under a heading
+ return 0;
+ } else if (blockFmt.hasProperty(QTextFormat::BlockCodeFence) || blockFmt.stringProperty(QTextFormat::BlockCodeLanguage).length() > 0) {
+ // It's important to preserve blank lines in code blocks. But blank lines in code blocks
+ // inside block quotes are getting preserved anyway (along with the "> " prefix).
+ if (!blockFmt.hasProperty(QTextFormat::BlockQuoteLevel))
+ missedBlankCodeBlockLine = true; // only if we don't get any fragments below
+ if (!m_fencedCodeBlock) {
+ QString fenceChar = blockFmt.stringProperty(QTextFormat::BlockCodeFence);
+ if (fenceChar.isEmpty())
+ fenceChar = QLatin1String("`");
+ m_codeBlockFence = QString(3, fenceChar.at(0));
+ // A block quote can contain an indented code block, but not vice-versa.
+ m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space) << m_codeBlockFence
+ << Space << blockFmt.stringProperty(QTextFormat::BlockCodeLanguage) << Newline;
+ m_fencedCodeBlock = true;
+ }
+ } else if (!blockFmt.indent()) {
+ if (m_fencedCodeBlock) {
+ m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space)
+ << m_codeBlockFence << Newline;
+ m_fencedCodeBlock = false;
+ m_codeBlockFence.clear();
+ }
+ m_wrappedLineIndent = 0;
+ m_linePrefix.clear();
+ if (blockFmt.hasProperty(QTextFormat::BlockQuoteLevel)) {
+ int level = blockFmt.intProperty(QTextFormat::BlockQuoteLevel);
+ QString quoteMarker = QStringLiteral("> ");
+ m_linePrefix.reserve(level * 2);
+ for (int i = 0; i < level; ++i)
+ m_linePrefix += quoteMarker;
+ }
+ if (blockFmt.hasProperty(QTextFormat::BlockCodeLanguage)) {
+ // A block quote can contain an indented code block, but not vice-versa.
+ m_linePrefix += QString(4, Space);
+ m_indentedCodeBlock = true;
+ }
+ }
+ if (blockFmt.headingLevel())
+ m_stream << QByteArray(blockFmt.headingLevel(), '#') << ' ';
+ else
+ m_stream << m_linePrefix;
+
+ QString wrapIndentString = m_linePrefix + QString(m_wrappedLineIndent, Space);
+ // It would be convenient if QTextStream had a lineCharPos() accessor,
+ // to keep track of how many characters (not bytes) have been written on the current line,
+ // but it doesn't. So we have to keep track with this col variable.
+ int col = wrapIndentString.length();
+ bool mono = false;
+ bool startsOrEndsWithBacktick = false;
+ bool bold = false;
+ bool italic = false;
+ bool underline = false;
+ bool strikeOut = false;
+ QString backticks(Backtick);
+ for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) {
+ missedBlankCodeBlockLine = false;
+ QString fragmentText = frag.fragment().text();
+ while (fragmentText.endsWith(Newline))
+ fragmentText.chop(1);
+ if (block.textList()) { // <li>first line</br>continuation</li>
+ QString newlineIndent = QString(Newline) + QString(m_wrappedLineIndent, Space);
+ fragmentText.replace(QString(LineBreak), newlineIndent);
+ } else if (blockFmt.indent() > 0) { // <li>first line<p>continuation</p></li>
+ m_stream << QString(m_wrappedLineIndent, Space);
+ } else {
+ fragmentText.replace(LineBreak, Newline);
+ }
+ startsOrEndsWithBacktick |= fragmentText.startsWith(Backtick) || fragmentText.endsWith(Backtick);
+ QTextCharFormat fmt = frag.fragment().charFormat();
+ if (fmt.isImageFormat()) {
+ QTextImageFormat ifmt = fmt.toImageFormat();
+ QString desc = ifmt.stringProperty(QTextFormat::ImageAltText);
+ if (desc.isEmpty())
+ desc = QLatin1String("image");
+ QString s = QLatin1String("![") + desc + QLatin1String("](") + ifmt.name();
+ QString title = ifmt.stringProperty(QTextFormat::ImageTitle);
+ if (!title.isEmpty())
+ s += Space + DoubleQuote + title + DoubleQuote;
+ s += QLatin1Char(')');
+ if (wrap && col + s.length() > ColumnLimit) {
+ m_stream << Newline << wrapIndentString;
+ col = m_wrappedLineIndent;
+ }
+ m_stream << s;
+ col += s.length();
+ } else if (fmt.hasProperty(QTextFormat::AnchorHref)) {
+ QString s = QLatin1Char('[') + fragmentText + QLatin1String("](") +
+ fmt.property(QTextFormat::AnchorHref).toString() + QLatin1Char(')');
+ if (wrap && col + s.length() > ColumnLimit) {
+ m_stream << Newline << wrapIndentString;
+ col = m_wrappedLineIndent;
+ }
+ m_stream << s;
+ col += s.length();
+ } else {
+ QFontInfo fontInfo(fmt.font());
+ bool monoFrag = fontInfo.fixedPitch();
+ QString markers;
+ if (!ignoreFormat) {
+ if (monoFrag != mono && !m_indentedCodeBlock && !m_fencedCodeBlock) {
+ if (monoFrag)
+ backticks = QString(adjacentBackticksCount(fragmentText) + 1, Backtick);
+ markers += backticks;
+ if (startsOrEndsWithBacktick)
+ markers += Space;
+ mono = monoFrag;
+ }
+ if (!blockFmt.headingLevel() && !mono) {
+ if (fontInfo.bold() != bold) {
+ markers += QLatin1String("**");
+ bold = fontInfo.bold();
+ }
+ if (fontInfo.italic() != italic) {
+ markers += QLatin1Char('*');
+ italic = fontInfo.italic();
+ }
+ if (fontInfo.strikeOut() != strikeOut) {
+ markers += QLatin1String("~~");
+ strikeOut = fontInfo.strikeOut();
+ }
+ if (fontInfo.underline() != underline) {
+ // Markdown doesn't support underline, but the parser will treat a single underline
+ // the same as a single asterisk, and the marked fragment will be rendered in italics.
+ // That will have to do.
+ markers += QLatin1Char('_');
+ underline = fontInfo.underline();
+ }
+ }
+ }
+ if (wrap && col + markers.length() * 2 + fragmentText.length() > ColumnLimit) {
+ int i = 0;
+ int fragLen = fragmentText.length();
+ bool breakingLine = false;
+ while (i < fragLen) {
+ if (col >= ColumnLimit) {
+ m_stream << Newline << wrapIndentString;
+ col = m_wrappedLineIndent;
+ while (fragmentText[i].isSpace())
+ ++i;
+ }
+ int j = i + ColumnLimit - col;
+ if (j < fragLen) {
+ int wi = nearestWordWrapIndex(fragmentText, j);
+ if (wi < 0) {
+ j = fragLen;
+ } else if (wi >= i) {
+ j = wi;
+ breakingLine = true;
+ }
+ } else {
+ j = fragLen;
+ breakingLine = false;
+ }
+ QString subfrag = fragmentText.mid(i, j - i);
+ if (!i) {
+ m_stream << markers;
+ col += markers.length();
+ }
+ if (col == m_wrappedLineIndent)
+ maybeEscapeFirstChar(subfrag);
+ m_stream << subfrag;
+ if (breakingLine) {
+ m_stream << Newline << wrapIndentString;
+ col = m_wrappedLineIndent;
+ } else {
+ col += subfrag.length();
+ }
+ i = j + 1;
+ }
+ } else {
+ m_stream << markers << fragmentText;
+ col += markers.length() + fragmentText.length();
+ }
+ }
+ }
+ if (mono) {
+ if (startsOrEndsWithBacktick) {
+ m_stream << Space;
+ col += 1;
+ }
+ m_stream << backticks;
+ col += backticks.size();
+ }
+ if (bold) {
+ m_stream << "**";
+ col += 2;
+ }
+ if (italic) {
+ m_stream << "*";
+ col += 1;
+ }
+ if (underline) {
+ m_stream << "_";
+ col += 1;
+ }
+ if (strikeOut) {
+ m_stream << "~~";
+ col += 2;
+ }
+ if (missedBlankCodeBlockLine)
+ m_stream << Newline;
+ return col;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h
new file mode 100644
index 0000000000..90310250ac
--- /dev/null
+++ b/src/gui/text/qtextmarkdownwriter_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTMARKDOWNWRITER_P_H
+#define QTEXTMARKDOWNWRITER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include <QtCore/QTextStream>
+
+#include "qtextdocument_p.h"
+#include "qtextdocumentwriter.h"
+#include "QAbstractTableModel"
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QTextMarkdownWriter
+{
+public:
+ QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features);
+ bool writeAll(const QTextDocument *document);
+ void writeTable(const QAbstractItemModel *table);
+
+ int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat, bool ignoreEmpty);
+ void writeFrame(const QTextFrame *frame);
+
+private:
+ struct ListInfo {
+ bool loose;
+ };
+
+ ListInfo listInfo(QTextList *list);
+
+private:
+ QTextStream &m_stream;
+ QTextDocument::MarkdownFeatures m_features;
+ QMap<QTextList *, ListInfo> m_listInfo;
+ QString m_linePrefix;
+ QString m_codeBlockFence;
+ int m_wrappedLineIndent = 0;
+ int m_lastListIndent = 1;
+ bool m_doubleNewlineWritten = false;
+ bool m_indentedCodeBlock = false;
+ bool m_fencedCodeBlock = false;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTEXTMARKDOWNWRITER_P_H
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index 0ed8be8530..1302bd66bb 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -678,7 +678,7 @@ QTextFrame::iterator::iterator(QTextFrame *frame, int block, int begin, int end)
/*!
Copy constructor. Constructs a copy of the \a other iterator.
*/
-QTextFrame::iterator::iterator(const iterator &other) Q_DECL_NOTHROW
+QTextFrame::iterator::iterator(const iterator &other) noexcept
{
f = other.f;
b = other.b;
@@ -691,7 +691,7 @@ QTextFrame::iterator::iterator(const iterator &other) Q_DECL_NOTHROW
Assigns \a other to this iterator and returns a reference to
this iterator.
*/
-QTextFrame::iterator &QTextFrame::iterator::operator=(const iterator &other) Q_DECL_NOTHROW
+QTextFrame::iterator &QTextFrame::iterator::operator=(const iterator &other) noexcept
{
f = other.f;
b = other.b;
@@ -704,8 +704,8 @@ QTextFrame::iterator &QTextFrame::iterator::operator=(const iterator &other) Q_D
#endif
/*!
- Returns the current frame pointed to by the iterator, or 0 if the
- iterator currently points to a block.
+ Returns the current frame pointed to by the iterator, or \nullptr
+ if the iterator currently points to a block.
\sa currentBlock()
*/
@@ -1291,12 +1291,12 @@ QVector<QTextLayout::FormatRange> QTextBlock::textFormats() const
}
/*!
- Returns the text document this text block belongs to, or 0 if the
- text block does not belong to any document.
+ Returns the text document this text block belongs to, or \nullptr
+ if the text block does not belong to any document.
*/
const QTextDocument *QTextBlock::document() const
{
- return p ? p->document() : 0;
+ return p ? p->document() : nullptr;
}
/*!
@@ -1306,7 +1306,7 @@ const QTextDocument *QTextBlock::document() const
QTextList *QTextBlock::textList() const
{
if (!isValid())
- return 0;
+ return nullptr;
const QTextBlockFormat fmt = blockFormat();
QTextObject *obj = p->document()->objectForFormat(fmt);
@@ -1316,8 +1316,8 @@ QTextList *QTextBlock::textList() const
/*!
\since 4.1
- Returns a pointer to a QTextBlockUserData object if previously set with
- setUserData() or a null pointer.
+ Returns a pointer to a QTextBlockUserData object,
+ if one has been set with setUserData(), or \nullptr.
*/
QTextBlockUserData *QTextBlock::userData() const
{
diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h
index 067f8473ea..215a76fb4d 100644
--- a/src/gui/text/qtextobject.h
+++ b/src/gui/text/qtextobject.h
@@ -151,11 +151,11 @@ public:
public:
iterator(); // ### Qt 6: inline
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
- iterator(const iterator &o) Q_DECL_NOTHROW; // = default
- iterator &operator=(const iterator &o) Q_DECL_NOTHROW; // = default
- iterator(iterator &&other) Q_DECL_NOTHROW // = default
+ iterator(const iterator &o) noexcept; // = default
+ iterator &operator=(const iterator &o) noexcept; // = default
+ iterator(iterator &&other) noexcept // = default
{ memcpy(static_cast<void *>(this), static_cast<void *>(&other), sizeof(iterator)); }
- iterator &operator=(iterator &&other) Q_DECL_NOTHROW // = default
+ iterator &operator=(iterator &&other) noexcept // = default
{ memcpy(static_cast<void *>(this), static_cast<void *>(&other), sizeof(iterator)); return *this; }
#endif
@@ -263,6 +263,7 @@ public:
iterator() : p(nullptr), b(0), e(0), n(0) {}
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
iterator(const iterator &o) : p(o.p), b(o.b), e(o.e), n(o.n) {}
+ iterator &operator=(const iterator &o) = default;
#endif
QTextFragment fragment() const;
diff --git a/src/gui/text/qtextobject_p.h b/src/gui/text/qtextobject_p.h
index 81ab023cc3..87c83868da 100644
--- a/src/gui/text/qtextobject_p.h
+++ b/src/gui/text/qtextobject_p.h
@@ -93,7 +93,7 @@ class QTextFramePrivate : public QTextObjectPrivate
Q_DECLARE_PUBLIC(QTextFrame)
public:
QTextFramePrivate(QTextDocument *doc)
- : QTextObjectPrivate(doc), fragment_start(0), fragment_end(0), parentFrame(0), layoutData(0)
+ : QTextObjectPrivate(doc), fragment_start(0), fragment_end(0), parentFrame(nullptr), layoutData(nullptr)
{
}
virtual void fragmentAdded(QChar type, uint fragment);
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp
index 1906502c10..3561c185a6 100644
--- a/src/gui/text/qtextodfwriter.cpp
+++ b/src/gui/text/qtextodfwriter.cpp
@@ -90,7 +90,7 @@ public:
contentStream = device;
}
- virtual ~QXmlStreamStrategy()
+ ~QXmlStreamStrategy()
{
if (contentStream)
contentStream->close();
@@ -523,9 +523,7 @@ void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, const QSet<int> &for
{
writer.writeStartElement(officeNS, QString::fromLatin1("automatic-styles"));
QVector<QTextFormat> allStyles = m_document->allFormats();
- QSetIterator<int> formatId(formats);
- while(formatId.hasNext()) {
- int formatIndex = formatId.next();
+ for (int formatIndex : formats) {
QTextFormat textFormat = allStyles.at(formatIndex);
switch (textFormat.type()) {
case QTextFormat::CharFormat:
@@ -546,10 +544,12 @@ void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, const QSet<int> &for
else
writeFrameFormat(writer, textFormat.toFrameFormat(), formatIndex);
break;
+#if QT_DEPRECATED_SINCE(5, 3)
case QTextFormat::TableFormat:
// this case never happens, because TableFormat is a FrameFormat
Q_UNREACHABLE();
break;
+#endif
}
}
@@ -936,26 +936,30 @@ void QTextOdfWriter::tableCellStyleElement(QXmlStreamWriter &writer, const int &
if (hasBorder) {
writer.writeAttribute(foNS, QString::fromLatin1("border"),
pixelToPoint(tableFormatTmp.border()) + QLatin1String(" ")
- + borderStyleName(tableFormatTmp.borderStyle())
- + QLatin1String(" #000000")); //!! HARD-CODING color black
+ + borderStyleName(tableFormatTmp.borderStyle()) + QLatin1String(" ")
+ + tableFormatTmp.borderBrush().color().name(QColor::HexRgb));
}
- qreal padding = format.topPadding();
- if (padding > 0 && padding == format.bottomPadding()
- && padding == format.leftPadding() && padding == format.rightPadding()) {
+ qreal topPadding = format.topPadding();
+ qreal padding = topPadding + tableFormatTmp.cellPadding();
+ if (padding > 0 && topPadding == format.bottomPadding()
+ && topPadding == format.leftPadding() && topPadding == format.rightPadding()) {
writer.writeAttribute(foNS, QString::fromLatin1("padding"), pixelToPoint(padding));
}
else {
if (padding > 0)
writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding));
- if (format.bottomPadding() > 0)
+ padding = format.bottomPadding() + tableFormatTmp.cellPadding();
+ if (padding > 0)
writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"),
- pixelToPoint(format.bottomPadding()));
- if (format.leftPadding() > 0)
+ pixelToPoint(padding));
+ padding = format.leftPadding() + tableFormatTmp.cellPadding();
+ if (padding > 0)
writer.writeAttribute(foNS, QString::fromLatin1("padding-left"),
- pixelToPoint(format.leftPadding()));
- if (format.rightPadding() > 0)
+ pixelToPoint(padding));
+ padding = format.rightPadding() + tableFormatTmp.cellPadding();
+ if (padding > 0)
writer.writeAttribute(foNS, QString::fromLatin1("padding-right"),
- pixelToPoint(format.rightPadding()));
+ pixelToPoint(padding));
}
if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
@@ -1007,7 +1011,7 @@ bool QTextOdfWriter::writeAll()
m_strategy = new QXmlStreamStrategy(m_device);
if (!m_device->isWritable() && ! m_device->open(QIODevice::WriteOnly)) {
- qWarning("QTextOdfWriter::writeAll: the device can not be opened for writing");
+ qWarning("QTextOdfWriter::writeAll: the device cannot be opened for writing");
return false;
}
QXmlStreamWriter writer(m_strategy->contentStream);
@@ -1051,7 +1055,7 @@ bool QTextOdfWriter::writeAll()
// add objects for lists, frames and tables
const QVector<QTextFormat> allFormats = m_document->allFormats();
- const QList<int> copy = formats.toList();
+ const QList<int> copy = formats.values();
for (auto index : copy) {
QTextObject *object = m_document->objectForFormat(allFormats[index]);
if (object) {
diff --git a/src/gui/text/qtexttable_p.h b/src/gui/text/qtexttable_p.h
index c969e1d5bc..5c05611009 100644
--- a/src/gui/text/qtexttable_p.h
+++ b/src/gui/text/qtexttable_p.h
@@ -61,7 +61,7 @@ class QTextTablePrivate : public QTextFramePrivate
{
Q_DECLARE_PUBLIC(QTextTable)
public:
- QTextTablePrivate(QTextDocument *document) : QTextFramePrivate(document), grid(0), nRows(0), nCols(0), dirty(true), blockFragmentUpdates(false) {}
+ QTextTablePrivate(QTextDocument *document) : QTextFramePrivate(document), grid(nullptr), nRows(0), nCols(0), dirty(true), blockFragmentUpdates(false) {}
~QTextTablePrivate();
static QTextTable *createTable(QTextDocumentPrivate *, int pos, int rows, int cols, const QTextTableFormat &tableFormat);
diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h
index eed6ee6a62..6fec8d7719 100644
--- a/src/gui/text/qzipreader_p.h
+++ b/src/gui/text/qzipreader_p.h
@@ -79,11 +79,11 @@ public:
struct FileInfo
{
- FileInfo() Q_DECL_NOTHROW
+ FileInfo() noexcept
: isDir(false), isFile(false), isSymLink(false), crc(0), size(0)
{}
- bool isValid() const Q_DECL_NOTHROW { return isDir || isFile || isSymLink; }
+ bool isValid() const noexcept { return isDir || isFile || isSymLink; }
QString filePath;
uint isDir : 1;
@@ -116,7 +116,7 @@ public:
private:
QZipReaderPrivate *d;
- Q_DISABLE_COPY(QZipReader)
+ Q_DISABLE_COPY_MOVE(QZipReader)
};
Q_DECLARE_TYPEINFO(QZipReader::FileInfo, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QZipReader::Status, Q_PRIMITIVE_TYPE);
diff --git a/src/gui/text/qzipwriter_p.h b/src/gui/text/qzipwriter_p.h
index 433bbab31e..b3bb5929cf 100644
--- a/src/gui/text/qzipwriter_p.h
+++ b/src/gui/text/qzipwriter_p.h
@@ -108,7 +108,7 @@ public:
void close();
private:
QZipWriterPrivate *d;
- Q_DISABLE_COPY(QZipWriter)
+ Q_DISABLE_COPY_MOVE(QZipWriter)
};
QT_END_NAMESPACE
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index abe20abe02..5e97b312f1 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -97,6 +97,25 @@ qtConfig(textodfwriter) {
text/qzip.cpp
}
+qtConfig(textmarkdownreader) {
+ qtConfig(system-textmarkdownreader) {
+ QMAKE_USE += libmd4c
+ } else {
+ include($$PWD/../../3rdparty/md4c.pri)
+ }
+ HEADERS += \
+ text/qtextmarkdownimporter_p.h
+ SOURCES += \
+ text/qtextmarkdownimporter.cpp
+}
+
+qtConfig(textmarkdownwriter) {
+ HEADERS += \
+ text/qtextmarkdownwriter_p.h
+ SOURCES += \
+ text/qtextmarkdownwriter.cpp
+}
+
qtConfig(cssparser) {
HEADERS += \
text/qcssparser_p.h
diff --git a/src/gui/util/qastchandler.cpp b/src/gui/util/qastchandler.cpp
new file mode 100644
index 0000000000..6d163c6701
--- /dev/null
+++ b/src/gui/util/qastchandler.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qastchandler_p.h"
+#include "qtexturefiledata_p.h"
+
+#include <private/qnumeric_p.h>
+
+#include <QFile>
+#include <QDebug>
+#include <QSize>
+
+QT_BEGIN_NAMESPACE
+
+struct AstcHeader
+{
+ quint8 magic[4];
+ quint8 blockDimX;
+ quint8 blockDimY;
+ quint8 blockDimZ;
+ quint8 xSize[3];
+ quint8 ySize[3];
+ quint8 zSize[3];
+};
+
+bool QAstcHandler::canRead(const QByteArray &suffix, const QByteArray &block)
+{
+ Q_UNUSED(suffix)
+
+ return block.startsWith("\x13\xAB\xA1\x5C");
+}
+
+quint32 QAstcHandler::astcGLFormat(quint8 xBlockDim, quint8 yBlockDim) const
+{
+ static const quint32 glFormatRGBABase = 0x93B0; // GL_COMPRESSED_RGBA_ASTC_4x4_KHR
+ static const quint32 glFormatSRGBBase = 0x93D0; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
+
+ static QSize dims[14] = {
+ { 4, 4 }, // GL_COMPRESSED_xxx_ASTC_4x4_KHR
+ { 5, 4 }, // GL_COMPRESSED_xxx_ASTC_5x4_KHR
+ { 5, 5 }, // GL_COMPRESSED_xxx_ASTC_5x5_KHR
+ { 6, 5 }, // GL_COMPRESSED_xxx_ASTC_6x5_KHR
+ { 6, 6 }, // GL_COMPRESSED_xxx_ASTC_6x6_KHR
+ { 8, 5 }, // GL_COMPRESSED_xxx_ASTC_8x5_KHR
+ { 8, 6 }, // GL_COMPRESSED_xxx_ASTC_8x6_KHR
+ { 8, 8 }, // GL_COMPRESSED_xxx_ASTC_8x8_KHR
+ { 10, 5 }, // GL_COMPRESSED_xxx_ASTC_10x5_KHR
+ { 10, 6 }, // GL_COMPRESSED_xxx_ASTC_10x6_KHR
+ { 10, 8 }, // GL_COMPRESSED_xxx_ASTC_10x8_KHR
+ { 10, 10 }, // GL_COMPRESSED_xxx_ASTC_10x10_KHR
+ { 12, 10 }, // GL_COMPRESSED_xxx_ASTC_12x10_KHR
+ { 12, 12 } // GL_COMPRESSED_xxx_ASTC_12x12_KHR
+ };
+
+ const QSize dim(xBlockDim, yBlockDim);
+ int index = -1;
+ for (int i = 0; i < 14; i++) {
+ if (dim == dims[i]) {
+ index = i;
+ break;
+ }
+ }
+ if (index < 0)
+ return 0;
+
+ bool useSrgb = qEnvironmentVariableIsSet("QT_ASTCHANDLER_USE_SRGB")
+ || logName().toLower().contains("srgb");
+
+ return useSrgb ? (glFormatSRGBBase + index) : (glFormatRGBABase + index);
+}
+
+QTextureFileData QAstcHandler::read()
+{
+ QTextureFileData nullData;
+ QTextureFileData res;
+
+ if (!device())
+ return nullData;
+
+ QByteArray fileData = device()->readAll();
+ if (fileData.size() < int(sizeof(AstcHeader)) || !canRead(QByteArray(), fileData)) {
+ qCDebug(lcQtGuiTextureIO, "Not an ASTC file: %s", logName().constData());
+ return nullData;
+ }
+ res.setData(fileData);
+
+ const AstcHeader *header = reinterpret_cast<const AstcHeader *>(fileData.constData());
+
+ int xSz = int(header->xSize[0]) | int(header->xSize[1]) << 8 | int(header->xSize[2]) << 16;
+ int ySz = int(header->ySize[0]) | int(header->ySize[1]) << 8 | int(header->ySize[2]) << 16;
+ int zSz = int(header->zSize[0]) | int(header->zSize[1]) << 8 | int(header->zSize[2]) << 16;
+
+ quint32 glFmt = astcGLFormat(header->blockDimX, header->blockDimY);
+
+ if (!xSz || !ySz || !zSz || !glFmt || header->blockDimZ != 1) {
+ qCDebug(lcQtGuiTextureIO, "Invalid ASTC header data in file %s", logName().constData());
+ return nullData;
+ }
+
+ res.setSize(QSize(xSz, ySz));
+ res.setGLFormat(0); // 0 for compressed textures
+ res.setGLInternalFormat(glFmt);
+ //? BaseInternalFormat
+
+ int xBlocks = (xSz + header->blockDimX - 1) / header->blockDimX;
+ int yBlocks = (ySz + header->blockDimY - 1) / header->blockDimY;
+ int zBlocks = (zSz + header->blockDimZ - 1) / header->blockDimZ;
+
+ int byteCount = 0;
+ bool oob = mul_overflow(xBlocks, yBlocks, &byteCount)
+ || mul_overflow(byteCount, zBlocks, &byteCount)
+ || mul_overflow(byteCount, 16, &byteCount);
+
+
+ res.setDataOffset(sizeof(AstcHeader));
+ res.setNumLevels(1);
+ res.setDataLength(byteCount);
+
+ if (oob || !res.isValid()) {
+ qCDebug(lcQtGuiTextureIO, "Invalid ASTC file %s", logName().constData());
+ return nullData;
+ }
+
+ res.setLogName(logName());
+
+#if 0
+ qDebug() << "ASTC file handler read" << res << res.dataOffset() << res.dataLength();
+#endif
+ return res;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/mirclient/qmirclientplatformservices.h b/src/gui/util/qastchandler_p.h
index a1cd5758ca..398f1833b6 100644
--- a/src/plugins/platforms/mirclient/qmirclientplatformservices.h
+++ b/src/gui/util/qastchandler_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,21 +37,37 @@
**
****************************************************************************/
+#ifndef QASTCHANDLER_H
+#define QASTCHANDLER_H
-#ifndef QMIRCLIENTPLATFORMSERVICES_H
-#define QMIRCLIENTPLATFORMSERVICES_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
-#include <qpa/qplatformservices.h>
-#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
-#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
+#include "qtexturefilehandler_p.h"
-class QMirClientPlatformServices : public QPlatformServices {
+QT_BEGIN_NAMESPACE
+
+class QAstcHandler : public QTextureFileHandler
+{
public:
- bool openUrl(const QUrl &url) override;
- bool openDocument(const QUrl &url) override;
+ using QTextureFileHandler::QTextureFileHandler;
+
+ static bool canRead(const QByteArray &suffix, const QByteArray &block);
+
+ QTextureFileData read() override;
private:
- bool callDispatcher(const QUrl &url);
+ quint32 astcGLFormat(quint8 xBlockDim, quint8 yBlockDim) const;
};
-#endif // QMIRCLIENTPLATFORMSERVICES_H
+QT_END_NAMESPACE
+
+#endif // QASTCHANDLER_H
diff --git a/src/gui/util/qgridlayoutengine_p.h b/src/gui/util/qgridlayoutengine_p.h
index 5f0cc5da73..5f0e84edb1 100644
--- a/src/gui/util/qgridlayoutengine_p.h
+++ b/src/gui/util/qgridlayoutengine_p.h
@@ -180,7 +180,7 @@ public:
t = &q_minimumAscent;
break;
default:
- t = 0;
+ t = nullptr;
break;
}
return *t;
@@ -205,7 +205,7 @@ public:
t = &q_minimumAscent;
break;
default:
- t = 0;
+ t = nullptr;
break;
}
return *t;
@@ -276,7 +276,7 @@ class Q_GUI_EXPORT QGridLayoutItem
{
public:
QGridLayoutItem(int row, int column, int rowSpan = 1, int columnSpan = 1,
- Qt::Alignment alignment = 0);
+ Qt::Alignment alignment = nullptr);
virtual ~QGridLayoutItem() {}
inline int firstRow() const { return q_firstRows[Ver]; }
@@ -339,7 +339,7 @@ private:
class Q_GUI_EXPORT QGridLayoutEngine
{
public:
- QGridLayoutEngine(Qt::Alignment defaultAlignment = Qt::Alignment(0), bool snapToPixelGrid = false);
+ QGridLayoutEngine(Qt::Alignment defaultAlignment = Qt::Alignment(nullptr), bool snapToPixelGrid = false);
inline ~QGridLayoutEngine() { qDeleteAll(q_items); }
int rowCount(Qt::Orientation orientation) const;
diff --git a/src/gui/util/qlayoutpolicy_p.h b/src/gui/util/qlayoutpolicy_p.h
index d92896e6e3..6457aeb653 100644
--- a/src/gui/util/qlayoutpolicy_p.h
+++ b/src/gui/util/qlayoutpolicy_p.h
@@ -66,6 +66,7 @@ class QVariant;
class Q_GUI_EXPORT QLayoutPolicy
{
+ Q_GADGET
Q_ENUMS(Policy)
public:
diff --git a/src/gui/util/qshaderformat.cpp b/src/gui/util/qshaderformat.cpp
index e4e3718199..ea86dd6ca5 100644
--- a/src/gui/util/qshaderformat.cpp
+++ b/src/gui/util/qshaderformat.cpp
@@ -41,59 +41,59 @@
QT_BEGIN_NAMESPACE
-QShaderFormat::QShaderFormat() Q_DECL_NOTHROW
+QShaderFormat::QShaderFormat() noexcept
: m_api(NoApi)
, m_shaderType(Fragment)
{
}
-QShaderFormat::Api QShaderFormat::api() const Q_DECL_NOTHROW
+QShaderFormat::Api QShaderFormat::api() const noexcept
{
return m_api;
}
-void QShaderFormat::setApi(QShaderFormat::Api api) Q_DECL_NOTHROW
+void QShaderFormat::setApi(QShaderFormat::Api api) noexcept
{
m_api = api;
}
-QVersionNumber QShaderFormat::version() const Q_DECL_NOTHROW
+QVersionNumber QShaderFormat::version() const noexcept
{
return m_version;
}
-void QShaderFormat::setVersion(const QVersionNumber &version) Q_DECL_NOTHROW
+void QShaderFormat::setVersion(const QVersionNumber &version) noexcept
{
m_version = version;
}
-QStringList QShaderFormat::extensions() const Q_DECL_NOTHROW
+QStringList QShaderFormat::extensions() const noexcept
{
return m_extensions;
}
-void QShaderFormat::setExtensions(const QStringList &extensions) Q_DECL_NOTHROW
+void QShaderFormat::setExtensions(const QStringList &extensions) noexcept
{
m_extensions = extensions;
m_extensions.sort();
}
-QString QShaderFormat::vendor() const Q_DECL_NOTHROW
+QString QShaderFormat::vendor() const noexcept
{
return m_vendor;
}
-void QShaderFormat::setVendor(const QString &vendor) Q_DECL_NOTHROW
+void QShaderFormat::setVendor(const QString &vendor) noexcept
{
m_vendor = vendor;
}
-bool QShaderFormat::isValid() const Q_DECL_NOTHROW
+bool QShaderFormat::isValid() const noexcept
{
return m_api != NoApi && m_version.majorVersion() > 0;
}
-bool QShaderFormat::supports(const QShaderFormat &other) const Q_DECL_NOTHROW
+bool QShaderFormat::supports(const QShaderFormat &other) const noexcept
{
if (!isValid() || !other.isValid())
return false;
@@ -133,7 +133,7 @@ void QShaderFormat::setShaderType(QShaderFormat::ShaderType shaderType) Q_DECL_N
m_shaderType = shaderType;
}
-bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW
+bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept
{
return lhs.api() == rhs.api()
&& lhs.version() == rhs.version()
diff --git a/src/gui/util/qshaderformat_p.h b/src/gui/util/qshaderformat_p.h
index 8d5e83bd22..c50d7d5729 100644
--- a/src/gui/util/qshaderformat_p.h
+++ b/src/gui/util/qshaderformat_p.h
@@ -78,22 +78,22 @@ public:
Compute
};
- Q_GUI_EXPORT QShaderFormat() Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QShaderFormat() noexcept;
- Q_GUI_EXPORT Api api() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT void setApi(Api api) Q_DECL_NOTHROW;
+ Q_GUI_EXPORT Api api() const noexcept;
+ Q_GUI_EXPORT void setApi(Api api) noexcept;
- Q_GUI_EXPORT QVersionNumber version() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT void setVersion(const QVersionNumber &version) Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QVersionNumber version() const noexcept;
+ Q_GUI_EXPORT void setVersion(const QVersionNumber &version) noexcept;
- Q_GUI_EXPORT QStringList extensions() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT void setExtensions(const QStringList &extensions) Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QStringList extensions() const noexcept;
+ Q_GUI_EXPORT void setExtensions(const QStringList &extensions) noexcept;
- Q_GUI_EXPORT QString vendor() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT void setVendor(const QString &vendor) Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QString vendor() const noexcept;
+ Q_GUI_EXPORT void setVendor(const QString &vendor) noexcept;
- Q_GUI_EXPORT bool isValid() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT bool supports(const QShaderFormat &other) const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT bool isValid() const noexcept;
+ Q_GUI_EXPORT bool supports(const QShaderFormat &other) const noexcept;
Q_GUI_EXPORT ShaderType shaderType() const Q_DECL_NOTHROW;
Q_GUI_EXPORT void setShaderType(ShaderType shaderType) Q_DECL_NOTHROW;
@@ -106,9 +106,9 @@ private:
ShaderType m_shaderType;
};
-Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept;
-inline bool operator!=(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW
+inline bool operator!=(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept
{
return !(lhs == rhs);
}
diff --git a/src/gui/util/qshadergraph.cpp b/src/gui/util/qshadergraph.cpp
index 40b85ac469..b05b710713 100644
--- a/src/gui/util/qshadergraph.cpp
+++ b/src/gui/util/qshadergraph.cpp
@@ -118,12 +118,12 @@ namespace
}
}
-QUuid QShaderGraph::Statement::uuid() const Q_DECL_NOTHROW
+QUuid QShaderGraph::Statement::uuid() const noexcept
{
return node.uuid();
}
-int QShaderGraph::Statement::portIndex(QShaderNodePort::Direction direction, const QString &portName) const Q_DECL_NOTHROW
+int QShaderGraph::Statement::portIndex(QShaderNodePort::Direction direction, const QString &portName) const noexcept
{
const QVector<QShaderNodePort> ports = node.ports();
int index = 0;
@@ -150,7 +150,7 @@ void QShaderGraph::removeNode(const QShaderNode &node)
m_nodes.erase(it);
}
-QVector<QShaderNode> QShaderGraph::nodes() const Q_DECL_NOTHROW
+QVector<QShaderNode> QShaderGraph::nodes() const noexcept
{
return m_nodes;
}
@@ -167,7 +167,7 @@ void QShaderGraph::removeEdge(const QShaderGraph::Edge &edge)
m_edges.removeAll(edge);
}
-QVector<QShaderGraph::Edge> QShaderGraph::edges() const Q_DECL_NOTHROW
+QVector<QShaderGraph::Edge> QShaderGraph::edges() const noexcept
{
return m_edges;
}
@@ -244,7 +244,7 @@ QVector<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringLis
return result;
}
-bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) Q_DECL_NOTHROW
+bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept
{
return lhs.sourceNodeUuid == rhs.sourceNodeUuid
&& lhs.sourcePortName == rhs.sourcePortName
@@ -252,7 +252,7 @@ bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) Q_
&& lhs.targetPortName == rhs.targetPortName;
}
-bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) Q_DECL_NOTHROW
+bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept
{
return lhs.inputs == rhs.inputs
&& lhs.outputs == rhs.outputs
diff --git a/src/gui/util/qshadergraph_p.h b/src/gui/util/qshadergraph_p.h
index 756e1b2da2..9367a3783c 100644
--- a/src/gui/util/qshadergraph_p.h
+++ b/src/gui/util/qshadergraph_p.h
@@ -73,8 +73,8 @@ public:
class Statement
{
public:
- Q_GUI_EXPORT QUuid uuid() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT int portIndex(QShaderNodePort::Direction direction, const QString &portName) const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QUuid uuid() const noexcept;
+ Q_GUI_EXPORT int portIndex(QShaderNodePort::Direction direction, const QString &portName) const noexcept;
QShaderNode node;
QVector<int> inputs;
@@ -83,11 +83,11 @@ public:
Q_GUI_EXPORT void addNode(const QShaderNode &node);
Q_GUI_EXPORT void removeNode(const QShaderNode &node);
- Q_GUI_EXPORT QVector<QShaderNode> nodes() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QVector<QShaderNode> nodes() const noexcept;
Q_GUI_EXPORT void addEdge(const Edge &edge);
Q_GUI_EXPORT void removeEdge(const Edge &edge);
- Q_GUI_EXPORT QVector<Edge> edges() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QVector<Edge> edges() const noexcept;
Q_GUI_EXPORT QVector<Statement> createStatements(const QStringList &enabledLayers = QStringList()) const;
@@ -96,16 +96,16 @@ private:
QVector<Edge> m_edges;
};
-Q_GUI_EXPORT bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept;
-inline bool operator!=(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) Q_DECL_NOTHROW
+inline bool operator!=(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept
{
return !(lhs == rhs);
}
-Q_GUI_EXPORT bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept;
-inline bool operator!=(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) Q_DECL_NOTHROW
+inline bool operator!=(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept
{
return !(lhs == rhs);
}
diff --git a/src/gui/util/qshadergraphloader.cpp b/src/gui/util/qshadergraphloader.cpp
index b9d8318655..a393e876e0 100644
--- a/src/gui/util/qshadergraphloader.cpp
+++ b/src/gui/util/qshadergraphloader.cpp
@@ -52,29 +52,29 @@ QT_BEGIN_NAMESPACE
void qt_register_ShaderLanguage_enums();
-QShaderGraphLoader::QShaderGraphLoader() Q_DECL_NOTHROW
+QShaderGraphLoader::QShaderGraphLoader() noexcept
: m_status(Null),
m_device(nullptr)
{
qt_register_ShaderLanguage_enums();
}
-QShaderGraphLoader::Status QShaderGraphLoader::status() const Q_DECL_NOTHROW
+QShaderGraphLoader::Status QShaderGraphLoader::status() const noexcept
{
return m_status;
}
-QShaderGraph QShaderGraphLoader::graph() const Q_DECL_NOTHROW
+QShaderGraph QShaderGraphLoader::graph() const noexcept
{
return m_graph;
}
-QIODevice *QShaderGraphLoader::device() const Q_DECL_NOTHROW
+QIODevice *QShaderGraphLoader::device() const noexcept
{
return m_device;
}
-void QShaderGraphLoader::setDevice(QIODevice *device) Q_DECL_NOTHROW
+void QShaderGraphLoader::setDevice(QIODevice *device) noexcept
{
m_device = device;
m_graph = QShaderGraph();
@@ -83,12 +83,12 @@ void QShaderGraphLoader::setDevice(QIODevice *device) Q_DECL_NOTHROW
: Error;
}
-QHash<QString, QShaderNode> QShaderGraphLoader::prototypes() const Q_DECL_NOTHROW
+QHash<QString, QShaderNode> QShaderGraphLoader::prototypes() const noexcept
{
return m_prototypes;
}
-void QShaderGraphLoader::setPrototypes(const QHash<QString, QShaderNode> &prototypes) Q_DECL_NOTHROW
+void QShaderGraphLoader::setPrototypes(const QHash<QString, QShaderNode> &prototypes) noexcept
{
m_prototypes = prototypes;
}
diff --git a/src/gui/util/qshadergraphloader_p.h b/src/gui/util/qshadergraphloader_p.h
index 97cbd8d18c..e7aa19fa2d 100644
--- a/src/gui/util/qshadergraphloader_p.h
+++ b/src/gui/util/qshadergraphloader_p.h
@@ -69,16 +69,16 @@ public:
Error
};
- Q_GUI_EXPORT QShaderGraphLoader() Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QShaderGraphLoader() noexcept;
- Q_GUI_EXPORT Status status() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT QShaderGraph graph() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT Status status() const noexcept;
+ Q_GUI_EXPORT QShaderGraph graph() const noexcept;
- Q_GUI_EXPORT QIODevice *device() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT void setDevice(QIODevice *device) Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QIODevice *device() const noexcept;
+ Q_GUI_EXPORT void setDevice(QIODevice *device) noexcept;
- Q_GUI_EXPORT QHash<QString, QShaderNode> prototypes() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT void setPrototypes(const QHash<QString, QShaderNode> &prototypes) Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QHash<QString, QShaderNode> prototypes() const noexcept;
+ Q_GUI_EXPORT void setPrototypes(const QHash<QString, QShaderNode> &prototypes) noexcept;
Q_GUI_EXPORT void load();
diff --git a/src/gui/util/qshadernode.cpp b/src/gui/util/qshadernode.cpp
index e570880d1d..547e5c51a8 100644
--- a/src/gui/util/qshadernode.cpp
+++ b/src/gui/util/qshadernode.cpp
@@ -41,7 +41,7 @@
QT_BEGIN_NAMESPACE
-QShaderNode::Type QShaderNode::type() const Q_DECL_NOTHROW
+QShaderNode::Type QShaderNode::type() const noexcept
{
int inputCount = 0;
int outputCount = 0;
@@ -62,27 +62,27 @@ QShaderNode::Type QShaderNode::type() const Q_DECL_NOTHROW
: Function;
}
-QUuid QShaderNode::uuid() const Q_DECL_NOTHROW
+QUuid QShaderNode::uuid() const noexcept
{
return m_uuid;
}
-void QShaderNode::setUuid(const QUuid &uuid) Q_DECL_NOTHROW
+void QShaderNode::setUuid(const QUuid &uuid) noexcept
{
m_uuid = uuid;
}
-QStringList QShaderNode::layers() const Q_DECL_NOTHROW
+QStringList QShaderNode::layers() const noexcept
{
return m_layers;
}
-void QShaderNode::setLayers(const QStringList &layers) Q_DECL_NOTHROW
+void QShaderNode::setLayers(const QStringList &layers) noexcept
{
m_layers = layers;
}
-QVector<QShaderNodePort> QShaderNode::ports() const Q_DECL_NOTHROW
+QVector<QShaderNodePort> QShaderNode::ports() const noexcept
{
return m_ports;
}
@@ -157,13 +157,13 @@ QShaderNode::Rule QShaderNode::rule(const QShaderFormat &format) const
return it != m_rules.crend() ? it->second : Rule();
}
-QShaderNode::Rule::Rule(const QByteArray &subs, const QByteArrayList &snippets) Q_DECL_NOTHROW
+QShaderNode::Rule::Rule(const QByteArray &subs, const QByteArrayList &snippets) noexcept
: substitution(subs),
headerSnippets(snippets)
{
}
-bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) Q_DECL_NOTHROW
+bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept
{
return lhs.substitution == rhs.substitution
&& lhs.headerSnippets == rhs.headerSnippets;
diff --git a/src/gui/util/qshadernode_p.h b/src/gui/util/qshadernode_p.h
index 12ff9b2a2c..c3d149d8a5 100644
--- a/src/gui/util/qshadernode_p.h
+++ b/src/gui/util/qshadernode_p.h
@@ -73,21 +73,21 @@ public:
class Rule
{
public:
- Q_GUI_EXPORT Rule(const QByteArray &substitution = QByteArray(), const QByteArrayList &headerSnippets = QByteArrayList()) Q_DECL_NOTHROW;
+ Q_GUI_EXPORT Rule(const QByteArray &substitution = QByteArray(), const QByteArrayList &headerSnippets = QByteArrayList()) noexcept;
QByteArray substitution;
QByteArrayList headerSnippets;
};
- Q_GUI_EXPORT Type type() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT Type type() const noexcept;
- Q_GUI_EXPORT QUuid uuid() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT void setUuid(const QUuid &uuid) Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QUuid uuid() const noexcept;
+ Q_GUI_EXPORT void setUuid(const QUuid &uuid) noexcept;
- Q_GUI_EXPORT QStringList layers() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT void setLayers(const QStringList &layers) Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QStringList layers() const noexcept;
+ Q_GUI_EXPORT void setLayers(const QStringList &layers) noexcept;
- Q_GUI_EXPORT QVector<QShaderNodePort> ports() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QVector<QShaderNodePort> ports() const noexcept;
Q_GUI_EXPORT void addPort(const QShaderNodePort &port);
Q_GUI_EXPORT void removePort(const QShaderNodePort &port);
@@ -110,9 +110,9 @@ private:
QVector<QPair<QShaderFormat, QShaderNode::Rule>> m_rules;
};
-Q_GUI_EXPORT bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept;
-inline bool operator!=(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) Q_DECL_NOTHROW
+inline bool operator!=(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept
{
return !(lhs == rhs);
}
diff --git a/src/gui/util/qshadernodeport.cpp b/src/gui/util/qshadernodeport.cpp
index 03646a9467..15dbc4160e 100644
--- a/src/gui/util/qshadernodeport.cpp
+++ b/src/gui/util/qshadernodeport.cpp
@@ -41,12 +41,12 @@
QT_BEGIN_NAMESPACE
-QShaderNodePort::QShaderNodePort() Q_DECL_NOTHROW
+QShaderNodePort::QShaderNodePort() noexcept
: direction(Output)
{
}
-bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) Q_DECL_NOTHROW
+bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept
{
return lhs.direction == rhs.direction
&& lhs.name == rhs.name;
diff --git a/src/gui/util/qshadernodeport_p.h b/src/gui/util/qshadernodeport_p.h
index cfdaf05017..c69ba23a3f 100644
--- a/src/gui/util/qshadernodeport_p.h
+++ b/src/gui/util/qshadernodeport_p.h
@@ -66,15 +66,15 @@ public:
Output
};
- Q_GUI_EXPORT QShaderNodePort() Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QShaderNodePort() noexcept;
QShaderNodePort::Direction direction;
QString name;
};
-Q_GUI_EXPORT bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) Q_DECL_NOTHROW;
+Q_GUI_EXPORT bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept;
-inline bool operator!=(const QShaderNodePort &lhs, const QShaderNodePort &rhs) Q_DECL_NOTHROW
+inline bool operator!=(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept
{
return !(lhs == rhs);
}
diff --git a/src/gui/util/qshadernodesloader.cpp b/src/gui/util/qshadernodesloader.cpp
index 5369e8bd4c..922479332c 100644
--- a/src/gui/util/qshadernodesloader.cpp
+++ b/src/gui/util/qshadernodesloader.cpp
@@ -48,28 +48,28 @@
QT_BEGIN_NAMESPACE
-QShaderNodesLoader::QShaderNodesLoader() Q_DECL_NOTHROW
+QShaderNodesLoader::QShaderNodesLoader() noexcept
: m_status(Null),
m_device(nullptr)
{
}
-QShaderNodesLoader::Status QShaderNodesLoader::status() const Q_DECL_NOTHROW
+QShaderNodesLoader::Status QShaderNodesLoader::status() const noexcept
{
return m_status;
}
-QHash<QString, QShaderNode> QShaderNodesLoader::nodes() const Q_DECL_NOTHROW
+QHash<QString, QShaderNode> QShaderNodesLoader::nodes() const noexcept
{
return m_nodes;
}
-QIODevice *QShaderNodesLoader::device() const Q_DECL_NOTHROW
+QIODevice *QShaderNodesLoader::device() const noexcept
{
return m_device;
}
-void QShaderNodesLoader::setDevice(QIODevice *device) Q_DECL_NOTHROW
+void QShaderNodesLoader::setDevice(QIODevice *device) noexcept
{
m_device = device;
m_nodes.clear();
diff --git a/src/gui/util/qshadernodesloader_p.h b/src/gui/util/qshadernodesloader_p.h
index 0bec871857..432d7d4494 100644
--- a/src/gui/util/qshadernodesloader_p.h
+++ b/src/gui/util/qshadernodesloader_p.h
@@ -69,13 +69,13 @@ public:
Error
};
- Q_GUI_EXPORT QShaderNodesLoader() Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QShaderNodesLoader() noexcept;
- Q_GUI_EXPORT Status status() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT QHash<QString, QShaderNode> nodes() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT Status status() const noexcept;
+ Q_GUI_EXPORT QHash<QString, QShaderNode> nodes() const noexcept;
- Q_GUI_EXPORT QIODevice *device() const Q_DECL_NOTHROW;
- Q_GUI_EXPORT void setDevice(QIODevice *device) Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QIODevice *device() const noexcept;
+ Q_GUI_EXPORT void setDevice(QIODevice *device) noexcept;
Q_GUI_EXPORT void load();
Q_GUI_EXPORT void load(const QJsonObject &prototypesObject);
diff --git a/src/gui/util/qtexturefilereader.cpp b/src/gui/util/qtexturefilereader.cpp
index 5d4bd600e0..fefb957323 100644
--- a/src/gui/util/qtexturefilereader.cpp
+++ b/src/gui/util/qtexturefilereader.cpp
@@ -41,6 +41,7 @@
#include "qpkmhandler_p.h"
#include "qktxhandler_p.h"
+#include "qastchandler_p.h"
#include <QFileInfo>
@@ -80,6 +81,8 @@ bool QTextureFileReader::canRead()
m_handler = new QPkmHandler(m_device, logName);
} else if (QKtxHandler::canRead(suffix, headerBlock)) {
m_handler = new QKtxHandler(m_device, logName);
+ } else if (QAstcHandler::canRead(suffix, headerBlock)) {
+ m_handler = new QAstcHandler(m_device, logName);
}
// else if OtherHandler::canRead() ...etc.
}
@@ -89,7 +92,7 @@ bool QTextureFileReader::canRead()
QList<QByteArray> QTextureFileReader::supportedFileFormats()
{
// Hardcoded for now
- return {QByteArrayLiteral("pkm"), QByteArrayLiteral("ktx")};
+ return {QByteArrayLiteral("pkm"), QByteArrayLiteral("ktx"), QByteArrayLiteral("astc")};
}
bool QTextureFileReader::init()
diff --git a/src/gui/util/qvalidator.h b/src/gui/util/qvalidator.h
index cc7cbcb559..f0e72e3814 100644
--- a/src/gui/util/qvalidator.h
+++ b/src/gui/util/qvalidator.h
@@ -69,6 +69,7 @@ public:
Intermediate,
Acceptable
};
+ Q_ENUM(State)
void setLocale(const QLocale &locale);
QLocale locale() const;
diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri
index 6324642505..d3402133d6 100644
--- a/src/gui/util/util.pri
+++ b/src/gui/util/util.pri
@@ -8,7 +8,6 @@ HEADERS += \
util/qabstractlayoutstyleinfo_p.h \
util/qlayoutpolicy_p.h \
util/qshaderformat_p.h \
- util/qshadergenerator_p.h \
util/qshadergraph_p.h \
util/qshadergraphloader_p.h \
util/qshaderlanguage_p.h \
@@ -19,7 +18,8 @@ HEADERS += \
util/qtexturefilereader_p.h \
util/qtexturefilehandler_p.h \
util/qpkmhandler_p.h \
- util/qktxhandler_p.h
+ util/qktxhandler_p.h \
+ util/qastchandler_p.h
SOURCES += \
util/qdesktopservices.cpp \
@@ -28,7 +28,6 @@ SOURCES += \
util/qabstractlayoutstyleinfo.cpp \
util/qlayoutpolicy.cpp \
util/qshaderformat.cpp \
- util/qshadergenerator.cpp \
util/qshadergraph.cpp \
util/qshadergraphloader.cpp \
util/qshaderlanguage.cpp \
@@ -38,4 +37,12 @@ SOURCES += \
util/qtexturefiledata.cpp \
util/qtexturefilereader.cpp \
util/qpkmhandler.cpp \
- util/qktxhandler.cpp
+ util/qktxhandler.cpp \
+ util/qastchandler.cpp
+
+qtConfig(regularexpression) {
+ HEADERS += \
+ util/qshadergenerator_p.h
+ SOURCES += \
+ util/qshadergenerator.cpp
+}
diff --git a/src/gui/vulkan/qplatformvulkaninstance.cpp b/src/gui/vulkan/qplatformvulkaninstance.cpp
index 6201d3ec11..9d044bfd58 100644
--- a/src/gui/vulkan/qplatformvulkaninstance.cpp
+++ b/src/gui/vulkan/qplatformvulkaninstance.cpp
@@ -85,4 +85,9 @@ void QPlatformVulkanInstance::presentQueued(QWindow *window)
Q_UNUSED(window);
}
+void QPlatformVulkanInstance::setDebugFilters(const QVector<QVulkanInstance::DebugFilter> &filters)
+{
+ Q_UNUSED(filters);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/vulkan/qplatformvulkaninstance.h b/src/gui/vulkan/qplatformvulkaninstance.h
index 9f34803f7b..d47c59b5db 100644
--- a/src/gui/vulkan/qplatformvulkaninstance.h
+++ b/src/gui/vulkan/qplatformvulkaninstance.h
@@ -78,6 +78,7 @@ public:
virtual PFN_vkVoidFunction getInstanceProcAddr(const char *name) = 0;
virtual bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) = 0;
virtual void presentQueued(QWindow *window);
+ virtual void setDebugFilters(const QVector<QVulkanInstance::DebugFilter> &filters);
private:
QScopedPointer<QPlatformVulkanInstancePrivate> d_ptr;
diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp
index 000c2b8caa..0605d88cca 100644
--- a/src/gui/vulkan/qvulkaninstance.cpp
+++ b/src/gui/vulkan/qvulkaninstance.cpp
@@ -269,6 +269,7 @@ public:
VkResult errorCode;
QScopedPointer<QVulkanFunctions> funcs;
QHash<VkDevice, QVulkanDeviceFunctions *> deviceFuncs;
+ QVector<QVulkanInstance::DebugFilter> debugFilters;
};
bool QVulkanInstancePrivate::ensureVulkan()
@@ -306,7 +307,7 @@ QVulkanInstance::QVulkanInstance()
/*!
Destructor.
- \note current() will return \c nullptr once the instance is destroyed.
+ \note current() will return \nullptr once the instance is destroyed.
*/
QVulkanInstance::~QVulkanInstance()
{
@@ -570,6 +571,7 @@ bool QVulkanInstance::create()
d_ptr->extensions = d_ptr->platformInst->enabledExtensions();
d_ptr->errorCode = VK_SUCCESS;
d_ptr->funcs.reset(new QVulkanFunctions(this));
+ d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters);
return true;
}
@@ -614,7 +616,7 @@ VkResult QVulkanInstance::errorCode() const
}
/*!
- \return the VkInstance handle this QVulkanInstance wraps, or \c null if
+ \return the VkInstance handle this QVulkanInstance wraps, or \nullptr if
create() has not yet been successfully called and no existing instance has
been provided via setVkInstance().
*/
@@ -785,6 +787,50 @@ void QVulkanInstance::presentQueued(QWindow *window)
d_ptr->platformInst->presentQueued(window);
}
+/*!
+ \typedef QVulkanInstance::DebugFilter
+
+ Typedef for debug filtering callback functions.
+
+ \sa installDebugOutputFilter(), removeDebugOutputFilter()
+ */
+
+/*!
+ Installs a \a filter function that is called for every Vulkan debug
+ message. When the callback returns \c true, the message is stopped (filtered
+ out) and will not appear on the debug output.
+
+ \note Filtering is only effective when NoDebugOutputRedirect is not
+ \l{setFlags()}{set}. Installing filters has no effect otherwise.
+
+ \note This function can be called before create().
+
+ \sa removeDebugOutputFilter()
+ */
+void QVulkanInstance::installDebugOutputFilter(DebugFilter filter)
+{
+ if (!d_ptr->debugFilters.contains(filter)) {
+ d_ptr->debugFilters.append(filter);
+ if (d_ptr->platformInst)
+ d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters);
+ }
+}
+
+/*!
+ Removes a \a filter function previously installed by
+ installDebugOutputFilter().
+
+ \note This function can be called before create().
+
+ \sa installDebugOutputFilter()
+ */
+void QVulkanInstance::removeDebugOutputFilter(DebugFilter filter)
+{
+ d_ptr->debugFilters.removeOne(filter);
+ if (d_ptr->platformInst)
+ d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters);
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QVulkanLayer &layer)
{
diff --git a/src/gui/vulkan/qvulkaninstance.h b/src/gui/vulkan/qvulkaninstance.h
index 57459e458c..70f2fd5102 100644
--- a/src/gui/vulkan/qvulkaninstance.h
+++ b/src/gui/vulkan/qvulkaninstance.h
@@ -84,14 +84,14 @@ struct QVulkanLayer
};
Q_DECLARE_TYPEINFO(QVulkanLayer, Q_MOVABLE_TYPE);
-inline bool operator==(const QVulkanLayer &lhs, const QVulkanLayer &rhs) Q_DECL_NOTHROW
+inline bool operator==(const QVulkanLayer &lhs, const QVulkanLayer &rhs) noexcept
{
return lhs.name == rhs.name && lhs.version == rhs.version && lhs.specVersion == rhs.specVersion;
}
-inline bool operator!=(const QVulkanLayer &lhs, const QVulkanLayer &rhs) Q_DECL_NOTHROW
+inline bool operator!=(const QVulkanLayer &lhs, const QVulkanLayer &rhs) noexcept
{ return !(lhs == rhs); }
-inline uint qHash(const QVulkanLayer &key, uint seed = 0) Q_DECL_NOTHROW
+inline uint qHash(const QVulkanLayer &key, uint seed = 0) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.name);
@@ -107,14 +107,14 @@ struct QVulkanExtension
};
Q_DECLARE_TYPEINFO(QVulkanExtension, Q_MOVABLE_TYPE);
-inline bool operator==(const QVulkanExtension &lhs, const QVulkanExtension &rhs) Q_DECL_NOTHROW
+inline bool operator==(const QVulkanExtension &lhs, const QVulkanExtension &rhs) noexcept
{
return lhs.name == rhs.name && lhs.version == rhs.version;
}
-inline bool operator!=(const QVulkanExtension &lhs, const QVulkanExtension &rhs) Q_DECL_NOTHROW
+inline bool operator!=(const QVulkanExtension &lhs, const QVulkanExtension &rhs) noexcept
{ return !(lhs == rhs); }
-inline uint qHash(const QVulkanExtension &key, uint seed = 0) Q_DECL_NOTHROW
+inline uint qHash(const QVulkanExtension &key, uint seed = 0) noexcept
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.name);
@@ -188,6 +188,11 @@ public:
void presentQueued(QWindow *window);
+ typedef bool (*DebugFilter)(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object,
+ size_t location, int32_t messageCode, const char *pLayerPrefix, const char *pMessage);
+ void installDebugOutputFilter(DebugFilter filter);
+ void removeDebugOutputFilter(DebugFilter filter);
+
private:
QScopedPointer<QVulkanInstancePrivate> d_ptr;
Q_DISABLE_COPY(QVulkanInstance)
diff --git a/src/gui/vulkan/qvulkanwindow_p.h b/src/gui/vulkan/qvulkanwindow_p.h
index c6a772bc31..fb374a5564 100644
--- a/src/gui/vulkan/qvulkanwindow_p.h
+++ b/src/gui/vulkan/qvulkanwindow_p.h
@@ -97,7 +97,7 @@ public:
int physDevIndex = 0;
QVector<VkPhysicalDevice> physDevs;
QVector<VkPhysicalDeviceProperties> physDevProps;
- QVulkanWindow::Flags flags = 0;
+ QVulkanWindow::Flags flags = nullptr;
QByteArrayList requestedDevExtensions;
QHash<VkPhysicalDevice, QVulkanInfoVector<QVulkanExtension> > supportedDevExtensions;
QVector<VkFormat> requestedColorFormats;
diff --git a/src/network/access/http2/bitstreams_p.h b/src/network/access/http2/bitstreams_p.h
index 9eba319dc2..ca272062a6 100644
--- a/src/network/access/http2/bitstreams_p.h
+++ b/src/network/access/http2/bitstreams_p.h
@@ -89,7 +89,7 @@ public:
void clear();
private:
- Q_DISABLE_COPY(BitOStream);
+ Q_DISABLE_COPY_MOVE(BitOStream);
std::vector<uchar> &buffer;
quint64 bitsSet;
diff --git a/src/network/access/http2/hpacktable_p.h b/src/network/access/http2/hpacktable_p.h
index 960e6a3d70..587d86f09c 100644
--- a/src/network/access/http2/hpacktable_p.h
+++ b/src/network/access/http2/hpacktable_p.h
@@ -236,7 +236,7 @@ private:
mutable QByteArray dummyDst;
- Q_DISABLE_COPY(FieldLookupTable)
+ Q_DISABLE_COPY_MOVE(FieldLookupTable)
};
}
diff --git a/src/network/access/qabstractnetworkcache.cpp b/src/network/access/qabstractnetworkcache.cpp
index 9afb99f23f..4e217294c4 100644
--- a/src/network/access/qabstractnetworkcache.cpp
+++ b/src/network/access/qabstractnetworkcache.cpp
@@ -331,11 +331,11 @@ QDataStream &operator<<(QDataStream &out, const QNetworkCacheMetaData &metaData)
static inline QDataStream &operator<<(QDataStream &out, const QNetworkCacheMetaData::AttributesMap &hash)
{
out << quint32(hash.size());
- QNetworkCacheMetaData::AttributesMap::ConstIterator it = hash.end();
- QNetworkCacheMetaData::AttributesMap::ConstIterator begin = hash.begin();
- while (it != begin) {
- --it;
+ QNetworkCacheMetaData::AttributesMap::ConstIterator it = hash.begin();
+ QNetworkCacheMetaData::AttributesMap::ConstIterator end = hash.end();
+ while (it != end) {
out << int(it.key()) << it.value();
+ ++it;
}
return out;
}
@@ -383,7 +383,7 @@ static inline QDataStream &operator>>(QDataStream &in, QNetworkCacheMetaData::At
int k;
QVariant t;
in >> k >> t;
- hash.insertMulti(QNetworkRequest::Attribute(k), t);
+ hash.insert(QNetworkRequest::Attribute(k), t);
}
if (in.status() != QDataStream::Ok)
@@ -475,7 +475,7 @@ QAbstractNetworkCache::~QAbstractNetworkCache()
the QIODevice when done with it.
If there is no cache for \a url, the url is invalid, or if there
- is an internal cache error 0 is returned.
+ is an internal cache error \nullptr is returned.
In the base class this is a pure virtual function.
@@ -496,7 +496,7 @@ QAbstractNetworkCache::~QAbstractNetworkCache()
Returns the device that should be populated with the data for
the cache item \a metaData. When all of the data has been written
insert() should be called. If metaData is invalid or the url in
- the metadata is invalid 0 is returned.
+ the metadata is invalid \nullptr is returned.
The cache owns the device and will take care of deleting it when
it is inserted or removed.
diff --git a/src/network/access/qabstractnetworkcache.h b/src/network/access/qabstractnetworkcache.h
index 678bae2d6e..e357dfe58f 100644
--- a/src/network/access/qabstractnetworkcache.h
+++ b/src/network/access/qabstractnetworkcache.h
@@ -67,12 +67,10 @@ public:
QNetworkCacheMetaData(const QNetworkCacheMetaData &other);
~QNetworkCacheMetaData();
-#ifdef Q_COMPILER_RVALUE_REFS
- QNetworkCacheMetaData &operator=(QNetworkCacheMetaData &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QNetworkCacheMetaData &operator=(QNetworkCacheMetaData &&other) noexcept { swap(other); return *this; }
QNetworkCacheMetaData &operator=(const QNetworkCacheMetaData &other);
- void swap(QNetworkCacheMetaData &other) Q_DECL_NOTHROW
+ void swap(QNetworkCacheMetaData &other) noexcept
{ qSwap(d, other.d); }
bool operator==(const QNetworkCacheMetaData &other) const;
diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp
index d33355c470..cc230a5411 100644
--- a/src/network/access/qftp.cpp
+++ b/src/network/access/qftp.cpp
@@ -955,11 +955,9 @@ void QFtpPI::readyRead()
}
}
}
- QString endOfMultiLine;
- endOfMultiLine[0] = '0' + replyCode[0];
- endOfMultiLine[1] = '0' + replyCode[1];
- endOfMultiLine[2] = '0' + replyCode[2];
- endOfMultiLine[3] = QLatin1Char(' ');
+ const char count[4] = { char('0' + replyCode[0]), char('0' + replyCode[1]),
+ char('0' + replyCode[2]), char(' ') };
+ QString endOfMultiLine(QLatin1String(count, 4));
QString lineCont(endOfMultiLine);
lineCont[3] = QLatin1Char('-');
QStringRef lineLeft4 = line.leftRef(4);
@@ -1826,8 +1824,8 @@ int QFtp::cd(const QString &dir)
is data available to read. You can then read the data with the
read() or readAll() functions.
- If \a dev is not 0, the data is written directly to the device \a
- dev. Make sure that the \a dev pointer is valid for the duration
+ If \a dev is not \nullptr, the data is written directly to the device
+ \a dev. Make sure that the \a dev pointer is valid for the duration
of the operation (it is safe to delete it when the
commandFinished() signal is emitted). In this case the readyRead()
signal is \e not emitted and you cannot read data with the
@@ -2124,6 +2122,17 @@ void QFtp::abort()
/*!
\internal
+ Clears the last error.
+
+ \sa currentCommand()
+*/
+void QFtp::clearError()
+{
+ d_func()->error = NoError;
+}
+
+/*!
+ \internal
Returns the identifier of the FTP command that is being executed
or 0 if there is no command being executed.
diff --git a/src/network/access/qftp_p.h b/src/network/access/qftp_p.h
index bba1f9b09d..a55429933b 100644
--- a/src/network/access/qftp_p.h
+++ b/src/network/access/qftp_p.h
@@ -67,7 +67,7 @@ class Q_AUTOTEST_EXPORT QFtp : public QObject
Q_OBJECT
public:
- explicit QFtp(QObject *parent = 0);
+ explicit QFtp(QObject *parent = nullptr);
virtual ~QFtp();
enum State {
@@ -118,7 +118,7 @@ public:
int setTransferMode(TransferMode mode);
int list(const QString &dir = QString());
int cd(const QString &dir);
- int get(const QString &file, QIODevice *dev=0, TransferType type = Binary);
+ int get(const QString &file, QIODevice *dev=nullptr, TransferType type = Binary);
int put(const QByteArray &data, const QString &file, TransferType type = Binary);
int put(QIODevice *dev, const QString &file, TransferType type = Binary);
int remove(const QString &file);
@@ -157,8 +157,11 @@ Q_SIGNALS:
void commandFinished(int, bool);
void done(bool);
+protected:
+ void clearError();
+
private:
- Q_DISABLE_COPY(QFtp)
+ Q_DISABLE_COPY_MOVE(QFtp)
Q_DECLARE_PRIVATE(QFtp)
Q_PRIVATE_SLOT(d_func(), void _q_startNextCommand())
diff --git a/src/network/access/qhsts.cpp b/src/network/access/qhsts.cpp
index ce70b6af90..0cef0ad3dc 100644
--- a/src/network/access/qhsts.cpp
+++ b/src/network/access/qhsts.cpp
@@ -145,7 +145,7 @@ void QHstsCache::updateKnownHost(const QString &host, const QDateTime &expires,
return;
}
- knownHosts.insert(pos, {hostName, newPolicy});
+ knownHosts.insert({hostName, newPolicy});
#if QT_CONFIG(settings)
if (hstsStore)
hstsStore->addToObserved(newPolicy);
@@ -156,7 +156,7 @@ void QHstsCache::updateKnownHost(const QString &host, const QDateTime &expires,
if (newPolicy.isExpired())
knownHosts.erase(pos);
else if (pos->second != newPolicy)
- pos->second = std::move(newPolicy);
+ pos->second = newPolicy;
else
return;
diff --git a/src/network/access/qhstspolicy.h b/src/network/access/qhstspolicy.h
index 176a8fa635..f1b2ee99e5 100644
--- a/src/network/access/qhstspolicy.h
+++ b/src/network/access/qhstspolicy.h
@@ -65,10 +65,10 @@ public:
QUrl::ParsingMode mode = QUrl::DecodedMode);
QHstsPolicy(const QHstsPolicy &rhs);
QHstsPolicy &operator=(const QHstsPolicy &rhs);
- QHstsPolicy &operator=(QHstsPolicy &&other) Q_DECL_NOTHROW { swap(other); return *this; }
+ QHstsPolicy &operator=(QHstsPolicy &&other) noexcept { swap(other); return *this; }
~QHstsPolicy();
- void swap(QHstsPolicy &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QHstsPolicy &other) noexcept { qSwap(d, other.d); }
void setHost(const QString &host, QUrl::ParsingMode mode = QUrl::DecodedMode);
QString host(QUrl::ComponentFormattingOptions options = QUrl::FullyDecoded) const;
diff --git a/src/network/access/qhstsstore_p.h b/src/network/access/qhstsstore_p.h
index e82596b250..5338d15592 100644
--- a/src/network/access/qhstsstore_p.h
+++ b/src/network/access/qhstsstore_p.h
@@ -87,7 +87,7 @@ private:
QVector<QHstsPolicy> observedPolicies;
QSettings store;
- Q_DISABLE_COPY(QHstsStore)
+ Q_DISABLE_COPY_MOVE(QHstsStore)
};
QT_END_NAMESPACE
diff --git a/src/network/access/qhttpmultipart.h b/src/network/access/qhttpmultipart.h
index 78585a704d..56db83779a 100644
--- a/src/network/access/qhttpmultipart.h
+++ b/src/network/access/qhttpmultipart.h
@@ -60,12 +60,10 @@ public:
QHttpPart();
QHttpPart(const QHttpPart &other);
~QHttpPart();
-#ifdef Q_COMPILER_RVALUE_REFS
- QHttpPart &operator=(QHttpPart &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QHttpPart &operator=(QHttpPart &&other) noexcept { swap(other); return *this; }
QHttpPart &operator=(const QHttpPart &other);
- void swap(QHttpPart &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QHttpPart &other) noexcept { qSwap(d, other.d); }
bool operator==(const QHttpPart &other) const;
inline bool operator!=(const QHttpPart &other) const
diff --git a/src/network/access/qhttpmultipart_p.h b/src/network/access/qhttpmultipart_p.h
index 363e0b346c..ead1eadf3b 100644
--- a/src/network/access/qhttpmultipart_p.h
+++ b/src/network/access/qhttpmultipart_p.h
@@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE
class QHttpPartPrivate: public QSharedData, public QNetworkHeadersPrivate
{
public:
- inline QHttpPartPrivate() : bodyDevice(0), headerCreated(false), readPointer(0)
+ inline QHttpPartPrivate() : bodyDevice(nullptr), headerCreated(false), readPointer(0)
{
}
~QHttpPartPrivate()
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index c58fd24a44..2e38ac2dcf 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -398,11 +398,12 @@ void QHttpNetworkConnectionPrivate::copyCredentials(int fromChannel, QAuthentica
{
Q_ASSERT(auth);
- // NTLM is a multi phase authentication. Copying credentials between authenticators would mess things up.
+ // NTLM and Negotiate do multi-phase authentication.
+ // Copying credentialsbetween authenticators would mess things up.
if (fromChannel >= 0) {
- if (!isProxy && channels[fromChannel].authMethod == QAuthenticatorPrivate::Ntlm)
- return;
- if (isProxy && channels[fromChannel].proxyAuthMethod == QAuthenticatorPrivate::Ntlm)
+ const QHttpNetworkConnectionChannel &channel = channels[fromChannel];
+ const QAuthenticatorPrivate::Method method = isProxy ? channel.proxyAuthMethod : channel.authMethod;
+ if (method == QAuthenticatorPrivate::Ntlm || method == QAuthenticatorPrivate::Negotiate)
return;
}
@@ -592,24 +593,26 @@ void QHttpNetworkConnectionPrivate::createAuthorization(QAbstractSocket *socket,
if ((channels[i].authMethod != QAuthenticatorPrivate::Ntlm && request.headerField("Authorization").isEmpty()) || channels[i].lastStatus == 401) {
QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(channels[i].authenticator);
if (priv && priv->method != QAuthenticatorPrivate::None) {
- QByteArray response = priv->calculateResponse(request.methodName(), request.uri(false));
+ QByteArray response = priv->calculateResponse(request.methodName(), request.uri(false), request.url().host());
request.setHeaderField("Authorization", response);
channels[i].authenticationCredentialsSent = true;
}
}
}
+#if QT_CONFIG(networkproxy)
// Send "Proxy-Authorization" header, but not if it's NTLM and the socket is already authenticated.
if (channels[i].proxyAuthMethod != QAuthenticatorPrivate::None) {
if (!(channels[i].proxyAuthMethod == QAuthenticatorPrivate::Ntlm && channels[i].lastStatus != 407)) {
QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(channels[i].proxyAuthenticator);
if (priv && priv->method != QAuthenticatorPrivate::None) {
- QByteArray response = priv->calculateResponse(request.methodName(), request.uri(false));
+ QByteArray response = priv->calculateResponse(request.methodName(), request.uri(false), networkProxy.hostName());
request.setHeaderField("Proxy-Authorization", response);
channels[i].proxyCredentialsSent = true;
}
}
}
+#endif // QT_CONFIG(networkproxy)
}
QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetworkRequest &request)
@@ -641,7 +644,7 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor
else { // SPDY, HTTP/2 ('h2' mode)
if (!pair.second->d_func()->requestIsPrepared)
prepareRequest(pair);
- channels[0].spdyRequestsToSend.insertMulti(request.priority(), pair);
+ channels[0].spdyRequestsToSend.insert(request.priority(), pair);
}
#ifndef Q_OS_WINRT
@@ -677,7 +680,7 @@ void QHttpNetworkConnectionPrivate::fillHttp2Queue()
for (auto &pair : highPriorityQueue) {
if (!pair.second->d_func()->requestIsPrepared)
prepareRequest(pair);
- channels[0].spdyRequestsToSend.insertMulti(QHttpNetworkRequest::HighPriority, pair);
+ channels[0].spdyRequestsToSend.insert(QHttpNetworkRequest::HighPriority, pair);
}
highPriorityQueue.clear();
@@ -685,7 +688,7 @@ void QHttpNetworkConnectionPrivate::fillHttp2Queue()
for (auto &pair : lowPriorityQueue) {
if (!pair.second->d_func()->requestIsPrepared)
prepareRequest(pair);
- channels[0].spdyRequestsToSend.insertMulti(pair.first.priority(), pair);
+ channels[0].spdyRequestsToSend.insert(pair.first.priority(), pair);
}
lowPriorityQueue.clear();
@@ -1317,8 +1320,12 @@ QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16
: QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt, connectionType)), parent)
{
Q_D(QHttpNetworkConnection);
- d->networkSession = qMove(networkSession);
+ d->networkSession = std::move(networkSession);
d->init();
+ if (QNetworkStatusMonitor::isEnabled()) {
+ connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged,
+ this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection);
+ }
}
QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName,
@@ -1329,8 +1336,12 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS
connectionType)), parent)
{
Q_D(QHttpNetworkConnection);
- d->networkSession = qMove(networkSession);
+ d->networkSession = std::move(networkSession);
d->init();
+ if (QNetworkStatusMonitor::isEnabled()) {
+ connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged,
+ this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection);
+ }
}
#else
QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt,
@@ -1339,6 +1350,10 @@ QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16
{
Q_D(QHttpNetworkConnection);
d->init();
+ if (QNetworkStatusMonitor::isEnabled()) {
+ connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged,
+ this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection);
+ }
}
QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName,
@@ -1349,8 +1364,12 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS
{
Q_D(QHttpNetworkConnection);
d->init();
+ if (QNetworkStatusMonitor::isEnabled()) {
+ connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged,
+ this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection);
+ }
}
-#endif
+#endif // QT_NO_BEARERMANAGEMENT
QHttpNetworkConnection::~QHttpNetworkConnection()
{
@@ -1476,7 +1495,7 @@ QSharedPointer<QSslContext> QHttpNetworkConnection::sslContext()
void QHttpNetworkConnection::setSslContext(QSharedPointer<QSslContext> context)
{
Q_D(QHttpNetworkConnection);
- d->sslContext = qMove(context);
+ d->sslContext = std::move(context);
}
void QHttpNetworkConnection::ignoreSslErrors(int channel)
@@ -1518,6 +1537,38 @@ void QHttpNetworkConnection::preConnectFinished()
d_func()->preConnectRequests--;
}
+QString QHttpNetworkConnection::peerVerifyName() const
+{
+ Q_D(const QHttpNetworkConnection);
+ return d->peerVerifyName;
+}
+
+void QHttpNetworkConnection::setPeerVerifyName(const QString &peerName)
+{
+ Q_D(QHttpNetworkConnection);
+ d->peerVerifyName = peerName;
+}
+
+void QHttpNetworkConnection::onlineStateChanged(bool isOnline)
+{
+ Q_D(QHttpNetworkConnection);
+
+ if (isOnline) {
+ // If we did not have any 'isOffline' previously - well, good
+ // to know, we are 'online' apparently.
+ return;
+ }
+
+ for (int i = 0; i < d->activeChannelCount; i++) {
+ auto &channel = d->channels[i];
+ channel.emitFinishedWithError(QNetworkReply::TemporaryNetworkFailureError, "Temporary network failure.");
+ channel.close();
+ }
+
+ // We don't care, this connection is broken from our POV.
+ d->connectionMonitor.stopMonitoring();
+}
+
#ifndef QT_NO_NETWORKPROXY
// only called from QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired, not
// from QHttpNetworkConnectionChannel::handleAuthenticationChallenge
diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h
index 91827a6eb1..85d89f20c2 100644
--- a/src/network/access/qhttpnetworkconnection_p.h
+++ b/src/network/access/qhttpnetworkconnection_p.h
@@ -67,6 +67,7 @@
#include <private/qhttpnetworkheader_p.h>
#include <private/qhttpnetworkrequest_p.h>
#include <private/qhttpnetworkreply_p.h>
+#include <private/qnetconmonitor_p.h>
#include <private/http2protocol_p.h>
#include <private/qhttpnetworkconnectionchannel_p.h>
@@ -101,10 +102,10 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT
explicit QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false,
ConnectionType connectionType = ConnectionTypeHTTP,
- QObject *parent = 0, QSharedPointer<QNetworkSession> networkSession
+ QObject *parent = nullptr, QSharedPointer<QNetworkSession> networkSession
= QSharedPointer<QNetworkSession>());
QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80,
- bool encrypt = false, QObject *parent = 0,
+ bool encrypt = false, QObject *parent = nullptr,
QSharedPointer<QNetworkSession> networkSession = QSharedPointer<QNetworkSession>(),
ConnectionType connectionType = ConnectionTypeHTTP);
#else
@@ -154,9 +155,15 @@ public:
void preConnectFinished();
+ QString peerVerifyName() const;
+ void setPeerVerifyName(const QString &peerName);
+
+public slots:
+ void onlineStateChanged(bool isOnline);
+
private:
Q_DECLARE_PRIVATE(QHttpNetworkConnection)
- Q_DISABLE_COPY(QHttpNetworkConnection)
+ Q_DISABLE_COPY_MOVE(QHttpNetworkConnection)
friend class QHttpThreadDelegate;
friend class QHttpNetworkReply;
friend class QHttpNetworkReplyPrivate;
@@ -289,6 +296,16 @@ public:
Http2::ProtocolParameters http2Parameters;
+ QString peerVerifyName;
+ // If network status monitoring is enabled, we activate connectionMonitor
+ // as soons as one of channels managed to connect to host (and we
+ // have a pair of addresses (us,peer).
+ // NETMONTODO: consider activating a monitor on a change from
+ // HostLookUp state to ConnectingState (means we have both
+ // local/remote addresses known and can start monitoring this
+ // early).
+ QNetworkConnectionMonitor connectionMonitor;
+
friend class QHttpNetworkConnectionChannel;
};
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index d5f63af745..9309d718e4 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -59,6 +59,8 @@
#include "private/qnetworksession_p.h"
#endif
+#include "private/qnetconmonitor_p.h"
+
QT_BEGIN_NAMESPACE
namespace
@@ -392,6 +394,7 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
if (!connection->sslContext().isNull())
QSslSocketPrivate::checkSettingSslContext(sslSocket, connection->sslContext());
+ sslSocket->setPeerVerifyName(connection->d_func()->peerVerifyName);
sslSocket->connectToHostEncrypted(connectHost, connectPort, QIODevice::ReadWrite, networkLayerPreference);
if (ignoreAllSslErrors)
sslSocket->ignoreSslErrors();
@@ -895,6 +898,16 @@ void QHttpNetworkConnectionChannel::_q_connected()
pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningSupportUnknown;
+ if (QNetworkStatusMonitor::isEnabled()) {
+ auto connectionPrivate = connection->d_func();
+ if (!connectionPrivate->connectionMonitor.isMonitoring()) {
+ // Now that we have a pair of addresses, we can start monitoring the
+ // connection status to handle its loss properly.
+ if (connectionPrivate->connectionMonitor.setTargets(socket->localAddress(), socket->peerAddress()))
+ connectionPrivate->connectionMonitor.startMonitoring();
+ }
+ }
+
// ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again!
//channels[i].reconnectAttempts = 2;
if (ssl || pendingEncrypt) { // FIXME: Didn't work properly with pendingEncrypt only, we should refactor this into an EncrypingState
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index c9c3172304..a8b635c45a 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -444,6 +444,9 @@ QAuthenticatorPrivate::Method QHttpNetworkReplyPrivate::authenticationMethod(boo
} else if (method < QAuthenticatorPrivate::DigestMd5
&& line.startsWith("digest")) {
method = QAuthenticatorPrivate::DigestMd5;
+ } else if (method < QAuthenticatorPrivate::Negotiate
+ && line.startsWith("negotiate")) {
+ method = QAuthenticatorPrivate::Negotiate;
}
}
return method;
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index 863e21ea3e..12cfe359aa 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -89,7 +89,7 @@ class Q_AUTOTEST_EXPORT QHttpNetworkReply : public QObject, public QHttpNetworkH
Q_OBJECT
public:
- explicit QHttpNetworkReply(const QUrl &url = QUrl(), QObject *parent = 0);
+ explicit QHttpNetworkReply(const QUrl &url = QUrl(), QObject *parent = nullptr);
virtual ~QHttpNetworkReply();
QUrl url() const override;
diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp
index 8de9760710..a3f71b8d2f 100644
--- a/src/network/access/qhttpnetworkrequest.cpp
+++ b/src/network/access/qhttpnetworkrequest.cpp
@@ -66,7 +66,8 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest
ssl(other.ssl),
preConnect(other.preConnect),
redirectCount(other.redirectCount),
- redirectPolicy(other.redirectPolicy)
+ redirectPolicy(other.redirectPolicy),
+ peerVerifyName(other.peerVerifyName)
{
}
@@ -90,7 +91,8 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot
&& (withCredentials == other.withCredentials)
&& (ssl == other.ssl)
&& (preConnect == other.preConnect)
- && (redirectPolicy == other.redirectPolicy);
+ && (redirectPolicy == other.redirectPolicy)
+ && (peerVerifyName == other.peerVerifyName);
}
QByteArray QHttpNetworkRequest::methodName() const
@@ -397,6 +399,15 @@ int QHttpNetworkRequest::minorVersion() const
return 1;
}
+QString QHttpNetworkRequest::peerVerifyName() const
+{
+ return d->peerVerifyName;
+}
+
+void QHttpNetworkRequest::setPeerVerifyName(const QString &peerName)
+{
+ d->peerVerifyName = peerName;
+}
QT_END_NAMESPACE
diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h
index bc797537ae..fb4896195b 100644
--- a/src/network/access/qhttpnetworkrequest_p.h
+++ b/src/network/access/qhttpnetworkrequest_p.h
@@ -147,6 +147,8 @@ public:
QByteArray methodName() const;
QByteArray uri(bool throughProxy) const;
+ QString peerVerifyName() const;
+ void setPeerVerifyName(const QString &peerName);
private:
QSharedDataPointer<QHttpNetworkRequestPrivate> d;
friend class QHttpNetworkRequestPrivate;
@@ -182,6 +184,7 @@ public:
bool preConnect;
int redirectCount;
QNetworkRequest::RedirectPolicy redirectPolicy;
+ QString peerVerifyName;
};
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 0e97acdd9d..6fb4710d77 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -123,7 +123,7 @@ static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const
}
-static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy)
+static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy, const QString &peerVerifyName)
{
QString result;
QUrl copy = url;
@@ -170,7 +170,8 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy)
#else
Q_UNUSED(proxy)
#endif
-
+ if (!peerVerifyName.isEmpty())
+ result += QLatin1Char(':') + peerVerifyName;
return "http-connection:" + std::move(result).toLatin1();
}
@@ -188,7 +189,7 @@ public:
QHttpNetworkConnection::ConnectionType connectionType,
QSharedPointer<QNetworkSession> networkSession)
: QHttpNetworkConnection(hostName, port, encrypt, connectionType, /*parent=*/0,
- qMove(networkSession))
+ std::move(networkSession))
#endif
{
setExpires(true);
@@ -317,12 +318,12 @@ void QHttpThreadDelegate::startRequest()
#ifndef QT_NO_NETWORKPROXY
if (transparentProxy.type() != QNetworkProxy::NoProxy)
- cacheKey = makeCacheKey(urlCopy, &transparentProxy);
+ cacheKey = makeCacheKey(urlCopy, &transparentProxy, httpRequest.peerVerifyName());
else if (cacheProxy.type() != QNetworkProxy::NoProxy)
- cacheKey = makeCacheKey(urlCopy, &cacheProxy);
+ cacheKey = makeCacheKey(urlCopy, &cacheProxy, httpRequest.peerVerifyName());
else
#endif
- cacheKey = makeCacheKey(urlCopy, 0);
+ cacheKey = makeCacheKey(urlCopy, 0, httpRequest.peerVerifyName());
// the http object is actually a QHttpNetworkConnection
@@ -352,7 +353,7 @@ void QHttpThreadDelegate::startRequest()
httpConnection->setTransparentProxy(transparentProxy);
httpConnection->setCacheProxy(cacheProxy);
#endif
-
+ httpConnection->setPeerVerifyName(httpRequest.peerVerifyName());
// cache the QHttpNetworkConnection corresponding to this cache key
connections.localData()->addEntry(cacheKey, httpConnection);
} else {
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index 019a8b8b74..6184b39b30 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -82,7 +82,7 @@ class QHttpThreadDelegate : public QObject
{
Q_OBJECT
public:
- explicit QHttpThreadDelegate(QObject *parent = 0);
+ explicit QHttpThreadDelegate(QObject *parent = nullptr);
~QHttpThreadDelegate();
@@ -207,7 +207,7 @@ public:
: QNonContiguousByteDevice(),
wantDataPending(false),
m_amount(0),
- m_data(0),
+ m_data(nullptr),
m_atEnd(aE),
m_size(s),
m_pos(0)
@@ -240,12 +240,12 @@ public:
// Do nothing, we already sent a wantData signal and wait for results
len = 0;
}
- return 0;
+ return nullptr;
}
bool advanceReadPointer(qint64 a) override
{
- if (m_data == 0)
+ if (m_data == nullptr)
return false;
m_amount -= a;
@@ -269,7 +269,7 @@ public:
bool reset() override
{
m_amount = 0;
- m_data = 0;
+ m_data = nullptr;
m_dataArray.clear();
if (wantDataPending) {
diff --git a/src/network/access/qnetworkaccessauthenticationmanager_p.h b/src/network/access/qnetworkaccessauthenticationmanager_p.h
index 548675728f..31111ca2a5 100644
--- a/src/network/access/qnetworkaccessauthenticationmanager_p.h
+++ b/src/network/access/qnetworkaccessauthenticationmanager_p.h
@@ -90,12 +90,12 @@ public:
void cacheCredentials(const QUrl &url, const QAuthenticator *auth);
QNetworkAuthenticationCredential fetchCachedCredentials(const QUrl &url,
- const QAuthenticator *auth = 0);
+ const QAuthenticator *auth = nullptr);
#ifndef QT_NO_NETWORKPROXY
void cacheProxyCredentials(const QNetworkProxy &proxy, const QAuthenticator *auth);
QNetworkAuthenticationCredential fetchCachedProxyCredentials(const QNetworkProxy &proxy,
- const QAuthenticator *auth = 0);
+ const QAuthenticator *auth = nullptr);
#endif
void clearCache();
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 272dd22097..848fc84de7 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -83,7 +83,7 @@ QNetworkAccessBackendFactory::QNetworkAccessBackendFactory()
QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
{
- if (QNetworkAccessBackendFactoryData::valid.load()) {
+ if (QNetworkAccessBackendFactoryData::valid.loadRelaxed()) {
QMutexLocker locker(&factoryData()->mutex);
factoryData()->removeAll(this);
}
@@ -92,7 +92,7 @@ QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessManager::Operation op,
const QNetworkRequest &request)
{
- if (QNetworkAccessBackendFactoryData::valid.load()) {
+ if (QNetworkAccessBackendFactoryData::valid.loadRelaxed()) {
QMutexLocker locker(&factoryData()->mutex);
QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin(),
end = factoryData()->constEnd();
@@ -110,7 +110,7 @@ QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessM
QStringList QNetworkAccessManagerPrivate::backendSupportedSchemes() const
{
- if (QNetworkAccessBackendFactoryData::valid.load()) {
+ if (QNetworkAccessBackendFactoryData::valid.loadRelaxed()) {
QMutexLocker locker(&factoryData()->mutex);
QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin();
QNetworkAccessBackendFactoryData::ConstIterator end = factoryData()->constEnd();
diff --git a/src/network/access/qnetworkaccesscache.cpp b/src/network/access/qnetworkaccesscache.cpp
index 00bb18cb82..b694a2c999 100644
--- a/src/network/access/qnetworkaccesscache.cpp
+++ b/src/network/access/qnetworkaccesscache.cpp
@@ -40,11 +40,12 @@
#include "qnetworkaccesscache_p.h"
#include "QtCore/qpointer.h"
#include "QtCore/qdatetime.h"
-#include "QtCore/qqueue.h"
#include "qnetworkaccessmanager_p.h"
#include "qnetworkreply_p.h"
#include "qnetworkrequest.h"
+#include <vector>
+
QT_BEGIN_NAMESPACE
enum ExpiryTimeEnum {
@@ -63,7 +64,7 @@ namespace {
struct QNetworkAccessCache::Node
{
QDateTime timestamp;
- QQueue<Receiver> receiverQueue;
+ std::vector<Receiver> receiverQueue;
QByteArray key;
Node *older, *newer;
@@ -277,10 +278,7 @@ bool QNetworkAccessCache::requestEntry(const QByteArray &key, QObject *target, c
// object is not shareable and is in use
// queue for later use
Q_ASSERT(node->older == 0 && node->newer == 0);
- Receiver receiver;
- receiver.object = target;
- receiver.member = member;
- node->receiverQueue.enqueue(receiver);
+ node->receiverQueue.push_back({target, member});
// request queued
return true;
@@ -331,17 +329,19 @@ void QNetworkAccessCache::releaseEntry(const QByteArray &key)
Q_ASSERT(node->useCount > 0);
// are there other objects waiting?
- if (!node->receiverQueue.isEmpty()) {
+ const auto objectStillExists = [](const Receiver &r) { return !r.object.isNull(); };
+
+ auto &queue = node->receiverQueue;
+ auto qit = std::find_if(queue.begin(), queue.end(), objectStillExists);
+
+ const Receiver receiver = qit == queue.end() ? Receiver{} : std::move(*qit++) ;
+
+ queue.erase(queue.begin(), qit);
+
+ if (receiver.object) {
// queue another activation
- Receiver receiver;
- do {
- receiver = node->receiverQueue.dequeue();
- } while (receiver.object.isNull() && !node->receiverQueue.isEmpty());
-
- if (!receiver.object.isNull()) {
- emitEntryReady(node, receiver.object, receiver.member);
- return;
- }
+ emitEntryReady(node, receiver.object, receiver.member);
+ return;
}
if (!--node->useCount) {
diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp
index fd6589b396..51ed2f5a55 100644
--- a/src/network/access/qnetworkaccessftpbackend.cpp
+++ b/src/network/access/qnetworkaccessftpbackend.cpp
@@ -99,6 +99,8 @@ public:
connect(this, SIGNAL(done(bool)), this, SLOT(deleteLater()));
close();
}
+
+ using QFtp::clearError;
};
QNetworkAccessFtpBackend::QNetworkAccessFtpBackend()
@@ -282,7 +284,10 @@ void QNetworkAccessFtpBackend::ftpDone()
}
// check for errors:
- if (ftp->error() != QFtp::NoError) {
+ if (state == CheckingFeatures && ftp->error() == QFtp::UnknownError) {
+ qWarning("QNetworkAccessFtpBackend: HELP command failed, ignoring it");
+ ftp->clearError();
+ } else if (ftp->error() != QFtp::NoError) {
QString msg;
if (operation() == QNetworkAccessManager::GetOperation)
msg = tr("Error while downloading %1: %2");
@@ -351,7 +356,7 @@ void QNetworkAccessFtpBackend::ftpDone()
}
} else if (state == Statting) {
// statted successfully, send the actual request
- emit metaDataChanged();
+ metaDataChanged();
state = Transferring;
QFtp::TransferType type = QFtp::Binary;
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 85e2c492e4..a2996e3533 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -90,6 +90,8 @@
#include "qnetworkreplywasmimpl_p.h"
#endif
+#include "qnetconmonitor_p.h"
+
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend)
@@ -486,18 +488,25 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
qRegisterMetaType<QNetworkReply::NetworkError>();
qRegisterMetaType<QSharedPointer<char> >();
-#ifndef QT_NO_BEARERMANAGEMENT
Q_D(QNetworkAccessManager);
- // if a session is required, we track online state through
- // the QNetworkSession's signals if a request is already made.
- // we need to track current accessibility state by default
- //
- connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)),
- SLOT(_q_onlineStateChanged(bool)));
- connect(&d->networkConfigurationManager, SIGNAL(configurationChanged(QNetworkConfiguration)),
- SLOT(_q_configurationChanged(QNetworkConfiguration)));
-
-#endif
+ if (QNetworkStatusMonitor::isEnabled()) {
+ connect(&d->statusMonitor, SIGNAL(onlineStateChanged(bool)),
+ SLOT(_q_onlineStateChanged(bool)));
+#ifdef QT_NO_BEARERMANAGEMENT
+ d->networkAccessible = d->statusMonitor.isNetworkAccesible();
+#else
+ d->networkAccessible = d->statusMonitor.isNetworkAccesible() ? Accessible : NotAccessible;
+ } else {
+ // if a session is required, we track online state through
+ // the QNetworkSession's signals if a request is already made.
+ // we need to track current accessibility state by default
+ //
+ connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)),
+ SLOT(_q_onlineStateChanged(bool)));
+ connect(&d->networkConfigurationManager, SIGNAL(configurationChanged(QNetworkConfiguration)),
+ SLOT(_q_configurationChanged(QNetworkConfiguration)));
+#endif // QT_NO_BEARERMANAGEMENT
+ }
}
/*!
@@ -1030,6 +1039,7 @@ QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &requ
void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config)
{
Q_D(QNetworkAccessManager);
+
d->networkConfiguration = config;
d->customNetworkConfiguration = true;
d->createSession(config);
@@ -1048,7 +1058,7 @@ QNetworkConfiguration QNetworkAccessManager::configuration() const
Q_D(const QNetworkAccessManager);
QSharedPointer<QNetworkSession> session(d->getNetworkSession());
- if (session) {
+ if (session && !d->statusMonitor.isEnabled()) {
return session->configuration();
} else {
return d->networkConfigurationManager.defaultConfiguration();
@@ -1075,7 +1085,7 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
Q_D(const QNetworkAccessManager);
QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession());
- if (networkSession) {
+ if (networkSession && !d->statusMonitor.isEnabled()) {
return d->networkConfigurationManager.configurationFromIdentifier(
networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString());
} else {
@@ -1114,6 +1124,12 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess
{
Q_D(const QNetworkAccessManager);
+ if (d->statusMonitor.isEnabled()) {
+ if (!d->statusMonitor.isMonitoring())
+ d->statusMonitor.start();
+ return d->networkAccessible;
+ }
+
if (d->customNetworkConfiguration && d->networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined))
return UnknownAccessibility;
@@ -1181,9 +1197,37 @@ QSharedPointer<QNetworkSession> QNetworkAccessManagerPrivate::getNetworkSession(
\sa connectToHost(), get(), post(), put(), deleteResource()
*/
+
void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quint16 port,
const QSslConfiguration &sslConfiguration)
{
+ connectToHostEncrypted(hostName, port, sslConfiguration, QString());
+}
+
+/*!
+ \since 5.13
+ \overload
+
+ Initiates a connection to the host given by \a hostName at port \a port, using
+ \a sslConfiguration with \a peerName set to be the hostName used for certificate
+ validation. This function is useful to complete the TCP and SSL handshake
+ to a host before the HTTPS request is made, resulting in a lower network latency.
+
+ \note Preconnecting a SPDY connection can be done by calling setAllowedNextProtocols()
+ on \a sslConfiguration with QSslConfiguration::NextProtocolSpdy3_0 contained in
+ the list of allowed protocols. When using SPDY, one single connection per host is
+ enough, i.e. calling this method multiple times per host will not result in faster
+ network transactions.
+
+ \note This function has no possibility to report errors.
+
+ \sa connectToHost(), get(), post(), put(), deleteResource()
+*/
+
+void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quint16 port,
+ const QSslConfiguration &sslConfiguration,
+ const QString &peerName)
+{
QUrl url;
url.setHost(hostName);
url.setPort(port);
@@ -1198,6 +1242,7 @@ void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quin
QSslConfiguration::NextProtocolSpdy3_0))
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
+ request.setPeerVerifyName(peerName);
get(request);
}
#endif
@@ -1357,11 +1402,17 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, redirectPolicy());
}
+ if (autoDeleteReplies()
+ && req.attribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute).isNull()) {
+ req.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, true);
+ }
+
bool isLocalFile = req.url().isLocalFile();
QString scheme = req.url().scheme();
#ifdef Q_OS_WASM
- if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) {
+ // Support http, https, and relateive urls
+ if (scheme == QLatin1String("http") || scheme == QLatin1String("https") || scheme.isEmpty()) {
QNetworkReplyWasmImpl *reply = new QNetworkReplyWasmImpl(this);
QNetworkReplyWasmImplPrivate *priv = reply->d_func();
priv->manager = this;
@@ -1404,35 +1455,57 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
}
}
-#ifndef QT_NO_BEARERMANAGEMENT
+ if (d->statusMonitor.isEnabled()) {
+ // See the code in ctor - QNetworkStatusMonitor allows us to
+ // immediately set 'networkAccessible' even before we start
+ // the monitor.
+#ifdef QT_NO_BEARERMANAGEMENT
+ if (d->networkAccessible
+#else
+ if (d->networkAccessible == NotAccessible
+#endif // QT_NO_BEARERMANAGEMENT
+ && !isLocalFile) {
+ QHostAddress dest;
+ QString host = req.url().host().toLower();
+ if (!(dest.setAddress(host) && dest.isLoopback())
+ && host != QLatin1String("localhost")
+ && host != QHostInfo::localHostName().toLower()) {
+ return new QDisabledNetworkReply(this, req, op);
+ }
+ }
- // Return a disabled network reply if network access is disabled.
- // Except if the scheme is empty or file:// or if the host resolves to a loopback address.
- if (d->networkAccessible == NotAccessible && !isLocalFile) {
- QHostAddress dest;
- QString host = req.url().host().toLower();
- if (!(dest.setAddress(host) && dest.isLoopback()) && host != QLatin1String("localhost")
+ if (!d->statusMonitor.isMonitoring() && !d->statusMonitor.start())
+ qWarning(lcNetMon, "failed to start network status monitoring");
+ } else {
+#ifndef QT_NO_BEARERMANAGEMENT
+ // Return a disabled network reply if network access is disabled.
+ // Except if the scheme is empty or file:// or if the host resolves to a loopback address.
+ if (d->networkAccessible == NotAccessible && !isLocalFile) {
+ QHostAddress dest;
+ QString host = req.url().host().toLower();
+ if (!(dest.setAddress(host) && dest.isLoopback()) && host != QLatin1String("localhost")
&& host != QHostInfo::localHostName().toLower()) {
- return new QDisabledNetworkReply(this, req, op);
+ return new QDisabledNetworkReply(this, req, op);
+ }
}
- }
- if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) {
- if (!d->networkConfiguration.identifier().isEmpty()) {
- if ((d->networkConfiguration.state() & QNetworkConfiguration::Defined)
- && d->networkConfiguration != d->networkConfigurationManager.defaultConfiguration())
- d->createSession(d->networkConfigurationManager.defaultConfiguration());
- else
- d->createSession(d->networkConfiguration);
+ if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) {
+ if (!d->networkConfiguration.identifier().isEmpty()) {
+ if ((d->networkConfiguration.state() & QNetworkConfiguration::Defined)
+ && d->networkConfiguration != d->networkConfigurationManager.defaultConfiguration())
+ d->createSession(d->networkConfigurationManager.defaultConfiguration());
+ else
+ d->createSession(d->networkConfiguration);
- } else {
- if (d->networkSessionRequired)
- d->createSession(d->networkConfigurationManager.defaultConfiguration());
- else
- d->initializeSession = false;
+ } else {
+ if (d->networkSessionRequired)
+ d->createSession(d->networkConfigurationManager.defaultConfiguration());
+ else
+ d->initializeSession = false;
+ }
}
- }
#endif
+ }
QNetworkRequest request = req;
if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() &&
@@ -1479,8 +1552,10 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
#endif
QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData);
#ifndef QT_NO_BEARERMANAGEMENT
- connect(this, SIGNAL(networkSessionConnected()),
- reply, SLOT(_q_networkSessionConnected()));
+ if (!d->statusMonitor.isEnabled()) {
+ connect(this, SIGNAL(networkSessionConnected()),
+ reply, SLOT(_q_networkSessionConnected()));
+ }
#endif
return reply;
}
@@ -1489,7 +1564,9 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
// first step: create the reply
QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
#ifndef QT_NO_BEARERMANAGEMENT
- if (!isLocalFile) {
+ // NETMONTODO: network reply impl must be augmented to use the same monitoring
+ // capabilities as http network reply impl does.
+ if (!isLocalFile && !d->statusMonitor.isEnabled()) {
connect(this, SIGNAL(networkSessionConnected()),
reply, SLOT(_q_networkSessionConnected()));
}
@@ -1600,13 +1677,50 @@ void QNetworkAccessManager::clearConnectionCache()
QNetworkAccessManagerPrivate::clearConnectionCache(this);
}
+
+/*!
+ \since 5.14
+
+ Returns the true if QNetworkAccessManager is currently configured
+ to automatically delete QNetworkReplies, false otherwise.
+
+ \sa setAutoDeleteReplies,
+ QNetworkRequest::AutoDeleteReplyOnFinishAttribute
+*/
+bool QNetworkAccessManager::autoDeleteReplies()
+{
+ return d_func()->autoDeleteReplies;
+}
+
+/*!
+ \since 5.14
+
+ Enables or disables automatic deletion of \l {QNetworkReply} {QNetworkReplies}.
+
+ Setting \a shouldAutoDelete to true is the same as setting the
+ QNetworkRequest::AutoDeleteReplyOnFinishAttribute attribute to
+ true on all \e{future} \l {QNetworkRequest} {QNetworkRequests}
+ passed to this instance of QNetworkAccessManager unless the
+ attribute was already explicitly set on the QNetworkRequest.
+
+ \sa autoDeleteReplies,
+ QNetworkRequest::AutoDeleteReplyOnFinishAttribute
+*/
+void QNetworkAccessManager::setAutoDeleteReplies(bool shouldAutoDelete)
+{
+ d_func()->autoDeleteReplies = shouldAutoDelete;
+}
+
void QNetworkAccessManagerPrivate::_q_replyFinished()
{
Q_Q(QNetworkAccessManager);
QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
- if (reply)
+ if (reply) {
emit q->finished(reply);
+ if (reply->request().attribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, false).toBool())
+ QMetaObject::invokeMethod(reply, [reply] { reply->deleteLater(); }, Qt::QueuedConnection);
+ }
#ifndef QT_NO_BEARERMANAGEMENT
// If there are no active requests, release our reference to the network session.
@@ -1958,7 +2072,13 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
{
- Q_Q(QNetworkAccessManager);
+ Q_Q(QNetworkAccessManager);
+
+ if (statusMonitor.isEnabled()) {
+ networkAccessible = isOnline ? QNetworkAccessManager::Accessible : QNetworkAccessManager::NotAccessible;
+ return;
+ }
+
// if the user set a config, we only care whether this one is active.
// Otherwise, this QNAM is online if there is an online config.
@@ -1988,6 +2108,9 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfiguration &configuration)
{
+ if (statusMonitor.isEnabled())
+ return;
+
const QString id = configuration.identifier();
if (configuration.state().testFlag(QNetworkConfiguration::Active)) {
if (!onlineConfigurations.contains(id)) {
@@ -2020,6 +2143,9 @@ void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfigu
void QNetworkAccessManagerPrivate::_q_networkSessionFailed(QNetworkSession::SessionError)
{
+ if (statusMonitor.isEnabled())
+ return;
+
const auto cfgs = networkConfigurationManager.allConfigurations();
for (const QNetworkConfiguration &cfg : cfgs) {
if (cfg.state().testFlag(QNetworkConfiguration::Active)) {
@@ -2031,6 +2157,13 @@ void QNetworkAccessManagerPrivate::_q_networkSessionFailed(QNetworkSession::Sess
}
}
+#else
+
+void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
+{
+ networkAccessible = isOnline;
+}
+
#endif // QT_NO_BEARERMANAGEMENT
#if QT_CONFIG(http)
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index 67b3a8b71b..601d0420ff 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -158,12 +158,18 @@ public:
#ifndef QT_NO_SSL
void connectToHostEncrypted(const QString &hostName, quint16 port = 443,
const QSslConfiguration &sslConfiguration = QSslConfiguration::defaultConfiguration());
+ void connectToHostEncrypted(const QString &hostName, quint16 port,
+ const QSslConfiguration &sslConfiguration,
+ const QString &peerName);
#endif
void connectToHost(const QString &hostName, quint16 port = 80);
void setRedirectPolicy(QNetworkRequest::RedirectPolicy policy);
QNetworkRequest::RedirectPolicy redirectPolicy() const;
+ bool autoDeleteReplies();
+ void setAutoDeleteReplies(bool autoDelete);
+
Q_SIGNALS:
#ifndef QT_NO_NETWORKPROXY
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator);
@@ -206,10 +212,10 @@ private:
#ifndef QT_NO_BEARERMANAGEMENT
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
- Q_PRIVATE_SLOT(d_func(), void _q_onlineStateChanged(bool))
Q_PRIVATE_SLOT(d_func(), void _q_configurationChanged(const QNetworkConfiguration &))
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed(QNetworkSession::SessionError))
#endif
+ Q_PRIVATE_SLOT(d_func(), void _q_onlineStateChanged(bool))
};
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index 5cab4928e4..67ea2094b3 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -55,6 +55,7 @@
#include "qnetworkaccessmanager.h"
#include "qnetworkaccesscache_p.h"
#include "qnetworkaccessbackend_p.h"
+#include "private/qnetconmonitor_p.h"
#include "qnetworkrequest.h"
#include "qhsts_p.h"
#include "private/qobject_p.h"
@@ -151,6 +152,7 @@ public:
QNetworkAccessBackend *findBackend(QNetworkAccessManager::Operation op, const QNetworkRequest &request);
QStringList backendSupportedSchemes() const;
+ void _q_onlineStateChanged(bool isOnline);
#ifndef QT_NO_BEARERMANAGEMENT
void createSession(const QNetworkConfiguration &config);
QSharedPointer<QNetworkSession> getNetworkSession() const;
@@ -160,12 +162,11 @@ public:
void _q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &config,
bool isSeamless);
void _q_networkSessionStateChanged(QNetworkSession::State state);
- void _q_onlineStateChanged(bool isOnline);
+
void _q_configurationChanged(const QNetworkConfiguration &configuration);
void _q_networkSessionFailed(QNetworkSession::SessionError error);
QSet<QString> onlineConfigurations;
-
#endif
#if QT_CONFIG(http)
@@ -199,6 +200,8 @@ public:
int activeReplyCount;
bool online;
bool initializeSession;
+#else
+ bool networkAccessible = true;
#endif
bool cookieJarCreated;
@@ -222,6 +225,9 @@ public:
QScopedPointer<QHstsStore> stsStore;
#endif // QT_CONFIG(settings)
bool stsEnabled = false;
+ mutable QNetworkStatusMonitor statusMonitor;
+
+ bool autoDeleteReplies = false;
#ifndef QT_NO_BEARERMANAGEMENT
Q_AUTOTEST_EXPORT static const QWeakPointer<const QNetworkSession> getNetworkSession(const QNetworkAccessManager *manager);
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp
index b7cf989477..903de322ff 100644
--- a/src/network/access/qnetworkcookie.cpp
+++ b/src/network/access/qnetworkcookie.cpp
@@ -46,6 +46,7 @@
#include "QtCore/qdebug.h"
#include "QtCore/qlist.h"
#include "QtCore/qlocale.h"
+#include <QtCore/qregexp.h>
#include "QtCore/qstring.h"
#include "QtCore/qstringlist.h"
#include "QtCore/qurl.h"
diff --git a/src/network/access/qnetworkcookie.h b/src/network/access/qnetworkcookie.h
index e462b98555..b712b63849 100644
--- a/src/network/access/qnetworkcookie.h
+++ b/src/network/access/qnetworkcookie.h
@@ -66,12 +66,10 @@ public:
explicit QNetworkCookie(const QByteArray &name = QByteArray(), const QByteArray &value = QByteArray());
QNetworkCookie(const QNetworkCookie &other);
~QNetworkCookie();
-#ifdef Q_COMPILER_RVALUE_REFS
- QNetworkCookie &operator=(QNetworkCookie &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QNetworkCookie &operator=(QNetworkCookie &&other) noexcept { swap(other); return *this; }
QNetworkCookie &operator=(const QNetworkCookie &other);
- void swap(QNetworkCookie &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QNetworkCookie &other) noexcept { qSwap(d, other.d); }
bool operator==(const QNetworkCookie &other) const;
inline bool operator!=(const QNetworkCookie &other) const
diff --git a/src/network/access/qnetworkcookiejar.cpp b/src/network/access/qnetworkcookiejar.cpp
index 072a7f249d..af5b126953 100644
--- a/src/network/access/qnetworkcookiejar.cpp
+++ b/src/network/access/qnetworkcookiejar.cpp
@@ -45,6 +45,14 @@
#include "QtCore/qdatetime.h"
#if QT_CONFIG(topleveldomain)
#include "private/qtldurl_p.h"
+#else
+QT_BEGIN_NAMESPACE
+static bool qIsEffectiveTLD(QString domain)
+{
+ // provide minimal checking by not accepting cookies on real TLDs
+ return !domain.contains(QLatin1Char('.'));
+}
+QT_END_NAMESPACE
#endif
QT_BEGIN_NAMESPACE
@@ -356,19 +364,12 @@ bool QNetworkCookieJar::validateCookie(const QNetworkCookie &cookie, const QUrl
// https://tools.ietf.org/html/rfc6265#section-5.3 step 5
if (host == domain)
return true;
-#if QT_CONFIG(topleveldomain)
// the check for effective TLDs makes the "embedded dot" rule from RFC 2109 section 4.3.2
// redundant; the "leading dot" rule has been relaxed anyway, see QNetworkCookie::normalize()
// we remove the leading dot for this check if it's present
- if (qIsEffectiveTLD(domain))
- return false; // not accepted
-#else
- // provide minimal checking by not accepting cookies on real TLDs
- if (!domain.contains(QLatin1Char('.')))
- return false;
-#endif
-
- return true;
+ // Normally defined in qtldurl_p.h, but uses fall-back in this file when topleveldomain isn't
+ // configured:
+ return !qIsEffectiveTLD(domain);
}
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkdiskcache_p.h b/src/network/access/qnetworkdiskcache_p.h
index f7988e7dda..c797e63830 100644
--- a/src/network/access/qnetworkdiskcache_p.h
+++ b/src/network/access/qnetworkdiskcache_p.h
@@ -67,7 +67,7 @@ class QFile;
class QCacheItem
{
public:
- QCacheItem() : file(0)
+ QCacheItem() : file(nullptr)
{
}
~QCacheItem()
@@ -85,7 +85,7 @@ public:
metaData = QNetworkCacheMetaData();
data.close();
delete file;
- file = 0;
+ file = nullptr;
}
void writeHeader(QFile *device) const;
void writeCompressedData(QFile *device) const;
diff --git a/src/network/access/qnetworkfile.cpp b/src/network/access/qnetworkfile.cpp
index 374dd26e2e..b7c91f28d8 100644
--- a/src/network/access/qnetworkfile.cpp
+++ b/src/network/access/qnetworkfile.cpp
@@ -65,21 +65,21 @@ void QNetworkFile::open()
if (fi.isDir()) {
QString msg = QCoreApplication::translate("QNetworkAccessFileBackend",
"Cannot open %1: Path is a directory").arg(fileName());
- error(QNetworkReply::ContentOperationNotPermittedError, msg);
+ emit error(QNetworkReply::ContentOperationNotPermittedError, msg);
} else {
- headerRead(QNetworkRequest::LastModifiedHeader, QVariant::fromValue(fi.lastModified()));
- headerRead(QNetworkRequest::ContentLengthHeader, QVariant::fromValue(fi.size()));
+ emit headerRead(QNetworkRequest::LastModifiedHeader, QVariant::fromValue(fi.lastModified()));
+ emit headerRead(QNetworkRequest::ContentLengthHeader, QVariant::fromValue(fi.size()));
opened = QFile::open(QIODevice::ReadOnly | QIODevice::Unbuffered);
if (!opened) {
QString msg = QCoreApplication::translate("QNetworkAccessFileBackend",
"Error opening %1: %2").arg(fileName(), errorString());
if (exists())
- error(QNetworkReply::ContentAccessDenied, msg);
+ emit error(QNetworkReply::ContentAccessDenied, msg);
else
- error(QNetworkReply::ContentNotFoundError, msg);
+ emit error(QNetworkReply::ContentNotFoundError, msg);
}
}
- finished(opened);
+ emit finished(opened);
}
void QNetworkFile::close()
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 2d7649fa61..b9651b35d2 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -59,6 +59,7 @@
#include <QtCore/private/qthread_p.h>
#include "qnetworkcookiejar.h"
+#include "qnetconmonitor_p.h"
#include <string.h> // for strchr
@@ -166,6 +167,11 @@ static QHash<QByteArray, QByteArray> parseHttpOptionHeader(const QByteArray &hea
#if QT_CONFIG(bearermanagement)
static bool isSessionNeeded(const QUrl &url)
{
+ if (QNetworkStatusMonitor::isEnabled()) {
+ // In case QNetworkStatus/QNetConManager are in business,
+ // no session, no bearer manager are involved.
+ return false;
+ }
// Connections to the local machine does not require a session
QString host = url.host().toLower();
return !QHostAddress(host).isLoopback() && host != QLatin1String("localhost")
@@ -787,6 +793,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
if (request.attribute(QNetworkRequest::EmitAllUploadProgressSignalsAttribute).toBool())
emitAllUploadProgressSignals = true;
+ httpRequest.setPeerVerifyName(newHttpRequest.peerVerifyName());
// Create the HTTP thread delegate
QHttpThreadDelegate *delegate = new QHttpThreadDelegate;
@@ -795,7 +802,8 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
if (blob.isValid() && blob.canConvert<Http2::ProtocolParameters>())
delegate->http2Parameters = blob.value<Http2::ProtocolParameters>();
#ifndef QT_NO_BEARERMANAGEMENT
- delegate->networkSession = managerPrivate->getNetworkSession();
+ if (!QNetworkStatusMonitor::isEnabled())
+ delegate->networkSession = managerPrivate->getNetworkSession();
#endif
// For the synchronous HTTP, this is the normal way the delegate gets deleted
@@ -1563,7 +1571,7 @@ bool QNetworkReplyHttpImplPrivate::sendCacheContents(const QNetworkCacheMetaData
QIODevice *contents = nc->data(url);
if (!contents) {
#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
- qDebug() << "Can not send cache, the contents are 0" << url;
+ qDebug() << "Cannot send cache, the contents are 0" << url;
#endif
return false;
}
@@ -1806,7 +1814,7 @@ bool QNetworkReplyHttpImplPrivate::start(const QNetworkRequest &newHttpRequest)
{
#ifndef QT_NO_BEARERMANAGEMENT
QSharedPointer<QNetworkSession> networkSession(managerPrivate->getNetworkSession());
- if (!networkSession) {
+ if (!networkSession || QNetworkStatusMonitor::isEnabled()) {
#endif
postRequest(newHttpRequest);
return true;
@@ -1894,7 +1902,7 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation()
// state changes.
if (!startWaitForSession(session))
return;
- } else if (session) {
+ } else if (session && !QNetworkStatusMonitor::isEnabled()) {
QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)),
q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)),
Qt::QueuedConnection);
@@ -2183,7 +2191,7 @@ void QNetworkReplyHttpImplPrivate::finished()
#ifndef QT_NO_BEARERMANAGEMENT
Q_ASSERT(managerPrivate);
QSharedPointer<QNetworkSession> session = managerPrivate->getNetworkSession();
- if (session && session->state() == QNetworkSession::Roaming &&
+ if (!QNetworkStatusMonitor::isEnabled() && session && session->state() == QNetworkSession::Roaming &&
state == Working && errorCode != QNetworkReply::OperationCanceledError) {
// only content with a known size will fail with a temporary network failure error
if (!totalSize.isNull()) {
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index a794b492e7..6eab500e8c 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -158,7 +158,7 @@ void QNetworkReplyImplPrivate::_q_startOperation()
} else {
if (state != Finished) {
if (operation == QNetworkAccessManager::GetOperation)
- pendingNotifications.append(NotifyDownstreamReadyWrite);
+ pendingNotifications.push_back(NotifyDownstreamReadyWrite);
handleNotifications();
}
@@ -368,6 +368,7 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const
outgoingData = data;
request = req;
+ originalRequest = req;
url = request.url();
operation = op;
@@ -432,8 +433,9 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const
void QNetworkReplyImplPrivate::backendNotify(InternalNotifications notification)
{
Q_Q(QNetworkReplyImpl);
- if (!pendingNotifications.contains(notification))
- pendingNotifications.enqueue(notification);
+ const auto it = std::find(pendingNotifications.cbegin(), pendingNotifications.cend(), notification);
+ if (it == pendingNotifications.cend())
+ pendingNotifications.push_back(notification);
if (pendingNotifications.size() == 1)
QCoreApplication::postEvent(q, new QEvent(QEvent::NetworkReplyUpdated));
@@ -444,14 +446,9 @@ void QNetworkReplyImplPrivate::handleNotifications()
if (notificationHandlingPaused)
return;
- NotificationQueue current = pendingNotifications;
- pendingNotifications.clear();
-
- if (state != Working)
- return;
-
- while (state == Working && !current.isEmpty()) {
- InternalNotifications notification = current.dequeue();
+ for (InternalNotifications notification : qExchange(pendingNotifications, {})) {
+ if (state != Working)
+ return;
switch (notification) {
case NotifyDownstreamReadyWrite:
if (copyDevice)
@@ -465,8 +462,7 @@ void QNetworkReplyImplPrivate::handleNotifications()
break;
case NotifyCopyFinished: {
- QIODevice *dev = copyDevice;
- copyDevice = 0;
+ QIODevice *dev = qExchange(copyDevice, nullptr);
backend->copyFinished(dev);
break;
}
@@ -1116,7 +1112,6 @@ bool QNetworkReplyImplPrivate::migrateBackend()
return true;
}
-#ifndef QT_NO_BEARERMANAGEMENT
QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent,
const QNetworkRequest &req,
QNetworkAccessManager::Operation op)
@@ -1141,7 +1136,6 @@ QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent,
QDisabledNetworkReply::~QDisabledNetworkReply()
{
}
-#endif
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h
index f4e8284ab6..8cec79541a 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -74,7 +74,7 @@ class QNetworkReplyImpl: public QNetworkReply
{
Q_OBJECT
public:
- QNetworkReplyImpl(QObject *parent = 0);
+ QNetworkReplyImpl(QObject *parent = nullptr);
~QNetworkReplyImpl();
virtual void abort() override;
@@ -117,8 +117,6 @@ public:
NotifyCopyFinished
};
- typedef QQueue<InternalNotifications> NotificationQueue;
-
QNetworkReplyImplPrivate();
void _q_startOperation();
@@ -178,7 +176,7 @@ public:
bool cacheEnabled;
QIODevice *cacheSaveDevice;
- NotificationQueue pendingNotifications;
+ std::vector<InternalNotifications> pendingNotifications;
bool notificationHandlingPaused;
QUrl urlForLastAuthentication;
@@ -209,7 +207,6 @@ public:
};
Q_DECLARE_TYPEINFO(QNetworkReplyImplPrivate::InternalNotifications, Q_PRIMITIVE_TYPE);
-#ifndef QT_NO_BEARERMANAGEMENT
class QDisabledNetworkReply : public QNetworkReply
{
Q_OBJECT
@@ -223,7 +220,6 @@ public:
protected:
qint64 readData(char *, qint64) override { return -1; }
};
-#endif
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp
index b1e9853a50..9f6422a107 100644
--- a/src/network/access/qnetworkreplywasmimpl.cpp
+++ b/src/network/access/qnetworkreplywasmimpl.cpp
@@ -59,6 +59,9 @@ using namespace emscripten;
static void q_requestErrorCallback(val event)
{
+ if (event.isNull() || event.isUndefined())
+ return;
+
val xhr = event["target"];
quintptr func = xhr["data-handler"].as<quintptr>();
@@ -77,19 +80,24 @@ static void q_requestErrorCallback(val event)
static void q_progressCallback(val event)
{
+ if (event.isNull() || event.isUndefined())
+ return;
+
val xhr = event["target"];
QNetworkReplyWasmImplPrivate *reply =
reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
Q_ASSERT(reply);
- if (xhr["lengthComputable"].as<bool>() && xhr["status"].as<int>() < 400)
- reply->emitDataReadProgress(xhr["loaded"].as<qint64>(), xhr["total"].as<qint64>());
-
+ if (xhr["status"].as<int>() < 400)
+ reply->emitDataReadProgress(event["loaded"].as<int>(), event["total"].as<int>());
}
static void q_loadCallback(val event)
{
+ if (event.isNull() || event.isUndefined())
+ return;
+
val xhr = event["target"];
QNetworkReplyWasmImplPrivate *reply =
@@ -117,10 +125,11 @@ static void q_loadCallback(val event)
val blob = xhr["response"];
val reader = val::global("FileReader").new_();
- reader.set("onload", val::module_property("QNetworkReplyWasmImplPrivate_readBinary"));
+ reader.set("onload", val::module_property("qt_QNetworkReplyWasmImplPrivate_readBinary"));
reader.set("data-handler", xhr["data-handler"]);
reader.call<void>("readAsArrayBuffer", blob);
+ val::global("Module").delete_(reader);
}
@@ -136,6 +145,9 @@ static void q_loadCallback(val event)
static void q_responseHeadersCallback(val event)
{
+ if (event.isNull() || event.isUndefined())
+ return;
+
val xhr = event["target"];
if (xhr["readyState"].as<int>() == 2) { // HEADERS_RECEIVED
@@ -152,12 +164,18 @@ static void q_responseHeadersCallback(val event)
static void q_readBinary(val event)
{
+ if (event.isNull() || event.isUndefined())
+ return;
+
val fileReader = event["target"];
QNetworkReplyWasmImplPrivate *reply =
reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fileReader["data-handler"].as<quintptr>());
Q_ASSERT(reply);
+ if (reply->state == QNetworkReplyPrivate::Finished || reply->state == QNetworkReplyPrivate::Aborted)
+ return;
+
// Set up source typed array
val result = fileReader["result"]; // ArrayBuffer
val Uint8Array = val::global("Uint8Array");
@@ -171,15 +189,19 @@ static void q_readBinary(val event)
reinterpret_cast<quintptr>(buffer.data()), size);
destinationTypedArray.call<void>("set", sourceTypedArray);
reply->dataReceived(buffer, buffer.size());
+
+ event.delete_(fileReader);
+ Uint8Array.delete_(sourceTypedArray);
+
QCoreApplication::processEvents();
}
-EMSCRIPTEN_BINDINGS(network_module) {
- function("QNetworkReplyWasmImplPrivate_requestErrorCallback", q_requestErrorCallback);
- function("QNetworkReplyWasmImplPrivate_progressCallback", q_progressCallback);
- function("QNetworkReplyWasmImplPrivate_loadCallback", q_loadCallback);
- function("QNetworkReplyWasmImplPrivate_responseHeadersCallback", q_responseHeadersCallback);
- function("QNetworkReplyWasmImplPrivate_readBinary", q_readBinary);
+EMSCRIPTEN_BINDINGS(qtNetworkModule) {
+ function("qt_QNetworkReplyWasmImplPrivate_requestErrorCallback", q_requestErrorCallback);
+ function("qt_QNetworkReplyWasmImplPrivate_progressCallback", q_progressCallback);
+ function("qt_QNetworkReplyWasmImplPrivate_loadCallback", q_loadCallback);
+ function("qt_QNetworkReplyWasmImplPrivate_responseHeadersCallback", q_responseHeadersCallback);
+ function("qt_QNetworkReplyWasmImplPrivate_readBinary", q_readBinary);
}
QNetworkReplyWasmImplPrivate::QNetworkReplyWasmImplPrivate()
@@ -194,14 +216,21 @@ QNetworkReplyWasmImplPrivate::QNetworkReplyWasmImplPrivate()
QNetworkReplyWasmImplPrivate::~QNetworkReplyWasmImplPrivate()
{
+ m_xhr.set("onerror", val::null());
+ m_xhr.set("onload", val::null());
+ m_xhr.set("onprogress", val::null());
+ m_xhr.set("onreadystatechange", val::null());
+ m_xhr.set("data-handler", val::null());
}
-QNetworkReplyWasmImpl::~QNetworkReplyWasmImpl()
+QNetworkReplyWasmImpl::QNetworkReplyWasmImpl(QObject *parent)
+ : QNetworkReply(*new QNetworkReplyWasmImplPrivate(), parent)
{
+ Q_D( QNetworkReplyWasmImpl);
+ d->state = QNetworkReplyPrivate::Idle;
}
-QNetworkReplyWasmImpl::QNetworkReplyWasmImpl(QObject *parent)
- : QNetworkReply(*new QNetworkReplyWasmImplPrivate(), parent)
+QNetworkReplyWasmImpl::~QNetworkReplyWasmImpl()
{
}
@@ -226,18 +255,23 @@ QByteArray QNetworkReplyWasmImpl::methodName() const
void QNetworkReplyWasmImpl::close()
{
+ QNetworkReply::close();
setFinished(true);
emit finished();
-
- QNetworkReply::close();
}
void QNetworkReplyWasmImpl::abort()
{
- Q_D(const QNetworkReplyWasmImpl);
+ Q_D( QNetworkReplyWasmImpl);
+ if (d->state == QNetworkReplyPrivate::Finished || d->state == QNetworkReplyPrivate::Aborted)
+ return;
+
+ setError(QNetworkReply::OperationCanceledError, QStringLiteral("Operation canceled"));
+
d->doAbort();
close();
+ d->state = QNetworkReplyPrivate::Aborted;
}
qint64 QNetworkReplyWasmImpl::bytesAvailable() const
@@ -327,14 +361,12 @@ void QNetworkReplyWasmImplPrivate::doSendRequest()
m_xhr = val::global("XMLHttpRequest").new_();
std::string verb = q->methodName().toStdString();
- QString extraDataString;
-
m_xhr.call<void>("open", verb, request.url().toString().toStdString());
- m_xhr.set("onerror", val::module_property("QNetworkReplyWasmImplPrivate_requestErrorCallback"));
- m_xhr.set("onload", val::module_property("QNetworkReplyWasmImplPrivate_loadCallback"));
- m_xhr.set("onprogress", val::module_property("QNetworkReplyWasmImplPrivate_progressCallback"));
- m_xhr.set("onreadystatechange", val::module_property("QNetworkReplyWasmImplPrivate_responseHeadersCallback"));
+ m_xhr.set("onerror", val::module_property("qt_QNetworkReplyWasmImplPrivate_requestErrorCallback"));
+ m_xhr.set("onload", val::module_property("qt_QNetworkReplyWasmImplPrivate_loadCallback"));
+ m_xhr.set("onprogress", val::module_property("qt_QNetworkReplyWasmImplPrivate_progressCallback"));
+ m_xhr.set("onreadystatechange", val::module_property("qt_QNetworkReplyWasmImplPrivate_responseHeadersCallback"));
m_xhr.set("data-handler", val(quintptr(reinterpret_cast<void *>(this))));
@@ -347,30 +379,12 @@ void QNetworkReplyWasmImplPrivate::doSendRequest()
if (outgoingData) // data from post request
extraData = outgoingData->readAll();
- if (contentType.contains("text") ||
- contentType.contains("json") ||
- contentType.contains("form")) {
- if (extraData.size() > 0)
- extraDataString.fromUtf8(extraData);
- }
- if (contentType.contains("json")) {
- if (!extraDataString.isEmpty()) {
- m_xhr.set("responseType", val("json"));
- dataToSend = val(extraDataString.toStdString());
- }
- } else if (contentType.contains("form")) { //construct form data
- if (!extraDataString.isEmpty()) {
- val formData = val::global("FormData").new_();
- QStringList formList = extraDataString.split('&');
-
- for (auto formEntry : formList) {
- formData.call<void>("append", formEntry.split('=')[0].toStdString(), formEntry.split('=')[1].toStdString());
- }
- dataToSend = formData;
- }
- } else {
- m_xhr.set("responseType", val("blob"));
+ if (!extraData.isEmpty()) {
+ dataToSend = val(typed_memory_view(extraData.size(),
+ reinterpret_cast<const unsigned char *>
+ (extraData.constData())));
}
+ m_xhr.set("responseType", val("blob"));
// set request headers
for (auto header : request.rawHeaderList()) {
m_xhr.call<void>("setRequestHeader", header.toStdString(), request.rawHeader(header).toStdString());
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index e4c46c3183..ba36c75419 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -331,6 +331,12 @@ QT_BEGIN_NAMESPACE
\omitvalue ResourceTypeAttribute
+ \value AutoDeleteReplyOnFinishAttribute
+ Requests only, type: QMetaType::Bool (default: false)
+ If set, this attribute will make QNetworkAccessManager delete
+ the QNetworkReply after having emitted "finished".
+ (This value was introduced in 5.14.)
+
\value User
Special type. Additional information can be passed in
QVariants with types ranging from User to UserMax. The default
@@ -438,6 +444,7 @@ public:
if (other.sslConfiguration)
sslConfiguration = new QSslConfiguration(*other.sslConfiguration);
#endif
+ peerVerifyName = other.peerVerifyName;
}
inline bool operator==(const QNetworkRequestPrivate &other) const
@@ -446,7 +453,8 @@ public:
priority == other.priority &&
rawHeaders == other.rawHeaders &&
attributes == other.attributes &&
- maxRedirectsAllowed == other.maxRedirectsAllowed;
+ maxRedirectsAllowed == other.maxRedirectsAllowed &&
+ peerVerifyName == other.peerVerifyName;
// don't compare cookedHeaders
}
@@ -456,6 +464,7 @@ public:
mutable QSslConfiguration *sslConfiguration;
#endif
int maxRedirectsAllowed;
+ QString peerVerifyName;
};
/*!
@@ -789,6 +798,32 @@ void QNetworkRequest::setMaximumRedirectsAllowed(int maxRedirectsAllowed)
d->maxRedirectsAllowed = maxRedirectsAllowed;
}
+/*!
+ \since 5.13
+
+ Returns the host name set for the certificate validation, as set by
+ setPeerVerifyName. By default this returns a null string.
+
+ \sa setPeerVerifyName
+*/
+QString QNetworkRequest::peerVerifyName() const
+{
+ return d->peerVerifyName;
+}
+
+/*!
+ \since 5.13
+
+ Sets \a peerName as host name for the certificate validation, instead of the one used for the
+ TCP connection.
+
+ \sa peerVerifyName
+*/
+void QNetworkRequest::setPeerVerifyName(const QString &peerName)
+{
+ d->peerVerifyName = peerName;
+}
+
static QByteArray headerName(QNetworkRequest::KnownHeaders header)
{
switch (header) {
@@ -1309,7 +1344,7 @@ QDateTime QNetworkHeadersPrivate::fromHttpDate(const QByteArray &value)
QByteArray QNetworkHeadersPrivate::toHttpDate(const QDateTime &dt)
{
- return QLocale::c().toString(dt, QLatin1String("ddd, dd MMM yyyy hh:mm:ss 'GMT'"))
+ return QLocale::c().toString(dt, QStringViewLiteral("ddd, dd MMM yyyy hh:mm:ss 'GMT'"))
.toLatin1();
}
diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h
index 8462eae8c8..846ead1592 100644
--- a/src/network/access/qnetworkrequest.h
+++ b/src/network/access/qnetworkrequest.h
@@ -98,6 +98,7 @@ public:
RedirectPolicyAttribute,
Http2DirectAttribute,
ResourceTypeAttribute, // internal
+ AutoDeleteReplyOnFinishAttribute,
User = 1000,
UserMax = 32767
@@ -130,12 +131,10 @@ public:
explicit QNetworkRequest(const QUrl &url = QUrl());
QNetworkRequest(const QNetworkRequest &other);
~QNetworkRequest();
-#ifdef Q_COMPILER_RVALUE_REFS
- QNetworkRequest &operator=(QNetworkRequest &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QNetworkRequest &operator=(QNetworkRequest &&other) noexcept { swap(other); return *this; }
QNetworkRequest &operator=(const QNetworkRequest &other);
- void swap(QNetworkRequest &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QNetworkRequest &other) noexcept { qSwap(d, other.d); }
bool operator==(const QNetworkRequest &other) const;
inline bool operator!=(const QNetworkRequest &other) const
@@ -173,6 +172,8 @@ public:
int maximumRedirectsAllowed() const;
void setMaximumRedirectsAllowed(int maximumRedirectsAllowed);
+ QString peerVerifyName() const;
+ void setPeerVerifyName(const QString &peerName);
private:
QSharedDataPointer<QNetworkRequestPrivate> d;
friend class QNetworkRequestPrivate;
diff --git a/src/network/bearer/qbearerengine.cpp b/src/network/bearer/qbearerengine.cpp
index 677da08cb6..c06adb202f 100644
--- a/src/network/bearer/qbearerengine.cpp
+++ b/src/network/bearer/qbearerengine.cpp
@@ -56,7 +56,7 @@ static void cleanUpConfigurations(QHash<QString, QNetworkConfigurationPrivatePoi
static bool hasUsedConfiguration(const QHash<QString, QNetworkConfigurationPrivatePointer> &configurations)
{
auto isUsed = [](const QNetworkConfigurationPrivatePointer &ptr) {
- return ptr->ref.load() > 1;
+ return ptr->ref.loadRelaxed() > 1;
};
const auto end = configurations.end();
return std::find_if(configurations.begin(), end, isUsed) != end;
diff --git a/src/network/bearer/qbearerengine_p.h b/src/network/bearer/qbearerengine_p.h
index 5fc2578a78..a5a020a857 100644
--- a/src/network/bearer/qbearerengine_p.h
+++ b/src/network/bearer/qbearerengine_p.h
@@ -77,7 +77,7 @@ class Q_NETWORK_EXPORT QBearerEngine : public QObject
friend class QNetworkConfigurationManagerPrivate;
public:
- explicit QBearerEngine(QObject *parent = 0);
+ explicit QBearerEngine(QObject *parent = nullptr);
virtual ~QBearerEngine();
virtual bool hasIdentifier(const QString &id) = 0;
diff --git a/src/network/bearer/qbearerplugin_p.h b/src/network/bearer/qbearerplugin_p.h
index 0cdde3c06c..ac787d0541 100644
--- a/src/network/bearer/qbearerplugin_p.h
+++ b/src/network/bearer/qbearerplugin_p.h
@@ -68,7 +68,7 @@ class Q_NETWORK_EXPORT QBearerEnginePlugin : public QObject
{
Q_OBJECT
public:
- explicit QBearerEnginePlugin(QObject *parent = 0);
+ explicit QBearerEnginePlugin(QObject *parent = nullptr);
virtual ~QBearerEnginePlugin();
virtual QBearerEngine *create(const QString &key) const = 0;
diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp
index e36903fc94..19bc44e02a 100644
--- a/src/network/bearer/qnetworkconfiguration.cpp
+++ b/src/network/bearer/qnetworkconfiguration.cpp
@@ -414,34 +414,7 @@ bool QNetworkConfiguration::isRoamingAvailable() const
*/
QList<QNetworkConfiguration> QNetworkConfiguration::children() const
{
- QList<QNetworkConfiguration> results;
-
- if (!d)
- return results;
-
- QMutexLocker locker(&d->mutex);
-
- if (d->type != QNetworkConfiguration::ServiceNetwork || !d->isValid)
- return results;
-
- for (auto it = d->serviceNetworkMembers.begin(), end = d->serviceNetworkMembers.end(); it != end;) {
- QNetworkConfigurationPrivatePointer p = it.value();
- //if we have an invalid member get rid of it -> was deleted earlier on
- {
- QMutexLocker childLocker(&p->mutex);
-
- if (!p->isValid) {
- it = d->serviceNetworkMembers.erase(it);
- continue;
- }
- }
- QNetworkConfiguration item;
- item.d = p;
- results << item;
- ++it;
- }
-
- return results;
+ return {};
}
/*!
@@ -518,7 +491,7 @@ QNetworkConfiguration::BearerType QNetworkConfiguration::bearerTypeFamily() cons
/*!
Returns the type of bearer used by this network configuration as a string.
- The string is not translated and therefore can not be shown to the user. The subsequent table
+ The string is not translated and therefore cannot be shown to the user. The subsequent table
shows the fixed mappings between BearerType and the bearer type name for known types. If the
BearerType is unknown this function may return additional information if it is available;
otherwise an empty string will be returned.
diff --git a/src/network/bearer/qnetworkconfiguration.h b/src/network/bearer/qnetworkconfiguration.h
index e7b74034fc..048abc2fc8 100644
--- a/src/network/bearer/qnetworkconfiguration.h
+++ b/src/network/bearer/qnetworkconfiguration.h
@@ -55,13 +55,11 @@ class Q_NETWORK_EXPORT QNetworkConfiguration
public:
QNetworkConfiguration();
QNetworkConfiguration(const QNetworkConfiguration& other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QNetworkConfiguration &operator=(QNetworkConfiguration &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QNetworkConfiguration &operator=(QNetworkConfiguration &&other) noexcept { swap(other); return *this; }
QNetworkConfiguration &operator=(const QNetworkConfiguration &other);
~QNetworkConfiguration();
- void swap(QNetworkConfiguration &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QNetworkConfiguration &other) noexcept { qSwap(d, other.d); }
bool operator==(const QNetworkConfiguration &other) const;
inline bool operator!=(const QNetworkConfiguration &other) const
diff --git a/src/network/bearer/qnetworkconfiguration_p.h b/src/network/bearer/qnetworkconfiguration_p.h
index 2fdb490ea0..2213d2ae14 100644
--- a/src/network/bearer/qnetworkconfiguration_p.h
+++ b/src/network/bearer/qnetworkconfiguration_p.h
@@ -72,13 +72,6 @@ public:
isValid(false), roamingSupported(false),
timeout(DefaultTimeout)
{}
- virtual ~QNetworkConfigurationPrivate()
- {
- //release pointers to member configurations
- serviceNetworkMembers.clear();
- }
-
- QMap<unsigned int, QNetworkConfigurationPrivatePointer> serviceNetworkMembers;
mutable QMutex mutex;
@@ -97,7 +90,7 @@ public:
static Q_CONSTEXPR int DefaultTimeout = 30000;
private:
- Q_DISABLE_COPY(QNetworkConfigurationPrivate)
+ Q_DISABLE_COPY_MOVE(QNetworkConfigurationPrivate)
};
QT_END_NAMESPACE
diff --git a/src/network/bearer/qsharednetworksession.cpp b/src/network/bearer/qsharednetworksession.cpp
index fc01acb8b4..af543f77e3 100644
--- a/src/network/bearer/qsharednetworksession.cpp
+++ b/src/network/bearer/qsharednetworksession.cpp
@@ -57,36 +57,30 @@ inline QSharedNetworkSessionManager* sharedNetworkSessionManager()
return rv;
}
-static void doDeleteLater(QObject* obj)
-{
- obj->deleteLater();
-}
+struct DeleteLater {
+ void operator()(QObject* obj) const
+ {
+ obj->deleteLater();
+ }
+};
QSharedPointer<QNetworkSession> QSharedNetworkSessionManager::getSession(const QNetworkConfiguration &config)
{
- QSharedNetworkSessionManager *m(sharedNetworkSessionManager());
- const auto it = m->sessions.constFind(config);
+ QSharedNetworkSessionManager *m = sharedNetworkSessionManager();
+ auto &entry = m->sessions[config];
//if already have a session, return it
- if (it != m->sessions.cend()) {
- QSharedPointer<QNetworkSession> p = it.value().toStrongRef();
- if (!p.isNull())
- return p;
- }
+ if (auto p = entry.toStrongRef())
+ return p;
//otherwise make one
- QSharedPointer<QNetworkSession> session(new QNetworkSession(config), doDeleteLater);
- m->sessions[config] = session;
+ QSharedPointer<QNetworkSession> session(new QNetworkSession(config), DeleteLater{});
+ entry = session;
return session;
}
void QSharedNetworkSessionManager::setSession(const QNetworkConfiguration &config, QSharedPointer<QNetworkSession> session)
{
- QSharedNetworkSessionManager *m(sharedNetworkSessionManager());
- m->sessions[config] = session;
-}
-
-uint qHash(const QNetworkConfiguration& config)
-{
- return ((uint)config.type()) | (((uint)config.bearerType()) << 8) | (((uint)config.purpose()) << 16);
+ QSharedNetworkSessionManager *m = sharedNetworkSessionManager();
+ m->sessions[config] = std::move(session);
}
QT_END_NAMESPACE
diff --git a/src/network/bearer/qsharednetworksession_p.h b/src/network/bearer/qsharednetworksession_p.h
index 001b8af02a..f22f9eeacb 100644
--- a/src/network/bearer/qsharednetworksession_p.h
+++ b/src/network/bearer/qsharednetworksession_p.h
@@ -54,16 +54,26 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qnetworksession.h"
#include "qnetworkconfiguration.h"
-#include <QHash>
#include <QSharedPointer>
#include <QWeakPointer>
#include <QMutex>
+#include <unordered_map>
+
#ifndef QT_NO_BEARERMANAGEMENT
QT_BEGIN_NAMESPACE
-uint qHash(const QNetworkConfiguration& config);
+namespace QtPrivate {
+struct NetworkConfigurationHash {
+ using result_type = size_t;
+ using argument_type = QNetworkConfiguration;
+ size_t operator()(const QNetworkConfiguration &config) const noexcept
+ {
+ return std::hash<size_t>{}(size_t(config.type()) | (size_t(config.bearerType()) << 8) | (size_t(config.purpose()) << 16));
+ }
+};
+}
class QSharedNetworkSessionManager
{
@@ -71,7 +81,7 @@ public:
static QSharedPointer<QNetworkSession> getSession(const QNetworkConfiguration &config);
static void setSession(const QNetworkConfiguration &config, QSharedPointer<QNetworkSession> session);
private:
- QHash<QNetworkConfiguration, QWeakPointer<QNetworkSession> > sessions;
+ std::unordered_map<QNetworkConfiguration, QWeakPointer<QNetworkSession>, QtPrivate::NetworkConfigurationHash> sessions;
};
QT_END_NAMESPACE
diff --git a/src/network/configure.json b/src/network/configure.json
index 2c005f0efb..56805da7b2 100644
--- a/src/network/configure.json
+++ b/src/network/configure.json
@@ -15,8 +15,10 @@
"openssl-linked": { "type": "void", "name": "openssl", "value": "linked" },
"openssl-runtime": { "type": "void", "name": "openssl", "value": "runtime" },
"dtls": "boolean",
+ "ocsp": "boolean",
"sctp": "boolean",
"securetransport": "boolean",
+ "schannel": "boolean",
"ssl": "boolean",
"system-proxies": "boolean"
}
@@ -184,6 +186,28 @@
]
},
"use": "openssl"
+ },
+ "ocsp": {
+ "label": "OCSP stapling support in OpenSSL",
+ "type": "compile",
+ "test": {
+ "include": ["openssl/ssl.h", "openssl/ocsp.h"],
+ "tail": [
+ "#if defined(OPENSSL_NO_OCSP) || defined(OPENSSL_NO_TLSEXT)",
+ "# error OpenSSL without OCSP stapling",
+ "#endif"
+ ]
+ },
+ "use": "openssl"
+ },
+ "gssapi": {
+ "label": "KRB5 GSSAPI support",
+ "type": "compile",
+ "test": {
+ "include": [ "gssapi/gssapi.h" ],
+ "main": ["gss_ctx_id_t ctx;"],
+ "qmake": "LIBS += -lgssapi_krb5"
+ }
}
},
@@ -229,13 +253,13 @@
"autoDetect": "!config.winrt && !config.wasm",
"enable": "input.openssl == 'yes' || input.openssl == 'runtime'",
"disable": "input.openssl == 'no' || input.openssl == 'linked' || input.ssl == 'no'",
- "condition": "!features.securetransport && libs.openssl_headers"
+ "condition": "!features.securetransport && !features.schannel && libs.openssl_headers"
},
"openssl-linked": {
"label": " Qt directly linked to OpenSSL",
"autoDetect": false,
"enable": "input.openssl == 'linked'",
- "condition": "!features.securetransport && libs.openssl",
+ "condition": "!features.securetransport && !features.schannel && libs.openssl",
"output": [
"privateFeature",
{ "type": "define", "name": "QT_LINKED_OPENSSL" }
@@ -246,20 +270,36 @@
"disable": "input.securetransport == 'no' || input.ssl == 'no'",
"condition": "config.darwin && (input.openssl == '' || input.openssl == 'no')",
"output": [
- "privateFeature",
+ "publicFeature",
{ "type": "define", "name": "QT_SECURETRANSPORT" }
]
},
+ "schannel": {
+ "label": "Schannel",
+ "disable": "input.schannel == 'no' || input.ssl == 'no'",
+ "condition": "input.schannel == 'yes' && config.win32 && !config.winrt && (input.openssl == '' || input.openssl == 'no')",
+ "output": [
+ "publicFeature",
+ { "type": "define", "name": "QT_SCHANNEL" }
+ ]
+ },
"ssl": {
"label": "SSL",
- "condition": "config.winrt || features.securetransport || features.openssl",
+ "condition": "config.winrt || features.securetransport || features.openssl || features.schannel",
"output": [ "publicFeature", "feature" ]
},
"dtls": {
"label": "DTLS",
"purpose": "Provides a DTLS implementation",
"section": "Networking",
- "condition": "features.openssl && tests.dtls",
+ "condition": "features.openssl && features.udpsocket && tests.dtls",
+ "output": [ "publicFeature" ]
+ },
+ "ocsp": {
+ "label": "OCSP-stapling",
+ "purpose": "Provides OCSP stapling support",
+ "section": "Networking",
+ "condition": "features.opensslv11 && tests.ocsp",
"output": [ "publicFeature" ]
},
"opensslv11": {
@@ -343,6 +383,20 @@
"purpose": "Provides API for DNS lookups.",
"section": "Networking",
"output": [ "publicFeature" ]
+ },
+ "gssapi": {
+ "label": "GSSAPI",
+ "purpose": "Enable SPNEGO authentication through GSSAPI",
+ "section": "Networking",
+ "condition": "!config.win32 && tests.gssapi",
+ "output": [ "publicFeature", "feature" ]
+ },
+ "sspi": {
+ "label": "SSPI",
+ "purpose": "Enable NTLM/SPNEGO authentication through SSPI",
+ "section": "Networking",
+ "condition": "config.win32 && !config.winrt",
+ "output": [ "publicFeature", "feature" ]
}
},
@@ -391,12 +445,19 @@ For example:
"args": "securetransport",
"condition": "config.darwin"
},
+ {
+ "type": "feature",
+ "args": "schannel",
+ "condition": "config.win32 && !config.winrt"
+ },
"openssl",
"openssl-linked",
"opensslv11",
"dtls",
+ "ocsp",
"sctp",
- "system-proxies"
+ "system-proxies",
+ "gssapi"
]
}
]
diff --git a/src/network/doc/src/dontdocument.qdoc b/src/network/doc/src/dontdocument.qdoc
new file mode 100644
index 0000000000..fe2e54b34c
--- /dev/null
+++ b/src/network/doc/src/dontdocument.qdoc
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+/*!
+ \dontdocument (QTypeInfo QMetaTypeId QIPv6Address)
+*/
diff --git a/src/network/doc/src/ssl.qdoc b/src/network/doc/src/ssl.qdoc
index a3af1d0477..e485a1b393 100644
--- a/src/network/doc/src/ssl.qdoc
+++ b/src/network/doc/src/ssl.qdoc
@@ -77,11 +77,12 @@
\section1 Import and Export Restrictions
- Due to import and export restrictions in some parts of the world, we
- are unable to supply the OpenSSL Toolkit with Qt packages. Developers wishing
- to use SSL communication in their deployed applications should either ensure
- that their users have the appropriate libraries installed, or they should
- consult a suitably qualified legal professional to ensure that applications
- using code from the OpenSSL project are correctly certified for import
- and export in relevant regions of the world.
+ Qt binary installers include the OpenSSL libraries used by QtNetwork. However,
+ those are not automatically deployed with applications that are built with Qt.
+ Import and export restrictions apply for some types of software, and for
+ some parts of the world. Developers wishing to use SSL communication in their
+ deployed applications should either ensure that their users have the appropriate
+ libraries installed, or they should consult a suitably qualified legal
+ professional to ensure that applications using code from the OpenSSL project
+ are correctly certified for import and export in relevant regions of the world.
*/
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri
index 7074fcd5eb..0e4cef5e74 100644
--- a/src/network/kernel/kernel.pri
+++ b/src/network/kernel/kernel.pri
@@ -16,7 +16,8 @@ HEADERS += kernel/qtnetworkglobal.h \
kernel/qnetworkinterface.h \
kernel/qnetworkinterface_p.h \
kernel/qnetworkinterface_unix_p.h \
- kernel/qnetworkproxy.h
+ kernel/qnetworkproxy.h \
+ kernel/qnetconmonitor_p.h
SOURCES += kernel/qauthenticator.cpp \
kernel/qhostaddress.cpp \
@@ -71,6 +72,17 @@ mac {
!uikit: LIBS_PRIVATE += -framework CoreServices -framework SystemConfiguration
}
+macos | ios {
+ OBJECTIVE_SOURCES += \
+ kernel/qnetconmonitor_darwin.mm
+
+ LIBS_PRIVATE += -framework SystemConfiguration
+} else {
+ SOURCES += kernel/qnetconmonitor_stub.cpp
+}
+
+qtConfig(gssapi): LIBS_PRIVATE += -lgssapi_krb5
+
uikit:HEADERS += kernel/qnetworkinterface_uikit_p.h
osx:SOURCES += kernel/qnetworkproxy_mac.cpp
else:win32:!winrt: SOURCES += kernel/qnetworkproxy_win.cpp
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp
index 34db5b4b31..3ca8806c2b 100644
--- a/src/network/kernel/qauthenticator.cpp
+++ b/src/network/kernel/qauthenticator.cpp
@@ -54,20 +54,29 @@
#include <qmutex.h>
#include <private/qmutexpool_p.h>
#include <rpc.h>
-#ifndef Q_OS_WINRT
+#endif
+
+#if QT_CONFIG(sspi) // SSPI
#define SECURITY_WIN32 1
#include <security.h>
-#endif
+#elif QT_CONFIG(gssapi) // GSSAPI
+#include <gssapi/gssapi.h>
#endif
QT_BEGIN_NAMESPACE
static QByteArray qNtlmPhase1();
static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phase2data);
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
-static QByteArray qNtlmPhase1_SSPI(QAuthenticatorPrivate *ctx);
-static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& phase2data);
-#endif
+#if QT_CONFIG(sspi) // SSPI
+static QByteArray qSspiStartup(QAuthenticatorPrivate *ctx, QAuthenticatorPrivate::Method method,
+ const QString& host);
+static QByteArray qSspiContinue(QAuthenticatorPrivate *ctx, QAuthenticatorPrivate::Method method,
+ const QString& host, const QByteArray& challenge = QByteArray());
+#elif QT_CONFIG(gssapi) // GSSAPI
+static QByteArray qGssapiStartup(QAuthenticatorPrivate *ctx, const QString& host);
+static QByteArray qGssapiContinue(QAuthenticatorPrivate *ctx,
+ const QByteArray& challenge = QByteArray());
+#endif // gssapi
/*!
\class QAuthenticator
@@ -90,6 +99,7 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray&
\li Basic
\li NTLM version 2
\li Digest-MD5
+ \li SPNEGO/Negotiate
\endlist
\target qauthenticator-options
@@ -133,6 +143,10 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray&
The Digest-MD5 authentication mechanism supports no outgoing options.
+ \section2 SPNEGO/Negotiate
+
+ This authentication mechanism currently supports no incoming or outgoing options.
+
\sa QSslSocket
*/
@@ -187,7 +201,7 @@ QAuthenticator &QAuthenticator::operator=(const QAuthenticator &other)
d->options = other.d->options;
} else if (d->phase == QAuthenticatorPrivate::Start) {
delete d;
- d = 0;
+ d = nullptr;
}
return *this;
}
@@ -339,21 +353,25 @@ bool QAuthenticator::isNull() const
return !d;
}
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
-class QNtlmWindowsHandles
+#if QT_CONFIG(sspi) // SSPI
+class QSSPIWindowsHandles
{
public:
CredHandle credHandle;
CtxtHandle ctxHandle;
};
-#endif
+#elif QT_CONFIG(gssapi) // GSSAPI
+class QGssApiHandles
+{
+public:
+ gss_ctx_id_t gssCtx = nullptr;
+ gss_name_t targetName;
+};
+#endif // gssapi
QAuthenticatorPrivate::QAuthenticatorPrivate()
: method(None)
- #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
- , ntlmWindowsHandles(0)
- #endif
, hasFailed(false)
, phase(Start)
, nonceCount(0)
@@ -363,13 +381,7 @@ QAuthenticatorPrivate::QAuthenticatorPrivate()
nonceCount = 0;
}
-QAuthenticatorPrivate::~QAuthenticatorPrivate()
-{
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
- if (ntlmWindowsHandles)
- delete ntlmWindowsHandles;
-#endif
-}
+QAuthenticatorPrivate::~QAuthenticatorPrivate() = default;
void QAuthenticatorPrivate::updateCredentials()
{
@@ -424,6 +436,9 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt
} else if (method < DigestMd5 && str.startsWith("digest")) {
method = DigestMd5;
headerVal = current.second.mid(7);
+ } else if (method < Negotiate && str.startsWith("negotiate")) {
+ method = Negotiate;
+ headerVal = current.second.mid(10);
}
}
@@ -439,6 +454,7 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt
phase = Done;
break;
case Ntlm:
+ case Negotiate:
// work is done in calculateResponse()
break;
case DigestMd5: {
@@ -456,48 +472,36 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt
}
}
-QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMethod, const QByteArray &path)
+QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMethod, const QByteArray &path, const QString& host)
{
+#if !QT_CONFIG(sspi) && !QT_CONFIG(gssapi)
+ Q_UNUSED(host);
+#endif
QByteArray response;
- const char *methodString = 0;
+ const char* methodString = nullptr;
switch(method) {
case QAuthenticatorPrivate::None:
methodString = "";
phase = Done;
break;
- case QAuthenticatorPrivate::Plain:
- response = '\0' + user.toUtf8() + '\0' + password.toUtf8();
- phase = Done;
- break;
case QAuthenticatorPrivate::Basic:
- methodString = "Basic ";
+ methodString = "Basic";
response = user.toLatin1() + ':' + password.toLatin1();
response = response.toBase64();
phase = Done;
break;
- case QAuthenticatorPrivate::Login:
- if (challenge.contains("VXNlciBOYW1lAA==")) {
- response = user.toUtf8().toBase64();
- phase = Phase2;
- } else if (challenge.contains("UGFzc3dvcmQA")) {
- response = password.toUtf8().toBase64();
- phase = Done;
- }
- break;
- case QAuthenticatorPrivate::CramMd5:
- break;
case QAuthenticatorPrivate::DigestMd5:
- methodString = "Digest ";
+ methodString = "Digest";
response = digestMd5Response(challenge, requestMethod, path);
phase = Done;
break;
case QAuthenticatorPrivate::Ntlm:
- methodString = "NTLM ";
+ methodString = "NTLM";
if (challenge.isEmpty()) {
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if QT_CONFIG(sspi) // SSPI
QByteArray phase1Token;
if (user.isEmpty()) // Only pull from system if no user was specified in authenticator
- phase1Token = qNtlmPhase1_SSPI(this);
+ phase1Token = qSspiStartup(this, method, host);
if (!phase1Token.isEmpty()) {
response = phase1Token.toBase64();
phase = Phase2;
@@ -511,10 +515,10 @@ QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMet
phase = Phase2;
}
} else {
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if QT_CONFIG(sspi) // SSPI
QByteArray phase3Token;
- if (ntlmWindowsHandles)
- phase3Token = qNtlmPhase3_SSPI(this, QByteArray::fromBase64(challenge));
+ if (sspiWindowsHandles)
+ phase3Token = qSspiContinue(this, method, host, QByteArray::fromBase64(challenge));
if (!phase3Token.isEmpty()) {
response = phase3Token.toBase64();
phase = Done;
@@ -527,8 +531,39 @@ QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMet
}
break;
+ case QAuthenticatorPrivate::Negotiate:
+ methodString = "Negotiate";
+ if (challenge.isEmpty()) {
+ QByteArray phase1Token;
+#if QT_CONFIG(sspi) // SSPI
+ phase1Token = qSspiStartup(this, method, host);
+#elif QT_CONFIG(gssapi) // GSSAPI
+ phase1Token = qGssapiStartup(this, host);
+#endif
+
+ if (!phase1Token.isEmpty()) {
+ response = phase1Token.toBase64();
+ phase = Phase2;
+ } else {
+ phase = Done;
+ }
+ } else {
+ QByteArray phase3Token;
+#if QT_CONFIG(sspi) // SSPI
+ phase3Token = qSspiContinue(this, method, host, QByteArray::fromBase64(challenge));
+#elif QT_CONFIG(gssapi) // GSSAPI
+ phase3Token = qGssapiContinue(this, QByteArray::fromBase64(challenge));
+#endif
+ if (!phase3Token.isEmpty()) {
+ response = phase3Token.toBase64();
+ phase = Done;
+ }
+ }
+
+ break;
}
- return QByteArray(methodString) + response;
+
+ return QByteArray::fromRawData(methodString, qstrlen(methodString)) + ' ' + response;
}
@@ -714,9 +749,10 @@ QByteArray QAuthenticatorPrivate::digestMd5Response(const QByteArray &challenge,
return credentials;
}
-// ---------------------------- Digest Md5 code ----------------------------------------
+// ---------------------------- End of Digest Md5 code ---------------------------------
+// ---------------------------- NTLM code ----------------------------------------------
/*
* NTLM message flags.
@@ -1434,156 +1470,237 @@ static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phas
return rc;
}
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+// ---------------------------- End of NTLM code ---------------------------------------
+
+#if QT_CONFIG(sspi) // SSPI
+// ---------------------------- SSPI code ----------------------------------------------
// See http://davenport.sourceforge.net/ntlm.html
// and libcurl http_ntlm.c
// Handle of secur32.dll
-static HMODULE securityDLLHandle = NULL;
+static HMODULE securityDLLHandle = nullptr;
// Pointer to SSPI dispatch table
-static PSecurityFunctionTable pSecurityFunctionTable = NULL;
-
+static PSecurityFunctionTable pSecurityFunctionTable = nullptr;
-static bool q_NTLM_SSPI_library_load()
+static bool q_SSPI_library_load()
{
static QBasicMutex mutex;
QMutexLocker l(&mutex);
// Initialize security interface
- if (pSecurityFunctionTable == NULL) {
+ if (pSecurityFunctionTable == nullptr) {
securityDLLHandle = LoadLibrary(L"secur32.dll");
- if (securityDLLHandle != NULL) {
+ if (securityDLLHandle != nullptr) {
INIT_SECURITY_INTERFACE pInitSecurityInterface =
reinterpret_cast<INIT_SECURITY_INTERFACE>(
reinterpret_cast<QFunctionPointer>(GetProcAddress(securityDLLHandle, "InitSecurityInterfaceW")));
- if (pInitSecurityInterface != NULL)
+ if (pInitSecurityInterface != nullptr)
pSecurityFunctionTable = pInitSecurityInterface();
}
}
- if (pSecurityFunctionTable == NULL)
+ if (pSecurityFunctionTable == nullptr)
return false;
return true;
}
-// Phase 1:
-static QByteArray qNtlmPhase1_SSPI(QAuthenticatorPrivate *ctx)
+static QByteArray qSspiStartup(QAuthenticatorPrivate *ctx, QAuthenticatorPrivate::Method method,
+ const QString& host)
{
- QByteArray result;
+ if (!q_SSPI_library_load())
+ return QByteArray();
- if (!q_NTLM_SSPI_library_load())
- return result;
+ TimeStamp expiry; // For Windows 9x compatibility of SSPI calls
- // 1. The client obtains a representation of the credential set
- // for the user via the SSPI AcquireCredentialsHandle function.
- if (!ctx->ntlmWindowsHandles)
- ctx->ntlmWindowsHandles = new QNtlmWindowsHandles;
- memset(&ctx->ntlmWindowsHandles->credHandle, 0, sizeof(CredHandle));
- TimeStamp tsDummy;
+ if (!ctx->sspiWindowsHandles)
+ ctx->sspiWindowsHandles.reset(new QSSPIWindowsHandles);
+ memset(&ctx->sspiWindowsHandles->credHandle, 0, sizeof(CredHandle));
+
+ // Acquire our credentials handle
SECURITY_STATUS secStatus = pSecurityFunctionTable->AcquireCredentialsHandle(
- NULL, (SEC_WCHAR*)L"NTLM", SECPKG_CRED_OUTBOUND, NULL, NULL,
- NULL, NULL, &ctx->ntlmWindowsHandles->credHandle, &tsDummy);
+ nullptr,
+ (SEC_WCHAR*)(method == QAuthenticatorPrivate::Negotiate ? L"Negotiate" : L"NTLM"),
+ SECPKG_CRED_OUTBOUND, nullptr, nullptr, nullptr, nullptr,
+ &ctx->sspiWindowsHandles->credHandle, &expiry
+ );
if (secStatus != SEC_E_OK) {
- delete ctx->ntlmWindowsHandles;
- ctx->ntlmWindowsHandles = 0;
- return result;
+ ctx->sspiWindowsHandles.reset(nullptr);
+ return QByteArray();
+ }
+
+ return qSspiContinue(ctx, method, host);
+}
+
+static QByteArray qSspiContinue(QAuthenticatorPrivate *ctx, QAuthenticatorPrivate::Method method,
+ const QString &host, const QByteArray &challenge)
+{
+ QByteArray result;
+ SecBuffer challengeBuf;
+ SecBuffer responseBuf;
+ SecBufferDesc challengeDesc;
+ SecBufferDesc responseDesc;
+ unsigned long attrs;
+ TimeStamp expiry; // For Windows 9x compatibility of SSPI calls
+
+ if (!challenge.isEmpty())
+ {
+ // Setup the challenge "input" security buffer
+ challengeDesc.ulVersion = SECBUFFER_VERSION;
+ challengeDesc.cBuffers = 1;
+ challengeDesc.pBuffers = &challengeBuf;
+ challengeBuf.BufferType = SECBUFFER_TOKEN;
+ challengeBuf.pvBuffer = (PVOID)(challenge.data());
+ challengeBuf.cbBuffer = challenge.length();
+ }
+
+ // Setup the response "output" security buffer
+ responseDesc.ulVersion = SECBUFFER_VERSION;
+ responseDesc.cBuffers = 1;
+ responseDesc.pBuffers = &responseBuf;
+ responseBuf.BufferType = SECBUFFER_TOKEN;
+ responseBuf.pvBuffer = nullptr;
+ responseBuf.cbBuffer = 0;
+
+ // Calculate target (SPN for Negotiate, empty for NTLM)
+ std::wstring targetNameW = (method == QAuthenticatorPrivate::Negotiate
+ ? QLatin1String("HTTP/") + host : QString()).toStdWString();
+
+ // Generate our challenge-response message
+ SECURITY_STATUS secStatus = pSecurityFunctionTable->InitializeSecurityContext(
+ &ctx->sspiWindowsHandles->credHandle,
+ !challenge.isEmpty() ? &ctx->sspiWindowsHandles->ctxHandle : nullptr,
+ const_cast<wchar_t*>(targetNameW.data()),
+ ISC_REQ_ALLOCATE_MEMORY,
+ 0, SECURITY_NATIVE_DREP,
+ !challenge.isEmpty() ? &challengeDesc : nullptr,
+ 0, &ctx->sspiWindowsHandles->ctxHandle,
+ &responseDesc, &attrs,
+ &expiry
+ );
+
+ if (secStatus == SEC_I_COMPLETE_NEEDED || secStatus == SEC_I_COMPLETE_AND_CONTINUE) {
+ secStatus = pSecurityFunctionTable->CompleteAuthToken(&ctx->sspiWindowsHandles->ctxHandle,
+ &responseDesc);
}
- // 2. The client calls the SSPI InitializeSecurityContext function
- // to obtain an authentication request token (in our case, a Type 1 message).
- // The client sends this token to the server.
- SecBufferDesc desc;
- SecBuffer buf;
- desc.ulVersion = SECBUFFER_VERSION;
- desc.cBuffers = 1;
- desc.pBuffers = &buf;
- buf.cbBuffer = 0;
- buf.BufferType = SECBUFFER_TOKEN;
- buf.pvBuffer = NULL;
- ULONG attrs;
-
- secStatus = pSecurityFunctionTable->InitializeSecurityContext(&ctx->ntlmWindowsHandles->credHandle, NULL,
- const_cast<SEC_WCHAR*>(L"") /* host */,
- ISC_REQ_ALLOCATE_MEMORY,
- 0, SECURITY_NETWORK_DREP,
- NULL, 0,
- &ctx->ntlmWindowsHandles->ctxHandle, &desc,
- &attrs, &tsDummy);
- if (secStatus == SEC_I_COMPLETE_AND_CONTINUE ||
- secStatus == SEC_I_CONTINUE_NEEDED) {
- pSecurityFunctionTable->CompleteAuthToken(&ctx->ntlmWindowsHandles->ctxHandle, &desc);
- } else if (secStatus != SEC_E_OK) {
- if ((const char*)buf.pvBuffer)
- pSecurityFunctionTable->FreeContextBuffer(buf.pvBuffer);
- pSecurityFunctionTable->FreeCredentialsHandle(&ctx->ntlmWindowsHandles->credHandle);
- delete ctx->ntlmWindowsHandles;
- ctx->ntlmWindowsHandles = 0;
- return result;
+ if (secStatus != SEC_I_COMPLETE_AND_CONTINUE && secStatus != SEC_I_CONTINUE_NEEDED) {
+ pSecurityFunctionTable->FreeCredentialsHandle(&ctx->sspiWindowsHandles->credHandle);
+ pSecurityFunctionTable->DeleteSecurityContext(&ctx->sspiWindowsHandles->ctxHandle);
+ ctx->sspiWindowsHandles.reset(nullptr);
}
- result = QByteArray((const char*)buf.pvBuffer, buf.cbBuffer);
- pSecurityFunctionTable->FreeContextBuffer(buf.pvBuffer);
+ result = QByteArray((const char*)responseBuf.pvBuffer, responseBuf.cbBuffer);
+ pSecurityFunctionTable->FreeContextBuffer(responseBuf.pvBuffer);
+
return result;
}
-// Phase 2:
-// 3. The server receives the token from the client, and uses it as input to the
-// AcceptSecurityContext SSPI function. This creates a local security context on
-// the server to represent the client, and yields an authentication response token
-// (the Type 2 message), which is sent to the client.
+// ---------------------------- End of SSPI code ---------------------------------------
+
+#elif QT_CONFIG(gssapi) // GSSAPI
+
+// ---------------------------- GSSAPI code ----------------------------------------------
+// See postgres src/interfaces/libpq/fe-auth.c
+
+// Fetch all errors of a specific type
+static void q_GSSAPI_error_int(const char *message, OM_uint32 stat, int type)
+{
+ OM_uint32 minStat, msgCtx = 0;
+ gss_buffer_desc msg;
+
+ do {
+ gss_display_status(&minStat, stat, type, GSS_C_NO_OID, &msgCtx, &msg);
+ qDebug() << message << ": " << reinterpret_cast<const char*>(msg.value);
+ gss_release_buffer(&minStat, &msg);
+ } while (msgCtx);
+}
+
+// GSSAPI errors contain two parts; extract both
+static void q_GSSAPI_error(const char *message, OM_uint32 majStat, OM_uint32 minStat)
+{
+ // Fetch major error codes
+ q_GSSAPI_error_int(message, majStat, GSS_C_GSS_CODE);
+
+ // Add the minor codes as well
+ q_GSSAPI_error_int(message, minStat, GSS_C_MECH_CODE);
+}
-// Phase 3:
-static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& phase2data)
+// Send initial GSS authentication token
+static QByteArray qGssapiStartup(QAuthenticatorPrivate *ctx, const QString &host)
{
- // 4. The client receives the response token from the server and calls
- // InitializeSecurityContext again, passing the server's token as input.
- // This provides us with another authentication request token (the Type 3 message).
- // The return value indicates that the security context was successfully initialized;
- // the token is sent to the server.
+ OM_uint32 majStat, minStat;
+
+ if (!ctx->gssApiHandles)
+ ctx->gssApiHandles.reset(new QGssApiHandles);
+
+ // Convert target name to internal form
+ QByteArray serviceName = QStringLiteral("HTTPS@%1").arg(host).toLocal8Bit();
+ gss_buffer_desc nameDesc = {static_cast<std::size_t>(serviceName.size()), serviceName.data()};
+
+ majStat = gss_import_name(&minStat, &nameDesc,
+ GSS_C_NT_HOSTBASED_SERVICE, &ctx->gssApiHandles->targetName);
+
+ if (majStat != GSS_S_COMPLETE) {
+ q_GSSAPI_error("gss_import_name error", majStat, minStat);
+ ctx->gssApiHandles.reset(nullptr);
+ return QByteArray();
+ }
+ // Call qGssapiContinue with GSS_C_NO_CONTEXT to get initial packet
+ ctx->gssApiHandles->gssCtx = GSS_C_NO_CONTEXT;
+ return qGssapiContinue(ctx);
+}
+
+// Continue GSS authentication with next token as needed
+static QByteArray qGssapiContinue(QAuthenticatorPrivate *ctx, const QByteArray& challenge)
+{
+ OM_uint32 majStat, minStat, ignored;
QByteArray result;
+ gss_buffer_desc inBuf = {0, nullptr}; // GSS input token
+ gss_buffer_desc outBuf; // GSS output token
- if (pSecurityFunctionTable == NULL)
- return result;
-
- SecBuffer type_2, type_3;
- SecBufferDesc type_2_desc, type_3_desc;
- ULONG attrs;
- TimeStamp tsDummy; // For Windows 9x compatibility of SPPI calls
-
- type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
- type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
- type_2_desc.pBuffers = &type_2;
- type_3_desc.pBuffers = &type_3;
-
- type_2.BufferType = SECBUFFER_TOKEN;
- type_2.pvBuffer = (PVOID)phase2data.data();
- type_2.cbBuffer = phase2data.length();
- type_3.BufferType = SECBUFFER_TOKEN;
- type_3.pvBuffer = 0;
- type_3.cbBuffer = 0;
-
- SECURITY_STATUS secStatus = pSecurityFunctionTable->InitializeSecurityContext(&ctx->ntlmWindowsHandles->credHandle,
- &ctx->ntlmWindowsHandles->ctxHandle,
- const_cast<SEC_WCHAR*>(L"") /* host */,
- ISC_REQ_ALLOCATE_MEMORY,
- 0, SECURITY_NETWORK_DREP, &type_2_desc,
- 0, &ctx->ntlmWindowsHandles->ctxHandle, &type_3_desc,
- &attrs, &tsDummy);
-
- if (secStatus == SEC_E_OK && ((const char*)type_3.pvBuffer)) {
- result = QByteArray((const char*)type_3.pvBuffer, type_3.cbBuffer);
- pSecurityFunctionTable->FreeContextBuffer(type_3.pvBuffer);
+ if (!challenge.isEmpty()) {
+ inBuf.value = const_cast<char*>(challenge.data());
+ inBuf.length = challenge.length();
}
- pSecurityFunctionTable->FreeCredentialsHandle(&ctx->ntlmWindowsHandles->credHandle);
- pSecurityFunctionTable->DeleteSecurityContext(&ctx->ntlmWindowsHandles->ctxHandle);
- delete ctx->ntlmWindowsHandles;
- ctx->ntlmWindowsHandles = 0;
+ majStat = gss_init_sec_context(&minStat,
+ GSS_C_NO_CREDENTIAL,
+ &ctx->gssApiHandles->gssCtx,
+ ctx->gssApiHandles->targetName,
+ GSS_C_NO_OID,
+ GSS_C_MUTUAL_FLAG,
+ 0,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ challenge.isEmpty() ? GSS_C_NO_BUFFER : &inBuf,
+ nullptr,
+ &outBuf,
+ nullptr,
+ nullptr);
+
+ if (outBuf.length != 0)
+ result = QByteArray(reinterpret_cast<const char*>(outBuf.value), outBuf.length);
+ gss_release_buffer(&ignored, &outBuf);
+
+ if (majStat != GSS_S_COMPLETE && majStat != GSS_S_CONTINUE_NEEDED) {
+ q_GSSAPI_error("gss_init_sec_context error", majStat, minStat);
+ gss_release_name(&ignored, &ctx->gssApiHandles->targetName);
+ if (ctx->gssApiHandles->gssCtx)
+ gss_delete_sec_context(&ignored, &ctx->gssApiHandles->gssCtx, GSS_C_NO_BUFFER);
+ ctx->gssApiHandles.reset(nullptr);
+ }
+
+ if (majStat == GSS_S_COMPLETE) {
+ gss_release_name(&ignored, &ctx->gssApiHandles->targetName);
+ ctx->gssApiHandles.reset(nullptr);
+ }
return result;
}
-#endif // Q_OS_WIN && !Q_OS_WINRT
+
+// ---------------------------- End of GSSAPI code ----------------------------------------------
+
+#endif // gssapi
QT_END_NAMESPACE
diff --git a/src/network/kernel/qauthenticator_p.h b/src/network/kernel/qauthenticator_p.h
index 8a1ee0ebe6..e201d22650 100644
--- a/src/network/kernel/qauthenticator_p.h
+++ b/src/network/kernel/qauthenticator_p.h
@@ -54,6 +54,7 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <qhash.h>
#include <qbytearray.h>
+#include <qscopedpointer.h>
#include <qstring.h>
#include <qauthenticator.h>
#include <qvariant.h>
@@ -61,14 +62,16 @@
QT_BEGIN_NAMESPACE
class QHttpResponseHeader;
-#ifdef Q_OS_WIN
-class QNtlmWindowsHandles;
+#if QT_CONFIG(sspi) // SSPI
+class QSSPIWindowsHandles;
+#elif QT_CONFIG(gssapi) // GSSAPI
+class QGssApiHandles;
#endif
class Q_AUTOTEST_EXPORT QAuthenticatorPrivate
{
public:
- enum Method { None, Basic, Plain, Login, Ntlm, CramMd5, DigestMd5 };
+ enum Method { None, Basic, Ntlm, DigestMd5, Negotiate };
QAuthenticatorPrivate();
~QAuthenticatorPrivate();
@@ -79,8 +82,10 @@ public:
Method method;
QString realm;
QByteArray challenge;
-#ifdef Q_OS_WIN
- QNtlmWindowsHandles *ntlmWindowsHandles;
+#if QT_CONFIG(sspi) // SSPI
+ QScopedPointer<QSSPIWindowsHandles> sspiWindowsHandles;
+#elif QT_CONFIG(gssapi) // GSSAPI
+ QScopedPointer<QGssApiHandles> gssApiHandles;
#endif
bool hasFailed; //credentials have been tried but rejected by server.
@@ -100,7 +105,7 @@ public:
QString workstation;
QString userDomain;
- QByteArray calculateResponse(const QByteArray &method, const QByteArray &path);
+ QByteArray calculateResponse(const QByteArray &method, const QByteArray &path, const QString& host);
inline static QAuthenticatorPrivate *getPrivate(QAuthenticator &auth) { return auth.d; }
inline static const QAuthenticatorPrivate *getPrivate(const QAuthenticator &auth) { return auth.d; }
diff --git a/src/network/kernel/qdnslookup.h b/src/network/kernel/qdnslookup.h
index eebd0abe66..110a74da44 100644
--- a/src/network/kernel/qdnslookup.h
+++ b/src/network/kernel/qdnslookup.h
@@ -64,13 +64,11 @@ class Q_NETWORK_EXPORT QDnsDomainNameRecord
public:
QDnsDomainNameRecord();
QDnsDomainNameRecord(const QDnsDomainNameRecord &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QDnsDomainNameRecord &operator=(QDnsDomainNameRecord &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDnsDomainNameRecord &operator=(QDnsDomainNameRecord &&other) noexcept { swap(other); return *this; }
QDnsDomainNameRecord &operator=(const QDnsDomainNameRecord &other);
~QDnsDomainNameRecord();
- void swap(QDnsDomainNameRecord &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QDnsDomainNameRecord &other) noexcept { qSwap(d, other.d); }
QString name() const;
quint32 timeToLive() const;
@@ -88,13 +86,11 @@ class Q_NETWORK_EXPORT QDnsHostAddressRecord
public:
QDnsHostAddressRecord();
QDnsHostAddressRecord(const QDnsHostAddressRecord &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QDnsHostAddressRecord &operator=(QDnsHostAddressRecord &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDnsHostAddressRecord &operator=(QDnsHostAddressRecord &&other) noexcept { swap(other); return *this; }
QDnsHostAddressRecord &operator=(const QDnsHostAddressRecord &other);
~QDnsHostAddressRecord();
- void swap(QDnsHostAddressRecord &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QDnsHostAddressRecord &other) noexcept { qSwap(d, other.d); }
QString name() const;
quint32 timeToLive() const;
@@ -112,13 +108,11 @@ class Q_NETWORK_EXPORT QDnsMailExchangeRecord
public:
QDnsMailExchangeRecord();
QDnsMailExchangeRecord(const QDnsMailExchangeRecord &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QDnsMailExchangeRecord &operator=(QDnsMailExchangeRecord &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDnsMailExchangeRecord &operator=(QDnsMailExchangeRecord &&other) noexcept { swap(other); return *this; }
QDnsMailExchangeRecord &operator=(const QDnsMailExchangeRecord &other);
~QDnsMailExchangeRecord();
- void swap(QDnsMailExchangeRecord &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QDnsMailExchangeRecord &other) noexcept { qSwap(d, other.d); }
QString exchange() const;
QString name() const;
@@ -137,13 +131,11 @@ class Q_NETWORK_EXPORT QDnsServiceRecord
public:
QDnsServiceRecord();
QDnsServiceRecord(const QDnsServiceRecord &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QDnsServiceRecord &operator=(QDnsServiceRecord &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDnsServiceRecord &operator=(QDnsServiceRecord &&other) noexcept { swap(other); return *this; }
QDnsServiceRecord &operator=(const QDnsServiceRecord &other);
~QDnsServiceRecord();
- void swap(QDnsServiceRecord &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QDnsServiceRecord &other) noexcept { qSwap(d, other.d); }
QString name() const;
quint16 port() const;
@@ -164,13 +156,11 @@ class Q_NETWORK_EXPORT QDnsTextRecord
public:
QDnsTextRecord();
QDnsTextRecord(const QDnsTextRecord &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QDnsTextRecord &operator=(QDnsTextRecord &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QDnsTextRecord &operator=(QDnsTextRecord &&other) noexcept { swap(other); return *this; }
QDnsTextRecord &operator=(const QDnsTextRecord &other);
~QDnsTextRecord();
- void swap(QDnsTextRecord &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QDnsTextRecord &other) noexcept { qSwap(d, other.d); }
QString name() const;
quint32 timeToLive() const;
diff --git a/src/network/kernel/qdnslookup_p.h b/src/network/kernel/qdnslookup_p.h
index 2dc98e527a..8c3c2ed3e1 100644
--- a/src/network/kernel/qdnslookup_p.h
+++ b/src/network/kernel/qdnslookup_p.h
@@ -95,7 +95,7 @@ public:
QDnsLookupPrivate()
: isFinished(false)
, type(QDnsLookup::A)
- , runnable(0)
+ , runnable(nullptr)
{ }
void _q_lookupFinished(const QDnsLookupReply &reply);
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index 5d0ef150f3..b54fb349fb 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -1333,7 +1333,7 @@ QDebug operator<<(QDebug d, const QHostAddress &address)
\relates QHostAddress
Returns a hash of the host address \a key, using \a seed to seed the calculation.
*/
-uint qHash(const QHostAddress &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QHostAddress &key, uint seed) noexcept
{
return qHashBits(key.d->a6.c, 16, seed);
}
diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h
index 00555f3d8e..799247695e 100644
--- a/src/network/kernel/qhostaddress.h
+++ b/src/network/kernel/qhostaddress.h
@@ -66,7 +66,7 @@ typedef QIPv6Address Q_IPV6ADDR;
class QHostAddress;
// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
-Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed = 0) noexcept;
class Q_NETWORK_EXPORT QHostAddress
{
@@ -102,11 +102,8 @@ public:
QHostAddress(SpecialAddress address);
~QHostAddress();
-#ifdef Q_COMPILER_RVALUE_REFS
- QHostAddress &operator=(QHostAddress &&other) Q_DECL_NOTHROW
+ QHostAddress &operator=(QHostAddress &&other) noexcept
{ swap(other); return *this; }
-#endif
-
QHostAddress &operator=(const QHostAddress &other);
#if QT_DEPRECATED_SINCE(5, 8)
QT_DEPRECATED_X("use = QHostAddress(string) instead")
@@ -114,7 +111,7 @@ public:
#endif
QHostAddress &operator=(SpecialAddress address);
- void swap(QHostAddress &other) Q_DECL_NOTHROW { d.swap(other.d); }
+ void swap(QHostAddress &other) noexcept { d.swap(other.d); }
void setAddress(quint32 ip4Addr);
void setAddress(quint8 *ip6Addr); // ### Qt 6: remove me
@@ -157,7 +154,7 @@ public:
static QPair<QHostAddress, int> parseSubnet(const QString &subnet);
- friend Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed) Q_DECL_NOTHROW;
+ friend Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed) noexcept;
protected:
friend class QHostAddressPrivate;
QExplicitlySharedDataPointer<QHostAddressPrivate> d;
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index 4d451dfdb7..9374728244 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -37,8 +37,11 @@
**
****************************************************************************/
+//#define QHOSTINFO_DEBUG
+
#include "qhostinfo.h"
#include "qhostinfo_p.h"
+#include <qplatformdefs.h>
#include "QtCore/qscopedpointer.h"
#include <qabstracteventdispatcher.h>
@@ -53,6 +56,15 @@
#ifdef Q_OS_UNIX
# include <unistd.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# if defined(AI_ADDRCONFIG)
+# define Q_ADDRCONFIG AI_ADDRCONFIG
+# endif
+#elif defined Q_OS_WIN
+# include <ws2tcpip.h>
+
+# define QT_SOCKLEN_T int
#endif
QT_BEGIN_NAMESPACE
@@ -64,8 +76,8 @@ Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager)
namespace {
struct ToBeLookedUpEquals {
typedef bool result_type;
- explicit ToBeLookedUpEquals(const QString &toBeLookedUp) Q_DECL_NOTHROW : m_toBeLookedUp(toBeLookedUp) {}
- result_type operator()(QHostInfoRunnable* lookup) const Q_DECL_NOTHROW
+ explicit ToBeLookedUpEquals(const QString &toBeLookedUp) noexcept : m_toBeLookedUp(toBeLookedUp) {}
+ result_type operator()(QHostInfoRunnable* lookup) const noexcept
{
return m_toBeLookedUp == lookup->toBeLookedUp;
}
@@ -305,25 +317,6 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
*/
/*!
- \fn template<typename PointerToMemberFunction> int QHostInfo::lookupHost(const QString &name, const QObject *receiver, PointerToMemberFunction function)
-
- \since 5.9
-
- \overload
-
- Looks up the IP address(es) associated with host name \a name, and
- returns an ID for the lookup. When the result of the lookup is
- ready, the slot or signal \a function in \a receiver is called with
- a QHostInfo argument. The QHostInfo object can then be inspected
- to get the results of the lookup.
-
- \note There is no guarantee on the order the signals will be emitted
- if you start multiple requests with lookupHost().
-
- \sa abortHostLookup(), addresses(), error(), fromName()
-*/
-
-/*!
\fn template<typename Functor> int QHostInfo::lookupHost(const QString &name, Functor functor)
\since 5.9
@@ -359,6 +352,16 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
thread of \a context. The context's thread must have a running Qt
event loop.
+ Here is an alternative signature for the function:
+ \code
+ lookupHost(const QString &name, const QObject *receiver, PointerToMemberFunction function)
+ \endcode
+
+ In this case, when the result of the lookup is ready, the slot or
+ signal \c{function} in \c{receiver} is called with a QHostInfo
+ argument. The QHostInfo object can then be inspected to get the
+ results of the lookup.
+
\note There is no guarantee on the order the signals will be emitted
if you start multiple requests with lookupHost().
@@ -421,6 +424,162 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer<QNetw
}
#endif
+QHostInfo QHostInfoAgent::reverseLookup(const QHostAddress &address)
+{
+ QHostInfo results;
+ // Reverse lookup
+ sockaddr_in sa4;
+ sockaddr_in6 sa6;
+ sockaddr *sa = 0;
+ QT_SOCKLEN_T saSize;
+ if (address.protocol() == QAbstractSocket::IPv4Protocol) {
+ sa = reinterpret_cast<sockaddr *>(&sa4);
+ saSize = sizeof(sa4);
+ memset(&sa4, 0, sizeof(sa4));
+ sa4.sin_family = AF_INET;
+ sa4.sin_addr.s_addr = htonl(address.toIPv4Address());
+ } else {
+ sa = reinterpret_cast<sockaddr *>(&sa6);
+ saSize = sizeof(sa6);
+ memset(&sa6, 0, sizeof(sa6));
+ sa6.sin6_family = AF_INET6;
+ memcpy(&sa6.sin6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr));
+ }
+
+ char hbuf[NI_MAXHOST];
+ if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), nullptr, 0, 0) == 0)
+ results.setHostName(QString::fromLatin1(hbuf));
+
+ if (results.hostName().isEmpty())
+ results.setHostName(address.toString());
+ results.setAddresses(QList<QHostAddress>() << address);
+
+ return results;
+}
+
+/*
+ Call getaddrinfo, and returns the results as QHostInfo::addresses
+*/
+QHostInfo QHostInfoAgent::lookup(const QString &hostName)
+{
+ QHostInfo results;
+
+ // IDN support
+ QByteArray aceHostname = QUrl::toAce(hostName);
+ results.setHostName(hostName);
+ if (aceHostname.isEmpty()) {
+ results.setError(QHostInfo::HostNotFound);
+ results.setErrorString(hostName.isEmpty() ?
+ QCoreApplication::translate("QHostInfoAgent", "No host name given") :
+ QCoreApplication::translate("QHostInfoAgent", "Invalid hostname"));
+ return results;
+ }
+
+ addrinfo *res = 0;
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+#ifdef Q_ADDRCONFIG
+ hints.ai_flags = Q_ADDRCONFIG;
+#endif
+
+ int result = getaddrinfo(aceHostname.constData(), nullptr, &hints, &res);
+# ifdef Q_ADDRCONFIG
+ if (result == EAI_BADFLAGS) {
+ // if the lookup failed with AI_ADDRCONFIG set, try again without it
+ hints.ai_flags = 0;
+ result = getaddrinfo(aceHostname.constData(), nullptr, &hints, &res);
+ }
+# endif
+
+ if (result == 0) {
+ addrinfo *node = res;
+ QList<QHostAddress> addresses;
+ while (node) {
+#ifdef QHOSTINFO_DEBUG
+ qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family
+ << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol
+ << "ai_addrlen:" << node->ai_addrlen;
+#endif
+ switch (node->ai_family) {
+ case AF_INET: {
+ QHostAddress addr;
+ addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr));
+ if (!addresses.contains(addr))
+ addresses.append(addr);
+ break;
+ }
+ case AF_INET6: {
+ QHostAddress addr;
+ sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr;
+ addr.setAddress(sa6->sin6_addr.s6_addr);
+ if (sa6->sin6_scope_id)
+ addr.setScopeId(QString::number(sa6->sin6_scope_id));
+ if (!addresses.contains(addr))
+ addresses.append(addr);
+ break;
+ }
+ default:
+ results.setError(QHostInfo::UnknownError);
+ results.setErrorString(QCoreApplication::translate("QHostInfoAgent", "Unknown address type"));
+ }
+ node = node->ai_next;
+ }
+ if (addresses.isEmpty()) {
+ // Reached the end of the list, but no addresses were found; this
+ // means the list contains one or more unknown address types.
+ results.setError(QHostInfo::UnknownError);
+ results.setErrorString(QCoreApplication::translate("QHostInfoAgent", "Unknown address type"));
+ }
+
+ results.setAddresses(addresses);
+ freeaddrinfo(res);
+ } else {
+ switch (result) {
+#ifdef Q_OS_WIN
+ case WSAHOST_NOT_FOUND: //authoritative not found
+ case WSATRY_AGAIN: //non authoritative not found
+ case WSANO_DATA: //valid name, no associated address
+#else
+ case EAI_NONAME:
+ case EAI_FAIL:
+# ifdef EAI_NODATA // EAI_NODATA is deprecated in RFC 3493
+ case EAI_NODATA:
+# endif
+#endif
+ results.setError(QHostInfo::HostNotFound);
+ results.setErrorString(QCoreApplication::translate("QHostInfoAgent", "Host not found"));
+ break;
+ default:
+ results.setError(QHostInfo::UnknownError);
+#ifdef Q_OS_WIN
+ results.setErrorString(QString::fromWCharArray(gai_strerror(result)));
+#else
+ results.setErrorString(QString::fromLocal8Bit(gai_strerror(result)));
+#endif
+ break;
+ }
+ }
+
+#if defined(QHOSTINFO_DEBUG)
+ if (results.error() != QHostInfo::NoError) {
+ qDebug("QHostInfoAgent::fromName(): error #%d %s",
+ h_errno, results.errorString().toLatin1().constData());
+ } else {
+ QString tmp;
+ QList<QHostAddress> addresses = results.addresses();
+ for (int i = 0; i < addresses.count(); ++i) {
+ if (i != 0) tmp += QLatin1String(", ");
+ tmp += addresses.at(i).toString();
+ }
+ qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}",
+ addresses.count(), aceHostname.constData(),
+ tmp.toLatin1().constData());
+ }
+#endif
+
+ return results;
+}
/*!
\enum QHostInfo::HostInfoError
diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h
index 75917a02a3..dc31cc08e4 100644
--- a/src/network/kernel/qhostinfo.h
+++ b/src/network/kernel/qhostinfo.h
@@ -63,10 +63,10 @@ public:
explicit QHostInfo(int lookupId = -1);
QHostInfo(const QHostInfo &d);
QHostInfo &operator=(const QHostInfo &d);
- QHostInfo &operator=(QHostInfo &&other) Q_DECL_NOTHROW { swap(other); return *this; }
+ QHostInfo &operator=(QHostInfo &&other) noexcept { swap(other); return *this; }
~QHostInfo();
- void swap(QHostInfo &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QHostInfo &other) noexcept { qSwap(d, other.d); }
QString hostName() const;
void setHostName(const QString &name);
@@ -91,13 +91,10 @@ public:
static QString localDomainName();
#ifdef Q_CLANG_QDOC
- template<typename PointerToMemberFunction>
- static int QHostInfo::lookupHost(const QString &name, const QObject *receiver,
- PointerToMemberFunction function);
template<typename Functor>
- static int QHostInfo::lookupHost(const QString &name, Functor functor);
+ static int lookupHost(const QString &name, Functor functor);
template<typename Functor>
- static int QHostInfo::lookupHost(const QString &name, const QObject *context, Functor functor);
+ static int lookupHost(const QString &name, const QObject *context, Functor functor);
#else
// lookupHost to a QObject slot
template <typename Func>
diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h
index 8cce302166..3c0ee2a0d8 100644
--- a/src/network/kernel/qhostinfo_p.h
+++ b/src/network/kernel/qhostinfo_p.h
@@ -101,7 +101,7 @@ public Q_SLOTS:
{
if (slotObj) {
QHostInfo copy = info;
- void *args[2] = { 0, reinterpret_cast<void *>(&copy) };
+ void *args[2] = { nullptr, reinterpret_cast<void *>(&copy) };
slotObj->call(const_cast<QObject*>(receiver.data()), args);
slotObj->destroyIfLastRef();
} else {
@@ -127,15 +127,16 @@ Q_SIGNALS:
void resultsReady(const QHostInfo &info);
};
-// needs to be QObject because fromName calls tr()
-class QHostInfoAgent : public QObject
+class QHostInfoAgent
{
- Q_OBJECT
public:
static QHostInfo fromName(const QString &hostName);
#ifndef QT_NO_BEARERMANAGEMENT
static QHostInfo fromName(const QString &hostName, QSharedPointer<QNetworkSession> networkSession);
#endif
+private:
+ static QHostInfo lookup(const QString &hostName);
+ static QHostInfo reverseLookup(const QHostAddress &address);
};
class QHostInfoPrivate
diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp
index e4810d68ee..78a05f8407 100644
--- a/src/network/kernel/qhostinfo_unix.cpp
+++ b/src/network/kernel/qhostinfo_unix.cpp
@@ -72,17 +72,6 @@
QT_BEGIN_NAMESPACE
-// Almost always the same. If not, specify in qplatformdefs.h.
-#if !defined(QT_SOCKOPTLEN_T)
-# define QT_SOCKOPTLEN_T QT_SOCKLEN_T
-#endif
-
-// HP-UXi has a bug in getaddrinfo(3) that makes it thread-unsafe
-// with this flag. So disable it in that platform.
-#if defined(AI_ADDRCONFIG) && !defined(Q_OS_HPUX)
-# define Q_ADDRCONFIG AI_ADDRCONFIG
-#endif
-
enum LibResolvFeature {
NeedResInit,
NeedResNInit
@@ -197,132 +186,10 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
local_res_init();
QHostAddress address;
- if (address.setAddress(hostName)) {
- // Reverse lookup
- sockaddr_in sa4;
- sockaddr_in6 sa6;
- sockaddr *sa = 0;
- QT_SOCKLEN_T saSize = 0;
- if (address.protocol() == QAbstractSocket::IPv4Protocol) {
- sa = (sockaddr *)&sa4;
- saSize = sizeof(sa4);
- memset(&sa4, 0, sizeof(sa4));
- sa4.sin_family = AF_INET;
- sa4.sin_addr.s_addr = htonl(address.toIPv4Address());
- }
- else {
- sa = (sockaddr *)&sa6;
- saSize = sizeof(sa6);
- memset(&sa6, 0, sizeof(sa6));
- sa6.sin6_family = AF_INET6;
- memcpy(sa6.sin6_addr.s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.s6_addr));
- }
-
- char hbuf[NI_MAXHOST];
- if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0)
- results.setHostName(QString::fromLatin1(hbuf));
-
- if (results.hostName().isEmpty())
- results.setHostName(address.toString());
- results.setAddresses(QList<QHostAddress>() << address);
- return results;
- }
-
- // IDN support
- QByteArray aceHostname = QUrl::toAce(hostName);
- results.setHostName(hostName);
- if (aceHostname.isEmpty()) {
- results.setError(QHostInfo::HostNotFound);
- results.setErrorString(hostName.isEmpty() ?
- QCoreApplication::translate("QHostInfoAgent", "No host name given") :
- QCoreApplication::translate("QHostInfoAgent", "Invalid hostname"));
- return results;
- }
-
- // Call getaddrinfo, and place all IPv4 addresses at the start and
- // the IPv6 addresses at the end of the address list in results.
- addrinfo *res = 0;
- struct addrinfo hints;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
-#ifdef Q_ADDRCONFIG
- hints.ai_flags = Q_ADDRCONFIG;
-#endif
+ if (address.setAddress(hostName))
+ return reverseLookup(address);
- int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res);
-# ifdef Q_ADDRCONFIG
- if (result == EAI_BADFLAGS) {
- // if the lookup failed with AI_ADDRCONFIG set, try again without it
- hints.ai_flags = 0;
- result = getaddrinfo(aceHostname.constData(), 0, &hints, &res);
- }
-# endif
-
- if (result == 0) {
- addrinfo *node = res;
- QList<QHostAddress> addresses;
- while (node) {
-#ifdef QHOSTINFO_DEBUG
- qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol << "ai_addrlen:" << node->ai_addrlen;
-#endif
- if (node->ai_family == AF_INET) {
- QHostAddress addr;
- addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr));
- if (!addresses.contains(addr))
- addresses.append(addr);
- }
- else if (node->ai_family == AF_INET6) {
- QHostAddress addr;
- sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr;
- addr.setAddress(sa6->sin6_addr.s6_addr);
- if (sa6->sin6_scope_id)
- addr.setScopeId(QString::number(sa6->sin6_scope_id));
- if (!addresses.contains(addr))
- addresses.append(addr);
- }
- node = node->ai_next;
- }
- if (addresses.isEmpty() && node == 0) {
- // Reached the end of the list, but no addresses were found; this
- // means the list contains one or more unknown address types.
- results.setError(QHostInfo::UnknownError);
- results.setErrorString(tr("Unknown address type"));
- }
-
- results.setAddresses(addresses);
- freeaddrinfo(res);
- } else if (result == EAI_NONAME
- || result == EAI_FAIL
-#ifdef EAI_NODATA
- // EAI_NODATA is deprecated in RFC 3493
- || result == EAI_NODATA
-#endif
- ) {
- results.setError(QHostInfo::HostNotFound);
- results.setErrorString(tr("Host not found"));
- } else {
- results.setError(QHostInfo::UnknownError);
- results.setErrorString(QString::fromLocal8Bit(gai_strerror(result)));
- }
-
-
-#if defined(QHOSTINFO_DEBUG)
- if (results.error() != QHostInfo::NoError) {
- qDebug("QHostInfoAgent::fromName(): error #%d %s",
- h_errno, results.errorString().toLatin1().constData());
- } else {
- QString tmp;
- QList<QHostAddress> addresses = results.addresses();
- for (int i = 0; i < addresses.count(); ++i) {
- if (i != 0) tmp += ", ";
- tmp += addresses.at(i).toString();
- }
- qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}",
- addresses.count(), hostName.toLatin1().constData(),
- tmp.toLatin1().constData());
- }
-#endif
- return results;
+ return lookup(hostName);
}
QString QHostInfo::localDomainName()
diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp
index c51e9968f8..0b5cc98970 100644
--- a/src/network/kernel/qhostinfo_win.cpp
+++ b/src/network/kernel/qhostinfo_win.cpp
@@ -51,27 +51,10 @@ QT_BEGIN_NAMESPACE
//#define QHOSTINFO_DEBUG
//###
-#define QT_SOCKLEN_T int
#ifndef NI_MAXHOST // already defined to 1025 in ws2tcpip.h?
#define NI_MAXHOST 1024
#endif
-static void translateWSAError(int error, QHostInfo *results)
-{
- switch (error) {
- case WSAHOST_NOT_FOUND: //authoritative not found
- case WSATRY_AGAIN: //non authoritative not found
- case WSANO_DATA: //valid name, no associated address
- results->setError(QHostInfo::HostNotFound);
- results->setErrorString(QHostInfoAgent::tr("Host not found"));
- return;
- default:
- results->setError(QHostInfo::UnknownError);
- results->setErrorString(QHostInfoAgent::tr("Unknown error (%1)").arg(error));
- return;
- }
-}
-
QHostInfo QHostInfoAgent::fromName(const QString &hostName)
{
QSysInfo::machineHostName(); // this initializes ws2_32.dll
@@ -79,98 +62,15 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
QHostInfo results;
#if defined(QHOSTINFO_DEBUG)
- qDebug("QHostInfoAgent::fromName(): looking up \"%s\" (IPv6 support is %s)",
- hostName.toLatin1().constData(),
- (getaddrinfo && freeaddrinfo) ? "enabled" : "disabled");
+ qDebug("QHostInfoAgent::fromName(%s) looking up...",
+ hostName.toLatin1().constData());
#endif
QHostAddress address;
- if (address.setAddress(hostName)) {
- // Reverse lookup
- sockaddr_in sa4;
- sockaddr_in6 sa6;
- sockaddr *sa;
- QT_SOCKLEN_T saSize;
- if (address.protocol() == QAbstractSocket::IPv4Protocol) {
- sa = reinterpret_cast<sockaddr *>(&sa4);
- saSize = sizeof(sa4);
- memset(&sa4, 0, sizeof(sa4));
- sa4.sin_family = AF_INET;
- sa4.sin_addr.s_addr = htonl(address.toIPv4Address());
- } else {
- sa = reinterpret_cast<sockaddr *>(&sa6);
- saSize = sizeof(sa6);
- memset(&sa6, 0, sizeof(sa6));
- sa6.sin6_family = AF_INET6;
- memcpy(&sa6.sin6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr));
- }
-
- char hbuf[NI_MAXHOST];
- if (getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0)
- results.setHostName(QString::fromLatin1(hbuf));
-
- if (results.hostName().isEmpty())
- results.setHostName(address.toString());
- results.setAddresses(QList<QHostAddress>() << address);
- return results;
- }
+ if (address.setAddress(hostName))
+ return reverseLookup(address);
- // IDN support
- QByteArray aceHostname = QUrl::toAce(hostName);
- results.setHostName(hostName);
- if (aceHostname.isEmpty()) {
- results.setError(QHostInfo::HostNotFound);
- results.setErrorString(hostName.isEmpty() ? tr("No host name given") : tr("Invalid hostname"));
- return results;
- }
-
- addrinfo *res;
- int err = getaddrinfo(aceHostname.constData(), 0, 0, &res);
- if (err == 0) {
- QList<QHostAddress> addresses;
- for (addrinfo *p = res; p != 0; p = p->ai_next) {
- switch (p->ai_family) {
- case AF_INET: {
- QHostAddress addr;
- addr.setAddress(ntohl(reinterpret_cast<sockaddr_in *>(p->ai_addr)->sin_addr.s_addr));
- if (!addresses.contains(addr))
- addresses.append(addr);
- }
- break;
- case AF_INET6: {
- QHostAddress addr;
- addr.setAddress(reinterpret_cast<const sockaddr_in6 *>(p->ai_addr)->sin6_addr.s6_addr);
- if (!addresses.contains(addr))
- addresses.append(addr);
- }
- break;
- default:
- results.setError(QHostInfo::UnknownError);
- results.setErrorString(tr("Unknown address type"));
- }
- }
- results.setAddresses(addresses);
- freeaddrinfo(res);
- } else {
- translateWSAError(WSAGetLastError(), &results);
- }
-
-#if defined(QHOSTINFO_DEBUG)
- if (results.error() != QHostInfo::NoError) {
- qDebug("QHostInfoAgent::run(): error (%s)",
- results.errorString().toLatin1().constData());
- } else {
- QString tmp;
- QList<QHostAddress> addresses = results.addresses();
- for (int i = 0; i < addresses.count(); ++i) {
- if (i != 0) tmp += ", ";
- tmp += addresses.at(i).toString();
- }
- qDebug("QHostInfoAgent::run(): found %i entries: {%s}",
- addresses.count(), tmp.toLatin1().constData());
- }
-#endif
- return results;
+ return lookup(hostName);
}
// QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp
diff --git a/src/network/kernel/qnetconmonitor_darwin.mm b/src/network/kernel/qnetconmonitor_darwin.mm
new file mode 100644
index 0000000000..a64cd6e530
--- /dev/null
+++ b/src/network/kernel/qnetconmonitor_darwin.mm
@@ -0,0 +1,419 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qnativesocketengine_p.h"
+#include "private/qnetconmonitor_p.h"
+
+#include "private/qobject_p.h"
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <netinet/in.h>
+
+#include <cstring>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcNetMon, "qt.network.monitor");
+
+namespace {
+
+class ReachabilityDispatchQueue
+{
+public:
+ ReachabilityDispatchQueue()
+ {
+ queue = dispatch_queue_create("qt-network-reachability-queue", nullptr);
+ if (!queue)
+ qCWarning(lcNetMon, "Failed to create a dispatch queue for reachability probes");
+ }
+
+ ~ReachabilityDispatchQueue()
+ {
+ if (queue)
+ dispatch_release(queue);
+ }
+
+ dispatch_queue_t data() const
+ {
+ return queue;
+ }
+
+private:
+ dispatch_queue_t queue = nullptr;
+
+ Q_DISABLE_COPY_MOVE(ReachabilityDispatchQueue)
+};
+
+dispatch_queue_t qt_reachability_queue()
+{
+ static const ReachabilityDispatchQueue reachabilityQueue;
+ return reachabilityQueue.data();
+}
+
+qt_sockaddr qt_hostaddress_to_sockaddr(const QHostAddress &src)
+{
+ if (src.isNull())
+ return {};
+
+ qt_sockaddr dst;
+ if (src.protocol() == QAbstractSocket::IPv4Protocol) {
+ dst.a4 = sockaddr_in{};
+ dst.a4.sin_family = AF_INET;
+ dst.a4.sin_addr.s_addr = htonl(src.toIPv4Address());
+ dst.a4.sin_len = sizeof(sockaddr_in);
+ } else if (src.protocol() == QAbstractSocket::IPv6Protocol) {
+ dst.a6 = sockaddr_in6{};
+ dst.a6.sin6_family = AF_INET6;
+ dst.a6.sin6_len = sizeof(sockaddr_in6);
+ const Q_IPV6ADDR ipv6 = src.toIPv6Address();
+ std::memcpy(&dst.a6.sin6_addr, &ipv6, sizeof ipv6);
+ } else {
+ Q_UNREACHABLE();
+ }
+
+ return dst;
+}
+
+} // unnamed namespace
+
+class QNetworkConnectionMonitorPrivate : public QObjectPrivate
+{
+public:
+ SCNetworkReachabilityRef probe = nullptr;
+ SCNetworkReachabilityFlags state = kSCNetworkReachabilityFlagsIsLocalAddress;
+ bool scheduled = false;
+
+ void updateState(SCNetworkReachabilityFlags newState);
+ void reset();
+ bool isReachable() const;
+
+ static void probeCallback(SCNetworkReachabilityRef probe, SCNetworkReachabilityFlags flags, void *info);
+
+ Q_DECLARE_PUBLIC(QNetworkConnectionMonitor)
+};
+
+void QNetworkConnectionMonitorPrivate::updateState(SCNetworkReachabilityFlags newState)
+{
+ // To be executed only on the reachability queue.
+ Q_Q(QNetworkConnectionMonitor);
+
+ // NETMONTODO: for now, 'online' for us means kSCNetworkReachabilityFlagsReachable
+ // is set. There are more possible flags that require more tests/some special
+ // setup. So in future this part and related can change/be extended.
+ const bool wasReachable = isReachable();
+ state = newState;
+ if (wasReachable != isReachable())
+ emit q->reachabilityChanged(isReachable());
+}
+
+void QNetworkConnectionMonitorPrivate::reset()
+{
+ if (probe) {
+ CFRelease(probe);
+ probe = nullptr;
+ }
+
+ state = kSCNetworkReachabilityFlagsIsLocalAddress;
+ scheduled = false;
+}
+
+bool QNetworkConnectionMonitorPrivate::isReachable() const
+{
+ return !!(state & kSCNetworkReachabilityFlagsReachable);
+}
+
+void QNetworkConnectionMonitorPrivate::probeCallback(SCNetworkReachabilityRef probe, SCNetworkReachabilityFlags flags, void *info)
+{
+ // To be executed only on the reachability queue.
+ Q_UNUSED(probe);
+
+ auto monitorPrivate = static_cast<QNetworkConnectionMonitorPrivate *>(info);
+ Q_ASSERT(monitorPrivate);
+ monitorPrivate->updateState(flags);
+}
+
+QNetworkConnectionMonitor::QNetworkConnectionMonitor()
+ : QObject(*new QNetworkConnectionMonitorPrivate)
+{
+}
+
+QNetworkConnectionMonitor::QNetworkConnectionMonitor(const QHostAddress &local, const QHostAddress &remote)
+ : QObject(*new QNetworkConnectionMonitorPrivate)
+{
+ setTargets(local, remote);
+}
+
+QNetworkConnectionMonitor::~QNetworkConnectionMonitor()
+{
+ Q_D(QNetworkConnectionMonitor);
+
+ stopMonitoring();
+ d->reset();
+}
+
+bool QNetworkConnectionMonitor::setTargets(const QHostAddress &local, const QHostAddress &remote)
+{
+ Q_D(QNetworkConnectionMonitor);
+
+ if (isMonitoring()) {
+ qCWarning(lcNetMon, "Monitor is already active, call stopMonitoring() first");
+ return false;
+ }
+
+ if (local.isNull()) {
+ qCWarning(lcNetMon, "Invalid (null) local address, cannot create a reachability target");
+ return false;
+ }
+
+ // Clear the old target if needed:
+ d->reset();
+
+ qt_sockaddr client = qt_hostaddress_to_sockaddr(local);
+ if (remote.isNull()) {
+ // That's a special case our QNetworkStatusMonitor is using (AnyIpv4/6 address to check an overall status).
+ d->probe = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, reinterpret_cast<sockaddr *>(&client));
+ } else {
+ qt_sockaddr target = qt_hostaddress_to_sockaddr(remote);
+ d->probe = SCNetworkReachabilityCreateWithAddressPair(kCFAllocatorDefault,
+ reinterpret_cast<sockaddr *>(&client),
+ reinterpret_cast<sockaddr *>(&target));
+ }
+
+ if (d->probe) {
+ // Let's read the initial state so that callback coming later can
+ // see a difference. Ignore errors though.
+ SCNetworkReachabilityGetFlags(d->probe, &d->state);
+ }else {
+ qCWarning(lcNetMon, "Failed to create network reachability probe");
+ return false;
+ }
+
+ return true;
+}
+
+bool QNetworkConnectionMonitor::startMonitoring()
+{
+ Q_D(QNetworkConnectionMonitor);
+
+ if (isMonitoring()) {
+ qCWarning(lcNetMon, "Monitor is already active, call stopMonitoring() first");
+ return false;
+ }
+
+ if (!d->probe) {
+ qCWarning(lcNetMon, "Can not start monitoring, set targets first");
+ return false;
+ }
+
+ auto queue = qt_reachability_queue();
+ if (!queue) {
+ qWarning(lcNetMon, "Failed to create a dispatch queue to schedule a probe on");
+ return false;
+ }
+
+ SCNetworkReachabilityContext context = {};
+ context.info = d;
+ if (!SCNetworkReachabilitySetCallback(d->probe, QNetworkConnectionMonitorPrivate::probeCallback, &context)) {
+ qWarning(lcNetMon, "Failed to set a reachability callback");
+ return false;
+ }
+
+
+ if (!SCNetworkReachabilitySetDispatchQueue(d->probe, queue)) {
+ qWarning(lcNetMon, "Failed to schedule a reachability callback on a queue");
+ return false;
+ }
+
+ return d->scheduled = true;
+}
+
+bool QNetworkConnectionMonitor::isMonitoring() const
+{
+ Q_D(const QNetworkConnectionMonitor);
+
+ return d->scheduled;
+}
+
+void QNetworkConnectionMonitor::stopMonitoring()
+{
+ Q_D(QNetworkConnectionMonitor);
+
+ if (d->scheduled) {
+ Q_ASSERT(d->probe);
+ SCNetworkReachabilitySetDispatchQueue(d->probe, nullptr);
+ SCNetworkReachabilitySetCallback(d->probe, nullptr, nullptr);
+ d->scheduled = false;
+ }
+}
+
+bool QNetworkConnectionMonitor::isReachable()
+{
+ Q_D(QNetworkConnectionMonitor);
+
+ if (isMonitoring()) {
+ qCWarning(lcNetMon, "Calling isReachable() is unsafe after the monitoring started");
+ return false;
+ }
+
+ if (!d->probe) {
+ qCWarning(lcNetMon, "Reachability is unknown, set the target first");
+ return false;
+ }
+
+ return d->isReachable();
+}
+
+class QNetworkStatusMonitorPrivate : public QObjectPrivate
+{
+public:
+ QNetworkConnectionMonitor ipv4Probe;
+ bool isOnlineIpv4 = false;
+ QNetworkConnectionMonitor ipv6Probe;
+ bool isOnlineIpv6 = false;
+};
+
+QNetworkStatusMonitor::QNetworkStatusMonitor()
+ : QObject(*new QNetworkStatusMonitorPrivate)
+{
+ Q_D(QNetworkStatusMonitor);
+
+ if (d->ipv4Probe.setTargets(QHostAddress::AnyIPv4, {})) {
+ // We manage to create SCNetworkReachabilityRef for IPv4, let's
+ // read the last known state then!
+ d->isOnlineIpv4 = d->ipv4Probe.isReachable();
+ }
+
+ if (d->ipv6Probe.setTargets(QHostAddress::AnyIPv6, {})) {
+ // We manage to create SCNetworkReachability ref for IPv6, let's
+ // read the last known state then!
+ d->isOnlineIpv6 = d->ipv6Probe.isReachable();
+ }
+
+
+ connect(&d->ipv4Probe, &QNetworkConnectionMonitor::reachabilityChanged, this,
+ &QNetworkStatusMonitor::reachabilityChanged, Qt::QueuedConnection);
+ connect(&d->ipv6Probe, &QNetworkConnectionMonitor::reachabilityChanged, this,
+ &QNetworkStatusMonitor::reachabilityChanged, Qt::QueuedConnection);
+}
+
+QNetworkStatusMonitor::~QNetworkStatusMonitor()
+{
+ Q_D(QNetworkStatusMonitor);
+
+ d->ipv4Probe.disconnect();
+ d->ipv4Probe.stopMonitoring();
+ d->ipv6Probe.disconnect();
+ d->ipv6Probe.stopMonitoring();
+}
+
+bool QNetworkStatusMonitor::start()
+{
+ Q_D(QNetworkStatusMonitor);
+
+ if (isMonitoring()) {
+ qCWarning(lcNetMon, "Network status monitor is already active");
+ return true;
+ }
+
+ d->ipv4Probe.startMonitoring();
+ d->ipv6Probe.startMonitoring();
+
+ return isMonitoring();
+}
+
+void QNetworkStatusMonitor::stop()
+{
+ Q_D(QNetworkStatusMonitor);
+
+ if (d->ipv4Probe.isMonitoring())
+ d->ipv4Probe.stopMonitoring();
+ if (d->ipv6Probe.isMonitoring())
+ d->ipv6Probe.stopMonitoring();
+}
+
+bool QNetworkStatusMonitor::isMonitoring() const
+{
+ Q_D(const QNetworkStatusMonitor);
+
+ return d->ipv4Probe.isMonitoring() || d->ipv6Probe.isMonitoring();
+}
+
+bool QNetworkStatusMonitor::isNetworkAccesible()
+{
+ // This function is to be executed on the thread that created
+ // and uses 'this'.
+ Q_D(QNetworkStatusMonitor);
+
+ return d->isOnlineIpv4 || d->isOnlineIpv6;
+}
+
+bool QNetworkStatusMonitor::isEnabled()
+{
+ return true;
+}
+
+void QNetworkStatusMonitor::reachabilityChanged(bool online)
+{
+ // This function is executed on the thread that created/uses 'this',
+ // not on the reachability queue.
+ Q_D(QNetworkStatusMonitor);
+
+ auto probe = qobject_cast<QNetworkConnectionMonitor *>(sender());
+ if (!probe)
+ return;
+
+ const bool isIpv4 = probe == &d->ipv4Probe;
+ bool &probeOnline = isIpv4 ? d->isOnlineIpv4 : d->isOnlineIpv6;
+ bool otherOnline = isIpv4 ? d->isOnlineIpv6 : d->isOnlineIpv4;
+
+ if (probeOnline == online) {
+ // We knew this already?
+ return;
+ }
+
+ probeOnline = online;
+ if (!otherOnline) {
+ // We either just lost or got a network access.
+ emit onlineStateChanged(probeOnline);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/kernel/qnetconmonitor_p.h b/src/network/kernel/qnetconmonitor_p.h
new file mode 100644
index 0000000000..74ee56d422
--- /dev/null
+++ b/src/network/kernel/qnetconmonitor_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETCONMONITOR_P_H
+#define QNETCONMONITOR_P_H
+
+#include <private/qtnetworkglobal_p.h>
+
+#include <QtCore/qloggingcategory.h>
+#include <QtNetwork/qhostaddress.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qobject.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConnectionMonitorPrivate;
+class QNetworkConnectionMonitor : public QObject
+{
+ Q_OBJECT
+
+public:
+ QNetworkConnectionMonitor();
+ QNetworkConnectionMonitor(const QHostAddress &local, const QHostAddress &remote = {});
+ ~QNetworkConnectionMonitor();
+
+ bool setTargets(const QHostAddress &local, const QHostAddress &remote);
+ bool isReachable();
+
+ // Important: on Darwin you should not call isReachable() after
+ // startMonitoring(), you have to listen to reachabilityChanged()
+ // signal instead.
+ bool startMonitoring();
+ bool isMonitoring() const;
+ void stopMonitoring();
+
+Q_SIGNALS:
+ // Important: connect to this using QueuedConnection. On Darwin
+ // callback is coming on a special dispatch queue.
+ void reachabilityChanged(bool isOnline);
+
+private:
+ Q_DECLARE_PRIVATE(QNetworkConnectionMonitor)
+ Q_DISABLE_COPY_MOVE(QNetworkConnectionMonitor)
+};
+
+class QNetworkStatusMonitorPrivate;
+class QNetworkStatusMonitor : public QObject
+{
+ Q_OBJECT
+
+public:
+ QNetworkStatusMonitor();
+ ~QNetworkStatusMonitor();
+
+ bool isNetworkAccesible();
+
+ bool start();
+ void stop();
+ bool isMonitoring() const;
+
+ static bool isEnabled();
+
+Q_SIGNALS:
+ // Unlike QNetworkConnectionMonitor, this can be connected to directly.
+ void onlineStateChanged(bool isOnline);
+
+private slots:
+ void reachabilityChanged(bool isOnline);
+
+private:
+ Q_DECLARE_PRIVATE(QNetworkStatusMonitor)
+ Q_DISABLE_COPY_MOVE(QNetworkStatusMonitor)
+};
+
+Q_DECLARE_LOGGING_CATEGORY(lcNetMon)
+
+QT_END_NAMESPACE
+
+#endif // QNETCONMONITOR_P_H
diff --git a/src/network/kernel/qnetconmonitor_stub.cpp b/src/network/kernel/qnetconmonitor_stub.cpp
new file mode 100644
index 0000000000..7f3a0c44c6
--- /dev/null
+++ b/src/network/kernel/qnetconmonitor_stub.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetconmonitor_p.h"
+
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcNetMon, "qt.network.monitor");
+
+// Note: this 'stub' version is never enabled (see QNetworkStatusMonitor::isEnabled below)
+// and thus should never affect QNAM in any unusuall way. Having this 'stub' version is similar
+// to building Qt with bearer management configured out.
+
+class QNetworkConnectionMonitorPrivate : public QObjectPrivate
+{
+};
+
+QNetworkConnectionMonitor::QNetworkConnectionMonitor()
+ : QObject(*new QNetworkConnectionMonitorPrivate)
+{
+}
+
+QNetworkConnectionMonitor::QNetworkConnectionMonitor(const QHostAddress &local, const QHostAddress &remote)
+ : QObject(*new QNetworkConnectionMonitorPrivate)
+{
+ Q_UNUSED(local)
+ Q_UNUSED(remote)
+}
+
+QNetworkConnectionMonitor::~QNetworkConnectionMonitor()
+{
+}
+
+bool QNetworkConnectionMonitor::setTargets(const QHostAddress &local, const QHostAddress &remote)
+{
+ Q_UNUSED(local)
+ Q_UNUSED(remote)
+
+ return false;
+}
+
+bool QNetworkConnectionMonitor::startMonitoring()
+{
+ return false;
+}
+
+bool QNetworkConnectionMonitor::isMonitoring() const
+{
+ return false;
+}
+
+void QNetworkConnectionMonitor::stopMonitoring()
+{
+}
+
+bool QNetworkConnectionMonitor::isReachable()
+{
+ return false;
+}
+
+class QNetworkStatusMonitorPrivate : public QObjectPrivate
+{
+};
+
+QNetworkStatusMonitor::QNetworkStatusMonitor()
+ : QObject(*new QNetworkStatusMonitorPrivate)
+{
+}
+
+QNetworkStatusMonitor::~QNetworkStatusMonitor()
+{
+}
+
+bool QNetworkStatusMonitor::start()
+{
+ return false;
+}
+
+void QNetworkStatusMonitor::stop()
+{
+}
+
+bool QNetworkStatusMonitor::isMonitoring() const
+{
+ return false;
+}
+
+bool QNetworkStatusMonitor::isNetworkAccesible()
+{
+ return false;
+}
+
+bool QNetworkStatusMonitor::isEnabled()
+{
+ return false;
+}
+
+void QNetworkStatusMonitor::reachabilityChanged(bool online)
+{
+ Q_UNUSED(online)
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/kernel/qnetworkdatagram.h b/src/network/kernel/qnetworkdatagram.h
index 1acb44a1e0..70958fea42 100644
--- a/src/network/kernel/qnetworkdatagram.h
+++ b/src/network/kernel/qnetworkdatagram.h
@@ -61,13 +61,13 @@ public:
~QNetworkDatagram()
{ if (d) destroy(d); }
- QNetworkDatagram(QNetworkDatagram &&other) Q_DECL_NOTHROW
+ QNetworkDatagram(QNetworkDatagram &&other) noexcept
: d(other.d)
{ other.d = nullptr; }
- QNetworkDatagram &operator=(QNetworkDatagram &&other) Q_DECL_NOTHROW
+ QNetworkDatagram &operator=(QNetworkDatagram &&other) noexcept
{ swap(other); return *this; }
- void swap(QNetworkDatagram &other) Q_DECL_NOTHROW
+ void swap(QNetworkDatagram &other) noexcept
{ qSwap(d, other.d); }
void clear();
diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h
index 148fd5e10d..4caedaa38f 100644
--- a/src/network/kernel/qnetworkinterface.h
+++ b/src/network/kernel/qnetworkinterface.h
@@ -64,13 +64,11 @@ public:
QNetworkAddressEntry();
QNetworkAddressEntry(const QNetworkAddressEntry &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QNetworkAddressEntry &operator=(QNetworkAddressEntry &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QNetworkAddressEntry &operator=(QNetworkAddressEntry &&other) noexcept { swap(other); return *this; }
QNetworkAddressEntry &operator=(const QNetworkAddressEntry &other);
~QNetworkAddressEntry();
- void swap(QNetworkAddressEntry &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QNetworkAddressEntry &other) noexcept { qSwap(d, other.d); }
bool operator==(const QNetworkAddressEntry &other) const;
inline bool operator!=(const QNetworkAddressEntry &other) const
@@ -142,13 +140,11 @@ public:
QNetworkInterface();
QNetworkInterface(const QNetworkInterface &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QNetworkInterface &operator=(QNetworkInterface &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QNetworkInterface &operator=(QNetworkInterface &&other) noexcept { swap(other); return *this; }
QNetworkInterface &operator=(const QNetworkInterface &other);
~QNetworkInterface();
- void swap(QNetworkInterface &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QNetworkInterface &other) noexcept { qSwap(d, other.d); }
bool isValid() const;
diff --git a/src/network/kernel/qnetworkinterface_p.h b/src/network/kernel/qnetworkinterface_p.h
index 87a46b75fa..44e27a7e34 100644
--- a/src/network/kernel/qnetworkinterface_p.h
+++ b/src/network/kernel/qnetworkinterface_p.h
@@ -82,7 +82,7 @@ public:
class QNetworkInterfacePrivate: public QSharedData
{
public:
- QNetworkInterfacePrivate() : index(0), flags(0)
+ QNetworkInterfacePrivate() : index(0), flags(nullptr)
{ }
~QNetworkInterfacePrivate()
{ }
diff --git a/src/network/kernel/qnetworkinterface_unix_p.h b/src/network/kernel/qnetworkinterface_unix_p.h
index c085194e3c..553af5a303 100644
--- a/src/network/kernel/qnetworkinterface_unix_p.h
+++ b/src/network/kernel/qnetworkinterface_unix_p.h
@@ -80,7 +80,7 @@ QT_BEGIN_NAMESPACE
static QNetworkInterface::InterfaceFlags convertFlags(uint rawFlags)
{
- QNetworkInterface::InterfaceFlags flags = 0;
+ QNetworkInterface::InterfaceFlags flags = nullptr;
flags |= (rawFlags & IFF_UP) ? QNetworkInterface::IsUp : QNetworkInterface::InterfaceFlag(0);
flags |= (rawFlags & IFF_RUNNING) ? QNetworkInterface::IsRunning : QNetworkInterface::InterfaceFlag(0);
flags |= (rawFlags & IFF_BROADCAST) ? QNetworkInterface::CanBroadcast : QNetworkInterface::InterfaceFlag(0);
diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp
index 3646a9526a..2f840e9e13 100644
--- a/src/network/kernel/qnetworkproxy.cpp
+++ b/src/network/kernel/qnetworkproxy.cpp
@@ -483,7 +483,7 @@ public:
template<> void QSharedDataPointer<QNetworkProxyPrivate>::detach()
{
- if (d && d->ref.load() == 1)
+ if (d && d->ref.loadRelaxed() == 1)
return;
QNetworkProxyPrivate *x = (d ? new QNetworkProxyPrivate(*d)
: new QNetworkProxyPrivate);
@@ -925,7 +925,7 @@ public:
template<> void QSharedDataPointer<QNetworkProxyQueryPrivate>::detach()
{
- if (d && d->ref.load() == 1)
+ if (d && d->ref.loadRelaxed() == 1)
return;
QNetworkProxyQueryPrivate *x = (d ? new QNetworkProxyQueryPrivate(*d)
: new QNetworkProxyQueryPrivate);
diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h
index 7e3e6906a8..302a2ce6ca 100644
--- a/src/network/kernel/qnetworkproxy.h
+++ b/src/network/kernel/qnetworkproxy.h
@@ -89,13 +89,11 @@ public:
QueryType queryType = TcpServer);
#endif
QNetworkProxyQuery(const QNetworkProxyQuery &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QNetworkProxyQuery &operator=(QNetworkProxyQuery &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QNetworkProxyQuery &operator=(QNetworkProxyQuery &&other) noexcept { swap(other); return *this; }
QNetworkProxyQuery &operator=(const QNetworkProxyQuery &other);
~QNetworkProxyQuery();
- void swap(QNetworkProxyQuery &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QNetworkProxyQuery &other) noexcept { qSwap(d, other.d); }
bool operator==(const QNetworkProxyQuery &other) const;
inline bool operator!=(const QNetworkProxyQuery &other) const
@@ -161,13 +159,11 @@ public:
QNetworkProxy(ProxyType type, const QString &hostName = QString(), quint16 port = 0,
const QString &user = QString(), const QString &password = QString());
QNetworkProxy(const QNetworkProxy &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QNetworkProxy &operator=(QNetworkProxy &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QNetworkProxy &operator=(QNetworkProxy &&other) noexcept { swap(other); return *this; }
QNetworkProxy &operator=(const QNetworkProxy &other);
~QNetworkProxy();
- void swap(QNetworkProxy &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QNetworkProxy &other) noexcept { qSwap(d, other.d); }
bool operator==(const QNetworkProxy &other) const;
inline bool operator!=(const QNetworkProxy &other) const
diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp
index db51732bd3..56397814b0 100644
--- a/src/network/kernel/qnetworkproxy_win.cpp
+++ b/src/network/kernel/qnetworkproxy_win.cpp
@@ -370,7 +370,7 @@ static QList<QNetworkProxy> parseServerList(const QNetworkProxyQuery &query, con
#if !defined(Q_OS_WINRT)
namespace {
class QRegistryWatcher {
- Q_DISABLE_COPY(QRegistryWatcher)
+ Q_DISABLE_COPY_MOVE(QRegistryWatcher)
public:
QRegistryWatcher() = default;
@@ -425,7 +425,7 @@ private:
class QWindowsSystemProxy
{
- Q_DISABLE_COPY(QWindowsSystemProxy)
+ Q_DISABLE_COPY_MOVE(QWindowsSystemProxy)
public:
QWindowsSystemProxy();
~QWindowsSystemProxy();
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index e86793cb21..9c8f29e18a 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -914,7 +914,7 @@ void QAbstractSocketPrivate::resolveProxy(const QString &hostname, quint16 port)
proxies << proxy;
} else {
// try the application settings instead
- QNetworkProxyQuery query(hostname, port, QString(),
+ QNetworkProxyQuery query(hostname, port, protocolTag,
socketType == QAbstractSocket::TcpSocket ?
QNetworkProxyQuery::TcpSocket :
socketType == QAbstractSocket::SctpSocket ?
@@ -2959,6 +2959,38 @@ QNetworkProxy QAbstractSocket::proxy() const
Q_D(const QAbstractSocket);
return d->proxy;
}
+
+/*!
+ \since 5.13
+
+ Returns the protocol tag for this socket.
+ If the protocol tag is set then this is passed to QNetworkProxyQuery
+ when this is created internally to indicate the protocol tag to be
+ used.
+
+ \sa setProtocolTag(), QNetworkProxyQuery
+*/
+
+QString QAbstractSocket::protocolTag() const
+{
+ Q_D(const QAbstractSocket);
+ return d->protocolTag;
+}
+
+/*!
+ \since 5.13
+
+ Sets the protocol tag for this socket to \a tag.
+
+ \sa protocolTag()
+*/
+
+void QAbstractSocket::setProtocolTag(const QString &tag)
+{
+ Q_D(QAbstractSocket);
+ d->protocolTag = tag;
+}
+
#endif // QT_NO_NETWORKPROXY
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h
index 6d5e57ac52..de09195eeb 100644
--- a/src/network/socket/qabstractsocket.h
+++ b/src/network/socket/qabstractsocket.h
@@ -197,6 +197,8 @@ public:
#ifndef QT_NO_NETWORKPROXY
void setProxy(const QNetworkProxy &networkProxy);
QNetworkProxy proxy() const;
+ QString protocolTag() const;
+ void setProtocolTag(const QString &tag);
#endif
Q_SIGNALS:
diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h
index 066a35ff85..5aa69d747e 100644
--- a/src/network/socket/qabstractsocket_p.h
+++ b/src/network/socket/qabstractsocket_p.h
@@ -83,7 +83,7 @@ public:
#ifndef QT_NO_NETWORKPROXY
inline void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator) override {
Q_Q(QAbstractSocket);
- q->proxyAuthenticationRequired(proxy, authenticator);
+ emit q->proxyAuthenticationRequired(proxy, authenticator);
}
#endif
@@ -124,6 +124,7 @@ public:
#ifndef QT_NO_NETWORKPROXY
QNetworkProxy proxy;
QNetworkProxy proxyInUse;
+ QString protocolTag;
void resolveProxy(const QString &hostName, quint16 port);
#else
inline void resolveProxy(const QString &, quint16) { }
diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h
index b15dd73c96..112e7032d6 100644
--- a/src/network/socket/qabstractsocketengine_p.h
+++ b/src/network/socket/qabstractsocketengine_p.h
@@ -88,7 +88,7 @@ public:
static QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType, const QNetworkProxy &, QObject *parent);
static QAbstractSocketEngine *createSocketEngine(qintptr socketDescriptor, QObject *parent);
- QAbstractSocketEngine(QObject *parent = 0);
+ QAbstractSocketEngine(QObject *parent = nullptr);
enum SocketOption {
NonBlockingSocketOption,
@@ -155,7 +155,7 @@ public:
virtual qint64 pendingDatagramSize() const = 0;
#endif // QT_NO_UDPSOCKET
- virtual qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header = 0,
+ virtual qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header = nullptr,
PacketHeaderOptions = WantNone) = 0;
virtual qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header) = 0;
virtual qint64 bytesToWrite() const = 0;
@@ -163,11 +163,11 @@ public:
virtual int option(SocketOption option) const = 0;
virtual bool setOption(SocketOption option, int value) = 0;
- virtual bool waitForRead(int msecs = 30000, bool *timedOut = 0) = 0;
- virtual bool waitForWrite(int msecs = 30000, bool *timedOut = 0) = 0;
+ virtual bool waitForRead(int msecs = 30000, bool *timedOut = nullptr) = 0;
+ virtual bool waitForWrite(int msecs = 30000, bool *timedOut = nullptr) = 0;
virtual bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
bool checkRead, bool checkWrite,
- int msecs = 30000, bool *timedOut = 0) = 0;
+ int msecs = 30000, bool *timedOut = nullptr) = 0;
QAbstractSocket::SocketError error() const;
QString errorString() const;
@@ -202,7 +202,7 @@ public Q_SLOTS:
public:
void setReceiver(QAbstractSocketEngineReceiver *receiver);
protected:
- QAbstractSocketEngine(QAbstractSocketEnginePrivate &dd, QObject* parent = 0);
+ QAbstractSocketEngine(QAbstractSocketEnginePrivate &dd, QObject* parent = nullptr);
void setError(QAbstractSocket::SocketError error, const QString &errorString) const;
void setState(QAbstractSocket::SocketState state);
@@ -215,7 +215,7 @@ protected:
private:
Q_DECLARE_PRIVATE(QAbstractSocketEngine)
- Q_DISABLE_COPY(QAbstractSocketEngine)
+ Q_DISABLE_COPY_MOVE(QAbstractSocketEngine)
};
class QAbstractSocketEnginePrivate : public QObjectPrivate
diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp
index 9427c3b00d..6cae29193d 100644
--- a/src/network/socket/qhttpsocketengine.cpp
+++ b/src/network/socket/qhttpsocketengine.cpp
@@ -524,7 +524,7 @@ void QHttpSocketEngine::slotSocketConnected()
//qDebug() << "slotSocketConnected: priv=" << priv << (priv ? (int)priv->method : -1);
if (priv && priv->method != QAuthenticatorPrivate::None) {
d->credentialsSent = true;
- data += "Proxy-Authorization: " + priv->calculateResponse(method, path);
+ data += "Proxy-Authorization: " + priv->calculateResponse(method, path, d->proxy.hostName());
data += "\r\n";
}
data += "\r\n";
@@ -649,7 +649,7 @@ void QHttpSocketEngine::slotSocketReadNotification()
}
if (priv->phase == QAuthenticatorPrivate::Done)
- emit proxyAuthenticationRequired(d->proxy, &d->authenticator);
+ proxyAuthenticationRequired(d->proxy, &d->authenticator);
// priv->phase will get reset to QAuthenticatorPrivate::Start if the authenticator got modified in the signal above.
if (priv->phase == QAuthenticatorPrivate::Done) {
setError(QAbstractSocket::ProxyAuthenticationRequiredError, tr("Authentication required"));
@@ -771,7 +771,7 @@ void QHttpSocketEngine::emitPendingReadNotification()
Q_D(QHttpSocketEngine);
d->readNotificationPending = false;
if (d->readNotificationEnabled)
- emit readNotification();
+ readNotification();
}
void QHttpSocketEngine::emitPendingWriteNotification()
@@ -779,14 +779,14 @@ void QHttpSocketEngine::emitPendingWriteNotification()
Q_D(QHttpSocketEngine);
d->writeNotificationPending = false;
if (d->writeNotificationEnabled)
- emit writeNotification();
+ writeNotification();
}
void QHttpSocketEngine::emitPendingConnectionNotification()
{
Q_D(QHttpSocketEngine);
d->connectionNotificationPending = false;
- emit connectionNotification();
+ connectionNotification();
}
void QHttpSocketEngine::emitReadNotification()
diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h
index cb7798694a..0c2c450c81 100644
--- a/src/network/socket/qhttpsocketengine_p.h
+++ b/src/network/socket/qhttpsocketengine_p.h
@@ -79,7 +79,7 @@ public:
ReadResponseContent,
ReadResponseHeader
};
- QHttpSocketEngine(QObject *parent = 0);
+ QHttpSocketEngine(QObject *parent = nullptr);
~QHttpSocketEngine();
bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) override;
@@ -126,11 +126,11 @@ public:
int option(SocketOption option) const override;
bool setOption(SocketOption option, int value) override;
- bool waitForRead(int msecs = 30000, bool *timedOut = 0) override;
- bool waitForWrite(int msecs = 30000, bool *timedOut = 0) override;
+ bool waitForRead(int msecs = 30000, bool *timedOut = nullptr) override;
+ bool waitForWrite(int msecs = 30000, bool *timedOut = nullptr) override;
bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
bool checkRead, bool checkWrite,
- int msecs = 30000, bool *timedOut = 0) override;
+ int msecs = 30000, bool *timedOut = nullptr) override;
bool isReadNotificationEnabled() const override;
void setReadNotificationEnabled(bool enable) override;
@@ -160,7 +160,7 @@ private:
bool readHttpHeader();
Q_DECLARE_PRIVATE(QHttpSocketEngine)
- Q_DISABLE_COPY(QHttpSocketEngine)
+ Q_DISABLE_COPY_MOVE(QHttpSocketEngine)
};
diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp
index a9789b7d04..3e36a7b229 100644
--- a/src/network/socket/qlocalserver.cpp
+++ b/src/network/socket/qlocalserver.cpp
@@ -408,7 +408,7 @@ int QLocalServer::maxPendingConnections() const
still a good idea to delete the object explicitly when you are done with
it, to avoid wasting memory.
- 0 is returned if this function is called when there are no pending
+ \nullptr is returned if this function is called when there are no pending
connections.
\sa hasPendingConnections(), newConnection(), incomingConnection()
@@ -506,8 +506,8 @@ void QLocalServer::setMaxPendingConnections(int numConnections)
/*!
Waits for at most \a msec milliseconds or until an incoming connection
is available. Returns \c true if a connection is available; otherwise
- returns \c false. If the operation timed out and \a timedOut is not 0,
- *timedOut will be set to true.
+ returns \c false. If the operation timed out and \a timedOut is not
+ \nullptr, *timedOut will be set to true.
This is a blocking function call. Its use is ill-advised in a
single-threaded GUI application, since the whole application will stop
diff --git a/src/network/socket/qlocalserver_p.h b/src/network/socket/qlocalserver_p.h
index 2c073908cb..92616e59ce 100644
--- a/src/network/socket/qlocalserver_p.h
+++ b/src/network/socket/qlocalserver_p.h
@@ -78,7 +78,7 @@ class QLocalServerPrivate : public QObjectPrivate
public:
QLocalServerPrivate() :
#if !defined(QT_LOCALSOCKET_TCP) && !defined(Q_OS_WIN)
- listenSocket(-1), socketNotifier(0),
+ listenSocket(-1), socketNotifier(nullptr),
#endif
maxPendingConnections(30), error(QAbstractSocket::UnknownSocketError),
socketOptions(QLocalServer::NoOptions)
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index d6ee76043f..4decbd5ded 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -87,9 +87,9 @@ void QLocalSocketPrivate::_q_winError(ulong windowsError, const QString &functio
}
if (currentState != state) {
- q->emit stateChanged(state);
+ emit q->stateChanged(state);
if (state == QLocalSocket::UnconnectedState && currentState != QLocalSocket::ConnectingState)
- q->emit disconnected();
+ emit q->disconnected();
}
emit q->error(error);
}
diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp
index 8947a7ee8a..5126a5330f 100644
--- a/src/network/socket/qnativesocketengine.cpp
+++ b/src/network/socket/qnativesocketengine.cpp
@@ -999,8 +999,8 @@ void QNativeSocketEngine::close()
/*!
Waits for \a msecs milliseconds or until the socket is ready for
- reading. If \a timedOut is not 0 and \a msecs milliseconds have
- passed, the value of \a timedOut is set to true.
+ reading. If \a timedOut is not \nullptr and \a msecs milliseconds
+ have passed, the value of \a timedOut is set to true.
Returns \c true if data is available for reading; otherwise returns
false.
@@ -1039,8 +1039,8 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
/*!
Waits for \a msecs milliseconds or until the socket is ready for
- writing. If \a timedOut is not 0 and \a msecs milliseconds have
- passed, the value of \a timedOut is set to true.
+ writing. If \a timedOut is not \nullptr and \a msecs milliseconds
+ have passed, the value of \a timedOut is set to true.
Returns \c true if data is available for writing; otherwise returns
false.
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index aa61b74823..e5f0701d14 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -125,7 +125,7 @@ class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine
{
Q_OBJECT
public:
- QNativeSocketEngine(QObject *parent = 0);
+ QNativeSocketEngine(QObject *parent = nullptr);
~QNativeSocketEngine();
bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) override;
@@ -161,7 +161,7 @@ public:
qint64 pendingDatagramSize() const override;
#endif // QT_NO_UDPSOCKET
- qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0,
+ qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = nullptr,
PacketHeaderOptions = WantNone) override;
qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) override;
qint64 bytesToWrite() const override;
@@ -177,11 +177,11 @@ public:
int option(SocketOption option) const override;
bool setOption(SocketOption option, int value) override;
- bool waitForRead(int msecs = 30000, bool *timedOut = 0) override;
- bool waitForWrite(int msecs = 30000, bool *timedOut = 0) override;
+ bool waitForRead(int msecs = 30000, bool *timedOut = nullptr) override;
+ bool waitForWrite(int msecs = 30000, bool *timedOut = nullptr) override;
bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
bool checkRead, bool checkWrite,
- int msecs = 30000, bool *timedOut = 0) override;
+ int msecs = 30000, bool *timedOut = nullptr) override;
bool isReadNotificationEnabled() const override;
void setReadNotificationEnabled(bool enable) override;
@@ -196,7 +196,7 @@ public Q_SLOTS:
private:
Q_DECLARE_PRIVATE(QNativeSocketEngine)
- Q_DISABLE_COPY(QNativeSocketEngine)
+ Q_DISABLE_COPY_MOVE(QNativeSocketEngine)
};
class QSocketNotifier;
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index c999bd2088..24e8eabb6e 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -1146,22 +1146,17 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
qint64 ret = -1;
int recvResult = 0;
DWORD flags;
- DWORD bufferCount = 5;
- WSABUF * buf = 0;
+ // We start at 1500 bytes (the MTU for Ethernet V2), which should catch
+ // almost all uses (effective MTU for UDP under IPv4 is 1468), except
+ // for localhost datagrams and those reassembled by the IP layer.
+ char udpMessagePeekBuffer[1500];
+ std::vector<WSABUF> buf;
for (;;) {
- // We start at 1500 bytes (the MTU for Ethernet V2), which should catch
- // almost all uses (effective MTU for UDP under IPv4 is 1468), except
- // for localhost datagrams and those reassembled by the IP layer.
- char udpMessagePeekBuffer[1500];
-
- buf = new WSABUF[bufferCount];
- for (DWORD i=0; i<bufferCount; i++) {
- buf[i].buf = udpMessagePeekBuffer;
- buf[i].len = sizeof(udpMessagePeekBuffer);
- }
+ buf.resize(buf.size() + 5, {sizeof(udpMessagePeekBuffer), udpMessagePeekBuffer});
+
flags = MSG_PEEK;
DWORD bytesRead = 0;
- recvResult = ::WSARecv(socketDescriptor, buf, bufferCount, &bytesRead, &flags, 0,0);
+ recvResult = ::WSARecv(socketDescriptor, buf.data(), DWORD(buf.size()), &bytesRead, &flags, nullptr, nullptr);
int err = WSAGetLastError();
if (recvResult != SOCKET_ERROR) {
ret = qint64(bytesRead);
@@ -1169,8 +1164,6 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
} else {
switch (err) {
case WSAEMSGSIZE:
- bufferCount += 5;
- delete[] buf;
continue;
case WSAECONNRESET:
case WSAENETRESET:
@@ -1185,9 +1178,6 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
}
}
- if (buf)
- delete[] buf;
-
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %lli", ret);
#endif
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index 6688bfe35c..e1fe58bb97 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -188,7 +188,7 @@ private slots:
private:
Q_DECLARE_PRIVATE(QNativeSocketEngine)
- Q_DISABLE_COPY(QNativeSocketEngine)
+ Q_DISABLE_COPY_MOVE(QNativeSocketEngine)
};
class QNativeSocketEnginePrivate : public QAbstractSocketEnginePrivate
diff --git a/src/network/socket/qsctpserver.cpp b/src/network/socket/qsctpserver.cpp
index 77cb997192..2aa694b3fd 100644
--- a/src/network/socket/qsctpserver.cpp
+++ b/src/network/socket/qsctpserver.cpp
@@ -229,13 +229,12 @@ QSctpSocket *QSctpServer::nextPendingDatagramConnection()
{
Q_D(QSctpServer);
- QMutableListIterator<QTcpSocket *> i(d->pendingConnections);
- while (i.hasNext()) {
- QSctpSocket *socket = qobject_cast<QSctpSocket *>(i.next());
+ for (auto it = d->pendingConnections.begin(), end = d->pendingConnections.end(); it != end; ++it) {
+ QSctpSocket *socket = qobject_cast<QSctpSocket *>(*it);
Q_ASSERT(socket);
if (socket->isInDatagramMode()) {
- i.remove();
+ d->pendingConnections.erase(it);
Q_ASSERT(d->socketEngine);
d->socketEngine->setReadNotificationEnabled(true);
return socket;
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index dd2bc90855..23aec12390 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -372,7 +372,7 @@ QSocks5BindData *QSocks5BindStore::retrieve(qintptr socketDescriptor)
store.erase(it);
if (bindData) {
if (bindData->controlSocket->thread() != QThread::currentThread()) {
- qWarning("Can not access socks5 bind data from different thread");
+ qWarning("Cannot access socks5 bind data from different thread");
return 0;
}
} else {
@@ -706,7 +706,7 @@ void QSocks5SocketEnginePrivate::reauthenticate()
// we require authentication
QAuthenticator auth;
- emit q->proxyAuthenticationRequired(proxyInfo, &auth);
+ q->proxyAuthenticationRequired(proxyInfo, &auth);
if (!auth.user().isEmpty() || !auth.password().isEmpty()) {
// we have new credentials, let's try again
@@ -915,7 +915,7 @@ void QSocks5SocketEnginePrivate::_q_emitPendingReadNotification()
if (readNotificationEnabled) {
QSOCKS5_D_DEBUG << "emitting readNotification";
QPointer<QSocks5SocketEngine> qq = q;
- emit q->readNotification();
+ q->readNotification();
if (!qq)
return;
// check if there needs to be a new zero read notification
@@ -944,7 +944,7 @@ void QSocks5SocketEnginePrivate::_q_emitPendingWriteNotification()
Q_Q(QSocks5SocketEngine);
if (writeNotificationEnabled) {
QSOCKS5_D_DEBUG << "emitting writeNotification";
- emit q->writeNotification();
+ q->writeNotification();
}
}
@@ -964,7 +964,7 @@ void QSocks5SocketEnginePrivate::_q_emitPendingConnectionNotification()
connectionNotificationPending = false;
Q_Q(QSocks5SocketEngine);
QSOCKS5_D_DEBUG << "emitting connectionNotification";
- emit q->connectionNotification();
+ q->connectionNotification();
}
void QSocks5SocketEnginePrivate::emitConnectionNotification()
diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h
index 1942eff4ca..c256987e2d 100644
--- a/src/network/socket/qsocks5socketengine_p.h
+++ b/src/network/socket/qsocks5socketengine_p.h
@@ -65,7 +65,7 @@ class Q_AUTOTEST_EXPORT QSocks5SocketEngine : public QAbstractSocketEngine
{
Q_OBJECT
public:
- QSocks5SocketEngine(QObject *parent = 0);
+ QSocks5SocketEngine(QObject *parent = nullptr);
~QSocks5SocketEngine();
bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) override;
@@ -104,7 +104,7 @@ public:
qint64 pendingDatagramSize() const override;
#endif // QT_NO_UDPSOCKET
- qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0,
+ qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = nullptr,
PacketHeaderOptions = WantNone) override;
qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) override;
qint64 bytesToWrite() const override;
@@ -112,11 +112,11 @@ public:
int option(SocketOption option) const override;
bool setOption(SocketOption option, int value) override;
- bool waitForRead(int msecs = 30000, bool *timedOut = 0) override;
- bool waitForWrite(int msecs = 30000, bool *timedOut = 0) override;
+ bool waitForRead(int msecs = 30000, bool *timedOut = nullptr) override;
+ bool waitForWrite(int msecs = 30000, bool *timedOut = nullptr) override;
bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
bool checkRead, bool checkWrite,
- int msecs = 30000, bool *timedOut = 0) override;
+ int msecs = 30000, bool *timedOut = nullptr) override;
bool isReadNotificationEnabled() const override;
void setReadNotificationEnabled(bool enable) override;
@@ -127,7 +127,7 @@ public:
private:
Q_DECLARE_PRIVATE(QSocks5SocketEngine)
- Q_DISABLE_COPY(QSocks5SocketEngine)
+ Q_DISABLE_COPY_MOVE(QSocks5SocketEngine)
Q_PRIVATE_SLOT(d_func(), void _q_controlSocketConnected())
Q_PRIVATE_SLOT(d_func(), void _q_controlSocketReadNotification())
Q_PRIVATE_SLOT(d_func(), void _q_controlSocketError(QAbstractSocket::SocketError))
diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp
index eddf789921..98e58192a2 100644
--- a/src/network/socket/qtcpserver.cpp
+++ b/src/network/socket/qtcpserver.cpp
@@ -493,7 +493,7 @@ QHostAddress QTcpServer::serverAddress() const
Waits for at most \a msec milliseconds or until an incoming
connection is available. Returns \c true if a connection is
available; otherwise returns \c false. If the operation timed out
- and \a timedOut is not 0, *\a timedOut will be set to true.
+ and \a timedOut is not \nullptr, *\a timedOut will be set to true.
This is a blocking function call. Its use is disadvised in a
single-threaded GUI application, since the whole application will
@@ -548,7 +548,7 @@ bool QTcpServer::hasPendingConnections() const
destroyed. It is still a good idea to delete the object
explicitly when you are done with it, to avoid wasting memory.
- 0 is returned if this function is called when there are no pending
+ \nullptr is returned if this function is called when there are no pending
connections.
\note The returned QTcpSocket object cannot be used from another
diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri
index 44ff5b7b39..c3a98ea31a 100644
--- a/src/network/socket/socket.pri
+++ b/src/network/socket/socket.pri
@@ -58,7 +58,7 @@ unix {
msvc: QMAKE_MOC_OPTIONS += -D_WINSOCK_DEPRECATED_NO_WARNINGS
win32:!winrt:SOURCES += socket/qnativesocketengine_win.cpp
-win32:!winrt:LIBS_PRIVATE += -ladvapi32
+win32:!winrt: QMAKE_USE_PRIVATE += advapi32
winrt {
SOURCES += socket/qnativesocketengine_winrt.cpp
diff --git a/src/network/ssl/qasn1element_p.h b/src/network/ssl/qasn1element_p.h
index 2068254a95..020b5aa1af 100644
--- a/src/network/ssl/qasn1element_p.h
+++ b/src/network/ssl/qasn1element_p.h
@@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
#define RSA_ENCRYPTION_OID QByteArrayLiteral(RSADSI_OID "1.1.1")
#define DSA_ENCRYPTION_OID QByteArrayLiteral("1.2.840.10040.4.1")
#define EC_ENCRYPTION_OID QByteArrayLiteral("1.2.840.10045.2.1")
+#define DH_ENCRYPTION_OID QByteArrayLiteral(RSADSI_OID "1.3.1")
// These are mostly from the RFC for PKCS#5
// PKCS#5: https://tools.ietf.org/html/rfc8018#appendix-B
@@ -137,6 +138,7 @@ public:
Rfc822NameType = 0x81,
DnsNameType = 0x82,
UniformResourceIdentifierType = 0x86,
+ IpAddressType = 0x87,
// context specific
Context0Type = 0xA0,
@@ -154,10 +156,10 @@ public:
static QAsn1Element fromVector(const QVector<QAsn1Element> &items);
static QAsn1Element fromObjectId(const QByteArray &id);
- bool toBool(bool *ok = 0) const;
+ bool toBool(bool *ok = nullptr) const;
QDateTime toDateTime() const;
QMultiMap<QByteArray, QString> toInfo() const;
- qint64 toInteger(bool *ok = 0) const;
+ qint64 toInteger(bool *ok = nullptr) const;
QVector<QAsn1Element> toVector() const;
QByteArray toObjectId() const;
QByteArray toObjectName() const;
diff --git a/src/network/ssl/qdtls.cpp b/src/network/ssl/qdtls.cpp
index 3185bfa124..a2280a7d10 100644
--- a/src/network/ssl/qdtls.cpp
+++ b/src/network/ssl/qdtls.cpp
@@ -342,7 +342,7 @@ QT_BEGIN_NAMESPACE
QSslConfiguration QDtlsBasePrivate::configuration() const
{
auto copyPrivate = new QSslConfigurationPrivate(dtlsConfiguration);
- copyPrivate->ref.store(0); // the QSslConfiguration constructor refs up
+ copyPrivate->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up
QSslConfiguration copy(copyPrivate);
copyPrivate->sessionCipher = sessionCipher;
copyPrivate->sessionProtocol = sessionProtocol;
diff --git a/src/network/ssl/qdtls.h b/src/network/ssl/qdtls.h
index 8505b00d5e..d057eadf19 100644
--- a/src/network/ssl/qdtls.h
+++ b/src/network/ssl/qdtls.h
@@ -48,7 +48,9 @@
#include <QtCore/qcryptographichash.h>
#include <QtCore/qobject.h>
+#ifndef Q_CLANG_QDOC
QT_REQUIRE_CONFIG(dtls);
+#endif
QT_BEGIN_NAMESPACE
diff --git a/src/network/ssl/qdtls_openssl.cpp b/src/network/ssl/qdtls_openssl.cpp
index 8be53df24f..d9ddcceb40 100644
--- a/src/network/ssl/qdtls_openssl.cpp
+++ b/src/network/ssl/qdtls_openssl.cpp
@@ -729,7 +729,7 @@ bool DtlsState::initCtxAndConnection(QDtlsBasePrivate *dtlsBase)
// Create a deep copy of our configuration
auto configurationCopy = new QSslConfigurationPrivate(dtlsBase->dtlsConfiguration);
- configurationCopy->ref.store(0); // the QSslConfiguration constructor refs up
+ configurationCopy->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up
// DTLSTODO: check we do not set something DTLS-incompatible there ...
TlsContext newContext(QSslContext::sharedFromConfiguration(dtlsBase->mode,
diff --git a/src/plugins/platforms/mirclient/qmirclientbackingstore.h b/src/network/ssl/qocsp_p.h
index 7644c77df2..71f59da0b4 100644
--- a/src/plugins/platforms/mirclient/qmirclientbackingstore.h
+++ b/src/network/ssl/qocsp_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtNetwork module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,38 +37,38 @@
**
****************************************************************************/
+#ifndef QOCSP_P_H
+#define QOCSP_P_H
-#ifndef QMIRCLIENTBACKINGSTORE_H
-#define QMIRCLIENTBACKINGSTORE_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
-#include <qpa/qplatformbackingstore.h>
+// Note, this file is a workaround: on 64-bit Windows one of OpenSSL
+// includes combined with openssl/ocsp.h results in macros from
+// wincrypt.h exposed. OpenSSL's own very "unique" and "inventive"
+// names like OCSP_RESPONSE or X509_NAME were asking to clash with
+// other entities (presumably macros) with the same names. Normally,
+// ossl_typ.h un-defines them, but due to a bug in OpenSSL, fails
+// to do this on Win 64. Thus we have to do it here. We only undef
+// 3 names, ossl_typ.h has more, but apparently we don't need them
+// (no name clash so far).
-class QOpenGLContext;
-class QOpenGLTexture;
-class QOpenGLTextureBlitter;
+QT_REQUIRE_CONFIG(ocsp);
-class QMirClientBackingStore : public QPlatformBackingStore
-{
-public:
- QMirClientBackingStore(QWindow* window);
- virtual ~QMirClientBackingStore();
+#ifdef Q_OS_WIN
+#undef X509_NAME
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
+#endif // Q_OS_WIN
- // QPlatformBackingStore methods.
- void beginPaint(const QRegion&) override;
- void flush(QWindow* window, const QRegion& region, const QPoint& offset) override;
- void resize(const QSize& size, const QRegion& staticContents) override;
- QPaintDevice* paintDevice() override;
- QImage toImage() const override;
+#include <openssl/ocsp.h>
-protected:
- void updateTexture();
-
-private:
- QScopedPointer<QOpenGLContext> mContext;
- QScopedPointer<QOpenGLTexture> mTexture;
- QScopedPointer<QOpenGLTextureBlitter> mBlitter;
- QImage mImage;
- QRegion mDirty;
-};
-
-#endif // QMIRCLIENTBACKINGSTORE_H
+#endif // QOCSP_P_H
diff --git a/src/network/ssl/qocspresponse.cpp b/src/network/ssl/qocspresponse.cpp
new file mode 100644
index 0000000000..79f0cfd1d4
--- /dev/null
+++ b/src/network/ssl/qocspresponse.cpp
@@ -0,0 +1,258 @@
+/****************************************************************************
+** Copyright (C) 2011 Richard J. Moore <rich@kde.org>
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qocspresponse_p.h"
+#include "qocspresponse.h"
+
+#include "qhashfunctions.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOcspResponse
+ \brief This class represents Online Certificate Status Protocol response.
+ \since 5.13
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ The QOcspResponse class represents the revocation status of a server's certficate,
+ received by the client-side socket during the TLS handshake. QSslSocket must be
+ configured with OCSP stapling enabled.
+
+ \sa QSslSocket, QSslSocket::ocspResponses(), certificateStatus(),
+ revocationReason(), responder(), subject(), QOcspCertificateStatus, QOcspRevocationReason,
+ QSslConfiguration::setOcspStaplingEnabled(), QSslConfiguration::ocspStaplingEnabled(),
+ QSslConfiguration::peerCertificate()
+*/
+
+/*!
+ \enum QOcspCertificateStatus
+ \brief Describes the Online Certificate Status
+ \relates QOcspResponse
+ \since 5.13
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ \value Good The certificate is not revoked, but this does not necessarily
+ mean that the certificate was ever issued or that the time at which
+ the response was produced is within the certificate's validity interval.
+ \value Revoked This state indicates that the certificate has been revoked
+ (either permanently or temporarily - on hold).
+ \value Unknown This state indicates that the responder doesn't know about
+ the certificate being requested.
+
+ \sa QOcspRevocationReason
+*/
+
+/*!
+ \enum QOcspRevocationReason
+ \brief Describes the reason for revocation
+ \relates QOcspResponse
+ \since 5.13
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+
+ This enumeration describes revocation reasons, defined in \l{https://tools.ietf.org/html/rfc5280#section-5.3.1}{RFC 5280, section 5.3.1}
+
+ \value None
+ \value Unspecified
+ \value KeyCompromise
+ \value CACompromise
+ \value AffiliationChanged
+ \value Superseded
+ \value CessationOfOperation
+ \value CertificateHold
+ \value RemoveFromCRL
+*/
+
+/*!
+ \since 5.13
+
+ Creates a new response with status QOcspCertificateStatus::Unknown
+ and revocation reason QOcspRevocationReason::None.
+
+ \sa QOcspCertificateStatus
+*/
+QOcspResponse::QOcspResponse()
+ : d(new QOcspResponsePrivate)
+{
+}
+
+/*!
+ \since 5.13
+
+ Copy-constructs a QOcspResponse instance.
+*/
+QOcspResponse::QOcspResponse(const QOcspResponse &) = default;
+
+/*!
+ \since 5.13
+
+ Move-constructs a QOcspResponse instance.
+*/
+QOcspResponse::QOcspResponse(QOcspResponse &&) noexcept = default;
+
+/*!
+ \since 5.13
+
+ Destroys the response.
+*/
+QOcspResponse::~QOcspResponse() = default;
+
+/*!
+ \since 5.13
+
+ Copy-assigns and returns a reference to this response.
+*/
+QOcspResponse &QOcspResponse::operator=(const QOcspResponse &) = default;
+
+/*!
+ \since 5.13
+
+ Move-assigns to this QOcspResponse instance.
+*/
+QOcspResponse &QOcspResponse::operator=(QOcspResponse &&) noexcept = default;
+
+/*!
+ \fn void QOcspResponse::swap(QOcspResponse &other)
+ \since 5.13
+
+ Swaps this response with \a other.
+*/
+
+/*!
+ \since 5.13
+
+ Returns the certificate status.
+
+ \sa QOcspCertificateStatus
+*/
+QOcspCertificateStatus QOcspResponse::certificateStatus() const
+{
+ return d->certificateStatus;
+}
+
+/*!
+ \since 5.13
+
+ Returns the reason for revocation.
+*/
+QOcspRevocationReason QOcspResponse::revocationReason() const
+{
+ return d->revocationReason;
+}
+
+/*!
+ \since 5.13
+
+ This function returns a certificate used to sign OCSP response.
+*/
+QSslCertificate QOcspResponse::responder() const
+{
+ return d->signerCert;
+}
+
+/*!
+ \since 5.13
+
+ This function returns a certificate, for which this response was issued.
+*/
+QSslCertificate QOcspResponse::subject() const
+{
+ return d->subjectCert;
+}
+
+/*!
+ \fn bool operator==(const QOcspResponse &lhs, const QOcspResponse &rhs)
+
+ Returns \c true if \a lhs and \a rhs are the responses for the same
+ certificate, signed by the same responder, have the same
+ revocation reason and the same certificate status.
+
+ \since 5.13
+ \relates QOcspResponse
+ */
+Q_NETWORK_EXPORT bool operator==(const QOcspResponse &lhs, const QOcspResponse &rhs)
+{
+ return lhs.d == rhs.d || *lhs.d == *rhs.d;
+}
+
+/*!
+ \fn bool operator != (const QOcspResponse &lhs, const QOcspResponse &rhs)
+
+ Returns \c true if \a lhs and \a rhs are responses for different certificates,
+ or signed by different responders, or have different revocation reasons, or different
+ certificate statuses.
+
+ \since 5.13
+ \relates QOcspResponse
+*/
+
+/*!
+ \fn uint qHash(const QOcspResponse &response, uint seed)
+
+ Returns the hash value for the \a response, using \a seed to seed the calculation.
+
+ \since 5.13
+ \relates QHash
+*/
+uint qHash(const QOcspResponse &response, uint seed)
+{
+ const QOcspResponsePrivate *d = response.d.data();
+ Q_ASSERT(d);
+
+ QtPrivate::QHashCombine hasher;
+ uint hash = hasher(seed, int(d->certificateStatus));
+ hash = hasher(hash, int(d->revocationReason));
+ if (!d->signerCert.isNull())
+ hash = hasher(hash, d->signerCert);
+ if (!d->subjectCert.isNull())
+ hash = hasher(hash, d->subjectCert);
+
+ return hash;
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qocspresponse.h b/src/network/ssl/qocspresponse.h
new file mode 100644
index 0000000000..0e134d236b
--- /dev/null
+++ b/src/network/ssl/qocspresponse.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+** Copyright (C) 2011 Richard J. Moore <rich@kde.org>
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOCSPRESPONSE_H
+#define QOCSPRESPONSE_H
+
+#include <QtNetwork/qtnetworkglobal.h>
+
+#include <QtCore/qshareddata.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qobject.h>
+
+#ifndef Q_CLANG_QDOC
+QT_REQUIRE_CONFIG(ssl);
+#endif
+
+QT_BEGIN_NAMESPACE
+
+enum class QOcspCertificateStatus
+{
+ Good,
+ Revoked,
+ Unknown
+};
+
+enum class QOcspRevocationReason
+{
+ None = -1,
+ Unspecified,
+ KeyCompromise,
+ CACompromise,
+ AffiliationChanged,
+ Superseded,
+ CessationOfOperation,
+ CertificateHold,
+ RemoveFromCRL
+};
+
+class QOcspResponse;
+Q_NETWORK_EXPORT uint qHash(const QOcspResponse &response, uint seed = 0);
+
+class QOcspResponsePrivate;
+class Q_NETWORK_EXPORT QOcspResponse
+{
+public:
+
+ QOcspResponse();
+ QOcspResponse(const QOcspResponse &other);
+ QOcspResponse(QOcspResponse && other) noexcept;
+ ~QOcspResponse();
+
+ QOcspResponse &operator = (const QOcspResponse &other);
+ QOcspResponse &operator = (QOcspResponse &&other) noexcept;
+
+ QOcspCertificateStatus certificateStatus() const;
+ QOcspRevocationReason revocationReason() const;
+
+ class QSslCertificate responder() const;
+ QSslCertificate subject() const;
+
+ void swap(QOcspResponse &other) noexcept { d.swap(other.d); }
+
+private:
+
+ friend class QSslSocketBackendPrivate;
+ friend Q_NETWORK_EXPORT bool operator==(const QOcspResponse &lhs, const QOcspResponse &rhs);
+ friend Q_NETWORK_EXPORT uint qHash(const QOcspResponse &response, uint seed);
+
+ QSharedDataPointer<QOcspResponsePrivate> d;
+};
+
+inline bool operator!=(const QOcspResponse &lhs, const QOcspResponse &rhs) { return !(lhs == rhs); }
+
+Q_DECLARE_SHARED(QOcspResponse)
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QOcspResponse)
+
+#endif // QOCSPRESPONSE_H
diff --git a/src/network/ssl/qocspresponse_p.h b/src/network/ssl/qocspresponse_p.h
new file mode 100644
index 0000000000..e421b76899
--- /dev/null
+++ b/src/network/ssl/qocspresponse_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+** Copyright (C) 2011 Richard J. Moore <rich@kde.org>
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOCSPRESPONSE_P_H
+#define QOCSPRESPONSE_P_H
+
+#include <private/qtnetworkglobal_p.h>
+
+#include <qsslcertificate.h>
+#include <qocspresponse.h>
+
+#include <qshareddata.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QOcspResponsePrivate : public QSharedData
+{
+public:
+
+ QOcspCertificateStatus certificateStatus = QOcspCertificateStatus::Unknown;
+ QOcspRevocationReason revocationReason = QOcspRevocationReason::None;
+
+ QSslCertificate signerCert;
+ QSslCertificate subjectCert;
+};
+
+inline bool operator==(const QOcspResponsePrivate &lhs, const QOcspResponsePrivate &rhs)
+{
+ return lhs.certificateStatus == rhs.certificateStatus
+ && lhs.revocationReason == rhs.revocationReason
+ && lhs.signerCert == rhs.signerCert
+ && lhs.subjectCert == rhs.subjectCert;
+}
+
+QT_END_NAMESPACE
+
+#endif // QOCSPRESPONSE_P_H
diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp
index 19d99bc489..c9fa7f85d9 100644
--- a/src/network/ssl/qssl.cpp
+++ b/src/network/ssl/qssl.cpp
@@ -71,7 +71,8 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
\value Rsa The RSA algorithm.
\value Dsa The DSA algorithm.
- \value Ec The Elliptic Curve algorithm
+ \value Ec The Elliptic Curve algorithm.
+ \value Dh The Diffie-Hellman algorithm.
\value Opaque A key that should be treated as a 'black box' by QSslKey.
The opaque key facility allows applications to add support for facilities
@@ -98,6 +99,9 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
\value DnsEntry A DNS host name entry; the entry contains a host name
entry that the certificate is valid for. The entry may contain wildcards.
+ \value IpAddressEntry An IP address entry; the entry contains an IP address
+ entry that the certificate is valid for, introduced in Qt 5.13.
+
\note In Qt 4, this enum was called \c {AlternateNameEntryType}. That name
is deprecated in Qt 5.
@@ -116,8 +120,8 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
Describes the protocol of the cipher.
- \value SslV3 SSLv3. When using the WinRT backend this option will also enable TLSv1.0
- \value SslV2 SSLv2. Note, SSLv2 support was removed in OpenSSL 1.1.
+ \value SslV3 SSLv3; not supported by QSslSocket.
+ \value SslV2 SSLv2; not supported by QSslSocket.
\value TlsV1_0 TLSv1.0
\value TlsV1_0OrLater TLSv1.0 and later versions. This option is not available when using the WinRT backend due to platform limitations.
\value TlsV1 Obsolete, means the same as TlsV1_0
@@ -132,19 +136,9 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
\value TlsV1_3 TLSv1.3. (Since Qt 5.12)
\value TlsV1_3OrLater TLSv1.3 and later versions. (Since Qt 5.12)
\value UnknownProtocol The cipher's protocol cannot be determined.
- \value AnyProtocol The socket understands SSLv2, SSLv3, TLSv1.0 and all
- supported later versions of TLS. This value is used by QSslSocket only.
- \value TlsV1SslV3 On the client side, this will send
- a TLS 1.0 Client Hello, enabling TLSv1_0 and SSLv3 connections.
- On the server side, this will enable both SSLv3 and TLSv1_0 connections.
- \value SecureProtocols The default option, using protocols known to be secure;
- currently behaves similar to TlsV1Ssl3 except denying SSLv3 connections that does
- not upgrade to TLS.
-
- \note most servers understand both SSL and TLS, but it is recommended to use
- TLS only for security reasons. However, SSL and TLS are not compatible with
- each other: if you get unexpected handshake failures, verify that you chose
- the correct setting for your protocol.
+ \value AnyProtocol Any supported protocol. This value is used by QSslSocket only.
+ \value TlsV1SslV3 Same as TlsV1_0.
+ \value SecureProtocols The default option, using protocols known to be secure.
*/
/*!
diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h
index 60362cb410..42c7b5c56d 100644
--- a/src/network/ssl/qssl.h
+++ b/src/network/ssl/qssl.h
@@ -62,12 +62,14 @@ namespace QSsl {
Opaque,
Rsa,
Dsa,
- Ec
+ Ec,
+ Dh,
};
enum AlternativeNameEntryType {
EmailEntry,
- DnsEntry
+ DnsEntry,
+ IpAddressEntry
};
#if QT_DEPRECATED_SINCE(5,0)
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index d153e0b929..4820953468 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -121,6 +121,9 @@
#ifdef QT_SECURETRANSPORT
#include "qsslsocket_mac_p.h"
#endif
+#if QT_CONFIG(schannel)
+#include "qsslsocket_schannel_p.h"
+#endif
#include "qssl_p.h"
#include "qsslcertificate.h"
@@ -414,7 +417,7 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
/*!
\fn Qt::HANDLE QSslCertificate::handle() const
Returns a pointer to the native certificate handle, if there is
- one, or a null pointer otherwise.
+ one, else \nullptr.
You can use this handle, together with the native API, to access
extended information about the certificate.
diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h
index 266fcdacb4..69901b526c 100644
--- a/src/network/ssl/qsslcertificate.h
+++ b/src/network/ssl/qsslcertificate.h
@@ -66,7 +66,7 @@ class QStringList;
class QSslCertificate;
// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
-Q_NETWORK_EXPORT uint qHash(const QSslCertificate &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_NETWORK_EXPORT uint qHash(const QSslCertificate &key, uint seed = 0) noexcept;
class QSslCertificatePrivate;
class Q_NETWORK_EXPORT QSslCertificate
@@ -88,12 +88,10 @@ public:
explicit QSslCertificate(const QByteArray &data = QByteArray(), QSsl::EncodingFormat format = QSsl::Pem);
QSslCertificate(const QSslCertificate &other);
~QSslCertificate();
-#ifdef Q_COMPILER_RVALUE_REFS
- QSslCertificate &operator=(QSslCertificate &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QSslCertificate &operator=(QSslCertificate &&other) noexcept { swap(other); return *this; }
QSslCertificate &operator=(const QSslCertificate &other);
- void swap(QSslCertificate &other) Q_DECL_NOTHROW
+ void swap(QSslCertificate &other) noexcept
{ qSwap(d, other.d); }
bool operator==(const QSslCertificate &other) const;
@@ -169,7 +167,7 @@ private:
friend class QSslCertificatePrivate;
friend class QSslSocketBackendPrivate;
- friend Q_NETWORK_EXPORT uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW;
+ friend Q_NETWORK_EXPORT uint qHash(const QSslCertificate &key, uint seed) noexcept;
};
Q_DECLARE_SHARED(QSslCertificate)
diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp
index fa87cfeaaf..806c6426e4 100644
--- a/src/network/ssl/qsslcertificate_openssl.cpp
+++ b/src/network/ssl/qsslcertificate_openssl.cpp
@@ -44,13 +44,15 @@
#include "qsslkey_p.h"
#include "qsslcertificateextension_p.h"
+#include <QtCore/qendian.h>
+
#if QT_CONFIG(thread)
#include <QtCore/private/qmutexpool_p.h>
#endif
QT_BEGIN_NAMESPACE
// forward declaration
-static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name);
+static QMultiMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name);
bool QSslCertificate::operator==(const QSslCertificate &other) const
{
@@ -63,7 +65,7 @@ bool QSslCertificate::operator==(const QSslCertificate &other) const
return false;
}
-uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QSslCertificate &key, uint seed) noexcept
{
if (X509 * const x509 = key.d->x509) {
const EVP_MD *sha1 = q_EVP_sha1();
@@ -207,10 +209,14 @@ QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlter
STACK_OF(GENERAL_NAME) *altNames = (STACK_OF(GENERAL_NAME) *)q_X509_get_ext_d2i(
d->x509, NID_subject_alt_name, nullptr, nullptr);
+ auto altName = [](ASN1_IA5STRING *ia5, int len) {
+ const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(ia5));
+ return QString::fromLatin1(altNameStr, len);
+ };
if (altNames) {
for (int i = 0; i < q_sk_GENERAL_NAME_num(altNames); ++i) {
const GENERAL_NAME *genName = q_sk_GENERAL_NAME_value(altNames, i);
- if (genName->type != GEN_DNS && genName->type != GEN_EMAIL)
+ if (genName->type != GEN_DNS && genName->type != GEN_EMAIL && genName->type != GEN_IPADD)
continue;
int len = q_ASN1_STRING_length(genName->d.ia5);
@@ -219,12 +225,32 @@ QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlter
continue;
}
- const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(genName->d.ia5));
- const QString altName = QString::fromLatin1(altNameStr, len);
- if (genName->type == GEN_DNS)
- result.insert(QSsl::DnsEntry, altName);
- else if (genName->type == GEN_EMAIL)
- result.insert(QSsl::EmailEntry, altName);
+ switch (genName->type) {
+ case GEN_DNS:
+ result.insert(QSsl::DnsEntry, altName(genName->d.ia5, len));
+ break;
+ case GEN_EMAIL:
+ result.insert(QSsl::EmailEntry, altName(genName->d.ia5, len));
+ break;
+ case GEN_IPADD: {
+ QHostAddress ipAddress;
+ switch (len) {
+ case 4: // IPv4
+ ipAddress = QHostAddress(qFromBigEndian(*reinterpret_cast<quint32 *>(genName->d.iPAddress->data)));
+ break;
+ case 16: // IPv6
+ ipAddress = QHostAddress(reinterpret_cast<quint8 *>(genName->d.iPAddress->data));
+ break;
+ default: // Unknown IP address format
+ break;
+ }
+ if (!ipAddress.isNull())
+ result.insert(QSsl::IpAddressEntry, ipAddress.toString());
+ break;
+ }
+ default:
+ break;
+ }
}
q_OPENSSL_sk_pop_free((OPENSSL_STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_GENERAL_NAME_free));
@@ -615,16 +641,16 @@ QByteArray QSslCertificatePrivate::asn1ObjectName(ASN1_OBJECT *object)
return asn1ObjectId(object);
}
-static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name)
+static QMultiMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name)
{
- QMap<QByteArray, QString> info;
+ QMultiMap<QByteArray, QString> info;
for (int i = 0; i < q_X509_NAME_entry_count(name); ++i) {
X509_NAME_ENTRY *e = q_X509_NAME_get_entry(name, i);
QByteArray name = QSslCertificatePrivate::asn1ObjectName(q_X509_NAME_ENTRY_get_object(e));
unsigned char *data = nullptr;
int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e));
- info.insertMulti(name, QString::fromUtf8((char*)data, size));
+ info.insert(name, QString::fromUtf8((char*)data, size));
#if QT_CONFIG(opensslv11)
q_CRYPTO_free(data, nullptr, 0);
#else
diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h
index dfdceab502..234cd45ceb 100644
--- a/src/network/ssl/qsslcertificate_p.h
+++ b/src/network/ssl/qsslcertificate_p.h
@@ -75,6 +75,10 @@ struct ASN1_OBJECT;
#include <windows.security.cryptography.certificates.h>
#endif
+#if QT_CONFIG(schannel)
+#include <wincrypt.h>
+#endif
+
QT_BEGIN_NAMESPACE
// forward declaration
@@ -83,7 +87,7 @@ class QSslCertificatePrivate
{
public:
QSslCertificatePrivate()
- : null(true), x509(0)
+ : null(true), x509(nullptr)
{
#ifndef QT_NO_SSL
QSslSocketPrivate::ensureInitialized();
@@ -96,14 +100,18 @@ public:
if (x509)
q_X509_free(x509);
#endif
+#if QT_CONFIG(schannel)
+ if (certificateContext)
+ CertFreeCertificateContext(certificateContext);
+#endif
}
bool null;
QByteArray versionString;
QByteArray serialNumberString;
- QMap<QByteArray, QString> issuerInfo;
- QMap<QByteArray, QString> subjectInfo;
+ QMultiMap<QByteArray, QString> issuerInfo;
+ QMultiMap<QByteArray, QString> subjectInfo;
QDateTime notValidAfter;
QDateTime notValidBefore;
@@ -143,6 +151,12 @@ public:
static QSslCertificate QSslCertificate_from_Certificate(ABI::Windows::Security::Cryptography::Certificates::ICertificate *iCertificate);
#endif
+
+#if QT_CONFIG(schannel)
+ const CERT_CONTEXT *certificateContext = nullptr;
+
+ static QSslCertificate QSslCertificate_from_CERT_CONTEXT(const CERT_CONTEXT *certificateContext);
+#endif
};
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslcertificate_qt.cpp b/src/network/ssl/qsslcertificate_qt.cpp
index dfdfd529e5..8b5035ad96 100644
--- a/src/network/ssl/qsslcertificate_qt.cpp
+++ b/src/network/ssl/qsslcertificate_qt.cpp
@@ -50,6 +50,8 @@
#include "qasn1element_p.h"
#include <QtCore/qdatastream.h>
+#include <QtCore/qendian.h>
+#include <QtNetwork/qhostaddress.h>
QT_BEGIN_NAMESPACE
@@ -62,7 +64,7 @@ bool QSslCertificate::operator==(const QSslCertificate &other) const
return d->derData == other.d->derData;
}
-uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QSslCertificate &key, uint seed) noexcept
{
// DER is the native encoding here, so toDer() is just "return d->derData":
return qHash(key.toDer(), seed);
@@ -139,7 +141,7 @@ QDateTime QSslCertificate::expiryDate() const
return d->notValidAfter;
}
-#ifndef Q_OS_WINRT // implemented in qsslcertificate_winrt.cpp
+#if !defined(Q_OS_WINRT) && !QT_CONFIG(schannel) // implemented in qsslcertificate_{winrt,schannel}.cpp
Qt::HANDLE QSslCertificate::handle() const
{
Q_UNIMPLEMENTED();
@@ -206,6 +208,10 @@ void QSslCertificatePrivate::init(const QByteArray &data, QSsl::EncodingFormat f
: certificatesFromDer(data, 1);
if (!certs.isEmpty()) {
*this = *certs.first().d;
+#if QT_CONFIG(schannel)
+ if (certificateContext)
+ certificateContext = CertDuplicateCertificateContext(certificateContext);
+#endif
}
}
}
@@ -399,10 +405,32 @@ bool QSslCertificatePrivate::parse(const QByteArray &data)
QDataStream nameStream(sanElem.value());
QAsn1Element nameElem;
while (nameElem.read(nameStream)) {
- if (nameElem.type() == QAsn1Element::Rfc822NameType) {
+ switch (nameElem.type()) {
+ case QAsn1Element::Rfc822NameType:
subjectAlternativeNames.insert(QSsl::EmailEntry, nameElem.toString());
- } else if (nameElem.type() == QAsn1Element::DnsNameType) {
+ break;
+ case QAsn1Element::DnsNameType:
subjectAlternativeNames.insert(QSsl::DnsEntry, nameElem.toString());
+ break;
+ case QAsn1Element::IpAddressType: {
+ QHostAddress ipAddress;
+ QByteArray ipAddrValue = nameElem.value();
+ switch (ipAddrValue.length()) {
+ case 4: // IPv4
+ ipAddress = QHostAddress(qFromBigEndian(*reinterpret_cast<quint32 *>(ipAddrValue.data())));
+ break;
+ case 16: // IPv6
+ ipAddress = QHostAddress(reinterpret_cast<quint8 *>(ipAddrValue.data()));
+ break;
+ default: // Unknown IP address format
+ break;
+ }
+ if (!ipAddress.isNull())
+ subjectAlternativeNames.insert(QSsl::IpAddressEntry, ipAddress.toString());
+ break;
+ }
+ default:
+ break;
}
}
}
diff --git a/src/plugins/platforms/mirclient/qmirclientcursor.h b/src/network/ssl/qsslcertificate_schannel.cpp
index c5de23b272..5ea713612a 100644
--- a/src/plugins/platforms/mirclient/qmirclientcursor.h
+++ b/src/network/ssl/qsslcertificate_schannel.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2015-2016 Canonical, Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtNetwork module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,28 +37,26 @@
**
****************************************************************************/
+#include "qsslcertificate.h"
+#include "qsslcertificate_p.h"
-#ifndef QMIRCLIENTCURSOR_H
-#define QMIRCLIENTCURSOR_H
+#include <wincrypt.h>
-#include <qpa/qplatformcursor.h>
+QT_BEGIN_NAMESPACE
-#include <QMap>
-#include <QByteArray>
+QSslCertificate QSslCertificatePrivate::QSslCertificate_from_CERT_CONTEXT(const CERT_CONTEXT *certificateContext)
+{
+ QByteArray derData = QByteArray((const char *)certificateContext->pbCertEncoded,
+ certificateContext->cbCertEncoded);
-struct MirConnection;
-struct MirSurface;
+ QSslCertificate certificate(derData, QSsl::Der);
+ certificate.d->certificateContext = CertDuplicateCertificateContext(certificateContext);
+ return certificate;
+}
-class QMirClientCursor : public QPlatformCursor
+Qt::HANDLE QSslCertificate::handle() const
{
-public:
- QMirClientCursor(MirConnection *connection);
- void changeCursor(QCursor *windowCursor, QWindow *window) override;
-private:
- void configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor);
- void applyDefaultCursorConfiguration(MirSurface *surface);
- QMap<int, QByteArray> mShapeToCursorName;
- MirConnection *mConnection;
-};
+ return Qt::HANDLE(d->certificateContext);
+}
-#endif // QMIRCLIENTCURSOR_H
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslcertificateextension.h b/src/network/ssl/qsslcertificateextension.h
index c2910e1707..7cc8a888be 100644
--- a/src/network/ssl/qsslcertificateextension.h
+++ b/src/network/ssl/qsslcertificateextension.h
@@ -55,13 +55,11 @@ class Q_NETWORK_EXPORT QSslCertificateExtension
public:
QSslCertificateExtension();
QSslCertificateExtension(const QSslCertificateExtension &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QSslCertificateExtension &operator=(QSslCertificateExtension &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QSslCertificateExtension &operator=(QSslCertificateExtension &&other) noexcept { swap(other); return *this; }
QSslCertificateExtension &operator=(const QSslCertificateExtension &other);
~QSslCertificateExtension();
- void swap(QSslCertificateExtension &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QSslCertificateExtension &other) noexcept { qSwap(d, other.d); }
QString oid() const;
QString name() const;
diff --git a/src/network/ssl/qsslcipher.h b/src/network/ssl/qsslcipher.h
index c6328e0169..6994f590ae 100644
--- a/src/network/ssl/qsslcipher.h
+++ b/src/network/ssl/qsslcipher.h
@@ -59,13 +59,11 @@ public:
explicit QSslCipher(const QString &name);
QSslCipher(const QString &name, QSsl::SslProtocol protocol);
QSslCipher(const QSslCipher &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QSslCipher &operator=(QSslCipher &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QSslCipher &operator=(QSslCipher &&other) noexcept { swap(other); return *this; }
QSslCipher &operator=(const QSslCipher &other);
~QSslCipher();
- void swap(QSslCipher &other) Q_DECL_NOTHROW
+ void swap(QSslCipher &other) noexcept
{ qSwap(d, other.d); }
bool operator==(const QSslCipher &other) const;
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 3f732b4646..7e92d3a526 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -228,7 +228,8 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->nextAllowedProtocols == other.d->nextAllowedProtocols &&
d->nextNegotiatedProtocol == other.d->nextNegotiatedProtocol &&
d->nextProtocolNegotiationStatus == other.d->nextProtocolNegotiationStatus &&
- d->dtlsCookieEnabled == other.d->dtlsCookieEnabled;
+ d->dtlsCookieEnabled == other.d->dtlsCookieEnabled &&
+ d->ocspStaplingEnabled == other.d->ocspStaplingEnabled;
}
/*!
@@ -272,7 +273,8 @@ bool QSslConfiguration::isNull() const
d->preSharedKeyIdentityHint.isNull() &&
d->nextAllowedProtocols.isEmpty() &&
d->nextNegotiatedProtocol.isNull() &&
- d->nextProtocolNegotiationStatus == QSslConfiguration::NextProtocolNegotiationNone);
+ d->nextProtocolNegotiationStatus == QSslConfiguration::NextProtocolNegotiationNone &&
+ d->ocspStaplingEnabled == false);
}
/*!
@@ -585,6 +587,8 @@ void QSslConfiguration::setPrivateKey(const QSslKey &key)
ciphers. You can revert to using the entire set by calling
setCiphers() with the list returned by QSslSocket::supportedCiphers().
+ \note This is not currently supported in the Schannel backend.
+
\sa setCiphers(), QSslSocket::supportedCiphers()
*/
QList<QSslCipher> QSslConfiguration::ciphers() const
@@ -600,6 +604,8 @@ QList<QSslCipher> QSslConfiguration::ciphers() const
Restricting the cipher suite must be done before the handshake
phase, where the session cipher is chosen.
+ \note This is not currently supported in the Schannel backend.
+
\sa ciphers(), QSslSocket::supportedCiphers()
*/
void QSslConfiguration::setCiphers(const QList<QSslCipher> &ciphers)
@@ -1094,6 +1100,37 @@ void QSslConfiguration::setDefaultDtlsConfiguration(const QSslConfiguration &con
#endif // dtls
+/*!
+ \since 5.13
+ If \a enabled is true, client QSslSocket will send a certificate status request
+ to its peer when initiating a handshake. During the handshake QSslSocket will
+ verify the server's response. This value must be set before the handshake
+ starts.
+
+ \sa ocspStaplingEnabled()
+*/
+void QSslConfiguration::setOcspStaplingEnabled(bool enabled)
+{
+#if QT_CONFIG(ocsp)
+ d->ocspStaplingEnabled = enabled;
+#else
+ if (enabled)
+ qCWarning(lcSsl, "Enabling OCSP-stapling requires the feature 'ocsp'");
+#endif // ocsp
+}
+
+/*!
+ \since 5.13
+ Returns true if OCSP stapling was enabled by setOCSPStaplingEnabled(),
+ otherwise false (which is the default value).
+
+ \sa setOcspStaplingEnabled()
+*/
+bool QSslConfiguration::ocspStaplingEnabled() const
+{
+ return d->ocspStaplingEnabled;
+}
+
/*! \internal
*/
bool QSslConfigurationPrivate::peerSessionWasShared(const QSslConfiguration &configuration) {
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index 454ac0cee3..c25c2686de 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -85,12 +85,10 @@ public:
QSslConfiguration();
QSslConfiguration(const QSslConfiguration &other);
~QSslConfiguration();
-#ifdef Q_COMPILER_RVALUE_REFS
- QSslConfiguration &operator=(QSslConfiguration &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QSslConfiguration &operator=(QSslConfiguration &&other) noexcept { swap(other); return *this; }
QSslConfiguration &operator=(const QSslConfiguration &other);
- void swap(QSslConfiguration &other) Q_DECL_NOTHROW
+ void swap(QSslConfiguration &other) noexcept
{ qSwap(d, other.d); }
bool operator==(const QSslConfiguration &other) const;
@@ -170,6 +168,9 @@ public:
static void setDefaultDtlsConfiguration(const QSslConfiguration &configuration);
#endif // dtls
+ void setOcspStaplingEnabled(bool enable);
+ bool ocspStaplingEnabled() const;
+
enum NextProtocolNegotiationStatus {
NextProtocolNegotiationNone,
NextProtocolNegotiationNegotiated,
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index 6c23165c6a..83126bb9a0 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -143,6 +143,12 @@ public:
const bool dtlsCookieEnabled = false;
#endif // dtls
+#if QT_CONFIG(ocsp)
+ bool ocspStaplingEnabled = false;
+#else
+ const bool ocspStaplingEnabled = false;
+#endif
+
// in qsslsocket.cpp:
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
index 35cca9f01a..e81e5582f4 100644
--- a/src/network/ssl/qsslcontext_openssl.cpp
+++ b/src/network/ssl/qsslcontext_openssl.cpp
@@ -243,12 +243,28 @@ QString QSslContext::errorString() const
return errorStr;
}
+#if QT_CONFIG(ocsp)
+extern "C" int qt_OCSP_status_server_callback(SSL *ssl, void *); // Defined in qsslsocket_openssl.cpp.
+#endif // ocsp
// static
void QSslContext::applyBackendConfig(QSslContext *sslContext)
{
- if (sslContext->sslConfiguration.backendConfiguration().isEmpty())
+ const QMap<QByteArray, QVariant> &conf = sslContext->sslConfiguration.backendConfiguration();
+ if (conf.isEmpty())
return;
+#if QT_CONFIG(ocsp)
+ auto ocspResponsePos = conf.find("Qt-OCSP-response");
+ if (ocspResponsePos != conf.end()) {
+ // This is our private, undocumented configuration option, existing only for
+ // the purpose of testing OCSP status responses. We don't even check this
+ // callback was set. If no - the test must fail.
+ q_SSL_CTX_set_tlsext_status_cb(sslContext->ctx, qt_OCSP_status_server_callback);
+ if (conf.size() == 1)
+ return;
+ }
+#endif // ocsp
+
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) {
QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free);
@@ -256,8 +272,10 @@ void QSslContext::applyBackendConfig(QSslContext *sslContext)
q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx);
q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE);
- const auto &backendConfig = sslContext->sslConfiguration.backendConfiguration();
- for (auto i = backendConfig.constBegin(); i != backendConfig.constEnd(); ++i) {
+ for (auto i = conf.constBegin(); i != conf.constEnd(); ++i) {
+ if (i.key() == "Qt-OCSP-response") // This never goes to SSL_CONF_cmd().
+ continue;
+
if (!i.value().canConvert(QMetaType::QByteArray)) {
sslContext->errorCode = QSslError::UnspecifiedError;
sslContext->errorStr = msgErrorSettingBackendConfig(
diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp
index c96a48dac1..db023b7331 100644
--- a/src/network/ssl/qsslcontext_openssl11.cpp
+++ b/src/network/ssl/qsslcontext_openssl11.cpp
@@ -95,6 +95,10 @@ init_context:
// SSL 2 is no longer supported, but chosen deliberately -> error
sslContext->ctx = nullptr;
unsupportedProtocol = true;
+ } else if (sslContext->sslConfiguration.protocol() == QSsl::SslV3) {
+ // SSL 3 is no longer supported, but chosen deliberately -> error
+ sslContext->ctx = nullptr;
+ unsupportedProtocol = true;
} else {
switch (sslContext->sslConfiguration.protocol()) {
case QSsl::DtlsV1_0:
@@ -151,11 +155,6 @@ init_context:
long maxVersion = anyVersion;
switch (sslContext->sslConfiguration.protocol()) {
- // The single-protocol versions first:
- case QSsl::SslV3:
- minVersion = SSL3_VERSION;
- maxVersion = SSL3_VERSION;
- break;
case QSsl::TlsV1_0:
minVersion = TLS1_VERSION;
maxVersion = TLS1_VERSION;
@@ -181,9 +180,6 @@ init_context:
// Ranges:
case QSsl::TlsV1SslV3:
case QSsl::AnyProtocol:
- minVersion = SSL3_VERSION;
- maxVersion = 0;
- break;
case QSsl::SecureProtocols:
case QSsl::TlsV1_0OrLater:
minVersion = TLS1_VERSION;
@@ -197,7 +193,6 @@ init_context:
minVersion = TLS1_2_VERSION;
maxVersion = 0;
break;
-#if QT_CONFIG(dtls)
case QSsl::DtlsV1_0:
minVersion = DTLS1_VERSION;
maxVersion = DTLS1_VERSION;
@@ -214,7 +209,6 @@ init_context:
minVersion = DTLS1_2_VERSION;
maxVersion = DTLS_MAX_VERSION;
break;
-#endif // dtls
case QSsl::TlsV1_3OrLater:
#ifdef TLS1_3_VERSION
minVersion = TLS1_3_VERSION;
@@ -227,8 +221,9 @@ init_context:
break;
#endif // TLS1_3_VERSION
case QSsl::SslV2:
- // This protocol is not supported by OpenSSL 1.1 and we handle
- // it as an error (see the code above).
+ case QSsl::SslV3:
+ // These protocols are not supported, and we handle
+ // them as an error (see the code above).
Q_UNREACHABLE();
break;
case QSsl::UnknownProtocol:
diff --git a/src/network/ssl/qsslcontext_openssl_p.h b/src/network/ssl/qsslcontext_openssl_p.h
index 48beebf134..1fa27279c7 100644
--- a/src/network/ssl/qsslcontext_openssl_p.h
+++ b/src/network/ssl/qsslcontext_openssl_p.h
@@ -89,7 +89,7 @@ public:
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
// must be public because we want to use it from an OpenSSL callback
struct NPNContext {
- NPNContext() : data(0),
+ NPNContext() : data(nullptr),
len(0),
status(QSslConfiguration::NextProtocolNegotiationNone)
{ }
diff --git a/src/network/ssl/qsslcontext_opensslpre11.cpp b/src/network/ssl/qsslcontext_opensslpre11.cpp
index 34537d1da4..956c5c32ec 100644
--- a/src/network/ssl/qsslcontext_opensslpre11.cpp
+++ b/src/network/ssl/qsslcontext_opensslpre11.cpp
@@ -115,32 +115,19 @@ init_context:
break;
#endif // dtls
case QSsl::SslV2:
-#ifndef OPENSSL_NO_SSL2
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
-#else
- // SSL 2 not supported by the system, but chosen deliberately -> error
- sslContext->ctx = 0;
- unsupportedProtocol = true;
-#endif
- break;
case QSsl::SslV3:
-#ifndef OPENSSL_NO_SSL3_METHOD
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
-#else
- // SSL 3 not supported by the system, but chosen deliberately -> error
+ // We don't support SSLv2 / SSLv3.
sslContext->ctx = 0;
unsupportedProtocol = true;
-#endif
break;
case QSsl::SecureProtocols:
// SSLv2 and SSLv3 will be disabled by SSL options
// But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32.
- case QSsl::TlsV1SslV3:
- // SSLv2 will will be disabled by SSL options
case QSsl::AnyProtocol:
default:
sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
break;
+ case QSsl::TlsV1SslV3:
case QSsl::TlsV1_0:
sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method());
break;
@@ -212,12 +199,9 @@ init_context:
long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
q_SSL_CTX_set_options(sslContext->ctx, options);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
// Tell OpenSSL to release memory early
// http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
- if (q_SSLeay() >= 0x10000000L)
- q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
-#endif
+ q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
// Initialize ciphers
QByteArray cipherString;
diff --git a/src/network/ssl/qssldiffiehellmanparameters.cpp b/src/network/ssl/qssldiffiehellmanparameters.cpp
index 7fbcff2861..7807afaa30 100644
--- a/src/network/ssl/qssldiffiehellmanparameters.cpp
+++ b/src/network/ssl/qssldiffiehellmanparameters.cpp
@@ -136,7 +136,7 @@ QSslDiffieHellmanParameters QSslDiffieHellmanParameters::fromEncoded(const QByte
to check whether the Diffie-Hellman parameters were valid
and loaded correctly.
- In particular, if \a device is \c nullptr or not open for reading, an invalid
+ In particular, if \a device is \nullptr or not open for reading, an invalid
object will be returned.
\sa isValid()
@@ -213,7 +213,7 @@ QSslDiffieHellmanParameters &QSslDiffieHellmanParameters::operator=(const QSslDi
Setting an empty QSslDiffieHellmanParameters instance on a QSslSocket-based
server will disable Diffie-Hellman key exchange.
*/
-bool QSslDiffieHellmanParameters::isEmpty() const Q_DECL_NOTHROW
+bool QSslDiffieHellmanParameters::isEmpty() const noexcept
{
return d->derData.isNull() && d->error == QSslDiffieHellmanParameters::NoError;
}
@@ -229,7 +229,7 @@ bool QSslDiffieHellmanParameters::isEmpty() const Q_DECL_NOTHROW
\sa error()
*/
-bool QSslDiffieHellmanParameters::isValid() const Q_DECL_NOTHROW
+bool QSslDiffieHellmanParameters::isValid() const noexcept
{
return d->error == QSslDiffieHellmanParameters::NoError;
}
@@ -253,7 +253,7 @@ bool QSslDiffieHellmanParameters::isValid() const Q_DECL_NOTHROW
Returns the error that caused the QSslDiffieHellmanParameters object
to be invalid.
*/
-QSslDiffieHellmanParameters::Error QSslDiffieHellmanParameters::error() const Q_DECL_NOTHROW
+QSslDiffieHellmanParameters::Error QSslDiffieHellmanParameters::error() const noexcept
{
return d->error;
}
@@ -262,7 +262,7 @@ QSslDiffieHellmanParameters::Error QSslDiffieHellmanParameters::error() const Q_
Returns a human-readable description of the error that caused the
QSslDiffieHellmanParameters object to be invalid.
*/
-QString QSslDiffieHellmanParameters::errorString() const Q_DECL_NOTHROW
+QString QSslDiffieHellmanParameters::errorString() const noexcept
{
switch (d->error) {
case QSslDiffieHellmanParameters::NoError:
@@ -283,7 +283,7 @@ QString QSslDiffieHellmanParameters::errorString() const Q_DECL_NOTHROW
Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
*/
-bool operator==(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) Q_DECL_NOTHROW
+bool operator==(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) noexcept
{
return lhs.d->derData == rhs.d->derData;
}
@@ -316,7 +316,7 @@ QDebug operator<<(QDebug debug, const QSslDiffieHellmanParameters &dhparam)
Returns an hash value for \a dhparam, using \a seed to seed
the calculation.
*/
-uint qHash(const QSslDiffieHellmanParameters &dhparam, uint seed) Q_DECL_NOTHROW
+uint qHash(const QSslDiffieHellmanParameters &dhparam, uint seed) noexcept
{
return qHash(dhparam.d->derData, seed);
}
diff --git a/src/network/ssl/qssldiffiehellmanparameters.h b/src/network/ssl/qssldiffiehellmanparameters.h
index 497d2bebfb..f62a3b8f44 100644
--- a/src/network/ssl/qssldiffiehellmanparameters.h
+++ b/src/network/ssl/qssldiffiehellmanparameters.h
@@ -56,16 +56,16 @@ class QSslDiffieHellmanParametersPrivate;
class QSslDiffieHellmanParameters;
// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
-Q_NETWORK_EXPORT uint qHash(const QSslDiffieHellmanParameters &dhparam, uint seed = 0) Q_DECL_NOTHROW;
+Q_NETWORK_EXPORT uint qHash(const QSslDiffieHellmanParameters &dhparam, uint seed = 0) noexcept;
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QSslDiffieHellmanParameters &dhparams);
#endif
-Q_NETWORK_EXPORT bool operator==(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) Q_DECL_NOTHROW;
+Q_NETWORK_EXPORT bool operator==(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) noexcept;
-inline bool operator!=(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) Q_DECL_NOTHROW
+inline bool operator!=(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) noexcept
{
return !operator==(lhs, rhs);
}
@@ -83,30 +83,30 @@ public:
Q_NETWORK_EXPORT QSslDiffieHellmanParameters();
Q_NETWORK_EXPORT QSslDiffieHellmanParameters(const QSslDiffieHellmanParameters &other);
- QSslDiffieHellmanParameters(QSslDiffieHellmanParameters &&other) Q_DECL_NOTHROW : d(other.d) { other.d = nullptr; }
+ QSslDiffieHellmanParameters(QSslDiffieHellmanParameters &&other) noexcept : d(other.d) { other.d = nullptr; }
Q_NETWORK_EXPORT ~QSslDiffieHellmanParameters();
Q_NETWORK_EXPORT QSslDiffieHellmanParameters &operator=(const QSslDiffieHellmanParameters &other);
- QSslDiffieHellmanParameters &operator=(QSslDiffieHellmanParameters &&other) Q_DECL_NOTHROW { swap(other); return *this; }
+ QSslDiffieHellmanParameters &operator=(QSslDiffieHellmanParameters &&other) noexcept { swap(other); return *this; }
- void swap(QSslDiffieHellmanParameters &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QSslDiffieHellmanParameters &other) noexcept { qSwap(d, other.d); }
Q_NETWORK_EXPORT static QSslDiffieHellmanParameters fromEncoded(const QByteArray &encoded, QSsl::EncodingFormat format = QSsl::Pem);
Q_NETWORK_EXPORT static QSslDiffieHellmanParameters fromEncoded(QIODevice *device, QSsl::EncodingFormat format = QSsl::Pem);
- Q_NETWORK_EXPORT bool isEmpty() const Q_DECL_NOTHROW;
- Q_NETWORK_EXPORT bool isValid() const Q_DECL_NOTHROW;
- Q_NETWORK_EXPORT Error error() const Q_DECL_NOTHROW;
- Q_NETWORK_EXPORT QString errorString() const Q_DECL_NOTHROW;
+ Q_NETWORK_EXPORT bool isEmpty() const noexcept;
+ Q_NETWORK_EXPORT bool isValid() const noexcept;
+ Q_NETWORK_EXPORT Error error() const noexcept;
+ Q_NETWORK_EXPORT QString errorString() const noexcept;
private:
QSslDiffieHellmanParametersPrivate *d;
friend class QSslContext;
- friend Q_NETWORK_EXPORT bool operator==(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) Q_DECL_NOTHROW;
+ friend Q_NETWORK_EXPORT bool operator==(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) noexcept;
#ifndef QT_NO_DEBUG_STREAM
friend Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QSslDiffieHellmanParameters &dhparam);
#endif
- friend Q_NETWORK_EXPORT uint qHash(const QSslDiffieHellmanParameters &dhparam, uint seed) Q_DECL_NOTHROW;
+ friend Q_NETWORK_EXPORT uint qHash(const QSslDiffieHellmanParameters &dhparam, uint seed) noexcept;
};
Q_DECLARE_SHARED(QSslDiffieHellmanParameters)
diff --git a/src/network/ssl/qsslellipticcurve.cpp b/src/network/ssl/qsslellipticcurve.cpp
index 88baa1ff6c..5608d32fa7 100644
--- a/src/network/ssl/qsslellipticcurve.cpp
+++ b/src/network/ssl/qsslellipticcurve.cpp
@@ -64,6 +64,8 @@ QT_BEGIN_NAMESPACE
QSslEllipticCurve instances can be compared for equality and can be used as keys
in QHash and QSet. They cannot be used as key in a QMap.
+
+ \note This class is currently only supported in OpenSSL.
*/
/*!
diff --git a/src/network/ssl/qsslellipticcurve.h b/src/network/ssl/qsslellipticcurve.h
index 57dda19bad..28de3a03b4 100644
--- a/src/network/ssl/qsslellipticcurve.h
+++ b/src/network/ssl/qsslellipticcurve.h
@@ -52,11 +52,11 @@ QT_BEGIN_NAMESPACE
class QSslEllipticCurve;
// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
-Q_DECL_CONSTEXPR uint qHash(QSslEllipticCurve curve, uint seed = 0) Q_DECL_NOTHROW;
+Q_DECL_CONSTEXPR uint qHash(QSslEllipticCurve curve, uint seed = 0) noexcept;
class QSslEllipticCurve {
public:
- Q_DECL_CONSTEXPR QSslEllipticCurve() Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR QSslEllipticCurve() noexcept
: id(0)
{
}
@@ -67,18 +67,18 @@ public:
Q_REQUIRED_RESULT Q_NETWORK_EXPORT QString shortName() const;
Q_REQUIRED_RESULT Q_NETWORK_EXPORT QString longName() const;
- Q_DECL_CONSTEXPR bool isValid() const Q_DECL_NOTHROW
+ Q_DECL_CONSTEXPR bool isValid() const noexcept
{
return id != 0;
}
- Q_NETWORK_EXPORT bool isTlsNamedCurve() const Q_DECL_NOTHROW;
+ Q_NETWORK_EXPORT bool isTlsNamedCurve() const noexcept;
private:
int id;
- friend Q_DECL_CONSTEXPR bool operator==(QSslEllipticCurve lhs, QSslEllipticCurve rhs) Q_DECL_NOTHROW;
- friend Q_DECL_CONSTEXPR uint qHash(QSslEllipticCurve curve, uint seed) Q_DECL_NOTHROW;
+ friend Q_DECL_CONSTEXPR bool operator==(QSslEllipticCurve lhs, QSslEllipticCurve rhs) noexcept;
+ friend Q_DECL_CONSTEXPR uint qHash(QSslEllipticCurve curve, uint seed) noexcept;
friend class QSslContext;
friend class QSslSocketPrivate;
@@ -87,13 +87,13 @@ private:
Q_DECLARE_TYPEINFO(QSslEllipticCurve, Q_PRIMITIVE_TYPE);
-Q_DECL_CONSTEXPR inline uint qHash(QSslEllipticCurve curve, uint seed) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline uint qHash(QSslEllipticCurve curve, uint seed) noexcept
{ return qHash(curve.id, seed); }
-Q_DECL_CONSTEXPR inline bool operator==(QSslEllipticCurve lhs, QSslEllipticCurve rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator==(QSslEllipticCurve lhs, QSslEllipticCurve rhs) noexcept
{ return lhs.id == rhs.id; }
-Q_DECL_CONSTEXPR inline bool operator!=(QSslEllipticCurve lhs, QSslEllipticCurve rhs) Q_DECL_NOTHROW
+Q_DECL_CONSTEXPR inline bool operator!=(QSslEllipticCurve lhs, QSslEllipticCurve rhs) noexcept
{ return !operator==(lhs, rhs); }
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/network/ssl/qsslellipticcurve_dummy.cpp b/src/network/ssl/qsslellipticcurve_dummy.cpp
index 93e081b9e0..1313e06875 100644
--- a/src/network/ssl/qsslellipticcurve_dummy.cpp
+++ b/src/network/ssl/qsslellipticcurve_dummy.cpp
@@ -63,7 +63,7 @@ QSslEllipticCurve QSslEllipticCurve::fromLongName(const QString &name)
return QSslEllipticCurve();
}
-bool QSslEllipticCurve::isTlsNamedCurve() const Q_DECL_NOTHROW
+bool QSslEllipticCurve::isTlsNamedCurve() const noexcept
{
return false;
}
diff --git a/src/network/ssl/qsslellipticcurve_openssl.cpp b/src/network/ssl/qsslellipticcurve_openssl.cpp
index 8cd14837f0..b5e38ada53 100644
--- a/src/network/ssl/qsslellipticcurve_openssl.cpp
+++ b/src/network/ssl/qsslellipticcurve_openssl.cpp
@@ -170,7 +170,7 @@ static const int tlsNamedCurveNIDs[] = {
static const size_t tlsNamedCurveNIDCount = sizeof(tlsNamedCurveNIDs) / sizeof(tlsNamedCurveNIDs[0]);
-bool QSslEllipticCurve::isTlsNamedCurve() const Q_DECL_NOTHROW
+bool QSslEllipticCurve::isTlsNamedCurve() const noexcept
{
const int * const tlsNamedCurveNIDsEnd = tlsNamedCurveNIDs + tlsNamedCurveNIDCount;
return std::find(tlsNamedCurveNIDs, tlsNamedCurveNIDsEnd, id) != tlsNamedCurveNIDsEnd;
diff --git a/src/network/ssl/qsslerror.cpp b/src/network/ssl/qsslerror.cpp
index 3f79d1a037..cdc018a508 100644
--- a/src/network/ssl/qsslerror.cpp
+++ b/src/network/ssl/qsslerror.cpp
@@ -86,6 +86,19 @@
\value UnspecifiedError
\value NoSslSupport
\value CertificateBlacklisted
+ \value CertificateStatusUnknown
+ \value OcspNoResponseFound
+ \value OcspMalformedRequest
+ \value OcspMalformedResponse
+ \value OcspInternalError
+ \value OcspTryLater
+ \value OcspSigRequred
+ \value OcspUnauthorized
+ \value OcspResponseCannotBeTrusted
+ \value OcspResponseCertIdUnknown
+ \value OcspResponseExpired
+ \value OcspStatusUnknown
+
\sa QSslError::errorString()
*/
@@ -292,6 +305,39 @@ QString QSslError::errorString() const
case CertificateBlacklisted:
errStr = QSslSocket::tr("The peer certificate is blacklisted");
break;
+ case OcspNoResponseFound:
+ errStr = QSslSocket::tr("No OCSP status response found");
+ break;
+ case OcspMalformedRequest:
+ errStr = QSslSocket::tr("The OCSP status request had invalid syntax");
+ break;
+ case OcspMalformedResponse:
+ errStr = QSslSocket::tr("OCSP response contains an unexpected number of SingleResponse structures");
+ break;
+ case OcspInternalError:
+ errStr = QSslSocket::tr("OCSP responder reached an inconsistent internal state");
+ break;
+ case OcspTryLater:
+ errStr = QSslSocket::tr("OCSP responder was unable to return a status for the requested certificate");
+ break;
+ case OcspSigRequred:
+ errStr = QSslSocket::tr("The server requires the client to sign the OCSP request in order to construct a response");
+ break;
+ case OcspUnauthorized:
+ errStr = QSslSocket::tr("The client is not authorized to request OCSP status from this server");
+ break;
+ case OcspResponseCannotBeTrusted:
+ errStr = QSslSocket::tr("OCSP responder's identity cannot be verified");
+ break;
+ case OcspResponseCertIdUnknown:
+ errStr = QSslSocket::tr("The identity of a certificate in an OCSP response cannot be established");
+ break;
+ case OcspResponseExpired:
+ errStr = QSslSocket::tr("The certificate status response has expired");
+ break;
+ case OcspStatusUnknown:
+ errStr = QSslSocket::tr("The certificate's status is unknown");
+ break;
default:
errStr = QSslSocket::tr("Unknown error");
break;
@@ -316,11 +362,11 @@ QSslCertificate QSslError::certificate() const
\since 5.4
\relates QHash
*/
-uint qHash(const QSslError &key, uint seed) Q_DECL_NOTHROW
+uint qHash(const QSslError &key, uint seed) noexcept
{
- // 2x boost::hash_combine inlined:
- seed ^= qHash(key.error()) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
- seed ^= qHash(key.certificate()) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, key.error());
+ seed = hash(seed, key.certificate());
return seed;
}
diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h
index d7c959423d..c4a0d52193 100644
--- a/src/network/ssl/qsslerror.h
+++ b/src/network/ssl/qsslerror.h
@@ -80,6 +80,18 @@ public:
HostNameMismatch,
NoSslSupport,
CertificateBlacklisted,
+ CertificateStatusUnknown,
+ OcspNoResponseFound,
+ OcspMalformedRequest,
+ OcspMalformedResponse,
+ OcspInternalError,
+ OcspTryLater,
+ OcspSigRequred,
+ OcspUnauthorized,
+ OcspResponseCannotBeTrusted,
+ OcspResponseCertIdUnknown,
+ OcspResponseExpired,
+ OcspStatusUnknown,
UnspecifiedError = -1
};
@@ -91,13 +103,11 @@ public:
QSslError(const QSslError &other);
- void swap(QSslError &other) Q_DECL_NOTHROW
+ void swap(QSslError &other) noexcept
{ qSwap(d, other.d); }
~QSslError();
-#ifdef Q_COMPILER_RVALUE_REFS
- QSslError &operator=(QSslError &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QSslError &operator=(QSslError &&other) noexcept { swap(other); return *this; }
QSslError &operator=(const QSslError &other);
bool operator==(const QSslError &other) const;
inline bool operator!=(const QSslError &other) const
@@ -112,7 +122,7 @@ private:
};
Q_DECLARE_SHARED(QSslError)
-Q_NETWORK_EXPORT uint qHash(const QSslError &key, uint seed = 0) Q_DECL_NOTHROW;
+Q_NETWORK_EXPORT uint qHash(const QSslError &key, uint seed = 0) noexcept;
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h
index 6de02b1e44..74be406539 100644
--- a/src/network/ssl/qsslkey.h
+++ b/src/network/ssl/qsslkey.h
@@ -71,13 +71,12 @@ public:
const QByteArray &passPhrase = QByteArray());
explicit QSslKey(Qt::HANDLE handle, QSsl::KeyType type = QSsl::PrivateKey);
QSslKey(const QSslKey &other);
-#ifdef Q_COMPILER_RVALUE_REFS
- QSslKey &operator=(QSslKey &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QSslKey(QSslKey &&other) noexcept;
+ QSslKey &operator=(QSslKey &&other) noexcept;
QSslKey &operator=(const QSslKey &other);
~QSslKey();
- void swap(QSslKey &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QSslKey &other) noexcept { qSwap(d, other.d); }
bool isNull() const;
void clear();
diff --git a/src/network/ssl/qsslkey_mac.cpp b/src/network/ssl/qsslkey_mac.cpp
index d460cbfdab..814fe1c4bc 100644
--- a/src/network/ssl/qsslkey_mac.cpp
+++ b/src/network/ssl/qsslkey_mac.cpp
@@ -42,7 +42,9 @@
#include <CommonCrypto/CommonCrypto.h>
-QT_USE_NAMESPACE
+#include <cstddef>
+
+QT_BEGIN_NAMESPACE
static QByteArray wrapCCCrypt(CCOperation ccOp,
QSslKeyPrivate::Cipher cipher,
@@ -64,17 +66,23 @@ static QByteArray wrapCCCrypt(CCOperation ccOp,
blockSize = kCCBlockSizeRC2;
ccAlgorithm = kCCAlgorithmRC2;
break;
- };
+ case QSslKeyPrivate::Aes128Cbc:
+ case QSslKeyPrivate::Aes192Cbc:
+ case QSslKeyPrivate::Aes256Cbc:
+ blockSize = kCCBlockSizeAES128;
+ ccAlgorithm = kCCAlgorithmAES;
+ break;
+ }
size_t plainLength = 0;
QByteArray plain(data.size() + blockSize, 0);
CCCryptorStatus status = CCCrypt(
ccOp, ccAlgorithm, kCCOptionPKCS7Padding,
- key.constData(), key.size(),
+ key.constData(), std::size_t(key.size()),
iv.constData(),
- data.constData(), data.size(),
- plain.data(), plain.size(), &plainLength);
+ data.constData(), std::size_t(data.size()),
+ plain.data(), std::size_t(plain.size()), &plainLength);
if (status == kCCSuccess)
- return plain.left(plainLength);
+ return plain.left(int(plainLength));
return QByteArray();
}
@@ -87,3 +95,5 @@ QByteArray QSslKeyPrivate::encrypt(Cipher cipher, const QByteArray &data, const
{
return wrapCCCrypt(kCCEncrypt, cipher, data, key, iv);
}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp
index 9a43e67772..888058df22 100644
--- a/src/network/ssl/qsslkey_openssl.cpp
+++ b/src/network/ssl/qsslkey_openssl.cpp
@@ -69,6 +69,11 @@ void QSslKeyPrivate::clear(bool deep)
q_DSA_free(dsa);
dsa = nullptr;
}
+ if (algorithm == QSsl::Dh && dh) {
+ if (deep)
+ q_DH_free(dh);
+ dh = nullptr;
+ }
#ifndef OPENSSL_NO_EC
if (algorithm == QSsl::Ec && ec) {
if (deep)
@@ -105,6 +110,12 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey)
type = QSsl::PrivateKey;
dsa = q_EVP_PKEY_get1_DSA(pkey);
return true;
+ } else if (keyType == EVP_PKEY_DH) {
+ isNull = false;
+ algorithm = QSsl::Dh;
+ type = QSsl::PrivateKey;
+ dh = q_EVP_PKEY_get1_DH(pkey);
+ return true;
}
#ifndef OPENSSL_NO_EC
else if (keyType == EVP_PKEY_EC) {
@@ -160,6 +171,15 @@ void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhra
: q_PEM_read_bio_DSAPrivateKey(bio, &dsa, nullptr, phrase);
if (dsa && dsa == result)
isNull = false;
+ } else if (algorithm == QSsl::Dh) {
+ EVP_PKEY *result = (type == QSsl::PublicKey)
+ ? q_PEM_read_bio_PUBKEY(bio, nullptr, nullptr, phrase)
+ : q_PEM_read_bio_PrivateKey(bio, nullptr, nullptr, phrase);
+ if (result)
+ dh = q_EVP_PKEY_get1_DH(result);
+ if (dh)
+ isNull = false;
+ q_EVP_PKEY_free(result);
#ifndef OPENSSL_NO_EC
} else if (algorithm == QSsl::Ec) {
EC_KEY *result = (type == QSsl::PublicKey)
@@ -181,6 +201,7 @@ int QSslKeyPrivate::length() const
switch (algorithm) {
case QSsl::Rsa: return q_RSA_bits(rsa);
case QSsl::Dsa: return q_DSA_bits(dsa);
+ case QSsl::Dh: return q_DH_bits(dh);
#ifndef OPENSSL_NO_EC
case QSsl::Ec: return q_EC_GROUP_get_degree(q_EC_KEY_get0_group(ec));
#endif
@@ -215,7 +236,7 @@ QByteArray QSslKeyPrivate::toPem(const QByteArray &passPhrase) const
fail = true;
} else {
if (!q_PEM_write_bio_RSAPrivateKey(
- bio, rsa, cipher, const_cast<uchar *>((const uchar *)passPhrase.data()),
+ bio, rsa, cipher, (uchar *)passPhrase.data(),
passPhrase.size(), nullptr, nullptr)) {
fail = true;
}
@@ -226,20 +247,33 @@ QByteArray QSslKeyPrivate::toPem(const QByteArray &passPhrase) const
fail = true;
} else {
if (!q_PEM_write_bio_DSAPrivateKey(
- bio, dsa, cipher, const_cast<uchar *>((const uchar *)passPhrase.data()),
+ bio, dsa, cipher, (uchar *)passPhrase.data(),
passPhrase.size(), nullptr, nullptr)) {
fail = true;
}
}
+ } else if (algorithm == QSsl::Dh) {
+ EVP_PKEY *result = q_EVP_PKEY_new();
+ if (!result || !q_EVP_PKEY_set1_DH(result, dh)) {
+ fail = true;
+ } else if (type == QSsl::PublicKey) {
+ if (!q_PEM_write_bio_PUBKEY(bio, result))
+ fail = true;
+ } else if (!q_PEM_write_bio_PrivateKey(
+ bio, result, cipher, (uchar *)passPhrase.data(),
+ passPhrase.size(), nullptr, nullptr)) {
+ fail = true;
+ }
+ q_EVP_PKEY_free(result);
#ifndef OPENSSL_NO_EC
} else if (algorithm == QSsl::Ec) {
if (type == QSsl::PublicKey) {
if (!q_PEM_write_bio_EC_PUBKEY(bio, ec))
fail = true;
} else {
- if (!q_PEM_write_bio_ECPrivateKey(bio, ec, cipher,
- const_cast<uchar *>((const uchar *)passPhrase.data()),
- passPhrase.size(), nullptr, nullptr)) {
+ if (!q_PEM_write_bio_ECPrivateKey(
+ bio, ec, cipher, (uchar *)passPhrase.data(),
+ passPhrase.size(), nullptr, nullptr)) {
fail = true;
}
}
@@ -267,6 +301,8 @@ Qt::HANDLE QSslKeyPrivate::handle() const
return Qt::HANDLE(rsa);
case QSsl::Dsa:
return Qt::HANDLE(dsa);
+ case QSsl::Dh:
+ return Qt::HANDLE(dh);
#ifndef OPENSSL_NO_EC
case QSsl::Ec:
return Qt::HANDLE(ec);
@@ -297,6 +333,15 @@ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data,
type = q_EVP_rc2_cbc();
#endif
break;
+ case QSslKeyPrivate::Aes128Cbc:
+ type = q_EVP_aes_128_cbc();
+ break;
+ case QSslKeyPrivate::Aes192Cbc:
+ type = q_EVP_aes_192_cbc();
+ break;
+ case QSslKeyPrivate::Aes256Cbc:
+ type = q_EVP_aes_256_cbc();
+ break;
}
if (type == nullptr)
diff --git a/src/network/ssl/qsslkey_p.cpp b/src/network/ssl/qsslkey_p.cpp
index 28e3e2efd8..b0d6c729f9 100644
--- a/src/network/ssl/qsslkey_p.cpp
+++ b/src/network/ssl/qsslkey_p.cpp
@@ -116,6 +116,8 @@ QByteArray QSslKeyPrivate::pemHeader() const
return QByteArrayLiteral("-----BEGIN DSA PRIVATE KEY-----");
else if (algorithm == QSsl::Ec)
return QByteArrayLiteral("-----BEGIN EC PRIVATE KEY-----");
+ else if (algorithm == QSsl::Dh)
+ return QByteArrayLiteral("-----BEGIN PRIVATE KEY-----");
Q_UNREACHABLE();
return QByteArray();
@@ -141,6 +143,8 @@ QByteArray QSslKeyPrivate::pemFooter() const
return QByteArrayLiteral("-----END DSA PRIVATE KEY-----");
else if (algorithm == QSsl::Ec)
return QByteArrayLiteral("-----END EC PRIVATE KEY-----");
+ else if (algorithm == QSsl::Dh)
+ return QByteArrayLiteral("-----END PRIVATE KEY-----");
Q_UNREACHABLE();
return QByteArray();
@@ -381,6 +385,24 @@ QSslKey::QSslKey(const QSslKey &other) : d(other.d)
{
}
+QSslKey::QSslKey(QSslKey &&other) noexcept
+ : d(nullptr)
+{
+ qSwap(d, other.d);
+}
+
+QSslKey &QSslKey::operator=(QSslKey &&other) noexcept
+{
+ if (this == &other)
+ return *this;
+
+ // If no one else is referencing the key data we want to make sure
+ // before we swap the d-ptr that it is not left in memory.
+ d.reset();
+ qSwap(d, other.d);
+ return *this;
+}
+
/*!
Destroys the QSslKey object.
*/
@@ -486,8 +508,8 @@ QByteArray QSslKey::toPem(const QByteArray &passPhrase) const
}
/*!
- Returns a pointer to the native key handle, if it is available;
- otherwise a null pointer is returned.
+ Returns a pointer to the native key handle, if there is
+ one, else \nullptr.
You can use this handle together with the native API to access
extended information about the key.
@@ -535,7 +557,9 @@ QDebug operator<<(QDebug debug, const QSslKey &key)
debug << "QSslKey("
<< (key.type() == QSsl::PublicKey ? "PublicKey" : "PrivateKey")
<< ", " << (key.algorithm() == QSsl::Opaque ? "OPAQUE" :
- (key.algorithm() == QSsl::Rsa ? "RSA" : ((key.algorithm() == QSsl::Dsa) ? "DSA" : "EC")))
+ (key.algorithm() == QSsl::Rsa ? "RSA" :
+ (key.algorithm() == QSsl::Dsa ? "DSA" :
+ (key.algorithm() == QSsl::Dh ? "DH" : "EC"))))
<< ", " << key.length()
<< ')';
return debug;
diff --git a/src/network/ssl/qsslkey_p.h b/src/network/ssl/qsslkey_p.h
index 7ae2cc740b..dd1a31b0e5 100644
--- a/src/network/ssl/qsslkey_p.h
+++ b/src/network/ssl/qsslkey_p.h
@@ -68,7 +68,7 @@ class QSslKeyPrivate
public:
inline QSslKeyPrivate()
: algorithm(QSsl::Opaque)
- , opaque(0)
+ , opaque(nullptr)
{
clear(false);
}
@@ -105,7 +105,10 @@ public:
enum Cipher {
DesCbc,
DesEde3Cbc,
- Rc2Cbc
+ Rc2Cbc,
+ Aes128Cbc,
+ Aes192Cbc,
+ Aes256Cbc
};
Q_AUTOTEST_EXPORT static QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv);
@@ -116,6 +119,7 @@ public:
EVP_PKEY *opaque;
RSA *rsa;
DSA *dsa;
+ DH *dh;
#ifndef OPENSSL_NO_EC
EC_KEY *ec;
#endif
@@ -129,7 +133,7 @@ public:
QAtomicInt ref;
private:
- Q_DISABLE_COPY(QSslKeyPrivate)
+ Q_DISABLE_COPY_MOVE(QSslKeyPrivate)
};
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslkey_qt.cpp b/src/network/ssl/qsslkey_qt.cpp
index a13275f3bb..43969c3d28 100644
--- a/src/network/ssl/qsslkey_qt.cpp
+++ b/src/network/ssl/qsslkey_qt.cpp
@@ -48,6 +48,8 @@
#include <QtNetwork/qpassworddigestor.h>
+#include <cstring>
+
QT_USE_NAMESPACE
static const quint8 bits_table[256] = {
@@ -124,6 +126,37 @@ static int numberOfBits(const QByteArray &modulus)
return bits;
}
+static QByteArray deriveAesKey(QSslKeyPrivate::Cipher cipher, const QByteArray &passPhrase, const QByteArray &iv)
+{
+ // This is somewhat simplified and shortened version of what OpenSSL does.
+ // See, for example, EVP_BytesToKey for the "algorithm" itself and elsewhere
+ // in their code for what they pass as arguments to EVP_BytesToKey when
+ // deriving encryption keys (when reading/writing pems files with encrypted
+ // keys).
+
+ Q_ASSERT(iv.size() >= 8);
+
+ QCryptographicHash hash(QCryptographicHash::Md5);
+
+ QByteArray data(passPhrase);
+ data.append(iv.data(), 8); // AKA PKCS5_SALT_LEN in OpenSSL.
+
+ hash.addData(data);
+
+ if (cipher == QSslKeyPrivate::Aes128Cbc)
+ return hash.result();
+
+ QByteArray key(hash.result());
+ hash.reset();
+ hash.addData(key);
+ hash.addData(data);
+
+ if (cipher == QSslKeyPrivate::Aes192Cbc)
+ return key.append(hash.result().constData(), 8);
+
+ return key.append(hash.result());
+}
+
static QByteArray deriveKey(QSslKeyPrivate::Cipher cipher, const QByteArray &passPhrase, const QByteArray &iv)
{
QByteArray key;
@@ -145,14 +178,19 @@ static QByteArray deriveKey(QSslKeyPrivate::Cipher cipher, const QByteArray &pas
case QSslKeyPrivate::Rc2Cbc:
key = hash.result();
break;
+ case QSslKeyPrivate::Aes128Cbc:
+ case QSslKeyPrivate::Aes192Cbc:
+ case QSslKeyPrivate::Aes256Cbc:
+ return deriveAesKey(cipher, passPhrase, iv);
}
return key;
}
void QSslKeyPrivate::clear(bool deep)
{
- Q_UNUSED(deep);
isNull = true;
+ if (deep)
+ std::memset(derData.data(), 0, derData.size());
derData.clear();
keyLength = -1;
}
@@ -165,6 +203,7 @@ static int extractPkcs8KeyLength(const QVector<QAsn1Element> &items, QSslKeyPriv
switch (algorithm){
case QSsl::Rsa: return "RSA";
case QSsl::Dsa: return "DSA";
+ case QSsl::Dh: return "DH";
case QSsl::Ec: return "EC";
case QSsl::Opaque: return "Opaque";
}
@@ -217,6 +256,21 @@ static int extractPkcs8KeyLength(const QVector<QAsn1Element> &items, QSslKeyPriv
if (dsaInfo.size() != 3 || dsaInfo[0].type() != QAsn1Element::IntegerType)
return -1;
keyLength = numberOfBits(dsaInfo[0].value());
+ } else if (value == DH_ENCRYPTION_OID) {
+ if (Q_UNLIKELY(that->algorithm != QSsl::Dh)) {
+ // As above for RSA.
+ qWarning() << "QSslKey: Found DH when asked to use" << getName(that->algorithm)
+ << "\nLoading will fail.";
+ return -1;
+ }
+ // DH's structure is documented here:
+ // https://www.cryptsoft.com/pkcs11doc/STANDARD/v201-95.pdf in section 11.9.
+ if (pkcs8Info[1].type() != QAsn1Element::SequenceType)
+ return -1;
+ const QVector<QAsn1Element> dhInfo = pkcs8Info[1].toVector();
+ if (dhInfo.size() < 2 || dhInfo.size() > 3 || dhInfo[0].type() != QAsn1Element::IntegerType)
+ return -1;
+ keyLength = numberOfBits(dhInfo[0].value());
} else {
// in case of unexpected formats:
qWarning() << "QSslKey: Unsupported PKCS#8 key algorithm:" << value
@@ -268,6 +322,16 @@ void QSslKeyPrivate::decodeDer(const QByteArray &der, const QByteArray &passPhra
if (params.isEmpty() || params[0].type() != QAsn1Element::IntegerType)
return;
keyLength = numberOfBits(params[0].value());
+ } else if (algorithm == QSsl::Dh) {
+ if (infoItems[0].toObjectId() != DH_ENCRYPTION_OID)
+ return;
+ if (infoItems[1].type() != QAsn1Element::SequenceType)
+ return;
+ // key params
+ const QVector<QAsn1Element> params = infoItems[1].toVector();
+ if (params.isEmpty() || params[0].type() != QAsn1Element::IntegerType)
+ return;
+ keyLength = numberOfBits(params[0].value());
} else if (algorithm == QSsl::Ec) {
if (infoItems[0].toObjectId() != EC_ENCRYPTION_OID)
return;
@@ -307,6 +371,12 @@ void QSslKeyPrivate::decodeDer(const QByteArray &der, const QByteArray &passPhra
if (items.size() != 6 || items[1].type() != QAsn1Element::IntegerType)
return;
keyLength = numberOfBits(items[1].value());
+ } else if (algorithm == QSsl::Dh) {
+ if (versionHex != "00")
+ return;
+ if (items.size() < 5 || items.size() > 6 || items[1].type() != QAsn1Element::IntegerType)
+ return;
+ keyLength = numberOfBits(items[1].value());
} else if (algorithm == QSsl::Ec) {
if (versionHex != "01")
return;
@@ -346,6 +416,12 @@ void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhra
cipher = DesEde3Cbc;
} else if (dekInfo.first() == "RC2-CBC") {
cipher = Rc2Cbc;
+ } else if (dekInfo.first() == "AES-128-CBC") {
+ cipher = Aes128Cbc;
+ } else if (dekInfo.first() == "AES-192-CBC") {
+ cipher = Aes192Cbc;
+ } else if (dekInfo.first() == "AES-256-CBC") {
+ cipher = Aes256Cbc;
} else {
clear(deepClear);
return;
@@ -522,6 +598,10 @@ static EncryptionData readPbes2(const QVector<QAsn1Element> &element, const QByt
return {};
break;
} // @todo(?): case (RC5 , AES)
+ case QSslKeyPrivate::Cipher::Aes128Cbc:
+ case QSslKeyPrivate::Cipher::Aes192Cbc:
+ case QSslKeyPrivate::Cipher::Aes256Cbc:
+ Q_UNREACHABLE();
}
if (Q_LIKELY(keyDerivationAlgorithm == PKCS5_PBKDF2_ENCRYPTION_OID)) {
diff --git a/src/network/ssl/qsslkey_schannel.cpp b/src/network/ssl/qsslkey_schannel.cpp
new file mode 100644
index 0000000000..1e21d123f4
--- /dev/null
+++ b/src/network/ssl/qsslkey_schannel.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qssl_p.h"
+#include "qsslkey.h"
+#include "qsslkey_p.h"
+#include "qsslcertificate_p.h"
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qscopeguard.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+const wchar_t *getName(QSslKeyPrivate::Cipher cipher)
+{
+ switch (cipher) {
+ case QSslKeyPrivate::Cipher::DesCbc:
+ return BCRYPT_DES_ALGORITHM;
+ case QSslKeyPrivate::Cipher::DesEde3Cbc:
+ return BCRYPT_3DES_ALGORITHM;
+ case QSslKeyPrivate::Cipher::Rc2Cbc:
+ return BCRYPT_RC2_ALGORITHM;
+ case QSslKeyPrivate::Cipher::Aes128Cbc:
+ case QSslKeyPrivate::Cipher::Aes192Cbc:
+ case QSslKeyPrivate::Cipher::Aes256Cbc:
+ return BCRYPT_AES_ALGORITHM;
+ }
+ Q_UNREACHABLE();
+}
+
+BCRYPT_ALG_HANDLE getHandle(QSslKeyPrivate::Cipher cipher)
+{
+ BCRYPT_ALG_HANDLE handle;
+ NTSTATUS status = BCryptOpenAlgorithmProvider(
+ &handle, // phAlgorithm
+ getName(cipher), // pszAlgId
+ nullptr, // pszImplementation
+ 0 // dwFlags
+ );
+ if (status < 0) {
+ qCWarning(lcSsl, "Failed to open algorithm handle (%ld)!", status);
+ return nullptr;
+ }
+
+ return handle;
+}
+
+BCRYPT_KEY_HANDLE generateSymmetricKey(BCRYPT_ALG_HANDLE handle,
+ const QByteArray &key)
+{
+ BCRYPT_KEY_HANDLE keyHandle;
+ NTSTATUS status = BCryptGenerateSymmetricKey(
+ handle, // hAlgorithm
+ &keyHandle, // phKey
+ nullptr, // pbKeyObject (can ignore)
+ 0, // cbKeyObject (also ignoring)
+ reinterpret_cast<unsigned char *>(const_cast<char *>(key.data())), // pbSecret
+ ULONG(key.length()), // cbSecret
+ 0 // dwFlags
+ );
+ if (status < 0) {
+ qCWarning(lcSsl, "Failed to generate symmetric key (%ld)!", status);
+ return nullptr;
+ }
+
+ status = BCryptSetProperty(
+ keyHandle, // hObject
+ BCRYPT_CHAINING_MODE, // pszProperty
+ reinterpret_cast<UCHAR *>(const_cast<wchar_t *>(BCRYPT_CHAIN_MODE_CBC)), // pbInput
+ ARRAYSIZE(BCRYPT_CHAIN_MODE_CBC), // cbInput
+ 0 // dwFlags
+ );
+ if (status < 0) {
+ BCryptDestroyKey(keyHandle);
+ qCWarning(lcSsl, "Failed to change the symmetric key's chaining mode (%ld)!", status);
+ return nullptr;
+ }
+ return keyHandle;
+}
+
+QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key,
+ const QByteArray &iv, bool encrypt)
+{
+ BCRYPT_ALG_HANDLE handle = getHandle(cipher);
+ if (!handle)
+ return {};
+ auto handleDealloc = qScopeGuard([&handle]() {
+ BCryptCloseAlgorithmProvider(handle, 0);
+ });
+
+ BCRYPT_KEY_HANDLE keyHandle = generateSymmetricKey(handle, key);
+ if (!keyHandle)
+ return {};
+ auto keyHandleDealloc = qScopeGuard([&keyHandle]() {
+ BCryptDestroyKey(keyHandle);
+ });
+
+ QByteArray ivCopy = iv; // This gets modified, so we take a copy
+
+ ULONG sizeNeeded = 0;
+ QVarLengthArray<unsigned char> output;
+ auto cryptFunction = encrypt ? BCryptEncrypt : BCryptDecrypt;
+ for (int i = 0; i < 2; i++) {
+ output.resize(int(sizeNeeded));
+ auto input = reinterpret_cast<unsigned char *>(const_cast<char *>(data.data()));
+ // Need to call it twice because the first iteration lets us know the size needed.
+ NTSTATUS status = cryptFunction(
+ keyHandle, // hKey
+ input, // pbInput
+ ULONG(data.length()), // cbInput
+ nullptr, // pPaddingInfo
+ reinterpret_cast<unsigned char *>(ivCopy.data()), // pbIV
+ ULONG(ivCopy.length()), // cbIV
+ sizeNeeded ? output.data() : nullptr, // pbOutput
+ ULONG(output.length()), // cbOutput
+ &sizeNeeded, // pcbResult
+ BCRYPT_BLOCK_PADDING // dwFlags
+ );
+ if (status < 0) {
+ qCWarning(lcSsl, "%s failed (%ld)!", encrypt ? "Encrypt" : "Decrypt", status);
+ return {};
+ }
+ }
+
+ return QByteArray(reinterpret_cast<const char *>(output.constData()), int(sizeNeeded));
+}
+} // anonymous namespace
+
+QByteArray QSslKeyPrivate::decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key,
+ const QByteArray &iv)
+{
+ return doCrypt(cipher, data, key, iv, false);
+}
+
+QByteArray QSslKeyPrivate::encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key,
+ const QByteArray &iv)
+{
+ return doCrypt(cipher, data, key, iv, true);
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslkey_winrt.cpp b/src/network/ssl/qsslkey_winrt.cpp
index f2ed813965..69eaaa387f 100644
--- a/src/network/ssl/qsslkey_winrt.cpp
+++ b/src/network/ssl/qsslkey_winrt.cpp
@@ -83,6 +83,15 @@ struct SslKeyGlobal
hr = keyProviderFactory->OpenAlgorithm(HString::MakeReference(L"RC2_CBC").Get(),
&keyProviders[QSslKeyPrivate::Rc2Cbc]);
Q_ASSERT_SUCCEEDED(hr);
+ hr = keyProviderFactory->OpenAlgorithm(HString::MakeReference(L"AES_CBC").Get(),
+ &keyProviders[QSslKeyPrivate::Aes128Cbc]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = keyProviderFactory->OpenAlgorithm(HString::MakeReference(L"AES_CBC").Get(),
+ &keyProviders[QSslKeyPrivate::Aes192Cbc]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = keyProviderFactory->OpenAlgorithm(HString::MakeReference(L"AES_CBC").Get(),
+ &keyProviders[QSslKeyPrivate::Aes256Cbc]);
+ Q_ASSERT_SUCCEEDED(hr);
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_CryptographicBuffer).Get(),
&bufferFactory);
diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.cpp b/src/network/ssl/qsslpresharedkeyauthenticator.cpp
index 3bb2719026..01e1501763 100644
--- a/src/network/ssl/qsslpresharedkeyauthenticator.cpp
+++ b/src/network/ssl/qsslpresharedkeyauthenticator.cpp
@@ -94,6 +94,8 @@ QSslPreSharedKeyAuthenticatorPrivate::QSslPreSharedKeyAuthenticatorPrivate()
\note PSK ciphersuites are supported only when using OpenSSL 1.0.1 (or
greater) as the SSL backend.
+ \note PSK is currently only supported in OpenSSL.
+
\sa QSslSocket
*/
diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.h b/src/network/ssl/qsslpresharedkeyauthenticator.h
index 423f7731b4..5d714dc34e 100644
--- a/src/network/ssl/qsslpresharedkeyauthenticator.h
+++ b/src/network/ssl/qsslpresharedkeyauthenticator.h
@@ -59,11 +59,9 @@ public:
Q_NETWORK_EXPORT QSslPreSharedKeyAuthenticator(const QSslPreSharedKeyAuthenticator &authenticator);
Q_NETWORK_EXPORT QSslPreSharedKeyAuthenticator &operator=(const QSslPreSharedKeyAuthenticator &authenticator);
-#ifdef Q_COMPILER_RVALUE_REFS
- QSslPreSharedKeyAuthenticator &operator=(QSslPreSharedKeyAuthenticator &&other) Q_DECL_NOTHROW { swap(other); return *this; }
-#endif
+ QSslPreSharedKeyAuthenticator &operator=(QSslPreSharedKeyAuthenticator &&other) noexcept { swap(other); return *this; }
- void swap(QSslPreSharedKeyAuthenticator &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QSslPreSharedKeyAuthenticator &other) noexcept { qSwap(d, other.d); }
Q_NETWORK_EXPORT QByteArray identityHint() const;
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 4f49a71e8a..ca6c58117d 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -133,7 +133,8 @@
\list
\li The socket's cryptographic cipher suite can be customized before
- the handshake phase with setCiphers() and setDefaultCiphers().
+ the handshake phase with QSslConfiguration::setCiphers()
+ and QSslConfiguration::setDefaultCiphers().
\li The socket's local certificate and private key can be customized
before the handshake phase with setLocalCertificate() and
setPrivateKey().
@@ -202,6 +203,7 @@
does not require this certificate to be valid. This is useful when you
want to display peer certificate details to the user without affecting the
actual SSL handshake. This mode is the default for servers.
+ Note: In Schannel this value acts the same as VerifyNone.
\value VerifyPeer QSslSocket will request a certificate from the peer
during the SSL handshake phase, and requires that this certificate is
@@ -312,6 +314,7 @@
#include "qssl_p.h"
#include "qsslsocket.h"
#include "qsslcipher.h"
+#include "qocspresponse.h"
#ifndef QT_NO_OPENSSL
#include "qsslsocket_openssl_p.h"
#endif
@@ -321,6 +324,9 @@
#ifdef QT_SECURETRANSPORT
#include "qsslsocket_mac_p.h"
#endif
+#if QT_CONFIG(schannel)
+#include "qsslsocket_schannel_p.h"
+#endif
#include "qsslconfiguration_p.h"
#include <QtCore/qdebug.h>
@@ -459,6 +465,9 @@ void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port, O
return;
}
+ if (!d->verifyProtocolSupported("QSslSocket::connectToHostEncrypted:"))
+ return;
+
d->init();
d->autoStartHandshake = true;
d->initialized = true;
@@ -752,8 +761,8 @@ qint64 QSslSocket::bytesAvailable() const
{
Q_D(const QSslSocket);
if (d->mode == UnencryptedMode)
- return QIODevice::bytesAvailable() + (d->plainSocket ? d->plainSocket->bytesAvailable() : 0);
- return QIODevice::bytesAvailable();
+ return QAbstractSocket::bytesAvailable() + (d->plainSocket ? d->plainSocket->bytesAvailable() : 0);
+ return QAbstractSocket::bytesAvailable();
}
/*!
@@ -809,8 +818,8 @@ bool QSslSocket::canReadLine() const
{
Q_D(const QSslSocket);
if (d->mode == UnencryptedMode)
- return QIODevice::canReadLine() || (d->plainSocket && d->plainSocket->canReadLine());
- return QIODevice::canReadLine();
+ return QAbstractSocket::canReadLine() || (d->plainSocket && d->plainSocket->canReadLine());
+ return QAbstractSocket::canReadLine();
}
/*!
@@ -840,8 +849,8 @@ bool QSslSocket::atEnd() const
{
Q_D(const QSslSocket);
if (d->mode == UnencryptedMode)
- return QIODevice::atEnd() && (!d->plainSocket || d->plainSocket->atEnd());
- return QIODevice::atEnd();
+ return QAbstractSocket::atEnd() && (!d->plainSocket || d->plainSocket->atEnd());
+ return QAbstractSocket::atEnd();
}
/*!
@@ -906,7 +915,8 @@ void QSslSocket::abort()
time without notice.
\sa localCertificate(), peerCertificate(), peerCertificateChain(),
- sessionCipher(), privateKey(), ciphers(), caCertificates()
+ sessionCipher(), privateKey(), QSslConfiguration::ciphers(),
+ QSslConfiguration::caCertificates()
*/
QSslConfiguration QSslSocket::sslConfiguration() const
{
@@ -914,7 +924,7 @@ QSslConfiguration QSslSocket::sslConfiguration() const
// create a deep copy of our configuration
QSslConfigurationPrivate *copy = new QSslConfigurationPrivate(d->configuration);
- copy->ref.store(0); // the QSslConfiguration constructor refs up
+ copy->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up
copy->sessionCipher = d->sessionCipher();
copy->sessionProtocol = d->sessionProtocol();
@@ -930,7 +940,8 @@ QSslConfiguration QSslSocket::sslConfiguration() const
It is not possible to set the SSL-state related fields.
- \sa setLocalCertificate(), setPrivateKey(), setCaCertificates(), setCiphers()
+ \sa setLocalCertificate(), setPrivateKey(), QSslConfiguration::setCaCertificates(),
+ QSslConfiguration::setCiphers()
*/
void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
{
@@ -952,6 +963,9 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
d->configuration.nextAllowedProtocols = configuration.allowedNextProtocols();
d->configuration.nextNegotiatedProtocol = configuration.nextNegotiatedProtocol();
d->configuration.nextProtocolNegotiationStatus = configuration.nextProtocolNegotiationStatus();
+#if QT_CONFIG(ocsp)
+ d->configuration.ocspStaplingEnabled = configuration.ocspStaplingEnabled();
+#endif
// if the CA certificates were set explicitly (either via
// QSslConfiguration::setCaCertificates() or QSslSocket::setCaCertificates(),
@@ -1113,8 +1127,10 @@ QList<QSslCertificate> QSslSocket::peerCertificateChain() const
session cipher. This ordered list must be in place before the
handshake phase begins.
- \sa ciphers(), setCiphers(), setDefaultCiphers(), defaultCiphers(),
- supportedCiphers()
+ \sa QSslConfiguration::ciphers(), QSslConfiguration::setCiphers(),
+ QSslConfiguration::setCiphers(),
+ QSslConfiguration::ciphers(),
+ QSslConfiguration::supportedCiphers()
*/
QSslCipher QSslSocket::sessionCipher() const
{
@@ -1136,6 +1152,20 @@ QSsl::SslProtocol QSslSocket::sessionProtocol() const
return d->sessionProtocol();
}
+/*!
+ \since 5.13
+
+ This function returns Online Certificate Status Protocol responses that
+ a server may send during a TLS handshake using OCSP stapling. The vector
+ is empty if no definitive response or no response at all was received.
+
+ \sa QSslConfiguration::setOcspStaplingEnabled()
+*/
+QVector<QOcspResponse> QSslSocket::ocspResponses() const
+{
+ Q_D(const QSslSocket);
+ return d->ocspResponses;
+}
/*!
Sets the socket's private \l {QSslKey} {key} to \a key. The
@@ -1179,12 +1209,21 @@ void QSslSocket::setPrivateKey(const QSslKey &key)
void QSslSocket::setPrivateKey(const QString &fileName, QSsl::KeyAlgorithm algorithm,
QSsl::EncodingFormat format, const QByteArray &passPhrase)
{
- Q_D(QSslSocket);
QFile file(fileName);
- if (file.open(QIODevice::ReadOnly)) {
- d->configuration.privateKey = QSslKey(file.readAll(), algorithm,
- format, QSsl::PrivateKey, passPhrase);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qCWarning(lcSsl, "QSslSocket::setPrivateKey: Couldn't open file for reading");
+ return;
+ }
+
+ QSslKey key(file.readAll(), algorithm, format, QSsl::PrivateKey, passPhrase);
+ if (key.isNull()) {
+ qCWarning(lcSsl, "QSslSocket::setPrivateKey: "
+ "The specified file does not contain a valid key");
+ return;
}
+
+ Q_D(QSslSocket);
+ d->configuration.privateKey = key;
}
/*!
@@ -1198,6 +1237,7 @@ QSslKey QSslSocket::privateKey() const
return d->configuration.privateKey;
}
+#if QT_DEPRECATED_SINCE(5, 5)
/*!
\deprecated
@@ -1341,6 +1381,7 @@ QList<QSslCipher> QSslSocket::supportedCiphers()
{
return QSslSocketPrivate::supportedCiphers();
}
+#endif // #if QT_DEPRECATED_SINCE(5, 5)
/*!
Searches all files in the \a path for certificates encoded in the
@@ -1376,7 +1417,8 @@ bool QSslSocket::addCaCertificates(const QString &path, QSsl::EncodingFormat for
To add multiple certificates, use addCaCertificates().
- \sa caCertificates(), setCaCertificates()
+ \sa QSslConfiguration::caCertificates(),
+ QSslConfiguration::setCaCertificates()
*/
void QSslSocket::addCaCertificate(const QSslCertificate &certificate)
{
@@ -1391,7 +1433,7 @@ void QSslSocket::addCaCertificate(const QSslCertificate &certificate)
For more precise control, use addCaCertificate().
- \sa caCertificates(), addDefaultCaCertificate()
+ \sa QSslConfiguration::caCertificates(), addDefaultCaCertificate()
*/
void QSslSocket::addCaCertificates(const QList<QSslCertificate> &certificates)
{
@@ -1399,6 +1441,7 @@ void QSslSocket::addCaCertificates(const QList<QSslCertificate> &certificates)
d->configuration.caCertificates += certificates;
}
+#if QT_DEPRECATED_SINCE(5, 5)
/*!
\deprecated
@@ -1443,6 +1486,7 @@ QList<QSslCertificate> QSslSocket::caCertificates() const
Q_D(const QSslSocket);
return d->configuration.caCertificates;
}
+#endif // #if QT_DEPRECATED_SINCE(5, 5)
/*!
Searches all files in the \a path for certificates with the
@@ -1454,7 +1498,8 @@ QList<QSslCertificate> QSslSocket::caCertificates() const
Each SSL socket's CA certificate database is initialized to the
default CA certificate database.
- \sa defaultCaCertificates(), addCaCertificates(), addDefaultCaCertificate()
+ \sa QSslConfiguration::caCertificates(), addCaCertificates(),
+ addDefaultCaCertificate()
*/
bool QSslSocket::addDefaultCaCertificates(const QString &path, QSsl::EncodingFormat encoding,
QRegExp::PatternSyntax syntax)
@@ -1467,7 +1512,7 @@ bool QSslSocket::addDefaultCaCertificates(const QString &path, QSsl::EncodingFor
SSL socket's CA certificate database is initialized to the default
CA certificate database.
- \sa defaultCaCertificates(), addCaCertificates()
+ \sa QSslConfiguration::defaultCaCertificates(), addCaCertificates()
*/
void QSslSocket::addDefaultCaCertificate(const QSslCertificate &certificate)
{
@@ -1479,13 +1524,14 @@ void QSslSocket::addDefaultCaCertificate(const QSslCertificate &certificate)
SSL socket's CA certificate database is initialized to the default
CA certificate database.
- \sa defaultCaCertificates(), addCaCertificates()
+ \sa QSslConfiguration::caCertificates(), addCaCertificates()
*/
void QSslSocket::addDefaultCaCertificates(const QList<QSslCertificate> &certificates)
{
QSslSocketPrivate::addDefaultCaCertificates(certificates);
}
+#if QT_DEPRECATED_SINCE(5, 5)
/*!
\deprecated
@@ -1553,6 +1599,7 @@ QList<QSslCertificate> QSslSocket::systemCaCertificates()
// we are calling ensureInitialized() in the method below
return QSslSocketPrivate::systemCaCertificates();
}
+#endif // #if QT_DEPRECATED_SINCE(5, 5)
/*!
Waits until the socket is connected, or \a msecs milliseconds,
@@ -1597,6 +1644,8 @@ bool QSslSocket::waitForEncrypted(int msecs)
return false;
if (d->mode == UnencryptedMode && !d->autoStartHandshake)
return false;
+ if (!d->verifyProtocolSupported("QSslSocket::waitForEncrypted:"))
+ return false;
QElapsedTimer stopWatch;
stopWatch.start();
@@ -1846,6 +1895,10 @@ void QSslSocket::startClientEncryption()
d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
return;
}
+
+ if (!d->verifyProtocolSupported("QSslSocket::startClientEncryption:"))
+ return;
+
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "QSslSocket::startClientEncryption()";
#endif
@@ -1889,6 +1942,9 @@ void QSslSocket::startServerEncryption()
d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
return;
}
+ if (!d->verifyProtocolSupported("QSslSocket::startServerEncryption"))
+ return;
+
d->mode = SslServerMode;
emit modeChanged(d->mode);
d->startServerEncryption();
@@ -1974,6 +2030,7 @@ void QSslSocket::connectToHost(const QString &hostName, quint16 port, OpenMode o
d->createPlainSocket(openMode);
}
#ifndef QT_NO_NETWORKPROXY
+ d->plainSocket->setProtocolTag(d->protocolTag);
d->plainSocket->setProxy(proxy());
#endif
QIODevice::open(openMode);
@@ -2108,6 +2165,7 @@ void QSslSocketPrivate::init()
shutdown = false;
pendingClose = false;
flushTriggered = false;
+ ocspResponses.clear();
// we don't want to clear the ignoreErrorsList, so
// that it is possible setting it before connecting
@@ -2122,6 +2180,20 @@ void QSslSocketPrivate::init()
/*!
\internal
*/
+bool QSslSocketPrivate::verifyProtocolSupported(const char *where)
+{
+ if (configuration.protocol == QSsl::SslV2 || configuration.protocol == QSsl::SslV3) {
+ qCWarning(lcSsl) << where << "Attempted to use an unsupported protocol.";
+ setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
+ QSslSocket::tr("Attempted to use an unsupported protocol."));
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \internal
+*/
QList<QSslCipher> QSslSocketPrivate::defaultCiphers()
{
QSslSocketPrivate::ensureInitialized();
@@ -2306,7 +2378,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
if (!global)
return;
- ptr->ref.store(1);
+ ptr->ref.storeRelaxed(1);
ptr->peerCertificate = global->peerCertificate;
ptr->peerCertificateChain = global->peerCertificateChain;
ptr->localCertificateChain = global->localCertificateChain;
@@ -2324,6 +2396,9 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
#if QT_CONFIG(dtls)
ptr->dtlsCookieEnabled = global->dtlsCookieEnabled;
#endif
+#if QT_CONFIG(ocsp)
+ ptr->ocspStaplingEnabled = global->ocspStaplingEnabled;
+#endif
}
/*!
@@ -2822,6 +2897,17 @@ QSharedPointer<QSslContext> QSslSocketPrivate::sslContext(QSslSocket *socket)
bool QSslSocketPrivate::isMatchingHostname(const QSslCertificate &cert, const QString &peerName)
{
+ QHostAddress hostAddress(peerName);
+ if (!hostAddress.isNull()) {
+ const auto subjectAlternativeNames = cert.subjectAlternativeNames();
+ const auto ipAddresses = subjectAlternativeNames.equal_range(QSsl::AlternativeNameEntryType::IpAddressEntry);
+
+ for (auto it = ipAddresses.first; it != ipAddresses.second; it++) {
+ if (QHostAddress(*it).isEqual(hostAddress, QHostAddress::StrictConversion))
+ return true;
+ }
+ }
+
const QString lowerPeerName = QString::fromLatin1(QUrl::toAce(peerName));
const QStringList commonNames = cert.subjectInfo(QSslCertificate::CommonName);
diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h
index c66ebdde54..35943c7d7e 100644
--- a/src/network/ssl/qsslsocket.h
+++ b/src/network/ssl/qsslsocket.h
@@ -44,6 +44,7 @@
#include <QtNetwork/qtnetworkglobal.h>
#include <QtCore/qlist.h>
#include <QtCore/qregexp.h>
+#include <QtCore/qvector.h>
#ifndef QT_NO_SSL
# include <QtNetwork/qtcpsocket.h>
# include <QtNetwork/qsslerror.h>
@@ -60,6 +61,7 @@ class QSslCertificate;
class QSslConfiguration;
class QSslEllipticCurve;
class QSslPreSharedKeyAuthenticator;
+class QOcspResponse;
class QSslSocketPrivate;
class Q_NETWORK_EXPORT QSslSocket : public QTcpSocket
@@ -142,6 +144,7 @@ public:
QList<QSslCertificate> peerCertificateChain() const;
QSslCipher sessionCipher() const;
QSsl::SslProtocol sessionProtocol() const;
+ QVector<QOcspResponse> ocspResponses() const;
// Private keys, for server sockets.
void setPrivateKey(const QSslKey &key);
@@ -228,7 +231,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_flushWriteBuffer())
Q_PRIVATE_SLOT(d_func(), void _q_flushReadBuffer())
Q_PRIVATE_SLOT(d_func(), void _q_resumeImplementation())
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !QT_CONFIG(schannel)
Q_PRIVATE_SLOT(d_func(), void _q_caRootLoaded(QSslCertificate,QSslCertificate))
#endif
friend class QSslSocketBackendPrivate;
diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp
index 7c5f4310f8..487e975db6 100644
--- a/src/network/ssl/qsslsocket_mac.cpp
+++ b/src/network/ssl/qsslsocket_mac.cpp
@@ -89,7 +89,7 @@ struct EphemeralSecKeychain
~EphemeralSecKeychain();
SecKeychainRef keychain = nullptr;
- Q_DISABLE_COPY(EphemeralSecKeychain)
+ Q_DISABLE_COPY_MOVE(EphemeralSecKeychain)
};
EphemeralSecKeychain::EphemeralSecKeychain()
@@ -995,9 +995,6 @@ void QSslSocketBackendPrivate::destroySslContext()
context.reset(nullptr);
}
-static QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase);
-
-
bool QSslSocketBackendPrivate::setSessionCertificate(QString &errorDescription, QAbstractSocket::SocketError &errorCode)
{
Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)");
@@ -1112,6 +1109,12 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
return false;
}
+ // SslV3 is unsupported.
+ if (configuration.protocol == QSsl::SslV3) {
+ qCDebug(lcSsl) << "protocol QSsl::SslV3 is disabled";
+ return false;
+ }
+
// SecureTransport has kTLSProtocol13 constant and also, kTLSProtocolMaxSupported.
// Calling SSLSetProtocolVersionMax/Min with any of these two constants results
// in errInvalidParam and a failure to set the protocol version. This means
@@ -1126,14 +1129,7 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
OSStatus err = errSecSuccess;
- if (configuration.protocol == QSsl::SslV3) {
- #ifdef QSSLSOCKET_DEBUG
- qCDebug(lcSsl) << plainSocket << "requesting : SSLv3";
- #endif
- err = SSLSetProtocolVersionMin(context, kSSLProtocol3);
- if (err == errSecSuccess)
- err = SSLSetProtocolVersionMax(context, kSSLProtocol3);
- } else if (configuration.protocol == QSsl::TlsV1_0) {
+ if (configuration.protocol == QSsl::TlsV1_0) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.0";
#endif
@@ -1158,13 +1154,14 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : any";
#endif
- // kSSLProtocol3, since kSSLProtocol2 is disabled:
- err = SSLSetProtocolVersionMin(context, kSSLProtocol3);
+ err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
} else if (configuration.protocol == QSsl::TlsV1SslV3) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : SSLv3 - TLSv1.2";
#endif
- err = SSLSetProtocolVersionMin(context, kSSLProtocol3);
+ err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
+ if (err == errSecSuccess)
+ err = SSLSetProtocolVersionMax(context, kTLSProtocol1);
} else if (configuration.protocol == QSsl::SecureProtocols) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2";
@@ -1210,7 +1207,7 @@ bool QSslSocketBackendPrivate::verifySessionProtocol() const
if (configuration.protocol == QSsl::AnyProtocol)
protocolOk = true;
else if (configuration.protocol == QSsl::TlsV1SslV3)
- protocolOk = (sessionProtocol() >= QSsl::SslV3);
+ protocolOk = (sessionProtocol() == QSsl::TlsV1_0);
else if (configuration.protocol == QSsl::SecureProtocols)
protocolOk = (sessionProtocol() >= QSsl::TlsV1_0);
else if (configuration.protocol == QSsl::TlsV1_0OrLater)
@@ -1503,264 +1500,4 @@ bool QSslSocketBackendPrivate::startHandshake()
}
}
-/*
- PKCS12 helpers.
-*/
-
-static QAsn1Element wrap(quint8 type, const QAsn1Element &child)
-{
- QByteArray value;
- QDataStream stream(&value, QIODevice::WriteOnly);
- child.write(stream);
- return QAsn1Element(type, value);
-}
-
-static QAsn1Element _q_PKCS7_data(const QByteArray &data)
-{
- QVector<QAsn1Element> items;
- items << QAsn1Element::fromObjectId("1.2.840.113549.1.7.1");
- items << wrap(QAsn1Element::Context0Type,
- QAsn1Element(QAsn1Element::OctetStringType, data));
- return QAsn1Element::fromVector(items);
-}
-
-/*!
- PKCS #12 key derivation.
-
- Some test vectors:
- http://www.drh-consultancy.demon.co.uk/test.txt
-*/
-static QByteArray _q_PKCS12_keygen(char id, const QByteArray &salt, const QString &passPhrase, int n, int r)
-{
- const int u = 20;
- const int v = 64;
-
- // password formatting
- QByteArray passUnicode(passPhrase.size() * 2 + 2, '\0');
- char *p = passUnicode.data();
- for (int i = 0; i < passPhrase.size(); ++i) {
- quint16 ch = passPhrase[i].unicode();
- *(p++) = (ch & 0xff00) >> 8;
- *(p++) = (ch & 0xff);
- }
-
- // prepare I
- QByteArray D(64, id);
- QByteArray S, P;
- const int sSize = v * ((salt.size() + v - 1) / v);
- S.resize(sSize);
- for (int i = 0; i < sSize; ++i) {
- S[i] = salt[i % salt.size()];
- }
- const int pSize = v * ((passUnicode.size() + v - 1) / v);
- P.resize(pSize);
- for (int i = 0; i < pSize; ++i) {
- P[i] = passUnicode[i % passUnicode.size()];
- }
- QByteArray I = S + P;
-
- // apply hashing
- const int c = (n + u - 1) / u;
- QByteArray A;
- QByteArray B;
- B.resize(v);
- QCryptographicHash hash(QCryptographicHash::Sha1);
- for (int i = 0; i < c; ++i) {
- // hash r iterations
- QByteArray Ai = D + I;
- for (int j = 0; j < r; ++j) {
- hash.reset();
- hash.addData(Ai);
- Ai = hash.result();
- }
-
- for (int j = 0; j < v; ++j) {
- B[j] = Ai[j % u];
- }
-
- // modify I as Ij = (Ij + B + 1) modulo 2^v
- for (int p = 0; p < I.size(); p += v) {
- quint8 carry = 1;
- for (int j = v - 1; j >= 0; --j) {
- quint16 v = quint8(I[p+j]) + quint8(B[j]) + carry;
- I[p+j] = v & 0xff;
- carry = (v & 0xff00) >> 8;
- }
- }
- A += Ai;
- }
- return A.left(n);
-}
-
-static QByteArray _q_PKCS12_salt()
-{
- QByteArray salt;
- salt.resize(8);
- for (int i = 0; i < salt.size(); ++i) {
- salt[i] = (qrand() & 0xff);
- }
- return salt;
-}
-
-static QByteArray _q_PKCS12_certBag(const QSslCertificate &cert)
-{
- QVector<QAsn1Element> items;
- items << QAsn1Element::fromObjectId("1.2.840.113549.1.12.10.1.3");
-
- // certificate
- QVector<QAsn1Element> certItems;
- certItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.22.1");
- certItems << wrap(QAsn1Element::Context0Type,
- QAsn1Element(QAsn1Element::OctetStringType, cert.toDer()));
- items << wrap(QAsn1Element::Context0Type,
- QAsn1Element::fromVector(certItems));
-
- // local key id
- const QByteArray localKeyId = cert.digest(QCryptographicHash::Sha1);
- QVector<QAsn1Element> idItems;
- idItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.21");
- idItems << wrap(QAsn1Element::SetType,
- QAsn1Element(QAsn1Element::OctetStringType, localKeyId));
- items << wrap(QAsn1Element::SetType, QAsn1Element::fromVector(idItems));
-
- // dump
- QAsn1Element root = wrap(QAsn1Element::SequenceType, QAsn1Element::fromVector(items));
- QByteArray ba;
- QDataStream stream(&ba, QIODevice::WriteOnly);
- root.write(stream);
- return ba;
-}
-
-static QAsn1Element _q_PKCS12_key(const QSslKey &key)
-{
- Q_ASSERT(key.algorithm() == QSsl::Rsa || key.algorithm() == QSsl::Dsa);
-
- QVector<QAsn1Element> keyItems;
- keyItems << QAsn1Element::fromInteger(0);
- QVector<QAsn1Element> algoItems;
- if (key.algorithm() == QSsl::Rsa)
- algoItems << QAsn1Element::fromObjectId(RSA_ENCRYPTION_OID);
- else if (key.algorithm() == QSsl::Dsa)
- algoItems << QAsn1Element::fromObjectId(DSA_ENCRYPTION_OID);
- algoItems << QAsn1Element(QAsn1Element::NullType);
- keyItems << QAsn1Element::fromVector(algoItems);
- keyItems << QAsn1Element(QAsn1Element::OctetStringType, key.toDer());
- return QAsn1Element::fromVector(keyItems);
-}
-
-static QByteArray _q_PKCS12_shroudedKeyBag(const QSslKey &key, const QString &passPhrase, const QByteArray &localKeyId)
-{
- const int iterations = 2048;
- QByteArray salt = _q_PKCS12_salt();
- QByteArray cKey = _q_PKCS12_keygen(1, salt, passPhrase, 24, iterations);
- QByteArray cIv = _q_PKCS12_keygen(2, salt, passPhrase, 8, iterations);
-
- // prepare and encrypt data
- QByteArray plain;
- QDataStream plainStream(&plain, QIODevice::WriteOnly);
- _q_PKCS12_key(key).write(plainStream);
- QByteArray crypted = QSslKeyPrivate::encrypt(QSslKeyPrivate::DesEde3Cbc,
- plain, cKey, cIv);
-
- QVector<QAsn1Element> items;
- items << QAsn1Element::fromObjectId("1.2.840.113549.1.12.10.1.2");
-
- // key
- QVector<QAsn1Element> keyItems;
- QVector<QAsn1Element> algoItems;
- algoItems << QAsn1Element::fromObjectId("1.2.840.113549.1.12.1.3");
- QVector<QAsn1Element> paramItems;
- paramItems << QAsn1Element(QAsn1Element::OctetStringType, salt);
- paramItems << QAsn1Element::fromInteger(iterations);
- algoItems << QAsn1Element::fromVector(paramItems);
- keyItems << QAsn1Element::fromVector(algoItems);
- keyItems << QAsn1Element(QAsn1Element::OctetStringType, crypted);
- items << wrap(QAsn1Element::Context0Type,
- QAsn1Element::fromVector(keyItems));
-
- // local key id
- QVector<QAsn1Element> idItems;
- idItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.21");
- idItems << wrap(QAsn1Element::SetType,
- QAsn1Element(QAsn1Element::OctetStringType, localKeyId));
- items << wrap(QAsn1Element::SetType,
- QAsn1Element::fromVector(idItems));
-
- // dump
- QAsn1Element root = wrap(QAsn1Element::SequenceType, QAsn1Element::fromVector(items));
- QByteArray ba;
- QDataStream stream(&ba, QIODevice::WriteOnly);
- root.write(stream);
- return ba;
-}
-
-static QByteArray _q_PKCS12_bag(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase)
-{
- QVector<QAsn1Element> items;
-
- // certs
- for (int i = 0; i < certs.size(); ++i)
- items << _q_PKCS7_data(_q_PKCS12_certBag(certs[i]));
-
- // key
- const QByteArray localKeyId = certs.first().digest(QCryptographicHash::Sha1);
- items << _q_PKCS7_data(_q_PKCS12_shroudedKeyBag(key, passPhrase, localKeyId));
-
- // dump
- QAsn1Element root = QAsn1Element::fromVector(items);
- QByteArray ba;
- QDataStream stream(&ba, QIODevice::WriteOnly);
- root.write(stream);
- return ba;
-}
-
-static QAsn1Element _q_PKCS12_mac(const QByteArray &data, const QString &passPhrase)
-{
- const int iterations = 2048;
-
- // salt generation
- QByteArray macSalt = _q_PKCS12_salt();
- QByteArray key = _q_PKCS12_keygen(3, macSalt, passPhrase, 20, iterations);
-
- // HMAC calculation
- QMessageAuthenticationCode hmac(QCryptographicHash::Sha1, key);
- hmac.addData(data);
-
- QVector<QAsn1Element> algoItems;
- algoItems << QAsn1Element::fromObjectId("1.3.14.3.2.26");
- algoItems << QAsn1Element(QAsn1Element::NullType);
-
- QVector<QAsn1Element> digestItems;
- digestItems << QAsn1Element::fromVector(algoItems);
- digestItems << QAsn1Element(QAsn1Element::OctetStringType, hmac.result());
-
- QVector<QAsn1Element> macItems;
- macItems << QAsn1Element::fromVector(digestItems);
- macItems << QAsn1Element(QAsn1Element::OctetStringType, macSalt);
- macItems << QAsn1Element::fromInteger(iterations);
- return QAsn1Element::fromVector(macItems);
-}
-
-QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase)
-{
- QVector<QAsn1Element> items;
-
- // version
- items << QAsn1Element::fromInteger(3);
-
- // auth safe
- const QByteArray data = _q_PKCS12_bag(certs, key, passPhrase);
- items << _q_PKCS7_data(data);
-
- // HMAC
- items << _q_PKCS12_mac(data, passPhrase);
-
- // dump
- QAsn1Element root = QAsn1Element::fromVector(items);
- QByteArray ba;
- QDataStream stream(&ba, QIODevice::WriteOnly);
- root.write(stream);
- return ba;
-}
-
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket_mac_p.h b/src/network/ssl/qsslsocket_mac_p.h
index e37171e56a..48aca964a1 100644
--- a/src/network/ssl/qsslsocket_mac_p.h
+++ b/src/network/ssl/qsslsocket_mac_p.h
@@ -75,7 +75,7 @@ public:
private:
SSLContextRef context;
- Q_DISABLE_COPY(QSecureTransportContext)
+ Q_DISABLE_COPY_MOVE(QSecureTransportContext)
};
class QSslSocketBackendPrivate : public QSslSocketPrivate
@@ -129,7 +129,7 @@ private:
QSecureTransportContext context;
bool renegotiating = false;
- Q_DISABLE_COPY(QSslSocketBackendPrivate)
+ Q_DISABLE_COPY_MOVE(QSslSocketBackendPrivate)
};
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index ec772ddb45..d4bad1b1a5 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -65,6 +65,7 @@
#include "qsslellipticcurve.h"
#include "qsslpresharedkeyauthenticator.h"
#include "qsslpresharedkeyauthenticator_p.h"
+#include "qocspresponse_p.h"
#ifdef Q_OS_WIN
#include "qwindowscarootfetcher_p.h"
@@ -87,16 +88,16 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qscopedvaluerollback.h>
+#if QT_CONFIG(ocsp)
+#include "qocsp_p.h"
+#endif
+
+#include <algorithm>
+
#include <string.h>
QT_BEGIN_NAMESPACE
-#if defined(Q_OS_WIN)
- PtrCertOpenSystemStoreW QSslSocketPrivate::ptrCertOpenSystemStoreW = nullptr;
- PtrCertFindCertificateInStore QSslSocketPrivate::ptrCertFindCertificateInStore = nullptr;
- PtrCertCloseStore QSslSocketPrivate::ptrCertCloseStore = nullptr;
-#endif
-
bool QSslSocketPrivate::s_libraryLoaded = false;
bool QSslSocketPrivate::s_loadedCiphersAndCerts = false;
bool QSslSocketPrivate::s_loadRootCertsOnDemand = false;
@@ -190,6 +191,37 @@ static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsi
#endif // TLS1_3_VERSION
#endif
+
+#if QT_CONFIG(ocsp)
+
+int qt_OCSP_status_server_callback(SSL *ssl, void *ocspRequest)
+{
+ Q_UNUSED(ocspRequest)
+ if (!ssl)
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+
+ auto d = static_cast<QSslSocketBackendPrivate *>(q_SSL_get_ex_data(ssl, QSslSocketBackendPrivate::s_indexForSSLExtraData));
+ if (!d)
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+
+ Q_ASSERT(d->mode == QSslSocket::SslServerMode);
+ const QByteArray &response = d->ocspResponseDer;
+ Q_ASSERT(response.size());
+
+ unsigned char *derCopy = static_cast<unsigned char *>(q_OPENSSL_malloc(size_t(response.size())));
+ if (!derCopy)
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+
+ std::copy(response.data(), response.data() + response.size(), derCopy);
+ // We don't check the return value: internally OpenSSL simply assignes the
+ // pointer (it assumes it now owns this memory btw!) and the length.
+ q_SSL_set_tlsext_status_ocsp_resp(ssl, derCopy, response.size());
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
+#endif // ocsp
+
} // extern "C"
QSslSocketBackendPrivate::QSslSocketBackendPrivate()
@@ -257,6 +289,115 @@ QSslErrorEntry QSslErrorEntry::fromStoreContext(X509_STORE_CTX *ctx)
};
}
+#if QT_CONFIG(ocsp)
+
+QSslError qt_OCSP_response_status_to_QSslError(long code)
+{
+ switch (code) {
+ case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST:
+ return QSslError::OcspMalformedRequest;
+ case OCSP_RESPONSE_STATUS_INTERNALERROR:
+ return QSslError::OcspInternalError;
+ case OCSP_RESPONSE_STATUS_TRYLATER:
+ return QSslError::OcspTryLater;
+ case OCSP_RESPONSE_STATUS_SIGREQUIRED:
+ return QSslError::OcspSigRequred;
+ case OCSP_RESPONSE_STATUS_UNAUTHORIZED:
+ return QSslError::OcspUnauthorized;
+ case OCSP_RESPONSE_STATUS_SUCCESSFUL:
+ default:
+ return {};
+ }
+ Q_UNREACHABLE();
+}
+
+QOcspRevocationReason qt_OCSP_revocation_reason(int reason)
+{
+ switch (reason) {
+ case OCSP_REVOKED_STATUS_NOSTATUS:
+ return QOcspRevocationReason::None;
+ case OCSP_REVOKED_STATUS_UNSPECIFIED:
+ return QOcspRevocationReason::Unspecified;
+ case OCSP_REVOKED_STATUS_KEYCOMPROMISE:
+ return QOcspRevocationReason::KeyCompromise;
+ case OCSP_REVOKED_STATUS_CACOMPROMISE:
+ return QOcspRevocationReason::CACompromise;
+ case OCSP_REVOKED_STATUS_AFFILIATIONCHANGED:
+ return QOcspRevocationReason::AffiliationChanged;
+ case OCSP_REVOKED_STATUS_SUPERSEDED:
+ return QOcspRevocationReason::Superseded;
+ case OCSP_REVOKED_STATUS_CESSATIONOFOPERATION:
+ return QOcspRevocationReason::CessationOfOperation;
+ case OCSP_REVOKED_STATUS_CERTIFICATEHOLD:
+ return QOcspRevocationReason::CertificateHold;
+ case OCSP_REVOKED_STATUS_REMOVEFROMCRL:
+ return QOcspRevocationReason::RemoveFromCRL;
+ default:
+ return QOcspRevocationReason::None;
+ }
+
+ Q_UNREACHABLE();
+}
+
+bool qt_OCSP_certificate_match(OCSP_SINGLERESP *singleResponse, X509 *peerCert, X509 *issuer)
+{
+ // OCSP_basic_verify does verify that the responder is legit, the response is
+ // correctly signed, CertID is correct. But it does not know which certificate
+ // we were presented with by our peer, so it does not check if it's a response
+ // for our peer's certificate.
+ Q_ASSERT(singleResponse && peerCert && issuer);
+
+ const OCSP_CERTID *certId = q_OCSP_SINGLERESP_get0_id(singleResponse); // Does not increment refcount.
+ if (!certId) {
+ qCWarning(lcSsl, "A SingleResponse without CertID");
+ return false;
+ }
+
+ ASN1_OBJECT *md = nullptr;
+ ASN1_INTEGER *reportedSerialNumber = nullptr;
+ const int result = q_OCSP_id_get0_info(nullptr, &md, nullptr, &reportedSerialNumber, const_cast<OCSP_CERTID *>(certId));
+ if (result != 1 || !md || !reportedSerialNumber) {
+ qCWarning(lcSsl, "Failed to extract a hash and serial number from CertID structure");
+ return false;
+ }
+
+ if (!q_X509_get_serialNumber(peerCert)) {
+ // Is this possible at all? But we have to check this,
+ // ASN1_INTEGER_cmp (called from OCSP_id_cmp) dereferences
+ // without any checks at all.
+ qCWarning(lcSsl, "No serial number in peer's ceritificate");
+ return false;
+ }
+
+ const int nid = q_OBJ_obj2nid(md);
+ if (nid == NID_undef) {
+ qCWarning(lcSsl, "Unknown hash algorithm in CertID");
+ return false;
+ }
+
+ const EVP_MD *digest = q_EVP_get_digestbynid(nid); // Does not increment refcount.
+ if (!digest) {
+ qCWarning(lcSsl) << "No digest for nid" << nid;
+ return false;
+ }
+
+ OCSP_CERTID *recreatedId = q_OCSP_cert_to_id(digest, peerCert, issuer);
+ if (!recreatedId) {
+ qCWarning(lcSsl, "Failed to re-create CertID");
+ return false;
+ }
+ const QSharedPointer<OCSP_CERTID> guard(recreatedId, q_OCSP_CERTID_free);
+
+ if (q_OCSP_id_cmp(const_cast<OCSP_CERTID *>(certId), recreatedId)) {
+ qDebug(lcSsl, "Certificate ID mismatch");
+ return false;
+ }
+ // Bingo!
+ return true;
+}
+
+#endif // ocsp
+
int q_X509Callback(int ok, X509_STORE_CTX *ctx)
{
if (!ok) {
@@ -330,7 +471,7 @@ long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, Q
{
long options;
if (protocol == QSsl::TlsV1SslV3)
- options = SSL_OP_ALL|SSL_OP_NO_SSLv2;
+ options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
else if (protocol == QSsl::SecureProtocols)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
else if (protocol == QSsl::TlsV1_0OrLater)
@@ -382,11 +523,12 @@ bool QSslSocketBackendPrivate::initSslContext()
{
Q_Q(QSslSocket);
- // If no external context was set (e.g. bei QHttpNetworkConnection) we will create a default context
+ // If no external context was set (e.g. by QHttpNetworkConnection) we will
+ // create a default context
if (!sslContextPointer) {
// create a deep copy of our configuration
QSslConfigurationPrivate *configurationCopy = new QSslConfigurationPrivate(configuration);
- configurationCopy->ref.store(0); // the QSslConfiguration constructor refs up
+ configurationCopy->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up
sslContextPointer = QSslContext::sharedFromConfiguration(mode, configurationCopy, allowRootCertOnDemandLoading);
}
@@ -407,7 +549,7 @@ bool QSslSocketBackendPrivate::initSslContext()
if (configuration.protocol != QSsl::SslV2 &&
configuration.protocol != QSsl::SslV3 &&
configuration.protocol != QSsl::UnknownProtocol &&
- mode == QSslSocket::SslClientMode && QSslSocket::sslLibraryVersionNumber() >= 0x00090806fL) {
+ mode == QSslSocket::SslClientMode) {
// Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
if (tlsHostName.isEmpty())
@@ -465,6 +607,40 @@ bool QSslSocketBackendPrivate::initSslContext()
}
#endif // openssl version >= 0x10101006L
+#if QT_CONFIG(ocsp)
+ if (configuration.ocspStaplingEnabled) {
+ if (mode == QSslSocket::SslServerMode) {
+ setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
+ QSslSocket::tr("Server-side QSslSocket does not support OCSP stapling"));
+ return false;
+ }
+ if (q_SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp) != 1) {
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Failed to enable OCSP stapling"));
+ return false;
+ }
+ }
+
+ ocspResponseDer.clear();
+ auto responsePos = configuration.backendConfig.find("Qt-OCSP-response");
+ if (responsePos != configuration.backendConfig.end()) {
+ // This is our private, undocumented 'API' we use for the auto-testing of
+ // OCSP-stapling. It must be a der-encoded OCSP response, presumably set
+ // by tst_QOcsp.
+ const QVariant data(responsePos.value());
+ if (data.canConvert<QByteArray>())
+ ocspResponseDer = data.toByteArray();
+ }
+
+ if (ocspResponseDer.size()) {
+ if (mode != QSslSocket::SslServerMode) {
+ setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
+ QSslSocket::tr("Client-side sockets do not send OCSP responses"));
+ return false;
+ }
+ }
+#endif // ocsp
+
return true;
}
@@ -605,22 +781,20 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
#endif
QList<QSslCertificate> systemCerts;
#if defined(Q_OS_WIN)
- if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
- HCERTSTORE hSystemStore;
- hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT");
- if (hSystemStore) {
- PCCERT_CONTEXT pc = nullptr;
- while (1) {
- pc = ptrCertFindCertificateInStore(hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, pc);
- if (!pc)
- break;
- QByteArray der(reinterpret_cast<const char *>(pc->pbCertEncoded),
- static_cast<int>(pc->cbCertEncoded));
- QSslCertificate cert(der, QSsl::Der);
- systemCerts.append(cert);
- }
- ptrCertCloseStore(hSystemStore, 0);
+ HCERTSTORE hSystemStore;
+ hSystemStore = CertOpenSystemStoreW(0, L"ROOT");
+ if (hSystemStore) {
+ PCCERT_CONTEXT pc = nullptr;
+ while (1) {
+ pc = CertFindCertificateInStore(hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, pc);
+ if (!pc)
+ break;
+ QByteArray der(reinterpret_cast<const char *>(pc->pbCertEncoded),
+ static_cast<int>(pc->cbCertEncoded));
+ QSslCertificate cert(der, QSsl::Der);
+ systemCerts.append(cert);
}
+ CertCloseStore(hSystemStore, 0);
}
#elif defined(Q_OS_UNIX)
QSet<QString> certFiles;
@@ -1057,9 +1231,33 @@ bool QSslSocketBackendPrivate::startHandshake()
}
}
- bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
- || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
- && mode == QSslSocket::SslClientMode);
+ const bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
+ || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
+ && mode == QSslSocket::SslClientMode);
+
+#if QT_CONFIG(ocsp)
+ // For now it's always QSslSocket::SslClientMode - initSslContext() will bail out early,
+ // if it's enabled in QSslSocket::SslServerMode. This can change.
+ if (!configuration.peerCertificate.isNull() && configuration.ocspStaplingEnabled && doVerifyPeer) {
+ if (!checkOcspStatus()) {
+ if (ocspErrors.isEmpty()) {
+ {
+ const ScopedBool bg(inSetAndEmitError, true);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, ocspErrorDescription);
+ }
+ q->abort();
+ return false;
+ }
+
+ for (const QSslError &error : ocspErrors) {
+ errors << error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ }
+ }
+#endif // ocsp
// Check the peer certificate itself. First try the subject's common name
// (CN) as a wildcard, then try all alternate subject name DNS entries the
@@ -1306,6 +1504,179 @@ void QSslSocketBackendPrivate::_q_caRootLoaded(QSslCertificate cert, QSslCertifi
#endif
+#if QT_CONFIG(ocsp)
+
+bool QSslSocketBackendPrivate::checkOcspStatus()
+{
+ Q_ASSERT(ssl);
+ Q_ASSERT(mode == QSslSocket::SslClientMode); // See initSslContext() for SslServerMode
+ Q_ASSERT(configuration.peerVerifyMode != QSslSocket::VerifyNone);
+
+ ocspResponses.clear();
+ ocspErrorDescription.clear();
+ ocspErrors.clear();
+
+ const unsigned char *responseData = nullptr;
+ const long responseLength = q_SSL_get_tlsext_status_ocsp_resp(ssl, &responseData);
+ if (responseLength <= 0 || !responseData) {
+ ocspErrors.push_back(QSslError::OcspNoResponseFound);
+ return false;
+ }
+
+ OCSP_RESPONSE *response = q_d2i_OCSP_RESPONSE(nullptr, &responseData, responseLength);
+ if (!response) {
+ // Treat this as a fatal SslHandshakeError.
+ ocspErrorDescription = QSslSocket::tr("Failed to decode OCSP response");
+ return false;
+ }
+ const QSharedPointer<OCSP_RESPONSE> responseGuard(response, q_OCSP_RESPONSE_free);
+
+ const int ocspStatus = q_OCSP_response_status(response);
+ if (ocspStatus != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
+ // It's not a definitive response, it's an error message (not signed by the responder).
+ ocspErrors.push_back(qt_OCSP_response_status_to_QSslError(ocspStatus));
+ return false;
+ }
+
+ OCSP_BASICRESP *basicResponse = q_OCSP_response_get1_basic(response);
+ if (!basicResponse) {
+ // SslHandshakeError.
+ ocspErrorDescription = QSslSocket::tr("Failed to extract basic OCSP response");
+ return false;
+ }
+ const QSharedPointer<OCSP_BASICRESP> basicResponseGuard(basicResponse, q_OCSP_BASICRESP_free);
+
+ SSL_CTX *ctx = q_SSL_get_SSL_CTX(ssl); // Does not increment refcount.
+ Q_ASSERT(ctx);
+ X509_STORE *store = q_SSL_CTX_get_cert_store(ctx); // Does not increment refcount.
+ if (!store) {
+ // SslHandshakeError.
+ ocspErrorDescription = QSslSocket::tr("No certificate verification store, cannot verify OCSP response");
+ return false;
+ }
+
+ STACK_OF(X509) *peerChain = q_SSL_get_peer_cert_chain(ssl); // Does not increment refcount.
+ X509 *peerX509 = q_SSL_get_peer_certificate(ssl);
+ Q_ASSERT(peerChain || peerX509);
+ const QSharedPointer<X509> peerX509Guard(peerX509, q_X509_free);
+ // OCSP_basic_verify with 0 as verificationFlags:
+ //
+ // 0) Tries to find the OCSP responder's certificate in either peerChain
+ // or basicResponse->certs. If not found, verification fails.
+ // 1) It checks the signature using the responder's public key.
+ // 2) Then it tries to validate the responder's cert (building a chain
+ // etc.)
+ // 3) It checks CertID in response.
+ // 4) Ensures the responder is authorized to sign the status respond.
+ //
+ // Note, OpenSSL prior to 1.0.2b would only use bs->certs to
+ // verify the responder's chain (see their commit 4ba9a4265bd).
+ // Working this around - is too much fuss for ancient versions we
+ // are dropping quite soon anyway.
+ const unsigned long verificationFlags = 0;
+ const int success = q_OCSP_basic_verify(basicResponse, peerChain, store, verificationFlags);
+ if (success <= 0)
+ ocspErrors.push_back(QSslError::OcspResponseCannotBeTrusted);
+
+ if (q_OCSP_resp_count(basicResponse) != 1) {
+ ocspErrors.push_back(QSslError::OcspMalformedResponse);
+ return false;
+ }
+
+ OCSP_SINGLERESP *singleResponse = q_OCSP_resp_get0(basicResponse, 0);
+ if (!singleResponse) {
+ ocspErrors.clear();
+ // A fatal problem -> SslHandshakeError.
+ ocspErrorDescription = QSslSocket::tr("Failed to decode a SingleResponse from OCSP status response");
+ return false;
+ }
+
+ // Let's make sure the response is for the correct certificate - we
+ // can re-create this CertID using our peer's certificate and its
+ // issuer's public key.
+ ocspResponses.push_back(QOcspResponse());
+ QOcspResponsePrivate *dResponse = ocspResponses.back().d.data();
+ dResponse->subjectCert = configuration.peerCertificate;
+ bool matchFound = false;
+ if (configuration.peerCertificate.isSelfSigned()) {
+ dResponse->signerCert = configuration.peerCertificate;
+ matchFound = qt_OCSP_certificate_match(singleResponse, peerX509, peerX509);
+ } else {
+ const STACK_OF(X509) *certs = q_SSL_get_peer_cert_chain(ssl);
+ if (!certs) // Oh, what a cataclysm! Last try:
+ certs = q_OCSP_resp_get0_certs(basicResponse);
+ if (certs) {
+ // It could be the first certificate in 'certs' is our peer's
+ // certificate. Since it was not captured by the 'self-signed' branch
+ // above, the CertID will not match and we'll just iterate on to the
+ // next certificate. So we start from 0, not 1.
+ for (int i = 0, e = q_sk_X509_num(certs); i < e; ++i) {
+ X509 *issuer = q_sk_X509_value(certs, i);
+ matchFound = qt_OCSP_certificate_match(singleResponse, peerX509, issuer);
+ if (matchFound) {
+ if (q_X509_check_issued(issuer, peerX509) == X509_V_OK) {
+ dResponse->signerCert = QSslCertificatePrivate::QSslCertificate_from_X509(issuer);
+ break;
+ }
+ matchFound = false;
+ }
+ }
+ }
+ }
+
+ if (!matchFound) {
+ dResponse->signerCert.clear();
+ ocspErrors.push_back({QSslError::OcspResponseCertIdUnknown, configuration.peerCertificate});
+ }
+
+ // Check if the response is valid time-wise:
+ ASN1_GENERALIZEDTIME *revTime = nullptr;
+ ASN1_GENERALIZEDTIME *thisUpdate = nullptr;
+ ASN1_GENERALIZEDTIME *nextUpdate = nullptr;
+ int reason;
+ const int certStatus = q_OCSP_single_get0_status(singleResponse, &reason, &revTime, &thisUpdate, &nextUpdate);
+ if (!thisUpdate) {
+ // This is unexpected, treat as SslHandshakeError, OCSP_check_validity assumes this pointer
+ // to be != nullptr.
+ ocspErrors.clear();
+ ocspResponses.clear();
+ ocspErrorDescription = QSslSocket::tr("Failed to extract 'this update time' from the SingleResponse");
+ return false;
+ }
+
+ // OCSP_check_validity(this, next, nsec, maxsec) does this check:
+ // this <= now <= next. They allow some freedom to account
+ // for delays/time inaccuracy.
+ // this > now + nsec ? -> NOT_YET_VALID
+ // if maxsec >= 0:
+ // now - maxsec > this ? -> TOO_OLD
+ // now - nsec > next ? -> EXPIRED
+ // next < this ? -> NEXT_BEFORE_THIS
+ // OK.
+ if (!q_OCSP_check_validity(thisUpdate, nextUpdate, 60, -1))
+ ocspErrors.push_back({QSslError::OcspResponseExpired, configuration.peerCertificate});
+
+ // And finally, the status:
+ switch (certStatus) {
+ case V_OCSP_CERTSTATUS_GOOD:
+ // This certificate was not found among the revoked ones.
+ dResponse->certificateStatus = QOcspCertificateStatus::Good;
+ break;
+ case V_OCSP_CERTSTATUS_REVOKED:
+ dResponse->certificateStatus = QOcspCertificateStatus::Revoked;
+ dResponse->revocationReason = qt_OCSP_revocation_reason(reason);
+ ocspErrors.push_back({QSslError::CertificateRevoked, configuration.peerCertificate});
+ break;
+ case V_OCSP_CERTSTATUS_UNKNOWN:
+ dResponse->certificateStatus = QOcspCertificateStatus::Unknown;
+ ocspErrors.push_back({QSslError::OcspStatusUnknown, configuration.peerCertificate});
+ }
+
+ return !ocspErrors.size();
+}
+
+#endif // ocsp
+
void QSslSocketBackendPrivate::disconnectFromHost()
{
if (ssl) {
diff --git a/src/network/ssl/qsslsocket_openssl11.cpp b/src/network/ssl/qsslsocket_openssl11.cpp
index 2a2667bd48..b60b8be41f 100644
--- a/src/network/ssl/qsslsocket_openssl11.cpp
+++ b/src/network/ssl/qsslsocket_openssl11.cpp
@@ -122,21 +122,7 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
#if QT_CONFIG(library)
//load symbols needed to receive certificates from system store
-#if defined(Q_OS_WIN)
- HINSTANCE hLib = LoadLibraryW(L"Crypt32");
- if (hLib) {
- ptrCertOpenSystemStoreW = reinterpret_cast<PtrCertOpenSystemStoreW>(
- reinterpret_cast<QFunctionPointer>(GetProcAddress(hLib, "CertOpenSystemStoreW")));
- ptrCertFindCertificateInStore = reinterpret_cast<PtrCertFindCertificateInStore>(
- reinterpret_cast<QFunctionPointer>(GetProcAddress(hLib, "CertFindCertificateInStore")));
- ptrCertCloseStore = reinterpret_cast<PtrCertCloseStore>(
- reinterpret_cast<QFunctionPointer>(GetProcAddress(hLib, "CertCloseStore")));
- if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
- qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
- } else {
- qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
- }
-#elif defined(Q_OS_QNX)
+#if defined(Q_OS_QNX)
s_loadRootCertsOnDemand = true;
#elif defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
// check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
diff --git a/src/network/ssl/qsslsocket_openssl11_symbols_p.h b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
index 0c32b0a934..0fe0899d4f 100644
--- a/src/network/ssl/qsslsocket_openssl11_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
@@ -82,14 +82,15 @@ Q_AUTOTEST_EXPORT const BIO_METHOD *q_BIO_s_mem();
int q_DSA_bits(DSA *a);
int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c);
+Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref(EVP_PKEY *a);
int q_EVP_PKEY_base_id(EVP_PKEY *a);
int q_RSA_bits(RSA *a);
-int q_OPENSSL_sk_num(OPENSSL_STACK *a);
-void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
-OPENSSL_STACK *q_OPENSSL_sk_new_null();
-void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
-void q_OPENSSL_sk_free(OPENSSL_STACK *a);
-void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
+Q_AUTOTEST_EXPORT int q_OPENSSL_sk_num(OPENSSL_STACK *a);
+Q_AUTOTEST_EXPORT void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
+Q_AUTOTEST_EXPORT OPENSSL_STACK *q_OPENSSL_sk_new_null();
+Q_AUTOTEST_EXPORT void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
+Q_AUTOTEST_EXPORT void q_OPENSSL_sk_free(OPENSSL_STACK *a);
+Q_AUTOTEST_EXPORT void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
int q_SSL_session_reused(SSL *a);
unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
@@ -102,6 +103,7 @@ const SSL_METHOD *q_TLS_server_method();
ASN1_TIME *q_X509_getm_notBefore(X509 *a);
ASN1_TIME *q_X509_getm_notAfter(X509 *a);
+Q_AUTOTEST_EXPORT void q_X509_up_ref(X509 *a);
long q_X509_get_version(X509 *a);
EVP_PKEY *q_X509_get_pubkey(X509 *a);
void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb);
@@ -174,6 +176,10 @@ void q_BIO_set_init(BIO *a, int init);
int q_BIO_get_shutdown(BIO *a);
void q_BIO_set_shutdown(BIO *a, int shut);
+#if QT_CONFIG(ocsp)
+const OCSP_CERTID *q_OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x);
+#endif // ocsp
+
#define q_SSL_CTX_set_min_proto_version(ctx, version) \
q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, nullptr)
diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
index c16b9d5f76..c23234e291 100644
--- a/src/network/ssl/qsslsocket_openssl_p.h
+++ b/src/network/ssl/qsslsocket_openssl_p.h
@@ -69,6 +69,9 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qsslsocket_p.h"
+#include <QtCore/qvector.h>
+#include <QtCore/qstring.h>
+
#ifdef Q_OS_WIN
#include <qt_windows.h>
#if defined(OCSP_RESPONSE)
@@ -152,6 +155,16 @@ public:
void _q_caRootLoaded(QSslCertificate,QSslCertificate) override;
#endif
+#if QT_CONFIG(ocsp)
+ bool checkOcspStatus();
+#endif
+
+ // This decription will go to setErrorAndEmit(SslHandshakeError, ocspErrorDescription)
+ QString ocspErrorDescription;
+ // These will go to sslErrors()
+ QVector<QSslError> ocspErrors;
+ QByteArray ocspResponseDer;
+
Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
static QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher);
static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 483a2cbad0..2eb9763e90 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -150,6 +150,7 @@ DEFINEFUNC(BIO *, BIO_new, const BIO_METHOD *a, a, return nullptr, return)
DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return nullptr, return)
DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
DEFINEFUNC(int, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX *c, c, return 0, return)
+DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *a, a, return 0, return)
DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return)
DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return)
DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return)
@@ -173,6 +174,7 @@ DEFINEFUNC2(unsigned long, SSL_set_options, SSL *ssl, ssl, unsigned long op, op,
DEFINEFUNC(const SSL_METHOD *, TLS_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, TLS_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(void, X509_up_ref, X509 *a, a, return, DUMMYARG)
DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return nullptr, return)
DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return nullptr, return)
DEFINEFUNC(long, X509_get_version, X509 *a, a, return -1, return)
@@ -202,6 +204,35 @@ DEFINEFUNC2(int, BIO_meth_set_create, BIO_METHOD *biom, biom, DgramCreateCallbac
DEFINEFUNC2(int, BIO_meth_set_destroy, BIO_METHOD *biom, biom, DgramDestroyCallback dtr, dtr, return 0, return)
#endif // dtls
+#if QT_CONFIG(ocsp)
+DEFINEFUNC(const OCSP_CERTID *, OCSP_SINGLERESP_get0_id, const OCSP_SINGLERESP *x, x, return nullptr, return)
+DEFINEFUNC3(OCSP_RESPONSE *, d2i_OCSP_RESPONSE, OCSP_RESPONSE **a, a, const unsigned char **in, in, long len, len, return nullptr, return)
+DEFINEFUNC(void, OCSP_RESPONSE_free, OCSP_RESPONSE *rs, rs, return, DUMMYARG)
+DEFINEFUNC(OCSP_BASICRESP *, OCSP_response_get1_basic, OCSP_RESPONSE *resp, resp, return nullptr, return)
+DEFINEFUNC(void, OCSP_BASICRESP_free, OCSP_BASICRESP *bs, bs, return, DUMMYARG)
+DEFINEFUNC(int, OCSP_response_status, OCSP_RESPONSE *resp, resp, return OCSP_RESPONSE_STATUS_INTERNALERROR, return)
+DEFINEFUNC4(int, OCSP_basic_verify, OCSP_BASICRESP *bs, bs, STACK_OF(X509) *certs, certs, X509_STORE *st, st, unsigned long flags, flags, return -1, return)
+DEFINEFUNC(int, OCSP_resp_count, OCSP_BASICRESP *bs, bs, return 0, return)
+DEFINEFUNC2(OCSP_SINGLERESP *, OCSP_resp_get0, OCSP_BASICRESP *bs, bs, int idx, idx, return nullptr, return)
+DEFINEFUNC5(int, OCSP_single_get0_status, OCSP_SINGLERESP *single, single, int *reason, reason, ASN1_GENERALIZEDTIME **revtime, revtime,
+ ASN1_GENERALIZEDTIME **thisupd, thisupd, ASN1_GENERALIZEDTIME **nextupd, nextupd, return -1, return)
+DEFINEFUNC4(int, OCSP_check_validity, ASN1_GENERALIZEDTIME *thisupd, thisupd, ASN1_GENERALIZEDTIME *nextupd, nextupd, long nsec, nsec, long maxsec, maxsec, return 0, return)
+DEFINEFUNC3(OCSP_CERTID *, OCSP_cert_to_id, const EVP_MD *dgst, dgst, X509 *subject, subject, X509 *issuer, issuer, return nullptr, return)
+DEFINEFUNC(void, OCSP_CERTID_free, OCSP_CERTID *cid, cid, return, DUMMYARG)
+DEFINEFUNC5(int, OCSP_id_get0_info, ASN1_OCTET_STRING **piNameHash, piNameHash, ASN1_OBJECT **pmd, pmd,
+ ASN1_OCTET_STRING **piKeyHash, piKeyHash, ASN1_INTEGER **pserial, pserial, OCSP_CERTID *cid, cid,
+ return 0, return)
+DEFINEFUNC2(OCSP_RESPONSE *, OCSP_response_create, int status, status, OCSP_BASICRESP *bs, bs, return nullptr, return)
+DEFINEFUNC(const STACK_OF(X509) *, OCSP_resp_get0_certs, const OCSP_BASICRESP *bs, bs, return nullptr, return)
+DEFINEFUNC2(int, OCSP_id_cmp, OCSP_CERTID *a, a, OCSP_CERTID *b, b, return -1, return)
+DEFINEFUNC7(OCSP_SINGLERESP *, OCSP_basic_add1_status, OCSP_BASICRESP *r, r, OCSP_CERTID *c, c, int s, s,
+ int re, re, ASN1_TIME *rt, rt, ASN1_TIME *t, t, ASN1_TIME *n, n, return nullptr, return)
+DEFINEFUNC(OCSP_BASICRESP *, OCSP_BASICRESP_new, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC2(int, i2d_OCSP_RESPONSE, OCSP_RESPONSE *r, r, unsigned char **ppout, ppout, return 0, return)
+DEFINEFUNC6(int, OCSP_basic_sign, OCSP_BASICRESP *br, br, X509 *signer, signer, EVP_PKEY *key, key,
+ const EVP_MD *dg, dg, STACK_OF(X509) *cs, cs, unsigned long flags, flags, return 0, return)
+#endif // ocsp
+
DEFINEFUNC2(void, BIO_set_data, BIO *a, a, void *ptr, ptr, return, DUMMYARG)
DEFINEFUNC(void *, BIO_get_data, BIO *a, a, return nullptr, return)
DEFINEFUNC2(void, BIO_set_init, BIO *a, a, int init, init, return, DUMMYARG)
@@ -240,17 +271,10 @@ DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO
DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return nullptr, return)
-#else
-DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return)
-DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG)
-DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
-DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return nullptr, return)
-#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L
DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
@@ -259,49 +283,18 @@ DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
-#endif
DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
-#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
-#endif
DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
-#else
-#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
-#endif
-DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
-DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
-#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
-#endif
-DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
-DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
-#endif
DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return nullptr, return)
@@ -334,6 +327,7 @@ DEFINEFUNC(const char *, SSLeay_version, int a, a, return nullptr, return)
#endif // QT_CONFIG(opensslv11)
DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return)
+DEFINEFUNC2(int, ASN1_INTEGER_cmp, const ASN1_INTEGER *a, a, const ASN1_INTEGER *b, b, return 1, return)
DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return)
DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return)
DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return)
@@ -362,6 +356,7 @@ DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *typ
DEFINEFUNC6(int, EVP_CipherInit_ex, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *cipher, cipher, ENGINE *impl, impl, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return)
DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return)
DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return)
+DEFINEFUNC(const EVP_MD *, EVP_get_digestbyname, const char *name, name, return nullptr, return)
#ifndef OPENSSL_NO_DES
DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return nullptr, return)
@@ -369,16 +364,24 @@ DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return null
#ifndef OPENSSL_NO_RC2
DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
+#ifndef OPENSSL_NO_AES
+DEFINEFUNC(const EVP_CIPHER *, EVP_aes_128_cbc, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const EVP_CIPHER *, EVP_aes_192_cbc, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const EVP_CIPHER *, EVP_aes_256_cbc, DUMMYARG, DUMMYARG, return nullptr, return)
+#endif
DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return)
DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return)
DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return)
+DEFINEFUNC2(int, EVP_PKEY_set1_DH, EVP_PKEY *a, a, DH *b, b, return -1, return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC2(int, EVP_PKEY_set1_EC_KEY, EVP_PKEY *a, a, EC_KEY *b, b, return -1, return)
#endif
+DEFINEFUNC2(int, EVP_PKEY_cmp, const EVP_PKEY *a, a, const EVP_PKEY *b, b, return -1, return)
DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG)
DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return nullptr, return)
DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return nullptr, return)
+DEFINEFUNC(DH *, EVP_PKEY_get1_DH, EVP_PKEY *a, a, return nullptr, return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return nullptr, return)
#endif
@@ -404,6 +407,7 @@ DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_p
DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
+DEFINEFUNC7(int, PEM_write_bio_PrivateKey, BIO *a, a, EVP_PKEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
#endif
@@ -416,6 +420,7 @@ DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_pass
#endif
DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return)
DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return)
+DEFINEFUNC2(int, PEM_write_bio_PUBKEY, BIO *a, a, EVP_PKEY *b, b, return 0, return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return)
#endif
@@ -433,12 +438,9 @@ DEFINEFUNC(int, SSL_connect, SSL *a, a, return -1, return)
DEFINEFUNC(int, SSL_CTX_check_private_key, const SSL_CTX *a, a, return -1, return)
DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return)
DEFINEFUNC(void, SSL_CTX_free, SSL_CTX *a, a, return, DUMMYARG)
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return nullptr, return)
-#else
-DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return nullptr, return)
-#endif
DEFINEFUNC2(int, SSL_CTX_set_cipher_list, SSL_CTX *a, a, const char *b, b, return -1, return)
+DEFINEFUNC3(long, SSL_CTX_callback_ctrl, SSL_CTX *ctx, ctx, int dst, dst, GenericCallbackType cb, cb, return 0, return)
DEFINEFUNC(int, SSL_CTX_set_default_verify_paths, SSL_CTX *a, a, return -1, return)
DEFINEFUNC3(void, SSL_CTX_set_verify, SSL_CTX *a, a, int b, b, int (*c)(int, X509_STORE_CTX *), c, return, DUMMYARG)
DEFINEFUNC2(void, SSL_CTX_set_verify_depth, SSL_CTX *a, a, int b, b, return, DUMMYARG)
@@ -458,22 +460,14 @@ DEFINEFUNC3(int, SSL_CONF_cmd, SSL_CONF_CTX *a, a, const char *b, b, const char
#endif
DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG)
DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return nullptr, return)
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr, return)
-#else
-DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr, return)
-#endif
DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return)
DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return nullptr, return)
DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return nullptr, return)
-#if OPENSSL_VERSION_NUMBER >= 0x00908000L
-// 0.9.8 broke SC and BC by changing this function's signature.
DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return)
-#else
-DEFINEFUNC(long, SSL_get_verify_result, SSL *a, a, return -1, return)
-#endif
DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return nullptr, return)
+DEFINEFUNC(SSL_CTX *, SSL_get_SSL_CTX, SSL *a, a, return nullptr, return)
DEFINEFUNC4(long, SSL_ctrl, SSL *a, a, int cmd, cmd, long larg, larg, void *parg, parg, return -1, return)
DEFINEFUNC3(int, SSL_read, SSL *a, a, void *b, b, int c, c, return -1, return)
DEFINEFUNC3(void, SSL_set_bio, SSL *a, a, BIO *b, b, BIO *c, c, return, DUMMYARG)
@@ -503,6 +497,9 @@ DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return nullptr, return)
DEFINEFUNC2(void, X509_print, BIO *a, a, X509 *b, b, return, DUMMYARG);
DEFINEFUNC(ASN1_OBJECT *, X509_EXTENSION_get_object, X509_EXTENSION *a, a, return nullptr, return)
DEFINEFUNC(void, X509_free, X509 *a, a, return, DUMMYARG)
+//Q_AUTOTEST_EXPORT ASN1_TIME *q_X509_gmtime_adj(ASN1_TIME *s, long adj);
+DEFINEFUNC2(ASN1_TIME *, X509_gmtime_adj, ASN1_TIME *s, s, long adj, adj, return nullptr, return)
+DEFINEFUNC(void, ASN1_TIME_free, ASN1_TIME *t, t, return, DUMMYARG)
DEFINEFUNC2(X509_EXTENSION *, X509_get_ext, X509 *a, a, int b, b, return nullptr, return)
DEFINEFUNC(int, X509_get_ext_count, X509 *a, a, return 0, return)
DEFINEFUNC4(void *, X509_get_ext_d2i, X509 *a, a, int b, b, int *c, c, int *d, d, return nullptr, return)
@@ -513,11 +510,7 @@ DEFINEFUNC(ASN1_OCTET_STRING *, X509_EXTENSION_get_data, X509_EXTENSION *a, a, r
DEFINEFUNC(void, BASIC_CONSTRAINTS_free, BASIC_CONSTRAINTS *a, a, return, DUMMYARG)
DEFINEFUNC(void, AUTHORITY_KEYID_free, AUTHORITY_KEYID *a, a, return, DUMMYARG)
DEFINEFUNC(void, GENERAL_NAME_free, GENERAL_NAME *a, a, return, DUMMYARG)
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, const ASN1_STRING *b, b, return 0, return)
-#else
-DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, ASN1_STRING *b, b, return 0, return)
-#endif
DEFINEFUNC2(int, X509_check_issued, X509 *a, a, X509 *b, b, return -1, return)
DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return nullptr, return)
DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return nullptr, return)
@@ -583,6 +576,7 @@ DEFINEFUNC2(void, BIO_clear_flags, BIO *b, b, int flags, flags, return, DUMMYARG
DEFINEFUNC2(void *, BIO_get_ex_data, BIO *b, b, int idx, idx, return nullptr, return)
DEFINEFUNC3(int, BIO_set_ex_data, BIO *b, b, int idx, idx, void *data, data, return -1, return)
+DEFINEFUNC3(void *, CRYPTO_malloc, size_t num, num, const char *file, file, int line, line, return nullptr, return)
DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG)
DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return)
@@ -705,7 +699,7 @@ static QStringList libraryPathList()
// discover paths of already loaded libraries
QSet<QString> loadedPaths;
dl_iterate_phdr(dlIterateCallback, &loadedPaths);
- paths.append(loadedPaths.toList());
+ paths.append(loadedPaths.values());
#endif
return paths;
@@ -974,6 +968,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(OPENSSL_init_crypto)
RESOLVEFUNC(ASN1_STRING_get0_data)
RESOLVEFUNC(EVP_CIPHER_CTX_reset)
+ RESOLVEFUNC(EVP_PKEY_up_ref)
RESOLVEFUNC(EVP_PKEY_base_id)
RESOLVEFUNC(RSA_bits)
RESOLVEFUNC(OPENSSL_sk_new_null)
@@ -997,6 +992,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(TLS_method)
RESOLVEFUNC(TLS_client_method)
RESOLVEFUNC(TLS_server_method)
+ RESOLVEFUNC(X509_up_ref)
RESOLVEFUNC(X509_STORE_CTX_get0_chain)
RESOLVEFUNC(X509_getm_notBefore)
RESOLVEFUNC(X509_getm_notAfter)
@@ -1034,7 +1030,30 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(BIO_meth_set_create)
RESOLVEFUNC(BIO_meth_set_destroy)
#endif // dtls
-
+#if QT_CONFIG(ocsp)
+ RESOLVEFUNC(OCSP_SINGLERESP_get0_id)
+ RESOLVEFUNC(d2i_OCSP_RESPONSE)
+ RESOLVEFUNC(OCSP_RESPONSE_free)
+ RESOLVEFUNC(OCSP_response_status)
+ RESOLVEFUNC(OCSP_response_get1_basic)
+ RESOLVEFUNC(OCSP_BASICRESP_free)
+ RESOLVEFUNC(OCSP_basic_verify)
+ RESOLVEFUNC(OCSP_resp_count)
+ RESOLVEFUNC(OCSP_resp_get0)
+ RESOLVEFUNC(OCSP_single_get0_status)
+ RESOLVEFUNC(OCSP_check_validity)
+ RESOLVEFUNC(OCSP_cert_to_id)
+ RESOLVEFUNC(OCSP_id_get0_info)
+ RESOLVEFUNC(OCSP_resp_get0_certs)
+ RESOLVEFUNC(OCSP_basic_sign)
+ RESOLVEFUNC(OCSP_response_create)
+ RESOLVEFUNC(i2d_OCSP_RESPONSE)
+ RESOLVEFUNC(OCSP_basic_add1_status)
+ RESOLVEFUNC(OCSP_BASICRESP_new)
+ RESOLVEFUNC(OCSP_CERTID_free)
+ RESOLVEFUNC(OCSP_cert_to_id)
+ RESOLVEFUNC(OCSP_id_cmp)
+#endif // ocsp
RESOLVEFUNC(BIO_set_data)
RESOLVEFUNC(BIO_get_data)
RESOLVEFUNC(BIO_set_init)
@@ -1075,24 +1094,12 @@ bool q_resolveOpenSslSymbols()
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
RESOLVEFUNC(SSL_get_ex_new_index)
#endif
-#ifndef OPENSSL_NO_SSL2
- RESOLVEFUNC(SSLv2_client_method)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
- RESOLVEFUNC(SSLv3_client_method)
-#endif
RESOLVEFUNC(SSLv23_client_method)
RESOLVEFUNC(TLSv1_client_method)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
RESOLVEFUNC(TLSv1_1_client_method)
RESOLVEFUNC(TLSv1_2_client_method)
#endif
-#ifndef OPENSSL_NO_SSL2
- RESOLVEFUNC(SSLv2_server_method)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
- RESOLVEFUNC(SSLv3_server_method)
-#endif
RESOLVEFUNC(SSLv23_server_method)
RESOLVEFUNC(TLSv1_server_method)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
@@ -1143,6 +1150,7 @@ bool q_resolveOpenSslSymbols()
#endif // !opensslv11
RESOLVEFUNC(ASN1_INTEGER_get)
+ RESOLVEFUNC(ASN1_INTEGER_cmp)
RESOLVEFUNC(ASN1_STRING_length)
RESOLVEFUNC(ASN1_STRING_to_UTF8)
RESOLVEFUNC(BIO_ctrl)
@@ -1179,6 +1187,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(EVP_CipherInit_ex)
RESOLVEFUNC(EVP_CipherUpdate)
RESOLVEFUNC(EVP_CipherFinal)
+ RESOLVEFUNC(EVP_get_digestbyname)
#ifndef OPENSSL_NO_DES
RESOLVEFUNC(EVP_des_cbc)
RESOLVEFUNC(EVP_des_ede3_cbc)
@@ -1186,16 +1195,24 @@ bool q_resolveOpenSslSymbols()
#ifndef OPENSSL_NO_RC2
RESOLVEFUNC(EVP_rc2_cbc)
#endif
+#ifndef OPENSSL_NO_AES
+ RESOLVEFUNC(EVP_aes_128_cbc)
+ RESOLVEFUNC(EVP_aes_192_cbc)
+ RESOLVEFUNC(EVP_aes_256_cbc)
+#endif
RESOLVEFUNC(EVP_sha1)
RESOLVEFUNC(EVP_PKEY_assign)
RESOLVEFUNC(EVP_PKEY_set1_RSA)
RESOLVEFUNC(EVP_PKEY_set1_DSA)
+ RESOLVEFUNC(EVP_PKEY_set1_DH)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(EVP_PKEY_set1_EC_KEY)
#endif
+ RESOLVEFUNC(EVP_PKEY_cmp)
RESOLVEFUNC(EVP_PKEY_free)
RESOLVEFUNC(EVP_PKEY_get1_DSA)
RESOLVEFUNC(EVP_PKEY_get1_RSA)
+ RESOLVEFUNC(EVP_PKEY_get1_DH)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(EVP_PKEY_get1_EC_KEY)
#endif
@@ -1219,6 +1236,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(PEM_read_bio_DHparams)
RESOLVEFUNC(PEM_write_bio_DSAPrivateKey)
RESOLVEFUNC(PEM_write_bio_RSAPrivateKey)
+ RESOLVEFUNC(PEM_write_bio_PrivateKey)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(PEM_write_bio_ECPrivateKey)
#endif
@@ -1232,6 +1250,7 @@ bool q_resolveOpenSslSymbols()
#endif
RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY)
RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY)
+ RESOLVEFUNC(PEM_write_bio_PUBKEY)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(PEM_write_bio_EC_PUBKEY)
#endif
@@ -1248,6 +1267,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_CTX_free)
RESOLVEFUNC(SSL_CTX_new)
RESOLVEFUNC(SSL_CTX_set_cipher_list)
+ RESOLVEFUNC(SSL_CTX_callback_ctrl)
RESOLVEFUNC(SSL_CTX_set_default_verify_paths)
RESOLVEFUNC(SSL_CTX_set_verify)
RESOLVEFUNC(SSL_CTX_set_verify_depth)
@@ -1277,6 +1297,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_get_peer_certificate)
RESOLVEFUNC(SSL_get_verify_result)
RESOLVEFUNC(SSL_new)
+ RESOLVEFUNC(SSL_get_SSL_CTX)
RESOLVEFUNC(SSL_ctrl)
RESOLVEFUNC(SSL_read)
RESOLVEFUNC(SSL_set_accept_state)
@@ -1325,6 +1346,8 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(X509_digest)
RESOLVEFUNC(X509_EXTENSION_get_object)
RESOLVEFUNC(X509_free)
+ RESOLVEFUNC(X509_gmtime_adj)
+ RESOLVEFUNC(ASN1_TIME_free)
RESOLVEFUNC(X509_get_ext)
RESOLVEFUNC(X509_get_ext_count)
RESOLVEFUNC(X509_get_ext_d2i)
@@ -1362,6 +1385,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(DTLS_server_method)
RESOLVEFUNC(DTLS_client_method)
#endif // dtls
+ RESOLVEFUNC(CRYPTO_malloc)
RESOLVEFUNC(DH_new)
RESOLVEFUNC(DH_free)
RESOLVEFUNC(d2i_DHparams)
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 3143117621..69b2b90fbd 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -72,6 +72,10 @@
#include "qsslsocket_openssl_p.h"
#include <QtCore/qglobal.h>
+#if QT_CONFIG(ocsp)
+#include "qocsp_p.h"
+#endif
+
QT_BEGIN_NAMESPACE
#define DUMMYARG
@@ -224,6 +228,7 @@ QT_BEGIN_NAMESPACE
bool q_resolveOpenSslSymbols();
long q_ASN1_INTEGER_get(ASN1_INTEGER *a);
+int q_ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y);
int q_ASN1_STRING_length(ASN1_STRING *a);
int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b);
long q_BIO_ctrl(BIO *a, int b, long c, void *d);
@@ -267,6 +272,8 @@ int q_EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned
int q_EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc);
int q_EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);
int q_EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+const EVP_MD *q_EVP_get_digestbyname(const char *name);
+
#ifndef OPENSSL_NO_DES
const EVP_CIPHER *q_EVP_des_cbc();
const EVP_CIPHER *q_EVP_des_ede3_cbc();
@@ -274,16 +281,24 @@ const EVP_CIPHER *q_EVP_des_ede3_cbc();
#ifndef OPENSSL_NO_RC2
const EVP_CIPHER *q_EVP_rc2_cbc();
#endif
-const EVP_MD *q_EVP_sha1();
+#ifndef OPENSSL_NO_AES
+const EVP_CIPHER *q_EVP_aes_128_cbc();
+const EVP_CIPHER *q_EVP_aes_192_cbc();
+const EVP_CIPHER *q_EVP_aes_256_cbc();
+#endif
+Q_AUTOTEST_EXPORT const EVP_MD *q_EVP_sha1();
int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c);
Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b);
-int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
+Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
+Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_DH(EVP_PKEY *a, DH *b);
#ifndef OPENSSL_NO_EC
-int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b);
+Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b);
#endif
-void q_EVP_PKEY_free(EVP_PKEY *a);
+Q_AUTOTEST_EXPORT int q_EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
+Q_AUTOTEST_EXPORT void q_EVP_PKEY_free(EVP_PKEY *a);
RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a);
DSA *q_EVP_PKEY_get1_DSA(EVP_PKEY *a);
+DH *q_EVP_PKEY_get1_DH(EVP_PKEY *a);
#ifndef OPENSSL_NO_EC
EC_KEY *q_EVP_PKEY_get1_EC_KEY(EVP_PKEY *a);
#endif
@@ -297,6 +312,7 @@ int q_OBJ_ln2nid(const char *s);
int q_i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *obj);
int q_OBJ_obj2txt(char *buf, int buf_len, ASN1_OBJECT *obj, int no_name);
int q_OBJ_obj2nid(const ASN1_OBJECT *a);
+#define q_EVP_get_digestbynid(a) q_EVP_get_digestbyname(q_OBJ_nid2sn(a))
#ifdef SSLEAY_MACROS
// ### verify
void *q_PEM_ASN1_read_bio(d2i_of_void *a, const char *b, BIO *c, void **d, pem_password_cb *e,
@@ -314,6 +330,8 @@ int q_PEM_write_bio_DSAPrivateKey(BIO *a, DSA *b, const EVP_CIPHER *c, unsigned
int e, pem_password_cb *f, void *g);
int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned char *d,
int e, pem_password_cb *f, void *g);
+int q_PEM_write_bio_PrivateKey(BIO *a, EVP_PKEY *b, const EVP_CIPHER *c, unsigned char *d,
+ int e, pem_password_cb *f, void *g);
#ifndef OPENSSL_NO_EC
int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigned char *d,
int e, pem_password_cb *f, void *g);
@@ -327,6 +345,7 @@ EC_KEY *q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d
#endif
int q_PEM_write_bio_DSA_PUBKEY(BIO *a, DSA *b);
int q_PEM_write_bio_RSA_PUBKEY(BIO *a, RSA *b);
+int q_PEM_write_bio_PUBKEY(BIO *a, EVP_PKEY *b);
#ifndef OPENSSL_NO_EC
int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b);
#endif
@@ -344,15 +363,15 @@ int q_SSL_connect(SSL *a);
int q_SSL_CTX_check_private_key(const SSL_CTX *a);
long q_SSL_CTX_ctrl(SSL_CTX *a, int b, long c, void *d);
void q_SSL_CTX_free(SSL_CTX *a);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
SSL_CTX *q_SSL_CTX_new(const SSL_METHOD *a);
-#else
-SSL_CTX *q_SSL_CTX_new(SSL_METHOD *a);
-#endif
int q_SSL_CTX_set_cipher_list(SSL_CTX *a, const char *b);
int q_SSL_CTX_set_default_verify_paths(SSL_CTX *a);
void q_SSL_CTX_set_verify(SSL_CTX *a, int b, int (*c)(int, X509_STORE_CTX *));
void q_SSL_CTX_set_verify_depth(SSL_CTX *a, int b);
+extern "C" {
+typedef void (*GenericCallbackType)();
+}
+long q_SSL_CTX_callback_ctrl(SSL_CTX *, int, GenericCallbackType);
int q_SSL_CTX_use_certificate(SSL_CTX *a, X509 *b);
int q_SSL_CTX_use_certificate_file(SSL_CTX *a, const char *b, int c);
int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b);
@@ -369,17 +388,14 @@ int q_SSL_CONF_cmd(SSL_CONF_CTX *a, const char *b, const char *c);
#endif
void q_SSL_free(SSL *a);
STACK_OF(SSL_CIPHER) *q_SSL_get_ciphers(const SSL *a);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
-#else
-SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
-#endif
int q_SSL_version(const SSL *a);
int q_SSL_get_error(SSL *a, int b);
STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a);
X509 *q_SSL_get_peer_certificate(SSL *a);
long q_SSL_get_verify_result(const SSL *a);
SSL *q_SSL_new(SSL_CTX *a);
+SSL_CTX *q_SSL_get_SSL_CTX(SSL *a);
long q_SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
int q_SSL_read(SSL *a, void *b, int c);
void q_SSL_set_bio(SSL *a, BIO *b, BIO *c);
@@ -414,7 +430,9 @@ X509 *q_X509_dup(X509 *a);
void q_X509_print(BIO *a, X509*b);
int q_X509_digest(const X509 *x509, const EVP_MD *type, unsigned char *md, unsigned int *len);
ASN1_OBJECT *q_X509_EXTENSION_get_object(X509_EXTENSION *a);
-void q_X509_free(X509 *a);
+Q_AUTOTEST_EXPORT void q_X509_free(X509 *a);
+Q_AUTOTEST_EXPORT ASN1_TIME *q_X509_gmtime_adj(ASN1_TIME *s, long adj);
+Q_AUTOTEST_EXPORT void q_ASN1_TIME_free(ASN1_TIME *t);
X509_EXTENSION *q_X509_get_ext(X509 *a, int b);
int q_X509_get_ext_count(X509 *a);
void *q_X509_get_ext_d2i(X509 *a, int b, int *c, int *d);
@@ -424,11 +442,7 @@ int q_X509_EXTENSION_get_critical(X509_EXTENSION *a);
ASN1_OCTET_STRING *q_X509_EXTENSION_get_data(X509_EXTENSION *a);
void q_BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *a);
void q_AUTHORITY_KEYID_free(AUTHORITY_KEYID *a);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
int q_ASN1_STRING_print(BIO *a, const ASN1_STRING *b);
-#else
-int q_ASN1_STRING_print(BIO *a, ASN1_STRING *b);
-#endif
int q_X509_check_issued(X509 *a, X509 *b);
X509_NAME *q_X509_get_issuer_name(X509 *a);
X509_NAME *q_X509_get_subject_name(X509 *a);
@@ -572,6 +586,57 @@ int q_BIO_set_ex_data(BIO *b, int idx, void *data);
class QDateTime;
QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime);
+#ifndef OPENSSL_NO_TLSEXT
+
+#define q_SSL_set_tlsext_status_type(ssl, type) \
+ q_SSL_ctrl((ssl), SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE, (type), nullptr)
+
+#endif // OPENSSL_NO_TLSEXT
+
+#if QT_CONFIG(ocsp)
+
+OCSP_RESPONSE *q_d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len);
+Q_AUTOTEST_EXPORT int q_i2d_OCSP_RESPONSE(OCSP_RESPONSE *r, unsigned char **ppout);
+Q_AUTOTEST_EXPORT OCSP_RESPONSE *q_OCSP_response_create(int status, OCSP_BASICRESP *bs);
+Q_AUTOTEST_EXPORT void q_OCSP_RESPONSE_free(OCSP_RESPONSE *rs);
+int q_OCSP_response_status(OCSP_RESPONSE *resp);
+OCSP_BASICRESP *q_OCSP_response_get1_basic(OCSP_RESPONSE *resp);
+Q_AUTOTEST_EXPORT OCSP_SINGLERESP *q_OCSP_basic_add1_status(OCSP_BASICRESP *rsp, OCSP_CERTID *cid,
+ int status, int reason, ASN1_TIME *revtime,
+ ASN1_TIME *thisupd, ASN1_TIME *nextupd);
+Q_AUTOTEST_EXPORT int q_OCSP_basic_sign(OCSP_BASICRESP *brsp, X509 *signer, EVP_PKEY *key, const EVP_MD *dgst,
+ STACK_OF(X509) *certs, unsigned long flags);
+Q_AUTOTEST_EXPORT OCSP_BASICRESP *q_OCSP_BASICRESP_new();
+Q_AUTOTEST_EXPORT void q_OCSP_BASICRESP_free(OCSP_BASICRESP *bs);
+int q_OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags);
+int q_OCSP_resp_count(OCSP_BASICRESP *bs);
+OCSP_SINGLERESP *q_OCSP_resp_get0(OCSP_BASICRESP *bs, int idx);
+int q_OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, ASN1_GENERALIZEDTIME **revtime,
+ ASN1_GENERALIZEDTIME **thisupd, ASN1_GENERALIZEDTIME **nextupd);
+int q_OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long nsec, long maxsec);
+int q_OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, ASN1_OCTET_STRING **pikeyHash,
+ ASN1_INTEGER **pserial, OCSP_CERTID *cid);
+
+const STACK_OF(X509) *q_OCSP_resp_get0_certs(const OCSP_BASICRESP *bs);
+Q_AUTOTEST_EXPORT OCSP_CERTID *q_OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
+Q_AUTOTEST_EXPORT void q_OCSP_CERTID_free(OCSP_CERTID *cid);
+int q_OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+
+#define q_SSL_get_tlsext_status_ocsp_resp(ssl, arg) \
+ q_SSL_ctrl(ssl, SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP, 0, arg)
+
+#define q_SSL_CTX_set_tlsext_status_cb(ssl, cb) \
+ q_SSL_CTX_callback_ctrl(ssl, SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB, GenericCallbackType(cb))
+
+# define q_SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \
+ q_SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP, arglen, arg)
+
+#endif // ocsp
+
+
+void *q_CRYPTO_malloc(size_t num, const char *file, int line);
+#define q_OPENSSL_malloc(num) q_CRYPTO_malloc(num, "", 0)
+
QT_END_NAMESPACE
#endif
diff --git a/src/network/ssl/qsslsocket_opensslpre11.cpp b/src/network/ssl/qsslsocket_opensslpre11.cpp
index bc4fd9dc85..f5aab821ea 100644
--- a/src/network/ssl/qsslsocket_opensslpre11.cpp
+++ b/src/network/ssl/qsslsocket_opensslpre11.cpp
@@ -251,21 +251,7 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
#if QT_CONFIG(library)
//load symbols needed to receive certificates from system store
-#if defined(Q_OS_WIN)
- HINSTANCE hLib = LoadLibraryW(L"Crypt32");
- if (hLib) {
- ptrCertOpenSystemStoreW = reinterpret_cast<PtrCertOpenSystemStoreW>(
- reinterpret_cast<QFunctionPointer>(GetProcAddress(hLib, "CertOpenSystemStoreW")));
- ptrCertFindCertificateInStore = reinterpret_cast<PtrCertFindCertificateInStore>(
- reinterpret_cast<QFunctionPointer>(GetProcAddress(hLib, "CertFindCertificateInStore")));
- ptrCertCloseStore = reinterpret_cast<PtrCertCloseStore>(
- reinterpret_cast<QFunctionPointer>(GetProcAddress(hLib, "CertCloseStore")));
- if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
- qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
- } else {
- qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
- }
-#elif defined(Q_OS_QNX)
+#if defined(Q_OS_QNX)
s_loadRootCertsOnDemand = true;
#elif defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
// check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
diff --git a/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h b/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h
index 48364ceb1d..f5626d5d16 100644
--- a/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h
+++ b/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h
@@ -91,9 +91,7 @@ void q_ERR_free_strings();
void q_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
void q_EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
typedef _STACK STACK;
-#endif
// The typedef we use to make our pre 1.1 code look more like 1.1 (less ifdefs).
typedef STACK OPENSSL_STACK;
@@ -113,22 +111,13 @@ void q_sk_free(STACK *a);
// address of this:
#define q_OPENSSL_sk_free q_sk_free
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
void *q_sk_value(STACK *a, int b);
void q_sk_push(STACK *st, void *data);
-#else
-char *q_sk_value(STACK *a, int b);
-void q_sk_push(STACK *st, char *data);
-#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L
#define q_OPENSSL_sk_value(a, b) q_sk_value(a, b)
#define q_OPENSSL_sk_push(st, data) q_sk_push(st, data)
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
SSL_CTX *q_SSL_CTX_new(const SSL_METHOD *a);
-#else
-SSL_CTX *q_SSL_CTX_new(SSL_METHOD *a);
-#endif
int q_SSL_library_init();
void q_SSL_load_error_strings();
@@ -137,49 +126,14 @@ void q_SSL_load_error_strings();
int q_SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-#ifndef OPENSSL_NO_SSL2
-const SSL_METHOD *q_SSLv2_client_method();
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-const SSL_METHOD *q_SSLv3_client_method();
-#endif
const SSL_METHOD *q_SSLv23_client_method();
const SSL_METHOD *q_TLSv1_client_method();
const SSL_METHOD *q_TLSv1_1_client_method();
const SSL_METHOD *q_TLSv1_2_client_method();
-#ifndef OPENSSL_NO_SSL2
-const SSL_METHOD *q_SSLv2_server_method();
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-const SSL_METHOD *q_SSLv3_server_method();
-#endif
const SSL_METHOD *q_SSLv23_server_method();
const SSL_METHOD *q_TLSv1_server_method();
const SSL_METHOD *q_TLSv1_1_server_method();
const SSL_METHOD *q_TLSv1_2_server_method();
-#else
-#ifndef OPENSSL_NO_SSL2
-SSL_METHOD *q_SSLv2_client_method();
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-SSL_METHOD *q_SSLv3_client_method();
-#endif
-SSL_METHOD *q_SSLv23_client_method();
-SSL_METHOD *q_TLSv1_client_method();
-SSL_METHOD *q_TLSv1_1_client_method();
-SSL_METHOD *q_TLSv1_2_client_method();
-#ifndef OPENSSL_NO_SSL2
-SSL_METHOD *q_SSLv2_server_method();
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-SSL_METHOD *q_SSLv3_server_method();
-#endif
-SSL_METHOD *q_SSLv23_server_method();
-SSL_METHOD *q_TLSv1_server_method();
-SSL_METHOD *q_TLSv1_1_server_method();
-SSL_METHOD *q_TLSv1_2_server_method();
-#endif
STACK_OF(X509) *q_X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
@@ -220,6 +174,7 @@ DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
#define q_SSL_SESSION_get_ticket_lifetime_hint(s) ((s)->tlsext_tick_lifetime_hint)
#define q_RSA_bits(rsa) q_BN_num_bits((rsa)->n)
#define q_DSA_bits(dsa) q_BN_num_bits((dsa)->p)
+#define q_DH_bits(dsa) q_BN_num_bits((dh)->p)
#define q_X509_STORE_set_verify_cb(s,c) X509_STORE_set_verify_cb_func((s),(c))
char *q_CONF_get1_default_config_file();
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index 6f34c6c888..daa9be23f4 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -58,6 +58,7 @@
#include <private/qtcpsocket_p.h>
#include "qsslkey.h"
#include "qsslconfiguration_p.h"
+#include "qocspresponse.h"
#ifndef QT_NO_OPENSSL
#include <private/qsslcontext_openssl_p.h>
#else
@@ -65,7 +66,7 @@ class QSslContext;
#endif
#include <QtCore/qstringlist.h>
-
+#include <QtCore/qvector.h>
#include <private/qringbuffer_p.h>
#if defined(Q_OS_MAC)
@@ -89,14 +90,6 @@ QT_BEGIN_NAMESPACE
typedef OSStatus (*PtrSecTrustCopyAnchorCertificates)(CFArrayRef*);
#endif
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
- typedef HCERTSTORE (WINAPI *PtrCertOpenSystemStoreW)(HCRYPTPROV_LEGACY, LPCWSTR);
- typedef PCCERT_CONTEXT (WINAPI *PtrCertFindCertificateInStore)(HCERTSTORE, DWORD, DWORD, DWORD, const void*, PCCERT_CONTEXT);
- typedef BOOL (WINAPI *PtrCertCloseStore)(HCERTSTORE, DWORD);
-#endif // Q_OS_WIN && !Q_OS_WINRT
-
-
-
class QSslSocketPrivate : public QTcpSocketPrivate
{
Q_DECLARE_PUBLIC(QSslSocket)
@@ -105,6 +98,7 @@ public:
virtual ~QSslSocketPrivate();
void init();
+ bool verifyProtocolSupported(const char *where);
bool initialized;
QSslSocket::SslMode mode;
@@ -155,12 +149,6 @@ public:
const QString &peerName);
Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname);
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
- static PtrCertOpenSystemStoreW ptrCertOpenSystemStoreW;
- static PtrCertFindCertificateInStore ptrCertFindCertificateInStore;
- static PtrCertCloseStore ptrCertCloseStore;
-#endif // Q_OS_WIN && !Q_OS_WINRT
-
// The socket itself, including private slots.
QTcpSocket *plainSocket;
void createPlainSocket(QIODevice::OpenMode openMode);
@@ -184,7 +172,7 @@ public:
void _q_flushWriteBuffer();
void _q_flushReadBuffer();
void _q_resumeImplementation();
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !QT_CONFIG(schannel)
virtual void _q_caRootLoaded(QSslCertificate,QSslCertificate) = 0;
#endif
@@ -220,8 +208,14 @@ protected:
bool verifyErrorsHaveBeenIgnored();
bool paused;
bool flushTriggered;
+ QVector<QOcspResponse> ocspResponses;
};
+#if QT_CONFIG(securetransport) || QT_CONFIG(schannel)
+// Implemented in qsslsocket_qt.cpp
+QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase);
+#endif
+
QT_END_NAMESPACE
#endif
diff --git a/src/network/ssl/qsslsocket_qt.cpp b/src/network/ssl/qsslsocket_qt.cpp
new file mode 100644
index 0000000000..b0fb60ea76
--- /dev/null
+++ b/src/network/ssl/qsslsocket_qt.cpp
@@ -0,0 +1,307 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore/qbytearray.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmessageauthenticationcode.h>
+
+#include "qsslsocket_p.h"
+#include "qasn1element_p.h"
+#include "qsslkey_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ PKCS12 helpers.
+*/
+
+static QAsn1Element wrap(quint8 type, const QAsn1Element &child)
+{
+ QByteArray value;
+ QDataStream stream(&value, QIODevice::WriteOnly);
+ child.write(stream);
+ return QAsn1Element(type, value);
+}
+
+static QAsn1Element _q_PKCS7_data(const QByteArray &data)
+{
+ QVector<QAsn1Element> items;
+ items << QAsn1Element::fromObjectId("1.2.840.113549.1.7.1");
+ items << wrap(QAsn1Element::Context0Type,
+ QAsn1Element(QAsn1Element::OctetStringType, data));
+ return QAsn1Element::fromVector(items);
+}
+
+/*!
+ PKCS #12 key derivation.
+
+ Some test vectors:
+ http://www.drh-consultancy.demon.co.uk/test.txt
+*/
+static QByteArray _q_PKCS12_keygen(char id, const QByteArray &salt, const QString &passPhrase, int n, int r)
+{
+ const int u = 20;
+ const int v = 64;
+
+ // password formatting
+ QByteArray passUnicode(passPhrase.size() * 2 + 2, '\0');
+ char *p = passUnicode.data();
+ for (int i = 0; i < passPhrase.size(); ++i) {
+ quint16 ch = passPhrase[i].unicode();
+ *(p++) = (ch & 0xff00) >> 8;
+ *(p++) = (ch & 0xff);
+ }
+
+ // prepare I
+ QByteArray D(64, id);
+ QByteArray S, P;
+ const int sSize = v * ((salt.size() + v - 1) / v);
+ S.resize(sSize);
+ for (int i = 0; i < sSize; ++i)
+ S[i] = salt[i % salt.size()];
+ const int pSize = v * ((passUnicode.size() + v - 1) / v);
+ P.resize(pSize);
+ for (int i = 0; i < pSize; ++i)
+ P[i] = passUnicode[i % passUnicode.size()];
+ QByteArray I = S + P;
+
+ // apply hashing
+ const int c = (n + u - 1) / u;
+ QByteArray A;
+ QByteArray B;
+ B.resize(v);
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ for (int i = 0; i < c; ++i) {
+ // hash r iterations
+ QByteArray Ai = D + I;
+ for (int j = 0; j < r; ++j) {
+ hash.reset();
+ hash.addData(Ai);
+ Ai = hash.result();
+ }
+
+ for (int j = 0; j < v; ++j)
+ B[j] = Ai[j % u];
+
+ // modify I as Ij = (Ij + B + 1) modulo 2^v
+ for (int p = 0; p < I.size(); p += v) {
+ quint8 carry = 1;
+ for (int j = v - 1; j >= 0; --j) {
+ quint16 v = quint8(I[p + j]) + quint8(B[j]) + carry;
+ I[p + j] = v & 0xff;
+ carry = (v & 0xff00) >> 8;
+ }
+ }
+ A += Ai;
+ }
+ return A.left(n);
+}
+
+static QByteArray _q_PKCS12_salt()
+{
+ QByteArray salt;
+ salt.resize(8);
+ for (int i = 0; i < salt.size(); ++i)
+ salt[i] = (qrand() & 0xff);
+ return salt;
+}
+
+static QByteArray _q_PKCS12_certBag(const QSslCertificate &cert)
+{
+ QVector<QAsn1Element> items;
+ items << QAsn1Element::fromObjectId("1.2.840.113549.1.12.10.1.3");
+
+ // certificate
+ QVector<QAsn1Element> certItems;
+ certItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.22.1");
+ certItems << wrap(QAsn1Element::Context0Type,
+ QAsn1Element(QAsn1Element::OctetStringType, cert.toDer()));
+ items << wrap(QAsn1Element::Context0Type,
+ QAsn1Element::fromVector(certItems));
+
+ // local key id
+ const QByteArray localKeyId = cert.digest(QCryptographicHash::Sha1);
+ QVector<QAsn1Element> idItems;
+ idItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.21");
+ idItems << wrap(QAsn1Element::SetType,
+ QAsn1Element(QAsn1Element::OctetStringType, localKeyId));
+ items << wrap(QAsn1Element::SetType, QAsn1Element::fromVector(idItems));
+
+ // dump
+ QAsn1Element root = wrap(QAsn1Element::SequenceType, QAsn1Element::fromVector(items));
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ root.write(stream);
+ return ba;
+}
+
+static QAsn1Element _q_PKCS12_key(const QSslKey &key)
+{
+ Q_ASSERT(key.algorithm() == QSsl::Rsa || key.algorithm() == QSsl::Dsa);
+
+ QVector<QAsn1Element> keyItems;
+ keyItems << QAsn1Element::fromInteger(0);
+ QVector<QAsn1Element> algoItems;
+ if (key.algorithm() == QSsl::Rsa)
+ algoItems << QAsn1Element::fromObjectId(RSA_ENCRYPTION_OID);
+ else if (key.algorithm() == QSsl::Dsa)
+ algoItems << QAsn1Element::fromObjectId(DSA_ENCRYPTION_OID);
+ algoItems << QAsn1Element(QAsn1Element::NullType);
+ keyItems << QAsn1Element::fromVector(algoItems);
+ keyItems << QAsn1Element(QAsn1Element::OctetStringType, key.toDer());
+ return QAsn1Element::fromVector(keyItems);
+}
+
+static QByteArray _q_PKCS12_shroudedKeyBag(const QSslKey &key, const QString &passPhrase, const QByteArray &localKeyId)
+{
+ const int iterations = 2048;
+ QByteArray salt = _q_PKCS12_salt();
+ QByteArray cKey = _q_PKCS12_keygen(1, salt, passPhrase, 24, iterations);
+ QByteArray cIv = _q_PKCS12_keygen(2, salt, passPhrase, 8, iterations);
+
+ // prepare and encrypt data
+ QByteArray plain;
+ QDataStream plainStream(&plain, QIODevice::WriteOnly);
+ _q_PKCS12_key(key).write(plainStream);
+ QByteArray crypted = QSslKeyPrivate::encrypt(QSslKeyPrivate::DesEde3Cbc,
+ plain, cKey, cIv);
+
+ QVector<QAsn1Element> items;
+ items << QAsn1Element::fromObjectId("1.2.840.113549.1.12.10.1.2");
+
+ // key
+ QVector<QAsn1Element> keyItems;
+ QVector<QAsn1Element> algoItems;
+ algoItems << QAsn1Element::fromObjectId("1.2.840.113549.1.12.1.3");
+ QVector<QAsn1Element> paramItems;
+ paramItems << QAsn1Element(QAsn1Element::OctetStringType, salt);
+ paramItems << QAsn1Element::fromInteger(iterations);
+ algoItems << QAsn1Element::fromVector(paramItems);
+ keyItems << QAsn1Element::fromVector(algoItems);
+ keyItems << QAsn1Element(QAsn1Element::OctetStringType, crypted);
+ items << wrap(QAsn1Element::Context0Type,
+ QAsn1Element::fromVector(keyItems));
+
+ // local key id
+ QVector<QAsn1Element> idItems;
+ idItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.21");
+ idItems << wrap(QAsn1Element::SetType,
+ QAsn1Element(QAsn1Element::OctetStringType, localKeyId));
+ items << wrap(QAsn1Element::SetType,
+ QAsn1Element::fromVector(idItems));
+
+ // dump
+ QAsn1Element root = wrap(QAsn1Element::SequenceType, QAsn1Element::fromVector(items));
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ root.write(stream);
+ return ba;
+}
+
+static QByteArray _q_PKCS12_bag(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase)
+{
+ QVector<QAsn1Element> items;
+
+ // certs
+ for (int i = 0; i < certs.size(); ++i)
+ items << _q_PKCS7_data(_q_PKCS12_certBag(certs[i]));
+
+ // key
+ if (!key.isNull()) {
+ const QByteArray localKeyId = certs.first().digest(QCryptographicHash::Sha1);
+ items << _q_PKCS7_data(_q_PKCS12_shroudedKeyBag(key, passPhrase, localKeyId));
+ }
+
+ // dump
+ QAsn1Element root = QAsn1Element::fromVector(items);
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ root.write(stream);
+ return ba;
+}
+
+static QAsn1Element _q_PKCS12_mac(const QByteArray &data, const QString &passPhrase)
+{
+ const int iterations = 2048;
+
+ // salt generation
+ QByteArray macSalt = _q_PKCS12_salt();
+ QByteArray key = _q_PKCS12_keygen(3, macSalt, passPhrase, 20, iterations);
+
+ // HMAC calculation
+ QMessageAuthenticationCode hmac(QCryptographicHash::Sha1, key);
+ hmac.addData(data);
+
+ QVector<QAsn1Element> algoItems;
+ algoItems << QAsn1Element::fromObjectId("1.3.14.3.2.26");
+ algoItems << QAsn1Element(QAsn1Element::NullType);
+
+ QVector<QAsn1Element> digestItems;
+ digestItems << QAsn1Element::fromVector(algoItems);
+ digestItems << QAsn1Element(QAsn1Element::OctetStringType, hmac.result());
+
+ QVector<QAsn1Element> macItems;
+ macItems << QAsn1Element::fromVector(digestItems);
+ macItems << QAsn1Element(QAsn1Element::OctetStringType, macSalt);
+ macItems << QAsn1Element::fromInteger(iterations);
+ return QAsn1Element::fromVector(macItems);
+}
+
+QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase)
+{
+ QVector<QAsn1Element> items;
+
+ // version
+ items << QAsn1Element::fromInteger(3);
+
+ // auth safe
+ const QByteArray data = _q_PKCS12_bag(certs, key, passPhrase);
+ items << _q_PKCS7_data(data);
+
+ // HMAC
+ items << _q_PKCS12_mac(data, passPhrase);
+
+ // dump
+ QAsn1Element root = QAsn1Element::fromVector(items);
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ root.write(stream);
+ return ba;
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket_schannel.cpp b/src/network/ssl/qsslsocket_schannel.cpp
new file mode 100644
index 0000000000..1314b432a4
--- /dev/null
+++ b/src/network/ssl/qsslsocket_schannel.cpp
@@ -0,0 +1,1994 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// #define QSSLSOCKET_DEBUG
+
+#include "qssl_p.h"
+#include "qsslsocket.h"
+#include "qsslsocket_schannel_p.h"
+#include "qsslcertificate.h"
+#include "qsslcertificateextension.h"
+#include "qsslcertificate_p.h"
+#include "qsslcipher_p.h"
+
+#include <QtCore/qscopeguard.h>
+#include <QtCore/qoperatingsystemversion.h>
+#include <QtCore/qregularexpression.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmutex.h>
+
+#define SECURITY_WIN32
+#include <security.h>
+#include <schnlsp.h>
+
+#if NTDDI_VERSION >= NTDDI_WINBLUE && !defined(Q_CC_MINGW)
+// ALPN = Application Layer Protocol Negotiation
+#define SUPPORTS_ALPN 1
+#endif
+
+// Not defined in MinGW
+#ifndef SECBUFFER_ALERT
+#define SECBUFFER_ALERT 17
+#endif
+#ifndef SECPKG_ATTR_APPLICATION_PROTOCOL
+#define SECPKG_ATTR_APPLICATION_PROTOCOL 35
+#endif
+
+// Another missing MinGW define
+#ifndef SEC_E_APPLICATION_PROTOCOL_MISMATCH
+#define SEC_E_APPLICATION_PROTOCOL_MISMATCH _HRESULT_TYPEDEF_(0x80090367L)
+#endif
+
+// Also not defined in MinGW.......
+#ifndef SP_PROT_TLS1_SERVER
+#define SP_PROT_TLS1_SERVER 0x00000040
+#endif
+#ifndef SP_PROT_TLS1_CLIENT
+#define SP_PROT_TLS1_CLIENT 0x00000080
+#endif
+#ifndef SP_PROT_TLS1_0_SERVER
+#define SP_PROT_TLS1_0_SERVER SP_PROT_TLS1_SERVER
+#endif
+#ifndef SP_PROT_TLS1_0_CLIENT
+#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT
+#endif
+#ifndef SP_PROT_TLS1_0
+#define SP_PROT_TLS1_0 (SP_PROT_TLS1_0_CLIENT | SP_PROT_TLS1_0_SERVER)
+#endif
+#ifndef SP_PROT_TLS1_1_SERVER
+#define SP_PROT_TLS1_1_SERVER 0x00000100
+#endif
+#ifndef SP_PROT_TLS1_1_CLIENT
+#define SP_PROT_TLS1_1_CLIENT 0x00000200
+#endif
+#ifndef SP_PROT_TLS1_1
+#define SP_PROT_TLS1_1 (SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_1_SERVER)
+#endif
+#ifndef SP_PROT_TLS1_2_SERVER
+#define SP_PROT_TLS1_2_SERVER 0x00000400
+#endif
+#ifndef SP_PROT_TLS1_2_CLIENT
+#define SP_PROT_TLS1_2_CLIENT 0x00000800
+#endif
+#ifndef SP_PROT_TLS1_2
+#define SP_PROT_TLS1_2 (SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_2_SERVER)
+#endif
+#ifndef SP_PROT_TLS1_3_SERVER
+#define SP_PROT_TLS1_3_SERVER 0x00001000
+#endif
+#ifndef SP_PROT_TLS1_3_CLIENT
+#define SP_PROT_TLS1_3_CLIENT 0x00002000
+#endif
+#ifndef SP_PROT_TLS1_3
+#define SP_PROT_TLS1_3 (SP_PROT_TLS1_3_CLIENT | SP_PROT_TLS1_3_SERVER)
+#endif
+
+/*
+ @future!:
+
+ - Transmitting intermediate certificates
+ - Look for a way to avoid putting intermediate certificates in the certificate store
+ - No documentation on how to send the chain
+ - A stackoverflow question on this from 3 years ago implies schannel only sends intermediate
+ certificates if it's "in the system or user certificate store".
+ - https://stackoverflow.com/q/30156584/2493610
+ - This can be done by users, but we shouldn't add any and all local intermediate
+ certs to the stores automatically.
+ - PSK support
+ - Was added in Windows 10 (it seems), documentation at time of writing is sparse/non-existent.
+ - Specifically about how to supply credentials when they're requested.
+ - Or how to recognize that they're requested in the first place.
+ - Skip certificate verification.
+ - Check if "PSK-only" is still required to do PSK _at all_ (all-around bad solution).
+ - Check if SEC_I_INCOMPLETE_CREDENTIALS is still returned for both "missing certificate" and
+ "missing PSK" when calling InitializeSecurityContext in "performHandshake".
+
+ Medium priority:
+ - Setting cipher-suites (or ALG_ID)
+ - People have survived without it in WinRT
+
+ Low priority:
+ - Possibly make RAII wrappers for SecBuffer (which I commonly create QScopeGuards for)
+
+*/
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+SecBuffer createSecBuffer(void *ptr, unsigned long length, unsigned long bufferType)
+{
+ return SecBuffer{ length, bufferType, ptr };
+}
+
+SecBuffer createSecBuffer(QByteArray &buffer, unsigned long bufferType)
+{
+ return createSecBuffer(buffer.data(), static_cast<unsigned long>(buffer.length()), bufferType);
+}
+
+QString schannelErrorToString(qint32 status)
+{
+ switch (status) {
+ case SEC_E_INSUFFICIENT_MEMORY:
+ return QSslSocket::tr("Insufficient memory");
+ case SEC_E_INTERNAL_ERROR:
+ return QSslSocket::tr("Internal error");
+ case SEC_E_INVALID_HANDLE:
+ return QSslSocket::tr("An internal handle was invalid");
+ case SEC_E_INVALID_TOKEN:
+ return QSslSocket::tr("An internal token was invalid");
+ case SEC_E_LOGON_DENIED:
+ // According to the link below we get this error when Schannel receives TLS1_ALERT_ACCESS_DENIED
+ // https://docs.microsoft.com/en-us/windows/desktop/secauthn/schannel-error-codes-for-tls-and-ssl-alerts
+ return QSslSocket::tr("Access denied");
+ case SEC_E_NO_AUTHENTICATING_AUTHORITY:
+ return QSslSocket::tr("No authority could be contacted for authorization");
+ case SEC_E_NO_CREDENTIALS:
+ return QSslSocket::tr("No credentials");
+ case SEC_E_TARGET_UNKNOWN:
+ return QSslSocket::tr("The target is unknown or unreachable");
+ case SEC_E_UNSUPPORTED_FUNCTION:
+ return QSslSocket::tr("An unsupported function was requested");
+ case SEC_E_WRONG_PRINCIPAL:
+ // SNI error
+ return QSslSocket::tr("The hostname provided does not match the one received from the peer");
+ case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
+ return QSslSocket::tr("No common protocol exists between the client and the server");
+ case SEC_E_ILLEGAL_MESSAGE:
+ return QSslSocket::tr("Unexpected or badly-formatted message received");
+ case SEC_E_ENCRYPT_FAILURE:
+ return QSslSocket::tr("The data could not be encrypted");
+ case SEC_E_ALGORITHM_MISMATCH:
+ return QSslSocket::tr("No cipher suites in common");
+ case SEC_E_UNKNOWN_CREDENTIALS:
+ // This can mean "invalid argument" in some cases...
+ return QSslSocket::tr("The credentials were not recognized / Invalid argument");
+ case SEC_E_MESSAGE_ALTERED:
+ // According to the Internet it also triggers for messages that are out of order.
+ // https://microsoft.public.platformsdk.security.narkive.com/4JAvlMvD/help-please-schannel-security-contexts-and-decryptmessage
+ return QSslSocket::tr("The message was tampered with, damaged or out of sequence.");
+ case SEC_E_OUT_OF_SEQUENCE:
+ return QSslSocket::tr("A message was received out of sequence.");
+ case SEC_E_CONTEXT_EXPIRED:
+ return QSslSocket::tr("The TLS/SSL connection has been closed");
+ default:
+ return QSslSocket::tr("Unknown error occurred: %1").arg(status);
+ }
+}
+
+DWORD toSchannelProtocol(QSsl::SslProtocol protocol)
+{
+ DWORD protocols = SP_PROT_NONE;
+ switch (protocol) {
+ case QSsl::UnknownProtocol:
+ return DWORD(-1);
+ case QSsl::DtlsV1_0:
+ case QSsl::DtlsV1_2:
+ case QSsl::DtlsV1_0OrLater:
+ case QSsl::DtlsV1_2OrLater:
+ return DWORD(-1); // Not supported at the moment (@future)
+ case QSsl::AnyProtocol:
+ protocols = SP_PROT_TLS1_0 | SP_PROT_TLS1_1 | SP_PROT_TLS1_2;
+ // @future Add TLS 1.3 when supported by Windows!
+ break;
+ case QSsl::SslV2:
+ case QSsl::SslV3:
+ return DWORD(-1); // Not supported
+ case QSsl::TlsV1SslV3:
+ protocols = SP_PROT_TLS1_0;
+ break;
+ case QSsl::TlsV1_0:
+ protocols = SP_PROT_TLS1_0;
+ break;
+ case QSsl::TlsV1_1:
+ protocols = SP_PROT_TLS1_1;
+ break;
+ case QSsl::TlsV1_2:
+ protocols = SP_PROT_TLS1_2;
+ break;
+ case QSsl::TlsV1_3:
+ if ((false)) // @future[0/1] Replace with version check once it's supported in Windows
+ protocols = SP_PROT_TLS1_3;
+ else
+ protocols = DWORD(-1);
+ break;
+ case QSsl::SecureProtocols: // TLS v1.0 and later is currently considered secure
+ case QSsl::TlsV1_0OrLater:
+ // For the "OrLater" protocols we fall through from one to the next, adding all of them
+ // in ascending order
+ protocols = SP_PROT_TLS1_0;
+ Q_FALLTHROUGH();
+ case QSsl::TlsV1_1OrLater:
+ protocols |= SP_PROT_TLS1_1;
+ Q_FALLTHROUGH();
+ case QSsl::TlsV1_2OrLater:
+ protocols |= SP_PROT_TLS1_2;
+ Q_FALLTHROUGH();
+ case QSsl::TlsV1_3OrLater:
+ if ((false)) // @future[1/1] Also replace this with a version check
+ protocols |= SP_PROT_TLS1_3;
+ else if (protocol == QSsl::TlsV1_3OrLater)
+ protocols = DWORD(-1); // if TlsV1_3OrLater was specifically chosen we should fail
+ break;
+ }
+ return protocols;
+}
+
+/*!
+ \internal
+ Used when converting the established session's \a protocol back to
+ Qt's own SslProtocol type.
+
+ Only one protocol should be passed in at a time.
+*/
+QSsl::SslProtocol toQtSslProtocol(DWORD protocol)
+{
+#define MAP_PROTOCOL(sp_protocol, q_protocol) \
+ if (protocol & sp_protocol) { \
+ Q_ASSERT(!(protocol & ~sp_protocol)); \
+ return q_protocol; \
+ }
+
+ MAP_PROTOCOL(SP_PROT_TLS1_0, QSsl::TlsV1_0)
+ MAP_PROTOCOL(SP_PROT_TLS1_1, QSsl::TlsV1_1)
+ MAP_PROTOCOL(SP_PROT_TLS1_2, QSsl::TlsV1_2)
+ MAP_PROTOCOL(SP_PROT_TLS1_3, QSsl::TlsV1_3)
+#undef MAP_PROTOCOL
+ Q_UNREACHABLE();
+ return QSsl::UnknownProtocol;
+}
+
+/*!
+ \internal
+ Used by verifyCertContext to check if a client cert is used by a server or vice versa.
+*/
+bool netscapeWrongCertType(const QList<QSslCertificateExtension> &extensions, bool isClient)
+{
+ const auto netscapeIt = std::find_if(
+ extensions.cbegin(), extensions.cend(),
+ [](const QSslCertificateExtension &extension) {
+ const auto netscapeCertType = QStringLiteral("2.16.840.1.113730.1.1");
+ return extension.oid() == netscapeCertType;
+ });
+ if (netscapeIt != extensions.cend()) {
+ const QByteArray netscapeCertTypeByte = netscapeIt->value().toByteArray();
+ int netscapeCertType = 0;
+ QDataStream dataStream(netscapeCertTypeByte);
+ dataStream >> netscapeCertType;
+ if (dataStream.status() != QDataStream::Status::Ok)
+ return true;
+ const int expectedPeerCertType = isClient ? NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE
+ : NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE;
+ if ((netscapeCertType & expectedPeerCertType) == 0)
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \internal
+ Used by verifyCertContext to check the basicConstraints certificate
+ extension to see if the certificate is a certificate authority.
+ Returns false if the certificate does not have the basicConstraints
+ extension or if it is not a certificate authority.
+*/
+bool isCertificateAuthority(const QList<QSslCertificateExtension> &extensions)
+{
+ auto it = std::find_if(extensions.cbegin(), extensions.cend(),
+ [](const QSslCertificateExtension &extension) {
+ return extension.name() == QLatin1String("basicConstraints");
+ });
+ if (it != extensions.cend()) {
+ QVariantMap basicConstraints = it->value().toMap();
+ return basicConstraints.value(QLatin1String("ca"), false).toBool();
+ }
+ return false;
+}
+
+/*!
+ \internal
+ Returns true if the attributes we requested from the context/handshake have
+ been given.
+*/
+bool matchesContextRequirements(DWORD attributes, DWORD requirements,
+ QSslSocket::PeerVerifyMode verifyMode,
+ bool isClient)
+{
+#ifdef QSSLSOCKET_DEBUG
+#define DEBUG_WARN(message) qCWarning(lcSsl, message)
+#else
+#define DEBUG_WARN(message)
+#endif
+
+#define CHECK_ATTRIBUTE(attributeName) \
+ do { \
+ const DWORD req##attributeName = isClient ? ISC_REQ_##attributeName : ASC_REQ_##attributeName; \
+ const DWORD ret##attributeName = isClient ? ISC_RET_##attributeName : ASC_RET_##attributeName; \
+ if (!(requirements & req##attributeName) != !(attributes & ret##attributeName)) { \
+ DEBUG_WARN("Missing attribute \"" #attributeName "\""); \
+ return false; \
+ } \
+ } while (false)
+
+ CHECK_ATTRIBUTE(CONFIDENTIALITY);
+ CHECK_ATTRIBUTE(REPLAY_DETECT);
+ CHECK_ATTRIBUTE(SEQUENCE_DETECT);
+ CHECK_ATTRIBUTE(STREAM);
+ if (verifyMode == QSslSocket::PeerVerifyMode::VerifyPeer)
+ CHECK_ATTRIBUTE(MUTUAL_AUTH);
+
+ // This one is manual because there is no server / ASC_ version
+ if (isClient) {
+ const auto reqManualCredValidation = ISC_REQ_MANUAL_CRED_VALIDATION;
+ const auto retManualCredValidation = ISC_RET_MANUAL_CRED_VALIDATION;
+ if (!(requirements & reqManualCredValidation) != !(attributes & retManualCredValidation)) {
+ DEBUG_WARN("Missing attribute \"MANUAL_CRED_VALIDATION\"");
+ return false;
+ }
+ }
+
+ return true;
+#undef CHECK_ATTRIBUTE
+#undef DEBUG_WARN
+}
+
+template<typename Required, typename Actual>
+Required const_reinterpret_cast(Actual *p)
+{
+ return Required(p);
+}
+
+#ifdef SUPPORTS_ALPN
+bool supportsAlpn()
+{
+ return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8_1;
+}
+
+QByteArray createAlpnString(const QByteArrayList &nextAllowedProtocols)
+{
+ QByteArray alpnString;
+ if (!nextAllowedProtocols.isEmpty() && supportsAlpn()) {
+ const QByteArray names = [&nextAllowedProtocols]() {
+ QByteArray protocolString;
+ for (QByteArray proto : nextAllowedProtocols) {
+ if (proto.size() > 255) {
+ qCWarning(lcSsl) << "TLS ALPN extension" << proto
+ << "is too long and will be truncated to 255 characters.";
+ proto = proto.left(255);
+ }
+ protocolString += char(proto.length()) + proto;
+ }
+ return protocolString;
+ }();
+
+ const quint16 namesSize = names.size();
+ const quint32 alpnId = SecApplicationProtocolNegotiationExt_ALPN;
+ const quint32 totalSize = sizeof(alpnId) + sizeof(namesSize) + namesSize;
+ alpnString = QByteArray::fromRawData(reinterpret_cast<const char *>(&totalSize), sizeof(totalSize))
+ + QByteArray::fromRawData(reinterpret_cast<const char *>(&alpnId), sizeof(alpnId))
+ + QByteArray::fromRawData(reinterpret_cast<const char *>(&namesSize), sizeof(namesSize))
+ + names;
+ }
+ return alpnString;
+}
+#endif // SUPPORTS_ALPN
+} // anonymous namespace
+
+bool QSslSocketPrivate::s_loadRootCertsOnDemand = true;
+bool QSslSocketPrivate::s_loadedCiphersAndCerts = false;
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_schannel_mutex, (QMutex::Recursive))
+
+void QSslSocketPrivate::ensureInitialized()
+{
+ const QMutexLocker locker(qt_schannel_mutex);
+ if (s_loadedCiphersAndCerts)
+ return;
+ s_loadedCiphersAndCerts = true;
+
+ setDefaultCaCertificates(systemCaCertificates());
+ s_loadRootCertsOnDemand = true; // setDefaultCaCertificates sets it to false, re-enable it.
+
+ resetDefaultCiphers();
+}
+
+void QSslSocketPrivate::resetDefaultCiphers()
+{
+ setDefaultSupportedCiphers(QSslSocketBackendPrivate::defaultCiphers());
+ setDefaultCiphers(QSslSocketBackendPrivate::defaultCiphers());
+}
+
+void QSslSocketPrivate::resetDefaultEllipticCurves()
+{
+ Q_UNIMPLEMENTED();
+}
+
+bool QSslSocketPrivate::supportsSsl()
+{
+ return true;
+}
+
+QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
+{
+ // Copied from qsslsocket_openssl.cpp's systemCaCertificates function.
+ QList<QSslCertificate> systemCerts;
+ auto hSystemStore = QHCertStorePointer(CertOpenSystemStore(0, L"ROOT"));
+ if (hSystemStore) {
+ PCCERT_CONTEXT pc = nullptr;
+ while ((pc = CertFindCertificateInStore(hSystemStore.get(), X509_ASN_ENCODING, 0,
+ CERT_FIND_ANY, nullptr, pc))) {
+ systemCerts.append(QSslCertificatePrivate::QSslCertificate_from_CERT_CONTEXT(pc));
+ }
+ }
+ return systemCerts;
+}
+
+long QSslSocketPrivate::sslLibraryVersionNumber()
+{
+ const auto os = QOperatingSystemVersion::current();
+ return (os.majorVersion() << 24) | ((os.minorVersion() & 0xFF) << 16) | (os.microVersion() & 0xFFFF);
+}
+
+QString QSslSocketPrivate::sslLibraryVersionString()
+{
+ const auto os = QOperatingSystemVersion::current();
+ return QString::fromLatin1("Secure Channel, %1 %2.%3.%4")
+ .arg(os.name(),
+ QString::number(os.majorVersion()),
+ QString::number(os.minorVersion()),
+ QString::number(os.microVersion()));
+}
+
+long QSslSocketPrivate::sslLibraryBuildVersionNumber()
+{
+ // There is no separate build version
+ return sslLibraryVersionNumber();
+}
+
+QString QSslSocketPrivate::sslLibraryBuildVersionString()
+{
+ const auto os = QOperatingSystemVersion::current();
+ return QString::fromLatin1("%1.%2.%3")
+ .arg(QString::number(os.majorVersion()),
+ QString::number(os.minorVersion()),
+ QString::number(os.microVersion()));
+}
+
+QSslSocketBackendPrivate::QSslSocketBackendPrivate()
+{
+ SecInvalidateHandle(&credentialHandle);
+ SecInvalidateHandle(&contextHandle);
+ ensureInitialized();
+}
+
+QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
+{
+ closeCertificateStores();
+ deallocateContext();
+ freeCredentialsHandle();
+ CertFreeCertificateContext(localCertContext);
+}
+
+bool QSslSocketBackendPrivate::sendToken(void *token, unsigned long tokenLength, bool emitError)
+{
+ if (tokenLength == 0)
+ return true;
+ const qint64 written = plainSocket->write(static_cast<const char *>(token), tokenLength);
+ if (written != qint64(tokenLength)) {
+ // Failed to write/buffer everything or an error occurred
+ if (emitError)
+ setErrorAndEmit(plainSocket->error(), plainSocket->errorString());
+ return false;
+ }
+ return true;
+}
+
+QString QSslSocketBackendPrivate::targetName() const
+{
+ // Used for SNI extension
+ return verificationPeerName.isEmpty() ? q_func()->peerName() : verificationPeerName;
+}
+
+ULONG QSslSocketBackendPrivate::getContextRequirements()
+{
+ const bool isClient = mode == QSslSocket::SslClientMode;
+ ULONG req = 0;
+
+ req |= ISC_REQ_ALLOCATE_MEMORY; // Allocate memory for buffers automatically
+ req |= ISC_REQ_CONFIDENTIALITY; // Encrypt messages
+ req |= ISC_REQ_REPLAY_DETECT; // Detect replayed messages
+ req |= ISC_REQ_SEQUENCE_DETECT; // Detect out of sequence messages
+ req |= ISC_REQ_STREAM; // Support a stream-oriented connection
+
+ if (isClient) {
+ req |= ISC_REQ_MANUAL_CRED_VALIDATION; // Manually validate certificate
+ } else {
+ switch (configuration.peerVerifyMode) {
+ case QSslSocket::PeerVerifyMode::VerifyNone:
+ // There doesn't seem to be a way to ask for an optional client cert :-(
+ case QSslSocket::PeerVerifyMode::AutoVerifyPeer:
+ case QSslSocket::PeerVerifyMode::QueryPeer:
+ break;
+ case QSslSocket::PeerVerifyMode::VerifyPeer:
+ req |= ISC_REQ_MUTUAL_AUTH;
+ break;
+ }
+ }
+
+ return req;
+}
+
+bool QSslSocketBackendPrivate::acquireCredentialsHandle()
+{
+ Q_ASSERT(schannelState == SchannelState::InitializeHandshake);
+
+ const bool isClient = mode == QSslSocket::SslClientMode;
+ const DWORD protocols = toSchannelProtocol(configuration.protocol);
+ if (protocols == DWORD(-1)) {
+ setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
+ QSslSocket::tr("Invalid protocol chosen"));
+ return false;
+ }
+
+ const CERT_CHAIN_CONTEXT *chainContext = nullptr;
+ auto freeCertChain = qScopeGuard([&chainContext]() {
+ if (chainContext)
+ CertFreeCertificateChain(chainContext);
+ });
+
+ DWORD certsCount = 0;
+ // Set up our certificate stores before trying to use one...
+ initializeCertificateStores();
+
+ // Check if user has specified a certificate chain but it could not be loaded.
+ // This happens if there was something wrong with the certificate chain or there was no private
+ // key.
+ if (!configuration.localCertificateChain.isEmpty() && !localCertificateStore)
+ return true; // 'true' because "tst_QSslSocket::setEmptyKey" expects us to not disconnect
+
+ if (localCertificateStore != nullptr) {
+ CERT_CHAIN_FIND_BY_ISSUER_PARA findParam;
+ ZeroMemory(&findParam, sizeof(findParam));
+ findParam.cbSize = sizeof(findParam);
+ findParam.pszUsageIdentifier = isClient ? szOID_PKIX_KP_CLIENT_AUTH : szOID_PKIX_KP_SERVER_AUTH;
+
+ // There should only be one chain in our store, so.. we grab that one.
+ chainContext = CertFindChainInStore(localCertificateStore.get(),
+ X509_ASN_ENCODING,
+ 0,
+ CERT_CHAIN_FIND_BY_ISSUER,
+ &findParam,
+ nullptr);
+ if (!chainContext) {
+ const QString message = isClient
+ ? QSslSocket::tr("The certificate provided cannot be used for a client.")
+ : QSslSocket::tr("The certificate provided cannot be used for a server.");
+ setErrorAndEmit(QAbstractSocket::SocketError::SslInvalidUserDataError, message);
+ return false;
+ }
+ Q_ASSERT(chainContext->cChain == 1);
+ Q_ASSERT(chainContext->rgpChain[0]);
+ Q_ASSERT(chainContext->rgpChain[0]->cbSize >= 1);
+ Q_ASSERT(chainContext->rgpChain[0]->rgpElement[0]);
+ Q_ASSERT(!localCertContext);
+ localCertContext = CertDuplicateCertificateContext(chainContext->rgpChain[0]
+ ->rgpElement[0]
+ ->pCertContext);
+ certsCount = 1;
+ Q_ASSERT(localCertContext);
+ }
+
+ SCHANNEL_CRED cred{
+ SCHANNEL_CRED_VERSION, // dwVersion
+ certsCount, // cCreds
+ &localCertContext, // paCred (certificate(s) containing a private key for authentication)
+ nullptr, // hRootStore
+
+ 0, // cMappers (reserved)
+ nullptr, // aphMappers (reserved)
+
+ 0, // cSupportedAlgs
+ nullptr, // palgSupportedAlgs (nullptr = system default) @future: QSslCipher-related
+
+ protocols, // grbitEnabledProtocols
+ 0, // dwMinimumCipherStrength (0 = system default)
+ 0, // dwMaximumCipherStrength (0 = system default)
+ 0, // dwSessionLifespan (0 = schannel default, 10 hours)
+ SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
+ | SCH_CRED_NO_DEFAULT_CREDS, // dwFlags
+ 0 // dwCredFormat (must be 0)
+ };
+
+ TimeStamp expiration{};
+ auto status = AcquireCredentialsHandle(nullptr, // pszPrincipal (unused)
+ const_cast<wchar_t *>(UNISP_NAME), // pszPackage
+ isClient ? SECPKG_CRED_OUTBOUND : SECPKG_CRED_INBOUND, // fCredentialUse
+ nullptr, // pvLogonID (unused)
+ &cred, // pAuthData
+ nullptr, // pGetKeyFn (unused)
+ nullptr, // pvGetKeyArgument (unused)
+ &credentialHandle, // phCredential
+ &expiration // ptsExpir
+ );
+
+ if (status != SEC_E_OK) {
+ setErrorAndEmit(QAbstractSocket::SslInternalError, schannelErrorToString(status));
+ return false;
+ }
+ return true;
+}
+
+void QSslSocketBackendPrivate::deallocateContext()
+{
+ if (SecIsValidHandle(&contextHandle)) {
+ DeleteSecurityContext(&contextHandle);
+ SecInvalidateHandle(&contextHandle);
+ }
+}
+
+void QSslSocketBackendPrivate::freeCredentialsHandle()
+{
+ if (SecIsValidHandle(&credentialHandle)) {
+ FreeCredentialsHandle(&credentialHandle);
+ SecInvalidateHandle(&credentialHandle);
+ }
+}
+
+void QSslSocketBackendPrivate::closeCertificateStores()
+{
+ localCertificateStore.reset();
+ peerCertificateStore.reset();
+ caCertificateStore.reset();
+}
+
+bool QSslSocketBackendPrivate::createContext()
+{
+ Q_ASSERT(SecIsValidHandle(&credentialHandle));
+ Q_ASSERT(schannelState == SchannelState::InitializeHandshake);
+ Q_ASSERT(mode == QSslSocket::SslClientMode);
+ ULONG contextReq = getContextRequirements();
+
+ SecBuffer outBuffers[3];
+ outBuffers[0] = createSecBuffer(nullptr, 0, SECBUFFER_TOKEN);
+ outBuffers[1] = createSecBuffer(nullptr, 0, SECBUFFER_ALERT);
+ outBuffers[2] = createSecBuffer(nullptr, 0, SECBUFFER_EMPTY);
+ auto freeBuffers = qScopeGuard([&outBuffers]() {
+ for (auto i = 0ull; i < ARRAYSIZE(outBuffers); i++) {
+ if (outBuffers[i].pvBuffer)
+ FreeContextBuffer(outBuffers[i].pvBuffer);
+ }
+ });
+ SecBufferDesc outputBufferDesc{
+ SECBUFFER_VERSION,
+ ARRAYSIZE(outBuffers),
+ outBuffers
+ };
+
+ TimeStamp expiry;
+
+ SecBufferDesc alpnBufferDesc;
+ bool useAlpn = false;
+#ifdef SUPPORTS_ALPN
+ configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNone;
+ QByteArray alpnString = createAlpnString(configuration.nextAllowedProtocols);
+ useAlpn = !alpnString.isEmpty();
+ SecBuffer alpnBuffers[1];
+ alpnBuffers[0] = createSecBuffer(alpnString, SECBUFFER_APPLICATION_PROTOCOLS);
+ alpnBufferDesc = {
+ SECBUFFER_VERSION,
+ ARRAYSIZE(alpnBuffers),
+ alpnBuffers
+ };
+#endif
+
+ auto status = InitializeSecurityContext(&credentialHandle, // phCredential
+ nullptr, // phContext
+ const_reinterpret_cast<SEC_WCHAR *>(targetName().utf16()), // pszTargetName
+ contextReq, // fContextReq
+ 0, // Reserved1
+ 0, // TargetDataRep (unused)
+ useAlpn ? &alpnBufferDesc : nullptr, // pInput
+ 0, // Reserved2
+ &contextHandle, // phNewContext
+ &outputBufferDesc, // pOutput
+ &contextAttributes, // pfContextAttr
+ &expiry // ptsExpiry
+ );
+
+ // This is the first call to InitializeSecurityContext, so theoretically "CONTINUE_NEEDED"
+ // should be the only non-error return-code here.
+ if (status != SEC_I_CONTINUE_NEEDED) {
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Error creating SSL context (%1)").arg(schannelErrorToString(status)));
+ return false;
+ }
+
+ if (!sendToken(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer))
+ return false;
+ schannelState = SchannelState::PerformHandshake;
+ return true;
+}
+
+bool QSslSocketBackendPrivate::acceptContext()
+{
+ Q_ASSERT(SecIsValidHandle(&credentialHandle));
+ Q_ASSERT(schannelState == SchannelState::InitializeHandshake);
+ Q_ASSERT(mode == QSslSocket::SslServerMode);
+ ULONG contextReq = getContextRequirements();
+
+ intermediateBuffer += plainSocket->read(16384);
+ if (intermediateBuffer.isEmpty())
+ return true; // definitely need more data..
+
+ SecBuffer inBuffers[2];
+ inBuffers[0] = createSecBuffer(intermediateBuffer, SECBUFFER_TOKEN);
+
+#ifdef SUPPORTS_ALPN
+ configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNone;
+ // The string must be alive when we call AcceptSecurityContext
+ QByteArray alpnString = createAlpnString(configuration.nextAllowedProtocols);
+ if (!alpnString.isEmpty()) {
+ inBuffers[1] = createSecBuffer(alpnString, SECBUFFER_APPLICATION_PROTOCOLS);
+ } else
+#endif
+ {
+ inBuffers[1] = createSecBuffer(nullptr, 0, SECBUFFER_EMPTY);
+ }
+
+ SecBufferDesc inputBufferDesc{
+ SECBUFFER_VERSION,
+ ARRAYSIZE(inBuffers),
+ inBuffers
+ };
+
+ SecBuffer outBuffers[3];
+ outBuffers[0] = createSecBuffer(nullptr, 0, SECBUFFER_TOKEN);
+ outBuffers[1] = createSecBuffer(nullptr, 0, SECBUFFER_ALERT);
+ outBuffers[2] = createSecBuffer(nullptr, 0, SECBUFFER_EMPTY);
+ auto freeBuffers = qScopeGuard([&outBuffers]() {
+ for (auto i = 0ull; i < ARRAYSIZE(outBuffers); i++) {
+ if (outBuffers[i].pvBuffer)
+ FreeContextBuffer(outBuffers[i].pvBuffer);
+ }
+ });
+ SecBufferDesc outputBufferDesc{
+ SECBUFFER_VERSION,
+ ARRAYSIZE(outBuffers),
+ outBuffers
+ };
+
+ TimeStamp expiry;
+ auto status = AcceptSecurityContext(
+ &credentialHandle, // phCredential
+ nullptr, // phContext
+ &inputBufferDesc, // pInput
+ contextReq, // fContextReq
+ 0, // TargetDataRep (unused)
+ &contextHandle, // phNewContext
+ &outputBufferDesc, // pOutput
+ &contextAttributes, // pfContextAttr
+ &expiry // ptsTimeStamp
+ );
+
+ if (inBuffers[1].BufferType == SECBUFFER_EXTRA) {
+ // https://docs.microsoft.com/en-us/windows/desktop/secauthn/extra-buffers-returned-by-schannel
+ // inBuffers[1].cbBuffer indicates the amount of bytes _NOT_ processed, the rest need to
+ // be stored.
+ intermediateBuffer = intermediateBuffer.right(int(inBuffers[1].cbBuffer));
+ } else if (status != SEC_E_INCOMPLETE_MESSAGE) {
+ intermediateBuffer.clear();
+ }
+
+ if (status != SEC_I_CONTINUE_NEEDED) {
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QSslSocket::tr("Error creating SSL context (%1)").arg(schannelErrorToString(status)));
+ return false;
+ }
+ if (!sendToken(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer))
+ return false;
+ schannelState = SchannelState::PerformHandshake;
+ return true;
+}
+
+bool QSslSocketBackendPrivate::performHandshake()
+{
+ if (plainSocket->state() == QAbstractSocket::UnconnectedState) {
+ setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
+ QSslSocket::tr("The TLS/SSL connection has been closed"));
+ return false;
+ }
+ Q_ASSERT(SecIsValidHandle(&credentialHandle));
+ Q_ASSERT(SecIsValidHandle(&contextHandle));
+ Q_ASSERT(schannelState == SchannelState::PerformHandshake);
+
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "Bytes available from socket:" << plainSocket->bytesAvailable();
+ qCDebug(lcSsl) << "intermediateBuffer size:" << intermediateBuffer.size();
+#endif
+
+ intermediateBuffer += plainSocket->read(16384);
+ if (intermediateBuffer.isEmpty())
+ return true; // no data, will fail
+
+ SecBuffer inputBuffers[2];
+ inputBuffers[0] = createSecBuffer(intermediateBuffer, SECBUFFER_TOKEN);
+ inputBuffers[1] = createSecBuffer(nullptr, 0, SECBUFFER_EMPTY);
+ SecBufferDesc inputBufferDesc{
+ SECBUFFER_VERSION,
+ ARRAYSIZE(inputBuffers),
+ inputBuffers
+ };
+
+ SecBuffer outBuffers[3];
+ outBuffers[0] = createSecBuffer(nullptr, 0, SECBUFFER_TOKEN);
+ outBuffers[1] = createSecBuffer(nullptr, 0, SECBUFFER_ALERT);
+ outBuffers[2] = createSecBuffer(nullptr, 0, SECBUFFER_EMPTY);
+ auto freeBuffers = qScopeGuard([&outBuffers]() {
+ for (auto i = 0ull; i < ARRAYSIZE(outBuffers); i++) {
+ if (outBuffers[i].pvBuffer)
+ FreeContextBuffer(outBuffers[i].pvBuffer);
+ }
+ });
+ SecBufferDesc outputBufferDesc{
+ SECBUFFER_VERSION,
+ ARRAYSIZE(outBuffers),
+ outBuffers
+ };
+
+ ULONG contextReq = getContextRequirements();
+ TimeStamp expiry;
+ auto status = InitializeSecurityContext(&credentialHandle, // phCredential
+ &contextHandle, // phContext
+ const_reinterpret_cast<SEC_WCHAR *>(targetName().utf16()), // pszTargetName
+ contextReq, // fContextReq
+ 0, // Reserved1
+ 0, // TargetDataRep (unused)
+ &inputBufferDesc, // pInput
+ 0, // Reserved2
+ nullptr, // phNewContext (we already have one)
+ &outputBufferDesc, // pOutput
+ &contextAttributes, // pfContextAttr
+ &expiry // ptsExpiry
+ );
+
+ if (inputBuffers[1].BufferType == SECBUFFER_EXTRA) {
+ // https://docs.microsoft.com/en-us/windows/desktop/secauthn/extra-buffers-returned-by-schannel
+ // inputBuffers[1].cbBuffer indicates the amount of bytes _NOT_ processed, the rest need to
+ // be stored.
+ intermediateBuffer = intermediateBuffer.right(int(inputBuffers[1].cbBuffer));
+ } else {
+ // Clear the buffer if we weren't asked for more data
+ if (status != SEC_E_INCOMPLETE_MESSAGE)
+ intermediateBuffer.clear();
+ }
+ switch (status) {
+ case SEC_E_OK:
+ // Need to transmit a final token in the handshake if 'cbBuffer' is non-zero.
+ if (!sendToken(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer))
+ return false;
+ schannelState = SchannelState::VerifyHandshake;
+ return true;
+ case SEC_I_CONTINUE_NEEDED:
+ if (!sendToken(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer))
+ return false;
+ // Must call InitializeSecurityContext again later (done through continueHandshake)
+ return true;
+ case SEC_I_INCOMPLETE_CREDENTIALS:
+ // Schannel takes care of picking certificate to send (other than the one we can specify),
+ // so if we get here then that means we don't have a certificate the server accepts.
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QSslSocket::tr("Server did not accept any certificate we could present."));
+ return false;
+ case SEC_I_CONTEXT_EXPIRED:
+ // "The message sender has finished using the connection and has initiated a shutdown."
+ if (outBuffers[0].BufferType == SECBUFFER_TOKEN) {
+ if (!sendToken(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer))
+ return false;
+ }
+ if (!shutdown) { // we did not initiate this
+ setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
+ QSslSocket::tr("The TLS/SSL connection has been closed"));
+ }
+ return true;
+ case SEC_E_INCOMPLETE_MESSAGE:
+ // Simply incomplete, wait for more data
+ return true;
+ case SEC_E_ALGORITHM_MISMATCH:
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QSslSocket::tr("Algorithm mismatch"));
+ shutdown = true; // skip sending the "Shutdown" alert
+ return false;
+ }
+
+ // Note: We can get here if the connection is using TLS 1.2 and the server certificate uses
+ // MD5, which is not allowed in Schannel. This causes an "invalid token" error during handshake.
+ // (If you came here investigating an error: md5 is insecure, update your certificate)
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QSslSocket::tr("Handshake failed: %1").arg(schannelErrorToString(status)));
+ return false;
+}
+
+bool QSslSocketBackendPrivate::verifyHandshake()
+{
+ Q_Q(QSslSocket);
+
+ const bool isClient = mode == QSslSocket::SslClientMode;
+#define CHECK_STATUS(status) \
+ if (status != SEC_E_OK) { \
+ setErrorAndEmit(QAbstractSocket::SslInternalError, \
+ QSslSocket::tr("Failed to query the TLS context: %1") \
+ .arg(schannelErrorToString(status))); \
+ return false; \
+ }
+
+ // Everything is set up, now make sure there's nothing wrong and query some attributes...
+ if (!matchesContextRequirements(contextAttributes, getContextRequirements(),
+ configuration.peerVerifyMode, isClient)) {
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QSslSocket::tr("Did not get the required attributes for the connection."));
+ return false;
+ }
+
+ // Get stream sizes (to know the max size of a message and the size of the header and trailer)
+ auto status = QueryContextAttributes(&contextHandle,
+ SECPKG_ATTR_STREAM_SIZES,
+ &streamSizes);
+ CHECK_STATUS(status);
+
+ // Get session cipher info
+ status = QueryContextAttributes(&contextHandle,
+ SECPKG_ATTR_CONNECTION_INFO,
+ &connectionInfo);
+ CHECK_STATUS(status);
+
+#ifdef SUPPORTS_ALPN
+ if (!configuration.nextAllowedProtocols.isEmpty() && supportsAlpn()) {
+ SecPkgContext_ApplicationProtocol alpn;
+ status = QueryContextAttributes(&contextHandle,
+ SECPKG_ATTR_APPLICATION_PROTOCOL,
+ &alpn);
+ CHECK_STATUS(status);
+ if (alpn.ProtoNegoStatus == SecApplicationProtocolNegotiationStatus_Success) {
+ QByteArray negotiatedProto = QByteArray((const char *)alpn.ProtocolId,
+ alpn.ProtocolIdSize);
+ if (!configuration.nextAllowedProtocols.contains(negotiatedProto)) {
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QSslSocket::tr("Unwanted protocol was negotiated"));
+ return false;
+ }
+ configuration.nextNegotiatedProtocol = negotiatedProto;
+ configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
+ } else {
+ configuration.nextNegotiatedProtocol = "";
+ configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationUnsupported;
+ }
+ }
+#endif // supports ALPN
+
+#undef CHECK_STATUS
+
+ // Verify certificate
+ CERT_CONTEXT *certificateContext = nullptr;
+ auto freeCertificate = qScopeGuard([&certificateContext]() {
+ if (certificateContext)
+ CertFreeCertificateContext(certificateContext);
+ });
+ status = QueryContextAttributes(&contextHandle,
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+ &certificateContext);
+
+ // QueryPeer can (currently) not work in Schannel since Schannel itself doesn't have a way to
+ // ask for a certificate and then still be OK if it's not received.
+ // To work around this we don't request a certificate at all for QueryPeer.
+ // For servers AutoVerifyPeer is supposed to be treated the same as QueryPeer.
+ // This means that servers using Schannel will only request client certificate for "VerifyPeer".
+ if ((!isClient && configuration.peerVerifyMode == QSslSocket::PeerVerifyMode::VerifyPeer)
+ || (isClient && configuration.peerVerifyMode != QSslSocket::PeerVerifyMode::VerifyNone
+ && configuration.peerVerifyMode != QSslSocket::PeerVerifyMode::QueryPeer)) {
+ if (status != SEC_E_OK) {
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "Couldn't retrieve peer certificate, status:"
+ << schannelErrorToString(status);
+#endif
+ const QSslError error{ QSslError::NoPeerCertificate };
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ }
+
+ // verifyCertContext returns false if the user disconnected while it was checking errors.
+ if (certificateContext && sslErrors.isEmpty() && !verifyCertContext(certificateContext))
+ return false;
+
+ if (!checkSslErrors() || state != QAbstractSocket::ConnectedState) {
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << __func__ << "was unsuccessful. Paused:" << paused;
+#endif
+ // If we're paused then checkSslErrors returned false, but it's not an error
+ return paused && state == QAbstractSocket::ConnectedState;
+ }
+
+ schannelState = SchannelState::Done;
+ peerCertVerified = true;
+ return true;
+}
+
+bool QSslSocketBackendPrivate::renegotiate()
+{
+ SecBuffer outBuffers[3];
+ outBuffers[0] = createSecBuffer(nullptr, 0, SECBUFFER_TOKEN);
+ outBuffers[1] = createSecBuffer(nullptr, 0, SECBUFFER_ALERT);
+ outBuffers[2] = createSecBuffer(nullptr, 0, SECBUFFER_EMPTY);
+ auto freeBuffers = qScopeGuard([&outBuffers]() {
+ for (auto i = 0ull; i < ARRAYSIZE(outBuffers); i++) {
+ if (outBuffers[i].pvBuffer)
+ FreeContextBuffer(outBuffers[i].pvBuffer);
+ }
+ });
+ SecBufferDesc outputBufferDesc{
+ SECBUFFER_VERSION,
+ ARRAYSIZE(outBuffers),
+ outBuffers
+ };
+
+ ULONG contextReq = getContextRequirements();
+ TimeStamp expiry;
+ SECURITY_STATUS status;
+ if (mode == QSslSocket::SslClientMode) {
+ status = InitializeSecurityContext(&credentialHandle, // phCredential
+ &contextHandle, // phContext
+ const_reinterpret_cast<SEC_WCHAR *>(targetName().utf16()), // pszTargetName
+ contextReq, // fContextReq
+ 0, // Reserved1
+ 0, // TargetDataRep (unused)
+ nullptr, // pInput (nullptr for renegotiate)
+ 0, // Reserved2
+ nullptr, // phNewContext (we already have one)
+ &outputBufferDesc, // pOutput
+ &contextAttributes, // pfContextAttr
+ &expiry // ptsExpiry
+ );
+ } else {
+ status = AcceptSecurityContext(
+ &credentialHandle, // phCredential
+ &contextHandle, // phContext
+ nullptr, // pInput
+ contextReq, // fContextReq
+ 0, // TargetDataRep (unused)
+ nullptr, // phNewContext
+ &outputBufferDesc, // pOutput
+ &contextAttributes, // pfContextAttr,
+ &expiry // ptsTimeStamp
+ );
+ }
+ if (status == SEC_I_CONTINUE_NEEDED) {
+ schannelState = SchannelState::PerformHandshake;
+ return sendToken(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer);
+ }
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QSslSocket::tr("Renegotiation was unsuccessful: %1").arg(schannelErrorToString(status)));
+ return false;
+}
+
+/*!
+ \internal
+ reset the state in preparation for reuse of socket
+*/
+void QSslSocketBackendPrivate::reset()
+{
+ closeCertificateStores(); // certificate stores could've changed
+ deallocateContext();
+ freeCredentialsHandle(); // in case we already had one (@future: session resumption requires re-use)
+
+ connectionInfo = {};
+ streamSizes = {};
+
+ CertFreeCertificateContext(localCertContext);
+ localCertContext = nullptr;
+
+ contextAttributes = 0;
+ intermediateBuffer.clear();
+ schannelState = SchannelState::InitializeHandshake;
+
+ connectionEncrypted = false;
+ shutdown = false;
+ peerCertVerified = false;
+ renegotiating = false;
+}
+
+void QSslSocketBackendPrivate::startClientEncryption()
+{
+ if (connectionEncrypted)
+ return; // let's not mess up the connection...
+ reset();
+ continueHandshake();
+}
+
+void QSslSocketBackendPrivate::startServerEncryption()
+{
+ if (connectionEncrypted)
+ return; // let's not mess up the connection...
+ reset();
+ continueHandshake();
+}
+
+void QSslSocketBackendPrivate::transmit()
+{
+ Q_Q(QSslSocket);
+
+ // Can happen if called through QSslSocket::abort->QSslSocket::close->QSslSocket::flush->here
+ if (plainSocket->state() == QAbstractSocket::SocketState::UnconnectedState)
+ return;
+
+ if (schannelState != SchannelState::Done) {
+ continueHandshake();
+ return;
+ }
+
+ if (connectionEncrypted) { // encrypt data in writeBuffer and write it to plainSocket
+ qint64 totalBytesWritten = 0;
+ qint64 writeBufferSize;
+ while ((writeBufferSize = writeBuffer.size()) > 0) {
+ const int headerSize = int(streamSizes.cbHeader);
+ const int trailerSize = int(streamSizes.cbTrailer);
+ // Try to read 'cbMaximumMessage' bytes from buffer before encrypting.
+ const int size = int(std::min(writeBufferSize, qint64(streamSizes.cbMaximumMessage)));
+ QByteArray fullMessage(headerSize + trailerSize + size, Qt::Uninitialized);
+ {
+ // Use peek() here instead of read() so we don't lose data if encryption fails.
+ qint64 copied = writeBuffer.peek(fullMessage.data() + headerSize, size);
+ Q_ASSERT(copied == size);
+ }
+
+ SecBuffer inputBuffers[4]{
+ createSecBuffer(fullMessage.data(), headerSize, SECBUFFER_STREAM_HEADER),
+ createSecBuffer(fullMessage.data() + headerSize, size, SECBUFFER_DATA),
+ createSecBuffer(fullMessage.data() + headerSize + size, trailerSize, SECBUFFER_STREAM_TRAILER),
+ createSecBuffer(nullptr, 0, SECBUFFER_EMPTY)
+ };
+ SecBufferDesc message{
+ SECBUFFER_VERSION,
+ ARRAYSIZE(inputBuffers),
+ inputBuffers
+ };
+ auto status = EncryptMessage(&contextHandle, 0, &message, 0);
+ if (status != SEC_E_OK) {
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Schannel failed to encrypt data: %1")
+ .arg(schannelErrorToString(status)));
+ return;
+ }
+ // Data was encrypted successfully, so we free() what we peek()ed earlier
+ writeBuffer.free(size);
+
+ // The trailer's size is not final, so resize fullMessage to not send trailing junk
+ fullMessage.resize(inputBuffers[0].cbBuffer + inputBuffers[1].cbBuffer + inputBuffers[2].cbBuffer);
+ const qint64 bytesWritten = plainSocket->write(fullMessage);
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "Wrote" << bytesWritten << "of total"
+ << fullMessage.length() << "bytes";
+#endif
+ if (bytesWritten >= 0) {
+ totalBytesWritten += bytesWritten;
+ } else {
+ setErrorAndEmit(plainSocket->error(), plainSocket->errorString());
+ return;
+ }
+ }
+
+ if (totalBytesWritten > 0) {
+ // Don't emit bytesWritten() recursively.
+ if (!emittedBytesWritten) {
+ emittedBytesWritten = true;
+ emit q->bytesWritten(totalBytesWritten);
+ emittedBytesWritten = false;
+ }
+ emit q->channelBytesWritten(0, totalBytesWritten);
+ }
+ }
+
+ if (connectionEncrypted) { // Decrypt data from remote
+ int totalRead = 0;
+ bool hadIncompleteData = false;
+ while (!readBufferMaxSize || buffer.size() < readBufferMaxSize) {
+ QByteArray ciphertext;
+ if (intermediateBuffer.length()) {
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "Restoring data from intermediateBuffer:"
+ << intermediateBuffer.length() << "bytes";
+#endif
+ ciphertext.swap(intermediateBuffer);
+ }
+ int initialLength = ciphertext.length();
+ ciphertext += plainSocket->read(16384);
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "Read" << ciphertext.length() - initialLength
+ << "encrypted bytes from the socket";
+#endif
+ if (ciphertext.length() == 0 || (hadIncompleteData && initialLength == ciphertext.length())) {
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << (hadIncompleteData ? "No new data received, leaving loop!"
+ : "Nothing to decrypt, leaving loop!");
+#endif
+ if (ciphertext.length()) // We have data, it came from intermediateBuffer, swap back
+ intermediateBuffer.swap(ciphertext);
+ break;
+ }
+ hadIncompleteData = false;
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "Total amount of bytes to decrypt:" << ciphertext.length();
+#endif
+
+ SecBuffer dataBuffer[4]{
+ createSecBuffer(ciphertext, SECBUFFER_DATA),
+ createSecBuffer(nullptr, 0, SECBUFFER_EMPTY),
+ createSecBuffer(nullptr, 0, SECBUFFER_EMPTY),
+ createSecBuffer(nullptr, 0, SECBUFFER_EMPTY)
+ };
+ SecBufferDesc message{
+ SECBUFFER_VERSION,
+ ARRAYSIZE(dataBuffer),
+ dataBuffer
+ };
+ auto status = DecryptMessage(&contextHandle, &message, 0, nullptr);
+ if (status == SEC_E_OK || status == SEC_I_RENEGOTIATE || status == SEC_I_CONTEXT_EXPIRED) {
+ // There can still be 0 output even if it succeeds, this is fine
+ if (dataBuffer[1].cbBuffer > 0) {
+ // It is always decrypted in-place.
+ // But [0] is the STREAM_HEADER, [1] is the DATA and [2] is the STREAM_TRAILER.
+ // The pointers in all of those still point into the 'ciphertext' byte array.
+ buffer.append(static_cast<char *>(dataBuffer[1].pvBuffer),
+ dataBuffer[1].cbBuffer);
+ totalRead += dataBuffer[1].cbBuffer;
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "Decrypted" << dataBuffer[1].cbBuffer
+ << "bytes. New read buffer size:" << buffer.size();
+#endif
+ }
+ if (dataBuffer[3].BufferType == SECBUFFER_EXTRA) {
+ // https://docs.microsoft.com/en-us/windows/desktop/secauthn/extra-buffers-returned-by-schannel
+ // dataBuffer[3].cbBuffer indicates the amount of bytes _NOT_ processed,
+ // the rest need to be stored.
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "We've got excess data, moving it to the intermediate buffer:"
+ << dataBuffer[3].cbBuffer << "bytes";
+#endif
+ intermediateBuffer = ciphertext.right(int(dataBuffer[3].cbBuffer));
+ }
+ } else if (status == SEC_E_INCOMPLETE_MESSAGE) {
+ // Need more data before we can decrypt.. to the buffer it goes!
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl, "We didn't have enough data to decrypt anything, will try again!");
+#endif
+ Q_ASSERT(intermediateBuffer.isEmpty());
+ intermediateBuffer.swap(ciphertext);
+ // We try again, but if we don't get any more data then we leave
+ hadIncompleteData = true;
+ } else if (status == SEC_E_INVALID_HANDLE) {
+ // I don't think this should happen, if it does we're done...
+ qCWarning(lcSsl, "The internal SSPI handle is invalid!");
+ Q_UNREACHABLE();
+ } else if (status == SEC_E_INVALID_TOKEN) {
+ qCWarning(lcSsl, "Got SEC_E_INVALID_TOKEN!");
+ Q_UNREACHABLE(); // Happened once due to a bug, but shouldn't generally happen(?)
+ } else if (status == SEC_E_MESSAGE_ALTERED) {
+ // The message has been altered, disconnect now.
+ shutdown = true; // skips sending the shutdown alert
+ disconnectFromHost();
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ schannelErrorToString(status));
+ break;
+ } else if (status == SEC_E_OUT_OF_SEQUENCE) {
+ // @todo: I don't know if this one is actually "fatal"..
+ // This path might never be hit as it seems this is for connection-oriented connections,
+ // while SEC_E_MESSAGE_ALTERED is for stream-oriented ones (what we use).
+ shutdown = true; // skips sending the shutdown alert
+ disconnectFromHost();
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ schannelErrorToString(status));
+ break;
+ } else if (status == SEC_I_CONTEXT_EXPIRED) {
+ // 'remote' has initiated a shutdown
+ disconnectFromHost();
+ setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
+ schannelErrorToString(status));
+ break;
+ } else if (status == SEC_I_RENEGOTIATE) {
+ // 'remote' wants to renegotiate
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl, "The peer wants to renegotiate.");
+#endif
+ schannelState = SchannelState::Renegotiate;
+ renegotiating = true;
+ // We need to call 'continueHandshake' or else there's no guarantee it ever gets called
+ continueHandshake();
+ break;
+ }
+ }
+
+ if (totalRead) {
+ if (readyReadEmittedPointer)
+ *readyReadEmittedPointer = true;
+ emit q->readyRead();
+ emit q->channelReadyRead(0);
+ }
+ }
+}
+
+void QSslSocketBackendPrivate::sendShutdown()
+{
+ const bool isClient = mode == QSslSocket::SslClientMode;
+ DWORD shutdownToken = SCHANNEL_SHUTDOWN;
+ SecBuffer buffer = createSecBuffer(&shutdownToken, sizeof(SCHANNEL_SHUTDOWN), SECBUFFER_TOKEN);
+ SecBufferDesc token{
+ SECBUFFER_VERSION,
+ 1,
+ &buffer
+ };
+ auto status = ApplyControlToken(&contextHandle, &token);
+
+ if (status != SEC_E_OK) {
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "Failed to apply shutdown control token:" << schannelErrorToString(status);
+#endif
+ return;
+ }
+
+ SecBuffer outBuffers[3];
+ outBuffers[0] = createSecBuffer(nullptr, 0, SECBUFFER_TOKEN);
+ outBuffers[1] = createSecBuffer(nullptr, 0, SECBUFFER_ALERT);
+ outBuffers[2] = createSecBuffer(nullptr, 0, SECBUFFER_EMPTY);
+ auto freeBuffers = qScopeGuard([&outBuffers]() {
+ for (auto i = 0ull; i < ARRAYSIZE(outBuffers); i++) {
+ if (outBuffers[i].pvBuffer)
+ FreeContextBuffer(outBuffers[i].pvBuffer);
+ }
+ });
+ SecBufferDesc outputBufferDesc{
+ SECBUFFER_VERSION,
+ ARRAYSIZE(outBuffers),
+ outBuffers
+ };
+
+ ULONG contextReq = getContextRequirements();
+ TimeStamp expiry;
+ if (isClient) {
+ status = InitializeSecurityContext(&credentialHandle, // phCredential
+ &contextHandle, // phContext
+ const_reinterpret_cast<SEC_WCHAR *>(targetName().utf16()), // pszTargetName
+ contextReq, // fContextReq
+ 0, // Reserved1
+ 0, // TargetDataRep (unused)
+ nullptr, // pInput
+ 0, // Reserved2
+ nullptr, // phNewContext (we already have one)
+ &outputBufferDesc, // pOutput
+ &contextAttributes, // pfContextAttr
+ &expiry // ptsExpiry
+ );
+ } else {
+ status = AcceptSecurityContext(
+ &credentialHandle, // phCredential
+ &contextHandle, // phContext
+ nullptr, // pInput
+ contextReq, // fContextReq
+ 0, // TargetDataRep (unused)
+ nullptr, // phNewContext
+ &outputBufferDesc, // pOutput
+ &contextAttributes, // pfContextAttr,
+ &expiry // ptsTimeStamp
+ );
+ }
+ if (status == SEC_E_OK || status == SEC_I_CONTEXT_EXPIRED) {
+ if (!sendToken(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, false)) {
+ // We failed to send the shutdown message, but it's not that important since we're
+ // shutting down anyway.
+ return;
+ }
+ } else {
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "Failed to initialize shutdown:" << schannelErrorToString(status);
+#endif
+ }
+}
+
+void QSslSocketBackendPrivate::disconnectFromHost()
+{
+ if (SecIsValidHandle(&contextHandle)) {
+ if (!shutdown) {
+ shutdown = true;
+ if (plainSocket->state() != QAbstractSocket::UnconnectedState) {
+ if (connectionEncrypted) {
+ // Read as much as possible because this is likely our last chance
+ qint64 tempMax = readBufferMaxSize;
+ readBufferMaxSize = 0;
+ transmit();
+ readBufferMaxSize = tempMax;
+ sendShutdown();
+ }
+ }
+ }
+ }
+ if (plainSocket->state() != QAbstractSocket::UnconnectedState)
+ plainSocket->disconnectFromHost();
+}
+
+void QSslSocketBackendPrivate::disconnected()
+{
+ shutdown = true;
+ connectionEncrypted = false;
+ deallocateContext();
+ freeCredentialsHandle();
+}
+
+QSslCipher QSslSocketBackendPrivate::sessionCipher() const
+{
+ if (!connectionEncrypted)
+ return QSslCipher();
+ return QSslCipher(QStringLiteral("Schannel"), sessionProtocol());
+}
+
+QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
+{
+ if (!connectionEncrypted)
+ return QSsl::SslProtocol::UnknownProtocol;
+ return toQtSslProtocol(connectionInfo.dwProtocol);
+}
+
+void QSslSocketBackendPrivate::continueHandshake()
+{
+ Q_Q(QSslSocket);
+ const bool isServer = mode == QSslSocket::SslServerMode;
+ switch (schannelState) {
+ case SchannelState::InitializeHandshake:
+ if (!SecIsValidHandle(&credentialHandle) && !acquireCredentialsHandle()) {
+ disconnectFromHost();
+ return;
+ }
+ if (!SecIsValidHandle(&credentialHandle)) // Needed to support tst_QSslSocket::setEmptyKey
+ return;
+ if (!SecIsValidHandle(&contextHandle) && !(isServer ? acceptContext() : createContext())) {
+ disconnectFromHost();
+ return;
+ }
+ if (schannelState != SchannelState::PerformHandshake)
+ break;
+ Q_FALLTHROUGH();
+ case SchannelState::PerformHandshake:
+ if (!performHandshake()) {
+ disconnectFromHost();
+ return;
+ }
+ if (schannelState != SchannelState::VerifyHandshake)
+ break;
+ Q_FALLTHROUGH();
+ case SchannelState::VerifyHandshake:
+ // if we're in shutdown or renegotiating then we might not need to verify
+ // (since we already did)
+ if (!peerCertVerified && !verifyHandshake()) {
+ shutdown = true; // Skip sending shutdown alert
+ q->abort(); // We don't want to send buffered data
+ disconnectFromHost();
+ return;
+ }
+ if (schannelState != SchannelState::Done)
+ break;
+ Q_FALLTHROUGH();
+ case SchannelState::Done:
+ // connectionEncrypted is already true if we come here from a renegotiation
+ if (!connectionEncrypted) {
+ connectionEncrypted = true; // all is done
+ emit q->encrypted();
+ }
+ renegotiating = false;
+ if (pendingClose) {
+ pendingClose = false;
+ disconnectFromHost();
+ } else {
+ transmit();
+ }
+ break;
+ case SchannelState::Renegotiate:
+ if (!renegotiate()) {
+ disconnectFromHost();
+ return;
+ }
+ break;
+ }
+}
+
+QList<QSslCipher> QSslSocketBackendPrivate::defaultCiphers()
+{
+ QList<QSslCipher> ciphers;
+ // @temp (I hope), stolen from qsslsocket_winrt.cpp
+ const QString protocolStrings[] = { QStringLiteral("TLSv1"), QStringLiteral("TLSv1.1"),
+ QStringLiteral("TLSv1.2"), QStringLiteral("TLSv1.3") };
+ const QSsl::SslProtocol protocols[] = { QSsl::TlsV1_0, QSsl::TlsV1_1,
+ QSsl::TlsV1_2, QSsl::TlsV1_3 };
+ const int size = ARRAYSIZE(protocols);
+ Q_STATIC_ASSERT(size == ARRAYSIZE(protocolStrings));
+ ciphers.reserve(size);
+ for (int i = 0; i < size; ++i) {
+ QSslCipher cipher;
+ cipher.d->isNull = false;
+ cipher.d->name = QStringLiteral("Schannel");
+ cipher.d->protocol = protocols[i];
+ cipher.d->protocolString = protocolStrings[i];
+ ciphers.append(cipher);
+ }
+
+ return ciphers;
+}
+
+QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &certificateChain,
+ const QString &hostName)
+{
+ Q_UNUSED(certificateChain);
+ Q_UNUSED(hostName);
+
+ Q_UNIMPLEMENTED();
+ return {}; // @future implement(?)
+}
+
+bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert,
+ QList<QSslCertificate> *caCertificates,
+ const QByteArray &passPhrase)
+{
+ Q_UNUSED(device);
+ Q_UNUSED(key);
+ Q_UNUSED(cert);
+ Q_UNUSED(caCertificates);
+ Q_UNUSED(passPhrase);
+ // @future: can load into its own certificate store (encountered problems extracting key).
+ Q_UNIMPLEMENTED();
+ return false;
+}
+
+/*
+ Copied from qsslsocket_mac.cpp, which was copied from qsslsocket_openssl.cpp
+*/
+bool QSslSocketBackendPrivate::checkSslErrors()
+{
+ if (sslErrors.isEmpty())
+ return true;
+ Q_Q(QSslSocket);
+
+ emit q->sslErrors(sslErrors);
+
+ const bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
+ || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
+ && mode == QSslSocket::SslClientMode);
+ const bool doEmitSslError = !verifyErrorsHaveBeenIgnored();
+ // check whether we need to emit an SSL handshake error
+ if (doVerifyPeer && doEmitSslError) {
+ if (q->pauseMode() & QAbstractSocket::PauseOnSslErrors) {
+ pauseSocketNotifiers(q);
+ paused = true;
+ } else {
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ sslErrors.constFirst().errorString());
+ plainSocket->disconnectFromHost();
+ }
+ return false;
+ }
+
+ return true;
+}
+
+void QSslSocketBackendPrivate::initializeCertificateStores()
+{
+ //// helper function which turns a chain into a certificate store
+ auto createStoreFromCertificateChain = [](const QList<QSslCertificate> certChain, const QSslKey &privateKey) {
+ const wchar_t *passphrase = L"";
+ // Need to embed the private key in the certificate
+ QByteArray pkcs12 = _q_makePkcs12(certChain,
+ privateKey,
+ QString::fromWCharArray(passphrase, 0));
+ CRYPT_DATA_BLOB pfxBlob;
+ pfxBlob.cbData = DWORD(pkcs12.length());
+ pfxBlob.pbData = reinterpret_cast<unsigned char *>(pkcs12.data());
+ return QHCertStorePointer(PFXImportCertStore(&pfxBlob, passphrase, 0));
+ };
+
+ if (!configuration.localCertificateChain.isEmpty()) {
+ if (configuration.privateKey.isNull()) {
+ setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
+ QSslSocket::tr("Cannot provide a certificate with no key"));
+ return;
+ }
+ if (localCertificateStore == nullptr) {
+ localCertificateStore = createStoreFromCertificateChain(configuration.localCertificateChain,
+ configuration.privateKey);
+ if (localCertificateStore == nullptr)
+ qCWarning(lcSsl, "Failed to load certificate chain!");
+ }
+ }
+
+ if (!configuration.caCertificates.isEmpty() && !caCertificateStore) {
+ caCertificateStore = createStoreFromCertificateChain(configuration.caCertificates,
+ {}); // No private key for the CA certs
+ }
+}
+
+bool QSslSocketBackendPrivate::verifyCertContext(CERT_CONTEXT *certContext)
+{
+ Q_ASSERT(certContext);
+ Q_Q(QSslSocket);
+
+ const bool isClient = mode == QSslSocket::SslClientMode;
+
+ // Create a collection of stores so we can pass in multiple stores as additional locations to
+ // search for the certificate chain
+ auto tempCertCollection = QHCertStorePointer(CertOpenStore(CERT_STORE_PROV_COLLECTION,
+ X509_ASN_ENCODING,
+ 0,
+ CERT_STORE_CREATE_NEW_FLAG,
+ nullptr));
+ if (!tempCertCollection) {
+#ifdef QSSLSOCKET_DEBUG
+ qCWarning(lcSsl, "Failed to create certificate store collection!");
+#endif
+ return false;
+ }
+
+ if (rootCertOnDemandLoadingAllowed()) {
+ // @future(maybe): following the OpenSSL backend these certificates should be added into
+ // the Ca list, not just included during verification.
+ // That being said, it's not trivial to add the root certificates (if and only if they
+ // came from the system root store). And I don't see this mentioned in our documentation.
+ auto rootStore = QHCertStorePointer(CertOpenSystemStore(0, L"ROOT"));
+ if (!rootStore) {
+#ifdef QSSLSOCKET_DEBUG
+ qCWarning(lcSsl, "Failed to open the system root CA certificate store!");
+#endif
+ return false;
+ } else if (!CertAddStoreToCollection(tempCertCollection.get(), rootStore.get(), 0, 1)) {
+#ifdef QSSLSOCKET_DEBUG
+ qCWarning(lcSsl, "Failed to add the system root CA certificate store to the certificate store collection!");
+#endif
+ return false;
+ }
+ }
+ if (caCertificateStore) {
+ if (!CertAddStoreToCollection(tempCertCollection.get(), caCertificateStore.get(), 0, 1)) {
+#ifdef QSSLSOCKET_DEBUG
+ qCWarning(lcSsl, "Failed to add the user's CA certificate store to the certificate store collection!");
+#endif
+ return false;
+ }
+ }
+
+ if (!CertAddStoreToCollection(tempCertCollection.get(), certContext->hCertStore, 0, 0)) {
+#ifdef QSSLSOCKET_DEBUG
+ qCWarning(lcSsl, "Failed to add certificate's origin store to the certificate store collection!");
+#endif
+ return false;
+ }
+
+ CERT_CHAIN_PARA parameters;
+ ZeroMemory(&parameters, sizeof(parameters));
+ parameters.cbSize = sizeof(CERT_CHAIN_PARA);
+ parameters.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
+ parameters.RequestedUsage.Usage.cUsageIdentifier = 1;
+ LPSTR oid = LPSTR(isClient ? szOID_PKIX_KP_SERVER_AUTH
+ : szOID_PKIX_KP_CLIENT_AUTH);
+ parameters.RequestedUsage.Usage.rgpszUsageIdentifier = &oid;
+
+ configuration.peerCertificate.clear();
+ configuration.peerCertificateChain.clear();
+ const CERT_CHAIN_CONTEXT *chainContext = nullptr;
+ auto freeCertChain = qScopeGuard([&chainContext]() {
+ if (chainContext)
+ CertFreeCertificateChain(chainContext);
+ });
+ BOOL status = CertGetCertificateChain(nullptr, // hChainEngine, default
+ certContext, // pCertContext
+ nullptr, // pTime, 'now'
+ tempCertCollection.get(), // hAdditionalStore, additional cert store
+ &parameters, // pChainPara
+ CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, // dwFlags
+ nullptr, // reserved
+ &chainContext // ppChainContext
+ );
+ if (status == FALSE || !chainContext || chainContext->cChain == 0) {
+ QSslError error(QSslError::UnableToVerifyFirstCertificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ return q->state() == QAbstractSocket::ConnectedState;
+ }
+
+ // Helper-function to get a QSslCertificate given a CERT_CHAIN_ELEMENT
+ static auto getCertificateFromChainElement = [](CERT_CHAIN_ELEMENT *element) {
+ if (!element)
+ return QSslCertificate();
+
+ const CERT_CONTEXT *certContext = element->pCertContext;
+ return QSslCertificatePrivate::QSslCertificate_from_CERT_CONTEXT(certContext);
+ };
+
+ // Pick a chain to use as the certificate chain, if multiple are available:
+ // According to https://docs.microsoft.com/en-gb/windows/desktop/api/wincrypt/ns-wincrypt-_cert_chain_context
+ // this seems to be the best way to get a trusted chain.
+ CERT_SIMPLE_CHAIN *chain = chainContext->rgpChain[chainContext->cChain - 1];
+
+ if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_PARTIAL_CHAIN) {
+ auto error = QSslError(QSslError::SslError::UnableToGetIssuerCertificate,
+ getCertificateFromChainElement(chain->rgpElement[chain->cElement - 1]));
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_INVALID_BASIC_CONSTRAINTS) {
+ // @Note: This is actually one of two errors:
+ // "either the certificate cannot be used to issue other certificates, or the chain path length has been exceeded."
+ // But here we are checking the chain's status, so we assume the "issuing" error cannot occur here.
+ auto error = QSslError(QSslError::PathLengthExceeded);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ static const DWORD leftoverCertChainErrorMask = CERT_TRUST_IS_CYCLIC | CERT_TRUST_INVALID_EXTENSION
+ | CERT_TRUST_INVALID_POLICY_CONSTRAINTS | CERT_TRUST_INVALID_NAME_CONSTRAINTS
+ | CERT_TRUST_CTL_IS_NOT_TIME_VALID | CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID
+ | CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE;
+ if (chain->TrustStatus.dwErrorStatus & leftoverCertChainErrorMask) {
+ auto error = QSslError(QSslError::SslError::UnspecifiedError);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+
+ DWORD verifyDepth = chain->cElement;
+ if (configuration.peerVerifyDepth > 0 && DWORD(configuration.peerVerifyDepth) < verifyDepth)
+ verifyDepth = DWORD(configuration.peerVerifyDepth);
+
+ for (DWORD i = 0; i < verifyDepth; i++) {
+ CERT_CHAIN_ELEMENT *element = chain->rgpElement[i];
+ QSslCertificate certificate = getCertificateFromChainElement(element);
+ const QList<QSslCertificateExtension> extensions = certificate.extensions();
+
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "issuer:" << certificate.issuerDisplayName()
+ << "\nsubject:" << certificate.subjectDisplayName()
+ << "\nQSslCertificate info:" << certificate
+ << "\nextended error info:" << element->pwszExtendedErrorInfo
+ << "\nerror status:" << element->TrustStatus.dwErrorStatus;
+#endif
+
+ configuration.peerCertificateChain.append(certificate);
+
+ if (certificate.isBlacklisted()) {
+ const auto error = QSslError(QSslError::CertificateBlacklisted, certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+
+ LONG result = CertVerifyTimeValidity(nullptr /*== now */, element->pCertContext->pCertInfo);
+ if (result != 0) {
+ auto error = QSslError(result == -1 ? QSslError::CertificateNotYetValid
+ : QSslError::CertificateExpired,
+ certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+
+ //// Errors
+ if (element->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID) {
+ // handled right above
+ Q_ASSERT(!sslErrors.isEmpty());
+ }
+ if (element->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED) {
+ auto error = QSslError(QSslError::CertificateRevoked, certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ if (element->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID) {
+ auto error = QSslError(QSslError::CertificateSignatureFailed, certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+
+ // While netscape shouldn't be relevant now it defined an extension which is
+ // still in use. Schannel does not check this automatically, so we do it here.
+ // It is used to differentiate between client and server certificates.
+ if (netscapeWrongCertType(extensions, isClient))
+ element->TrustStatus.dwErrorStatus |= CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
+
+ if (element->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
+ auto error = QSslError(QSslError::InvalidPurpose, certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ if (element->TrustStatus.dwErrorStatus & CERT_TRUST_IS_UNTRUSTED_ROOT) {
+ // Override this error if we have the certificate inside our trusted CAs list.
+ const bool isTrustedRoot = configuration.caCertificates.contains(certificate);
+ if (!isTrustedRoot) {
+ auto error = QSslError(QSslError::CertificateUntrusted, certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ }
+ static const DWORD certRevocationCheckUnavailableError = CERT_TRUST_IS_OFFLINE_REVOCATION
+ | CERT_TRUST_REVOCATION_STATUS_UNKNOWN;
+ if (element->TrustStatus.dwErrorStatus & certRevocationCheckUnavailableError) {
+ // @future(maybe): Do something with this
+ }
+
+ // Dumping ground of errors that don't fit our specific errors
+ static const DWORD leftoverCertErrorMask = CERT_TRUST_IS_CYCLIC
+ | CERT_TRUST_INVALID_EXTENSION | CERT_TRUST_INVALID_NAME_CONSTRAINTS
+ | CERT_TRUST_INVALID_POLICY_CONSTRAINTS
+ | CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT
+ | CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT
+ | CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT
+ | CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT
+ | CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT;
+ if (element->TrustStatus.dwErrorStatus & leftoverCertErrorMask) {
+ auto error = QSslError(QSslError::UnspecifiedError, certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ if (element->TrustStatus.dwErrorStatus & CERT_TRUST_INVALID_BASIC_CONSTRAINTS) {
+ auto it = std::find_if(extensions.cbegin(), extensions.cend(),
+ [](const QSslCertificateExtension &extension) {
+ return extension.name() == QLatin1String("basicConstraints");
+ });
+ if (it != extensions.cend()) {
+ // @Note: This is actually one of two errors:
+ // "either the certificate cannot be used to issue other certificates,
+ // or the chain path length has been exceeded."
+ QVariantMap basicConstraints = it->value().toMap();
+ QSslError error;
+ if (i > 0 && !basicConstraints.value(QLatin1String("ca"), false).toBool())
+ error = QSslError(QSslError::InvalidPurpose, certificate);
+ else
+ error = QSslError(QSslError::PathLengthExceeded, certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ }
+ if (element->TrustStatus.dwErrorStatus & CERT_TRUST_IS_EXPLICIT_DISTRUST) {
+ auto error = QSslError(QSslError::CertificateBlacklisted, certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+
+ if (element->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED) {
+ // If it's self-signed *and* a CA then we can assume it's a root CA certificate
+ // and we can ignore the "self-signed" note:
+ // We check the basicConstraints certificate extension when possible, but this didn't
+ // exist for version 1, so we can only guess in that case
+ const bool isRootCertificateAuthority = isCertificateAuthority(extensions)
+ || certificate.version() == "1";
+
+ // Root certificate tends to be signed by themselves, so ignore self-signed status.
+ if (!isRootCertificateAuthority) {
+ auto error = QSslError(QSslError::SelfSignedCertificate, certificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ }
+ }
+
+ if (!configuration.peerCertificateChain.isEmpty())
+ configuration.peerCertificate = configuration.peerCertificateChain.first();
+
+ // @Note: Somewhat copied from qsslsocket_mac.cpp
+ const bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
+ || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
+ && mode == QSslSocket::SslClientMode);
+ // Check the peer certificate itself. First try the subject's common name
+ // (CN) as a wildcard, then try all alternate subject name DNS entries the
+ // same way.
+ if (!configuration.peerCertificate.isNull()) {
+ // but only if we're a client connecting to a server
+ // if we're the server, don't check CN
+ if (mode == QSslSocket::SslClientMode) {
+ const QString peerName(verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName);
+ if (!isMatchingHostname(configuration.peerCertificate, peerName)) {
+ // No matches in common names or alternate names.
+ const QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+ }
+ } else if (doVerifyPeer) {
+ // No peer certificate presented. Report as error if the socket
+ // expected one.
+ const QSslError error(QSslError::NoPeerCertificate);
+ sslErrors += error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+
+ return true;
+}
+
+bool QSslSocketBackendPrivate::rootCertOnDemandLoadingAllowed()
+{
+ return allowRootCertOnDemandLoading && s_loadRootCertsOnDemand;
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket_schannel_p.h b/src/network/ssl/qsslsocket_schannel_p.h
new file mode 100644
index 0000000000..9879e2fc60
--- /dev/null
+++ b/src/network/ssl/qsslsocket_schannel_p.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSSLSOCKET_SCHANNEL_P_H
+#define QSSLSOCKET_SCHANNEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_REQUIRE_CONFIG(schannel);
+
+#include <QtNetwork/private/qtnetworkglobal_p.h>
+
+#include "qsslsocket_p.h"
+
+#define SECURITY_WIN32
+#include <security.h>
+#include <schnlsp.h>
+#undef SECURITY_WIN32
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+struct QHCertStoreDeleter {
+ void operator()(HCERTSTORE store)
+ {
+ CertCloseStore(store, 0);
+ }
+};
+typedef std::unique_ptr<void, QHCertStoreDeleter> QHCertStorePointer;
+
+class QSslSocketBackendPrivate final : public QSslSocketPrivate
+{
+ Q_DISABLE_COPY_MOVE(QSslSocketBackendPrivate)
+ Q_DECLARE_PUBLIC(QSslSocket)
+public:
+ QSslSocketBackendPrivate();
+ ~QSslSocketBackendPrivate();
+
+ // Platform specific functions
+ void startClientEncryption() override;
+ void startServerEncryption() override;
+ void transmit() override;
+ void disconnectFromHost() override;
+ void disconnected() override;
+ QSslCipher sessionCipher() const override;
+ QSsl::SslProtocol sessionProtocol() const override;
+ void continueHandshake() override;
+
+ static QList<QSslCipher> defaultCiphers();
+ static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain,
+ const QString &hostName);
+ static bool importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert,
+ QList<QSslCertificate> *caCertificates, const QByteArray &passPhrase);
+
+private:
+ enum class SchannelState {
+ InitializeHandshake, // create and transmit context (client)/accept context (server)
+ PerformHandshake, // get token back, process it
+ VerifyHandshake, // Verify that things are OK
+ Done, // Connection encrypted!
+ Renegotiate // Renegotiating!
+ } schannelState = SchannelState::InitializeHandshake;
+
+ void reset();
+ bool acquireCredentialsHandle();
+ ULONG getContextRequirements();
+ bool createContext(); // for clients
+ bool acceptContext(); // for server
+ bool performHandshake();
+ bool verifyHandshake();
+ bool renegotiate();
+
+ bool sendToken(void *token, unsigned long tokenLength, bool emitError = true);
+ QString targetName() const;
+
+ bool checkSslErrors();
+ void deallocateContext();
+ void freeCredentialsHandle();
+ void closeCertificateStores();
+ void sendShutdown();
+
+ void initializeCertificateStores();
+ bool verifyCertContext(CERT_CONTEXT *certContext);
+
+ bool rootCertOnDemandLoadingAllowed();
+
+ SecPkgContext_ConnectionInfo connectionInfo = {};
+ SecPkgContext_StreamSizes streamSizes = {};
+
+ CredHandle credentialHandle; // Initialized in ctor
+ CtxtHandle contextHandle; // Initialized in ctor
+
+ QByteArray intermediateBuffer; // data which is left-over or incomplete
+
+ QHCertStorePointer localCertificateStore = nullptr;
+ QHCertStorePointer peerCertificateStore = nullptr;
+ QHCertStorePointer caCertificateStore = nullptr;
+
+ const CERT_CONTEXT *localCertContext = nullptr;
+
+ ULONG contextAttributes = 0;
+
+ bool renegotiating = false;
+ bool peerCertVerified = false;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSSLSOCKET_SCHANNEL_P_H
diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp
index cc69b9ac96..d54ac2ad73 100644
--- a/src/network/ssl/qsslsocket_winrt.cpp
+++ b/src/network/ssl/qsslsocket_winrt.cpp
@@ -207,9 +207,9 @@ void QSslSocketPrivate::resetDefaultCiphers()
QList<QSslCipher> QSslSocketBackendPrivate::defaultCiphers()
{
QList<QSslCipher> ciphers;
- const QString protocolStrings[] = { QStringLiteral("SSLv3"), QStringLiteral("TLSv1"),
+ const QString protocolStrings[] = { QStringLiteral("TLSv1"),
QStringLiteral("TLSv1.1"), QStringLiteral("TLSv1.2") };
- const QSsl::SslProtocol protocols[] = { QSsl::SslV3, QSsl::TlsV1_0, QSsl::TlsV1_1, QSsl::TlsV1_2 };
+ const QSsl::SslProtocol protocols[] = { QSsl::TlsV1_0, QSsl::TlsV1_1, QSsl::TlsV1_2 };
const int size = static_cast<int>(ARRAYSIZE(protocols));
ciphers.reserve(size);
for (int i = 0; i < size; ++i) {
@@ -234,10 +234,14 @@ void QSslSocketBackendPrivate::startClientEncryption()
QSsl::SslProtocol protocol = q->protocol();
switch (q->protocol()) {
- case QSsl::AnyProtocol:
+ case QSsl::SslV2:
case QSsl::SslV3:
+ setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
+ QStringLiteral("unsupported protocol"));
+ return;
+ case QSsl::AnyProtocol:
case QSsl::TlsV1SslV3:
- protectionLevel = SocketProtectionLevel_Ssl; // Only use this value if weak cipher support is required
+ protectionLevel = SocketProtectionLevel_Tls10;
break;
case QSsl::TlsV1_0:
protectionLevel = SocketProtectionLevel_Tls10;
diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri
index 6975264038..8bb70a2aed 100644
--- a/src/network/ssl/ssl.pri
+++ b/src/network/ssl/ssl.pri
@@ -29,7 +29,9 @@ qtConfig(ssl) {
ssl/qsslsocket.h \
ssl/qsslsocket_p.h \
ssl/qsslpresharedkeyauthenticator.h \
- ssl/qsslpresharedkeyauthenticator_p.h
+ ssl/qsslpresharedkeyauthenticator_p.h \
+ ssl/qocspresponse.h \
+ ssl/qocspresponse_p.h
SOURCES += ssl/qsslconfiguration.cpp \
ssl/qsslcipher.cpp \
ssl/qssldiffiehellmanparameters.cpp \
@@ -37,7 +39,8 @@ qtConfig(ssl) {
ssl/qsslkey_p.cpp \
ssl/qsslerror.cpp \
ssl/qsslsocket.cpp \
- ssl/qsslpresharedkeyauthenticator.cpp
+ ssl/qsslpresharedkeyauthenticator.cpp \
+ ssl/qocspresponse.cpp
winrt {
HEADERS += ssl/qsslsocket_winrt_p.h
@@ -49,6 +52,19 @@ qtConfig(ssl) {
ssl/qsslellipticcurve_dummy.cpp
}
+ qtConfig(schannel) {
+ HEADERS += ssl/qsslsocket_schannel_p.h
+ SOURCES += ssl/qsslsocket_schannel.cpp \
+ ssl/qsslcertificate_schannel.cpp \
+ ssl/qsslkey_schannel.cpp \
+ ssl/qsslkey_qt.cpp \
+ ssl/qssldiffiehellmanparameters_dummy.cpp \
+ ssl/qsslellipticcurve_dummy.cpp \
+ ssl/qsslsocket_qt.cpp
+
+ LIBS_PRIVATE += "-lSecur32" "-lCrypt32" "-lbcrypt" "-lncrypt"
+ }
+
qtConfig(securetransport) {
HEADERS += ssl/qsslsocket_mac_p.h
SOURCES += ssl/qssldiffiehellmanparameters_dummy.cpp \
@@ -56,6 +72,7 @@ qtConfig(ssl) {
ssl/qsslkey_mac.cpp \
ssl/qsslsocket_mac_shared.cpp \
ssl/qsslsocket_mac.cpp \
+ ssl/qsslsocket_qt.cpp \
ssl/qsslellipticcurve_dummy.cpp
}
@@ -83,6 +100,8 @@ qtConfig(ssl) {
SOURCES += ssl/qdtls_openssl.cpp
}
+ qtConfig(ocsp): HEADERS += ssl/qocsp_p.h
+
qtConfig(opensslv11) {
HEADERS += ssl/qsslsocket_openssl11_symbols_p.h
SOURCES += ssl/qsslsocket_openssl11.cpp \
diff --git a/src/opengl/doc/qtopengl.qdocconf b/src/opengl/doc/qtopengl.qdocconf
index 6ff6cae2cb..2d38a5d2af 100644
--- a/src/opengl/doc/qtopengl.qdocconf
+++ b/src/opengl/doc/qtopengl.qdocconf
@@ -23,6 +23,8 @@ depends += qtdoc qtcore qtgui qtwidgets qmake
examplesinstallpath = opengl
+tagfile = qtopengl.tags
+
# The following parameters are for creating a qhp file, the qhelpgenerator
# program can convert the qhp file into a qch file which can be opened in
# Qt Assistant and/or Qt Creator.
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
index ec472da2e8..d23b3ad550 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -372,7 +372,7 @@ private:
class QGLEngineShaderProg
{
public:
- QGLEngineShaderProg() : program(0) {}
+ QGLEngineShaderProg() : program(nullptr) {}
~QGLEngineShaderProg() {
if (program)
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index d1ed621790..762aac2f65 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -160,7 +160,7 @@ public:
void setTranslateZ(GLfloat z);
private:
- Q_DISABLE_COPY(QGL2PaintEngineEx)
+ Q_DISABLE_COPY_MOVE(QGL2PaintEngineEx)
};
class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate, protected QOpenGLExtensions
@@ -175,9 +175,9 @@ public:
QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) :
q(q_ptr),
- shaderManager(0),
+ shaderManager(nullptr),
width(0), height(0),
- ctx(0),
+ ctx(nullptr),
useSystemClip(true),
elementIndicesVBOId(0),
opacityArray(0),
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
index e76216ef5d..7c12ce8998 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
@@ -139,7 +139,7 @@ public:
inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; }
- inline const QOpenGLContextGroup *contextGroup() const { return m_textureResource ? m_textureResource->group() : 0; }
+ inline const QOpenGLContextGroup *contextGroup() const { return m_textureResource ? m_textureResource->group() : nullptr; }
inline int serialNumber() const { return m_serialNumber; }
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index ba4a1dcaa1..2b4af3ef9f 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -397,7 +397,7 @@ QGLFormat::QGLFormat(QGL::FormatOptions options, int plane)
*/
void QGLFormat::detach()
{
- if (d->ref.load() != 1) {
+ if (d->ref.loadRelaxed() != 1) {
QGLFormatPrivate *newd = new QGLFormatPrivate(d);
if (!d->ref.deref())
delete d;
@@ -3880,12 +3880,9 @@ void QGLContext::doneCurrent()
*/
QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
- : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
+ : QWidget(*(new QGLWidgetPrivate), parent, f)
{
Q_D(QGLWidget);
- setAttribute(Qt::WA_PaintOnScreen);
- setAttribute(Qt::WA_NoSystemBackground);
- setAutoFillBackground(true); // for compatibility
d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget);
}
@@ -3893,12 +3890,9 @@ QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFl
\internal
*/
QGLWidget::QGLWidget(QGLWidgetPrivate &dd, const QGLFormat &format, QWidget *parent, const QGLWidget *shareWidget, Qt::WindowFlags f)
- : QWidget(dd, parent, f | Qt::MSWindowsOwnDC)
+ : QWidget(dd, parent, f)
{
Q_D(QGLWidget);
- setAttribute(Qt::WA_PaintOnScreen);
- setAttribute(Qt::WA_NoSystemBackground);
- setAutoFillBackground(true); // for compatibility
d->init(new QGLContext(format, this), shareWidget);
}
@@ -3935,12 +3929,9 @@ QGLWidget::QGLWidget(QGLWidgetPrivate &dd, const QGLFormat &format, QWidget *par
QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent, const QGLWidget* shareWidget,
Qt::WindowFlags f)
- : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
+ : QWidget(*(new QGLWidgetPrivate), parent, f)
{
Q_D(QGLWidget);
- setAttribute(Qt::WA_PaintOnScreen);
- setAttribute(Qt::WA_NoSystemBackground);
- setAutoFillBackground(true); // for compatibility
d->init(new QGLContext(format, this), shareWidget);
}
@@ -3971,12 +3962,9 @@ QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent, const QGLWidget*
*/
QGLWidget::QGLWidget(QGLContext *context, QWidget *parent, const QGLWidget *shareWidget,
Qt::WindowFlags f)
- : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
+ : QWidget(*(new QGLWidgetPrivate), parent, f)
{
Q_D(QGLWidget);
- setAttribute(Qt::WA_PaintOnScreen);
- setAttribute(Qt::WA_NoSystemBackground);
- setAutoFillBackground(true); // for compatibility
d->init(context, shareWidget);
}
@@ -4035,7 +4023,7 @@ QGLWidget::~QGLWidget()
\fn QFunctionPointer QGLContext::getProcAddress(const QString &proc) const
Returns a function pointer to the GL extension function passed in
- \a proc. 0 is returned if a pointer to the function could not be
+ \a proc. \nullptr is returned if a pointer to the function could not be
obtained.
*/
QFunctionPointer QGLContext::getProcAddress(const QString &procName) const
@@ -4131,14 +4119,14 @@ void QGLWidget::swapBuffers()
/*!
\fn const QGLContext* QGLWidget::overlayContext() const
- Returns the overlay context of this widget, or 0 if this widget
- has no overlay.
+ Returns the overlay context of this widget, or \nullptr if this
+ widget has no overlay.
\sa context()
*/
const QGLContext* QGLWidget::overlayContext() const
{
- return 0;
+ return nullptr;
}
/*!
@@ -5169,6 +5157,15 @@ QPaintEngine *QGLWidget::paintEngine() const
void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget)
{
+ Q_Q(QGLWidget);
+ q->setAttribute(Qt::WA_PaintOnScreen);
+ q->setAttribute(Qt::WA_NoSystemBackground);
+ q->setAutoFillBackground(true); // for compatibility
+
+ mustHaveWindowHandle = 1;
+ q->setAttribute(Qt::WA_NativeWindow);
+ q->setWindowFlag(Qt::MSWindowsOwnDC);
+
initContext(context, shareWidget);
}
@@ -5211,7 +5208,7 @@ void QGLContextGroup::addShare(const QGLContext *context, const QGLContext *shar
return;
// Make sure 'context' is not already shared with another group of contexts.
- Q_ASSERT(context->d_ptr->group->m_refs.load() == 1);
+ Q_ASSERT(context->d_ptr->group->m_refs.loadRelaxed() == 1);
// Free 'context' group resources and make it use the same resources as 'share'.
QGLContextGroup *group = share->d_ptr->group;
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
index a1ba0485e0..f5accbeb3c 100644
--- a/src/opengl/qgl.h
+++ b/src/opengl/qgl.h
@@ -51,22 +51,6 @@
#include <QtGui/QSurfaceFormat>
-#if defined(Q_CLANG_QDOC)
-#undef GLint
-typedef int GLint;
-#undef GLuint
-typedef unsigned int GLuint;
-#undef GLenum
-typedef unsigned int GLenum;
-#undef GLclampf
-typedef float GLclampf;
-#undef GLsizei
-typedef int GLsizei;
-#undef GLboolean
-typedef bool GLboolean;
-#endif
-
-
QT_BEGIN_NAMESPACE
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index ed364283cc..4e52c0f5e9 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -203,7 +203,7 @@ const QGLContext *qt_gl_transfer_context(const QGLContext *);
class QGLTemporaryContextPrivate;
class QGLTemporaryContext {
public:
- explicit QGLTemporaryContext(bool directRendering = true, QWidget *parent = 0);
+ explicit QGLTemporaryContext(bool directRendering = true, QWidget *parent = nullptr);
~QGLTemporaryContext();
private:
@@ -302,7 +302,7 @@ class Q_OPENGL_EXPORT QGLShareContextScope
{
public:
QGLShareContextScope(const QGLContext *ctx)
- : m_oldContext(0)
+ : m_oldContext(nullptr)
{
QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
if (currentContext != ctx && !QGLContext::areSharing(ctx, currentContext)) {
@@ -367,7 +367,7 @@ Q_SIGNALS:
class QGLTexture {
public:
- explicit QGLTexture(QGLContext *ctx = 0, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D,
+ explicit QGLTexture(QGLContext *ctx = nullptr, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D,
QGLContext::BindOptions opt = QGLContext::DefaultBindOption)
: context(ctx),
id(tx_id),
@@ -378,7 +378,7 @@ public:
~QGLTexture() {
if (options & QGLContext::MemoryManagedBindOption) {
Q_ASSERT(context);
- QPlatformPixmap *boundPixmap = 0;
+ QPlatformPixmap *boundPixmap = nullptr;
context->d_ptr->texture_destroyer->emitFreeTexture(context, boundPixmap, id);
}
}
@@ -392,9 +392,9 @@ public:
bool canBindCompressedTexture
(const char *buf, int len, const char *format, bool *hasAlpha);
QSize bindCompressedTexture
- (const QString& fileName, const char *format = 0);
+ (const QString& fileName, const char *format = nullptr);
QSize bindCompressedTexture
- (const char *buf, int len, const char *format = 0);
+ (const char *buf, int len, const char *format = nullptr);
QSize bindCompressedTextureDDS(const char *buf, int len);
QSize bindCompressedTexturePVR(const char *buf, int len);
};
diff --git a/src/opengl/qglcolormap.cpp b/src/opengl/qglcolormap.cpp
index d607363ac0..f314a9715d 100644
--- a/src/opengl/qglcolormap.cpp
+++ b/src/opengl/qglcolormap.cpp
@@ -153,7 +153,7 @@ QGLColormap & QGLColormap::operator=(const QGLColormap &map)
void QGLColormap::detach_helper()
{
QGLColormapData *x = new QGLColormapData;
- x->ref.store(1);
+ x->ref.storeRelaxed(1);
x->cmapHandle = 0;
x->cells = 0;
if (d->cells) {
diff --git a/src/opengl/qglcolormap.h b/src/opengl/qglcolormap.h
index 772e327e34..b59b56e040 100644
--- a/src/opengl/qglcolormap.h
+++ b/src/opengl/qglcolormap.h
@@ -90,7 +90,7 @@ private:
inline void QGLColormap::detach()
{
- if (d->ref.load() != 1)
+ if (d->ref.loadRelaxed() != 1)
detach_helper();
}
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index 0b2ddf97fe..d0f82a85fa 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -145,7 +145,7 @@ extern QImage qt_gl_read_frame_buffer(const QSize&, bool, bool);
*/
void QGLFramebufferObjectFormat::detach()
{
- if (d->ref.load() != 1) {
+ if (d->ref.loadRelaxed() != 1) {
QGLFramebufferObjectFormatPrivate *newd
= new QGLFramebufferObjectFormatPrivate(d);
if (!d->ref.deref())
@@ -211,7 +211,7 @@ QGLFramebufferObjectFormat::~QGLFramebufferObjectFormat()
If the desired amount of samples per pixel is not supported by the hardware
then the maximum number of samples per pixel will be used. Note that
- multisample framebuffer objects can not be bound as textures. Also, the
+ multisample framebuffer objects cannot be bound as textures. Also, the
\c{GL_EXT_framebuffer_multisample} extension is required to create a
framebuffer with more than one sample per pixel.
diff --git a/src/opengl/qglframebufferobject_p.h b/src/opengl/qglframebufferobject_p.h
index bf5e21cf0b..9d536527c3 100644
--- a/src/opengl/qglframebufferobject_p.h
+++ b/src/opengl/qglframebufferobject_p.h
@@ -124,9 +124,9 @@ private:
class QGLFramebufferObjectPrivate
{
public:
- QGLFramebufferObjectPrivate() : fbo_guard(0), texture_guard(0), depth_buffer_guard(0)
- , stencil_buffer_guard(0), color_buffer_guard(0)
- , valid(false), engine(0) {}
+ QGLFramebufferObjectPrivate() : fbo_guard(nullptr), texture_guard(nullptr), depth_buffer_guard(nullptr)
+ , stencil_buffer_guard(nullptr), color_buffer_guard(nullptr)
+ , valid(false), engine(nullptr) {}
~QGLFramebufferObjectPrivate() {}
void init(QGLFramebufferObject *q, const QSize& sz,
diff --git a/src/opengl/qglfunctions.cpp b/src/opengl/qglfunctions.cpp
index 7fe7102510..f22f9f470b 100644
--- a/src/opengl/qglfunctions.cpp
+++ b/src/opengl/qglfunctions.cpp
@@ -170,7 +170,8 @@ QGLFunctions::QGLFunctions()
/*!
Constructs a function resolver for \a context. If \a context
- is null, then the resolver will be created for the current QGLContext.
+ is \nullptr, then the resolver will be created for the current
+ QGLContext.
An object constructed in this way can only be used with \a context
and other contexts that share with it. Use initializeGLFunctions()
@@ -305,7 +306,7 @@ bool QGLFunctions::hasOpenGLFeature(QGLFunctions::OpenGLFeature feature) const
/*!
Initializes GL function resolution for \a context. If \a context
- is null, then the current QGLContext will be used.
+ is \nullptr, then the current QGLContext will be used.
After calling this function, the QGLFunctions object can only be
used with \a context and other contexts that share with it.
diff --git a/src/opengl/qglpixelbuffer_p.h b/src/opengl/qglpixelbuffer_p.h
index 9125fcfb4b..2729ade2b6 100644
--- a/src/opengl/qglpixelbuffer_p.h
+++ b/src/opengl/qglpixelbuffer_p.h
@@ -77,7 +77,7 @@ private:
class QGLPixelBufferPrivate {
Q_DECLARE_PUBLIC(QGLPixelBuffer)
public:
- QGLPixelBufferPrivate(QGLPixelBuffer *q) : q_ptr(q), invalid(true), qctx(0), widget(0), fbo(0), blit_fbo(0), pbuf(0), ctx(0)
+ QGLPixelBufferPrivate(QGLPixelBuffer *q) : q_ptr(q), invalid(true), qctx(nullptr), widget(nullptr), fbo(nullptr), blit_fbo(nullptr), pbuf(nullptr), ctx(nullptr)
{
}
bool init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget);
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index 545df8fa44..35f60318be 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -3169,7 +3169,8 @@ GLenum QGLShaderProgram::geometryOutputType() const
Language (GLSL) are supported on this system; false otherwise.
The \a context is used to resolve the GLSL extensions.
- If \a context is null, then QGLContext::currentContext() is used.
+ If \a context is \nullptr, then QGLContext::currentContext() is
+ used.
*/
bool QGLShaderProgram::hasOpenGLShaderPrograms(const QGLContext *context)
{
@@ -3207,7 +3208,8 @@ void QGLShaderProgram::shaderDestroyed()
this system; false otherwise.
The \a context is used to resolve the GLSL extensions.
- If \a context is null, then QGLContext::currentContext() is used.
+ If \a context is \nullptr, then QGLContext::currentContext() is
+ used.
\since 4.7
*/
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
index dfdef44b54..3ce88197d2 100644
--- a/src/opengl/qglshaderprogram.h
+++ b/src/opengl/qglshaderprogram.h
@@ -46,17 +46,6 @@
#include <QtGui/qvector4d.h>
#include <QtGui/qmatrix4x4.h>
-#if defined(Q_CLANG_QDOC)
-#undef GLfloat
-typedef double GLfloat;
-#undef GLint
-typedef int GLint;
-#undef GLuint
-typedef unsigned int GLuint;
-#undef GLenum
-typedef unsigned int GLenum;
-#endif
-
QT_BEGIN_NAMESPACE
diff --git a/src/opengl/qgraphicsshadereffect_p.h b/src/opengl/qgraphicsshadereffect_p.h
index 9efcecd25f..218caa2936 100644
--- a/src/opengl/qgraphicsshadereffect_p.h
+++ b/src/opengl/qgraphicsshadereffect_p.h
@@ -67,7 +67,7 @@ class Q_OPENGL_EXPORT QGraphicsShaderEffect : public QGraphicsEffect
{
Q_OBJECT
public:
- QGraphicsShaderEffect(QObject *parent = 0);
+ QGraphicsShaderEffect(QObject *parent = nullptr);
virtual ~QGraphicsShaderEffect();
QByteArray pixelShaderFragment() const;
@@ -80,7 +80,7 @@ protected:
private:
Q_DECLARE_PRIVATE(QGraphicsShaderEffect)
- Q_DISABLE_COPY(QGraphicsShaderEffect)
+ Q_DISABLE_COPY_MOVE(QGraphicsShaderEffect)
friend class QGLCustomShaderEffectStage;
};
diff --git a/src/platformheaders/doc/qtplatformheaders.qdocconf b/src/platformheaders/doc/qtplatformheaders.qdocconf
index 1ff6fe7a21..9a034e7671 100644
--- a/src/platformheaders/doc/qtplatformheaders.qdocconf
+++ b/src/platformheaders/doc/qtplatformheaders.qdocconf
@@ -35,5 +35,7 @@ sourcedirs += ..
exampledirs += snippets
imagedirs += images
+tagfile = qtplatformheaders.tags
+
navigation.landingpage = "Qt Platform Headers"
navigation.cppclassespage = "Qt Platform Headers C++ Classes"
diff --git a/src/platformheaders/doc/src/dontdocument.qdoc b/src/platformheaders/doc/src/dontdocument.qdoc
new file mode 100644
index 0000000000..dc02c6473e
--- /dev/null
+++ b/src/platformheaders/doc/src/dontdocument.qdoc
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+/*!
+ \dontdocument (QMetaTypeId)
+*/
diff --git a/src/platformheaders/nativecontexts/qeglnativecontext.h b/src/platformheaders/nativecontexts/qeglnativecontext.h
index d4a0e998da..5af2b304fe 100644
--- a/src/platformheaders/nativecontexts/qeglnativecontext.h
+++ b/src/platformheaders/nativecontexts/qeglnativecontext.h
@@ -54,8 +54,8 @@ typedef int EGLDisplay;
struct QEGLNativeContext
{
QEGLNativeContext()
- : m_context(0),
- m_display(0)
+ : m_context(nullptr),
+ m_display(nullptr)
{ }
QEGLNativeContext(EGLContext ctx, EGLDisplay dpy)
diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
index e51c2fde67..032dcafa6e 100644
--- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
+++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
@@ -81,6 +81,15 @@ public:
func(window, border);
}
+ typedef void (*SetHasBorderInFullScreenDefault)(bool border);
+ static const QByteArray setHasBorderInFullScreenDefaultIdentifier() { return QByteArrayLiteral("WindowsSetHasBorderInFullScreenDefault"); }
+ static void setHasBorderInFullScreenDefault(bool border)
+ {
+ auto func = reinterpret_cast<SetHasBorderInFullScreenDefault>(QGuiApplication::platformFunction(setHasBorderInFullScreenDefaultIdentifier()));
+ if (func)
+ func(border);
+ }
+
typedef void (*SetWindowActivationBehaviorType)(WindowActivationBehavior);
static const QByteArray setWindowActivationBehaviorIdentifier() { return QByteArrayLiteral("WindowsSetWindowActivationBehavior"); }
diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
index a52bbe061b..0c52cde753 100644
--- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
+++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
@@ -93,7 +93,40 @@
is true then it will enable the WS_BORDER flag in full screen mode to enable other top level windows
inside the application to appear on top when required.
+ \note The setting must be applied before showing the window or switching it
+ to full screen. For QML, setHasBorderInFullScreenDefault() can be used to
+ set a default value.
+
+ See also \l [QtDoc] {Fullscreen OpenGL Based Windows}
+*/
+
+/*!
+ \typedef QWindowsWindowFunctions::SetHasBorderInFullScreenDefault
+ \since 5.13
+
+ This is the typedef for the function returned by QGuiApplication::platformFunction
+ when passed setHasBorderInFullScreenDefaultIdentifier.
+*/
+
+/*!
+ \fn QByteArray QWindowsWindowFunctions::setHasBorderInFullScreenDefaultIdentifier()
+ \since 5.13
+
+ This function returns the bytearray that can be used to query
+ QGuiApplication::platformFunction to retrieve the SetHasBorderInFullScreen function.
+*/
+
+/*!
+ \fn void QWindowsWindowFunctions::setHasBorderInFullScreenDefault(bool border)
+ \since 5.13
+
+ This is a convenience function that can be used directly instead of resolving
+ the function pointer. \a border will be relayed to the function retrieved by
+ QGuiApplication. When \a border is true, the WS_BORDER flag will be set
+ in full screen mode for all windows by default.
+
See also \l [QtDoc] {Fullscreen OpenGL Based Windows}
+ \sa setHasBorderInFullScreen()
*/
/*!
diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_p.h b/src/platformsupport/devicediscovery/qdevicediscovery_p.h
index e3c22b0b37..f1f50e9708 100644
--- a/src/platformsupport/devicediscovery/qdevicediscovery_p.h
+++ b/src/platformsupport/devicediscovery/qdevicediscovery_p.h
@@ -86,7 +86,7 @@ public:
Q_ENUM(QDeviceType)
Q_DECLARE_FLAGS(QDeviceTypes, QDeviceType)
- static QDeviceDiscovery *create(QDeviceTypes type, QObject *parent = 0);
+ static QDeviceDiscovery *create(QDeviceTypes type, QObject *parent = nullptr);
virtual QStringList scanConnectedDevices() = 0;
@@ -96,7 +96,7 @@ signals:
protected:
QDeviceDiscovery(QDeviceTypes types, QObject *parent) : QObject(parent), m_types(types) { }
- Q_DISABLE_COPY(QDeviceDiscovery)
+ Q_DISABLE_COPY_MOVE(QDeviceDiscovery)
QDeviceTypes m_types;
};
diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_udev_p.h b/src/platformsupport/devicediscovery/qdevicediscovery_udev_p.h
index 28618d0b21..82b475776d 100644
--- a/src/platformsupport/devicediscovery/qdevicediscovery_udev_p.h
+++ b/src/platformsupport/devicediscovery/qdevicediscovery_udev_p.h
@@ -61,7 +61,7 @@ class QDeviceDiscoveryUDev : public QDeviceDiscovery
Q_OBJECT
public:
- QDeviceDiscoveryUDev(QDeviceTypes types, struct udev *udev, QObject *parent = 0);
+ QDeviceDiscoveryUDev(QDeviceTypes types, struct udev *udev, QObject *parent = nullptr);
~QDeviceDiscoveryUDev();
QStringList scanConnectedDevices() override;
diff --git a/src/platformsupport/eglconvenience/qeglpbuffer_p.h b/src/platformsupport/eglconvenience/qeglpbuffer_p.h
index 0285e067a6..8ad2eb7248 100644
--- a/src/platformsupport/eglconvenience/qeglpbuffer_p.h
+++ b/src/platformsupport/eglconvenience/qeglpbuffer_p.h
@@ -60,7 +60,7 @@ class QEGLPbuffer : public QPlatformOffscreenSurface
{
public:
QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface,
- QEGLPlatformContext::Flags flags = 0);
+ QEGLPlatformContext::Flags flags = nullptr);
~QEGLPbuffer();
QSurfaceFormat format() const override { return m_format; }
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index e44918823b..94def16748 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -338,14 +338,6 @@ void QEGLPlatformContext::updateFormatFromGL()
QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
int major, minor;
if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
- // Some Android 4.2.2 devices report OpenGL ES 3.0 without the functions being available.
- static int apiLevel = QtAndroidPrivate::androidSdkVersion();
- if (apiLevel <= 17 && major >= 3) {
- major = 2;
- minor = 0;
- }
-#endif
m_format.setMajorVersion(major);
m_format.setMinorVersion(minor);
}
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
index d6cbbe4131..ed77c57df5 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
@@ -68,8 +68,8 @@ public:
Q_DECLARE_FLAGS(Flags, Flag)
QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
- EGLConfig *config = 0, const QVariant &nativeHandle = QVariant(),
- Flags flags = 0);
+ EGLConfig *config = nullptr, const QVariant &nativeHandle = QVariant(),
+ Flags flags = nullptr);
~QEGLPlatformContext();
void initialize() override;
diff --git a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h
index c3d3070210..31a79dbc6c 100644
--- a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h
+++ b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h
@@ -131,6 +131,12 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
#endif
+#ifndef EGL_EXT_stream_acquire_mode
+#define EGL_EXT_stream_acquire_mode 1
+#define EGL_CONSUMER_AUTO_ACQUIRE_EXT 0x332B
+#define EGL_RESOURCE_BUSY_EXT 0x3353
+#endif
+
#ifndef EGL_EXT_platform_device
#define EGL_PLATFORM_DEVICE_EXT 0x313F
#endif
@@ -156,6 +162,11 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC) (EGLDi
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
#endif
+#ifndef EGL_NV_output_drm_flip_event
+#define EGL_NV_output_drm_flip_event 1
+#define EGL_DRM_FLIP_EVENT_DATA_NV 0x333E
+#endif
+
QT_BEGIN_NAMESPACE
class QEGLStreamConvenience
diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h b/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
index 085a1c52f3..b9254d3071 100644
--- a/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
+++ b/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
@@ -64,7 +64,7 @@ class QPAEventDispatcherGlib : public QEventDispatcherGlib
Q_DECLARE_PRIVATE(QPAEventDispatcherGlib)
public:
- explicit QPAEventDispatcherGlib(QObject *parent = 0);
+ explicit QPAEventDispatcherGlib(QObject *parent = nullptr);
~QPAEventDispatcherGlib();
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
@@ -77,7 +77,7 @@ class QPAEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate
{
Q_DECLARE_PUBLIC(QPAEventDispatcherGlib)
public:
- QPAEventDispatcherGlibPrivate(GMainContext *context = 0);
+ QPAEventDispatcherGlibPrivate(GMainContext *context = nullptr);
GUserEventSource *userEventSource;
};
diff --git a/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h b/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h
index 7f775b73ee..8157b8793d 100644
--- a/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h
+++ b/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h
@@ -61,7 +61,7 @@ class QUnixEventDispatcherQPA : public QEventDispatcherUNIX
Q_OBJECT
public:
- explicit QUnixEventDispatcherQPA(QObject *parent = 0);
+ explicit QUnixEventDispatcherQPA(QObject *parent = nullptr);
~QUnixEventDispatcherQPA();
bool processEvents(QEventLoop::ProcessEventsFlags flags);
diff --git a/src/platformsupport/fbconvenience/qfbvthandler_p.h b/src/platformsupport/fbconvenience/qfbvthandler_p.h
index 17d07317b2..d565ec3632 100644
--- a/src/platformsupport/fbconvenience/qfbvthandler_p.h
+++ b/src/platformsupport/fbconvenience/qfbvthandler_p.h
@@ -63,7 +63,7 @@ class QFbVtHandler : public QObject
Q_OBJECT
public:
- QFbVtHandler(QObject *parent = 0);
+ QFbVtHandler(QObject *parent = nullptr);
~QFbVtHandler();
signals:
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index e545d54ec2..7abf295782 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -721,7 +721,7 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont
FcValue value;
value.type = FcTypeString;
- QByteArray cs = family.toUtf8();
+ const QByteArray cs = family.toUtf8();
value.u.s = (const FcChar8 *)cs.data();
FcPatternAdd(pattern,FC_FAMILY,value,true);
@@ -863,7 +863,7 @@ QString QFontconfigDatabase::resolveFontFamilyAlias(const QString &family) const
return family;
if (!family.isEmpty()) {
- QByteArray cs = family.toUtf8();
+ const QByteArray cs = family.toUtf8();
FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) cs.constData());
}
FcConfigSubstitute(0, pattern, FcMatchPattern);
diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
index 8d6620a55f..8d0a20f7b9 100644
--- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
+++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
@@ -121,13 +121,12 @@ class QtFreetypeData
{
public:
QtFreetypeData()
- : library(0), hasPatentFreeLcdRendering(false)
+ : library(0)
{ }
~QtFreetypeData();
FT_Library library;
QHash<QFontEngine::FaceId, QFreetypeFace *> faces;
- bool hasPatentFreeLcdRendering;
};
QtFreetypeData::~QtFreetypeData()
@@ -153,11 +152,6 @@ QtFreetypeData *qt_getFreetypeData()
FT_Bool no_darkening = false;
FT_Property_Set(freetypeData->library, "cff", "no-stem-darkening", &no_darkening);
#endif
- // FreeType has since 2.8.1 a patent free alternative to LCD-filtering.
- FT_Int amajor, aminor = 0, apatch = 0;
- FT_Library_Version(freetypeData->library, &amajor, &aminor, &apatch);
- if (QT_VERSION_CHECK(amajor, aminor, apatch) >= QT_VERSION_CHECK(2, 8, 1))
- freetypeData->hasPatentFreeLcdRendering = true;
}
return freetypeData;
}
@@ -260,7 +254,7 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
}
newFreetype->face = face;
- newFreetype->ref.store(1);
+ newFreetype->ref.storeRelaxed(1);
newFreetype->xsize = 0;
newFreetype->ysize = 0;
newFreetype->matrix.xx = 0x10000;
@@ -561,26 +555,7 @@ QFontEngineFT::Glyph::~Glyph()
delete [] data;
}
-struct LcdFilterDummy
-{
- static inline void filterPixel(uchar &, uchar &, uchar &)
- {}
-};
-
-struct LcdFilterLegacy
-{
- static inline void filterPixel(uchar &red, uchar &green, uchar &blue)
- {
- uint r = red, g = green, b = blue;
- // intra-pixel filter used by the legacy filter (adopted from _ft_lcd_filter_legacy)
- red = (r * uint(65538 * 9/13) + g * uint(65538 * 1/6) + b * uint(65538 * 1/13)) / 65536;
- green = (r * uint(65538 * 3/13) + g * uint(65538 * 4/6) + b * uint(65538 * 3/13)) / 65536;
- blue = (r * uint(65538 * 1/13) + g * uint(65538 * 1/6) + b * uint(65538 * 9/13)) / 65536;
- }
-};
-
-template <typename LcdFilter>
-static void convertRGBToARGB_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
+static inline void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
{
const int offs = bgr ? -1 : 1;
const int w = width * 3;
@@ -590,7 +565,6 @@ static void convertRGBToARGB_helper(const uchar *src, uint *dst, int width, int
uchar red = src[x + 1 - offs];
uchar green = src[x + 1];
uchar blue = src[x + 1 + offs];
- LcdFilter::filterPixel(red, green, blue);
*dd++ = (0xFFU << 24) | (red << 16) | (green << 8) | blue;
}
dst += width;
@@ -598,16 +572,7 @@ static void convertRGBToARGB_helper(const uchar *src, uint *dst, int width, int
}
}
-static inline void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
-{
- if (!legacyFilter)
- convertRGBToARGB_helper<LcdFilterDummy>(src, dst, width, height, src_pitch, bgr);
- else
- convertRGBToARGB_helper<LcdFilterLegacy>(src, dst, width, height, src_pitch, bgr);
-}
-
-template <typename LcdFilter>
-static void convertRGBToARGB_V_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
+static inline void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
{
const int offs = bgr ? -src_pitch : src_pitch;
while (height--) {
@@ -615,54 +580,12 @@ static void convertRGBToARGB_V_helper(const uchar *src, uint *dst, int width, in
uchar red = src[x + src_pitch - offs];
uchar green = src[x + src_pitch];
uchar blue = src[x + src_pitch + offs];
- LcdFilter::filterPixel(red, green, blue);
*dst++ = (0XFFU << 24) | (red << 16) | (green << 8) | blue;
}
src += 3*src_pitch;
}
}
-static inline void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
-{
- if (!legacyFilter)
- convertRGBToARGB_V_helper<LcdFilterDummy>(src, dst, width, height, src_pitch, bgr);
- else
- convertRGBToARGB_V_helper<LcdFilterLegacy>(src, dst, width, height, src_pitch, bgr);
-}
-
-static inline void convertGRAYToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch)
-{
- while (height--) {
- const uchar *p = src;
- const uchar * const e = p + width;
- while (p < e) {
- uchar gray = *p++;
- *dst++ = (0xFFU << 24) | (gray << 16) | (gray << 8) | gray;
- }
- src += src_pitch;
- }
-}
-
-static void convoluteBitmap(const uchar *src, uchar *dst, int width, int height, int pitch)
-{
- // convolute the bitmap with a triangle filter to get rid of color fringes
- // If we take account for a gamma value of 2, we end up with
- // weights of 1, 4, 9, 4, 1. We use an approximation of 1, 3, 8, 3, 1 here,
- // as this nicely sums up to 16 :)
- int h = height;
- while (h--) {
- dst[0] = dst[1] = 0;
- //
- for (int x = 2; x < width - 2; ++x) {
- uint sum = src[x-2] + 3*src[x-1] + 8*src[x] + 3*src[x+1] + src[x+2];
- dst[x] = (uchar) (sum >> 4);
- }
- dst[width - 2] = dst[width - 1] = 0;
- src += pitch;
- dst += pitch;
- }
-}
-
static QFontEngine::SubpixelAntialiasingType subpixelAntialiasingTypeHint()
{
static int type = -1;
@@ -1153,196 +1076,97 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
int glyph_buffer_size = 0;
QScopedArrayPointer<uchar> glyph_buffer;
- bool useFreetypeRenderGlyph = false;
- if (slot->format == FT_GLYPH_FORMAT_OUTLINE && (hsubpixel || vfactor != 1)) {
- err = FT_Library_SetLcdFilter(slot->library, (FT_LcdFilter)lcdFilterType);
- // We use FT_Render_Glyph if freetype has support for lcd-filtering
- // or is version 2.8.1 or higher and can do without.
- if (err == FT_Err_Ok || qt_getFreetypeData()->hasPatentFreeLcdRendering)
- useFreetypeRenderGlyph = true;
+ FT_Render_Mode renderMode = (default_hint_style == HintLight) ? FT_RENDER_MODE_LIGHT : FT_RENDER_MODE_NORMAL;
+ switch (format) {
+ case Format_Mono:
+ renderMode = FT_RENDER_MODE_MONO;
+ break;
+ case Format_A32:
+ Q_ASSERT(hsubpixel || vfactor != 1);
+ renderMode = hsubpixel ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_LCD_V;
+ break;
+ case Format_A8:
+ case Format_ARGB:
+ break;
+ default:
+ Q_UNREACHABLE();
}
- if (useFreetypeRenderGlyph) {
- err = FT_Render_Glyph(slot, hsubpixel ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_LCD_V);
-
- if (err != FT_Err_Ok)
- qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
-
- FT_Library_SetLcdFilter(slot->library, FT_LCD_FILTER_NONE);
+ FT_Library_SetLcdFilter(slot->library, (FT_LcdFilter)lcdFilterType);
- info.height = slot->bitmap.rows / vfactor;
- info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width;
- info.x = slot->bitmap_left;
- info.y = slot->bitmap_top;
+ err = FT_Render_Glyph(slot, renderMode);
+ if (err != FT_Err_Ok)
+ qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
- glyph_buffer_size = info.width * info.height * 4;
- glyph_buffer.reset(new uchar[glyph_buffer_size]);
+ FT_Library_SetLcdFilter(slot->library, FT_LCD_FILTER_NONE);
- if (hsubpixel)
- convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB, false);
- else if (vfactor != 1)
- convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB, false);
- } else {
- int left = slot->metrics.horiBearingX;
- int right = slot->metrics.horiBearingX + slot->metrics.width;
- int top = slot->metrics.horiBearingY;
- int bottom = slot->metrics.horiBearingY - slot->metrics.height;
- if (transform && slot->format != FT_GLYPH_FORMAT_BITMAP)
- transformBoundingBox(&left, &top, &right, &bottom, &matrix);
- left = FLOOR(left);
- right = CEIL(right);
- bottom = FLOOR(bottom);
- top = CEIL(top);
-
- int hpixels = TRUNC(right - left);
- // subpixel position requires one more pixel
- if (subPixelPosition > 0 && format != Format_Mono)
- hpixels++;
-
- if (hsubpixel)
- hpixels = hpixels*3 + 8;
- info.width = hpixels;
- info.height = TRUNC(top - bottom);
- info.x = TRUNC(left);
- info.y = TRUNC(top);
- if (hsubpixel) {
- info.width /= 3;
- info.x -= 1;
- }
-
- // If any of the metrics are too large to fit, don't cache them
- if (areMetricsTooLarge(info))
- return 0;
+ info.height = slot->bitmap.rows;
+ info.width = slot->bitmap.width;
+ info.x = slot->bitmap_left;
+ info.y = slot->bitmap_top;
+ if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD)
+ info.width = info.width / 3;
+ if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V)
+ info.height = info.height / vfactor;
int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 :
(format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4));
- if (glyph_buffer_size < pitch * info.height) {
- glyph_buffer_size = pitch * info.height;
- glyph_buffer.reset(new uchar[glyph_buffer_size]);
- memset(glyph_buffer.data(), 0, glyph_buffer_size);
- }
- if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
- FT_Bitmap bitmap;
- bitmap.rows = info.height*vfactor;
- bitmap.width = hpixels;
- bitmap.pitch = format == Format_Mono ? (((info.width + 31) & ~31) >> 3) : ((bitmap.width + 3) & ~3);
- int bitmap_buffer_size = bitmap.rows * bitmap.pitch;
- if (!hsubpixel && vfactor == 1 && format != Format_A32) {
- Q_ASSERT(glyph_buffer_size <= bitmap_buffer_size);
- bitmap.buffer = glyph_buffer.data();
- } else {
- bitmap.buffer = new uchar[bitmap_buffer_size];
- memset(bitmap.buffer, 0, bitmap_buffer_size);
- }
- bitmap.pixel_mode = format == Format_Mono ? FT_PIXEL_MODE_MONO : FT_PIXEL_MODE_GRAY;
- FT_Matrix matrix;
- matrix.xx = (hsubpixel ? 3 : 1) << 16;
- matrix.yy = vfactor << 16;
- matrix.yx = matrix.xy = 0;
-
- FT_Outline_Transform(&slot->outline, &matrix);
- FT_Outline_Translate (&slot->outline, (hsubpixel ? -3*left +(4<<6) : -left), -bottom*vfactor);
- FT_Outline_Get_Bitmap(slot->library, &slot->outline, &bitmap);
- if (hsubpixel) {
- Q_ASSERT (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
- Q_ASSERT(antialias);
- uchar *convoluted = new uchar[bitmap_buffer_size];
- bool useLegacyLcdFilter = false;
- useLegacyLcdFilter = (lcdFilterType == FT_LCD_FILTER_LEGACY);
- uchar *buffer = bitmap.buffer;
- if (!useLegacyLcdFilter) {
- convoluteBitmap(bitmap.buffer, convoluted, bitmap.width, info.height, bitmap.pitch);
- buffer = convoluted;
- }
- convertRGBToARGB(buffer + 1, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch, subpixelType != Subpixel_RGB, useLegacyLcdFilter);
- delete [] convoluted;
- } else if (vfactor != 1) {
- convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch, subpixelType != Subpixel_VRGB, true);
- } else if (format == Format_A32 && bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
- convertGRAYToARGB(bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch);
- }
+ glyph_buffer_size = info.height * pitch;
+ glyph_buffer.reset(new uchar[glyph_buffer_size]);
- if (bitmap.buffer != glyph_buffer.data())
- delete [] bitmap.buffer;
- } else if (slot->format == FT_GLYPH_FORMAT_BITMAP) {
-#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100) >= 20500)
- Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO || slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA);
-#else
- Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO);
-#endif
+ if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
+ Q_ASSERT(format == Format_Mono);
uchar *src = slot->bitmap.buffer;
uchar *dst = glyph_buffer.data();
int h = slot->bitmap.rows;
- if (format == Format_Mono) {
- int bytes = ((info.width + 7) & ~7) >> 3;
- while (h--) {
- memcpy (dst, src, bytes);
- dst += pitch;
- src += slot->bitmap.pitch;
- }
- } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
- if (hsubpixel) {
- while (h--) {
- uint *dd = (uint *)dst;
- *dd++ = 0;
- for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++) {
- uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000);
- *dd++ = a;
- }
- *dd++ = 0;
- dst += pitch;
- src += slot->bitmap.pitch;
- }
- } else if (vfactor != 1) {
- while (h--) {
- uint *dd = (uint *)dst;
- for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++) {
- uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000);
- *dd++ = a;
- }
- dst += pitch;
- src += slot->bitmap.pitch;
- }
- } else {
- while (h--) {
- for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++) {
- unsigned char a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xff : 0x00);
- dst[x] = a;
- }
- dst += pitch;
- src += slot->bitmap.pitch;
- }
- }
+
+ int bytes = ((info.width + 7) & ~7) >> 3;
+ while (h--) {
+ memcpy (dst, src, bytes);
+ dst += pitch;
+ src += slot->bitmap.pitch;
}
-#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100) >= 20500)
- else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
- {
- while (h--) {
+ } else if (slot->bitmap.pixel_mode == 7 /*FT_PIXEL_MODE_BGRA*/) {
+ Q_ASSERT(format == Format_ARGB);
+ uchar *src = slot->bitmap.buffer;
+ uchar *dst = glyph_buffer.data();
+ int h = slot->bitmap.rows;
+ while (h--) {
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- const quint32 *srcPixel = (const quint32 *)src;
- quint32 *dstPixel = (quint32 *)dst;
- for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++, srcPixel++, dstPixel++) {
- const quint32 pixel = *srcPixel;
- *dstPixel = qbswap(pixel);
- }
+ const quint32 *srcPixel = (const quint32 *)src;
+ quint32 *dstPixel = (quint32 *)dst;
+ for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++, srcPixel++, dstPixel++) {
+ const quint32 pixel = *srcPixel;
+ *dstPixel = qbswap(pixel);
+ }
#else
- memcpy(dst, src, slot->bitmap.width * 4);
+ memcpy(dst, src, slot->bitmap.width * 4);
#endif
- dst += slot->bitmap.pitch;
- src += slot->bitmap.pitch;
- }
- info.width = info.linearAdvance = info.xOff = slot->bitmap.width;
- info.height = slot->bitmap.rows;
- info.x = slot->bitmap_left;
- info.y = slot->bitmap_top;
+ dst += slot->bitmap.pitch;
+ src += slot->bitmap.pitch;
}
-#endif
+ info.linearAdvance = info.xOff = slot->bitmap.width;
+ } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
+ Q_ASSERT(format == Format_A8);
+ uchar *src = slot->bitmap.buffer;
+ uchar *dst = glyph_buffer.data();
+ int h = slot->bitmap.rows;
+ int bytes = info.width;
+ while (h--) {
+ memcpy (dst, src, bytes);
+ dst += pitch;
+ src += slot->bitmap.pitch;
+ }
+ } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) {
+ Q_ASSERT(format == Format_A32);
+ convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB);
+ } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) {
+ Q_ASSERT(format == Format_A32);
+ convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB);
} else {
- qWarning("QFontEngine: Glyph neither outline nor bitmap format=%d", slot->format);
+ qWarning("QFontEngine: Glyph rendered in unknown pixel_mode=%d", slot->bitmap.pixel_mode);
return 0;
}
- }
-
if (!g) {
g = new Glyph;
@@ -1556,7 +1380,7 @@ QFontEngineFT::QGlyphSet *QFontEngineFT::loadGlyphSet(const QTransform &matrix)
gs = &transformedGlyphSets[0];
gs->clear();
gs->transformationMatrix = m;
- gs->outline_drawing = fontDef.pixelSize * fontDef.pixelSize * qAbs(matrix.det()) >= QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE;
+ gs->outline_drawing = fontDef.pixelSize * fontDef.pixelSize * qAbs(matrix.determinant()) > QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE;
}
Q_ASSERT(gs != 0);
diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h
index d498b0ac8b..2d1d5e6572 100644
--- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h
+++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h
@@ -268,7 +268,7 @@ private:
inline bool isScalableBitmap() const { return freetype->isScalableBitmap(); }
inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const
- { return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly, disableOutlineDrawing); }
+ { return loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr, glyph, subPixelPosition, format, fetchMetricsOnly, disableOutlineDrawing); }
Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const;
Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t, bool fetchBoundingBox = false, bool disableOutlineDrawing = false);
diff --git a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp
index 4baba64de3..25c10fbd3c 100644
--- a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp
@@ -127,7 +127,7 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
error = FT_New_Face(library, file.constData(), index, &face);
}
if (error != FT_Err_Ok) {
- qDebug() << "FT_New_Face failed with index" << index << ':' << hex << error;
+ qDebug() << "FT_New_Face failed with index" << index << ':' << Qt::hex << error;
break;
}
numFaces = face->num_faces;
@@ -142,7 +142,6 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
weight = QFont::Bold;
bool fixedPitch = (face->face_flags & FT_FACE_FLAG_FIXED_WIDTH);
-
QSupportedWritingSystems writingSystems;
// detect symbol fonts
for (int i = 0; i < face->num_charmaps; ++i) {
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
index 9e6e5d88c7..79f7eb3d43 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
@@ -1007,12 +1007,27 @@ static QChar *createFontFile(const QString &faceName)
return faceNamePtr;
}
+namespace {
+ struct StoreFontPayload {
+ StoreFontPayload(const QString &family,
+ QWindowsFontDatabase *fontDatabase)
+ : populatedFontFamily(family)
+ , windowsFontDatabase(fontDatabase)
+ {}
+
+ QString populatedFontFamily;
+ QSet<QPair<QString,QString> > foundFontAndStyles;
+ QWindowsFontDatabase *windowsFontDatabase;
+ };
+}
+
static bool addFontToDatabase(QString familyName,
QString styleName,
const LOGFONT &logFont,
const TEXTMETRIC *textmetric,
const FONTSIGNATURE *signature,
- int type)
+ int type,
+ StoreFontPayload *sfp)
{
// the "@family" fonts are just the same as "family". Ignore them.
if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_")))
@@ -1092,6 +1107,16 @@ static bool addFontToDatabase(QString familyName,
writingSystems.setSupported(ws);
}
+ // We came here from populating a different font family, so we have
+ // to ensure the entire typographic family is populated before we
+ // mark it as such inside registerFont()
+ if (!subFamilyName.isEmpty()
+ && familyName != subFamilyName
+ && sfp->populatedFontFamily != familyName
+ && !QPlatformFontDatabase::isFamilyPopulated(familyName)) {
+ sfp->windowsFontDatabase->populateFamily(familyName);
+ }
+
QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight,
style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
@@ -1128,17 +1153,18 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t
// to the documentation is identical to a TEXTMETRIC except for the last four
// members, which we don't use anyway
const FONTSIGNATURE *signature = nullptr;
+ StoreFontPayload *sfp = reinterpret_cast<StoreFontPayload *>(lparam);
+ Q_ASSERT(sfp != nullptr);
if (type & TRUETYPE_FONTTYPE) {
signature = &reinterpret_cast<const NEWTEXTMETRICEX *>(textmetric)->ntmFontSig;
// We get a callback for each script-type supported, but we register them all
// at once using the signature, so we only need one call to addFontToDatabase().
- QSet<QPair<QString,QString>> *foundFontAndStyles = reinterpret_cast<QSet<QPair<QString,QString>> *>(lparam);
QPair<QString,QString> fontAndStyle(familyName, styleName);
- if (foundFontAndStyles->contains(fontAndStyle))
+ if (sfp->foundFontAndStyles.contains(fontAndStyle))
return 1;
- foundFontAndStyles->insert(fontAndStyle);
+ sfp->foundFontAndStyles.insert(fontAndStyle);
}
- addFontToDatabase(familyName, styleName, *logFont, textmetric, signature, type);
+ addFontToDatabase(familyName, styleName, *logFont, textmetric, signature, type, sfp);
// keep on enumerating
return 1;
@@ -1157,8 +1183,8 @@ void QWindowsFontDatabase::populateFamily(const QString &familyName)
familyName.toWCharArray(lf.lfFaceName);
lf.lfFaceName[familyName.size()] = 0;
lf.lfPitchAndFamily = 0;
- QSet<QPair<QString,QString>> foundFontAndStyles;
- EnumFontFamiliesEx(dummy, &lf, storeFont, reinterpret_cast<intptr_t>(&foundFontAndStyles), 0);
+ StoreFontPayload sfp(familyName, this);
+ EnumFontFamiliesEx(dummy, &lf, storeFont, reinterpret_cast<intptr_t>(&sfp), 0);
ReleaseDC(0, dummy);
}
@@ -1338,11 +1364,11 @@ QT_WARNING_POP
if (request.family != fontEngine->fontDef.family) {
qWarning("%s: Failed to load font. Got fallback instead: %s",
__FUNCTION__, qPrintable(fontEngine->fontDef.family));
- if (fontEngine->ref.load() == 0)
+ if (fontEngine->ref.loadRelaxed() == 0)
delete fontEngine;
fontEngine = 0;
} else {
- Q_ASSERT(fontEngine->ref.load() == 0);
+ Q_ASSERT(fontEngine->ref.loadRelaxed() == 0);
// Override the generated font name
switch (fontEngine->type()) {
@@ -1514,7 +1540,7 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
if (names.name.isEmpty())
continue;
- families->append(qMove(names));
+ families->append(std::move(names));
if (values || signatures)
getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
@@ -1598,8 +1624,9 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
TEXTMETRIC textMetrics;
GetTextMetrics(hdc, &textMetrics);
+ StoreFontPayload sfp(familyName, this);
addFontToDatabase(familyName, styleName, lf, &textMetrics, &signatures.at(j),
- TRUETYPE_FONTTYPE);
+ TRUETYPE_FONTTYPE, &sfp);
SelectObject(hdc, oldobj);
DeleteObject(hfont);
@@ -1818,7 +1845,7 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request, const QS
QString fam = faceName;
if (fam.isEmpty())
- fam = request.family;
+ fam = request.families.size() > 0 ? request.families.at(0) : request.family;
if (Q_UNLIKELY(fam.size() >= LF_FACESIZE)) {
qCritical("%s: Family name '%s' is too long.", __FUNCTION__, qPrintable(fam));
fam.truncate(LF_FACESIZE - 1);
@@ -1961,13 +1988,13 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q
} else {
HGDIOBJ oldFont = SelectObject(data->hdc, hfont);
+ const QFont::HintingPreference hintingPreference =
+ static_cast<QFont::HintingPreference>(request.hintingPreference);
+ bool useDw = useDirectWrite(hintingPreference, fam);
+
IDWriteFontFace *directWriteFontFace = NULL;
HRESULT hr = data->directWriteGdiInterop->CreateFontFaceFromHdc(data->hdc, &directWriteFontFace);
- if (FAILED(hr)) {
- const QString errorString = qt_error_string(int(hr));
- qWarning().noquote().nospace() << "DirectWrite: CreateFontFaceFromHDC() failed ("
- << errorString << ") for " << request << ' ' << lf << " dpi=" << dpi;
- } else {
+ if (SUCCEEDED(hr)) {
bool isColorFont = false;
#if defined(QT_USE_DIRECTWRITE2)
IDWriteFontFace2 *directWriteFontFace2 = nullptr;
@@ -1977,9 +2004,7 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q
isColorFont = directWriteFontFace2->GetPaletteEntryCount() > 0;
}
#endif
- const QFont::HintingPreference hintingPreference =
- static_cast<QFont::HintingPreference>(request.hintingPreference);
- const bool useDw = useDirectWrite(hintingPreference, fam, isColorFont);
+ useDw = useDw || useDirectWrite(hintingPreference, fam, isColorFont);
qCDebug(lcQpaFonts) << __FUNCTION__ << request.family << request.pointSize
<< "pt" << "hintingPreference=" << hintingPreference << "color=" << isColorFont
<< dpi << "dpi" << "useDirectWrite=" << useDw;
@@ -2001,6 +2026,10 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q
} else {
directWriteFontFace->Release();
}
+ } else if (useDw) {
+ const QString errorString = qt_error_string(int(hr));
+ qWarning().noquote().nospace() << "DirectWrite: CreateFontFaceFromHDC() failed ("
+ << errorString << ") for " << request << ' ' << lf << " dpi=" << dpi;
}
SelectObject(data->hdc, oldFont);
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
index fdef0f5ff1..a6b7fcf31e 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
@@ -48,7 +48,11 @@
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
#include <QtCore/QSettings>
+#if QT_CONFIG(regularexpression)
#include <QtCore/QRegularExpression>
+#else
+#include <QtCore/QRegExp>
+#endif
#include <QtGui/QGuiApplication>
#include <QtGui/QFontDatabase>
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
index afba86bbe1..a1cab17a87 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
@@ -67,7 +67,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaFonts)
class QWindowsFontEngineData
{
- Q_DISABLE_COPY(QWindowsFontEngineData)
+ Q_DISABLE_COPY_MOVE(QWindowsFontEngineData)
public:
QWindowsFontEngineData();
~QWindowsFontEngineData();
@@ -85,7 +85,7 @@ public:
class QWindowsFontDatabase : public QPlatformFontDatabase
{
- Q_DISABLE_COPY(QWindowsFontDatabase)
+ Q_DISABLE_COPY_MOVE(QWindowsFontDatabase)
public:
enum FontOptions {
// Relevant bits from QWindowsIntegration::Options
@@ -96,6 +96,8 @@ public:
QWindowsFontDatabase();
~QWindowsFontDatabase() override;
+ void ensureFamilyPopulated(const QString &familyName);
+
void populateFontDatabase() override;
void populateFamily(const QString &familyName) override;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
index 2b575a9b45..b1b9d828ac 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
@@ -66,7 +66,7 @@ class QWindowsFontEngineData;
class QWindowsFontEngine : public QFontEngine
{
- Q_DISABLE_COPY(QWindowsFontEngine)
+ Q_DISABLE_COPY_MOVE(QWindowsFontEngine)
public:
QWindowsFontEngine(const QString &name, LOGFONT lf,
const QSharedPointer<QWindowsFontEngineData> &fontEngineData);
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
index 57c41938bc..60a5896e7b 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
@@ -69,7 +69,7 @@ namespace {
class GeometrySink: public IDWriteGeometrySink
{
- Q_DISABLE_COPY(GeometrySink)
+ Q_DISABLE_COPY_MOVE(GeometrySink)
public:
GeometrySink(QPainterPath *path)
: m_refCount(0), m_path(path)
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h
index 9326f5aece..3eaf8cf3d8 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h
@@ -72,7 +72,7 @@ class QWindowsFontEngineData;
class QWindowsFontEngineDirectWrite : public QFontEngine
{
- Q_DISABLE_COPY(QWindowsFontEngineDirectWrite)
+ Q_DISABLE_COPY_MOVE(QWindowsFontEngineDirectWrite)
public:
explicit QWindowsFontEngineDirectWrite(IDWriteFontFace *directWriteFontFace,
qreal pixelSize,
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h
index 6c47a527d2..ed68ac2644 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
class QWindowsNativeImage
{
- Q_DISABLE_COPY(QWindowsNativeImage)
+ Q_DISABLE_COPY_MOVE(QWindowsNativeImage)
public:
QWindowsNativeImage(int width, int height,
QImage::Format format);
diff --git a/src/platformsupport/fontdatabases/windows/windows.pri b/src/platformsupport/fontdatabases/windows/windows.pri
index 9c529f55ea..7ddfb2c281 100644
--- a/src/platformsupport/fontdatabases/windows/windows.pri
+++ b/src/platformsupport/fontdatabases/windows/windows.pri
@@ -30,5 +30,5 @@ qtConfig(directwrite):qtConfig(direct2d) {
DEFINES *= QT_NO_DIRECTWRITE
}
-LIBS += -lole32 -lgdi32 -luser32 -ladvapi32
-mingw: LIBS += -luuid
+QMAKE_USE_PRIVATE += advapi32 ole32 user32 gdi32
+mingw: QMAKE_USE_PRIVATE += uuid
diff --git a/src/platformsupport/fontdatabases/winrt/winrt.pri b/src/platformsupport/fontdatabases/winrt/winrt.pri
index 7617df2e7a..1cd417c1fd 100644
--- a/src/platformsupport/fontdatabases/winrt/winrt.pri
+++ b/src/platformsupport/fontdatabases/winrt/winrt.pri
@@ -8,6 +8,4 @@ HEADERS += \
DEFINES += __WRL_NO_DEFAULT_LIB__
-LIBS += -lws2_32
-
-QMAKE_USE_PRIVATE += dwrite_1
+QMAKE_USE_PRIVATE += dwrite_1 ws2_32
diff --git a/src/platformsupport/glxconvenience/glxconvenience.pro b/src/platformsupport/glxconvenience/glxconvenience.pro
index 8367dc5e31..1b9cf79080 100644
--- a/src/platformsupport/glxconvenience/glxconvenience.pro
+++ b/src/platformsupport/glxconvenience/glxconvenience.pro
@@ -6,7 +6,7 @@ CONFIG += static internal_module
DEFINES += QT_NO_CAST_FROM_ASCII
-QMAKE_USE_PRIVATE += xlib
+QMAKE_USE += xlib
HEADERS += qglxconvenience_p.h
SOURCES += qglxconvenience.cpp
diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp
index 6bd73de8f3..948b00596f 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience.cpp
+++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp
@@ -224,13 +224,16 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format
}
QXlibPointer<XVisualInfo> visual(glXGetVisualFromFBConfig(display, candidate));
- if (visual.isNull())
- continue;
-
- const int actualRed = qPopulationCount(visual->red_mask);
- const int actualGreen = qPopulationCount(visual->green_mask);
- const int actualBlue = qPopulationCount(visual->blue_mask);
- const int actualAlpha = visual->depth - actualRed - actualGreen - actualBlue;
+ int actualRed;
+ int actualGreen;
+ int actualBlue;
+ int actualAlpha;
+ glXGetFBConfigAttrib(display, candidate, GLX_RED_SIZE, &actualRed);
+ glXGetFBConfigAttrib(display, candidate, GLX_GREEN_SIZE, &actualGreen);
+ glXGetFBConfigAttrib(display, candidate, GLX_BLUE_SIZE, &actualBlue);
+ glXGetFBConfigAttrib(display, candidate, GLX_ALPHA_SIZE, &actualAlpha);
+ // Sometimes the visuals don't have a depth that includes the alpha channel.
+ actualAlpha = qMin(actualAlpha, visual->depth - actualRed - actualGreen - actualBlue);
if (requestedRed && actualRed < requestedRed)
continue;
@@ -312,7 +315,7 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display,
glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize);
glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize);
glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize);
- glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleBuffers);
+ glXGetFBConfigAttrib(display, config, GLX_SAMPLE_BUFFERS_ARB, &sampleBuffers);
glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo);
if (flags & QGLX_SUPPORTS_SRGB)
glXGetFBConfigAttrib(display, config, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgbCapable);
@@ -351,7 +354,7 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display,
glXGetConfig(display, visualInfo, GLX_ALPHA_SIZE, &alphaSize);
glXGetConfig(display, visualInfo, GLX_DEPTH_SIZE, &depthSize);
glXGetConfig(display, visualInfo, GLX_STENCIL_SIZE, &stencilSize);
- glXGetConfig(display, visualInfo, GLX_SAMPLES_ARB, &sampleBuffers);
+ glXGetConfig(display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &sampleBuffers);
glXGetConfig(display, visualInfo, GLX_STEREO, &stereo);
if (flags & QGLX_SUPPORTS_SRGB)
glXGetConfig(display, visualInfo, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgbCapable);
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
index ad134a825f..bff4a2522c 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
@@ -66,7 +66,7 @@ Q_LOGGING_CATEGORY(qLcEvdevKeyMap, "qt.qpa.input.keymap")
// simple builtin US keymap
#include "qevdevkeyboard_defaultmap_p.h"
-void QFdContainer::reset() Q_DECL_NOTHROW
+void QFdContainer::reset() noexcept
{
if (m_fd >= 0)
qt_safe_close(m_fd);
@@ -98,11 +98,12 @@ QEvdevKeyboardHandler::~QEvdevKeyboardHandler()
unloadKeymap();
}
-QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device,
+std::unique_ptr<QEvdevKeyboardHandler> QEvdevKeyboardHandler::create(const QString &device,
const QString &specification,
const QString &defaultKeymapFile)
{
- qCDebug(qLcEvdevKey) << "Try to create keyboard handler for" << device << specification;
+ qCDebug(qLcEvdevKey, "Try to create keyboard handler for \"%ls\" \"%ls\"",
+ qUtf16Printable(device), qUtf16Printable(specification));
QString keymapFile = defaultKeymapFile;
int repeatDelay = 400;
@@ -127,7 +128,7 @@ QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device,
grab = arg.mid(5).toInt();
}
- qCDebug(qLcEvdevKey) << "Opening keyboard at" << device;
+ qCDebug(qLcEvdevKey, "Opening keyboard at %ls", qUtf16Printable(device));
QFdContainer fd(qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0));
if (fd.get() >= 0) {
@@ -137,16 +138,16 @@ QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device,
::ioctl(fd.get(), EVIOCSREP, kbdrep);
}
- return new QEvdevKeyboardHandler(device, fd, disableZap, enableCompose, keymapFile);
+ return std::unique_ptr<QEvdevKeyboardHandler>(new QEvdevKeyboardHandler(device, fd, disableZap, enableCompose, keymapFile));
} else {
- qWarning("Cannot open keyboard input device '%s': %s", qPrintable(device), strerror(errno));
- return 0;
+ qErrnoWarning("Cannot open keyboard input device '%ls'", qUtf16Printable(device));
+ return nullptr;
}
}
void QEvdevKeyboardHandler::switchLed(int led, bool state)
{
- qCDebug(qLcEvdevKey) << "switchLed" << led << state;
+ qCDebug(qLcEvdevKey, "switchLed %d %d", led, int(state));
struct ::input_event led_ie;
::gettimeofday(&led_ie.time, 0);
@@ -170,7 +171,7 @@ void QEvdevKeyboardHandler::readKeycode()
return;
} else if (result < 0) {
if (errno != EINTR && errno != EAGAIN) {
- qErrnoWarning(errno, "evdevkeyboard: Could not read from input device");
+ qErrnoWarning("evdevkeyboard: Could not read from input device");
// If the device got disconnected, stop reading, otherwise we get flooded
// by the above error over and over again.
if (errno == ENODEV) {
@@ -473,7 +474,7 @@ QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint
void QEvdevKeyboardHandler::unloadKeymap()
{
- qCDebug(qLcEvdevKey) << "Unload current keymap and restore built-in";
+ qCDebug(qLcEvdevKey, "Unload current keymap and restore built-in");
if (m_keymap && m_keymap != s_keymap_default)
delete [] m_keymap;
@@ -517,12 +518,12 @@ void QEvdevKeyboardHandler::unloadKeymap()
bool QEvdevKeyboardHandler::loadKeymap(const QString &file)
{
- qCDebug(qLcEvdevKey) << "Loading keymap" << file;
+ qCDebug(qLcEvdevKey, "Loading keymap %ls", qUtf16Printable(file));
QFile f(file);
if (!f.open(QIODevice::ReadOnly)) {
- qWarning("Could not open keymap file '%s'", qPrintable(file));
+ qWarning("Could not open keymap file '%ls'", qUtf16Printable(file));
return false;
}
@@ -541,7 +542,7 @@ bool QEvdevKeyboardHandler::loadKeymap(const QString &file)
ds >> qmap_magic >> qmap_version >> qmap_keymap_size >> qmap_keycompose_size;
if (ds.status() != QDataStream::Ok || qmap_magic != QEvdevKeyboardMap::FileMagic || qmap_version != 1 || qmap_keymap_size == 0) {
- qWarning("'%s' is not a valid .qmap keymap file", qPrintable(file));
+ qWarning("'%ls' is not a valid .qmap keymap file", qUtf16Printable(file));
return false;
}
@@ -557,7 +558,7 @@ bool QEvdevKeyboardHandler::loadKeymap(const QString &file)
delete [] qmap_keymap;
delete [] qmap_keycompose;
- qWarning("Keymap file '%s' can not be loaded.", qPrintable(file));
+ qWarning("Keymap file '%ls' cannot be loaded.", qUtf16Printable(file));
return false;
}
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
index 5498a3e4f0..f92a2bf704 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
@@ -55,6 +55,8 @@
#include <QTimer>
#include <QDataStream>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QSocketNotifier;
@@ -132,15 +134,15 @@ inline QDataStream &operator<<(QDataStream &ds, const QEvdevKeyboardMap::Composi
class QFdContainer
{
int m_fd;
- Q_DISABLE_COPY(QFdContainer);
+ Q_DISABLE_COPY_MOVE(QFdContainer);
public:
- explicit QFdContainer(int fd = -1) Q_DECL_NOTHROW : m_fd(fd) {}
+ explicit QFdContainer(int fd = -1) noexcept : m_fd(fd) {}
~QFdContainer() { reset(); }
- int get() const Q_DECL_NOTHROW { return m_fd; }
+ int get() const noexcept { return m_fd; }
- int release() Q_DECL_NOTHROW { int result = m_fd; m_fd = -1; return result; }
- void reset() Q_DECL_NOTHROW;
+ int release() noexcept { int result = m_fd; m_fd = -1; return result; }
+ void reset() noexcept;
};
class QEvdevKeyboardHandler : public QObject
@@ -168,7 +170,7 @@ public:
SwitchConsoleMask = 0x0000007f
};
- static QEvdevKeyboardHandler *create(const QString &device,
+ static std::unique_ptr<QEvdevKeyboardHandler> create(const QString &device,
const QString &specification,
const QString &defaultKeymapFile = QString());
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp
index e1659bc0d9..52d9c34b1c 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp
@@ -39,6 +39,8 @@
#include "qevdevkeyboardmanager_p.h"
+#include <QtInputSupport/private/qevdevutil_p.h>
+
#include <QStringList>
#include <QCoreApplication>
#include <QLoggingCategory>
@@ -61,36 +63,24 @@ QEvdevKeyboardManager::QEvdevKeyboardManager(const QString &key, const QString &
if (spec.isEmpty())
spec = specification;
- QStringList args = spec.split(QLatin1Char(':'));
- QStringList devices;
-
- foreach (const QString &arg, args) {
- if (arg.startsWith(QLatin1String("/dev/"))) {
- // if device is specified try to use it
- devices.append(arg);
- args.removeAll(arg);
- }
- }
-
- // build new specification without /dev/ elements
- m_spec = args.join(QLatin1Char(':'));
+ auto parsed = QEvdevUtil::parseSpecification(spec);
+ m_spec = std::move(parsed.spec);
// add all keyboards for devices specified in the argument list
- foreach (const QString &device, devices)
+ for (const QString &device : qAsConst(parsed.devices))
addKeyboard(device);
- if (devices.isEmpty()) {
- qCDebug(qLcEvdevKey) << "evdevkeyboard: Using device discovery";
- m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Keyboard, this);
- if (m_deviceDiscovery) {
+ if (parsed.devices.isEmpty()) {
+ qCDebug(qLcEvdevKey, "evdevkeyboard: Using device discovery");
+ if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Keyboard, this)) {
// scan and add already connected keyboards
- const QStringList devices = m_deviceDiscovery->scanConnectedDevices();
+ const QStringList devices = deviceDiscovery->scanConnectedDevices();
for (const QString &device : devices)
addKeyboard(device);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceDetected,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected,
this, &QEvdevKeyboardManager::addKeyboard);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
this, &QEvdevKeyboardManager::removeKeyboard);
}
}
@@ -98,36 +88,34 @@ QEvdevKeyboardManager::QEvdevKeyboardManager(const QString &key, const QString &
QEvdevKeyboardManager::~QEvdevKeyboardManager()
{
- qDeleteAll(m_keyboards);
- m_keyboards.clear();
}
void QEvdevKeyboardManager::addKeyboard(const QString &deviceNode)
{
- qCDebug(qLcEvdevKey) << "Adding keyboard at" << deviceNode;
- QEvdevKeyboardHandler *keyboard;
- keyboard = QEvdevKeyboardHandler::create(deviceNode, m_spec, m_defaultKeymapFile);
+ qCDebug(qLcEvdevKey, "Adding keyboard at %ls", qUtf16Printable(deviceNode));
+ auto keyboard = QEvdevKeyboardHandler::create(deviceNode, m_spec, m_defaultKeymapFile);
if (keyboard) {
- m_keyboards.insert(deviceNode, keyboard);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypeKeyboard, m_keyboards.count());
+ m_keyboards.add(deviceNode, std::move(keyboard));
+ updateDeviceCount();
} else {
- qWarning("Failed to open keyboard device %s", qPrintable(deviceNode));
+ qWarning("Failed to open keyboard device %ls", qUtf16Printable(deviceNode));
}
}
void QEvdevKeyboardManager::removeKeyboard(const QString &deviceNode)
{
- if (m_keyboards.contains(deviceNode)) {
- qCDebug(qLcEvdevKey) << "Removing keyboard at" << deviceNode;
- QEvdevKeyboardHandler *keyboard = m_keyboards.value(deviceNode);
- m_keyboards.remove(deviceNode);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypeKeyboard, m_keyboards.count());
- delete keyboard;
+ if (m_keyboards.remove(deviceNode)) {
+ qCDebug(qLcEvdevKey, "Removing keyboard at %ls", qUtf16Printable(deviceNode));
+ updateDeviceCount();
}
}
+void QEvdevKeyboardManager::updateDeviceCount()
+{
+ QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
+ QInputDeviceManager::DeviceTypeKeyboard, m_keyboards.count());
+}
+
void QEvdevKeyboardManager::loadKeymap(const QString &file)
{
m_defaultKeymapFile = file;
@@ -141,22 +129,22 @@ void QEvdevKeyboardManager::loadKeymap(const QString &file)
if (arg.startsWith(QLatin1String("keymap=")))
keymapFromSpec = arg.mid(7).toString();
}
- foreach (QEvdevKeyboardHandler *handler, m_keyboards) {
+ for (const auto &keyboard : m_keyboards) {
if (keymapFromSpec.isEmpty())
- handler->unloadKeymap();
+ keyboard.handler->unloadKeymap();
else
- handler->loadKeymap(keymapFromSpec);
+ keyboard.handler->loadKeymap(keymapFromSpec);
}
} else {
- foreach (QEvdevKeyboardHandler *handler, m_keyboards)
- handler->loadKeymap(file);
+ for (const auto &keyboard : m_keyboards)
+ keyboard.handler->loadKeymap(file);
}
}
void QEvdevKeyboardManager::switchLang()
{
- foreach (QEvdevKeyboardHandler *handler, m_keyboards)
- handler->switchLang();
+ for (const auto &keyboard : m_keyboards)
+ keyboard.handler->switchLang();
}
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h
index 326e438a7c..d91da330c3 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h
@@ -53,6 +53,7 @@
#include "qevdevkeyboardhandler_p.h"
+#include <QtInputSupport/private/devicehandlerlist_p.h>
#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
#include <QObject>
@@ -64,7 +65,7 @@ QT_BEGIN_NAMESPACE
class QEvdevKeyboardManager : public QObject
{
public:
- QEvdevKeyboardManager(const QString &key, const QString &specification, QObject *parent = 0);
+ QEvdevKeyboardManager(const QString &key, const QString &specification, QObject *parent = nullptr);
~QEvdevKeyboardManager();
void loadKeymap(const QString &file);
@@ -74,9 +75,10 @@ public:
void removeKeyboard(const QString &deviceNode);
private:
+ void updateDeviceCount();
+
QString m_spec;
- QHash<QString,QEvdevKeyboardHandler*> m_keyboards;
- QDeviceDiscovery *m_deviceDiscovery;
+ QtInputSupport::DeviceHandlerList<QEvdevKeyboardHandler> m_keyboards;
QString m_defaultKeymapFile;
};
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
index 86a4cd0076..6a53ad2088 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
@@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(qLcEvdevMouse, "qt.qpa.input")
-QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QString &specification)
+std::unique_ptr<QEvdevMouseHandler> QEvdevMouseHandler::create(const QString &device, const QString &specification)
{
qCDebug(qLcEvdevMouse) << "create mouse handler for" << device << specification;
@@ -91,10 +91,10 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr
fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
if (fd >= 0) {
::ioctl(fd, EVIOCGRAB, grab);
- return new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit);
+ return std::unique_ptr<QEvdevMouseHandler>(new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit));
} else {
qErrnoWarning(errno, "Cannot open mouse input device %s", qPrintable(device));
- return 0;
+ return nullptr;
}
}
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
index c7f2b04eb2..727f1a02f9 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
@@ -56,6 +56,8 @@
#include <QPoint>
#include <QEvent>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QSocketNotifier;
@@ -64,7 +66,7 @@ class QEvdevMouseHandler : public QObject
{
Q_OBJECT
public:
- static QEvdevMouseHandler *create(const QString &device, const QString &specification);
+ static std::unique_ptr<QEvdevMouseHandler> create(const QString &device, const QString &specification);
~QEvdevMouseHandler();
void readMouseData();
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
index ae81bca00f..0c19294905 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
@@ -39,6 +39,8 @@
#include "qevdevmousemanager_p.h"
+#include <QtInputSupport/private/qevdevutil_p.h>
+
#include <QStringList>
#include <QGuiApplication>
#include <QScreen>
@@ -63,40 +65,32 @@ QEvdevMouseManager::QEvdevMouseManager(const QString &key, const QString &specif
if (spec.isEmpty())
spec = specification;
- QStringList args = spec.split(QLatin1Char(':'));
- QStringList devices;
+ auto parsed = QEvdevUtil::parseSpecification(spec);
+ m_spec = std::move(parsed.spec);
- foreach (const QString &arg, args) {
- if (arg.startsWith(QLatin1String("/dev/"))) {
- // if device is specified try to use it
- devices.append(arg);
- args.removeAll(arg);
- } else if (arg.startsWith(QLatin1String("xoffset="))) {
+ for (const QStringRef &arg : qAsConst(parsed.args)) {
+ if (arg.startsWith(QLatin1String("xoffset="))) {
m_xoffset = arg.mid(8).toInt();
} else if (arg.startsWith(QLatin1String("yoffset="))) {
m_yoffset = arg.mid(8).toInt();
}
}
- // build new specification without /dev/ elements
- m_spec = args.join(QLatin1Char(':'));
-
// add all mice for devices specified in the argument list
- foreach (const QString &device, devices)
+ for (const QString &device : qAsConst(parsed.devices))
addMouse(device);
- if (devices.isEmpty()) {
- qCDebug(qLcEvdevMouse) << "evdevmouse: Using device discovery";
- m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Mouse | QDeviceDiscovery::Device_Touchpad, this);
- if (m_deviceDiscovery) {
+ if (parsed.devices.isEmpty()) {
+ qCDebug(qLcEvdevMouse, "evdevmouse: Using device discovery");
+ if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Mouse | QDeviceDiscovery::Device_Touchpad, this)) {
// scan and add already connected keyboards
- const QStringList devices = m_deviceDiscovery->scanConnectedDevices();
+ const QStringList devices = deviceDiscovery->scanConnectedDevices();
for (const QString &device : devices)
addMouse(device);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceDetected,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected,
this, &QEvdevMouseManager::addMouse);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
this, &QEvdevMouseManager::removeMouse);
}
}
@@ -111,8 +105,6 @@ QEvdevMouseManager::QEvdevMouseManager(const QString &key, const QString &specif
QEvdevMouseManager::~QEvdevMouseManager()
{
- qDeleteAll(m_mice);
- m_mice.clear();
}
void QEvdevMouseManager::clampPosition()
@@ -159,31 +151,32 @@ void QEvdevMouseManager::handleWheelEvent(QPoint delta)
void QEvdevMouseManager::addMouse(const QString &deviceNode)
{
- qCDebug(qLcEvdevMouse) << "Adding mouse at" << deviceNode;
- QEvdevMouseHandler *handler = QEvdevMouseHandler::create(deviceNode, m_spec);
+ qCDebug(qLcEvdevMouse, "Adding mouse at %ls", qUtf16Printable(deviceNode));
+ auto handler = QEvdevMouseHandler::create(deviceNode, m_spec);
if (handler) {
- connect(handler, &QEvdevMouseHandler::handleMouseEvent,
+ connect(handler.get(), &QEvdevMouseHandler::handleMouseEvent,
this, &QEvdevMouseManager::handleMouseEvent);
- connect(handler, &QEvdevMouseHandler::handleWheelEvent,
+ connect(handler.get(), &QEvdevMouseHandler::handleWheelEvent,
this, &QEvdevMouseManager::handleWheelEvent);
- m_mice.insert(deviceNode, handler);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypePointer, m_mice.count());
+ m_mice.add(deviceNode, std::move(handler));
+ updateDeviceCount();
} else {
- qWarning("evdevmouse: Failed to open mouse device %s", qPrintable(deviceNode));
+ qWarning("evdevmouse: Failed to open mouse device %ls", qUtf16Printable(deviceNode));
}
}
void QEvdevMouseManager::removeMouse(const QString &deviceNode)
{
- if (m_mice.contains(deviceNode)) {
- qCDebug(qLcEvdevMouse) << "Removing mouse at" << deviceNode;
- QEvdevMouseHandler *handler = m_mice.value(deviceNode);
- m_mice.remove(deviceNode);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypePointer, m_mice.count());
- delete handler;
+ if (m_mice.remove(deviceNode)) {
+ qCDebug(qLcEvdevMouse, "Removing mouse at %ls", qUtf16Printable(deviceNode));
+ updateDeviceCount();
}
}
+void QEvdevMouseManager::updateDeviceCount()
+{
+ QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
+ QInputDeviceManager::DeviceTypePointer, m_mice.count());
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
index 13a8e3dec5..f5c32ed8b5 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
@@ -53,6 +53,8 @@
#include "qevdevmousehandler_p.h"
+#include <QtInputSupport/private/devicehandlerlist_p.h>
+
#include <QObject>
#include <QHash>
#include <QSocketNotifier>
@@ -65,7 +67,7 @@ class QDeviceDiscovery;
class QEvdevMouseManager : public QObject
{
public:
- QEvdevMouseManager(const QString &key, const QString &specification, QObject *parent = 0);
+ QEvdevMouseManager(const QString &key, const QString &specification, QObject *parent = nullptr);
~QEvdevMouseManager();
void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons,
@@ -77,10 +79,10 @@ public:
private:
void clampPosition();
+ void updateDeviceCount();
QString m_spec;
- QHash<QString,QEvdevMouseHandler*> m_mice;
- QDeviceDiscovery *m_deviceDiscovery;
+ QtInputSupport::DeviceHandlerList<QEvdevMouseHandler> m_mice;
int m_x;
int m_y;
int m_xoffset;
diff --git a/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
index b6051aaf3c..c86840b76c 100644
--- a/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
+++ b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
@@ -172,11 +172,11 @@ QEvdevTabletHandler::QEvdevTabletHandler(const QString &device, const QString &s
setObjectName(QLatin1String("Evdev Tablet Handler"));
- qCDebug(qLcEvdevTablet, "evdevtablet: using %s", qPrintable(device));
+ qCDebug(qLcEvdevTablet, "evdevtablet: using %ls", qUtf16Printable(device));
m_fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
if (m_fd < 0) {
- qErrnoWarning(errno, "evdevtablet: Cannot open input device %s", qPrintable(device));
+ qErrnoWarning("evdevtablet: Cannot open input device %ls", qUtf16Printable(device));
return;
}
@@ -184,11 +184,11 @@ QEvdevTabletHandler::QEvdevTabletHandler(const QString &device, const QString &s
if (grabSuccess)
ioctl(m_fd, EVIOCGRAB, (void *) 0);
else
- qWarning("evdevtablet: %s: The device is grabbed by another process. No events will be read.", qPrintable(device));
+ qWarning("evdevtablet: %ls: The device is grabbed by another process. No events will be read.", qUtf16Printable(device));
d = new QEvdevTabletData(this);
if (!queryLimits())
- qWarning("evdevtablet: %s: Unset or invalid ABS limits. Behavior will be unspecified.", qPrintable(device));
+ qWarning("evdevtablet: %ls: Unset or invalid ABS limits. Behavior will be unspecified.", qUtf16Printable(device));
m_notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated, this, &QEvdevTabletHandler::readData);
@@ -216,32 +216,32 @@ bool QEvdevTabletHandler::queryLimits()
if (ok) {
d->minValues.x = absInfo.minimum;
d->maxValues.x = absInfo.maximum;
- qCDebug(qLcEvdevTablet, "evdevtablet: %s: min X: %d max X: %d", qPrintable(m_device),
+ qCDebug(qLcEvdevTablet, "evdevtablet: %ls: min X: %d max X: %d", qUtf16Printable(m_device),
d->minValues.x, d->maxValues.x);
}
ok &= ioctl(m_fd, EVIOCGABS(ABS_Y), &absInfo) >= 0;
if (ok) {
d->minValues.y = absInfo.minimum;
d->maxValues.y = absInfo.maximum;
- qCDebug(qLcEvdevTablet, "evdevtablet: %s: min Y: %d max Y: %d", qPrintable(m_device),
+ qCDebug(qLcEvdevTablet, "evdevtablet: %ls: min Y: %d max Y: %d", qUtf16Printable(m_device),
d->minValues.y, d->maxValues.y);
}
if (ioctl(m_fd, EVIOCGABS(ABS_PRESSURE), &absInfo) >= 0) {
d->minValues.p = absInfo.minimum;
d->maxValues.p = absInfo.maximum;
- qCDebug(qLcEvdevTablet, "evdevtablet: %s: min pressure: %d max pressure: %d", qPrintable(m_device),
+ qCDebug(qLcEvdevTablet, "evdevtablet: %ls: min pressure: %d max pressure: %d", qUtf16Printable(m_device),
d->minValues.p, d->maxValues.p);
}
if (ioctl(m_fd, EVIOCGABS(ABS_DISTANCE), &absInfo) >= 0) {
d->minValues.d = absInfo.minimum;
d->maxValues.d = absInfo.maximum;
- qCDebug(qLcEvdevTablet, "evdevtablet: %s: min distance: %d max distance: %d", qPrintable(m_device),
+ qCDebug(qLcEvdevTablet, "evdevtablet: %ls: min distance: %d max distance: %d", qUtf16Printable(m_device),
d->minValues.d, d->maxValues.d);
}
char name[128];
if (ioctl(m_fd, EVIOCGNAME(sizeof(name) - 1), name) >= 0) {
d->devName = QString::fromLocal8Bit(name);
- qCDebug(qLcEvdevTablet, "evdevtablet: %s: device name: %s", qPrintable(m_device), name);
+ qCDebug(qLcEvdevTablet, "evdevtablet: %ls: device name: %s", qUtf16Printable(m_device), name);
}
return ok;
}
@@ -253,11 +253,11 @@ void QEvdevTabletHandler::readData()
for (; ;) {
int result = QT_READ(m_fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n);
if (!result) {
- qWarning("evdevtablet: %s: Got EOF from input device", qPrintable(m_device));
+ qWarning("evdevtablet: %ls: Got EOF from input device", qUtf16Printable(m_device));
return;
} else if (result < 0) {
if (errno != EINTR && errno != EAGAIN) {
- qErrnoWarning(errno, "evdevtablet: %s: Could not read from input device", qPrintable(m_device));
+ qErrnoWarning("evdevtablet: %ls: Could not read from input device", qUtf16Printable(m_device));
if (errno == ENODEV) { // device got disconnected -> stop reading
delete m_notifier;
m_notifier = 0;
diff --git a/src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h b/src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h
index 66e821117a..b83bb21258 100644
--- a/src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h
+++ b/src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h
@@ -64,7 +64,7 @@ class QEvdevTabletData;
class QEvdevTabletHandler : public QObject
{
public:
- explicit QEvdevTabletHandler(const QString &device, const QString &spec = QString(), QObject *parent = 0);
+ explicit QEvdevTabletHandler(const QString &device, const QString &spec = QString(), QObject *parent = nullptr);
~QEvdevTabletHandler();
qint64 deviceId() const;
@@ -83,7 +83,7 @@ private:
class QEvdevTabletHandlerThread : public QDaemonThread
{
public:
- explicit QEvdevTabletHandlerThread(const QString &device, const QString &spec, QObject *parent = 0);
+ explicit QEvdevTabletHandlerThread(const QString &device, const QString &spec, QObject *parent = nullptr);
~QEvdevTabletHandlerThread();
void run() override;
QEvdevTabletHandler *handler() { return m_handler; }
diff --git a/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp b/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp
index 90949408ac..d9888c5b97 100644
--- a/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp
+++ b/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp
@@ -40,12 +40,15 @@
#include "qevdevtabletmanager_p.h"
#include "qevdevtablethandler_p.h"
+#include <QtInputSupport/private/qevdevutil_p.h>
+
#include <QStringList>
#include <QGuiApplication>
#include <QLoggingCategory>
#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
#include <private/qguiapplication_p.h>
#include <private/qinputdevicemanager_p_p.h>
+#include <private/qmemory_p.h>
QT_BEGIN_NAMESPACE
@@ -64,34 +67,23 @@ QEvdevTabletManager::QEvdevTabletManager(const QString &key, const QString &spec
if (spec.isEmpty())
spec = specification;
- QStringList args = spec.split(QLatin1Char(':'));
- QStringList devices;
-
- foreach (const QString &arg, args) {
- if (arg.startsWith(QLatin1String("/dev/"))) {
- devices.append(arg);
- args.removeAll(arg);
- }
- }
-
- // build new specification without /dev/ elements
- m_spec = args.join(QLatin1Char(':'));
+ auto parsed = QEvdevUtil::parseSpecification(spec);
+ m_spec = std::move(parsed.spec);
- foreach (const QString &device, devices)
+ for (const QString &device : qAsConst(parsed.devices))
addDevice(device);
// when no devices specified, use device discovery to scan and monitor
- if (devices.isEmpty()) {
- qCDebug(qLcEvdevTablet) << "evdevtablet: Using device discovery";
- m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Tablet, this);
- if (m_deviceDiscovery) {
- const QStringList devices = m_deviceDiscovery->scanConnectedDevices();
+ if (parsed.devices.isEmpty()) {
+ qCDebug(qLcEvdevTablet, "evdevtablet: Using device discovery");
+ if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Tablet, this)) {
+ const QStringList devices = deviceDiscovery->scanConnectedDevices();
for (const QString &device : devices)
addDevice(device);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceDetected,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected,
this, &QEvdevTabletManager::addDevice);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
this, &QEvdevTabletManager::removeDevice);
}
}
@@ -99,33 +91,32 @@ QEvdevTabletManager::QEvdevTabletManager(const QString &key, const QString &spec
QEvdevTabletManager::~QEvdevTabletManager()
{
- qDeleteAll(m_activeDevices);
}
void QEvdevTabletManager::addDevice(const QString &deviceNode)
{
- qCDebug(qLcEvdevTablet) << "Adding device at" << deviceNode;
- QEvdevTabletHandlerThread *handler;
- handler = new QEvdevTabletHandlerThread(deviceNode, m_spec);
+ qCDebug(qLcEvdevTablet, "Adding device at %ls", qUtf16Printable(deviceNode));
+ auto handler = qt_make_unique<QEvdevTabletHandlerThread>(deviceNode, m_spec);
if (handler) {
- m_activeDevices.insert(deviceNode, handler);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypeTablet, m_activeDevices.count());
+ m_activeDevices.add(deviceNode, std::move(handler));
+ updateDeviceCount();
} else {
- qWarning("evdevtablet: Failed to open tablet device %s", qPrintable(deviceNode));
+ qWarning("evdevtablet: Failed to open tablet device %ls", qUtf16Printable(deviceNode));
}
}
void QEvdevTabletManager::removeDevice(const QString &deviceNode)
{
- if (m_activeDevices.contains(deviceNode)) {
- qCDebug(qLcEvdevTablet) << "Removing device at" << deviceNode;
- QEvdevTabletHandlerThread *handler = m_activeDevices.value(deviceNode);
- m_activeDevices.remove(deviceNode);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypeTablet, m_activeDevices.count());
- delete handler;
+ if (m_activeDevices.remove(deviceNode)) {
+ qCDebug(qLcEvdevTablet, "Removing device at %ls", qUtf16Printable(deviceNode));
+ updateDeviceCount();
}
}
+void QEvdevTabletManager::updateDeviceCount()
+{
+ QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
+ QInputDeviceManager::DeviceTypeTablet, m_activeDevices.count());
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h b/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h
index cde91c55aa..bb18ffba04 100644
--- a/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h
+++ b/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+#include <QtInputSupport/private/devicehandlerlist_p.h>
+
#include <QObject>
#include <QHash>
#include <QSocketNotifier>
@@ -63,16 +65,17 @@ class QEvdevTabletHandlerThread;
class QEvdevTabletManager : public QObject
{
public:
- QEvdevTabletManager(const QString &key, const QString &spec, QObject *parent = 0);
+ QEvdevTabletManager(const QString &key, const QString &spec, QObject *parent = nullptr);
~QEvdevTabletManager();
void addDevice(const QString &deviceNode);
void removeDevice(const QString &deviceNode);
private:
+ void updateDeviceCount();
+
QString m_spec;
- QDeviceDiscovery *m_deviceDiscovery;
- QHash<QString, QEvdevTabletHandlerThread *> m_activeDevices;
+ QtInputSupport::DeviceHandlerList<QEvdevTabletHandlerThread> m_activeDevices;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
index f3cc160b3e..737d85d5c3 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
@@ -49,6 +49,9 @@
#include <QtCore/private/qcore_unix_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/private/qguiapplication_p.h>
+
+#include <mutex>
+
#ifdef Q_OS_FREEBSD
#include <dev/evdev/input.h>
#else
@@ -225,7 +228,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
}
}
- qCDebug(qLcEvdevTouch, "evdevtouch: Using device %s", qPrintable(device));
+ qCDebug(qLcEvdevTouch, "evdevtouch: Using device %ls", qUtf16Printable(device));
m_fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
@@ -233,7 +236,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
connect(m_notify, &QSocketNotifier::activated, this, &QEvdevTouchScreenHandler::readData);
} else {
- qErrnoWarning(errno, "evdevtouch: Cannot open input device %s", qPrintable(device));
+ qErrnoWarning("evdevtouch: Cannot open input device %ls", qUtf16Printable(device));
return;
}
@@ -263,8 +266,8 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
d->deviceNode = device;
qCDebug(qLcEvdevTouch,
- "evdevtouch: %s: Protocol type %c %s (%s), filtered=%s",
- qPrintable(d->deviceNode),
+ "evdevtouch: %ls: Protocol type %c %s (%s), filtered=%s",
+ qUtf16Printable(d->deviceNode),
d->m_typeB ? 'B' : 'A', mtdevStr,
d->m_singleTouch ? "single" : "multi",
d->m_filtered ? "yes" : "no");
@@ -276,7 +279,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
bool has_x_range = false, has_y_range = false;
if (ioctl(m_fd, EVIOCGABS((d->m_singleTouch ? ABS_X : ABS_MT_POSITION_X)), &absInfo) >= 0) {
- qCDebug(qLcEvdevTouch, "evdevtouch: %s: min X: %d max X: %d", qPrintable(device),
+ qCDebug(qLcEvdevTouch, "evdevtouch: %ls: min X: %d max X: %d", qUtf16Printable(device),
absInfo.minimum, absInfo.maximum);
d->hw_range_x_min = absInfo.minimum;
d->hw_range_x_max = absInfo.maximum;
@@ -284,7 +287,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
}
if (ioctl(m_fd, EVIOCGABS((d->m_singleTouch ? ABS_Y : ABS_MT_POSITION_Y)), &absInfo) >= 0) {
- qCDebug(qLcEvdevTouch, "evdevtouch: %s: min Y: %d max Y: %d", qPrintable(device),
+ qCDebug(qLcEvdevTouch, "evdevtouch: %ls: min Y: %d max Y: %d", qUtf16Printable(device),
absInfo.minimum, absInfo.maximum);
d->hw_range_y_min = absInfo.minimum;
d->hw_range_y_max = absInfo.maximum;
@@ -292,10 +295,10 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
}
if (!has_x_range || !has_y_range)
- qWarning("evdevtouch: %s: Invalid ABS limits, behavior unspecified", qPrintable(device));
+ qWarning("evdevtouch: %ls: Invalid ABS limits, behavior unspecified", qUtf16Printable(device));
if (ioctl(m_fd, EVIOCGABS(ABS_PRESSURE), &absInfo) >= 0) {
- qCDebug(qLcEvdevTouch, "evdevtouch: %s: min pressure: %d max pressure: %d", qPrintable(device),
+ qCDebug(qLcEvdevTouch, "evdevtouch: %ls: min pressure: %d max pressure: %d", qUtf16Printable(device),
absInfo.minimum, absInfo.maximum);
if (absInfo.maximum > absInfo.minimum) {
d->hw_pressure_min = absInfo.minimum;
@@ -306,7 +309,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
char name[1024];
if (ioctl(m_fd, EVIOCGNAME(sizeof(name) - 1), name) >= 0) {
d->hw_name = QString::fromLocal8Bit(name);
- qCDebug(qLcEvdevTouch, "evdevtouch: %s: device name: %s", qPrintable(device), name);
+ qCDebug(qLcEvdevTouch, "evdevtouch: %ls: device name: %s", qUtf16Printable(device), name);
}
// Fix up the coordinate ranges for am335x in case the kernel driver does not have them fixed.
@@ -342,8 +345,8 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
if (mapping.load()) {
d->m_screenName = mapping.screenNameForDeviceNode(d->deviceNode);
if (!d->m_screenName.isEmpty())
- qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %s to screen %s",
- qPrintable(d->deviceNode), qPrintable(d->m_screenName));
+ qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %ls to screen %ls",
+ qUtf16Printable(d->deviceNode), qUtf16Printable(d->m_screenName));
}
registerTouchDevice();
@@ -424,7 +427,7 @@ err:
return;
} else if (events < 0) {
if (errno != EINTR && errno != EAGAIN) {
- qErrnoWarning(errno, "evdevtouch: Could not read from input device");
+ qErrnoWarning("evdevtouch: Could not read from input device");
if (errno == ENODEV) { // device got disconnected -> stop reading
delete m_notify;
m_notify = nullptr;
@@ -560,8 +563,9 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
if (!m_contacts.isEmpty() && m_contacts.constBegin().value().trackingId == -1)
assignIds();
+ std::unique_lock<QMutex> locker;
if (m_filtered)
- m_mutex.lock();
+ locker = std::unique_lock<QMutex>{m_mutex};
// update timestamps
m_lastTimeStamp = m_timeStamp;
@@ -571,9 +575,9 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
m_touchPoints.clear();
Qt::TouchPointStates combinedStates;
- QMutableHashIterator<int, Contact> it(m_contacts);
- while (it.hasNext()) {
- it.next();
+ for (auto i = m_contacts.begin(), end = m_contacts.end(); i != end; /*erasing*/) {
+ auto it = i++;
+
Contact &contact(it.value());
if (!contact.state)
@@ -596,7 +600,7 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
// Avoid reporting a contact in released state more than once.
if (!m_typeB && contact.state == Qt::TouchPointReleased
&& !m_lastContacts.contains(key)) {
- it.remove();
+ m_contacts.erase(it);
continue;
}
@@ -604,9 +608,7 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
}
// Now look for contacts that have disappeared since the last sync.
- it = m_lastContacts;
- while (it.hasNext()) {
- it.next();
+ for (auto it = m_lastContacts.begin(), end = m_lastContacts.end(); it != end; ++it) {
Contact &contact(it.value());
int key = m_typeB ? it.key() : contact.trackingId;
if (m_typeB) {
@@ -623,9 +625,9 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
}
// Remove contacts that have just been reported as released.
- it = m_contacts;
- while (it.hasNext()) {
- it.next();
+ for (auto i = m_contacts.begin(), end = m_contacts.end(); i != end; /*erasing*/) {
+ auto it = i++;
+
Contact &contact(it.value());
if (!contact.state)
@@ -635,7 +637,7 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
if (m_typeB)
contact.state = static_cast<Qt::TouchPointState>(0);
else
- it.remove();
+ m_contacts.erase(it);
} else {
contact.state = Qt::TouchPointStationary;
}
@@ -648,9 +650,6 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
if (!m_touchPoints.isEmpty() && combinedStates != Qt::TouchPointStationary)
reportPoints();
-
- if (m_filtered)
- m_mutex.unlock();
}
m_lastEventType = data->type;
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
index 4cacbf03e5..b280f27fac 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
@@ -40,12 +40,15 @@
#include "qevdevtouchmanager_p.h"
#include "qevdevtouchhandler_p.h"
+#include <QtInputSupport/private/qevdevutil_p.h>
+
#include <QStringList>
#include <QGuiApplication>
#include <QLoggingCategory>
#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
#include <private/qguiapplication_p.h>
#include <private/qinputdevicemanager_p_p.h>
+#include <private/qmemory_p.h>
QT_BEGIN_NAMESPACE
@@ -64,34 +67,23 @@ QEvdevTouchManager::QEvdevTouchManager(const QString &key, const QString &specif
if (spec.isEmpty())
spec = specification;
- QStringList args = spec.split(QLatin1Char(':'));
- QStringList devices;
-
- foreach (const QString &arg, args) {
- if (arg.startsWith(QLatin1String("/dev/"))) {
- devices.append(arg);
- args.removeAll(arg);
- }
- }
-
- // build new specification without /dev/ elements
- m_spec = args.join(QLatin1Char(':'));
+ auto parsed = QEvdevUtil::parseSpecification(spec);
+ m_spec = std::move(parsed.spec);
- foreach (const QString &device, devices)
+ for (const QString &device : qAsConst(parsed.devices))
addDevice(device);
// when no devices specified, use device discovery to scan and monitor
- if (devices.isEmpty()) {
- qCDebug(qLcEvdevTouch) << "evdevtouch: Using device discovery";
- m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Touchpad | QDeviceDiscovery::Device_Touchscreen, this);
- if (m_deviceDiscovery) {
- const QStringList devices = m_deviceDiscovery->scanConnectedDevices();
+ if (parsed.devices.isEmpty()) {
+ qCDebug(qLcEvdevTouch, "evdevtouch: Using device discovery");
+ if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Touchpad | QDeviceDiscovery::Device_Touchscreen, this)) {
+ const QStringList devices = deviceDiscovery->scanConnectedDevices();
for (const QString &device : devices)
addDevice(device);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceDetected,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected,
this, &QEvdevTouchManager::addDevice);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
this, &QEvdevTouchManager::removeDevice);
}
}
@@ -99,30 +91,24 @@ QEvdevTouchManager::QEvdevTouchManager(const QString &key, const QString &specif
QEvdevTouchManager::~QEvdevTouchManager()
{
- qDeleteAll(m_activeDevices);
}
void QEvdevTouchManager::addDevice(const QString &deviceNode)
{
- qCDebug(qLcEvdevTouch) << "evdevtouch: Adding device at" << deviceNode;
- QEvdevTouchScreenHandlerThread *handler;
- handler = new QEvdevTouchScreenHandlerThread(deviceNode, m_spec);
+ qCDebug(qLcEvdevTouch, "evdevtouch: Adding device at %ls", qUtf16Printable(deviceNode));
+ auto handler = qt_make_unique<QEvdevTouchScreenHandlerThread>(deviceNode, m_spec);
if (handler) {
- m_activeDevices.insert(deviceNode, handler);
- connect(handler, &QEvdevTouchScreenHandlerThread::touchDeviceRegistered, this, &QEvdevTouchManager::updateInputDeviceCount);
+ m_activeDevices.add(deviceNode, std::move(handler));
+ connect(handler.get(), &QEvdevTouchScreenHandlerThread::touchDeviceRegistered, this, &QEvdevTouchManager::updateInputDeviceCount);
} else {
- qWarning("evdevtouch: Failed to open touch device %s", qPrintable(deviceNode));
+ qWarning("evdevtouch: Failed to open touch device %ls", qUtf16Printable(deviceNode));
}
}
void QEvdevTouchManager::removeDevice(const QString &deviceNode)
{
- if (m_activeDevices.contains(deviceNode)) {
- qCDebug(qLcEvdevTouch) << "evdevtouch: Removing device at" << deviceNode;
- QEvdevTouchScreenHandlerThread *handler = m_activeDevices.value(deviceNode);
- m_activeDevices.remove(deviceNode);
- delete handler;
-
+ if (m_activeDevices.remove(deviceNode)) {
+ qCDebug(qLcEvdevTouch, "evdevtouch: Removing device at %ls", qUtf16Printable(deviceNode));
updateInputDeviceCount();
}
}
@@ -130,13 +116,13 @@ void QEvdevTouchManager::removeDevice(const QString &deviceNode)
void QEvdevTouchManager::updateInputDeviceCount()
{
int registeredTouchDevices = 0;
- Q_FOREACH (QEvdevTouchScreenHandlerThread *handler, m_activeDevices) {
- if (handler->isTouchDeviceRegistered())
+ for (const auto &device : m_activeDevices) {
+ if (device.handler->isTouchDeviceRegistered())
++registeredTouchDevices;
}
- qCDebug(qLcEvdevTouch) << "evdevtouch: Updating QInputDeviceManager device count:" << registeredTouchDevices << " touch devices,"
- << m_activeDevices.count() - registeredTouchDevices << "pending handler(s)" ;
+ qCDebug(qLcEvdevTouch, "evdevtouch: Updating QInputDeviceManager device count: %d touch devices, %d pending handler(s)",
+ registeredTouchDevices, m_activeDevices.count() - registeredTouchDevices);
QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
QInputDeviceManager::DeviceTypeTouch, registeredTouchDevices);
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h b/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
index e524c516f1..94ee05d900 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+#include <QtInputSupport/private/devicehandlerlist_p.h>
+
#include <QObject>
#include <QHash>
#include <QSocketNotifier>
@@ -63,7 +65,7 @@ class QEvdevTouchScreenHandlerThread;
class QEvdevTouchManager : public QObject
{
public:
- QEvdevTouchManager(const QString &key, const QString &spec, QObject *parent = 0);
+ QEvdevTouchManager(const QString &key, const QString &spec, QObject *parent = nullptr);
~QEvdevTouchManager();
void addDevice(const QString &deviceNode);
@@ -73,8 +75,7 @@ public:
private:
QString m_spec;
- QDeviceDiscovery *m_deviceDiscovery;
- QHash<QString, QEvdevTouchScreenHandlerThread *> m_activeDevices;
+ QtInputSupport::DeviceHandlerList<QEvdevTouchScreenHandlerThread> m_activeDevices;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/input-support.pro b/src/platformsupport/input/input-support.pro
new file mode 100644
index 0000000000..3d39210b9e
--- /dev/null
+++ b/src/platformsupport/input/input-support.pro
@@ -0,0 +1,35 @@
+TARGET = QtInputSupport
+MODULE = input_support
+
+QT = core-private gui-private devicediscovery_support-private
+CONFIG += static internal_module
+
+DEFINES += QT_NO_CAST_FROM_ASCII
+PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
+
+qtConfig(evdev) {
+ include($$PWD/evdevmouse/evdevmouse.pri)
+ include($$PWD/evdevkeyboard/evdevkeyboard.pri)
+ include($$PWD/evdevtouch/evdevtouch.pri)
+ qtConfig(tabletevent) {
+ include($$PWD/evdevtablet/evdevtablet.pri)
+ }
+}
+
+qtConfig(tslib) {
+ include($$PWD/tslib/tslib.pri)
+}
+
+qtConfig(libinput) {
+ include($$PWD/libinput/libinput.pri)
+}
+
+qtConfig(evdev)|qtConfig(libinput) {
+ include($$PWD/shared/shared.pri)
+}
+
+qtConfig(integrityhid) {
+ include($$PWD/integrityhid/integrityhid.pri)
+}
+
+load(qt_module)
diff --git a/src/platformsupport/input/input.pro b/src/platformsupport/input/input.pro
index 3d39210b9e..138c04dea3 100644
--- a/src/platformsupport/input/input.pro
+++ b/src/platformsupport/input/input.pro
@@ -1,35 +1,8 @@
-TARGET = QtInputSupport
-MODULE = input_support
+TEMPLATE = subdirs
+QT_FOR_CONFIG += gui-private
-QT = core-private gui-private devicediscovery_support-private
-CONFIG += static internal_module
+qtConfig(xkbcommon): SUBDIRS += xkbcommon
-DEFINES += QT_NO_CAST_FROM_ASCII
-PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
+SUBDIRS += input-support.pro ### FIXME - QTBUG-52657
-qtConfig(evdev) {
- include($$PWD/evdevmouse/evdevmouse.pri)
- include($$PWD/evdevkeyboard/evdevkeyboard.pri)
- include($$PWD/evdevtouch/evdevtouch.pri)
- qtConfig(tabletevent) {
- include($$PWD/evdevtablet/evdevtablet.pri)
- }
-}
-
-qtConfig(tslib) {
- include($$PWD/tslib/tslib.pri)
-}
-
-qtConfig(libinput) {
- include($$PWD/libinput/libinput.pri)
-}
-
-qtConfig(evdev)|qtConfig(libinput) {
- include($$PWD/shared/shared.pri)
-}
-
-qtConfig(integrityhid) {
- include($$PWD/integrityhid/integrityhid.pri)
-}
-
-load(qt_module)
+CONFIG += ordered
diff --git a/src/platformsupport/input/libinput/libinput.pri b/src/platformsupport/input/libinput/libinput.pri
index 476f20c1b8..f80b5f41d9 100644
--- a/src/platformsupport/input/libinput/libinput.pri
+++ b/src/platformsupport/input/libinput/libinput.pri
@@ -14,4 +14,7 @@ QMAKE_USE_PRIVATE += libudev libinput
INCLUDEPATH += $$PWD/../shared
-qtConfig(xkbcommon): QMAKE_USE_PRIVATE += xkbcommon
+qtConfig(xkbcommon): {
+ QMAKE_USE_PRIVATE += xkbcommon
+ QT += xkbcommon_support-private
+}
diff --git a/src/platformsupport/input/libinput/qlibinputhandler.cpp b/src/platformsupport/input/libinput/qlibinputhandler.cpp
index 52eaa18f4b..bb81890a67 100644
--- a/src/platformsupport/input/libinput/qlibinputhandler.cpp
+++ b/src/platformsupport/input/libinput/qlibinputhandler.cpp
@@ -205,6 +205,9 @@ void QLibInputHandler::processEvent(libinput_event *ev)
case LIBINPUT_EVENT_POINTER_MOTION:
m_pointer->processMotion(libinput_event_get_pointer_event(ev));
break;
+ case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
+ m_pointer->processAbsMotion(libinput_event_get_pointer_event(ev));
+ break;
case LIBINPUT_EVENT_POINTER_AXIS:
m_pointer->processAxis(libinput_event_get_pointer_event(ev));
break;
diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp
index baef769bc9..6586b084f1 100644
--- a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp
+++ b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp
@@ -47,6 +47,7 @@
#if QT_CONFIG(xkbcommon)
#include <xkbcommon/xkbcommon-keysyms.h>
#include <xkbcommon/xkbcommon-names.h>
+#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
#endif
QT_BEGIN_NAMESPACE
@@ -56,88 +57,7 @@ Q_DECLARE_LOGGING_CATEGORY(qLcLibInput)
const int REPEAT_DELAY = 500;
const int REPEAT_RATE = 100;
-#if QT_CONFIG(xkbcommon)
-struct KeyTabEntry {
- int xkbkey;
- int qtkey;
-};
-
-static inline bool operator==(const KeyTabEntry &a, const KeyTabEntry &b)
-{
- return a.xkbkey == b.xkbkey;
-}
-
-static const KeyTabEntry keyTab[] = {
- { XKB_KEY_Escape, Qt::Key_Escape },
- { XKB_KEY_Tab, Qt::Key_Tab },
- { XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab },
- { XKB_KEY_BackSpace, Qt::Key_Backspace },
- { XKB_KEY_Return, Qt::Key_Return },
- { XKB_KEY_Insert, Qt::Key_Insert },
- { XKB_KEY_Delete, Qt::Key_Delete },
- { XKB_KEY_Clear, Qt::Key_Delete },
- { XKB_KEY_Pause, Qt::Key_Pause },
- { XKB_KEY_Print, Qt::Key_Print },
-
- { XKB_KEY_Home, Qt::Key_Home },
- { XKB_KEY_End, Qt::Key_End },
- { XKB_KEY_Left, Qt::Key_Left },
- { XKB_KEY_Up, Qt::Key_Up },
- { XKB_KEY_Right, Qt::Key_Right },
- { XKB_KEY_Down, Qt::Key_Down },
- { XKB_KEY_Prior, Qt::Key_PageUp },
- { XKB_KEY_Next, Qt::Key_PageDown },
-
- { XKB_KEY_Shift_L, Qt::Key_Shift },
- { XKB_KEY_Shift_R, Qt::Key_Shift },
- { XKB_KEY_Shift_Lock, Qt::Key_Shift },
- { XKB_KEY_Control_L, Qt::Key_Control },
- { XKB_KEY_Control_R, Qt::Key_Control },
- { XKB_KEY_Meta_L, Qt::Key_Meta },
- { XKB_KEY_Meta_R, Qt::Key_Meta },
- { XKB_KEY_Alt_L, Qt::Key_Alt },
- { XKB_KEY_Alt_R, Qt::Key_Alt },
- { XKB_KEY_Caps_Lock, Qt::Key_CapsLock },
- { XKB_KEY_Num_Lock, Qt::Key_NumLock },
- { XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock },
- { XKB_KEY_Super_L, Qt::Key_Super_L },
- { XKB_KEY_Super_R, Qt::Key_Super_R },
- { XKB_KEY_Menu, Qt::Key_Menu },
- { XKB_KEY_Hyper_L, Qt::Key_Hyper_L },
- { XKB_KEY_Hyper_R, Qt::Key_Hyper_R },
- { XKB_KEY_Help, Qt::Key_Help },
-
- { XKB_KEY_KP_Space, Qt::Key_Space },
- { XKB_KEY_KP_Tab, Qt::Key_Tab },
- { XKB_KEY_KP_Enter, Qt::Key_Enter },
- { XKB_KEY_KP_Home, Qt::Key_Home },
- { XKB_KEY_KP_Left, Qt::Key_Left },
- { XKB_KEY_KP_Up, Qt::Key_Up },
- { XKB_KEY_KP_Right, Qt::Key_Right },
- { XKB_KEY_KP_Down, Qt::Key_Down },
- { XKB_KEY_KP_Prior, Qt::Key_PageUp },
- { XKB_KEY_KP_Next, Qt::Key_PageDown },
- { XKB_KEY_KP_End, Qt::Key_End },
- { XKB_KEY_KP_Begin, Qt::Key_Clear },
- { XKB_KEY_KP_Insert, Qt::Key_Insert },
- { XKB_KEY_KP_Delete, Qt::Key_Delete },
- { XKB_KEY_KP_Equal, Qt::Key_Equal },
- { XKB_KEY_KP_Multiply, Qt::Key_Asterisk },
- { XKB_KEY_KP_Add, Qt::Key_Plus },
- { XKB_KEY_KP_Separator, Qt::Key_Comma },
- { XKB_KEY_KP_Subtract, Qt::Key_Minus },
- { XKB_KEY_KP_Decimal, Qt::Key_Period },
- { XKB_KEY_KP_Divide, Qt::Key_Slash },
-};
-#endif
-
QLibInputKeyboard::QLibInputKeyboard()
-#if QT_CONFIG(xkbcommon)
- : m_ctx(0),
- m_keymap(0),
- m_state(0),
- m_mods(Qt::NoModifier)
-#endif
{
#if QT_CONFIG(xkbcommon)
qCDebug(qLcLibInput) << "Using xkbcommon for key mapping";
@@ -148,18 +68,14 @@ QLibInputKeyboard::QLibInputKeyboard()
}
m_keymap = xkb_keymap_new_from_names(m_ctx, nullptr, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!m_keymap) {
- qWarning("Failed to compile keymap");
+ qCWarning(qLcLibInput, "Failed to compile keymap");
return;
}
m_state = xkb_state_new(m_keymap);
if (!m_state) {
- qWarning("Failed to create xkb state");
+ qCWarning(qLcLibInput, "Failed to create xkb state");
return;
}
- m_modindex[0] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_CTRL);
- m_modindex[1] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_ALT);
- m_modindex[2] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_SHIFT);
- m_modindex[3] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_LOGO);
m_repeatTimer.setSingleShot(true);
connect(&m_repeatTimer, &QTimer::timeout, this, &QLibInputKeyboard::handleRepeat);
@@ -186,52 +102,33 @@ void QLibInputKeyboard::processKey(libinput_event_keyboard *e)
if (!m_ctx || !m_keymap || !m_state)
return;
- const uint32_t k = libinput_event_keyboard_get_key(e) + 8;
+ const uint32_t keycode = libinput_event_keyboard_get_key(e) + 8;
+ const xkb_keysym_t sym = xkb_state_key_get_one_sym(m_state, keycode);
const bool pressed = libinput_event_keyboard_get_key_state(e) == LIBINPUT_KEY_STATE_PRESSED;
- QVarLengthArray<char, 32> chars(32);
- const int size = xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size());
- if (Q_UNLIKELY(size + 1 > chars.size())) { // +1 for NUL
- chars.resize(size + 1);
- xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size());
- }
- const QString text = QString::fromUtf8(chars.constData(), size);
-
- const xkb_keysym_t sym = xkb_state_key_get_one_sym(m_state, k);
+ // Modifiers here is the modifier state before the event, i.e. not
+ // including the current key in case it is a modifier. See the XOR
+ // logic in QKeyEvent::modifiers(). ### QTBUG-73826
+ Qt::KeyboardModifiers modifiers = QXkbCommon::modifiers(m_state);
- // mods here is the modifier state before the event, i.e. not
- // including the current key in case it is a modifier.
- Qt::KeyboardModifiers mods = Qt::NoModifier;
- const int qtkey = keysymToQtKey(sym, &mods, text);
+ const QString text = QXkbCommon::lookupString(m_state, keycode);
+ const int qtkey = QXkbCommon::keysymToQtKey(sym, modifiers, m_state, keycode);
- if (qtkey == Qt::Key_Control)
- mods |= Qt::ControlModifier;
- if (qtkey == Qt::Key_Alt)
- mods |= Qt::AltModifier;
- if (qtkey == Qt::Key_Shift)
- mods |= Qt::ShiftModifier;
- if (qtkey == Qt::Key_Meta)
- mods |= Qt::MetaModifier;
- xkb_state_update_key(m_state, k, pressed ? XKB_KEY_DOWN : XKB_KEY_UP);
+ xkb_state_update_key(m_state, keycode, pressed ? XKB_KEY_DOWN : XKB_KEY_UP);
- if (mods != Qt::NoModifier) {
- if (pressed)
- m_mods |= mods;
- else
- m_mods &= ~mods;
+ Qt::KeyboardModifiers modifiersAfterStateChange = QXkbCommon::modifiers(m_state);
+ QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(modifiersAfterStateChange);
- QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(m_mods);
- }
QWindowSystemInterface::handleExtendedKeyEvent(nullptr,
pressed ? QEvent::KeyPress : QEvent::KeyRelease,
- qtkey, m_mods, k, sym, m_mods, text);
+ qtkey, modifiers, keycode, sym, modifiers, text);
- if (pressed && xkb_keymap_key_repeats(m_keymap, k)) {
+ if (pressed && xkb_keymap_key_repeats(m_keymap, keycode)) {
m_repeatData.qtkey = qtkey;
- m_repeatData.mods = mods;
- m_repeatData.nativeScanCode = k;
+ m_repeatData.mods = modifiers;
+ m_repeatData.nativeScanCode = keycode;
m_repeatData.virtualKey = sym;
- m_repeatData.nativeMods = mods;
+ m_repeatData.nativeMods = modifiers;
m_repeatData.unicodeText = text;
m_repeatData.repeatCount = 1;
m_repeatTimer.setInterval(REPEAT_DELAY);
@@ -256,50 +153,6 @@ void QLibInputKeyboard::handleRepeat()
m_repeatTimer.setInterval(REPEAT_RATE);
m_repeatTimer.start();
}
-
-int QLibInputKeyboard::keysymToQtKey(xkb_keysym_t key) const
-{
- const size_t elemCount = sizeof(keyTab) / sizeof(KeyTabEntry);
- KeyTabEntry e;
- e.xkbkey = key;
- const KeyTabEntry *result = std::find(keyTab, keyTab + elemCount, e);
- return result != keyTab + elemCount ? result->qtkey : 0;
-}
-
-int QLibInputKeyboard::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers *modifiers, const QString &text) const
-{
- int code = 0;
-#if QT_CONFIG(textcodec)
- QTextCodec *systemCodec = QTextCodec::codecForLocale();
-#endif
- if (keysym < 128 || (keysym < 256
-#if QT_CONFIG(textcodec)
- && systemCodec->mibEnum() == 4
-#endif
- )) {
- // upper-case key, if known
- code = isprint((int)keysym) ? toupper((int)keysym) : 0;
- } else if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
- // function keys
- code = Qt::Key_F1 + ((int)keysym - XKB_KEY_F1);
- } else if (keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_9) {
- if (keysym >= XKB_KEY_KP_0) {
- // numeric keypad keys
- code = Qt::Key_0 + ((int)keysym - XKB_KEY_KP_0);
- } else {
- code = keysymToQtKey(keysym);
- }
- *modifiers |= Qt::KeypadModifier;
- } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f
- && text.unicode()->unicode() != 0x7f
- && !(keysym >= XKB_KEY_dead_grave && keysym <= XKB_KEY_dead_longsolidusoverlay)) {
- code = text.unicode()->toUpper().unicode();
- } else {
- // any other keys
- code = keysymToQtKey(keysym);
- }
- return code;
-}
#endif
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard_p.h b/src/platformsupport/input/libinput/qlibinputkeyboard_p.h
index 14ae71b545..7521902e02 100644
--- a/src/platformsupport/input/libinput/qlibinputkeyboard_p.h
+++ b/src/platformsupport/input/libinput/qlibinputkeyboard_p.h
@@ -79,10 +79,9 @@ private:
int keysymToQtKey(xkb_keysym_t key) const;
int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers *modifiers, const QString &text) const;
- xkb_context *m_ctx;
- xkb_keymap *m_keymap;
- xkb_state *m_state;
- xkb_mod_index_t m_modindex[4];
+ xkb_context *m_ctx = nullptr;
+ xkb_keymap *m_keymap = nullptr;
+ xkb_state *m_state = nullptr;
QTimer m_repeatTimer;
@@ -95,7 +94,6 @@ private:
QString unicodeText;
int repeatCount;
} m_repeatData;
- Qt::KeyboardModifiers m_mods;
#endif
};
diff --git a/src/platformsupport/input/libinput/qlibinputpointer.cpp b/src/platformsupport/input/libinput/qlibinputpointer.cpp
index c54b61fc66..db9e81b5df 100644
--- a/src/platformsupport/input/libinput/qlibinputpointer.cpp
+++ b/src/platformsupport/input/libinput/qlibinputpointer.cpp
@@ -103,6 +103,24 @@ void QLibInputPointer::processMotion(libinput_event_pointer *e)
Qt::NoButton, QEvent::MouseMove, mods);
}
+void QLibInputPointer::processAbsMotion(libinput_event_pointer *e)
+{
+ QScreen * const primaryScreen = QGuiApplication::primaryScreen();
+ const QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen);
+
+ const double x = libinput_event_pointer_get_absolute_x_transformed(e, g.width());
+ const double y = libinput_event_pointer_get_absolute_y_transformed(e, g.height());
+
+ m_pos.setX(qBound(g.left(), qRound(g.left() + x), g.right()));
+ m_pos.setY(qBound(g.top(), qRound(g.top() + y), g.bottom()));
+
+ Qt::KeyboardModifiers mods = QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers();
+
+ QWindowSystemInterface::handleMouseEvent(nullptr, m_pos, m_pos, m_buttons,
+ Qt::NoButton, QEvent::MouseMove, mods);
+
+}
+
void QLibInputPointer::processAxis(libinput_event_pointer *e)
{
double value; // default axis value is 15 degrees per wheel click
diff --git a/src/platformsupport/input/libinput/qlibinputpointer_p.h b/src/platformsupport/input/libinput/qlibinputpointer_p.h
index a7a66337f1..55d4a5f919 100644
--- a/src/platformsupport/input/libinput/qlibinputpointer_p.h
+++ b/src/platformsupport/input/libinput/qlibinputpointer_p.h
@@ -64,6 +64,7 @@ public:
void processButton(libinput_event_pointer *e);
void processMotion(libinput_event_pointer *e);
+ void processAbsMotion(libinput_event_pointer *e);
void processAxis(libinput_event_pointer *e);
void setPos(const QPoint &pos);
diff --git a/src/platformsupport/input/libinput/qlibinputtouch_p.h b/src/platformsupport/input/libinput/qlibinputtouch_p.h
index 6f88001d19..51304e6a21 100644
--- a/src/platformsupport/input/libinput/qlibinputtouch_p.h
+++ b/src/platformsupport/input/libinput/qlibinputtouch_p.h
@@ -73,7 +73,7 @@ public:
private:
struct DeviceState {
- DeviceState() : m_touchDevice(0) { }
+ DeviceState() : m_touchDevice(nullptr) { }
QWindowSystemInterface::TouchPoint *point(int32_t slot);
QList<QWindowSystemInterface::TouchPoint> m_points;
QTouchDevice *m_touchDevice;
diff --git a/src/plugins/platforms/mirclient/qmirclientclipboard.h b/src/platformsupport/input/shared/devicehandlerlist_p.h
index 09e9bcdf38..97794d4d7d 100644
--- a/src/plugins/platforms/mirclient/qmirclientclipboard.h
+++ b/src/platformsupport/input/shared/devicehandlerlist_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,56 +37,59 @@
**
****************************************************************************/
+#ifndef QTINPUTSUPPORT_DEVICEHANDLERLIST_P_H
+#define QTINPUTSUPPORT_DEVICEHANDLERLIST_P_H
-#ifndef QMIRCLIENTCLIPBOARD_H
-#define QMIRCLIENTCLIPBOARD_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
-#include <qpa/qplatformclipboard.h>
+#include <QString>
-#include <QMimeData>
-#include <QPointer>
+#include <vector>
+#include <memory>
-namespace com {
- namespace ubuntu {
- namespace content {
- class Hub;
- }
- }
-}
-
-class QDBusPendingCallWatcher;
+namespace QtInputSupport {
-class QMirClientClipboard : public QObject, public QPlatformClipboard
-{
- Q_OBJECT
+template <typename Handler>
+class DeviceHandlerList {
public:
- QMirClientClipboard();
- virtual ~QMirClientClipboard();
-
- // QPlatformClipboard methods.
- QMimeData* mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
- void setMimeData(QMimeData* data, QClipboard::Mode mode = QClipboard::Clipboard) override;
- bool supportsMode(QClipboard::Mode mode) const override;
- bool ownsMode(QClipboard::Mode mode) const override;
+ struct Device {
+ QString deviceNode;
+ std::unique_ptr<Handler> handler;
+ };
-private Q_SLOTS:
- void onApplicationStateChanged(Qt::ApplicationState state);
-
-private:
- void updateMimeData();
- void requestMimeData();
+ void add(const QString &deviceNode, std::unique_ptr<Handler> handler)
+ {
+ v.push_back({deviceNode, std::move(handler)});
+ }
- QMimeData *mMimeData;
+ bool remove(const QString &deviceNode)
+ {
+ const auto deviceNodeMatches = [&] (const Device &d) { return d.deviceNode == deviceNode; };
+ const auto it = std::find_if(v.cbegin(), v.cend(), deviceNodeMatches);
+ if (it == v.cend())
+ return false;
+ v.erase(it);
+ return true;
+ }
- enum {
- OutdatedClipboard, // Our mimeData is outdated, need to fetch latest from ContentHub
- SyncingClipboard, // Our mimeData is outdated and we are waiting for ContentHub to reply with the latest paste
- SyncedClipboard // Our mimeData is in sync with what ContentHub has
- } mClipboardState{OutdatedClipboard};
+ int count() const noexcept { return static_cast<int>(v.size()); }
- com::ubuntu::content::Hub *mContentHub;
+ typename std::vector<Device>::const_iterator begin() const noexcept { return v.begin(); }
+ typename std::vector<Device>::const_iterator end() const noexcept { return v.end(); }
- QDBusPendingCallWatcher *mPasteReply{nullptr};
+private:
+ std::vector<Device> v;
};
-#endif // QMIRCLIENTCLIPBOARD_H
+} // QtInputSupport
+
+#endif // QTINPUTSUPPORT_DEVICEHANDLERLIST_P_H
diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.cpp b/src/platformsupport/input/shared/qevdevutil.cpp
index fc44edfe40..74f8bcdc2b 100644
--- a/src/plugins/platforms/mirclient/qmirclientplugin.cpp
+++ b/src/platformsupport/input/shared/qevdevutil.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the plugins module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,20 +37,34 @@
**
****************************************************************************/
+#include "qevdevutil_p.h"
-#include "qmirclientplugin.h"
-#include "qmirclientintegration.h"
-#include "qmirclientlogging.h"
+QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(mirclient, "qt.qpa.mirclient", QtWarningMsg)
+namespace QEvdevUtil {
-QPlatformIntegration *QMirClientIntegrationPlugin::create(const QString &system,
- const QStringList &/*paramList*/,
- int &argc, char **argv)
+ParsedSpecification parseSpecification(const QString &specification)
{
- if (system.toLower() == QLatin1String("mirclient")) {
- return new QMirClientClientIntegration(argc, argv);
- } else {
- return 0;
+ ParsedSpecification result;
+
+ result.args = specification.splitRef(QLatin1Char(':'));
+
+ for (const QStringRef &arg : qAsConst(result.args)) {
+ if (arg.startsWith(QLatin1String("/dev/"))) {
+ // if device is specified try to use it
+ result.devices.append(arg.toString());
+ } else {
+ // build new specification without /dev/ elements
+ result.spec += arg + QLatin1Char(':');
+ }
}
+
+ if (!result.spec.isEmpty())
+ result.spec.chop(1); // remove trailing ':'
+
+ return result;
}
+
+} // namespace QEvdevUtil
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.h b/src/platformsupport/input/shared/qevdevutil_p.h
index 92331a6fb1..7d0a5af130 100644
--- a/src/plugins/platforms/mirclient/qmirclientglcontext.h
+++ b/src/platformsupport/input/shared/qevdevutil_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the plugins module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,27 +37,40 @@
**
****************************************************************************/
+#ifndef QEVDEVUTIL_P_H
+#define QEVDEVUTIL_P_H
-#ifndef QMIRCLIENTGLCONTEXT_H
-#define QMIRCLIENTGLCONTEXT_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
-#include <qpa/qplatformopenglcontext.h>
-#include <QtEglSupport/private/qeglplatformcontext_p.h>
+#include <QString>
+#include <QStringList>
+#include <QVector>
+#include <QStringRef>
-#include <EGL/egl.h>
+QT_BEGIN_NAMESPACE
-class QMirClientOpenGLContext : public QEGLPlatformContext
+namespace QEvdevUtil {
+
+struct ParsedSpecification
{
-public:
- QMirClientOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
- EGLDisplay display);
+ QString spec;
+ QStringList devices;
+ QVector<QStringRef> args;
+};
- // QEGLPlatformContext methods.
- void swapBuffers(QPlatformSurface *surface) final;
- bool makeCurrent(QPlatformSurface *surface) final;
+ParsedSpecification parseSpecification(const QString &specification);
-protected:
- EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) final;
-};
+}
+
+QT_END_NAMESPACE
-#endif // QMIRCLIENTGLCONTEXT_H
+#endif // QEVDEVUTIL_P_H
diff --git a/src/platformsupport/input/shared/shared.pri b/src/platformsupport/input/shared/shared.pri
index 1443235244..c29d11e7d6 100644
--- a/src/platformsupport/input/shared/shared.pri
+++ b/src/platformsupport/input/shared/shared.pri
@@ -1,5 +1,8 @@
HEADERS += \
+ $$PWD/devicehandlerlist_p.h \
+ $$PWD/qevdevutil_p.h \
$$PWD/qtouchoutputmapping_p.h
SOURCES += \
+ $$PWD/qevdevutil.cpp \
$$PWD/qtouchoutputmapping.cpp
diff --git a/src/platformsupport/input/tslib/qtslib.cpp b/src/platformsupport/input/tslib/qtslib.cpp
index 7609416fea..df57147af6 100644
--- a/src/platformsupport/input/tslib/qtslib.cpp
+++ b/src/platformsupport/input/tslib/qtslib.cpp
@@ -57,38 +57,20 @@ QTsLibMouseHandler::QTsLibMouseHandler(const QString &key,
const QString &specification,
QObject *parent)
: QObject(parent),
- m_notify(0), m_x(0), m_y(0), m_pressed(0), m_rawMode(false)
+ m_rawMode(!key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive))
{
qCDebug(qLcTsLib) << "Initializing tslib plugin" << key << specification;
setObjectName(QLatin1String("TSLib Mouse Handler"));
- QByteArray device = qgetenv("TSLIB_TSDEVICE");
-
- if (specification.startsWith(QLatin1String("/dev/")))
- device = specification.toLocal8Bit();
-
- if (device.isEmpty())
- device = QByteArrayLiteral("/dev/input/event1");
-
- m_dev = ts_open(device.constData(), 1);
+ m_dev = ts_setup(nullptr, 1);
if (!m_dev) {
- qErrnoWarning(errno, "ts_open() failed");
+ qErrnoWarning(errno, "ts_setup() failed");
return;
}
- if (ts_config(m_dev))
- qErrnoWarning(errno, "ts_config() failed");
-
- m_rawMode = !key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive);
-
- int fd = ts_fd(m_dev);
- if (fd >= 0) {
- qCDebug(qLcTsLib) << "tslib device is" << device;
- m_notify = new QSocketNotifier(fd, QSocketNotifier::Read, this);
- connect(m_notify, &QSocketNotifier::activated, this, &QTsLibMouseHandler::readMouseData);
- } else {
- qErrnoWarning(errno, "tslib: Cannot open input device %s", device.constData());
- }
+ qCDebug(qLcTsLib) << "tslib device is" << ts_get_eventpath(m_dev);
+ m_notify = new QSocketNotifier(ts_fd(m_dev), QSocketNotifier::Read, this);
+ connect(m_notify, &QSocketNotifier::activated, this, &QTsLibMouseHandler::readMouseData);
}
QTsLibMouseHandler::~QTsLibMouseHandler()
diff --git a/src/platformsupport/input/tslib/qtslib_p.h b/src/platformsupport/input/tslib/qtslib_p.h
index 0c08fb6a3d..ffd60cd0e3 100644
--- a/src/platformsupport/input/tslib/qtslib_p.h
+++ b/src/platformsupport/input/tslib/qtslib_p.h
@@ -71,11 +71,12 @@ private slots:
void readMouseData();
private:
- QSocketNotifier * m_notify;
+ QSocketNotifier * m_notify = nullptr;
tsdev *m_dev;
- int m_x, m_y;
- bool m_pressed;
- bool m_rawMode;
+ int m_x = 0;
+ int m_y = 0;
+ bool m_pressed = false;
+ const bool m_rawMode;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/xkbcommon/qxkbcommon.cpp b/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
new file mode 100644
index 0000000000..877c5d848f
--- /dev/null
+++ b/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
@@ -0,0 +1,828 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxkbcommon_p.h"
+
+#include <private/qmakearray_p.h>
+
+#include <QtCore/QMetaMethod>
+#include <QtGui/QKeyEvent>
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <qpa/qplatforminputcontext.h>
+#include <qpa/qplatformintegration.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcXkbcommon, "qt.xkbcommon")
+
+static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
+ xkb_state *state, xkb_keycode_t code,
+ bool superAsMeta, bool hyperAsMeta);
+
+typedef struct xkb2qt
+{
+ unsigned int xkb;
+ unsigned int qt;
+
+ constexpr bool operator <=(const xkb2qt &that) const noexcept
+ {
+ return xkb <= that.xkb;
+ }
+
+ constexpr bool operator <(const xkb2qt &that) const noexcept
+ {
+ return xkb < that.xkb;
+ }
+} xkb2qt_t;
+
+template<std::size_t Xkb, std::size_t Qt>
+struct Xkb2Qt
+{
+ using Type = xkb2qt_t;
+ static constexpr Type data() noexcept { return Type{Xkb, Qt}; }
+};
+
+static constexpr const auto KeyTbl = qMakeArray(
+ QSortedData<
+ // misc keys
+
+ Xkb2Qt<XKB_KEY_Escape, Qt::Key_Escape>,
+ Xkb2Qt<XKB_KEY_Tab, Qt::Key_Tab>,
+ Xkb2Qt<XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab>,
+ Xkb2Qt<XKB_KEY_BackSpace, Qt::Key_Backspace>,
+ Xkb2Qt<XKB_KEY_Return, Qt::Key_Return>,
+ Xkb2Qt<XKB_KEY_Insert, Qt::Key_Insert>,
+ Xkb2Qt<XKB_KEY_Delete, Qt::Key_Delete>,
+ Xkb2Qt<XKB_KEY_Clear, Qt::Key_Delete>,
+ Xkb2Qt<XKB_KEY_Pause, Qt::Key_Pause>,
+ Xkb2Qt<XKB_KEY_Print, Qt::Key_Print>,
+ Xkb2Qt<0x1005FF60, Qt::Key_SysReq>, // hardcoded Sun SysReq
+ Xkb2Qt<0x1007ff00, Qt::Key_SysReq>, // hardcoded X386 SysReq
+
+ // cursor movement
+
+ Xkb2Qt<XKB_KEY_Home, Qt::Key_Home>,
+ Xkb2Qt<XKB_KEY_End, Qt::Key_End>,
+ Xkb2Qt<XKB_KEY_Left, Qt::Key_Left>,
+ Xkb2Qt<XKB_KEY_Up, Qt::Key_Up>,
+ Xkb2Qt<XKB_KEY_Right, Qt::Key_Right>,
+ Xkb2Qt<XKB_KEY_Down, Qt::Key_Down>,
+ Xkb2Qt<XKB_KEY_Prior, Qt::Key_PageUp>,
+ Xkb2Qt<XKB_KEY_Next, Qt::Key_PageDown>,
+
+ // modifiers
+
+ Xkb2Qt<XKB_KEY_Shift_L, Qt::Key_Shift>,
+ Xkb2Qt<XKB_KEY_Shift_R, Qt::Key_Shift>,
+ Xkb2Qt<XKB_KEY_Shift_Lock, Qt::Key_Shift>,
+ Xkb2Qt<XKB_KEY_Control_L, Qt::Key_Control>,
+ Xkb2Qt<XKB_KEY_Control_R, Qt::Key_Control>,
+ Xkb2Qt<XKB_KEY_Meta_L, Qt::Key_Meta>,
+ Xkb2Qt<XKB_KEY_Meta_R, Qt::Key_Meta>,
+ Xkb2Qt<XKB_KEY_Alt_L, Qt::Key_Alt>,
+ Xkb2Qt<XKB_KEY_Alt_R, Qt::Key_Alt>,
+ Xkb2Qt<XKB_KEY_Caps_Lock, Qt::Key_CapsLock>,
+ Xkb2Qt<XKB_KEY_Num_Lock, Qt::Key_NumLock>,
+ Xkb2Qt<XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock>,
+ Xkb2Qt<XKB_KEY_Super_L, Qt::Key_Super_L>,
+ Xkb2Qt<XKB_KEY_Super_R, Qt::Key_Super_R>,
+ Xkb2Qt<XKB_KEY_Menu, Qt::Key_Menu>,
+ Xkb2Qt<XKB_KEY_Hyper_L, Qt::Key_Hyper_L>,
+ Xkb2Qt<XKB_KEY_Hyper_R, Qt::Key_Hyper_R>,
+ Xkb2Qt<XKB_KEY_Help, Qt::Key_Help>,
+ Xkb2Qt<0x1000FF74, Qt::Key_Backtab>, // hardcoded HP backtab
+ Xkb2Qt<0x1005FF10, Qt::Key_F11>, // hardcoded Sun F36 (labeled F11)
+ Xkb2Qt<0x1005FF11, Qt::Key_F12>, // hardcoded Sun F37 (labeled F12)
+
+ // numeric and function keypad keys
+
+ Xkb2Qt<XKB_KEY_KP_Space, Qt::Key_Space>,
+ Xkb2Qt<XKB_KEY_KP_Tab, Qt::Key_Tab>,
+ Xkb2Qt<XKB_KEY_KP_Enter, Qt::Key_Enter>,
+ Xkb2Qt<XKB_KEY_KP_Home, Qt::Key_Home>,
+ Xkb2Qt<XKB_KEY_KP_Left, Qt::Key_Left>,
+ Xkb2Qt<XKB_KEY_KP_Up, Qt::Key_Up>,
+ Xkb2Qt<XKB_KEY_KP_Right, Qt::Key_Right>,
+ Xkb2Qt<XKB_KEY_KP_Down, Qt::Key_Down>,
+ Xkb2Qt<XKB_KEY_KP_Prior, Qt::Key_PageUp>,
+ Xkb2Qt<XKB_KEY_KP_Next, Qt::Key_PageDown>,
+ Xkb2Qt<XKB_KEY_KP_End, Qt::Key_End>,
+ Xkb2Qt<XKB_KEY_KP_Begin, Qt::Key_Clear>,
+ Xkb2Qt<XKB_KEY_KP_Insert, Qt::Key_Insert>,
+ Xkb2Qt<XKB_KEY_KP_Delete, Qt::Key_Delete>,
+ Xkb2Qt<XKB_KEY_KP_Equal, Qt::Key_Equal>,
+ Xkb2Qt<XKB_KEY_KP_Multiply, Qt::Key_Asterisk>,
+ Xkb2Qt<XKB_KEY_KP_Add, Qt::Key_Plus>,
+ Xkb2Qt<XKB_KEY_KP_Separator, Qt::Key_Comma>,
+ Xkb2Qt<XKB_KEY_KP_Subtract, Qt::Key_Minus>,
+ Xkb2Qt<XKB_KEY_KP_Decimal, Qt::Key_Period>,
+ Xkb2Qt<XKB_KEY_KP_Divide, Qt::Key_Slash>,
+
+ // special non-XF86 function keys
+
+ Xkb2Qt<XKB_KEY_Undo, Qt::Key_Undo>,
+ Xkb2Qt<XKB_KEY_Redo, Qt::Key_Redo>,
+ Xkb2Qt<XKB_KEY_Find, Qt::Key_Find>,
+ Xkb2Qt<XKB_KEY_Cancel, Qt::Key_Cancel>,
+
+ // International input method support keys
+
+ // International & multi-key character composition
+ Xkb2Qt<XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr>,
+ Xkb2Qt<XKB_KEY_Multi_key, Qt::Key_Multi_key>,
+ Xkb2Qt<XKB_KEY_Codeinput, Qt::Key_Codeinput>,
+ Xkb2Qt<XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate>,
+ Xkb2Qt<XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate>,
+ Xkb2Qt<XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate>,
+
+ // Misc Functions
+ Xkb2Qt<XKB_KEY_Mode_switch, Qt::Key_Mode_switch>,
+ Xkb2Qt<XKB_KEY_script_switch, Qt::Key_Mode_switch>,
+
+ // Japanese keyboard support
+ Xkb2Qt<XKB_KEY_Kanji, Qt::Key_Kanji>,
+ Xkb2Qt<XKB_KEY_Muhenkan, Qt::Key_Muhenkan>,
+ //Xkb2Qt<XKB_KEY_Henkan_Mode, Qt::Key_Henkan_Mode>,
+ Xkb2Qt<XKB_KEY_Henkan_Mode, Qt::Key_Henkan>,
+ Xkb2Qt<XKB_KEY_Henkan, Qt::Key_Henkan>,
+ Xkb2Qt<XKB_KEY_Romaji, Qt::Key_Romaji>,
+ Xkb2Qt<XKB_KEY_Hiragana, Qt::Key_Hiragana>,
+ Xkb2Qt<XKB_KEY_Katakana, Qt::Key_Katakana>,
+ Xkb2Qt<XKB_KEY_Hiragana_Katakana, Qt::Key_Hiragana_Katakana>,
+ Xkb2Qt<XKB_KEY_Zenkaku, Qt::Key_Zenkaku>,
+ Xkb2Qt<XKB_KEY_Hankaku, Qt::Key_Hankaku>,
+ Xkb2Qt<XKB_KEY_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku>,
+ Xkb2Qt<XKB_KEY_Touroku, Qt::Key_Touroku>,
+ Xkb2Qt<XKB_KEY_Massyo, Qt::Key_Massyo>,
+ Xkb2Qt<XKB_KEY_Kana_Lock, Qt::Key_Kana_Lock>,
+ Xkb2Qt<XKB_KEY_Kana_Shift, Qt::Key_Kana_Shift>,
+ Xkb2Qt<XKB_KEY_Eisu_Shift, Qt::Key_Eisu_Shift>,
+ Xkb2Qt<XKB_KEY_Eisu_toggle, Qt::Key_Eisu_toggle>,
+ //Xkb2Qt<XKB_KEY_Kanji_Bangou, Qt::Key_Kanji_Bangou>,
+ //Xkb2Qt<XKB_KEY_Zen_Koho, Qt::Key_Zen_Koho>,
+ //Xkb2Qt<XKB_KEY_Mae_Koho, Qt::Key_Mae_Koho>,
+ Xkb2Qt<XKB_KEY_Kanji_Bangou, Qt::Key_Codeinput>,
+ Xkb2Qt<XKB_KEY_Zen_Koho, Qt::Key_MultipleCandidate>,
+ Xkb2Qt<XKB_KEY_Mae_Koho, Qt::Key_PreviousCandidate>,
+
+ // Korean keyboard support
+ Xkb2Qt<XKB_KEY_Hangul, Qt::Key_Hangul>,
+ Xkb2Qt<XKB_KEY_Hangul_Start, Qt::Key_Hangul_Start>,
+ Xkb2Qt<XKB_KEY_Hangul_End, Qt::Key_Hangul_End>,
+ Xkb2Qt<XKB_KEY_Hangul_Hanja, Qt::Key_Hangul_Hanja>,
+ Xkb2Qt<XKB_KEY_Hangul_Jamo, Qt::Key_Hangul_Jamo>,
+ Xkb2Qt<XKB_KEY_Hangul_Romaja, Qt::Key_Hangul_Romaja>,
+ //Xkb2Qt<XKB_KEY_Hangul_Codeinput, Qt::Key_Hangul_Codeinput>,
+ Xkb2Qt<XKB_KEY_Hangul_Codeinput, Qt::Key_Codeinput>,
+ Xkb2Qt<XKB_KEY_Hangul_Jeonja, Qt::Key_Hangul_Jeonja>,
+ Xkb2Qt<XKB_KEY_Hangul_Banja, Qt::Key_Hangul_Banja>,
+ Xkb2Qt<XKB_KEY_Hangul_PreHanja, Qt::Key_Hangul_PreHanja>,
+ Xkb2Qt<XKB_KEY_Hangul_PostHanja, Qt::Key_Hangul_PostHanja>,
+ //Xkb2Qt<XKB_KEY_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate>,
+ //Xkb2Qt<XKB_KEY_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate>,
+ //Xkb2Qt<XKB_KEY_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_SingleCandidate, Qt::Key_SingleCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_Special, Qt::Key_Hangul_Special>,
+ //Xkb2Qt<XKB_KEY_Hangul_switch, Qt::Key_Hangul_switch>,
+ Xkb2Qt<XKB_KEY_Hangul_switch, Qt::Key_Mode_switch>,
+
+ // dead keys
+ Xkb2Qt<XKB_KEY_dead_grave, Qt::Key_Dead_Grave>,
+ Xkb2Qt<XKB_KEY_dead_acute, Qt::Key_Dead_Acute>,
+ Xkb2Qt<XKB_KEY_dead_circumflex, Qt::Key_Dead_Circumflex>,
+ Xkb2Qt<XKB_KEY_dead_tilde, Qt::Key_Dead_Tilde>,
+ Xkb2Qt<XKB_KEY_dead_macron, Qt::Key_Dead_Macron>,
+ Xkb2Qt<XKB_KEY_dead_breve, Qt::Key_Dead_Breve>,
+ Xkb2Qt<XKB_KEY_dead_abovedot, Qt::Key_Dead_Abovedot>,
+ Xkb2Qt<XKB_KEY_dead_diaeresis, Qt::Key_Dead_Diaeresis>,
+ Xkb2Qt<XKB_KEY_dead_abovering, Qt::Key_Dead_Abovering>,
+ Xkb2Qt<XKB_KEY_dead_doubleacute, Qt::Key_Dead_Doubleacute>,
+ Xkb2Qt<XKB_KEY_dead_caron, Qt::Key_Dead_Caron>,
+ Xkb2Qt<XKB_KEY_dead_cedilla, Qt::Key_Dead_Cedilla>,
+ Xkb2Qt<XKB_KEY_dead_ogonek, Qt::Key_Dead_Ogonek>,
+ Xkb2Qt<XKB_KEY_dead_iota, Qt::Key_Dead_Iota>,
+ Xkb2Qt<XKB_KEY_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound>,
+ Xkb2Qt<XKB_KEY_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound>,
+ Xkb2Qt<XKB_KEY_dead_belowdot, Qt::Key_Dead_Belowdot>,
+ Xkb2Qt<XKB_KEY_dead_hook, Qt::Key_Dead_Hook>,
+ Xkb2Qt<XKB_KEY_dead_horn, Qt::Key_Dead_Horn>,
+ Xkb2Qt<XKB_KEY_dead_stroke, Qt::Key_Dead_Stroke>,
+ Xkb2Qt<XKB_KEY_dead_abovecomma, Qt::Key_Dead_Abovecomma>,
+ Xkb2Qt<XKB_KEY_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma>,
+ Xkb2Qt<XKB_KEY_dead_doublegrave, Qt::Key_Dead_Doublegrave>,
+ Xkb2Qt<XKB_KEY_dead_belowring, Qt::Key_Dead_Belowring>,
+ Xkb2Qt<XKB_KEY_dead_belowmacron, Qt::Key_Dead_Belowmacron>,
+ Xkb2Qt<XKB_KEY_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex>,
+ Xkb2Qt<XKB_KEY_dead_belowtilde, Qt::Key_Dead_Belowtilde>,
+ Xkb2Qt<XKB_KEY_dead_belowbreve, Qt::Key_Dead_Belowbreve>,
+ Xkb2Qt<XKB_KEY_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis>,
+ Xkb2Qt<XKB_KEY_dead_invertedbreve, Qt::Key_Dead_Invertedbreve>,
+ Xkb2Qt<XKB_KEY_dead_belowcomma, Qt::Key_Dead_Belowcomma>,
+ Xkb2Qt<XKB_KEY_dead_currency, Qt::Key_Dead_Currency>,
+ Xkb2Qt<XKB_KEY_dead_a, Qt::Key_Dead_a>,
+ Xkb2Qt<XKB_KEY_dead_A, Qt::Key_Dead_A>,
+ Xkb2Qt<XKB_KEY_dead_e, Qt::Key_Dead_e>,
+ Xkb2Qt<XKB_KEY_dead_E, Qt::Key_Dead_E>,
+ Xkb2Qt<XKB_KEY_dead_i, Qt::Key_Dead_i>,
+ Xkb2Qt<XKB_KEY_dead_I, Qt::Key_Dead_I>,
+ Xkb2Qt<XKB_KEY_dead_o, Qt::Key_Dead_o>,
+ Xkb2Qt<XKB_KEY_dead_O, Qt::Key_Dead_O>,
+ Xkb2Qt<XKB_KEY_dead_u, Qt::Key_Dead_u>,
+ Xkb2Qt<XKB_KEY_dead_U, Qt::Key_Dead_U>,
+ Xkb2Qt<XKB_KEY_dead_small_schwa, Qt::Key_Dead_Small_Schwa>,
+ Xkb2Qt<XKB_KEY_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa>,
+ Xkb2Qt<XKB_KEY_dead_greek, Qt::Key_Dead_Greek>,
+ Xkb2Qt<XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline>,
+ Xkb2Qt<XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline>,
+ Xkb2Qt<XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline>,
+ Xkb2Qt<XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay>,
+
+ // Special keys from X.org - This include multimedia keys,
+ // wireless/bluetooth/uwb keys, special launcher keys, etc.
+ Xkb2Qt<XKB_KEY_XF86Back, Qt::Key_Back>,
+ Xkb2Qt<XKB_KEY_XF86Forward, Qt::Key_Forward>,
+ Xkb2Qt<XKB_KEY_XF86Stop, Qt::Key_Stop>,
+ Xkb2Qt<XKB_KEY_XF86Refresh, Qt::Key_Refresh>,
+ Xkb2Qt<XKB_KEY_XF86Favorites, Qt::Key_Favorites>,
+ Xkb2Qt<XKB_KEY_XF86AudioMedia, Qt::Key_LaunchMedia>,
+ Xkb2Qt<XKB_KEY_XF86OpenURL, Qt::Key_OpenUrl>,
+ Xkb2Qt<XKB_KEY_XF86HomePage, Qt::Key_HomePage>,
+ Xkb2Qt<XKB_KEY_XF86Search, Qt::Key_Search>,
+ Xkb2Qt<XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown>,
+ Xkb2Qt<XKB_KEY_XF86AudioMute, Qt::Key_VolumeMute>,
+ Xkb2Qt<XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp>,
+ Xkb2Qt<XKB_KEY_XF86AudioPlay, Qt::Key_MediaPlay>,
+ Xkb2Qt<XKB_KEY_XF86AudioStop, Qt::Key_MediaStop>,
+ Xkb2Qt<XKB_KEY_XF86AudioPrev, Qt::Key_MediaPrevious>,
+ Xkb2Qt<XKB_KEY_XF86AudioNext, Qt::Key_MediaNext>,
+ Xkb2Qt<XKB_KEY_XF86AudioRecord, Qt::Key_MediaRecord>,
+ Xkb2Qt<XKB_KEY_XF86AudioPause, Qt::Key_MediaPause>,
+ Xkb2Qt<XKB_KEY_XF86Mail, Qt::Key_LaunchMail>,
+ Xkb2Qt<XKB_KEY_XF86MyComputer, Qt::Key_Launch0>, // ### Qt 6: remap properly
+ Xkb2Qt<XKB_KEY_XF86Calculator, Qt::Key_Launch1>,
+ Xkb2Qt<XKB_KEY_XF86Memo, Qt::Key_Memo>,
+ Xkb2Qt<XKB_KEY_XF86ToDoList, Qt::Key_ToDoList>,
+ Xkb2Qt<XKB_KEY_XF86Calendar, Qt::Key_Calendar>,
+ Xkb2Qt<XKB_KEY_XF86PowerDown, Qt::Key_PowerDown>,
+ Xkb2Qt<XKB_KEY_XF86ContrastAdjust, Qt::Key_ContrastAdjust>,
+ Xkb2Qt<XKB_KEY_XF86Standby, Qt::Key_Standby>,
+ Xkb2Qt<XKB_KEY_XF86MonBrightnessUp, Qt::Key_MonBrightnessUp>,
+ Xkb2Qt<XKB_KEY_XF86MonBrightnessDown, Qt::Key_MonBrightnessDown>,
+ Xkb2Qt<XKB_KEY_XF86KbdLightOnOff, Qt::Key_KeyboardLightOnOff>,
+ Xkb2Qt<XKB_KEY_XF86KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp>,
+ Xkb2Qt<XKB_KEY_XF86KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown>,
+ Xkb2Qt<XKB_KEY_XF86PowerOff, Qt::Key_PowerOff>,
+ Xkb2Qt<XKB_KEY_XF86WakeUp, Qt::Key_WakeUp>,
+ Xkb2Qt<XKB_KEY_XF86Eject, Qt::Key_Eject>,
+ Xkb2Qt<XKB_KEY_XF86ScreenSaver, Qt::Key_ScreenSaver>,
+ Xkb2Qt<XKB_KEY_XF86WWW, Qt::Key_WWW>,
+ Xkb2Qt<XKB_KEY_XF86Sleep, Qt::Key_Sleep>,
+ Xkb2Qt<XKB_KEY_XF86LightBulb, Qt::Key_LightBulb>,
+ Xkb2Qt<XKB_KEY_XF86Shop, Qt::Key_Shop>,
+ Xkb2Qt<XKB_KEY_XF86History, Qt::Key_History>,
+ Xkb2Qt<XKB_KEY_XF86AddFavorite, Qt::Key_AddFavorite>,
+ Xkb2Qt<XKB_KEY_XF86HotLinks, Qt::Key_HotLinks>,
+ Xkb2Qt<XKB_KEY_XF86BrightnessAdjust, Qt::Key_BrightnessAdjust>,
+ Xkb2Qt<XKB_KEY_XF86Finance, Qt::Key_Finance>,
+ Xkb2Qt<XKB_KEY_XF86Community, Qt::Key_Community>,
+ Xkb2Qt<XKB_KEY_XF86AudioRewind, Qt::Key_AudioRewind>,
+ Xkb2Qt<XKB_KEY_XF86BackForward, Qt::Key_BackForward>,
+ Xkb2Qt<XKB_KEY_XF86ApplicationLeft, Qt::Key_ApplicationLeft>,
+ Xkb2Qt<XKB_KEY_XF86ApplicationRight, Qt::Key_ApplicationRight>,
+ Xkb2Qt<XKB_KEY_XF86Book, Qt::Key_Book>,
+ Xkb2Qt<XKB_KEY_XF86CD, Qt::Key_CD>,
+ Xkb2Qt<XKB_KEY_XF86Calculater, Qt::Key_Calculator>,
+ Xkb2Qt<XKB_KEY_XF86Clear, Qt::Key_Clear>,
+ Xkb2Qt<XKB_KEY_XF86ClearGrab, Qt::Key_ClearGrab>,
+ Xkb2Qt<XKB_KEY_XF86Close, Qt::Key_Close>,
+ Xkb2Qt<XKB_KEY_XF86Copy, Qt::Key_Copy>,
+ Xkb2Qt<XKB_KEY_XF86Cut, Qt::Key_Cut>,
+ Xkb2Qt<XKB_KEY_XF86Display, Qt::Key_Display>,
+ Xkb2Qt<XKB_KEY_XF86DOS, Qt::Key_DOS>,
+ Xkb2Qt<XKB_KEY_XF86Documents, Qt::Key_Documents>,
+ Xkb2Qt<XKB_KEY_XF86Excel, Qt::Key_Excel>,
+ Xkb2Qt<XKB_KEY_XF86Explorer, Qt::Key_Explorer>,
+ Xkb2Qt<XKB_KEY_XF86Game, Qt::Key_Game>,
+ Xkb2Qt<XKB_KEY_XF86Go, Qt::Key_Go>,
+ Xkb2Qt<XKB_KEY_XF86iTouch, Qt::Key_iTouch>,
+ Xkb2Qt<XKB_KEY_XF86LogOff, Qt::Key_LogOff>,
+ Xkb2Qt<XKB_KEY_XF86Market, Qt::Key_Market>,
+ Xkb2Qt<XKB_KEY_XF86Meeting, Qt::Key_Meeting>,
+ Xkb2Qt<XKB_KEY_XF86MenuKB, Qt::Key_MenuKB>,
+ Xkb2Qt<XKB_KEY_XF86MenuPB, Qt::Key_MenuPB>,
+ Xkb2Qt<XKB_KEY_XF86MySites, Qt::Key_MySites>,
+ Xkb2Qt<XKB_KEY_XF86New, Qt::Key_New>,
+ Xkb2Qt<XKB_KEY_XF86News, Qt::Key_News>,
+ Xkb2Qt<XKB_KEY_XF86OfficeHome, Qt::Key_OfficeHome>,
+ Xkb2Qt<XKB_KEY_XF86Open, Qt::Key_Open>,
+ Xkb2Qt<XKB_KEY_XF86Option, Qt::Key_Option>,
+ Xkb2Qt<XKB_KEY_XF86Paste, Qt::Key_Paste>,
+ Xkb2Qt<XKB_KEY_XF86Phone, Qt::Key_Phone>,
+ Xkb2Qt<XKB_KEY_XF86Reply, Qt::Key_Reply>,
+ Xkb2Qt<XKB_KEY_XF86Reload, Qt::Key_Reload>,
+ Xkb2Qt<XKB_KEY_XF86RotateWindows, Qt::Key_RotateWindows>,
+ Xkb2Qt<XKB_KEY_XF86RotationPB, Qt::Key_RotationPB>,
+ Xkb2Qt<XKB_KEY_XF86RotationKB, Qt::Key_RotationKB>,
+ Xkb2Qt<XKB_KEY_XF86Save, Qt::Key_Save>,
+ Xkb2Qt<XKB_KEY_XF86Send, Qt::Key_Send>,
+ Xkb2Qt<XKB_KEY_XF86Spell, Qt::Key_Spell>,
+ Xkb2Qt<XKB_KEY_XF86SplitScreen, Qt::Key_SplitScreen>,
+ Xkb2Qt<XKB_KEY_XF86Support, Qt::Key_Support>,
+ Xkb2Qt<XKB_KEY_XF86TaskPane, Qt::Key_TaskPane>,
+ Xkb2Qt<XKB_KEY_XF86Terminal, Qt::Key_Terminal>,
+ Xkb2Qt<XKB_KEY_XF86Tools, Qt::Key_Tools>,
+ Xkb2Qt<XKB_KEY_XF86Travel, Qt::Key_Travel>,
+ Xkb2Qt<XKB_KEY_XF86Video, Qt::Key_Video>,
+ Xkb2Qt<XKB_KEY_XF86Word, Qt::Key_Word>,
+ Xkb2Qt<XKB_KEY_XF86Xfer, Qt::Key_Xfer>,
+ Xkb2Qt<XKB_KEY_XF86ZoomIn, Qt::Key_ZoomIn>,
+ Xkb2Qt<XKB_KEY_XF86ZoomOut, Qt::Key_ZoomOut>,
+ Xkb2Qt<XKB_KEY_XF86Away, Qt::Key_Away>,
+ Xkb2Qt<XKB_KEY_XF86Messenger, Qt::Key_Messenger>,
+ Xkb2Qt<XKB_KEY_XF86WebCam, Qt::Key_WebCam>,
+ Xkb2Qt<XKB_KEY_XF86MailForward, Qt::Key_MailForward>,
+ Xkb2Qt<XKB_KEY_XF86Pictures, Qt::Key_Pictures>,
+ Xkb2Qt<XKB_KEY_XF86Music, Qt::Key_Music>,
+ Xkb2Qt<XKB_KEY_XF86Battery, Qt::Key_Battery>,
+ Xkb2Qt<XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth>,
+ Xkb2Qt<XKB_KEY_XF86WLAN, Qt::Key_WLAN>,
+ Xkb2Qt<XKB_KEY_XF86UWB, Qt::Key_UWB>,
+ Xkb2Qt<XKB_KEY_XF86AudioForward, Qt::Key_AudioForward>,
+ Xkb2Qt<XKB_KEY_XF86AudioRepeat, Qt::Key_AudioRepeat>,
+ Xkb2Qt<XKB_KEY_XF86AudioRandomPlay, Qt::Key_AudioRandomPlay>,
+ Xkb2Qt<XKB_KEY_XF86Subtitle, Qt::Key_Subtitle>,
+ Xkb2Qt<XKB_KEY_XF86AudioCycleTrack, Qt::Key_AudioCycleTrack>,
+ Xkb2Qt<XKB_KEY_XF86Time, Qt::Key_Time>,
+ Xkb2Qt<XKB_KEY_XF86Select, Qt::Key_Select>,
+ Xkb2Qt<XKB_KEY_XF86View, Qt::Key_View>,
+ Xkb2Qt<XKB_KEY_XF86TopMenu, Qt::Key_TopMenu>,
+ Xkb2Qt<XKB_KEY_XF86Red, Qt::Key_Red>,
+ Xkb2Qt<XKB_KEY_XF86Green, Qt::Key_Green>,
+ Xkb2Qt<XKB_KEY_XF86Yellow, Qt::Key_Yellow>,
+ Xkb2Qt<XKB_KEY_XF86Blue, Qt::Key_Blue>,
+ Xkb2Qt<XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth>,
+ Xkb2Qt<XKB_KEY_XF86Suspend, Qt::Key_Suspend>,
+ Xkb2Qt<XKB_KEY_XF86Hibernate, Qt::Key_Hibernate>,
+ Xkb2Qt<XKB_KEY_XF86TouchpadToggle, Qt::Key_TouchpadToggle>,
+ Xkb2Qt<XKB_KEY_XF86TouchpadOn, Qt::Key_TouchpadOn>,
+ Xkb2Qt<XKB_KEY_XF86TouchpadOff, Qt::Key_TouchpadOff>,
+ Xkb2Qt<XKB_KEY_XF86AudioMicMute, Qt::Key_MicMute>,
+ Xkb2Qt<XKB_KEY_XF86Launch0, Qt::Key_Launch2>, // ### Qt 6: remap properly
+ Xkb2Qt<XKB_KEY_XF86Launch1, Qt::Key_Launch3>,
+ Xkb2Qt<XKB_KEY_XF86Launch2, Qt::Key_Launch4>,
+ Xkb2Qt<XKB_KEY_XF86Launch3, Qt::Key_Launch5>,
+ Xkb2Qt<XKB_KEY_XF86Launch4, Qt::Key_Launch6>,
+ Xkb2Qt<XKB_KEY_XF86Launch5, Qt::Key_Launch7>,
+ Xkb2Qt<XKB_KEY_XF86Launch6, Qt::Key_Launch8>,
+ Xkb2Qt<XKB_KEY_XF86Launch7, Qt::Key_Launch9>,
+ Xkb2Qt<XKB_KEY_XF86Launch8, Qt::Key_LaunchA>,
+ Xkb2Qt<XKB_KEY_XF86Launch9, Qt::Key_LaunchB>,
+ Xkb2Qt<XKB_KEY_XF86LaunchA, Qt::Key_LaunchC>,
+ Xkb2Qt<XKB_KEY_XF86LaunchB, Qt::Key_LaunchD>,
+ Xkb2Qt<XKB_KEY_XF86LaunchC, Qt::Key_LaunchE>,
+ Xkb2Qt<XKB_KEY_XF86LaunchD, Qt::Key_LaunchF>,
+ Xkb2Qt<XKB_KEY_XF86LaunchE, Qt::Key_LaunchG>,
+ Xkb2Qt<XKB_KEY_XF86LaunchF, Qt::Key_LaunchH>
+ >::Data{}
+);
+
+xkb_keysym_t QXkbCommon::qxkbcommon_xkb_keysym_to_upper(xkb_keysym_t ks)
+{
+ xkb_keysym_t lower, upper;
+
+ xkbcommon_XConvertCase(ks, &lower, &upper);
+
+ return upper;
+}
+
+QString QXkbCommon::lookupString(struct xkb_state *state, xkb_keycode_t code)
+{
+ QVarLengthArray<char, 32> chars(32);
+ const int size = xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
+ if (Q_UNLIKELY(size + 1 > chars.size())) { // +1 for NUL
+ chars.resize(size + 1);
+ xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
+ }
+ return QString::fromUtf8(chars.constData(), size);
+}
+
+QString QXkbCommon::lookupStringNoKeysymTransformations(xkb_keysym_t keysym)
+{
+ QVarLengthArray<char, 32> chars(32);
+ const int size = xkb_keysym_to_utf8(keysym, chars.data(), chars.size());
+ if (size == 0)
+ return QString(); // the keysym does not have a Unicode representation
+
+ if (Q_UNLIKELY(size > chars.size())) {
+ chars.resize(size);
+ xkb_keysym_to_utf8(keysym, chars.data(), chars.size());
+ }
+ return QString::fromUtf8(chars.constData(), size - 1);
+}
+
+QVector<xkb_keysym_t> QXkbCommon::toKeysym(QKeyEvent *event)
+{
+ QVector<xkb_keysym_t> keysyms;
+ int qtKey = event->key();
+
+ if (qtKey >= Qt::Key_F1 && qtKey <= Qt::Key_F35) {
+ keysyms.append(XKB_KEY_F1 + (qtKey - Qt::Key_F1));
+ } else if (event->modifiers() & Qt::KeypadModifier) {
+ if (qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9)
+ keysyms.append(XKB_KEY_KP_0 + (qtKey - Qt::Key_0));
+ } else if (isLatin(qtKey) && event->text().isUpper()) {
+ keysyms.append(qtKey);
+ }
+
+ if (!keysyms.isEmpty())
+ return keysyms;
+
+ // check if we have a direct mapping
+ auto it = std::find_if(KeyTbl.cbegin(), KeyTbl.cend(), [&qtKey](xkb2qt_t elem) {
+ return elem.qt == static_cast<uint>(qtKey);
+ });
+ if (it != KeyTbl.end()) {
+ keysyms.append(it->xkb);
+ return keysyms;
+ }
+
+ QVector<uint> ucs4;
+ if (event->text().isEmpty())
+ ucs4.append(qtKey);
+ else
+ ucs4 = event->text().toUcs4();
+
+ // From libxkbcommon keysym-utf.c:
+ // "We allow to represent any UCS character in the range U-00000000 to
+ // U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff."
+ for (uint utf32 : qAsConst(ucs4))
+ keysyms.append(utf32 | 0x01000000);
+
+ return keysyms;
+}
+
+int QXkbCommon::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers)
+{
+ return keysymToQtKey(keysym, modifiers, nullptr, 0);
+}
+
+int QXkbCommon::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
+ xkb_state *state, xkb_keycode_t code,
+ bool superAsMeta, bool hyperAsMeta)
+{
+ // Note 1: All standard key sequences on linux (as defined in platform theme)
+ // that use a latin character also contain a control modifier, which is why
+ // checking for Qt::ControlModifier is sufficient here. It is possible to
+ // override QPlatformTheme::keyBindings() and provide custom sequences for
+ // QKeySequence::StandardKey. Custom sequences probably should respect this
+ // convention (alternatively, we could test against other modifiers here).
+ // Note 2: The possibleKeys() shorcut mechanism is not affected by this value
+ // adjustment and does its own thing.
+ if (modifiers & Qt::ControlModifier) {
+ // With standard shortcuts we should prefer a latin character, this is
+ // for checks like "some qkeyevent == QKeySequence::Copy" to work even
+ // when using for example 'russian' keyboard layout.
+ if (!QXkbCommon::isLatin(keysym)) {
+ xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code);
+ if (latinKeysym != XKB_KEY_NoSymbol)
+ keysym = latinKeysym;
+ }
+ }
+
+ return keysymToQtKey_internal(keysym, modifiers, state, code, superAsMeta, hyperAsMeta);
+}
+
+static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
+ xkb_state *state, xkb_keycode_t code,
+ bool superAsMeta, bool hyperAsMeta)
+{
+ int qtKey = 0;
+
+ // lookup from direct mapping
+ if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
+ // function keys
+ qtKey = Qt::Key_F1 + (keysym - XKB_KEY_F1);
+ } else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) {
+ // numeric keypad keys
+ qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0);
+ } else if (QXkbCommon::isLatin(keysym)) {
+ qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym);
+ } else {
+ // check if we have a direct mapping
+ xkb2qt_t searchKey{keysym, 0};
+ auto it = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
+ if (it != KeyTbl.end() && !(searchKey < *it))
+ qtKey = it->qt;
+ }
+
+ if (qtKey)
+ return qtKey;
+
+ // lookup from unicode
+ QString text;
+ if (!state || modifiers & Qt::ControlModifier) {
+ // Control modifier changes the text to ASCII control character, therefore we
+ // can't use this text to map keysym to a qt key. We can use the same keysym
+ // (it is not affectd by transformation) to obtain untransformed text. For details
+ // see "Appendix A. Default Symbol Transformations" in the XKB specification.
+ text = QXkbCommon::lookupStringNoKeysymTransformations(keysym);
+ } else {
+ text = QXkbCommon::lookupString(state, code);
+ }
+ if (!text.isEmpty()) {
+ if (text.unicode()->isDigit()) {
+ // Ensures that also non-latin digits are mapped to corresponding qt keys,
+ // e.g CTRL + Û² (arabic two), is mapped to CTRL + Qt::Key_2.
+ qtKey = Qt::Key_0 + text.unicode()->digitValue();
+ } else {
+ qtKey = text.unicode()->toUpper().unicode();
+ }
+ }
+
+ // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
+ if (superAsMeta && (qtKey == Qt::Key_Super_L || qtKey == Qt::Key_Super_R))
+ qtKey = Qt::Key_Meta;
+ if (hyperAsMeta && (qtKey == Qt::Key_Hyper_L || qtKey == Qt::Key_Hyper_R))
+ qtKey = Qt::Key_Meta;
+
+ return qtKey;
+}
+
+Qt::KeyboardModifiers QXkbCommon::modifiers(struct xkb_state *state)
+{
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0)
+ modifiers |= Qt::ControlModifier;
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE) > 0)
+ modifiers |= Qt::AltModifier;
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_EFFECTIVE) > 0)
+ modifiers |= Qt::ShiftModifier;
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO, XKB_STATE_MODS_EFFECTIVE) > 0)
+ modifiers |= Qt::MetaModifier;
+
+ return modifiers;
+}
+
+// Possible modifier states.
+static const Qt::KeyboardModifiers ModsTbl[] = {
+ Qt::NoModifier, // 0
+ Qt::ShiftModifier, // 1
+ Qt::ControlModifier, // 2
+ Qt::ControlModifier | Qt::ShiftModifier, // 3
+ Qt::AltModifier, // 4
+ Qt::AltModifier | Qt::ShiftModifier, // 5
+ Qt::AltModifier | Qt::ControlModifier, // 6
+ Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
+ Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts
+};
+
+QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event,
+ bool superAsMeta, bool hyperAsMeta)
+{
+ QList<int> result;
+ quint32 keycode = event->nativeScanCode();
+ Qt::KeyboardModifiers modifiers = event->modifiers();
+ xkb_keymap *keymap = xkb_state_get_keymap(state);
+ // turn off the modifier bits which doesn't participate in shortcuts
+ Qt::KeyboardModifiers notNeeded = Qt::KeypadModifier | Qt::GroupSwitchModifier;
+ modifiers &= ~notNeeded;
+ // create a fresh kb state and test against the relevant modifier combinations
+ ScopedXKBState scopedXkbQueryState(xkb_state_new(keymap));
+ xkb_state *queryState = scopedXkbQueryState.get();
+ if (!queryState) {
+ qCWarning(lcXkbcommon) << Q_FUNC_INFO << "failed to compile xkb keymap";
+ return result;
+ }
+ // get kb state from the master state and update the temporary state
+ xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED);
+ xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED);
+ xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED);
+ xkb_mod_mask_t depressedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
+ xkb_state_update_mask(queryState, depressedMods, latchedMods, lockedMods, 0, 0, lockedLayout);
+ // handle shortcuts for level three and above
+ xkb_layout_index_t layoutIndex = xkb_state_key_get_layout(queryState, keycode);
+ xkb_level_index_t levelIndex = 0;
+ if (layoutIndex != XKB_LAYOUT_INVALID) {
+ levelIndex = xkb_state_key_get_level(queryState, keycode, layoutIndex);
+ if (levelIndex == XKB_LEVEL_INVALID)
+ levelIndex = 0;
+ }
+ if (levelIndex <= 1)
+ xkb_state_update_mask(queryState, 0, latchedMods, lockedMods, 0, 0, lockedLayout);
+
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(queryState, keycode);
+ if (sym == XKB_KEY_NoSymbol)
+ return result;
+
+ int baseQtKey = keysymToQtKey_internal(sym, modifiers, queryState, keycode, superAsMeta, hyperAsMeta);
+ if (baseQtKey)
+ result += (baseQtKey + modifiers);
+
+ xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(keymap, "Shift");
+ xkb_mod_index_t altMod = xkb_keymap_mod_get_index(keymap, "Alt");
+ xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(keymap, "Control");
+ xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(keymap, "Meta");
+
+ Q_ASSERT(shiftMod < 32);
+ Q_ASSERT(altMod < 32);
+ Q_ASSERT(controlMod < 32);
+
+ xkb_mod_mask_t depressed;
+ int qtKey = 0;
+ // obtain a list of possible shortcuts for the given key event
+ for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) {
+ Qt::KeyboardModifiers neededMods = ModsTbl[i];
+ if ((modifiers & neededMods) == neededMods) {
+ if (i == 8) {
+ if (isLatin(baseQtKey))
+ continue;
+ // add a latin key as a fall back key
+ sym = lookupLatinKeysym(state, keycode);
+ } else {
+ depressed = 0;
+ if (neededMods & Qt::AltModifier)
+ depressed |= (1 << altMod);
+ if (neededMods & Qt::ShiftModifier)
+ depressed |= (1 << shiftMod);
+ if (neededMods & Qt::ControlModifier)
+ depressed |= (1 << controlMod);
+ if (metaMod < 32 && neededMods & Qt::MetaModifier)
+ depressed |= (1 << metaMod);
+ xkb_state_update_mask(queryState, depressed, latchedMods, lockedMods, 0, 0, lockedLayout);
+ sym = xkb_state_key_get_one_sym(queryState, keycode);
+ }
+ if (sym == XKB_KEY_NoSymbol)
+ continue;
+
+ Qt::KeyboardModifiers mods = modifiers & ~neededMods;
+ qtKey = keysymToQtKey_internal(sym, mods, queryState, keycode, superAsMeta, hyperAsMeta);
+ if (!qtKey || qtKey == baseQtKey)
+ continue;
+
+ // catch only more specific shortcuts, i.e. Ctrl+Shift+= also generates Ctrl++ and +,
+ // but Ctrl++ is more specific than +, so we should skip the last one
+ bool ambiguous = false;
+ for (int shortcut : qAsConst(result)) {
+ if (int(shortcut & ~Qt::KeyboardModifierMask) == qtKey && (shortcut & mods) == mods) {
+ ambiguous = true;
+ break;
+ }
+ }
+ if (ambiguous)
+ continue;
+
+ result += (qtKey + mods);
+ }
+ }
+
+ return result;
+}
+
+void QXkbCommon::verifyHasLatinLayout(xkb_keymap *keymap)
+{
+ const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(keymap);
+ const xkb_keycode_t minKeycode = xkb_keymap_min_keycode(keymap);
+ const xkb_keycode_t maxKeycode = xkb_keymap_max_keycode(keymap);
+
+ const xkb_keysym_t *keysyms = nullptr;
+ int nrLatinKeys = 0;
+ for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
+ for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
+ xkb_keymap_key_get_syms_by_level(keymap, code, layout, 0, &keysyms);
+ if (keysyms && isLatin(keysyms[0]))
+ nrLatinKeys++;
+ if (nrLatinKeys > 10) // arbitrarily chosen threshold
+ return;
+ }
+ }
+ // This means that lookupLatinKeysym() will not find anything and latin
+ // key shortcuts might not work. This is a bug in the affected desktop
+ // environment. Usually can be solved via system settings by adding e.g. 'us'
+ // layout to the list of seleced layouts, or by using command line, "setxkbmap
+ // -layout rus,en". The position of latin key based layout in the list of the
+ // selected layouts is irrelevant. Properly functioning desktop environments
+ // handle this behind the scenes, even if no latin key based layout has been
+ // explicitly listed in the selected layouts.
+ qCDebug(lcXkbcommon, "no keyboard layouts with latin keys present");
+}
+
+xkb_keysym_t QXkbCommon::lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode)
+{
+ xkb_layout_index_t layout;
+ xkb_keysym_t sym = XKB_KEY_NoSymbol;
+ xkb_keymap *keymap = xkb_state_get_keymap(state);
+ const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(keymap, keycode);
+ const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(state, keycode);
+ // Look at user layouts in the order in which they are defined in system
+ // settings to find a latin keysym.
+ for (layout = 0; layout < layoutCount; ++layout) {
+ if (layout == currentLayout)
+ continue;
+ const xkb_keysym_t *syms = nullptr;
+ xkb_level_index_t level = xkb_state_key_get_level(state, keycode, layout);
+ if (xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms) != 1)
+ continue;
+ if (isLatin(syms[0])) {
+ sym = syms[0];
+ break;
+ }
+ }
+
+ if (sym == XKB_KEY_NoSymbol)
+ return sym;
+
+ xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED);
+ xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED);
+
+ // Check for uniqueness, consider the following setup:
+ // setxkbmap -layout us,ru,us -variant dvorak,, -option 'grp:ctrl_alt_toggle' (set 'ru' as active).
+ // In this setup, the user would expect to trigger a ctrl+q shortcut by pressing ctrl+<physical x key>,
+ // because "US dvorak" is higher up in the layout settings list. This check verifies that an obtained
+ // 'sym' can not be acquired by any other layout higher up in the user's layout list. If it can be acquired
+ // then the obtained key is not unique. This prevents ctrl+<physical q key> from generating a ctrl+q
+ // shortcut in the above described setup. We don't want ctrl+<physical x key> and ctrl+<physical q key> to
+ // generate the same shortcut event in this case.
+ const xkb_keycode_t minKeycode = xkb_keymap_min_keycode(keymap);
+ const xkb_keycode_t maxKeycode = xkb_keymap_max_keycode(keymap);
+ ScopedXKBState queryState(xkb_state_new(keymap));
+ for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) {
+ xkb_state_update_mask(queryState.get(), 0, latchedMods, lockedMods, 0, 0, prevLayout);
+ for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
+ xkb_keysym_t prevSym = xkb_state_key_get_one_sym(queryState.get(), code);
+ if (prevSym == sym) {
+ sym = XKB_KEY_NoSymbol;
+ break;
+ }
+ }
+ }
+
+ return sym;
+}
+
+void QXkbCommon::setXkbContext(QPlatformInputContext *inputContext, struct xkb_context *context)
+{
+ if (!inputContext || !context)
+ return;
+
+ const char *const inputContextClassName = "QComposeInputContext";
+ const char *const normalizedSignature = "setXkbContext(xkb_context*)";
+
+ if (inputContext->objectName() != QLatin1String(inputContextClassName))
+ return;
+
+ static const QMetaMethod setXkbContext = [&]() {
+ int methodIndex = inputContext->metaObject()->indexOfMethod(normalizedSignature);
+ QMetaMethod method = inputContext->metaObject()->method(methodIndex);
+ Q_ASSERT(method.isValid());
+ if (!method.isValid())
+ qCWarning(lcXkbcommon) << normalizedSignature << "not found on" << inputContextClassName;
+ return method;
+ }();
+
+ if (!setXkbContext.isValid())
+ return;
+
+ setXkbContext.invoke(inputContext, Qt::DirectConnection, Q_ARG(struct xkb_context*, context));
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbxkbcommon.h b/src/platformsupport/input/xkbcommon/qxkbcommon_3rdparty.cpp
index 422c0c0f12..08f43b3b72 100644
--- a/src/plugins/platforms/xcb/qxcbxkbcommon.h
+++ b/src/platformsupport/input/xkbcommon/qxkbcommon_3rdparty.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,10 +37,7 @@
**
****************************************************************************/
-/* XConvertCase was copied from src/3rdparty/xkbcommon/src/keysym.c,
- which contains the following license information:
-
- Copyright 1985, 1987, 1990, 1998 The Open Group
+/* Copyright 1985, 1987, 1990, 1998 The Open Group
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -89,6 +86,7 @@
*/
/*
+ XConvertCase was copied from src/3rdparty/xkbcommon/src/keysym.c
The following code modifications were applied:
XConvertCase() was renamed to xkbcommon_XConvertCase(), to not confuse it
@@ -99,10 +97,9 @@
results instead of using the less complete version from keysym.c
*/
-#include <xkbcommon/xkbcommon.h>
-#include <QtCore/QChar>
+#include "qxkbcommon_p.h"
-QT_BEGIN_NAMESPACE
+#include <QtCore/QChar>
static void qt_UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *upper)
{
@@ -110,7 +107,7 @@ static void qt_UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *
*upper = QChar::toUpper(code);
}
-void xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper)
+void QXkbCommon::xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper)
{
/* Latin 1 keysym */
if (sym < 0x100) {
@@ -220,14 +217,3 @@ void xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t
break;
}
}
-
-xkb_keysym_t xkbcommon_xkb_keysym_to_upper(xkb_keysym_t ks)
-{
- xkb_keysym_t lower, upper;
-
- xkbcommon_XConvertCase(ks, &lower, &upper);
-
- return upper;
-}
-
-QT_END_NAMESPACE
diff --git a/src/platformsupport/input/xkbcommon/qxkbcommon_p.h b/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
new file mode 100644
index 0000000000..561eae03db
--- /dev/null
+++ b/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXKBCOMMON_P_H
+#define QXKBCOMMON_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+#include <QtCore/QVector>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QList>
+
+#include <xkbcommon/xkbcommon.h>
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcXkbcommon)
+
+class QEvent;
+class QKeyEvent;
+class QPlatformInputContext;
+
+class QXkbCommon
+{
+public:
+ static QString lookupString(struct xkb_state *state, xkb_keycode_t code);
+ static QString lookupStringNoKeysymTransformations(xkb_keysym_t keysym);
+
+ static QVector<xkb_keysym_t> toKeysym(QKeyEvent *event);
+
+ static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers);
+ static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
+ xkb_state *state, xkb_keycode_t code,
+ bool superAsMeta = false, bool hyperAsMeta = false);
+
+ // xkbcommon_* API is part of libxkbcommon internals, with modifications as
+ // desribed in the header of the implementation file.
+ static void xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper);
+ static xkb_keysym_t qxkbcommon_xkb_keysym_to_upper(xkb_keysym_t ks);
+
+ static Qt::KeyboardModifiers modifiers(struct xkb_state *state);
+
+ static QList<int> possibleKeys(xkb_state *state, const QKeyEvent *event,
+ bool superAsMeta = false, bool hyperAsMeta = false);
+
+ static void verifyHasLatinLayout(xkb_keymap *keymap);
+ static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode);
+
+ static bool isLatin(xkb_keysym_t sym) {
+ return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z'));
+ }
+ static bool isKeypad(xkb_keysym_t sym) {
+ return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9;
+ }
+
+ static void setXkbContext(QPlatformInputContext *inputContext, struct xkb_context *context);
+
+ struct XKBStateDeleter {
+ void operator()(struct xkb_state *state) const { return xkb_state_unref(state); }
+ };
+ struct XKBKeymapDeleter {
+ void operator()(struct xkb_keymap *keymap) const { return xkb_keymap_unref(keymap); }
+ };
+ struct XKBContextDeleter {
+ void operator()(struct xkb_context *context) const { return xkb_context_unref(context); }
+ };
+ using ScopedXKBState = std::unique_ptr<struct xkb_state, XKBStateDeleter>;
+ using ScopedXKBKeymap = std::unique_ptr<struct xkb_keymap, XKBKeymapDeleter>;
+ using ScopedXKBContext = std::unique_ptr<struct xkb_context, XKBContextDeleter>;
+};
+
+QT_END_NAMESPACE
+
+#endif // QXKBCOMMON_P_H
diff --git a/src/platformsupport/input/xkbcommon/xkbcommon.pro b/src/platformsupport/input/xkbcommon/xkbcommon.pro
new file mode 100644
index 0000000000..22b16ae44a
--- /dev/null
+++ b/src/platformsupport/input/xkbcommon/xkbcommon.pro
@@ -0,0 +1,23 @@
+TARGET = QtXkbCommonSupport
+MODULE = xkbcommon_support
+
+QT = core-private gui-private
+CONFIG += static internal_module
+
+DEFINES += QT_NO_CAST_FROM_ASCII
+PRECOMPILED_HEADER = ../../../corelib/global/qt_pch.h
+
+QMAKE_USE += xkbcommon
+
+HEADERS += \
+ qxkbcommon_p.h
+
+SOURCES += \
+ qxkbcommon.cpp \
+ qxkbcommon_3rdparty.cpp
+
+# qxkbcommon.cpp::KeyTbl has more than 256 levels of expansion and older
+# Clang uses that as a limit (it's 1024 in current versions).
+clang:!intel_icc: QMAKE_CXXFLAGS += -ftemplate-depth=1024
+
+load(qt_module)
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
index 7e3a870421..8cc7a539b5 100644
--- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp
+++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -791,9 +791,7 @@ void QKmsDevice::discoverPlanes()
for (int i = 0; i < countFormats; ++i) {
uint32_t f = drmplane->formats[i];
plane.supportedFormats.append(f);
- QString s;
- s.sprintf("%c%c%c%c ", f, f >> 8, f >> 16, f >> 24);
- formatStr += s;
+ formatStr += QString::asprintf("%c%c%c%c ", f, f >> 8, f >> 16, f >> 24);
}
qCDebug(qLcKmsDebug, "plane %d: id = %u countFormats = %d possibleCrtcs = 0x%x supported formats = %s",
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
index 580cf0e31d..8a825f8284 100644
--- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
+++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
@@ -2050,8 +2050,8 @@ QVariantList AtSpiAdaptor::getAttributes(QAccessibleInterface *interface, int of
int endOffset;
QString joined = interface->textInterface()->attributes(offset, &startOffset, &endOffset);
- QStringList attributes = joined.split (QLatin1Char(';'), QString::SkipEmptyParts, Qt::CaseSensitive);
- foreach (const QString &attr, attributes) {
+ const QStringList attributes = joined.split (QLatin1Char(';'), QString::SkipEmptyParts, Qt::CaseSensitive);
+ for (const QString &attr : attributes) {
QStringList items;
items = attr.split(QLatin1Char(':'), QString::SkipEmptyParts, Qt::CaseSensitive);
AtSpiAttribute attribute = atspiTextAttribute(items[0], items[1]);
@@ -2069,14 +2069,13 @@ QVariantList AtSpiAdaptor::getAttributeValue(QAccessibleInterface *interface, in
{
QString mapped;
QString joined;
- QStringList attributes;
QSpiAttributeSet map;
int startOffset;
int endOffset;
joined = interface->textInterface()->attributes(offset, &startOffset, &endOffset);
- attributes = joined.split (QLatin1Char(';'), QString::SkipEmptyParts, Qt::CaseSensitive);
- foreach (const QString& attr, attributes) {
+ const QStringList attributes = joined.split (QLatin1Char(';'), QString::SkipEmptyParts, Qt::CaseSensitive);
+ for (const QString& attr : attributes) {
QStringList items;
items = attr.split(QLatin1Char(':'), QString::SkipEmptyParts, Qt::CaseSensitive);
AtSpiAttribute attribute = atspiTextAttribute(items[0], items[1]);
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h
index b5704f53ad..0b624389a3 100644
--- a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h
+++ b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h
@@ -76,7 +76,7 @@ class AtSpiAdaptor :public QDBusVirtualObject
Q_OBJECT
public:
- explicit AtSpiAdaptor(DBusConnection *connection, QObject *parent = 0);
+ explicit AtSpiAdaptor(DBusConnection *connection, QObject *parent = nullptr);
~AtSpiAdaptor();
void registerApplication();
diff --git a/src/platformsupport/linuxaccessibility/cache_p.h b/src/platformsupport/linuxaccessibility/cache_p.h
index e8529b779b..cc55acc6f8 100644
--- a/src/platformsupport/linuxaccessibility/cache_p.h
+++ b/src/platformsupport/linuxaccessibility/cache_p.h
@@ -65,7 +65,7 @@ class QSpiDBusCache : public QObject
Q_OBJECT
public:
- explicit QSpiDBusCache(QDBusConnection c, QObject* parent = 0);
+ explicit QSpiDBusCache(QDBusConnection c, QObject* parent = nullptr);
void emitAddAccessible(const QSpiAccessibleCacheItem& item);
void emitRemoveAccessible(const QSpiObjectReference& item);
diff --git a/src/platformsupport/linuxaccessibility/dbusconnection_p.h b/src/platformsupport/linuxaccessibility/dbusconnection_p.h
index 4030fabc22..860c18ca05 100644
--- a/src/platformsupport/linuxaccessibility/dbusconnection_p.h
+++ b/src/platformsupport/linuxaccessibility/dbusconnection_p.h
@@ -65,7 +65,7 @@ class DBusConnection : public QObject
Q_OBJECT
public:
- DBusConnection(QObject *parent = 0);
+ DBusConnection(QObject *parent = nullptr);
QDBusConnection connection() const;
bool isEnabled() const { return m_enabled; }
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
index 7959f0c28a..f484795fbb 100644
--- a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
@@ -69,7 +69,7 @@ class QDBusMenuConnection : public QObject
Q_OBJECT
public:
- QDBusMenuConnection(QObject *parent = 0, const QString &serviceName = QString());
+ QDBusMenuConnection(QObject *parent = nullptr, const QString &serviceName = QString());
QDBusConnection connection() const { return m_connection; }
QDBusServiceWatcher *dbusWatcher() const { return m_dbusWatcher; }
bool isStatusNotifierHostRegistered() const { return m_statusNotifierHostRegistered; }
diff --git a/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp b/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp
index e81d272d4f..ca740f967e 100644
--- a/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp
+++ b/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp
@@ -52,6 +52,9 @@
#include <qdebug.h>
#include <qrect.h>
#include <qloggingcategory.h>
+#include <qstandardpaths.h>
+#include <qdir.h>
+#include <qmetaobject.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformservices.h>
#include <qdbusconnectioninterface.h>
diff --git a/src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor.cpp b/src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor.cpp
index d3c5454f01..ef2d330959 100644
--- a/src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor.cpp
+++ b/src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor.cpp
@@ -52,6 +52,9 @@
#ifndef QT_NO_SYSTEMTRAYICON
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QCoreApplication>
+
#include "qdbustrayicon_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h b/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h
index 03899723ab..ab99ea65dd 100644
--- a/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h
+++ b/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h
@@ -65,6 +65,7 @@
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
+#include <QtCore/QLoggingCategory>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
@@ -87,7 +88,7 @@ public:
public:
QXdgNotificationInterface(const QString &service, const QString &path,
- const QDBusConnection &connection, QObject *parent = 0);
+ const QDBusConnection &connection, QObject *parent = nullptr);
~QXdgNotificationInterface();
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index 6db25a90da..70d5616075 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -175,15 +175,9 @@ QStringList QGenericUnixTheme::xdgIconThemePaths()
if (homeIconDir.isDir())
paths.prepend(homeIconDir.absoluteFilePath());
- QString xdgDirString = QFile::decodeName(qgetenv("XDG_DATA_DIRS"));
- if (xdgDirString.isEmpty())
- xdgDirString = QLatin1String("/usr/local/share/:/usr/share/");
- const auto xdgDirs = xdgDirString.splitRef(QLatin1Char(':'));
- for (const QStringRef &xdgDir : xdgDirs) {
- const QFileInfo xdgIconsDir(xdgDir + QLatin1String("/icons"));
- if (xdgIconsDir.isDir())
- paths.append(xdgIconsDir.absoluteFilePath());
- }
+ paths.append(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation,
+ QStringLiteral("icons"),
+ QStandardPaths::LocateDirectory));
return paths;
}
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
index a5963b79ea..c0da9d8370 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
@@ -109,7 +109,7 @@ public:
QVariant themeHint(ThemeHint hint) const override;
QIcon fileIcon(const QFileInfo &fileInfo,
- QPlatformTheme::IconOptions iconOptions = 0) const override;
+ QPlatformTheme::IconOptions iconOptions = nullptr) const override;
const QPalette *palette(Palette type = SystemPalette) const override;
@@ -134,7 +134,7 @@ public:
QGnomeTheme();
QVariant themeHint(ThemeHint hint) const override;
QIcon fileIcon(const QFileInfo &fileInfo,
- QPlatformTheme::IconOptions = 0) const override;
+ QPlatformTheme::IconOptions = nullptr) const override;
const QFont *font(Font type) const override;
QString standardButtonText(int button) const override;
diff --git a/src/platformsupport/themes/qabstractfileiconengine.cpp b/src/platformsupport/themes/qabstractfileiconengine.cpp
index 192ed00510..c5800d9119 100644
--- a/src/platformsupport/themes/qabstractfileiconengine.cpp
+++ b/src/platformsupport/themes/qabstractfileiconengine.cpp
@@ -76,7 +76,7 @@ QPixmap QAbstractFileIconEngine::pixmap(const QSize &size, QIcon::Mode mode,
key += QLatin1Char('_') + QString::number(size.width());
QPixmap result;
- if (!QPixmapCache::find(key, result)) {
+ if (!QPixmapCache::find(key, &result)) {
result = filePixmap(size, mode, state);
if (!result.isNull())
QPixmapCache::insert(key, result);
diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
index b9c5669b3f..68340a3173 100644
--- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
+++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
@@ -330,6 +330,11 @@ bool QBasicPlatformVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevi
return supported;
}
+void QBasicPlatformVulkanInstance::setDebugFilters(const QVector<QVulkanInstance::DebugFilter> &filters)
+{
+ m_debugFilters = filters;
+}
+
void QBasicPlatformVulkanInstance::destroySurface(VkSurfaceKHR surface) const
{
if (m_destroySurface && surface)
@@ -345,11 +350,11 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugReportFlag
const char *pMessage,
void *pUserData)
{
- Q_UNUSED(flags);
- Q_UNUSED(objectType);
- Q_UNUSED(object);
- Q_UNUSED(location);
- Q_UNUSED(pUserData);
+ QBasicPlatformVulkanInstance *self = static_cast<QBasicPlatformVulkanInstance *>(pUserData);
+ for (QVulkanInstance::DebugFilter filter : *self->debugFilters()) {
+ if (filter(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage))
+ return VK_FALSE;
+ }
// not categorized, just route to plain old qDebug
qDebug("vkDebug: %s: %d: %s", pLayerPrefix, messageCode, pMessage);
@@ -374,6 +379,7 @@ void QBasicPlatformVulkanInstance::setupDebugOutput()
| VK_DEBUG_REPORT_WARNING_BIT_EXT
| VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
dbgCallbackInfo.pfnCallback = defaultDebugCallbackFunc;
+ dbgCallbackInfo.pUserData = this;
VkResult err = createDebugReportCallback(m_vkInst, &dbgCallbackInfo, nullptr, &m_debugCallback);
if (err != VK_SUCCESS)
diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
index 566140b032..e59d9219fb 100644
--- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
+++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
@@ -73,7 +73,10 @@ public:
QByteArrayList enabledExtensions() const override;
PFN_vkVoidFunction getInstanceProcAddr(const char *name) override;
bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override;
+ void setDebugFilters(const QVector<QVulkanInstance::DebugFilter> &filters) override;
+
void destroySurface(VkSurfaceKHR surface) const;
+ const QVector<QVulkanInstance::DebugFilter> *debugFilters() const { return &m_debugFilters; }
protected:
void loadVulkanLibrary(const QString &defaultLibraryName);
@@ -105,6 +108,7 @@ private:
VkDebugReportCallbackEXT m_debugCallback;
PFN_vkDestroyDebugReportCallbackEXT m_vkDestroyDebugReportCallbackEXT;
+ QVector<QVulkanInstance::DebugFilter> m_debugFilters;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/vkconvenience/qvkconvenience.cpp b/src/platformsupport/vkconvenience/qvkconvenience.cpp
new file mode 100644
index 0000000000..acde1d1bda
--- /dev/null
+++ b/src/platformsupport/vkconvenience/qvkconvenience.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvkconvenience_p.h"
+
+#include <QOpenGLTexture>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVkConvenience
+ \brief A collection of static helper functions for Vulkan support
+ \since 5.14
+ \internal
+ \ingroup qpa
+ */
+
+#if QT_CONFIG(opengl)
+VkFormat QVkConvenience::vkFormatFromGlFormat(uint glFormat)
+{
+ using GlFormat = QOpenGLTexture::TextureFormat;
+ switch (glFormat) {
+ case GlFormat::NoFormat: return VK_FORMAT_UNDEFINED; // GL_NONE
+
+ // Unsigned normalized formats
+ case GlFormat::R8_UNorm: return VK_FORMAT_R8_UNORM; // GL_R8
+ case GlFormat::RG8_UNorm: return VK_FORMAT_R8G8_UNORM; // GL_RG8
+ case GlFormat::RGB8_UNorm: return VK_FORMAT_R8G8B8_UNORM; // GL_RGB8
+ case GlFormat::RGBA8_UNorm: return VK_FORMAT_R8G8B8A8_UNORM; // GL_RGBA8
+
+ case GlFormat::R16_UNorm: return VK_FORMAT_R16_UNORM; // GL_R16
+ case GlFormat::RG16_UNorm: return VK_FORMAT_R16G16_UNORM; // GL_RG16
+ case GlFormat::RGB16_UNorm: return VK_FORMAT_R16G16B16_UNORM; // GL_RGB16
+ case GlFormat::RGBA16_UNorm: return VK_FORMAT_R16G16B16A16_UNORM; // GL_RGBA16
+
+ // Signed normalized formats
+ case GlFormat::R8_SNorm: return VK_FORMAT_R8_SNORM; // GL_R8_SNORM
+ case GlFormat::RG8_SNorm: return VK_FORMAT_R8G8_SNORM; // GL_RG8_SNORM
+ case GlFormat::RGB8_SNorm: return VK_FORMAT_R8G8B8_SNORM; // GL_RGB8_SNORM
+ case GlFormat::RGBA8_SNorm: return VK_FORMAT_R8G8B8A8_SNORM; // GL_RGBA8_SNORM
+
+ case GlFormat::R16_SNorm: return VK_FORMAT_R16_SNORM; // GL_R16_SNORM
+ case GlFormat::RG16_SNorm: return VK_FORMAT_R16G16_SNORM; // GL_RG16_SNORM
+ case GlFormat::RGB16_SNorm: return VK_FORMAT_R16G16B16_SNORM; // GL_RGB16_SNORM
+ case GlFormat::RGBA16_SNorm: return VK_FORMAT_R16G16B16A16_SNORM; // GL_RGBA16_SNORM
+
+ // Unsigned integer formats
+ case GlFormat::R8U: return VK_FORMAT_R8_UINT; // GL_R8UI
+ case GlFormat::RG8U: return VK_FORMAT_R8G8_UINT; // GL_RG8UI
+ case GlFormat::RGB8U: return VK_FORMAT_R8G8B8_UINT; // GL_RGB8UI
+ case GlFormat::RGBA8U: return VK_FORMAT_R8G8B8A8_UINT; // GL_RGBA8UI
+
+ case GlFormat::R16U: return VK_FORMAT_R16_UINT; // GL_R16UI
+ case GlFormat::RG16U: return VK_FORMAT_R16G16_UINT; // GL_RG16UI
+ case GlFormat::RGB16U: return VK_FORMAT_R16G16B16_UINT; // GL_RGB16UI
+ case GlFormat::RGBA16U: return VK_FORMAT_R16G16B16A16_UINT; // GL_RGBA16UI
+
+ case GlFormat::R32U: return VK_FORMAT_R32_UINT; // GL_R32UI
+ case GlFormat::RG32U: return VK_FORMAT_R32G32_UINT; // GL_RG32UI
+ case GlFormat::RGB32U: return VK_FORMAT_R32G32B32_UINT; // GL_RGB32UI
+ case GlFormat::RGBA32U: return VK_FORMAT_R32G32B32A32_UINT; // GL_RGBA32UI
+
+ // Signed integer formats
+ case GlFormat::R8I: return VK_FORMAT_R8_SINT; // GL_R8I
+ case GlFormat::RG8I: return VK_FORMAT_R8G8_SINT; // GL_RG8I
+ case GlFormat::RGB8I: return VK_FORMAT_R8G8B8_SINT; // GL_RGB8I
+ case GlFormat::RGBA8I: return VK_FORMAT_R8G8B8A8_SINT; // GL_RGBA8I
+
+ case GlFormat::R16I: return VK_FORMAT_R16_SINT; // GL_R16I
+ case GlFormat::RG16I: return VK_FORMAT_R16G16_SINT; // GL_RG16I
+ case GlFormat::RGB16I: return VK_FORMAT_R16G16B16_SINT; // GL_RGB16I
+ case GlFormat::RGBA16I: return VK_FORMAT_R16G16B16A16_SINT; // GL_RGBA16I
+
+ case GlFormat::R32I: return VK_FORMAT_R32_SINT; // GL_R32I
+ case GlFormat::RG32I: return VK_FORMAT_R32G32_SINT; // GL_RG32I
+ case GlFormat::RGB32I: return VK_FORMAT_R32G32B32_SINT; // GL_RGB32I
+ case GlFormat::RGBA32I: return VK_FORMAT_R32G32B32A32_SINT; // GL_RGBA32I
+
+ // Floating point formats
+ case GlFormat::R16F: return VK_FORMAT_R16_SFLOAT; // GL_R16F
+ case GlFormat::RG16F: return VK_FORMAT_R16G16_SFLOAT; // GL_RG16F
+ case GlFormat::RGB16F: return VK_FORMAT_R16G16B16_SFLOAT; // GL_RGB16F
+ case GlFormat::RGBA16F: return VK_FORMAT_R16G16B16A16_SFLOAT; // GL_RGBA16F
+
+ case GlFormat::R32F: return VK_FORMAT_R32_SFLOAT; // GL_R32F
+ case GlFormat::RG32F: return VK_FORMAT_R32G32_SFLOAT; // GL_RG32F
+ case GlFormat::RGB32F: return VK_FORMAT_R32G32B32_SFLOAT; // GL_RGB32F
+ case GlFormat::RGBA32F: return VK_FORMAT_R32G32B32A32_SFLOAT; // GL_RGBA32F
+
+ // Packed formats
+ case GlFormat::RGB9E5: return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; // GL_RGB9_E5
+ case GlFormat::RG11B10F: return VK_FORMAT_B10G11R11_UFLOAT_PACK32; // GL_R11F_G11F_B10F
+// case GlFormat::RG3B2: return VK_FORMAT_R3_G3_B2; // GL_R3_G3_B2
+ case GlFormat::R5G6B5: return VK_FORMAT_R5G6B5_UNORM_PACK16; // GL_RGB565
+ case GlFormat::RGB5A1: return VK_FORMAT_R5G5B5A1_UNORM_PACK16; // GL_RGB5_A1
+ case GlFormat::RGBA4: return VK_FORMAT_R4G4B4A4_UNORM_PACK16; // GL_RGBA4
+ case GlFormat::RGB10A2: return VK_FORMAT_A2R10G10B10_UINT_PACK32; // GL_RGB10_A2UI
+
+ // Depth formats
+// case Format::D16: return VK_FORMAT_DEPTH_COMPONENT16; // GL_DEPTH_COMPONENT16
+// case Format::D24: return VK_FORMAT_DEPTH_COMPONENT24; // GL_DEPTH_COMPONENT24
+// case Format::D24S8: return VK_FORMAT_DEPTH24_STENCIL8; // GL_DEPTH24_STENCIL8
+// case Format::D32: return VK_FORMAT_DEPTH_COMPONENT32; // GL_DEPTH_COMPONENT32
+// case Format::D32F: return VK_FORMAT_DEPTH_COMPONENT32F; // GL_DEPTH_COMPONENT32F
+// case Format::D32FS8X24: return VK_FORMAT_DEPTH32F_STENCIL8; // GL_DEPTH32F_STENCIL8
+// case Format::S8: return VK_FORMAT_STENCIL_INDEX8; // GL_STENCIL_INDEX8
+
+ // Compressed formats
+ case GlFormat::RGB_DXT1: return VK_FORMAT_BC1_RGB_UNORM_BLOCK; // GL_COMPRESSED_RGB_S3TC_DXT1_EXT
+ case GlFormat::RGBA_DXT1: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
+ case GlFormat::RGBA_DXT3: return VK_FORMAT_BC2_UNORM_BLOCK; // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
+ case GlFormat::RGBA_DXT5: return VK_FORMAT_BC3_UNORM_BLOCK; // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
+ case GlFormat::R_ATI1N_UNorm: return VK_FORMAT_BC4_UNORM_BLOCK; // GL_COMPRESSED_RED_RGTC1
+ case GlFormat::R_ATI1N_SNorm: return VK_FORMAT_BC4_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_RED_RGTC1
+ case GlFormat::RG_ATI2N_UNorm: return VK_FORMAT_BC5_UNORM_BLOCK; // GL_COMPRESSED_RG_RGTC2
+ case GlFormat::RG_ATI2N_SNorm: return VK_FORMAT_BC5_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_RG_RGTC2
+ case GlFormat::RGB_BP_UNSIGNED_FLOAT: return VK_FORMAT_BC6H_UFLOAT_BLOCK; // GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB
+ case GlFormat::RGB_BP_SIGNED_FLOAT: return VK_FORMAT_BC6H_SFLOAT_BLOCK; // GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB
+ case GlFormat::RGB_BP_UNorm: return VK_FORMAT_BC7_UNORM_BLOCK; // GL_COMPRESSED_RGBA_BPTC_UNORM_ARB
+ case GlFormat::R11_EAC_UNorm: return VK_FORMAT_EAC_R11_UNORM_BLOCK; // GL_COMPRESSED_R11_EAC
+ case GlFormat::R11_EAC_SNorm: return VK_FORMAT_EAC_R11_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_R11_EAC
+ case GlFormat::RG11_EAC_UNorm: return VK_FORMAT_EAC_R11G11_UNORM_BLOCK; // GL_COMPRESSED_RG11_EAC
+ case GlFormat::RG11_EAC_SNorm: return VK_FORMAT_EAC_R11G11_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_RG11_EAC
+ case GlFormat::RGB8_ETC2: return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; // GL_COMPRESSED_RGB8_ETC2
+ case GlFormat::SRGB8_ETC2: return VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ETC2
+ case GlFormat::RGB8_PunchThrough_Alpha1_ETC2: return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ case GlFormat::SRGB8_PunchThrough_Alpha1_ETC2: return VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ case GlFormat::RGBA8_ETC2_EAC: return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; // GL_COMPRESSED_RGBA8_ETC2_EAC
+ case GlFormat::SRGB8_Alpha8_ETC2_EAC: return VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
+// case GlFormat::RGB8_ETC1: return VK_FORMAT_ETC1_RGB8_OES; // GL_ETC1_RGB8_OES
+ case GlFormat::RGBA_ASTC_4x4: return VK_FORMAT_ASTC_4x4_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_4x4_KHR
+ case GlFormat::RGBA_ASTC_5x4: return VK_FORMAT_ASTC_5x4_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_5x4_KHR
+ case GlFormat::RGBA_ASTC_5x5: return VK_FORMAT_ASTC_5x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_5x5_KHR
+ case GlFormat::RGBA_ASTC_6x5: return VK_FORMAT_ASTC_6x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_6x5_KHR
+ case GlFormat::RGBA_ASTC_6x6: return VK_FORMAT_ASTC_6x6_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_6x6_KHR
+ case GlFormat::RGBA_ASTC_8x5: return VK_FORMAT_ASTC_8x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_8x5_KHR
+ case GlFormat::RGBA_ASTC_8x6: return VK_FORMAT_ASTC_8x6_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_8x6_KHR
+ case GlFormat::RGBA_ASTC_8x8: return VK_FORMAT_ASTC_8x8_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_8x8_KHR
+ case GlFormat::RGBA_ASTC_10x5: return VK_FORMAT_ASTC_10x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x5_KHR
+ case GlFormat::RGBA_ASTC_10x6: return VK_FORMAT_ASTC_10x6_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x6_KHR
+ case GlFormat::RGBA_ASTC_10x8: return VK_FORMAT_ASTC_10x8_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x8_KHR
+ case GlFormat::RGBA_ASTC_10x10: return VK_FORMAT_ASTC_10x10_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x10_KHR
+ case GlFormat::RGBA_ASTC_12x10: return VK_FORMAT_ASTC_12x10_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_12x10_KHR
+ case GlFormat::RGBA_ASTC_12x12: return VK_FORMAT_ASTC_12x12_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_12x12_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_4x4: return VK_FORMAT_ASTC_4x4_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_5x4: return VK_FORMAT_ASTC_5x4_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_5x5: return VK_FORMAT_ASTC_5x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_6x5: return VK_FORMAT_ASTC_6x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_6x6: return VK_FORMAT_ASTC_6x6_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_8x5: return VK_FORMAT_ASTC_8x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_8x6: return VK_FORMAT_ASTC_8x6_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_8x8: return VK_FORMAT_ASTC_8x8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_10x5: return VK_FORMAT_ASTC_10x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_10x6: return VK_FORMAT_ASTC_10x6_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_10x8: return VK_FORMAT_ASTC_10x8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_10x10: return VK_FORMAT_ASTC_10x10_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_12x10: return VK_FORMAT_ASTC_12x10_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
+ case GlFormat::SRGB8_Alpha8_ASTC_12x12: return VK_FORMAT_ASTC_12x12_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
+
+ // sRGB formats
+ case GlFormat::SRGB8: return VK_FORMAT_R8G8B8_SRGB; // GL_SRGB8
+ case GlFormat::SRGB8_Alpha8: return VK_FORMAT_R8G8B8A8_SRGB; // GL_SRGB8_ALPHA8
+ case GlFormat::SRGB_DXT1: return VK_FORMAT_BC1_RGB_SRGB_BLOCK; // GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
+ case GlFormat::SRGB_Alpha_DXT1: return VK_FORMAT_BC1_RGBA_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
+ case GlFormat::SRGB_Alpha_DXT3: return VK_FORMAT_BC2_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
+ case GlFormat::SRGB_Alpha_DXT5: return VK_FORMAT_BC3_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
+ case GlFormat::SRGB_BP_UNorm: return VK_FORMAT_BC7_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB
+
+ // ES 2 formats
+// case GlFormat::DepthFormat: return VK_FORMAT_DEPTH_COMPONENT; // GL_DEPTH_COMPONENT
+// case GlFormat::AlphaFormat: return VK_FORMAT_ALPHA; // GL_ALPHA
+// case GlFormat::RGBFormat: return VK_FORMAT_RGB; // GL_RGB
+// case GlFormat::RGBAFormat: return VK_FORMAT_RGBA; // GL_RGBA
+// case GlFormat::LuminanceFormat: return VK_FORMAT_LUMINANCE; // GL_LUMINANCE
+// case GlFormat::LuminanceAlphaFormat: return VK_FORMAT;
+ default: return VK_FORMAT_UNDEFINED;
+ }
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/mirclient/qmirclientappstatecontroller.h b/src/platformsupport/vkconvenience/qvkconvenience_p.h
index b3aa0022d9..580271b593 100644
--- a/src/plugins/platforms/mirclient/qmirclientappstatecontroller.h
+++ b/src/platformsupport/vkconvenience/qvkconvenience_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -37,26 +37,33 @@
**
****************************************************************************/
+#ifndef QVKCONVENIENCE_P_H
+#define QVKCONVENIENCE_P_H
-#ifndef QMIRCLIENTAPPSTATECONTROLLER_H
-#define QMIRCLIENTAPPSTATECONTROLLER_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
-#include <QTimer>
+#include <QtCore/qglobal.h>
+#include <qvulkaninstance.h>
-class QMirClientAppStateController
+QT_BEGIN_NAMESPACE
+
+class QVkConvenience
{
public:
- QMirClientAppStateController();
-
- void setSuspended();
- void setResumed();
-
- void setWindowFocused(bool focused);
-
-private:
- bool m_suspended;
- bool m_lastActive;
- QTimer m_inactiveTimer;
+#if QT_CONFIG(opengl)
+ static VkFormat vkFormatFromGlFormat(uint glFormat);
+#endif
};
-#endif // QMIRCLIENTAPPSTATECONTROLLER_H
+QT_END_NAMESPACE
+
+#endif // QVKCONVENIENCE_P_H
diff --git a/src/platformsupport/vkconvenience/vkconvenience.pro b/src/platformsupport/vkconvenience/vkconvenience.pro
index 7a4cdb041d..ee540024cf 100644
--- a/src/platformsupport/vkconvenience/vkconvenience.pro
+++ b/src/platformsupport/vkconvenience/vkconvenience.pro
@@ -8,9 +8,11 @@ DEFINES += QT_NO_CAST_FROM_ASCII
PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
SOURCES += \
+ qvkconvenience.cpp \
qbasicvulkanplatforminstance.cpp
HEADERS += \
+ qvkconvenience_p.h \
qbasicvulkanplatforminstance_p.h
load(qt_module)
diff --git a/src/plugins/bearer/connman/qconnmanengine.h b/src/plugins/bearer/connman/qconnmanengine.h
index c9ff17f801..ef80d38fa2 100644
--- a/src/plugins/bearer/connman/qconnmanengine.h
+++ b/src/plugins/bearer/connman/qconnmanengine.h
@@ -68,7 +68,7 @@ class QConnmanEngine : public QBearerEngineImpl
Q_OBJECT
public:
- QConnmanEngine(QObject *parent = 0);
+ QConnmanEngine(QObject *parent = nullptr);
~QConnmanEngine();
bool connmanAvailable() const;
diff --git a/src/plugins/bearer/connman/qconnmanservice_linux_p.h b/src/plugins/bearer/connman/qconnmanservice_linux_p.h
index d2804ebca6..790325f9a1 100644
--- a/src/plugins/bearer/connman/qconnmanservice_linux_p.h
+++ b/src/plugins/bearer/connman/qconnmanservice_linux_p.h
@@ -105,7 +105,7 @@ class QConnmanManagerInterface : public QDBusAbstractInterface
public:
- QConnmanManagerInterface( QObject *parent = 0);
+ QConnmanManagerInterface( QObject *parent = nullptr);
~QConnmanManagerInterface();
QDBusObjectPath path() const;
@@ -155,7 +155,7 @@ class QConnmanServiceInterface : public QDBusAbstractInterface
public:
- explicit QConnmanServiceInterface(const QString &dbusPathName,QObject *parent = 0);
+ explicit QConnmanServiceInterface(const QString &dbusPathName,QObject *parent = nullptr);
~QConnmanServiceInterface();
QVariantMap getProperties();
@@ -202,7 +202,7 @@ class QConnmanTechnologyInterface : public QDBusAbstractInterface
public:
- explicit QConnmanTechnologyInterface(const QString &dbusPathName,QObject *parent = 0);
+ explicit QConnmanTechnologyInterface(const QString &dbusPathName,QObject *parent = nullptr);
~QConnmanTechnologyInterface();
QString type();
diff --git a/src/plugins/bearer/generic/qgenericengine.h b/src/plugins/bearer/generic/qgenericengine.h
index 08960d66f6..79c71ca7a3 100644
--- a/src/plugins/bearer/generic/qgenericengine.h
+++ b/src/plugins/bearer/generic/qgenericengine.h
@@ -55,7 +55,7 @@ class QGenericEngine : public QBearerEngineImpl
Q_OBJECT
public:
- QGenericEngine(QObject *parent = 0);
+ QGenericEngine(QObject *parent = nullptr);
~QGenericEngine();
QString getInterfaceFromId(const QString &id) override;
diff --git a/src/plugins/bearer/linux_common/qofonoservice_linux_p.h b/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
index 35614a20f2..62df5d4fa7 100644
--- a/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
+++ b/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
@@ -100,7 +100,7 @@ class QOfonoManagerInterface : public QDBusAbstractInterface
public:
- QOfonoManagerInterface( QObject *parent = 0);
+ QOfonoManagerInterface( QObject *parent = nullptr);
~QOfonoManagerInterface();
QStringList getModems();
@@ -120,7 +120,7 @@ class QOfonoModemInterface : public QDBusAbstractInterface
public:
- explicit QOfonoModemInterface(const QString &dbusModemPathName, QObject *parent = 0);
+ explicit QOfonoModemInterface(const QString &dbusModemPathName, QObject *parent = nullptr);
~QOfonoModemInterface();
bool isPowered();
@@ -140,7 +140,7 @@ class QOfonoNetworkRegistrationInterface : public QDBusAbstractInterface
public:
- explicit QOfonoNetworkRegistrationInterface(const QString &dbusModemPathName, QObject *parent = 0);
+ explicit QOfonoNetworkRegistrationInterface(const QString &dbusModemPathName, QObject *parent = nullptr);
~QOfonoNetworkRegistrationInterface();
QString getTechnology();
@@ -159,7 +159,7 @@ class QOfonoDataConnectionManagerInterface : public QDBusAbstractInterface
public:
- explicit QOfonoDataConnectionManagerInterface(const QString &dbusPathName, QObject *parent = 0);
+ explicit QOfonoDataConnectionManagerInterface(const QString &dbusPathName, QObject *parent = nullptr);
~QOfonoDataConnectionManagerInterface();
QStringList contexts();
@@ -184,7 +184,7 @@ class QOfonoConnectionContextInterface : public QDBusAbstractInterface
public:
- explicit QOfonoConnectionContextInterface(const QString &dbusPathName, QObject *parent = 0);
+ explicit QOfonoConnectionContextInterface(const QString &dbusPathName, QObject *parent = nullptr);
~QOfonoConnectionContextInterface();
QVariant getProperty(const QString &);
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
index 543e66491d..e74b1cf744 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
@@ -465,7 +465,7 @@ void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path,
cpPriv->state |= QNetworkConfiguration::Active;
if (deviceType == DEVICE_TYPE_ETHERNET) {
- for (const auto *interfaceDevice : interfaceDevices) {
+ for (auto interfaceDevice : qAsConst(interfaceDevices)) {
if (interfaceDevice->deviceType() == deviceType) {
auto *wiredDevice = wiredDevices.value(interfaceDevice->path());
if (wiredDevice && wiredDevice->carrier()) {
@@ -716,7 +716,7 @@ QNetworkSession::State QNetworkManagerEngine::sessionStateForId(const QString &i
if (!ptr->isValid)
return QNetworkSession::Invalid;
- for (QNetworkManagerConnectionActive *activeConnection : activeConnectionsList) {
+ for (QNetworkManagerConnectionActive *activeConnection : qAsConst(activeConnectionsList)) {
const QString identifier = activeConnection->connection().path();
if (id == identifier) {
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
index 74fe24b5ab..a95c68abdf 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
@@ -69,7 +69,7 @@ class QNetworkManagerEngine : public QBearerEngineImpl
Q_OBJECT
public:
- QNetworkManagerEngine(QObject *parent = 0);
+ QNetworkManagerEngine(QObject *parent = nullptr);
~QNetworkManagerEngine();
bool networkManagerAvailable() const;
@@ -99,7 +99,7 @@ private Q_SLOTS:
void interfacePropertiesChanged(const QMap<QString, QVariant> &properties);
void activeConnectionPropertiesChanged(const QMap<QString, QVariant> &properties);
- void newConnection(const QDBusObjectPath &path, QNetworkManagerSettings *settings = 0);
+ void newConnection(const QDBusObjectPath &path, QNetworkManagerSettings *settings = nullptr);
void removeConnection(const QString &path);
void updateConnection();
void activationFinished(QDBusPendingCallWatcher *watcher);
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
index 3e77580015..35199eb7a2 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
@@ -72,11 +72,9 @@ QNetworkManagerInterface::QNetworkManagerInterface(QObject *parent)
QLatin1String(NM_DBUS_PATH),
DBUS_PROPERTIES_INTERFACE,
QDBusConnection::systemBus());
- QList<QVariant> argumentList;
- argumentList << QLatin1String(NM_DBUS_INTERFACE);
QDBusPendingReply<QVariantMap> propsReply
- = managerPropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"),
- argumentList);
+ = managerPropertiesInterface.call(QDBus::Block, QLatin1String("GetAll"), QLatin1String(NM_DBUS_INTERFACE));
+
if (!propsReply.isError()) {
propertyMap = propsReply.value();
} else {
@@ -344,11 +342,8 @@ QNetworkManagerInterfaceDevice::QNetworkManagerInterfaceDevice(const QString &de
DBUS_PROPERTIES_INTERFACE,
QDBusConnection::systemBus(),parent);
- QList<QVariant> argumentList;
- argumentList << QLatin1String(NM_DBUS_INTERFACE_DEVICE);
QDBusPendingReply<QVariantMap> propsReply
- = devicePropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"),
- argumentList);
+ = devicePropertiesInterface.call(QDBus::Block, QLatin1String("GetAll"), QLatin1String(NM_DBUS_INTERFACE_DEVICE));
if (!propsReply.isError()) {
propertyMap = propsReply.value();
@@ -446,11 +441,8 @@ QNetworkManagerInterfaceDeviceWired::QNetworkManagerInterfaceDeviceWired(const Q
DBUS_PROPERTIES_INTERFACE,
QDBusConnection::systemBus(),parent);
- QList<QVariant> argumentList;
- argumentList << QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRED);
QDBusPendingReply<QVariantMap> propsReply
- = deviceWiredPropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"),
- argumentList);
+ = deviceWiredPropertiesInterface.call(QDBus::Block, QLatin1String("GetAll"), QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRED));
if (!propsReply.isError()) {
propertyMap = propsReply.value();
@@ -543,11 +535,9 @@ QNetworkManagerInterfaceDeviceWireless::QNetworkManagerInterfaceDeviceWireless(c
DBUS_PROPERTIES_INTERFACE,
QDBusConnection::systemBus(),parent);
- QList<QVariant> argumentList;
- argumentList << QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS);
QDBusPendingReply<QVariantMap> propsReply
- = deviceWirelessPropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"),
- argumentList);
+ = deviceWirelessPropertiesInterface.call(QDBus::Block, QLatin1String("GetAll"), QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS));
+
if (!propsReply.isError()) {
propertyMap = propsReply.value();
}
@@ -647,11 +637,9 @@ QNetworkManagerInterfaceDeviceModem::QNetworkManagerInterfaceDeviceModem(const Q
QLatin1String("org.freedesktop.DBus.Properties"),
QDBusConnection::systemBus(),parent);
- QList<QVariant> argumentList;
- argumentList << QLatin1String(NM_DBUS_INTERFACE_DEVICE_MODEM);
QDBusPendingReply<QVariantMap> propsReply
- = deviceModemPropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"),
- argumentList);
+ = deviceModemPropertiesInterface.call(QDBus::Block, QLatin1String("GetAll"), QLatin1String(NM_DBUS_INTERFACE_DEVICE_MODEM));
+
if (!propsReply.isError()) {
propertyMap = propsReply.value();
}
@@ -746,9 +734,7 @@ QList <QDBusObjectPath> QNetworkManagerSettings::listConnections()
QString QNetworkManagerSettings::getConnectionByUuid(const QString &uuid)
{
- QList<QVariant> argumentList;
- argumentList << QVariant::fromValue(uuid);
- QDBusReply<QDBusObjectPath > reply = callWithArgumentList(QDBus::Block,QLatin1String("GetConnectionByUuid"), argumentList);
+ QDBusReply<QDBusObjectPath > reply = call(QDBus::Block, QLatin1String("GetConnectionByUuid"), uuid);
return reply.value().path();
}
@@ -917,11 +903,8 @@ QNetworkManagerConnectionActive::QNetworkManagerConnectionActive(const QString &
QDBusConnection::systemBus());
- QList<QVariant> argumentList;
- argumentList << QLatin1String(NM_DBUS_INTERFACE_ACTIVE_CONNECTION);
QDBusPendingReply<QVariantMap> propsReply
- = connectionActivePropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"),
- argumentList);
+ = connectionActivePropertiesInterface.call(QDBus::Block, QLatin1String("GetAll"), QLatin1String(NM_DBUS_INTERFACE_ACTIVE_CONNECTION));
if (!propsReply.isError()) {
propertyMap = propsReply.value();
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
index c879083faf..bff7a71097 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
@@ -152,7 +152,7 @@ public:
NM_STATE_CONNECTED_GLOBAL = 70
} NMState;
- QNetworkManagerInterface(QObject *parent = 0);
+ QNetworkManagerInterface(QObject *parent = nullptr);
~QNetworkManagerInterface();
QList <QDBusObjectPath> getDevices();
@@ -228,7 +228,7 @@ public:
Q_DECLARE_FLAGS(ApSecurityFlags, ApSecurityFlag)
- explicit QNetworkManagerInterfaceAccessPoint(const QString &dbusPathName, QObject *parent = 0);
+ explicit QNetworkManagerInterfaceAccessPoint(const QString &dbusPathName, QObject *parent = nullptr);
~QNetworkManagerInterfaceAccessPoint();
quint32 flags() const;
@@ -259,7 +259,7 @@ class QNetworkManagerInterfaceDevice : public QDBusAbstractInterface
public:
- explicit QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent = 0);
+ explicit QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent = nullptr);
~QNetworkManagerInterfaceDevice();
QString udi() const;
@@ -288,7 +288,7 @@ class QNetworkManagerInterfaceDeviceWired : public QDBusAbstractInterface
public:
explicit QNetworkManagerInterfaceDeviceWired(const QString &ifaceDevicePath,
- QObject *parent = 0);
+ QObject *parent = nullptr);
~QNetworkManagerInterfaceDeviceWired();
QString hwAddress() const;
@@ -325,7 +325,7 @@ public:
};
explicit QNetworkManagerInterfaceDeviceWireless(const QString &ifaceDevicePath,
- QObject *parent = 0);
+ QObject *parent = nullptr);
~QNetworkManagerInterfaceDeviceWireless();
QList <QDBusObjectPath> getAccessPoints();
@@ -367,7 +367,7 @@ public:
Q_DECLARE_FLAGS(ModemCapabilities, ModemCapability)
explicit QNetworkManagerInterfaceDeviceModem(const QString &ifaceDevicePath,
- QObject *parent = 0);
+ QObject *parent = nullptr);
~QNetworkManagerInterfaceDeviceModem();
ModemCapabilities modemCapabilities() const;
@@ -392,7 +392,7 @@ class QNetworkManagerSettings : public QDBusAbstractInterface
public:
- explicit QNetworkManagerSettings(const QString &settingsService, QObject *parent = 0);
+ explicit QNetworkManagerSettings(const QString &settingsService, QObject *parent = nullptr);
~QNetworkManagerSettings();
QList <QDBusObjectPath> listConnections();
@@ -413,7 +413,7 @@ class QNetworkManagerSettingsConnection : public QDBusAbstractInterface
public:
- QNetworkManagerSettingsConnection(const QString &settingsService, const QString &connectionObjectPath, QObject *parent = 0);
+ QNetworkManagerSettingsConnection(const QString &settingsService, const QString &connectionObjectPath, QObject *parent = nullptr);
~QNetworkManagerSettingsConnection();
QNmSettingsMap getSettings();
@@ -451,7 +451,7 @@ public:
Activated = 2
};
- explicit QNetworkManagerConnectionActive(const QString &dbusPathName, QObject *parent = 0);
+ explicit QNetworkManagerConnectionActive(const QString &dbusPathName, QObject *parent = nullptr);
~ QNetworkManagerConnectionActive();
QDBusObjectPath connection() const;
@@ -478,7 +478,7 @@ class QNetworkManagerIp4Config : public QDBusAbstractInterface
Q_OBJECT
public:
- explicit QNetworkManagerIp4Config(const QString &dbusPathName, QObject *parent = 0);
+ explicit QNetworkManagerIp4Config(const QString &dbusPathName, QObject *parent = nullptr);
~QNetworkManagerIp4Config();
QStringList domains() const;
@@ -489,7 +489,7 @@ class PropertiesDBusInterface : public QDBusAbstractInterface
public:
PropertiesDBusInterface(const QString &service, const QString &path,
const QString &interface, const QDBusConnection &connection,
- QObject *parent = 0)
+ QObject *parent = nullptr)
: QDBusAbstractInterface(service, path, interface.toLatin1().data(), connection, parent)
{}
};
diff --git a/src/plugins/bearer/nla/nla.pro b/src/plugins/bearer/nla/nla.pro
index 113d0667d2..76f3279d25 100644
--- a/src/plugins/bearer/nla/nla.pro
+++ b/src/plugins/bearer/nla/nla.pro
@@ -2,7 +2,7 @@ TARGET = qnlabearer
QT = core core-private network network-private
-LIBS += -lws2_32
+QMAKE_USE_PRIVATE += ws2_32
HEADERS += qnlaengine.h \
../platformdefs_win.h \
diff --git a/src/plugins/bearer/nla/qnlaengine.cpp b/src/plugins/bearer/nla/qnlaengine.cpp
index 726e1efb92..e1e60389f1 100644
--- a/src/plugins/bearer/nla/qnlaengine.cpp
+++ b/src/plugins/bearer/nla/qnlaengine.cpp
@@ -75,38 +75,38 @@ QWindowsSockInit2::~QWindowsSockInit2()
#ifdef BEARER_MANAGEMENT_DEBUG
static void printBlob(NLA_BLOB *blob)
{
- qDebug() << "==== BEGIN NLA_BLOB ====" << endl
+ qDebug() << "==== BEGIN NLA_BLOB ====" << Qt::endl
- << "type:" << blob->header.type << endl
- << "size:" << blob->header.dwSize << endl
+ << "type:" << blob->header.type << Qt::endl
+ << "size:" << blob->header.dwSize << Qt::endl
<< "next offset:" << blob->header.nextOffset;
switch (blob->header.type) {
case NLA_RAW_DATA:
- qDebug() << "Raw Data" << endl
+ qDebug() << "Raw Data" << Qt::endl
<< '\t' << blob->data.rawData;
break;
case NLA_INTERFACE:
- qDebug() << "Interface" << endl
- << "\ttype:" << blob->data.interfaceData.dwType << endl
- << "\tspeed:" << blob->data.interfaceData.dwSpeed << endl
+ qDebug() << "Interface" << Qt::endl
+ << "\ttype:" << blob->data.interfaceData.dwType << Qt::endl
+ << "\tspeed:" << blob->data.interfaceData.dwSpeed << Qt::endl
<< "\tadapter:" << blob->data.interfaceData.adapterName;
break;
case NLA_802_1X_LOCATION:
- qDebug() << "802.1x Location" << endl
+ qDebug() << "802.1x Location" << Qt::endl
<< '\t' << blob->data.locationData.information;
break;
case NLA_CONNECTIVITY:
- qDebug() << "Connectivity" << endl
- << "\ttype:" << blob->data.connectivity.type << endl
+ qDebug() << "Connectivity" << Qt::endl
+ << "\ttype:" << blob->data.connectivity.type << Qt::endl
<< "\tinternet:" << blob->data.connectivity.internet;
break;
case NLA_ICS:
- qDebug() << "ICS" << endl
- << "\tspeed:" << blob->data.ICS.remote.speed << endl
- << "\ttype:" << blob->data.ICS.remote.type << endl
- << "\tstate:" << blob->data.ICS.remote.state << endl
- << "\tmachine name:" << blob->data.ICS.remote.machineName << endl
+ qDebug() << "ICS" << Qt::endl
+ << "\tspeed:" << blob->data.ICS.remote.speed << Qt::endl
+ << "\ttype:" << blob->data.ICS.remote.type << Qt::endl
+ << "\tstate:" << blob->data.ICS.remote.state << Qt::endl
+ << "\tmachine name:" << blob->data.ICS.remote.machineName << Qt::endl
<< "\tshared adapter name:" << blob->data.ICS.remote.sharedAdapterName;
break;
default:
@@ -119,9 +119,6 @@ static void printBlob(NLA_BLOB *blob)
static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interface)
{
-#ifdef Q_OS_WINCE
- Q_UNUSED(interface)
-#else
unsigned long oid;
DWORD bytesWritten;
@@ -177,8 +174,6 @@ static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interf
qDebug() << medium << physicalMedium;
#endif
-#endif
-
return QNetworkConfiguration::BearerUnknown;
}
@@ -307,16 +302,12 @@ void QNlaThread::run()
break;
}
-#ifndef Q_OS_WINCE
// Not interested in unrelated IO completion events
// although we also don't want to block them
while (WaitForSingleObjectEx(changeEvent, WSA_INFINITE, true) != WAIT_IO_COMPLETION &&
handle)
{
}
-#else
- WaitForSingleObject(changeEvent, WSA_INFINITE);
-#endif
mutex.lock();
if (handle) {
diff --git a/src/plugins/bearer/qbearerengine_impl.h b/src/plugins/bearer/qbearerengine_impl.h
index 3f8a4d821d..5c003aaaf6 100644
--- a/src/plugins/bearer/qbearerengine_impl.h
+++ b/src/plugins/bearer/qbearerengine_impl.h
@@ -56,7 +56,7 @@ public:
DisconnectionError,
};
- QBearerEngineImpl(QObject *parent = 0) : QBearerEngine(parent) {}
+ QBearerEngineImpl(QObject *parent = nullptr) : QBearerEngine(parent) {}
~QBearerEngineImpl() {}
virtual void connectToId(const QString &id) = 0;
diff --git a/src/plugins/bearer/qnetworksession_impl.cpp b/src/plugins/bearer/qnetworksession_impl.cpp
index 903525a204..c6b678ab20 100644
--- a/src/plugins/bearer/qnetworksession_impl.cpp
+++ b/src/plugins/bearer/qnetworksession_impl.cpp
@@ -83,8 +83,6 @@ Q_SIGNALS:
void forcedSessionClose(const QNetworkConfiguration &config);
};
-#include "qnetworksession_impl.moc"
-
Q_GLOBAL_STATIC(QNetworkSessionManagerPrivate, sessionManager);
void QNetworkSessionPrivateImpl::syncStateWithInterface()
@@ -433,3 +431,5 @@ void QNetworkSessionPrivateImpl::decrementTimeout()
}
QT_END_NAMESPACE
+
+#include "qnetworksession_impl.moc"
diff --git a/src/plugins/bearer/qnetworksession_impl.h b/src/plugins/bearer/qnetworksession_impl.h
index d9aa6ca8fb..0f8e014900 100644
--- a/src/plugins/bearer/qnetworksession_impl.h
+++ b/src/plugins/bearer/qnetworksession_impl.h
@@ -66,7 +66,7 @@ class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate
public:
QNetworkSessionPrivateImpl()
- : engine(0), startTime(0), lastError(QNetworkSession::UnknownSessionError), sessionTimeout(-1), currentPolicies(QNetworkSession::NoPolicy), opened(false)
+ : engine(nullptr), startTime(0), lastError(QNetworkSession::UnknownSessionError), sessionTimeout(-1), currentPolicies(QNetworkSession::NoPolicy), opened(false)
{}
~QNetworkSessionPrivateImpl()
{}
diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp
index bb18ba5085..cb82672acd 100644
--- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp
+++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp
@@ -169,7 +169,7 @@ void QTuioHandler::processPackets()
messages.push_back(msg);
}
- for (const QOscMessage &message : messages) {
+ for (const QOscMessage &message : qAsConst(messages)) {
if (message.addressPattern() == "/tuio/2Dcur") {
QList<QVariant> arguments = message.arguments();
if (arguments.count() == 0) {
@@ -368,12 +368,12 @@ void QTuioHandler::process2DCurFseq(const QOscMessage &message)
QList<QWindowSystemInterface::TouchPoint> tpl;
tpl.reserve(m_activeCursors.size() + m_deadCursors.size());
- for (const QTuioCursor &tc : m_activeCursors) {
+ for (const QTuioCursor &tc : qAsConst(m_activeCursors)) {
QWindowSystemInterface::TouchPoint tp = cursorToTouchPoint(tc, win);
tpl.append(tp);
}
- for (const QTuioCursor &tc : m_deadCursors) {
+ for (const QTuioCursor &tc : qAsConst(m_deadCursors)) {
QWindowSystemInterface::TouchPoint tp = cursorToTouchPoint(tc, win);
tp.state = Qt::TouchPointReleased;
tpl.append(tp);
@@ -542,12 +542,12 @@ void QTuioHandler::process2DObjFseq(const QOscMessage &message)
QList<QWindowSystemInterface::TouchPoint> tpl;
tpl.reserve(m_activeTokens.size() + m_deadTokens.size());
- for (const QTuioToken & t : m_activeTokens) {
+ for (const QTuioToken & t : qAsConst(m_activeTokens)) {
QWindowSystemInterface::TouchPoint tp = tokenToTouchPoint(t, win);
tpl.append(tp);
}
- for (const QTuioToken & t : m_deadTokens) {
+ for (const QTuioToken & t : qAsConst(m_deadTokens)) {
QWindowSystemInterface::TouchPoint tp = tokenToTouchPoint(t, win);
tp.state = Qt::TouchPointReleased;
tp.velocity = QVector2D();
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
index 54fe857908..9d5ccc8a3d 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp
+++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
@@ -40,10 +40,14 @@
#include "qjpeghandler_p.h"
#include <qimage.h>
+#include <qcolorspace.h>
+#include <qcolortransform.h>
+#include <qdebug.h>
#include <qvariant.h>
#include <qvector.h>
#include <qbuffer.h>
#include <qmath.h>
+#include <private/qicc_p.h>
#include <private/qsimd_p.h>
#include <private/qimage_p.h> // for qt_getImageText
@@ -725,6 +729,7 @@ public:
QRect clipRect;
QString description;
QStringList readTexts;
+ QByteArray iccProfile;
struct jpeg_decompress_struct info;
struct my_jpeg_source_mgr * iod_src;
@@ -887,6 +892,7 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
if (!setjmp(err.setjmp_buffer)) {
jpeg_save_markers(&info, JPEG_COM, 0xFFFF);
jpeg_save_markers(&info, JPEG_APP0 + 1, 0xFFFF); // Exif uses APP1 marker
+ jpeg_save_markers(&info, JPEG_APP0 + 2, 0xFFFF); // ICC uses APP2 marker
(void) jpeg_read_header(&info, TRUE);
@@ -919,6 +925,10 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
readTexts.append(value);
} else if (marker->marker == JPEG_APP0 + 1) {
exifData.append((const char*)marker->data, marker->data_length);
+ } else if (marker->marker == JPEG_APP0 + 2) {
+ if (marker->data_length > 128 + 4 + 14 && strcmp((const char *)marker->data, "ICC_PROFILE") == 0) {
+ iccProfile.append((const char*)marker->data + 14, marker->data_length - 14);
+ }
}
}
@@ -954,6 +964,9 @@ bool QJpegHandlerPrivate::read(QImage *image)
for (int i = 0; i < readTexts.size()-1; i+=2)
image->setText(readTexts.at(i), readTexts.at(i+1));
+ if (!iccProfile.isEmpty())
+ image->setColorSpace(QColorSpace::fromIccProfile(iccProfile));
+
state = ReadingEnd;
return true;
}
@@ -962,7 +975,6 @@ bool QJpegHandlerPrivate::read(QImage *image)
}
return false;
-
}
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, const uchar *src, int len);
diff --git a/src/plugins/platforminputcontexts/compose/compose.pro b/src/plugins/platforminputcontexts/compose/compose.pro
index 68bc2c3466..2e2f8600c3 100644
--- a/src/plugins/platforminputcontexts/compose/compose.pro
+++ b/src/plugins/platforminputcontexts/compose/compose.pro
@@ -3,18 +3,14 @@ TARGET = composeplatforminputcontextplugin
QT += core-private gui-private
SOURCES += $$PWD/qcomposeplatforminputcontextmain.cpp \
- $$PWD/qcomposeplatforminputcontext.cpp \
- $$PWD/generator/qtablegenerator.cpp \
+ $$PWD/qcomposeplatforminputcontext.cpp
-HEADERS += $$PWD/qcomposeplatforminputcontext.h \
- $$PWD/generator/qtablegenerator.h \
+HEADERS += $$PWD/qcomposeplatforminputcontext.h
QMAKE_USE_PRIVATE += xkbcommon
include($$OUT_PWD/../../../gui/qtgui-config.pri)
-DEFINES += X11_PREFIX='\\"$$QMAKE_X11_PREFIX\\"'
-
OTHER_FILES += $$PWD/compose.json
PLUGIN_TYPE = platforminputcontexts
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
deleted file mode 100644
index b5a0a5bbeb..0000000000
--- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
+++ /dev/null
@@ -1,658 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qtablegenerator.h"
-
-#include <QtCore/QByteArray>
-#include <QtCore/QTextCodec>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtCore/QStringList>
-#include <QtCore/QString>
-#include <QtCore/QSaveFile>
-#include <QtCore/QStandardPaths>
-#include <private/qcore_unix_p.h>
-
-#include <algorithm>
-
-#include <xkbcommon/xkbcommon.h>
-
-#include <locale.h> // LC_CTYPE
-#include <string.h> // strchr, strncmp, etc.
-#include <strings.h> // strncasecmp
-#include <clocale> // LC_CTYPE
-
-static const quint32 SupportedCacheVersion = 1;
-
-/*
- In short on how and why the "Compose" file is cached:
-
- The "Compose" file is large, for en_US it's likely located at:
- /usr/share/X11/locale/en_US.UTF-8/Compose
- and it has about 6000 string lines.
- Q(Gui)Applications parse this file each time they're created. On modern CPUs
- it incurs a 4-10 ms startup penalty of each Qt gui app, on older CPUs -
- tens of ms or more.
- Since the "Compose" file (almost) never changes using a pre-parsed
- cache file instead of the "Compose" file is a good idea to improve Qt5
- application startup time by about 5+ ms (or tens of ms on older CPUs).
-
- The cache file contains the contents of the QComposeCacheFileHeader struct at the
- beginning followed by the pre-parsed contents of the "Compose" file.
-
- struct QComposeCacheFileHeader stores
- (a) The cache version - in the unlikely event that some day one might need
- to break compatibility.
- (b) The (cache) file size.
- (c) The lastModified field tracks if anything changed since the last time
- the cache file was saved.
- If anything did change then we read the compose file and save (cache) it
- in binary/pre-parsed format, which should happen extremely rarely if at all.
-*/
-
-struct QComposeCacheFileHeader
-{
- quint32 cacheVersion;
- // The compiler will add 4 padding bytes anyway.
- // Reserve them explicitly to possibly use in the future.
- quint32 reserved;
- quint64 fileSize;
- qint64 lastModified;
-};
-
-// localHostName() copied from qtbase/src/corelib/io/qlockfile_unix.cpp
-static QByteArray localHostName()
-{
- QByteArray hostName(512, Qt::Uninitialized);
- if (gethostname(hostName.data(), hostName.size()) == -1)
- return QByteArray();
- hostName.truncate(strlen(hostName.data()));
- return hostName;
-}
-
-/*
- Reads metadata about the Compose file. Later used to determine if the
- compose cache should be updated. The fileSize field will be zero on failure.
-*/
-static QComposeCacheFileHeader readFileMetadata(const QString &path)
-{
- quint64 fileSize = 0;
- qint64 lastModified = 0;
- const QByteArray pathBytes = QFile::encodeName(path);
- QT_STATBUF st;
- if (QT_STAT(pathBytes.data(), &st) == 0) {
- lastModified = st.st_mtime;
- fileSize = st.st_size;
- }
- QComposeCacheFileHeader info = { 0, 0, fileSize, lastModified };
- return info;
-}
-
-static const QString getCacheFilePath()
-{
- QFile machineIdFile("/var/lib/dbus/machine-id");
- QString machineId;
- if (machineIdFile.exists()) {
- if (machineIdFile.open(QIODevice::ReadOnly))
- machineId = QString::fromLatin1(machineIdFile.readAll().trimmed());
- }
- if (machineId.isEmpty())
- machineId = localHostName();
- const QString dirPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
-
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
- return dirPath + QLatin1String("/qt_compose_cache_big_endian_") + machineId;
- return dirPath + QLatin1String("/qt_compose_cache_little_endian_") + machineId;
-}
-
-// Returns empty vector on failure
-static QVector<QComposeTableElement> loadCache(const QComposeCacheFileHeader &composeInfo)
-{
- QVector<QComposeTableElement> vec;
- const QString cacheFilePath = getCacheFilePath();
- QFile inputFile(cacheFilePath);
-
- if (!inputFile.open(QIODevice::ReadOnly))
- return vec;
- QComposeCacheFileHeader cacheInfo;
- // use a "buffer" variable to make the line after this one more readable.
- char *buffer = reinterpret_cast<char*>(&cacheInfo);
-
- if (inputFile.read(buffer, sizeof cacheInfo) != sizeof cacheInfo)
- return vec;
- if (cacheInfo.fileSize == 0)
- return vec;
- // using "!=" just in case someone replaced with a backup that existed before
- if (cacheInfo.lastModified != composeInfo.lastModified)
- return vec;
- if (cacheInfo.cacheVersion != SupportedCacheVersion)
- return vec;
- const QByteArray pathBytes = QFile::encodeName(cacheFilePath);
- QT_STATBUF st;
- if (QT_STAT(pathBytes.data(), &st) != 0)
- return vec;
- const off_t fileSize = st.st_size;
- if (fileSize > 1024 * 1024 * 5) {
- // The cache file size is usually about 150KB, so if its size is over
- // say 5MB then somebody inflated the file, abort.
- return vec;
- }
- const off_t bufferSize = fileSize - (sizeof cacheInfo);
- const size_t elemSize = sizeof (struct QComposeTableElement);
- const int elemCount = bufferSize / elemSize;
- const QByteArray ba = inputFile.read(bufferSize);
- const char *data = ba.data();
- // Since we know the number of the (many) elements and their size in
- // advance calling vector.reserve(..) seems reasonable.
- vec.reserve(elemCount);
-
- for (int i = 0; i < elemCount; i++) {
- const QComposeTableElement *elem =
- reinterpret_cast<const QComposeTableElement*>(data + (i * elemSize));
- vec.push_back(*elem);
- }
- return vec;
-}
-
-// Returns true on success, false otherwise.
-static bool saveCache(const QComposeCacheFileHeader &info, const QVector<QComposeTableElement> &vec)
-{
- const QString filePath = getCacheFilePath();
-#if QT_CONFIG(temporaryfile)
- QSaveFile outputFile(filePath);
-#else
- QFile outputFile(filePath);
-#endif
- if (!outputFile.open(QIODevice::WriteOnly))
- return false;
- const char *data = reinterpret_cast<const char*>(&info);
-
- if (outputFile.write(data, sizeof info) != sizeof info)
- return false;
- data = reinterpret_cast<const char*>(vec.constData());
- const qint64 size = vec.size() * (sizeof (struct QComposeTableElement));
-
- if (outputFile.write(data, size) != size)
- return false;
-#if QT_CONFIG(temporaryfile)
- return outputFile.commit();
-#else
- return true;
-#endif
-}
-
-TableGenerator::TableGenerator() : m_state(NoErrors),
- m_systemComposeDir(QString())
-{
- initPossibleLocations();
- QString composeFilePath = findComposeFile();
-#ifdef DEBUG_GENERATOR
-// don't use cache when in debug mode.
- if (!composeFilePath.isEmpty())
- qDebug() << "Using Compose file from: " << composeFilePath;
-#else
- QComposeCacheFileHeader fileInfo = readFileMetadata(composeFilePath);
- if (fileInfo.fileSize != 0)
- m_composeTable = loadCache(fileInfo);
-#endif
- if (m_composeTable.isEmpty() && cleanState()) {
- if (composeFilePath.isEmpty()) {
- m_state = MissingComposeFile;
- } else {
- QFile composeFile(composeFilePath);
- composeFile.open(QIODevice::ReadOnly);
- parseComposeFile(&composeFile);
- orderComposeTable();
- if (m_composeTable.isEmpty()) {
- m_state = EmptyTable;
-#ifndef DEBUG_GENERATOR
-// don't save cache when in debug mode
- } else {
- fileInfo.cacheVersion = SupportedCacheVersion;
- saveCache(fileInfo, m_composeTable);
-#endif
- }
- }
- }
-#ifdef DEBUG_GENERATOR
- printComposeTable();
-#endif
-}
-
-void TableGenerator::initPossibleLocations()
-{
- // Compose files come as a part of Xlib library. Xlib doesn't provide
- // a mechanism how to retrieve the location of these files reliably, since it was
- // never meant for external software to parse compose tables directly. Best we
- // can do is to hardcode search paths. To add an extra system path use
- // the QTCOMPOSE environment variable
- m_possibleLocations.reserve(7);
- if (qEnvironmentVariableIsSet("QTCOMPOSE"))
- m_possibleLocations.append(QString::fromLocal8Bit(qgetenv("QTCOMPOSE")));
- m_possibleLocations.append(QStringLiteral("/usr/share/X11/locale"));
- m_possibleLocations.append(QStringLiteral("/usr/local/share/X11/locale"));
- m_possibleLocations.append(QStringLiteral("/usr/lib/X11/locale"));
- m_possibleLocations.append(QStringLiteral("/usr/local/lib/X11/locale"));
- m_possibleLocations.append(QStringLiteral(X11_PREFIX "/share/X11/locale"));
- m_possibleLocations.append(QStringLiteral(X11_PREFIX "/lib/X11/locale"));
-}
-
-QString TableGenerator::findComposeFile()
-{
- // check if XCOMPOSEFILE points to a Compose file
- if (qEnvironmentVariableIsSet("XCOMPOSEFILE")) {
- const QString path = QFile::decodeName(qgetenv("XCOMPOSEFILE"));
- if (QFile::exists(path))
- return path;
- else
- qWarning("$XCOMPOSEFILE doesn't point to an existing file");
- }
-
- // check if user’s home directory has a file named .XCompose
- if (cleanState()) {
- QString path = qgetenv("HOME") + QLatin1String("/.XCompose");
- if (QFile::exists(path))
- return path;
- }
-
- // check for the system provided compose files
- if (cleanState()) {
- QString table = composeTableForLocale();
- if (cleanState()) {
- if (table.isEmpty())
- // no table mappings for the system's locale in the compose.dir
- m_state = UnsupportedLocale;
- else {
- QString path = QDir(systemComposeDir()).filePath(table);
- if (QFile::exists(path))
- return path;
- }
- }
- }
- return QString();
-}
-
-QString TableGenerator::composeTableForLocale()
-{
- QByteArray loc = locale().toUpper().toUtf8();
- QString table = readLocaleMappings(loc);
- if (table.isEmpty())
- table = readLocaleMappings(readLocaleAliases(loc));
- return table;
-}
-
-bool TableGenerator::findSystemComposeDir()
-{
- bool found = false;
- for (int i = 0; i < m_possibleLocations.size(); ++i) {
- QString path = m_possibleLocations.at(i);
- if (QFile::exists(path + QLatin1String("/compose.dir"))) {
- m_systemComposeDir = path;
- found = true;
- break;
- }
- }
-
- if (!found) {
- // should we ask to report this in the qt bug tracker?
- m_state = UnknownSystemComposeDir;
- qWarning("Qt Warning: Could not find a location of the system's Compose files. "
- "Consider setting the QTCOMPOSE environment variable.");
- }
-
- return found;
-}
-
-QString TableGenerator::systemComposeDir()
-{
- if (m_systemComposeDir.isNull()
- && !findSystemComposeDir()) {
- return QLatin1String("$QTCOMPOSE");
- }
-
- return m_systemComposeDir;
-}
-
-QString TableGenerator::locale() const
-{
- char *name = setlocale(LC_CTYPE, (char *)0);
- return QLatin1String(name);
-}
-
-QString TableGenerator::readLocaleMappings(const QByteArray &locale)
-{
- QString file;
- if (locale.isEmpty())
- return file;
-
- QFile mappings(systemComposeDir() + QLatin1String("/compose.dir"));
- if (mappings.open(QIODevice::ReadOnly)) {
- const int localeNameLength = locale.size();
- const char * const localeData = locale.constData();
-
- char l[1024];
- // formating of compose.dir has some inconsistencies
- while (!mappings.atEnd()) {
- int read = mappings.readLine(l, sizeof(l));
- if (read <= 0)
- break;
-
- char *line = l;
- if (*line >= 'a' && *line <= 'z') {
- // file name
- while (*line && *line != ':' && *line != ' ' && *line != '\t')
- ++line;
- if (!*line)
- continue;
- const char * const composeFileNameEnd = line;
- *line = '\0';
- ++line;
-
- // locale name
- while (*line && (*line == ' ' || *line == '\t'))
- ++line;
- const char * const lc = line;
- while (*line && *line != ' ' && *line != '\t' && *line != '\n')
- ++line;
- *line = '\0';
- if (localeNameLength == (line - lc) && !strncasecmp(lc, localeData, line - lc)) {
- file = QString::fromLocal8Bit(l, composeFileNameEnd - l);
- break;
- }
- }
- }
- mappings.close();
- }
- return file;
-}
-
-QByteArray TableGenerator::readLocaleAliases(const QByteArray &locale)
-{
- QFile aliases(systemComposeDir() + QLatin1String("/locale.alias"));
- QByteArray fullLocaleName;
- if (aliases.open(QIODevice::ReadOnly)) {
- while (!aliases.atEnd()) {
- char l[1024];
- int read = aliases.readLine(l, sizeof(l));
- char *line = l;
- if (read && ((*line >= 'a' && *line <= 'z') ||
- (*line >= 'A' && *line <= 'Z'))) {
- const char *alias = line;
- while (*line && *line != ':' && *line != ' ' && *line != '\t')
- ++line;
- if (!*line)
- continue;
- *line = 0;
- if (locale.size() == (line - alias)
- && !strncasecmp(alias, locale.constData(), line - alias)) {
- // found a match for alias, read the real locale name
- ++line;
- while (*line && (*line == ' ' || *line == '\t'))
- ++line;
- const char *fullName = line;
- while (*line && *line != ' ' && *line != '\t' && *line != '\n')
- ++line;
- *line = 0;
- fullLocaleName = fullName;
-#ifdef DEBUG_GENERATOR
- qDebug() << "Alias for: " << alias << "is: " << fullLocaleName;
- break;
-#endif
- }
- }
- }
- aliases.close();
- }
- return fullLocaleName;
-}
-
-bool TableGenerator::processFile(const QString &composeFileName)
-{
- QFile composeFile(composeFileName);
- if (composeFile.open(QIODevice::ReadOnly)) {
- parseComposeFile(&composeFile);
- return true;
- }
- qWarning() << QString(QLatin1String("Qt Warning: Compose file: \"%1\" can't be found"))
- .arg(composeFile.fileName());
- return false;
-}
-
-TableGenerator::~TableGenerator()
-{
-}
-
-QVector<QComposeTableElement> TableGenerator::composeTable() const
-{
- return m_composeTable;
-}
-
-void TableGenerator::parseComposeFile(QFile *composeFile)
-{
-#ifdef DEBUG_GENERATOR
- qDebug() << "TableGenerator::parseComposeFile: " << composeFile->fileName();
-#endif
-
- char line[1024];
- while (!composeFile->atEnd()) {
- composeFile->readLine(line, sizeof(line));
- if (*line == '<')
- parseKeySequence(line);
- else if (!strncmp(line, "include", 7))
- parseIncludeInstruction(QString::fromLocal8Bit(line));
- }
-
- composeFile->close();
-}
-
-void TableGenerator::parseIncludeInstruction(QString line)
-{
- // Parse something that looks like:
- // include "/usr/share/X11/locale/en_US.UTF-8/Compose"
- QString quote = QStringLiteral("\"");
- line.remove(0, line.indexOf(quote) + 1);
- line.chop(line.length() - line.indexOf(quote));
-
- // expand substitutions if present
- line.replace(QLatin1String("%H"), QString(qgetenv("HOME")));
- line.replace(QLatin1String("%L"), systemComposeDir() + QLatin1Char('/') + composeTableForLocale());
- line.replace(QLatin1String("%S"), systemComposeDir());
-
- processFile(line);
-}
-
-ushort TableGenerator::keysymToUtf8(quint32 sym)
-{
- QByteArray chars;
- int bytes;
- chars.resize(8);
- bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size());
- if (bytes == -1)
- qWarning("TableGenerator::keysymToUtf8 - buffer too small");
-
- chars.resize(bytes-1);
-
-#ifdef DEBUG_GENERATOR
- QTextCodec *codec = QTextCodec::codecForLocale();
- qDebug() << QString("keysym - 0x%1 : utf8 - %2").arg(QString::number(sym, 16))
- .arg(codec->toUnicode(chars));
-#endif
- return QString::fromUtf8(chars).at(0).unicode();
-}
-
-static inline int fromBase8(const char *s, const char *end)
-{
- int result = 0;
- while (*s && s != end) {
- if (*s < '0' || *s > '7')
- return 0;
- result *= 8;
- result += *s - '0';
- ++s;
- }
- return result;
-}
-
-static inline int fromBase16(const char *s, const char *end)
-{
- int result = 0;
- while (*s && s != end) {
- result *= 16;
- if (*s >= '0' && *s <= '9')
- result += *s - '0';
- else if (*s >= 'a' && *s <= 'f')
- result += *s - 'a' + 10;
- else if (*s >= 'A' && *s <= 'F')
- result += *s - 'A' + 10;
- else
- return 0;
- ++s;
- }
- return result;
-}
-
-void TableGenerator::parseKeySequence(char *line)
-{
- // we are interested in the lines with the following format:
- // <Multi_key> <numbersign> <S> : "♬" U266c # BEAMED SIXTEENTH NOTE
- char *keysEnd = strchr(line, ':');
- if (!keysEnd)
- return;
-
- QComposeTableElement elem;
- // find the composed value - strings may be direct text encoded in the locale
- // for which the compose file is to be used, or an escaped octal or hexadecimal
- // character code. Octal codes are specified as "\123" and hexadecimal codes as "\0x123a".
- char *composeValue = strchr(keysEnd, '"');
- if (!composeValue)
- return;
- ++composeValue;
-
- char *composeValueEnd = strchr(composeValue, '"');
- if (!composeValueEnd)
- return;
-
- // if composed value is a quotation mark adjust the end pointer
- if (composeValueEnd[1] == '"')
- ++composeValueEnd;
-
- if (*composeValue == '\\' && composeValue[1] >= '0' && composeValue[1] <= '9') {
- // handle octal and hex code values
- char detectBase = composeValue[2];
- if (detectBase == 'x') {
- // hexadecimal character code
- elem.value = keysymToUtf8(fromBase16(composeValue + 3, composeValueEnd));
- } else {
- // octal character code
- elem.value = keysymToUtf8(fromBase8(composeValue + 1, composeValueEnd));
- }
- } else {
- // handle direct text encoded in the locale
- if (*composeValue == '\\')
- ++composeValue;
- elem.value = QString::fromLocal8Bit(composeValue, composeValueEnd - composeValue).at(0).unicode();
- ++composeValue;
- }
-
-#ifdef DEBUG_GENERATOR
- // find the comment
- elem.comment = QString::fromLocal8Bit(composeValueEnd + 1).trimmed();
-#endif
-
- // find the key sequence and convert to X11 keysym
- char *k = line;
- const char *kend = keysEnd;
-
- for (int i = 0; i < QT_KEYSEQUENCE_MAX_LEN; i++) {
- // find the next pair of angle brackets and get the contents within
- while (k < kend && *k != '<')
- ++k;
- char *sym = ++k;
- while (k < kend && *k != '>')
- ++k;
- *k = '\0';
- if (k < kend) {
- elem.keys[i] = xkb_keysym_from_name(sym, (xkb_keysym_flags)0);
- if (elem.keys[i] == XKB_KEY_NoSymbol) {
- if (!strcmp(sym, "dead_inverted_breve"))
- elem.keys[i] = XKB_KEY_dead_invertedbreve;
- else if (!strcmp(sym, "dead_double_grave"))
- elem.keys[i] = XKB_KEY_dead_doublegrave;
-#ifdef DEBUG_GENERATOR
- else
- qWarning() << QString("Qt Warning - invalid keysym: %1").arg(sym);
-#endif
- }
- } else {
- elem.keys[i] = 0;
- }
- }
- m_composeTable.append(elem);
-}
-
-void TableGenerator::printComposeTable() const
-{
-#ifdef DEBUG_GENERATOR
-# ifndef QT_NO_DEBUG_STREAM
- if (m_composeTable.isEmpty())
- return;
-
- QDebug ds = qDebug() << "output:\n";
- ds.nospace();
- const int tableSize = m_composeTable.size();
- for (int i = 0; i < tableSize; ++i) {
- const QComposeTableElement &elem = m_composeTable.at(i);
- ds << "{ {";
- for (int j = 0; j < QT_KEYSEQUENCE_MAX_LEN; j++) {
- ds << hex << showbase << elem.keys[j] << ", ";
- }
- ds << "}, " << hex << showbase << elem.value << ", \"\" }, // " << elem.comment << " \n";
- }
-# endif
-#endif
-}
-
-void TableGenerator::orderComposeTable()
-{
- // Stable-sorting to ensure that the item that appeared before the other in the
- // original container will still appear first after the sort. This property is
- // needed to handle the cases when user re-defines already defined key sequence
- std::stable_sort(m_composeTable.begin(), m_composeTable.end(), ByKeys());
-}
-
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h
deleted file mode 100644
index 4f58358f4e..0000000000
--- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QTABLEGENERATOR_H
-#define QTABLEGENERATOR_H
-
-#include <QtCore/QVector>
-#include <QtCore/QFile>
-#include <QtCore/QMap>
-#include <QtCore/QString>
-
-#include <algorithm>
-
-static Q_CONSTEXPR int QT_KEYSEQUENCE_MAX_LEN = 6;
-
-//#define DEBUG_GENERATOR
-
-/* Whenever QComposeTableElement gets modified supportedCacheVersion
- from qtablegenerator.cpp must be bumped. */
-struct QComposeTableElement {
- uint keys[QT_KEYSEQUENCE_MAX_LEN];
- uint value;
-#ifdef DEBUG_GENERATOR
- QString comment;
-#endif
-};
-
-#ifndef DEBUG_GENERATOR
-QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(QComposeTableElement, Q_PRIMITIVE_TYPE);
-QT_END_NAMESPACE
-#endif
-
-struct ByKeys
-{
- using uint_array = uint[QT_KEYSEQUENCE_MAX_LEN];
- using result_type = bool;
-
- bool operator()(const uint_array &lhs, const uint_array &rhs) const Q_DECL_NOTHROW
- {
- return std::lexicographical_compare(lhs, lhs + QT_KEYSEQUENCE_MAX_LEN,
- rhs, rhs + QT_KEYSEQUENCE_MAX_LEN);
- }
-
- bool operator()(const uint_array &lhs, const QComposeTableElement &rhs) const Q_DECL_NOTHROW
- {
- return operator()(lhs, rhs.keys);
- }
-
- bool operator()(const QComposeTableElement &lhs, const uint_array &rhs) const Q_DECL_NOTHROW
- {
- return operator()(lhs.keys, rhs);
- }
-
- bool operator()(const QComposeTableElement &lhs, const QComposeTableElement &rhs) const Q_DECL_NOTHROW
- {
- return operator()(lhs.keys, rhs.keys);
- }
-};
-
-class TableGenerator
-{
-
-public:
- enum TableState
- {
- UnsupportedLocale,
- EmptyTable,
- UnknownSystemComposeDir,
- MissingComposeFile,
- NoErrors
- };
-
- TableGenerator();
- ~TableGenerator();
-
- void parseComposeFile(QFile *composeFile);
- void printComposeTable() const;
- void orderComposeTable();
-
- QVector<QComposeTableElement> composeTable() const;
- TableState tableState() const { return m_state; }
-
-protected:
- bool processFile(const QString &composeFileName);
- void parseKeySequence(char *line);
- void parseIncludeInstruction(QString line);
-
- QString findComposeFile();
- bool findSystemComposeDir();
- QString systemComposeDir();
- QString composeTableForLocale();
-
- ushort keysymToUtf8(quint32 sym);
-
- QString readLocaleMappings(const QByteArray &locale);
- QByteArray readLocaleAliases(const QByteArray &locale);
- void initPossibleLocations();
- bool cleanState() const { return m_state == NoErrors; }
- QString locale() const;
-
-private:
- QVector<QComposeTableElement> m_composeTable;
- TableState m_state;
- QString m_systemComposeDir;
- QList<QString> m_possibleLocations;
-};
-
-#endif // QTABLEGENERATOR_H
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
index 81a730232c..4e9828663f 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -36,131 +36,110 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
#include "qcomposeplatforminputcontext.h"
#include <QtCore/QCoreApplication>
#include <QtGui/QKeyEvent>
-#include <QtCore/QDebug>
+#include <QtGui/QGuiApplication>
-#include <algorithm>
+#include <locale.h>
QT_BEGIN_NAMESPACE
-//#define DEBUG_COMPOSING
+Q_LOGGING_CATEGORY(lcXkbCompose, "qt.xkb.compose")
-static const int ignoreKeys[] = {
- Qt::Key_Shift,
- Qt::Key_Control,
- Qt::Key_Meta,
- Qt::Key_Alt,
- Qt::Key_CapsLock,
- Qt::Key_Super_L,
- Qt::Key_Super_R,
- Qt::Key_Hyper_L,
- Qt::Key_Hyper_R,
- Qt::Key_Mode_switch
-};
+QComposeInputContext::QComposeInputContext()
+{
+ setObjectName(QStringLiteral("QComposeInputContext"));
+ qCDebug(lcXkbCompose, "using xkb compose input context");
+}
-static const int composingKeys[] = {
- Qt::Key_Multi_key,
- Qt::Key_Dead_Grave,
- Qt::Key_Dead_Acute,
- Qt::Key_Dead_Circumflex,
- Qt::Key_Dead_Tilde,
- Qt::Key_Dead_Macron,
- Qt::Key_Dead_Breve,
- Qt::Key_Dead_Abovedot,
- Qt::Key_Dead_Diaeresis,
- Qt::Key_Dead_Abovering,
- Qt::Key_Dead_Doubleacute,
- Qt::Key_Dead_Caron,
- Qt::Key_Dead_Cedilla,
- Qt::Key_Dead_Ogonek,
- Qt::Key_Dead_Iota,
- Qt::Key_Dead_Voiced_Sound,
- Qt::Key_Dead_Semivoiced_Sound,
- Qt::Key_Dead_Belowdot,
- Qt::Key_Dead_Hook,
- Qt::Key_Dead_Horn,
- Qt::Key_Dead_Stroke,
- Qt::Key_Dead_Abovecomma,
- Qt::Key_Dead_Abovereversedcomma,
- Qt::Key_Dead_Doublegrave,
- Qt::Key_Dead_Belowring,
- Qt::Key_Dead_Belowmacron,
- Qt::Key_Dead_Belowcircumflex,
- Qt::Key_Dead_Belowtilde,
- Qt::Key_Dead_Belowbreve,
- Qt::Key_Dead_Belowdiaeresis,
- Qt::Key_Dead_Invertedbreve,
- Qt::Key_Dead_Belowcomma,
- Qt::Key_Dead_Currency,
- Qt::Key_Dead_a,
- Qt::Key_Dead_A,
- Qt::Key_Dead_e,
- Qt::Key_Dead_E,
- Qt::Key_Dead_i,
- Qt::Key_Dead_I,
- Qt::Key_Dead_o,
- Qt::Key_Dead_O,
- Qt::Key_Dead_u,
- Qt::Key_Dead_U,
- Qt::Key_Dead_Small_Schwa,
- Qt::Key_Dead_Capital_Schwa,
- Qt::Key_Dead_Greek,
- Qt::Key_Dead_Lowline,
- Qt::Key_Dead_Aboveverticalline,
- Qt::Key_Dead_Belowverticalline,
- Qt::Key_Dead_Longsolidusoverlay
-};
+QComposeInputContext::~QComposeInputContext()
+{
+ xkb_compose_state_unref(m_composeState);
+ xkb_compose_table_unref(m_composeTable);
+}
-QComposeInputContext::QComposeInputContext()
- : m_tableState(TableGenerator::EmptyTable)
- , m_compositionTableInitialized(false)
+void QComposeInputContext::ensureInitialized()
{
- clearComposeBuffer();
+ if (m_initialized)
+ return;
+
+ if (!m_XkbContext) {
+ qCWarning(lcXkbCompose) << "error: xkb context has not been set on" << metaObject()->className();
+ return;
+ }
+
+ m_initialized = true;
+ const char *locale = setlocale(LC_CTYPE, "");
+ if (!locale)
+ locale = setlocale(LC_CTYPE, nullptr);
+ qCDebug(lcXkbCompose) << "detected locale (LC_CTYPE):" << locale;
+
+ m_composeTable = xkb_compose_table_new_from_locale(m_XkbContext, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
+ if (m_composeTable)
+ m_composeState = xkb_compose_state_new(m_composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
+
+ if (!m_composeTable) {
+ qCWarning(lcXkbCompose, "failed to create compose table");
+ return;
+ }
+ if (!m_composeState) {
+ qCWarning(lcXkbCompose, "failed to create compose state");
+ return;
+ }
}
bool QComposeInputContext::filterEvent(const QEvent *event)
{
- const QKeyEvent *keyEvent = (const QKeyEvent *)event;
- // should pass only the key presses
- if (keyEvent->type() != QEvent::KeyPress) {
+ auto keyEvent = static_cast<const QKeyEvent *>(event);
+ if (keyEvent->type() != QEvent::KeyPress)
return false;
- }
- // if there were errors when generating the compose table input
- // context should not try to filter anything, simply return false
- if (m_compositionTableInitialized && (m_tableState & TableGenerator::NoErrors) != TableGenerator::NoErrors)
+ if (!inputMethodAccepted())
return false;
- int keyval = keyEvent->key();
- int keysym = 0;
+ // lazy initialization - we don't want to do this on an app startup
+ ensureInitialized();
- if (ignoreKey(keyval))
+ if (!m_composeTable || !m_composeState)
return false;
- if (!composeKey(keyval) && keyEvent->text().isEmpty())
+ xkb_compose_state_feed(m_composeState, keyEvent->nativeVirtualKey());
+
+ switch (xkb_compose_state_get_status(m_composeState)) {
+ case XKB_COMPOSE_COMPOSING:
+ return true;
+ case XKB_COMPOSE_CANCELLED:
+ reset();
return false;
+ case XKB_COMPOSE_COMPOSED:
+ {
+ const int size = xkb_compose_state_get_utf8(m_composeState, nullptr, 0);
+ QVarLengthArray<char, 32> buffer(size + 1);
+ xkb_compose_state_get_utf8(m_composeState, buffer.data(), buffer.size());
+ QString composedText = QString::fromUtf8(buffer.constData());
- keysym = keyEvent->nativeVirtualKey();
+ QInputMethodEvent event;
+ event.setCommitString(composedText);
- int nCompose = 0;
- while (nCompose < QT_KEYSEQUENCE_MAX_LEN && m_composeBuffer[nCompose] != 0)
- nCompose++;
+ if (!m_focusObject && qApp)
+ m_focusObject = qApp->focusObject();
- if (nCompose == QT_KEYSEQUENCE_MAX_LEN) {
- reset();
- nCompose = 0;
- }
+ if (m_focusObject)
+ QCoreApplication::sendEvent(m_focusObject, &event);
+ else
+ qCWarning(lcXkbCompose, "no focus object");
- m_composeBuffer[nCompose] = keysym;
- // check sequence
- if (checkComposeTable())
+ reset();
return true;
-
- return false;
+ }
+ case XKB_COMPOSE_NOTHING:
+ return false;
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
}
bool QComposeInputContext::isValid() const
@@ -175,7 +154,8 @@ void QComposeInputContext::setFocusObject(QObject *object)
void QComposeInputContext::reset()
{
- clearComposeBuffer();
+ if (m_composeState)
+ xkb_compose_state_reset(m_composeState);
}
void QComposeInputContext::update(Qt::InputMethodQueries q)
@@ -183,125 +163,4 @@ void QComposeInputContext::update(Qt::InputMethodQueries q)
QPlatformInputContext::update(q);
}
-static bool isDuplicate(const QComposeTableElement &lhs, const QComposeTableElement &rhs)
-{
- return std::equal(lhs.keys, lhs.keys + QT_KEYSEQUENCE_MAX_LEN,
- QT_MAKE_CHECKED_ARRAY_ITERATOR(rhs.keys, QT_KEYSEQUENCE_MAX_LEN));
-}
-
-bool QComposeInputContext::checkComposeTable()
-{
- if (!m_compositionTableInitialized) {
- TableGenerator reader;
- m_tableState = reader.tableState();
-
- m_compositionTableInitialized = true;
- if ((m_tableState & TableGenerator::NoErrors) == TableGenerator::NoErrors) {
- m_composeTable = reader.composeTable();
- } else {
-#ifdef DEBUG_COMPOSING
- qDebug( "### FAILED_PARSING ###" );
-#endif
- // if we have errors, don' try to look things up anyways.
- reset();
- return false;
- }
- }
- Q_ASSERT(!m_composeTable.isEmpty());
- QVector<QComposeTableElement>::const_iterator it =
- std::lower_bound(m_composeTable.constBegin(), m_composeTable.constEnd(), m_composeBuffer, ByKeys());
-
- // prevent dereferencing an 'end' iterator, which would result in a crash
- if (it == m_composeTable.constEnd())
- it -= 1;
-
- QComposeTableElement elem = *it;
- // would be nicer if qLowerBound had API that tells if the item was actually found
- if (m_composeBuffer[0] != elem.keys[0]) {
-#ifdef DEBUG_COMPOSING
- qDebug( "### no match ###" );
-#endif
- reset();
- return false;
- }
- // check if compose buffer is matched
- for (int i=0; i < QT_KEYSEQUENCE_MAX_LEN; i++) {
-
- // check if partial match
- if (m_composeBuffer[i] == 0 && elem.keys[i]) {
-#ifdef DEBUG_COMPOSING
- qDebug("### partial match ###");
-#endif
- return true;
- }
-
- if (m_composeBuffer[i] != elem.keys[i]) {
-#ifdef DEBUG_COMPOSING
- qDebug("### different entry ###");
-#endif
- reset();
- return i != 0;
- }
- }
-#ifdef DEBUG_COMPOSING
- qDebug("### match exactly ###");
-#endif
-
- // check if the key sequence is overwriten - see the comment in
- // TableGenerator::orderComposeTable()
- int next = 1;
- do {
- // if we are at the end of the table, then we have nothing to do here
- if (it + next != m_composeTable.constEnd()) {
- QComposeTableElement nextElem = *(it + next);
- if (isDuplicate(elem, nextElem)) {
- elem = nextElem;
- next++;
- continue;
- } else {
- break;
- }
- }
- break;
- } while (true);
-
- commitText(elem.value);
- reset();
-
- return true;
-}
-
-void QComposeInputContext::commitText(uint character) const
-{
- QInputMethodEvent event;
- event.setCommitString(QChar(character));
- QCoreApplication::sendEvent(m_focusObject, &event);
-}
-
-bool QComposeInputContext::ignoreKey(int keyval) const
-{
- for (uint i = 0; i < (sizeof(ignoreKeys) / sizeof(ignoreKeys[0])); i++)
- if (keyval == ignoreKeys[i])
- return true;
-
- return false;
-}
-
-bool QComposeInputContext::composeKey(int keyval) const
-{
- for (uint i = 0; i < (sizeof(composingKeys) / sizeof(composingKeys[0])); i++)
- if (keyval == composingKeys[i])
- return true;
-
- return false;
-}
-
-void QComposeInputContext::clearComposeBuffer()
-{
- for (uint i=0; i < (sizeof(m_composeBuffer) / sizeof(int)); i++)
- m_composeBuffer[i] = 0;
-}
-
-QComposeInputContext::~QComposeInputContext() {}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h
index 4830959665..b1de1b1094 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -36,24 +36,24 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
#ifndef QCOMPOSEPLATFORMINPUTCONTEXT_H
#define QCOMPOSEPLATFORMINPUTCONTEXT_H
-#include <qpa/qplatforminputcontext.h>
+#include <QtCore/QLoggingCategory>
-#include <QtCore/QList>
+#include <qpa/qplatforminputcontext.h>
-#include "generator/qtablegenerator.h"
+#include <xkbcommon/xkbcommon-compose.h>
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcXkbCompose)
+
class QEvent;
class QComposeInputContext : public QPlatformInputContext
{
Q_OBJECT
-
public:
QComposeInputContext();
~QComposeInputContext();
@@ -62,21 +62,22 @@ public:
void setFocusObject(QObject *object) override;
void reset() override;
void update(Qt::InputMethodQueries) override;
+
bool filterEvent(const QEvent *event) override;
+ // This invokable is called from QXkbCommon::setXkbContext().
+ Q_INVOKABLE void setXkbContext(struct xkb_context *context) { m_XkbContext = context; }
+
protected:
- void clearComposeBuffer();
- bool ignoreKey(int keyval) const;
- bool composeKey(int keyval) const;
- bool checkComposeTable();
- void commitText(uint character) const;
+ void ensureInitialized();
private:
- QObject *m_focusObject;
- QVector<QComposeTableElement> m_composeTable;
- uint m_composeBuffer[QT_KEYSEQUENCE_MAX_LEN];
- TableGenerator::TableState m_tableState;
- bool m_compositionTableInitialized;
+ bool m_initialized = false;
+ xkb_context *m_context = nullptr;
+ xkb_compose_table *m_composeTable = nullptr;
+ xkb_compose_state *m_composeState = nullptr;
+ QObject *m_focusObject = nullptr;
+ struct xkb_context *m_XkbContext = nullptr;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
index 6b33df65b9..d062d4fd6a 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -61,7 +61,7 @@ QComposeInputContext *QComposePlatformInputContextPlugin::create(const QString &
if (system.compare(system, QLatin1String("compose"), Qt::CaseInsensitive) == 0
|| system.compare(system, QLatin1String("xim"), Qt::CaseInsensitive) == 0)
return new QComposeInputContext;
- return 0;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforminputcontexts/ibus/ibus.pro b/src/plugins/platforminputcontexts/ibus/ibus.pro
index 52836bb8b6..9ba2297e38 100644
--- a/src/plugins/platforminputcontexts/ibus/ibus.pro
+++ b/src/plugins/platforminputcontexts/ibus/ibus.pro
@@ -1,6 +1,6 @@
TARGET = ibusplatforminputcontextplugin
-QT += dbus gui-private
+QT += dbus gui-private xkbcommon_support-private
SOURCES += $$PWD/qibusplatforminputcontext.cpp \
$$PWD/qibusproxy.cpp \
$$PWD/qibusproxyportal.cpp \
diff --git a/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h b/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
index 47a40ab8c2..396a213aaa 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusinputcontextproxy.h
@@ -31,7 +31,7 @@ public:
{ return "org.freedesktop.IBus.InputContext"; }
public:
- QIBusInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ QIBusInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~QIBusInputContextProxy();
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
index ca315840e2..f2429f24ff 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
@@ -47,7 +47,11 @@
#include <qpa/qplatformcursor.h>
#include <qpa/qplatformscreen.h>
-#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qwindowsysteminterface_p.h>
+
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
#include "qibusproxy.h"
#include "qibusproxyportal.h"
@@ -217,17 +221,14 @@ void QIBusPlatformInputContext::update(Qt::InputMethodQueries q)
&& (q.testFlag(Qt::ImSurroundingText)
|| q.testFlag(Qt::ImCursorPosition)
|| q.testFlag(Qt::ImAnchorPosition))) {
- QInputMethodQueryEvent srrndTextQuery(Qt::ImSurroundingText);
- QInputMethodQueryEvent cursorPosQuery(Qt::ImCursorPosition);
- QInputMethodQueryEvent anchorPosQuery(Qt::ImAnchorPosition);
- QCoreApplication::sendEvent(input, &srrndTextQuery);
- QCoreApplication::sendEvent(input, &cursorPosQuery);
- QCoreApplication::sendEvent(input, &anchorPosQuery);
+ QInputMethodQueryEvent query(Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition);
+
+ QCoreApplication::sendEvent(input, &query);
- QString surroundingText = srrndTextQuery.value(Qt::ImSurroundingText).toString();
- uint cursorPosition = cursorPosQuery.value(Qt::ImCursorPosition).toUInt();
- uint anchorPosition = anchorPosQuery.value(Qt::ImAnchorPosition).toUInt();
+ QString surroundingText = query.value(Qt::ImSurroundingText).toString();
+ uint cursorPosition = query.value(Qt::ImCursorPosition).toUInt();
+ uint anchorPosition = query.value(Qt::ImAnchorPosition).toUInt();
QIBusText text;
text.text = surroundingText;
@@ -336,14 +337,12 @@ void QIBusPlatformInputContext::forwardKeyEvent(uint keyval, uint keycode, uint
if (!input)
return;
- if (debug)
- qDebug() << "forwardKeyEvent" << keyval << keycode << state;
-
QEvent::Type type = QEvent::KeyPress;
if (state & IBUS_RELEASE_MASK)
type = QEvent::KeyRelease;
state &= ~IBUS_RELEASE_MASK;
+ keycode += 8;
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
if (state & IBUS_SHIFT_MASK)
@@ -355,7 +354,13 @@ void QIBusPlatformInputContext::forwardKeyEvent(uint keyval, uint keycode, uint
if (state & IBUS_META_MASK)
modifiers |= Qt::MetaModifier;
- QKeyEvent event(type, keyval, modifiers, QString(keyval));
+ int qtcode = QXkbCommon::keysymToQtKey(keyval, modifiers);
+ QString text = QXkbCommon::lookupStringNoKeysymTransformations(keyval);
+
+ if (debug)
+ qDebug() << "forwardKeyEvent" << keyval << keycode << state << modifiers << qtcode << text;
+
+ QKeyEvent event(type, qtcode, modifiers, keycode, keyval, state, text);
QCoreApplication::sendEvent(input, &event);
}
@@ -422,9 +427,9 @@ bool QIBusPlatformInputContext::filterEvent(const QEvent *event)
QDBusPendingReply<bool> reply = d->context->ProcessKeyEvent(sym, code - 8, ibusState);
if (m_eventFilterUseSynchronousMode || reply.isFinished()) {
- bool retval = reply.value();
- qCDebug(qtQpaInputMethods) << "filterEvent return" << code << sym << state << retval;
- return retval;
+ bool filtered = reply.value();
+ qCDebug(qtQpaInputMethods) << "filterEvent return" << code << sym << state << filtered;
+ return filtered;
}
Qt::KeyboardModifiers modifiers = keyEvent->modifiers();
@@ -494,23 +499,22 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal
const bool isAutoRepeat = args.at(7).toBool();
// copied from QXcbKeyboard::handleKeyEvent()
- bool retval = reply.value();
- qCDebug(qtQpaInputMethods) << "filterEventFinished return" << code << sym << state << retval;
- if (!retval) {
+ bool filtered = reply.value();
+ qCDebug(qtQpaInputMethods) << "filterEventFinished return" << code << sym << state << filtered;
+ if (!filtered) {
#ifndef QT_NO_CONTEXTMENU
if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu
&& window != NULL) {
const QPoint globalPos = window->screen()->handle()->cursor()->pos();
const QPoint pos = window->mapFromGlobal(globalPos);
-#ifndef QT_NO_CONTEXTMENU
- QWindowSystemInterface::handleContextMenuEvent(window, false, pos,
- globalPos, modifiers);
-#endif
+ QWindowSystemInterfacePrivate::ContextMenuEvent contextMenuEvent(window, false, pos,
+ globalPos, modifiers);
+ QGuiApplicationPrivate::processWindowSystemEvent(&contextMenuEvent);
}
-#endif // QT_NO_CONTEXTMENU
- QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers,
- code, sym, state, string, isAutoRepeat);
-
+#endif
+ QWindowSystemInterfacePrivate::KeyEvent keyEvent(window, time, type, qtcode, modifiers,
+ code, sym, state, string, isAutoRepeat);
+ QGuiApplicationPrivate::processWindowSystemEvent(&keyEvent);
}
call->deleteLater();
}
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
index d4daea2eb3..8e7b8df120 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
@@ -59,9 +59,9 @@ class QIBusFilterEventWatcher: public QDBusPendingCallWatcher
{
public:
explicit QIBusFilterEventWatcher(const QDBusPendingCall &call,
- QObject *parent = 0,
- QWindow *window = 0,
- const Qt::KeyboardModifiers modifiers = 0,
+ QObject *parent = nullptr,
+ QWindow *window = nullptr,
+ const Qt::KeyboardModifiers modifiers = nullptr,
const QVariantList arguments = QVariantList())
: QDBusPendingCallWatcher(call, parent)
, m_window(window)
diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxy.h b/src/plugins/platforminputcontexts/ibus/qibusproxy.h
index 839e972c34..c9876deebf 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusproxy.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusproxy.h
@@ -35,7 +35,7 @@ public:
{ return QStringLiteral("org.freedesktop.DBus.Properties"); }
public:
- QIBusProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+ QIBusProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~QIBusProxy();
diff --git a/src/plugins/platforminputcontexts/platforminputcontexts.pro b/src/plugins/platforminputcontexts/platforminputcontexts.pro
index ed6b1b8702..56a39a49e7 100644
--- a/src/plugins/platforminputcontexts/platforminputcontexts.pro
+++ b/src/plugins/platforminputcontexts/platforminputcontexts.pro
@@ -1,10 +1,11 @@
TEMPLATE = subdirs
QT_FOR_CONFIG += gui-private
-qtHaveModule(dbus) {
-!mac:!win32:SUBDIRS += ibus
-}
-
-qtConfig(xcb): SUBDIRS += compose
+qtConfig(xkbcommon) {
+ SUBDIRS += compose
+ qtHaveModule(dbus) {
+ !macos:!win32:SUBDIRS += ibus
+ }
+}
diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro
index 73db9e93a3..78632a9bea 100644
--- a/src/plugins/platforms/android/android.pro
+++ b/src/plugins/platforms/android/android.pro
@@ -20,6 +20,7 @@ INCLUDEPATH += \
$$QT_SOURCE_TREE/src/3rdparty/android
SOURCES += $$PWD/androidplatformplugin.cpp \
+ $$PWD/androidcontentfileengine.cpp \
$$PWD/androiddeadlockprotector.cpp \
$$PWD/androidjnimain.cpp \
$$PWD/androidjniaccessibility.cpp \
@@ -46,9 +47,11 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/qandroidplatformopenglcontext.cpp \
$$PWD/qandroidplatformforeignwindow.cpp \
$$PWD/qandroideventdispatcher.cpp \
- $$PWD/qandroidplatformoffscreensurface.cpp
+ $$PWD/qandroidplatformoffscreensurface.cpp \
+ $$PWD/qandroidplatformfiledialoghelper.cpp
HEADERS += $$PWD/qandroidplatformintegration.h \
+ $$PWD/androidcontentfileengine.h \
$$PWD/androiddeadlockprotector.h \
$$PWD/androidjnimain.h \
$$PWD/androidjniaccessibility.h \
@@ -75,7 +78,8 @@ HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/qandroidplatformopenglcontext.h \
$$PWD/qandroidplatformforeignwindow.h \
$$PWD/qandroideventdispatcher.h \
- $$PWD/qandroidplatformoffscreensurface.h
+ $$PWD/qandroidplatformoffscreensurface.h \
+ $$PWD/qandroidplatformfiledialoghelper.h
qtConfig(android-style-assets): SOURCES += $$PWD/extract.cpp
else: SOURCES += $$PWD/extract-dummy.cpp
diff --git a/src/plugins/platforms/mirclient/qmirclientappstatecontroller.cpp b/src/plugins/platforms/android/androidcontentfileengine.cpp
index 69fc9b7aa7..1444407195 100644
--- a/src/plugins/platforms/mirclient/qmirclientappstatecontroller.cpp
+++ b/src/plugins/platforms/android/androidcontentfileengine.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2019 Volker Krause <vkrause@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -37,66 +37,56 @@
**
****************************************************************************/
+#include "androidcontentfileengine.h"
-#include "qmirclientappstatecontroller.h"
+#include <private/qjni_p.h>
+#include <private/qjnihelpers_p.h>
-#include <qpa/qwindowsysteminterface.h>
+#include <QDebug>
-/*
- * QMirClientAppStateController - updates Qt's QApplication::applicationState property.
- *
- * Tries to avoid active-inactive-active invocations using a timer. The rapid state
- * change can confuse some applications.
- */
-
-QMirClientAppStateController::QMirClientAppStateController()
- : m_suspended(false)
- , m_lastActive(true)
+AndroidContentFileEngine::AndroidContentFileEngine(const QString &fileName)
+ : QFSFileEngine(fileName)
{
- m_inactiveTimer.setSingleShot(true);
- m_inactiveTimer.setInterval(10);
- QObject::connect(&m_inactiveTimer, &QTimer::timeout, []()
- {
- QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
- });
}
-void QMirClientAppStateController::setSuspended()
+bool AndroidContentFileEngine::open(QIODevice::OpenMode openMode)
{
- m_inactiveTimer.stop();
- if (!m_suspended) {
- m_suspended = true;
-
- QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
+ QString openModeStr;
+ if (openMode & QFileDevice::ReadOnly) {
+ openModeStr += QLatin1Char('r');
+ }
+ if (openMode & QFileDevice::WriteOnly) {
+ openModeStr += QLatin1Char('w');
+ }
+ if (openMode & QFileDevice::Truncate) {
+ openModeStr += QLatin1Char('t');
+ } else if (openMode & QFileDevice::Append) {
+ openModeStr += QLatin1Char('a');
}
-}
-void QMirClientAppStateController::setResumed()
-{
- m_inactiveTimer.stop();
- if (m_suspended) {
- m_suspended = false;
+ const auto fd = QJNIObjectPrivate::callStaticMethod<jint>("org/qtproject/qt5/android/QtNative",
+ "openFdForContentUrl",
+ "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I",
+ QtAndroidPrivate::context(),
+ QJNIObjectPrivate::fromString(fileName(DefaultName)).object(),
+ QJNIObjectPrivate::fromString(openModeStr).object());
- if (m_lastActive) {
- QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
- } else {
- QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
- }
+ if (fd < 0) {
+ return false;
}
+
+ return QFSFileEngine::open(openMode, fd, QFile::AutoCloseHandle);
}
-void QMirClientAppStateController::setWindowFocused(bool focused)
-{
- if (m_suspended) {
- return;
- }
- if (focused) {
- m_inactiveTimer.stop();
- QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
- } else {
- m_inactiveTimer.start();
+AndroidContentFileEngineHandler::AndroidContentFileEngineHandler() = default;
+AndroidContentFileEngineHandler::~AndroidContentFileEngineHandler() = default;
+
+QAbstractFileEngine* AndroidContentFileEngineHandler::create(const QString &fileName) const
+{
+ if (!fileName.startsWith(QLatin1String("content"))) {
+ return nullptr;
}
- m_lastActive = focused;
+ return new AndroidContentFileEngine(fileName);
}
diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.h b/src/plugins/platforms/android/androidcontentfileengine.h
index 207d97b5af..db3def03d6 100644
--- a/src/plugins/platforms/mirclient/qmirclientplugin.h
+++ b/src/plugins/platforms/android/androidcontentfileengine.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2019 Volker Krause <vkrause@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -37,20 +37,24 @@
**
****************************************************************************/
+#ifndef ANDROIDCONTENTFILEENGINE_H
+#define ANDROIDCONTENTFILEENGINE_H
-#ifndef QMIRCLIENTPLUGIN_H
-#define QMIRCLIENTPLUGIN_H
+#include <private/qfsfileengine_p.h>
-#include <qpa/qplatformintegrationplugin.h>
-
-class QMirClientIntegrationPlugin : public QPlatformIntegrationPlugin
+class AndroidContentFileEngine : public QFSFileEngine
{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "mirclient.json")
+public:
+ AndroidContentFileEngine(const QString &fileName);
+ bool open(QIODevice::OpenMode openMode) override;
+};
+class AndroidContentFileEngineHandler : public QAbstractFileEngineHandler
+{
public:
- QPlatformIntegration *create(const QString &system, const QStringList &paramList,
- int &argc, char **argv) override;
+ AndroidContentFileEngineHandler();
+ ~AndroidContentFileEngineHandler();
+ QAbstractFileEngine *create(const QString &fileName) const override;
};
-#endif // QMIRCLIENTPLUGIN_H
+#endif // ANDROIDCONTENTFILEENGINE_H
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index 309e41bfd6..d4b7f38bf6 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -329,10 +329,7 @@ if (!clazz) { \
GET_AND_CHECK_STATIC_METHOD(m_setFocusedMethodID, nodeInfoClass, "setFocused", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setScrollableMethodID, nodeInfoClass, "setScrollable", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setVisibleToUserMethodID, nodeInfoClass, "setVisibleToUser", "(Z)V");
-
- if (QtAndroidPrivate::androidSdkVersion() >= 18) {
- GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V");
- }
+ GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V");
return true;
}
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 74edfd8356..70dde46ffa 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -49,6 +49,7 @@
#include "androidjniinput.h"
#include "androidjniclipboard.h"
#include "androidjnimenu.h"
+#include "androidcontentfileengine.h"
#include "androiddeadlockprotector.h"
#include "qandroidplatformdialoghelpers.h"
#include "qandroidplatformintegration.h"
@@ -116,6 +117,7 @@ static double m_scaledDensity = 0;
static double m_density = 1.0;
static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = nullptr;
+static AndroidContentFileEngineHandler *m_androidContentFileEngineHandler = nullptr;
@@ -445,6 +447,7 @@ static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring pa
{
m_androidPlatformIntegration = nullptr;
m_androidAssetsFileEngineHandler = new AndroidAssetsFileEngineHandler();
+ m_androidContentFileEngineHandler = new AndroidContentFileEngineHandler();
m_mainLibraryHnd = nullptr;
{ // Set env. vars
const char *nativeString = env->GetStringUTFChars(environmentString, 0);
@@ -482,7 +485,7 @@ static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring pa
}
if (Q_UNLIKELY(!m_main)) {
- qCritical() << "dlsym failed:" << dlerror() << endl
+ qCritical() << "dlsym failed:" << dlerror() << Qt::endl
<< "Could not find main method";
return false;
}
@@ -555,6 +558,8 @@ static void quitQtAndroidPlugin(JNIEnv *env, jclass /*clazz*/)
m_androidPlatformIntegration = nullptr;
delete m_androidAssetsFileEngineHandler;
m_androidAssetsFileEngineHandler = nullptr;
+ delete m_androidContentFileEngineHandler;
+ m_androidContentFileEngineHandler = nullptr;
}
static void terminateQt(JNIEnv *env, jclass /*clazz*/)
diff --git a/src/plugins/platforms/android/extract-dummy.cpp b/src/plugins/platforms/android/extract-dummy.cpp
index d07fbe1ba7..fdce8ec64c 100644
--- a/src/plugins/platforms/android/extract-dummy.cpp
+++ b/src/plugins/platforms/android/extract-dummy.cpp
@@ -40,16 +40,6 @@
#include <jni.h>
#include <extract.h>
-extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo(JNIEnv *, jobject, Res_png_9patch*)
-{
- return 0;
-}
-
-extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractChunkInfo(JNIEnv *, jobject, jbyteArray)
-{
- return 0;
-}
-
extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo20(JNIEnv *, jobject, long)
{
return 0;
diff --git a/src/plugins/platforms/android/extract.cpp b/src/plugins/platforms/android/extract.cpp
index 2f2ffa7126..acffa353f1 100644
--- a/src/plugins/platforms/android/extract.cpp
+++ b/src/plugins/platforms/android/extract.cpp
@@ -48,46 +48,6 @@
#define LOG_TAG "extractSyleInfo"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
-extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo(JNIEnv * env, jobject, Res_png_9patch* chunk)
-{
- Res_png_9patch::deserialize(chunk);
- //printChunkInformation(chunk);
- jintArray result;
- size_t size = 3+chunk->numXDivs+chunk->numYDivs+chunk->numColors;
- result = env->NewIntArray(size);
- if (!result)
- return 0;
-
- jint *data = (jint*)malloc(sizeof(jint)*size);
- size_t pos = 0;
- data[pos++]=chunk->numXDivs;
- data[pos++]=chunk->numYDivs;
- data[pos++]=chunk->numColors;
- for (int x = 0; x <chunk->numXDivs; x ++)
- data[pos++]=chunk->xDivs[x];
- for (int y = 0; y <chunk->numYDivs; y ++)
- data[pos++]=chunk->yDivs[y];
- for (int c = 0; c <chunk->numColors; c ++)
- data[pos++]=chunk->colors[c];
- env->SetIntArrayRegion(result, 0, size, data);
- free(data);
- return result;
-}
-
-extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractChunkInfo(JNIEnv * env, jobject obj, jbyteArray chunkObj)
-{
- size_t chunkSize = env->GetArrayLength(chunkObj);
- void* storage = alloca(chunkSize);
- env->GetByteArrayRegion(chunkObj, 0, chunkSize,
- reinterpret_cast<jbyte*>(storage));
-
- if (!env->ExceptionCheck())
- return Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo(env, obj, static_cast<Res_png_9patch*>(storage));
- else
- env->ExceptionClear();
- return 0;
-}
-
// The following part was shamelessly stolen from ResourceTypes.cpp from Android's sources
/*
* Copyright (C) 2005 The Android Open Source Project
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp
index e12551283f..3a1fb7a6de 100644
--- a/src/plugins/platforms/android/qandroideventdispatcher.cpp
+++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp
@@ -78,14 +78,14 @@ void QAndroidEventDispatcher::stop()
void QAndroidEventDispatcher::goingToStop(bool stop)
{
- m_goingToStop.store(stop ? 1 : 0);
+ m_goingToStop.storeRelaxed(stop ? 1 : 0);
if (!stop)
wakeUp();
}
bool QAndroidEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
{
- if (m_goingToStop.load())
+ if (m_goingToStop.loadRelaxed())
flags |= QEventLoop::ExcludeSocketNotifiers | QEventLoop::X11ExcludeTimers;
{
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.h b/src/plugins/platforms/android/qandroideventdispatcher.h
index e6f903bced..4fdd7af7a5 100644
--- a/src/plugins/platforms/android/qandroideventdispatcher.h
+++ b/src/plugins/platforms/android/qandroideventdispatcher.h
@@ -68,7 +68,7 @@ class QAndroidEventDispatcherStopper
{
public:
static QAndroidEventDispatcherStopper *instance();
- static bool stopped() {return !instance()->m_started.load(); }
+ static bool stopped() {return !instance()->m_started.loadRelaxed(); }
void startAll();
void stopAll();
void addEventDispatcher(QAndroidEventDispatcher *dispatcher);
diff --git a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp
new file mode 100644
index 0000000000..4fb271a75c
--- /dev/null
+++ b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB)
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidplatformfiledialoghelper.h"
+
+#include <androidjnimain.h>
+#include <private/qjni_p.h>
+#include <jni.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtAndroidFileDialogHelper {
+
+#define RESULT_OK -1
+#define REQUEST_CODE 1305 // Arbitrary
+
+QAndroidPlatformFileDialogHelper::QAndroidPlatformFileDialogHelper()
+ : QPlatformFileDialogHelper()
+ , m_selectedFile()
+{
+}
+
+bool QAndroidPlatformFileDialogHelper::handleActivityResult(jint requestCode, jint resultCode, jobject data)
+{
+ if (requestCode != REQUEST_CODE)
+ return false;
+
+ if (resultCode == RESULT_OK) {
+ const QJNIObjectPrivate intent = QJNIObjectPrivate::fromLocalRef(data);
+ const QJNIObjectPrivate uri = intent.callObjectMethod("getData", "()Landroid/net/Uri;");
+ const QString uriStr = uri.callObjectMethod("toString", "()Ljava/lang/String;").toString();
+ m_selectedFile = QUrl(uriStr);
+ Q_EMIT fileSelected(m_selectedFile);
+ Q_EMIT accept();
+ } else {
+ Q_EMIT reject();
+ }
+
+ return true;
+}
+
+bool QAndroidPlatformFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
+{
+ Q_UNUSED(windowFlags)
+ Q_UNUSED(windowModality)
+ Q_UNUSED(parent)
+
+ if (options()->fileMode() != QFileDialogOptions::FileMode::ExistingFile)
+ return false;
+
+ QtAndroidPrivate::registerActivityResultListener(this);
+
+ const QJNIObjectPrivate ACTION_OPEN_DOCUMENT = QJNIObjectPrivate::getStaticObjectField("android/content/Intent", "ACTION_OPEN_DOCUMENT", "Ljava/lang/String;");
+ QJNIObjectPrivate intent("android/content/Intent", "(Ljava/lang/String;)V", ACTION_OPEN_DOCUMENT.object());
+ const QJNIObjectPrivate CATEGORY_OPENABLE = QJNIObjectPrivate::getStaticObjectField("android/content/Intent", "CATEGORY_OPENABLE", "Ljava/lang/String;");
+ intent.callObjectMethod("addCategory", "(Ljava/lang/String;)Landroid/content/Intent;", CATEGORY_OPENABLE.object());
+ intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", QJNIObjectPrivate::fromString(QStringLiteral("*/*")).object());
+
+ const QJNIObjectPrivate activity(QtAndroid::activity());
+ activity.callMethod<void>("startActivityForResult", "(Landroid/content/Intent;I)V", intent.object(), REQUEST_CODE);
+
+ return true;
+}
+
+void QAndroidPlatformFileDialogHelper::exec()
+{
+}
+
+void QAndroidPlatformFileDialogHelper::hide()
+{
+}
+
+QString QAndroidPlatformFileDialogHelper::selectedNameFilter() const
+{
+ return QString();
+}
+
+void QAndroidPlatformFileDialogHelper::selectNameFilter(const QString &filter)
+{
+ Q_UNUSED(filter)
+}
+
+void QAndroidPlatformFileDialogHelper::setFilter()
+{
+}
+
+QList<QUrl> QAndroidPlatformFileDialogHelper::selectedFiles() const
+{
+ return {m_selectedFile};
+}
+
+void QAndroidPlatformFileDialogHelper::selectFile(const QUrl &file)
+{
+ Q_UNUSED(file)
+}
+
+QUrl QAndroidPlatformFileDialogHelper::directory() const
+{
+ return QUrl();
+}
+
+void QAndroidPlatformFileDialogHelper::setDirectory(const QUrl &directory)
+{
+ Q_UNUSED(directory)
+}
+
+bool QAndroidPlatformFileDialogHelper::defaultNameFilterDisables() const
+{
+ return false;
+}
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h
new file mode 100644
index 0000000000..e445aa2fef
--- /dev/null
+++ b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB)
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDPLATFORMFILEDIALOGHELPER_H
+#define QANDROIDPLATFORMFILEDIALOGHELPER_H
+
+#include <jni.h>
+#include <qpa/qplatformdialoghelper.h>
+#include <QtCore/private/qjnihelpers_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtAndroidFileDialogHelper {
+
+class QAndroidPlatformFileDialogHelper: public QPlatformFileDialogHelper, public QtAndroidPrivate::ActivityResultListener
+{
+ Q_OBJECT
+
+public:
+ QAndroidPlatformFileDialogHelper();
+ void exec() override;
+
+ bool show(Qt::WindowFlags windowFlags,
+ Qt::WindowModality windowModality,
+ QWindow *parent) override;
+ void hide() override;
+
+ QString selectedNameFilter() const override;
+ void selectNameFilter(const QString &filter) override;
+ void setFilter() override;
+ QList<QUrl> selectedFiles() const override;
+ void selectFile(const QUrl &file) override;
+ QUrl directory() const override;
+ void setDirectory(const QUrl &directory) override;
+ bool defaultNameFilterDisables() const override;
+ bool handleActivityResult(jint requestCode, jint resultCode, jobject data) override;
+
+private:
+ QUrl m_selectedFile;
+};
+
+}
+QT_END_NAMESPACE
+
+#endif // QANDROIDPLATFORMFILEDIALOGHELPER_H
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp
index b891407c44..a78a62337f 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp
@@ -44,6 +44,7 @@
#include "qandroidplatformmenu.h"
#include "qandroidplatformmenuitem.h"
#include "qandroidplatformdialoghelpers.h"
+#include "qandroidplatformfiledialoghelper.h"
#include <QCoreApplication>
#include <QDebug>
@@ -512,6 +513,8 @@ bool QAndroidPlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType t
{
if (type == MessageDialog)
return qEnvironmentVariableIntValue("QT_USE_ANDROID_NATIVE_DIALOGS") == 1;
+ if (type == FileDialog)
+ return true;
return false;
}
@@ -520,6 +523,8 @@ QPlatformDialogHelper *QAndroidPlatformTheme::createPlatformDialogHelper(QPlatfo
switch (type) {
case MessageDialog:
return new QtAndroidDialogHelpers::QAndroidPlatformMessageDialogHelper;
+ case FileDialog:
+ return new QtAndroidFileDialogHelper::QAndroidPlatformFileDialogHelper;
default:
return 0;
}
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h
index f2e51bd3df..5edd274759 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformwindow.h
@@ -65,6 +65,9 @@ public:
void setParent(const QPlatformWindow *window) override;
WId winId() const override { return m_windowId; }
+ bool setMouseGrabEnabled(bool grab) override { return false; }
+ bool setKeyboardGrabEnabled(bool grab) override { return false; }
+
QAndroidPlatformScreen *platformScreen() const;
void propagateSizeHints() override;
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 368cf56c80..db4ec251ae 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -177,7 +177,7 @@ NSString *macRole(QAccessibleInterface *interface)
if (roleMap.isEmpty())
populateRoleMap();
- // MAC_ACCESSIBILTY_DEBUG() << "role for" << interface.object() << "interface role" << hex << qtRole;
+ // MAC_ACCESSIBILTY_DEBUG() << "role for" << interface.object() << "interface role" << Qt::hex << qtRole;
if (roleMap.contains(qtRole)) {
// MAC_ACCESSIBILTY_DEBUG() << "return" << roleMap[qtRole];
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
index 914aaa2b1b..7fbe729381 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
@@ -52,7 +52,7 @@
@class QT_MANGLE_NAMESPACE(QMacAccessibilityElement);
-@interface QT_MANGLE_NAMESPACE(QMacAccessibilityElement) : NSObject
+@interface QT_MANGLE_NAMESPACE(QMacAccessibilityElement) : NSObject <NSAccessibilityElement>
- (instancetype)initWithId:(QAccessible::Id)anId;
+ (instancetype)elementWithId:(QAccessible::Id)anId;
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index f26263261c..3560c9d9b5 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -51,6 +51,19 @@ QT_USE_NAMESPACE
#ifndef QT_NO_ACCESSIBILITY
+/**
+ * Converts between absolute character offsets and line numbers of a
+ * QAccessibleTextInterface. Works in exactly one of two modes:
+ *
+ * - Pass *line == -1 in order to get a line containing character at the given
+ * *offset
+ * - Pass *offset == -1 in order to get the offset of first character of the
+ * given *line
+ *
+ * You can optionally also pass non-NULL `start` and `end`, which will in both
+ * modes be filled with the offset of the first and last characters of the
+ * relevant line.
+ */
static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *offset, NSUInteger *start = 0, NSUInteger *end = 0)
{
Q_ASSERT(*line == -1 || *offset == -1);
@@ -161,6 +174,17 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
// accessibility protocol
//
+- (BOOL)isAccessibilityFocused
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid()) {
+ return false;
+ }
+ // Just check if the app thinks we're focused.
+ id focusedElement = NSApp.accessibilityApplicationFocusedUIElement;
+ return [focusedElement isEqual:self];
+}
+
// attributes
+ (id) lineNumberForIndex: (int)index forText:(const QString &)text
@@ -174,57 +198,61 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
return YES;
}
-- (NSArray<NSString *> *)accessibilityAttributeNames {
- static NSArray<NSString *> *defaultAttributes = [@[
- NSAccessibilityRoleAttribute,
- NSAccessibilityRoleDescriptionAttribute,
- NSAccessibilitySubroleAttribute,
- NSAccessibilityChildrenAttribute,
- NSAccessibilityFocusedAttribute,
- NSAccessibilityParentAttribute,
- NSAccessibilityWindowAttribute,
- NSAccessibilityTopLevelUIElementAttribute,
- NSAccessibilityPositionAttribute,
- NSAccessibilitySizeAttribute,
- NSAccessibilityTitleAttribute,
- NSAccessibilityDescriptionAttribute,
- NSAccessibilityEnabledAttribute
- ] retain];
+- (NSString *) accessibilityRole {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return NSAccessibilityUnknownRole;
+ return QCocoaAccessible::macRole(iface);
+}
+- (NSString *) accessibilitySubRole {
QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
if (!iface || !iface->isValid())
- return defaultAttributes;
+ return NSAccessibilityUnknownRole;
+ return QCocoaAccessible::macSubrole(iface);
+}
- NSMutableArray<NSString *> *attributes = [[NSMutableArray<NSString *> alloc] initWithCapacity:defaultAttributes.count];
- [attributes addObjectsFromArray:defaultAttributes];
+- (NSString *) accessibilityRoleDescription {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return NSAccessibilityUnknownRole;
+ return NSAccessibilityRoleDescription(self.accessibilityRole, self.accessibilitySubRole);
+}
- if (QCocoaAccessible::hasValueAttribute(iface)) {
- [attributes addObject:NSAccessibilityValueAttribute];
- }
+- (NSArray *) accessibilityChildren {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return nil;
+ return QCocoaAccessible::unignoredChildren(iface);
+}
- if (iface->textInterface()) {
- [attributes addObjectsFromArray:@[
- NSAccessibilityNumberOfCharactersAttribute,
- NSAccessibilitySelectedTextAttribute,
- NSAccessibilitySelectedTextRangeAttribute,
- NSAccessibilityVisibleCharacterRangeAttribute,
- NSAccessibilityInsertionPointLineNumberAttribute
- ]];
-
-// TODO: multi-selection: NSAccessibilitySelectedTextRangesAttribute,
- }
+- (id) accessibilityWindow {
+ // We're in the same window as our parent.
+ return [self.accessibilityParent accessibilityWindow];
+}
- if (iface->valueInterface()) {
- [attributes addObjectsFromArray:@[
- NSAccessibilityMinValueAttribute,
- NSAccessibilityMaxValueAttribute
- ]];
- }
+- (id) accessibilityTopLevelUIElementAttribute {
+ // We're in the same top level element as our parent.
+ return [self.accessibilityParent accessibilityTopLevelUIElementAttribute];
+}
- return [attributes autorelease];
+- (NSString *) accessibilityTitle {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return nil;
+ if (iface->role() == QAccessible::StaticText)
+ return nil;
+ return iface->text(QAccessible::Name).toNSString();
+}
+
+- (BOOL) accessibilityEnabledAttribute {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return false;
+ return !iface->state().disabled;
}
-- (id)parentElement {
+- (id)accessibilityParent {
QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
if (!iface || !iface->isValid())
return nil;
@@ -237,7 +265,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
if (QAccessibleInterface *parent = iface->parent()) {
if (parent->role() != QAccessible::Application) {
QAccessible::Id parentId = QAccessible::uniqueId(parent);
- return [QMacAccessibilityElement elementWithId: parentId];
+ return NSAccessibilityUnignoredAncestor([QMacAccessibilityElement elementWithId: parentId]);
}
}
@@ -245,123 +273,130 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
QPlatformWindow *platformWindow = window->handle();
if (platformWindow) {
QCocoaWindow *win = static_cast<QCocoaWindow*>(platformWindow);
- return qnsview_cast(win->view());
+ return NSAccessibilityUnignoredAncestor(qnsview_cast(win->view()));
}
}
return nil;
}
+- (NSRect)accessibilityFrame {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return NSZeroRect;
+ return QCocoaScreen::mapToNative(iface->rect());
+}
-- (id) minValueAttribute:(QAccessibleInterface*)iface {
+- (NSString*)accessibilityLabel {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid()) {
+ qWarning() << "Called accessibilityLabel on invalid object: " << axid;
+ return nil;
+ }
+ return iface->text(QAccessible::Description).toNSString();
+}
+
+- (void)setAccessibilityLabel:(NSString*)label{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return;
+ iface->setText(QAccessible::Description, QString::fromNSString(label));
+}
+
+- (id) accessibilityMinValue:(QAccessibleInterface*)iface {
if (QAccessibleValueInterface *val = iface->valueInterface())
return @(val->minimumValue().toDouble());
return nil;
}
-- (id) maxValueAttribute:(QAccessibleInterface*)iface {
+- (id) accessibilityMaxValue:(QAccessibleInterface*)iface {
if (QAccessibleValueInterface *val = iface->valueInterface())
return @(val->maximumValue().toDouble());
return nil;
}
-- (id)accessibilityAttributeValue:(NSString *)attribute {
+- (id) accessibilityValue {
QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid()) {
- qWarning() << "Called attribute on invalid object: " << axid;
+ if (!iface || !iface->isValid())
return nil;
- }
- if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
- return QCocoaAccessible::macRole(iface);
- } else if ([attribute isEqualToString:NSAccessibilitySubroleAttribute]) {
- return QCocoaAccessible::macSubrole(iface);
- } else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
- return NSAccessibilityRoleDescription(QCocoaAccessible::macRole(iface),
- [self accessibilityAttributeValue:NSAccessibilitySubroleAttribute]);
- } else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
- return QCocoaAccessible::unignoredChildren(iface);
- } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
- // Just check if the app thinks we're focused.
- id focusedElement = [NSApp accessibilityAttributeValue:NSAccessibilityFocusedUIElementAttribute];
- return @([focusedElement isEqual:self]);
- } else if ([attribute isEqualToString:NSAccessibilityParentAttribute]) {
- return NSAccessibilityUnignoredAncestor([self parentElement]);
- } else if ([attribute isEqualToString:NSAccessibilityWindowAttribute]) {
- // We're in the same window as our parent.
- return [[self parentElement] accessibilityAttributeValue:NSAccessibilityWindowAttribute];
- } else if ([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute]) {
- // We're in the same top level element as our parent.
- return [[self parentElement] accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute];
- } else if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) {
- // The position in points of the element's lower-left corner in screen-relative coordinates
- QPointF qtPosition = QRectF(iface->rect()).bottomLeft();
- return [NSValue valueWithPoint:QCocoaScreen::mapToNative(qtPosition)];
- } else if ([attribute isEqualToString:NSAccessibilitySizeAttribute]) {
- QSize qtSize = iface->rect().size();
- return [NSValue valueWithSize: NSMakeSize(qtSize.width(), qtSize.height())];
- } else if ([attribute isEqualToString:NSAccessibilityTitleAttribute]) {
- if (iface->role() == QAccessible::StaticText)
- return nil;
- return iface->text(QAccessible::Name).toNSString();
- } else if ([attribute isEqualToString:NSAccessibilityDescriptionAttribute]) {
- return iface->text(QAccessible::Description).toNSString();
- } else if ([attribute isEqualToString:NSAccessibilityEnabledAttribute]) {
- return @(!iface->state().disabled);
- } else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
- // VoiceOver asks for the value attribute for all elements. Return nil
- // if we don't want the element to have a value attribute.
- if (!QCocoaAccessible::hasValueAttribute(iface))
- return nil;
+ // VoiceOver asks for the value attribute for all elements. Return nil
+ // if we don't want the element to have a value attribute.
+ if (!QCocoaAccessible::hasValueAttribute(iface))
+ return nil;
- return QCocoaAccessible::getValueAttribute(iface);
+ return QCocoaAccessible::getValueAttribute(iface);
+}
+
+- (NSInteger) accessibilityNumberOfCharacters {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return 0;
+ if (QAccessibleTextInterface *text = iface->textInterface())
+ return text->characterCount();
+ return 0;
+}
- } else if ([attribute isEqualToString:NSAccessibilityNumberOfCharactersAttribute]) {
- if (QAccessibleTextInterface *text = iface->textInterface())
- return @(text->characterCount());
+- (NSString *) accessibilitySelectedText {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
return nil;
- } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
- if (QAccessibleTextInterface *text = iface->textInterface()) {
- int start = 0;
- int end = 0;
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ int start = 0;
+ int end = 0;
+ text->selection(0, &start, &end);
+ return text->text(start, end).toNSString();
+ }
+ return nil;
+}
+
+- (NSRange) accessibilitySelectedTextRange {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return NSRange();
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ int start = 0;
+ int end = 0;
+ if (text->selectionCount() > 0) {
text->selection(0, &start, &end);
- return text->text(start, end).toNSString();
- }
- return nil;
- } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
- if (QAccessibleTextInterface *text = iface->textInterface()) {
- int start = 0;
- int end = 0;
- if (text->selectionCount() > 0) {
- text->selection(0, &start, &end);
- } else {
- start = text->cursorPosition();
- end = start;
- }
- return [NSValue valueWithRange:NSMakeRange(quint32(start), quint32(end - start))];
- }
- return [NSValue valueWithRange: NSMakeRange(0, 0)];
- } else if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
- // FIXME This is not correct and may impact performance for big texts
- if (QAccessibleTextInterface *text = iface->textInterface())
- return [NSValue valueWithRange: NSMakeRange(0, text->characterCount())];
- return [NSValue valueWithRange: NSMakeRange(0, iface->text(QAccessible::Name).length())];
- } else if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) {
- if (QAccessibleTextInterface *text = iface->textInterface()) {
- int line = 0; // true for all single line edits
- if (iface->state().multiLine) {
- int position = text->cursorPosition();
- convertLineOffset(text, &line, &position);
- }
- return @(line);
+ } else {
+ start = text->cursorPosition();
+ end = start;
}
- return nil;
- } else if ([attribute isEqualToString:NSAccessibilityMinValueAttribute]) {
- return [self minValueAttribute:iface];
- } else if ([attribute isEqualToString:NSAccessibilityMaxValueAttribute]) {
- return [self maxValueAttribute:iface];
+ return NSMakeRange(quint32(start), quint32(end - start));
}
+ return NSMakeRange(0, 0);
+}
- return nil;
+- (NSInteger)accessibilityLineForIndex:(NSInteger)index {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return 0;
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ QString textToPos = text->text(0, index);
+ return textToPos.count('\n');
+ }
+ return 0;
+}
+
+- (NSRange)accessibilityVisibleCharacterRange {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return NSRange();
+ // FIXME This is not correct and may impact performance for big texts
+ if (QAccessibleTextInterface *text = iface->textInterface())
+ return NSMakeRange(0, static_cast<uint>(text->characterCount()));
+ return NSMakeRange(0, static_cast<uint>(iface->text(QAccessible::Name).length()));
+}
+
+- (NSInteger) accessibilityInsertionPointLineNumber {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return 0;
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ int position = text->cursorPosition();
+ return [self accessibilityLineForIndex:position];
+ }
+ return 0;
}
- (NSArray *)accessibilityParameterizedAttributeNames {
@@ -408,8 +443,11 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
int index = [parameter intValue];
if (index < 0 || index > iface->textInterface()->characterCount())
return nil;
- int line = -1;
- convertLineOffset(iface->textInterface(), &line, &index);
+ int line = 0; // true for all single line edits
+ if (iface->state().multiLine) {
+ line = -1;
+ convertLineOffset(iface->textInterface(), &line, &index);
+ }
return @(line);
}
if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) {
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 78aa98094c..01b4894324 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -292,18 +292,6 @@ void QNSWindowBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const
// ----------------------------------------------------------------------------
-// https://stackoverflow.com/a/52722575/2761869
-template<class R>
-struct backwards_t {
- R r;
- constexpr auto begin() const { using std::rbegin; return rbegin(r); }
- constexpr auto begin() { using std::rbegin; return rbegin(r); }
- constexpr auto end() const { using std::rend; return rend(r); }
- constexpr auto end() { using std::rend; return rend(r); }
-};
-template<class R>
-constexpr backwards_t<R> backwards(R&& r) { return {std::forward<R>(r)}; }
-
QCALayerBackingStore::QCALayerBackingStore(QWindow *window)
: QPlatformBackingStore(window)
{
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index d1695ea860..5f32400af0 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -51,7 +51,6 @@
#include "qt_mac_p.h"
#include "qcocoahelpers.h"
#include "qcocoaeventdispatcher.h"
-#include <qregexp.h>
#include <qbuffer.h>
#include <qdebug.h>
#include <qstringlist.h>
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index d0100d0410..0f8fec0548 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -86,7 +86,7 @@ QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context)
}
m_context = nativeHandle.value<QCocoaNativeContext>().context();
if (!m_context) {
- qCWarning(lcQpaOpenGLContext, "QCocoaNativeContext's NSOpenGLContext can not be null");
+ qCWarning(lcQpaOpenGLContext, "QCocoaNativeContext's NSOpenGLContext cannot be null");
return;
}
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 69aa7937b6..69a1854598 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -176,6 +176,18 @@ T qt_mac_resolveOption(const T &fallback, QWindow *window, const QByteArray &pro
return fallback;
}
+// https://stackoverflow.com/a/52722575/2761869
+template<class R>
+struct backwards_t {
+ R r;
+ constexpr auto begin() const { using std::rbegin; return rbegin(r); }
+ constexpr auto begin() { using std::rbegin; return rbegin(r); }
+ constexpr auto end() const { using std::rend; return rend(r); }
+ constexpr auto end() { using std::rend; return rend(r); }
+};
+template<class R>
+constexpr backwards_t<R> backwards(R&& r) { return {std::forward<R>(r)}; }
+
// -------------------------------------------------------------------------
#if !defined(Q_PROCESSOR_X86_64)
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index d36a7f6d09..c9eafa81d0 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
Q_LOGGING_CATEGORY(lcQpaDrawing, "qt.qpa.drawing");
Q_LOGGING_CATEGORY(lcQpaMouse, "qt.qpa.input.mouse", QtCriticalMsg);
-Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen");
+Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen", QtCriticalMsg);
//
// Conversion Functions
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index ecbd19c9a2..bfc3bfe9de 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -61,8 +61,6 @@
QT_BEGIN_NAMESPACE
-class QCocoaScreen;
-
class QCocoaIntegration : public QObject, public QPlatformIntegration
{
Q_OBJECT
@@ -113,9 +111,6 @@ public:
Qt::KeyboardModifiers queryKeyboardModifiers() const override;
QList<int> possibleKeys(const QKeyEvent *event) const override;
- void updateScreens();
- QCocoaScreen *screenForNSScreen(NSScreen *nsScreen);
-
void setToolbar(QWindow *window, NSToolbar *toolbar);
NSToolbar *toolbar(QWindow *window) const;
void clearToolbars();
@@ -143,8 +138,6 @@ private:
QScopedPointer<QCocoaAccessibility> mAccessibility;
#endif
QScopedPointer<QPlatformTheme> mPlatformTheme;
- QList<QCocoaScreen *> mScreens;
- QMacNotificationObserver m_screensObserver;
#ifndef QT_NO_CLIPBOARD
QCocoaClipboard *mCocoaClipboard;
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 232c74b1e9..300082d694 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -207,9 +207,7 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
// which will resolve to an actual value and result in screen invalidation.
cocoaApplication.presentationOptions = NSApplicationPresentationDefault;
- m_screensObserver = QMacNotificationObserver([NSApplication sharedApplication],
- NSApplicationDidChangeScreenParametersNotification, [&]() { updateScreens(); });
- updateScreens();
+ QCocoaScreen::initializeScreens();
QMacInternalPasteboardMime::initializeMimeTypes();
QCocoaMimeTypes::initializeMimeTypes();
@@ -242,10 +240,7 @@ QCocoaIntegration::~QCocoaIntegration()
QMacInternalPasteboardMime::destroyMimeTypes();
#endif
- // Delete screens in reverse order to avoid crash in case of multiple screens
- while (!mScreens.isEmpty()) {
- QWindowSystemInterface::handleScreenRemoved(mScreens.takeLast());
- }
+ QCocoaScreen::cleanupScreens();
clearToolbars();
}
@@ -260,88 +255,6 @@ QCocoaIntegration::Options QCocoaIntegration::options() const
return mOptions;
}
-/*!
- \brief Synchronizes the screen list, adds new screens, removes deleted ones
-*/
-void QCocoaIntegration::updateScreens()
-{
- NSArray<NSScreen *> *scrs = [NSScreen screens];
- NSMutableArray<NSScreen *> *screens = [NSMutableArray<NSScreen *> arrayWithArray:scrs];
- if ([screens count] == 0)
- if ([NSScreen mainScreen])
- [screens addObject:[NSScreen mainScreen]];
- if ([screens count] == 0)
- return;
- QSet<QCocoaScreen*> remainingScreens = QSet<QCocoaScreen*>::fromList(mScreens);
- QList<QPlatformScreen *> siblings;
- uint screenCount = [screens count];
- for (uint i = 0; i < screenCount; i++) {
- NSScreen* scr = [screens objectAtIndex:i];
- CGDirectDisplayID dpy = scr.qt_displayId;
- // If this screen is a mirror and is not the primary one of the mirror set, ignore it.
- // Exception: The NSScreen API has been observed to a return a screen list with one
- // mirrored, non-primary screen when Qt is running as a startup item. Always use the
- // screen if there's only one screen in the list.
- if (screenCount > 1 && CGDisplayIsInMirrorSet(dpy)) {
- CGDirectDisplayID primary = CGDisplayMirrorsDisplay(dpy);
- if (primary != kCGNullDirectDisplay && primary != dpy)
- continue;
- }
- QCocoaScreen* screen = nullptr;
- foreach (QCocoaScreen* existingScr, mScreens) {
- // NSScreen documentation says do not cache the array returned from [NSScreen screens].
- // However in practice, we can identify a screen by its pointer: if resolution changes,
- // the NSScreen object will be the same instance, just with different values.
- if (existingScr->nativeScreen() == scr) {
- screen = existingScr;
- break;
- }
- }
- if (screen) {
- remainingScreens.remove(screen);
- screen->updateProperties();
- } else {
- screen = new QCocoaScreen(i);
- mScreens.append(screen);
- qCDebug(lcQpaScreen) << "Adding" << screen;
- QWindowSystemInterface::handleScreenAdded(screen);
- }
- siblings << screen;
- }
-
- // Set virtual siblings list. All screens in mScreens are siblings, because we ignored the
- // mirrors. Note that some of the screens we update the siblings list for here may be deleted
- // below, but update anyway to keep the to-be-deleted screens out of the siblings list.
- foreach (QCocoaScreen* screen, mScreens)
- screen->setVirtualSiblings(siblings);
-
- // Now the leftovers in remainingScreens are no longer current, so we can delete them.
- foreach (QCocoaScreen* screen, remainingScreens) {
- mScreens.removeOne(screen);
- // Prevent stale references to NSScreen during destroy
- screen->m_screenIndex = -1;
- qCDebug(lcQpaScreen) << "Removing" << screen;
- QWindowSystemInterface::handleScreenRemoved(screen);
- }
-}
-
-QCocoaScreen *QCocoaIntegration::screenForNSScreen(NSScreen *nsScreen)
-{
- NSUInteger index = [[NSScreen screens] indexOfObject:nsScreen];
- if (index == NSNotFound)
- return nullptr;
-
- if (index >= unsigned(mScreens.count()))
- updateScreens();
-
- for (QCocoaScreen *screen : mScreens) {
- if (screen->nativeScreen() == nsScreen)
- return screen;
- }
-
- return nullptr;
-}
-
bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index ef9b2659d2..c35cf6d799 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -53,6 +53,7 @@
#include <QtGui/private/qcoregraphics_p.h>
#include <QtCore/QDebug>
+#include <QtCore/QRegExp>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.h b/src/plugins/platforms/cocoa/qcocoascreen.h
index 9ded98df32..491af2fe9c 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.h
+++ b/src/plugins/platforms/cocoa/qcocoascreen.h
@@ -48,10 +48,14 @@
QT_BEGIN_NAMESPACE
+class QCocoaIntegration;
+
class QCocoaScreen : public QPlatformScreen
{
public:
- QCocoaScreen(int screenIndex);
+ static void initializeScreens();
+ static void cleanupScreens();
+
~QCocoaScreen();
// ----------------------------------------------------
@@ -61,19 +65,18 @@ public:
QRect availableGeometry() const override { return m_availableGeometry; }
int depth() const override { return m_depth; }
QImage::Format format() const override { return m_format; }
- qreal devicePixelRatio() const override;
+ qreal devicePixelRatio() const override { return m_devicePixelRatio; }
QSizeF physicalSize() const override { return m_physicalSize; }
QDpi logicalDpi() const override { return m_logicalDpi; }
qreal refreshRate() const override { return m_refreshRate; }
QString name() const override { return m_name; }
QPlatformCursor *cursor() const override { return m_cursor; }
QWindow *topLevelAt(const QPoint &point) const override;
- QList<QPlatformScreen *> virtualSiblings() const override { return m_siblings; }
+ QList<QPlatformScreen *> virtualSiblings() const override;
QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const override;
// ----------------------------------------------------
- // Additional methods
- void setVirtualSiblings(const QList<QPlatformScreen *> &siblings) { m_siblings = siblings; }
+
NSScreen *nativeScreen() const;
void updateProperties();
@@ -82,14 +85,21 @@ public:
bool isRunningDisplayLink() const;
static QCocoaScreen *primaryScreen();
+ static QCocoaScreen *get(NSScreen *nsScreen);
+ static QCocoaScreen *get(CGDirectDisplayID displayId);
static CGPoint mapToNative(const QPointF &pos, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
static CGRect mapToNative(const QRectF &rect, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
static QPointF mapFromNative(CGPoint pos, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
static QRectF mapFromNative(CGRect rect, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
-public:
- int m_screenIndex;
+private:
+ QCocoaScreen(CGDirectDisplayID displayId);
+ static void add(CGDirectDisplayID displayId);
+ void remove();
+
+ CGDirectDisplayID m_displayId = 0;
+
QRect m_geometry;
QRect m_availableGeometry;
QDpi m_logicalDpi;
@@ -99,11 +109,13 @@ public:
QImage::Format m_format;
QSizeF m_physicalSize;
QCocoaCursor *m_cursor;
- QList<QPlatformScreen *> m_siblings;
+ qreal m_devicePixelRatio;
CVDisplayLinkRef m_displayLink = nullptr;
dispatch_source_t m_displayLinkSource = nullptr;
QAtomicInt m_pendingUpdates;
+
+ friend QDebug operator<<(QDebug debug, const QCocoaScreen *screen);
};
#ifndef QT_NO_DEBUG_STREAM
@@ -116,5 +128,4 @@ QT_END_NAMESPACE
@property(readonly) CGDirectDisplayID qt_displayId;
@end
-#endif
-
+#endif // QCOCOASCREEN_H
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm
index 6a5b0e6e3e..392099d083 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.mm
+++ b/src/plugins/platforms/cocoa/qcocoascreen.mm
@@ -41,6 +41,7 @@
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
+#include "qcocoaintegration.h"
#include <QtCore/qcoreapplication.h>
#include <QtGui/private/qcoregraphics_p.h>
@@ -53,34 +54,104 @@
QT_BEGIN_NAMESPACE
-class QCoreTextFontEngine;
-class QFontEngineFT;
+void QCocoaScreen::initializeScreens()
+{
+ uint32_t displayCount = 0;
+ if (CGGetActiveDisplayList(0, nullptr, &displayCount) != kCGErrorSuccess)
+ qFatal("Failed to get number of active displays");
+
+ CGDirectDisplayID activeDisplays[displayCount];
+ if (CGGetActiveDisplayList(displayCount, &activeDisplays[0], &displayCount) != kCGErrorSuccess)
+ qFatal("Failed to get active displays");
+
+ for (CGDirectDisplayID displayId : activeDisplays)
+ QCocoaScreen::add(displayId);
+
+ CGDisplayRegisterReconfigurationCallback([](CGDirectDisplayID displayId, CGDisplayChangeSummaryFlags flags, void *userInfo) {
+ if (flags & kCGDisplayBeginConfigurationFlag)
+ return; // Wait for changes to apply
+
+ Q_UNUSED(userInfo);
+
+ QCocoaScreen *cocoaScreen = QCocoaScreen::get(displayId);
+
+ if ((flags & kCGDisplayAddFlag) || !cocoaScreen) {
+ if (!CGDisplayIsActive(displayId)) {
+ qCDebug(lcQpaScreen) << "Not adding inactive display" << displayId;
+ return; // Will be added when activated
+ }
+ QCocoaScreen::add(displayId);
+ } else if ((flags & kCGDisplayRemoveFlag) || !CGDisplayIsActive(displayId)) {
+ cocoaScreen->remove();
+ } else {
+ // Detect changes to the primary screen immediately, instead of
+ // waiting for a display reconfigure with kCGDisplaySetMainFlag.
+ // This ensures that any property updates to the other screens
+ // will be in reference to the correct primary screen.
+ QCocoaScreen *mainDisplay = QCocoaScreen::get(CGMainDisplayID());
+ if (QGuiApplication::primaryScreen()->handle() != mainDisplay) {
+ mainDisplay->updateProperties();
+ qCInfo(lcQpaScreen) << "Primary screen changed to" << mainDisplay;
+ QWindowSystemInterface::handlePrimaryScreenChanged(mainDisplay);
+ }
-QCocoaScreen::QCocoaScreen(int screenIndex)
- : QPlatformScreen(), m_screenIndex(screenIndex), m_refreshRate(60.0)
+ if (cocoaScreen == mainDisplay)
+ return; // Already reconfigured
+
+ cocoaScreen->updateProperties();
+ qCInfo(lcQpaScreen) << "Reconfigured" << cocoaScreen;
+ }
+ }, nullptr);
+}
+
+void QCocoaScreen::add(CGDirectDisplayID displayId)
+{
+ QCocoaScreen *cocoaScreen = new QCocoaScreen(displayId);
+ qCInfo(lcQpaScreen) << "Adding" << cocoaScreen;
+ QWindowSystemInterface::handleScreenAdded(cocoaScreen, CGDisplayIsMain(displayId));
+}
+
+QCocoaScreen::QCocoaScreen(CGDirectDisplayID displayId)
+ : QPlatformScreen(), m_displayId(displayId)
{
updateProperties();
m_cursor = new QCocoaCursor;
}
-QCocoaScreen::~QCocoaScreen()
+void QCocoaScreen::cleanupScreens()
{
- delete m_cursor;
+ // Remove screens in reverse order to avoid crash in case of multiple screens
+ for (QScreen *screen : backwards(QGuiApplication::screens()))
+ static_cast<QCocoaScreen*>(screen->handle())->remove();
+}
- CVDisplayLinkRelease(m_displayLink);
- if (m_displayLinkSource)
- dispatch_release(m_displayLinkSource);
+void QCocoaScreen::remove()
+{
+ m_displayId = 0; // Prevent stale references during removal
+
+ // This may result in the application responding to QGuiApplication::screenRemoved
+ // by moving the window to another screen, either by setGeometry, or by setScreen.
+ // If the window isn't moved by the application, Qt will as a fallback move it to
+ // the primary screen via setScreen. Due to the way setScreen works, this won't
+ // actually recreate the window on the new screen, it will just assign the new
+ // QScreen to the window. The associated NSWindow will have an NSScreen determined
+ // by AppKit. AppKit will then move the window to another screen by changing the
+ // geometry, and we will get a callback in QCocoaWindow::windowDidMove and then
+ // QCocoaWindow::windowDidChangeScreen. At that point the window will appear to have
+ // already changed its screen, but that's only true if comparing the Qt screens,
+ // not when comparing the NSScreens.
+ QWindowSystemInterface::handleScreenRemoved(this);
}
-NSScreen *QCocoaScreen::nativeScreen() const
+QCocoaScreen::~QCocoaScreen()
{
- NSArray<NSScreen *> *screens = [NSScreen screens];
+ Q_ASSERT_X(!screen(), "QCocoaScreen", "QScreen should be deleted first");
- // Stale reference, screen configuration has changed
- if (m_screenIndex < 0 || (NSUInteger)m_screenIndex >= [screens count])
- return nil;
+ delete m_cursor;
- return [screens objectAtIndex:m_screenIndex];
+ CVDisplayLinkRelease(m_displayLink);
+ if (m_displayLinkSource)
+ dispatch_release(m_displayLinkSource);
}
static QString displayName(CGDirectDisplayID displayID)
@@ -117,35 +188,37 @@ static QString displayName(CGDirectDisplayID displayID)
void QCocoaScreen::updateProperties()
{
- NSScreen *nsScreen = nativeScreen();
- if (!nsScreen)
- return;
+ Q_ASSERT(m_displayId);
const QRect previousGeometry = m_geometry;
const QRect previousAvailableGeometry = m_availableGeometry;
const QDpi previousLogicalDpi = m_logicalDpi;
const qreal previousRefreshRate = m_refreshRate;
+ // Some properties are only available via NSScreen
+ NSScreen *nsScreen = nativeScreen();
+ Q_ASSERT(nsScreen);
+
// The reference screen for the geometry is always the primary screen
- QRectF primaryScreenGeometry = QRectF::fromCGRect([[NSScreen screens] firstObject].frame);
+ QRectF primaryScreenGeometry = QRectF::fromCGRect(CGDisplayBounds(CGMainDisplayID()));
m_geometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.frame), primaryScreenGeometry).toRect();
m_availableGeometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.visibleFrame), primaryScreenGeometry).toRect();
+ m_devicePixelRatio = nsScreen.backingScaleFactor;
+
m_format = QImage::Format_RGB32;
- m_depth = NSBitsPerPixelFromDepth([nsScreen depth]);
+ m_depth = NSBitsPerPixelFromDepth(nsScreen.depth);
- CGDirectDisplayID dpy = nsScreen.qt_displayId;
- CGSize size = CGDisplayScreenSize(dpy);
+ CGSize size = CGDisplayScreenSize(m_displayId);
m_physicalSize = QSizeF(size.width, size.height);
m_logicalDpi.first = 72;
m_logicalDpi.second = 72;
- CGDisplayModeRef displayMode = CGDisplayCopyDisplayMode(dpy);
+
+ QCFType<CGDisplayModeRef> displayMode = CGDisplayCopyDisplayMode(m_displayId);
float refresh = CGDisplayModeGetRefreshRate(displayMode);
- CGDisplayModeRelease(displayMode);
- if (refresh > 0)
- m_refreshRate = refresh;
+ m_refreshRate = refresh > 0 ? refresh : 60.0;
- m_name = displayName(dpy);
+ m_name = displayName(m_displayId);
const bool didChangeGeometry = m_geometry != previousGeometry || m_availableGeometry != previousAvailableGeometry;
@@ -155,24 +228,6 @@ void QCocoaScreen::updateProperties()
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second);
if (m_refreshRate != previousRefreshRate)
QWindowSystemInterface::handleScreenRefreshRateChange(screen(), m_refreshRate);
-
- qCDebug(lcQpaScreen) << "Updated properties for" << this;
-
- if (didChangeGeometry) {
- // When a screen changes its geometry, AppKit will send us a NSWindowDidMoveNotification
- // for each window, resulting in calls to handleGeometryChange(), but this happens before
- // the NSApplicationDidChangeScreenParametersNotification, so when we map the new geometry
- // (which is correct at that point) to the screen using QCocoaScreen::mapFromNative(), we
- // end up using the stale screen geometry, and the new window geometry we report is wrong.
- // To make sure we finally report the correct window geometry, we need to do another pass
- // of geometry reporting, now that the screen properties have been updates. FIXME: Ideally
- // this would be solved by not caching the screen properties in QCocoaScreen, but that
- // requires more research.
- for (QWindow *window : windows()) {
- if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow*>(window->handle()))
- cocoaWindow->handleGeometryChange();
- }
- }
}
// ----------------------- Display link -----------------------
@@ -181,8 +236,10 @@ Q_LOGGING_CATEGORY(lcQpaScreenUpdates, "qt.qpa.screen.updates", QtCriticalMsg);
void QCocoaScreen::requestUpdate()
{
+ Q_ASSERT(m_displayId);
+
if (!m_displayLink) {
- CVDisplayLinkCreateWithCGDisplay(nativeScreen().qt_displayId, &m_displayLink);
+ CVDisplayLinkCreateWithCGDisplay(m_displayId, &m_displayLink);
CVDisplayLinkSetOutputCallback(m_displayLink, [](CVDisplayLinkRef, const CVTimeStamp*,
const CVTimeStamp*, CVOptionFlags, CVOptionFlags*, void* displayLinkContext) -> int {
// FIXME: It would be nice if update requests would include timing info
@@ -269,6 +326,9 @@ struct DeferredDebugHelper
void QCocoaScreen::deliverUpdateRequests()
{
+ if (!m_displayId)
+ return; // Screen removed
+
QMacAutoReleasePool pool;
// The CVDisplayLink callback is a notification that it's a good time to produce a new frame.
@@ -283,7 +343,7 @@ void QCocoaScreen::deliverUpdateRequests()
const int pendingUpdates = ++m_pendingUpdates;
DeferredDebugHelper screenUpdates(lcQpaScreenUpdates());
- qDeferredDebug(screenUpdates) << "display link callback for screen " << m_screenIndex;
+ qDeferredDebug(screenUpdates) << "display link callback for screen " << m_displayId;
if (const int framesAheadOfDelivery = pendingUpdates - 1) {
// If we have more than one update pending it means that a previous display link callback
@@ -370,13 +430,6 @@ bool QCocoaScreen::isRunningDisplayLink() const
// -----------------------------------------------------------
-qreal QCocoaScreen::devicePixelRatio() const
-{
- QMacAutoReleasePool pool;
- NSScreen *nsScreen = nativeScreen();
- return qreal(nsScreen ? [nsScreen backingScaleFactor] : 1.0);
-}
-
QPlatformScreen::SubpixelAntialiasingType QCocoaScreen::subpixelAntialiasingTypeHint() const
{
QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint();
@@ -430,7 +483,7 @@ QPixmap QCocoaScreen::grabWindow(WId view, int x, int y, int width, int height)
{
// Determine the grab rect. FIXME: The rect should be bounded by the view's
// geometry, but note that for the pixeltool use case that window will be the
- // desktop widgets's view, which currently gets resized to fit one screen
+ // desktop widget's view, which currently gets resized to fit one screen
// only, since its NSWindow has the NSWindowStyleMaskTitled flag set.
Q_UNUSED(view);
QRect grabRect = QRect(x, y, width, height);
@@ -482,7 +535,7 @@ QPixmap QCocoaScreen::grabWindow(WId view, int x, int y, int width, int height)
for (uint i = 0; i < displayCount; ++i)
dpr = qMax(dpr, images.at(i).devicePixelRatio());
- // Alocate target pixmap and draw each screen's content
+ // Allocate target pixmap and draw each screen's content
qCDebug(lcQpaScreen) << "Create grap pixmap" << grabRect.size() << "at devicePixelRatio" << dpr;
QPixmap windowPixmap(grabRect.size() * dpr);
windowPixmap.setDevicePixelRatio(dpr);
@@ -499,7 +552,57 @@ QPixmap QCocoaScreen::grabWindow(WId view, int x, int y, int width, int height)
*/
QCocoaScreen *QCocoaScreen::primaryScreen()
{
- return static_cast<QCocoaScreen *>(QGuiApplication::primaryScreen()->handle());
+ auto screen = static_cast<QCocoaScreen *>(QGuiApplication::primaryScreen()->handle());
+ Q_ASSERT_X(screen == get(CGMainDisplayID()), "QCocoaScreen",
+ "The application's primary screen should always be in sync with the main display");
+ return screen;
+}
+
+QList<QPlatformScreen*> QCocoaScreen::virtualSiblings() const
+{
+ QList<QPlatformScreen*> siblings;
+
+ // Screens on macOS are always part of the same virtual desktop
+ for (QScreen *screen : QGuiApplication::screens())
+ siblings << screen->handle();
+
+ return siblings;
+}
+
+QCocoaScreen *QCocoaScreen::get(NSScreen *nsScreen)
+{
+ return get(nsScreen.qt_displayId);
+}
+
+QCocoaScreen *QCocoaScreen::get(CGDirectDisplayID displayId)
+{
+ for (QScreen *screen : QGuiApplication::screens()) {
+ QCocoaScreen *cocoaScreen = static_cast<QCocoaScreen*>(screen->handle());
+ if (cocoaScreen->m_displayId == displayId)
+ return cocoaScreen;
+ }
+
+ return nullptr;
+}
+
+NSScreen *QCocoaScreen::nativeScreen() const
+{
+ if (!m_displayId)
+ return nil; // The display has been disconnected
+
+ // A single display may have different displayIds depending on
+ // which GPU is in use or which physical port the display is
+ // connected to. By comparing UUIDs instead of display IDs we
+ // ensure that we always pick up the appropriate NSScreen.
+ QCFType<CFUUIDRef> uuid = CGDisplayCreateUUIDFromDisplayID(m_displayId);
+
+ for (NSScreen *screen in [NSScreen screens]) {
+ if (CGDisplayCreateUUIDFromDisplayID(screen.qt_displayId) == uuid)
+ return screen;
+ }
+
+ qCWarning(lcQpaScreen) << "Could not find NSScreen for display ID" << m_displayId;
+ return nil;
}
CGPoint QCocoaScreen::mapToNative(const QPointF &pos, QCocoaScreen *screen)
@@ -533,11 +636,10 @@ QDebug operator<<(QDebug debug, const QCocoaScreen *screen)
debug.nospace();
debug << "QCocoaScreen(" << (const void *)screen;
if (screen) {
- debug << ", index=" << screen->m_screenIndex;
- debug << ", native=" << screen->nativeScreen();
debug << ", geometry=" << screen->geometry();
debug << ", dpr=" << screen->devicePixelRatio();
debug << ", name=" << screen->name();
+ debug << ", native=" << screen->nativeScreen();
}
debug << ')';
return debug;
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index 4982f5ee05..de5cf85854 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -383,9 +383,9 @@ QT_END_NAMESPACE
}
- (QRectF)geometry {
- if (NSWindow *window = [[item view] window]) {
- if (QCocoaScreen *screen = QCocoaIntegration::instance()->screenForNSScreen([window screen]))
- return screen->mapFromNative([window frame]);
+ if (NSWindow *window = item.view.window) {
+ if (QCocoaScreen *screen = QCocoaScreen::get(window.screen))
+ return screen->mapFromNative(window.frame);
}
return QRectF();
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index dc7319484e..363a026e71 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -217,6 +217,7 @@ QCocoaWindow::~QCocoaWindow()
}
[m_view release];
+ [m_nsWindow close];
[m_nsWindow release];
}
@@ -618,7 +619,7 @@ void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
if (nsWindow.styleMask & NSWindowStyleMaskUtilityWindow
&& newState & (Qt::WindowMinimized | Qt::WindowFullScreen)) {
- qWarning() << window()->type() << "windows can not be made" << newState;
+ qWarning() << window()->type() << "windows cannot be made" << newState;
handleWindowStateChanged(HandleUnconditionally);
return;
}
@@ -1210,17 +1211,17 @@ void QCocoaWindow::windowDidChangeScreen()
return;
// Note: When a window is resized to 0x0 Cocoa will report the window's screen as nil
- auto *currentScreen = QCocoaIntegration::instance()->screenForNSScreen(m_view.window.screen);
+ auto *currentScreen = QCocoaScreen::get(m_view.window.screen);
auto *previousScreen = static_cast<QCocoaScreen*>(screen());
Q_ASSERT_X(!m_view.window.screen || currentScreen,
"QCocoaWindow", "Failed to get QCocoaScreen for NSScreen");
// Note: The previous screen may be the same as the current screen, either because
- // the screen was just reconfigured, which still results in AppKit sending an
- // NSWindowDidChangeScreenNotification, because the previous screen was removed,
+ // a) the screen was just reconfigured, which still results in AppKit sending an
+ // NSWindowDidChangeScreenNotification, b) because the previous screen was removed,
// and we ended up calling QWindow::setScreen to move the window, which doesn't
- // actually move the window to the new screen, or because we've delivered the
+ // actually move the window to the new screen, or c) because we've delivered the
// screen change to the top level window, which will make all the child windows
// of that window report the new screen when requested via QWindow::screen().
// We still need to deliver the screen change in all these cases, as the
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm
index ba6cfca219..358a6b49fd 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.mm
+++ b/src/plugins/platforms/cocoa/qmacclipboard.mm
@@ -489,19 +489,16 @@ QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const
QMacInternalPasteboardMime *c = mimes.at(mime);
QString c_flavor = c->flavorFor(format);
if (!c_flavor.isEmpty()) {
- // Handle text/plain a little differently. Try handling Unicode first.
- bool checkForUtf16 = (c_flavor == QLatin1String("com.apple.traditional-mac-plain-text")
- || c_flavor == QLatin1String("public.utf8-plain-text"));
- if (checkForUtf16 || c_flavor == QLatin1String("public.utf16-plain-text")) {
- // Try to get the NSStringPboardType from NSPasteboard, newlines are mapped
- // correctly (as '\n') in this data. The 'public.utf16-plain-text' type
- // usually maps newlines to '\r' instead.
+ // Converting via PasteboardCopyItemFlavorData below will for some UITs result
+ // in newlines mapping to '\r' instead of '\n'. To work around this we shortcut
+ // the conversion via NSPasteboard's NSStringPboardType if possible.
+ if (c_flavor == QLatin1String("com.apple.traditional-mac-plain-text")
+ || c_flavor == QLatin1String("public.utf8-plain-text")
+ || c_flavor == QLatin1String("public.utf16-plain-text")) {
QString str = qt_mac_get_pasteboardString(paste);
if (!str.isEmpty())
return str;
}
- if (checkForUtf16 && hasFlavor(QLatin1String("public.utf16-plain-text")))
- c_flavor = QLatin1String("public.utf16-plain-text");
QVariant ret;
QList<QByteArray> retList;
diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm
index 116a9a73df..d2e6f848a0 100644
--- a/src/plugins/platforms/cocoa/qnsview_drawing.mm
+++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm
@@ -106,7 +106,7 @@
"_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER");
if (wantsLayer != -1 && [self layerEnabledByMacOS]) {
- qCWarning(lcQpaDrawing) << "Layer-backing can not be explicitly controlled on 10.14 when built against the 10.14 SDK";
+ qCWarning(lcQpaDrawing) << "Layer-backing cannot be explicitly controlled on 10.14 when built against the 10.14 SDK";
return true;
}
diff --git a/src/plugins/platforms/cocoa/qnsview_gestures.mm b/src/plugins/platforms/cocoa/qnsview_gestures.mm
index 61d551ee0e..f6cd3af4da 100644
--- a/src/plugins/platforms/cocoa/qnsview_gestures.mm
+++ b/src/plugins/platforms/cocoa/qnsview_gestures.mm
@@ -70,7 +70,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures")
if ([self handleGestureAsBeginEnd:event])
return;
- qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification] << "from device" << hex << [event deviceID];
+ qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification] << "from device" << Qt::hex << [event deviceID];
const NSTimeInterval timestamp = [event timestamp];
QPointF windowPoint;
QPointF screenPoint;
@@ -85,7 +85,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures")
return;
static bool zoomIn = true;
- qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn << "from device" << hex << [event deviceID];
+ qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn << "from device" << Qt::hex << [event deviceID];
const NSTimeInterval timestamp = [event timestamp];
QPointF windowPoint;
QPointF screenPoint;
@@ -116,7 +116,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures")
if (!m_platformWindow)
return;
- qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY] << "from device" << hex << [event deviceID];
+ qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY] << "from device" << Qt::hex << [event deviceID];
const NSTimeInterval timestamp = [event timestamp];
QPointF windowPoint;
QPointF screenPoint;
@@ -145,7 +145,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures")
QPointF windowPoint;
QPointF screenPoint;
[self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint << "from device" << hex << [event deviceID];
+ qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint << "from device" << Qt::hex << [event deviceID];
QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::BeginNativeGesture,
windowPoint, screenPoint);
}
@@ -155,7 +155,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures")
if (!m_platformWindow)
return;
- qCDebug(lcQpaGestures) << "endGestureWithEvent" << "from device" << hex << [event deviceID];
+ qCDebug(lcQpaGestures) << "endGestureWithEvent" << "from device" << Qt::hex << [event deviceID];
const NSTimeInterval timestamp = [event timestamp];
QPointF windowPoint;
QPointF screenPoint;
diff --git a/src/plugins/platforms/cocoa/qnsview_mouse.mm b/src/plugins/platforms/cocoa/qnsview_mouse.mm
index a887cb841d..7c566442f0 100644
--- a/src/plugins/platforms/cocoa/qnsview_mouse.mm
+++ b/src/plugins/platforms/cocoa/qnsview_mouse.mm
@@ -222,6 +222,11 @@
return NO;
if ([self isTransparentForUserInput])
return NO;
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint: &windowPoint andScreenPoint: &screenPoint];
+ if (!qt_window_private(m_platformWindow->window())->allowClickThrough(screenPoint.toPoint()))
+ return NO;
return YES;
}
diff --git a/src/plugins/platforms/cocoa/qnsview_touch.mm b/src/plugins/platforms/cocoa/qnsview_touch.mm
index e789213f70..9330844aec 100644
--- a/src/plugins/platforms/cocoa/qnsview_touch.mm
+++ b/src/plugins/platforms/cocoa/qnsview_touch.mm
@@ -60,7 +60,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch")
const NSTimeInterval timestamp = [event timestamp];
const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
- qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points << "from device" << hex << [event deviceID];
+ qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points << "from device" << Qt::hex << [event deviceID];
QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
}
@@ -71,7 +71,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch")
const NSTimeInterval timestamp = [event timestamp];
const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
- qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points << "from device" << hex << [event deviceID];
+ qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points << "from device" << Qt::hex << [event deviceID];
QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
}
@@ -82,7 +82,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch")
const NSTimeInterval timestamp = [event timestamp];
const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
- qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points << "from device" << hex << [event deviceID];
+ qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points << "from device" << Qt::hex << [event deviceID];
QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
}
@@ -93,7 +93,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch")
const NSTimeInterval timestamp = [event timestamp];
const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
- qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points << "from device" << hex << [event deviceID];
+ qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points << "from device" << Qt::hex << [event deviceID];
QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
}
diff --git a/src/plugins/platforms/direct2d/direct2d.pro b/src/plugins/platforms/direct2d/direct2d.pro
index 9764272632..6e73bd14f9 100644
--- a/src/plugins/platforms/direct2d/direct2d.pro
+++ b/src/plugins/platforms/direct2d/direct2d.pro
@@ -8,8 +8,8 @@ QT += \
qtConfig(accessibility): QT += accessibility_support-private
qtConfig(vulkan): QT += vulkan_support-private
-LIBS += -ldwmapi -lversion -lgdi32
-QMAKE_USE_PRIVATE += dwrite_1 d2d1_1 d3d11_1 dxgi1_2
+LIBS += -ldwmapi -lversion
+QMAKE_USE_PRIVATE += gdi32 dwrite_1 d2d1_1 d3d11_1 dxgi1_2
include(../windows/windows.pri)
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
index f72ea2b038..6d4d47e3da 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
@@ -48,7 +48,7 @@ class QWindowsDirect2DWindow;
class QWindowsDirect2DBackingStore : public QPlatformBackingStore
{
- Q_DISABLE_COPY(QWindowsDirect2DBackingStore)
+ Q_DISABLE_COPY_MOVE(QWindowsDirect2DBackingStore)
public:
QWindowsDirect2DBackingStore(QWindow *window);
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h
index d8a8a49aec..8fd683106d 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h
@@ -59,7 +59,7 @@ class QColor;
class QWindowsDirect2DBitmap
{
Q_DECLARE_PRIVATE(QWindowsDirect2DBitmap)
- Q_DISABLE_COPY(QWindowsDirect2DBitmap)
+ Q_DISABLE_COPY_MOVE(QWindowsDirect2DBitmap)
public:
QWindowsDirect2DBitmap();
QWindowsDirect2DBitmap(ID2D1Bitmap1 *bitmap, ID2D1DeviceContext *dc);
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h
index aee0eb867d..a28c674671 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h
@@ -91,7 +91,7 @@ private:
};
class QWindowsDirect2DDeviceContextSuspender {
- Q_DISABLE_COPY(QWindowsDirect2DDeviceContextSuspender)
+ Q_DISABLE_COPY_MOVE(QWindowsDirect2DDeviceContextSuspender)
QWindowsDirect2DDeviceContext *m_dc;
public:
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
index 86c863ec50..0cf05cb0ac 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
@@ -91,7 +91,7 @@ static QVersionNumber systemD2DVersion()
if (VerQueryValue(info.constData(), __TEXT("\\"),
reinterpret_cast<void **>(&fi), &size) && size) {
- const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi);
+ const auto *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi);
return QVersionNumber{HIWORD(verInfo->dwFileVersionMS), LOWORD(verInfo->dwFileVersionMS),
HIWORD(verInfo->dwFileVersionLS), LOWORD(verInfo->dwFileVersionLS)};
}
@@ -140,7 +140,7 @@ QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::create(const QStringLi
return nullptr;
}
- QWindowsDirect2DIntegration *integration = new QWindowsDirect2DIntegration(paramList);
+ auto *integration = new QWindowsDirect2DIntegration(paramList);
if (!integration->init()) {
delete integration;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index fa201c784e..cf3e88d54e 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -253,7 +253,7 @@ struct D2DVectorPathCache {
static void cleanup_func(QPaintEngineEx *engine, void *data) {
Q_UNUSED(engine);
- D2DVectorPathCache *e = static_cast<D2DVectorPathCache *>(data);
+ auto *e = static_cast<D2DVectorPathCache *>(data);
delete e;
}
};
@@ -689,7 +689,7 @@ public:
*needsEmulation = true;
} else {
ComPtr<ID2D1LinearGradientBrush> linear;
- const QLinearGradient *qlinear = static_cast<const QLinearGradient *>(newBrush.gradient());
+ const auto *qlinear = static_cast<const QLinearGradient *>(newBrush.gradient());
D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES linearGradientBrushProperties;
ComPtr<ID2D1GradientStopCollection> gradientStopCollection;
@@ -727,7 +727,7 @@ public:
*needsEmulation = true;
} else {
ComPtr<ID2D1RadialGradientBrush> radial;
- const QRadialGradient *qradial = static_cast<const QRadialGradient *>(newBrush.gradient());
+ const auto *qradial = static_cast<const QRadialGradient *>(newBrush.gradient());
D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES radialGradientBrushProperties;
ComPtr<ID2D1GradientStopCollection> gradientStopCollection;
@@ -807,7 +807,7 @@ public:
: nullptr;
if (cacheEntry) {
- D2DVectorPathCache *e = static_cast<D2DVectorPathCache *>(cacheEntry->data);
+ auto *e = static_cast<D2DVectorPathCache *>(cacheEntry->data);
if (alias && e->aliased)
return e->aliased;
else if (!alias && e->antiAliased)
@@ -885,7 +885,7 @@ public:
if (!cacheEntry)
cacheEntry = path.addCacheData(q, new D2DVectorPathCache, D2DVectorPathCache::cleanup_func);
- D2DVectorPathCache *e = static_cast<D2DVectorPathCache *>(cacheEntry->data);
+ auto *e = static_cast<D2DVectorPathCache *>(cacheEntry->data);
if (alias)
e->aliased = geometry;
else
@@ -1481,7 +1481,7 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r,
return;
}
- QWindowsDirect2DPlatformPixmap *pp = static_cast<QWindowsDirect2DPlatformPixmap *>(pm.handle());
+ auto *pp = static_cast<QWindowsDirect2DPlatformPixmap *>(pm.handle());
QWindowsDirect2DBitmap *bitmap = pp->bitmap();
ensurePen();
@@ -1593,7 +1593,7 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem
Q_D(QWindowsDirect2DPaintEngine);
D2D_TAG(D2DDebugDrawTextItemTag);
- const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+ const auto &ti = static_cast<const QTextItemInt &>(textItem);
if (ti.glyphs.numGlyphs == 0)
return;
@@ -1686,7 +1686,7 @@ void QWindowsDirect2DPaintEngine::rasterFill(const QVectorPath &path, const QBru
p.setBrush(state()->brush);
p.setPen(state()->pen);
- QPaintEngineEx *extended = static_cast<QPaintEngineEx *>(engine);
+ auto *extended = static_cast<QPaintEngineEx *>(engine);
for (const QPainterClipInfo &info : qAsConst(state()->clipInfo)) {
extended->state()->matrix = info.matrix;
extended->transformChanged();
@@ -1800,7 +1800,7 @@ void QWindowsDirect2DPaintEngine::resume()
class QWindowsDirect2DPaintEngineSuspenderImpl
{
- Q_DISABLE_COPY(QWindowsDirect2DPaintEngineSuspenderImpl)
+ Q_DISABLE_COPY_MOVE(QWindowsDirect2DPaintEngineSuspenderImpl)
QWindowsDirect2DPaintEngine *m_engine;
bool m_active;
public:
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
index 6404c60b13..f61e908bce 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
@@ -128,7 +128,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsDirect2DPaintEngine::Flags)
class QWindowsDirect2DPaintEngineSuspenderPrivate;
class QWindowsDirect2DPaintEngineSuspender
{
- Q_DISABLE_COPY(QWindowsDirect2DPaintEngineSuspender)
+ Q_DISABLE_COPY_MOVE(QWindowsDirect2DPaintEngineSuspender)
Q_DECLARE_PRIVATE(QWindowsDirect2DPaintEngineSuspender)
QScopedPointer<QWindowsDirect2DPaintEngineSuspenderPrivate> d_ptr;
public:
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
index 239e5f3087..c417daaeae 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
@@ -310,7 +310,7 @@ void QWindowsDirect2DWindow::setupBitmap()
QWindowsDirect2DPaintEngine::Flags flags = QWindowsDirect2DPaintEngine::NoFlag;
if (!m_directRendering)
flags |= QWindowsDirect2DPaintEngine::TranslucentTopLevelWindow;
- QWindowsDirect2DPlatformPixmap *pp = new QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixmapType,
+ auto *pp = new QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixmapType,
flags,
m_bitmap.data());
m_pixmap.reset(new QPixmap(pp));
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
index 24f82e7843..09a10bcc9c 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
@@ -157,7 +157,7 @@ gbm_surface *QEglFSKmsGbmScreen::createSurface(EGLConfig eglConfig)
const auto gbmDevice = static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice();
EGLint native_format = -1;
EGLBoolean success = eglGetConfigAttrib(display(), eglConfig, EGL_NATIVE_VISUAL_ID, &native_format);
- qCDebug(qLcEglfsKmsDebug) << "Got native format" << hex << native_format << dec << "from eglGetConfigAttrib() with return code" << bool(success);
+ qCDebug(qLcEglfsKmsDebug) << "Got native format" << Qt::hex << native_format << Qt::dec << "from eglGetConfigAttrib() with return code" << bool(success);
if (success)
m_gbm_surface = gbm_surface_create(gbmDevice,
@@ -423,7 +423,7 @@ void QEglFSKmsGbmScreen::updateFlipStatus()
if (m_flipPending)
return;
- for (const CloneDestination &d : m_cloneDests) {
+ for (const CloneDestination &d : qAsConst(m_cloneDests)) {
if (d.cloneFlipPending)
return;
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
index 3e78196227..2c6b4245b7 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -114,16 +114,20 @@ public:
: QEglFSWindow(w)
, m_integration(integration)
, m_egl_stream(EGL_NO_STREAM_KHR)
+ , m_framePending(false)
{ }
~QEglFSKmsEglDeviceWindow() { destroy(); }
void invalidateSurface() override;
void resetSurface() override;
+ void flip();
+ static void pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data);
const QEglFSKmsEglDeviceIntegration *m_integration;
EGLStreamKHR m_egl_stream;
EGLint m_latency;
+ bool m_framePending;
};
void QEglFSKmsEglDeviceWindow::invalidateSurface()
@@ -144,6 +148,9 @@ void QEglFSKmsEglDeviceWindow::resetSurface()
streamAttribs[streamAttribCount++] = EGL_STREAM_FIFO_LENGTH_KHR;
streamAttribs[streamAttribCount++] = fifoLength;
}
+
+ streamAttribs[streamAttribCount++] = EGL_CONSUMER_AUTO_ACQUIRE_EXT;
+ streamAttribs[streamAttribCount++] = EGL_FALSE;
streamAttribs[streamAttribCount++] = EGL_NONE;
m_egl_stream = m_integration->m_funcs->create_stream(display, streamAttribs);
@@ -241,6 +248,49 @@ void QEglFSKmsEglDeviceWindow::resetSurface()
qCDebug(qLcEglfsKmsDebug, "Created stream producer surface %p", m_surface);
}
+void QEglFSKmsEglDeviceWindow::flip()
+{
+ EGLDisplay display = screen()->display();
+
+ EGLAttrib acquire_attribs[3] = { EGL_NONE };
+
+ acquire_attribs[0] = EGL_DRM_FLIP_EVENT_DATA_NV;
+ acquire_attribs[1] = (EGLAttrib)this;
+ acquire_attribs[2] = EGL_NONE;
+
+ if (m_egl_stream != EGL_NO_STREAM_KHR)
+ if (!m_integration->m_funcs->acquire_stream_attrib_nv(display, m_egl_stream, acquire_attribs))
+ qWarning("eglStreamConsumerAcquireAttribNV failed: eglError: %x", eglGetError());
+
+ m_framePending = true;
+
+ while (m_framePending) {
+ drmEventContext drmEvent;
+ memset(&drmEvent, 0, sizeof(drmEvent));
+ drmEvent.version = 3;
+ drmEvent.vblank_handler = nullptr;
+ drmEvent.page_flip_handler = pageFlipHandler;
+ drmHandleEvent(m_integration->m_device->fd(), &drmEvent);
+ }
+}
+
+void QEglFSKmsEglDeviceWindow::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
+{
+ Q_UNUSED(fd);
+ Q_UNUSED(sequence);
+ Q_UNUSED(tv_sec);
+ Q_UNUSED(tv_usec);
+
+ QEglFSKmsEglDeviceWindow *window = static_cast<QEglFSKmsEglDeviceWindow*>(user_data);
+ window->m_framePending = false;
+}
+
+void QEglFSKmsEglDeviceIntegration::presentBuffer(QPlatformSurface *surface)
+{
+ QEglFSKmsEglDeviceWindow *eglWindow = static_cast<QEglFSKmsEglDeviceWindow*>(surface);
+ eglWindow->flip();
+}
+
QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const
{
QEglFSKmsEglDeviceWindow *eglWindow = new QEglFSKmsEglDeviceWindow(window, this);
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
index 5819d82ebf..a5697ec831 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
@@ -62,6 +62,8 @@ public:
bool supportsPBuffers() const override;
QEglFSWindow *createWindow(QWindow *window) const override;
+ void presentBuffer(QPlatformSurface *surface) override;
+
EGLDeviceEXT eglDevice() const { return m_egl_device; }
protected:
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp
index 3bdae239cd..296e301f07 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp
@@ -66,6 +66,11 @@ void QEglFSVivWaylandIntegration::platformInit()
mScreenSize.setWidth(width);
}
+void QEglFSVivWaylandIntegration::platformDestroy()
+{
+ wl_display_destroy(mWaylandDisplay);
+}
+
QSize QEglFSVivWaylandIntegration::screenSize() const
{
return mScreenSize;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h
index 2c49eb6440..bee23dfb3e 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h
@@ -49,6 +49,7 @@ class QEglFSVivWaylandIntegration : public QEglFSDeviceIntegration
{
public:
void platformInit() override;
+ void platformDestroy() override;
QSize screenSize() const override;
EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) override;
void destroyNativeWindow(EGLNativeWindowType window) override;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp
index 2e84915c80..07b2de7c58 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp
@@ -66,7 +66,7 @@ QAtomicInt running;
void EventReader::run()
{
xcb_generic_event_t *event = nullptr;
- while (running.load() && (event = xcb_wait_for_event(m_integration->connection()))) {
+ while (running.loadRelaxed() && (event = xcb_wait_for_event(m_integration->connection()))) {
uint response_type = event->response_type & ~0x80;
switch (response_type) {
case XCB_CLIENT_MESSAGE: {
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
index 535e7d7aa6..c9509ae599 100644
--- a/src/plugins/platforms/ios/qioscontext.mm
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -118,7 +118,7 @@ QSurfaceFormat QIOSContext::format() const
return m_format;
}
-#define QT_IOS_GL_STATUS_CASE(val) case val: return QLatin1Literal(#val)
+#define QT_IOS_GL_STATUS_CASE(val) case val: return QLatin1String(#val)
static QString fboStatusString(GLenum status)
{
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
index 7a871b3812..af6bd1d630 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
@@ -72,7 +72,7 @@ public:
QList<QPlatformScreen *> screens() const;
- QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+ QFunctionPointer platformFunction(const QByteArray &function) const override;
private:
void createInputHandlers();
diff --git a/src/plugins/platforms/mirclient/mirclient.json b/src/plugins/platforms/mirclient/mirclient.json
deleted file mode 100644
index c31558a2f1..0000000000
--- a/src/plugins/platforms/mirclient/mirclient.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Keys": [ "mirclient" ]
-}
diff --git a/src/plugins/platforms/mirclient/mirclient.pro b/src/plugins/platforms/mirclient/mirclient.pro
deleted file mode 100644
index d9eb069200..0000000000
--- a/src/plugins/platforms/mirclient/mirclient.pro
+++ /dev/null
@@ -1,61 +0,0 @@
-TARGET = qmirclient
-
-QT += \
- core-private gui-private dbus \
- theme_support-private eventdispatcher_support-private \
- fontdatabase_support-private egl_support-private
-
-qtHaveModule(linuxaccessibility_support-private): \
- QT += linuxaccessibility_support-private
-
-DEFINES += MESA_EGL_NO_X11_HEADERS
-# CONFIG += c++11 # only enables C++0x
-QMAKE_CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Werror -Wall
-QMAKE_LFLAGS += -std=c++11 -Wl,-no-undefined
-
-QMAKE_USE_PRIVATE += mirclient
-
-SOURCES = \
- qmirclientappstatecontroller.cpp \
- qmirclientbackingstore.cpp \
- qmirclientclipboard.cpp \
- qmirclientcursor.cpp \
- qmirclientdebugextension.cpp \
- qmirclientdesktopwindow.cpp \
- qmirclientglcontext.cpp \
- qmirclientinput.cpp \
- qmirclientintegration.cpp \
- qmirclientnativeinterface.cpp \
- qmirclientplatformservices.cpp \
- qmirclientplugin.cpp \
- qmirclientscreen.cpp \
- qmirclientscreenobserver.cpp \
- qmirclienttheme.cpp \
- qmirclientwindow.cpp
-
-HEADERS = \
- qmirclientappstatecontroller.h \
- qmirclientbackingstore.h \
- qmirclientclipboard.h \
- qmirclientcursor.h \
- qmirclientdebugextension.h \
- qmirclientdesktopwindow.h \
- qmirclientglcontext.h \
- qmirclientinput.h \
- qmirclientintegration.h \
- qmirclientlogging.h \
- qmirclientnativeinterface.h \
- qmirclientorientationchangeevent_p.h \
- qmirclientplatformservices.h \
- qmirclientplugin.h \
- qmirclientscreen.h \
- qmirclientscreenobserver.h \
- qmirclienttheme.h \
- qmirclientwindow.h
-
-QMAKE_USE_PRIVATE += xkbcommon
-
-PLUGIN_TYPE = platforms
-PLUGIN_CLASS_NAME = MirServerIntegrationPlugin
-!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
-load(qt_plugin)
diff --git a/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp b/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp
deleted file mode 100644
index 51363619d9..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qmirclientbackingstore.h"
-#include "qmirclientlogging.h"
-#include <QtGui/QOpenGLContext>
-#include <QtGui/QOpenGLTexture>
-#include <QtGui/QMatrix4x4>
-#include <QtGui/qopengltextureblitter.h>
-#include <QtGui/qopenglfunctions.h>
-
-QMirClientBackingStore::QMirClientBackingStore(QWindow* window)
- : QPlatformBackingStore(window)
- , mContext(new QOpenGLContext)
- , mTexture(new QOpenGLTexture(QOpenGLTexture::Target2D))
- , mBlitter(new QOpenGLTextureBlitter)
-{
- mContext->setFormat(window->requestedFormat());
- mContext->setScreen(window->screen());
- mContext->create();
-
- window->setSurfaceType(QSurface::OpenGLSurface);
-}
-
-QMirClientBackingStore::~QMirClientBackingStore()
-{
- mContext->makeCurrent(window()); // needed as QOpenGLTexture destructor assumes current context
-}
-
-void QMirClientBackingStore::flush(QWindow* window, const QRegion& region, const QPoint& offset)
-{
- Q_UNUSED(region);
- Q_UNUSED(offset);
- mContext->makeCurrent(window);
- glViewport(0, 0, window->width(), window->height());
-
- updateTexture();
-
- if (!mBlitter->isCreated())
- mBlitter->create();
-
- mBlitter->bind();
- mBlitter->blit(mTexture->textureId(), QMatrix4x4(), QOpenGLTextureBlitter::OriginTopLeft);
- mBlitter->release();
-
- mContext->swapBuffers(window);
-}
-
-void QMirClientBackingStore::updateTexture()
-{
- if (mDirty.isNull())
- return;
-
- if (!mTexture->isCreated()) {
- mTexture->setMinificationFilter(QOpenGLTexture::Nearest);
- mTexture->setMagnificationFilter(QOpenGLTexture::Nearest);
- mTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
- mTexture->setData(mImage, QOpenGLTexture::DontGenerateMipMaps);
- mTexture->create();
- }
- mTexture->bind();
-
- QRegion fixed;
- QRect imageRect = mImage.rect();
-
- for (const QRect &rect : mDirty) {
- // intersect with image rect to be sure
- QRect r = imageRect & rect;
-
- // if the rect is wide enough it is cheaper to just extend it instead of doing an image copy
- if (r.width() >= imageRect.width() / 2) {
- r.setX(0);
- r.setWidth(imageRect.width());
- }
-
- fixed |= r;
- }
-
- for (const QRect &rect : fixed) {
- // if the sub-rect is full-width we can pass the image data directly to
- // OpenGL instead of copying, since there is no gap between scanlines
- if (rect.width() == imageRect.width()) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
- mImage.constScanLine(rect.y()));
- } else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
- mImage.copy(rect).constBits());
- }
- }
- /* End of code taken from QEGLPlatformBackingStore */
-
- mDirty = QRegion();
-}
-
-
-void QMirClientBackingStore::beginPaint(const QRegion& region)
-{
- mDirty |= region;
-}
-
-void QMirClientBackingStore::resize(const QSize& size, const QRegion& /*staticContents*/)
-{
- mImage = QImage(size, QImage::Format_RGBA8888);
-
- mContext->makeCurrent(window());
-
- if (mTexture->isCreated())
- mTexture->destroy();
-}
-
-QPaintDevice* QMirClientBackingStore::paintDevice()
-{
- return &mImage;
-}
-
-QImage QMirClientBackingStore::toImage() const
-{
- // used by QPlatformBackingStore::composeAndFlush
- return mImage;
-}
diff --git a/src/plugins/platforms/mirclient/qmirclientclipboard.cpp b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp
deleted file mode 100644
index b9fc9b3b42..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientclipboard.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qmirclientclipboard.h"
-#include "qmirclientlogging.h"
-#include "qmirclientwindow.h"
-
-#include <QDBusPendingCallWatcher>
-#include <QGuiApplication>
-#include <QSignalBlocker>
-#include <QtCore/QMimeData>
-#include <QtCore/QStringList>
-
-// content-hub
-#include <com/ubuntu/content/hub.h>
-
-// get this cumbersome nested namespace out of the way
-using namespace com::ubuntu::content;
-
-QMirClientClipboard::QMirClientClipboard()
- : mMimeData(new QMimeData)
- , mContentHub(Hub::Client::instance())
-{
- connect(mContentHub, &Hub::pasteboardChanged, this, [this]() {
- if (mClipboardState == QMirClientClipboard::SyncedClipboard) {
- mClipboardState = QMirClientClipboard::OutdatedClipboard;
- emitChanged(QClipboard::Clipboard);
- }
- });
-
- connect(qGuiApp, &QGuiApplication::applicationStateChanged,
- this, &QMirClientClipboard::onApplicationStateChanged);
-
- requestMimeData();
-}
-
-QMirClientClipboard::~QMirClientClipboard()
-{
- delete mMimeData;
-}
-
-QMimeData* QMirClientClipboard::mimeData(QClipboard::Mode mode)
-{
- if (mode != QClipboard::Clipboard)
- return nullptr;
-
- // Blocks dataChanged() signal from being emitted. Makes no sense to emit it from
- // inside the data getter.
- const QSignalBlocker blocker(this);
-
- if (mClipboardState == OutdatedClipboard) {
- updateMimeData();
- } else if (mClipboardState == SyncingClipboard) {
- mPasteReply->waitForFinished();
- }
-
- return mMimeData;
-}
-
-void QMirClientClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode)
-{
- QWindow *focusWindow = QGuiApplication::focusWindow();
- if (focusWindow && mode == QClipboard::Clipboard && mimeData != nullptr) {
- QString surfaceId = static_cast<QMirClientWindow*>(focusWindow->handle())->persistentSurfaceId();
-
- QDBusPendingCall reply = mContentHub->createPaste(surfaceId, *mimeData);
-
- // Don't care whether it succeeded
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
- connect(watcher, &QDBusPendingCallWatcher::finished,
- watcher, &QObject::deleteLater);
-
- mMimeData = mimeData;
- mClipboardState = SyncedClipboard;
- emitChanged(QClipboard::Clipboard);
- }
-}
-
-bool QMirClientClipboard::supportsMode(QClipboard::Mode mode) const
-{
- return mode == QClipboard::Clipboard;
-}
-
-bool QMirClientClipboard::ownsMode(QClipboard::Mode mode) const
-{
- Q_UNUSED(mode);
- return false;
-}
-
-void QMirClientClipboard::onApplicationStateChanged(Qt::ApplicationState state)
-{
- if (state == Qt::ApplicationActive) {
- // Only focused or active applications might be allowed to paste, so we probably
- // missed changes in the clipboard while we were hidden, inactive or, more importantly,
- // suspended.
- requestMimeData();
- }
-}
-
-void QMirClientClipboard::updateMimeData()
-{
- if (qGuiApp->applicationState() != Qt::ApplicationActive) {
- // Don't even bother asking as content-hub would probably ignore our request (and should).
- return;
- }
-
- delete mMimeData;
-
- QWindow *focusWindow = QGuiApplication::focusWindow();
- if (focusWindow) {
- QString surfaceId = static_cast<QMirClientWindow*>(focusWindow->handle())->persistentSurfaceId();
- mMimeData = mContentHub->latestPaste(surfaceId);
- mClipboardState = SyncedClipboard;
- emitChanged(QClipboard::Clipboard);
- }
-}
-
-void QMirClientClipboard::requestMimeData()
-{
- if (qGuiApp->applicationState() != Qt::ApplicationActive) {
- // Don't even bother asking as content-hub would probably ignore our request (and should).
- return;
- }
-
- QWindow *focusWindow = QGuiApplication::focusWindow();
- if (!focusWindow) {
- return;
- }
-
- QString surfaceId = static_cast<QMirClientWindow*>(focusWindow->handle())->persistentSurfaceId();
- QDBusPendingCall reply = mContentHub->requestLatestPaste(surfaceId);
- mClipboardState = SyncingClipboard;
-
- mPasteReply = new QDBusPendingCallWatcher(reply, this);
- connect(mPasteReply, &QDBusPendingCallWatcher::finished,
- this, [this]() {
- delete mMimeData;
- mMimeData = mContentHub->paste(*mPasteReply);
- mClipboardState = SyncedClipboard;
- mPasteReply->deleteLater();
- mPasteReply = nullptr;
- emitChanged(QClipboard::Clipboard);
- });
-}
diff --git a/src/plugins/platforms/mirclient/qmirclientcursor.cpp b/src/plugins/platforms/mirclient/qmirclientcursor.cpp
deleted file mode 100644
index 812cde95c6..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientcursor.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015-2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qmirclientcursor.h"
-
-#include "qmirclientlogging.h"
-#include "qmirclientwindow.h"
-
-#include <mir_toolkit/mir_client_library.h>
-
-Q_LOGGING_CATEGORY(mirclientCursor, "qt.qpa.mirclient.cursor", QtWarningMsg)
-
-QMirClientCursor::QMirClientCursor(MirConnection *connection)
- : mConnection(connection)
-{
- /*
- * TODO: Add the missing cursors to Mir (LP: #1388987)
- * Those are the ones without a mir_ prefix, which are X11 cursors
- * and won't be understood by any shell other than Unity8.
- */
- mShapeToCursorName[Qt::ArrowCursor] = mir_arrow_cursor_name;
- mShapeToCursorName[Qt::UpArrowCursor] = "up_arrow";
- mShapeToCursorName[Qt::CrossCursor] = mir_crosshair_cursor_name;
- mShapeToCursorName[Qt::WaitCursor] = mir_busy_cursor_name;
- mShapeToCursorName[Qt::IBeamCursor] = mir_caret_cursor_name;
- mShapeToCursorName[Qt::SizeVerCursor] = mir_vertical_resize_cursor_name;
- mShapeToCursorName[Qt::SizeHorCursor] = mir_horizontal_resize_cursor_name;
- mShapeToCursorName[Qt::SizeBDiagCursor] = mir_diagonal_resize_bottom_to_top_cursor_name;
- mShapeToCursorName[Qt::SizeFDiagCursor] = mir_diagonal_resize_top_to_bottom_cursor_name;
- mShapeToCursorName[Qt::SizeAllCursor] = mir_omnidirectional_resize_cursor_name;
- mShapeToCursorName[Qt::BlankCursor] = mir_disabled_cursor_name;
- mShapeToCursorName[Qt::SplitVCursor] = mir_vsplit_resize_cursor_name;
- mShapeToCursorName[Qt::SplitHCursor] = mir_hsplit_resize_cursor_name;
- mShapeToCursorName[Qt::PointingHandCursor] = mir_pointing_hand_cursor_name;
- mShapeToCursorName[Qt::ForbiddenCursor] = "forbidden";
- mShapeToCursorName[Qt::WhatsThisCursor] = "whats_this";
- mShapeToCursorName[Qt::BusyCursor] = "left_ptr_watch";
- mShapeToCursorName[Qt::OpenHandCursor] = mir_open_hand_cursor_name;
- mShapeToCursorName[Qt::ClosedHandCursor] = mir_closed_hand_cursor_name;
- mShapeToCursorName[Qt::DragCopyCursor] = "dnd-copy";
- mShapeToCursorName[Qt::DragMoveCursor] = "dnd-move";
- mShapeToCursorName[Qt::DragLinkCursor] = "dnd-link";
-}
-
-namespace {
-const char *qtCursorShapeToStr(Qt::CursorShape shape)
-{
- switch (shape) {
- case Qt::ArrowCursor:
- return "Arrow";
- case Qt::UpArrowCursor:
- return "UpArrow";
- case Qt::CrossCursor:
- return "Cross";
- case Qt::WaitCursor:
- return "Wait";
- case Qt::IBeamCursor:
- return "IBeam";
- case Qt::SizeVerCursor:
- return "SizeVer";
- case Qt::SizeHorCursor:
- return "SizeHor";
- case Qt::SizeBDiagCursor:
- return "SizeBDiag";
- case Qt::SizeFDiagCursor:
- return "SizeFDiag";
- case Qt::SizeAllCursor:
- return "SizeAll";
- case Qt::BlankCursor:
- return "Blank";
- case Qt::SplitVCursor:
- return "SplitV";
- case Qt::SplitHCursor:
- return "SplitH";
- case Qt::PointingHandCursor:
- return "PointingHand";
- case Qt::ForbiddenCursor:
- return "Forbidden";
- case Qt::WhatsThisCursor:
- return "WhatsThis";
- case Qt::BusyCursor:
- return "Busy";
- case Qt::OpenHandCursor:
- return "OpenHand";
- case Qt::ClosedHandCursor:
- return "ClosedHand";
- case Qt::DragCopyCursor:
- return "DragCopy";
- case Qt::DragMoveCursor:
- return "DragMove";
- case Qt::DragLinkCursor:
- return "DragLink";
- case Qt::BitmapCursor:
- return "Bitmap";
- default:
- return "???";
- }
-}
-} // anonymous namespace
-
-void QMirClientCursor::changeCursor(QCursor *windowCursor, QWindow *window)
-{
- if (!window) {
- return;
- }
-
- MirSurface *surface = static_cast<QMirClientWindow*>(window->handle())->mirSurface();
-
- if (!surface) {
- return;
- }
-
-
- if (windowCursor) {
- qCDebug(mirclientCursor, "changeCursor shape=%s, window=%p", qtCursorShapeToStr(windowCursor->shape()), window);
- if (!windowCursor->pixmap().isNull()) {
- configureMirCursorWithPixmapQCursor(surface, *windowCursor);
- } else if (windowCursor->shape() == Qt::BitmapCursor) {
- // TODO: Implement bitmap cursor support
- applyDefaultCursorConfiguration(surface);
- } else {
- const auto &cursorName = mShapeToCursorName.value(windowCursor->shape(), QByteArray("left_ptr"));
- auto cursorConfiguration = mir_cursor_configuration_from_name(cursorName.data());
- mir_surface_configure_cursor(surface, cursorConfiguration);
- mir_cursor_configuration_destroy(cursorConfiguration);
- }
- } else {
- applyDefaultCursorConfiguration(surface);
- }
-
-}
-
-void QMirClientCursor::configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor)
-{
- QImage image = cursor.pixmap().toImage();
-
- if (image.format() != QImage::Format_ARGB32) {
- image = image.convertToFormat(QImage::Format_ARGB32);
- }
-
- MirBufferStream *bufferStream = mir_connection_create_buffer_stream_sync(mConnection,
- image.width(), image.height(), mir_pixel_format_argb_8888, mir_buffer_usage_software);
-
- {
- MirGraphicsRegion region;
- mir_buffer_stream_get_graphics_region(bufferStream, &region);
-
- char *regionLine = region.vaddr;
- Q_ASSERT(image.bytesPerLine() <= region.stride);
- for (int i = 0; i < image.height(); ++i) {
- memcpy(regionLine, image.scanLine(i), image.bytesPerLine());
- regionLine += region.stride;
- }
- }
-
- mir_buffer_stream_swap_buffers_sync(bufferStream);
-
- {
- auto configuration = mir_cursor_configuration_from_buffer_stream(bufferStream, cursor.hotSpot().x(), cursor.hotSpot().y());
- mir_surface_configure_cursor(surface, configuration);
- mir_cursor_configuration_destroy(configuration);
- }
-
- mir_buffer_stream_release_sync(bufferStream);
-}
-
-void QMirClientCursor::applyDefaultCursorConfiguration(MirSurface *surface)
-{
- auto cursorConfiguration = mir_cursor_configuration_from_name("left_ptr");
- mir_surface_configure_cursor(surface, cursorConfiguration);
- mir_cursor_configuration_destroy(cursorConfiguration);
-}
diff --git a/src/plugins/platforms/mirclient/qmirclientdebugextension.cpp b/src/plugins/platforms/mirclient/qmirclientdebugextension.cpp
deleted file mode 100644
index 9aa934083d..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientdebugextension.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qmirclientdebugextension.h"
-
-#include "qmirclientlogging.h"
-
-// mir client debug
-#include <mir_toolkit/debug/surface.h>
-
-Q_LOGGING_CATEGORY(mirclientDebug, "qt.qpa.mirclient.debug")
-
-QMirClientDebugExtension::QMirClientDebugExtension()
- : m_mirclientDebug(QStringLiteral("mirclient-debug-extension"), 1)
- , m_mapper(nullptr)
-{
- qCDebug(mirclientDebug) << "NOTICE: Loading mirclient-debug-extension";
- m_mapper = (MapperPrototype) m_mirclientDebug.resolve("mir_debug_surface_coords_to_screen");
-
- if (!m_mirclientDebug.isLoaded()) {
- qCWarning(mirclientDebug) << "ERROR: mirclient-debug-extension failed to load:"
- << m_mirclientDebug.errorString();
- } else if (!m_mapper) {
- qCWarning(mirclientDebug) << "ERROR: unable to find required symbols in mirclient-debug-extension:"
- << m_mirclientDebug.errorString();
- }
-}
-
-QPoint QMirClientDebugExtension::mapSurfacePointToScreen(MirSurface *surface, const QPoint &point)
-{
- if (!m_mapper) {
- return point;
- }
-
- QPoint mappedPoint;
- bool status = m_mapper(surface, point.x(), point.y(), &mappedPoint.rx(), &mappedPoint.ry());
- if (status) {
- return mappedPoint;
- } else {
- return point;
- }
-}
diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.cpp b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp
deleted file mode 100644
index fc7d90d5ec..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientglcontext.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qmirclientglcontext.h"
-#include "qmirclientlogging.h"
-#include "qmirclientwindow.h"
-
-#include <QOpenGLFramebufferObject>
-#include <QtEglSupport/private/qeglconvenience_p.h>
-#include <QtEglSupport/private/qeglpbuffer_p.h>
-#include <QtGui/private/qopenglcontext_p.h>
-
-Q_LOGGING_CATEGORY(mirclientGraphics, "qt.qpa.mirclient.graphics", QtWarningMsg)
-
-namespace {
-
-void printEglConfig(EGLDisplay display, EGLConfig config)
-{
- Q_ASSERT(display != EGL_NO_DISPLAY);
- Q_ASSERT(config != nullptr);
-
- const char *string = eglQueryString(display, EGL_VENDOR);
- qCDebug(mirclientGraphics, "EGL vendor: %s", string);
-
- string = eglQueryString(display, EGL_VERSION);
- qCDebug(mirclientGraphics, "EGL version: %s", string);
-
- string = eglQueryString(display, EGL_EXTENSIONS);
- qCDebug(mirclientGraphics, "EGL extensions: %s", string);
-
- qCDebug(mirclientGraphics, "EGL configuration attributes:");
- q_printEglConfig(display, config);
-}
-
-} // anonymous namespace
-
-QMirClientOpenGLContext::QMirClientOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
- EGLDisplay display)
- : QEGLPlatformContext(format, share, display, 0)
-{
- if (mirclientGraphics().isDebugEnabled()) {
- printEglConfig(display, eglConfig());
- }
-}
-
-static bool needsFBOReadBackWorkaround()
-{
- static bool set = false;
- static bool needsWorkaround = false;
-
- if (Q_UNLIKELY(!set)) {
- const char *rendererString = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
- needsWorkaround = qstrncmp(rendererString, "Mali-400", 8) == 0
- || qstrncmp(rendererString, "Mali-T7", 7) == 0
- || qstrncmp(rendererString, "PowerVR Rogue G6200", 19) == 0;
- set = true;
- }
-
- return needsWorkaround;
-}
-
-bool QMirClientOpenGLContext::makeCurrent(QPlatformSurface* surface)
-{
- const bool ret = QEGLPlatformContext::makeCurrent(surface);
-
- if (Q_LIKELY(ret)) {
- QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context());
- if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) {
- ctx_d->workaround_brokenFBOReadBack = true;
- }
- }
- return ret;
-}
-
-// Following method used internally in the base class QEGLPlatformContext to access
-// the egl surface of a QPlatformSurface/QMirClientWindow
-EGLSurface QMirClientOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
-{
- if (surface->surface()->surfaceClass() == QSurface::Window) {
- return static_cast<QMirClientWindow *>(surface)->eglSurface();
- } else {
- return static_cast<QEGLPbuffer *>(surface)->pbuffer();
- }
-}
-
-void QMirClientOpenGLContext::swapBuffers(QPlatformSurface* surface)
-{
- QEGLPlatformContext::swapBuffers(surface);
-
- if (surface->surface()->surfaceClass() == QSurface::Window) {
- // notify window on swap completion
- auto platformWindow = static_cast<QMirClientWindow *>(surface);
- platformWindow->onSwapBuffersDone();
- }
-}
diff --git a/src/plugins/platforms/mirclient/qmirclientinput.cpp b/src/plugins/platforms/mirclient/qmirclientinput.cpp
deleted file mode 100644
index e5319b0435..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientinput.cpp
+++ /dev/null
@@ -1,708 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014-2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-// Local
-#include "qmirclientinput.h"
-#include "qmirclientintegration.h"
-#include "qmirclientnativeinterface.h"
-#include "qmirclientscreen.h"
-#include "qmirclientwindow.h"
-#include "qmirclientlogging.h"
-#include "qmirclientorientationchangeevent_p.h"
-
-// Qt
-#include <QtCore/QThread>
-#include <QtCore/qglobal.h>
-#include <QtCore/QCoreApplication>
-#include <QtGui/private/qguiapplication_p.h>
-#include <qpa/qplatforminputcontext.h>
-#include <qpa/qwindowsysteminterface.h>
-#include <QTextCodec>
-
-#include <xkbcommon/xkbcommon.h>
-#include <xkbcommon/xkbcommon-keysyms.h>
-
-#include <mir_toolkit/mir_client_library.h>
-
-Q_LOGGING_CATEGORY(mirclientInput, "qt.qpa.mirclient.input", QtWarningMsg)
-
-namespace
-{
-
-// XKB Keysyms which do not map directly to Qt types (i.e. Unicode points)
-static const uint32_t KeyTable[] = {
- XKB_KEY_Escape, Qt::Key_Escape,
- XKB_KEY_Tab, Qt::Key_Tab,
- XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab,
- XKB_KEY_BackSpace, Qt::Key_Backspace,
- XKB_KEY_Return, Qt::Key_Return,
- XKB_KEY_Insert, Qt::Key_Insert,
- XKB_KEY_Delete, Qt::Key_Delete,
- XKB_KEY_Clear, Qt::Key_Delete,
- XKB_KEY_Pause, Qt::Key_Pause,
- XKB_KEY_Print, Qt::Key_Print,
-
- XKB_KEY_Home, Qt::Key_Home,
- XKB_KEY_End, Qt::Key_End,
- XKB_KEY_Left, Qt::Key_Left,
- XKB_KEY_Up, Qt::Key_Up,
- XKB_KEY_Right, Qt::Key_Right,
- XKB_KEY_Down, Qt::Key_Down,
- XKB_KEY_Prior, Qt::Key_PageUp,
- XKB_KEY_Next, Qt::Key_PageDown,
-
- XKB_KEY_Shift_L, Qt::Key_Shift,
- XKB_KEY_Shift_R, Qt::Key_Shift,
- XKB_KEY_Shift_Lock, Qt::Key_Shift,
- XKB_KEY_Control_L, Qt::Key_Control,
- XKB_KEY_Control_R, Qt::Key_Control,
- XKB_KEY_Meta_L, Qt::Key_Meta,
- XKB_KEY_Meta_R, Qt::Key_Meta,
- XKB_KEY_Alt_L, Qt::Key_Alt,
- XKB_KEY_Alt_R, Qt::Key_Alt,
- XKB_KEY_Caps_Lock, Qt::Key_CapsLock,
- XKB_KEY_Num_Lock, Qt::Key_NumLock,
- XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock,
- XKB_KEY_Super_L, Qt::Key_Super_L,
- XKB_KEY_Super_R, Qt::Key_Super_R,
- XKB_KEY_Menu, Qt::Key_Menu,
- XKB_KEY_Hyper_L, Qt::Key_Hyper_L,
- XKB_KEY_Hyper_R, Qt::Key_Hyper_R,
- XKB_KEY_Help, Qt::Key_Help,
-
- XKB_KEY_KP_Space, Qt::Key_Space,
- XKB_KEY_KP_Tab, Qt::Key_Tab,
- XKB_KEY_KP_Enter, Qt::Key_Enter,
- XKB_KEY_KP_Home, Qt::Key_Home,
- XKB_KEY_KP_Left, Qt::Key_Left,
- XKB_KEY_KP_Up, Qt::Key_Up,
- XKB_KEY_KP_Right, Qt::Key_Right,
- XKB_KEY_KP_Down, Qt::Key_Down,
- XKB_KEY_KP_Prior, Qt::Key_PageUp,
- XKB_KEY_KP_Next, Qt::Key_PageDown,
- XKB_KEY_KP_End, Qt::Key_End,
- XKB_KEY_KP_Begin, Qt::Key_Clear,
- XKB_KEY_KP_Insert, Qt::Key_Insert,
- XKB_KEY_KP_Delete, Qt::Key_Delete,
- XKB_KEY_KP_Equal, Qt::Key_Equal,
- XKB_KEY_KP_Multiply, Qt::Key_Asterisk,
- XKB_KEY_KP_Add, Qt::Key_Plus,
- XKB_KEY_KP_Separator, Qt::Key_Comma,
- XKB_KEY_KP_Subtract, Qt::Key_Minus,
- XKB_KEY_KP_Decimal, Qt::Key_Period,
- XKB_KEY_KP_Divide, Qt::Key_Slash,
-
- XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr,
- XKB_KEY_Multi_key, Qt::Key_Multi_key,
- XKB_KEY_Codeinput, Qt::Key_Codeinput,
- XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate,
- XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate,
- XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate,
-
- // dead keys
- XKB_KEY_dead_grave, Qt::Key_Dead_Grave,
- XKB_KEY_dead_acute, Qt::Key_Dead_Acute,
- XKB_KEY_dead_circumflex, Qt::Key_Dead_Circumflex,
- XKB_KEY_dead_tilde, Qt::Key_Dead_Tilde,
- XKB_KEY_dead_macron, Qt::Key_Dead_Macron,
- XKB_KEY_dead_breve, Qt::Key_Dead_Breve,
- XKB_KEY_dead_abovedot, Qt::Key_Dead_Abovedot,
- XKB_KEY_dead_diaeresis, Qt::Key_Dead_Diaeresis,
- XKB_KEY_dead_abovering, Qt::Key_Dead_Abovering,
- XKB_KEY_dead_doubleacute, Qt::Key_Dead_Doubleacute,
- XKB_KEY_dead_caron, Qt::Key_Dead_Caron,
- XKB_KEY_dead_cedilla, Qt::Key_Dead_Cedilla,
- XKB_KEY_dead_ogonek, Qt::Key_Dead_Ogonek,
- XKB_KEY_dead_iota, Qt::Key_Dead_Iota,
- XKB_KEY_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound,
- XKB_KEY_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound,
- XKB_KEY_dead_belowdot, Qt::Key_Dead_Belowdot,
- XKB_KEY_dead_hook, Qt::Key_Dead_Hook,
- XKB_KEY_dead_horn, Qt::Key_Dead_Horn,
- XKB_KEY_dead_stroke, Qt::Key_Dead_Stroke,
- XKB_KEY_dead_abovecomma, Qt::Key_Dead_Abovecomma,
- XKB_KEY_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma,
- XKB_KEY_dead_doublegrave, Qt::Key_Dead_Doublegrave,
- XKB_KEY_dead_belowring, Qt::Key_Dead_Belowring,
- XKB_KEY_dead_belowmacron, Qt::Key_Dead_Belowmacron,
- XKB_KEY_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex,
- XKB_KEY_dead_belowtilde, Qt::Key_Dead_Belowtilde,
- XKB_KEY_dead_belowbreve, Qt::Key_Dead_Belowbreve,
- XKB_KEY_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis,
- XKB_KEY_dead_invertedbreve, Qt::Key_Dead_Invertedbreve,
- XKB_KEY_dead_belowcomma, Qt::Key_Dead_Belowcomma,
- XKB_KEY_dead_currency, Qt::Key_Dead_Currency,
- XKB_KEY_dead_a, Qt::Key_Dead_a,
- XKB_KEY_dead_A, Qt::Key_Dead_A,
- XKB_KEY_dead_e, Qt::Key_Dead_e,
- XKB_KEY_dead_E, Qt::Key_Dead_E,
- XKB_KEY_dead_i, Qt::Key_Dead_i,
- XKB_KEY_dead_I, Qt::Key_Dead_I,
- XKB_KEY_dead_o, Qt::Key_Dead_o,
- XKB_KEY_dead_O, Qt::Key_Dead_O,
- XKB_KEY_dead_u, Qt::Key_Dead_u,
- XKB_KEY_dead_U, Qt::Key_Dead_U,
- XKB_KEY_dead_small_schwa, Qt::Key_Dead_Small_Schwa,
- XKB_KEY_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa,
- XKB_KEY_dead_greek, Qt::Key_Dead_Greek,
- XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline,
- XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline,
- XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline,
- XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay,
-
- XKB_KEY_Mode_switch, Qt::Key_Mode_switch,
- XKB_KEY_script_switch, Qt::Key_Mode_switch,
- XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp,
- XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown,
- XKB_KEY_XF86PowerOff, Qt::Key_PowerOff,
- XKB_KEY_XF86PowerDown, Qt::Key_PowerDown,
-
- 0, 0
-};
-
-Qt::WindowState mirSurfaceStateToWindowState(MirSurfaceState state)
-{
- switch (state) {
- case mir_surface_state_fullscreen:
- return Qt::WindowFullScreen;
- case mir_surface_state_maximized:
- case mir_surface_state_vertmaximized:
- case mir_surface_state_horizmaximized:
- return Qt::WindowMaximized;
- case mir_surface_state_minimized:
- return Qt::WindowMinimized;
- case mir_surface_state_hidden:
- // We should be handling this state separately.
- Q_ASSERT(false);
- case mir_surface_state_restored:
- case mir_surface_state_unknown:
- default:
- return Qt::WindowNoState;
- }
-}
-
-} // namespace
-
-class UbuntuEvent : public QEvent
-{
-public:
- UbuntuEvent(QMirClientWindow* window, const MirEvent *event, QEvent::Type type)
- : QEvent(type), window(window) {
- nativeEvent = mir_event_ref(event);
- }
- ~UbuntuEvent()
- {
- mir_event_unref(nativeEvent);
- }
-
- QPointer<QMirClientWindow> window;
- const MirEvent *nativeEvent;
-};
-
-QMirClientInput::QMirClientInput(QMirClientClientIntegration* integration)
- : QObject(nullptr)
- , mIntegration(integration)
- , mEventFilterType(static_cast<QMirClientNativeInterface*>(
- integration->nativeInterface())->genericEventFilterType())
- , mEventType(static_cast<QEvent::Type>(QEvent::registerEventType()))
- , mLastInputWindow(nullptr)
-{
- // Initialize touch device.
- mTouchDevice = new QTouchDevice;
- mTouchDevice->setType(QTouchDevice::TouchScreen);
- mTouchDevice->setCapabilities(
- QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure |
- QTouchDevice::NormalizedPosition);
- QWindowSystemInterface::registerTouchDevice(mTouchDevice);
-}
-
-QMirClientInput::~QMirClientInput()
-{
- // Qt will take care of deleting mTouchDevice.
-}
-
-static const char* nativeEventTypeToStr(MirEventType t)
-{
- switch (t)
- {
- case mir_event_type_key:
- return "key";
- case mir_event_type_motion:
- return "motion";
- case mir_event_type_surface:
- return "surface";
- case mir_event_type_resize:
- return "resize";
- case mir_event_type_prompt_session_state_change:
- return "prompt_session_state_change";
- case mir_event_type_orientation:
- return "orientation";
- case mir_event_type_close_surface:
- return "close_surface";
- case mir_event_type_input:
- return "input";
- case mir_event_type_keymap:
- return "keymap";
- case mir_event_type_input_configuration:
- return "input_configuration";
- case mir_event_type_surface_output:
- return "surface_output";
- case mir_event_type_input_device_state:
- return "input_device_state";
- default:
- return "unknown";
- }
-}
-
-void QMirClientInput::customEvent(QEvent* event)
-{
- Q_ASSERT(QThread::currentThread() == thread());
- UbuntuEvent* ubuntuEvent = static_cast<UbuntuEvent*>(event);
- const MirEvent *nativeEvent = ubuntuEvent->nativeEvent;
-
- if ((ubuntuEvent->window == nullptr) || (ubuntuEvent->window->window() == nullptr)) {
- qCWarning(mirclient) << "Attempted to deliver an event to a non-existent window, ignoring.";
- return;
- }
-
- // Event filtering.
- long result;
- if (QWindowSystemInterface::handleNativeEvent(
- ubuntuEvent->window->window(), mEventFilterType,
- const_cast<void *>(static_cast<const void *>(nativeEvent)), &result) == true) {
- qCDebug(mirclient, "event filtered out by native interface");
- return;
- }
-
- qCDebug(mirclientInput, "customEvent(type=%s)", nativeEventTypeToStr(mir_event_get_type(nativeEvent)));
-
- // Event dispatching.
- switch (mir_event_get_type(nativeEvent))
- {
- case mir_event_type_input:
- dispatchInputEvent(ubuntuEvent->window, mir_event_get_input_event(nativeEvent));
- break;
- case mir_event_type_resize:
- {
- auto resizeEvent = mir_event_get_resize_event(nativeEvent);
-
- // Enable workaround for Screen rotation
- auto const targetWindow = ubuntuEvent->window;
- if (targetWindow) {
- auto const screen = static_cast<QMirClientScreen*>(targetWindow->screen());
- if (screen) {
- screen->handleWindowSurfaceResize(
- mir_resize_event_get_width(resizeEvent),
- mir_resize_event_get_height(resizeEvent));
- }
-
- targetWindow->handleSurfaceResized(
- mir_resize_event_get_width(resizeEvent),
- mir_resize_event_get_height(resizeEvent));
- }
- break;
- }
- case mir_event_type_surface:
- handleSurfaceEvent(ubuntuEvent->window, mir_event_get_surface_event(nativeEvent));
- break;
- case mir_event_type_surface_output:
- handleSurfaceOutputEvent(ubuntuEvent->window, mir_event_get_surface_output_event(nativeEvent));
- break;
- case mir_event_type_orientation:
- dispatchOrientationEvent(ubuntuEvent->window->window(), mir_event_get_orientation_event(nativeEvent));
- break;
- case mir_event_type_close_surface:
- QWindowSystemInterface::handleCloseEvent(ubuntuEvent->window->window());
- break;
- default:
- qCDebug(mirclient, "unhandled event type: %d", static_cast<int>(mir_event_get_type(nativeEvent)));
- }
-}
-
-void QMirClientInput::postEvent(QMirClientWindow *platformWindow, const MirEvent *event)
-{
- QWindow *window = platformWindow->window();
-
- QCoreApplication::postEvent(this, new UbuntuEvent(
- platformWindow, event, mEventType));
-
- if ((window->flags().testFlag(Qt::WindowTransparentForInput)) && window->parent()) {
- QCoreApplication::postEvent(this, new UbuntuEvent(
- static_cast<QMirClientWindow*>(platformWindow->QPlatformWindow::parent()),
- event, mEventType));
- }
-}
-
-void QMirClientInput::dispatchInputEvent(QMirClientWindow *window, const MirInputEvent *ev)
-{
- switch (mir_input_event_get_type(ev))
- {
- case mir_input_event_type_key:
- dispatchKeyEvent(window, ev);
- break;
- case mir_input_event_type_touch:
- dispatchTouchEvent(window, ev);
- break;
- case mir_input_event_type_pointer:
- dispatchPointerEvent(window, ev);
- break;
- default:
- break;
- }
-}
-
-void QMirClientInput::dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *ev)
-{
- const MirTouchEvent *tev = mir_input_event_get_touch_event(ev);
-
- // FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That
- // needs to be fixed as soon as the compat input lib adds query support.
- const float kMaxPressure = 1.28;
- const QRect kWindowGeometry = window->geometry();
- QList<QWindowSystemInterface::TouchPoint> touchPoints;
-
-
- // TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left
- // as Qt::TouchPointMoved
- const unsigned int kPointerCount = mir_touch_event_point_count(tev);
- touchPoints.reserve(int(kPointerCount));
- for (unsigned int i = 0; i < kPointerCount; ++i) {
- QWindowSystemInterface::TouchPoint touchPoint;
-
- const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) + kWindowGeometry.x();
- const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere
- const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major);
- const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor);
- const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure);
- touchPoint.id = mir_touch_event_id(tev, i);
- touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());
- touchPoint.area = QRectF(kX - (kW / 2.0), kY - (kH / 2.0), kW, kH);
- touchPoint.pressure = kP / kMaxPressure;
-
- MirTouchAction touch_action = mir_touch_event_action(tev, i);
- switch (touch_action)
- {
- case mir_touch_action_down:
- mLastInputWindow = window;
- touchPoint.state = Qt::TouchPointPressed;
- break;
- case mir_touch_action_up:
- touchPoint.state = Qt::TouchPointReleased;
- break;
- case mir_touch_action_change:
- touchPoint.state = Qt::TouchPointMoved;
- break;
- default:
- Q_UNREACHABLE();
- }
-
- touchPoints.append(touchPoint);
- }
-
- ulong timestamp = mir_input_event_get_event_time(ev) / 1000000;
- QWindowSystemInterface::handleTouchEvent(window->window(), timestamp,
- mTouchDevice, touchPoints);
-}
-
-static uint32_t translateKeysym(uint32_t sym, const QString &text) {
- int code = 0;
-
- QTextCodec *systemCodec = QTextCodec::codecForLocale();
- if (sym < 128 || (sym < 256 && systemCodec->mibEnum() == 4)) {
- // upper-case key, if known
- code = isprint((int)sym) ? toupper((int)sym) : 0;
- } else if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F35) {
- return Qt::Key_F1 + (int(sym) - XKB_KEY_F1);
- } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f
- && text.unicode()->unicode() != 0x7f
- && !(sym >= XKB_KEY_dead_grave && sym <= XKB_KEY_dead_currency)) {
- code = text.unicode()->toUpper().unicode();
- } else {
- for (int i = 0; KeyTable[i]; i += 2)
- if (sym == KeyTable[i])
- code = KeyTable[i + 1];
- }
-
- return code;
-}
-
-namespace
-{
-Qt::KeyboardModifiers qt_modifiers_from_mir(MirInputEventModifiers modifiers)
-{
- Qt::KeyboardModifiers q_modifiers = Qt::NoModifier;
- if (modifiers & mir_input_event_modifier_shift) {
- q_modifiers |= Qt::ShiftModifier;
- }
- if (modifiers & mir_input_event_modifier_ctrl) {
- q_modifiers |= Qt::ControlModifier;
- }
- if (modifiers & mir_input_event_modifier_alt_left) {
- q_modifiers |= Qt::AltModifier;
- }
- if (modifiers & mir_input_event_modifier_meta) {
- q_modifiers |= Qt::MetaModifier;
- }
- if (modifiers & mir_input_event_modifier_alt_right) {
- q_modifiers |= Qt::GroupSwitchModifier;
- }
- return q_modifiers;
-}
-}
-
-void QMirClientInput::dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event)
-{
- const MirKeyboardEvent *key_event = mir_input_event_get_keyboard_event(event);
-
- ulong timestamp = mir_input_event_get_event_time(event) / 1000000;
- xkb_keysym_t xk_sym = mir_keyboard_event_key_code(key_event);
- quint32 scan_code = mir_keyboard_event_scan_code(key_event);
- quint32 native_modifiers = mir_keyboard_event_modifiers(key_event);
-
- // Key modifier and unicode index mapping.
- auto modifiers = qt_modifiers_from_mir(native_modifiers);
-
- MirKeyboardAction action = mir_keyboard_event_action(key_event);
- QEvent::Type keyType = action == mir_keyboard_action_up
- ? QEvent::KeyRelease : QEvent::KeyPress;
-
- if (action == mir_keyboard_action_down)
- mLastInputWindow = window;
-
- QString text;
- QVarLengthArray<char, 32> chars(32);
- {
- int result = xkb_keysym_to_utf8(xk_sym, chars.data(), chars.size());
-
- if (result > 0) {
- text = QString::fromUtf8(chars.constData());
- }
- }
- int sym = translateKeysym(xk_sym, text);
-
- bool is_auto_rep = action == mir_keyboard_action_repeat;
-
- QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
- if (context) {
- QKeyEvent qKeyEvent(keyType, sym, modifiers, scan_code, xk_sym, native_modifiers, text, is_auto_rep);
- qKeyEvent.setTimestamp(timestamp);
- if (context->filterEvent(&qKeyEvent)) {
- qCDebug(mirclient, "key event filtered out by input context");
- return;
- }
- }
-
- QWindowSystemInterface::handleExtendedKeyEvent(window->window(), timestamp, keyType, sym, modifiers, scan_code, xk_sym, native_modifiers, text, is_auto_rep);
-}
-
-namespace
-{
-Qt::MouseButtons extract_buttons(const MirPointerEvent *pev)
-{
- Qt::MouseButtons buttons = Qt::NoButton;
- if (mir_pointer_event_button_state(pev, mir_pointer_button_primary))
- buttons |= Qt::LeftButton;
- if (mir_pointer_event_button_state(pev, mir_pointer_button_secondary))
- buttons |= Qt::RightButton;
- if (mir_pointer_event_button_state(pev, mir_pointer_button_tertiary))
- buttons |= Qt::MiddleButton;
- if (mir_pointer_event_button_state(pev, mir_pointer_button_back))
- buttons |= Qt::BackButton;
- if (mir_pointer_event_button_state(pev, mir_pointer_button_forward))
- buttons |= Qt::ForwardButton;
-
- return buttons;
-}
-}
-
-void QMirClientInput::dispatchPointerEvent(QMirClientWindow *platformWindow, const MirInputEvent *ev)
-{
- const auto window = platformWindow->window();
- const auto timestamp = mir_input_event_get_event_time(ev) / 1000000;
-
- const auto pev = mir_input_event_get_pointer_event(ev);
- const auto action = mir_pointer_event_action(pev);
-
- const auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev));
- const auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x),
- mir_pointer_event_axis_value(pev, mir_pointer_axis_y));
-
- mLastInputWindow = platformWindow;
-
- switch (action) {
- case mir_pointer_action_button_up:
- case mir_pointer_action_button_down:
- case mir_pointer_action_motion:
- {
- const float hDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_hscroll);
- const float vDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_vscroll);
-
- if (hDelta != 0 || vDelta != 0) {
- // QWheelEvent::DefaultDeltasPerStep = 120 but doesn't exist on vivid
- const QPoint angleDelta(120 * hDelta, 120 * vDelta);
- QWindowSystemInterface::handleWheelEvent(window, timestamp, localPoint, window->position() + localPoint,
- QPoint(), angleDelta, modifiers, Qt::ScrollUpdate);
- }
- auto buttons = extract_buttons(pev);
- QWindowSystemInterface::handleMouseEvent(window, timestamp, localPoint, window->position() + localPoint /* Should we omit global point instead? */,
- buttons, modifiers);
- break;
- }
- case mir_pointer_action_enter:
- QWindowSystemInterface::handleEnterEvent(window, localPoint, window->position() + localPoint);
- break;
- case mir_pointer_action_leave:
- QWindowSystemInterface::handleLeaveEvent(window);
- break;
- default:
- Q_UNREACHABLE();
- }
-}
-
-static const char* nativeOrientationDirectionToStr(MirOrientation orientation)
-{
- switch (orientation) {
- case mir_orientation_normal:
- return "Normal";
- case mir_orientation_left:
- return "Left";
- case mir_orientation_inverted:
- return "Inverted";
- case mir_orientation_right:
- return "Right";
- }
- Q_UNREACHABLE();
-}
-
-void QMirClientInput::dispatchOrientationEvent(QWindow *window, const MirOrientationEvent *event)
-{
- MirOrientation mir_orientation = mir_orientation_event_get_direction(event);
- qCDebug(mirclientInput, "orientation direction: %s", nativeOrientationDirectionToStr(mir_orientation));
-
- if (!window->screen()) {
- qCDebug(mirclient, "Window has no associated screen, dropping orientation event");
- return;
- }
-
- OrientationChangeEvent::Orientation orientation;
- switch (mir_orientation) {
- case mir_orientation_normal:
- orientation = OrientationChangeEvent::TopUp;
- break;
- case mir_orientation_left:
- orientation = OrientationChangeEvent::LeftUp;
- break;
- case mir_orientation_inverted:
- orientation = OrientationChangeEvent::TopDown;
- break;
- case mir_orientation_right:
- orientation = OrientationChangeEvent::RightUp;
- break;
- default:
- qCDebug(mirclient, "No such orientation %d", mir_orientation);
- return;
- }
-
- // Dispatch orientation event to [Platform]Screen, as that is where Qt reads it. Screen will handle
- // notifying Qt of the actual orientation change - done to prevent multiple Windows each creating
- // an identical orientation change event and passing it directly to Qt.
- // [Platform]Screen can also factor in the native orientation.
- QCoreApplication::postEvent(static_cast<QMirClientScreen*>(window->screen()->handle()),
- new OrientationChangeEvent(OrientationChangeEvent::mType, orientation));
-}
-
-void QMirClientInput::handleSurfaceEvent(const QPointer<QMirClientWindow> &window, const MirSurfaceEvent *event)
-{
- auto surfaceEventAttribute = mir_surface_event_get_attribute(event);
-
- switch (surfaceEventAttribute) {
- case mir_surface_attrib_focus: {
- window->handleSurfaceFocusChanged(
- mir_surface_event_get_attribute_value(event) == mir_surface_focused);
- break;
- }
- case mir_surface_attrib_visibility: {
- window->handleSurfaceExposeChange(
- mir_surface_event_get_attribute_value(event) == mir_surface_visibility_exposed);
- break;
- }
- // Remaining attributes are ones client sets for server, and server should not override them
- case mir_surface_attrib_state: {
- MirSurfaceState state = static_cast<MirSurfaceState>(mir_surface_event_get_attribute_value(event));
-
- if (state == mir_surface_state_hidden) {
- window->handleSurfaceVisibilityChanged(false);
- } else {
- // it's visible!
- window->handleSurfaceVisibilityChanged(true);
- window->handleSurfaceStateChanged(mirSurfaceStateToWindowState(state));
- }
- break;
- }
- case mir_surface_attrib_type:
- case mir_surface_attrib_swapinterval:
- case mir_surface_attrib_dpi:
- case mir_surface_attrib_preferred_orientation:
- case mir_surface_attribs:
- break;
- }
-}
-
-void QMirClientInput::handleSurfaceOutputEvent(const QPointer<QMirClientWindow> &window, const MirSurfaceOutputEvent *event)
-{
- const uint32_t outputId = mir_surface_output_event_get_output_id(event);
- const int dpi = mir_surface_output_event_get_dpi(event);
- const MirFormFactor formFactor = mir_surface_output_event_get_form_factor(event);
- const float scale = mir_surface_output_event_get_scale(event);
-
- const auto screenObserver = mIntegration->screenObserver();
- QMirClientScreen *screen = screenObserver->findScreenWithId(outputId);
- if (!screen) {
- qCWarning(mirclient) << "Mir notified window" << window->window() << "on an unknown screen with id" << outputId;
- return;
- }
-
- screenObserver->handleScreenPropertiesChange(screen, dpi, formFactor, scale);
- window->handleScreenPropertiesChange(formFactor, scale);
-
- if (window->screen() != screen) {
- QWindowSystemInterface::handleWindowScreenChanged(window->window(), screen->screen());
- }
-}
diff --git a/src/plugins/platforms/mirclient/qmirclientinput.h b/src/plugins/platforms/mirclient/qmirclientinput.h
deleted file mode 100644
index 263cb5e54e..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientinput.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014-2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef QMIRCLIENTINPUT_H
-#define QMIRCLIENTINPUT_H
-
-// Qt
-#include <qpa/qwindowsysteminterface.h>
-
-#include <mir_toolkit/mir_client_library.h>
-
-class QMirClientClientIntegration;
-class QMirClientWindow;
-
-class QMirClientInput : public QObject
-{
- Q_OBJECT
-
-public:
- QMirClientInput(QMirClientClientIntegration* integration);
- virtual ~QMirClientInput();
-
- // QObject methods.
- void customEvent(QEvent* event) override;
-
- void postEvent(QMirClientWindow* window, const MirEvent *event);
- QMirClientClientIntegration* integration() const { return mIntegration; }
- QMirClientWindow *lastInputWindow() const {return mLastInputWindow; }
-
-protected:
- void dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event);
- void dispatchPointerEvent(QMirClientWindow *window, const MirInputEvent *event);
- void dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *event);
- void dispatchInputEvent(QMirClientWindow *window, const MirInputEvent *event);
-
- void dispatchOrientationEvent(QWindow* window, const MirOrientationEvent *event);
- void handleSurfaceEvent(const QPointer<QMirClientWindow> &window, const MirSurfaceEvent *event);
- void handleSurfaceOutputEvent(const QPointer<QMirClientWindow> &window, const MirSurfaceOutputEvent *event);
-
-private:
- QMirClientClientIntegration* mIntegration;
- QTouchDevice* mTouchDevice;
- const QByteArray mEventFilterType;
- const QEvent::Type mEventType;
-
- QMirClientWindow *mLastInputWindow;
-};
-
-#endif // QMIRCLIENTINPUT_H
diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.cpp b/src/plugins/platforms/mirclient/qmirclientintegration.cpp
deleted file mode 100644
index d2b1dbee0d..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientintegration.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014-2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-// Local
-#include "qmirclientintegration.h"
-#include "qmirclientbackingstore.h"
-#include "qmirclientclipboard.h"
-#include "qmirclientdebugextension.h"
-#include "qmirclientdesktopwindow.h"
-#include "qmirclientglcontext.h"
-#include "qmirclientinput.h"
-#include "qmirclientlogging.h"
-#include "qmirclientnativeinterface.h"
-#include "qmirclientscreen.h"
-#include "qmirclienttheme.h"
-#include "qmirclientwindow.h"
-
-// Qt
-#include <QFileInfo>
-#include <QGuiApplication>
-#include <qpa/qplatformnativeinterface.h>
-#include <qpa/qplatforminputcontextfactory_p.h>
-#include <qpa/qplatforminputcontext.h>
-#include <qpa/qwindowsysteminterface.h>
-#include <QtEglSupport/private/qeglconvenience_p.h>
-#include <QtEglSupport/private/qeglpbuffer_p.h>
-#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
-#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
-#ifndef QT_NO_ACCESSIBILITY
-#include <qpa/qplatformaccessibility.h>
-#ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE
-#include <QtLinuxAccessibilitySupport/private/bridge_p.h>
-#endif
-#endif
-
-#include <QOpenGLContext>
-#include <QOffscreenSurface>
-
-// platform-api
-#include <ubuntu/application/lifecycle_delegate.h>
-#include <ubuntu/application/id.h>
-#include <ubuntu/application/options.h>
-
-static void resumedCallback(const UApplicationOptions */*options*/, void* context)
-{
- auto integration = static_cast<QMirClientClientIntegration*>(context);
- integration->appStateController()->setResumed();
-}
-
-static void aboutToStopCallback(UApplicationArchive */*archive*/, void* context)
-{
- auto integration = static_cast<QMirClientClientIntegration*>(context);
- auto inputContext = integration->inputContext();
- if (inputContext) {
- inputContext->hideInputPanel();
- } else {
- qCWarning(mirclient) << "aboutToStopCallback(): no input context";
- }
- integration->appStateController()->setSuspended();
-}
-
-QMirClientClientIntegration::QMirClientClientIntegration(int argc, char **argv)
- : QPlatformIntegration()
- , mNativeInterface(new QMirClientNativeInterface(this))
- , mFontDb(new QGenericUnixFontDatabase)
- , mServices(new QMirClientPlatformServices)
- , mAppStateController(new QMirClientAppStateController)
- , mScaleFactor(1.0)
-{
- {
- QStringList args = QCoreApplication::arguments();
- setupOptions(args);
- QByteArray sessionName = generateSessionName(args);
- setupDescription(sessionName);
- }
-
- // Create new application instance
- mInstance = u_application_instance_new_from_description_with_options(mDesc, mOptions);
-
- if (Q_UNLIKELY(!mInstance))
- qFatal("QMirClientClientIntegration: connection to Mir server failed. Check that a Mir server is\n"
- "running, and the correct socket is being used and is accessible. The shell may have\n"
- "rejected the incoming connection, so check its log file");
-
- mMirConnection = u_application_instance_get_mir_connection(mInstance);
-
- // Choose the default surface format suited to the Mir platform
- QSurfaceFormat defaultFormat;
- defaultFormat.setRedBufferSize(8);
- defaultFormat.setGreenBufferSize(8);
- defaultFormat.setBlueBufferSize(8);
- QSurfaceFormat::setDefaultFormat(defaultFormat);
-
- // Initialize EGL.
- mEglNativeDisplay = mir_connection_get_egl_native_display(mMirConnection);
- ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY);
- ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE);
-
- // Has debug mode been requsted, either with "-testability" switch or QT_LOAD_TESTABILITY env var
- bool testability = qEnvironmentVariableIsSet("QT_LOAD_TESTABILITY");
- for (int i=1; !testability && i<argc; i++) {
- if (strcmp(argv[i], "-testability") == 0) {
- testability = true;
- }
- }
- if (testability) {
- mDebugExtension.reset(new QMirClientDebugExtension);
- }
-}
-
-void QMirClientClientIntegration::initialize()
-{
- // Init the ScreenObserver
- mScreenObserver.reset(new QMirClientScreenObserver(mMirConnection));
- connect(mScreenObserver.data(), &QMirClientScreenObserver::screenAdded,
- [this](QMirClientScreen *screen) { QWindowSystemInterface::handleScreenAdded(screen); });
- connect(mScreenObserver.data(), &QMirClientScreenObserver::screenRemoved,
- this, &QMirClientClientIntegration::destroyScreen);
-
- Q_FOREACH (auto screen, mScreenObserver->screens()) {
- QWindowSystemInterface::handleScreenAdded(screen);
- }
-
- // Initialize input.
- mInput = new QMirClientInput(this);
- mInputContext = QPlatformInputContextFactory::create();
-
- // compute the scale factor
- const int defaultGridUnit = 8;
- int gridUnit = defaultGridUnit;
- QByteArray gridUnitString = qgetenv("GRID_UNIT_PX");
- if (!gridUnitString.isEmpty()) {
- bool ok;
- gridUnit = gridUnitString.toInt(&ok);
- if (!ok) {
- gridUnit = defaultGridUnit;
- }
- }
- mScaleFactor = static_cast<qreal>(gridUnit) / defaultGridUnit;
-}
-
-QMirClientClientIntegration::~QMirClientClientIntegration()
-{
- eglTerminate(mEglDisplay);
- delete mInput;
- delete mInputContext;
- delete mServices;
-}
-
-QPlatformServices *QMirClientClientIntegration::services() const
-{
- return mServices;
-}
-
-void QMirClientClientIntegration::setupOptions(QStringList &args)
-{
- int argc = args.size() + 1;
- char **argv = new char*[argc];
- for (int i = 0; i < argc - 1; i++)
- argv[i] = qstrdup(args.at(i).toLocal8Bit());
- argv[argc - 1] = nullptr;
-
- mOptions = u_application_options_new_from_cmd_line(argc - 1, argv);
-
- for (int i = 0; i < argc; i++)
- delete [] argv[i];
- delete [] argv;
-}
-
-void QMirClientClientIntegration::setupDescription(QByteArray &sessionName)
-{
- mDesc = u_application_description_new();
-
- UApplicationId* id = u_application_id_new_from_stringn(sessionName.data(), sessionName.count());
- u_application_description_set_application_id(mDesc, id);
-
- UApplicationLifecycleDelegate* delegate = u_application_lifecycle_delegate_new();
- u_application_lifecycle_delegate_set_application_resumed_cb(delegate, &resumedCallback);
- u_application_lifecycle_delegate_set_application_about_to_stop_cb(delegate, &aboutToStopCallback);
- u_application_lifecycle_delegate_set_context(delegate, this);
- u_application_description_set_application_lifecycle_delegate(mDesc, delegate);
-}
-
-QByteArray QMirClientClientIntegration::generateSessionName(QStringList &args)
-{
- // Try to come up with some meaningful session name to uniquely identify this session,
- // helping with shell debugging
-
- if (args.count() == 0) {
- return QByteArray("QtUbuntu");
- } if (args[0].contains("qmlscene")) {
- return generateSessionNameFromQmlFile(args);
- } else {
- // use the executable name
- QFileInfo fileInfo(args[0]);
- return fileInfo.fileName().toLocal8Bit();
- }
-}
-
-QByteArray QMirClientClientIntegration::generateSessionNameFromQmlFile(QStringList &args)
-{
- Q_FOREACH (QString arg, args) {
- if (arg.endsWith(".qml")) {
- QFileInfo fileInfo(arg);
- return fileInfo.fileName().toLocal8Bit();
- }
- }
-
- // give up
- return "qmlscene";
-}
-
-QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window) const
-{
- if (window->type() == Qt::Desktop) {
- // Desktop windows should not be backed up by a mir surface as they don't draw anything (nor should).
- return new QMirClientDesktopWindow(window);
- } else {
- return new QMirClientWindow(window, mInput, mNativeInterface, mAppStateController.data(),
- mEglDisplay, mMirConnection, mDebugExtension.data());
- }
-}
-
-bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const
-{
- switch (cap) {
- case ThreadedOpenGL:
- if (qEnvironmentVariableIsEmpty("QTUBUNTU_NO_THREADED_OPENGL")) {
- return true;
- } else {
- qCDebug(mirclient, "disabled threaded OpenGL");
- return false;
- }
-
- case ThreadedPixmaps:
- case OpenGL:
- case ApplicationState:
- case MultipleWindows:
- case NonFullScreenWindows:
-#if QT_VERSION > QT_VERSION_CHECK(5, 5, 0)
- case SwitchableWidgetComposition:
-#endif
- case RasterGLSurface: // needed for QQuickWidget
- return true;
- default:
- return QPlatformIntegration::hasCapability(cap);
- }
-}
-
-QAbstractEventDispatcher *QMirClientClientIntegration::createEventDispatcher() const
-{
- return createUnixEventDispatcher();
-}
-
-QPlatformBackingStore* QMirClientClientIntegration::createPlatformBackingStore(QWindow* window) const
-{
- return new QMirClientBackingStore(window);
-}
-
-QPlatformOpenGLContext* QMirClientClientIntegration::createPlatformOpenGLContext(
- QOpenGLContext* context) const
-{
- QSurfaceFormat format(context->format());
-
- auto platformContext = new QMirClientOpenGLContext(format, context->shareHandle(), mEglDisplay);
- if (!platformContext->isValid()) {
- // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default
- // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a
- // 1.4 context, but the XCB EGL backend tries to honor it, and fails. The 1.4 context appears to
- // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default
- // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455).
- static const bool isMesa = QString(eglQueryString(mEglDisplay, EGL_VENDOR)).contains(QStringLiteral("Mesa"));
- if (isMesa) {
- qCDebug(mirclientGraphics, "Attempting to choose OpenGL 1.4 context which may suit Mesa");
- format.setMajorVersion(1);
- format.setMinorVersion(4);
- delete platformContext;
- platformContext = new QMirClientOpenGLContext(format, context->shareHandle(), mEglDisplay);
- }
- }
- return platformContext;
-}
-
-QStringList QMirClientClientIntegration::themeNames() const
-{
- return QStringList(QMirClientTheme::name);
-}
-
-QPlatformTheme* QMirClientClientIntegration::createPlatformTheme(const QString& name) const
-{
- Q_UNUSED(name);
- return new QMirClientTheme;
-}
-
-QVariant QMirClientClientIntegration::styleHint(StyleHint hint) const
-{
- switch (hint) {
- case QPlatformIntegration::StartDragDistance: {
- // default is 10 pixels (see QPlatformTheme::defaultThemeHint)
- return 10.0 * mScaleFactor;
- }
- case QPlatformIntegration::PasswordMaskDelay: {
- // return time in milliseconds - 1 second
- return QVariant(1000);
- }
- default:
- break;
- }
- return QPlatformIntegration::styleHint(hint);
-}
-
-QPlatformClipboard* QMirClientClientIntegration::clipboard() const
-{
- static QPlatformClipboard *clipboard = nullptr;
- if (!clipboard) {
- clipboard = new QMirClientClipboard;
- }
- return clipboard;
-}
-
-QPlatformNativeInterface* QMirClientClientIntegration::nativeInterface() const
-{
- return mNativeInterface;
-}
-
-QPlatformOffscreenSurface *QMirClientClientIntegration::createPlatformOffscreenSurface(
- QOffscreenSurface *surface) const
-{
- return new QEGLPbuffer(mEglDisplay, surface->requestedFormat(), surface);
-}
-
-void QMirClientClientIntegration::destroyScreen(QMirClientScreen *screen)
-{
- // FIXME: on deleting a screen while a Window is on it, Qt will automatically
- // move the window to the primaryScreen(). This will trigger a screenChanged
- // signal, causing things like QQuickScreenAttached to re-fetch screen properties
- // like DPI and physical size. However this is crashing, as Qt is calling virtual
- // functions on QPlatformScreen, for reasons unclear. As workaround, move window
- // to primaryScreen() before deleting the screen. Might be QTBUG-38650
-
- QScreen *primaryScreen = QGuiApplication::primaryScreen();
- if (screen != primaryScreen->handle()) {
- uint32_t movedWindowCount = 0;
- Q_FOREACH (QWindow *w, QGuiApplication::topLevelWindows()) {
- if (w->screen()->handle() == screen) {
- QWindowSystemInterface::handleWindowScreenChanged(w, primaryScreen);
- ++movedWindowCount;
- }
- }
- if (movedWindowCount > 0) {
- QWindowSystemInterface::flushWindowSystemEvents();
- }
- }
-
- qCDebug(mirclient) << "Removing Screen with id" << screen->mirOutputId() << "and geometry" << screen->geometry();
-#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
- delete screen;
-#else
- QWindowSystemInterface::handleScreenRemoved(screen);
-#endif
-}
-
-#ifndef QT_NO_ACCESSIBILITY
-QPlatformAccessibility *QMirClientClientIntegration::accessibility() const
-{
-#if !defined(QT_NO_ACCESSIBILITY_ATSPI_BRIDGE)
- if (!mAccessibility) {
- Q_ASSERT_X(QCoreApplication::eventDispatcher(), "QMirClientIntegration",
- "Initializing accessibility without event-dispatcher!");
- mAccessibility.reset(new QSpiAccessibleBridge());
- }
-#endif
- return mAccessibility.data();
-}
-#endif
diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.h b/src/plugins/platforms/mirclient/qmirclientintegration.h
deleted file mode 100644
index 035117f4da..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientintegration.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef QMIRCLIENTINTEGRATION_H
-#define QMIRCLIENTINTEGRATION_H
-
-#include <qpa/qplatformintegration.h>
-#include <QSharedPointer>
-
-#include "qmirclientappstatecontroller.h"
-#include "qmirclientplatformservices.h"
-#include "qmirclientscreenobserver.h"
-
-// platform-api
-#include <ubuntu/application/description.h>
-#include <ubuntu/application/instance.h>
-
-#include <EGL/egl.h>
-
-class QMirClientDebugExtension;
-class QMirClientInput;
-class QMirClientNativeInterface;
-class QMirClientScreen;
-class MirConnection;
-
-class QMirClientClientIntegration : public QObject, public QPlatformIntegration
-{
- Q_OBJECT
-
-public:
- QMirClientClientIntegration(int argc, char **argv);
- virtual ~QMirClientClientIntegration();
-
- // QPlatformIntegration methods.
- bool hasCapability(QPlatformIntegration::Capability cap) const override;
- QAbstractEventDispatcher *createEventDispatcher() const override;
- QPlatformNativeInterface* nativeInterface() const override;
- QPlatformBackingStore* createPlatformBackingStore(QWindow* window) const override;
- QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context) const override;
- QPlatformFontDatabase* fontDatabase() const override { return mFontDb; }
- QStringList themeNames() const override;
- QPlatformTheme* createPlatformTheme(const QString& name) const override;
- QVariant styleHint(StyleHint hint) const override;
- QPlatformServices *services() const override;
- QPlatformWindow* createPlatformWindow(QWindow* window) const override;
- QPlatformInputContext* inputContext() const override { return mInputContext; }
- QPlatformClipboard* clipboard() const override;
- void initialize() override;
- QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
- QPlatformAccessibility *accessibility() const override;
-
- // New methods.
- MirConnection *mirConnection() const { return mMirConnection; }
- EGLDisplay eglDisplay() const { return mEglDisplay; }
- EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; }
- QMirClientAppStateController *appStateController() const { return mAppStateController.data(); }
- QMirClientScreenObserver *screenObserver() const { return mScreenObserver.data(); }
- QMirClientDebugExtension *debugExtension() const { return mDebugExtension.data(); }
-
-private Q_SLOTS:
- void destroyScreen(QMirClientScreen *screen);
-
-private:
- void setupOptions(QStringList &args);
- void setupDescription(QByteArray &sessionName);
- static QByteArray generateSessionName(QStringList &args);
- static QByteArray generateSessionNameFromQmlFile(QStringList &args);
-
- QMirClientNativeInterface* mNativeInterface;
- QPlatformFontDatabase* mFontDb;
-
- QMirClientPlatformServices* mServices;
-
- QMirClientInput* mInput;
- QPlatformInputContext* mInputContext;
- mutable QScopedPointer<QPlatformAccessibility> mAccessibility;
- QScopedPointer<QMirClientDebugExtension> mDebugExtension;
- QScopedPointer<QMirClientScreenObserver> mScreenObserver;
- QScopedPointer<QMirClientAppStateController> mAppStateController;
- qreal mScaleFactor;
-
- MirConnection *mMirConnection;
-
- // Platform API stuff
- UApplicationOptions* mOptions;
- UApplicationDescription* mDesc;
- UApplicationInstance* mInstance;
-
- // EGL related
- EGLDisplay mEglDisplay{EGL_NO_DISPLAY};
- EGLNativeDisplayType mEglNativeDisplay;
-};
-
-#endif // QMIRCLIENTINTEGRATION_H
diff --git a/src/plugins/platforms/mirclient/qmirclientlogging.h b/src/plugins/platforms/mirclient/qmirclientlogging.h
deleted file mode 100644
index 4921864ced..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientlogging.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef QMIRCLIENTLOGGING_H
-#define QMIRCLIENTLOGGING_H
-
-#include <QLoggingCategory>
-
-#define ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
-
-Q_DECLARE_LOGGING_CATEGORY(mirclient)
-Q_DECLARE_LOGGING_CATEGORY(mirclientBufferSwap)
-Q_DECLARE_LOGGING_CATEGORY(mirclientInput)
-Q_DECLARE_LOGGING_CATEGORY(mirclientGraphics)
-Q_DECLARE_LOGGING_CATEGORY(mirclientCursor)
-Q_DECLARE_LOGGING_CATEGORY(mirclientDebug)
-
-#endif // QMIRCLIENTLOGGING_H
diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp
deleted file mode 100644
index b85e6fedfa..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-// Local
-#include "qmirclientnativeinterface.h"
-#include "qmirclientscreen.h"
-#include "qmirclientglcontext.h"
-#include "qmirclientwindow.h"
-
-// Qt
-#include <QtGui/private/qguiapplication_p.h>
-#include <QtGui/qopenglcontext.h>
-#include <QtGui/qscreen.h>
-#include <QtCore/QMap>
-
-class UbuntuResourceMap : public QMap<QByteArray, QMirClientNativeInterface::ResourceType>
-{
-public:
- UbuntuResourceMap()
- : QMap<QByteArray, QMirClientNativeInterface::ResourceType>() {
- insert("egldisplay", QMirClientNativeInterface::EglDisplay);
- insert("eglcontext", QMirClientNativeInterface::EglContext);
- insert("nativeorientation", QMirClientNativeInterface::NativeOrientation);
- insert("display", QMirClientNativeInterface::Display);
- insert("mirconnection", QMirClientNativeInterface::MirConnection);
- insert("mirsurface", QMirClientNativeInterface::MirSurface);
- insert("scale", QMirClientNativeInterface::Scale);
- insert("formfactor", QMirClientNativeInterface::FormFactor);
- }
-};
-
-Q_GLOBAL_STATIC(UbuntuResourceMap, ubuntuResourceMap)
-
-QMirClientNativeInterface::QMirClientNativeInterface(const QMirClientClientIntegration *integration)
- : mIntegration(integration)
- , mGenericEventFilterType(QByteArrayLiteral("Event"))
- , mNativeOrientation(nullptr)
-{
-}
-
-QMirClientNativeInterface::~QMirClientNativeInterface()
-{
- delete mNativeOrientation;
- mNativeOrientation = nullptr;
-}
-
-void* QMirClientNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
-{
- const QByteArray lowerCaseResource = resourceString.toLower();
-
- if (!ubuntuResourceMap()->contains(lowerCaseResource)) {
- return nullptr;
- }
-
- const ResourceType resourceType = ubuntuResourceMap()->value(lowerCaseResource);
-
- if (resourceType == QMirClientNativeInterface::MirConnection) {
- return mIntegration->mirConnection();
- } else {
- return nullptr;
- }
-}
-
-void* QMirClientNativeInterface::nativeResourceForContext(
- const QByteArray& resourceString, QOpenGLContext* context)
-{
- if (!context)
- return nullptr;
-
- const QByteArray kLowerCaseResource = resourceString.toLower();
-
- if (!ubuntuResourceMap()->contains(kLowerCaseResource))
- return nullptr;
-
- const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
-
- if (kResourceType == QMirClientNativeInterface::EglContext)
- return static_cast<QMirClientOpenGLContext*>(context->handle())->eglContext();
- else
- return nullptr;
-}
-
-void* QMirClientNativeInterface::nativeResourceForWindow(const QByteArray& resourceString, QWindow* window)
-{
- const QByteArray kLowerCaseResource = resourceString.toLower();
- if (!ubuntuResourceMap()->contains(kLowerCaseResource))
- return NULL;
- const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
-
- switch (kResourceType) {
- case EglDisplay:
- return mIntegration->eglDisplay();
- case NativeOrientation:
- // Return the device's native screen orientation.
- if (window) {
- QMirClientScreen *ubuntuScreen = static_cast<QMirClientScreen*>(window->screen()->handle());
- mNativeOrientation = new Qt::ScreenOrientation(ubuntuScreen->nativeOrientation());
- } else {
- QPlatformScreen *platformScreen = QGuiApplication::primaryScreen()->handle();
- mNativeOrientation = new Qt::ScreenOrientation(platformScreen->nativeOrientation());
- }
- return mNativeOrientation;
- case MirSurface:
- if (window) {
- auto ubuntuWindow = static_cast<QMirClientWindow*>(window->handle());
- if (ubuntuWindow) {
- return ubuntuWindow->mirSurface();
- } else {
- return nullptr;
- }
- } else {
- return nullptr;
- }
- default:
- return nullptr;
- }
-}
-
-void* QMirClientNativeInterface::nativeResourceForScreen(const QByteArray& resourceString, QScreen* screen)
-{
- const QByteArray kLowerCaseResource = resourceString.toLower();
- if (!ubuntuResourceMap()->contains(kLowerCaseResource))
- return NULL;
- const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
- if (!screen)
- screen = QGuiApplication::primaryScreen();
- auto ubuntuScreen = static_cast<QMirClientScreen*>(screen->handle());
- if (kResourceType == QMirClientNativeInterface::Display) {
- return mIntegration->eglNativeDisplay();
- // Changes to the following properties are emitted via the QMirClientNativeInterface::screenPropertyChanged
- // signal fired by QMirClientScreen. Connect to this signal for these properties updates.
- // WARNING: code highly thread unsafe!
- } else if (kResourceType == QMirClientNativeInterface::Scale) {
- // In application code, read with:
- // float scale = *reinterpret_cast<float*>(nativeResourceForScreen("scale", screen()));
- return &ubuntuScreen->mScale;
- } else if (kResourceType == QMirClientNativeInterface::FormFactor) {
- return &ubuntuScreen->mFormFactor;
- } else
- return NULL;
-}
-
-// Changes to these properties are emitted via the QMirClientNativeInterface::windowPropertyChanged
-// signal fired by QMirClientWindow. Connect to this signal for these properties updates.
-QVariantMap QMirClientNativeInterface::windowProperties(QPlatformWindow *window) const
-{
- QVariantMap propertyMap;
- auto w = static_cast<QMirClientWindow*>(window);
- if (w) {
- propertyMap.insert("scale", w->scale());
- propertyMap.insert("formFactor", w->formFactor());
- }
- return propertyMap;
-}
-
-QVariant QMirClientNativeInterface::windowProperty(QPlatformWindow *window, const QString &name) const
-{
- auto w = static_cast<QMirClientWindow*>(window);
- if (!w) {
- return QVariant();
- }
-
- if (name == QStringLiteral("scale")) {
- return w->scale();
- } else if (name == QStringLiteral("formFactor")) {
- return w->formFactor();
- } else {
- return QVariant();
- }
-}
-
-QVariant QMirClientNativeInterface::windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const
-{
- QVariant returnVal = windowProperty(window, name);
- if (!returnVal.isValid()) {
- return defaultValue;
- } else {
- return returnVal;
- }
-}
diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.h b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h
deleted file mode 100644
index eb601de301..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientnativeinterface.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef QMIRCLIENTNATIVEINTERFACE_H
-#define QMIRCLIENTNATIVEINTERFACE_H
-
-#include <qpa/qplatformnativeinterface.h>
-
-#include "qmirclientintegration.h"
-
-class QPlatformScreen;
-
-class QMirClientNativeInterface : public QPlatformNativeInterface {
- Q_OBJECT
-public:
- enum ResourceType { EglDisplay, EglContext, NativeOrientation, Display, MirConnection, MirSurface, Scale, FormFactor };
-
- QMirClientNativeInterface(const QMirClientClientIntegration *integration);
- ~QMirClientNativeInterface();
-
- // QPlatformNativeInterface methods.
- void* nativeResourceForIntegration(const QByteArray &resource) override;
- void* nativeResourceForContext(const QByteArray& resourceString,
- QOpenGLContext* context) override;
- void* nativeResourceForWindow(const QByteArray& resourceString,
- QWindow* window) override;
- void* nativeResourceForScreen(const QByteArray& resourceString,
- QScreen* screen) override;
-
- QVariantMap windowProperties(QPlatformWindow *window) const override;
- QVariant windowProperty(QPlatformWindow *window, const QString &name) const override;
- QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const override;
-
- // New methods.
- const QByteArray& genericEventFilterType() const { return mGenericEventFilterType; }
-
-Q_SIGNALS: // New signals
- void screenPropertyChanged(QPlatformScreen *screen, const QString &propertyName);
-
-private:
- const QMirClientClientIntegration *mIntegration;
- const QByteArray mGenericEventFilterType;
- Qt::ScreenOrientation* mNativeOrientation;
-};
-
-#endif // QMIRCLIENTNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/mirclient/qmirclientplatformservices.cpp b/src/plugins/platforms/mirclient/qmirclientplatformservices.cpp
deleted file mode 100644
index 1ccd57fc28..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientplatformservices.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qmirclientplatformservices.h"
-
-#include <QUrl>
-
-#include <ubuntu/application/url_dispatcher/service.h>
-#include <ubuntu/application/url_dispatcher/session.h>
-
-bool QMirClientPlatformServices::openUrl(const QUrl &url)
-{
- return callDispatcher(url);
-}
-
-bool QMirClientPlatformServices::openDocument(const QUrl &url)
-{
- return callDispatcher(url);
-}
-
-bool QMirClientPlatformServices::callDispatcher(const QUrl &url)
-{
- UAUrlDispatcherSession* session = ua_url_dispatcher_session();
- if (!session)
- return false;
-
- ua_url_dispatcher_session_open(session, url.toEncoded().constData(), NULL, NULL);
-
- free(session);
-
- // We are returning true here because the other option
- // is spawning a nested event loop and wait for the
- // callback. But there is no guarantee on how fast
- // the callback is going to be so we prefer to avoid the
- // nested event loop. Long term plan is improve Qt API
- // to support an async openUrl
- return true;
-}
diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.cpp b/src/plugins/platforms/mirclient/qmirclientscreen.cpp
deleted file mode 100644
index cc8db830aa..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientscreen.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014-2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-// local
-#include "qmirclientscreen.h"
-#include "qmirclientlogging.h"
-#include "qmirclientorientationchangeevent_p.h"
-#include "qmirclientnativeinterface.h"
-
-#include <mir_toolkit/mir_client_library.h>
-
-// Qt
-#include <QGuiApplication>
-#include <QtCore/qmath.h>
-#include <QScreen>
-#include <QThread>
-#include <qpa/qwindowsysteminterface.h>
-#include <QtEglSupport/private/qeglconvenience_p.h>
-
-#include <memory>
-
-static const int overrideDevicePixelRatio = qgetenv("QT_DEVICE_PIXEL_RATIO").toInt();
-
-static const char *orientationToStr(Qt::ScreenOrientation orientation) {
- switch (orientation) {
- case Qt::PrimaryOrientation:
- return "primary";
- case Qt::PortraitOrientation:
- return "portrait";
- case Qt::LandscapeOrientation:
- return "landscape";
- case Qt::InvertedPortraitOrientation:
- return "inverted portrait";
- case Qt::InvertedLandscapeOrientation:
- return "inverted landscape";
- }
- Q_UNREACHABLE();
-}
-
-const QEvent::Type OrientationChangeEvent::mType =
- static_cast<QEvent::Type>(QEvent::registerEventType());
-
-
-QMirClientScreen::QMirClientScreen(const MirOutput *output, MirConnection *connection)
- : mDevicePixelRatio(1.0)
- , mFormat(QImage::Format_RGB32)
- , mDepth(32)
- , mDpi{0}
- , mFormFactor{mir_form_factor_unknown}
- , mScale{1.0}
- , mOutputId(0)
- , mCursor(connection)
-{
- setMirOutput(output);
-}
-
-QMirClientScreen::~QMirClientScreen()
-{
-}
-
-void QMirClientScreen::customEvent(QEvent* event) {
- Q_ASSERT(QThread::currentThread() == thread());
-
- OrientationChangeEvent* oReadingEvent = static_cast<OrientationChangeEvent*>(event);
- switch (oReadingEvent->mOrientation) {
- case OrientationChangeEvent::LeftUp: {
- mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
- Qt::InvertedPortraitOrientation : Qt::LandscapeOrientation;
- break;
- }
- case OrientationChangeEvent::TopUp: {
- mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
- Qt::LandscapeOrientation : Qt::PortraitOrientation;
- break;
- }
- case OrientationChangeEvent::RightUp: {
- mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
- Qt::PortraitOrientation : Qt::InvertedLandscapeOrientation;
- break;
- }
- case OrientationChangeEvent::TopDown: {
- mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
- Qt::InvertedLandscapeOrientation : Qt::InvertedPortraitOrientation;
- break;
- }
- }
-
- // Raise the event signal so that client apps know the orientation changed
- qCDebug(mirclient, "QMirClientScreen::customEvent - handling orientation change to %s", orientationToStr(mCurrentOrientation));
- QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation);
-}
-
-void QMirClientScreen::handleWindowSurfaceResize(int windowWidth, int windowHeight)
-{
- if ((windowWidth > windowHeight && mGeometry.width() < mGeometry.height())
- || (windowWidth < windowHeight && mGeometry.width() > mGeometry.height())) {
-
- // The window aspect ratio differ's from the screen one. This means that
- // unity8 has rotated the window in its scene.
- // As there's no way to express window rotation in Qt's API, we have
- // Flip QScreen's dimensions so that orientation properties match
- // (primaryOrientation particularly).
- // FIXME: This assumes a phone scenario. Won't work, or make sense,
- // on the desktop
-
- QRect currGeometry = mGeometry;
- mGeometry.setWidth(currGeometry.height());
- mGeometry.setHeight(currGeometry.width());
-
- qCDebug(mirclient, "QMirClientScreen::handleWindowSurfaceResize - new screen geometry (w=%d, h=%d)",
- mGeometry.width(), mGeometry.height());
- QWindowSystemInterface::handleScreenGeometryChange(screen(),
- mGeometry /* newGeometry */,
- mGeometry /* newAvailableGeometry */);
-
- if (mGeometry.width() < mGeometry.height()) {
- mCurrentOrientation = Qt::PortraitOrientation;
- } else {
- mCurrentOrientation = Qt::LandscapeOrientation;
- }
- qCDebug(mirclient, "QMirClientScreen::handleWindowSurfaceResize - new orientation %s",orientationToStr(mCurrentOrientation));
- QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation);
- }
-}
-
-void QMirClientScreen::setMirOutput(const MirOutput *output)
-{
- // Physical screen size (in mm)
- mPhysicalSize.setWidth(mir_output_get_physical_width_mm(output));
- mPhysicalSize.setHeight(mir_output_get_physical_height_mm(output));
-
- // Pixel Format
-// mFormat = qImageFormatFromMirPixelFormat(mir_output_get_current_pixel_format(output)); // GERRY: TODO
-
- // Pixel depth
- mDepth = 8 * MIR_BYTES_PER_PIXEL(mir_output_get_current_pixel_format(output));
-
- // Mode = Resolution & refresh rate
- const MirOutputMode *mode = mir_output_get_current_mode(output);
- mNativeGeometry.setX(mir_output_get_position_x(output));
- mNativeGeometry.setY(mir_output_get_position_y(output));
- mNativeGeometry.setWidth(mir_output_mode_get_width(mode));
- mNativeGeometry.setHeight(mir_output_mode_get_height(mode));
-
- mRefreshRate = mir_output_mode_get_refresh_rate(mode);
-
- // UI scale & DPR
- mScale = mir_output_get_scale_factor(output);
- if (overrideDevicePixelRatio > 0) {
- mDevicePixelRatio = overrideDevicePixelRatio;
- } else {
- mDevicePixelRatio = 1.0; // FIXME - need to determine suitable DPR for the specified scale
- }
-
- mFormFactor = mir_output_get_form_factor(output);
-
- mOutputId = mir_output_get_id(output);
-
- mGeometry.setX(mNativeGeometry.x());
- mGeometry.setY(mNativeGeometry.y());
- mGeometry.setWidth(mNativeGeometry.width());
- mGeometry.setHeight(mNativeGeometry.height());
-
- // Set the default orientation based on the initial screen dimensions.
- mNativeOrientation = (mGeometry.width() >= mGeometry.height()) ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
-
- // If it's a landscape device (i.e. some tablets), start in landscape, otherwise portrait
- mCurrentOrientation = (mNativeOrientation == Qt::LandscapeOrientation) ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
-}
-
-void QMirClientScreen::updateMirOutput(const MirOutput *output)
-{
- auto oldRefreshRate = mRefreshRate;
- auto oldScale = mScale;
- auto oldFormFactor = mFormFactor;
- auto oldGeometry = mGeometry;
-
- setMirOutput(output);
-
- // Emit change signals in particular order
- if (oldGeometry != mGeometry) {
- QWindowSystemInterface::handleScreenGeometryChange(screen(),
- mGeometry /* newGeometry */,
- mGeometry /* newAvailableGeometry */);
- }
-
- if (!qFuzzyCompare(mRefreshRate, oldRefreshRate)) {
- QWindowSystemInterface::handleScreenRefreshRateChange(screen(), mRefreshRate);
- }
-
- auto nativeInterface = static_cast<QMirClientNativeInterface *>(qGuiApp->platformNativeInterface());
- if (!qFuzzyCompare(mScale, oldScale)) {
- nativeInterface->screenPropertyChanged(this, QStringLiteral("scale"));
- }
- if (mFormFactor != oldFormFactor) {
- nativeInterface->screenPropertyChanged(this, QStringLiteral("formFactor"));
- }
-}
-
-void QMirClientScreen::setAdditionalMirDisplayProperties(float scale, MirFormFactor formFactor, int dpi)
-{
- if (mDpi != dpi) {
- mDpi = dpi;
- QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), dpi, dpi);
- }
-
- auto nativeInterface = static_cast<QMirClientNativeInterface *>(qGuiApp->platformNativeInterface());
- if (!qFuzzyCompare(mScale, scale)) {
- mScale = scale;
- nativeInterface->screenPropertyChanged(this, QStringLiteral("scale"));
- }
- if (mFormFactor != formFactor) {
- mFormFactor = formFactor;
- nativeInterface->screenPropertyChanged(this, QStringLiteral("formFactor"));
- }
-}
-
-QDpi QMirClientScreen::logicalDpi() const
-{
- if (mDpi > 0) {
- return QDpi(mDpi, mDpi);
- } else {
- return QPlatformScreen::logicalDpi();
- }
-}
diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.h b/src/plugins/platforms/mirclient/qmirclientscreen.h
deleted file mode 100644
index b31cba1964..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientscreen.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014-2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef QMIRCLIENTSCREEN_H
-#define QMIRCLIENTSCREEN_H
-
-#include <qpa/qplatformscreen.h>
-#include <QSurfaceFormat>
-
-#include <mir_toolkit/common.h> // just for MirFormFactor enum
-
-#include "qmirclientcursor.h"
-
-struct MirConnection;
-struct MirOutput;
-
-class QMirClientScreen : public QObject, public QPlatformScreen
-{
- Q_OBJECT
-public:
- QMirClientScreen(const MirOutput *output, MirConnection *connection);
- virtual ~QMirClientScreen();
-
- // QPlatformScreen methods.
- QImage::Format format() const override { return mFormat; }
- int depth() const override { return mDepth; }
- QRect geometry() const override { return mGeometry; }
- QRect availableGeometry() const override { return mGeometry; }
- QSizeF physicalSize() const override { return mPhysicalSize; }
- qreal devicePixelRatio() const override { return mDevicePixelRatio; }
- QDpi logicalDpi() const override;
- Qt::ScreenOrientation nativeOrientation() const override { return mNativeOrientation; }
- Qt::ScreenOrientation orientation() const override { return mNativeOrientation; }
- QPlatformCursor *cursor() const override { return const_cast<QMirClientCursor*>(&mCursor); }
-
- // Additional Screen properties from Mir
- int mirOutputId() const { return mOutputId; }
- MirFormFactor formFactor() const { return mFormFactor; }
- float scale() const { return mScale; }
-
- // Internally used methods
- void updateMirOutput(const MirOutput *output);
- void setAdditionalMirDisplayProperties(float scale, MirFormFactor formFactor, int dpi);
- void handleWindowSurfaceResize(int width, int height);
-
- // QObject methods.
- void customEvent(QEvent* event) override;
-
-private:
- void setMirOutput(const MirOutput *output);
-
- QRect mGeometry, mNativeGeometry;
- QSizeF mPhysicalSize;
- qreal mDevicePixelRatio;
- Qt::ScreenOrientation mNativeOrientation;
- Qt::ScreenOrientation mCurrentOrientation;
- QImage::Format mFormat;
- int mDepth;
- int mDpi;
- qreal mRefreshRate;
- MirFormFactor mFormFactor;
- float mScale;
- int mOutputId;
- QMirClientCursor mCursor;
-
- friend class QMirClientNativeInterface;
-};
-
-#endif // QMIRCLIENTSCREEN_H
diff --git a/src/plugins/platforms/mirclient/qmirclientscreenobserver.cpp b/src/plugins/platforms/mirclient/qmirclientscreenobserver.cpp
deleted file mode 100644
index 792aeca351..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientscreenobserver.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qmirclientscreenobserver.h"
-#include "qmirclientscreen.h"
-#include "qmirclientwindow.h"
-#include "qmirclientlogging.h"
-
-// Qt
-#include <QMetaObject>
-#include <QPointer>
-
-// Mir
-#include <mirclient/mir_toolkit/mir_connection.h>
-#include <mirclient/mir_toolkit/mir_display_configuration.h>
-
-#include <memory>
-
-namespace {
- static void displayConfigurationChangedCallback(MirConnection */*connection*/, void* context)
- {
- ASSERT(context != NULL);
- QMirClientScreenObserver *observer = static_cast<QMirClientScreenObserver *>(context);
- QMetaObject::invokeMethod(observer, "update");
- }
-
- const char *mirFormFactorToStr(MirFormFactor formFactor)
- {
- switch (formFactor) {
- case mir_form_factor_unknown: return "unknown";
- case mir_form_factor_phone: return "phone";
- case mir_form_factor_tablet: return "tablet";
- case mir_form_factor_monitor: return "monitor";
- case mir_form_factor_tv: return "tv";
- case mir_form_factor_projector: return "projector";
- }
- Q_UNREACHABLE();
- }
-} // anonymous namespace
-
-QMirClientScreenObserver::QMirClientScreenObserver(MirConnection *mirConnection)
- : mMirConnection(mirConnection)
-{
- mir_connection_set_display_config_change_callback(mirConnection, ::displayConfigurationChangedCallback, this);
- update();
-}
-
-void QMirClientScreenObserver::update()
-{
- // Wrap MirDisplayConfiguration to always delete when out of scope
- auto configDeleter = [](MirDisplayConfig *config) { mir_display_config_release(config); };
- using configUp = std::unique_ptr<MirDisplayConfig, decltype(configDeleter)>;
- configUp displayConfig(mir_connection_create_display_configuration(mMirConnection), configDeleter);
-
- // Mir only tells us something changed, it is up to us to figure out what.
- QList<QMirClientScreen*> newScreenList;
- QList<QMirClientScreen*> oldScreenList = mScreenList;
- mScreenList.clear();
-
- for (int i = 0; i < mir_display_config_get_num_outputs(displayConfig.get()); i++) {
- const MirOutput *output = mir_display_config_get_output(displayConfig.get(), i);
- if (mir_output_is_enabled(output)) {
- QMirClientScreen *screen = findScreenWithId(oldScreenList, mir_output_get_id(output));
- if (screen) { // we've already set up this display before
- screen->updateMirOutput(output);
- oldScreenList.removeAll(screen);
- } else {
- // new display, so create QMirClientScreen for it
- screen = new QMirClientScreen(output, mMirConnection);
- newScreenList.append(screen);
- qCDebug(mirclient) << "Added Screen with id" << mir_output_get_id(output)
- << "and geometry" << screen->geometry();
- }
- mScreenList.append(screen);
- }
- }
-
- // Announce old & unused Screens, should be deleted by the slot
- Q_FOREACH (const auto screen, oldScreenList) {
- Q_EMIT screenRemoved(screen);
- }
-
- /*
- * Mir's MirDisplayOutput does not include formFactor or scale for some reason, but Qt
- * will want that information on creating the QScreen. Only way we get that info is when
- * Mir positions a Window on that Screen. See "handleScreenPropertiesChange" method
- */
-
- // Announce new Screens
- Q_FOREACH (const auto screen, newScreenList) {
- Q_EMIT screenAdded(screen);
- }
-
- qCDebug(mirclient) << "=======================================";
- for (auto screen: mScreenList) {
- qCDebug(mirclient) << screen << "- id:" << screen->mirOutputId()
- << "geometry:" << screen->geometry()
- << "form factor:" << mirFormFactorToStr(screen->formFactor())
- << "scale:" << screen->scale();
- }
- qCDebug(mirclient) << "=======================================";
-}
-
-QMirClientScreen *QMirClientScreenObserver::findScreenWithId(int id)
-{
- return findScreenWithId(mScreenList, id);
-}
-
-QMirClientScreen *QMirClientScreenObserver::findScreenWithId(const QList<QMirClientScreen *> &list, int id)
-{
- Q_FOREACH (const auto screen, list) {
- if (screen->mirOutputId() == id) {
- return screen;
- }
- }
- return nullptr;
-}
-
-void QMirClientScreenObserver::handleScreenPropertiesChange(QMirClientScreen *screen, int dpi,
- MirFormFactor formFactor, float scale)
-{
- screen->setAdditionalMirDisplayProperties(scale, formFactor, dpi);
-}
-
diff --git a/src/plugins/platforms/mirclient/qmirclienttheme.h b/src/plugins/platforms/mirclient/qmirclienttheme.h
deleted file mode 100644
index 4bab1d0ee0..0000000000
--- a/src/plugins/platforms/mirclient/qmirclienttheme.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef QMIRCLIENTTHEME_H
-#define QMIRCLIENTTHEME_H
-
-#include <QtThemeSupport/private/qgenericunixthemes_p.h>
-
-class QMirClientTheme : public QGenericUnixTheme
-{
-public:
- static const char* name;
- QMirClientTheme();
- virtual ~QMirClientTheme();
-
- // From QPlatformTheme
- QVariant themeHint(ThemeHint hint) const override;
-};
-
-#endif // QMIRCLIENTTHEME_H
diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.cpp b/src/plugins/platforms/mirclient/qmirclientwindow.cpp
deleted file mode 100644
index decd21516e..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientwindow.cpp
+++ /dev/null
@@ -1,968 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014-2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-// Local
-#include "qmirclientwindow.h"
-#include "qmirclientdebugextension.h"
-#include "qmirclientnativeinterface.h"
-#include "qmirclientinput.h"
-#include "qmirclientintegration.h"
-#include "qmirclientscreen.h"
-#include "qmirclientlogging.h"
-
-#include <mir_toolkit/mir_client_library.h>
-#include <mir_toolkit/version.h>
-
-// Qt
-#include <qpa/qwindowsysteminterface.h>
-#include <QMutexLocker>
-#include <QSize>
-#include <QtMath>
-#include <QtEglSupport/private/qeglconvenience_p.h>
-
-// Platform API
-#include <ubuntu/application/instance.h>
-
-#include <EGL/egl.h>
-
-Q_LOGGING_CATEGORY(mirclientBufferSwap, "qt.qpa.mirclient.bufferSwap", QtWarningMsg)
-
-namespace
-{
-const Qt::WindowType LowChromeWindowHint = (Qt::WindowType)0x00800000;
-
-// FIXME: this used to be defined by platform-api, but it's been removed in v3. Change ubuntu-keyboard to use
-// a different enum for window roles.
-enum UAUiWindowRole {
- U_MAIN_ROLE = 1,
- U_DASH_ROLE,
- U_INDICATOR_ROLE,
- U_NOTIFICATIONS_ROLE,
- U_GREETER_ROLE,
- U_LAUNCHER_ROLE,
- U_ON_SCREEN_KEYBOARD_ROLE,
- U_SHUTDOWN_DIALOG_ROLE,
-};
-
-struct MirSpecDeleter
-{
- void operator()(MirSurfaceSpec *spec) { mir_surface_spec_release(spec); }
-};
-
-using Spec = std::unique_ptr<MirSurfaceSpec, MirSpecDeleter>;
-
-EGLNativeWindowType nativeWindowFor(MirSurface *surf)
-{
- auto stream = mir_surface_get_buffer_stream(surf);
- return reinterpret_cast<EGLNativeWindowType>(mir_buffer_stream_get_egl_native_window(stream));
-}
-
-const char *qtWindowStateToStr(Qt::WindowState state)
-{
- switch (state) {
- case Qt::WindowNoState:
- return "NoState";
- case Qt::WindowFullScreen:
- return "FullScreen";
- case Qt::WindowMaximized:
- return "Maximized";
- case Qt::WindowMinimized:
- return "Minimized";
- case Qt::WindowActive:
- return "Active";
- }
- Q_UNREACHABLE();
-}
-
-const char *mirSurfaceStateToStr(MirSurfaceState surfaceState)
-{
- switch (surfaceState) {
- case mir_surface_state_unknown: return "unknown";
- case mir_surface_state_restored: return "restored";
- case mir_surface_state_minimized: return "minimized";
- case mir_surface_state_maximized: return "vertmaximized";
- case mir_surface_state_vertmaximized: return "vertmaximized";
- case mir_surface_state_fullscreen: return "fullscreen";
- case mir_surface_state_horizmaximized: return "horizmaximized";
- case mir_surface_state_hidden: return "hidden";
- case mir_surface_states: Q_UNREACHABLE();
- }
- Q_UNREACHABLE();
-}
-
-const char *mirPixelFormatToStr(MirPixelFormat pixelFormat)
-{
- switch (pixelFormat) {
- case mir_pixel_format_invalid: return "invalid";
- case mir_pixel_format_abgr_8888: return "ABGR8888";
- case mir_pixel_format_xbgr_8888: return "XBGR8888";
- case mir_pixel_format_argb_8888: return "ARGB8888";
- case mir_pixel_format_xrgb_8888: return "XRGB8888";
- case mir_pixel_format_bgr_888: return "BGR888";
- case mir_pixel_format_rgb_888: return "RGB888";
- case mir_pixel_format_rgb_565: return "RGB565";
- case mir_pixel_format_rgba_5551: return "RGBA5551";
- case mir_pixel_format_rgba_4444: return "RGBA4444";
- case mir_pixel_formats: Q_UNREACHABLE();
- }
- Q_UNREACHABLE();
-}
-
-const char *mirSurfaceTypeToStr(MirSurfaceType type)
-{
- switch (type) {
- case mir_surface_type_normal: return "Normal"; /**< AKA "regular" */
- case mir_surface_type_utility: return "Utility"; /**< AKA "floating regular" */
- case mir_surface_type_dialog: return "Dialog";
- case mir_surface_type_gloss: return "Gloss";
- case mir_surface_type_freestyle: return "Freestyle";
- case mir_surface_type_menu: return "Menu";
- case mir_surface_type_inputmethod: return "Input Method"; /**< AKA "OSK" or handwriting etc. */
- case mir_surface_type_satellite: return "Satellite"; /**< AKA "toolbox"/"toolbar" */
- case mir_surface_type_tip: return "Tip"; /**< AKA "tooltip" */
- case mir_surface_types: Q_UNREACHABLE();
- }
- return "";
-}
-
-MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
-{
- switch (state) {
- case Qt::WindowNoState:
- case Qt::WindowActive:
- return mir_surface_state_restored;
- case Qt::WindowFullScreen:
- return mir_surface_state_fullscreen;
- case Qt::WindowMaximized:
- return mir_surface_state_maximized;
- case Qt::WindowMinimized:
- return mir_surface_state_minimized;
- }
- return mir_surface_state_unknown; // should never be reached
-}
-
-MirSurfaceType qtWindowTypeToMirSurfaceType(Qt::WindowType type)
-{
- switch (type & Qt::WindowType_Mask) {
- case Qt::Dialog:
- return mir_surface_type_dialog;
- case Qt::Sheet:
- case Qt::Drawer:
- return mir_surface_type_utility;
- case Qt::Popup:
- case Qt::Tool:
- return mir_surface_type_menu;
- case Qt::ToolTip:
- return mir_surface_type_tip;
- case Qt::SplashScreen:
- return mir_surface_type_freestyle;
- case Qt::Window:
- default:
- return mir_surface_type_normal;
- }
-}
-
-WId makeId()
-{
- static int id = 1;
- return id++;
-}
-
-UAUiWindowRole roleFor(QWindow *window)
-{
- QVariant roleVariant = window->property("role");
- if (!roleVariant.isValid())
- return U_MAIN_ROLE;
-
- uint role = roleVariant.toUInt();
- if (role < U_MAIN_ROLE || role > U_SHUTDOWN_DIALOG_ROLE)
- return U_MAIN_ROLE;
-
- return static_cast<UAUiWindowRole>(role);
-}
-
-QMirClientWindow *transientParentFor(QWindow *window)
-{
- QWindow *parent = window->transientParent();
- return parent ? static_cast<QMirClientWindow *>(parent->handle()) : nullptr;
-}
-
-bool requiresParent(const MirSurfaceType type)
-{
- switch (type) {
- case mir_surface_type_dialog: //FIXME - not quite what the specification dictates, but is what Mir's api dictates
- case mir_surface_type_utility:
- case mir_surface_type_gloss:
- case mir_surface_type_menu:
- case mir_surface_type_satellite:
- case mir_surface_type_tip:
- return true;
- default:
- return false;
- }
-}
-
-bool requiresParent(const Qt::WindowType type)
-{
- return requiresParent(qtWindowTypeToMirSurfaceType(type));
-}
-
-bool isMovable(const Qt::WindowType type)
-{
- auto mirType = qtWindowTypeToMirSurfaceType(type);
- switch (mirType) {
- case mir_surface_type_menu:
- case mir_surface_type_tip:
- return true;
- default:
- return false;
- }
-}
-
-Spec makeSurfaceSpec(QWindow *window, MirPixelFormat pixelFormat, QMirClientWindow *parentWindowHandle,
- MirConnection *connection)
-{
- const auto geometry = window->geometry();
- const int width = geometry.width() > 0 ? geometry.width() : 1;
- const int height = geometry.height() > 0 ? geometry.height() : 1;
- auto type = qtWindowTypeToMirSurfaceType(window->type());
-
- if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) {
- type = mir_surface_type_inputmethod;
- }
-
- MirRectangle location{geometry.x(), geometry.y(), 0, 0};
- MirSurface *parent = nullptr;
- if (parentWindowHandle) {
- parent = parentWindowHandle->mirSurface();
- // Qt uses absolute positioning, but Mir positions surfaces relative to parent.
- location.top -= parentWindowHandle->geometry().top();
- location.left -= parentWindowHandle->geometry().left();
- }
-
- Spec spec;
-
- switch (type) {
- case mir_surface_type_menu:
- spec = Spec{mir_connection_create_spec_for_menu(connection, width, height, pixelFormat, parent,
- &location, mir_edge_attachment_any)};
- break;
- case mir_surface_type_dialog:
- spec = Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent)};
- break;
- case mir_surface_type_utility:
- spec = Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)};
- break;
- case mir_surface_type_tip:
-#if MIR_CLIENT_VERSION < MIR_VERSION_NUMBER(3, 4, 0)
- spec = Spec{mir_connection_create_spec_for_tooltip(connection, width, height, pixelFormat, parent,
- &location)};
-#else
- spec = Spec{mir_connection_create_spec_for_tip(connection, width, height, pixelFormat, parent,
- &location, mir_edge_attachment_any)};
-#endif
- break;
- case mir_surface_type_inputmethod:
- spec = Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)};
- break;
- default:
- spec = Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)};
- break;
- }
-
- qCDebug(mirclient, "makeSurfaceSpec(window=%p): %s spec (type=0x%x, position=(%d, %d)px, size=(%dx%d)px)",
- window, mirSurfaceTypeToStr(type), window->type(), location.left, location.top, width, height);
-
- return std::move(spec);
-}
-
-void setSizingConstraints(MirSurfaceSpec *spec, const QSize& minSize, const QSize& maxSize, const QSize& increment)
-{
- mir_surface_spec_set_min_width(spec, minSize.width());
- mir_surface_spec_set_min_height(spec, minSize.height());
- if (maxSize.width() >= minSize.width()) {
- mir_surface_spec_set_max_width(spec, maxSize.width());
- }
- if (maxSize.height() >= minSize.height()) {
- mir_surface_spec_set_max_height(spec, maxSize.height());
- }
- if (increment.width() > 0) {
- mir_surface_spec_set_width_increment(spec, increment.width());
- }
- if (increment.height() > 0) {
- mir_surface_spec_set_height_increment(spec, increment.height());
- }
-}
-
-MirSurface *createMirSurface(QWindow *window, int mirOutputId, QMirClientWindow *parentWindowHandle,
- MirPixelFormat pixelFormat, MirConnection *connection,
- mir_surface_event_callback inputCallback, void *inputContext)
-{
- auto spec = makeSurfaceSpec(window, pixelFormat, parentWindowHandle, connection);
-
- // Install event handler as early as possible
- mir_surface_spec_set_event_handler(spec.get(), inputCallback, inputContext);
-
- const auto title = window->title().toUtf8();
- mir_surface_spec_set_name(spec.get(), title.constData());
-
- setSizingConstraints(spec.get(), window->minimumSize(), window->maximumSize(), window->sizeIncrement());
-
- if (window->windowState() == Qt::WindowFullScreen) {
- mir_surface_spec_set_fullscreen_on_output(spec.get(), mirOutputId);
- }
-
- if (window->flags() & LowChromeWindowHint) {
- mir_surface_spec_set_shell_chrome(spec.get(), mir_shell_chrome_low);
- }
-
- if (!window->isVisible()) {
- mir_surface_spec_set_state(spec.get(), mir_surface_state_hidden);
- }
-
- auto surface = mir_surface_create_sync(spec.get());
- Q_ASSERT(mir_surface_is_valid(surface));
- return surface;
-}
-
-QMirClientWindow *getParentIfNecessary(QWindow *window, QMirClientInput *input)
-{
- QMirClientWindow *parentWindowHandle = nullptr;
- if (requiresParent(window->type())) {
- parentWindowHandle = transientParentFor(window);
- if (parentWindowHandle == nullptr) {
- // NOTE: Mir requires this surface have a parent. Try using the last surface to receive input as that will
- // most likely be the one that caused this surface to be created
- parentWindowHandle = input->lastInputWindow();
- }
- }
- return parentWindowHandle;
-}
-
-MirPixelFormat disableAlphaBufferIfPossible(MirPixelFormat pixelFormat)
-{
- switch (pixelFormat) {
- case mir_pixel_format_abgr_8888:
- return mir_pixel_format_xbgr_8888;
- case mir_pixel_format_argb_8888:
- return mir_pixel_format_xrgb_8888;
- default: // can do nothing, leave it alone
- return pixelFormat;
- }
-}
-} //namespace
-
-
-
-class UbuntuSurface
-{
-public:
- UbuntuSurface(QMirClientWindow *platformWindow, EGLDisplay display, QMirClientInput *input, MirConnection *connection);
- ~UbuntuSurface();
-
- UbuntuSurface(const UbuntuSurface &) = delete;
- UbuntuSurface& operator=(const UbuntuSurface &) = delete;
-
- void updateGeometry(const QRect &newGeometry);
- void updateTitle(const QString& title);
- void setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment);
-
- void onSwapBuffersDone();
- void handleSurfaceResized(int width, int height);
- int needsRepaint() const;
-
- MirSurfaceState state() const { return mir_surface_get_state(mMirSurface); }
- void setState(MirSurfaceState state);
-
- MirSurfaceType type() const { return mir_surface_get_type(mMirSurface); }
-
- void setShellChrome(MirShellChrome shellChrome);
-
- EGLSurface eglSurface() const { return mEglSurface; }
- MirSurface *mirSurface() const { return mMirSurface; }
-
- void setSurfaceParent(MirSurface*);
- bool hasParent() const { return mParented; }
-
- QSurfaceFormat format() const { return mFormat; }
-
- bool mNeedsExposeCatchup;
-
- QString persistentSurfaceId();
-
-private:
- static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context);
- void postEvent(const MirEvent *event);
-
- QWindow * const mWindow;
- QMirClientWindow * const mPlatformWindow;
- QMirClientInput * const mInput;
- MirConnection * const mConnection;
- QMirClientWindow * mParentWindowHandle{nullptr};
-
- MirSurface* mMirSurface;
- const EGLDisplay mEglDisplay;
- EGLSurface mEglSurface;
-
- bool mNeedsRepaint;
- bool mParented;
- QSize mBufferSize;
- QSurfaceFormat mFormat;
- MirPixelFormat mPixelFormat;
-
- QMutex mTargetSizeMutex;
- QSize mTargetSize;
- MirShellChrome mShellChrome;
- QString mPersistentIdStr;
-};
-
-UbuntuSurface::UbuntuSurface(QMirClientWindow *platformWindow, EGLDisplay display, QMirClientInput *input, MirConnection *connection)
- : mWindow(platformWindow->window())
- , mPlatformWindow(platformWindow)
- , mInput(input)
- , mConnection(connection)
- , mEglDisplay(display)
- , mNeedsRepaint(false)
- , mParented(mWindow->transientParent() || mWindow->parent())
- , mFormat(mWindow->requestedFormat())
- , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal)
-{
- // Have Qt choose most suitable EGLConfig for the requested surface format, and update format to reflect it
- EGLConfig config = q_configFromGLFormat(display, mFormat, true);
- if (config == 0) {
- // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default
- // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a
- // 1.4 context, but the XCB EGL backend tries to honor it, and fails. The 1.4 context appears to
- // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default
- // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455).
- static const bool isMesa = QString(eglQueryString(display, EGL_VENDOR)).contains(QStringLiteral("Mesa"));
- if (isMesa) {
- qCDebug(mirclientGraphics, "Attempting to choose OpenGL 1.4 context which may suit Mesa");
- mFormat.setMajorVersion(1);
- mFormat.setMinorVersion(4);
- config = q_configFromGLFormat(display, mFormat, true);
- }
- }
- if (config == 0) {
- qCritical() << "Qt failed to choose a suitable EGLConfig to suit the surface format" << mFormat;
- }
-
- mFormat = q_glFormatFromConfig(display, config, mFormat);
-
- // Have Mir decide the pixel format most suited to the chosen EGLConfig. This is the only way
- // Mir will know what EGLConfig has been chosen - it cannot deduce it from the buffers.
- mPixelFormat = mir_connection_get_egl_pixel_format(connection, display, config);
- // But the chosen EGLConfig might have an alpha buffer enabled, even if not requested by the client.
- // If that's the case, try to edit the chosen pixel format in order to disable the alpha buffer.
- // This is an optimization for the compositor, as it can avoid blending this surface.
- if (mWindow->requestedFormat().alphaBufferSize() < 0) {
- mPixelFormat = disableAlphaBufferIfPossible(mPixelFormat);
- }
-
- const auto outputId = static_cast<QMirClientScreen *>(mWindow->screen()->handle())->mirOutputId();
-
- mParentWindowHandle = getParentIfNecessary(mWindow, input);
-
- mMirSurface = createMirSurface(mWindow, outputId, mParentWindowHandle, mPixelFormat, connection, surfaceEventCallback, this);
- mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirSurface), nullptr);
-
- mNeedsExposeCatchup = mir_surface_get_visibility(mMirSurface) == mir_surface_visibility_occluded;
-
- // Window manager can give us a final size different from what we asked for
- // so let's check what we ended up getting
- MirSurfaceParameters parameters;
- mir_surface_get_parameters(mMirSurface, &parameters);
-
- auto geom = mWindow->geometry();
- geom.setWidth(parameters.width);
- geom.setHeight(parameters.height);
-
- // Assume that the buffer size matches the surface size at creation time
- mBufferSize = geom.size();
- QWindowSystemInterface::handleGeometryChange(mWindow, geom);
-
- qCDebug(mirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title()
- << "role:" << roleFor(mWindow);
- qCDebug(mirclientGraphics)
- << "Requested format:" << mWindow->requestedFormat()
- << "\nActual format:" << mFormat
- << "with associated Mir pixel format:" << mirPixelFormatToStr(mPixelFormat);
-}
-
-UbuntuSurface::~UbuntuSurface()
-{
- if (mEglSurface != EGL_NO_SURFACE)
- eglDestroySurface(mEglDisplay, mEglSurface);
- if (mMirSurface) {
- mir_surface_release_sync(mMirSurface);
- }
-}
-
-void UbuntuSurface::updateGeometry(const QRect &newGeometry)
-{
- qCDebug(mirclient,"updateGeometry(window=%p, width=%d, height=%d)", mWindow,
- newGeometry.width(), newGeometry.height());
-
- Spec spec;
- if (isMovable(mWindow->type())) {
- spec = Spec{makeSurfaceSpec(mWindow, mPixelFormat, mParentWindowHandle, mConnection)};
- } else {
- spec = Spec{mir_connection_create_spec_for_changes(mConnection)};
- mir_surface_spec_set_width(spec.get(), newGeometry.width());
- mir_surface_spec_set_height(spec.get(), newGeometry.height());
- }
- mir_surface_apply_spec(mMirSurface, spec.get());
-}
-
-void UbuntuSurface::updateTitle(const QString& newTitle)
-{
- const auto title = newTitle.toUtf8();
- Spec spec{mir_connection_create_spec_for_changes(mConnection)};
- mir_surface_spec_set_name(spec.get(), title.constData());
- mir_surface_apply_spec(mMirSurface, spec.get());
-}
-
-void UbuntuSurface::setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment)
-{
- Spec spec{mir_connection_create_spec_for_changes(mConnection)};
- ::setSizingConstraints(spec.get(), minSize, maxSize, increment);
- mir_surface_apply_spec(mMirSurface, spec.get());
-}
-
-void UbuntuSurface::handleSurfaceResized(int width, int height)
-{
- QMutexLocker lock(&mTargetSizeMutex);
-
- // mir's resize event is mainly a signal that we need to redraw our content. We use the
- // width/height as identifiers to figure out if this is the latest surface resize event
- // that has posted, discarding any old ones. This avoids issuing too many redraw events.
- // see TODO in postEvent as the ideal way we should handle this.
- // The actual buffer size may or may have not changed at this point, so let the rendering
- // thread drive the window geometry updates.
- mNeedsRepaint = mTargetSize.width() == width && mTargetSize.height() == height;
-}
-
-int UbuntuSurface::needsRepaint() const
-{
- if (mNeedsRepaint) {
- if (mTargetSize != mBufferSize) {
- //If the buffer hasn't changed yet, we need at least two redraws,
- //once to get the new buffer size and propagate the geometry changes
- //and the second to redraw the content at the new size
- return 2;
- } else {
- // The buffer size has already been updated so we only need one redraw
- // to render at the new size
- return 1;
- }
- }
- return 0;
-}
-
-void UbuntuSurface::setState(MirSurfaceState state)
-{
- mir_wait_for(mir_surface_set_state(mMirSurface, state));
-}
-
-void UbuntuSurface::setShellChrome(MirShellChrome chrome)
-{
- if (chrome != mShellChrome) {
- auto spec = Spec{mir_connection_create_spec_for_changes(mConnection)};
- mir_surface_spec_set_shell_chrome(spec.get(), chrome);
- mir_surface_apply_spec(mMirSurface, spec.get());
-
- mShellChrome = chrome;
- }
-}
-
-void UbuntuSurface::onSwapBuffersDone()
-{
- static int sFrameNumber = 0;
- ++sFrameNumber;
-
- EGLint eglSurfaceWidth = -1;
- EGLint eglSurfaceHeight = -1;
- eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidth);
- eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeight);
-
- const bool validSize = eglSurfaceWidth > 0 && eglSurfaceHeight > 0;
-
- if (validSize && (mBufferSize.width() != eglSurfaceWidth || mBufferSize.height() != eglSurfaceHeight)) {
-
- qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - size changed (%d, %d) => (%d, %d)",
- mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height(), eglSurfaceWidth, eglSurfaceHeight);
-
- mBufferSize.rwidth() = eglSurfaceWidth;
- mBufferSize.rheight() = eglSurfaceHeight;
-
- QRect newGeometry = mPlatformWindow->geometry();
- newGeometry.setSize(mBufferSize);
-
- QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry);
- } else {
- qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size (%d,%d)",
- mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height());
- }
-}
-
-void UbuntuSurface::surfaceEventCallback(MirSurface *surface, const MirEvent *event, void* context)
-{
- Q_UNUSED(surface);
- Q_ASSERT(context != nullptr);
-
- auto s = static_cast<UbuntuSurface *>(context);
- s->postEvent(event);
-}
-
-void UbuntuSurface::postEvent(const MirEvent *event)
-{
- if (mir_event_type_resize == mir_event_get_type(event)) {
- // TODO: The current event queue just accumulates all resize events;
- // It would be nicer if we could update just one event if that event has not been dispatched.
- // As a workaround, we use the width/height as an identifier of this latest event
- // so the event handler (handleSurfaceResized) can discard/ignore old ones.
- const auto resizeEvent = mir_event_get_resize_event(event);
- const auto width = mir_resize_event_get_width(resizeEvent);
- const auto height = mir_resize_event_get_height(resizeEvent);
- qCDebug(mirclient, "resizeEvent(window=%p, width=%d, height=%d)", mWindow, width, height);
-
- QMutexLocker lock(&mTargetSizeMutex);
- mTargetSize.rwidth() = width;
- mTargetSize.rheight() = height;
- }
-
- mInput->postEvent(mPlatformWindow, event);
-}
-
-void UbuntuSurface::setSurfaceParent(MirSurface* parent)
-{
- qCDebug(mirclient, "setSurfaceParent(window=%p)", mWindow);
-
- mParented = true;
- Spec spec{mir_connection_create_spec_for_changes(mConnection)};
- mir_surface_spec_set_parent(spec.get(), parent);
- mir_surface_apply_spec(mMirSurface, spec.get());
-}
-
-QString UbuntuSurface::persistentSurfaceId()
-{
- if (mPersistentIdStr.isEmpty()) {
- MirPersistentId* mirPermaId = mir_surface_request_persistent_id_sync(mMirSurface);
- mPersistentIdStr = mir_persistent_id_as_string(mirPermaId);
- mir_persistent_id_release(mirPermaId);
- }
- return mPersistentIdStr;
-}
-
-QMirClientWindow::QMirClientWindow(QWindow *w, QMirClientInput *input, QMirClientNativeInterface *native,
- QMirClientAppStateController *appState, EGLDisplay eglDisplay,
- MirConnection *mirConnection, QMirClientDebugExtension *debugExt)
- : QObject(nullptr)
- , QPlatformWindow(w)
- , mId(makeId())
- , mWindowState(w->windowState())
- , mWindowFlags(w->flags())
- , mWindowVisible(false)
- , mAppStateController(appState)
- , mDebugExtention(debugExt)
- , mNativeInterface(native)
- , mSurface(new UbuntuSurface{this, eglDisplay, input, mirConnection})
- , mScale(1.0)
- , mFormFactor(mir_form_factor_unknown)
-{
- mWindowExposed = mSurface->mNeedsExposeCatchup == false;
-
- qCDebug(mirclient, "QMirClientWindow(window=%p, screen=%p, input=%p, surf=%p) with title '%s', role: '%d'",
- w, w->screen()->handle(), input, mSurface.get(), qPrintable(window()->title()), roleFor(window()));
-}
-
-QMirClientWindow::~QMirClientWindow()
-{
- qCDebug(mirclient, "~QMirClientWindow(window=%p)", this);
-}
-
-void QMirClientWindow::handleSurfaceResized(int width, int height)
-{
- QMutexLocker lock(&mMutex);
- qCDebug(mirclient, "handleSurfaceResize(window=%p, size=(%dx%d)px", window(), width, height);
-
- mSurface->handleSurfaceResized(width, height);
-
- // This resize event could have occurred just after the last buffer swap for this window.
- // This means the client may still be holding a buffer with the older size. The first redraw call
- // will then render at the old size. After swapping the client now will get a new buffer with the
- // updated size but it still needs re-rendering so another redraw may be needed.
- // A mir API to drop the currently held buffer would help here, so that we wouldn't have to redraw twice
- auto const numRepaints = mSurface->needsRepaint();
- lock.unlock();
- qCDebug(mirclient, "handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints);
- for (int i = 0; i < numRepaints; i++) {
- qCDebug(mirclient, "handleSurfaceResize(window=%p) repainting size=(%dx%d)dp", window(), geometry().size().width(), geometry().size().height());
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
- }
-}
-
-void QMirClientWindow::handleSurfaceExposeChange(bool exposed)
-{
- QMutexLocker lock(&mMutex);
- qCDebug(mirclient, "handleSurfaceExposeChange(window=%p, exposed=%s)", window(), exposed ? "true" : "false");
-
- mSurface->mNeedsExposeCatchup = false;
- if (mWindowExposed == exposed) return;
- mWindowExposed = exposed;
-
- lock.unlock();
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
-}
-
-void QMirClientWindow::handleSurfaceFocusChanged(bool focused)
-{
- qCDebug(mirclient, "handleSurfaceFocusChanged(window=%p, focused=%d)", window(), focused);
- if (focused) {
- mAppStateController->setWindowFocused(true);
- QWindowSystemInterface::handleWindowActivated(window(), Qt::ActiveWindowFocusReason);
- } else {
- mAppStateController->setWindowFocused(false);
- }
-}
-
-void QMirClientWindow::handleSurfaceVisibilityChanged(bool visible)
-{
- qCDebug(mirclient, "handleSurfaceVisibilityChanged(window=%p, visible=%d)", window(), visible);
-
- if (mWindowVisible == visible) return;
- mWindowVisible = visible;
-
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
-}
-
-void QMirClientWindow::handleSurfaceStateChanged(Qt::WindowState state)
-{
- qCDebug(mirclient, "handleSurfaceStateChanged(window=%p, %s)", window(), qtWindowStateToStr(state));
-
- if (mWindowState == state) return;
- mWindowState = state;
-
- QWindowSystemInterface::handleWindowStateChanged(window(), state);
-}
-
-void QMirClientWindow::setWindowState(Qt::WindowStates states)
-{
- Qt::WindowState state = Qt::WindowNoState;
- if (states & Qt::WindowMinimized)
- state = Qt::WindowMinimized;
- else if (states & Qt::WindowFullScreen)
- state = Qt::WindowFullScreen;
- else if (states & Qt::WindowMaximized)
- state = Qt::WindowMaximized;
-
- QMutexLocker lock(&mMutex);
- qCDebug(mirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));
-
- if (mWindowState == state) return;
- mWindowState = state;
-
- lock.unlock();
- updateSurfaceState();
-}
-
-void QMirClientWindow::setWindowFlags(Qt::WindowFlags flags)
-{
- QMutexLocker lock(&mMutex);
- qCDebug(mirclient, "setWindowFlags(window=%p, 0x%x)", this, (int)flags);
-
- if (mWindowFlags == flags) return;
- mWindowFlags = flags;
-
- mSurface->setShellChrome(mWindowFlags & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal);
-}
-
-QRect QMirClientWindow::geometry() const
-{
- if (mDebugExtention) {
- auto geom = QPlatformWindow::geometry();
- geom.moveTopLeft(mDebugExtention->mapSurfacePointToScreen(mSurface->mirSurface(), QPoint(0,0)));
- return geom;
- } else {
- return QPlatformWindow::geometry();
- }
-}
-
-void QMirClientWindow::setGeometry(const QRect& rect)
-{
- QMutexLocker lock(&mMutex);
-
- if (window()->windowState() == Qt::WindowFullScreen || window()->windowState() == Qt::WindowMaximized) {
- qCDebug(mirclient, "setGeometry(window=%p) - not resizing, window is maximized or fullscreen", window());
- return;
- }
-
- qCDebug(mirclient, "setGeometry (window=%p, position=(%d, %d)dp, size=(%dx%d)dp)",
- window(), rect.x(), rect.y(), rect.width(), rect.height());
- // Immediately update internal geometry so Qt believes position updated
- QRect newPosition(geometry());
- newPosition.moveTo(rect.topLeft());
- QPlatformWindow::setGeometry(newPosition);
-
- mSurface->updateGeometry(rect);
- // Note: don't call handleGeometryChange here, wait to see what Mir replies with.
-}
-
-void QMirClientWindow::setVisible(bool visible)
-{
- QMutexLocker lock(&mMutex);
- qCDebug(mirclient, "setVisible (window=%p, visible=%s)", window(), visible ? "true" : "false");
-
- if (mWindowVisible == visible) return;
- mWindowVisible = visible;
-
- if (visible) {
- if (!mSurface->hasParent() && window()->type() == Qt::Dialog) {
- // The dialog may have been parented after creation time
- // so morph it into a modal dialog
- auto parent = transientParentFor(window());
- if (parent) {
- mSurface->setSurfaceParent(parent->mirSurface());
- }
- }
- }
-
- lock.unlock();
- updateSurfaceState();
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
-}
-
-void QMirClientWindow::setWindowTitle(const QString& title)
-{
- QMutexLocker lock(&mMutex);
- qCDebug(mirclient, "setWindowTitle(window=%p) title=%s)", window(), title.toUtf8().constData());
- mSurface->updateTitle(title);
-}
-
-void QMirClientWindow::propagateSizeHints()
-{
- QMutexLocker lock(&mMutex);
- const auto win = window();
- qCDebug(mirclient, "propagateSizeHints(window=%p) min(%d,%d), max(%d,%d) increment(%d, %d)",
- win, win->minimumSize().width(), win->minimumSize().height(),
- win->maximumSize().width(), win->maximumSize().height(),
- win->sizeIncrement().width(), win->sizeIncrement().height());
- mSurface->setSizingConstraints(win->minimumSize(), win->maximumSize(), win->sizeIncrement());
-}
-
-bool QMirClientWindow::isExposed() const
-{
- // mNeedsExposeCatchup because we need to render a frame to get the expose surface event from mir.
- return mWindowVisible && (mWindowExposed || (mSurface && mSurface->mNeedsExposeCatchup));
-}
-
-QSurfaceFormat QMirClientWindow::format() const
-{
- return mSurface->format();
-}
-
-QPoint QMirClientWindow::mapToGlobal(const QPoint &pos) const
-{
- if (mDebugExtention) {
- return mDebugExtention->mapSurfacePointToScreen(mSurface->mirSurface(), pos);
- } else {
- return pos;
- }
-}
-
-void* QMirClientWindow::eglSurface() const
-{
- return mSurface->eglSurface();
-}
-
-MirSurface *QMirClientWindow::mirSurface() const
-{
- return mSurface->mirSurface();
-}
-
-WId QMirClientWindow::winId() const
-{
- return mId;
-}
-
-void QMirClientWindow::onSwapBuffersDone()
-{
- QMutexLocker lock(&mMutex);
- mSurface->onSwapBuffersDone();
-
- if (mSurface->mNeedsExposeCatchup) {
- mSurface->mNeedsExposeCatchup = false;
- mWindowExposed = false;
-
- lock.unlock();
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
- }
-}
-
-void QMirClientWindow::handleScreenPropertiesChange(MirFormFactor formFactor, float scale)
-{
- // Update the scale & form factor native-interface properties for the windows affected
- // as there is no convenient way to emit signals for those custom properties on a QScreen
- if (formFactor != mFormFactor) {
- mFormFactor = formFactor;
- Q_EMIT mNativeInterface->windowPropertyChanged(this, QStringLiteral("formFactor"));
- }
-
- if (!qFuzzyCompare(scale, mScale)) {
- mScale = scale;
- Q_EMIT mNativeInterface->windowPropertyChanged(this, QStringLiteral("scale"));
- }
-}
-
-void QMirClientWindow::updateSurfaceState()
-{
- QMutexLocker lock(&mMutex);
- MirSurfaceState newState = mWindowVisible ? qtWindowStateToMirSurfaceState(mWindowState) :
- mir_surface_state_hidden;
- qCDebug(mirclient, "updateSurfaceState (window=%p, surfaceState=%s)", window(), mirSurfaceStateToStr(newState));
- if (newState != mSurface->state()) {
- mSurface->setState(newState);
- }
-}
-
-QString QMirClientWindow::persistentSurfaceId()
-{
- return mSurface->persistentSurfaceId();
-}
diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.h b/src/plugins/platforms/mirclient/qmirclientwindow.h
deleted file mode 100644
index 6c5695d62f..0000000000
--- a/src/plugins/platforms/mirclient/qmirclientwindow.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014-2016 Canonical, Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef QMIRCLIENTWINDOW_H
-#define QMIRCLIENTWINDOW_H
-
-#include <qpa/qplatformwindow.h>
-#include <QSharedPointer>
-#include <QMutex>
-
-#include <mir_toolkit/common.h> // needed only for MirFormFactor enum
-
-#include <memory>
-
-#include <EGL/egl.h>
-
-class QMirClientAppStateController;
-class QMirClientDebugExtension;
-class QMirClientNativeInterface;
-class QMirClientInput;
-class QMirClientScreen;
-class UbuntuSurface;
-struct MirSurface;
-class MirConnection;
-
-class QMirClientWindow : public QObject, public QPlatformWindow
-{
- Q_OBJECT
-public:
- QMirClientWindow(QWindow *w, QMirClientInput *input, QMirClientNativeInterface* native,
- QMirClientAppStateController *appState, EGLDisplay eglDisplay,
- MirConnection *mirConnection, QMirClientDebugExtension *debugExt);
- virtual ~QMirClientWindow();
-
- // QPlatformWindow methods.
- WId winId() const override;
- QRect geometry() const override;
- void setGeometry(const QRect&) override;
- void setWindowState(Qt::WindowStates state) override;
- void setWindowFlags(Qt::WindowFlags flags) override;
- void setVisible(bool visible) override;
- void setWindowTitle(const QString &title) override;
- void propagateSizeHints() override;
- bool isExposed() const override;
-
- QPoint mapToGlobal(const QPoint &pos) const override;
- QSurfaceFormat format() const override;
-
- // Additional Window properties exposed by NativeInterface
- MirFormFactor formFactor() const { return mFormFactor; }
- float scale() const { return mScale; }
-
- // New methods.
- void *eglSurface() const;
- MirSurface *mirSurface() const;
- void handleSurfaceResized(int width, int height);
- void handleSurfaceExposeChange(bool exposed);
- void handleSurfaceFocusChanged(bool focused);
- void handleSurfaceVisibilityChanged(bool visible);
- void handleSurfaceStateChanged(Qt::WindowState state);
- void onSwapBuffersDone();
- void handleScreenPropertiesChange(MirFormFactor formFactor, float scale);
- QString persistentSurfaceId();
-
-private:
- void updateSurfaceState();
- mutable QMutex mMutex;
- const WId mId;
- Qt::WindowState mWindowState;
- Qt::WindowFlags mWindowFlags;
- bool mWindowVisible;
- bool mWindowExposed;
- QMirClientAppStateController *mAppStateController;
- QMirClientDebugExtension *mDebugExtention;
- QMirClientNativeInterface *mNativeInterface;
- std::unique_ptr<UbuntuSurface> mSurface;
- float mScale;
- MirFormFactor mFormFactor;
-};
-
-#endif // QMIRCLIENTWINDOW_H
diff --git a/src/plugins/platforms/offscreen/offscreen.pro b/src/plugins/platforms/offscreen/offscreen.pro
index 392ee8bed1..f226132592 100644
--- a/src/plugins/platforms/offscreen/offscreen.pro
+++ b/src/plugins/platforms/offscreen/offscreen.pro
@@ -17,13 +17,10 @@ HEADERS = qoffscreenintegration.h \
OTHER_FILES += offscreen.json
-qtConfig(system-xcb):qtConfig(xlib):qtConfig(opengl):!qtConfig(opengles2) {
+qtConfig(xlib):qtConfig(opengl):!qtConfig(opengles2) {
SOURCES += qoffscreenintegration_x11.cpp
HEADERS += qoffscreenintegration_x11.h
QT += glx_support-private
- system(echo "Using X11 offscreen integration with GLX")
-} else {
- SOURCES += qoffscreenintegration_dummy.cpp
}
PLUGIN_TYPE = platforms
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
index ef3b0dd3ff..869e9228cd 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
@@ -67,6 +67,10 @@
#include <qpa/qplatformservices.h>
+#if QT_CONFIG(xlib) && QT_CONFIG(opengl) && !QT_CONFIG(opengles2)
+#include "qoffscreenintegration_x11.h"
+#endif
+
QT_BEGIN_NAMESPACE
class QCoreTextFontEngine;
@@ -220,4 +224,14 @@ QPlatformServices *QOffscreenIntegration::services() const
return m_services.data();
}
+QOffscreenIntegration *QOffscreenIntegration::createOffscreenIntegration()
+{
+#if QT_CONFIG(xlib) && QT_CONFIG(opengl) && !QT_CONFIG(opengles2)
+ QByteArray glx = qgetenv("QT_QPA_OFFSCREEN_NO_GLX");
+ if (glx.isEmpty())
+ return new QOffscreenX11Integration;
+#endif
+ return new QOffscreenIntegration;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.h b/src/plugins/platforms/offscreen/qoffscreenintegration.h
index fc988126bb..098e726550 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration.h
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration.h
@@ -41,6 +41,7 @@
#define QOFFSCREENINTEGRATION_H
#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformnativeinterface.h>
#include <qscopedpointer.h>
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
index 93566220e8..92fc8aa57a 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
@@ -41,6 +41,7 @@
#include <QByteArray>
#include <QOpenGLContext>
+#include <QtPlatformHeaders/QGLXNativeContext>
#include <X11/Xlib.h>
#include <GL/glx.h>
@@ -52,16 +53,36 @@
QT_BEGIN_NAMESPACE
-QOffscreenIntegration *QOffscreenIntegration::createOffscreenIntegration()
+class QOffscreenX11Info
{
- return new QOffscreenX11Integration;
-}
+public:
+ QOffscreenX11Info(QOffscreenX11Connection *connection)
+ : m_connection(connection)
+ {
+ }
+
+ Display *display() const {
+ return (Display *)m_connection->display();
+ }
+
+ Window root() const {
+ return DefaultRootWindow(display());
+ }
+
+ int screenNumber() const {
+ return m_connection->screenNumber();
+ }
+
+private:
+ QOffscreenX11Connection *m_connection;
+};
bool QOffscreenX11Integration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
case OpenGL: return true;
case ThreadedOpenGL: return true;
+ case RasterGLSurface: return true;
default: return QOffscreenIntegration::hasCapability(cap);
}
}
@@ -77,6 +98,40 @@ QPlatformOpenGLContext *QOffscreenX11Integration::createPlatformOpenGLContext(QO
return new QOffscreenX11GLXContext(m_connection->x11Info(), context);
}
+QPlatformNativeInterface *QOffscreenX11Integration::nativeInterface() const
+{
+ return const_cast<QOffscreenX11Integration *>(this);
+}
+
+void *QOffscreenX11Integration::nativeResourceForScreen(const QByteArray &resource, QScreen *screen)
+{
+ Q_UNUSED(screen)
+ if (resource.toLower() == QByteArrayLiteral("display") ) {
+ if (!m_connection)
+ m_connection.reset(new QOffscreenX11Connection);
+ return m_connection->display();
+ }
+ return nullptr;
+}
+
+#ifndef QT_NO_OPENGL
+void *QOffscreenX11Integration::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) {
+ if (resource.toLower() == QByteArrayLiteral("glxconfig") ) {
+ if (context) {
+ QOffscreenX11GLXContext *glxPlatformContext = static_cast<QOffscreenX11GLXContext *>(context->handle());
+ return glxPlatformContext->glxConfig();
+ }
+ }
+ if (resource.toLower() == QByteArrayLiteral("glxcontext") ) {
+ if (context) {
+ QOffscreenX11GLXContext *glxPlatformContext = static_cast<QOffscreenX11GLXContext *>(context->handle());
+ return glxPlatformContext->glxContext();
+ }
+ }
+ return nullptr;
+}
+#endif
+
QOffscreenX11Connection::QOffscreenX11Connection()
{
XInitThreads();
@@ -93,30 +148,6 @@ QOffscreenX11Connection::~QOffscreenX11Connection()
XCloseDisplay((Display *)m_display);
}
-class QOffscreenX11Info
-{
-public:
- QOffscreenX11Info(QOffscreenX11Connection *connection)
- : m_connection(connection)
- {
- }
-
- Display *display() const {
- return (Display *)m_connection->display();
- }
-
- Window root() const {
- return DefaultRootWindow(display());
- }
-
- int screenNumber() const {
- return m_connection->screenNumber();
- }
-
-private:
- QOffscreenX11Connection *m_connection;
-};
-
QOffscreenX11Info *QOffscreenX11Connection::x11Info()
{
if (!m_x11Info)
@@ -127,11 +158,12 @@ QOffscreenX11Info *QOffscreenX11Connection::x11Info()
class QOffscreenX11GLXContextData
{
public:
- QOffscreenX11Info *x11;
+ QOffscreenX11Info *x11 = nullptr;
QSurfaceFormat format;
- GLXContext context;
- GLXContext shareContext;
- Window window;
+ GLXContext context = nullptr;
+ GLXContext shareContext = nullptr;
+ GLXFBConfig config = nullptr;
+ Window window = 0;
};
static Window createDummyWindow(QOffscreenX11Info *x11, XVisualInfo *visualInfo)
@@ -142,6 +174,7 @@ static Window createDummyWindow(QOffscreenX11Info *x11, XVisualInfo *visualInfo)
a.border_pixel = BlackPixel(x11->display(), x11->screenNumber());
a.colormap = cmap;
+
Window window = XCreateWindow(x11->display(), x11->root(),
0, 0, 100, 100,
0, visualInfo->depth, InputOutput, visualInfo->visual,
@@ -163,14 +196,23 @@ static Window createDummyWindow(QOffscreenX11Info *x11, GLXFBConfig config)
QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGLContext *context)
: d(new QOffscreenX11GLXContextData)
{
+
d->x11 = x11;
d->format = context->format();
+ if (d->format.renderableType() == QSurfaceFormat::DefaultRenderableType)
+ d->format.setRenderableType(QSurfaceFormat::OpenGL);
+
+ if (d->format.renderableType() != QSurfaceFormat::OpenGL)
+ return;
+
d->shareContext = 0;
if (context->shareHandle())
d->shareContext = static_cast<QOffscreenX11GLXContext *>(context->shareHandle())->d->context;
GLXFBConfig config = qglx_findConfig(x11->display(), x11->screenNumber(), d->format);
+ d->config = config;
+
if (config) {
d->context = glXCreateNewContext(x11->display(), config, GLX_RGBA_TYPE, d->shareContext, true);
if (!d->context && d->shareContext) {
@@ -199,6 +241,9 @@ QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGL
d->window = createDummyWindow(x11, visualInfo);
XFree(visualInfo);
}
+ if (d->context)
+ context->setNativeHandle(QVariant::fromValue<QGLXNativeContext>(QGLXNativeContext(d->context)));
+
}
QOffscreenX11GLXContext::~QOffscreenX11GLXContext()
@@ -251,4 +296,14 @@ bool QOffscreenX11GLXContext::isValid() const
return d->context && d->window;
}
+void *QOffscreenX11GLXContext::glxContext() const
+{
+ return d->context;
+}
+
+void *QOffscreenX11GLXContext::glxConfig() const
+{
+ return d->config;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h
index 5e1c6b799b..5ef51a15a8 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h
@@ -52,12 +52,19 @@ QT_BEGIN_NAMESPACE
class QOffscreenX11Connection;
class QOffscreenX11Info;
-class QOffscreenX11Integration : public QOffscreenIntegration
+class QOffscreenX11Integration : public QOffscreenIntegration, public QPlatformNativeInterface
{
public:
bool hasCapability(QPlatformIntegration::Capability cap) const override;
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
+ QPlatformNativeInterface *nativeInterface()const override;
+
+ // QPlatformNativeInterface
+ void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) override;
+#ifndef QT_NO_OPENGL
+ void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override;
+#endif
private:
mutable QScopedPointer<QOffscreenX11Connection> m_connection;
@@ -97,6 +104,9 @@ public:
bool isSharing() const override;
bool isValid() const override;
+ void *glxConfig() const;
+ void *glxContext() const;
+
private:
QScopedPointer<QOffscreenX11GLXContextData> d;
};
diff --git a/src/plugins/platforms/openwfd/qopenwfdscreen.h b/src/plugins/platforms/openwfd/qopenwfdscreen.h
index dede0025a9..dec51d306b 100644
--- a/src/plugins/platforms/openwfd/qopenwfdscreen.h
+++ b/src/plugins/platforms/openwfd/qopenwfdscreen.h
@@ -48,7 +48,6 @@
#include <WF/wfd.h>
#include <QtCore/QVarLengthArray>
-#include <QtCore/QLinkedList>
#define BUFFER_NUM 4
diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro
index acc55adf6f..c4f2b30965 100644
--- a/src/plugins/platforms/platforms.pro
+++ b/src/plugins/platforms/platforms.pro
@@ -48,6 +48,4 @@ haiku {
wasm: SUBDIRS += wasm
-qtConfig(mirclient): SUBDIRS += mirclient
-
qtConfig(integrityfb): SUBDIRS += integrity
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index 96bfa1dd19..bfd56e8d13 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -33,6 +33,7 @@ QT += \
SOURCES = main.cpp \
qqnxbuffer.cpp \
+ qqnxforeignwindow.cpp \
qqnxintegration.cpp \
qqnxscreen.cpp \
qqnxwindow.cpp \
@@ -50,6 +51,7 @@ SOURCES = main.cpp \
HEADERS = main.h \
qqnxbuffer.h \
+ qqnxforeignwindow.h \
qqnxkeytranslator.h \
qqnxintegration.h \
qqnxscreen.h \
diff --git a/src/plugins/platforms/mirclient/qmirclienttheme.cpp b/src/plugins/platforms/qnx/qqnxforeignwindow.cpp
index dcfef7ca67..94608215dc 100644
--- a/src/plugins/platforms/mirclient/qmirclienttheme.cpp
+++ b/src/plugins/platforms/qnx/qqnxforeignwindow.cpp
@@ -1,6 +1,6 @@
-/****************************************************************************
+/***************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2018 QNX Software Systems. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -37,31 +37,29 @@
**
****************************************************************************/
+#include "qqnxforeignwindow.h"
+#include "qqnxintegration.h"
-#include "qmirclienttheme.h"
+QT_BEGIN_NAMESPACE
-#include <QtCore/QVariant>
-
-const char *QMirClientTheme::name = "ubuntu";
-
-QMirClientTheme::QMirClientTheme()
+QQnxForeignWindow::QQnxForeignWindow(QWindow *window,
+ screen_context_t context,
+ screen_window_t screenWindow)
+ : QQnxWindow(window, context, screenWindow)
{
+ initWindow();
}
-QMirClientTheme::~QMirClientTheme()
+bool QQnxForeignWindow::isForeignWindow() const
{
+ return true;
}
-QVariant QMirClientTheme::themeHint(ThemeHint hint) const
+int QQnxForeignWindow::pixelFormat() const
{
- if (hint == QPlatformTheme::SystemIconThemeName) {
- QByteArray iconTheme = qgetenv("QTUBUNTU_ICON_THEME");
- if (iconTheme.isEmpty()) {
- return QVariant(QStringLiteral("ubuntu-mobile"));
- } else {
- return QVariant(QString(iconTheme));
- }
- } else {
- return QGenericUnixTheme::themeHint(hint);
- }
+ int result = SCREEN_FORMAT_RGBA8888;
+ screen_get_window_property_iv(nativeHandle(), SCREEN_PROPERTY_FORMAT, &result);
+ return result;
}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/mirclient/qmirclientdebugextension.h b/src/plugins/platforms/qnx/qqnxforeignwindow.h
index 0596561d77..22dde643e4 100644
--- a/src/plugins/platforms/mirclient/qmirclientdebugextension.h
+++ b/src/plugins/platforms/qnx/qqnxforeignwindow.h
@@ -1,6 +1,6 @@
-/****************************************************************************
+/***************************************************************************
**
-** Copyright (C) 2016 Canonical, Ltd.
+** Copyright (C) 2018 QNX Software Systems. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -37,27 +37,25 @@
**
****************************************************************************/
+#ifndef QQNXFOREIGNWINDOW_H
+#define QQNXFOREIGNWINDOW_H
-#ifndef QMIRCLIENTDEBUGEXTENSION_H
-#define QMIRCLIENTDEBUGEXTENSION_H
+#include "qqnxwindow.h"
-#include <QPoint>
-#include <QLibrary>
-struct MirSurface;
+QT_BEGIN_NAMESPACE
-typedef bool (*MapperPrototype)(MirSurface* surface, int x, int y, int* screenX, int* screenY);
-
-
-class QMirClientDebugExtension
+class QQnxForeignWindow : public QQnxWindow
{
public:
- QMirClientDebugExtension();
+ QQnxForeignWindow(QWindow *window,
+ screen_context_t context,
+ screen_window_t screenWindow);
- QPoint mapSurfacePointToScreen(MirSurface *, const QPoint &point);
-
-private:
- QLibrary m_mirclientDebug;
- MapperPrototype m_mapper;
+ bool isForeignWindow() const override;
+ int pixelFormat() const override;
+ void resetBuffers() override {}
};
-#endif // QMIRCLIENTDEBUGEXTENSION_H
+QT_END_NAMESPACE
+
+#endif // QQNXFOREIGNWINDOW_H
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index a45dcabeb7..f479e94988 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -51,6 +51,7 @@
#include "qqnxabstractvirtualkeyboard.h"
#include "qqnxservices.h"
+#include "qqnxforeignwindow.h"
#include "qqnxrasterwindow.h"
#if !defined(QT_NO_OPENGL)
#include "qqnxeglwindow.h"
@@ -147,6 +148,7 @@ static inline int getContextCapabilities(const QStringList &paramList)
QQnxIntegration::QQnxIntegration(const QStringList &paramList)
: QPlatformIntegration()
+ , m_screenContextId(256, 0)
, m_screenEventThread(0)
, m_navigatorEventHandler(new QQnxNavigatorEventHandler())
, m_virtualKeyboard(0)
@@ -178,6 +180,11 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
qFatal("%s - Screen: Failed to create screen context - Error: %s (%i)",
Q_FUNC_INFO, strerror(errno), errno);
}
+ screen_get_context_property_cv(m_screenContext,
+ SCREEN_PROPERTY_ID,
+ m_screenContextId.size(),
+ m_screenContextId.data());
+ m_screenContextId.resize(strlen(m_screenContextId.constData()));
#if QT_CONFIG(qqnx_pps)
// Create/start navigator event notifier
@@ -310,6 +317,7 @@ bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const
qIntegrationDebug();
switch (cap) {
case MultipleWindows:
+ case ForeignWindows:
case ThreadedPixmaps:
return true;
#if !defined(QT_NO_OPENGL)
@@ -323,6 +331,18 @@ bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const
}
}
+QPlatformWindow *QQnxIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
+{
+ screen_window_t screenWindow = reinterpret_cast<screen_window_t>(nativeHandle);
+ if (this->window(screenWindow)) {
+ qWarning() << "QWindow already created for foreign window"
+ << screenWindow;
+ return nullptr;
+ }
+
+ return new QQnxForeignWindow(window, m_screenContext, screenWindow);
+}
+
QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const
{
qIntegrationDebug();
@@ -478,7 +498,7 @@ QPlatformServices * QQnxIntegration::services() const
return m_services;
}
-QWindow *QQnxIntegration::window(screen_window_t qnxWindow)
+QWindow *QQnxIntegration::window(screen_window_t qnxWindow) const
{
qIntegrationDebug();
QMutexLocker locker(&m_windowMapperMutex);
@@ -587,12 +607,11 @@ QList<screen_display_t *> QQnxIntegration::sortDisplays(screen_display_t *availa
// Move all displays with matching ID from the intermediate list
// to the beginning of the ordered list
- QMutableListIterator<screen_display_t *> iter(allDisplays);
- while (iter.hasNext()) {
- screen_display_t *display = iter.next();
+ for (auto it = allDisplays.begin(), end = allDisplays.end(); it != end; ++it) {
+ screen_display_t *display = *it;
if (getIdOfDisplay(*display) == requestedValue) {
orderedDisplays.append(display);
- iter.remove();
+ allDisplays.erase(it);
break;
}
}
@@ -706,6 +725,11 @@ screen_context_t QQnxIntegration::screenContext()
return m_screenContext;
}
+QByteArray QQnxIntegration::screenContextId()
+{
+ return m_screenContextId;
+}
+
QQnxNavigatorEventHandler *QQnxIntegration::navigatorEventHandler()
{
return m_navigatorEventHandler;
diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h
index 366556dc4b..0bf37880d1 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.h
+++ b/src/plugins/platforms/qnx/qqnxintegration.h
@@ -92,6 +92,7 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const override;
+ QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override;
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
@@ -123,7 +124,7 @@ public:
QPlatformServices *services() const override;
- QWindow *window(screen_window_t qnxWindow);
+ QWindow *window(screen_window_t qnxWindow) const;
QQnxScreen *screenForNative(screen_display_t qnxScreen) const;
@@ -132,6 +133,7 @@ public:
QQnxScreen *primaryDisplay() const;
Options options() const;
screen_context_t screenContext();
+ QByteArray screenContextId();
QQnxNavigatorEventHandler *navigatorEventHandler();
@@ -145,6 +147,7 @@ private:
int displayCount);
screen_context_t m_screenContext;
+ QByteArray m_screenContextId;
QQnxScreenEventThread *m_screenEventThread;
QQnxNavigatorEventHandler *m_navigatorEventHandler;
QQnxAbstractVirtualKeyboard *m_virtualKeyboard;
@@ -168,7 +171,7 @@ private:
QSimpleDrag *m_drag;
#endif
QQnxWindowMapper m_windowMapper;
- QMutex m_windowMapperMutex;
+ mutable QMutex m_windowMapperMutex;
Options m_options;
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
index e4843cb438..56131dcc48 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
@@ -45,6 +45,7 @@
#include "qqnxkeytranslator.h"
#include "qqnxscreen.h"
#include "qqnxscreeneventfilter.h"
+#include "qqnxscreentraits.h"
#include <QDebug>
#include <QGuiApplication>
@@ -89,6 +90,51 @@ static QString capKeyString(int cap, int modifiers, int key)
return QString();
}
+template <typename T>
+static void finishCloseEvent(screen_event_t event)
+{
+ T t;
+ screen_get_event_property_pv(event,
+ screen_traits<T>::propertyName,
+ reinterpret_cast<void**>(&t));
+ screen_traits<T>::destroy(t);
+}
+
+static void finishCloseEvent(screen_event_t event)
+{
+ // Let libscreen know that we're finished with anything that may have been acquired.
+ int objectType = SCREEN_OBJECT_TYPE_CONTEXT;
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType);
+ switch (objectType) {
+ case SCREEN_OBJECT_TYPE_CONTEXT:
+ finishCloseEvent<screen_context_t>(event);
+ break;
+ case SCREEN_OBJECT_TYPE_DEVICE:
+ finishCloseEvent<screen_device_t>(event);
+ break;
+ case SCREEN_OBJECT_TYPE_DISPLAY:
+ // no screen_destroy_display
+ break;
+ case SCREEN_OBJECT_TYPE_GROUP:
+ finishCloseEvent<screen_group_t>(event);
+ break;
+ case SCREEN_OBJECT_TYPE_PIXMAP:
+ finishCloseEvent<screen_pixmap_t>(event);
+ break;
+ case SCREEN_OBJECT_TYPE_SESSION:
+ finishCloseEvent<screen_session_t>(event);
+ break;
+#if _SCREEN_VERSION >= _SCREEN_MAKE_VERSION(2, 0, 0)
+ case SCREEN_OBJECT_TYPE_STREAM:
+ finishCloseEvent<screen_stream_t>(event);
+ break;
+#endif
+ case SCREEN_OBJECT_TYPE_WINDOW:
+ finishCloseEvent<screen_window_t>(event);
+ break;
+ }
+}
+
QT_BEGIN_NAMESPACE
QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration)
@@ -242,11 +288,18 @@ void QQnxScreenEventHandler::processEvents()
break;
++count;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr result = 0;
+#else
long result = 0;
+#endif
QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral("screen_event_t"), event, &result);
if (!handled)
handleEvent(event);
+
+ if (type == SCREEN_EVENT_CLOSE)
+ finishCloseEvent(event);
}
m_eventThread->armEventsPending(count);
@@ -381,6 +434,8 @@ void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event)
if (m_lastGlobalMousePoint != globalPoint ||
m_lastLocalMousePoint != localPoint ||
m_lastButtonState != buttons) {
+ if (m_lastButtonState != 0 && buttons == 0)
+ (static_cast<QQnxWindow *>(w->handle()))->handleActivationEvent();
QWindowSystemInterface::handleMouseEvent(w, localPoint, globalPoint, buttons);
qScreenEventDebug() << "Qt mouse, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), b=" << static_cast<int>(buttons);
}
@@ -457,6 +512,9 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType)
m_lastMouseWindow = qnxWindow;
if (w) {
+ if (qnxType == SCREEN_EVENT_MTOUCH_RELEASE)
+ (static_cast<QQnxWindow *>(w->handle()))->handleActivationEvent();
+
// get size of screen which contains window
QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(w);
QSizeF screenSize = platformScreen->geometry().size();
diff --git a/src/plugins/platforms/qnx/qqnxscreentraits.h b/src/plugins/platforms/qnx/qqnxscreentraits.h
new file mode 100644
index 0000000000..ebd74141f2
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxscreentraits.h
@@ -0,0 +1,127 @@
+/***************************************************************************
+**
+** Copyright (C) 2018 QNX Software Systems. All rights reserved.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQNXSCREENTRAITS_H
+#define QQNXSCREENTRAITS_H
+
+#include <screen/screen.h>
+
+QT_BEGIN_NAMESPACE
+
+template <typename T>
+class screen_traits
+{
+};
+
+template <>
+class screen_traits<screen_context_t>
+{
+public:
+ typedef screen_context_t screen_type;
+ static const int propertyName = SCREEN_PROPERTY_CONTEXT;
+ static int destroy(screen_context_t context) { return screen_destroy_context(context); }
+};
+
+template <>
+class screen_traits<screen_device_t>
+{
+public:
+ typedef screen_device_t screen_type;
+ static const int propertyName = SCREEN_PROPERTY_DEVICE;
+ static int destroy(screen_device_t device) { return screen_destroy_device(device); }
+};
+
+template <>
+class screen_traits<screen_display_t>
+{
+public:
+ typedef screen_display_t screen_type;
+ static const int propertyName = SCREEN_PROPERTY_DISPLAY;
+};
+
+template <>
+class screen_traits<screen_group_t>
+{
+public:
+ typedef screen_group_t screen_type;
+ static const int propertyName = SCREEN_PROPERTY_GROUP;
+ static int destroy(screen_group_t group) { return screen_destroy_group(group); }
+};
+
+template <>
+class screen_traits<screen_pixmap_t>
+{
+public:
+ typedef screen_pixmap_t screen_type;
+ static const int propertyName = SCREEN_PROPERTY_PIXMAP;
+ static int destroy(screen_pixmap_t pixmap) { return screen_destroy_pixmap(pixmap); }
+};
+
+template <>
+class screen_traits<screen_session_t>
+{
+public:
+ typedef screen_session_t screen_type;
+ static const int propertyName = SCREEN_PROPERTY_SESSION;
+ static int destroy(screen_session_t session) { return screen_destroy_session(session); }
+};
+
+#if _SCREEN_VERSION >= _SCREEN_MAKE_VERSION(2, 0, 0)
+template <>
+class screen_traits<screen_stream_t>
+{
+public:
+ typedef screen_stream_t screen_type;
+ static const int propertyName = SCREEN_PROPERTY_STREAM;
+ static int destroy(screen_stream_t stream) { return screen_destroy_stream(stream); }
+};
+#endif
+
+template <>
+class screen_traits<screen_window_t>
+{
+public:
+ typedef screen_window_t screen_type;
+ static const int propertyName = SCREEN_PROPERTY_WINDOW;
+ static int destroy(screen_window_t window) { return screen_destroy_window(window); }
+};
+
+QT_END_NAMESPACE
+
+#endif // QQNXSCREENTRAITS_H
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 2096bc789e..1d3d609017 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -155,8 +155,10 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
m_parentWindow(0),
m_visible(false),
m_exposed(true),
+ m_foreign(false),
m_windowState(Qt::WindowNoState),
- m_mmRendererWindow(0)
+ m_mmRendererWindow(0),
+ m_firstActivateHandled(false)
{
qWindowDebug() << "window =" << window << ", size =" << window->size();
@@ -253,6 +255,39 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
}
}
+QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, screen_window_t screenWindow)
+ : QPlatformWindow(window)
+ , m_screenContext(context)
+ , m_window(screenWindow)
+ , m_screen(0)
+ , m_parentWindow(0)
+ , m_visible(false)
+ , m_exposed(true)
+ , m_foreign(true)
+ , m_windowState(Qt::WindowNoState)
+ , m_mmRendererWindow(0)
+ , m_parentGroupName(256, 0)
+ , m_isTopLevel(false)
+{
+ qWindowDebug() << "window =" << window << ", size =" << window->size();
+
+ collectWindowGroup();
+
+ screen_get_window_property_cv(m_window,
+ SCREEN_PROPERTY_PARENT,
+ m_parentGroupName.size(),
+ m_parentGroupName.data());
+ m_parentGroupName.resize(strlen(m_parentGroupName.constData()));
+
+ // If a window group has been provided join it now. If it's an empty string that's OK too,
+ // it'll cause us not to join a group (the app will presumably join at some future time).
+ QVariant parentGroup = window->property("qnxInitialWindowGroup");
+ if (!parentGroup.isValid())
+ parentGroup = window->property("_q_platform_qnxParentGroup");
+ if (parentGroup.isValid() && parentGroup.canConvert<QByteArray>())
+ joinWindowGroup(parentGroup.toByteArray());
+}
+
QQnxWindow::~QQnxWindow()
{
qWindowDebug() << "window =" << window();
@@ -269,7 +304,11 @@ QQnxWindow::~QQnxWindow()
m_screen->updateHierarchy();
// Cleanup QNX window and its buffers
- screen_destroy_window(m_window);
+ // Foreign windows are cleaned up externally after the CLOSE event has been handled.
+ if (m_foreign)
+ removeContextPermission();
+ else
+ screen_destroy_window(m_window);
}
void QQnxWindow::setGeometry(const QRect &rect)
@@ -341,6 +380,14 @@ void QQnxWindow::setVisible(bool visible)
if (visible) {
applyWindowState();
} else {
+ if (showWithoutActivating() && focusable() && m_firstActivateHandled) {
+ m_firstActivateHandled = false;
+ int val = SCREEN_SENSITIVITY_NO_FOCUS;
+ Q_SCREEN_CHECKERROR(
+ screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val),
+ "Failed to set window sensitivity");
+ }
+
// Flush the context, otherwise it won't disappear immediately
screen_flush_context(m_screenContext, 0);
}
@@ -618,13 +665,56 @@ void QQnxWindow::requestActivateWindow()
void QQnxWindow::setFocus(screen_window_t newFocusWindow)
{
+ screen_window_t temporaryFocusWindow = nullptr;
+
screen_group_t screenGroup = 0;
- screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_GROUP,
- reinterpret_cast<void**>(&screenGroup));
- if (screenGroup) {
- screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS,
- reinterpret_cast<void**>(&newFocusWindow));
+ Q_SCREEN_CHECKERROR(screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_GROUP,
+ reinterpret_cast<void **>(&screenGroup)),
+ "Failed to retrieve window group");
+
+ if (showWithoutActivating() && focusable() && !m_firstActivateHandled) {
+ m_firstActivateHandled = true;
+ int val = SCREEN_SENSITIVITY_TEST;
+ Q_SCREEN_CHECKERROR(
+ screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val),
+ "Failed to set window sensitivity");
+
+#if _SCREEN_VERSION < _SCREEN_MAKE_VERSION(1, 0, 0)
+ // For older versions of screen, the window may still have group
+ // focus even though it was marked NO_FOCUS when it was hidden.
+ // In that situation, focus has to be given to another window
+ // so that this window can take focus back from it.
+ screen_window_t oldFocusWindow = nullptr;
+ Q_SCREEN_CHECKERROR(
+ screen_get_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS,
+ reinterpret_cast<void **>(&oldFocusWindow)),
+ "Failed to retrieve group focus");
+ if (newFocusWindow == oldFocusWindow) {
+ char groupName[256];
+ memset(groupName, 0, sizeof(groupName));
+ Q_SCREEN_CHECKERROR(screen_get_group_property_cv(screenGroup, SCREEN_PROPERTY_NAME,
+ sizeof(groupName) - 1, groupName),
+ "Failed to retrieve group name");
+
+ Q_SCREEN_CHECKERROR(screen_create_window_type(&temporaryFocusWindow,
+ m_screenContext, SCREEN_CHILD_WINDOW),
+ "Failed to create temporary focus window");
+ Q_SCREEN_CHECKERROR(screen_join_window_group(temporaryFocusWindow, groupName),
+ "Temporary focus window failed to join window group");
+ Q_SCREEN_CHECKERROR(
+ screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS,
+ reinterpret_cast<void **>(&temporaryFocusWindow)),
+ "Temporary focus window failed to take focus");
+ screen_flush_context(m_screenContext, 0);
+ }
+#endif
}
+
+ Q_SCREEN_CHECKERROR(screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS,
+ reinterpret_cast<void **>(&newFocusWindow)),
+ "Failed to set group focus");
+
+ screen_destroy_window(temporaryFocusWindow);
}
void QQnxWindow::setWindowState(Qt::WindowStates state)
@@ -711,7 +801,11 @@ void QQnxWindow::initWindow()
screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, &val),
"Failed to set swap interval");
- if (window()->flags() & Qt::WindowDoesNotAcceptFocus) {
+ if (showWithoutActivating() || !focusable()) {
+ // NO_FOCUS is temporary for showWithoutActivating (and pop-up) windows.
+ // Using NO_FOCUS ensures that screen doesn't activate the window because
+ // it was just created. Sensitivity will be changed to TEST when the
+ // window is clicked or touched.
val = SCREEN_SENSITIVITY_NO_FOCUS;
Q_SCREEN_CHECKERROR(
screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val),
@@ -737,14 +831,24 @@ void QQnxWindow::initWindow()
setGeometryHelper(shouldMakeFullScreen() ? screen()->geometry() : window()->geometry());
}
-void QQnxWindow::createWindowGroup()
+void QQnxWindow::collectWindowGroup()
{
- // Generate a random window group name
- m_windowGroupName = QUuid::createUuid().toByteArray();
+ QByteArray groupName(256, 0);
+ Q_SCREEN_CHECKERROR(screen_get_window_property_cv(m_window,
+ SCREEN_PROPERTY_GROUP,
+ groupName.size(),
+ groupName.data()),
+ "Failed to retrieve window group");
+ groupName.resize(strlen(groupName.constData()));
+ m_windowGroupName = groupName;
+}
- // Create window group so child windows can be parented by container window
- Q_SCREEN_CHECKERROR(screen_create_window_group(m_window, m_windowGroupName.constData()),
+void QQnxWindow::createWindowGroup()
+{
+ Q_SCREEN_CHECKERROR(screen_create_window_group(m_window, nullptr),
"Failed to create window group");
+
+ collectWindowGroup();
}
void QQnxWindow::joinWindowGroup(const QByteArray &groupName)
@@ -753,6 +857,17 @@ void QQnxWindow::joinWindowGroup(const QByteArray &groupName)
qWindowDebug() << "group:" << groupName;
+ // screen has this annoying habit of generating a CLOSE/CREATE when the owner context of
+ // the parent group moves a foreign window to another group that it also owns. The
+ // CLOSE/CREATE changes the identity of the foreign window. Usually, this is undesirable.
+ // To prevent this CLOSE/CREATE when changing the parent group, we temporarily add a
+ // context permission for the Qt context. screen won't send a CLOSE/CREATE when the
+ // context has some permission other than the PARENT permission. If there isn't a new
+ // group (the window has no parent), this context permission is left in place.
+
+ if (m_foreign && !m_parentGroupName.isEmpty())\
+ addContextPermission();
+
if (!groupName.isEmpty()) {
if (groupName != m_parentGroupName) {
screen_join_window_group(m_window, groupName);
@@ -771,6 +886,9 @@ void QQnxWindow::joinWindowGroup(const QByteArray &groupName)
m_parentGroupName = "";
}
+ if (m_foreign && !groupName.isEmpty())
+ removeContextPermission();
+
if (changed)
screen_flush_context(m_screenContext, 0);
}
@@ -825,4 +943,44 @@ bool QQnxWindow::shouldMakeFullScreen() const
&& (QQnxIntegration::instance()->options() & QQnxIntegration::FullScreenApplication));
}
+
+void QQnxWindow::handleActivationEvent()
+{
+ if (showWithoutActivating() && focusable() && !m_firstActivateHandled)
+ requestActivateWindow();
+}
+
+bool QQnxWindow::showWithoutActivating() const
+{
+ return (window()->flags() & Qt::Popup) == Qt::Popup
+ || window()->property("_q_showWithoutActivating").toBool();
+}
+
+bool QQnxWindow::focusable() const
+{
+ return (window()->flags() & Qt::WindowDoesNotAcceptFocus) != Qt::WindowDoesNotAcceptFocus;
+}
+
+void QQnxWindow::addContextPermission()
+{
+ QByteArray grantString("context:");
+ grantString.append(QQnxIntegration::instance()->screenContextId());
+ grantString.append(":rw-");
+ screen_set_window_property_cv(m_window,
+ SCREEN_PROPERTY_PERMISSIONS,
+ grantString.length(),
+ grantString.data());
+}
+
+void QQnxWindow::removeContextPermission()
+{
+ QByteArray revokeString("context:");
+ revokeString.append(QQnxIntegration::instance()->screenContextId());
+ revokeString.append(":---");
+ screen_set_window_property_cv(m_window,
+ SCREEN_PROPERTY_PERMISSIONS,
+ revokeString.length(),
+ revokeString.data());
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h
index 2895a547b1..9040619c41 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.h
+++ b/src/plugins/platforms/qnx/qqnxwindow.h
@@ -64,7 +64,8 @@ class QQnxWindow : public QPlatformWindow
{
friend class QQnxScreen;
public:
- QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow);
+ explicit QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow);
+ explicit QQnxWindow(QWindow *window, screen_context_t context, screen_window_t screenWindow);
virtual ~QQnxWindow();
void setGeometry(const QRect &rect) override;
@@ -113,6 +114,7 @@ public:
bool shouldMakeFullScreen() const;
void windowPosted();
+ void handleActivationEvent();
protected:
virtual int pixelFormat() const = 0;
@@ -123,6 +125,7 @@ protected:
screen_context_t m_screenContext;
private:
+ void collectWindowGroup();
void createWindowGroup();
void setGeometryHelper(const QRect &rect);
void removeFromParent();
@@ -131,6 +134,11 @@ private:
void updateZorder(screen_window_t window, int &zOrder);
void applyWindowState();
void setFocus(screen_window_t newFocusWindow);
+ bool showWithoutActivating() const;
+ bool focusable() const;
+
+ void addContextPermission();
+ void removeContextPermission();
screen_window_t m_window;
QSize m_bufferSize;
@@ -141,6 +149,7 @@ private:
QScopedPointer<QQnxAbstractCover> m_cover;
bool m_visible;
bool m_exposed;
+ bool m_foreign;
QRect m_unmaximizedGeometry;
Qt::WindowStates m_windowState;
QString m_mmRendererWindowName;
@@ -152,6 +161,7 @@ private:
QByteArray m_parentGroupName;
bool m_isTopLevel;
+ bool m_firstActivateHandled;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/vnc/qvnc.cpp b/src/plugins/platforms/vnc/qvnc.cpp
index ffe00de2b1..32114c6443 100644
--- a/src/plugins/platforms/vnc/qvnc.cpp
+++ b/src/plugins/platforms/vnc/qvnc.cpp
@@ -600,7 +600,7 @@ void QVncClientCursor::changeCursor(QCursor *widgetCursor, QWindow *window)
cursor = *platformImage.image();
hotspot = platformImage.hotspot();
}
- for (auto client : clients)
+ for (auto client : qAsConst(clients))
client->setDirtyCursor();
}
@@ -638,16 +638,14 @@ void QVncServer::init()
QVncServer::~QVncServer()
{
- for (auto client : clients) {
- delete client;
- }
+ qDeleteAll(clients);
}
void QVncServer::setDirty()
{
- for (auto client : clients) {
+ for (auto client : qAsConst(clients))
client->setDirty(qvnc_screen->dirtyRegion);
- }
+
qvnc_screen->clearDirty();
}
diff --git a/src/plugins/platforms/vnc/qvnc_p.h b/src/plugins/platforms/vnc/qvnc_p.h
index 338fae9f87..f7f2f74ddb 100644
--- a/src/plugins/platforms/vnc/qvnc_p.h
+++ b/src/plugins/platforms/vnc/qvnc_p.h
@@ -139,7 +139,7 @@ public:
class QRfbServerInit
{
public:
- QRfbServerInit() { name = 0; }
+ QRfbServerInit() { name = nullptr; }
~QRfbServerInit() { delete[] name; }
int size() const { return QRfbPixelFormat::size() + 8 + strlen(name); }
diff --git a/src/plugins/platforms/vnc/qvncscreen.cpp b/src/plugins/platforms/vnc/qvncscreen.cpp
index 67d33de2f0..2eca18fb4d 100644
--- a/src/plugins/platforms/vnc/qvncscreen.cpp
+++ b/src/plugins/platforms/vnc/qvncscreen.cpp
@@ -75,7 +75,7 @@ bool QVncScreen::initialize()
mDepth = 32;
mPhysicalSize = QSizeF(mGeometry.width()/96.*25.4, mGeometry.height()/96.*25.4);
- for (const QString &arg : mArgs) {
+ for (const QString &arg : qAsConst(mArgs)) {
QRegularExpressionMatch match;
if (arg.contains(mmSizeRx, &match)) {
mPhysicalSize = QSizeF(match.captured("width").toDouble(), match.captured("height").toDouble());
diff --git a/src/plugins/platforms/vnc/qvncscreen.h b/src/plugins/platforms/vnc/qvncscreen.h
index e69aa90d41..db658d4ecc 100644
--- a/src/plugins/platforms/vnc/qvncscreen.h
+++ b/src/plugins/platforms/vnc/qvncscreen.h
@@ -82,12 +82,12 @@ public:
qreal dpiX = 96;
qreal dpiY = 96;
- QVncDirtyMap *dirty = 0;
+ QVncDirtyMap *dirty = nullptr;
QRegion dirtyRegion;
int refreshRate = 30;
- QVncServer *vncServer = 0;
+ QVncServer *vncServer = nullptr;
#if QT_CONFIG(cursor)
- QVncClientCursor *clientCursor = 0;
+ QVncClientCursor *clientCursor = nullptr;
#endif
};
diff --git a/src/plugins/platforms/wasm/qtloader.js b/src/plugins/platforms/wasm/qtloader.js
index 37a5308034..ef4a6ec2b9 100644
--- a/src/plugins/platforms/wasm/qtloader.js
+++ b/src/plugins/platforms/wasm/qtloader.js
@@ -50,6 +50,7 @@
// External mode.usage:
//
// var config = {
+// canvasElements : [$("canvas-id")],
// showLoader: function() {
// loader.style.display = 'block'
// canvas.style.display = 'hidden'
@@ -69,6 +70,8 @@
// One or more HTML elements. QtLoader will display loader elements
// on these while loading the applicaton, and replace the loader with a
// canvas on load complete.
+// canvasElements : [canvas-element, ...]
+// One or more canvas elements.
// showLoader : function(status, containerElement)
// Optional loading element constructor function. Implement to create
// a custom loading screen. This function may be called multiple times,
@@ -115,6 +118,14 @@
// "Exited", iff crashed is false.
// exitText
// Abort/exit message.
+// addCanvasElement
+// Add canvas at run-time. Adds a corresponding QScreen,
+// removeCanvasElement
+// Remove canvas at run-time. Removes the corresponding QScreen.
+// resizeCanvasElement
+// Signals to the application that a canvas has been resized.
+// setFontDpi
+// Sets the logical font dpi for the application.
var Module = {}
@@ -146,8 +157,26 @@ function QtLoader(config)
while (element.firstChild) element.removeChild(element.firstChild);
}
- // Set default state handler functions if needed
+ function createCanvas() {
+ var canvas = document.createElement("canvas");
+ canvas.className = "QtCanvas";
+ canvas.style.height = "100%";
+ canvas.style.width = "100%";
+
+ // Set contentEditable in order to enable clipboard events; hide the resulting focus frame.
+ canvas.contentEditable = true;
+ canvas.style.outline = "0px solid transparent";
+ canvas.style.caretColor = "transparent";
+ canvas.style.cursor = "default";
+
+ return canvas;
+ }
+
+ // Set default state handler functions and create canvases if needed
if (config.containerElements !== undefined) {
+
+ config.canvasElements = config.containerElements.map(createCanvas);
+
config.showError = config.showError || function(errorText, container) {
removeChildren(container);
var errorTextElement = document.createElement("text");
@@ -164,12 +193,8 @@ function QtLoader(config)
return loadingText;
};
- config.showCanvas = config.showCanvas || function(container) {
+ config.showCanvas = config.showCanvas || function(canvas, container) {
removeChildren(container);
- var canvas = document.createElement("canvas");
- canvas.className = "QtCanvas"
- canvas.style = "height: 100%; width: 100%;"
- return canvas;
}
config.showExit = config.showExit || function(crashed, exitCode, container) {
@@ -211,6 +236,11 @@ function QtLoader(config)
publicAPI.canLoadApplication = canLoadQt();
publicAPI.status = undefined;
publicAPI.loadEmscriptenModule = loadEmscriptenModule;
+ publicAPI.addCanvasElement = addCanvasElement;
+ publicAPI.removeCanvasElement = removeCanvasElement;
+ publicAPI.resizeCanvasElement = resizeCanvasElement;
+ publicAPI.setFontDpi = setFontDpi;
+ publicAPI.fontDpi = fontDpi;
restartCount = 0;
@@ -312,13 +342,13 @@ function QtLoader(config)
// and is ready to be instantiated. Define the instantiateWasm callback which
// emscripten will call to create the instance.
Module.instantiateWasm = function(imports, successCallback) {
- return WebAssembly.instantiate(wasmModule, imports).then(function(instance) {
- successCallback(instance);
- return instance;
+ WebAssembly.instantiate(wasmModule, imports).then(function(instance) {
+ successCallback(instance, wasmModule);
}, function(error) {
self.error = error;
setStatus("Error");
});
+ return {};
};
Module.locateFile = Module.locateFile || function(filename) {
@@ -378,10 +408,14 @@ function QtLoader(config)
Module.preRun = Module.preRun || []
Module.preRun.push(function() {
for (var [key, value] of Object.entries(config.environment)) {
- Module.ENV[key.toUpperCase()] = value;
+ ENV[key.toUpperCase()] = value;
}
});
+ Module.mainScriptUrlOrBlob = new Blob([emscriptenModuleSource], {type: 'text/javascript'});
+
+ Module.qtCanvasElements = config.canvasElements;
+
config.restart = function() {
// Restart by reloading the page. This will wipe all state which means
@@ -436,19 +470,17 @@ function QtLoader(config)
}
function setCanvasContent() {
- var firstCanvas;
if (config.containerElements === undefined) {
- firstCanvas = config.showCanvas();
- } else {
- for (container of config.containerElements) {
- var canvasElement = config.showCanvas(container);
- container.appendChild(canvasElement);
- }
- firstCanvas = config.containerElements[0].firstChild;
+ if (config.showCanvas !== undefined)
+ config.showCanvas();
+ return;
}
- if (Module.canvas === undefined) {
- Module.canvas = firstCanvas;
+ for (var i = 0; i < config.containerElements.length; ++i) {
+ var container = config.containerElements[i];
+ var canvas = config.canvasElements[i];
+ config.showCanvas(canvas, container);
+ container.appendChild(canvas);
}
}
@@ -510,6 +542,35 @@ function QtLoader(config)
window.setTimeout(function() { handleStatusChange(); }, 0);
}
+ function addCanvasElement(element) {
+ if (publicAPI.status == "Running")
+ Module.qtAddCanvasElement(element);
+ else
+ console.log("Error: addCanvasElement can only be called in the Running state");
+ }
+
+ function removeCanvasElement(element) {
+ if (publicAPI.status == "Running")
+ Module.qtRemoveCanvasElement(element);
+ else
+ console.log("Error: removeCanvasElement can only be called in the Running state");
+ }
+
+ function resizeCanvasElement(element) {
+ if (publicAPI.status == "Running")
+ Module.qtResizeCanvasElement(element);
+ }
+
+ function setFontDpi(dpi) {
+ Module.qtFontDpi = dpi;
+ if (publicAPI.status == "Running")
+ Module.qtSetFontDpi(dpi);
+ }
+
+ function fontDpi() {
+ return Module.qtFontDpi;
+ }
+
setStatus("Created");
return publicAPI;
diff --git a/src/plugins/platforms/wasm/qtlogo.svg b/src/plugins/platforms/wasm/qtlogo.svg
index cb8989bb79..ad7c7776bf 100644
--- a/src/plugins/platforms/wasm/qtlogo.svg
+++ b/src/plugins/platforms/wasm/qtlogo.svg
@@ -5,15 +5,10 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="462pt"
height="339pt"
viewBox="0 0 462 339"
- version="1.1"
- id="svg2"
- inkscape:version="0.91 r13725"
- sodipodi:docname="TheQtCompany_logo_2.svg">
+ version="1.1">
<metadata
id="metadata20">
<rdf:RDF>
@@ -26,28 +21,6 @@
</cc:Work>
</rdf:RDF>
</metadata>
- <defs
- id="defs18" />
- <sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="1536"
- inkscape:window-height="801"
- id="namedview16"
- showgrid="false"
- inkscape:zoom="1.1138643"
- inkscape:cx="270.58047"
- inkscape:cy="174.65092"
- inkscape:window-x="-8"
- inkscape:window-y="-8"
- inkscape:window-maximized="1"
- inkscape:current-layer="svg2" />
<path
fill="#41cd52"
d=" M 63.50 0.00 L 462.00 0.00 L 462.00 274.79 C 440.60 296.26 419.13 317.66 397.61 339.00 L 0.00 339.00 L 0.00 63.39 C 21.08 42.18 42.34 21.13 63.50 0.00 Z"
diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.cpp b/src/plugins/platforms/wasm/qwasmbackingstore.cpp
index 5b40c44807..e8eda2605f 100644
--- a/src/plugins/platforms/wasm/qwasmbackingstore.cpp
+++ b/src/plugins/platforms/wasm/qwasmbackingstore.cpp
@@ -55,6 +55,12 @@ QWasmBackingStore::~QWasmBackingStore()
{
}
+void QWasmBackingStore::destroy()
+{
+ if (m_texture->isCreated())
+ m_texture->destroy();
+}
+
QPaintDevice *QWasmBackingStore::paintDevice()
{
return &m_image;
diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.h b/src/plugins/platforms/wasm/qwasmbackingstore.h
index 6ffa262e3d..4bca83c457 100644
--- a/src/plugins/platforms/wasm/qwasmbackingstore.h
+++ b/src/plugins/platforms/wasm/qwasmbackingstore.h
@@ -44,6 +44,7 @@ class QWasmBackingStore : public QPlatformBackingStore
public:
QWasmBackingStore(QWasmCompositor *compositor, QWindow *window);
~QWasmBackingStore();
+ void destroy();
QPaintDevice *paintDevice() override;
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp
new file mode 100644
index 0000000000..d4a1e4dd50
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmclipboard.h"
+#include "qwasmwindow.h"
+
+#include <emscripten.h>
+#include <emscripten/html5.h>
+#include <emscripten/bind.h>
+
+#include <QCoreApplication>
+#include <qpa/qwindowsysteminterface.h>
+
+using namespace emscripten;
+
+// there has got to be a better way...
+static QByteArray g_clipboardArray;
+static QByteArray g_clipboardFormat;
+
+static val getClipboardData()
+{
+ return val(g_clipboardArray.constData());
+}
+
+static val getClipboardFormat()
+{
+ return val(g_clipboardFormat.constData());
+}
+
+static void pasteClipboardData(emscripten::val format, emscripten::val dataPtr)
+{
+ QString formatString = QString::fromStdString(format.as<std::string>());
+ QByteArray dataArray = QByteArray::fromStdString(dataPtr.as<std::string>());
+ QMimeData *mMimeData = new QMimeData;
+ mMimeData->setData(formatString, dataArray);
+ QWasmClipboard::qWasmClipboardPaste(mMimeData);
+}
+
+static void qClipboardPromiseResolve(emscripten::val something)
+{
+ pasteClipboardData(emscripten::val("text/plain"), something);
+}
+
+static void qClipboardCutTo(val event)
+{
+ if (!QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi) {
+ // Send synthetic Ctrl+X to make the app cut data to Qt's clipboard
+ QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(
+ 0, QEvent::KeyPress, Qt::Key_X, Qt::ControlModifier, "X");
+ }
+
+ val module = val::global("Module");
+ val clipdata = module.call<val>("qtGetClipboardData");
+ val clipFormat = module.call<val>("qtGetClipboardFormat");
+ event["clipboardData"].call<void>("setData", clipFormat, clipdata);
+ event.call<void>("preventDefault");
+}
+
+static void qClipboardCopyTo(val event)
+{
+ if (!QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi) {
+ // Send synthetic Ctrl+C to make the app copy data to Qt's clipboard
+ QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(
+ 0, QEvent::KeyPress, Qt::Key_C, Qt::ControlModifier, "C");
+ }
+
+ val module = val::global("Module");
+ val clipdata = module.call<val>("qtGetClipboardData");
+ val clipFormat = module.call<val>("qtGetClipboardFormat");
+ event["clipboardData"].call<void>("setData", clipFormat, clipdata);
+ event.call<void>("preventDefault");
+}
+
+static void qClipboardPasteTo(val event)
+{
+ bool hasClipboardApi = QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi;
+ val clipdata = hasClipboardApi ?
+ val::global("Module").call<val>("qtGetClipboardData") :
+ event["clipboardData"].call<val>("getData", std::string("text"));
+
+ const std::string data = clipdata.as<std::string>();
+ if (data.length() > 0) {
+ QString qstr = QString::fromStdString(data);
+ QMimeData *mMimeData = new QMimeData;
+ mMimeData->setText(qstr);
+ QWasmClipboard::qWasmClipboardPaste(mMimeData);
+ }
+}
+
+EMSCRIPTEN_BINDINGS(qtClipboardModule) {
+ function("qtGetClipboardData", &getClipboardData);
+ function("qtGetClipboardFormat", &getClipboardFormat);
+ function("qtPasteClipboardData", &pasteClipboardData);
+ function("qtClipboardPromiseResolve", &qClipboardPromiseResolve);
+ function("qtClipboardCutTo", &qClipboardCutTo);
+ function("qtClipboardCopyTo", &qClipboardCopyTo);
+ function("qtClipboardPasteTo", &qClipboardPasteTo);
+}
+
+QWasmClipboard::QWasmClipboard()
+{
+ val clipboard = val::global("navigator")["clipboard"];
+ hasClipboardApi = (!clipboard.isUndefined() && !clipboard["readText"].isUndefined());
+
+ initClipboardEvents();
+}
+
+QWasmClipboard::~QWasmClipboard()
+{
+ g_clipboardArray.clear();
+ g_clipboardFormat.clear();
+}
+
+QMimeData* QWasmClipboard::mimeData(QClipboard::Mode mode)
+{
+ if (mode != QClipboard::Clipboard)
+ return nullptr;
+
+ return QPlatformClipboard::mimeData(mode);
+}
+
+void QWasmClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode)
+{
+ if (mimeData->hasText()) {
+ g_clipboardFormat = mimeData->formats().at(0).toUtf8();
+ g_clipboardArray = mimeData->text().toUtf8();
+ } else if (mimeData->hasHtml()) {
+ g_clipboardFormat =mimeData->formats().at(0).toUtf8();
+ g_clipboardArray = mimeData->html().toUtf8();
+ }
+
+ QPlatformClipboard::setMimeData(mimeData, mode);
+}
+
+bool QWasmClipboard::supportsMode(QClipboard::Mode mode) const
+{
+ return mode == QClipboard::Clipboard;
+}
+
+bool QWasmClipboard::ownsMode(QClipboard::Mode mode) const
+{
+ Q_UNUSED(mode);
+ return false;
+}
+
+void QWasmClipboard::qWasmClipboardPaste(QMimeData *mData)
+{
+ QWasmIntegration::get()->clipboard()->setMimeData(mData, QClipboard::Clipboard);
+
+ QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(
+ 0, QEvent::KeyPress, Qt::Key_V, Qt::ControlModifier, "V");
+}
+
+void QWasmClipboard::initClipboardEvents()
+{
+ if (!hasClipboardApi)
+ return;
+
+ val permissions = val::global("navigator")["permissions"];
+ val readPermissionsMap = val::object();
+ readPermissionsMap.set("name", val("clipboard-read"));
+ permissions.call<val>("query", readPermissionsMap);
+
+ val writePermissionsMap = val::object();
+ writePermissionsMap.set("name", val("clipboard-write"));
+ permissions.call<val>("query", writePermissionsMap);
+}
+
+void QWasmClipboard::installEventHandlers(const QString &canvasId)
+{
+ if (hasClipboardApi)
+ return;
+
+ // Fallback path for browsers which do not support direct clipboard access
+ val canvas = val::global(canvasId.toUtf8().constData());
+ canvas.call<void>("addEventListener", std::string("cut"),
+ val::module_property("qtClipboardCutTo"));
+ canvas.call<void>("addEventListener", std::string("copy"),
+ val::module_property("qtClipboardCopyTo"));
+ canvas.call<void>("addEventListener", std::string("paste"),
+ val::module_property("qtClipboardPasteTo"));
+}
+
+void QWasmClipboard::readTextFromClipboard()
+{
+ if (QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi) {
+ val navigator = val::global("navigator");
+ val textPromise = navigator["clipboard"].call<val>("readText");
+ val readTextResolve = val::global("Module")["qtClipboardPromiseResolve"];
+ textPromise.call<val>("then", readTextResolve);
+ }
+}
+
+void QWasmClipboard::writeTextToClipboard()
+{
+ if (QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi) {
+ val module = val::global("Module");
+ val txt = module.call<val>("qtGetClipboardData");
+ val format = module.call<val>("qtGetClipboardFormat");
+ val navigator = val::global("navigator");
+ navigator["clipboard"].call<void>("writeText", txt.as<std::string>());
+ }
+}
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.h b/src/plugins/platforms/wasm/qwasmclipboard.h
new file mode 100644
index 0000000000..00aae8fead
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmclipboard.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWasmClipboard_H
+#define QWasmClipboard_H
+
+#include <QObject>
+
+#include <qpa/qplatformclipboard.h>
+#include <QMimeData>
+
+#include <emscripten/bind.h>
+
+class QWasmClipboard : public QObject, public QPlatformClipboard
+{
+public:
+ QWasmClipboard();
+ virtual ~QWasmClipboard();
+
+ // QPlatformClipboard methods.
+ QMimeData* mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
+ void setMimeData(QMimeData* data, QClipboard::Mode mode = QClipboard::Clipboard) override;
+ bool supportsMode(QClipboard::Mode mode) const override;
+ bool ownsMode(QClipboard::Mode mode) const override;
+
+ static void qWasmClipboardPaste(QMimeData *mData);
+ void initClipboardEvents();
+ void installEventHandlers(const QString &canvasId);
+ bool hasClipboardApi;
+ void readTextFromClipboard();
+ void writeTextToClipboard();
+};
+
+#endif // QWASMCLIPBOARD_H
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index 3dc6b7d2f3..6d211667be 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -37,6 +37,7 @@
#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglfunctions.h>
#include <QtGui/qopengltextureblitter.h>
+#include <QtGui/qoffscreensurface.h>
#include <QtGui/qpainter.h>
#include <private/qpixmapcache_p.h>
@@ -56,8 +57,9 @@ QWasmCompositedWindow::QWasmCompositedWindow()
{
}
-QWasmCompositor::QWasmCompositor()
- : m_frameBuffer(nullptr)
+QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
+ :QObject(screen)
+ , m_frameBuffer(nullptr)
, m_blitter(new QOpenGLTextureBlitter)
, m_needComposit(false)
, m_inFlush(false)
@@ -70,6 +72,28 @@ QWasmCompositor::QWasmCompositor()
QWasmCompositor::~QWasmCompositor()
{
delete m_frameBuffer;
+ destroy();
+}
+
+void QWasmCompositor::destroy()
+{
+ // Destroy OpenGL resources. This is done here in a separate function
+ // which can be called while screen() still returns a valid screen
+ // (which it might not, during destruction). A valid QScreen is
+ // a requirement for QOffscreenSurface on Wasm since the native
+ // context is tied to a single canvas.
+ if (m_context) {
+ QOffscreenSurface offScreenSurface(screen()->screen());
+ offScreenSurface.setFormat(m_context->format());
+ offScreenSurface.create();
+ m_context->makeCurrent(&offScreenSurface);
+ for (QWasmWindow *window : m_windowStack)
+ window->destroy();
+ m_blitter.reset(nullptr);
+ m_context.reset(nullptr);
+ }
+
+ m_isEnabled = false; // prevent frame() from creating a new m_context
}
void QWasmCompositor::setEnabled(bool enabled)
@@ -107,11 +131,6 @@ void QWasmCompositor::removeWindow(QWasmWindow *window)
notifyTopWindowChanged(window);
}
-void QWasmCompositor::setScreen(QWasmScreen *screen)
-{
- m_screen = screen;
-}
-
void QWasmCompositor::setVisible(QWasmWindow *window, bool visible)
{
QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
@@ -197,7 +216,7 @@ void QWasmCompositor::requestRedraw()
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
-QWindow *QWasmCompositor::windowAt(QPoint p, int padding) const
+QWindow *QWasmCompositor::windowAt(QPoint globalPoint, int padding) const
{
int index = m_windowStack.count() - 1;
// qDebug() << "window at" << "point" << p << "window count" << index;
@@ -209,7 +228,7 @@ QWindow *QWasmCompositor::windowAt(QPoint p, int padding) const
QRect geometry = compositedWindow.window->windowFrameGeometry()
.adjusted(-padding, -padding, padding, padding);
- if (compositedWindow.visible && geometry.contains(p))
+ if (compositedWindow.visible && geometry.contains(globalPoint))
return m_windowStack.at(index)->window();
--index;
}
@@ -255,10 +274,13 @@ void QWasmCompositor::blit(QOpenGLTextureBlitter *blitter, QWasmScreen *screen,
void QWasmCompositor::drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window)
{
QWasmBackingStore *backingStore = window->backingStore();
+ if (!backingStore)
+ return;
QOpenGLTexture const *texture = backingStore->getUpdatedTexture();
-
- blit(blitter, screen, texture, window->geometry());
+ QPoint windowCanvasPosition = window->geometry().topLeft() - screen->geometry().topLeft();
+ QRect windowCanvasGeometry = QRect(windowCanvasPosition, window->geometry().size());
+ blit(blitter, screen, texture, windowCanvasGeometry);
}
QPalette QWasmCompositor::makeWindowPalette()
@@ -654,7 +676,7 @@ void QWasmCompositor::frame()
m_needComposit = false;
- if (m_windowStack.empty() || !m_screen)
+ if (!m_isEnabled || m_windowStack.empty() || !screen())
return;
QWasmWindow *someWindow = nullptr;
@@ -673,17 +695,19 @@ void QWasmCompositor::frame()
if (m_context.isNull()) {
m_context.reset(new QOpenGLContext());
//mContext->setFormat(mScreen->format());
- m_context->setScreen(m_screen->screen());
+ m_context->setScreen(screen()->screen());
m_context->create();
}
- m_context->makeCurrent(someWindow->window());
+ bool ok = m_context->makeCurrent(someWindow->window());
+ if (!ok)
+ return;
if (!m_blitter->isCreated())
m_blitter->create();
- qreal dpr = m_screen->devicePixelRatio();
- glViewport(0, 0, m_screen->geometry().width() * dpr, m_screen->geometry().height() * dpr);
+ qreal dpr = screen()->devicePixelRatio();
+ glViewport(0, 0, screen()->geometry().width() * dpr, screen()->geometry().height() * dpr);
m_context->functions()->glClearColor(0.2, 0.2, 0.2, 1.0);
m_context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -697,7 +721,7 @@ void QWasmCompositor::frame()
if (!compositedWindow.visible)
continue;
- drawWindow(m_blitter.data(), m_screen, window);
+ drawWindow(m_blitter.data(), screen(), window);
}
m_blitter->release();
@@ -719,3 +743,8 @@ void QWasmCompositor::notifyTopWindowChanged(QWasmWindow *window)
requestRedraw();
QWindowSystemInterface::handleWindowActivated(window->window());
}
+
+QWasmScreen *QWasmCompositor::screen()
+{
+ return static_cast<QWasmScreen *>(parent());
+}
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h
index 4e5ed46cec..98f4a79b27 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.h
+++ b/src/plugins/platforms/wasm/qwasmcompositor.h
@@ -62,8 +62,9 @@ class QWasmCompositor : public QObject
{
Q_OBJECT
public:
- QWasmCompositor();
+ QWasmCompositor(QWasmScreen *screen);
~QWasmCompositor();
+ void destroy();
enum QWasmSubControl {
SC_None = 0x00000000,
@@ -103,7 +104,6 @@ public:
void addWindow(QWasmWindow *window, QWasmWindow *parentWindow = nullptr);
void removeWindow(QWasmWindow *window);
- void setScreen(QWasmScreen *screen);
void setVisible(QWasmWindow *window, bool visible);
void raise(QWasmWindow *window);
@@ -117,7 +117,7 @@ public:
void redrawWindowContent();
void requestRedraw();
- QWindow *windowAt(QPoint p, int padding = 0) const;
+ QWindow *windowAt(QPoint globalPoint, int padding = 0) const;
QWindow *keyWindow() const;
bool event(QEvent *event);
@@ -129,8 +129,7 @@ private slots:
void frame();
private:
- void createFrameBuffer();
- void flushCompletedCallback(int32_t);
+ QWasmScreen *screen();
void notifyTopWindowChanged(QWasmWindow *window);
void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
@@ -142,7 +141,6 @@ private:
QImage *m_frameBuffer;
QScopedPointer<QOpenGLContext> m_context;
QScopedPointer<QOpenGLTextureBlitter> m_blitter;
- QWasmScreen *m_screen;
QHash<QWasmWindow *, QWasmCompositedWindow> m_compositedWindows;
QList<QWasmWindow *> m_windowStack;
diff --git a/src/plugins/platforms/wasm/qwasmcursor.cpp b/src/plugins/platforms/wasm/qwasmcursor.cpp
index 54804a55b3..2b3f37300d 100644
--- a/src/plugins/platforms/wasm/qwasmcursor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcursor.cpp
@@ -28,19 +28,21 @@
****************************************************************************/
#include "qwasmcursor.h"
+#include "qwasmscreen.h"
#include <QtCore/qdebug.h>
+#include <QtGui/qwindow.h>
#include <emscripten/emscripten.h>
+#include <emscripten/bind.h>
void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
{
- if (windowCursor == nullptr)
+ if (!windowCursor || !window)
+ return;
+ QScreen *screen = window->screen();
+ if (!screen)
return;
-
- // FIXME: The HTML5 plugin sets the cursor on the native canvas; when using multiple windows
- // multiple cursors need to be managed taking mouse postion and stacking into account.
- Q_UNUSED(window);
// Bitmap and custom cursors are not implemented (will fall back to "auto")
if (windowCursor->shape() == Qt::BitmapCursor || windowCursor->shape() >= Qt::CustomCursor)
@@ -51,12 +53,10 @@ void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
if (htmlCursorName.isEmpty())
htmlCursorName = "auto";
- // Set cursor on the main canvas
- EM_ASM_ARGS({
- if (Module['canvas']) {
- Module['canvas'].style['cursor'] = Pointer_stringify($0);
- }
- }, htmlCursorName.constData());
+ // Set cursor on the canvas
+ QString canvasId = QWasmScreen::get(screen)->canvasId();
+ emscripten::val canvasStyle = emscripten::val::global(canvasId.toUtf8().constData())["style"];
+ canvasStyle.set("cursor", emscripten::val(htmlCursorName.constData()));
}
QByteArray QWasmCursor::cursorShapeToHtml(Qt::CursorShape shape)
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
index 8ab109f03c..3895646b89 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -31,6 +31,7 @@
#include "qwasmeventdispatcher.h"
#include "qwasmcompositor.h"
#include "qwasmintegration.h"
+#include "qwasmclipboard.h"
#include <QtGui/qevent.h>
#include <qpa/qwindowsysteminterface.h>
@@ -39,6 +40,9 @@
#include <QtCore/qobject.h>
#include <QtCore/qdeadlinetimer.h>
+#include <private/qmakearray_p.h>
+#include <QtCore/qnamespace.h>
+
#include <emscripten/bind.h>
#include <iostream>
@@ -46,71 +50,331 @@
QT_BEGIN_NAMESPACE
using namespace emscripten;
+typedef struct emkb2qt {
+ const char *em;
+ unsigned int qt;
+
+ constexpr bool operator <=(const emkb2qt &that) const noexcept
+ {
+ return !(strcmp(that) > 0);
+ }
+
+ bool operator <(const emkb2qt &that) const noexcept
+ {
+ return ::strcmp(em, that.em) < 0;
+ }
+ constexpr int strcmp(const emkb2qt &that, const int i = 0) const
+ {
+ return em[i] == 0 && that.em[i] == 0 ? 0
+ : em[i] == 0 ? -1
+ : that.em[i] == 0 ? 1
+ : em[i] < that.em[i] ? -1
+ : em[i] > that.em[i] ? 1
+ : strcmp(that, i + 1);
+ }
+} emkb2qt_t;
+
+template<unsigned int Qt, char ... EmChar>
+struct Emkb2Qt
+{
+ static constexpr const char storage[sizeof ... (EmChar) + 1] = {EmChar..., '\0'};
+ using Type = emkb2qt_t;
+ static constexpr Type data() noexcept { return Type{storage, Qt}; }
+};
+
+template<unsigned int Qt, char ... EmChar> constexpr char Emkb2Qt<Qt, EmChar...>::storage[];
+
+static constexpr const auto KeyTbl = qMakeArray(
+ QSortedData<
+ Emkb2Qt< Qt::Key_Escape, 'E','s','c','a','p','e' >,
+ Emkb2Qt< Qt::Key_Tab, 'T','a','b' >,
+ Emkb2Qt< Qt::Key_Backspace, 'B','a','c','k','s','p','a','c','e' >,
+ Emkb2Qt< Qt::Key_Return, 'E','n','t','e','r' >,
+ Emkb2Qt< Qt::Key_Insert, 'I','n','s','e','r','t' >,
+ Emkb2Qt< Qt::Key_Delete, 'D','e','l','e','t','e' >,
+ Emkb2Qt< Qt::Key_Pause, 'P','a','u','s','e' >,
+ Emkb2Qt< Qt::Key_Pause, 'C','l','e','a','r' >,
+ Emkb2Qt< Qt::Key_Home, 'H','o','m','e' >,
+ Emkb2Qt< Qt::Key_End, 'E','n','d' >,
+ Emkb2Qt< Qt::Key_Left, 'A','r','r','o','w','L','e','f','t' >,
+ Emkb2Qt< Qt::Key_Up, 'A','r','r','o','w','U','p' >,
+ Emkb2Qt< Qt::Key_Right, 'A','r','r','o','w','R','i','g','h','t' >,
+ Emkb2Qt< Qt::Key_Down, 'A','r','r','o','w','D','o','w','n' >,
+ Emkb2Qt< Qt::Key_PageUp, 'P','a','g','e','U','p' >,
+ Emkb2Qt< Qt::Key_PageDown, 'P','a','g','e','D','o','w','n' >,
+ Emkb2Qt< Qt::Key_Shift, 'S','h','i','f','t' >,
+ Emkb2Qt< Qt::Key_Control, 'C','o','n','t','r','o','l' >,
+ Emkb2Qt< Qt::Key_Meta, 'O','S'>,
+ Emkb2Qt< Qt::Key_Alt, 'A','l','t','L','e','f','t' >,
+ Emkb2Qt< Qt::Key_Alt, 'A','l','t' >,
+ Emkb2Qt< Qt::Key_CapsLock, 'C','a','p','s','L','o','c','k' >,
+ Emkb2Qt< Qt::Key_NumLock, 'N','u','m','L','o','c','k' >,
+ Emkb2Qt< Qt::Key_ScrollLock, 'S','c','r','o','l','l','L','o','c','k' >,
+ Emkb2Qt< Qt::Key_F1, 'F','1' >,
+ Emkb2Qt< Qt::Key_F2, 'F','2' >,
+ Emkb2Qt< Qt::Key_F3, 'F','3' >,
+ Emkb2Qt< Qt::Key_F4, 'F','4' >,
+ Emkb2Qt< Qt::Key_F5, 'F','5' >,
+ Emkb2Qt< Qt::Key_F6, 'F','6' >,
+ Emkb2Qt< Qt::Key_F7, 'F','7' >,
+ Emkb2Qt< Qt::Key_F8, 'F','8' >,
+ Emkb2Qt< Qt::Key_F9, 'F','9' >,
+ Emkb2Qt< Qt::Key_F10, 'F','1','0' >,
+ Emkb2Qt< Qt::Key_F11, 'F','1','1' >,
+ Emkb2Qt< Qt::Key_F12, 'F','1','2' >,
+ Emkb2Qt< Qt::Key_F13, 'F','1','3' >,
+ Emkb2Qt< Qt::Key_F14, 'F','1','4' >,
+ Emkb2Qt< Qt::Key_F15, 'F','1','5' >,
+ Emkb2Qt< Qt::Key_F16, 'F','1','6' >,
+ Emkb2Qt< Qt::Key_F17, 'F','1','7' >,
+ Emkb2Qt< Qt::Key_F18, 'F','1','8' >,
+ Emkb2Qt< Qt::Key_F19, 'F','1','9' >,
+ Emkb2Qt< Qt::Key_F20, 'F','2','0' >,
+ Emkb2Qt< Qt::Key_F21, 'F','2','1' >,
+ Emkb2Qt< Qt::Key_F22, 'F','2','2' >,
+ Emkb2Qt< Qt::Key_F23, 'F','2','3' >,
+ Emkb2Qt< Qt::Key_Space, ' ' >,
+ Emkb2Qt< Qt::Key_Comma, ',' >,
+ Emkb2Qt< Qt::Key_Minus, '-' >,
+ Emkb2Qt< Qt::Key_Period, '.' >,
+ Emkb2Qt< Qt::Key_Slash, '/' >,
+ Emkb2Qt< Qt::Key_0, '0' >,
+ Emkb2Qt< Qt::Key_1, '1' >,
+ Emkb2Qt< Qt::Key_2, '2' >,
+ Emkb2Qt< Qt::Key_3, '3' >,
+ Emkb2Qt< Qt::Key_4, '4' >,
+ Emkb2Qt< Qt::Key_5, '5' >,
+ Emkb2Qt< Qt::Key_6, '6' >,
+ Emkb2Qt< Qt::Key_7, '7' >,
+ Emkb2Qt< Qt::Key_8, '8' >,
+ Emkb2Qt< Qt::Key_9, '9' >,
+ Emkb2Qt< Qt::Key_Semicolon, ';' >,
+ Emkb2Qt< Qt::Key_Equal, '=' >,
+ Emkb2Qt< Qt::Key_A, 'K','e','y','A' >,
+ Emkb2Qt< Qt::Key_B, 'K','e','y','B' >,
+ Emkb2Qt< Qt::Key_C, 'K','e','y','C' >,
+ Emkb2Qt< Qt::Key_D, 'K','e','y','D' >,
+ Emkb2Qt< Qt::Key_E, 'K','e','y','E' >,
+ Emkb2Qt< Qt::Key_F, 'K','e','y','F' >,
+ Emkb2Qt< Qt::Key_G, 'K','e','y','G' >,
+ Emkb2Qt< Qt::Key_H, 'K','e','y','H' >,
+ Emkb2Qt< Qt::Key_I, 'K','e','y','I' >,
+ Emkb2Qt< Qt::Key_J, 'K','e','y','J' >,
+ Emkb2Qt< Qt::Key_K, 'K','e','y','K' >,
+ Emkb2Qt< Qt::Key_L, 'K','e','y','L' >,
+ Emkb2Qt< Qt::Key_M, 'K','e','y','M' >,
+ Emkb2Qt< Qt::Key_N, 'K','e','y','N' >,
+ Emkb2Qt< Qt::Key_O, 'K','e','y','O' >,
+ Emkb2Qt< Qt::Key_P, 'K','e','y','P' >,
+ Emkb2Qt< Qt::Key_Q, 'K','e','y','Q' >,
+ Emkb2Qt< Qt::Key_R, 'K','e','y','R' >,
+ Emkb2Qt< Qt::Key_S, 'K','e','y','S' >,
+ Emkb2Qt< Qt::Key_T, 'K','e','y','T' >,
+ Emkb2Qt< Qt::Key_U, 'K','e','y','U' >,
+ Emkb2Qt< Qt::Key_V, 'K','e','y','V' >,
+ Emkb2Qt< Qt::Key_W, 'K','e','y','W' >,
+ Emkb2Qt< Qt::Key_X, 'K','e','y','X' >,
+ Emkb2Qt< Qt::Key_Y, 'K','e','y','Y' >,
+ Emkb2Qt< Qt::Key_Z, 'K','e','y','Z' >,
+ Emkb2Qt< Qt::Key_BracketLeft, '[' >,
+ Emkb2Qt< Qt::Key_Backslash, '\\' >,
+ Emkb2Qt< Qt::Key_BracketRight, ']' >,
+ Emkb2Qt< Qt::Key_Apostrophe, '\'' >,
+ Emkb2Qt< Qt::Key_QuoteLeft, 'B','a','c','k','q','u','o','t','e' >,
+ Emkb2Qt< Qt::Key_multiply, 'N','u','m','p','a','d','M','u','l','t','i','p','l','y' >,
+ Emkb2Qt< Qt::Key_Minus, 'N','u','m','p','a','d','S','u','b','t','r','a','c','t' >,
+ Emkb2Qt< Qt::Key_Period, 'N','u','m','p','a','d','D','e','c','i','m','a','l' >,
+ Emkb2Qt< Qt::Key_Plus, 'N','u','m','p','a','d','A','d','d' >,
+ Emkb2Qt< Qt::Key_division, 'N','u','m','p','a','d','D','i','v','i','d','e' >,
+ Emkb2Qt< Qt::Key_Equal, 'N','u','m','p','a','d','E','q','u','a','l' >,
+ Emkb2Qt< Qt::Key_0, 'N','u','m','p','a','d','0' >,
+ Emkb2Qt< Qt::Key_1, 'N','u','m','p','a','d','1' >,
+ Emkb2Qt< Qt::Key_2, 'N','u','m','p','a','d','2' >,
+ Emkb2Qt< Qt::Key_3, 'N','u','m','p','a','d','3' >,
+ Emkb2Qt< Qt::Key_4, 'N','u','m','p','a','d','4' >,
+ Emkb2Qt< Qt::Key_5, 'N','u','m','p','a','d','5' >,
+ Emkb2Qt< Qt::Key_6, 'N','u','m','p','a','d','6' >,
+ Emkb2Qt< Qt::Key_7, 'N','u','m','p','a','d','7' >,
+ Emkb2Qt< Qt::Key_8, 'N','u','m','p','a','d','8' >,
+ Emkb2Qt< Qt::Key_9, 'N','u','m','p','a','d','9' >,
+ Emkb2Qt< Qt::Key_Comma, 'N','u','m','p','a','d','C','o','m','m','a' >,
+ Emkb2Qt< Qt::Key_Enter, 'N','u','m','p','a','d','E','n','t','e','r' >,
+ Emkb2Qt< Qt::Key_Paste, 'P','a','s','t','e' >,
+ Emkb2Qt< Qt::Key_AltGr, 'A','l','t','R','i','g','h','t' >,
+ Emkb2Qt< Qt::Key_Help, 'H','e','l','p' >,
+ Emkb2Qt< Qt::Key_Equal, '=' >,
+ Emkb2Qt< Qt::Key_yen, 'I','n','t','l','Y','e','n' >,
+
+ Emkb2Qt< Qt::Key_Exclam, '\x21' >,
+ Emkb2Qt< Qt::Key_QuoteDbl, '\x22' >,
+ Emkb2Qt< Qt::Key_NumberSign, '\x23' >,
+ Emkb2Qt< Qt::Key_Dollar, '\x24' >,
+ Emkb2Qt< Qt::Key_Percent, '\x25' >,
+ Emkb2Qt< Qt::Key_Ampersand, '\x26' >,
+ Emkb2Qt< Qt::Key_ParenLeft, '\x28' >,
+ Emkb2Qt< Qt::Key_ParenRight, '\x29' >,
+ Emkb2Qt< Qt::Key_Asterisk, '\x2a' >,
+ Emkb2Qt< Qt::Key_Plus, '\x2b' >,
+ Emkb2Qt< Qt::Key_Colon, '\x3a' >,
+ Emkb2Qt< Qt::Key_Semicolon, '\x3b' >,
+ Emkb2Qt< Qt::Key_Less, '\x3c' >,
+ Emkb2Qt< Qt::Key_Equal, '\x3d' >,
+ Emkb2Qt< Qt::Key_Greater, '\x3e' >,
+ Emkb2Qt< Qt::Key_Question, '\x3f' >,
+ Emkb2Qt< Qt::Key_At, '\x40' >,
+ Emkb2Qt< Qt::Key_BracketLeft, '\x5b' >,
+ Emkb2Qt< Qt::Key_Backslash, '\x5c' >,
+ Emkb2Qt< Qt::Key_BracketRight, '\x5d' >,
+ Emkb2Qt< Qt::Key_AsciiCircum, '\x5e' >,
+ Emkb2Qt< Qt::Key_Underscore, '\x5f' >,
+ Emkb2Qt< Qt::Key_QuoteLeft, '\x60'>,
+ Emkb2Qt< Qt::Key_BraceLeft, '\x7b'>,
+ Emkb2Qt< Qt::Key_Bar, '\x7c'>,
+ Emkb2Qt< Qt::Key_BraceRight, '\x7d'>,
+ Emkb2Qt< Qt::Key_AsciiTilde, '\x7e'>,
+ Emkb2Qt< Qt::Key_Space, '\x20' >,
+ Emkb2Qt< Qt::Key_Comma, '\x2c' >,
+ Emkb2Qt< Qt::Key_Minus, '\x2d' >,
+ Emkb2Qt< Qt::Key_Period, '\x2e' >,
+ Emkb2Qt< Qt::Key_Slash, '\x2f' >,
+ Emkb2Qt< Qt::Key_Apostrophe, '\x27' >,
+ Emkb2Qt< Qt::Key_Menu, 'C','o','n','t','e','x','t','M','e','n','u' >,
+
+ Emkb2Qt< Qt::Key_Agrave, '\xc3','\xa0' >,
+ Emkb2Qt< Qt::Key_Aacute, '\xc3','\xa1' >,
+ Emkb2Qt< Qt::Key_Acircumflex, '\xc3','\xa2' >,
+ Emkb2Qt< Qt::Key_Adiaeresis, '\xc3','\xa4' >,
+ Emkb2Qt< Qt::Key_AE, '\xc3','\xa6' >,
+ Emkb2Qt< Qt::Key_Atilde, '\xc3','\xa3' >,
+ Emkb2Qt< Qt::Key_Aring, '\xc3','\xa5' >,
+ Emkb2Qt< Qt::Key_Ccedilla, '\xc3','\xa7' >,
+ Emkb2Qt< Qt::Key_Egrave, '\xc3','\xa8' >,
+ Emkb2Qt< Qt::Key_Eacute, '\xc3','\xa9' >,
+ Emkb2Qt< Qt::Key_Ecircumflex, '\xc3','\xaa' >,
+ Emkb2Qt< Qt::Key_Ediaeresis, '\xc3','\xab' >,
+ Emkb2Qt< Qt::Key_Icircumflex, '\xc3','\xae' >,
+ Emkb2Qt< Qt::Key_Idiaeresis, '\xc3','\xaf' >,
+ Emkb2Qt< Qt::Key_Ocircumflex, '\xc3','\xb4' >,
+ Emkb2Qt< Qt::Key_Odiaeresis, '\xc3','\xb6' >,
+ Emkb2Qt< Qt::Key_Ograve, '\xc3','\xb2' >,
+ Emkb2Qt< Qt::Key_Oacute, '\xc3','\xb3' >,
+ Emkb2Qt< Qt::Key_Ooblique, '\xc3','\xb8' >,
+ Emkb2Qt< Qt::Key_Otilde, '\xc3','\xb5' >,
+ Emkb2Qt< Qt::Key_Ucircumflex, '\xc3','\xbb' >,
+ Emkb2Qt< Qt::Key_Udiaeresis, '\xc3','\xbc' >,
+ Emkb2Qt< Qt::Key_Ugrave, '\xc3','\xb9' >,
+ Emkb2Qt< Qt::Key_Uacute, '\xc3','\xba' >,
+ Emkb2Qt< Qt::Key_Ntilde, '\xc3','\xb1' >,
+ Emkb2Qt< Qt::Key_ydiaeresis, '\xc3','\xbf' >
+ >::Data{}
+ );
+
+static constexpr const auto DeadKeyShiftTbl = qMakeArray(
+ QSortedData<
+ // shifted
+ Emkb2Qt< Qt::Key_Agrave, '\xc3','\x80' >,
+ Emkb2Qt< Qt::Key_Aacute, '\xc3','\x81' >,
+ Emkb2Qt< Qt::Key_Acircumflex, '\xc3','\x82' >,
+ Emkb2Qt< Qt::Key_Adiaeresis, '\xc3','\x84' >,
+ Emkb2Qt< Qt::Key_AE, '\xc3','\x86' >,
+ Emkb2Qt< Qt::Key_Atilde, '\xc3','\x83' >,
+ Emkb2Qt< Qt::Key_Aring, '\xc3','\x85' >,
+ Emkb2Qt< Qt::Key_Egrave, '\xc3','\x88' >,
+ Emkb2Qt< Qt::Key_Eacute, '\xc3','\x89' >,
+ Emkb2Qt< Qt::Key_Ecircumflex, '\xc3','\x8a' >,
+ Emkb2Qt< Qt::Key_Ediaeresis, '\xc3','\x8b' >,
+ Emkb2Qt< Qt::Key_Icircumflex, '\xc3','\x8e' >,
+ Emkb2Qt< Qt::Key_Idiaeresis, '\xc3','\x8f' >,
+ Emkb2Qt< Qt::Key_Ocircumflex, '\xc3','\x94' >,
+ Emkb2Qt< Qt::Key_Odiaeresis, '\xc3','\x96' >,
+ Emkb2Qt< Qt::Key_Ograve, '\xc3','\x92' >,
+ Emkb2Qt< Qt::Key_Oacute, '\xc3','\x93' >,
+ Emkb2Qt< Qt::Key_Ooblique, '\xc3','\x98' >,
+ Emkb2Qt< Qt::Key_Otilde, '\xc3','\x95' >,
+ Emkb2Qt< Qt::Key_Ucircumflex, '\xc3','\x9b' >,
+ Emkb2Qt< Qt::Key_Udiaeresis, '\xc3','\x9c' >,
+ Emkb2Qt< Qt::Key_Ugrave, '\xc3','\x99' >,
+ Emkb2Qt< Qt::Key_Uacute, '\xc3','\x9a' >,
+ Emkb2Qt< Qt::Key_Ntilde, '\xc3','\x91' >,
+ Emkb2Qt< Qt::Key_Ccedilla, '\xc3','\x87' >,
+ Emkb2Qt< Qt::Key_ydiaeresis, '\xc3','\x8f' >
+ >::Data{}
+);
+
// macOS CTRL <-> META switching. We most likely want to enable
// the existing switching code in QtGui, but for now do it here.
static bool g_usePlatformMacCtrlMetaSwitching = false;
bool g_useNaturalScrolling = true; // natural scrolling is default on linux/windows
-void setNaturalScrolling(bool use) {
- g_useNaturalScrolling = use;
+static void mouseWheelEvent(emscripten::val event) {
+
+ emscripten::val wheelInterted = event["webkitDirectionInvertedFromDevice"];
+
+ if (wheelInterted.as<bool>()) {
+ g_useNaturalScrolling = true;
+ }
}
-EMSCRIPTEN_BINDINGS(mouse_module) {
- function("setNaturalScrolling", &setNaturalScrolling);
+EMSCRIPTEN_BINDINGS(qtMouseModule) {
+ function("qtMouseWheelEvent", &mouseWheelEvent);
}
-QWasmEventTranslator::QWasmEventTranslator(QObject *parent)
- : QObject(parent)
+QWasmEventTranslator::QWasmEventTranslator(QWasmScreen *screen)
+ : QObject(screen)
, draggedWindow(nullptr)
, lastWindow(nullptr)
, pressedButtons(Qt::NoButton)
, resizeMode(QWasmWindow::ResizeNone)
{
- emscripten_set_keydown_callback(0, (void *)this, 1, &keyboard_cb);
- emscripten_set_keyup_callback(0, (void *)this, 1, &keyboard_cb);
-
- emscripten_set_mousedown_callback(0, (void *)this, 1, &mouse_cb);
- emscripten_set_mouseup_callback(0, (void *)this, 1, &mouse_cb);
- emscripten_set_mousemove_callback(0, (void *)this, 1, &mouse_cb);
-
- emscripten_set_focus_callback(0, (void *)this, 1, &focus_cb);
-
- emscripten_set_wheel_callback(0, (void *)this, 1, &wheel_cb);
-
touchDevice = new QTouchDevice;
touchDevice->setType(QTouchDevice::TouchScreen);
touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition);
QWindowSystemInterface::registerTouchDevice(touchDevice);
- emscripten_set_touchstart_callback("#canvas", (void *)this, 1, &touchCallback);
- emscripten_set_touchend_callback("#canvas", (void *)this, 1, &touchCallback);
- emscripten_set_touchmove_callback("#canvas", (void *)this, 1, &touchCallback);
- emscripten_set_touchcancel_callback("#canvas", (void *)this, 1, &touchCallback);
+ initEventHandlers();
+}
+
+void QWasmEventTranslator::initEventHandlers()
+{
+ QByteArray _canvasId = screen()->canvasId().toUtf8();
+ const char *canvasId = _canvasId.constData();
// The Platform Detect: expand coverage and move as needed
enum Platform {
GenericPlatform,
MacOSPlatform
};
- Platform platform =
- Platform(EM_ASM_INT("if (navigator.platform.includes(\"Mac\")) return 1; return 0;"));
-
+ Platform platform = Platform(emscripten::val::global("navigator")["platform"]
+ .call<bool>("includes", emscripten::val("Mac")));
g_usePlatformMacCtrlMetaSwitching = (platform == MacOSPlatform);
if (platform == MacOSPlatform) {
g_useNaturalScrolling = false; // make this !default on macOS
- EM_ASM(
- if (window.safari !== undefined) {//this only works on safari
- Module["canvas"].addEventListener('wheel', mouseWheelEvent);
- function mouseWheelEvent(e) {
- if (event.webkitDirectionInvertedFromDevice) {
- Module.setNaturalScrolling(event.webkitDirectionInvertedFromDevice);
- }
- }
- }
- );
+
+ if (emscripten::val::global("window")["safari"].isUndefined()) {
+
+ emscripten::val::global(canvasId).call<void>("addEventListener",
+ std::string("wheel"),
+ val::module_property("qtMouseWheelEvent"));
+ }
}
+
+ emscripten_set_keydown_callback(canvasId, (void *)this, 1, &keyboard_cb);
+ emscripten_set_keyup_callback(canvasId, (void *)this, 1, &keyboard_cb);
+
+ emscripten_set_mousedown_callback(canvasId, (void *)this, 1, &mouse_cb);
+ emscripten_set_mouseup_callback(canvasId, (void *)this, 1, &mouse_cb);
+ emscripten_set_mousemove_callback(canvasId, (void *)this, 1, &mouse_cb);
+
+ emscripten_set_focus_callback(canvasId, (void *)this, 1, &focus_cb);
+
+ emscripten_set_wheel_callback(canvasId, (void *)this, 1, &wheel_cb);
+
+ emscripten_set_touchstart_callback(canvasId, (void *)this, 1, &touchCallback);
+ emscripten_set_touchend_callback(canvasId, (void *)this, 1, &touchCallback);
+ emscripten_set_touchmove_callback(canvasId, (void *)this, 1, &touchCallback);
+ emscripten_set_touchcancel_callback(canvasId, (void *)this, 1, &touchCallback);
}
template <typename Event>
@@ -153,132 +417,49 @@ QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateMouseEventModifier(c
int QWasmEventTranslator::keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
{
- Q_UNUSED(userData)
-
- bool alphanumeric;
- Qt::Key qtKey = translateEmscriptKey(keyEvent, &alphanumeric);
+ QWasmEventTranslator *wasmTranslator = reinterpret_cast<QWasmEventTranslator *>(userData);
+ bool accepted = wasmTranslator->processKeyboard(eventType, keyEvent);
- QEvent::Type keyType = QEvent::None;
- switch (eventType) {
- case EMSCRIPTEN_EVENT_KEYPRESS:
- case EMSCRIPTEN_EVENT_KEYDOWN: //down
- keyType = QEvent::KeyPress;
- break;
- case EMSCRIPTEN_EVENT_KEYUP: //up
- keyType = QEvent::KeyRelease;
- break;
- default:
- break;
- };
-
- if (keyType == QEvent::None)
- return 0;
-
- QString keyText = alphanumeric ? QString(keyEvent->key) : QString();
- bool accepted = QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(
- 0, keyType, qtKey, translateKeyboardEventModifier(keyEvent), keyText);
- QWasmEventDispatcher::maintainTimers();
return accepted ? 1 : 0;
}
-Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey, bool *outAlphanumeric)
+QWasmScreen *QWasmEventTranslator::screen()
{
- Qt::Key qtKey;
- if (outAlphanumeric)
- *outAlphanumeric = false;
-
- switch (emscriptKey->keyCode) {
- case KeyMultiply: qtKey = Qt::Key_Asterisk; *outAlphanumeric = true; break;
- case KeyAdd: qtKey = Qt::Key_Plus; *outAlphanumeric = true; break;
- case KeyMinus: qtKey = Qt::Key_Minus; *outAlphanumeric = true; break;
- case KeySubtract: qtKey = Qt::Key_Minus; *outAlphanumeric = true; break;
- case KeyDecimal: qtKey = Qt::Key_Period; *outAlphanumeric = true; break;
- case KeyDivide: qtKey = Qt::Key_Slash; *outAlphanumeric = true; break;
- case KeyNumPad0: qtKey = Qt::Key_0; *outAlphanumeric = true; break;
- case KeyNumPad1: qtKey = Qt::Key_1; *outAlphanumeric = true; break;
- case KeyNumPad2: qtKey = Qt::Key_2; *outAlphanumeric = true; break;
- case KeyNumPad3: qtKey = Qt::Key_3; *outAlphanumeric = true; break;
- case KeyNumPad4: qtKey = Qt::Key_4; *outAlphanumeric = true; break;
- case KeyNumPad5: qtKey = Qt::Key_5; *outAlphanumeric = true; break;
- case KeyNumPad6: qtKey = Qt::Key_6; *outAlphanumeric = true; break;
- case KeyNumPad7: qtKey = Qt::Key_7; *outAlphanumeric = true; break;
- case KeyNumPad8: qtKey = Qt::Key_8; *outAlphanumeric = true; break;
- case KeyNumPad9: qtKey = Qt::Key_9; *outAlphanumeric = true; break;
- case KeyComma: qtKey = Qt::Key_Comma; *outAlphanumeric = true; break;
- case KeyPeriod: qtKey = Qt::Key_Period; *outAlphanumeric = true; break;
- case KeySlash: qtKey = Qt::Key_Slash; *outAlphanumeric = true; break;
- case KeySemiColon: qtKey = Qt::Key_Semicolon; *outAlphanumeric = true; break;
- case KeyEquals: qtKey = Qt::Key_Equal; *outAlphanumeric = true; break;
- case KeyOpenBracket: qtKey = Qt::Key_BracketLeft; *outAlphanumeric = true; break;
- case KeyCloseBracket: qtKey = Qt::Key_BracketRight; *outAlphanumeric = true; break;
- case KeyBackSlash: qtKey = Qt::Key_Backslash; *outAlphanumeric = true; break;
- case KeyMeta:
- Q_FALLTHROUGH();
- case KeyMetaRight:
- qtKey = Qt::Key_Meta;
- break;
- case KeyTab: qtKey = Qt::Key_Tab; break;
- case KeyClear: qtKey = Qt::Key_Clear; break;
- case KeyBackSpace: qtKey = Qt::Key_Backspace; break;
- case KeyEnter: qtKey = Qt::Key_Return; break;
- case KeyShift: qtKey = Qt::Key_Shift; break;
- case KeyControl: qtKey = Qt::Key_Control; break;
- case KeyAlt: qtKey = Qt::Key_Alt; break;
- case KeyCapsLock: qtKey = Qt::Key_CapsLock; break;
- case KeyEscape: qtKey = Qt::Key_Escape; break;
- case KeyPageUp: qtKey = Qt::Key_PageUp; break;
- case KeyPageDown: qtKey = Qt::Key_PageDown; break;
- case KeyEnd: qtKey = Qt::Key_End; break;
- case KeyHome: qtKey = Qt::Key_Home; break;
- case KeyLeft: qtKey = Qt::Key_Left; break;
- case KeyUp: qtKey = Qt::Key_Up; break;
- case KeyRight: qtKey = Qt::Key_Right; break;
- case KeyDown: qtKey = Qt::Key_Down; break;
- case KeyBrightnessDown: qtKey = Qt::Key_MonBrightnessDown; break;
- case KeyBrightnessUp: qtKey = Qt::Key_MonBrightnessUp; break;
- case KeyMediaTrackPrevious: qtKey = Qt::Key_MediaPrevious; break;
- case KeyMediaPlayPause: qtKey = Qt::Key_MediaTogglePlayPause; break;
- case KeyMediaTrackNext: qtKey = Qt::Key_MediaNext; break;
- case KeyAudioVolumeMute: qtKey = Qt::Key_VolumeMute; break;
- case KeyAudioVolumeDown: qtKey = Qt::Key_VolumeDown; break;
- case KeyAudioVolumeUp: qtKey = Qt::Key_VolumeUp; break;
- case KeyDelete: qtKey = Qt::Key_Delete; break;
-
- case KeyF1: qtKey = Qt::Key_F1; break;
- case KeyF2: qtKey = Qt::Key_F2; break;
- case KeyF3: qtKey = Qt::Key_F3; break;
- case KeyF4: qtKey = Qt::Key_F4; break;
- case KeyF5: qtKey = Qt::Key_F5; break;
- case KeyF6: qtKey = Qt::Key_F6; break;
- case KeyF7: qtKey = Qt::Key_F7; break;
- case KeyF8: qtKey = Qt::Key_F8; break;
- case KeyF9: qtKey = Qt::Key_F9; break;
- case KeyF10: qtKey = Qt::Key_F10; break;
- case KeyF11: qtKey = Qt::Key_F11; break;
- case KeyF12: qtKey = Qt::Key_F12; break;
- case 124: qtKey = Qt::Key_F13; break;
- case 125: qtKey = Qt::Key_F14; break;
-
- case KeySpace:
- default:
- if (outAlphanumeric)
- *outAlphanumeric = true;
- qtKey = static_cast<Qt::Key>(emscriptKey->keyCode);
- break;
- }
+ return static_cast<QWasmScreen *>(parent());
+}
+
+Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey)
+{
+ Qt::Key qtKey = Qt::Key_unknown;
+
+ if (qstrncmp(emscriptKey->code, "Key", 3) == 0 || qstrncmp(emscriptKey->code, "Numpad", 6) == 0) {
- // Handle Mac command key. Using event->keyCode as above is
- // no reliable since the codes differ between browsers.
- if (qstrncmp(emscriptKey->key, "Meta", 4) == 0) {
- qtKey = Qt::Key_Meta;
- *outAlphanumeric = false;
+ emkb2qt_t searchKey{emscriptKey->code, 0}; // search emcsripten code
+ auto it1 = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
+ if (it1 != KeyTbl.end() && !(searchKey < *it1)) {
+ qtKey = static_cast<Qt::Key>(it1->qt);
+ }
+ } else if (qstrncmp(emscriptKey->key, "Dead", 4) == 0 ) {
+ emkb2qt_t searchKey1{emscriptKey->code, 0};
+ for (auto it1 = KeyTbl.cbegin(); it1 != KeyTbl.end(); ++it1)
+ if (it1 != KeyTbl.end() && (qstrcmp(searchKey1.em, it1->em) == 0)) {
+ qtKey = static_cast<Qt::Key>(it1->qt);
+ }
}
- if (g_usePlatformMacCtrlMetaSwitching) {
- if (qtKey == Qt::Key_Meta)
- qtKey = Qt::Key_Control;
- else if (qtKey == Qt::Key_Control)
- qtKey = Qt::Key_Meta;
+ if (qtKey == Qt::Key_unknown) {
+ emkb2qt_t searchKey{emscriptKey->key, 0}; // search unicode key
+ auto it1 = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
+ if (it1 != KeyTbl.end() && !(searchKey < *it1)) {
+ qtKey = static_cast<Qt::Key>(it1->qt);
+ }
+ }
+ if (qtKey == Qt::Key_unknown) {//try harder with shifted number keys
+ emkb2qt_t searchKey1{emscriptKey->key, 0};
+ for (auto it1 = KeyTbl.cbegin(); it1 != KeyTbl.end(); ++it1)
+ if (it1 != KeyTbl.end() && (qstrcmp(searchKey1.em, it1->em) == 0)) {
+ qtKey = static_cast<Qt::Key>(it1->qt);
+ }
}
return qtKey;
@@ -363,27 +544,30 @@ void resizeWindow(QWindow *window, QWasmWindow::ResizeMode mode,
void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent)
{
auto timestamp = mouseEvent->timestamp;
- QPoint point(mouseEvent->canvasX, mouseEvent->canvasY);
+ QPoint targetPoint(mouseEvent->targetX, mouseEvent->targetY);
+ QPoint globalPoint = screen()->geometry().topLeft() + targetPoint;
QEvent::Type buttonEventType = QEvent::None;
-
Qt::MouseButton button = translateMouseButton(mouseEvent->button);
Qt::KeyboardModifiers modifiers = translateMouseEventModifier(mouseEvent);
- QWindow *window2 = QWasmIntegration::get()->compositor()->windowAt(point, 5);
- if (window2 != nullptr)
- lastWindow = window2;
+ QWindow *window2 = screen()->compositor()->windowAt(globalPoint, 5);
- QWasmWindow *htmlWindow = static_cast<QWasmWindow*>(window2->handle());
+ if (window2 == nullptr) {
+ window2 = lastWindow;
+ } else {
+ lastWindow = window2;
+ }
- bool interior = window2 && window2->geometry().contains(point);
+ QPoint localPoint = window2->mapFromGlobal(globalPoint);
+ bool interior = window2->geometry().contains(globalPoint);
- QPoint localPoint(point.x() - window2->geometry().x(), point.y() - window2->geometry().y());
+ QWasmWindow *htmlWindow = static_cast<QWasmWindow*>(window2->handle());
switch (eventType) {
case EMSCRIPTEN_EVENT_MOUSEDOWN:
{
if (window2)
- window2->raise();
+ window2->requestActivate();
pressedButtons.setFlag(button);
@@ -391,18 +575,18 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
pressedWindow = window2;
buttonEventType = QEvent::MouseButtonPress;
if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
- if (htmlWindow && window2->flags().testFlag(Qt::WindowTitleHint) && htmlWindow->isPointOnTitle(point))
+ if (htmlWindow && window2->flags().testFlag(Qt::WindowTitleHint) && htmlWindow->isPointOnTitle(globalPoint))
draggedWindow = window2;
- else if (htmlWindow && htmlWindow->isPointOnResizeRegion(point)) {
+ else if (htmlWindow && htmlWindow->isPointOnResizeRegion(globalPoint)) {
draggedWindow = window2;
- resizeMode = htmlWindow->resizeModeAtPoint(point);
- resizePoint = point;
+ resizeMode = htmlWindow->resizeModeAtPoint(globalPoint);
+ resizePoint = globalPoint;
resizeStartRect = window2->geometry();
}
}
}
- htmlWindow->injectMousePressed(localPoint, point, button, modifiers);
+ htmlWindow->injectMousePressed(localPoint, globalPoint, button, modifiers);
break;
}
case EMSCRIPTEN_EVENT_MOUSEUP:
@@ -422,7 +606,7 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
}
if (oldWindow)
- oldWindow->injectMouseReleased(localPoint, point, button, modifiers);
+ oldWindow->injectMouseReleased(localPoint, globalPoint, button, modifiers);
break;
}
case EMSCRIPTEN_EVENT_MOUSEMOVE: // drag event
@@ -435,7 +619,7 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
}
if (resizeMode != QWasmWindow::ResizeNone && !(htmlWindow->m_windowState & Qt::WindowFullScreen)) {
- QPoint delta = QPoint(mouseEvent->canvasX, mouseEvent->canvasY) - resizePoint;
+ QPoint delta = QPoint(mouseEvent->targetX, mouseEvent->targetY) - resizePoint;
resizeWindow(draggedWindow, resizeMode, resizeStartRect, delta);
}
}
@@ -451,7 +635,7 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
}
if (window2 && interior) {
QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
- window2, timestamp, localPoint, point, pressedButtons, button, buttonEventType, modifiers);
+ window2, timestamp, localPoint, globalPoint, pressedButtons, button, buttonEventType, modifiers);
}
}
@@ -463,8 +647,8 @@ int QWasmEventTranslator::focus_cb(int /*eventType*/, const EmscriptenFocusEvent
int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
{
Q_UNUSED(eventType)
- Q_UNUSED(userData)
+ QWasmEventTranslator *eventTranslator = static_cast<QWasmEventTranslator *>(userData);
EmscriptenMouseEvent mouseEvent = wheelEvent->mouse;
int scrollFactor = 0;
@@ -483,21 +667,24 @@ int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wh
if (g_useNaturalScrolling) //macOS platform has document oriented scrolling
scrollFactor = -scrollFactor;
- Qt::KeyboardModifiers modifiers = translateMouseEventModifier(&mouseEvent);
+ QWasmEventTranslator *translator = (QWasmEventTranslator*)userData;
+ Qt::KeyboardModifiers modifiers = translator->translateMouseEventModifier(&mouseEvent);
auto timestamp = mouseEvent.timestamp;
- QPoint globalPoint(mouseEvent.canvasX, mouseEvent.canvasY);
-
- QWindow *window2 = QWasmIntegration::get()->compositor()->windowAt(globalPoint, 5);
+ QPoint targetPoint(mouseEvent.targetX, mouseEvent.targetY);
+ QPoint globalPoint = eventTranslator->screen()->geometry().topLeft() + targetPoint;
- QPoint localPoint(globalPoint.x() - window2->geometry().x(), globalPoint.y() - window2->geometry().y());
+ QWindow *window2 = eventTranslator->screen()->compositor()->windowAt(globalPoint, 5);
+ if (!window2)
+ return 0;
+ QPoint localPoint = window2->mapFromGlobal(globalPoint);
QPoint pixelDelta;
if (wheelEvent->deltaY != 0) pixelDelta.setY(wheelEvent->deltaY * scrollFactor);
if (wheelEvent->deltaX != 0) pixelDelta.setX(wheelEvent->deltaX * scrollFactor);
- QWindowSystemInterface::handleWheelEvent(window2, timestamp, localPoint, globalPoint, QPoint(), pixelDelta, modifiers);
-
+ QWindowSystemInterface::handleWheelEvent(window2, timestamp, localPoint,
+ globalPoint, QPoint(), pixelDelta, modifiers);
QWasmEventDispatcher::maintainTimers();
return 1;
@@ -505,6 +692,12 @@ int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wh
int QWasmEventTranslator::touchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
{
+ auto translator = reinterpret_cast<QWasmEventTranslator*>(userData);
+ return translator->handleTouch(eventType, touchEvent);
+}
+
+int QWasmEventTranslator::handleTouch(int eventType, const EmscriptenTouchEvent *touchEvent)
+{
QList<QWindowSystemInterface::TouchPoint> touchPointList;
touchPointList.reserve(touchEvent->numTouches);
QWindow *window2;
@@ -513,43 +706,69 @@ int QWasmEventTranslator::touchCallback(int eventType, const EmscriptenTouchEven
const EmscriptenTouchPoint *touches = &touchEvent->touches[i];
- QPoint point(touches->canvasX, touches->canvasY);
- window2 = QWasmIntegration::get()->compositor()->windowAt(point, 5);
+ QPoint targetPoint(touches->targetX, touches->targetY);
+ QPoint globalPoint = screen()->geometry().topLeft() + targetPoint;
+
+ window2 = this->screen()->compositor()->windowAt(globalPoint, 5);
+ if (window2 == nullptr)
+ continue;
QWindowSystemInterface::TouchPoint touchPoint;
- auto cX = point.x();
- auto cY = point.y();
touchPoint.area = QRect(0, 0, 8, 8);
- touchPoint.area.moveCenter(QPointF(cX,cY)); // simulate area
-
touchPoint.id = touches->identifier;
- touchPoint.normalPosition = QPointF(cX / window2->width(), cY / window2->height());
+ touchPoint.pressure = 1.0;
+
+ touchPoint.area.moveCenter(globalPoint);
+
+ const auto tp = pressedTouchIds.constFind(touchPoint.id);
+ if (tp != pressedTouchIds.constEnd())
+ touchPoint.normalPosition = tp.value();
+
+ QPointF localPoint = QPointF(window2->mapFromGlobal(globalPoint));
+ QPointF normalPosition(localPoint.x() / window2->width(),
+ localPoint.y() / window2->height());
+
+ const bool stationaryTouchPoint = (normalPosition == touchPoint.normalPosition);
+ touchPoint.normalPosition = normalPosition;
switch (eventType) {
case EMSCRIPTEN_EVENT_TOUCHSTART:
- touchPoint.state = Qt::TouchPointPressed;
+ if (tp != pressedTouchIds.constEnd()) {
+ touchPoint.state = (stationaryTouchPoint
+ ? Qt::TouchPointStationary
+ : Qt::TouchPointMoved);
+ } else {
+ touchPoint.state = Qt::TouchPointPressed;
+ }
+ pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
+
break;
case EMSCRIPTEN_EVENT_TOUCHEND:
touchPoint.state = Qt::TouchPointReleased;
+ pressedTouchIds.remove(touchPoint.id);
break;
case EMSCRIPTEN_EVENT_TOUCHMOVE:
- touchPoint.state = Qt::TouchPointMoved;
+ touchPoint.state = (stationaryTouchPoint
+ ? Qt::TouchPointStationary
+ : Qt::TouchPointMoved);
+
+ pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
break;
default:
- Q_UNREACHABLE();
+ break;
}
touchPointList.append(touchPoint);
}
- QWasmEventTranslator *wasmEventTranslator = (QWasmEventTranslator*)userData;
QFlags<Qt::KeyboardModifier> keyModifier = translatKeyModifier(touchEvent);
- if (eventType != EMSCRIPTEN_EVENT_TOUCHCANCEL)
- QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(window2, wasmEventTranslator->getTimestamp(), wasmEventTranslator->touchDevice, touchPointList, keyModifier);
- else
- QWindowSystemInterface::handleTouchCancelEvent(window2, wasmEventTranslator->getTimestamp(), wasmEventTranslator->touchDevice, keyModifier);
+ QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(
+ window2, getTimestamp(), touchDevice, touchPointList, keyModifier);
+
+ if (eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL)
+ QWindowSystemInterface::handleTouchCancelEvent(window2, getTimestamp(), touchDevice, keyModifier);
QWasmEventDispatcher::maintainTimers();
return 1;
@@ -560,4 +779,134 @@ quint64 QWasmEventTranslator::getTimestamp()
return QDeadlineTimer::current().deadlineNSecs() / 1000;
}
+Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey)
+{
+ Qt::Key wasmKey = Qt::Key_unknown;
+ switch (deadKey) {
+#ifdef Q_OS_MACOS
+ case Qt::Key_QuoteLeft: // ` macOS: Key_Dead_Grave
+#else
+ case Qt::Key_O: // ´ Key_Dead_Grave
+#endif
+ wasmKey = graveKeyTable.value(accentBaseKey);
+ break;
+ case Qt::Key_E: // ´ Key_Dead_Acute
+ wasmKey = acuteKeyTable.value(accentBaseKey);
+ break;
+ case Qt::Key_AsciiTilde:
+ case Qt::Key_N:// Key_Dead_Tilde
+ wasmKey = tildeKeyTable.value(accentBaseKey);
+ break;
+#ifndef Q_OS_MACOS
+ case Qt::Key_QuoteLeft:
+#endif
+ case Qt::Key_U:// ¨ Key_Dead_Diaeresis
+ wasmKey = diaeresisKeyTable.value(accentBaseKey);
+ break;
+ case Qt::Key_I:// macOS Key_Dead_Circumflex
+ case Qt::Key_6:// linux
+ case Qt::Key_Apostrophe:// linux
+ wasmKey = circumflexKeyTable.value(accentBaseKey);
+ break;
+ break;
+ default:
+ break;
+ };
+
+ return wasmKey;
+}
+
+bool QWasmEventTranslator::processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent)
+{
+ Qt::Key qtKey = translateEmscriptKey(keyEvent);
+
+ Qt::KeyboardModifiers modifiers = translateKeyboardEventModifier(keyEvent);
+
+ QString keyText;
+ QEvent::Type keyType = QEvent::None;
+ switch (eventType) {
+ case EMSCRIPTEN_EVENT_KEYPRESS:
+ case EMSCRIPTEN_EVENT_KEYDOWN: // down
+ keyType = QEvent::KeyPress;
+
+ if (m_emDeadKey != Qt::Key_unknown) {
+
+ Qt::Key transformedKey = translateDeadKey(m_emDeadKey, qtKey);
+
+ if (transformedKey != Qt::Key_unknown)
+ qtKey = transformedKey;
+
+ if (keyEvent->shiftKey == 0) {
+ for (auto it = KeyTbl.cbegin(); it != KeyTbl.end(); ++it) {
+ if (it != KeyTbl.end() && (qtKey == static_cast<Qt::Key>(it->qt))) {
+ keyText = it->em;
+ m_emDeadKey = Qt::Key_unknown;
+ break;
+ }
+ }
+ } else {
+ for (auto it = DeadKeyShiftTbl.cbegin(); it != DeadKeyShiftTbl.end(); ++it) {
+ if (it != DeadKeyShiftTbl.end() && (qtKey == static_cast<Qt::Key>(it->qt))) {
+ keyText = it->em;
+ m_emDeadKey = Qt::Key_unknown;
+ break;
+ }
+ }
+ }
+ }
+ if (qstrncmp(keyEvent->key, "Dead", 4) == 0 || qtKey == Qt::Key_AltGr) {
+ qtKey = translateEmscriptKey(keyEvent);
+ m_emStickyDeadKey = true;
+ if (keyEvent->shiftKey == 1 && qtKey == Qt::Key_QuoteLeft)
+ qtKey = Qt::Key_AsciiTilde;
+ m_emDeadKey = qtKey;
+ }
+ break;
+ case EMSCRIPTEN_EVENT_KEYUP: // up
+ keyType = QEvent::KeyRelease;
+ if (m_emStickyDeadKey && qtKey != Qt::Key_Alt) {
+ m_emStickyDeadKey = false;
+ }
+ break;
+ default:
+ break;
+ };
+
+ if (keyType == QEvent::None)
+ return 0;
+
+ QFlags<Qt::KeyboardModifier> mods = translateKeyboardEventModifier(keyEvent);
+
+ // Clipboard fallback path: cut/copy/paste are handled by clipboard event
+ // handlers if direct clipboard access is not available.
+ if (!QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi && modifiers & Qt::ControlModifier &&
+ (qtKey == Qt::Key_X || qtKey == Qt::Key_C || qtKey == Qt::Key_V)) {
+ return 0;
+ }
+
+ bool accepted = false;
+
+ if (keyType == QEvent::KeyPress &&
+ mods.testFlag(Qt::ControlModifier)
+ && qtKey == Qt::Key_V) {
+ QWasmIntegration::get()->getWasmClipboard()->readTextFromClipboard();
+ } else {
+ if (keyText.isEmpty())
+ keyText = QString(keyEvent->key);
+ if (keyText.size() > 1)
+ keyText.clear();
+ accepted = QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(
+ 0, keyType, qtKey, modifiers, keyText);
+ }
+ if (keyType == QEvent::KeyPress &&
+ mods.testFlag(Qt::ControlModifier)
+ && qtKey == Qt::Key_C) {
+ QWasmIntegration::get()->getWasmClipboard()->writeTextToClipboard();
+ }
+
+ QWasmEventDispatcher::maintainTimers();
+
+ return accepted;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h
index f3dff8e48c..1655b7226a 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.h
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h
@@ -36,6 +36,7 @@
#include <emscripten/html5.h>
#include "qwasmwindow.h"
#include <QtGui/qtouchdevice.h>
+#include <QHash>
QT_BEGIN_NAMESPACE
@@ -45,133 +46,9 @@ class QWasmEventTranslator : public QObject
{
Q_OBJECT
- enum KeyCode {
- // numpad
- KeyNumPad0 = 0x60,
- KeyNumPad1 = 0x61,
- KeyNumPad2 = 0x62,
- KeyNumPad3 = 0x63,
- KeyNumPad4 = 0x64,
- KeyNumPad5 = 0x65,
- KeyNumPad6 = 0x66,
- KeyNumPad7 = 0x67,
- KeyNumPad8 = 0x68,
- KeyNumPad9 = 0x69,
- KeyMultiply = 0x6A,
- KeyAdd = 0x6B,
- KeySeparator = 0x6C,
- KeySubtract = 0x6D,
- KeyDecimal = 0x6E,
- KeyDivide = 0x6F,
- KeyMeta = 0x5B,
- KeyMetaRight = 0x5C,
- ////////
- KeyClear = 0x90,
- KeyEnter = 0xD,
- KeyBackSpace = 0x08,
- KeyCancel = 0x03,
- KeyTab = 0x09,
- KeyShift = 0x10,
- KeyControl = 0x11,
- KeyAlt = 0x12,
- KeyPause = 0x13,
- KeyCapsLock = 0x14,
- KeyEscape = 0x1B,
- KeySpace = 0x20,
- KeyPageUp = 0x21,
- KeyPageDown = 0x22,
- KeyEnd = 0x23,
- KeyHome = 0x24,
- KeyLeft = 0x25,
- KeyUp = 0x26,
- KeyRight = 0x27,
- KeyDown = 0x28,
- KeyComma = 0xBC,
- KeyPeriod = 0xBE,
- KeySlash = 0xBF,
- KeyZero = 0x30,
- KeyOne = 0x31,
- KeyTwo = 0x32,
- KeyThree = 0x33,
- KeyFour = 0x34,
- KeyFive = 0x35,
- KeySix = 0x36,
- KeySeven = 0x37,
- KeyEight = 0x38,
- KeyNine = 0x39,
- KeyBrightnessDown = 0xD8,
- KeyBrightnessUp = 0xD9,
- KeyMediaTrackPrevious = 0xB1,
- KeyMediaPlayPause = 0xB3,
- KeyMediaTrackNext = 0xB0,
- KeyAudioVolumeMute = 0xAD,
- KeyAudioVolumeDown = 0xAE,
- KeyAudioVolumeUp = 0xAF,
- KeySemiColon = 0xBA,
- KeyEquals = 0xBB,
- KeyMinus = 0xBD,
- KeyA = 0x41,
- KeyB = 0x42,
- KeyC = 0x43,
- KeyD = 0x44,
- KeyE = 0x45,
- KeyF = 0x46,
- KeyG = 0x47,
- KeyH = 0x48,
- KeyI = 0x49,
- KeyJ = 0x4A,
- KeyK = 0x4B,
- KeyL = 0x4C,
- KeyM = 0x4D,
- KeyN = 0x4E,
- KeyO = 0x4F,
- KeyP = 0x50,
- KeyQ = 0x51,
- KeyR = 0x52,
- KeyS = 0x53,
- KeyT = 0x54,
- KeyU = 0x55,
- KeyV = 0x56,
- KeyW = 0x57,
- KeyX = 0x58,
- KeyY = 0x59,
- KeyZ = 0x5A,
- KeyOpenBracket = 0xDB,
- KeyBackSlash = 0xDC,
- KeyCloseBracket = 0xDD,
- KeyF1 = 0x70,
- KeyF2 = 0x71,
- KeyF3 = 0x72,
- KeyF4 = 0x73,
- KeyF5 = 0x74,
- KeyF6 = 0x75,
- KeyF7 = 0x76,
- KeyF8 = 0x77,
- KeyF9 = 0x78,
- KeyF10 = 0x79,
- KeyF11 = 0x7A,
- KeyF12 = 0x7B,
- KeyDelete = 0x2E,
- KeyNumLock = 0x90,
- KeyScrollLock = 0x91,
- KeyPrintScreen = 0x9A,
- KeyInsert = 0x9B,
- KeyHelp = 0x9C,
- KeyBackQuote = 0xC0,
- KeyQuote = 0xDE,
- KeyFinal = 0x18,
- KeyConvert = 0x1C,
- KeyNonConvert = 0x1D,
- KeyAccept = 0x1E,
- KeyModeChange = 0x1F,
- KeyKana = 0x15,
- KeyKanji = 0x19,
- KeyUndefined = 0x0
- };
-
public:
- explicit QWasmEventTranslator(QObject *parent = 0);
+ explicit QWasmEventTranslator(QWasmScreen *screen);
static int keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
static int mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
@@ -181,18 +58,62 @@ public:
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
void processEvents();
+ void initEventHandlers();
+ int handleTouch(int eventType, const EmscriptenTouchEvent *touchEvent);
Q_SIGNALS:
void getWindowAt(const QPoint &point, QWindow **window);
private:
- static Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey, bool *outAlphanumretic);
+ QWasmScreen *screen();
+ Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey);
template <typename Event>
- static QFlags<Qt::KeyboardModifier> translatKeyModifier(const Event *event);
- static QFlags<Qt::KeyboardModifier> translateKeyboardEventModifier(const EmscriptenKeyboardEvent *keyEvent);
- static QFlags<Qt::KeyboardModifier> translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent);
- static Qt::MouseButton translateMouseButton(unsigned short button);
+ QFlags<Qt::KeyboardModifier> translatKeyModifier(const Event *event);
+ QFlags<Qt::KeyboardModifier> translateKeyboardEventModifier(const EmscriptenKeyboardEvent *keyEvent);
+ QFlags<Qt::KeyboardModifier> translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent);
+ Qt::MouseButton translateMouseButton(unsigned short button);
void processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent);
+ bool processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent);
+
+ Qt::Key translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey);
+
+ QHash<Qt::Key , Qt::Key> tildeKeyTable { // ~
+ { Qt::Key_A, Qt::Key_Atilde},
+ { Qt::Key_N, Qt::Key_Ntilde},
+ { Qt::Key_O, Qt::Key_Otilde}
+ };
+ QHash<Qt::Key , Qt::Key> graveKeyTable { // `
+ { Qt::Key_A, Qt::Key_Agrave},
+ { Qt::Key_E, Qt::Key_Egrave},
+ { Qt::Key_I, Qt::Key_Igrave},
+ { Qt::Key_O, Qt::Key_Ograve},
+ { Qt::Key_U, Qt::Key_Ugrave}
+ };
+ QHash<Qt::Key , Qt::Key> acuteKeyTable { // '
+ { Qt::Key_A, Qt::Key_Aacute},
+ { Qt::Key_E, Qt::Key_Eacute},
+ { Qt::Key_I, Qt::Key_Iacute},
+ { Qt::Key_O, Qt::Key_Oacute},
+ { Qt::Key_U, Qt::Key_Uacute},
+ { Qt::Key_Y, Qt::Key_Yacute}
+ };
+ QHash<Qt::Key , Qt::Key> diaeresisKeyTable { // umlaut ¨
+ { Qt::Key_A, Qt::Key_Adiaeresis},
+ { Qt::Key_E, Qt::Key_Ediaeresis},
+ { Qt::Key_I, Qt::Key_Idiaeresis},
+ { Qt::Key_O, Qt::Key_Odiaeresis},
+ { Qt::Key_U, Qt::Key_Udiaeresis},
+ { Qt::Key_Y, Qt::Key_ydiaeresis}
+ };
+ QHash<Qt::Key , Qt::Key> circumflexKeyTable { // ^
+ { Qt::Key_A, Qt::Key_Acircumflex},
+ { Qt::Key_E, Qt::Key_Ecircumflex},
+ { Qt::Key_I, Qt::Key_Icircumflex},
+ { Qt::Key_O, Qt::Key_Ocircumflex},
+ { Qt::Key_U, Qt::Key_Ucircumflex}
+ };
+
+ QMap <int, QPointF> pressedTouchIds;
private:
QWindow *draggedWindow;
@@ -205,6 +126,9 @@ private:
QRect resizeStartRect;
QTouchDevice *touchDevice;
quint64 getTimestamp();
+
+ Qt::Key m_emDeadKey = Qt::Key_unknown;
+ bool m_emStickyDeadKey = false;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmfontdatabase.cpp b/src/plugins/platforms/wasm/qwasmfontdatabase.cpp
index 0c72dfddc4..dc6bb5847e 100644
--- a/src/plugins/platforms/wasm/qwasmfontdatabase.cpp
+++ b/src/plugins/platforms/wasm/qwasmfontdatabase.cpp
@@ -38,9 +38,9 @@ void QWasmFontDatabase::populateFontDatabase()
// Load font file from resources. Currently
// all fonts needs to be bundled with the nexe
// as Qt resources.
- QStringList fontFileNames = QStringList() << QStringLiteral(":/fonts/Vera.ttf")
+ QStringList fontFileNames = QStringList() << QStringLiteral(":/fonts/DejaVuSansMono.ttf")
+ << QStringLiteral(":/fonts/Vera.ttf")
<< QStringLiteral(":/fonts/DejaVuSans.ttf");
-
foreach (const QString &fontFileName, fontFileNames) {
QFile theFont(fontFileName);
if (!theFont.open(QIODevice::ReadOnly))
@@ -82,5 +82,9 @@ void QWasmFontDatabase::releaseHandle(void *handle)
QFreeTypeFontDatabase::releaseHandle(handle);
}
+QFont QWasmFontDatabase::defaultFont() const
+{
+ return QFont(QLatin1String("Bitstream Vera Sans"));
+}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmfontdatabase.h b/src/plugins/platforms/wasm/qwasmfontdatabase.h
index 891f12859e..cbd187a022 100644
--- a/src/plugins/platforms/wasm/qwasmfontdatabase.h
+++ b/src/plugins/platforms/wasm/qwasmfontdatabase.h
@@ -44,6 +44,7 @@ public:
QChar::Script script) const override;
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) override;
void releaseHandle(void *handle) override;
+ QFont defaultFont() const override;
};
QT_END_NAMESPACE
#endif
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index 3829043d07..116612c286 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -33,6 +33,9 @@
#include "qwasmcompositor.h"
#include "qwasmopenglcontext.h"
#include "qwasmtheme.h"
+#include "qwasmclipboard.h"
+#include "qwasmservices.h"
+#include "qwasmoffscreensurface.h"
#include "qwasmwindow.h"
#ifndef QT_NO_OPENGL
@@ -46,8 +49,10 @@
#include <QtGui/qscreen.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/qcoreapplication.h>
+#include <qpa/qplatforminputcontextfactory_p.h>
#include <emscripten/bind.h>
+#include <emscripten/val.h>
// this is where EGL headers are pulled in, make sure it is last
#include "qwasmscreen.h"
@@ -55,47 +60,97 @@
using namespace emscripten;
QT_BEGIN_NAMESPACE
-void browserBeforeUnload()
+static void browserBeforeUnload(emscripten::val)
{
QWasmIntegration::QWasmBrowserExit();
}
-EMSCRIPTEN_BINDINGS(my_module)
+static void addCanvasElement(emscripten::val canvas)
{
- function("browserBeforeUnload", &browserBeforeUnload);
+ QString canvasId = QString::fromStdString(canvas["id"].as<std::string>());
+ QWasmIntegration::get()->addScreen(canvasId);
}
-static QWasmIntegration *globalHtml5Integration;
-QWasmIntegration *QWasmIntegration::get() { return globalHtml5Integration; }
+static void removeCanvasElement(emscripten::val canvas)
+{
+ QString canvasId = QString::fromStdString(canvas["id"].as<std::string>());
+ QWasmIntegration::get()->removeScreen(canvasId);
+}
+
+static void resizeCanvasElement(emscripten::val canvas)
+{
+ QString canvasId = QString::fromStdString(canvas["id"].as<std::string>());
+ QWasmIntegration::get()->resizeScreen(canvasId);
+}
+
+static void qtUpdateDpi()
+{
+ QWasmIntegration::get()->updateDpi();
+}
+
+EMSCRIPTEN_BINDINGS(qtQWasmIntegraton)
+{
+ function("qtBrowserBeforeUnload", &browserBeforeUnload);
+ function("qtAddCanvasElement", &addCanvasElement);
+ function("qtRemoveCanvasElement", &removeCanvasElement);
+ function("qtResizeCanvasElement", &resizeCanvasElement);
+ function("qtUpdateDpi", &qtUpdateDpi);
+}
+
+QWasmIntegration *QWasmIntegration::s_instance;
QWasmIntegration::QWasmIntegration()
: m_fontDb(nullptr),
- m_compositor(new QWasmCompositor),
- m_screen(new QWasmScreen(m_compositor)),
- m_eventDispatcher(nullptr)
+ m_desktopServices(nullptr),
+ m_clipboard(new QWasmClipboard)
{
+ s_instance = this;
+
+ // We expect that qtloader.js has populated Module.qtCanvasElements with one or more canvases.
+ // Also check Module.canvas, which may be set if the emscripen or a custom loader is used.
+ emscripten::val qtCanvaseElements = val::module_property("qtCanvasElements");
+ emscripten::val canvas = val::module_property("canvas");
+
+ if (!qtCanvaseElements.isUndefined()) {
+ int screenCount = qtCanvaseElements["length"].as<int>();
+ for (int i = 0; i < screenCount; ++i) {
+ emscripten::val canvas = qtCanvaseElements[i].as<emscripten::val>();
+ QString canvasId = QString::fromStdString(canvas["id"].as<std::string>());
+ addScreen(canvasId);
+ }
+ } else if (!canvas.isUndefined()){
+ QString canvasId = QString::fromStdString(canvas["id"].as<std::string>());
+ addScreen(canvasId);
+ }
- globalHtml5Integration = this;
-
- updateQScreenAndCanvasRenderSize();
- QWindowSystemInterface::handleScreenAdded(m_screen);
- emscripten_set_resize_callback(0, (void *)this, 1, uiEvent_cb);
+ emscripten::val::global("window").set("onbeforeunload", val::module_property("qtBrowserBeforeUnload"));
- m_eventTranslator = new QWasmEventTranslator;
+ // install browser window resize handler
+ auto onWindowResize = [](int eventType, const EmscriptenUiEvent *e, void *userData) -> int {
+ Q_UNUSED(eventType);
+ Q_UNUSED(e);
+ Q_UNUSED(userData);
- EM_ASM(// exit app if browser closes
- window.onbeforeunload = function () {
- Module.browserBeforeUnload();
- };
- );
+ // This resize event is called when the HTML window is resized. Depending
+ // on the page layout the the canvas(es) might also have been resized, so we
+ // update the Qt screen sizes (and canvas render sizes).
+ if (QWasmIntegration *integration = QWasmIntegration::get())
+ integration->resizeAllScreens();
+ return 0;
+ };
+ emscripten_set_resize_callback(nullptr, nullptr, 1, onWindowResize);
}
QWasmIntegration::~QWasmIntegration()
{
- delete m_compositor;
- QWindowSystemInterface::handleScreenRemoved(m_screen);
delete m_fontDb;
- delete m_eventTranslator;
+ delete m_desktopServices;
+
+ for (auto it = m_screens.constBegin(); it != m_screens.constEnd(); ++it)
+ QWindowSystemInterface::handleScreenRemoved(*it);
+ m_screens.clear();
+
+ s_instance = nullptr;
}
void QWasmIntegration::QWasmBrowserExit()
@@ -109,7 +164,7 @@ bool QWasmIntegration::hasCapability(QPlatformIntegration::Capability cap) const
switch (cap) {
case ThreadedPixmaps: return true;
case OpenGL: return true;
- case ThreadedOpenGL: return true;
+ case ThreadedOpenGL: return false;
case RasterGLSurface: return false; // to enable this you need to fix qopenglwidget and quickwidget for wasm
case MultipleWindows: return true;
case WindowManagement: return true;
@@ -119,13 +174,15 @@ bool QWasmIntegration::hasCapability(QPlatformIntegration::Capability cap) const
QPlatformWindow *QWasmIntegration::createPlatformWindow(QWindow *window) const
{
- return new QWasmWindow(window, m_compositor, m_backingStores.value(window));
+ QWasmCompositor *compositor = QWasmScreen::get(window->screen())->compositor();
+ return new QWasmWindow(window, compositor, m_backingStores.value(window));
}
QPlatformBackingStore *QWasmIntegration::createPlatformBackingStore(QWindow *window) const
{
#ifndef QT_NO_OPENGL
- QWasmBackingStore *backingStore = new QWasmBackingStore(m_compositor, window);
+ QWasmCompositor *compositor = QWasmScreen::get(window->screen())->compositor();
+ QWasmBackingStore *backingStore = new QWasmBackingStore(compositor, window);
m_backingStores.insert(window, backingStore);
return backingStore;
#else
@@ -140,6 +197,23 @@ QPlatformOpenGLContext *QWasmIntegration::createPlatformOpenGLContext(QOpenGLCon
}
#endif
+void QWasmIntegration::initialize()
+{
+ QString icStr = QPlatformInputContextFactory::requested();
+ if (!icStr.isNull())
+ m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
+}
+
+QPlatformInputContext *QWasmIntegration::inputContext() const
+{
+ return m_inputContext.data();
+}
+
+QPlatformOffscreenSurface *QWasmIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
+{
+ return new QWasmOffscrenSurface(surface);
+}
+
QPlatformFontDatabase *QWasmIntegration::fontDatabase() const
{
if (m_fontDb == nullptr)
@@ -155,9 +229,21 @@ QAbstractEventDispatcher *QWasmIntegration::createEventDispatcher() const
QVariant QWasmIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
{
+ if (hint == ShowIsFullScreen)
+ return true;
+
return QPlatformIntegration::styleHint(hint);
}
+Qt::WindowState QWasmIntegration::defaultWindowState(Qt::WindowFlags flags) const
+{
+ // Don't maximize dialogs
+ if (flags & Qt::Dialog & ~Qt::Window)
+ return Qt::WindowNoState;
+
+ return QPlatformIntegration::defaultWindowState(flags);
+}
+
QStringList QWasmIntegration::themeNames() const
{
return QStringList() << QLatin1String("webassembly");
@@ -170,50 +256,53 @@ QPlatformTheme *QWasmIntegration::createPlatformTheme(const QString &name) const
return QPlatformIntegration::createPlatformTheme(name);
}
-int QWasmIntegration::uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData)
+QPlatformServices *QWasmIntegration::services() const
{
- Q_UNUSED(e)
- Q_UNUSED(userData)
-
- if (eventType == EMSCRIPTEN_EVENT_RESIZE) {
- // This resize event is called when the HTML window is resized. Depending
- // on the page layout the the canvas might also have been resized, so we
- // update the Qt screen size (and canvas render size).
- updateQScreenAndCanvasRenderSize();
- }
+ if (m_desktopServices == nullptr)
+ m_desktopServices = new QWasmServices();
+ return m_desktopServices;
+}
- return 0;
+QPlatformClipboard* QWasmIntegration::clipboard() const
+{
+ return m_clipboard;
}
-static void set_canvas_size(double width, double height)
+void QWasmIntegration::addScreen(const QString &canvasId)
{
- EM_ASM_({
- var canvas = Module.canvas;
- canvas.width = $0;
- canvas.height = $1;
- }, width, height);
+ QWasmScreen *screen = new QWasmScreen(canvasId);
+ m_clipboard->installEventHandlers(canvasId);
+ m_screens.insert(canvasId, screen);
+ QWindowSystemInterface::handleScreenAdded(screen);
}
-void QWasmIntegration::updateQScreenAndCanvasRenderSize()
+void QWasmIntegration::removeScreen(const QString &canvasId)
{
- // The HTML canvas has two sizes: the CSS size and the canvas render size.
- // The CSS size is determined according to standard CSS rules, while the
- // render size is set using the "width" and "height" attributes. The render
- // size must be set manually and is not auto-updated on CSS size change.
- // Setting the render size to a value larger than the CSS size enables high-dpi
- // rendering.
+ QWasmScreen *exScreen = m_screens.take(canvasId);
+ exScreen->destroy(); // clean up before deleting the screen
+ QWindowSystemInterface::handleScreenRemoved(exScreen);
+}
- double css_width;
- double css_height;
- emscripten_get_element_css_size(0, &css_width, &css_height);
- QSizeF cssSize(css_width, css_height);
+void QWasmIntegration::resizeScreen(const QString &canvasId)
+{
+ m_screens.value(canvasId)->updateQScreenAndCanvasRenderSize();
+}
- QWasmScreen *screen = QWasmIntegration::get()->m_screen;
- QSizeF canvasSize = cssSize * screen->devicePixelRatio();
+void QWasmIntegration::updateDpi()
+{
+ emscripten::val dpi = emscripten::val::module_property("qtFontDpi");
+ if (dpi.isUndefined())
+ return;
+ qreal dpiValue = dpi.as<qreal>();
+ for (QWasmScreen *screen : m_screens)
+ QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen->screen(), dpiValue, dpiValue);
+}
- set_canvas_size(canvasSize.width(), canvasSize.height());
- screen->setGeometry(QRect(QPoint(0, 0), cssSize.toSize()));
- QWasmIntegration::get()->m_compositor->redrawWindowContent();
+void QWasmIntegration::resizeAllScreens()
+{
+ qDebug() << "resizeAllScreens";
+ for (QWasmScreen *screen : m_screens)
+ screen->updateQScreenAndCanvasRenderSize();
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h
index ebc3d9d431..2102f5c226 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.h
+++ b/src/plugins/platforms/wasm/qwasmintegration.h
@@ -34,6 +34,7 @@
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformscreen.h>
+#include <qpa/qplatforminputcontext.h>
#include <QtCore/qhash.h>
@@ -49,6 +50,8 @@ class QWasmEventDispatcher;
class QWasmScreen;
class QWasmCompositor;
class QWasmBackingStore;
+class QWasmClipboard;
+class QWasmServices;
class QWasmIntegration : public QObject, public QPlatformIntegration
{
@@ -63,28 +66,39 @@ public:
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
#endif
+ QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
QPlatformFontDatabase *fontDatabase() const override;
QAbstractEventDispatcher *createEventDispatcher() const override;
QVariant styleHint(QPlatformIntegration::StyleHint hint) const override;
+ Qt::WindowState defaultWindowState(Qt::WindowFlags flags) const override;
QStringList themeNames() const override;
QPlatformTheme *createPlatformTheme(const QString &name) const override;
+ QPlatformServices *services() const override;
+ QPlatformClipboard *clipboard() const override;
+ void initialize() override;
+ QPlatformInputContext *inputContext() const override;
- static QWasmIntegration *get();
- QWasmScreen *screen() { return m_screen; }
- QWasmCompositor *compositor() { return m_compositor; }
- QWasmEventTranslator *eventTranslator() { return m_eventTranslator; }
+ QWasmClipboard *getWasmClipboard() { return m_clipboard; }
+ static QWasmIntegration *get() { return s_instance; }
static void QWasmBrowserExit();
- static void updateQScreenAndCanvasRenderSize();
+
+ void addScreen(const QString &canvasId);
+ void removeScreen(const QString &canvasId);
+ void resizeScreen(const QString &canvasId);
+ void resizeAllScreens();
+ void updateDpi();
private:
mutable QWasmFontDatabase *m_fontDb;
- QWasmCompositor *m_compositor;
- mutable QWasmScreen *m_screen;
- mutable QWasmEventTranslator *m_eventTranslator;
- mutable QWasmEventDispatcher *m_eventDispatcher;
- static int uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData);
+ mutable QWasmServices *m_desktopServices;
mutable QHash<QWindow *, QWasmBackingStore *> m_backingStores;
+
+ QHash<QString, QWasmScreen *> m_screens;
+ mutable QWasmClipboard *m_clipboard;
+ qreal m_fontDpi = -1;
+ mutable QScopedPointer<QPlatformInputContext> m_inputContext;
+ static QWasmIntegration *s_instance;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp b/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp
new file mode 100644
index 0000000000..a205e5ddea
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmoffscreensurface.h"
+
+QWasmOffscrenSurface::QWasmOffscrenSurface(QOffscreenSurface *offscreenSurface)
+ :QPlatformOffscreenSurface(offscreenSurface)
+{
+
+}
+
+QWasmOffscrenSurface::~QWasmOffscrenSurface()
+{
+
+}
diff --git a/src/plugins/platforms/wasm/qwasmoffscreensurface.h b/src/plugins/platforms/wasm/qwasmoffscreensurface.h
new file mode 100644
index 0000000000..9d3e805be0
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmoffscreensurface.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMOFFSCREENSURFACE_H
+#define QWASMOFFSCREENSURFACE_H
+
+#include <qpa/qplatformoffscreensurface.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOffscreenSurface;
+class QWasmOffscrenSurface : public QPlatformOffscreenSurface
+{
+public:
+ explicit QWasmOffscrenSurface(QOffscreenSurface *offscreenSurface);
+ ~QWasmOffscrenSurface();
+private:
+
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
index 73af3d1878..62087f54bd 100644
--- a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
+++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
@@ -28,7 +28,7 @@
****************************************************************************/
#include "qwasmopenglcontext.h"
-
+#include "qwasmintegration.h"
#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
@@ -37,47 +37,46 @@ QWasmOpenGLContext::QWasmOpenGLContext(const QSurfaceFormat &format)
: m_requestedFormat(format)
{
m_requestedFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+
+ // if we set one, we need to set the other as well since in webgl, these are tied together
+ if (format.depthBufferSize() < 0 && format.stencilBufferSize() > 0)
+ m_requestedFormat.setDepthBufferSize(16);
+
+ if (format.stencilBufferSize() < 0 && format.depthBufferSize() > 0)
+ m_requestedFormat.setStencilBufferSize(8);
+
}
QWasmOpenGLContext::~QWasmOpenGLContext()
{
- if (m_context)
+ if (m_context) {
emscripten_webgl_destroy_context(m_context);
+ m_context = 0;
+ }
}
-void QWasmOpenGLContext::maybeRecreateEmscriptenContext(QPlatformSurface *surface)
+bool QWasmOpenGLContext::maybeCreateEmscriptenContext(QPlatformSurface *surface)
{
- // Native emscripten contexts are tied to a single surface. Recreate
- // the context if the surface is changed.
- if (surface != m_surface) {
- m_surface = surface;
-
- // Destroy existing context
- if (m_context)
- emscripten_webgl_destroy_context(m_context);
-
- // Create new context
- const char *canvasId = 0; // (use default canvas) FIXME: get the actual canvas from the surface.
- m_context = createEmscriptenContext(canvasId, m_requestedFormat);
-
- // Register context-lost callback.
- auto callback = [](int eventType, const void *reserved, void *userData) -> EM_BOOL
- {
- Q_UNUSED(eventType);
- Q_UNUSED(reserved);
- // The application may get contex-lost if e.g. moved to the background. Set
- // m_contextLost which will make isValid() return false. Application code will
- // then detect this and recrate the the context, resulting in a new QWasmOpenGLContext
- // instance.
- reinterpret_cast<QWasmOpenGLContext *>(userData)->m_contextLost = true;
- return true;
- };
- bool capture = true;
- emscripten_set_webglcontextlost_callback(canvasId, this, capture, callback);
- }
+ // Native emscripten/WebGL contexts are tied to a single screen/canvas. The first
+ // call to this function creates a native canvas for the given screen, subsequent
+ // calls verify that the surface is on/off the same screen.
+ QPlatformScreen *screen = surface->screen();
+ if (m_context && !screen)
+ return false; // Alternative: return true to support makeCurrent on QOffScreenSurface with
+ // no screen. However, Qt likes to substitute QGuiApplication::primaryScreen()
+ // for null screens, which foils this plan.
+ if (!screen)
+ return false;
+ if (m_context)
+ return m_screen == screen;
+
+ QString canvasId = QWasmScreen::get(screen)->canvasId();
+ m_context = createEmscriptenContext(canvasId, m_requestedFormat);
+ m_screen = screen;
+ return true;
}
-EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(const char *canvasId, QSurfaceFormat format)
+EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(const QString &canvasId, QSurfaceFormat format)
{
EmscriptenWebGLContextAttributes attributes;
emscripten_webgl_init_context_attributes(&attributes); // Populate with default attributes
@@ -91,12 +90,16 @@ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(cons
attributes.majorVersion = 2;
}
+ // WebGL doesn't allow separate attach buffers to STENCIL_ATTACHMENT and DEPTH_ATTACHMENT
+ // we need both or none
+ bool useDepthStencil = (format.depthBufferSize() > 0 || format.stencilBufferSize() > 0);
+
// WebGL offers enable/disable control but not size control for these
attributes.alpha = format.alphaBufferSize() > 0;
- attributes.depth = format.depthBufferSize() > 0;
- attributes.stencil = format.stencilBufferSize() > 0;
+ attributes.depth = useDepthStencil;
+ attributes.stencil = useDepthStencil;
- EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(canvasId, &attributes);
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(canvasId.toLocal8Bit().constData(), &attributes);
return context;
}
@@ -113,7 +116,9 @@ GLuint QWasmOpenGLContext::defaultFramebufferObject(QPlatformSurface *surface) c
bool QWasmOpenGLContext::makeCurrent(QPlatformSurface *surface)
{
- maybeRecreateEmscriptenContext(surface);
+ bool ok = maybeCreateEmscriptenContext(surface);
+ if (!ok)
+ return false;
return emscripten_webgl_make_context_current(m_context) == EMSCRIPTEN_RESULT_SUCCESS;
}
@@ -136,7 +141,9 @@ bool QWasmOpenGLContext::isSharing() const
bool QWasmOpenGLContext::isValid() const
{
- return (m_contextLost == false);
+ // Note: we get isValid() calls before we see the surface and can
+ // create a native context, so no context is also a valid state.
+ return !m_context || !emscripten_is_webgl_context_lost(m_context);
}
QFunctionPointer QWasmOpenGLContext::getProcAddress(const char *procName)
diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.h b/src/plugins/platforms/wasm/qwasmopenglcontext.h
index 9123100479..d27007e8ea 100644
--- a/src/plugins/platforms/wasm/qwasmopenglcontext.h
+++ b/src/plugins/platforms/wasm/qwasmopenglcontext.h
@@ -34,6 +34,7 @@
QT_BEGIN_NAMESPACE
+class QPlatformScreen;
class QWasmOpenGLContext : public QPlatformOpenGLContext
{
public:
@@ -50,12 +51,11 @@ public:
QFunctionPointer getProcAddress(const char *procName) override;
private:
- void maybeRecreateEmscriptenContext(QPlatformSurface *surface);
- static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const char *canvasId, QSurfaceFormat format);
+ bool maybeCreateEmscriptenContext(QPlatformSurface *surface);
+ static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const QString &canvasId, QSurfaceFormat format);
- bool m_contextLost = false;
QSurfaceFormat m_requestedFormat;
- QPlatformSurface *m_surface = nullptr;
+ QPlatformScreen *m_screen = nullptr;
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE m_context = 0;
};
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
index 93e9906ffc..f2eabfa486 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.cpp
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -29,7 +29,11 @@
#include "qwasmscreen.h"
#include "qwasmwindow.h"
+#include "qwasmeventtranslator.h"
#include "qwasmcompositor.h"
+#include "qwasmintegration.h"
+#include <emscripten/bind.h>
+#include <emscripten/val.h>
#include <QtEglSupport/private/qeglconvenience_p.h>
#ifndef QT_NO_OPENGL
@@ -43,17 +47,48 @@
QT_BEGIN_NAMESPACE
-QWasmScreen::QWasmScreen(QWasmCompositor *compositor)
- : m_compositor(compositor)
- , m_depth(32)
- , m_format(QImage::Format_RGB32)
+QWasmScreen::QWasmScreen(const QString &canvasId)
+ : m_canvasId(canvasId)
+
{
- m_compositor->setScreen(this);
+ m_compositor = new QWasmCompositor(this);
+ m_eventTranslator = new QWasmEventTranslator(this);
+ updateQScreenAndCanvasRenderSize();
}
QWasmScreen::~QWasmScreen()
{
+ destroy();
+}
+
+void QWasmScreen::destroy()
+{
+ m_compositor->destroy();
+}
+
+QWasmScreen *QWasmScreen::get(QPlatformScreen *screen)
+{
+ return static_cast<QWasmScreen *>(screen);
+}
+QWasmScreen *QWasmScreen::get(QScreen *screen)
+{
+ return get(screen->handle());
+}
+
+QWasmCompositor *QWasmScreen::compositor()
+{
+ return m_compositor;
+}
+
+QWasmEventTranslator *QWasmScreen::eventTranslator()
+{
+ return m_eventTranslator;
+}
+
+QString QWasmScreen::canvasId() const
+{
+ return m_canvasId;
}
QRect QWasmScreen::geometry() const
@@ -71,18 +106,32 @@ QImage::Format QWasmScreen::format() const
return m_format;
}
+QDpi QWasmScreen::logicalDpi() const
+{
+ emscripten::val dpi = emscripten::val::module_property("qtFontDpi");
+ if (!dpi.isUndefined()) {
+ qreal dpiValue = dpi.as<qreal>();
+ return QDpi(dpiValue, dpiValue);
+ }
+ const qreal defaultDpi = 96;
+ return QDpi(defaultDpi, defaultDpi);
+}
+
qreal QWasmScreen::devicePixelRatio() const
{
// FIXME: The effective device pixel ratio may be different from the
// HTML window dpr if the OpenGL driver/GPU allocates a less than
// full resolution surface. Use emscripten_webgl_get_drawing_buffer_size()
// and compute the dpr instead.
- double htmlWindowDpr = EM_ASM_DOUBLE({
- return window.devicePixelRatio;
- });
+ double htmlWindowDpr = emscripten::val::global("window")["devicePixelRatio"].as<double>();
return qreal(htmlWindowDpr);
}
+QString QWasmScreen::name() const
+{
+ return m_canvasId;
+}
+
QPlatformCursor *QWasmScreen::cursor() const
{
return const_cast<QWasmCursor *>(&m_cursor);
@@ -115,4 +164,31 @@ void QWasmScreen::setGeometry(const QRect &rect)
resizeMaximizedWindows();
}
+void QWasmScreen::updateQScreenAndCanvasRenderSize()
+{
+ // The HTML canvas has two sizes: the CSS size and the canvas render size.
+ // The CSS size is determined according to standard CSS rules, while the
+ // render size is set using the "width" and "height" attributes. The render
+ // size must be set manually and is not auto-updated on CSS size change.
+ // Setting the render size to a value larger than the CSS size enables high-dpi
+ // rendering.
+
+ QByteArray canvasId = m_canvasId.toUtf8();
+ double css_width;
+ double css_height;
+ emscripten_get_element_css_size(canvasId.constData(), &css_width, &css_height);
+ QSizeF cssSize(css_width, css_height);
+
+ QSizeF canvasSize = cssSize * devicePixelRatio();
+ emscripten::val canvas = emscripten::val::global(canvasId.constData());
+ canvas.set("width", canvasSize.width());
+ canvas.set("height", canvasSize.height());
+
+ emscripten::val rect = canvas.call<emscripten::val>("getBoundingClientRect");
+ QPoint position(rect["left"].as<int>(), rect["top"].as<int>());
+
+ setGeometry(QRect(position, cssSize.toSize()));
+ m_compositor->redrawWindowContent();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h
index 3891db77bb..fcf693681c 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.h
+++ b/src/plugins/platforms/wasm/qwasmscreen.h
@@ -43,20 +43,30 @@ class QPlatformOpenGLContext;
class QWasmWindow;
class QWasmBackingStore;
class QWasmCompositor;
+class QWasmEventTranslator;
class QOpenGLContext;
class QWasmScreen : public QObject, public QPlatformScreen
{
Q_OBJECT
public:
-
- QWasmScreen(QWasmCompositor *compositor);
+ QWasmScreen(const QString &canvasId);
~QWasmScreen();
+ void destroy();
+
+ static QWasmScreen *get(QPlatformScreen *screen);
+ static QWasmScreen *get(QScreen *screen);
+ QString canvasId() const;
+
+ QWasmCompositor *compositor();
+ QWasmEventTranslator *eventTranslator();
QRect geometry() const override;
int depth() const override;
QImage::Format format() const override;
+ QDpi logicalDpi() const override;
qreal devicePixelRatio() const override;
+ QString name() const override;
QPlatformCursor *cursor() const override;
void resizeMaximizedWindows();
@@ -64,17 +74,18 @@ public:
QWindow *topLevelAt(const QPoint &p) const override;
void invalidateSize();
+ void updateQScreenAndCanvasRenderSize();
public slots:
void setGeometry(const QRect &rect);
-protected:
private:
- QWasmCompositor *m_compositor;
-
+ QString m_canvasId;
+ QWasmCompositor *m_compositor = nullptr;
+ QWasmEventTranslator *m_eventTranslator = nullptr;
QRect m_geometry = QRect(0, 0, 100, 100);
- int m_depth;
- QImage::Format m_format;
+ int m_depth = 32;
+ QImage::Format m_format = QImage::Format_RGB32;
QWasmCursor m_cursor;
};
diff --git a/src/plugins/platforms/wasm/qwasmservices.cpp b/src/plugins/platforms/wasm/qwasmservices.cpp
new file mode 100644
index 0000000000..9328b8c065
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmservices.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmservices.h"
+#include <QtCore/QUrl>
+#include <QtCore/QDebug>
+
+#include <emscripten/val.h>
+
+QT_BEGIN_NAMESPACE
+
+bool QWasmServices::openUrl(const QUrl &url)
+{
+ QByteArray utf8Url = url.toString().toUtf8();
+ emscripten::val::global("window").call<void>("open", emscripten::val(utf8Url.constData()), emscripten::val("_blank"));
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmservices.h b/src/plugins/platforms/wasm/qwasmservices.h
new file mode 100644
index 0000000000..3b37f21f82
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmservices.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMDESKTOPSERVICES_H
+#define QWASMDESKTOPSERVICES_H
+
+#include <qpa/qplatformservices.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWasmServices : public QPlatformServices
+{
+public:
+ bool openUrl(const QUrl &url) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWASMDESKTOPSERVICES_H
diff --git a/src/plugins/platforms/wasm/qwasmtheme.cpp b/src/plugins/platforms/wasm/qwasmtheme.cpp
index a7f2db3bd3..978d60d686 100644
--- a/src/plugins/platforms/wasm/qwasmtheme.cpp
+++ b/src/plugins/platforms/wasm/qwasmtheme.cpp
@@ -29,15 +29,22 @@
#include "qwasmtheme.h"
#include <QtCore/qvariant.h>
+#include <QFontDatabase>
QT_BEGIN_NAMESPACE
QWasmTheme::QWasmTheme()
{
+ QFontDatabase fdb;
+ for (auto family : fdb.families())
+ if (fdb.isFixedPitch(family))
+ fixedFont = new QFont(family);
}
QWasmTheme::~QWasmTheme()
{
+ if (fixedFont)
+ delete fixedFont;
}
QVariant QWasmTheme::themeHint(ThemeHint hint) const
@@ -47,4 +54,12 @@ QVariant QWasmTheme::themeHint(ThemeHint hint) const
return QPlatformTheme::themeHint(hint);
}
+const QFont *QWasmTheme::font(Font type) const
+{
+ if (type == QPlatformTheme::FixedFont) {
+ return fixedFont;
+ }
+ return nullptr;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmtheme.h b/src/plugins/platforms/wasm/qwasmtheme.h
index e4cc06e049..7123a1f3d4 100644
--- a/src/plugins/platforms/wasm/qwasmtheme.h
+++ b/src/plugins/platforms/wasm/qwasmtheme.h
@@ -31,6 +31,7 @@
#define QWASMTHEME_H
#include <qpa/qplatformtheme.h>
+#include <QtGui/QFont>
QT_BEGIN_NAMESPACE
@@ -49,6 +50,8 @@ public:
~QWasmTheme();
QVariant themeHint(ThemeHint hint) const override;
+ const QFont *font(Font type) const override;
+ QFont *fixedFont = nullptr;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index 25a0190053..594db65cfd 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -65,6 +65,12 @@ QWasmWindow::~QWasmWindow()
m_compositor->removeWindow(this);
}
+void QWasmWindow::destroy()
+{
+ if (m_backingStore)
+ m_backingStore->destroy();
+}
+
void QWasmWindow::initialize()
{
QRect rect = windowGeometry();
@@ -198,8 +204,10 @@ void QWasmWindow::injectMouseReleased(const QPoint &local, const QPoint &global,
if (!hasTitleBar() || button != Qt::LeftButton)
return;
- if (closeButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarCloseButton)
+ if (closeButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarCloseButton) {
window()->close();
+ return;
+ }
if (maxButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarMaxButton) {
window()->setWindowState(Qt::WindowMaximized);
diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h
index cbbce99aeb..a098172649 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.h
+++ b/src/plugins/platforms/wasm/qwasmwindow.h
@@ -58,6 +58,7 @@ public:
QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore);
~QWasmWindow();
+ void destroy();
void initialize() override;
diff --git a/src/plugins/platforms/wasm/wasm.pro b/src/plugins/platforms/wasm/wasm.pro
index eaaba53aa2..c28df8f893 100644
--- a/src/plugins/platforms/wasm/wasm.pro
+++ b/src/plugins/platforms/wasm/wasm.pro
@@ -18,7 +18,10 @@ SOURCES = \
qwasmcompositor.cpp \
qwasmcursor.cpp \
qwasmopenglcontext.cpp \
- qwasmtheme.cpp
+ qwasmtheme.cpp \
+ qwasmclipboard.cpp \
+ qwasmservices.cpp \
+ qwasmoffscreensurface.cpp
HEADERS = \
qwasmintegration.h \
@@ -31,11 +34,15 @@ HEADERS = \
qwasmstylepixmaps_p.h \
qwasmcursor.h \
qwasmopenglcontext.h \
- qwasmtheme.h
+ qwasmtheme.h \
+ qwasmclipboard.h \
+ qwasmservices.h \
+ qwasmoffscreensurface.h
wasmfonts.files = \
../../../3rdparty/wasm/Vera.ttf \
- ../../../3rdparty/wasm/DejaVuSans.ttf
+ ../../../3rdparty/wasm/DejaVuSans.ttf \
+ ../../../3rdparty/wasm/DejaVuSansMono.ttf
wasmfonts.prefix = /fonts
wasmfonts.base = ../../../3rdparty/wasm
RESOURCES += wasmfonts
diff --git a/src/plugins/platforms/wasm/wasm_shell.html b/src/plugins/platforms/wasm/wasm_shell.html
index 67bfcdfbdc..a118c217f3 100644
--- a/src/plugins/platforms/wasm/wasm_shell.html
+++ b/src/plugins/platforms/wasm/wasm_shell.html
@@ -3,31 +3,36 @@
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <title>APPNAME</title>
+ <title>@APPNAME@</title>
<style>
html, body { padding: 0; margin : 0; overflow:hidden; height: 100% }
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
- canvas { border: 0px none; background-color: white; height:100%; width:100%; }
+ canvas { border: 0px none; background-color: white; height:100%; width:100%; }
+ /* The contenteditable property is set to true for the canvas in order to support
+ clipboard events. Hide the resulting focus frame and set the cursor back to
+ the default cursor. */
+ canvas { outline: 0px solid transparent; caret-color: transparent; cursor:default }
</style>
</head>
<body onload="init()">
- <figure style="overflow:visible;" id="spinner">
+ <figure style="overflow:visible;" id="qtspinner">
<center style="margin-top:1.5em; line-height:150%">
<img src="qtlogo.svg"; width=320; height=200; style="display:block"> </img>
- <strong>Qt for WebAssembly: APPNAME</strong>
- <div id="status"></div>
+ <strong>Qt for WebAssembly: @APPNAME@</strong>
+ <div id="qtstatus"></div>
<noscript>JavaScript is disabled. Please enable JavaScript to use this application.</noscript>
</center>
</figure>
- <canvas id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ <canvas id="qtcanvas" oncontextmenu="event.preventDefault()" contenteditable="true"></canvas>
<script type='text/javascript'>
function init() {
- var spinner = document.getElementById('spinner');
- var canvas = document.getElementById('canvas');
- var status = document.getElementById('status')
+ var spinner = document.querySelector('#qtspinner');
+ var canvas = document.querySelector('#qtcanvas');
+ var status = document.querySelector('#qtstatus')
var qtLoader = QtLoader({
+ canvasElements : [canvas],
showLoader: function(loaderStatus) {
spinner.style.display = 'block';
canvas.style.display = 'none';
@@ -50,10 +55,9 @@
showCanvas: function() {
spinner.style.display = 'none';
canvas.style.display = 'block';
- return canvas;
},
});
- qtLoader.loadEmscriptenModule("APPNAME");
+ qtLoader.loadEmscriptenModule("@APPNAME@");
}
</script>
<script type="text/javascript" src="qtloader.js"></script>
diff --git a/src/plugins/platforms/windows/qwin10helpers.cpp b/src/plugins/platforms/windows/qwin10helpers.cpp
index cc17d8798f..9a7fce9cd5 100644
--- a/src/plugins/platforms/windows/qwin10helpers.cpp
+++ b/src/plugins/platforms/windows/qwin10helpers.cpp
@@ -137,7 +137,7 @@ bool qt_windowsIsTabletMode(HWND hwnd)
const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
HSTRING_HEADER uiViewSettingsIdRefHeader;
HSTRING uiViewSettingsIdHs = nullptr;
- const UINT32 uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
+ const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
if (FAILED(baseComDll.windowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
return false;
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index 68807fabdd..bd7bdc55d1 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -158,7 +158,7 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion &region)
format = qt_maybeAlphaVersionWithSameDepth(format);
QWindowsNativeImage *oldwni = m_image.data();
- QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format);
+ auto *newwni = new QWindowsNativeImage(size.width(), size.height(), format);
if (oldwni && !region.isEmpty()) {
const QImage &oldimg(oldwni->image());
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h
index 088ab3b257..b96c8f0e61 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.h
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.h
@@ -52,7 +52,7 @@ class QWindowsNativeImage;
class QWindowsBackingStore : public QPlatformBackingStore
{
- Q_DISABLE_COPY(QWindowsBackingStore)
+ Q_DISABLE_COPY_MOVE(QWindowsBackingStore)
public:
QWindowsBackingStore(QWindow *window);
~QWindowsBackingStore() override;
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.h b/src/plugins/platforms/windows/qwindowsclipboard.h
index 469d638b89..24a6bc908d 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.h
+++ b/src/plugins/platforms/windows/qwindowsclipboard.h
@@ -58,7 +58,7 @@ protected:
class QWindowsClipboard : public QPlatformClipboard
{
- Q_DISABLE_COPY(QWindowsClipboard)
+ Q_DISABLE_COPY_MOVE(QWindowsClipboard)
public:
QWindowsClipboard();
~QWindowsClipboard() override;
@@ -87,8 +87,8 @@ private:
QWindowsClipboardRetrievalMimeData m_retrievalData;
QWindowsOleDataObject *m_data = nullptr;
- HWND m_clipboardViewer = 0;
- HWND m_nextClipboardViewer = 0;
+ HWND m_clipboardViewer = nullptr;
+ HWND m_nextClipboardViewer = nullptr;
bool m_formatListenerRegistered = false;
};
diff --git a/src/plugins/platforms/windows/qwindowscombase.h b/src/plugins/platforms/windows/qwindowscombase.h
index 6b25d665dc..45cba9c68b 100644
--- a/src/plugins/platforms/windows/qwindowscombase.h
+++ b/src/plugins/platforms/windows/qwindowscombase.h
@@ -80,7 +80,7 @@ bool qWindowsComQueryUnknownInterfaceMulti(Derived *d, REFIID id, LPVOID *iface)
// Helper base class to provide IUnknown methods for COM classes (single inheritance)
template <class ComInterface> class QWindowsComBase : public ComInterface
{
- Q_DISABLE_COPY(QWindowsComBase)
+ Q_DISABLE_COPY_MOVE(QWindowsComBase)
public:
explicit QWindowsComBase(ULONG initialRefCount = 1) : m_ref(initialRefCount) {}
virtual ~QWindowsComBase() = default;
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 38b9823d6b..bb349f08a7 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -134,8 +134,8 @@ static inline bool useRTL_Extensions()
#if QT_CONFIG(sessionmanager)
static inline QWindowsSessionManager *platformSessionManager()
{
- QGuiApplicationPrivate *guiPrivate = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
- QSessionManagerPrivate *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(guiPrivate->session_manager));
+ auto *guiPrivate = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
+ auto *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(guiPrivate->session_manager));
return static_cast<QWindowsSessionManager *>(managerPrivate->platformSessionManager);
}
@@ -548,7 +548,7 @@ QString QWindowsContext::registerWindowClass(QString cname,
// add a UUID.
static int classExists = -1;
- const HINSTANCE appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
+ const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
if (classExists == -1) {
WNDCLASS wcinfo;
classExists = GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(cname.utf16()), &wcinfo);
@@ -594,14 +594,14 @@ QString QWindowsContext::registerWindowClass(QString cname,
d->m_registeredWindowClassNames.insert(cname);
qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << ' ' << cname
- << " style=0x" << hex << style << dec
+ << " style=0x" << Qt::hex << style << Qt::dec
<< " brush=" << brush << " icon=" << icon << " atom=" << atom;
return cname;
}
void QWindowsContext::unregisterWindowClasses()
{
- const HINSTANCE appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
+ const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
for (const QString &name : qAsConst(d->m_registeredWindowClassNames)) {
if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose)
@@ -716,7 +716,7 @@ static inline bool findPlatformWindowHelper(const POINT &screenPoint, unsigned c
HWND *hwnd, QWindowsWindow **result)
{
POINT point = screenPoint;
- ScreenToClient(*hwnd, &point);
+ screenToClient(*hwnd, &point);
// Returns parent if inside & none matched.
const HWND child = ChildWindowFromPointEx(*hwnd, point, cwexFlags);
if (!child || child == *hwnd)
@@ -1053,7 +1053,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
// For non-client-area messages, these are screen coordinates (as expected
// in the MSG structure), otherwise they are client coordinates.
if (!(et & QtWindows::NonClientEventFlag)) {
- ClientToScreen(msg.hwnd, &msg.pt);
+ clientToScreen(msg.hwnd, &msg.pt);
}
} else {
GetCursorPos(&msg.pt);
@@ -1144,13 +1144,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::QuerySizeHints:
d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
return true;
- case QtWindows::ResizeEvent: {
- const QSize size(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) - d->m_creationContext->menuHeight);
- d->m_creationContext->obtainedGeometry.setSize(size);
- }
+ case QtWindows::ResizeEvent:
+ d->m_creationContext->obtainedSize = QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return true;
case QtWindows::MoveEvent:
- d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ d->m_creationContext->obtainedPos = QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return true;
case QtWindows::NonClientCreate:
if (shouldHaveNonClientDpiScaling(d->m_creationContext->window))
@@ -1363,7 +1361,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
sessionManager->blocksInteraction();
sessionManager->clearCancellation();
- QGuiApplicationPrivate *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
+ auto *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
qGuiAppPriv->commitData();
if (lParam & ENDSESSION_LOGOFF)
@@ -1381,7 +1379,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
// we receive the message for each toplevel window included internal hidden ones,
// but the aboutToQuit signal should be emitted only once.
- QGuiApplicationPrivate *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
+ auto *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
if (endsession && !qGuiAppPriv->aboutToQuitEmitted) {
qGuiAppPriv->aboutToQuitEmitted = true;
int index = QGuiApplication::staticMetaObject.indexOfSignal("aboutToQuit()");
@@ -1594,7 +1592,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR
if (QWindowsContext::verbose > 1 && lcQpaEvents().isDebugEnabled()) {
if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message)) {
qCDebug(lcQpaEvents).nospace() << "EVENT: hwd=" << hwnd << ' ' << eventName
- << " msg=0x" << hex << message << " et=0x" << et << dec << " wp="
+ << " msg=0x" << Qt::hex << message << " et=0x" << et << Qt::dec << " wp="
<< int(wParam) << " at " << GET_X_LPARAM(lParam) << ','
<< GET_Y_LPARAM(lParam) << " handled=" << handled;
}
@@ -1630,7 +1628,11 @@ static inline QByteArray nativeEventType() { return QByteArrayLiteral("windows_g
bool QWindowsContext::filterNativeEvent(MSG *msg, LRESULT *result)
{
QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr filterResult = 0;
+#else
long filterResult = 0;
+#endif
if (dispatcher && dispatcher->filterNativeEvent(nativeEventType(), msg, &filterResult)) {
*result = LRESULT(filterResult);
return true;
@@ -1641,7 +1643,11 @@ bool QWindowsContext::filterNativeEvent(MSG *msg, LRESULT *result)
// Send to QWindowSystemInterface
bool QWindowsContext::filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result)
{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr filterResult = 0;
+#else
long filterResult = 0;
+#endif
if (QWindowSystemInterface::handleNativeEvent(window, nativeEventType(), msg, &filterResult)) {
*result = LRESULT(filterResult);
return true;
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 4908f14629..d94ae3f73b 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -155,7 +155,7 @@ struct QWindowsShcoreDLL {
class QWindowsContext
{
- Q_DISABLE_COPY(QWindowsContext)
+ Q_DISABLE_COPY_MOVE(QWindowsContext)
public:
enum SystemInfoFlags
@@ -180,11 +180,11 @@ public:
QString registerWindowClass(const QWindow *w);
QString registerWindowClass(QString cname, WNDPROC proc,
- unsigned style = 0, HBRUSH brush = 0,
+ unsigned style = 0, HBRUSH brush = nullptr,
bool icon = false);
HWND createDummyWindow(const QString &classNameIn,
const wchar_t *windowName,
- WNDPROC wndProc = 0, DWORD style = WS_OVERLAPPED);
+ WNDPROC wndProc = nullptr, DWORD style = WS_OVERLAPPED);
HDC displayContext() const;
int screenDepth() const;
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 20a8117304..17e8cffb76 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -752,7 +752,7 @@ QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const
&& GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor)
&& bmColor.bmWidth == bmColor.bmWidthBytes / 4) {
const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes;
- uchar *colorBits = new uchar[colorBitsLength];
+ auto *colorBits = new uchar[colorBitsLength];
GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits);
const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight,
bmColor.bmWidthBytes, QImage::Format_ARGB32);
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index 8495b51a5a..b896f4c7a9 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -61,14 +61,14 @@ inline bool operator==(const QWindowsPixmapCursorCacheKey &k1, const QWindowsPix
return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
}
-inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) Q_DECL_NOTHROW
+inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) noexcept
{
return (uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
}
class CursorHandle
{
- Q_DISABLE_COPY(CursorHandle)
+ Q_DISABLE_COPY_MOVE(CursorHandle)
public:
explicit CursorHandle(HCURSOR hcursor = nullptr) : m_hcursor(hcursor) {}
~CursorHandle()
@@ -84,7 +84,7 @@ private:
const HCURSOR m_hcursor;
};
-typedef QSharedPointer<CursorHandle> CursorHandlePtr;
+using CursorHandlePtr = QSharedPointer<CursorHandle>;
class QWindowsCursor : public QPlatformCursor
{
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 9de3268fc8..b7ab952a1d 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -271,7 +271,7 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::ensureNativeDialo
class QWindowsDialogThread : public QThread
{
public:
- typedef QSharedPointer<QWindowsNativeDialogBase> QWindowsNativeDialogBasePtr;
+ using QWindowsNativeDialogBasePtr = QSharedPointer<QWindowsNativeDialogBase>;
explicit QWindowsDialogThread(const QWindowsNativeDialogBasePtr &d, HWND owner)
: m_dialog(d), m_owner(owner) {}
@@ -356,7 +356,7 @@ struct FindDialogContext
static BOOL QT_WIN_CALLBACK findDialogEnumWindowsProc(HWND hwnd, LPARAM lParam)
{
- FindDialogContext *context = reinterpret_cast<FindDialogContext *>(lParam);
+ auto *context = reinterpret_cast<FindDialogContext *>(lParam);
DWORD winPid = 0;
GetWindowThreadProcessId(hwnd, &winPid);
if (winPid != context->processId)
@@ -507,7 +507,7 @@ class QWindowsNativeFileDialogBase;
class QWindowsNativeFileDialogEventHandler : public QWindowsComBase<IFileDialogEvents>
{
- Q_DISABLE_COPY(QWindowsNativeFileDialogEventHandler)
+ Q_DISABLE_COPY_MOVE(QWindowsNativeFileDialogEventHandler)
public:
static IFileDialogEvents *create(QWindowsNativeFileDialogBase *nativeFileDialog);
@@ -531,7 +531,7 @@ private:
IFileDialogEvents *QWindowsNativeFileDialogEventHandler::create(QWindowsNativeFileDialogBase *nativeFileDialog)
{
IFileDialogEvents *result;
- QWindowsNativeFileDialogEventHandler *eventHandler = new QWindowsNativeFileDialogEventHandler(nativeFileDialog);
+ auto *eventHandler = new QWindowsNativeFileDialogEventHandler(nativeFileDialog);
if (FAILED(eventHandler->QueryInterface(IID_IFileDialogEvents, reinterpret_cast<void **>(&result)))) {
qErrnoWarning("Unable to obtain IFileDialogEvents");
return nullptr;
@@ -551,7 +551,7 @@ IFileDialogEvents *QWindowsNativeFileDialogEventHandler::create(QWindowsNativeFi
class QWindowsShellItem
{
public:
- typedef std::vector<IShellItem *> IShellItems;
+ using IShellItems = std::vector<IShellItem *>;
explicit QWindowsShellItem(IShellItem *item);
@@ -736,7 +736,7 @@ QString QWindowsShellItem::libraryItemDefaultSaveFolder(IShellItem *item)
#ifndef QT_NO_DEBUG_STREAM
void QWindowsShellItem::format(QDebug &d) const
{
- d << "attributes=0x" << hex << attributes() << dec;
+ d << "attributes=0x" << Qt::hex << attributes() << Qt::dec;
if (isFileSystem())
d << " [filesys]";
if (isDir())
@@ -972,7 +972,7 @@ void QWindowsNativeFileDialogBase::doExec(HWND owner)
// gets a WM_CLOSE or the parent window is destroyed.
const HRESULT hr = m_fileDialog->Show(owner);
QWindowsDialogs::eatMouseMove();
- qCDebug(lcQpaDialogs) << '<' << __FUNCTION__ << " returns " << hex << hr;
+ qCDebug(lcQpaDialogs) << '<' << __FUNCTION__ << " returns " << Qt::hex << hr;
// Emit accepted() only if there is a result as otherwise UI hangs occur.
// For example, typing in invalid URLs results in empty result lists.
if (hr == S_OK && !m_data.selectedFiles().isEmpty()) {
@@ -1013,7 +1013,7 @@ void QWindowsNativeFileDialogBase::setMode(QFileDialogOptions::FileMode mode,
}
qCDebug(lcQpaDialogs) << __FUNCTION__ << "mode=" << mode
<< "acceptMode=" << acceptMode << "options=" << options
- << "results in" << showbase << hex << flags;
+ << "results in" << Qt::showbase << Qt::hex << flags;
if (FAILED(m_fileDialog->SetOptions(flags)))
qErrnoWarning("%s: SetOptions() failed", __FUNCTION__);
@@ -1112,7 +1112,7 @@ void QWindowsNativeFileDialogBase::setDefaultSuffixSys(const QString &s)
// If this parameter is non-empty, it will be appended by the dialog for the 'Any files'
// filter ('*'). If this parameter is non-empty and the current filter has a suffix,
// the dialog will append the filter's suffix.
- wchar_t *wSuffix = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(s.utf16()));
+ auto *wSuffix = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(s.utf16()));
m_fileDialog->SetDefaultExtension(wSuffix);
}
@@ -1125,7 +1125,7 @@ static inline IFileDialog2 *getFileDialog2(IFileDialog *fileDialog)
void QWindowsNativeFileDialogBase::setLabelText(QFileDialogOptions::DialogLabel l, const QString &text)
{
- wchar_t *wText = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(text.utf16()));
+ auto *wText = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(text.utf16()));
switch (l) {
case QFileDialogOptions::FileName:
m_fileDialog->SetFileNameLabel(wText);
@@ -1688,7 +1688,7 @@ class QWindowsXpNativeFileDialog : public QWindowsNativeDialogBase
{
Q_OBJECT
public:
- typedef QSharedPointer<QFileDialogOptions> OptionsPtr;
+ using OptionsPtr = QSharedPointer<QFileDialogOptions>;
static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);
@@ -1770,7 +1770,7 @@ void QWindowsXpNativeFileDialog::doExec(HWND owner)
static int QT_WIN_CALLBACK xpFileDialogGetExistingDirCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
- QWindowsXpNativeFileDialog *dialog = reinterpret_cast<QWindowsXpNativeFileDialog *>(lpData);
+ auto *dialog = reinterpret_cast<QWindowsXpNativeFileDialog *>(lpData);
return dialog->existingDirCallback(hwnd, uMsg, lParam);
}
@@ -1779,7 +1779,7 @@ static int QT_WIN_CALLBACK xpFileDialogGetExistingDirCallbackProc(HWND hwnd, UIN
#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
typedef ITEMIDLIST *qt_LpItemIdList;
#else
-typedef PIDLIST_ABSOLUTE qt_LpItemIdList;
+using qt_LpItemIdList = PIDLIST_ABSOLUTE;
#endif
int QWindowsXpNativeFileDialog::existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam)
@@ -1843,7 +1843,7 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow
const QList<FilterSpec> specs =
filterSpecs(m_options->nameFilters(), m_options->options() & QFileDialogOptions::HideNameFilterDetails, &totalStringLength);
const int size = specs.size();
- wchar_t *ptr = new wchar_t[totalStringLength + 2 * size + 1];
+ auto *ptr = new wchar_t[totalStringLength + 2 * size + 1];
ofn->lpstrFilter = ptr;
for (const FilterSpec &spec : specs) {
ptr += spec.description.toWCharArray(ptr);
@@ -2007,7 +2007,7 @@ QString QWindowsXpFileDialogHelper::selectedNameFilter() const
\ingroup qt-lighthouse-win
*/
-typedef QSharedPointer<QColor> SharedPointerColor;
+using SharedPointerColor = QSharedPointer<QColor>;
#ifdef USE_NATIVE_COLOR_DIALOG
class QWindowsNativeColorDialog : public QWindowsNativeDialogBase
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index 6099ea9ac6..8686749011 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -64,9 +64,9 @@ namespace QWindowsDialogs
template <class BaseClass>
class QWindowsDialogHelperBase : public BaseClass
{
- Q_DISABLE_COPY(QWindowsDialogHelperBase)
+ Q_DISABLE_COPY_MOVE(QWindowsDialogHelperBase)
public:
- typedef QSharedPointer<QWindowsNativeDialogBase> QWindowsNativeDialogBasePtr;
+ using QWindowsNativeDialogBasePtr = QSharedPointer<QWindowsNativeDialogBase>;
~QWindowsDialogHelperBase() { cleanupThread(); }
void exec() override;
@@ -75,7 +75,7 @@ public:
QWindow *parent) override;
void hide() override;
- virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return true; }
+ virtual bool supportsNonModalDialog(const QWindow * /* parent */ = nullptr) const { return true; }
protected:
QWindowsDialogHelperBase() = default;
@@ -91,7 +91,7 @@ private:
void cleanupThread();
QWindowsNativeDialogBasePtr m_nativeDialog;
- HWND m_ownerWindow = 0;
+ HWND m_ownerWindow = nullptr;
int m_timerId = 0;
QThread *m_thread = nullptr;
};
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 322865b0f3..3e4c93d47a 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -428,7 +428,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
if (QWindowsContext::verbose > 1 || result != S_OK) {
qCDebug(lcQpaMime) << __FUNCTION__ << "fEscapePressed=" << fEscapePressed
<< "grfKeyState=" << grfKeyState << "buttons" << m_currentButtons
- << "returns 0x" << hex << int(result) << dec;
+ << "returns 0x" << Qt::hex << int(result) << Qt::dec;
}
return ResultFromScode(result);
}
@@ -627,7 +627,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
m_chosenEffect = DROPEFFECT_COPY;
HGLOBAL hData = GlobalAlloc(0, sizeof(DWORD));
if (hData) {
- DWORD *moveEffect = reinterpret_cast<DWORD *>(GlobalLock(hData));
+ auto *moveEffect = reinterpret_cast<DWORD *>(GlobalLock(hData));
*moveEffect = DROPEFFECT_MOVE;
GlobalUnlock(hData);
STGMEDIUM medium;
@@ -704,13 +704,13 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag)
DWORD resultEffect;
QWindowsDrag::m_canceled = false;
- QWindowsOleDropSource *windowDropSource = new QWindowsOleDropSource(this);
+ auto *windowDropSource = new QWindowsOleDropSource(this);
windowDropSource->createCursors();
- QWindowsDropDataObject *dropDataObject = new QWindowsDropDataObject(dropData);
+ auto *dropDataObject = new QWindowsDropDataObject(dropData);
const Qt::DropActions possibleActions = drag->supportedActions();
const DWORD allowedEffects = translateToWinDragEffects(possibleActions);
qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x"
- << hex << int(possibleActions) << "effects=0x" << allowedEffects << dec;
+ << Qt::hex << int(possibleActions) << "effects=0x" << allowedEffects << Qt::dec;
// Indicate message handlers we are in DoDragDrop() event loop.
QWindowsDrag::m_dragging = true;
const HRESULT r = DoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
@@ -734,9 +734,9 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag)
dropDataObject->releaseQt();
dropDataObject->Release(); // Will delete obj if refcount becomes 0
windowDropSource->Release(); // Will delete src if refcount becomes 0
- qCDebug(lcQpaMime) << '<' << __FUNCTION__ << hex << "allowedEffects=0x" << allowedEffects
+ qCDebug(lcQpaMime) << '<' << __FUNCTION__ << Qt::hex << "allowedEffects=0x" << allowedEffects
<< "reportedPerformedEffect=0x" << reportedPerformedEffect
- << " resultEffect=0x" << resultEffect << "hr=0x" << int(r) << dec << "dropAction=" << dragResult;
+ << " resultEffect=0x" << resultEffect << "hr=0x" << int(r) << Qt::dec << "dropAction=" << dragResult;
return dragResult;
}
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index 063e81150e..e9f3dc5189 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -469,10 +469,10 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
+ auto *window = static_cast<QWindowsWindow *>(surface);
window->aboutToMakeCurrent();
int err = 0;
- EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
+ auto eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
if (eglSurface == EGL_NO_SURFACE) {
if (err == EGL_CONTEXT_LOST) {
m_eglContext = EGL_NO_CONTEXT;
@@ -531,9 +531,9 @@ void QWindowsEGLContext::doneCurrent()
void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
{
QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
+ auto *window = static_cast<QWindowsWindow *>(surface);
int err = 0;
- EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
+ auto eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
if (eglSurface == EGL_NO_SURFACE) {
if (err == EGL_CONTEXT_LOST) {
m_eglContext = EGL_NO_CONTEXT;
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 8a1e1ddae8..d96e266159 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -109,7 +109,7 @@ private:
class QWindowsEGLStaticContext : public QWindowsStaticOpenGLContext
{
- Q_DISABLE_COPY(QWindowsEGLStaticContext)
+ Q_DISABLE_COPY_MOVE(QWindowsEGLStaticContext)
public:
static QWindowsEGLStaticContext *create(QWindowsOpenGLTester::Renderers preferredType);
diff --git a/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp b/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
index 08e11c5e39..f2418b0e60 100644
--- a/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
@@ -50,7 +50,7 @@ void *QWindowsGdiNativeInterface::nativeResourceForBackingStore(const QByteArray
qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData());
return nullptr;
}
- QWindowsBackingStore *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
+ auto *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
if (resource == "getDC")
return wbs->getDC();
qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index e95eaef420..24526bad2c 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -243,7 +243,7 @@ QDebug operator<<(QDebug d, const PIXELFORMATDESCRIPTOR &pd)
QDebugStateSaver saver(d);
d.nospace();
d << "PIXELFORMATDESCRIPTOR "
- << "dwFlags=" << hex << showbase << pd.dwFlags << dec << noshowbase;
+ << "dwFlags=" << Qt::hex << Qt::showbase << pd.dwFlags << Qt::dec << Qt::noshowbase;
if (pd.dwFlags & PFD_DRAW_TO_WINDOW) d << " PFD_DRAW_TO_WINDOW";
if (pd.dwFlags & PFD_DRAW_TO_BITMAP) d << " PFD_DRAW_TO_BITMAP";
if (pd.dwFlags & PFD_SUPPORT_GDI) d << " PFD_SUPPORT_GDI";
@@ -631,10 +631,10 @@ static int choosePixelFormat(HDC hdc,
nsp << __FUNCTION__;
if (sampleBuffersRequested)
nsp << " samples=" << iAttributes[samplesValuePosition];
- nsp << " Attributes: " << hex << showbase;
+ nsp << " Attributes: " << Qt::hex << Qt::showbase;
for (int ii = 0; ii < i; ++ii)
nsp << iAttributes[ii] << ',';
- nsp << noshowbase << dec << "\n obtained px #" << pixelFormat
+ nsp << Qt::noshowbase << Qt::dec << "\n obtained px #" << pixelFormat
<< " of " << numFormats << "\n " << *obtainedPfd;
qCDebug(lcQpaGl) << message;
} // Debug
@@ -784,7 +784,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext,
if (!result) {
QString message;
QDebug(&message).nospace() << __FUNCTION__ << ": wglCreateContextAttribsARB() failed (GL error code: 0x"
- << hex << staticContext.opengl32.glGetError() << dec << ") for format: " << format << ", shared context: " << shared;
+ << Qt::hex << staticContext.opengl32.glGetError() << Qt::dec << ") for format: " << format << ", shared context: " << shared;
qErrnoWarning("%s", qPrintable(message));
}
return result;
@@ -916,7 +916,7 @@ void QWindowsOpenGLContextFormat::apply(QSurfaceFormat *format) const
class QOpenGLTemporaryContext
{
- Q_DISABLE_COPY(QOpenGLTemporaryContext)
+ Q_DISABLE_COPY_MOVE(QOpenGLTemporaryContext)
public:
QOpenGLTemporaryContext();
~QOpenGLTemporaryContext();
@@ -1009,7 +1009,7 @@ QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering)
QScopedPointer<QOpenGLTemporaryContext> temporaryContext;
if (!QOpenGLStaticContext::opengl32.wglGetCurrentContext())
temporaryContext.reset(new QOpenGLTemporaryContext);
- QOpenGLStaticContext *result = new QOpenGLStaticContext;
+ auto *result = new QOpenGLStaticContext;
qCDebug(lcQpaGl) << __FUNCTION__ << *result;
return result;
}
@@ -1051,7 +1051,7 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext,
qWarning("QWindowsGLContext: Requires a QWGLNativeContext");
return;
}
- QWGLNativeContext handle = nativeHandle.value<QWGLNativeContext>();
+ auto handle = nativeHandle.value<QWGLNativeContext>();
HGLRC wglcontext = handle.context();
HWND wnd = handle.window();
if (!wglcontext || !wnd) {
@@ -1233,7 +1233,7 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval)
hasRobustness = exts && strstr(exts, "GL_ARB_robustness");
} else {
typedef const GLubyte * (APIENTRY *glGetStringi_t)(GLenum, GLuint);
- glGetStringi_t glGetStringi = reinterpret_cast<glGetStringi_t>(
+ auto glGetStringi = reinterpret_cast<glGetStringi_t>(
reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetStringi")));
if (glGetStringi) {
GLint n = 0;
@@ -1305,7 +1305,7 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
Q_ASSERT(surface->surface()->supportsOpenGL());
// Do we already have a DC entry for that window?
- QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
+ auto *window = static_cast<QWindowsWindow *>(surface);
window->aboutToMakeCurrent();
const HWND hwnd = window->handle();
if (const QOpenGLContextData *contextData = findByHWND(m_windowContexts, hwnd)) {
@@ -1374,7 +1374,7 @@ QFunctionPointer QWindowsGLContext::getProcAddress(const char *procName)
// Even though we use QFunctionPointer, it does not mean the function can be called.
// It will need to be cast to the proper function type with the correct calling
// convention. QFunctionPointer is nothing more than a glorified void* here.
- QFunctionPointer procAddress = reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(procName));
+ auto procAddress = reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(procName));
// We support AllGLFunctionsQueryable, which means this function must be able to
// return a function pointer even for functions that are in GL.h and exported
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index 199f8112e3..1abe2eb390 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -75,9 +75,9 @@ struct QOpenGLContextData
QOpenGLContextData(HGLRC r, HWND h, HDC d) : renderingContext(r), hwnd(h), hdc(d) {}
QOpenGLContextData() {}
- HGLRC renderingContext = 0;
- HWND hwnd = 0;
- HDC hdc = 0;
+ HGLRC renderingContext = nullptr;
+ HWND hwnd = nullptr;
+ HDC hdc = nullptr;
};
class QOpenGLStaticContext;
@@ -89,7 +89,7 @@ struct QWindowsOpenGLContextFormat
QSurfaceFormat::OpenGLContextProfile profile = QSurfaceFormat::NoProfile;
int version = 0; //! majorVersion<<8 + minorVersion
- QSurfaceFormat::FormatOptions options = 0;
+ QSurfaceFormat::FormatOptions options = nullptr;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -134,7 +134,7 @@ private:
class QOpenGLStaticContext : public QWindowsStaticOpenGLContext
{
- Q_DISABLE_COPY(QOpenGLStaticContext)
+ Q_DISABLE_COPY_MOVE(QOpenGLStaticContext)
QOpenGLStaticContext();
public:
enum Extensions
@@ -222,7 +222,7 @@ private:
typedef GLenum (APIENTRY *GlGetGraphicsResetStatusArbType)();
inline void releaseDCs();
- bool updateObtainedParams(HDC hdc, int *obtainedSwapInterval = 0);
+ bool updateObtainedParams(HDC hdc, int *obtainedSwapInterval = nullptr);
QOpenGLStaticContext *m_staticContext;
QOpenGLContext *m_context;
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 8adcf56b11..e681dbb0cb 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -445,7 +445,7 @@ static inline QTextFormat standardFormat(StandardFormat format)
const QPalette palette = QGuiApplication::palette();
const QColor background = palette.text().color();
result.setBackground(QBrush(background));
- result.setForeground(palette.background());
+ result.setForeground(palette.window());
break;
}
}
@@ -657,9 +657,9 @@ void QWindowsInputContext::handleInputLanguageChanged(WPARAM wparam, LPARAM lpar
m_locale = qt_localeFromLCID(m_languageId);
emitLocaleChanged();
- qCDebug(lcQpaInputMethods) << __FUNCTION__ << hex << showbase
+ qCDebug(lcQpaInputMethods) << __FUNCTION__ << Qt::hex << Qt::showbase
<< oldLanguageId << "->" << newLanguageId << "Character set:"
- << DWORD(wparam) << dec << noshowbase << m_locale;
+ << DWORD(wparam) << Qt::dec << Qt::noshowbase << m_locale;
}
/*!
@@ -717,7 +717,7 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv)
reconv->dwCompStrOffset = DWORD(startPos) * sizeof(ushort); // byte count.
reconv->dwTargetStrLen = reconv->dwCompStrLen;
reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
- ushort *pastReconv = reinterpret_cast<ushort *>(reconv + 1);
+ auto *pastReconv = reinterpret_cast<ushort *>(reconv + 1);
std::copy(surroundingText.utf16(), surroundingText.utf16() + surroundingText.size(),
QT_MAKE_UNCHECKED_ARRAY_ITERATOR(pastReconv));
return memSize;
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index a47585c29e..857706bcb9 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -53,12 +53,12 @@ class QWindowsWindow;
class QWindowsInputContext : public QPlatformInputContext
{
- Q_DISABLE_COPY(QWindowsInputContext)
+ Q_DISABLE_COPY_MOVE(QWindowsInputContext)
Q_OBJECT
struct CompositionContext
{
- HWND hwnd = 0;
+ HWND hwnd = nullptr;
QString composition;
int position = 0;
bool isComposing = false;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 5c1fa00088..eccf1c4928 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -133,7 +133,7 @@ QT_BEGIN_NAMESPACE
struct QWindowsIntegrationPrivate
{
- Q_DISABLE_COPY(QWindowsIntegrationPrivate)
+ Q_DISABLE_COPY_MOVE(QWindowsIntegrationPrivate)
explicit QWindowsIntegrationPrivate(const QStringList &paramList);
~QWindowsIntegrationPrivate();
@@ -217,6 +217,8 @@ static inline unsigned parseOptions(const QStringList &paramList,
options |= QWindowsIntegration::NoNativeMenus;
} else if (param == QLatin1String("nowmpointer")) {
options |= QWindowsIntegration::DontUseWMPointer;
+ } else if (param == QLatin1String("reverse")) {
+ options |= QWindowsIntegration::RtlEnabled;
} else {
qWarning() << "Unknown option" << param;
}
@@ -322,9 +324,9 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
{
if (window->type() == Qt::Desktop) {
- QWindowsDesktopWindow *result = new QWindowsDesktopWindow(window);
+ auto *result = new QWindowsDesktopWindow(window);
qCDebug(lcQpaWindows) << "Desktop window:" << window
- << showbase << hex << result->winId() << noshowbase << dec << result->geometry();
+ << Qt::showbase << Qt::hex << result->winId() << Qt::noshowbase << Qt::dec << result->geometry();
return result;
}
@@ -369,15 +371,15 @@ QPlatformWindow *QWindowsIntegration::createForeignWindow(QWindow *window, WId n
qWarning("Windows QPA: Invalid foreign window ID %p.", hwnd);
return nullptr;
}
- QWindowsForeignWindow *result = new QWindowsForeignWindow(window, hwnd);
+ auto *result = new QWindowsForeignWindow(window, hwnd);
const QRect obtainedGeometry = result->geometry();
QScreen *screen = nullptr;
if (const QPlatformScreen *pScreen = result->screenForGeometry(obtainedGeometry))
screen = pScreen->screen();
if (screen && screen != window->screen())
window->setScreen(screen);
- qCDebug(lcQpaWindows) << "Foreign window:" << window << showbase << hex
- << result->winId() << noshowbase << dec << obtainedGeometry << screen;
+ qCDebug(lcQpaWindows) << "Foreign window:" << window << Qt::showbase << Qt::hex
+ << result->winId() << Qt::noshowbase << Qt::dec << obtainedGeometry << screen;
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index e28b2c2fb3..b49d21022b 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -54,7 +54,7 @@ class QWindowsStaticOpenGLContext;
class QWindowsIntegration : public QPlatformIntegration
{
- Q_DISABLE_COPY(QWindowsIntegration)
+ Q_DISABLE_COPY_MOVE(QWindowsIntegration)
public:
enum Options { // Options to be passed on command line.
FontDatabaseFreeType = 0x1,
@@ -69,7 +69,8 @@ public:
AlwaysUseNativeMenus = 0x100,
NoNativeMenus = 0x200,
DontUseWMPointer = 0x400,
- DetectAltGrModifier = 0x800
+ DetectAltGrModifier = 0x800,
+ RtlEnabled = 0x1000
};
explicit QWindowsIntegration(const QStringList &paramList);
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index c5af4d8042..4b54051e0c 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -100,7 +100,7 @@ QWindowsKeyMapper::QWindowsKeyMapper()
: m_useRTLExtensions(false), m_keyGrabber(nullptr)
{
memset(keyLayout, 0, sizeof(keyLayout));
- QGuiApplication *app = static_cast<QGuiApplication *>(QGuiApplication::instance());
+ auto *app = static_cast<QGuiApplication *>(QGuiApplication::instance());
QObject::connect(app, &QGuiApplication::applicationStateChanged,
app, clearKeyRecorderOnApplicationInActive);
changeKeyboard();
@@ -554,7 +554,7 @@ QDebug operator<<(QDebug d, const KeyboardLayoutItem &k)
if (const quint32 qtKey = k.qtKey[i]) {
d << '[' << i << ' ';
QtDebugUtils::formatQFlags(d, ModsTbl[i]);
- d << ' ' << hex << showbase << qtKey << dec << noshowbase << ' ';
+ d << ' ' << Qt::hex << Qt::showbase << qtKey << Qt::dec << Qt::noshowbase << ' ';
QtDebugUtils::formatQEnum(d, Qt::Key(qtKey));
if (qtKey >= 32 && qtKey < 128)
d << " '" << char(qtKey) << '\'';
@@ -776,7 +776,7 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32
::ToAscii(vk_key, scancode, kbdBuffer, reinterpret_cast<LPWORD>(&buffer), 0);
}
qCDebug(lcQpaEvents) << __FUNCTION__ << "for virtual key="
- << hex << showbase << vk_key << dec << noshowbase << keyLayout[vk_key];
+ << Qt::hex << Qt::showbase << vk_key << Qt::dec << Qt::noshowbase << keyLayout[vk_key];
}
static inline QString messageKeyText(const MSG &msg)
@@ -950,7 +950,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
const UINT msgType = msg.message;
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
- quint32 vk_key = quint32(msg.wParam);
+ auto vk_key = quint32(msg.wParam);
quint32 nModifiers = 0;
QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
@@ -1182,7 +1182,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
// results, if we map this virtual key-code directly (for eg '?' US layouts). So try
// to find the correct key using the current message parameters & keyboard state.
if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
- const QWindowsInputContext *windowsInputContext =
+ const auto *windowsInputContext =
qobject_cast<const QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
if (!(windowsInputContext && windowsInputContext->isComposing()))
vk_key = ImmGetVirtualKey(reinterpret_cast<HWND>(window->winId()));
@@ -1384,7 +1384,7 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
}
}
qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey="
- << showbase << hex << e->nativeVirtualKey() << dec << noshowbase
+ << Qt::showbase << Qt::hex << e->nativeVirtualKey() << Qt::dec << Qt::noshowbase
<< e->modifiers() << kbItem << "\n returns" << formatKeys(result);
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h
index a454f0f973..b1ada1d373 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.h
+++ b/src/plugins/platforms/windows/qwindowskeymapper.h
@@ -71,7 +71,7 @@ struct KeyboardLayoutItem {
class QWindowsKeyMapper
{
- Q_DISABLE_COPY(QWindowsKeyMapper)
+ Q_DISABLE_COPY_MOVE(QWindowsKeyMapper)
public:
explicit QWindowsKeyMapper();
~QWindowsKeyMapper();
diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp
index 5a92a7cf90..d20edd685e 100644
--- a/src/plugins/platforms/windows/qwindowsmenu.cpp
+++ b/src/plugins/platforms/windows/qwindowsmenu.cpp
@@ -518,7 +518,7 @@ QWindowsMenu::~QWindowsMenu()
void QWindowsMenu::insertMenuItem(QPlatformMenuItem *menuItemIn, QPlatformMenuItem *before)
{
qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << menuItemIn << ", before=" << before << ')' << this;
- QWindowsMenuItem *menuItem = static_cast<QWindowsMenuItem *>(menuItemIn);
+ auto *menuItem = static_cast<QWindowsMenuItem *>(menuItemIn);
const int index = insertBefore(&m_menuItems, menuItemIn, before);
const bool append = index == m_menuItems.size() - 1;
menuItem->insertIntoMenu(this, append, index);
@@ -689,7 +689,7 @@ void QWindowsPopupMenu::showPopup(const QWindow *parentWindow, const QRect &targ
const QPlatformMenuItem *item)
{
qCDebug(lcQpaMenus) << __FUNCTION__ << '>' << this << parentWindow << targetRect << item;
- const QWindowsBaseWindow *window = static_cast<const QWindowsBaseWindow *>(parentWindow->handle());
+ const auto *window = static_cast<const QWindowsBaseWindow *>(parentWindow->handle());
const QPoint globalPos = window->mapToGlobal(targetRect.topLeft());
trackPopupMenu(window->handle(), globalPos.x(), globalPos.y());
}
@@ -756,7 +756,7 @@ QWindowsMenuBar::~QWindowsMenuBar()
void QWindowsMenuBar::insertMenu(QPlatformMenu *menuIn, QPlatformMenu *before)
{
qCDebug(lcQpaMenus) << __FUNCTION__ << menuIn << "before=" << before;
- QWindowsMenu *menu = static_cast<QWindowsMenu *>(menuIn);
+ auto *menu = static_cast<QWindowsMenu *>(menuIn);
const int index = insertBefore(&m_menus, menuIn, before);
menu->insertIntoMenuBar(this, index == m_menus.size() - 1, index);
}
@@ -784,7 +784,7 @@ void QWindowsMenuBar::handleReparent(QWindow *newParentWindow)
if (QPlatformWindow *platWin = newParentWindow->handle())
install(static_cast<QWindowsWindow *>(platWin));
else // Store for later creation, see menuBarOf()
- newParentWindow->setProperty(menuBarPropertyName, qVariantFromValue<QObject *>(this));
+ newParentWindow->setProperty(menuBarPropertyName, QVariant::fromValue<QObject *>(this));
}
QWindowsMenuBar *QWindowsMenuBar::menuBarOf(const QWindow *notYetCreatedWindow)
@@ -896,8 +896,8 @@ void QWindowsMenuItem::formatDebug(QDebug &d) const
d << ", parentMenu=" << static_cast<const void *>(m_parentMenu);
if (m_subMenu)
d << ", subMenu=" << static_cast<const void *>(m_subMenu);
- d << ", tag=" << showbase << hex
- << tag() << noshowbase << dec << ", id=" << m_id;
+ d << ", tag=" << Qt::showbase << Qt::hex
+ << tag() << Qt::noshowbase << Qt::dec << ", id=" << m_id;
#if QT_CONFIG(shortcut)
if (!m_shortcut.isEmpty())
d << ", shortcut=" << m_shortcut;
@@ -933,7 +933,7 @@ void QWindowsMenu::formatDebug(QDebug &d) const
if (m_parentMenu != nullptr)
d << " [on menu]";
if (tag())
- d << ", tag=" << showbase << hex << tag() << noshowbase << dec;
+ d << ", tag=" << Qt::showbase << Qt::hex << tag() << Qt::noshowbase << Qt::dec;
if (m_visible)
d << " [visible]";
if (m_enabled)
diff --git a/src/plugins/platforms/windows/qwindowsmenu.h b/src/plugins/platforms/windows/qwindowsmenu.h
index 6de1553f35..aa36846ec0 100644
--- a/src/plugins/platforms/windows/qwindowsmenu.h
+++ b/src/plugins/platforms/windows/qwindowsmenu.h
@@ -120,7 +120,7 @@ class QWindowsMenu : public QPlatformMenu
{
Q_OBJECT
public:
- typedef QVector<QWindowsMenuItem *> MenuItems;
+ using MenuItems = QVector<QWindowsMenuItem *>;
QWindowsMenu();
~QWindowsMenu();
@@ -196,7 +196,7 @@ class QWindowsMenuBar : public QPlatformMenuBar
{
Q_OBJECT
public:
- typedef QVector<QWindowsMenu *> Menus;
+ using Menus = QVector<QWindowsMenu *>;
QWindowsMenuBar();
~QWindowsMenuBar() override;
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 030d8d1e0f..b9d8b191f5 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -178,7 +178,7 @@ static bool qt_write_dibv5(QDataStream &s, QImage image)
if (image.format() != QImage::Format_ARGB32)
image = image.convertToFormat(QImage::Format_ARGB32);
- uchar *buf = new uchar[bpl_bmp];
+ auto *buf = new uchar[bpl_bmp];
memset(buf, 0, size_t(bpl_bmp));
for (int y=image.height()-1; y>=0; y--) {
@@ -264,7 +264,7 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image)
const int bpl = image.bytesPerLine();
uchar *data = image.bits();
- uchar *buf24 = new uchar[bpl];
+ auto *buf24 = new uchar[bpl];
const int bpl24 = ((w * nbits + 31) / 32) * 4;
while (--h >= 0) {
@@ -286,7 +286,7 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image)
if (bi.bV5Height < 0) {
// Flip the image
- uchar *buf = new uchar[bpl];
+ auto *buf = new uchar[bpl];
h = -bi.bV5Height;
for (int y = 0; y < h/2; ++y) {
memcpy(buf, data + y * bpl, size_t(bpl));
@@ -772,16 +772,16 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
}
QByteArray result(size, '\0');
- DROPFILES* d = reinterpret_cast<DROPFILES *>(result.data());
+ auto* d = reinterpret_cast<DROPFILES *>(result.data());
d->pFiles = sizeof(DROPFILES);
GetCursorPos(&d->pt); // try
d->fNC = true;
char *files = (reinterpret_cast<char*>(d)) + d->pFiles;
d->fWide = true;
- wchar_t *f = reinterpret_cast<wchar_t *>(files);
+ auto *f = reinterpret_cast<wchar_t *>(files);
for (int i=0; i<fileNames.size(); i++) {
- const size_t l = size_t(fileNames.at(i).length());
+ const auto l = size_t(fileNames.at(i).length());
memcpy(f, fileNames.at(i).utf16(), l * sizeof(ushort));
f += l;
*f++ = 0;
@@ -852,9 +852,9 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD
if (data.isEmpty())
return QVariant();
- const DROPFILES *hdrop = reinterpret_cast<const DROPFILES *>(data.constData());
+ const auto *hdrop = reinterpret_cast<const DROPFILES *>(data.constData());
if (hdrop->fWide) {
- const wchar_t *filesw = reinterpret_cast<const wchar_t *>(data.constData() + hdrop->pFiles);
+ const auto *filesw = reinterpret_cast<const wchar_t *>(data.constData() + hdrop->pFiles);
int i = 0;
while (filesw[i]) {
QString fileurl = QString::fromWCharArray(filesw + i);
@@ -1055,7 +1055,7 @@ QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, co
QVector<FORMATETC> formatetcs;
if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) {
//add DIBV5 if image has alpha channel. Do not add CF_PNG here as it will confuse MS Office (QTBUG47656).
- QImage image = qvariant_cast<QImage>(mimeData->imageData());
+ auto image = qvariant_cast<QImage>(mimeData->imageData());
if (!image.isNull() && image.hasAlphaChannel())
formatetcs += setCf(CF_DIBV5);
formatetcs += setCf(CF_DIB);
@@ -1097,7 +1097,7 @@ bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeD
{
int cf = getCf(formatetc);
if ((cf == CF_DIB || cf == CF_DIBV5 || cf == int(CF_PNG)) && mimeData->hasImage()) {
- QImage img = qvariant_cast<QImage>(mimeData->imageData());
+ auto img = qvariant_cast<QImage>(mimeData->imageData());
if (img.isNull())
return false;
QByteArray ba;
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
index 6bbbae1a0e..1c389e8800 100644
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ b/src/plugins/platforms/windows/qwindowsmime.h
@@ -53,7 +53,7 @@ class QMimeData;
class QWindowsMime
{
- Q_DISABLE_COPY(QWindowsMime)
+ Q_DISABLE_COPY_MOVE(QWindowsMime)
public:
QWindowsMime();
virtual ~QWindowsMime();
@@ -73,7 +73,7 @@ public:
class QWindowsMimeConverter
{
- Q_DISABLE_COPY(QWindowsMimeConverter)
+ Q_DISABLE_COPY_MOVE(QWindowsMimeConverter)
public:
QWindowsMimeConverter();
~QWindowsMimeConverter();
@@ -85,7 +85,7 @@ public:
// Convenience.
QVariant convertToMime(const QStringList &mimeTypes, IDataObject *pDataObj, QVariant::Type preferredType,
- QString *format = 0) const;
+ QString *format = nullptr) const;
void registerMime(QWindowsMime *mime);
void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); }
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index e33591c33d..6df5e6aa27 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -106,7 +106,7 @@ static inline void compressMouseMove(MSG *msg)
// Extract the x,y coordinates from the lParam as we do in the WndProc
msg->pt.x = GET_X_LPARAM(mouseMsg.lParam);
msg->pt.y = GET_Y_LPARAM(mouseMsg.lParam);
- ClientToScreen(msg->hwnd, &(msg->pt));
+ clientToScreen(msg->hwnd, &(msg->pt));
// Remove the mouse move message
PeekMessage(&mouseMsg, msg->hwnd, WM_MOUSEMOVE,
WM_MOUSEMOVE, PM_REMOVE);
@@ -124,10 +124,10 @@ static inline QTouchDevice *createTouchDevice()
return nullptr;
const int tabletPc = GetSystemMetrics(SM_TABLETPC);
const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES);
- qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~NID_READY)
- << "Ready:" << (digitizers & NID_READY) << dec << noshowbase
+ qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY)
+ << "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase
<< "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints;
- QTouchDevice *result = new QTouchDevice;
+ auto *result = new QTouchDevice;
result->setType(digitizers & NID_INTEGRATED_TOUCH
? QTouchDevice::TouchScreen : QTouchDevice::TouchPad);
QTouchDevice::Capabilities capabilities = QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition;
@@ -268,7 +268,13 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
if (et == QtWindows::MouseWheelEvent)
return translateMouseWheelEvent(window, hwnd, msg, result);
- const QPoint winEventPosition(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
+ QPoint winEventPosition(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
+ if ((et & QtWindows::NonClientEventFlag) == 0 && QWindowsBaseWindow::isRtlLayout(hwnd)) {
+ RECT clientArea;
+ GetClientRect(hwnd, &clientArea);
+ winEventPosition.setX(clientArea.right - winEventPosition.x());
+ }
+
QPoint clientPosition;
QPoint globalPosition;
if (et & QtWindows::NonClientEventFlag) {
@@ -300,7 +306,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
// However, when tablet support is active, extraInfo is a packet serial number. This is not a problem
// since we do not want to ignore mouse events coming from a tablet.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms703320.aspx
- const quint64 extraInfo = quint64(GetMessageExtraInfo());
+ const auto extraInfo = quint64(GetMessageExtraInfo());
if ((extraInfo & signatureMask) == miWpSignature) {
if (extraInfo & 0x80) { // Bit 7 indicates touch event, else tablet pen.
source = Qt::MouseEventSynthesizedBySystem;
@@ -364,7 +370,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
return true;
}
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+ auto *platformWindow = static_cast<QWindowsWindow *>(window->handle());
// If the window was recently resized via mouse doubleclick on the frame or title bar,
// we don't get WM_LBUTTONDOWN or WM_LBUTTONDBLCLK for the second click,
@@ -603,8 +609,8 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
QtWindows::WindowsEventType,
MSG msg, LRESULT *)
{
- typedef QWindowSystemInterface::TouchPoint QTouchPoint;
- typedef QList<QWindowSystemInterface::TouchPoint> QTouchPointList;
+ using QTouchPoint = QWindowSystemInterface::TouchPoint;
+ using QTouchPointList = QList<QWindowSystemInterface::TouchPoint>;
if (!QWindowsContext::instance()->initTouch()) {
qWarning("Unable to initialize touch handling.");
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h
index 5fe4b09c1e..1d3d1f4761 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.h
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.h
@@ -54,7 +54,7 @@ class QTouchDevice;
class QWindowsMouseHandler
{
- Q_DISABLE_COPY(QWindowsMouseHandler)
+ Q_DISABLE_COPY_MOVE(QWindowsMouseHandler)
public:
QWindowsMouseHandler();
@@ -79,7 +79,7 @@ public:
static Qt::MouseButtons queryMouseButtons();
QWindow *windowUnderMouse() const { return m_windowUnderMouse.data(); }
- void clearWindowUnderMouse() { m_windowUnderMouse = 0; }
+ void clearWindowUnderMouse() { m_windowUnderMouse = nullptr; }
void clearEvents();
private:
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index ed945ec4b1..d1d181d66e 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -40,6 +40,7 @@
#include "qwindowsnativeinterface.h"
#include "qwindowsclipboard.h"
#include "qwindowswindow.h"
+#include "qwindowsscreen.h"
#include "qwindowscontext.h"
#include "qwindowscursor.h"
#include "qwindowsopenglcontext.h"
@@ -97,7 +98,7 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc
qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData());
return nullptr;
}
- QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle());
+ auto *bw = static_cast<QWindowsWindow *>(window->handle());
int type = resourceType(resource);
if (type == HandleType)
return bw->handle();
@@ -124,6 +125,21 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc
return nullptr;
}
+void *QWindowsNativeInterface::nativeResourceForScreen(const QByteArray &resource, QScreen *screen)
+{
+ if (!screen || !screen->handle()) {
+ qWarning("%s: '%s' requested for null screen or screen without handle.", __FUNCTION__, resource.constData());
+ return nullptr;
+ }
+ auto *bs = static_cast<QWindowsScreen *>(screen->handle());
+ int type = resourceType(resource);
+ if (type == HandleType)
+ return bs->handle();
+
+ qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
+ return nullptr;
+}
+
#ifndef QT_NO_CURSOR
void *QWindowsNativeInterface::nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor)
{
@@ -141,9 +157,9 @@ static const char customMarginPropertyC[] = "WindowsCustomMargins";
QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const QString &name) const
{
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window);
+ auto *platformWindow = static_cast<QWindowsWindow *>(window);
if (name == QLatin1String(customMarginPropertyC))
- return qVariantFromValue(platformWindow->customMargins());
+ return QVariant::fromValue(platformWindow->customMargins());
return QVariant();
}
@@ -155,7 +171,7 @@ QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const
void QWindowsNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value)
{
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window);
+ auto *platformWindow = static_cast<QWindowsWindow *>(window);
if (name == QLatin1String(customMarginPropertyC))
platformWindow->setCustomMargins(qvariant_cast<QMargins>(value));
}
@@ -190,7 +206,7 @@ void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resour
return nullptr;
}
- QWindowsOpenGLContext *glcontext = static_cast<QWindowsOpenGLContext *>(context->handle());
+ auto *glcontext = static_cast<QWindowsOpenGLContext *>(context->handle());
switch (resourceType(resource)) {
case RenderingContextType: // Fall through.
case EglContextType:
@@ -277,6 +293,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun
return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic);
if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier())
return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic);
+ if (function == QWindowsWindowFunctions::setHasBorderInFullScreenDefaultIdentifier())
+ return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenDefault);
if (function == QWindowsWindowFunctions::setWindowActivationBehaviorIdentifier())
return QFunctionPointer(QWindowsNativeInterface::setWindowActivationBehavior);
if (function == QWindowsWindowFunctions::isTabletModeIdentifier())
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h
index e6f8aae8fb..ce395dc5a4 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.h
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h
@@ -74,6 +74,7 @@ public:
void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override;
#endif
void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override;
+ void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) override;
#ifndef QT_NO_CURSOR
void *nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor) override;
#endif
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index e9c3f2cbf6..f3450e2806 100644
--- a/src/plugins/platforms/windows/qwindowsole.cpp
+++ b/src/plugins/platforms/windows/qwindowsole.cpp
@@ -110,7 +110,7 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
}
if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled())
- qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << hex << showbase << quint64(hr);
+ qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << Qt::hex << Qt::showbase << quint64(hr);
return hr;
}
@@ -135,7 +135,7 @@ QWindowsOleDataObject::QueryGetData(LPFORMATETC pformatetc)
ResultFromScode(S_OK) : ResultFromScode(S_FALSE);
}
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << hex << int(hr);
+ qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << Qt::hex << int(hr);
return hr;
}
@@ -155,7 +155,7 @@ QWindowsOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL
HRESULT hr = ResultFromScode(E_NOTIMPL);
if (pFormatetc->cfFormat == CF_PERFORMEDDROPEFFECT && pMedium->tymed == TYMED_HGLOBAL) {
- DWORD * val = (DWORD*)GlobalLock(pMedium->hGlobal);
+ auto * val = (DWORD*)GlobalLock(pMedium->hGlobal);
performedEffect = *val;
GlobalUnlock(pMedium->hGlobal);
if (fRelease)
@@ -163,7 +163,7 @@ QWindowsOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL
hr = ResultFromScode(S_OK);
}
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << hex << int(hr);
+ qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << Qt::hex << int(hr);
return hr;
}
@@ -193,7 +193,7 @@ QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppe
fmtetcs.append(formatetc);
}
- QWindowsOleEnumFmtEtc *enumFmtEtc = new QWindowsOleEnumFmtEtc(fmtetcs);
+ auto *enumFmtEtc = new QWindowsOleEnumFmtEtc(fmtetcs);
*ppenumFormatEtc = enumFmtEtc;
if (enumFmtEtc->isNull()) {
delete enumFmtEtc;
@@ -237,7 +237,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs)
qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs;
m_lpfmtetcs.reserve(fmtetcs.count());
for (int idx = 0; idx < fmtetcs.count(); ++idx) {
- LPFORMATETC destetc = new FORMATETC();
+ auto destetc = new FORMATETC();
if (copyFormatEtc(destetc, &(fmtetcs.at(idx)))) {
m_lpfmtetcs.append(destetc);
} else {
@@ -255,7 +255,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<LPFORMATETC> &lpfmtet
m_lpfmtetcs.reserve(lpfmtetcs.count());
for (int idx = 0; idx < lpfmtetcs.count(); ++idx) {
LPFORMATETC srcetc = lpfmtetcs.at(idx);
- LPFORMATETC destetc = new FORMATETC();
+ auto destetc = new FORMATETC();
if (copyFormatEtc(destetc, srcetc)) {
m_lpfmtetcs.append(destetc);
} else {
@@ -357,7 +357,7 @@ QWindowsOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum)
if (newEnum == nullptr)
return ResultFromScode(E_INVALIDARG);
- QWindowsOleEnumFmtEtc *result = new QWindowsOleEnumFmtEtc(m_lpfmtetcs);
+ auto *result = new QWindowsOleEnumFmtEtc(m_lpfmtetcs);
result->m_nIndex = m_nIndex;
if (result->isNull()) {
diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h
index cc6d93d35e..1416a7e575 100644
--- a/src/plugins/platforms/windows/qwindowsopenglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h
@@ -51,7 +51,7 @@ class QWindowsOpenGLContext;
class QWindowsStaticOpenGLContext
{
- Q_DISABLE_COPY(QWindowsStaticOpenGLContext)
+ Q_DISABLE_COPY_MOVE(QWindowsStaticOpenGLContext)
public:
static QWindowsStaticOpenGLContext *create();
virtual ~QWindowsStaticOpenGLContext() = default;
@@ -63,7 +63,7 @@ public:
// If the windowing system interface needs explicitly created window surfaces (like EGL),
// reimplement these.
- virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, int * /*err*/) { return 0; }
+ virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, int * /*err*/) { return nullptr; }
virtual void destroyWindowSurface(void * /*nativeSurface*/) { }
protected:
@@ -75,14 +75,14 @@ private:
class QWindowsOpenGLContext : public QPlatformOpenGLContext
{
- Q_DISABLE_COPY(QWindowsOpenGLContext)
+ Q_DISABLE_COPY_MOVE(QWindowsOpenGLContext)
public:
// Returns the native context handle (e.g. HGLRC for WGL, EGLContext for EGL).
virtual void *nativeContext() const = 0;
// These should be implemented only for some winsys interfaces, for example EGL.
// For others, like WGL, they are not relevant.
- virtual void *nativeDisplay() const { return 0; }
+ virtual void *nativeDisplay() const { return nullptr; }
virtual void *nativeConfig() const { return 0; }
protected:
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index 840a3a11c4..afc1991e2c 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -83,7 +83,7 @@ static GpuDescription adapterIdentifierToGpuDescription(const D3DADAPTER_IDENTIF
class QDirect3D9Handle
{
public:
- Q_DISABLE_COPY(QDirect3D9Handle)
+ Q_DISABLE_COPY_MOVE(QDirect3D9Handle)
QDirect3D9Handle();
~QDirect3D9Handle();
@@ -188,9 +188,9 @@ QDebug operator<<(QDebug d, const GpuDescription &gd)
{
QDebugStateSaver s(d);
d.nospace();
- d << hex << showbase << "GpuDescription(vendorId=" << gd.vendorId
+ d << Qt::hex << Qt::showbase << "GpuDescription(vendorId=" << gd.vendorId
<< ", deviceId=" << gd.deviceId << ", subSysId=" << gd.subSysId
- << dec << noshowbase << ", revision=" << gd.revision
+ << Qt::dec << Qt::noshowbase << ", revision=" << gd.revision
<< ", driver: " << gd.driverName
<< ", version=" << gd.driverVersion << ", " << gd.description
<< gd.gpuSuitableScreen << ')';
@@ -207,11 +207,11 @@ QString GpuDescription::toString() const
<< "\n Driver Name : " << driverName
<< "\n Driver Version : " << driverVersion.toString()
<< "\n Vendor ID : 0x" << qSetPadChar(QLatin1Char('0'))
- << uppercasedigits << hex << qSetFieldWidth(4) << vendorId
+ << Qt::uppercasedigits << Qt::hex << qSetFieldWidth(4) << vendorId
<< "\n Device ID : 0x" << qSetFieldWidth(4) << deviceId
<< "\n SubSys ID : 0x" << qSetFieldWidth(8) << subSysId
<< "\n Revision ID : 0x" << qSetFieldWidth(4) << revision
- << dec;
+ << Qt::dec;
if (!gpuSuitableScreen.isEmpty())
str << "\nGL windows forced to screen: " << gpuSuitableScreen;
return result;
@@ -457,7 +457,7 @@ bool QWindowsOpenGLTester::testDesktopGL()
// Check the version. If we got 1.x then it's all hopeless and we can stop right here.
typedef const GLubyte * (APIENTRY * GetString_t)(GLenum name);
- GetString_t GetString = reinterpret_cast<GetString_t>(
+ auto GetString = reinterpret_cast<GetString_t>(
reinterpret_cast<QFunctionPointer>(::GetProcAddress(lib, "glGetString")));
if (GetString) {
if (const char *versionStr = reinterpret_cast<const char *>(GetString(GL_VERSION))) {
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 8b88007949..b3d961db72 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -318,10 +318,10 @@ static QTouchDevice *createTouchDevice()
return nullptr;
const int tabletPc = GetSystemMetrics(SM_TABLETPC);
const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES);
- qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~NID_READY)
- << "Ready:" << (digitizers & NID_READY) << dec << noshowbase
+ qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY)
+ << "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase
<< "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints;
- QTouchDevice *result = new QTouchDevice;
+ auto *result = new QTouchDevice;
result->setType(digitizers & NID_INTEGRATED_TOUCH
? QTouchDevice::TouchScreen : QTouchDevice::TouchPad);
QTouchDevice::Capabilities capabilities = QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition;
@@ -351,7 +351,7 @@ void QWindowsPointerHandler::handleCaptureRelease(QWindow *window,
QEvent::Type eventType,
Qt::MouseButtons mouseButtons)
{
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+ auto *platformWindow = static_cast<QWindowsWindow *>(window->handle());
// Qt expects the platform plugin to capture the mouse on any button press until release.
if (!platformWindow->hasMouseCapture() && eventType == QEvent::MouseButtonPress) {
@@ -387,7 +387,7 @@ void QWindowsPointerHandler::handleEnterLeave(QWindow *window,
QWindow *currentWindowUnderPointer,
QPoint globalPos)
{
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+ auto *platformWindow = static_cast<QWindowsWindow *>(window->handle());
const bool hasCapture = platformWindow->hasMouseCapture();
// No enter or leave events are sent as long as there is an autocapturing window.
@@ -471,26 +471,26 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
if (!screen)
return false;
- POINTER_TOUCH_INFO *touchInfo = static_cast<POINTER_TOUCH_INFO *>(vTouchInfo);
+ auto *touchInfo = static_cast<POINTER_TOUCH_INFO *>(vTouchInfo);
const QRect screenGeometry = screen->geometry();
QList<QWindowSystemInterface::TouchPoint> touchPoints;
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaEvents).noquote().nospace() << showbase
+ qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase
<< __FUNCTION__
- << " message=" << hex << msg.message
- << " count=" << dec << count;
+ << " message=" << Qt::hex << msg.message
+ << " count=" << Qt::dec << count;
- Qt::TouchPointStates allStates = 0;
+ Qt::TouchPointStates allStates = nullptr;
for (quint32 i = 0; i < count; ++i) {
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaEvents).noquote().nospace() << showbase
+ qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase
<< " TouchPoint id=" << touchInfo[i].pointerInfo.pointerId
<< " frame=" << touchInfo[i].pointerInfo.frameId
- << " flags=" << hex << touchInfo[i].pointerInfo.pointerFlags;
+ << " flags=" << Qt::hex << touchInfo[i].pointerInfo.pointerFlags;
QWindowSystemInterface::TouchPoint touchPoint;
const quint32 pointerId = touchInfo[i].pointerInfo.pointerId;
@@ -551,13 +551,13 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
if (et & QtWindows::NonClientEventFlag)
return false; // Let DefWindowProc() handle Non Client messages.
- POINTER_PEN_INFO *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
+ auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
RECT pRect, dRect;
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
return false;
- const qint64 sourceDevice = (qint64)penInfo->pointerInfo.sourceDevice;
+ const auto sourceDevice = (qint64)penInfo->pointerInfo.sourceDevice;
const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y);
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left)
@@ -572,11 +572,11 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
const int z = 0;
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaEvents).noquote().nospace() << showbase
+ qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase
<< __FUNCTION__ << " sourceDevice=" << sourceDevice
<< " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos
- << " message=" << hex << msg.message
- << " flags=" << hex << penInfo->pointerInfo.pointerFlags;
+ << " message=" << Qt::hex << msg.message
+ << " flags=" << Qt::hex << penInfo->pointerInfo.pointerFlags;
const QTabletEvent::TabletDevice device = QTabletEvent::Stylus;
QTabletEvent::PointerType type;
@@ -697,7 +697,13 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
{
*result = 0;
- const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
+ QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
+ if ((et & QtWindows::NonClientEventFlag) == 0 && QWindowsBaseWindow::isRtlLayout(hwnd)) {
+ RECT clientArea;
+ GetClientRect(hwnd, &clientArea);
+ eventPos.setX(clientArea.right - eventPos.x());
+ }
+
QPoint localPos;
QPoint globalPos;
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h
index ccbb1d3939..068e804007 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.h
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.h
@@ -55,7 +55,7 @@ class QTouchDevice;
class QWindowsPointerHandler
{
- Q_DISABLE_COPY(QWindowsPointerHandler)
+ Q_DISABLE_COPY_MOVE(QWindowsPointerHandler)
public:
QWindowsPointerHandler() = default;
bool translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result);
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index cc0f3c1a6e..d919d97211 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -72,7 +72,7 @@ static inline QDpi monitorDPI(HMONITOR hMonitor)
return {0, 0};
}
-typedef QList<QWindowsScreenData> WindowsScreenDataList;
+using WindowsScreenDataList = QList<QWindowsScreenData>;
static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
{
@@ -120,7 +120,7 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
{
QWindowsScreenData data;
if (monitorData(hMonitor, &data)) {
- WindowsScreenDataList *result = reinterpret_cast<WindowsScreenDataList *>(p);
+ auto *result = reinterpret_cast<WindowsScreenDataList *>(p);
// QWindowSystemInterface::handleScreenAdded() documentation specifies that first
// added screen will be the primary screen, so order accordingly.
// Note that the side effect of this policy is that there is no way to change primary
@@ -323,6 +323,11 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData)
}
}
+HMONITOR QWindowsScreen::handle() const
+{
+ return m_data.hMonitor;
+}
+
QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScreen::virtualGeometry()
{
QRect result;
@@ -547,7 +552,7 @@ bool QWindowsScreenManager::handleScreenChanges()
if (existingIndex != -1) {
m_screens.at(existingIndex)->handleChanges(newData);
} else {
- QWindowsScreen *newScreen = new QWindowsScreen(newData);
+ auto *newScreen = new QWindowsScreen(newData);
m_screens.push_back(newScreen);
QWindowSystemInterface::handleScreenAdded(newScreen,
newData.flags & QWindowsScreenData::PrimaryScreen);
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 8ad012512e..0ccebf6d71 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -76,7 +76,7 @@ class QWindowsScreen : public QPlatformScreen
{
public:
#ifndef QT_NO_CURSOR
- typedef QScopedPointer<QPlatformCursor> CursorPtr;
+ using CursorPtr = QScopedPointer<QPlatformCursor>;
#endif
explicit QWindowsScreen(const QWindowsScreenData &data);
@@ -104,6 +104,8 @@ public:
inline void handleChanges(const QWindowsScreenData &newData);
+ HMONITOR handle() const;
+
#ifndef QT_NO_CURSOR
QPlatformCursor *cursor() const override { return m_cursor.data(); }
const CursorPtr &cursorPtr() const { return m_cursor; }
@@ -125,7 +127,7 @@ private:
class QWindowsScreenManager
{
public:
- typedef QList<QWindowsScreen *> WindowsScreenList;
+ using WindowsScreenList = QList<QWindowsScreen *>;
QWindowsScreenManager();
diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp
index 9504513a5e..b2b1dee232 100644
--- a/src/plugins/platforms/windows/qwindowsservices.cpp
+++ b/src/plugins/platforms/windows/qwindowsservices.cpp
@@ -57,7 +57,7 @@ static inline bool shellExecute(const QUrl &url)
const QString nativeFilePath = url.isLocalFile() && !url.hasFragment() && !url.hasQuery()
? QDir::toNativeSeparators(url.toLocalFile())
: url.toString(QUrl::FullyEncoded);
- const quintptr result =
+ const auto result =
reinterpret_cast<quintptr>(ShellExecute(nullptr, nullptr,
reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()),
nullptr, nullptr, SW_SHOWNORMAL));
diff --git a/src/plugins/platforms/windows/qwindowssessionmanager.h b/src/plugins/platforms/windows/qwindowssessionmanager.h
index 4c4256f2b0..0769ed1fce 100644
--- a/src/plugins/platforms/windows/qwindowssessionmanager.h
+++ b/src/plugins/platforms/windows/qwindowssessionmanager.h
@@ -79,7 +79,7 @@ private:
bool m_blockUserInput = false;
bool m_canceled = false;
- Q_DISABLE_COPY(QWindowsSessionManager)
+ Q_DISABLE_COPY_MOVE(QWindowsSessionManager)
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
index c0f4e4d014..f2dba4d06b 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
@@ -117,7 +117,7 @@ struct QWindowsHwndSystemTrayIconEntry
QWindowsSystemTrayIcon *trayIcon;
};
-typedef QVector<QWindowsHwndSystemTrayIconEntry> HwndTrayIconEntries;
+using HwndTrayIconEntries = QVector<QWindowsHwndSystemTrayIconEntry>;
Q_GLOBAL_STATIC(HwndTrayIconEntries, hwndTrayIconEntries)
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index fa209f09c4..cd5a78abb6 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -146,13 +146,13 @@ QDebug operator<<(QDebug d, const LOGCONTEXT &lc)
QDebugStateSaver saver(d);
d.nospace();
d << "LOGCONTEXT(\"" << QString::fromWCharArray(lc.lcName) << "\", options=0x"
- << hex << lc.lcOptions << dec;
+ << Qt::hex << lc.lcOptions << Qt::dec;
formatOptions(d, lc.lcOptions);
- d << ", status=0x" << hex << lc.lcStatus << ", device=0x" << lc.lcDevice
- << dec << ", PktRate=" << lc.lcPktRate
+ d << ", status=0x" << Qt::hex << lc.lcStatus << ", device=0x" << lc.lcDevice
+ << Qt::dec << ", PktRate=" << lc.lcPktRate
<< ", PktData=" << lc.lcPktData << ", PktMode=" << lc.lcPktMode
- << ", MoveMask=0x" << hex << lc.lcMoveMask << ", BtnDnMask=0x" << lc.lcBtnDnMask
- << ", BtnUpMask=0x" << lc.lcBtnUpMask << dec << ", SysMode=" << lc.lcSysMode
+ << ", MoveMask=0x" << Qt::hex << lc.lcMoveMask << ", BtnDnMask=0x" << lc.lcBtnDnMask
+ << ", BtnUpMask=0x" << lc.lcBtnUpMask << Qt::dec << ", SysMode=" << lc.lcSysMode
<< ", InOrg=(" << lc.lcInOrgX << ", " << lc.lcInOrgY << ", " << lc.lcInOrgZ
<< "), InExt=(" << lc.lcInExtX << ", " << lc.lcInExtY << ", " << lc.lcInExtZ
<< ") OutOrg=(" << lc.lcOutOrgX << ", " << lc.lcOutOrgY << ", "
@@ -305,7 +305,7 @@ QString QWindowsTabletSupport::description() const
<< '.' << (specificationVersion & 0xFF) << " implementation: v"
<< (implementationVersion >> 8) << '.' << (implementationVersion & 0xFF)
<< ' ' << devices << " device(s), " << cursors << " cursor(s), "
- << extensions << " extensions" << ", options: 0x" << hex << opts << dec;
+ << extensions << " extensions" << ", options: 0x" << Qt::hex << opts << Qt::dec;
formatOptions(str, opts);
if (m_tiltSupport)
str << " tilt";
@@ -435,6 +435,27 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
m_currentDevice = m_devices.size();
m_devices.push_back(tabletInit(uniqueId, cursorType));
}
+
+ /**
+ * We should check button map for changes on every proximity event, not
+ * only during initialization phase.
+ *
+ * WARNING: in 2016 there were some Wacom table drivers, which could mess up
+ * button mapping if the remapped button was pressed, while the
+ * application **didn't have input focus**. This bug is somehow
+ * related to the fact that Wacom drivers allow user to configure
+ * per-application button-mappings. If the bug shows up again,
+ * just move this button-map fetching into initialization block.
+ *
+ * See https://bugs.kde.org/show_bug.cgi?id=359561
+ */
+ BYTE logicalButtons[32];
+ memset(logicalButtons, 0, 32);
+ m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_SYSBTNMAP, &logicalButtons);
+ m_devices[m_currentDevice].buttonsMap[0x1] = logicalButtons[0];
+ m_devices[m_currentDevice].buttonsMap[0x2] = logicalButtons[1];
+ m_devices[m_currentDevice].buttonsMap[0x4] = logicalButtons[2];
+
m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor);
m_state = PenProximity;
qCDebug(lcQpaTablet) << "enter proximity for device #"
@@ -446,6 +467,52 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
return true;
}
+Qt::MouseButton buttonValueToEnum(DWORD button,
+ const QWindowsTabletDeviceData &tdd) {
+
+ enum : unsigned {
+ leftButtonValue = 0x1,
+ middleButtonValue = 0x2,
+ rightButtonValue = 0x4,
+ doubleClickButtonValue = 0x7
+ };
+
+ button = tdd.buttonsMap.value(button);
+
+ return button == leftButtonValue ? Qt::LeftButton :
+ button == rightButtonValue ? Qt::RightButton :
+ button == doubleClickButtonValue ? Qt::MiddleButton :
+ button == middleButtonValue ? Qt::MiddleButton :
+ button ? Qt::LeftButton /* fallback item */ :
+ Qt::NoButton;
+}
+
+Qt::MouseButtons convertTabletButtons(DWORD btnNew,
+ const QWindowsTabletDeviceData &tdd) {
+
+ Qt::MouseButtons buttons = Qt::NoButton;
+ for (unsigned int i = 0; i < 3; i++) {
+ unsigned int btn = 0x1 << i;
+
+ if (btn & btnNew) {
+ Qt::MouseButton convertedButton =
+ buttonValueToEnum(btn, tdd);
+
+ buttons |= convertedButton;
+
+ /**
+ * If a button that is present in hardware input is
+ * mapped to a Qt::NoButton, it means that it is going
+ * to be eaten by the driver, for example by its
+ * "Pan/Scroll" feature. Therefore we shouldn't handle
+ * any of the events associated to it. We'll just return
+ * Qt::NoButtons here.
+ */
+ }
+ }
+ return buttons;
+}
+
bool QWindowsTabletSupport::translateTabletPacketEvent()
{
static PACKET localPacketBuf[TabletPacketQSize]; // our own tablet packet queue.
@@ -552,9 +619,12 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
<< tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation;
}
+ Qt::MouseButtons buttons =
+ convertTabletButtons(packet.pkButtons, m_devices.at(m_currentDevice));
+
QWindowSystemInterface::handleTabletEvent(target, packet.pkTime, QPointF(localPos), globalPosF,
currentDevice, currentPointer,
- static_cast<Qt::MouseButtons>(packet.pkButtons),
+ buttons,
pressureNew, tiltX, tiltY,
tangentialPressure, rotation, z,
uniqueId,
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h
index d91701d6a5..6bcf3357a5 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.h
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.h
@@ -45,6 +45,7 @@
#include <QtCore/qvector.h>
#include <QtCore/qpoint.h>
+#include <QtCore/qhash.h>
#include <wintab.h>
@@ -100,6 +101,7 @@ struct QWindowsTabletDeviceData
qint64 uniqueId = 0;
int currentDevice = 0;
int currentPointerType = 0;
+ QHash<quint8, quint8> buttonsMap;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -108,7 +110,7 @@ QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t);
class QWindowsTabletSupport
{
- Q_DISABLE_COPY(QWindowsTabletSupport)
+ Q_DISABLE_COPY_MOVE(QWindowsTabletSupport)
explicit QWindowsTabletSupport(HWND window, HCTX context);
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 6dd3e6ed56..437c9562ab 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -162,25 +162,19 @@ public:
m_init = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
QMutexLocker readyLocker(&m_readyMutex);
- while (!m_cancelled.load()) {
- if (!m_params && !m_cancelled.load()
+ while (!m_cancelled.loadRelaxed()) {
+ if (!m_params && !m_cancelled.loadRelaxed()
&& !m_readyCondition.wait(&m_readyMutex, 1000))
continue;
if (m_params) {
const QString fileName = m_params->fileName;
SHFILEINFO info;
-#ifndef Q_OS_WINCE
- const UINT oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
-#endif
const bool result = SHGetFileInfo(reinterpret_cast<const wchar_t *>(fileName.utf16()),
m_params->attributes, &info, sizeof(SHFILEINFO),
m_params->flags);
-#ifndef Q_OS_WINCE
- SetErrorMode(oldErrorMode);
-#endif
m_doneMutex.lock();
- if (!m_cancelled.load()) {
+ if (!m_cancelled.loadRelaxed()) {
*m_params->result = result;
memcpy(m_params->info, &info, sizeof(SHFILEINFO));
}
@@ -210,7 +204,7 @@ public:
void cancel()
{
QMutexLocker doneLocker(&m_doneMutex);
- m_cancelled.store(1);
+ m_cancelled.storeRelaxed(1);
m_readyCondition.wakeAll();
}
@@ -284,24 +278,24 @@ static inline QPalette systemPalette()
result.setColor(QPalette::Link, Qt::blue);
result.setColor(QPalette::LinkVisited, Qt::magenta);
result.setColor(QPalette::Inactive, QPalette::Button, result.button().color());
- result.setColor(QPalette::Inactive, QPalette::Window, result.background().color());
+ result.setColor(QPalette::Inactive, QPalette::Window, result.window().color());
result.setColor(QPalette::Inactive, QPalette::Light, result.light().color());
result.setColor(QPalette::Inactive, QPalette::Dark, result.dark().color());
if (result.midlight() == result.button())
result.setColor(QPalette::Midlight, result.button().color().lighter(110));
- if (result.background() != result.base()) {
+ if (result.window() != result.base()) {
result.setColor(QPalette::Inactive, QPalette::Highlight, result.color(QPalette::Inactive, QPalette::Window));
result.setColor(QPalette::Inactive, QPalette::HighlightedText, result.color(QPalette::Inactive, QPalette::Text));
}
const QColor disabled =
- mixColors(result.foreground().color(), result.button().color());
+ mixColors(result.windowText().color(), result.button().color());
- result.setColorGroup(QPalette::Disabled, result.foreground(), result.button(),
+ result.setColorGroup(QPalette::Disabled, result.windowText(), result.button(),
result.light(), result.dark(), result.mid(),
result.text(), result.brightText(), result.base(),
- result.background());
+ result.window());
result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
result.setColor(QPalette::Disabled, QPalette::Text, disabled);
result.setColor(QPalette::Disabled, QPalette::ButtonText, disabled);
@@ -310,7 +304,7 @@ static inline QPalette systemPalette()
result.setColor(QPalette::Disabled, QPalette::HighlightedText,
getSysColor(COLOR_HIGHLIGHTTEXT));
result.setColor(QPalette::Disabled, QPalette::Base,
- result.background().color());
+ result.window().color());
return result;
}
@@ -333,7 +327,7 @@ static inline QPalette toolTipPalette(const QPalette &systemPalette)
result.setColor(QPalette::All, QPalette::ToolTipBase, tipBgColor);
result.setColor(QPalette::All, QPalette::ToolTipText, tipTextColor);
const QColor disabled =
- mixColors(result.foreground().color(), result.button().color());
+ mixColors(result.windowText().color(), result.button().color());
result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
result.setColor(QPalette::Disabled, QPalette::Text, disabled);
result.setColor(QPalette::Disabled, QPalette::ToolTipText, disabled);
@@ -589,7 +583,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon);
static QPixmap loadIconFromShell32(int resourceId, QSizeF size)
{
if (const HMODULE hmod = QSystemLibrary::load(L"shell32")) {
- HICON iconHandle =
+ auto iconHandle =
static_cast<HICON>(LoadImage(hmod, MAKEINTRESOURCE(resourceId),
IMAGE_ICON, int(size.width()), int(size.height()), 0));
if (iconHandle) {
@@ -858,7 +852,8 @@ QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon
int iIcon = (useDefaultFolderIcon && defaultFolderIIcon >= 0) ? defaultFolderIIcon
: **dirIconEntryCache.object(filePath);
if (iIcon) {
- QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize, requestedImageListSize), pixmap);
+ QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize, requestedImageListSize),
+ &pixmap);
if (pixmap.isNull()) // Let's keep both caches in sync
dirIconEntryCache.remove(filePath);
else
@@ -889,7 +884,7 @@ QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon
//using the unique icon index provided by windows save us from duplicate keys
key = dirIconPixmapCacheKey(info.iIcon, iconSize, requestedImageListSize);
- QPixmapCache::find(key, pixmap);
+ QPixmapCache::find(key, &pixmap);
if (!pixmap.isNull()) {
QMutexLocker locker(&mx);
dirIconEntryCache.insert(filePath, FakePointer<int>::create(info.iIcon));
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index c132f20167..4e24308445 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -51,7 +51,7 @@ class QWindow;
class QWindowsTheme : public QPlatformTheme
{
- Q_DISABLE_COPY(QWindowsTheme)
+ Q_DISABLE_COPY_MOVE(QWindowsTheme)
public:
QWindowsTheme();
~QWindowsTheme() override;
@@ -71,7 +71,7 @@ public:
QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
- QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions = 0) const override;
+ QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions = nullptr) const override;
void windowsThemeChanged(QWindow *window);
void displayChanged() { refreshIconPixmapSizes(); }
diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
index 731e4b5432..ffe2e62069 100644
--- a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
+++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
*/
class QWindowsThreadPoolRunner
{
- Q_DISABLE_COPY(QWindowsThreadPoolRunner)
+ Q_DISABLE_COPY_MOVE(QWindowsThreadPoolRunner)
#if QT_CONFIG(thread)
template <class RunnableFunction> // nested class implementing QRunnable to execute a function.
diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
index 7a01483abd..812ea8193a 100644
--- a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
+++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
@@ -81,7 +81,7 @@ bool QWindowsVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice,
VkSurfaceKHR QWindowsVulkanInstance::createSurface(HWND win)
{
- VkSurfaceKHR surface = 0;
+ VkSurfaceKHR surface = VK_NULL_HANDLE;
if (!m_createSurface) {
m_createSurface = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>(
diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.h b/src/plugins/platforms/windows/qwindowsvulkaninstance.h
index 3292137c39..cc7ef476d4 100644
--- a/src/plugins/platforms/windows/qwindowsvulkaninstance.h
+++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.h
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
class QWindowsVulkanInstance : public QBasicPlatformVulkanInstance
{
- Q_DISABLE_COPY(QWindowsVulkanInstance)
+ Q_DISABLE_COPY_MOVE(QWindowsVulkanInstance)
public:
QWindowsVulkanInstance(QVulkanInstance *instance);
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index eb521dac52..5db7deeef6 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -86,7 +86,7 @@
QT_BEGIN_NAMESPACE
-typedef QSharedPointer<QWindowCreationContext> QWindowCreationContextPtr;
+using QWindowCreationContextPtr = QSharedPointer<QWindowCreationContext>;
enum {
defaultWindowWidth = 160,
@@ -134,6 +134,10 @@ static QByteArray debugWinExStyle(DWORD exStyle)
rc += " WS_EX_LAYERED";
if (exStyle & WS_EX_DLGMODALFRAME)
rc += " WS_EX_DLGMODALFRAME";
+ if (exStyle & WS_EX_LAYOUTRTL)
+ rc += " WS_EX_LAYOUTRTL";
+ if (exStyle & WS_EX_NOINHERITLAYOUT)
+ rc += " WS_EX_NOINHERITLAYOUT";
return rc;
}
@@ -239,7 +243,7 @@ QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp)
QDebugStateSaver saver(d);
d.nospace();
d.noquote();
- d << "WINDOWPLACEMENT(flags=0x" << hex << wp.flags << dec << ", showCmd="
+ d << "WINDOWPLACEMENT(flags=0x" << Qt::hex << wp.flags << Qt::dec << ", showCmd="
<< wp.showCmd << ", ptMinPosition=" << wp.ptMinPosition << ", ptMaxPosition=" << wp.ptMaxPosition
<< ", rcNormalPosition=" << wp.rcNormalPosition;
return d;
@@ -249,7 +253,7 @@ QDebug operator<<(QDebug d, const GUID &guid)
{
QDebugStateSaver saver(d);
d.nospace();
- d << '{' << hex << uppercasedigits << qSetPadChar(QLatin1Char('0'))
+ d << '{' << Qt::hex << Qt::uppercasedigits << qSetPadChar(QLatin1Char('0'))
<< qSetFieldWidth(8) << guid.Data1
<< qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
<< guid.Data2 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
@@ -307,7 +311,7 @@ static inline QRect frameGeometry(HWND hwnd, bool topLevel)
const int width = rect.right - rect.left;
const int height = rect.bottom - rect.top;
POINT leftTop = { rect.left, rect.top };
- ScreenToClient(parent, &leftTop);
+ screenToClient(parent, &leftTop);
rect.left = leftTop.x;
rect.top = leftTop.y;
rect.right = leftTop.x + width;
@@ -490,7 +494,7 @@ static QMargins invisibleMargins(QPoint screenPoint)
struct WindowCreationData
{
- typedef QWindowsWindowData WindowData;
+ using WindowData = QWindowsWindowData;
enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 };
void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0);
@@ -667,6 +671,17 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
if ((flags & Qt::MSWindowsFixedSizeDialogHint))
dialog = true;
+ // This causes the title bar to drawn RTL and the close button
+ // to be left. Note that this causes:
+ // - All DCs created on the Window to have RTL layout (see SetLayout)
+ // - ClientToScreen() and ScreenToClient() to work in reverse as well.
+ // - Mouse event coordinates to be mirrored.
+ // - Positioning of child Windows.
+ if (QGuiApplication::layoutDirection() == Qt::RightToLeft
+ && (QWindowsIntegration::instance()->options() & QWindowsIntegration::RtlEnabled) != 0) {
+ exStyle |= WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT;
+ }
+
// Parent: Use transient parent for top levels.
if (popup) {
flags |= Qt::WindowStaysOnTopHint; // a popup stays on top, no parent.
@@ -749,8 +764,8 @@ QWindowsWindowData
if (title.isEmpty() && (result.flags & Qt::WindowTitleHint))
title = topLevel ? qAppName() : w->objectName();
- const wchar_t *titleUtf16 = reinterpret_cast<const wchar_t *>(title.utf16());
- const wchar_t *classNameUtf16 = reinterpret_cast<const wchar_t *>(windowClassName.utf16());
+ const auto *titleUtf16 = reinterpret_cast<const wchar_t *>(title.utf16());
+ const auto *classNameUtf16 = reinterpret_cast<const wchar_t *>(windowClassName.utf16());
// Capture events before CreateWindowEx() returns. The context is cleared in
// the QWindowsWindow constructor.
@@ -772,6 +787,16 @@ QWindowsWindowData
QPoint pos = calcPosition(w, context, invMargins);
+ // Mirror the position when creating on a parent in RTL mode, ditto for the obtained geometry.
+ int mirrorParentWidth = 0;
+ if (!w->isTopLevel() && QWindowsBaseWindow::isRtlLayout(parentHandle)) {
+ RECT rect;
+ GetClientRect(parentHandle, &rect);
+ mirrorParentWidth = rect.right;
+ }
+ if (mirrorParentWidth != 0 && pos.x() != CW_USEDEFAULT && context->frameWidth != CW_USEDEFAULT)
+ pos.setX(mirrorParentWidth - context->frameWidth - pos.x());
+
result.hwnd = CreateWindowEx(exStyle, classNameUtf16, titleUtf16,
style,
pos.x(), pos.y(),
@@ -779,14 +804,21 @@ QWindowsWindowData
parentHandle, nullptr, appinst, nullptr);
qCDebug(lcQpaWindows).nospace()
<< "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: "
- << context->obtainedGeometry << ' ' << context->margins;
+ << context->obtainedPos << context->obtainedSize << ' ' << context->margins;
if (!result.hwnd) {
qErrnoWarning("%s: CreateWindowEx failed", __FUNCTION__);
return result;
}
- result.geometry = context->obtainedGeometry;
+ if (mirrorParentWidth != 0) {
+ context->obtainedPos.setX(mirrorParentWidth - context->obtainedSize.width()
+ - context->obtainedPos.x());
+ }
+
+ QRect obtainedGeometry(context->obtainedPos, context->obtainedSize);
+
+ result.geometry = obtainedGeometry;
result.fullFrameMargins = context->margins;
result.embedded = embedded;
result.hasFrame = hasFrame;
@@ -905,7 +937,7 @@ QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle, qreal dpi)
const QMargins result(qAbs(rect.left), qAbs(rect.top),
qAbs(rect.right), qAbs(rect.bottom));
qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << " style="
- << showbase << hex << style << " exStyle=" << exStyle << dec << noshowbase
+ << Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase
<< " dpi=" << dpi
<< ' ' << rect << ' ' << result;
return result;
@@ -950,7 +982,7 @@ bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, co
if (!msg.wParam || customMargins.isNull())
return false;
*result = DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
- NCCALCSIZE_PARAMS *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
+ auto *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
const RECT oldClientArea = ncp->rgrc[0];
ncp->rgrc[0].left += customMargins.left();
ncp->rgrc[0].top += customMargins.top();
@@ -1033,6 +1065,11 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
\ingroup qt-lighthouse-win
*/
+bool QWindowsBaseWindow::isRtlLayout(HWND hwnd)
+{
+ return (GetWindowLongPtrW(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0;
+}
+
QWindowsBaseWindow *QWindowsBaseWindow::baseWindowOf(const QWindow *w)
{
if (w) {
@@ -1195,7 +1232,9 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
DWORD style, DWORD exStyle) :
window(w),
requestedGeometryIn(geometryIn),
- requestedGeometry(geometry), obtainedGeometry(geometry),
+ requestedGeometry(geometry),
+ obtainedPos(geometryIn.topLeft()),
+ obtainedSize(geometryIn.size()),
margins(QWindowsGeometryHint::frame(w, geometry, style, exStyle)),
customMargins(cm)
{
@@ -1258,6 +1297,7 @@ void QWindowCreationContext::applyToMinMaxInfo(MINMAXINFO *mmi) const
const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle";
const char *QWindowsWindow::hasBorderInFullScreenProperty = "_q_has_border_in_fullscreen";
+bool QWindowsWindow::m_borderInFullScreenDefault = false;
QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) :
QWindowsBaseWindow(aWindow),
@@ -1265,7 +1305,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
m_cursor(new CursorHandle),
m_format(aWindow->requestedFormat())
#if QT_CONFIG(vulkan)
- , m_vkSurface(0)
+ , m_vkSurface(VK_NULL_HANDLE)
#endif
{
QWindowsContext::instance()->addWindow(m_data.hwnd, this);
@@ -1295,7 +1335,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
if (aWindow->isTopLevel())
setWindowIcon(aWindow->icon());
- if (aWindow->property(hasBorderInFullScreenProperty).toBool())
+ if (m_borderInFullScreenDefault || aWindow->property(hasBorderInFullScreenProperty).toBool())
setFlag(HasBorderInFullScreen);
clearFlag(WithinCreate);
}
@@ -1322,11 +1362,12 @@ void QWindowsWindow::initialize()
// will send the message) and screen change signals of QWindow.
if (w->type() != Qt::Desktop) {
const Qt::WindowState state = w->windowState();
+ const QRect obtainedGeometry(creationContext->obtainedPos, creationContext->obtainedSize);
if (state != Qt::WindowMaximized && state != Qt::WindowFullScreen
- && creationContext->requestedGeometryIn != creationContext->obtainedGeometry) {
- QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, creationContext->obtainedGeometry);
+ && creationContext->requestedGeometryIn != obtainedGeometry) {
+ QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
}
- QPlatformScreen *obtainedScreen = screenForGeometry(creationContext->obtainedGeometry);
+ QPlatformScreen *obtainedScreen = screenForGeometry(obtainedGeometry);
if (obtainedScreen && screen() != obtainedScreen)
QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(w, obtainedScreen->screen());
}
@@ -1365,14 +1406,14 @@ void QWindowsWindow::destroyWindow()
QVulkanInstance *inst = window()->vulkanInstance();
if (inst)
static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
- m_vkSurface = 0;
+ m_vkSurface = VK_NULL_HANDLE;
}
#endif
#ifndef QT_NO_OPENGL
if (m_surface) {
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
staticOpenGLContext->destroyWindowSurface(m_surface);
- m_surface = 0;
+ m_surface = nullptr;
}
#endif
DestroyWindow(m_data.hwnd);
@@ -1461,7 +1502,7 @@ QWindow *QWindowsWindow::topLevelOf(QWindow *w)
w = parent;
if (const QPlatformWindow *handle = w->handle()) {
- const QWindowsWindow *ww = static_cast<const QWindowsWindow *>(handle);
+ const auto *ww = static_cast<const QWindowsWindow *>(handle);
if (ww->isEmbedded()) {
HWND parentHWND = GetAncestor(ww->handle(), GA_PARENT);
const HWND desktopHwnd = GetDesktopWindow();
@@ -1535,7 +1576,7 @@ bool QWindowsWindow::isActive() const
bool QWindowsWindow::isAncestorOf(const QPlatformWindow *child) const
{
- const QWindowsWindow *childWindow = static_cast<const QWindowsWindow *>(child);
+ const auto *childWindow = static_cast<const QWindowsWindow *>(child);
return IsChild(m_data.hwnd, childWindow->handle());
}
@@ -1684,7 +1725,7 @@ void QWindowsWindow::setParent_sys(const QPlatformWindow *parent)
HWND oldParentHWND = parentHwnd();
HWND newParentHWND = nullptr;
if (parent) {
- const QWindowsWindow *parentW = static_cast<const QWindowsWindow *>(parent);
+ const auto *parentW = static_cast<const QWindowsWindow *>(parent);
newParentHWND = parentW->handle();
}
@@ -1943,7 +1984,16 @@ void QWindowsBaseWindow::setGeometry_sys(const QRect &rect) const
windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
result = SetWindowPlacement(hwnd, &windowPlacement);
} else {
- result = MoveWindow(hwnd, frameGeometry.x(), frameGeometry.y(),
+ int x = frameGeometry.x();
+ if (!window()->isTopLevel()) {
+ const HWND parentHandle = GetParent(hwnd);
+ if (isRtlLayout(parentHandle)) {
+ RECT rect;
+ GetClientRect(parentHandle, &rect);
+ x = rect.right - frameGeometry.width() - x;
+ }
+ }
+ result = MoveWindow(hwnd, x, frameGeometry.y(),
frameGeometry.width(), frameGeometry.height(), true);
}
qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << window()
@@ -1959,8 +2009,11 @@ void QWindowsBaseWindow::setGeometry_sys(const QRect &rect) const
HDC QWindowsWindow::getDC()
{
- if (!m_hdc)
+ if (!m_hdc) {
m_hdc = GetDC(handle());
+ if (QGuiApplication::layoutDirection() == Qt::RightToLeft)
+ SetLayout(m_hdc, 0); // Clear RTL layout
+ }
return m_hdc;
}
@@ -2315,7 +2368,7 @@ void QWindowsWindow::propagateSizeHints()
bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &margins)
{
- WINDOWPOS *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam);
+ auto *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam);
if ((windowPos->flags & SWP_NOZORDER) == 0) {
if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(qWindow)) {
QWindow *parentWindow = qWindow->parent();
@@ -2892,14 +2945,14 @@ void QWindowsWindow::invalidateSurface()
QVulkanInstance *inst = window()->vulkanInstance();
if (inst)
static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
- m_vkSurface = 0;
+ m_vkSurface = VK_NULL_HANDLE;
}
#endif
#ifndef QT_NO_OPENGL
if (m_surface) {
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
staticOpenGLContext->destroyWindowSurface(m_surface);
- m_surface = 0;
+ m_surface = nullptr;
}
#endif // QT_NO_OPENGL
}
@@ -2954,6 +3007,11 @@ void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border
window->setProperty(hasBorderInFullScreenProperty, QVariant(border));
}
+void QWindowsWindow::setHasBorderInFullScreenDefault(bool border)
+{
+ m_borderInFullScreenDefault = border;
+}
+
void QWindowsWindow::setHasBorderInFullScreen(bool border)
{
if (testFlag(HasBorderInFullScreen) == border)
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index ce67e46df3..7efbcf900c 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -89,7 +89,8 @@ struct QWindowCreationContext
const QWindow *window;
QRect requestedGeometryIn; // QWindow scaled
QRect requestedGeometry; // after QPlatformWindow::initialGeometry()
- QRect obtainedGeometry;
+ QPoint obtainedPos;
+ QSize obtainedSize;
QMargins margins;
QMargins customMargins; // User-defined, additional frame for WM_NCCALCSIZE
int frameX = CW_USEDEFAULT; // Passed on to CreateWindowEx(), including frame.
@@ -105,7 +106,7 @@ struct QWindowsWindowData
QRect geometry;
QMargins fullFrameMargins; // Do not use directly for windows, see FrameDirty.
QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
- HWND hwnd = 0;
+ HWND hwnd = nullptr;
bool embedded = false;
bool hasFrame = false;
@@ -116,7 +117,7 @@ struct QWindowsWindowData
class QWindowsBaseWindow : public QPlatformWindow
{
- Q_DISABLE_COPY(QWindowsBaseWindow)
+ Q_DISABLE_COPY_MOVE(QWindowsBaseWindow)
public:
explicit QWindowsBaseWindow(QWindow *window) : QPlatformWindow(window) {}
@@ -134,6 +135,7 @@ public:
unsigned style() const { return GetWindowLongPtr(handle(), GWL_STYLE); }
unsigned exStyle() const { return GetWindowLongPtr(handle(), GWL_EXSTYLE); }
+ static bool isRtlLayout(HWND hwnd);
static QWindowsBaseWindow *baseWindowOf(const QWindow *w);
static HWND handleOf(const QWindow *w);
@@ -340,6 +342,7 @@ public:
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
static void setHasBorderInFullScreenStatic(QWindow *window, bool border);
+ static void setHasBorderInFullScreenDefault(bool border);
void setHasBorderInFullScreen(bool border);
static QString formatWindowTitle(const QString &title);
@@ -354,7 +357,7 @@ private:
inline void setParent_sys(const QPlatformWindow *parent);
inline void updateTransientParent() const;
void destroyWindow();
- inline bool isDropSiteEnabled() const { return m_dropTarget != 0; }
+ inline bool isDropSiteEnabled() const { return m_dropTarget != nullptr; }
void setDropSiteEnabled(bool enabled);
void updateDropSite(bool topLevel);
void handleGeometryChange();
@@ -365,7 +368,7 @@ private:
mutable QWindowsWindowData m_data;
QPointer<QWindowsMenuBar> m_menuBar;
mutable unsigned m_flags = WithinCreate;
- HDC m_hdc = 0;
+ HDC m_hdc = nullptr;
Qt::WindowStates m_windowState = Qt::WindowNoState;
qreal m_opacity = 1;
#ifndef QT_NO_CURSOR
@@ -375,16 +378,17 @@ private:
unsigned m_savedStyle = 0;
QRect m_savedFrameGeometry;
const QSurfaceFormat m_format;
- HICON m_iconSmall = 0;
- HICON m_iconBig = 0;
+ HICON m_iconSmall = nullptr;
+ HICON m_iconBig = nullptr;
void *m_surface = nullptr;
static bool m_screenForGLInitialized;
#if QT_CONFIG(vulkan)
// note: intentionally not using void * in order to avoid breaking x86
- VkSurfaceKHR m_vkSurface = 0;
+ VkSurfaceKHR m_vkSurface = VK_NULL_HANDLE;
#endif
+ static bool m_borderInFullScreenDefault;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -397,18 +401,38 @@ QDebug operator<<(QDebug d, const WINDOWPOS &);
QDebug operator<<(QDebug d, const GUID &guid);
#endif // !QT_NO_DEBUG_STREAM
+static inline void clientToScreen(HWND hwnd, POINT *wP)
+{
+ if (QWindowsBaseWindow::isRtlLayout(hwnd)) {
+ RECT clientArea;
+ GetClientRect(hwnd, &clientArea);
+ wP->x = clientArea.right - wP->x;
+ }
+ ClientToScreen(hwnd, wP);
+}
+
+static inline void screenToClient(HWND hwnd, POINT *wP)
+{
+ ScreenToClient(hwnd, wP);
+ if (QWindowsBaseWindow::isRtlLayout(hwnd)) {
+ RECT clientArea;
+ GetClientRect(hwnd, &clientArea);
+ wP->x = clientArea.right - wP->x;
+ }
+}
+
// ---------- QWindowsGeometryHint inline functions.
QPoint QWindowsGeometryHint::mapToGlobal(HWND hwnd, const QPoint &qp)
{
POINT p = { qp.x(), qp.y() };
- ClientToScreen(hwnd, &p);
+ clientToScreen(hwnd, &p);
return QPoint(p.x, p.y);
}
QPoint QWindowsGeometryHint::mapFromGlobal(const HWND hwnd, const QPoint &qp)
{
POINT p = { qp.x(), qp.y() };
- ScreenToClient(hwnd, &p);
+ screenToClient(hwnd, &p);
return QPoint(p.x, p.y);
}
@@ -447,11 +471,11 @@ inline void QWindowsWindow::destroyIcon()
{
if (m_iconBig) {
DestroyIcon(m_iconBig);
- m_iconBig = 0;
+ m_iconBig = nullptr;
}
if (m_iconSmall) {
DestroyIcon(m_iconSmall);
- m_iconSmall = 0;
+ m_iconSmall = nullptr;
}
}
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
index 9caa7d6898..a20df28e3f 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
@@ -57,7 +57,7 @@ class QAccessibleInterface;
class QWindowsUiaBaseProvider : public QObject
{
Q_OBJECT
- Q_DISABLE_COPY(QWindowsUiaBaseProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaBaseProvider)
public:
explicit QWindowsUiaBaseProvider(QAccessible::Id id);
virtual ~QWindowsUiaBaseProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
index 3d17056d38..3244122038 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaGridItemProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IGridItemProvider>
{
- Q_DISABLE_COPY(QWindowsUiaGridItemProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaGridItemProvider)
public:
explicit QWindowsUiaGridItemProvider(QAccessible::Id id);
virtual ~QWindowsUiaGridItemProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
index b96fc1a93c..0e5f81108e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaGridProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IGridProvider>
{
- Q_DISABLE_COPY(QWindowsUiaGridProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaGridProvider)
public:
explicit QWindowsUiaGridProvider(QAccessible::Id id);
virtual ~QWindowsUiaGridProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
index 5fb509c5f3..7d646894a1 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaInvokeProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IInvokeProvider>
{
- Q_DISABLE_COPY(QWindowsUiaInvokeProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaInvokeProvider)
public:
explicit QWindowsUiaInvokeProvider(QAccessible::Id id);
virtual ~QWindowsUiaInvokeProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index a427e553f0..b276798316 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -82,7 +82,7 @@ QWindowsUiaMainProvider *QWindowsUiaMainProvider::providerForAccessible(QAccessi
QAccessible::Id id = QAccessible::uniqueId(accessible);
QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance();
- QWindowsUiaMainProvider *provider = qobject_cast<QWindowsUiaMainProvider *>(providerCache->providerForId(id));
+ auto *provider = qobject_cast<QWindowsUiaMainProvider *>(providerCache->providerForId(id));
if (provider) {
provider->AddRef();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
index df0d60f9c9..cdc239ed99 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
@@ -60,7 +60,7 @@ class QWindowsUiaMainProvider :
public IRawElementProviderFragmentRoot
{
Q_OBJECT
- Q_DISABLE_COPY(QWindowsUiaMainProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaMainProvider)
public:
static QWindowsUiaMainProvider *providerForAccessible(QAccessibleInterface *accessible);
explicit QWindowsUiaMainProvider(QAccessibleInterface *a, int initialRefCount = 1);
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
index c5e0a03ee5..fc82d3a2cc 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaRangeValueProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IRangeValueProvider>
{
- Q_DISABLE_COPY(QWindowsUiaRangeValueProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaRangeValueProvider)
public:
explicit QWindowsUiaRangeValueProvider(QAccessible::Id id);
virtual ~QWindowsUiaRangeValueProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
index 1f2605188b..4b59c4e40f 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaSelectionItemProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ISelectionItemProvider>
{
- Q_DISABLE_COPY(QWindowsUiaSelectionItemProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaSelectionItemProvider)
public:
explicit QWindowsUiaSelectionItemProvider(QAccessible::Id id);
virtual ~QWindowsUiaSelectionItemProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
index 0376d25804..ee1044ec7a 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaSelectionProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ISelectionProvider>
{
- Q_DISABLE_COPY(QWindowsUiaSelectionProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaSelectionProvider)
public:
explicit QWindowsUiaSelectionProvider(QAccessible::Id id);
virtual ~QWindowsUiaSelectionProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
index bf4b52ee0b..9804c35f8e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaTableItemProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ITableItemProvider>
{
- Q_DISABLE_COPY(QWindowsUiaTableItemProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaTableItemProvider)
public:
explicit QWindowsUiaTableItemProvider(QAccessible::Id id);
virtual ~QWindowsUiaTableItemProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
index 94c8ab93a7..a8b16035ec 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaTableProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ITableProvider>
{
- Q_DISABLE_COPY(QWindowsUiaTableProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaTableProvider)
public:
explicit QWindowsUiaTableProvider(QAccessible::Id id);
virtual ~QWindowsUiaTableProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
index 9d1e72fb78..50ecfc7ecd 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
@@ -100,7 +100,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetSelection(SAFEARRAY **pRet
for (LONG i = 0; i < selCount; ++i) {
int startOffset = 0, endOffset = 0;
textInterface->selection((int)i, &startOffset, &endOffset);
- QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), startOffset, endOffset);
+ auto *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), startOffset, endOffset);
SafeArrayPutElement(*pRetVal, &i, static_cast<IUnknown *>(textRangeProvider));
textRangeProvider->Release();
}
@@ -110,7 +110,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetSelection(SAFEARRAY **pRet
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1))) {
LONG i = 0;
int cursorPosition = textInterface->cursorPosition();
- QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), cursorPosition, cursorPosition);
+ auto *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), cursorPosition, cursorPosition);
SafeArrayPutElement(*pRetVal, &i, static_cast<IUnknown *>(textRangeProvider));
textRangeProvider->Release();
}
@@ -138,7 +138,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetVisibleRanges(SAFEARRAY **
// Considering the entire text as visible.
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1))) {
LONG i = 0;
- QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), 0, textInterface->characterCount());
+ auto *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), 0, textInterface->characterCount());
SafeArrayPutElement(*pRetVal, &i, static_cast<IUnknown *>(textRangeProvider));
textRangeProvider->Release();
}
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
index a9be70fa16..ffab48b0e8 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaTextProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ITextProvider2>
{
- Q_DISABLE_COPY(QWindowsUiaTextProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaTextProvider)
public:
explicit QWindowsUiaTextProvider(QAccessible::Id id);
~QWindowsUiaTextProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
index 1be186f6b3..8e395669f8 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
@@ -92,7 +92,7 @@ HRESULT QWindowsUiaTextRangeProvider::Compare(ITextRangeProvider *range, BOOL *p
if (!range || !pRetVal)
return E_INVALIDARG;
- QWindowsUiaTextRangeProvider *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(range);
+ auto *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(range);
*pRetVal = ((targetProvider->m_startOffset == m_startOffset) && (targetProvider->m_endOffset == m_endOffset));
return S_OK;
}
@@ -110,7 +110,7 @@ HRESULT QWindowsUiaTextRangeProvider::CompareEndpoints(TextPatternRangeEndpoint
if (!targetRange || !pRetVal)
return E_INVALIDARG;
- QWindowsUiaTextRangeProvider *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
+ auto *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
int point = (endpoint == TextPatternRangeEndpoint_Start) ? m_startOffset : m_endOffset;
int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
@@ -373,7 +373,7 @@ HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByRange(TextPatternRangeEndpoi
qCDebug(lcQpaUiAutomation) << __FUNCTION__
<< "endpoint=" << endpoint << "targetRange=" << targetRange << "targetEndpoint=" << targetEndpoint << "this: " << this;
- QWindowsUiaTextRangeProvider *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
+ auto *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
targetProvider->m_startOffset : targetProvider->m_endOffset;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
index 39b9069fc0..3b4ec63ceb 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaTextRangeProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ITextRangeProvider>
{
- Q_DISABLE_COPY(QWindowsUiaTextRangeProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaTextRangeProvider)
public:
explicit QWindowsUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset);
virtual ~QWindowsUiaTextRangeProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
index 2bed6f7e36..892b635b41 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaToggleProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IToggleProvider>
{
- Q_DISABLE_COPY(QWindowsUiaToggleProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaToggleProvider)
public:
explicit QWindowsUiaToggleProvider(QAccessible::Id id);
virtual ~QWindowsUiaToggleProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
index 334a17e51d..3edfe7a08b 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaValueProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IValueProvider>
{
- Q_DISABLE_COPY(QWindowsUiaValueProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaValueProvider)
public:
explicit QWindowsUiaValueProvider(QAccessible::Id id);
virtual ~QWindowsUiaValueProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/uiautomation.pri b/src/plugins/platforms/windows/uiautomation/uiautomation.pri
index 5d4fa5755b..ee9332e7ea 100644
--- a/src/plugins/platforms/windows/uiautomation/uiautomation.pri
+++ b/src/plugins/platforms/windows/uiautomation/uiautomation.pri
@@ -41,5 +41,4 @@ HEADERS += \
$$PWD/qwindowsuiawindowprovider.h \
$$PWD/qwindowsuiautils.h
-mingw: LIBS *= -luuid
-
+mingw: QMAKE_USE *= uuid
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index 7004d7e854..95ba961df1 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -1,15 +1,21 @@
# Note: OpenGL32 must precede Gdi32 as it overwrites some functions.
-LIBS += -lole32 -luser32 -lwinspool -limm32 -lwinmm -loleaut32
+LIBS += -lwinspool -limm32 -loleaut32
QT_FOR_CONFIG += gui
qtConfig(opengl):!qtConfig(opengles2):!qtConfig(dynamicgl): LIBS *= -lopengl32
-mingw: LIBS *= -luuid
+mingw: QMAKE_USE *= uuid
# For the dialog helpers:
-LIBS += -lshlwapi -lshell32 -ladvapi32 -lwtsapi32
-
-QMAKE_USE_PRIVATE += d3d9/nolink
+LIBS += -lshlwapi -lwtsapi32
+
+QMAKE_USE_PRIVATE += \
+ advapi32 \
+ d3d9/nolink \
+ ole32 \
+ shell32 \
+ user32 \
+ winmm
DEFINES *= QT_NO_CAST_FROM_ASCII QT_NO_FOREACH
diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro
index 174bc7b609..50a3bb41a9 100644
--- a/src/plugins/platforms/windows/windows.pro
+++ b/src/plugins/platforms/windows/windows.pro
@@ -8,7 +8,8 @@ QT += \
qtConfig(accessibility): QT += accessibility_support-private
qtConfig(vulkan): QT += vulkan_support-private
-LIBS += -lgdi32 -ldwmapi
+LIBS += -ldwmapi
+QMAKE_USE_PRIVATE += gdi32
include(windows.pri)
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index e611c7be24..0d77889a36 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -1097,7 +1097,7 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
d->currentTargetWindow = topWindow();
if (d->mouseGrabWindow)
- d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+ d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window();
qCDebug(lcQpaEvents) << __FUNCTION__ << "handleEnterEvent" << d->currentTargetWindow << pos;
QWindowSystemInterface::handleEnterEvent(d->currentTargetWindow, pos, pos);
@@ -1121,7 +1121,7 @@ HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args)
d->touchPoints.remove(id);
if (d->mouseGrabWindow)
- d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+ d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window();
qCDebug(lcQpaEvents) << __FUNCTION__ << "handleLeaveEvent" << d->currentTargetWindow;
QWindowSystemInterface::handleLeaveEvent(d->currentTargetWindow);
@@ -1152,7 +1152,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
d->currentTargetWindow = windowUnderPointer;
if (d->mouseGrabWindow)
- d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+ d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window();
if (d->currentTargetWindow) {
const QPointF globalPosDelta = pos - posPoint;
@@ -1354,7 +1354,7 @@ void QWinRTScreen::emulateMouseMove(const QPointF &point, MousePositionTransitio
d->currentTargetWindow = windowUnderPointer;
if (d->mouseGrabWindow)
- d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+ d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window();
if (d->currentTargetWindow) {
const QPointF globalPosDelta = pos - posPoint;
diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro
index 43132a1a76..43dc8f074c 100644
--- a/src/plugins/platforms/winrt/winrt.pro
+++ b/src/plugins/platforms/winrt/winrt.pro
@@ -8,8 +8,7 @@ QT += \
DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__
-LIBS += -lws2_32
-QMAKE_USE_PRIVATE += d3d11
+QMAKE_USE_PRIVATE += d3d11 ws2_32
SOURCES = \
main.cpp \
diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationplugin.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationplugin.h
index d5a0af97b0..b18248570f 100644
--- a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationplugin.h
+++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationplugin.h
@@ -54,7 +54,7 @@ class Q_XCB_EXPORT QXcbGlIntegrationPlugin : public QObject
{
Q_OBJECT
public:
- explicit QXcbGlIntegrationPlugin(QObject *parent = 0)
+ explicit QXcbGlIntegrationPlugin(QObject *parent = nullptr)
: QObject(parent)
{ }
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
index b751aaf8a3..34895caaa2 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
@@ -164,7 +164,11 @@ bool QXcbGlxIntegration::handleXcbEvent(xcb_generic_event_t *event, uint respons
XUnlockDisplay(xdisplay);
locked = false;
auto eventType = m_connection->nativeInterface()->nativeEventType();
+# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr result = 0;
+# else
long result = 0;
+# endif
handled = dispatcher->filterNativeEvent(eventType, &ev, &result);
}
#endif
diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
index 6ddcec0256..82b6d60bcd 100644
--- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
+++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
@@ -455,11 +455,11 @@ static const uchar base_dither_matrix[DITHER_SIZE][DITHER_SIZE] = {
static QPixmap qt_patternForAlpha(uchar alpha, int screen)
{
QPixmap pm;
- QString key = QLatin1Literal("$qt-alpha-brush$")
+ QString key = QLatin1String("$qt-alpha-brush$")
% HexString<uchar>(alpha)
% HexString<int>(screen);
- if (!QPixmapCache::find(key, pm)) {
+ if (!QPixmapCache::find(key, &pm)) {
// #### why not use a mono image here????
QImage pattern(DITHER_SIZE, DITHER_SIZE, QImage::Format_ARGB32);
pattern.fill(0xffffffff);
diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h
index 9b01c0a3fc..bc82351283 100644
--- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h
+++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h
@@ -116,7 +116,7 @@ protected:
friend GC qt_x11_get_brush_gc(QPainter *);
private:
- Q_DISABLE_COPY(QX11PaintEngine)
+ Q_DISABLE_COPY_MOVE(QX11PaintEngine)
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
index b1ce39f363..f86bedbdcd 100644
--- a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
+++ b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
@@ -2017,7 +2017,7 @@ QImage QX11PlatformPixmap::toImage(const QXImageWrapper &xiWrapper, const QRect
}
} else if (xi->bits_per_pixel == d) { // compatible depth
char *xidata = xi->data; // copy each scanline
- int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line);
+ int bpl = qMin(int(image.bytesPerLine()),xi->bytes_per_line);
for (int y=0; y<xi->height; y++) {
memcpy(image.scanLine(y), xidata, bpl);
xidata += xi->bytes_per_line;
diff --git a/src/plugins/platforms/xcb/nativepainting/qt_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qt_x11_p.h
index a13a8f0483..1f7e7cf49b 100644
--- a/src/plugins/platforms/xcb/nativepainting/qt_x11_p.h
+++ b/src/plugins/platforms/xcb/nativepainting/qt_x11_p.h
@@ -190,7 +190,7 @@ struct QX11InfoData {
};
template <class T>
-Q_DECL_RELAXED_CONSTEXPR inline int lowest_bit(T v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline int lowest_bit(T v) noexcept
{
int result = qCountTrailingZeroBits(v);
return ((result >> 3) == sizeof(T)) ? -1 : result;
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index f9240a45cc..741317d766 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -641,17 +641,17 @@ void QXcbBackingStoreImage::flushPixmap(const QRegion &region, bool fullRegion)
xcb_subimage.bit_order = m_xcb_image->bit_order;
const bool needsByteSwap = xcb_subimage.byte_order != m_xcb_image->byte_order;
+ // Ensure that we don't send more than maxPutImageRequestDataBytes per request.
+ const auto maxPutImageRequestDataBytes = connection()->maxRequestDataBytes(sizeof(xcb_put_image_request_t));
for (const QRect &rect : region) {
- // We must make sure that each request is not larger than max_req_size.
- // Each request takes req_size + m_xcb_image->stride * height bytes.
- static const uint32_t req_size = sizeof(xcb_put_image_request_t);
- const uint32_t max_req_size = xcb_get_maximum_request_length(xcb_connection());
- const int rows_per_put = (max_req_size - req_size) / m_xcb_image->stride;
+ const quint32 stride = round_up_scanline(rect.width() * m_qimage.depth(), xcb_subimage.scanline_pad) >> 3;
+ const int rows_per_put = maxPutImageRequestDataBytes / stride;
// This assert could trigger if a single row has more pixels than fit in
- // a single PutImage request. However, max_req_size is guaranteed to be
- // at least 16384 bytes. That should be enough for quite large images.
+ // a single PutImage request. In the absence of the BIG-REQUESTS extension
+ // the theoretical maximum lengths of maxPutImageRequestDataBytes can be
+ // roughly 256kB.
Q_ASSERT(rows_per_put > 0);
// If we upload the whole image in a single chunk, the result might be
@@ -666,9 +666,10 @@ void QXcbBackingStoreImage::flushPixmap(const QRegion &region, bool fullRegion)
while (height > 0) {
const int rows = std::min(height, rows_per_put);
const QRect subRect(x, y, width, rows);
- const quint32 stride = round_up_scanline(width * m_qimage.depth(), xcb_subimage.scanline_pad) >> 3;
const QImage subImage = native_sub_image(&m_flushBuffer, stride, m_qimage, subRect, needsByteSwap);
+ Q_ASSERT(static_cast<size_t>(subImage.sizeInBytes()) <= maxPutImageRequestDataBytes);
+
xcb_subimage.width = width;
xcb_subimage.height = rows;
xcb_subimage.data = const_cast<uint8_t *>(subImage.constBits());
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index ac8b029916..2cb6720d40 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -240,8 +240,8 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, atom(QXcbAtom::CLIPBOARD), mask);
}
- // change property protocol request is 24 bytes
- m_increment = (xcb_get_maximum_request_length(xcb_connection()) * 4) - 24;
+ // xcb_change_property_request_t and xcb_get_property_request_t are the same size
+ m_maxPropertyRequestDataBytes = connection()->maxRequestDataBytes(sizeof(xcb_change_property_request_t));
}
QXcbClipboard::~QXcbClipboard()
@@ -486,7 +486,7 @@ xcb_atom_t QXcbClipboard::sendSelection(QMimeData *d, xcb_atom_t target, xcb_win
if (m_clipboard_closing)
allow_incr = false;
- if (data.size() > m_increment && allow_incr) {
+ if (data.size() > m_maxPropertyRequestDataBytes && allow_incr) {
long bytes = data.size();
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window, property,
atom(QXcbAtom::INCR), 32, 1, (const void *)&bytes);
@@ -496,7 +496,7 @@ xcb_atom_t QXcbClipboard::sendSelection(QMimeData *d, xcb_atom_t target, xcb_win
}
// make sure we can perform the XChangeProperty in a single request
- if (data.size() > m_increment)
+ if (data.size() > m_maxPropertyRequestDataBytes)
return XCB_NONE; // ### perhaps use several XChangeProperty calls w/ PropModeAppend?
int dataSize = data.size() / (dataFormat / 8);
// use a single request to transfer data
@@ -678,17 +678,8 @@ void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_eve
emitChanged(mode);
}
-
-static inline int maxSelectionIncr(xcb_connection_t *c)
-{
- int l = xcb_get_maximum_request_length(c);
- return (l > 65536 ? 65536*4 : l*4) - 100;
-}
-
bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, bool deleteProperty, QByteArray *buffer, int *size, xcb_atom_t *type, int *format)
{
- int maxsize = maxSelectionIncr(xcb_connection());
- ulong bytes_left; // bytes_after
xcb_atom_t dummy_type;
int dummy_format;
@@ -705,7 +696,8 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
}
*type = reply->type;
*format = reply->format;
- bytes_left = reply->bytes_after;
+
+ auto bytes_left = reply->bytes_after;
int offset = 0, buffer_offset = 0;
@@ -720,7 +712,8 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
while (bytes_left) {
// more to read...
- reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, offset, maxsize/4);
+ reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, win, property,
+ XCB_GET_PROPERTY_TYPE_ANY, offset, m_maxPropertyRequestDataBytes / 4);
if (!reply || reply->type == XCB_NONE)
break;
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h
index 26d3b3b395..51ae0dc1ee 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.h
+++ b/src/plugins/platforms/xcb/qxcbclipboard.h
@@ -113,7 +113,7 @@ public:
xcb_window_t getSelectionOwner(xcb_atom_t atom) const;
QByteArray getSelection(xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property, xcb_timestamp_t t = 0);
- int increment() const { return m_increment; }
+ int increment() const { return m_maxPropertyRequestDataBytes; }
int clipboardTimeout() const { return clipboard_timeout; }
void removeTransaction(xcb_window_t window) { m_transactions.remove(window); }
@@ -137,7 +137,7 @@ private:
static const int clipboard_timeout;
- int m_increment = 0;
+ int m_maxPropertyRequestDataBytes = 0;
bool m_clipboard_closing = false;
xcb_timestamp_t m_incr_receive_time = 0;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 0d71a5a552..d27a288feb 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -132,6 +132,12 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
if (!m_startupId.isNull())
qunsetenv("DESKTOP_STARTUP_ID");
+ m_focusInTimer.setSingleShot(true);
+ m_focusInTimer.callOnTimeout([]() {
+ // No FocusIn events for us, proceed with FocusOut normally.
+ QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason);
+ });
+
sync();
}
@@ -432,7 +438,11 @@ const char *xcb_protocol_request_codes[] =
void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr result = 0;
+#else
long result = 0;
+#endif
QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
if (dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->nativeEventType(), error, &result))
return;
@@ -529,7 +539,11 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
if (Q_UNLIKELY(lcQpaEvents().isDebugEnabled()))
printXcbEvent(lcQpaEvents(), "Event", event);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr result = 0; // Used only by MS Windows
+#else
long result = 0; // Used only by MS Windows
+#endif
if (QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance()) {
if (dispatcher->filterNativeEvent(m_nativeInterface->nativeEventType(), event, &result))
return;
@@ -731,11 +745,6 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
m_glIntegration->handleXcbEvent(event, response_type);
}
-void QXcbConnection::addPeekFunc(PeekFunc f)
-{
- m_peekFuncs.append(f);
-}
-
void QXcbConnection::setFocusWindow(QWindow *w)
{
m_focusWindow = w ? static_cast<QXcbWindow *>(w->handle()) : nullptr;
@@ -1015,15 +1024,6 @@ void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags)
if (compressEvent(event))
continue;
- auto isWaitingFor = [=](PeekFunc peekFunc) {
- // These callbacks return true if the event is what they were
- // waiting for, remove them from the list in that case.
- return peekFunc(this, event);
- };
- m_peekFuncs.erase(std::remove_if(m_peekFuncs.begin(), m_peekFuncs.end(),
- isWaitingFor),
- m_peekFuncs.end());
-
handleXcbEvent(event);
// The lock-based solution used to free the lock inside this loop,
@@ -1032,12 +1032,6 @@ void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags)
m_eventQueue->flushBufferedEvents();
}
- // Indicate with a null event that the event the callbacks are waiting for
- // is not in the queue currently.
- for (PeekFunc f : qAsConst(m_peekFuncs))
- f(this, nullptr);
- m_peekFuncs.clear();
-
xcb_flush(xcb_connection());
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 15537fede4..7cf25d41a6 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -43,6 +43,7 @@
#include <xcb/xcb.h>
#include <xcb/randr.h>
+#include <QtCore/QTimer>
#include <QtGui/private/qtguiglobal_p.h>
#include "qxcbexport.h"
#include <QHash>
@@ -107,7 +108,7 @@ public:
virtual void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource = Qt::MouseEventNotSynthesized) {}
virtual void handleXIEnterLeave(xcb_ge_event_t *) {}
#endif
- virtual QXcbWindow *toWindow() { return 0; }
+ virtual QXcbWindow *toWindow() { return nullptr; }
};
typedef QHash<xcb_window_t, QXcbWindowEventListener *> WindowMapper;
@@ -183,9 +184,6 @@ public:
QXcbWindowEventListener *windowEventListenerFromId(xcb_window_t id);
QXcbWindow *platformWindowFromId(xcb_window_t id);
- typedef bool (*PeekFunc)(QXcbConnection *, xcb_generic_event_t *);
- void addPeekFunc(PeekFunc f);
-
inline xcb_timestamp_t time() const { return m_time; }
inline void setTime(xcb_timestamp_t t) { if (timeGreaterThan(t, m_time)) m_time = t; }
@@ -247,6 +245,8 @@ public:
void flush() { xcb_flush(xcb_connection()); }
void processXcbEvents(QEventLoop::ProcessEventsFlags flags);
+ QTimer &focusInTimer() { return m_focusInTimer; }
+
protected:
bool event(QEvent *e) override;
@@ -366,9 +366,7 @@ private:
WindowMapper m_mapper;
- QVector<PeekFunc> m_peekFuncs;
-
- Qt::MouseButtons m_buttonState = 0;
+ Qt::MouseButtons m_buttonState = nullptr;
Qt::MouseButton m_button = Qt::NoButton;
QXcbWindow *m_focusWindow = nullptr;
@@ -388,6 +386,8 @@ private:
friend class QXcbEventQueue;
QByteArray m_xdgCurrentDesktop;
+ QTimer m_focusInTimer;
+
};
#if QT_CONFIG(xcb_xinput)
#if QT_CONFIG(tabletevent)
diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
index af72285135..9a028e5a7e 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
@@ -134,6 +134,7 @@ QXcbBasicConnection::QXcbBasicConnection(const char *displayName)
m_setup = xcb_get_setup(m_xcbConnection);
m_xcbAtom.initialize(m_xcbConnection);
+ m_maximumRequestLength = xcb_get_maximum_request_length(m_xcbConnection);
xcb_extension_t *extensions[] = {
&xcb_shm_id, &xcb_xfixes_id, &xcb_randr_id, &xcb_shape_id, &xcb_sync_id,
@@ -178,6 +179,14 @@ QXcbBasicConnection::~QXcbBasicConnection()
}
}
+size_t QXcbBasicConnection::maxRequestDataBytes(size_t requestSize) const
+{
+ if (hasBigRequest())
+ requestSize += 4; // big-request encoding adds 4 bytes
+
+ return m_maximumRequestLength * 4 - requestSize;
+}
+
xcb_atom_t QXcbBasicConnection::internAtom(const char *name)
{
if (!name || *name == 0)
@@ -199,6 +208,11 @@ QByteArray QXcbBasicConnection::atomName(xcb_atom_t atom)
return QByteArray();
}
+bool QXcbBasicConnection::hasBigRequest() const
+{
+ return m_maximumRequestLength > m_setup->maximum_request_length;
+}
+
#if QT_CONFIG(xcb_xinput)
// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
// - "pad0" became "extension"
diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.h b/src/plugins/platforms/xcb/qxcbconnection_basic.h
index 6e407a5f80..1bd4310562 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_basic.h
+++ b/src/plugins/platforms/xcb/qxcbconnection_basic.h
@@ -74,6 +74,8 @@ public:
}
const xcb_setup_t *setup() const { return m_setup; }
+ size_t maxRequestDataBytes(size_t requestSize) const;
+
inline xcb_atom_t atom(QXcbAtom::Atom qatom) const { return m_xcbAtom.atom(qatom); }
QXcbAtom::Atom qatom(xcb_atom_t atom) const { return m_xcbAtom.qatom(atom); }
xcb_atom_t internAtom(const char *name);
@@ -95,6 +97,7 @@ public:
bool hasShmFd() const { return m_hasShmFd; }
bool hasXSync() const { return m_hasXSync; }
bool hasXinerama() const { return m_hasXinerama; }
+ bool hasBigRequest() const;
#if QT_CONFIG(xcb_xinput)
bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
@@ -153,12 +156,14 @@ private:
uint32_t m_xfixesFirstEvent = 0;
uint32_t m_xrandrFirstEvent = 0;
uint32_t m_xkbFirstEvent = 0;
+
+ uint32_t m_maximumRequestLength = 0;
};
#define Q_XCB_REPLY_CONNECTION_ARG(connection, ...) connection
struct QStdFreeDeleter {
- void operator()(void *p) const Q_DECL_NOTHROW { return std::free(p); }
+ void operator()(void *p) const noexcept { return std::free(p); }
};
#define Q_XCB_REPLY(call, ...) \
diff --git a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
index 4e631beb25..9ba71ada37 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
@@ -210,7 +210,7 @@ void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_cha
const int idx = m_screens.indexOf(screen);
if (idx > 0) {
qAsConst(m_screens).first()->setPrimary(false);
- m_screens.swap(0, idx);
+ m_screens.swapItemsAt(0, idx);
}
screen->virtualDesktop()->setPrimaryScreen(screen);
QWindowSystemInterface::handlePrimaryScreenChanged(screen);
@@ -262,7 +262,7 @@ void QXcbConnection::destroyScreen(QXcbScreen *screen)
newPrimary->setPrimary(true);
const int idx = m_screens.indexOf(newPrimary);
if (idx > 0)
- m_screens.swap(0, idx);
+ m_screens.swapItemsAt(0, idx);
QWindowSystemInterface::handlePrimaryScreenChanged(newPrimary);
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 450706fc53..bc09fe2f91 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -641,7 +641,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
qreal nx = -1.0, ny = -1.0;
qreal w = 0.0, h = 0.0;
bool majorAxisIsY = touchPoint.area.height() > touchPoint.area.width();
- for (const TouchDeviceData::ValuatorClassInfo vci : dev->valuatorInfo) {
+ for (const TouchDeviceData::ValuatorClassInfo &vci : qAsConst(dev->valuatorInfo)) {
double value;
if (!xi2GetValuatorValueIfSet(xiDeviceEvent, vci.number, &value))
continue;
@@ -827,7 +827,7 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
| XCB_INPUT_XI_EVENT_MASK_TOUCH_UPDATE
| XCB_INPUT_XI_EVENT_MASK_TOUCH_END;
- for (int id : m_xiMasterPointerIds) {
+ for (int id : qAsConst(m_xiMasterPointerIds)) {
xcb_generic_error_t *error = nullptr;
auto cookie = xcb_input_xi_grab_device(xcb_connection(), w, XCB_CURRENT_TIME, XCB_CURSOR_NONE, id,
XCB_INPUT_GRAB_MODE_22_ASYNC, XCB_INPUT_GRAB_MODE_22_ASYNC,
@@ -845,7 +845,7 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
free(reply);
}
} else { // ungrab
- for (int id : m_xiMasterPointerIds) {
+ for (int id : qAsConst(m_xiMasterPointerIds)) {
auto cookie = xcb_input_xi_ungrab_device_checked(xcb_connection(), XCB_CURRENT_TIME, id);
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
if (error) {
diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h
index 5bc806381c..0b238823f0 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.h
+++ b/src/plugins/platforms/xcb/qxcbcursor.h
@@ -65,7 +65,7 @@ inline bool operator==(const QXcbCursorCacheKey &k1, const QXcbCursorCacheKey &k
return k1.shape == k2.shape && k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
}
-inline uint qHash(const QXcbCursorCacheKey &k, uint seed) Q_DECL_NOTHROW
+inline uint qHash(const QXcbCursorCacheKey &k, uint seed) noexcept
{
return (uint(k.shape) + uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
}
@@ -83,7 +83,7 @@ public:
QPoint pos() const override;
void setPos(const QPoint &pos) override;
- static void queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask = 0);
+ static void queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask = nullptr);
#ifndef QT_NO_CURSOR
xcb_cursor_t xcbCursor(const QCursor &c) const
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index c19008c04b..1388e68acc 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -86,7 +86,7 @@ public:
void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event);
void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event);
void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event,
- Qt::MouseButtons b = 0, Qt::KeyboardModifiers mods = 0);
+ Qt::MouseButtons b = nullptr, Qt::KeyboardModifiers mods = nullptr);
void handleStatus(const xcb_client_message_event_t *event);
void handleSelectionRequest(const xcb_selection_request_event_t *event);
@@ -109,7 +109,7 @@ private:
void init();
void handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *event,
- Qt::MouseButtons b = 0, Qt::KeyboardModifiers mods = 0);
+ Qt::MouseButtons b = nullptr, Qt::KeyboardModifiers mods = nullptr);
void handle_xdnd_status(const xcb_client_message_event_t *event);
void send_leave();
diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
index acec0486c2..82a36c0727 100644
--- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp
+++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
@@ -262,7 +262,7 @@ qint32 QXcbEventQueue::generatePeekerId()
bool QXcbEventQueue::removePeekerId(qint32 peekerId)
{
- const auto it = m_peekerToNode.find(peekerId);
+ const auto it = m_peekerToNode.constFind(peekerId);
if (it == m_peekerToNode.constEnd()) {
qCWarning(lcQpaXcb, "failed to remove unknown peeker id: %d", peekerId);
return false;
@@ -281,7 +281,7 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData,
const bool peekerIdProvided = peekerId != -1;
auto peekerToNodeIt = m_peekerToNode.find(peekerId);
- if (peekerIdProvided && peekerToNodeIt == m_peekerToNode.constEnd()) {
+ if (peekerIdProvided && peekerToNodeIt == m_peekerToNode.end()) {
qCWarning(lcQpaXcb, "failed to find index for unknown peeker id: %d", peekerId);
return false;
}
@@ -341,7 +341,7 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData,
// Before updating, make sure that a peeker callback did not remove
// the peeker id.
peekerToNodeIt = m_peekerToNode.find(peekerId);
- if (peekerToNodeIt != m_peekerToNode.constEnd())
+ if (peekerToNodeIt != m_peekerToNode.end())
*peekerToNodeIt = node; // id still in the cache, update node
}
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index ed9e87a036..95ca40fc95 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -357,6 +357,8 @@ void QXcbIntegration::initialize()
m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
if (!m_inputContext && icStr != defaultInputContext && icStr != QLatin1String("none"))
m_inputContext.reset(QPlatformInputContextFactory::create(defaultInputContext));
+
+ defaultConnection()->keyboard()->initialize();
}
void QXcbIntegration::moveToScreen(QWindow *window, int screen)
@@ -548,6 +550,7 @@ void QXcbIntegration::beep() const
return;
xcb_connection_t *connection = static_cast<QXcbScreen *>(screen)->xcb_connection();
xcb_bell(connection, 0);
+ xcb_flush(connection);
}
bool QXcbIntegration::nativePaintingEnabled() const
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index c5dc7b21ad..d0e02ecdd1 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -39,7 +39,6 @@
#include "qxcbkeyboard.h"
#include "qxcbwindow.h"
#include "qxcbscreen.h"
-#include "qxcbxkbcommon.h"
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatforminputcontext.h>
@@ -49,404 +48,20 @@
#include <QtCore/QMetaEnum>
#include <private/qguiapplication_p.h>
-#include <private/qmakearray_p.h>
-#include <xkbcommon/xkbcommon-keysyms.h>
+#if QT_CONFIG(xkb)
+#include <xkbcommon/xkbcommon-x11.h>
+#endif
#if QT_CONFIG(xcb_xinput)
#include <xcb/xinput.h>
#endif
-QT_BEGIN_NAMESPACE
-
-typedef struct xkb2qt
-{
- unsigned int xkb;
- unsigned int qt;
-
- constexpr bool operator <=(const xkb2qt &that) const noexcept
- {
- return xkb <= that.xkb;
- }
-
- constexpr bool operator <(const xkb2qt &that) const noexcept
- {
- return xkb < that.xkb;
- }
-} xkb2qt_t;
-template<std::size_t Xkb, std::size_t Qt>
-struct Xkb2Qt
-{
- using Type = xkb2qt_t;
- static constexpr Type data() noexcept { return Type{Xkb, Qt}; }
-};
-
-static constexpr const auto KeyTbl = qMakeArray(
- QSortedData<
- // misc keys
-
- Xkb2Qt<XKB_KEY_Escape, Qt::Key_Escape>,
- Xkb2Qt<XKB_KEY_Tab, Qt::Key_Tab>,
- Xkb2Qt<XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab>,
- Xkb2Qt<XKB_KEY_BackSpace, Qt::Key_Backspace>,
- Xkb2Qt<XKB_KEY_Return, Qt::Key_Return>,
- Xkb2Qt<XKB_KEY_Insert, Qt::Key_Insert>,
- Xkb2Qt<XKB_KEY_Delete, Qt::Key_Delete>,
- Xkb2Qt<XKB_KEY_Clear, Qt::Key_Delete>,
- Xkb2Qt<XKB_KEY_Pause, Qt::Key_Pause>,
- Xkb2Qt<XKB_KEY_Print, Qt::Key_Print>,
- Xkb2Qt<0x1005FF60, Qt::Key_SysReq>, // hardcoded Sun SysReq
- Xkb2Qt<0x1007ff00, Qt::Key_SysReq>, // hardcoded X386 SysReq
-
- // cursor movement
-
- Xkb2Qt<XKB_KEY_Home, Qt::Key_Home>,
- Xkb2Qt<XKB_KEY_End, Qt::Key_End>,
- Xkb2Qt<XKB_KEY_Left, Qt::Key_Left>,
- Xkb2Qt<XKB_KEY_Up, Qt::Key_Up>,
- Xkb2Qt<XKB_KEY_Right, Qt::Key_Right>,
- Xkb2Qt<XKB_KEY_Down, Qt::Key_Down>,
- Xkb2Qt<XKB_KEY_Prior, Qt::Key_PageUp>,
- Xkb2Qt<XKB_KEY_Next, Qt::Key_PageDown>,
-
- // modifiers
-
- Xkb2Qt<XKB_KEY_Shift_L, Qt::Key_Shift>,
- Xkb2Qt<XKB_KEY_Shift_R, Qt::Key_Shift>,
- Xkb2Qt<XKB_KEY_Shift_Lock, Qt::Key_Shift>,
- Xkb2Qt<XKB_KEY_Control_L, Qt::Key_Control>,
- Xkb2Qt<XKB_KEY_Control_R, Qt::Key_Control>,
- Xkb2Qt<XKB_KEY_Meta_L, Qt::Key_Meta>,
- Xkb2Qt<XKB_KEY_Meta_R, Qt::Key_Meta>,
- Xkb2Qt<XKB_KEY_Alt_L, Qt::Key_Alt>,
- Xkb2Qt<XKB_KEY_Alt_R, Qt::Key_Alt>,
- Xkb2Qt<XKB_KEY_Caps_Lock, Qt::Key_CapsLock>,
- Xkb2Qt<XKB_KEY_Num_Lock, Qt::Key_NumLock>,
- Xkb2Qt<XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock>,
- Xkb2Qt<XKB_KEY_Super_L, Qt::Key_Super_L>,
- Xkb2Qt<XKB_KEY_Super_R, Qt::Key_Super_R>,
- Xkb2Qt<XKB_KEY_Menu, Qt::Key_Menu>,
- Xkb2Qt<XKB_KEY_Hyper_L, Qt::Key_Hyper_L>,
- Xkb2Qt<XKB_KEY_Hyper_R, Qt::Key_Hyper_R>,
- Xkb2Qt<XKB_KEY_Help, Qt::Key_Help>,
- Xkb2Qt<0x1000FF74, Qt::Key_Backtab>, // hardcoded HP backtab
- Xkb2Qt<0x1005FF10, Qt::Key_F11>, // hardcoded Sun F36 (labeled F11)
- Xkb2Qt<0x1005FF11, Qt::Key_F12>, // hardcoded Sun F37 (labeled F12)
-
- // numeric and function keypad keys
-
- Xkb2Qt<XKB_KEY_KP_Space, Qt::Key_Space>,
- Xkb2Qt<XKB_KEY_KP_Tab, Qt::Key_Tab>,
- Xkb2Qt<XKB_KEY_KP_Enter, Qt::Key_Enter>,
- //Xkb2Qt<XKB_KEY_KP_F1, Qt::Key_F1>,
- //Xkb2Qt<XKB_KEY_KP_F2, Qt::Key_F2>,
- //Xkb2Qt<XKB_KEY_KP_F3, Qt::Key_F3>,
- //Xkb2Qt<XKB_KEY_KP_F4, Qt::Key_F4>,
- Xkb2Qt<XKB_KEY_KP_Home, Qt::Key_Home>,
- Xkb2Qt<XKB_KEY_KP_Left, Qt::Key_Left>,
- Xkb2Qt<XKB_KEY_KP_Up, Qt::Key_Up>,
- Xkb2Qt<XKB_KEY_KP_Right, Qt::Key_Right>,
- Xkb2Qt<XKB_KEY_KP_Down, Qt::Key_Down>,
- Xkb2Qt<XKB_KEY_KP_Prior, Qt::Key_PageUp>,
- Xkb2Qt<XKB_KEY_KP_Next, Qt::Key_PageDown>,
- Xkb2Qt<XKB_KEY_KP_End, Qt::Key_End>,
- Xkb2Qt<XKB_KEY_KP_Begin, Qt::Key_Clear>,
- Xkb2Qt<XKB_KEY_KP_Insert, Qt::Key_Insert>,
- Xkb2Qt<XKB_KEY_KP_Delete, Qt::Key_Delete>,
- Xkb2Qt<XKB_KEY_KP_Equal, Qt::Key_Equal>,
- Xkb2Qt<XKB_KEY_KP_Multiply, Qt::Key_Asterisk>,
- Xkb2Qt<XKB_KEY_KP_Add, Qt::Key_Plus>,
- Xkb2Qt<XKB_KEY_KP_Separator, Qt::Key_Comma>,
- Xkb2Qt<XKB_KEY_KP_Subtract, Qt::Key_Minus>,
- Xkb2Qt<XKB_KEY_KP_Decimal, Qt::Key_Period>,
- Xkb2Qt<XKB_KEY_KP_Divide, Qt::Key_Slash>,
-
- // special non-XF86 function keys
-
- Xkb2Qt<XKB_KEY_Undo, Qt::Key_Undo>,
- Xkb2Qt<XKB_KEY_Redo, Qt::Key_Redo>,
- Xkb2Qt<XKB_KEY_Find, Qt::Key_Find>,
- Xkb2Qt<XKB_KEY_Cancel, Qt::Key_Cancel>,
-
- // International input method support keys
-
- // International & multi-key character composition
- Xkb2Qt<XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr>,
- Xkb2Qt<XKB_KEY_Multi_key, Qt::Key_Multi_key>,
- Xkb2Qt<XKB_KEY_Codeinput, Qt::Key_Codeinput>,
- Xkb2Qt<XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate>,
- Xkb2Qt<XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate>,
- Xkb2Qt<XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate>,
-
- // Misc Functions
- Xkb2Qt<XKB_KEY_Mode_switch, Qt::Key_Mode_switch>,
- Xkb2Qt<XKB_KEY_script_switch, Qt::Key_Mode_switch>,
-
- // Japanese keyboard support
- Xkb2Qt<XKB_KEY_Kanji, Qt::Key_Kanji>,
- Xkb2Qt<XKB_KEY_Muhenkan, Qt::Key_Muhenkan>,
- //Xkb2Qt<XKB_KEY_Henkan_Mode, Qt::Key_Henkan_Mode>,
- Xkb2Qt<XKB_KEY_Henkan_Mode, Qt::Key_Henkan>,
- Xkb2Qt<XKB_KEY_Henkan, Qt::Key_Henkan>,
- Xkb2Qt<XKB_KEY_Romaji, Qt::Key_Romaji>,
- Xkb2Qt<XKB_KEY_Hiragana, Qt::Key_Hiragana>,
- Xkb2Qt<XKB_KEY_Katakana, Qt::Key_Katakana>,
- Xkb2Qt<XKB_KEY_Hiragana_Katakana, Qt::Key_Hiragana_Katakana>,
- Xkb2Qt<XKB_KEY_Zenkaku, Qt::Key_Zenkaku>,
- Xkb2Qt<XKB_KEY_Hankaku, Qt::Key_Hankaku>,
- Xkb2Qt<XKB_KEY_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku>,
- Xkb2Qt<XKB_KEY_Touroku, Qt::Key_Touroku>,
- Xkb2Qt<XKB_KEY_Massyo, Qt::Key_Massyo>,
- Xkb2Qt<XKB_KEY_Kana_Lock, Qt::Key_Kana_Lock>,
- Xkb2Qt<XKB_KEY_Kana_Shift, Qt::Key_Kana_Shift>,
- Xkb2Qt<XKB_KEY_Eisu_Shift, Qt::Key_Eisu_Shift>,
- Xkb2Qt<XKB_KEY_Eisu_toggle, Qt::Key_Eisu_toggle>,
- //Xkb2Qt<XKB_KEY_Kanji_Bangou, Qt::Key_Kanji_Bangou>,
- //Xkb2Qt<XKB_KEY_Zen_Koho, Qt::Key_Zen_Koho>,
- //Xkb2Qt<XKB_KEY_Mae_Koho, Qt::Key_Mae_Koho>,
- Xkb2Qt<XKB_KEY_Kanji_Bangou, Qt::Key_Codeinput>,
- Xkb2Qt<XKB_KEY_Zen_Koho, Qt::Key_MultipleCandidate>,
- Xkb2Qt<XKB_KEY_Mae_Koho, Qt::Key_PreviousCandidate>,
-
- // Korean keyboard support
- Xkb2Qt<XKB_KEY_Hangul, Qt::Key_Hangul>,
- Xkb2Qt<XKB_KEY_Hangul_Start, Qt::Key_Hangul_Start>,
- Xkb2Qt<XKB_KEY_Hangul_End, Qt::Key_Hangul_End>,
- Xkb2Qt<XKB_KEY_Hangul_Hanja, Qt::Key_Hangul_Hanja>,
- Xkb2Qt<XKB_KEY_Hangul_Jamo, Qt::Key_Hangul_Jamo>,
- Xkb2Qt<XKB_KEY_Hangul_Romaja, Qt::Key_Hangul_Romaja>,
- //Xkb2Qt<XKB_KEY_Hangul_Codeinput, Qt::Key_Hangul_Codeinput>,
- Xkb2Qt<XKB_KEY_Hangul_Codeinput, Qt::Key_Codeinput>,
- Xkb2Qt<XKB_KEY_Hangul_Jeonja, Qt::Key_Hangul_Jeonja>,
- Xkb2Qt<XKB_KEY_Hangul_Banja, Qt::Key_Hangul_Banja>,
- Xkb2Qt<XKB_KEY_Hangul_PreHanja, Qt::Key_Hangul_PreHanja>,
- Xkb2Qt<XKB_KEY_Hangul_PostHanja, Qt::Key_Hangul_PostHanja>,
- //Xkb2Qt<XKB_KEY_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate>,
- //Xkb2Qt<XKB_KEY_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate>,
- //Xkb2Qt<XKB_KEY_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate>,
- Xkb2Qt<XKB_KEY_Hangul_SingleCandidate, Qt::Key_SingleCandidate>,
- Xkb2Qt<XKB_KEY_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate>,
- Xkb2Qt<XKB_KEY_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate>,
- Xkb2Qt<XKB_KEY_Hangul_Special, Qt::Key_Hangul_Special>,
- //Xkb2Qt<XKB_KEY_Hangul_switch, Qt::Key_Hangul_switch>,
- Xkb2Qt<XKB_KEY_Hangul_switch, Qt::Key_Mode_switch>,
-
- // dead keys
- Xkb2Qt<XKB_KEY_dead_grave, Qt::Key_Dead_Grave>,
- Xkb2Qt<XKB_KEY_dead_acute, Qt::Key_Dead_Acute>,
- Xkb2Qt<XKB_KEY_dead_circumflex, Qt::Key_Dead_Circumflex>,
- Xkb2Qt<XKB_KEY_dead_tilde, Qt::Key_Dead_Tilde>,
- Xkb2Qt<XKB_KEY_dead_macron, Qt::Key_Dead_Macron>,
- Xkb2Qt<XKB_KEY_dead_breve, Qt::Key_Dead_Breve>,
- Xkb2Qt<XKB_KEY_dead_abovedot, Qt::Key_Dead_Abovedot>,
- Xkb2Qt<XKB_KEY_dead_diaeresis, Qt::Key_Dead_Diaeresis>,
- Xkb2Qt<XKB_KEY_dead_abovering, Qt::Key_Dead_Abovering>,
- Xkb2Qt<XKB_KEY_dead_doubleacute, Qt::Key_Dead_Doubleacute>,
- Xkb2Qt<XKB_KEY_dead_caron, Qt::Key_Dead_Caron>,
- Xkb2Qt<XKB_KEY_dead_cedilla, Qt::Key_Dead_Cedilla>,
- Xkb2Qt<XKB_KEY_dead_ogonek, Qt::Key_Dead_Ogonek>,
- Xkb2Qt<XKB_KEY_dead_iota, Qt::Key_Dead_Iota>,
- Xkb2Qt<XKB_KEY_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound>,
- Xkb2Qt<XKB_KEY_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound>,
- Xkb2Qt<XKB_KEY_dead_belowdot, Qt::Key_Dead_Belowdot>,
- Xkb2Qt<XKB_KEY_dead_hook, Qt::Key_Dead_Hook>,
- Xkb2Qt<XKB_KEY_dead_horn, Qt::Key_Dead_Horn>,
- Xkb2Qt<XKB_KEY_dead_stroke, Qt::Key_Dead_Stroke>,
- Xkb2Qt<XKB_KEY_dead_abovecomma, Qt::Key_Dead_Abovecomma>,
- Xkb2Qt<XKB_KEY_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma>,
- Xkb2Qt<XKB_KEY_dead_doublegrave, Qt::Key_Dead_Doublegrave>,
- Xkb2Qt<XKB_KEY_dead_belowring, Qt::Key_Dead_Belowring>,
- Xkb2Qt<XKB_KEY_dead_belowmacron, Qt::Key_Dead_Belowmacron>,
- Xkb2Qt<XKB_KEY_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex>,
- Xkb2Qt<XKB_KEY_dead_belowtilde, Qt::Key_Dead_Belowtilde>,
- Xkb2Qt<XKB_KEY_dead_belowbreve, Qt::Key_Dead_Belowbreve>,
- Xkb2Qt<XKB_KEY_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis>,
- Xkb2Qt<XKB_KEY_dead_invertedbreve, Qt::Key_Dead_Invertedbreve>,
- Xkb2Qt<XKB_KEY_dead_belowcomma, Qt::Key_Dead_Belowcomma>,
- Xkb2Qt<XKB_KEY_dead_currency, Qt::Key_Dead_Currency>,
- Xkb2Qt<XKB_KEY_dead_a, Qt::Key_Dead_a>,
- Xkb2Qt<XKB_KEY_dead_A, Qt::Key_Dead_A>,
- Xkb2Qt<XKB_KEY_dead_e, Qt::Key_Dead_e>,
- Xkb2Qt<XKB_KEY_dead_E, Qt::Key_Dead_E>,
- Xkb2Qt<XKB_KEY_dead_i, Qt::Key_Dead_i>,
- Xkb2Qt<XKB_KEY_dead_I, Qt::Key_Dead_I>,
- Xkb2Qt<XKB_KEY_dead_o, Qt::Key_Dead_o>,
- Xkb2Qt<XKB_KEY_dead_O, Qt::Key_Dead_O>,
- Xkb2Qt<XKB_KEY_dead_u, Qt::Key_Dead_u>,
- Xkb2Qt<XKB_KEY_dead_U, Qt::Key_Dead_U>,
- Xkb2Qt<XKB_KEY_dead_small_schwa, Qt::Key_Dead_Small_Schwa>,
- Xkb2Qt<XKB_KEY_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa>,
- Xkb2Qt<XKB_KEY_dead_greek, Qt::Key_Dead_Greek>,
- Xkb2Qt<XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline>,
- Xkb2Qt<XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline>,
- Xkb2Qt<XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline>,
- Xkb2Qt<XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay>,
-
- // Special keys from X.org - This include multimedia keys,
- // wireless/bluetooth/uwb keys, special launcher keys, etc.
- Xkb2Qt<XKB_KEY_XF86Back, Qt::Key_Back>,
- Xkb2Qt<XKB_KEY_XF86Forward, Qt::Key_Forward>,
- Xkb2Qt<XKB_KEY_XF86Stop, Qt::Key_Stop>,
- Xkb2Qt<XKB_KEY_XF86Refresh, Qt::Key_Refresh>,
- Xkb2Qt<XKB_KEY_XF86Favorites, Qt::Key_Favorites>,
- Xkb2Qt<XKB_KEY_XF86AudioMedia, Qt::Key_LaunchMedia>,
- Xkb2Qt<XKB_KEY_XF86OpenURL, Qt::Key_OpenUrl>,
- Xkb2Qt<XKB_KEY_XF86HomePage, Qt::Key_HomePage>,
- Xkb2Qt<XKB_KEY_XF86Search, Qt::Key_Search>,
- Xkb2Qt<XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown>,
- Xkb2Qt<XKB_KEY_XF86AudioMute, Qt::Key_VolumeMute>,
- Xkb2Qt<XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp>,
- Xkb2Qt<XKB_KEY_XF86AudioPlay, Qt::Key_MediaPlay>,
- Xkb2Qt<XKB_KEY_XF86AudioStop, Qt::Key_MediaStop>,
- Xkb2Qt<XKB_KEY_XF86AudioPrev, Qt::Key_MediaPrevious>,
- Xkb2Qt<XKB_KEY_XF86AudioNext, Qt::Key_MediaNext>,
- Xkb2Qt<XKB_KEY_XF86AudioRecord, Qt::Key_MediaRecord>,
- Xkb2Qt<XKB_KEY_XF86AudioPause, Qt::Key_MediaPause>,
- Xkb2Qt<XKB_KEY_XF86Mail, Qt::Key_LaunchMail>,
- Xkb2Qt<XKB_KEY_XF86MyComputer, Qt::Key_Launch0>, // ### Qt 6: remap properly
- Xkb2Qt<XKB_KEY_XF86Calculator, Qt::Key_Launch1>,
- Xkb2Qt<XKB_KEY_XF86Memo, Qt::Key_Memo>,
- Xkb2Qt<XKB_KEY_XF86ToDoList, Qt::Key_ToDoList>,
- Xkb2Qt<XKB_KEY_XF86Calendar, Qt::Key_Calendar>,
- Xkb2Qt<XKB_KEY_XF86PowerDown, Qt::Key_PowerDown>,
- Xkb2Qt<XKB_KEY_XF86ContrastAdjust, Qt::Key_ContrastAdjust>,
- Xkb2Qt<XKB_KEY_XF86Standby, Qt::Key_Standby>,
- Xkb2Qt<XKB_KEY_XF86MonBrightnessUp, Qt::Key_MonBrightnessUp>,
- Xkb2Qt<XKB_KEY_XF86MonBrightnessDown, Qt::Key_MonBrightnessDown>,
- Xkb2Qt<XKB_KEY_XF86KbdLightOnOff, Qt::Key_KeyboardLightOnOff>,
- Xkb2Qt<XKB_KEY_XF86KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp>,
- Xkb2Qt<XKB_KEY_XF86KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown>,
- Xkb2Qt<XKB_KEY_XF86PowerOff, Qt::Key_PowerOff>,
- Xkb2Qt<XKB_KEY_XF86WakeUp, Qt::Key_WakeUp>,
- Xkb2Qt<XKB_KEY_XF86Eject, Qt::Key_Eject>,
- Xkb2Qt<XKB_KEY_XF86ScreenSaver, Qt::Key_ScreenSaver>,
- Xkb2Qt<XKB_KEY_XF86WWW, Qt::Key_WWW>,
- Xkb2Qt<XKB_KEY_XF86Sleep, Qt::Key_Sleep>,
- Xkb2Qt<XKB_KEY_XF86LightBulb, Qt::Key_LightBulb>,
- Xkb2Qt<XKB_KEY_XF86Shop, Qt::Key_Shop>,
- Xkb2Qt<XKB_KEY_XF86History, Qt::Key_History>,
- Xkb2Qt<XKB_KEY_XF86AddFavorite, Qt::Key_AddFavorite>,
- Xkb2Qt<XKB_KEY_XF86HotLinks, Qt::Key_HotLinks>,
- Xkb2Qt<XKB_KEY_XF86BrightnessAdjust, Qt::Key_BrightnessAdjust>,
- Xkb2Qt<XKB_KEY_XF86Finance, Qt::Key_Finance>,
- Xkb2Qt<XKB_KEY_XF86Community, Qt::Key_Community>,
- Xkb2Qt<XKB_KEY_XF86AudioRewind, Qt::Key_AudioRewind>,
- Xkb2Qt<XKB_KEY_XF86BackForward, Qt::Key_BackForward>,
- Xkb2Qt<XKB_KEY_XF86ApplicationLeft, Qt::Key_ApplicationLeft>,
- Xkb2Qt<XKB_KEY_XF86ApplicationRight, Qt::Key_ApplicationRight>,
- Xkb2Qt<XKB_KEY_XF86Book, Qt::Key_Book>,
- Xkb2Qt<XKB_KEY_XF86CD, Qt::Key_CD>,
- Xkb2Qt<XKB_KEY_XF86Calculater, Qt::Key_Calculator>,
- Xkb2Qt<XKB_KEY_XF86Clear, Qt::Key_Clear>,
- Xkb2Qt<XKB_KEY_XF86ClearGrab, Qt::Key_ClearGrab>,
- Xkb2Qt<XKB_KEY_XF86Close, Qt::Key_Close>,
- Xkb2Qt<XKB_KEY_XF86Copy, Qt::Key_Copy>,
- Xkb2Qt<XKB_KEY_XF86Cut, Qt::Key_Cut>,
- Xkb2Qt<XKB_KEY_XF86Display, Qt::Key_Display>,
- Xkb2Qt<XKB_KEY_XF86DOS, Qt::Key_DOS>,
- Xkb2Qt<XKB_KEY_XF86Documents, Qt::Key_Documents>,
- Xkb2Qt<XKB_KEY_XF86Excel, Qt::Key_Excel>,
- Xkb2Qt<XKB_KEY_XF86Explorer, Qt::Key_Explorer>,
- Xkb2Qt<XKB_KEY_XF86Game, Qt::Key_Game>,
- Xkb2Qt<XKB_KEY_XF86Go, Qt::Key_Go>,
- Xkb2Qt<XKB_KEY_XF86iTouch, Qt::Key_iTouch>,
- Xkb2Qt<XKB_KEY_XF86LogOff, Qt::Key_LogOff>,
- Xkb2Qt<XKB_KEY_XF86Market, Qt::Key_Market>,
- Xkb2Qt<XKB_KEY_XF86Meeting, Qt::Key_Meeting>,
- Xkb2Qt<XKB_KEY_XF86MenuKB, Qt::Key_MenuKB>,
- Xkb2Qt<XKB_KEY_XF86MenuPB, Qt::Key_MenuPB>,
- Xkb2Qt<XKB_KEY_XF86MySites, Qt::Key_MySites>,
- Xkb2Qt<XKB_KEY_XF86New, Qt::Key_New>,
- Xkb2Qt<XKB_KEY_XF86News, Qt::Key_News>,
- Xkb2Qt<XKB_KEY_XF86OfficeHome, Qt::Key_OfficeHome>,
- Xkb2Qt<XKB_KEY_XF86Open, Qt::Key_Open>,
- Xkb2Qt<XKB_KEY_XF86Option, Qt::Key_Option>,
- Xkb2Qt<XKB_KEY_XF86Paste, Qt::Key_Paste>,
- Xkb2Qt<XKB_KEY_XF86Phone, Qt::Key_Phone>,
- Xkb2Qt<XKB_KEY_XF86Reply, Qt::Key_Reply>,
- Xkb2Qt<XKB_KEY_XF86Reload, Qt::Key_Reload>,
- Xkb2Qt<XKB_KEY_XF86RotateWindows, Qt::Key_RotateWindows>,
- Xkb2Qt<XKB_KEY_XF86RotationPB, Qt::Key_RotationPB>,
- Xkb2Qt<XKB_KEY_XF86RotationKB, Qt::Key_RotationKB>,
- Xkb2Qt<XKB_KEY_XF86Save, Qt::Key_Save>,
- Xkb2Qt<XKB_KEY_XF86Send, Qt::Key_Send>,
- Xkb2Qt<XKB_KEY_XF86Spell, Qt::Key_Spell>,
- Xkb2Qt<XKB_KEY_XF86SplitScreen, Qt::Key_SplitScreen>,
- Xkb2Qt<XKB_KEY_XF86Support, Qt::Key_Support>,
- Xkb2Qt<XKB_KEY_XF86TaskPane, Qt::Key_TaskPane>,
- Xkb2Qt<XKB_KEY_XF86Terminal, Qt::Key_Terminal>,
- Xkb2Qt<XKB_KEY_XF86Tools, Qt::Key_Tools>,
- Xkb2Qt<XKB_KEY_XF86Travel, Qt::Key_Travel>,
- Xkb2Qt<XKB_KEY_XF86Video, Qt::Key_Video>,
- Xkb2Qt<XKB_KEY_XF86Word, Qt::Key_Word>,
- Xkb2Qt<XKB_KEY_XF86Xfer, Qt::Key_Xfer>,
- Xkb2Qt<XKB_KEY_XF86ZoomIn, Qt::Key_ZoomIn>,
- Xkb2Qt<XKB_KEY_XF86ZoomOut, Qt::Key_ZoomOut>,
- Xkb2Qt<XKB_KEY_XF86Away, Qt::Key_Away>,
- Xkb2Qt<XKB_KEY_XF86Messenger, Qt::Key_Messenger>,
- Xkb2Qt<XKB_KEY_XF86WebCam, Qt::Key_WebCam>,
- Xkb2Qt<XKB_KEY_XF86MailForward, Qt::Key_MailForward>,
- Xkb2Qt<XKB_KEY_XF86Pictures, Qt::Key_Pictures>,
- Xkb2Qt<XKB_KEY_XF86Music, Qt::Key_Music>,
- Xkb2Qt<XKB_KEY_XF86Battery, Qt::Key_Battery>,
- Xkb2Qt<XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth>,
- Xkb2Qt<XKB_KEY_XF86WLAN, Qt::Key_WLAN>,
- Xkb2Qt<XKB_KEY_XF86UWB, Qt::Key_UWB>,
- Xkb2Qt<XKB_KEY_XF86AudioForward, Qt::Key_AudioForward>,
- Xkb2Qt<XKB_KEY_XF86AudioRepeat, Qt::Key_AudioRepeat>,
- Xkb2Qt<XKB_KEY_XF86AudioRandomPlay, Qt::Key_AudioRandomPlay>,
- Xkb2Qt<XKB_KEY_XF86Subtitle, Qt::Key_Subtitle>,
- Xkb2Qt<XKB_KEY_XF86AudioCycleTrack, Qt::Key_AudioCycleTrack>,
- Xkb2Qt<XKB_KEY_XF86Time, Qt::Key_Time>,
- Xkb2Qt<XKB_KEY_XF86Select, Qt::Key_Select>,
- Xkb2Qt<XKB_KEY_XF86View, Qt::Key_View>,
- Xkb2Qt<XKB_KEY_XF86TopMenu, Qt::Key_TopMenu>,
- Xkb2Qt<XKB_KEY_XF86Red, Qt::Key_Red>,
- Xkb2Qt<XKB_KEY_XF86Green, Qt::Key_Green>,
- Xkb2Qt<XKB_KEY_XF86Yellow, Qt::Key_Yellow>,
- Xkb2Qt<XKB_KEY_XF86Blue, Qt::Key_Blue>,
- Xkb2Qt<XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth>,
- Xkb2Qt<XKB_KEY_XF86Suspend, Qt::Key_Suspend>,
- Xkb2Qt<XKB_KEY_XF86Hibernate, Qt::Key_Hibernate>,
- Xkb2Qt<XKB_KEY_XF86TouchpadToggle, Qt::Key_TouchpadToggle>,
- Xkb2Qt<XKB_KEY_XF86TouchpadOn, Qt::Key_TouchpadOn>,
- Xkb2Qt<XKB_KEY_XF86TouchpadOff, Qt::Key_TouchpadOff>,
- Xkb2Qt<XKB_KEY_XF86AudioMicMute, Qt::Key_MicMute>,
- Xkb2Qt<XKB_KEY_XF86Launch0, Qt::Key_Launch2>, // ### Qt 6: remap properly
- Xkb2Qt<XKB_KEY_XF86Launch1, Qt::Key_Launch3>,
- Xkb2Qt<XKB_KEY_XF86Launch2, Qt::Key_Launch4>,
- Xkb2Qt<XKB_KEY_XF86Launch3, Qt::Key_Launch5>,
- Xkb2Qt<XKB_KEY_XF86Launch4, Qt::Key_Launch6>,
- Xkb2Qt<XKB_KEY_XF86Launch5, Qt::Key_Launch7>,
- Xkb2Qt<XKB_KEY_XF86Launch6, Qt::Key_Launch8>,
- Xkb2Qt<XKB_KEY_XF86Launch7, Qt::Key_Launch9>,
- Xkb2Qt<XKB_KEY_XF86Launch8, Qt::Key_LaunchA>,
- Xkb2Qt<XKB_KEY_XF86Launch9, Qt::Key_LaunchB>,
- Xkb2Qt<XKB_KEY_XF86LaunchA, Qt::Key_LaunchC>,
- Xkb2Qt<XKB_KEY_XF86LaunchB, Qt::Key_LaunchD>,
- Xkb2Qt<XKB_KEY_XF86LaunchC, Qt::Key_LaunchE>,
- Xkb2Qt<XKB_KEY_XF86LaunchD, Qt::Key_LaunchF>,
- Xkb2Qt<XKB_KEY_XF86LaunchE, Qt::Key_LaunchG>,
- Xkb2Qt<XKB_KEY_XF86LaunchF, Qt::Key_LaunchH>
- >::Data{}
-);
-
-// Possible modifier states.
-static const Qt::KeyboardModifiers ModsTbl[] = {
- Qt::NoModifier, // 0
- Qt::ShiftModifier, // 1
- Qt::ControlModifier, // 2
- Qt::ControlModifier | Qt::ShiftModifier, // 3
- Qt::AltModifier, // 4
- Qt::AltModifier | Qt::ShiftModifier, // 5
- Qt::AltModifier | Qt::ControlModifier, // 6
- Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
- Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts
-};
+QT_BEGIN_NAMESPACE
Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const
{
- Qt::KeyboardModifiers ret = 0;
+ Qt::KeyboardModifiers ret = Qt::NoModifier;
if (s & XCB_MOD_MASK_SHIFT)
ret |= Qt::ShiftModifier;
if (s & XCB_MOD_MASK_CONTROL)
@@ -473,7 +88,7 @@ static xcb_keysym_t getUnshiftedXKey(xcb_keysym_t unshifted, xcb_keysym_t shifte
xcb_keysym_t xlower;
xcb_keysym_t xupper;
- xkbcommon_XConvertCase(unshifted, &xlower, &xupper);
+ QXkbCommon::xkbcommon_XConvertCase(unshifted, &xlower, &xupper);
if (xlower != xupper // Check if symbol is cased
&& unshifted == xupper) { // Unshifted must be upper case
@@ -805,7 +420,12 @@ void QXcbKeyboard::updateKeymap()
updateXKBMods();
- checkForLatinLayout();
+ QXkbCommon::verifyHasLatinLayout(m_xkbKeymap.get());
+}
+
+QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
+{
+ return QXkbCommon::possibleKeys(m_xkbState.get(), event, m_superAsMeta, m_hyperAsMeta);
}
#if QT_CONFIG(xkb)
@@ -918,272 +538,6 @@ void QXcbKeyboard::updateXKBMods()
xkb_mods.mod5 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod5");
}
-static bool isLatin(xkb_keysym_t sym)
-{
- return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z'));
-}
-
-void QXcbKeyboard::checkForLatinLayout() const
-{
- const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(m_xkbKeymap.get());
- const xcb_keycode_t minKeycode = xkb_keymap_min_keycode(m_xkbKeymap.get());
- const xcb_keycode_t maxKeycode = xkb_keymap_max_keycode(m_xkbKeymap.get());
-
- const xkb_keysym_t *keysyms = nullptr;
- int nrLatinKeys = 0;
- for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
- for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
- xkb_keymap_key_get_syms_by_level(m_xkbKeymap.get(), code, layout, 0, &keysyms);
- if (keysyms && isLatin(keysyms[0]))
- nrLatinKeys++;
- if (nrLatinKeys > 10) // arbitrarily chosen threshold
- return;
- }
- }
- // This means that lookupLatinKeysym() will not find anything and latin
- // key shortcuts might not work. This is a bug in the affected desktop
- // environment. Usually can be solved via system settings by adding e.g. 'us'
- // layout to the list of seleced layouts, or by using command line, "setxkbmap
- // -layout rus,en". The position of latin key based layout in the list of the
- // selected layouts is irrelevant. Properly functioning desktop environments
- // handle this behind the scenes, even if no latin key based layout has been
- // explicitly listed in the selected layouts.
- qCWarning(lcQpaKeyboard, "no keyboard layouts with latin keys present");
-}
-
-xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
-{
- xkb_layout_index_t layout;
- xkb_keysym_t sym = XKB_KEY_NoSymbol;
- const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(m_xkbKeymap.get(), keycode);
- const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(m_xkbState.get(), keycode);
- // Look at user layouts in the order in which they are defined in system
- // settings to find a latin keysym.
- for (layout = 0; layout < layoutCount; ++layout) {
- if (layout == currentLayout)
- continue;
- const xkb_keysym_t *syms;
- xkb_level_index_t level = xkb_state_key_get_level(m_xkbState.get(), keycode, layout);
- if (xkb_keymap_key_get_syms_by_level(m_xkbKeymap.get(), keycode, layout, level, &syms) != 1)
- continue;
- if (isLatin(syms[0])) {
- sym = syms[0];
- break;
- }
- }
-
- if (sym == XKB_KEY_NoSymbol)
- return sym;
-
- xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LATCHED);
- xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LOCKED);
-
- // Check for uniqueness, consider the following setup:
- // setxkbmap -layout us,ru,us -variant dvorak,, -option 'grp:ctrl_alt_toggle' (set 'ru' as active).
- // In this setup, the user would expect to trigger a ctrl+q shortcut by pressing ctrl+<physical x key>,
- // because "US dvorak" is higher up in the layout settings list. This check verifies that an obtained
- // 'sym' can not be acquired by any other layout higher up in the user's layout list. If it can be acquired
- // then the obtained key is not unique. This prevents ctrl+<physical q key> from generating a ctrl+q
- // shortcut in the above described setup. We don't want ctrl+<physical x key> and ctrl+<physical q key> to
- // generate the same shortcut event in this case.
- const xcb_keycode_t minKeycode = xkb_keymap_min_keycode(m_xkbKeymap.get());
- const xcb_keycode_t maxKeycode = xkb_keymap_max_keycode(m_xkbKeymap.get());
- ScopedXKBState state(xkb_state_new(m_xkbKeymap.get()));
- for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) {
- xkb_state_update_mask(state.get(), 0, latchedMods, lockedMods, 0, 0, prevLayout);
- for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
- xkb_keysym_t prevSym = xkb_state_key_get_one_sym(state.get(), code);
- if (prevSym == sym) {
- sym = XKB_KEY_NoSymbol;
- break;
- }
- }
- }
-
- return sym;
-}
-
-static const char *qtKeyName(int qtKey)
-{
- int keyEnumIndex = qt_getQtMetaObject()->indexOfEnumerator("Key");
- QMetaEnum keyEnum = qt_getQtMetaObject()->enumerator(keyEnumIndex);
- return keyEnum.valueToKey(qtKey);
-}
-
-QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
-{
- // turn off the modifier bits which doesn't participate in shortcuts
- Qt::KeyboardModifiers notNeeded = Qt::KeypadModifier | Qt::GroupSwitchModifier;
- Qt::KeyboardModifiers modifiers = event->modifiers() &= ~notNeeded;
- // create a fresh kb state and test against the relevant modifier combinations
- struct xkb_state *kb_state = xkb_state_new(m_xkbKeymap.get());
- if (!kb_state) {
- qWarning("QXcbKeyboard: failed to compile xkb keymap!");
- return QList<int>();
- }
- // get kb state from the master xkb_state and update the temporary kb_state
- xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(m_xkbState.get(), XKB_STATE_LAYOUT_LOCKED);
- xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LATCHED);
- xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LOCKED);
- xkb_mod_mask_t depressedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_DEPRESSED);
-
- xkb_state_update_mask(kb_state, depressedMods, latchedMods, lockedMods, 0, 0, lockedLayout);
- quint32 keycode = event->nativeScanCode();
- // handle shortcuts for level three and above
- xkb_layout_index_t layoutIndex = xkb_state_key_get_layout(kb_state, keycode);
- xkb_level_index_t levelIndex = 0;
- if (layoutIndex != XKB_LAYOUT_INVALID) {
- levelIndex = xkb_state_key_get_level(kb_state, keycode, layoutIndex);
- if (levelIndex == XKB_LEVEL_INVALID)
- levelIndex = 0;
- }
- if (levelIndex <= 1)
- xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods, 0, 0, lockedLayout);
-
- xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, keycode);
- if (sym == XKB_KEY_NoSymbol) {
- xkb_state_unref(kb_state);
- return QList<int>();
- }
-
- QList<int> result;
- int baseQtKey = keysymToQtKey(sym, modifiers, kb_state, keycode);
- if (baseQtKey)
- result += (baseQtKey + modifiers);
-
- xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Shift");
- xkb_mod_index_t altMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Alt");
- xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Control");
- xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Meta");
-
- Q_ASSERT(shiftMod < 32);
- Q_ASSERT(altMod < 32);
- Q_ASSERT(controlMod < 32);
-
- xkb_mod_mask_t depressed;
- int qtKey = 0;
- // obtain a list of possible shortcuts for the given key event
- for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) {
- Qt::KeyboardModifiers neededMods = ModsTbl[i];
- if ((modifiers & neededMods) == neededMods) {
- if (i == 8) {
- if (isLatin(baseQtKey))
- continue;
- // add a latin key as a fall back key
- sym = lookupLatinKeysym(keycode);
- } else {
- depressed = 0;
- if (neededMods & Qt::AltModifier)
- depressed |= (1 << altMod);
- if (neededMods & Qt::ShiftModifier)
- depressed |= (1 << shiftMod);
- if (neededMods & Qt::ControlModifier)
- depressed |= (1 << controlMod);
- if (metaMod < 32 && neededMods & Qt::MetaModifier)
- depressed |= (1 << metaMod);
- xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, 0, 0, lockedLayout);
- sym = xkb_state_key_get_one_sym(kb_state, keycode);
- }
- if (sym == XKB_KEY_NoSymbol)
- continue;
-
- Qt::KeyboardModifiers mods = modifiers & ~neededMods;
- qtKey = keysymToQtKey(sym, mods, kb_state, keycode);
- if (!qtKey || qtKey == baseQtKey)
- continue;
-
- // catch only more specific shortcuts, i.e. Ctrl+Shift+= also generates Ctrl++ and +,
- // but Ctrl++ is more specific than +, so we should skip the last one
- bool ambiguous = false;
- for (int shortcut : qAsConst(result)) {
- if (int(shortcut & ~Qt::KeyboardModifierMask) == qtKey && (shortcut & mods) == mods) {
- ambiguous = true;
- break;
- }
- }
- if (ambiguous)
- continue;
-
- result += (qtKey + mods);
- }
- }
- xkb_state_unref(kb_state);
- return result;
-}
-
-int QXcbKeyboard::keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
- struct xkb_state *state, xcb_keycode_t code) const
-{
- int qtKey = 0;
-
- // lookup from direct mapping
- if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
- // function keys
- qtKey = Qt::Key_F1 + (keysym - XKB_KEY_F1);
- } else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) {
- // numeric keypad keys
- qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0);
- } else if (isLatin(keysym)) {
- qtKey = xkbcommon_xkb_keysym_to_upper(keysym);
- } else {
- // check if we have a direct mapping
- xkb2qt_t searchKey{keysym, 0};
- auto it = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
- if (it != KeyTbl.end() && !(searchKey < *it))
- qtKey = it->qt;
- }
-
- QString text;
- bool fromUnicode = qtKey == 0;
- if (fromUnicode) { // lookup from unicode
- if (modifiers & Qt::ControlModifier) {
- // Control modifier changes the text to ASCII control character, therefore we
- // can't use this text to map keysym to a qt key. We can use the same keysym
- // (it is not affectd by transformation) to obtain untransformed text. For details
- // see "Appendix A. Default Symbol Transformations" in the XKB specification.
- text = lookupStringNoKeysymTransformations(keysym);
- } else {
- text = lookupString(state, code);
- }
- if (!text.isEmpty()) {
- if (text.unicode()->isDigit()) {
- // Ensures that also non-latin digits are mapped to corresponding qt keys,
- // e.g CTRL + Û² (arabic two), is mapped to CTRL + Qt::Key_2.
- qtKey = Qt::Key_0 + text.unicode()->digitValue();
- } else {
- qtKey = text.unicode()->toUpper().unicode();
- }
- }
- }
-
- if (rmod_masks.meta) {
- // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
- if (rmod_masks.meta == rmod_masks.super && (qtKey == Qt::Key_Super_L
- || qtKey == Qt::Key_Super_R)) {
- qtKey = Qt::Key_Meta;
- } else if (rmod_masks.meta == rmod_masks.hyper && (qtKey == Qt::Key_Hyper_L
- || qtKey == Qt::Key_Hyper_R)) {
- qtKey = Qt::Key_Meta;
- }
- }
-
- if (Q_UNLIKELY(lcQpaKeyboard().isDebugEnabled())) {
- char keysymName[64];
- xkb_keysym_get_name(keysym, keysymName, sizeof(keysymName));
- QString keysymInHex = QString(QStringLiteral("0x%1")).arg(keysym, 0, 16);
- if (qtKeyName(qtKey)) {
- qCDebug(lcQpaKeyboard).nospace() << "keysym: " << keysymName << "("
- << keysymInHex << ") mapped to Qt::" << qtKeyName(qtKey) << " | text: " << text
- << " | qt key: " << qtKey << " mapped from unicode number: " << fromUnicode;
- } else {
- qCDebug(lcQpaKeyboard).nospace() << "no Qt::Key for keysym: " << keysymName
- << "(" << keysymInHex << ") | text: " << text << " | qt key: " << qtKey;
- }
- }
-
- return qtKey;
-}
-
QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
: QXcbObject(connection)
{
@@ -1211,6 +565,12 @@ QXcbKeyboard::~QXcbKeyboard()
xcb_key_symbols_free(m_key_symbols);
}
+void QXcbKeyboard::initialize()
+{
+ auto inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
+ QXkbCommon::setXkbContext(inputContext, m_xkbContext.get());
+}
+
void QXcbKeyboard::selectEvents()
{
#if QT_CONFIG(xkb)
@@ -1514,6 +874,12 @@ void QXcbKeyboard::resolveMaskConflicts()
rmod_masks.meta = rmod_masks.hyper;
}
}
+
+ // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
+ if (rmod_masks.meta && rmod_masks.meta == rmod_masks.super)
+ m_superAsMeta = true;
+ if (rmod_masks.meta && rmod_masks.meta == rmod_masks.hyper)
+ m_hyperAsMeta = true;
}
void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, xcb_keycode_t code,
@@ -1529,7 +895,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
if (type == QEvent::KeyPress)
targetWindow->updateNetWmUserTime(time);
- ScopedXKBState sendEventState;
+ QXkbCommon::ScopedXKBState sendEventState;
if (fromSendEvent) {
// Have a temporary keyboard state filled in from state
// this way we allow for synthetic events to have different state
@@ -1546,30 +912,13 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
struct xkb_state *xkbState = fromSendEvent ? sendEventState.get() : m_xkbState.get();
xcb_keysym_t sym = xkb_state_key_get_one_sym(xkbState, code);
- QString text = lookupString(xkbState, code);
+ QString text = QXkbCommon::lookupString(xkbState, code);
Qt::KeyboardModifiers modifiers = translateModifiers(state);
- if (sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9)
+ if (QXkbCommon::isKeypad(sym))
modifiers |= Qt::KeypadModifier;
- // Note 1: All standard key sequences on linux (as defined in platform theme)
- // that use a latin character also contain a control modifier, which is why
- // checking for Qt::ControlModifier is sufficient here. It is possible to
- // override QPlatformTheme::keyBindings() and provide custom sequences for
- // QKeySequence::StandardKey. Custom sequences probably should respect this
- // convention (alternatively, we could test against other modifiers here).
- // Note 2: The possibleKeys() shorcut mechanism is not affected by this value
- // adjustment and does its own thing.
- xcb_keysym_t latinKeysym = XKB_KEY_NoSymbol;
- if (modifiers & Qt::ControlModifier) {
- // With standard shortcuts we should prefer a latin character, this is
- // in checks like "event == QKeySequence::Copy".
- if (!isLatin(sym))
- latinKeysym = lookupLatinKeysym(code);
- }
-
- int qtcode = keysymToQtKey(latinKeysym != XKB_KEY_NoSymbol ? latinKeysym : sym,
- modifiers, xkbState, code);
+ int qtcode = QXkbCommon::keysymToQtKey(sym, modifiers, xkbState, code, m_superAsMeta, m_hyperAsMeta);
if (type == QEvent::KeyPress) {
if (m_isAutoRepeat && m_autoRepeatCode != code)
@@ -1611,28 +960,6 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
}
}
-QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code) const
-{
- QVarLengthArray<char, 32> chars(32);
- const int size = xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
- if (Q_UNLIKELY(size + 1 > chars.size())) { // +1 for NUL
- chars.resize(size + 1);
- xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
- }
- return QString::fromUtf8(chars.constData(), size);
-}
-
-QString QXcbKeyboard::lookupStringNoKeysymTransformations(xkb_keysym_t keysym) const
-{
- QVarLengthArray<char, 32> chars(32);
- const int size = xkb_keysym_to_utf8(keysym, chars.data(), chars.size());
- if (Q_UNLIKELY(size > chars.size())) {
- chars.resize(size);
- xkb_keysym_to_utf8(keysym, chars.data(), chars.size());
- }
- return QString::fromUtf8(chars.constData(), size);
-}
-
static bool fromSendEvent(const void *event)
{
// From X11 protocol: Every event contains an 8-bit type code. The most
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index f8490592b7..e35c82ad24 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -50,16 +50,12 @@
#endif
#include <xkbcommon/xkbcommon.h>
-#if QT_CONFIG(xkb)
-#include <xkbcommon/xkbcommon-x11.h>
-#endif
+#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
#include <QEvent>
QT_BEGIN_NAMESPACE
-class QWindow;
-
class QXcbKeyboard : public QXcbObject
{
public:
@@ -67,6 +63,7 @@ public:
~QXcbKeyboard();
+ void initialize();
void selectEvents();
void handleKeyPressEvent(const xcb_key_press_event_t *event);
@@ -75,7 +72,7 @@ public:
Qt::KeyboardModifiers translateModifiers(int s) const;
void updateKeymap(xcb_mapping_notify_event_t *event);
void updateKeymap();
- QList<int> possibleKeys(const QKeyEvent *e) const;
+ QList<int> possibleKeys(const QKeyEvent *event) const;
// when XKEYBOARD not present on the X server
void updateXKBMods();
@@ -96,10 +93,6 @@ protected:
quint16 state, xcb_timestamp_t time, bool fromSendEvent);
void resolveMaskConflicts();
- QString lookupString(struct xkb_state *state, xcb_keycode_t code) const;
- QString lookupStringNoKeysymTransformations(xkb_keysym_t keysym) const;
- int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
- struct xkb_state *state, xcb_keycode_t code) const;
typedef QMap<xcb_keysym_t, int> KeysymModifierMap;
struct xkb_keymap *keymapFromCore(const KeysymModifierMap &keysymMods);
@@ -111,9 +104,6 @@ protected:
void updateVModMapping();
void updateVModToRModMapping();
- xkb_keysym_t lookupLatinKeysym(xkb_keycode_t keycode) const;
- void checkForLatinLayout() const;
-
private:
bool m_config = false;
bool m_isAutoRepeat = false;
@@ -148,22 +138,12 @@ private:
int core_device_id;
#endif
- struct XKBStateDeleter {
- void operator()(struct xkb_state *state) const { return xkb_state_unref(state); }
- };
- struct XKBKeymapDeleter {
- void operator()(struct xkb_keymap *keymap) const { return xkb_keymap_unref(keymap); }
- };
- struct XKBContextDeleter {
- void operator()(struct xkb_context *context) const { return xkb_context_unref(context); }
- };
- using ScopedXKBState = std::unique_ptr<struct xkb_state, XKBStateDeleter>;
- using ScopedXKBKeymap = std::unique_ptr<struct xkb_keymap, XKBKeymapDeleter>;
- using ScopedXKBContext = std::unique_ptr<struct xkb_context, XKBContextDeleter>;
+ QXkbCommon::ScopedXKBState m_xkbState;
+ QXkbCommon::ScopedXKBKeymap m_xkbKeymap;
+ QXkbCommon::ScopedXKBContext m_xkbContext;
- ScopedXKBState m_xkbState;
- ScopedXKBKeymap m_xkbKeymap;
- ScopedXKBContext m_xkbContext;
+ bool m_superAsMeta = false;
+ bool m_hyperAsMeta = false;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 6f3584f509..81b889a80f 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -304,7 +304,7 @@ QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterface::n
QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterface::nativeResourceFunctionForBackingStore(const QByteArray &resource)
{
const QByteArray lowerCaseResource = resource.toLower();
- NativeResourceForBackingStoreFunction func = handlerNativeResourceFunctionForBackingStore(resource);
+ NativeResourceForBackingStoreFunction func = handlerNativeResourceFunctionForBackingStore(lowerCaseResource);
return func;
}
@@ -636,13 +636,13 @@ static void dumpNativeWindowsRecursion(const QXcbConnection *connection, xcb_win
const QChar oldPadChar =str.padChar();
str.setFieldWidth(8);
str.setPadChar(QLatin1Char('0'));
- str << hex << window;
+ str << Qt::hex << window;
str.setFieldWidth(oldFieldWidth);
str.setPadChar(oldPadChar);
- str << dec << " \""
+ str << Qt::dec << " \""
<< QXcbWindow::windowTitle(connection, window) << "\" "
- << geom.width() << 'x' << geom.height() << forcesign << geom.x() << geom.y()
- << noforcesign << '\n';
+ << geom.width() << 'x' << geom.height() << Qt::forcesign << geom.x() << geom.y()
+ << Qt::noforcesign << '\n';
auto reply = Q_XCB_REPLY(xcb_query_tree, conn, window);
if (reply) {
diff --git a/src/plugins/platforms/xcb/qxcbobject.h b/src/plugins/platforms/xcb/qxcbobject.h
index 1b98d9346b..931bed9ec1 100644
--- a/src/plugins/platforms/xcb/qxcbobject.h
+++ b/src/plugins/platforms/xcb/qxcbobject.h
@@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE
class QXcbObject
{
public:
- QXcbObject(QXcbConnection *connection = 0) : m_connection(connection) {}
+ QXcbObject(QXcbConnection *connection = nullptr) : m_connection(connection) {}
void setConnection(QXcbConnection *connection) { m_connection = connection; }
QXcbConnection *connection() const { return m_connection; }
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 39e83e0451..8c34bd9c91 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -147,7 +147,7 @@ void QXcbVirtualDesktop::setPrimaryScreen(QPlatformScreen *s)
{
const int idx = m_screens.indexOf(s);
Q_ASSERT(idx > -1);
- m_screens.swap(0, idx);
+ m_screens.swapItemsAt(0, idx);
}
QXcbXSettings *QXcbVirtualDesktop::xSettings() const
@@ -925,7 +925,7 @@ QByteArray QXcbScreen::getEdid() const
static inline void formatRect(QDebug &debug, const QRect r)
{
debug << r.width() << 'x' << r.height()
- << forcesign << r.x() << r.y() << noforcesign;
+ << Qt::forcesign << r.x() << r.y() << Qt::noforcesign;
}
static inline void formatSizeF(QDebug &debug, const QSizeF s)
@@ -939,7 +939,7 @@ QDebug operator<<(QDebug debug, const QXcbScreen *screen)
debug.nospace();
debug << "QXcbScreen(" << (const void *)screen;
if (screen) {
- debug << fixed << qSetRealNumberPrecision(1);
+ debug << Qt::fixed << qSetRealNumberPrecision(1);
debug << ", name=" << screen->name();
debug << ", geometry=";
formatRect(debug, screen->geometry());
@@ -957,7 +957,7 @@ QDebug operator<<(QDebug debug, const QXcbScreen *screen)
debug << "), orientation=" << screen->orientation();
debug << ", depth=" << screen->depth();
debug << ", refreshRate=" << screen->refreshRate();
- debug << ", root=" << hex << screen->root();
+ debug << ", root=" << Qt::hex << screen->root();
debug << ", windowManagerName=" << screen->windowManagerName();
}
debug << ')';
diff --git a/src/plugins/platforms/xcb/qxcbsessionmanager.h b/src/plugins/platforms/xcb/qxcbsessionmanager.h
index 0ad9445361..79c587b38d 100644
--- a/src/plugins/platforms/xcb/qxcbsessionmanager.h
+++ b/src/plugins/platforms/xcb/qxcbsessionmanager.h
@@ -85,8 +85,6 @@ public:
private:
QEventLoop *m_eventLoop;
-
- Q_DISABLE_COPY(QXcbSessionManager)
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 3bfcbf2adb..396b47001d 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -843,40 +843,12 @@ void QXcbWindow::doFocusIn()
QWindowSystemInterface::handleWindowActivated(w, Qt::ActiveWindowFocusReason);
}
-static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event)
-{
- if (!event) {
- // FocusIn event is not in the queue, proceed with FocusOut normally.
- QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason);
- return true;
- }
- uint response_type = event->response_type & ~0x80;
- if (response_type == XCB_FOCUS_IN) {
- // Ignore focus events that are being sent only because the pointer is over
- // our window, even if the input focus is in a different window.
- xcb_focus_in_event_t *e = (xcb_focus_in_event_t *) event;
- if (e->detail != XCB_NOTIFY_DETAIL_POINTER)
- return true;
- }
-
- /* We are also interested in XEMBED_FOCUS_IN events */
- if (response_type == XCB_CLIENT_MESSAGE) {
- xcb_client_message_event_t *cme = (xcb_client_message_event_t *)event;
- if (cme->type == connection->atom(QXcbAtom::_XEMBED)
- && cme->data.data32[1] == XEMBED_FOCUS_IN)
- return true;
- }
-
- return false;
-}
-
void QXcbWindow::doFocusOut()
{
connection()->setFocusWindow(nullptr);
relayFocusToModalWindow();
// Do not set the active window to nullptr if there is a FocusIn coming.
- // The FocusIn handler will update QXcbConnection::setFocusWindow() accordingly.
- connection()->addPeekFunc(focusInPeeker);
+ connection()->focusInTimer().start(400);
}
struct QtMotifWmHints {
@@ -1685,7 +1657,11 @@ bool QXcbWindow::requestSystemTrayWindowDock()
bool QXcbWindow::handleNativeEvent(xcb_generic_event_t *event)
{
auto eventType = connection()->nativeInterface()->nativeEventType();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr result = 0; // Used only by MS Windows
+#else
long result = 0; // Used only by MS Windows
+#endif
return QWindowSystemInterface::handleNativeEvent(window(), eventType, event, &result);
}
@@ -2264,6 +2240,8 @@ void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *event)
// our window, even if the input focus is in a different window.
if (event->detail == XCB_NOTIFY_DETAIL_POINTER)
return;
+
+ connection()->focusInTimer().stop();
doFocusIn();
}
@@ -2491,6 +2469,7 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event)
xcbScreen()->windowShown(this);
break;
case XEMBED_FOCUS_IN:
+ connection()->focusInTimer().stop();
Qt::FocusReason reason;
switch (event->data.data32[2]) {
case XEMBED_FOCUS_FIRST:
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 8258cc2dfa..5de5974ca7 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -166,7 +166,7 @@ public:
bool needsSync() const;
void postSyncWindowRequest();
- void clearSyncWindowRequest() { m_pendingSyncRequest = 0; }
+ void clearSyncWindowRequest() { m_pendingSyncRequest = nullptr; }
QXcbScreen *xcbScreen() const;
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index db3d6629b3..34c671c8c7 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -6,7 +6,8 @@ QT += \
core-private gui-private \
service_support-private theme_support-private \
fontdatabase_support-private \
- edid_support-private
+ edid_support-private \
+ xkbcommon_support-private
qtHaveModule(linuxaccessibility_support-private): \
QT += linuxaccessibility_support-private
@@ -52,7 +53,6 @@ HEADERS = \
qxcbimage.h \
qxcbxsettings.h \
qxcbsystemtraytracker.h \
- qxcbxkbcommon.h \
qxcbeventqueue.h \
qxcbeventdispatcher.h \
qxcbconnection_basic.h \
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h
index 4c5f474595..5cfc4df0d0 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h
@@ -72,7 +72,7 @@ public:
QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
QIcon fileIcon(const QFileInfo &fileInfo,
- QPlatformTheme::IconOptions iconOptions = 0) const override;
+ QPlatformTheme::IconOptions iconOptions = nullptr) const override;
QIconEngine *createIconEngine(const QString &iconName) const override;
@@ -84,7 +84,7 @@ public:
private:
QScopedPointer<QXdgDesktopPortalThemePrivate> d_ptr;
- Q_DISABLE_COPY(QXdgDesktopPortalTheme)
+ Q_DISABLE_COPY_MOVE(QXdgDesktopPortalTheme)
};
QT_END_NAMESPACE
diff --git a/src/plugins/printsupport/cups/qcupsprintengine_p.h b/src/plugins/printsupport/cups/qcupsprintengine_p.h
index 2a1a83b9d7..c021b0c643 100644
--- a/src/plugins/printsupport/cups/qcupsprintengine_p.h
+++ b/src/plugins/printsupport/cups/qcupsprintengine_p.h
@@ -77,7 +77,7 @@ public:
// end reimplementations QPdfPrintEngine
private:
- Q_DISABLE_COPY(QCupsPrintEngine)
+ Q_DISABLE_COPY_MOVE(QCupsPrintEngine)
};
class QCupsPrintEnginePrivate : public QPdfPrintEnginePrivate
@@ -91,7 +91,7 @@ public:
void closePrintDevice() override;
private:
- Q_DISABLE_COPY(QCupsPrintEnginePrivate)
+ Q_DISABLE_COPY_MOVE(QCupsPrintEnginePrivate)
void changePrinter(const QString &newPrinter);
void setPageSize(const QPageSize &pageSize);
diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.h b/src/plugins/printsupport/windows/qwindowsprintersupport.h
index 4267701145..400701628e 100644
--- a/src/plugins/printsupport/windows/qwindowsprintersupport.h
+++ b/src/plugins/printsupport/windows/qwindowsprintersupport.h
@@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE
class QWindowsPrinterSupport : public QPlatformPrinterSupport
{
- Q_DISABLE_COPY(QWindowsPrinterSupport)
+ Q_DISABLE_COPY_MOVE(QWindowsPrinterSupport)
public:
QWindowsPrinterSupport();
~QWindowsPrinterSupport() override;
diff --git a/src/plugins/printsupport/windows/windows.pro b/src/plugins/printsupport/windows/windows.pro
index 06694fb7fe..6ca601b2a4 100644
--- a/src/plugins/printsupport/windows/windows.pro
+++ b/src/plugins/printsupport/windows/windows.pro
@@ -18,7 +18,8 @@ HEADERS += \
OTHER_FILES += windows.json
-LIBS += -lwinspool -lcomdlg32 -lgdi32 -luser32
+LIBS += -lwinspool -lcomdlg32
+QMAKE_USE_PRIVATE += user32 gdi32
PLUGIN_TYPE = printsupport
PLUGIN_CLASS_NAME = QWindowsPrinterSupportPlugin
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index f2ae3fbc47..febbe58506 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -197,6 +197,7 @@ protected:
QSqlRecord record() const override;
void virtual_hook(int id, void *data) override;
bool nextResult() override;
+ void detachFromResultSet() override;
#if MYSQL_VERSION_ID >= 40108
bool prepare(const QString &stmt) override;
@@ -804,6 +805,15 @@ int QMYSQLResult::numRowsAffected()
return d->rowsAffected;
}
+void QMYSQLResult::detachFromResultSet()
+{
+ Q_D(QMYSQLResult);
+
+ if (d->preparedQuery) {
+ mysql_stmt_free_result(d->stmt);
+ }
+}
+
QVariant QMYSQLResult::lastInsertId() const
{
Q_D(const QMYSQLResult);
@@ -1541,7 +1551,7 @@ QSqlIndex QMYSQLDriver::primaryIndex(const QString& tablename) const
QSqlQuery i(createResult());
QString stmt(QLatin1String("show index from %1;"));
QSqlRecord fil = record(tablename);
- i.exec(stmt.arg(tablename));
+ i.exec(stmt.arg(escapeIdentifier(tablename, QSqlDriver::TableName)));
while (i.isActive() && i.next()) {
if (i.value(2).toString() == QLatin1String("PRIMARY")) {
idx.append(fil.field(i.value(4).toString()));
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
index 1fbbcd0ef1..7f98efccba 100644
--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
@@ -345,7 +345,7 @@ static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
{
int nativeCode = -1;
QString message = qODBCWarn(p, &nativeCode);
- return QSqlError(QLatin1String("QODBC3: ") + err, qODBCWarn(p), type,
+ return QSqlError(QLatin1String("QODBC3: ") + err, message, type,
nativeCode != -1 ? QString::number(nativeCode) : QString());
}
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc_p.h b/src/plugins/sqldrivers/odbc/qsql_odbc_p.h
index ea0aa6fc8b..ccd0206f38 100644
--- a/src/plugins/sqldrivers/odbc/qsql_odbc_p.h
+++ b/src/plugins/sqldrivers/odbc/qsql_odbc_p.h
@@ -89,8 +89,8 @@ class Q_EXPORT_SQLDRIVER_ODBC QODBCDriver : public QSqlDriver
friend class QODBCResultPrivate;
public:
- explicit QODBCDriver(QObject *parent=0);
- QODBCDriver(SQLHANDLE env, SQLHANDLE con, QObject * parent=0);
+ explicit QODBCDriver(QObject *parent=nullptr);
+ QODBCDriver(SQLHANDLE env, SQLHANDLE con, QObject * parent=nullptr);
virtual ~QODBCDriver();
bool hasFeature(DriverFeature f) const override;
void close() override;
diff --git a/src/plugins/sqldrivers/psql/main.cpp b/src/plugins/sqldrivers/psql/main.cpp
index c5d546f6ff..a0862a238a 100644
--- a/src/plugins/sqldrivers/psql/main.cpp
+++ b/src/plugins/sqldrivers/psql/main.cpp
@@ -61,11 +61,9 @@ QPSQLDriverPlugin::QPSQLDriverPlugin()
QSqlDriver* QPSQLDriverPlugin::create(const QString &name)
{
- if (name == QLatin1String("QPSQL") || name == QLatin1String("QPSQL7")) {
- QPSQLDriver* driver = new QPSQLDriver();
- return driver;
- }
- return 0;
+ if (name == QLatin1String("QPSQL") || name == QLatin1String("QPSQL7"))
+ return new QPSQLDriver;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp
index 7ad9db1ea8..bf9424897d 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql.cpp
+++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp
@@ -42,7 +42,7 @@
#include <qcoreapplication.h>
#include <qvariant.h>
#include <qdatetime.h>
-#include <qregexp.h>
+#include <qregularexpression.h>
#include <qsqlerror.h>
#include <qsqlfield.h>
#include <qsqlindex.h>
@@ -53,6 +53,9 @@
#include <qlocale.h>
#include <QtSql/private/qsqlresult_p.h>
#include <QtSql/private/qsqldriver_p.h>
+#include <QtCore/private/qlocale_tools_p.h>
+
+#include <queue>
#include <libpq-fe.h>
#include <pg_config.h>
@@ -133,7 +136,7 @@ protected:
bool nextResult() override;
QVariant data(int i) override;
bool isNull(int field) override;
- bool reset (const QString &query) override;
+ bool reset(const QString &query) override;
int size() override;
int numRowsAffected() override;
QSqlRecord record() const override;
@@ -147,10 +150,10 @@ class QPSQLDriverPrivate final : public QSqlDriverPrivate
Q_DECLARE_PUBLIC(QPSQLDriver)
public:
QPSQLDriverPrivate() : QSqlDriverPrivate(),
- connection(0),
+ connection(nullptr),
isUtf8(false),
pro(QPSQLDriver::Version6),
- sn(0),
+ sn(nullptr),
pendingNotifyCheck(false),
hasBackslashEscape(false),
stmtCount(0),
@@ -187,11 +190,13 @@ public:
void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type)
{
- QString query = QString::fromLatin1("select pg_class.relname, pg_namespace.nspname from pg_class "
- "left join pg_namespace on (pg_class.relnamespace = pg_namespace.oid) "
- "where (pg_class.relkind = '%1') and (pg_class.relname !~ '^Inv') "
- "and (pg_class.relname !~ '^pg_') "
- "and (pg_namespace.nspname != 'information_schema')").arg(type);
+ const QString query =
+ QStringLiteral("SELECT pg_class.relname, pg_namespace.nspname FROM pg_class "
+ "LEFT JOIN pg_namespace ON (pg_class.relnamespace = pg_namespace.oid) "
+ "WHERE (pg_class.relkind = '") + type +
+ QStringLiteral("') AND (pg_class.relname !~ '^Inv') "
+ "AND (pg_class.relname !~ '^pg_') "
+ "AND (pg_namespace.nspname != 'information_schema')");
t.exec(query);
while (t.next()) {
QString schema = t.value(1).toString();
@@ -294,10 +299,10 @@ public:
Q_DECLARE_SQLDRIVER_PRIVATE(QPSQLDriver)
QPSQLResultPrivate(QPSQLResult *q, const QPSQLDriver *drv)
: QSqlResultPrivate(q, drv),
- result(0),
+ result(nullptr),
+ stmtId(InvalidStatementId),
currentSize(-1),
canFetchMoreRows(false),
- stmtId(InvalidStatementId),
preparedQueriesEnabled(false)
{ }
@@ -305,25 +310,25 @@ public:
void deallocatePreparedStmt();
PGresult *result;
- QList<PGresult*> nextResultSets;
+ std::queue<PGresult*> nextResultSets;
+ QString preparedStmtId;
+ StatementId stmtId;
int currentSize;
bool canFetchMoreRows;
- StatementId stmtId;
bool preparedQueriesEnabled;
- QString preparedStmtId;
bool processResults();
};
-static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
- const QPSQLDriverPrivate *p, PGresult* result = 0)
+static QSqlError qMakeError(const QString &err, QSqlError::ErrorType type,
+ const QPSQLDriverPrivate *p, PGresult *result = nullptr)
{
const char *s = PQerrorMessage(p->connection);
QString msg = p->isUtf8 ? QString::fromUtf8(s) : QString::fromLocal8Bit(s);
QString errorCode;
if (result) {
- errorCode = QString::fromLatin1(PQresultErrorField(result, PG_DIAG_SQLSTATE));
- msg += QString::fromLatin1("(%1)").arg(errorCode);
+ errorCode = QString::fromLatin1(PQresultErrorField(result, PG_DIAG_SQLSTATE));
+ msg += QString::fromLatin1("(%1)").arg(errorCode);
}
return QSqlError(QLatin1String("QPSQL: ") + err, msg, type, errorCode);
}
@@ -423,7 +428,7 @@ static QVariant::Type qDecodePSQLType(int t)
void QPSQLResultPrivate::deallocatePreparedStmt()
{
- const QString stmt = QLatin1String("DEALLOCATE ") + preparedStmtId;
+ const QString stmt = QStringLiteral("DEALLOCATE ") + preparedStmtId;
PGresult *result = drv_d_func()->exec(stmt);
if (PQresultStatus(result) != PGRES_COMMAND_OK)
@@ -432,7 +437,7 @@ void QPSQLResultPrivate::deallocatePreparedStmt()
preparedStmtId.clear();
}
-QPSQLResult::QPSQLResult(const QPSQLDriver* db)
+QPSQLResult::QPSQLResult(const QPSQLDriver *db)
: QSqlResult(*new QPSQLResultPrivate(this, db))
{
Q_D(QPSQLResult);
@@ -460,8 +465,10 @@ void QPSQLResult::cleanup()
if (d->result)
PQclear(d->result);
d->result = nullptr;
- while (!d->nextResultSets.isEmpty())
- PQclear(d->nextResultSets.takeFirst());
+ while (!d->nextResultSets.empty()) {
+ PQclear(d->nextResultSets.front());
+ d->nextResultSets.pop();
+ }
if (d->stmtId != InvalidStatementId) {
if (d->drv_d_func())
d->drv_d_func()->finishQuery(d->stmtId);
@@ -622,7 +629,11 @@ bool QPSQLResult::nextResult()
if (d->result)
PQclear(d->result);
- d->result = d->nextResultSets.isEmpty() ? nullptr : d->nextResultSets.takeFirst();
+ d->result = nullptr;
+ if (!d->nextResultSets.empty()) {
+ d->result = d->nextResultSets.front();
+ d->nextResultSets.pop();
+ }
return d->processResults();
}
@@ -646,34 +657,37 @@ QVariant QPSQLResult::data(int i)
return d->drv_d_func()->isUtf8 ? QString::fromUtf8(val) : QString::fromLatin1(val);
case QVariant::LongLong:
if (val[0] == '-')
- return QString::fromLatin1(val).toLongLong();
+ return QByteArray::fromRawData(val, qstrlen(val)).toLongLong();
else
- return QString::fromLatin1(val).toULongLong();
+ return QByteArray::fromRawData(val, qstrlen(val)).toULongLong();
case QVariant::Int:
return atoi(val);
case QVariant::Double: {
if (ptype == QNUMERICOID) {
- if (numericalPrecisionPolicy() != QSql::HighPrecision) {
- QVariant retval;
- bool convert;
- double dbl=QString::fromLatin1(val).toDouble(&convert);
- if (numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
- retval = (qlonglong)dbl;
- else if (numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
- retval = (int)dbl;
- else if (numericalPrecisionPolicy() == QSql::LowPrecisionDouble)
- retval = dbl;
- if (!convert)
- return QVariant();
- return retval;
- }
- return QString::fromLatin1(val);
+ if (numericalPrecisionPolicy() == QSql::HighPrecision)
+ return QString::fromLatin1(val);
+ }
+ bool ok;
+ double dbl = qstrtod(val, nullptr, &ok);
+ if (!ok) {
+ if (qstricmp(val, "NaN") == 0)
+ dbl = qQNaN();
+ else if (qstricmp(val, "Infinity") == 0)
+ dbl = qInf();
+ else if (qstricmp(val, "-Infinity") == 0)
+ dbl = -qInf();
+ else
+ return QVariant();
}
- if (qstricmp(val, "Infinity") == 0)
- return qInf();
- if (qstricmp(val, "-Infinity") == 0)
- return -qInf();
- return QString::fromLatin1(val).toDouble();
+ if (ptype == QNUMERICOID) {
+ if (numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
+ return QVariant((qlonglong)dbl);
+ else if (numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
+ return QVariant((int)dbl);
+ else if (numericalPrecisionPolicy() == QSql::LowPrecisionDouble)
+ return QVariant(dbl);
+ }
+ return dbl;
}
case QVariant::Date:
if (val[0] == '\0') {
@@ -701,7 +715,7 @@ QVariant QPSQLResult::data(int i)
#if QT_CONFIG(datestring)
if (dtval.length() < 10) {
return QVariant(QDateTime());
- } else {
+ } else {
QChar sign = dtval[dtval.size() - 3];
if (sign == QLatin1Char('-') || sign == QLatin1Char('+')) dtval += QLatin1String(":00");
return QVariant(QDateTime::fromString(dtval, Qt::ISODate).toLocalTime());
@@ -731,7 +745,7 @@ bool QPSQLResult::isNull(int field)
return PQgetisnull(d->result, currentRow, field);
}
-bool QPSQLResult::reset (const QString& query)
+bool QPSQLResult::reset(const QString &query)
{
Q_D(QPSQLResult);
cleanup();
@@ -754,7 +768,7 @@ bool QPSQLResult::reset (const QString& query)
if (!isForwardOnly()) {
// Fetch all result sets right away
while (PGresult *nextResultSet = d->drv_d_func()->getResult(d->stmtId))
- d->nextResultSets.append(nextResultSet);
+ d->nextResultSets.push(nextResultSet);
}
return d->processResults();
}
@@ -768,7 +782,8 @@ int QPSQLResult::size()
int QPSQLResult::numRowsAffected()
{
Q_D(const QPSQLResult);
- return QString::fromLatin1(PQcmdTuples(d->result)).toInt();
+ const char *tuples = PQcmdTuples(d->result);
+ return QByteArray::fromRawData(tuples, qstrlen(tuples)).toInt();
}
QVariant QPSQLResult::lastInsertId() const
@@ -777,7 +792,7 @@ QVariant QPSQLResult::lastInsertId() const
if (d->drv_d_func()->pro >= QPSQLDriver::Version8_1) {
QSqlQuery qry(driver()->createResult());
// Most recent sequence value obtained from nextval
- if (qry.exec(QLatin1String("SELECT lastval();")) && qry.next())
+ if (qry.exec(QStringLiteral("SELECT lastval();")) && qry.next())
return qry.value(0);
} else if (isActive()) {
Oid id = PQoidValue(d->result);
@@ -857,7 +872,6 @@ QSqlRecord QPSQLResult::record() const
void QPSQLResult::virtual_hook(int id, void *data)
{
Q_ASSERT(data);
-
QSqlResult::virtual_hook(id, data);
}
@@ -868,15 +882,13 @@ static QString qCreateParamString(const QVector<QVariant> &boundValues, const QS
QString params;
QSqlField f;
- for (int i = 0; i < boundValues.count(); ++i) {
- const QVariant &val = boundValues.at(i);
-
+ for (const QVariant &val : boundValues) {
f.setType(val.type());
if (val.isNull())
f.clear();
else
f.setValue(val);
- if(!params.isNull())
+ if (!params.isNull())
params.append(QLatin1String(", "));
params.append(driver->formatValue(f));
}
@@ -886,7 +898,7 @@ static QString qCreateParamString(const QVector<QVariant> &boundValues, const QS
QString qMakePreparedStmtId()
{
static QBasicAtomicInt qPreparedStmtCount = Q_BASIC_ATOMIC_INITIALIZER(0);
- QString id = QLatin1String("qpsqlpstmt_") + QString::number(qPreparedStmtCount.fetchAndAddRelaxed(1) + 1, 16);
+ QString id = QStringLiteral("qpsqlpstmt_") + QString::number(qPreparedStmtCount.fetchAndAddRelaxed(1) + 1, 16);
return id;
}
@@ -902,7 +914,7 @@ bool QPSQLResult::prepare(const QString &query)
d->deallocatePreparedStmt();
const QString stmtId = qMakePreparedStmtId();
- const QString stmt = QString::fromLatin1("PREPARE %1 AS ").arg(stmtId).append(d->positionalToNamedBinding(query));
+ const QString stmt = QStringLiteral("PREPARE %1 AS ").arg(stmtId).append(d->positionalToNamedBinding(query));
PGresult *result = d->drv_d_func()->exec(stmt);
@@ -930,9 +942,9 @@ bool QPSQLResult::exec()
QString stmt;
const QString params = qCreateParamString(boundValues(), driver());
if (params.isEmpty())
- stmt = QString::fromLatin1("EXECUTE %1").arg(d->preparedStmtId);
+ stmt = QStringLiteral("EXECUTE %1").arg(d->preparedStmtId);
else
- stmt = QString::fromLatin1("EXECUTE %1 (%2)").arg(d->preparedStmtId, params);
+ stmt = QStringLiteral("EXECUTE %1 (%2)").arg(d->preparedStmtId, params);
d->stmtId = d->drv_d_func()->sendQuery(stmt);
if (d->stmtId == InvalidStatementId) {
@@ -948,7 +960,7 @@ bool QPSQLResult::exec()
if (!isForwardOnly()) {
// Fetch all result sets right away
while (PGresult *nextResultSet = d->drv_d_func()->getResult(d->stmtId))
- d->nextResultSets.append(nextResultSet);
+ d->nextResultSets.push(nextResultSet);
}
return d->processResults();
}
@@ -957,7 +969,7 @@ bool QPSQLResult::exec()
bool QPSQLDriverPrivate::setEncodingUtf8()
{
- PGresult* result = exec("SET CLIENT_ENCODING TO 'UNICODE'");
+ PGresult *result = exec("SET CLIENT_ENCODING TO 'UNICODE'");
int status = PQresultStatus(result);
PQclear(result);
return status == PGRES_COMMAND_OK;
@@ -965,7 +977,7 @@ bool QPSQLDriverPrivate::setEncodingUtf8()
void QPSQLDriverPrivate::setDatestyle()
{
- PGresult* result = exec("SET DATESTYLE TO 'ISO'");
+ PGresult *result = exec("SET DATESTYLE TO 'ISO'");
int status = PQresultStatus(result);
if (status != PGRES_COMMAND_OK)
qWarning("%s", PQerrorMessage(connection));
@@ -994,7 +1006,7 @@ void QPSQLDriverPrivate::detectBackslashEscape()
hasBackslashEscape = true;
} else {
hasBackslashEscape = false;
- PGresult* result = exec(QLatin1String("SELECT '\\\\' x"));
+ PGresult *result = exec(QStringLiteral("SELECT '\\\\' x"));
int status = PQresultStatus(result);
if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK)
if (QString::fromLatin1(PQgetvalue(result, 0, 0)) == QLatin1String("\\"))
@@ -1072,20 +1084,21 @@ static QPSQLDriver::Protocol qMakePSQLVersion(int vMaj, int vMin)
static QPSQLDriver::Protocol qFindPSQLVersion(const QString &versionString)
{
- const QRegExp rx(QStringLiteral("(\\d+)(?:\\.(\\d+))?"));
- if (rx.indexIn(versionString) != -1) {
+ const QRegularExpression rx(QStringLiteral("(\\d+)(?:\\.(\\d+))?"));
+ const QRegularExpressionMatch match = rx.match(versionString);
+ if (match.hasMatch()) {
// Beginning with PostgreSQL version 10, a major release is indicated by
// increasing the first part of the version, e.g. 10 to 11.
// Before version 10, a major release was indicated by increasing either
// the first or second part of the version number, e.g. 9.5 to 9.6.
- int vMaj = rx.cap(1).toInt();
+ int vMaj = match.capturedRef(1).toInt();
int vMin;
if (vMaj >= 10) {
vMin = 0;
} else {
- if (rx.cap(2).isEmpty())
+ if (match.capturedRef(2).isEmpty())
return QPSQLDriver::VersionUnknown;
- vMin = rx.cap(2).toInt();
+ vMin = match.capturedRef(2).toInt();
}
return qMakePSQLVersion(vMaj, vMin);
}
@@ -1096,7 +1109,7 @@ static QPSQLDriver::Protocol qFindPSQLVersion(const QString &versionString)
QPSQLDriver::Protocol QPSQLDriverPrivate::getPSQLVersion()
{
QPSQLDriver::Protocol serverVersion = QPSQLDriver::Version6;
- PGresult* result = exec("select version()");
+ PGresult *result = exec("SELECT version()");
int status = PQresultStatus(result);
if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK) {
serverVersion = qFindPSQLVersion(
@@ -1202,12 +1215,12 @@ static QString qQuote(QString s)
return s;
}
-bool QPSQLDriver::open(const QString & db,
- const QString & user,
- const QString & password,
- const QString & host,
- int port,
- const QString& connOpts)
+bool QPSQLDriver::open(const QString &db,
+ const QString &user,
+ const QString &password,
+ const QString &host,
+ int port,
+ const QString &connOpts)
{
Q_D(QPSQLDriver);
if (isOpen())
@@ -1236,7 +1249,7 @@ bool QPSQLDriver::open(const QString & db,
setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d));
setOpenError(true);
PQfinish(d->connection);
- d->connection = 0;
+ d->connection = nullptr;
return false;
}
@@ -1260,12 +1273,12 @@ void QPSQLDriver::close()
if (d->sn) {
disconnect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int)));
delete d->sn;
- d->sn = 0;
+ d->sn = nullptr;
}
if (d->connection)
PQfinish(d->connection);
- d->connection = 0;
+ d->connection = nullptr;
setOpen(false);
setOpenError(false);
}
@@ -1283,7 +1296,7 @@ bool QPSQLDriver::beginTransaction()
qWarning("QPSQLDriver::beginTransaction: Database not open");
return false;
}
- PGresult* res = d->exec("BEGIN");
+ PGresult *res = d->exec("BEGIN");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Could not begin transaction"),
QSqlError::TransactionError, d, res));
@@ -1301,7 +1314,7 @@ bool QPSQLDriver::commitTransaction()
qWarning("QPSQLDriver::commitTransaction: Database not open");
return false;
}
- PGresult* res = d->exec("COMMIT");
+ PGresult *res = d->exec("COMMIT");
bool transaction_failed = false;
@@ -1330,7 +1343,7 @@ bool QPSQLDriver::rollbackTransaction()
qWarning("QPSQLDriver::rollbackTransaction: Database not open");
return false;
}
- PGresult* res = d->exec("ROLLBACK");
+ PGresult *res = d->exec("ROLLBACK");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Could not rollback transaction"),
QSqlError::TransactionError, d, res));
@@ -1355,8 +1368,8 @@ QStringList QPSQLDriver::tables(QSql::TableType type) const
if (type & QSql::Views)
const_cast<QPSQLDriverPrivate*>(d)->appendTables(tl, t, QLatin1Char('v'));
if (type & QSql::SystemTables) {
- t.exec(QLatin1String("select relname from pg_class where (relkind = 'r') "
- "and (relname like 'pg_%') "));
+ t.exec(QStringLiteral("SELECT relname FROM pg_class WHERE (relkind = 'r') "
+ "AND (relname LIKE 'pg_%') "));
while (t.next())
tl.append(t.value(0).toString());
}
@@ -1373,7 +1386,7 @@ static void qSplitTableName(QString &tablename, QString &schema)
tablename = tablename.mid(dot + 1);
}
-QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
+QSqlIndex QPSQLDriver::primaryIndex(const QString &tablename) const
{
QSqlIndex idx(tablename);
if (!isOpen())
@@ -1383,31 +1396,23 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
QString tbl = tablename;
QString schema;
qSplitTableName(tbl, schema);
-
- if (isIdentifierEscaped(tbl, QSqlDriver::TableName))
- tbl = stripDelimiters(tbl, QSqlDriver::TableName);
- else
- tbl = std::move(tbl).toLower();
-
- if (isIdentifierEscaped(schema, QSqlDriver::TableName))
- schema = stripDelimiters(schema, QSqlDriver::TableName);
- else
- schema = std::move(schema).toLower();
-
- QString stmt = QLatin1String("SELECT pg_attribute.attname, pg_attribute.atttypid::int, "
- "pg_class.relname "
- "FROM pg_attribute, pg_class "
- "WHERE %1 pg_class.oid IN "
- "(SELECT indexrelid FROM pg_index WHERE indisprimary = true AND indrelid IN "
- "(SELECT oid FROM pg_class WHERE relname = '%2')) "
- "AND pg_attribute.attrelid = pg_class.oid "
- "AND pg_attribute.attisdropped = false "
- "ORDER BY pg_attribute.attnum");
+ schema = stripDelimiters(schema, QSqlDriver::TableName);
+ tbl = stripDelimiters(tbl, QSqlDriver::TableName);
+
+ QString stmt = QStringLiteral("SELECT pg_attribute.attname, pg_attribute.atttypid::int, "
+ "pg_class.relname "
+ "FROM pg_attribute, pg_class "
+ "WHERE %1 pg_class.oid IN "
+ "(SELECT indexrelid FROM pg_index WHERE indisprimary = true AND indrelid IN "
+ "(SELECT oid FROM pg_class WHERE relname = '%2')) "
+ "AND pg_attribute.attrelid = pg_class.oid "
+ "AND pg_attribute.attisdropped = false "
+ "ORDER BY pg_attribute.attnum");
if (schema.isEmpty())
- stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid) AND"));
+ stmt = stmt.arg(QStringLiteral("pg_table_is_visible(pg_class.oid) AND"));
else
- stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
- "pg_namespace where pg_namespace.nspname = '%1') AND").arg(schema));
+ stmt = stmt.arg(QStringLiteral("pg_class.relnamespace = (SELECT oid FROM "
+ "pg_namespace WHERE pg_namespace.nspname = '%1') AND").arg(schema));
i.exec(stmt.arg(tbl));
while (i.isActive() && i.next()) {
@@ -1418,7 +1423,7 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
return idx;
}
-QSqlRecord QPSQLDriver::record(const QString& tablename) const
+QSqlRecord QPSQLDriver::record(const QString &tablename) const
{
QSqlRecord info;
if (!isOpen())
@@ -1427,34 +1432,26 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
QString tbl = tablename;
QString schema;
qSplitTableName(tbl, schema);
-
- if (isIdentifierEscaped(tbl, QSqlDriver::TableName))
- tbl = stripDelimiters(tbl, QSqlDriver::TableName);
- else
- tbl = std::move(tbl).toLower();
-
- if (isIdentifierEscaped(schema, QSqlDriver::TableName))
- schema = stripDelimiters(schema, QSqlDriver::TableName);
- else
- schema = std::move(schema).toLower();
-
- QString stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
- "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
- "pg_attrdef.adsrc "
- "from pg_class, pg_attribute "
- "left join pg_attrdef on (pg_attrdef.adrelid = "
- "pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
- "where %1 "
- "and pg_class.relname = '%2' "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid "
- "and pg_attribute.attisdropped = false "
- "order by pg_attribute.attnum");
+ schema = stripDelimiters(schema, QSqlDriver::TableName);
+ tbl = stripDelimiters(tbl, QSqlDriver::TableName);
+
+ QString stmt = QStringLiteral("SELECT pg_attribute.attname, pg_attribute.atttypid::int, "
+ "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
+ "pg_attrdef.adsrc "
+ "FROM pg_class, pg_attribute "
+ "LEFT JOIN pg_attrdef ON (pg_attrdef.adrelid = "
+ "pg_attribute.attrelid AND pg_attrdef.adnum = pg_attribute.attnum) "
+ "WHERE %1 "
+ "AND pg_class.relname = '%2' "
+ "AND pg_attribute.attnum > 0 "
+ "AND pg_attribute.attrelid = pg_class.oid "
+ "AND pg_attribute.attisdropped = false "
+ "ORDER BY pg_attribute.attnum");
if (schema.isEmpty())
- stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid)"));
+ stmt = stmt.arg(QStringLiteral("pg_table_is_visible(pg_class.oid)"));
else
- stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
- "pg_namespace where pg_namespace.nspname = '%1')").arg(schema));
+ stmt = stmt.arg(QStringLiteral("pg_class.relnamespace = (SELECT oid FROM "
+ "pg_namespace WHERE pg_namespace.nspname = '%1')").arg(schema));
QSqlQuery query(createResult());
query.exec(stmt.arg(tbl));
@@ -1496,9 +1493,10 @@ inline void assignSpecialPsqlFloatValue(FloatType val, QString *target)
QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
{
Q_D(const QPSQLDriver);
+ const auto nullStr = [](){ return QStringLiteral("NULL"); };
QString r;
if (field.isNull()) {
- r = QLatin1String("NULL");
+ r = nullStr();
} else {
switch (int(field.type())) {
case QVariant::DateTime:
@@ -1507,36 +1505,36 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
// we force the value to be considered with a timezone information, and we force it to be UTC
// this is safe since postgresql stores only the UTC value and not the timezone offset (only used
// while parsing), so we have correct behavior in both case of with timezone and without tz
- r = QLatin1String("TIMESTAMP WITH TIME ZONE ") + QLatin1Char('\'') +
- QLocale::c().toString(field.value().toDateTime().toUTC(), QLatin1String("yyyy-MM-ddThh:mm:ss.zzz")) +
+ r = QStringLiteral("TIMESTAMP WITH TIME ZONE ") + QLatin1Char('\'') +
+ QLocale::c().toString(field.value().toDateTime().toUTC(), QStringViewLiteral("yyyy-MM-ddThh:mm:ss.zzz")) +
QLatin1Char('Z') + QLatin1Char('\'');
} else {
- r = QLatin1String("NULL");
+ r = nullStr();
}
#else
- r = QLatin1String("NULL");
+ r = nullStr();
#endif // datestring
break;
case QVariant::Time:
#if QT_CONFIG(datestring)
if (field.value().toTime().isValid()) {
- r = QLatin1Char('\'') + field.value().toTime().toString(QLatin1String("hh:mm:ss.zzz")) + QLatin1Char('\'');
+ r = QLatin1Char('\'') + field.value().toTime().toString(QStringViewLiteral("hh:mm:ss.zzz")) + QLatin1Char('\'');
} else
#endif
{
- r = QLatin1String("NULL");
+ r = nullStr();
}
break;
case QVariant::String:
r = QSqlDriver::formatValue(field, trimStrings);
if (d->hasBackslashEscape)
- r.replace(QLatin1String("\\"), QLatin1String("\\\\"));
+ r.replace(QLatin1Char('\\'), QLatin1String("\\\\"));
break;
case QVariant::Bool:
if (field.value().toBool())
- r = QLatin1String("TRUE");
+ r = QStringLiteral("TRUE");
else
- r = QLatin1String("FALSE");
+ r = QStringLiteral("FALSE");
break;
case QVariant::ByteArray: {
QByteArray ba(field.value().toByteArray());
@@ -1576,7 +1574,7 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
QString QPSQLDriver::escapeIdentifier(const QString &identifier, IdentifierType) const
{
QString res = identifier;
- if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
+ if (!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
res.replace(QLatin1Char('"'), QLatin1String("\"\""));
res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
res.replace(QLatin1Char('.'), QLatin1String("\".\""));
@@ -1615,7 +1613,7 @@ bool QPSQLDriver::subscribeToNotification(const QString &name)
// Add the name to the list of subscriptions here so that QSQLDriverPrivate::exec knows
// to check for notifications immediately after executing the LISTEN
d->seid << name;
- QString query = QLatin1String("LISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
+ QString query = QStringLiteral("LISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
PGresult *result = d->exec(query);
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
d->seid.removeLast();
@@ -1651,7 +1649,7 @@ bool QPSQLDriver::unsubscribeFromNotification(const QString &name)
return false;
}
- QString query = QLatin1String("UNLISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
+ QString query = QStringLiteral("UNLISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
PGresult *result = d->exec(query);
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
setLastError(qMakeError(tr("Unable to unsubscribe"), QSqlError::StatementError, d, result));
@@ -1665,7 +1663,7 @@ bool QPSQLDriver::unsubscribeFromNotification(const QString &name)
if (d->seid.isEmpty()) {
disconnect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int)));
delete d->sn;
- d->sn = 0;
+ d->sn = nullptr;
}
return true;
@@ -1683,8 +1681,8 @@ void QPSQLDriver::_q_handleNotification(int)
d->pendingNotifyCheck = false;
PQconsumeInput(d->connection);
- PGnotify *notify = 0;
- while((notify = PQnotifies(d->connection)) != 0) {
+ PGnotify *notify = nullptr;
+ while ((notify = PQnotifies(d->connection)) != nullptr) {
QString name(QLatin1String(notify->relname));
if (d->seid.contains(name)) {
QString payload;
diff --git a/src/plugins/sqldrivers/psql/qsql_psql_p.h b/src/plugins/sqldrivers/psql/qsql_psql_p.h
index 7e1849d857..99e0b5f60f 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql_p.h
+++ b/src/plugins/sqldrivers/psql/qsql_psql_p.h
@@ -96,22 +96,22 @@ public:
UnknownLaterVersion = 100000
};
- explicit QPSQLDriver(QObject *parent=0);
- explicit QPSQLDriver(PGconn *conn, QObject *parent=0);
+ explicit QPSQLDriver(QObject *parent = nullptr);
+ explicit QPSQLDriver(PGconn *conn, QObject *parent = nullptr);
~QPSQLDriver();
bool hasFeature(DriverFeature f) const override;
- bool open(const QString & db,
- const QString & user,
- const QString & password,
- const QString & host,
+ bool open(const QString &db,
+ const QString &user,
+ const QString &password,
+ const QString &host,
int port,
- const QString& connOpts) override;
+ const QString &connOpts) override;
bool isOpen() const override;
void close() override;
QSqlResult *createResult() const override;
QStringList tables(QSql::TableType) const override;
- QSqlIndex primaryIndex(const QString& tablename) const override;
- QSqlRecord record(const QString& tablename) const override;
+ QSqlIndex primaryIndex(const QString &tablename) const override;
+ QSqlRecord record(const QString &tablename) const override;
Protocol protocol() const;
QVariant handle() const override;
diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite_p.h b/src/plugins/sqldrivers/sqlite/qsql_sqlite_p.h
index 61be4c937f..c7952bca9a 100644
--- a/src/plugins/sqldrivers/sqlite/qsql_sqlite_p.h
+++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite_p.h
@@ -72,8 +72,8 @@ class Q_EXPORT_SQLDRIVER_SQLITE QSQLiteDriver : public QSqlDriver
Q_OBJECT
friend class QSQLiteResultPrivate;
public:
- explicit QSQLiteDriver(QObject *parent = 0);
- explicit QSQLiteDriver(sqlite3 *connection, QObject *parent = 0);
+ explicit QSQLiteDriver(QObject *parent = nullptr);
+ explicit QSQLiteDriver(sqlite3 *connection, QObject *parent = nullptr);
~QSQLiteDriver();
bool hasFeature(DriverFeature f) const override;
bool open(const QString & db,
diff --git a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp
index 390f05c7aa..b7bcd044ab 100644
--- a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp
+++ b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp
@@ -43,7 +43,6 @@
#include <qvariant.h>
#include <qdatetime.h>
#include <qfile.h>
-#include <qregexp.h>
#include <qsqlerror.h>
#include <qsqlfield.h>
#include <qsqlindex.h>
diff --git a/src/plugins/sqldrivers/sqlite2/smain.cpp b/src/plugins/sqldrivers/sqlite2/smain.cpp
index 3a5734f8c9..7d971d6e5a 100644
--- a/src/plugins/sqldrivers/sqlite2/smain.cpp
+++ b/src/plugins/sqldrivers/sqlite2/smain.cpp
@@ -43,6 +43,7 @@
QT_BEGIN_NAMESPACE
+// ### Qt6: remove, obsolete since 5.14
class QSQLite2DriverPlugin : public QSqlDriverPlugin
{
Q_OBJECT
diff --git a/src/plugins/sqldrivers/tds/main.cpp b/src/plugins/sqldrivers/tds/main.cpp
index 4aa1444608..18efb22ea4 100644
--- a/src/plugins/sqldrivers/tds/main.cpp
+++ b/src/plugins/sqldrivers/tds/main.cpp
@@ -50,6 +50,7 @@
QT_BEGIN_NAMESPACE
+// ### Qt6: remove, obsolete since 4.7
class QTDSDriverPlugin : public QSqlDriverPlugin
{
Q_OBJECT
diff --git a/src/plugins/sqldrivers/tds/qsql_tds.cpp b/src/plugins/sqldrivers/tds/qsql_tds.cpp
index ad95b097ef..603372230d 100644
--- a/src/plugins/sqldrivers/tds/qsql_tds.cpp
+++ b/src/plugins/sqldrivers/tds/qsql_tds.cpp
@@ -813,7 +813,7 @@ QString QTDSDriver::formatValue(const QSqlField &field,
r = QLatin1String("NULL");
else if (field.type() == QVariant::DateTime) {
if (field.value().toDateTime().isValid()){
- r = field.value().toDateTime().toString(QLatin1String("yyyyMMdd hh:mm:ss"));
+ r = field.value().toDateTime().toString(QStringViewLiteral("yyyyMMdd hh:mm:ss"));
r.prepend(QLatin1String("'"));
r.append(QLatin1String("'"));
} else
diff --git a/src/plugins/styles/android/qandroidstyle_p.h b/src/plugins/styles/android/qandroidstyle_p.h
index 3faa08afb9..6cb30a2f79 100644
--- a/src/plugins/styles/android/qandroidstyle_p.h
+++ b/src/plugins/styles/android/qandroidstyle_p.h
@@ -371,7 +371,7 @@ public:
void unpolish(QWidget *widget);
private:
- Q_DISABLE_COPY(QAndroidStyle)
+ Q_DISABLE_COPY_MOVE(QAndroidStyle)
static ItemType qtControl(QStyle::ComplexControl control);
static ItemType qtControl(QStyle::ContentsType contentsType);
static ItemType qtControl(QStyle::ControlElement controlElement);
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index ce08725684..6c4605b5d2 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -50,92 +50,30 @@
#define QMAC_QAQUASTYLE_SIZE_CONSTRAIN
//#define DEBUG_SIZE_CONSTRAINT
-#include <private/qcore_mac_p.h>
-#if QT_CONFIG(tabbar)
-#include <private/qtabbar_p.h>
-#endif
-#include <private/qpainter_p.h>
-#include <qapplication.h>
-#include <qbitmap.h>
-#if QT_CONFIG(combobox)
-#include <private/qcombobox_p.h>
-#include <qcombobox.h>
-#endif
-#if QT_CONFIG(dialogbuttonbox)
-#include <qdialogbuttonbox.h>
-#endif
-#if QT_CONFIG(dockwidget)
-#include <qdockwidget.h>
-#endif
-#include <qevent.h>
-#include <qfocusframe.h>
-#include <qformlayout.h>
-#include <qgroupbox.h>
-#include <qhash.h>
-#include <qheaderview.h>
-#if QT_CONFIG(lineedit)
-#include <qlineedit.h>
-#endif
-#if QT_CONFIG(mainwindow)
-#include <qmainwindow.h>
-#endif
+#include <QtCore/qoperatingsystemversion.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qvarlengtharray.h>
+
+#include <QtCore/private/qcore_mac_p.h>
+
+#include <QtGui/private/qcoregraphics_p.h>
+#include <QtGui/qpa/qplatformfontdatabase.h>
+#include <QtGui/qpa/qplatformtheme.h>
+
+#include <QtWidgets/private/qstyleanimation_p.h>
+
#if QT_CONFIG(mdiarea)
-#include <qmdisubwindow.h>
-#endif
-#if QT_CONFIG(menubar)
-#include <qmenubar.h>
-#endif
-#include <qpaintdevice.h>
-#include <qpainter.h>
-#include <qpixmapcache.h>
-#include <qpointer.h>
-#if QT_CONFIG(progressbar)
-#include <qprogressbar.h>
-#endif
-#if QT_CONFIG(pushbutton)
-#include <qpushbutton.h>
-#endif
-#include <qradiobutton.h>
-#if QT_CONFIG(rubberband)
-#include <qrubberband.h>
+#include <QtWidgets/qmdisubwindow.h>
#endif
#if QT_CONFIG(scrollbar)
-#include <qscrollbar.h>
-#endif
-#if QT_CONFIG(sizegrip)
-#include <qsizegrip.h>
+#include <QtWidgets/qscrollbar.h>
#endif
-#include <qstyleoption.h>
-#include <qtoolbar.h>
-#if QT_CONFIG(toolbutton)
-#include <qtoolbutton.h>
-#endif
-#if QT_CONFIG(treeview)
-#include <qtreeview.h>
-#endif
-#if QT_CONFIG(tableview)
-#include <qtableview.h>
+#if QT_CONFIG(tabbar)
+#include <QtWidgets/private/qtabbar_p.h>
#endif
-#include <qoperatingsystemversion.h>
#if QT_CONFIG(wizard)
-#include <qwizard.h>
-#endif
-#include <qdebug.h>
-#if QT_CONFIG(datetimeedit)
-#include <qdatetimeedit.h>
-#endif
-#include <qmath.h>
-#include <QtWidgets/qgraphicsproxywidget.h>
-#if QT_CONFIG(graphicsview)
-#include <QtWidgets/qgraphicsview.h>
+#include <QtWidgets/qwizard.h>
#endif
-#include <QtCore/qvariant.h>
-#include <QtCore/qvarlengtharray.h>
-#include <private/qstylehelper_p.h>
-#include <private/qstyleanimation_p.h>
-#include <qpa/qplatformfontdatabase.h>
-#include <qpa/qplatformtheme.h>
-#include <QtGui/private/qcoregraphics_p.h>
QT_USE_NAMESPACE
@@ -886,8 +824,10 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
else if (qobject_cast<const QLineEdit *>(widg))
ct = QStyle::CT_LineEdit;
#endif
+#if QT_CONFIG(itemviews)
else if (qobject_cast<const QHeaderView *>(widg))
ct = QStyle::CT_HeaderSection;
+#endif
#if QT_CONFIG(menubar)
else if (qobject_cast<const QMenuBar *>(widg))
ct = QStyle::CT_MenuBar;
@@ -2863,9 +2803,11 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay;
}
break;
+#if QT_CONFIG(itemviews)
case SH_ItemView_ScrollMode:
ret = QAbstractItemView::ScrollPerPixel;
break;
+#endif
case SH_TitleBar_ShowToolTipsOnButtons:
// min/max/close buttons on windows don't show tool tips
ret = false;
@@ -4081,7 +4023,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
titleRect.width());
const auto text = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width());
- proxy()->drawItemText(p, titleRect, Qt::AlignCenter | Qt::TextShowMnemonic, dwOpt->palette,
+ proxy()->drawItemText(p, titleRect, Qt::AlignCenter, dwOpt->palette,
dwOpt->state & State_Enabled, text, QPalette::WindowText);
}
p->restore();
@@ -4565,6 +4507,7 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
const int controlSize = getControlSize(opt, widget);
switch (sr) {
+#if QT_CONFIG(itemviews)
case SE_ItemViewItemText:
if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
int fw = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, widget);
@@ -4574,6 +4517,7 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
rect.adjust(-fw, 0, 0, 0);
}
break;
+#endif
case SE_ToolBoxTabContents:
rect = QCommonStyle::subElementRect(sr, opt, widget);
break;
@@ -6123,8 +6067,9 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
switch (ct) {
#if QT_CONFIG(spinbox)
case CT_SpinBox:
- if (qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
- const int buttonWidth = 20; // FIXME Use subControlRect()
+ if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
+ const bool hasButtons = (vopt->buttonSymbols != QAbstractSpinBox::NoButtons);
+ const int buttonWidth = hasButtons ? proxy()->subControlRect(CC_SpinBox, vopt, SC_SpinBoxUp, widget).width() : 0;
sz += QSize(buttonWidth, 0);
}
break;
@@ -6400,12 +6345,14 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
sz = sz.expandedTo(QSize(sz.width(), minimumSize));
}
break;
+#if QT_CONFIG(itemviews)
case CT_ItemViewItem:
if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
sz = QCommonStyle::sizeFromContents(ct, vopt, csz, widget);
sz.setHeight(sz.height() + 2);
}
break;
+#endif
default:
sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget);
diff --git a/src/plugins/styles/mac/qmacstyle_mac_p.h b/src/plugins/styles/mac/qmacstyle_mac_p.h
index d6874001d3..88f104cccf 100644
--- a/src/plugins/styles/mac/qmacstyle_mac_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p.h
@@ -115,7 +115,7 @@ public:
const QWidget *widget = 0) const;
private:
- Q_DISABLE_COPY(QMacStyle)
+ Q_DISABLE_COPY_MOVE(QMacStyle)
Q_DECLARE_PRIVATE(QMacStyle)
};
diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
index 6b3f525adc..d6af18f01f 100644
--- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
@@ -41,98 +41,105 @@
#ifndef QMACSTYLE_MAC_P_P_H
#define QMACSTYLE_MAC_P_P_H
-#include <QtWidgets/private/qtwidgetsglobal_p.h>
-#include <QtWidgets/private/qcommonstyle_p.h>
#include "qmacstyle_mac_p.h"
-#include <private/qapplication_p.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qmath.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qtextstream.h>
+#include <QtCore/qvector.h>
+
+#include <QtGui/private/qpainter_p.h>
+
+#include <QtGui/qbitmap.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpixmapcache.h>
+
+#include <QtWidgets/private/qapplication_p.h>
+#include <QtWidgets/private/qcommonstyle_p.h>
+#include <QtWidgets/private/qstylehelper_p.h>
+
+#include <QtWidgets/qapplication.h>
+#include <QtWidgets/qfocusframe.h>
+#include <QtWidgets/qformlayout.h>
+#include <QtWidgets/qlayout.h>
+#include <QtWidgets/qstyleoption.h>
+#include <QtWidgets/qtextedit.h>
+
+#if QT_CONFIG(checkbox)
+#include <QtWidgets/qcheckbox.h>
+#endif
#if QT_CONFIG(combobox)
-#include <private/qcombobox_p.h>
+#include <QtWidgets/private/qcombobox_p.h>
+#include <QtWidgets/qcombobox.h>
#endif
-#include <private/qpainter_p.h>
-#include <private/qstylehelper_p.h>
-#include <qapplication.h>
-#include <qbitmap.h>
-#if QT_CONFIG(checkbox)
-#include <qcheckbox.h>
+#if QT_CONFIG(datetimeedit)
+#include <QtWidgets/qdatetimeedit.h>
#endif
-#include <qcombobox.h>
#if QT_CONFIG(dialogbuttonbox)
-#include <qdialogbuttonbox.h>
+#include <QtWidgets/qdialogbuttonbox.h>
#endif
#if QT_CONFIG(dockwidget)
-#include <qdockwidget.h>
+#include <QtWidgets/qdockwidget.h>
+#endif
+#if QT_CONFIG(graphicsview)
+#include <QtWidgets/qgraphicsproxywidget.h>
+#include <QtWidgets/qgraphicsview.h>
#endif
-#include <qevent.h>
-#include <qfocusframe.h>
-#include <qformlayout.h>
#if QT_CONFIG(groupbox)
-#include <qgroupbox.h>
+#include <QtWidgets/qgroupbox.h>
+#endif
+#if QT_CONFIG(itemviews)
+#include <QtWidgets/qheaderview.h>
#endif
-#include <qhash.h>
-#include <qheaderview.h>
-#include <qlayout.h>
#if QT_CONFIG(lineedit)
-#include <qlineedit.h>
+#include <QtWidgets/qlineedit.h>
#endif
#if QT_CONFIG(listview)
-#include <qlistview.h>
+#include <QtWidgets/qlistview.h>
#endif
#if QT_CONFIG(mainwindow)
-#include <qmainwindow.h>
+#include <QtWidgets/qmainwindow.h>
#endif
-#include <qmap.h>
#if QT_CONFIG(menubar)
-#include <qmenubar.h>
+#include <QtWidgets/qmenubar.h>
#endif
-#include <qpaintdevice.h>
-#include <qpainter.h>
-#include <qpixmapcache.h>
-#include <qpointer.h>
#if QT_CONFIG(progressbar)
-#include <qprogressbar.h>
+#include <QtWidgets/qprogressbar.h>
#endif
#if QT_CONFIG(pushbutton)
-#include <qpushbutton.h>
+#include <QtWidgets/qpushbutton.h>
#endif
-#include <qradiobutton.h>
+#include <QtWidgets/qradiobutton.h>
#if QT_CONFIG(rubberband)
-#include <qrubberband.h>
+#include <QtWidgets/qrubberband.h>
#endif
#if QT_CONFIG(sizegrip)
-#include <qsizegrip.h>
+#include <QtWidgets/qsizegrip.h>
#endif
#if QT_CONFIG(spinbox)
-#include <qspinbox.h>
+#include <QtWidgets/qspinbox.h>
#endif
#if QT_CONFIG(splitter)
-#include <qsplitter.h>
+#include <QtWidgets/qsplitter.h>
+#endif
+#if QT_CONFIG(tableview)
+#include <QtWidgets/qtableview.h>
#endif
-#include <qstyleoption.h>
-#include <qtextedit.h>
-#include <qtextstream.h>
#if QT_CONFIG(toolbar)
-#include <qtoolbar.h>
+#include <QtWidgets/qtoolbar.h>
#endif
#if QT_CONFIG(toolbutton)
-#include <qtoolbutton.h>
+#include <QtWidgets/qtoolbutton.h>
#endif
#if QT_CONFIG(treeview)
-#include <qtreeview.h>
-#endif
-#if QT_CONFIG(tableview)
-#include <qtableview.h>
+#include <QtWidgets/qtreeview.h>
#endif
-#include <qdebug.h>
-#if QT_CONFIG(datetimeedit)
-#include <qdatetimeedit.h>
-#endif
-#include <qmath.h>
-#include <qpair.h>
-#include <qvector.h>
-#include <QtWidgets/qgraphicsproxywidget.h>
-#include <QtWidgets/qgraphicsview.h>
-
-
//
// W A R N I N G
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
index 771552a121..8a3ae17b1d 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
@@ -632,7 +632,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
{
QPen pen = painter->pen();
int margin = 3;
- painter->setPen(option->palette.background().color().darker(114));
+ painter->setPen(option->palette.window().color().darker(114));
if (option->state & State_Horizontal) {
int x1 = option->rect.center().x();
painter->drawLine(QPoint(x1, option->rect.top() + margin), QPoint(x1, option->rect.bottom() - margin));
@@ -704,7 +704,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
if (sectionSize.width() > 0 && sectionSize.height() > 0) {
QString key = QString::fromLatin1("qvdelegate-%1-%2-%3-%4-%5").arg(sectionSize.width())
.arg(sectionSize.height()).arg(selected).arg(active).arg(hover);
- if (!QPixmapCache::find(key, pixmap)) {
+ if (!QPixmapCache::find(key, &pixmap)) {
pixmap = QPixmap(sectionSize);
pixmap.fill(Qt::transparent);
@@ -1053,7 +1053,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
QString name = QString::fromLatin1("qiprogress-%1-%2").arg(pixmapSize.width()).arg(pixmapSize.height());
QPixmap pixmap;
- if (!QPixmapCache::find(name, pixmap)) {
+ if (!QPixmapCache::find(name, &pixmap)) {
QImage image(pixmapSize, QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter imagePainter(&image);
@@ -1363,7 +1363,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
case CE_ToolBar:
if (const QStyleOptionToolBar *toolbar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
QPalette pal = option->palette;
- pal.setColor(QPalette::Dark, option->palette.background().color().darker(130));
+ pal.setColor(QPalette::Dark, option->palette.window().color().darker(130));
QStyleOptionToolBar copyOpt = *toolbar;
copyOpt.palette = pal;
QWindowsStyle::drawControl(element, &copyOpt, painter, widget);
@@ -1388,8 +1388,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
painter->translate(-rect.left() + 1, -rect.top());
}
- painter->setBrush(option->palette.background().color().darker(110));
- painter->setPen(option->palette.background().color().darker(130));
+ painter->setBrush(option->palette.window().color().darker(110));
+ painter->setPen(option->palette.window().color().darker(130));
painter->drawRect(rect.adjusted(0, 1, -1, -3));
int buttonMargin = 4;
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h b/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h
index 0ebb0eb41a..43a2a670f8 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h
@@ -99,7 +99,7 @@ public:
QPalette standardPalette() const override;
private:
- Q_DISABLE_COPY(QWindowsVistaStyle)
+ Q_DISABLE_COPY_MOVE(QWindowsVistaStyle)
Q_DECLARE_PRIVATE(QWindowsVistaStyle)
friend class QStyleFactory;
};
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
index 4b583e13d3..a331b2ee87 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
@@ -511,8 +511,8 @@ QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData)
if (numBytes == 0)
return QRegion();
- char *buf = new char[numBytes];
- if (buf == 0)
+ char *buf = new (std::nothrow) char[numBytes];
+ if (!buf)
return QRegion();
RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf);
@@ -740,7 +740,8 @@ bool QWindowsXPStylePrivate::drawBackgroundDirectly(HDC dc, XPThemeData &themeDa
{
QPainter *painter = themeData.painter;
- const QPointF redirectionDelta(painter->deviceMatrix().dx(), painter->deviceMatrix().dy());
+ const auto deviceTransform = painter->deviceTransform();
+ const QPointF redirectionDelta(deviceTransform.dx(), deviceTransform.dy());
const QRect area = scaleRect(QRectF(themeData.rect), additionalDevicePixelRatio).translated(redirectionDelta).toRect();
QRegion sysRgn = painter->paintEngine()->systemClip();
@@ -835,7 +836,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
alphaType = data.alphaType;
potentialInvalidAlpha = data.hadInvalidAlpha;
- haveCachedPixmap = QPixmapCache::find(pixmapCacheKey, cachedPixmap);
+ haveCachedPixmap = QPixmapCache::find(pixmapCacheKey, &cachedPixmap);
#ifdef DEBUG_XP_STYLE
char buf[25];
@@ -1485,11 +1486,13 @@ case PE_Frame:
// Inner white border
p->setPen(QPen(option->palette.base().color(), 0));
- p->drawRect(QRectF(option->rect).adjusted(QStyleHelper::dpiScaled(0.5), QStyleHelper::dpiScaled(0.5),
- QStyleHelper::dpiScaled(-1), QStyleHelper::dpiScaled(-1)));
+ const auto topLevelAdjustment = QStyleHelper::dpiScaled(0.5);
+ const auto bottomRightAdjustment = QStyleHelper::dpiScaled(-1);
+ p->drawRect(QRectF(option->rect).adjusted(topLevelAdjustment, topLevelAdjustment,
+ bottomRightAdjustment, bottomRightAdjustment));
// Outer dark border
p->setPen(QPen(bordercolor, 0));
- p->drawRect(QRectF(option->rect).adjusted(0, 0, QStyleHelper::dpiScaled(-0.5), QStyleHelper::dpiScaled(-0.5)));
+ p->drawRect(QRectF(option->rect).adjusted(0, 0, -topLevelAdjustment, -topLevelAdjustment));
p->setPen(oldPen);
return;
} else if (fillType == BT_NONE) {
@@ -3533,9 +3536,12 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
qRound(QStyleHelper::dpiScaled(16)), he - qRound(QStyleHelper::dpiScaled(2)));
break;
- case SC_ComboBoxEditField:
- rect = QRect(x + qRound(QStyleHelper::dpiScaled(2)), y + qRound(QStyleHelper::dpiScaled(2)),
- wi - qRound(QStyleHelper::dpiScaled(3 + 16)), he - qRound(QStyleHelper::dpiScaled(4)));
+ case SC_ComboBoxEditField: {
+ const int frame = qRound(QStyleHelper::dpiScaled(2));
+ rect = QRect(x + frame, y + frame,
+ wi - qRound(QStyleHelper::dpiScaled(3 + 16)),
+ he - qRound(QStyleHelper::dpiScaled(4)));
+ }
break;
case SC_ComboBoxListBoxPopup:
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle_p.h b/src/plugins/styles/windowsvista/qwindowsxpstyle_p.h
index 7e9f4ddda6..0f70105b0e 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle_p.h
@@ -96,7 +96,7 @@ public:
const QWidget *widget = nullptr) const override;
private:
- Q_DISABLE_COPY(QWindowsXPStyle)
+ Q_DISABLE_COPY_MOVE(QWindowsXPStyle)
Q_DECLARE_PRIVATE(QWindowsXPStyle)
friend class QStyleFactory;
};
diff --git a/src/plugins/styles/windowsvista/windowsvista.pro b/src/plugins/styles/windowsvista/windowsvista.pro
index f82bcfc91b..c08db7f533 100644
--- a/src/plugins/styles/windowsvista/windowsvista.pro
+++ b/src/plugins/styles/windowsvista/windowsvista.pro
@@ -10,7 +10,7 @@ SOURCES += qwindowsvistastyle.cpp
HEADERS += qwindowsxpstyle_p.h qwindowsxpstyle_p_p.h
SOURCES += qwindowsxpstyle.cpp
-LIBS_PRIVATE += -lgdi32 -luser32
+QMAKE_USE_PRIVATE += user32 gdi32
# DEFINES/LIBS needed for qwizard_win.cpp and the styles
include(../../../widgets/kernel/win.pri)
diff --git a/src/printsupport/dialogs/qabstractprintdialog.h b/src/printsupport/dialogs/qabstractprintdialog.h
index 3cc89890fc..372716adfc 100644
--- a/src/printsupport/dialogs/qabstractprintdialog.h
+++ b/src/printsupport/dialogs/qabstractprintdialog.h
@@ -73,7 +73,9 @@ public:
PrintPageRange = 0x0004,
PrintShowPageSize = 0x0008,
PrintCollateCopies = 0x0010,
- DontUseSheet = 0x0020,
+#if QT_DEPRECATED_SINCE(5, 14)
+ DontUseSheet Q_DECL_ENUMERATOR_DEPRECATED = 0x0020,
+#endif
PrintCurrentPage = 0x0040
};
Q_ENUM(PrintDialogOption)
@@ -84,8 +86,6 @@ public:
explicit QAbstractPrintDialog(QPrinter *printer, QWidget *parent = nullptr);
~QAbstractPrintDialog();
- int exec() override = 0;
-
// obsolete
void addEnabledOption(PrintDialogOption option);
void setEnabledOptions(PrintDialogOptions options);
diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp
index d9b4a84aa9..1d8af9dbf0 100644
--- a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp
+++ b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp
@@ -361,13 +361,21 @@ void QPageSetupWidget::initPageSizes()
QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
if (ps) {
QPrintDevice printDevice = ps->createPrintDevice(m_printerName);
+ const QPageSize defaultSize = printDevice.defaultPageSize();
const auto pageSizes = printDevice.supportedPageSizes();
for (const QPageSize &pageSize : pageSizes)
m_ui.pageSizeCombo->addItem(pageSize.name(), QVariant::fromValue(pageSize));
- if (m_ui.pageSizeCombo->count() > 0 && printDevice.supportsCustomPageSizes()) {
- m_ui.pageSizeCombo->addItem(tr("Custom"));
- m_realCustomPageSizeIndex = m_ui.pageSizeCombo->count() - 1;
+ if (m_ui.pageSizeCombo->count() > 0) {
+ if (printDevice.supportsCustomPageSizes()) {
+ m_ui.pageSizeCombo->addItem(tr("Custom"));
+ m_realCustomPageSizeIndex = m_ui.pageSizeCombo->count() - 1;
+ }
m_blockSignals = false;
+
+ // If the defaultSize is index 0, setCurrentIndex won't emit the currentIndexChanged
+ // signal; workaround the issue by initially setting the currentIndex to -1
+ m_ui.pageSizeCombo->setCurrentIndex(-1);
+ m_ui.pageSizeCombo->setCurrentIndex(m_ui.pageSizeCombo->findData(QVariant::fromValue(defaultSize)));
return;
}
}
@@ -403,12 +411,6 @@ void QPageSetupWidget::setPrinter(QPrinter *printer, QPrintDevice *printDevice,
// Initialize the layout to the current QPrinter layout
m_pageLayout = m_printer->pageLayout();
- if (printDevice) {
- const QPageSize pageSize = printDevice->defaultPageSize();
- const QMarginsF printable = printDevice->printableMargins(pageSize, m_pageLayout.orientation(), m_printer->resolution());
- m_pageLayout.setPageSize(pageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units()));
- }
-
// Assume if margins are Points then is by default, so set to locale default units
if (m_pageLayout.units() == QPageLayout::Point) {
if (QLocale().measurementSystem() == QLocale::MetricSystem)
@@ -735,8 +737,12 @@ int QPageSetupDialog::exec()
Q_D(QPageSetupDialog);
int ret = QDialog::exec();
- if (ret == Accepted)
+ if (ret == Accepted) {
static_cast <QUnixPageSetupDialogPrivate*>(d)->widget->setupPrinter();
+ static_cast <QUnixPageSetupDialogPrivate*>(d)->widget->updateSavedValues();
+ } else {
+ static_cast <QUnixPageSetupDialogPrivate*>(d)->widget->revertToSavedValues();
+ }
return ret;
}
diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp
index 5390a8b2f2..5136ba13e5 100644
--- a/src/printsupport/dialogs/qprintdialog_unix.cpp
+++ b/src/printsupport/dialogs/qprintdialog_unix.cpp
@@ -398,12 +398,12 @@ static const char *ppdOriginallySelectedChoiceProperty = "_q_ppd_originally_sele
// Used to store the warning label pointer for each QComboBox that represents an advanced option
static const char *warningLabelProperty = "_q_warning_label";
-static bool isBlacklistedGroup(const ppd_group_t *group) Q_DECL_NOTHROW
+static bool isBlacklistedGroup(const ppd_group_t *group) noexcept
{
return qstrcmp(group->name, "InstallableOptions") == 0;
};
-static bool isBlacklistedOption(const char *keyword) Q_DECL_NOTHROW
+static bool isBlacklistedOption(const char *keyword) noexcept
{
// We already let the user set these options elsewhere
const char *cupsOptionBlacklist[] = {
@@ -734,11 +734,11 @@ void QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputForma
}
#if QT_CONFIG(cups)
-static std::vector<std::pair<int, int>> pageRangesFromString(const QString &pagesString) Q_DECL_NOTHROW
+static std::vector<std::pair<int, int>> pageRangesFromString(const QString &pagesString) noexcept
{
std::vector<std::pair<int, int>> result;
const QStringList items = pagesString.split(',');
- for (const QString item : items) {
+ for (const QString &item : items) {
if (item.isEmpty())
return {};
@@ -788,7 +788,7 @@ static std::vector<std::pair<int, int>> pageRangesFromString(const QString &page
return result;
}
-static QString stringFromPageRanges(const std::vector<std::pair<int, int>> &pageRanges) Q_DECL_NOTHROW
+static QString stringFromPageRanges(const std::vector<std::pair<int, int>> &pageRanges) noexcept
{
QString result;
@@ -805,7 +805,7 @@ static QString stringFromPageRanges(const std::vector<std::pair<int, int>> &page
return result;
}
-static bool isValidPagesString(const QString &pagesString) Q_DECL_NOTHROW
+static bool isValidPagesString(const QString &pagesString) noexcept
{
if (pagesString.isEmpty())
return false;
@@ -1082,7 +1082,7 @@ void QPrintDialog::setVisible(bool visible)
int QPrintDialog::exec()
{
- return QDialog::exec();
+ return QAbstractPrintDialog::exec();
}
void QPrintDialog::accept()
diff --git a/src/printsupport/dialogs/qprintpreviewdialog.cpp b/src/printsupport/dialogs/qprintpreviewdialog.cpp
index 418bc47a59..39575d5f57 100644
--- a/src/printsupport/dialogs/qprintpreviewdialog.cpp
+++ b/src/printsupport/dialogs/qprintpreviewdialog.cpp
@@ -152,8 +152,8 @@ class QPrintPreviewDialogPrivate : public QDialogPrivate
Q_DECLARE_PUBLIC(QPrintPreviewDialog)
public:
QPrintPreviewDialogPrivate()
- : printDialog(nullptr), ownPrinter(false),
- initialized(false) {}
+ : printDialog(nullptr), pageSetupDialog(nullptr),
+ ownPrinter(false), initialized(false) {}
// private slots
void _q_fit(QAction *action);
@@ -178,6 +178,7 @@ public:
void updateZoomFactor();
QPrintDialog *printDialog;
+ QPageSetupDialog *pageSetupDialog;
QPrintPreviewWidget *preview;
QPrinter *printer;
bool ownPrinter;
@@ -331,7 +332,7 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
QVBoxLayout *topLayout = new QVBoxLayout;
topLayout->addWidget(mw);
- topLayout->setMargin(0);
+ topLayout->setContentsMargins(0, 0, 0, 0);
q->setLayout(topLayout);
QString caption = QCoreApplication::translate("QPrintPreviewDialog", "Print Preview");
@@ -494,7 +495,7 @@ void QPrintPreviewDialogPrivate::updatePageNumLabel()
void QPrintPreviewDialogPrivate::updateZoomFactor()
{
- zoomFactor->lineEdit()->setText(QString().sprintf("%.1f%%", preview->zoomFactor()*100));
+ zoomFactor->lineEdit()->setText(QString::asprintf("%.1f%%", preview->zoomFactor()*100));
}
void QPrintPreviewDialogPrivate::_q_fit(QAction* action)
@@ -602,8 +603,10 @@ void QPrintPreviewDialogPrivate::_q_pageSetup()
{
Q_Q(QPrintPreviewDialog);
- QPageSetupDialog pageSetup(printer, q);
- if (pageSetup.exec() == QDialog::Accepted) {
+ if (!pageSetupDialog)
+ pageSetupDialog = new QPageSetupDialog(printer, q);
+
+ if (pageSetupDialog->exec() == QDialog::Accepted) {
// update possible orientation changes
if (preview->orientation() == QPrinter::Portrait) {
portraitAction->setChecked(true);
@@ -713,6 +716,7 @@ QPrintPreviewDialog::~QPrintPreviewDialog()
if (d->ownPrinter)
delete d->printer;
delete d->printDialog;
+ delete d->pageSetupDialog;
}
/*!
diff --git a/src/printsupport/doc/src/dontdocument.qdoc b/src/printsupport/doc/src/dontdocument.qdoc
new file mode 100644
index 0000000000..74552b4e99
--- /dev/null
+++ b/src/printsupport/doc/src/dontdocument.qdoc
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+/*!
+ \dontdocument (QMetaTypeId QPlatformPrintDevice QPlatformPrinterSupportPlugin)
+*/
diff --git a/src/printsupport/kernel/kernel.pri b/src/printsupport/kernel/kernel.pri
index ea7b4b9780..2ceaf152eb 100644
--- a/src/printsupport/kernel/kernel.pri
+++ b/src/printsupport/kernel/kernel.pri
@@ -33,7 +33,10 @@ win32 {
$$PWD/qprintengine_win_p.h
SOURCES += \
$$PWD/qprintengine_win.cpp
- !winrt: LIBS_PRIVATE += -lwinspool -lcomdlg32 -lgdi32 -luser32
+ !winrt {
+ LIBS_PRIVATE += -lwinspool -lcomdlg32
+ QMAKE_USE_PRIVATE += user32 gdi32
+ }
}
unix:!darwin:qtConfig(cups) {
diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp
index 8505e8356c..5236b8c8fa 100644
--- a/src/printsupport/kernel/qcups.cpp
+++ b/src/printsupport/kernel/qcups.cpp
@@ -44,12 +44,12 @@
QT_BEGIN_NAMESPACE
-static QStringList cupsOptionsList(QPrinter *printer) Q_DECL_NOTHROW
+static QStringList cupsOptionsList(QPrinter *printer) noexcept
{
return printer->printEngine()->property(PPK_CupsOptions).toStringList();
}
-void setCupsOptions(QPrinter *printer, const QStringList &cupsOptions) Q_DECL_NOTHROW
+void setCupsOptions(QPrinter *printer, const QStringList &cupsOptions) noexcept
{
printer->printEngine()->setProperty(PPK_CupsOptions, QVariant(cupsOptions));
}
diff --git a/src/printsupport/kernel/qplatformprintdevice.cpp b/src/printsupport/kernel/qplatformprintdevice.cpp
index 69d984cb0c..3d76cad688 100644
--- a/src/printsupport/kernel/qplatformprintdevice.cpp
+++ b/src/printsupport/kernel/qplatformprintdevice.cpp
@@ -40,10 +40,8 @@
#include "qplatformprintdevice.h"
#include "qprintdevice_p.h"
-#if QT_CONFIG(printdialog)
-#include "qprintdialog.h"
-#endif
+#include <QtCore/qcoreapplication.h>
#include <QtGui/qpagelayout.h>
QT_BEGIN_NAMESPACE
@@ -165,7 +163,7 @@ QPageSize QPlatformPrintDevice::supportedPageSize(const QPageSize &pageSize) con
// e.g. Windows defines DMPAPER_11X17 and DMPAPER_TABLOID with names "11x17" and "Tabloid", but both
// map to QPageSize::Tabloid / PPD Key "Tabloid" / ANSI B Tabloid
if (pageSize.id() != QPageSize::Custom) {
- for (const QPageSize &ps : m_pageSizes) {
+ for (const QPageSize &ps : qAsConst(m_pageSizes)) {
if (ps.id() == pageSize.id() && ps.name() == pageSize.name())
return ps;
}
@@ -173,7 +171,7 @@ QPageSize QPlatformPrintDevice::supportedPageSize(const QPageSize &pageSize) con
// Next try match on id only if not custom
if (pageSize.id() != QPageSize::Custom) {
- for (const QPageSize &ps : m_pageSizes) {
+ for (const QPageSize &ps : qAsConst(m_pageSizes)) {
if (ps.id() == pageSize.id())
return ps;
}
@@ -188,7 +186,7 @@ QPageSize QPlatformPrintDevice::supportedPageSize(QPageSize::PageSizeId pageSize
if (!m_havePageSizes)
loadPageSizes();
- for (const QPageSize &ps : m_pageSizes) {
+ for (const QPageSize &ps : qAsConst(m_pageSizes)) {
if (ps.id() == pageSizeId)
return ps;
}
@@ -202,7 +200,7 @@ QPageSize QPlatformPrintDevice::supportedPageSize(const QString &pageName) const
if (!m_havePageSizes)
loadPageSizes();
- for (const QPageSize &ps : m_pageSizes) {
+ for (const QPageSize &ps : qAsConst(m_pageSizes)) {
if (ps.name() == pageName)
return ps;
}
@@ -235,7 +233,7 @@ QPageSize QPlatformPrintDevice::supportedPageSizeMatch(const QPageSize &pageSize
return pageSize;
// Try to find a supported page size based on point size
- for (const QPageSize &ps : m_pageSizes) {
+ for (const QPageSize &ps : qAsConst(m_pageSizes)) {
if (ps.sizePoints() == pageSize.sizePoints())
return ps;
}
@@ -291,11 +289,7 @@ QPrint::InputSlot QPlatformPrintDevice::defaultInputSlot() const
{
QPrint::InputSlot input;
input.key = QByteArrayLiteral("Auto");
-#if QT_CONFIG(printdialog)
- input.name = QPrintDialog::tr("Automatic");
-#else
- input.name = QString::fromLatin1("Automatic");
-#endif
+ input.name = QCoreApplication::translate("Print Device Input Slot", "Automatic");
input.id = QPrint::Auto;
return input;
}
@@ -315,11 +309,7 @@ QPrint::OutputBin QPlatformPrintDevice::defaultOutputBin() const
{
QPrint::OutputBin output;
output.key = QByteArrayLiteral("Auto");
-#if QT_CONFIG(printdialog)
- output.name = QPrintDialog::tr("Automatic");
-#else
- output.name = QString::fromLatin1("Automatic");
-#endif
+ output.name = QCoreApplication::translate("Print Device Output Bin", "Automatic");
output.id = QPrint::AutoOutputBin;
return output;
}
diff --git a/src/printsupport/kernel/qprintdevice_p.h b/src/printsupport/kernel/qprintdevice_p.h
index a2b18f08cf..9e76c37617 100644
--- a/src/printsupport/kernel/qprintdevice_p.h
+++ b/src/printsupport/kernel/qprintdevice_p.h
@@ -76,9 +76,7 @@ public:
~QPrintDevice();
QPrintDevice &operator=(const QPrintDevice &other);
- #ifdef Q_COMPILER_RVALUE_REFS
QPrintDevice &operator=(QPrintDevice &&other) { swap(other); return *this; }
-#endif
void swap(QPrintDevice &other) { d.swap(other.d); }
diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp
index 829a13863b..ddcd8c4702 100644
--- a/src/printsupport/kernel/qprinter.cpp
+++ b/src/printsupport/kernel/qprinter.cpp
@@ -1848,7 +1848,7 @@ QList<int> QPrinter::supportedResolutions() const
= d->printEngine->property(QPrintEngine::PPK_SupportedResolutions).toList();
QList<int> intlist;
intlist.reserve(varlist.size());
- for (auto var : varlist)
+ for (const auto &var : varlist)
intlist << var.toInt();
return intlist;
}
diff --git a/src/printsupport/kernel/qprinterinfo.cpp b/src/printsupport/kernel/qprinterinfo.cpp
index 4b092dee64..167b2361ef 100644
--- a/src/printsupport/kernel/qprinterinfo.cpp
+++ b/src/printsupport/kernel/qprinterinfo.cpp
@@ -400,6 +400,35 @@ QList<QPrinter::DuplexMode> QPrinterInfo::supportedDuplexModes() const
}
/*!
+ Returns the default color mode of this printer.
+
+ \since 5.13
+*/
+
+QPrinter::ColorMode QPrinterInfo::defaultColorMode() const
+{
+ Q_D(const QPrinterInfo);
+ return QPrinter::ColorMode(d->m_printDevice.defaultColorMode());
+}
+
+/*!
+ Returns the supported color modes of this printer.
+
+ \since 5.13
+*/
+
+QList<QPrinter::ColorMode> QPrinterInfo::supportedColorModes() const
+{
+ Q_D(const QPrinterInfo);
+ QList<QPrinter::ColorMode> list;
+ const auto supportedColorModes = d->m_printDevice.supportedColorModes();
+ list.reserve(supportedColorModes.size());
+ for (QPrint::ColorMode mode : supportedColorModes)
+ list << QPrinter::ColorMode(mode);
+ return list;
+}
+
+/*!
Returns a list of all the available Printer Names on this system.
It is recommended to use this instead of availablePrinters() as
diff --git a/src/printsupport/kernel/qprinterinfo.h b/src/printsupport/kernel/qprinterinfo.h
index 8bac395ab3..7195cb76b5 100644
--- a/src/printsupport/kernel/qprinterinfo.h
+++ b/src/printsupport/kernel/qprinterinfo.h
@@ -93,6 +93,9 @@ public:
QPrinter::DuplexMode defaultDuplexMode() const;
QList<QPrinter::DuplexMode> supportedDuplexModes() const;
+ QPrinter::ColorMode defaultColorMode() const;
+ QList<QPrinter::ColorMode> supportedColorModes() const;
+
static QStringList availablePrinterNames();
static QList<QPrinterInfo> availablePrinters();
diff --git a/src/printsupport/widgets/qcupsjobwidget_p.h b/src/printsupport/widgets/qcupsjobwidget_p.h
index 4b6b047e26..42da9c7580 100644
--- a/src/printsupport/widgets/qcupsjobwidget_p.h
+++ b/src/printsupport/widgets/qcupsjobwidget_p.h
@@ -113,7 +113,7 @@ private:
int m_savedPriority;
QCUPSSupport::JobSheets m_savedJobSheets;
- Q_DISABLE_COPY(QCupsJobWidget)
+ Q_DISABLE_COPY_MOVE(QCupsJobWidget)
};
QT_END_NAMESPACE
diff --git a/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc b/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc
index d127bdf8a5..9709deeccb 100644
--- a/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc
+++ b/src/sql/doc/snippets/code/doc_src_sql-driver.qdoc
@@ -237,3 +237,16 @@ Could not create database object
//! [38]
QPSQLDriver::getResult: Query results lost - probably discarded on executing another SQL query.
//! [38]
+
+//! [39]
+CREATE TABLE "testTable" ("id" INTEGER);
+//! [39]
+
+//! [40]
+QString tableString("testTable");
+QSqlQuery q;
+// Create table query is not quoted, therefore it is mapped to lower case
+q.exec(QString("CREATE TABLE %1 (id INTEGER)").arg(tableString));
+// Call toLower() on the string so that it can be matched
+QSqlRecord rec = database.record(tableString.toLower());
+//! [40]
diff --git a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp
index a27feb1505..bba0487452 100644
--- a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp
+++ b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp
@@ -213,7 +213,7 @@ void QSqlQuery_snippets()
while (i.hasNext()) {
i.next();
cout << i.key().toUtf8().data() << ": "
- << i.value().toString().toUtf8().data() << endl;
+ << i.value().toString().toUtf8().data() << Qt::endl;
}
//! [14]
}
@@ -223,7 +223,7 @@ void QSqlQuery_snippets()
//! [15]
QList<QVariant> list = query.boundValues().values();
for (int i = 0; i < list.size(); ++i)
- cout << i << ": " << list.at(i).toString().toUtf8().data() << endl;
+ cout << i << ": " << list.at(i).toString().toUtf8().data() << Qt::endl;
//! [15]
}
}
diff --git a/src/sql/doc/src/dontdocument.qdoc b/src/sql/doc/src/dontdocument.qdoc
new file mode 100644
index 0000000000..0193ace4b4
--- /dev/null
+++ b/src/sql/doc/src/dontdocument.qdoc
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+/*!
+ \dontdocument (QTypeInfo)
+*/
diff --git a/src/sql/doc/src/sql-driver.qdoc b/src/sql/doc/src/sql-driver.qdoc
index fd95e89812..c6ac4d17ff 100644
--- a/src/sql/doc/src/sql-driver.qdoc
+++ b/src/sql/doc/src/sql-driver.qdoc
@@ -54,9 +54,9 @@
\li Open Database Connectivity (ODBC) - Microsoft SQL Server and other
ODBC-compliant databases
\row \li \l{#QPSQL}{QPSQL} \li PostgreSQL (versions 7.3 and above)
- \row \li \l{#QSQLITE2}{QSQLITE2} \li SQLite version 2
+ \row \li \l{#QSQLITE2}{QSQLITE2} \li SQLite version 2 \note obsolete since Qt 5.14
\row \li \l{#QSQLITE}{QSQLITE} \li SQLite version 3
- \row \li \l{#QTDS}{QTDS} \li Sybase Adaptive Server \note obsolete from Qt 4.7
+ \row \li \l{#QTDS}{QTDS} \li Sybase Adaptive Server \note obsolete since Qt 4.7
\endtable
SQLite is the in-process database system with the best test coverage
@@ -381,6 +381,23 @@
multibyte enabled PostgreSQL server can be found in the PostgreSQL
Administrator Guide, Chapter 5.
+ \section3 QPSQL Case Sensitivity
+
+ PostgreSQL databases will only respect case sensitivity if the table or field
+ name is quoted when the table is created. So for example, a SQL query such
+ as:
+
+ \snippet code/doc_src_sql-driver.qdoc 39
+
+ will ensure that it can be accessed with the same case that was used. If the
+ table or field name is not quoted when created, the actual table name
+ or field name will be lower-case. When QSqlDatabase::record() or
+ QSqlDatabase::primaryIndex() access a table or field that was unquoted
+ when created, the name passed to the function must be lower-case to
+ ensure it is found. For example:
+
+ \snippet code/doc_src_sql-driver.qdoc 40
+
\section3 QPSQL BLOB Support
Binary Large Objects are supported through the \c BYTEA field type in
diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp
index 2c7b4b83db..99aa3e96c4 100644
--- a/src/sql/kernel/qsqldatabase.cpp
+++ b/src/sql/kernel/qsqldatabase.cpp
@@ -184,7 +184,7 @@ QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null()
void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn)
{
- if (db.d->ref.load() != 1 && doWarn) {
+ if (db.d->ref.loadRelaxed() != 1 && doWarn) {
qWarning("QSqlDatabasePrivate::removeDatabase: connection '%s' is still in use, "
"all queries will cease to work.", name.toLocal8Bit().constData());
db.d->disable();
@@ -1088,6 +1088,11 @@ QStringList QSqlDatabase::tables(QSql::TableType type) const
Returns the primary index for table \a tablename. If no primary
index exists, an empty QSqlIndex is returned.
+ \note Some drivers, such as the \l {QPSQL Case Sensitivity}{QPSQL}
+ driver, may may require you to pass \a tablename in lower case if
+ the table was not quoted when created. See the
+ \l{sql-driver.html}{Qt SQL driver} documentation for more information.
+
\sa tables(), record()
*/
@@ -1102,6 +1107,11 @@ QSqlIndex QSqlDatabase::primaryIndex(const QString& tablename) const
the table (or view) called \a tablename. The order in which the
fields appear in the record is undefined. If no such table (or
view) exists, an empty record is returned.
+
+ \note Some drivers, such as the \l {QPSQL Case Sensitivity}{QPSQL}
+ driver, may may require you to pass \a tablename in lower case if
+ the table was not quoted when created. See the
+ \l{sql-driver.html}{Qt SQL driver} documentation for more information.
*/
QSqlRecord QSqlDatabase::record(const QString& tablename) const
@@ -1380,6 +1390,40 @@ QSqlDatabase QSqlDatabase::cloneDatabase(const QSqlDatabase &other, const QStrin
}
/*!
+ \since 5.13
+ \overload
+
+ Clones the database connection \a other and stores it as \a
+ connectionName. All the settings from the original database, e.g.
+ databaseName(), hostName(), etc., are copied across. Does nothing
+ if \a other is an invalid database. Returns the newly created
+ database connection.
+
+ \note The new connection has not been opened. Before using the new
+ connection, you must call open().
+
+ This overload is useful when cloning the database in another thread to the
+ one that is used by the database represented by \a other.
+*/
+
+QSqlDatabase QSqlDatabase::cloneDatabase(const QString &other, const QString &connectionName)
+{
+ const QConnectionDict *dict = dbDict();
+ Q_ASSERT(dict);
+
+ dict->lock.lockForRead();
+ QSqlDatabase otherDb = dict->value(other);
+ dict->lock.unlock();
+ if (!otherDb.isValid())
+ return QSqlDatabase();
+
+ QSqlDatabase db(otherDb.driverName());
+ db.d->copy(otherDb.d);
+ QSqlDatabasePrivate::addDatabase(db, connectionName);
+ return db;
+}
+
+/*!
\since 4.4
Returns the connection name, which may be empty. \note The
diff --git a/src/sql/kernel/qsqldatabase.h b/src/sql/kernel/qsqldatabase.h
index 3aadab9b2f..f233c72c19 100644
--- a/src/sql/kernel/qsqldatabase.h
+++ b/src/sql/kernel/qsqldatabase.h
@@ -118,6 +118,7 @@ public:
static QSqlDatabase addDatabase(QSqlDriver* driver,
const QString& connectionName = QLatin1String(defaultConnection));
static QSqlDatabase cloneDatabase(const QSqlDatabase &other, const QString& connectionName);
+ static QSqlDatabase cloneDatabase(const QString &other, const QString& connectionName);
static QSqlDatabase database(const QString& connectionName = QLatin1String(defaultConnection),
bool open = true);
static void removeDatabase(const QString& connectionName);
diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp
index 8c6ae382f6..7f7b81b05b 100644
--- a/src/sql/kernel/qsqldriver.cpp
+++ b/src/sql/kernel/qsqldriver.cpp
@@ -488,6 +488,8 @@ QString QSqlDriver::stripDelimiters(const QString &identifier, IdentifierType ty
QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
const QSqlRecord &rec, bool preparedStatement) const
{
+ const auto tableNameString = tableName.isEmpty() ? QString()
+ : prepareIdentifier(tableName, QSqlDriver::TableName, this);
int i;
QString s;
s.reserve(128);
@@ -500,13 +502,12 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
if (s.isEmpty())
return s;
s.chop(2);
- s.prepend(QLatin1String("SELECT ")).append(QLatin1String(" FROM ")).append(tableName);
+ s = QLatin1String("SELECT ") + s + QLatin1String(" FROM ") + tableNameString;
break;
case WhereStatement:
{
- const QString tableNamePrefix = tableName.isEmpty()
- ? QString()
- : prepareIdentifier(tableName, QSqlDriver::TableName, this) + QLatin1Char('.');
+ const QString tableNamePrefix = tableNameString.isEmpty()
+ ? QString() : tableNameString + QLatin1Char('.');
for (int i = 0; i < rec.count(); ++i) {
if (!rec.isGenerated(i))
continue;
@@ -523,8 +524,7 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
break;
}
case UpdateStatement:
- s.append(QLatin1String("UPDATE ")).append(tableName).append(
- QLatin1String(" SET "));
+ s = s + QLatin1String("UPDATE ") + tableNameString + QLatin1String(" SET ");
for (i = 0; i < rec.count(); ++i) {
if (!rec.isGenerated(i))
continue;
@@ -541,10 +541,10 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
s.clear();
break;
case DeleteStatement:
- s.append(QLatin1String("DELETE FROM ")).append(tableName);
+ s = s + QLatin1String("DELETE FROM ") + tableNameString;
break;
case InsertStatement: {
- s.append(QLatin1String("INSERT INTO ")).append(tableName).append(QLatin1String(" ("));
+ s = s + QLatin1String("INSERT INTO ") + tableNameString + QLatin1String(" (");
QString vals;
for (i = 0; i < rec.count(); ++i) {
if (!rec.isGenerated(i))
diff --git a/src/sql/kernel/qsqlerror.cpp b/src/sql/kernel/qsqlerror.cpp
index 41ea497ad7..7a1a91948c 100644
--- a/src/sql/kernel/qsqlerror.cpp
+++ b/src/sql/kernel/qsqlerror.cpp
@@ -365,7 +365,7 @@ QString QSqlError::nativeErrorCode() const
QString QSqlError::text() const
{
QString result = d->databaseError;
- if (!d->databaseError.endsWith(QLatin1String("\n")))
+ if (!d->databaseError.isEmpty() && !d->driverError.isEmpty() && !d->databaseError.endsWith(QLatin1String("\n")))
result += QLatin1Char(' ');
result += d->driverError;
return result;
diff --git a/src/sql/kernel/qsqlerror.h b/src/sql/kernel/qsqlerror.h
index 6dac47a7fe..7dfb6eb9ec 100644
--- a/src/sql/kernel/qsqlerror.h
+++ b/src/sql/kernel/qsqlerror.h
@@ -66,15 +66,15 @@ public:
ErrorType type = NoError,
const QString &errorCode = QString());
QSqlError(const QSqlError& other);
- QSqlError(QSqlError &&other) Q_DECL_NOTHROW : d(other.d) { other.d = nullptr; }
+ QSqlError(QSqlError &&other) noexcept : d(other.d) { other.d = nullptr; }
QSqlError& operator=(const QSqlError& other);
- QSqlError &operator=(QSqlError &&other) Q_DECL_NOTHROW { swap(other); return *this; }
+ QSqlError &operator=(QSqlError &&other) noexcept { swap(other); return *this; }
bool operator==(const QSqlError& other) const;
bool operator!=(const QSqlError& other) const;
~QSqlError();
- void swap(QSqlError &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+ void swap(QSqlError &other) noexcept { qSwap(d, other.d); }
QString driverText() const;
QString databaseText() const;
diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp
index daadcb8a0e..e7c444f5b9 100644
--- a/src/sql/kernel/qsqlquery.cpp
+++ b/src/sql/kernel/qsqlquery.cpp
@@ -374,7 +374,7 @@ bool QSqlQuery::exec(const QString& query)
QElapsedTimer t;
t.start();
#endif
- if (d->ref.load() != 1) {
+ if (d->ref.loadRelaxed() != 1) {
bool fo = isForwardOnly();
*this = QSqlQuery(driver()->createResult());
d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy());
@@ -960,7 +960,7 @@ void QSqlQuery::clear()
*/
bool QSqlQuery::prepare(const QString& query)
{
- if (d->ref.load() != 1) {
+ if (d->ref.loadRelaxed() != 1) {
bool fo = isForwardOnly();
*this = QSqlQuery(driver()->createResult());
setForwardOnly(fo);
diff --git a/src/sql/kernel/qsqlrecord.cpp b/src/sql/kernel/qsqlrecord.cpp
index ecbe3eacdb..c4dc5d1adb 100644
--- a/src/sql/kernel/qsqlrecord.cpp
+++ b/src/sql/kernel/qsqlrecord.cpp
@@ -535,7 +535,7 @@ QDebug operator<<(QDebug dbg, const QSqlRecord &r)
dbg << "QSqlRecord(" << count << ')';
for (int i = 0; i < count; ++i) {
dbg.nospace();
- dbg << '\n' << qSetFieldWidth(2) << right << i << left << qSetFieldWidth(0) << ':';
+ dbg << '\n' << qSetFieldWidth(2) << Qt::right << i << Qt::left << qSetFieldWidth(0) << ':';
dbg.space();
dbg << r.field(i) << r.value(i).toString();
}
diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp
index 589088238b..cc91c6d0ed 100644
--- a/src/sql/kernel/qsqlresult.cpp
+++ b/src/sql/kernel/qsqlresult.cpp
@@ -41,7 +41,6 @@
#include "qvariant.h"
#include "qhash.h"
-#include "qregexp.h"
#include "qsqlerror.h"
#include "qsqlfield.h"
#include "qsqlrecord.h"
diff --git a/src/sql/models/qsqlquerymodel_p.h b/src/sql/models/qsqlquerymodel_p.h
index d5ca2f89cb..64e9aeb3db 100644
--- a/src/sql/models/qsqlquerymodel_p.h
+++ b/src/sql/models/qsqlquerymodel_p.h
@@ -75,7 +75,7 @@ public:
void initColOffsets(int size);
int columnInQuery(int modelColumn) const;
- mutable QSqlQuery query = { QSqlQuery(0) };
+ mutable QSqlQuery query = { QSqlQuery(nullptr) };
mutable QSqlError error;
QModelIndex bottom;
QSqlRecord rec;
diff --git a/src/sql/models/qsqlrelationaldelegate.h b/src/sql/models/qsqlrelationaldelegate.h
index ca5c46778f..2f16a4a54b 100644
--- a/src/sql/models/qsqlrelationaldelegate.h
+++ b/src/sql/models/qsqlrelationaldelegate.h
@@ -58,7 +58,7 @@ QT_REQUIRE_CONFIG(sqlmodel);
#include <QtCore/qmetaobject.h>
QT_BEGIN_NAMESPACE
-
+// ### Qt6: QStyledItemDelegate
class QSqlRelationalDelegate: public QItemDelegate
{
static int fieldIndex(const QSqlTableModel *const model,
diff --git a/src/sql/models/qsqlrelationaltablemodel.cpp b/src/sql/models/qsqlrelationaltablemodel.cpp
index 1f590c4ab2..34be010474 100644
--- a/src/sql/models/qsqlrelationaltablemodel.cpp
+++ b/src/sql/models/qsqlrelationaltablemodel.cpp
@@ -626,8 +626,8 @@ QString QSqlRelationalTableModel::selectStatement() const
/*!
Returns a QSqlTableModel object for accessing the table for which
- \a column is a foreign key, or 0 if there is no relation for the
- given \a column.
+ \a column is a foreign key, or \nullptr if there is no relation for
+ the given \a column.
The returned object is owned by the QSqlRelationalTableModel.
@@ -636,12 +636,12 @@ QString QSqlRelationalTableModel::selectStatement() const
QSqlTableModel *QSqlRelationalTableModel::relationModel(int column) const
{
Q_D(const QSqlRelationalTableModel);
- if ( column < 0 || column >= d->relations.count())
- return 0;
+ if (column < 0 || column >= d->relations.count())
+ return nullptr;
QRelation &relation = const_cast<QSqlRelationalTableModelPrivate *>(d)->relations[column];
if (!relation.isValid())
- return 0;
+ return nullptr;
if (!relation.model)
relation.populateModel();
diff --git a/src/sql/models/qsqlrelationaltablemodel.h b/src/sql/models/qsqlrelationaltablemodel.h
index 555755009c..1929bd320a 100644
--- a/src/sql/models/qsqlrelationaltablemodel.h
+++ b/src/sql/models/qsqlrelationaltablemodel.h
@@ -58,7 +58,7 @@ public:
const QString &displayCol)
: tName(aTableName), iColumn(indexCol), dColumn(displayCol) {}
- void swap(QSqlRelation &other) Q_DECL_NOTHROW
+ void swap(QSqlRelation &other) noexcept
{
qSwap(tName, other.tName);
qSwap(iColumn, other.iColumn);
@@ -71,7 +71,7 @@ public:
{ return iColumn; }
inline QString displayColumn() const
{ return dColumn; }
- bool isValid() const Q_DECL_NOTHROW
+ bool isValid() const noexcept
{ return !(tName.isEmpty() || iColumn.isEmpty() || dColumn.isEmpty()); }
private:
QString tName, iColumn, dColumn;
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp
index a33f76838f..11d30ab2e8 100644
--- a/src/sql/models/qsqltablemodel.cpp
+++ b/src/sql/models/qsqltablemodel.cpp
@@ -50,6 +50,7 @@
#include "qsqltablemodel_p.h"
#include <qdebug.h>
+#include <qstringlistmodel.h>
QT_BEGIN_NAMESPACE
@@ -607,6 +608,16 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in
return true;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \reimp
+ */
+bool QSqlTableModel::clearItemData(const QModelIndex &index)
+{
+ return setData(index, QVariant(), Qt::EditRole);
+}
+#endif
+
/*!
This function simply calls QSqlQueryModel::setQuery(\a query).
You should normally not call it on a QSqlTableModel. Instead, use
diff --git a/src/sql/models/qsqltablemodel.h b/src/sql/models/qsqltablemodel.h
index 7acc7dc94d..eba27e60ec 100644
--- a/src/sql/models/qsqltablemodel.h
+++ b/src/sql/models/qsqltablemodel.h
@@ -74,6 +74,9 @@ public:
QSqlRecord record(int row) const;
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool clearItemData(const QModelIndex &index) override;
+#endif
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h
index bb568ab444..9ac34e7259 100644
--- a/src/sql/models/qsqltablemodel_p.h
+++ b/src/sql/models/qsqltablemodel_p.h
@@ -93,7 +93,7 @@ public:
QSqlTableModel::EditStrategy strategy;
bool busyInsertingRows;
- QSqlQuery editQuery = { QSqlQuery(0) };
+ QSqlQuery editQuery = { QSqlQuery(nullptr) };
QSqlIndex primaryIndex;
QString tableName;
QString filter;
diff --git a/src/src.pro b/src/src.pro
index 1c76a2e46f..b1afdd27a5 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -21,10 +21,6 @@ src_tools_rcc.subdir = tools/rcc
src_tools_rcc.target = sub-rcc
src_tools_rcc.depends = src_tools_bootstrap
-src_tools_qfloat16_tables.subdir = tools/qfloat16-tables
-src_tools_qfloat16_tables.target = sub-qfloat16-tables
-src_tools_qfloat16_tables.depends = src_tools_bootstrap
-
src_tools_qlalr.subdir = tools/qlalr
src_tools_qlalr.target = sub-qlalr
force_bootstrap: src_tools_qlalr.depends = src_tools_bootstrap
@@ -57,6 +53,10 @@ src_tools_androiddeployqt.subdir = tools/androiddeployqt
src_tools_androiddeployqt.target = sub-androiddeployqt
src_tools_androiddeployqt.depends = src_corelib
+src_tools_androidtestrunner.subdir = tools/androidtestrunner
+src_tools_androidtestrunner.target = sub-androidtestrunner
+src_tools_androidtestrunner.depends = src_corelib
+
src_tools_qvkgen.subdir = tools/qvkgen
src_tools_qvkgen.target = sub-qvkgen
force_bootstrap: src_tools_qvkgen.depends = src_tools_bootstrap
@@ -68,7 +68,7 @@ src_winmain.depends = sub-corelib # just for the module .pri file
src_corelib.subdir = $$PWD/corelib
src_corelib.target = sub-corelib
-src_corelib.depends = src_tools_moc src_tools_rcc src_tools_qfloat16_tables
+src_corelib.depends = src_tools_moc src_tools_rcc
src_xml.subdir = $$PWD/xml
src_xml.target = sub-xml
@@ -155,12 +155,12 @@ src_android.subdir = $$PWD/android
src_3rdparty_freetype.depends += src_corelib
}
}
-SUBDIRS += src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_qfloat16_tables
+SUBDIRS += src_tools_bootstrap src_tools_moc src_tools_rcc
qtConfig(regularexpression):pcre2 {
SUBDIRS += src_3rdparty_pcre2
src_corelib.depends += src_3rdparty_pcre2
}
-TOOLS = src_tools_moc src_tools_rcc src_tools_qlalr src_tools_qfloat16_tables
+TOOLS = src_tools_moc src_tools_rcc src_tools_qlalr
!force_bootstrap:if(qtConfig(lttng)|qtConfig(etw)) {
SUBDIRS += src_tools_tracegen
src_corelib.depends += src_tools_tracegen
@@ -189,8 +189,10 @@ qtConfig(dbus) {
}
android {
- SUBDIRS += src_tools_androiddeployqt
- TOOLS += src_tools_androiddeployqt
+ SUBDIRS += src_tools_androiddeployqt \
+ src_tools_androidtestrunner
+ TOOLS += src_tools_androiddeployqt \
+ src_tools_androidtestrunner
}
qtConfig(concurrent): SUBDIRS += src_concurrent
diff --git a/src/testlib/configure.json b/src/testlib/configure.json
index c464037205..726f614ee5 100644
--- a/src/testlib/configure.json
+++ b/src/testlib/configure.json
@@ -5,11 +5,23 @@
],
"features": {
+ "testlib_selfcover": {
+ "label": "Coverage testing of testlib itself",
+ "purpose": "Gauges how thoroughly testlib's selftest exercises testlib's code",
+ "autoDetect": false,
+ "output": [ "publicFeature" ]
+ },
"itemmodeltester": {
"label": "Tester for item models",
"purpose": "Provides a utility to test item models.",
"condition": "features.itemmodel",
"output": [ "publicFeature" ]
+ },
+ "valgrind": {
+ "label": "Valgrind",
+ "purpose": "Profiling support with callgrind.",
+ "condition": "(config.linux || config.darwin) && features.process && features.regularexpression",
+ "output": [ "publicFeature" ]
}
},
diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf
index 93a5ab393c..5fdf6d9415 100644
--- a/src/testlib/doc/qttestlib.qdocconf
+++ b/src/testlib/doc/qttestlib.qdocconf
@@ -27,7 +27,7 @@ qhp.QtTestLib.subprojects.classes.sortPages = true
tagfile = ../../../doc/qttestlib/qttestlib.tags
-depends += qtcore qtdoc qtwidgets qtgui qmake qtquick
+depends += qtcore qtdoc qtwidgets qtgui qmake qtqmltest
headerdirs += ..
diff --git a/src/testlib/doc/src/dontdocument.qdoc b/src/testlib/doc/src/dontdocument.qdoc
new file mode 100644
index 0000000000..59270c7a4f
--- /dev/null
+++ b/src/testlib/doc/src/dontdocument.qdoc
@@ -0,0 +1,32 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+/*!
+ \dontdocument (QTestEventLoop QTestData QEventSizeOfChecker QSpontaneKeyEvent
+ QTestEvent QTestKeyEvent QTestKeyClicksEvent QTestMouseEvent
+ QTestDelayEvent QMetaTypeId)
+*/
diff --git a/src/testlib/doc/src/qttest-index.qdoc b/src/testlib/doc/src/qttest-index.qdoc
index 6e4f954034..23be46b431 100644
--- a/src/testlib/doc/src/qttest-index.qdoc
+++ b/src/testlib/doc/src/qttest-index.qdoc
@@ -75,11 +75,15 @@
\section1 Reference
- These are links to the API reference materials.
+ \list
+ \li \l{Qt Test C++ Classes}
+ \endlist
+
+ The \l {Qt Quick Test} module enables unit testing Qt Quick applications.
\list
- \li \l{Qt Test C++ Classes}{C++ Classes}
- \li \l{Qt Quick Test QML Types}{QML Types}
+ \li \l{Qt Quick Test QML Types}
+ \li \l{Qt Quick Test C++ API}
\endlist
*/
diff --git a/src/testlib/qabstractitemmodeltester.h b/src/testlib/qabstractitemmodeltester.h
index 757074c6ae..57b8f283bc 100644
--- a/src/testlib/qabstractitemmodeltester.h
+++ b/src/testlib/qabstractitemmodeltester.h
@@ -123,11 +123,11 @@ do { \
MODELTESTER_VERIFY(variant.canConvert<QFont>());
// General Purpose roles that should return a QColor or a QBrush
- variant = model->data(model->index(0, 0), Qt::BackgroundColorRole);
+ variant = model->data(model->index(0, 0), Qt::BackgroundRole);
if (variant.isValid())
MODELTESTER_VERIFY(variant.canConvert<QColor>() || variant.canConvert<QBrush>());
- variant = model->data(model->index(0, 0), Qt::TextColorRole);
+ variant = model->data(model->index(0, 0), Qt::ForegroundRole);
if (variant.isValid())
MODELTESTER_VERIFY(variant.canConvert<QColor>() || variant.canConvert<QBrush>());
diff --git a/src/testlib/qabstracttestlogger_p.h b/src/testlib/qabstracttestlogger_p.h
index a64e7ea96f..9bb1d1e80c 100644
--- a/src/testlib/qabstracttestlogger_p.h
+++ b/src/testlib/qabstracttestlogger_p.h
@@ -97,14 +97,14 @@ public:
virtual void enterTestData(QTestData *) {}
virtual void addIncident(IncidentTypes type, const char *description,
- const char *file = 0, int line = 0) = 0;
+ const char *file = nullptr, int line = 0) = 0;
virtual void addBenchmarkResult(const QBenchmarkResult &result) = 0;
virtual void addMessage(QtMsgType, const QMessageLogContext &,
const QString &);
virtual void addMessage(MessageTypes type, const QString &message,
- const char *file = 0, int line = 0) = 0;
+ const char *file = nullptr, int line = 0) = 0;
void outputString(const char *msg);
@@ -151,7 +151,7 @@ struct QTestCharBuffer
inline bool reset(int newSize)
{
- char *newBuf = 0;
+ char *newBuf = nullptr;
if (buf == staticBuf) {
// if we point to our internal buffer, we need to malloc first
newBuf = reinterpret_cast<char *>(malloc(newSize));
diff --git a/src/testlib/qbenchmark.cpp b/src/testlib/qbenchmark.cpp
index d49d07bb70..8d5543a0fc 100644
--- a/src/testlib/qbenchmark.cpp
+++ b/src/testlib/qbenchmark.cpp
@@ -82,7 +82,7 @@ QBenchmarkMeasurerBase * QBenchmarkGlobalData::createMeasurer()
{
QBenchmarkMeasurerBase *measurer = 0;
if (0) {
-#ifdef QTESTLIB_USE_VALGRIND
+#if QT_CONFIG(valgrind)
} else if (mode_ == CallgrindChildProcess || mode_ == CallgrindParentProcess) {
measurer = new QBenchmarkCallgrindMeasurer;
#endif
diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h
index 3fa9c5f534..49868ac23a 100644
--- a/src/testlib/qbenchmark_p.h
+++ b/src/testlib/qbenchmark_p.h
@@ -55,12 +55,6 @@
#include <QtCore/qglobal.h>
-#if (defined(Q_OS_LINUX) || defined Q_OS_MACOS) && QT_CONFIG(process)
-#define QTESTLIB_USE_VALGRIND
-#else
-#undef QTESTLIB_USE_VALGRIND
-#endif
-
#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE) && !defined(Q_OS_ANDROID)
#define QTESTLIB_USE_PERF_EVENTS
#else
@@ -70,7 +64,7 @@
#include <QtTest/private/qbenchmarkmeasurement_p.h>
#include <QtCore/QMap>
#include <QtTest/qttestglobal.h>
-#ifdef QTESTLIB_USE_VALGRIND
+#if QT_CONFIG(valgrind)
#include <QtTest/private/qbenchmarkvalgrind_p.h>
#endif
#ifdef QTESTLIB_USE_PERF_EVENTS
diff --git a/src/testlib/qbenchmarkevent.cpp b/src/testlib/qbenchmarkevent.cpp
index f696f8b1eb..a8270219e4 100644
--- a/src/testlib/qbenchmarkevent.cpp
+++ b/src/testlib/qbenchmarkevent.cpp
@@ -96,7 +96,11 @@ QTest::QBenchmarkMetric QBenchmarkEvent::metricType()
}
// This could be done in a much better way, this is just the beginning.
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QBenchmarkEvent::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
+#else
bool QBenchmarkEvent::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
+#endif
{
Q_UNUSED(eventType);
Q_UNUSED(message);
diff --git a/src/testlib/qbenchmarkevent_p.h b/src/testlib/qbenchmarkevent_p.h
index af42a17141..0f47aa475c 100644
--- a/src/testlib/qbenchmarkevent_p.h
+++ b/src/testlib/qbenchmarkevent_p.h
@@ -71,7 +71,11 @@ public:
int adjustMedianCount(int suggestion) override;
bool repeatCount() override { return 1; }
QTest::QBenchmarkMetric metricType() override;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
+#else
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
+#endif
qint64 eventCounter;
};
diff --git a/src/testlib/qbenchmarkvalgrind.cpp b/src/testlib/qbenchmarkvalgrind.cpp
index 1de149258d..0dac804338 100644
--- a/src/testlib/qbenchmarkvalgrind.cpp
+++ b/src/testlib/qbenchmarkvalgrind.cpp
@@ -39,13 +39,12 @@
#include <QtTest/private/qbenchmark_p.h>
-#ifdef QTESTLIB_USE_VALGRIND
-
#include <QtTest/private/qbenchmarkvalgrind_p.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qprocess.h>
#include <QtCore/qdir.h>
+#include <QtCore/qregularexpression.h>
#include <QtCore/qset.h>
#include <QtTest/private/callgrind_p.h>
@@ -90,13 +89,13 @@ qint64 QBenchmarkValgrindUtils::extractResult(const QString &fileName)
qint64 val = -1;
bool valSeen = false;
- QRegExp rxValue(QLatin1String("^summary: (\\d+)"));
+ QRegularExpression rxValue(QLatin1String("^summary: (\\d+)"));
while (!file.atEnd()) {
const QString line(QLatin1String(file.readLine()));
- if (rxValue.indexIn(line) != -1) {
- Q_ASSERT(rxValue.captureCount() == 1);
+ QRegularExpressionMatch match = rxValue.match(line);
+ if (match.hasMatch()) {
bool ok;
- val = rxValue.cap(1).toLongLong(&ok);
+ val = match.captured(1).toLongLong(&ok);
Q_ASSERT(ok);
valSeen = true;
break;
@@ -120,13 +119,12 @@ QString QBenchmarkValgrindUtils::getNewestFileName()
int hiSuffix = -1;
QFileInfo lastFileInfo;
const QString pattern = QString::fromLatin1("%1.(\\d+)").arg(base);
- QRegExp rx(pattern);
+ QRegularExpression rx(pattern);
for (const QFileInfo &fileInfo : fiList) {
- const int index = rx.indexIn(fileInfo.fileName());
- Q_ASSERT(index == 0);
- Q_UNUSED(index);
+ QRegularExpressionMatch match = rx.match(fileInfo.fileName());
+ Q_ASSERT(match.hasMatch());
bool ok;
- const int suffix = rx.cap(1).toInt(&ok);
+ const int suffix = match.captured(1).toInt(&ok);
Q_ASSERT(ok);
Q_ASSERT(suffix >= 0);
if (suffix > hiSuffix) {
@@ -243,5 +241,3 @@ QTest::QBenchmarkMetric QBenchmarkCallgrindMeasurer::metricType()
}
QT_END_NAMESPACE
-
-#endif // QTESTLIB_USE_VALGRIND
diff --git a/src/testlib/qbenchmarkvalgrind_p.h b/src/testlib/qbenchmarkvalgrind_p.h
index 69219b9a65..0619be9f22 100644
--- a/src/testlib/qbenchmarkvalgrind_p.h
+++ b/src/testlib/qbenchmarkvalgrind_p.h
@@ -58,6 +58,8 @@
class QStringList;
+QT_REQUIRE_CONFIG(valgrind);
+
QT_BEGIN_NAMESPACE
class QBenchmarkValgrindUtils
diff --git a/src/testlib/qcsvbenchmarklogger_p.h b/src/testlib/qcsvbenchmarklogger_p.h
index 5840aee0f5..83e465c859 100644
--- a/src/testlib/qcsvbenchmarklogger_p.h
+++ b/src/testlib/qcsvbenchmarklogger_p.h
@@ -68,11 +68,11 @@ public:
void leaveTestFunction() override;
void addIncident(IncidentTypes type, const char *description,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
void addBenchmarkResult(const QBenchmarkResult &result) override;
void addMessage(MessageTypes type, const QString &message,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
};
QT_END_NAMESPACE
diff --git a/src/testlib/qplaintestlogger_p.h b/src/testlib/qplaintestlogger_p.h
index 55755830b2..80ef4864c1 100644
--- a/src/testlib/qplaintestlogger_p.h
+++ b/src/testlib/qplaintestlogger_p.h
@@ -68,17 +68,17 @@ public:
void leaveTestFunction() override;
void addIncident(IncidentTypes type, const char *description,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
void addBenchmarkResult(const QBenchmarkResult &result) override;
void addMessage(QtMsgType, const QMessageLogContext &,
const QString &) override;
void addMessage(MessageTypes type, const QString &message,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
private:
- void printMessage(const char *type, const char *msg, const char *file = 0, int line = 0);
+ void printMessage(const char *type, const char *msg, const char *file = nullptr, int line = 0);
void outputMessage(const char *str);
void printBenchmarkResult(const QBenchmarkResult &result);
};
diff --git a/src/testlib/qsignaldumper.cpp b/src/testlib/qsignaldumper.cpp
index 8305c5d424..d0b6d0dd3f 100644
--- a/src/testlib/qsignaldumper.cpp
+++ b/src/testlib/qsignaldumper.cpp
@@ -87,7 +87,7 @@ static void qSignalDumperCallback(QObject *caller, int signal_index, void **argv
str += objname.toLocal8Bit();
if (!objname.isEmpty())
str += ' ';
- str += QByteArray::number(quintptr(caller), 16);
+ str += QByteArray::number(quintptr(caller), 16).rightJustified(8, '0');
str += ") ";
str += member.name();
@@ -105,7 +105,7 @@ static void qSignalDumperCallback(QObject *caller, int signal_index, void **argv
str += '@';
quintptr addr = quintptr(*reinterpret_cast<void **>(argv[i + 1]));
- str.append(QByteArray::number(addr, 16));
+ str.append(QByteArray::number(addr, 16).rightJustified(8, '0'));
} else if (typeId != QMetaType::UnknownType) {
Q_ASSERT(typeId != QMetaType::Void); // void parameter => metaobject is corrupt
str.append(arg)
@@ -144,7 +144,7 @@ static void qSignalDumperCallbackSlot(QObject *caller, int method_index, void **
str += objname.toLocal8Bit();
if (!objname.isEmpty())
str += ' ';
- str += QByteArray::number(quintptr(caller), 16);
+ str += QByteArray::number(quintptr(caller), 16).rightJustified(8, '0');
str += ") ";
str += member.methodSignature();
@@ -170,13 +170,12 @@ void QSignalDumper::startDump()
{
static QSignalSpyCallbackSet set = { QTest::qSignalDumperCallback,
QTest::qSignalDumperCallbackSlot, QTest::qSignalDumperCallbackEndSignal, 0 };
- qt_register_signal_spy_callbacks(set);
+ qt_register_signal_spy_callbacks(&set);
}
void QSignalDumper::endDump()
{
- static QSignalSpyCallbackSet nset = { 0, 0, 0 ,0 };
- qt_register_signal_spy_callbacks(nset);
+ qt_register_signal_spy_callbacks(nullptr);
}
void QSignalDumper::ignoreClass(const QByteArray &klass)
diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h
index 218a26ec5c..0285080662 100644
--- a/src/testlib/qsignalspy.h
+++ b/src/testlib/qsignalspy.h
@@ -122,7 +122,7 @@ public:
}
if (!QMetaObject::connect(obj, sigIndex, this, memberOffset,
- Qt::DirectConnection, 0)) {
+ Qt::DirectConnection, nullptr)) {
qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect.");
return;
}
diff --git a/src/testlib/qsignalspy.qdoc b/src/testlib/qsignalspy.qdoc
index 77affc9a4b..3352307d69 100644
--- a/src/testlib/qsignalspy.qdoc
+++ b/src/testlib/qsignalspy.qdoc
@@ -63,7 +63,7 @@
Constructs a new QSignalSpy that listens for emissions of the \a signal
from the QObject \a object. If QSignalSpy is not able to listen for a
- valid signal (for example, because \a object is null or \a signal does
+ valid signal (for example, because \a object is \nullptr or \a signal does
not denote a valid signal of \a object), an explanatory warning message
will be output using qWarning() and subsequent calls to \c isValid() will
return false.
@@ -77,7 +77,7 @@
Constructs a new QSignalSpy that listens for emissions of the \a signal
from the QObject \a object. If QSignalSpy is not able to listen for a
- valid signal (for example, because \a object is null or \a signal does
+ valid signal (for example, because \a object is \nullptr or \a signal does
not denote a valid signal of \a object), an explanatory warning message
will be output using qWarning() and subsequent calls to \c isValid() will
return false.
diff --git a/src/testlib/qtaptestlogger.cpp b/src/testlib/qtaptestlogger.cpp
index 540b36e273..476761e602 100644
--- a/src/testlib/qtaptestlogger.cpp
+++ b/src/testlib/qtaptestlogger.cpp
@@ -154,10 +154,10 @@ void QTapTestLogger::addIncident(IncidentTypes type, const char *description,
// This is fragile, but unfortunately testlib doesn't plumb
// the expected and actual values to the loggers (yet).
static QRegularExpression verifyRegex(
- QLatin1Literal("^'(?<actualexpression>.*)' returned (?<actual>\\w+).+\\((?<message>.*)\\)$"));
+ QLatin1String("^'(?<actualexpression>.*)' returned (?<actual>\\w+).+\\((?<message>.*)\\)$"));
static QRegularExpression comparRegex(
- QLatin1Literal("^(?<message>.*)\n"
+ QLatin1String("^(?<message>.*)\n"
"\\s*Actual\\s+\\((?<actualexpression>.*)\\)\\s*: (?<actual>.*)\n"
"\\s*Expected\\s+\\((?<expectedexpresssion>.*)\\)\\s*: (?<expected>.*)$"));
@@ -168,22 +168,22 @@ void QTapTestLogger::addIncident(IncidentTypes type, const char *description,
if (match.hasMatch()) {
bool isVerify = match.regularExpression() == verifyRegex;
- QString message = match.captured(QLatin1Literal("message"));
+ QString message = match.captured(QLatin1String("message"));
QString expected;
QString actual;
if (isVerify) {
- QString expression = QLatin1Literal(" (")
- % match.captured(QLatin1Literal("actualexpression")) % QLatin1Char(')') ;
- actual = match.captured(QLatin1Literal("actual")).toLower() % expression;
- expected = (actual.startsWith(QLatin1Literal("true")) ? QLatin1Literal("false") : QLatin1Literal("true")) % expression;
+ QString expression = QLatin1String(" (")
+ % match.captured(QLatin1String("actualexpression")) % QLatin1Char(')') ;
+ actual = match.captured(QLatin1String("actual")).toLower() % expression;
+ expected = (actual.startsWith(QLatin1String("true")) ? QLatin1String("false") : QLatin1String("true")) % expression;
if (message.isEmpty())
- message = QLatin1Literal("Verification failed");
+ message = QLatin1String("Verification failed");
} else {
- expected = match.captured(QLatin1Literal("expected"))
- % QLatin1Literal(" (") % match.captured(QLatin1Literal("expectedexpresssion")) % QLatin1Char(')');
- actual = match.captured(QLatin1Literal("actual"))
- % QLatin1Literal(" (") % match.captured(QLatin1Literal("actualexpression")) % QLatin1Char(')');
+ expected = match.captured(QLatin1String("expected"))
+ % QLatin1String(" (") % match.captured(QLatin1String("expectedexpresssion")) % QLatin1Char(')');
+ actual = match.captured(QLatin1String("actual"))
+ % QLatin1String(" (") % match.captured(QLatin1String("actualexpression")) % QLatin1Char(')');
}
QTestCharBuffer diagnosticsYamlish;
diff --git a/src/testlib/qtaptestlogger_p.h b/src/testlib/qtaptestlogger_p.h
index b51343e4fe..967c724b51 100644
--- a/src/testlib/qtaptestlogger_p.h
+++ b/src/testlib/qtaptestlogger_p.h
@@ -70,9 +70,9 @@ public:
void enterTestData(QTestData *data) override;
void addIncident(IncidentTypes type, const char *description,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
void addMessage(MessageTypes type, const QString &message,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
void addBenchmarkResult(const QBenchmarkResult &) override {};
private:
diff --git a/src/testlib/qteamcitylogger.cpp b/src/testlib/qteamcitylogger.cpp
index 577c8e70cd..88c83d1269 100644
--- a/src/testlib/qteamcitylogger.cpp
+++ b/src/testlib/qteamcitylogger.cpp
@@ -251,7 +251,7 @@ QString QTeamCityLogger::tcEscapedString(const QString &str) const
}
}
- return qMove(formattedString).simplified();
+ return std::move(formattedString).simplified();
}
QString QTeamCityLogger::escapedTestFuncName() const
diff --git a/src/testlib/qteamcitylogger_p.h b/src/testlib/qteamcitylogger_p.h
index 80f2454724..dd7c0cdcf0 100644
--- a/src/testlib/qteamcitylogger_p.h
+++ b/src/testlib/qteamcitylogger_p.h
@@ -70,11 +70,11 @@ public:
void leaveTestFunction() override;
void addIncident(IncidentTypes type, const char *description,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
void addBenchmarkResult(const QBenchmarkResult &result) override;
void addMessage(MessageTypes type, const QString &message,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
private:
QString currTestFuncName;
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 28b62129b6..89abc616d9 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -51,6 +51,7 @@
#include <QtCore/qstringlist.h>
#include <QtCore/qcborcommon.h>
#include <QtCore/qdatetime.h>
+#include <QtCore/qabstractitemmodel.h>
#include <QtCore/qobject.h>
#include <QtCore/qvariant.h>
#include <QtCore/qurl.h>
@@ -128,6 +129,13 @@ template<> inline char *toString(const QChar &c)
return qstrdup(qPrintable(QString::fromLatin1("QChar: '%1' (0x%2)").arg(c).arg(QString::number(static_cast<int>(c.unicode()), 16))));
}
+template<> inline char *toString(const QModelIndex &idx)
+{
+ char msg[128];
+ qsnprintf(msg, sizeof(msg), "QModelIndex(%d,%d,%p,%p)", idx.row(), idx.column(), idx.internalPointer(), idx.model());
+ return qstrdup(msg);
+}
+
template<> inline char *toString(const QPoint &p)
{
char msg[128] = {'\0'};
@@ -366,27 +374,41 @@ QT_END_NAMESPACE
# define QTEST_SET_MAIN_SOURCE_PATH QTest::setMainSourcePath(__FILE__);
#endif
+// Hooks for coverage-testing of QTestLib itself:
+#if QT_CONFIG(testlib_selfcover) && defined(__COVERAGESCANNER__)
+struct QtCoverageScanner
+{
+ QtCoverageScanner(const char *name)
+ {
+ __coveragescanner_clear();
+ __coveragescanner_testname(name);
+ }
+ ~QtCoverageScanner()
+ {
+ __coveragescanner_save();
+ __coveragescanner_testname("");
+ }
+};
+#define TESTLIB_SELFCOVERAGE_START(name) QtCoverageScanner _qtCoverageScanner(name);
+#else
+#define TESTLIB_SELFCOVERAGE_START(name)
+#endif
+
#define QTEST_APPLESS_MAIN(TestObject) \
int main(int argc, char *argv[]) \
{ \
+ TESTLIB_SELFCOVERAGE_START(TestObject) \
TestObject tc; \
QTEST_SET_MAIN_SOURCE_PATH \
return QTest::qExec(&tc, argc, argv); \
}
#include <QtTest/qtestsystem.h>
-#include <set>
-
-#ifndef QT_NO_OPENGL
-# define QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
- extern Q_TESTLIB_EXPORT std::set<QByteArray> *(*qgpu_features_ptr)(const QString &); \
- extern Q_GUI_EXPORT std::set<QByteArray> *qgpu_features(const QString &);
-# define QTEST_ADD_GPU_BLACKLIST_SUPPORT \
- qgpu_features_ptr = qgpu_features;
-#else
-# define QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS
-# define QTEST_ADD_GPU_BLACKLIST_SUPPORT
-#endif
+
+// Two backwards-compatibility defines for an obsolete feature:
+#define QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS
+#define QTEST_ADD_GPU_BLACKLIST_SUPPORT
+// ### Qt 6: fully remove these.
#if defined(QT_NETWORK_LIB)
# include <QtTest/qtest_network.h>
@@ -402,56 +424,49 @@ int main(int argc, char *argv[]) \
# define QTEST_DISABLE_KEYPAD_NAVIGATION
#endif
-#define QTEST_MAIN(TestObject) \
-QT_BEGIN_NAMESPACE \
-QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
-QT_END_NAMESPACE \
-int main(int argc, char *argv[]) \
-{ \
+#define QTEST_MAIN_IMPL(TestObject) \
+ TESTLIB_SELFCOVERAGE_START(#TestObject) \
QApplication app(argc, argv); \
app.setAttribute(Qt::AA_Use96Dpi, true); \
QTEST_DISABLE_KEYPAD_NAVIGATION \
- QTEST_ADD_GPU_BLACKLIST_SUPPORT \
TestObject tc; \
QTEST_SET_MAIN_SOURCE_PATH \
- return QTest::qExec(&tc, argc, argv); \
-}
+ return QTest::qExec(&tc, argc, argv);
#elif defined(QT_GUI_LIB)
#include <QtTest/qtest_gui.h>
-#define QTEST_MAIN(TestObject) \
-QT_BEGIN_NAMESPACE \
-QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
-QT_END_NAMESPACE \
-int main(int argc, char *argv[]) \
-{ \
+#define QTEST_MAIN_IMPL(TestObject) \
+ TESTLIB_SELFCOVERAGE_START(#TestObject) \
QGuiApplication app(argc, argv); \
app.setAttribute(Qt::AA_Use96Dpi, true); \
- QTEST_ADD_GPU_BLACKLIST_SUPPORT \
TestObject tc; \
QTEST_SET_MAIN_SOURCE_PATH \
- return QTest::qExec(&tc, argc, argv); \
-}
+ return QTest::qExec(&tc, argc, argv);
#else
-#define QTEST_MAIN(TestObject) \
-int main(int argc, char *argv[]) \
-{ \
+#define QTEST_MAIN_IMPL(TestObject) \
+ TESTLIB_SELFCOVERAGE_START(#TestObject) \
QCoreApplication app(argc, argv); \
app.setAttribute(Qt::AA_Use96Dpi, true); \
TestObject tc; \
QTEST_SET_MAIN_SOURCE_PATH \
- return QTest::qExec(&tc, argc, argv); \
-}
+ return QTest::qExec(&tc, argc, argv);
#endif // QT_GUI_LIB
+#define QTEST_MAIN(TestObject) \
+int main(int argc, char *argv[]) \
+{ \
+ QTEST_MAIN_IMPL(TestObject) \
+}
+
#define QTEST_GUILESS_MAIN(TestObject) \
int main(int argc, char *argv[]) \
{ \
+ TESTLIB_SELFCOVERAGE_START(#TestObject) \
QCoreApplication app(argc, argv); \
app.setAttribute(Qt::AA_Use96Dpi, true); \
TestObject tc; \
diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp
index ae2913da9a..886f1f75b9 100644
--- a/src/testlib/qtestblacklist.cpp
+++ b/src/testlib/qtestblacklist.cpp
@@ -221,22 +221,6 @@ static bool checkCondition(const QByteArray &condition)
static bool ignoreAll = false;
static std::set<QByteArray> *ignoredTests = 0;
-static std::set<QByteArray> *gpuFeatures = 0;
-
-Q_TESTLIB_EXPORT std::set<QByteArray> *(*qgpu_features_ptr)(const QString &) = 0;
-
-static bool isGPUTestBlacklisted(const char *slot, const char *data = 0)
-{
- const QByteArray disableKey = QByteArrayLiteral("disable_") + QByteArray(slot);
- if (gpuFeatures->find(disableKey) != gpuFeatures->end()) {
- QByteArray msg = QByteArrayLiteral("Skipped due to GPU blacklist: ") + disableKey;
- if (data)
- msg += ':' + QByteArray(data);
- QTest::qSkip(msg.constData(), __FILE__, __LINE__);
- return true;
- }
- return false;
-}
namespace QTestPrivate {
@@ -276,17 +260,6 @@ void parseBlackList()
}
}
-void parseGpuBlackList()
-{
- if (!qgpu_features_ptr)
- return;
- QString filename = QTest::qFindTestData(QStringLiteral("GPU_BLACKLIST"));
- if (filename.isEmpty())
- return;
- if (!gpuFeatures)
- gpuFeatures = qgpu_features_ptr(filename);
-}
-
void checkBlackLists(const char *slot, const char *data)
{
bool ignore = ignoreAll;
@@ -302,21 +275,8 @@ void checkBlackLists(const char *slot, const char *data)
}
QTestResult::setBlacklistCurrentTest(ignore);
-
- // Tests blacklisted in GPU_BLACKLIST are to be skipped. Just ignoring the result is
- // not sufficient since these are expected to crash or behave in undefined ways.
- if (!ignore && gpuFeatures) {
- QByteArray s_gpu = slot;
- ignore = isGPUTestBlacklisted(s_gpu, data);
- if (!ignore && data) {
- s_gpu += ':';
- s_gpu += data;
- isGPUTestBlacklisted(s_gpu);
- }
- }
-}
-
}
+} // QTestPrivate
QT_END_NAMESPACE
diff --git a/src/testlib/qtestblacklist_p.h b/src/testlib/qtestblacklist_p.h
index 08ce052231..4522c64992 100644
--- a/src/testlib/qtestblacklist_p.h
+++ b/src/testlib/qtestblacklist_p.h
@@ -58,7 +58,6 @@ QT_BEGIN_NAMESPACE
namespace QTestPrivate {
// Export functions so they can also be used by QQuickTest
Q_TESTLIB_EXPORT void parseBlackList();
- Q_TESTLIB_EXPORT void parseGpuBlackList();
Q_TESTLIB_EXPORT void checkBlackLists(const char *slot, const char *data);
}
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 0c935a1f1c..ac309374e3 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -52,6 +52,7 @@
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
#include <QtCore/qdebug.h>
+#include <QtCore/qfloat16.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/private/qtools_p.h>
#include <QtCore/qdiriterator.h>
@@ -249,7 +250,7 @@ static void stackTrace()
static bool installCoverageTool(const char * appname, const char * testname)
{
-#ifdef __COVERAGESCANNER__
+#if defined(__COVERAGESCANNER__) && !QT_CONFIG(testlib_selfcover)
if (!qEnvironmentVariableIsEmpty("QT_TESTCOCOON_ACTIVE"))
return false;
// Set environment variable QT_TESTCOCOON_ACTIVE to prevent an eventual subtest from
@@ -286,74 +287,75 @@ namespace QTestPrivate
namespace QTest
{
- class WatchDog;
+class WatchDog;
- static QObject *currentTestObject = 0;
- static QString mainSourcePath;
+static QObject *currentTestObject = 0;
+static QString mainSourcePath;
#if defined(Q_OS_MACOS)
- bool macNeedsActivate = false;
- IOPMAssertionID powerID;
+bool macNeedsActivate = false;
+IOPMAssertionID powerID;
#endif
- class TestMethods {
- Q_DISABLE_COPY(TestMethods)
- public:
- typedef std::vector<QMetaMethod> MetaMethods;
+class TestMethods {
+public:
+ Q_DISABLE_COPY_MOVE(TestMethods)
- explicit TestMethods(const QObject *o, const MetaMethods &m = MetaMethods());
+ typedef std::vector<QMetaMethod> MetaMethods;
- void invokeTests(QObject *testObject) const;
+ explicit TestMethods(const QObject *o, const MetaMethods &m = MetaMethods());
- static QMetaMethod findMethod(const QObject *obj, const char *signature);
+ void invokeTests(QObject *testObject) const;
- private:
- bool invokeTest(int index, const char *data, WatchDog *watchDog) const;
- void invokeTestOnData(int index) const;
+ static QMetaMethod findMethod(const QObject *obj, const char *signature);
- QMetaMethod m_initTestCaseMethod; // might not exist, check isValid().
- QMetaMethod m_initTestCaseDataMethod;
- QMetaMethod m_cleanupTestCaseMethod;
- QMetaMethod m_initMethod;
- QMetaMethod m_cleanupMethod;
+private:
+ bool invokeTest(int index, const char *data, WatchDog *watchDog) const;
+ void invokeTestOnData(int index) const;
- MetaMethods m_methods;
- };
+ QMetaMethod m_initTestCaseMethod; // might not exist, check isValid().
+ QMetaMethod m_initTestCaseDataMethod;
+ QMetaMethod m_cleanupTestCaseMethod;
+ QMetaMethod m_initMethod;
+ QMetaMethod m_cleanupMethod;
- TestMethods::TestMethods(const QObject *o, const MetaMethods &m)
- : m_initTestCaseMethod(TestMethods::findMethod(o, "initTestCase()"))
- , m_initTestCaseDataMethod(TestMethods::findMethod(o, "initTestCase_data()"))
- , m_cleanupTestCaseMethod(TestMethods::findMethod(o, "cleanupTestCase()"))
- , m_initMethod(TestMethods::findMethod(o, "init()"))
- , m_cleanupMethod(TestMethods::findMethod(o, "cleanup()"))
- , m_methods(m)
- {
- if (m.empty()) {
- const QMetaObject *metaObject = o->metaObject();
- const int count = metaObject->methodCount();
- m_methods.reserve(count);
- for (int i = 0; i < count; ++i) {
- const QMetaMethod me = metaObject->method(i);
- if (isValidSlot(me))
- m_methods.push_back(me);
- }
+ MetaMethods m_methods;
+};
+
+TestMethods::TestMethods(const QObject *o, const MetaMethods &m)
+ : m_initTestCaseMethod(TestMethods::findMethod(o, "initTestCase()"))
+ , m_initTestCaseDataMethod(TestMethods::findMethod(o, "initTestCase_data()"))
+ , m_cleanupTestCaseMethod(TestMethods::findMethod(o, "cleanupTestCase()"))
+ , m_initMethod(TestMethods::findMethod(o, "init()"))
+ , m_cleanupMethod(TestMethods::findMethod(o, "cleanup()"))
+ , m_methods(m)
+{
+ if (m.empty()) {
+ const QMetaObject *metaObject = o->metaObject();
+ const int count = metaObject->methodCount();
+ m_methods.reserve(count);
+ for (int i = 0; i < count; ++i) {
+ const QMetaMethod me = metaObject->method(i);
+ if (isValidSlot(me))
+ m_methods.push_back(me);
}
}
+}
- QMetaMethod TestMethods::findMethod(const QObject *obj, const char *signature)
- {
- const QMetaObject *metaObject = obj->metaObject();
- const int funcIndex = metaObject->indexOfMethod(signature);
- return funcIndex >= 0 ? metaObject->method(funcIndex) : QMetaMethod();
- }
+QMetaMethod TestMethods::findMethod(const QObject *obj, const char *signature)
+{
+ const QMetaObject *metaObject = obj->metaObject();
+ const int funcIndex = metaObject->indexOfMethod(signature);
+ return funcIndex >= 0 ? metaObject->method(funcIndex) : QMetaMethod();
+}
- static int keyDelay = -1;
- static int mouseDelay = -1;
- static int eventDelay = -1;
+static int keyDelay = -1;
+static int mouseDelay = -1;
+static int eventDelay = -1;
#if QT_CONFIG(thread)
- static int timeout = -1;
+static int timeout = -1;
#endif
- static bool noCrashHandler = false;
+static bool noCrashHandler = false;
/*! \internal
Invoke a method of the object without generating warning if the method does not exist
@@ -500,7 +502,7 @@ static void qPrintDataTags(FILE *stream)
}
}
-static int qToInt(char *str)
+static int qToInt(const char *str)
{
char *pEnd;
int l = (int)strtol(str, &pEnd, 10);
@@ -511,7 +513,7 @@ static int qToInt(char *str)
return l;
}
-Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
+Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool qml)
{
int logFormat = -1; // Not set
const char *logFilename = 0;
@@ -572,7 +574,7 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
" -nocrashhandler : Disables the crash handler. Useful for debugging crashes.\n"
"\n"
" Benchmarking options:\n"
-#ifdef QTESTLIB_USE_VALGRIND
+#if QT_CONFIG(valgrind)
" -callgrind : Use callgrind to time benchmarks\n"
#endif
#ifdef QTESTLIB_USE_PERF_EVENTS
@@ -715,7 +717,7 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
}
} else if (strcmp(argv[i], "-nocrashhandler") == 0) {
QTest::noCrashHandler = true;
-#ifdef QTESTLIB_USE_VALGRIND
+#if QT_CONFIG(valgrind)
} else if (strcmp(argv[i], "-callgrind") == 0) {
if (QBenchmarkValgrindUtils::haveValgrind())
if (QFileInfo(QDir::currentPath()).isWritable()) {
@@ -815,9 +817,9 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
// we load the QML files. So just store the data for now.
int colon = -1;
int offset;
- for (offset = 0; *(argv[i]+offset); ++offset) {
- if (*(argv[i]+offset) == ':') {
- if (*(argv[i]+offset+1) == ':') {
+ for (offset = 0; argv[i][offset]; ++offset) {
+ if (argv[i][offset] == ':') {
+ if (argv[i][offset + 1] == ':') {
// "::" is used as a test name separator.
// e.g. "ClickTests::test_click:row1".
++offset;
@@ -864,6 +866,11 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
QTestLog::addLogger(QTestLog::Plain, logFilename);
}
+// Temporary, backwards compatibility, until qtdeclarative's use of it is converted
+Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml) {
+ qtest_qParseArgs(argc, const_cast<const char *const *>(argv), qml);
+}
+
QBenchmarkResult qMedian(const QVector<QBenchmarkResult> &container)
{
const int count = container.count();
@@ -1005,14 +1012,14 @@ public:
WatchDog()
{
QMutexLocker locker(&mutex);
- timeout.store(-1);
+ timeout.storeRelaxed(-1);
start();
waitCondition.wait(&mutex);
}
~WatchDog() {
{
QMutexLocker locker(&mutex);
- timeout.store(0);
+ timeout.storeRelaxed(0);
waitCondition.wakeAll();
}
wait();
@@ -1020,13 +1027,13 @@ public:
void beginTest() {
QMutexLocker locker(&mutex);
- timeout.store(defaultTimeout());
+ timeout.storeRelaxed(defaultTimeout());
waitCondition.wakeAll();
}
void testFinished() {
QMutexLocker locker(&mutex);
- timeout.store(-1);
+ timeout.storeRelaxed(-1);
waitCondition.wakeAll();
}
@@ -1034,7 +1041,7 @@ public:
QMutexLocker locker(&mutex);
waitCondition.wakeAll();
while (1) {
- int t = timeout.load();
+ int t = timeout.loadRelaxed();
if (!t)
break;
if (Q_UNLIKELY(!waitCondition.wait(&mutex, t))) {
@@ -1088,7 +1095,7 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co
const int globalDataCount = gTable->dataCount();
int curGlobalDataIndex = 0;
- /* For each test function that has a *_data() table/function, do: */
+ /* For each entry in the global data table, do: */
do {
if (!gTable->isEmpty())
QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex));
@@ -1096,50 +1103,50 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co
if (curGlobalDataIndex == 0) {
qsnprintf(member, 512, "%s_data()", name.constData());
invokeMethod(QTest::currentTestObject, member);
+ if (QTestResult::skipCurrentTest())
+ break;
}
bool foundFunction = false;
- if (!QTestResult::skipCurrentTest()) {
- int curDataIndex = 0;
- const int dataCount = table.dataCount();
-
- // Data tag requested but none available?
- if (data && !dataCount) {
- // Let empty data tag through.
- if (!*data)
- data = 0;
- else {
- fprintf(stderr, "Unknown testdata for function %s(): '%s'\n", name.constData(), data);
- fprintf(stderr, "Function has no testdata.\n");
- return false;
- }
+ int curDataIndex = 0;
+ const int dataCount = table.dataCount();
+
+ // Data tag requested but none available?
+ if (data && !dataCount) {
+ // Let empty data tag through.
+ if (!*data)
+ data = 0;
+ else {
+ fprintf(stderr, "Unknown testdata for function %s(): '%s'\n", name.constData(), data);
+ fprintf(stderr, "Function has no testdata.\n");
+ return false;
}
+ }
- /* For each entry in the data table, do: */
- do {
- QTestResult::setSkipCurrentTest(false);
- QTestResult::setBlacklistCurrentTest(false);
- if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) {
- foundFunction = true;
+ /* For each entry in this test's data table, do: */
+ do {
+ QTestResult::setSkipCurrentTest(false);
+ QTestResult::setBlacklistCurrentTest(false);
+ if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) {
+ foundFunction = true;
- QTestPrivate::checkBlackLists(name.constData(), dataCount ? table.testData(curDataIndex)->dataTag() : 0);
+ QTestPrivate::checkBlackLists(name.constData(), dataCount ? table.testData(curDataIndex)->dataTag() : 0);
- QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0)
- : table.testData(curDataIndex));
+ QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0)
+ : table.testData(curDataIndex));
- QTestPrivate::qtestMouseButtons = Qt::NoButton;
- if (watchDog)
- watchDog->beginTest();
- invokeTestOnData(index);
- if (watchDog)
- watchDog->testFinished();
+ QTestPrivate::qtestMouseButtons = Qt::NoButton;
+ if (watchDog)
+ watchDog->beginTest();
+ invokeTestOnData(index);
+ if (watchDog)
+ watchDog->testFinished();
- if (data)
- break;
- }
- ++curDataIndex;
- } while (curDataIndex < dataCount);
- }
+ if (data)
+ break;
+ }
+ ++curDataIndex;
+ } while (curDataIndex < dataCount);
if (data && !foundFunction) {
fprintf(stderr, "Unknown testdata for function %s: '%s()'\n", name.constData(), data);
@@ -1214,7 +1221,9 @@ char *formatString(const char *prefix, const char *suffix, size_t numArguments,
Returns a pointer to a string that is the string \a ba represented
as a space-separated sequence of hex characters. If the input is
considered too long, it is truncated. A trucation is indicated in
- the returned string as an ellipsis at the end.
+ the returned string as an ellipsis at the end. The caller has
+ ownership of the returned pointer and must ensure it is later passed
+ to operator delete[].
\a length is the length of the string \a ba.
*/
@@ -1450,7 +1459,7 @@ void TestMethods::invokeTests(QObject *testObject) const
QScopedPointer<WatchDog> watchDog;
if (!debuggerPresent()
-#ifdef QTESTLIB_USE_VALGRIND
+#if QT_CONFIG(valgrind)
&& QBenchmarkGlobalData::current->mode() != QBenchmarkGlobalData::CallgrindChildProcess
#endif
) {
@@ -1616,7 +1625,7 @@ FatalSignalHandler::~FatalSignalHandler()
// Helper class for resolving symbol names by dynamically loading "dbghelp.dll".
class DebugSymbolResolver
{
- Q_DISABLE_COPY(DebugSymbolResolver)
+ Q_DISABLE_COPY_MOVE(DebugSymbolResolver)
public:
struct Symbol {
Symbol() : name(nullptr), address(0) {}
@@ -1832,8 +1841,6 @@ void QTest::qInit(QObject *testObject, int argc, char **argv)
#endif
QTestPrivate::parseBlackList();
- QTestPrivate::parseGpuBlackList();
-
QTestResult::reset();
QTEST_ASSERT(testObject);
@@ -1859,7 +1866,7 @@ int QTest::qRun()
{
QTEST_ASSERT(currentTestObject);
-#ifdef QTESTLIB_USE_VALGRIND
+#if QT_CONFIG(valgrind)
int callgrindChildExitCode = 0;
#endif
@@ -1879,7 +1886,7 @@ int QTest::qRun()
} // !noCrashHandler
#endif // Q_OS_WIN
-#ifdef QTESTLIB_USE_VALGRIND
+#if QT_CONFIG(valgrind)
if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) {
if (Q_UNLIKELY(!qApp))
qFatal("QtTest: -callgrind option is not available with QTEST_APPLESS_MAIN");
@@ -1937,7 +1944,7 @@ int QTest::qRun()
}
#endif
-#ifdef QTESTLIB_USE_VALGRIND
+#if QT_CONFIG(valgrind)
if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
return callgrindChildExitCode;
#endif
@@ -2141,7 +2148,7 @@ QSharedPointer<QTemporaryDir> QTest::qExtractTestData(const QString &dirName)
}
}
- result = qMove(tempDir);
+ result = std::move(tempDir);
return result;
}
@@ -2183,13 +2190,12 @@ QString QTest::qFindTestData(const QString& base, const char *file, int line, co
if (found.isEmpty()) {
const char *testObjectName = QTestResult::currentTestObjectName();
if (testObjectName) {
- QString testsPath = QLibraryInfo::location(QLibraryInfo::TestsPath);
- QString candidate = QString::fromLatin1("%1/%2/%3")
+ const QString testsPath = QLibraryInfo::location(QLibraryInfo::TestsPath);
+ const QString candidate = QString::fromLatin1("%1/%2/%3")
.arg(testsPath, QFile::decodeName(testObjectName).toLower(), base);
if (QFileInfo::exists(candidate)) {
found = candidate;
- }
- else if (QTestLog::verboseLevel() >= 2) {
+ } else if (QTestLog::verboseLevel() >= 2) {
QTestLog::info(qPrintable(
QString::fromLatin1("testdata %1 not found in tests install path [%2]; "
"checking next location")
@@ -2211,11 +2217,10 @@ QString QTest::qFindTestData(const QString& base, const char *file, int line, co
}
const QString canonicalPath = srcdir.canonicalFilePath();
- QString candidate = QString::fromLatin1("%1/%2").arg(canonicalPath, base);
+ const QString candidate = QString::fromLatin1("%1/%2").arg(canonicalPath, base);
if (!canonicalPath.isEmpty() && QFileInfo::exists(candidate)) {
found = candidate;
- }
- else if (QTestLog::verboseLevel() >= 2) {
+ } else if (QTestLog::verboseLevel() >= 2) {
QTestLog::info(qPrintable(
QString::fromLatin1("testdata %1 not found relative to source path [%2]")
.arg(base, QDir::toNativeSeparators(candidate))),
@@ -2225,31 +2230,48 @@ QString QTest::qFindTestData(const QString& base, const char *file, int line, co
// 4. Try resources
if (found.isEmpty()) {
- QString candidate = QString::fromLatin1(":/%1").arg(base);
- if (QFileInfo::exists(candidate))
+ const QString candidate = QString::fromLatin1(":/%1").arg(base);
+ if (QFileInfo::exists(candidate)) {
found = candidate;
+ } else if (QTestLog::verboseLevel() >= 2) {
+ QTestLog::info(qPrintable(
+ QString::fromLatin1("testdata %1 not found in resources [%2]")
+ .arg(base, QDir::toNativeSeparators(candidate))),
+ file, line);
+ }
}
// 5. Try current directory
if (found.isEmpty()) {
const QString candidate = QDir::currentPath() + QLatin1Char('/') + base;
- if (QFileInfo::exists(candidate))
+ if (QFileInfo::exists(candidate)) {
found = candidate;
+ } else if (QTestLog::verboseLevel() >= 2) {
+ QTestLog::info(qPrintable(
+ QString::fromLatin1("testdata %1 not found in current directory [%2]")
+ .arg(base, QDir::toNativeSeparators(candidate))),
+ file, line);
+ }
}
// 6. Try main source directory
if (found.isEmpty()) {
- QString candidate = QTest::mainSourcePath % QLatin1Char('/') % base;
- if (QFileInfo::exists(candidate))
+ const QString candidate = QTest::mainSourcePath % QLatin1Char('/') % base;
+ if (QFileInfo::exists(candidate)) {
found = candidate;
+ } else if (QTestLog::verboseLevel() >= 2) {
+ QTestLog::info(qPrintable(
+ QString::fromLatin1("testdata %1 not found in main source directory [%2]")
+ .arg(base, QDir::toNativeSeparators(candidate))),
+ file, line);
+ }
}
if (found.isEmpty()) {
QTest::qWarn(qPrintable(
QString::fromLatin1("testdata %1 could not be located!").arg(base)),
file, line);
- }
- else if (QTestLog::verboseLevel() >= 1) {
+ } else if (QTestLog::verboseLevel() >= 1) {
QTestLog::info(qPrintable(
QString::fromLatin1("testdata %1 was located at %2").arg(base, QDir::toNativeSeparators(found))),
file, line);
@@ -2323,7 +2345,7 @@ void QTest::addColumnInternal(int id, const char *name)
*/
QTestData &QTest::newRow(const char *dataTag)
{
- QTEST_ASSERT_X(dataTag, "QTest::newRow()", "Data tag can not be null");
+ QTEST_ASSERT_X(dataTag, "QTest::newRow()", "Data tag cannot be null");
QTestTable *tbl = QTestTable::currentTestTable();
QTEST_ASSERT_X(tbl, "QTest::newRow()", "Cannot add testdata outside of a _data slot.");
QTEST_ASSERT_X(tbl->elementCount(), "QTest::newRow()", "Must add columns before attempting to add rows.");
@@ -2497,22 +2519,39 @@ bool QTest::compare_helper(bool success, const char *failureMsg,
return QTestResult::compare(success, failureMsg, val1, val2, actual, expected, file, line);
}
+template <typename T>
+static bool floatingCompare(const T &t1, const T &t2)
+{
+ switch (qFpClassify(t1))
+ {
+ case FP_INFINITE:
+ return (t1 < 0) == (t2 < 0) && qFpClassify(t2) == FP_INFINITE;
+ case FP_NAN:
+ return qFpClassify(t2) == FP_NAN;
+ default:
+ return qFuzzyCompare(t1, t2);
+ }
+}
+
+/*! \fn bool QTest::qCompare(const qfloat16 &t1, const qfloat16 &t2, const char *actual, const char *expected, const char *file, int line)
+ \internal
+ */
+bool QTest::qCompare(qfloat16 const &t1, qfloat16 const &t2, const char *actual, const char *expected,
+ const char *file, int line)
+{
+ return compare_helper(floatingCompare(t1, t2),
+ "Compared qfloat16s are not the same (fuzzy compare)",
+ toString(t1), toString(t2), actual, expected, file, line);
+}
+
/*! \fn bool QTest::qCompare(const float &t1, const float &t2, const char *actual, const char *expected, const char *file, int line)
\internal
*/
bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const char *expected,
const char *file, int line)
{
- bool equal = false;
- int cl1 = std::fpclassify(t1);
- int cl2 = std::fpclassify(t2);
- if (cl1 == FP_INFINITE)
- equal = ((t1 < 0) == (t2 < 0)) && cl2 == FP_INFINITE;
- else if (cl1 == FP_NAN)
- equal = (cl2 == FP_NAN);
- else
- equal = qFuzzyCompare(t1, t2);
- return compare_helper(equal, "Compared floats are not the same (fuzzy compare)",
+ return compare_helper(floatingCompare(t1, t2),
+ "Compared floats are not the same (fuzzy compare)",
toString(t1), toString(t2), actual, expected, file, line);
}
@@ -2522,16 +2561,8 @@ bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const
bool QTest::qCompare(double const &t1, double const &t2, const char *actual, const char *expected,
const char *file, int line)
{
- bool equal = false;
- int cl1 = std::fpclassify(t1);
- int cl2 = std::fpclassify(t2);
- if (cl1 == FP_INFINITE)
- equal = ((t1 < 0) == (t2 < 0)) && cl2 == FP_INFINITE;
- else if (cl1 == FP_NAN)
- equal = (cl2 == FP_NAN);
- else
- equal = qFuzzyCompare(t1, t2);
- return compare_helper(equal, "Compared doubles are not the same (fuzzy compare)",
+ return compare_helper(floatingCompare(t1, t2),
+ "Compared doubles are not the same (fuzzy compare)",
toString(t1), toString(t2), actual, expected, file, line);
}
@@ -2601,7 +2632,7 @@ static void massageExponent(char *text)
template <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
{ \
char *msg = new char[128]; \
- switch (std::fpclassify(t)) { \
+ switch (qFpClassify(t)) { \
case FP_INFINITE: \
qstrncpy(msg, (t < 0 ? "-inf" : "inf"), 128); \
break; \
@@ -2609,15 +2640,16 @@ template <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
qstrncpy(msg, "nan", 128); \
break; \
default: \
- qsnprintf(msg, 128, #FORMAT, t); \
+ qsnprintf(msg, 128, #FORMAT, double(t)); \
massageExponent(msg); \
break; \
} \
return msg; \
}
+TO_STRING_FLOAT(qfloat16, %.3g)
TO_STRING_FLOAT(float, %g)
-TO_STRING_FLOAT(double, %.12lg)
+TO_STRING_FLOAT(double, %.12g)
template <> Q_TESTLIB_EXPORT char *QTest::toString<char>(const char &t)
{
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index 5fed9d6bcc..794283ff78 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -57,6 +57,7 @@
QT_BEGIN_NAMESPACE
+class qfloat16;
class QRegularExpression;
#define QVERIFY(statement) \
@@ -67,17 +68,17 @@ do {\
#define QFAIL(message) \
do {\
- QTest::qFail(message, __FILE__, __LINE__);\
+ QTest::qFail(static_cast<const char *>(message), __FILE__, __LINE__);\
return;\
} while (false)
#define QVERIFY2(statement, description) \
do {\
if (statement) {\
- if (!QTest::qVerify(true, #statement, (description), __FILE__, __LINE__))\
+ if (!QTest::qVerify(true, #statement, static_cast<const char *>(description), __FILE__, __LINE__))\
return;\
} else {\
- if (!QTest::qVerify(false, #statement, (description), __FILE__, __LINE__))\
+ if (!QTest::qVerify(false, #statement, static_cast<const char *>(description), __FILE__, __LINE__))\
return;\
}\
} while (false)
@@ -184,23 +185,15 @@ do { \
#define QSKIP_INTERNAL(statement) \
do {\
- QTest::qSkip(statement, __FILE__, __LINE__);\
+ QTest::qSkip(static_cast<const char *>(statement), __FILE__, __LINE__);\
return;\
} while (false)
-#ifdef Q_COMPILER_VARIADIC_MACROS
-
#define QSKIP(statement, ...) QSKIP_INTERNAL(statement)
-#else
-
-#define QSKIP(statement) QSKIP_INTERNAL(statement)
-
-#endif
-
#define QEXPECT_FAIL(dataIndex, comment, mode)\
do {\
- if (!QTest::qExpectFail(dataIndex, comment, QTest::mode, __FILE__, __LINE__))\
+ if (!QTest::qExpectFail(dataIndex, static_cast<const char *>(comment), QTest::mode, __FILE__, __LINE__))\
return;\
} while (false)
@@ -217,7 +210,7 @@ do {\
} while (false)
#define QWARN(msg)\
- QTest::qWarn(msg, __FILE__, __LINE__)
+ QTest::qWarn(static_cast<const char *>(msg), __FILE__, __LINE__)
#ifdef QT_TESTCASE_BUILDDIR
# define QFINDTESTDATA(basepath)\
@@ -361,6 +354,9 @@ namespace QTest
}
#endif
+ Q_TESTLIB_EXPORT bool qCompare(qfloat16 const &t1, qfloat16 const &t2,
+ const char *actual, const char *expected, const char *file, int line);
+
Q_TESTLIB_EXPORT bool qCompare(float const &t1, float const &t2,
const char *actual, const char *expected, const char *file, int line);
@@ -405,6 +401,7 @@ namespace QTest
QTEST_COMPARE_DECL(float)
QTEST_COMPARE_DECL(double)
+ QTEST_COMPARE_DECL(qfloat16)
QTEST_COMPARE_DECL(char)
QTEST_COMPARE_DECL(signed char)
QTEST_COMPARE_DECL(unsigned char)
diff --git a/src/testlib/qtestcoreelement_p.h b/src/testlib/qtestcoreelement_p.h
index e79efdd87f..84406fed85 100644
--- a/src/testlib/qtestcoreelement_p.h
+++ b/src/testlib/qtestcoreelement_p.h
@@ -80,7 +80,7 @@ class QTestCoreElement: public QTestCoreList<ElementType>
template<class ElementType>
QTestCoreElement<ElementType>::QTestCoreElement(int t)
- :listOfAttributes(0), type(QTest::LogElementType(t))
+ :listOfAttributes(nullptr), type(QTest::LogElementType(t))
{
}
@@ -114,7 +114,7 @@ const char *QTestCoreElement<ElementType>::attributeValue(QTest::AttributeIndex
if (attrb)
return attrb->value();
- return 0;
+ return nullptr;
}
template <class ElementType>
@@ -124,7 +124,7 @@ const char *QTestCoreElement<ElementType>::attributeName(QTest::AttributeIndex i
if (attrb)
return attrb->name();
- return 0;
+ return nullptr;
}
template <class ElementType>
@@ -145,7 +145,7 @@ const char *QTestCoreElement<ElementType>::elementName() const
if (type != QTest::LET_Undefined)
return xmlElementNames[type];
- return 0;
+ return nullptr;
}
template <class ElementType>
@@ -165,7 +165,7 @@ const QTestElementAttribute *QTestCoreElement<ElementType>::attribute(QTest::Att
iterator = iterator->nextElement();
}
- return 0;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/testlib/qtestcorelist_p.h b/src/testlib/qtestcorelist_p.h
index 5943695876..daeb293644 100644
--- a/src/testlib/qtestcorelist_p.h
+++ b/src/testlib/qtestcorelist_p.h
@@ -66,9 +66,6 @@ class QTestCoreList
void addToList(T **list);
T *nextElement();
T *previousElement();
- int count(T *list);
- int count();
-
private:
T *next;
T *prev;
@@ -76,8 +73,8 @@ class QTestCoreList
template <class T>
QTestCoreList<T>::QTestCoreList()
- : next(0)
- , prev(0)
+ : next(nullptr)
+ , prev(nullptr)
{
}
@@ -85,12 +82,12 @@ template <class T>
QTestCoreList<T>::~QTestCoreList()
{
if (prev) {
- prev->next = 0;
+ prev->next = nullptr;
}
delete prev;
if (next) {
- next->prev = 0;
+ next->prev = nullptr;
}
delete next;
}
@@ -121,20 +118,6 @@ T *QTestCoreList<T>::previousElement()
return prev;
}
-template <class T>
-int QTestCoreList<T>::count()
-{
- int numOfElements = 0;
- T *it = next;
-
- while (it) {
- ++numOfElements;
- it = it->nextElement();
- }
-
- return numOfElements;
-}
-
QT_END_NAMESPACE
#endif
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index 57bb7d95a7..14543c3cde 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -74,6 +74,10 @@ QT_BEGIN_NAMESPACE
static void saveCoverageTool(const char * appname, bool testfailed, bool installedTestCoverage)
{
#ifdef __COVERAGESCANNER__
+# if QT_CONFIG(testlib_selfcover)
+ __coveragescanner_teststate(QTestLog::failCount() > 0 ? "FAILED" :
+ QTestLog::passCount() > 0 ? "PASSED" : "SKIPPED");
+# else
if (!installedTestCoverage)
return;
// install again to make sure the filename is correct.
@@ -84,6 +88,7 @@ static void saveCoverageTool(const char * appname, bool testfailed, bool install
__coveragescanner_testname("");
__coveragescanner_clear();
unsetenv("QT_TESTCOCOON_ACTIVE");
+# endif // testlib_selfcover
#else
Q_UNUSED(appname);
Q_UNUSED(testfailed);
@@ -214,7 +219,7 @@ namespace QTest {
}
if (type != QtFatalMsg) {
- if (counter.load() <= 0)
+ if (counter.loadRelaxed() <= 0)
return;
if (!counter.deref()) {
diff --git a/src/testlib/qxmltestlogger_p.h b/src/testlib/qxmltestlogger_p.h
index b85742f939..04ed57d587 100644
--- a/src/testlib/qxmltestlogger_p.h
+++ b/src/testlib/qxmltestlogger_p.h
@@ -71,11 +71,11 @@ public:
void leaveTestFunction() override;
void addIncident(IncidentTypes type, const char *description,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
void addBenchmarkResult(const QBenchmarkResult &result) override;
void addMessage(MessageTypes type, const QString &message,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
static int xmlCdata(QTestCharBuffer *dest, char const* src);
static int xmlQuote(QTestCharBuffer *dest, char const* src);
diff --git a/src/testlib/qxunittestlogger_p.h b/src/testlib/qxunittestlogger_p.h
index 8fb01fbe61..48f07ddcf2 100644
--- a/src/testlib/qxunittestlogger_p.h
+++ b/src/testlib/qxunittestlogger_p.h
@@ -71,12 +71,12 @@ class QXunitTestLogger : public QAbstractTestLogger
void leaveTestFunction() override;
void addIncident(IncidentTypes type, const char *description,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
void addBenchmarkResult(const QBenchmarkResult &result) override;
void addTag(QTestElement* element);
void addMessage(MessageTypes type, const QString &message,
- const char *file = 0, int line = 0) override;
+ const char *file = nullptr, int line = 0) override;
private:
QTestElement *listOfTestcases;
diff --git a/src/testlib/selfcover.pri b/src/testlib/selfcover.pri
new file mode 100644
index 0000000000..7de50ba6e6
--- /dev/null
+++ b/src/testlib/selfcover.pri
@@ -0,0 +1,28 @@
+# Configuration for testlib and its tests, to instrument with
+# FrogLogic's Squish CoCo (cf. testcocoon.prf, which handles similar
+# for general code; but testlib needs special handling).
+
+# Only for use when feature testlib_selfcover is enabled:
+!qtConfig(testlib_selfcover): return()
+
+# This enables verification that testlib itself is adequately tested,
+# as a grounds for trusting that testing with it is useful.
+# Exclude all non-testlib source from coverage instrumentation:
+COVERAGE_OPTIONS = --cs-exclude-file-abs-wildcard=$$QT_SOURCE_TREE/*
+COVERAGE_OPTIONS += --cs-include-file-abs-wildcard=*/src/testlib/*
+COVERAGE_OPTIONS += --cs-mcc # enable Multiple Condition Coverage
+COVERAGE_OPTIONS += --cs-mcdc # enable Multiple Condition / Decision Coverage
+# (recommended for ISO 26262 ASIL A, B and C -- highly recommended for ASIL D)
+# https://doc.froglogic.com/squish-coco/4.1/codecoverage.html#sec%3Amcdc
+
+QMAKE_CFLAGS += $$COVERAGE_OPTIONS
+QMAKE_CXXFLAGS += $$COVERAGE_OPTIONS
+QMAKE_LFLAGS += $$COVERAGE_OPTIONS
+
+# FIXME: relies on QMAKE_* being just the command-names, with no path prefix
+QMAKE_CC = cs$$QMAKE_CC
+QMAKE_CXX = cs$$QMAKE_CXX
+QMAKE_LINK = cs$$QMAKE_LINK
+QMAKE_LINK_SHLIB = cs$$QMAKE_LINK_SHLIB
+QMAKE_AR = cs$$QMAKE_AR
+QMAKE_LIB = cs$$QMAKE_LIB
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index 34bb581e02..530bc6b425 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -17,7 +17,6 @@ HEADERS = \
qbenchmark_p.h \
qbenchmarkmeasurement_p.h \
qbenchmarktimemeasurers_p.h \
- qbenchmarkvalgrind_p.h \
qbenchmarkevent_p.h \
qbenchmarkperfevents_p.h \
qbenchmarkmetric.h \
@@ -70,7 +69,6 @@ SOURCES = \
qabstracttestlogger.cpp \
qbenchmark.cpp \
qbenchmarkmeasurement.cpp \
- qbenchmarkvalgrind.cpp \
qbenchmarkevent.cpp \
qbenchmarkperfevents.cpp \
qbenchmarkmetric.cpp \
@@ -92,6 +90,13 @@ qtConfig(itemmodeltester) {
qabstractitemmodeltester.cpp
}
+qtConfig(valgrind) {
+ HEADERS += \
+ qbenchmarkvalgrind_p.h
+ SOURCES += \
+ qbenchmarkvalgrind.cpp
+}
+
DEFINES *= QT_NO_CAST_TO_ASCII \
QT_NO_CAST_FROM_ASCII \
QT_NO_FOREACH \
@@ -146,4 +151,5 @@ mac {
!qtHaveModule(network): HEADERSCLEAN_EXCLUDE += qtest_network.h
+include(selfcover.pri)
load(qt_module)
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index 6a6f8034e3..10bbd59bfb 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
@@ -52,6 +52,21 @@
#define QT_POPEN_READ "r"
#endif
+class ActionTimer
+{
+ qint64 started;
+public:
+ ActionTimer() = default;
+ void start()
+ {
+ started = QDateTime::currentMSecsSinceEpoch();
+ }
+ int elapsed()
+ {
+ return int(QDateTime::currentMSecsSinceEpoch() - started);
+ }
+};
+
static const bool mustReadOutputAnyway = true; // pclose seems to return the wrong error code unless we read the output
void deleteRecursively(const QString &dirName)
@@ -103,7 +118,6 @@ struct Options
, timing(false)
, generateAssetsFileList(true)
, build(true)
- , gradle(false)
, auxMode(false)
, deploymentMechanism(Bundled)
, releasePackage(false)
@@ -135,16 +149,14 @@ struct Options
bool timing;
bool generateAssetsFileList;
bool build;
- bool gradle;
bool auxMode;
bool stripLibraries = true;
- QTime timer;
+ ActionTimer timer;
// External tools
QString sdkPath;
QString sdkBuildToolsVersion;
QString ndkPath;
- QString antTool;
QString jdkPath;
// Build paths
@@ -197,6 +209,7 @@ struct Options
bool sectionsOnly;
bool protectedAuthenticationPath;
bool jarSigner;
+ QString apkPath;
// Gdbserver
TriState gdbServer;
@@ -354,13 +367,6 @@ Options parseOptions()
options.helpRequested = true;
} else if (argument.compare(QLatin1String("--verbose"), Qt::CaseInsensitive) == 0) {
options.verbose = true;
- } else if (argument.compare(QLatin1String("--gradle"), Qt::CaseInsensitive) == 0) {
- options.gradle = true;
- } else if (argument.compare(QLatin1String("--ant"), Qt::CaseInsensitive) == 0) {
- if (i + 1 == arguments.size())
- options.helpRequested = true;
- else
- options.antTool = arguments.at(++i);
} else if (argument.compare(QLatin1String("--deployment"), Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size()) {
options.helpRequested = true;
@@ -391,6 +397,11 @@ Options parseOptions()
options.helpRequested = true;
else
options.jdkPath = arguments.at(++i);
+ } else if (argument.compare(QLatin1String("--apk"), Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ options.helpRequested = true;
+ else
+ options.apkPath = arguments.at(++i);
} else if (argument.compare(QLatin1String("--sign"), Qt::CaseInsensitive) == 0) {
if (i + 2 >= arguments.size()) {
options.helpRequested = true;
@@ -500,9 +511,6 @@ void printHelp()
" --android-platform <platform>: Builds against the given android\n"
" platform. By default, the highest available version will be\n"
" used.\n"
- " --gradle. Use gradle instead of ant to create and install the apk.\n"
- " --ant <path/to/ant>: If unspecified, ant from the PATH will be\n"
- " used.\n"
" --release: Builds a package ready for release. By default, the\n"
" package will be signed with a debug key.\n"
" --sign <url/to/keystore> <alias>: Signs the package with the\n"
@@ -542,6 +550,7 @@ void printHelp()
" dependencies into the build directory and update the XML templates.\n"
" The project will not be built or installed.\n"
" --no-strip: Do not strip debug symbols from libraries.\n"
+ " --apk <path/where/to/copy/the/apk>: Path where to copy the built apk.\n"
" --help: Displays this information.\n\n",
qPrintable(QCoreApplication::arguments().at(0))
);
@@ -1009,16 +1018,13 @@ bool copyAndroidTemplate(const Options &options)
if (options.verbose)
fprintf(stdout, "Copying Android package template.\n");
- if (options.gradle && !copyGradleTemplate(options))
+ if (!copyGradleTemplate(options))
return false;
if (!copyAndroidTemplate(options, QLatin1String("/src/android/templates")))
return false;
- if (options.gradle)
- return true;
-
- return copyAndroidTemplate(options, QLatin1String("/src/android/java"));
+ return true;
}
bool copyAndroidSources(const Options &options)
@@ -1270,36 +1276,6 @@ bool updateStringsXml(const Options &options)
if (!updateFile(fileName, replacements))
return false;
- if (options.gradle)
- return true;
-
- // ant can't (easily) build multiple res folders,
- // so we need to replace the "<!-- %%INSERT_STRINGS -->" placeholder
- // from the main res folder
- QFile stringsXml(fileName);
- if (!stringsXml.open(QIODevice::ReadOnly)) {
- fprintf(stderr, "Cannot open %s for reading.\n", qPrintable(fileName));
- return false;
- }
-
- QXmlStreamReader reader(&stringsXml);
- while (!reader.atEnd()) {
- reader.readNext();
- if (reader.isStartElement() &&
- reader.name() == QLatin1String("string") &&
- reader.attributes().hasAttribute(QLatin1String("name")) &&
- reader.attributes().value(QLatin1String("name")) == QLatin1String("app_name")) {
- return true;
- }
- }
-
- replacements.clear();
- replacements[QStringLiteral("<!-- %%INSERT_STRINGS -->")] = QString::fromLatin1("<string name=\"app_name\">%1</string>\n")
- .arg(QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1));
-
- if (!updateFile(fileName, replacements))
- return false;
-
return true;
}
@@ -1400,8 +1376,8 @@ bool updateAndroidManifest(Options &options)
options.packageName = reader.attributes().value(QLatin1String("package")).toString();
} else if (reader.name() == QLatin1String("uses-sdk")) {
if (reader.attributes().hasAttribute(QLatin1String("android:minSdkVersion")))
- if (reader.attributes().value(QLatin1String("android:minSdkVersion")).toInt() < 16) {
- fprintf(stderr, "Invalid minSdkVersion version, minSdkVersion must be >= 16\n");
+ if (reader.attributes().value(QLatin1String("android:minSdkVersion")).toInt() < 21) {
+ fprintf(stderr, "Invalid minSdkVersion version, minSdkVersion must be >= 21\n");
return false;
}
} else if ((reader.name() == QLatin1String("application") ||
@@ -1730,6 +1706,11 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
.arg(shellQuote(rootPath))
.arg(importPaths.join(QLatin1Char(' ')));
+ if (options->verbose) {
+ fprintf(stdout, "Running qmlimportscanner with the following command: %s\n",
+ qmlImportScanner.toLocal8Bit().constData());
+ }
+
FILE *qmlImportScannerCommand = popen(qmlImportScanner.toLocal8Bit().constData(), QT_POPEN_READ);
if (qmlImportScannerCommand == 0) {
fprintf(stderr, "Couldn't run qmlimportscanner.\n");
@@ -2200,64 +2181,6 @@ QString findInPath(const QString &fileName)
return QString();
}
-bool buildAntProject(const Options &options)
-{
- if (options.verbose)
- fprintf(stdout, "Building Android package using ant.\n");
-
- QString antTool = options.antTool;
- if (antTool.isEmpty()) {
-#if defined(Q_OS_WIN32)
- antTool = findInPath(QLatin1String("ant.bat"));
-#else
- antTool = findInPath(QLatin1String("ant"));
-#endif
- }
-
- if (antTool.isEmpty()) {
- fprintf(stderr, "Cannot find ant in PATH. Please use --ant option to pass in the correct path.\n");
- return false;
- }
-
- if (options.verbose)
- fprintf(stdout, "Using ant: %s\n", qPrintable(antTool));
-
- QString oldPath = QDir::currentPath();
- if (!QDir::setCurrent(options.outputDirectory)) {
- fprintf(stderr, "Cannot current path to %s\n", qPrintable(options.outputDirectory));
- return false;
- }
-
- QString ant = QString::fromLatin1("%1 %2").arg(shellQuote(antTool)).arg(options.releasePackage ? QLatin1String(" release") : QLatin1String(" debug"));
-
- FILE *antCommand = openProcess(ant);
- if (antCommand == 0) {
- fprintf(stderr, "Cannot run ant command: %s\n.", qPrintable(ant));
- return false;
- }
-
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), antCommand) != 0) {
- fprintf(stdout, "%s", buffer);
- fflush(stdout);
- }
-
- int errorCode = pclose(antCommand);
- if (errorCode != 0) {
- fprintf(stderr, "Building the android package failed!\n");
- if (!options.verbose)
- fprintf(stderr, " -- For more information, run this command with --verbose.\n");
- return false;
- }
-
- if (!QDir::setCurrent(oldPath)) {
- fprintf(stderr, "Cannot change back to old path: %s\n", qPrintable(oldPath));
- return false;
- }
-
- return true;
-}
-
typedef QMap<QByteArray, QByteArray> GradleProperties;
static GradleProperties readGradleProperties(const QString &path)
@@ -2315,7 +2238,7 @@ static bool mergeGradleProperties(const QString &path, GradleProperties properti
return true;
}
-bool buildGradleProject(const Options &options)
+bool buildAndroidProject(const Options &options)
{
GradleProperties localProperties;
localProperties["sdk.dir"] = options.sdkPath.toLocal8Bit();
@@ -2383,12 +2306,6 @@ bool buildGradleProject(const Options &options)
return true;
}
-bool buildAndroidProject(const Options &options)
-{
- return options.gradle ? buildGradleProject(options)
- : buildAntProject(options);
-}
-
bool uninstallApk(const Options &options)
{
if (options.verbose)
@@ -2425,15 +2342,11 @@ enum PackageType {
QString apkPath(const Options &options, PackageType pt)
{
QString path(options.outputDirectory);
- if (options.gradle) {
- path += QLatin1String("/build/outputs/apk/");
- QString buildType(options.releasePackage ? QLatin1String("release/") : QLatin1String("debug/"));
- if (QDir(path + buildType).exists())
- path += buildType;
- path += QDir(options.outputDirectory).dirName() + QLatin1Char('-');
- } else {
- path += QLatin1String("/bin/QtApp-");
- }
+ path += QLatin1String("/build/outputs/apk/");
+ QString buildType(options.releasePackage ? QLatin1String("release/") : QLatin1String("debug/"));
+ if (QDir(path + buildType).exists())
+ path += buildType;
+ path += QDir(options.outputDirectory).dirName() + QLatin1Char('-');
if (options.releasePackage) {
path += QLatin1String("release-");
if (pt == UnsignedAPK)
@@ -2483,6 +2396,14 @@ bool installApk(const Options &options)
return true;
}
+bool copyPackage(const Options &options)
+{
+ fflush(stdout);
+ auto from = apkPath(options, options.keyStore.isEmpty() ? UnsignedAPK : SignedAPK);
+ QFile::remove(options.apkPath);
+ return QFile::copy(from, options.apkPath);
+}
+
bool copyStdCpp(Options *options)
{
if (options->verbose)
@@ -2853,7 +2774,8 @@ enum ErrorCode
CannotSignPackage = 15,
CannotInstallApk = 16,
CannotGenerateAssetsFileList = 18,
- CannotCopyAndroidExtraResources = 19
+ CannotCopyAndroidExtraResources = 19,
+ CannotCopyApk = 20
};
int main(int argc, char *argv[])
@@ -2910,8 +2832,7 @@ int main(int argc, char *argv[])
}
if (options.build) {
- if (options.gradle)
- cleanAndroidFiles(options);
+ cleanAndroidFiles(options);
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %d ms: Cleaned Android file\n", options.timer.elapsed());
@@ -2985,9 +2906,6 @@ int main(int argc, char *argv[])
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %d ms: Updated files\n", options.timer.elapsed());
- if (!options.gradle && !createAndroidProject(options))
- return CannotCreateAndroidProject;
-
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %d ms: Created project\n", options.timer.elapsed());
@@ -3000,6 +2918,9 @@ int main(int argc, char *argv[])
if (!options.keyStore.isEmpty() && !signPackage(options))
return CannotSignPackage;
+ if (!options.apkPath.isEmpty() && !copyPackage(options))
+ return CannotCopyApk;
+
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %d ms: Signed package\n", options.timer.elapsed());
}
diff --git a/src/tools/androidtestrunner/androidtestrunner.pro b/src/tools/androidtestrunner/androidtestrunner.pro
new file mode 100644
index 0000000000..641d3e0003
--- /dev/null
+++ b/src/tools/androidtestrunner/androidtestrunner.pro
@@ -0,0 +1,13 @@
+option(host_build)
+CONFIG += console
+
+SOURCES += \
+ main.cpp
+
+# Required for declarations of popen/pclose on Windows
+windows: QMAKE_CXXFLAGS += -U__STRICT_ANSI__
+
+DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
+DEFINES += QT_NO_FOREACH
+
+load(qt_app)
diff --git a/src/tools/androidtestrunner/main.cpp b/src/tools/androidtestrunner/main.cpp
new file mode 100644
index 0000000000..bb69b7b914
--- /dev/null
+++ b/src/tools/androidtestrunner/main.cpp
@@ -0,0 +1,490 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 BogDan Vatra <bogdan@kde.org>
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QCoreApplication>
+#include <QDir>
+#include <QHash>
+#include <QRegExp>
+#include <QSystemSemaphore>
+#include <QXmlStreamReader>
+
+#include <algorithm>
+#include <chrono>
+#include <functional>
+#include <thread>
+
+#ifdef Q_CC_MSVC
+#define popen _popen
+#define QT_POPEN_READ "rb"
+#define pclose _pclose
+#else
+#define QT_POPEN_READ "r"
+#endif
+
+struct Options
+{
+ bool helpRequested = false;
+ bool verbose = false;
+ std::chrono::seconds timeout{300}; // 5minutes
+ QString androidDeployQtCommand;
+ QString buildPath;
+ QString adbCommand{QStringLiteral("adb")};
+ QString makeCommand;
+ QString package;
+ QString activity;
+ QStringList testArgsList;
+ QHash<QString, QString> outFiles;
+ QString testArgs;
+ QString apkPath;
+ QHash<QString, std::function<bool(const QByteArray &)>> checkFiles = {
+ {QStringLiteral("txt"), [](const QByteArray &data) -> bool {
+ return data.indexOf("\nFAIL! : ") < 0;
+ }},
+ {QStringLiteral("csv"), [](const QByteArray &/*data*/) -> bool {
+ // It seems csv is broken
+ return true;
+ }},
+ {QStringLiteral("xml"), [](const QByteArray &data) -> bool {
+ QXmlStreamReader reader{data};
+ while (!reader.atEnd()) {
+ reader.readNext();
+ if (reader.isStartElement() && reader.name() == QStringLiteral("Incident") &&
+ reader.attributes().value(QStringLiteral("type")).toString() == QStringLiteral("fail")) {
+ return false;
+ }
+ }
+ return true;
+ }},
+ {QStringLiteral("lightxml"), [](const QByteArray &data) -> bool {
+ return data.indexOf("\n<Incident type=\"fail\" ") < 0;
+ }},
+ {QStringLiteral("xunitxml"), [](const QByteArray &data) -> bool {
+ QXmlStreamReader reader{data};
+ while (!reader.atEnd()) {
+ reader.readNext();
+ if (reader.isStartElement() && reader.name() == QStringLiteral("testcase") &&
+ reader.attributes().value(QStringLiteral("result")).toString() == QStringLiteral("fail")) {
+ return false;
+ }
+ }
+ return true;
+ }},
+ {QStringLiteral("teamcity"), [](const QByteArray &data) -> bool {
+ return data.indexOf("' message='Failure! |[Loc: ") < 0;
+ }},
+ {QStringLiteral("tap"), [](const QByteArray &data) -> bool {
+ return data.indexOf("\nnot ok ") < 0;
+ }},
+ };
+};
+
+static Options g_options;
+
+static bool execCommand(const QString &command, QByteArray *output = nullptr, bool verbose = false)
+{
+ if (verbose)
+ fprintf(stdout, "Execute %s\n", command.toUtf8().constData());
+ FILE *process = popen(command.toUtf8().constData(), QT_POPEN_READ);
+
+ if (!process) {
+ fprintf(stderr, "Cannot execute command %s", qPrintable(command));
+ return false;
+ }
+ char buffer[512];
+ while (fgets(buffer, sizeof(buffer), process)) {
+ if (output)
+ output->append(buffer);
+ if (verbose)
+ fprintf(stdout, "%s", buffer);
+ }
+ return pclose(process) == 0;
+}
+
+// Copy-pasted from qmake/library/ioutil.cpp
+inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16])
+{
+ for (int x = arg.length() - 1; x >= 0; --x) {
+ ushort c = arg.unicode()[x].unicode();
+ if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7))))
+ return true;
+ }
+ return false;
+}
+
+static QString shellQuoteUnix(const QString &arg)
+{
+ // Chars that should be quoted (TM). This includes:
+ static const uchar iqm[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8,
+ 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78
+ }; // 0-32 \'"$`<>|;&(){}*?#!~[]
+
+ if (!arg.length())
+ return QStringLiteral("\"\"");
+
+ QString ret(arg);
+ if (hasSpecialChars(ret, iqm)) {
+ ret.replace(QLatin1Char('\''), QStringLiteral("'\\''"));
+ ret.prepend(QLatin1Char('\''));
+ ret.append(QLatin1Char('\''));
+ }
+ return ret;
+}
+
+static QString shellQuoteWin(const QString &arg)
+{
+ // Chars that should be quoted (TM). This includes:
+ // - control chars & space
+ // - the shell meta chars "&()<>^|
+ // - the potential separators ,;=
+ static const uchar iqm[] = {
+ 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
+ };
+
+ if (!arg.length())
+ return QStringLiteral("\"\"");
+
+ QString ret(arg);
+ if (hasSpecialChars(ret, iqm)) {
+ // Quotes are escaped and their preceding backslashes are doubled.
+ // It's impossible to escape anything inside a quoted string on cmd
+ // level, so the outer quoting must be "suspended".
+ ret.replace(QRegExp(QStringLiteral("(\\\\*)\"")), QStringLiteral("\"\\1\\1\\^\"\""));
+ // The argument must not end with a \ since this would be interpreted
+ // as escaping the quote -- rather put the \ behind the quote: e.g.
+ // rather use "foo"\ than "foo\"
+ int i = ret.length();
+ while (i > 0 && ret.at(i - 1) == QLatin1Char('\\'))
+ --i;
+ ret.insert(i, QLatin1Char('"'));
+ ret.prepend(QLatin1Char('"'));
+ }
+ return ret;
+}
+
+static QString shellQuote(const QString &arg)
+{
+ if (QDir::separator() == QLatin1Char('\\'))
+ return shellQuoteWin(arg);
+ else
+ return shellQuoteUnix(arg);
+}
+
+static bool parseOptions()
+{
+ QStringList arguments = QCoreApplication::arguments();
+ int i = 1;
+ for (; i < arguments.size(); ++i) {
+ const QString &argument = arguments.at(i);
+ if (argument.compare(QStringLiteral("--androiddeployqt"), Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ g_options.helpRequested = true;
+ else
+ g_options.androidDeployQtCommand = arguments.at(++i).trimmed();
+ } else if (argument.compare(QStringLiteral("--adb"), Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ g_options.helpRequested = true;
+ else
+ g_options.adbCommand = arguments.at(++i);
+ } else if (argument.compare(QStringLiteral("--path"), Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ g_options.helpRequested = true;
+ else
+ g_options.buildPath = arguments.at(++i);
+ } else if (argument.compare(QStringLiteral("--make"), Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ g_options.helpRequested = true;
+ else
+ g_options.makeCommand = arguments.at(++i);
+ } else if (argument.compare(QStringLiteral("--apk"), Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ g_options.helpRequested = true;
+ else
+ g_options.apkPath = arguments.at(++i);
+ } else if (argument.compare(QStringLiteral("--activity"), Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ g_options.helpRequested = true;
+ else
+ g_options.activity = arguments.at(++i);
+ } else if (argument.compare(QStringLiteral("--timeout"), Qt::CaseInsensitive) == 0) {
+ if (i + 1 == arguments.size())
+ g_options.helpRequested = true;
+ else
+ g_options.timeout = std::chrono::seconds{arguments.at(++i).toInt()};
+ } else if (argument.compare(QStringLiteral("--help"), Qt::CaseInsensitive) == 0) {
+ g_options.helpRequested = true;
+ } else if (argument.compare(QStringLiteral("--verbose"), Qt::CaseInsensitive) == 0) {
+ g_options.verbose = true;
+ } else if (argument.compare(QStringLiteral("--"), Qt::CaseInsensitive) == 0) {
+ ++i;
+ break;
+ } else {
+ g_options.testArgsList << arguments.at(i);
+ }
+ }
+ for (;i < arguments.size(); ++i)
+ g_options.testArgsList << arguments.at(i);
+
+ if (g_options.helpRequested || g_options.androidDeployQtCommand.isEmpty() || g_options.buildPath.isEmpty())
+ return false;
+
+ QString serial = qEnvironmentVariable("ANDROID_DEVICE_SERIAL");
+ if (!serial.isEmpty())
+ g_options.adbCommand += QStringLiteral(" -s %1").arg(serial);
+ return true;
+}
+
+static void printHelp()
+{// "012345678901234567890123456789012345678901234567890123456789012345678901"
+ fprintf(stderr, "Syntax: %s <options> -- [TESTARGS] \n"
+ "\n"
+ " Creates an Android package in a temp directory <destination> and\n"
+ " runs it on the default emulator/device or on the one specified by\n"
+ " \"ANDROID_DEVICE_SERIAL\" environment variable.\n\n"
+ " Mandatory arguments:\n"
+ " --androiddeployqt <androiddeployqt cmd>: The androiddeployqt:\n"
+ " path including its additional arguments.\n"
+ " --path <path>: The path where androiddeployqt will build the .apk.\n"
+ " Optional arguments:\n"
+ " --adb <adb cmd>: The Android ADB command. If missing the one from\n"
+ " $PATH will be used.\n"
+ " --activity <acitvity>: The Activity to run. If missing the first\n"
+ " activity from AndroidManifest.qml file will be used.\n"
+ " --timout <seconds>: Timeout to run the test.\n"
+ " Default is 5 minutes.\n"
+ " --make <make cmd>: make command, needed to install the qt library.\n"
+ " If make is missing make sure the --path is set.\n"
+ " --apk <apk path>: If the apk is specified and if exists, we'll skip\n"
+ " the package building.\n"
+ " -- arguments that will be passed to the test application.\n"
+ " --verbose: Prints out information during processing.\n"
+ " --help: Displays this information.\n\n",
+ qPrintable(QCoreApplication::arguments().at(0))
+ );
+}
+
+static QString packageNameFromAndroidManifest(const QString &androidManifestPath)
+{
+ QFile androidManifestXml(androidManifestPath);
+ if (androidManifestXml.open(QIODevice::ReadOnly)) {
+ QXmlStreamReader reader(&androidManifestXml);
+ while (!reader.atEnd()) {
+ reader.readNext();
+ if (reader.isStartElement() && reader.name() == QStringLiteral("manifest"))
+ return reader.attributes().value(QStringLiteral("package")).toString();
+ }
+ }
+ return {};
+}
+
+static QString activityFromAndroidManifest(const QString &androidManifestPath)
+{
+ QFile androidManifestXml(androidManifestPath);
+ if (androidManifestXml.open(QIODevice::ReadOnly)) {
+ QXmlStreamReader reader(&androidManifestXml);
+ while (!reader.atEnd()) {
+ reader.readNext();
+ if (reader.isStartElement() && reader.name() == QStringLiteral("activity"))
+ return reader.attributes().value(QStringLiteral("android:name")).toString();
+ }
+ }
+ return {};
+}
+
+static void setOutputFile(QString file, QString format)
+{
+ if (file.isEmpty())
+ file = QStringLiteral("-");
+ if (format.isEmpty())
+ format = QStringLiteral("txt");
+
+ g_options.outFiles[format] = file;
+}
+
+static bool parseTestArgs()
+{
+ QRegExp newLoggingFormat{QStringLiteral("(.*),(txt|csv|xunitxml|xml|lightxml|teamcity|tap)")};
+ QRegExp oldFormats{QStringLiteral("-(txt|csv|xunitxml|xml|lightxml|teamcity|tap)")};
+
+ QString file;
+ QString logType;
+ QString unhandledArgs;
+ for (int i = 0; i < g_options.testArgsList.size(); ++i) {
+ const QString &arg = g_options.testArgsList[i].trimmed();
+ if (arg == QStringLiteral("-o")) {
+ if (i >= g_options.testArgsList.size() - 1)
+ return false; // missing file argument
+
+ const auto &filePath = g_options.testArgsList[++i];
+ if (!newLoggingFormat.exactMatch(filePath)) {
+ file = filePath;
+ } else {
+ const auto capturedTexts = newLoggingFormat.capturedTexts();
+ setOutputFile(capturedTexts.at(1), capturedTexts.at(2));
+ }
+ } else if (oldFormats.exactMatch(arg)) {
+ logType = oldFormats.capturedTexts().at(1);
+ } else {
+ unhandledArgs += QStringLiteral(" %1").arg(arg);
+ }
+ }
+ if (g_options.outFiles.isEmpty() || !file.isEmpty() || !logType.isEmpty())
+ setOutputFile(file, logType);
+
+ for (const auto &format : g_options.outFiles.keys())
+ g_options.testArgs += QStringLiteral(" -o output.%1,%1").arg(format);
+
+ g_options.testArgs += unhandledArgs;
+ g_options.testArgs = QStringLiteral("shell am start -e applicationArguments \"'%1'\" -n %2/%3").arg(shellQuote(g_options.testArgs.trimmed()),
+ g_options.package,
+ g_options.activity);
+ return true;
+}
+
+static bool isRunning() {
+ QByteArray output;
+ if (!execCommand(QStringLiteral("%1 shell \"ps | grep ' %2'\"").arg(g_options.adbCommand,
+ shellQuote(g_options.package)), &output)) {
+
+ return false;
+ }
+ return output.indexOf(" " + g_options.package.toUtf8()) > -1;
+}
+
+static bool waitToFinish()
+{
+ using clock = std::chrono::system_clock;
+ auto start = clock::now();
+ // wait to start
+ while (!isRunning()) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ if ((clock::now() - start) > std::chrono::seconds{10})
+ return false;
+ }
+
+ // Wait to finish
+ while (isRunning()) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(250));
+ if ((clock::now() - start) > g_options.timeout)
+ return false;
+ }
+ return true;
+}
+
+
+static bool pullFiles()
+{
+ bool ret = true;
+ for (auto it = g_options.outFiles.constBegin(); it != g_options.outFiles.end(); ++it) {
+ QByteArray output;
+ if (!execCommand(QStringLiteral("%1 shell run-as %2 cat files/output.%3")
+ .arg(g_options.adbCommand, g_options.package, it.key()), &output)) {
+ return false;
+ }
+ auto checkerIt = g_options.checkFiles.find(it.key());
+ ret &= checkerIt != g_options.checkFiles.end() && checkerIt.value()(output);
+ if (it.value() == QStringLiteral("-")){
+ fprintf(stdout, "%s", output.constData());
+ fflush(stdout);
+ } else {
+ QFile out{it.value()};
+ if (!out.open(QIODevice::WriteOnly))
+ return false;
+ out.write(output);
+ }
+ }
+ return ret;
+}
+
+struct RunnerLocker
+{
+ RunnerLocker()
+ {
+ runner.acquire();
+ }
+ ~RunnerLocker()
+ {
+ runner.release();
+ }
+ QSystemSemaphore runner{QStringLiteral("androidtestrunner"), 1, QSystemSemaphore::Open};
+};
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication a(argc, argv);
+ if (!parseOptions()) {
+ printHelp();
+ return 1;
+ }
+
+ RunnerLocker lock; // do not install or run packages while another test is running
+ if (!g_options.apkPath.isEmpty() && QFile::exists(g_options.apkPath)) {
+ if (!execCommand(QStringLiteral("%1 install -r %2")
+ .arg(g_options.adbCommand, g_options.apkPath), nullptr, g_options.verbose)) {
+ return 1;
+ }
+ } else {
+ if (!g_options.makeCommand.isEmpty()) {
+ // we need to run make INSTALL_ROOT=path install to install the application file(s) first
+ if (!execCommand(QStringLiteral("%1 INSTALL_ROOT=%2 install")
+ .arg(g_options.makeCommand, g_options.buildPath), nullptr, g_options.verbose)) {
+ return 1;
+ }
+ }
+
+ // Run androiddeployqt
+ static auto verbose = g_options.verbose ? QStringLiteral("--verbose") : QStringLiteral();
+ if (!execCommand(QStringLiteral("%1 %3 --reinstall --output %2 --apk %4").arg(g_options.androidDeployQtCommand,
+ g_options.buildPath,
+ verbose,
+ g_options.apkPath), nullptr, true)) {
+ return 1;
+ }
+ }
+
+ QString manifest = g_options.buildPath + QStringLiteral("/AndroidManifest.xml");
+ g_options.package = packageNameFromAndroidManifest(manifest);
+ if (g_options.activity.isEmpty())
+ g_options.activity = activityFromAndroidManifest(manifest);
+
+ // parseTestArgs depends on g_options.package
+ if (!parseTestArgs())
+ return 1;
+
+ // start the tests
+ bool res = execCommand(QStringLiteral("%1 %2").arg(g_options.adbCommand, g_options.testArgs),
+ nullptr, g_options.verbose) && waitToFinish();
+ if (res)
+ res &= pullFiles();
+ res &= execCommand(QStringLiteral("%1 uninstall %2").arg(g_options.adbCommand, g_options.package),
+ nullptr, g_options.verbose);
+ fflush(stdout);
+ return res ? 0 : 1;
+}
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index 83e44ff9a4..8598fc2721 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -19,8 +19,6 @@ DEFINES += \
QT_NO_FOREACH \
QT_NO_CAST_FROM_ASCII
-DEFINES -= QT_EVAL
-
SOURCES += \
../../corelib/codecs/qlatincodec.cpp \
../../corelib/codecs/qtextcodec.cpp \
@@ -44,6 +42,7 @@ SOURCES += \
../../corelib/io/qfsfileengine.cpp \
../../corelib/io/qfsfileengine_iterator.cpp \
../../corelib/io/qiodevice.cpp \
+ ../../corelib/io/qipaddress.cpp \
../../corelib/io/qfiledevice.cpp \
../../corelib/io/qresource.cpp \
../../corelib/io/qtemporarydir.cpp \
@@ -52,11 +51,17 @@ SOURCES += \
../../corelib/io/qstandardpaths.cpp \
../../corelib/io/qloggingcategory.cpp \
../../corelib/io/qloggingregistry.cpp \
+ ../../corelib/io/qurl.cpp \
+ ../../corelib/io/qurlidna.cpp \
+ ../../corelib/io/qurlquery.cpp \
+ ../../corelib/io/qurlrecode.cpp \
../../corelib/kernel/qcoreapplication.cpp \
../../corelib/kernel/qcoreglobaldata.cpp \
../../corelib/kernel/qmetatype.cpp \
../../corelib/kernel/qvariant.cpp \
../../corelib/kernel/qsystemerror.cpp \
+ ../../corelib/kernel/qsharedmemory.cpp \
+ ../../corelib/kernel/qsystemsemaphore.cpp \
../../corelib/plugin/quuid.cpp \
../../corelib/serialization/qdatastream.cpp \
../../corelib/serialization/qjson.cpp \
@@ -69,6 +74,7 @@ SOURCES += \
../../corelib/serialization/qtextstream.cpp \
../../corelib/serialization/qxmlutils.cpp \
../../corelib/serialization/qxmlstream.cpp \
+ ../../corelib/time/qdatetime.cpp \
../../corelib/tools/qbitarray.cpp \
../../corelib/tools/qbytearray.cpp \
../../corelib/tools/qarraydata.cpp \
@@ -76,7 +82,6 @@ SOURCES += \
../../corelib/tools/qcommandlineparser.cpp \
../../corelib/tools/qcommandlineoption.cpp \
../../corelib/tools/qcryptographichash.cpp \
- ../../corelib/tools/qdatetime.cpp \
../../corelib/tools/qhash.cpp \
../../corelib/tools/qlist.cpp \
../../corelib/tools/qlinkedlist.cpp \
@@ -93,12 +98,19 @@ SOURCES += \
../../corelib/tools/qstringbuilder.cpp \
../../corelib/tools/qstring_compat.cpp \
../../corelib/tools/qstringlist.cpp \
+ ../../corelib/tools/qstringview.cpp \
../../corelib/tools/qversionnumber.cpp \
../../corelib/tools/qvsnprintf.cpp \
../../xml/dom/qdom.cpp \
../../xml/sax/qxml.cpp
unix:SOURCES += ../../corelib/kernel/qcore_unix.cpp \
+ ../../corelib/kernel/qsharedmemory_posix.cpp \
+ ../../corelib/kernel/qsharedmemory_systemv.cpp \
+ ../../corelib/kernel/qsharedmemory_unix.cpp \
+ ../../corelib/kernel/qsystemsemaphore_posix.cpp \
+ ../../corelib/kernel/qsystemsemaphore_systemv.cpp \
+ ../../corelib/kernel/qsystemsemaphore_unix.cpp \
../../corelib/io/qfilesystemengine_unix.cpp \
../../corelib/io/qfilesystemiterator_unix.cpp \
../../corelib/io/qfsfileengine_unix.cpp
@@ -108,12 +120,18 @@ win32:SOURCES += ../../corelib/global/qoperatingsystemversion_win.cpp \
../../corelib/io/qfilesystemiterator_win.cpp \
../../corelib/io/qfsfileengine_win.cpp \
../../corelib/kernel/qcoreapplication_win.cpp \
+ ../../corelib/kernel/qsharedmemory_win.cpp \
+ ../../corelib/kernel/qsystemsemaphore_win.cpp \
../../corelib/plugin/qsystemlibrary.cpp \
mac {
SOURCES += \
../../corelib/kernel/qcoreapplication_mac.cpp \
- ../../corelib/kernel/qcore_mac.cpp
+ ../../corelib/kernel/qcore_mac.cpp \
+ ../../corelib/io/qfilesystemengine_unix.cpp \
+ ../../corelib/io/qfilesystemiterator_unix.cpp \
+ ../../corelib/io/qfsfileengine_unix.cpp
+
OBJECTIVE_SOURCES += \
../../corelib/global/qoperatingsystemversion_darwin.mm \
../../corelib/kernel/qcore_mac_objc.mm \
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 12ffd6ae95..41d0bbf2a1 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -619,7 +619,7 @@ void Generator::generateCode()
fprintf(out, "// a) You are using a NOTIFY signal that does not exist. Fix it.\n");
fprintf(out, "// b) You are using a NOTIFY signal that does exist (in a parent class) but has a non-empty parameter list. This is a moc limitation.\n");
fprintf(out, "Q_DECL_UNUSED static void checkNotifySignalValidity_%s(%s *t) {\n", qualifiedClassNameIdentifier.constData(), cdef->qualified.constData());
- for (const QByteArray &nonClassSignal : cdef->nonClassSignalList)
+ for (const QByteArray &nonClassSignal : qAsConst(cdef->nonClassSignalList))
fprintf(out, " t->%s();\n", nonClassSignal.constData());
fprintf(out, "}\n");
}
@@ -1549,16 +1549,16 @@ void Generator::generateSignal(FunctionDef *def,int index)
fprintf(out, "nullptr");
} else {
if (def->returnTypeIsVolatile)
- fprintf(out, "const_cast<void*>(reinterpret_cast<const volatile void*>(&_t0))");
+ fprintf(out, "const_cast<void*>(reinterpret_cast<const volatile void*>(std::addressof(_t0)))");
else
- fprintf(out, "const_cast<void*>(reinterpret_cast<const void*>(&_t0))");
+ fprintf(out, "const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t0)))");
}
int i;
for (i = 1; i < offset; ++i)
if (i <= def->arguments.count() && def->arguments.at(i - 1).type.isVolatile)
- fprintf(out, ", const_cast<void*>(reinterpret_cast<const volatile void*>(&_t%d))", i);
+ fprintf(out, ", const_cast<void*>(reinterpret_cast<const volatile void*>(std::addressof(_t%d)))", i);
else
- fprintf(out, ", const_cast<void*>(reinterpret_cast<const void*>(&_t%d))", i);
+ fprintf(out, ", const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t%d)))", i);
fprintf(out, " };\n");
fprintf(out, " QMetaObject::activate(%s, &staticMetaObject, %d, _a);\n", thisPtr.constData(), index);
if (def->normalizedType != "void")
@@ -1652,6 +1652,12 @@ void Generator::generatePluginMetaData()
jsonObjectToCbor(&map, o);
}
+ if (!cdef->pluginData.uri.isEmpty()) {
+ dev.nextItem("\"URI\"");
+ cbor_encode_int(&map, int(QtPluginMetaDataKeys::URI));
+ cbor_encode_text_string(&map, cdef->pluginData.uri.constData(), cdef->pluginData.uri.size());
+ }
+
// Add -M args from the command line:
for (auto it = cdef->pluginData.metaArgs.cbegin(), end = cdef->pluginData.metaArgs.cend(); it != end; ++it) {
const QJsonArray &a = it.value();
diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h
index 134166580b..eae0353199 100644
--- a/src/tools/moc/generator.h
+++ b/src/tools/moc/generator.h
@@ -39,7 +39,7 @@ class Generator
ClassDef *cdef;
QVector<uint> meta_data;
public:
- Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = 0);
+ Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr);
void generateCode();
private:
bool registerableMetaType(const QByteArray &propertyType);
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 7272df4265..2f0ea633fa 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -159,6 +159,7 @@ Type Moc::parseType()
bool isVoid = false;
type.firstToken = lookup();
for (;;) {
+ skipCxxAttributes();
switch (next()) {
case SIGNED:
case UNSIGNED:
@@ -188,8 +189,11 @@ Type Moc::parseType()
}
break;
}
+
+ skipCxxAttributes();
test(ENUM) || test(CLASS) || test(STRUCT);
for(;;) {
+ skipCxxAttributes();
switch (next()) {
case IDENTIFIER:
// void mySlot(unsigned myArg)
@@ -281,6 +285,7 @@ bool Moc::parseEnum(EnumDef *def)
break;
next(IDENTIFIER);
def->values += lexem();
+ skipCxxAttributes();
} while (test(EQ) ? until(COMMA) : test(COMMA));
next(RBRACE);
if (isTypdefEnum) {
@@ -356,6 +361,15 @@ bool Moc::testFunctionAttribute(Token tok, FunctionDef *def)
return false;
}
+bool Moc::skipCxxAttributes()
+{
+ auto rewind = index;
+ if (test(LBRACK) && test(LBRACK) && until(RBRACK) && test(RBRACK))
+ return true;
+ index = rewind;
+ return false;
+}
+
bool Moc::testFunctionRevision(FunctionDef *def)
{
if (test(Q_REVISION_TOKEN)) {
@@ -381,7 +395,7 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
//skip modifiers and attributes
while (test(INLINE) || (test(STATIC) && (def->isStatic = true) == true) ||
(test(VIRTUAL) && (def->isVirtual = true) == true) //mark as virtual
- || testFunctionAttribute(def) || testFunctionRevision(def)) {}
+ || skipCxxAttributes() || testFunctionAttribute(def) || testFunctionRevision(def)) {}
bool templateFunction = (lookup() == TEMPLATE);
def->type = parseType();
if (def->type.name.isEmpty()) {
@@ -454,10 +468,11 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
until(RBRACE);
else if ((def->isAbstract = test(EQ)))
until(SEMIC);
+ else if (skipCxxAttributes())
+ until(SEMIC);
else
error();
}
-
if (scopedFunctionName) {
const QByteArray msg = "Function declaration " + def->name
+ " contains extra qualification. Ignoring as signal or slot.";
@@ -475,7 +490,7 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
//skip modifiers and attributes
while (test(EXPLICIT) || test(INLINE) || (test(STATIC) && (def->isStatic = true) == true) ||
(test(VIRTUAL) && (def->isVirtual = true) == true) //mark as virtual
- || testFunctionAttribute(def) || testFunctionRevision(def)) {}
+ || skipCxxAttributes() || testFunctionAttribute(def) || testFunctionRevision(def)) {}
bool tilde = test(TILDE);
def->type = parseType();
if (def->type.name.isEmpty())
@@ -565,6 +580,7 @@ void Moc::parse()
} else if (!test(SEMIC)) {
NamespaceDef def;
def.classname = nsName;
+ def.doGenerate = currentFilenames.size() <= 1;
next(LBRACE);
def.begin = index - 1;
@@ -572,25 +588,22 @@ void Moc::parse()
def.end = index;
index = def.begin + 1;
- const bool parseNamespace = currentFilenames.size() <= 1;
- if (parseNamespace) {
- for (int i = namespaceList.size() - 1; i >= 0; --i) {
- if (inNamespace(&namespaceList.at(i))) {
- def.qualified.prepend(namespaceList.at(i).classname + "::");
- }
- }
- for (const QByteArray &ns : nested) {
- NamespaceDef parentNs;
- parentNs.classname = ns;
- parentNs.qualified = def.qualified;
- def.qualified += ns + "::";
- parentNs.begin = def.begin;
- parentNs.end = def.end;
- namespaceList += parentNs;
+ for (int i = namespaceList.size() - 1; i >= 0; --i) {
+ if (inNamespace(&namespaceList.at(i))) {
+ def.qualified.prepend(namespaceList.at(i).classname + "::");
}
}
+ for (const QByteArray &ns : nested) {
+ NamespaceDef parentNs;
+ parentNs.classname = ns;
+ parentNs.qualified = def.qualified;
+ def.qualified += ns + "::";
+ parentNs.begin = def.begin;
+ parentNs.end = def.end;
+ namespaceList += parentNs;
+ }
- while (parseNamespace && inNamespace(&def) && hasNext()) {
+ while (inNamespace(&def) && hasNext()) {
switch (next()) {
case NAMESPACE:
if (test(IDENTIFIER)) {
@@ -915,7 +928,8 @@ void Moc::parse()
} else {
knownGadgets.insert(def.classname, def.qualified);
knownGadgets.insert(def.qualified, def.qualified);
- classList += def;
+ if (n.doGenerate)
+ classList += def;
}
}
}
@@ -992,7 +1006,7 @@ void Moc::generate(FILE *out)
fprintf(out, "** WARNING! All changes made in this file will be lost!\n"
"*****************************************************************************/\n\n");
-
+ fprintf(out, "#include <memory>\n"); // For std::addressof
if (!noInclude) {
if (includePath.size() && !includePath.endsWith('/'))
includePath += '/';
@@ -1180,6 +1194,15 @@ void Moc::createPropertyDef(PropertyDef &propDef)
propDef.type = type;
+ auto checkIsFunction = [&](const QByteArray &def, const char *name) {
+ if (def.endsWith(')')) {
+ QByteArray msg = "Providing a function for ";
+ msg += name;
+ msg += " in a property declaration is deprecated and will not be supported in Qt 6 anymore.";
+ warning(msg.constData());
+ }
+ };
+
next();
propDef.name = lexem();
while (test(IDENTIFIER)) {
@@ -1229,11 +1252,13 @@ void Moc::createPropertyDef(PropertyDef &propDef)
error(2);
break;
case 'S':
- if (l == "SCRIPTABLE")
+ if (l == "SCRIPTABLE") {
propDef.scriptable = v + v2;
- else if (l == "STORED")
+ checkIsFunction(propDef.scriptable, "SCRIPTABLE");
+ } else if (l == "STORED") {
propDef.stored = v + v2;
- else
+ checkIsFunction(propDef.stored, "STORED");
+ } else
error(2);
break;
case 'W': if (l != "WRITE") error(2);
@@ -1241,15 +1266,18 @@ void Moc::createPropertyDef(PropertyDef &propDef)
break;
case 'D': if (l != "DESIGNABLE") error(2);
propDef.designable = v + v2;
+ checkIsFunction(propDef.designable, "DESIGNABLE");
break;
case 'E': if (l != "EDITABLE") error(2);
propDef.editable = v + v2;
+ checkIsFunction(propDef.editable, "EDITABLE");
break;
case 'N': if (l != "NOTIFY") error(2);
propDef.notify = v;
break;
case 'U': if (l != "USER") error(2);
propDef.user = v + v2;
+ checkIsFunction(propDef.user, "USER");
break;
default:
error(2);
@@ -1297,6 +1325,9 @@ void Moc::parsePluginData(ClassDef *def)
if (l == "IID") {
next(STRING_LITERAL);
def->pluginData.iid = unquotedLexem();
+ } else if (l == "URI") {
+ next(STRING_LITERAL);
+ def->pluginData.uri = unquotedLexem();
} else if (l == "FILE") {
next(STRING_LITERAL);
QByteArray metaDataFile = unquotedLexem();
@@ -1337,6 +1368,7 @@ void Moc::parsePluginData(ClassDef *def)
+ " does not contain a valid JSON object. Declaration will be ignored";
warning(msg.constData());
def->pluginData.iid = QByteArray();
+ def->pluginData.uri = QByteArray();
return;
}
}
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index d98c73e1a0..bb1c9501fe 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -83,57 +83,53 @@ Q_DECLARE_TYPEINFO(ArgumentDef, Q_MOVABLE_TYPE);
struct FunctionDef
{
- FunctionDef(): returnTypeIsVolatile(false), access(Private), isConst(false), isVirtual(false), isStatic(false),
- inlineCode(false), wasCloned(false), isCompat(false), isInvokable(false),
- isScriptable(false), isSlot(false), isSignal(false), isPrivateSignal(false),
- isConstructor(false), isDestructor(false), isAbstract(false), revision(0) {}
Type type;
+ QVector<ArgumentDef> arguments;
QByteArray normalizedType;
QByteArray tag;
QByteArray name;
- bool returnTypeIsVolatile;
-
- QVector<ArgumentDef> arguments;
+ QByteArray inPrivateClass;
enum Access { Private, Protected, Public };
- Access access;
- bool isConst;
- bool isVirtual;
- bool isStatic;
- bool inlineCode;
- bool wasCloned;
-
- QByteArray inPrivateClass;
- bool isCompat;
- bool isInvokable;
- bool isScriptable;
- bool isSlot;
- bool isSignal;
- bool isPrivateSignal;
- bool isConstructor;
- bool isDestructor;
- bool isAbstract;
-
- int revision;
+ Access access = Private;
+ int revision = 0;
+
+ bool isConst = false;
+ bool isVirtual = false;
+ bool isStatic = false;
+ bool inlineCode = false;
+ bool wasCloned = false;
+
+ bool returnTypeIsVolatile = false;
+
+ bool isCompat = false;
+ bool isInvokable = false;
+ bool isScriptable = false;
+ bool isSlot = false;
+ bool isSignal = false;
+ bool isPrivateSignal = false;
+ bool isConstructor = false;
+ bool isDestructor = false;
+ bool isAbstract = false;
};
Q_DECLARE_TYPEINFO(FunctionDef, Q_MOVABLE_TYPE);
struct PropertyDef
{
- PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec), revision(0){}
- QByteArray name, type, member, read, write, reset, designable, scriptable, editable, stored, user, notify, inPrivateClass;
- int notifyId; // -1 means no notifyId, >= 0 means signal defined in this class, < -1 means signal not defined in this class
- bool constant;
- bool final;
- enum Specification { ValueSpec, ReferenceSpec, PointerSpec };
- Specification gspec;
bool stdCppSet() const {
QByteArray s("set");
s += toupper(name[0]);
s += name.mid(1);
return (s == write);
}
- int revision;
+
+ QByteArray name, type, member, read, write, reset, designable, scriptable, editable, stored, user, notify, inPrivateClass;
+ int notifyId = -1; // -1 means no notifyId, >= 0 means signal defined in this class, < -1 means signal not defined in this class
+ enum Specification { ValueSpec, ReferenceSpec, PointerSpec };
+ Specification gspec = ValueSpec;
+ int revision = 0;
+ bool constant = false;
+ bool final = false;
};
Q_DECLARE_TYPEINFO(PropertyDef, Q_MOVABLE_TYPE);
@@ -169,11 +165,9 @@ struct ClassDef : BaseDef {
};
QVector<QVector<Interface> >interfaceList;
- bool hasQObject = false;
- bool hasQGadget = false;
-
struct PluginData {
QByteArray iid;
+ QByteArray uri;
QMap<QString, QJsonArray> metaArgs;
QJsonDocument metaData;
} pluginData;
@@ -181,17 +175,21 @@ struct ClassDef : BaseDef {
QVector<FunctionDef> constructorList;
QVector<FunctionDef> signalList, slotList, methodList, publicList;
QVector<QByteArray> nonClassSignalList;
- int notifyableProperties = 0;
QVector<PropertyDef> propertyList;
+ int notifyableProperties = 0;
int revisionedMethods = 0;
int revisionedProperties = 0;
+ bool hasQObject = false;
+ bool hasQGadget = false;
+
};
Q_DECLARE_TYPEINFO(ClassDef, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(ClassDef::Interface, Q_MOVABLE_TYPE);
struct NamespaceDef : BaseDef {
bool hasQNamespace = false;
+ bool doGenerate = false;
};
Q_DECLARE_TYPEINFO(NamespaceDef, Q_MOVABLE_TYPE);
@@ -260,6 +258,8 @@ public:
bool testFunctionAttribute(Token tok, FunctionDef *def);
bool testFunctionRevision(FunctionDef *def);
+ bool skipCxxAttributes();
+
void checkSuperClasses(ClassDef *def);
void checkProperties(ClassDef* cdef);
};
diff --git a/src/tools/moc/parser.h b/src/tools/moc/parser.h
index bedcbbf7e2..63f4cf0d9a 100644
--- a/src/tools/moc/parser.h
+++ b/src/tools/moc/parser.h
@@ -69,9 +69,9 @@ public:
inline const Symbol &symbol() { return symbols.at(index-1);}
Q_NORETURN void error(int rollback);
- Q_NORETURN void error(const char *msg = 0);
- void warning(const char * = 0);
- void note(const char * = 0);
+ Q_NORETURN void error(const char *msg = nullptr);
+ void warning(const char * = nullptr);
+ void note(const char * = nullptr);
};
diff --git a/src/tools/moc/util/generate.sh b/src/tools/moc/util/generate.sh
index 3894be1309..5460d28924 100755
--- a/src/tools/moc/util/generate.sh
+++ b/src/tools/moc/util/generate.sh
@@ -27,6 +27,8 @@
##
#############################################################################
+set -ex
+
qmake
make
cat licenseheader.txt > ../keywords.cpp
diff --git a/src/tools/moc/util/generate_keywords.pro b/src/tools/moc/util/generate_keywords.pro
index 2bbc3ced61..e29738c18a 100644
--- a/src/tools/moc/util/generate_keywords.pro
+++ b/src/tools/moc/util/generate_keywords.pro
@@ -1,4 +1,5 @@
CONFIG -= moc
CONFIG += cmdline
+QT = core
SOURCES += generate_keywords.cpp
diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
index 7c6f0bdeef..522c55593f 100644
--- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
+++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
@@ -32,7 +32,6 @@
#include <qfile.h>
#include <qlist.h>
#include <qbuffer.h>
-#include <qregexp.h>
#include <qvector.h>
#include <qdebug.h>
diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
index ab7726a01f..ce4232f3e8 100644
--- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
+++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
@@ -161,22 +161,22 @@ static QString moc(const QString &name)
static QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost)
{
- ts << "/*" << endl
- << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << endl
- << " * Command line was: " << commandLine << endl
- << " *" << endl
- << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << endl
- << " *" << endl
- << " * This is an auto-generated file." << endl;
+ ts << "/*" << Qt::endl
+ << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << Qt::endl
+ << " * Command line was: " << commandLine << Qt::endl
+ << " *" << Qt::endl
+ << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << Qt::endl
+ << " *" << Qt::endl
+ << " * This is an auto-generated file." << Qt::endl;
if (changesWillBeLost)
- ts << " * Do not edit! All changes made to it will be lost." << endl;
+ ts << " * Do not edit! All changes made to it will be lost." << Qt::endl;
else
- ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << endl
- << " * before re-generating it." << endl;
+ ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << Qt::endl
+ << " * before re-generating it." << Qt::endl;
- ts << " */" << endl
- << endl;
+ ts << " */" << Qt::endl
+ << Qt::endl;
return ts;
}
@@ -326,7 +326,6 @@ static void writeArgList(QTextStream &ts, const QStringList &argNames,
// yes, starting from 1
for (int i = 1; i < outputArgs.count(); ++i) {
const QDBusIntrospection::Argument &arg = outputArgs.at(i);
- QString name = arg.name;
if (!first)
ts << ", ";
@@ -467,72 +466,70 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
}
includeGuard = QString(QLatin1String("%1"))
.arg(includeGuard);
- hs << "#ifndef " << includeGuard << endl
- << "#define " << includeGuard << endl
- << endl;
+ hs << "#ifndef " << includeGuard << Qt::endl
+ << "#define " << includeGuard << Qt::endl
+ << Qt::endl;
// include our stuff:
- hs << "#include <QtCore/QObject>" << endl
+ hs << "#include <QtCore/QObject>" << Qt::endl
<< includeList
- << "#include <QtDBus/QtDBus>" << endl;
+ << "#include <QtDBus/QtDBus>" << Qt::endl;
for (const QString &include : qAsConst(includes)) {
- hs << "#include \"" << include << "\"" << endl;
+ hs << "#include \"" << include << "\"" << Qt::endl;
if (headerName.isEmpty())
- cs << "#include \"" << include << "\"" << endl;
+ cs << "#include \"" << include << "\"" << Qt::endl;
}
- hs << endl;
+ hs << Qt::endl;
if (cppName != headerName) {
if (!headerName.isEmpty() && headerName != QLatin1String("-"))
- cs << "#include \"" << headerName << "\"" << endl << endl;
+ cs << "#include \"" << headerName << "\"" << Qt::endl << Qt::endl;
}
for (const QDBusIntrospection::Interface *interface : interfaces) {
QString className = classNameForInterface(interface->name, Proxy);
// comment:
- hs << "/*" << endl
- << " * Proxy class for interface " << interface->name << endl
- << " */" << endl;
- cs << "/*" << endl
- << " * Implementation of interface class " << className << endl
- << " */" << endl
- << endl;
+ hs << "/*" << Qt::endl
+ << " * Proxy class for interface " << interface->name << Qt::endl
+ << " */" << Qt::endl;
+ cs << "/*" << Qt::endl
+ << " * Implementation of interface class " << className << Qt::endl
+ << " */" << Qt::endl
+ << Qt::endl;
// class header:
- hs << "class " << className << ": public QDBusAbstractInterface" << endl
- << "{" << endl
- << " Q_OBJECT" << endl;
+ hs << "class " << className << ": public QDBusAbstractInterface" << Qt::endl
+ << "{" << Qt::endl
+ << " Q_OBJECT" << Qt::endl;
// the interface name
- hs << "public:" << endl
- << " static inline const char *staticInterfaceName()" << endl
- << " { return \"" << interface->name << "\"; }" << endl
- << endl;
+ hs << "public:" << Qt::endl
+ << " static inline const char *staticInterfaceName()" << Qt::endl
+ << " { return \"" << interface->name << "\"; }" << Qt::endl
+ << Qt::endl;
// constructors/destructors:
- hs << "public:" << endl
- << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << endl
- << endl
- << " ~" << className << "();" << endl
- << endl;
- cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << endl
- << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << endl
- << "{" << endl
- << "}" << endl
- << endl
- << className << "::~" << className << "()" << endl
- << "{" << endl
- << "}" << endl
- << endl;
+ hs << "public:" << Qt::endl
+ << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << Qt::endl
+ << Qt::endl
+ << " ~" << className << "();" << Qt::endl
+ << Qt::endl;
+ cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << Qt::endl
+ << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << Qt::endl
+ << "{" << Qt::endl
+ << "}" << Qt::endl
+ << Qt::endl
+ << className << "::~" << className << "()" << Qt::endl
+ << "{" << Qt::endl
+ << "}" << Qt::endl
+ << Qt::endl;
// properties:
for (const QDBusIntrospection::Property &property : interface->properties) {
QByteArray type = qtTypeName(property.type, property.annotations);
- QString templateType = templateArg(type);
- QString constRefType = constRefArg(type);
QString getter = propertyGetter(property);
QString setter = propertySetter(property);
@@ -548,27 +545,27 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
// it's writeable
hs << " WRITE " << setter;
- hs << ")" << endl;
+ hs << ")" << Qt::endl;
// getter:
if (property.access != QDBusIntrospection::Property::Write) {
- hs << " inline " << type << " " << getter << "() const" << endl
+ hs << " inline " << type << " " << getter << "() const" << Qt::endl
<< " { return qvariant_cast< " << type << " >(property(\""
- << property.name << "\")); }" << endl;
+ << property.name << "\")); }" << Qt::endl;
}
// setter:
if (property.access != QDBusIntrospection::Property::Read) {
- hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl
+ hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << Qt::endl
<< " { setProperty(\"" << property.name
- << "\", QVariant::fromValue(value)); }" << endl;
+ << "\", QVariant::fromValue(value)); }" << Qt::endl;
}
- hs << endl;
+ hs << Qt::endl;
}
// methods:
- hs << "public Q_SLOTS: // METHODS" << endl;
+ hs << "public Q_SLOTS: // METHODS" << Qt::endl;
for (const QDBusIntrospection::Method &method : interface->methods) {
bool isDeprecated = method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true");
bool isNoReply =
@@ -598,26 +595,26 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
QStringList argNames = makeArgNames(method.inputArgs);
writeArgList(hs, argNames, method.annotations, method.inputArgs);
- hs << ")" << endl
- << " {" << endl
- << " QList<QVariant> argumentList;" << endl;
+ hs << ")" << Qt::endl
+ << " {" << Qt::endl
+ << " QList<QVariant> argumentList;" << Qt::endl;
if (!method.inputArgs.isEmpty()) {
hs << " argumentList";
for (int argPos = 0; argPos < method.inputArgs.count(); ++argPos)
hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')';
- hs << ";" << endl;
+ hs << ";" << Qt::endl;
}
if (isNoReply)
hs << " callWithArgumentList(QDBus::NoBlock, "
- << "QStringLiteral(\"" << method.name << "\"), argumentList);" << endl;
+ << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl;
else
hs << " return asyncCallWithArgumentList(QStringLiteral(\""
- << method.name << "\"), argumentList);" << endl;
+ << method.name << "\"), argumentList);" << Qt::endl;
// close the function:
- hs << " }" << endl;
+ hs << " }" << Qt::endl;
if (method.outputArgs.count() > 1) {
// generate the old-form QDBusReply methods with multiple incoming parameters
@@ -630,39 +627,39 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs);
writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs);
- hs << ")" << endl
- << " {" << endl
- << " QList<QVariant> argumentList;" << endl;
+ hs << ")" << Qt::endl
+ << " {" << Qt::endl
+ << " QList<QVariant> argumentList;" << Qt::endl;
int argPos = 0;
if (!method.inputArgs.isEmpty()) {
hs << " argumentList";
for (argPos = 0; argPos < method.inputArgs.count(); ++argPos)
hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')';
- hs << ";" << endl;
+ hs << ";" << Qt::endl;
}
hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, "
- << "QStringLiteral(\"" << method.name << "\"), argumentList);" << endl;
+ << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl;
argPos++;
hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == "
- << method.outputArgs.count() << ") {" << endl;
+ << method.outputArgs.count() << ") {" << Qt::endl;
// yes, starting from 1
for (int i = 1; i < method.outputArgs.count(); ++i)
hs << " " << argNames.at(argPos++) << " = qdbus_cast<"
<< templateArg(qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out"))
- << ">(reply.arguments().at(" << i << "));" << endl;
- hs << " }" << endl
- << " return reply;" << endl
- << " }" << endl;
+ << ">(reply.arguments().at(" << i << "));" << Qt::endl;
+ hs << " }" << Qt::endl
+ << " return reply;" << Qt::endl
+ << " }" << Qt::endl;
}
- hs << endl;
+ hs << Qt::endl;
}
- hs << "Q_SIGNALS: // SIGNALS" << endl;
+ hs << "Q_SIGNALS: // SIGNALS" << Qt::endl;
for (const QDBusIntrospection::Signal &signal : interface->signals_) {
hs << " ";
if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) ==
@@ -674,12 +671,12 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
QStringList argNames = makeArgNames(signal.outputArgs);
writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs);
- hs << ");" << endl; // finished for header
+ hs << ");" << Qt::endl; // finished for header
}
// close the class:
- hs << "};" << endl
- << endl;
+ hs << "};" << Qt::endl
+ << Qt::endl;
}
if (!skipNamespaces) {
@@ -701,17 +698,17 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
// i parts matched
// close last.arguments().count() - i namespaces:
for (int j = i; j < last.count(); ++j)
- hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << endl;
+ hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << Qt::endl;
// open current.arguments().count() - i namespaces
for (int j = i; j < current.count(); ++j)
- hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << endl;
+ hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << Qt::endl;
// add this class:
if (!name.isEmpty()) {
hs << QString(current.count() * 2, QLatin1Char(' '))
<< "typedef ::" << classNameForInterface(it->constData()->name, Proxy)
- << " " << name << ";" << endl;
+ << " " << name << ";" << Qt::endl;
}
if (it == interfaces.constEnd())
@@ -722,12 +719,12 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf
}
// close the include guard
- hs << "#endif" << endl;
+ hs << "#endif" << Qt::endl;
QString mocName = moc(filename);
if (includeMocs && !mocName.isEmpty())
- cs << endl
- << "#include \"" << mocName << "\"" << endl;
+ cs << Qt::endl
+ << "#include \"" << mocName << "\"" << Qt::endl;
cs.flush();
hs.flush();
@@ -775,36 +772,36 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
}
includeGuard = QString(QLatin1String("%1"))
.arg(includeGuard);
- hs << "#ifndef " << includeGuard << endl
- << "#define " << includeGuard << endl
- << endl;
+ hs << "#ifndef " << includeGuard << Qt::endl
+ << "#define " << includeGuard << Qt::endl
+ << Qt::endl;
// include our stuff:
- hs << "#include <QtCore/QObject>" << endl;
+ hs << "#include <QtCore/QObject>" << Qt::endl;
if (cppName == headerName)
- hs << "#include <QtCore/QMetaObject>" << endl
- << "#include <QtCore/QVariant>" << endl;
- hs << "#include <QtDBus/QtDBus>" << endl;
+ hs << "#include <QtCore/QMetaObject>" << Qt::endl
+ << "#include <QtCore/QVariant>" << Qt::endl;
+ hs << "#include <QtDBus/QtDBus>" << Qt::endl;
for (const QString &include : qAsConst(includes)) {
- hs << "#include \"" << include << "\"" << endl;
+ hs << "#include \"" << include << "\"" << Qt::endl;
if (headerName.isEmpty())
- cs << "#include \"" << include << "\"" << endl;
+ cs << "#include \"" << include << "\"" << Qt::endl;
}
if (cppName != headerName) {
if (!headerName.isEmpty() && headerName != QLatin1String("-"))
- cs << "#include \"" << headerName << "\"" << endl;
+ cs << "#include \"" << headerName << "\"" << Qt::endl;
- cs << "#include <QtCore/QMetaObject>" << endl
+ cs << "#include <QtCore/QMetaObject>" << Qt::endl
<< includeList
- << endl;
+ << Qt::endl;
hs << forwardDeclarations;
} else {
hs << includeList;
}
- hs << endl;
+ hs << Qt::endl;
QString parent = parentClassName;
if (parentClassName.isEmpty())
@@ -814,47 +811,47 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
QString className = classNameForInterface(interface->name, Adaptor);
// comment:
- hs << "/*" << endl
- << " * Adaptor class for interface " << interface->name << endl
- << " */" << endl;
- cs << "/*" << endl
- << " * Implementation of adaptor class " << className << endl
- << " */" << endl
- << endl;
+ hs << "/*" << Qt::endl
+ << " * Adaptor class for interface " << interface->name << Qt::endl
+ << " */" << Qt::endl;
+ cs << "/*" << Qt::endl
+ << " * Implementation of adaptor class " << className << Qt::endl
+ << " */" << Qt::endl
+ << Qt::endl;
// class header:
- hs << "class " << className << ": public QDBusAbstractAdaptor" << endl
- << "{" << endl
- << " Q_OBJECT" << endl
- << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << endl
- << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << endl
+ hs << "class " << className << ": public QDBusAbstractAdaptor" << Qt::endl
+ << "{" << Qt::endl
+ << " Q_OBJECT" << Qt::endl
+ << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << Qt::endl
+ << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << Qt::endl
<< stringify(interface->introspection)
- << " \"\")" << endl
- << "public:" << endl
- << " " << className << "(" << parent << " *parent);" << endl
- << " virtual ~" << className << "();" << endl
- << endl;
+ << " \"\")" << Qt::endl
+ << "public:" << Qt::endl
+ << " " << className << "(" << parent << " *parent);" << Qt::endl
+ << " virtual ~" << className << "();" << Qt::endl
+ << Qt::endl;
if (!parentClassName.isEmpty())
- hs << " inline " << parent << " *parent() const" << endl
- << " { return static_cast<" << parent << " *>(QObject::parent()); }" << endl
- << endl;
+ hs << " inline " << parent << " *parent() const" << Qt::endl
+ << " { return static_cast<" << parent << " *>(QObject::parent()); }" << Qt::endl
+ << Qt::endl;
// constructor/destructor
- cs << className << "::" << className << "(" << parent << " *parent)" << endl
- << " : QDBusAbstractAdaptor(parent)" << endl
- << "{" << endl
- << " // constructor" << endl
- << " setAutoRelaySignals(true);" << endl
- << "}" << endl
- << endl
- << className << "::~" << className << "()" << endl
- << "{" << endl
- << " // destructor" << endl
- << "}" << endl
- << endl;
-
- hs << "public: // PROPERTIES" << endl;
+ cs << className << "::" << className << "(" << parent << " *parent)" << Qt::endl
+ << " : QDBusAbstractAdaptor(parent)" << Qt::endl
+ << "{" << Qt::endl
+ << " // constructor" << Qt::endl
+ << " setAutoRelaySignals(true);" << Qt::endl
+ << "}" << Qt::endl
+ << Qt::endl
+ << className << "::~" << className << "()" << Qt::endl
+ << "{" << Qt::endl
+ << " // destructor" << Qt::endl
+ << "}" << Qt::endl
+ << Qt::endl;
+
+ hs << "public: // PROPERTIES" << Qt::endl;
for (const QDBusIntrospection::Property &property : interface->properties) {
QByteArray type = qtTypeName(property.type, property.annotations);
QString constRefType = constRefArg(type);
@@ -866,38 +863,38 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
hs << " READ " << getter;
if (property.access != QDBusIntrospection::Property::Read)
hs << " WRITE " << setter;
- hs << ")" << endl;
+ hs << ")" << Qt::endl;
// getter:
if (property.access != QDBusIntrospection::Property::Write) {
- hs << " " << type << " " << getter << "() const;" << endl;
+ hs << " " << type << " " << getter << "() const;" << Qt::endl;
cs << type << " "
- << className << "::" << getter << "() const" << endl
- << "{" << endl
- << " // get the value of property " << property.name << endl
- << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << endl
- << "}" << endl
- << endl;
+ << className << "::" << getter << "() const" << Qt::endl
+ << "{" << Qt::endl
+ << " // get the value of property " << property.name << Qt::endl
+ << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << Qt::endl
+ << "}" << Qt::endl
+ << Qt::endl;
}
// setter
if (property.access != QDBusIntrospection::Property::Read) {
- hs << " void " << setter << "(" << constRefType << "value);" << endl;
- cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << endl
- << "{" << endl
- << " // set the value of property " << property.name << endl
+ hs << " void " << setter << "(" << constRefType << "value);" << Qt::endl;
+ cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << Qt::endl
+ << "{" << Qt::endl
+ << " // set the value of property " << property.name << Qt::endl
<< " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value";
if (constRefType.contains(QLatin1String("QDBusVariant")))
cs << ".variant()";
- cs << "));" << endl
- << "}" << endl
- << endl;
+ cs << "));" << Qt::endl
+ << "}" << Qt::endl
+ << Qt::endl;
}
- hs << endl;
+ hs << Qt::endl;
}
- hs << "public Q_SLOTS: // METHODS" << endl;
+ hs << "public Q_SLOTS: // METHODS" << Qt::endl;
for (const QDBusIntrospection::Method &method : interface->methods) {
bool isNoReply =
method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true");
@@ -933,10 +930,10 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs);
writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs);
- hs << ");" << endl; // finished for header
- cs << ")" << endl
- << "{" << endl
- << " // handle method call " << interface->name << "." << methodName(method) << endl;
+ hs << ");" << Qt::endl; // finished for header
+ cs << ")" << Qt::endl
+ << "{" << Qt::endl
+ << " // handle method call " << interface->name << "." << methodName(method) << Qt::endl;
// make the call
bool usingInvokeMethod = false;
@@ -948,7 +945,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
// we are using QMetaObject::invokeMethod
if (!returnType.isEmpty())
cs << " " << returnType << " " << argNames.at(method.inputArgs.count())
- << ";" << endl;
+ << ";" << Qt::endl;
static const char invoke[] = " QMetaObject::invokeMethod(parent(), \"";
cs << invoke << name << "\"";
@@ -969,10 +966,10 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
<< argNames.at(i)
<< ")";
- cs << ");" << endl;
+ cs << ");" << Qt::endl;
if (!returnType.isEmpty())
- cs << " return " << argNames.at(method.inputArgs.count()) << ";" << endl;
+ cs << " return " << argNames.at(method.inputArgs.count()) << ";" << Qt::endl;
} else {
if (parentClassName.isEmpty())
cs << " //";
@@ -1000,13 +997,13 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
first = false;
}
- cs << ");" << endl;
+ cs << ");" << Qt::endl;
}
- cs << "}" << endl
- << endl;
+ cs << "}" << Qt::endl
+ << Qt::endl;
}
- hs << "Q_SIGNALS: // SIGNALS" << endl;
+ hs << "Q_SIGNALS: // SIGNALS" << Qt::endl;
for (const QDBusIntrospection::Signal &signal : interface->signals_) {
hs << " ";
if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) ==
@@ -1018,21 +1015,21 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte
QStringList argNames = makeArgNames(signal.outputArgs);
writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs);
- hs << ");" << endl; // finished for header
+ hs << ");" << Qt::endl; // finished for header
}
// close the class:
- hs << "};" << endl
- << endl;
+ hs << "};" << Qt::endl
+ << Qt::endl;
}
// close the include guard
- hs << "#endif" << endl;
+ hs << "#endif" << Qt::endl;
QString mocName = moc(filename);
if (includeMocs && !mocName.isEmpty())
- cs << endl
- << "#include \"" << mocName << "\"" << endl;
+ cs << Qt::endl
+ << "#include \"" << mocName << "\"" << Qt::endl;
cs.flush();
hs.flush();
diff --git a/src/tools/qfloat16-tables/qfloat16-tables.pro b/src/tools/qfloat16-tables/qfloat16-tables.pro
deleted file mode 100644
index a7d10ac197..0000000000
--- a/src/tools/qfloat16-tables/qfloat16-tables.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-option(host_build)
-
-CONFIG += force_bootstrap
-SOURCES += gen_qfloat16_tables.cpp
-
-load(qt_tool)
-
-lib.CONFIG = dummy_install
-INSTALLS = lib
diff --git a/src/tools/qlalr/cppgenerator.cpp b/src/tools/qlalr/cppgenerator.cpp
index b14c73a8fe..ee17be041e 100644
--- a/src/tools/qlalr/cppgenerator.cpp
+++ b/src/tools/qlalr/cppgenerator.cpp
@@ -43,7 +43,7 @@ void generateSeparator(int i, QTextStream &out)
if (!(i % 10)) {
if (i)
out << ",";
- out << endl << " ";
+ out << Qt::endl << " ";
} else {
out << ", ";
}
@@ -127,8 +127,8 @@ void CppGenerator::operator () ()
{
// action table...
state_count = aut.states.size ();
- terminal_count = grammar.terminals.size ();
- non_terminal_count = grammar.non_terminals.size ();
+ terminal_count = static_cast<int>(grammar.terminals.size());
+ non_terminal_count = static_cast<int>(grammar.non_terminals.size());
#define ACTION(i, j) table [(i) * terminal_count + (j)]
#define GOTO(i, j) pgoto [(i) * non_terminal_count + (j)]
@@ -187,14 +187,14 @@ void CppGenerator::operator () ()
{
if (verbose)
qout() << "*** Warning. Found a reduce/reduce conflict in state " << q << " on token ``" << s << "'' between rule "
- << r << " and " << -u << endl;
+ << r << " and " << -u << Qt::endl;
++reduce_reduce_conflict_count;
u = qMax (u, -r);
if (verbose)
- qout() << "\tresolved using rule " << -u << endl;
+ qout() << "\tresolved using rule " << -u << Qt::endl;
}
else if (u > 0)
@@ -227,7 +227,7 @@ void CppGenerator::operator () ()
++shift_reduce_conflict_count;
if (verbose)
- qout() << "*** Warning. Found a shift/reduce conflict in state " << q << " on token ``" << s << "'' with rule " << r << endl;
+ qout() << "*** Warning. Found a shift/reduce conflict in state " << q << " on token ``" << s << "'' with rule " << r << Qt::endl;
}
}
}
@@ -238,11 +238,11 @@ void CppGenerator::operator () ()
{
if (shift_reduce_conflict_count != grammar.expected_shift_reduce
|| reduce_reduce_conflict_count != grammar.expected_reduce_reduce)
- qerr() << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << endl;
+ qerr() << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl;
if (verbose)
- qout() << endl << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << endl
- << endl;
+ qout() << Qt::endl << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl
+ << Qt::endl;
}
QBitArray used_rules (grammar.rules.count ());
@@ -266,7 +266,7 @@ void CppGenerator::operator () ()
RulePointer rule = grammar.rules.begin () + i;
if (rule != grammar.goal)
- qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << endl;
+ qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << Qt::endl;
}
}
@@ -348,26 +348,26 @@ void CppGenerator::operator () ()
{
out << copyrightHeader()
<< privateCopyrightHeader()
- << endl;
+ << Qt::endl;
}
out << "// This file was generated by qlalr - DO NOT EDIT!\n";
- out << startIncludeGuard(grammar.merged_output) << endl;
+ out << startIncludeGuard(grammar.merged_output) << Qt::endl;
if (copyright) {
- out << "#if defined(ERROR)" << endl
- << "# undef ERROR" << endl
- << "#endif" << endl << endl;
+ out << "#if defined(ERROR)" << Qt::endl
+ << "# undef ERROR" << Qt::endl
+ << "#endif" << Qt::endl << Qt::endl;
}
generateDecl (out);
generateImpl (out);
out << p.decls();
out << p.impls();
- out << endl;
+ out << Qt::endl;
- out << endIncludeGuard(grammar.merged_output) << endl;
+ out << endIncludeGuard(grammar.merged_output) << Qt::endl;
return;
}
@@ -388,24 +388,24 @@ void CppGenerator::operator () ()
{
out << copyrightHeader()
<< privateCopyrightHeader()
- << endl;
+ << Qt::endl;
}
out << "// This file was generated by qlalr - DO NOT EDIT!\n";
- out << "#ifndef " << prot << endl
- << "#define " << prot << endl
- << endl;
+ out << "#ifndef " << prot << Qt::endl
+ << "#define " << prot << Qt::endl
+ << Qt::endl;
if (copyright) {
- out << "#include <QtCore/qglobal.h>" << endl << endl;
- out << "QT_BEGIN_NAMESPACE" << endl << endl;
+ out << "#include <QtCore/qglobal.h>" << Qt::endl << Qt::endl;
+ out << "QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl;
}
generateDecl (out);
if (copyright)
- out << "QT_END_NAMESPACE" << endl;
+ out << "QT_END_NAMESPACE" << Qt::endl;
- out << "#endif // " << prot << endl << endl;
+ out << "#endif // " << prot << Qt::endl << Qt::endl;
} // end decls
{ // bits...
@@ -419,12 +419,12 @@ void CppGenerator::operator () ()
out << "// This file was generated by qlalr - DO NOT EDIT!\n";
- out << "#include \"" << declFileName << "\"" << endl << endl;
+ out << "#include \"" << declFileName << "\"" << Qt::endl << Qt::endl;
if (copyright)
- out << "QT_BEGIN_NAMESPACE" << endl << endl;
+ out << "QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl;
generateImpl(out);
if (copyright)
- out << "QT_END_NAMESPACE" << endl;
+ out << "QT_END_NAMESPACE" << Qt::endl;
} // end bits
@@ -455,12 +455,12 @@ QString CppGenerator::debugInfoProt() const
void CppGenerator::generateDecl (QTextStream &out)
{
- out << "class " << grammar.table_name << endl
- << "{" << endl
- << "public:" << endl
- << " enum VariousConstants {" << endl;
+ out << "class " << grammar.table_name << Qt::endl
+ << "{" << Qt::endl
+ << "public:" << Qt::endl
+ << " enum VariousConstants {" << Qt::endl;
- for (Name t : qAsConst(grammar.terminals))
+ for (const Name &t : qAsConst(grammar.terminals))
{
QString name = *t;
int value = std::distance (grammar.names.begin (), t);
@@ -474,62 +474,62 @@ void CppGenerator::generateDecl (QTextStream &out)
else
name.prepend (grammar.token_prefix);
- out << " " << name << " = " << value << "," << endl;
+ out << " " << name << " = " << value << "," << Qt::endl;
}
- out << endl
- << " ACCEPT_STATE = " << accept_state << "," << endl
- << " RULE_COUNT = " << grammar.rules.size () << "," << endl
- << " STATE_COUNT = " << state_count << "," << endl
- << " TERMINAL_COUNT = " << terminal_count << "," << endl
- << " NON_TERMINAL_COUNT = " << non_terminal_count << "," << endl
- << endl
- << " GOTO_INDEX_OFFSET = " << compressed_action.index.size () << "," << endl
- << " GOTO_INFO_OFFSET = " << compressed_action.info.size () << "," << endl
- << " GOTO_CHECK_OFFSET = " << compressed_action.check.size () << endl
- << " };" << endl
- << endl
- << " static const char *const spell[];" << endl
- << " static const short lhs[];" << endl
- << " static const short rhs[];" << endl;
+ out << Qt::endl
+ << " ACCEPT_STATE = " << accept_state << "," << Qt::endl
+ << " RULE_COUNT = " << grammar.rules.size () << "," << Qt::endl
+ << " STATE_COUNT = " << state_count << "," << Qt::endl
+ << " TERMINAL_COUNT = " << terminal_count << "," << Qt::endl
+ << " NON_TERMINAL_COUNT = " << non_terminal_count << "," << Qt::endl
+ << Qt::endl
+ << " GOTO_INDEX_OFFSET = " << compressed_action.index.size () << "," << Qt::endl
+ << " GOTO_INFO_OFFSET = " << compressed_action.info.size () << "," << Qt::endl
+ << " GOTO_CHECK_OFFSET = " << compressed_action.check.size () << Qt::endl
+ << " };" << Qt::endl
+ << Qt::endl
+ << " static const char *const spell[];" << Qt::endl
+ << " static const short lhs[];" << Qt::endl
+ << " static const short rhs[];" << Qt::endl;
if (debug_info)
{
QString prot = debugInfoProt();
- out << endl << "#ifndef " << prot << endl
- << " static const int rule_index[];" << endl
- << " static const int rule_info[];" << endl
- << "#endif // " << prot << endl << endl;
+ out << Qt::endl << "#ifndef " << prot << Qt::endl
+ << " static const int rule_index[];" << Qt::endl
+ << " static const int rule_info[];" << Qt::endl
+ << "#endif // " << prot << Qt::endl << Qt::endl;
}
- out << " static const short goto_default[];" << endl
- << " static const short action_default[];" << endl
- << " static const short action_index[];" << endl
- << " static const short action_info[];" << endl
- << " static const short action_check[];" << endl
- << endl
- << " static inline int nt_action (int state, int nt)" << endl
- << " {" << endl
- << " const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;" << endl
- << " if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)" << endl
- << " return goto_default [nt];" << endl
- << endl
- << " return action_info [GOTO_INFO_OFFSET + yyn];" << endl
- << " }" << endl
- << endl
- << " static inline int t_action (int state, int token)" << endl
- << " {" << endl
- << " const int yyn = action_index [state] + token;" << endl
- << endl
- << " if (yyn < 0 || action_check [yyn] != token)" << endl
- << " return - action_default [state];" << endl
- << endl
- << " return action_info [yyn];" << endl
- << " }" << endl
- << "};" << endl
- << endl
- << endl;
+ out << " static const short goto_default[];" << Qt::endl
+ << " static const short action_default[];" << Qt::endl
+ << " static const short action_index[];" << Qt::endl
+ << " static const short action_info[];" << Qt::endl
+ << " static const short action_check[];" << Qt::endl
+ << Qt::endl
+ << " static inline int nt_action (int state, int nt)" << Qt::endl
+ << " {" << Qt::endl
+ << " const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;" << Qt::endl
+ << " if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)" << Qt::endl
+ << " return goto_default [nt];" << Qt::endl
+ << Qt::endl
+ << " return action_info [GOTO_INFO_OFFSET + yyn];" << Qt::endl
+ << " }" << Qt::endl
+ << Qt::endl
+ << " static inline int t_action (int state, int token)" << Qt::endl
+ << " {" << Qt::endl
+ << " const int yyn = action_index [state] + token;" << Qt::endl
+ << Qt::endl
+ << " if (yyn < 0 || action_check [yyn] != token)" << Qt::endl
+ << " return - action_default [state];" << Qt::endl
+ << Qt::endl
+ << " return action_info [yyn];" << Qt::endl
+ << " }" << Qt::endl
+ << "};" << Qt::endl
+ << Qt::endl
+ << Qt::endl;
}
void CppGenerator::generateImpl (QTextStream &out)
@@ -568,16 +568,16 @@ void CppGenerator::generateImpl (QTextStream &out)
{
first_nt = false;
QString prot = debugInfoProt();
- out << endl << "#ifndef " << prot << endl;
+ out << Qt::endl << "#ifndef " << prot << Qt::endl;
}
out << "\"" << *t << "\"";
}
}
if (debug_info)
- out << endl << "#endif // " << debugInfoProt() << endl;
+ out << Qt::endl << "#endif // " << debugInfoProt() << Qt::endl;
- out << endl << "};" << endl << endl;
+ out << Qt::endl << "};" << Qt::endl << Qt::endl;
out << "const short " << grammar.table_name << "::lhs [] = {";
idx = 0;
@@ -587,7 +587,7 @@ void CppGenerator::generateImpl (QTextStream &out)
out << aut.id (rule->lhs);
}
- out << endl << "};" << endl << endl;
+ out << Qt::endl << "};" << Qt::endl << Qt::endl;
out << "const short " << grammar.table_name << "::rhs [] = {";
idx = 0;
@@ -597,13 +597,13 @@ void CppGenerator::generateImpl (QTextStream &out)
out << rule->rhs.size ();
}
- out << endl << "};" << endl << endl;
+ out << Qt::endl << "};" << Qt::endl << Qt::endl;
if (debug_info)
{
QString prot = debugInfoProt();
- out << endl << "#ifndef " << prot << endl;
+ out << Qt::endl << "#ifndef " << prot << Qt::endl;
out << "const int " << grammar.table_name << "::rule_info [] = {";
idx = 0;
for (auto rule = grammar.rules.cbegin (); rule != grammar.rules.cend (); ++rule, ++idx)
@@ -615,7 +615,7 @@ void CppGenerator::generateImpl (QTextStream &out)
for (const Name &n : rule->rhs)
out << ", " << name_ids.value (n);
}
- out << endl << "};" << endl << endl;
+ out << Qt::endl << "};" << Qt::endl << Qt::endl;
out << "const int " << grammar.table_name << "::rule_index [] = {";
idx = 0;
@@ -627,8 +627,8 @@ void CppGenerator::generateImpl (QTextStream &out)
out << offset;
offset += rule->rhs.size () + 1;
}
- out << endl << "};" << endl
- << "#endif // " << prot << endl << endl;
+ out << Qt::endl << "};" << Qt::endl
+ << "#endif // " << prot << Qt::endl << Qt::endl;
}
out << "const short " << grammar.table_name << "::action_default [] = {";
@@ -642,27 +642,27 @@ void CppGenerator::generateImpl (QTextStream &out)
else
out << "0";
}
- out << endl << "};" << endl << endl;
+ out << Qt::endl << "};" << Qt::endl << Qt::endl;
out << "const short " << grammar.table_name << "::goto_default [] = {";
generateList(defgoto, out);
- out << endl << "};" << endl << endl;
+ out << Qt::endl << "};" << Qt::endl << Qt::endl;
out << "const short " << grammar.table_name << "::action_index [] = {";
generateList(compressed_action.index, out);
- out << "," << endl;
+ out << "," << Qt::endl;
generateList(compressed_goto.index, out);
- out << endl << "};" << endl << endl;
+ out << Qt::endl << "};" << Qt::endl << Qt::endl;
out << "const short " << grammar.table_name << "::action_info [] = {";
generateList(compressed_action.info, out);
- out << "," << endl;
+ out << "," << Qt::endl;
generateList(compressed_goto.info, out);
- out << endl << "};" << endl << endl;
+ out << Qt::endl << "};" << Qt::endl << Qt::endl;
out << "const short " << grammar.table_name << "::action_check [] = {";
generateList(compressed_action.check, out);
- out << "," << endl;
+ out << "," << Qt::endl;
generateList(compressed_goto.check, out);
- out << endl << "};" << endl << endl;
+ out << Qt::endl << "};" << Qt::endl << Qt::endl;
}
diff --git a/src/tools/qlalr/dotgraph.cpp b/src/tools/qlalr/dotgraph.cpp
index 1fa0a1ac77..1d479af2b2 100644
--- a/src/tools/qlalr/dotgraph.cpp
+++ b/src/tools/qlalr/dotgraph.cpp
@@ -41,9 +41,9 @@ void DotGraph::operator () (Automaton *aut)
{
Grammar *g = aut->_M_grammar;
- out << "digraph {" << endl << endl;
+ out << "digraph {" << Qt::endl << Qt::endl;
- out << "subgraph Includes {" << endl;
+ out << "subgraph Includes {" << Qt::endl;
for (Automaton::IncludesGraph::iterator incl = Automaton::IncludesGraph::begin_nodes ();
incl != Automaton::IncludesGraph::end_nodes (); ++incl)
{
@@ -53,14 +53,14 @@ void DotGraph::operator () (Automaton *aut)
out << "\t->\t";
out << "\"(" << aut->id ((*edge)->data.state) << ", " << (*edge)->data.nt << ")\"\t";
out << "[label=\"" << incl->data.state->follows [incl->data.nt] << "\"]";
- out << endl;
+ out << Qt::endl;
}
}
- out << "}" << endl << endl;
+ out << "}" << Qt::endl << Qt::endl;
- out << "subgraph LRA {" << endl;
- //out << "node [shape=record];" << endl << endl;
+ out << "subgraph LRA {" << Qt::endl;
+ //out << "node [shape=record];" << Qt::endl << Qt::endl;
for (StatePointer q = aut->states.begin (); q != aut->states.end (); ++q)
{
@@ -74,16 +74,16 @@ void DotGraph::operator () (Automaton *aut)
for (ItemPointer item = q->kernel.begin (); item != q->kernel.end (); ++item)
out << "| <" << index++ << "> " << *item;
- out << "}\"]" << endl;
+ out << "}\"]" << Qt::endl;
for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a)
{
const char *clr = g->isTerminal (a.key ()) ? "blue" : "red";
- out << "\t" << state << "\t->\t" << aut->id (*a) << "\t[color=\"" << clr << "\",label=\"" << a.key () << "\"]" << endl;
+ out << "\t" << state << "\t->\t" << aut->id (*a) << "\t[color=\"" << clr << "\",label=\"" << a.key () << "\"]" << Qt::endl;
}
- out << endl;
+ out << Qt::endl;
}
- out << "}" << endl;
- out << endl << endl << "}" << endl;
+ out << "}" << Qt::endl;
+ out << Qt::endl << Qt::endl << "}" << Qt::endl;
}
diff --git a/src/tools/qlalr/lalr.cpp b/src/tools/qlalr/lalr.cpp
index ec960925aa..8af3b3c0db 100644
--- a/src/tools/qlalr/lalr.cpp
+++ b/src/tools/qlalr/lalr.cpp
@@ -313,7 +313,7 @@ void Automaton::buildNullables ()
}
#ifndef QLALR_NO_DEBUG_NULLABLES
- qerr() << "nullables = {" << nullables << endl;
+ qerr() << "nullables = {" << nullables << Qt::endl;
#endif
}
@@ -456,7 +456,7 @@ void Automaton::buildLookbackSets ()
lookbacks.insert (item, Lookback (p, A));
#ifndef QLALR_NO_DEBUG_LOOKBACKS
- qerr() << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << endl;
+ qerr() << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << Qt::endl;
#endif
}
}
@@ -487,7 +487,7 @@ void Automaton::buildDirectReads ()
#ifndef QLALR_NO_DEBUG_DIRECT_READS
for (QMap<Name, NameSet>::iterator dr = q->reads.begin (); dr != q->reads.end (); ++dr)
- qerr() << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << endl;
+ qerr() << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << Qt::endl;
#endif
}
}
@@ -520,7 +520,7 @@ void Automaton::buildReadsDigraph ()
dump (qerr(), source);
qerr() << " reads ";
dump (qerr(), target);
- qerr() << endl;
+ qerr() << Qt::endl;
#endif
}
}
@@ -555,7 +555,7 @@ void Automaton::visitReadNode (ReadNode node)
_M_reads_stack.push (node);
#ifndef QLALR_NO_DEBUG_INCLUDES
- // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl;
+ // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << Qt::endl;
#endif
for (ReadsGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge)
@@ -635,7 +635,7 @@ void Automaton::buildIncludesDigraph ()
source->insertEdge (target);
#ifndef QLALR_NO_DEBUG_INCLUDES
- qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl;
+ qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << Qt::endl;
#endif // QLALR_NO_DEBUG_INCLUDES
continue;
@@ -657,7 +657,7 @@ void Automaton::buildIncludesDigraph ()
source->insertEdge (target);
#ifndef QLALR_NO_DEBUG_INCLUDES
- qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl;
+ qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << Qt::endl;
#endif // QLALR_NO_DEBUG_INCLUDES
}
}
@@ -674,7 +674,7 @@ void Automaton::visitIncludeNode (IncludeNode node)
_M_includes_stack.push (node);
#ifndef QLALR_NO_DEBUG_INCLUDES
- // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl;
+ // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << Qt::endl;
#endif
for (IncludesGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge)
@@ -690,7 +690,7 @@ void Automaton::visitIncludeNode (IncludeNode node)
dump (qerr(), node);
qerr() << " += follows";
dump (qerr(), r);
- qerr() << endl;
+ qerr() << Qt::endl;
#endif
NameSet &dst = node->data.state->follows [node->data.nt];
@@ -726,7 +726,7 @@ void Automaton::buildLookaheads ()
#ifndef QLALR_NO_DEBUG_LOOKAHEADS
qerr() << "(" << id (p) << ", " << *item->rule << ") lookbacks ";
dump (qerr(), lookback);
- qerr() << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << endl;
+ qerr() << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << Qt::endl;
#endif
lookaheads [item].insert (q->follows [lookback.nt].begin (), q->follows [lookback.nt].end ());
@@ -754,7 +754,7 @@ void Automaton::buildDefaultReduceActions ()
if (item->dot != item->end_rhs ())
continue;
- int la = lookaheads.value (item).size ();
+ int la = static_cast<int>(lookaheads.value(item).size());
if (def == state->closure.end () || la > size)
{
def = item;
diff --git a/src/tools/qlalr/lalr.g b/src/tools/qlalr/lalr.g
index 05d30c21fd..a849800dd5 100644
--- a/src/tools/qlalr/lalr.g
+++ b/src/tools/qlalr/lalr.g
@@ -261,7 +261,7 @@ int Recognizer::nextToken()
if (ch == QLatin1Char ('"'))
inp ();
else
- qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << Qt::endl;
_M_current_value = text;
return (token = STRING_LITERAL);
@@ -314,7 +314,7 @@ int Recognizer::nextToken()
return (token = PREC);
else
{
- qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << Qt::endl;
exit (EXIT_FAILURE);
return (token = ERROR);
}
@@ -659,7 +659,7 @@ case $rule_number: {
if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ())
{
- qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl;
return false;
}
@@ -683,7 +683,7 @@ case $rule_number: {
if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ())
{
- qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl;
return false;
}
@@ -712,7 +712,7 @@ case $rule_number: {
Name tok = _M_grammar->intern (sym(2));
if (! _M_grammar->isTerminal (tok))
{
- qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << Qt::endl;
_M_current_rule->prec = _M_grammar->names.end ();
}
else
@@ -758,7 +758,7 @@ case $rule_number: {
}
}
- qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << Qt::endl;
return false;
}
diff --git a/src/tools/qlalr/lalr.h b/src/tools/qlalr/lalr.h
index 6a2baaa462..55b65a640d 100644
--- a/src/tools/qlalr/lalr.h
+++ b/src/tools/qlalr/lalr.h
@@ -39,6 +39,7 @@
#include <algorithm>
#include <functional>
+#include <set>
class Rule;
class State;
@@ -48,89 +49,6 @@ class State;
class Arrow;
class Automaton;
-template <typename _Tp >
-class OrderedSet : protected QMap<_Tp, bool>
-{
- typedef QMap<_Tp, bool> _Base;
-
-public:
- class const_iterator
- {
- typename _Base::const_iterator _M_iterator;
-
- public:
- const_iterator () {}
-
- const_iterator (const typename _Base::const_iterator &it):
- _M_iterator (it) {}
-
- const _Tp &operator * () const
- { return _M_iterator.key (); }
-
- const _Tp *operator -> () const
- { return &_M_iterator.key (); }
-
- const_iterator &operator ++ ()
- { ++_M_iterator; return *this; }
-
- const_iterator operator ++ (int) const
- {
- const_iterator me (*this);
- ++_M_iterator;
- return me;
- }
-
- bool operator == (const const_iterator &other) const
- { return _M_iterator == other._M_iterator; }
-
- bool operator != (const const_iterator &other) const
- { return _M_iterator != other._M_iterator; }
- };
-
- typedef const_iterator iterator;
-
-public:
- OrderedSet () {}
-
- const_iterator begin () const
- { return const_iterator (_Base::begin ()); }
-
- const_iterator end () const
- { return const_iterator (_Base::end ()); }
-
- bool isEmpty () const
- { return _Base::isEmpty (); }
-
- int size () const
- { return _Base::size (); }
-
- const_iterator find (const _Tp &elt) const
- { return const_iterator (_Base::find (elt)); }
-
- QPair<const_iterator, bool> insert (const _Tp &elt)
- {
- int elts = _Base::size ();
- const_iterator it (_Base::insert (typename _Base::key_type (elt), true));
- return qMakePair (it, elts != _Base::size ());
- }
-
- QPair<const_iterator, bool> insert (const_iterator, const _Tp &elt)
- {
- int elts = _Base::size ();
- const_iterator it (_Base::insert (typename _Base::key_type (elt), true));
- return qMakePair (it, elts != _Base::size ());
- }
-
- const _Tp &operator [] (const _Tp &elt)
- { return *insert (elt)->first; }
-
- template <typename _InputIterator>
- void insert (_InputIterator first, _InputIterator last)
- {
- for (; first != last; ++first)
- insert (*first);
- }
-};
// names
typedef QLinkedList<QString>::iterator Name;
@@ -138,7 +56,7 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(QLinkedList<QString>::iterator, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
typedef QLinkedList<Name> NameList;
-typedef OrderedSet<Name> NameSet;
+typedef std::set<Name> NameSet;
// items
typedef QLinkedList<Item> ItemList;
@@ -255,7 +173,7 @@ template <typename _Tp>
class Node
{
public:
- typedef OrderedSet<Node<_Tp> > Repository;
+ typedef std::set<Node<_Tp> > Repository;
typedef typename Repository::iterator iterator;
typedef typename QLinkedList<iterator>::iterator edge_iterator;
@@ -404,9 +322,6 @@ public:
StatePointer state;
Name nt;
};
-QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(OrderedSet<Node<Read> >::const_iterator, Q_PRIMITIVE_TYPE);
-QT_END_NAMESPACE
class Include
{
@@ -428,9 +343,6 @@ public:
StatePointer state;
Name nt;
};
-QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(OrderedSet<Node<Include> >::const_iterator, Q_PRIMITIVE_TYPE);
-QT_END_NAMESPACE
class Automaton
{
diff --git a/src/tools/qlalr/main.cpp b/src/tools/qlalr/main.cpp
index 5971eb201d..a920b13c85 100644
--- a/src/tools/qlalr/main.cpp
+++ b/src/tools/qlalr/main.cpp
@@ -44,15 +44,15 @@
static void help_me ()
{
- qerr() << "Usage: qlalr [options] [input file name]" << endl
- << endl
- << " --help, -h\t\tdisplay this help and exit" << endl
- << " --verbose, -v\t\tverbose output" << endl
- << " --no-debug\t\tno debug information" << endl
- << " --no-lines\t\tno #line directives" << endl
- << " --dot\t\t\tgenerate a graph" << endl
- << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << endl
- << endl;
+ qerr() << "Usage: qlalr [options] [input file name]" << Qt::endl
+ << Qt::endl
+ << " --help, -h\t\tdisplay this help and exit" << Qt::endl
+ << " --verbose, -v\t\tverbose output" << Qt::endl
+ << " --no-debug\t\tno debug information" << Qt::endl
+ << " --no-lines\t\tno #line directives" << Qt::endl
+ << " --dot\t\t\tgenerate a graph" << Qt::endl
+ << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << Qt::endl
+ << Qt::endl;
exit (0);
}
@@ -91,7 +91,7 @@ int main (int argc, char *argv[])
file_name = arg;
else
- qerr() << "*** Warning. Ignore argument `" << arg << "'" << endl;
+ qerr() << "*** Warning. Ignore argument `" << arg << "'" << Qt::endl;
}
if (file_name.isEmpty ())
@@ -108,13 +108,13 @@ int main (int argc, char *argv[])
if (grammar.rules.isEmpty ())
{
- qerr() << "*** Fatal. No rules!" << endl;
+ qerr() << "*** Fatal. No rules!" << Qt::endl;
exit (EXIT_FAILURE);
}
else if (grammar.start == grammar.names.end ())
{
- qerr() << "*** Fatal. No start symbol!" << endl;
+ qerr() << "*** Fatal. No start symbol!" << Qt::endl;
exit (EXIT_FAILURE);
}
diff --git a/src/tools/qlalr/parsetable.cpp b/src/tools/qlalr/parsetable.cpp
index c88ac1291e..9e71acebb4 100644
--- a/src/tools/qlalr/parsetable.cpp
+++ b/src/tools/qlalr/parsetable.cpp
@@ -43,13 +43,13 @@ void ParseTable::operator () (Automaton *aut)
int rindex = 1;
for (RulePointer rule = g->rules.begin (); rule != g->rules.end (); ++rule)
- out << rindex++ << ")\t" << *rule << endl;
- out << endl << endl;
+ out << rindex++ << ")\t" << *rule << Qt::endl;
+ out << Qt::endl << Qt::endl;
int index = 0;
for (StatePointer state = aut->states.begin (); state != aut->states.end (); ++state)
{
- out << "state " << index++ << endl << endl;
+ out << "state " << index++ << Qt::endl << Qt::endl;
for (ItemPointer item = state->kernel.begin (); item != state->kernel.end (); ++item)
{
@@ -58,7 +58,7 @@ void ParseTable::operator () (Automaton *aut)
if (item->dot == item->end_rhs ())
out << " " << aut->lookaheads [item];
- out << endl;
+ out << Qt::endl;
}
bool first = true;
@@ -68,11 +68,11 @@ void ParseTable::operator () (Automaton *aut)
continue;
if (first)
- out << endl;
+ out << Qt::endl;
first = false;
- out << " " << *arrow.key () << " shift, and go to state " << std::distance (aut->states.begin (), *arrow) << endl;
+ out << " " << *arrow.key () << " shift, and go to state " << std::distance (aut->states.begin (), *arrow) << Qt::endl;
}
first = true;
@@ -82,13 +82,13 @@ void ParseTable::operator () (Automaton *aut)
continue;
if (first)
- out << endl;
+ out << Qt::endl;
first = false;
const auto lookaheads = aut->lookaheads.value(item);
for (const Name &la : lookaheads)
- out << " " << *la << " reduce using rule " << aut->id (item->rule) << " (" << *item->rule->lhs << ")" << endl;
+ out << " " << *la << " reduce using rule " << aut->id (item->rule) << " (" << *item->rule->lhs << ")" << Qt::endl;
}
first = true;
@@ -98,19 +98,19 @@ void ParseTable::operator () (Automaton *aut)
continue;
if (first)
- out << endl;
+ out << Qt::endl;
first = false;
- out << " " << *arrow.key () << " go to state " << std::distance (aut->states.begin (), *arrow) << endl;
+ out << " " << *arrow.key () << " go to state " << std::distance (aut->states.begin (), *arrow) << Qt::endl;
}
if (state->defaultReduce != g->rules.end ())
{
- out << endl
- << " $default reduce using rule " << aut->id (state->defaultReduce) << " (" << *state->defaultReduce->lhs << ")" << endl;
+ out << Qt::endl
+ << " $default reduce using rule " << aut->id (state->defaultReduce) << " (" << *state->defaultReduce->lhs << ")" << Qt::endl;
}
- out << endl;
+ out << Qt::endl;
}
}
diff --git a/src/tools/qlalr/recognizer.cpp b/src/tools/qlalr/recognizer.cpp
index ab797c85d0..3da54c0c6a 100644
--- a/src/tools/qlalr/recognizer.cpp
+++ b/src/tools/qlalr/recognizer.cpp
@@ -97,7 +97,7 @@ int Recognizer::nextToken()
if (ch == QLatin1Char ('"'))
inp ();
else
- qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << Qt::endl;
_M_current_value = text;
return (token = STRING_LITERAL);
@@ -150,7 +150,7 @@ int Recognizer::nextToken()
return (token = PREC);
else
{
- qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << Qt::endl;
exit (EXIT_FAILURE);
return (token = ERROR);
}
@@ -405,7 +405,7 @@ case 34: {
if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ())
{
- qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl;
return false;
}
@@ -420,7 +420,7 @@ case 38: {
if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ())
{
- qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl;
return false;
}
@@ -443,7 +443,7 @@ case 40: {
Name tok = _M_grammar->intern (sym(2));
if (! _M_grammar->isTerminal (tok))
{
- qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << Qt::endl;
_M_current_rule->prec = _M_grammar->names.end ();
}
else
@@ -474,7 +474,7 @@ case 43: {
}
}
- qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << endl;
+ qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << Qt::endl;
return false;
}
diff --git a/src/tools/qvkgen/qvkgen.cpp b/src/tools/qvkgen/qvkgen.cpp
index 059f9413cb..4db3f26161 100644
--- a/src/tools/qvkgen/qvkgen.cpp
+++ b/src/tools/qvkgen/qvkgen.cpp
@@ -192,22 +192,20 @@ QString VkSpecParser::parseName()
QString funcSig(const VkSpecParser::Command &c, const char *className = nullptr)
{
- QString s;
- s.sprintf("%s %s%s%s", qPrintable(c.cmd.type),
- (className ? className : ""), (className ? "::" : ""),
- qPrintable(c.cmd.name));
+ QString s(QString::asprintf("%s %s%s%s", qPrintable(c.cmd.type),
+ (className ? className : ""), (className ? "::" : ""),
+ qPrintable(c.cmd.name)));
if (!c.args.isEmpty()) {
s += QLatin1Char('(');
bool first = true;
for (const VkSpecParser::TypedName &a : c.args) {
- QString argStr;
- argStr.sprintf("%s%s%s%s", qPrintable(a.type), (a.type.endsWith(QLatin1Char('*')) ? "" : " "),
- qPrintable(a.name), qPrintable(a.typeSuffix));
if (!first)
s += QStringLiteral(", ");
else
first = false;
- s += argStr;
+ s += QString::asprintf("%s%s%s%s", qPrintable(a.type),
+ (a.type.endsWith(QLatin1Char('*')) ? "" : " "),
+ qPrintable(a.name), qPrintable(a.typeSuffix));
}
s += QLatin1Char(')');
}
@@ -216,13 +214,12 @@ QString funcSig(const VkSpecParser::Command &c, const char *className = nullptr)
QString funcCall(const VkSpecParser::Command &c, int idx)
{
- QString s;
// template:
// [return] reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(d_ptr->m_funcs[0])(instance, pPhysicalDeviceCount, pPhysicalDevices);
- s.sprintf("%sreinterpret_cast<PFN_%s>(d_ptr->m_funcs[%d])",
- (c.cmd.type == QStringLiteral("void") ? "" : "return "),
- qPrintable(c.cmd.name),
- idx);
+ QString s = QString::asprintf("%sreinterpret_cast<PFN_%s>(d_ptr->m_funcs[%d])",
+ (c.cmd.type == QStringLiteral("void") ? "" : "return "),
+ qPrintable(c.cmd.name),
+ idx);
if (!c.args.isEmpty()) {
s += QLatin1Char('(');
bool first = true;
@@ -338,10 +335,9 @@ bool genVulkanFunctionsH(const QVector<VkSpecParser::Command> &commands, const Q
*dst += QStringLiteral(";\n");
}
- QString str;
- str.sprintf(s, preamble.get(licHeaderFn).constData(), instCmdStr.toUtf8().constData(), devCmdStr.toUtf8().constData());
-
- f.write(str.toUtf8());
+ f.write(QString::asprintf(s, preamble.get(licHeaderFn).constData(),
+ instCmdStr.toUtf8().constData(),
+ devCmdStr.toUtf8().constData()).toUtf8());
return true;
}
@@ -400,10 +396,7 @@ bool genVulkanFunctionsPH(const QVector<VkSpecParser::Command> &commands, const
[](const VkSpecParser::Command &c) { return c.deviceLevel; });
const int instLevelCount = commands.count() - devLevelCount;
- QString str;
- str.sprintf(s, preamble.get(licHeaderFn).constData(), instLevelCount, devLevelCount);
-
- f.write(str.toUtf8());
+ f.write(QString::asprintf(s, preamble.get(licHeaderFn).constData(), instLevelCount, devLevelCount).toUtf8());
return true;
}
@@ -478,10 +471,12 @@ bool genVulkanFunctionsPC(const QVector<VkSpecParser::Command> &commands, const
if (instCmdNamesStr.count() > 2)
instCmdNamesStr = instCmdNamesStr.left(instCmdNamesStr.count() - 2);
- QString str;
- str.sprintf(s, preamble.get(licHeaderFn).constData(),
- instCmdWrapperStr.toUtf8().constData(), instCmdNamesStr.toUtf8().constData(), instIdx,
- devCmdWrapperStr.toUtf8().constData(), devCmdNamesStr.toUtf8().constData(), commands.count() - instIdx);
+ const QString str =
+ QString::asprintf(s, preamble.get(licHeaderFn).constData(),
+ instCmdWrapperStr.toUtf8().constData(),
+ instCmdNamesStr.toUtf8().constData(), instIdx,
+ devCmdWrapperStr.toUtf8().constData(),
+ devCmdNamesStr.toUtf8().constData(), commands.count() - instIdx);
f.write(str.toUtf8());
diff --git a/src/tools/rcc/main.cpp b/src/tools/rcc/main.cpp
index 12f986b1e2..0eb6766b5a 100644
--- a/src/tools/rcc/main.cpp
+++ b/src/tools/rcc/main.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
@@ -127,10 +128,25 @@ int runRcc(int argc, char *argv[])
QCommandLineOption rootOption(QStringLiteral("root"), QStringLiteral("Prefix resource access path with root path."), QStringLiteral("path"));
parser.addOption(rootOption);
+#if QT_CONFIG(zstd) && !defined(QT_NO_COMPRESS)
+# define ALGOS "[zstd], zlib, none"
+#elif QT_CONFIG(zstd)
+# define ALGOS "[zstd], none"
+#elif !defined(QT_NO_COMPRESS)
+# define ALGOS "[zlib], none"
+#else
+# define ALGOS "[none]"
+#endif
+ const QString &algoDescription =
+ QStringLiteral("Compress input files using algorithm <algo> (" ALGOS ").");
+ QCommandLineOption compressionAlgoOption(QStringLiteral("compress-algo"), algoDescription, QStringLiteral("algo"));
+ parser.addOption(compressionAlgoOption);
+#undef ALGOS
+
QCommandLineOption compressOption(QStringLiteral("compress"), QStringLiteral("Compress input files by <level>."), QStringLiteral("level"));
parser.addOption(compressOption);
- QCommandLineOption nocompressOption(QStringLiteral("no-compress"), QStringLiteral("Disable all compression."));
+ QCommandLineOption nocompressOption(QStringLiteral("no-compress"), QStringLiteral("Disable all compression. Same as --compress-algo=none."));
parser.addOption(nocompressOption);
QCommandLineOption thresholdOption(QStringLiteral("threshold"), QStringLiteral("Threshold to consider compressing files."), QStringLiteral("level"));
@@ -139,6 +155,11 @@ int runRcc(int argc, char *argv[])
QCommandLineOption binaryOption(QStringLiteral("binary"), QStringLiteral("Output a binary file for use as a dynamic resource."));
parser.addOption(binaryOption);
+ QCommandLineOption generatorOption(QStringList{QStringLiteral("g"), QStringLiteral("generator")});
+ generatorOption.setDescription(QStringLiteral("Select generator."));
+ generatorOption.setValueName(QStringLiteral("cpp|python|python2"));
+ parser.addOption(generatorOption);
+
QCommandLineOption passOption(QStringLiteral("pass"), QStringLiteral("Pass number for big resources"), QStringLiteral("number"));
parser.addOption(passOption);
@@ -169,13 +190,13 @@ int runRcc(int argc, char *argv[])
QString errorMsg;
- quint8 formatVersion = 2;
+ quint8 formatVersion = 3;
if (parser.isSet(formatVersionOption)) {
bool ok = false;
formatVersion = parser.value(formatVersionOption).toUInt(&ok);
if (!ok) {
errorMsg = QLatin1String("Invalid format version specified");
- } else if (formatVersion != 1 && formatVersion != 2) {
+ } else if (formatVersion < 1 || formatVersion > 3) {
errorMsg = QLatin1String("Unsupported format version specified");
}
}
@@ -189,14 +210,33 @@ int runRcc(int argc, char *argv[])
|| library.resourceRoot().at(0) != QLatin1Char('/'))
errorMsg = QLatin1String("Root must start with a /");
}
- if (parser.isSet(compressOption))
- library.setCompressLevel(parser.value(compressOption).toInt());
+
+ if (parser.isSet(compressionAlgoOption))
+ library.setCompressionAlgorithm(RCCResourceLibrary::parseCompressionAlgorithm(parser.value(compressionAlgoOption), &errorMsg));
+ if (formatVersion < 3 && library.compressionAlgorithm() == RCCResourceLibrary::CompressionAlgorithm::Zstd)
+ errorMsg = QLatin1String("Zstandard compression requires format version 3 or higher");
if (parser.isSet(nocompressOption))
- library.setCompressLevel(-2);
+ library.setCompressionAlgorithm(RCCResourceLibrary::CompressionAlgorithm::None);
+ if (parser.isSet(compressOption) && errorMsg.isEmpty()) {
+ int level = library.parseCompressionLevel(library.compressionAlgorithm(), parser.value(compressOption), &errorMsg);
+ library.setCompressLevel(level);
+ }
if (parser.isSet(thresholdOption))
library.setCompressThreshold(parser.value(thresholdOption).toInt());
if (parser.isSet(binaryOption))
library.setFormat(RCCResourceLibrary::Binary);
+ if (parser.isSet(generatorOption)) {
+ auto value = parser.value(generatorOption);
+ if (value == QLatin1String("cpp"))
+ library.setFormat(RCCResourceLibrary::C_Code);
+ else if (value == QLatin1String("python"))
+ library.setFormat(RCCResourceLibrary::Python3_Code);
+ else if (value == QLatin1String("python2"))
+ library.setFormat(RCCResourceLibrary::Python2_Code);
+ else
+ errorMsg = QLatin1String("Invalid generator: ") + value;
+ }
+
if (parser.isSet(passOption)) {
if (parser.value(passOption) == QLatin1String("1"))
library.setFormat(RCCResourceLibrary::Pass1);
@@ -257,6 +297,8 @@ int runRcc(int argc, char *argv[])
switch (library.format()) {
case RCCResourceLibrary::C_Code:
case RCCResourceLibrary::Pass1:
+ case RCCResourceLibrary::Python3_Code:
+ case RCCResourceLibrary::Python2_Code:
mode = QIODevice::WriteOnly | QIODevice::Text;
break;
case RCCResourceLibrary::Pass2:
diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp
index 1a7cab01df..94f6911010 100644
--- a/src/tools/rcc/rcc.cpp
+++ b/src/tools/rcc/rcc.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
@@ -36,11 +37,16 @@
#include <qfile.h>
#include <qiodevice.h>
#include <qlocale.h>
+#include <qregexp.h>
#include <qstack.h>
#include <qxmlstream.h>
#include <algorithm>
+#if QT_CONFIG(zstd)
+# include <zstd.h>
+#endif
+
// Note: A copy of this file is used in Qt Designer (qttools/src/designer/src/lib/shared/rcc.cpp)
QT_BEGIN_NAMESPACE
@@ -48,15 +54,21 @@ QT_BEGIN_NAMESPACE
enum {
CONSTANT_USENAMESPACE = 1,
CONSTANT_COMPRESSLEVEL_DEFAULT = -1,
+ CONSTANT_ZSTDCOMPRESSLEVEL_CHECK = 1, // Zstd level to check if compressing is a good idea
+ CONSTANT_ZSTDCOMPRESSLEVEL_STORE = 14, // Zstd level to actually store the data
CONSTANT_COMPRESSTHRESHOLD_DEFAULT = 70
};
-
-#define writeString(s) write(s, sizeof(s))
+#if QT_CONFIG(zstd)
+# define CONSTANT_COMPRESSALGO_DEFAULT RCCResourceLibrary::CompressionAlgorithm::Zstd
+#elif !defined(QT_NO_COMPRESS)
+# define CONSTANT_COMPRESSALGO_DEFAULT RCCResourceLibrary::CompressionAlgorithm::Zlib
+#else
+# define CONSTANT_COMPRESSALGO_DEFAULT RCCResourceLibrary::CompressionAlgorithm::None
+#endif
void RCCResourceLibrary::write(const char *str, int len)
{
- --len; // trailing \0 on string literals...
int n = m_out.size();
m_out.resize(n + len);
memcpy(m_out.data() + n, str, len);
@@ -88,15 +100,18 @@ class RCCFileInfo
public:
enum Flags
{
+ // must match qresource.cpp
NoFlags = 0x00,
Compressed = 0x01,
- Directory = 0x02
+ Directory = 0x02,
+ CompressedZstd = 0x04
};
RCCFileInfo(const QString &name = QString(), const QFileInfo &fileInfo = QFileInfo(),
QLocale::Language language = QLocale::C,
QLocale::Country country = QLocale::AnyCountry,
uint flags = NoFlags,
+ RCCResourceLibrary::CompressionAlgorithm compressAlgo = CONSTANT_COMPRESSALGO_DEFAULT,
int compressLevel = CONSTANT_COMPRESSLEVEL_DEFAULT,
int compressThreshold = CONSTANT_COMPRESSTHRESHOLD_DEFAULT);
~RCCFileInfo();
@@ -115,6 +130,7 @@ public:
QFileInfo m_fileInfo;
RCCFileInfo *m_parent;
QHash<QString, RCCFileInfo*> m_children;
+ RCCResourceLibrary::CompressionAlgorithm m_compressAlgo;
int m_compressLevel;
int m_compressThreshold;
@@ -125,7 +141,7 @@ public:
RCCFileInfo::RCCFileInfo(const QString &name, const QFileInfo &fileInfo,
QLocale::Language language, QLocale::Country country, uint flags,
- int compressLevel, int compressThreshold)
+ RCCResourceLibrary::CompressionAlgorithm compressAlgo, int compressLevel, int compressThreshold)
{
m_name = name;
m_fileInfo = fileInfo;
@@ -136,6 +152,7 @@ RCCFileInfo::RCCFileInfo(const QString &name, const QFileInfo &fileInfo,
m_nameOffset = 0;
m_dataOffset = 0;
m_childOffset = 0;
+ m_compressAlgo = compressAlgo;
m_compressLevel = compressLevel;
m_compressThreshold = compressThreshold;
}
@@ -157,6 +174,8 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
{
const bool text = lib.m_format == RCCResourceLibrary::C_Code;
const bool pass1 = lib.m_format == RCCResourceLibrary::Pass1;
+ const bool python = lib.m_format == RCCResourceLibrary::Python3_Code
+ || lib.m_format == RCCResourceLibrary::Python2_Code;
//some info
if (text || pass1) {
if (m_language != QLocale::C) {
@@ -203,6 +222,8 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
}
if (text || pass1)
lib.writeChar('\n');
+ else if (python)
+ lib.writeString("\\\n");
if (lib.formatVersion() >= 2) {
// last modified time stamp
@@ -211,9 +232,14 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
static const quint64 sourceDate = 1000 * qgetenv("QT_RCC_SOURCE_DATE_OVERRIDE").toULongLong();
if (sourceDate != 0)
lastmod = sourceDate;
+ static const quint64 sourceDate2 = 1000 * qgetenv("SOURCE_DATE_EPOCH").toULongLong();
+ if (sourceDate2 != 0)
+ lastmod = sourceDate2;
lib.writeNumber8(lastmod);
if (text || pass1)
lib.writeChar('\n');
+ else if (python)
+ lib.writeString("\\\n");
}
}
@@ -224,6 +250,8 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
const bool pass1 = lib.m_format == RCCResourceLibrary::Pass1;
const bool pass2 = lib.m_format == RCCResourceLibrary::Pass2;
const bool binary = lib.m_format == RCCResourceLibrary::Binary;
+ const bool python = lib.m_format == RCCResourceLibrary::Python3_Code
+ || lib.m_format == RCCResourceLibrary::Python2_Code;
//capture the offset
m_dataOffset = offset;
@@ -236,19 +264,82 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
}
QByteArray data = file.readAll();
-#ifndef QT_NO_COMPRESS
// Check if compression is useful for this file
- if (m_compressLevel != 0 && data.size() != 0) {
- QByteArray compressed =
- qCompress(reinterpret_cast<uchar *>(data.data()), data.size(), m_compressLevel);
-
- int compressRatio = int(100.0 * (data.size() - compressed.size()) / data.size());
- if (compressRatio >= m_compressThreshold) {
- data = compressed;
- m_flags |= Compressed;
+ if (data.size() != 0) {
+#if QT_CONFIG(zstd)
+ if (m_compressAlgo == RCCResourceLibrary::CompressionAlgorithm::Best) {
+ m_compressAlgo = RCCResourceLibrary::CompressionAlgorithm::Zstd;
+ m_compressLevel = 19; // not ZSTD_maxCLevel(), as 20+ are experimental
+ }
+ if (m_compressAlgo == RCCResourceLibrary::CompressionAlgorithm::Zstd) {
+ if (lib.m_zstdCCtx == nullptr)
+ lib.m_zstdCCtx = ZSTD_createCCtx();
+ qsizetype size = data.size();
+ size = ZSTD_COMPRESSBOUND(size);
+
+ int compressLevel = m_compressLevel;
+ if (compressLevel < 0)
+ compressLevel = CONSTANT_ZSTDCOMPRESSLEVEL_CHECK;
+
+ QByteArray compressed(size, Qt::Uninitialized);
+ char *dst = const_cast<char *>(compressed.constData());
+ size_t n = ZSTD_compressCCtx(lib.m_zstdCCtx, dst, size,
+ data.constData(), data.size(),
+ compressLevel);
+ if (n * 100.0 < data.size() * 1.0 * (100 - m_compressThreshold) ) {
+ // compressing is worth it
+ if (m_compressLevel < 0) {
+ // heuristic compression, so recompress
+ n = ZSTD_compressCCtx(lib.m_zstdCCtx, dst, size,
+ data.constData(), data.size(),
+ CONSTANT_ZSTDCOMPRESSLEVEL_STORE);
+ }
+ if (ZSTD_isError(n)) {
+ QString msg = QString::fromLatin1("%1: error: compression with zstd failed: %2\n")
+ .arg(m_name, QString::fromUtf8(ZSTD_getErrorName(n)));
+ lib.m_errorDevice->write(msg.toUtf8());
+ } else if (lib.verbose()) {
+ QString msg = QString::fromLatin1("%1: note: compressed using zstd (%2 -> %3)\n")
+ .arg(m_name).arg(data.size()).arg(n);
+ lib.m_errorDevice->write(msg.toUtf8());
+ }
+
+ lib.m_overallFlags |= CompressedZstd;
+ m_flags |= CompressedZstd;
+ data = std::move(compressed);
+ data.truncate(n);
+ } else if (lib.verbose()) {
+ QString msg = QString::fromLatin1("%1: note: not compressed\n").arg(m_name);
+ lib.m_errorDevice->write(msg.toUtf8());
+ }
+ }
+#endif
+#ifndef QT_NO_COMPRESS
+ if (m_compressAlgo == RCCResourceLibrary::CompressionAlgorithm::Best) {
+ m_compressAlgo = RCCResourceLibrary::CompressionAlgorithm::Zlib;
+ m_compressLevel = 9;
+ }
+ if (m_compressAlgo == RCCResourceLibrary::CompressionAlgorithm::Zlib) {
+ QByteArray compressed =
+ qCompress(reinterpret_cast<uchar *>(data.data()), data.size(), m_compressLevel);
+
+ int compressRatio = int(100.0 * (data.size() - compressed.size()) / data.size());
+ if (compressRatio >= m_compressThreshold) {
+ if (lib.verbose()) {
+ QString msg = QString::fromLatin1("%1: note: compressed using zlib (%2 -> %3)\n")
+ .arg(m_name).arg(data.size()).arg(compressed.size());
+ lib.m_errorDevice->write(msg.toUtf8());
+ }
+ data = compressed;
+ lib.m_overallFlags |= Compressed;
+ m_flags |= Compressed;
+ } else if (lib.verbose()) {
+ QString msg = QString::fromLatin1("%1: note: not compressed\n").arg(m_name);
+ lib.m_errorDevice->write(msg.toUtf8());
+ }
}
- }
#endif // QT_NO_COMPRESS
+ }
// some info
if (text || pass1) {
@@ -258,20 +349,24 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
}
// write the length
-
- if (text || binary || pass2)
+ if (text || binary || pass2 || python)
lib.writeNumber4(data.size());
if (text || pass1)
lib.writeString("\n ");
+ else if (python)
+ lib.writeString("\\\n");
offset += 4;
// write the payload
const char *p = data.constData();
- if (text) {
+ if (text || python) {
for (int i = data.size(), j = 0; --i >= 0; --j) {
lib.writeHex(*p++);
if (j == 0) {
- lib.writeString("\n ");
+ if (text)
+ lib.writeString("\n ");
+ else
+ lib.writeString("\\\n");
j = 16;
}
}
@@ -283,6 +378,9 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
// done
if (text || pass1)
lib.writeString("\n ");
+ else if (python)
+ lib.writeString("\\\n");
+
return offset;
}
@@ -290,6 +388,8 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
{
const bool text = lib.m_format == RCCResourceLibrary::C_Code;
const bool pass1 = lib.m_format == RCCResourceLibrary::Pass1;
+ const bool python = lib.m_format == RCCResourceLibrary::Python3_Code
+ || lib.m_format == RCCResourceLibrary::Python2_Code;
// capture the offset
m_nameOffset = offset;
@@ -305,12 +405,16 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
lib.writeNumber2(m_name.length());
if (text || pass1)
lib.writeString("\n ");
+ else if (python)
+ lib.writeString("\\\n");
offset += 2;
// write the hash
lib.writeNumber4(qt_hash(m_name));
if (text || pass1)
lib.writeString("\n ");
+ else if (python)
+ lib.writeString("\\\n");
offset += 4;
// write the m_name
@@ -319,12 +423,17 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset)
lib.writeNumber2(unicode[i].unicode());
if ((text || pass1) && i % 16 == 0)
lib.writeString("\n ");
+ else if (python && i % 16 == 0)
+ lib.writeString("\\\n");
}
offset += m_name.length()*2;
// done
if (text || pass1)
lib.writeString("\n ");
+ else if (python)
+ lib.writeString("\\\n");
+
return offset;
}
@@ -343,7 +452,8 @@ RCCResourceLibrary::Strings::Strings() :
ATTRIBUTE_PREFIX(QLatin1String("prefix")),
ATTRIBUTE_ALIAS(QLatin1String("alias")),
ATTRIBUTE_THRESHOLD(QLatin1String("threshold")),
- ATTRIBUTE_COMPRESS(QLatin1String("compress"))
+ ATTRIBUTE_COMPRESS(QLatin1String("compress")),
+ ATTRIBUTE_COMPRESSALGO(QStringLiteral("compression-algorithm"))
{
}
@@ -351,22 +461,30 @@ RCCResourceLibrary::RCCResourceLibrary(quint8 formatVersion)
: m_root(0),
m_format(C_Code),
m_verbose(false),
+ m_compressionAlgo(CONSTANT_COMPRESSALGO_DEFAULT),
m_compressLevel(CONSTANT_COMPRESSLEVEL_DEFAULT),
m_compressThreshold(CONSTANT_COMPRESSTHRESHOLD_DEFAULT),
m_treeOffset(0),
m_namesOffset(0),
m_dataOffset(0),
+ m_overallFlags(0),
m_useNameSpace(CONSTANT_USENAMESPACE),
m_errorDevice(0),
m_outDevice(0),
m_formatVersion(formatVersion)
{
m_out.reserve(30 * 1000 * 1000);
+#if QT_CONFIG(zstd)
+ m_zstdCCtx = nullptr;
+#endif
}
RCCResourceLibrary::~RCCResourceLibrary()
{
delete m_root;
+#if QT_CONFIG(zstd)
+ ZSTD_freeCCtx(m_zstdCCtx);
+#endif
}
enum RCCXmlTag {
@@ -391,6 +509,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
QLocale::Language language = QLocale::c().language();
QLocale::Country country = QLocale::c().country();
QString alias;
+ auto compressAlgo = m_compressionAlgo;
int compressLevel = m_compressLevel;
int compressThreshold = m_compressThreshold;
@@ -444,17 +563,27 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
if (attributes.hasAttribute(m_strings.ATTRIBUTE_ALIAS))
alias = attributes.value(m_strings.ATTRIBUTE_ALIAS).toString();
+ compressAlgo = m_compressionAlgo;
compressLevel = m_compressLevel;
- if (attributes.hasAttribute(m_strings.ATTRIBUTE_COMPRESS))
- compressLevel = attributes.value(m_strings.ATTRIBUTE_COMPRESS).toString().toInt();
-
compressThreshold = m_compressThreshold;
+
+ QString errorString;
+ if (attributes.hasAttribute(m_strings.ATTRIBUTE_COMPRESSALGO))
+ compressAlgo = parseCompressionAlgorithm(attributes.value(m_strings.ATTRIBUTE_COMPRESSALGO), &errorString);
+ if (errorString.isEmpty() && attributes.hasAttribute(m_strings.ATTRIBUTE_COMPRESS)) {
+ QString value = attributes.value(m_strings.ATTRIBUTE_COMPRESS).toString();
+ compressLevel = parseCompressionLevel(compressAlgo, value, &errorString);
+ }
+
+ // Special case for -no-compress
+ if (m_compressLevel == -2)
+ compressAlgo = CompressionAlgorithm::None;
+
if (attributes.hasAttribute(m_strings.ATTRIBUTE_THRESHOLD))
compressThreshold = attributes.value(m_strings.ATTRIBUTE_THRESHOLD).toString().toInt();
- // Special case for -no-compress. Overrides all other settings.
- if (m_compressLevel == -2)
- compressLevel = 0;
+ if (!errorString.isEmpty())
+ reader.raiseError(errorString);
}
} else {
reader.raiseError(QString(QLatin1String("unexpected tag: %1")).arg(reader.name().toString()));
@@ -520,6 +649,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
language,
country,
child.isDir() ? RCCFileInfo::Directory : RCCFileInfo::NoFlags,
+ compressAlgo,
compressLevel,
compressThreshold)
);
@@ -535,6 +665,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
language,
country,
RCCFileInfo::NoFlags,
+ compressAlgo,
compressLevel,
compressThreshold)
);
@@ -729,6 +860,55 @@ RCCResourceLibrary::ResourceDataFileMap RCCResourceLibrary::resourceDataFileMap(
return rc;
}
+RCCResourceLibrary::CompressionAlgorithm RCCResourceLibrary::parseCompressionAlgorithm(QStringView value, QString *errorMsg)
+{
+ if (value == QLatin1String("best"))
+ return CompressionAlgorithm::Best;
+ if (value == QLatin1String("zlib")) {
+#ifdef QT_NO_COMPRESS
+ *errorMsg = QLatin1String("zlib support not compiled in");
+#else
+ return CompressionAlgorithm::Zlib;
+#endif
+ } else if (value == QLatin1String("zstd")) {
+#if QT_CONFIG(zstd)
+ return CompressionAlgorithm::Zstd;
+#else
+ *errorMsg = QLatin1String("Zstandard support not compiled in");
+#endif
+ } else if (value != QLatin1String("none")) {
+ *errorMsg = QString::fromLatin1("Unknown compression algorithm '%1'").arg(value);
+ }
+
+ return CompressionAlgorithm::None;
+}
+
+int RCCResourceLibrary::parseCompressionLevel(CompressionAlgorithm algo, const QString &level, QString *errorMsg)
+{
+ bool ok;
+ int c = level.toInt(&ok);
+ if (ok) {
+ switch (algo) {
+ case CompressionAlgorithm::None:
+ case CompressionAlgorithm::Best:
+ return 0;
+ case CompressionAlgorithm::Zlib:
+ if (c >= 1 && c <= 9)
+ return c;
+ break;
+ case CompressionAlgorithm::Zstd:
+#if QT_CONFIG(zstd)
+ if (c >= 0 && c <= ZSTD_maxCLevel())
+ return c;
+#endif
+ break;
+ }
+ }
+
+ *errorMsg = QString::fromLatin1("invalid compression level '%1'").arg(level);
+ return 0;
+}
+
bool RCCResourceLibrary::output(QIODevice &outDevice, QIODevice &tempDevice, QIODevice &errorDevice)
{
m_errorDevice = &errorDevice;
@@ -795,18 +975,45 @@ bool RCCResourceLibrary::output(QIODevice &outDevice, QIODevice &tempDevice, QIO
return true;
}
+void RCCResourceLibrary::writeDecimal(int value)
+{
+ Q_ASSERT(m_format != RCCResourceLibrary::Binary);
+ char buf[std::numeric_limits<int>::digits10 + 2];
+ int n = snprintf(buf, sizeof(buf), "%d", value);
+ write(buf, n);
+}
+
+static const char hexDigits[] = "0123456789abcdef";
+
+inline void RCCResourceLibrary::write2HexDigits(quint8 number)
+{
+ writeChar(hexDigits[number >> 4]);
+ writeChar(hexDigits[number & 0xf]);
+}
+
void RCCResourceLibrary::writeHex(quint8 tmp)
{
- const char digits[] = "0123456789abcdef";
- writeChar('0');
- writeChar('x');
- if (tmp < 16) {
- writeChar(digits[tmp]);
- } else {
- writeChar(digits[tmp >> 4]);
- writeChar(digits[tmp & 0xf]);
+ switch (m_format) {
+ case RCCResourceLibrary::Python3_Code:
+ case RCCResourceLibrary::Python2_Code:
+ if (tmp >= 32 && tmp < 127 && tmp != '"' && tmp != '\\') {
+ writeChar(char(tmp));
+ } else {
+ writeChar('\\');
+ writeChar('x');
+ write2HexDigits(tmp);
+ }
+ break;
+ default:
+ writeChar('0');
+ writeChar('x');
+ if (tmp < 16)
+ writeChar(hexDigits[tmp]);
+ else
+ write2HexDigits(tmp);
+ writeChar(',');
+ break;
}
- writeChar(',');
}
void RCCResourceLibrary::writeNumber2(quint16 number)
@@ -874,7 +1081,9 @@ void RCCResourceLibrary::writeNumber8(quint64 number)
bool RCCResourceLibrary::writeHeader()
{
- if (m_format == C_Code || m_format == Pass1) {
+ switch (m_format) {
+ case C_Code:
+ case Pass1:
writeString("/****************************************************************************\n");
writeString("** Resource object code\n");
writeString("**\n");
@@ -883,12 +1092,30 @@ bool RCCResourceLibrary::writeHeader()
writeString("\n**\n");
writeString("** WARNING! All changes made in this file will be lost!\n");
writeString( "*****************************************************************************/\n\n");
- } else if (m_format == Binary) {
+ break;
+ case Python3_Code:
+ case Python2_Code:
+ writeString("# Resource object code (Python ");
+ writeChar(m_format == Python3_Code ? '3' : '2');
+ writeString(")\n");
+ writeString("# Created by: object code\n");
+ writeString("# Created by: The Resource Compiler for Qt version ");
+ writeByteArray(QT_VERSION_STR);
+ writeString("\n");
+ writeString("# WARNING! All changes made in this file will be lost!\n\n");
+ writeString("from PySide2 import QtCore\n\n");
+ break;
+ case Binary:
writeString("qres");
writeNumber4(0);
writeNumber4(0);
writeNumber4(0);
writeNumber4(0);
+ if (m_formatVersion >= 3)
+ writeNumber4(m_overallFlags);
+ break;
+ default:
+ break;
}
return true;
}
@@ -896,10 +1123,21 @@ bool RCCResourceLibrary::writeHeader()
bool RCCResourceLibrary::writeDataBlobs()
{
Q_ASSERT(m_errorDevice);
- if (m_format == C_Code) {
+ switch (m_format) {
+ case C_Code:
writeString("static const unsigned char qt_resource_data[] = {\n");
- } else if (m_format == Binary) {
+ break;
+ case Python3_Code:
+ writeString("qt_resource_data = b\"\\\n");
+ break;
+ case Python2_Code:
+ writeString("qt_resource_data = \"\\\n");
+ break;
+ case Binary:
m_dataOffset = m_out.size();
+ break;
+ default:
+ break;
}
if (!m_root)
@@ -925,24 +1163,46 @@ bool RCCResourceLibrary::writeDataBlobs()
}
}
}
- if (m_format == C_Code)
+ switch (m_format) {
+ case C_Code:
writeString("\n};\n\n");
- else if (m_format == Pass1) {
+ break;
+ case Python3_Code:
+ case Python2_Code:
+ writeString("\"\n\n");
+ break;
+ case Pass1:
if (offset < 8)
offset = 8;
writeString("\nstatic const unsigned char qt_resource_data[");
writeByteArray(QByteArray::number(offset));
writeString("] = { 'Q', 'R', 'C', '_', 'D', 'A', 'T', 'A' };\n\n");
+ break;
+ default:
+ break;
}
return true;
}
bool RCCResourceLibrary::writeDataNames()
{
- if (m_format == C_Code || m_format == Pass1)
+ switch (m_format) {
+ case C_Code:
+ case Pass1:
writeString("static const unsigned char qt_resource_name[] = {\n");
- else if (m_format == Binary)
+ break;
+ case Python3_Code:
+ writeString("qt_resource_name = b\"\\\n");
+ break;
+ case Python2_Code:
+ writeString("qt_resource_name = \"\\\n");
+ break;
+ case Binary:
m_namesOffset = m_out.size();
+ break;
+ default:
+ break;
+ }
QHash<QString, int> names;
QStack<RCCFileInfo*> pending;
@@ -967,8 +1227,18 @@ bool RCCResourceLibrary::writeDataNames()
}
}
}
- if (m_format == C_Code || m_format == Pass1)
+ switch (m_format) {
+ case C_Code:
+ case Pass1:
writeString("\n};\n\n");
+ break;
+ case Python3_Code:
+ case Python2_Code:
+ writeString("\"\n\n");
+ break;
+ default:
+ break;
+ }
return true;
}
@@ -983,10 +1253,24 @@ struct qt_rcc_compare_hash
bool RCCResourceLibrary::writeDataStructure()
{
- if (m_format == C_Code || m_format == Pass1)
+ switch (m_format) {
+ case C_Code:
+ case Pass1:
writeString("static const unsigned char qt_resource_struct[] = {\n");
- else if (m_format == Binary)
+ break;
+ case Python3_Code:
+ writeString("qt_resource_struct = b\"\\\n");
+ break;
+ case Python2_Code:
+ writeString("qt_resource_struct = \"\\\n");
+ break;
+ case Binary:
m_treeOffset = m_out.size();
+ break;
+ default:
+ break;
+ }
+
QStack<RCCFileInfo*> pending;
if (!m_root)
@@ -1030,8 +1314,18 @@ bool RCCResourceLibrary::writeDataStructure()
pending.push(child);
}
}
- if (m_format == C_Code || m_format == Pass1)
+ switch (m_format) {
+ case C_Code:
+ case Pass1:
writeString("\n};\n\n");
+ break;
+ case Python3_Code:
+ case Python2_Code:
+ writeString("\"\n\n");
+ break;
+ default:
+ break;
+ }
return true;
}
@@ -1091,10 +1385,35 @@ bool RCCResourceLibrary::writeInitializer()
if (m_root) {
writeString("bool qRegisterResourceData"
"(int, const unsigned char *, "
- "const unsigned char *, const unsigned char *);\n\n");
+ "const unsigned char *, const unsigned char *);\n");
writeString("bool qUnregisterResourceData"
"(int, const unsigned char *, "
"const unsigned char *, const unsigned char *);\n\n");
+
+ if (m_overallFlags & (RCCFileInfo::Compressed | RCCFileInfo::CompressedZstd)) {
+ // use variable relocations with ELF and Mach-O
+ writeString("#if defined(__ELF__) || defined(__APPLE__)\n");
+ if (m_overallFlags & RCCFileInfo::Compressed) {
+ writeString("static inline unsigned char qResourceFeatureZlib()\n"
+ "{\n"
+ " extern const unsigned char qt_resourceFeatureZlib;\n"
+ " return qt_resourceFeatureZlib;\n"
+ "}\n");
+ }
+ if (m_overallFlags & RCCFileInfo::CompressedZstd) {
+ writeString("static inline unsigned char qResourceFeatureZstd()\n"
+ "{\n"
+ " extern const unsigned char qt_resourceFeatureZstd;\n"
+ " return qt_resourceFeatureZstd;\n"
+ "}\n");
+ }
+ writeString("#else\n");
+ if (m_overallFlags & RCCFileInfo::Compressed)
+ writeString("unsigned char qResourceFeatureZlib();\n");
+ if (m_overallFlags & RCCFileInfo::CompressedZstd)
+ writeString("unsigned char qResourceFeatureZstd();\n");
+ writeString("#endif\n\n");
+ }
}
if (m_useNameSpace)
@@ -1113,12 +1432,12 @@ bool RCCResourceLibrary::writeInitializer()
writeString("()\n{\n");
if (m_root) {
- writeString(" ");
+ writeString(" int version = ");
+ writeDecimal(m_formatVersion);
+ writeString(";\n ");
writeAddNamespaceFunction("qRegisterResourceData");
- writeString("\n (");
- writeHex(m_formatVersion);
- writeString(" qt_resource_struct, "
- "qt_resource_name, qt_resource_data);\n");
+ writeString("\n (version, qt_resource_struct, "
+ "qt_resource_name, qt_resource_data);\n");
}
writeString(" return 1;\n");
writeString("}\n\n");
@@ -1136,11 +1455,24 @@ bool RCCResourceLibrary::writeInitializer()
writeMangleNamespaceFunction(cleanResources);
writeString("()\n{\n");
if (m_root) {
- writeString(" ");
+ writeString(" int version = ");
+ writeDecimal(m_formatVersion);
+ writeString(";\n ");
+
+ // ODR-use certain symbols from QtCore if we require optional features
+ if (m_overallFlags & RCCFileInfo::Compressed) {
+ writeString("version += ");
+ writeAddNamespaceFunction("qResourceFeatureZlib()");
+ writeString(";\n ");
+ }
+ if (m_overallFlags & RCCFileInfo::CompressedZstd) {
+ writeString("version += ");
+ writeAddNamespaceFunction("qResourceFeatureZstd()");
+ writeString(";\n ");
+ }
+
writeAddNamespaceFunction("qUnregisterResourceData");
- writeString("\n (");
- writeHex(m_formatVersion);
- writeString(" qt_resource_struct, "
+ writeString("\n (version, qt_resource_struct, "
"qt_resource_name, qt_resource_data);\n");
}
writeString(" return 1;\n");
@@ -1176,6 +1508,23 @@ bool RCCResourceLibrary::writeInitializer()
p[i++] = (m_namesOffset >> 16) & 0xff;
p[i++] = (m_namesOffset >> 8) & 0xff;
p[i++] = (m_namesOffset >> 0) & 0xff;
+
+ if (m_formatVersion >= 3) {
+ p[i++] = (m_overallFlags >> 24) & 0xff;
+ p[i++] = (m_overallFlags >> 16) & 0xff;
+ p[i++] = (m_overallFlags >> 8) & 0xff;
+ p[i++] = (m_overallFlags >> 0) & 0xff;
+ }
+ } else if (m_format == Python3_Code || m_format == Python2_Code) {
+ writeString("def qInitResources():\n");
+ writeString(" QtCore.qRegisterResourceData(0x");
+ write2HexDigits(m_formatVersion);
+ writeString(", qt_resource_struct, qt_resource_name, qt_resource_data)\n\n");
+ writeString("def qCleanupResources():\n");
+ writeString(" QtCore.qUnregisterResourceData(0x");
+ write2HexDigits(m_formatVersion);
+ writeString(", qt_resource_struct, qt_resource_name, qt_resource_data)\n\n");
+ writeString("qInitResources()\n");
}
return true;
}
diff --git a/src/tools/rcc/rcc.h b/src/tools/rcc/rcc.h
index 36984cf38a..190c37a1f6 100644
--- a/src/tools/rcc/rcc.h
+++ b/src/tools/rcc/rcc.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
@@ -35,6 +36,8 @@
#include <qhash.h>
#include <qstring.h>
+typedef struct ZSTD_CCtx_s ZSTD_CCtx;
+
QT_BEGIN_NAMESPACE
class RCCFileInfo;
@@ -55,7 +58,7 @@ public:
bool readFiles(bool listMode, QIODevice &errorDevice);
- enum Format { Binary, C_Code, Pass1, Pass2 };
+ enum Format { Binary, C_Code, Pass1, Pass2, Python3_Code, Python2_Code };
void setFormat(Format f) { m_format = f; }
Format format() const { return m_format; }
@@ -77,6 +80,19 @@ public:
void setOutputName(const QString &name) { m_outputName = name; }
QString outputName() const { return m_outputName; }
+ enum class CompressionAlgorithm {
+ Zlib,
+ Zstd,
+
+ Best = 99,
+ None = -1
+ };
+
+ static CompressionAlgorithm parseCompressionAlgorithm(QStringView algo, QString *errorMsg);
+ void setCompressionAlgorithm(CompressionAlgorithm algo) { m_compressionAlgo = algo; }
+ CompressionAlgorithm compressionAlgorithm() const { return m_compressionAlgo; }
+
+ static int parseCompressionLevel(CompressionAlgorithm algo, const QString &level, QString *errorMsg);
void setCompressLevel(int c) { m_compressLevel = c; }
int compressLevel() const { return m_compressLevel; }
@@ -104,6 +120,7 @@ private:
const QString ATTRIBUTE_ALIAS;
const QString ATTRIBUTE_THRESHOLD;
const QString ATTRIBUTE_COMPRESS;
+ const QString ATTRIBUTE_COMPRESSALGO;
};
friend class RCCFileInfo;
void reset();
@@ -117,13 +134,20 @@ private:
bool writeInitializer();
void writeMangleNamespaceFunction(const QByteArray &name);
void writeAddNamespaceFunction(const QByteArray &name);
+ void writeDecimal(int value);
void writeHex(quint8 number);
+ void write2HexDigits(quint8 number);
void writeNumber2(quint16 number);
void writeNumber4(quint32 number);
void writeNumber8(quint64 number);
void writeChar(char c) { m_out.append(c); }
void writeByteArray(const QByteArray &);
void write(const char *, int len);
+ void writeString(const char *s) { write(s, static_cast<int>(strlen(s))); }
+
+#if QT_CONFIG(zstd)
+ ZSTD_CCtx *m_zstdCCtx;
+#endif
const Strings m_strings;
RCCFileInfo *m_root;
@@ -133,11 +157,13 @@ private:
QString m_outputName;
Format m_format;
bool m_verbose;
+ CompressionAlgorithm m_compressionAlgo;
int m_compressLevel;
int m_compressThreshold;
int m_treeOffset;
int m_namesOffset;
int m_dataOffset;
+ quint32 m_overallFlags;
bool m_useNameSpace;
QStringList m_failedResources;
QIODevice *m_errorDevice;
diff --git a/src/tools/rcc/rcc.pro b/src/tools/rcc/rcc.pro
index 208ec54a73..ae55b5d8af 100644
--- a/src/tools/rcc/rcc.pro
+++ b/src/tools/rcc/rcc.pro
@@ -8,3 +8,14 @@ SOURCES += main.cpp
QMAKE_TARGET_DESCRIPTION = "Qt Resource Compiler"
load(qt_tool)
+
+# RCC is a bootstrapped tool, so qglobal.h #includes qconfig-bootstrapped.h
+# and that has a #define saying zstd isn't present (for qresource.cpp, which is
+# part of the bootstrap lib). So we inform the presence of the feature in the
+# command-line.
+qtConfig(zstd):!cross_compile {
+ DEFINES += QT_FEATURE_zstd=1
+ QMAKE_USE_PRIVATE += zstd
+} else {
+ DEFINES += QT_FEATURE_zstd=-1
+}
diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp
index e839137915..acd81bd5c1 100644
--- a/src/tools/tracegen/etw.cpp
+++ b/src/tools/tracegen/etw.cpp
@@ -45,7 +45,6 @@
#include <qfile.h>
#include <qfileinfo.h>
#include <qtextstream.h>
-#include <qregexp.h>
#include <quuid.h>
static inline QString providerVar(const QString &providerName)
diff --git a/src/tools/tracegen/helpers.cpp b/src/tools/tracegen/helpers.cpp
index f0ac7ed47f..a5526065d6 100644
--- a/src/tools/tracegen/helpers.cpp
+++ b/src/tools/tracegen/helpers.cpp
@@ -46,7 +46,7 @@ QString includeGuard(const QString &filename)
for (int i = 0; i < guard.size(); ++i) {
if (!guard.at(i).isLetterOrNumber())
- guard[i] = QChar('_');
+ guard[i] = QLatin1Char('_');
}
return guard;
diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp
index f0fbca9e16..1aef1b3d17 100644
--- a/src/tools/tracegen/lttng.cpp
+++ b/src/tools/tracegen/lttng.cpp
@@ -46,7 +46,6 @@
#include <qfile.h>
#include <qfileinfo.h>
#include <qtextstream.h>
-#include <qregexp.h>
#include <qdebug.h>
static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field)
diff --git a/src/tools/uic/cpp/cppwriteincludes.cpp b/src/tools/uic/cpp/cppwriteincludes.cpp
index d51fddffea..0ba49627c0 100644
--- a/src/tools/uic/cpp/cppwriteincludes.cpp
+++ b/src/tools/uic/cpp/cppwriteincludes.cpp
@@ -119,7 +119,7 @@ void WriteIncludes::acceptUI(DomUI *node)
writeHeaders(m_globalIncludes, true);
writeHeaders(m_localIncludes, false);
- m_output << QLatin1Char('\n');
+ m_output << '\n';
}
void WriteIncludes::acceptWidget(DomWidget *node)
@@ -214,14 +214,14 @@ void WriteIncludes::add(const QString &className, bool determineHeader, const QS
m_knownClasses.insert(className);
const CustomWidgetsInfo *cwi = m_uic->customWidgetsInfo();
- if (cwi->extends(className, QLatin1String("QTreeView"))
- || cwi->extends(className, QLatin1String("QTreeWidget"))
- || cwi->extends(className, QLatin1String("QTableView"))
- || cwi->extends(className, QLatin1String("QTableWidget"))) {
+ static const QStringList treeViewsWithHeaders = {
+ QLatin1String("QTreeView"), QLatin1String("QTreeWidget"),
+ QLatin1String("QTableView"), QLatin1String("QTableWidget")
+ };
+ if (cwi->extendsOneOf(className, treeViewsWithHeaders))
add(QLatin1String("QHeaderView"));
- }
- if (!m_laidOut && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox")))
+ if (!m_laidOut && cwi->extends(className, QLatin1String("QToolBox")))
add(QLatin1String("QLayout")); // spacing property of QToolBox)
if (className == QLatin1String("Line")) { // ### hmm, deprecate me!
@@ -314,7 +314,7 @@ void WriteIncludes::writeHeaders(const OrderedSet &headers, bool global)
const QString value = m_oldHeaderToNewHeader.value(header, header);
const auto trimmed = QStringRef(&value).trimmed();
if (!trimmed.isEmpty())
- m_output << "#include " << openingQuote << trimmed << closingQuote << QLatin1Char('\n');
+ m_output << "#include " << openingQuote << trimmed << closingQuote << '\n';
}
}
diff --git a/src/tools/uic/cpp/cppwriteincludes.h b/src/tools/uic/cpp/cppwriteincludes.h
index 7f03849798..aadc6f54fc 100644
--- a/src/tools/uic/cpp/cppwriteincludes.h
+++ b/src/tools/uic/cpp/cppwriteincludes.h
@@ -40,6 +40,7 @@
QT_BEGIN_NAMESPACE
class QTextStream;
+class CustomWidgetsInfo;
class Driver;
class Uic;
@@ -58,9 +59,9 @@ struct WriteIncludes : public TreeWalker
//
// actions
//
- void acceptActionGroup(DomActionGroup *node) Q_DECL_OVERRIDE;
- void acceptAction(DomAction *node) Q_DECL_OVERRIDE;
- void acceptActionRef(DomActionRef *node) Q_DECL_OVERRIDE;
+ void acceptActionGroup(DomActionGroup *node) override;
+ void acceptAction(DomAction *node) override;
+ void acceptActionRef(DomActionRef *node) override;
//
// custom widgets
@@ -74,11 +75,14 @@ struct WriteIncludes : public TreeWalker
void acceptIncludes(DomIncludes *node) override;
void acceptInclude(DomInclude *node) override;
+protected:
+ QTextStream &output() const { return m_output; }
+
private:
void add(const QString &className, bool determineHeader = true, const QString &header = QString(), bool global = false);
private:
- typedef std::set<QString> OrderedSet;
+ using OrderedSet = std::set<QString>;
void insertIncludeForClass(const QString &className, QString header = QString(), bool global = false);
void insertInclude(const QString &header, bool global);
void writeHeaders(const OrderedSet &headers, bool global);
@@ -93,7 +97,7 @@ private:
QSet<QString> m_knownClasses;
- typedef QMap<QString, QString> StringMap;
+ using StringMap = QMap<QString, QString>;
StringMap m_classToHeader;
StringMap m_oldHeaderToNewHeader;
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index 0adc91ddb9..85b9a9f60b 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -32,7 +32,8 @@
#include "utils.h"
#include "uic.h"
#include "databaseinfo.h"
-#include "globaldefs.h"
+
+#include <language.h>
#include <qtextstream.h>
#include <qversionnumber.h>
@@ -45,41 +46,32 @@
QT_BEGIN_NAMESPACE
namespace {
- // Fixup an enumeration name from class Qt.
- // They are currently stored as "BottomToolBarArea" instead of "Qt::BottomToolBarArea".
- // due to MO issues. This might be fixed in the future.
- QLatin1String qtEnumerationPrefix(const QString &name) {
- static const QLatin1String prefix("Qt::");
- if (name.indexOf(prefix) != 0)
- return prefix;
- return QLatin1String();
- }
// figure out the toolbar area of a DOM attrib list.
// By legacy, it is stored as an integer. As of 4.3.0, it is the enumeration value.
QString toolBarAreaStringFromDOMAttributes(const CPP::WriteInitialization::DomPropertyMap &attributes) {
const DomProperty *pstyle = attributes.value(QLatin1String("toolBarArea"));
+ QString result;
if (!pstyle)
- return QString();
-
+ return result;
switch (pstyle->kind()) {
- case DomProperty::Number: {
- return QLatin1String("static_cast<Qt::ToolBarArea>(")
- + QString::number(pstyle->elementNumber()) + QLatin1String("), ");
- }
- case DomProperty::Enum: {
- const QString area = pstyle->elementEnum();
- return qtEnumerationPrefix(area) + area + QLatin1String(", ");
- }
+ case DomProperty::Number:
+ result = QLatin1String(language::toolbarArea(pstyle->elementNumber()));
+ break;
+ case DomProperty::Enum:
+ result = pstyle->elementEnum();
+ break;
default:
break;
}
- return QString();
+ if (!result.startsWith(QLatin1String("Qt::")))
+ result.prepend(QLatin1String("Qt::"));
+ return result + QLatin1String(", ");
}
// Write a statement to create a spacer item.
void writeSpacerItem(const DomSpacer *node, QTextStream &output) {
const QHash<QString, DomProperty *> properties = propertyMap(node->elementProperty());
- output << "new QSpacerItem(";
+ output << language::operatorNew << "QSpacerItem(";
int w = 0;
int h = 0;
@@ -110,11 +102,9 @@ namespace {
if (orientation == QLatin1String("Qt::Vertical") || orientation == QLatin1String("Vertical"))
isVspacer = true;
}
-
- if (isVspacer)
- output << "QSizePolicy::Minimum, " << sizeType << ')';
- else
- output << sizeType << ", QSizePolicy::Minimum)";
+ const QString horizType = isVspacer ? QLatin1String("QSizePolicy::Minimum") : sizeType;
+ const QString vertType = isVspacer ? sizeType : QLatin1String("QSizePolicy::Minimum");
+ output << language::enumValue(horizType) << ", " << language::enumValue(vertType) << ')';
}
@@ -128,7 +118,8 @@ namespace {
// Write object->setFoo(x);
template <class Value>
void writeSetter(const QString &indent, const QString &varName,const QString &setter, Value v, QTextStream &str) {
- str << indent << varName << "->" << setter << '(' << v << ");\n";
+ str << indent << varName << language::derefPointer
+ << setter << '(' << v << ')' << language::eol;
}
static inline bool iconHasStatePixmaps(const DomResourceIcon *i) {
@@ -173,17 +164,16 @@ namespace {
}
return true;
}
-
- inline void openIfndef(QTextStream &str, const QString &symbol) { if (!symbol.isEmpty()) str << QLatin1String("#ifndef ") << symbol << endl; }
- inline void closeIfndef(QTextStream &str, const QString &symbol) { if (!symbol.isEmpty()) str << QLatin1String("#endif // ") << symbol << endl; }
-
- const char *accessibilityDefineC = "QT_NO_ACCESSIBILITY";
- const char *toolTipDefineC = "QT_NO_TOOLTIP";
- const char *whatsThisDefineC = "QT_NO_WHATSTHIS";
- const char *statusTipDefineC = "QT_NO_STATUSTIP";
- const char *shortcutDefineC = "QT_NO_SHORTCUT";
}
+// QtGui
+static inline QString accessibilityConfigKey() { return QStringLiteral("accessibility"); }
+static inline QString shortcutConfigKey() { return QStringLiteral("shortcut"); }
+static inline QString whatsThisConfigKey() { return QStringLiteral("whatsthis"); }
+// QtWidgets
+static inline QString statusTipConfigKey() { return QStringLiteral("statustip"); }
+static inline QString toolTipConfigKey() { return QStringLiteral("tooltip"); }
+
namespace CPP {
FontHandle::FontHandle(const DomFont *domFont) :
@@ -500,53 +490,50 @@ void WriteInitialization::acceptUI(DomUI *node)
const QString varName = m_driver->findOrInsertWidget(node->elementWidget());
m_mainFormVarName = varName;
- m_registeredWidgets.insert(varName, node->elementWidget()); // register the main widget
const QString widgetClassName = node->elementWidget()->attributeClass();
- m_output << m_option.indent << "void " << "setupUi(" << widgetClassName << " *" << varName << ")\n"
- << m_option.indent << "{\n";
+ const QString parameterType = widgetClassName + QLatin1String(" *");
+ m_output << m_option.indent
+ << language::startFunctionDefinition1("setupUi", parameterType, varName, m_option.indent);
const QStringList connections = m_uic->databaseInfo()->connections();
- for (int i=0; i<connections.size(); ++i) {
- QString connection = connections.at(i);
-
+ for (const auto &connection : connections) {
if (connection == QLatin1String("(default)"))
continue;
const QString varConn = connection + QLatin1String("Connection");
- m_output << m_indent << varConn << " = QSqlDatabase::database(" << fixString(connection, m_dindent) << ");\n";
+ m_output << m_indent << varConn << " = QSqlDatabase::database("
+ << language::charliteral(connection, m_dindent) << ");\n";
}
acceptWidget(node->elementWidget());
if (!m_buddies.empty())
- openIfndef(m_output, QLatin1String(shortcutDefineC));
+ m_output << language::openQtConfig(shortcutConfigKey());
for (const Buddy &b : qAsConst(m_buddies)) {
- if (!m_registeredWidgets.contains(b.objName)) {
+ const QString buddyVarName = m_driver->widgetVariableName(b.buddyAttributeName);
+ if (buddyVarName.isEmpty()) {
fprintf(stderr, "%s: Warning: Buddy assignment: '%s' is not a valid widget.\n",
qPrintable(m_option.messagePrefix()),
- b.objName.toLatin1().data());
- continue;
- } else if (!m_registeredWidgets.contains(b.buddy)) {
- fprintf(stderr, "%s: Warning: Buddy assignment: '%s' is not a valid widget.\n",
- qPrintable(m_option.messagePrefix()),
- b.buddy.toLatin1().data());
+ qPrintable(b.buddyAttributeName));
continue;
}
- m_output << m_indent << b.objName << "->setBuddy(" << b.buddy << ");\n";
+ m_output << m_indent << b.labelVarName << language::derefPointer
+ << "setBuddy(" << buddyVarName << ')' << language::eol;
}
if (!m_buddies.empty())
- closeIfndef(m_output, QLatin1String(shortcutDefineC));
+ m_output << language::closeQtConfig(shortcutConfigKey());
if (node->elementTabStops())
acceptTabStops(node->elementTabStops());
- if (m_delayedActionInitialization.size())
+ if (!m_delayedActionInitialization.isEmpty())
m_output << "\n" << m_delayedActionInitialization;
- m_output << "\n" << m_indent << "retranslateUi(" << varName << ");\n";
+ m_output << "\n" << m_indent << language::self
+ << "retranslateUi(" << varName << ')' << language::eol;
if (node->elementConnections())
acceptConnections(node->elementConnections());
@@ -554,22 +541,24 @@ void WriteInitialization::acceptUI(DomUI *node)
if (!m_delayedInitialization.isEmpty())
m_output << "\n" << m_delayedInitialization << "\n";
- if (m_option.autoConnection)
- m_output << "\n" << m_indent << "QMetaObject::connectSlotsByName(" << varName << ");\n";
+ if (m_option.autoConnection) {
+ m_output << "\n" << m_indent << "QMetaObject" << language::qualifier
+ << "connectSlotsByName(" << varName << ')' << language::eol;
+ }
- m_output << m_option.indent << "} // setupUi\n\n";
+ m_output << m_option.indent << language::endFunctionDefinition("setupUi");
- if (!m_mainFormUsedInRetranslateUi) {
+ if (!m_mainFormUsedInRetranslateUi && language::language() == Language::Cpp) {
m_refreshInitialization += m_indent;
m_refreshInitialization += QLatin1String("Q_UNUSED(");
m_refreshInitialization += varName ;
m_refreshInitialization += QLatin1String(");\n");
}
- m_output << m_option.indent << "void " << "retranslateUi(" << widgetClassName << " *" << varName << ")\n"
- << m_option.indent << "{\n"
+ m_output << m_option.indent
+ << language::startFunctionDefinition1("retranslateUi", parameterType, varName, m_option.indent)
<< m_refreshInitialization
- << m_option.indent << "} // retranslateUi\n\n";
+ << m_option.indent << language::endFunctionDefinition("retranslateUi");
m_layoutChain.pop();
m_widgetChain.pop();
@@ -592,9 +581,11 @@ void WriteInitialization::addWizardPage(const QString &pageVarName, const DomWid
}
}
if (id.isEmpty()) {
- m_output << m_indent << parentWidget << "->addPage(" << pageVarName << ");\n";
+ m_output << m_indent << parentWidget << language::derefPointer
+ << "addPage(" << pageVarName << ')' << language::eol;
} else {
- m_output << m_indent << parentWidget << "->setPage(" << id << ", " << pageVarName << ");\n";
+ m_output << m_indent << parentWidget << language::derefPointer
+ << "setPage(" << id << ", " << pageVarName << ')' << language::eol;
}
}
@@ -603,7 +594,6 @@ void WriteInitialization::acceptWidget(DomWidget *node)
m_layoutMarginType = m_widgetChain.count() == 1 ? TopLevelMargin : ChildMargin;
const QString className = node->attributeClass();
const QString varName = m_driver->findOrInsertWidget(node);
- m_registeredWidgets.insert(varName, node); // register the current widget
QString parentWidget, parentClass;
if (m_widgetChain.top()) {
@@ -616,18 +606,24 @@ void WriteInitialization::acceptWidget(DomWidget *node)
if (m_uic->isContainer(parentClass))
parentWidget.clear();
- if (m_widgetChain.size() != 1)
- m_output << m_indent << varName << " = new " << m_uic->customWidgetsInfo()->realClassName(className) << '(' << parentWidget << ");\n";
+ const auto *cwi = m_uic->customWidgetsInfo();
+
+ if (m_widgetChain.size() != 1) {
+ m_output << m_indent << varName << " = " << language::operatorNew
+ << language::fixClassName(cwi->realClassName(className))
+ << '(' << parentWidget << ')' << language::eol;
+ }
parentWidget = savedParentWidget;
- if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QComboBox"))) {
+
+ if (cwi->extends(className, QLatin1String("QComboBox"))) {
initializeComboBox(node);
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) {
+ } else if (cwi->extends(className, QLatin1String("QListWidget"))) {
initializeListWidget(node);
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeWidget"))) {
+ } else if (cwi->extends(className, QLatin1String("QTreeWidget"))) {
initializeTreeWidget(node);
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableWidget"))) {
+ } else if (cwi->extends(className, QLatin1String("QTableWidget"))) {
initializeTableWidget(node);
}
@@ -636,7 +632,8 @@ void WriteInitialization::acceptWidget(DomWidget *node)
writeProperties(varName, className, node->elementProperty());
- if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QMenu")) && parentWidget.size()) {
+ if (!parentWidget.isEmpty()
+ && cwi->extends(className, QLatin1String("QMenu"))) {
initializeMenu(node, parentWidget);
}
@@ -648,7 +645,7 @@ void WriteInitialization::acceptWidget(DomWidget *node)
if (const DomWidget* parentWidget = m_widgetChain.top()) {
const QString parentClass = parentWidget->attributeClass();
if (parentClass != QLatin1String("QMainWindow")
- && !m_uic->isCustomWidgetContainer(parentClass)
+ && !m_uic->customWidgetsInfo()->isCustomWidgetContainer(parentClass)
&& !m_uic->isContainer(parentClass))
m_layoutWidget = true;
}
@@ -664,101 +661,100 @@ void WriteInitialization::acceptWidget(DomWidget *node)
const QString pageDefaultString = QLatin1String("Page");
- if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QMainWindow"))) {
- if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QMenuBar"))) {
- m_output << m_indent << parentWidget << "->setMenuBar(" << varName <<");\n";
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBar"))) {
- m_output << m_indent << parentWidget << "->addToolBar("
- << toolBarAreaStringFromDOMAttributes(attributes) << varName << ");\n";
+ if (cwi->extends(parentClass, QLatin1String("QMainWindow"))) {
+ if (cwi->extends(className, QLatin1String("QMenuBar"))) {
+ m_output << m_indent << parentWidget << language::derefPointer
+ << "setMenuBar(" << varName << ')' << language::eol;
+ } else if (cwi->extends(className, QLatin1String("QToolBar"))) {
+ m_output << m_indent << parentWidget << language::derefPointer << "addToolBar("
+ << language::enumValue(toolBarAreaStringFromDOMAttributes(attributes)) << varName
+ << ')' << language::eol;
if (const DomProperty *pbreak = attributes.value(QLatin1String("toolBarBreak"))) {
if (pbreak->elementBool() == QLatin1String("true")) {
- m_output << m_indent << parentWidget << "->insertToolBarBreak(" << varName << ");\n";
+ m_output << m_indent << parentWidget << language::derefPointer
+ << "insertToolBarBreak(" << varName << ')' << language::eol;
}
}
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QDockWidget"))) {
- QString area;
+ } else if (cwi->extends(className, QLatin1String("QDockWidget"))) {
+ m_output << m_indent << parentWidget << language::derefPointer << "addDockWidget(";
if (DomProperty *pstyle = attributes.value(QLatin1String("dockWidgetArea"))) {
- area += QLatin1String("static_cast<Qt::DockWidgetArea>(");
- area += QString::number(pstyle->elementNumber());
- area += QLatin1String("), ");
+ m_output << "Qt" << language::qualifier
+ << language::dockWidgetArea(pstyle->elementNumber()) << ", ";
}
-
- m_output << m_indent << parentWidget << "->addDockWidget(" << area << varName << ");\n";
+ m_output << varName << ");\n";
} else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStatusBar"))) {
- m_output << m_indent << parentWidget << "->setStatusBar(" << varName << ");\n";
+ m_output << m_indent << parentWidget << language::derefPointer
+ << "setStatusBar(" << varName << ')' << language::eol;
} else {
- m_output << m_indent << parentWidget << "->setCentralWidget(" << varName << ");\n";
+ m_output << m_indent << parentWidget << language::derefPointer
+ << "setCentralWidget(" << varName << ')' << language::eol;
}
}
// Check for addPageMethod of a custom plugin first
- const QString addPageMethod = m_uic->customWidgetsInfo()->customWidgetAddPageMethod(parentClass);
+ QString addPageMethod = cwi->customWidgetAddPageMethod(parentClass);
+ if (addPageMethod.isEmpty())
+ addPageMethod = cwi->simpleContainerAddPageMethod(parentClass);
if (!addPageMethod.isEmpty()) {
- m_output << m_indent << parentWidget << "->" << addPageMethod << '(' << varName << ");\n";
- } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QStackedWidget"))) {
- m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n";
- } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QToolBar"))) {
- m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n";
- } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QDockWidget"))) {
- m_output << m_indent << parentWidget << "->setWidget(" << varName << ");\n";
- } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QScrollArea"))) {
- m_output << m_indent << parentWidget << "->setWidget(" << varName << ");\n";
- } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QSplitter"))) {
- m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n";
- } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QMdiArea"))) {
- m_output << m_indent << parentWidget << "->addSubWindow(" << varName << ");\n";
+ m_output << m_indent << parentWidget << language::derefPointer
+ << addPageMethod << '(' << varName << ')' << language::eol;
} else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QWizard"))) {
addWizardPage(varName, node, parentWidget);
} else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QToolBox"))) {
- QString icon;
- if (const DomProperty *picon = attributes.value(QLatin1String("icon"))) {
- icon += QLatin1String(", ") ;
- icon += iconCall(picon);
- }
-
const DomProperty *plabel = attributes.value(QLatin1String("label"));
- DomString *plabelString = plabel ? plabel->elementString() : 0;
-
- m_output << m_indent << parentWidget << "->addItem(" << varName << icon << ", " << noTrCall(plabelString, pageDefaultString) << ");\n";
+ DomString *plabelString = plabel ? plabel->elementString() : nullptr;
+ QString icon;
+ if (const DomProperty *picon = attributes.value(QLatin1String("icon")))
+ icon = QLatin1String(", ") + iconCall(picon); // Side effect: Writes icon definition
+ m_output << m_indent << parentWidget << language::derefPointer << "addItem("
+ << varName << icon << ", " << noTrCall(plabelString, pageDefaultString)
+ << ')' << language::eol;
- autoTrOutput(plabelString, pageDefaultString) << m_indent << parentWidget << "->setItemText("
- << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(plabelString, pageDefaultString) << ");\n";
+ autoTrOutput(plabelString, pageDefaultString) << m_indent << parentWidget
+ << language::derefPointer << "setItemText(" << parentWidget
+ << language::derefPointer << "indexOf(" << varName << "), "
+ << autoTrCall(plabelString, pageDefaultString) << ')' << language::eol;
-#ifndef QT_NO_TOOLTIP
if (DomProperty *ptoolTip = attributes.value(QLatin1String("toolTip"))) {
- autoTrOutput(ptoolTip->elementString()) << m_indent << parentWidget << "->setItemToolTip("
- << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(ptoolTip->elementString()) << ");\n";
+ autoTrOutput(ptoolTip->elementString())
+ << language::openQtConfig(toolTipConfigKey())
+ << m_indent << parentWidget << language::derefPointer << "setItemToolTip(" << parentWidget
+ << language::derefPointer << "indexOf(" << varName << "), "
+ << autoTrCall(ptoolTip->elementString()) << ')' << language::eol
+ << language::closeQtConfig(toolTipConfigKey());
}
-#endif // QT_NO_TOOLTIP
} else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QTabWidget"))) {
- QString icon;
- if (const DomProperty *picon = attributes.value(QLatin1String("icon"))) {
- icon += QLatin1String(", ");
- icon += iconCall(picon);
- }
-
const DomProperty *ptitle = attributes.value(QLatin1String("title"));
- DomString *ptitleString = ptitle ? ptitle->elementString() : 0;
-
- m_output << m_indent << parentWidget << "->addTab(" << varName << icon << ", " << "QString());\n";
+ DomString *ptitleString = ptitle ? ptitle->elementString() : nullptr;
+ QString icon;
+ if (const DomProperty *picon = attributes.value(QLatin1String("icon")))
+ icon = QLatin1String(", ") + iconCall(picon); // Side effect: Writes icon definition
+ m_output << m_indent << parentWidget << language::derefPointer << "addTab("
+ << varName << icon << ", " << "QString())" << language::eol;
- autoTrOutput(ptitleString, pageDefaultString) << m_indent << parentWidget << "->setTabText("
- << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(ptitleString, pageDefaultString) << ");\n";
+ autoTrOutput(ptitleString, pageDefaultString) << m_indent << parentWidget
+ << language::derefPointer << "setTabText(" << parentWidget
+ << language::derefPointer << "indexOf(" << varName << "), "
+ << autoTrCall(ptitleString, pageDefaultString) << ')' << language::eol;
-#ifndef QT_NO_TOOLTIP
if (const DomProperty *ptoolTip = attributes.value(QLatin1String("toolTip"))) {
- autoTrOutput(ptoolTip->elementString()) << m_indent << parentWidget << "->setTabToolTip("
- << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(ptoolTip->elementString()) << ");\n";
+ autoTrOutput(ptoolTip->elementString())
+ << language::openQtConfig(toolTipConfigKey())
+ << m_indent << parentWidget << language::derefPointer << "setTabToolTip("
+ << parentWidget << language::derefPointer << "indexOf(" << varName
+ << "), " << autoTrCall(ptoolTip->elementString()) << ')' << language::eol
+ << language::closeQtConfig(toolTipConfigKey());
}
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_WHATSTHIS
if (const DomProperty *pwhatsThis = attributes.value(QLatin1String("whatsThis"))) {
- autoTrOutput(pwhatsThis->elementString()) << m_indent << parentWidget << "->setTabWhatsThis("
- << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(pwhatsThis->elementString()) << ");\n";
+ autoTrOutput(pwhatsThis->elementString())
+ << language::openQtConfig(whatsThisConfigKey())
+ << m_indent << parentWidget << language::derefPointer << "setTabWhatsThis("
+ << parentWidget << language::derefPointer << "indexOf(" << varName
+ << "), " << autoTrCall(pwhatsThis->elementString()) << ')' << language::eol
+ << language::closeQtConfig(whatsThisConfigKey());
}
-#endif // QT_NO_WHATSTHIS
}
//
@@ -774,8 +770,14 @@ void WriteInitialization::acceptWidget(DomWidget *node)
QLatin1String("stretchLastSection"),
};
- if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeView"))
- || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeWidget"))) {
+ static const QStringList trees = {
+ QLatin1String("QTreeView"), QLatin1String("QTreeWidget")
+ };
+ static const QStringList tables = {
+ QLatin1String("QTableView"), QLatin1String("QTableWidget")
+ };
+
+ if (cwi->extendsOneOf(className, trees)) {
DomPropertyList headerProperties;
for (auto realPropertyName : realPropertyNames) {
const QString fakePropertyName = QLatin1String("header")
@@ -785,12 +787,11 @@ void WriteInitialization::acceptWidget(DomWidget *node)
headerProperties << fakeProperty;
}
}
- writeProperties(varName + QLatin1String("->header()"), QLatin1String("QHeaderView"),
- headerProperties, WritePropertyIgnoreObjectName);
-
- } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableView"))
- || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableWidget"))) {
+ writeProperties(varName + language::derefPointer + QLatin1String("header()"),
+ QLatin1String("QHeaderView"), headerProperties,
+ WritePropertyIgnoreObjectName);
+ } else if (cwi->extendsOneOf(className, tables)) {
static const QLatin1String headerPrefixes[] = {
QLatin1String("horizontalHeader"),
QLatin1String("verticalHeader"),
@@ -806,8 +807,9 @@ void WriteInitialization::acceptWidget(DomWidget *node)
headerProperties << fakeProperty;
}
}
- writeProperties(varName + QLatin1String("->") + headerPrefix + QLatin1String("()"),
- QLatin1String("QHeaderView"),
+ const QString headerVar = varName + language::derefPointer
+ + headerPrefix + QLatin1String("()");
+ writeProperties(headerVar, QLatin1String("QHeaderView"),
headerProperties, WritePropertyIgnoreObjectName);
}
}
@@ -817,15 +819,15 @@ void WriteInitialization::acceptWidget(DomWidget *node)
const QStringList zOrder = node->elementZOrder();
for (const QString &name : zOrder) {
- if (!m_registeredWidgets.contains(name)) {
+ const QString varName = m_driver->widgetVariableName(name);
+ if (varName.isEmpty()) {
fprintf(stderr, "%s: Warning: Z-order assignment: '%s' is not a valid widget.\n",
qPrintable(m_option.messagePrefix()),
name.toLatin1().data());
- continue;
+ } else {
+ m_output << m_indent << varName << language::derefPointer << "raise()"
+ << language::eol;
}
-
- if (!name.isEmpty())
- m_output << m_indent << name << "->raise();\n";
}
}
@@ -840,7 +842,7 @@ void WriteInitialization::addButtonGroup(const DomWidget *buttonNode, const QStr
const DomButtonGroup *group = m_driver->findButtonGroup(attributeName);
// Legacy feature: Create missing groups on the fly as the UIC button group feature
// was present before the actual Designer support (4.5)
- const bool createGroupOnTheFly = group == 0;
+ const bool createGroupOnTheFly = group == nullptr;
if (createGroupOnTheFly) {
DomButtonGroup *newGroup = new DomButtonGroup;
newGroup->setAttributeName(attributeName);
@@ -856,11 +858,13 @@ void WriteInitialization::addButtonGroup(const DomWidget *buttonNode, const QStr
m_output << m_indent;
if (createGroupOnTheFly)
m_output << className << " *";
- m_output << groupName << " = new " << className << '(' << m_mainFormVarName << ");\n";
+ m_output << groupName << " = " << language::operatorNew
+ << className << '(' << m_mainFormVarName << ')' << language::eol;
m_buttonGroups.insert(groupName);
writeProperties(groupName, className, group->elementProperty());
}
- m_output << m_indent << groupName << "->addButton(" << varName << ");\n";
+ m_output << m_indent << groupName << language::derefPointer << "addButton("
+ << varName << ')' << language::eol;
}
void WriteInitialization::acceptLayout(DomLayout *node)
@@ -873,7 +877,7 @@ void WriteInitialization::acceptLayout(DomLayout *node)
bool isGroupBox = false;
- m_output << m_indent << varName << " = new " << className << '(';
+ m_output << m_indent << varName << " = " << language::operatorNew << className << '(';
if (!m_layoutChain.top() && !isGroupBox)
m_output << m_driver->findOrInsertWidget(m_widgetChain.top());
@@ -894,8 +898,7 @@ void WriteInitialization::acceptLayout(DomLayout *node)
if (m_layoutWidget) {
bool left, top, right, bottom;
left = top = right = bottom = false;
- for (int i = 0; i < propList.size(); ++i) {
- const DomProperty *p = propList.at(i);
+ for (const DomProperty *p : propList) {
const QString propertyName = p->attributeName();
if (propertyName == QLatin1String("leftMargin") && p->kind() == DomProperty::Number)
left = true;
@@ -965,9 +968,12 @@ void WriteInitialization::writePropertyList(const QString &varName,
return;
const QStringList list = value.split(QLatin1Char(','));
const int count = list.count();
- for (int i = 0; i < count; i++)
- if (list.at(i) != defaultValue)
- m_output << m_indent << varName << "->" << setFunction << '(' << i << ", " << list.at(i) << ");\n";
+ for (int i = 0; i < count; i++) {
+ if (list.at(i) != defaultValue) {
+ m_output << m_indent << varName << language::derefPointer << setFunction
+ << '(' << i << ", " << list.at(i) << ')' << language::eol;
+ }
+ }
}
void WriteInitialization::acceptSpacer(DomSpacer *node)
@@ -984,6 +990,24 @@ static inline QString formLayoutRole(int column, int colspan)
return column == 0 ? QLatin1String("QFormLayout::LabelRole") : QLatin1String("QFormLayout::FieldRole");
}
+static QString layoutAddMethod(DomLayoutItem::Kind kind, const QString &layoutClass)
+{
+ const QString methodPrefix = layoutClass == QLatin1String("QFormLayout")
+ ? QLatin1String("set") : QLatin1String("add");
+ switch (kind) {
+ case DomLayoutItem::Widget:
+ return methodPrefix + QLatin1String("Widget");
+ case DomLayoutItem::Layout:
+ return methodPrefix + QLatin1String("Layout");
+ case DomLayoutItem::Spacer:
+ return methodPrefix + QLatin1String("Item");
+ case DomLayoutItem::Unknown:
+ Q_ASSERT( false );
+ break;
+ }
+ Q_UNREACHABLE();
+}
+
void WriteInitialization::acceptLayoutItem(DomLayoutItem *node)
{
TreeWalker::acceptLayoutItem(node);
@@ -996,47 +1020,27 @@ void WriteInitialization::acceptLayoutItem(DomLayoutItem *node)
const QString layoutName = m_driver->findOrInsertLayout(layout);
const QString itemName = m_driver->findOrInsertLayoutItem(node);
- QString addArgs;
- QString methodPrefix = QLatin1String("add"); //Consistent API-design galore!
+ m_output << "\n" << m_indent << layoutName << language::derefPointer << ""
+ << layoutAddMethod(node->kind(), layout->attributeClass()) << '(';
+
if (layout->attributeClass() == QLatin1String("QGridLayout")) {
const int row = node->attributeRow();
const int col = node->attributeColumn();
const int rowSpan = node->hasAttributeRowSpan() ? node->attributeRowSpan() : 1;
const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1;
-
- addArgs = QString::fromLatin1("%1, %2, %3, %4, %5").arg(itemName).arg(row).arg(col).arg(rowSpan).arg(colSpan);
+ m_output << itemName << ", " << row << ", " << col << ", " << rowSpan << ", " << colSpan;
if (!node->attributeAlignment().isEmpty())
- addArgs += QLatin1String(", ") + node->attributeAlignment();
+ m_output << ", " << language::enumValue(node->attributeAlignment());
+ } else if (layout->attributeClass() == QLatin1String("QFormLayout")) {
+ const int row = node->attributeRow();
+ const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1;
+ const QString role = formLayoutRole(node->attributeColumn(), colSpan);
+ m_output << row << ", " << language::enumValue(role) << ", " << itemName;
} else {
- if (layout->attributeClass() == QLatin1String("QFormLayout")) {
- methodPrefix = QLatin1String("set");
- const int row = node->attributeRow();
- const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1;
- const QString role = formLayoutRole(node->attributeColumn(), colSpan);
- addArgs = QString::fromLatin1("%1, %2, %3").arg(row).arg(role, itemName);
- } else {
- addArgs = itemName;
- if (layout->attributeClass().contains(QLatin1String("Box")) && !node->attributeAlignment().isEmpty())
- addArgs += QLatin1String(", 0, ") + node->attributeAlignment();
- }
- }
-
- // figure out "add" method
- m_output << "\n" << m_indent << layoutName << "->";
- switch (node->kind()) {
- case DomLayoutItem::Widget:
- m_output << methodPrefix << "Widget(" << addArgs;
- break;
- case DomLayoutItem::Layout:
- m_output << methodPrefix << "Layout(" << addArgs;
- break;
- case DomLayoutItem::Spacer:
- m_output << methodPrefix << "Item(" << addArgs;
- break;
- case DomLayoutItem::Unknown:
- Q_ASSERT( 0 );
- break;
+ m_output << itemName;
+ if (layout->attributeClass().contains(QLatin1String("Box")) && !node->attributeAlignment().isEmpty())
+ m_output << ", 0, " << language::enumValue(node->attributeAlignment());
}
m_output << ");\n\n";
}
@@ -1049,7 +1053,8 @@ void WriteInitialization::acceptActionGroup(DomActionGroup *node)
if (m_actionGroupChain.top())
varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top());
- m_output << m_indent << actionName << " = new QActionGroup(" << varName << ");\n";
+ m_output << m_indent << actionName << " = " << language::operatorNew
+ << "QActionGroup(" << varName << ");\n";
writeProperties(actionName, QLatin1String("QActionGroup"), node->elementProperty());
m_actionGroupChain.push(node);
@@ -1063,47 +1068,51 @@ void WriteInitialization::acceptAction(DomAction *node)
return;
const QString actionName = m_driver->findOrInsertAction(node);
- m_registeredActions.insert(actionName, node);
QString varName = m_driver->findOrInsertWidget(m_widgetChain.top());
if (m_actionGroupChain.top())
varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top());
- m_output << m_indent << actionName << " = new QAction(" << varName << ");\n";
+ m_output << m_indent << actionName << " = " << language::operatorNew
+ << "QAction(" << varName << ')' << language::eol;
writeProperties(actionName, QLatin1String("QAction"), node->elementProperty());
}
void WriteInitialization::acceptActionRef(DomActionRef *node)
{
QString actionName = node->attributeName();
- const bool isSeparator = actionName == QLatin1String("separator");
- bool isMenu = false;
+ if (actionName.isEmpty() || !m_widgetChain.top()
+ || m_driver->actionGroupByName(actionName)) {
+ return;
+ }
- QString varName = m_driver->findOrInsertWidget(m_widgetChain.top());
+ const QString varName = m_driver->findOrInsertWidget(m_widgetChain.top());
- if (actionName.isEmpty() || !m_widgetChain.top()) {
- return;
- } else if (m_driver->actionGroupByName(actionName)) {
- return;
- } else if (const DomWidget *w = m_driver->widgetByName(actionName)) {
- isMenu = m_uic->isMenu(w->attributeClass());
- } else if (!(m_driver->actionByName(actionName) || isSeparator)) {
- fprintf(stderr, "%s: Warning: action `%s' not declared\n",
- qPrintable(m_option.messagePrefix()),
- actionName.toLatin1().data());
+ if (m_widgetChain.top() && actionName == QLatin1String("separator")) {
+ // separator is always reserved!
+ m_actionOut << m_indent << varName << language::derefPointer
+ << "addSeparator()" << language::eol;
return;
}
- if (m_widgetChain.top() && isSeparator) {
- // separator is always reserved!
- m_actionOut << m_indent << varName << "->addSeparator();\n";
+ const DomWidget *domWidget = m_driver->widgetByName(actionName);
+ if (domWidget && m_uic->isMenu(domWidget->attributeClass())) {
+ m_actionOut << m_indent << varName << language::derefPointer
+ << "addAction(" << m_driver->findOrInsertWidget(domWidget)
+ << language::derefPointer << "menuAction())" << language::eol;
return;
}
- if (isMenu)
- actionName += QLatin1String("->menuAction()");
+ const DomAction *domAction = m_driver->actionByName(actionName);
+ if (!domAction) {
+ fprintf(stderr, "%s: Warning: action `%s' not declared\n",
+ qPrintable(m_option.messagePrefix()), qPrintable(actionName));
+ return;
+ }
- m_actionOut << m_indent << varName << "->addAction(" << actionName << ");\n";
+ m_actionOut << m_indent << varName << language::derefPointer
+ << "addAction(" << m_driver->findOrInsertAction(domAction)
+ << ')' << language::eol;
}
QString WriteInitialization::writeStringListProperty(const DomStringList *list) const
@@ -1120,11 +1129,28 @@ QString WriteInitialization::writeStringListProperty(const DomStringList *list)
str << '\n' << m_indent << " << " << trCall(values.at(i), comment);
} else {
for (int i = 0; i < values.size(); ++i)
- str << " << QString::fromUtf8(" << fixString(values.at(i), m_dindent) << ')';
+ str << " << " << language::qstring(values.at(i), m_dindent);
}
return propertyValue;
}
+static QString configKeyForProperty(const QString &propertyName)
+{
+ if (propertyName == QLatin1String("toolTip"))
+ return toolTipConfigKey();
+ if (propertyName == QLatin1String("whatsThis"))
+ return whatsThisConfigKey();
+ if (propertyName == QLatin1String("statusTip"))
+ return statusTipConfigKey();
+ if (propertyName == QLatin1String("shortcut"))
+ return shortcutConfigKey();
+ if (propertyName == QLatin1String("accessibleName")
+ || propertyName == QLatin1String("accessibleDescription")) {
+ return accessibilityConfigKey();
+ }
+ return QString();
+}
+
void WriteInitialization::writeProperties(const QString &varName,
const QString &className,
const DomPropertyList &lst,
@@ -1135,19 +1161,32 @@ void WriteInitialization::writeProperties(const QString &varName,
if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QAxWidget"))) {
DomPropertyMap properties = propertyMap(lst);
if (DomProperty *p = properties.value(QLatin1String("control"))) {
- m_output << m_indent << varName << "->setControl(QString::fromUtf8("
- << fixString(toString(p->elementString()), m_dindent) << "));\n";
+ m_output << m_indent << varName << language::derefPointer << "setControl("
+ << language::qstring(toString(p->elementString()), m_dindent)
+ << ')' << language::eol;
}
}
QString indent;
if (!m_widgetChain.top()) {
indent = m_option.indent;
- m_output << m_indent << "if (" << varName << "->objectName().isEmpty())\n";
+ switch (language::language()) {
+ case Language::Cpp:
+ m_output << m_indent << "if (" << varName << "->objectName().isEmpty())\n";
+ break;
+ case Language::Python:
+ m_output << m_indent << "if " << varName << ".objectName():\n";
+ break;
+ }
+ }
+ if (!(flags & WritePropertyIgnoreObjectName)) {
+ QString objectName = varName;
+ if (!language::self.isEmpty() && objectName.startsWith(language::self))
+ objectName.remove(0, language::self.size());
+ m_output << m_indent << indent
+ << varName << language::derefPointer << "setObjectName("
+ << language::qstring(objectName, m_dindent) << ')' << language::eol;
}
- if (!(flags & WritePropertyIgnoreObjectName))
- m_output << m_indent << indent << varName
- << "->setObjectName(QString::fromUtf8(" << fixString(varName, m_dindent) << "));\n";
int leftMargin, topMargin, rightMargin, bottomMargin;
leftMargin = topMargin = rightMargin = bottomMargin = -1;
@@ -1163,28 +1202,31 @@ void WriteInitialization::writeProperties(const QString &varName,
// special case for the property `geometry': Do not use position
if (isTopLevel && propertyName == QLatin1String("geometry") && p->elementRect()) {
const DomRect *r = p->elementRect();
- m_output << m_indent << varName << "->resize(" << r->elementWidth() << ", " << r->elementHeight() << ");\n";
+ m_output << m_indent << varName << language::derefPointer << "resize("
+ << r->elementWidth() << ", " << r->elementHeight() << ')' << language::eol;
continue;
}
if (propertyName == QLatin1String("currentRow") // QListWidget::currentRow
&& m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) {
- m_delayedOut << m_indent << varName << "->setCurrentRow("
- << p->elementNumber() << ");\n";
+ m_delayedOut << m_indent << varName << language::derefPointer
+ << "setCurrentRow(" << p->elementNumber() << ')' << language::eol;
continue;
}
+ static const QStringList currentIndexWidgets = {
+ QLatin1String("QComboBox"), QLatin1String("QStackedWidget"),
+ QLatin1String("QTabWidget"), QLatin1String("QToolBox")
+ };
if (propertyName == QLatin1String("currentIndex") // set currentIndex later
- && (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QComboBox"))
- || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStackedWidget"))
- || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTabWidget"))
- || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox")))) {
- m_delayedOut << m_indent << varName << "->setCurrentIndex("
- << p->elementNumber() << ");\n";
+ && (m_uic->customWidgetsInfo()->extendsOneOf(className, currentIndexWidgets))) {
+ m_delayedOut << m_indent << varName << language::derefPointer
+ << "setCurrentIndex(" << p->elementNumber() << ')' << language::eol;
continue;
}
if (propertyName == QLatin1String("tabSpacing")
&& m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox"))) {
- m_delayedOut << m_indent << varName << "->layout()->setSpacing("
- << p->elementNumber() << ");\n";
+ m_delayedOut << m_indent << varName << language::derefPointer
+ << "layout()" << language::derefPointer << "setSpacing("
+ << p->elementNumber() << ')' << language::eol;
continue;
}
if (propertyName == QLatin1String("control") // ActiveQt support
@@ -1211,10 +1253,15 @@ void WriteInitialization::writeProperties(const QString &varName,
if (p->elementEnum() == QLatin1String("Qt::Vertical"))
shape = QLatin1String("QFrame::VLine");
- m_output << m_indent << varName << "->setFrameShape(" << shape << ");\n";
+ m_output << m_indent << varName << language::derefPointer << "setFrameShape("
+ << language::enumValue(shape) << ')' << language::eol;
// QFrame Default is 'Plain'. Make the line 'Sunken' unless otherwise specified
- if (!frameShadowEncountered)
- m_output << m_indent << varName << "->setFrameShadow(QFrame::Sunken);\n";
+ if (!frameShadowEncountered) {
+ m_output << m_indent << varName << language::derefPointer
+ << "setFrameShadow("
+ << language::enumValue(QLatin1String("QFrame::Sunken"))
+ << ')' << language::eol;
+ }
continue;
} else if ((flags & WritePropertyIgnoreMargin) && propertyName == QLatin1String("margin")) {
continue;
@@ -1246,25 +1293,28 @@ void WriteInitialization::writeProperties(const QString &varName,
QString setFunction;
- if (stdset) {
- setFunction = QLatin1String("->set")
- + propertyName.at(0).toUpper()
- + propertyName.midRef(1)
- + QLatin1Char('(');
- } else {
- setFunction += QLatin1String("->setProperty(\"")
- + propertyName
- + QLatin1String("\", QVariant");
- if (p->kind() == DomProperty::Enum)
- setFunction += QLatin1String("::fromValue");
- setFunction += QLatin1Char('(');
- }
+ {
+ QTextStream str(&setFunction);
+ if (stdset) {
+ str << language::derefPointer <<"set" << propertyName.at(0).toUpper()
+ << propertyName.midRef(1) << '(';
+ } else {
+ str << language::derefPointer << QLatin1String("setProperty(\"")
+ << propertyName << "\", ";
+ if (language::language() == Language::Cpp) {
+ str << "QVariant";
+ if (p->kind() == DomProperty::Enum)
+ str << "::fromValue";
+ str << '(';
+ }
+ }
+ } // QTextStream
QString varNewName = varName;
switch (p->kind()) {
case DomProperty::Bool: {
- propertyValue = p->elementBool();
+ propertyValue = language::boolValue(p->elementBool() == language::cppTrue);
break;
}
case DomProperty::Color:
@@ -1275,13 +1325,12 @@ void WriteInitialization::writeProperties(const QString &varName,
Buddy buddy = { varName, p->elementCstring() };
m_buddies.append(std::move(buddy));
} else {
- if (stdset)
- propertyValue = fixString(p->elementCstring(), m_dindent);
- else {
- propertyValue = QLatin1String("QByteArray(")
- + fixString(p->elementCstring(), m_dindent)
- + QLatin1Char(')');
- }
+ QTextStream str(&propertyValue);
+ if (!stdset)
+ str << "QByteArray(";
+ str << language::charliteral(p->elementCstring(), m_dindent);
+ if (!stdset)
+ str << ')';
}
break;
case DomProperty::Cursor:
@@ -1290,17 +1339,19 @@ void WriteInitialization::writeProperties(const QString &varName,
break;
case DomProperty::CursorShape:
if (p->hasAttributeStdset() && !p->attributeStdset())
- varNewName += QLatin1String("->viewport()");
- propertyValue = QString::fromLatin1("QCursor(Qt::%1)")
- .arg(p->elementCursorShape());
+ varNewName += language::derefPointer + QLatin1String("viewport()");
+ propertyValue = QLatin1String("QCursor(Qt") + language::qualifier
+ + p->elementCursorShape() + QLatin1Char(')');
break;
case DomProperty::Enum:
propertyValue = p->elementEnum();
- if (!propertyValue.contains(QLatin1String("::")))
- propertyValue = className + QLatin1String("::") + propertyValue;
+ if (propertyValue.contains(language::cppQualifier))
+ propertyValue = language::enumValue(propertyValue);
+ else
+ propertyValue.prepend(className + language::qualifier);
break;
case DomProperty::Set:
- propertyValue = p->elementSet();
+ propertyValue = language::enumValue(p->elementSet());
break;
case DomProperty::Font:
propertyValue = writeFontProperties(p->elementFont());
@@ -1314,8 +1365,8 @@ void WriteInitialization::writeProperties(const QString &varName,
case DomProperty::Palette: {
const DomPalette *pal = p->elementPalette();
const QString paletteName = m_driver->unique(QLatin1String("palette"));
- m_output << m_indent << "QPalette " << paletteName << ";\n";
-
+ m_output << m_indent << language::stackVariable("QPalette", paletteName)
+ << language::eol;
writeColorGroup(pal->elementActive(), QLatin1String("QPalette::Active"), paletteName);
writeColorGroup(pal->elementInactive(), QLatin1String("QPalette::Inactive"), paletteName);
writeColorGroup(pal->elementDisabled(), QLatin1String("QPalette::Disabled"), paletteName);
@@ -1351,15 +1402,16 @@ void WriteInitialization::writeProperties(const QString &varName,
}
case DomProperty::Locale: {
const DomLocale *locale = p->elementLocale();
- propertyValue = QString::fromLatin1("QLocale(QLocale::%1, QLocale::%2)")
- .arg(locale->attributeLanguage(), locale->attributeCountry());
+ QTextStream(&propertyValue) << "QLocale(QLocale" << language::qualifier
+ << locale->attributeLanguage() << ", QLocale" << language::qualifier
+ << locale->attributeCountry() << ')';
break;
}
case DomProperty::SizePolicy: {
const QString spName = writeSizePolicy( p->elementSizePolicy());
- m_output << m_indent << spName << QString::fromLatin1(
- ".setHeightForWidth(%1->sizePolicy().hasHeightForWidth());\n")
- .arg(varName);
+ m_output << m_indent << spName << ".setHeightForWidth("
+ << varName << language::derefPointer << "sizePolicy().hasHeightForWidth())"
+ << language::eol;
propertyValue = spName;
break;
@@ -1450,8 +1502,8 @@ void WriteInitialization::writeProperties(const QString &varName,
case DomProperty::Url: {
const DomUrl* u = p->elementUrl();
- propertyValue = QString::fromLatin1("QUrl(QString::fromUtf8(%1))")
- .arg(fixString(u->elementString()->text(), m_dindent));
+ QTextStream(&propertyValue) << "QUrl("
+ << language::qstring(u->elementString()->text(), m_dindent) << ")";
break;
}
case DomProperty::Brush:
@@ -1461,29 +1513,19 @@ void WriteInitialization::writeProperties(const QString &varName,
break;
}
- if (propertyValue.size()) {
- const char* defineC = 0;
- if (propertyName == QLatin1String("toolTip"))
- defineC = toolTipDefineC;
- else if (propertyName == QLatin1String("whatsThis"))
- defineC = whatsThisDefineC;
- else if (propertyName == QLatin1String("statusTip"))
- defineC = statusTipDefineC;
- else if (propertyName == QLatin1String("shortcut"))
- defineC = shortcutDefineC;
- else if (propertyName == QLatin1String("accessibleName") || propertyName == QLatin1String("accessibleDescription"))
- defineC = accessibilityDefineC;
+ if (!propertyValue.isEmpty()) {
+ const QString configKey = configKeyForProperty(propertyName);
QTextStream &o = delayProperty ? m_delayedOut : autoTrOutput(p);
- if (defineC)
- openIfndef(o, QLatin1String(defineC));
+ if (!configKey.isEmpty())
+ o << language::openQtConfig(configKey);
o << m_indent << varNewName << setFunction << propertyValue;
- if (!stdset)
+ if (!stdset && language::language() == Language::Cpp)
o << ')';
- o << ");\n";
- if (defineC)
- closeIfndef(o, QLatin1String(defineC));
+ o << ')' << language::eol;
+ if (!configKey.isEmpty())
+ o << language::closeQtConfig(configKey);
if (varName == m_mainFormVarName && &o == &m_refreshOut) {
// this is the only place (currently) where we output mainForm name to the retranslateUi().
@@ -1493,11 +1535,9 @@ void WriteInitialization::writeProperties(const QString &varName,
}
}
if (leftMargin != -1 || topMargin != -1 || rightMargin != -1 || bottomMargin != -1) {
- m_output << m_indent << varName << QLatin1String("->setContentsMargins(")
- << leftMargin << QLatin1String(", ")
- << topMargin << QLatin1String(", ")
- << rightMargin << QLatin1String(", ")
- << bottomMargin << QLatin1String(");\n");
+ m_output << m_indent << varName << language::derefPointer << "setContentsMargins("
+ << leftMargin << ", " << topMargin << ", "
+ << rightMargin << ", " << bottomMargin << ");\n";
}
}
@@ -1516,20 +1556,15 @@ QString WriteInitialization::writeSizePolicy(const DomSizePolicy *sp)
const QString spName = m_driver->unique(QLatin1String("sizePolicy"));
m_sizePolicyNameMap.insert(sizePolicyHandle, spName);
- m_output << m_indent << "QSizePolicy " << spName;
- do {
- if (sp->hasElementHSizeType() && sp->hasElementVSizeType()) {
- m_output << "(static_cast<QSizePolicy::Policy>(" << sp->elementHSizeType()
- << "), static_cast<QSizePolicy::Policy>(" << sp->elementVSizeType() << "));\n";
- break;
- }
- if (sp->hasAttributeHSizeType() && sp->hasAttributeVSizeType()) {
- m_output << "(QSizePolicy::" << sp->attributeHSizeType() << ", QSizePolicy::"
- << sp->attributeVSizeType() << ");\n";
- break;
- }
- m_output << ";\n";
- } while (false);
+ m_output << m_indent << language::stackVariableWithInitParameters("QSizePolicy", spName);
+ if (sp->hasElementHSizeType() && sp->hasElementVSizeType()) {
+ m_output << "QSizePolicy" << language::qualifier << language::sizePolicy(sp->elementHSizeType())
+ << ", QSizePolicy" << language::qualifier << language::sizePolicy(sp->elementVSizeType());
+ } else if (sp->hasAttributeHSizeType() && sp->hasAttributeVSizeType()) {
+ m_output << "QSizePolicy" << language::qualifier << sp->attributeHSizeType()
+ << ", QSizePolicy" << language::qualifier << sp->attributeVSizeType();
+ }
+ m_output << ')' << language::eol;
m_output << m_indent << spName << ".setHorizontalStretch("
<< sp->elementHorStretch() << ");\n";
@@ -1553,10 +1588,11 @@ QString WriteInitialization::writeFontProperties(const DomFont *f)
const QString fontName = m_driver->unique(QLatin1String("font"));
m_fontPropertiesNameMap.insert(FontHandle(f), fontName);
- m_output << m_indent << "QFont " << fontName << ";\n";
+ m_output << m_indent << language::stackVariable("QFont", fontName)
+ << language::eol;
if (f->hasElementFamily() && !f->elementFamily().isEmpty()) {
- m_output << m_indent << fontName << ".setFamily(QString::fromUtf8("
- << fixString(f->elementFamily(), m_dindent) << "));\n";
+ m_output << m_indent << fontName << ".setFamily("
+ << language::qstring(f->elementFamily(), m_dindent) << ");\n";
}
if (f->hasElementPointSize() && f->elementPointSize() > 0) {
m_output << m_indent << fontName << ".setPointSize(" << f->elementPointSize()
@@ -1565,39 +1601,51 @@ QString WriteInitialization::writeFontProperties(const DomFont *f)
if (f->hasElementBold()) {
m_output << m_indent << fontName << ".setBold("
- << (f->elementBold() ? "true" : "false") << ");\n";
+ << language::boolValue(f->elementBold()) << ')' << language::eol;
}
if (f->hasElementItalic()) {
m_output << m_indent << fontName << ".setItalic("
- << (f->elementItalic() ? "true" : "false") << ");\n";
+ << language::boolValue(f->elementItalic()) << ')' << language::eol;
}
if (f->hasElementUnderline()) {
m_output << m_indent << fontName << ".setUnderline("
- << (f->elementUnderline() ? "true" : "false") << ");\n";
+ << language::boolValue(f->elementUnderline()) << ')' << language::eol;
}
if (f->hasElementWeight() && f->elementWeight() > 0) {
m_output << m_indent << fontName << ".setWeight("
- << f->elementWeight() << ");" << endl;
+ << f->elementWeight() << ");" << Qt::endl;
}
if (f->hasElementStrikeOut()) {
m_output << m_indent << fontName << ".setStrikeOut("
- << (f->elementStrikeOut() ? "true" : "false") << ");\n";
+ << language::boolValue(f->elementStrikeOut()) << ')' << language::eol;
}
if (f->hasElementKerning()) {
m_output << m_indent << fontName << ".setKerning("
- << (f->elementKerning() ? "true" : "false") << ");\n";
+ << language::boolValue(f->elementKerning()) << ')' << language::eol;
}
if (f->hasElementAntialiasing()) {
- m_output << m_indent << fontName << ".setStyleStrategy("
- << (f->elementAntialiasing() ? "QFont::PreferDefault" : "QFont::NoAntialias") << ");\n";
+ m_output << m_indent << fontName << ".setStyleStrategy(QFont"
+ << language::qualifier
+ << (f->elementAntialiasing() ? "PreferDefault" : "NoAntialias")
+ << ')' << language::eol;
}
if (f->hasElementStyleStrategy()) {
- m_output << m_indent << fontName << ".setStyleStrategy(QFont::"
- << f->elementStyleStrategy() << ");\n";
+ m_output << m_indent << fontName << ".setStyleStrategy(QFont"
+ << language::qualifier << f->elementStyleStrategy() << ')' << language::eol;
}
return fontName;
}
+static void writeIconAddFile(QTextStream &output, const QString &indent,
+ const QString &iconName, const QString &fileName,
+ const char *mode, const char *state)
+{
+ output << indent << iconName << ".addFile("
+ << language::qstring(fileName, indent) << ", QSize(), QIcon"
+ << language::qualifier << mode << ", QIcon" << language::qualifier
+ << state << ')' << language::eol;
+}
+
// Post 4.4 write resource icon
static void writeResourceIcon(QTextStream &output,
const QString &iconName,
@@ -1605,91 +1653,92 @@ static void writeResourceIcon(QTextStream &output,
const DomResourceIcon *i)
{
if (i->hasElementNormalOff()) {
- output << indent << iconName << ".addFile(QString::fromUtf8("
- << fixString(i->elementNormalOff()->text(), indent)
- << "), QSize(), QIcon::Normal, QIcon::Off);\n";
+ writeIconAddFile(output, indent, iconName, i->elementNormalOff()->text(),
+ "Normal", "Off");
}
if (i->hasElementNormalOn()) {
- output << indent << iconName << ".addFile(QString::fromUtf8("
- << fixString(i->elementNormalOn()->text(), indent)
- << "), QSize(), QIcon::Normal, QIcon::On);\n";
+ writeIconAddFile(output, indent, iconName, i->elementNormalOn()->text(),
+ "Normal", "On");
}
if (i->hasElementDisabledOff()) {
- output << indent << iconName << ".addFile(QString::fromUtf8("
- << fixString(i->elementDisabledOff()->text(), indent)
- << "), QSize(), QIcon::Disabled, QIcon::Off);\n";
+ writeIconAddFile(output, indent, iconName, i->elementDisabledOff()->text(),
+ "Disabled", "Off");
}
if (i->hasElementDisabledOn()) {
- output << indent << iconName << ".addFile(QString::fromUtf8("
- << fixString(i->elementDisabledOn()->text(), indent)
- << "), QSize(), QIcon::Disabled, QIcon::On);\n";
+ writeIconAddFile(output, indent, iconName, i->elementDisabledOn()->text(),
+ "Disabled", "On");
}
if (i->hasElementActiveOff()) {
- output << indent << iconName << ".addFile(QString::fromUtf8("
- << fixString(i->elementActiveOff()->text(), indent)
- << "), QSize(), QIcon::Active, QIcon::Off);\n";
+ writeIconAddFile(output, indent, iconName, i->elementActiveOff()->text(),
+ "Active", "Off");
}
if (i->hasElementActiveOn()) {
- output << indent << iconName << ".addFile(QString::fromUtf8("
- << fixString(i->elementActiveOn()->text(), indent)
- << "), QSize(), QIcon::Active, QIcon::On);\n";
+ writeIconAddFile(output, indent, iconName, i->elementActiveOn()->text(),
+ "Active", "On");
}
if (i->hasElementSelectedOff()) {
- output << indent << iconName << ".addFile(QString::fromUtf8("
- << fixString(i->elementSelectedOff()->text(), indent)
- << "), QSize(), QIcon::Selected, QIcon::Off);\n";
+ writeIconAddFile(output, indent, iconName, i->elementSelectedOff()->text(),
+ "Selected", "Off");
}
if (i->hasElementSelectedOn()) {
- output << indent << iconName << ".addFile(QString::fromUtf8("
- << fixString(i->elementSelectedOn()->text(), indent)
- << "), QSize(), QIcon::Selected, QIcon::On);\n";
+ writeIconAddFile(output, indent, iconName, i->elementSelectedOff()->text(),
+ "Selected", "On");
}
}
+static void writeIconAddPixmap(QTextStream &output, const QString &indent,
+ const QString &iconName, const QString &call,
+ const char *mode, const char *state)
+{
+ output << indent << iconName << ".addPixmap(" << call << ", QIcon"
+ << language::qualifier << mode << ", QIcon" << language::qualifier
+ << state << ')' << language::eol;
+}
+
void WriteInitialization::writePixmapFunctionIcon(QTextStream &output,
const QString &iconName,
const QString &indent,
const DomResourceIcon *i) const
{
if (i->hasElementNormalOff()) {
- output << indent << iconName << ".addPixmap("
- << pixCall(QLatin1String("QPixmap"), i->elementNormalOff()->text())
- << ", QIcon::Normal, QIcon::Off);\n";
+ writeIconAddPixmap(output, indent, iconName,
+ pixCall(QLatin1String("QPixmap"), i->elementNormalOff()->text()),
+ "Normal", "Off");
}
if (i->hasElementNormalOn()) {
- output << indent << iconName << ".addPixmap("
- << pixCall(QLatin1String("QPixmap"), i->elementNormalOn()->text())
- << ", QIcon::Normal, QIcon::On);\n";
+ writeIconAddPixmap(output, indent, iconName,
+ pixCall(QLatin1String("QPixmap"), i->elementNormalOn()->text()),
+ "Normal", "On");
}
if (i->hasElementDisabledOff()) {
- output << indent << iconName << ".addPixmap("
- << pixCall(QLatin1String("QPixmap"), i->elementDisabledOff()->text())
- << ", QIcon::Disabled, QIcon::Off);\n";
+ writeIconAddPixmap(output, indent, iconName,
+ pixCall(QLatin1String("QPixmap"), i->elementDisabledOff()->text()),
+ "Disabled", "Off");
}
if (i->hasElementDisabledOn()) {
- output << indent << iconName << ".addPixmap("
- << pixCall(QLatin1String("QPixmap"), i->elementDisabledOn()->text())
- << ", QIcon::Disabled, QIcon::On);\n";
+ writeIconAddPixmap(output, indent, iconName,
+ pixCall(QLatin1String("QPixmap"), i->elementDisabledOn()->text()),
+ "Disabled", "On");
}
if (i->hasElementActiveOff()) {
- output << indent << iconName << ".addPixmap("
- << pixCall(QLatin1String("QPixmap"), i->elementActiveOff()->text())
- << ", QIcon::Active, QIcon::Off);\n";
+ writeIconAddPixmap(output, indent, iconName,
+ pixCall(QLatin1String("QPixmap"), i->elementActiveOff()->text()),
+ "Active", "Off");
}
if (i->hasElementActiveOn()) {
- output << indent << iconName << ".addPixmap("
- << pixCall(QLatin1String("QPixmap"), i->elementActiveOn()->text())
- << ", QIcon::Active, QIcon::On);\n";
+ writeIconAddPixmap(output, indent, iconName,
+ pixCall(QLatin1String("QPixmap"), i->elementActiveOn()->text()),
+ "Active", "On");
}
if (i->hasElementSelectedOff()) {
- output << indent << iconName << ".addPixmap("
- << pixCall(QLatin1String("QPixmap"), i->elementSelectedOff()->text())
- << ", QIcon::Selected, QIcon::Off);\n";
+ writeIconAddPixmap(output, indent, iconName,
+ pixCall(QLatin1String("QPixmap"), i->elementSelectedOff()->text()),
+ "Selected", "Off");
}
if (i->hasElementSelectedOn()) {
- output << indent << iconName << ".addPixmap("
- << pixCall(QLatin1String("QPixmap"), i->elementSelectedOn()->text())
- << ", QIcon::Selected, QIcon::On);\n";
+ writeIconAddPixmap(output, indent, iconName,
+ pixCall(QLatin1String("QPixmap"), i->elementSelectedOn()->text()),
+ "Selected", "On");
}
}
@@ -1698,57 +1747,76 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
// check cache
const IconHandle iconHandle(i);
const IconPropertiesNameMap::const_iterator it = m_iconPropertiesNameMap.constFind(iconHandle);
- if (it != m_iconPropertiesNameMap.constEnd()) {
+ if (it != m_iconPropertiesNameMap.constEnd())
return it.value();
- }
// insert with new name
const QString iconName = m_driver->unique(QLatin1String("icon"));
m_iconPropertiesNameMap.insert(IconHandle(i), iconName);
- if (isIconFormat44(i)) {
- if (i->attributeTheme().isEmpty()) {
- // No theme: Write resource icon as is
- m_output << m_indent << "QIcon " << iconName << ";\n";
- if (m_uic->pixmapFunction().isEmpty())
- writeResourceIcon(m_output, iconName, m_indent, i);
- else
- writePixmapFunctionIcon(m_output, iconName, m_indent, i);
- } else {
- // Theme: Generate code to check the theme and default to resource
- const QString themeIconName = fixString(i->attributeTheme(), QString());
- if (iconHasStatePixmaps(i)) {
- // Theme + default state pixmaps:
- // Generate code to check the theme and default to state pixmaps
- m_output << m_indent << "QIcon " << iconName << ";\n";
- const char themeNameStringVariableC[] = "iconThemeName";
- // Store theme name in a variable
- m_output << m_indent;
- if (m_firstThemeIcon) { // Declare variable string
- m_output << "QString ";
- m_firstThemeIcon = false;
- }
- m_output << themeNameStringVariableC << " = QString::fromUtf8("
- << themeIconName << ");\n";
- m_output << m_indent << "if (QIcon::hasThemeIcon("
- << themeNameStringVariableC
- << ")) {\n"
- << m_dindent << iconName << " = QIcon::fromTheme(" << themeNameStringVariableC << ");\n"
- << m_indent << "} else {\n";
- if (m_uic->pixmapFunction().isEmpty())
- writeResourceIcon(m_output, iconName, m_dindent, i);
- else
- writePixmapFunctionIcon(m_output, iconName, m_dindent, i);
- m_output << m_indent << "}\n";
- } else {
- // Theme, but no state pixmaps: Construct from theme directly.
- m_output << m_indent << "QIcon " << iconName
- << "(QIcon::fromTheme(QString::fromUtf8("
- << themeIconName << ")));\n";
- } // Theme, but not state
- } // >= 4.4
- } else { // pre-4.4 legacy
- m_output << m_indent << "const QIcon " << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text())<< ";\n";
+
+ const bool isCpp = language::language() == Language::Cpp;
+
+ if (Q_UNLIKELY(!isIconFormat44(i))) { // pre-4.4 legacy
+ m_output << m_indent;
+ if (isCpp)
+ m_output << "const QIcon ";
+ m_output << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text())
+ << language::eol;
+ return iconName;
+ }
+
+ // 4.4 onwards
+ if (i->attributeTheme().isEmpty()) {
+ // No theme: Write resource icon as is
+ m_output << m_indent << language::stackVariable("QIcon", iconName)
+ << language::eol;
+ if (m_uic->pixmapFunction().isEmpty())
+ writeResourceIcon(m_output, iconName, m_indent, i);
+ else
+ writePixmapFunctionIcon(m_output, iconName, m_indent, i);
+ return iconName;
}
+
+ // Theme: Generate code to check the theme and default to resource
+ if (iconHasStatePixmaps(i)) {
+ // Theme + default state pixmaps:
+ // Generate code to check the theme and default to state pixmaps
+ m_output << m_indent << language::stackVariable("QIcon", iconName) << ";\n";
+ const char themeNameStringVariableC[] = "iconThemeName";
+ // Store theme name in a variable
+ m_output << m_indent;
+ if (m_firstThemeIcon) { // Declare variable string
+ if (isCpp)
+ m_output << "QString ";
+ m_firstThemeIcon = false;
+ }
+ m_output << themeNameStringVariableC << " = "
+ << language::qstring(i->attributeTheme()) << language::eol;
+ m_output << m_indent << "if ";
+ if (isCpp)
+ m_output << '(';
+ m_output << "QIcon" << language::qualifier << "hasThemeIcon("
+ << themeNameStringVariableC << ')' << (isCpp ? ") {" : ":") << '\n'
+ << m_dindent << iconName << " = QIcon" << language::qualifier << "fromTheme("
+ << themeNameStringVariableC << ')' << language::eol
+ << m_indent << (isCpp ? "} else {" : "else:") << '\n';
+ if (m_uic->pixmapFunction().isEmpty())
+ writeResourceIcon(m_output, iconName, m_dindent, i);
+ else
+ writePixmapFunctionIcon(m_output, iconName, m_dindent, i);
+ m_output << m_indent;
+ if (isCpp)
+ m_output << '}';
+ m_output << '\n';
+ return iconName;
+ }
+
+ // Theme, but no state pixmaps: Construct from theme directly.
+ m_output << m_indent
+ << language::stackVariableWithInitParameters("QIcon", iconName)
+ << "QIcon" << language::qualifier << "fromTheme("
+ << language::qstring(i->attributeTheme()) << "))"
+ << language::eol;
return iconName;
}
@@ -1784,7 +1852,7 @@ void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QStri
const DomColor *color = colors.at(i);
m_output << m_indent << paletteName << ".setColor(" << group
- << ", " << "static_cast<QPalette::ColorRole>(" << QString::number(i) << ')'
+ << ", QPalette" << language::qualifier << language::paletteColorRole(i)
<< ", " << domColor2QString(color)
<< ");\n";
}
@@ -1801,8 +1869,9 @@ void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QStri
<< versionAdded.majorVersion() << ", " << versionAdded.minorVersion()
<< ", " << versionAdded.microVersion() << ")\n";
}
- m_output << m_indent << paletteName << ".setBrush(" << group
- << ", " << "QPalette::" << roleName
+ m_output << m_indent << paletteName << ".setBrush("
+ << language::enumValue(group) << ", "
+ << "QPalette" << language::qualifier << roleName
<< ", " << brushName << ");\n";
if (!versionAdded.isNull())
m_output << "#endif\n";
@@ -1849,31 +1918,36 @@ void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brush
const QString gradientType = gradient->attributeType();
const QString gradientName = m_driver->unique(QLatin1String("gradient"));
if (gradientType == QLatin1String("LinearGradient")) {
- m_output << m_indent << "QLinearGradient " << gradientName
- << '(' << gradient->attributeStartX()
+ m_output << m_indent
+ << language::stackVariableWithInitParameters("QLinearGradient", gradientName)
+ << gradient->attributeStartX()
<< ", " << gradient->attributeStartY()
<< ", " << gradient->attributeEndX()
- << ", " << gradient->attributeEndY() << ");\n";
+ << ", " << gradient->attributeEndY() << ')' << language::eol;
} else if (gradientType == QLatin1String("RadialGradient")) {
- m_output << m_indent << "QRadialGradient " << gradientName
- << '(' << gradient->attributeCentralX()
+ m_output << m_indent
+ << language::stackVariableWithInitParameters("QRadialGradient", gradientName)
+ << gradient->attributeCentralX()
<< ", " << gradient->attributeCentralY()
<< ", " << gradient->attributeRadius()
<< ", " << gradient->attributeFocalX()
- << ", " << gradient->attributeFocalY() << ");\n";
+ << ", " << gradient->attributeFocalY() << ')' << language::eol;
} else if (gradientType == QLatin1String("ConicalGradient")) {
- m_output << m_indent << "QConicalGradient " << gradientName
- << '(' << gradient->attributeCentralX()
+ m_output << m_indent
+ << language::stackVariableWithInitParameters("QConicalGradient", gradientName)
+ << gradient->attributeCentralX()
<< ", " << gradient->attributeCentralY()
- << ", " << gradient->attributeAngle() << ");\n";
+ << ", " << gradient->attributeAngle() << ')' << language::eol;
}
- m_output << m_indent << gradientName << ".setSpread(QGradient::"
- << gradient->attributeSpread() << ");\n";
+ m_output << m_indent << gradientName << ".setSpread(QGradient"
+ << language::qualifier << gradient->attributeSpread()
+ << ')' << language::eol;
if (gradient->hasAttributeCoordinateMode()) {
- m_output << m_indent << gradientName << ".setCoordinateMode(QGradient::"
- << gradient->attributeCoordinateMode() << ");\n";
+ m_output << m_indent << gradientName << ".setCoordinateMode(QGradient"
+ << language::qualifier << gradient->attributeCoordinateMode()
+ << ')' << language::eol;
}
const auto &stops = gradient->elementGradientStop();
@@ -1881,23 +1955,26 @@ void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brush
const DomColor *color = stop->elementColor();
m_output << m_indent << gradientName << ".setColorAt("
<< stop->attributePosition() << ", "
- << domColor2QString(color) << ");\n";
+ << domColor2QString(color) << ')' << language::eol;
}
- m_output << m_indent << "QBrush " << brushName << '('
- << gradientName << ");\n";
+ m_output << m_indent
+ << language::stackVariableWithInitParameters("QBrush", brushName)
+ << gradientName << ')' << language::eol;
} else if (style == QLatin1String("TexturePattern")) {
const DomProperty *property = brush->elementTexture();
const QString iconValue = iconCall(property);
- m_output << m_indent << "QBrush " << brushName << " = QBrush("
- << iconValue << ");\n";
+ m_output << m_indent
+ << language::stackVariableWithInitParameters("QBrush", brushName)
+ << iconValue << ')' << language::eol;
} else {
const DomColor *color = brush->elementColor();
- m_output << m_indent << "QBrush " << brushName << '('
- << domColor2QString(color) << ");\n";
+ m_output << m_indent
+ << language::stackVariableWithInitParameters("QBrush", brushName)
+ << domColor2QString(color) << ')' << language::eol;
m_output << m_indent << brushName << ".setStyle("
- << "Qt::" << style << ");\n";
+ << language::qtQualifier << style << ')' << language::eol;
}
}
@@ -1917,12 +1994,11 @@ void WriteInitialization::acceptTabStops(DomTabStops *tabStops)
const QStringList l = tabStops->elementTabStop();
for (int i=0; i<l.size(); ++i) {
- const QString &name = l.at(i);
+ const QString name = m_driver->widgetVariableName(l.at(i));
- if (!m_registeredWidgets.contains(name)) {
+ if (name.isEmpty()) {
fprintf(stderr, "%s: Warning: Tab-stop assignment: '%s' is not a valid widget.\n",
- qPrintable(m_option.messagePrefix()),
- name.toLatin1().data());
+ qPrintable(m_option.messagePrefix()), qPrintable(l.at(i)));
continue;
}
@@ -1933,7 +2009,8 @@ void WriteInitialization::acceptTabStops(DomTabStops *tabStops)
if (name.isEmpty() || lastName.isEmpty())
continue;
- m_output << m_indent << "QWidget::setTabOrder(" << lastName << ", " << name << ");\n";
+ m_output << m_indent << "QWidget" << language::qualifier << "setTabOrder("
+ << lastName << ", " << name << ')' << language::eol;
lastName = name;
}
@@ -1975,15 +2052,14 @@ QString WriteInitialization::pixCall(const QString &t, const QString &text) cons
return type;
}
+ QTextStream str(&type);
+ str << '(';
QString pixFunc = m_uic->pixmapFunction();
if (pixFunc.isEmpty())
- pixFunc = QLatin1String("QString::fromUtf8");
-
- type += QLatin1Char('(')
- + pixFunc
- + QLatin1Char('(')
- + fixString(text, m_dindent)
- + QLatin1String("))");
+ str << language::qstring(text, m_dindent);
+ else
+ str << pixFunc << '(' << language::charliteral(text, m_dindent) << ')';
+ str << ')';
return type;
}
@@ -2006,13 +2082,15 @@ void WriteInitialization::initializeComboBox(DomWidget *w)
if (icon)
iconValue = iconCall(icon);
- m_output << m_indent << varName << "->addItem(";
+ m_output << m_indent << varName << language::derefPointer << "addItem(";
if (icon)
m_output << iconValue << ", ";
if (needsTranslation(text->elementString())) {
m_output << "QString());\n";
- m_refreshOut << m_indent << varName << "->setItemText(" << i << ", " << trCall(text->elementString()) << ");\n";
+ m_refreshOut << m_indent << varName << language::derefPointer
+ << "setItemText(" << i << ", " << trCall(text->elementString())
+ << ')' << language::eol;
} else {
m_output << noTrCall(text->elementString()) << ");\n";
}
@@ -2027,9 +2105,13 @@ QString WriteInitialization::disableSorting(DomWidget *w, const QString &varName
if (!w->elementItem().isEmpty()) {
tempName = m_driver->unique(QLatin1String("__sortingEnabled"));
m_refreshOut << "\n";
- m_refreshOut << m_indent << "const bool " << tempName
- << " = " << varName << "->isSortingEnabled();\n";
- m_refreshOut << m_indent << varName << "->setSortingEnabled(false);\n";
+ m_refreshOut << m_indent;
+ if (language::language() == Language::Cpp)
+ m_refreshOut << "const bool ";
+ m_refreshOut << tempName << " = " << varName << language::derefPointer
+ << "isSortingEnabled()" << language::eol
+ << m_indent << varName << language::derefPointer
+ << "setSortingEnabled(" << language::boolValue(false) << ')' << language::eol;
}
return tempName;
}
@@ -2037,7 +2119,8 @@ QString WriteInitialization::disableSorting(DomWidget *w, const QString &varName
void WriteInitialization::enableSorting(DomWidget *w, const QString &varName, const QString &tempName)
{
if (!w->elementItem().isEmpty()) {
- m_refreshOut << m_indent << varName << "->setSortingEnabled(" << tempName << ");\n\n";
+ m_refreshOut << m_indent << varName << language::derefPointer
+ << "setSortingEnabled(" << tempName << ')' << language::eol << '\n';
}
}
@@ -2059,10 +2142,15 @@ void WriteInitialization::enableSorting(DomWidget *w, const QString &varName, co
void WriteInitialization::addInitializer(Item *item,
const QString &name, int column, const QString &value, const QString &directive, bool translatable) const
{
- if (!value.isEmpty())
- item->addSetter(QLatin1String("->set") + name.at(0).toUpper() + name.midRef(1) +
- QLatin1Char('(') + (column < 0 ? QString() : QString::number(column) +
- QLatin1String(", ")) + value + QLatin1String(");"), directive, translatable);
+ if (!value.isEmpty()) {
+ QString setter;
+ QTextStream str(&setter);
+ str << language::derefPointer << "set" << name.at(0).toUpper() << name.midRef(1) << '(';
+ if (column >= 0)
+ str << column << ", ";
+ str << value << ");";
+ item->addSetter(setter, directive, translatable);
+ }
}
/*!
@@ -2107,10 +2195,11 @@ void WriteInitialization::addQtFlagsInitializer(Item *item,
const DomPropertyMap &properties, const QString &name, int column) const
{
if (const DomProperty *p = properties.value(name)) {
+ const QString orOperator = QLatin1Char('|') + language::qtQualifier;
QString v = p->elementSet();
if (!v.isEmpty()) {
- v.replace(QLatin1Char('|'), QLatin1String("|Qt::"));
- addInitializer(item, name, column, QLatin1String("Qt::") + v);
+ v.replace(QLatin1Char('|'), orOperator);
+ addInitializer(item, name, column, language::qtQualifier + v);
}
}
}
@@ -2125,7 +2214,7 @@ void WriteInitialization::addQtEnumInitializer(Item *item,
if (const DomProperty *p = properties.value(name)) {
QString v = p->elementEnum();
if (!v.isEmpty())
- addInitializer(item, name, column, QLatin1String("Qt::") + v);
+ addInitializer(item, name, column, language::qtQualifier + v);
}
}
@@ -2144,9 +2233,12 @@ void WriteInitialization::addCommonInitializers(Item *item,
addQtFlagsInitializer(item, properties, QLatin1String("textAlignment"), column);
addQtEnumInitializer(item, properties, QLatin1String("checkState"), column);
addStringInitializer(item, properties, QLatin1String("text"), column);
- addStringInitializer(item, properties, QLatin1String("toolTip"), column, QLatin1String(toolTipDefineC));
- addStringInitializer(item, properties, QLatin1String("whatsThis"), column, QLatin1String(whatsThisDefineC));
- addStringInitializer(item, properties, QLatin1String("statusTip"), column, QLatin1String(statusTipDefineC));
+ addStringInitializer(item, properties, QLatin1String("toolTip"), column,
+ toolTipConfigKey());
+ addStringInitializer(item, properties, QLatin1String("whatsThis"), column,
+ whatsThisConfigKey());
+ addStringInitializer(item, properties, QLatin1String("statusTip"), column,
+ statusTipConfigKey());
}
void WriteInitialization::initializeListWidget(DomWidget *w)
@@ -2171,7 +2263,9 @@ void WriteInitialization::initializeListWidget(DomWidget *w)
addCommonInitializers(&item, properties);
item.writeSetupUi(varName);
- item.writeRetranslateUi(varName + QLatin1String("->item(") + QString::number(i) + QLatin1Char(')'));
+ QString parentPath;
+ QTextStream(&parentPath) << varName << language::derefPointer << "item(" << i << ')';
+ item.writeRetranslateUi(parentPath);
}
enableSorting(w, varName, tempName);
}
@@ -2192,14 +2286,19 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w)
if (const DomProperty *p = properties.value(QLatin1String("text"))) {
DomString *str = p->elementString();
- if (str && str->text().isEmpty())
- m_output << m_indent << varName << "->headerItem()->setText(" << i << ", QString());\n";
+ if (str && str->text().isEmpty()) {
+ m_output << m_indent << varName << language::derefPointer
+ << "headerItem()" << language::derefPointer << "setText("
+ << i << ", QString())" << language::eol;
+ }
}
}
const QString itemName = item.writeSetupUi(QString(), Item::DontConstruct);
- item.writeRetranslateUi(varName + QLatin1String("->headerItem()"));
- if (!itemName.isNull())
- m_output << m_indent << varName << "->setHeaderItem(" << itemName << ");\n";
+ item.writeRetranslateUi(varName + language::derefPointer + QLatin1String("headerItem()"));
+ if (!itemName.isNull()) {
+ m_output << m_indent << varName << language::derefPointer
+ << "setHeaderItem(" << itemName << ')' << language::eol;
+ }
if (w->elementItem().empty())
return;
@@ -2210,7 +2309,9 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w)
for (int i = 0; i < items.count(); i++) {
Item *itm = items[i];
itm->writeSetupUi(varName);
- itm->writeRetranslateUi(varName + QLatin1String("->topLevelItem(") + QString::number(i) + QLatin1Char(')'));
+ QString parentPath;
+ QTextStream(&parentPath) << varName << language::derefPointer << "topLevelItem(" << i << ')';
+ itm->writeRetranslateUi(parentPath);
delete itm;
}
@@ -2272,8 +2373,10 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
const auto &columns = w->elementColumn();
if (!columns.empty()) {
- m_output << m_indent << "if (" << varName << "->columnCount() < " << columns.size() << ")\n"
- << m_dindent << varName << "->setColumnCount(" << columns.size() << ");\n";
+ m_output << m_indent << "if (" << varName << language::derefPointer << "columnCount() < "
+ << columns.size() << ")\n"
+ << m_dindent << varName << language::derefPointer << "setColumnCount("
+ << columns.size() << ')' << language::eol;
}
for (int i = 0; i < columns.size(); ++i) {
@@ -2285,8 +2388,12 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
addCommonInitializers(&item, properties);
QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
- item.writeRetranslateUi(varName + QLatin1String("->horizontalHeaderItem(") + QString::number(i) + QLatin1Char(')'));
- m_output << m_indent << varName << "->setHorizontalHeaderItem(" << QString::number(i) << ", " << itemName << ");\n";
+ QString parentPath;
+ QTextStream(&parentPath) << varName << language::derefPointer
+ << "horizontalHeaderItem(" << i << ')';
+ item.writeRetranslateUi(parentPath);
+ m_output << m_indent << varName << language::derefPointer << "setHorizontalHeaderItem("
+ << i << ", " << itemName << ')' << language::eol;
}
}
@@ -2294,8 +2401,9 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
const auto &rows = w->elementRow();
if (!rows.isEmpty()) {
- m_output << m_indent << "if (" << varName << "->rowCount() < " << rows.size() << ")\n"
- << m_dindent << varName << "->setRowCount(" << rows.size() << ");\n";
+ m_output << m_indent << "if (" << varName << language::derefPointer << "rowCount() < " << rows.size() << ")\n"
+ << m_dindent << varName << language::derefPointer << "setRowCount("
+ << rows.size() << ')' << language::eol;
}
for (int i = 0; i < rows.size(); ++i) {
@@ -2307,8 +2415,11 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
addCommonInitializers(&item, properties);
QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
- item.writeRetranslateUi(varName + QLatin1String("->verticalHeaderItem(") + QString::number(i) + QLatin1Char(')'));
- m_output << m_indent << varName << "->setVerticalHeaderItem(" << QString::number(i) << ", " << itemName << ");\n";
+ QString parentPath;
+ QTextStream(&parentPath) << varName << language::derefPointer << "verticalHeaderItem(" << i << ')';
+ item.writeRetranslateUi(parentPath);
+ m_output << m_indent << varName << language::derefPointer << "setVerticalHeaderItem("
+ << i << ", " << itemName << ')' << language::eol;
}
}
@@ -2328,8 +2439,12 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
addCommonInitializers(&item, properties);
QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
- item.writeRetranslateUi(varName + QLatin1String("->item(") + QString::number(r) + QLatin1String(", ") + QString::number(c) + QLatin1Char(')'));
- m_output << m_indent << varName << "->setItem(" << QString::number(r) << ", " << QString::number(c) << ", " << itemName << ");\n";
+ QString parentPath;
+ QTextStream(&parentPath) << varName << language::derefPointer << "item(" << r
+ << ", " << c << ')';
+ item.writeRetranslateUi(parentPath);
+ m_output << m_indent << varName << language::derefPointer << "setItem("
+ << r << ", " << c << ", " << itemName << ')' << language::eol;
}
}
enableSorting(w, varName, tempName);
@@ -2337,32 +2452,37 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
QString WriteInitialization::trCall(const QString &str, const QString &commentHint, const QString &id) const
{
- if (str.isEmpty())
- return QLatin1String("QString()");
+ if (str.isEmpty()) {
+ return language::language() == Language::Cpp
+ ? QLatin1String("QString()") : QLatin1String("\"\"");
+ }
QString result;
- const QString comment = commentHint.isEmpty() ? QString(QLatin1String("nullptr")) : fixString(commentHint, m_dindent);
+ QTextStream ts(&result);
const bool idBasedTranslations = m_driver->useIdBasedTranslations();
if (m_option.translateFunction.isEmpty()) {
if (idBasedTranslations || m_option.idBased) {
- result += QLatin1String("qtTrId(");
+ ts << "qtTrId(";
} else {
- result += QLatin1String("QApplication::translate(\"")
- + m_generatedClass
- + QLatin1String("\", ");
+ ts << "QCoreApplication" << language::qualifier << "translate("
+ << '"' << m_generatedClass << "\", ";
}
} else {
- result += m_option.translateFunction + QLatin1Char('(');
+ ts << m_option.translateFunction << '(';
}
- result += fixString(idBasedTranslations ? id : str, m_dindent);
+ ts << language::charliteral(idBasedTranslations ? id : str, m_dindent);
if (!idBasedTranslations && !m_option.idBased) {
- result += QLatin1String(", ") + comment;
+ ts << ", ";
+ if (commentHint.isEmpty())
+ ts << language::nullPtr;
+ else
+ ts << language::charliteral(commentHint, m_dindent);
}
- result += QLatin1Char(')');
+ ts << ')';
return result;
}
@@ -2373,7 +2493,8 @@ void WriteInitialization::initializeMenu(DomWidget *w, const QString &/*parentWi
const DomAction *action = m_driver->actionByName(menuAction);
if (action && action->hasAttributeMenu()) {
- m_output << m_indent << menuAction << " = " << menuName << "->menuAction();\n";
+ m_output << m_indent << menuAction << " = " << menuName
+ << language::derefPointer << "menuAction()" << language::eol;
}
}
@@ -2397,9 +2518,9 @@ QString WriteInitialization::noTrCall(DomString *str, const QString &defaultStri
return QString();
if (str)
value = str->text();
- QString ret = QLatin1String("QString::fromUtf8(");
- ret += fixString(value, m_dindent);
- ret += QLatin1Char(')');
+ QString ret;
+ QTextStream ts(&ret);
+ ts << language::qstring(value, m_dindent);
return ret;
}
@@ -2427,54 +2548,42 @@ QTextStream &WriteInitialization::autoTrOutput(const DomString *str, const QStri
return m_output;
}
-bool WriteInitialization::isValidObject(const QString &name) const
+WriteInitialization::Declaration WriteInitialization::findDeclaration(const QString &name)
{
- return m_registeredWidgets.contains(name)
- || m_registeredActions.contains(name);
-}
-
-QString WriteInitialization::findDeclaration(const QString &name)
-{
- const QString normalized = Driver::normalizedName(name);
-
- if (DomWidget *widget = m_driver->widgetByName(normalized))
- return m_driver->findOrInsertWidget(widget);
- if (DomAction *action = m_driver->actionByName(normalized))
- return m_driver->findOrInsertAction(action);
- if (const DomButtonGroup *group = m_driver->findButtonGroup(normalized))
- return m_driver->findOrInsertButtonGroup(group);
- return QString();
+ if (const DomWidget *widget = m_driver->widgetByName(name))
+ return {m_driver->findOrInsertWidget(widget), widget->attributeClass()};
+ if (const DomAction *action = m_driver->actionByName(name))
+ return {m_driver->findOrInsertAction(action), QStringLiteral("QAction")};
+ if (const DomButtonGroup *group = m_driver->findButtonGroup(name))
+ return {m_driver->findOrInsertButtonGroup(group), QStringLiteral("QButtonGroup")};
+ return {};
}
void WriteInitialization::acceptConnection(DomConnection *connection)
{
- const QString sender = findDeclaration(connection->elementSender());
- const QString receiver = findDeclaration(connection->elementReceiver());
-
- if (sender.isEmpty() || receiver.isEmpty())
- return;
+ const QString senderName = connection->elementSender();
+ const QString receiverName = connection->elementReceiver();
- m_output << m_indent << "QObject::connect("
- << sender
- << ", "
- << "SIGNAL("<<connection->elementSignal()<<')'
- << ", "
- << receiver
- << ", "
- << "SLOT("<<connection->elementSlot()<<')'
- << ");\n";
-}
+ const auto senderDecl = findDeclaration(senderName);
+ const auto receiverDecl = findDeclaration(receiverName);
-DomWidget *WriteInitialization::findWidget(QLatin1String widgetClass)
-{
- for (int i = m_widgetChain.count() - 1; i >= 0; --i) {
- DomWidget *widget = m_widgetChain.at(i);
-
- if (widget && m_uic->customWidgetsInfo()->extends(widget->attributeClass(), widgetClass))
- return widget;
+ if (senderDecl.name.isEmpty() || receiverDecl.name.isEmpty()) {
+ QString message;
+ QTextStream(&message) << m_option.messagePrefix()
+ << ": Warning: Invalid signal/slot connection: \""
+ << senderName << "\" -> \"" << receiverName << "\".";
+ fprintf(stderr, "%s\n", qPrintable(message));
+ return;
}
- return 0;
+ language::SignalSlot theSignal{senderDecl.name, connection->elementSignal(),
+ senderDecl.className};
+ language::SignalSlot theSlot{receiverDecl.name, connection->elementSlot(),
+ receiverDecl.className};
+
+ m_output << m_indent;
+ language::formatConnection(m_output, theSignal, theSlot);
+ m_output << ";\n";
}
static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet<QString> &directives)
@@ -2483,15 +2592,18 @@ static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet<QS
return;
if (directives.size() == 1) {
- outputStream << "#ifndef " << *directives.cbegin() << endl;
+ outputStream << language::openQtConfig(*directives.cbegin());
return;
}
- auto list = directives.toList();
+ auto list = directives.values();
// sort (always generate in the same order):
std::sort(list.begin(), list.end());
- outputStream << "#if !defined(" << list.join(QLatin1String(") || !defined(")) << ')' << endl;
+ outputStream << "#if " << language::qtConfig(list.constFirst());
+ for (int i = 1, size = list.size(); i < size; ++i)
+ outputStream << " || " << language::qtConfig(list.at(i));
+ outputStream << Qt::endl;
}
static void generateMultiDirectiveEnd(QTextStream &outputStream, const QSet<QString> &directives)
@@ -2499,12 +2611,11 @@ static void generateMultiDirectiveEnd(QTextStream &outputStream, const QSet<QStr
if (directives.isEmpty())
return;
- outputStream << "#endif" << endl;
+ outputStream << "#endif" << Qt::endl;
}
WriteInitialization::Item::Item(const QString &itemClassName, const QString &indent, QTextStream &setupUiStream, QTextStream &retranslateUiStream, Driver *driver)
:
- m_parent(0),
m_itemClassName(itemClassName),
m_indent(indent),
m_setupUiStream(setupUiStream),
@@ -2527,7 +2638,8 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp
bool generateMultiDirective = false;
if (emptyItemPolicy == Item::ConstructItemOnly && m_children.isEmpty()) {
if (m_setupUiData.policy == ItemData::DontGenerate) {
- m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n";
+ m_setupUiStream << m_indent << language::operatorNew << m_itemClassName
+ << '(' << parent << ')' << language::eol;
return QString();
}
if (m_setupUiData.policy == ItemData::GenerateWithMultiDirective)
@@ -2538,19 +2650,27 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp
generateMultiDirectiveBegin(m_setupUiStream, m_setupUiData.directives);
const QString uniqueName = m_driver->unique(QLatin1String("__") + m_itemClassName.toLower());
- m_setupUiStream << m_indent << m_itemClassName << " *" << uniqueName << " = new " << m_itemClassName << '(' << parent << ");\n";
+ m_setupUiStream << m_indent;
+ if (language::language() == Language::Cpp)
+ m_setupUiStream << m_itemClassName << " *";
+ m_setupUiStream << uniqueName
+ << " = " << language::operatorNew << m_itemClassName << '(' << parent
+ << ')' << language::eol;
if (generateMultiDirective) {
m_setupUiStream << "#else\n";
- m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n";
+ m_setupUiStream << m_indent << language::operatorNew << m_itemClassName
+ << '(' << parent << ')' << language::eol;
generateMultiDirectiveEnd(m_setupUiStream, m_setupUiData.directives);
}
QMultiMap<QString, QString>::ConstIterator it = m_setupUiData.setters.constBegin();
while (it != m_setupUiData.setters.constEnd()) {
- openIfndef(m_setupUiStream, it.key());
- m_setupUiStream << m_indent << uniqueName << it.value() << endl;
- closeIfndef(m_setupUiStream, it.key());
+ if (!it.key().isEmpty())
+ m_setupUiStream << language::openQtConfig(it.key());
+ m_setupUiStream << m_indent << uniqueName << it.value() << Qt::endl;
+ if (!it.key().isEmpty())
+ m_setupUiStream << language::closeQtConfig(it.key());
++it;
}
for (Item *child : qAsConst(m_children))
@@ -2567,7 +2687,10 @@ void WriteInitialization::Item::writeRetranslateUi(const QString &parentPath)
generateMultiDirectiveBegin(m_retranslateUiStream, m_retranslateUiData.directives);
const QString uniqueName = m_driver->unique(QLatin1String("___") + m_itemClassName.toLower());
- m_retranslateUiStream << m_indent << m_itemClassName << " *" << uniqueName << " = " << parentPath << ";\n";
+ m_retranslateUiStream << m_indent;
+ if (language::language() == Language::Cpp)
+ m_retranslateUiStream << m_itemClassName << " *";
+ m_retranslateUiStream << uniqueName << " = " << parentPath << language::eol;
if (m_retranslateUiData.policy == ItemData::GenerateWithMultiDirective)
generateMultiDirectiveEnd(m_retranslateUiStream, m_retranslateUiData.directives);
@@ -2577,17 +2700,23 @@ void WriteInitialization::Item::writeRetranslateUi(const QString &parentPath)
while (it != m_retranslateUiData.setters.constEnd()) {
const QString newDirective = it.key();
if (oldDirective != newDirective) {
- closeIfndef(m_retranslateUiStream, oldDirective);
- openIfndef(m_retranslateUiStream, newDirective);
+ if (!oldDirective.isEmpty())
+ m_retranslateUiStream << language::closeQtConfig(oldDirective);
+ if (!newDirective.isEmpty())
+ m_retranslateUiStream << language::openQtConfig(newDirective);
oldDirective = newDirective;
}
- m_retranslateUiStream << m_indent << uniqueName << it.value() << endl;
+ m_retranslateUiStream << m_indent << uniqueName << it.value() << Qt::endl;
++it;
}
- closeIfndef(m_retranslateUiStream, oldDirective);
+ if (!oldDirective.isEmpty())
+ m_retranslateUiStream << language::closeQtConfig(oldDirective);
- for (int i = 0; i < m_children.size(); i++)
- m_children[i]->writeRetranslateUi(uniqueName + QLatin1String("->child(") + QString::number(i) + QLatin1Char(')'));
+ for (int i = 0; i < m_children.size(); i++) {
+ QString method;
+ QTextStream(&method) << uniqueName << language::derefPointer << "child(" << i << ')';
+ m_children[i]->writeRetranslateUi(method);
+ }
}
void WriteInitialization::Item::addSetter(const QString &setter, const QString &directive, bool translatable)
diff --git a/src/tools/uic/cpp/cppwriteinitialization.h b/src/tools/uic/cpp/cppwriteinitialization.h
index cce83bd677..3cd0efeaac 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.h
+++ b/src/tools/uic/cpp/cppwriteinitialization.h
@@ -85,8 +85,8 @@ namespace CPP {
struct WriteInitialization : public TreeWalker
{
- typedef QList<DomProperty*> DomPropertyList;
- typedef QHash<QString, DomProperty*> DomPropertyMap;
+ using DomPropertyList = QList<DomProperty*>;
+ using DomPropertyMap = QHash<QString, DomProperty*>;
WriteInitialization(Uic *uic);
@@ -161,7 +161,7 @@ private:
// special initialization
//
class Item {
- Q_DISABLE_COPY(Item)
+ Q_DISABLE_COPY_MOVE(Item)
public:
Item(const QString &itemClassName, const QString &indent, QTextStream &setupUiStream, QTextStream &retranslateUiStream, Driver *driver);
~Item();
@@ -174,8 +174,6 @@ private:
void writeRetranslateUi(const QString &parentPath);
void addSetter(const QString &setter, const QString &directive = QString(), bool translatable = false); // don't call it if you already added *this as a child of another Item
void addChild(Item *child); // all setters should already been added
- int setupUiCount() const { return m_setupUiData.setters.count(); }
- int retranslateUiCount() const { return m_retranslateUiData.setters.count(); }
private:
struct ItemData
{
@@ -190,7 +188,7 @@ private:
ItemData m_setupUiData;
ItemData m_retranslateUiData;
QList<Item *> m_children;
- Item *m_parent;
+ Item *m_parent = nullptr;
const QString m_itemClassName;
const QString m_indent;
@@ -222,10 +220,13 @@ private:
QString disableSorting(DomWidget *w, const QString &varName);
void enableSorting(DomWidget *w, const QString &varName, const QString &tempName);
- QString findDeclaration(const QString &name);
- DomWidget *findWidget(QLatin1String widgetClass);
+ struct Declaration
+ {
+ QString name;
+ QString className;
+ };
- bool isValidObject(const QString &name) const;
+ Declaration findDeclaration(const QString &name);
private:
QString writeFontProperties(const DomFont *f);
@@ -247,8 +248,8 @@ private:
struct Buddy
{
- QString objName;
- QString buddy;
+ QString labelVarName;
+ QString buddyAttributeName;
};
friend class QTypeInfo<Buddy>;
@@ -258,15 +259,13 @@ private:
QVector<Buddy> m_buddies;
QSet<QString> m_buttonGroups;
- QHash<QString, DomWidget*> m_registeredWidgets;
- QHash<QString, DomAction*> m_registeredActions;
- typedef QHash<uint, QString> ColorBrushHash;
+ using ColorBrushHash = QHash<uint, QString>;
ColorBrushHash m_colorBrushHash;
// Map from font properties to font variable name for reuse
// Map from size policy to variable for reuse
- typedef QMap<FontHandle, QString> FontPropertiesNameMap;
- typedef QMap<IconHandle, QString> IconPropertiesNameMap;
- typedef QMap<SizePolicyHandle, QString> SizePolicyNameMap;
+ using FontPropertiesNameMap = QMap<FontHandle, QString>;
+ using IconPropertiesNameMap = QMap<IconHandle, QString>;
+ using SizePolicyNameMap = QMap<SizePolicyHandle, QString>;
FontPropertiesNameMap m_fontPropertiesNameMap;
IconPropertiesNameMap m_iconPropertiesNameMap;
SizePolicyNameMap m_sizePolicyNameMap;
diff --git a/src/tools/uic/customwidgetsinfo.cpp b/src/tools/uic/customwidgetsinfo.cpp
index 0ac0c2b6a3..d6a409152b 100644
--- a/src/tools/uic/customwidgetsinfo.cpp
+++ b/src/tools/uic/customwidgetsinfo.cpp
@@ -31,6 +31,8 @@
#include "ui4.h"
#include "utils.h"
+#include <utility>
+
QT_BEGIN_NAMESPACE
CustomWidgetsInfo::CustomWidgetsInfo() = default;
@@ -73,6 +75,24 @@ bool CustomWidgetsInfo::extends(const QString &classNameIn, QLatin1String baseCl
return false;
}
+bool CustomWidgetsInfo::extendsOneOf(const QString &classNameIn,
+ const QStringList &baseClassNames) const
+{
+ if (baseClassNames.contains(classNameIn))
+ return true;
+
+ QString className = classNameIn;
+ while (const DomCustomWidget *c = customWidget(className)) {
+ const QString extends = c->elementExtends();
+ if (className == extends) // Faulty legacy custom widget entries exist.
+ return false;
+ if (baseClassNames.contains(extends))
+ return true;
+ className = extends;
+ }
+ return false;
+}
+
bool CustomWidgetsInfo::isCustomWidgetContainer(const QString &className) const
{
if (const DomCustomWidget *dcw = m_customWidgets.value(className, 0))
@@ -96,5 +116,24 @@ QString CustomWidgetsInfo::customWidgetAddPageMethod(const QString &name) const
return QString();
}
+// add page methods for simple containers taking only the widget parameter
+QString CustomWidgetsInfo::simpleContainerAddPageMethod(const QString &name) const
+{
+ using AddPageMethod = std::pair<const char *, const char *>;
+
+ static AddPageMethod addPageMethods[] = {
+ {"QStackedWidget", "addWidget"},
+ {"QToolBar", "addWidget"},
+ {"QDockWidget", "setWidget"},
+ {"QScrollArea", "setWidget"},
+ {"QSplitter", "addWidget"},
+ {"QMdiArea", "addSubWindow"}
+ };
+ for (const auto &m : addPageMethods) {
+ if (extends(name, QLatin1String(m.first)))
+ return QLatin1String(m.second);
+ }
+ return QString();
+}
QT_END_NAMESPACE
diff --git a/src/tools/uic/customwidgetsinfo.h b/src/tools/uic/customwidgetsinfo.h
index 944ed59215..a1b24ab042 100644
--- a/src/tools/uic/customwidgetsinfo.h
+++ b/src/tools/uic/customwidgetsinfo.h
@@ -48,25 +48,21 @@ public:
void acceptCustomWidgets(DomCustomWidgets *node) override;
void acceptCustomWidget(DomCustomWidget *node) override;
- inline QStringList customWidgets() const
- { return m_customWidgets.keys(); }
-
- inline bool hasCustomWidget(const QString &name) const
- { return m_customWidgets.contains(name); }
-
inline DomCustomWidget *customWidget(const QString &name) const
{ return m_customWidgets.value(name); }
QString customWidgetAddPageMethod(const QString &name) const;
+ QString simpleContainerAddPageMethod(const QString &name) const;
QString realClassName(const QString &className) const;
bool extends(const QString &className, QLatin1String baseClassName) const;
+ bool extendsOneOf(const QString &className, const QStringList &baseClassNames) const;
bool isCustomWidgetContainer(const QString &className) const;
private:
- typedef QMap<QString, DomCustomWidget*> NameCustomWidgetMap;
+ using NameCustomWidgetMap = QMap<QString, DomCustomWidget*>;
NameCustomWidgetMap m_customWidgets;
};
diff --git a/src/tools/uic/databaseinfo.cpp b/src/tools/uic/databaseinfo.cpp
index fa5d5f5df0..9b0d1614ab 100644
--- a/src/tools/uic/databaseinfo.cpp
+++ b/src/tools/uic/databaseinfo.cpp
@@ -33,9 +33,7 @@
QT_BEGIN_NAMESPACE
-DatabaseInfo::DatabaseInfo()
-{
-}
+DatabaseInfo::DatabaseInfo() = default;
void DatabaseInfo::acceptUI(DomUI *node)
{
@@ -59,10 +57,9 @@ void DatabaseInfo::acceptWidget(DomWidget *node)
DomProperty *db = properties.value(QLatin1String("database"));
if (db && db->elementStringList()) {
QStringList info = db->elementStringList()->elementString();
-
- QString connection = info.size() > 0 ? info.at(0) : QString();
- if (connection.isEmpty())
+ if (info.isEmpty() || info.constFirst().isEmpty())
return;
+ const QString &connection = info.constFirst();
m_connections.append(connection);
QString table = info.size() > 1 ? info.at(1) : QString();
diff --git a/src/tools/uic/databaseinfo.h b/src/tools/uic/databaseinfo.h
index bebf139c5a..4015e39dbc 100644
--- a/src/tools/uic/databaseinfo.h
+++ b/src/tools/uic/databaseinfo.h
@@ -48,12 +48,6 @@ public:
inline QStringList connections() const
{ return m_connections; }
- inline QStringList cursors(const QString &connection) const
- { return m_cursors.value(connection); }
-
- inline QStringList fields(const QString &connection) const
- { return m_fields.value(connection); }
-
private:
QStringList m_connections;
QMap<QString, QStringList> m_cursors;
diff --git a/src/tools/uic/driver.cpp b/src/tools/uic/driver.cpp
index 91a48815fd..8b9b4806e6 100644
--- a/src/tools/uic/driver.cpp
+++ b/src/tools/uic/driver.cpp
@@ -30,9 +30,13 @@
#include "uic.h"
#include "ui4.h"
+#include <language.h>
+
#include <qfileinfo.h>
#include <qdebug.h>
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
Driver::Driver()
@@ -43,39 +47,62 @@ Driver::Driver()
Driver::~Driver() = default;
-QString Driver::findOrInsertWidget(DomWidget *ui_widget)
+static inline QString spacerItemClass() { return QStringLiteral("QSpacerItem"); }
+static inline QString actionGroupClass() { return QStringLiteral("QActionGroup"); }
+static inline QString actionClass() { return QStringLiteral("QAction"); }
+static inline QString buttonGroupClass() { return QStringLiteral("QButtonGroup"); }
+
+template <class DomClass>
+Driver::DomObjectHashConstIt<DomClass>
+ Driver::findByAttributeNameIt(const DomObjectHash<DomClass> &domHash,
+ const QString &name) const
{
- if (!m_widgets.contains(ui_widget))
- m_widgets.insert(ui_widget, unique(ui_widget->attributeName(), ui_widget->attributeClass()));
+ const auto end = domHash.cend();
+ for (auto it = domHash.cbegin(); it != end; ++it) {
+ if (it.key()->attributeName() == name)
+ return it;
+ }
+ return end;
+}
- return m_widgets.value(ui_widget);
+template <class DomClass>
+const DomClass *Driver::findByAttributeName(const DomObjectHash<DomClass> &domHash,
+ const QString &name) const
+{
+ auto it = findByAttributeNameIt(domHash, name);
+ return it != domHash.cend() ? it.key() : nullptr;
}
-QString Driver::findOrInsertSpacer(DomSpacer *ui_spacer)
+template <class DomClass>
+QString Driver::findOrInsert(DomObjectHash<DomClass> *domHash, const DomClass *dom,
+ const QString &className, bool isMember)
{
- if (!m_spacers.contains(ui_spacer)) {
- QString name;
- if (ui_spacer->hasAttributeName())
- name = ui_spacer->attributeName();
- m_spacers.insert(ui_spacer, unique(name, QLatin1String("QSpacerItem")));
+ auto it = domHash->find(dom);
+ if (it == domHash->end()) {
+ const QString name = this->unique(dom->attributeName(), className);
+ it = domHash->insert(dom, isMember ? language::self + name : name);
}
+ return it.value();
+}
- return m_spacers.value(ui_spacer);
+QString Driver::findOrInsertWidget(const DomWidget *ui_widget)
+{
+ // Top level is passed into setupUI(), everything else is a member variable
+ const bool isMember = !m_widgets.isEmpty();
+ return findOrInsert(&m_widgets, ui_widget, ui_widget->attributeClass(), isMember);
}
-QString Driver::findOrInsertLayout(DomLayout *ui_layout)
+QString Driver::findOrInsertSpacer(const DomSpacer *ui_spacer)
{
- if (!m_layouts.contains(ui_layout)) {
- QString name;
- if (ui_layout->hasAttributeName())
- name = ui_layout->attributeName();
- m_layouts.insert(ui_layout, unique(name, ui_layout->attributeClass()));
- }
+ return findOrInsert(&m_spacers, ui_spacer, spacerItemClass());
+}
- return m_layouts.value(ui_layout);
+QString Driver::findOrInsertLayout(const DomLayout *ui_layout)
+{
+ return findOrInsert(&m_layouts, ui_layout, ui_layout->attributeClass());
}
-QString Driver::findOrInsertLayoutItem(DomLayoutItem *ui_layoutItem)
+QString Driver::findOrInsertLayoutItem(const DomLayoutItem *ui_layoutItem)
{
switch (ui_layoutItem->kind()) {
case DomLayoutItem::Widget:
@@ -93,38 +120,25 @@ QString Driver::findOrInsertLayoutItem(DomLayoutItem *ui_layoutItem)
return QString();
}
-QString Driver::findOrInsertActionGroup(DomActionGroup *ui_group)
+QString Driver::findOrInsertActionGroup(const DomActionGroup *ui_group)
{
- if (!m_actionGroups.contains(ui_group))
- m_actionGroups.insert(ui_group, unique(ui_group->attributeName(), QLatin1String("QActionGroup")));
-
- return m_actionGroups.value(ui_group);
+ return findOrInsert(&m_actionGroups, ui_group, actionGroupClass());
}
-QString Driver::findOrInsertAction(DomAction *ui_action)
+QString Driver::findOrInsertAction(const DomAction *ui_action)
{
- if (!m_actions.contains(ui_action))
- m_actions.insert(ui_action, unique(ui_action->attributeName(), QLatin1String("QAction")));
-
- return m_actions.value(ui_action);
+ return findOrInsert(&m_actions, ui_action, actionClass());
}
QString Driver::findOrInsertButtonGroup(const DomButtonGroup *ui_group)
{
- ButtonGroupNameHash::iterator it = m_buttonGroups.find(ui_group);
- if (it == m_buttonGroups.end())
- it = m_buttonGroups.insert(ui_group, unique(ui_group->attributeName(), QLatin1String("QButtonGroup")));
- return it.value();
+ return findOrInsert(&m_buttonGroups, ui_group, buttonGroupClass());
}
// Find a group by its non-uniqified name
const DomButtonGroup *Driver::findButtonGroup(const QString &attributeName) const
{
- const ButtonGroupNameHash::const_iterator cend = m_buttonGroups.constEnd();
- for (ButtonGroupNameHash::const_iterator it = m_buttonGroups.constBegin(); it != cend; ++it)
- if (it.key()->attributeName() == attributeName)
- return it.key();
- return 0;
+ return findByAttributeName(m_buttonGroups, attributeName);
}
@@ -136,11 +150,9 @@ QString Driver::findOrInsertName(const QString &name)
QString Driver::normalizedName(const QString &name)
{
QString result = name;
- QChar *data = result.data();
- for (int i = name.size(); --i >= 0; ++data) {
- if (!data->isLetterOrNumber())
- *data = QLatin1Char('_');
- }
+ std::replace_if(result.begin(), result.end(),
+ [] (QChar c) { return !c.isLetterOrNumber(); },
+ QLatin1Char('_'));
return result;
}
@@ -149,23 +161,21 @@ QString Driver::unique(const QString &instanceName, const QString &className)
QString name;
bool alreadyUsed = false;
- if (instanceName.size()) {
- int id = 1;
- name = instanceName;
- name = normalizedName(name);
+ if (!instanceName.isEmpty()) {
+ name = normalizedName(instanceName);
QString base = name;
- while (m_nameRepository.contains(name)) {
+ for (int id = 1; m_nameRepository.contains(name); ++id) {
alreadyUsed = true;
- name = base + QString::number(id++);
+ name = base + QString::number(id);
}
- } else if (className.size()) {
+ } else if (!className.isEmpty()) {
name = unique(qtify(className));
} else {
name = unique(QLatin1String("var"));
}
- if (alreadyUsed && className.size()) {
+ if (alreadyUsed && !className.isEmpty()) {
fprintf(stderr, "%s: Warning: The name '%s' (%s) is already in use, defaulting to '%s'.\n",
qPrintable(m_option.messagePrefix()),
qPrintable(instanceName), qPrintable(className),
@@ -181,17 +191,10 @@ QString Driver::qtify(const QString &name)
QString qname = name;
if (qname.at(0) == QLatin1Char('Q') || qname.at(0) == QLatin1Char('K'))
- qname = qname.mid(1);
-
- int i=0;
- while (i < qname.length()) {
- if (qname.at(i).toLower() != qname.at(i))
- qname[i] = qname.at(i).toLower();
- else
- break;
+ qname.remove(0, 1);
- ++i;
- }
+ for (int i = 0, size = qname.size(); i < size && qname.at(i).isUpper(); ++i)
+ qname[i] = qname.at(i).toLower();
return qname;
}
@@ -253,7 +256,7 @@ bool Driver::uic(const QString &fileName, DomUI *ui, QTextStream *out)
QTextStream *oldOutput = m_output;
- m_output = out != 0 ? out : &m_stdout;
+ m_output = out != nullptr ? out : &m_stdout;
Uic tool(this);
const bool result = tool.write(ui);
@@ -306,58 +309,25 @@ bool Driver::uic(const QString &fileName, QTextStream *out)
return rtn;
}
-void Driver::reset()
-{
- Q_ASSERT( m_output == 0 );
-
- m_option = Option();
- m_output = 0;
- m_problems.clear();
-
- QStringList m_problems;
-
- m_widgets.clear();
- m_spacers.clear();
- m_layouts.clear();
- m_actionGroups.clear();
- m_actions.clear();
- m_nameRepository.clear();
- m_pixmaps.clear();
-}
-
-void Driver::insertPixmap(const QString &pixmap)
-{
- m_pixmaps.insert(pixmap, true);
-}
-
-bool Driver::containsPixmap(const QString &pixmap) const
-{
- return m_pixmaps.contains(pixmap);
-}
-
-DomWidget *Driver::widgetByName(const QString &name) const
-{
- return m_widgets.key(name);
-}
-
-DomSpacer *Driver::spacerByName(const QString &name) const
+const DomWidget *Driver::widgetByName(const QString &attributeName) const
{
- return m_spacers.key(name);
+ return findByAttributeName(m_widgets, attributeName);
}
-DomLayout *Driver::layoutByName(const QString &name) const
+QString Driver::widgetVariableName(const QString &attributeName) const
{
- return m_layouts.key(name);
+ auto it = findByAttributeNameIt(m_widgets, attributeName);
+ return it != m_widgets.cend() ? it.value() : QString();
}
-DomActionGroup *Driver::actionGroupByName(const QString &name) const
+const DomActionGroup *Driver::actionGroupByName(const QString &attributeName) const
{
- return m_actionGroups.key(name);
+ return findByAttributeName(m_actionGroups, attributeName);
}
-DomAction *Driver::actionByName(const QString &name) const
+const DomAction *Driver::actionByName(const QString &attributeName) const
{
- return m_actions.key(name);
+ return findByAttributeName(m_actions, attributeName);
}
QT_END_NAMESPACE
diff --git a/src/tools/uic/driver.h b/src/tools/uic/driver.h
index 1563bdbd83..45ec23b4aa 100644
--- a/src/tools/uic/driver.h
+++ b/src/tools/uic/driver.h
@@ -49,27 +49,20 @@ class DomButtonGroup;
class Driver
{
- Q_DISABLE_COPY(Driver)
+ Q_DISABLE_COPY_MOVE(Driver)
public:
Driver();
virtual ~Driver();
// tools
bool printDependencies(const QString &fileName);
- bool uic(const QString &fileName, QTextStream *output = 0);
- bool uic(const QString &fileName, DomUI *ui, QTextStream *output = 0);
+ bool uic(const QString &fileName, QTextStream *output = nullptr);
+ bool uic(const QString &fileName, DomUI *ui, QTextStream *output = nullptr);
// configuration
inline QTextStream &output() const { return *m_output; }
inline Option &option() { return m_option; }
- // initialization
- void reset();
-
- // error
- inline QStringList problems() { return m_problems; }
- inline void addProblem(const QString &problem) { m_problems.append(problem); }
-
// utils
static QString headerFileName(const QString &fileName);
QString headerFileName() const;
@@ -80,50 +73,52 @@ public:
const QString &className=QString());
// symbol table
- QString findOrInsertWidget(DomWidget *ui_widget);
- QString findOrInsertSpacer(DomSpacer *ui_spacer);
- QString findOrInsertLayout(DomLayout *ui_layout);
- QString findOrInsertLayoutItem(DomLayoutItem *ui_layoutItem);
+ QString findOrInsertWidget(const DomWidget *ui_widget);
+ QString findOrInsertSpacer(const DomSpacer *ui_spacer);
+ QString findOrInsertLayout(const DomLayout *ui_layout);
+ QString findOrInsertLayoutItem(const DomLayoutItem *ui_layoutItem);
QString findOrInsertName(const QString &name);
- QString findOrInsertActionGroup(DomActionGroup *ui_group);
- QString findOrInsertAction(DomAction *ui_action);
+ QString findOrInsertActionGroup(const DomActionGroup *ui_group);
+ QString findOrInsertAction(const DomAction *ui_action);
QString findOrInsertButtonGroup(const DomButtonGroup *ui_group);
// Find a group by its non-uniqified name
const DomButtonGroup *findButtonGroup(const QString &attributeName) const;
- inline bool hasName(const QString &name) const
- { return m_nameRepository.contains(name); }
-
- DomWidget *widgetByName(const QString &name) const;
- DomSpacer *spacerByName(const QString &name) const;
- DomLayout *layoutByName(const QString &name) const;
- DomActionGroup *actionGroupByName(const QString &name) const;
- DomAction *actionByName(const QString &name) const;
-
- // pixmap
- void insertPixmap(const QString &pixmap);
- bool containsPixmap(const QString &pixmap) const;
+ const DomWidget *widgetByName(const QString &attributeName) const;
+ QString widgetVariableName(const QString &attributeName) const;
+ const DomActionGroup *actionGroupByName(const QString &attributeName) const;
+ const DomAction *actionByName(const QString &attributeName) const;
bool useIdBasedTranslations() const { return m_idBasedTranslations; }
void setUseIdBasedTranslations(bool u) { m_idBasedTranslations = u; }
private:
+ template <class DomClass> using DomObjectHash = QHash<const DomClass *, QString>;
+ template <class DomClass> using DomObjectHashConstIt =
+ typename DomObjectHash<DomClass>::ConstIterator;
+
+ template <class DomClass>
+ DomObjectHashConstIt<DomClass> findByAttributeNameIt(const DomObjectHash<DomClass> &domHash,
+ const QString &name) const;
+ template <class DomClass>
+ const DomClass *findByAttributeName(const DomObjectHash<DomClass> &domHash,
+ const QString &name) const;
+ template <class DomClass>
+ QString findOrInsert(DomObjectHash<DomClass> *domHash, const DomClass *dom, const QString &className,
+ bool isMember = true);
+
Option m_option;
QTextStream m_stdout;
QTextStream *m_output;
- QStringList m_problems;
-
// symbol tables
- QHash<DomWidget*, QString> m_widgets;
- QHash<DomSpacer*, QString> m_spacers;
- QHash<DomLayout*, QString> m_layouts;
- QHash<DomActionGroup*, QString> m_actionGroups;
- typedef QHash<const DomButtonGroup*, QString> ButtonGroupNameHash;
- ButtonGroupNameHash m_buttonGroups;
- QHash<DomAction*, QString> m_actions;
+ DomObjectHash<DomWidget> m_widgets;
+ DomObjectHash<DomSpacer> m_spacers;
+ DomObjectHash<DomLayout> m_layouts;
+ DomObjectHash<DomActionGroup> m_actionGroups;
+ DomObjectHash<DomButtonGroup> m_buttonGroups;
+ DomObjectHash<DomAction> m_actions;
QHash<QString, bool> m_nameRepository;
- QHash<QString, bool> m_pixmaps;
bool m_idBasedTranslations = false;
};
diff --git a/src/tools/uic/main.cpp b/src/tools/uic/main.cpp
index 41bd62bbf4..439789d221 100644
--- a/src/tools/uic/main.cpp
+++ b/src/tools/uic/main.cpp
@@ -29,6 +29,7 @@
#include "uic.h"
#include "option.h"
#include "driver.h"
+#include <language.h>
#include <qfile.h>
#include <qdir.h>
@@ -96,7 +97,7 @@ int runUic(int argc, char *argv[])
QCommandLineOption generatorOption(QStringList() << QStringLiteral("g") << QStringLiteral("generator"));
generatorOption.setDescription(QStringLiteral("Select generator."));
- generatorOption.setValueName(QStringLiteral("java|cpp"));
+ generatorOption.setValueName(QStringLiteral("python|cpp"));
parser.addOption(generatorOption);
QCommandLineOption idBasedOption(QStringLiteral("idbased"));
@@ -116,6 +117,13 @@ int runUic(int argc, char *argv[])
driver.option().translateFunction = parser.value(translateOption);
driver.option().includeFile = parser.value(includeOption);
+ Language language = Language::Cpp;
+ if (parser.isSet(generatorOption)) {
+ if (parser.value(generatorOption).compare(QLatin1String("python")) == 0)
+ language = Language::Python;
+ }
+ language::setLanguage(language);
+
if (parser.isSet(noStringLiteralOption))
fprintf(stderr, "The -s, --no-stringliteral option is deprecated and it won't take any effect.\n");
@@ -129,9 +137,9 @@ int runUic(int argc, char *argv[])
return !driver.printDependencies(inputFile);
}
- QTextStream *out = 0;
+ QTextStream *out = nullptr;
QFile f;
- if (driver.option().outputFile.size()) {
+ if (!driver.option().outputFile.isEmpty()) {
f.setFileName(driver.option().outputFile);
if (!f.open(QIODevice::WriteOnly | QFile::Text)) {
fprintf(stderr, "Could not create output file\n");
diff --git a/src/tools/uic/python/python.pri b/src/tools/uic/python/python.pri
new file mode 100644
index 0000000000..4dd31160a1
--- /dev/null
+++ b/src/tools/uic/python/python.pri
@@ -0,0 +1,8 @@
+INCLUDEPATH += $$PWD
+
+# Input
+HEADERS += $$PWD/pythonwritedeclaration.h \
+ $$PWD/pythonwriteimports.h
+
+SOURCES += $$PWD/pythonwritedeclaration.cpp \
+ $$PWD/pythonwriteimports.cpp
diff --git a/src/tools/uic/python/pythonwritedeclaration.cpp b/src/tools/uic/python/pythonwritedeclaration.cpp
new file mode 100644
index 0000000000..5122b18e23
--- /dev/null
+++ b/src/tools/uic/python/pythonwritedeclaration.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pythonwritedeclaration.h"
+#include <cppwriteinitialization.h>
+#include <language.h>
+#include <driver.h>
+#include <ui4.h>
+#include <uic.h>
+
+#include <QtCore/qtextstream.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Python {
+
+WriteDeclaration::WriteDeclaration(Uic *uic) :
+ m_uic(uic),
+ m_driver(uic->driver()),
+ m_output(uic->output()),
+ m_option(uic->option())
+{
+}
+
+void WriteDeclaration::acceptUI(DomUI *node)
+{
+ // remove any left-over C++ namespaces
+ const QString qualifiedClassName = QLatin1String("Ui_") + node->elementClass()
+ + m_option.postfix;
+ m_output << "class " << language::fixClassName(qualifiedClassName) << "(object):\n";
+
+ TreeWalker::acceptWidget(node->elementWidget());
+ if (const DomButtonGroups *domButtonGroups = node->elementButtonGroups())
+ acceptButtonGroups(domButtonGroups);
+ CPP::WriteInitialization(m_uic).acceptUI(node);
+}
+
+// Register button groups to prevent the on-the-fly creation legacy
+// feature from triggering
+void WriteDeclaration::acceptButtonGroup(const DomButtonGroup *buttonGroup)
+{
+ m_driver->findOrInsertButtonGroup(buttonGroup);
+}
+
+} // namespace Python
+
+QT_END_NAMESPACE
diff --git a/src/tools/uic/python/pythonwritedeclaration.h b/src/tools/uic/python/pythonwritedeclaration.h
new file mode 100644
index 0000000000..a8d50b6fbf
--- /dev/null
+++ b/src/tools/uic/python/pythonwritedeclaration.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYTHONWRITEDECLARATION_H
+#define PYTHONWRITEDECLARATION_H
+
+#include <treewalker.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTextStream;
+class Driver;
+class Uic;
+
+struct Option;
+
+namespace Python {
+
+struct WriteDeclaration : public TreeWalker
+{
+ WriteDeclaration(Uic *uic);
+
+ void acceptUI(DomUI *node) override;
+ void acceptButtonGroup(const DomButtonGroup *buttonGroup) override;
+
+private:
+ Uic *m_uic;
+ Driver *m_driver;
+ QTextStream &m_output;
+ const Option &m_option;
+};
+
+} // namespace Python
+
+QT_END_NAMESPACE
+
+#endif // PYTHONWRITEDECLARATION_H
diff --git a/src/tools/uic/python/pythonwriteimports.cpp b/src/tools/uic/python/pythonwriteimports.cpp
new file mode 100644
index 0000000000..303615f77b
--- /dev/null
+++ b/src/tools/uic/python/pythonwriteimports.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pythonwriteimports.h"
+
+#include <customwidgetsinfo.h>
+#include <uic.h>
+
+#include <ui4.h>
+
+#include <QtCore/qtextstream.h>
+
+QT_BEGIN_NAMESPACE
+
+static const char *standardImports =
+R"I(from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
+ QRect, QSize, QUrl, Qt)
+from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QFont,
+ QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap,
+ QRadialGradient)
+from PySide2.QtWidgets import *
+)I";
+
+namespace Python {
+
+WriteImports::WriteImports(Uic *uic) : m_uic(uic)
+{
+}
+
+void WriteImports::acceptUI(DomUI *node)
+{
+ auto &output = m_uic->output();
+ output << standardImports << '\n';
+ if (auto customWidgets = node->elementCustomWidgets()) {
+ TreeWalker::acceptCustomWidgets(customWidgets);
+ output << '\n';
+ }
+}
+
+QString WriteImports::qtModuleOf(const DomCustomWidget *node) const
+{
+ if (m_uic->customWidgetsInfo()->extends(node->elementClass(), QLatin1String("QAxWidget")))
+ return QStringLiteral("QtAxContainer");
+ if (const auto headerElement = node->elementHeader()) {
+ const auto &header = headerElement->text();
+ if (header.startsWith(QLatin1String("Qt"))) {
+ const int slash = header.indexOf(QLatin1Char('/'));
+ if (slash != -1)
+ return header.left(slash);
+ }
+ }
+ return QString();
+}
+
+void WriteImports::acceptCustomWidget(DomCustomWidget *node)
+{
+ const auto &className = node->elementClass();
+ if (className.contains(QLatin1String("::")))
+ return; // Exclude namespaced names (just to make tests pass).
+ const QString &qtModule = qtModuleOf(node);
+ auto &output = m_uic->output();
+ if (!qtModule.isEmpty())
+ output << "from PySide2." << qtModule << ' ';
+ output << "import " << className << '\n';
+}
+
+} // namespace Python
+
+QT_END_NAMESPACE
diff --git a/src/tools/uic/python/pythonwriteimports.h b/src/tools/uic/python/pythonwriteimports.h
new file mode 100644
index 0000000000..427cbb48b1
--- /dev/null
+++ b/src/tools/uic/python/pythonwriteimports.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYTHONWRITEIMPORTS_H
+#define PYTHONWRITEIMPORTS_H
+
+#include <treewalker.h>
+
+QT_BEGIN_NAMESPACE
+
+class Uic;
+
+namespace Python {
+
+struct WriteImports : public TreeWalker
+{
+public:
+ explicit WriteImports(Uic *uic);
+
+ void acceptUI(DomUI *node) override;
+ void acceptCustomWidget(DomCustomWidget *node) override;
+
+private:
+ QString qtModuleOf(const DomCustomWidget *node) const;
+
+ Uic *const m_uic;
+};
+
+} // namespace Python
+
+QT_END_NAMESPACE
+
+#endif // PYTHONWRITEIMPORTS_H
diff --git a/src/tools/uic/qclass_lib_map.h b/src/tools/uic/qclass_lib_map.h
index 8e1afa0878..8cebe65a00 100644
--- a/src/tools/uic/qclass_lib_map.h
+++ b/src/tools/uic/qclass_lib_map.h
@@ -249,7 +249,7 @@ QT_CLASS_LIB(QLatin1String, QtCore, qstring.h)
QT_CLASS_LIB(QCharRef, QtCore, qstring.h)
QT_CLASS_LIB(QConstString, QtCore, qstring.h)
QT_CLASS_LIB(QStringRef, QtCore, qstring.h)
-QT_CLASS_LIB(QLatin1Literal, QtCore, qstringbuilder.h)
+QT_CLASS_LIB(QLatin1Literal, QtCore, qstring.h)
QT_CLASS_LIB(QAbstractConcatenable, QtCore, qstringbuilder.h)
QT_CLASS_LIB(QConcatenable, QtCore, qstringbuilder.h)
QT_CLASS_LIB(QStringBuilder, QtCore, qstringbuilder.h)
diff --git a/src/tools/uic/shared/language.cpp b/src/tools/uic/shared/language.cpp
new file mode 100644
index 0000000000..235a8ed2fc
--- /dev/null
+++ b/src/tools/uic/shared/language.cpp
@@ -0,0 +1,426 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "language.h"
+
+#include <QtCore/qtextstream.h>
+
+namespace language {
+
+static Encoding encoding = Encoding::Utf8;
+static Language _language = Language::Cpp;
+
+Language language() { return _language; }
+
+void setLanguage(Language l)
+{
+ _language = l;
+ switch (_language) {
+ case Language::Cpp:
+ derefPointer = QLatin1String("->");
+ nullPtr = QLatin1String("nullptr");
+ operatorNew = QLatin1String("new ");
+ qtQualifier = QLatin1String("Qt::");
+ qualifier = QLatin1String("::");
+ self = QLatin1String(""); // for testing: change to "this->";
+ eol = QLatin1String(";\n");
+ encoding = Encoding::Utf8;
+ break;
+ case Language::Python:
+ derefPointer = QLatin1String(".");
+ nullPtr = QLatin1String("None");
+ operatorNew = QLatin1String("");
+ qtQualifier = QLatin1String("Qt.");
+ qualifier = QLatin1String(".");
+ self = QLatin1String("self.");
+ eol = QLatin1String("\n");
+ encoding = Encoding::Unicode;
+ break;
+ }
+}
+
+QString derefPointer;
+QString nullPtr;
+QString operatorNew;
+QString qtQualifier;
+QString qualifier;
+QString self;
+QString eol;
+
+QString cppQualifier = QLatin1String("::");
+QString cppTrue = QLatin1String("true");
+QString cppFalse = QLatin1String("false");
+
+QTextStream &operator<<(QTextStream &str, const qtConfig &c)
+{
+ str << "QT_CONFIG(" << c.parameter() << ')';
+ return str;
+}
+
+QTextStream &operator<<(QTextStream &str, const openQtConfig &c)
+{
+ str << "#if " << qtConfig(c.parameter()) << '\n';
+ return str;
+}
+
+QTextStream &operator<<(QTextStream &str, const closeQtConfig &c)
+{
+ str << "#endif // " << qtConfig(c.parameter()) << '\n';
+ return str;
+}
+
+struct EnumLookup
+{
+ int value;
+ const char *valueString;
+};
+
+template <int N>
+const char *lookupEnum(const EnumLookup(&array)[N], int value, int defaultIndex = 0)
+{
+ for (int i = 0; i < N; ++i) {
+ if (value == array[i].value)
+ return array[i].valueString;
+ }
+ const char *defaultValue = array[defaultIndex].valueString;
+ qWarning("uic: Warning: Invalid enumeration value %d, defaulting to %s",
+ value, defaultValue);
+ return defaultValue;
+}
+
+QString fixClassName(QString className)
+{
+ if (language() == Language::Python)
+ className.replace(cppQualifier, QLatin1String("_"));
+ return className;
+}
+
+const char *toolbarArea(int v)
+{
+ static const EnumLookup toolBarAreas[] =
+ {
+ {0, "NoToolBarArea"},
+ {0x1, "LeftToolBarArea"},
+ {0x2, "RightToolBarArea"},
+ {0x4, "TopToolBarArea"},
+ {0x8, "BottomToolBarArea"},
+ {0xf, "AllToolBarAreas"}
+ };
+ return lookupEnum(toolBarAreas, v);
+}
+
+const char *sizePolicy(int v)
+{
+ static const EnumLookup sizePolicies[] =
+ {
+ {0, "Fixed"},
+ {0x1, "Minimum"},
+ {0x4, "Maximum"},
+ {0x5, "Preferred"},
+ {0x3, "MinimumExpanding"},
+ {0x7, "Expanding"},
+ {0xD, "Ignored"}
+ };
+ return lookupEnum(sizePolicies, v, 3);
+}
+
+const char *dockWidgetArea(int v)
+{
+ static const EnumLookup dockWidgetAreas[] =
+ {
+ {0, "NoDockWidgetArea"},
+ {0x1, "LeftDockWidgetArea"},
+ {0x2, "RightDockWidgetArea"},
+ {0x4, "TopDockWidgetArea"},
+ {0x8, "BottomDockWidgetArea"},
+ {0xf, "AllDockWidgetAreas"}
+ };
+ return lookupEnum(dockWidgetAreas, v);
+}
+
+const char *paletteColorRole(int v)
+{
+ static const EnumLookup colorRoles[] =
+ {
+ {0, "WindowText"},
+ {1, "Button"},
+ {2, "Light"},
+ {3, "Midlight"},
+ {4, "Dark"},
+ {5, "Mid"},
+ {6, "Text"},
+ {7, "BrightText"},
+ {8, "ButtonText"},
+ {9, "Base"},
+ {10, "Window"},
+ {11, "Shadow"},
+ {12, "Highlight"},
+ {13, "HighlightedText"},
+ {14, "Link"},
+ {15, "LinkVisited"},
+ {16, "AlternateBase"},
+ {17, "NoRole"},
+ {18, "ToolTipBase"},
+ {19, "ToolTipText"},
+ {20, "PlaceholderText"},
+ };
+ return lookupEnum(colorRoles, v);
+}
+
+// Helpers for formatting a character sequences
+
+// Format a special character like '\x0a'
+static int formatEscapedNumber(QTextStream &str, ushort value, int base, int width,
+ char prefix = 0)
+{
+ int length = 1 + width;
+ str << '\\';
+ if (prefix) {
+ str << prefix;
+ ++length;
+ }
+ const auto oldPadChar = str.padChar();
+ const auto oldFieldWidth = str.fieldWidth();
+ const auto oldFieldAlignment = str.fieldAlignment();
+ const auto oldIntegerBase = str.integerBase();
+ str.setPadChar(QLatin1Char('0'));
+ str.setFieldWidth(width);
+ str.setFieldAlignment(QTextStream::AlignRight);
+ str.setIntegerBase(base);
+ str << value;
+ str.setIntegerBase(oldIntegerBase);
+ str.setFieldAlignment(oldFieldAlignment);
+ str.setFieldWidth(oldFieldWidth);
+ str.setPadChar(oldPadChar);
+ return length;
+}
+
+static int formatSpecialCharacter(QTextStream &str, ushort value)
+{
+ int length = 0;
+ switch (value) {
+ case '\\':
+ str << "\\\\";
+ length += 2;
+ break;
+ case '\"':
+ str << "\\\"";
+ length += 2;
+ break;
+ case '\n':
+ str << "\\n\"\n\"";
+ length += 5;
+ break;
+ default:
+ break;
+ }
+ return length;
+}
+
+// Format a sequence of characters for C++ with special characters numerically
+// escaped (non-raw string literals), wrappped at maxSegmentSize. FormattingTraits
+// are used to transform characters into (unsigned) codes, which can be used
+// for either normal escapes or Unicode code points as used in Unicode literals.
+
+enum : int { maxSegmentSize = 1024 };
+
+template <Encoding e>
+struct FormattingTraits
+{
+};
+
+template <>
+struct FormattingTraits<Encoding::Utf8>
+{
+ static ushort code(char c) { return uchar(c); }
+};
+
+template <>
+struct FormattingTraits<Encoding::Unicode>
+{
+ static ushort code(QChar c) { return c.unicode(); }
+};
+
+template <Encoding e, class Iterator>
+static void formatStringSequence(QTextStream &str, Iterator it, Iterator end,
+ const QString &indent,
+ int escapeIntegerBase, int escapeWidth,
+ char escapePrefix = 0)
+{
+ str << '"';
+ int length = 0;
+ while (it != end) {
+ const auto code = FormattingTraits<e>::code(*it);
+ if (code >= 0x80) {
+ length += formatEscapedNumber(str, code, escapeIntegerBase, escapeWidth, escapePrefix);
+ } else if (const int l = formatSpecialCharacter(str, code)) {
+ length += l;
+ } else if (code != '\r') {
+ str << *it;
+ ++length;
+ }
+ ++it;
+ if (it != end && length > maxSegmentSize) {
+ str << "\"\n" << indent << indent << '"';
+ length = 0;
+ }
+ }
+ str << '"';
+}
+
+void _formatString(QTextStream &str, const QString &value, const QString &indent,
+ bool qString)
+{
+ switch (encoding) {
+ // Special characters as 3 digit octal escapes (u8"\303\234mlaut")
+ case Encoding::Utf8: {
+ if (qString && _language == Language::Cpp)
+ str << "QString::fromUtf8(";
+ const QByteArray utf8 = value.toUtf8();
+ formatStringSequence<Encoding::Utf8>(str, utf8.cbegin(), utf8.cend(), indent,
+ 8, 3);
+ if (qString && _language == Language::Cpp)
+ str << ')';
+ }
+ break;
+ // Special characters as 4 digit hex Unicode points (u8"\u00dcmlaut")
+ case Encoding::Unicode:
+ str << 'u'; // Python Unicode literal (would be UTF-16 in C++)
+ formatStringSequence<Encoding::Unicode>(str, value.cbegin(), value.cend(), indent,
+ 16, 4, 'u');
+ break;
+ }
+}
+
+QTextStream &operator<<(QTextStream &str, const repeat &r)
+{
+ for (int i = 0; i < r.m_count; ++i)
+ str << r.m_char;
+ return str;
+}
+
+startFunctionDefinition1::startFunctionDefinition1(const char *name, const QString &parameterType,
+ const QString &parameterName,
+ const QString &indent,
+ const char *returnType) :
+ m_name(name), m_parameterType(parameterType), m_parameterName(parameterName),
+ m_indent(indent), m_return(returnType)
+{
+}
+
+QTextStream &operator<<(QTextStream &str, const startFunctionDefinition1 &f)
+{
+ switch (language()) {
+ case Language::Cpp:
+ str << (f.m_return ? f.m_return : "void") << ' ' << f.m_name << '('
+ << f.m_parameterType;
+ if (f.m_parameterType.cend()->isLetter())
+ str << ' ';
+ str << f.m_parameterName << ')' << '\n' << f.m_indent << "{\n";
+ break;
+ case Language::Python:
+ str << "def " << f.m_name << "(self, " << f.m_parameterName << "):\n";
+ break;
+ }
+ return str;
+}
+
+endFunctionDefinition::endFunctionDefinition(const char *name) : m_name(name)
+{
+}
+
+QTextStream &operator<<(QTextStream &str, const endFunctionDefinition &f)
+{
+ switch (language()) {
+ case Language::Cpp:
+ str << "} // " << f.m_name << "\n\n";
+ break;
+ case Language::Python:
+ str << "# " << f.m_name << "\n\n";
+ break;
+ }
+ return str;
+}
+
+void _formatStackVariable(QTextStream &str, const char *className, QStringView varName,
+ bool withInitParameters)
+{
+ switch (language()) {
+ case Language::Cpp:
+ str << className << ' ' << varName;
+ if (withInitParameters)
+ str << '(';
+ break;
+ case Language::Python:
+ str << varName << " = " << className << '(';
+ if (!withInitParameters)
+ str << ')';
+ break;
+ }
+}
+
+void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver)
+{
+ switch (language()) {
+ case Language::Cpp:
+ str << "QObject::connect(" << sender.name << ", SIGNAL("<< sender.signature
+ << "), " << receiver.name << ", SLOT("<< receiver.signature << "))";
+ break;
+ case Language::Python:
+ str << sender.name << '.'
+ << sender.signature.leftRef(sender.signature.indexOf(QLatin1Char('(')))
+ << ".connect(" << receiver.name << '.'
+ << receiver.signature.leftRef(receiver.signature.indexOf(QLatin1Char('(')))
+ << ')';
+ break;
+ }
+}
+
+QString boolValue(bool v)
+{
+ switch (language()) {
+ case Language::Cpp:
+ return v ? cppTrue : cppFalse;
+ case Language::Python:
+ return v ? QStringLiteral("True") : QStringLiteral("False");
+ }
+ Q_UNREACHABLE();
+}
+
+static inline QString dot() { return QStringLiteral("."); }
+
+QString enumValue(const QString &value)
+{
+ if (language() == Language::Cpp || !value.contains(cppQualifier))
+ return value;
+ QString fixed = value;
+ fixed.replace(cppQualifier, dot());
+ return fixed;
+}
+
+} // namespace language
diff --git a/src/tools/uic/shared/language.h b/src/tools/uic/shared/language.h
new file mode 100644
index 0000000000..fc8af9715b
--- /dev/null
+++ b/src/tools/uic/shared/language.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LANGUAGE_H
+#define LANGUAGE_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qstringview.h>
+#include <QtCore/qstring.h>
+
+QT_FORWARD_DECLARE_CLASS(QTextStream)
+
+enum class Language { Cpp, Python };
+
+namespace language {
+
+Language language();
+void setLanguage(Language);
+
+extern QString derefPointer;
+extern QString nullPtr;
+extern QString operatorNew;
+extern QString qtQualifier;
+extern QString qualifier;
+extern QString self;
+extern QString eol;
+
+extern QString cppQualifier;
+extern QString cppTrue;
+extern QString cppFalse;
+
+// Base class for streamable objects with one QStringView parameter
+class StringViewStreamable
+{
+public:
+ StringViewStreamable(QStringView parameter) : m_parameter(parameter) {}
+
+ QStringView parameter() const { return m_parameter; }
+
+private:
+ QStringView m_parameter;
+};
+
+class qtConfig : public StringViewStreamable
+{
+public:
+ qtConfig(QStringView name) : StringViewStreamable(name) {}
+};
+
+QTextStream &operator<<(QTextStream &str, const qtConfig &c);
+
+class openQtConfig : public StringViewStreamable
+{
+public:
+ openQtConfig(QStringView name) : StringViewStreamable(name) {}
+};
+
+QTextStream &operator<<(QTextStream &str, const openQtConfig &c);
+
+class closeQtConfig : public StringViewStreamable
+{
+public:
+ closeQtConfig(QStringView name) : StringViewStreamable(name) {}
+};
+
+QTextStream &operator<<(QTextStream &, const closeQtConfig &c);
+
+QString fixClassName(QString className);
+
+const char *toolbarArea(int v);
+const char *sizePolicy(int v);
+const char *dockWidgetArea(int v);
+const char *paletteColorRole(int v);
+
+enum class Encoding { Utf8, Unicode };
+
+void _formatString(QTextStream &str, const QString &value, const QString &indent,
+ bool qString);
+
+template <bool AsQString>
+class _string
+{
+public:
+ explicit _string(const QString &value, const QString &indent = QString())
+ : m_value(value), m_indent(indent) {}
+
+ void format(QTextStream &str) const
+ { _formatString(str, m_value, m_indent, AsQString); }
+
+private:
+ const QString &m_value;
+ const QString &m_indent;
+};
+
+template <bool AsQString>
+inline QTextStream &operator<<(QTextStream &str, const language::_string<AsQString> &s)
+{
+ s.format(str);
+ return str;
+}
+
+using charliteral = _string<false>;
+using qstring = _string<true>;
+
+class repeat {
+public:
+ explicit repeat(int count, char c) : m_count(count), m_char(c) {}
+
+ friend QTextStream &operator<<(QTextStream &str, const repeat &r);
+
+private:
+ const int m_count;
+ const char m_char;
+};
+
+class startFunctionDefinition1 {
+public:
+ explicit startFunctionDefinition1(const char *name, const QString &parameterType,
+ const QString &parameterName,
+ const QString &indent,
+ const char *returnType = nullptr);
+
+ friend QTextStream &operator<<(QTextStream &str, const startFunctionDefinition1 &f);
+private:
+ const char *m_name;
+ const QString &m_parameterType;
+ const QString &m_parameterName;
+ const QString &m_indent;
+ const char *m_return;
+};
+
+class endFunctionDefinition {
+public:
+ explicit endFunctionDefinition(const char *name);
+
+ friend QTextStream &operator<<(QTextStream &str, const endFunctionDefinition &f);
+private:
+ const char *m_name;
+};
+
+void _formatStackVariable(QTextStream &str, const char *className, QStringView varName, bool withInitParameters);
+
+template <bool withInitParameters>
+class _stackVariable {
+public:
+ explicit _stackVariable(const char *className, QStringView varName) :
+ m_className(className), m_varName(varName) {}
+
+ void format(QTextStream &str) const
+ { _formatStackVariable(str, m_className, m_varName, withInitParameters); }
+
+private:
+ const char *m_className;
+ QStringView m_varName;
+ QStringView m_parameters;
+};
+
+template <bool withInitParameters>
+inline QTextStream &operator<<(QTextStream &str, const _stackVariable<withInitParameters> &s)
+{
+ s.format(str);
+ return str;
+}
+
+using stackVariable = _stackVariable<false>;
+using stackVariableWithInitParameters = _stackVariable<true>;
+
+struct SignalSlot
+{
+ QString name;
+ QString signature;
+ QString className;
+};
+
+void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver);
+
+QString boolValue(bool v);
+
+QString enumValue(const QString &value);
+
+} // namespace language
+
+#endif // LANGUAGE_H
diff --git a/src/tools/uic/shared/shared.pri b/src/tools/uic/shared/shared.pri
new file mode 100644
index 0000000000..dce2af8bf1
--- /dev/null
+++ b/src/tools/uic/shared/shared.pri
@@ -0,0 +1,5 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/language.h
+
+SOURCES += $$PWD/language.cpp
diff --git a/src/tools/uic/treewalker.h b/src/tools/uic/treewalker.h
index 43d4633d83..3777229517 100644
--- a/src/tools/uic/treewalker.h
+++ b/src/tools/uic/treewalker.h
@@ -77,6 +77,9 @@ class DomButtonGroup;
struct TreeWalker
{
+ Q_DISABLE_COPY_MOVE(TreeWalker)
+
+ TreeWalker() = default;
inline virtual ~TreeWalker() = default;
virtual void acceptUI(DomUI *ui);
@@ -101,8 +104,7 @@ struct TreeWalker
virtual void acceptTime(DomTime *time);
virtual void acceptDateTime(DomDateTime *dateTime);
virtual void acceptProperty(DomProperty *property);
- typedef QVector<DomScript *> DomScripts;
- typedef QVector<DomWidget *> DomWidgets;
+ using DomWidgets = QVector<DomWidget *>;
virtual void acceptIncludes(DomIncludes *includes);
virtual void acceptInclude(DomInclude *incl);
virtual void acceptAction(DomAction *action);
diff --git a/src/tools/uic/uic.cpp b/src/tools/uic/uic.cpp
index a5b331192f..207356f28d 100644
--- a/src/tools/uic/uic.cpp
+++ b/src/tools/uic/uic.cpp
@@ -35,6 +35,10 @@
#include "cppwriteincludes.h"
#include "cppwritedeclaration.h"
+#include <pythonwritedeclaration.h>
+#include <pythonwriteimports.h>
+
+#include <language.h>
#include <qxmlstream.h>
#include <qfileinfo.h>
@@ -65,7 +69,7 @@ bool Uic::printDependencies()
return false;
}
- DomUI *ui = 0;
+ DomUI *ui = nullptr;
{
QXmlStreamReader reader;
reader.setDevice(&f);
@@ -103,21 +107,63 @@ bool Uic::printDependencies()
return true;
}
-void Uic::writeCopyrightHeader(DomUI *ui)
+void Uic::writeCopyrightHeaderCpp(const DomUI *ui) const
{
QString comment = ui->elementComment();
- if (comment.size())
+ if (!comment.isEmpty())
out << "/*\n" << comment << "\n*/\n\n";
out << "/********************************************************************************\n";
out << "** Form generated from reading UI file '" << QFileInfo(opt.inputFile).fileName() << "'\n";
out << "**\n";
- out << "** Created by: Qt User Interface Compiler version " << QLatin1String(QT_VERSION_STR) << "\n";
+ out << "** Created by: Qt User Interface Compiler version " << QT_VERSION_STR << "\n";
out << "**\n";
out << "** WARNING! All changes made in this file will be lost when recompiling UI file!\n";
out << "********************************************************************************/\n\n";
}
+// Format existing UI file comments for Python with some smartness : Replace all
+// leading C++ comment characters by '#' or prepend '#' if needed.
+
+static inline bool isCppCommentChar(QChar c)
+{
+ return c == QLatin1Char('/') || c == QLatin1Char('*');
+}
+
+static int leadingCppCommentCharCount(const QStringRef &s)
+{
+ int i = 0;
+ for (const int size = s.size(); i < size && isCppCommentChar(s.at(i)); ++i) {
+ }
+ return i;
+}
+
+void Uic::writeCopyrightHeaderPython(const DomUI *ui) const
+{
+ QString comment = ui->elementComment();
+ if (!comment.isEmpty()) {
+ const auto lines = comment.splitRef(QLatin1Char('\n'));
+ for (const auto &line : lines) {
+ if (const int leadingCommentChars = leadingCppCommentCharCount(line)) {
+ out << language::repeat(leadingCommentChars, '#')
+ << line.right(line.size() - leadingCommentChars);
+ } else {
+ if (!line.startsWith(QLatin1Char('#')))
+ out << "# ";
+ out << line;
+ }
+ out << '\n';
+ }
+ out << '\n';
+ }
+
+ out << language::repeat(80, '#') << "\n## Form generated from reading UI file '"
+ << QFileInfo(opt.inputFile).fileName()
+ << "'\n##\n## Created by: Qt User Interface Compiler version " << QT_VERSION_STR
+ << "\n##\n## WARNING! All changes made in this file will be lost when recompiling UI file!\n"
+ << language::repeat(80, '#') << "\n\n";
+}
+
// Check the version with a stream reader at the <ui> element.
static double versionFromUiAttribute(QXmlStreamReader &reader)
@@ -132,7 +178,7 @@ static double versionFromUiAttribute(QXmlStreamReader &reader)
DomUI *Uic::parseUiFile(QXmlStreamReader &reader)
{
- DomUI *ui = 0;
+ DomUI *ui = nullptr;
const QString uiElement = QLatin1String("ui");
while (!reader.atEnd()) {
@@ -143,7 +189,7 @@ DomUI *Uic::parseUiFile(QXmlStreamReader &reader)
if (version < 4.0) {
const QString msg = QString::fromLatin1("uic: File generated with too old version of Qt Designer (%1)").arg(version);
fprintf(stderr, "%s\n", qPrintable(msg));
- return 0;
+ return nullptr;
}
ui = new DomUI();
@@ -155,7 +201,7 @@ DomUI *Uic::parseUiFile(QXmlStreamReader &reader)
}
if (reader.hasError()) {
delete ui;
- ui = 0;
+ ui = nullptr;
fprintf(stderr, "%s\n", qPrintable(QString::fromLatin1("uic: Error in line %1, column %2 : %3")
.arg(reader.lineNumber()).arg(reader.columnNumber())
.arg(reader.errorString())));
@@ -195,15 +241,26 @@ bool Uic::write(QIODevice *in)
bool Uic::write(DomUI *ui)
{
- using namespace CPP;
-
if (!ui || !ui->elementWidget())
return false;
- if (opt.copyrightHeader)
- writeCopyrightHeader(ui);
+ const auto lang = language::language();
- if (opt.headerProtection) {
+ if (lang == Language::Python)
+ out << "# -*- coding: utf-8 -*-\n\n";
+
+ if (opt.copyrightHeader) {
+ switch (language::language()) {
+ case Language::Cpp:
+ writeCopyrightHeaderCpp(ui);
+ break;
+ case Language::Python:
+ writeCopyrightHeaderPython(ui);
+ break;
+ }
+ }
+
+ if (opt.headerProtection && lang == Language::Cpp) {
writeHeaderProtectionStart();
out << "\n";
}
@@ -218,13 +275,25 @@ bool Uic::write(DomUI *ui)
info.acceptUI(ui);
cWidgetsInfo.acceptUI(ui);
- WriteIncludes writeIncludes(this);
- writeIncludes.acceptUI(ui);
- Validator(this).acceptUI(ui);
- WriteDeclaration(this).acceptUI(ui);
+ switch (language::language()) {
+ case Language::Cpp: {
+ CPP::WriteIncludes writeIncludes(this);
+ writeIncludes.acceptUI(ui);
+ Validator(this).acceptUI(ui);
+ CPP::WriteDeclaration(this).acceptUI(ui);
+ }
+ break;
+ case Language::Python: {
+ Python::WriteImports writeImports(this);
+ writeImports.acceptUI(ui);
+ Validator(this).acceptUI(ui);
+ Python::WriteDeclaration(this).acceptUI(ui);
+ }
+ break;
+ }
- if (opt.headerProtection)
+ if (opt.headerProtection && lang == Language::Cpp)
writeHeaderProtectionEnd();
return true;
@@ -243,55 +312,34 @@ void Uic::writeHeaderProtectionEnd()
out << "#endif // " << h << "\n";
}
-bool Uic::isMainWindow(const QString &className) const
-{
- return customWidgetsInfo()->extends(className, QLatin1String("QMainWindow"));
-}
-
-bool Uic::isToolBar(const QString &className) const
-{
- return customWidgetsInfo()->extends(className, QLatin1String("QToolBar"));
-}
-
bool Uic::isButton(const QString &className) const
{
- return customWidgetsInfo()->extends(className, QLatin1String("QRadioButton"))
- || customWidgetsInfo()->extends(className, QLatin1String("QToolButton"))
- || customWidgetsInfo()->extends(className, QLatin1String("QCheckBox"))
- || customWidgetsInfo()->extends(className, QLatin1String("QPushButton"))
- || customWidgetsInfo()->extends(className, QLatin1String("QCommandLinkButton"));
+ static const QStringList buttons = {
+ QLatin1String("QRadioButton"), QLatin1String("QToolButton"),
+ QLatin1String("QCheckBox"), QLatin1String("QPushButton"),
+ QLatin1String("QCommandLinkButton")
+ };
+ return customWidgetsInfo()->extendsOneOf(className, buttons);
}
bool Uic::isContainer(const QString &className) const
{
- return customWidgetsInfo()->extends(className, QLatin1String("QStackedWidget"))
- || customWidgetsInfo()->extends(className, QLatin1String("QToolBox"))
- || customWidgetsInfo()->extends(className, QLatin1String("QTabWidget"))
- || customWidgetsInfo()->extends(className, QLatin1String("QScrollArea"))
- || customWidgetsInfo()->extends(className, QLatin1String("QMdiArea"))
- || customWidgetsInfo()->extends(className, QLatin1String("QWizard"))
- || customWidgetsInfo()->extends(className, QLatin1String("QDockWidget"));
-}
-
-bool Uic::isCustomWidgetContainer(const QString &className) const
-{
- return customWidgetsInfo()->isCustomWidgetContainer(className);
-}
-
-bool Uic::isStatusBar(const QString &className) const
-{
- return customWidgetsInfo()->extends(className, QLatin1String("QStatusBar"));
-}
-
-bool Uic::isMenuBar(const QString &className) const
-{
- return customWidgetsInfo()->extends(className, QLatin1String("QMenuBar"));
+ static const QStringList containers = {
+ QLatin1String("QStackedWidget"), QLatin1String("QToolBox"),
+ QLatin1String("QTabWidget"), QLatin1String("QScrollArea"),
+ QLatin1String("QMdiArea"), QLatin1String("QWizard"),
+ QLatin1String("QDockWidget")
+ };
+
+ return customWidgetsInfo()->extendsOneOf(className, containers);
}
bool Uic::isMenu(const QString &className) const
{
- return customWidgetsInfo()->extends(className, QLatin1String("QMenu"))
- || customWidgetsInfo()->extends(className, QLatin1String("QPopupMenu"));
+ static const QStringList menus = {
+ QLatin1String("QMenu"), QLatin1String("QPopupMenu")
+ };
+ return customWidgetsInfo()->extendsOneOf(className, menus);
}
QT_END_NAMESPACE
diff --git a/src/tools/uic/uic.h b/src/tools/uic/uic.h
index 4c961aa0a5..f3dfd49149 100644
--- a/src/tools/uic/uic.h
+++ b/src/tools/uic/uic.h
@@ -53,7 +53,7 @@ struct Option;
class Uic
{
- Q_DISABLE_COPY(Uic)
+ Q_DISABLE_COPY_MOVE(Uic)
public:
Uic(Driver *driver);
~Uic();
@@ -85,18 +85,14 @@ public:
bool write(DomUI *ui);
- bool isMainWindow(const QString &className) const;
- bool isToolBar(const QString &className) const;
- bool isStatusBar(const QString &className) const;
bool isButton(const QString &className) const;
bool isContainer(const QString &className) const;
- bool isCustomWidgetContainer(const QString &className) const;
- bool isMenuBar(const QString &className) const;
bool isMenu(const QString &className) const;
private:
// copyright header
- void writeCopyrightHeader(DomUI *ui);
+ void writeCopyrightHeaderCpp(const DomUI *ui) const;
+ void writeCopyrightHeaderPython(const DomUI *ui) const;
DomUI *parseUiFile(QXmlStreamReader &reader);
// header protection
diff --git a/src/tools/uic/uic.pri b/src/tools/uic/uic.pri
index 3f0bab05dd..1c9098dcf9 100644
--- a/src/tools/uic/uic.pri
+++ b/src/tools/uic/uic.pri
@@ -5,7 +5,6 @@ HEADERS += \
$$PWD/customwidgetsinfo.h \
$$PWD/databaseinfo.h \
$$PWD/driver.h \
- $$PWD/globaldefs.h \
$$PWD/option.h \
$$PWD/treewalker.h \
$$PWD/utils.h \
diff --git a/src/tools/uic/uic.pro b/src/tools/uic/uic.pro
index 18511395d9..1bf8ef8ad3 100644
--- a/src/tools/uic/uic.pro
+++ b/src/tools/uic/uic.pro
@@ -5,7 +5,9 @@ option(host_build)
DEFINES += QT_UIC QT_NO_CAST_FROM_ASCII QT_NO_FOREACH
include(uic.pri)
+include(shared/shared.pri)
include(cpp/cpp.pri)
+include(python/python.pri)
HEADERS += uic.h
diff --git a/src/tools/uic/utils.h b/src/tools/uic/utils.h
index 3f32a532ca..34c4ab23d4 100644
--- a/src/tools/uic/utils.h
+++ b/src/tools/uic/utils.h
@@ -42,55 +42,6 @@ inline bool toBool(const QString &str)
inline QString toString(const DomString *str)
{ return str ? str->text() : QString(); }
-inline QString fixString(const QString &str, const QString &indent)
-{
- QString cursegment;
- QStringList result;
- const QByteArray utf8 = str.toUtf8();
- const int utf8Length = utf8.length();
-
- for (int i = 0; i < utf8Length; ++i) {
- const uchar cbyte = utf8.at(i);
- if (cbyte >= 0x80) {
- cursegment += QLatin1Char('\\');
- cursegment += QString::number(cbyte, 8);
- } else {
- switch(cbyte) {
- case '\\':
- cursegment += QLatin1String("\\\\"); break;
- case '\"':
- cursegment += QLatin1String("\\\""); break;
- case '\r':
- break;
- case '\n':
- cursegment += QLatin1String("\\n\"\n\""); break;
- default:
- cursegment += QLatin1Char(cbyte);
- }
- }
-
- if (cursegment.length() > 1024) {
- result << cursegment;
- cursegment.clear();
- }
- }
-
- if (!cursegment.isEmpty())
- result << cursegment;
-
-
- QString joinstr = QLatin1String("\"\n");
- joinstr += indent;
- joinstr += indent;
- joinstr += QLatin1Char('"');
-
- QString rc(QLatin1Char('"'));
- rc += result.join(joinstr);
- rc += QLatin1Char('"');
-
- return rc;
-}
-
inline QHash<QString, DomProperty *> propertyMap(const QList<DomProperty *> &properties)
{
QHash<QString, DomProperty *> map;
diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp
index 507584eb02..7f87288520 100644
--- a/src/widgets/accessible/qaccessiblemenu.cpp
+++ b/src/widgets/accessible/qaccessiblemenu.cpp
@@ -47,6 +47,7 @@
#endif
#include <QtWidgets/QAction>
#include <qstyle.h>
+#include <private/qwidget_p.h>
#ifndef QT_NO_ACCESSIBILITY
@@ -241,15 +242,9 @@ QObject *QAccessibleMenuItem::object() const
/*! \reimp */
QWindow *QAccessibleMenuItem::window() const
{
- QWindow *result = nullptr;
- if (!m_owner.isNull()) {
- result = m_owner->windowHandle();
- if (!result) {
- if (const QWidget *nativeParent = m_owner->nativeParentWidget())
- result = nativeParent->windowHandle();
- }
- }
- return result;
+ return m_owner.isNull()
+ ? nullptr
+ : qt_widget_private(m_owner.data())->windowHandle(QWidgetPrivate::WindowHandleMode::Closest);
}
QRect QAccessibleMenuItem::rect() const
diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp
index 0d87cc486d..52c953ed3a 100644
--- a/src/widgets/accessible/qaccessiblewidgets.cpp
+++ b/src/widgets/accessible/qaccessiblewidgets.cpp
@@ -101,9 +101,9 @@ QString qt_accHotKey(const QString &text);
QList<QWidget*> childWidgets(const QWidget *widget)
{
- if (widget == 0)
- return QList<QWidget*>();
QList<QWidget*> widgets;
+ if (!widget)
+ return widgets;
for (QObject *o : widget->children()) {
QWidget *w = qobject_cast<QWidget *>(o);
if (!w)
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index 29178c02c3..82c341b47c 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -57,6 +57,11 @@
#include "qpainter.h"
#include "qpixmap.h"
#include "qpushbutton.h"
+#if QT_CONFIG(regularexpression)
+#include <qregularexpression.h>
+#else
+#include <qregexp.h>
+#endif
#if QT_CONFIG(settings)
#include "qsettings.h"
#endif
@@ -646,7 +651,7 @@ void QColorWell::mouseMoveEvent(QMouseEvent *e)
drg->setMimeData(mime);
drg->setPixmap(pix);
mousePressed = false;
- drg->start();
+ drg->exec(Qt::CopyAction);
}
#endif
}
@@ -842,8 +847,8 @@ void QColorLuminancePicker::paintEvent(QPaintEvent *)
p.drawPixmap(1, coff, *pix);
const QPalette &g = palette();
qDrawShadePanel(&p, r, g, true);
- p.setPen(g.foreground().color());
- p.setBrush(g.foreground());
+ p.setPen(g.windowText().color());
+ p.setBrush(g.windowText());
QPolygon a;
int y = val2y(val);
a.setPoints(3, w, y, w+5, y+5, w+5, y-5);
@@ -1131,7 +1136,7 @@ void QColorShowLabel::mouseMoveEvent(QMouseEvent *e)
drg->setMimeData(mime);
drg->setPixmap(pix);
mousePressed = false;
- drg->start();
+ drg->exec(Qt::CopyAction);
}
#endif
}
@@ -1179,7 +1184,8 @@ QColorShower::QColorShower(QColorDialog *parent)
curQColor = Qt::white;
gl = new QGridLayout(this);
- gl->setMargin(gl->spacing());
+ const int s = gl->spacing();
+ gl->setContentsMargins(s, s, s, s);
lab = new QColorShowLabel(this);
#ifdef QT_SMALL_COLORDIALOG
@@ -1615,7 +1621,7 @@ void QColorDialogPrivate::_q_pickScreenColor()
q->grabMouse();
#endif
-#ifdef Q_OS_WIN32 // excludes WinCE and WinRT
+#ifdef Q_OS_WIN32 // excludes WinRT
// On Windows mouse tracking doesn't work over other processes's windows
updateTimer->start(30);
@@ -1807,7 +1813,7 @@ void QColorDialogPrivate::initWidgets()
rightLay->addStretch();
cs = new QColorShower(q);
- pickLay->setMargin(cs->gl->margin());
+ pickLay->setContentsMargins(cs->gl->contentsMargins());
QObject::connect(cs, SIGNAL(newCol(QRgb)), q, SLOT(_q_newColorTypedIn(QRgb)));
QObject::connect(cs, SIGNAL(currentColorChanged(QColor)),
q, SIGNAL(currentColorChanged(QColor)));
@@ -1816,7 +1822,7 @@ void QColorDialogPrivate::initWidgets()
#else
rightLay->addWidget(cs);
if (leftLay)
- leftLay->addSpacing(cs->gl->margin());
+ leftLay->addSpacing(cs->gl->contentsMargins().right());
#endif
buttons = new QDialogButtonBox(q);
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp
index 1c10e3e786..5692a16bce 100644
--- a/src/widgets/dialogs/qdialog.cpp
+++ b/src/widgets/dialogs/qdialog.cpp
@@ -148,7 +148,7 @@ bool QDialogPrivate::canBeNativeDialog() const
/*!
\internal
- Properly hides dialog and sets the \p resultCode
+ Properly hides dialog and sets the \a resultCode.
*/
void QDialogPrivate::hide(int resultCode)
{
@@ -164,8 +164,8 @@ void QDialogPrivate::hide(int resultCode)
/*!
\internal
- Emits finished() signal with \p resultCode. If the \p dialogCode
- is equal to 0 emits rejected(), if the \p dialogCode is equal to
+ Emits finished() signal with \a resultCode. If the \a dialogCode
+ is equal to 0 emits rejected(), if the \a dialogCode is equal to
1 emits accepted().
*/
void QDialogPrivate::finalize(int resultCode, int dialogCode)
@@ -270,12 +270,11 @@ void QDialogPrivate::deletePlatformHelper()
The most common way to display a modal dialog is to call its
exec() function. When the user closes the dialog, exec() will
- provide a useful \l{#return}{return value}. Typically,
- to get the dialog to close and return the appropriate value, we
- connect a default button, e.g. \uicontrol OK, to the accept() slot and a
- \uicontrol Cancel button to the reject() slot.
- Alternatively you can call the done() slot with \c Accepted or
- \c Rejected.
+ provide a useful \l{#return}{return value}. To close the dialog
+ and return the appropriate value, you must connect a default button,
+ e.g. an \uicontrol OK button to the accept() slot and a
+ \uicontrol Cancel button to the reject() slot. Alternatively, you
+ can call the done() slot with \c Accepted or \c Rejected.
An alternative is to call setModal(true) or setWindowModality(),
then show(). Unlike exec(), show() returns control to the caller
@@ -429,7 +428,7 @@ QDialog::~QDialog()
/*!
\internal
This function is called by the push button \a pushButton when it
- becomes the default button. If \a pushButton is 0, the dialogs
+ becomes the default button. If \a pushButton is \nullptr, the dialogs
default default button becomes the default button. This is what a
push button calls when it loses focus.
*/
@@ -767,12 +766,31 @@ void QDialog::setVisible(bool visible)
if (!testAttribute(Qt::WA_DontShowOnScreen) && d->canBeNativeDialog() && d->setNativeDialogVisible(visible))
return;
+ // We should not block windows by the invisible modal dialog
+ // if a platform-specific dialog is implemented as an in-process
+ // Qt window, because in this case it will also be blocked.
+ const bool dontBlockWindows = testAttribute(Qt::WA_DontShowOnScreen)
+ && d->styleHint(QPlatformDialogHelper::DialogIsQtWindow).toBool();
+ Qt::WindowModality oldModality;
+ bool wasModalitySet;
+
+ if (dontBlockWindows) {
+ oldModality = windowModality();
+ wasModalitySet = testAttribute(Qt::WA_SetWindowModality);
+ setWindowModality(Qt::NonModal);
+ }
+
if (visible) {
if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
return;
QWidget::setVisible(visible);
+#if QT_DEPRECATED_SINCE(5, 13)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
showExtension(d->doShowExtension);
+QT_WARNING_POP
+#endif
QWidget *fw = window()->focusWidget();
if (!fw)
fw = this;
@@ -833,6 +851,11 @@ void QDialog::setVisible(bool visible)
d->eventLoop->exit();
}
+ if (dontBlockWindows) {
+ setWindowModality(oldModality);
+ setAttribute(Qt::WA_SetWindowModality, wasModalitySet);
+ }
+
#if QT_CONFIG(pushbutton)
const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
if (d->mainDef && isActiveWindow()
@@ -934,6 +957,7 @@ void QDialog::adjustPosition(QWidget* w)
move(p);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -1002,7 +1026,7 @@ void QDialog::setExtension(QWidget* extension)
/*!
\obsolete
- Returns the dialog's extension or 0 if no extension has been
+ Returns the dialog's extension or \nullptr if no extension has been
defined.
Instead of using this functionality, we recommend that you simply call
@@ -1078,7 +1102,7 @@ void QDialog::showExtension(bool showIt)
#endif
}
}
-
+#endif
/*! \reimp */
QSize QDialog::sizeHint() const
diff --git a/src/widgets/dialogs/qdialog.h b/src/widgets/dialogs/qdialog.h
index 7f267dd939..ce2194a1de 100644
--- a/src/widgets/dialogs/qdialog.h
+++ b/src/widgets/dialogs/qdialog.h
@@ -69,11 +69,12 @@ public:
void setVisible(bool visible) override;
- void setOrientation(Qt::Orientation orientation);
- Qt::Orientation orientation() const;
-
- void setExtension(QWidget* extension);
- QWidget* extension() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use show/hide on the affected widget instead") void setOrientation(Qt::Orientation orientation);
+ QT_DEPRECATED_X("Use show/hide on the affected widget instead") Qt::Orientation orientation() const;
+ QT_DEPRECATED_X("Use show/hide on the affected widget instead") void setExtension(QWidget* extension);
+ QT_DEPRECATED_X("Use show/hide on the affected widget instead") QWidget* extension() const;
+#endif
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
@@ -96,7 +97,9 @@ public Q_SLOTS:
virtual void accept();
virtual void reject();
- void showExtension(bool);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use show/hide on the affected widget instead") void showExtension(bool);
+#endif
protected:
QDialog(QDialogPrivate &, QWidget *parent, Qt::WindowFlags f = Qt::WindowFlags());
diff --git a/src/widgets/dialogs/qdialog_p.h b/src/widgets/dialogs/qdialog_p.h
index 92634f6793..74f775a0bd 100644
--- a/src/widgets/dialogs/qdialog_p.h
+++ b/src/widgets/dialogs/qdialog_p.h
@@ -75,15 +75,15 @@ public:
QDialogPrivate()
:
#if QT_CONFIG(pushbutton)
- mainDef(0),
+ mainDef(nullptr),
#endif
- orientation(Qt::Horizontal),extension(0), doShowExtension(false),
+ orientation(Qt::Horizontal),extension(nullptr), doShowExtension(false),
#if QT_CONFIG(sizegrip)
- resizer(0),
+ resizer(nullptr),
sizeGripEnabled(false),
#endif
- rescode(0), resetModalityTo(-1), wasModalitySet(true), eventLoop(0),
- nativeDialogInUse(false), m_platformHelper(0), m_platformHelperCreated(false)
+ rescode(0), resetModalityTo(-1), wasModalitySet(true), eventLoop(nullptr),
+ nativeDialogInUse(false), m_platformHelper(nullptr), m_platformHelperCreated(false)
{}
~QDialogPrivate();
@@ -140,14 +140,14 @@ class QAutoPointer {
struct internal { void func() {} };
typedef void (internal::*RestrictedBool)();
public:
- explicit QAutoPointer(T *t) Q_DECL_NOTHROW : o(t) {}
+ explicit QAutoPointer(T *t) noexcept : o(t) {}
~QAutoPointer() { delete o; }
- T *operator->() const Q_DECL_NOTHROW { return get(); }
- T *get() const Q_DECL_NOTHROW { return o; }
+ T *operator->() const noexcept { return get(); }
+ T *get() const noexcept { return o; }
T &operator*() const { return *get(); }
- operator RestrictedBool() const Q_DECL_NOTHROW { return o ? &internal::func : nullptr; }
- bool operator!() const Q_DECL_NOTHROW { return !o; }
+ operator RestrictedBool() const noexcept { return o ? &internal::func : nullptr; }
+ bool operator!() const noexcept { return !o; }
private:
Q_DISABLE_COPY(QAutoPointer);
};
diff --git a/src/widgets/dialogs/qerrormessage.cpp b/src/widgets/dialogs/qerrormessage.cpp
index fd68f19680..51a3e080bf 100644
--- a/src/widgets/dialogs/qerrormessage.cpp
+++ b/src/widgets/dialogs/qerrormessage.cpp
@@ -322,8 +322,8 @@ bool QErrorMessagePrivate::nextPending()
#else
errors->setPlainText(message);
#endif
- currentMessage = qMove(message);
- currentType = qMove(type);
+ currentMessage = std::move(message);
+ currentType = std::move(type);
return true;
}
}
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index eb3479b3e0..2f45635298 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -73,6 +73,11 @@
#elif defined(Q_OS_WIN)
# include <QtCore/qt_windows.h>
#endif
+#if defined(Q_OS_WASM)
+#include <private/qwasmlocalfileaccess_p.h>
+#endif
+
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -584,10 +589,13 @@ void QFileDialogPrivate::retranslateWindowTitle()
return;
if (q->acceptMode() == QFileDialog::AcceptOpen) {
const QFileDialog::FileMode fileMode = q->fileMode();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fileMode == QFileDialog::DirectoryOnly || fileMode == QFileDialog::Directory)
q->setWindowTitle(QFileDialog::tr("Find Directory"));
else
q->setWindowTitle(QFileDialog::tr("Open"));
+QT_WARNING_POP
} else
q->setWindowTitle(QFileDialog::tr("Save As"));
@@ -611,7 +619,10 @@ void QFileDialogPrivate::updateFileNameLabel()
setLabelTextControl(QFileDialog::FileName, options->labelText(QFileDialogOptions::FileName));
} else {
switch (q_func()->fileMode()) {
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
case QFileDialog::DirectoryOnly:
+QT_WARNING_POP
case QFileDialog::Directory:
setLabelTextControl(QFileDialog::FileName, QFileDialog::tr("Directory:"));
break;
@@ -639,7 +650,10 @@ void QFileDialogPrivate::updateOkButtonText(bool saveAsOnFolder)
return;
} else {
switch (q->fileMode()) {
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
case QFileDialog::DirectoryOnly:
+QT_WARNING_POP
case QFileDialog::Directory:
setLabelTextControl(QFileDialog::Accept, QFileDialog::tr("&Choose"));
break;
@@ -1359,6 +1373,7 @@ void QFileDialog::setNameFilter(const QString &filter)
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\property QFileDialog::nameFilterDetailsVisible
\obsolete
@@ -1380,6 +1395,7 @@ bool QFileDialog::isNameFilterDetailsVisible() const
{
return !testOption(HideNameFilterDetails);
}
+#endif
/*
@@ -1704,7 +1720,10 @@ void QFileDialog::setFileMode(QFileDialog::FileMode mode)
d->options->setFileMode(static_cast<QFileDialogOptions::FileMode>(mode));
// keep ShowDirsOnly option in sync with fileMode (BTW, DirectoryOnly is obsolete)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
setOption(ShowDirsOnly, mode == DirectoryOnly);
+QT_WARNING_POP
if (!d->usingWidgets())
return;
@@ -1722,11 +1741,14 @@ void QFileDialog::setFileMode(QFileDialog::FileMode mode)
// set filter
d->model->setFilter(d->filterForMode(filter()));
// setup file type for directory
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (mode == DirectoryOnly || mode == Directory) {
d->qFileDialogUi->fileTypeCombo->clear();
d->qFileDialogUi->fileTypeCombo->addItem(tr("Directories"));
d->qFileDialogUi->fileTypeCombo->setEnabled(false);
}
+QT_WARNING_POP
d->updateFileNameLabel();
d->updateOkButtonText();
d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
@@ -1859,6 +1881,7 @@ QFileDialog::AcceptMode QFileDialog::acceptMode() const
return static_cast<AcceptMode>(d->options->acceptMode());
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\property QFileDialog::readOnly
\obsolete
@@ -1918,6 +1941,7 @@ bool QFileDialog::confirmOverwrite() const
{
return !testOption(DontConfirmOverwrite);
}
+#endif
/*!
\property QFileDialog::defaultSuffix
@@ -2122,8 +2146,8 @@ QString QFileDialog::labelText(DialogLabel label) const
\snippet code/src_gui_dialogs_qfiledialog.cpp 8
The function creates a modal file dialog with the given \a parent widget.
- If \a parent is not 0, the dialog will be shown centered over the parent
- widget.
+ If \a parent is not \nullptr, the dialog will be shown centered over the
+ parent widget.
The file dialog's working directory will be set to \a dir. If \a dir
includes a file name, the file will be selected. Only files that match the
@@ -2145,8 +2169,8 @@ QString QFileDialog::labelText(DialogLabel label) const
native file dialog and not a QFileDialog.
On Windows the dialog will spin a blocking modal event loop that will not
- dispatch any QTimers, and if \a parent is not 0 then it will position the
- dialog just below the parent's title bar.
+ dispatch any QTimers, and if \a parent is not \nullptr then it will position
+ the dialog just below the parent's title bar.
On Unix/X11, the normal behavior of the file dialog is to resolve and
follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
@@ -2235,8 +2259,8 @@ QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
\snippet code/src_gui_dialogs_qfiledialog.cpp 9
This function creates a modal file dialog with the given \a parent widget.
- If \a parent is not 0, the dialog will be shown centered over the parent
- widget.
+ If \a parent is not \nullptr, the dialog will be shown centered over the
+ parent widget.
The file dialog's working directory will be set to \a dir. If \a dir
includes a file name, the file will be selected. The filter is set to
@@ -2254,8 +2278,8 @@ QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
native file dialog and not a QFileDialog.
On Windows the dialog will spin a blocking modal event loop that will not
- dispatch any QTimers, and if \a parent is not 0 then it will position the
- dialog just below the parent's title bar.
+ dispatch any QTimers, and if \a parent is not \nullptr then it will position
+ the dialog just below the parent's title bar.
On Unix/X11, the normal behavior of the file dialog is to resolve and
follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
@@ -2344,12 +2368,91 @@ QList<QUrl> QFileDialog::getOpenFileUrls(QWidget *parent,
}
/*!
+ This is a convenience static function that will return the content of a file
+ selected by the user.
+
+ This function is used to access local files on Qt for WebAssembly, where the web
+ sandbox places restrictions on how such access may happen. Its implementation will
+ make the browser display a native file dialog, where the user makes the file selection.
+
+ It can also be used on other platforms, where it will fall back to using QFileDialog.
+
+ The function is asynchronous and returns immediately. The \a fileOpenCompleted
+ callback will be called when a file has been selected and its contents has been
+ read into memory.
+
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 14
+ \since 5.13
+*/
+void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::function<void(const QString &, const QByteArray &)> &fileOpenCompleted)
+{
+#ifdef Q_OS_WASM
+ auto openFileImpl = std::make_shared<std::function<void(void)>>();
+ QString fileName;
+ QByteArray fileContent;
+ *openFileImpl = [=]() mutable {
+ auto fileDialogClosed = [&](bool fileSelected) {
+ if (!fileSelected) {
+ fileOpenCompleted(fileName, fileContent);
+ openFileImpl.reset();
+ }
+ };
+ auto acceptFile = [&](uint64_t size, const std::string name) -> char * {
+ const uint64_t twoGB = 1ULL << 31; // QByteArray limit
+ if (size > twoGB)
+ return nullptr;
+
+ fileName = QString::fromStdString(name);
+ fileContent.resize(size);
+ return fileContent.data();
+ };
+ auto fileContentReady = [&]() mutable {
+ fileOpenCompleted(fileName, fileContent);
+ openFileImpl.reset();
+ };
+
+ auto qtFilterStringToWebAcceptString = [](const QString &qtString) {
+ // The Qt and Web name filter string formats are similar, but
+ // not identical.
+ return qtString.toStdString(); // ### TODO
+ };
+
+ QWasmLocalFileAccess::openFile(qtFilterStringToWebAcceptString(nameFilter), fileDialogClosed, acceptFile, fileContentReady);
+ };
+
+ (*openFileImpl)();
+#else
+ QFileDialog *dialog = new QFileDialog();
+ dialog->selectNameFilter(nameFilter);
+
+ auto fileSelected = [=](const QString &fileName) {
+ QByteArray fileContent;
+ if (!fileName.isNull()) {
+ QFile selectedFile(fileName);
+ selectedFile.open(QIODevice::ReadOnly);
+ fileContent = selectedFile.readAll();
+ }
+ fileOpenCompleted(fileName, fileContent);
+ };
+
+ auto dialogClosed = [=](int code) {
+ Q_UNUSED(code);
+ delete dialog;
+ };
+
+ connect(dialog, &QFileDialog::fileSelected, fileSelected);
+ connect(dialog, &QFileDialog::finished, dialogClosed);
+ dialog->show();
+#endif
+}
+
+/*!
This is a convenience static function that will return a file name selected
by the user. The file does not have to exist.
It creates a modal file dialog with the given \a parent widget. If
- \a parent is not 0, the dialog will be shown centered over the parent
- widget.
+ \a parent is not \nullptr, the dialog will be shown centered over the
+ parent widget.
\snippet code/src_gui_dialogs_qfiledialog.cpp 11
@@ -2375,9 +2478,9 @@ QList<QUrl> QFileDialog::getOpenFileUrls(QWidget *parent,
native file dialog and not a QFileDialog.
On Windows the dialog will spin a blocking modal event loop that will not
- dispatch any QTimers, and if \a parent is not 0 then it will position the
- dialog just below the parent's title bar. On \macos, with its native file
- dialog, the filter argument is ignored.
+ dispatch any QTimers, and if \a parent is not \nullptr then it will
+ position the dialog just below the parent's title bar. On \macos, with its
+ native file dialog, the filter argument is ignored.
On Unix/X11, the normal behavior of the file dialog is to resolve and
follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
@@ -2467,8 +2570,8 @@ QUrl QFileDialog::getSaveFileUrl(QWidget *parent,
\snippet code/src_gui_dialogs_qfiledialog.cpp 12
This function creates a modal file dialog with the given \a parent widget.
- If \a parent is not 0, the dialog will be shown centered over the parent
- widget.
+ If \a parent is not \nullptr, the dialog will be shown centered over the
+ parent widget.
The dialog's working directory is set to \a dir, and the caption is set to
\a caption. Either of these may be an empty string in which case the
@@ -2492,8 +2595,8 @@ QUrl QFileDialog::getSaveFileUrl(QWidget *parent,
symlinks as regular directories.
On Windows, the dialog will spin a blocking modal event loop that will not
- dispatch any QTimers, and if \a parent is not 0 then it will position the
- dialog just below the parent's title bar.
+ dispatch any QTimers, and if \a parent is not \nullptr then it will position
+ the dialog just below the parent's title bar.
\warning Do not delete \a parent during the execution of the dialog. If you
want to do this, you should create the dialog yourself using one of the
@@ -2548,7 +2651,10 @@ QUrl QFileDialog::getExistingDirectoryUrl(QWidget *parent,
args.parent = parent;
args.caption = caption;
args.directory = QFileDialogPrivate::workingDirectory(dir);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
args.mode = (options & ShowDirsOnly ? DirectoryOnly : Directory);
+QT_WARNING_POP
args.options = options;
QFileDialog dialog(args);
@@ -2661,7 +2767,10 @@ void QFileDialog::accept()
}
switch (fileMode()) {
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
case DirectoryOnly:
+QT_WARNING_POP
case Directory: {
QString fn = files.first();
QFileInfo info(fn);
@@ -2697,7 +2806,7 @@ void QFileDialog::accept()
}
// check if we have to ask for permission to overwrite the file
- if (!info.exists() || !confirmOverwrite() || acceptMode() == AcceptOpen) {
+ if (!info.exists() || testOption(DontConfirmOverwrite) || acceptMode() == AcceptOpen) {
d->emitFilesSelected(QStringList(fn));
QDialog::accept();
#if QT_CONFIG(messagebox)
@@ -3265,6 +3374,18 @@ void QFileDialogPrivate::_q_goHome()
q->setDirectory(QDir::homePath());
}
+
+void QFileDialogPrivate::saveHistorySelection()
+{
+ if (qFileDialogUi.isNull() || currentHistoryLocation < 0 || currentHistoryLocation >= currentHistory.size())
+ return;
+ auto &item = currentHistory[currentHistoryLocation];
+ item.selection.clear();
+ const auto selectedIndexes = qFileDialogUi->listView->selectionModel()->selectedRows();
+ for (const auto &index : selectedIndexes)
+ item.selection.append(QPersistentModelIndex(index));
+}
+
/*!
\internal
@@ -3278,17 +3399,49 @@ void QFileDialogPrivate::_q_pathChanged(const QString &newPath)
qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath));
q->setHistory(qFileDialogUi->lookInCombo->history());
- if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation) != QDir::toNativeSeparators(newPath)) {
+ const QString newNativePath = QDir::toNativeSeparators(newPath);
+
+ // equal paths indicate this was invoked by _q_navigateBack/Forward()
+ if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation).path != newNativePath) {
+ if (currentHistoryLocation >= 0)
+ saveHistorySelection();
while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.count()) {
currentHistory.removeLast();
}
- currentHistory.append(QDir::toNativeSeparators(newPath));
+ currentHistory.append({newNativePath, PersistentModelIndexList()});
++currentHistoryLocation;
}
qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);
qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);
}
+void QFileDialogPrivate::navigate(HistoryItem &historyItem)
+{
+ Q_Q(QFileDialog);
+ q->setDirectory(historyItem.path);
+ // Restore selection unless something has changed in the file system
+ if (qFileDialogUi.isNull() || historyItem.selection.isEmpty())
+ return;
+ if (std::any_of(historyItem.selection.cbegin(), historyItem.selection.cend(),
+ [](const QPersistentModelIndex &i) { return !i.isValid(); })) {
+ historyItem.selection.clear();
+ return;
+ }
+
+ QAbstractItemView *view = q->viewMode() == QFileDialog::List
+ ? static_cast<QAbstractItemView *>(qFileDialogUi->listView)
+ : static_cast<QAbstractItemView *>(qFileDialogUi->treeView);
+ auto selectionModel = view->selectionModel();
+ const QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select
+ | QItemSelectionModel::Rows;
+ selectionModel->select(historyItem.selection.constFirst(),
+ flags | QItemSelectionModel::Clear | QItemSelectionModel::Current);
+ for (int i = 1, size = historyItem.selection.size(); i < size; ++i)
+ selectionModel->select(historyItem.selection.at(i), flags);
+
+ view->scrollTo(historyItem.selection.constFirst());
+}
+
/*!
\internal
@@ -3296,11 +3449,9 @@ void QFileDialogPrivate::_q_pathChanged(const QString &newPath)
*/
void QFileDialogPrivate::_q_navigateBackward()
{
- Q_Q(QFileDialog);
if (!currentHistory.isEmpty() && currentHistoryLocation > 0) {
- --currentHistoryLocation;
- QString previousHistory = currentHistory.at(currentHistoryLocation);
- q->setDirectory(previousHistory);
+ saveHistorySelection();
+ navigate(currentHistory[--currentHistoryLocation]);
}
}
@@ -3311,11 +3462,9 @@ void QFileDialogPrivate::_q_navigateBackward()
*/
void QFileDialogPrivate::_q_navigateForward()
{
- Q_Q(QFileDialog);
if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) {
- ++currentHistoryLocation;
- QString nextHistory = currentHistory.at(currentHistoryLocation);
- q->setDirectory(nextHistory);
+ saveHistorySelection();
+ navigate(currentHistory[++currentHistoryLocation]);
}
}
@@ -3526,12 +3675,13 @@ void QFileDialogPrivate::_q_autoCompleteFileName(const QString &text)
if (oldFiles.removeAll(idx) == 0)
newFiles.append(idx);
}
- for (int i = 0; i < newFiles.count(); ++i)
- select(newFiles.at(i));
- if (lineEdit()->hasFocus())
- for (int i = 0; i < oldFiles.count(); ++i)
- qFileDialogUi->listView->selectionModel()->select(oldFiles.at(i),
- QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
+ for (const auto &newFile : qAsConst(newFiles))
+ select(newFile);
+ if (lineEdit()->hasFocus()) {
+ auto *sm = qFileDialogUi->listView->selectionModel();
+ for (const auto &oldFile : qAsConst(oldFiles))
+ sm->select(oldFile, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
+ }
}
}
@@ -3565,7 +3715,10 @@ void QFileDialogPrivate::_q_updateOkButton()
isOpenDirectory = true;
} else {
switch (fileMode) {
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
case QFileDialog::DirectoryOnly:
+QT_WARNING_POP
case QFileDialog::Directory: {
QString fn = files.first();
QModelIndex idx = model->index(fn);
@@ -3657,12 +3810,15 @@ void QFileDialogPrivate::_q_enterDirectory(const QModelIndex &index)
const QFileDialog::FileMode fileMode = q->fileMode();
q->setDirectory(path);
emit q->directoryEntered(path);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fileMode == QFileDialog::Directory
|| fileMode == QFileDialog::DirectoryOnly) {
// ### find out why you have to do both of these.
lineEdit()->setText(QString());
lineEdit()->clear();
}
+QT_WARNING_POP
} else {
// Do not accept when shift-clicking to multi-select a file in environments with single-click-activation (KDE)
if (!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, nullptr, qFileDialogUi->treeView)
@@ -3695,7 +3851,7 @@ void QFileDialogPrivate::_q_goToDirectory(const QString &path)
}
QDir dir(path2);
if (!dir.exists())
- dir = getEnvironmentVariable(path2);
+ dir.setPath(getEnvironmentVariable(path2));
if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {
_q_enterDirectory(index);
@@ -3754,7 +3910,10 @@ void QFileDialogPrivate::_q_selectionChanged()
{
const QFileDialog::FileMode fileMode = q_func()->fileMode();
const QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
bool stripDirs = (fileMode != QFileDialog::DirectoryOnly && fileMode != QFileDialog::Directory);
+QT_WARNING_POP
QStringList allFiles;
for (const auto &index : indexes) {
@@ -3806,10 +3965,13 @@ void QFileDialogPrivate::_q_rowsInserted(const QModelIndex &parent)
void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString &oldName, const QString &newName)
{
const QFileDialog::FileMode fileMode = q_func()->fileMode();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fileMode == QFileDialog::Directory || fileMode == QFileDialog::DirectoryOnly) {
if (path == rootPath() && lineEdit()->text() == oldName)
lineEdit()->setText(newName);
}
+QT_WARNING_POP
}
void QFileDialogPrivate::_q_emitUrlSelected(const QUrl &file)
diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h
index a4d289a77a..354a1f928b 100644
--- a/src/widgets/dialogs/qfiledialog.h
+++ b/src/widgets/dialogs/qfiledialog.h
@@ -46,6 +46,8 @@
#include <QtCore/qurl.h>
#include <QtWidgets/qdialog.h>
+#include <functional>
+
QT_REQUIRE_CONFIG(filedialog);
QT_BEGIN_NAMESPACE
@@ -64,19 +66,22 @@ class Q_WIDGETS_EXPORT QFileDialog : public QDialog
Q_PROPERTY(ViewMode viewMode READ viewMode WRITE setViewMode)
Q_PROPERTY(FileMode fileMode READ fileMode WRITE setFileMode)
Q_PROPERTY(AcceptMode acceptMode READ acceptMode WRITE setAcceptMode)
+ Q_PROPERTY(QString defaultSuffix READ defaultSuffix WRITE setDefaultSuffix)
+#if QT_DEPRECATED_SINCE(5, 13)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly DESIGNABLE false)
- Q_PROPERTY(bool resolveSymlinks READ resolveSymlinks WRITE setResolveSymlinks DESIGNABLE false)
Q_PROPERTY(bool confirmOverwrite READ confirmOverwrite WRITE setConfirmOverwrite DESIGNABLE false)
- Q_PROPERTY(QString defaultSuffix READ defaultSuffix WRITE setDefaultSuffix)
+ Q_PROPERTY(bool resolveSymlinks READ resolveSymlinks WRITE setResolveSymlinks DESIGNABLE false)
Q_PROPERTY(bool nameFilterDetailsVisible READ isNameFilterDetailsVisible
WRITE setNameFilterDetailsVisible DESIGNABLE false)
+#endif
Q_PROPERTY(Options options READ options WRITE setOptions)
Q_PROPERTY(QStringList supportedSchemes READ supportedSchemes WRITE setSupportedSchemes)
public:
enum ViewMode { Detail, List };
Q_ENUM(ViewMode)
- enum FileMode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly };
+ enum FileMode { AnyFile, ExistingFile, Directory, ExistingFiles,
+ DirectoryOnly Q_DECL_ENUMERATOR_DEPRECATED_X("Use setOption(ShowDirsOnly, true) instead")};
Q_ENUM(FileMode)
enum AcceptMode { AcceptOpen, AcceptSave };
Q_ENUM(AcceptMode)
@@ -87,7 +92,9 @@ public:
ShowDirsOnly = 0x00000001,
DontResolveSymlinks = 0x00000002,
DontConfirmOverwrite = 0x00000004,
- DontUseSheet = 0x00000008,
+#if QT_DEPRECATED_SINCE(5, 14)
+ DontUseSheet Q_DECL_ENUMERATOR_DEPRECATED = 0x00000008,
+#endif
DontUseNativeDialog = 0x00000010,
ReadOnly = 0x00000020,
HideNameFilterDetails = 0x00000040,
@@ -117,8 +124,12 @@ public:
void selectUrl(const QUrl &url);
QList<QUrl> selectedUrls() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use setOption(HideNameFilterDetails, !enabled) instead")
void setNameFilterDetailsVisible(bool enabled);
+ QT_DEPRECATED_X("Use !testOption(HideNameFilterDetails) instead")
bool isNameFilterDetailsVisible() const;
+#endif
void setNameFilter(const QString &filter);
void setNameFilters(const QStringList &filters);
@@ -145,11 +156,15 @@ public:
void setAcceptMode(AcceptMode mode);
AcceptMode acceptMode() const;
+#if QT_DEPRECATED_SINCE(5, 13)
void setReadOnly(bool enabled);
bool isReadOnly() const;
+ QT_DEPRECATED_X("Use setOption(DontResolveSymlinks, !enabled) instead")
void setResolveSymlinks(bool enabled);
+ QT_DEPRECATED_X("Use !testOption(DontResolveSymlinks) instead")
bool resolveSymlinks() const;
+#endif
void setSidebarUrls(const QList<QUrl> &urls);
QList<QUrl> sidebarUrls() const;
@@ -157,8 +172,12 @@ public:
QByteArray saveState() const;
bool restoreState(const QByteArray &state);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use setOption(DontConfirmOverwrite, !enabled) instead")
void setConfirmOverwrite(bool enabled);
+ QT_DEPRECATED_X("Use !testOption(DontConfirmOverwrite) instead")
bool confirmOverwrite() const;
+#endif
void setDefaultSuffix(const QString &suffix);
QString defaultSuffix() const;
@@ -263,6 +282,8 @@ public:
Options options = Options(),
const QStringList &supportedSchemes = QStringList());
+ static void getOpenFileContent(const QString &nameFilter,
+ const std::function<void(const QString &, const QByteArray &)> &fileContentsReady);
protected:
QFileDialog(const QFileDialogArgs &args);
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index 2e49696b77..dcf147348f 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -98,7 +98,7 @@ class QPlatformDialogHelper;
struct QFileDialogArgs
{
- QFileDialogArgs() : parent(0), mode(QFileDialog::AnyFile) {}
+ QFileDialogArgs() : parent(nullptr), mode(QFileDialog::AnyFile) {}
QWidget *parent;
QString caption;
@@ -116,6 +116,14 @@ class Q_WIDGETS_EXPORT QFileDialogPrivate : public QDialogPrivate
Q_DECLARE_PUBLIC(QFileDialog)
public:
+ using PersistentModelIndexList = QVector<QPersistentModelIndex>;
+
+ struct HistoryItem
+ {
+ QString path;
+ PersistentModelIndexList selection;
+ };
+
QFileDialogPrivate();
QPlatformFileDialogHelper *platformFileDialogHelper() const
@@ -164,13 +172,9 @@ public:
QDir::Filters filterForMode(QDir::Filters filters) const
{
- const QFileDialog::FileMode fileMode = q_func()->fileMode();
- if (fileMode == QFileDialog::DirectoryOnly) {
- filters |= QDir::Drives | QDir::AllDirs | QDir::Dirs;
+ filters |= QDir::Drives | QDir::AllDirs | QDir::Dirs | QDir::Files;
+ if (q_func()->testOption(QFileDialog::ShowDirsOnly))
filters &= ~QDir::Files;
- } else {
- filters |= QDir::Drives | QDir::AllDirs | QDir::Files | QDir::Dirs;
- }
return filters;
}
@@ -197,9 +201,11 @@ public:
void retranslateWindowTitle();
void retranslateStrings();
void emitFilesSelected(const QStringList &files);
+ void saveHistorySelection();
void _q_goHome();
void _q_pathChanged(const QString &);
+ void navigate(HistoryItem &);
void _q_navigateBackward();
void _q_navigateForward();
void _q_navigateToParent();
@@ -241,7 +247,7 @@ public:
QString setWindowTitle;
- QStringList currentHistory;
+ QList<HistoryItem> currentHistory;
int currentHistoryLocation;
QAction *renameAction;
@@ -290,13 +296,13 @@ private:
virtual void helperPrepareShow(QPlatformDialogHelper *) override;
virtual void helperDone(QDialog::DialogCode, QPlatformDialogHelper *) override;
- Q_DISABLE_COPY(QFileDialogPrivate)
+ Q_DISABLE_COPY_MOVE(QFileDialogPrivate)
};
class QFileDialogLineEdit : public QLineEdit
{
public:
- QFileDialogLineEdit(QWidget *parent = 0) : QLineEdit(parent), d_ptr(0){}
+ QFileDialogLineEdit(QWidget *parent = nullptr) : QLineEdit(parent), d_ptr(nullptr){}
void setFileDialogPrivate(QFileDialogPrivate *d_pointer) {d_ptr = d_pointer; }
void keyPressEvent(QKeyEvent *e) override;
bool hideOnEsc;
@@ -307,7 +313,7 @@ private:
class QFileDialogComboBox : public QComboBox
{
public:
- QFileDialogComboBox(QWidget *parent = 0) : QComboBox(parent), urlModel(0) {}
+ QFileDialogComboBox(QWidget *parent = nullptr) : QComboBox(parent), urlModel(nullptr) {}
void setFileDialogPrivate(QFileDialogPrivate *d_pointer);
void showPopup() override;
void setHistory(const QStringList &paths);
@@ -323,7 +329,7 @@ private:
class QFileDialogListView : public QListView
{
public:
- QFileDialogListView(QWidget *parent = 0);
+ QFileDialogListView(QWidget *parent = nullptr);
void setFileDialogPrivate(QFileDialogPrivate *d_pointer);
QSize sizeHint() const override;
protected:
diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp
index 1e03ad8b06..f39ae2b53e 100644
--- a/src/widgets/dialogs/qfileinfogatherer.cpp
+++ b/src/widgets/dialogs/qfileinfogatherer.cpp
@@ -54,12 +54,12 @@ QT_BEGIN_NAMESPACE
static QBasicAtomicInt fetchedRoot = Q_BASIC_ATOMIC_INITIALIZER(false);
Q_AUTOTEST_EXPORT void qt_test_resetFetchedRoot()
{
- fetchedRoot.store(false);
+ fetchedRoot.storeRelaxed(false);
}
Q_AUTOTEST_EXPORT bool qt_test_isFetchedRoot()
{
- return fetchedRoot.load();
+ return fetchedRoot.loadRelaxed();
}
#endif
@@ -111,7 +111,7 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent)
*/
QFileInfoGatherer::~QFileInfoGatherer()
{
- abort.store(true);
+ abort.storeRelaxed(true);
QMutexLocker locker(&mutex);
condition.wakeAll();
locker.unlock();
@@ -247,9 +247,9 @@ void QFileInfoGatherer::run()
{
forever {
QMutexLocker locker(&mutex);
- while (!abort.load() && path.isEmpty())
+ while (!abort.loadRelaxed() && path.isEmpty())
condition.wait(&mutex);
- if (abort.load())
+ if (abort.loadRelaxed())
return;
const QString thisPath = qAsConst(path).front();
path.pop_front();
@@ -303,7 +303,7 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
// List drives
if (path.isEmpty()) {
#ifdef QT_BUILD_INTERNAL
- fetchedRoot.store(true);
+ fetchedRoot.storeRelaxed(true);
#endif
QFileInfoList infoList;
if (files.isEmpty()) {
@@ -332,7 +332,7 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
QStringList allFiles;
if (files.isEmpty()) {
QDirIterator dirIt(path, QDir::AllEntries | QDir::System | QDir::Hidden);
- while (!abort.load() && dirIt.hasNext()) {
+ while (!abort.loadRelaxed() && dirIt.hasNext()) {
dirIt.next();
fileInfo = dirIt.fileInfo();
allFiles.append(fileInfo.fileName());
@@ -343,7 +343,7 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
emit newListOfFiles(path, allFiles);
QStringList::const_iterator filesIt = filesToCheck.constBegin();
- while (!abort.load() && filesIt != filesToCheck.constEnd()) {
+ while (!abort.loadRelaxed() && filesIt != filesToCheck.constEnd()) {
fileInfo.setFile(path + QDir::separator() + *filesIt);
++filesIt;
fetch(fileInfo, base, firstTime, updatedFiles, path);
diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h
index 134a14b7ce..795f60249f 100644
--- a/src/widgets/dialogs/qfileinfogatherer_p.h
+++ b/src/widgets/dialogs/qfileinfogatherer_p.h
@@ -166,7 +166,7 @@ Q_SIGNALS:
void directoryLoaded(const QString &path);
public:
- explicit QFileInfoGatherer(QObject *parent = 0);
+ explicit QFileInfoGatherer(QObject *parent = nullptr);
~QFileInfoGatherer();
#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index d29f74e93d..a778fd3a45 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -1197,8 +1197,8 @@ QStringList QFileSystemModel::mimeTypes() const
\a indexes. The format used to describe the items corresponding to the
indexes is obtained from the mimeTypes() function.
- If the list of indexes is empty, 0 is returned rather than a serialized
- empty list.
+ If the list of indexes is empty, \nullptr is returned rather than a
+ serialized empty list.
*/
QMimeData *QFileSystemModel::mimeData(const QModelIndexList &indexes) const
{
@@ -1847,8 +1847,7 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QV
std::sort(rowsToUpdate.begin(), rowsToUpdate.end());
QString min;
QString max;
- for (int i = 0; i < rowsToUpdate.count(); ++i) {
- QString value = rowsToUpdate.at(i);
+ for (const QString &value : qAsConst(rowsToUpdate)) {
//##TODO is there a way to bundle signals with QString as the content of the list?
/*if (min.isEmpty()) {
min = value;
diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h
index 9c432e1ae6..d8f9f2b076 100644
--- a/src/widgets/dialogs/qfilesystemmodel_p.h
+++ b/src/widgets/dialogs/qfilesystemmodel_p.h
@@ -99,13 +99,13 @@ public:
class QFileSystemNode
{
public:
- explicit QFileSystemNode(const QString &filename = QString(), QFileSystemNode *p = 0)
- : fileName(filename), populatedChildren(false), isVisible(false), dirtyChildrenIndex(-1), parent(p), info(0) {}
+ explicit QFileSystemNode(const QString &filename = QString(), QFileSystemNode *p = nullptr)
+ : fileName(filename), populatedChildren(false), isVisible(false), dirtyChildrenIndex(-1), parent(p), info(nullptr) {}
~QFileSystemNode() {
qDeleteAll(children);
delete info;
- info = 0;
- parent = 0;
+ info = nullptr;
+ parent = nullptr;
}
QString fileName;
@@ -116,7 +116,7 @@ public:
inline qint64 size() const { if (info && !info->isDir()) return info->size(); return 0; }
inline QString type() const { if (info) return info->displayType; return QLatin1String(""); }
inline QDateTime lastModified() const { if (info) return info->lastModified(); return QDateTime(); }
- inline QFile::Permissions permissions() const { if (info) return info->permissions(); return 0; }
+ inline QFile::Permissions permissions() const { if (info) return info->permissions(); return nullptr; }
inline bool isReadable() const { return ((permissions() & QFile::ReadUser) != 0); }
inline bool isWritable() const { return ((permissions() & QFile::WriteUser) != 0); }
inline bool isExecutable() const { return ((permissions() & QFile::ExeUser) != 0); }
@@ -162,7 +162,7 @@ public:
return info && (*info == fileInfo);
}
- inline bool hasInformation() const { return info != 0; }
+ inline bool hasInformation() const { return info != nullptr; }
void populate(const QExtendedInformation &fileInfo) {
if (!info)
diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp
index 477c6bd540..2b81180ecb 100644
--- a/src/widgets/dialogs/qfontdialog.cpp
+++ b/src/widgets/dialogs/qfontdialog.cpp
@@ -534,7 +534,7 @@ void QFontDialogPrivate::updateFamilies()
//and try some fall backs
match_t type = MATCH_NONE;
- if (bestFamilyType <= MATCH_NONE && familyName2 == f.lastResortFamily())
+ if (bestFamilyType <= MATCH_NONE && familyName2 == QStringLiteral("helvetica"))
type = MATCH_LAST_RESORT;
if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.family())
type = MATCH_APP;
diff --git a/src/widgets/dialogs/qfscompleter_p.h b/src/widgets/dialogs/qfscompleter_p.h
index 3b829d4a52..f5110a7622 100644
--- a/src/widgets/dialogs/qfscompleter_p.h
+++ b/src/widgets/dialogs/qfscompleter_p.h
@@ -64,8 +64,8 @@ QT_BEGIN_NAMESPACE
*/
class Q_WIDGETS_EXPORT QFSCompleter : public QCompleter {
public:
- explicit QFSCompleter(QFileSystemModel *model, QObject *parent = 0)
- : QCompleter(model, parent), proxyModel(0), sourceModel(model)
+ explicit QFSCompleter(QFileSystemModel *model, QObject *parent = nullptr)
+ : QCompleter(model, parent), proxyModel(nullptr), sourceModel(model)
{
#if defined(Q_OS_WIN)
setCaseSensitivity(Qt::CaseInsensitive);
diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp
index ac1952a642..9bfea06a54 100644
--- a/src/widgets/dialogs/qmessagebox.cpp
+++ b/src/widgets/dialogs/qmessagebox.cpp
@@ -113,7 +113,7 @@ public:
, copyAvailable(false)
{
QVBoxLayout *layout = new QVBoxLayout;
- layout->setMargin(0);
+ layout->setContentsMargins(QMargins());
QFrame *line = new QFrame(this);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
@@ -834,7 +834,7 @@ QMessageBox::QMessageBox(QWidget *parent)
The message box is an \l{Qt::ApplicationModal} {application modal}
dialog box.
- On \macos, if \a parent is not 0 and you want your message box
+ On \macos, if \a parent is not \nullptr and you want your message box
to appear as a Qt::Sheet of that parent, set the message box's
\l{setWindowModality()} {window modality} to Qt::WindowModal
(default). Otherwise, the message box will be a standard dialog.
@@ -983,7 +983,7 @@ QMessageBox::StandardButton QMessageBox::standardButton(QAbstractButton *button)
\since 4.2
Returns a pointer corresponding to the standard button \a which,
- or 0 if the standard button doesn't exist in this message box.
+ or \nullptr if the standard button doesn't exist in this message box.
\sa standardButtons, standardButton()
*/
@@ -1106,7 +1106,7 @@ void QMessageBoxPrivate::detectEscapeButton()
\since 4.2
Returns the button that was clicked by the user,
- or 0 if the user hit the \uicontrol Esc key and
+ or \nullptr if the user hit the \uicontrol Esc key and
no \l{setEscapeButton()}{escape button} was set.
If exec() hasn't been called yet, returns nullptr.
@@ -1173,7 +1173,7 @@ void QMessageBox::setDefaultButton(QMessageBox::StandardButton button)
/*! \since 5.2
Sets the checkbox \a cb on the message dialog. The message box takes ownership of the checkbox.
- The argument \a cb can be 0 to remove an existing checkbox from the message box.
+ The argument \a cb can be \nullptr to remove an existing checkbox from the message box.
\sa checkBox()
*/
@@ -1205,7 +1205,7 @@ void QMessageBox::setCheckBox(QCheckBox *cb)
/*! \since 5.2
- Returns the checkbox shown on the dialog. This is 0 if no checkbox is set.
+ Returns the checkbox shown on the dialog. This is \nullptr if no checkbox is set.
\sa setCheckBox()
*/
@@ -1570,7 +1570,7 @@ QList<QAbstractButton *> QMessageBox::buttons() const
\since 4.5
Returns the button role for the specified \a button. This function returns
- \l InvalidRole if \a button is 0 or has not been added to the message box.
+ \l InvalidRole if \a button is \nullptr or has not been added to the message box.
\sa buttons(), addButton()
*/
@@ -1835,7 +1835,7 @@ void QMessageBox::about(QWidget *parent, const QString &title, const QString &te
/*!
Displays a simple message box about Qt, with the given \a title
- and centered over \a parent (if \a parent is not 0). The message
+ and centered over \a parent (if \a parent is not \nullptr). The message
includes the version number of Qt being used by the application.
This is useful for inclusion in the \uicontrol Help menu of an application,
@@ -2662,14 +2662,9 @@ QPixmap QMessageBoxPrivate::standardIcon(QMessageBox::Icon icon, QMessageBox *mb
break;
}
if (!tmpIcon.isNull()) {
- QWindow *window = nullptr;
- if (mb) {
- window = mb->windowHandle();
- if (!window) {
- if (const QWidget *nativeParent = mb->nativeParentWidget())
- window = nativeParent->windowHandle();
- }
- }
+ QWindow *window = mb
+ ? qt_widget_private(mb)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest)
+ : nullptr;
return tmpIcon.pixmap(window, QSize(iconSize, iconSize));
}
return QPixmap();
diff --git a/src/widgets/dialogs/qmessagebox.h b/src/widgets/dialogs/qmessagebox.h
index 4b993a9e65..0a2edb1eee 100644
--- a/src/widgets/dialogs/qmessagebox.h
+++ b/src/widgets/dialogs/qmessagebox.h
@@ -284,9 +284,9 @@ public:
Q_SIGNALS:
void buttonClicked(QAbstractButton *button);
-#ifdef Q_QDOC
+#ifdef Q_CLANG_QDOC
public Q_SLOTS:
- int exec();
+ int exec() override;
#endif
protected:
diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp
index e1fb1055ae..078dd6463b 100644
--- a/src/widgets/dialogs/qprogressdialog.cpp
+++ b/src/widgets/dialogs/qprogressdialog.cpp
@@ -47,7 +47,6 @@
#include "qapplication.h"
#include "qstyle.h"
#include "qpushbutton.h"
-#include "qcursor.h"
#include "qtimer.h"
#include "qelapsedtimer.h"
#include <private/qdialog_p.h>
@@ -94,9 +93,6 @@ public:
bool cancellation_flag;
bool setValue_called;
QElapsedTimer starttime;
-#ifndef QT_NO_CURSOR
- QCursor parentCursor;
-#endif
int showTime;
bool autoClose;
bool autoReset;
@@ -597,12 +593,6 @@ void QProgressDialog::setRange(int minimum, int maximum)
void QProgressDialog::reset()
{
Q_D(QProgressDialog);
-#ifndef QT_NO_CURSOR
- if (value() >= 0) {
- if (parentWidget())
- parentWidget()->setCursor(d->parentCursor);
- }
-#endif
if (d->autoClose || d->forceHide)
hide();
d->bar->reset();
diff --git a/src/widgets/dialogs/qsidebar.cpp b/src/widgets/dialogs/qsidebar.cpp
index d52f18b406..2c8c66e1e2 100644
--- a/src/widgets/dialogs/qsidebar.cpp
+++ b/src/widgets/dialogs/qsidebar.cpp
@@ -381,8 +381,6 @@ QSidebar::QSidebar(QWidget *parent) : QListView(parent)
void QSidebar::setModelAndUrls(QFileSystemModel *model, const QList<QUrl> &newUrls)
{
- // ### TODO make icon size dynamic
- setIconSize(QSize(24,24));
setUniformItemSizes(true);
urlModel = new QUrlModel(this);
urlModel->setFileSystemModel(model);
diff --git a/src/widgets/dialogs/qsidebar_p.h b/src/widgets/dialogs/qsidebar_p.h
index 4a82f88878..6056f19452 100644
--- a/src/widgets/dialogs/qsidebar_p.h
+++ b/src/widgets/dialogs/qsidebar_p.h
@@ -67,7 +67,7 @@ class QFileSystemModel;
class QSideBarDelegate : public QStyledItemDelegate
{
public:
- QSideBarDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {}
+ QSideBarDelegate(QWidget *parent = nullptr) : QStyledItemDelegate(parent) {}
void initStyleOption(QStyleOptionViewItem *option,
const QModelIndex &index) const override;
};
@@ -82,7 +82,7 @@ public:
EnabledRole = Qt::UserRole + 2
};
- QUrlModel(QObject *parent = 0);
+ QUrlModel(QObject *parent = nullptr);
QStringList mimeTypes() const override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
@@ -127,7 +127,7 @@ Q_SIGNALS:
void goToUrl(const QUrl &url);
public:
- QSidebar(QWidget *parent = 0);
+ QSidebar(QWidget *parent = nullptr);
void setModelAndUrls(QFileSystemModel *model, const QList<QUrl> &newUrls);
~QSidebar();
diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp
index 21e1ff2778..f428114bbe 100644
--- a/src/widgets/dialogs/qwizard.cpp
+++ b/src/widgets/dialogs/qwizard.cpp
@@ -331,7 +331,7 @@ QWizardHeader::QWizardHeader(QWidget *parent)
titleLabel->setFont(font);
layout = new QGridLayout(this);
- layout->setMargin(0);
+ layout->setContentsMargins(QMargins());
layout->setSpacing(0);
layout->setRowMinimumHeight(3, 1);
@@ -769,7 +769,7 @@ void QWizardPrivate::reset()
for (int i = history.count() - 1; i >= 0; --i)
q->cleanupPage(history.at(i));
history.clear();
- for (QWizardPage *page : pageMap)
+ for (QWizardPage *page : qAsConst(pageMap))
page->d_func()->initialized = false;
current = -1;
@@ -1032,13 +1032,13 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
int pageColumn = qMin(1, numColumns - 1);
if (mac) {
- mainLayout->setMargin(0);
+ mainLayout->setContentsMargins(QMargins());
mainLayout->setSpacing(0);
buttonLayout->setContentsMargins(MacLayoutLeftMargin, MacButtonTopMargin, MacLayoutRightMargin, MacLayoutBottomMargin);
- pageVBoxLayout->setMargin(7);
+ pageVBoxLayout->setContentsMargins(7, 7, 7, 7);
} else {
if (modern) {
- mainLayout->setMargin(0);
+ mainLayout->setContentsMargins(QMargins());
mainLayout->setSpacing(0);
pageVBoxLayout->setContentsMargins(deltaMarginLeft, deltaMarginTop,
deltaMarginRight, deltaMarginBottom);
@@ -1595,23 +1595,25 @@ bool QWizardPrivate::handleAeroStyleChange()
bool vistaMargins = false;
if (isVistaThemeEnabled()) {
+ const int topOffset = vistaHelper->topOffset();
+ const int topPadding = vistaHelper->topPadding();
if (isVistaThemeEnabled(QVistaHelper::VistaAero)) {
if (isWindow) {
vistaHelper->setDWMTitleBar(QVistaHelper::ExtendedTitleBar);
q->installEventFilter(vistaHelper);
}
q->setMouseTracking(true);
- antiFlickerWidget->move(0, vistaHelper->titleBarSize() + vistaHelper->topOffset());
+ antiFlickerWidget->move(0, vistaHelper->titleBarSize() + topOffset);
vistaHelper->backButton()->move(
- 0, vistaHelper->topOffset() // ### should ideally work without the '+ 1'
- - qMin(vistaHelper->topOffset(), vistaHelper->topPadding() + 1));
+ 0, topOffset // ### should ideally work without the '+ 1'
+ - qMin(topOffset, topPadding + 1));
vistaMargins = true;
vistaHelper->backButton()->show();
} else {
if (isWindow)
vistaHelper->setDWMTitleBar(QVistaHelper::NormalTitleBar);
q->setMouseTracking(true);
- antiFlickerWidget->move(0, vistaHelper->topOffset());
+ antiFlickerWidget->move(0, topOffset);
vistaHelper->backButton()->move(0, -1); // ### should ideally work with (0, 0)
}
if (isWindow)
@@ -2374,8 +2376,8 @@ void QWizard::removePage(int id)
/*!
\fn QWizardPage *QWizard::page(int id) const
- Returns the page with the given \a id, or 0 if there is no such
- page.
+ Returns the page with the given \a id, or \nullptr if there is no
+ such page.
\sa addPage(), setPage()
*/
@@ -2462,8 +2464,8 @@ int QWizard::startId() const
}
/*!
- Returns a pointer to the current page, or 0 if there is no current
- page (e.g., before the wizard is shown).
+ Returns a pointer to the current page, or \nullptr if there is no
+ current page (e.g., before the wizard is shown).
This is equivalent to calling page(currentId()).
@@ -2954,7 +2956,7 @@ void QWizard::setDefaultProperty(const char *className, const char *property,
Passing 0 shows no side widget.
- When the \a widget is not 0 the wizard reparents it.
+ When the \a widget is not \nullptr the wizard reparents it.
Any previous side widget is hidden.
@@ -2963,7 +2965,7 @@ void QWizard::setDefaultProperty(const char *className, const char *property,
All widgets set here will be deleted by the wizard when it is
destroyed unless you separately reparent the widget after setting
- some other side widget (or 0).
+ some other side widget (or \nullptr).
By default, no side widget is present.
*/
@@ -2981,7 +2983,7 @@ void QWizard::setSideWidget(QWidget *widget)
/*!
\since 4.7
- Returns the widget on the left side of the wizard or 0.
+ Returns the widget on the left side of the wizard or \nullptr.
By default, no side widget is present.
*/
@@ -3257,7 +3259,11 @@ void QWizard::paintEvent(QPaintEvent * event)
/*!
\reimp
*/
+# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QWizard::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
+# else
bool QWizard::nativeEvent(const QByteArray &eventType, void *message, long *result)
+# endif
{
#if QT_CONFIG(style_windowsvista)
Q_D(QWizard);
@@ -3969,7 +3975,7 @@ void QWizardPage::registerField(const QString &name, QWidget *widget, const char
}
/*!
- Returns the wizard associated with this page, or 0 if this page
+ Returns the wizard associated with this page, or \nullptr if this page
hasn't been inserted into a QWizard yet.
\sa QWizard::addPage(), QWizard::setPage()
diff --git a/src/widgets/dialogs/qwizard.h b/src/widgets/dialogs/qwizard.h
index 0dd837b197..ef71efa0cb 100644
--- a/src/widgets/dialogs/qwizard.h
+++ b/src/widgets/dialogs/qwizard.h
@@ -188,7 +188,11 @@ protected:
void resizeEvent(QResizeEvent *event) override;
void paintEvent(QPaintEvent *event) override;
#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
+# else
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
+# endif
#endif
void done(int result) override;
virtual void initializePage(int id);
diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp
index aa9ad7f290..95f8f6a878 100644
--- a/src/widgets/dialogs/qwizard_win.cpp
+++ b/src/widgets/dialogs/qwizard_win.cpp
@@ -172,7 +172,7 @@ void QVistaHelper::updateCustomMargins(bool vistaMargins)
const QMargins customMarginsDp = vistaMargins
? QMargins(0, -titleBarSizeDp(), 0, 0)
: QMargins();
- const QVariant customMarginsV = qVariantFromValue(customMarginsDp);
+ const QVariant customMarginsV = QVariant::fromValue(customMarginsDp);
// The dynamic property takes effect when creating the platform window.
window->setProperty("_q_windowsCustomMargins", customMarginsV);
// If a platform window exists, change via native interface.
@@ -293,9 +293,9 @@ void QVistaHelper::drawTitleBar(QPainter *painter)
int glowOffset = 0;
if (vistaState() == VistaAero) {
- textHeight += 2 * glowSize();
- textWidth += 2 * glowSize();
glowOffset = glowSize();
+ textHeight += 2 * glowOffset;
+ textWidth += 2 * glowOffset;
}
const int titleLeft = (wizard->layoutDirection() == Qt::LeftToRight
@@ -339,7 +339,11 @@ void QVistaHelper::setTitleBarIconAndCaptionVisible(bool visible)
SetWindowThemeAttribute(handle, WTA_NONCLIENT, &opt, sizeof(WTA_OPTIONS));
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QVistaHelper::winEvent(MSG* msg, qintptr *result)
+#else
bool QVistaHelper::winEvent(MSG* msg, long* result)
+#endif
{
switch (msg->message) {
case WM_NCHITTEST: {
@@ -401,7 +405,11 @@ void QVistaHelper::mouseEvent(QEvent *event)
}
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QVistaHelper::handleWinEvent(MSG *message, qintptr *result)
+#else
bool QVistaHelper::handleWinEvent(MSG *message, long *result)
+#endif
{
if (message->message == WM_THEMECHANGED || message->message == WM_DWMCOMPOSITIONCHANGED)
cachedVistaState = Dirty;
@@ -509,7 +517,11 @@ bool QVistaHelper::eventFilter(QObject *obj, QEvent *event)
if (event->type() == QEvent::MouseMove) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr result;
+#else
long result;
+#endif
MSG msg;
msg.message = WM_NCHITTEST;
msg.wParam = 0;
@@ -523,7 +535,11 @@ bool QVistaHelper::eventFilter(QObject *obj, QEvent *event)
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton) {
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr result;
+#else
long result;
+#endif
MSG msg;
msg.message = WM_NCHITTEST;
msg.wParam = 0;
@@ -538,7 +554,11 @@ bool QVistaHelper::eventFilter(QObject *obj, QEvent *event)
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton) {
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ qintptr result;
+#else
long result;
+#endif
MSG msg;
msg.message = WM_NCHITTEST;
msg.wParam = 0;
diff --git a/src/widgets/dialogs/qwizard_win_p.h b/src/widgets/dialogs/qwizard_win_p.h
index d302dedaa3..b3796e3f48 100644
--- a/src/widgets/dialogs/qwizard_win_p.h
+++ b/src/widgets/dialogs/qwizard_win_p.h
@@ -84,7 +84,7 @@ class QWizard;
class QVistaHelper : public QObject
{
- Q_DISABLE_COPY(QVistaHelper)
+ Q_DISABLE_COPY_MOVE(QVistaHelper)
public:
QVistaHelper(QWizard *wizard);
~QVistaHelper() override;
@@ -93,7 +93,11 @@ public:
bool setDWMTitleBar(TitleBarChangeType type);
void setTitleBarIconAndCaptionVisible(bool visible);
void mouseEvent(QEvent *event);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool handleWinEvent(MSG *message, qintptr *result);
+#else
bool handleWinEvent(MSG *message, long *result);
+#endif
void resizeEvent(QResizeEvent *event);
void paintEvent(QPaintEvent *event);
QVistaBackButton *backButton() const { return backButton_; }
@@ -130,7 +134,11 @@ private:
void drawTitleBar(QPainter *painter);
void setMouseCursor(QPoint pos);
void collapseTopFrameStrut();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool winEvent(MSG *message, qintptr *result);
+#else
bool winEvent(MSG *message, long *result);
+#endif
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
diff --git a/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc b/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
index 9af04f6b4c..098eaf4717 100644
--- a/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
+++ b/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
@@ -514,13 +514,15 @@ QLabel { border-width: 1px 2px 3px 4px } /* 1px 2px 3px 4px */
//! [84]
-QLabel { border-color: red } /* opaque red */
-QLabel { border-color: #FF0000 } /* opaque red */
-QLabel { border-color: rgba(255, 0, 0, 75%) } /* 75% opaque red */
-QLabel { border-color: rgb(255, 0, 0) } /* opaque red */
-QLabel { border-color: rgb(100%, 0%, 0%) } /* opaque red */
-QLabel { border-color: hsv(60, 255, 255) } /* opaque yellow */
-QLabel { border-color: hsva(240, 255, 255, 75%) } /* 75% blue */
+QLabel { border-color: red } /* opaque red */
+QLabel { border-color: #FF0000 } /* opaque red */
+QLabel { border-color: rgba(255, 0, 0, 75%) } /* 75% opaque red */
+QLabel { border-color: rgb(255, 0, 0) } /* opaque red */
+QLabel { border-color: rgb(100%, 0%, 0%) } /* opaque red */
+QLabel { border-color: hsv(60, 100%, 100%) } /* opaque yellow */
+QLabel { border-color: hsva(240, 255, 255, 75%) } /* 75% blue */
+QLabel { border-color: hsl(60, 100%, 50%) } /* opaque yellow */
+QLabel { border-color: hsla(240, 255, 50%, 75%) } /* 75% blue */
//! [84]
diff --git a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp
index 06cca37111..1e9daf824b 100644
--- a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp
+++ b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp
@@ -144,3 +144,14 @@ dialog.exec();
//! [14]
"Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
//! [14]
+
+//! [14]
+auto fileOpenCompleted = [](const QSting &fileName, const QByteArray &fileContent) {
+ if (fileName.isEmpty()) {
+ // No file was selected
+ } else {
+ // Use fileName and fileContent
+ }
+}
+QFileDialog::getOpenFileContent("Images (*.png *.xpm *.jpg)", fileContentReady);
+//! [14]
diff --git a/src/widgets/doc/snippets/code/src_gui_itemviews_qdatawidgetmapper.cpp b/src/widgets/doc/snippets/code/src_gui_itemviews_qdatawidgetmapper.cpp
index 4dad563660..cc1568cb9d 100644
--- a/src/widgets/doc/snippets/code/src_gui_itemviews_qdatawidgetmapper.cpp
+++ b/src/widgets/doc/snippets/code/src_gui_itemviews_qdatawidgetmapper.cpp
@@ -59,7 +59,7 @@ mapper->toFirst();
//! [1]
-QDataWidgetMapper *mapper = new QDataWidgetMapper();
+QDataWidgetMapper *mapper = new QDataWidgetMapper;
mapper->setModel(myModel);
mapper->addMapping(nameLineEdit, 0);
mapper->addMapping(ageSpinBox, 1);
@@ -67,7 +67,7 @@ mapper->addMapping(ageSpinBox, 1);
//! [2]
-QDataWidgetMapper *mapper = new QDataWidgetMapper();
-connect(myTableView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- mapper, SLOT(setCurrentModelIndex(QModelIndex)));
+QDataWidgetMapper *mapper = new QDataWidgetMapper;
+connect(myTableView->selectionModel(), &QItemSelectionModel::currentRowChanged,
+ mapper, &QDataWidgetMapper::setCurrentModelIndex);
//! [2]
diff --git a/src/widgets/doc/snippets/code/src_gui_kernel_qapplication.cpp b/src/widgets/doc/snippets/code/src_gui_kernel_qapplication.cpp
index a907a0421f..0a70c1d32a 100644
--- a/src/widgets/doc/snippets/code/src_gui_kernel_qapplication.cpp
+++ b/src/widgets/doc/snippets/code/src_gui_kernel_qapplication.cpp
@@ -100,7 +100,8 @@ QSize MyWidget::sizeHint() const
//! [4]
void showAllHiddenTopLevelWidgets()
{
- foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ const QWidgetList topLevelWidgets = QApplication::topLevelWidgets();
+ for (QWidget *widget : topLevelWidgets) {
if (widget->isHidden())
widget->show();
}
@@ -111,7 +112,8 @@ void showAllHiddenTopLevelWidgets()
//! [5]
void updateAllWidgets()
{
- foreach (QWidget *widget, QApplication::allWidgets())
+ const QWidgetList allWidgets = QApplication::allWidgets();
+ for (QWidget *widget : allWidgets)
widget->update();
}
//! [5]
@@ -171,13 +173,15 @@ appname -session id
//! [10]
-foreach (const QString &command, mySession.restartCommand())
+const QStringList commands = mySession.restartCommand();
+for (const QString &command : commands)
do_something(command);
//! [10]
//! [11]
-foreach (const QString &command, mySession.discardCommand())
+const QStringList commands = mySession.discardCommand();
+for (const QString &command : commands)
do_something(command);
//! [11]
diff --git a/src/widgets/doc/snippets/code/src_gui_widgets_qmenu.cpp b/src/widgets/doc/snippets/code/src_gui_widgets_qmenu.cpp
index 4b1c4cd645..da3fd28056 100644
--- a/src/widgets/doc/snippets/code/src_gui_widgets_qmenu.cpp
+++ b/src/widgets/doc/snippets/code/src_gui_widgets_qmenu.cpp
@@ -81,7 +81,7 @@ exec(e->globalPos());
//! [6]
QMenu menu;
QAction *at = actions[0]; // Assumes actions is not empty
-foreach (QAction *a, actions)
+for (QAction *a : qAsConst(actions))
menu.addAction(a);
menu.exec(pos, at);
//! [6]
diff --git a/src/widgets/doc/snippets/dialogs/dialogs.cpp b/src/widgets/doc/snippets/dialogs/dialogs.cpp
index cca3ac8d75..7fa793c70f 100644
--- a/src/widgets/doc/snippets/dialogs/dialogs.cpp
+++ b/src/widgets/doc/snippets/dialogs/dialogs.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
typedef QDialog WordCountDialog;
typedef QDialog FindDialog;
@@ -76,7 +76,8 @@ void EditorWindow::find()
{
if (!findDialog) {
findDialog = new FindDialog(this);
- connect(findDialog, SIGNAL(findNext()), this, SLOT(findNext()));
+ connect(findDialog, &FindDialog::findNext,
+ this, &EditorWindow::findNext);
}
findDialog->show();
@@ -249,9 +250,9 @@ Operation::Operation(QObject *parent)
: QObject(parent), steps(0)
{
pd = new QProgressDialog("Operation in progress.", "Cancel", 0, 100);
- connect(pd, SIGNAL(canceled()), this, SLOT(cancel()));
+ connect(pd, &QProgressDialog::canceled, this, &Operation::cancel);
t = new QTimer(this);
- connect(t, SIGNAL(timeout()), this, SLOT(perform()));
+ connect(t, &QTimer::timeout, this, &Operation::perform);
t->start(0);
}
//! [4] //! [5]
diff --git a/src/widgets/doc/snippets/dockwidgets/mainwindow.cpp b/src/widgets/doc/snippets/dockwidgets/mainwindow.cpp
index f6959cc12b..53f91589bf 100644
--- a/src/widgets/doc/snippets/dockwidgets/mainwindow.cpp
+++ b/src/widgets/doc/snippets/dockwidgets/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
@@ -63,8 +63,8 @@ MainWindow::MainWindow(QWidget *parent)
textBrowser = new QTextBrowser(this);
- connect(headingList, SIGNAL(itemClicked(QListWidgetItem*)),
- this, SLOT(updateText(QListWidgetItem*)));
+ connect(headingList, &QListWidget::itemClicked,
+ this, &MainWindow::updateText);
updateText(headingList->item(0));
headingList->setCurrentRow(0);
@@ -119,7 +119,7 @@ void MainWindow::setupMenus()
QAction *exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcut(tr("Ctrl+Q"));
exitAct->setStatusTip(tr("Exit the application"));
- connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
+ connect(exitAct, &QAction::triggered, qApp, &QApplication::closeAllWindows);
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(exitAct);
diff --git a/src/widgets/doc/snippets/mdiareasnippets.cpp b/src/widgets/doc/snippets/mdiareasnippets.cpp
index b9d6f05daf..dec7aaa1e7 100644
--- a/src/widgets/doc/snippets/mdiareasnippets.cpp
+++ b/src/widgets/doc/snippets/mdiareasnippets.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
void mainWindowExample()
{
@@ -95,7 +95,7 @@ int main(int argv, char **args)
QAction *act = new QAction(qApp);
act->setShortcut(Qt::ALT + Qt::Key_S);
act->setShortcutContext( Qt::ApplicationShortcut );
- QObject::connect(act, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ QObject::connect(act, &QAction::triggered, qApp, &QApplication::aboutQt);
QWidget widget5;
widget5.show();
diff --git a/src/widgets/doc/snippets/qlistview-dnd/mainwindow.cpp b/src/widgets/doc/snippets/qlistview-dnd/mainwindow.cpp
index c2af9c4cf1..45f1eb7aa3 100644
--- a/src/widgets/doc/snippets/qlistview-dnd/mainwindow.cpp
+++ b/src/widgets/doc/snippets/qlistview-dnd/mainwindow.cpp
@@ -73,7 +73,8 @@ listView->setDropIndicatorShown(true);
this->listView = listView;
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
+ connect(quitAction, &QAction::triggered,
+ this, &QWidget::close);
setupListItems();
diff --git a/src/widgets/doc/snippets/qlistview-dnd/model.cpp b/src/widgets/doc/snippets/qlistview-dnd/model.cpp
index 710bbb2964..6835479e7a 100644
--- a/src/widgets/doc/snippets/qlistview-dnd/model.cpp
+++ b/src/widgets/doc/snippets/qlistview-dnd/model.cpp
@@ -54,7 +54,7 @@
A simple model that uses a QStringList as its data source.
*/
-#include <QtGui>
+#include <QtWidgets>
#include "model.h"
@@ -121,7 +121,7 @@ bool DragDropListModel::dropMimeData(const QMimeData *data,
//! [6]
insertRows(beginRow, rows, QModelIndex());
- foreach (const QString &text, newItems) {
+ for (const QString &text : qAsConst(newItems)) {
QModelIndex idx = index(beginRow, 0, QModelIndex());
setData(idx, text);
beginRow++;
@@ -146,12 +146,12 @@ Qt::ItemFlags DragDropListModel::flags(const QModelIndex &index) const
//! [8]
QMimeData *DragDropListModel::mimeData(const QModelIndexList &indexes) const
{
- QMimeData *mimeData = new QMimeData();
+ QMimeData *mimeData = new QMimeData;
QByteArray encodedData;
QDataStream stream(&encodedData, QIODevice::WriteOnly);
- foreach (const QModelIndex &index, indexes) {
+ for (const QModelIndex &index : indexes) {
if (index.isValid()) {
QString text = data(index, Qt::DisplayRole).toString();
stream << text;
diff --git a/src/widgets/doc/snippets/qlistwidget-dnd/mainwindow.cpp b/src/widgets/doc/snippets/qlistwidget-dnd/mainwindow.cpp
index 1153250b17..70df2b112e 100644
--- a/src/widgets/doc/snippets/qlistwidget-dnd/mainwindow.cpp
+++ b/src/widgets/doc/snippets/qlistwidget-dnd/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
@@ -74,7 +74,7 @@ listWidget->setDragDropMode(QAbstractItemView::InternalMove);
this->listWidget = listWidget;
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
+ connect(quitAction, &QAction::triggered, this, &QWidget::close);
setupListItems();
diff --git a/src/widgets/doc/snippets/qlistwidget-using/mainwindow.cpp b/src/widgets/doc/snippets/qlistwidget-using/mainwindow.cpp
index ff69fd2efd..13b20bb856 100644
--- a/src/widgets/doc/snippets/qlistwidget-using/mainwindow.cpp
+++ b/src/widgets/doc/snippets/qlistwidget-using/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
@@ -77,14 +77,13 @@ MainWindow::MainWindow()
listWidget = new QListWidget(this);
listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
- connect(ascendingAction, SIGNAL(triggered()), this, SLOT(sortAscending()));
- connect(descendingAction, SIGNAL(triggered()), this, SLOT(sortDescending()));
- connect(insertAction, SIGNAL(triggered()), this, SLOT(insertItem()));
- connect(removeAction, SIGNAL(triggered()), this, SLOT(removeItem()));
- connect(listWidget,
- SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
- this, SLOT(updateMenus(QListWidgetItem*)));
+ connect(quitAction, &QAction::triggered, this, &QWidget::close);
+ connect(ascendingAction, &QAction::triggered, this, &MainWindow::sortAscending);
+ connect(descendingAction, &QAction::triggered, this, &MainWindow::sortDescending);
+ connect(insertAction, &QAction::triggered, this, &MainWindow::insertItem);
+ connect(removeAction, &QAction::triggered, this, &MainWindow::removeItem);
+ connect(listWidget, &QListWidget::currentItemChanged,
+ this, &MainWindow::updateMenus);
setupListItems();
updateMenus(listWidget->currentItem());
diff --git a/src/widgets/doc/snippets/qsortfilterproxymodel/main.cpp b/src/widgets/doc/snippets/qsortfilterproxymodel/main.cpp
index a6284bd578..2d4b1023f1 100644
--- a/src/widgets/doc/snippets/qsortfilterproxymodel/main.cpp
+++ b/src/widgets/doc/snippets/qsortfilterproxymodel/main.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
int main(int argc, char *argv[])
{
@@ -74,9 +74,8 @@ int main(int argc, char *argv[])
filteredView->setWindowTitle("Filtered view onto a string list model");
QLineEdit *patternEditor = new QLineEdit;
- QObject::
- connect(patternEditor, SIGNAL(textChanged(QString)),
- filterModel, SLOT(setFilterRegExp(QString)));
+ QObject::connect(patternEditor, &QLineEdit::textChanged,
+ filterModel, &QSortFilterProxyModel::setFilterWildcard);
QVBoxLayout *layout = new QVBoxLayout(window);
layout->addWidget(filteredView);
diff --git a/src/widgets/doc/snippets/qstackedlayout/main.cpp b/src/widgets/doc/snippets/qstackedlayout/main.cpp
index 765608848c..9c61939dee 100644
--- a/src/widgets/doc/snippets/qstackedlayout/main.cpp
+++ b/src/widgets/doc/snippets/qstackedlayout/main.cpp
@@ -48,13 +48,12 @@
**
****************************************************************************/
-#include <QtGui>
-#include <QApplication>
+#include <QtWidgets>
class Widget : public QWidget
{
public:
- Widget(QWidget *parent = 0);
+ Widget(QWidget *parent = nullptr);
};
Widget::Widget(QWidget *parent)
@@ -75,8 +74,8 @@ Widget::Widget(QWidget *parent)
pageComboBox->addItem(tr("Page 1"));
pageComboBox->addItem(tr("Page 2"));
pageComboBox->addItem(tr("Page 3"));
- connect(pageComboBox, SIGNAL(activated(int)),
- stackedLayout, SLOT(setCurrentIndex(int)));
+ connect(pageComboBox, QOverload<int>::of(&QComboBox::activated),
+ stackedLayout, &QStackedLayout::setCurrentIndex);
//! [1]
//! [2]
diff --git a/src/widgets/doc/snippets/qstackedwidget/main.cpp b/src/widgets/doc/snippets/qstackedwidget/main.cpp
index a6c9c7afe3..077c281830 100644
--- a/src/widgets/doc/snippets/qstackedwidget/main.cpp
+++ b/src/widgets/doc/snippets/qstackedwidget/main.cpp
@@ -48,8 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
-#include <QApplication>
+#include <QtWidgets>
class Widget : public QWidget
{
@@ -75,8 +74,8 @@ Widget::Widget(QWidget *parent)
pageComboBox->addItem(tr("Page 1"));
pageComboBox->addItem(tr("Page 2"));
pageComboBox->addItem(tr("Page 3"));
- connect(pageComboBox, SIGNAL(activated(int)),
- stackedWidget, SLOT(setCurrentIndex(int)));
+ connect(pageComboBox, QOverload<int>::of(&QComboBox::activated),
+ stackedWidget, &QStackedWidget::setCurrentIndex);
//! [1] //! [2]
QVBoxLayout *layout = new QVBoxLayout;
diff --git a/src/widgets/doc/snippets/qtablewidget-resizing/mainwindow.cpp b/src/widgets/doc/snippets/qtablewidget-resizing/mainwindow.cpp
index 95113153e1..d2c50336f6 100644
--- a/src/widgets/doc/snippets/qtablewidget-resizing/mainwindow.cpp
+++ b/src/widgets/doc/snippets/qtablewidget-resizing/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
@@ -72,9 +72,9 @@ MainWindow::MainWindow()
//! [0]
tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
- connect(tableWidthAction, SIGNAL(triggered()), this, SLOT(changeWidth()));
- connect(tableHeightAction, SIGNAL(triggered()), this, SLOT(changeHeight()));
+ connect(quitAction, &QAction::triggered, this, &QWidget::close);
+ connect(tableWidthAction, &QAction::triggered, this, &MainWindow::changeWidth);
+ connect(tableHeightAction, &QAction::triggered, this, &MainWindow::changeHeight);
setupTableItems();
diff --git a/src/widgets/doc/snippets/qtablewidget-using/mainwindow.cpp b/src/widgets/doc/snippets/qtablewidget-using/mainwindow.cpp
index 15b9457dd5..47b63b2b3f 100644
--- a/src/widgets/doc/snippets/qtablewidget-using/mainwindow.cpp
+++ b/src/widgets/doc/snippets/qtablewidget-using/mainwindow.cpp
@@ -48,8 +48,8 @@
**
****************************************************************************/
-#include <QtGui>
-#include "math.h"
+#include <QtWidgets>
+#include <math.h>
#include "mainwindow.h"
@@ -89,9 +89,9 @@ MainWindow::MainWindow()
tableWidget->setHorizontalHeaderItem(1, squaresHeaderItem);
tableWidget->setHorizontalHeaderItem(2, cubesHeaderItem);
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
- connect(sumItemsAction, SIGNAL(triggered()), this, SLOT(sumItems()));
- connect(averageItemsAction, SIGNAL(triggered()), this, SLOT(averageItems()));
+ connect(quitAction, &QAction::triggered, this, &QWidget::close);
+ connect(sumItemsAction, &QAction::triggered, this, &MainWindow::sumItems);
+ connect(averageItemsAction, &QAction::triggered, this, &MainWindow::averageItems);
setupTableItems();
@@ -119,12 +119,11 @@ void MainWindow::setupTableItems()
void MainWindow::averageItems()
{
- QList<QTableWidgetItem *> selected = tableWidget->selectedItems();
- QTableWidgetItem *item;
+ const QList<QTableWidgetItem *> selected = tableWidget->selectedItems();
int number = 0;
double total = 0;
- foreach (item, selected) {
+ for (QTableWidgetItem *item : selected) {
bool ok;
double value = item->text().toDouble(&ok);
@@ -140,12 +139,11 @@ void MainWindow::averageItems()
void MainWindow::sumItems()
{
//! [4]
- QList<QTableWidgetItem *> selected = tableWidget->selectedItems();
- QTableWidgetItem *item;
+ const QList<QTableWidgetItem *> selected = tableWidget->selectedItems();
int number = 0;
double total = 0;
- foreach (item, selected) {
+ for (QTableWidgetItem *item : selected) {
bool ok;
double value = item->text().toDouble(&ok);
diff --git a/src/widgets/doc/snippets/qtreewidget-using/mainwindow.cpp b/src/widgets/doc/snippets/qtreewidget-using/mainwindow.cpp
index ee7e028a13..b9e258cb03 100644
--- a/src/widgets/doc/snippets/qtreewidget-using/mainwindow.cpp
+++ b/src/widgets/doc/snippets/qtreewidget-using/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
@@ -90,16 +90,15 @@ MainWindow::MainWindow()
treeWidget->setHeaderLabels(headers);
//! [2]
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
- connect(ascendingAction, SIGNAL(triggered()), this, SLOT(sortAscending()));
- connect(autoSortAction, SIGNAL(triggered()), this, SLOT(updateSortItems()));
- connect(descendingAction, SIGNAL(triggered()), this, SLOT(sortDescending()));
- connect(findItemsAction, SIGNAL(triggered()), this, SLOT(findItems()));
- connect(insertAction, SIGNAL(triggered()), this, SLOT(insertItem()));
- connect(removeAction, SIGNAL(triggered()), this, SLOT(removeItem()));
- connect(treeWidget,
- SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
- this, SLOT(updateMenus(QTreeWidgetItem*)));
+ connect(quitAction, &QAction::triggered, this, &QWidget::close);
+ connect(ascendingAction, &QAction::triggered, this, &MainWindow::sortAscending);
+ connect(autoSortAction, &QAction::triggered, this, &MainWindow::updateSortItems);
+ connect(descendingAction, &QAction::triggered, this, &MainWindow::sortDescending);
+ connect(findItemsAction, &QAction::triggered, this, &MainWindow::findItems);
+ connect(insertAction, &QAction::triggered, this, &MainWindow::insertItem);
+ connect(removeAction, &QAction::triggered, this, &MainWindow::removeItem);
+ connect(treeWidget, &QTreeWidget::currentItemChanged,
+ this, &MainWindow::updateMenus);
setupTreeItems();
updateMenus(treeWidget->currentItem());
@@ -150,18 +149,16 @@ void MainWindow::findItems()
if (itemText.isEmpty())
return;
-//! [6]
- QTreeWidgetItem *item;
-//! [6]
- foreach (item, treeWidget->selectedItems())
- treeWidget->setItemSelected(item, false);
+ const QList<QTreeWidgetItem *> items = treeWidget->selectedItems();
+ for (QTreeWidgetItem *item : items)
+ item->setSelected(false);
//! [7]
- QList<QTreeWidgetItem *> found = treeWidget->findItems(
+ const QList<QTreeWidgetItem *> found = treeWidget->findItems(
itemText, Qt::MatchWildcard);
- foreach (item, found) {
- treeWidget->setItemSelected(item, true);
+ for (QTreeWidgetItem *item : found) {
+ item->setSelected(true);
// Show the item->text(0) for each item.
}
//! [7]
diff --git a/src/widgets/doc/snippets/qtreewidgetitemiterator-using/mainwindow.cpp b/src/widgets/doc/snippets/qtreewidgetitemiterator-using/mainwindow.cpp
index 5f1f606185..bfe099bbb4 100644
--- a/src/widgets/doc/snippets/qtreewidgetitemiterator-using/mainwindow.cpp
+++ b/src/widgets/doc/snippets/qtreewidgetitemiterator-using/mainwindow.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include "mainwindow.h"
@@ -85,16 +85,15 @@ MainWindow::MainWindow()
headers << tr("Subject") << tr("Default");
treeWidget->setHeaderLabels(headers);
- connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
- connect(ascendingAction, SIGNAL(triggered()), this, SLOT(sortAscending()));
- connect(autoSortAction, SIGNAL(triggered()), this, SLOT(updateSortItems()));
- connect(descendingAction, SIGNAL(triggered()), this, SLOT(sortDescending()));
- connect(findItemsAction, SIGNAL(triggered()), this, SLOT(findItems()));
- connect(insertAction, SIGNAL(triggered()), this, SLOT(insertItem()));
- connect(removeAction, SIGNAL(triggered()), this, SLOT(removeItem()));
- connect(treeWidget,
- SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
- this, SLOT(updateMenus(QTreeWidgetItem*)));
+ connect(quitAction, &QAction::triggered, this, &QWidget::close);
+ connect(ascendingAction, &QAction::triggered, this, &MainWindow::sortAscending);
+ connect(autoSortAction, &QAction::triggered, this, &MainWindow::updateSortItems);
+ connect(descendingAction, &QAction::triggered, this, &MainWindow::sortDescending);
+ connect(findItemsAction, &QAction::triggered, this, &MainWindow::findItems);
+ connect(insertAction, &QAction::triggered, this, &MainWindow::insertItem);
+ connect(removeAction, &QAction::triggered, this, &MainWindow::removeItem);
+ connect(treeWidget, &QTreeWidget::currentItemChanged,
+ this, &MainWindow::updateMenus);
setupTreeItems();
updateMenus(treeWidget->currentItem());
diff --git a/src/widgets/doc/snippets/reading-selections/window.cpp b/src/widgets/doc/snippets/reading-selections/window.cpp
index 08805fe4b3..045d66a199 100644
--- a/src/widgets/doc/snippets/reading-selections/window.cpp
+++ b/src/widgets/doc/snippets/reading-selections/window.cpp
@@ -81,9 +81,9 @@ MainWindow::MainWindow(QWidget *parent)
QAction *selectAllAction = actionMenu->addAction(tr("&Select All"));
menuBar()->addMenu(actionMenu);
- connect(fillAction, SIGNAL(triggered()), this, SLOT(fillSelection()));
- connect(clearAction, SIGNAL(triggered()), this, SLOT(clearSelection()));
- connect(selectAllAction, SIGNAL(triggered()), this, SLOT(selectAll()));
+ connect(fillAction, &QAction::triggered, this, &MainWindow::fillSelection);
+ connect(clearAction, &QAction::triggered, this, &MainWindow::clearSelection);
+ connect(selectAllAction, &QAction::triggered, this, &MainWindow::selectAll);
selectionModel = table->selectionModel();
@@ -94,10 +94,9 @@ MainWindow::MainWindow(QWidget *parent)
void MainWindow::fillSelection()
{
//! [0]
- QModelIndexList indexes = selectionModel->selectedIndexes();
- QModelIndex index;
+ const QModelIndexList indexes = selectionModel->selectedIndexes();
- foreach(index, indexes) {
+ for (const QModelIndex &index : indexes) {
QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());
model->setData(index, text);
}
@@ -106,11 +105,10 @@ void MainWindow::fillSelection()
void MainWindow::clearSelection()
{
- QModelIndexList indexes = selectionModel->selectedIndexes();
- QModelIndex index;
+ const QModelIndexList indexes = selectionModel->selectedIndexes();
- foreach(index, indexes)
- model->setData(index, "");
+ for (const QModelIndex &index : indexes)
+ model->setData(index, QString());
}
void MainWindow::selectAll()
diff --git a/src/widgets/doc/snippets/timeline/main.cpp b/src/widgets/doc/snippets/timeline/main.cpp
index 74aa749254..4dfa2400d0 100644
--- a/src/widgets/doc/snippets/timeline/main.cpp
+++ b/src/widgets/doc/snippets/timeline/main.cpp
@@ -48,7 +48,7 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
#include <math.h>
int main(int argv, char *args[])
@@ -68,7 +68,7 @@ int main(int argv, char *args[])
for (int i = 0; i < 200; ++i)
animation->setPosAt(i / 200.0, QPointF(i, i));
- QGraphicsScene *scene = new QGraphicsScene();
+ QGraphicsScene *scene = new QGraphicsScene;
scene->setSceneRect(0, 0, 250, 250);
scene->addItem(ball);
diff --git a/src/widgets/doc/snippets/updating-selections/window.cpp b/src/widgets/doc/snippets/updating-selections/window.cpp
index 0bdcf8a64d..26e9b56ae4 100644
--- a/src/widgets/doc/snippets/updating-selections/window.cpp
+++ b/src/widgets/doc/snippets/updating-selections/window.cpp
@@ -74,12 +74,10 @@ MainWindow::MainWindow(QWidget *parent)
table->setModel(model);
selectionModel = table->selectionModel();
- connect(selectionModel,
- SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
- this, SLOT(updateSelection(QItemSelection,QItemSelection)));
- connect(selectionModel,
- SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(changeCurrent(QModelIndex,QModelIndex)));
+ connect(selectionModel, &QItemSelectionModel::selectionChanged,
+ this, &MainWindow::updateSelection);
+ connect(selectionModel, &QItemSelectionModel::currentChanged,
+ this, &MainWindow::changeCurrent);
statusBar();
setCentralWidget(table);
@@ -89,10 +87,9 @@ MainWindow::MainWindow(QWidget *parent)
void MainWindow::updateSelection(const QItemSelection &selected,
const QItemSelection &deselected)
{
- QModelIndex index;
QModelIndexList items = selected.indexes();
- foreach (index, items) {
+ for (const QModelIndex &index : qAsConst(items)) {
QString text = QString("(%1,%2)").arg(index.row()).arg(index.column());
model->setData(index, text);
//! [0] //! [1]
@@ -102,8 +99,8 @@ void MainWindow::updateSelection(const QItemSelection &selected,
//! [2]
items = deselected.indexes();
- foreach (index, items)
- model->setData(index, "");
+ for (const QModelIndex &index : qAsConst(items)) {
+ model->setData(index, QString());
}
//! [2]
diff --git a/src/widgets/doc/src/dontdocument.qdoc b/src/widgets/doc/src/dontdocument.qdoc
new file mode 100644
index 0000000000..9de8b5e62d
--- /dev/null
+++ b/src/widgets/doc/src/dontdocument.qdoc
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+/*!
+ \dontdocument (QTypeInfo QMetaTypeId)
+*/
diff --git a/src/widgets/doc/src/model-view-programming.qdoc b/src/widgets/doc/src/model-view-programming.qdoc
index f6b7c80656..9335ff78c9 100644
--- a/src/widgets/doc/src/model-view-programming.qdoc
+++ b/src/widgets/doc/src/model-view-programming.qdoc
@@ -693,9 +693,9 @@
\l QAbstractItemDelegate class.
Delegates are expected to be able to render their contents themselves
- by implementing the \l{QItemDelegate::paint()}{paint()}
- and \l{QItemDelegate::sizeHint()}{sizeHint()} functions.
- However, simple widget-based delegates can subclass \l QItemDelegate
+ by implementing the \l{QStyledItemDelegate::paint()}{paint()}
+ and \l{QStyledItemDelegate::sizeHint()}{sizeHint()} functions.
+ However, simple widget-based delegates can subclass \l QStyledItemDelegate
instead of \l QAbstractItemDelegate, and take advantage of the default
implementations of these functions.
@@ -709,14 +709,14 @@
\section2 Using an existing delegate
- The standard views provided with Qt use instances of \l QItemDelegate
+ The standard views provided with Qt use instances of \l QStyledItemDelegate
to provide editing facilities. This default implementation of the
delegate interface renders items in the usual style for each of the
standard views: \l QListView, \l QTableView, and \l QTreeView.
All the standard roles are handled by the default delegate used by
the standard views. The way these are interpreted is described in the
- QItemDelegate documentation.
+ QStyledItemDelegate documentation.
The delegate used by a view is returned by the
\l{QAbstractItemView::itemDelegate()}{itemDelegate()} function.
@@ -799,7 +799,7 @@
In this case, we ensure that the spin box is up-to-date, and update
the model with the value it contains using the index specified.
- The standard \l QItemDelegate class informs the view when it has
+ The standard \l QStyledItemDelegate class informs the view when it has
finished editing by emitting the
\l{QAbstractItemDelegate::closeEditor()}{closeEditor()} signal.
The view ensures that the editor widget is closed and destroyed. In
@@ -838,11 +838,11 @@
assist any subsequent editing operations. This is achieved by
emitting the \l{QAbstractItemDelegate::closeEditor()}{closeEditor()}
signal with a suitable hint. This is taken care of by the default
- QItemDelegate event filter which we installed on the spin box when
+ QStyledItemDelegate event filter which we installed on the spin box when
it was constructed.
The behavior of the spin box could be adjusted to make it more user
- friendly. In the default event filter supplied by QItemDelegate, if
+ friendly. In the default event filter supplied by QStyledItemDelegate, if
the user hits \uicontrol Return to confirm their choice in the spin box,
the delegate commits the value to the model and closes the spin box.
We can change this behavior by installing our own event filter on the
@@ -1003,8 +1003,8 @@
\snippet reading-selections/window.cpp 0
- The above code uses Qt's convenient \l{Container Classes}{foreach
- keyword} to iterate over, and modify, the items corresponding to the
+ The above code uses a range-based for-loop to iterate over,
+ and modify, the items corresponding to the
indexes returned by the selection model.
The selection model emits signals to indicate changes in the
@@ -1611,7 +1611,6 @@
We can obtain a list of matching items with the \c findItems()
function:
- \snippet qtreewidget-using/mainwindow.cpp 6
\snippet qtreewidget-using/mainwindow.cpp 7
The above code causes items in a tree widget to be selected if they
diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
index 43f9dda49a..00323eace6 100644
--- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
@@ -2881,14 +2881,20 @@
| \tt{rgba(\e{r}, \e{g}, \e{b}, \e{a})} \br
| \tt{hsv(\e{h}, \e{s}, \e{v})} \br
| \tt{hsva(\e{h}, \e{s}, \e{v}, \e{a})} \br
+ | \tt{hsl(\e{h}, \e{s}, \e{l})} \br
+ | \tt{hsla(\e{h}, \e{s}, \e{l}, \e{a})} \br
| \tt{#\e{rrggbb}} \br
| \l{QColor::setNamedColor()}{Color Name} \br
- \li Specifies a color as RGB (red, green, blue) or RGBA
- (red, green, blue, alpha) or HSV (hue, saturation, value) or HSVA
- (hue, saturation, value, alpha) or a named color. The \c rgb() or \c rgba()
- syntax can be used with integer values between 0 and 255, or with
- percentages. The value of s, v, and a in \c hsv() or \c hsva() must all
- be in the range 0-255; the value of h must be in the range 0-359.
+ \li Specifies a color as RGB (red, green, blue), RGBA (red,
+ green, blue, alpha), HSV (hue, saturation, value), HSVA
+ (hue, saturation, value, alpha), HSL (hue, saturation,
+ lightness), HSLA (hue, saturation, lightness, alpha) or a
+ named color. The \c rgb() or \c rgba() syntax can be used
+ with integer values between 0 and 255, or with percentages.
+ The value of s, v, l and a in \c hsv(), \c hsva() \c hsl()
+ or \c hsla() must all be in the range 0-255 or with
+ percentages, the value of h must be in the range 0-359.
+ The support for HSL(A) is available since 5.13.
Examples:
diff --git a/src/widgets/effects/qgraphicseffect_p.h b/src/widgets/effects/qgraphicseffect_p.h
index c5c7ff5900..7e342a9f3c 100644
--- a/src/widgets/effects/qgraphicseffect_p.h
+++ b/src/widgets/effects/qgraphicseffect_p.h
@@ -80,15 +80,15 @@ public:
QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const;
QRect deviceRect() const;
QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates,
- QPoint *offset = 0,
+ QPoint *offset = nullptr,
QGraphicsEffect::PixmapPadMode mode = QGraphicsEffect::PadToEffectiveBoundingRect) const;
protected:
- QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0);
+ QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = nullptr);
private:
Q_DECLARE_PRIVATE(QGraphicsEffectSource)
- Q_DISABLE_COPY(QGraphicsEffectSource)
+ Q_DISABLE_COPY_MOVE(QGraphicsEffectSource)
friend class QGraphicsEffect;
friend class QGraphicsEffectPrivate;
friend class QGraphicsScenePrivate;
@@ -125,7 +125,7 @@ public:
virtual void draw(QPainter *p) = 0;
virtual void update() = 0;
virtual bool isPixmap() const = 0;
- virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0,
+ virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = nullptr,
QGraphicsEffect::PixmapPadMode mode = QGraphicsEffect::PadToTransparentBorder) const = 0;
virtual void effectBoundingRectChanged() = 0;
@@ -149,7 +149,7 @@ class Q_WIDGETS_EXPORT QGraphicsEffectPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QGraphicsEffect)
public:
- QGraphicsEffectPrivate() : source(0), isEnabled(1) {}
+ QGraphicsEffectPrivate() : source(nullptr), isEnabled(1) {}
~QGraphicsEffectPrivate();
inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource)
diff --git a/src/widgets/effects/qpixmapfilter.cpp b/src/widgets/effects/qpixmapfilter.cpp
index 60edd01d00..e1e8175423 100644
--- a/src/widgets/effects/qpixmapfilter.cpp
+++ b/src/widgets/effects/qpixmapfilter.cpp
@@ -54,6 +54,8 @@
#include "private/qmemrotate_p.h"
#include "private/qdrawhelper_p.h"
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QPixmapFilterPrivate : public QObjectPrivate
@@ -319,7 +321,7 @@ static void convolute(
const QImage processImage = (srcImage.format() != QImage::Format_ARGB32_Premultiplied ) ? srcImage.convertToFormat(QImage::Format_ARGB32_Premultiplied) : srcImage;
// TODO: support also other formats directly without copying
- int *fixedKernel = new int[kernelWidth*kernelHeight];
+ std::unique_ptr<int[]> fixedKernel(new int[kernelWidth * kernelHeight]);
for(int i = 0; i < kernelWidth*kernelHeight; i++)
{
fixedKernel[i] = (int)(65536 * kernel[i]);
@@ -403,7 +405,6 @@ static void convolute(
}
yk++;
}
- delete[] fixedKernel;
}
/*!
diff --git a/src/widgets/effects/qpixmapfilter_p.h b/src/widgets/effects/qpixmapfilter_p.h
index 0f582bde60..c56acb8a24 100644
--- a/src/widgets/effects/qpixmapfilter_p.h
+++ b/src/widgets/effects/qpixmapfilter_p.h
@@ -100,7 +100,7 @@ class Q_WIDGETS_EXPORT QPixmapConvolutionFilter : public QPixmapFilter
Q_DECLARE_PRIVATE(QPixmapConvolutionFilter)
public:
- QPixmapConvolutionFilter(QObject *parent = 0);
+ QPixmapConvolutionFilter(QObject *parent = nullptr);
~QPixmapConvolutionFilter();
void setConvolutionKernel(const qreal *matrix, int rows, int columns);
@@ -124,7 +124,7 @@ class Q_WIDGETS_EXPORT QPixmapBlurFilter : public QPixmapFilter
Q_DECLARE_PRIVATE(QPixmapBlurFilter)
public:
- QPixmapBlurFilter(QObject *parent = 0);
+ QPixmapBlurFilter(QObject *parent = nullptr);
~QPixmapBlurFilter();
void setRadius(qreal radius);
@@ -148,7 +148,7 @@ class Q_WIDGETS_EXPORT QPixmapColorizeFilter : public QPixmapFilter
Q_DECLARE_PRIVATE(QPixmapColorizeFilter)
public:
- QPixmapColorizeFilter(QObject *parent = 0);
+ QPixmapColorizeFilter(QObject *parent = nullptr);
~QPixmapColorizeFilter();
void setColor(const QColor& color);
@@ -168,7 +168,7 @@ class Q_WIDGETS_EXPORT QPixmapDropShadowFilter : public QPixmapFilter
Q_DECLARE_PRIVATE(QPixmapDropShadowFilter)
public:
- QPixmapDropShadowFilter(QObject *parent = 0);
+ QPixmapDropShadowFilter(QObject *parent = nullptr);
~QPixmapDropShadowFilter();
QRectF boundingRectFor(const QRectF &rect) const override;
diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
index 008560d856..4f44373cad 100644
--- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -2066,7 +2066,7 @@ QList<AnchorData *> getVariables(const QList<QSimplexConstraint *> &constraints)
for (auto it = c->variables.cbegin(), end = c->variables.cend(); it != end; ++it)
variableSet.insert(static_cast<AnchorData *>(it.key()));
}
- return variableSet.toList();
+ return variableSet.values();
}
/*!
diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h
index 699ca32bfe..b5f14948ac 100644
--- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h
+++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h
@@ -89,7 +89,7 @@ struct AnchorVertex {
: m_item(item), m_edge(edge), m_type(Normal) {}
AnchorVertex()
- : m_item(0), m_edge(Qt::AnchorPoint(0)), m_type(Normal) {}
+ : m_item(nullptr), m_edge(Qt::AnchorPoint(0)), m_type(Normal) {}
#ifdef QT_DEBUG
inline QString toString() const;
@@ -123,18 +123,18 @@ struct AnchorData : public QSimplexVariable {
};
AnchorData()
- : QSimplexVariable(), from(0), to(0),
+ : QSimplexVariable(), from(nullptr), to(nullptr),
minSize(0), prefSize(0), maxSize(0),
minPrefSize(0), maxPrefSize(0),
sizeAtMinimum(0), sizeAtPreferred(0),
- sizeAtMaximum(0), item(0), graphicsAnchor(0),
+ sizeAtMaximum(0), item(nullptr), graphicsAnchor(nullptr),
type(Normal), isLayoutAnchor(false),
isCenterAnchor(false), orientation(0),
dependency(Independent) {}
virtual ~AnchorData();
virtual void updateChildrenSizes() {}
- void refreshSizeHints(const QLayoutStyleInfo *styleInfo = 0);
+ void refreshSizeHints(const QLayoutStyleInfo *styleInfo = nullptr);
#ifdef QT_DEBUG
void dump(int indent = 2);
@@ -402,7 +402,7 @@ public:
static QGraphicsAnchorLayoutPrivate *get(QGraphicsAnchorLayout *q)
{
- return q ? q->d_func() : 0;
+ return q ? q->d_func() : nullptr;
}
static Qt::AnchorPoint oppositeEdge(
@@ -443,7 +443,7 @@ public:
Qt::AnchorPoint firstEdge,
QGraphicsLayoutItem *secondItem,
Qt::AnchorPoint secondEdge,
- qreal *spacing = 0);
+ qreal *spacing = nullptr);
// Helper for Anchor Manipulation methods
void addAnchor_helper(QGraphicsLayoutItem *firstItem,
diff --git a/src/widgets/graphicsview/qgraphicsgridlayout.cpp b/src/widgets/graphicsview/qgraphicsgridlayout.cpp
index d9005afbef..6b7052a0ab 100644
--- a/src/widgets/graphicsview/qgraphicsgridlayout.cpp
+++ b/src/widgets/graphicsview/qgraphicsgridlayout.cpp
@@ -552,20 +552,19 @@ int QGraphicsGridLayout::count() const
}
/*!
- Returns the layout item at \a index, or 0 if there is no layout item at
- this index.
+ Returns the layout item at \a index, or \nullptr if there is no
+ layout item at this index.
*/
QGraphicsLayoutItem *QGraphicsGridLayout::itemAt(int index) const
{
Q_D(const QGraphicsGridLayout);
if (index < 0 || index >= d->engine.itemCount()) {
qWarning("QGraphicsGridLayout::itemAt: invalid index %d", index);
- return 0;
+ return nullptr;
}
- QGraphicsLayoutItem *item = 0;
if (QGraphicsGridLayoutEngineItem *engineItem = static_cast<QGraphicsGridLayoutEngineItem*>(d->engine.itemAt(index)))
- item = engineItem->layoutItem();
- return item;
+ return engineItem->layoutItem();
+ return nullptr;
}
/*!
diff --git a/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h b/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h
index 370df9eed7..e98160e40f 100644
--- a/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h
+++ b/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h
@@ -68,7 +68,7 @@ class QGraphicsLayoutPrivate;
class QGraphicsGridLayoutEngineItem : public QGridLayoutItem {
public:
QGraphicsGridLayoutEngineItem(QGraphicsLayoutItem *item, int row, int columns, int rowSpan = 1, int columnSpan = 1,
- Qt::Alignment alignment = 0)
+ Qt::Alignment alignment = nullptr)
: QGridLayoutItem(row, columns, rowSpan, columnSpan, alignment), q_layoutItem(item) {}
virtual QLayoutPolicy::Policy sizePolicy(Qt::Orientation orientation) const override
@@ -115,7 +115,7 @@ public:
{
const int index = indexOf(layoutItem);
if (index < 0)
- return 0;
+ return nullptr;
return static_cast<QGraphicsGridLayoutEngineItem*>(q_items.at(index));
}
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index dbce80b125..65708fa1ca 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -661,9 +661,9 @@
\value ItemSceneChange The item is moved to a new scene. This notification is
also sent when the item is added to its initial scene, and when it is removed.
- The item's scene() is the old scene (or 0 if the item has not been added to a
- scene yet). The value argument is the new scene (i.e., a QGraphicsScene
- pointer), or a null pointer if the item is removed from a scene. Do not
+ The item's scene() is the old scene, or \nullptr if the item has not been added
+ to a scene yet. The value argument is the new scene (i.e., a QGraphicsScene
+ pointer), or \nullptr if the item is removed from a scene. Do not
override this change by passing this item to QGraphicsScene::addItem() as this
notification is delivered; instead, you can return the new scene from
itemChange(). Use this feature with caution; objecting to a scene change can
@@ -1542,7 +1542,7 @@ void QGraphicsItemCache::purge()
Constructs a QGraphicsItem with the given \a parent item.
It does not modify the parent object returned by QObject::parent().
- If \a parent is 0, you can add the item to a scene by calling
+ If \a parent is \nullptr, you can add the item to a scene by calling
QGraphicsScene::addItem(). The item will then become a top-level item.
\sa QGraphicsScene::addItem(), setParentItem()
@@ -1650,8 +1650,8 @@ QGraphicsItem::~QGraphicsItem()
}
/*!
- Returns the current scene for the item, or 0 if the item is not stored in
- a scene.
+ Returns the current scene for the item, or \nullptr if the item is
+ not stored in a scene.
To add or move an item to a scene, call QGraphicsScene::addItem().
*/
@@ -1661,15 +1661,15 @@ QGraphicsScene *QGraphicsItem::scene() const
}
/*!
- Returns a pointer to this item's item group, or 0 if this item is not
- member of a group.
+ Returns a pointer to this item's item group, or \nullptr if this
+ item is not member of a group.
\sa QGraphicsItemGroup, QGraphicsScene::createItemGroup()
*/
QGraphicsItemGroup *QGraphicsItem::group() const
{
if (!d_ptr->isMemberOfGroup)
- return 0;
+ return nullptr;
QGraphicsItem *parent = const_cast<QGraphicsItem *>(this);
while ((parent = parent->d_ptr->parent)) {
if (QGraphicsItemGroup *group = qgraphicsitem_cast<QGraphicsItemGroup *>(parent))
@@ -1677,11 +1677,11 @@ QGraphicsItemGroup *QGraphicsItem::group() const
}
// Unreachable; if d_ptr->isMemberOfGroup is != 0, then one parent of this
// item is a group item.
- return 0;
+ return nullptr;
}
/*!
- Adds this item to the item group \a group. If \a group is 0, this item is
+ Adds this item to the item group \a group. If \a group is \nullptr, this item is
removed from any current group and added as a child of the previous
group's parent.
@@ -1699,7 +1699,7 @@ void QGraphicsItem::setGroup(QGraphicsItemGroup *group)
/*!
Returns a pointer to this item's parent item. If this item does not have a
- parent, 0 is returned.
+ parent, \nullptr is returned.
\sa setParentItem(), childItems()
*/
@@ -1710,8 +1710,9 @@ QGraphicsItem *QGraphicsItem::parentItem() const
/*!
Returns this item's top-level item. The top-level item is the item's
- topmost ancestor item whose parent is 0. If an item has no parent, its own
- pointer is returned (i.e., a top-level item is its own top-level item).
+ topmost ancestor item whose parent is \nullptr. If an item has no
+ parent, its own pointer is returned (i.e., a top-level item is its
+ own top-level item).
\sa parentItem()
*/
@@ -1734,7 +1735,7 @@ QGraphicsItem *QGraphicsItem::topLevelItem() const
QGraphicsObject *QGraphicsItem::parentObject() const
{
QGraphicsItem *p = d_ptr->parent;
- return (p && p->d_ptr->isObject) ? static_cast<QGraphicsObject *>(p) : 0;
+ return (p && p->d_ptr->isObject) ? static_cast<QGraphicsObject *>(p) : nullptr;
}
/*!
@@ -1757,23 +1758,24 @@ QGraphicsWidget *QGraphicsItem::parentWidget() const
\since 4.4
Returns a pointer to the item's top level widget (i.e., the item's
- ancestor whose parent is 0, or whose parent is not a widget), or 0 if this
- item does not have a top level widget. If the item is its own top level
- widget, this function returns a pointer to the item itself.
+ ancestor whose parent is \nullptr, or whose parent is not a widget), or
+ \nullptr if this item does not have a top level widget. If the item
+ is its own top level widget, this function returns a pointer to the
+ item itself.
*/
QGraphicsWidget *QGraphicsItem::topLevelWidget() const
{
if (const QGraphicsWidget *p = parentWidget())
return p->topLevelWidget();
- return isWidget() ? static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this)) : 0;
+ return isWidget() ? static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this)) : nullptr;
}
/*!
\since 4.4
- Returns the item's window, or 0 if this item does not have a window. If
- the item is a window, it will return itself. Otherwise it will return the
- closest ancestor that is a window.
+ Returns the item's window, or \nullptr if this item does not have a
+ window. If the item is a window, it will return itself. Otherwise
+ it will return the closest ancestor that is a window.
\sa QGraphicsWidget::isWindow()
*/
@@ -1782,15 +1784,15 @@ QGraphicsWidget *QGraphicsItem::window() const
QGraphicsItem *p = panel();
if (p && p->isWindow())
return static_cast<QGraphicsWidget *>(p);
- return 0;
+ return nullptr;
}
/*!
\since 4.6
- Returns the item's panel, or 0 if this item does not have a panel. If the
- item is a panel, it will return itself. Otherwise it will return the
- closest ancestor that is a panel.
+ Returns the item's panel, or \nullptr if this item does not have a
+ panel. If the item is a panel, it will return itself. Otherwise it
+ will return the closest ancestor that is a panel.
\sa isPanel(), ItemIsPanel
*/
@@ -1798,7 +1800,7 @@ QGraphicsItem *QGraphicsItem::panel() const
{
if (d_ptr->flags & ItemIsPanel)
return const_cast<QGraphicsItem *>(this);
- return d_ptr->parent ? d_ptr->parent->panel() : 0;
+ return d_ptr->parent ? d_ptr->parent->panel() : nullptr;
}
/*!
@@ -2397,7 +2399,7 @@ bool QGraphicsItem::isVisible() const
/*!
\since 4.4
Returns \c true if the item is visible to \a parent; otherwise, false is
- returned. \a parent can be 0, in which case this function will return
+ returned. \a parent can be \nullptr, in which case this function will return
whether the item is visible to the scene or not.
An item may not be visible to its ancestors even if isVisible() is true. It
@@ -2925,7 +2927,7 @@ void QGraphicsItem::setOpacity(qreal opacity)
}
/*!
- Returns a pointer to this item's effect if it has one; otherwise 0.
+ Returns a pointer to this item's effect if it has one; otherwise \nullptr.
\since 4.6
*/
@@ -2939,7 +2941,7 @@ QGraphicsEffect *QGraphicsItem::graphicsEffect() const
Sets \a effect as the item's effect. If there already is an effect installed
on this item, QGraphicsItem will delete the existing effect before installing
the new \a effect. You can delete an existing effect by calling
- setGraphicsEffect(0).
+ setGraphicsEffect(\nullptr).
If \a effect is the installed effect on a different item, setGraphicsEffect() will remove
the effect from the item and install it on this item.
@@ -3577,7 +3579,7 @@ void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent, bool hiddenB
/*!
\since 4.6
- Returns this item's focus proxy, or 0 if this item has no
+ Returns this item's focus proxy, or \nullptr if this item has no
focus proxy.
\sa setFocusProxy(), setFocus(), hasFocus()
@@ -3640,7 +3642,7 @@ void QGraphicsItem::setFocusProxy(QGraphicsItem *item)
If this item, a child or descendant of this item currently has input
focus, this function will return a pointer to that item. If
- no descendant has input focus, 0 is returned.
+ no descendant has input focus, \nullptr is returned.
\sa hasFocus(), setFocus(), QWidget::focusWidget()
*/
@@ -3995,6 +3997,7 @@ void QGraphicsItem::ensureVisible(const QRectF &rect, int xmargin, int ymargin)
ensureVisible(QRectF(\a x, \a y, \a w, \a h), \a xmargin, \a ymargin).
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -4010,6 +4013,7 @@ QMatrix QGraphicsItem::matrix() const
{
return transform().toAffine();
}
+#endif
/*!
\since 4.3
@@ -4320,6 +4324,7 @@ void QGraphicsItem::setTransformOriginPoint(const QPointF &origin)
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -4332,7 +4337,7 @@ QMatrix QGraphicsItem::sceneMatrix() const
d_ptr->ensureSceneTransform();
return d_ptr->sceneTransform.toAffine();
}
-
+#endif
/*!
\since 4.3
@@ -4544,6 +4549,7 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
return x;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -4582,6 +4588,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
// Send post-notification.
itemChange(ItemTransformHasChanged, QVariant::fromValue<QTransform>(newTransform));
}
+#endif
/*!
\since 4.3
@@ -4636,6 +4643,7 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
d_ptr->sendScenePosChange();
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -4645,6 +4653,7 @@ void QGraphicsItem::resetMatrix()
{
resetTransform();
}
+#endif
/*!
\since 4.3
@@ -5790,7 +5799,7 @@ void QGraphicsItemPrivate::clearSubFocus(QGraphicsItem *rootItem, QGraphicsItem
/*!
\internal
- Sets the focusProxy pointer to 0 for all items that have this item as their
+ Sets the focusProxy pointer to \nullptr for all items that have this item as their
focusProxy.
*/
void QGraphicsItemPrivate::resetFocusProxy()
@@ -6001,7 +6010,7 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect)
Maps the point \a point, which is in this item's coordinate system, to \a
item's coordinate system, and returns the mapped coordinate.
- If \a item is 0, this function returns the same as mapToScene().
+ If \a item is \nullptr, this function returns the same as mapToScene().
\sa itemTransform(), mapToParent(), mapToScene(), transform(), mapFromItem(), {The Graphics
View Coordinate System}
@@ -6071,7 +6080,7 @@ QPointF QGraphicsItem::mapToScene(const QPointF &point) const
Maps the rectangle \a rect, which is in this item's coordinate system, to
\a item's coordinate system, and returns the mapped rectangle as a polygon.
- If \a item is 0, this function returns the same as mapToScene().
+ If \a item is \nullptr, this function returns the same as mapToScene().
\sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
Graphics View Coordinate System}
@@ -6142,7 +6151,7 @@ QPolygonF QGraphicsItem::mapToScene(const QRectF &rect) const
\a item's coordinate system, and returns the mapped rectangle as a new
rectangle (i.e., the bounding rectangle of the resulting polygon).
- If \a item is 0, this function returns the same as mapRectToScene().
+ If \a item is \nullptr, this function returns the same as mapRectToScene().
\sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
Graphics View Coordinate System}
@@ -6217,7 +6226,7 @@ QRectF QGraphicsItem::mapRectToScene(const QRectF &rect) const
this item's coordinate system, and returns the mapped rectangle as a new
rectangle (i.e., the bounding rectangle of the resulting polygon).
- If \a item is 0, this function returns the same as mapRectFromScene().
+ If \a item is \nullptr, this function returns the same as mapRectFromScene().
\sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
Graphics View Coordinate System}
@@ -6290,7 +6299,7 @@ QRectF QGraphicsItem::mapRectFromScene(const QRectF &rect) const
Maps the polygon \a polygon, which is in this item's coordinate system, to
\a item's coordinate system, and returns the mapped polygon.
- If \a item is 0, this function returns the same as mapToScene().
+ If \a item is \nullptr, this function returns the same as mapToScene().
\sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
Graphics View Coordinate System}
@@ -6337,7 +6346,7 @@ QPolygonF QGraphicsItem::mapToScene(const QPolygonF &polygon) const
Maps the path \a path, which is in this item's coordinate system, to
\a item's coordinate system, and returns the mapped path.
- If \a item is 0, this function returns the same as mapToScene().
+ If \a item is \nullptr, this function returns the same as mapToScene().
\sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The
Graphics View Coordinate System}
@@ -6384,7 +6393,7 @@ QPainterPath QGraphicsItem::mapToScene(const QPainterPath &path) const
Maps the point \a point, which is in \a item's coordinate system, to this
item's coordinate system, and returns the mapped coordinate.
- If \a item is 0, this function returns the same as mapFromScene().
+ If \a item is \nullptr, this function returns the same as mapFromScene().
\sa itemTransform(), mapFromParent(), mapFromScene(), transform(), mapToItem(), {The Graphics
View Coordinate System}
@@ -6456,7 +6465,7 @@ QPointF QGraphicsItem::mapFromScene(const QPointF &point) const
this item's coordinate system, and returns the mapped rectangle as a
polygon.
- If \a item is 0, this function returns the same as mapFromScene()
+ If \a item is \nullptr, this function returns the same as mapFromScene()
\sa itemTransform(), mapToItem(), mapFromParent(), transform(), {The Graphics View Coordinate
System}
@@ -6524,7 +6533,7 @@ QPolygonF QGraphicsItem::mapFromScene(const QRectF &rect) const
Maps the polygon \a polygon, which is in \a item's coordinate system, to
this item's coordinate system, and returns the mapped polygon.
- If \a item is 0, this function returns the same as mapFromScene().
+ If \a item is \nullptr, this function returns the same as mapFromScene().
\sa itemTransform(), mapToItem(), mapFromParent(), transform(), {The
Graphics View Coordinate System}
@@ -6569,7 +6578,7 @@ QPolygonF QGraphicsItem::mapFromScene(const QPolygonF &polygon) const
Maps the path \a path, which is in \a item's coordinate system, to
this item's coordinate system, and returns the mapped path.
- If \a item is 0, this function returns the same as mapFromScene().
+ If \a item is \nullptr, this function returns the same as mapFromScene().
\sa itemTransform(), mapFromParent(), mapFromScene(), mapToItem(), {The
Graphics View Coordinate System}
@@ -6633,15 +6642,15 @@ bool QGraphicsItem::isAncestorOf(const QGraphicsItem *child) const
/*!
\since 4.4
- Returns the closest common ancestor item of this item and \a other, or 0
- if either \a other is 0, or there is no common ancestor.
+ Returns the closest common ancestor item of this item and \a other,
+ or \nullptr if either \a other is \nullptr, or there is no common ancestor.
\sa isAncestorOf()
*/
QGraphicsItem *QGraphicsItem::commonAncestorItem(const QGraphicsItem *other) const
{
if (!other)
- return 0;
+ return nullptr;
if (other == this)
return const_cast<QGraphicsItem *>(this);
const QGraphicsItem *thisw = this;
@@ -6726,7 +6735,7 @@ void QGraphicsItem::setData(int key, const QVariant &value)
\since 4.2
Returns the given \a item cast to type T if \a item is of type T;
- otherwise, 0 is returned.
+ otherwise, \nullptr is returned.
\note To make this function work correctly with custom items, reimplement
the \l{QGraphicsItem::}{type()} function for each custom QGraphicsItem
diff --git a/src/widgets/graphicsview/qgraphicsitem.h b/src/widgets/graphicsview/qgraphicsitem.h
index c228e765d8..7dd4441ae9 100644
--- a/src/widgets/graphicsview/qgraphicsitem.h
+++ b/src/widgets/graphicsview/qgraphicsitem.h
@@ -283,10 +283,16 @@ public:
inline void ensureVisible(qreal x, qreal y, qreal w, qreal h, int xmargin = 50, int ymargin = 50);
// Local transformation
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use transform() instead")
QMatrix matrix() const;
+ QT_DEPRECATED_X("Use sceneTransform() instead")
QMatrix sceneMatrix() const;
+ QT_DEPRECATED_X("Use setTransform() instead")
void setMatrix(const QMatrix &matrix, bool combine = false);
+ QT_DEPRECATED_X("Use resetTransform() instead")
void resetMatrix();
+#endif
QTransform transform() const;
QTransform sceneTransform() const;
QTransform deviceTransform(const QTransform &viewportTransform) const;
@@ -487,7 +493,9 @@ private:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsItem::GraphicsItemFlags)
+#ifndef Q_CLANG_QDOC
Q_DECLARE_INTERFACE(QGraphicsItem, "org.qt-project.Qt.QGraphicsItem")
+#endif
inline void QGraphicsItem::setPos(qreal ax, qreal ay)
{ setPos(QPointF(ax, ay)); }
diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h
index 54c25bf6e1..92d85f7125 100644
--- a/src/widgets/graphicsview/qgraphicsitem_p.h
+++ b/src/widgets/graphicsview/qgraphicsitem_p.h
@@ -78,13 +78,13 @@ public:
typedef void (*ClearFunction)(QDeclarativeListProperty<T> *);
QDeclarativeListProperty()
- : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {}
+ : object(nullptr), data(nullptr), append(nullptr), count(nullptr), at(nullptr), clear(nullptr), dummy1(nullptr), dummy2(nullptr) {}
QDeclarativeListProperty(QObject *o, QList<T *> &list)
: object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at),
- clear(qlist_clear), dummy1(0), dummy2(0) {}
+ clear(qlist_clear), dummy1(nullptr), dummy2(nullptr) {}
QDeclarativeListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0,
ClearFunction r = 0)
- : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {}
+ : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(nullptr), dummy2(nullptr) {}
bool operator==(const QDeclarativeListProperty &o) const {
return object == o.object &&
@@ -198,8 +198,8 @@ public:
|| (ancestorFlags & AncestorIgnoresTransformations);
}
- void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const;
- void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const;
+ void combineTransformToParent(QTransform *x, const QTransform *viewTransform = nullptr) const;
+ void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = nullptr) const;
virtual void updateSceneTransformFromParent();
static bool movableAncestorIsSelected(const QGraphicsItem *item);
@@ -232,7 +232,7 @@ public:
void childrenBoundingRectHelper(QTransform *x, QRectF *rect, QGraphicsItem *topMostEffectItem);
void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
const QRegion &exposedRegion, bool allItems = false) const;
- QRectF effectiveBoundingRect(QGraphicsItem *topMostEffectItem = 0) const;
+ QRectF effectiveBoundingRect(QGraphicsItem *topMostEffectItem = nullptr) const;
QRectF sceneEffectiveBoundingRect() const;
QRectF effectiveBoundingRect(const QRectF &rect) const;
@@ -408,8 +408,8 @@ public:
void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide);
void clearFocusHelper(bool giveFocusToParent, bool hiddenByParentPanel);
- void setSubFocus(QGraphicsItem *rootItem = 0, QGraphicsItem *stopItem = 0);
- void clearSubFocus(QGraphicsItem *rootItem = 0, QGraphicsItem *stopItem = 0);
+ void setSubFocus(QGraphicsItem *rootItem = nullptr, QGraphicsItem *stopItem = nullptr);
+ void clearSubFocus(QGraphicsItem *rootItem = nullptr, QGraphicsItem *stopItem = nullptr);
void resetFocusProxy();
virtual void subFocusItemChange();
virtual void focusScopeItemChange(bool isSubFocusItem);
@@ -541,7 +541,7 @@ struct QGraphicsItemPrivate::TransformData
onlyTransform(true)
{ }
- QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const
+ QTransform computedFullTransform(QTransform *postmultiplyTransform = nullptr) const
{
if (onlyTransform) {
if (!postmultiplyTransform || postmultiplyTransform->isIdentity())
@@ -595,12 +595,12 @@ class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate
{
public:
QGraphicsItemEffectSourcePrivate(QGraphicsItem *i)
- : QGraphicsEffectSourcePrivate(), item(i), info(0)
+ : QGraphicsEffectSourcePrivate(), item(i), info(nullptr)
{}
void detach() override
{
- item->d_ptr->graphicsEffect = 0;
+ item->d_ptr->graphicsEffect = nullptr;
item->prepareGeometryChange();
}
@@ -608,7 +608,7 @@ public:
{ return item; }
const QWidget *widget() const override
- { return 0; }
+ { return nullptr; }
void update() override {
item->d_ptr->updateDueToGraphicsEffect = true;
@@ -628,7 +628,7 @@ public:
}
const QStyleOption *styleOption() const override
- { return info ? info->option : 0; }
+ { return info ? info->option : nullptr; }
QRect deviceRect() const override
{
@@ -644,7 +644,7 @@ public:
QPixmap pixmap(Qt::CoordinateSystem system,
QPoint *offset,
QGraphicsEffect::PixmapPadMode mode) const override;
- QRectF paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = 0) const;
+ QRectF paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = nullptr) const;
QGraphicsItem *item;
QGraphicsItemPaintInfo *info;
diff --git a/src/widgets/graphicsview/qgraphicsitemanimation.cpp b/src/widgets/graphicsview/qgraphicsitemanimation.cpp
index 572ec141bc..ad77e2f260 100644
--- a/src/widgets/graphicsview/qgraphicsitemanimation.cpp
+++ b/src/widgets/graphicsview/qgraphicsitemanimation.cpp
@@ -115,7 +115,7 @@ public:
QGraphicsItem *item;
QPointF startPos;
- QMatrix startMatrix;
+ QTransform startTransform;
qreal step;
@@ -294,23 +294,38 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::posList() const
return list;
}
+#if QT_DEPRECATED_SINCE(5, 14)
/*!
Returns the matrix used to transform the item at the specified \a step value.
+
+ \obsolete Use transformAt() instead
*/
QMatrix QGraphicsItemAnimation::matrixAt(qreal step) const
{
check_step_valid(step, "matrixAt");
+ return transformAt(step).toAffine();
+}
+#endif
+
+/*!
+ Returns the transform used for the item at the specified \a step value.
+
+ \since 5.14
+*/
+QTransform QGraphicsItemAnimation::transformAt(qreal step) const
+{
+ check_step_valid(step, "transformAt");
- QMatrix matrix;
+ QTransform transform;
if (!d->rotation.isEmpty())
- matrix.rotate(rotationAt(step));
+ transform.rotate(rotationAt(step));
if (!d->verticalScale.isEmpty())
- matrix.scale(horizontalScaleAt(step), verticalScaleAt(step));
+ transform.scale(horizontalScaleAt(step), verticalScaleAt(step));
if (!d->verticalShear.isEmpty())
- matrix.shear(horizontalShearAt(step), verticalShearAt(step));
+ transform.shear(horizontalShearAt(step), verticalShearAt(step));
if (!d->xTranslation.isEmpty())
- matrix.translate(xTranslationAt(step), yTranslationAt(step));
- return matrix;
+ transform.translate(xTranslationAt(step), yTranslationAt(step));
+ return transform;
}
/*!
@@ -542,13 +557,14 @@ void QGraphicsItemAnimation::setStep(qreal step)
|| !d->horizontalShear.isEmpty()
|| !d->xTranslation.isEmpty()
|| !d->yTranslation.isEmpty()) {
- d->item->setMatrix(d->startMatrix * matrixAt(step));
+ d->item->setTransform(d->startTransform * transformAt(step));
}
}
afterAnimationStep(step);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
Resets the item to its starting position and transformation.
@@ -561,8 +577,9 @@ void QGraphicsItemAnimation::reset()
if (!d->item)
return;
d->startPos = d->item->pos();
- d->startMatrix = d->item->matrix();
+ d->startTransform = d->item->transform();
}
+#endif
/*!
\fn void QGraphicsItemAnimation::beforeAnimationStep(qreal step)
diff --git a/src/widgets/graphicsview/qgraphicsitemanimation.h b/src/widgets/graphicsview/qgraphicsitemanimation.h
index 7417d7729c..3051fb2e2b 100644
--- a/src/widgets/graphicsview/qgraphicsitemanimation.h
+++ b/src/widgets/graphicsview/qgraphicsitemanimation.h
@@ -51,6 +51,7 @@ class QGraphicsItem;
class QMatrix;
class QPointF;
class QTimeLine;
+class QTransform;
template <class T1, class T2> struct QPair;
class QGraphicsItemAnimationPrivate;
@@ -71,7 +72,11 @@ public:
QList<QPair<qreal, QPointF> > posList() const;
void setPosAt(qreal step, const QPointF &pos);
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_X("Use transformAt() instead")
QMatrix matrixAt(qreal step) const;
+#endif
+ QTransform transformAt(qreal step) const;
qreal rotationAt(qreal step) const;
QList<QPair<qreal, qreal> > rotationList() const;
@@ -96,7 +101,10 @@ public:
public Q_SLOTS:
void setStep(qreal x);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use setStep(0) instead")
void reset();
+#endif
protected:
virtual void beforeAnimationStep(qreal step);
diff --git a/src/widgets/graphicsview/qgraphicslayout.h b/src/widgets/graphicsview/qgraphicslayout.h
index 28b335ceaa..efcafa5e6a 100644
--- a/src/widgets/graphicsview/qgraphicslayout.h
+++ b/src/widgets/graphicsview/qgraphicslayout.h
@@ -83,7 +83,9 @@ private:
friend class QGraphicsWidget;
};
+#ifndef Q_CLANG_QDOC
Q_DECLARE_INTERFACE(QGraphicsLayout, "org.qt-project.Qt.QGraphicsLayout")
+#endif
QT_END_NAMESPACE
diff --git a/src/widgets/graphicsview/qgraphicslayout_p.h b/src/widgets/graphicsview/qgraphicslayout_p.h
index 302ad1e116..0d91151e22 100644
--- a/src/widgets/graphicsview/qgraphicslayout_p.h
+++ b/src/widgets/graphicsview/qgraphicslayout_p.h
@@ -91,7 +91,7 @@ public:
m_defaultSpacing[1] = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
}
- inline void invalidate() { m_valid = false; m_style = 0; m_widget = 0; }
+ inline void invalidate() { m_valid = false; m_style = nullptr; m_widget = nullptr; }
inline QStyle *style() const { return m_style; }
inline QWidget *widget() const { return m_widget; }
@@ -130,7 +130,7 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPriva
Q_DECLARE_PUBLIC(QGraphicsLayout)
public:
- QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0),
+ QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(nullptr, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0),
activated(true) { }
void reparentChildItems(QGraphicsItem *newParent);
diff --git a/src/widgets/graphicsview/qgraphicslayoutitem.cpp b/src/widgets/graphicsview/qgraphicslayoutitem.cpp
index aed154a95f..1192bad51e 100644
--- a/src/widgets/graphicsview/qgraphicslayoutitem.cpp
+++ b/src/widgets/graphicsview/qgraphicslayoutitem.cpp
@@ -193,7 +193,7 @@ QSizeF *QGraphicsLayoutItemPrivate::effectiveSizeHints(const QSizeF &constraint)
/*!
\internal
- Returns the parent item of this layout, or 0 if this layout is
+ Returns the parent item of this layout, or \nullptr if this layout is
not installed on any widget.
If this is the item that the layout is installed on, it will return "itself".
@@ -214,7 +214,7 @@ QGraphicsItem *QGraphicsLayoutItemPrivate::parentItem() const
while (parent && parent->isLayout()) {
parent = parent->parentLayoutItem();
}
- return parent ? parent->graphicsItem() : 0;
+ return parent ? parent->graphicsItem() : nullptr;
}
/*!
@@ -368,7 +368,7 @@ bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const
passing a QGraphicsLayoutItem pointer to QGraphicsLayoutItem's
protected constructor, or by calling setParentLayoutItem(). The
parentLayoutItem() function returns a pointer to the item's layoutItem
- parent. If the item's parent is 0 or if the parent does not inherit
+ parent. If the item's parent is \nullptr or if the parent does not inherit
from QGraphicsItem, the parentLayoutItem() function then returns \nullptr.
isLayout() returns \c true if the QGraphicsLayoutItem subclass is itself a
layout, or false otherwise.
@@ -737,7 +737,7 @@ QRectF QGraphicsLayoutItem::geometry() const
This virtual function provides the \a left, \a top, \a right and \a bottom
contents margins for this QGraphicsLayoutItem. The default implementation
assumes all contents margins are 0. The parameters point to values stored
- in qreals. If any of the pointers is 0, that value will not be updated.
+ in qreals. If any of the pointers is \nullptr, that value will not be updated.
\sa QGraphicsWidget::setContentsMargins()
*/
@@ -826,8 +826,8 @@ void QGraphicsLayoutItem::updateGeometry()
}
/*!
- Returns the parent of this QGraphicsLayoutItem, or 0 if there is no parent,
- or if the parent does not inherit from QGraphicsLayoutItem
+ Returns the parent of this QGraphicsLayoutItem, or \nullptr if there is
+ no parent, or if the parent does not inherit from QGraphicsLayoutItem
(QGraphicsLayoutItem is often used through multiple inheritance with
QObject-derived classes).
@@ -917,7 +917,7 @@ QGraphicsItem *QGraphicsLayoutItem::graphicsItem() const
* advantage of the automatic reparenting capabilities of QGraphicsLayout it
* should set this value.
* Note that if you delete \a item and not delete the layout item, you are
- * responsible of calling setGraphicsItem(0) in order to avoid having a
+ * responsible of calling setGraphicsItem(\nullptr) in order to avoid having a
* dangling pointer.
*
* \sa graphicsItem()
diff --git a/src/widgets/graphicsview/qgraphicslayoutitem.h b/src/widgets/graphicsview/qgraphicslayoutitem.h
index 44f430034b..86a0a87361 100644
--- a/src/widgets/graphicsview/qgraphicslayoutitem.h
+++ b/src/widgets/graphicsview/qgraphicslayoutitem.h
@@ -116,7 +116,9 @@ private:
friend class QGraphicsLayout;
};
+#ifndef Q_CLANG_QDOC
Q_DECLARE_INTERFACE(QGraphicsLayoutItem, "org.qt-project.Qt.QGraphicsLayoutItem")
+#endif
inline void QGraphicsLayoutItem::setMinimumSize(qreal aw, qreal ah)
{ setMinimumSize(QSizeF(aw, ah)); }
diff --git a/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp b/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp
index af969b346d..da2510a8cb 100644
--- a/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp
+++ b/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp
@@ -50,15 +50,13 @@ QT_BEGIN_NAMESPACE
QGraphicsLayoutStyleInfo::QGraphicsLayoutStyleInfo(const QGraphicsLayoutPrivate *layout)
: m_layout(layout), m_style(0)
{
- m_widget = new QWidget; // pixelMetric might need a widget ptr
- if (m_widget)
- m_styleOption.initFrom(m_widget);
+ m_widget.reset(new QWidget); // pixelMetric might need a widget ptr
+ m_styleOption.initFrom(m_widget.get());
m_isWindow = m_styleOption.state & QStyle::State_Window;
}
QGraphicsLayoutStyleInfo::~QGraphicsLayoutStyleInfo()
{
- delete m_widget;
}
qreal QGraphicsLayoutStyleInfo::combinedLayoutSpacing(QLayoutPolicy::ControlTypes controls1,
@@ -93,7 +91,7 @@ qreal QGraphicsLayoutStyleInfo::windowMargin(Qt::Orientation orientation) const
const_cast<QStyleOption*>(&m_styleOption), widget());
}
-QWidget *QGraphicsLayoutStyleInfo::widget() const { return m_widget; }
+QWidget *QGraphicsLayoutStyleInfo::widget() const { return m_widget.get(); }
QStyle *QGraphicsLayoutStyleInfo::style() const
{
diff --git a/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h b/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h
index 7886de432c..9807efb26e 100644
--- a/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h
+++ b/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h
@@ -54,6 +54,8 @@
#include <QtGui/private/qabstractlayoutstyleinfo_p.h>
#include <QtWidgets/qstyleoption.h>
+#include <memory>
+
QT_REQUIRE_CONFIG(graphicsview);
QT_BEGIN_NAMESPACE
@@ -82,7 +84,7 @@ public:
virtual void invalidate() override
{
- m_style = 0;
+ m_style = nullptr;
QAbstractLayoutStyleInfo::invalidate();
}
@@ -93,7 +95,7 @@ private:
const QGraphicsLayoutPrivate *m_layout;
mutable QStyle *m_style;
QStyleOption m_styleOption;
- QWidget *m_widget;
+ std::unique_ptr<QWidget> m_widget;
};
QT_END_NAMESPACE
diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp
index 513cf9d361..e9f092020f 100644
--- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp
@@ -556,7 +556,7 @@ QGraphicsProxyWidget::~QGraphicsProxyWidget()
exclusively either inside or outside of Graphics View. You cannot embed a
widget as long as it is is visible elsewhere in the UI, at the same time.
- \a widget must be a top-level widget whose parent is 0.
+ \a widget must be a top-level widget whose parent is \nullptr.
When the widget is embedded, its state (e.g., visible, enabled, geometry,
size hints) is copied into the proxy widget. If the embedded widget is
@@ -739,7 +739,7 @@ QWidget *QGraphicsProxyWidget::widget() const
Returns the rectangle for \a widget, which must be a descendant of
widget(), or widget() itself, in this proxy item's local coordinates.
- If no widget is embedded, \a widget is 0, or \a widget is not a
+ If no widget is embedded, \a widget is \nullptr, or \a widget is not a
descendant of the embedded widget, this function returns an empty QRectF.
\sa widget()
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index 3dce958b08..e5bd65d61e 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -1923,12 +1923,13 @@ void QGraphicsScene::setBspTreeDepth(int depth)
QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
if (!bspTree) {
- qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP");
+ qWarning("QGraphicsScene::setBspTreeDepth: cannot apply if indexing method is not BSP");
return;
}
bspTree->setBspTreeDepth(depth);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\property QGraphicsScene::sortCacheEnabled
\brief whether sort caching is enabled
@@ -1949,6 +1950,7 @@ void QGraphicsScene::setSortCacheEnabled(bool enabled)
return;
d->sortCacheEnabled = enabled;
}
+#endif
/*!
Calculates and returns the bounding rect of all items on the scene. This
@@ -2144,8 +2146,8 @@ QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
\overload
\obsolete
- Returns the topmost visible item at the specified \a position, or 0 if
- there are no items at this position.
+ Returns the topmost visible item at the specified \a position, or
+ \nullptr if there are no items at this position.
This function is deprecated and returns incorrect results if the scene
contains items that ignore transformations. Use the overload that takes
@@ -2159,7 +2161,7 @@ QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
/*!
\since 4.6
- Returns the topmost visible item at the specified \a position, or 0
+ Returns the topmost visible item at the specified \a position, or \nullptr
if there are no items at this position.
\a deviceTransform is the transformation that applies to the view, and needs to
@@ -2173,7 +2175,7 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform
{
const QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape,
Qt::DescendingOrder, deviceTransform);
- return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
+ return itemsAtPoint.isEmpty() ? nullptr : itemsAtPoint.first();
}
/*!
@@ -2182,7 +2184,7 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform
\since 4.6
Returns the topmost visible item at the position specified by (\a x, \a
- y), or 0 if there are no items at this position.
+ y), or \nullptr if there are no items at this position.
\a deviceTransform is the transformation that applies to the view, and needs to
be provided if the scene contains items that ignore transformations.
@@ -2199,7 +2201,7 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform
\obsolete
Returns the topmost visible item at the position specified by (\a x, \a
- y), or 0 if there are no items at this position.
+ y), or \nullptr if there are no items at this position.
This convenience function is equivalent to calling \c
{itemAt(QPointF(x, y))}.
@@ -2941,9 +2943,9 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
/*!
When the scene is active, this functions returns the scene's current focus
- item, or 0 if no item currently has focus. When the scene is inactive, this
- functions returns the item that will gain input focus when the scene becomes
- active.
+ item, or \nullptr if no item currently has focus. When the scene is inactive,
+ this functions returns the item that will gain input focus when the scene
+ becomes active.
The focus item receives keyboard input when the scene receives a
key event.
@@ -2961,12 +2963,12 @@ QGraphicsItem *QGraphicsScene::focusItem() const
focusReason, after removing focus from any previous item that may have had
focus.
- If \a item is 0, or if it either does not accept focus (i.e., it does not
+ If \a item is \nullptr, or if it either does not accept focus (i.e., it does not
have the QGraphicsItem::ItemIsFocusable flag enabled), or is not visible
or not enabled, this function only removes focus from any previous
focusitem.
- If item is not 0, and the scene does not currently have focus (i.e.,
+ If item is not \nullptr, and the scene does not currently have focus (i.e.,
hasFocus() returns \c false), this function will call setFocus()
automatically.
@@ -3062,9 +3064,9 @@ bool QGraphicsScene::stickyFocus() const
}
/*!
- Returns the current mouse grabber item, or 0 if no item is currently
- grabbing the mouse. The mouse grabber item is the item that receives all
- mouse events sent to the scene.
+ Returns the current mouse grabber item, or \nullptr if no item is
+ currently grabbing the mouse. The mouse grabber item is the item
+ that receives all mouse events sent to the scene.
An item becomes a mouse grabber when it receives and accepts a
mouse press event, and it stays the mouse grabber until either of
@@ -3322,6 +3324,9 @@ void QGraphicsScene::advance()
\l{QWidget::}{enterEvent()} and \l{QWidget::}{leaveEvent()}. Use this
function to obtain those events instead.
+ Returns \c true if \a event has been recognized and processed; otherwise,
+ returns \c false.
+
\sa contextMenuEvent(), keyPressEvent(), keyReleaseEvent(),
mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(),
mouseDoubleClickEvent(), focusInEvent(), focusOutEvent()
@@ -5547,11 +5552,11 @@ bool QGraphicsScene::focusNextPrevChild(bool next)
\a oldFocusItem is a pointer to the item that previously had focus, or
0 if no item had focus before the signal was emitted. \a newFocusItem
- is a pointer to the item that gained input focus, or 0 if focus was lost.
+ is a pointer to the item that gained input focus, or \nullptr if focus was lost.
\a reason is the reason for the focus change (e.g., if the scene was
deactivated while an input field had focus, \a oldFocusItem would point
- to the input field item, \a newFocusItem would be 0, and \a reason would be
- Qt::ActiveWindowFocusReason.
+ to the input field item, \a newFocusItem would be \nullptr, and \a reason
+ would be Qt::ActiveWindowFocusReason.
*/
/*!
@@ -5582,7 +5587,7 @@ QStyle *QGraphicsScene::style() const
the style for all widgets in the scene that do not have a style explicitly
assigned to them.
- If \a style is 0, QGraphicsScene will revert to QApplication::style().
+ If \a style is \nullptr, QGraphicsScene will revert to QApplication::style().
\sa style()
*/
@@ -5703,7 +5708,8 @@ bool QGraphicsScene::isActive() const
/*!
\since 4.6
- Returns the current active panel, or 0 if no panel is currently active.
+ Returns the current active panel, or \nullptr if no panel is
+ currently active.
\sa QGraphicsScene::setActivePanel()
*/
@@ -5720,7 +5726,7 @@ QGraphicsItem *QGraphicsScene::activePanel() const
deactivate any currently active panel.
If the scene is currently inactive, \a item remains inactive until the
- scene becomes active (or, ir \a item is 0, no item will be activated).
+ scene becomes active (or, ir \a item is \nullptr, no item will be activated).
\sa activePanel(), isActive(), QGraphicsItem::isActive()
*/
@@ -5733,8 +5739,8 @@ void QGraphicsScene::setActivePanel(QGraphicsItem *item)
/*!
\since 4.4
- Returns the current active window, or 0 if no window is currently
- active.
+ Returns the current active window, or \nullptr if no window is
+ currently active.
\sa QGraphicsScene::setActiveWindow()
*/
@@ -5743,7 +5749,7 @@ QGraphicsWidget *QGraphicsScene::activeWindow() const
Q_D(const QGraphicsScene);
if (d->activePanel && d->activePanel->isWindow())
return static_cast<QGraphicsWidget *>(d->activePanel);
- return 0;
+ return nullptr;
}
/*!
@@ -6346,7 +6352,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
<< "delivering override to"
<< item.data() << gestures;
// send gesture override
- QGestureEvent ev(gestures.toList());
+ QGestureEvent ev(gestures.values());
ev.t = QEvent::GestureOverride;
ev.setWidget(event->widget());
// mark event and individual gestures as ignored
@@ -6436,7 +6442,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
<< "delivering to"
<< receiver.data() << gestures;
- QGestureEvent ev(gestures.toList());
+ QGestureEvent ev(gestures.values());
ev.setWidget(event->widget());
sendEvent(receiver.data(), &ev);
QSet<QGesture *> ignoredGestures;
@@ -6467,7 +6473,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
// look for new potential targets for gestures that were ignored
// and should be propagated.
- QSet<QGraphicsObject *> targetsSet = cachedTargetItems.toSet();
+ QSet<QGraphicsObject *> targetsSet(cachedTargetItems.constBegin(), cachedTargetItems.constEnd());
if (receiver) {
// first if the gesture should be propagated to parents only
@@ -6499,7 +6505,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures,
&cachedItemGestures, &targetsSet, 0, 0);
- cachedTargetItems = targetsSet.toList();
+ cachedTargetItems = targetsSet.values();
std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
<< "new targets:" << cachedTargetItems;
@@ -6577,7 +6583,7 @@ void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original)
}
Q_ASSERT(target);
- const QList<QGesture *> list = gestures.toList();
+ const QList<QGesture *> list = gestures.values();
QGestureEvent ev(list);
sendEvent(target, &ev);
diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h
index 287e551db7..3cc00ead08 100644
--- a/src/widgets/graphicsview/qgraphicsscene.h
+++ b/src/widgets/graphicsview/qgraphicsscene.h
@@ -103,7 +103,9 @@ class Q_WIDGETS_EXPORT QGraphicsScene : public QObject
Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth)
Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
Q_PROPERTY(QFont font READ font WRITE setFont)
+#if QT_DEPRECATED_SINCE(5, 13)
Q_PROPERTY(bool sortCacheEnabled READ isSortCacheEnabled WRITE setSortCacheEnabled)
+#endif
Q_PROPERTY(bool stickyFocus READ stickyFocus WRITE setStickyFocus)
Q_PROPERTY(qreal minimumRenderSize READ minimumRenderSize WRITE setMinimumRenderSize)
Q_PROPERTY(bool focusOnTouch READ focusOnTouch WRITE setFocusOnTouch)
@@ -141,8 +143,10 @@ public:
ItemIndexMethod itemIndexMethod() const;
void setItemIndexMethod(ItemIndexMethod method);
- bool isSortCacheEnabled() const;
- void setSortCacheEnabled(bool enabled);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED bool isSortCacheEnabled() const;
+ QT_DEPRECATED void setSortCacheEnabled(bool enabled);
+#endif
int bspTreeDepth() const;
void setBspTreeDepth(int depth);
diff --git a/src/widgets/graphicsview/qgraphicsscene_p.h b/src/widgets/graphicsview/qgraphicsscene_p.h
index a2d13436fc..7934359cee 100644
--- a/src/widgets/graphicsview/qgraphicsscene_p.h
+++ b/src/widgets/graphicsview/qgraphicsscene_p.h
@@ -226,7 +226,7 @@ public:
void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const,
QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0),
- const QTransform *const effectTransform = 0);
+ const QTransform *const effectTransform = nullptr);
void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const,
QRegion *, QWidget *, qreal, const QTransform *const, bool, bool);
@@ -312,9 +312,9 @@ public:
void gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures,
Qt::GestureFlag flag,
QHash<QGraphicsObject *, QSet<QGesture *> > *targets,
- QSet<QGraphicsObject *> *itemsSet = 0,
- QSet<QGesture *> *normal = 0,
- QSet<QGesture *> *conflicts = 0);
+ QSet<QGraphicsObject *> *itemsSet = nullptr,
+ QSet<QGesture *> *normal = nullptr,
+ QSet<QGesture *> *conflicts = nullptr);
void cancelGesturesForChildren(QGesture *original);
void grabGesture(QGraphicsItem *, Qt::GestureType gesture);
void ungrabGesture(QGraphicsItem *, Qt::GestureType gesture);
diff --git a/src/widgets/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/widgets/graphicsview/qgraphicsscenebsptreeindex_p.h
index b6387a2c56..7e0e525a6b 100644
--- a/src/widgets/graphicsview/qgraphicsscenebsptreeindex_p.h
+++ b/src/widgets/graphicsview/qgraphicsscenebsptreeindex_p.h
@@ -74,7 +74,7 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex
Q_OBJECT
Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth)
public:
- QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0);
+ QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = nullptr);
~QGraphicsSceneBspTreeIndex();
QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const override;
@@ -99,7 +99,7 @@ protected:
private :
Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex)
- Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex)
+ Q_DISABLE_COPY_MOVE(QGraphicsSceneBspTreeIndex)
Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache())
Q_PRIVATE_SLOT(d_func(), void _q_updateIndex())
diff --git a/src/widgets/graphicsview/qgraphicssceneevent.cpp b/src/widgets/graphicsview/qgraphicssceneevent.cpp
index 398ef1aaf5..5077a39d67 100644
--- a/src/widgets/graphicsview/qgraphicssceneevent.cpp
+++ b/src/widgets/graphicsview/qgraphicssceneevent.cpp
@@ -319,8 +319,8 @@ QGraphicsSceneEvent::~QGraphicsSceneEvent()
}
/*!
- Returns the widget where the event originated, or 0 if the event
- originates from another application.
+ Returns the widget where the event originated, or \nullptr if the
+ event originates from another application.
*/
QWidget *QGraphicsSceneEvent::widget() const
{
diff --git a/src/widgets/graphicsview/qgraphicssceneindex_p.h b/src/widgets/graphicsview/qgraphicssceneindex_p.h
index bdc57bd9ea..b494c52671 100644
--- a/src/widgets/graphicsview/qgraphicssceneindex_p.h
+++ b/src/widgets/graphicsview/qgraphicssceneindex_p.h
@@ -77,7 +77,7 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneIndex : public QObject
Q_OBJECT
public:
- QGraphicsSceneIndex(QGraphicsScene *scene = 0);
+ QGraphicsSceneIndex(QGraphicsScene *scene = nullptr);
virtual ~QGraphicsSceneIndex();
QGraphicsScene *scene() const;
@@ -115,7 +115,7 @@ protected:
friend class QGraphicsItemPrivate;
friend class QGraphicsSceneBspTreeIndex;
private:
- Q_DISABLE_COPY(QGraphicsSceneIndex)
+ Q_DISABLE_COPY_MOVE(QGraphicsSceneIndex)
Q_DECLARE_PRIVATE(QGraphicsSceneIndex)
};
@@ -151,7 +151,7 @@ inline void QGraphicsSceneIndexPrivate::items_helper(const QRectF &rect, QGraphi
if (order == Qt::DescendingOrder) {
const int n = items->size();
for (int i = 0; i < n / 2; ++i)
- items->swap(i, n - i - 1);
+ items->swapItemsAt(i, n - i - 1);
}
}
diff --git a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
index 07d5d80ef1..ead52c1fb0 100644
--- a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
+++ b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
@@ -67,7 +67,7 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex
Q_OBJECT
public:
- QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene), m_numSortedElements(0)
+ QGraphicsSceneLinearIndex(QGraphicsScene *scene = nullptr) : QGraphicsSceneIndex(scene), m_numSortedElements(0)
{ }
QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const override
diff --git a/src/widgets/graphicsview/qgraphicstransform_p.h b/src/widgets/graphicsview/qgraphicstransform_p.h
index e54ee9fb3c..05e12c3e64 100644
--- a/src/widgets/graphicsview/qgraphicstransform_p.h
+++ b/src/widgets/graphicsview/qgraphicstransform_p.h
@@ -66,7 +66,7 @@ public:
Q_DECLARE_PUBLIC(QGraphicsTransform)
QGraphicsTransformPrivate()
- : QObjectPrivate(), item(0) {}
+ : QObjectPrivate(), item(nullptr) {}
~QGraphicsTransformPrivate();
QGraphicsItem *item;
diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp
index 24647dd74c..5fe520132f 100644
--- a/src/widgets/graphicsview/qgraphicsview.cpp
+++ b/src/widgets/graphicsview/qgraphicsview.cpp
@@ -1676,7 +1676,7 @@ void QGraphicsView::setInteractive(bool allowed)
/*!
Returns a pointer to the scene that is currently visualized in the
- view. If no scene is currently visualized, 0 is returned.
+ view. If no scene is currently visualized, \nullptr is returned.
\sa setScene()
*/
diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp
index a4534c73dd..cd647a5db1 100644
--- a/src/widgets/graphicsview/qgraphicswidget.cpp
+++ b/src/widgets/graphicsview/qgraphicswidget.cpp
@@ -159,7 +159,7 @@ QT_BEGIN_NAMESPACE
manage the relationships between parent and child items. These functions
control the stacking order of items as well as their ownership.
- \note The QObject::parent() should always return 0 for QGraphicsWidgets,
+ \note The QObject::parent() should always return \nullptr for QGraphicsWidgets,
but this policy is not strictly defined.
\sa QGraphicsProxyWidget, QGraphicsItem, {Widgets and Layouts}
@@ -473,8 +473,9 @@ relayoutChildrenAndReturn:
*/
/*!
- Sets the widget's contents margins to \a left, \a top, \a right and \a
- bottom.
+ \since 5.14
+
+ Sets the widget's contents margins to \a margins.
Contents margins are used by the assigned layout to define the placement
of subwidgets and layouts. Margins are particularly useful for widgets
@@ -488,23 +489,17 @@ relayoutChildrenAndReturn:
\sa getContentsMargins(), setGeometry()
*/
-void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qreal bottom)
+void QGraphicsWidget::setContentsMargins(QMarginsF margins)
{
Q_D(QGraphicsWidget);
- if (!d->margins && left == 0 && top == 0 && right == 0 && bottom == 0)
+ if (!d->margins && margins.isNull())
return;
d->ensureMargins();
- if (left == d->margins[d->Left]
- && top == d->margins[d->Top]
- && right == d->margins[d->Right]
- && bottom == d->margins[d->Bottom])
+ if (*d->margins == margins)
return;
- d->margins[d->Left] = left;
- d->margins[d->Top] = top;
- d->margins[d->Right] = right;
- d->margins[d->Bottom] = bottom;
+ *d->margins = margins;
if (QGraphicsLayout *l = d->layout)
l->invalidate();
@@ -516,9 +511,20 @@ void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qre
}
/*!
+ \overload
+
+ Sets the widget's contents margins to \a left, \a top, \a right and \a
+ bottom.
+*/
+void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qreal bottom)
+{
+ setContentsMargins({left, top, right, bottom});
+}
+
+/*!
Gets the widget's contents margins. The margins are stored in \a left, \a
top, \a right and \a bottom, as pointers to qreals. Each argument can
- be \e {omitted} by passing 0.
+ be \e {omitted} by passing \nullptr.
\sa setContentsMargins()
*/
@@ -528,18 +534,19 @@ void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right,
if (left || top || right || bottom)
d->ensureMargins();
if (left)
- *left = d->margins[d->Left];
+ *left = d->margins->left();
if (top)
- *top = d->margins[d->Top];
+ *top = d->margins->top();
if (right)
- *right = d->margins[d->Right];
+ *right = d->margins->right();
if (bottom)
- *bottom = d->margins[d->Bottom];
+ *bottom = d->margins->bottom();
}
/*!
- Sets the widget's window frame margins to \a left, \a top, \a right and
- \a bottom. The default frame margins are provided by the style, and they
+ \since 5.14
+ Sets the widget's window frame margins to \a margins.
+ The default frame margins are provided by the style, and they
depend on the current window flags.
If you would like to draw your own window decoration, you can set your
@@ -547,33 +554,36 @@ void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right,
\sa unsetWindowFrameMargins(), getWindowFrameMargins(), windowFrameRect()
*/
-void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom)
+void QGraphicsWidget::setWindowFrameMargins(QMarginsF margins)
{
Q_D(QGraphicsWidget);
- if (!d->windowFrameMargins && left == 0 && top == 0 && right == 0 && bottom == 0)
+ if (!d->windowFrameMargins && margins.isNull())
return;
d->ensureWindowFrameMargins();
- bool unchanged =
- d->windowFrameMargins[d->Left] == left
- && d->windowFrameMargins[d->Top] == top
- && d->windowFrameMargins[d->Right] == right
- && d->windowFrameMargins[d->Bottom] == bottom;
+ const bool unchanged = *d->windowFrameMargins == margins;
if (d->setWindowFrameMargins && unchanged)
return;
if (!unchanged)
prepareGeometryChange();
- d->windowFrameMargins[d->Left] = left;
- d->windowFrameMargins[d->Top] = top;
- d->windowFrameMargins[d->Right] = right;
- d->windowFrameMargins[d->Bottom] = bottom;
+ *d->windowFrameMargins = margins;
d->setWindowFrameMargins = true;
}
/*!
+ \overload
+ Sets the widget's window frame margins to \a left, \a top, \a right and
+ \a bottom.
+*/
+void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom)
+{
+ setWindowFrameMargins({left, top, right, bottom});
+}
+
+/*!
Gets the widget's window frame margins. The margins are stored in \a left,
\a top, \a right and \a bottom as pointers to qreals. Each argument can
- be \e {omitted} by passing 0.
+ be \e {omitted} by passing \nullptr.
\sa setWindowFrameMargins(), windowFrameRect()
*/
@@ -583,13 +593,13 @@ void QGraphicsWidget::getWindowFrameMargins(qreal *left, qreal *top, qreal *righ
if (left || top || right || bottom)
d->ensureWindowFrameMargins();
if (left)
- *left = d->windowFrameMargins[d->Left];
+ *left = d->windowFrameMargins->left();
if (top)
- *top = d->windowFrameMargins[d->Top];
+ *top = d->windowFrameMargins->top();
if (right)
- *right = d->windowFrameMargins[d->Right];
+ *right = d->windowFrameMargins->right();
if (bottom)
- *bottom = d->windowFrameMargins[d->Bottom];
+ *bottom = d->windowFrameMargins->bottom();
}
/*!
@@ -624,8 +634,8 @@ QRectF QGraphicsWidget::windowFrameGeometry() const
{
Q_D(const QGraphicsWidget);
return d->windowFrameMargins
- ? geometry().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top],
- d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom])
+ ? geometry().adjusted(-d->windowFrameMargins->left(), -d->windowFrameMargins->top(),
+ d->windowFrameMargins->right(), d->windowFrameMargins->bottom())
: geometry();
}
@@ -638,8 +648,8 @@ QRectF QGraphicsWidget::windowFrameRect() const
{
Q_D(const QGraphicsWidget);
return d->windowFrameMargins
- ? rect().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top],
- d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom])
+ ? rect().adjusted(-d->windowFrameMargins->left(), -d->windowFrameMargins->top(),
+ d->windowFrameMargins->right(), d->windowFrameMargins->bottom())
: rect();
}
@@ -751,8 +761,8 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c
if (d->layout) {
QSizeF marginSize(0,0);
if (d->margins) {
- marginSize = QSizeF(d->margins[d->Left] + d->margins[d->Right],
- d->margins[d->Top] + d->margins[d->Bottom]);
+ marginSize = QSizeF(d->margins->left() + d->margins->right(),
+ d->margins->top() + d->margins->bottom());
}
sh = d->layout->effectiveSizeHint(which, constraint - marginSize);
sh += marginSize;
@@ -780,7 +790,7 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c
\brief The layout of the widget
Any existing layout manager is deleted before the new layout is assigned. If
- \a layout is 0, the widget is left without a layout. Existing subwidgets'
+ \a layout is \nullptr, the widget is left without a layout. Existing subwidgets'
geometries will remain unaffected.
QGraphicsWidget takes ownership of \a layout.
@@ -792,7 +802,7 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c
explicitly managed by \a layout remain unaffected by the layout after
it has been assigned to this widget.
- If no layout is currently managing this widget, layout() will return 0.
+ If no layout is currently managing this widget, layout() will return \nullptr.
*/
@@ -803,8 +813,8 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c
*/
/*!
- Returns this widget's layout, or 0 if no layout is currently managing this
- widget.
+ Returns this widget's layout, or \nullptr if no layout is currently
+ managing this widget.
\sa setLayout()
*/
@@ -818,7 +828,7 @@ QGraphicsLayout *QGraphicsWidget::layout() const
\fn void QGraphicsWidget::setLayout(QGraphicsLayout *layout)
Sets the layout for this widget to \a layout. Any existing layout manager
- is deleted before the new layout is assigned. If \a layout is 0, the
+ is deleted before the new layout is assigned. If \a layout is \nullptr, the
widget is left without a layout. Existing subwidgets' geometries will
remain unaffected.
@@ -937,11 +947,11 @@ QStyle *QGraphicsWidget::style() const
Sets the widget's style to \a style. QGraphicsWidget does \e not take
ownership of \a style.
- If no style is assigned, or \a style is 0, the widget will use
+ If no style is assigned, or \a style is \nullptr, the widget will use
QGraphicsScene::style() (if this has been set). Otherwise the widget will
use QApplication::style().
- This function sets the Qt::WA_SetStyle attribute if \a style is not 0;
+ This function sets the Qt::WA_SetStyle attribute if \a style is not \nullptr;
otherwise it clears the attribute.
\sa style()
@@ -1232,6 +1242,9 @@ QVariant QGraphicsWidget::propertyChange(const QString &propertyName, const QVar
event() or in any of the convenience functions; you should not have to
reimplement this function in a subclass of QGraphicsWidget.
+ Returns \c true if \a event has been recognized and processed; otherwise,
+ returns \c false.
+
\sa QGraphicsItem::sceneEvent()
*/
bool QGraphicsWidget::sceneEvent(QEvent *event)
@@ -1317,7 +1330,7 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
const qreal cornerMargin = 20;
//### Not sure of this one, it should be the same value for all edges.
const qreal windowFrameWidth = d->windowFrameMargins
- ? d->windowFrameMargins[d->Left] : 0;
+ ? d->windowFrameMargins->left() : 0;
Qt::WindowFrameSection s = Qt::NoSection;
if (x <= left + cornerMargin) {
@@ -1344,7 +1357,7 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
if (s == Qt::NoSection) {
QRectF r1 = r;
r1.setHeight(d->windowFrameMargins
- ? d->windowFrameMargins[d->Top] : 0);
+ ? d->windowFrameMargins->top() : 0);
if (r1.contains(pos))
s = Qt::TitleBarArea;
}
@@ -1871,7 +1884,7 @@ void QGraphicsWidget::setFocusPolicy(Qt::FocusPolicy policy)
/*!
If this widget, a child or descendant of this widget currently has input
focus, this function will return a pointer to that widget. If
- no descendant widget has input focus, 0 is returned.
+ no descendant widget has input focus, \nullptr is returned.
\sa QGraphicsItem::focusItem(), QWidget::focusWidget()
*/
@@ -1880,7 +1893,7 @@ QGraphicsWidget *QGraphicsWidget::focusWidget() const
Q_D(const QGraphicsWidget);
if (d->subFocusItem && d->subFocusItem->d_ptr->isWidget)
return static_cast<QGraphicsWidget *>(d->subFocusItem);
- return 0;
+ return nullptr;
}
#ifndef QT_NO_SHORTCUT
@@ -2022,7 +2035,7 @@ void QGraphicsWidget::addActions(QList<QAction *> actions)
\since 4.5
Inserts the action \a action to this widget's list of actions,
- before the action \a before. It appends the action if \a before is 0 or
+ before the action \a before. It appends the action if \a before is \nullptr or
\a before is not a valid action for this widget.
A QGraphicsWidget should only have one of each action.
@@ -2062,7 +2075,7 @@ void QGraphicsWidget::insertAction(QAction *before, QAction *action)
\since 4.5
Inserts the actions \a actions to this widget's list of actions,
- before the action \a before. It appends the action if \a before is 0 or
+ before the action \a before. It appends the action if \a before is \nullptr or
\a before is not a valid action for this widget.
A QGraphicsWidget can have at most one of each action.
@@ -2131,9 +2144,9 @@ QList<QAction *> QGraphicsWidget::actions() const
\snippet code/src_gui_graphicsview_qgraphicswidget.cpp 2
- If \a first is 0, this indicates that \a second should be the first widget
+ If \a first is \nullptr, this indicates that \a second should be the first widget
to receive input focus should the scene gain Tab focus (i.e., the user
- hits Tab so that focus passes into the scene). If \a second is 0, this
+ hits Tab so that focus passes into the scene). If \a second is \nullptr, this
indicates that \a first should be the first widget to gain focus if the
scene gained BackTab focus.
@@ -2306,7 +2319,7 @@ void QGraphicsWidget::paintWindowFrame(QPainter *painter, const QStyleOptionGrap
QStyleHintReturnMask mask;
bool setMask = style()->styleHint(QStyle::SH_WindowFrame_Mask, &bar, widget, &mask) && !mask.region.isEmpty();
bool hasBorder = !style()->styleHint(QStyle::SH_TitleBar_NoBorder, &bar, widget);
- int frameWidth = style()->pixelMetric(QStyle::PM_MDIFrameWidth, &bar, widget);
+ int frameWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, &bar, widget);
if (setMask) {
painter->save();
painter->setClipRegion(mask.region, Qt::IntersectClip);
diff --git a/src/widgets/graphicsview/qgraphicswidget.h b/src/widgets/graphicsview/qgraphicswidget.h
index 481fb55db3..8223b921c9 100644
--- a/src/widgets/graphicsview/qgraphicswidget.h
+++ b/src/widgets/graphicsview/qgraphicswidget.h
@@ -111,9 +111,11 @@ public:
inline QRectF rect() const { return QRectF(QPointF(), size()); }
void setContentsMargins(qreal left, qreal top, qreal right, qreal bottom);
+ void setContentsMargins(QMarginsF margins);
void getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const override;
void setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom);
+ void setWindowFrameMargins(QMarginsF margins);
void getWindowFrameMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const;
void unsetWindowFrameMargins();
QRectF windowFrameGeometry() const;
diff --git a/src/widgets/graphicsview/qgraphicswidget_p.cpp b/src/widgets/graphicsview/qgraphicswidget_p.cpp
index 1514fca456..ce027c1319 100644
--- a/src/widgets/graphicsview/qgraphicswidget_p.cpp
+++ b/src/widgets/graphicsview/qgraphicswidget_p.cpp
@@ -51,6 +51,8 @@
#include <QtWidgets/QStyleOptionTitleBar>
#include <QtWidgets/QGraphicsSceneMouseEvent>
+#include <private/qmemory_p.h>
+
QT_BEGIN_NAMESPACE
void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags)
@@ -109,8 +111,6 @@ QGraphicsWidgetPrivate::QGraphicsWidgetPrivate()
QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate()
{
// Remove any lazily allocated data
- delete[] margins;
- delete[] windowFrameMargins;
delete windowData;
}
@@ -122,11 +122,8 @@ QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate()
*/
void QGraphicsWidgetPrivate::ensureMargins() const
{
- if (!margins) {
- margins = new qreal[4];
- for (int i = 0; i < 4; ++i)
- margins[i] = 0;
- }
+ if (!margins)
+ margins = qt_make_unique<QMarginsF>();
}
/*!
@@ -137,11 +134,8 @@ void QGraphicsWidgetPrivate::ensureMargins() const
*/
void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const
{
- if (!windowFrameMargins) {
- windowFrameMargins = new qreal[4];
- for (int i = 0; i < 4; ++i)
- windowFrameMargins[i] = 0;
- }
+ if (!windowFrameMargins)
+ windowFrameMargins = qt_make_unique<QMarginsF>();
}
/*!
@@ -372,8 +366,8 @@ void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEve
bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar));
QPointF pos = event->pos();
if (windowFrameMargins) {
- pos.rx() += windowFrameMargins[Left];
- pos.ry() += windowFrameMargins[Top];
+ pos.rx() += windowFrameMargins->left();
+ pos.ry() += windowFrameMargins->top();
}
bar.subControls = QStyle::SC_TitleBarCloseButton;
if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar,
@@ -669,8 +663,8 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent
QStyleOptionTitleBar bar;
// make sure that the coordinates (rect and pos) we send to the style are positive.
if (windowFrameMargins) {
- pos.rx() += windowFrameMargins[Left];
- pos.ry() += windowFrameMargins[Top];
+ pos.rx() += windowFrameMargins->left();
+ pos.ry() += windowFrameMargins->top();
}
initStyleOptionTitleBar(&bar);
bar.rect = q->windowFrameRect().toRect();
diff --git a/src/widgets/graphicsview/qgraphicswidget_p.h b/src/widgets/graphicsview/qgraphicswidget_p.h
index 505a2a24c0..5e0fdb693b 100644
--- a/src/widgets/graphicsview/qgraphicswidget_p.h
+++ b/src/widgets/graphicsview/qgraphicswidget_p.h
@@ -60,6 +60,8 @@
#include <QtWidgets/qsizepolicy.h>
#include <QtWidgets/qstyle.h>
+#include <memory>
+
QT_REQUIRE_CONFIG(graphicsview);
QT_BEGIN_NAMESPACE
@@ -78,11 +80,10 @@ public:
qreal titleBarHeight(const QStyleOptionTitleBar &options) const;
// Margins
- enum {Left, Top, Right, Bottom};
- mutable qreal *margins;
+ mutable std::unique_ptr<QMarginsF> margins;
void ensureMargins() const;
- void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene = 0);
+ void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene = nullptr);
void setLayout_helper(QGraphicsLayout *l);
// Layouts
@@ -193,7 +194,7 @@ public:
void ensureWindowData();
bool setWindowFrameMargins;
- mutable qreal *windowFrameMargins;
+ mutable std::unique_ptr<QMarginsF> windowFrameMargins;
void ensureWindowFrameMargins() const;
#ifndef QT_NO_ACTION
diff --git a/src/widgets/graphicsview/qsimplex_p.cpp b/src/widgets/graphicsview/qsimplex_p.cpp
index e6ffa856f1..e18f1fa4c4 100644
--- a/src/widgets/graphicsview/qsimplex_p.cpp
+++ b/src/widgets/graphicsview/qsimplex_p.cpp
@@ -164,7 +164,7 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> &newConstraints)
for (auto it = v.cbegin(), end = v.cend(); it != end; ++it)
variablesSet.insert(it.key());
}
- variables = variablesSet.toList();
+ variables = variablesSet.values();
// Set Variables reverse mapping
// We also need to be able to find the index for a given variable, to do that
diff --git a/src/widgets/graphicsview/qsimplex_p.h b/src/widgets/graphicsview/qsimplex_p.h
index 2342da2437..a69cef6115 100644
--- a/src/widgets/graphicsview/qsimplex_p.h
+++ b/src/widgets/graphicsview/qsimplex_p.h
@@ -82,7 +82,7 @@ struct QSimplexVariable
*/
struct QSimplexConstraint
{
- QSimplexConstraint() : constant(0), ratio(Equal), artificial(0) {}
+ QSimplexConstraint() : constant(0), ratio(Equal), artificial(nullptr) {}
enum Ratio {
LessOrEqual = 0,
@@ -150,7 +150,7 @@ struct QSimplexConstraint
class QSimplex
{
- Q_DISABLE_COPY(QSimplex)
+ Q_DISABLE_COPY_MOVE(QSimplex)
public:
QSimplex();
~QSimplex();
diff --git a/src/widgets/itemviews/qabstractitemdelegate.cpp b/src/widgets/itemviews/qabstractitemdelegate.cpp
index 50668b3251..31dde8832b 100644
--- a/src/widgets/itemviews/qabstractitemdelegate.cpp
+++ b/src/widgets/itemviews/qabstractitemdelegate.cpp
@@ -88,7 +88,7 @@ QT_BEGIN_NAMESPACE
and is part of Qt's \l{Model/View Programming}{model/view framework}.
To render an item in a custom way, you must implement paint() and
- sizeHint(). The QItemDelegate class provides default implementations for
+ sizeHint(). The QStyledItemDelegate class provides default implementations for
these functions; if you do not need custom rendering, subclass that
class instead.
@@ -115,7 +115,7 @@ QT_BEGIN_NAMESPACE
The second approach is to handle user events directly by reimplementing
editorEvent().
- \sa {model-view-programming}{Model/View Programming}, QItemDelegate,
+ \sa {model-view-programming}{Model/View Programming}, QStyledItemDelegate,
{Pixelator Example}, QStyledItemDelegate, QStyle
*/
@@ -345,6 +345,7 @@ bool QAbstractItemDelegate::editorEvent(QEvent *,
return false;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
@@ -364,6 +365,7 @@ QString QAbstractItemDelegate::elidedText(const QFontMetrics &fontMetrics, int w
{
return fontMetrics.elidedText(text, mode, width);
}
+#endif
/*!
\since 4.3
diff --git a/src/widgets/itemviews/qabstractitemdelegate.h b/src/widgets/itemviews/qabstractitemdelegate.h
index 575728e806..5696e55691 100644
--- a/src/widgets/itemviews/qabstractitemdelegate.h
+++ b/src/widgets/itemviews/qabstractitemdelegate.h
@@ -103,8 +103,11 @@ public:
const QStyleOptionViewItem &option,
const QModelIndex &index);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QFontMetrics::elidedText() instead")
static QString elidedText(const QFontMetrics &fontMetrics, int width,
Qt::TextElideMode mode, const QString &text);
+#endif
virtual bool helpEvent(QHelpEvent *event,
QAbstractItemView *view,
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index e1e45143b4..1d1c144bb8 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -940,8 +940,8 @@ void QAbstractItemView::setItemDelegateForRow(int row, QAbstractItemDelegate *de
\since 4.2
Returns the item delegate used by this view and model for the given \a row,
- or 0 if no delegate has been assigned. You can call itemDelegate() to get a
- pointer to the current delegate for a given index.
+ or \nullptr if no delegate has been assigned. You can call itemDelegate()
+ to get a pointer to the current delegate for a given index.
\sa setItemDelegateForRow(), itemDelegateForColumn(), setItemDelegate()
*/
@@ -1689,6 +1689,9 @@ bool QAbstractItemView::event(QEvent *event)
This? mode, if the given \a event is a QEvent::ToolTip,or a
QEvent::WhatsThis. It passes all other
events on to its base class viewportEvent() handler.
+
+ Returns \c true if \a event has been recognized and processed; otherwise,
+ returns \c false.
*/
bool QAbstractItemView::viewportEvent(QEvent *event)
{
@@ -2438,8 +2441,14 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
break;
case Qt::Key_Space:
case Qt::Key_Select:
- if (!edit(currentIndex(), AnyKeyPressed, event) && d->selectionModel)
- d->selectionModel->select(currentIndex(), selectionCommand(currentIndex(), event));
+ if (!edit(currentIndex(), AnyKeyPressed, event)) {
+ if (d->selectionModel)
+ d->selectionModel->select(currentIndex(), selectionCommand(currentIndex(), event));
+ if (event->key() == Qt::Key_Space) {
+ keyboardSearch(event->text());
+ event->accept();
+ }
+ }
#ifdef QT_KEYPAD_NAVIGATION
if ( event->key()==Qt::Key_Select ) {
// Also do Key_Enter action.
@@ -2915,6 +2924,7 @@ void QAbstractItemView::editorDestroyed(QObject *editor)
setState(NoState);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
Sets the horizontal scroll bar's steps per item to \a steps.
@@ -2972,6 +2982,7 @@ int QAbstractItemView::verticalStepsPerItem() const
{
return 1;
}
+#endif
/*!
Moves to and selects the item best matching the string \a search.
@@ -3205,7 +3216,7 @@ bool QAbstractItemView::isPersistentEditorOpen(const QModelIndex &index) const
This function should only be used to display static content within the
visible area corresponding to an item of data. If you want to display
custom dynamic content or implement a custom editor widget, subclass
- QItemDelegate instead.
+ QStyledItemDelegate instead.
\sa {Delegate Classes}
*/
@@ -4450,15 +4461,8 @@ QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes,
if (paintPairs.isEmpty())
return QPixmap();
- qreal scale = 1.0f;
-
- Q_Q(const QAbstractItemView);
- QWidget *window = q->window();
- if (window) {
- QWindow *windowHandle = window->windowHandle();
- if (windowHandle)
- scale = windowHandle->devicePixelRatio();
- }
+ QWindow *window = windowHandle(WindowHandleMode::Closest);
+ const qreal scale = window ? window->devicePixelRatio() : qreal(1);
QPixmap pixmap(r->size() * scale);
pixmap.setDevicePixelRatio(scale);
diff --git a/src/widgets/itemviews/qabstractitemview.h b/src/widgets/itemviews/qabstractitemview.h
index 981582c166..be8fa07c94 100644
--- a/src/widgets/itemviews/qabstractitemview.h
+++ b/src/widgets/itemviews/qabstractitemview.h
@@ -272,10 +272,12 @@ Q_SIGNALS:
protected:
QAbstractItemView(QAbstractItemViewPrivate &, QWidget *parent = nullptr);
- void setHorizontalStepsPerItem(int steps);
- int horizontalStepsPerItem() const;
- void setVerticalStepsPerItem(int steps);
- int verticalStepsPerItem() const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED void setHorizontalStepsPerItem(int steps);
+ QT_DEPRECATED int horizontalStepsPerItem() const;
+ QT_DEPRECATED void setVerticalStepsPerItem(int steps);
+ QT_DEPRECATED int verticalStepsPerItem() const;
+#endif
enum CursorAction { MoveUp, MoveDown, MoveLeft, MoveRight,
MoveHome, MoveEnd, MovePageUp, MovePageDown,
diff --git a/src/widgets/itemviews/qcolumnview.cpp b/src/widgets/itemviews/qcolumnview.cpp
index 1fe17721ba..a4eed2d885 100644
--- a/src/widgets/itemviews/qcolumnview.cpp
+++ b/src/widgets/itemviews/qcolumnview.cpp
@@ -801,7 +801,7 @@ void QColumnView::initializeColumn(QAbstractItemView *column) const
}
/*!
- Returns the preview widget, or 0 if there is none.
+ Returns the preview widget, or \nullptr if there is none.
\sa setPreviewWidget(), updatePreviewWidget()
*/
diff --git a/src/widgets/itemviews/qcolumnview_p.h b/src/widgets/itemviews/qcolumnview_p.h
index 9f0d2a40dc..c60579255e 100644
--- a/src/widgets/itemviews/qcolumnview_p.h
+++ b/src/widgets/itemviews/qcolumnview_p.h
@@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE
class QColumnViewPreviewColumn : public QAbstractItemView {
public:
- explicit QColumnViewPreviewColumn(QWidget *parent) : QAbstractItemView(parent), previewWidget(0) {
+ explicit QColumnViewPreviewColumn(QWidget *parent) : QAbstractItemView(parent), previewWidget(nullptr) {
}
void setPreviewWidget(QWidget *widget) {
@@ -181,11 +181,12 @@ public:
/*!
* This is a delegate that will paint the triangle
*/
+// ### Qt6: QStyledItemDelegate
class QColumnViewDelegate : public QItemDelegate
{
public:
- explicit QColumnViewDelegate(QObject *parent = 0) : QItemDelegate(parent) {}
+ explicit QColumnViewDelegate(QObject *parent = nullptr) : QItemDelegate(parent) {}
~QColumnViewDelegate() {}
void paint(QPainter *painter,
diff --git a/src/widgets/itemviews/qcolumnviewgrip_p.h b/src/widgets/itemviews/qcolumnviewgrip_p.h
index 7e2793074b..4311edbeb4 100644
--- a/src/widgets/itemviews/qcolumnviewgrip_p.h
+++ b/src/widgets/itemviews/qcolumnviewgrip_p.h
@@ -68,12 +68,12 @@ Q_SIGNALS:
void gripMoved(int offset);
public:
- explicit QColumnViewGrip(QWidget *parent = 0);
+ explicit QColumnViewGrip(QWidget *parent = nullptr);
~QColumnViewGrip();
int moveGrip(int offset);
protected:
- QColumnViewGrip(QColumnViewGripPrivate &, QWidget *parent = 0, Qt::WindowFlags f = 0);
+ QColumnViewGrip(QColumnViewGripPrivate &, QWidget *parent = nullptr, Qt::WindowFlags f = nullptr);
void paintEvent(QPaintEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
@@ -82,7 +82,7 @@ protected:
private:
Q_DECLARE_PRIVATE(QColumnViewGrip)
- Q_DISABLE_COPY(QColumnViewGrip)
+ Q_DISABLE_COPY_MOVE(QColumnViewGrip)
};
class QColumnViewGripPrivate : public QWidgetPrivate
diff --git a/src/widgets/itemviews/qdatawidgetmapper.cpp b/src/widgets/itemviews/qdatawidgetmapper.cpp
index 1f0dbff7a9..125ee73194 100644
--- a/src/widgets/itemviews/qdatawidgetmapper.cpp
+++ b/src/widgets/itemviews/qdatawidgetmapper.cpp
@@ -324,6 +324,7 @@ void QDataWidgetMapperPrivate::_q_modelDestroyed()
QDataWidgetMapper::QDataWidgetMapper(QObject *parent)
: QObject(*new QDataWidgetMapperPrivate, parent)
{
+ // ### Qt6: QStyledItemDelegate
setItemDelegate(new QItemDelegate(this));
}
diff --git a/src/widgets/itemviews/qdirmodel.cpp b/src/widgets/itemviews/qdirmodel.cpp
index 78fc623fb5..b94c31fb42 100644
--- a/src/widgets/itemviews/qdirmodel.cpp
+++ b/src/widgets/itemviews/qdirmodel.cpp
@@ -1252,11 +1252,10 @@ void QDirModelPrivate::restorePersistentIndexes()
for (const SavedPersistent &sp : qAsConst(savedPersistent)) {
QPersistentModelIndexData *data = sp.data;
QModelIndex idx = q->index(sp.path, sp.column);
- if (idx != data->index || data->model == 0) {
+ if (idx != data->index || data->index.model() == nullptr) {
//data->model may be equal to 0 if the model is getting destroyed
persistent.indexes.remove(data->index);
data->index = idx;
- data->model = q;
if (idx.isValid())
persistent.indexes.insert(idx, data);
}
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index ed418f143c..1fcd5bdef2 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -2286,13 +2286,15 @@ void QHeaderViewPrivate::_q_sectionsChanged(const QList<QPersistentModelIndex> &
: index.row());
// the new visualIndices are already adjusted / reset by initializeSections()
const int newVisualIndex = visualIndex(newLogicalIndex);
- auto &newSection = sectionItems[newVisualIndex];
- newSection = item.section;
-
- if (newSection.isHidden) {
- // otherwise setSectionHidden will return without doing anything
- newSection.isHidden = false;
- q->setSectionHidden(newLogicalIndex, true);
+ if (newVisualIndex < sectionItems.count()) {
+ auto &newSection = sectionItems[newVisualIndex];
+ newSection = item.section;
+
+ if (newSection.isHidden) {
+ // otherwise setSectionHidden will return without doing anything
+ newSection.isHidden = false;
+ q->setSectionHidden(newLogicalIndex, true);
+ }
}
}
@@ -2324,9 +2326,10 @@ void QHeaderView::initializeSections()
if (stretchLastSection()) // we've already gotten the size hint
d->maybeRestorePrevLastSectionAndStretchLast();
- //make sure we update the hidden sections
+ // make sure we update the hidden sections
+ // simulate remove from newCount to oldCount
if (newCount < oldCount)
- d->updateHiddenSections(0, newCount-1);
+ d->updateHiddenSections(newCount, oldCount);
}
}
@@ -3119,9 +3122,25 @@ void QHeaderView::scrollContentsBy(int dx, int dy)
\reimp
\internal
*/
-void QHeaderView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &)
+void QHeaderView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
Q_D(QHeaderView);
+ if (!roles.isEmpty()) {
+ const auto doesRoleAffectSize = [](int role) -> bool {
+ switch (role) {
+ case Qt::DisplayRole:
+ case Qt::DecorationRole:
+ case Qt::SizeHintRole:
+ case Qt::FontRole:
+ return true;
+ default:
+ // who knows what a subclass or custom style might do
+ return role >= Qt::UserRole;
+ }
+ };
+ if (std::none_of(roles.begin(), roles.end(), doesRoleAffectSize))
+ return;
+ }
d->invalidateCachedSizeHint();
if (d->hasAutoResizeSections()) {
bool resizeRequired = d->globalResizeMode == ResizeToContents;
@@ -3877,9 +3896,9 @@ void QHeaderViewPrivate::updateDefaultSectionSizeFromStyle()
void QHeaderViewPrivate::recalcSectionStartPos() const // linear (but fast)
{
int pixelpos = 0;
- for (QVector<SectionItem>::const_iterator i = sectionItems.constBegin(); i != sectionItems.constEnd(); ++i) {
- i->calculated_startpos = pixelpos; // write into const mutable
- pixelpos += i->size;
+ for (const SectionItem &i : sectionItems) {
+ i.calculated_startpos = pixelpos; // write into const mutable
+ pixelpos += i.size;
}
sectionStartposRecalc = false;
}
diff --git a/src/widgets/itemviews/qheaderview_p.h b/src/widgets/itemviews/qheaderview_p.h
index d9fc1baec5..766adef36d 100644
--- a/src/widgets/itemviews/qheaderview_p.h
+++ b/src/widgets/itemviews/qheaderview_p.h
@@ -102,7 +102,7 @@ public:
lastSectionLogicalIdx(-1), // Only trust when we stretch last section
sectionIndicatorOffset(0),
#if QT_CONFIG(label)
- sectionIndicator(0),
+ sectionIndicator(nullptr),
#endif
globalResizeMode(QHeaderView::Interactive),
sectionStartposRecalc(true),
diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp
index dff4cc4593..460764f1b8 100644
--- a/src/widgets/itemviews/qitemdelegate.cpp
+++ b/src/widgets/itemviews/qitemdelegate.cpp
@@ -266,7 +266,7 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
\row \li \l Qt::AccessibleDescriptionRole \li QString
\row \li \l Qt::AccessibleTextRole \li QString
\endomit
- \row \li \l Qt::BackgroundRole \li QBrush
+ \row \li \l Qt::BackgroundRole \li QBrush (\since 4.2)
\row \li \l Qt::BackgroundColorRole \li QColor (obsolete; use Qt::BackgroundRole instead)
\row \li \l Qt::CheckStateRole \li Qt::CheckState
\row \li \l Qt::DecorationRole \li QIcon, QPixmap and QColor
@@ -278,7 +278,7 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
\row \li \l Qt::StatusTipRole \li
\endomit
\row \li \l Qt::TextAlignmentRole \li Qt::Alignment
- \row \li \l Qt::ForegroundRole \li QBrush
+ \row \li \l Qt::ForegroundRole \li QBrush (\since 4.2)
\row \li \l Qt::TextColorRole \li QColor (obsolete; use Qt::ForegroundRole instead)
\omit
\row \li \l Qt::ToolTipRole
@@ -724,8 +724,8 @@ void QItemDelegate::drawDecoration(QPainter *painter, const QStyleOptionViewItem
QPoint p = QStyle::alignedRect(option.direction, option.decorationAlignment,
pixmap.size(), rect).topLeft();
if (option.state & QStyle::State_Selected) {
- QPixmap *pm = selected(pixmap, option.palette, option.state & QStyle::State_Enabled);
- painter->drawPixmap(p, *pm);
+ const QPixmap pm = selectedPixmap(pixmap, option.palette, option.state & QStyle::State_Enabled);
+ painter->drawPixmap(p, pm);
} else {
painter->drawPixmap(p, pixmap);
}
@@ -789,7 +789,7 @@ void QItemDelegate::drawCheck(QPainter *painter,
const QWidget *widget = d->widget(option);
QStyle *style = widget ? widget->style() : QApplication::style();
- style->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &opt, painter, widget);
+ style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &opt, painter, widget);
}
/*!
@@ -1001,17 +1001,32 @@ static QString qPixmapSerial(quint64 i, bool enabled)
return QString((const QChar *)ptr, int(&arr[sizeof(arr) / sizeof(ushort)] - ptr));
}
+#if QT_DEPRECATED_SINCE(5, 13)
+QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette, bool enabled) const
+{
+ const QString key = qPixmapSerial(pixmap.cacheKey(), enabled);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+ QPixmap *pm = QPixmapCache::find(key);
+ if (pm)
+ return pm;
+ selectedPixmap(pixmap, palette, enabled);
+ return QPixmapCache::find(key);
+QT_WARNING_POP
+}
+#endif
+
/*!
\internal
Returns the selected version of the given \a pixmap using the given \a palette.
The \a enabled argument decides whether the normal or disabled highlight color of
the palette is used.
*/
-QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette, bool enabled) const
+QPixmap QItemDelegate::selectedPixmap(const QPixmap &pixmap, const QPalette &palette, bool enabled)
{
- QString key = qPixmapSerial(pixmap.cacheKey(), enabled);
- QPixmap *pm = QPixmapCache::find(key);
- if (!pm) {
+ const QString key = qPixmapSerial(pixmap.cacheKey(), enabled);
+ QPixmap pm;
+ if (!QPixmapCache::find(key, &pm)) {
QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
QColor color = palette.color(enabled ? QPalette::Normal : QPalette::Disabled,
@@ -1023,13 +1038,12 @@ QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette,
painter.fillRect(0, 0, img.width(), img.height(), color);
painter.end();
- QPixmap selected = QPixmap(QPixmap::fromImage(img));
- int n = (img.sizeInBytes() >> 10) + 1;
+ pm = QPixmap(QPixmap::fromImage(img));
+ const int n = (img.sizeInBytes() >> 10) + 1;
if (QPixmapCache::cacheLimit() < n)
QPixmapCache::setCacheLimit(n);
- QPixmapCache::insert(key, selected);
- pm = QPixmapCache::find(key);
+ QPixmapCache::insert(key, pm);
}
return pm;
}
@@ -1089,7 +1103,7 @@ QRect QItemDelegate::doCheck(const QStyleOptionViewItem &option,
opt.rect = bounding;
const QWidget *widget = d->widget(option); // cast
QStyle *style = widget ? widget->style() : QApplication::style();
- return style->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, widget);
+ return style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &opt, widget);
}
return QRect();
}
diff --git a/src/widgets/itemviews/qitemdelegate.h b/src/widgets/itemviews/qitemdelegate.h
index 539dec4374..e504615fb2 100644
--- a/src/widgets/itemviews/qitemdelegate.h
+++ b/src/widgets/itemviews/qitemdelegate.h
@@ -113,7 +113,12 @@ protected:
const QStyleOptionViewItem &option) const;
QPixmap decoration(const QStyleOptionViewItem &option, const QVariant &variant) const;
+
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use selectedPixmap() instead")
QPixmap *selected(const QPixmap &pixmap, const QPalette &palette, bool enabled) const;
+#endif
+ static QPixmap selectedPixmap(const QPixmap &pixmap, const QPalette &palette, bool enabled);
QRect doCheck(const QStyleOptionViewItem &option, const QRect &bounding,
const QVariant &variant) const;
diff --git a/src/widgets/itemviews/qitemeditorfactory.cpp b/src/widgets/itemviews/qitemeditorfactory.cpp
index 1465ee71a7..2d49dd4421 100644
--- a/src/widgets/itemviews/qitemeditorfactory.cpp
+++ b/src/widgets/itemviews/qitemeditorfactory.cpp
@@ -122,7 +122,7 @@ Q_SIGNALS:
\inmodule QtWidgets
When editing data in an item view, editors are created and
- displayed by a delegate. QItemDelegate, which is the delegate by
+ displayed by a delegate. QStyledItemDelegate, which is the delegate by
default installed on Qt's item views, uses a QItemEditorFactory to
create editors for it. A default unique instance provided by
QItemEditorFactory is used by all item delegates. If you set a
@@ -156,7 +156,7 @@ Q_SIGNALS:
Additional editors can be registered with the registerEditor() function.
- \sa QItemDelegate, {Model/View Programming}, {Color Editor Factory Example}
+ \sa QStyledItemDelegate, {Model/View Programming}, {Color Editor Factory Example}
*/
/*!
@@ -379,7 +379,7 @@ void QItemEditorFactory::setDefaultFactory(QItemEditorFactory *factory)
QItemEditorCreatorBase objects are specialized widget factories that
provide editor widgets for one particular QVariant data type. They
are used by QItemEditorFactory to create editors for
- \l{QItemDelegate}s. Creator bases must be registered with
+ \l{QStyledItemDelegate}s. Creator bases must be registered with
QItemEditorFactory::registerEditor().
An editor should provide a user property for the data it edits.
@@ -461,7 +461,7 @@ QItemEditorCreatorBase::~QItemEditorCreatorBase()
\snippet code/src_gui_itemviews_qitemeditorfactory.cpp 1
The constructor takes the name of the property that contains the
- editing data. QItemDelegate can then access the property by name
+ editing data. QStyledItemDelegate can then access the property by name
when it sets and retrieves editing data. Only use this class if
your editor does not define a user property (using the USER
keyword in the Q_PROPERTY macro). If the widget has a user
@@ -476,7 +476,7 @@ QItemEditorCreatorBase::~QItemEditorCreatorBase()
Constructs an editor creator object using \a valuePropertyName
as the name of the property to be used for editing. The
- property name is used by QItemDelegate when setting and
+ property name is used by QStyledItemDelegate when setting and
getting editor data.
Note that the \a valuePropertyName is only used if the editor
@@ -512,11 +512,11 @@ QItemEditorCreatorBase::~QItemEditorCreatorBase()
\snippet code/src_gui_itemviews_qitemeditorfactory.cpp 2
Setting the \c editorFactory created above in an item delegate via
- QItemDelegate::setItemEditorFactory() makes sure that all values of type
+ QStyledItemDelegate::setItemEditorFactory() makes sure that all values of type
QVariant::DateTime will be edited in \c{MyFancyDateTimeEdit}.
The editor must provide a user property that will contain the
- editing data. The property is used by \l{QItemDelegate}s to set
+ editing data. The property is used by \l{QStyledItemDelegate}s to set
and retrieve the data (using Qt's \l{Meta-Object
System}{meta-object system}). You set the user property with
the USER keyword:
@@ -524,7 +524,7 @@ QItemEditorCreatorBase::~QItemEditorCreatorBase()
\snippet code/src_gui_itemviews_qitemeditorfactory.cpp 3
\sa QItemEditorCreatorBase, QItemEditorCreator,
- QItemEditorFactory, QItemDelegate, {Color Editor Factory Example}
+ QItemEditorFactory, QStyledItemDelegate, {Color Editor Factory Example}
*/
/*!
diff --git a/src/widgets/itemviews/qitemeditorfactory.h b/src/widgets/itemviews/qitemeditorfactory.h
index f2610ad3de..118f6e45e8 100644
--- a/src/widgets/itemviews/qitemeditorfactory.h
+++ b/src/widgets/itemviews/qitemeditorfactory.h
@@ -66,8 +66,8 @@ class QItemEditorCreator : public QItemEditorCreatorBase
{
public:
inline explicit QItemEditorCreator(const QByteArray &valuePropertyName);
- inline QWidget *createWidget(QWidget *parent) const { return new T(parent); }
- inline QByteArray valuePropertyName() const { return propertyName; }
+ inline QWidget *createWidget(QWidget *parent) const override { return new T(parent); }
+ inline QByteArray valuePropertyName() const override { return propertyName; }
private:
QByteArray propertyName;
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp
index e07514f297..641b15f85b 100644
--- a/src/widgets/itemviews/qlistview.cpp
+++ b/src/widgets/itemviews/qlistview.cpp
@@ -2263,8 +2263,8 @@ int QListModeViewBase::verticalScrollToValue(int index, QListView::ScrollHint hi
} else {
int scrollBarValue = verticalScrollBar()->value();
int numHidden = 0;
- for (int i = 0; i < flowPositions.count() - 1 && i <= scrollBarValue; ++i)
- if (isHidden(i))
+ for (const auto &idx : qAsConst(dd->hiddenRows))
+ if (idx.row() <= scrollBarValue)
++numHidden;
value = qBound(0, scrollValueMap.at(verticalScrollBar()->value()) - numHidden, flowPositions.count() - 1);
}
@@ -2704,21 +2704,24 @@ int QListModeViewBase::perItemScrollToValue(int index, int scrollValue, int view
return scrollValue;
itemExtent += spacing();
- QVector<int> visibleFlowPositions;
- visibleFlowPositions.reserve(flowPositions.count() - 1);
- for (int i = 0; i < flowPositions.count() - 1; i++) { // flowPositions count is +1 larger than actual row count
- if (!isHidden(i))
- visibleFlowPositions.append(flowPositions.at(i));
- }
-
+ QVector<int> hiddenRows = dd->hiddenRowIds();
+ std::sort(hiddenRows.begin(), hiddenRows.end());
+ int hiddenRowsBefore = 0;
+ for (int i = 0; i < hiddenRows.size() - 1; ++i)
+ if (hiddenRows.at(i) > index + hiddenRowsBefore)
+ break;
+ else
+ ++hiddenRowsBefore;
if (!wrap) {
int topIndex = index;
const int bottomIndex = topIndex;
- const int bottomCoordinate = visibleFlowPositions.at(index);
-
+ const int bottomCoordinate = flowPositions.at(index + hiddenRowsBefore);
while (topIndex > 0 &&
- (bottomCoordinate - visibleFlowPositions.at(topIndex - 1) + itemExtent) <= (viewportSize)) {
+ (bottomCoordinate - flowPositions.at(topIndex + hiddenRowsBefore - 1) + itemExtent) <= (viewportSize)) {
topIndex--;
+ // will the next one be a hidden row -> skip
+ while (hiddenRowsBefore > 0 && hiddenRows.at(hiddenRowsBefore - 1) >= topIndex + hiddenRowsBefore - 1)
+ hiddenRowsBefore--;
}
const int itemCount = bottomIndex - topIndex + 1;
@@ -2737,7 +2740,7 @@ int QListModeViewBase::perItemScrollToValue(int index, int scrollValue, int view
? Qt::Horizontal : Qt::Vertical);
if (flowOrientation == orientation) { // scrolling in the "flow" direction
// ### wrapped scrolling in the flow direction
- return visibleFlowPositions.at(index); // ### always pixel based for now
+ return flowPositions.at(index + hiddenRowsBefore); // ### always pixel based for now
} else if (!segmentStartRows.isEmpty()) { // we are scrolling in the "segment" direction
int segment = qBinarySearch<int>(segmentStartRows, index, 0, segmentStartRows.count() - 1);
int leftSegment = segment;
@@ -3371,9 +3374,9 @@ int QListView::visualIndex(const QModelIndex &index) const
d->executePostedLayout();
QListViewItem itm = d->indexToListViewItem(index);
int visualIndex = d->commonListView->itemIndex(itm);
- for (int row = 0; row <= index.row() && visualIndex >= 0; row++) {
- if (d->isHidden(row))
- visualIndex--;
+ for (const auto &idx : qAsConst(d->hiddenRows)) {
+ if (idx.row() <= index.row())
+ --visualIndex;
}
return visualIndex;
}
diff --git a/src/widgets/itemviews/qlistview_p.h b/src/widgets/itemviews/qlistview_p.h
index c94357afe9..86331bb862 100644
--- a/src/widgets/itemviews/qlistview_p.h
+++ b/src/widgets/itemviews/qlistview_p.h
@@ -248,7 +248,7 @@ private:
class QIconModeViewBase : public QCommonListViewBase
{
public:
- QIconModeViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d), interSectingVector(0) {}
+ QIconModeViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d), interSectingVector(nullptr) {}
QBspTree tree;
QVector<QListViewItem> items;
@@ -394,6 +394,14 @@ public:
QModelIndex idx = model->index(row, 0, root);
return isPersistent(idx) && hiddenRows.contains(idx);
}
+ // helper to avoid checking for isPersistent and creating persistent indexes as above in isHidden
+ QVector<int> hiddenRowIds() const {
+ QVector<int> rowIds;
+ rowIds.reserve(hiddenRows.size());
+ for (const auto &idx : hiddenRows)
+ rowIds += idx.row();
+ return rowIds;
+ }
inline bool isHiddenOrDisabled(int row) const { return isHidden(row) || !isIndexEnabled(modelIndex(row)); }
void removeCurrentAndDisabled(QVector<QModelIndex> *indexes, const QModelIndex &current) const;
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index b9c0e0a4b7..37bb370e73 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -227,6 +227,22 @@ bool QListModel::setData(const QModelIndex &index, const QVariant &value, int ro
return true;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QListModel::clearItemData(const QModelIndex &index)
+{
+ if (!checkIndex(index, CheckIndexOption::IndexIsValid))
+ return false;
+ QListWidgetItem *item = items.at(index.row());
+ const auto beginIter = item->d->values.cbegin();
+ const auto endIter = item->d->values.cend();
+ if (std::all_of(beginIter, endIter, [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); }))
+ return true; //it's already cleared
+ item->d->values.clear();
+ emit dataChanged(index, index, QVector<int>{});
+ return true;
+}
+#endif
+
QMap<int, QVariant> QListModel::itemData(const QModelIndex &index) const
{
QMap<int, QVariant> roles;
@@ -277,6 +293,30 @@ bool QListModel::removeRows(int row, int count, const QModelIndex &parent)
return true;
}
+/*!
+ \since 5.13
+ \reimp
+*/
+bool QListModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
+{
+ if (sourceRow < 0
+ || sourceRow + count - 1 >= rowCount(sourceParent)
+ || destinationChild <= 0
+ || destinationChild > rowCount(destinationParent)
+ || sourceRow == destinationChild - 1
+ || count <= 0) {
+ return false;
+ }
+ if (!beginMoveRows(QModelIndex(), sourceRow, sourceRow + count - 1, QModelIndex(), destinationChild))
+ return false;
+ destinationChild--;
+ const int fromRow = destinationChild < sourceRow ? (sourceRow + count - 1) : sourceRow;
+ while (count--)
+ items.move(fromRow, destinationChild);
+ endMoveRows();
+ return true;
+}
+
Qt::ItemFlags QListModel::flags(const QModelIndex &index) const
{
if (!index.isValid() || index.row() >= items.count() || index.model() != this)
@@ -289,7 +329,7 @@ void QListModel::sort(int column, Qt::SortOrder order)
if (column != 0)
return;
- emit layoutAboutToBeChanged();
+ emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
QVector < QPair<QListWidgetItem*,int> > sorting(items.count());
for (int i = 0; i < items.count(); ++i) {
@@ -313,7 +353,7 @@ void QListModel::sort(int column, Qt::SortOrder order)
}
changePersistentIndexList(fromIndexes, toIndexes);
- emit layoutChanged();
+ emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
}
/**
@@ -543,24 +583,6 @@ Qt::DropActions QListModel::supportedDropActions() const
*/
/*!
- \fn void QListWidgetItem::setSelected(bool select)
- \since 4.2
-
- Sets the selected state of the item to \a select.
-
- \sa isSelected()
-*/
-
-/*!
- \fn bool QListWidgetItem::isSelected() const
- \since 4.2
-
- Returns \c true if the item is selected; otherwise returns \c false.
-
- \sa setSelected()
-*/
-
-/*!
\fn void QListWidgetItem::setHidden(bool hide)
\since 4.2
@@ -594,14 +616,14 @@ Qt::DropActions QListModel::supportedDropActions() const
\sa type()
*/
-QListWidgetItem::QListWidgetItem(QListWidget *view, int type)
- : rtti(type), view(view), d(new QListWidgetItemPrivate(this)),
+QListWidgetItem::QListWidgetItem(QListWidget *listview, int type)
+ : rtti(type), view(listview), d(new QListWidgetItemPrivate(this)),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled)
{
- if (QListModel *model = (view ? qobject_cast<QListModel*>(view->model()) : 0))
+ if (QListModel *model = listModel())
model->insert(model->rowCount(), this);
}
@@ -621,16 +643,20 @@ QListWidgetItem::QListWidgetItem(QListWidget *view, int type)
\sa type()
*/
-QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *view, int type)
- : rtti(type), view(0), d(new QListWidgetItemPrivate(this)),
+QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *listview, int type)
+ : rtti(type), view(listview), d(new QListWidgetItemPrivate(this)),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled)
{
- setData(Qt::DisplayRole, text);
- this->view = view;
- if (QListModel *model = (view ? qobject_cast<QListModel*>(view->model()) : 0))
+ QListModel *model = listModel();
+ {
+ QSignalBlocker b(view);
+ QSignalBlocker bm(model);
+ setData(Qt::DisplayRole, text);
+ }
+ if (model)
model->insert(model->rowCount(), this);
}
@@ -652,17 +678,21 @@ QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *view, int typ
\sa type()
*/
QListWidgetItem::QListWidgetItem(const QIcon &icon,const QString &text,
- QListWidget *view, int type)
- : rtti(type), view(0), d(new QListWidgetItemPrivate(this)),
+ QListWidget *listview, int type)
+ : rtti(type), view(listview), d(new QListWidgetItemPrivate(this)),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled)
{
- setData(Qt::DisplayRole, text);
- setData(Qt::DecorationRole, icon);
- this->view = view;
- if (QListModel *model = (view ? qobject_cast<QListModel*>(view->model()) : 0))
+ QListModel *model = listModel();
+ {
+ QSignalBlocker b(view);
+ QSignalBlocker bm(model);
+ setData(Qt::DisplayRole, text);
+ setData(Qt::DecorationRole, icon);
+ }
+ if (model)
model->insert(model->rowCount(), this);
}
@@ -671,7 +701,7 @@ QListWidgetItem::QListWidgetItem(const QIcon &icon,const QString &text,
*/
QListWidgetItem::~QListWidgetItem()
{
- if (QListModel *model = (view ? qobject_cast<QListModel*>(view->model()) : 0))
+ if (QListModel *model = listModel())
model->remove(this);
delete d;
}
@@ -708,7 +738,7 @@ void QListWidgetItem::setData(int role, const QVariant &value)
}
if (!found)
d->values.append(QWidgetItemData(role, value));
- if (QListModel *model = (view ? qobject_cast<QListModel*>(view->model()) : nullptr)) {
+ if (QListModel *model = listModel()) {
const QVector<int> roles((role == Qt::DisplayRole) ?
QVector<int>({Qt::DisplayRole, Qt::EditRole}) :
QVector<int>({role}));
@@ -775,7 +805,7 @@ void QListWidgetItem::write(QDataStream &out) const
\sa data(), flags()
*/
QListWidgetItem::QListWidgetItem(const QListWidgetItem &other)
- : rtti(Type), view(0),
+ : rtti(Type), view(nullptr),
d(new QListWidgetItemPrivate(this)),
itemFlags(other.itemFlags)
{
@@ -797,6 +827,15 @@ QListWidgetItem &QListWidgetItem::operator=(const QListWidgetItem &other)
return *this;
}
+/*!
+ \internal
+ returns the QListModel if a view is set
+ */
+QListModel *QListWidgetItem::listModel() const
+{
+ return (view ? qobject_cast<QListModel*>(view->model()) : nullptr);
+}
+
#ifndef QT_NO_DATASTREAM
/*!
@@ -949,6 +988,50 @@ QDataStream &operator>>(QDataStream &in, QListWidgetItem &item)
*/
/*!
+ \fn void QListWidgetItem::setSelected(bool select)
+ \since 4.2
+
+ Sets the selected state of the item to \a select.
+
+ \sa isSelected()
+*/
+void QListWidgetItem::setSelected(bool select)
+{
+ const QListModel *model = listModel();
+ if (!model || !view->selectionModel())
+ return;
+ const QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
+ if (selectionMode == QAbstractItemView::NoSelection)
+ return;
+ const QModelIndex index = model->index(this);
+ if (selectionMode == QAbstractItemView::SingleSelection)
+ view->selectionModel()->select(index, select
+ ? QItemSelectionModel::ClearAndSelect
+ : QItemSelectionModel::Deselect);
+ else
+ view->selectionModel()->select(index, select
+ ? QItemSelectionModel::Select
+ : QItemSelectionModel::Deselect);
+}
+
+/*!
+ \fn bool QListWidgetItem::isSelected() const
+ \since 4.2
+
+ Returns \c true if the item is selected; otherwise returns \c false.
+
+ \sa setSelected()
+*/
+bool QListWidgetItem::isSelected() const
+{
+ const QListModel *model = listModel();
+ if (!model || !view->selectionModel())
+ return false;
+ const QModelIndex index = model->index(this);
+ return view->selectionModel()->isSelected(index);
+}
+
+/*!
\fn void QListWidgetItem::setFlags(Qt::ItemFlags flags)
Sets the item flags for the list item to \a flags.
@@ -958,7 +1041,7 @@ QDataStream &operator>>(QDataStream &in, QListWidgetItem &item)
void QListWidgetItem::setFlags(Qt::ItemFlags aflags)
{
itemFlags = aflags;
- if (QListModel *model = (view ? qobject_cast<QListModel*>(view->model()) : 0))
+ if (QListModel *model = listModel())
model->itemChanged(this);
}
@@ -1678,7 +1761,7 @@ QWidget *QListWidget::itemWidget(QListWidgetItem *item) const
This function should only be used to display static content in the place of
a list widget item. If you want to display custom dynamic content or
- implement a custom editor widget, use QListView and subclass QItemDelegate
+ implement a custom editor widget, use QListView and subclass QStyledItemDelegate
instead.
\sa itemWidget(), removeItemWidget(), {Delegate Classes}
@@ -1690,6 +1773,7 @@ void QListWidget::setItemWidget(QListWidgetItem *item, QWidget *widget)
QAbstractItemView::setIndexWidget(index, widget);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
Returns \c true if \a item is selected; otherwise returns \c false.
@@ -1699,9 +1783,7 @@ void QListWidget::setItemWidget(QListWidgetItem *item, QWidget *widget)
*/
bool QListWidget::isItemSelected(const QListWidgetItem *item) const
{
- Q_D(const QListWidget);
- QModelIndex index = d->listModel()->index(const_cast<QListWidgetItem*>(item));
- return selectionModel()->isSelected(index);
+ return ((item && item->listWidget() == this) ? item->isSelected() : false);
}
/*!
@@ -1714,20 +1796,10 @@ bool QListWidget::isItemSelected(const QListWidgetItem *item) const
*/
void QListWidget::setItemSelected(const QListWidgetItem *item, bool select)
{
- Q_D(QListWidget);
- QModelIndex index = d->listModel()->index(const_cast<QListWidgetItem*>(item));
-
- if (d->selectionMode == SingleSelection) {
- selectionModel()->select(index, select
- ? QItemSelectionModel::ClearAndSelect
- : QItemSelectionModel::Deselect);
- } else if (d->selectionMode != NoSelection) {
- selectionModel()->select(index, select
- ? QItemSelectionModel::Select
- : QItemSelectionModel::Deselect);
- }
-
+ if (item && item->listWidget() == this)
+ const_cast<QListWidgetItem*>(item)->setSelected(select);
}
+#endif
/*!
Returns a list of all selected items in the list widget.
@@ -1763,6 +1835,7 @@ QList<QListWidgetItem*> QListWidget::findItems(const QString &text, Qt::MatchFla
return items;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
Returns \c true if the \a item is explicitly hidden; otherwise returns \c false.
@@ -1786,6 +1859,7 @@ void QListWidget::setItemHidden(const QListWidgetItem *item, bool hide)
{
setRowHidden(row(item), hide);
}
+#endif
/*!
Scrolls the view if necessary to ensure that the \a item is visible.
@@ -1828,8 +1902,8 @@ QStringList QListWidget::mimeTypes() const
\a items. The format used to describe the items is obtained from the
mimeTypes() function.
- If the list of items is empty, 0 is returned instead of a serialized empty
- list.
+ If the list of items is empty, \nullptr is returned instead of a
+ serialized empty list.
*/
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
QMimeData *QListWidget::mimeData(const QList<QListWidgetItem *> &items) const
diff --git a/src/widgets/itemviews/qlistwidget.h b/src/widgets/itemviews/qlistwidget.h
index 947fdb1a2f..c102b144df 100644
--- a/src/widgets/itemviews/qlistwidget.h
+++ b/src/widgets/itemviews/qlistwidget.h
@@ -61,10 +61,10 @@ class Q_WIDGETS_EXPORT QListWidgetItem
friend class QListWidget;
public:
enum ItemType { Type = 0, UserType = 1000 };
- explicit QListWidgetItem(QListWidget *view = nullptr, int type = Type);
- explicit QListWidgetItem(const QString &text, QListWidget *view = nullptr, int type = Type);
+ explicit QListWidgetItem(QListWidget *listview = nullptr, int type = Type);
+ explicit QListWidgetItem(const QString &text, QListWidget *listview = nullptr, int type = Type);
explicit QListWidgetItem(const QIcon &icon, const QString &text,
- QListWidget *view = nullptr, int type = Type);
+ QListWidget *listview = nullptr, int type = Type);
QListWidgetItem(const QListWidgetItem &other);
virtual ~QListWidgetItem();
@@ -72,8 +72,8 @@ public:
inline QListWidget *listWidget() const { return view; }
- inline void setSelected(bool select);
- inline bool isSelected() const;
+ void setSelected(bool select);
+ bool isSelected() const;
inline void setHidden(bool hide);
inline bool isHidden() const;
@@ -114,20 +114,29 @@ public:
inline void setTextAlignment(int alignment)
{ setData(Qt::TextAlignmentRole, alignment); }
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QListWidgetItem::background() instead")
inline QColor backgroundColor() const
- { return qvariant_cast<QColor>(data(Qt::BackgroundColorRole)); }
+ { return qvariant_cast<QColor>(data(Qt::BackgroundRole)); }
+#endif
+ // no QT_DEPRECATED_SINCE because it is a virtual function
+ QT_DEPRECATED_X ("Use QListWidgetItem::setBackground() instead")
virtual void setBackgroundColor(const QColor &color)
- { setData(Qt::BackgroundColorRole, color); }
+ { setData(Qt::BackgroundRole, color); }
inline QBrush background() const
{ return qvariant_cast<QBrush>(data(Qt::BackgroundRole)); }
inline void setBackground(const QBrush &brush)
{ setData(Qt::BackgroundRole, brush); }
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QListWidgetItem::foreground() instead")
inline QColor textColor() const
- { return qvariant_cast<QColor>(data(Qt::TextColorRole)); }
+ { return qvariant_cast<QColor>(data(Qt::ForegroundRole)); }
+ QT_DEPRECATED_X ("Use QListWidgetItem::setForeground() instead")
inline void setTextColor(const QColor &color)
- { setData(Qt::TextColorRole, color); }
+ { setData(Qt::ForegroundRole, color); }
+#endif
inline QBrush foreground() const
{ return qvariant_cast<QBrush>(data(Qt::ForegroundRole)); }
@@ -158,6 +167,7 @@ public:
inline int type() const { return rtti; }
private:
+ QListModel *listModel() const;
int rtti;
QVector<void *> dummy;
QListWidget *view;
@@ -246,13 +256,21 @@ public:
void setItemWidget(QListWidgetItem *item, QWidget *widget);
inline void removeItemWidget(QListWidgetItem *item);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QListWidgetItem::isSelected() instead")
bool isItemSelected(const QListWidgetItem *item) const;
+ QT_DEPRECATED_X ("Use QListWidgetItem::setSelected() instead")
void setItemSelected(const QListWidgetItem *item, bool select);
+#endif
QList<QListWidgetItem*> selectedItems() const;
QList<QListWidgetItem*> findItems(const QString &text, Qt::MatchFlags flags) const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QListWidgetItem::isHidden() instead")
bool isItemHidden(const QListWidgetItem *item) const;
+ QT_DEPRECATED_X ("Use QListWidgetItem::setHidden() instead")
void setItemHidden(const QListWidgetItem *item, bool hide);
+#endif
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
protected:
#endif
@@ -331,17 +349,11 @@ inline void QListWidget::addItem(QListWidgetItem *aitem)
inline QListWidgetItem *QListWidget::itemAt(int ax, int ay) const
{ return itemAt(QPoint(ax, ay)); }
-inline void QListWidgetItem::setSelected(bool aselect)
-{ if (view) view->setItemSelected(this, aselect); }
-
-inline bool QListWidgetItem::isSelected() const
-{ return (view ? view->isItemSelected(this) : false); }
-
inline void QListWidgetItem::setHidden(bool ahide)
-{ if (view) view->setItemHidden(this, ahide); }
+{ if (view) view->setRowHidden(view->row(this), ahide); }
inline bool QListWidgetItem::isHidden() const
-{ return (view ? view->isItemHidden(this) : false); }
+{ return (view ? view->isRowHidden(view->row(this)) : false); }
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qlistwidget_p.h b/src/widgets/itemviews/qlistwidget_p.h
index 9cb3d5966b..65a7124322 100644
--- a/src/widgets/itemviews/qlistwidget_p.h
+++ b/src/widgets/itemviews/qlistwidget_p.h
@@ -100,11 +100,15 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool clearItemData(const QModelIndex &index) override;
+#endif
QMap<int, QVariant> itemData(const QModelIndex &index) const override;
bool insertRows(int row, int count = 1, const QModelIndex &parent = QModelIndex()) override;
bool removeRows(int row, int count = 1, const QModelIndex &parent = QModelIndex()) override;
+ bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
diff --git a/src/widgets/itemviews/qstyleditemdelegate.cpp b/src/widgets/itemviews/qstyleditemdelegate.cpp
index 0f7566e8ec..22067851cb 100644
--- a/src/widgets/itemviews/qstyleditemdelegate.cpp
+++ b/src/widgets/itemviews/qstyleditemdelegate.cpp
@@ -139,7 +139,7 @@ public:
\row \li \l Qt::AccessibleDescriptionRole \li QString
\row \li \l Qt::AccessibleTextRole \li QString
\endomit
- \row \li \l Qt::BackgroundRole \li QBrush
+ \row \li \l Qt::BackgroundRole \li QBrush (\since 4.2)
\row \li \l Qt::BackgroundColorRole \li QColor (obsolete; use Qt::BackgroundRole instead)
\row \li \l Qt::CheckStateRole \li Qt::CheckState
\row \li \l Qt::DecorationRole \li QIcon, QPixmap, QImage and QColor
@@ -151,7 +151,7 @@ public:
\row \li \l Qt::StatusTipRole \li
\endomit
\row \li \l Qt::TextAlignmentRole \li Qt::Alignment
- \row \li \l Qt::ForegroundRole \li QBrush
+ \row \li \l Qt::ForegroundRole \li QBrush (\since 4.2)
\row \li \l Qt::TextColorRole \li QColor (obsolete; use Qt::ForegroundRole instead)
\omit
\row \li \l Qt::ToolTipRole
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index 8fe5b70332..8860ef208d 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -58,6 +58,8 @@
#include <qaccessible.h>
#endif
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
/** \internal
@@ -65,7 +67,7 @@ QT_BEGIN_NAMESPACE
*/
void QSpanCollection::addSpan(QSpanCollection::Span *span)
{
- spans.append(span);
+ spans.push_back(span);
Index::iterator it_y = index.lowerBound(-span->top());
if (it_y == index.end() || it_y.key() != -span->top()) {
//there is no spans that starts with the row in the index, so create a sublist for it.
@@ -132,26 +134,27 @@ void QSpanCollection::updateSpan(QSpanCollection::Span *span, int old_height)
}
if (span->width() == 0 && span->height() == 0) {
- spans.removeOne(span);
+ spans.remove(span);
delete span;
}
}
/** \internal
- * \return a spans that spans over cell x,y (column,row) or 0 if there is none.
+ * \return a spans that spans over cell x,y (column,row)
+ * or \nullptr if there is none.
*/
QSpanCollection::Span *QSpanCollection::spanAt(int x, int y) const
{
Index::const_iterator it_y = index.lowerBound(-y);
if (it_y == index.end())
- return 0;
+ return nullptr;
SubIndex::const_iterator it_x = (*it_y).lowerBound(-x);
if (it_x == (*it_y).end())
- return 0;
+ return nullptr;
Span *span = *it_x;
if (span->right() >= x && span->bottom() >= y)
return span;
- return 0;
+ return nullptr;
}
@@ -168,7 +171,7 @@ void QSpanCollection::clear()
/** \internal
* return a list to all the spans that spans over cells in the given rectangle
*/
-QList<QSpanCollection::Span *> QSpanCollection::spansInRect(int x, int y, int w, int h) const
+QSet<QSpanCollection::Span *> QSpanCollection::spansInRect(int x, int y, int w, int h) const
{
QSet<Span *> list;
Index::const_iterator it_y = index.lowerBound(-y);
@@ -190,7 +193,7 @@ QList<QSpanCollection::Span *> QSpanCollection::spansInRect(int x, int y, int w,
break;
--it_y;
}
- return list.toList();
+ return list;
}
#undef DEBUG_SPAN_UPDATE
@@ -209,17 +212,16 @@ QDebug operator<<(QDebug str, const QSpanCollection::Span &span)
void QSpanCollection::updateInsertedRows(int start, int end)
{
#ifdef DEBUG_SPAN_UPDATE
- qDebug() << start << end << endl << index;
+ qDebug() << start << end << Qt::endl << index;
#endif
- if (spans.isEmpty())
+ if (spans.empty())
return;
int delta = end - start + 1;
#ifdef DEBUG_SPAN_UPDATE
qDebug("Before");
#endif
- for (SpanList::iterator it = spans.begin(); it != spans.end(); ++it) {
- Span *span = *it;
+ for (Span *span : spans) {
#ifdef DEBUG_SPAN_UPDATE
qDebug() << span << *span;
#endif
@@ -257,17 +259,16 @@ void QSpanCollection::updateInsertedRows(int start, int end)
void QSpanCollection::updateInsertedColumns(int start, int end)
{
#ifdef DEBUG_SPAN_UPDATE
- qDebug() << start << end << endl << index;
+ qDebug() << start << end << Qt::endl << index;
#endif
- if (spans.isEmpty())
+ if (spans.empty())
return;
int delta = end - start + 1;
#ifdef DEBUG_SPAN_UPDATE
qDebug("Before");
#endif
- for (SpanList::iterator it = spans.begin(); it != spans.end(); ++it) {
- Span *span = *it;
+ for (Span *span : spans) {
#ifdef DEBUG_SPAN_UPDATE
qDebug() << span << *span;
#endif
@@ -338,9 +339,9 @@ bool QSpanCollection::cleanSpanSubIndex(QSpanCollection::SubIndex &subindex, int
void QSpanCollection::updateRemovedRows(int start, int end)
{
#ifdef DEBUG_SPAN_UPDATE
- qDebug() << start << end << endl << index;
+ qDebug() << start << end << Qt::endl << index;
#endif
- if (spans.isEmpty())
+ if (spans.empty())
return;
SpanList spansToBeDeleted;
@@ -376,7 +377,7 @@ void QSpanCollection::updateRemovedRows(int start, int end)
if (span->m_top == span->m_bottom && span->m_left == span->m_right)
span->will_be_deleted = true;
if (span->will_be_deleted) {
- spansToBeDeleted.append(span);
+ spansToBeDeleted.push_back(span);
it = spans.erase(it);
} else {
++it;
@@ -388,7 +389,7 @@ void QSpanCollection::updateRemovedRows(int start, int end)
foreach (QSpanCollection::Span *span, spans)
qDebug() << span << *span;
#endif
- if (spans.isEmpty()) {
+ if (spans.empty()) {
qDeleteAll(spansToBeDeleted);
index.clear();
return;
@@ -465,9 +466,9 @@ void QSpanCollection::updateRemovedRows(int start, int end)
void QSpanCollection::updateRemovedColumns(int start, int end)
{
#ifdef DEBUG_SPAN_UPDATE
- qDebug() << start << end << endl << index;
+ qDebug() << start << end << Qt::endl << index;
#endif
- if (spans.isEmpty())
+ if (spans.empty())
return;
SpanList toBeDeleted;
@@ -503,7 +504,7 @@ void QSpanCollection::updateRemovedColumns(int start, int end)
if (span->m_top == span->m_bottom && span->m_left == span->m_right)
span->will_be_deleted = true;
if (span->will_be_deleted) {
- toBeDeleted.append(span);
+ toBeDeleted.push_back(span);
it = spans.erase(it);
} else {
++it;
@@ -515,7 +516,7 @@ void QSpanCollection::updateRemovedColumns(int start, int end)
foreach (QSpanCollection::Span *span, spans)
qDebug() << span << *span;
#endif
- if (spans.isEmpty()) {
+ if (spans.empty()) {
qDeleteAll(toBeDeleted);
index.clear();
return;
@@ -551,13 +552,13 @@ bool QSpanCollection::checkConsistency() const
for (SubIndex::const_iterator it = subIndex.begin(); it != subIndex.end(); ++it) {
int x = -it.key();
Span *span = it.value();
- if (!spans.contains(span) || span->left() != x
- || y < span->top() || y > span->bottom())
+ const bool contains = std::find(spans.begin(), spans.end(), span) != spans.end();
+ if (!contains || span->left() != x || y < span->top() || y > span->bottom())
return false;
}
}
- foreach (const Span *span, spans) {
+ for (const Span *span : spans) {
if (span->width() < 1 || span->height() < 1
|| (span->width() == 1 && span->height() == 1))
return false;
@@ -862,19 +863,17 @@ void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter,
bool alternateBase = false;
QRegion region = viewport->rect();
- QList<QSpanCollection::Span *> visibleSpans;
+ QSet<QSpanCollection::Span *> visibleSpans;
bool sectionMoved = verticalHeader->sectionsMoved() || horizontalHeader->sectionsMoved();
if (!sectionMoved) {
visibleSpans = spans.spansInRect(logicalColumn(firstVisualColumn), logicalRow(firstVisualRow),
lastVisualColumn - firstVisualColumn + 1, lastVisualRow - firstVisualRow + 1);
} else {
- QSet<QSpanCollection::Span *> set;
for(int x = firstVisualColumn; x <= lastVisualColumn; x++)
for(int y = firstVisualRow; y <= lastVisualRow; y++)
- set.insert(spans.spanAt(x,y));
- set.remove(0);
- visibleSpans = set.toList();
+ visibleSpans.insert(spans.spanAt(x,y));
+ visibleSpans.remove(nullptr);
}
for (QSpanCollection::Span *span : qAsConst(visibleSpans)) {
@@ -964,6 +963,15 @@ void QTableViewPrivate::_q_updateSpanRemovedColumns(const QModelIndex &parent, i
/*!
\internal
+ Sort the model when the header sort indicator changed
+*/
+void QTableViewPrivate::_q_sortIndicatorChanged(int column, Qt::SortOrder order)
+{
+ model->sort(column, order);
+}
+
+/*!
+ \internal
Draws a table cell.
*/
void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index)
@@ -1099,7 +1107,7 @@ int QTableViewPrivate::heightHintForIndex(const QModelIndex &index, int hint, QS
\l showGrid property.
The items shown in a table view, like those in the other item views, are
- rendered and edited using standard \l{QItemDelegate}{delegates}. However,
+ rendered and edited using standard \l{QStyledItemDelegate}{delegates}. However,
for some tasks it is sometimes useful to be able to insert widgets in a
table instead. Widgets are set for particular indexes with the
\l{QAbstractItemView::}{setIndexWidget()} function, and
@@ -1171,8 +1179,6 @@ QSize QTableView::viewportSizeHint() const
Q_D(const QTableView);
QSize result( (d->verticalHeader->isHidden() ? 0 : d->verticalHeader->width()) + d->horizontalHeader->length(),
(d->horizontalHeader->isHidden() ? 0 : d->horizontalHeader->height()) + d->verticalHeader->length());
- result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
- horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
return result;
}
@@ -1443,12 +1449,12 @@ void QTableView::paintEvent(QPaintEvent *event)
//firstVisualRow is the visual index of the first visible row. lastVisualRow is the visual index of the last visible Row.
//same goes for ...VisualColumn
int firstVisualRow = qMax(verticalHeader->visualIndexAt(0),0);
- int lastVisualRow = verticalHeader->visualIndexAt(verticalHeader->viewport()->height());
+ int lastVisualRow = verticalHeader->visualIndexAt(verticalHeader->height());
if (lastVisualRow == -1)
lastVisualRow = d->model->rowCount(d->root) - 1;
int firstVisualColumn = horizontalHeader->visualIndexAt(0);
- int lastVisualColumn = horizontalHeader->visualIndexAt(horizontalHeader->viewport()->width());
+ int lastVisualColumn = horizontalHeader->visualIndexAt(horizontalHeader->width());
if (rightToLeft)
qSwap(firstVisualColumn, lastVisualColumn);
if (firstVisualColumn == -1)
@@ -1917,7 +1923,7 @@ void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionF
int right = qMax(d->visualColumn(tl.column()), d->visualColumn(br.column()));
do {
expanded = false;
- foreach (QSpanCollection::Span *it, d->spans.spans) {
+ for (QSpanCollection::Span *it : d->spans.spans) {
const QSpanCollection::Span &span = *it;
int t = d->visualRow(span.top());
int l = d->visualColumn(span.left());
@@ -2611,25 +2617,27 @@ void QTableView::setColumnHidden(int column, bool hide)
void QTableView::setSortingEnabled(bool enable)
{
Q_D(QTableView);
- d->sortingEnabled = enable;
horizontalHeader()->setSortIndicatorShown(enable);
if (enable) {
disconnect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
this, SLOT(_q_selectColumn(int)));
disconnect(horizontalHeader(), SIGNAL(sectionPressed(int)),
this, SLOT(selectColumn(int)));
- connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(sortByColumn(int)), Qt::UniqueConnection);
+ //sortByColumn has to be called before we connect or set the sortingEnabled flag
+ // because otherwise it will not call sort on the model.
sortByColumn(horizontalHeader()->sortIndicatorSection(),
horizontalHeader()->sortIndicatorOrder());
+ connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
+ this, SLOT(_q_sortIndicatorChanged(int,Qt::SortOrder)), Qt::UniqueConnection);
} else {
connect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
this, SLOT(_q_selectColumn(int)), Qt::UniqueConnection);
connect(horizontalHeader(), SIGNAL(sectionPressed(int)),
this, SLOT(selectColumn(int)), Qt::UniqueConnection);
disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(sortByColumn(int)));
+ this, SLOT(_q_sortIndicatorChanged(int,Qt::SortOrder)));
}
+ d->sortingEnabled = enable;
}
bool QTableView::isSortingEnabled() const
@@ -3158,19 +3166,21 @@ void QTableView::resizeColumnsToContents()
d->horizontalHeader->resizeSections(QHeaderView::ResizeToContents);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
\overload
+ This function is deprecated. Use
+ sortByColumn(int column, Qt::SortOrder order) instead.
Sorts the model by the values in the given \a column.
*/
void QTableView::sortByColumn(int column)
{
Q_D(QTableView);
- if (column == -1)
- return;
- d->model->sort(column, d->horizontalHeader->sortIndicatorOrder());
+ sortByColumn(column, d->horizontalHeader->sortIndicatorOrder());
}
+#endif
/*!
\since 4.2
@@ -3182,8 +3192,14 @@ void QTableView::sortByColumn(int column)
void QTableView::sortByColumn(int column, Qt::SortOrder order)
{
Q_D(QTableView);
+ if (column < 0)
+ return;
+ // If sorting is enabled it will emit a signal connected to
+ // _q_sortIndicatorChanged, which then actually sorts
d->horizontalHeader->setSortIndicator(column, order);
- sortByColumn(column);
+ // If sorting is not enabled, force to sort now
+ if (!d->sortingEnabled)
+ d->model->sort(column, order);
}
/*!
diff --git a/src/widgets/itemviews/qtableview.h b/src/widgets/itemviews/qtableview.h
index 60c2f34103..3275c09f88 100644
--- a/src/widgets/itemviews/qtableview.h
+++ b/src/widgets/itemviews/qtableview.h
@@ -118,7 +118,6 @@ public:
int columnSpan(int row, int column) const;
void clearSpans();
- void sortByColumn(int column, Qt::SortOrder order);
public Q_SLOTS:
void selectRow(int row);
@@ -131,7 +130,11 @@ public Q_SLOTS:
void resizeRowsToContents();
void resizeColumnToContents(int column);
void resizeColumnsToContents();
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QTableView::sortByColumn(int column, Qt::SortOrder order) instead")
void sortByColumn(int column);
+#endif
+ void sortByColumn(int column, Qt::SortOrder order);
void setShowGrid(bool show);
protected Q_SLOTS:
@@ -188,6 +191,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_updateSpanInsertedColumns(QModelIndex,int,int))
Q_PRIVATE_SLOT(d_func(), void _q_updateSpanRemovedRows(QModelIndex,int,int))
Q_PRIVATE_SLOT(d_func(), void _q_updateSpanRemovedColumns(QModelIndex,int,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sortIndicatorChanged(int column, Qt::SortOrder order))
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qtableview_p.h b/src/widgets/itemviews/qtableview_p.h
index a50e6b6410..8f174351d2 100644
--- a/src/widgets/itemviews/qtableview_p.h
+++ b/src/widgets/itemviews/qtableview_p.h
@@ -53,12 +53,13 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include <QtCore/QList>
-#include <QtCore/QLinkedList>
#include <QtCore/QMap>
#include <QtCore/QSet>
#include <QtCore/QDebug>
#include "private/qabstractitemview_p.h"
+#include <list>
+
QT_REQUIRE_CONFIG(tableview);
QT_BEGIN_NAMESPACE
@@ -104,7 +105,7 @@ public:
void updateSpan(Span *span, int old_height);
Span *spanAt(int x, int y) const;
void clear();
- QList<Span *> spansInRect(int x, int y, int w, int h) const;
+ QSet<Span *> spansInRect(int x, int y, int w, int h) const;
void updateInsertedRows(int start, int end);
void updateInsertedColumns(int start, int end);
@@ -115,7 +116,7 @@ public:
bool checkConsistency() const;
#endif
- typedef QLinkedList<Span *> SpanList;
+ typedef std::list<Span *> SpanList;
SpanList spans; //lists of all spans
private:
//the indexes are negative so the QMap::lowerBound do what i need.
@@ -137,7 +138,7 @@ public:
: showGrid(true), gridStyle(Qt::SolidLine),
rowSectionAnchor(-1), columnSectionAnchor(-1),
columnResizeTimerID(0), rowResizeTimerID(0),
- horizontalHeader(0), verticalHeader(0),
+ horizontalHeader(nullptr), verticalHeader(nullptr),
sortingEnabled(false), geometryRecursionBlock(false),
visualCursor(QPoint())
{
@@ -210,7 +211,7 @@ public:
return span(row, column).width();
}
inline bool hasSpans() const {
- return !spans.spans.isEmpty();
+ return !spans.spans.empty();
}
inline int rowSpanHeight(int row, int span) const {
return sectionSpanSize(verticalHeader, row, span);
@@ -257,6 +258,7 @@ public:
void _q_updateSpanInsertedColumns(const QModelIndex &parent, int start, int end);
void _q_updateSpanRemovedRows(const QModelIndex &parent, int start, int end);
void _q_updateSpanRemovedColumns(const QModelIndex &parent, int start, int end);
+ void _q_sortIndicatorChanged(int column, Qt::SortOrder order);
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp
index d576d323c3..0fb9e28385 100644
--- a/src/widgets/itemviews/qtablewidget.cpp
+++ b/src/widgets/itemviews/qtablewidget.cpp
@@ -189,7 +189,7 @@ void QTableModel::setItem(int row, int column, QTableWidgetItem *item)
sortedRow = qMax((int)(it - colItems.begin()), 0);
}
if (sortedRow != row) {
- emit layoutAboutToBeChanged();
+ emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
// move the items @ row to sortedRow
int cc = columnCount();
QVector<QTableWidgetItem*> rowItems(cc);
@@ -209,7 +209,7 @@ void QTableModel::setItem(int row, int column, QTableWidgetItem *item)
changePersistentIndexList(oldPersistentIndexes,
newPersistentIndexes);
- emit layoutChanged();
+ emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
return;
}
}
@@ -480,6 +480,24 @@ bool QTableModel::setItemData(const QModelIndex &index, const QMap<int, QVariant
return true;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QTableModel::clearItemData(const QModelIndex &index)
+{
+ if (!checkIndex(index, CheckIndexOption::IndexIsValid))
+ return false;
+ QTableWidgetItem *itm = item(index);
+ if (!itm)
+ return false;
+ const auto beginIter = itm->values.cbegin();
+ const auto endIter = itm->values.cend();
+ if (std::all_of(beginIter, endIter, [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); }))
+ return true; //it's already cleared
+ itm->values.clear();
+ emit dataChanged(index, index, QVector<int>{});
+ return true;
+}
+#endif
+
Qt::ItemFlags QTableModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
@@ -530,12 +548,12 @@ void QTableModel::sort(int column, Qt::SortOrder order)
}
}
- emit layoutAboutToBeChanged();
+ emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
tableItems = sorted_table;
changePersistentIndexList(from, to); // ### slow
- emit layoutChanged();
+ emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
}
/*
@@ -580,7 +598,7 @@ void QTableModel::ensureSorted(int column, Qt::SortOrder order,
vit = colItems.insert(vit, item);
if (newRow != oldRow) {
if (!changed) {
- emit layoutAboutToBeChanged();
+ emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
oldPersistentIndexes = persistentIndexList();
newPersistentIndexes = oldPersistentIndexes;
changed = true;
@@ -615,7 +633,7 @@ void QTableModel::ensureSorted(int column, Qt::SortOrder order,
verticalHeaderItems = newVertical;
changePersistentIndexList(oldPersistentIndexes,
newPersistentIndexes);
- emit layoutChanged();
+ emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
}
}
@@ -1037,24 +1055,6 @@ QTableWidgetSelectionRange::~QTableWidgetSelectionRange()
*/
/*!
- \fn void QTableWidgetItem::setSelected(bool select)
- \since 4.2
-
- Sets the selected state of the item to \a select.
-
- \sa isSelected()
-*/
-
-/*!
- \fn bool QTableWidgetItem::isSelected() const
- \since 4.2
-
- Returns \c true if the item is selected, otherwise returns \c false.
-
- \sa setSelected()
-*/
-
-/*!
\fn QSize QTableWidgetItem::sizeHint() const
\since 4.1
@@ -1091,6 +1091,44 @@ QTableWidgetSelectionRange::~QTableWidgetSelectionRange()
*/
/*!
+ \fn bool QTableWidgetItem::isSelected() const
+ \since 4.2
+
+ Returns \c true if the item is selected, otherwise returns \c false.
+
+ \sa setSelected()
+*/
+bool QTableWidgetItem::isSelected() const
+{
+ if (!view || !view->selectionModel())
+ return false;
+ const QTableModel *model = qobject_cast<const QTableModel*>(view->model());
+ if (!model)
+ return false;
+ const QModelIndex index = model->index(this);
+ return view->selectionModel()->isSelected(index);
+}
+
+/*!
+ \fn void QTableWidgetItem::setSelected(bool select)
+ \since 4.2
+
+ Sets the selected state of the item to \a select.
+
+ \sa isSelected()
+*/
+void QTableWidgetItem::setSelected(bool select)
+{
+ if (!view || !view->selectionModel())
+ return;
+ const QTableModel *model = qobject_cast<const QTableModel*>(view->model());
+ if (!model)
+ return;
+ const QModelIndex index = model->index(this);
+ view->selectionModel()->select(index, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
+}
+
+/*!
\fn Qt::ItemFlags QTableWidgetItem::flags() const
Returns the flags used to describe the item. These determine whether
@@ -1110,7 +1148,7 @@ QTableWidgetSelectionRange::~QTableWidgetSelectionRange()
void QTableWidgetItem::setFlags(Qt::ItemFlags aflags)
{
itemFlags = aflags;
- if (QTableModel *model = (view ? qobject_cast<QTableModel*>(view->model()) : 0))
+ if (QTableModel *model = tableModel())
model->itemChanged(this);
}
@@ -1301,7 +1339,7 @@ void QTableWidgetItem::setFlags(Qt::ItemFlags aflags)
\sa type()
*/
QTableWidgetItem::QTableWidgetItem(int type)
- : rtti(type), view(0), d(new QTableWidgetItemPrivate(this)),
+ : rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
itemFlags(Qt::ItemIsEditable
|Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
@@ -1317,7 +1355,7 @@ QTableWidgetItem::QTableWidgetItem(int type)
\sa type()
*/
QTableWidgetItem::QTableWidgetItem(const QString &text, int type)
- : rtti(type), view(0), d(new QTableWidgetItemPrivate(this)),
+ : rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
itemFlags(Qt::ItemIsEditable
|Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
@@ -1334,7 +1372,7 @@ QTableWidgetItem::QTableWidgetItem(const QString &text, int type)
\sa type()
*/
QTableWidgetItem::QTableWidgetItem(const QIcon &icon, const QString &text, int type)
- : rtti(type), view(0), d(new QTableWidgetItemPrivate(this)),
+ : rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
itemFlags(Qt::ItemIsEditable
|Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
@@ -1351,9 +1389,8 @@ QTableWidgetItem::QTableWidgetItem(const QIcon &icon, const QString &text, int t
*/
QTableWidgetItem::~QTableWidgetItem()
{
- if (QTableModel *model = (view ? qobject_cast<QTableModel*>(view->model()) : 0))
+ if (QTableModel *model = tableModel())
model->removeItem(this);
- view = 0;
delete d;
}
@@ -1389,7 +1426,7 @@ void QTableWidgetItem::setData(int role, const QVariant &value)
}
if (!found)
values.append(QWidgetItemData(role, value));
- if (QTableModel *model = (view ? qobject_cast<QTableModel*>(view->model()) : nullptr))
+ if (QTableModel *model = tableModel())
{
const QVector<int> roles((role == Qt::DisplayRole) ?
QVector<int>({Qt::DisplayRole, Qt::EditRole}) :
@@ -1444,6 +1481,16 @@ void QTableWidgetItem::write(QDataStream &out) const
}
/*!
+ \internal
+ returns the QTableModel if a view is set
+*/
+QTableModel *QTableWidgetItem::tableModel() const
+{
+ return (view ? qobject_cast<QTableModel*>(view->model()) : nullptr);
+}
+
+
+/*!
\relates QTableWidgetItem
Reads a table widget item from stream \a in into \a item.
@@ -1486,7 +1533,7 @@ QDataStream &operator<<(QDataStream &out, const QTableWidgetItem &item)
\sa data(), flags()
*/
QTableWidgetItem::QTableWidgetItem(const QTableWidgetItem &other)
- : rtti(Type), values(other.values), view(0),
+ : rtti(Type), values(other.values), view(nullptr),
d(new QTableWidgetItemPrivate(this)),
itemFlags(other.itemFlags)
{
@@ -2305,6 +2352,7 @@ void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
QAbstractItemView::setIndexWidget(index, widget);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
Returns \c true if the \a item is selected, otherwise returns \c false.
@@ -2315,9 +2363,7 @@ void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
bool QTableWidget::isItemSelected(const QTableWidgetItem *item) const
{
- Q_D(const QTableWidget);
- QModelIndex index = d->tableModel()->index(item);
- return selectionModel()->isSelected(index);
+ return ((item && item->tableWidget() == this) ? item->isSelected() : false);
}
/*!
@@ -2329,10 +2375,10 @@ bool QTableWidget::isItemSelected(const QTableWidgetItem *item) const
*/
void QTableWidget::setItemSelected(const QTableWidgetItem *item, bool select)
{
- Q_D(QTableWidget);
- QModelIndex index = d->tableModel()->index(item);
- selectionModel()->select(index, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
+ if (item && item->tableWidget() == this)
+ const_cast<QTableWidgetItem*>(item)->setSelected(select);
}
+#endif
/*!
Selects or deselects the \a range depending on \a select.
@@ -2587,8 +2633,8 @@ QStringList QTableWidget::mimeTypes() const
\a items. The format used to describe the items is obtained from the
mimeTypes() function.
- If the list of items is empty, 0 is returned rather than a serialized
- empty list.
+ If the list of items is empty, \nullptr is returned rather than a
+ serialized empty list.
*/
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem *> &items) const
diff --git a/src/widgets/itemviews/qtablewidget.h b/src/widgets/itemviews/qtablewidget.h
index 9de27d164f..d93032f3f0 100644
--- a/src/widgets/itemviews/qtablewidget.h
+++ b/src/widgets/itemviews/qtablewidget.h
@@ -92,8 +92,8 @@ public:
inline int row() const;
inline int column() const;
- inline void setSelected(bool select);
- inline bool isSelected() const;
+ void setSelected(bool select);
+ bool isSelected() const;
inline Qt::ItemFlags flags() const { return itemFlags; }
void setFlags(Qt::ItemFlags flags);
@@ -131,20 +131,28 @@ public:
inline void setTextAlignment(int alignment)
{ setData(Qt::TextAlignmentRole, alignment); }
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QTableWidgetItem::background() instead")
inline QColor backgroundColor() const
- { return qvariant_cast<QColor>(data(Qt::BackgroundColorRole)); }
+ { return qvariant_cast<QColor>(data(Qt::BackgroundRole)); }
+ QT_DEPRECATED_X ("Use QTableWidgetItem::setBackground() instead")
inline void setBackgroundColor(const QColor &color)
- { setData(Qt::BackgroundColorRole, color); }
+ { setData(Qt::BackgroundRole, color); }
+#endif
inline QBrush background() const
{ return qvariant_cast<QBrush>(data(Qt::BackgroundRole)); }
inline void setBackground(const QBrush &brush)
{ setData(Qt::BackgroundRole, brush); }
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QTableWidgetItem::foreground() instead")
inline QColor textColor() const
- { return qvariant_cast<QColor>(data(Qt::TextColorRole)); }
+ { return qvariant_cast<QColor>(data(Qt::ForegroundRole)); }
+ QT_DEPRECATED_X ("Use QTableWidgetItem::setForeground() instead")
inline void setTextColor(const QColor &color)
- { setData(Qt::TextColorRole, color); }
+ { setData(Qt::ForegroundRole, color); }
+#endif
inline QBrush foreground() const
{ return qvariant_cast<QBrush>(data(Qt::ForegroundRole)); }
@@ -175,6 +183,9 @@ public:
inline int type() const { return rtti; }
private:
+ QTableModel *tableModel() const;
+
+private:
int rtti;
QVector<QWidgetItemData> values;
QTableWidget *view;
@@ -268,8 +279,12 @@ public:
void setCellWidget(int row, int column, QWidget *widget);
inline void removeCellWidget(int row, int column);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QTableWidgetItem::isSelected() instead")
bool isItemSelected(const QTableWidgetItem *item) const;
+ QT_DEPRECATED_X ("Use QTableWidgetItem::setSelected() instead")
void setItemSelected(const QTableWidgetItem *item, bool select);
+#endif
void setRangeSelected(const QTableWidgetSelectionRange &range, bool select);
QList<QTableWidgetSelectionRange> selectedRanges() const;
@@ -375,12 +390,6 @@ inline int QTableWidgetItem::row() const
inline int QTableWidgetItem::column() const
{ return (view ? view->column(this) : -1); }
-inline void QTableWidgetItem::setSelected(bool aselect)
-{ if (view) view->setItemSelected(this, aselect); }
-
-inline bool QTableWidgetItem::isSelected() const
-{ return (view ? view->isItemSelected(this) : false); }
-
QT_END_NAMESPACE
#endif // QTABLEWIDGET_H
diff --git a/src/widgets/itemviews/qtablewidget_p.h b/src/widgets/itemviews/qtablewidget_p.h
index 9899272fce..d88326f129 100644
--- a/src/widgets/itemviews/qtablewidget_p.h
+++ b/src/widgets/itemviews/qtablewidget_p.h
@@ -129,6 +129,9 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool clearItemData(const QModelIndex &index) override;
+#endif
QMap<int, QVariant> itemData(const QModelIndex &index) const override;
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 5a7615b388..55b10d13c1 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -1089,15 +1089,8 @@ void QTreeView::keyboardSearch(const QString &search)
if (start.column() > 0)
index = index.sibling(index.row(), start.column());
- if (index.isValid()) {
- QItemSelectionModel::SelectionFlags flags = (d->selectionMode == SingleSelection
- ? QItemSelectionModel::SelectionFlags(
- QItemSelectionModel::ClearAndSelect
- |d->selectionBehaviorFlags())
- : QItemSelectionModel::SelectionFlags(
- QItemSelectionModel::NoUpdate));
- selectionModel()->setCurrentIndex(index, flags);
- }
+ if (index.isValid())
+ setCurrentIndex(index);
}
/*!
@@ -1774,7 +1767,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
? QPalette::Normal : QPalette::Disabled;
o.backgroundColor = option.palette.color(cg, d->selectionModel->isSelected(index)
- ? QPalette::Highlight : QPalette::Background);
+ ? QPalette::Highlight : QPalette::Window);
int x = 0;
if (!option.showDecorationSelected)
x = header->sectionPosition(0) + d->indentationForItem(d->current);
@@ -1993,21 +1986,7 @@ void QTreeView::keyPressEvent(QKeyEvent *event)
if (d->isIndexValid(current) && d->model && d->itemsExpandable) {
switch (event->key()) {
case Qt::Key_Asterisk: {
- // do layouting only once after expanding is done
- d->doDelayedItemsLayout();
- QStack<QModelIndex> parents;
- parents.push(current);
- while (!parents.isEmpty()) {
- QModelIndex parent = parents.pop();
- for (int row = 0; row < d->model->rowCount(parent); ++row) {
- QModelIndex child = d->model->index(row, 0, parent);
- if (!d->isIndexValid(child))
- break;
- parents.push(child);
- expand(child);
- }
- }
- expand(current);
+ expandRecursively(current);
break; }
case Qt::Key_Plus:
expand(current);
@@ -2161,12 +2140,10 @@ int QTreeView::verticalOffset() const
// ### find a faster way to do this
d->executePostedLayout();
int offset = 0;
- for (int i = 0; i < d->viewItems.count(); ++i) {
- if (i == verticalScrollBar()->value())
- return offset;
+ const int cnt = std::min(d->viewItems.count(), verticalScrollBar()->value());
+ for (int i = 0; i < cnt; ++i)
offset += d->itemHeight(i);
- }
- return 0;
+ return offset;
}
// scroll per pixel
return verticalScrollBar()->value();
@@ -2325,9 +2302,9 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
case MovePageDown:
return d->modelIndex(d->pageDown(vi), current.column());
case MoveHome:
- return d->model->index(0, current.column(), d->root);
+ return d->modelIndex(d->itemForKeyHome(), current.column());
case MoveEnd:
- return d->modelIndex(d->viewItems.count() - 1, current.column());
+ return d->modelIndex(d->itemForKeyEnd(), current.column());
}
return current;
}
@@ -2622,10 +2599,13 @@ void QTreeView::resizeColumnToContents(int column)
d->header->resizeSection(column, qMax(contents, header));
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
\overload
+ This function is deprecated. Use
+ sortByColumn(int column, Qt::SortOrder order) instead.
Sorts the model by the values in the given \a column.
*/
void QTreeView::sortByColumn(int column)
@@ -2633,6 +2613,7 @@ void QTreeView::sortByColumn(int column)
Q_D(QTreeView);
sortByColumn(column, d->header->sortIndicatorOrder());
}
+#endif
/*!
\since 4.2
@@ -2648,10 +2629,12 @@ void QTreeView::sortByColumn(int column)
void QTreeView::sortByColumn(int column, Qt::SortOrder order)
{
Q_D(QTreeView);
-
- //If sorting is enabled will emit a signal connected to _q_sortIndicatorChanged, which then actually sorts
+ if (column < 0)
+ return;
+ // If sorting is enabled it will emit a signal connected to
+ // _q_sortIndicatorChanged, which then actually sorts
d->header->setSortIndicator(column, order);
- //If sorting is not enabled, force to sort now.
+ // If sorting is not enabled, force to sort now
if (!d->sortingEnabled)
d->model->sort(column, order);
}
@@ -2695,11 +2678,7 @@ QSize QTreeView::viewportSizeHint() const
QSize result = QSize(d->header->length(), deepestRect.bottom() + 1);
// add size for header
- result += QSize(0, d->header->isVisible() ? d->header->height() : 0);
-
- // add size for scrollbars
- result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
- horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
+ result += QSize(0, d->header->isHidden() ? 0 : d->header->height());
return result;
}
@@ -2708,7 +2687,7 @@ QSize QTreeView::viewportSizeHint() const
\since 4.2
Expands all expandable items.
- Warning: if the model contains a large number of items,
+ \warning: if the model contains a large number of items,
this function will take some time to execute.
\sa collapseAll(), expand(), collapse(), setExpanded()
@@ -2724,6 +2703,50 @@ void QTreeView::expandAll()
}
/*!
+ \since 5.13
+ Expands the item at the given \a index and all its children to the
+ given \a depth. The \a depth is relative to the given \a index.
+ A \a depth of -1 will expand all children, a \a depth of 0 will
+ only expand the given \a index.
+
+ \warning: if the model contains a large number of items,
+ this function will take some time to execute.
+
+ \sa expandAll()
+*/
+void QTreeView::expandRecursively(const QModelIndex &index, int depth)
+{
+ Q_D(QTreeView);
+
+ if (depth < -1)
+ return;
+ // do layouting only once after expanding is done
+ d->doDelayedItemsLayout();
+ expand(index);
+ if (depth == 0)
+ return;
+ QStack<QPair<QModelIndex, int>> parents;
+ parents.push({index, 0});
+ while (!parents.isEmpty()) {
+ const QPair<QModelIndex, int> elem = parents.pop();
+ const QModelIndex &parent = elem.first;
+ const int curDepth = elem.second;
+ const int rowCount = d->model->rowCount(parent);
+ for (int row = 0; row < rowCount; ++row) {
+ const QModelIndex child = d->model->index(row, 0, parent);
+ if (!d->isIndexValid(child))
+ break;
+ if (depth == -1 || curDepth + 1 < depth)
+ parents.push({child, curDepth + 1});
+ if (d->isIndexExpanded(child))
+ continue;
+ if (d->storeExpanded(child))
+ emit expanded(child);
+ }
+ }
+}
+
+/*!
\since 4.2
Collapses all expanded items.
@@ -3400,7 +3423,11 @@ int QTreeViewPrivate::pageUp(int i) const
int index = itemAtCoordinate(coordinateForItem(i) - viewport->height());
while (isItemHiddenOrDisabled(index))
index--;
- return index == -1 ? 0 : index;
+ if (index == -1)
+ index = 0;
+ while (isItemHiddenOrDisabled(index))
+ index++;
+ return index >= viewItems.count() ? 0 : index;
}
int QTreeViewPrivate::pageDown(int i) const
@@ -3408,6 +3435,26 @@ int QTreeViewPrivate::pageDown(int i) const
int index = itemAtCoordinate(coordinateForItem(i) + viewport->height());
while (isItemHiddenOrDisabled(index))
index++;
+ if (index == -1 || index >= viewItems.count())
+ index = viewItems.count() - 1;
+ while (isItemHiddenOrDisabled(index))
+ index--;
+ return index == -1 ? viewItems.count() - 1 : index;
+}
+
+int QTreeViewPrivate::itemForKeyHome() const
+{
+ int index = 0;
+ while (isItemHiddenOrDisabled(index))
+ index++;
+ return index >= viewItems.count() ? 0 : index;
+}
+
+int QTreeViewPrivate::itemForKeyEnd() const
+{
+ int index = viewItems.count() - 1;
+ while (isItemHiddenOrDisabled(index))
+ index--;
return index == -1 ? viewItems.count() - 1 : index;
}
diff --git a/src/widgets/itemviews/qtreeview.h b/src/widgets/itemviews/qtreeview.h
index 33dbf1c1ce..bb00f1df07 100644
--- a/src/widgets/itemviews/qtreeview.h
+++ b/src/widgets/itemviews/qtreeview.h
@@ -143,7 +143,6 @@ public:
void doItemsLayout() override;
void reset() override;
- void sortByColumn(int column, Qt::SortOrder order);
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>()) override;
void selectAll() override;
@@ -158,8 +157,13 @@ public Q_SLOTS:
void expand(const QModelIndex &index);
void collapse(const QModelIndex &index);
void resizeColumnToContents(int column);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QTreeView::sortByColumn(int column, Qt::SortOrder order) instead")
void sortByColumn(int column);
+#endif
+ void sortByColumn(int column, Qt::SortOrder order);
void expandAll();
+ void expandRecursively(const QModelIndex &index, int depth = -1);
void collapseAll();
void expandToDepth(int depth);
diff --git a/src/widgets/itemviews/qtreeview_p.h b/src/widgets/itemviews/qtreeview_p.h
index 0a0e7aae87..836d8f0c2d 100644
--- a/src/widgets/itemviews/qtreeview_p.h
+++ b/src/widgets/itemviews/qtreeview_p.h
@@ -87,7 +87,7 @@ public:
QTreeViewPrivate()
: QAbstractItemViewPrivate(),
- header(0), indent(20), lastViewedItem(0), defaultItemHeight(-1),
+ header(nullptr), indent(20), lastViewedItem(0), defaultItemHeight(-1),
uniformRowHeights(false), rootDecoration(true),
itemsExpandable(true), sortingEnabled(false),
expandsOnDoubleClick(true),
@@ -140,6 +140,8 @@ public:
int pageUp(int item) const;
int pageDown(int item) const;
+ int itemForKeyHome() const;
+ int itemForKeyEnd() const;
int itemHeight(int item) const;
int indentationForItem(int item) const;
@@ -155,7 +157,7 @@ public:
bool checkViewItems() const;
#endif
- int firstVisibleItem(int *offset = 0) const;
+ int firstVisibleItem(int *offset = nullptr) const;
int lastVisibleItem(int firstVisual = -1, int offset = -1) const;
int columnAt(int x) const;
bool hasVisibleChildren( const QModelIndex& parent) const;
diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp
index 9fbfb50029..d2dc91b18c 100644
--- a/src/widgets/itemviews/qtreewidget.cpp
+++ b/src/widgets/itemviews/qtreewidget.cpp
@@ -390,6 +390,27 @@ bool QTreeModel::setData(const QModelIndex &index, const QVariant &value, int ro
return false;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QTreeModel::clearItemData(const QModelIndex &index)
+{
+ if (!checkIndex(index, CheckIndexOption::IndexIsValid))
+ return false;
+ QTreeWidgetItem *itm = item(index);
+ if (!itm)
+ return false;
+ const auto beginIter = itm->values.at(index.column()).cbegin();
+ const auto endIter = itm->values.at(index.column()).cend();
+ if (std::all_of(beginIter, endIter, [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); })
+ && !itm->d->display.at(index.column()).isValid()) {
+ return true; //it's already cleared
+ }
+ itm->d->display[index.column()] = QVariant();
+ itm->values[index.column()].clear();
+ emit dataChanged(index, index, QVector<int>{});
+ return true;
+}
+#endif
+
QMap<int, QVariant> QTreeModel::itemData(const QModelIndex &index) const
{
QMap<int, QVariant> roles;
@@ -635,7 +656,7 @@ void QTreeModel::ensureSorted(int column, Qt::SortOrder order,
// we are going to change the persistent indexes, so we need to prepare
if (!changed) { // this will only happen once
changed = true;
- emit layoutAboutToBeChanged(); // the selection model needs to know
+ emit layoutAboutToBeChanged({parent}, QAbstractItemModel::VerticalSortHint); // the selection model needs to know
oldPersistentIndexes = persistentIndexList();
newPersistentIndexes = oldPersistentIndexes;
}
@@ -668,7 +689,7 @@ void QTreeModel::ensureSorted(int column, Qt::SortOrder order,
if (changed) {
itm->children = lst;
changePersistentIndexList(oldPersistentIndexes, newPersistentIndexes);
- emit layoutChanged();
+ emit layoutChanged({parent}, QAbstractItemModel::VerticalSortHint);
}
}
@@ -988,8 +1009,18 @@ void QTreeModel::timerEvent(QTimerEvent *ev)
Sets the selected state of the item to \a select.
\sa isSelected()
-
*/
+void QTreeWidgetItem::setSelected(bool select)
+{
+ const QTreeModel *model = treeModel();
+ if (!model || !view->selectionModel())
+ return;
+ const QModelIndex index = model->index(this, 0);
+ view->selectionModel()->select(index, (select ? QItemSelectionModel::Select
+ : QItemSelectionModel::Deselect)
+ | QItemSelectionModel::Rows);
+ d->selected = select;
+}
/*!
\fn bool QTreeWidgetItem::isSelected() const
@@ -999,6 +1030,10 @@ void QTreeModel::timerEvent(QTimerEvent *ev)
\sa setSelected()
*/
+bool QTreeWidgetItem::isSelected() const
+{
+ return d->selected;
+}
/*!
\fn void QTreeWidgetItem::setHidden(bool hide)
@@ -1012,12 +1047,18 @@ void QTreeModel::timerEvent(QTimerEvent *ev)
\sa isHidden()
*/
-void QTreeWidgetItem::setHidden(bool ahide)
+void QTreeWidgetItem::setHidden(bool hide)
{
- if (view) {
- view->setItemHidden(this, ahide);
- d->hidden = ahide;
+ const QTreeModel *model = treeModel();
+ if (!model)
+ return;
+ if (this == model->headerItem) {
+ view->header()->setHidden(hide);
+ } else {
+ const QModelIndex index = view->d_func()->index(this);
+ view->setRowHidden(index.row(), index.parent(), hide);
}
+ d->hidden = hide;
}
/*!
@@ -1031,7 +1072,15 @@ void QTreeWidgetItem::setHidden(bool ahide)
bool QTreeWidgetItem::isHidden() const
{
- return (view ? d->hidden : false);
+ const QTreeModel *model = treeModel();
+ if (!model)
+ return false;
+ if (this == model->headerItem)
+ return view->header()->isHidden();
+ if (view->d_func()->hiddenIndexes.isEmpty())
+ return false;
+ QTreeModel::SkipSorting skipSorting(model);
+ return view->d_func()->isRowHidden(view->d_func()->index(this));
}
/*!
@@ -1043,6 +1092,14 @@ bool QTreeWidgetItem::isHidden() const
\sa isExpanded()
*/
+void QTreeWidgetItem::setExpanded(bool expand)
+{
+ const QTreeModel *model = treeModel();
+ if (!model)
+ return;
+ QTreeModel::SkipSorting skipSorting(model);
+ view->setExpanded(view->d_func()->index(this), expand);
+}
/*!
\fn bool QTreeWidgetItem::isExpanded() const
@@ -1052,6 +1109,14 @@ bool QTreeWidgetItem::isHidden() const
\sa setExpanded()
*/
+bool QTreeWidgetItem::isExpanded() const
+{
+ const QTreeModel *model = treeModel();
+ if (!model)
+ return false;
+ QTreeModel::SkipSorting skipSorting(model);
+ return view->isExpanded(view->d_func()->index(this));
+}
/*!
\fn void QTreeWidgetItem::setFirstColumnSpanned(bool span)
@@ -1062,6 +1127,14 @@ bool QTreeWidgetItem::isHidden() const
\sa isFirstColumnSpanned()
*/
+void QTreeWidgetItem::setFirstColumnSpanned(bool span)
+{
+ const QTreeModel *model = treeModel();
+ if (!model || this == model->headerItem)
+ return; // We can't set the header items to spanning
+ const QModelIndex index = model->index(this, 0);
+ view->setFirstColumnSpanned(index.row(), index.parent(), span);
+}
/*!
\fn bool QTreeWidgetItem::isFirstColumnSpanned() const
@@ -1071,6 +1144,14 @@ bool QTreeWidgetItem::isHidden() const
\sa setFirstColumnSpanned()
*/
+bool QTreeWidgetItem::isFirstColumnSpanned() const
+{
+ const QTreeModel *model = treeModel();
+ if (!model || this == model->headerItem)
+ return false;
+ const QModelIndex index = model->index(this, 0);
+ return view->isFirstColumnSpanned(index.row(), index.parent());
+}
/*!
\fn QString QTreeWidgetItem::text(int column) const
@@ -1325,7 +1406,7 @@ bool QTreeWidgetItem::isHidden() const
\sa type()
*/
QTreeWidgetItem::QTreeWidgetItem(int type)
- : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
+ : rtti(type), view(nullptr), d(new QTreeWidgetItemPrivate(this)), par(nullptr),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
@@ -1344,7 +1425,7 @@ QTreeWidgetItem::QTreeWidgetItem(int type)
\sa type()
*/
QTreeWidgetItem::QTreeWidgetItem(const QStringList &strings, int type)
- : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
+ : rtti(type), view(nullptr), d(new QTreeWidgetItemPrivate(this)), par(nullptr),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
@@ -1364,16 +1445,16 @@ QTreeWidgetItem::QTreeWidgetItem(const QStringList &strings, int type)
\sa type()
*/
-QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, int type)
- : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
+QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview, int type)
+ : rtti(type), view(nullptr), d(new QTreeWidgetItemPrivate(this)), par(nullptr),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled
|Qt::ItemIsDropEnabled)
{
- if (view && view->model()) {
- QTreeModel *model = qobject_cast<QTreeModel*>(view->model());
+ // do not set this->view here otherwise insertChild() will fail
+ if (QTreeModel *model = treeModel(treeview)) {
model->rootItem->addChild(this);
values.reserve(model->headerItem->columnCount());
}
@@ -1389,8 +1470,8 @@ QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, int type)
\sa type()
*/
-QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, const QStringList &strings, int type)
- : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
+QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview, const QStringList &strings, int type)
+ : rtti(type), view(nullptr), d(new QTreeWidgetItemPrivate(this)), par(nullptr),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
@@ -1399,8 +1480,8 @@ QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, const QStringList &strings,
{
for (int i = 0; i < strings.count(); ++i)
setText(i, strings.at(i));
- if (view && view->model()) {
- QTreeModel *model = qobject_cast<QTreeModel*>(view->model());
+ // do not set this->view here otherwise insertChild() will fail
+ if (QTreeModel *model = treeModel(treeview)) {
model->rootItem->addChild(this);
values.reserve(model->headerItem->columnCount());
}
@@ -1414,21 +1495,19 @@ QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, const QStringList &strings,
\sa type()
*/
-QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, QTreeWidgetItem *after, int type)
- : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
+QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *treeview, QTreeWidgetItem *after, int type)
+ : rtti(type), view(nullptr), d(new QTreeWidgetItemPrivate(this)), par(nullptr),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled
|Qt::ItemIsDropEnabled)
{
- if (view) {
- QTreeModel *model = qobject_cast<QTreeModel*>(view->model());
- if (model) {
- int i = model->rootItem->children.indexOf(after) + 1;
- model->rootItem->insertChild(i, this);
- values.reserve(model->headerItem->columnCount());
- }
+ // do not set this->view here otherwise insertChild() will fail
+ if (QTreeModel *model = treeModel(treeview)) {
+ int i = model->rootItem->children.indexOf(after) + 1;
+ model->rootItem->insertChild(i, this);
+ values.reserve(model->headerItem->columnCount());
}
}
@@ -1438,7 +1517,7 @@ QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, QTreeWidgetItem *after, int
\sa type()
*/
QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, int type)
- : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
+ : rtti(type), view(nullptr), d(new QTreeWidgetItemPrivate(this)), par(nullptr),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
@@ -1456,7 +1535,7 @@ QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, int type)
\sa type()
*/
QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, const QStringList &strings, int type)
- : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
+ : rtti(type), view(nullptr), d(new QTreeWidgetItemPrivate(this)), par(nullptr),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
@@ -1478,7 +1557,7 @@ QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, const QStringList &str
\sa type()
*/
QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *after, int type)
- : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
+ : rtti(type), view(nullptr), d(new QTreeWidgetItemPrivate(this)), par(nullptr),
itemFlags(Qt::ItemIsSelectable
|Qt::ItemIsUserCheckable
|Qt::ItemIsEnabled
@@ -1501,7 +1580,7 @@ QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *after
QTreeWidgetItem::~QTreeWidgetItem()
{
- QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
+ QTreeModel *model = treeModel();
bool wasSkipSort = false;
if (model) {
wasSkipSort = model->skipPendingSort;
@@ -1663,16 +1742,17 @@ void QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
void QTreeWidgetItemPrivate::updateHiddenStatus(QTreeWidgetItem *item, bool inserting)
{
- QTreeModel *model = (item->view ? qobject_cast<QTreeModel*>(item->view->model()) : 0);
+ QTreeModel *model = item->treeModel();
if (!model)
return;
QStack<QTreeWidgetItem *> parents;
parents.push(item);
while (!parents.isEmpty()) {
QTreeWidgetItem *parent = parents.pop();
- QModelIndex index = model->index(parent, 0);
- if (parent->d->hidden)
+ if (parent->d->hidden) {
+ const QModelIndex index = model->index(parent, 0);
item->view->setRowHidden(index.row(), index.parent(), inserting);
+ }
for (int i = 0; i < parent->children.count(); ++i) {
QTreeWidgetItem *child = parent->children.at(i);
parents.push(child);
@@ -1737,7 +1817,7 @@ void QTreeWidgetItem::setData(int column, int role, const QVariant &value)
if (column < 0)
return;
- QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
+ QTreeModel *model = treeModel();
switch (role) {
case Qt::EditRole:
case Qt::DisplayRole: {
@@ -1945,7 +2025,7 @@ void QTreeWidgetItem::insertChild(int index, QTreeWidgetItem *child)
if (index < 0 || index > children.count() || child == 0 || child->view != 0 || child->par != 0)
return;
- if (QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0)) {
+ if (QTreeModel *model = treeModel()) {
const bool wasSkipSort = model->skipPendingSort;
model->skipPendingSort = true;
if (model->rootItem == this)
@@ -1996,7 +2076,7 @@ QTreeWidgetItem *QTreeWidgetItem::takeChild(int index)
{
// we move this outside the check of the index to allow executing
// pending sorts from inline functions, using this function (hack)
- QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
+ QTreeModel *model = treeModel();
if (model) {
// This will trigger a layoutChanged signal, thus we might want to optimize
// this function by not emitting the rowsRemoved signal etc to the view.
@@ -2054,7 +2134,7 @@ void QTreeWidgetItem::insertChildren(int index, const QList<QTreeWidgetItem*> &c
insertChild(index, children.at(n));
return;
}
- QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
+ QTreeModel *model = treeModel();
QStack<QTreeWidgetItem*> stack;
QList<QTreeWidgetItem*> itemsToInsert;
for (int n = 0; n < children.count(); ++n) {
@@ -2101,7 +2181,7 @@ QList<QTreeWidgetItem*> QTreeWidgetItem::takeChildren()
{
QList<QTreeWidgetItem*> removed;
if (children.count() > 0) {
- QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
+ QTreeModel *model = treeModel();
if (model) {
// This will trigger a layoutChanged signal, thus we might want to optimize
// this function by not emitting the rowsRemoved signal etc to the view.
@@ -2133,7 +2213,7 @@ QList<QTreeWidgetItem*> QTreeWidgetItem::takeChildren()
void QTreeWidgetItemPrivate::sortChildren(int column, Qt::SortOrder order, bool climb)
{
- QTreeModel *model = (q->view ? qobject_cast<QTreeModel*>(q->view->model()) : 0);
+ QTreeModel *model = q->treeModel();
if (!model)
return;
model->sortItems(&q->children, column, order);
@@ -2156,7 +2236,7 @@ void QTreeWidgetItemPrivate::sortChildren(int column, Qt::SortOrder order, bool
*/
void QTreeWidgetItem::sortChildren(int column, Qt::SortOrder order, bool climb)
{
- QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
+ QTreeModel *model = treeModel();
if (!model)
return;
if (model->isChanging())
@@ -2164,9 +2244,9 @@ void QTreeWidgetItem::sortChildren(int column, Qt::SortOrder order, bool climb)
QTreeModel::SkipSorting skipSorting(model);
int oldSortColumn = view->d_func()->explicitSortColumn;
view->d_func()->explicitSortColumn = column;
- emit model->layoutAboutToBeChanged();
+ emit model->layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
d->sortChildren(column, order, climb);
- emit model->layoutChanged();
+ emit model->layoutChanged({}, QAbstractItemModel::VerticalSortHint);
view->d_func()->explicitSortColumn = oldSortColumn;
}
@@ -2236,7 +2316,7 @@ void QTreeWidgetItem::emitDataChanged()
*/
void QTreeWidgetItem::itemChanged()
{
- if (QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0))
+ if (QTreeModel *model = treeModel())
model->itemChanged(this);
}
@@ -2245,10 +2325,21 @@ void QTreeWidgetItem::itemChanged()
*/
void QTreeWidgetItem::executePendingSort() const
{
- if (QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0))
+ if (QTreeModel *model = treeModel())
model->executePendingSort();
}
+/*!
+ \internal
+ returns the QTreeModel if a view is set
+*/
+QTreeModel *QTreeWidgetItem::treeModel(QTreeWidget *v) const
+{
+ if (!v)
+ v = view;
+ return (v ? qobject_cast<QTreeModel*>(v->model()) : nullptr);
+}
+
#ifndef QT_NO_DATASTREAM
/*!
@@ -2448,8 +2539,8 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
QStyle::SH_ItemView_ActivateItemOnSingleClick style hint) or
pressing a special key (e.g., \uicontrol Enter).
- The specified \a item is the item that was clicked, or 0 if no
- item was clicked. The \a column is the item's column that was
+ The specified \a item is the item that was clicked, or \nullptr if
+ no item was clicked. The \a column is the item's column that was
clicked, or -1 if no item was clicked.
*/
@@ -2459,8 +2550,8 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
This signal is emitted when the user presses a mouse button inside
the widget.
- The specified \a item is the item that was clicked, or 0 if no
- item was clicked. The \a column is the item's column that was
+ The specified \a item is the item that was clicked, or \nullptr if
+ no item was clicked. The \a column is the item's column that was
clicked, or -1 if no item was clicked.
*/
@@ -2480,8 +2571,8 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
This signal is emitted when the user double clicks inside the
widget.
- The specified \a item is the item that was clicked, or 0 if no
- item was clicked. The \a column is the item's column that was
+ The specified \a item is the item that was clicked, or \nullptr if
+ no item was clicked. The \a column is the item's column that was
clicked. If no item was double clicked, no signal will be emitted.
*/
@@ -2633,8 +2724,8 @@ QTreeWidgetItem *QTreeWidget::invisibleRootItem() const
}
/*!
- Returns the top level item at the given \a index, or 0 if the item does
- not exist.
+ Returns the top level item at the given \a index, or \nullptr if the
+ item does not exist.
\sa topLevelItemCount(), insertTopLevelItem()
*/
@@ -3010,7 +3101,7 @@ QWidget *QTreeWidget::itemWidget(QTreeWidgetItem *item, int column) const
This function should only be used to display static content in the place of
a tree widget item. If you want to display custom dynamic content or
- implement a custom editor widget, use QTreeView and subclass QItemDelegate
+ implement a custom editor widget, use QTreeView and subclass QStyledItemDelegate
instead.
This function cannot be called before the item hierarchy has been set up,
@@ -3027,6 +3118,7 @@ void QTreeWidget::setItemWidget(QTreeWidgetItem *item, int column, QWidget *widg
QAbstractItemView::setIndexWidget(d->index(item, column), widget);
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
Returns \c true if the \a item is selected; otherwise returns \c false.
@@ -3038,9 +3130,7 @@ void QTreeWidget::setItemWidget(QTreeWidgetItem *item, int column, QWidget *widg
*/
bool QTreeWidget::isItemSelected(const QTreeWidgetItem *item) const
{
- if (!item)
- return false;
- return item->d->selected;
+ return ((item && item->treeWidget() == this) ? item->isSelected() : false);
}
/*!
@@ -3055,16 +3145,10 @@ bool QTreeWidget::isItemSelected(const QTreeWidgetItem *item) const
*/
void QTreeWidget::setItemSelected(const QTreeWidgetItem *item, bool select)
{
- Q_D(QTreeWidget);
-
- if (!item)
- return;
-
- selectionModel()->select(d->index(item), (select ? QItemSelectionModel::Select
- : QItemSelectionModel::Deselect)
- |QItemSelectionModel::Rows);
- item->d->selected = select;
+ if (item && item->treeWidget() == this)
+ const_cast<QTreeWidgetItem*>(item)->setSelected(select);
}
+#endif
/*!
Returns a list of all selected non-hidden items.
@@ -3081,7 +3165,7 @@ QList<QTreeWidgetItem*> QTreeWidget::selectedItems() const
seen.reserve(indexes.count());
for (const auto &index : indexes) {
QTreeWidgetItem *item = d->item(index);
- if (isItemHidden(item) || seen.contains(item))
+ if (item->isHidden() || seen.contains(item))
continue;
seen.insert(item);
items.append(item);
@@ -3105,6 +3189,7 @@ QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFla
return items;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
Returns \c true if the \a item is explicitly hidden, otherwise returns \c false.
@@ -3114,13 +3199,7 @@ QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFla
*/
bool QTreeWidget::isItemHidden(const QTreeWidgetItem *item) const
{
- Q_D(const QTreeWidget);
- if (item == d->treeModel()->headerItem)
- return header()->isHidden();
- if (d->hiddenIndexes.isEmpty())
- return false;
- QTreeModel::SkipSorting skipSorting(d->treeModel());
- return d->isRowHidden(d->index(item));
+ return ((item && item->treeWidget() == this) ? item->isHidden() : false);
}
/*!
@@ -3134,16 +3213,8 @@ bool QTreeWidget::isItemHidden(const QTreeWidgetItem *item) const
*/
void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide)
{
- if (!item)
- return;
- Q_D(QTreeWidget);
- if (item == d->treeModel()->headerItem) {
- header()->setHidden(hide);
- } else {
- const QModelIndex index = d->index(item);
- setRowHidden(index.row(), index.parent(), hide);
- }
- item->d->hidden = hide;
+ if (item && item->treeWidget() == this)
+ const_cast<QTreeWidgetItem*>(item)->setHidden(hide);
}
/*!
@@ -3157,9 +3228,7 @@ void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide)
*/
bool QTreeWidget::isItemExpanded(const QTreeWidgetItem *item) const
{
- Q_D(const QTreeWidget);
- QTreeModel::SkipSorting skipSorting(d->treeModel());
- return isExpanded(d->index(item));
+ return ((item && item->treeWidget() == this) ? item->isExpanded() : false);
}
/*!
@@ -3174,9 +3243,8 @@ bool QTreeWidget::isItemExpanded(const QTreeWidgetItem *item) const
*/
void QTreeWidget::setItemExpanded(const QTreeWidgetItem *item, bool expand)
{
- Q_D(QTreeWidget);
- QTreeModel::SkipSorting skipSorting(d->treeModel());
- setExpanded(d->index(item), expand);
+ if (item && item->treeWidget() == this)
+ const_cast<QTreeWidgetItem*>(item)->setExpanded(expand);
}
/*!
@@ -3186,14 +3254,14 @@ void QTreeWidget::setItemExpanded(const QTreeWidgetItem *item, bool expand)
otherwise returns \c false.
\sa setFirstItemColumnSpanned()
+
+ \obsolete
+
+ This function is deprecated. Use \l{QTreeWidgetItem::isFirstColumnSpanned()} instead.
*/
bool QTreeWidget::isFirstItemColumnSpanned(const QTreeWidgetItem *item) const
{
- Q_D(const QTreeWidget);
- if (item == d->treeModel()->headerItem)
- return false; // We can't set the header items to spanning
- const QModelIndex index = d->index(item);
- return isFirstColumnSpanned(index.row(), index.parent());
+ return ((item && item->treeWidget() == this) ? item->isFirstColumnSpanned() : false);
}
/*!
@@ -3203,15 +3271,17 @@ bool QTreeWidget::isFirstItemColumnSpanned(const QTreeWidgetItem *item) const
otherwise the item will show one section per column.
\sa isFirstItemColumnSpanned()
+
+ \obsolete
+
+ This function is deprecated. Use \l{QTreeWidgetItem::setFirstColumnSpanned()} instead.
*/
void QTreeWidget::setFirstItemColumnSpanned(const QTreeWidgetItem *item, bool span)
{
- Q_D(QTreeWidget);
- if (item == d->treeModel()->headerItem)
- return; // We can't set header items to spanning
- const QModelIndex index = d->index(item);
- setFirstColumnSpanned(index.row(), index.parent(), span);
+ if (item && item->treeWidget() == this)
+ const_cast<QTreeWidgetItem*>(item)->setFirstColumnSpanned(span);
}
+#endif
/*!
\since 4.3
@@ -3325,8 +3395,8 @@ QStringList QTreeWidget::mimeTypes() const
\a items. The format used to describe the items is obtained from the
mimeTypes() function.
- If the list of items is empty, 0 is returned rather than a serialized
- empty list.
+ If the list of items is empty, \nullptr is returned rather than a
+ serialized empty list.
*/
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
QMimeData *QTreeWidget::mimeData(const QList<QTreeWidgetItem *> &items) const
diff --git a/src/widgets/itemviews/qtreewidget.h b/src/widgets/itemviews/qtreewidget.h
index 975f208702..bed77b336d 100644
--- a/src/widgets/itemviews/qtreewidget.h
+++ b/src/widgets/itemviews/qtreewidget.h
@@ -66,9 +66,9 @@ public:
enum ItemType { Type = 0, UserType = 1000 };
explicit QTreeWidgetItem(int type = Type);
explicit QTreeWidgetItem(const QStringList &strings, int type = Type);
- explicit QTreeWidgetItem(QTreeWidget *view, int type = Type);
- QTreeWidgetItem(QTreeWidget *view, const QStringList &strings, int type = Type);
- QTreeWidgetItem(QTreeWidget *view, QTreeWidgetItem *after, int type = Type);
+ explicit QTreeWidgetItem(QTreeWidget *treeview, int type = Type);
+ QTreeWidgetItem(QTreeWidget *treeview, const QStringList &strings, int type = Type);
+ QTreeWidgetItem(QTreeWidget *treeview, QTreeWidgetItem *after, int type = Type);
explicit QTreeWidgetItem(QTreeWidgetItem *parent, int type = Type);
QTreeWidgetItem(QTreeWidgetItem *parent, const QStringList &strings, int type = Type);
QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *after, int type = Type);
@@ -79,17 +79,17 @@ public:
inline QTreeWidget *treeWidget() const { return view; }
- inline void setSelected(bool select);
- inline bool isSelected() const;
+ void setSelected(bool select);
+ bool isSelected() const;
void setHidden(bool hide);
bool isHidden() const;
- inline void setExpanded(bool expand);
- inline bool isExpanded() const;
+ void setExpanded(bool expand);
+ bool isExpanded() const;
- inline void setFirstColumnSpanned(bool span);
- inline bool isFirstColumnSpanned() const;
+ void setFirstColumnSpanned(bool span);
+ bool isFirstColumnSpanned() const;
inline void setDisabled(bool disabled);
inline bool isDisabled() const;
@@ -134,20 +134,28 @@ public:
inline void setTextAlignment(int column, int alignment)
{ setData(column, Qt::TextAlignmentRole, alignment); }
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::background() instead")
inline QColor backgroundColor(int column) const
- { return qvariant_cast<QColor>(data(column, Qt::BackgroundColorRole)); }
+ { return qvariant_cast<QColor>(data(column, Qt::BackgroundRole)); }
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::setBackground() instead")
inline void setBackgroundColor(int column, const QColor &color)
- { setData(column, Qt::BackgroundColorRole, color); }
+ { setData(column, Qt::BackgroundRole, color); }
+#endif
inline QBrush background(int column) const
{ return qvariant_cast<QBrush>(data(column, Qt::BackgroundRole)); }
inline void setBackground(int column, const QBrush &brush)
{ setData(column, Qt::BackgroundRole, brush); }
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::foreground() instead")
inline QColor textColor(int column) const
- { return qvariant_cast<QColor>(data(column, Qt::TextColorRole)); }
+ { return qvariant_cast<QColor>(data(column, Qt::ForegroundRole)); }
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::setForeground() instead")
inline void setTextColor(int column, const QColor &color)
- { setData(column, Qt::TextColorRole, color); }
+ { setData(column, Qt::ForegroundRole, color); }
+#endif
inline QBrush foreground(int column) const
{ return qvariant_cast<QBrush>(data(column, Qt::ForegroundRole)); }
@@ -207,6 +215,7 @@ private:
QVariant childrenCheckState(int column) const;
void itemChanged();
void executePendingSort() const;
+ QTreeModel *treeModel(QTreeWidget *v = nullptr) const;
int rtti;
// One item has a vector of column entries. Each column has a vector of (role, value) pairs.
@@ -306,20 +315,32 @@ public:
void setItemWidget(QTreeWidgetItem *item, int column, QWidget *widget);
inline void removeItemWidget(QTreeWidgetItem *item, int column);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::isSelected() instead")
bool isItemSelected(const QTreeWidgetItem *item) const;
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::setSelected() instead")
void setItemSelected(const QTreeWidgetItem *item, bool select);
+#endif
QList<QTreeWidgetItem*> selectedItems() const;
QList<QTreeWidgetItem*> findItems(const QString &text, Qt::MatchFlags flags,
int column = 0) const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::isHidden() instead")
bool isItemHidden(const QTreeWidgetItem *item) const;
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::setHidden() instead")
void setItemHidden(const QTreeWidgetItem *item, bool hide);
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::isExpanded() instead")
bool isItemExpanded(const QTreeWidgetItem *item) const;
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::setExpanded() instead")
void setItemExpanded(const QTreeWidgetItem *item, bool expand);
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::isFirstColumnSpanned() instead")
bool isFirstItemColumnSpanned(const QTreeWidgetItem *item) const;
+ QT_DEPRECATED_X ("Use QTreeWidgetItem::setFirstColumnSpanned() instead")
void setFirstItemColumnSpanned(const QTreeWidgetItem *item, bool span);
+#endif
QTreeWidgetItem *itemAbove(const QTreeWidgetItem *item) const;
QTreeWidgetItem *itemBelow(const QTreeWidgetItem *item) const;
@@ -404,24 +425,6 @@ inline QTreeWidgetItem *QTreeWidget::itemAt(int ax, int ay) const
inline void QTreeWidget::setHeaderLabel(const QString &alabel)
{ setHeaderLabels(QStringList(alabel)); }
-inline void QTreeWidgetItem::setSelected(bool aselect)
-{ if (view) view->setItemSelected(this, aselect); }
-
-inline bool QTreeWidgetItem::isSelected() const
-{ return (view ? view->isItemSelected(this) : false); }
-
-inline void QTreeWidgetItem::setExpanded(bool aexpand)
-{ if (view) view->setItemExpanded(this, aexpand); }
-
-inline bool QTreeWidgetItem::isExpanded() const
-{ return (view ? view->isItemExpanded(this) : false); }
-
-inline void QTreeWidgetItem::setFirstColumnSpanned(bool aspan)
-{ if (view) view->setFirstItemColumnSpanned(this, aspan); }
-
-inline bool QTreeWidgetItem::isFirstColumnSpanned() const
-{ return (view ? view->isFirstItemColumnSpanned(this) : false); }
-
inline void QTreeWidgetItem::setDisabled(bool disabled)
{ setFlags(disabled ? (flags() & ~Qt::ItemIsEnabled) : flags() | Qt::ItemIsEnabled); }
diff --git a/src/widgets/itemviews/qtreewidget_p.h b/src/widgets/itemviews/qtreewidget_p.h
index adc2c2c421..81e7e86203 100644
--- a/src/widgets/itemviews/qtreewidget_p.h
+++ b/src/widgets/itemviews/qtreewidget_p.h
@@ -78,7 +78,7 @@ class QTreeModel : public QAbstractItemModel
friend class QTreeWidgetItemIteratorPrivate;
public:
- explicit QTreeModel(int columns = 0, QTreeWidget *parent = 0);
+ explicit QTreeModel(int columns = 0, QTreeWidget *parent = nullptr);
~QTreeModel();
inline QTreeWidget *view() const
@@ -99,7 +99,9 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
-
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool clearItemData(const QModelIndex &index) override;
+#endif
QMap<int, QVariant> itemData(const QModelIndex &index) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
@@ -138,7 +140,7 @@ public:
{ return createIndex(row, col, item); }
protected:
- QTreeModel(QTreeModelPrivate &, QTreeWidget *parent = 0);
+ QTreeModel(QTreeModelPrivate &, QTreeWidget *parent = nullptr);
void emitDataChanged(QTreeWidgetItem *item, int column, const QVector<int> &roles);
void beginInsertItems(QTreeWidgetItem *parent, int row, int count);
void endInsertItems();
diff --git a/src/widgets/itemviews/qtreewidgetitemiterator.cpp b/src/widgets/itemviews/qtreewidgetitemiterator.cpp
index 1c1f60bc37..14c19fcb9c 100644
--- a/src/widgets/itemviews/qtreewidgetitemiterator.cpp
+++ b/src/widgets/itemviews/qtreewidgetitemiterator.cpp
@@ -170,7 +170,7 @@ QTreeWidgetItemIterator &QTreeWidgetItemIterator::operator=(const QTreeWidgetIte
/*!
The prefix ++ operator (++it) advances the iterator to the next matching item
and returns a reference to the resulting iterator.
- Sets the current pointer to 0 if the current item is the last matching item.
+ Sets the current pointer to \nullptr if the current item is the last matching item.
*/
QTreeWidgetItemIterator &QTreeWidgetItemIterator::operator++()
@@ -185,7 +185,7 @@ QTreeWidgetItemIterator &QTreeWidgetItemIterator::operator++()
/*!
The prefix -- operator (--it) advances the iterator to the previous matching item
and returns a reference to the resulting iterator.
- Sets the current pointer to 0 if the current item is the first matching item.
+ Sets the current pointer to \nullptr if the current item is the first matching item.
*/
QTreeWidgetItemIterator &QTreeWidgetItemIterator::operator--()
@@ -395,7 +395,7 @@ void QTreeWidgetItemIteratorPrivate::ensureValidIterator(const QTreeWidgetItem *
iterator goes backward.)
If the current item is beyond the last item, the current item pointer is
- set to 0. Returns the resulting iterator.
+ set to \nullptr. Returns the resulting iterator.
*/
/*!
@@ -411,7 +411,7 @@ void QTreeWidgetItemIteratorPrivate::ensureValidIterator(const QTreeWidgetItem *
iterator goes forward.)
If the current item is ahead of the last item, the current item pointer is
- set to 0. Returns the resulting iterator.
+ set to \nullptr. Returns the resulting iterator.
*/
/*!
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri
index c2f6e4ce75..a4b81335c5 100644
--- a/src/widgets/kernel/kernel.pri
+++ b/src/widgets/kernel/kernel.pri
@@ -23,7 +23,6 @@ HEADERS += \
kernel/qshortcut.h \
kernel/qsizepolicy.h \
kernel/qstackedlayout.h \
- kernel/qtooltip.h \
kernel/qwidget.h \
kernel/qwidget_p.h \
kernel/qwidgetaction.h \
@@ -51,7 +50,6 @@ SOURCES += \
kernel/qshortcut.cpp \
kernel/qsizepolicy.cpp \
kernel/qstackedlayout.cpp \
- kernel/qtooltip.cpp \
kernel/qwidget.cpp \
kernel/qwidgetaction.cpp \
kernel/qgesture.cpp \
@@ -79,6 +77,11 @@ qtConfig(formlayout) {
SOURCES += kernel/qformlayout.cpp
}
+qtConfig(tooltip) {
+ HEADERS += kernel/qtooltip.h
+ SOURCES += kernel/qtooltip.cpp
+}
+
qtConfig(whatsthis) {
HEADERS += kernel/qwhatsthis.h
SOURCES += kernel/qwhatsthis.cpp
diff --git a/src/widgets/kernel/mac.pri b/src/widgets/kernel/mac.pri
index f7e7aa869a..d21e5d4a74 100644
--- a/src/widgets/kernel/mac.pri
+++ b/src/widgets/kernel/mac.pri
@@ -1,4 +1 @@
-macos {
- LIBS_PRIVATE += -framework AppKit -lz
- *-mwerks:INCLUDEPATH += compat
-}
+macos: LIBS_PRIVATE += -framework AppKit -lz
diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp
index 1ca5514655..f6631199d6 100644
--- a/src/widgets/kernel/qaction.cpp
+++ b/src/widgets/kernel/qaction.cpp
@@ -1153,8 +1153,9 @@ void QAction::activate(ActionEvent event)
if(event == Trigger) {
QPointer<QObject> guard = this;
if(d->checkable) {
- // the checked action of an exclusive group cannot be unchecked
- if (d->checked && (d->group && d->group->isExclusive()
+ // the checked action of an exclusive group may not be unchecked
+ if (d->checked && (d->group
+ && d->group->exclusionPolicy() == QActionGroup::ExclusionPolicy::Exclusive
&& d->group->checkedAction() == this)) {
if (!guard.isNull())
emit triggered(true);
diff --git a/src/widgets/kernel/qactiongroup.cpp b/src/widgets/kernel/qactiongroup.cpp
index 7934ae1d90..ab42b1c7aa 100644
--- a/src/widgets/kernel/qactiongroup.cpp
+++ b/src/widgets/kernel/qactiongroup.cpp
@@ -52,12 +52,16 @@ class QActionGroupPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QActionGroup)
public:
- QActionGroupPrivate() : exclusive(1), enabled(1), visible(1) { }
+ QActionGroupPrivate() : enabled(1),
+ visible(1),
+ exclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive)
+ {
+ }
QList<QAction *> actions;
QPointer<QAction> current;
- uint exclusive : 1;
uint enabled : 1;
uint visible : 1;
+ QActionGroup::ExclusionPolicy exclusionPolicy;
private:
void _q_actionTriggered(); //private slot
@@ -70,7 +74,7 @@ void QActionGroupPrivate::_q_actionChanged()
Q_Q(QActionGroup);
QAction *action = qobject_cast<QAction*>(q->sender());
Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionChanged", "internal error");
- if(exclusive) {
+ if (exclusionPolicy != QActionGroup::ExclusionPolicy::None) {
if (action->isChecked()) {
if (action != current) {
if(current)
@@ -127,12 +131,17 @@ void QActionGroupPrivate::_q_actionHovered()
actions is chosen. Each action in an action group emits its
triggered() signal as usual.
- As stated above, an action group is \l exclusive by default; it
- ensures that only one checkable action is active at any one time.
+ As stated above, an action group is exclusive by default; it
+ ensures that at most only one checkable action is active at any one time.
If you want to group checkable actions without making them
- exclusive, you can turn of exclusiveness by calling
+ exclusive, you can turn off exclusiveness by calling
setExclusive(false).
+ By default the active action of an exclusive group cannot be unchecked.
+ In some cases it may be useful to allow unchecking all the actions,
+ you can allow this by calling
+ setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional).
+
Actions can be added to an action group using addAction(), but it
is usually more convenient to specify a group when creating
actions; this ensures that actions are automatically created with
@@ -146,10 +155,33 @@ void QActionGroupPrivate::_q_actionHovered()
*/
/*!
+ \enum QActionGroup::ExclusionPolicy
+
+ This enum specifies the different policies that can be used to
+ control how the group performs exclusive checking on checkable actions.
+
+ \value None
+ The actions in the group can be checked independently of each other.
+
+ \value Exclusive
+ Exactly one action can be checked at any one time.
+ This is the default policy.
+
+ \value ExclusiveOptional
+ At most one action can be checked at any one time. The actions
+ can also be all unchecked.
+
+ \sa exclusionPolicy
+ \since 5.14
+*/
+
+/*!
Constructs an action group for the \a parent object.
The action group is exclusive by default. Call setExclusive(false)
- to make the action group non-exclusive.
+ to make the action group non-exclusive. To make the group exclusive
+ but allow unchecking the active action call instead
+ setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional)
*/
QActionGroup::QActionGroup(QObject* parent) : QObject(*new QActionGroupPrivate, parent)
{
@@ -258,26 +290,56 @@ QList<QAction*> QActionGroup::actions() const
}
/*!
- \property QActionGroup::exclusive
- \brief whether the action group does exclusive checking
+ \brief Enable or disable the group exclusion checking
- If exclusive is true, only one checkable action in the action group
- can ever be active at any time. If the user chooses another
- checkable action in the group, the one they chose becomes active and
- the one that was active becomes inactive.
+ This is a convenience method that calls
+ setExclusionPolicy(ExclusionPolicy::Exclusive).
- \sa QAction::checkable
+ \sa QActionGroup::exclusionPolicy
*/
void QActionGroup::setExclusive(bool b)
{
- Q_D(QActionGroup);
- d->exclusive = b;
+ setExclusionPolicy(b ? QActionGroup::ExclusionPolicy::Exclusive
+ : QActionGroup::ExclusionPolicy::None);
}
+/*!
+ \brief Returs true if the group is exclusive
+
+ The group is exclusive if the ExclusionPolicy is either Exclusive
+ or ExclusionOptional.
+
+*/
bool QActionGroup::isExclusive() const
{
+ return exclusionPolicy() != QActionGroup::ExclusionPolicy::None;
+}
+
+/*!
+ \property QActionGroup::exclusionPolicy
+ \brief This property holds the group exclusive checking policy
+
+ If exclusionPolicy is set to Exclusive, only one checkable
+ action in the action group can ever be active at any time. If the user
+ chooses another checkable action in the group, the one they chose becomes
+ active and the one that was active becomes inactive. If exclusionPolicy is
+ set to ExclusionOptional the group is exclusive but the active checkable
+ action in the group can be unchecked leaving the group with no actions
+ checked.
+
+ \sa QAction::checkable
+ \since 5.14
+*/
+void QActionGroup::setExclusionPolicy(QActionGroup::ExclusionPolicy policy)
+{
+ Q_D(QActionGroup);
+ d->exclusionPolicy = policy;
+}
+
+QActionGroup::ExclusionPolicy QActionGroup::exclusionPolicy() const
+{
Q_D(const QActionGroup);
- return d->exclusive;
+ return d->exclusionPolicy;
}
/*!
@@ -316,8 +378,8 @@ bool QActionGroup::isEnabled() const
}
/*!
- Returns the currently checked action in the group, or 0 if none
- are checked.
+ Returns the currently checked action in the group, or \nullptr if
+ none are checked.
*/
QAction *QActionGroup::checkedAction() const
{
diff --git a/src/widgets/kernel/qactiongroup.h b/src/widgets/kernel/qactiongroup.h
index 61c90b911d..90f488bedb 100644
--- a/src/widgets/kernel/qactiongroup.h
+++ b/src/widgets/kernel/qactiongroup.h
@@ -55,11 +55,18 @@ class Q_WIDGETS_EXPORT QActionGroup : public QObject
Q_OBJECT
Q_DECLARE_PRIVATE(QActionGroup)
- Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive)
+ Q_PROPERTY(QActionGroup::ExclusionPolicy exclusionPolicy READ exclusionPolicy WRITE setExclusionPolicy)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
public:
+ enum class ExclusionPolicy {
+ None,
+ Exclusive,
+ ExclusiveOptional
+ };
+ Q_ENUM(ExclusionPolicy)
+
explicit QActionGroup(QObject* parent);
~QActionGroup();
@@ -73,6 +80,7 @@ public:
bool isExclusive() const;
bool isEnabled() const;
bool isVisible() const;
+ ExclusionPolicy exclusionPolicy() const;
public Q_SLOTS:
@@ -80,6 +88,7 @@ public Q_SLOTS:
inline void setDisabled(bool b) { setEnabled(!b); }
void setVisible(bool);
void setExclusive(bool);
+ void setExclusionPolicy(ExclusionPolicy policy);
Q_SIGNALS:
void triggered(QAction *);
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 8e01cb17c5..526bf0a0ff 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -570,10 +570,6 @@ void QApplicationPrivate::init()
initialize();
eventDispatcher->startingUp();
-#ifdef QT_EVAL
- extern void qt_gui_eval_init(QCoreApplicationPrivate::Type);
- qt_gui_eval_init(application_type);
-#endif
#ifndef QT_NO_ACCESSIBILITY
// factory for accessible interfaces for widgets shipped with Qt
QAccessible::installFactory(&qAccessibleFactory);
@@ -767,7 +763,7 @@ QWidget *QApplication::activeModalWidget()
/*!
Cleans up any window system resources that were allocated by this
- application. Sets the global variable \c qApp to 0.
+ application. Sets the global variable \c qApp to \nullptr.
*/
QApplication::~QApplication()
@@ -876,8 +872,8 @@ void qt_cleanup()
/*!
\fn QWidget *QApplication::widgetAt(const QPoint &point)
- Returns the widget at global screen position \a point, or 0 if there is no
- Qt widget there.
+ Returns the widget at global screen position \a point, or \nullptr
+ if there is no Qt widget there.
This function can be slow.
@@ -887,9 +883,9 @@ QWidget *QApplication::widgetAt(const QPoint &p)
{
QWidget *window = QApplication::topLevelAt(p);
if (!window)
- return 0;
+ return nullptr;
- QWidget *child = 0;
+ QWidget *child = nullptr;
if (!window->testAttribute(Qt::WA_TransparentForMouseEvents))
child = window->childAt(window->mapFromGlobal(p));
@@ -925,8 +921,8 @@ QWidget *QApplication::widgetAt(const QPoint &p)
\overload
- Returns the widget at global screen position (\a x, \a y), or 0 if there is
- no Qt widget there.
+ Returns the widget at global screen position (\a x, \a y), or
+ \nullptr if there is no Qt widget there.
*/
/*!
@@ -1224,6 +1220,7 @@ QStyle* QApplication::setStyle(const QString& style)
return s;
}
+#if QT_DEPRECATED_SINCE(5, 8)
/*!
Returns the color specification.
\obsolete
@@ -1298,6 +1295,7 @@ void QApplication::setColorSpec(int spec)
{
Q_UNUSED(spec)
}
+#endif
/*!
\property QApplication::globalStrut
@@ -1409,6 +1407,7 @@ void QApplicationPrivate::setPalette_helper(const QPalette &palette, const char*
else
*QApplicationPrivate::set_pal = palette;
QCoreApplication::setAttribute(Qt::AA_SetPalette);
+ emit qGuiApp->paletteChanged(*QGuiApplicationPrivate::app_pal);
}
}
@@ -1685,13 +1684,13 @@ QWidgetList QApplication::topLevelWidgets()
QWidgetList QApplication::allWidgets()
{
if (QWidgetPrivate::allWidgets)
- return QWidgetPrivate::allWidgets->toList();
+ return QWidgetPrivate::allWidgets->values();
return QWidgetList();
}
/*!
- Returns the application widget that has the keyboard input focus, or 0 if
- no widget in this application has the focus.
+ Returns the application widget that has the keyboard input focus,
+ or \nullptr if no widget in this application has the focus.
\sa QWidget::setFocus(), QWidget::hasFocus(), activeWindow(), focusChanged()
*/
@@ -1759,7 +1758,7 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
/*!
Returns the application top-level window that has the keyboard input focus,
- or 0 if no application window has the focus. There might be an
+ or \nullptr if no application window has the focus. There might be an
activeWindow() even if there is no focusWidget(), for example if no widget
in that window accepts key events.
@@ -1864,8 +1863,8 @@ void QApplication::aboutQt()
This signal is emitted when the widget that has keyboard focus changed from
\a old to \a now, i.e., because the user pressed the tab-key, clicked into
- a widget or changed the active window. Both \a old and \a now can be the
- null-pointer.
+ a widget or changed the active window. Both \a old and \a now can be \nullptr.
+
The signal is emitted after both widget have been notified about the change
through QFocusEvent.
@@ -3853,6 +3852,7 @@ Qt::NavigationMode QApplication::navigationMode()
return QApplicationPrivate::navigationMode;
}
+# if QT_DEPRECATED_SINCE(5, 13)
/*!
Sets whether Qt should use focus navigation suitable for use with a
minimal keypad.
@@ -3895,6 +3895,7 @@ bool QApplication::keypadNavigationEnabled()
return QApplicationPrivate::navigationMode == Qt::NavigationModeKeypadTabOrder ||
QApplicationPrivate::navigationMode == Qt::NavigationModeKeypadDirectional;
}
+# endif
#endif
/*!
diff --git a/src/widgets/kernel/qapplication.h b/src/widgets/kernel/qapplication.h
index 7a5d7ba1a9..27e743a28d 100644
--- a/src/widgets/kernel/qapplication.h
+++ b/src/widgets/kernel/qapplication.h
@@ -180,8 +180,12 @@ public:
bool notify(QObject *, QEvent *) override;
#ifdef QT_KEYPAD_NAVIGATION
- static Q_DECL_DEPRECATED void setKeypadNavigationEnabled(bool);
- static bool keypadNavigationEnabled();
+# if QT_DEPRECATED_SINCE(5, 13)
+ static QT_DEPRECATED_X ("Use QApplication::setNavigationMode() instead")
+ void setKeypadNavigationEnabled(bool);
+ static QT_DEPRECATED_X ("Use QApplication::navigationMode() instead")
+ bool keypadNavigationEnabled();
+# endif
static void setNavigationMode(Qt::NavigationMode mode);
static Qt::NavigationMode navigationMode();
#endif
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 133279f977..98eb9b73c6 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -128,10 +128,10 @@ public:
void notifyWindowIconChanged() override;
//modality
- bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = 0) const override;
+ bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = nullptr) const override;
static bool isBlockedByModal(QWidget *widget);
static bool modalState();
- static bool tryModalHelper(QWidget *widget, QWidget **rettop = 0);
+ static bool tryModalHelper(QWidget *widget, QWidget **rettop = nullptr);
#if 0 // Used to be included in Qt4 for Q_WS_MAC
static QWidget *tryModalHelper_sys(QWidget *top);
bool canQuit();
@@ -157,7 +157,7 @@ public:
void openPopup(QWidget *popup);
static void setFocusWidget(QWidget *focus, Qt::FocusReason reason);
static QWidget *focusNextPrevChild_helper(QWidget *toplevel, bool next,
- bool *wrappingOccurred = 0);
+ bool *wrappingOccurred = nullptr);
#if QT_CONFIG(graphicsview)
// Maintain a list of all scenes to ensure font and palette propagation to
@@ -238,7 +238,7 @@ public:
return window;
if (const QWidget *nativeParent = widget->nativeParentWidget())
return nativeParent->windowHandle();
- return 0;
+ return nullptr;
}
#ifdef Q_OS_WIN
diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp
index 5fb7882932..ac0cfcf2f5 100644
--- a/src/widgets/kernel/qdesktopwidget.cpp
+++ b/src/widgets/kernel/qdesktopwidget.cpp
@@ -176,26 +176,32 @@ void QDesktopWidgetPrivate::_q_updateScreens()
// Notice that we trigger screenCountChanged even if a screen was removed and another one added,
// in which case the total number of screens did not change. This is the only way for applications
// to notice that a screen was swapped out against another one.
+#if QT_DEPRECATED_SINCE(5, 11)
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
emit q->screenCountChanged(targetLength);
QT_WARNING_POP
+#endif
}
+#if QT_DEPRECATED_SINCE(5, 11)
foreach (int changedScreen, changedScreens)
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
emit q->resized(changedScreen);
QT_WARNING_POP
+#endif
}
void QDesktopWidgetPrivate::_q_availableGeometryChanged()
{
+#if QT_DEPRECATED_SINCE(5, 11)
Q_Q(QDesktopWidget);
if (QScreen *screen = qobject_cast<QScreen *>(q->sender()))
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
emit q->workAreaResized(QGuiApplication::screens().indexOf(screen));
QT_WARNING_POP
+#endif
}
QDesktopWidget::QDesktopWidget()
@@ -212,10 +218,12 @@ QDesktopWidget::~QDesktopWidget()
{
}
+#if QT_DEPRECATED_SINCE(5, 11)
bool QDesktopWidget::isVirtualDesktop() const
{
return QDesktopWidgetPrivate::isVirtualDesktop();
}
+#endif
bool QDesktopWidgetPrivate::isVirtualDesktop()
{
@@ -242,24 +250,27 @@ int QDesktopWidgetPrivate::height()
return geometry().height();
}
+#if QT_DEPRECATED_SINCE(5, 11)
int QDesktopWidget::primaryScreen() const
{
return QDesktopWidgetPrivate::primaryScreen();
}
+#endif
int QDesktopWidgetPrivate::primaryScreen()
{
return 0;
}
-int QDesktopWidget::numScreens() const
+int QDesktopWidgetPrivate::numScreens()
{
- return QDesktopWidgetPrivate::numScreens();
+ return qMax(QGuiApplication::screens().size(), 1);
}
-int QDesktopWidgetPrivate::numScreens()
+#if QT_DEPRECATED_SINCE(5, 11)
+int QDesktopWidget::numScreens() const
{
- return qMax(QGuiApplication::screens().size(), 1);
+ return QDesktopWidgetPrivate::numScreens();
}
QWidget *QDesktopWidget::screen(int screen)
@@ -274,6 +285,7 @@ const QRect QDesktopWidget::availableGeometry(int screenNo) const
{
return QDesktopWidgetPrivate::availableGeometry(screenNo);
}
+#endif
const QRect QDesktopWidgetPrivate::availableGeometry(int screenNo)
{
@@ -281,10 +293,12 @@ const QRect QDesktopWidgetPrivate::availableGeometry(int screenNo)
return screen ? screen->availableGeometry() : QRect();
}
+#if QT_DEPRECATED_SINCE(5, 11)
const QRect QDesktopWidget::screenGeometry(int screenNo) const
{
return QDesktopWidgetPrivate::screenGeometry(screenNo);
}
+#endif
const QRect QDesktopWidgetPrivate::screenGeometry(int screenNo)
{
@@ -307,20 +321,12 @@ int QDesktopWidgetPrivate::screenNumber(const QWidget *w)
if (screens.isEmpty()) // This should never happen
return primaryScreen();
- const QWindow *winHandle = w->windowHandle();
- if (!winHandle) {
- if (const QWidget *nativeParent = w->nativeParentWidget())
- winHandle = nativeParent->windowHandle();
- }
-
// If there is more than one virtual desktop
if (screens.count() != screens.constFirst()->virtualSiblings().count()) {
// Find the root widget, get a QScreen from it and use the
// virtual siblings for checking the window position.
- if (winHandle) {
- if (const QScreen *winScreen = winHandle->screen())
- screens = winScreen->virtualSiblings();
- }
+ if (const QScreen *winScreen = qt_widget_private(const_cast<QWidget *>(w))->associatedScreen())
+ screens = winScreen->virtualSiblings();
}
// Get the screen number from window position using screen geometry
@@ -344,10 +350,12 @@ int QDesktopWidgetPrivate::screenNumber(const QWidget *w)
return allScreens.indexOf(widgetScreen);
}
+#if QT_DEPRECATED_SINCE(5, 11)
int QDesktopWidget::screenNumber(const QPoint &p) const
{
return QDesktopWidgetPrivate::screenNumber(p);
}
+#endif
int QDesktopWidgetPrivate::screenNumber(const QPoint &p)
{
diff --git a/src/widgets/kernel/qdesktopwidget.h b/src/widgets/kernel/qdesktopwidget.h
index f986f0db20..e5c587984f 100644
--- a/src/widgets/kernel/qdesktopwidget.h
+++ b/src/widgets/kernel/qdesktopwidget.h
@@ -52,9 +52,11 @@ class QDesktopWidgetPrivate;
class Q_WIDGETS_EXPORT QDesktopWidget : public QWidget
{
Q_OBJECT
+#if QT_DEPRECATED_SINCE(5, 11)
Q_PROPERTY(bool virtualDesktop READ isVirtualDesktop)
Q_PROPERTY(int screenCount READ screenCount NOTIFY screenCountChanged)
Q_PROPERTY(int primaryScreen READ primaryScreen NOTIFY primaryScreenChanged)
+#endif
public:
QDesktopWidget();
~QDesktopWidget();
diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp
index 600934b8a1..9146ba84c8 100644
--- a/src/widgets/kernel/qformlayout.cpp
+++ b/src/widgets/kernel/qformlayout.cpp
@@ -419,13 +419,15 @@ void QFormLayoutPrivate::updateSizes()
if (label) {
maxMinLblWidth = qMax(maxMinLblWidth, label->minSize.width());
maxShLblWidth = qMax(maxShLblWidth, label->sizeHint.width());
- if (field) {
+ }
+ if (field) {
+ if (field->fullRow) {
+ maxMinIfldWidth = qMax(maxMinIfldWidth, field->minSize.width());
+ maxShIfldWidth = qMax(maxShIfldWidth, field->sizeHint.width());
+ } else {
maxMinFldWidth = qMax(maxMinFldWidth, field->minSize.width() + field->sbsHSpace);
maxShFldWidth = qMax(maxShFldWidth, field->sizeHint.width() + field->sbsHSpace);
}
- } else if (field) {
- maxMinIfldWidth = qMax(maxMinIfldWidth, field->minSize.width());
- maxShIfldWidth = qMax(maxShIfldWidth, field->sizeHint.width());
}
prevLbl = label;
@@ -781,7 +783,7 @@ void QFormLayoutPrivate::setupVerticalLayoutData(int width)
vLayouts[vidx].expansive = expanding || (vLayouts[vidx].stretch > 0);
vLayouts[vidx].empty = false;
- if (vLayouts[vidx].stretch > 0)
+ if (vLayouts[vidx].expansive)
addTopBottomStretch = false;
if (vidx > 1)
@@ -2207,8 +2209,11 @@ void QFormLayoutPrivate::arrangeWidgets(const QVector<QLayoutStruct>& layouts, Q
QSize sz(qMin(label->layoutWidth, label->sizeHint.width()), height);
int x = leftOffset + rect.x() + label->layoutPos;
- if (fixedAlignment(q->labelAlignment(), layoutDirection) & Qt::AlignRight)
+ const auto fAlign = fixedAlignment(q->labelAlignment(), layoutDirection);
+ if (fAlign & Qt::AlignRight)
x += label->layoutWidth - sz.width();
+ else if (fAlign & Qt::AlignHCenter)
+ x += label->layoutWidth / 2 - sz.width() / 2;
QPoint p(x, layouts.at(label->vLayoutIndex).pos);
// ### expansion & sizepolicy stuff
diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h
index 636103c1e1..cbf8d60892 100644
--- a/src/widgets/kernel/qgesture_p.h
+++ b/src/widgets/kernel/qgesture_p.h
@@ -111,7 +111,7 @@ class QPinchGesturePrivate : public QGesturePrivate
public:
QPinchGesturePrivate()
- : totalChangeFlags(0), changeFlags(0),
+ : totalChangeFlags(nullptr), changeFlags(nullptr),
totalScaleFactor(1), lastScaleFactor(1), scaleFactor(1),
totalRotationAngle(0), lastRotationAngle(0), rotationAngle(0),
isNewSequence(true)
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 891858b035..ff7bc1eccf 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -136,7 +136,7 @@ Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *r
++m_lastCustomGestureId;
type = Qt::GestureType(m_lastCustomGestureId);
}
- m_recognizers.insertMulti(type, recognizer);
+ m_recognizers.insert(type, recognizer);
return type;
}
@@ -167,30 +167,26 @@ void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType type)
{
- QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin();
- while (iter != m_objectGestures.end()) {
- ObjectGesture objectGesture = iter.key();
- if (objectGesture.gesture == type && target == objectGesture.object) {
- QSet<QGesture *> gestures = iter.value().toSet();
- for (QHash<QGestureRecognizer *, QSet<QGesture *> >::iterator
- it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) {
- it.value() -= gestures;
- }
- foreach (QGesture *g, gestures) {
- m_deletedRecognizers.remove(g);
- m_gestureToRecognizer.remove(g);
- m_maybeGestures.remove(g);
- m_activeGestures.remove(g);
- m_gestureOwners.remove(g);
- m_gestureTargets.remove(g);
- m_gesturesToDelete.insert(g);
- }
+ const auto iter = m_objectGestures.find({target, type});
+ if (iter == m_objectGestures.end())
+ return;
- iter = m_objectGestures.erase(iter);
- } else {
- ++iter;
- }
+ const QList<QGesture *> &gestures = iter.value();
+ for (auto &e : m_obsoleteGestures) {
+ for (QGesture *g : gestures)
+ e -= g;
}
+ for (QGesture *g : gestures) {
+ m_deletedRecognizers.remove(g);
+ m_gestureToRecognizer.remove(g);
+ m_maybeGestures.remove(g);
+ m_activeGestures.remove(g);
+ m_gestureOwners.remove(g);
+ m_gestureTargets.remove(g);
+ m_gesturesToDelete.insert(g);
+ }
+
+ m_objectGestures.erase(iter);
}
// get or create a QGesture object that will represent the state for a given object, used by the recognizer
@@ -509,15 +505,15 @@ void QGestureManager::cleanupGesturesForRemovedRecognizer(QGesture *gesture)
// return true if accepted (consumed)
bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
{
- QMap<Qt::GestureType, int> types;
+ QVarLengthArray<Qt::GestureType, 16> types;
QMultiMap<QObject *, Qt::GestureType> contexts;
QWidget *w = receiver;
typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
if (!w->d_func()->gestureContext.isEmpty()) {
for(ContextIterator it = w->d_func()->gestureContext.constBegin(),
e = w->d_func()->gestureContext.constEnd(); it != e; ++it) {
- types.insert(it.key(), 0);
- contexts.insertMulti(w, it.key());
+ types.push_back(it.key());
+ contexts.insert(w, it.key());
}
}
// find all gesture contexts for the widget tree
@@ -528,8 +524,8 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
e = w->d_func()->gestureContext.constEnd(); it != e; ++it) {
if (!(it.value() & Qt::DontStartGestureOnChildren)) {
if (!types.contains(it.key())) {
- types.insert(it.key(), 0);
- contexts.insertMulti(w, it.key());
+ types.push_back(it.key());
+ contexts.insert(w, it.key());
}
}
}
@@ -543,15 +539,15 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event)
#if QT_CONFIG(graphicsview)
bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
{
- QMap<Qt::GestureType, int> types;
+ QVarLengthArray<Qt::GestureType, 16> types;
QMultiMap<QObject *, Qt::GestureType> contexts;
QGraphicsObject *item = receiver;
if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator;
for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.constBegin(),
e = item->QGraphicsItem::d_func()->gestureContext.constEnd(); it != e; ++it) {
- types.insert(it.key(), 0);
- contexts.insertMulti(item, it.key());
+ types.push_back(it.key());
+ contexts.insert(item, it.key());
}
}
// find all gesture contexts for the graphics object tree
@@ -563,8 +559,8 @@ bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event)
e = item->QGraphicsItem::d_func()->gestureContext.constEnd(); it != e; ++it) {
if (!(it.value() & Qt::DontStartGestureOnChildren)) {
if (!types.contains(it.key())) {
- types.insert(it.key(), 0);
- contexts.insertMulti(item, it.key());
+ types.push_back(it.key());
+ contexts.insert(item, it.key());
}
}
}
diff --git a/src/widgets/kernel/qgridlayout.cpp b/src/widgets/kernel/qgridlayout.cpp
index f1c6c96a6d..4f2b505e32 100644
--- a/src/widgets/kernel/qgridlayout.cpp
+++ b/src/widgets/kernel/qgridlayout.cpp
@@ -1330,8 +1330,8 @@ QLayoutItem *QGridLayout::itemAt(int index) const
/*!
\since 4.4
- Returns the layout item that occupies cell (\a row, \a column), or 0 if
- the cell is empty.
+ Returns the layout item that occupies cell (\a row, \a column), or
+ \nullptr if the cell is empty.
\sa getItemPosition(), indexOf()
*/
@@ -1346,7 +1346,7 @@ QLayoutItem *QGridLayout::itemAtPosition(int row, int column) const
return box->item();
}
}
- return 0;
+ return nullptr;
}
/*!
diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp
index eac5674161..f71d038a5f 100644
--- a/src/widgets/kernel/qlayout.cpp
+++ b/src/widgets/kernel/qlayout.cpp
@@ -109,7 +109,7 @@ static int menuBarHeightForWidth(QWidget *menubar, int w)
/*!
Constructs a new top-level QLayout, with parent \a parent.
- \a parent may not be a \c nullptr.
+ \a parent may not be \nullptr.
The layout is set directly as the top-level layout for
\a parent. There can be only one top-level layout for a
@@ -282,6 +282,7 @@ bool QLayout::setAlignment(QLayout *l, Qt::Alignment alignment)
return false;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\property QLayout::margin
\brief the width of the outside border of the layout
@@ -307,6 +308,15 @@ int QLayout::margin() const
}
/*!
+ \obsolete
+*/
+void QLayout::setMargin(int margin)
+{
+ setContentsMargins(margin, margin, margin, margin);
+}
+
+#endif
+/*!
\property QLayout::spacing
\brief the spacing between widgets inside the layout
@@ -344,14 +354,6 @@ int QLayout::spacing() const
}
}
-/*!
- \obsolete
-*/
-void QLayout::setMargin(int margin)
-{
- setContentsMargins(margin, margin, margin, margin);
-}
-
void QLayout::setSpacing(int spacing)
{
if (QBoxLayout* boxlayout = qobject_cast<QBoxLayout*>(this)) {
@@ -417,9 +419,9 @@ void QLayout::setContentsMargins(const QMargins &margins)
/*!
\since 4.3
- Extracts the left, top, right, and bottom margins used around the
- layout, and assigns them to *\a left, *\a top, *\a right, and *\a
- bottom (unless they are null pointers).
+ For each of \a left, \a top, \a right and \a bottom that is not
+ \nullptr, stores the size of the margin named in the location the
+ pointer refers to.
By default, QLayout uses the values provided by the style. On
most platforms, the margin is 11 pixels in all directions.
@@ -474,8 +476,8 @@ QRect QLayout::contentsRect() const
/*!
- Returns the parent widget of this layout, or 0 if this layout is
- not installed on any widget.
+ Returns the parent widget of this layout, or \nullptr if this
+ layout is not installed on any widget.
If the layout is a sub-layout, this function returns the parent
widget of the parent layout.
@@ -490,11 +492,11 @@ QWidget *QLayout::parentWidget() const
QLayout *parentLayout = qobject_cast<QLayout*>(parent());
if (Q_UNLIKELY(!parentLayout)) {
qWarning("QLayout::parentWidget: A layout can only have another layout as a parent.");
- return 0;
+ return nullptr;
}
return parentLayout->parentWidget();
} else {
- return 0;
+ return nullptr;
}
} else {
Q_ASSERT(parent() && parent()->isWidgetType());
@@ -950,8 +952,8 @@ void QLayout::setMenuBar(QWidget *widget)
}
/*!
- Returns the menu bar set for this layout, or 0 if no menu bar is
- set.
+ Returns the menu bar set for this layout, or \nullptr if no
+ menu bar is set.
*/
QWidget *QLayout::menuBar() const
@@ -1130,8 +1132,9 @@ bool QLayout::activate()
Searches for widget \a from and replaces it with widget \a to if found.
Returns the layout item that contains the widget \a from on success.
- Otherwise \c 0 is returned. If \a options contains \c Qt::FindChildrenRecursively
- (the default), sub-layouts are searched for doing the replacement.
+ Otherwise \nullptr is returned.
+ If \a options contains \c Qt::FindChildrenRecursively (the default),
+ sub-layouts are searched for doing the replacement.
Any other flag in \a options is ignored.
Notice that the returned item therefore might not belong to this layout,
@@ -1153,6 +1156,8 @@ QLayoutItem *QLayout::replaceWidget(QWidget *from, QWidget *to, Qt::FindChildOpt
Q_D(QLayout);
if (!from || !to)
return 0;
+ if (from == to) // Do not return a QLayoutItem for \a from, since ownership still
+ return nullptr; // belongs to the layout (since nothing was changed)
int index = -1;
QLayoutItem *item = 0;
diff --git a/src/widgets/kernel/qlayout.h b/src/widgets/kernel/qlayout.h
index 616f4e7164..35a04a35b2 100644
--- a/src/widgets/kernel/qlayout.h
+++ b/src/widgets/kernel/qlayout.h
@@ -63,7 +63,9 @@ class Q_WIDGETS_EXPORT QLayout : public QObject, public QLayoutItem
Q_OBJECT
Q_DECLARE_PRIVATE(QLayout)
+#if QT_DEPRECATED_SINCE(5, 13)
Q_PROPERTY(int margin READ margin WRITE setMargin)
+#endif
Q_PROPERTY(int spacing READ spacing WRITE setSpacing)
Q_PROPERTY(SizeConstraint sizeConstraint READ sizeConstraint WRITE setSizeConstraint)
public:
@@ -81,10 +83,12 @@ public:
QLayout();
~QLayout();
+#if QT_DEPRECATED_SINCE(5, 13)
int margin() const;
- int spacing() const;
-
void setMargin(int);
+#endif
+
+ int spacing() const;
void setSpacing(int);
void setContentsMargins(int left, int top, int right, int bottom);
diff --git a/src/widgets/kernel/qlayout_p.h b/src/widgets/kernel/qlayout_p.h
index 8a1b12a6be..8e1d773355 100644
--- a/src/widgets/kernel/qlayout_p.h
+++ b/src/widgets/kernel/qlayout_p.h
@@ -80,7 +80,7 @@ public:
static QWidgetItem *createWidgetItem(const QLayout *layout, QWidget *widget);
static QSpacerItem *createSpacerItem(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy = QSizePolicy::Minimum, QSizePolicy::Policy vPolicy = QSizePolicy::Minimum);
- virtual QLayoutItem* replaceAt(int index, QLayoutItem *newitem) { Q_UNUSED(index); Q_UNUSED(newitem); return 0; }
+ virtual QLayoutItem* replaceAt(int index, QLayoutItem *newitem) { Q_UNUSED(index); Q_UNUSED(newitem); return nullptr; }
static QWidgetItemFactoryMethod widgetItemFactoryMethod;
static QSpacerItemFactoryMethod spacerItemFactoryMethod;
diff --git a/src/widgets/kernel/qlayoutengine_p.h b/src/widgets/kernel/qlayoutengine_p.h
index 812fa7cf3b..948c2424e6 100644
--- a/src/widgets/kernel/qlayoutengine_p.h
+++ b/src/widgets/kernel/qlayoutengine_p.h
@@ -105,9 +105,9 @@ Q_WIDGETS_EXPORT QSize qSmartMinSize(const QWidgetItem *i);
Q_WIDGETS_EXPORT QSize qSmartMinSize(const QWidget *w);
Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QSize &sizeHint,
const QSize &minSize, const QSize &maxSize,
- const QSizePolicy &sizePolicy, Qt::Alignment align = 0);
-Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QWidgetItem *i, Qt::Alignment align = 0);
-Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QWidget *w, Qt::Alignment align = 0);
+ const QSizePolicy &sizePolicy, Qt::Alignment align = nullptr);
+Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QWidgetItem *i, Qt::Alignment align = nullptr);
+Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QWidget *w, Qt::Alignment align = nullptr);
Q_WIDGETS_EXPORT int qSmartSpacing(const QLayout *layout, QStyle::PixelMetric pm);
diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp
index 25890e888b..0aab0bb06d 100644
--- a/src/widgets/kernel/qlayoutitem.cpp
+++ b/src/widgets/kernel/qlayoutitem.cpp
@@ -309,24 +309,24 @@ void QLayoutItem::invalidate()
/*!
If this item is a QLayout, it is returned as a QLayout; otherwise
- 0 is returned. This function provides type-safe casting.
+ \nullptr is returned. This function provides type-safe casting.
\sa spacerItem(), widget()
*/
-QLayout * QLayoutItem::layout()
+QLayout *QLayoutItem::layout()
{
- return 0;
+ return nullptr;
}
/*!
If this item is a QSpacerItem, it is returned as a QSpacerItem;
- otherwise 0 is returned. This function provides type-safe casting.
+ otherwise \nullptr is returned. This function provides type-safe casting.
\sa layout(), widget()
*/
-QSpacerItem * QLayoutItem::spacerItem()
+QSpacerItem *QLayoutItem::spacerItem()
{
- return 0;
+ return nullptr;
}
/*!
@@ -354,7 +354,7 @@ QSpacerItem * QSpacerItem::spacerItem()
/*!
If this item manages a QWidget, returns that widget. Otherwise,
- \c nullptr is returned.
+ \nullptr is returned.
\note While the functions layout() and spacerItem() perform casts, this
function returns another object: QLayout and QSpacerItem inherit QLayoutItem,
@@ -362,9 +362,9 @@ QSpacerItem * QSpacerItem::spacerItem()
\sa layout(), spacerItem()
*/
-QWidget * QLayoutItem::widget()
+QWidget *QLayoutItem::widget()
{
- return 0;
+ return nullptr;
}
/*!
@@ -502,6 +502,17 @@ void QWidgetItem::setGeometry(const QRect &rect)
else if (!(align & Qt::AlignTop))
y = y + (r.height() - s.height()) / 2;
+ // Make sure we don't move outside of the parent, e.g when styles demand
+ // surplus space that exceeds the available margins (f.ex macOS with QGroupBox)
+ if (x < 0) {
+ s.rwidth() += x;
+ x = 0;
+ }
+ if (y < 0) {
+ s.rheight() += y;
+ y = 0;
+ }
+
wid->setGeometry(x, y, s.width(), s.height());
}
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 7aef74c507..ae7729b49b 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -1118,8 +1118,8 @@ void QOpenGLWidget::setTextureFormat(GLenum texFormat)
/*!
\return the active internal texture format if the widget has already
initialized, the requested format if one was set but the widget has not yet
- been made visible, or 0 if setTextureFormat() was not called and the widget
- has not yet been made visible.
+ been made visible, or \nullptr if setTextureFormat() was not called and the
+ widget has not yet been made visible.
\since 5.10
*/
@@ -1333,11 +1333,8 @@ int QOpenGLWidget::metric(QPaintDevice::PaintDeviceMetric metric) const
if (d->inBackingStorePaint)
return QWidget::metric(metric);
- QWidget *tlw = window();
- QWindow *window = tlw ? tlw->windowHandle() : 0;
- QScreen *screen = tlw && tlw->windowHandle() ? tlw->windowHandle()->screen() : 0;
- if (!screen && QGuiApplication::primaryScreen())
- screen = QGuiApplication::primaryScreen();
+ auto window = d->windowHandle(QWidgetPrivate::WindowHandleMode::TopLevel);
+ QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen();
const float dpmx = qt_defaultDpiX() * 100. / 2.54;
const float dpmy = qt_defaultDpiY() * 100. / 2.54;
diff --git a/src/widgets/kernel/qsizepolicy.cpp b/src/widgets/kernel/qsizepolicy.cpp
index b5a0cd3940..54bf8fe0dc 100644
--- a/src/widgets/kernel/qsizepolicy.cpp
+++ b/src/widgets/kernel/qsizepolicy.cpp
@@ -232,7 +232,7 @@ QT_BEGIN_NAMESPACE
Returns the control type associated with the widget for which
this size policy applies.
*/
-QSizePolicy::ControlType QSizePolicy::controlType() const Q_DECL_NOTHROW
+QSizePolicy::ControlType QSizePolicy::controlType() const noexcept
{
return QSizePolicy::ControlType(1 << bits.ctype);
}
@@ -253,7 +253,7 @@ QSizePolicy::ControlType QSizePolicy::controlType() const Q_DECL_NOTHROW
\sa QStyle::layoutSpacing()
*/
-void QSizePolicy::setControlType(ControlType type) Q_DECL_NOTHROW
+void QSizePolicy::setControlType(ControlType type) noexcept
{
bits.ctype = toControlTypeFieldValue(type);
}
diff --git a/src/widgets/kernel/qsizepolicy.h b/src/widgets/kernel/qsizepolicy.h
index dba742dec5..f26923eeb0 100644
--- a/src/widgets/kernel/qsizepolicy.h
+++ b/src/widgets/kernel/qsizepolicy.h
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
class QVariant;
class QSizePolicy;
-Q_DECL_CONST_FUNCTION inline uint qHash(QSizePolicy key, uint seed = 0) Q_DECL_NOTHROW;
+Q_DECL_CONST_FUNCTION inline uint qHash(QSizePolicy key, uint seed = 0) noexcept;
class Q_WIDGETS_EXPORT QSizePolicy
{
@@ -110,60 +110,60 @@ public:
Q_DECLARE_FLAGS(ControlTypes, ControlType)
Q_FLAG(ControlTypes)
- QT_SIZEPOLICY_CONSTEXPR QSizePolicy() Q_DECL_NOTHROW : data(0) { }
+ QT_SIZEPOLICY_CONSTEXPR QSizePolicy() noexcept : data(0) { }
#if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_QDOC)
- QT_SIZEPOLICY_CONSTEXPR QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) Q_DECL_NOTHROW
+ QT_SIZEPOLICY_CONSTEXPR QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) noexcept
: bits{0, 0, quint32(horizontal), quint32(vertical),
type == DefaultType ? 0 : toControlTypeFieldValue(type), 0, 0, 0}
{}
#else
- QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) Q_DECL_NOTHROW
+ QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) noexcept
: data(0) {
bits.horPolicy = horizontal;
bits.verPolicy = vertical;
setControlType(type);
}
#endif // uniform-init
- QT_SIZEPOLICY_CONSTEXPR Policy horizontalPolicy() const Q_DECL_NOTHROW { return static_cast<Policy>(bits.horPolicy); }
- QT_SIZEPOLICY_CONSTEXPR Policy verticalPolicy() const Q_DECL_NOTHROW { return static_cast<Policy>(bits.verPolicy); }
- ControlType controlType() const Q_DECL_NOTHROW;
+ QT_SIZEPOLICY_CONSTEXPR Policy horizontalPolicy() const noexcept { return static_cast<Policy>(bits.horPolicy); }
+ QT_SIZEPOLICY_CONSTEXPR Policy verticalPolicy() const noexcept { return static_cast<Policy>(bits.verPolicy); }
+ ControlType controlType() const noexcept;
- Q_DECL_RELAXED_CONSTEXPR void setHorizontalPolicy(Policy d) Q_DECL_NOTHROW { bits.horPolicy = d; }
- Q_DECL_RELAXED_CONSTEXPR void setVerticalPolicy(Policy d) Q_DECL_NOTHROW { bits.verPolicy = d; }
- void setControlType(ControlType type) Q_DECL_NOTHROW;
+ Q_DECL_RELAXED_CONSTEXPR void setHorizontalPolicy(Policy d) noexcept { bits.horPolicy = d; }
+ Q_DECL_RELAXED_CONSTEXPR void setVerticalPolicy(Policy d) noexcept { bits.verPolicy = d; }
+ void setControlType(ControlType type) noexcept;
- QT_SIZEPOLICY_CONSTEXPR Qt::Orientations expandingDirections() const Q_DECL_NOTHROW {
+ QT_SIZEPOLICY_CONSTEXPR Qt::Orientations expandingDirections() const noexcept {
return ( (verticalPolicy() & ExpandFlag) ? Qt::Vertical : Qt::Orientations() )
| ( (horizontalPolicy() & ExpandFlag) ? Qt::Horizontal : Qt::Orientations() ) ;
}
- Q_DECL_RELAXED_CONSTEXPR void setHeightForWidth(bool b) Q_DECL_NOTHROW { bits.hfw = b; }
- QT_SIZEPOLICY_CONSTEXPR bool hasHeightForWidth() const Q_DECL_NOTHROW { return bits.hfw; }
- Q_DECL_RELAXED_CONSTEXPR void setWidthForHeight(bool b) Q_DECL_NOTHROW { bits.wfh = b; }
- QT_SIZEPOLICY_CONSTEXPR bool hasWidthForHeight() const Q_DECL_NOTHROW { return bits.wfh; }
+ Q_DECL_RELAXED_CONSTEXPR void setHeightForWidth(bool b) noexcept { bits.hfw = b; }
+ QT_SIZEPOLICY_CONSTEXPR bool hasHeightForWidth() const noexcept { return bits.hfw; }
+ Q_DECL_RELAXED_CONSTEXPR void setWidthForHeight(bool b) noexcept { bits.wfh = b; }
+ QT_SIZEPOLICY_CONSTEXPR bool hasWidthForHeight() const noexcept { return bits.wfh; }
- QT_SIZEPOLICY_CONSTEXPR bool operator==(const QSizePolicy& s) const Q_DECL_NOTHROW { return data == s.data; }
- QT_SIZEPOLICY_CONSTEXPR bool operator!=(const QSizePolicy& s) const Q_DECL_NOTHROW { return data != s.data; }
+ QT_SIZEPOLICY_CONSTEXPR bool operator==(const QSizePolicy& s) const noexcept { return data == s.data; }
+ QT_SIZEPOLICY_CONSTEXPR bool operator!=(const QSizePolicy& s) const noexcept { return data != s.data; }
- friend Q_DECL_CONST_FUNCTION uint qHash(QSizePolicy key, uint seed) Q_DECL_NOTHROW { return qHash(key.data, seed); }
+ friend Q_DECL_CONST_FUNCTION uint qHash(QSizePolicy key, uint seed) noexcept { return qHash(key.data, seed); }
operator QVariant() const;
- QT_SIZEPOLICY_CONSTEXPR int horizontalStretch() const Q_DECL_NOTHROW { return static_cast<int>(bits.horStretch); }
- QT_SIZEPOLICY_CONSTEXPR int verticalStretch() const Q_DECL_NOTHROW { return static_cast<int>(bits.verStretch); }
+ QT_SIZEPOLICY_CONSTEXPR int horizontalStretch() const noexcept { return static_cast<int>(bits.horStretch); }
+ QT_SIZEPOLICY_CONSTEXPR int verticalStretch() const noexcept { return static_cast<int>(bits.verStretch); }
Q_DECL_RELAXED_CONSTEXPR void setHorizontalStretch(int stretchFactor) { bits.horStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); }
Q_DECL_RELAXED_CONSTEXPR void setVerticalStretch(int stretchFactor) { bits.verStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); }
- QT_SIZEPOLICY_CONSTEXPR bool retainSizeWhenHidden() const Q_DECL_NOTHROW { return bits.retainSizeWhenHidden; }
- Q_DECL_RELAXED_CONSTEXPR void setRetainSizeWhenHidden(bool retainSize) Q_DECL_NOTHROW { bits.retainSizeWhenHidden = retainSize; }
+ QT_SIZEPOLICY_CONSTEXPR bool retainSizeWhenHidden() const noexcept { return bits.retainSizeWhenHidden; }
+ Q_DECL_RELAXED_CONSTEXPR void setRetainSizeWhenHidden(bool retainSize) noexcept { bits.retainSizeWhenHidden = retainSize; }
- Q_DECL_RELAXED_CONSTEXPR void transpose() Q_DECL_NOTHROW { *this = transposed(); }
+ Q_DECL_RELAXED_CONSTEXPR void transpose() noexcept { *this = transposed(); }
Q_REQUIRED_RESULT
#ifndef Q_QDOC
QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT
#endif
- QSizePolicy transposed() const Q_DECL_NOTHROW
+ QSizePolicy transposed() const noexcept
{
return QSizePolicy(bits.transposed());
}
@@ -173,11 +173,11 @@ private:
friend Q_WIDGETS_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &);
friend Q_WIDGETS_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &);
#endif
- QT_SIZEPOLICY_CONSTEXPR QSizePolicy(int i) Q_DECL_NOTHROW : data(i) { }
+ QT_SIZEPOLICY_CONSTEXPR QSizePolicy(int i) noexcept : data(i) { }
struct Bits;
- QT_SIZEPOLICY_CONSTEXPR explicit QSizePolicy(Bits b) Q_DECL_NOTHROW : bits(b) { }
+ QT_SIZEPOLICY_CONSTEXPR explicit QSizePolicy(Bits b) noexcept : bits(b) { }
- static Q_DECL_RELAXED_CONSTEXPR quint32 toControlTypeFieldValue(ControlType type) Q_DECL_NOTHROW
+ static Q_DECL_RELAXED_CONSTEXPR quint32 toControlTypeFieldValue(ControlType type) noexcept
{
/*
The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10,
@@ -207,7 +207,7 @@ private:
quint32 retainSizeWhenHidden : 1;
QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT
- Bits transposed() const Q_DECL_NOTHROW
+ Bits transposed() const noexcept
{
return {verStretch, // \ swap
horStretch, // /
diff --git a/src/widgets/kernel/qstackedlayout.cpp b/src/widgets/kernel/qstackedlayout.cpp
index 7430d833db..0412dc188d 100644
--- a/src/widgets/kernel/qstackedlayout.cpp
+++ b/src/widgets/kernel/qstackedlayout.cpp
@@ -378,20 +378,20 @@ void QStackedLayout::setCurrentWidget(QWidget *widget)
/*!
- Returns the current widget, or 0 if there are no widgets in this
- layout.
+ Returns the current widget, or \nullptr if there are no widgets
+ in this layout.
\sa currentIndex(), setCurrentWidget()
*/
QWidget *QStackedLayout::currentWidget() const
{
Q_D(const QStackedLayout);
- return d->index >= 0 ? d->list.at(d->index)->widget() : 0;
+ return d->index >= 0 ? d->list.at(d->index)->widget() : nullptr;
}
/*!
- Returns the widget at the given \a index, or 0 if there is no
- widget at the given position.
+ Returns the widget at the given \a index, or \nullptr if there is
+ no widget at the given position.
\sa currentWidget(), indexOf()
*/
@@ -399,7 +399,7 @@ QWidget *QStackedLayout::widget(int index) const
{
Q_D(const QStackedLayout);
if (index < 0 || index >= d->list.size())
- return 0;
+ return nullptr;
return d->list.at(index)->widget();
}
diff --git a/src/widgets/kernel/qt_widgets_pch.h b/src/widgets/kernel/qt_widgets_pch.h
index bec6536637..b70941950b 100644
--- a/src/widgets/kernel/qt_widgets_pch.h
+++ b/src/widgets/kernel/qt_widgets_pch.h
@@ -45,41 +45,17 @@
* UNSUPPORTED.
*/
-// from corelib/global/qt_pch.h
+#include "../../gui/kernel/qt_gui_pch.h"
+
#if defined __cplusplus
#include <qtwidgetsglobal.h>
-
-
-#if 0 // Used to be included in Qt4 for Q_WS_WIN
-# define _POSIX_
-# include <limits.h>
-# undef _POSIX_
-#endif
-
-#include <qcoreapplication.h>
-#include <qlist.h>
-#include <qvariant.h> // All moc genereated code has this include
-#include <qobject.h>
-#include <qregexp.h>
-#include <qstring.h>
-#include <qstringlist.h>
-#if QT_CONFIG(textcodec)
-#include <qtextcodec.h>
-#endif
-
#include <qapplication.h>
-#include <qbitmap.h>
-#include <qcursor.h>
-#include <qdesktopwidget.h>
-#include <qevent.h>
-#include <qimage.h>
+#include <qabstractbutton.h>
+#include <qabstractscrollarea.h>
+#include <qabstractslider.h>
+#include <qaction.h>
+#include <qcommonstyle.h>
#include <qlayout.h>
-#include <qpainter.h>
-#include <qpixmap.h>
#include <qstyle.h>
-#include <qtimer.h>
#include <qwidget.h>
-
-#include <stdlib.h>
-
#endif
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
index cf0f3f153b..d030a28356 100644
--- a/src/widgets/kernel/qtooltip.cpp
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -41,7 +41,6 @@
#endif
#include <QtWidgets/private/qtwidgetsglobal_p.h>
-#include <QtWidgets/private/qlabel_p.h>
#include <qapplication.h>
#include <qdesktopwidget.h>
@@ -61,6 +60,7 @@
#ifndef QT_NO_TOOLTIP
#include <qlabel.h>
+#include <QtWidgets/private/qlabel_p.h>
#include <qtooltip.h>
#if 0 // Used to be included in Qt4 for Q_WS_MAC
@@ -482,8 +482,8 @@ bool QTipLabel::tipChanged(const QPoint &pos, const QString &text, QObject *o)
The \a rect is in the coordinates of the widget you specify with
\a w. If the \a rect is not empty you must specify a widget.
- Otherwise this argument can be 0 but it is used to determine the
- appropriate screen on multi-head systems.
+ Otherwise this argument can be \nullptr but it is used to
+ determine the appropriate screen on multi-head systems.
If \a text is empty the tool tip is hidden. If the text is the
same as the currently shown tooltip, the tip will \e not move.
diff --git a/src/widgets/kernel/qtooltip.h b/src/widgets/kernel/qtooltip.h
index edf1de0c1d..1b263a6629 100644
--- a/src/widgets/kernel/qtooltip.h
+++ b/src/widgets/kernel/qtooltip.h
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
class Q_WIDGETS_EXPORT QToolTip
{
- QToolTip() Q_DECL_EQ_DELETE;
+ QToolTip() = delete;
public:
// ### Qt 6 - merge the three showText functions below
static void showText(const QPoint &pos, const QString &text, QWidget *w = nullptr);
diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp
index 1fa83d3238..4a798a7490 100644
--- a/src/widgets/kernel/qwhatsthis.cpp
+++ b/src/widgets/kernel/qwhatsthis.cpp
@@ -398,10 +398,10 @@ QWhatsThisPrivate::QWhatsThisPrivate()
#ifdef QT_NO_CURSOR
Q_UNUSED(sentEvent);
#else
- QApplication::setOverrideCursor((!sentEvent || !e.isAccepted())?
+ QGuiApplication::setOverrideCursor((!sentEvent || !e.isAccepted())?
Qt::ForbiddenCursor:Qt::WhatsThisCursor);
} else {
- QApplication::setOverrideCursor(Qt::WhatsThisCursor);
+ QGuiApplication::setOverrideCursor(Qt::WhatsThisCursor);
#endif
}
#ifndef QT_NO_ACCESSIBILITY
@@ -417,7 +417,7 @@ QWhatsThisPrivate::~QWhatsThisPrivate()
action->setChecked(false);
#endif // QT_CONFIG(action)
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
#ifndef QT_NO_ACCESSIBILITY
QAccessibleEvent event(this, QAccessible::ContextHelpEnd);
diff --git a/src/widgets/kernel/qwhatsthis.h b/src/widgets/kernel/qwhatsthis.h
index 59c0b01c9b..fa5b97d98a 100644
--- a/src/widgets/kernel/qwhatsthis.h
+++ b/src/widgets/kernel/qwhatsthis.h
@@ -54,7 +54,7 @@ class QAction;
class Q_WIDGETS_EXPORT QWhatsThis
{
- QWhatsThis() Q_DECL_EQ_DELETE;
+ QWhatsThis() = delete;
public:
static void enterWhatsThisMode();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 6ef3a4f163..2176c612d0 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -79,6 +79,7 @@
#include "private/qstylesheetstyle_p.h"
#include "private/qstyle_p.h"
#include "qfileinfo.h"
+#include "qscopeguard.h"
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/qinputmethod.h>
#include <QtGui/qopenglcontext.h>
@@ -511,10 +512,10 @@ void QWidget::setAutoFillBackground(bool enabled)
Every widget's constructor accepts one or two standard arguments:
\list 1
- \li \c{QWidget *parent = 0} is the parent of the new widget. If it is 0
- (the default), the new widget will be a window. If not, it will be
- a child of \e parent, and be constrained by \e parent's geometry
- (unless you specify Qt::Window as window flag).
+ \li \c{QWidget *parent = \nullptr} is the parent of the new widget.
+ If it is \nullptr (the default), the new widget will be a window.
+ If not, it will be a child of \e parent, and be constrained by
+ \e parent's geometry (unless you specify Qt::Window as window flag).
\li \c{Qt::WindowFlags f = 0} (where available) sets the window flags;
the default is suitable for almost all widgets, but to get, for
example, a window without a window system frame, you must use
@@ -1003,14 +1004,14 @@ struct QWidgetExceptionCleaner
Constructs a widget which is a child of \a parent, with widget
flags set to \a f.
- If \a parent is 0, the new widget becomes a window. If
+ If \a parent is \nullptr, the new widget becomes a window. If
\a parent is another widget, this widget becomes a child window
inside \a parent. The new widget is deleted when its \a parent is
deleted.
The widget flags argument, \a f, is normally 0, but it can be set
- to customize the frame of a window (i.e. \a
- parent must be 0). To customize the frame, use a value composed
+ to customize the frame of a window (i.e. \a parent must be
+ \nullptr). To customize the frame, use a value composed
from the bitwise OR of any of the \l{Qt::WindowFlags}{window flags}.
If you add a child widget to an already visible widget you must
@@ -1123,6 +1124,8 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
{
Q_Q(QWidget);
+ Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
+
if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
qFatal("QWidget: Cannot create a QWidget without QApplication");
@@ -1249,6 +1252,33 @@ void QWidgetPrivate::createRecursively()
}
}
+QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
+{
+ if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
+ if (QTLWExtra *x = maybeTopData())
+ return x->window;
+ }
+ if (mode == WindowHandleMode::Closest) {
+ if (auto nativeParent = q_func()->nativeParentWidget()) {
+ if (auto window = nativeParent->windowHandle())
+ return window;
+ }
+ }
+ if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
+ if (auto topLevel = q_func()->topLevelWidget()) {
+ if (auto window = topLevel ->windowHandle())
+ return window;
+ }
+ }
+ return nullptr;
+}
+
+QScreen *QWidgetPrivate::associatedScreen() const
+{
+ if (auto window = windowHandle(WindowHandleMode::Closest))
+ return window->screen();
+ return nullptr;
+}
// ### fixme: Qt 6: Remove parameter window from QWidget::create()
@@ -1348,11 +1378,6 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
setAttribute(Qt::WA_DropSiteRegistered, true);
-#ifdef QT_EVAL
- extern void qt_eval_init_widget(QWidget *w);
- qt_eval_init_widget(this);
-#endif
-
// need to force the resting of the icon after changing parents
if (testAttribute(Qt::WA_SetWindowIcon))
d->setWindowIcon_sys();
@@ -2418,29 +2443,34 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrus
}
}
-void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const
+bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) const
{
- Q_Q(const QWidget);
-
#if QT_CONFIG(scrollarea)
- bool resetBrushOrigin = false;
- QPointF oldBrushOrigin;
+ Q_Q(const QWidget);
//If we are painting the viewport of a scrollarea, we must apply an offset to the brush in case we are drawing a texture
+ if (brush.style() == Qt::NoBrush || brush.style() == Qt::SolidPattern)
+ return false;
QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
if (scrollArea && scrollArea->viewport() == q) {
QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
- oldBrushOrigin = painter->brushOrigin();
- resetBrushOrigin = true;
painter->setBrushOrigin(-priv->contentsOffset());
-
}
#endif // QT_CONFIG(scrollarea)
+ return true;
+}
+void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const
+{
+ Q_Q(const QWidget);
+
+ bool brushOriginSet = false;
const QBrush autoFillBrush = q->palette().brush(q->backgroundRole());
if ((flags & DrawAsRoot) && !(q->autoFillBackground() && autoFillBrush.isOpaque())) {
const QBrush bg = q->palette().brush(QPalette::Window);
+ if (!brushOriginSet)
+ brushOriginSet = updateBrushOrigin(painter, bg);
if (!(flags & DontSetCompositionMode)) {
//copy alpha straight in
QPainter::CompositionMode oldMode = painter->compositionMode();
@@ -2452,8 +2482,11 @@ void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int
}
}
- if (q->autoFillBackground())
+ if (q->autoFillBackground()) {
+ if (!brushOriginSet)
+ brushOriginSet = updateBrushOrigin(painter, autoFillBrush);
fillRegion(painter, rgn, autoFillBrush);
+ }
if (q->testAttribute(Qt::WA_StyledBackground)) {
painter->setClipRegion(rgn);
@@ -2461,11 +2494,6 @@ void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int
opt.initFrom(q);
q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
}
-
-#if QT_CONFIG(scrollarea)
- if (resetBrushOrigin)
- painter->setBrushOrigin(oldBrushOrigin);
-#endif // QT_CONFIG(scrollarea)
}
/*
@@ -2499,12 +2527,12 @@ void QWidgetPrivate::deactivateWidgetCleanup()
The window identifier type depends on the underlying window
system, see \c qwindowdefs.h for the actual definition. If there
- is no widget with this identifier, 0 is returned.
+ is no widget with this identifier, \nullptr is returned.
*/
QWidget *QWidget::find(WId id)
{
- return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : 0;
+ return QWidgetPrivate::mapper ? QWidgetPrivate::mapper->value(id, 0) : nullptr;
}
@@ -3297,7 +3325,7 @@ void QWidget::addActions(QList<QAction*> actions)
/*!
Inserts the action \a action to this widget's list of actions,
- before the action \a before. It appends the action if \a before is 0 or
+ before the action \a before. It appends the action if \a before is \nullptr or
\a before is not a valid action for this widget.
A QWidget should only have one of each action.
@@ -3331,7 +3359,7 @@ void QWidget::insertAction(QAction *before, QAction *action)
/*!
Inserts the actions \a actions to this widget's list of actions,
- before the action \a before. It appends the action if \a before is 0 or
+ before the action \a before. It appends the action if \a before is \nullptr or
\a before is not a valid action for this widget.
A QWidget can have at most one of each action.
@@ -4250,7 +4278,7 @@ void QWidget::setFixedHeight(int h)
/*!
Translates the widget coordinate \a pos to the coordinate system
- of \a parent. The \a parent must not be 0 and must be a parent
+ of \a parent. The \a parent must not be \nullptr and must be a parent
of the calling widget.
\sa mapFrom(), mapToParent(), mapToGlobal(), underMouse()
@@ -4275,7 +4303,7 @@ QPoint QWidget::mapTo(const QWidget * parent, const QPoint & pos) const
/*!
Translates the widget coordinate \a pos from the coordinate system
of \a parent to this widget's coordinate system. The \a parent
- must not be 0 and must be a parent of the calling widget.
+ must not be \nullptr and must be a parent of the calling widget.
\sa mapTo(), mapFromParent(), mapFromGlobal(), underMouse()
*/
@@ -4354,7 +4382,8 @@ QWidget *QWidget::window() const
\since 4.4
Returns the native parent for this widget, i.e. the next ancestor widget
- that has a system identifier, or 0 if it does not have any native parent.
+ that has a system identifier, or \nullptr if it does not have any native
+ parent.
\sa effectiveWinId()
*/
@@ -4975,9 +5004,9 @@ void QWidget::unsetLayoutDirection()
Some underlying window implementations will reset the cursor if it
leaves a widget even if the mouse is grabbed. If you want to have
a cursor set for all widgets, even when outside the window, consider
- QApplication::setOverrideCursor().
+ QGuiApplication::setOverrideCursor().
- \sa QApplication::setOverrideCursor()
+ \sa QGuiApplication::setOverrideCursor()
*/
#ifndef QT_NO_CURSOR
@@ -5290,7 +5319,7 @@ QPixmap QWidget::grab(const QRect &rectangle)
\brief The graphicsEffect function returns a pointer to the
widget's graphics effect.
- If the widget has no graphics effect, 0 is returned.
+ If the widget has no graphics effect, \nullptr is returned.
\since 4.6
@@ -5334,7 +5363,7 @@ void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
return;
if (d->graphicsEffect) {
- d->invalidateBuffer(rect());
+ d->invalidateBackingStore(rect());
delete d->graphicsEffect;
d->graphicsEffect = 0;
}
@@ -5754,12 +5783,10 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
QPoint offset = targetOffset;
offset -= paintRegion.boundingRect().topLeft();
QPoint redirectionOffset;
- QPaintDevice *redirected = 0;
+ QPaintDevice *redirected = nullptr;
if (target->devType() == QInternal::Widget)
redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
- if (!redirected)
- redirected = QPainter::redirected(target, &redirectionOffset);
if (redirected) {
target = redirected;
@@ -5936,10 +5963,10 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *
Finds the nearest widget embedded in a graphics proxy widget along the chain formed by this
widget and its ancestors. The search starts at \a origin (inclusive).
- If successful, the function returns the proxy that embeds the widget, or 0 if no embedded
- widget was found.
+ If successful, the function returns the proxy that embeds the widget, or \nullptr if no
+ embedded widget was found.
*/
-QGraphicsProxyWidget * QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
+QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin)
{
if (origin) {
QWExtra *extra = origin->d_func()->extra;
@@ -5947,7 +5974,7 @@ QGraphicsProxyWidget * QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget
return extra->proxyWidget;
return nearestGraphicsProxyWidget(origin->parentWidget());
}
- return 0;
+ return nullptr;
}
#endif
@@ -6073,13 +6100,7 @@ QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widg
{
Q_ASSERT(widget);
-#ifdef QT_EVAL
- extern QString qt_eval_adapt_window_title(const QString &title);
- QString cap = qt_eval_adapt_window_title(title);
-#else
QString cap = title;
-#endif
-
if (cap.isEmpty())
return cap;
@@ -6419,7 +6440,7 @@ void QWidget::setWindowRole(const QString &role)
/*!
- Sets the widget's focus proxy to widget \a w. If \a w is 0, the
+ Sets the widget's focus proxy to widget \a w. If \a w is \nullptr, the
function resets this widget to have no focus proxy.
Some widgets can "have focus", but create a child widget, such as
@@ -6452,15 +6473,15 @@ void QWidget::setFocusProxy(QWidget * w)
/*!
- Returns the focus proxy, or 0 if there is no focus proxy.
+ Returns the focus proxy, or \nullptr if there is no focus proxy.
\sa setFocusProxy()
*/
-QWidget * QWidget::focusProxy() const
+QWidget *QWidget::focusProxy() const
{
Q_D(const QWidget);
- return d->extra ? (QWidget *)d->extra->focus_proxy : 0;
+ return d->extra ? (QWidget *)d->extra->focus_proxy : nullptr;
}
@@ -7363,11 +7384,11 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
if (renderToTexture) {
QRegion updateRegion(q->geometry());
updateRegion += QRect(oldPos, olds);
- q->parentWidget()->d_func()->invalidateBuffer(updateRegion);
+ q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
} else if (isMove && !isResize) {
moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
} else {
- invalidateBuffer_resizeHelper(oldPos, olds);
+ invalidateBackingStore_resizeHelper(oldPos, olds);
}
}
}
@@ -8126,10 +8147,10 @@ void QWidgetPrivate::show_sys()
{
Q_Q(QWidget);
- QWidgetWindow *window = windowHandle();
+ auto window = qobject_cast<QWidgetWindow *>(windowHandle());
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
- invalidateBuffer(q->rect());
+ invalidateBackingStore(q->rect());
q->setAttribute(Qt::WA_Mapped);
// add our window the modal window list (native dialogs)
if (window && q->isWindow()
@@ -8172,7 +8193,7 @@ void QWidgetPrivate::show_sys()
#ifndef QT_NO_CURSOR
qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
#endif
- invalidateBuffer(q->rect());
+ invalidateBackingStore(q->rect());
window->setNativeWindowVisibility(true);
// Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
if (window->isTopLevel()) {
@@ -8265,7 +8286,7 @@ void QWidgetPrivate::hide_sys()
{
Q_Q(QWidget);
- QWidgetWindow *window = windowHandle();
+ auto window = qobject_cast<QWidgetWindow *>(windowHandle());
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
q->setAttribute(Qt::WA_Mapped, false);
@@ -8286,12 +8307,12 @@ void QWidgetPrivate::hide_sys()
QWidget *p = q->parentWidget();
if (p &&p->isVisible()) {
if (renderToTexture)
- p->d_func()->invalidateBuffer(q->geometry());
+ p->d_func()->invalidateBackingStore(q->geometry());
else
- invalidateBuffer(q->rect());
+ invalidateBackingStore(q->rect());
}
} else {
- invalidateBuffer(q->rect());
+ invalidateBackingStore(q->rect());
}
if (window)
@@ -8845,7 +8866,7 @@ QSize QWidget::minimumSizeHint() const
/*!
\fn QWidget *QWidget::parentWidget() const
- Returns the parent of this widget, or 0 if it does not have any
+ Returns the parent of this widget, or \nullptr if it does not have any
parent widget.
*/
@@ -10189,7 +10210,11 @@ void QWidget::hideEvent(QHideEvent *)
\endtable
*/
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
+#else
bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
+#endif
{
Q_UNUSED(eventType);
Q_UNUSED(message);
@@ -10261,7 +10286,7 @@ QRegion QWidget::mask() const
}
/*!
- Returns the layout manager that is installed on this widget, or 0
+ Returns the layout manager that is installed on this widget, or \nullptr
if no layout manager is installed.
The layout manager sets the geometry of the widget's children
@@ -10699,6 +10724,22 @@ static void sendWindowChangeToTextureChildrenRecursively(QWidget *widget)
void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
{
Q_D(QWidget);
+ Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
+#ifdef QT_DEBUG
+ const auto checkForParentChildLoops = qScopeGuard([&](){
+ int depth = 0;
+ auto p = parentWidget();
+ while (p) {
+ if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) {
+ qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
+ "this is undefined behavior",
+ this, metaObject()->className(), qPrintable(objectName()));
+ }
+ p = p->parentWidget();
+ }
+ });
+#endif
+
bool resized = testAttribute(Qt::WA_Resized);
bool wasCreated = testAttribute(Qt::WA_WState_Created);
QWidget *oldtlw = window();
@@ -11933,7 +11974,7 @@ void QWidget::raise()
QRegion region(rect());
d->subtractOpaqueSiblings(region);
- d->invalidateBuffer(region);
+ d->invalidateBackingStore(region);
}
if (testAttribute(Qt::WA_WState_Created))
d->raise_sys();
@@ -11953,7 +11994,7 @@ void QWidgetPrivate::raise_sys()
} else if (renderToTexture) {
if (QWidget *p = q->parentWidget()) {
setDirtyOpaqueRegion();
- p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
}
}
}
@@ -12003,7 +12044,7 @@ void QWidgetPrivate::lower_sys()
q->windowHandle()->lower();
} else if (QWidget *p = q->parentWidget()) {
setDirtyOpaqueRegion();
- p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
}
}
@@ -12047,7 +12088,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget*)
Q_Q(QWidget);
if (QWidget *p = q->parentWidget()) {
setDirtyOpaqueRegion();
- p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
}
}
@@ -12149,14 +12190,14 @@ bool QWidgetPrivate::navigateToDirection(Direction direction)
Searches for a widget that is positioned in the \a direction, starting
from the current focusWidget.
- Returns the pointer to a found widget or 0, if there was no widget in
- that direction.
+ Returns the pointer to a found widget or \nullptr, if there was no widget
+ in that direction.
*/
QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
{
const QWidget *sourceWidget = QApplication::focusWidget();
if (!sourceWidget)
- return 0;
+ return nullptr;
const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint()));
const int sourceX =
(direction == DirectionNorth || direction == DirectionSouth) ?
@@ -12170,7 +12211,7 @@ QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction)
const QPoint sourceCenter = sourceRect.center();
const QWidget *sourceWindow = sourceWidget->window();
- QWidget *targetWidget = 0;
+ QWidget *targetWidget = nullptr;
int shortestDistance = INT_MAX;
const auto targetCandidates = QApplication::allWidgets();
@@ -12489,7 +12530,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
d->aboutToDestroy();
if (!isWindow() && parentWidget())
- parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
+ parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
d->deactivateWidgetCleanup();
if ((windowType() == Qt::Popup) && qApp)
@@ -12837,7 +12878,7 @@ void QWidget::releaseKeyboard()
Returns the widget that is currently grabbing the mouse input.
If no widget in this application is currently grabbing the mouse,
- 0 is returned.
+ \nullptr is returned.
\sa grabMouse(), keyboardGrabber()
*/
@@ -12854,7 +12895,7 @@ QWidget *QWidget::mouseGrabber()
Returns the widget that is currently grabbing the keyboard input.
If no widget in this application is currently grabbing the
- keyboard, 0 is returned.
+ keyboard, \nullptr is returned.
\sa grabMouse(), mouseGrabber()
*/
@@ -13211,7 +13252,7 @@ QDebug operator<<(QDebug debug, const QWidget *widget)
if (widget->isWindow())
debug << ", window";
debug << ", " << geometry.width() << 'x' << geometry.height()
- << forcesign << geometry.x() << geometry.y() << noforcesign;
+ << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
if (frameGeometry != geometry) {
const QMargins margins(geometry.x() - frameGeometry.x(),
geometry.y() - frameGeometry.y(),
@@ -13221,7 +13262,7 @@ QDebug operator<<(QDebug debug, const QWidget *widget)
}
debug << ", devicePixelRatio=" << widget->devicePixelRatioF();
if (const WId wid = widget->internalWinId())
- debug << ", winId=0x" << hex << wid << dec;
+ debug << ", winId=0x" << Qt::hex << wid << Qt::dec;
}
debug << ')';
} else {
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index 9d5fe89c70..e47deb5d0d 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -235,7 +235,10 @@ public:
bool isEnabled() const;
bool isEnabledTo(const QWidget *) const;
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X ("Use isEnabled() instead")
bool isEnabledToTLW() const;
+#endif
public Q_SLOTS:
void setEnabled(bool);
@@ -552,7 +555,7 @@ public:
void addAction(QAction *action);
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
void addActions(const QList<QAction*> &actions);
- void insertActions(const QAction *before, const QList<QAction*> &actions);
+ void insertActions(QAction *before, const QList<QAction*> &actions);
#else
void addActions(QList<QAction*> actions);
void insertActions(QAction *before, QList<QAction*> actions);
@@ -645,7 +648,12 @@ protected:
virtual void showEvent(QShowEvent *event);
virtual void hideEvent(QHideEvent *event);
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
+#else
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result);
+#endif
// Misc. protected functions
virtual void changeEvent(QEvent *);
@@ -769,8 +777,10 @@ inline bool QWidget::isEnabled() const
inline bool QWidget::isModal() const
{ return data->window_modality != Qt::NonModal; }
+#if QT_DEPRECATED_SINCE(5, 13)
inline bool QWidget::isEnabledToTLW() const
{ return isEnabled(); }
+#endif
inline int QWidget::minimumWidth() const
{ return minimumSize().width(); }
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 64bc463ae2..99ec38e050 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -146,11 +146,11 @@ public:
inline operator bool() const
{
- return (0 != m_ptr);
+ return (nullptr != m_ptr);
}
private:
- Q_DISABLE_COPY(QWidgetBackingStoreTracker)
+ Q_DISABLE_COPY_MOVE(QWidgetBackingStoreTracker)
private:
QWidgetBackingStore* m_ptr;
@@ -343,7 +343,15 @@ public:
QPainter *sharedPainter() const;
void setSharedPainter(QPainter *painter);
QWidgetBackingStore *maybeBackingStore() const;
- QWidgetWindow *windowHandle() const;
+
+ enum class WindowHandleMode {
+ Direct,
+ Closest,
+ TopLevel
+ };
+ QWindow *windowHandle(WindowHandleMode mode = WindowHandleMode::Direct) const;
+
+ QScreen *associatedScreen() const;
template <typename T>
void repaint(T t);
@@ -404,6 +412,7 @@ public:
void setUpdatesEnabled_helper(bool );
+ bool updateBrushOrigin(QPainter *, const QBrush &brush) const;
void paintBackground(QPainter *, const QRegion &, int flags = DrawAsRoot) const;
bool isAboutToShow() const;
QRegion prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags);
@@ -412,7 +421,7 @@ public:
void render(QPaintDevice *target, const QPoint &targetOffset, const QRegion &sourceRegion,
QWidget::RenderFlags renderFlags);
void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,
- QPainter *sharedPainter = 0, QWidgetBackingStore *backingStore = 0);
+ QPainter *sharedPainter = nullptr, QWidgetBackingStore *backingStore = nullptr);
void sendPaintEvent(const QRegion &toBePainted);
@@ -429,7 +438,7 @@ public:
QRegion clipRegion() const;
void setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region);
void subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const;
- void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0,
+ void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = nullptr,
bool alsoNonOpaque = false) const;
void clipToEffectiveMask(QRegion &region) const;
void updateIsOpaque();
@@ -453,10 +462,11 @@ public:
void scrollChildren(int dx, int dy);
void moveRect(const QRect &, int dx, int dy);
void scrollRect(const QRect &, int dx, int dy);
- void invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize);
- // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
- void invalidateBuffer(const QRegion &);
- void invalidateBuffer(const QRect &);
+ void invalidateBackingStore_resizeHelper(const QPoint &oldPos, const QSize &oldSize);
+
+ template <class T>
+ void invalidateBackingStore(const T &);
+
QRegion overlappedRegion(const QRect &rect, bool breakAfterFirst = false) const;
void syncBackingStore();
void syncBackingStore(const QRegion &region);
@@ -525,7 +535,7 @@ public:
void getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const;
void setLayoutItemMargins(int left, int top, int right, int bottom);
- void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0);
+ void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = nullptr);
void updateContentsRect();
QMargins safeAreaMargins() const;
@@ -555,7 +565,7 @@ public:
QGraphicsProxyWidget *ancestorProxy = widget->d_func()->nearestGraphicsProxyWidget(widget);
//It's embedded if it has an ancestor
if (ancestorProxy) {
- if (!bypassGraphicsProxyWidget(widget) && ancestorProxy->scene() != 0) {
+ if (!bypassGraphicsProxyWidget(widget) && ancestorProxy->scene() != nullptr) {
// One view, let be smart and return the viewport rect then the popup is aligned
if (ancestorProxy->scene()->views().size() == 1) {
QGraphicsView *view = ancestorProxy->scene()->views().at(0);
@@ -586,7 +596,7 @@ public:
}
inline void restoreRedirected()
- { redirectDev = 0; }
+ { redirectDev = nullptr; }
inline void enforceNativeChildren()
{
@@ -608,6 +618,11 @@ public:
return extra ? extra->nativeChildrenForced : false;
}
+ inline QRect effectiveRectFor(const QRegion &region) const
+ {
+ return effectiveRectFor(region.boundingRect());
+ }
+
inline QRect effectiveRectFor(const QRect &rect) const
{
#if QT_CONFIG(graphicseffect)
@@ -647,7 +662,7 @@ public:
QOpenGLContext *shareContext() const;
- virtual QObject *focusObject() { return 0; }
+ virtual QObject *focusObject() { return nullptr; }
#ifndef QT_NO_OPENGL
virtual GLuint textureId() const { return 0; }
@@ -655,7 +670,7 @@ public:
Q_Q(QWidget);
return q->testAttribute(Qt::WA_AlwaysStackOnTop)
? QPlatformTextureList::StacksOnTop
- : QPlatformTextureList::Flags(0);
+ : QPlatformTextureList::Flags(nullptr);
}
virtual QImage grabFramebuffer() { return QImage(); }
virtual void beginBackingStorePainting() { }
@@ -899,7 +914,7 @@ struct QWidgetPaintContext
{
inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, int f,
QPainter *p, QWidgetBackingStore *b)
- : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), backingStore(b), painter(0) {}
+ : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), backingStore(b), painter(nullptr) {}
QPaintDevice *pdev;
QRegion rgn;
@@ -915,14 +930,14 @@ class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate
{
public:
QWidgetEffectSourcePrivate(QWidget *widget)
- : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0), updateDueToGraphicsEffect(false)
+ : QGraphicsEffectSourcePrivate(), m_widget(widget), context(nullptr), updateDueToGraphicsEffect(false)
{}
void detach() override
- { m_widget->d_func()->graphicsEffect = 0; }
+ { m_widget->d_func()->graphicsEffect = nullptr; }
const QGraphicsItem *graphicsItem() const override
- { return 0; }
+ { return nullptr; }
const QWidget *widget() const override
{ return m_widget; }
@@ -948,7 +963,7 @@ public:
}
const QStyleOption *styleOption() const override
- { return 0; }
+ { return nullptr; }
QRect deviceRect() const override
{ return m_widget->window()->rect(); }
@@ -978,14 +993,14 @@ inline QTLWExtra *QWidgetPrivate::topData() const
inline QTLWExtra *QWidgetPrivate::maybeTopData() const
{
- return extra ? extra->topextra : 0;
+ return extra ? extra->topextra : nullptr;
}
inline QPainter *QWidgetPrivate::sharedPainter() const
{
Q_Q(const QWidget);
QTLWExtra *x = q->window()->d_func()->maybeTopData();
- return x ? x->sharedPainter : 0;
+ return x ? x->sharedPainter : nullptr;
}
inline void QWidgetPrivate::setSharedPainter(QPainter *painter)
@@ -1006,14 +1021,7 @@ inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const
{
Q_Q(const QWidget);
QTLWExtra *x = q->window()->d_func()->maybeTopData();
- return x ? x->backingStoreTracker.data() : 0;
-}
-
-inline QWidgetWindow *QWidgetPrivate::windowHandle() const
-{
- if (QTLWExtra *x = maybeTopData())
- return x->window;
- return nullptr;
+ return x ? x->backingStoreTracker.data() : nullptr;
}
QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index a32eb2a03b..595beeaf47 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -310,12 +310,6 @@ bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *wi
return store->scroll(tlwRect, dx, dy);
}
-void QWidgetBackingStore::releaseBuffer()
-{
- if (store)
- store->resize(QSize());
-}
-
/*!
Prepares the window surface to paint a\ toClean region of the \a widget and
updates the BeginPaintInfo struct accordingly.
@@ -507,6 +501,9 @@ void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTi
}
}
+static inline QRect widgetRectFor(QWidget *, const QRect &r) { return r; }
+static inline QRect widgetRectFor(QWidget *widget, const QRegion &) { return widget->rect(); }
+
/*!
Marks the region of the widget as dirty (if not already marked as dirty) and
posts an UpdateRequest event to the top-level widget (if not already posted).
@@ -517,42 +514,44 @@ void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTi
If the widget paints directly on screen, the event is sent to the widget
instead of the top-level widget, and bufferState is completely ignored.
-
- ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
*/
-void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget,
- UpdateTime updateTime, BufferState bufferState)
+template <class T>
+void QWidgetBackingStore::markDirty(const T &r, QWidget *widget, UpdateTime updateTime, BufferState bufferState)
{
Q_ASSERT(tlw->d_func()->extra);
Q_ASSERT(tlw->d_func()->extra->topextra);
Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize);
Q_ASSERT(widget->isVisible() && widget->updatesEnabled());
Q_ASSERT(widget->window() == tlw);
- Q_ASSERT(!rgn.isEmpty());
+ Q_ASSERT(!r.isEmpty());
#if QT_CONFIG(graphicseffect)
widget->d_func()->invalidateGraphicsEffectsRecursively();
-#endif // QT_CONFIG(graphicseffect)
+#endif
+
+ QRect widgetRect = widgetRectFor(widget, r);
+
+ // ---------------------------------------------------------------------------
if (widget->d_func()->paintOnScreen()) {
if (widget->d_func()->dirty.isEmpty()) {
- widget->d_func()->dirty = rgn;
+ widget->d_func()->dirty = r;
sendUpdateRequest(widget, updateTime);
return;
- } else if (qt_region_strictContains(widget->d_func()->dirty, widget->rect())) {
+ } else if (qt_region_strictContains(widget->d_func()->dirty, widgetRect)) {
if (updateTime == UpdateNow)
sendUpdateRequest(widget, updateTime);
- return; // Already dirty.
+ return; // Already dirty
}
const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty();
- widget->d_func()->dirty += rgn;
+ widget->d_func()->dirty += r;
if (!eventAlreadyPosted || updateTime == UpdateNow)
sendUpdateRequest(widget, updateTime);
return;
}
- const QPoint offset = widget->mapTo(tlw, QPoint());
+ // ---------------------------------------------------------------------------
if (QWidgetPrivate::get(widget)->renderToTexture) {
if (!widget->d_func()->inDirtyList)
@@ -562,133 +561,67 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget,
return;
}
- const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());
- if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {
+ // ---------------------------------------------------------------------------
+
+ QRect effectiveWidgetRect = widget->d_func()->effectiveRectFor(widgetRect);
+ const QPoint offset = widget->mapTo(tlw, QPoint());
+ QRect translatedRect = effectiveWidgetRect.translated(offset);
+#if QT_CONFIG(graphicseffect)
+ // Graphics effects may exceed window size, clamp
+ translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size()));
+#endif
+ if (qt_region_strictContains(dirty, translatedRect)) {
if (updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
- return; // Already dirty.
+ return; // Already dirty
}
+ // ---------------------------------------------------------------------------
+
if (bufferState == BufferInvalid) {
const bool eventAlreadyPosted = !dirty.isEmpty() || updateRequestSent;
#if QT_CONFIG(graphicseffect)
if (widget->d_func()->graphicsEffect)
- dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset);
+ dirty += widget->d_func()->effectiveRectFor(r).translated(offset);
else
-#endif // QT_CONFIG(graphicseffect)
- dirty += rgn.translated(offset);
+#endif
+ dirty += r.translated(offset);
+
if (!eventAlreadyPosted || updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
return;
}
+ // ---------------------------------------------------------------------------
+
if (dirtyWidgets.isEmpty()) {
- addDirtyWidget(widget, rgn);
+ addDirtyWidget(widget, r);
sendUpdateRequest(tlw, updateTime);
return;
}
+ // ---------------------------------------------------------------------------
+
if (widget->d_func()->inDirtyList) {
- if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) {
+ if (!qt_region_strictContains(widget->d_func()->dirty, effectiveWidgetRect)) {
#if QT_CONFIG(graphicseffect)
if (widget->d_func()->graphicsEffect)
- widget->d_func()->dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect());
+ widget->d_func()->dirty += widget->d_func()->effectiveRectFor(r);
else
-#endif // QT_CONFIG(graphicseffect)
- widget->d_func()->dirty += rgn;
+#endif
+ widget->d_func()->dirty += r;
}
} else {
- addDirtyWidget(widget, rgn);
- }
-
- if (updateTime == UpdateNow)
- sendUpdateRequest(tlw, updateTime);
-}
-
-/*!
- This function is equivalent to calling markDirty(QRegion(rect), ...), but
- is more efficient as it eliminates QRegion operations/allocations and can
- use the rect more precisely for additional cut-offs.
-
- ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
-*/
-void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget,
- UpdateTime updateTime, BufferState bufferState)
-{
- Q_ASSERT(tlw->d_func()->extra);
- Q_ASSERT(tlw->d_func()->extra->topextra);
- Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize);
- Q_ASSERT(widget->isVisible() && widget->updatesEnabled());
- Q_ASSERT(widget->window() == tlw);
- Q_ASSERT(!rect.isEmpty());
-
-#if QT_CONFIG(graphicseffect)
- widget->d_func()->invalidateGraphicsEffectsRecursively();
-#endif // QT_CONFIG(graphicseffect)
-
- if (widget->d_func()->paintOnScreen()) {
- if (widget->d_func()->dirty.isEmpty()) {
- widget->d_func()->dirty = QRegion(rect);
- sendUpdateRequest(widget, updateTime);
- return;
- } else if (qt_region_strictContains(widget->d_func()->dirty, rect)) {
- if (updateTime == UpdateNow)
- sendUpdateRequest(widget, updateTime);
- return; // Already dirty.
- }
-
- const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty();
- widget->d_func()->dirty += rect;
- if (!eventAlreadyPosted || updateTime == UpdateNow)
- sendUpdateRequest(widget, updateTime);
- return;
+ addDirtyWidget(widget, r);
}
- if (QWidgetPrivate::get(widget)->renderToTexture) {
- if (!widget->d_func()->inDirtyList)
- addDirtyRenderToTextureWidget(widget);
- if (!updateRequestSent || updateTime == UpdateNow)
- sendUpdateRequest(tlw, updateTime);
- return;
- }
-
-
- const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
- QRect translatedRect = widgetRect;
- if (widget != tlw)
- translatedRect.translate(widget->mapTo(tlw, QPoint()));
- // Graphics effects may exceed window size, clamp.
- translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size()));
- if (qt_region_strictContains(dirty, translatedRect)) {
- if (updateTime == UpdateNow)
- sendUpdateRequest(tlw, updateTime);
- return; // Already dirty
- }
-
- if (bufferState == BufferInvalid) {
- const bool eventAlreadyPosted = !dirty.isEmpty();
- dirty += translatedRect;
- if (!eventAlreadyPosted || updateTime == UpdateNow)
- sendUpdateRequest(tlw, updateTime);
- return;
- }
-
- if (dirtyWidgets.isEmpty()) {
- addDirtyWidget(widget, rect);
- sendUpdateRequest(tlw, updateTime);
- return;
- }
-
- if (widget->d_func()->inDirtyList) {
- if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect))
- widget->d_func()->dirty += widgetRect;
- } else {
- addDirtyWidget(widget, rect);
- }
+ // ---------------------------------------------------------------------------
if (updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
}
+template void QWidgetBackingStore::markDirty<QRect>(const QRect &, QWidget *, UpdateTime, BufferState);
+template void QWidgetBackingStore::markDirty<QRegion>(const QRegion &, QWidget *, UpdateTime, BufferState);
/*!
Marks the \a region of the \a widget as dirty on screen. The \a region will be copied from
@@ -859,11 +792,11 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
if (!extra || !extra->hasMask) {
parentR -= newRect;
} else {
- // invalidateBuffer() excludes anything outside the mask
+ // invalidateBackingStore() excludes anything outside the mask
parentR += newRect & clipR;
}
- pd->invalidateBuffer(parentR);
- invalidateBuffer((newRect & clipR).translated(-data.crect.topLeft()));
+ pd->invalidateBackingStore(parentR);
+ invalidateBackingStore((newRect & clipR).translated(-data.crect.topLeft()));
} else {
QWidgetBackingStore *wbs = x->backingStoreTracker.data();
@@ -894,7 +827,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
if (childUpdatesEnabled) {
if (!overlappedExpose.isEmpty()) {
overlappedExpose.translate(-data.crect.topLeft());
- invalidateBuffer(overlappedExpose);
+ invalidateBackingStore(overlappedExpose);
}
if (!childExpose.isEmpty()) {
childExpose.translate(-data.crect.topLeft());
@@ -944,9 +877,9 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
if (!overlappedRegion(scrollRect.translated(data.crect.topLeft()), true).isEmpty()) {
QRegion region(scrollRect);
subtractOpaqueSiblings(region);
- invalidateBuffer(region);
+ invalidateBackingStore(region);
}else {
- invalidateBuffer(scrollRect);
+ invalidateBackingStore(scrollRect);
}
} else {
const QPoint toplevelOffset = q->mapTo(tlw, QPoint());
@@ -987,7 +920,7 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
return;
if (!overlappedExpose.isEmpty())
- invalidateBuffer(overlappedExpose);
+ invalidateBackingStore(overlappedExpose);
if (!childExpose.isEmpty()) {
wbs->markDirty(childExpose, q);
isScrolled = true;
@@ -1471,26 +1404,11 @@ void QWidgetBackingStore::flush(QWidget *widget)
dirtyOnScreenWidgets->clear();
}
-static inline bool discardInvalidateBufferRequest(QWidget *widget, QTLWExtra *tlwExtra)
-{
- Q_ASSERT(widget);
- if (QApplication::closingDown())
- return true;
-
- if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore)
- return true;
-
- if (!widget->isVisible() || !widget->updatesEnabled())
- return true;
-
- return false;
-}
-
/*!
- Invalidates the buffer when the widget is resized.
+ Invalidates the backing store when the widget is resized.
Static areas are never invalidated unless absolutely needed.
*/
-void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize)
+void QWidgetPrivate::invalidateBackingStore_resizeHelper(const QPoint &oldPos, const QSize &oldSize)
{
Q_Q(QWidget);
Q_ASSERT(!q->isWindow());
@@ -1515,10 +1433,10 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q
if (hasStaticChildren) {
QRegion dirty(newWidgetRect);
dirty -= staticChildren;
- invalidateBuffer(dirty);
+ invalidateBackingStore(dirty);
} else {
// Entire widget needs repaint.
- invalidateBuffer(newWidgetRect);
+ invalidateBackingStore(newWidgetRect);
}
if (!parentAreaExposed)
@@ -1530,14 +1448,14 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q
parentExpose &= QRect(oldPos, oldSize);
if (hasStaticChildren)
parentExpose -= data.crect; // Offset is unchanged, safe to do this.
- q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ q->parentWidget()->d_func()->invalidateBackingStore(parentExpose);
} else {
if (hasStaticChildren && !graphicsEffect) {
QRegion parentExpose(QRect(oldPos, oldSize));
parentExpose -= data.crect; // Offset is unchanged, safe to do this.
- q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ q->parentWidget()->d_func()->invalidateBackingStore(parentExpose);
} else {
- q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(QRect(oldPos, oldSize)));
+ q->parentWidget()->d_func()->invalidateBackingStore(effectiveRectFor(QRect(oldPos, oldSize)));
}
}
return;
@@ -1558,7 +1476,7 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q
if (!sizeDecreased || !oldWidgetRect.contains(newWidgetRect)) {
QRegion newVisible(newWidgetRect);
newVisible -= oldWidgetRect;
- invalidateBuffer(newVisible);
+ invalidateBackingStore(newVisible);
}
if (!parentAreaExposed)
@@ -1570,74 +1488,56 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q
QRegion parentExpose(oldRect);
parentExpose &= extra->mask.translated(oldPos);
parentExpose -= (extra->mask.translated(data.crect.topLeft()) & data.crect);
- q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ q->parentWidget()->d_func()->invalidateBackingStore(parentExpose);
} else {
QRegion parentExpose(oldRect);
parentExpose -= data.crect;
- q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
+ q->parentWidget()->d_func()->invalidateBackingStore(parentExpose);
}
}
/*!
- Invalidates the \a rgn (in widget's coordinates) of the backing store, i.e.
- all widgets intersecting with the region will be repainted when the backing store
- is synced.
-
- ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
+ Invalidates the \a r (in widget's coordinates) of the backing store, i.e.
+ all widgets intersecting with the region will be repainted when the backing
+ store is synced.
*/
-void QWidgetPrivate::invalidateBuffer(const QRegion &rgn)
+template <class T>
+void QWidgetPrivate::invalidateBackingStore(const T &r)
{
- Q_Q(QWidget);
-
- QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
- if (discardInvalidateBufferRequest(q, tlwExtra) || rgn.isEmpty())
+ if (r.isEmpty())
return;
- QRegion wrgn(rgn);
- wrgn &= clipRect();
- if (!graphicsEffect && extra && extra->hasMask)
- wrgn &= extra->mask;
- if (wrgn.isEmpty())
+ if (QApplication::closingDown())
return;
- tlwExtra->backingStoreTracker->markDirty(wrgn, q,
- QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
-}
-
-/*!
- This function is equivalent to calling invalidateBuffer(QRegion(rect), ...), but
- is more efficient as it eliminates QRegion operations/allocations and can
- use the rect more precisely for additional cut-offs.
-
- ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
-*/
-void QWidgetPrivate::invalidateBuffer(const QRect &rect)
-{
Q_Q(QWidget);
-
- QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
- if (discardInvalidateBufferRequest(q, tlwExtra) || rect.isEmpty())
+ if (!q->isVisible() || !q->updatesEnabled())
return;
- QRect wRect(rect);
- wRect &= clipRect();
- if (wRect.isEmpty())
+ QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
+ if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore)
return;
- if (graphicsEffect || !extra || !extra->hasMask) {
- tlwExtra->backingStoreTracker->markDirty(wRect, q,
- QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
+ T clipped(r);
+ clipped &= clipRect();
+ if (clipped.isEmpty())
return;
- }
- QRegion wRgn(extra->mask);
- wRgn &= wRect;
- if (wRgn.isEmpty())
- return;
+ if (!graphicsEffect && extra && extra->hasMask) {
+ QRegion masked(extra->mask);
+ masked &= clipped;
+ if (masked.isEmpty())
+ return;
- tlwExtra->backingStoreTracker->markDirty(wRgn, q,
+ tlwExtra->backingStoreTracker->markDirty(masked, q,
QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
+ } else {
+ tlwExtra->backingStoreTracker->markDirty(clipped, q,
+ QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
+ }
}
+// Needed by tst_QWidget
+template Q_AUTOTEST_EXPORT void QWidgetPrivate::invalidateBackingStore<QRect>(const QRect &r);
void QWidgetPrivate::repaint_sys(const QRegion &rgn)
{
diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h
index 53ccda850a..9409ba7832 100644
--- a/src/widgets/kernel/qwidgetbackingstore_p.h
+++ b/src/widgets/kernel/qwidgetbackingstore_p.h
@@ -109,7 +109,7 @@ public:
void sync(QWidget *exposedWidget, const QRegion &exposedRegion);
void sync();
- void flush(QWidget *widget = 0);
+ void flush(QWidget *widget = nullptr);
QBackingStore *backingStore() const { return store; }
@@ -118,10 +118,8 @@ public:
return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && dirtyRenderToTextureWidgets.isEmpty());
}
- // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
- void markDirty(const QRegion &rgn, QWidget *widget, UpdateTime updateTime = UpdateLater,
- BufferState bufferState = BufferValid);
- void markDirty(const QRect &rect, QWidget *widget, UpdateTime updateTime = UpdateLater,
+ template <class T>
+ void markDirty(const T &r, QWidget *widget, UpdateTime updateTime = UpdateLater,
BufferState bufferState = BufferValid);
private:
@@ -151,14 +149,13 @@ private:
void doSync();
bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget);
- void releaseBuffer();
void beginPaint(QRegion &toClean, QWidget *widget, QBackingStore *backingStore,
BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates = true);
void endPaint(const QRegion &cleaned, QBackingStore *backingStore, BeginPaintInfo *beginPaintInfo);
- QRegion dirtyRegion(QWidget *widget = 0) const;
- QRegion staticContents(QWidget *widget = 0, const QRect &withinClipRect = QRect()) const;
+ QRegion dirtyRegion(QWidget *widget = nullptr) const;
+ QRegion staticContents(QWidget *widget = nullptr, const QRect &withinClipRect = QRect()) const;
void markDirtyOnScreen(const QRegion &dirtyOnScreen, QWidget *widget, const QPoint &topLevelOffset);
@@ -305,7 +302,7 @@ private:
friend class QWidget;
friend class QBackingStore;
- Q_DISABLE_COPY(QWidgetBackingStore)
+ Q_DISABLE_COPY_MOVE(QWidgetBackingStore)
};
QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index fbc71cd0ea..a5d9eee49d 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -106,6 +106,7 @@ public:
if (QWidget *widget = q->widget())
QWidgetPrivate::get(widget)->updateContentsRect();
}
+ bool allowClickThrough(const QPoint &) const override;
};
QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
@@ -221,6 +222,11 @@ static inline bool shouldBePropagatedToWidget(QEvent *event)
}
}
+bool QWidgetWindowPrivate::allowClickThrough(const QPoint &) const
+{
+ return true;
+}
+
bool QWidgetWindow::event(QEvent *event)
{
if (!m_widget)
@@ -586,10 +592,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
w->window()->raise();
}
- QWindow *win = w->windowHandle();
- if (!win)
- win = w->nativeParentWidget()->windowHandle();
- if (win) {
+ if (auto win = qt_widget_private(w)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest)) {
const QRect globalGeometry = win->isTopLevel()
? win->geometry()
: QRect(win->mapToGlobal(QPoint(0, 0)), win->size());
@@ -1018,7 +1021,11 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
}
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+bool QWidgetWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
+#else
bool QWidgetWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
+#endif
{
return m_widget->nativeEvent(eventType, message, result);
}
@@ -1096,7 +1103,7 @@ void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e)
}
}
if (fw && fw->isEnabled()) {
- QPoint pos = fw->inputMethodQuery(Qt::ImMicroFocus).toRect().center();
+ QPoint pos = fw->inputMethodQuery(Qt::ImCursorRectangle).toRect().center();
QContextMenuEvent widgetEvent(QContextMenuEvent::Keyboard, pos, fw->mapToGlobal(pos),
e->modifiers());
QGuiApplication::forwardEvent(fw, &widgetEvent, e);
diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index 0728135467..80a345465d 100644
--- a/src/widgets/kernel/qwidgetwindow_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -103,7 +103,11 @@ protected:
#endif
void handleExposeEvent(QExposeEvent *);
void handleWindowStateChangedEvent(QWindowStateChangeEvent *event);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
+#else
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
+#endif
#if QT_CONFIG(tabletevent)
void handleTabletEvent(QTabletEvent *);
#endif
diff --git a/src/widgets/kernel/qwindowcontainer_p.h b/src/widgets/kernel/qwindowcontainer_p.h
index a8754232a8..c6de168c10 100644
--- a/src/widgets/kernel/qwindowcontainer_p.h
+++ b/src/widgets/kernel/qwindowcontainer_p.h
@@ -64,7 +64,7 @@ class Q_WIDGETS_EXPORT QWindowContainer : public QWidget
Q_DECLARE_PRIVATE(QWindowContainer)
public:
- explicit QWindowContainer(QWindow *embeddedWindow, QWidget *parent = 0, Qt::WindowFlags f = 0);
+ explicit QWindowContainer(QWindow *embeddedWindow, QWidget *parent = nullptr, Qt::WindowFlags f = nullptr);
~QWindowContainer();
QWindow *containedWindow() const;
diff --git a/src/widgets/kernel/win.pri b/src/widgets/kernel/win.pri
index f6877b02db..3b3170beb1 100644
--- a/src/widgets/kernel/win.pri
+++ b/src/widgets/kernel/win.pri
@@ -2,4 +2,7 @@
# --------------------------------------------------------------------
INCLUDEPATH += ../3rdparty/wintab
-!winrt: LIBS_PRIVATE *= -lshell32 -luxtheme -ldwmapi
+!winrt {
+ LIBS_PRIVATE *= -luxtheme -ldwmapi
+ QMAKE_USE_PRIVATE += shell32
+}
diff --git a/src/widgets/statemachine/qbasickeyeventtransition_p.h b/src/widgets/statemachine/qbasickeyeventtransition_p.h
index 5007b79739..f23c078570 100644
--- a/src/widgets/statemachine/qbasickeyeventtransition_p.h
+++ b/src/widgets/statemachine/qbasickeyeventtransition_p.h
@@ -63,11 +63,11 @@ class Q_AUTOTEST_EXPORT QBasicKeyEventTransition : public QAbstractTransition
{
Q_OBJECT
public:
- QBasicKeyEventTransition(QState *sourceState = 0);
- QBasicKeyEventTransition(QEvent::Type type, int key, QState *sourceState = 0);
+ QBasicKeyEventTransition(QState *sourceState = nullptr);
+ QBasicKeyEventTransition(QEvent::Type type, int key, QState *sourceState = nullptr);
QBasicKeyEventTransition(QEvent::Type type, int key,
Qt::KeyboardModifiers modifierMask,
- QState *sourceState = 0);
+ QState *sourceState = nullptr);
~QBasicKeyEventTransition();
QEvent::Type eventType() const;
@@ -84,7 +84,7 @@ protected:
void onTransition(QEvent *) override;
private:
- Q_DISABLE_COPY(QBasicKeyEventTransition)
+ Q_DISABLE_COPY_MOVE(QBasicKeyEventTransition)
Q_DECLARE_PRIVATE(QBasicKeyEventTransition)
};
diff --git a/src/widgets/statemachine/qbasicmouseeventtransition_p.h b/src/widgets/statemachine/qbasicmouseeventtransition_p.h
index 93d2a5ec61..dd619d189c 100644
--- a/src/widgets/statemachine/qbasicmouseeventtransition_p.h
+++ b/src/widgets/statemachine/qbasicmouseeventtransition_p.h
@@ -65,9 +65,9 @@ class Q_AUTOTEST_EXPORT QBasicMouseEventTransition : public QAbstractTransition
{
Q_OBJECT
public:
- QBasicMouseEventTransition(QState *sourceState = 0);
+ QBasicMouseEventTransition(QState *sourceState = nullptr);
QBasicMouseEventTransition(QEvent::Type type, Qt::MouseButton button,
- QState *sourceState = 0);
+ QState *sourceState = nullptr);
~QBasicMouseEventTransition();
QEvent::Type eventType() const;
@@ -87,7 +87,7 @@ protected:
void onTransition(QEvent *) override;
private:
- Q_DISABLE_COPY(QBasicMouseEventTransition)
+ Q_DISABLE_COPY_MOVE(QBasicMouseEventTransition)
Q_DECLARE_PRIVATE(QBasicMouseEventTransition)
};
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index c739ddc6e2..9e701995a4 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -100,6 +100,9 @@
#if QT_CONFIG(wizard)
#include <qwizard.h>
#endif
+#if QT_CONFIG(filedialog)
+#include <qsidebar_p.h>
+#endif
#include <qfileinfo.h>
#include <qdir.h>
#if QT_CONFIG(settings)
@@ -113,10 +116,7 @@
#include <limits.h>
-#if QT_CONFIG(itemviews)
-# include "private/qtextengine_p.h"
-#endif
-
+#include <private/qtextengine_p.h>
#include <private/qstylehelper_p.h>
QT_BEGIN_NAMESPACE
@@ -191,12 +191,12 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
opt->state & (State_Sunken | State_On), 1,
&opt->palette.brush(QPalette::Button));
break;
- case PE_IndicatorViewItemCheck:
+ case PE_IndicatorItemViewItemCheck:
proxy()->drawPrimitive(PE_IndicatorCheckBox, opt, p, widget);
break;
case PE_IndicatorCheckBox:
if (opt->state & State_NoChange) {
- p->setPen(opt->palette.foreground().color());
+ p->setPen(opt->palette.windowText().color());
p->fillRect(opt->rect, opt->palette.brush(QPalette::Button));
p->drawRect(opt->rect);
p->drawLine(opt->rect.topLeft(), opt->rect.bottomRight());
@@ -212,7 +212,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
p->drawArc(opt->rect, 0, 5760);
if (opt->state & (State_Sunken | State_On)) {
ir.adjust(2, 2, -2, -2);
- p->setBrush(opt->palette.foreground());
+ p->setBrush(opt->palette.windowText());
bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting);
p->setRenderHint(QPainter::Qt4CompatiblePainting);
p->drawEllipse(ir);
@@ -231,7 +231,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
else
p->setPen(Qt::white);
} else {
- p->setPen(opt->palette.foreground().color());
+ p->setPen(opt->palette.windowText().color());
}
QRect focusRect = opt->rect.adjusted(1, 1, -1, -1);
p->drawRect(focusRect.adjusted(0, 0, -1, -1)); //draw pen inclusive
@@ -278,7 +278,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
qDrawShadePanel(p, frame->rect, frame->palette, frame->state & State_Sunken,
frame->lineWidth);
} else {
- qDrawPlainRect(p, frame->rect, frame->palette.foreground().color(), frame->lineWidth);
+ qDrawPlainRect(p, frame->rect, frame->palette.windowText().color(), frame->lineWidth);
}
}
break;
@@ -615,7 +615,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
}
p->setPen(QPen(tab->palette.dark(), qreal(.8)));
- p->setBrush(tab->palette.background());
+ p->setBrush(tab->palette.window());
p->setRenderHint(QPainter::Antialiasing);
p->drawPath(path);
}
@@ -748,7 +748,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
QString pixmapName = QStyleHelper::uniqueName(QLatin1String("$qt_ia-")
% QLatin1String(metaObject()->className()), opt, QSize(size, size))
% HexString<uint>(pe);
- if (!QPixmapCache::find(pixmapName, pixmap)) {
+ if (!QPixmapCache::find(pixmapName, &pixmap)) {
qreal pixelRatio = p->device()->devicePixelRatioF();
int border = qRound(pixelRatio*(size/5));
int sqsize = qRound(pixelRatio*(2*(size/2)));
@@ -1249,8 +1249,9 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *w
// High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize
tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height()));
- *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2,
- tabIconSize.width(), tabIconSize.height());
+ const int offsetX = (iconSize.width() - tabIconSize.width()) / 2;
+ *iconRect = QRect(tr.left() + offsetX, tr.center().y() - tabIconSize.height() / 2,
+ tabIconSize.width(), tabIconSize.height());
if (!verticalTabs)
*iconRect = proxyStyle->visualRect(opt->direction, opt->rect, *iconRect);
tr.setLeft(tr.left() + tabIconSize.width() + 4);
@@ -1565,7 +1566,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QPalette pal2 = pb->palette;
// Correct the highlight color if it is the same as the background
- if (pal2.highlight() == pal2.background())
+ if (pal2.highlight() == pal2.window())
pal2.setColor(QPalette::Highlight, pb->palette.color(QPalette::Active,
QPalette::Highlight));
bool reverse = ((!vertical && (pb->direction == Qt::RightToLeft)) || vertical);
@@ -1853,14 +1854,14 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
}
}
- p->setPen(QPen(tab->palette.foreground(), 0));
+ p->setPen(QPen(tab->palette.windowText(), 0));
if (selected) {
p->setBrush(tab->palette.base());
} else {
if (widget && widget->parentWidget())
- p->setBrush(widget->parentWidget()->palette().background());
+ p->setBrush(widget->parentWidget()->palette().window());
else
- p->setBrush(tab->palette.background());
+ p->setBrush(tab->palette.window());
}
int y;
@@ -2157,7 +2158,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
const int indent = p->fontMetrics().descent();
proxy()->drawItemText(p, r.adjusted(indent + 1, 1, -indent - 1, -1),
- Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette,
+ Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette,
dwOpt->state & State_Enabled, dwOpt->title,
QPalette::WindowText);
@@ -2184,7 +2185,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
}
break;
case CE_FocusFrame:
- p->fillRect(opt->rect, opt->palette.foreground());
+ p->fillRect(opt->rect, opt->palette.windowText());
break;
case CE_HeaderSection:
qDrawShadePanel(p, opt->rect, opt->palette,
@@ -2192,7 +2193,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
&opt->palette.brush(QPalette::Button));
break;
case CE_HeaderEmptyArea:
- p->fillRect(opt->rect, opt->palette.background());
+ p->fillRect(opt->rect, opt->palette.window());
break;
#if QT_CONFIG(combobox)
case CE_ComboBoxLabel:
@@ -2296,7 +2297,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
option.state |= QStyle::State_On;
break;
}
- proxy()->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p, widget);
}
// draw the icon
@@ -3137,7 +3138,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
}
d->cachedOption = new QStyleOptionViewItem(*vopt);
}
- if (sr == SE_ViewItemCheckIndicator)
+ if (sr == SE_ItemViewItemCheckIndicator)
r = d->checkRect;
else if (sr == SE_ItemViewItemDecoration)
r = d->decorationRect;
@@ -3153,13 +3154,17 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
///we need to access the widget here because the style option doesn't
//have all the information we need (ie. the layout's margin)
const QToolBar *tb = qobject_cast<const QToolBar*>(widget);
- const int margin = tb && tb->layout() ? tb->layout()->margin() : 2;
+ const QMargins margins = tb && tb->layout() ? tb->layout()->contentsMargins() : QMargins(2, 2, 2, 2);
const int handleExtent = proxy()->pixelMetric(QStyle::PM_ToolBarHandleExtent, opt, tb);
if (tbopt->state & QStyle::State_Horizontal) {
- r = QRect(margin, margin, handleExtent, tbopt->rect.height() - 2*margin);
+ r = QRect(margins.left(), margins.top(),
+ handleExtent,
+ tbopt->rect.height() - (margins.top() + margins.bottom()));
r = QStyle::visualRect(tbopt->direction, tbopt->rect, r);
} else {
- r = QRect(margin, margin, tbopt->rect.width() - 2*margin, handleExtent);
+ r = QRect(margins.left(), margins.top(),
+ tbopt->rect.width() - (margins.left() + margins.right()),
+ handleExtent);
}
}
}
@@ -3256,7 +3261,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
// Since there is no subrect for tickmarks do a translation here.
p->save();
p->translate(slider->rect.x(), slider->rect.y());
- p->setPen(slider->palette.foreground().color());
+ p->setPen(slider->palette.windowText().color());
int v = slider->minimum;
while (v <= slider->maximum + 1) {
if (v == slider->maximum + 1 && interval == 1)
@@ -3702,7 +3707,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
QPalette pal = opt->palette;
// draw notches
if (dial->subControls & QStyle::SC_DialTickmarks) {
- p->setPen(pal.foreground().color());
+ p->setPen(pal.windowText().color());
p->drawLines(QStyleHelper::calcLines(dial));
}
@@ -4359,8 +4364,10 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
int topMargin = 0;
int topHeight = 0;
int verticalAlignment = proxy()->styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
- if (groupBox->text.size() || (groupBox->subControls & QStyle::SC_GroupBoxCheckBox)) {
- topHeight = groupBox->fontMetrics.height();
+ bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox;
+ if (groupBox->text.size() || hasCheckBox) {
+ int checkBoxHeight = hasCheckBox ? proxy()->pixelMetric(PM_IndicatorHeight, groupBox, widget) : 0;
+ topHeight = qMax(groupBox->fontMetrics.height(), checkBoxHeight);
if (verticalAlignment & Qt::AlignVCenter)
topMargin = topHeight / 2;
else if (verticalAlignment & Qt::AlignTop)
@@ -4385,20 +4392,24 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
case SC_GroupBoxCheckBox:
case SC_GroupBoxLabel: {
QFontMetrics fontMetrics = groupBox->fontMetrics;
- int h = fontMetrics.height();
+ int th = fontMetrics.height();
int tw = fontMetrics.size(Qt::TextShowMnemonic, groupBox->text + QLatin1Char(' ')).width();
int marg = (groupBox->features & QStyleOptionFrame::Flat) ? 0 : 8;
ret = groupBox->rect.adjusted(marg, 0, -marg, 0);
- ret.setHeight(h);
int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget);
+ int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget);
int indicatorSpace = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, opt, widget) - 1;
bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox;
- int checkBoxSize = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0;
+ int checkBoxWidth = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0;
+ int checkBoxHeight = hasCheckBox ? indicatorHeight : 0;
+
+ int h = qMax(th, checkBoxHeight);
+ ret.setHeight(h);
// Adjusted rect for label + indicatorWidth + indicatorSpace
QRect totalRect = alignedRect(groupBox->direction, groupBox->textAlignment,
- QSize(tw + checkBoxSize, h), ret);
+ QSize(tw + checkBoxWidth, h), ret);
// Adjust totalRect if checkbox is set
if (hasCheckBox) {
@@ -4406,15 +4417,14 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
int left = 0;
// Adjust for check box
if (sc == SC_GroupBoxCheckBox) {
- int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget);
left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth);
- int top = totalRect.top() + qMax(0, fontMetrics.height() - indicatorHeight) / 2;
+ int top = totalRect.top() + (h - checkBoxHeight) / 2;
totalRect.setRect(left, top, indicatorWidth, indicatorHeight);
// Adjust for label
} else {
- left = ltr ? (totalRect.left() + checkBoxSize - 2) : totalRect.left();
- totalRect.setRect(left, totalRect.top(),
- totalRect.width() - checkBoxSize, totalRect.height());
+ left = ltr ? (totalRect.left() + checkBoxWidth - 2) : totalRect.left();
+ int top = totalRect.top() + (h - th) / 2;
+ totalRect.setRect(left, top, totalRect.width() - checkBoxWidth, th);
}
}
ret = totalRect;
@@ -4790,9 +4800,16 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
break;
case PM_TabBarIconSize:
- case PM_ListViewIconSize:
ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
break;
+ case PM_ListViewIconSize:
+#if QT_CONFIG(filedialog)
+ if (qobject_cast<const QSidebar *>(widget))
+ ret = int(QStyleHelper::dpiScaled(24.));
+ else
+#endif
+ ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
+ break;
case PM_ButtonIconSize:
case PM_SmallIconSize:
@@ -4972,8 +4989,8 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
break;
#if QT_CONFIG(groupbox)
case CT_GroupBox:
- if (const QGroupBox *grb = static_cast<const QGroupBox *>(widget))
- sz += QSize(!grb->isFlat() ? 16 : 0, 0);
+ if (const QStyleOptionGroupBox *styleOpt = qstyleoption_cast<const QStyleOptionGroupBox *>(opt))
+ sz += QSize(styleOpt->features.testFlag(QStyleOptionFrame::Flat) ? 0 : 16, 0);
break;
#endif // QT_CONFIG(groupbox)
case CT_MdiControls:
@@ -5009,7 +5026,8 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case CT_SpinBox:
if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
// Add button + frame widths
- const int buttonWidth = (vopt->subControls & (QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown)) != 0 ? 20 : 0;
+ const bool hasButtons = (vopt->buttonSymbols != QAbstractSpinBox::NoButtons);
+ const int buttonWidth = hasButtons ? proxy()->subControlRect(CC_SpinBox, vopt, SC_SpinBoxUp, widget).width() : 0;
const int fw = vopt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0;
sz += QSize(buttonWidth + 2*fw, 2*fw);
}
diff --git a/src/widgets/styles/qcommonstyle_p.h b/src/widgets/styles/qcommonstyle_p.h
index 296f89ce5f..4860dfe4c9 100644
--- a/src/widgets/styles/qcommonstyle_p.h
+++ b/src/widgets/styles/qcommonstyle_p.h
@@ -71,7 +71,7 @@ class Q_WIDGETS_EXPORT QCommonStylePrivate : public QStylePrivate
public:
inline QCommonStylePrivate() :
#if QT_CONFIG(itemviews)
- cachedOption(0),
+ cachedOption(nullptr),
#endif
animationFps(30)
{ }
diff --git a/src/widgets/styles/qdrawutil.cpp b/src/widgets/styles/qdrawutil.cpp
index 299dbb9f82..d30b43a679 100644
--- a/src/widgets/styles/qdrawutil.cpp
+++ b/src/widgets/styles/qdrawutil.cpp
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
namespace {
class PainterStateGuard {
- Q_DISABLE_COPY(PainterStateGuard)
+ Q_DISABLE_COPY_MOVE(PainterStateGuard)
public:
explicit PainterStateGuard(QPainter *p) : m_painter(p) {}
~PainterStateGuard()
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index 64954dc833..34cc3c93db 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -261,7 +261,7 @@ static void qt_fusion_draw_arrow(Qt::ArrowType type, QPainter *painter, const QS
QString cacheKey = QStyleHelper::uniqueName(QLatin1String("fusion-arrow"), option, rect.size())
% HexString<uint>(type)
% HexString<uint>(color.rgba());
- if (!QPixmapCache::find(cacheKey, cachePixmap)) {
+ if (!QPixmapCache::find(cacheKey, &cachePixmap)) {
cachePixmap = styleCachePixmap(rect.size());
cachePixmap.fill(Qt::transparent);
QPainter cachePainter(&cachePixmap);
@@ -539,7 +539,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
{
if (option->rect.width() <= 1 || option->rect.height() <= 1)
break;
- QColor arrowColor = option->palette.foreground().color();
+ QColor arrowColor = option->palette.windowText().color();
arrowColor.setAlpha(160);
Qt::ArrowType arrow = Qt::UpArrow;
switch (elem) {
@@ -558,7 +558,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
qt_fusion_draw_arrow(arrow, painter, option, option->rect, arrowColor);
}
break;
- case PE_IndicatorViewItemCheck:
+ case PE_IndicatorItemViewItemCheck:
{
QStyleOptionButton button;
button.QStyleOption::operator=(*option);
@@ -569,7 +569,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
case PE_IndicatorHeaderArrow:
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
QRect r = header->rect;
- QColor arrowColor = header->palette.foreground().color();
+ QColor arrowColor = header->palette.windowText().color();
arrowColor.setAlpha(180);
QPoint offset = QPoint(0, -2);
@@ -598,24 +598,24 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
const int margin = 6;
if (option->state & State_Horizontal) {
const int offset = rect.width()/2;
- painter->setPen(QPen(option->palette.background().color().darker(110)));
+ painter->setPen(QPen(option->palette.window().color().darker(110)));
painter->drawLine(rect.bottomLeft().x() + offset,
rect.bottomLeft().y() - margin,
rect.topLeft().x() + offset,
rect.topLeft().y() + margin);
- painter->setPen(QPen(option->palette.background().color().lighter(110)));
+ painter->setPen(QPen(option->palette.window().color().lighter(110)));
painter->drawLine(rect.bottomLeft().x() + offset + 1,
rect.bottomLeft().y() - margin,
rect.topLeft().x() + offset + 1,
rect.topLeft().y() + margin);
} else { //Draw vertical separator
const int offset = rect.height()/2;
- painter->setPen(QPen(option->palette.background().color().darker(110)));
+ painter->setPen(QPen(option->palette.window().color().darker(110)));
painter->drawLine(rect.topLeft().x() + margin ,
rect.topLeft().y() + offset,
rect.topRight().x() - margin,
rect.topRight().y() + offset);
- painter->setPen(QPen(option->palette.background().color().lighter(110)));
+ painter->setPen(QPen(option->palette.window().color().lighter(110)));
painter->drawLine(rect.topLeft().x() + margin ,
rect.topLeft().y() + offset + 1,
rect.topRight().x() - margin,
@@ -642,8 +642,8 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
{
painter->setPen(QPen(outline));
painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
- QColor frameLight = option->palette.background().color().lighter(160);
- QColor frameShadow = option->palette.background().color().darker(110);
+ QColor frameLight = option->palette.window().color().lighter(160);
+ QColor frameShadow = option->palette.window().color().darker(110);
//paint beveleffect
QRect frame = option->rect.adjusted(1, 1, -1, -1);
@@ -661,14 +661,14 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->save();
{
- QColor softshadow = option->palette.background().color().darker(120);
+ QColor softshadow = option->palette.window().color().darker(120);
QRect rect= option->rect;
painter->setPen(softshadow);
painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
painter->setPen(QPen(option->palette.light(), 1));
painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1));
- painter->setPen(QPen(option->palette.background().color().darker(120)));
+ painter->setPen(QPen(option->palette.window().color().darker(120)));
painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1));
painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), QPoint(rect.right() - 1, rect.bottom() - 1));
@@ -704,7 +704,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->setPen(QPen(option->palette.light(), 1));
painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1),
QPoint(rect.left() + 1, rect.bottom() - 1));
- painter->setPen(QPen(option->palette.background().color().darker(120)));
+ painter->setPen(QPen(option->palette.window().color().darker(120)));
painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1),
QPoint(rect.right() - 2, rect.bottom() - 1));
painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1),
@@ -748,7 +748,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->translate(0.5, 0.5);
rect = rect.adjusted(0, 0, -1, -1);
- QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.foreground().color(), 85);
+ QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85);
painter->setBrush(Qt::NoBrush);
// Gradient fill
@@ -802,14 +802,14 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
case PE_IndicatorRadioButton:
painter->save();
{
- QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.foreground().color(), 85);
+ QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.windowText().color(), 85);
painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color());
painter->setRenderHint(QPainter::Antialiasing, true);
QPainterPath circle;
const QPointF circleCenter = rect.center() + QPoint(1, 1);
const qreal outlineRadius = (rect.width() + (rect.width() + 1) % 2) / 2.0 - 1;
circle.addEllipse(circleCenter, outlineRadius, outlineRadius);
- painter->setPen(QPen(option->palette.background().color().darker(150)));
+ painter->setPen(QPen(option->palette.window().color().darker(150)));
if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
painter->setPen(QPen(highlightedOutline));
painter->drawPath(circle);
@@ -991,7 +991,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
case PE_PanelMenu: {
painter->save();
const QBrush menuBackground = option->palette.base().color().lighter(108);
- QColor borderColor = option->palette.background().color().darker(160);
+ QColor borderColor = option->palette.window().color().darker(160);
qDrawPlainRect(painter, option->rect, borderColor, 1, &menuBackground);
painter->restore();
}
@@ -1256,7 +1256,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
Qt::ElideRight, titleRect.width());
proxy()->drawItemText(painter,
titleRect,
- Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette,
+ Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette,
dwOpt->state & State_Enabled, titleText,
QPalette::WindowText);
}
@@ -1272,7 +1272,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
pixmapName += QString::number(- int(header->orientation));
QPixmap cache;
- if (!QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, &cache)) {
cache = styleCachePixmap(rect.size());
cache.fill(Qt::transparent);
QRect pixmapRect(0, 0, rect.width(), rect.height());
@@ -1283,8 +1283,8 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
gradientStopColor = buttonColor.darker(102);
QLinearGradient gradient(pixmapRect.topLeft(), pixmapRect.bottomLeft());
- if (option->palette.background().gradient()) {
- gradient.setStops(option->palette.background().gradient()->stops());
+ if (option->palette.window().gradient()) {
+ gradient.setStops(option->palette.window().gradient()->stops());
} else {
QColor midColor1 = mergedColors(gradientStartColor, gradientStopColor, 60);
QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 40);
@@ -1519,7 +1519,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
proxy()->drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
} else {
- QColor shadow = mergedColors(option->palette.background().color().darker(120),
+ QColor shadow = mergedColors(option->palette.window().color().darker(120),
outline.lighter(140), 60);
painter->setPen(QPen(shadow));
painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
@@ -1649,7 +1649,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
if (!ignoreCheckMark && checkable && checked) {
QStyleOption opt = *option;
if (act) {
- QColor activeColor = mergedColors(option->palette.background().color(),
+ QColor activeColor = mergedColors(option->palette.window().color(),
option->palette.highlight().color());
opt.palette.setBrush(QPalette::Button, activeColor);
}
@@ -1731,7 +1731,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
newMI.rect = vSubMenuRect;
newMI.state = !enabled ? State_None : State_Enabled;
if (selected)
- newMI.palette.setColor(QPalette::Foreground,
+ newMI.palette.setColor(QPalette::WindowText,
newMI.palette.highlightedText().color());
proxy()->drawPrimitive(arrow, &newMI, painter, widget);
}
@@ -1812,7 +1812,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
painter->save();
{
painter->fillRect(rect, option->palette.window());
- QColor shadow = mergedColors(option->palette.background().color().darker(120),
+ QColor shadow = mergedColors(option->palette.window().color().darker(120),
outline.lighter(140), 60);
painter->setPen(QPen(shadow));
painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight());
@@ -1975,7 +1975,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
// ### backgroundrole/foregroundrole should be part of the style option
alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), outline);
} else {
- alphaCornerColor = mergedColors(option->palette.background().color(), outline);
+ alphaCornerColor = mergedColors(option->palette.window().color(), outline);
}
switch (control) {
@@ -2030,7 +2030,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
QPixmap cache;
QString pixmapName = QStyleHelper::uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size());
- if (!QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, &cache)) {
cache = styleCachePixmap(spinBox->rect.size());
cache.fill(Qt::transparent);
@@ -2039,7 +2039,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
QRect rect = pixmapRect;
QRect r = rect.adjusted(0, 1, 0, -1);
QPainter cachePainter(&cache);
- QColor arrowColor = spinBox->palette.foreground().color();
+ QColor arrowColor = spinBox->palette.windowText().color();
arrowColor.setAlpha(160);
bool isEnabled = (spinBox->state & State_Enabled);
@@ -2174,13 +2174,13 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
QColor highlight = option->palette.highlight().color();
QColor titleBarFrameBorder(active ? highlight.darker(180): outline.darker(110));
- QColor titleBarHighlight(active ? highlight.lighter(120): palette.background().color().lighter(120));
+ QColor titleBarHighlight(active ? highlight.lighter(120): palette.window().color().lighter(120));
QColor textColor(active ? 0xffffff : 0xff000000);
QColor textAlphaColor(active ? 0xffffff : 0xff000000 );
{
// Fill title bar gradient
- QColor titlebarColor = QColor(active ? highlight: palette.background().color());
+ QColor titlebarColor = QColor(active ? highlight: palette.window().color());
QLinearGradient gradient(option->rect.center().x(), option->rect.top(),
option->rect.center().x(), option->rect.bottom());
@@ -2531,7 +2531,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
QColor alphaOutline = outline;
alphaOutline.setAlpha(180);
- QColor arrowColor = option->palette.foreground().color();
+ QColor arrowColor = option->palette.windowText().color();
arrowColor.setAlpha(160);
const QColor bgColor = QStyleHelper::backgroundColor(option->palette, widget);
@@ -2745,7 +2745,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
if (!comboBox->frame)
pixmapName += QLatin1String("-frameless");
- if (!QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, &cache)) {
cache = styleCachePixmap(comboBox->rect.size());
cache.fill(Qt::transparent);
QPainter cachePainter(&cache);
@@ -2860,7 +2860,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
QRect pixmapRect(0, 0, groove.width(), groove.height());
// draw background groove
- if (!QPixmapCache::find(groovePixmapName, cache)) {
+ if (!QPixmapCache::find(groovePixmapName, &cache)) {
cache = styleCachePixmap(pixmapRect.size());
cache.fill(Qt::transparent);
QPainter groovePainter(&cache);
@@ -2888,7 +2888,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
// draw blue groove highlight
QRect clipRect;
groovePixmapName += QLatin1String("_blue");
- if (!QPixmapCache::find(groovePixmapName, cache)) {
+ if (!QPixmapCache::find(groovePixmapName, &cache)) {
cache = styleCachePixmap(pixmapRect.size());
cache.fill(Qt::transparent);
QPainter groovePainter(&cache);
@@ -2995,7 +2995,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
// draw handle
if ((option->subControls & SC_SliderHandle) ) {
QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size());
- if (!QPixmapCache::find(handlePixmapName, cache)) {
+ if (!QPixmapCache::find(handlePixmapName, &cache)) {
cache = styleCachePixmap(handle.size());
cache.fill(Qt::transparent);
QRect pixmapRect(0, 0, handle.width(), handle.height());
@@ -3233,7 +3233,7 @@ QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *opti
QFont fontBold = menuItem->font;
fontBold.setBold(true);
QFontMetrics fmBold(fontBold);
- w += fmBold.width(menuItem->text) - fm.horizontalAdvance(menuItem->text);
+ w += fmBold.horizontalAdvance(menuItem->text) - fm.horizontalAdvance(menuItem->text);
}
const int checkcol = qMax<int>(maxpmw, QStyleHelper::dpiScaled(QFusionStylePrivate::menuCheckMarkWidth)); // Windows always shows a check column
w += checkcol;
@@ -3681,7 +3681,7 @@ int QFusionStyle::styleHint(StyleHint hint, const QStyleOption *option, const QW
case SH_FontDialog_SelectAssociatedText:
case SH_MenuBar_AltKeyNavigation:
case SH_ComboBox_ListMouseTracking:
- case SH_ScrollBar_StopMouseOverSlider:
+ case SH_Slider_StopMouseOverSlider:
case SH_ScrollBar_MiddleClickAbsolutePosition:
case SH_EtchDisabledText:
case SH_TitleBar_AutoRaise:
@@ -3713,7 +3713,7 @@ int QFusionStyle::styleHint(StyleHint hint, const QStyleOption *option, const QW
return 0;
case SH_Table_GridLineColor:
- return option ? option->palette.background().color().darker(120).rgb() : 0;
+ return option ? option->palette.window().color().darker(120).rgb() : 0;
case SH_MessageBox_TextInteractionFlags:
return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse;
diff --git a/src/widgets/styles/qfusionstyle_p.h b/src/widgets/styles/qfusionstyle_p.h
index e67e792727..cbefe3e1af 100644
--- a/src/widgets/styles/qfusionstyle_p.h
+++ b/src/widgets/styles/qfusionstyle_p.h
@@ -72,28 +72,28 @@ public:
QPalette standardPalette () const override;
void drawPrimitive(PrimitiveElement elem,
const QStyleOption *option,
- QPainter *painter, const QWidget *widget = 0) const override;
+ QPainter *painter, const QWidget *widget = nullptr) const override;
void drawControl(ControlElement ce, const QStyleOption *option, QPainter *painter,
const QWidget *widget) const override;
- int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const override;
+ int pixelMetric(PixelMetric metric, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const override;
void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
QPainter *painter, const QWidget *widget) const override;
- QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const override;
+ QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = nullptr) const override;
QSize sizeFromContents(ContentsType type, const QStyleOption *option,
const QSize &size, const QWidget *widget) const override;
SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
- const QPoint &pt, const QWidget *w = 0) const override;
+ const QPoint &pt, const QWidget *w = nullptr) const override;
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
SubControl sc, const QWidget *widget) const override;
QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
const QStyleOption *opt) const override;
- int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0,
- QStyleHintReturn *returnData = 0) const override;
+ int styleHint(StyleHint hint, const QStyleOption *option = nullptr, const QWidget *widget = nullptr,
+ QStyleHintReturn *returnData = nullptr) const override;
QRect itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const override;
- QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = 0,
- const QWidget *widget = 0) const override;
+ QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr) const override;
QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
- const QWidget *widget = 0) const override;
+ const QWidget *widget = nullptr) const override;
void drawItemPixmap(QPainter *painter, const QRect &rect,
int alignment, const QPixmap &pixmap) const override;
void drawItemText(QPainter *painter, const QRect &rect,
diff --git a/src/widgets/styles/qfusionstyle_p_p.h b/src/widgets/styles/qfusionstyle_p_p.h
index 169fd9a407..a92041fcfe 100644
--- a/src/widgets/styles/qfusionstyle_p_p.h
+++ b/src/widgets/styles/qfusionstyle_p_p.h
@@ -113,7 +113,7 @@ public:
QColor outline(const QPalette &pal) const {
if (pal.window().style() == Qt::TexturePattern)
return QColor(0, 0, 0, 160);
- return pal.background().color().darker(140);
+ return pal.window().color().darker(140);
}
QColor highlightedOutline(const QPalette &pal) const {
diff --git a/src/widgets/styles/qpixmapstyle_p.h b/src/widgets/styles/qpixmapstyle_p.h
index 590434d95e..d32631a527 100644
--- a/src/widgets/styles/qpixmapstyle_p.h
+++ b/src/widgets/styles/qpixmapstyle_p.h
@@ -147,7 +147,7 @@ public:
void drawControl(ControlElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget = nullptr) const override;
void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option,
- QPainter *painter, const QWidget *widget=0) const override;
+ QPainter *painter, const QWidget *widget=nullptr) const override;
QSize sizeFromContents(ContentsType type, const QStyleOption *option,
const QSize &contentsSize, const QWidget *widget = nullptr) const override;
diff --git a/src/widgets/styles/qproxystyle_p.h b/src/widgets/styles/qproxystyle_p.h
index 2343a03e2a..2321f0fed0 100644
--- a/src/widgets/styles/qproxystyle_p.h
+++ b/src/widgets/styles/qproxystyle_p.h
@@ -67,7 +67,7 @@ public:
void ensureBaseStyle() const;
private:
QProxyStylePrivate() :
- QCommonStylePrivate(), baseStyle(0) {}
+ QCommonStylePrivate(), baseStyle(nullptr) {}
mutable QPointer <QStyle> baseStyle;
};
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index ec5b6df6b3..2c1132da19 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -2101,6 +2101,20 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SP_MediaVolume Icon indicating a volume control.
\value SP_MediaVolumeMuted Icon indicating a muted volume control.
\value SP_LineEditClearButton Icon for a standard clear button in a QLineEdit. This enum value was added in Qt 5.2.
+ \value SP_DialogYesToAllButton Icon for a standard YesToAll button in a QDialogButtonBox.
+ This enum value was added in Qt 5.14.
+ \value SP_DialogNoToAllButton Icon for a standard NoToAll button in a QDialogButtonBox.
+ This enum value was added in Qt 5.14.
+ \value SP_DialogSaveAllButton Icon for a standard SaveAll button in a QDialogButtonBox.
+ This enum value was added in Qt 5.14.
+ \value SP_DialogAbortButton Icon for a standard Abort button in a QDialogButtonBox.
+ This enum value was added in Qt 5.14.
+ \value SP_DialogRetryButton Icon for a standard Retry button in a QDialogButtonBox.
+ This enum value was added in Qt 5.14.
+ \value SP_DialogIgnoreButton Icon for a standard Ignore button in a QDialogButtonBox.
+ This enum value was added in Qt 5.14.
+ \value SP_RestoreDefaultsButton Icon for a standard RestoreDefaults button in a QDialogButtonBox.
+ This enum value was added in Qt 5.14.
\value SP_CustomBase Base value for custom standard pixmaps;
custom values must be greater than this value.
diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h
index 9192dae864..ee234457f5 100644
--- a/src/widgets/styles/qstyle.h
+++ b/src/widgets/styles/qstyle.h
@@ -141,8 +141,10 @@ public:
PE_FrameGroupBox,
PE_FrameLineEdit,
PE_FrameMenu,
- PE_FrameStatusBar, // ### Qt 6: remove
- PE_FrameStatusBarItem = PE_FrameStatusBar,
+ PE_FrameStatusBarItem,
+#if QT_DEPRECATED_SINCE(5, 13) // ### Qt 6: remove
+ PE_FrameStatusBar Q_DECL_ENUMERATOR_DEPRECATED = PE_FrameStatusBarItem,
+#endif
PE_FrameTabWidget,
PE_FrameWindow,
PE_FrameButtonBevel,
@@ -162,8 +164,10 @@ public:
PE_IndicatorArrowUp,
PE_IndicatorBranch,
PE_IndicatorButtonDropDown,
- PE_IndicatorViewItemCheck, // ### Qt 6: remove
- PE_IndicatorItemViewItemCheck = PE_IndicatorViewItemCheck,
+ PE_IndicatorItemViewItemCheck,
+#if QT_DEPRECATED_SINCE(5, 13) // ### Qt 6: remove
+ PE_IndicatorViewItemCheck Q_DECL_ENUMERATOR_DEPRECATED = PE_IndicatorItemViewItemCheck,
+#endif
PE_IndicatorCheckBox,
PE_IndicatorDockWidgetResizeHandle,
PE_IndicatorHeaderArrow,
@@ -308,9 +312,10 @@ public:
SE_TabWidgetLeftCorner,
SE_TabWidgetRightCorner,
- SE_ViewItemCheckIndicator, // ### Qt 6: remove
- SE_ItemViewItemCheckIndicator = SE_ViewItemCheckIndicator,
-
+ SE_ItemViewItemCheckIndicator,
+#if QT_DEPRECATED_SINCE(5, 13) // ### Qt 6: remove
+ SE_ViewItemCheckIndicator Q_DECL_ENUMERATOR_DEPRECATED = SE_ItemViewItemCheckIndicator,
+#endif
SE_TabBarTearIndicator,
SE_TabBarTearIndicatorLeft = SE_TabBarTearIndicator,
@@ -506,9 +511,11 @@ public:
PM_DialogButtonsButtonHeight,
PM_MdiSubWindowFrameWidth,
- PM_MDIFrameWidth = PM_MdiSubWindowFrameWidth, // ### Qt 6: remove
PM_MdiSubWindowMinimizedWidth,
- PM_MDIMinimizedWidth = PM_MdiSubWindowMinimizedWidth, // ### Qt 6: remove
+#if QT_DEPRECATED_SINCE(5, 13) // ### Qt 6: remove
+ PM_MDIFrameWidth Q_DECL_ENUMERATOR_DEPRECATED = PM_MdiSubWindowFrameWidth,
+ PM_MDIMinimizedWidth Q_DECL_ENUMERATOR_DEPRECATED = PM_MdiSubWindowMinimizedWidth,
+#endif
PM_HeaderMargin,
PM_HeaderMarkSize,
@@ -649,7 +656,9 @@ public:
SH_ComboBox_Popup,
SH_TitleBar_NoBorder,
SH_Slider_StopMouseOverSlider,
- SH_ScrollBar_StopMouseOverSlider = SH_Slider_StopMouseOverSlider, // ### Qt 6: remove
+#if QT_DEPRECATED_SINCE(5, 13) // ### Qt 6: remove
+ SH_ScrollBar_StopMouseOverSlider Q_DECL_ENUMERATOR_DEPRECATED = SH_Slider_StopMouseOverSlider,
+#endif
SH_BlinkCursorWhenTextSelected,
SH_RichText_FullWidthSelection,
SH_Menu_Scrollable,
@@ -823,6 +832,13 @@ public:
SP_MediaVolume,
SP_MediaVolumeMuted,
SP_LineEditClearButton,
+ SP_DialogYesToAllButton,
+ SP_DialogNoToAllButton,
+ SP_DialogSaveAllButton,
+ SP_DialogAbortButton,
+ SP_DialogRetryButton,
+ SP_DialogIgnoreButton,
+ SP_RestoreDefaultsButton,
// do not add any values below/greater than this
SP_CustomBase = 0xf0000000
};
diff --git a/src/widgets/styles/qstyle_p.h b/src/widgets/styles/qstyle_p.h
index 9643012c31..7942cafaf7 100644
--- a/src/widgets/styles/qstyle_p.h
+++ b/src/widgets/styles/qstyle_p.h
@@ -66,7 +66,7 @@ class QStylePrivate: public QObjectPrivate
Q_DECLARE_PUBLIC(QStyle)
public:
inline QStylePrivate()
- : layoutSpacingIndex(-1), proxyStyle(0) {}
+ : layoutSpacingIndex(-1), proxyStyle(nullptr) {}
static bool useFullScreenForPopup();
@@ -99,7 +99,7 @@ inline QPixmap styleCachePixmap(const QSize &size)
int txType = painter->deviceTransform().type() | painter->worldTransform().type(); \
bool doPixmapCache = (!option->rect.isEmpty()) \
&& ((txType <= QTransform::TxTranslate) || (painter->deviceTransform().type() == QTransform::TxScale)); \
- if (doPixmapCache && QPixmapCache::find(unique, internalPixmapCache)) { \
+ if (doPixmapCache && QPixmapCache::find(unique, &internalPixmapCache)) { \
painter->drawPixmap(option->rect.topLeft(), internalPixmapCache); \
} else { \
if (doPixmapCache) { \
diff --git a/src/widgets/styles/qstylehelper_p.h b/src/widgets/styles/qstylehelper_p.h
index d79dfe4288..fe052b8984 100644
--- a/src/widgets/styles/qstylehelper_p.h
+++ b/src/widgets/styles/qstylehelper_p.h
@@ -89,11 +89,11 @@ namespace QStyleHelper
Q_WIDGETS_EXPORT bool isInstanceOf(QObject *obj, QAccessible::Role role);
Q_WIDGETS_EXPORT bool hasAncestor(QObject *obj, QAccessible::Role role);
#endif
- Q_WIDGETS_EXPORT QColor backgroundColor(const QPalette &pal, const QWidget* widget = 0);
+ Q_WIDGETS_EXPORT QColor backgroundColor(const QPalette &pal, const QWidget* widget = nullptr);
enum WidgetSizePolicy { SizeLarge = 0, SizeSmall = 1, SizeMini = 2, SizeDefault = -1 };
- Q_WIDGETS_EXPORT WidgetSizePolicy widgetSizePolicy(const QWidget *w, const QStyleOption *opt = 0);
+ Q_WIDGETS_EXPORT WidgetSizePolicy widgetSizePolicy(const QWidget *w, const QStyleOption *opt = nullptr);
}
diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp
index 97631a5841..88031a9f1e 100644
--- a/src/widgets/styles/qstyleoption.cpp
+++ b/src/widgets/styles/qstyleoption.cpp
@@ -3270,7 +3270,7 @@ QStyleOptionViewItem::QStyleOptionViewItem(int version)
\fn template <typename T> T qstyleoption_cast<T>(const QStyleOption *option)
\relates QStyleOption
- Returns a T or 0 depending on the \l{QStyleOption::type}{type} and
+ Returns a T or \nullptr depending on the \l{QStyleOption::type}{type} and
\l{QStyleOption::version}{version} of the given \a option.
Example:
@@ -3285,7 +3285,7 @@ QStyleOptionViewItem::QStyleOptionViewItem(int version)
\overload
\relates QStyleOption
- Returns a T or 0 depending on the type of the given \a option.
+ Returns a T or \nullptr depending on the type of the given \a option.
*/
#if QT_CONFIG(tabwidget)
@@ -4006,7 +4006,7 @@ QStyleHintReturnVariant::~QStyleHintReturnVariant()
\fn template <typename T> T qstyleoption_cast<T>(const QStyleHintReturn *hint)
\relates QStyleHintReturn
- Returns a T or 0 depending on the \l{QStyleHintReturn::type}{type}
+ Returns a T or \nullptr depending on the \l{QStyleHintReturn::type}{type}
and \l{QStyleHintReturn::version}{version} of \a hint.
Example:
@@ -4021,7 +4021,7 @@ QStyleHintReturnVariant::~QStyleHintReturnVariant()
\overload
\relates QStyleHintReturn
- Returns a T or 0 depending on the type of \a hint.
+ Returns a T or \nullptr depending on the type of \a hint.
*/
#if !defined(QT_NO_DEBUG_STREAM)
diff --git a/src/widgets/styles/qstyleoption.h b/src/widgets/styles/qstyleoption.h
index 8ae07efc81..763575ff5b 100644
--- a/src/widgets/styles/qstyleoption.h
+++ b/src/widgets/styles/qstyleoption.h
@@ -118,6 +118,7 @@ public:
QStyleOptionFocusRect();
QStyleOptionFocusRect(const QStyleOptionFocusRect &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionFocusRect &operator=(const QStyleOptionFocusRect &other) = default;
protected:
QStyleOptionFocusRect(int version);
@@ -142,6 +143,7 @@ public:
QStyleOptionFrame();
QStyleOptionFrame(const QStyleOptionFrame &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionFrame &operator=(const QStyleOptionFrame &other) = default;
protected:
QStyleOptionFrame(int version);
@@ -171,6 +173,7 @@ public:
QStyleOptionTabWidgetFrame();
inline QStyleOptionTabWidgetFrame(const QStyleOptionTabWidgetFrame &other)
: QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionTabWidgetFrame &operator=(const QStyleOptionTabWidgetFrame &other) = default;
protected:
QStyleOptionTabWidgetFrame(int version);
@@ -194,6 +197,7 @@ public:
QStyleOptionTabBarBase();
QStyleOptionTabBarBase(const QStyleOptionTabBarBase &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionTabBarBase &operator=(const QStyleOptionTabBarBase &other) = default;
protected:
QStyleOptionTabBarBase(int version);
@@ -225,6 +229,7 @@ public:
QStyleOptionHeader();
QStyleOptionHeader(const QStyleOptionHeader &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionHeader &operator=(const QStyleOptionHeader &other) = default;
protected:
QStyleOptionHeader(int version);
@@ -247,6 +252,7 @@ public:
QStyleOptionButton();
QStyleOptionButton(const QStyleOptionButton &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionButton &operator=(const QStyleOptionButton &other) = default;
protected:
QStyleOptionButton(int version);
@@ -284,6 +290,7 @@ public:
QStyleOptionTab();
QStyleOptionTab(const QStyleOptionTab &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionTab &operator=(const QStyleOptionTab &other) = default;
protected:
QStyleOptionTab(int version);
@@ -314,6 +321,7 @@ public:
int midLineWidth;
QStyleOptionToolBar();
QStyleOptionToolBar(const QStyleOptionToolBar &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionToolBar &operator=(const QStyleOptionToolBar &other) = default;
protected:
QStyleOptionToolBar(int version);
@@ -341,6 +349,7 @@ public:
QStyleOptionProgressBar();
QStyleOptionProgressBar(const QStyleOptionProgressBar &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionProgressBar &operator=(const QStyleOptionProgressBar &other) = default;
protected:
QStyleOptionProgressBar(int version);
@@ -371,6 +380,7 @@ public:
QStyleOptionMenuItem();
QStyleOptionMenuItem(const QStyleOptionMenuItem &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionMenuItem &operator=(const QStyleOptionMenuItem &other) = default;
protected:
QStyleOptionMenuItem(int version);
@@ -390,6 +400,7 @@ public:
QStyleOptionDockWidget();
QStyleOptionDockWidget(const QStyleOptionDockWidget &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionDockWidget &operator=(const QStyleOptionDockWidget &other) = default;
protected:
QStyleOptionDockWidget(int version);
@@ -441,6 +452,7 @@ public:
QStyleOptionViewItem();
QStyleOptionViewItem(const QStyleOptionViewItem &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionViewItem &operator=(const QStyleOptionViewItem &other) = default;
protected:
QStyleOptionViewItem(int version);
@@ -471,6 +483,7 @@ public:
QStyleOptionToolBox();
QStyleOptionToolBox(const QStyleOptionToolBox &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionToolBox &operator=(const QStyleOptionToolBox &other) = default;
protected:
QStyleOptionToolBox(int version);
@@ -490,6 +503,7 @@ public:
QStyleOptionRubberBand();
QStyleOptionRubberBand(const QStyleOptionRubberBand &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionRubberBand &operator=(const QStyleOptionRubberBand &other) = default;
protected:
QStyleOptionRubberBand(int version);
@@ -508,6 +522,7 @@ public:
QStyleOptionComplex(int version = QStyleOptionComplex::Version, int type = SO_Complex);
QStyleOptionComplex(const QStyleOptionComplex &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionComplex &operator=(const QStyleOptionComplex &other) = default;
};
#if QT_CONFIG(slider)
@@ -532,6 +547,7 @@ public:
QStyleOptionSlider();
QStyleOptionSlider(const QStyleOptionSlider &other) : QStyleOptionComplex(Version, Type) { *this = other; }
+ QStyleOptionSlider &operator=(const QStyleOptionSlider &other) = default;
protected:
QStyleOptionSlider(int version);
@@ -551,6 +567,7 @@ public:
QStyleOptionSpinBox();
QStyleOptionSpinBox(const QStyleOptionSpinBox &other) : QStyleOptionComplex(Version, Type) { *this = other; }
+ QStyleOptionSpinBox &operator=(const QStyleOptionSpinBox &other) = default;
protected:
QStyleOptionSpinBox(int version);
@@ -578,6 +595,7 @@ public:
QStyleOptionToolButton();
QStyleOptionToolButton(const QStyleOptionToolButton &other) : QStyleOptionComplex(Version, Type) { *this = other; }
+ QStyleOptionToolButton &operator=(const QStyleOptionToolButton &other) = default;
protected:
QStyleOptionToolButton(int version);
@@ -600,6 +618,7 @@ public:
QStyleOptionComboBox();
QStyleOptionComboBox(const QStyleOptionComboBox &other) : QStyleOptionComplex(Version, Type) { *this = other; }
+ QStyleOptionComboBox &operator=(const QStyleOptionComboBox &other) = default;
protected:
QStyleOptionComboBox(int version);
@@ -618,6 +637,7 @@ public:
QStyleOptionTitleBar();
QStyleOptionTitleBar(const QStyleOptionTitleBar &other) : QStyleOptionComplex(Version, Type) { *this = other; }
+ QStyleOptionTitleBar &operator=(const QStyleOptionTitleBar &other) = default;
protected:
QStyleOptionTitleBar(int version);
@@ -638,6 +658,7 @@ public:
QStyleOptionGroupBox();
QStyleOptionGroupBox(const QStyleOptionGroupBox &other) : QStyleOptionComplex(Version, Type) { *this = other; }
+ QStyleOptionGroupBox &operator=(const QStyleOptionGroupBox &other) = default;
protected:
QStyleOptionGroupBox(int version);
};
@@ -652,6 +673,7 @@ public:
QStyleOptionSizeGrip();
QStyleOptionSizeGrip(const QStyleOptionSizeGrip &other) : QStyleOptionComplex(Version, Type) { *this = other; }
+ QStyleOptionSizeGrip &operator=(const QStyleOptionSizeGrip &other) = default;
protected:
QStyleOptionSizeGrip(int version);
};
@@ -668,6 +690,7 @@ public:
QStyleOptionGraphicsItem();
QStyleOptionGraphicsItem(const QStyleOptionGraphicsItem &other) : QStyleOption(Version, Type) { *this = other; }
+ QStyleOptionGraphicsItem &operator=(const QStyleOptionGraphicsItem &other) = default;
static qreal levelOfDetailFromTransform(const QTransform &worldTransform);
protected:
QStyleOptionGraphicsItem(int version);
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 28b4c363a6..c1f498cd0c 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -44,6 +44,7 @@
#include "private/qcssutil_p.h"
#include <qdebug.h>
+#include <qdir.h>
#include <qapplication.h>
#if QT_CONFIG(menu)
#include <qmenu.h>
@@ -850,7 +851,7 @@ QHash<QStyle::SubControl, QRect> QStyleSheetStyle::titleBarLayout(const QWidget
info.rule = subRule;
info.offset = offsets[where];
info.where = where;
- infos.append(qMove(info));
+ infos.append(std::move(info));
offsets[where] += info.width;
}
@@ -957,8 +958,10 @@ QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QObject
origin = Origin_Padding;
Origin clip = Origin_Border;
if (v.extractBackground(&brush, &uri, &repeat, &alignment, &origin, &attachment, &clip)) {
- bg = new QStyleSheetBackgroundData(brush, QStyleSheetStyle::loadPixmap(uri, object),
- repeat, alignment, origin, attachment, clip);
+ QPixmap pixmap = QStyleSheetStyle::loadPixmap(uri, object);
+ if (!uri.isEmpty() && pixmap.isNull())
+ qWarning("Could not create pixmap from %s", qPrintable(QDir::toNativeSeparators(uri)));
+ bg = new QStyleSheetBackgroundData(brush, pixmap, repeat, alignment, origin, attachment, clip);
}
QBrush sfg, fg;
@@ -3246,8 +3249,8 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
#if QT_CONFIG(scrollbar)
case CC_ScrollBar:
if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- QStyleOptionSlider sbOpt(*sb);
if (!rule.hasDrawable()) {
+ QStyleOptionSlider sbOpt(*sb);
sbOpt.rect = rule.borderRect(opt->rect);
rule.drawBackgroundImage(p, opt->rect);
baseStyle()->drawComplexControl(cc, &sbOpt, p, w);
@@ -3443,7 +3446,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
case CE_ToolButtonLabel:
if (const QStyleOptionToolButton *btn = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
if (rule.hasBox() || btn->features & QStyleOptionToolButton::Arrow) {
- QCommonStyle::drawControl(ce, opt, p, w);
+ QWindowsStyle::drawControl(ce, opt, p, w);
} else {
QStyleOptionToolButton butOpt(*btn);
rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button);
@@ -3817,7 +3820,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
if (subRule.hasDrawable()) {
subRule.drawRule(p, opt->rect);
- QCommonStyle::drawControl(ce, &mi, p, w);
+ QCommonStyle::drawControl(ce, &mi, p, w); // deliberate bypass of the base
} else {
if (rule.hasDrawable() && !(opt->state & QStyle::State_Selected)) {
// So that the menu bar background is not hidden by the items
@@ -4083,6 +4086,11 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
if (subRule.hasFont)
p->setFont(subRule.font);
boxCopy.rect = subRule.contentsRect(opt->rect);
+ if (subRule.hasImage()) {
+ // the image is already drawn with CE_ToolBoxTabShape, adjust rect here
+ const int iconExtent = proxy()->pixelMetric(QStyle::PM_SmallIconSize, box, w);
+ boxCopy.rect.setLeft(boxCopy.rect.left() + iconExtent);
+ }
QWindowsStyle::drawControl(ce, &boxCopy, p , w);
if (subRule.hasFont)
p->setFont(oldFont);
@@ -4155,12 +4163,12 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab);
QRect r = positionRect(w, subRule, PseudoElement_TabBarTab, opt->rect, opt->direction);
- if (ce == CE_TabBarTabShape && subRule.hasDrawable()) {
+ if (ce == CE_TabBarTabShape && subRule.hasDrawable() && tab->shape < QTabBar::TriangularNorth) {
subRule.drawRule(p, r);
return;
}
QStyleOptionTab tabCopy(*tab);
- subRule.configurePalette(&tabCopy.palette, QPalette::WindowText, QPalette::Window);
+ subRule.configurePalette(&tabCopy.palette, QPalette::WindowText, QPalette::Base);
QFont oldFont = p->font();
if (subRule.hasFont)
p->setFont(subRule.font);
@@ -4218,7 +4226,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
QString titleText = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, r.width());
drawItemText(p, r,
- alignment | Qt::TextShowMnemonic, dwOpt->palette,
+ alignment, dwOpt->palette,
dwOpt->state & State_Enabled, titleText,
QPalette::WindowText);
@@ -4292,7 +4300,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
switch (pe) {
- case PE_FrameStatusBar: {
+ case PE_FrameStatusBarItem: {
QRenderRule subRule = renderRule(w ? w->parentWidget() : nullptr, opt, PseudoElement_Item);
if (subRule.hasDrawable()) {
subRule.drawRule(p, opt->rect);
@@ -4313,7 +4321,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
pseudoElement = PseudoElement_ExclusiveIndicator;
break;
- case PE_IndicatorViewItemCheck:
+ case PE_IndicatorItemViewItemCheck:
pseudoElement = PseudoElement_ViewItemIndicator;
break;
@@ -4977,17 +4985,19 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
switch (ct) {
#if QT_CONFIG(spinbox)
- case CT_SpinBox: // ### hopelessly broken QAbstractSpinBox (part 1)
+ case CT_SpinBox:
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
- // Add some space for the up/down buttons
- QRenderRule subRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton);
- if (subRule.hasDrawable()) {
- QRect r = positionRect(w, rule, subRule, PseudoElement_SpinBoxUpButton,
- opt->rect, opt->direction);
- sz += QSize(r.width(), 0);
- } else {
- QSize defaultUpSize = defaultSize(w, subRule.size(), spinbox->rect, PseudoElement_SpinBoxUpButton);
- sz += QSize(defaultUpSize.width(), 0);
+ if (spinbox->buttonSymbols != QAbstractSpinBox::NoButtons) {
+ // Add some space for the up/down buttons
+ QRenderRule subRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton);
+ if (subRule.hasDrawable()) {
+ QRect r = positionRect(w, rule, subRule, PseudoElement_SpinBoxUpButton,
+ opt->rect, opt->direction);
+ sz.rwidth() += r.width();
+ } else {
+ QSize defaultUpSize = defaultSize(w, subRule.size(), spinbox->rect, PseudoElement_SpinBoxUpButton);
+ sz.rwidth() += defaultUpSize.width();
+ }
}
if (rule.hasBox() || rule.hasBorder() || !rule.hasNativeBorder())
sz = rule.boxSize(sz);
@@ -5083,7 +5093,8 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
QRenderRule subRule = renderRule(w, opt, pe);
if ((pe == PseudoElement_MenuSeparator) && subRule.hasContentsSize()) {
return QSize(sz.width(), subRule.size().height());
- } else if ((pe == PseudoElement_Item) && (subRule.hasBox() || subRule.hasBorder())) {
+ }
+ if ((pe == PseudoElement_Item) && (subRule.hasBox() || subRule.hasBorder() || subRule.hasFont)) {
QSize sz(csz);
if (mi->text.contains(QLatin1Char('\t')))
sz.rwidth() += 12; //as in QCommonStyle
@@ -5097,6 +5108,11 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
QRect checkmarkRect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
sz.rwidth() += std::max(mi->maxIconWidth, checkmarkRect.width()) + 4;
}
+ if (subRule.hasFont) {
+ QFontMetrics fm(subRule.font);
+ const QRect r = fm.boundingRect(QRect(), Qt::TextSingleLine | Qt::TextShowMnemonic, mi->text);
+ sz = sz.expandedTo(r.size());
+ }
return subRule.boxSize(subRule.adjustSize(sz));
}
}
@@ -5475,8 +5491,12 @@ QRect QStyleSheetStyle::subControlRect(ComplexControl cc, const QStyleOptionComp
: Qt::Alignment(Qt::AlignRight);
downAlign = resolveAlignment(opt->direction, downAlign);
- int upSize = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w).width();
- int downSize = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w).width();
+ const bool hasButtons = (spin->buttonSymbols != QAbstractSpinBox::NoButtons);
+ const int upSize = hasButtons
+ ? subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w).width() : 0;
+ const int downSize = hasButtons
+ ? subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w).width() : 0;
+
int widestL = qMax((upAlign & Qt::AlignLeft) ? upSize : 0,
(downAlign & Qt::AlignLeft) ? downSize : 0);
int widestR = qMax((upAlign & Qt::AlignRight) ? upSize : 0,
@@ -5768,11 +5788,10 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c
case SE_PushButtonContents:
case SE_PushButtonFocusRect:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
- QStyleOptionButton btnOpt(*btn);
if (rule.hasBox() || !rule.hasNativeBorder())
return visualRect(opt->direction, opt->rect, rule.contentsRect(opt->rect));
- return rule.baseStyleCanDraw() ? baseStyle()->subElementRect(se, &btnOpt, w)
- : QWindowsStyle::subElementRect(se, &btnOpt, w);
+ return rule.baseStyleCanDraw() ? baseStyle()->subElementRect(se, btn, w)
+ : QWindowsStyle::subElementRect(se, btn, w);
}
break;
@@ -5827,7 +5846,7 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c
return ParentStyle::subElementRect(se, opt, w);
#if QT_CONFIG(itemviews)
- case SE_ViewItemCheckIndicator:
+ case SE_ItemViewItemCheckIndicator:
if (!qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
return subElementRect(SE_CheckBoxIndicator, opt, w);
}
diff --git a/src/widgets/styles/qstylesheetstyle_p.h b/src/widgets/styles/qstylesheetstyle_p.h
index d4edb83525..c5266558af 100644
--- a/src/widgets/styles/qstylesheetstyle_p.h
+++ b/src/widgets/styles/qstylesheetstyle_p.h
@@ -82,40 +82,40 @@ public:
~QStyleSheetStyle();
void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p,
- const QWidget *w = 0) const override;
+ const QWidget *w = nullptr) const override;
void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p,
- const QWidget *w = 0) const override;
+ const QWidget *w = nullptr) const override;
void drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const override;
void drawItemText(QPainter *painter, const QRect& rect, int alignment, const QPalette &pal,
bool enabled, const QString& text, QPalette::ColorRole textRole = QPalette::NoRole) const override;
void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p,
- const QWidget *w = 0) const override;
+ const QWidget *w = nullptr) const override;
QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
const QStyleOption *option) const override;
SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
- const QPoint &pt, const QWidget *w = 0) const override;
+ const QPoint &pt, const QWidget *w = nullptr) const override;
QRect itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pixmap) const override;
QRect itemTextRect(const QFontMetrics &metrics, const QRect &rect, int alignment, bool enabled,
const QString &text) const override;
- int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const override;
+ int pixelMetric(PixelMetric metric, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const override;
void polish(QWidget *widget) override;
void polish(QApplication *app) override;
void polish(QPalette &pal) override;
QSize sizeFromContents(ContentsType ct, const QStyleOption *opt,
- const QSize &contentsSize, const QWidget *widget = 0) const override;
+ const QSize &contentsSize, const QWidget *widget = nullptr) const override;
QPalette standardPalette() const override;
- QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *opt = 0,
- const QWidget *widget = 0) const override;
- QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option = 0,
- const QWidget *w = 0 ) const override;
+ QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *opt = nullptr,
+ const QWidget *widget = nullptr) const override;
+ QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option = nullptr,
+ const QWidget *w = nullptr ) const override;
int layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2,
- Qt::Orientation orientation, const QStyleOption *option = 0,
- const QWidget *widget = 0) const override;
- int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0,
- QStyleHintReturn *shret = 0) const override;
- QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const override;
+ Qt::Orientation orientation, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr) const override;
+ int styleHint(StyleHint sh, const QStyleOption *opt = nullptr, const QWidget *w = nullptr,
+ QStyleHintReturn *shret = nullptr) const override;
+ QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = nullptr) const override;
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc,
- const QWidget *w = 0) const override;
+ const QWidget *w = nullptr) const override;
// These functions are called from QApplication/QWidget. Be careful.
QStyle *baseStyle() const;
@@ -173,7 +173,7 @@ public:
static int numinstances;
private:
- Q_DISABLE_COPY(QStyleSheetStyle)
+ Q_DISABLE_COPY_MOVE(QStyleSheetStyle)
Q_DECLARE_PRIVATE(QStyleSheetStyle)
};
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 12ca5201c1..3c0478b84e 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -248,7 +248,7 @@ void QWindowsStyle::polish(QApplication *app)
d->activeGradientCaptionColor = app->palette().highlight() .color();
d->inactiveCaptionColor = app->palette().dark().color();
d->inactiveGradientCaptionColor = app->palette().dark().color();
- d->inactiveCaptionText = app->palette().background().color();
+ d->inactiveCaptionText = app->palette().window().color();
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) //fetch native title bar colors
if(app->desktopSettingsAware()){
@@ -380,23 +380,12 @@ int QWindowsStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm)
return QWindowsStylePrivate::InvalidMetric;
}
-static QWindow *windowOf(const QWidget *w)
+static QScreen *screenOf(const QWidget *w)
{
- QWindow *result = nullptr;
if (w) {
- result = w->windowHandle();
- if (!result) {
- if (const QWidget *np = w->nativeParentWidget())
- result = np->windowHandle();
- }
+ if (auto screen = qt_widget_private(const_cast<QWidget *>(w))->associatedScreen())
+ return screen;
}
- return result;
-}
-
-static QScreen *screenOf(const QWidget *w)
-{
- if (const QWindow *window = windowOf(w))
- return window->screen();
return QGuiApplication::primaryScreen();
}
@@ -554,7 +543,7 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid
case SH_MenuBar_MouseTracking:
case SH_Menu_MouseTracking:
case SH_ComboBox_ListMouseTracking:
- case SH_ScrollBar_StopMouseOverSlider:
+ case SH_Slider_StopMouseOverSlider:
case SH_MainWindow_SpaceBelowMenuBar:
ret = 1;
@@ -802,8 +791,10 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
QPen oldPen = p->pen();
p->setPen(QPen(opt->palette.shadow().color(), 0));
QRectF rect = opt->rect;
- rect.adjust(QStyleHelper::dpiScaled(0.5), QStyleHelper::dpiScaled(0.5),
- QStyleHelper::dpiScaled(-1.5), QStyleHelper::dpiScaled(-1.5));
+ const qreal topLevelAdjustment = QStyleHelper::dpiScaled(0.5);
+ const qreal bottomRightAdjustment = QStyleHelper::dpiScaled(-1.5);
+ rect.adjust(topLevelAdjustment, topLevelAdjustment,
+ bottomRightAdjustment, bottomRightAdjustment);
p->drawRect(rect);
p->setPen(oldPen);
break;
@@ -817,7 +808,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
else if (opt->state & State_Enabled)
fill = opt->palette.base();
else
- fill = opt->palette.background();
+ fill = opt->palette.window();
p->save();
doRestore = true;
qDrawWinPanel(p, opt->rect, opt->palette, true, &fill);
@@ -827,13 +818,13 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
p->setPen(opt->palette.text().color());
}
Q_FALLTHROUGH();
- case PE_IndicatorViewItemCheck:
+ case PE_IndicatorItemViewItemCheck:
if (!doRestore) {
p->save();
doRestore = true;
}
#if QT_CONFIG(itemviews)
- if (pe == PE_IndicatorViewItemCheck) {
+ if (pe == PE_IndicatorItemViewItemCheck) {
const QStyleOptionViewItem *itemViewOpt = qstyleoption_cast<const QStyleOptionViewItem *>(opt);
p->setPen(itemViewOpt
&& itemViewOpt->showDecorationSelected
@@ -951,14 +942,14 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
if (frame->lineWidth == 2 || pe == PE_Frame) {
QPalette popupPal = frame->palette;
if (pe == PE_FrameMenu) {
- popupPal.setColor(QPalette::Light, frame->palette.background().color());
+ popupPal.setColor(QPalette::Light, frame->palette.window().color());
popupPal.setColor(QPalette::Midlight, frame->palette.light().color());
}
if (pe == PE_Frame && (frame->state & State_Raised))
qDrawWinButton(p, frame->rect, popupPal, frame->state & State_Sunken);
else if (pe == PE_Frame && (frame->state & State_Sunken))
{
- popupPal.setColor(QPalette::Midlight, frame->palette.background().color());
+ popupPal.setColor(QPalette::Midlight, frame->palette.window().color());
qDrawWinPanel(p, frame->rect, popupPal, frame->state & State_Sunken);
}
else
@@ -968,7 +959,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
}
} else {
QPalette popupPal = opt->palette;
- popupPal.setColor(QPalette::Light, opt->palette.background().color());
+ popupPal.setColor(QPalette::Light, opt->palette.window().color());
popupPal.setColor(QPalette::Midlight, opt->palette.light().color());
qDrawWinPanel(p, opt->rect, popupPal, opt->state & State_Sunken);
}
@@ -996,7 +987,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
break; }
case PE_FrameWindow: {
QPalette popupPal = opt->palette;
- popupPal.setColor(QPalette::Light, opt->palette.background().color());
+ popupPal.setColor(QPalette::Light, opt->palette.window().color());
popupPal.setColor(QPalette::Midlight, opt->palette.light().color());
qDrawWinPanel(p, opt->rect, popupPal, opt->state & State_Sunken);
break; }
@@ -1315,12 +1306,12 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
x2 -= onlyOne || lastTab ? borderThinkness : 0;
}
- p->fillRect(QRect(x1 + 1, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 2), tab->palette.background());
+ p->fillRect(QRect(x1 + 1, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 2), tab->palette.window());
// Delete border
if (selected) {
- p->fillRect(QRect(x1,y2-1,x2-x1,1), tab->palette.background());
- p->fillRect(QRect(x1,y2,x2-x1,1), tab->palette.background());
+ p->fillRect(QRect(x1,y2-1,x2-x1,1), tab->palette.window());
+ p->fillRect(QRect(x1,y2,x2-x1,1), tab->palette.window());
}
// Left
if (firstTab || selected || onlyOne || !previousSelected) {
@@ -1351,12 +1342,12 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
x2 -= lastTab ? borderThinkness : 0;
}
- p->fillRect(QRect(x1 + 1, y1 + 2, (x2 - x1) - 1, (y2 - y1) - 1), tab->palette.background());
+ p->fillRect(QRect(x1 + 1, y1 + 2, (x2 - x1) - 1, (y2 - y1) - 1), tab->palette.window());
// Delete border
if (selected) {
- p->fillRect(QRect(x1, y1 + 1, (x2 - 1)-x1, 1), tab->palette.background());
- p->fillRect(QRect(x1, y1, (x2 - 1)-x1, 1), tab->palette.background());
+ p->fillRect(QRect(x1, y1 + 1, (x2 - 1)-x1, 1), tab->palette.window());
+ p->fillRect(QRect(x1, y1, (x2 - 1)-x1, 1), tab->palette.window());
}
// Left
if (firstTab || selected || onlyOne || !previousSelected) {
@@ -1389,12 +1380,12 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
y2 -= lastTab ? borderThinkness : 0;
}
- p->fillRect(QRect(x1 + 1, y1 + 1, (x2 - x1) - 2, (y2 - y1) - 1), tab->palette.background());
+ p->fillRect(QRect(x1 + 1, y1 + 1, (x2 - x1) - 2, (y2 - y1) - 1), tab->palette.window());
// Delete border
if (selected) {
- p->fillRect(QRect(x2 - 1, y1, 1, y2-y1), tab->palette.background());
- p->fillRect(QRect(x2, y1, 1, y2-y1), tab->palette.background());
+ p->fillRect(QRect(x2 - 1, y1, 1, y2-y1), tab->palette.window());
+ p->fillRect(QRect(x2, y1, 1, y2-y1), tab->palette.window());
}
// Top
if (firstTab || selected || onlyOne || !previousSelected) {
@@ -1427,12 +1418,12 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
y2 -= lastTab ? borderThinkness : 0;
}
- p->fillRect(QRect(x1 + 2, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 1), tab->palette.background());
+ p->fillRect(QRect(x1 + 2, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 1), tab->palette.window());
// Delete border
if (selected) {
- p->fillRect(QRect(x1 + 1, y1, 1, (y2 - 1)-y1),tab->palette.background());
- p->fillRect(QRect(x1, y1, 1, (y2-1)-y1), tab->palette.background());
+ p->fillRect(QRect(x1 + 1, y1, 1, (y2 - 1)-y1),tab->palette.window());
+ p->fillRect(QRect(x1, y1, 1, (y2-1)-y1), tab->palette.window());
}
// Top
if (firstTab || selected || onlyOne || !previousSelected) {
@@ -1526,7 +1517,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
br = QBrush(paletteBrush.textureImage());
} else
br = QBrush(opt->palette.light().color(), Qt::Dense4Pattern);
- p->setBackground(opt->palette.background().color());
+ p->setBackground(opt->palette.window().color());
p->setBrush(br);
}
p->drawRect(opt->rect);
@@ -1693,7 +1684,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
}
QPalette pal2 = pb->palette;
// Correct the highlight color if it is the same as the background
- if (pal2.highlight() == pal2.background())
+ if (pal2.highlight() == pal2.window())
pal2.setColor(QPalette::Highlight, pb->palette.color(QPalette::Active,
QPalette::Highlight));
bool reverse = ((!vertical && (pb->direction == Qt::RightToLeft)) || vertical);
@@ -1825,7 +1816,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
titleRect.height(), titleRect.width());
}
proxy()->drawItemText(p, titleRect,
- Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, palette,
+ Qt::AlignLeft | Qt::AlignVCenter, palette,
dwOpt->state & State_Enabled, dwOpt->title,
floating ? (active ? QPalette::BrightText : QPalette::Window) : QPalette::WindowText);
p->setFont(oldFont);
@@ -1843,7 +1834,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->setBackground(cb->palette.highlight());
} else {
p->setPen(cb->palette.text().color());
- p->setBackground(cb->palette.background());
+ p->setBackground(cb->palette.window());
}
}
QCommonStyle::drawControl(ce, opt, p, widget);
@@ -2185,7 +2176,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
} else {
p->setPen(cmb->palette.text().color());
- p->setBackground(cmb->palette.background());
+ p->setBackground(cmb->palette.window());
}
if (cmb->state & State_HasFocus && !cmb->editable) {
diff --git a/src/widgets/styles/qwindowsstyle_p.h b/src/widgets/styles/qwindowsstyle_p.h
index 7993b9f1c6..b5f0bd68a1 100644
--- a/src/widgets/styles/qwindowsstyle_p.h
+++ b/src/widgets/styles/qwindowsstyle_p.h
@@ -77,32 +77,32 @@ public:
void polish(QPalette &) override;
void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p,
- const QWidget *w = 0) const override;
+ const QWidget *w = nullptr) const override;
void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p,
- const QWidget *w = 0) const override;
- QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const override;
+ const QWidget *w = nullptr) const override;
+ QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = nullptr) const override;
void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p,
- const QWidget *w = 0) const override;
+ const QWidget *w = nullptr) const override;
QSize sizeFromContents(ContentsType ct, const QStyleOption *opt,
- const QSize &contentsSize, const QWidget *widget = 0) const override;
+ const QSize &contentsSize, const QWidget *widget = nullptr) const override;
- int pixelMetric(PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0) const override;
+ int pixelMetric(PixelMetric pm, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const override;
- int styleHint(StyleHint hint, const QStyleOption *opt = 0, const QWidget *widget = 0,
- QStyleHintReturn *returnData = 0) const override;
+ int styleHint(StyleHint hint, const QStyleOption *opt = nullptr, const QWidget *widget = nullptr,
+ QStyleHintReturn *returnData = nullptr) const override;
QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
- const QWidget *widget = 0) const override;
+ const QWidget *widget = nullptr) const override;
- QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = 0,
- const QWidget *widget = 0) const override;
+ QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr) const override;
protected:
bool eventFilter(QObject *o, QEvent *e) override;
QWindowsStyle(QWindowsStylePrivate &dd);
private:
- Q_DISABLE_COPY(QWindowsStyle)
+ Q_DISABLE_COPY_MOVE(QWindowsStyle)
Q_DECLARE_PRIVATE(QWindowsStyle)
};
diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h
index 67fa6a2f86..e6ea809f11 100644
--- a/src/widgets/styles/qwindowsstyle_p_p.h
+++ b/src/widgets/styles/qwindowsstyle_p_p.h
@@ -69,9 +69,9 @@ public:
enum { InvalidMetric = -23576 };
QWindowsStylePrivate();
- static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0);
+ static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = nullptr, const QWidget *widget = nullptr);
static int fixedPixelMetric(QStyle::PixelMetric pm);
- static qreal devicePixelRatio(const QWidget *widget = 0)
+ static qreal devicePixelRatio(const QWidget *widget = nullptr)
{ return widget ? widget->devicePixelRatioF() : QWindowsStylePrivate::appDevicePixelRatio(); }
static qreal nativeMetricScaleFactor(const QWidget *widget = nullptr);
diff --git a/src/widgets/util/qcompleter_p.h b/src/widgets/util/qcompleter_p.h
index 765363744b..a52e63a6e2 100644
--- a/src/widgets/util/qcompleter_p.h
+++ b/src/widgets/util/qcompleter_p.h
@@ -75,7 +75,7 @@ class QCompleterPrivate : public QObjectPrivate
public:
QCompleterPrivate();
~QCompleterPrivate() { delete popup; }
- void init(QAbstractItemModel *model = 0);
+ void init(QAbstractItemModel *model = nullptr);
QPointer<QWidget> widget;
QCompletionModel *proxy;
@@ -194,6 +194,7 @@ private:
const QIndexMapper& iv, QMatchData* m);
};
+// ### Qt6: QStyledItemDelegate
class QCompleterItemDelegate : public QItemDelegate
{
public:
diff --git a/src/widgets/util/qflickgesture.cpp b/src/widgets/util/qflickgesture.cpp
index b59fe0d504..a8b2a00a80 100644
--- a/src/widgets/util/qflickgesture.cpp
+++ b/src/widgets/util/qflickgesture.cpp
@@ -130,8 +130,6 @@ private:
, mouseEventSource(Qt::MouseEventNotSynthesized)
{ }
- static PressDelayHandler *inst;
-
public:
enum {
UngrabMouseBefore = 1,
diff --git a/src/widgets/util/qflickgesture_p.h b/src/widgets/util/qflickgesture_p.h
index 74a0f2a0f3..0b47516047 100644
--- a/src/widgets/util/qflickgesture_p.h
+++ b/src/widgets/util/qflickgesture_p.h
@@ -71,14 +71,12 @@ class Q_WIDGETS_EXPORT QFlickGesture : public QGesture
Q_DECLARE_PRIVATE(QFlickGesture)
public:
- QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject *parent = 0);
+ QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject *parent = nullptr);
~QFlickGesture();
friend class QFlickGestureRecognizer;
};
-class PressDelayHandler;
-
class QFlickGesturePrivate : public QGesturePrivate
{
Q_DECLARE_PUBLIC(QFlickGesture)
@@ -89,7 +87,6 @@ public:
QScroller *receiverScroller;
Qt::MouseButton button; // NoButton == Touch
bool macIgnoreWheel;
- static PressDelayHandler *pressDelayHandler;
};
class QFlickGestureRecognizer : public QGestureRecognizer
diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp
index d15f5e5955..a38a50d3df 100644
--- a/src/widgets/util/qsystemtrayicon.cpp
+++ b/src/widgets/util/qsystemtrayicon.cpp
@@ -574,7 +574,7 @@ QBalloonTip::QBalloonTip(const QIcon &icon, const QString &title,
layout->addWidget(msgLabel, 1, 0, 1, 3);
#endif
layout->setSizeConstraint(QLayout::SetFixedSize);
- layout->setMargin(3);
+ layout->setContentsMargins(3, 3, 3, 3);
setLayout(layout);
QPalette pal = palette();
diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp
index e928b9fe37..8788c42252 100644
--- a/src/widgets/util/qundostack.cpp
+++ b/src/widgets/util/qundostack.cpp
@@ -102,9 +102,9 @@ QT_BEGIN_NAMESPACE
/*!
Constructs a QUndoCommand object with the given \a parent and \a text.
- If \a parent is not 0, this command is appended to parent's child list.
- The parent command then owns this command and will delete it in its
- destructor.
+ If \a parent is not \nullptr, this command is appended to parent's
+ child list. The parent command then owns this command and will delete
+ it in its destructor.
\sa ~QUndoCommand()
*/
@@ -118,9 +118,9 @@ QUndoCommand::QUndoCommand(const QString &text, QUndoCommand *parent)
/*!
Constructs a QUndoCommand object with parent \a parent.
- If \a parent is not 0, this command is appended to parent's child list.
- The parent command then owns this command and will delete it in its
- destructor.
+ If \a parent is not \nullptr, this command is appended to parent's
+ child list. The parent command then owns this command and will delete
+ it in its destructor.
\sa ~QUndoCommand()
*/
diff --git a/src/widgets/util/qundostack_p.h b/src/widgets/util/qundostack_p.h
index 04bc381114..05c9e0d27e 100644
--- a/src/widgets/util/qundostack_p.h
+++ b/src/widgets/util/qundostack_p.h
@@ -80,7 +80,7 @@ class QUndoStackPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QUndoStack)
public:
- QUndoStackPrivate() : index(0), clean_index(0), group(0), undo_limit(0) {}
+ QUndoStackPrivate() : index(0), clean_index(0), group(nullptr), undo_limit(0) {}
QList<QUndoCommand*> command_list;
QList<QUndoCommand*> macro_stack;
@@ -98,7 +98,7 @@ class QUndoAction : public QAction
{
Q_OBJECT
public:
- explicit QUndoAction(const QString &prefix, QObject *parent = 0);
+ explicit QUndoAction(const QString &prefix, QObject *parent = nullptr);
void setTextFormat(const QString &textFormat, const QString &defaultText);
public Q_SLOTS:
void setPrefixedText(const QString &text);
diff --git a/src/widgets/util/qundoview.cpp b/src/widgets/util/qundoview.cpp
index c862cbcea5..f59d87fb9d 100644
--- a/src/widgets/util/qundoview.cpp
+++ b/src/widgets/util/qundoview.cpp
@@ -361,7 +361,7 @@ QUndoStack *QUndoView::stack() const
Sets the stack displayed by this view to \a stack. If \a stack is 0, the view
will be empty.
- If the view was previously looking at a QUndoGroup, the group is set to 0.
+ If the view was previously looking at a QUndoGroup, the group is set to \nullptr.
\sa stack(), setGroup()
*/
diff --git a/src/widgets/widgets.pro b/src/widgets/widgets.pro
index e556cb8b10..6f807e1696 100644
--- a/src/widgets/widgets.pro
+++ b/src/widgets/widgets.pro
@@ -32,8 +32,6 @@ qtConfig(graphicseffect) {
QMAKE_LIBS += $$QMAKE_LIBS_GUI
-contains(DEFINES,QT_EVAL):include($$QT_SOURCE_TREE/src/corelib/eval.pri)
-
QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtWidgets.dynlist
# Code coverage with TestCocoon
diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp
index 598d173144..5ea8330db2 100644
--- a/src/widgets/widgets/qabstractscrollarea.cpp
+++ b/src/widgets/widgets/qabstractscrollarea.cpp
@@ -185,7 +185,7 @@ QAbstractScrollAreaScrollBarContainer::QAbstractScrollAreaScrollBarContainer(Qt:
orientation(orientation)
{
setLayout(layout);
- layout->setMargin(0);
+ layout->setContentsMargins(QMargins());
layout->setSpacing(0);
layout->addWidget(scrollBar);
layout->setSizeConstraint(QLayout::SetMaximumSize);
@@ -820,7 +820,7 @@ QWidget *QAbstractScrollArea::cornerWidget() const
All widgets set here will be deleted by the scroll area when it is
destroyed unless you separately reparent the widget after setting
- some other corner widget (or 0).
+ some other corner widget (or \nullptr).
Any \e newly set widget should have no current parent.
@@ -1604,8 +1604,10 @@ QSize QAbstractScrollArea::sizeHint() const
if (!d->sizeHint.isValid() || d->sizeAdjustPolicy == QAbstractScrollArea::AdjustToContents) {
const int f = 2 * d->frameWidth;
const QSize frame( f, f );
- const QSize scrollbars(d->vbarpolicy == Qt::ScrollBarAlwaysOn ? d->vbar->sizeHint().width() : 0,
- d->hbarpolicy == Qt::ScrollBarAlwaysOn ? d->hbar->sizeHint().height() : 0);
+ const bool vbarHidden = d->vbar->isHidden() || d->vbarpolicy == Qt::ScrollBarAlwaysOff;
+ const bool hbarHidden = d->hbar->isHidden() || d->hbarpolicy == Qt::ScrollBarAlwaysOff;
+ const QSize scrollbars(vbarHidden ? 0 : d->vbar->sizeHint().width(),
+ hbarHidden ? 0 : d->hbar->sizeHint().height());
d->sizeHint = frame + scrollbars + viewportSizeHint();
}
return d->sizeHint;
diff --git a/src/widgets/widgets/qabstractslider_p.h b/src/widgets/widgets/qabstractslider_p.h
index 419ce2ba07..1b8c76c7ec 100644
--- a/src/widgets/widgets/qabstractslider_p.h
+++ b/src/widgets/widgets/qabstractslider_p.h
@@ -134,7 +134,7 @@ public:
inline void setAdjustedSliderPosition(int position)
{
Q_Q(QAbstractSlider);
- if (q->style()->styleHint(QStyle::SH_Slider_StopMouseOverSlider, 0, q)) {
+ if (q->style()->styleHint(QStyle::SH_Slider_StopMouseOverSlider, nullptr, q)) {
if ((position > pressValue - 2 * pageStep) && (position < pressValue + 2 * pageStep)) {
repeatAction = QAbstractSlider::SliderNoAction;
q->setSliderPosition(pressValue);
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index 00ac5034e9..04276aa400 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -212,6 +212,7 @@ void QAbstractSpinBox::setButtonSymbols(ButtonSymbols buttonSymbols)
if (d->buttonSymbols != buttonSymbols) {
d->buttonSymbols = buttonSymbols;
d->updateEditFieldGeometry();
+ updateGeometry();
update();
}
}
@@ -252,7 +253,7 @@ QString QAbstractSpinBox::text() const
All values are displayed with the prefix and suffix (if set), \e
except for the special value, which only shows the special value
- text. This special text is passed in the QSpinBox::valueChanged()
+ text. This special text is passed in the QSpinBox::textChanged()
signal that passes a QString.
To turn off the special-value text display, call this function
@@ -342,18 +343,18 @@ void QAbstractSpinBox::setReadOnly(bool enable)
\since 4.3
If keyboard tracking is enabled (the default), the spinbox
- emits the valueChanged() signal while the new value is being
- entered from the keyboard.
+ emits the valueChanged() and textChanged() signals while the
+ new value is being entered from the keyboard.
E.g. when the user enters the value 600 by typing 6, 0, and 0,
the spinbox emits 3 signals with the values 6, 60, and 600
respectively.
If keyboard tracking is disabled, the spinbox doesn't emit the
- valueChanged() signal while typing. It emits the signal later,
- when the return key is pressed, when keyboard focus is lost, or
- when other spinbox functionality is used, e.g. pressing an arrow
- key.
+ valueChanged() and textChanged() signals while typing. It emits
+ the signals later, when the return key is pressed, when keyboard
+ focus is lost, or when other spinbox functionality is used, e.g.
+ pressing an arrow key.
*/
bool QAbstractSpinBox::keyboardTracking() const
@@ -688,7 +689,7 @@ QLineEdit *QAbstractSpinBox::lineEdit() const
\fn void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit)
Sets the line edit of the spinbox to be \a lineEdit instead of the
- current line edit widget. \a lineEdit can not be 0.
+ current line edit widget. \a lineEdit cannot be \nullptr.
QAbstractSpinBox takes ownership of the new lineEdit
@@ -1319,6 +1320,7 @@ void QAbstractSpinBox::contextMenuEvent(QContextMenuEvent *event)
d->reset();
QAction *selAll = new QAction(tr("&Select All"), menu);
+ selAll->setShortcut(QKeySequence::SelectAll);
menu->insertAction(d->edit->d_func()->selectAllAction,
selAll);
menu->removeAction(d->edit->d_func()->selectAllAction);
@@ -2030,8 +2032,8 @@ QVariant operator+(const QVariant &arg1, const QVariant &arg2)
#if QT_CONFIG(datetimeparser)
case QVariant::DateTime: {
QDateTime a2 = arg2.toDateTime();
- QDateTime a1 = arg1.toDateTime().addDays(QDATETIMEEDIT_DATETIME_MIN.daysTo(a2));
- a1.setTime(a1.time().addMSecs(QTime().msecsTo(a2.time())));
+ QDateTime a1 = arg1.toDateTime().addDays(QDATETIMEEDIT_DATE_MIN.daysTo(a2.date()));
+ a1.setTime(a1.time().addMSecs(a2.time().msecsSinceStartOfDay()));
ret = QVariant(a1);
break;
}
@@ -2093,11 +2095,11 @@ QVariant operator*(const QVariant &arg1, double multiplier)
#if QT_CONFIG(datetimeparser)
case QVariant::DateTime: {
double days = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDateTime().date()) * multiplier;
- int daysInt = (int)days;
+ const qint64 daysInt = qint64(days);
days -= daysInt;
- long msecs = (long)((QDATETIMEEDIT_TIME_MIN.msecsTo(arg1.toDateTime().time()) * multiplier)
- + (days * (24 * 3600 * 1000)));
- ret = QDateTime(QDate().addDays(int(days)), QTime().addMSecs(msecs));
+ qint64 msecs = qint64(arg1.toDateTime().time().msecsSinceStartOfDay() * multiplier
+ + days * (24 * 3600 * 1000));
+ ret = QDATETIMEEDIT_DATE_MIN.addDays(daysInt).startOfDay().addMSecs(msecs);
break;
}
#endif // datetimeparser
@@ -2127,8 +2129,8 @@ double operator/(const QVariant &arg1, const QVariant &arg2)
case QVariant::DateTime:
a1 = QDATETIMEEDIT_DATE_MIN.daysTo(arg1.toDate());
a2 = QDATETIMEEDIT_DATE_MIN.daysTo(arg2.toDate());
- a1 += (double)QDATETIMEEDIT_TIME_MIN.msecsTo(arg1.toDateTime().time()) / (long)(3600 * 24 * 1000);
- a2 += (double)QDATETIMEEDIT_TIME_MIN.msecsTo(arg2.toDateTime().time()) / (long)(3600 * 24 * 1000);
+ a1 += arg1.toDateTime().time().msecsSinceStartOfDay() / (36e5 * 24);
+ a2 += arg2.toDateTime().time().msecsSinceStartOfDay() / (36e5 * 24);
break;
#endif // datetimeparser
default: break;
diff --git a/src/widgets/widgets/qabstractspinbox_p.h b/src/widgets/widgets/qabstractspinbox_p.h
index fce88e43f4..ad169fde19 100644
--- a/src/widgets/widgets/qabstractspinbox_p.h
+++ b/src/widgets/widgets/qabstractspinbox_p.h
@@ -97,7 +97,7 @@ public:
void init();
void reset();
void updateState(bool up, bool fromKeyboard = false);
- QString stripped(const QString &text, int *pos = 0) const;
+ QString stripped(const QString &text, int *pos = nullptr) const;
bool specialValue() const;
virtual QVariant getZeroVariant() const;
virtual void setRange(const QVariant &min, const QVariant &max);
diff --git a/src/widgets/widgets/qbuttongroup.cpp b/src/widgets/widgets/qbuttongroup.cpp
index fa1ccd347f..669faa92c7 100644
--- a/src/widgets/widgets/qbuttongroup.cpp
+++ b/src/widgets/widgets/qbuttongroup.cpp
@@ -291,8 +291,8 @@ QList<QAbstractButton*> QButtonGroup::buttons() const
}
/*!
- Returns the button group's checked button, or 0 if no buttons are
- checked.
+ Returns the button group's checked button, or \nullptr if no
+ buttons are checked.
\sa buttonClicked()
*/
@@ -305,8 +305,8 @@ QAbstractButton *QButtonGroup::checkedButton() const
/*!
\since 4.1
- Returns the button with the specified \a id, or 0 if no such button
- exists.
+ Returns the button with the specified \a id, or \nullptr if no
+ such button exists.
*/
QAbstractButton *QButtonGroup::button(int id) const
{
diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp
index 2ff383d9c7..510b34cb18 100644
--- a/src/widgets/widgets/qcalendarwidget.cpp
+++ b/src/widgets/widgets/qcalendarwidget.cpp
@@ -827,9 +827,9 @@ class StaticDayOfWeekAssociativeArray {
bool contained[7];
T data[7];
- static Q_DECL_CONSTEXPR int day2idx(Qt::DayOfWeek day) Q_DECL_NOTHROW { return int(day) - 1; } // alt: day % 7
+ static Q_DECL_CONSTEXPR int day2idx(Qt::DayOfWeek day) noexcept { return int(day) - 1; } // alt: day % 7
public:
- Q_DECL_CONSTEXPR StaticDayOfWeekAssociativeArray() Q_DECL_NOEXCEPT_EXPR(noexcept(T()))
+ Q_DECL_CONSTEXPR StaticDayOfWeekAssociativeArray() noexcept(noexcept(T()))
#ifdef Q_COMPILER_CONSTEXPR
: contained{}, data{} // arrays require uniform initialization
#else
@@ -837,17 +837,17 @@ public:
#endif
{}
- Q_DECL_CONSTEXPR bool contains(Qt::DayOfWeek day) const Q_DECL_NOTHROW { return contained[day2idx(day)]; }
- Q_DECL_CONSTEXPR const T &value(Qt::DayOfWeek day) const Q_DECL_NOTHROW { return data[day2idx(day)]; }
+ Q_DECL_CONSTEXPR bool contains(Qt::DayOfWeek day) const noexcept { return contained[day2idx(day)]; }
+ Q_DECL_CONSTEXPR const T &value(Qt::DayOfWeek day) const noexcept { return data[day2idx(day)]; }
- Q_DECL_RELAXED_CONSTEXPR T &operator[](Qt::DayOfWeek day) Q_DECL_NOTHROW
+ Q_DECL_RELAXED_CONSTEXPR T &operator[](Qt::DayOfWeek day) noexcept
{
const int idx = day2idx(day);
contained[idx] = true;
return data[idx];
}
- Q_DECL_RELAXED_CONSTEXPR void insert(Qt::DayOfWeek day, T v) Q_DECL_NOTHROW
+ Q_DECL_RELAXED_CONSTEXPR void insert(Qt::DayOfWeek day, T v) noexcept
{
operator[](day).swap(v);
}
@@ -1178,9 +1178,9 @@ QVariant QCalendarModel::data(const QModelIndex &index, int role) const
}
QTextCharFormat fmt = formatForCell(row, column);
- if (role == Qt::BackgroundColorRole)
+ if (role == Qt::BackgroundRole)
return fmt.background().color();
- if (role == Qt::TextColorRole)
+ if (role == Qt::ForegroundRole)
return fmt.foreground().color();
if (role == Qt::FontRole)
return fmt.font();
@@ -1555,6 +1555,7 @@ void QCalendarView::mouseReleaseEvent(QMouseEvent *event)
}
}
+// ### Qt6: QStyledItemDelegate
class QCalendarDelegate : public QItemDelegate
{
Q_OBJECT
@@ -1777,7 +1778,7 @@ void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget)
spaceHolder = new QSpacerItem(0,0);
QHBoxLayout *headerLayout = new QHBoxLayout;
- headerLayout->setMargin(0);
+ headerLayout->setContentsMargins(QMargins());
headerLayout->setSpacing(0);
headerLayout->addWidget(prevMonth);
headerLayout->insertStretch(headerLayout->count());
@@ -2100,7 +2101,7 @@ QCalendarWidget::QCalendarWidget(QWidget *parent)
setBackgroundRole(QPalette::Window);
QVBoxLayout *layoutV = new QVBoxLayout(this);
- layoutV->setMargin(0);
+ layoutV->setContentsMargins(QMargins());
d->m_model = new QCalendarModel(this);
QTextCharFormat fmt;
fmt.setForeground(QBrush(Qt::red));
@@ -2147,7 +2148,7 @@ QCalendarWidget::QCalendarWidget(QWidget *parent)
connect(d->yearEdit, SIGNAL(editingFinished()),
this, SLOT(_q_yearEditingFinished()));
- layoutV->setMargin(0);
+ layoutV->setContentsMargins(QMargins());
layoutV->setSpacing(0);
layoutV->addWidget(d->navBarBackground);
layoutV->addWidget(d->m_view);
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index bdd2462c92..a052f2df79 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -167,7 +167,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt
break;
}
if (index.data(Qt::BackgroundRole).canConvert<QBrush>()) {
- menuOption.palette.setBrush(QPalette::All, QPalette::Background,
+ menuOption.palette.setBrush(QPalette::All, QPalette::Window,
qvariant_cast<QBrush>(index.data(Qt::BackgroundRole)));
}
menuOption.text = index.model()->data(index, Qt::DisplayRole).toString()
@@ -468,7 +468,7 @@ QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView
// we need a vertical layout
QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, this);
layout->setSpacing(0);
- layout->setMargin(0);
+ layout->setContentsMargins(QMargins());
// set item view
setItemView(itemView);
@@ -691,7 +691,7 @@ void QComboBoxPrivateContainer::changeEvent(QEvent *e)
setFrameStyle(combo->style()->styleHint(QStyle::SH_ComboBox_PopupFrameStyle, &opt, combo));
}
- QWidget::changeEvent(e);
+ QFrame::changeEvent(e);
}
@@ -891,14 +891,21 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
currentIndex was reset.
*/
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\fn void QComboBox::currentIndexChanged(const QString &text)
\since 4.1
+ \obsolete
+
+ Use currentTextChanged(const QString &) or currentIndexChanged(int)
+ instead.
+
This signal is sent whenever the currentIndex in the combobox
changes either through user interaction or programmatically. The
item's \a text is passed.
*/
+#endif
/*!
\fn void QComboBox::currentTextChanged(const QString &text)
@@ -1353,7 +1360,13 @@ void QComboBoxPrivate::emitActivated(const QModelIndex &index)
return;
QString text(itemText(index));
emit q->activated(index.row());
+ emit q->textActivated(text);
+#if QT_DEPRECATED_SINCE(5, 15)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
emit q->activated(text);
+QT_WARNING_POP
+#endif
}
void QComboBoxPrivate::_q_emitHighlighted(const QModelIndex &index)
@@ -1363,7 +1376,13 @@ void QComboBoxPrivate::_q_emitHighlighted(const QModelIndex &index)
return;
QString text(itemText(index));
emit q->highlighted(index.row());
+ emit q->textHighlighted(text);
+#if QT_DEPRECATED_SINCE(5, 15)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
emit q->highlighted(text);
+QT_WARNING_POP
+#endif
}
void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index)
@@ -1371,7 +1390,12 @@ void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index)
Q_Q(QComboBox);
const QString text = itemText(index);
emit q->currentIndexChanged(index.row());
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
emit q->currentIndexChanged(text);
+ QT_WARNING_POP
+#endif
// signal lineEdit.textChanged already connected to signal currentTextChanged, so don't emit double here
if (!lineEdit)
emit q->currentTextChanged(text);
@@ -1479,6 +1503,7 @@ int QComboBox::maxCount() const
}
#if QT_CONFIG(completer)
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\property QComboBox::autoCompletion
@@ -1496,7 +1521,7 @@ int QComboBox::maxCount() const
/*!
\obsolete
- Use setCompleter() instead.
+ Use completer() instead.
*/
bool QComboBox::autoCompletion() const
{
@@ -1572,6 +1597,7 @@ void QComboBox::setAutoCompletionCaseSensitivity(Qt::CaseSensitivity sensitivity
if (d->lineEdit && d->lineEdit->completer())
d->lineEdit->completer()->setCaseSensitivity(sensitivity);
}
+#endif // QT_DEPRECATED_SINCE(5, 13)
#endif // QT_CONFIG(completer)
@@ -1855,12 +1881,11 @@ void QComboBox::setLineEdit(QLineEdit *edit)
d->updateFocusPolicy();
d->lineEdit->setFocusProxy(this);
d->lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
+#if QT_DEPRECATED_SINCE(5, 13)
#if QT_CONFIG(completer)
setAutoCompletion(d->autoCompletion);
-#endif
#ifdef QT_KEYPAD_NAVIGATION
-#if QT_CONFIG(completer)
if (QApplication::keypadNavigationEnabled()) {
// Editable combo boxes will have a completer that is set to UnfilteredPopupCompletion.
// This means that when the user enters edit mode they are immediately presented with a
@@ -1873,6 +1898,7 @@ void QComboBox::setLineEdit(QLineEdit *edit)
}
#endif
#endif
+#endif
setAttribute(Qt::WA_InputMethodEnabled);
d->updateLayoutDirection();
@@ -1884,8 +1910,8 @@ void QComboBox::setLineEdit(QLineEdit *edit)
}
/*!
- Returns the line edit used to edit items in the combobox, or 0 if there
- is no line edit.
+ Returns the line edit used to edit items in the combobox, or
+ \nullptr if there is no line edit.
Only editable combo boxes have a line edit.
*/
@@ -1937,12 +1963,15 @@ const QValidator *QComboBox::validator() const
performs case insensitive inline completion is automatically created.
\note The completer is removed when the \l editable property becomes \c false.
+ Setting a completer on a QComboBox that is not editable will be ignored.
*/
void QComboBox::setCompleter(QCompleter *c)
{
Q_D(QComboBox);
- if (!d->lineEdit)
+ if (!d->lineEdit) {
+ qWarning("Setting a QCompleter on non-editable QComboBox is not allowed.");
return;
+ }
d->lineEdit->setCompleter(c);
if (c) {
connect(c, SIGNAL(activated(QModelIndex)), this, SLOT(_q_completerActivated(QModelIndex)));
@@ -2013,7 +2042,7 @@ QAbstractItemModel *QComboBox::model() const
}
/*!
- Sets the model to be \a model. \a model must not be 0.
+ Sets the model to be \a model. \a model must not be \nullptr.
If you want to clear the contents of a model, call clear().
\sa clear()
@@ -2809,19 +2838,15 @@ void QComboBox::showPopup()
bool startTimer = !container->isVisible();
container->raise();
container->create();
- QWindow *containerWindow = container->window()->windowHandle();
- if (containerWindow) {
- QWindow *win = window()->windowHandle();
- if (win) {
- QScreen *currentScreen = win->screen();
- if (currentScreen && !currentScreen->virtualSiblings().contains(containerWindow->screen())) {
- containerWindow->setScreen(currentScreen);
-
- // This seems to workaround an issue in xcb+multi GPU+multiscreen
- // environment where the window might not always show up when screen
- // is changed.
- container->hide();
- }
+ if (QWindow *containerWindow = qt_widget_private(container)->windowHandle(QWidgetPrivate::WindowHandleMode::TopLevel)) {
+ QScreen *currentScreen = d->associatedScreen();
+ if (currentScreen && !currentScreen->virtualSiblings().contains(containerWindow->screen())) {
+ containerWindow->setScreen(currentScreen);
+
+ // This seems to workaround an issue in xcb+multi GPU+multiscreen
+ // environment where the window might not always show up when screen
+ // is changed.
+ container->hide();
}
}
container->show();
diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h
index 671c883584..3b48b151a1 100644
--- a/src/widgets/widgets/qcombobox.h
+++ b/src/widgets/widgets/qcombobox.h
@@ -73,8 +73,10 @@ class Q_WIDGETS_EXPORT QComboBox : public QWidget
Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize)
#if QT_CONFIG(completer)
+#if QT_DEPRECATED_SINCE(5, 13)
Q_PROPERTY(bool autoCompletion READ autoCompletion WRITE setAutoCompletion DESIGNABLE false)
Q_PROPERTY(Qt::CaseSensitivity autoCompletionCaseSensitivity READ autoCompletionCaseSensitivity WRITE setAutoCompletionCaseSensitivity DESIGNABLE false)
+#endif
#endif // QT_CONFIG(completer)
Q_PROPERTY(bool duplicatesEnabled READ duplicatesEnabled WRITE setDuplicatesEnabled)
@@ -93,12 +95,17 @@ public:
int maxCount() const;
#if QT_CONFIG(completer)
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use completer() instead.")
bool autoCompletion() const;
+ QT_DEPRECATED_X("Use setCompleter() instead.")
void setAutoCompletion(bool enable);
-
+ QT_DEPRECATED_X("Use completer()->caseSensitivity() instead.")
Qt::CaseSensitivity autoCompletionCaseSensitivity() const;
+ QT_DEPRECATED_X("Use completer()->setCaseSensitivity() instead.")
void setAutoCompletionCaseSensitivity(Qt::CaseSensitivity sensitivity);
#endif
+#endif
bool duplicatesEnabled() const;
void setDuplicatesEnabled(bool enable);
@@ -216,12 +223,21 @@ public Q_SLOTS:
Q_SIGNALS:
void editTextChanged(const QString &);
void activated(int index);
- void activated(const QString &);
+ void textActivated(const QString &);
void highlighted(int index);
- void highlighted(const QString &);
+ void textHighlighted(const QString &);
void currentIndexChanged(int index);
- void currentIndexChanged(const QString &);
void currentTextChanged(const QString &);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_VERSION_X(5, 13, "Use currentTextChanged() instead")
+ void currentIndexChanged(const QString &);
+#endif
+#if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_VERSION_X(5, 15, "Use textActivated() instead")
+ void activated(const QString &);
+ QT_DEPRECATED_VERSION_X(5, 15, "Use textHighlighted() instead")
+ void highlighted(const QString &);
+#endif
protected:
void focusInEvent(QFocusEvent *e) override;
diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h
index 3f75a357e4..eadb21628f 100644
--- a/src/widgets/widgets/qcombobox_p.h
+++ b/src/widgets/widgets/qcombobox_p.h
@@ -86,7 +86,7 @@ class QComboBoxListView : public QListView
{
Q_OBJECT
public:
- QComboBoxListView(QComboBox *cmb = 0) : combo(cmb) {}
+ QComboBoxListView(QComboBox *cmb = nullptr) : combo(cmb) {}
protected:
void resizeEvent(QResizeEvent *event) override
@@ -277,7 +277,7 @@ protected:
const QStyleOptionViewItem &option,
const QModelIndex &index) const override {
QStyleOptionMenuItem opt = getStyleOption(option, index);
- painter->fillRect(option.rect, opt.palette.background());
+ painter->fillRect(option.rect, opt.palette.window());
mCombo->style()->drawControl(QStyle::CE_MenuItem, &opt, painter, mCombo);
}
QSize sizeHint(const QStyleOptionViewItem &option,
@@ -293,6 +293,7 @@ private:
QComboBox *mCombo;
};
+// ### Qt6: QStyledItemDelegate ?
// Note that this class is intentionally not using QStyledItemDelegate
// Vista does not use the new theme for combo boxes and there might
// be other side effects from using the new class
@@ -330,7 +331,7 @@ protected:
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const override {
if (isSeparator(index)) {
- int pm = mCombo->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, mCombo);
+ int pm = mCombo->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, mCombo);
return QSize(pm, pm);
}
return QItemDelegate::sizeHint(option, index);
diff --git a/src/widgets/widgets/qcommandlinkbutton.h b/src/widgets/widgets/qcommandlinkbutton.h
index 2d01d63df8..3d2dd5784d 100644
--- a/src/widgets/widgets/qcommandlinkbutton.h
+++ b/src/widgets/widgets/qcommandlinkbutton.h
@@ -66,10 +66,16 @@ public:
QString description() const;
void setDescription(const QString &description);
+ // QTBUG-68722
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
protected:
+#else
+public:
+#endif
QSize sizeHint() const override;
int heightForWidth(int) const override;
QSize minimumSizeHint() const override;
+protected:
bool event(QEvent *e) override;
void paintEvent(QPaintEvent *) override;
diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp
index acab768d75..642f35c638 100644
--- a/src/widgets/widgets/qdatetimeedit.cpp
+++ b/src/widgets/widgets/qdatetimeedit.cpp
@@ -153,7 +153,7 @@ QDateTimeEdit::QDateTimeEdit(QWidget *parent)
: QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
{
Q_D(QDateTimeEdit);
- d->init(QDateTime(QDATETIMEEDIT_DATE_INITIAL, QDATETIMEEDIT_TIME_MIN));
+ d->init(QDATETIMEEDIT_DATE_INITIAL.startOfDay());
}
/*!
@@ -165,8 +165,7 @@ QDateTimeEdit::QDateTimeEdit(const QDateTime &datetime, QWidget *parent)
: QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
{
Q_D(QDateTimeEdit);
- d->init(datetime.isValid() ? datetime : QDateTime(QDATETIMEEDIT_DATE_INITIAL,
- QDATETIMEEDIT_TIME_MIN));
+ d->init(datetime.isValid() ? datetime : QDATETIMEEDIT_DATE_INITIAL.startOfDay());
}
/*!
@@ -342,7 +341,7 @@ QDateTime QDateTimeEdit::minimumDateTime() const
void QDateTimeEdit::clearMinimumDateTime()
{
- setMinimumDateTime(QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN));
+ setMinimumDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN.startOfDay());
}
void QDateTimeEdit::setMinimumDateTime(const QDateTime &dt)
@@ -385,7 +384,7 @@ QDateTime QDateTimeEdit::maximumDateTime() const
void QDateTimeEdit::clearMaximumDateTime()
{
- setMaximumDateTime(QDATETIMEEDIT_DATETIME_MAX);
+ setMaximumDateTime(QDATETIMEEDIT_DATE_MAX.endOfDay());
}
void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt)
@@ -1660,8 +1659,8 @@ QDateTimeEditPrivate::QDateTimeEditPrivate()
first.pos = 0;
sections = 0;
calendarPopup = false;
- minimum = QDATETIMEEDIT_COMPAT_DATETIME_MIN;
- maximum = QDATETIMEEDIT_DATETIME_MAX;
+ minimum = QDATETIMEEDIT_COMPAT_DATE_MIN.startOfDay();
+ maximum = QDATETIMEEDIT_DATE_MAX.endOfDay();
arrowState = QStyle::State_None;
monthCalendar = 0;
readLocaleSettings();
@@ -1685,8 +1684,8 @@ void QDateTimeEditPrivate::updateTimeSpec()
const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask);
if (!dateShown) {
if (minimum.toTime() >= maximum.toTime()){
- minimum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MIN, spec);
- maximum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MAX, spec);
+ minimum = value.toDate().startOfDay(spec);
+ maximum = value.toDate().endOfDay(spec);
}
}
}
@@ -2384,7 +2383,7 @@ void QDateTimeEditPrivate::init(const QVariant &var)
Q_Q(QDateTimeEdit);
switch (var.type()) {
case QVariant::Date:
- value = QDateTime(var.toDate(), QDATETIMEEDIT_TIME_MIN);
+ value = var.toDate().startOfDay();
updateTimeSpec();
q->setDisplayFormat(defaultDateFormat);
if (sectionNodes.isEmpty()) // ### safeguard for broken locale
@@ -2601,7 +2600,7 @@ void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
QVBoxLayout *widgetLayout = qobject_cast<QVBoxLayout*>(layout());
if (!widgetLayout) {
widgetLayout = new QVBoxLayout(this);
- widgetLayout->setMargin(0);
+ widgetLayout->setContentsMargins(QMargins());
widgetLayout->setSpacing(0);
}
delete calendar.data();
diff --git a/src/widgets/widgets/qdatetimeedit_p.h b/src/widgets/widgets/qdatetimeedit_p.h
index 1ebc98dedf..c05e7d9b48 100644
--- a/src/widgets/widgets/qdatetimeedit_p.h
+++ b/src/widgets/widgets/qdatetimeedit_p.h
@@ -123,7 +123,7 @@ public:
static QDateTimeEdit::Sections convertSections(QDateTimeParser::Sections s);
static QDateTimeEdit::Section convertToPublic(QDateTimeParser::Section s);
- void initCalendarPopup(QCalendarWidget *cw = 0);
+ void initCalendarPopup(QCalendarWidget *cw = nullptr);
void positionCalendarPopup();
QDateTimeEdit::Sections sections;
@@ -145,7 +145,7 @@ class QCalendarPopup : public QWidget
{
Q_OBJECT
public:
- explicit QCalendarPopup(QWidget *parent = 0, QCalendarWidget *cw = 0);
+ explicit QCalendarPopup(QWidget *parent = nullptr, QCalendarWidget *cw = nullptr);
QDate selectedDate() { return verifyCalendarInstance()->selectedDate(); }
void setDate(const QDate &date);
void setDateRange(const QDate &min, const QDate &max);
diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp
index d93e71e32f..28f6cdc7bd 100644
--- a/src/widgets/widgets/qdialogbuttonbox.cpp
+++ b/src/widgets/widgets/qdialogbuttonbox.cpp
@@ -387,12 +387,25 @@ QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardBut
icon = QStyle::SP_DialogNoButton;
break;
case QDialogButtonBox::YesToAll:
+ icon = QStyle::SP_DialogYesToAllButton;
+ break;
case QDialogButtonBox::NoToAll:
+ icon = QStyle::SP_DialogNoToAllButton;
+ break;
case QDialogButtonBox::SaveAll:
+ icon = QStyle::SP_DialogSaveAllButton;
+ break;
case QDialogButtonBox::Abort:
+ icon = QStyle::SP_DialogAbortButton;
+ break;
case QDialogButtonBox::Retry:
+ icon = QStyle::SP_DialogRetryButton;
+ break;
case QDialogButtonBox::Ignore:
+ icon = QStyle::SP_DialogIgnoreButton;
+ break;
case QDialogButtonBox::RestoreDefaults:
+ icon = QStyle::SP_RestoreDefaultsButton;
break;
case QDialogButtonBox::NoButton:
return 0;
@@ -820,7 +833,7 @@ QDialogButtonBox::StandardButtons QDialogButtonBox::standardButtons() const
/*!
Returns the QPushButton corresponding to the standard button \a which,
- or 0 if the standard button doesn't exist in this button box.
+ or \nullptr if the standard button doesn't exist in this button box.
\sa standardButton(), standardButtons(), buttons()
*/
diff --git a/src/widgets/widgets/qdockarealayout_p.h b/src/widgets/widgets/qdockarealayout_p.h
index 49bd157179..ab9c0c476c 100644
--- a/src/widgets/widgets/qdockarealayout_p.h
+++ b/src/widgets/widgets/qdockarealayout_p.h
@@ -89,7 +89,7 @@ struct QDockAreaLayoutItem
{
enum ItemFlags { NoFlags = 0, GapItem = 1, KeepSize = 2 };
- explicit QDockAreaLayoutItem(QLayoutItem *_widgetItem = 0);
+ explicit QDockAreaLayoutItem(QLayoutItem *_widgetItem = nullptr);
explicit QDockAreaLayoutItem(QDockAreaLayoutInfo *_subinfo);
explicit QDockAreaLayoutItem(QPlaceHolderItem *_placeHolderItem);
QDockAreaLayoutItem(const QDockAreaLayoutItem &other);
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 6c871aae2c..b8b6c12bf3 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -55,6 +55,7 @@
#include <private/qwidgetresizehandler_p.h>
#include <private/qstylesheetstyle_p.h>
+#include <qpa/qplatformtheme.h>
#include "qdockwidget_p.h"
#include "qmainwindowlayout_p.h"
@@ -66,18 +67,21 @@ extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*); /
// qmainwindow.cpp
extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
-static inline QMainWindowLayout *qt_mainwindow_layout_from_dock(const QDockWidget *dock)
+static const QMainWindow *mainwindow_from_dock(const QDockWidget *dock)
{
- const QWidget *p = dock->parentWidget();
- while (p) {
- const QMainWindow *window = qobject_cast<const QMainWindow*>(p);
- if (window)
- return qt_mainwindow_layout(window);
- p = p->parentWidget();
+ for (const QWidget *p = dock->parentWidget(); p; p = p->parentWidget()) {
+ if (const QMainWindow *window = qobject_cast<const QMainWindow*>(p))
+ return window;
}
return nullptr;
}
+static inline QMainWindowLayout *qt_mainwindow_layout_from_dock(const QDockWidget *dock)
+{
+ auto mainWindow = mainwindow_from_dock(dock);
+ return mainWindow ? qt_mainwindow_layout(mainWindow) : nullptr;
+}
+
static inline bool hasFeature(const QDockWidgetPrivate *priv, QDockWidget::DockWidgetFeature feature)
{ return (priv->features & feature) == feature; }
@@ -838,8 +842,9 @@ void QDockWidgetPrivate::endDrag(bool abort)
q->releaseMouse();
if (state->dragging) {
- QMainWindowLayout *mwLayout = qt_mainwindow_layout_from_dock(q);
- Q_ASSERT(mwLayout != 0);
+ const QMainWindow *mainWindow = mainwindow_from_dock(q);
+ Q_ASSERT(mainWindow != nullptr);
+ QMainWindowLayout *mwLayout = qt_mainwindow_layout(mainWindow);
if (abort || !mwLayout->plug(state->widgetItem)) {
if (hasFeature(this, QDockWidget::DockWidgetFloatable)) {
@@ -860,8 +865,12 @@ void QDockWidgetPrivate::endDrag(bool abort)
} else {
setResizerActive(false);
}
- if (q->isFloating()) // Might not be floating when dragging a QDockWidgetGroupWindow
+ if (q->isFloating()) { // Might not be floating when dragging a QDockWidgetGroupWindow
undockedGeometry = q->geometry();
+#if QT_CONFIG(tabwidget)
+ tabPosition = mwLayout->tabPosition(mainWindow->dockWidgetArea(q));
+#endif
+ }
q->activateWindow();
} else {
// The tab was not plugged back in the QMainWindow but the QDockWidget cannot
@@ -922,7 +931,8 @@ bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event)
initDrag(event->pos(), false);
if (state)
- state->ctrlDrag = hasFeature(this, QDockWidget::DockWidgetFloatable) && event->modifiers() & Qt::ControlModifier;
+ state->ctrlDrag = (hasFeature(this, QDockWidget::DockWidgetFloatable) && event->modifiers() & Qt::ControlModifier) ||
+ (!hasFeature(this, QDockWidget::DockWidgetMovable) && q->isFloating());
return true;
}
@@ -1044,7 +1054,8 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event)
initDrag(event->pos(), true);
if (state == 0)
break;
- state->ctrlDrag = event->modifiers() & Qt::ControlModifier;
+ state->ctrlDrag = (event->modifiers() & Qt::ControlModifier) ||
+ (!hasFeature(this, QDockWidget::DockWidgetMovable) && q->isFloating());
startDrag();
break;
case QEvent::NonClientAreaMouseMove:
@@ -1171,6 +1182,8 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
QMainWindowLayout *mwlayout = qt_mainwindow_layout_from_dock(q);
if (mwlayout)
emit q->dockLocationChanged(mwlayout->dockWidgetArea(q));
+ } else {
+ emit q->dockLocationChanged(Qt::NoDockWidgetArea);
}
}
@@ -1522,10 +1535,10 @@ bool QDockWidget::event(QEvent *event)
d->toggleViewAction->setChecked(true);
QPoint parentTopLeft(0, 0);
if (isWindow()) {
- if (const QWindow *window = windowHandle())
- parentTopLeft = window->screen()->availableVirtualGeometry().topLeft();
- else
- parentTopLeft = QGuiApplication::primaryScreen()->availableVirtualGeometry().topLeft();
+ const QScreen *screen = d->associatedScreen();
+ parentTopLeft = screen
+ ? screen->availableVirtualGeometry().topLeft()
+ : QGuiApplication::primaryScreen()->availableVirtualGeometry().topLeft();
}
emit visibilityChanged(geometry().right() >= parentTopLeft.x() && geometry().bottom() >= parentTopLeft.y());
}
@@ -1729,8 +1742,8 @@ void QDockWidget::setTitleBarWidget(QWidget *widget)
/*!
\since 4.3
- Returns the custom title bar widget set on the QDockWidget, or 0 if no
- custom title bar has been set.
+ Returns the custom title bar widget set on the QDockWidget, or
+ \nullptr if no custom title bar has been set.
\sa setTitleBarWidget()
*/
diff --git a/src/widgets/widgets/qdockwidget_p.h b/src/widgets/widgets/qdockwidget_p.h
index 766e4ed161..bc6ac86c45 100644
--- a/src/widgets/widgets/qdockwidget_p.h
+++ b/src/widgets/widgets/qdockwidget_p.h
@@ -57,6 +57,10 @@
#include "QtWidgets/qboxlayout.h"
#include "QtWidgets/qdockwidget.h"
+#if QT_CONFIG(tabwidget)
+# include "QtWidgets/qtabwidget.h"
+#endif
+
QT_REQUIRE_CONFIG(dockwidget);
QT_BEGIN_NAMESPACE
@@ -81,33 +85,32 @@ class QDockWidgetPrivate : public QWidgetPrivate
};
public:
- inline QDockWidgetPrivate()
- : QWidgetPrivate(), state(0),
- features(QDockWidget::DockWidgetClosable
- | QDockWidget::DockWidgetMovable
- | QDockWidget::DockWidgetFloatable),
- allowedAreas(Qt::AllDockWidgetAreas), resizer(0)
- { }
-
void init();
void _q_toggleView(bool); // private slot
void _q_toggleTopLevel(); // private slot
void updateButtons();
- DragState *state;
- QDockWidget::DockWidgetFeatures features;
- Qt::DockWidgetAreas allowedAreas;
+#if QT_CONFIG(tabwidget)
+ QTabWidget::TabPosition tabPosition = QTabWidget::North;
+#endif
+
+ DragState *state = nullptr;
+
+ QDockWidget::DockWidgetFeatures features = QDockWidget::DockWidgetClosable
+ | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable;
+ Qt::DockWidgetAreas allowedAreas = Qt::AllDockWidgetAreas;
QFont font;
#ifndef QT_NO_ACTION
- QAction *toggleViewAction;
+ QAction *toggleViewAction = nullptr;
#endif
// QMainWindow *findMainWindow(QWidget *widget) const;
QRect undockedGeometry;
QString fixedWindowTitle;
+ QString dockedWindowTitle;
bool mousePressEvent(QMouseEvent *event);
bool mouseDoubleClickEvent(QMouseEvent *event);
@@ -128,14 +131,14 @@ public:
bool isAnimating() const;
private:
- QWidgetResizeHandler *resizer;
+ QWidgetResizeHandler *resizer = nullptr;
};
class Q_WIDGETS_EXPORT QDockWidgetLayout : public QLayout
{
Q_OBJECT
public:
- QDockWidgetLayout(QWidget *parent = 0);
+ QDockWidgetLayout(QWidget *parent = nullptr);
~QDockWidgetLayout();
void addItem(QLayoutItem *item) override;
QLayoutItem *itemAt(int index) const override;
@@ -193,15 +196,15 @@ inline QLayoutItem *QDockWidgetItem::dockWidgetChildItem() const
{
if (QDockWidgetLayout *layout = dockWidgetLayout())
return layout->itemForRole(QDockWidgetLayout::Content);
- return 0;
+ return nullptr;
}
inline QDockWidgetLayout *QDockWidgetItem::dockWidgetLayout() const
{
QWidget *w = const_cast<QDockWidgetItem*>(this)->widget();
- if (w != 0)
+ if (w != nullptr)
return qobject_cast<QDockWidgetLayout*>(w->layout());
- return 0;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qfontcombobox.cpp b/src/widgets/widgets/qfontcombobox.cpp
index 957a464b71..4a99b0f962 100644
--- a/src/widgets/widgets/qfontcombobox.cpp
+++ b/src/widgets/widgets/qfontcombobox.cpp
@@ -236,9 +236,10 @@ void QFontFamilyDelegate::paint(QPainter *painter,
if (QFontDatabase().isSmoothlyScalable(text)) {
icon = &truetype;
}
- QSize actualSize = icon->actualSize(r.size());
-
- icon->paint(painter, r, Qt::AlignLeft|Qt::AlignVCenter);
+ const QSize actualSize = icon->actualSize(r.size());
+ const QRect iconRect = QStyle::alignedRect(option.direction, option.displayAlignment,
+ actualSize, r);
+ icon->paint(painter, iconRect, Qt::AlignLeft|Qt::AlignVCenter);
if (option.direction == Qt::RightToLeft)
r.setRight(r.right() - actualSize.width() - 4);
else
@@ -247,6 +248,7 @@ void QFontFamilyDelegate::paint(QPainter *painter,
QFont old = painter->font();
painter->setFont(font);
+ const Qt::Alignment textAlign = QStyle::visualAlignment(option.direction, option.displayAlignment);
// If the ascent of the font is larger than the height of the rect,
// we will clip the text, so it's better to align the tight bounding rect in this case
// This is specifically for fonts where the ascent is very large compared to
@@ -254,9 +256,11 @@ void QFontFamilyDelegate::paint(QPainter *painter,
QFontMetricsF fontMetrics(font);
if (fontMetrics.ascent() > r.height()) {
QRectF tbr = fontMetrics.tightBoundingRect(text);
- painter->drawText(r.x(), r.y() + (r.height() + tbr.height()) / 2.0, text);
+ QRect textRect(r);
+ textRect.setHeight(textRect.height() + (r.height() - tbr.height()));
+ painter->drawText(textRect, Qt::AlignBottom|Qt::TextSingleLine|textAlign, text);
} else {
- painter->drawText(r, Qt::AlignVCenter|Qt::AlignLeading|Qt::TextSingleLine, text);
+ painter->drawText(r, Qt::AlignVCenter|Qt::TextSingleLine|textAlign, text);
}
if (writingSystem != QFontDatabase::Any)
@@ -270,7 +274,7 @@ void QFontFamilyDelegate::paint(QPainter *painter,
r.setRight(r.right() - w);
else
r.setLeft(r.left() + w);
- painter->drawText(r, Qt::AlignVCenter|Qt::AlignLeading|Qt::TextSingleLine, sample);
+ painter->drawText(r, Qt::AlignVCenter|Qt::TextSingleLine|textAlign, sample);
}
painter->setFont(old);
diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp
index 60f88df9af..a840bf4ee6 100644
--- a/src/widgets/widgets/qlabel.cpp
+++ b/src/widgets/widgets/qlabel.cpp
@@ -1098,7 +1098,7 @@ void QLabel::paintEvent(QPaintEvent *)
QImage scaledImage =
d->cachedimage->scaled(scaledSize,
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
- d->scaledpixmap = new QPixmap(QPixmap::fromImage(scaledImage));
+ d->scaledpixmap = new QPixmap(QPixmap::fromImage(std::move(scaledImage)));
d->scaledpixmap->setDevicePixelRatio(devicePixelRatioF());
}
pix = *d->scaledpixmap;
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index 86c7d35dbc..09b7687d8e 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -315,7 +315,7 @@ QString QLineEdit::text() const
void QLineEdit::setText(const QString& text)
{
Q_D(QLineEdit);
- d->control->setText(text);
+ d->setText(text);
}
/*!
@@ -586,7 +586,7 @@ void QLineEdit::setEchoMode(EchoMode mode)
#ifndef QT_NO_VALIDATOR
/*!
- Returns a pointer to the current input validator, or 0 if no
+ Returns a pointer to the current input validator, or \nullptr if no
validator has been set.
\sa setValidator()
@@ -1489,8 +1489,11 @@ bool QLineEdit::event(QEvent * e)
} else if (e->type() == QEvent::LeaveEditFocus) {
d->setCursorVisible(false);
d->control->setCursorBlinkEnabled(false);
- if (d->control->hasAcceptableInput() || d->control->fixup())
+ if (d->edited && (d->control->hasAcceptableInput()
+ || d->control->fixup())) {
emit editingFinished();
+ d->edited = false;
+ }
}
}
#endif
@@ -1897,7 +1900,6 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
/*!\reimp
*/
-
void QLineEdit::focusOutEvent(QFocusEvent *e)
{
Q_D(QLineEdit);
@@ -1920,8 +1922,10 @@ void QLineEdit::focusOutEvent(QFocusEvent *e)
#endif
if (reason != Qt::PopupFocusReason
|| !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) {
- if (hasAcceptableInput() || d->control->fixup())
+ if (d->edited && (hasAcceptableInput() || d->control->fixup())) {
emit editingFinished();
+ d->edited = false;
+ }
}
#ifdef QT_KEYPAD_NAVIGATION
d->control->setCancelText(QString());
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index 6dcb2dd693..7d580e50a5 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -127,6 +127,7 @@ void QLineEditPrivate::_q_handleWindowActivate()
void QLineEditPrivate::_q_textEdited(const QString &text)
{
Q_Q(QLineEdit);
+ edited = true;
emit q->textEdited(text);
#if QT_CONFIG(completer)
if (control->completer()
@@ -272,6 +273,12 @@ void QLineEditPrivate::setCursorVisible(bool visible)
q->update();
}
+void QLineEditPrivate::setText(const QString& text)
+{
+ edited = true;
+ control->setText(text);
+}
+
void QLineEditPrivate::updatePasswordEchoEditing(bool editing)
{
Q_Q(QLineEdit);
@@ -324,7 +331,7 @@ void QLineEditPrivate::drag()
data->setText(control->selectedText());
QDrag *drag = new QDrag(q);
drag->setMimeData(data);
- Qt::DropAction action = drag->start();
+ Qt::DropAction action = drag->exec(Qt::CopyAction);
if (action == Qt::MoveAction && !control->isReadOnly() && drag->target() != q)
control->removeSelection();
}
@@ -348,9 +355,7 @@ QLineEditPrivate *QLineEditIconButton::lineEditPrivate() const
void QLineEditIconButton::paintEvent(QPaintEvent *)
{
QPainter painter(this);
- QWindow *window = nullptr;
- if (const QWidget *nativeParent = nativeParentWidget())
- window = nativeParent->windowHandle();
+ QWindow *window = qt_widget_private(this)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest);
QIcon::Mode state = QIcon::Disabled;
if (isEnabled())
state = isDown() ? QIcon::Active : QIcon::Normal;
diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h
index 12a2f1ddfd..3f98aab901 100644
--- a/src/widgets/widgets/qlineedit_p.h
+++ b/src/widgets/widgets/qlineedit_p.h
@@ -85,7 +85,7 @@ class Q_AUTOTEST_EXPORT QLineEditIconButton : public QToolButton
Q_OBJECT
Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
public:
- explicit QLineEditIconButton(QWidget *parent = 0);
+ explicit QLineEditIconButton(QWidget *parent = nullptr);
qreal opacity() const { return m_opacity; }
void setOpacity(qreal value);
@@ -134,7 +134,7 @@ public:
};
struct SideWidgetEntry {
- explicit SideWidgetEntry(QWidget *w = 0, QAction *a = 0, int _flags = 0) : widget(w), action(a), flags(_flags) {}
+ explicit SideWidgetEntry(QWidget *w = nullptr, QAction *a = nullptr, int _flags = 0) : widget(w), action(a), flags(_flags) {}
QWidget *widget;
QAction *action;
@@ -151,7 +151,7 @@ public:
QLineEditPrivate()
: control(0), frame(1), contextMenuEnabled(1), cursorVisible(0),
- dragEnabled(0), clickCausedFocus(0), hscroll(0), vscroll(0),
+ dragEnabled(0), clickCausedFocus(0), edited(0), hscroll(0), vscroll(0),
alignment(Qt::AlignLeading | Qt::AlignVCenter),
leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0),
lastTextSize(0), mouseYThreshold(0)
@@ -176,6 +176,7 @@ public:
bool inSelection(int x) const;
QRect cursorRect() const;
void setCursorVisible(bool visible);
+ void setText(const QString& text);
void updatePasswordEchoEditing(bool);
@@ -202,6 +203,7 @@ public:
uint cursorVisible : 1;
uint dragEnabled : 1;
uint clickCausedFocus : 1;
+ uint edited : 1;
int hscroll;
int vscroll;
uint alignment;
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index 411b482c11..9c4c46f2d6 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -596,7 +596,7 @@ QStatusBar *QMainWindow::statusBar() const
/*!
Sets the status bar for the main window to \a statusbar.
- Setting the status bar to 0 will remove it from the main window.
+ Setting the status bar to \nullptr will remove it from the main window.
Note that QMainWindow takes ownership of the \a statusbar pointer
and deletes it at the appropriate time.
@@ -851,7 +851,11 @@ void QMainWindow::removeToolBar(QToolBar *toolbar)
\sa addToolBar(), addToolBarBreak(), Qt::ToolBarArea
*/
-Qt::ToolBarArea QMainWindow::toolBarArea(QToolBar *toolbar) const
+Qt::ToolBarArea QMainWindow::toolBarArea(
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+ const
+#endif
+ QToolBar *toolbar) const
{ return d_func()->layout->toolBarArea(toolbar); }
/*!
@@ -1460,8 +1464,8 @@ void QMainWindow::contextMenuEvent(QContextMenuEvent *event)
#if QT_CONFIG(menu)
/*!
Returns a popup menu containing checkable entries for the toolbars and
- dock widgets present in the main window. If there are no toolbars and
- dock widgets present, this function returns a null pointer.
+ dock widgets present in the main window. If there are no toolbars and
+ dock widgets present, this function returns \nullptr.
By default, this function is called by the main window when the user
activates a context menu, typically by right-clicking on a toolbar or a dock
diff --git a/src/widgets/widgets/qmainwindow.h b/src/widgets/widgets/qmainwindow.h
index 8f2a192446..85e3f87d77 100644
--- a/src/widgets/widgets/qmainwindow.h
+++ b/src/widgets/widgets/qmainwindow.h
@@ -158,7 +158,11 @@ public:
bool unifiedTitleAndToolBarOnMac() const;
- Qt::ToolBarArea toolBarArea(QToolBar *toolbar) const;
+ Qt::ToolBarArea toolBarArea(
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+ const
+#endif
+ QToolBar *toolbar) const;
bool toolBarBreak(QToolBar *toolbar) const;
#endif
#if QT_CONFIG(dockwidget)
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index 053bfbf024..b8f997b782 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -1388,7 +1388,7 @@ void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar)
invalidate();
}
-Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const
+Qt::ToolBarArea QMainWindowLayout::toolBarArea(const QToolBar *toolbar) const
{
QInternal::DockPosition pos = layoutState.toolBarAreaLayout.findToolBar(toolbar);
switch (pos) {
@@ -2525,6 +2525,30 @@ void QMainWindowLayout::updateGapIndicator()
#endif // QT_CONFIG(rubberband)
}
+static QTabBar::Shape tabwidgetPositionToTabBarShape(QWidget *w)
+{
+ QTabBar::Shape result = QTabBar::RoundedSouth;
+#if QT_CONFIG(tabwidget)
+ if (qobject_cast<QDockWidget *>(w)) {
+ switch (static_cast<QDockWidgetPrivate *>(qt_widget_private(w))->tabPosition) {
+ case QTabWidget::North:
+ result = QTabBar::RoundedNorth;
+ break;
+ case QTabWidget::South:
+ result = QTabBar::RoundedSouth;
+ break;
+ case QTabWidget::West:
+ result = QTabBar::RoundedWest;
+ break;
+ case QTabWidget::East:
+ result = QTabBar::RoundedEast;
+ break;
+ }
+ }
+#endif // tabwidget
+ return result;
+}
+
void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
{
if (!parentWidget()->isVisible() || parentWidget()->isMinimized()
@@ -2560,9 +2584,9 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
}
}
for (QWidget *w : candidates) {
- QWindow *handle1 = widget->windowHandle();
- QWindow *handle2 = w->windowHandle();
- if (handle1 && handle2 && handle1->screen() != handle2->screen())
+ const QScreen *screen1 = qt_widget_private(widget)->associatedScreen();
+ const QScreen *screen2 = qt_widget_private(w)->associatedScreen();
+ if (screen1 && screen2 && screen1 != screen2)
continue;
if (!w->geometry().contains(mousePos))
continue;
@@ -2573,8 +2597,9 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow(); // FIXME
floatingTabs->setGeometry(dropTo->geometry());
QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
+ const QTabBar::Shape shape = tabwidgetPositionToTabBarShape(dropTo);
*info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, QInternal::LeftDock,
- Qt::Horizontal, QTabBar::RoundedSouth,
+ Qt::Horizontal, shape,
static_cast<QMainWindow *>(parentWidget()));
info->tabbed = true;
QLayout *parentLayout = dropTo->parentWidget()->layout();
diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h
index 72cbec2350..7cdb8ead2f 100644
--- a/src/widgets/widgets/qmainwindowlayout_p.h
+++ b/src/widgets/widgets/qmainwindowlayout_p.h
@@ -122,7 +122,7 @@ template <typename Layout>
QCursor QMainWindowLayoutSeparatorHelper<Layout>::separatorCursor(const QList<int> &path)
{
const QDockAreaLayoutInfo *info = layout()->dockAreaLayoutInfo()->info(path);
- Q_ASSERT(info != 0);
+ Q_ASSERT(info != nullptr);
if (path.size() == 1) { // is this the "top-level" separator which separates a dock area
// from the central widget?
switch (path.first()) {
@@ -334,7 +334,7 @@ class QDockWidgetGroupWindow : public QWidget
{
Q_OBJECT
public:
- explicit QDockWidgetGroupWindow(QWidget* parent = 0, Qt::WindowFlags f = 0)
+ explicit QDockWidgetGroupWindow(QWidget* parent = nullptr, Qt::WindowFlags f = nullptr)
: QWidget(parent, f) {}
QDockAreaLayoutInfo *layoutInfo() const;
const QDockAreaLayoutInfo *tabLayoutInfo() const;
@@ -430,7 +430,7 @@ public:
bool isValid() const;
QLayoutItem *plug(const QList<int> &path);
- QLayoutItem *unplug(const QList<int> &path, QMainWindowLayoutState *savedState = 0);
+ QLayoutItem *unplug(const QList<int> &path, QMainWindowLayoutState *savedState = nullptr);
void saveState(QDataStream &stream) const;
bool checkFormat(QDataStream &stream);
@@ -475,7 +475,7 @@ public:
void addToolBar(Qt::ToolBarArea area, QToolBar *toolbar, bool needAddChildWidget = true);
void insertToolBar(QToolBar *before, QToolBar *toolbar);
- Qt::ToolBarArea toolBarArea(QToolBar *toolbar) const;
+ Qt::ToolBarArea toolBarArea(const QToolBar *toolbar) const;
bool toolBarBreak(QToolBar *toolBar) const;
void getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const;
void removeToolBar(QToolBar *toolbar);
diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp
index f32cd26478..fe3d1663a8 100644
--- a/src/widgets/widgets/qmdiarea.cpp
+++ b/src/widgets/widgets/qmdiarea.cpp
@@ -954,14 +954,6 @@ void QMdiAreaPrivate::rearrange(Rearranger *rearranger)
}
}
- if (active && rearranger->type() == Rearranger::RegularTiler && !tileCalledFromResizeEvent) {
- // Move active window in front if necessary. That's the case if we
- // have any windows with staysOnTopHint set.
- int indexToActive = widgets.indexOf((QWidget *)active);
- if (indexToActive > 0)
- widgets.move(indexToActive, 0);
- }
-
QRect domain = viewport->rect();
if (rearranger->type() == Rearranger::RegularTiler && !widgets.isEmpty())
domain = resizeToMinimumTileSize(minSubWindowSize, widgets.count());
@@ -1296,7 +1288,11 @@ QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, in
minAreaHeight += 2 * frame;
}
const QSize diff = QSize(minAreaWidth, minAreaHeight).expandedTo(q->size()) - q->size();
- topLevel->resize(topLevel->size() + diff);
+ // Only resize topLevel widget if scroll bars are disabled.
+ if (hbarpolicy == Qt::ScrollBarAlwaysOff)
+ topLevel->resize(topLevel->size().width() + diff.width(), topLevel->size().height());
+ if (vbarpolicy == Qt::ScrollBarAlwaysOff)
+ topLevel->resize(topLevel->size().width(), topLevel->size().height() + diff.height());
}
QRect domain = viewport->rect();
@@ -1778,7 +1774,7 @@ QSize QMdiArea::minimumSizeHint() const
}
/*!
- Returns a pointer to the current subwindow, or 0 if there is
+ Returns a pointer to the current subwindow, or \nullptr if there is
no current subwindow.
This function will return the same as activeSubWindow() if
@@ -1790,13 +1786,13 @@ QMdiSubWindow *QMdiArea::currentSubWindow() const
{
Q_D(const QMdiArea);
if (d->childWindows.isEmpty())
- return 0;
+ return nullptr;
if (d->active)
return d->active;
if (d->isActivated && !window()->isMinimized())
- return 0;
+ return nullptr;
Q_ASSERT(d->indicesToActivatedChildren.count() > 0);
int index = d->indicesToActivatedChildren.at(0);
@@ -1808,7 +1804,7 @@ QMdiSubWindow *QMdiArea::currentSubWindow() const
/*!
Returns a pointer to the current active subwindow. If no
- window is currently active, 0 is returned.
+ window is currently active, \nullptr is returned.
Subwindows are treated as top-level windows with respect to
window state, i.e., if a widget outside the MDI area is the active
@@ -1825,7 +1821,7 @@ QMdiSubWindow *QMdiArea::activeSubWindow() const
}
/*!
- Activates the subwindow \a window. If \a window is 0, any
+ Activates the subwindow \a window. If \a window is \nullptr, any
current active window is deactivated.
\sa activeSubWindow()
@@ -1834,7 +1830,7 @@ void QMdiArea::setActiveSubWindow(QMdiSubWindow *window)
{
Q_D(QMdiArea);
if (!window) {
- d->activateWindow(0);
+ d->activateWindow(nullptr);
return;
}
@@ -1992,9 +1988,11 @@ QMdiSubWindow *QMdiArea::addSubWindow(QWidget *widget, Qt::WindowFlags windowFla
Q_ASSERT(child->testAttribute(Qt::WA_DeleteOnClose));
}
+ d->appendChild(child);
+
if (childFocus)
childFocus->setFocus();
- d->appendChild(child);
+
return child;
}
@@ -2002,9 +2000,9 @@ QMdiSubWindow *QMdiArea::addSubWindow(QWidget *widget, Qt::WindowFlags windowFla
Removes \a widget from the MDI area. The \a widget must be
either a QMdiSubWindow or a widget that is the internal widget of
a subwindow. Note \a widget is never actually deleted by QMdiArea.
- If a QMdiSubWindow is passed in its parent is set to 0 and it is
- removed, but if an internal widget is passed in the child widget
- is set to 0 but the QMdiSubWindow is not removed.
+ If a QMdiSubWindow is passed in, its parent is set to \nullptr and it is
+ removed; but if an internal widget is passed in, the child widget
+ is set to \nullptr and the QMdiSubWindow is \e not removed.
\sa addSubWindow()
*/
@@ -2640,7 +2638,11 @@ bool QMdiArea::eventFilter(QObject *object, QEvent *event)
#endif // QT_CONFIG(tabbar)
Q_FALLTHROUGH();
case QEvent::Hide:
- d->isSubWindowsTiled = false;
+ // Do not reset the isSubWindowsTiled flag if the event is a spontaneous system window event.
+ // This ensures that tiling will be performed during the resizeEvent after an application
+ // window minimize (hide) and then restore (show).
+ if (!event->spontaneous())
+ d->isSubWindowsTiled = false;
break;
#if QT_CONFIG(rubberband)
case QEvent::Close:
diff --git a/src/widgets/widgets/qmdiarea_p.h b/src/widgets/widgets/qmdiarea_p.h
index fd00118ec6..0a6368044a 100644
--- a/src/widgets/widgets/qmdiarea_p.h
+++ b/src/widgets/widgets/qmdiarea_p.h
@@ -183,7 +183,7 @@ public:
int tabToPreviousTimerId;
// Slots.
- void _q_deactivateAllWindows(QMdiSubWindow *aboutToActivate = 0);
+ void _q_deactivateAllWindows(QMdiSubWindow *aboutToActivate = nullptr);
void _q_processWindowStateChanged(Qt::WindowStates oldState, Qt::WindowStates newState);
void _q_currentTabChanged(int index);
void _q_closeTab(int index);
@@ -198,7 +198,7 @@ public:
void activateCurrentWindow();
void activateHighlightedWindow();
void emitWindowActivated(QMdiSubWindow *child);
- void resetActiveWindow(QMdiSubWindow *child = 0);
+ void resetActiveWindow(QMdiSubWindow *child = nullptr);
void updateActiveWindow(int removedIndex, bool activeRemoved);
void updateScrollBars();
void internalRaise(QMdiSubWindow *child) const;
diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp
index e9511f944f..685c5e159e 100644
--- a/src/widgets/widgets/qmdisubwindow.cpp
+++ b/src/widgets/widgets/qmdisubwindow.cpp
@@ -2268,7 +2268,7 @@ QMdiSubWindow::QMdiSubWindow(QWidget *parent, Qt::WindowFlags flags)
setMouseTracking(true);
setLayout(new QVBoxLayout);
setFocusPolicy(Qt::StrongFocus);
- layout()->setMargin(0);
+ layout()->setContentsMargins(QMargins());
d->updateGeometryConstraints();
setAttribute(Qt::WA_Resized, false);
d->titleBarPalette = d->desktopPalette();
@@ -2576,7 +2576,8 @@ void QMdiSubWindow::showSystemMenu()
/*!
\since 4.4
- Returns the area containing this sub-window, or 0 if there is none.
+ Returns the area containing this sub-window, or \nullptr if there
+ is none.
\sa QMdiArea::addSubWindow()
*/
@@ -2590,7 +2591,7 @@ QMdiArea *QMdiSubWindow::mdiArea() const
}
parent = parent->parentWidget();
}
- return 0;
+ return nullptr;
}
/*!
@@ -3347,8 +3348,11 @@ void QMdiSubWindow::mouseMoveEvent(QMouseEvent *mouseEvent)
}
if ((mouseEvent->buttons() & Qt::LeftButton) || d->isInInteractiveMode) {
- if ((d->isResizeOperation() && d->resizeEnabled) || (d->isMoveOperation() && d->moveEnabled))
- d->setNewGeometry(mapToParent(mouseEvent->pos()));
+ if ((d->isResizeOperation() && d->resizeEnabled) || (d->isMoveOperation() && d->moveEnabled)) {
+ // As setNewGeometry moves the window, it invalidates the pos() value of any mouse move events that are
+ // currently queued in the event loop. Map to parent using globalPos() instead.
+ d->setNewGeometry(parentWidget()->mapFromGlobal(mouseEvent->globalPos()));
+ }
return;
}
diff --git a/src/widgets/widgets/qmdisubwindow_p.h b/src/widgets/widgets/qmdisubwindow_p.h
index 719984c8d4..d3513b6708 100644
--- a/src/widgets/widgets/qmdisubwindow_p.h
+++ b/src/widgets/widgets/qmdisubwindow_p.h
@@ -78,7 +78,7 @@ template<typename T>
class ControlElement : public T
{
public:
- ControlElement(QMdiSubWindow *child) : T(child, 0)
+ ControlElement(QMdiSubWindow *child) : T(child, nullptr)
{
Q_ASSERT(child);
mdiChild = child;
@@ -88,7 +88,7 @@ public:
{
if (classname && strcmp(classname, "ControlElement") == 0)
return this;
- return 0;
+ return nullptr;
}
QPointer<QMdiSubWindow> mdiChild;
@@ -102,7 +102,7 @@ public:
#if QT_CONFIG(menubar)
void showButtonsInMenuBar(QMenuBar *menuBar);
- void removeButtonsFromMenuBar(QMenuBar *menuBar = 0);
+ void removeButtonsFromMenuBar(QMenuBar *menuBar = nullptr);
QMenuBar *menuBar() const { return m_menuBar; }
#endif
void updateWindowIcon(const QIcon &windowIcon);
@@ -331,7 +331,7 @@ public:
inline bool autoRaise() const
{
Q_Q(const QMdiSubWindow);
- return q->style()->styleHint(QStyle::SH_TitleBar_AutoRaise, 0, q);
+ return q->style()->styleHint(QStyle::SH_TitleBar_AutoRaise, nullptr, q);
}
inline bool isResizeOperation() const
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 2d107de268..7b6a1b6da8 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -1782,21 +1782,6 @@ QAction *QMenu::addAction(const QString &text, const QObject *receiver, const ch
return action;
}
-/*!\fn template<typename PointerToMemberFunction> QAction *QMenu::addAction(const QString &text, const QObject *receiver, PointerToMemberFunction method, const QKeySequence &shortcut = 0)
-
- \since 5.6
-
- \overload
-
- This convenience function creates a new action with the text \a
- text and an optional shortcut \a shortcut. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a method of the \a receiver. The function adds the newly created
- action to the menu's list of actions and returns it.
-
- QMenu takes ownership of the returned QAction.
-*/
-
/*!\fn template<typename Functor> QAction *QMenu::addAction(const QString &text, Functor functor, const QKeySequence &shortcut = 0)
\since 5.6
@@ -1821,25 +1806,11 @@ QAction *QMenu::addAction(const QString &text, const QObject *receiver, const ch
This convenience function creates a new action with the text \a
text and an optional shortcut \a shortcut. The action's
\l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor. The function adds the newly created
- action to the menu's list of actions and returns it.
+ \a functor. The functor can be a pointer to a member function of
+ the \a context object. The newly created action is added to the
+ menu's list of actions and a pointer to it is returned.
- If \a context is destroyed, the functor will not be called.
-
- QMenu takes ownership of the returned QAction.
-*/
-
-/*!\fn template<typename PointerToMemberFunction> QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *receiver, PointerToMemberFunction method, const QKeySequence &shortcut = 0)
-
- \since 5.6
-
- \overload
-
- This convenience function creates a new action with an \a icon
- and some \a text and an optional shortcut \a shortcut. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a method of the \a receiver. The function adds the newly created
- action to the menu's list of actions and returns it.
+ If the \a context object is destroyed, the functor will not be called.
QMenu takes ownership of the returned QAction.
*/
@@ -1868,8 +1839,9 @@ QAction *QMenu::addAction(const QString &text, const QObject *receiver, const ch
This convenience function creates a new action with an \a icon
and some \a text and an optional shortcut \a shortcut. The action's
\l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor. The function adds the newly created
- action to the menu's list of actions and returns it.
+ \a functor. The \a functor can be a pointer to a member function
+ of the \a context object. The newly created action is added to the
+ menu's list of actions and a pointer to it is returned.
If \a context is destroyed, the functor will not be called.
@@ -2223,7 +2195,7 @@ void QMenu::setActiveAction(QAction *act)
/*!
- Returns the currently highlighted action, or 0 if no
+ Returns the currently highlighted action, or \nullptr if no
action is currently highlighted.
*/
QAction *QMenu::activeAction() const
@@ -2603,8 +2575,8 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
This is equivalent to \c{exec(pos())}.
This returns the triggered QAction in either the popup menu or one
- of its submenus, or 0 if no item was triggered (normally because
- the user pressed Esc).
+ of its submenus, or \nullptr if no item was triggered (normally
+ because the user pressed Esc).
In most situations you'll want to specify the position yourself,
for example, the current mouse position:
@@ -2630,8 +2602,8 @@ QAction *QMenu::exec()
coordinates into global coordinates, use QWidget::mapToGlobal().
This returns the triggered QAction in either the popup menu or one
- of its submenus, or 0 if no item was triggered (normally because
- the user pressed Esc).
+ of its submenus, or \nullptr if no item was triggered (normally
+ because the user pressed Esc).
Note that all signals are emitted as usual. If you connect a
QAction to a slot and call the menu's exec(), you get the result
@@ -2667,11 +2639,11 @@ QAction *QMenu::exec(const QPoint &p, QAction *action)
QPointer<QObject> guard = this;
(void) eventLoop.exec();
if (guard.isNull())
- return 0;
+ return nullptr;
action = d->syncAction;
- d->syncAction = 0;
- d->eventLoop = 0;
+ d->syncAction = nullptr;
+ d->eventLoop = nullptr;
return action;
}
@@ -2689,7 +2661,7 @@ QAction *QMenu::exec(const QPoint &p, QAction *action)
QGraphicsView).
The function returns the triggered QAction in either the popup
- menu or one of its submenus, or 0 if no item was triggered
+ menu or one of its submenus, or \nullptr if no item was triggered
(normally because the user pressed Esc).
This is equivalent to:
diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h
index 628f818b5e..84ab9e027a 100644
--- a/src/widgets/widgets/qmenu.h
+++ b/src/widgets/widgets/qmenu.h
@@ -82,14 +82,10 @@ public:
QAction *addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut = 0);
#ifdef Q_CLANG_QDOC
- template<typename PointerToMemberFunction>
- QAction *addAction(const QString &text, const QObject *receiver, PointerToMemberFunction method, const QKeySequence &shortcut = 0);
template<typename Functor>
QAction *addAction(const QString &text, Functor functor, const QKeySequence &shortcut = 0);
template<typename Functor>
QAction *addAction(const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut = 0);
- template<typename PointerToMemberFunction>
- QAction *addAction(const QIcon &icon, const QString &text, const QObject *receiver, PointerToMemberFunction method, const QKeySequence &shortcut = 0);
template<typename Functor>
QAction *addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut = 0);
template<typename Functor>
diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h
index b8976385f4..efbbc099a1 100644
--- a/src/widgets/widgets/qmenu_p.h
+++ b/src/widgets/widgets/qmenu_p.h
@@ -95,6 +95,12 @@ static inline int &rperp(Qt::Orientation o, QPoint &pos)
static inline int &rperp(Qt::Orientation o, QSize &size)
{ return o == Qt::Vertical ? size.rwidth() : size.rheight(); }
+static inline int pick(Qt::Orientation o, const QMargins &m)
+{ return o == Qt::Horizontal ? (m.left() + m.right()) : (m.top() + m.bottom()); }
+
+static inline int perp(Qt::Orientation o, const QMargins &m)
+{ return o == Qt::Vertical ? (m.left() + m.right()) : (m.top() + m.bottom()); }
+
class QTornOffMenu;
class QEventLoop;
@@ -115,7 +121,7 @@ private:
class QMenuSloppyState
{
- Q_DISABLE_COPY(QMenuSloppyState)
+ Q_DISABLE_COPY_MOVE(QMenuSloppyState)
public:
QMenuSloppyState()
: m_enabled(false)
@@ -129,9 +135,9 @@ public:
void initialize(QMenu *menu)
{
m_menu = menu;
- m_uni_directional = menu->style()->styleHint(QStyle::SH_Menu_SubMenuUniDirection, 0, menu);
- m_uni_dir_fail_at_count = short(menu->style()->styleHint(QStyle::SH_Menu_SubMenuUniDirectionFailCount, 0, menu));
- m_select_other_actions = menu->style()->styleHint(QStyle::SH_Menu_SubMenuSloppySelectOtherActions, 0 , menu);
+ m_uni_directional = menu->style()->styleHint(QStyle::SH_Menu_SubMenuUniDirection, nullptr, menu);
+ m_uni_dir_fail_at_count = short(menu->style()->styleHint(QStyle::SH_Menu_SubMenuUniDirectionFailCount, nullptr, menu));
+ m_select_other_actions = menu->style()->styleHint(QStyle::SH_Menu_SubMenuSloppySelectOtherActions, nullptr , menu);
m_timeout = short(menu->style()->styleHint(QStyle::SH_Menu_SubMenuSloppyCloseTimeout));
m_discard_state_when_entering_parent = menu->style()->styleHint(QStyle::SH_Menu_SubMenuResetWhenReenteringParent);
m_dont_start_time_on_leave = menu->style()->styleHint(QStyle::SH_Menu_SubMenuDontStartSloppyOnLeave);
@@ -372,7 +378,7 @@ public:
}
void stop()
{
- action = 0;
+ action = nullptr;
timer.stop();
}
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 33c10f3a9a..9a60f1477d 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -906,8 +906,8 @@ QAction *QMenuBar::insertMenu(QAction *before, QMenu *menu)
}
/*!
- Returns the QAction that is currently highlighted. A null pointer
- will be returned if no action is currently selected.
+ Returns the QAction that is currently highlighted, if any,
+ else \nullptr.
*/
QAction *QMenuBar::activeAction() const
{
diff --git a/src/widgets/widgets/qmenubar_p.h b/src/widgets/widgets/qmenubar_p.h
index c276a4512d..e3db16d190 100644
--- a/src/widgets/widgets/qmenubar_p.h
+++ b/src/widgets/widgets/qmenubar_p.h
@@ -65,9 +65,9 @@ class QMenuBarPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QMenuBar)
public:
- QMenuBarPrivate() : itemsDirty(0), currentAction(0), mouseDown(0),
+ QMenuBarPrivate() : itemsDirty(0), currentAction(nullptr), mouseDown(0),
closePopupMode(0), defaultPopDown(1), popupState(0), keyboardState(0), altPressed(0),
- doChildEffects(false), platformMenuBar(0)
+ doChildEffects(false), platformMenuBar(nullptr)
{ }
~QMenuBarPrivate()
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index 3b5132a8c8..4a875975a4 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -1622,7 +1622,7 @@ void QPlainTextEdit::timerEvent(QTimerEvent *e)
const QPoint globalPos = QCursor::pos();
pos = d->viewport->mapFromGlobal(globalPos);
QMouseEvent ev(QEvent::MouseMove, pos, d->viewport->mapTo(d->viewport->topLevelWidget(), pos), globalPos,
- Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ Qt::LeftButton, Qt::LeftButton, QGuiApplication::keyboardModifiers());
mouseMoveEvent(&ev);
}
int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height();
@@ -2052,7 +2052,7 @@ void QPlainTextEdit::paintEvent(QPaintEvent *e)
if (backgroundVisible() && !block.isValid() && offset.y() <= er.bottom()
&& (centerOnScroll() || verticalScrollBar()->maximum() == verticalScrollBar()->minimum())) {
- painter.fillRect(QRect(QPoint((int)er.left(), (int)offset.y()), er.bottomRight()), palette().background());
+ painter.fillRect(QRect(QPoint((int)er.left(), (int)offset.y()), er.bottomRight()), palette().window());
}
}
@@ -2905,6 +2905,7 @@ void QPlainTextEdit::setCenterOnScroll(bool enabled)
if (enabled == d->centerOnScroll)
return;
d->centerOnScroll = enabled;
+ d->_q_adjustScrollbars();
}
@@ -2942,6 +2943,27 @@ bool QPlainTextEdit::find(const QRegExp &exp, QTextDocument::FindFlags options)
#endif
/*!
+ \fn bool QPlainTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
+
+ \since 5.13
+ \overload
+
+ Finds the next occurrence, matching the regular expression, \a exp, using the given
+ \a options. The QTextDocument::FindCaseSensitively option is ignored for this overload,
+ use QRegularExpression::CaseInsensitiveOption instead.
+
+ Returns \c true if a match was found and changes the cursor to select the match;
+ otherwise returns \c false.
+*/
+#if QT_CONFIG(regularexpression)
+bool QPlainTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
+{
+ Q_D(QPlainTextEdit);
+ return d->control->find(exp, options);
+}
+#endif
+
+/*!
\fn void QPlainTextEdit::copyAvailable(bool yes)
This signal is emitted when text is selected or de-selected in the
diff --git a/src/widgets/widgets/qplaintextedit.h b/src/widgets/widgets/qplaintextedit.h
index e5ac4c82b8..a5945d649a 100644
--- a/src/widgets/widgets/qplaintextedit.h
+++ b/src/widgets/widgets/qplaintextedit.h
@@ -60,6 +60,7 @@ class QMenu;
class QPlainTextEditPrivate;
class QMimeData;
class QPagedPaintDevice;
+class QRegularExpression;
class Q_WIDGETS_EXPORT QPlainTextEdit : public QAbstractScrollArea
{
@@ -149,6 +150,9 @@ public:
#ifndef QT_NO_REGEXP
bool find(const QRegExp &exp, QTextDocument::FindFlags options = QTextDocument::FindFlags());
#endif
+#if QT_CONFIG(regularexpression)
+ bool find(const QRegularExpression &exp, QTextDocument::FindFlags options = QTextDocument::FindFlags());
+#endif
inline QString toPlainText() const
{ return document()->toPlainText(); }
diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp
index 8f7271c2dc..b578aa0b18 100644
--- a/src/widgets/widgets/qpushbutton.cpp
+++ b/src/widgets/widgets/qpushbutton.cpp
@@ -545,8 +545,8 @@ void QPushButton::setMenu(QMenu* menu)
}
/*!
- Returns the button's associated popup menu or 0 if no popup menu
- has been set.
+ Returns the button's associated popup menu or \nullptr if no popup
+ menu has been set.
\sa setMenu()
*/
diff --git a/src/widgets/widgets/qscrollarea.cpp b/src/widgets/widgets/qscrollarea.cpp
index 0bfc56f7fa..9994344d79 100644
--- a/src/widgets/widgets/qscrollarea.cpp
+++ b/src/widgets/widgets/qscrollarea.cpp
@@ -217,7 +217,7 @@ void QScrollAreaPrivate::updateScrollBars()
}
/*!
- Returns the scroll area's widget, or 0 if there is none.
+ Returns the scroll area's widget, or \nullptr if there is none.
\sa setWidget()
*/
diff --git a/src/widgets/widgets/qscrollarea_p.h b/src/widgets/widgets/qscrollarea_p.h
index fa2e0241cf..2bdf9ed596 100644
--- a/src/widgets/widgets/qscrollarea_p.h
+++ b/src/widgets/widgets/qscrollarea_p.h
@@ -65,7 +65,7 @@ class QScrollAreaPrivate: public QAbstractScrollAreaPrivate
Q_DECLARE_PUBLIC(QScrollArea)
public:
- QScrollAreaPrivate(): resizable(false), alignment(0){}
+ QScrollAreaPrivate(): resizable(false), alignment(nullptr){}
void updateScrollBars();
void updateWidgetPosition();
QPointer<QWidget> widget;
diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp
index 7624b1ed3c..97a3a12336 100644
--- a/src/widgets/widgets/qspinbox.cpp
+++ b/src/widgets/widgets/qspinbox.cpp
@@ -128,9 +128,10 @@ public:
manually. The spin box supports integer values but can be extended to
use different strings with validate(), textFromValue() and valueFromText().
- Every time the value changes QSpinBox emits two valueChanged() signals,
- one providing an int and the other a QString. The QString overload
- provides the value with both prefix() and suffix().
+ Every time the value changes QSpinBox emits valueChanged() and
+ textChanged() signals, the former providing a int and the latter
+ a QString. The textChanged() signal provides the value with both
+ prefix() and suffix().
The current value can be fetched with value() and set with setValue().
Clicking the up/down buttons or using the keyboard accelerator's
@@ -183,12 +184,23 @@ public:
*/
/*!
+ \fn void QSpinBox::textChanged(const QString &text)
+ \since 5.14
+
+ This signal is emitted whenever the spin box's text is changed.
+ The new text is passed in \a text with prefix() and suffix().
+*/
+
+#if QT_DEPRECATED_SINCE(5, 14)
+/*!
\fn void QSpinBox::valueChanged(const QString &text)
\overload
+ \obsolete Use textChanged(QString) instead
The new value is passed in \a text with prefix() and suffix().
*/
+#endif
/*!
Constructs a spin box with 0 as minimum value and 99 as maximum value, a
@@ -594,9 +606,9 @@ void QSpinBox::fixup(QString &input) const
values but can be extended to use different strings with
validate(), textFromValue() and valueFromText().
- Every time the value changes QDoubleSpinBox emits two
- valueChanged() signals, one taking providing a double and the other
- a QString. The QString overload provides the value with both
+ Every time the value changes QDoubleSpinBox emits valueChanged() and
+ textChanged() signals, the former providing a double and the latter
+ a QString. The textChanged() signal provides the value with both
prefix() and suffix(). The current value can be fetched with
value() and set with setValue().
@@ -644,12 +656,23 @@ void QSpinBox::fixup(QString &input) const
*/
/*!
+ \fn void QDoubleSpinBox::textChanged(const QString &text)
+ \since 5.14
+
+ This signal is emitted whenever the spin box's text is changed.
+ The new text is passed in \a text with prefix() and suffix().
+*/
+
+#if QT_DEPRECATED_SINCE(5, 14)
+/*!
\fn void QDoubleSpinBox::valueChanged(const QString &text);
\overload
+ \obsolete Use textChanged(QString) instead
The new value is passed in \a text with prefix() and suffix().
*/
+#endif
/*!
Constructs a spin box with 0.0 as minimum value and 99.99 as maximum value,
@@ -728,6 +751,10 @@ void QDoubleSpinBox::setPrefix(const QString &prefix)
d->prefix = prefix;
d->updateEdit();
+
+ d->cachedSizeHint = QSize();
+ d->cachedMinimumSizeHint = QSize(); // minimumSizeHint cares about the prefix
+ updateGeometry();
}
/*!
@@ -1068,7 +1095,13 @@ void QSpinBoxPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
if (ep != NeverEmit) {
pendingEmit = false;
if (ep == AlwaysEmit || value != old) {
+#if QT_DEPRECATED_SINCE(5, 14)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
emit q->valueChanged(edit->displayText());
+QT_WARNING_POP
+#endif
+ emit q->textChanged(edit->displayText());
emit q->valueChanged(value.toInt());
}
}
@@ -1219,7 +1252,13 @@ void QDoubleSpinBoxPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
if (ep != NeverEmit) {
pendingEmit = false;
if (ep == AlwaysEmit || value != old) {
+#if QT_DEPRECATED_SINCE(5, 14)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
emit q->valueChanged(edit->displayText());
+QT_WARNING_POP
+#endif
+ emit q->textChanged(edit->displayText());
emit q->valueChanged(value.toDouble());
}
}
diff --git a/src/widgets/widgets/qspinbox.h b/src/widgets/widgets/qspinbox.h
index d2eac903fb..762dd4a46a 100644
--- a/src/widgets/widgets/qspinbox.h
+++ b/src/widgets/widgets/qspinbox.h
@@ -106,7 +106,11 @@ public Q_SLOTS:
Q_SIGNALS:
void valueChanged(int);
+ void textChanged(const QString &);
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_X("Use textChanged(QString) instead")
void valueChanged(const QString &);
+#endif
private:
Q_DISABLE_COPY(QSpinBox)
@@ -168,7 +172,11 @@ public Q_SLOTS:
Q_SIGNALS:
void valueChanged(double);
+ void textChanged(const QString &);
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_X("Use textChanged(QString) instead")
void valueChanged(const QString &);
+#endif
private:
Q_DISABLE_COPY(QDoubleSpinBox)
diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp
index 3b516f36b6..08533040a7 100644
--- a/src/widgets/widgets/qsplitter.cpp
+++ b/src/widgets/widgets/qsplitter.cpp
@@ -1231,7 +1231,7 @@ QSplitterHandle *QSplitter::createHandle()
/*!
Returns the handle to the left of (or above) the item in the
- splitter's layout at the given \a index, or \c nullptr if there is no such item.
+ splitter's layout at the given \a index, or \nullptr if there is no such item.
The handle at index 0 is always hidden.
For right-to-left languages such as Arabic and Hebrew, the layout
@@ -1250,7 +1250,7 @@ QSplitterHandle *QSplitter::handle(int index) const
/*!
Returns the widget at the given \a index in the splitter's layout,
- or \c nullptr if there is no such widget.
+ or \nullptr if there is no such widget.
\sa count(), handle(), indexOf(), insertWidget()
*/
@@ -1378,7 +1378,7 @@ bool QSplitter::event(QEvent *e)
default:
;
}
- return QWidget::event(e);
+ return QFrame::event(e);
}
/*!
@@ -1783,6 +1783,7 @@ void QSplitter::setStretchFactor(int index, int stretch)
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\relates QSplitter
\obsolete
@@ -1792,7 +1793,7 @@ void QSplitter::setStretchFactor(int index, int stretch)
QTextStream& operator<<(QTextStream& ts, const QSplitter& splitter)
{
- ts << splitter.saveState() << endl;
+ ts << splitter.saveState() << Qt::endl;
return ts;
}
@@ -1813,6 +1814,7 @@ QTextStream& operator>>(QTextStream& ts, QSplitter& splitter)
splitter.restoreState(std::move(line).toLatin1());
return ts;
}
+#endif
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qsplitter.h b/src/widgets/widgets/qsplitter.h
index 16fac48d1c..ec980d9ee3 100644
--- a/src/widgets/widgets/qsplitter.h
+++ b/src/widgets/widgets/qsplitter.h
@@ -129,8 +129,12 @@ private:
friend class QSplitterHandle;
};
+#if QT_DEPRECATED_SINCE(5, 13)
+QT_DEPRECATED_X("Use QSplitter::saveState() instead")
Q_WIDGETS_EXPORT QTextStream& operator<<(QTextStream&, const QSplitter&);
+QT_DEPRECATED_X("Use QSplitter::restoreState() instead")
Q_WIDGETS_EXPORT QTextStream& operator>>(QTextStream&, QSplitter&);
+#endif
class QSplitterHandlePrivate;
class Q_WIDGETS_EXPORT QSplitterHandle : public QWidget
diff --git a/src/widgets/widgets/qsplitter_p.h b/src/widgets/widgets/qsplitter_p.h
index f0d621004f..871406a51d 100644
--- a/src/widgets/widgets/qsplitter_p.h
+++ b/src/widgets/widgets/qsplitter_p.h
@@ -70,7 +70,7 @@ public:
QWidget *widget;
QSplitterHandle *handle;
- QSplitterLayoutStruct() : sizer(-1), collapsed(false), collapsible(Default), widget(0), handle(0) {}
+ QSplitterLayoutStruct() : sizer(-1), collapsed(false), collapsible(Default), widget(nullptr), handle(nullptr) {}
~QSplitterLayoutStruct() { delete handle; }
int getWidgetSize(Qt::Orientation orient);
int getHandleSize(Qt::Orientation orient);
@@ -84,7 +84,7 @@ class QSplitterPrivate : public QFramePrivate
public:
QSplitterPrivate() :
#if QT_CONFIG(rubberband)
- rubberBand(0),
+ rubberBand(nullptr),
#endif
opaque(true), firstShow(true),
childrenCollapsible(true), compatMode(false), handleWidth(-1), blockChildAdd(false), opaqueResizeSet(false) {}
@@ -140,7 +140,7 @@ class QSplitterHandlePrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QSplitterHandle)
public:
- QSplitterHandlePrivate() : s(0), orient(Qt::Horizontal), mouseOffset(0), opaq(false), hover(false), pressed(false) {}
+ QSplitterHandlePrivate() : s(nullptr), orient(Qt::Horizontal), mouseOffset(0), opaq(false), hover(false), pressed(false) {}
inline int pick(const QPoint &pos) const
{ return orient == Qt::Horizontal ? pos.x() : pos.y(); }
diff --git a/src/widgets/widgets/qstackedwidget.cpp b/src/widgets/widgets/qstackedwidget.cpp
index 2217dab870..f863964c58 100644
--- a/src/widgets/widgets/qstackedwidget.cpp
+++ b/src/widgets/widgets/qstackedwidget.cpp
@@ -220,7 +220,7 @@ int QStackedWidget::currentIndex() const
}
/*!
- Returns the current widget, or 0 if there are no child widgets.
+ Returns the current widget, or \nullptr if there are no child widgets.
\sa currentIndex(), setCurrentWidget()
*/
@@ -260,8 +260,8 @@ int QStackedWidget::indexOf(QWidget *widget) const
}
/*!
- Returns the widget at the given \a index, or 0 if there is no such
- widget.
+ Returns the widget at the given \a index, or \nullptr if there is
+ no such widget.
\sa currentWidget(), indexOf()
*/
diff --git a/src/widgets/widgets/qstatusbar.cpp b/src/widgets/widgets/qstatusbar.cpp
index ef98bb6950..e9044e6cad 100644
--- a/src/widgets/widgets/qstatusbar.cpp
+++ b/src/widgets/widgets/qstatusbar.cpp
@@ -482,14 +482,14 @@ void QStatusBar::reformat()
#if QT_CONFIG(sizegrip)
if (d->resizer) {
d->box = new QHBoxLayout(this);
- d->box->setMargin(0);
+ d->box->setContentsMargins(QMargins());
vbox = new QVBoxLayout;
d->box->addLayout(vbox);
} else
#endif
{
vbox = d->box = new QVBoxLayout(this);
- d->box->setMargin(0);
+ d->box->setContentsMargins(QMargins());
}
vbox->addSpacing(3);
QBoxLayout* l = new QHBoxLayout;
@@ -689,7 +689,7 @@ void QStatusBar::paintEvent(QPaintEvent *event)
}
}
if (haveMessage) {
- p.setPen(palette().foreground().color());
+ p.setPen(palette().windowText().color());
p.drawText(d->messageRect(), Qt::AlignLeading | Qt::AlignVCenter | Qt::TextSingleLine, d->tempItem);
}
}
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp
index 68453e1842..b13f4da9d2 100644
--- a/src/widgets/widgets/qtabbar.cpp
+++ b/src/widgets/widgets/qtabbar.cpp
@@ -2093,7 +2093,6 @@ void QTabBarPrivate::setupMovableTab()
grabImage.setDevicePixelRatio(q->devicePixelRatioF());
grabImage.fill(Qt::transparent);
QStylePainter p(&grabImage, q);
- p.initFrom(q);
QStyleOptionTab tab;
q->initStyleOption(&tab, pressedIndex);
@@ -2567,7 +2566,7 @@ void QTabBar::setChangeCurrentOnDrag(bool change)
The tab bar will take ownership of the widget and so all widgets set here
will be deleted by the tab bar when it is destroyed unless you separately
- reparent the widget after setting some other widget (or 0).
+ reparent the widget after setting some other widget (or \nullptr).
\sa tabsClosable()
*/
@@ -2597,14 +2596,14 @@ void QTabBar::setTabButton(int index, ButtonPosition position, QWidget *widget)
}
/*!
- Returns the widget set a tab \a index and \a position or 0 if
- one is not set.
+ Returns the widget set a tab \a index and \a position or \nullptr
+ if one is not set.
*/
QWidget *QTabBar::tabButton(int index, ButtonPosition position) const
{
Q_D(const QTabBar);
if (index < 0 || index >= d->tabList.count())
- return 0;
+ return nullptr;
if (position == LeftSide)
return d->tabList.at(index).leftWidget;
else
diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h
index 9b798e89c9..458d486b10 100644
--- a/src/widgets/widgets/qtabbar_p.h
+++ b/src/widgets/widgets/qtabbar_p.h
@@ -92,7 +92,7 @@ public:
drawBase(true), scrollOffset(0), hoverIndex(-1), elideModeSetByUser(false), useScrollButtonsSetByUser(false), expanding(true), closeButtonOnTabs(false),
selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false),
dragInProgress(false), documentMode(false), autoHide(false), changeCurrentOnDrag(false),
- switchTabCurrentIndex(-1), switchTabTimerId(0), movingTab(0)
+ switchTabCurrentIndex(-1), switchTabTimerId(0), movingTab(nullptr)
#if 0 // Used to be included in Qt4 for Q_WS_MAC
, previousPressedIndex(-1)
#endif
@@ -182,7 +182,7 @@ public:
int indexAtPos(const QPoint &p) const;
- inline bool isAnimated() const { Q_Q(const QTabBar); return q->style()->styleHint(QStyle::SH_Widget_Animation_Duration, 0, q) > 0; }
+ inline bool isAnimated() const { Q_Q(const QTabBar); return q->style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, q) > 0; }
inline bool validIndex(int index) const { return index >= 0 && index < tabList.count(); }
void setCurrentNextEnabledIndex(int offset);
diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp
index 8a848554e3..547b8a82f9 100644
--- a/src/widgets/widgets/qtabwidget.cpp
+++ b/src/widgets/widgets/qtabwidget.cpp
@@ -579,7 +579,7 @@ void QTabWidget::setTabEnabled(int index, bool enable)
All widgets set here will be deleted by the tab widget when it is
destroyed unless you separately reparent the widget after setting
- some other corner widget (or 0).
+ some other corner widget (or \nullptr).
Note: Corner widgets are designed for \l North and \l South tab positions;
other orientations are known to not work properly.
@@ -605,7 +605,7 @@ void QTabWidget::setCornerWidget(QWidget * widget, Qt::Corner corner)
}
/*!
- Returns the widget shown in the \a corner of the tab widget or 0.
+ Returns the widget shown in the \a corner of the tab widget or \nullptr.
*/
QWidget * QTabWidget::cornerWidget(Qt::Corner corner) const
{
@@ -1146,8 +1146,8 @@ void QTabWidget::keyPressEvent(QKeyEvent *e)
}
/*!
- Returns the tab page at index position \a index or 0 if the \a
- index is out of range.
+ Returns the tab page at index position \a index or \nullptr if the
+ \a index is out of range.
*/
QWidget *QTabWidget::widget(int index) const
{
diff --git a/src/widgets/widgets/qtextbrowser.cpp b/src/widgets/widgets/qtextbrowser.cpp
index 09541bb53b..bee1021950 100644
--- a/src/widgets/widgets/qtextbrowser.cpp
+++ b/src/widgets/widgets/qtextbrowser.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -57,9 +57,12 @@
#endif
#include <qtextobject.h>
#include <qdesktopservices.h>
+#include <qmimedatabase.h>
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcBrowser, "qt.text.browser")
+
class QTextBrowserPrivate : public QTextEditPrivate
{
Q_DECLARE_PUBLIC(QTextBrowser)
@@ -83,6 +86,7 @@ public:
int hpos;
int vpos;
int focusIndicatorPosition, focusIndicatorAnchor;
+ QTextDocument::ResourceType type = QTextDocument::UnknownResource;
};
HistoryEntry history(int i) const
@@ -119,6 +123,8 @@ public:
bool openExternalLinks;
bool openLinks;
+ QTextDocument::ResourceType currentType;
+
#ifndef QT_NO_CURSOR
QCursor oldCursor;
#endif
@@ -134,7 +140,7 @@ public:
void _q_activateAnchor(const QString &href);
void _q_highlightLink(const QString &href);
- void setSource(const QUrl &url);
+ void setSource(const QUrl &url, QTextDocument::ResourceType type);
// re-imlemented from QTextEditPrivate
virtual QUrl resolveUrl(const QUrl &url) const override;
@@ -271,12 +277,12 @@ void QTextBrowserPrivate::_q_highlightLink(const QString &anchor)
}
}
-void QTextBrowserPrivate::setSource(const QUrl &url)
+void QTextBrowserPrivate::setSource(const QUrl &url, QTextDocument::ResourceType type)
{
Q_Q(QTextBrowser);
#ifndef QT_NO_CURSOR
if (q->isVisible())
- QApplication::setOverrideCursor(Qt::WaitCursor);
+ QGuiApplication::setOverrideCursor(Qt::WaitCursor);
#endif
textOrSourceChanged = true;
@@ -288,10 +294,22 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
currentUrlWithoutFragment.setFragment(QString());
QUrl newUrlWithoutFragment = currentURL.resolved(url);
newUrlWithoutFragment.setFragment(QString());
+ QString fileName = url.fileName();
+ if (type == QTextDocument::UnknownResource) {
+#if QT_CONFIG(textmarkdownreader)
+ if (fileName.endsWith(QLatin1String(".md")) ||
+ fileName.endsWith(QLatin1String(".mkd")) ||
+ fileName.endsWith(QLatin1String(".markdown")))
+ type = QTextDocument::MarkdownResource;
+ else
+#endif
+ type = QTextDocument::HtmlResource;
+ }
+ currentType = type;
if (url.isValid()
&& (newUrlWithoutFragment != currentUrlWithoutFragment || forceLoadOnSourceChange)) {
- QVariant data = q->loadResource(QTextDocument::HtmlResource, resolveUrl(url));
+ QVariant data = q->loadResource(type, resolveUrl(url));
if (data.type() == QVariant::String) {
txt = data.toString();
} else if (data.type() == QVariant::ByteArray) {
@@ -310,7 +328,7 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
const QStringRef firstTag = txt.leftRef(txt.indexOf(QLatin1Char('>')) + 1);
if (firstTag.startsWith(QLatin1String("<qt")) && firstTag.contains(QLatin1String("type")) && firstTag.contains(QLatin1String("detail"))) {
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
#if QT_CONFIG(whatsthis)
QWhatsThis::showText(QCursor::pos(), txt, q);
@@ -327,9 +345,21 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
home = url;
if (doSetText) {
+ // Setting the base URL helps QTextDocument::resource() to find resources with relative paths.
+ // But don't set it unless it contains the document's path, because QTextBrowserPrivate::resolveUrl()
+ // can already deal with local files on the filesystem in case the base URL was not set.
+ QUrl baseUrl = currentURL.adjusted(QUrl::RemoveFilename);
+ if (!baseUrl.path().isEmpty())
+ q->document()->setBaseUrl(baseUrl);
+ q->document()->setMetaInformation(QTextDocument::DocumentUrl, currentURL.toString());
+ qCDebug(lcBrowser) << "loading" << currentURL << "base" << q->document()->baseUrl() << "type" << type << txt.size() << "chars";
+#if QT_CONFIG(textmarkdownreader)
+ if (type == QTextDocument::MarkdownResource)
+ q->QTextEdit::setMarkdown(txt);
+ else
+#endif
#ifndef QT_NO_TEXTHTMLPARSER
q->QTextEdit::setHtml(txt);
- q->document()->setMetaInformation(QTextDocument::DocumentUrl, currentURL.toString());
#else
q->QTextEdit::setPlainText(txt);
#endif
@@ -355,7 +385,7 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
#ifndef QT_NO_CURSOR
if (q->isVisible())
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
emit q->sourceChanged(url);
}
@@ -551,6 +581,7 @@ QTextBrowserPrivate::HistoryEntry QTextBrowserPrivate::createHistoryEntry() cons
{
HistoryEntry entry;
entry.url = q_func()->source();
+ entry.type = q_func()->sourceType();
entry.title = q_func()->documentTitle();
entry.hpos = hbar->value();
entry.vpos = vbar->value();
@@ -567,7 +598,7 @@ QTextBrowserPrivate::HistoryEntry QTextBrowserPrivate::createHistoryEntry() cons
void QTextBrowserPrivate::restoreHistoryEntry(const HistoryEntry &entry)
{
- setSource(entry.url);
+ setSource(entry.url, entry.type);
hbar->setValue(entry.hpos);
vbar->setValue(entry.vpos);
if (entry.focusIndicatorAnchor != -1 && entry.focusIndicatorPosition != -1) {
@@ -709,7 +740,13 @@ QTextBrowser::~QTextBrowser()
document is displayed as a popup rather than as new document in
the browser window itself. Otherwise, the document is displayed
normally in the text browser with the text set to the contents of
- the named document with setHtml().
+ the named document with \l QTextDocument::setHtml() or
+ \l QTextDocument::setMarkdown(), depending on whether the filename ends
+ with any of the known Markdown file extensions.
+
+ If you would like to avoid automatic type detection
+ and specify the type explicitly, call setSource() rather than
+ setting this property.
By default, this property contains an empty URL.
*/
@@ -723,6 +760,23 @@ QUrl QTextBrowser::source() const
}
/*!
+ \property QTextBrowser::sourceType
+ \brief the type of the displayed document
+
+ This is QTextDocument::UnknownResource if no document is displayed or if
+ the type of the source is unknown. Otherwise it holds the type that was
+ detected, or the type that was specified when setSource() was called.
+*/
+QTextDocument::ResourceType QTextBrowser::sourceType() const
+{
+ Q_D(const QTextBrowser);
+ if (d->stack.isEmpty())
+ return QTextDocument::UnknownResource;
+ else
+ return d->stack.top().type;
+}
+
+/*!
\property QTextBrowser::searchPaths
\brief the search paths used by the text browser to find supporting
content
@@ -752,16 +806,46 @@ void QTextBrowser::reload()
Q_D(QTextBrowser);
QUrl s = d->currentURL;
d->currentURL = QUrl();
- setSource(s);
+ setSource(s, d->currentType);
}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
void QTextBrowser::setSource(const QUrl &url)
{
+ setSource(url, QTextDocument::UnknownResource);
+}
+#endif
+
+/*!
+ Attempts to load the document at the given \a url with the specified \a type.
+
+ If \a type is \l {QTextDocument::ResourceType::UnknownResource}{UnknownResource}
+ (the default), the document type will be detected: that is, if the url ends
+ with an extension of \c{.md}, \c{.mkd} or \c{.markdown}, the document will be
+ loaded via \l QTextDocument::setMarkdown(); otherwise it will be loaded via
+ \l QTextDocument::setHtml(). This detection can be bypassed by specifying
+ the \a type explicitly.
+*/
+void QTextBrowser::setSource(const QUrl &url, QTextDocument::ResourceType type)
+{
+ doSetSource(url, type);
+}
+
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+/*!
+ Attempts to load the document at the given \a url with the specified \a type.
+
+ setSource() calls doSetSource. In Qt 5, setSource(const QUrl &url) was virtual.
+ In Qt 6, doSetSource() is virtual instead, so that it can be overridden in subclasses.
+*/
+#endif
+void QTextBrowser::doSetSource(const QUrl &url, QTextDocument::ResourceType type)
+{
Q_D(QTextBrowser);
const QTextBrowserPrivate::HistoryEntry historyEntry = d->createHistoryEntry();
- d->setSource(url);
+ d->setSource(url, type);
if (!url.isValid())
return;
@@ -775,6 +859,7 @@ void QTextBrowser::setSource(const QUrl &url)
QTextBrowserPrivate::HistoryEntry entry;
entry.url = url;
+ entry.type = d->currentType;
entry.title = documentTitle();
entry.hpos = 0;
entry.vpos = 0;
@@ -1086,6 +1171,7 @@ void QTextBrowser::paintEvent(QPaintEvent *e)
\row \li QTextDocument::HtmlResource \li QString or QByteArray
\row \li QTextDocument::ImageResource \li QImage, QPixmap or QByteArray
\row \li QTextDocument::StyleSheetResource \li QString or QByteArray
+ \row \li QTextDocument::MarkdownResource \li QString or QByteArray
\endtable
*/
QVariant QTextBrowser::loadResource(int /*type*/, const QUrl &name)
diff --git a/src/widgets/widgets/qtextbrowser.h b/src/widgets/widgets/qtextbrowser.h
index ea81256f50..33e5b3980c 100644
--- a/src/widgets/widgets/qtextbrowser.h
+++ b/src/widgets/widgets/qtextbrowser.h
@@ -55,6 +55,7 @@ class Q_WIDGETS_EXPORT QTextBrowser : public QTextEdit
Q_OBJECT
Q_PROPERTY(QUrl source READ source WRITE setSource)
+ Q_PROPERTY(QTextDocument::ResourceType sourceType READ sourceType)
Q_OVERRIDE(bool modified SCRIPTABLE false)
Q_OVERRIDE(bool readOnly DESIGNABLE false SCRIPTABLE false)
Q_OVERRIDE(bool undoRedoEnabled DESIGNABLE false SCRIPTABLE false)
@@ -67,6 +68,7 @@ public:
virtual ~QTextBrowser();
QUrl source() const;
+ QTextDocument::ResourceType sourceType() const;
QStringList searchPaths() const;
void setSearchPaths(const QStringList &paths);
@@ -88,7 +90,12 @@ public:
void setOpenLinks(bool open);
public Q_SLOTS:
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
virtual void setSource(const QUrl &name);
+ void setSource(const QUrl &name, QTextDocument::ResourceType type);
+#else
+ void setSource(const QUrl &name, QTextDocument::ResourceType type = QTextDocument::UnknownResource);
+#endif
virtual void backward();
virtual void forward();
virtual void home();
@@ -112,6 +119,10 @@ protected:
virtual void focusOutEvent(QFocusEvent *ev) override;
virtual bool focusNextPrevChild(bool next) override;
virtual void paintEvent(QPaintEvent *e) override;
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+ virtual
+#endif
+ void doSetSource(const QUrl &name, QTextDocument::ResourceType type = QTextDocument::UnknownResource);
private:
Q_DISABLE_COPY(QTextBrowser)
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index ab636660d7..01f7c34f93 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -105,6 +105,14 @@ public:
else
ed->insertFromMimeData(source);
}
+ QVariant loadResource(int type, const QUrl &name) override {
+ auto *ed = qobject_cast<QTextEdit *>(parent());
+ if (!ed)
+ return QWidgetTextControl::loadResource(type, name);
+
+ QUrl resolvedName = ed->d_func()->resolveUrl(name);
+ return ed->loadResource(type, resolvedName);
+ }
};
QTextEditPrivate::QTextEditPrivate()
@@ -159,6 +167,7 @@ void QTextEditPrivate::init(const QString &html)
QObject::connect(control, SIGNAL(copyAvailable(bool)), q, SIGNAL(copyAvailable(bool)));
QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(_q_cursorPositionChanged()));
+ QObject::connect(control, SIGNAL(blockMarkerHovered(QTextBlock)), q, SLOT(_q_hoveredBlockWithMarkerChanged(QTextBlock)));
QObject::connect(control, SIGNAL(textChanged()), q, SLOT(updateMicroFocus()));
@@ -179,6 +188,7 @@ void QTextEditPrivate::init(const QString &html)
vbar->setSingleStep(20);
viewport->setBackgroundRole(QPalette::Base);
+ q->setMouseTracking(true);
q->setAcceptDrops(true);
q->setFocusPolicy(Qt::StrongFocus);
q->setAttribute(Qt::WA_KeyCompression);
@@ -220,6 +230,21 @@ void QTextEditPrivate::_q_cursorPositionChanged()
#endif
}
+void QTextEditPrivate::_q_hoveredBlockWithMarkerChanged(const QTextBlock &block)
+{
+ Q_Q(QTextEdit);
+ Qt::CursorShape cursor = cursorToRestoreAfterHover;
+ if (block.isValid() && !q->isReadOnly()) {
+ QTextBlockFormat::MarkerType marker = block.blockFormat().marker();
+ if (marker != QTextBlockFormat::NoMarker) {
+ if (viewport->cursor().shape() != Qt::PointingHandCursor)
+ cursorToRestoreAfterHover = viewport->cursor().shape();
+ cursor = Qt::PointingHandCursor;
+ }
+ }
+ viewport->setCursor(cursor);
+}
+
void QTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode)
{
QTextCursor cursor = control->textCursor();
@@ -358,8 +383,8 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
\section1 Introduction and Concepts
QTextEdit is an advanced WYSIWYG viewer/editor supporting rich
- text formatting using HTML-style tags. It is optimized to handle
- large documents and to respond quickly to user input.
+ text formatting using HTML-style tags, or Markdown format. It is optimized
+ to handle large documents and to respond quickly to user input.
QTextEdit works on paragraphs and characters. A paragraph is a
formatted string which is word-wrapped to fit into the width of
@@ -373,7 +398,7 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
QTextEdit can display images, lists and tables. If the text is
too large to view within the text edit's viewport, scroll bars will
appear. The text edit can load both plain text and rich text files.
- Rich text is described using a subset of HTML 4 markup, refer to the
+ Rich text can be described using a subset of HTML 4 markup; refer to the
\l {Supported HTML Subset} page for more information.
If you just need to display a small piece of rich text use QLabel.
@@ -393,12 +418,19 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
QTextEdit can display a large HTML subset, including tables and
images.
- The text is set or replaced using setHtml() which deletes any
+ The text can be set or replaced using \l setHtml() which deletes any
existing text and replaces it with the text passed in the
setHtml() call. If you call setHtml() with legacy HTML, and then
call toHtml(), the text that is returned may have different markup,
but will render the same. The entire text can be deleted with clear().
+ Text can also be set or replaced using \l setMarkdown(), and the same
+ caveats apply: if you then call \l toMarkdown(), the text that is returned
+ may be different, but the meaning is preserved as much as possible.
+ Markdown with some embedded HTML can be parsed, with the same limitations
+ that \l setHtml() has; but \l toMarkdown() only writes "pure" Markdown,
+ without any embedded HTML.
+
Text itself can be inserted using the QTextCursor class or using the
convenience functions insertHtml(), insertPlainText(), append() or
paste(). QTextCursor is also able to insert complex objects like tables
@@ -1205,6 +1237,56 @@ QString QTextEdit::toHtml() const
}
#endif
+#if QT_CONFIG(textmarkdownreader) && QT_CONFIG(textmarkdownwriter)
+/*!
+ \property QTextEdit::markdown
+
+ This property provides a Markdown interface to the text of the text edit.
+
+ \c toMarkdown() returns the text of the text edit as "pure" Markdown,
+ without any embedded HTML formatting. Some features that QTextDocument
+ supports (such as the use of specific colors and named fonts) cannot be
+ expressed in "pure" Markdown, and they will be omitted.
+
+ \c setMarkdown() changes the text of the text edit. Any previous text is
+ removed and the undo/redo history is cleared. The input text is
+ interpreted as rich text in Markdown format.
+
+ Parsing of HTML included in the \a markdown string is handled in the same
+ way as in \l setHtml; however, Markdown formatting inside HTML blocks is
+ not supported.
+
+ Some features of the parser can be enabled or disabled via the \a features
+ argument:
+
+ \value MarkdownNoHTML
+ Any HTML tags in the Markdown text will be discarded
+ \value MarkdownDialectCommonMark
+ The parser supports only the features standardized by CommonMark
+ \value MarkdownDialectGitHub
+ The parser supports the GitHub dialect
+
+ The default is \c MarkdownDialectGitHub.
+
+ \sa plainText, html, QTextDocument::toMarkdown(), QTextDocument::setMarkdown()
+*/
+#endif
+
+#if QT_CONFIG(textmarkdownreader)
+void QTextEdit::setMarkdown(const QString &markdown)
+{
+ Q_D(const QTextEdit);
+ d->control->setMarkdown(markdown);
+}
+#endif
+
+#if QT_CONFIG(textmarkdownwriter)
+QString QTextEdit::toMarkdown(QTextDocument::MarkdownFeatures features) const
+{
+ Q_D(const QTextEdit);
+ return d->control->toMarkdown(features);
+}
+#endif
/*! \reimp
*/
@@ -2545,6 +2627,27 @@ bool QTextEdit::find(const QRegExp &exp, QTextDocument::FindFlags options)
#endif
/*!
+ \fn bool QTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
+
+ \since 5.13
+ \overload
+
+ Finds the next occurrence, matching the regular expression, \a exp, using the given
+ \a options. The QTextDocument::FindCaseSensitively option is ignored for this overload,
+ use QRegularExpression::CaseInsensitiveOption instead.
+
+ Returns \c true if a match was found and changes the cursor to select the match;
+ otherwise returns \c false.
+*/
+#if QT_CONFIG(regularexpression)
+bool QTextEdit::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
+{
+ Q_D(QTextEdit);
+ return d->control->find(exp, options);
+}
+#endif
+
+/*!
\fn void QTextEdit::copyAvailable(bool yes)
This signal is emitted when text is selected or de-selected in the
diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h
index 51d6c2ccba..09ef44b7b2 100644
--- a/src/widgets/widgets/qtextedit.h
+++ b/src/widgets/widgets/qtextedit.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -57,6 +57,7 @@ class QMenu;
class QTextEditPrivate;
class QMimeData;
class QPagedPaintDevice;
+class QRegularExpression;
class Q_WIDGETS_EXPORT QTextEdit : public QAbstractScrollArea
{
@@ -70,6 +71,9 @@ class Q_WIDGETS_EXPORT QTextEdit : public QAbstractScrollArea
QDOC_PROPERTY(QTextOption::WrapMode wordWrapMode READ wordWrapMode WRITE setWordWrapMode)
Q_PROPERTY(int lineWrapColumnOrWidth READ lineWrapColumnOrWidth WRITE setLineWrapColumnOrWidth)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
+#if QT_CONFIG(textmarkdownreader) && QT_CONFIG(textmarkdownwriter)
+ Q_PROPERTY(QString markdown READ toMarkdown WRITE setMarkdown NOTIFY textChanged)
+#endif
#ifndef QT_NO_TEXTHTMLPARSER
Q_PROPERTY(QString html READ toHtml WRITE setHtml NOTIFY textChanged USER true)
#endif
@@ -165,11 +169,17 @@ public:
#ifndef QT_NO_REGEXP
bool find(const QRegExp &exp, QTextDocument::FindFlags options = QTextDocument::FindFlags());
#endif
+#if QT_CONFIG(regularexpression)
+ bool find(const QRegularExpression &exp, QTextDocument::FindFlags options = QTextDocument::FindFlags());
+#endif
QString toPlainText() const;
#ifndef QT_NO_TEXTHTMLPARSER
QString toHtml() const;
#endif
+#if QT_CONFIG(textmarkdownwriter)
+ QString toMarkdown(QTextDocument::MarkdownFeatures features = QTextDocument::MarkdownDialectGitHub) const;
+#endif
void ensureCursorVisible();
@@ -234,6 +244,9 @@ public Q_SLOTS:
#ifndef QT_NO_TEXTHTMLPARSER
void setHtml(const QString &text);
#endif
+#if QT_CONFIG(textmarkdownreader)
+ void setMarkdown(const QString &markdown);
+#endif
void setText(const QString &text);
#ifndef QT_NO_CLIPBOARD
@@ -318,6 +331,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_adjustScrollbars())
Q_PRIVATE_SLOT(d_func(), void _q_ensureVisible(const QRectF &))
Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_hoveredBlockWithMarkerChanged(const QTextBlock &))
friend class QTextEditControl;
friend class QTextDocument;
friend class QWidgetTextControl;
diff --git a/src/widgets/widgets/qtextedit_p.h b/src/widgets/widgets/qtextedit_p.h
index c4ee75c78d..f7b4d15318 100644
--- a/src/widgets/widgets/qtextedit_p.h
+++ b/src/widgets/widgets/qtextedit_p.h
@@ -104,6 +104,7 @@ public:
void _q_currentCharFormatChanged(const QTextCharFormat &format);
void _q_cursorPositionChanged();
+ void _q_hoveredBlockWithMarkerChanged(const QTextBlock &block);
void updateDefaultTextOption();
@@ -136,6 +137,8 @@ public:
QString placeholderText;
+ Qt::CursorShape cursorToRestoreAfterHover = Qt::IBeamCursor;
+
#ifdef QT_KEYPAD_NAVIGATION
QBasicTimer deleteAllTimer;
#endif
diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp
index 4af71c126e..bcf5a40ae3 100644
--- a/src/widgets/widgets/qtoolbar.cpp
+++ b/src/widgets/widgets/qtoolbar.cpp
@@ -799,18 +799,6 @@ QAction *QToolBar::addAction(const QIcon &icon, const QString &text,
return action;
}
-/*!\fn template<typename PointerToMemberFunction> QAction *QToolBar::addAction(const QString &text, const QObject *receiver, PointerToMemberFunction method)
-
- \since 5.6
-
- \overload
-
- Creates a new action with the given \a text. This action is added to
- the end of the toolbar. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a method of the \a receiver.
-*/
-
/*!\fn template<typename Functor> QAction *QToolBar::addAction(const QString &text, Functor functor)
\since 5.6
@@ -829,24 +817,13 @@ QAction *QToolBar::addAction(const QIcon &icon, const QString &text,
\overload
- Creates a new action with the given \a text. This action is added to
- the end of the toolbar. The action's
+ Creates a new action with the given \a text. This action is added
+ to the end of the toolbar. The action's
\l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor.
-
- If \a context is destroyed, the functor will not be called.
-*/
-
-/*!\fn template<typename PointerToMemberFunction> QAction *QToolBar::addAction(const QIcon &icon, const QString &text, const QObject *receiver, PointerToMemberFunction method)
-
- \since 5.6
+ \a functor. The \a functor can be a pointer to a member function
+ in the \a context object.
- \overload
-
- Creates a new action with the given \a icon and \a text. This
- action is added to the end of the toolbar. The action's
- \l{QAction::triggered()}{triggered()} signal is connected to the
- \a method of the \a receiver.
+ If the \a context object is destroyed, the \a functor will not be called.
*/
/*!\fn template<typename Functor> QAction *QToolBar::addAction(const QIcon &icon, const QString &text, Functor functor)
@@ -870,9 +847,10 @@ QAction *QToolBar::addAction(const QIcon &icon, const QString &text,
Creates a new action with the given \a icon and \a text. This
action is added to the end of the toolbar. The action's
\l{QAction::triggered()}{triggered()} signal is connected to the
- \a functor.
+ \a functor. The \a functor can be a pointer to a member function
+ of the \a context object.
- If \a context is destroyed, the functor will not be called.
+ If the \a context object is destroyed, the \a functor will not be called.
*/
/*!
@@ -1067,7 +1045,7 @@ void QToolBar::paintEvent(QPaintEvent *)
if (d->layout->expanded || d->layout->animating || isWindow()) {
//if the toolbar is expended, we need to fill the background with the window color
//because some styles may expects that.
- p.fillRect(opt.rect, palette().background());
+ p.fillRect(opt.rect, palette().window());
style->drawControl(QStyle::CE_ToolBar, &opt, &p, this);
style->drawPrimitive(QStyle::PE_FrameMenu, &opt, &p, this);
} else {
diff --git a/src/widgets/widgets/qtoolbar.h b/src/widgets/widgets/qtoolbar.h
index 4ae83190d1..0c434e8d1d 100644
--- a/src/widgets/widgets/qtoolbar.h
+++ b/src/widgets/widgets/qtoolbar.h
@@ -99,15 +99,11 @@ public:
QAction *addAction(const QString &text, const QObject *receiver, const char* member);
QAction *addAction(const QIcon &icon, const QString &text,
const QObject *receiver, const char* member);
-#ifdef Q_QDOC
- template<typename PointerToMemberFunction>
- QAction *addAction(const QString &text, const QObject *receiver, PointerToMemberFunction method);
+#ifdef Q_CLANG_QDOC
template<typename Functor>
QAction *addAction(const QString &text, Functor functor);
template<typename Functor>
QAction *addAction(const QString &text, const QObject *context, Functor functor);
- template<typename PointerToMemberFunction>
- QAction *addAction(const QIcon &icon, const QString &text, const QObject *receiver, PointerToMemberFunction method);
template<typename Functor>
QAction *addAction(const QIcon &icon, const QString &text, Functor functor);
template<typename Functor>
@@ -149,7 +145,7 @@ public:
connect(result, &QAction::triggered, slot);
return result;
}
-#endif // !Q_QDOC
+#endif // !Q_CLANG_QDOC
QAction *addSeparator();
QAction *insertSeparator(QAction *before);
diff --git a/src/widgets/widgets/qtoolbar_p.h b/src/widgets/widgets/qtoolbar_p.h
index 4db75762c8..8cb5850903 100644
--- a/src/widgets/widgets/qtoolbar_p.h
+++ b/src/widgets/widgets/qtoolbar_p.h
@@ -73,7 +73,7 @@ public:
: explicitIconSize(false), explicitToolButtonStyle(false), movable(true), floatable(true),
allowedAreas(Qt::AllToolBarAreas), orientation(Qt::Horizontal),
toolButtonStyle(Qt::ToolButtonIconOnly),
- layout(0), state(0)
+ layout(nullptr), state(nullptr)
#ifdef Q_OS_OSX
, macWindowDragging(false)
#endif
diff --git a/src/widgets/widgets/qtoolbararealayout.cpp b/src/widgets/widgets/qtoolbararealayout.cpp
index edf497111b..adc329131c 100644
--- a/src/widgets/widgets/qtoolbararealayout.cpp
+++ b/src/widgets/widgets/qtoolbararealayout.cpp
@@ -789,7 +789,7 @@ void QToolBarAreaLayout::deleteAllLayoutItems()
}
}
-QInternal::DockPosition QToolBarAreaLayout::findToolBar(QToolBar *toolBar) const
+QInternal::DockPosition QToolBarAreaLayout::findToolBar(const QToolBar *toolBar) const
{
for (int i = 0; i < QInternal::DockCount; ++i) {
const QToolBarAreaLayoutInfo &dock = docks[i];
@@ -1078,7 +1078,11 @@ bool QToolBarAreaLayout::insertGap(const QList<int> &path, QLayoutItem *item)
void QToolBarAreaLayout::remove(const QList<int> &path)
{
Q_ASSERT(path.count() == 3);
- docks[path.at(0)].lines[path.at(1)].toolBarItems.removeAt(path.at(2));
+ QToolBarAreaLayoutInfo &dock = docks[path.at(0)];
+ QToolBarAreaLayoutLine &line = dock.lines[path.at(1)];
+ line.toolBarItems.removeAt(path.at(2));
+ if (line.toolBarItems.isEmpty())
+ dock.lines.removeAt(path.at(1));
}
void QToolBarAreaLayout::remove(QLayoutItem *item)
diff --git a/src/widgets/widgets/qtoolbararealayout_p.h b/src/widgets/widgets/qtoolbararealayout_p.h
index dffbab1f21..5df95a3038 100644
--- a/src/widgets/widgets/qtoolbararealayout_p.h
+++ b/src/widgets/widgets/qtoolbararealayout_p.h
@@ -69,7 +69,7 @@ class QStyleOptionToolBar;
class QToolBarAreaLayoutItem
{
public:
- QToolBarAreaLayoutItem(QLayoutItem *item = 0)
+ QToolBarAreaLayoutItem(QLayoutItem *item = nullptr)
: widgetItem(item), pos(0), size(-1), preferredSize(-1), gap(false) {}
bool skip() const;
@@ -196,7 +196,7 @@ public:
void insertItem(QInternal::DockPosition pos, QLayoutItem *item);
void insertItem(QToolBar *before, QLayoutItem *item);
- QInternal::DockPosition findToolBar(QToolBar *toolBar) const;
+ QInternal::DockPosition findToolBar(const QToolBar *toolBar) const;
bool toolBarBreak(QToolBar *toolBar) const;
void getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const;
diff --git a/src/widgets/widgets/qtoolbarlayout.cpp b/src/widgets/widgets/qtoolbarlayout.cpp
index f2d329d59d..d50e19a5ed 100644
--- a/src/widgets/widgets/qtoolbarlayout.cpp
+++ b/src/widgets/widgets/qtoolbarlayout.cpp
@@ -119,8 +119,9 @@ void QToolBarLayout::updateMarginAndSpacing()
QStyle *style = tb->style();
QStyleOptionToolBar opt;
tb->initStyleOption(&opt);
- setMargin(style->pixelMetric(QStyle::PM_ToolBarItemMargin, &opt, tb)
- + style->pixelMetric(QStyle::PM_ToolBarFrameWidth, &opt, tb));
+ const int margin = style->pixelMetric(QStyle::PM_ToolBarItemMargin, &opt, tb)
+ + style->pixelMetric(QStyle::PM_ToolBarFrameWidth, &opt, tb);
+ setContentsMargins(margin, margin, margin, margin);
setSpacing(style->pixelMetric(QStyle::PM_ToolBarItemSpacing, &opt, tb));
}
@@ -268,7 +269,7 @@ void QToolBarLayout::updateGeomArray() const
tb->initStyleOption(&opt);
const int handleExtent = movable()
? style->pixelMetric(QStyle::PM_ToolBarHandleExtent, &opt, tb) : 0;
- const int margin = this->margin();
+ const QMargins margins = contentsMargins();
const int spacing = this->spacing();
const int extensionExtent = style->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, tb);
Qt::Orientation o = tb->orientation();
@@ -330,12 +331,12 @@ void QToolBarLayout::updateGeomArray() const
that->empty = count == 0;
rpick(o, that->minSize) += handleExtent;
- that->minSize += QSize(2*margin, 2*margin);
+ that->minSize += QSize(pick(Qt::Horizontal, margins), pick(Qt::Vertical, margins));
if (items.count() > 1)
rpick(o, that->minSize) += spacing + extensionExtent;
rpick(o, that->hint) += handleExtent;
- that->hint += QSize(2*margin, 2*margin);
+ that->hint += QSize(pick(Qt::Horizontal, margins), pick(Qt::Vertical, margins));
that->dirty = false;
}
@@ -384,7 +385,7 @@ void QToolBarLayout::setGeometry(const QRect &rect)
QStyle *style = tb->style();
QStyleOptionToolBar opt;
tb->initStyleOption(&opt);
- const int margin = this->margin();
+ const QMargins margins = contentsMargins();
const int extensionExtent = style->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, tb);
Qt::Orientation o = tb->orientation();
@@ -403,14 +404,18 @@ void QToolBarLayout::setGeometry(const QRect &rect)
QSize hint = sizeHint();
QPoint pos;
- rpick(o, pos) = pick(o, rect.bottomRight()) - margin - extensionExtent + 2;
+ rpick(o, pos) = pick(o, rect.bottomRight()) -
+ pick(o, QSize(margins.bottom(), margins.right())) - extensionExtent + 2;
if (area == Qt::LeftToolBarArea || area == Qt::TopToolBarArea)
- rperp(o, pos) = perp(o, rect.topLeft()) + margin;
+ rperp(o, pos) = perp(o, rect.topLeft()) +
+ perp(o, QSize(margins.top(), margins.left()));
else
- rperp(o, pos) = perp(o, rect.bottomRight()) - margin - (perp(o, hint) - 2*margin) + 1;
+ rperp(o, pos) = perp(o, rect.bottomRight()) -
+ perp(o, QSize(margins.bottom(), margins.right())) -
+ (perp(o, hint) - perp(o, margins)) + 1;
QSize size;
rpick(o, size) = extensionExtent;
- rperp(o, size) = perp(o, hint) - 2*margin;
+ rperp(o, size) = perp(o, hint) - perp(o, margins);
QRect r(pos, size);
if (o == Qt::Horizontal)
@@ -443,13 +448,13 @@ bool QToolBarLayout::layoutActions(const QSize &size)
tb->initStyleOption(&opt);
const int handleExtent = movable()
? style->pixelMetric(QStyle::PM_ToolBarHandleExtent, &opt, tb) : 0;
- const int margin = this->margin();
+ const QMargins margins = contentsMargins();
const int spacing = this->spacing();
const int extensionExtent = style->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, tb);
Qt::Orientation o = tb->orientation();
bool extensionMenuContainsOnlyWidgetActions = true;
- int space = pick(o, rect.size()) - 2*margin - handleExtent;
+ int space = pick(o, rect.size()) - pick(o, margins) - handleExtent;
if (space <= 0)
return false; // nothing to do.
@@ -458,7 +463,7 @@ bool QToolBarLayout::layoutActions(const QSize &size)
bool ranOutOfSpace = false;
int rows = 0;
- int rowPos = perp(o, rect.topLeft()) + margin;
+ int rowPos = perp(o, rect.topLeft()) + perp(o, QSize(margins.top(), margins.left()));
int i = 0;
while (i < items.count()) {
QVector<QLayoutStruct> a = geomArray;
@@ -521,14 +526,14 @@ bool QToolBarLayout::layoutActions(const QSize &size)
}
QPoint pos;
- rpick(o, pos) = margin + handleExtent + a[j].pos;
+ rpick(o, pos) = pick(o, QSize(margins.top(), margins.left())) + handleExtent + a[j].pos;
rperp(o, pos) = rowPos;
QSize size;
rpick(o, size) = a[j].size;
if (expanded)
rperp(o, size) = rowHeight;
else
- rperp(o, size) = perp(o, rect.size()) - 2*margin;
+ rperp(o, size) = perp(o, rect.size()) - perp(o, QSize(margins.top(), margins.left()));
QRect r(pos, size);
if (o == Qt::Horizontal)
@@ -589,7 +594,7 @@ QSize QToolBarLayout::expandedSize(const QSize &size) const
tb->initStyleOption(&opt);
const int handleExtent = movable()
? style->pixelMetric(QStyle::PM_ToolBarHandleExtent, &opt, tb) : 0;
- const int margin = this->margin();
+ const QMargins margins = contentsMargins();
const int spacing = this->spacing();
const int extensionExtent = style->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, tb);
@@ -609,9 +614,9 @@ QSize QToolBarLayout::expandedSize(const QSize &size) const
if (rows == 1)
++rows; // we want to expand to at least two rows
int space = total_w/rows + spacing + extensionExtent;
- space = qMax(space, min_w - 2*margin - handleExtent);
+ space = qMax(space, min_w - pick(o, margins) - handleExtent);
if (win != 0)
- space = qMin(space, pick(o, win->size()) - 2*margin - handleExtent);
+ space = qMin(space, pick(o, win->size()) - pick(o, margins) - handleExtent);
int w = 0;
int h = 0;
@@ -644,11 +649,11 @@ QSize QToolBarLayout::expandedSize(const QSize &size) const
h += rowHeight + spacing;
}
- w += 2*margin + handleExtent + spacing + extensionExtent;
+ w += pick(Qt::Horizontal, margins) + handleExtent + spacing + extensionExtent;
w = qMax(w, min_w);
if (win != 0)
w = qMin(w, pick(o, win->size()));
- h += 2*margin - spacing; //there is no spacing before the first row
+ h += pick(Qt::Vertical, margins) - spacing; //there is no spacing before the first row
QSize result;
rpick(o, result) = w;
diff --git a/src/widgets/widgets/qtoolbarlayout_p.h b/src/widgets/widgets/qtoolbarlayout_p.h
index a788d30450..b5dc121b93 100644
--- a/src/widgets/widgets/qtoolbarlayout_p.h
+++ b/src/widgets/widgets/qtoolbarlayout_p.h
@@ -79,7 +79,7 @@ class QToolBarLayout : public QLayout
Q_OBJECT
public:
- QToolBarLayout(QWidget *parent = 0);
+ QToolBarLayout(QWidget *parent = nullptr);
~QToolBarLayout();
void addItem(QLayoutItem *item) override;
diff --git a/src/widgets/widgets/qtoolbox.cpp b/src/widgets/widgets/qtoolbox.cpp
index 46ade0277c..4d7f543a99 100644
--- a/src/widgets/widgets/qtoolbox.cpp
+++ b/src/widgets/widgets/qtoolbox.cpp
@@ -50,6 +50,8 @@
#include <qtooltip.h>
#include <qabstractbutton.h>
+#include <private/qmemory_p.h>
+
#include "qframe_p.h"
QT_BEGIN_NAMESPACE
@@ -106,7 +108,7 @@ public:
return widget == other.widget;
}
};
- typedef QList<Page> PageList;
+ typedef std::vector<std::unique_ptr<Page>> PageList;
inline QToolBoxPrivate()
: currentPage(0)
@@ -130,26 +132,27 @@ public:
const QToolBoxPrivate::Page *QToolBoxPrivate::page(const QObject *widget) const
{
if (!widget)
- return 0;
+ return nullptr;
- for (PageList::ConstIterator i = pageList.constBegin(); i != pageList.constEnd(); ++i)
- if ((*i).widget == widget)
- return (const Page*) &(*i);
- return 0;
+ for (const auto &page : pageList) {
+ if (page->widget == widget)
+ return page.get();
+ }
+ return nullptr;
}
QToolBoxPrivate::Page *QToolBoxPrivate::page(int index)
{
- if (index >= 0 && index < pageList.size())
- return &pageList[index];
- return 0;
+ if (index >= 0 && index < static_cast<int>(pageList.size()))
+ return pageList[index].get();
+ return nullptr;
}
const QToolBoxPrivate::Page *QToolBoxPrivate::page(int index) const
{
- if (index >= 0 && index < pageList.size())
- return &pageList.at(index);
- return 0;
+ if (index >= 0 && index < static_cast<int>(pageList.size()))
+ return pageList[index].get();
+ return nullptr;
}
void QToolBoxPrivate::updateTabs()
@@ -157,13 +160,12 @@ void QToolBoxPrivate::updateTabs()
QToolBoxButton *lastButton = currentPage ? currentPage->button : 0;
bool after = false;
int index = 0;
- for (index = 0; index < pageList.count(); ++index) {
- const Page &page = pageList.at(index);
- QToolBoxButton *tB = page.button;
+ for (const auto &page : pageList) {
+ QToolBoxButton *tB = page->button;
// update indexes, since the updates are delayed, the indexes will be correct
// when we actually paint.
tB->setIndex(index);
- QWidget *tW = page.widget;
+ QWidget *tW = page->widget;
if (after) {
QPalette p = tB->palette();
p.setColor(tB->backgroundRole(), tW->palette().color(tW->backgroundRole()));
@@ -174,6 +176,7 @@ void QToolBoxPrivate::updateTabs()
tB->update();
}
after = tB == lastButton;
+ ++index;
}
}
@@ -294,7 +297,7 @@ QToolBox::QToolBox(QWidget *parent, Qt::WindowFlags f)
{
Q_D(QToolBox);
d->layout = new QVBoxLayout(this);
- d->layout->setMargin(0);
+ d->layout->setContentsMargins(QMargins());
setBackgroundRole(QPalette::Button);
}
@@ -345,7 +348,8 @@ int QToolBox::insertItem(int index, QWidget *widget, const QIcon &icon, const QS
Q_D(QToolBox);
connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(_q_widgetDestroyed(QObject*)));
- QToolBoxPrivate::Page c;
+ auto newPage = qt_make_unique<QToolBoxPrivate::Page>();
+ auto &c = *newPage;
c.widget = widget;
c.button = new QToolBoxButton(this);
c.button->setObjectName(QLatin1String("qt_toolbox_toolboxbutton"));
@@ -360,15 +364,15 @@ int QToolBox::insertItem(int index, QWidget *widget, const QIcon &icon, const QS
c.setText(text);
c.setIcon(icon);
- if (index < 0 || index >= (int)d->pageList.count()) {
- index = d->pageList.count();
- d->pageList.append(c);
+ if (index < 0 || index >= static_cast<int>(d->pageList.size())) {
+ index = static_cast<int>(d->pageList.size());
+ d->pageList.push_back(std::move(newPage));
d->layout->addWidget(c.button);
d->layout->addWidget(c.sv);
if (index == 0)
setCurrentIndex(index);
} else {
- d->pageList.insert(index, c);
+ d->pageList.insert(d->pageList.cbegin() + index, std::move(newPage));
d->relayout();
if (d->currentPage) {
QWidget *current = d->currentPage->widget;
@@ -391,12 +395,13 @@ void QToolBoxPrivate::_q_buttonClicked()
{
Q_Q(QToolBox);
QToolBoxButton *tb = qobject_cast<QToolBoxButton*>(q->sender());
- QWidget* item = 0;
- for (QToolBoxPrivate::PageList::ConstIterator i = pageList.constBegin(); i != pageList.constEnd(); ++i)
- if ((*i).button == tb) {
- item = (*i).widget;
+ QWidget* item = nullptr;
+ for (const auto &page : pageList) {
+ if (page->button == tb) {
+ item = page->widget;
break;
}
+ }
q->setCurrentIndex(q->indexOf(item));
}
@@ -411,7 +416,7 @@ void QToolBoxPrivate::_q_buttonClicked()
int QToolBox::count() const
{
Q_D(const QToolBox);
- return d->pageList.count();
+ return static_cast<int>(d->pageList.size());
}
void QToolBox::setCurrentIndex(int index)
@@ -437,13 +442,19 @@ void QToolBoxPrivate::relayout()
Q_Q(QToolBox);
delete layout;
layout = new QVBoxLayout(q);
- layout->setMargin(0);
- for (QToolBoxPrivate::PageList::ConstIterator i = pageList.constBegin(); i != pageList.constEnd(); ++i) {
- layout->addWidget((*i).button);
- layout->addWidget((*i).sv);
+ layout->setContentsMargins(QMargins());
+ for (const auto &page : pageList) {
+ layout->addWidget(page->button);
+ layout->addWidget(page->sv);
}
}
+auto pageEquals = [](const QToolBoxPrivate::Page *page) {
+ return [page](const std::unique_ptr<QToolBoxPrivate::Page> &ptr) {
+ return ptr.get() == page;
+ };
+};
+
void QToolBoxPrivate::_q_widgetDestroyed(QObject *object)
{
Q_Q(QToolBox);
@@ -458,9 +469,9 @@ void QToolBoxPrivate::_q_widgetDestroyed(QObject *object)
delete c->button;
bool removeCurrent = c == currentPage;
- pageList.removeAll(*c);
+ pageList.erase(std::remove_if(pageList.begin(), pageList.end(), pageEquals(c)), pageList.end());
- if (!pageList.count()) {
+ if (pageList.empty()) {
currentPage = 0;
emit q->currentChanged(-1);
} else if (removeCurrent) {
@@ -504,7 +515,8 @@ int QToolBox::currentIndex() const
}
/*!
- Returns a pointer to the current widget, or 0 if there is no such item.
+ Returns a pointer to the current widget, or \nullptr if there is
+ no such item.
\sa currentIndex(), setCurrentWidget()
*/
@@ -512,7 +524,7 @@ int QToolBox::currentIndex() const
QWidget * QToolBox::currentWidget() const
{
Q_D(const QToolBox);
- return d->currentPage ? d->currentPage->widget : 0;
+ return d->currentPage ? d->currentPage->widget : nullptr;
}
/*!
@@ -530,16 +542,16 @@ void QToolBox::setCurrentWidget(QWidget *widget)
}
/*!
- Returns the widget at position \a index, or 0 if there is no such
- item.
+ Returns the widget at position \a index, or \nullptr if there is
+ no such item.
*/
QWidget *QToolBox::widget(int index) const
{
Q_D(const QToolBox);
- if (index < 0 || index >= (int) d->pageList.size())
- return 0;
- return d->pageList.at(index).widget;
+ if (index < 0 || index >= static_cast<int>(d->pageList.size()))
+ return nullptr;
+ return d->pageList[index]->widget;
}
/*!
@@ -551,7 +563,12 @@ int QToolBox::indexOf(QWidget *widget) const
{
Q_D(const QToolBox);
const QToolBoxPrivate::Page *c = (widget ? d->page(widget) : 0);
- return c ? d->pageList.indexOf(*c) : -1;
+ if (!c)
+ return -1;
+ const auto it = std::find_if(d->pageList.cbegin(), d->pageList.cend(), pageEquals(c));
+ if (it == d->pageList.cend())
+ return -1;
+ return static_cast<int>(it - d->pageList.cbegin());
}
/*!
@@ -570,7 +587,7 @@ void QToolBox::setItemEnabled(int index, bool enabled)
if (!enabled && c == d->currentPage) {
int curIndexUp = index;
int curIndexDown = curIndexUp;
- const int count = d->pageList.count();
+ const int count = static_cast<int>(d->pageList.size());
while (curIndexUp > 0 || curIndexDown < count-1) {
if (curIndexDown < count-1) {
if (d->page(++curIndexDown)->button->isEnabled()) {
diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp
index 6a24712319..b00b219386 100644
--- a/src/widgets/widgets/qtoolbutton.cpp
+++ b/src/widgets/widgets/qtoolbutton.cpp
@@ -669,7 +669,8 @@ void QToolButton::setMenu(QMenu* menu)
}
/*!
- Returns the associated menu, or 0 if no menu has been defined.
+ Returns the associated menu, or \nullptr if no menu has been
+ defined.
\sa setMenu()
*/
@@ -678,7 +679,7 @@ QMenu* QToolButton::menu() const
Q_D(const QToolButton);
if (d->menuAction)
return d->menuAction->menu();
- return 0;
+ return nullptr;
}
/*!
diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h
index f4df95865d..940a17714f 100644
--- a/src/widgets/widgets/qwidgetlinecontrol_p.h
+++ b/src/widgets/widgets/qwidgetlinecontrol_p.h
@@ -91,7 +91,7 @@ public:
m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0),
m_validInput(1), m_blinkStatus(0), m_blinkEnabled(false), m_blinkTimer(0), m_deleteAllTimer(0),
m_ascent(0), m_maxLength(32767), m_lastCursorPos(-1),
- m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0),
+ m_tripleClickTimer(0), m_maskData(nullptr), m_modifiedState(0), m_undoState(0),
m_selstart(0), m_selend(0), m_passwordEchoEditing(false)
, m_passwordEchoTimer(0)
, m_passwordMaskDelay(-1)
@@ -103,7 +103,7 @@ public:
, m_passwordMaskDelayOverride(-1)
#endif
, m_keyboardScheme(0)
- , m_accessibleObject(0)
+ , m_accessibleObject(nullptr)
{
init(txt);
}
diff --git a/src/widgets/widgets/qwidgetresizehandler_p.h b/src/widgets/widgets/qwidgetresizehandler_p.h
index b87bbd6229..df3ac7cb8a 100644
--- a/src/widgets/widgets/qwidgetresizehandler_p.h
+++ b/src/widgets/widgets/qwidgetresizehandler_p.h
@@ -73,7 +73,7 @@ public:
Any = Move|Resize
};
- explicit QWidgetResizeHandler(QWidget *parent, QWidget *cw = 0);
+ explicit QWidgetResizeHandler(QWidget *parent, QWidget *cw = nullptr);
void setActive(bool b) { setActive(Any, b); }
void setActive(Action ac, bool b);
bool isActive() const { return isActive(Any); }
@@ -100,7 +100,7 @@ protected:
void keyPressEvent(QKeyEvent *e);
private:
- Q_DISABLE_COPY(QWidgetResizeHandler)
+ Q_DISABLE_COPY_MOVE(QWidgetResizeHandler)
enum MousePosition {
Nowhere,
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index ee757bf870..cad3a64749 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -57,9 +57,6 @@
#include <qtimer.h>
#include "private/qtextdocumentlayout_p.h"
#include "private/qabstracttextdocumentlayout_p.h"
-#if QT_CONFIG(textedit)
-#include "private/qtextedit_p.h"
-#endif
#include "qtextdocument.h"
#include "private/qtextdocument_p.h"
#include "qtextlist.h"
@@ -221,6 +218,14 @@ bool QWidgetTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e)
else if (e == QKeySequence::SelectPreviousLine) {
op = QTextCursor::Up;
mode = QTextCursor::KeepAnchor;
+ {
+ QTextBlock block = cursor.block();
+ QTextLine line = currentTextLine(cursor);
+ if (!block.previous().isValid()
+ && line.isValid()
+ && line.lineNumber() == 0)
+ op = QTextCursor::Start;
+ }
}
else if (e == QKeySequence::SelectNextLine) {
op = QTextCursor::Down;
@@ -489,6 +494,11 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString
formatCursor.select(QTextCursor::Document);
formatCursor.setCharFormat(charFormatForInsertion);
formatCursor.endEditBlock();
+#if QT_CONFIG(textmarkdownreader)
+ } else if (format == Qt::MarkdownText) {
+ doc->setMarkdown(text);
+ doc->setUndoRedoEnabled(false);
+#endif
} else {
#ifndef QT_NO_TEXTHTMLPARSER
doc->setHtml(text);
@@ -1192,6 +1202,14 @@ void QWidgetTextControl::setPlainText(const QString &text)
d->setContent(Qt::PlainText, text);
}
+#if QT_CONFIG(textmarkdownreader)
+void QWidgetTextControl::setMarkdown(const QString &text)
+{
+ Q_D(QWidgetTextControl);
+ d->setContent(Qt::MarkdownText, text);
+}
+#endif
+
void QWidgetTextControl::setHtml(const QString &text)
{
Q_D(QWidgetTextControl);
@@ -1360,15 +1378,8 @@ process:
QVariant QWidgetTextControl::loadResource(int type, const QUrl &name)
{
-#if !QT_CONFIG(textedit)
Q_UNUSED(type);
Q_UNUSED(name);
-#else
- if (QTextEdit *textEdit = qobject_cast<QTextEdit *>(parent())) {
- QUrl resolvedName = textEdit->d_func()->resolveUrl(name);
- return textEdit->loadResource(type, resolvedName);
- }
-#endif
return QVariant();
}
@@ -1573,6 +1584,11 @@ void QWidgetTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton butto
e->ignore();
return;
}
+ bool wasValid = blockWithMarkerUnderMouse.isValid();
+ blockWithMarkerUnderMouse = q->blockWithMarkerAt(pos);
+ if (wasValid != blockWithMarkerUnderMouse.isValid())
+ emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
+
cursorIsFocusIndicator = false;
const QTextCursor oldSelection = cursor;
@@ -1591,6 +1607,8 @@ void QWidgetTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton butto
selectedBlockOnTrippleClick = cursor;
anchorOnMousePress = QString();
+ blockWithMarkerUnderMouse = QTextBlock();
+ emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
trippleClickTimer.stop();
} else {
@@ -1730,6 +1748,11 @@ void QWidgetTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button
}
selectionChanged(true);
repaintOldAndNewSelection(oldSelection);
+ } else {
+ bool wasValid = blockWithMarkerUnderMouse.isValid();
+ blockWithMarkerUnderMouse = q->blockWithMarkerAt(mousePos);
+ if (wasValid != blockWithMarkerUnderMouse.isValid())
+ emit q->blockMarkerHovered(blockWithMarkerUnderMouse);
}
sendMouseEventToInputContext(e, QEvent::MouseMove, button, mousePos, modifiers, buttons, globalPos);
@@ -1779,6 +1802,26 @@ void QWidgetTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton but
emit q->microFocusChanged();
}
+ // toggle any checkbox that the user clicks
+ if ((interactionFlags & Qt::TextEditable) && (button & Qt::LeftButton) &&
+ (blockWithMarkerUnderMouse.isValid()) && !cursor.hasSelection()) {
+ QTextBlock markerBlock = q->blockWithMarkerAt(pos);
+ if (markerBlock == blockWithMarkerUnderMouse) {
+ auto fmt = blockWithMarkerUnderMouse.blockFormat();
+ switch (fmt.marker()) {
+ case QTextBlockFormat::Unchecked :
+ fmt.setMarker(QTextBlockFormat::Checked);
+ break;
+ case QTextBlockFormat::Checked:
+ fmt.setMarker(QTextBlockFormat::Unchecked);
+ break;
+ default:
+ break;
+ }
+ cursor.setBlockFormat(fmt);
+ }
+ }
+
if (interactionFlags & Qt::LinksAccessibleByMouse) {
if (!(button & Qt::LeftButton))
return;
@@ -2377,6 +2420,12 @@ QString QWidgetTextControl::anchorAtCursor() const
return d->anchorForCursor(d->cursor);
}
+QTextBlock QWidgetTextControl::blockWithMarkerAt(const QPointF &pos) const
+{
+ Q_D(const QWidgetTextControl);
+ return d->doc->documentLayout()->blockWithMarkerAt(pos);
+}
+
bool QWidgetTextControl::overwriteMode() const
{
Q_D(const QWidgetTextControl);
@@ -2433,7 +2482,7 @@ void QWidgetTextControl::setExtraSelections(const QList<QTextEdit::ExtraSelectio
QHash<int, int> hash;
for (int i = 0; i < d->extraSelections.count(); ++i) {
const QAbstractTextDocumentLayout::Selection &esel = d->extraSelections.at(i);
- hash.insertMulti(esel.cursor.anchor(), i);
+ hash.insert(esel.cursor.anchor(), i);
}
for (int i = 0; i < selections.count(); ++i) {
@@ -3101,6 +3150,19 @@ bool QWidgetTextControl::find(const QRegExp &exp, QTextDocument::FindFlags optio
}
#endif
+#if QT_CONFIG(regularexpression)
+bool QWidgetTextControl::find(const QRegularExpression &exp, QTextDocument::FindFlags options)
+{
+ Q_D(QWidgetTextControl);
+ QTextCursor search = d->doc->find(exp, d->cursor, options);
+ if (search.isNull())
+ return false;
+
+ setTextCursor(search);
+ return true;
+}
+#endif
+
QString QWidgetTextControl::toPlainText() const
{
return document()->toPlainText();
@@ -3113,6 +3175,13 @@ QString QWidgetTextControl::toHtml() const
}
#endif
+#ifndef QT_NO_TEXTHTMLPARSER
+QString QWidgetTextControl::toMarkdown(QTextDocument::MarkdownFeatures features) const
+{
+ return document()->toMarkdown(features);
+}
+#endif
+
void QWidgetTextControlPrivate::append(const QString &text, Qt::TextFormat format)
{
QTextCursor tmp(doc);
diff --git a/src/widgets/widgets/qwidgettextcontrol_p.h b/src/widgets/widgets/qwidgettextcontrol_p.h
index 4b2acbd934..59bf5466e6 100644
--- a/src/widgets/widgets/qwidgettextcontrol_p.h
+++ b/src/widgets/widgets/qwidgettextcontrol_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -80,6 +80,7 @@ class QMenu;
class QWidgetTextControlPrivate;
class QAbstractScrollArea;
class QEvent;
+class QRegularExpression;
class QTimerEvent;
class Q_WIDGETS_EXPORT QWidgetTextControl : public QInputControl
@@ -96,9 +97,9 @@ class Q_WIDGETS_EXPORT QWidgetTextControl : public QInputControl
Q_PROPERTY(bool openExternalLinks READ openExternalLinks WRITE setOpenExternalLinks)
Q_PROPERTY(bool ignoreUnusedNavigationEvents READ ignoreUnusedNavigationEvents WRITE setIgnoreUnusedNavigationEvents)
public:
- explicit QWidgetTextControl(QObject *parent = 0);
- explicit QWidgetTextControl(const QString &text, QObject *parent = 0);
- explicit QWidgetTextControl(QTextDocument *doc, QObject *parent = 0);
+ explicit QWidgetTextControl(QObject *parent = nullptr);
+ explicit QWidgetTextControl(const QString &text, QObject *parent = nullptr);
+ explicit QWidgetTextControl(QTextDocument *doc, QObject *parent = nullptr);
virtual ~QWidgetTextControl();
void setDocument(QTextDocument *document);
@@ -115,15 +116,21 @@ public:
void setCurrentCharFormat(const QTextCharFormat &format);
QTextCharFormat currentCharFormat() const;
- bool find(const QString &exp, QTextDocument::FindFlags options = 0);
+ bool find(const QString &exp, QTextDocument::FindFlags options = nullptr);
#ifndef QT_NO_REGEXP
- bool find(const QRegExp &exp, QTextDocument::FindFlags options = 0);
+ bool find(const QRegExp &exp, QTextDocument::FindFlags options = nullptr);
+#endif
+#if QT_CONFIG(regularexpression)
+ bool find(const QRegularExpression &exp, QTextDocument::FindFlags options = nullptr);
#endif
QString toPlainText() const;
#ifndef QT_NO_TEXTHTMLPARSER
QString toHtml() const;
#endif
+#if QT_CONFIG(textmarkdownwriter)
+ QString toMarkdown(QTextDocument::MarkdownFeatures features = QTextDocument::MarkdownDialectGitHub) const;
+#endif
virtual void ensureCursorVisible();
@@ -143,6 +150,8 @@ public:
QString anchorAtCursor() const;
+ QTextBlock blockWithMarkerAt(const QPointF &pos) const;
+
bool overwriteMode() const;
void setOverwriteMode(bool overwrite);
@@ -190,6 +199,9 @@ public:
public Q_SLOTS:
void setPlainText(const QString &text);
+#if QT_CONFIG(textmarkdownreader)
+ void setMarkdown(const QString &text);
+#endif
void setHtml(const QString &text);
#ifndef QT_NO_CLIPBOARD
@@ -232,6 +244,7 @@ Q_SIGNALS:
void microFocusChanged();
void linkActivated(const QString &link);
void linkHovered(const QString &);
+ void blockMarkerHovered(const QTextBlock &block);
void modificationChanged(bool m);
public:
@@ -239,11 +252,11 @@ public:
QPalette palette() const;
void setPalette(const QPalette &pal);
- virtual void processEvent(QEvent *e, const QMatrix &matrix, QWidget *contextWidget = 0);
- void processEvent(QEvent *e, const QPointF &coordinateOffset = QPointF(), QWidget *contextWidget = 0);
+ virtual void processEvent(QEvent *e, const QMatrix &matrix, QWidget *contextWidget = nullptr);
+ void processEvent(QEvent *e, const QPointF &coordinateOffset = QPointF(), QWidget *contextWidget = nullptr);
// control methods
- void drawContents(QPainter *painter, const QRectF &rect = QRectF(), QWidget *widget = 0);
+ void drawContents(QPainter *painter, const QRectF &rect = QRectF(), QWidget *widget = nullptr);
void setFocus(bool focus, Qt::FocusReason = Qt::OtherFocusReason);
@@ -263,7 +276,7 @@ protected:
virtual bool event(QEvent *e) override;
private:
- Q_DISABLE_COPY(QWidgetTextControl)
+ Q_DISABLE_COPY_MOVE(QWidgetTextControl)
Q_PRIVATE_SLOT(d_func(), void _q_updateCurrentCharFormatAndSelection())
Q_PRIVATE_SLOT(d_func(), void _q_emitCursorPosChanged(const QTextCursor &))
Q_PRIVATE_SLOT(d_func(), void _q_deleteSelected())
diff --git a/src/widgets/widgets/qwidgettextcontrol_p_p.h b/src/widgets/widgets/qwidgettextcontrol_p_p.h
index 232dab180f..c77a31bedf 100644
--- a/src/widgets/widgets/qwidgettextcontrol_p_p.h
+++ b/src/widgets/widgets/qwidgettextcontrol_p_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -55,6 +55,7 @@
#include "QtGui/qtextdocumentfragment.h"
#include "QtGui/qtextcursor.h"
#include "QtGui/qtextformat.h"
+#include "QtGui/qtextobject.h"
#if QT_CONFIG(menu)
#include "QtWidgets/qmenu.h"
#endif
@@ -89,9 +90,9 @@ public:
void createAutoBulletList();
void init(Qt::TextFormat format = Qt::RichText, const QString &text = QString(),
- QTextDocument *document = 0);
+ QTextDocument *document = nullptr);
void setContent(Qt::TextFormat format = Qt::RichText, const QString &text = QString(),
- QTextDocument *document = 0);
+ QTextDocument *document = nullptr);
void startDrag();
void paste(const QMimeData *source);
@@ -227,6 +228,7 @@ public:
QString highlightedAnchor; // Anchor below cursor
QString anchorOnMousePress;
+ QTextBlock blockWithMarkerUnderMouse;
bool hadSelectionOnMousePress;
bool ignoreUnusedNavigationEvents;
diff --git a/src/winmain/winmain.pro b/src/winmain/winmain.pro
index 9cb6ab0c59..1f54c846ec 100644
--- a/src/winmain/winmain.pro
+++ b/src/winmain/winmain.pro
@@ -23,7 +23,7 @@ winrt {
} else {
CONFIG -= qt
SOURCES = qtmain_win.cpp
- LIBS += -lshell32
+ QMAKE_USE_PRIVATE += shell32
}
load(qt_installs)
diff --git a/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp b/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp
index 2d18e0e537..f7d81f676f 100644
--- a/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp
+++ b/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp
@@ -74,7 +74,7 @@ QDomNode n = d.firstChild();
while (!n.isNull()) {
if (n.isElement()) {
QDomElement e = n.toElement();
- cout << "Element name: " << e.tagName() << endl;
+ cout << "Element name: " << e.tagName() << Qt::endl;
break;
}
n = n.nextSibling();
@@ -126,10 +126,10 @@ QDomElement element4 = document.createElement("MyElement");
QDomElement e = //...
//...
QDomAttr a = e.attributeNode("href");
-cout << a.value() << endl; // prints "http://qt-project.org"
+cout << a.value() << Qt::endl; // prints "http://qt-project.org"
a.setValue("http://qt-project.org/doc"); // change the node's attribute
QDomAttr a2 = e.attributeNode("href");
-cout << a2.value() << endl; // prints "http://qt-project.org/doc"
+cout << a2.value() << Qt::endl; // prints "http://qt-project.org/doc"
//! [8]
@@ -201,7 +201,7 @@ QDomNode n = docElem.firstChild();
while(!n.isNull()) {
QDomElement e = n.toElement(); // try to convert the node to an element.
if(!e.isNull()) {
- cout << qPrintable(e.tagName()) << endl; // the node really is an element.
+ cout << qPrintable(e.tagName()) << Qt::endl; // the node really is an element.
}
n = n.nextSibling();
}
diff --git a/src/xml/doc/src/dontdocument.qdoc b/src/xml/doc/src/dontdocument.qdoc
new file mode 100644
index 0000000000..0193ace4b4
--- /dev/null
+++ b/src/xml/doc/src/dontdocument.qdoc
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+/*!
+ \dontdocument (QTypeInfo)
+*/
diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp
index 5893d8448e..8d232237bf 100644
--- a/src/xml/dom/qdom.cpp
+++ b/src/xml/dom/qdom.cpp
@@ -48,7 +48,9 @@
#include <qhash.h>
#include <qiodevice.h>
#include <qlist.h>
-#include <qregexp.h>
+#if QT_CONFIG(regularexpression)
+#include <qregularexpression.h>
+#endif
#if QT_CONFIG(textcodec)
#include <qtextcodec.h>
#endif
@@ -134,7 +136,7 @@ public:
class QDomNodePrivate
{
public:
- QDomNodePrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = 0);
+ QDomNodePrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = nullptr);
QDomNodePrivate(QDomNodePrivate* n, bool deep);
virtual ~QDomNodePrivate();
@@ -157,11 +159,11 @@ public:
virtual void normalize();
virtual void clear();
- inline QDomNodePrivate* parent() const { return hasParent ? ownerNode : 0; }
+ inline QDomNodePrivate* parent() const { return hasParent ? ownerNode : nullptr; }
inline void setParent(QDomNodePrivate *p) { ownerNode = p; hasParent = true; }
void setNoParent() {
- ownerNode = hasParent ? (QDomNodePrivate*)ownerDocument() : 0;
+ ownerNode = hasParent ? (QDomNodePrivate*)ownerDocument() : nullptr;
hasParent = false;
}
@@ -287,7 +289,7 @@ public:
class QDomDocumentTypePrivate : public QDomNodePrivate
{
public:
- QDomDocumentTypePrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = 0);
+ QDomDocumentTypePrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = nullptr);
QDomDocumentTypePrivate(QDomDocumentTypePrivate* n, bool deep);
~QDomDocumentTypePrivate();
void init();
@@ -315,7 +317,7 @@ public:
class QDomDocumentFragmentPrivate : public QDomNodePrivate
{
public:
- QDomDocumentFragmentPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = 0);
+ QDomDocumentFragmentPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = nullptr);
QDomDocumentFragmentPrivate(QDomNodePrivate* n, bool deep);
// Reimplemented from QDomNodePrivate
@@ -905,7 +907,7 @@ QDomImplementationPrivate* QDomImplementationPrivate::clone()
*/
QDomImplementation::QDomImplementation()
{
- impl = 0;
+ impl = nullptr;
}
/*!
@@ -1034,7 +1036,7 @@ QDomDocumentType QDomImplementation::createDocumentType(const QString& qName, co
if (!ok)
return QDomDocumentType();
- QDomDocumentTypePrivate *dt = new QDomDocumentTypePrivate(0);
+ QDomDocumentTypePrivate *dt = new QDomDocumentTypePrivate(nullptr);
dt->name = fixedName;
if (systemId.isNull()) {
dt->publicId.clear();
@@ -1068,7 +1070,7 @@ QDomDocument QDomImplementation::createDocument(const QString& nsURI, const QStr
*/
bool QDomImplementation::isNull()
{
- return (impl == 0);
+ return (impl == nullptr);
}
/*!
@@ -1242,14 +1244,14 @@ void QDomNodeListPrivate::createList()
QDomNodePrivate* QDomNodeListPrivate::item(int index)
{
if (!node_impl)
- return 0;
+ return nullptr;
const QDomDocumentPrivate *const doc = node_impl->ownerDocument();
if (!doc || timestamp != doc->nodeListTime)
createList();
if (index >= list.size())
- return 0;
+ return nullptr;
return list.at(index);
}
@@ -1303,13 +1305,13 @@ int QDomNodeListPrivate::length() const
Creates an empty node list.
*/
QDomNodeList::QDomNodeList()
+ : impl(nullptr)
{
- impl = 0;
}
QDomNodeList::QDomNodeList(QDomNodeListPrivate* p)
+ : impl(p)
{
- impl = p;
}
/*!
@@ -1441,10 +1443,10 @@ QDomNodePrivate::QDomNodePrivate(QDomDocumentPrivate *doc, QDomNodePrivate *par)
setParent(par);
else
setOwnerDocument(doc);
- prev = 0;
- next = 0;
- first = 0;
- last = 0;
+ prev = nullptr;
+ next = nullptr;
+ first = nullptr;
+ last = nullptr;
createdWithDom1Interface = true;
lineNumber = -1;
columnNumber = -1;
@@ -1453,10 +1455,10 @@ QDomNodePrivate::QDomNodePrivate(QDomDocumentPrivate *doc, QDomNodePrivate *par)
QDomNodePrivate::QDomNodePrivate(QDomNodePrivate *n, bool deep) : ref(1)
{
setOwnerDocument(n->ownerDocument());
- prev = 0;
- next = 0;
- first = 0;
- last = 0;
+ prev = nullptr;
+ next = nullptr;
+ first = nullptr;
+ last = nullptr;
name = n->name;
value = n->value;
@@ -1486,8 +1488,8 @@ QDomNodePrivate::~QDomNodePrivate()
p->setNoParent();
p = n;
}
- first = 0;
- last = 0;
+ first = nullptr;
+ last = nullptr;
}
void QDomNodePrivate::clear()
@@ -1501,8 +1503,8 @@ void QDomNodePrivate::clear()
delete p;
p = n;
}
- first = 0;
- last = 0;
+ first = nullptr;
+ last = nullptr;
}
QDomNodePrivate* QDomNodePrivate::namedItem(const QString &n)
@@ -1513,7 +1515,7 @@ QDomNodePrivate* QDomNodePrivate::namedItem(const QString &n)
return p;
p = p->next;
}
- return 0;
+ return nullptr;
}
@@ -1521,15 +1523,15 @@ QDomNodePrivate* QDomNodePrivate::insertBefore(QDomNodePrivate* newChild, QDomNo
{
// Error check
if (!newChild)
- return 0;
+ return nullptr;
// Error check
if (newChild == refChild)
- return 0;
+ return nullptr;
// Error check
if (refChild && refChild->parent() != this)
- return 0;
+ return nullptr;
// "mark lists as dirty"
QDomDocumentPrivate *const doc = ownerDocument();
@@ -1540,7 +1542,7 @@ QDomNodePrivate* QDomNodePrivate::insertBefore(QDomNodePrivate* newChild, QDomNo
// all elements of the fragment instead of the fragment itself.
if (newChild->isDocumentFragment()) {
// Fragment is empty ?
- if (newChild->first == 0)
+ if (newChild->first == nullptr)
return newChild;
// New parent
@@ -1551,7 +1553,7 @@ QDomNodePrivate* QDomNodePrivate::insertBefore(QDomNodePrivate* newChild, QDomNo
}
// Insert at the beginning ?
- if (!refChild || refChild->prev == 0) {
+ if (!refChild || refChild->prev == nullptr) {
if (first)
first->prev = newChild->last;
newChild->last->next = first;
@@ -1570,8 +1572,8 @@ QDomNodePrivate* QDomNodePrivate::insertBefore(QDomNodePrivate* newChild, QDomNo
// does not decrease the reference.
// Remove the nodes from the fragment
- newChild->first = 0;
- newChild->last = 0;
+ newChild->first = nullptr;
+ newChild->last = nullptr;
return newChild;
}
@@ -1594,7 +1596,7 @@ QDomNodePrivate* QDomNodePrivate::insertBefore(QDomNodePrivate* newChild, QDomNo
return newChild;
}
- if (refChild->prev == 0) {
+ if (refChild->prev == nullptr) {
if (first)
first->prev = newChild;
newChild->next = first;
@@ -1616,15 +1618,15 @@ QDomNodePrivate* QDomNodePrivate::insertAfter(QDomNodePrivate* newChild, QDomNod
{
// Error check
if (!newChild)
- return 0;
+ return nullptr;
// Error check
if (newChild == refChild)
- return 0;
+ return nullptr;
// Error check
if (refChild && refChild->parent() != this)
- return 0;
+ return nullptr;
// "mark lists as dirty"
QDomDocumentPrivate *const doc = ownerDocument();
@@ -1635,7 +1637,7 @@ QDomNodePrivate* QDomNodePrivate::insertAfter(QDomNodePrivate* newChild, QDomNod
// all elements of the fragment instead of the fragment itself.
if (newChild->isDocumentFragment()) {
// Fragment is empty ?
- if (newChild->first == 0)
+ if (newChild->first == nullptr)
return newChild;
// New parent
@@ -1646,7 +1648,7 @@ QDomNodePrivate* QDomNodePrivate::insertAfter(QDomNodePrivate* newChild, QDomNod
}
// Insert at the end
- if (!refChild || refChild->next == 0) {
+ if (!refChild || refChild->next == nullptr) {
if (last)
last->next = newChild->first;
newChild->first->prev = last;
@@ -1664,8 +1666,8 @@ QDomNodePrivate* QDomNodePrivate::insertAfter(QDomNodePrivate* newChild, QDomNod
// does not decrease the reference.
// Remove the nodes from the fragment
- newChild->first = 0;
- newChild->last = 0;
+ newChild->first = nullptr;
+ newChild->last = nullptr;
return newChild;
}
@@ -1690,7 +1692,7 @@ QDomNodePrivate* QDomNodePrivate::insertAfter(QDomNodePrivate* newChild, QDomNod
return newChild;
}
- if (refChild->next == 0) {
+ if (refChild->next == nullptr) {
if (last)
last->next = newChild;
newChild->prev = last;
@@ -1711,11 +1713,11 @@ QDomNodePrivate* QDomNodePrivate::insertAfter(QDomNodePrivate* newChild, QDomNod
QDomNodePrivate* QDomNodePrivate::replaceChild(QDomNodePrivate* newChild, QDomNodePrivate* oldChild)
{
if (!newChild || !oldChild)
- return 0;
+ return nullptr;
if (oldChild->parent() != this)
- return 0;
+ return nullptr;
if (newChild == oldChild)
- return 0;
+ return nullptr;
// mark lists as dirty
QDomDocumentPrivate *const doc = ownerDocument();
@@ -1726,7 +1728,7 @@ QDomNodePrivate* QDomNodePrivate::replaceChild(QDomNodePrivate* newChild, QDomNo
// all elements of the fragment instead of the fragment itself.
if (newChild->isDocumentFragment()) {
// Fragment is empty ?
- if (newChild->first == 0)
+ if (newChild->first == nullptr)
return newChild;
// New parent
@@ -1751,15 +1753,15 @@ QDomNodePrivate* QDomNodePrivate::replaceChild(QDomNodePrivate* newChild, QDomNo
last = newChild->last;
oldChild->setNoParent();
- oldChild->next = 0;
- oldChild->prev = 0;
+ oldChild->next = nullptr;
+ oldChild->prev = nullptr;
// No need to increase the reference since QDomDocumentFragment
// does not decrease the reference.
// Remove the nodes from the fragment
- newChild->first = 0;
- newChild->last = 0;
+ newChild->first = nullptr;
+ newChild->last = nullptr;
// We are no longer interested in the old node
if (oldChild)
@@ -1792,8 +1794,8 @@ QDomNodePrivate* QDomNodePrivate::replaceChild(QDomNodePrivate* newChild, QDomNo
last = newChild;
oldChild->setNoParent();
- oldChild->next = 0;
- oldChild->prev = 0;
+ oldChild->next = nullptr;
+ oldChild->prev = nullptr;
// We are no longer interested in the old node
if (oldChild)
@@ -1806,7 +1808,7 @@ QDomNodePrivate* QDomNodePrivate::removeChild(QDomNodePrivate* oldChild)
{
// Error check
if (oldChild->parent() != this)
- return 0;
+ return nullptr;
// "mark lists as dirty"
QDomDocumentPrivate *const doc = ownerDocument();
@@ -1815,8 +1817,8 @@ QDomNodePrivate* QDomNodePrivate::removeChild(QDomNodePrivate* oldChild)
// Perhaps oldChild was just created with "createElement" or that. In this case
// its parent is QDomDocument but it is not part of the documents child list.
- if (oldChild->next == 0 && oldChild->prev == 0 && first != oldChild)
- return 0;
+ if (oldChild->next == nullptr && oldChild->prev == nullptr && first != oldChild)
+ return nullptr;
if (oldChild->next)
oldChild->next->prev = oldChild->prev;
@@ -1829,8 +1831,8 @@ QDomNodePrivate* QDomNodePrivate::removeChild(QDomNodePrivate* oldChild)
first = oldChild->next;
oldChild->setNoParent();
- oldChild->next = 0;
- oldChild->prev = 0;
+ oldChild->next = nullptr;
+ oldChild->prev = nullptr;
// We are no longer interested in the old node
oldChild->ref.deref();
@@ -1841,7 +1843,7 @@ QDomNodePrivate* QDomNodePrivate::removeChild(QDomNodePrivate* oldChild)
QDomNodePrivate* QDomNodePrivate::appendChild(QDomNodePrivate* newChild)
{
// No reference manipulation needed. Done in insertAfter.
- return insertAfter(newChild, 0);
+ return insertAfter(newChild, nullptr);
}
QDomDocumentPrivate* QDomNodePrivate::ownerDocument()
@@ -1867,7 +1869,7 @@ QDomNodePrivate* QDomNodePrivate::cloneNode(bool deep)
static void qNormalizeNode(QDomNodePrivate* n)
{
QDomNodePrivate* p = n->first;
- QDomTextPrivate* t = 0;
+ QDomTextPrivate* t = nullptr;
while (p) {
if (p->isText()) {
@@ -1882,7 +1884,7 @@ static void qNormalizeNode(QDomNodePrivate* n)
}
} else {
p = p->next;
- t = 0;
+ t = nullptr;
}
}
}
@@ -1949,7 +1951,7 @@ void QDomNodePrivate::setLocation(int lineNumber, int columnNumber)
which return a QDomNode, e.g. firstChild(). You can make an
independent (deep) copy of the node with cloneNode().
- A QDomNode can be null, much like a null pointer. Creating a copy
+ A QDomNode can be null, much like \nullptr. Creating a copy
of a null node results in another null node. It is not
possible to modify a null node, but it is possible to assign another,
possibly non-null node to it. In this case, the copy of the null node
@@ -2007,8 +2009,8 @@ void QDomNodePrivate::setLocation(int lineNumber, int columnNumber)
Constructs a \l{isNull()}{null} node.
*/
QDomNode::QDomNode()
+ : impl(nullptr)
{
- impl = 0;
}
/*!
@@ -2617,7 +2619,7 @@ bool QDomNode::hasChildNodes() const
{
if (!impl)
return false;
- return IMPL->first != 0;
+ return IMPL->first != nullptr;
}
/*!
@@ -2626,7 +2628,7 @@ bool QDomNode::hasChildNodes() const
*/
bool QDomNode::isNull() const
{
- return (impl == 0);
+ return (impl == nullptr);
}
/*!
@@ -2639,7 +2641,7 @@ void QDomNode::clear()
{
if (impl && !impl->ref.deref())
delete impl;
- impl = 0;
+ impl = nullptr;
}
/*!
@@ -3092,13 +3094,13 @@ QDomNodePrivate* QDomNamedNodeMapPrivate::namedItemNS(const QString& nsURI, cons
return n;
}
}
- return 0;
+ return nullptr;
}
QDomNodePrivate* QDomNamedNodeMapPrivate::setNamedItem(QDomNodePrivate* arg)
{
if (readonly || !arg)
- return 0;
+ return nullptr;
if (appendToParent)
return parent->appendChild(arg);
@@ -3113,7 +3115,7 @@ QDomNodePrivate* QDomNamedNodeMapPrivate::setNamedItem(QDomNodePrivate* arg)
QDomNodePrivate* QDomNamedNodeMapPrivate::setNamedItemNS(QDomNodePrivate* arg)
{
if (readonly || !arg)
- return 0;
+ return nullptr;
if (appendToParent)
return parent->appendChild(arg);
@@ -3134,11 +3136,11 @@ QDomNodePrivate* QDomNamedNodeMapPrivate::setNamedItemNS(QDomNodePrivate* arg)
QDomNodePrivate* QDomNamedNodeMapPrivate::removeNamedItem(const QString& name)
{
if (readonly)
- return 0;
+ return nullptr;
QDomNodePrivate* p = namedItem(name);
- if (p == 0)
- return 0;
+ if (p == nullptr)
+ return nullptr;
if (appendToParent)
return parent->removeChild(p);
@@ -3151,7 +3153,7 @@ QDomNodePrivate* QDomNamedNodeMapPrivate::removeNamedItem(const QString& name)
QDomNodePrivate* QDomNamedNodeMapPrivate::item(int index) const
{
if (index >= length() || index < 0)
- return 0;
+ return nullptr;
return *(map.constBegin() + index);
}
@@ -3162,12 +3164,12 @@ int QDomNamedNodeMapPrivate::length() const
bool QDomNamedNodeMapPrivate::contains(const QString& name) const
{
- return map.value(name) != 0;
+ return map.contains(name);
}
bool QDomNamedNodeMapPrivate::containsNS(const QString& nsURI, const QString & localName) const
{
- return namedItemNS(nsURI, localName) != 0;
+ return namedItemNS(nsURI, localName) != nullptr;
}
/**************************************************************
@@ -3220,8 +3222,8 @@ bool QDomNamedNodeMapPrivate::containsNS(const QString& nsURI, const QString & l
Constructs an empty named node map.
*/
QDomNamedNodeMap::QDomNamedNodeMap()
+ : impl(nullptr)
{
- impl = 0;
}
/*!
@@ -3568,7 +3570,7 @@ QDomNodePrivate* QDomDocumentTypePrivate::removeChild(QDomNodePrivate* oldChild)
QDomNodePrivate* QDomDocumentTypePrivate::appendChild(QDomNodePrivate* newChild)
{
- return insertAfter(newChild, 0);
+ return insertAfter(newChild, nullptr);
}
static QString quotedValue(const QString &data)
@@ -3596,7 +3598,7 @@ void QDomDocumentTypePrivate::save(QTextStream& s, int, int indent) const
}
if (entities->length()>0 || notations->length()>0) {
- s << " [" << endl;
+ s << " [" << Qt::endl;
QHash<QString, QDomNodePrivate *>::const_iterator it2 = notations->map.constBegin();
for (; it2 != notations->map.constEnd(); ++it2)
@@ -3609,7 +3611,7 @@ void QDomDocumentTypePrivate::save(QTextStream& s, int, int indent) const
s << ']';
}
- s << '>' << endl;
+ s << '>' << Qt::endl;
}
/**************************************************************
@@ -4113,7 +4115,7 @@ QDomAttrPrivate::QDomAttrPrivate(QDomAttrPrivate* n, bool deep)
void QDomAttrPrivate::setNodeValue(const QString& v)
{
value = v;
- QDomTextPrivate *t = new QDomTextPrivate(0, this, v);
+ QDomTextPrivate *t = new QDomTextPrivate(nullptr, this, v);
// keep the refcount balanced: appendChild() does a ref anyway.
t->ref.deref();
if (first) {
@@ -4487,7 +4489,7 @@ void QDomElementPrivate::setAttributeNS(const QString& nsURI, const QString& qNa
void QDomElementPrivate::removeAttribute(const QString& aname)
{
QDomNodePrivate* p = m_attr->removeNamedItem(aname);
- if (p && p->ref.load() == 0)
+ if (p && p->ref.loadRelaxed() == 0)
delete p;
}
@@ -4515,7 +4517,7 @@ QDomAttrPrivate* QDomElementPrivate::setAttributeNode(QDomAttrPrivate* newAttr)
QDomAttrPrivate* QDomElementPrivate::setAttributeNodeNS(QDomAttrPrivate* newAttr)
{
- QDomNodePrivate* n = 0;
+ QDomNodePrivate* n = nullptr;
if (!newAttr->prefix.isNull())
n = m_attr->namedItemNS(newAttr->namespaceURI, newAttr->name);
@@ -4625,7 +4627,7 @@ void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const
/* -1 disables new lines. */
if (indent != -1)
- s << endl;
+ s << Qt::endl;
}
QDomNodePrivate::save(s, depth + 1, indent); if (!last->isText())
s << QString(indent < 1 ? 0 : depth * indent, QLatin1Char(' '));
@@ -4637,7 +4639,7 @@ void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const
if (!(next && next->isText())) {
/* -1 disables new lines. */
if (indent != -1)
- s << endl;
+ s << Qt::endl;
}
}
@@ -5181,11 +5183,11 @@ QDomNodePrivate* QDomTextPrivate::cloneNode(bool deep)
QDomTextPrivate* QDomTextPrivate::splitText(int offset)
{
if (!parent()) {
- qWarning("QDomText::splitText The node has no parent. So I can not split");
- return 0;
+ qWarning("QDomText::splitText The node has no parent. So I cannot split");
+ return nullptr;
}
- QDomTextPrivate* t = new QDomTextPrivate(ownerDocument(), 0, value.mid(offset));
+ QDomTextPrivate* t = new QDomTextPrivate(ownerDocument(), nullptr, value.mid(offset));
value.truncate(offset);
parent()->insertAfter(t, this);
@@ -5327,7 +5329,7 @@ void QDomCommentPrivate::save(QTextStream& s, int depth, int indent) const
s << "-->";
if (!(next && next->isText()))
- s << endl;
+ s << Qt::endl;
}
/**************************************************************
@@ -5550,7 +5552,7 @@ void QDomNotationPrivate::save(QTextStream& s, int, int) const
} else {
s << "SYSTEM " << quotedValue(m_sys);
}
- s << '>' << endl;
+ s << '>' << Qt::endl;
}
/**************************************************************
@@ -5731,7 +5733,7 @@ void QDomEntityPrivate::save(QTextStream& s, int, int) const
_name = QLatin1String("% ") + _name.mid(1);
if (m_sys.isNull() && m_pub.isNull()) {
- s << "<!ENTITY " << _name << " \"" << encodeEntity(value.toUtf8()) << "\">" << endl;
+ s << "<!ENTITY " << _name << " \"" << encodeEntity(value.toUtf8()) << "\">" << Qt::endl;
} else {
s << "<!ENTITY " << _name << ' ';
if (m_pub.isNull()) {
@@ -5742,7 +5744,7 @@ void QDomEntityPrivate::save(QTextStream& s, int, int) const
if (! m_notationName.isNull()) {
s << " NDATA " << m_notationName;
}
- s << '>' << endl;
+ s << '>' << Qt::endl;
}
}
@@ -6012,7 +6014,7 @@ QDomNodePrivate* QDomProcessingInstructionPrivate::cloneNode(bool deep)
void QDomProcessingInstructionPrivate::save(QTextStream& s, int, int) const
{
- s << "<?" << name << ' ' << value << "?>" << endl;
+ s << "<?" << name << ' ' << value << "?>" << Qt::endl;
}
/**************************************************************
@@ -6142,7 +6144,7 @@ void QDomProcessingInstruction::setData(const QString& d)
**************************************************************/
QDomDocumentPrivate::QDomDocumentPrivate()
- : QDomNodePrivate(0),
+ : QDomNodePrivate(nullptr),
impl(new QDomImplementationPrivate),
nodeListTime(1)
{
@@ -6153,7 +6155,7 @@ QDomDocumentPrivate::QDomDocumentPrivate()
}
QDomDocumentPrivate::QDomDocumentPrivate(const QString& aname)
- : QDomNodePrivate(0),
+ : QDomNodePrivate(nullptr),
impl(new QDomImplementationPrivate),
nodeListTime(1)
{
@@ -6165,11 +6167,11 @@ QDomDocumentPrivate::QDomDocumentPrivate(const QString& aname)
}
QDomDocumentPrivate::QDomDocumentPrivate(QDomDocumentTypePrivate* dt)
- : QDomNodePrivate(0),
+ : QDomNodePrivate(nullptr),
impl(new QDomImplementationPrivate),
nodeListTime(1)
{
- if (dt != 0) {
+ if (dt != nullptr) {
type = dt;
} else {
type = new QDomDocumentTypePrivate(this, this);
@@ -6265,9 +6267,9 @@ QDomElementPrivate* QDomDocumentPrivate::createElement(const QString &tagName)
bool ok;
QString fixedName = fixedXmlName(tagName, &ok);
if (!ok)
- return 0;
+ return nullptr;
- QDomElementPrivate *e = new QDomElementPrivate(this, 0, fixedName);
+ QDomElementPrivate *e = new QDomElementPrivate(this, nullptr, fixedName);
e->ref.deref();
return e;
}
@@ -6277,16 +6279,16 @@ QDomElementPrivate* QDomDocumentPrivate::createElementNS(const QString &nsURI, c
bool ok;
QString fixedName = fixedXmlName(qName, &ok, true);
if (!ok)
- return 0;
+ return nullptr;
- QDomElementPrivate *e = new QDomElementPrivate(this, 0, nsURI, fixedName);
+ QDomElementPrivate *e = new QDomElementPrivate(this, nullptr, nsURI, fixedName);
e->ref.deref();
return e;
}
QDomDocumentFragmentPrivate* QDomDocumentPrivate::createDocumentFragment()
{
- QDomDocumentFragmentPrivate *f = new QDomDocumentFragmentPrivate(this, (QDomNodePrivate*)0);
+ QDomDocumentFragmentPrivate *f = new QDomDocumentFragmentPrivate(this, (QDomNodePrivate*)nullptr);
f->ref.deref();
return f;
}
@@ -6296,9 +6298,9 @@ QDomTextPrivate* QDomDocumentPrivate::createTextNode(const QString &data)
bool ok;
QString fixedData = fixedCharData(data, &ok);
if (!ok)
- return 0;
+ return nullptr;
- QDomTextPrivate *t = new QDomTextPrivate(this, 0, fixedData);
+ QDomTextPrivate *t = new QDomTextPrivate(this, nullptr, fixedData);
t->ref.deref();
return t;
}
@@ -6308,9 +6310,9 @@ QDomCommentPrivate* QDomDocumentPrivate::createComment(const QString &data)
bool ok;
QString fixedData = fixedComment(data, &ok);
if (!ok)
- return 0;
+ return nullptr;
- QDomCommentPrivate *c = new QDomCommentPrivate(this, 0, fixedData);
+ QDomCommentPrivate *c = new QDomCommentPrivate(this, nullptr, fixedData);
c->ref.deref();
return c;
}
@@ -6320,9 +6322,9 @@ QDomCDATASectionPrivate* QDomDocumentPrivate::createCDATASection(const QString &
bool ok;
QString fixedData = fixedCDataSection(data, &ok);
if (!ok)
- return 0;
+ return nullptr;
- QDomCDATASectionPrivate *c = new QDomCDATASectionPrivate(this, 0, fixedData);
+ QDomCDATASectionPrivate *c = new QDomCDATASectionPrivate(this, nullptr, fixedData);
c->ref.deref();
return c;
}
@@ -6333,13 +6335,13 @@ QDomProcessingInstructionPrivate* QDomDocumentPrivate::createProcessingInstructi
bool ok;
QString fixedData = fixedPIData(data, &ok);
if (!ok)
- return 0;
+ return nullptr;
// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
QString fixedTarget = fixedXmlName(target, &ok);
if (!ok)
- return 0;
+ return nullptr;
- QDomProcessingInstructionPrivate *p = new QDomProcessingInstructionPrivate(this, 0, fixedTarget, fixedData);
+ QDomProcessingInstructionPrivate *p = new QDomProcessingInstructionPrivate(this, nullptr, fixedTarget, fixedData);
p->ref.deref();
return p;
}
@@ -6348,9 +6350,9 @@ QDomAttrPrivate* QDomDocumentPrivate::createAttribute(const QString &aname)
bool ok;
QString fixedName = fixedXmlName(aname, &ok);
if (!ok)
- return 0;
+ return nullptr;
- QDomAttrPrivate *a = new QDomAttrPrivate(this, 0, fixedName);
+ QDomAttrPrivate *a = new QDomAttrPrivate(this, nullptr, fixedName);
a->ref.deref();
return a;
}
@@ -6360,9 +6362,9 @@ QDomAttrPrivate* QDomDocumentPrivate::createAttributeNS(const QString &nsURI, co
bool ok;
QString fixedName = fixedXmlName(qName, &ok, true);
if (!ok)
- return 0;
+ return nullptr;
- QDomAttrPrivate *a = new QDomAttrPrivate(this, 0, nsURI, fixedName);
+ QDomAttrPrivate *a = new QDomAttrPrivate(this, nullptr, nsURI, fixedName);
a->ref.deref();
return a;
}
@@ -6372,16 +6374,16 @@ QDomEntityReferencePrivate* QDomDocumentPrivate::createEntityReference(const QSt
bool ok;
QString fixedName = fixedXmlName(aname, &ok);
if (!ok)
- return 0;
+ return nullptr;
- QDomEntityReferencePrivate *e = new QDomEntityReferencePrivate(this, 0, fixedName);
+ QDomEntityReferencePrivate *e = new QDomEntityReferencePrivate(this, nullptr, fixedName);
e->ref.deref();
return e;
}
QDomNodePrivate* QDomDocumentPrivate::importNode(QDomNodePrivate *importedNode, bool deep)
{
- QDomNodePrivate *node = 0;
+ QDomNodePrivate *node = nullptr;
switch (importedNode->nodeType()) {
case QDomNode::AttributeNode:
node = new QDomAttrPrivate((QDomAttrPrivate*)importedNode, true);
@@ -6430,19 +6432,19 @@ void QDomDocumentPrivate::saveDocument(QTextStream& s, const int indent, QDomNod
const QDomNodePrivate* n = first;
if(encUsed == QDomNode::EncodingFromDocument) {
-#if QT_CONFIG(textcodec)
+#if QT_CONFIG(textcodec) && QT_CONFIG(regularexpression)
const QDomNodePrivate* n = first;
- QTextCodec *codec = 0;
+ QTextCodec *codec = nullptr;
if (n && n->isProcessingInstruction() && n->nodeName() == QLatin1String("xml")) {
// we have an XML declaration
QString data = n->nodeValue();
- QRegExp encoding(QString::fromLatin1("encoding\\s*=\\s*((\"([^\"]*)\")|('([^']*)'))"));
- encoding.indexIn(data);
- QString enc = encoding.cap(3);
+ QRegularExpression encoding(QString::fromLatin1("encoding\\s*=\\s*((\"([^\"]*)\")|('([^']*)'))"));
+ auto match = encoding.match(data);
+ QString enc = match.captured(3);
if (enc.isEmpty())
- enc = encoding.cap(5);
+ enc = match.captured(5);
if (!enc.isEmpty())
codec = QTextCodec::codecForName(std::move(enc).toLatin1());
}
@@ -6591,7 +6593,7 @@ void QDomDocumentPrivate::saveDocument(QTextStream& s, const int indent, QDomNod
*/
QDomDocument::QDomDocument()
{
- impl = 0;
+ impl = nullptr;
}
/*!
@@ -6820,7 +6822,7 @@ bool QDomDocument::setContent(QXmlInputSource *source, QXmlReader *reader, QStri
{
if (!impl)
impl = new QDomDocumentPrivate();
- return IMPL->setContent(source, reader, 0, errorMsg, errorLine, errorColumn);
+ return IMPL->setContent(source, reader, nullptr, errorMsg, errorLine, errorColumn);
}
/*!
@@ -7367,7 +7369,7 @@ QDomComment QDomNode::toComment() const
QDomHandler::QDomHandler(QDomDocumentPrivate* adoc, QXmlSimpleReader* areader, bool namespaceProcessing)
: errorLine(0), errorColumn(0), doc(adoc), node(adoc), cdata(false),
- nsProcessing(namespaceProcessing), locator(0), reader(areader)
+ nsProcessing(namespaceProcessing), locator(nullptr), reader(areader)
{
}
@@ -7441,7 +7443,7 @@ bool QDomHandler::characters(const QString& ch)
if (cdata) {
n.reset(doc->createCDATASection(ch));
} else if (!entityName.isEmpty()) {
- QScopedPointer<QDomEntityPrivate> e(new QDomEntityPrivate(doc, 0, entityName,
+ QScopedPointer<QDomEntityPrivate> e(new QDomEntityPrivate(doc, nullptr, entityName,
QString(), QString(), QString()));
e->value = ch;
e->ref.deref();
@@ -7526,7 +7528,7 @@ bool QDomHandler::comment(const QString& ch)
bool QDomHandler::unparsedEntityDecl(const QString &name, const QString &publicId, const QString &systemId, const QString &notationName)
{
- QDomEntityPrivate* e = new QDomEntityPrivate(doc, 0, name,
+ QDomEntityPrivate* e = new QDomEntityPrivate(doc, nullptr, name,
publicId, systemId, notationName);
// keep the refcount balanced: appendChild() does a ref anyway.
e->ref.deref();
@@ -7541,7 +7543,7 @@ bool QDomHandler::externalEntityDecl(const QString &name, const QString &publicI
bool QDomHandler::notationDecl(const QString & name, const QString & publicId, const QString & systemId)
{
- QDomNotationPrivate* n = new QDomNotationPrivate(doc, 0, name, publicId, systemId);
+ QDomNotationPrivate* n = new QDomNotationPrivate(doc, nullptr, name, publicId, systemId);
// keep the refcount balanced: appendChild() does a ref anyway.
n->ref.deref();
doc->doctype()->appendChild(n);
diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp
index 7b6669b057..1c45118fb1 100644
--- a/src/xml/sax/qxml.cpp
+++ b/src/xml/sax/qxml.cpp
@@ -43,7 +43,9 @@
#include "qtextcodec.h"
#endif
#include "qbuffer.h"
-#include "qregexp.h"
+#if QT_CONFIG(regularexpression)
+#include "qregularexpression.h"
+#endif
#include "qmap.h"
#include "qhash.h"
#include "qstack.h"
@@ -193,19 +195,23 @@ static const signed char charLookupTable[256]={
*/
static bool stripTextDecl(QString& str)
{
- QString textDeclStart(QLatin1String("<?xml"));
+ QLatin1String textDeclStart("<?xml");
if (str.startsWith(textDeclStart)) {
- QRegExp textDecl(QString::fromLatin1(
+#if QT_CONFIG(regularexpression)
+ QRegularExpression textDecl(QString::fromLatin1(
"^<\\?xml\\s+"
"(version\\s*=\\s*((['\"])[-a-zA-Z0-9_.:]+\\3))?"
"\\s*"
"(encoding\\s*=\\s*((['\"])[A-Za-z][-a-zA-Z0-9_.]*\\6))?"
"\\s*\\?>"
- ));
+ ));
QString strTmp = str.replace(textDecl, QLatin1String(""));
if (strTmp.length() != str.length())
return false; // external entity has wrong TextDecl
str = strTmp;
+#else
+ return false;
+#endif
}
return true;
}
@@ -1073,12 +1079,12 @@ void QXmlInputSource::init()
d = new QXmlInputSourcePrivate;
QT_TRY {
- d->inputDevice = 0;
- d->inputStream = 0;
+ d->inputDevice = nullptr;
+ d->inputStream = nullptr;
setData(QString());
#if QT_CONFIG(textcodec)
- d->encMapper = 0;
+ d->encMapper = nullptr;
#endif
d->nextReturnedEndOfData = true; // first call to next() will call fetchData()
@@ -1351,13 +1357,13 @@ QString QXmlInputSource::fromRawData(const QByteArray &data, bool beginning)
return QString();
if (beginning) {
delete d->encMapper;
- d->encMapper = 0;
+ d->encMapper = nullptr;
}
int mib = 106; // UTF-8
// This is the initial UTF codec we will read the encoding declaration with
- if (d->encMapper == 0) {
+ if (d->encMapper == nullptr) {
d->encodingDeclBytes.clear();
d->encodingDeclChars.clear();
d->lookingForEncodingDecl = true;
@@ -2365,13 +2371,13 @@ bool QXmlDefaultHandler::unparsedEntityDecl(const QString&, const QString&,
/*!
\reimp
- Sets \a ret to 0, so that the reader uses the system identifier
+ Sets \a ret to \nullptr, so that the reader uses the system identifier
provided in the XML document.
*/
bool QXmlDefaultHandler::resolveEntity(const QString&, const QString&,
QXmlInputSource*& ret)
{
- ret = 0;
+ ret = nullptr;
return true;
}
@@ -2514,15 +2520,15 @@ inline void QXmlSimpleReaderPrivate::refClear()
QXmlSimpleReaderPrivate::QXmlSimpleReaderPrivate(QXmlSimpleReader *reader)
{
q_ptr = reader;
- parseStack = 0;
+ parseStack = nullptr;
locator.reset(new QXmlSimpleReaderLocator(reader));
- entityRes = 0;
- dtdHnd = 0;
- contentHnd = 0;
- errorHnd = 0;
- lexicalHnd = 0;
- declHnd = 0;
+ entityRes = nullptr;
+ dtdHnd = nullptr;
+ contentHnd = nullptr;
+ errorHnd = nullptr;
+ lexicalHnd = nullptr;
+ declHnd = nullptr;
// default feature settings
useNamespaces = true;
@@ -2607,8 +2613,9 @@ void QXmlSimpleReaderPrivate::initIncrementalParsing()
is returned. If no such feature exists the return value is
undefined.
- If \a ok is not 0: \c{*}\a{ok} is set to true if the reader has the
- feature called \a name; otherwise \c{*}\a{ok} is set to false.
+ If \a ok is not \nullptr: \c{*}\a{ok} is set to true if the
+ reader has the feature called \a name; otherwise \c{*}\a{ok} is
+ set to false.
\sa setFeature(), hasFeature()
*/
@@ -2637,7 +2644,7 @@ void QXmlSimpleReaderPrivate::initIncrementalParsing()
If the reader has the property \a name, this function returns the
value of the property; otherwise the return value is undefined.
- If \a ok is not 0: if the reader has the \a name property
+ If \a ok is not \nullptr: if the reader has the \a name property
\c{*}\a{ok} is set to true; otherwise \c{*}\a{ok} is set to false.
\sa setProperty(), hasProperty()
@@ -2670,9 +2677,9 @@ void QXmlSimpleReaderPrivate::initIncrementalParsing()
*/
/*!
- \fn QXmlEntityResolver* QXmlReader::entityResolver() const
+ \fn QXmlEntityResolver *QXmlReader::entityResolver() const
- Returns the entity resolver or 0 if none was set.
+ Returns the entity resolver or \nullptr if none was set.
\sa setEntityResolver()
*/
@@ -2686,9 +2693,9 @@ void QXmlSimpleReaderPrivate::initIncrementalParsing()
*/
/*!
- \fn QXmlDTDHandler* QXmlReader::DTDHandler() const
+ \fn QXmlDTDHandler *QXmlReader::DTDHandler() const
- Returns the DTD handler or 0 if none was set.
+ Returns the DTD handler or \nullptr if none was set.
\sa setDTDHandler()
*/
@@ -2702,9 +2709,9 @@ void QXmlSimpleReaderPrivate::initIncrementalParsing()
*/
/*!
- \fn QXmlContentHandler* QXmlReader::contentHandler() const
+ \fn QXmlContentHandler *QXmlReader::contentHandler() const
- Returns the content handler or 0 if none was set.
+ Returns the content handler or \nullptr if none was set.
\sa setContentHandler()
*/
@@ -2719,9 +2726,9 @@ void QXmlSimpleReaderPrivate::initIncrementalParsing()
*/
/*!
- \fn QXmlErrorHandler* QXmlReader::errorHandler() const
+ \fn QXmlErrorHandler *QXmlReader::errorHandler() const
- Returns the error handler or 0 if none is set.
+ Returns the error handler or \nullptr if none is set.
\sa setErrorHandler()
*/
@@ -2735,9 +2742,9 @@ void QXmlSimpleReaderPrivate::initIncrementalParsing()
*/
/*!
- \fn QXmlLexicalHandler* QXmlReader::lexicalHandler() const
+ \fn QXmlLexicalHandler *QXmlReader::lexicalHandler() const
- Returns the lexical handler or 0 if none was set.
+ Returns the lexical handler or \nullptr if none was set.
\sa setLexicalHandler()
*/
@@ -2751,9 +2758,9 @@ void QXmlSimpleReaderPrivate::initIncrementalParsing()
*/
/*!
- \fn QXmlDeclHandler* QXmlReader::declHandler() const
+ \fn QXmlDeclHandler *QXmlReader::declHandler() const
- Returns the declaration handler or 0 if none was set.
+ Returns the declaration handler or \nullptr if none was set.
\sa setDeclHandler()
*/
@@ -2925,7 +2932,7 @@ bool QXmlSimpleReader::feature(const QString& name, bool *ok) const
{
const QXmlSimpleReaderPrivate *d = d_func();
- if (ok != 0)
+ if (ok)
*ok = true;
if (name == QLatin1String("http://xml.org/sax/features/namespaces")) {
return d->useNamespaces;
@@ -2939,7 +2946,7 @@ bool QXmlSimpleReader::feature(const QString& name, bool *ok) const
return d->reportEntities;
} else {
qWarning("Unknown feature %s", name.toLatin1().data());
- if (ok != 0)
+ if (ok)
*ok = false;
}
return false;
@@ -3016,9 +3023,9 @@ bool QXmlSimpleReader::hasFeature(const QString& name) const
*/
void* QXmlSimpleReader::property(const QString&, bool *ok) const
{
- if (ok != 0)
+ if (ok)
*ok = false;
- return 0;
+ return nullptr;
}
/*! \reimp
@@ -3199,7 +3206,7 @@ bool QXmlSimpleReader::parse(const QXmlInputSource *input, bool incremental)
d->initIncrementalParsing();
} else {
delete d->parseStack;
- d->parseStack = 0;
+ d->parseStack = nullptr;
}
d->init(input);
@@ -3244,7 +3251,7 @@ bool QXmlSimpleReader::parse(const QXmlInputSource *input, bool incremental)
bool QXmlSimpleReader::parseContinue()
{
Q_D(QXmlSimpleReader);
- if (d->parseStack == 0 || d->parseStack->isEmpty())
+ if (d->parseStack == nullptr || d->parseStack->isEmpty())
return false;
d->initData();
int state = d->parseStack->pop().state;
@@ -3261,7 +3268,7 @@ bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental)
if (state==0) {
if (!parseProlog()) {
if (incremental && error.isNull()) {
- pushParseState(0, 0);
+ pushParseState(nullptr, 0);
return true;
} else {
clear(tags);
@@ -3273,7 +3280,7 @@ bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental)
if (state==1) {
if (!parseElement()) {
if (incremental && error.isNull()) {
- pushParseState(0, 1);
+ pushParseState(nullptr, 1);
return true;
} else {
clear(tags);
@@ -3286,7 +3293,7 @@ bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental)
while (!atEnd()) {
if (!parseMisc()) {
if (incremental && error.isNull()) {
- pushParseState(0, 2);
+ pushParseState(nullptr, 2);
return true;
} else {
clear(tags);
@@ -3296,7 +3303,7 @@ bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental)
}
if (!atEndOrig && incremental) {
// we parsed something at all, so be prepared to come back later
- pushParseState(0, 2);
+ pushParseState(nullptr, 2);
return true;
}
// is stack empty?
@@ -3308,7 +3315,7 @@ bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental)
// call the handler
if (contentHnd) {
delete parseStack;
- parseStack = 0;
+ parseStack = nullptr;
if (!contentHnd->endDocument()) {
reportParseError(contentHnd->errorString());
return false;
@@ -3343,7 +3350,7 @@ bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental)
signed char state;
signed char input;
-(4) if (d->parseStack == 0 || d->parseStack->isEmpty()) {
+(4) if (d->parseStack == nullptr || d->parseStack->isEmpty()) {
(4a) ...
} else {
(4b) ...
@@ -3433,7 +3440,7 @@ bool QXmlSimpleReaderPrivate::parseProlog()
signed char state;
signed char input;
- if (parseStack == 0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr|| parseStack->isEmpty()) {
xmldecl_possible = true;
doctype_read = false;
state = Init;
@@ -3624,7 +3631,7 @@ bool QXmlSimpleReaderPrivate::parseElement()
int state;
int input;
- if (parseStack == 0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr|| parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -3993,7 +4000,7 @@ bool QXmlSimpleReaderPrivate::parseContent()
signed char state;
signed char input;
- if (parseStack == 0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
contentCharDataRead = false;
state = Init;
} else {
@@ -4296,7 +4303,7 @@ bool QXmlSimpleReaderPrivate::parseMisc()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -4451,7 +4458,7 @@ bool QXmlSimpleReaderPrivate::parsePI()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -4678,7 +4685,7 @@ bool QXmlSimpleReaderPrivate::parseDoctype()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
startDTDwasReported = false;
systemId.clear();
publicId.clear();
@@ -4889,7 +4896,7 @@ bool QXmlSimpleReaderPrivate::parseExternalID()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
systemId.clear();
publicId.clear();
state = Init;
@@ -5053,7 +5060,7 @@ bool QXmlSimpleReaderPrivate::parseMarkupdecl()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -5211,7 +5218,7 @@ bool QXmlSimpleReaderPrivate::parsePEReference()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -5248,7 +5255,7 @@ bool QXmlSimpleReaderPrivate::parsePEReference()
} else if (entityRes) {
QMap<QString,QXmlSimpleReaderPrivate::ExternParameterEntity>::Iterator it2;
it2 = externParameterEntities.find(ref());
- QXmlInputSource *ret = 0;
+ QXmlInputSource *ret = nullptr;
if (it2 != externParameterEntities.end()) {
if (!entityRes->resolveEntity((*it2).publicId, (*it2).systemId, ret)) {
delete ret;
@@ -5389,7 +5396,7 @@ bool QXmlSimpleReaderPrivate::parseAttlistDecl()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -5605,7 +5612,7 @@ bool QXmlSimpleReaderPrivate::parseAttType()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -5826,7 +5833,7 @@ bool QXmlSimpleReaderPrivate::parseAttValue()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -5968,7 +5975,7 @@ bool QXmlSimpleReaderPrivate::parseElementDecl()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -6177,7 +6184,7 @@ bool QXmlSimpleReaderPrivate::parseNotationDecl()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -6321,7 +6328,7 @@ bool QXmlSimpleReaderPrivate::parseChoiceSeq()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -6550,7 +6557,7 @@ bool QXmlSimpleReaderPrivate::parseEntityDecl()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -6825,7 +6832,7 @@ bool QXmlSimpleReaderPrivate::parseEntityValue()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -6944,7 +6951,7 @@ bool QXmlSimpleReaderPrivate::parseComment()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -7056,7 +7063,7 @@ bool QXmlSimpleReaderPrivate::parseAttribute()
int state;
int input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -7155,7 +7162,7 @@ bool QXmlSimpleReaderPrivate::parseName()
};
int state;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -7241,7 +7248,7 @@ bool QXmlSimpleReaderPrivate::parseNmtoken()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
state = Init;
} else {
state = parseStack->pop().state;
@@ -7349,7 +7356,7 @@ bool QXmlSimpleReaderPrivate::parseReference()
signed char state;
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
parseReference_charDataRead = false;
state = Init;
} else {
@@ -7575,7 +7582,7 @@ bool QXmlSimpleReaderPrivate::processReference()
if (parseReference_context == InContent) {
if (contentCharDataRead) {
if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
- if (contentHnd != 0 && !contentHnd->characters(string())) {
+ if (contentHnd != nullptr && !contentHnd->characters(string())) {
reportParseError(contentHnd->errorString());
return false;
}
@@ -7603,7 +7610,7 @@ bool QXmlSimpleReaderPrivate::processReference()
// Included if validating
bool skipIt = true;
if (entityRes) {
- QXmlInputSource *ret = 0;
+ QXmlInputSource *ret = nullptr;
if (!entityRes->resolveEntity((*itExtern).publicId, (*itExtern).systemId, ret)) {
delete ret;
reportParseError(entityRes->errorString());
@@ -7689,7 +7696,7 @@ bool QXmlSimpleReaderPrivate::parseString()
signed char state; // state in this function is the position in the string s
signed char input;
- if (parseStack==0 || parseStack->isEmpty()) {
+ if (parseStack == nullptr || parseStack->isEmpty()) {
Done = parseString_s.length();
state = 0;
} else {
@@ -7793,7 +7800,7 @@ void QXmlSimpleReaderPrivate::next()
c = inputSource->next();
// If we are not incremental parsing, we just skip over EndOfData chars to give the
// parser an uninterrupted stream of document chars.
- if (c == QXmlInputSource::EndOfData && parseStack == 0)
+ if (c == QXmlInputSource::EndOfData && parseStack == nullptr)
c = inputSource->next();
if (uc == '\n') {
lineNr++;
@@ -7825,7 +7832,7 @@ bool QXmlSimpleReaderPrivate::eat_ws()
}
next();
}
- if (parseStack != 0) {
+ if (parseStack != nullptr) {
unexpectedEof(&QXmlSimpleReaderPrivate::eat_ws, 0);
return false;
}
@@ -7915,7 +7922,7 @@ void QXmlSimpleReaderPrivate::reportParseError(const QString& error)
*/
void QXmlSimpleReaderPrivate::unexpectedEof(ParseFunction where, int state)
{
- if (parseStack == 0) {
+ if (parseStack == nullptr) {
reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
} else {
if (c == QXmlInputSource::EndOfDocument) {
@@ -7935,7 +7942,7 @@ void QXmlSimpleReaderPrivate::unexpectedEof(ParseFunction where, int state)
*/
void QXmlSimpleReaderPrivate::parseFailed(ParseFunction where, int state)
{
- if (parseStack!=0 && error.isNull()) {
+ if (parseStack != nullptr && error.isNull()) {
pushParseState(where, state);
}
}
diff --git a/src/xml/sax/qxml.h b/src/xml/sax/qxml.h
index 94dc8dfb8e..9be14bd7a9 100644
--- a/src/xml/sax/qxml.h
+++ b/src/xml/sax/qxml.h
@@ -116,16 +116,14 @@ class Q_XML_EXPORT QXmlAttributes
{
public:
QXmlAttributes();
-#ifdef Q_COMPILER_DEFAULT_MEMBERS
QXmlAttributes(const QXmlAttributes &) = default;
- QXmlAttributes(QXmlAttributes &&) Q_DECL_NOTHROW = default;
+ QXmlAttributes(QXmlAttributes &&) noexcept = default;
QXmlAttributes &operator=(const QXmlAttributes &) = default;
- QXmlAttributes &operator=(QXmlAttributes &&) Q_DECL_NOTHROW = default;
-#endif // default members
+ QXmlAttributes &operator=(QXmlAttributes &&) noexcept = default;
QT6_NOT_VIRTUAL ~QXmlAttributes();
- void swap(QXmlAttributes &other) Q_DECL_NOTHROW
+ void swap(QXmlAttributes &other) noexcept
{
qSwap(attList, other.attList);
qSwap(d, other.d);
diff --git a/src/xml/sax/qxml_p.h b/src/xml/sax/qxml_p.h
index 98dc2aea0c..eb6135db04 100644
--- a/src/xml/sax/qxml_p.h
+++ b/src/xml/sax/qxml_p.h
@@ -229,7 +229,7 @@ private:
// for the DTD currently being parsed.
static const int dtdRecursionLimit = 2;
// The maximum amount of characters an entity value may contain, after expansion.
- static const int entityCharacterLimit = 1024;
+ static const int entityCharacterLimit = 4096;
const QString &string();
void stringClear();
diff --git a/sync.profile b/sync.profile
index a6d0e2a4a7..e6fc285573 100644
--- a/sync.profile
+++ b/sync.profile
@@ -18,6 +18,7 @@
"QtEventDispatcherSupport" => "$basedir/src/platformsupport/eventdispatchers",
"QtFontDatabaseSupport" => "$basedir/src/platformsupport/fontdatabases",
"QtInputSupport" => "$basedir/src/platformsupport/input",
+ "QtXkbCommonSupport" => "$basedir/src/platformsupport/input/xkbcommon",
"QtPlatformCompositorSupport" => "$basedir/src/platformsupport/platformcompositor",
"QtServiceSupport" => "$basedir/src/platformsupport/services",
"QtThemeSupport" => "$basedir/src/platformsupport/themes",
diff --git a/tests/auto/android/runtests_androiddeployqt.pl b/tests/auto/android/runtests_androiddeployqt.pl
deleted file mode 100755
index 24b44cf9b2..0000000000
--- a/tests/auto/android/runtests_androiddeployqt.pl
+++ /dev/null
@@ -1,550 +0,0 @@
-#!/usr/bin/perl -w
-#############################################################################
-##
-## Copyright (C) 2012-2013 BogDan Vatra <bogdan@kde.org>
-## Copyright (C) 2016 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of the test suite of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:GPL-EXCEPT$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 3 as published by the Free Software
-## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-use Cwd;
-use Cwd 'abs_path';
-use File::Basename;
-use File::Temp 'tempdir';
-use File::Path 'remove_tree';
-use Getopt::Long;
-use Pod::Usage;
-use XML::Simple;
-use Term::ANSIColor;
-
-### default options
-my @stack = cwd;
-my $device_serial=""; # "-s device_serial";
-my $deployqt_device_serial=""; # "-device device_serial";
-my $log_out="xml";
-my $max_runtime = 5;
-my $className="org.qtproject.qt5.android.bindings.QtActivity";
-my $jobs = 4;
-my $testsubset = "";
-my $man = 0;
-my $help = 0;
-my $make_clean = 0;
-my $stop_on_fail = 0;
-my $time_out=400;
-my $android_toolchain_version = "4.8";
-my $host_arch = "linux-x86";
-my $android_sdk_dir = "$ENV{'ANDROID_SDK_ROOT'}";
-my $android_ndk_dir = "$ENV{'ANDROID_NDK_ROOT'}";
-my $android_to_connect = "$ENV{'ANDROID_DEVICE'}";
-my $ant_tool = `which ant`;
-my $silent = 0;
-chomp $ant_tool;
-my $strip_tool="";
-my $readelf_tool="";
-# for ci usage
-my @failures = '';
-my $total_tests = 0;
-my $total_failed = 0;
-my $failed_insignificants = 0;
-my $ci_use = 0;
-my $start = time();
-my $uninstall = 0;
-
-GetOptions('h|help' => \$help
- , man => \$man
- , 's|serial=s' => \$device_serial
- , 't|test=s' => \$testsubset
- , 'c|clean' => \$make_clean
- , 'j|jobs=i' => \$jobs
- , 'logtype=s' => \$log_out
- , 'runtime=i' => \$max_runtime
- , 'sdk=s' => \$android_sdk_dir
- , 'ndk=s' => \$android_ndk_dir
- , 'toolchain=s' => \$android_toolchain_version
- , 'host=s' => \$host_arch
- , 'ant=s' => \$ant_tool
- , 'strip=s' => \$strip_tool
- , 'readelf=s' => \$readelf_tool
- , 'testcase=s' => \$testcase
- , 'f|fail' => sub { $stop_on_fail = 1 }
- , 'silent' => sub { $silent = 1 }
- , 'ci' => sub { $ci_use = 1 }
- , 'uninstall' => sub { $uninstall = 1 }
- ) or pod2usage(2);
-pod2usage(1) if $help;
-pod2usage(-verbose => 2) if $man;
-
-if ($ci_use){
- use QMake::Project;
-}
-my $adb_tool="$android_sdk_dir/platform-tools/adb";
-
-# For CI. Nodes are connecting to test devices over IP, which is stored to env variable
-if ($android_to_connect ne ""){
- print " Found device to be connected from env: $android_to_connect \n";
- system("$adb_tool disconnect $android_to_connect");
- system("$adb_tool connect $android_to_connect");
- sleep(2);# let it connect
- system("$adb_tool -s $android_to_connect reboot &");# adb bug, it blocks forever
- sleep(15); # wait for the device to come up again
- system("$adb_tool disconnect $android_to_connect");# cleans up the left adb reboot process
- system("$adb_tool connect $android_to_connect");
- $device_serial =$android_to_connect;
-}
-
-system("$adb_tool devices") == 0 or die "No device found, please plug/start at least one device/emulator\n"; # make sure we have at least on device attached
-
-$deployqt_device_serial = "--device $device_serial" if ($device_serial);
-$device_serial = "-s $device_serial" if ($device_serial);
-$testsubset="/$testsubset" if ($testsubset);
-
-$strip_tool="$android_ndk_dir/toolchains/arm-linux-androideabi-$android_toolchain_version/prebuilt/$host_arch/bin/arm-linux-androideabi-strip" unless($strip_tool);
-$readelf_tool="$android_ndk_dir/toolchains/arm-linux-androideabi-$android_toolchain_version/prebuilt/$host_arch/bin/arm-linux-androideabi-readelf" unless($readelf_tool);
-$readelf_tool="$readelf_tool -d -w ";
-
-sub dir
-{
-# print "@stack\n";
-}
-
-sub pushd ($)
-{
- unless ( chdir $_[0] )
- {
- warn "Error: $!\n";
- return;
- }
- unshift @stack, cwd;
- dir;
-}
-
-sub popd ()
-{
- @stack > 1 and shift @stack;
- chdir $stack[0];
- dir;
-}
-
-##############################
-# Read possible insignificance
-# from pro file
-##############################
-sub check_if_insignificant
-{
- return 0 if ( !$ci_use );
- my $case = shift;
- my $insignificant = 0;
- my $prj = QMake::Project->new( 'Makefile' );
- $insignificant = $prj->test( 'insignificant_test' );
- return $insignificant;
-}
-
-##############################
-# Print output from given
-# $testresult.txt file
-##############################
-sub print_output
-{
- my $res_file = shift;
- my $case = shift;
- my $insignificant = shift;
- my $print_all = 0;
- $total_tests++;
- if (-e $res_file) {
- open my $file, $res_file or die "Could not open $res_file: $!";
- while (my $line = <$file>) {
- if ($line =~ m/^FAIL/) {
- print "$line";
- # Pretend to be like the "real" testrunner and print out
- # all steps
- $print_all = 1;
- }
- }
- close $file;
- if ($print_all) {
- # In case we are printing all, the test failed
- system("cat $res_file");
- if ($insignificant) {
- print " Testrunner: $case failed, but it is marked with insignificant_test\n";
- push (@failures ,(basename($case)." [insignificant]"));
- $failed_insignificants++;
- } else {
- $total_failed++;
- push (@failures ,(basename($case)));
- }
- } else {
- my $cmd = "sed -n 'x;\$p' ${res_file}";
- my $summary = qx(${cmd});
- if ($summary =~ m/^Totals/) {
- print "$summary";
- } else {
- print "Error: The log is incomplete. Looks like you have to increase the timeout.";
- # The test log seems inclomplete, considering the test as failed.
- if ($insignificant) {
- print " Testrunner: $case failed, but it is marked with insignificant_test\n";
- push (@failures ,(basename($case)." [insignificant]"));
- $failed_insignificants++;
- } else {
- $total_failed++;
- push (@failures ,(basename($case)));
- }
- }
- }
- } else {
- if ($insignificant) {
- print " Failed to execute $case, but it is marked with insignificant_test\n";
- push (@failures ,(basename($case)." [insignificant]"));
- $failed_insignificants++;
- } else {
- print "Failed to execute $case \n";
- $total_failed++;
- push (@failures ,(basename($case)));
- }
- }
-}
-
-##############################
-# Print summary of test run
-##############################
-
-sub print_summary
-{
- my $total = time()-$start;
- my $h = 0;
- my $m = 0;
- my $s = 0;
- my $exit = 0;
- print "=== Timing: =================== TEST RUN COMPLETED! ============================\n";
- if ($total > 60*60) {
- $h = int($total/60/60);
- $s = int($total - $h*60*60);
-
- $m = int($s/60);
- $s = 0;
- print "Total: $h hours $m minutes\n";
- } elsif ($total > 60) {
- $m = int($total/60);
- $s = int($total - $m*60);
- print "Total: $m minutes $s seconds\n";
- } else {
- $s = int($total);
- print "Total: $s seconds\n";
- }
-
- print "=== Failures: ==================================================================";
- foreach my $failed (@failures) {
- print $failed."\n";
- $exit = 1;
- }
- print "=== Totals: ".$total_tests." tests, ".($total_tests-$total_failed).
- " passes, ".$failed_insignificants.
- " insignificant fails ======================\n";
- return $exit;
-}
-
-
-sub waitForProcess
-{
- my $process=shift;
- my $action=shift;
- my $timeout=shift;
- my $sleepPeriod=shift;
- $sleepPeriod=1 if !defined($sleepPeriod);
- print "Waiting for $process ".$timeout*$sleepPeriod." seconds to" if (!$silent);
- print $action?" start...\n":" die...\n" if (!$silent);
- while ($timeout--)
- {
- my $output = `$adb_tool $device_serial shell ps 2>&1`; # get current processes
- #FIXME check why $output is not matching m/.*S $process\n/ or m/.*S $process$/ (eol)
- my $res=($output =~ m/.*S $process/)?1:0; # check the procress
- if ($action == $res)
- {
- print "... succeed\n" if (!$silent);
- return 1;
- }
- sleep($sleepPeriod);
- print "timeount in ".$timeout*$sleepPeriod." seconds\n" if (!$silent);
- }
- print "... failed\n" if (!$silent);
- return 0;
-}
-
-my $src_dir_qt=abs_path(dirname($0)."/../../..");
-my $quadruplor_dir="$src_dir_qt/tests/auto/android";
-my $qmake_path="$src_dir_qt/bin/qmake";
-my $androiddeployqt_path="$src_dir_qt/bin/androiddeployqt";
-my $tests_dir="$src_dir_qt/tests$testsubset";
-my $temp_dir=tempdir(CLEANUP => 1);
-my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
-my $output_dir=$stack[0]."/".(1900+$year)."-$mon-$mday-$hour:$min";
-mkdir($output_dir);
-unlink("latest");
-system(" ln -s $output_dir latest");
-my $sdk_api=0;
-my $output = `$adb_tool $device_serial shell getprop`; # get device properties
-if ($output =~ m/.*\[ro.build.version.sdk\]: \[(\d+)\]/)
-{
- $sdk_api=int($1);
- $sdk_api=5 if ($sdk_api>5 && $sdk_api<8);
- $sdk_api=9 if ($sdk_api>9);
-}
-
-sub checkXMLOutput
-{
- print color 'bold red';
- my $fileName = shift;
- my $XMLOutput = eval { XMLin($fileName, ForceArray => 1) };
- if (!defined($XMLOutput)) {
- print "Can't parse the $fileName file, probably the test crased.\n";
- print color 'reset';
- die "Stopping\n" if $stop_on_fail;
- return;
- }
- my $testName = $XMLOutput->{name};
- my $fail = 0;
- while (my($node_key, $node_valule) = each (%{$XMLOutput})) {
- next if $node_key ne "TestFunction";
- while (my($function_key, $function_valule) = each (%{$node_valule})) {
- while (my($test_key, $test_valule) = each (%{$function_valule})) {
- next if $test_key ne "Incident";
- for my $incident (@{$test_valule}) {
- if (($incident->{type} ne "pass") && ($incident->{type} ne "xfail")) {
- print "test $testName::$function_key failed $incident->{file}:$incident->{line}\n";
- $fail = 1;
- }
- }
- }
- }
- }
- print color 'reset';
- die "Stopping\n" if $stop_on_fail and $fail;
-}
-
-sub startTest
-{
- my $testName = shift;
- my $packageName = "org.qtproject.example.tst_$testName";
- my $intentName = "$packageName/org.qtproject.qt5.android.bindings.QtActivity";
- my $output_file = shift;
- my $insignificance = shift;
- my $get_xml= 0;
- my $get_txt= 0;
- my $testLib ="";
- if ($log_out eq "xml") {
- $testLib="-o /data/data/$packageName/output.xml,xml";
- $get_xml = 1;
- } elsif ($log_out eq "txt") {
- $testLib="-o /data/data/$packageName/output.txt,txt";
- $get_txt = 1;
- } else {
- $testLib="-o /data/data/$packageName/output.xml,xml -o /data/data/$packageName/output.txt,txt";
- $get_xml = 1;
- $get_txt = 1;
- }
-
- my $cmd="${adb_tool} ${device_serial} shell am start -e applicationArguments \"${testLib}\" -n ${intentName}";
- my $res = qx(${cmd});
- print $res if (!$silent);
- #wait to start (if it has not started and quit already)
- waitForProcess($packageName,1,10);
-
- #wait to stop
- unless(waitForProcess($packageName,0,$time_out,5))
- {
- #killProcess($packageName);
- print "Someone should kill $packageName\n";
- system("$adb_tool $device_serial uninstall $packageName") if ($uninstall);
- return 1;
- }
-
- # Wait for three seconds to allow process to write all data
- sleep(3);
-
- system("$adb_tool $device_serial pull /data/data/$packageName/output.xml $output_dir/$output_file.xml") if ($get_xml);
-
- system("$adb_tool $device_serial pull /data/data/$packageName/output.txt $output_dir/$output_file.txt") if ($get_txt);
- if ($get_txt){
- print "Test results for $packageName:\n";
- my $insig =
- print_output("$output_dir/$output_file.txt", $packageName, $insignificance);
- }
- system("$adb_tool $device_serial uninstall $packageName") if ($uninstall);
-
- checkXMLOutput("$output_dir/$output_file.xml") if ($get_xml);
- return 1;
-}
-
-########### build qt tests and benchmarks ###########
-pushd($tests_dir);
-print "Building $tests_dir \n";
-system("make distclean") if ($make_clean);
-system("$qmake_path -r") == 0 or die "Can't run qmake\n"; #exec qmake
-system("make -j$jobs") == 0 or warn "Can't build all tests\n"; #exec make
-
-my $testsFiles = "";
-if ($testcase) {
- $testsFiles=`find . -name libtst_$testcase.so`; # only tests
-} else {
- $testsFiles=`find . -name libtst_*.so`; # only tests
-}
-
-foreach (split("\n",$testsFiles))
-{
- chomp; #remove white spaces
- pushd(abs_path(dirname($_))); # cd to application dir
- my $insig = check_if_insignificant();
- my $cmd="make INSTALL_ROOT=${temp_dir} install";
- my $res = qx(${cmd});
- print $res if (!$silent);
- my $application=basename(cwd);
- if ($silent) {
- $cmd="$androiddeployqt_path --install ${deployqt_device_serial} --output ${temp_dir} --deployment debug --verbose --input android-libtst_${application}.so-deployment-settings.json >/dev/null 2>&1";
- } else {
- $cmd="$androiddeployqt_path --install ${deployqt_device_serial} --output ${temp_dir} --deployment debug --verbose --input android-libtst_${application}.so-deployment-settings.json";
- }
- $res = qx(${cmd});
- print $res if (!$silent);
- my $output_name=dirname($_);
- $output_name =~ s/\.//; # remove first "." character
- $output_name =~ s/\///; # remove first "/" character
- $output_name =~ s/\//_/g; # replace all "/" with "_"
- $output_name=$application unless($output_name);
- $time_out=$max_runtime*60/5; # 5 minutes time out for a normal test
-
- $applicationLibrary = `find $temp_dir -name libtst_bench_$application.so`;
-
- if ($applicationLibrary)
- {
- $time_out=5*60/5; # 10 minutes for a benchmark
- $application = "bench_$application";
- }
- else
- {
- $applicationLibrary = `find $temp_dir -name libtst_$application.so`;
- }
-
- if (!$applicationLibrary)
- {
- print "Can't find application binary libtst_$application.so in $temp_dir!\n";
- }
- else
- {
- startTest($application, "$output_name", $insig) or warn "Can't run $application ...\n";
- }
-
- popd();
- remove_tree( $temp_dir, {keep_root => 1} );
-}
-print_summary() if ($ci_use);
-popd();
-
-__END__
-
-=head1 NAME
-
-Script to run all qt tests/benchmarks to an android device/emulator
-
-=head1 SYNOPSIS
-
-runtests.pl [options]
-
-=head1 OPTIONS
-
-=over 8
-=item B<-f --fail>
-
-Stop the script when test fails. Default 0
-
-=item B<-s --serial = serial>
-
-Device serial number. May be empty if only one device is attached.
-
-=item B<-t --test = test_subset>
-
-Tests subset (e.g. benchmarks, auto, auto/qbuffer, etc.).
-
-=item B<-c --clean>
-
-Clean tests before building them.
-
-=item B<-j --jobs = number>
-
-Make jobs when building tests.
-
-=item B<--sdk = sdk_path>
-
-Android SDK path.
-
-=item B<--ndk = ndk_path>
-
-Android NDK path.
-
-=item B<--ant = ant_tool_path>
-
-Ant tool path.
-
-=item B<--strip = strip_tool_path>
-
-Android strip tool path, used to deploy qt libs.
-
-=item B<--readelf = readelf_tool_path>
-
-Android readelf tool path, used to check if a test application uses qt OpenGL.
-
-=item B<--logtype = xml|txt|both>
-
-The format of log file, default is xml.
-
-=item B<--runtime = minutes>
-
-The timeout period before stopping individual tests from running.
-
-=item B<-silent>
-
-Suppress output of system commands.
-
-=item B<-ci>
-
-Enables checking if test is insignificant or not. Also prints test
-summary after all tests has been executed.
-
-=item B<-uninstall>
-
-Uninstalls the test after has been executed.
-
-=item B<-h --help>
-
-Print a brief help message and exits.
-
-=item B<--man>
-
-Prints the manual page and exits.
-
-=back
-
-=head1 DESCRIPTION
-
-B<This program> will run all qt tests/benchmarks to an android device/emulator.
-
-=cut
diff --git a/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
index 2e698e6615..3c77b1ba0b 100644
--- a/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
+++ b/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp
@@ -88,7 +88,7 @@ QAtomicInt iterations;
class PrintFor : public IterateKernel<TestIterator, void>
{
public:
- PrintFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.store(0); }
+ PrintFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.storeRelaxed(0); }
bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
{
iterations.fetchAndAddRelaxed(end - begin);
@@ -107,7 +107,7 @@ public:
class SleepPrintFor : public IterateKernel<TestIterator, void>
{
public:
- SleepPrintFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.store(0); }
+ SleepPrintFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.storeRelaxed(0); }
inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
{
QTest::qSleep(200);
@@ -127,7 +127,7 @@ public:
void tst_QtConcurrentIterateKernel::instantiate()
{
startThreadEngine(new PrintFor(0, 40)).startBlocking();
- QCOMPARE(iterations.load(), 40);
+ QCOMPARE(iterations.loadRelaxed(), 40);
}
void tst_QtConcurrentIterateKernel::cancel()
@@ -138,8 +138,8 @@ void tst_QtConcurrentIterateKernel::cancel()
f.waitForFinished();
QVERIFY(f.isCanceled());
// the threads might run one iteration each before they are canceled.
- QVERIFY2(iterations.load() <= QThread::idealThreadCount(),
- (QByteArray::number(iterations.load()) + ' ' + QByteArray::number(QThread::idealThreadCount())));
+ QVERIFY2(iterations.loadRelaxed() <= QThread::idealThreadCount(),
+ (QByteArray::number(iterations.loadRelaxed()) + ' ' + QByteArray::number(QThread::idealThreadCount())));
}
}
@@ -147,7 +147,7 @@ QAtomicInt counter;
class CountFor : public IterateKernel<TestIterator, void>
{
public:
- CountFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.store(0); }
+ CountFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.storeRelaxed(0); }
inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
{
counter.fetchAndAddRelaxed(end - begin);
@@ -164,10 +164,10 @@ void tst_QtConcurrentIterateKernel::stresstest()
const int iterations = 1000;
const int times = 50;
for (int i = 0; i < times; ++i) {
- counter.store(0);
+ counter.storeRelaxed(0);
CountFor f(0, iterations);
f.startBlocking();
- QCOMPARE(counter.load(), iterations);
+ QCOMPARE(counter.loadRelaxed(), iterations);
}
}
@@ -186,7 +186,7 @@ public:
// this class throttles between iterations 100 and 200,
// and then records how many threads that run between
// iterations 140 and 160.
- ThrottleFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.store(0); throttling = false; }
+ ThrottleFor(TestIterator begin, TestIterator end) : IterateKernel<TestIterator, void>(begin, end) { iterations.storeRelaxed(0); throttling = false; }
inline bool runIterations(TestIterator/*beginIterator*/, int begin, int end, void *)
{
if (200 >= begin && 200 < end) {
@@ -217,7 +217,7 @@ public:
bool shouldThrottleThread()
{
- const int load = iterations.load();
+ const int load = iterations.loadRelaxed();
return (load > 100 && load < 200);
}
bool throttling;
@@ -226,14 +226,14 @@ public:
void tst_QtConcurrentIterateKernel::throttling()
{
const int totalIterations = 400;
- iterations.store(0);
+ iterations.storeRelaxed(0);
threads.clear();
ThrottleFor f(0, totalIterations);
f.startBlocking();
- QCOMPARE(iterations.load(), totalIterations);
+ QCOMPARE(iterations.loadRelaxed(), totalIterations);
QCOMPARE(threads.count(), 1);
diff --git a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
index b864b065e6..383de0b2ce 100644
--- a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
+++ b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
@@ -127,14 +127,11 @@ void tst_QtConcurrentMap::map()
QtConcurrent::map(numberList.begin(), numberList.end(), &Number::multiplyBy2).waitForFinished();
QCOMPARE(numberList, QList<Number>() << 4 << 8 << 12);
-#ifdef Q_COMPILER_LAMBDA
// lambda
QtConcurrent::map(list, [](int &x){x *= 2;}).waitForFinished();
QCOMPARE(list, QList<int>() << 128 << 256 << 384);
QtConcurrent::map(list.begin(), list.end(), [](int &x){x *= 2;}).waitForFinished();
QCOMPARE(list, QList<int>() << 256 << 512 << 768);
-#endif
-
}
// functors don't take arguments by reference, making these no-ops
@@ -160,13 +157,11 @@ void tst_QtConcurrentMap::map()
QtConcurrent::map(list.begin(), list.end(), multiplyBy2Immutable).waitForFinished();
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
-#ifdef Q_COMPILER_LAMBDA
// lambda
QtConcurrent::map(list, [](int x){x *= 2;}).waitForFinished();
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
QtConcurrent::map(list.begin(), list.end(), [](int x){x *= 2;}).waitForFinished();
QCOMPARE(list, QList<int>() << 1 << 2 << 3);
-#endif
}
// Linked lists and forward iterators
@@ -2026,12 +2021,12 @@ int fn(int &i)
return i;
}
-int fnConstNoExcept(const int &i) Q_DECL_NOTHROW
+int fnConstNoExcept(const int &i) noexcept
{
return i;
}
-int fnNoExcept(int &i) Q_DECL_NOTHROW
+int fnNoExcept(int &i) noexcept
{
return i;
}
@@ -2046,12 +2041,12 @@ QString changeType(int &)
return QString();
}
-QString changeTypeConstNoExcept(const int &) Q_DECL_NOTHROW
+QString changeTypeConstNoExcept(const int &) noexcept
{
return QString();
}
-QString changeTypeNoExcept(int &) Q_DECL_NOTHROW
+QString changeTypeNoExcept(int &) noexcept
{
return QString();
}
@@ -2066,12 +2061,12 @@ int changeTypeQStringList(QStringList &)
return 0;
}
-int changeTypeQStringListConstNoExcept(const QStringList &) Q_DECL_NOTHROW
+int changeTypeQStringListConstNoExcept(const QStringList &) noexcept
{
return 0;
}
-int changeTypeQStringListNoExcept(QStringList &) Q_DECL_NOTHROW
+int changeTypeQStringListNoExcept(QStringList &) noexcept
{
return 0;
}
@@ -2101,22 +2096,22 @@ public:
return QString();
}
- MemFnTester fnNoExcept() Q_DECL_NOTHROW
+ MemFnTester fnNoExcept() noexcept
{
return MemFnTester();
}
- MemFnTester fnConstNoExcept() const Q_DECL_NOTHROW
+ MemFnTester fnConstNoExcept() const noexcept
{
return MemFnTester();
}
- QString changeTypeNoExcept() Q_DECL_NOTHROW
+ QString changeTypeNoExcept() noexcept
{
return QString();
}
- QString changeTypeConstNoExcept() const Q_DECL_NOTHROW
+ QString changeTypeConstNoExcept() const noexcept
{
return QString();
}
@@ -2186,8 +2181,8 @@ public:
void updatePeak()
{
forever {
- const int localPeak = peakInstanceCount.load();
- const int localCurrent = currentInstanceCount.load();
+ const int localPeak = peakInstanceCount.loadRelaxed();
+ const int localCurrent = currentInstanceCount.loadRelaxed();
if (localCurrent <= localPeak)
break;
if (peakInstanceCount.testAndSetOrdered(localPeak, localCurrent))
@@ -2225,35 +2220,35 @@ void tst_QtConcurrentMap::throttling()
const int allowedTemporaries = QThread::idealThreadCount() * 40;
{
- currentInstanceCount.store(0);
- peakInstanceCount.store(0);
+ currentInstanceCount.storeRelaxed(0);
+ peakInstanceCount.storeRelaxed(0);
QList<InstanceCounter> instances;
for (int i = 0; i < itemcount; ++i)
instances.append(InstanceCounter());
- QCOMPARE(currentInstanceCount.load(), itemcount);
+ QCOMPARE(currentInstanceCount.loadRelaxed(), itemcount);
int results = QtConcurrent::blockingMappedReduced(instances, slowMap, fastReduce);
QCOMPARE(results, itemcount);
- QCOMPARE(currentInstanceCount.load(), itemcount);
- QVERIFY(peakInstanceCount.load() < itemcount + allowedTemporaries);
+ QCOMPARE(currentInstanceCount.loadRelaxed(), itemcount);
+ QVERIFY(peakInstanceCount.loadRelaxed() < itemcount + allowedTemporaries);
}
{
- QCOMPARE(currentInstanceCount.load(), 0);
- peakInstanceCount.store(0);
+ QCOMPARE(currentInstanceCount.loadRelaxed(), 0);
+ peakInstanceCount.storeRelaxed(0);
QList<InstanceCounter> instances;
for (int i = 0; i < itemcount; ++i)
instances.append(InstanceCounter());
- QCOMPARE(currentInstanceCount.load(), itemcount);
+ QCOMPARE(currentInstanceCount.loadRelaxed(), itemcount);
int results = QtConcurrent::blockingMappedReduced(instances, fastMap, slowReduce);
QCOMPARE(results, itemcount);
- QCOMPARE(currentInstanceCount.load(), itemcount);
- QVERIFY(peakInstanceCount.load() < itemcount + allowedTemporaries);
+ QCOMPARE(currentInstanceCount.loadRelaxed(), itemcount);
+ QVERIFY(peakInstanceCount.loadRelaxed() < itemcount + allowedTemporaries);
}
}
@@ -2385,8 +2380,8 @@ InstanceCounter ic_fn(const InstanceCounter & ic)
// assigned over with operator ==
void tst_QtConcurrentMap::qFutureAssignmentLeak()
{
- currentInstanceCount.store(0);
- peakInstanceCount.store(0);
+ currentInstanceCount.storeRelaxed(0);
+ peakInstanceCount.storeRelaxed(0);
QFuture<InstanceCounter> future;
{
QList<InstanceCounter> list;
@@ -2405,9 +2400,9 @@ void tst_QtConcurrentMap::qFutureAssignmentLeak()
// Use QTRY_COMPARE because QtConcurrent::ThreadEngine::asynchronousFinish()
// deletes its internals after signaling finished, so it might still be holding
// on to copies of InstanceCounter for a short while.
- QTRY_COMPARE(currentInstanceCount.load(), 1000);
+ QTRY_COMPARE(currentInstanceCount.loadRelaxed(), 1000);
future = QFuture<InstanceCounter>();
- QTRY_COMPARE(currentInstanceCount.load(), 0);
+ QTRY_COMPARE(currentInstanceCount.loadRelaxed(), 0);
}
inline void increment(int &num)
diff --git a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
index 1596a9fafd..a4eb2936b5 100644
--- a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
+++ b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
@@ -48,12 +48,8 @@ private slots:
#ifndef QT_NO_EXCEPTIONS
void exceptions();
#endif
-#ifdef Q_COMPILER_DECLTYPE
void functor();
-#endif
-#ifdef Q_COMPILER_LAMBDA
void lambda();
-#endif
};
void light()
@@ -126,23 +122,23 @@ public:
class ANoExcept
{
public:
- int member0() Q_DECL_NOTHROW { return 10; }
- int member1(int in) Q_DECL_NOTHROW { return in; }
+ int member0() noexcept { return 10; }
+ int member1(int in) noexcept { return in; }
typedef int result_type;
- int operator()() Q_DECL_NOTHROW { return 10; }
- int operator()(int in) Q_DECL_NOTHROW { return in; }
+ int operator()() noexcept { return 10; }
+ int operator()(int in) noexcept { return in; }
};
class AConstNoExcept
{
public:
- int member0() const Q_DECL_NOTHROW { return 10; }
- int member1(int in) const Q_DECL_NOTHROW { return in; }
+ int member0() const noexcept { return 10; }
+ int member1(int in) const noexcept { return in; }
typedef int result_type;
- int operator()() const Q_DECL_NOTHROW { return 10; }
- int operator()(int in) const Q_DECL_NOTHROW { return in; }
+ int operator()() const noexcept { return 10; }
+ int operator()(int in) const noexcept { return in; }
};
void tst_QtConcurrentRun::returnValue()
@@ -510,17 +506,17 @@ void tst_QtConcurrentRun::recursive()
int levels = 15;
for (int i = 0; i < QThread::idealThreadCount(); ++i) {
- count.store(0);
+ count.storeRelaxed(0);
QThreadPool::globalInstance()->setMaxThreadCount(i);
recursiveRun(levels);
- QCOMPARE(count.load(), (int)std::pow(2.0, levels) - 1);
+ QCOMPARE(count.loadRelaxed(), (int)std::pow(2.0, levels) - 1);
}
for (int i = 0; i < QThread::idealThreadCount(); ++i) {
- count.store(0);
+ count.storeRelaxed(0);
QThreadPool::globalInstance()->setMaxThreadCount(i);
recursiveResult(levels);
- QCOMPARE(count.load(), (int)std::pow(2.0, levels) - 1);
+ QCOMPARE(count.loadRelaxed(), (int)std::pow(2.0, levels) - 1);
}
}
@@ -574,7 +570,7 @@ public:
static QAtomicInt cancel;
void run() override {
int iter = 60;
- while (--iter && !cancel.load())
+ while (--iter && !cancel.loadRelaxed())
QThread::currentThread()->msleep(25);
}
};
@@ -642,13 +638,12 @@ void tst_QtConcurrentRun::exceptions()
caught = true;
}
- SlowTask::cancel.store(true);
+ SlowTask::cancel.storeRelaxed(true);
QVERIFY2(caught, "did not get exception");
}
#endif
-#ifdef Q_COMPILER_DECLTYPE
// Compiler supports decltype
struct Functor {
int operator()() { return 42; }
@@ -706,9 +701,7 @@ void tst_QtConcurrentRun::functor()
QtConcurrent::run(&pool, f, 1,2,3,4,5).waitForFinished();
}
}
-#endif
-#ifdef Q_COMPILER_LAMBDA
// Compiler supports lambda
void tst_QtConcurrentRun::lambda()
{
@@ -717,14 +710,12 @@ void tst_QtConcurrentRun::lambda()
QCOMPARE(QtConcurrent::run([](int a, double b){ return a + b; }, 12, 15).result(), double(12+15));
QCOMPARE(QtConcurrent::run([](int a , int, int, int, int b){ return a + b; }, 1, 2, 3, 4, 5).result(), 1 + 5);
-#ifdef Q_COMPILER_INITIALIZER_LISTS
{
QString str { "Hello World Foo" };
QFuture<QStringList> f1 = QtConcurrent::run([&](){ return str.split(' '); });
auto r = f1.result();
QCOMPARE(r, QStringList({"Hello", "World", "Foo"}));
}
-#endif
// and now with explicit pool:
QThreadPool pool;
@@ -733,16 +724,13 @@ void tst_QtConcurrentRun::lambda()
QCOMPARE(QtConcurrent::run(&pool, [](int a, double b){ return a + b; }, 12, 15).result(), double(12+15));
QCOMPARE(QtConcurrent::run(&pool, [](int a , int, int, int, int b){ return a + b; }, 1, 2, 3, 4, 5).result(), 1 + 5);
-#ifdef Q_COMPILER_INITIALIZER_LISTS
{
QString str { "Hello World Foo" };
QFuture<QStringList> f1 = QtConcurrent::run(&pool, [&](){ return str.split(' '); });
auto r = f1.result();
QCOMPARE(r, QStringList({"Hello", "World", "Foo"}));
}
-#endif
}
-#endif
QTEST_MAIN(tst_QtConcurrentRun)
#include "tst_qtconcurrentrun.moc"
diff --git a/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp b/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
index a68f7d5a4e..d4c669cddc 100644
--- a/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
+++ b/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp
@@ -28,6 +28,7 @@
#include <qtconcurrentthreadengine.h>
#include <qexception.h>
#include <QThread>
+#include <QElapsedTimer>
#include <QtTest/QtTest>
using namespace QtConcurrent;
@@ -186,7 +187,7 @@ class ThrottleAlwaysUser : public ThreadEngine<void>
public:
ThrottleAlwaysUser()
{
- count.store(initialCount = 100);
+ count.storeRelaxed(initialCount = 100);
finishing = false;
}
@@ -198,7 +199,7 @@ public:
ThreadFunctionResult threadFunction()
{
forever {
- const int local = count.load();
+ const int local = count.loadRelaxed();
if (local == 0) {
finishing = true;
return ThreadFinished;
@@ -223,13 +224,13 @@ void tst_QtConcurrentThreadEngine::throttle()
for (int i = 0; i < repeats; ++i) {
QFuture<void> f = (new ThrottleAlwaysUser())->startAsynchronously();
f.waitForFinished();
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
}
for (int i = 0; i < repeats; ++i) {
ThrottleAlwaysUser t;
t.startBlocking();
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
}
}
@@ -382,7 +383,7 @@ void tst_QtConcurrentThreadEngine::cancelQueuedSlowUser()
{
const int times = 100;
- QTime t;
+ QElapsedTimer t;
t.start();
{
diff --git a/tests/auto/corelib/corelib.pro b/tests/auto/corelib/corelib.pro
index 44e1c519b0..1d76e1549b 100644
--- a/tests/auto/corelib/corelib.pro
+++ b/tests/auto/corelib/corelib.pro
@@ -14,4 +14,5 @@ SUBDIRS = \
serialization \
statemachine \
thread \
+ time \
tools
diff --git a/tests/auto/corelib/global/qflags/tst_qflags.cpp b/tests/auto/corelib/global/qflags/tst_qflags.cpp
index 72b086350e..1568855032 100644
--- a/tests/auto/corelib/global/qflags/tst_qflags.cpp
+++ b/tests/auto/corelib/global/qflags/tst_qflags.cpp
@@ -142,7 +142,6 @@ void tst_QFlags::signedness()
std::is_signed<Qt::Alignment::Int>::value));
}
-#if defined(Q_COMPILER_CLASS_ENUM)
enum class MyStrictEnum { StrictZero, StrictOne, StrictTwo, StrictFour=4 };
Q_DECLARE_FLAGS( MyStrictFlags, MyStrictEnum )
Q_DECLARE_OPERATORS_FOR_FLAGS( MyStrictFlags )
@@ -154,11 +153,9 @@ Q_STATIC_ASSERT( !QTypeInfo<MyStrictFlags>::isComplex );
Q_STATIC_ASSERT( !QTypeInfo<MyStrictFlags>::isStatic );
Q_STATIC_ASSERT( !QTypeInfo<MyStrictFlags>::isLarge );
Q_STATIC_ASSERT( !QTypeInfo<MyStrictFlags>::isPointer );
-#endif
void tst_QFlags::classEnum()
{
-#if defined(Q_COMPILER_CLASS_ENUM)
// The main aim of the test is making sure it compiles
// The QCOMPARE are there as an extra
MyStrictEnum e1 = MyStrictEnum::StrictOne;
@@ -257,27 +254,19 @@ void tst_QFlags::classEnum()
// Just to make sure it compiles
if (false)
qDebug() << f3;
-#endif
}
void tst_QFlags::initializerLists()
{
-#if defined(Q_COMPILER_INITIALIZER_LISTS)
Qt::MouseButtons bts = { Qt::LeftButton, Qt::RightButton };
QVERIFY(bts.testFlag(Qt::LeftButton));
QVERIFY(bts.testFlag(Qt::RightButton));
QVERIFY(!bts.testFlag(Qt::MiddleButton));
-#if defined(Q_COMPILER_CLASS_ENUM)
MyStrictNoOpFlags flags = { MyStrictNoOpEnum::StrictOne, MyStrictNoOpEnum::StrictFour };
QVERIFY(flags.testFlag(MyStrictNoOpEnum::StrictOne));
QVERIFY(flags.testFlag(MyStrictNoOpEnum::StrictFour));
QVERIFY(!flags.testFlag(MyStrictNoOpEnum::StrictTwo));
-#endif // Q_COMPILER_CLASS_ENUM
-
-#else
- QSKIP("This test requires C++11 initializer_list support.");
-#endif // Q_COMPILER_INITIALIZER_LISTS
}
void tst_QFlags::testSetFlags()
diff --git a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp
index b73a297245..5c7737085e 100644
--- a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp
+++ b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 by Southwest Research Institute (R)
** Contact: https://www.qt.io/licensing/
**
@@ -48,6 +49,7 @@ private slots:
void arithOps();
void floatToFloat16();
void floatFromFloat16();
+ void limits();
};
void tst_qfloat16::fuzzyCompare_data()
@@ -347,5 +349,164 @@ void tst_qfloat16::floatFromFloat16()
QCOMPARE(out[i], expected[i]);
}
+static qfloat16 powf16(qfloat16 base, int raise)
+{
+ const qfloat16 one(1.f);
+ if (raise < 0) {
+ raise = -raise;
+ base = one / base;
+ }
+ qfloat16 answer = (raise & 1) ? base : one;
+ while (raise > 0) {
+ raise >>= 1;
+ base *= base;
+ if (raise & 1)
+ answer *= base;
+ }
+ return answer;
+}
+
+void tst_qfloat16::limits()
+{
+ // *NOT* using QCOMPARE() on finite qfloat16 values, since that uses fuzzy
+ // comparison, and we need exact here.
+ using Bounds = std::numeric_limits<qfloat16>;
+ QVERIFY(Bounds::is_specialized);
+ QVERIFY(Bounds::is_signed);
+ QVERIFY(!Bounds::is_integer);
+ QVERIFY(!Bounds::is_exact);
+ QVERIFY(Bounds::is_iec559);
+ QVERIFY(Bounds::is_bounded);
+ QVERIFY(!Bounds::is_modulo);
+ QVERIFY(!Bounds::traps);
+ QVERIFY(Bounds::has_infinity);
+ QVERIFY(Bounds::has_quiet_NaN);
+ QVERIFY(Bounds::has_signaling_NaN);
+ QCOMPARE(Bounds::has_denorm, std::denorm_present);
+ QCOMPARE(Bounds::round_style, std::round_to_nearest);
+ QCOMPARE(Bounds::radix, 2);
+ // Untested: has_denorm_loss
+
+ // A few common values:
+ const qfloat16 zero(0), one(1), ten(10);
+ QVERIFY(qIsFinite(zero));
+ QVERIFY(!qIsInf(zero));
+ QVERIFY(!qIsNaN(zero));
+ QCOMPARE(qFpClassify(zero), FP_ZERO);
+ QVERIFY(qIsFinite(one));
+ QVERIFY(!qIsInf(one));
+ QCOMPARE(qFpClassify(one), FP_NORMAL);
+ QVERIFY(!qIsNaN(one));
+ QVERIFY(qIsFinite(ten));
+ QVERIFY(!qIsInf(ten));
+ QVERIFY(!qIsNaN(ten));
+ QCOMPARE(qFpClassify(ten), FP_NORMAL);
+
+ // digits in the mantissa, including the implicit 1 before the binary dot at its left:
+ QVERIFY(qfloat16(1 << (Bounds::digits - 1)) + one > qfloat16(1 << (Bounds::digits - 1)));
+ QVERIFY(qfloat16(1 << Bounds::digits) + one == qfloat16(1 << Bounds::digits));
+
+ // There is a wilful of-by-one in how m(ax|in)_exponent are defined; they're
+ // the lowest and highest n for which radix^{n-1} are normal and finite.
+ const qfloat16 two(Bounds::radix);
+ qfloat16 bit = powf16(two, Bounds::max_exponent - 1);
+ QVERIFY(qIsFinite(bit));
+ QVERIFY(qIsInf(bit * two));
+ bit = powf16(two, Bounds::min_exponent - 1);
+ QVERIFY(bit.isNormal());
+ QCOMPARE(qFpClassify(bit), FP_NORMAL);
+ QVERIFY(!(bit / two).isNormal());
+ QCOMPARE(qFpClassify(bit / two), FP_SUBNORMAL);
+ QVERIFY(bit / two > zero);
+
+ // Base ten (with no matching off-by-one idiocy):
+ // the lowest negative number n such that 10^n is a valid normalized value
+ qfloat16 low10(powf16(ten, Bounds::min_exponent10));
+ QVERIFY(low10 > zero);
+ QVERIFY(low10.isNormal());
+ low10 /= ten;
+ QVERIFY(low10 == zero || !low10.isNormal());
+ // the largest positive number n such that 10^n is a representable finite value
+ qfloat16 high10(powf16(ten, Bounds::max_exponent10));
+ QVERIFY(high10 > zero);
+ QVERIFY(qIsFinite(high10));
+ QVERIFY(!qIsFinite(high10 * ten));
+ QCOMPARE(qFpClassify(high10), FP_NORMAL);
+
+ // How many digits are significant ? (Casts avoid linker errors ...)
+ QCOMPARE(int(Bounds::digits10), 3); // 9.79e-4 has enough sigificant digits:
+ qfloat16 below(9.785e-4f), above(9.794e-4f);
+#if 0 // Sadly, the QEMU x-compile for arm64 "optimises" comparisons:
+ const bool overOptimised = false;
+#else
+ const bool overOptimised = (below != above);
+ if (overOptimised)
+ QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
+#endif // (but it did, so should, pass everywhere else, confirming digits10 is indeed 3).
+ QVERIFY(below == above);
+ QCOMPARE(int(Bounds::max_digits10), 5); // we need 5 to distinguish these two:
+ QVERIFY(qfloat16(1000.5f) != qfloat16(1001.4f));
+
+ // Actual limiting values of the type:
+ const qfloat16 rose(one + Bounds::epsilon());
+ QVERIFY(rose > one);
+ if (overOptimised)
+ QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
+ QVERIFY(one + Bounds::epsilon() / rose == one);
+ QVERIFY(qIsInf(Bounds::infinity()));
+ QVERIFY(!qIsNaN(Bounds::infinity()));
+ QVERIFY(!qIsFinite(Bounds::infinity()));
+ QCOMPARE(Bounds::infinity(), Bounds::infinity());
+ QCOMPARE(qFpClassify(Bounds::infinity()), FP_INFINITE);
+
+ QVERIFY(Bounds::infinity() > -Bounds::infinity());
+ QVERIFY(Bounds::infinity() > zero);
+ QVERIFY(qIsInf(-Bounds::infinity()));
+ QVERIFY(!qIsNaN(-Bounds::infinity()));
+ QVERIFY(!qIsFinite(-Bounds::infinity()));
+ QCOMPARE(-Bounds::infinity(), -Bounds::infinity());
+ QCOMPARE(qFpClassify(-Bounds::infinity()), FP_INFINITE);
+
+ QVERIFY(-Bounds::infinity() < zero);
+ QVERIFY(qIsNaN(Bounds::quiet_NaN()));
+ QVERIFY(!qIsInf(Bounds::quiet_NaN()));
+ QVERIFY(!qIsFinite(Bounds::quiet_NaN()));
+ QVERIFY(!(Bounds::quiet_NaN() == Bounds::quiet_NaN()));
+ QCOMPARE(Bounds::quiet_NaN(), Bounds::quiet_NaN());
+ QCOMPARE(qFpClassify(Bounds::quiet_NaN()), FP_NAN);
+
+ QVERIFY(Bounds::max() > zero);
+ QVERIFY(qIsFinite(Bounds::max()));
+ QVERIFY(!qIsInf(Bounds::max()));
+ QVERIFY(!qIsNaN(Bounds::max()));
+ QVERIFY(qIsInf(Bounds::max() * rose));
+ QCOMPARE(qFpClassify(Bounds::max()), FP_NORMAL);
+
+ QVERIFY(Bounds::lowest() < zero);
+ QVERIFY(qIsFinite(Bounds::lowest()));
+ QVERIFY(!qIsInf(Bounds::lowest()));
+ QVERIFY(!qIsNaN(Bounds::lowest()));
+ QVERIFY(qIsInf(Bounds::lowest() * rose));
+ QCOMPARE(qFpClassify(Bounds::lowest()), FP_NORMAL);
+
+ QVERIFY(Bounds::min() > zero);
+ QVERIFY(Bounds::min().isNormal());
+ QVERIFY(!(Bounds::min() / rose).isNormal());
+ QVERIFY(qIsFinite(Bounds::min()));
+ QVERIFY(!qIsInf(Bounds::min()));
+ QVERIFY(!qIsNaN(Bounds::min()));
+ QCOMPARE(qFpClassify(Bounds::min()), FP_NORMAL);
+
+ QVERIFY(Bounds::denorm_min() > zero);
+ QVERIFY(!Bounds::denorm_min().isNormal());
+ QVERIFY(qIsFinite(Bounds::denorm_min()));
+ QVERIFY(!qIsInf(Bounds::denorm_min()));
+ QVERIFY(!qIsNaN(Bounds::denorm_min()));
+ if (overOptimised)
+ QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
+ QCOMPARE(Bounds::denorm_min() / rose, zero);
+ QCOMPARE(qFpClassify(Bounds::denorm_min()), FP_SUBNORMAL);
+}
+
QTEST_APPLESS_MAIN(tst_qfloat16)
#include "tst_qfloat16.moc"
diff --git a/tests/auto/corelib/global/qglobal/qglobal.c b/tests/auto/corelib/global/qglobal/qglobal.c
index 0719c4b921..c7124454d0 100644
--- a/tests/auto/corelib/global/qglobal/qglobal.c
+++ b/tests/auto/corelib/global/qglobal/qglobal.c
@@ -85,7 +85,7 @@ int tst_QtVersion()
return QT_VERSION;
}
-const char *tst_qVersion() Q_DECL_NOTHROW
+const char *tst_qVersion() Q_DECL_NOEXCEPT
{
#if !defined(QT_NAMESPACE)
return qVersion();
diff --git a/tests/auto/corelib/global/qglobal/qglobal.pro b/tests/auto/corelib/global/qglobal/qglobal.pro
index a40cb9a288..b105769430 100644
--- a/tests/auto/corelib/global/qglobal/qglobal.pro
+++ b/tests/auto/corelib/global/qglobal/qglobal.pro
@@ -2,3 +2,4 @@ CONFIG += testcase
TARGET = tst_qglobal
QT = core testlib
SOURCES = tst_qglobal.cpp qglobal.c
+contains(QT_CONFIG, c++1z): CONFIG += c++1z
diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
index 78b954f373..5e5492de59 100644
--- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
+++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp
@@ -126,6 +126,46 @@ void tst_QGlobal::for_each()
QCOMPARE(i, counter++);
}
QCOMPARE(counter, list.count());
+
+ // Should also work with an existing variable
+ int local;
+ counter = 0;
+ foreach (local, list) {
+ QCOMPARE(local, counter++);
+ }
+ QCOMPARE(counter, list.count());
+ QCOMPARE(local, counter - 1);
+
+ // Test the macro does not mess if/else conditions
+ counter = 0;
+ if (true)
+ foreach (int i, list)
+ QCOMPARE(i, counter++);
+ else
+ QFAIL("If/Else mismatch");
+ QCOMPARE(counter, list.count());
+
+ counter = 0;
+ if (false)
+ foreach (int i, list)
+ if (i) QFAIL("If/Else mismatch");
+ else QFAIL("If/Else mismatch");
+ else
+ foreach (int i, list)
+ if (false) { }
+ else QCOMPARE(i, counter++);
+ QCOMPARE(counter, list.count());
+
+ // break and continue
+ counter = 0;
+ foreach (int i, list) {
+ if (i == 0)
+ continue;
+ QCOMPARE(i, (counter++) + 1);
+ if (i == 3)
+ break;
+ }
+ QCOMPARE(counter, 3);
}
void tst_QGlobal::qassert()
@@ -416,12 +456,8 @@ typedef int (Empty::*memFun) ();
} while (false) \
/**/
-#ifdef Q_COMPILER_RVALUE_REFS
#define TEST_AlignOf_RValueRef(type, alignment) \
TEST_AlignOf_impl(type, alignment)
-#else
-#define TEST_AlignOf_RValueRef(type, alignment) do {} while (false)
-#endif
#define TEST_AlignOf_impl(type, alignment) \
do { \
diff --git a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp
index 2d7db813dd..820a0b999b 100644
--- a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp
+++ b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp
@@ -145,7 +145,7 @@ void tst_QGlobalStatic::exception()
exceptionCaught = true;
}
QVERIFY(exceptionCaught);
- QCOMPARE(Q_QGS_throwingGS::guard.load(), 0);
+ QCOMPARE(Q_QGS_throwingGS::guard.loadRelaxed(), 0);
QVERIFY(!throwingGS.exists());
QVERIFY(!throwingGS.isDestroyed());
}
@@ -154,10 +154,10 @@ QBasicAtomicInt exceptionControlVar = Q_BASIC_ATOMIC_INITIALIZER(1);
Q_GLOBAL_STATIC_WITH_ARGS(ThrowingType, exceptionGS, (exceptionControlVar))
void tst_QGlobalStatic::catchExceptionAndRetry()
{
- if (exceptionControlVar.load() != 1)
+ if (exceptionControlVar.loadRelaxed() != 1)
QSKIP("This test cannot be run more than once");
- ThrowingType::constructedCount.store(0);
- ThrowingType::destructedCount.store(0);
+ ThrowingType::constructedCount.storeRelaxed(0);
+ ThrowingType::destructedCount.storeRelaxed(0);
bool exceptionCaught = false;
try {
@@ -165,11 +165,11 @@ void tst_QGlobalStatic::catchExceptionAndRetry()
} catch (int) {
exceptionCaught = true;
}
- QCOMPARE(ThrowingType::constructedCount.load(), 1);
+ QCOMPARE(ThrowingType::constructedCount.loadRelaxed(), 1);
QVERIFY(exceptionCaught);
exceptionGS();
- QCOMPARE(ThrowingType::constructedCount.load(), 2);
+ QCOMPARE(ThrowingType::constructedCount.loadRelaxed(), 2);
}
QBasicAtomicInt threadStressTestControlVar = Q_BASIC_ATOMIC_INITIALIZER(5);
@@ -194,9 +194,9 @@ void tst_QGlobalStatic::threadStressTest()
}
};
- ThrowingType::constructedCount.store(0);
- ThrowingType::destructedCount.store(0);
- int expectedConstructionCount = threadStressTestControlVar.load() + 1;
+ ThrowingType::constructedCount.storeRelaxed(0);
+ ThrowingType::destructedCount.storeRelaxed(0);
+ int expectedConstructionCount = threadStressTestControlVar.loadRelaxed() + 1;
if (expectedConstructionCount <= 0)
QSKIP("This test cannot be run more than once");
diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
index d3ed1a6d0d..23507ec2e6 100644
--- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
+++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
@@ -254,19 +254,15 @@ public:
int rvalue() && { ADD("TestClass1::rvalue"); return 0; }
int const_rvalue() const && { ADD("TestClass1::const_rvalue"); return 0; }
#endif
-#ifdef Q_COMPILER_DECLTYPE
int decltype_param(int x = 0, decltype(x) = 0) { ADD("TestClass1::decltype_param"); return x; }
template<typename T> int decltype_template_param(T x = 0, decltype(x) = 0)
{ ADD("TestClass1::decltype_template_param"); return x; }
template<typename T> void decltype_template_param2(T x, decltype(x + QString()))
{ ADD("TestClass1::decltype_template_param2"); }
-# ifdef Q_COMPILER_AUTO_FUNCTION
auto decltype_return(int x = 0) -> decltype(x)
{ ADD("TestClass1::decltype_return"); return x; }
template <typename T> auto decltype_template_return(T x = 0) -> decltype(x)
{ ADD("TestClass1::decltype_template_return"); return x; }
-# endif
-#endif
public:
TestClass1()
@@ -323,15 +319,11 @@ public:
std::move(*this).rvalue();
std::move(*this).const_rvalue();
#endif
-#ifdef Q_COMPILER_DECLTYPE
decltype_param();
decltype_template_param(0);
decltype_template_param2(QByteArray(), QString());
-# ifdef Q_COMPILER_AUTO_FUNCTION
decltype_return();
decltype_template_return(0);
-# endif
-#endif
}
};
@@ -878,12 +870,14 @@ void tst_qmessagehandler::setMessagePattern()
#endif
// make sure there is no QT_MESSAGE_PATTERN in the environment
- QStringList environment = m_baseEnvironment;
- QMutableListIterator<QString> iter(environment);
- while (iter.hasNext()) {
- if (iter.next().startsWith("QT_MESSAGE_PATTERN"))
- iter.remove();
- }
+ QStringList environment;
+ environment.reserve(m_baseEnvironment.size());
+ const auto doesNotStartWith = [](QLatin1String s) {
+ return [s](const QString &str) { return !str.startsWith(s); };
+ };
+ std::copy_if(m_baseEnvironment.cbegin(), m_baseEnvironment.cend(),
+ std::back_inserter(environment),
+ doesNotStartWith(QLatin1String("QT_MESSAGE_PATTERN")));
process.setEnvironment(environment);
process.start(appExe);
diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
index 03300c6dbe..0a84b1fdd8 100644
--- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
+++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -42,7 +42,8 @@ class tst_QNumeric: public QObject
private slots:
void fuzzyCompare_data();
void fuzzyCompare();
- void qNan();
+ void qNanInf();
+ void classifyfp();
void floatDistance_data();
void floatDistance();
void floatDistance_double_data();
@@ -91,7 +92,7 @@ void tst_QNumeric::fuzzyCompare()
# pragma GCC optimize "no-fast-math"
#endif
-void tst_QNumeric::qNan()
+void tst_QNumeric::qNanInf()
{
#if defined __FAST_MATH__ && (__GNUC__ * 100 + __GNUC_MINOR__ < 404)
QSKIP("Non-conformant fast math mode is enabled, cannot run test");
@@ -99,9 +100,16 @@ void tst_QNumeric::qNan()
double nan = qQNaN();
QVERIFY(!(0 > nan));
QVERIFY(!(0 < nan));
+ QVERIFY(!(0 == nan));
+ QVERIFY(!(nan == nan));
QVERIFY(qIsNaN(nan));
QVERIFY(qIsNaN(nan + 1));
QVERIFY(qIsNaN(-nan));
+ QVERIFY(qIsNaN(1.0 / nan));
+ QVERIFY(qIsNaN(0.0 / nan));
+ QVERIFY(qIsNaN(0.0 * nan));
+ QCOMPARE(nan, nan);
+ QCOMPARE(nan, -nan);
Q_STATIC_ASSERT(sizeof(double) == 8);
#ifdef Q_LITTLE_ENDIAN
@@ -113,17 +121,56 @@ void tst_QNumeric::qNan()
QVERIFY(!qIsFinite(nan));
QVERIFY(!qIsInf(nan));
QVERIFY(qIsNaN(nan));
+ QVERIFY(qIsNaN(-nan));
+ QVERIFY(!(nan == nan));
+ QVERIFY(qIsNaN(0.0 * nan));
+ QCOMPARE(qFpClassify(nan), FP_NAN);
+ QCOMPARE(nan, nan);
+ QCOMPARE(nan, -nan);
+ QCOMPARE(nan, qQNaN());
double inf = qInf();
QVERIFY(inf > 0);
QVERIFY(-inf < 0);
QVERIFY(qIsInf(inf));
+ QCOMPARE(inf, inf);
+ QCOMPARE(-inf, -inf);
QVERIFY(qIsInf(-inf));
- QVERIFY(qIsInf(2*inf));
- QCOMPARE(1/inf, 0.0);
- QVERIFY(qIsNaN(0*nan));
- QVERIFY(qIsNaN(0*inf));
- QVERIFY(qFuzzyCompare(1/inf, 0.0));
+ QVERIFY(qIsInf(inf + 1));
+ QVERIFY(qIsInf(inf - 1));
+ QVERIFY(qIsInf(inf * 2.0));
+ QVERIFY(qIsInf(inf / 2.0));
+ QVERIFY(qFuzzyCompare(1.0 / inf, 0.0));
+ QCOMPARE(1.0 / inf, 0.0);
+ QVERIFY(qIsNaN(0.0 * inf));
+}
+
+void tst_QNumeric::classifyfp()
+{
+ QCOMPARE(qFpClassify(qQNaN()), FP_NAN);
+
+ QCOMPARE(qFpClassify(qInf()), FP_INFINITE);
+ QCOMPARE(qFpClassify(-qInf()), FP_INFINITE);
+ QCOMPARE(qFpClassify(DBL_MAX * 2.0), FP_INFINITE);
+ QCOMPARE(qFpClassify(FLT_MAX * 2.f), FP_INFINITE);
+ QCOMPARE(qFpClassify(DBL_MAX * -2.0), FP_INFINITE);
+ QCOMPARE(qFpClassify(FLT_MAX * -2.f), FP_INFINITE);
+
+ QCOMPARE(qFpClassify(1.0), FP_NORMAL);
+ QCOMPARE(qFpClassify(DBL_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(-DBL_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(DBL_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(-DBL_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(DBL_MIN / 2.0), FP_SUBNORMAL);
+ QCOMPARE(qFpClassify(DBL_MIN / -2.0), FP_SUBNORMAL);
+
+ QCOMPARE(qFpClassify(1.f), FP_NORMAL);
+ QCOMPARE(qFpClassify(FLT_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(-FLT_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(FLT_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(-FLT_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(FLT_MIN / 2.f), FP_SUBNORMAL);
+ QCOMPARE(qFpClassify(FLT_MIN / -2.f), FP_SUBNORMAL);
}
void tst_QNumeric::floatDistance_data()
@@ -461,13 +508,13 @@ template <typename Int> static void mulOverflow_template()
QCOMPARE(mul_overflow(Int(max / 2), Int(3), &r), true);
QCOMPARE(mul_overflow(mid1, Int(mid2 + 1), &r), true);
QCOMPARE(mul_overflow(Int(max / 2 + 2), Int(2), &r), true);
+ QCOMPARE(mul_overflow(Int(max - max / 2), Int(2), &r), true);
QCOMPARE(mul_overflow(Int(1ULL << (std::numeric_limits<Int>::digits - 1)), Int(2), &r), true);
if (min) {
QCOMPARE(mul_overflow(min, Int(2), &r), true);
QCOMPARE(mul_overflow(Int(min / 2), Int(3), &r), true);
QCOMPARE(mul_overflow(Int(min / 2 - 1), Int(2), &r), true);
- QCOMPARE(mul_overflow(Int(min + min/2), Int(2), &r), true);
}
#endif
}
diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
index 7c04611823..e238be1de3 100644
--- a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
+++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
@@ -57,7 +57,7 @@ static const double RandomValueFP = double(0.3010463714599609);
static void setRNGControl(uint v)
{
#ifdef QT_BUILD_INTERNAL
- qt_randomdevice_control.store(v);
+ qt_randomdevice_control.storeRelaxed(v);
#else
Q_UNUSED(v);
#endif
@@ -511,7 +511,7 @@ void tst_QRandomGenerator::generateNonContiguous()
QFETCH(uint, control);
RandomGenerator rng(control);
- QLinkedList<quint64> list = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ std::list<quint64> list(8);
auto longerArrayCheck = [&] {
QRandomGenerator().generate(list.begin(), list.end());
return find_if(list.begin(), list.end(), [&](quint64 cur) {
diff --git a/tests/auto/corelib/io/largefile/tst_largefile.cpp b/tests/auto/corelib/io/largefile/tst_largefile.cpp
index dca7672b8e..f459f62c91 100644
--- a/tests/auto/corelib/io/largefile/tst_largefile.cpp
+++ b/tests/auto/corelib/io/largefile/tst_largefile.cpp
@@ -36,6 +36,7 @@
#include <QDebug>
+#include <algorithm>
#include <cstdlib>
#include <cstdio>
@@ -489,13 +490,13 @@ void tst_LargeFile::mapFile()
// Keep full block mapped to facilitate OS and/or internal reuse by Qt.
uchar *baseAddress = largeFile.map(position, blockSize);
QVERIFY( baseAddress );
- QVERIFY( qEqual(block.begin(), block.end(), reinterpret_cast<char*>(baseAddress)) );
+ QVERIFY( std::equal(block.begin(), block.end(), reinterpret_cast<char*>(baseAddress)) );
for (int offset = 1; offset < blockSize; ++offset) {
uchar *address = largeFile.map(position + offset, blockSize - offset);
QVERIFY( address );
- if ( !qEqual(block.begin() + offset, block.end(), reinterpret_cast<char*>(address)) ) {
+ if ( !std::equal(block.begin() + offset, block.end(), reinterpret_cast<char*>(address)) ) {
qDebug() << "Expected:" << block.toHex();
qDebug() << "Actual :" << QByteArray(reinterpret_cast<char*>(address), blockSize).toHex();
QVERIFY(false);
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index 7b8b1df166..a818c6c09d 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -309,7 +309,7 @@ void tst_QDebug::stateSaver() const
QDebug d = qDebug();
{
QDebugStateSaver saver(d);
- d.nospace() << hex << right << qSetFieldWidth(3) << qSetPadChar('0') << 42;
+ d.nospace() << Qt::hex << Qt::right << qSetFieldWidth(3) << qSetPadChar('0') << 42;
}
d << 42;
}
@@ -327,7 +327,7 @@ void tst_QDebug::stateSaver() const
{
QDebug d = qDebug();
- d.noquote().nospace() << QStringLiteral("Hello") << hex << 42;
+ d.noquote().nospace() << QStringLiteral("Hello") << Qt::hex << 42;
{
QDebugStateSaver saver(d);
d.resetFormat();
@@ -660,7 +660,7 @@ void tst_QDebug::textStreamModifiers() const
QString file, function;
int line = 0;
MessageHandlerSetter mhs(myMessageHandler);
- { qDebug() << hex << short(0xf) << int(0xf) << unsigned(0xf) << long(0xf) << qint64(0xf) << quint64(0xf); }
+ { qDebug() << Qt::hex << short(0xf) << int(0xf) << unsigned(0xf) << long(0xf) << qint64(0xf) << quint64(0xf); }
#ifndef QT_NO_MESSAGELOGCONTEXT
file = __FILE__; line = __LINE__ - 2; function = Q_FUNC_INFO;
#endif
@@ -678,7 +678,7 @@ void tst_QDebug::resetFormat() const
MessageHandlerSetter mhs(myMessageHandler);
{
QDebug d = qDebug();
- d.nospace().noquote() << hex << int(0xf);
+ d.nospace().noquote() << Qt::hex << int(0xf);
d.resetFormat() << int(0xf) << QStringLiteral("foo");
}
#ifndef QT_NO_MESSAGELOGCONTEXT
diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp
index 34588b19bc..2aebc67dcf 100644
--- a/tests/auto/corelib/io/qdir/tst_qdir.cpp
+++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp
@@ -349,21 +349,21 @@ void tst_QDir::mkdirRmdir_data()
QTest::addColumn<QString>("path");
QTest::addColumn<bool>("recurse");
- QStringList dirs;
- dirs << "testdir/one"
- << "testdir/two/three/four"
- << "testdir/../testdir/three";
- QTest::newRow("plain") << QDir::currentPath() + "/" + dirs.at(0) << false;
- QTest::newRow("recursive") << QDir::currentPath() + "/" + dirs.at(1) << true;
- QTest::newRow("with-..") << QDir::currentPath() + "/" + dirs.at(2) << false;
-
- QTest::newRow("relative-plain") << dirs.at(0) << false;
- QTest::newRow("relative-recursive") << dirs.at(1) << true;
- QTest::newRow("relative-with-..") << dirs.at(2) << false;
-
- // Ensure that none of these directories already exist
- for (int i = 0; i < dirs.count(); ++i)
- QVERIFY(!QFile::exists(dirs.at(i)));
+ const struct {
+ const char *name; // shall have a prefix added
+ const char *path; // relative
+ bool recurse;
+ } cases[] = {
+ { "plain", "testdir/one", false },
+ { "recursive", "testdir/two/three/four", true },
+ { "with-..", "testdir/../testdir/three", false },
+ };
+
+ for (const auto &it : cases) {
+ QVERIFY(!QFile::exists(it.path));
+ QTest::addRow("absolute-%s", it.name) << (QDir::currentPath() + "/") + it.path << it.recurse;
+ QTest::addRow("relative-%s", it.name) << QString::fromLatin1(it.path) << it.recurse;
+ }
}
void tst_QDir::mkdirRmdir()
@@ -2045,7 +2045,7 @@ void tst_QDir::detachingOperations()
QCOMPARE(dir2.nameFilters(), nameFilters);
QCOMPARE(dir2.sorting(), sorting);
- dir2 = path1;
+ dir2.setPath(path1);
QCOMPARE(dir2.path(), path1);
QCOMPARE(dir2.filter(), filter);
QCOMPARE(dir2.nameFilters(), nameFilters);
diff --git a/tests/auto/corelib/io/qfile/test.pro b/tests/auto/corelib/io/qfile/test.pro
index 95389ab3e2..7a2767bf3c 100644
--- a/tests/auto/corelib/io/qfile/test.pro
+++ b/tests/auto/corelib/io/qfile/test.pro
@@ -23,4 +23,4 @@ TESTDATA += \
Makefile forCopying.txt forRenaming.txt \
resources/file1.ext1
-win32:!winrt: LIBS += -lole32 -luuid
+win32:!winrt: QMAKE_USE += ole32 uuid
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index 678a80c3f7..4f010f37c2 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -2099,7 +2099,7 @@ void tst_QFile::i18nFileName()
QVERIFY2(file.open(QFile::WriteOnly | QFile::Text), msgOpenFailed(file).constData());
QTextStream ts(&file);
ts.setCodec("UTF-8");
- ts << fileName << endl;
+ ts << fileName << Qt::endl;
}
{
QFile file(fileName);
@@ -2149,7 +2149,7 @@ void tst_QFile::longFileName()
QFile file(fileName);
QVERIFY2(file.open(QFile::WriteOnly | QFile::Text), msgOpenFailed(file).constData());
QTextStream ts(&file);
- ts << fileName << endl;
+ ts << fileName << Qt::endl;
}
{
QFile file(fileName);
diff --git a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro
index 496729f9f1..d181d16a3e 100644
--- a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro
+++ b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro
@@ -5,4 +5,4 @@ SOURCES = tst_qfileinfo.cpp
RESOURCES += qfileinfo.qrc \
testdata.qrc
-win32:!winrt: LIBS += -ladvapi32 -lnetapi32
+win32:!winrt: QMAKE_USE += advapi32 netapi32
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index baf78f6a04..0944ec252e 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -96,31 +96,36 @@ inline bool qIsLikelyToBeNfs(const QString &path)
}
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
-enum NtfsTargetType {
- NtfsTargetFile = 0x0,
- NtfsTargetDir = 0x1
-};
-
-static bool createNtfsSymLinkHelper(const QString &path, const QString &target, NtfsTargetType targetType)
-{
- DWORD dwFlags = targetType;
- DWORD err = ERROR_SUCCESS;
-
- SetLastError(0);
- const bool result = CreateSymbolicLink(reinterpret_cast<const wchar_t*>(path.utf16()),
- reinterpret_cast<const wchar_t*>(target.utf16()), dwFlags);
- err = GetLastError();
-
- // CreateSymbolicLink can return TRUE & still fail to create the link,
- // the error code in that case might be ERROR_PRIVILEGE_NOT_HELD (1314)
- if (!result || err != ERROR_SUCCESS) {
- qWarning() << "Error creating NTFS-symlink from:" << path << "to" << target << ":" << qt_error_string(err);
+# ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE // MinGW
+# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2)
+# endif
- return false;
+static DWORD createSymbolicLink(const QString &symLinkName, const QString &target,
+ QString *errorMessage)
+{
+ DWORD result = ERROR_SUCCESS;
+ const QString nativeSymLinkName = QDir::toNativeSeparators(symLinkName);
+ const QString nativeTarget = QDir::toNativeSeparators(target);
+ DWORD flags = 0;
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14972))
+ flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
+ if (QFileInfo(target).isDir())
+ flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
+ if (CreateSymbolicLink(reinterpret_cast<const wchar_t*>(nativeSymLinkName.utf16()),
+ reinterpret_cast<const wchar_t*>(nativeTarget.utf16()), flags) == FALSE) {
+ result = GetLastError();
+ QTextStream(errorMessage) << "CreateSymbolicLink(" << nativeSymLinkName << ", "
+ << nativeTarget << ", 0x" << hex << flags << dec << ") failed with error " << result
+ << ": " << qt_error_string(int(result));
}
- return true;
+ return result;
}
-#endif
+
+static QByteArray msgInsufficientPrivileges(const QString &errorMessage)
+{
+ return "Insufficient privileges (" + errorMessage.toLocal8Bit() + ')';
+}
+#endif // Q_OS_WIN && !Q_OS_WINRT
static QString seedAndTemplate()
{
@@ -650,6 +655,8 @@ void tst_QFileInfo::canonicalFilePath()
QVERIFY(tempFile.open(QFile::WriteOnly));
QFileInfo fi(tempFile.fileName());
QCOMPARE(fi.canonicalFilePath(), QDir::currentPath() + "/" + fileName);
+ fi = QFileInfo(tempFile.fileName() + QString::fromLatin1("/"));
+ QCOMPARE(fi.canonicalFilePath(), QString::fromLatin1(""));
tempFile.remove();
// This used to crash on Mac, verify that it doesn't anymore.
@@ -731,13 +738,14 @@ void tst_QFileInfo::canonicalFilePath()
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
{
+ QString errorMessage;
const QString linkTarget = QStringLiteral("res");
- BOOL ret = createNtfsSymLinkHelper(linkTarget, m_resourcesDir, NtfsTargetDir);
- if (!ret)
- QSKIP("Symbolic links aren't supported by FS");
+ const DWORD dwErr = createSymbolicLink(linkTarget, m_resourcesDir, &errorMessage);
+ if (dwErr == ERROR_PRIVILEGE_NOT_HELD)
+ QSKIP(msgInsufficientPrivileges(errorMessage));
+ QVERIFY2(dwErr == ERROR_SUCCESS, qPrintable(errorMessage));
QString currentPath = QDir::currentPath();
- bool is_res_Current = QDir::setCurrent(linkTarget);
- QCOMPARE(is_res_Current, true);
+ QVERIFY(QDir::setCurrent(linkTarget));
const QString actualCanonicalPath = QFileInfo("file1").canonicalFilePath();
QVERIFY(QDir::setCurrent(currentPath));
QCOMPARE(actualCanonicalPath, m_resourcesDir + QStringLiteral("/file1"));
@@ -1176,7 +1184,7 @@ void tst_QFileInfo::fileTimes()
QTest::qSleep(sleepTime);
beforeWrite = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
QTextStream ts(&file);
- ts << fileName << endl;
+ ts << fileName << Qt::endl;
}
{
QFileInfo fileInfo(fileName);
@@ -1476,8 +1484,24 @@ void tst_QFileInfo::refresh()
}
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+
+struct NtfsTestResource {
+
+ enum Type { None, SymLink, Junction };
+
+ explicit NtfsTestResource(Type tp = None, const QString &s = QString(), const QString &t = QString())
+ : source(s), target(t), type(tp) {}
+
+ QString source;
+ QString target;
+ Type type;
+};
+
+Q_DECLARE_METATYPE(NtfsTestResource)
+
void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
{
+ QTest::addColumn<NtfsTestResource>("resource");
QTest::addColumn<QString>("path");
QTest::addColumn<bool>("isSymLink");
QTest::addColumn<QString>("linkTarget");
@@ -1500,25 +1524,20 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
QString fileInSymlink(absSymlink);
fileInSymlink.append("\\file");
QFile file(fileInTarget);
- file.open(QIODevice::ReadWrite);
+ QVERIFY2(file.open(QIODevice::ReadWrite), qPrintable(file.errorString()));
file.close();
- bool result = true;
- if (!pwd.exists("abs_symlink"))
- result = createNtfsSymLinkHelper(absSymlink, absTarget, NtfsTargetDir);
- if (result && !pwd.exists(relSymlink))
- result = createNtfsSymLinkHelper(relSymlink, relTarget, NtfsTargetDir);
- if (!result) {
- //we need at least one data set for the test not to assert fail when skipping _data function
- QDir target("target");
- QTest::newRow("dummy") << target.path() << false << "" << target.canonicalPath();
- QSKIP("link not supported by FS or insufficient privilege");
- }
QVERIFY2(file.exists(), msgDoesNotExist(file.fileName()).constData());
- QTest::newRow("absolute dir symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath();
- QTest::newRow("relative dir symlink") << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath();
- QTest::newRow("file in symlink dir") << fileInSymlink << false << "" << target.canonicalPath().append("/file");
+ QTest::newRow("absolute dir symlink")
+ << NtfsTestResource(NtfsTestResource::SymLink, absSymlink, absTarget)
+ << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath();
+ QTest::newRow("relative dir symlink")
+ << NtfsTestResource(NtfsTestResource::SymLink, relSymlink, relTarget)
+ << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath();
+ QTest::newRow("file in symlink dir")
+ << NtfsTestResource()
+ << fileInSymlink << false << "" << target.canonicalPath().append("/file");
}
{
//File symlinks
@@ -1531,41 +1550,51 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
QString relSymlink = "rel_symlink.cpp";
QString relToRelTarget = QDir::toNativeSeparators(relativeDir.relativeFilePath(target.absoluteFilePath()));
QString relToRelSymlink = "relative/rel_symlink";
- QVERIFY(pwd.exists("abs_symlink.cpp") || createNtfsSymLinkHelper(absSymlink, absTarget, NtfsTargetFile));
- QVERIFY(pwd.exists(relSymlink) || createNtfsSymLinkHelper(relSymlink, relTarget, NtfsTargetFile));
- QVERIFY(pwd.exists(relToRelSymlink) || createNtfsSymLinkHelper(relToRelSymlink, relToRelTarget, NtfsTargetFile));
- QTest::newRow("absolute file symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
- QTest::newRow("relative file symlink") << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
- QTest::newRow("relative to relative file symlink") << relToRelSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
+
+ QTest::newRow("absolute file symlink")
+ << NtfsTestResource(NtfsTestResource::SymLink, absSymlink, absTarget)
+ << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
+ QTest::newRow("relative file symlink")
+ << NtfsTestResource(NtfsTestResource::SymLink, relSymlink, relTarget)
+ << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
+ QTest::newRow("relative to relative file symlink")
+ << NtfsTestResource(NtfsTestResource::SymLink, relToRelSymlink, relToRelTarget)
+ << relToRelSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
}
{
// Symlink to UNC share
pwd.mkdir("unc");
+ QString errorMessage;
QString uncTarget = QStringLiteral("//") + QtNetworkSettings::winServerName() + "/testshare";
QString uncSymlink = QDir::toNativeSeparators(pwd.absolutePath().append("\\unc\\link_to_unc"));
- QVERIFY(pwd.exists("link_to_unc") || createNtfsSymLinkHelper(uncSymlink, uncTarget, NtfsTargetDir));
- QTest::newRow("UNC symlink") << uncSymlink << true << uncTarget << uncTarget;
+ QTest::newRow("UNC symlink")
+ << NtfsTestResource(NtfsTestResource::SymLink, uncSymlink, uncTarget)
+ << QDir::fromNativeSeparators(uncSymlink) << true << QDir::fromNativeSeparators(uncTarget) << uncTarget;
}
//Junctions
QString target = "target";
QString junction = "junction_pwd";
- FileSystem::createNtfsJunction(target, junction);
QFileInfo targetInfo(target);
- QTest::newRow("junction_pwd") << junction << false << QString() << QString();
+ QTest::newRow("junction_pwd")
+ << NtfsTestResource(NtfsTestResource::Junction, junction, target)
+ << junction << false << QString() << QString();
QFileInfo fileInJunction(targetInfo.absoluteFilePath().append("/file"));
QFile file(fileInJunction.absoluteFilePath());
- file.open(QIODevice::ReadWrite);
+ QVERIFY2(file.open(QIODevice::ReadWrite), qPrintable(file.errorString()));
file.close();
QVERIFY2(file.exists(), msgDoesNotExist(file.fileName()).constData());
- QTest::newRow("file in junction") << fileInJunction.absoluteFilePath() << false << "" << fileInJunction.canonicalFilePath();
+ QTest::newRow("file in junction")
+ << NtfsTestResource()
+ << fileInJunction.absoluteFilePath() << false << QString() << fileInJunction.canonicalFilePath();
target = QDir::rootPath();
junction = "junction_root";
- FileSystem::createNtfsJunction(target, junction);
targetInfo.setFile(target);
- QTest::newRow("junction_root") << junction << false << QString() << QString();
+ QTest::newRow("junction_root")
+ << NtfsTestResource(NtfsTestResource::Junction, junction, target)
+ << junction << false << QString() << QString();
//Mountpoint
wchar_t buffer[MAX_PATH];
@@ -1574,17 +1603,38 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
QString rootVolume = QString::fromWCharArray(buffer);
junction = "mountpoint";
rootVolume.replace("\\\\?\\","\\??\\");
- FileSystem::createNtfsJunction(rootVolume, junction);
- QTest::newRow("mountpoint") << junction << false << QString() << QString();
+ QTest::newRow("mountpoint")
+ << NtfsTestResource(NtfsTestResource::Junction, junction, rootVolume)
+ << junction << false << QString() << QString();
}
void tst_QFileInfo::ntfsJunctionPointsAndSymlinks()
{
+ QFETCH(NtfsTestResource, resource);
QFETCH(QString, path);
QFETCH(bool, isSymLink);
QFETCH(QString, linkTarget);
QFETCH(QString, canonicalFilePath);
+ QString errorMessage;
+ DWORD creationResult = ERROR_SUCCESS;
+ switch (resource.type) {
+ case NtfsTestResource::None:
+ break;
+ case NtfsTestResource::SymLink:
+ creationResult = createSymbolicLink(resource.source, resource.target, &errorMessage);
+ break;
+ case NtfsTestResource::Junction:
+ creationResult = FileSystem::createNtfsJunction(resource.target, resource.source, &errorMessage);
+ if (creationResult == ERROR_NOT_SUPPORTED) // Special value indicating non-NTFS drive
+ QSKIP(qPrintable(errorMessage));
+ break;
+ }
+
+ if (creationResult == ERROR_PRIVILEGE_NOT_HELD)
+ QSKIP(msgInsufficientPrivileges(errorMessage));
+ QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
+
QFileInfo fi(path);
const bool actualIsSymLink = fi.isSymLink();
const QString actualSymLinkTarget = isSymLink ? fi.symLinkTarget() : QString();
@@ -1984,7 +2034,7 @@ static void stateCheck(const QFileInfo &info, const QString &dirname, const QStr
QVERIFY(!info.isRoot());
QCOMPARE(info.isNativePath(), !filename.isEmpty());
- QCOMPARE(info.readLink(), QString());
+ QCOMPARE(info.symLinkTarget(), QString());
QCOMPARE(info.ownerId(), uint(-2));
QCOMPARE(info.groupId(), uint(-2));
QCOMPARE(info.owner(), QString());
diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
index 67ffa91e57..cdd1f6361e 100644
--- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
+++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
@@ -46,11 +46,13 @@ public:
tst_QFileSystemWatcher();
private slots:
+#ifdef QT_BUILD_INTERNAL
void basicTest_data();
void basicTest();
void watchDirectory_data();
void watchDirectory();
+#endif
void addPath();
void removePath();
@@ -58,8 +60,10 @@ private slots:
void removePaths();
void removePathsFilesInSameDirectory();
+#ifdef QT_BUILD_INTERNAL
void watchFileAndItsDirectory_data() { basicTest_data(); }
void watchFileAndItsDirectory();
+#endif
void nonExistingFile();
@@ -67,8 +71,10 @@ private slots:
void destroyAfterQCoreApplication();
+#ifdef QT_BUILD_INTERNAL
void QTBUG2331();
void QTBUG2331_data() { basicTest_data(); }
+#endif
void signalsEmittedAfterFileMoved();
@@ -90,6 +96,7 @@ tst_QFileSystemWatcher::tst_QFileSystemWatcher()
#endif
}
+#ifdef QT_BUILD_INTERNAL
void tst_QFileSystemWatcher::basicTest_data()
{
QTest::addColumn<QString>("backend");
@@ -360,6 +367,7 @@ void tst_QFileSystemWatcher::watchDirectory()
for (const auto &testDirName : testDirs)
QVERIFY(temporaryDir.rmdir(testDirName));
}
+#endif // QT_BUILD_INTERNAL
void tst_QFileSystemWatcher::addPath()
{
@@ -502,6 +510,7 @@ void tst_QFileSystemWatcher::removePathsFilesInSameDirectory()
QCOMPARE(watcher.files().size(), 0);
}
+#ifdef QT_BUILD_INTERNAL
static QByteArray msgFileOperationFailed(const char *what, const QFile &f)
{
return what + QByteArrayLiteral(" failed on \"")
@@ -601,6 +610,7 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory()
QVERIFY(temporaryDir.rmdir(testDirName));
}
+#endif // QT_BUILD_INTERNAL
void tst_QFileSystemWatcher::nonExistingFile()
{
@@ -673,6 +683,7 @@ void tst_QFileSystemWatcher::destroyAfterQCoreApplication()
QTest::qWait(30);
}
+#ifdef QT_BUILD_INTERNAL
// regression test for QTBUG2331.
// essentially, on windows, directories were not unwatched after being deleted
// from the disk, causing all sorts of interesting problems.
@@ -696,6 +707,7 @@ void tst_QFileSystemWatcher::QTBUG2331()
QTRY_COMPARE(changedSpy.count(), 1);
QCOMPARE(watcher.directories(), QStringList());
}
+#endif // QT_BUILD_INTERNAL
class SignalReceiver : public QObject
{
diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro
index da2660fd02..e33e22b36f 100644
--- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro
+++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro
@@ -3,4 +3,4 @@ TARGET = tst_qlockfile
SOURCES += tst_qlockfile.cpp
QT = core-private testlib concurrent
-win32:!winrt:LIBS += -ladvapi32
+win32:!winrt: QMAKE_USE += advapi32
diff --git a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
index 11a9b3f189..79ac6b0fc4 100644
--- a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
+++ b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp
@@ -104,7 +104,7 @@ public:
for (int a = 0; a < _configitemEntryOrder.count(); a++) {
out << _configitemEntryOrder[a]
<< " = "
- << _values.value(_configitemEntryOrder[a]) << endl;
+ << _values.value(_configitemEntryOrder[a]) << Qt::endl;
}
out.flush();
return ret.toLatin1();
@@ -369,11 +369,9 @@ private slots:
}
Q_LOGGING_CATEGORY(TST_MACRO_1, "tst.macro.1")
-#ifdef Q_COMPILER_VARIADIC_MACROS
Q_LOGGING_CATEGORY(TST_MACRO_2, "tst.macro.2", QtDebugMsg)
Q_LOGGING_CATEGORY(TST_MACRO_3, "tst.macro.3", QtFatalMsg)
Q_LOGGING_CATEGORY(TST_MACRO_4, "tst.macro.4", QtInfoMsg)
-#endif
void QLoggingCategoryMacro()
{
@@ -384,7 +382,6 @@ private slots:
QCOMPARE(cat1.isWarningEnabled(), true);
QCOMPARE(cat1.isCriticalEnabled(), true);
-#ifdef Q_COMPILER_VARIADIC_MACROS
const QLoggingCategory &cat2 = TST_MACRO_2();
QCOMPARE(cat2.categoryName(), "tst.macro.2");
QCOMPARE(cat2.isDebugEnabled(), true);
@@ -405,7 +402,6 @@ private slots:
QCOMPARE(cat4.isInfoEnabled(), true);
QCOMPARE(cat4.isWarningEnabled(), true);
QCOMPARE(cat4.isCriticalEnabled(), true);
-#endif
}
void qCDebugMacros()
diff --git a/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro b/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro
index 935f43630c..e41ed0a425 100644
--- a/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro
+++ b/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro
@@ -1,6 +1,6 @@
win32 {
SOURCES = main_win.cpp
- LIBS += -luser32
+ QMAKE_USE += user32
}
CONFIG -= qt app_bundle
diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro
index 2cfcb4794e..964c47f6ae 100644
--- a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro
+++ b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro
@@ -1,6 +1,6 @@
win32 {
SOURCES = main_win.cpp
- LIBS += -luser32
+ QMAKE_USE += user32
}
unix {
SOURCES = main_unix.cpp
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index e0aa577154..e4ff3c2a08 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -32,6 +32,7 @@
#include <QtTest/QtTest>
#include <QtCore/QProcess>
#include <QtCore/QDir>
+#include <QtCore/QElapsedTimer>
#include <QtCore/QFile>
#include <QtCore/QThread>
#include <QtCore/QTemporaryDir>
@@ -185,12 +186,12 @@ void tst_QProcess::getSetCheck()
{
QProcess obj1;
// ProcessChannelMode QProcess::readChannelMode()
- // void QProcess::setReadChannelMode(ProcessChannelMode)
- obj1.setReadChannelMode(QProcess::ProcessChannelMode(QProcess::SeparateChannels));
+ // void QProcess::setProcessChannelMode(ProcessChannelMode)
+ obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::SeparateChannels));
QCOMPARE(QProcess::ProcessChannelMode(QProcess::SeparateChannels), obj1.readChannelMode());
- obj1.setReadChannelMode(QProcess::ProcessChannelMode(QProcess::MergedChannels));
+ obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::MergedChannels));
QCOMPARE(QProcess::ProcessChannelMode(QProcess::MergedChannels), obj1.readChannelMode());
- obj1.setReadChannelMode(QProcess::ProcessChannelMode(QProcess::ForwardedChannels));
+ obj1.setProcessChannelMode(QProcess::ProcessChannelMode(QProcess::ForwardedChannels));
QCOMPARE(QProcess::ProcessChannelMode(QProcess::ForwardedChannels), obj1.readChannelMode());
// ProcessChannel QProcess::readChannel()
@@ -420,7 +421,7 @@ void tst_QProcess::echoTest()
process.write(input);
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
do {
QVERIFY(process.isOpen());
@@ -479,7 +480,7 @@ void tst_QProcess::echoTest2()
QVERIFY(spy1.isValid());
QVERIFY(spy2.isValid());
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
forever {
QTestEventLoop::instance().enterLoop(1);
@@ -913,7 +914,7 @@ public:
switch (n) {
case 0:
- setReadChannelMode(QProcess::MergedChannels);
+ setProcessChannelMode(QProcess::MergedChannels);
connect(this, &QIODevice::readyRead, this, &SoftExitProcess::terminateSlot);
break;
case 1:
@@ -929,7 +930,7 @@ public:
this, &SoftExitProcess::terminateSlot);
break;
case 4:
- setReadChannelMode(QProcess::MergedChannels);
+ setProcessChannelMode(QProcess::MergedChannels);
connect(this, SIGNAL(channelReadyRead(int)), this, SLOT(terminateSlot()));
break;
default:
@@ -1025,7 +1026,7 @@ void tst_QProcess::softExitInSlots()
void tst_QProcess::mergedChannels()
{
QProcess process;
- process.setReadChannelMode(QProcess::MergedChannels);
+ process.setProcessChannelMode(QProcess::MergedChannels);
QCOMPARE(process.readChannelMode(), QProcess::MergedChannels);
process.start("testProcessEcho2/testProcessEcho2");
@@ -1951,7 +1952,7 @@ void tst_QProcess::setStandardOutputFile()
// run the process
QProcess process;
- process.setReadChannelMode(channelMode);
+ process.setProcessChannelMode(channelMode);
if (channelToTest == QProcess::StandardOutput)
process.setStandardOutputFile(file.fileName(), mode);
else
@@ -2037,7 +2038,7 @@ void tst_QProcess::setStandardOutputProcess()
QFETCH(bool, merged);
QFETCH(bool, waitForBytesWritten);
- source.setReadChannelMode(merged ? QProcess::MergedChannels : QProcess::SeparateChannels);
+ source.setProcessChannelMode(merged ? QProcess::MergedChannels : QProcess::SeparateChannels);
source.setStandardOutputProcess(&sink);
source.start("testProcessEcho2/testProcessEcho2");
@@ -2072,7 +2073,7 @@ void tst_QProcess::fileWriterProcess()
stdinStr += line;
}
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
const QString fileName = m_temporaryDir.path() + QLatin1String("/fileWriterProcess.txt");
const QString binary = QDir::currentPath() + QLatin1String("/fileWriterProcess/fileWriterProcess");
diff --git a/tests/auto/corelib/io/qsettings/qsettings.pro b/tests/auto/corelib/io/qsettings/qsettings.pro
index 79552b62df..98ea337e7f 100644
--- a/tests/auto/corelib/io/qsettings/qsettings.pro
+++ b/tests/auto/corelib/io/qsettings/qsettings.pro
@@ -5,7 +5,7 @@ SOURCES = tst_qsettings.cpp
RESOURCES += qsettings.qrc
INCLUDEPATH += $$PWD/../../kernel/qmetatype
-msvc: LIBS += advapi32.lib
+msvc: QMAKE_USE += advapi32
darwin: LIBS += -framework CoreFoundation
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
index 1379c788d1..56d924dcc6 100644
--- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
+++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
@@ -32,8 +32,8 @@
#include <qstandardpaths.h>
#include <qfileinfo.h>
#include <qsysinfo.h>
-#include <qregexp.h>
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)
+#include <qregularexpression.h>
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
# include <qt_windows.h>
#endif
@@ -131,7 +131,7 @@ static const char * const enumNames[MaxStandardLocation + 1 - int(QStandardPaths
void tst_qstandardpaths::initTestCase()
{
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
// Disable WOW64 redirection, see testFindExecutable()
if (QSysInfo::buildCpuArchitecture() != QSysInfo::currentCpuArchitecture()) {
void *oldMode;
@@ -140,7 +140,7 @@ void tst_qstandardpaths::initTestCase()
qErrnoWarning("Wow64DisableWow64FsRedirection() failed");
QVERIFY(disabledDisableWow64FsRedirection);
}
-#endif // Q_OS_WIN && !Q_OS_WINRT && !Q_OS_WINCE
+#endif // Q_OS_WIN && !Q_OS_WINRT
QVERIFY2(m_localConfigTempDir.isValid(), qPrintable(m_localConfigTempDir.errorString()));
QVERIFY2(m_globalConfigTempDir.isValid(), qPrintable(m_globalConfigTempDir.errorString()));
QVERIFY2(m_localAppTempDir.isValid(), qPrintable(m_localAppTempDir.errorString()));
@@ -566,7 +566,8 @@ void tst_qstandardpaths::testAllWritableLocations()
void tst_qstandardpaths::testCleanPath()
{
- const QRegExp filter(QStringLiteral("\\\\"));
+#if QT_CONFIG(regularexpression)
+ const QRegularExpression filter(QStringLiteral("\\\\"));
QVERIFY(filter.isValid());
for (int i = 0; i <= QStandardPaths::GenericCacheLocation; ++i) {
const QStringList paths = QStandardPaths::standardLocations(QStandardPaths::StandardLocation(i));
@@ -574,6 +575,9 @@ void tst_qstandardpaths::testCleanPath()
qPrintable(QString::fromLatin1("Backslash found in %1 %2")
.arg(i).arg(paths.join(QLatin1Char(',')))));
}
+#else
+ QSKIP("regularexpression feature disabled");
+#endif
}
void tst_qstandardpaths::testXdgPathCleanup()
diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
index dbc3d68e93..67d8c55b04 100644
--- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
+++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
@@ -215,7 +215,7 @@ void tst_QTemporaryFile::fileTemplate()
if (!fileTemplate.isEmpty())
file.setFileTemplate(fileTemplate);
- QCOMPARE(file.open(), true);
+ QVERIFY2(file.open(), qPrintable(file.errorString()));
QString fileName = QFileInfo(file).fileName();
if (prefix.length())
@@ -376,7 +376,7 @@ void tst_QTemporaryFile::io()
before.setSecsSinceEpoch(before.toSecsSinceEpoch());
QVERIFY(file.open());
- QVERIFY(file.readLink().isEmpty()); // it's not a link!
+ QVERIFY(file.symLinkTarget().isEmpty()); // it's not a link!
QFile::Permissions perm = file.permissions();
QVERIFY(perm & QFile::ReadOwner);
QVERIFY(file.setPermissions(perm));
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index d697dae9dd..3123c42326 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -136,8 +136,8 @@ private slots:
void emptyQueryOrFragment();
void hasFragment_data();
void hasFragment();
- void setEncodedFragment_data();
- void setEncodedFragment();
+ void setFragment_data();
+ void setFragment();
void fromEncoded();
void stripTrailingSlash_data();
void stripTrailingSlash();
@@ -350,15 +350,15 @@ void tst_QUrl::comparison()
// 6.2.2.1 Make sure hexdecimal characters in percent encoding are
// treated case-insensitively
QUrl url5;
- url5.setEncodedQuery("a=%2a");
+ url5.setQuery(QLatin1String("a=%2a"));
QUrl url6;
- url6.setEncodedQuery("a=%2A");
+ url6.setQuery(QLatin1String("a=%2A"));
QCOMPARE(url5, url6);
QUrl url7;
- url7.setEncodedQuery("a=C");
+ url7.setQuery(QLatin1String("a=C"));
QUrl url8;
- url8.setEncodedQuery("a=c");
+ url8.setQuery(QLatin1String("a=c"));
QVERIFY(url7 != url8);
QVERIFY(url7 < url8);
@@ -502,7 +502,7 @@ void tst_QUrl::setUrl()
QVERIFY(url.isValid());
QCOMPARE(url.scheme(), QString::fromLatin1("file"));
QCOMPARE(url.path(), QString::fromLatin1("/"));
- QVERIFY(url.encodedQuery().isEmpty());
+ QVERIFY(url.query().isEmpty());
QVERIFY(url.userInfo().isEmpty());
QVERIFY(url.authority().isEmpty());
QVERIFY(url.fragment().isEmpty());
@@ -517,7 +517,7 @@ void tst_QUrl::setUrl()
QVERIFY(url.isValid());
QCOMPARE(url.scheme(), QString::fromLatin1("http"));
QCOMPARE(url.path(), QString());
- QVERIFY(url.encodedQuery().isEmpty());
+ QVERIFY(url.query().isEmpty());
QVERIFY(url.userInfo().isEmpty());
QVERIFY(url.fragment().isEmpty());
QCOMPARE(url.host(), QString::fromLatin1("www.foo.bar"));
@@ -536,7 +536,7 @@ void tst_QUrl::setUrl()
QVERIFY(url.isValid());
QCOMPARE(url.scheme(), QString::fromLatin1("http"));
QCOMPARE(url.path(), QString());
- QVERIFY(url.encodedQuery().isEmpty());
+ QVERIFY(url.query().isEmpty());
QCOMPARE(url.userName(), QString::fromLatin1("user:"));
QCOMPARE(url.password(), QString::fromLatin1("pass@"));
QCOMPARE(url.userInfo(), QString::fromLatin1("user%3A:pass@"));
@@ -781,7 +781,7 @@ void tst_QUrl::setUrl()
QVERIFY(url.isValid());
QCOMPARE(url.scheme(), QString("http"));
QCOMPARE(url.host(), QString("1.2.3.4"));
- QCOMPARE(url.encodedQuery(), QByteArray("foo"));
+ QCOMPARE(url.query(QUrl::FullyEncoded), QLatin1String("foo"));
}
{
QUrl url;
@@ -798,13 +798,13 @@ void tst_QUrl::setUrl()
QCOMPARE(url.scheme(), QString("data"));
QCOMPARE(url.host(), QString());
QCOMPARE(url.path(), QString("text/javascript,d5 = 'five\\u0027s';"));
- QCOMPARE(url.encodedPath().constData(), "text/javascript,d5%20%3D%20'five%5Cu0027s'%3B");
+ QCOMPARE(url.path(QUrl::FullyEncoded), QLatin1String("text/javascript,d5%20%3D%20'five%5Cu0027s'%3B"));
}
{
// invalid port number
QUrl url;
- url.setEncodedUrl("foo://tel:2147483648");
+ url.setUrl(QLatin1String("foo://tel:2147483648"), QUrl::StrictMode);
QVERIFY(!url.isValid());
}
@@ -1144,7 +1144,7 @@ void tst_QUrl::toString_constructed_data()
QTest::addColumn<QString>("host");
QTest::addColumn<int>("port");
QTest::addColumn<QString>("path");
- QTest::addColumn<QByteArray>("query");
+ QTest::addColumn<QString>("query");
QTest::addColumn<QString>("fragment");
QTest::addColumn<QString>("asString");
QTest::addColumn<QByteArray>("asEncoded");
@@ -1153,19 +1153,19 @@ void tst_QUrl::toString_constructed_data()
QString n("");
QTest::newRow("data1") << n << n << n << QString::fromLatin1("qt-project.org") << -1 << QString::fromLatin1("/index.html")
- << QByteArray() << n << QString::fromLatin1("//qt-project.org/index.html")
+ << QString() << n << QString::fromLatin1("//qt-project.org/index.html")
<< QByteArray("//qt-project.org/index.html") << 0u;
- QTest::newRow("data2") << QString::fromLatin1("file") << n << n << n << -1 << QString::fromLatin1("/root") << QByteArray()
+ QTest::newRow("data2") << QString::fromLatin1("file") << n << n << n << -1 << QString::fromLatin1("/root") << QString()
<< n << QString::fromLatin1("file:///root") << QByteArray("file:///root") << 0u;
QTest::newRow("userAndPass") << QString::fromLatin1("http") << QString::fromLatin1("dfaure") << QString::fromLatin1("kde")
- << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n
+ << "kde.org" << 443 << QString::fromLatin1("/") << QString() << n
<< QString::fromLatin1("http://dfaure:kde@kde.org:443/") << QByteArray("http://dfaure:kde@kde.org:443/")
<< 0u;
QTest::newRow("PassWithoutUser") << QString::fromLatin1("http") << n << QString::fromLatin1("kde")
- << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n
+ << "kde.org" << 443 << QString::fromLatin1("/") << QString() << n
<< QString::fromLatin1("http://:kde@kde.org:443/") << QByteArray("http://:kde@kde.org:443/") << 0u;
QTest::newRow("PassWithoutUser-RemovePassword") << QString::fromLatin1("http") << n << QString::fromLatin1("kde")
- << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n
+ << "kde.org" << 443 << QString::fromLatin1("/") << QString() << n
<< QString::fromLatin1("http://kde.org:443/") << QByteArray("http://kde.org:443/")
<< uint(QUrl::RemovePassword);
}
@@ -1178,7 +1178,7 @@ void tst_QUrl::toString_constructed()
QFETCH(QString, host);
QFETCH(int, port);
QFETCH(QString, path);
- QFETCH(QByteArray, query);
+ QFETCH(QString, query);
QFETCH(QString, fragment);
QFETCH(QString, asString);
QFETCH(QByteArray, asEncoded);
@@ -1198,7 +1198,7 @@ void tst_QUrl::toString_constructed()
if (!path.isEmpty())
url.setPath(path);
if (!query.isEmpty())
- url.setEncodedQuery(query);
+ url.setQuery(query, QUrl::StrictMode);
if (!fragment.isEmpty())
url.setFragment(fragment);
@@ -1757,7 +1757,7 @@ void tst_QUrl::symmetry()
QCOMPARE(url.host(QUrl::EncodeUnicode | QUrl::EncodeSpaces), QString::fromUtf8("www.xn--rksmrgs-5wao1o.se"));
QCOMPARE(url.path(), QString::fromLatin1("/pub"));
// this will be encoded ...
- QCOMPARE(url.encodedQuery().constData(), QString::fromLatin1("a=b&a=d%C3%B8&a=f").toLatin1().constData());
+ QCOMPARE(url.query(QUrl::FullyEncoded), QLatin1String("a=b&a=d%C3%B8&a=f"));
QCOMPARE(url.fragment(), QString::fromUtf8("vræl"));
QUrl onlyHost("//qt-project.org");
@@ -2009,7 +2009,7 @@ void tst_QUrl::hasQuery()
QUrl qurl(url);
QCOMPARE(qurl.hasQuery(), trueFalse);
- QCOMPARE(qurl.encodedQuery().isNull(), !trueFalse);
+ QCOMPARE(qurl.query().isNull(), !trueFalse);
}
void tst_QUrl::nameprep()
@@ -2192,10 +2192,12 @@ void tst_QUrl::schemeValidator_data()
QTest::newRow("percent-encoded") << "%68%74%%74%70://example.com" << false << "%68%74%%74%70";
static const char controls[] = "!\"$&'()*,;<=>[\\]^_`{|}~";
- for (size_t i = 0; i < sizeof(controls) - 1; ++i)
- QTest::newRow(("with-" + QByteArray(1, controls[i])).constData())
- << QString("pre%1post://example.com/").arg(QLatin1Char(controls[i]))
- << false << QString("pre%1post").arg(QLatin1Char(controls[i]));
+ for (char control : controls) {
+ const QString scheme = QLatin1String("pre") + QLatin1Char(control) + QLatin1String("post");
+ QTest::newRow((QByteArrayLiteral("with-") + control).constData())
+ << (scheme + QLatin1String("://example.com/"))
+ << false << scheme;
+ }
}
void tst_QUrl::schemeValidator()
@@ -2342,7 +2344,7 @@ void tst_QUrl::tolerantParser()
QVERIFY(url.isValid());
QVERIFY(!url.toString().isEmpty());
QCOMPARE(url.path(), QString("/path with spaces.html"));
- url.setEncodedUrl("http://www.example.com/path%20with spaces.html", QUrl::StrictMode);
+ url.setUrl(QLatin1String("http://www.example.com/path%20with spaces.html"), QUrl::StrictMode);
QVERIFY(!url.isValid());
QVERIFY(url.toString().isEmpty());
}
@@ -2392,36 +2394,36 @@ void tst_QUrl::tolerantParser()
QCOMPARE(url.toEncoded(), QByteArray("%25hello.com/f%25"));
QCOMPARE(url.toString(), QString("%25hello.com/f%25"));
- url.setEncodedUrl("http://www.host.com/foo.php?P0=[2006-3-8]");
+ url.setUrl(QLatin1String("http://www.host.com/foo.php?P0=[2006-3-8]"), QUrl::StrictMode);
QVERIFY(url.isValid());
QVERIFY(!url.toString().isEmpty());
- url.setEncodedUrl("http://foo.bar/[image][1].jpg");
+ url.setUrl(QLatin1String("http://foo.bar/[image][1].jpg"), QUrl::StrictMode);
QVERIFY(url.isValid());
QCOMPARE(url.toString(QUrl::FullyEncoded), QString("http://foo.bar/[image][1].jpg"));
QCOMPARE(url.toEncoded(), QByteArray("http://foo.bar/[image][1].jpg"));
QCOMPARE(url.toString(), QString("http://foo.bar/[image][1].jpg"));
- url.setEncodedUrl("http://foo.bar/%5Bimage%5D%5B1%5D.jpg");
+ url.setUrl(QLatin1String("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"), QUrl::StrictMode);
QVERIFY(url.isValid());
QCOMPARE(url.toString(QUrl::FullyEncoded), QString("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"));
QCOMPARE(url.toEncoded(), QByteArray("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"));
QCOMPARE(url.toString(), QString("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"));
- url.setEncodedUrl("//[::56:56:56:56:56:56:56]");
+ url.setUrl(QLatin1String("//[::56:56:56:56:56:56:56]"), QUrl::StrictMode);
QCOMPARE(url.toString(QUrl::FullyEncoded), QString("//[0:56:56:56:56:56:56:56]"));
QCOMPARE(url.toEncoded(), QByteArray("//[0:56:56:56:56:56:56:56]"));
- url.setEncodedUrl("data:text/css,div%20{%20border-right:%20solid;%20}");
+ url.setUrl(QLatin1String("data:text/css,div%20{%20border-right:%20solid;%20}"), QUrl::TolerantMode);
QCOMPARE(url.toString(QUrl::FullyEncoded), QString("data:text/css,div%20%7B%20border-right:%20solid;%20%7D"));
QCOMPARE(url.toEncoded(), QByteArray("data:text/css,div%20%7B%20border-right:%20solid;%20%7D"));
QCOMPARE(url.toString(), QString("data:text/css,div %7B border-right: solid; %7D"));
}
{
- QByteArray tsdgeos("http://google.com/c?c=Translation+%C2%BB+trunk|");
+ const QString tsdgeos = QLatin1String("http://google.com/c?c=Translation+%C2%BB+trunk|");
QUrl tsdgeosQUrl;
- tsdgeosQUrl.setEncodedUrl(tsdgeos, QUrl::TolerantMode);
+ tsdgeosQUrl.setUrl(tsdgeos, QUrl::TolerantMode);
QVERIFY(tsdgeosQUrl.isValid()); // failed in Qt-4.4, works in Qt-4.5
QByteArray tsdgeosExpected("http://google.com/c?c=Translation+%C2%BB+trunk%7C");
QCOMPARE(QString(tsdgeosQUrl.toEncoded()), QString(tsdgeosExpected));
@@ -2626,31 +2628,31 @@ void tst_QUrl::emptyQueryOrFragment()
// start with an empty one
QUrl url("http://www.foo.bar/baz");
QVERIFY(!url.hasQuery());
- QVERIFY(url.encodedQuery().isNull());
+ QVERIFY(url.query().isNull());
// add encodedQuery
url.setQuery("abc=def");
QVERIFY(url.hasQuery());
QCOMPARE(url.query(), QString(QLatin1String("abc=def")));
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?abc=def")));
- url.setEncodedQuery("abc=def");
+ url.setQuery(QLatin1String("abc=def"));
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?abc=def")));
// remove encodedQuery
url.setQuery(QString());
QVERIFY(!url.hasQuery());
- QVERIFY(url.encodedQuery().isNull());
+ QVERIFY(url.query().isNull());
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz")));
- url.setEncodedQuery(QByteArray());
+ url.setQuery(QString());
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz")));
// add empty encodedQuery
url.setQuery("");
QVERIFY(url.hasQuery());
- QVERIFY(url.encodedQuery().isEmpty());
- QVERIFY(!url.encodedQuery().isNull());
+ QVERIFY(url.query().isEmpty());
+ QVERIFY(!url.query().isNull());
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?")));
- url.setEncodedQuery("");
+ url.setQuery(QLatin1String(""));
QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?")));
}
}
@@ -2682,35 +2684,33 @@ void tst_QUrl::hasFragment()
QCOMPARE(qurl.fragment().isNull(), !trueFalse);
}
-void tst_QUrl::setEncodedFragment_data()
+void tst_QUrl::setFragment_data()
{
- QTest::addColumn<QByteArray>("base");
- QTest::addColumn<QByteArray>("fragment");
- QTest::addColumn<QByteArray>("expected");
+ QTest::addColumn<QString>("base");
+ QTest::addColumn<QString>("fragment");
+ QTest::addColumn<QString>("expected");
- typedef QByteArray BA;
- QTest::newRow("null") << BA("http://www.kde.org") << BA() << BA("http://www.kde.org");
- QTest::newRow("empty") << BA("http://www.kde.org") << BA("") << BA("http://www.kde.org#");
- QTest::newRow("basic test") << BA("http://www.kde.org") << BA("abc") << BA("http://www.kde.org#abc");
- QTest::newRow("initial url has fragment") << BA("http://www.kde.org#old") << BA("new") << BA("http://www.kde.org#new");
- QTest::newRow("encoded fragment") << BA("http://www.kde.org") << BA("a%20c") << BA("http://www.kde.org#a%20c");
- QTest::newRow("with #") << BA("http://www.kde.org") << BA("a#b") << BA("http://www.kde.org#a%23b"); // toString uses "a#b"
- QTest::newRow("unicode") << BA("http://www.kde.org") << BA("\xc3\xa9") << BA("http://www.kde.org#%C3%A9");
- QTest::newRow("binary") << BA("http://www.kde.org") << BA("\x00\xc0\x80", 3) << BA("http://www.kde.org#%00%C0%80");
+ QTest::newRow("null") << QString::fromLatin1("http://www.kde.org") << QString() << QString::fromLatin1("http://www.kde.org");
+ QTest::newRow("empty") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("") << QString::fromLatin1("http://www.kde.org#");
+ QTest::newRow("basic test") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("abc") << QString::fromLatin1("http://www.kde.org#abc");
+ QTest::newRow("initial url has fragment") << QString::fromLatin1("http://www.kde.org#old") << QString::fromLatin1("new") << QString::fromLatin1("http://www.kde.org#new");
+ QTest::newRow("encoded fragment") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("a%20c") << QString::fromLatin1("http://www.kde.org#a%20c");
+ QTest::newRow("with #") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("a#b") << QString::fromLatin1("http://www.kde.org#a%23b"); // toString uses "a#b"
+ QTest::newRow("unicode") << QString::fromLatin1("http://www.kde.org") << QString::fromUtf8("\xc3\xa9") << QString::fromLatin1("http://www.kde.org#%C3%A9");
}
-void tst_QUrl::setEncodedFragment()
+void tst_QUrl::setFragment()
{
- QFETCH(QByteArray, base);
- QFETCH(QByteArray, fragment);
- QFETCH(QByteArray, expected);
+ QFETCH(QString, base);
+ QFETCH(QString, fragment);
+ QFETCH(QString, expected);
QUrl u;
- u.setEncodedUrl(base, QUrl::TolerantMode);
+ u.setUrl(base, QUrl::TolerantMode);
QVERIFY(u.isValid());
- u.setEncodedFragment(fragment);
+ u.setFragment(fragment);
QVERIFY(u.isValid());
QCOMPARE(!fragment.isNull(), u.hasFragment());
- QCOMPARE(QString::fromLatin1(u.toEncoded()), QString::fromLatin1(expected));
+ QCOMPARE(QString::fromUtf8(u.toEncoded()), expected);
}
void tst_QUrl::fromEncoded()
@@ -3258,14 +3258,14 @@ void tst_QUrl::isEmptyForEncodedUrl()
{
{
QUrl url;
- url.setEncodedUrl("LABEL=USB_STICK", QUrl::TolerantMode);
+ url.setUrl(QLatin1String("LABEL=USB_STICK"), QUrl::TolerantMode);
QVERIFY( url.isValid() );
QCOMPARE( url.path(), QString("LABEL=USB_STICK") );
QVERIFY( !url.isEmpty() );
}
{
QUrl url;
- url.setEncodedUrl("LABEL=USB_STICK", QUrl::TolerantMode);
+ url.setUrl(QLatin1String("LABEL=USB_STICK"), QUrl::TolerantMode);
QVERIFY( url.isValid() );
QVERIFY( !url.isEmpty() );
QCOMPARE( url.path(), QString("LABEL=USB_STICK") );
@@ -3277,7 +3277,7 @@ void tst_QUrl::isEmptyForEncodedUrl()
void tst_QUrl::toEncodedNotUsingUninitializedPath()
{
QUrl url;
- url.setEncodedPath("/test.txt");
+ url.setPath(QLatin1String("/test.txt"));
url.setHost("example.com");
QCOMPARE(url.toEncoded().constData(), "//example.com/test.txt");
@@ -3410,6 +3410,21 @@ void tst_QUrl::effectiveTLDs_data()
QTest::newRow("yes16") << QUrl::fromEncoded("http://anything.pagespeedmobilizer.com") << ".pagespeedmobilizer.com";
QTest::newRow("yes17") << QUrl::fromEncoded("http://anything.eu-central-1.compute.amazonaws.com") << ".eu-central-1.compute.amazonaws.com";
QTest::newRow("yes18") << QUrl::fromEncoded("http://anything.ltd.hk") << ".ltd.hk";
+ QTest::newRow("trentino.it")
+ << QUrl::fromEncoded("http://any.thing.trentino.it") << ".trentino.it";
+ QTest::newRow("net.ni") << QUrl::fromEncoded("http://test.net.ni") << ".net.ni";
+ QTest::newRow("dyn.cosidns.de")
+ << QUrl::fromEncoded("http://test.dyn.cosidns.de") << ".dyn.cosidns.de";
+ QTest::newRow("freeddns.org")
+ << QUrl::fromEncoded("http://test.freeddns.org") << ".freeddns.org";
+ QTest::newRow("app.os.stg.fedoraproject.org")
+ << QUrl::fromEncoded("http://test.app.os.stg.fedoraproject.org")
+ << ".app.os.stg.fedoraproject.org";
+ QTest::newRow("development.run") << QUrl::fromEncoded("http://test.development.run") << ".development.run";
+ QTest::newRow("crafting.xyz") << QUrl::fromEncoded("http://test.crafting.xyz") << ".crafting.xyz";
+ QTest::newRow("nym.ie") << QUrl::fromEncoded("http://shamus.nym.ie") << ".nym.ie";
+ QTest::newRow("vapor.cloud") << QUrl::fromEncoded("http://test.vapor.cloud") << ".vapor.cloud";
+ QTest::newRow("official.academy") << QUrl::fromEncoded("http://acredited.official.academy") << ".official.academy";
}
void tst_QUrl::effectiveTLDs()
@@ -3642,17 +3657,6 @@ void tst_QUrl::componentEncodings()
QCOMPARE(url.toString(formatting),
(((QString(toString ))))); // the weird () and space is to align the output
- if (formatting == QUrl::FullyEncoded) {
- QCOMPARE(url.encodedUserName(), userName.toUtf8());
- QCOMPARE(url.encodedPassword(), password.toUtf8());
- // no encodedUserInfo
- QCOMPARE(url.encodedHost(), host.toUtf8());
- // no encodedAuthority
- QCOMPARE(url.encodedPath(), path.toUtf8());
- QCOMPARE(url.encodedQuery(), query.toUtf8());
- QCOMPARE(url.encodedFragment(), fragment.toUtf8());
- }
-
// repeat with the URL we got from toString
QUrl url2(toString);
QCOMPARE(url2.userName(formatting), userName);
@@ -4072,13 +4076,12 @@ public:
QVector<QUrl> m_urls;
};
-static const UrlStorage * s_urlStorage = 0;
+static const UrlStorage * s_urlStorage = nullptr;
void tst_QUrl::testThreadingHelper()
{
const UrlStorage* storage = s_urlStorage;
- for (int i = 0 ; i < storage->m_urls.size(); ++i ) {
- const QUrl& u = storage->m_urls.at(i);
+ for (const auto &u : storage->m_urls) {
// QVERIFY/QCOMPARE trigger race conditions in helgrind
if (!u.isValid())
qFatal("invalid url");
diff --git a/tests/auto/corelib/io/qurlquery/tst_qurlquery.cpp b/tests/auto/corelib/io/qurlquery/tst_qurlquery.cpp
index d839141091..25d392b37e 100644
--- a/tests/auto/corelib/io/qurlquery/tst_qurlquery.cpp
+++ b/tests/auto/corelib/io/qurlquery/tst_qurlquery.cpp
@@ -233,6 +233,14 @@ void tst_QUrlQuery::constructing()
query += qMakePair(QString("prosent"), QString("%"));
copy.setQueryItems(query);
QVERIFY(!copy.isEmpty());
+
+ QUrlQuery fromList = {
+ {QString("type"), QString("login")},
+ {QString("name"), QString::fromUtf8("Ã¥ge nissemannsen")},
+ {QString("ole&du"), QString::fromUtf8("anne+jørgen=sant")},
+ {QString("prosent"), QString("%")}
+ };
+ QCOMPARE(fromList, copy);
}
void tst_QUrlQuery::addRemove()
diff --git a/tests/auto/corelib/itemmodels/itemmodels.pro b/tests/auto/corelib/itemmodels/itemmodels.pro
index cca350ad43..ffbda6ec40 100644
--- a/tests/auto/corelib/itemmodels/itemmodels.pro
+++ b/tests/auto/corelib/itemmodels/itemmodels.pro
@@ -5,9 +5,11 @@ SUBDIRS = qstringlistmodel
qtHaveModule(gui): SUBDIRS += \
qabstractitemmodel \
qabstractproxymodel \
+ qconcatenatetablesproxymodel \
qidentityproxymodel \
qitemselectionmodel \
qsortfilterproxymodel_recursive \
+ qtransposeproxymodel \
qtHaveModule(widgets) {
SUBDIRS += \
diff --git a/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp b/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp
index b960ca9220..3a4493474b 100644
--- a/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp
+++ b/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp
@@ -309,7 +309,8 @@ bool QtTestModel::moveColumns(const QModelIndex &sourceParent, int src, int cnt,
void QtTestModel::reset()
{
- QAbstractItemModel::reset();
+ QAbstractItemModel::beginResetModel();
+ QAbstractItemModel::endResetModel();
}
bool QtTestModel::canDropMimeData(const QMimeData *data, Qt::DropAction action,
@@ -1785,13 +1786,12 @@ class ModelWithCustomRole : public QStringListModel
{
Q_OBJECT
public:
- ModelWithCustomRole(QObject *parent = 0)
- : QStringListModel(parent)
- {
- QHash<int, QByteArray> roleNames_ = roleNames();
- roleNames_.insert(Qt::UserRole + 1, "custom");
- setRoleNames(roleNames_);
- }
+ using QStringListModel::QStringListModel;
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return {{Qt::UserRole + 1, QByteArrayLiteral("custom")}};
+ }
};
ListenerObject::ListenerObject(QAbstractProxyModel *parent)
diff --git a/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp b/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp
index 886941bff6..adb93b7a75 100644
--- a/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp
@@ -313,11 +313,12 @@ public:
CustomRole2
};
- StandardItemModelWithCustomRoleNames() {
- QHash<int, QByteArray> _roleNames = roleNames();
- _roleNames.insert(CustomRole1, "custom1");
- _roleNames.insert(CustomRole2, "custom2");
- setRoleNames(_roleNames);
+ QHash<int, QByteArray> roleNames() const override
+ {
+ auto result = QStandardItemModel::roleNames();
+ result.insert(CustomRole1, QByteArrayLiteral("custom1"));
+ result.insert(CustomRole2, QByteArrayLiteral("custom2"));
+ return result;
}
};
@@ -329,11 +330,10 @@ public:
AnotherCustomRole2
};
- AnotherStandardItemModelWithCustomRoleNames() {
- QHash<int, QByteArray> _roleNames = roleNames();
- _roleNames.insert(AnotherCustomRole1, "another_custom1");
- _roleNames.insert(AnotherCustomRole2, "another_custom2");
- setRoleNames(_roleNames);
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return {{AnotherCustomRole1, QByteArrayLiteral("another_custom1")},
+ {AnotherCustomRole2, QByteArrayLiteral("another_custom2")}};
}
};
diff --git a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro
new file mode 100644
index 0000000000..ee4ea28b5b
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+TARGET = tst_qconcatenatetablesproxymodel
+QT = core gui testlib
+
+SOURCES = tst_qconcatenatetablesproxymodel.cpp
diff --git a/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
new file mode 100644
index 0000000000..40617c1f7d
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qconcatenatetablesproxymodel/tst_qconcatenatetablesproxymodel.cpp
@@ -0,0 +1,823 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QSignalSpy>
+#include <QSortFilterProxyModel>
+#include <QTest>
+#include <QStandardItemModel>
+#include <QIdentityProxyModel>
+#include <QItemSelectionModel>
+#include <QMimeData>
+#include <QStringListModel>
+#include <QAbstractItemModelTester>
+
+#include <qconcatenatetablesproxymodel.h>
+
+Q_DECLARE_METATYPE(QModelIndex)
+
+// Extracts a full row from a model as a string
+// Works best if every cell contains only one character
+static QString extractRowTexts(QAbstractItemModel *model, int row, const QModelIndex &parent = QModelIndex())
+{
+ QString result;
+ const int colCount = model->columnCount();
+ for (int col = 0; col < colCount; ++col) {
+ const QString txt = model->index(row, col, parent).data().toString();
+ result += txt.isEmpty() ? QStringLiteral(" ") : txt;
+ }
+ return result;
+}
+
+// Extracts a full column from a model as a string
+// Works best if every cell contains only one character
+static QString extractColumnTexts(QAbstractItemModel *model, int column, const QModelIndex &parent = QModelIndex())
+{
+ QString result;
+ const int rowCount = model->rowCount();
+ for (int row = 0; row < rowCount; ++row) {
+ const QString txt = model->index(row, column, parent).data().toString();
+ result += txt.isEmpty() ? QStringLiteral(" ") : txt;
+ }
+ return result;
+}
+
+static QString rowSpyToText(const QSignalSpy &spy)
+{
+ if (!spy.isValid())
+ return QStringLiteral("THE SIGNALSPY IS INVALID!");
+ QString str;
+ for (int i = 0; i < spy.count(); ++i) {
+ str += spy.at(i).at(1).toString() + QLatin1Char(',') + spy.at(i).at(2).toString();
+ if (i + 1 < spy.count())
+ str += QLatin1Char(';');
+ }
+ return str;
+}
+
+class tst_QConcatenateTablesProxyModel : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void init();
+ void shouldAggregateTwoModelsCorrectly();
+ void shouldAggregateThenRemoveTwoEmptyModelsCorrectly();
+ void shouldAggregateTwoEmptyModelsWhichThenGetFilled();
+ void shouldHandleDataChanged();
+ void shouldHandleSetData();
+ void shouldHandleSetItemData();
+ void shouldHandleRowInsertionAndRemoval();
+ void shouldAggregateAnotherModelThenRemoveModels();
+ void shouldUseSmallestColumnCount();
+ void shouldIncreaseColumnCountWhenRemovingFirstModel();
+ void shouldHandleColumnInsertionAndRemoval();
+ void shouldPropagateLayoutChanged();
+ void shouldReactToModelReset();
+ void shouldUpdateColumnsOnModelReset();
+ void shouldPropagateDropOnItem_data();
+ void shouldPropagateDropOnItem();
+ void shouldPropagateDropBetweenItems();
+ void shouldPropagateDropBetweenItemsAtModelBoundary();
+ void shouldPropagateDropAfterLastRow_data();
+ void shouldPropagateDropAfterLastRow();
+
+private:
+ QStandardItemModel mod;
+ QStandardItemModel mod2;
+ QStandardItemModel mod3;
+};
+
+void tst_QConcatenateTablesProxyModel::init()
+{
+ // Prepare some source models to use later on
+ mod.clear();
+ mod.appendRow({ new QStandardItem(QStringLiteral("A")), new QStandardItem(QStringLiteral("B")), new QStandardItem(QStringLiteral("C")) });
+ mod.setHorizontalHeaderLabels(QStringList() << QStringLiteral("H1") << QStringLiteral("H2") << QStringLiteral("H3"));
+ mod.setVerticalHeaderLabels(QStringList() << QStringLiteral("One"));
+
+ mod2.clear();
+ mod2.appendRow({ new QStandardItem(QStringLiteral("D")), new QStandardItem(QStringLiteral("E")), new QStandardItem(QStringLiteral("F")) });
+ mod2.setHorizontalHeaderLabels(QStringList() << QStringLiteral("H1") << QStringLiteral("H2") << QStringLiteral("H3"));
+ mod2.setVerticalHeaderLabels(QStringList() << QStringLiteral("Two"));
+
+ mod3.clear();
+ mod3.appendRow({ new QStandardItem(QStringLiteral("1")), new QStandardItem(QStringLiteral("2")), new QStandardItem(QStringLiteral("3")) });
+ mod3.appendRow({ new QStandardItem(QStringLiteral("4")), new QStandardItem(QStringLiteral("5")), new QStandardItem(QStringLiteral("6")) });
+}
+
+void tst_QConcatenateTablesProxyModel::shouldAggregateTwoModelsCorrectly()
+{
+ // Given a combining proxy
+ QConcatenateTablesProxyModel pm;
+
+ // When adding two source models
+ pm.addSourceModel(&mod);
+ pm.addSourceModel(&mod2);
+ QAbstractItemModelTester modelTest(&pm, this);
+
+ // Then the proxy should show 2 rows
+ QCOMPARE(pm.rowCount(), 2);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF"));
+
+ // ... and correct headers
+ QCOMPARE(pm.headerData(0, Qt::Horizontal).toString(), QStringLiteral("H1"));
+ QCOMPARE(pm.headerData(1, Qt::Horizontal).toString(), QStringLiteral("H2"));
+ QCOMPARE(pm.headerData(2, Qt::Horizontal).toString(), QStringLiteral("H3"));
+ QCOMPARE(pm.headerData(0, Qt::Vertical).toString(), QStringLiteral("One"));
+ QCOMPARE(pm.headerData(1, Qt::Vertical).toString(), QStringLiteral("Two"));
+
+ QVERIFY(!pm.canFetchMore(QModelIndex()));
+}
+
+void tst_QConcatenateTablesProxyModel::shouldAggregateThenRemoveTwoEmptyModelsCorrectly()
+{
+ // Given a combining proxy
+ QConcatenateTablesProxyModel pm;
+
+ // When adding two empty models
+ QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int)));
+ QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+ QIdentityProxyModel i1, i2;
+ pm.addSourceModel(&i1);
+ pm.addSourceModel(&i2);
+
+ // Then the proxy should still be empty (and no signals emitted)
+ QCOMPARE(pm.rowCount(), 0);
+ QCOMPARE(pm.columnCount(), 0);
+ QCOMPARE(rowATBISpy.count(), 0);
+ QCOMPARE(rowInsertedSpy.count(), 0);
+
+ // When removing the empty models
+ pm.removeSourceModel(&i1);
+ pm.removeSourceModel(&i2);
+
+ // Then the proxy should still be empty (and no signals emitted)
+ QCOMPARE(pm.rowCount(), 0);
+ QCOMPARE(pm.columnCount(), 0);
+ QCOMPARE(rowATBRSpy.count(), 0);
+ QCOMPARE(rowRemovedSpy.count(), 0);
+}
+
+void tst_QConcatenateTablesProxyModel::shouldAggregateTwoEmptyModelsWhichThenGetFilled()
+{
+ // Given a combining proxy with two empty models
+ QConcatenateTablesProxyModel pm;
+ QIdentityProxyModel i1, i2;
+ pm.addSourceModel(&i1);
+ pm.addSourceModel(&i2);
+
+ // When filling them afterwards
+ i1.setSourceModel(&mod);
+ i2.setSourceModel(&mod2);
+ QAbstractItemModelTester modelTest(&pm, this);
+
+ // Then the proxy should show 2 rows
+ QCOMPARE(pm.rowCount(), 2);
+ QCOMPARE(pm.columnCount(), 3);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF"));
+
+ // ... and correct headers
+ QCOMPARE(pm.headerData(0, Qt::Horizontal).toString(), QStringLiteral("H1"));
+ QCOMPARE(pm.headerData(1, Qt::Horizontal).toString(), QStringLiteral("H2"));
+ QCOMPARE(pm.headerData(2, Qt::Horizontal).toString(), QStringLiteral("H3"));
+ QCOMPARE(pm.headerData(0, Qt::Vertical).toString(), QStringLiteral("One"));
+ QCOMPARE(pm.headerData(1, Qt::Vertical).toString(), QStringLiteral("Two"));
+
+ QVERIFY(!pm.canFetchMore(QModelIndex()));
+}
+
+void tst_QConcatenateTablesProxyModel::shouldHandleDataChanged()
+{
+ // Given two models combined
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod);
+ pm.addSourceModel(&mod2);
+ QAbstractItemModelTester modelTest(&pm, this);
+ QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+
+ // When a cell in a source model changes
+ mod.item(0, 0)->setData("a", Qt::EditRole);
+
+ // Then the change should be notified to the proxy
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(dataChangedSpy.at(0).at(0).toModelIndex(), pm.index(0, 0));
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("aBC"));
+
+ // Same test with the other model
+ mod2.item(0, 2)->setData("f", Qt::EditRole);
+
+ QCOMPARE(dataChangedSpy.count(), 2);
+ QCOMPARE(dataChangedSpy.at(1).at(0).toModelIndex(), pm.index(1, 2));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEf"));
+}
+
+void tst_QConcatenateTablesProxyModel::shouldHandleSetData()
+{
+ // Given two models combined
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod);
+ pm.addSourceModel(&mod2);
+ QAbstractItemModelTester modelTest(&pm, this);
+ QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+
+ // When changing a cell using setData
+ pm.setData(pm.index(0, 0), "a");
+
+ // Then the change should be notified to the proxy
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(dataChangedSpy.at(0).at(0).toModelIndex(), pm.index(0, 0));
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("aBC"));
+
+ // Same test with the other model
+ pm.setData(pm.index(1, 2), "f");
+
+ QCOMPARE(dataChangedSpy.count(), 2);
+ QCOMPARE(dataChangedSpy.at(1).at(0).toModelIndex(), pm.index(1, 2));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEf"));
+}
+
+void tst_QConcatenateTablesProxyModel::shouldHandleSetItemData()
+{
+ // Given two models combined
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod);
+ pm.addSourceModel(&mod2);
+ QAbstractItemModelTester modelTest(&pm, this);
+ QSignalSpy dataChangedSpy(&pm, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+
+ // When changing a cell using setData
+ pm.setItemData(pm.index(0, 0), QMap<int, QVariant>{ std::make_pair<int, QVariant>(Qt::DisplayRole, QStringLiteral("X")),
+ std::make_pair<int, QVariant>(Qt::UserRole, 88) });
+
+ // Then the change should be notified to the proxy
+ QCOMPARE(dataChangedSpy.count(), 1);
+ QCOMPARE(dataChangedSpy.at(0).at(0).toModelIndex(), pm.index(0, 0));
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("XBC"));
+ QCOMPARE(pm.index(0, 0).data(Qt::UserRole).toInt(), 88);
+
+ // Same test with the other model
+ pm.setItemData(pm.index(1, 2), QMap<int, QVariant>{ std::make_pair<int, QVariant>(Qt::DisplayRole, QStringLiteral("Y")),
+ std::make_pair<int, QVariant>(Qt::UserRole, 89) });
+
+ QCOMPARE(dataChangedSpy.count(), 2);
+ QCOMPARE(dataChangedSpy.at(1).at(0).toModelIndex(), pm.index(1, 2));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEY"));
+ QCOMPARE(pm.index(1, 2).data(Qt::UserRole).toInt(), 89);
+}
+
+void tst_QConcatenateTablesProxyModel::shouldHandleRowInsertionAndRemoval()
+{
+ // Given two models combined
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod);
+ pm.addSourceModel(&mod2);
+ QAbstractItemModelTester modelTest(&pm, this);
+ QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int)));
+
+ // When a source model inserts a new row
+ QList<QStandardItem *> row;
+ row.append(new QStandardItem(QStringLiteral("1")));
+ row.append(new QStandardItem(QStringLiteral("2")));
+ row.append(new QStandardItem(QStringLiteral("3")));
+ mod2.insertRow(0, row);
+
+ // Then the proxy should notify its users and show changes
+ QCOMPARE(rowSpyToText(rowATBISpy), QStringLiteral("1,1"));
+ QCOMPARE(rowSpyToText(rowInsertedSpy), QStringLiteral("1,1"));
+ QCOMPARE(pm.rowCount(), 3);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("DEF"));
+
+ // When removing that row
+ QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+ mod2.removeRow(0);
+
+ // Then the proxy should notify its users and show changes
+ QCOMPARE(rowATBRSpy.count(), 1);
+ QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 1);
+ QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 1);
+ QCOMPARE(rowRemovedSpy.count(), 1);
+ QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 1);
+ QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 1);
+ QCOMPARE(pm.rowCount(), 2);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF"));
+
+ // When removing the last row from mod2
+ rowATBRSpy.clear();
+ rowRemovedSpy.clear();
+ mod2.removeRow(0);
+
+ // Then the proxy should notify its users and show changes
+ QCOMPARE(rowATBRSpy.count(), 1);
+ QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 1);
+ QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 1);
+ QCOMPARE(rowRemovedSpy.count(), 1);
+ QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 1);
+ QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 1);
+ QCOMPARE(pm.rowCount(), 1);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+}
+
+void tst_QConcatenateTablesProxyModel::shouldAggregateAnotherModelThenRemoveModels()
+{
+ // Given two models combined, and a third model
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod);
+ pm.addSourceModel(&mod2);
+ QAbstractItemModelTester modelTest(&pm, this);
+
+ QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int)));
+
+ // When adding the new source model
+ pm.addSourceModel(&mod3);
+
+ // Then the proxy should notify its users about the two rows inserted
+ QCOMPARE(rowSpyToText(rowATBISpy), QStringLiteral("2,3"));
+ QCOMPARE(rowSpyToText(rowInsertedSpy), QStringLiteral("2,3"));
+ QCOMPARE(pm.rowCount(), 4);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 3), QStringLiteral("456"));
+
+ // When removing that source model again
+ QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+ pm.removeSourceModel(&mod3);
+
+ // Then the proxy should notify its users about the row removed
+ QCOMPARE(rowATBRSpy.count(), 1);
+ QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 2);
+ QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 3);
+ QCOMPARE(rowRemovedSpy.count(), 1);
+ QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 2);
+ QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 3);
+ QCOMPARE(pm.rowCount(), 2);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF"));
+
+ // When removing model 2
+ rowATBRSpy.clear();
+ rowRemovedSpy.clear();
+ pm.removeSourceModel(&mod2);
+ QCOMPARE(rowATBRSpy.count(), 1);
+ QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 1);
+ QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 1);
+ QCOMPARE(rowRemovedSpy.count(), 1);
+ QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 1);
+ QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 1);
+ QCOMPARE(pm.rowCount(), 1);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+
+ // When removing model 1
+ rowATBRSpy.clear();
+ rowRemovedSpy.clear();
+ pm.removeSourceModel(&mod);
+ QCOMPARE(rowATBRSpy.count(), 1);
+ QCOMPARE(rowATBRSpy.at(0).at(1).toInt(), 0);
+ QCOMPARE(rowATBRSpy.at(0).at(2).toInt(), 0);
+ QCOMPARE(rowRemovedSpy.count(), 1);
+ QCOMPARE(rowRemovedSpy.at(0).at(1).toInt(), 0);
+ QCOMPARE(rowRemovedSpy.at(0).at(2).toInt(), 0);
+ QCOMPARE(pm.rowCount(), 0);
+}
+
+void tst_QConcatenateTablesProxyModel::shouldUseSmallestColumnCount()
+{
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod);
+ pm.addSourceModel(&mod2);
+ mod2.setColumnCount(1);
+ pm.addSourceModel(&mod3);
+ QAbstractItemModelTester modelTest(&pm, this);
+
+ QCOMPARE(pm.rowCount(), 4);
+ QCOMPARE(pm.columnCount(), 1);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("A"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("D"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("1"));
+ QCOMPARE(extractRowTexts(&pm, 3), QStringLiteral("4"));
+
+ const QModelIndex indexA = pm.mapFromSource(mod.index(0, 0));
+ QVERIFY(indexA.isValid());
+ QCOMPARE(indexA, pm.index(0, 0));
+
+ const QModelIndex indexB = pm.mapFromSource(mod.index(0, 1));
+ QVERIFY(!indexB.isValid());
+
+ const QModelIndex indexD = pm.mapFromSource(mod2.index(0, 0));
+ QVERIFY(indexD.isValid());
+ QCOMPARE(indexD, pm.index(1, 0));
+}
+
+void tst_QConcatenateTablesProxyModel::shouldIncreaseColumnCountWhenRemovingFirstModel()
+{
+ // Given a model with 2 columns and one with 3 columns
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod);
+ QAbstractItemModelTester modelTest(&pm, this);
+ mod.setColumnCount(2);
+ pm.addSourceModel(&mod2);
+ QCOMPARE(pm.rowCount(), 2);
+ QCOMPARE(pm.columnCount(), 2);
+
+ QSignalSpy colATBISpy(&pm, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy colInsertedSpy(&pm, SIGNAL(columnsInserted(QModelIndex,int,int)));
+ QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+
+ // When removing the first source model
+ pm.removeSourceModel(&mod);
+
+ // Then the proxy should notify its users about the row removed, and the column added
+ QCOMPARE(pm.rowCount(), 1);
+ QCOMPARE(pm.columnCount(), 3);
+ QCOMPARE(rowSpyToText(rowATBRSpy), QStringLiteral("0,0"));
+ QCOMPARE(rowSpyToText(rowRemovedSpy), QStringLiteral("0,0"));
+ QCOMPARE(rowSpyToText(colATBISpy), QStringLiteral("2,2"));
+ QCOMPARE(rowSpyToText(colInsertedSpy), QStringLiteral("2,2"));
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("DEF"));
+}
+
+void tst_QConcatenateTablesProxyModel::shouldHandleColumnInsertionAndRemoval()
+{
+ // Given two models combined, one with 2 columns and one with 3
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod);
+ QAbstractItemModelTester modelTest(&pm, this);
+ mod.setColumnCount(2);
+ pm.addSourceModel(&mod2);
+ QSignalSpy colATBISpy(&pm, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy colInsertedSpy(&pm, SIGNAL(columnsInserted(QModelIndex,int,int)));
+ QSignalSpy colATBRSpy(&pm, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy colRemovedSpy(&pm, SIGNAL(columnsRemoved(QModelIndex,int,int)));
+
+ // When the first source model inserts a new column
+ QCOMPARE(mod.columnCount(), 2);
+ mod.setColumnCount(3);
+
+ // Then the proxy should notify its users and show changes
+ QCOMPARE(rowSpyToText(colATBISpy), QStringLiteral("2,2"));
+ QCOMPARE(rowSpyToText(colInsertedSpy), QStringLiteral("2,2"));
+ QCOMPARE(pm.rowCount(), 2);
+ QCOMPARE(pm.columnCount(), 3);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("AB "));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF"));
+
+ // And when removing two columns
+ mod.setColumnCount(1);
+
+ // Then the proxy should notify its users and show changes
+ QCOMPARE(rowSpyToText(colATBRSpy), QStringLiteral("1,2"));
+ QCOMPARE(rowSpyToText(colRemovedSpy), QStringLiteral("1,2"));
+ QCOMPARE(pm.rowCount(), 2);
+ QCOMPARE(pm.columnCount(), 1);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("A"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("D"));
+}
+
+void tst_QConcatenateTablesProxyModel::shouldPropagateLayoutChanged()
+{
+ // Given two source models, the second one being a QSFPM
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod);
+ QAbstractItemModelTester modelTest(&pm, this);
+
+ QSortFilterProxyModel qsfpm;
+ qsfpm.setSourceModel(&mod3);
+ pm.addSourceModel(&qsfpm);
+
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("456"));
+
+ // And a selection (row 1)
+ QItemSelectionModel selection(&pm);
+ selection.select(pm.index(1, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ const QModelIndexList lst = selection.selectedIndexes();
+ QCOMPARE(lst.count(), 3);
+ for (int col = 0; col < lst.count(); ++col) {
+ QCOMPARE(lst.at(col).row(), 1);
+ QCOMPARE(lst.at(col).column(), col);
+ }
+
+ QSignalSpy layoutATBCSpy(&pm, SIGNAL(layoutAboutToBeChanged()));
+ QSignalSpy layoutChangedSpy(&pm, SIGNAL(layoutChanged()));
+
+ // When changing the sorting in the QSFPM
+ qsfpm.sort(0, Qt::DescendingOrder);
+
+ // Then the proxy should emit the layoutChanged signals, and show re-sorted data
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("123"));
+ QCOMPARE(layoutATBCSpy.count(), 1);
+ QCOMPARE(layoutChangedSpy.count(), 1);
+
+ // And the selection should be updated accordingly (it became row 2)
+ const QModelIndexList lstAfter = selection.selectedIndexes();
+ QCOMPARE(lstAfter.count(), 3);
+ for (int col = 0; col < lstAfter.count(); ++col) {
+ QCOMPARE(lstAfter.at(col).row(), 2);
+ QCOMPARE(lstAfter.at(col).column(), col);
+ }
+}
+
+void tst_QConcatenateTablesProxyModel::shouldReactToModelReset()
+{
+ // Given two source models, the second one being a QSFPM
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod);
+ QAbstractItemModelTester modelTest(&pm, this);
+
+ QSortFilterProxyModel qsfpm;
+ qsfpm.setSourceModel(&mod3);
+ pm.addSourceModel(&qsfpm);
+
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("456"));
+ QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+ QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int)));
+ QSignalSpy colATBRSpy(&pm, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy colRemovedSpy(&pm, SIGNAL(columnsRemoved(QModelIndex,int,int)));
+ QSignalSpy modelATBResetSpy(&pm, SIGNAL(modelAboutToBeReset()));
+ QSignalSpy modelResetSpy(&pm, SIGNAL(modelReset()));
+
+ // When changing the source model of the QSFPM
+ qsfpm.setSourceModel(&mod2);
+
+ // Then the proxy should emit the reset signals, and show the new data
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("ABC"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF"));
+ QCOMPARE(rowATBRSpy.count(), 0);
+ QCOMPARE(rowRemovedSpy.count(), 0);
+ QCOMPARE(rowATBISpy.count(), 0);
+ QCOMPARE(rowInsertedSpy.count(), 0);
+ QCOMPARE(colATBRSpy.count(), 0);
+ QCOMPARE(colRemovedSpy.count(), 0);
+ QCOMPARE(modelATBResetSpy.count(), 1);
+ QCOMPARE(modelResetSpy.count(), 1);
+}
+
+void tst_QConcatenateTablesProxyModel::shouldUpdateColumnsOnModelReset()
+{
+ // Given two source models, the first one being a QSFPM
+ QConcatenateTablesProxyModel pm;
+
+ QSortFilterProxyModel qsfpm;
+ qsfpm.setSourceModel(&mod3);
+ pm.addSourceModel(&qsfpm);
+ pm.addSourceModel(&mod);
+ QAbstractItemModelTester modelTest(&pm, this);
+
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("ABC"));
+
+ // ... and a model with only 2 columns
+ QStandardItemModel mod2Columns;
+ mod2Columns.appendRow({ new QStandardItem(QStringLiteral("W")), new QStandardItem(QStringLiteral("X")) });
+
+ QSignalSpy rowATBRSpy(&pm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy rowRemovedSpy(&pm, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+ QSignalSpy rowATBISpy(&pm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ QSignalSpy rowInsertedSpy(&pm, SIGNAL(rowsInserted(QModelIndex,int,int)));
+ QSignalSpy colATBRSpy(&pm, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy colRemovedSpy(&pm, SIGNAL(columnsRemoved(QModelIndex,int,int)));
+ QSignalSpy modelATBResetSpy(&pm, SIGNAL(modelAboutToBeReset()));
+ QSignalSpy modelResetSpy(&pm, SIGNAL(modelReset()));
+
+ // When changing the source model of the QSFPM
+ qsfpm.setSourceModel(&mod2Columns);
+
+ // Then the proxy should reset, and show the new data
+ QCOMPARE(modelATBResetSpy.count(), 1);
+ QCOMPARE(modelResetSpy.count(), 1);
+ QCOMPARE(rowATBRSpy.count(), 0);
+ QCOMPARE(rowRemovedSpy.count(), 0);
+ QCOMPARE(rowATBISpy.count(), 0);
+ QCOMPARE(rowInsertedSpy.count(), 0);
+ QCOMPARE(colATBRSpy.count(), 0);
+ QCOMPARE(colRemovedSpy.count(), 0);
+
+ QCOMPARE(pm.rowCount(), 2);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("WX"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("AB"));
+}
+
+void tst_QConcatenateTablesProxyModel::shouldPropagateDropOnItem_data()
+{
+ QTest::addColumn<int>("sourceRow");
+ QTest::addColumn<int>("destRow");
+ QTest::addColumn<QString>("expectedResult");
+
+ QTest::newRow("0-3") << 0 << 3 << QStringLiteral("ABCA");
+ QTest::newRow("1-2") << 1 << 2 << QStringLiteral("ABBD");
+ QTest::newRow("2-1") << 2 << 1 << QStringLiteral("ACCD");
+ QTest::newRow("3-0") << 3 << 0 << QStringLiteral("DBCD");
+
+}
+
+void tst_QConcatenateTablesProxyModel::shouldPropagateDropOnItem()
+{
+ // Given two source models who handle drops
+
+ // Note: QStandardItemModel handles drop onto items by inserting child rows,
+ // which is good for QTreeView but not for QTableView or QConcatenateTablesProxyModel.
+ // So we use QStringListModel here instead.
+ QConcatenateTablesProxyModel pm;
+ QStringListModel model1({QStringLiteral("A"), QStringLiteral("B")});
+ QStringListModel model2({QStringLiteral("C"), QStringLiteral("D")});
+ pm.addSourceModel(&model1);
+ pm.addSourceModel(&model2);
+ QAbstractItemModelTester modelTest(&pm, this);
+ QCOMPARE(extractColumnTexts(&pm, 0), QStringLiteral("ABCD"));
+
+ // When dragging one item
+ QFETCH(int, sourceRow);
+ QMimeData* mimeData = pm.mimeData({pm.index(sourceRow, 0)});
+ QVERIFY(mimeData);
+
+ // and dropping onto another item
+ QFETCH(int, destRow);
+ QVERIFY(pm.canDropMimeData(mimeData, Qt::CopyAction, -1, -1, pm.index(destRow, 0)));
+ QVERIFY(pm.dropMimeData(mimeData, Qt::CopyAction, -1, -1, pm.index(destRow, 0)));
+ delete mimeData;
+
+ // Then the result should be as expected
+ QFETCH(QString, expectedResult);
+ QCOMPARE(extractColumnTexts(&pm, 0), expectedResult);
+}
+
+void tst_QConcatenateTablesProxyModel::shouldPropagateDropBetweenItems()
+{
+ // Given two models combined
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod3);
+ pm.addSourceModel(&mod2);
+ QAbstractItemModelTester modelTest(&pm, this);
+ QCOMPARE(pm.rowCount(), 3);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("DEF"));
+
+ // When dragging the last row
+ QModelIndexList indexes;
+ indexes.reserve(pm.columnCount());
+ for (int col = 0; col < pm.columnCount(); ++col) {
+ indexes.append(pm.index(2, col));
+ }
+ QMimeData* mimeData = pm.mimeData(indexes);
+ QVERIFY(mimeData);
+
+ // and dropping it before row 1
+ const int destRow = 1;
+ QVERIFY(pm.canDropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex()));
+ QVERIFY(pm.dropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex()));
+ delete mimeData;
+
+ // Then a new row should be inserted
+ QCOMPARE(pm.rowCount(), 4);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("DEF"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("456"));
+ QCOMPARE(extractRowTexts(&pm, 3), QStringLiteral("DEF"));
+}
+
+void tst_QConcatenateTablesProxyModel::shouldPropagateDropBetweenItemsAtModelBoundary()
+{
+ // Given two models combined
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod3);
+ pm.addSourceModel(&mod2);
+ QAbstractItemModelTester modelTest(&pm, this);
+ QCOMPARE(pm.rowCount(), 3);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("DEF"));
+
+ // When dragging the first row
+ QModelIndexList indexes;
+ indexes.reserve(pm.columnCount());
+ for (int col = 0; col < pm.columnCount(); ++col) {
+ indexes.append(pm.index(0, col));
+ }
+ QMimeData* mimeData = pm.mimeData(indexes);
+ QVERIFY(mimeData);
+
+ // and dropping it before row 2
+ const int destRow = 2;
+ QVERIFY(pm.canDropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex()));
+ QVERIFY(pm.dropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex()));
+ delete mimeData;
+
+ // Then a new row should be inserted
+ QCOMPARE(pm.rowCount(), 4);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 3), QStringLiteral("DEF"));
+
+ // and it should be part of the second model
+ QCOMPARE(mod2.rowCount(), 2);
+}
+
+void tst_QConcatenateTablesProxyModel::shouldPropagateDropAfterLastRow_data()
+{
+ QTest::addColumn<int>("destRow");
+
+ // Dropping after the last row is documented to be done with destRow == -1.
+ QTest::newRow("-1") << -1;
+ // However, sometimes QTreeView calls dropMimeData with destRow == rowCount...
+ // Not sure if that's a bug or not, but let's support it in the model, just in case.
+ QTest::newRow("3") << 3;
+}
+
+void tst_QConcatenateTablesProxyModel::shouldPropagateDropAfterLastRow()
+{
+ QFETCH(int, destRow);
+
+ // Given two models combined
+ QConcatenateTablesProxyModel pm;
+ pm.addSourceModel(&mod3);
+ pm.addSourceModel(&mod2);
+ QAbstractItemModelTester modelTest(&pm, this);
+ QCOMPARE(pm.rowCount(), 3);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("DEF"));
+
+ // When dragging the second row
+ QModelIndexList indexes;
+ indexes.reserve(pm.columnCount());
+ for (int col = 0; col < pm.columnCount(); ++col) {
+ indexes.append(pm.index(1, col));
+ }
+ QMimeData* mimeData = pm.mimeData(indexes);
+ QVERIFY(mimeData);
+
+ // and dropping it after the last row
+ QVERIFY(pm.canDropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex()));
+ QVERIFY(pm.dropMimeData(mimeData, Qt::CopyAction, destRow, 0, QModelIndex()));
+ delete mimeData;
+
+ // Then a new row should be inserted at the end
+ QCOMPARE(pm.rowCount(), 4);
+ QCOMPARE(extractRowTexts(&pm, 0), QStringLiteral("123"));
+ QCOMPARE(extractRowTexts(&pm, 1), QStringLiteral("456"));
+ QCOMPARE(extractRowTexts(&pm, 2), QStringLiteral("DEF"));
+ QCOMPARE(extractRowTexts(&pm, 3), QStringLiteral("456"));
+
+}
+
+QTEST_GUILESS_MAIN(tst_QConcatenateTablesProxyModel)
+
+#include "tst_qconcatenatetablesproxymodel.moc"
diff --git a/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp b/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp
index 6ea7a38137..354190e754 100644
--- a/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp
+++ b/tests/auto/corelib/itemmodels/qitemmodel/modelstotest.cpp
@@ -153,7 +153,7 @@ QAbstractItemModel *ModelsToTest::createModel(const QString &modelType)
QStandardItemModel *standardItemModel = new QStandardItemModel;
model->setSourceModel(standardItemModel);
populateTestArea(model);
- model->setFilterRegExp(QRegExp("(^$|I.*)"));
+ model->setFilterRegularExpression(QRegularExpression("(^$|I.*)"));
return model;
}
@@ -251,7 +251,7 @@ QModelIndex ModelsToTest::populateTestArea(QAbstractItemModel *model)
QString val = xval + QString::number(y) + QString::number(i);
QModelIndex index = model->index(x, y, parent);
model->setData(index, val);
- model->setData(index, blue, Qt::TextColorRole);
+ model->setData(index, blue, Qt::ForegroundRole);
}
}
*/
@@ -276,7 +276,7 @@ QModelIndex ModelsToTest::populateTestArea(QAbstractItemModel *model)
QString val = xval + QString::number(y) + QString::number(i);
QModelIndex index = realModel->index(x, y, parent);
realModel->setData(index, val);
- realModel->setData(index, blue, Qt::TextColorRole);
+ realModel->setData(index, blue, Qt::ForegroundRole);
}
}
*/
diff --git a/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp b/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp
index af52852b99..b9deb7b6a9 100644
--- a/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp
+++ b/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp
@@ -577,12 +577,12 @@ void tst_QItemModel::data()
alignment == Qt::AlignJustify);
}
- QVariant colorVariant = currentModel->data(currentModel->index(0,0), Qt::BackgroundColorRole);
+ QVariant colorVariant = currentModel->data(currentModel->index(0,0), Qt::BackgroundRole);
if (colorVariant.isValid()) {
QVERIFY(colorVariant.canConvert<QColor>());
}
- colorVariant = currentModel->data(currentModel->index(0,0), Qt::TextColorRole);
+ colorVariant = currentModel->data(currentModel->index(0,0), Qt::ForegroundRole);
if (colorVariant.isValid()) {
QVERIFY(colorVariant.canConvert<QColor>());
}
diff --git a/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp
index 6fbaa28d69..f78f5bc138 100644
--- a/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp
+++ b/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp
@@ -2211,8 +2211,8 @@ void tst_QItemSelectionModel::childrenDeselectionSignal()
}
QModelIndex root = model.index(0,0);
- QModelIndex par = root.child(0,0);
- QModelIndex sel = par.child(0,0);
+ QModelIndex par = model.index(0, 0, root);
+ QModelIndex sel = model.index(0, 0, par);
QItemSelectionModel selectionModel(&model);
selectionModel.select(sel, QItemSelectionModel::SelectCurrent);
@@ -2240,9 +2240,9 @@ void tst_QItemSelectionModel::childrenDeselectionSignal()
}
}
- sel = model.index(0, 0).child(0, 0);
+ sel = model.index(0, 0, model.index(0, 0));
selectionModel.select(sel, QItemSelectionModel::Select);
- QModelIndex sel2 = model.index(1, 0).child(0, 0);
+ QModelIndex sel2 = model.index(0, 0, model.index(1, 0));
selectionModel.select(sel2, QItemSelectionModel::Select);
QVERIFY(selectionModel.selection().contains(sel));
@@ -2264,7 +2264,7 @@ void tst_QItemSelectionModel::layoutChangedWithAllSelected1()
QCOMPARE(model.rowCount(), 3);
QCOMPARE(proxy.rowCount(), 3);
- proxy.setFilterRegExp( QRegExp("f"));
+ proxy.setFilterRegularExpression(QRegularExpression("f"));
QCOMPARE(proxy.rowCount(), 2);
QList<QPersistentModelIndex> indexList;
@@ -2276,7 +2276,7 @@ void tst_QItemSelectionModel::layoutChangedWithAllSelected1()
foreach(QPersistentModelIndex index, indexList)
QVERIFY(selection.isSelected(index));
- proxy.setFilterRegExp(QRegExp());
+ proxy.setFilterRegularExpression(QRegularExpression());
QCOMPARE(proxy.rowCount(), 3);
//let's check the selection hasn't changed
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
index ccce5a44e5..0f7588a71a 100644
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
@@ -3977,7 +3977,7 @@ void tst_QSortFilterProxyModel::hierarchyFilterInvalidation()
QTreeView view;
view.setModel(&proxy);
- view.setCurrentIndex(proxy.index(2, 0).child(0, 0));
+ view.setCurrentIndex(proxy.index(0, 0, proxy.index(2, 0)));
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
diff --git a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp
index 1b40e77648..3919472b96 100644
--- a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp
+++ b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp
@@ -84,8 +84,116 @@ private slots:
void setData_emits_on_change_only();
void supportedDragDropActions();
+
+ void moveRows_data();
+ void moveRows();
+ void moveRowsInvalid_data();
+ void moveRowsInvalid();
+
+ void itemData();
+ void setItemData();
};
+void tst_QStringListModel::moveRowsInvalid_data()
+{
+ QTest::addColumn<QStringListModel*>("baseModel");
+ QTest::addColumn<QModelIndex>("startParent");
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<QModelIndex>("destinationParent");
+ QTest::addColumn<int>("destination");
+
+ QStringListModel* tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("destination_equal_source") << tempModel << QModelIndex() << 0 << 1 << QModelIndex() << 1;
+ tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("count_equal_0") << tempModel << QModelIndex() << 0 << 0 << QModelIndex() << 2;
+ tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("move_child") << tempModel << tempModel->index(0, 0) << 0 << 1 << QModelIndex() << 2;
+ tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("move_to_child") << tempModel << QModelIndex() << 0 << 1 << tempModel->index(0, 0) << 2;
+ tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("negative_count") << tempModel << QModelIndex() << 0 << -1 << QModelIndex() << 2;
+ tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("negative_source_row") << tempModel << QModelIndex() << -1 << 1 << QModelIndex() << 2;
+ tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("negative_destination_row") << tempModel << QModelIndex() << 0 << 1 << QModelIndex() << -1;
+ tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("source_row_equal_rowCount") << tempModel << QModelIndex() << tempModel->rowCount() << 1 << QModelIndex() << 1;
+ tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("destination_row_greater_rowCount") << tempModel << QModelIndex() << 0 << 1 << QModelIndex() << tempModel->rowCount() + 1;
+ tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("move_row_within_source_range") << tempModel << QModelIndex() << 0 << 3 << QModelIndex() << 2;
+ tempModel = new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
+ QTest::addRow("destination_row_before_0") << tempModel << QModelIndex() << 1 << 1 << QModelIndex() << 0;
+}
+
+void tst_QStringListModel::moveRowsInvalid()
+{
+ QFETCH(QStringListModel* const, baseModel);
+ QFETCH(const QModelIndex, startParent);
+ QFETCH(const int, startRow);
+ QFETCH(const int, count);
+ QFETCH(const QModelIndex, destinationParent);
+ QFETCH(const int, destination);
+
+ QSignalSpy rowMovedSpy(baseModel, &QAbstractItemModel::rowsMoved);
+ QSignalSpy rowAboutMovedSpy(baseModel, &QAbstractItemModel::rowsAboutToBeMoved);
+ QVERIFY(rowMovedSpy.isValid());
+ QVERIFY(rowAboutMovedSpy.isValid());
+ QVERIFY(!baseModel->moveRows(startParent, startRow, count, destinationParent, destination));
+ QCOMPARE(rowMovedSpy.size(), 0);
+ QCOMPARE(rowAboutMovedSpy.size(), 0);
+ delete baseModel;
+}
+
+void tst_QStringListModel::moveRows_data()
+{
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<int>("destination");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("1_Item_from_top_to_middle") << 0 << 1 << 3 << QStringList{"B", "C", "A", "D", "E", "F"};
+ QTest::newRow("1_Item_from_top_to_bottom") << 0 << 1 << 6 << QStringList{"B", "C", "D", "E", "F", "A"};
+ QTest::newRow("1_Item_from_middle_to_top") << 2 << 1 << 1 << QStringList{"C", "A", "B", "D", "E", "F"};
+ QTest::newRow("1_Item_from_bottom_to_middle") << 5 << 1 << 3 << QStringList{"A", "B", "F", "C", "D", "E"};
+ QTest::newRow("1_Item_from_bottom to_top") << 5 << 1 << 1 << QStringList{"F", "A", "B", "C", "D", "E"};
+ QTest::newRow("1_Item_from_middle_to_bottom") << 2 << 1 << 6 << QStringList{"A", "B", "D", "E", "F", "C"};
+ QTest::newRow("1_Item_from_middle_to_middle_before") << 2 << 1 << 1 << QStringList{"C", "A", "B", "D", "E", "F"};
+ QTest::newRow("1_Item_from_middle_to_middle_after") << 2 << 1 << 4 << QStringList{"A", "B", "D", "C", "E", "F"};
+
+ QTest::newRow("2_Items_from_top_to_middle") << 0 << 2 << 3 << QStringList{"C", "A", "B", "D", "E", "F"};
+ QTest::newRow("2_Items_from_top_to_bottom") << 0 << 2 << 6 << QStringList{"C", "D", "E", "F", "A", "B"};
+ QTest::newRow("2_Items_from_middle_to_top") << 2 << 2 << 1 << QStringList{"C", "D", "A", "B", "E", "F"};
+ QTest::newRow("2_Items_from_bottom_to_middle") << 4 << 2 << 3 << QStringList{"A", "B", "E", "F", "C", "D"};
+ QTest::newRow("2_Items_from_bottom_to_top") << 4 << 2 << 1 << QStringList{"E", "F", "A", "B", "C", "D"};
+ QTest::newRow("2_Items_from_middle_to_bottom") << 2 << 2 << 6 << QStringList{"A", "B", "E", "F", "C", "D"};
+ QTest::newRow("2_Items_from_middle_to_middle_before") << 3 << 2 << 2 << QStringList{"A", "D", "E", "B", "C", "F"};
+ QTest::newRow("2_Items_from_middle_to_middle_after") << 1 << 2 << 5 << QStringList{"A", "D", "E", "B", "C", "F"};
+}
+
+void tst_QStringListModel::moveRows()
+{
+ QFETCH(const int, startRow);
+ QFETCH(const int, count);
+ QFETCH(const int, destination);
+ QFETCH(const QStringList, expected);
+ QStringListModel baseModel(QStringList{"A", "B", "C", "D", "E", "F"});
+ QSignalSpy rowMovedSpy(&baseModel, &QAbstractItemModel::rowsMoved);
+ QSignalSpy rowAboutMovedSpy(&baseModel, &QAbstractItemModel::rowsAboutToBeMoved);
+ QVERIFY(baseModel.moveRows(QModelIndex(), startRow, count, QModelIndex(), destination));
+ QCOMPARE(baseModel.stringList(), expected);
+ QCOMPARE(rowMovedSpy.size(), 1);
+ QCOMPARE(rowAboutMovedSpy.size(), 1);
+ for (const QList<QVariant> &signalArgs : {rowMovedSpy.first(), rowAboutMovedSpy.first()}){
+ QVERIFY(!signalArgs.at(0).value<QModelIndex>().isValid());
+ QCOMPARE(signalArgs.at(1).toInt(), startRow);
+ QCOMPARE(signalArgs.at(2).toInt(), startRow + count - 1);
+ QVERIFY(!signalArgs.at(3).value<QModelIndex>().isValid());
+ QCOMPARE(signalArgs.at(4).toInt(), destination);
+ }
+}
+
void tst_QStringListModel::rowsAboutToBeRemoved_rowsRemoved_data()
{
QTest::addColumn<QStringList>("input");
@@ -225,7 +333,7 @@ template <class C>
C sorted(C c)
{
std::sort(c.begin(), c.end());
- return qMove(c);
+ return std::move(c);
}
void tst_QStringListModel::setData_emits_both_roles()
@@ -248,6 +356,74 @@ void tst_QStringListModel::setData_emits_both_roles()
expected);
}
+void tst_QStringListModel::itemData()
+{
+ QStringListModel testModel{ QStringList {
+ QStringLiteral("One"),
+ QStringLiteral("Two"),
+ QStringLiteral("Three"),
+ QStringLiteral("Four"),
+ QStringLiteral("Five")
+ }};
+ QMap<int, QVariant> compareMap;
+ QCOMPARE(testModel.itemData(QModelIndex()), compareMap);
+ compareMap.insert(Qt::DisplayRole, QStringLiteral("Two"));
+ compareMap.insert(Qt::EditRole, QStringLiteral("Two"));
+ QCOMPARE(testModel.itemData(testModel.index(1, 0)), compareMap);
+}
+
+void tst_QStringListModel::setItemData()
+{
+ QStringListModel testModel{ QStringList {
+ QStringLiteral("One"),
+ QStringLiteral("Two"),
+ QStringLiteral("Three"),
+ QStringLiteral("Four"),
+ QStringLiteral("Five")
+ }};
+ QSignalSpy dataChangedSpy(&testModel, &QAbstractItemModel::dataChanged);
+ QModelIndex changeIndex = testModel.index(1, 0);
+ const QVector<int> changeRoles{Qt::DisplayRole, Qt::EditRole};
+ const QString changedString("Changed");
+ QMap<int, QVariant> newItemData{std::make_pair<int>(Qt::DisplayRole, changedString)};
+ // invalid index does nothing and returns false
+ QVERIFY(!testModel.setItemData(QModelIndex(), newItemData));
+ // valid data is set, return value is true and dataChanged is emitted once
+ QVERIFY(testModel.setItemData(changeIndex, newItemData));
+ QCOMPARE(changeIndex.data(Qt::DisplayRole).toString(), changedString);
+ QCOMPARE(changeIndex.data(Qt::EditRole).toString(), changedString);
+ QCOMPARE(dataChangedSpy.size(), 1);
+ QVariantList dataChangedArguments = dataChangedSpy.takeFirst();
+ QCOMPARE(dataChangedArguments.at(0).value<QModelIndex>(), changeIndex);
+ QCOMPARE(dataChangedArguments.at(1).value<QModelIndex>(), changeIndex);
+ QCOMPARE(dataChangedArguments.at(2).value<QVector<int> >(), changeRoles);
+ // Unsupported roles do nothing return false
+ newItemData.clear();
+ newItemData.insert(Qt::UserRole, changedString);
+ QVERIFY(!testModel.setItemData(changeIndex, newItemData));
+ QCOMPARE(dataChangedSpy.size(), 0);
+ // If some but not all the roles are supported it returns false and does nothing
+ newItemData.insert(Qt::EditRole, changedString);
+ changeIndex = testModel.index(2, 0);
+ QVERIFY(!testModel.setItemData(changeIndex, newItemData));
+ QCOMPARE(changeIndex.data(Qt::DisplayRole).toString(), QStringLiteral("Three"));
+ QCOMPARE(changeIndex.data(Qt::EditRole).toString(), QStringLiteral("Three"));
+ QCOMPARE(dataChangedSpy.size(), 0);
+ // Qt::EditRole and Qt::DisplayRole are both set, Qt::EditRole takes precedence
+ newItemData.clear();
+ newItemData.insert(Qt::EditRole, changedString);
+ newItemData.insert(Qt::DisplayRole, QStringLiteral("Ignored"));
+ changeIndex = testModel.index(3, 0);
+ QVERIFY(testModel.setItemData(changeIndex, newItemData));
+ QCOMPARE(changeIndex.data(Qt::DisplayRole).toString(), changedString);
+ QCOMPARE(changeIndex.data(Qt::EditRole).toString(), changedString);
+ QCOMPARE(dataChangedSpy.size(), 1);
+ dataChangedArguments = dataChangedSpy.takeFirst();
+ QCOMPARE(dataChangedArguments.at(0).value<QModelIndex>(), changeIndex);
+ QCOMPARE(dataChangedArguments.at(1).value<QModelIndex>(), changeIndex);
+ QCOMPARE(dataChangedArguments.at(2).value<QVector<int> >(), changeRoles);
+}
+
void tst_QStringListModel::setData_emits_on_change_only()
{
QStringListModel model(QStringList{QStringLiteral("one"), QStringLiteral("two")});
diff --git a/tests/auto/corelib/itemmodels/qtransposeproxymodel/qtransposeproxymodel.pro b/tests/auto/corelib/itemmodels/qtransposeproxymodel/qtransposeproxymodel.pro
new file mode 100644
index 0000000000..3834add115
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qtransposeproxymodel/qtransposeproxymodel.pro
@@ -0,0 +1,6 @@
+CONFIG += testcase
+TARGET = tst_qtransposeproxymodel
+QT = core gui testlib
+
+SOURCES = tst_qtransposeproxymodel.cpp
+
diff --git a/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp b/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp
new file mode 100644
index 0000000000..a30ac46571
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qtransposeproxymodel/tst_qtransposeproxymodel.cpp
@@ -0,0 +1,915 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QTest>
+#include <QSignalSpy>
+#include <QStandardItemModel>
+#include <QStringListModel>
+#include <QAbstractItemModelTester>
+#include <random>
+
+#include <qtransposeproxymodel.h>
+
+class tst_QTransposeProxyModel : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void initTestCase();
+ void index();
+ void data();
+ void setData_data();
+ void setData();
+ void parent();
+ void mapToSource();
+ void mapFromSource();
+ void basicTest_data();
+ void basicTest();
+ void sort();
+ void insertRowBase_data();
+ void insertRowBase();
+ void insertColumnBase_data();
+ void insertColumnBase();
+ void insertColumnProxy_data();
+ void insertColumnProxy();
+ void insertRowProxy_data();
+ void insertRowProxy();
+ void removeRowBase_data();
+ void removeRowBase();
+ void removeColumnBase_data();
+ void removeColumnBase();
+ void removeColumnProxy_data();
+ void removeColumnProxy();
+ void removeRowProxy_data();
+ void removeRowProxy();
+ void headerData();
+ void setHeaderData();
+ void span();
+ void itemData();
+ void setItemData();
+ void moveRowsBase();
+ void moveColumnsProxy();
+private:
+ void testTransposed(
+ const QAbstractItemModel *const baseModel,
+ const QAbstractItemModel *const transposed,
+ const QModelIndex &baseParent = QModelIndex(),
+ const QModelIndex &transposedParent = QModelIndex()
+ );
+ QAbstractItemModel *createListModel(QObject *parent);
+ QAbstractItemModel *createTableModel(QObject *parent);
+ QAbstractItemModel *createTreeModel(QObject *parent);
+};
+
+QAbstractItemModel *tst_QTransposeProxyModel::createListModel(QObject *parent)
+{
+ QStringList sequence;
+ sequence.reserve(10);
+ for (int i = 0; i < 10; ++i)
+ sequence.append(QString::number(i));
+ return new QStringListModel(sequence, parent);
+}
+
+QAbstractItemModel *tst_QTransposeProxyModel::createTableModel(QObject *parent)
+{
+ QAbstractItemModel *model = new QStandardItemModel(parent);
+ model->insertRows(0, 5);
+ model->insertColumns(0, 4);
+ for (int i = 0; i < model->rowCount(); ++i) {
+ for (int j = 0; j < model->columnCount(); ++j) {
+ model->setData(model->index(i, j), QStringLiteral("%1,%2").arg(i).arg(j), Qt::EditRole);
+ model->setData(model->index(i, j), i, Qt::UserRole);
+ model->setData(model->index(i, j), j, Qt::UserRole + 1);
+ }
+ }
+ return model;
+}
+
+QAbstractItemModel *tst_QTransposeProxyModel::createTreeModel(QObject *parent)
+{
+ QAbstractItemModel *model = new QStandardItemModel(parent);
+ model->insertRows(0, 5);
+ model->insertColumns(0, 4);
+ for (int i = 0; i < model->rowCount(); ++i) {
+ for (int j = 0; j < model->columnCount(); ++j) {
+ const QModelIndex parIdx = model->index(i, j);
+ model->setData(parIdx, QStringLiteral("%1,%2").arg(i).arg(j), Qt::EditRole);
+ model->setData(parIdx, i, Qt::UserRole);
+ model->setData(parIdx, j, Qt::UserRole + 1);
+ model->insertRows(0, 3, parIdx);
+ model->insertColumns(0, 2, parIdx);
+ for (int h = 0; h < model->rowCount(parIdx); ++h) {
+ for (int k = 0; k < model->columnCount(parIdx); ++k) {
+ const QModelIndex childIdx = model->index(h, k, parIdx);
+ model->setData(childIdx, QStringLiteral("%1,%2,%3,%4").arg(i).arg(j).arg(h).arg(k), Qt::EditRole);
+ model->setData(childIdx, i, Qt::UserRole);
+ model->setData(childIdx, j, Qt::UserRole + 1);
+ model->setData(childIdx, h, Qt::UserRole + 2);
+ model->setData(childIdx, k, Qt::UserRole + 3);
+ }
+ }
+ }
+ }
+ return model;
+}
+
+void tst_QTransposeProxyModel::testTransposed(
+ const QAbstractItemModel *const baseModel,
+ const QAbstractItemModel *const transposed,
+ const QModelIndex &baseParent,
+ const QModelIndex &transposedParent
+)
+{
+ QCOMPARE(transposed->hasChildren(transposedParent), baseModel->hasChildren(baseParent));
+ QCOMPARE(transposed->columnCount(transposedParent), baseModel->rowCount(baseParent));
+ QCOMPARE(transposed->rowCount(transposedParent), baseModel->columnCount(baseParent));
+ for (int i = 0, maxRow = baseModel->rowCount(baseParent); i < maxRow; ++i) {
+ for (int j = 0, maxCol = baseModel->columnCount(baseParent); j < maxCol; ++j) {
+ const QModelIndex baseIdx = baseModel->index(i, j, baseParent);
+ const QModelIndex transIdx = transposed->index(j, i, transposedParent);
+ QCOMPARE(transIdx.data(), baseIdx.data());
+ QCOMPARE(transIdx.data(Qt::UserRole), baseIdx.data(Qt::UserRole));
+ QCOMPARE(transIdx.data(Qt::UserRole + 1), baseIdx.data(Qt::UserRole + 1));
+ QCOMPARE(transIdx.data(Qt::UserRole + 2), baseIdx.data(Qt::UserRole + 2));
+ QCOMPARE(transIdx.data(Qt::UserRole + 3), baseIdx.data(Qt::UserRole + 3));
+ if (baseModel->hasChildren(baseIdx)) {
+ testTransposed(baseModel, transposed, baseIdx, transIdx);
+ }
+ }
+ }
+}
+
+void tst_QTransposeProxyModel::initTestCase()
+{
+ qRegisterMetaType<QList<QPersistentModelIndex> >();
+ qRegisterMetaType<QAbstractItemModel::LayoutChangeHint>();
+}
+
+void tst_QTransposeProxyModel::index()
+{
+ QAbstractItemModel *model = createTreeModel(this);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ QVERIFY(!proxy.index(0, -1).isValid());
+ QVERIFY(!proxy.index(0, -1).isValid());
+ QVERIFY(!proxy.index(-1, -1).isValid());
+ QVERIFY(!proxy.index(0, proxy.columnCount()).isValid());
+ QVERIFY(!proxy.index(proxy.rowCount(), 0).isValid());
+ QVERIFY(!proxy.index(proxy.rowCount(), proxy.columnCount()).isValid());
+ QModelIndex tempIdx = proxy.index(0, 1);
+ QVERIFY(tempIdx.isValid());
+ QCOMPARE(tempIdx.row(), 0);
+ QCOMPARE(tempIdx.column(), 1);
+ tempIdx = proxy.index(0, 1, tempIdx);
+ QVERIFY(tempIdx.isValid());
+ QCOMPARE(tempIdx.row(), 0);
+ QCOMPARE(tempIdx.column(), 1);
+ delete model;
+}
+
+void tst_QTransposeProxyModel::data()
+{
+ QStringListModel model{QStringList{"A", "B"}};
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(&model);
+ QCOMPARE(proxy.index(0, 1).data().toString(), QStringLiteral("B"));
+}
+
+void tst_QTransposeProxyModel::parent()
+{
+ QAbstractItemModel *model = createTreeModel(this);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ const QModelIndex parentIdx = proxy.index(0, 0);
+ const QModelIndex childIdx = proxy.index(0, 0, parentIdx);
+ QVERIFY(parentIdx.isValid());
+ QVERIFY(childIdx.isValid());
+ QCOMPARE(childIdx.parent(), parentIdx);
+ delete model;
+}
+
+void tst_QTransposeProxyModel::mapToSource()
+{
+ QAbstractItemModel *model = createTreeModel(this);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ QVERIFY(!proxy.mapToSource(QModelIndex()).isValid());
+ QCOMPARE(proxy.mapToSource(proxy.index(0, 0)), model->index(0, 0));
+ QCOMPARE(proxy.mapToSource(proxy.index(1, 0)), model->index(0, 1));
+ QCOMPARE(proxy.mapToSource(proxy.index(0, 1)), model->index(1, 0));
+ const QModelIndex proxyParent = proxy.index(1, 0);
+ const QModelIndex sourceParent = model->index(0, 1);
+ QCOMPARE(proxy.mapToSource(proxy.index(0, 0, proxyParent)), model->index(0, 0, sourceParent));
+ QCOMPARE(proxy.mapToSource(proxy.index(1, 0, proxyParent)), model->index(0, 1, sourceParent));
+ QCOMPARE(proxy.mapToSource(proxy.index(0, 1, proxyParent)), model->index(1, 0, sourceParent));
+ delete model;
+}
+
+void tst_QTransposeProxyModel::mapFromSource()
+{
+ QAbstractItemModel *model = createTreeModel(this);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ QVERIFY(!proxy.mapFromSource(QModelIndex()).isValid());
+ QCOMPARE(proxy.mapFromSource(model->index(0, 0)), proxy.index(0, 0));
+ QCOMPARE(proxy.mapFromSource(model->index(0, 1)), proxy.index(1, 0));
+ QCOMPARE(proxy.mapFromSource(model->index(1, 0)), proxy.index(0, 1));
+ const QModelIndex proxyParent = proxy.index(1, 0);
+ const QModelIndex sourceParent = model->index(0, 1);
+ QCOMPARE(proxy.mapToSource(proxy.index(0, 0, proxyParent)), model->index(0, 0, sourceParent));
+ QCOMPARE(proxy.mapFromSource(model->index(1, 0, sourceParent)), proxy.index(0, 1, proxyParent));
+ QCOMPARE(proxy.mapFromSource(model->index(0, 1, sourceParent)), proxy.index(1, 0, proxyParent));
+ delete model;
+}
+
+void tst_QTransposeProxyModel::basicTest_data()
+{
+ QTest::addColumn<QAbstractItemModel *>("model");
+ QTest::newRow("List") << createListModel(this);
+ QTest::newRow("Table") << createTableModel(this);
+ QTest::newRow("Tree") << createTreeModel(this);
+}
+
+void tst_QTransposeProxyModel::basicTest()
+{
+ QFETCH(QAbstractItemModel *, model);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ testTransposed(model, &proxy);
+ delete model;
+}
+
+void tst_QTransposeProxyModel::sort()
+{
+ QStringList sequence;
+ sequence.reserve(100);
+ for (int i = 0; i < 100; ++i)
+ sequence.append(QStringLiteral("%1").arg(i, 3, 10, QLatin1Char('0')));
+ std::shuffle(sequence.begin(), sequence.end(), std::mt19937(88));
+ const QString firstItemBeforeSort = sequence.first();
+ QStringListModel baseModel(sequence);
+ QTransposeProxyModel proxyModel;
+ new QAbstractItemModelTester(&proxyModel, &proxyModel);
+ proxyModel.setSourceModel(&baseModel);
+ QSignalSpy layoutChangedSpy(&proxyModel, &QAbstractItemModel::layoutChanged);
+ QVERIFY(layoutChangedSpy.isValid());
+ QSignalSpy layoutAboutToBeChangedSpy(&proxyModel, &QAbstractItemModel::layoutAboutToBeChanged);
+ QVERIFY(layoutAboutToBeChangedSpy.isValid());
+ QPersistentModelIndex firstIndexBeforeSort = proxyModel.index(0, 0);
+ baseModel.sort(0, Qt::AscendingOrder);
+ QCOMPARE(layoutChangedSpy.count(), 1);
+ QCOMPARE(layoutAboutToBeChangedSpy.count(), 1);
+ QCOMPARE(layoutChangedSpy.takeFirst().at(1).toInt(), int(QAbstractItemModel::HorizontalSortHint));
+ QCOMPARE(firstIndexBeforeSort.data().toString(), firstItemBeforeSort);
+ for (int i = 0; i < 100; ++i)
+ QCOMPARE(proxyModel.index(0, i).data().toInt(), i);
+}
+
+void tst_QTransposeProxyModel::removeColumnBase_data()
+{
+ QTest::addColumn<QAbstractItemModel *>("model");
+ QTest::addColumn<QModelIndex>("parent");
+ QTest::newRow("Table") << createTableModel(this) << QModelIndex();
+ QTest::newRow("Tree_Root_Item") << createTreeModel(this) << QModelIndex();
+ QAbstractItemModel *model = createTreeModel(this);
+ QTest::newRow("Tree_Child_Item") << model << model->index(0, 0);
+}
+
+void tst_QTransposeProxyModel::removeColumnBase()
+{
+ QFETCH(QAbstractItemModel * const, model);
+ QFETCH(const QModelIndex, parent);
+ QTransposeProxyModel proxy;
+ QSignalSpy rowRemoveSpy(&proxy, &QAbstractItemModel::rowsRemoved);
+ QVERIFY(rowRemoveSpy.isValid());
+ QSignalSpy rowAboutToBeRemoveSpy(&proxy, &QAbstractItemModel::rowsAboutToBeRemoved);
+ QVERIFY(rowAboutToBeRemoveSpy.isValid());
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ const int oldRowCount = proxy.rowCount(proxy.mapFromSource(parent));
+ const QVariant expectedNewVal = model->index(0, 2, parent).data();
+ QVERIFY(model->removeColumn(1, parent));
+ QCOMPARE(proxy.rowCount(proxy.mapFromSource(parent)), oldRowCount - 1);
+ QCOMPARE(proxy.index(1, 0, proxy.mapFromSource(parent)).data(), expectedNewVal);
+ QCOMPARE(rowRemoveSpy.count(), 1);
+ QCOMPARE(rowAboutToBeRemoveSpy.count(), 1);
+ for (const auto &spyArgs : {rowRemoveSpy.takeFirst(),
+ rowAboutToBeRemoveSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxy.mapFromSource(parent));
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ delete model;
+}
+
+void tst_QTransposeProxyModel::insertColumnBase_data()
+{
+ QTest::addColumn<QAbstractItemModel *>("model");
+ QTest::addColumn<QModelIndex>("parent");
+ QTest::newRow("Table") << createTableModel(this) << QModelIndex();
+ QTest::newRow("Tree_Root_Item") << createTreeModel(this) << QModelIndex();
+ QAbstractItemModel *model = createTreeModel(this);
+ QTest::newRow("Tree_Child_Item") << model << model->index(0, 0);
+}
+
+void tst_QTransposeProxyModel::insertColumnBase()
+{
+ QFETCH(QAbstractItemModel * const, model);
+ QFETCH(const QModelIndex, parent);
+ QTransposeProxyModel proxy;
+ QSignalSpy rowInsertSpy(&proxy, &QAbstractItemModel::rowsInserted);
+ QVERIFY(rowInsertSpy.isValid());
+ QSignalSpy rowAboutToBeInsertSpy(&proxy, &QAbstractItemModel::rowsAboutToBeInserted);
+ QVERIFY(rowAboutToBeInsertSpy.isValid());
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ const int oldRowCount = proxy.rowCount(proxy.mapFromSource(parent));
+ QVERIFY(model->insertColumn(1, parent));
+ QCOMPARE(proxy.rowCount(proxy.mapFromSource(parent)), oldRowCount + 1);
+ QVERIFY(!proxy.index(1, 0, proxy.mapFromSource(parent)).data().isValid());
+ QCOMPARE(rowInsertSpy.count(), 1);
+ QCOMPARE(rowAboutToBeInsertSpy.count(), 1);
+ for (const auto &spyArgs : {rowInsertSpy.takeFirst(),
+ rowAboutToBeInsertSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxy.mapFromSource(parent));
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ delete model;
+}
+
+void tst_QTransposeProxyModel::removeRowBase_data()
+{
+ QTest::addColumn<QAbstractItemModel *>("model");
+ QTest::addColumn<QModelIndex>("parent");
+ QTest::newRow("List") << createListModel(this) << QModelIndex();
+ QTest::newRow("Table") << createTableModel(this) << QModelIndex();
+ QTest::newRow("Tree_Root_Item") << createTreeModel(this) << QModelIndex();
+ QAbstractItemModel *model = createTreeModel(this);
+ QTest::newRow("Tree_Child_Item") << model << model->index(0, 0);
+}
+
+void tst_QTransposeProxyModel::removeRowBase()
+{
+ QFETCH(QAbstractItemModel * const, model);
+ QFETCH(const QModelIndex, parent);
+ QTransposeProxyModel proxy;
+ QSignalSpy columnsRemoveSpy(&proxy, &QAbstractItemModel::columnsRemoved);
+ QVERIFY(columnsRemoveSpy.isValid());
+ QSignalSpy columnsAboutToBeRemoveSpy(&proxy, &QAbstractItemModel::columnsAboutToBeRemoved);
+ QVERIFY(columnsAboutToBeRemoveSpy.isValid());
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ const int oldColCount = proxy.columnCount(proxy.mapFromSource(parent));
+ const QVariant expectedNewVal = model->index(2, 0, parent).data();
+ QVERIFY(model->removeRow(1, parent));
+ QCOMPARE(proxy.columnCount(proxy.mapFromSource(parent)), oldColCount - 1);
+ QCOMPARE(proxy.index(0, 1, proxy.mapFromSource(parent)).data(), expectedNewVal);
+ QCOMPARE(columnsRemoveSpy.count(), 1);
+ QCOMPARE(columnsAboutToBeRemoveSpy.count(), 1);
+ for (const auto &spyArgs : {columnsRemoveSpy.takeFirst(),
+ columnsAboutToBeRemoveSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxy.mapFromSource(parent));
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ delete model;
+}
+
+void tst_QTransposeProxyModel::insertRowBase_data()
+{
+ QTest::addColumn<QAbstractItemModel *>("model");
+ QTest::addColumn<QModelIndex>("parent");
+ QTest::newRow("List") << createListModel(this) << QModelIndex();
+ QTest::newRow("Table") << createTableModel(this) << QModelIndex();
+ QTest::newRow("Tree_Root_Item") << createTreeModel(this) << QModelIndex();
+ QAbstractItemModel *model = createTreeModel(this);
+ QTest::newRow("Tree_Child_Item") << model << model->index(0, 0);
+}
+
+void tst_QTransposeProxyModel::insertRowBase()
+{
+ QFETCH(QAbstractItemModel * const, model);
+ QFETCH(const QModelIndex, parent);
+ QTransposeProxyModel proxy;
+ QSignalSpy columnsInsertSpy(&proxy, &QAbstractItemModel::columnsInserted);
+ QVERIFY(columnsInsertSpy.isValid());
+ QSignalSpy columnsAboutToBeInsertSpy(&proxy, &QAbstractItemModel::columnsAboutToBeInserted);
+ QVERIFY(columnsAboutToBeInsertSpy.isValid());
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ const int oldColCount = proxy.columnCount(proxy.mapFromSource(parent));
+ QVERIFY(model->insertRow(1, parent));
+ QCOMPARE(proxy.columnCount(proxy.mapFromSource(parent)), oldColCount + 1);
+ QVERIFY(proxy.index(0, 1, proxy.mapFromSource(parent)).data().isNull());
+ QCOMPARE(columnsInsertSpy.count(), 1);
+ QCOMPARE(columnsAboutToBeInsertSpy.count(), 1);
+ for (const auto &spyArgs : {columnsInsertSpy.takeFirst(),
+ columnsAboutToBeInsertSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxy.mapFromSource(parent));
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ delete model;
+}
+
+void tst_QTransposeProxyModel::removeColumnProxy_data()
+{
+ QTest::addColumn<QAbstractItemModel *>("model");
+ QTest::addColumn<bool>("rootItem");
+ QTest::newRow("List") << createListModel(this) << true;
+ QTest::newRow("Table") << createTableModel(this) << true;
+ QTest::newRow("Tree_Root_Item") << createTreeModel(this) << true;
+ QTest::newRow("Tree_Child_Item") << createTreeModel(this) << false;
+}
+
+void tst_QTransposeProxyModel::removeColumnProxy()
+{
+ QFETCH(QAbstractItemModel *, model);
+ QFETCH(bool, rootItem);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ QSignalSpy columnsRemoveSpy(&proxy, &QAbstractItemModel::columnsRemoved);
+ QVERIFY(columnsRemoveSpy.isValid());
+ QSignalSpy columnsAboutToBeRemoveSpy(&proxy, &QAbstractItemModel::columnsAboutToBeRemoved);
+ QVERIFY(columnsAboutToBeRemoveSpy.isValid());
+ QSignalSpy rowsRemoveSpy(model, &QAbstractItemModel::rowsRemoved);
+ QVERIFY(rowsRemoveSpy.isValid());
+ QSignalSpy rowsAboutToBeRemoveSpy(model, &QAbstractItemModel::rowsAboutToBeRemoved);
+ QVERIFY(rowsAboutToBeRemoveSpy.isValid());
+ proxy.setSourceModel(model);
+ const QModelIndex proxyParent = rootItem ? QModelIndex() : proxy.index(0, 1);
+ const QModelIndex sourceParent = proxy.mapToSource(proxyParent);
+ const int oldColCount = proxy.columnCount(proxyParent);
+ const int oldRowCount = model->rowCount(sourceParent);
+ const QVariant expectedNewVal = proxy.index(0, 2, proxyParent).data();
+ QVERIFY(proxy.removeColumn(1, proxyParent));
+ QCOMPARE(proxy.columnCount(proxyParent), oldColCount - 1);
+ QCOMPARE(model->rowCount(sourceParent), oldRowCount - 1);
+ QCOMPARE(proxy.index(0, 1, proxyParent).data(), expectedNewVal);
+ QCOMPARE(model->index(1, 0, sourceParent).data(), expectedNewVal);
+ QCOMPARE(columnsRemoveSpy.count(), 1);
+ QCOMPARE(columnsAboutToBeRemoveSpy.count(), 1);
+ QCOMPARE(rowsRemoveSpy.count(), 1);
+ QCOMPARE(rowsAboutToBeRemoveSpy.count(), 1);
+ for (const auto &spyArgs : {columnsRemoveSpy.takeFirst(),
+ columnsAboutToBeRemoveSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxyParent);
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ for (const auto &spyArgs : {rowsRemoveSpy.takeFirst(),
+ rowsAboutToBeRemoveSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), sourceParent);
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ delete model;
+}
+
+void tst_QTransposeProxyModel::insertColumnProxy_data()
+{
+ QTest::addColumn<QAbstractItemModel *>("model");
+ QTest::addColumn<bool>("rootItem");
+ QTest::newRow("List") << createListModel(this) << true;
+ QTest::newRow("Table") << createTableModel(this) << true;
+ QTest::newRow("Tree_Root_Item") << createTreeModel(this) << true;
+ QTest::newRow("Tree_Child_Item") << createTreeModel(this) << false;
+}
+
+void tst_QTransposeProxyModel::insertColumnProxy()
+{
+ QFETCH(QAbstractItemModel *, model);
+ QFETCH(bool, rootItem);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ QSignalSpy columnsInsertSpy(&proxy, &QAbstractItemModel::columnsInserted);
+ QVERIFY(columnsInsertSpy.isValid());
+ QSignalSpy columnsAboutToBeInsertSpy(&proxy, &QAbstractItemModel::columnsAboutToBeInserted);
+ QVERIFY(columnsAboutToBeInsertSpy.isValid());
+ QSignalSpy rowsInsertSpy(model, &QAbstractItemModel::rowsInserted);
+ QVERIFY(rowsInsertSpy.isValid());
+ QSignalSpy rowsAboutToBeInsertSpy(model, &QAbstractItemModel::rowsAboutToBeInserted);
+ QVERIFY(rowsAboutToBeInsertSpy.isValid());
+ proxy.setSourceModel(model);
+ const QModelIndex proxyParent = rootItem ? QModelIndex() : proxy.index(0, 1);
+ const QModelIndex sourceParent = proxy.mapToSource(proxyParent);
+ const int oldColCount = proxy.columnCount(proxyParent);
+ const int oldRowCount = model->rowCount(sourceParent);
+ QVERIFY(proxy.insertColumn(1, proxyParent));
+ QCOMPARE(proxy.columnCount(proxyParent), oldColCount + 1);
+ QCOMPARE(model->rowCount(sourceParent), oldRowCount + 1);
+ QVERIFY(proxy.index(0, 1, proxyParent).data().isNull());
+ QVERIFY(model->index(1, 0, sourceParent).data().isNull());
+ QCOMPARE(columnsInsertSpy.count(), 1);
+ QCOMPARE(columnsAboutToBeInsertSpy.count(), 1);
+ QCOMPARE(rowsInsertSpy.count(), 1);
+ QCOMPARE(rowsAboutToBeInsertSpy.count(), 1);
+ for (const auto &spyArgs : {columnsInsertSpy.takeFirst(),
+ columnsAboutToBeInsertSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxyParent);
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ for (const auto &spyArgs : {rowsInsertSpy.takeFirst(),
+ rowsAboutToBeInsertSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), sourceParent);
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ delete model;
+}
+
+void tst_QTransposeProxyModel::removeRowProxy_data()
+{
+ QTest::addColumn<QAbstractItemModel *>("model");
+ QTest::addColumn<bool>("rootItem");
+ QTest::newRow("Table") << createTableModel(this) << true;
+ QTest::newRow("Tree_Root_Item") << createTreeModel(this) << true;
+ QTest::newRow("Tree_Child_Item") << createTreeModel(this) << false;
+}
+
+void tst_QTransposeProxyModel::removeRowProxy()
+{
+ QFETCH(QAbstractItemModel *, model);
+ QFETCH(bool, rootItem);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ QSignalSpy rowsRemoveSpy(&proxy, &QAbstractItemModel::rowsRemoved);
+ QVERIFY(rowsRemoveSpy.isValid());
+ QSignalSpy rowsAboutToBeRemoveSpy(&proxy, &QAbstractItemModel::rowsAboutToBeRemoved);
+ QVERIFY(rowsAboutToBeRemoveSpy.isValid());
+ QSignalSpy columnsRemoveSpy(model, &QAbstractItemModel::columnsRemoved);
+ QVERIFY(columnsRemoveSpy.isValid());
+ QSignalSpy columnsAboutToBeRemoveSpy(model, &QAbstractItemModel::columnsAboutToBeRemoved);
+ QVERIFY(columnsAboutToBeRemoveSpy.isValid());
+ proxy.setSourceModel(model);
+ const QModelIndex proxyParent = rootItem ? QModelIndex() : proxy.index(0, 1);
+ const QModelIndex sourceParent = proxy.mapToSource(proxyParent);
+ const int oldRowCount = proxy.rowCount(proxyParent);
+ const int oldColCount = model->columnCount(sourceParent);
+ const QVariant expectedNewVal = proxy.index(2, 0, proxyParent).data();
+ QVERIFY(proxy.removeRow(1, proxyParent));
+ QCOMPARE(proxy.rowCount(proxyParent), oldRowCount - 1);
+ QCOMPARE(model->columnCount(sourceParent), oldColCount - 1);
+ QCOMPARE(proxy.index(1, 0, proxyParent).data(), expectedNewVal);
+ QCOMPARE(model->index(0, 1, sourceParent).data(), expectedNewVal);
+ QCOMPARE(columnsRemoveSpy.count(), 1);
+ QCOMPARE(columnsAboutToBeRemoveSpy.count(), 1);
+ QCOMPARE(rowsRemoveSpy.count(), 1);
+ QCOMPARE(rowsAboutToBeRemoveSpy.count(), 1);
+ for (const auto &spyArgs : {columnsRemoveSpy.takeFirst(),
+ columnsAboutToBeRemoveSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), sourceParent);
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ for (const auto &spyArgs : {rowsRemoveSpy.takeFirst(),
+ rowsAboutToBeRemoveSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxyParent);
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ delete model;
+}
+
+void tst_QTransposeProxyModel::insertRowProxy_data()
+{
+ QTest::addColumn<QAbstractItemModel *>("model");
+ QTest::addColumn<bool>("rootItem");
+ QTest::newRow("Table") << createTableModel(this) << true;
+ QTest::newRow("Tree_Root_Item") << createTreeModel(this) << true;
+ QTest::newRow("Tree_Child_Item") << createTreeModel(this) << false;
+}
+
+void tst_QTransposeProxyModel::insertRowProxy()
+{
+ QFETCH(QAbstractItemModel *, model);
+ QFETCH(bool, rootItem);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ QSignalSpy rowsInsertSpy(&proxy, &QAbstractItemModel::rowsInserted);
+ QVERIFY(rowsInsertSpy.isValid());
+ QSignalSpy rowsAboutToBeInsertSpy(&proxy, &QAbstractItemModel::rowsAboutToBeInserted);
+ QVERIFY(rowsAboutToBeInsertSpy.isValid());
+ QSignalSpy columnsInsertSpy(model, &QAbstractItemModel::columnsInserted);
+ QVERIFY(columnsInsertSpy.isValid());
+ QSignalSpy columnsAboutToBeInsertSpy(model, &QAbstractItemModel::columnsAboutToBeInserted);
+ QVERIFY(columnsAboutToBeInsertSpy.isValid());
+ proxy.setSourceModel(model);
+ const QModelIndex proxyParent = rootItem ? QModelIndex() : proxy.index(0, 1);
+ const QModelIndex sourceParent = proxy.mapToSource(proxyParent);
+ const int oldRowCount = proxy.rowCount(proxyParent);
+ const int oldColCount = model->columnCount(sourceParent);
+ QVERIFY(proxy.insertRow(1, proxyParent));
+ QCOMPARE(proxy.rowCount(proxyParent), oldRowCount + 1);
+ QCOMPARE(model->columnCount(sourceParent), oldColCount + 1);
+ QVERIFY(proxy.index(1, 0, proxyParent).data().isNull());
+ QVERIFY(model->index(0, 1, sourceParent).data().isNull());
+ QCOMPARE(columnsInsertSpy.count(), 1);
+ QCOMPARE(columnsAboutToBeInsertSpy.count(), 1);
+ QCOMPARE(rowsInsertSpy.count(), 1);
+ QCOMPARE(rowsAboutToBeInsertSpy.count(), 1);
+ for (const auto &spyArgs : {columnsInsertSpy.takeFirst(),
+ columnsAboutToBeInsertSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), sourceParent);
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ for (const auto &spyArgs : {rowsInsertSpy.takeFirst(),
+ rowsAboutToBeInsertSpy.takeFirst()}) {
+ QCOMPARE(spyArgs.at(0).value<QModelIndex>(), proxyParent);
+ QCOMPARE(spyArgs.at(1).toInt(), 1);
+ QCOMPARE(spyArgs.at(2).toInt(), 1);
+ }
+ delete model;
+}
+
+void tst_QTransposeProxyModel::headerData()
+{
+ QStandardItemModel model;
+ model.insertRows(0, 3);
+ model.insertColumns(0, 5);
+ for (int i = 0; i < model.rowCount(); ++i)
+ model.setHeaderData(i, Qt::Horizontal, QChar('A' + i));
+ for (int i = 1; i <= model.columnCount(); ++i)
+ model.setHeaderData(i, Qt::Vertical, i);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(&model);
+ for (int i = 0; i < model.rowCount(); ++i)
+ QCOMPARE(model.headerData(i, Qt::Horizontal), proxy.headerData(i, Qt::Vertical));
+ for (int i = 0; i < model.columnCount(); ++i)
+ QCOMPARE(model.headerData(i, Qt::Vertical), proxy.headerData(i, Qt::Horizontal));
+}
+
+void tst_QTransposeProxyModel::setHeaderData()
+{
+ QStandardItemModel model;
+ model.insertRows(0, 3);
+ model.insertColumns(0, 5);
+ for (int i = 0; i < model.rowCount(); ++i)
+ model.setHeaderData(i, Qt::Horizontal, QChar('A' + i));
+ for (int i = 1; i <= model.columnCount(); ++i)
+ model.setHeaderData(i, Qt::Vertical, i);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(&model);
+ QVERIFY(proxy.setHeaderData(1, Qt::Horizontal, 99));
+ QCOMPARE(model.headerData(1, Qt::Vertical).toInt(), 99);
+ QVERIFY(proxy.setHeaderData(1, Qt::Vertical, QChar('Z')));
+ QCOMPARE(model.headerData(1, Qt::Horizontal).toChar(), QChar('Z'));
+}
+
+void tst_QTransposeProxyModel::span()
+{
+ class SpanModel : public QStandardItemModel
+ {
+ Q_DISABLE_COPY(SpanModel)
+ public:
+ SpanModel(int rows, int columns, QObject *parent = nullptr)
+ : QStandardItemModel(rows, columns, parent)
+ {}
+ QSize span(const QModelIndex &index) const override
+ {
+ Q_UNUSED(index)
+ return QSize(2, 1);
+ }
+ };
+ SpanModel model(3, 5);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(&model);
+ QCOMPARE(proxy.span(proxy.index(0, 0)), QSize(1, 2));
+}
+
+void tst_QTransposeProxyModel::itemData()
+{
+ QAbstractItemModel *model = createTreeModel(this);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ QMap<int, QVariant> itmData = proxy.itemData(proxy.index(0, 1));
+ QCOMPARE(itmData.value(Qt::DisplayRole).toString(), QStringLiteral("1,0"));
+ QCOMPARE(itmData.value(Qt::UserRole).toInt(), 1);
+ QCOMPARE(itmData.value(Qt::UserRole + 1).toInt(), 0);
+ itmData = proxy.itemData(proxy.index(1, 2, proxy.index(0, 1)));
+ QCOMPARE(itmData.value(Qt::DisplayRole).toString(), QStringLiteral("1,0,2,1"));
+ QCOMPARE(itmData.value(Qt::UserRole).toInt(), 1);
+ QCOMPARE(itmData.value(Qt::UserRole + 1).toInt(), 0);
+ QCOMPARE(itmData.value(Qt::UserRole + 2).toInt(), 2);
+ QCOMPARE(itmData.value(Qt::UserRole + 3).toInt(), 1);
+ QVERIFY(proxy.itemData(QModelIndex()).isEmpty());
+ delete model;
+}
+
+void tst_QTransposeProxyModel::setItemData()
+{
+ QAbstractItemModel *model = createTreeModel(this);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ QSignalSpy sourceDataChangeSpy(model, &QAbstractItemModel::dataChanged);
+ QVERIFY(sourceDataChangeSpy.isValid());
+ QSignalSpy proxyDataChangeSpy(&proxy, &QAbstractItemModel::dataChanged);
+ QVERIFY(proxyDataChangeSpy.isValid());
+ const QMap<int, QVariant> itmData = {
+ std::make_pair<int, QVariant>(Qt::DisplayRole, QStringLiteral("Test")),
+ std::make_pair<int, QVariant>(Qt::UserRole, 88),
+ std::make_pair<int, QVariant>(Qt::UserRole + 1, 99),
+ };
+ QModelIndex idx = proxy.index(0, 1);
+ QVERIFY(proxy.setItemData(idx, itmData));
+ QCOMPARE(idx.data(Qt::DisplayRole).toString(), QStringLiteral("Test"));
+ QCOMPARE(idx.data(Qt::UserRole).toInt(), 88);
+ QCOMPARE(idx.data(Qt::UserRole + 1).toInt(), 99);
+ QCOMPARE(sourceDataChangeSpy.size(), 1);
+ QCOMPARE(proxyDataChangeSpy.size(), 1);
+ auto signalData = proxyDataChangeSpy.takeFirst();
+ QCOMPARE(signalData.at(0).value<QModelIndex>(), idx);
+ QCOMPARE(signalData.at(1).value<QModelIndex>(), idx);
+ const QVector<int> expectedRoles{Qt::DisplayRole, Qt::UserRole, Qt::EditRole, Qt::UserRole + 1};
+ QVector<int> receivedRoles = signalData.at(2).value<QVector<int> >();
+ QCOMPARE(receivedRoles.size(), expectedRoles.size());
+ for (int role : expectedRoles)
+ QVERIFY(receivedRoles.contains(role));
+ signalData = sourceDataChangeSpy.takeFirst();
+ QCOMPARE(signalData.at(0).value<QModelIndex>(), proxy.mapToSource(idx));
+ QCOMPARE(signalData.at(1).value<QModelIndex>(), proxy.mapToSource(idx));
+ receivedRoles = signalData.at(2).value<QVector<int> >();
+ QCOMPARE(receivedRoles.size(), expectedRoles.size());
+ for (int role : expectedRoles)
+ QVERIFY(receivedRoles.contains(role));
+ idx = proxy.index(1, 2, proxy.index(0, 1));
+ QVERIFY(proxy.setItemData(idx, itmData));
+ QCOMPARE(idx.data(Qt::DisplayRole).toString(), QStringLiteral("Test"));
+ QCOMPARE(idx.data(Qt::UserRole).toInt(), 88);
+ QCOMPARE(idx.data(Qt::UserRole + 1).toInt(), 99);
+ QCOMPARE(idx.data(Qt::UserRole + 2).toInt(), 2);
+ QCOMPARE(idx.data(Qt::UserRole + 3).toInt(), 1);
+ QCOMPARE(sourceDataChangeSpy.size(), 1);
+ QCOMPARE(proxyDataChangeSpy.size(), 1);
+ signalData = proxyDataChangeSpy.takeFirst();
+ QCOMPARE(signalData.at(0).value<QModelIndex>(), idx);
+ QCOMPARE(signalData.at(1).value<QModelIndex>(), idx);
+ receivedRoles = signalData.at(2).value<QVector<int> >();
+ QCOMPARE(receivedRoles.size(), expectedRoles.size());
+ for (int role : expectedRoles)
+ QVERIFY(receivedRoles.contains(role));
+ signalData = sourceDataChangeSpy.takeFirst();
+ QCOMPARE(signalData.at(0).value<QModelIndex>(), proxy.mapToSource(idx));
+ QCOMPARE(signalData.at(1).value<QModelIndex>(), proxy.mapToSource(idx));
+ receivedRoles = signalData.at(2).value<QVector<int> >();
+ QCOMPARE(receivedRoles.size(), expectedRoles.size());
+ for (int role : expectedRoles)
+ QVERIFY(receivedRoles.contains(role));
+ QVERIFY(!proxy.setItemData(QModelIndex(), itmData));
+ delete model;
+}
+
+void tst_QTransposeProxyModel::moveRowsBase()
+{
+ QStringListModel model{QStringList{"A", "B", "C", "D"}};
+ QTransposeProxyModel proxy;
+ QSignalSpy columnsMoveSpy(&proxy, &QAbstractItemModel::columnsMoved);
+ QVERIFY(columnsMoveSpy.isValid());
+ QSignalSpy columnsAboutToBeMoveSpy(&proxy, &QAbstractItemModel::columnsAboutToBeMoved);
+ QVERIFY(columnsAboutToBeMoveSpy.isValid());
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(&model);
+ const QStringList expectedNewVal = {"B", "A", "C", "D"};
+ QVERIFY(model.moveRows(QModelIndex(), 0, 1, QModelIndex(), 2));
+ for (int i = 0; i < expectedNewVal.size(); ++i)
+ QCOMPARE(proxy.index(0, i).data(), expectedNewVal.at(i));
+ QCOMPARE(columnsMoveSpy.count(), 1);
+ QCOMPARE(columnsAboutToBeMoveSpy.count(), 1);
+ for (const auto &spyArgs : {columnsMoveSpy.takeFirst(),
+ columnsAboutToBeMoveSpy.takeFirst()}) {
+ QVERIFY(!spyArgs.at(0).value<QModelIndex>().isValid());
+ QCOMPARE(spyArgs.at(1).toInt(), 0);
+ QCOMPARE(spyArgs.at(2).toInt(), 0);
+ QVERIFY(!spyArgs.at(3).value<QModelIndex>().isValid());
+ QCOMPARE(spyArgs.at(4).toInt(), 2);
+ }
+}
+
+void tst_QTransposeProxyModel::moveColumnsProxy()
+{
+ QStringListModel model{QStringList{"A", "B", "C", "D"}};
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ QSignalSpy columnsMoveSpy(&proxy, &QAbstractItemModel::columnsMoved);
+ QVERIFY(columnsMoveSpy.isValid());
+ QSignalSpy columnsAboutToBeMoveSpy(&proxy, &QAbstractItemModel::columnsAboutToBeMoved);
+ QVERIFY(columnsAboutToBeMoveSpy.isValid());
+ QSignalSpy rowsMoveSpy(&model, &QAbstractItemModel::rowsMoved);
+ QVERIFY(rowsMoveSpy.isValid());
+ QSignalSpy rowsAboutToBeMoveSpy(&model, &QAbstractItemModel::rowsAboutToBeMoved);
+ QVERIFY(rowsAboutToBeMoveSpy.isValid());
+ proxy.setSourceModel(&model);
+ const QStringList expectedNewVal = {"B", "A", "C", "D"};
+ QVERIFY(proxy.moveColumns(QModelIndex(), 0, 1, QModelIndex(), 2));
+ for (int i = 0; i < expectedNewVal.size(); ++i)
+ QCOMPARE(proxy.index(0, i).data(), expectedNewVal.at(i));
+ for (int i = 0; i < expectedNewVal.size(); ++i)
+ QCOMPARE(model.index(i, 0).data(), expectedNewVal.at(i));
+ QCOMPARE(columnsMoveSpy.count(), 1);
+ QCOMPARE(columnsAboutToBeMoveSpy.count(), 1);
+ QCOMPARE(rowsMoveSpy.count(), 1);
+ QCOMPARE(rowsAboutToBeMoveSpy.count(), 1);
+ for (const auto &spyArgs : {columnsMoveSpy.takeFirst(),
+ columnsAboutToBeMoveSpy.takeFirst(),
+ rowsMoveSpy.takeFirst(),rowsAboutToBeMoveSpy.takeFirst()}) {
+ QVERIFY(!spyArgs.at(0).value<QModelIndex>().isValid());
+ QCOMPARE(spyArgs.at(1).toInt(), 0);
+ QCOMPARE(spyArgs.at(2).toInt(), 0);
+ QVERIFY(!spyArgs.at(3).value<QModelIndex>().isValid());
+ }
+}
+
+void tst_QTransposeProxyModel::setData_data()
+{
+ QTest::addColumn<QAbstractItemModel *>("model");
+ QTest::addColumn<bool>("rootItem");
+ QTest::addColumn<bool>("viaProxy");
+ QTest::newRow("List_via_Base") << createListModel(this) << true << false;
+ QTest::newRow("Table_via_Base") << createTableModel(this) << true << false;
+ QTest::newRow("Tree_via_Base_Root_Item") << createTreeModel(this) << true << false;
+ QTest::newRow("Tree_via_Base_Child_Item") << createTreeModel(this) << false << false;
+ QTest::newRow("List_via_Proxy") << createListModel(this) << true << true;
+ QTest::newRow("Table_via_Proxy") << createTableModel(this) << true << true;
+ QTest::newRow("Tree_via_Proxy_Root_Item") << createTreeModel(this) << true << true;
+ QTest::newRow("Tree_via_Proxy_Child_Item") << createTreeModel(this) << false << true;
+}
+
+void tst_QTransposeProxyModel::setData()
+{
+ QFETCH(QAbstractItemModel *, model);
+ QFETCH(bool, rootItem);
+ QFETCH(bool, viaProxy);
+ QTransposeProxyModel proxy;
+ new QAbstractItemModelTester(&proxy, &proxy);
+ proxy.setSourceModel(model);
+ QSignalSpy sourceDataChangeSpy(model, &QAbstractItemModel::dataChanged);
+ QVERIFY(sourceDataChangeSpy.isValid());
+ QSignalSpy proxyDataChangeSpy(&proxy, &QAbstractItemModel::dataChanged);
+ QVERIFY(proxyDataChangeSpy.isValid());
+ const QString testData = QStringLiteral("TestingSetData");
+ if (viaProxy) {
+ const QModelIndex parIdx = rootItem ? QModelIndex() : proxy.index(0, 1);
+ QVERIFY(proxy.setData(proxy.index(0, 1, parIdx), testData));
+ QCOMPARE(model->index(1, 0, proxy.mapToSource(parIdx)).data().toString(), testData);
+ } else {
+ const QModelIndex parIdx = rootItem ? QModelIndex() : model->index(1, 0);
+ QVERIFY(model->setData(model->index(1, 0, parIdx), testData));
+ QCOMPARE(proxy.index(0, 1, proxy.mapFromSource(parIdx)).data().toString(), testData);
+ }
+ QCOMPARE(sourceDataChangeSpy.size(), 1);
+ QCOMPARE(proxyDataChangeSpy.size(), 1);
+ delete model;
+}
+
+QTEST_GUILESS_MAIN(tst_QTransposeProxyModel)
+
+#include "tst_qtransposeproxymodel.moc"
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
index 6adb393ddd..39c90f69b4 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
@@ -611,7 +611,7 @@ void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents()
TestApplication app(argc, argv);
ProcessEventsAlwaysSendsPostedEventsObject object;
- QTime t;
+ QElapsedTimer t;
t.start();
int i = 1;
do {
@@ -775,49 +775,49 @@ private slots:
QCoreApplicationPrivate *privateClass = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
{
- QCOMPARE(privateClass->quitLockRef.load(), 0);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 0);
// Test with a lock active so that the refcount doesn't drop to zero during these tests, causing a quit.
// (until we exit the scope)
QEventLoopLocker locker;
- QCOMPARE(privateClass->quitLockRef.load(), 1);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
JobObject *job1 = new JobObject(this);
- QCOMPARE(privateClass->quitLockRef.load(), 2);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 2);
delete job1;
- QCOMPARE(privateClass->quitLockRef.load(), 1);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
job1 = new JobObject(this);
- QCOMPARE(privateClass->quitLockRef.load(), 2);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 2);
JobObject *job2 = new JobObject(this);
- QCOMPARE(privateClass->quitLockRef.load(), 3);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 3);
delete job1;
- QCOMPARE(privateClass->quitLockRef.load(), 2);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 2);
JobObject *job3 = new JobObject(job2);
Q_UNUSED(job3);
- QCOMPARE(privateClass->quitLockRef.load(), 3);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 3);
JobObject *job4 = new JobObject(job2);
Q_UNUSED(job4);
- QCOMPARE(privateClass->quitLockRef.load(), 4);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 4);
delete job2;
- QCOMPARE(privateClass->quitLockRef.load(), 1);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
}
- QCOMPARE(privateClass->quitLockRef.load(), 0);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 0);
}
};
diff --git a/tests/auto/corelib/kernel/qeventloop/qeventloop.pro b/tests/auto/corelib/kernel/qeventloop/qeventloop.pro
index 295a42aa9c..159761c0c6 100644
--- a/tests/auto/corelib/kernel/qeventloop/qeventloop.pro
+++ b/tests/auto/corelib/kernel/qeventloop/qeventloop.pro
@@ -3,6 +3,6 @@ TARGET = tst_qeventloop
QT = core network testlib core-private
SOURCES = $$PWD/tst_qeventloop.cpp
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
qtConfig(glib): DEFINES += HAVE_GLIB
diff --git a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
index 482ed8d130..1f0b8d4b4e 100644
--- a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
+++ b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
@@ -638,16 +638,16 @@ void tst_QEventLoop::testQuitLock()
QEventLoopPrivate* privateClass = static_cast<QEventLoopPrivate*>(QObjectPrivate::get(&eventLoop));
- QCOMPARE(privateClass->quitLockRef.load(), 0);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 0);
JobObject *job1 = new JobObject(&eventLoop, this);
job1->start(500);
- QCOMPARE(privateClass->quitLockRef.load(), 1);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
eventLoop.exec();
- QCOMPARE(privateClass->quitLockRef.load(), 0);
+ QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 0);
job1 = new JobObject(&eventLoop, this);
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
index ac0731b883..89a06b358e 100644
--- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
+++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
@@ -331,6 +331,7 @@ private slots:
void signal();
void signalIndex_data();
void signalIndex();
+ void enumDebugStream_data();
void enumDebugStream();
void inherits_data();
@@ -1772,37 +1773,104 @@ void tst_QMetaObject::signalIndex()
SignalTestHelper::signalIndex(mm));
}
+void tst_QMetaObject::enumDebugStream_data()
+{
+ QTest::addColumn<int>("verbosity");
+ QTest::addColumn<QString>("normalEnumMsg");
+ QTest::addColumn<QString>("scopedEnumMsg");
+ QTest::addColumn<QString>("globalEnumMsg");
+ QTest::addColumn<QString>("normalFlagMsg");
+ QTest::addColumn<QString>("normalFlagsMsg");
+ QTest::addColumn<QString>("scopedFlagMsg");
+ QTest::addColumn<QString>("scopedFlagsMsg");
+ QTest::addColumn<QString>("flagAsEnumMsg");
+
+ QTest::newRow("verbosity=0") << 0
+ << "hello MyEnum2 world"
+ << "hello MyScopedEnum::Enum3 scoped world"
+ << "WindowTitleHint Window Desktop WindowSystemMenuHint"
+ << "hello MyFlag1 world"
+ << "MyFlag1 MyFlag2|MyFlag3"
+ << "MyScopedFlag(MyFlag2)"
+ << "MyScopedFlag(MyFlag2|MyFlag3)"
+ << "MyFlag1";
+
+ QTest::newRow("verbosity=1") << 1
+ << "hello MyEnum::MyEnum2 world"
+ << "hello MyScopedEnum::Enum3 scoped world"
+ << "WindowType::WindowTitleHint WindowType::Window WindowType::Desktop WindowType::WindowSystemMenuHint"
+ << "hello MyFlag(MyFlag1) world"
+ << "MyFlag(MyFlag1) MyFlag(MyFlag2|MyFlag3)"
+ << "MyScopedFlag(MyFlag2)"
+ << "MyScopedFlag(MyFlag2|MyFlag3)"
+ << "MyFlag::MyFlag1";
+
+ QTest::newRow("verbosity=2") << 2
+ << "hello MyNamespace::MyClass::MyEnum2 world"
+ << "hello MyNamespace::MyClass::MyScopedEnum::Enum3 scoped world"
+ << "Qt::WindowTitleHint Qt::Window Qt::Desktop Qt::WindowSystemMenuHint"
+ << "hello QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) world"
+ << "QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)"
+ << "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)"
+ << "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3)"
+ << "MyNamespace::MyClass::MyFlag1";
+
+ QTest::newRow("verbosity=3") << 3
+ << "hello MyNamespace::MyClass::MyEnum::MyEnum2 world"
+ << "hello MyNamespace::MyClass::MyScopedEnum::Enum3 scoped world"
+ << "Qt::WindowType::WindowTitleHint Qt::WindowType::Window Qt::WindowType::Desktop Qt::WindowType::WindowSystemMenuHint"
+ << "hello QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) world"
+ << "QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)"
+ << "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)"
+ << "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3)"
+ << "MyNamespace::MyClass::MyFlag::MyFlag1";
+}
+
void tst_QMetaObject::enumDebugStream()
{
- QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyEnum2 world ");
- qDebug() << "hello" << MyNamespace::MyClass::MyEnum2 << "world";
+ QFETCH(int, verbosity);
+
+ QFETCH(QString, normalEnumMsg);
+ QFETCH(QString, scopedEnumMsg);
+ QFETCH(QString, globalEnumMsg);
+
+ QFETCH(QString, normalFlagMsg);
+ QFETCH(QString, normalFlagsMsg);
+ QFETCH(QString, scopedFlagMsg);
+ QFETCH(QString, scopedFlagsMsg);
+ QFETCH(QString, flagAsEnumMsg);
+
+ // Enums
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(normalEnumMsg));
+ qDebug().verbosity(verbosity) << "hello" << MyNamespace::MyClass::MyEnum2 << "world";
- QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyScopedEnum::Enum3 scoped world ");
- qDebug() << "hello" << MyNamespace::MyClass::MyScopedEnum::Enum3 << "scoped world";
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(scopedEnumMsg));
+ qDebug().verbosity(verbosity) << "hello" << MyNamespace::MyClass::MyScopedEnum::Enum3 << "scoped world";
- QTest::ignoreMessage(QtDebugMsg, "Qt::WindowTitleHint Qt::Window Qt::Desktop Qt::WindowSystemMenuHint");
- qDebug() << Qt::WindowTitleHint << Qt::Window << Qt::Desktop << Qt::WindowSystemMenuHint;
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(globalEnumMsg));
+ qDebug().verbosity(verbosity) << Qt::WindowTitleHint << Qt::Window << Qt::Desktop << Qt::WindowSystemMenuHint;
- QTest::ignoreMessage(QtDebugMsg, "hello QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) world");
+ // Flags
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(normalFlagMsg));
MyNamespace::MyClass::MyFlags f1 = MyNamespace::MyClass::MyFlag1;
- qDebug() << "hello" << f1 << "world";
+ qDebug().verbosity(verbosity) << "hello" << f1 << "world";
MyNamespace::MyClass::MyFlags f2 = MyNamespace::MyClass::MyFlag2 | MyNamespace::MyClass::MyFlag3;
- QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)");
- qDebug() << f1 << f2;
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(normalFlagsMsg));
+ qDebug().verbosity(verbosity) << f1 << f2;
- QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)");
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(scopedFlagMsg));
MyNamespace::MyClass::MyScopedFlags f3 = MyNamespace::MyClass::MyScopedFlag::MyFlag2;
- qDebug() << f3;
+ qDebug().verbosity(verbosity) << f3;
- QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3)");
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(scopedFlagsMsg));
f3 |= MyNamespace::MyClass::MyScopedFlag::MyFlag3;
- qDebug() << f3;
+ qDebug().verbosity(verbosity) << f3;
// Single flag recognized as enum:
- QTest::ignoreMessage(QtDebugMsg, "MyNamespace::MyClass::MyFlag1");
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(flagAsEnumMsg));
MyNamespace::MyClass::MyFlag f4 = MyNamespace::MyClass::MyFlag1;
- qDebug() << f4;
+ qDebug().verbosity(verbosity) << f4;
}
void tst_QMetaObject::inherits_data()
diff --git a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
index 681a5d0146..cc67fc7884 100644
--- a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
+++ b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
@@ -130,7 +130,7 @@ public:
QString m_value;
void setValue(const QString &value) { m_value = value; }
QString getValue() { return m_value; }
- void resetValue() { m_value = QLatin1Literal("reset"); }
+ void resetValue() { m_value = QLatin1String("reset"); }
};
void tst_QMetaProperty::gadget()
@@ -140,7 +140,7 @@ void tst_QMetaProperty::gadget()
QVERIFY(valueProp.isValid());
{
MyGadget g;
- QString hello = QLatin1Literal("hello");
+ QString hello = QLatin1String("hello");
QVERIFY(valueProp.writeOnGadget(&g, hello));
QCOMPARE(g.m_value, QLatin1String("hello"));
QCOMPARE(valueProp.readOnGadget(&g), QVariant(hello));
@@ -242,7 +242,7 @@ void tst_QMetaProperty::conversion()
QCOMPARE(custom.str, QString());
// or reset resetable
QVERIFY(value7P.write(this, QVariant()));
- QCOMPARE(value7, QLatin1Literal("reset"));
+ QCOMPARE(value7, QLatin1String("reset"));
}
QTEST_MAIN(tst_QMetaProperty)
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index e6fac74ccc..28458c43c7 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -73,6 +73,7 @@ private slots:
void defined();
void threadSafety();
void namespaces();
+ void id();
void qMetaTypeId();
void properties();
void normalizedTypes();
@@ -342,6 +343,7 @@ struct Bar
++failureCount;
}
}
+ ~Bar() {}
public:
static int failureCount;
@@ -458,7 +460,7 @@ void tst_QMetaType::threadSafety()
namespace TestSpace
{
- struct Foo { double d; };
+ struct Foo { double d; public: ~Foo() {} };
struct QungTfu {};
}
Q_DECLARE_METATYPE(TestSpace::Foo)
@@ -476,6 +478,12 @@ void tst_QMetaType::namespaces()
QCOMPARE(QMetaType::typeName(qungTfuId), "TestSpace::QungTfu");
}
+void tst_QMetaType::id()
+{
+ QCOMPARE(QMetaType(QMetaType::QString).id(), QMetaType::QString);
+ QCOMPARE(QMetaType(::qMetaTypeId<TestSpace::Foo>()).id(), ::qMetaTypeId<TestSpace::Foo>());
+}
+
void tst_QMetaType::qMetaTypeId()
{
QCOMPARE(::qMetaTypeId<QString>(), int(QMetaType::QString));
@@ -509,11 +517,17 @@ void tst_QMetaType::properties()
}
template <typename T>
-struct Whity { T t; };
+struct Whity { T t; Whity() {} };
Q_DECLARE_METATYPE( Whity < int > )
Q_DECLARE_METATYPE(Whity<double>)
+#if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(Whity<double>, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
+#endif
+
void tst_QMetaType::normalizedTypes()
{
int WhityIntId = ::qMetaTypeId<Whity<int> >();
@@ -812,10 +826,13 @@ void tst_QMetaType::sizeOfStaticLess()
QCOMPARE(size_t(QMetaType(type).sizeOf()), size);
}
-struct CustomMovable {};
+struct CustomMovable { CustomMovable() {} };
+#if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(CustomMovable, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
+#endif
+
Q_DECLARE_METATYPE(CustomMovable);
class CustomObject : public QObject
@@ -844,13 +861,15 @@ public:
};
Q_DECLARE_METATYPE(CustomMultiInheritanceObject*);
-class C { char _[4]; };
-class M { char _[4]; };
+class C { char _[4]; public: C() = default; C(const C&) {} };
+class M { char _[4]; public: M() {} };
class P { char _[4]; };
QT_BEGIN_NAMESPACE
+#if defined(Q_CC_GNU) && Q_CC_GNU < 501
Q_DECLARE_TYPEINFO(M, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(P, Q_PRIMITIVE_TYPE);
+#endif
QT_END_NAMESPACE
// avoid the comma:
@@ -896,7 +915,7 @@ QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(ADD_METATYPE_TEST_ROW)
QT_FOR_EACH_STATIC_CORE_POINTER(ADD_METATYPE_TEST_ROW)
#undef ADD_METATYPE_TEST_ROW
QTest::newRow("TestSpace::Foo") << ::qMetaTypeId<TestSpace::Foo>() << false << true << false << false;
- QTest::newRow("Whity<double>") << ::qMetaTypeId<Whity<double> >() << false << true << false << false;
+ QTest::newRow("Whity<double>") << ::qMetaTypeId<Whity<double> >() << true << true << false << false;
QTest::newRow("CustomMovable") << ::qMetaTypeId<CustomMovable>() << true << true << false << false;
QTest::newRow("CustomObject*") << ::qMetaTypeId<CustomObject*>() << true << false << true << false;
QTest::newRow("CustomMultiInheritanceObject*") << ::qMetaTypeId<CustomMultiInheritanceObject*>() << true << false << true << false;
@@ -1480,7 +1499,7 @@ public:
typedef MyObject* MyObjectPtr;
Q_DECLARE_METATYPE(MyObjectPtr)
-#if defined(Q_COMPILER_VARIADIC_MACROS) && !defined(TST_QMETATYPE_BROKEN_COMPILER)
+#if !defined(TST_QMETATYPE_BROKEN_COMPILER)
static QByteArray createTypeName(const char *begin, const char *va)
{
QByteArray tn(begin);
@@ -1678,7 +1697,7 @@ void tst_QMetaType::automaticTemplateRegistration()
QVERIFY(qRegisterMetaType<UnregisteredTypeList>("UnregisteredTypeList") > 0);
}
-#if defined(Q_COMPILER_VARIADIC_MACROS) && !defined(TST_QMETATYPE_BROKEN_COMPILER)
+#if !defined(TST_QMETATYPE_BROKEN_COMPILER)
#define FOR_EACH_STATIC_PRIMITIVE_TYPE(F) \
F(bool) \
@@ -1757,7 +1776,7 @@ void tst_QMetaType::automaticTemplateRegistration()
CREATE_AND_VERIFY_CONTAINER(QHash, void*, void*)
CREATE_AND_VERIFY_CONTAINER(QHash, const void*, const void*)
-#endif // Q_COMPILER_VARIADIC_MACROS
+#endif // !defined(TST_QMETATYPE_BROKEN_COMPILER)
#define TEST_OWNING_SMARTPOINTER(SMARTPOINTER, ELEMENT_TYPE, FLAG_TEST, FROMVARIANTFUNCTION) \
{ \
@@ -1815,13 +1834,6 @@ DECLARE_NONSTREAMABLE(void)
DECLARE_NONSTREAMABLE(void*)
DECLARE_NONSTREAMABLE(QModelIndex)
DECLARE_NONSTREAMABLE(QPersistentModelIndex)
-DECLARE_NONSTREAMABLE(QJsonValue)
-DECLARE_NONSTREAMABLE(QJsonObject)
-DECLARE_NONSTREAMABLE(QJsonArray)
-DECLARE_NONSTREAMABLE(QJsonDocument)
-DECLARE_NONSTREAMABLE(QCborValue)
-DECLARE_NONSTREAMABLE(QCborArray)
-DECLARE_NONSTREAMABLE(QCborMap)
DECLARE_NONSTREAMABLE(QObject*)
DECLARE_NONSTREAMABLE(QWidget*)
@@ -2553,9 +2565,7 @@ Q_DECLARE_METATYPE(UndefinedFunction0);
Q_DECLARE_METATYPE(UndefinedFunction1);
Q_DECLARE_METATYPE(UndefinedFunction2);
Q_DECLARE_METATYPE(UndefinedFunction3);
-#ifdef Q_COMPILER_VARIADIC_TEMPLATES
Q_DECLARE_METATYPE(UndefinedFunction4);
-#endif
QTEST_MAIN(tst_QMetaType)
#include "tst_qmetatype.moc"
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
index 6bda9638f7..22bcb69ac9 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
@@ -236,7 +236,7 @@ template<> struct TestValueFactory<QMetaType::QRegExp> {
template<> struct TestValueFactory<QMetaType::QRegularExpression> {
static QRegularExpression *create()
{
-#ifndef QT_NO_REGEXP
+#if QT_CONFIG(regularexpression)
return new QRegularExpression("abc.*def");
#else
return 0;
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index 06254091cd..7c9d8a476a 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -32,7 +32,6 @@
#include <qcoreapplication.h>
#include <qpointer.h>
#include <qtimer.h>
-#include <qregexp.h>
#include <qregularexpression.h>
#include <qmetaobject.h>
#include <qvariant.h>
@@ -41,6 +40,7 @@
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
+#include <QScopedPointer>
#if QT_CONFIG(process)
# include <QProcess>
#endif
@@ -153,6 +153,8 @@ private slots:
void mutableFunctor();
void checkArgumentsForNarrowing();
void nullReceiver();
+ void functorReferencesConnection();
+ void disconnectDisconnects();
};
struct QObjectCreatedOnShutdown
@@ -285,104 +287,100 @@ static void playWithObjects()
void tst_QObject::disconnect()
{
- SenderObject *s = new SenderObject;
- ReceiverObject *r1 = new ReceiverObject;
- ReceiverObject *r2 = new ReceiverObject;
+ SenderObject s;
+ ReceiverObject r1;
+ ReceiverObject r2;
- connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) );
+ connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()));
- connect( s, SIGNAL(signal2()), r1, SLOT(slot2()) );
- connect( s, SIGNAL(signal3()), r1, SLOT(slot3()) );
- connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) );
+ connect(&s, SIGNAL(signal2()), &r1, SLOT(slot2()));
+ connect(&s, SIGNAL(signal3()), &r1, SLOT(slot3()));
+ connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()));
- s->emitSignal1();
- s->emitSignal2();
- s->emitSignal3();
- s->emitSignal4();
+ s.emitSignal1();
+ s.emitSignal2();
+ s.emitSignal3();
+ s.emitSignal4();
- QVERIFY(r1->called(1));
- QVERIFY(r1->called(2));
- QVERIFY(r1->called(3));
- QVERIFY(r1->called(4));
- r1->reset();
+ QVERIFY(r1.called(1));
+ QVERIFY(r1.called(2));
+ QVERIFY(r1.called(3));
+ QVERIFY(r1.called(4));
+ r1.reset();
// usual disconnect with all parameters given
- bool ret = QObject::disconnect( s, SIGNAL(signal1()), r1, SLOT(slot1()) );
+ bool ret = QObject::disconnect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()));
- s->emitSignal1();
+ s.emitSignal1();
- QVERIFY(!r1->called(1));
- r1->reset();
+ QVERIFY(!r1.called(1));
+ r1.reset();
QVERIFY(ret);
- ret = QObject::disconnect( s, SIGNAL(signal1()), r1, SLOT(slot1()) );
+ ret = QObject::disconnect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()));
QVERIFY(!ret);
// disconnect all signals from s from all slots from r1
- QObject::disconnect( s, 0, r1, 0 );
+ QObject::disconnect(&s, 0, &r1, 0);
- s->emitSignal2();
- s->emitSignal3();
- s->emitSignal4();
+ s.emitSignal2();
+ s.emitSignal3();
+ s.emitSignal4();
- QVERIFY(!r1->called(2));
- QVERIFY(!r1->called(3));
- QVERIFY(!r1->called(4));
- r1->reset();
+ QVERIFY(!r1.called(2));
+ QVERIFY(!r1.called(3));
+ QVERIFY(!r1.called(4));
+ r1.reset();
- connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) );
- connect( s, SIGNAL(signal1()), r1, SLOT(slot2()) );
- connect( s, SIGNAL(signal1()), r1, SLOT(slot3()) );
- connect( s, SIGNAL(signal2()), r1, SLOT(slot4()) );
+ connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()));
+ connect(&s, SIGNAL(signal1()), &r1, SLOT(slot2()));
+ connect(&s, SIGNAL(signal1()), &r1, SLOT(slot3()));
+ connect(&s, SIGNAL(signal2()), &r1, SLOT(slot4()));
// disconnect s's signal1() from all slots of r1
- QObject::disconnect( s, SIGNAL(signal1()), r1, 0 );
+ QObject::disconnect(&s, SIGNAL(signal1()), &r1, 0);
- s->emitSignal1();
- s->emitSignal2();
+ s.emitSignal1();
+ s.emitSignal2();
- QVERIFY(!r1->called(1));
- QVERIFY(!r1->called(2));
- QVERIFY(!r1->called(3));
- QVERIFY(r1->called(4));
- r1->reset();
+ QVERIFY(!r1.called(1));
+ QVERIFY(!r1.called(2));
+ QVERIFY(!r1.called(3));
+ QVERIFY(r1.called(4));
+ r1.reset();
// make sure all is disconnected again
- QObject::disconnect( s, 0, r1, 0 );
+ QObject::disconnect(&s, 0, &r1, 0);
- connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) );
- connect( s, SIGNAL(signal1()), r2, SLOT(slot1()) );
- connect( s, SIGNAL(signal2()), r1, SLOT(slot2()) );
- connect( s, SIGNAL(signal2()), r2, SLOT(slot2()) );
- connect( s, SIGNAL(signal3()), r1, SLOT(slot3()) );
- connect( s, SIGNAL(signal3()), r2, SLOT(slot3()) );
+ connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()));
+ connect(&s, SIGNAL(signal1()), &r2, SLOT(slot1()));
+ connect(&s, SIGNAL(signal2()), &r1, SLOT(slot2()));
+ connect(&s, SIGNAL(signal2()), &r2, SLOT(slot2()));
+ connect(&s, SIGNAL(signal3()), &r1, SLOT(slot3()));
+ connect(&s, SIGNAL(signal3()), &r2, SLOT(slot3()));
// disconnect signal1() from all receivers
- QObject::disconnect( s, SIGNAL(signal1()), 0, 0 );
- s->emitSignal1();
- s->emitSignal2();
- s->emitSignal3();
+ QObject::disconnect(&s, SIGNAL(signal1()), 0, 0);
+ s.emitSignal1();
+ s.emitSignal2();
+ s.emitSignal3();
- QVERIFY(!r1->called(1));
- QVERIFY(!r2->called(1));
- QVERIFY(r1->called(2));
- QVERIFY(r2->called(2));
- QVERIFY(r1->called(2));
- QVERIFY(r2->called(2));
+ QVERIFY(!r1.called(1));
+ QVERIFY(!r2.called(1));
+ QVERIFY(r1.called(2));
+ QVERIFY(r2.called(2));
+ QVERIFY(r1.called(2));
+ QVERIFY(r2.called(2));
- r1->reset();
- r2->reset();
+ r1.reset();
+ r2.reset();
// disconnect all signals of s from all receivers
- QObject::disconnect( s, 0, 0, 0 );
+ QObject::disconnect(&s, 0, 0, 0);
- QVERIFY(!r1->called(2));
- QVERIFY(!r2->called(2));
- QVERIFY(!r1->called(2));
- QVERIFY(!r2->called(2));
-
- delete r2;
- delete r1;
- delete s;
+ QVERIFY(!r1.called(2));
+ QVERIFY(!r2.called(2));
+ QVERIFY(!r1.called(2));
+ QVERIFY(!r2.called(2));
}
class AutoConnectSender : public QObject
@@ -504,14 +502,13 @@ void tst_QObject::connectSlotsByName()
void tst_QObject::qobject_castTemplate()
{
- QObject *o = 0;
- QVERIFY( !::qobject_cast<QObject*>(o) );
+ QScopedPointer<QObject> o;
+ QVERIFY(!::qobject_cast<QObject*>(o.data()));
- o = new SenderObject;
- QVERIFY( ::qobject_cast<SenderObject*>(o) );
- QVERIFY( ::qobject_cast<QObject*>(o) );
- QVERIFY( !::qobject_cast<ReceiverObject*>(o) );
- delete o;
+ o.reset(new SenderObject);
+ QVERIFY(::qobject_cast<SenderObject*>(o.data()));
+ QVERIFY(::qobject_cast<QObject*>(o.data()));
+ QVERIFY(!::qobject_cast<ReceiverObject*>(o.data()));
}
void tst_QObject::findChildren()
@@ -539,91 +536,91 @@ void tst_QObject::findChildren()
QObject *op = 0;
- op = qFindChild<QObject*>(&o, "o1");
+ op = o.findChild<QObject*>("o1");
QCOMPARE(op, &o1);
- op = qFindChild<QObject*>(&o, "o2");
+ op = o.findChild<QObject*>("o2");
QCOMPARE(op, &o2);
- op = qFindChild<QObject*>(&o, "o11");
+ op = o.findChild<QObject*>("o11");
QCOMPARE(op, &o11);
- op = qFindChild<QObject*>(&o, "o12");
+ op = o.findChild<QObject*>("o12");
QCOMPARE(op, &o12);
- op = qFindChild<QObject*>(&o, "o111");
+ op = o.findChild<QObject*>("o111");
QCOMPARE(op, &o111);
- op = qFindChild<QObject*>(&o, "t1");
+ op = o.findChild<QObject*>("t1");
QCOMPARE(op, static_cast<QObject *>(&t1));
- op = qFindChild<QObject*>(&o, "t121");
+ op = o.findChild<QObject*>("t121");
QCOMPARE(op, static_cast<QObject *>(&t121));
- op = qFindChild<QTimer*>(&o, "t1");
+ op = o.findChild<QTimer*>("t1");
QCOMPARE(op, static_cast<QObject *>(&t1));
- op = qFindChild<QTimer*>(&o, "t121");
+ op = o.findChild<QTimer*>("t121");
QCOMPARE(op, static_cast<QObject *>(&t121));
- op = qFindChild<QTimer*>(&o, "o12");
+ op = o.findChild<QTimer*>("o12");
QCOMPARE(op, static_cast<QObject *>(0));
- op = qFindChild<QObject*>(&o, "o");
+ op = o.findChild<QObject*>("o");
QCOMPARE(op, static_cast<QObject *>(0));
- op = qFindChild<QObject*>(&o, "harry");
+ op = o.findChild<QObject*>("harry");
QCOMPARE(op, static_cast<QObject *>(0));
- op = qFindChild<QObject*>(&o, "o1");
+ op = o.findChild<QObject*>("o1");
QCOMPARE(op, &o1);
QList<QObject*> l;
QList<QTimer*> tl;
- l = qFindChildren<QObject*>(&o, "o1");
+ l = o.findChildren<QObject*>("o1");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o1);
- l = qFindChildren<QObject*>(&o, "o2");
+ l = o.findChildren<QObject*>("o2");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o2);
- l = qFindChildren<QObject*>(&o, "o11");
+ l = o.findChildren<QObject*>("o11");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o11);
- l = qFindChildren<QObject*>(&o, "o12");
+ l = o.findChildren<QObject*>("o12");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o12);
- l = qFindChildren<QObject*>(&o, "o111");
+ l = o.findChildren<QObject*>("o111");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o111);
- l = qFindChildren<QObject*>(&o, "t1");
+ l = o.findChildren<QObject*>("t1");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), static_cast<QObject *>(&t1));
- l = qFindChildren<QObject*>(&o, "t121");
+ l = o.findChildren<QObject*>("t121");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), static_cast<QObject *>(&t121));
- tl = qFindChildren<QTimer*>(&o, "t1");
+ tl = o.findChildren<QTimer*>("t1");
QCOMPARE(tl.size(), 1);
QCOMPARE(tl.at(0), &t1);
- tl = qFindChildren<QTimer*>(&o, "t121");
+ tl = o.findChildren<QTimer*>("t121");
QCOMPARE(tl.size(), 1);
QCOMPARE(tl.at(0), &t121);
- l = qFindChildren<QObject*>(&o, "o");
+ l = o.findChildren<QObject*>("o");
QCOMPARE(l.size(), 0);
- l = qFindChildren<QObject*>(&o, "harry");
+ l = o.findChildren<QObject*>("harry");
QCOMPARE(l.size(), 0);
- tl = qFindChildren<QTimer*>(&o, "o12");
+ tl = o.findChildren<QTimer*>("o12");
QCOMPARE(tl.size(), 0);
- l = qFindChildren<QObject*>(&o, "o1");
+ l = o.findChildren<QObject*>("o1");
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o1);
- l = qFindChildren<QObject*>(&o, QRegExp("o.*"));
+ l = o.findChildren<QObject*>(QRegularExpression("^o.*$"));
QCOMPARE(l.size(), 5);
QVERIFY(l.contains(&o1));
QVERIFY(l.contains(&o2));
QVERIFY(l.contains(&o11));
QVERIFY(l.contains(&o12));
QVERIFY(l.contains(&o111));
- l = qFindChildren<QObject*>(&o, QRegExp("t.*"));
+ l = o.findChildren<QObject*>(QRegularExpression("t.*"));
QCOMPARE(l.size(), 2);
QVERIFY(l.contains(&t1));
QVERIFY(l.contains(&t121));
- tl = qFindChildren<QTimer*>(&o, QRegExp(".*"));
+ tl = o.findChildren<QTimer*>(QRegularExpression("^.*$"));
QCOMPARE(tl.size(), 3);
QVERIFY(tl.contains(&t1));
QVERIFY(tl.contains(&t121));
- tl = qFindChildren<QTimer*>(&o, QRegExp("o.*"));
+ tl = o.findChildren<QTimer*>(QRegularExpression("^o.*$"));
QCOMPARE(tl.size(), 0);
- l = qFindChildren<QObject*>(&o, QRegExp("harry"));
+ l = o.findChildren<QObject*>(QRegularExpression("^harry$"));
QCOMPARE(l.size(), 0);
l = o.findChildren<QObject*>(QRegularExpression("o.*"));
@@ -647,18 +644,18 @@ void tst_QObject::findChildren()
QCOMPARE(l.size(), 0);
// empty and null string check
- op = qFindChild<QObject*>(&o);
+ op = o.findChild<QObject*>();
QCOMPARE(op, &o1);
- op = qFindChild<QObject*>(&o, "");
+ op = o.findChild<QObject*>("");
QCOMPARE(op, &unnamed);
- op = qFindChild<QObject*>(&o, "unnamed");
+ op = o.findChild<QObject*>("unnamed");
QCOMPARE(op, static_cast<QObject *>(0));
- l = qFindChildren<QObject*>(&o);
+ l = o.findChildren<QObject*>();
QCOMPARE(l.size(), 9);
- l = qFindChildren<QObject*>(&o, "");
+ l = o.findChildren<QObject*>("");
QCOMPARE(l.size(), 2);
- l = qFindChildren<QObject*>(&o, "unnamed");
+ l = o.findChildren<QObject*>("unnamed");
QCOMPARE(l.size(), 0);
tl = o.findChildren<QTimer *>("t1");
@@ -726,19 +723,19 @@ void tst_QObject::findChildren()
QCOMPARE(l.size(), 1);
QCOMPARE(l.at(0), &o1);
- l = o.findChildren<QObject*>(QRegExp("o.*"), Qt::FindDirectChildrenOnly);
+ l = o.findChildren<QObject*>(QRegularExpression("^o.*$"), Qt::FindDirectChildrenOnly);
QCOMPARE(l.size(), 2);
QVERIFY(l.contains(&o1));
QVERIFY(l.contains(&o2));
- l = o.findChildren<QObject*>(QRegExp("t.*"), Qt::FindDirectChildrenOnly);
+ l = o.findChildren<QObject*>(QRegularExpression("^t.*$"), Qt::FindDirectChildrenOnly);
QCOMPARE(l.size(), 1);
QVERIFY(l.contains(&t1));
- tl = o.findChildren<QTimer*>(QRegExp(".*"), Qt::FindDirectChildrenOnly);
+ tl = o.findChildren<QTimer*>(QRegularExpression("^.*$"), Qt::FindDirectChildrenOnly);
QCOMPARE(tl.size(), 2);
QVERIFY(tl.contains(&t1));
- tl = o.findChildren<QTimer*>(QRegExp("o.*"), Qt::FindDirectChildrenOnly);
+ tl = o.findChildren<QTimer*>(QRegularExpression("^o.*$"), Qt::FindDirectChildrenOnly);
QCOMPARE(tl.size(), 0);
- l = o.findChildren<QObject*>(QRegExp("harry"), Qt::FindDirectChildrenOnly);
+ l = o.findChildren<QObject*>(QRegularExpression("^harry$"), Qt::FindDirectChildrenOnly);
QCOMPARE(l.size(), 0);
// empty and null string check
@@ -798,192 +795,197 @@ void tst_QObject::connectDisconnectNotify_data()
void tst_QObject::connectDisconnectNotify()
{
- NotifyObject *s = new NotifyObject;
- NotifyObject *r = new NotifyObject;
+ NotifyObject s;
+ NotifyObject r;
QFETCH(QString, a_signal);
QFETCH(QString, a_slot);
// Obtaining meta methods
- int signalIndx = ((SenderObject*)s)->metaObject()->indexOfSignal(
+ int signalIndx = ((SenderObject &)s).metaObject()->indexOfSignal(
QMetaObject::normalizedSignature(a_signal.toLatin1().constData()+1).constData());
- int methodIndx = ((ReceiverObject*)r)->metaObject()->indexOfMethod(
+ int methodIndx = ((ReceiverObject &)r).metaObject()->indexOfMethod(
QMetaObject::normalizedSignature(a_slot.toLatin1().constData()+1).constData());
- QMetaMethod signal = ((SenderObject*)s)->metaObject()->method(signalIndx);
- QMetaMethod method = ((ReceiverObject*)r)->metaObject()->method(methodIndx);
+ QMetaMethod signal = ((SenderObject &)s).metaObject()->method(signalIndx);
+ QMetaMethod method = ((ReceiverObject &)r).metaObject()->method(methodIndx);
QVERIFY(signal.isValid());
QVERIFY(method.isValid());
// Test connectNotify
- QVERIFY(QObject::connect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1()));
- QCOMPARE(s->connectedSignals.size(), 1);
- QCOMPARE(s->connectedSignals.at(0), signal);
- QVERIFY(s->disconnectedSignals.isEmpty());
+ QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(),
+ (ReceiverObject *)&r, a_slot.toLatin1()));
+ QCOMPARE(s.connectedSignals.size(), 1);
+ QCOMPARE(s.connectedSignals.at(0), signal);
+ QVERIFY(s.disconnectedSignals.isEmpty());
// Test disconnectNotify
- QVERIFY(QObject::disconnect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1()));
- QCOMPARE(s->disconnectedSignals.size(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), signal);
- QCOMPARE(s->connectedSignals.size(), 1);
+ QVERIFY(QObject::disconnect((SenderObject *)&s, a_signal.toLatin1(),
+ (ReceiverObject *)&r, a_slot.toLatin1()));
+ QCOMPARE(s.disconnectedSignals.size(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), signal);
+ QCOMPARE(s.connectedSignals.size(), 1);
// Reconnect
- s->clearNotifications();
- QVERIFY(QObject::connect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1()));
- QCOMPARE(s->connectedSignals.size(), 1);
- QCOMPARE(s->connectedSignals.at(0), signal);
- QVERIFY(s->disconnectedSignals.isEmpty());
+ s.clearNotifications();
+ QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(),
+ (ReceiverObject *)&r, a_slot.toLatin1()));
+ QCOMPARE(s.connectedSignals.size(), 1);
+ QCOMPARE(s.connectedSignals.at(0), signal);
+ QVERIFY(s.disconnectedSignals.isEmpty());
// Test disconnectNotify for a complete disconnect
- QVERIFY(((SenderObject*)s)->disconnect((ReceiverObject*)r));
- QCOMPARE(s->disconnectedSignals.size(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod());
- QCOMPARE(s->connectedSignals.size(), 1);
+ QVERIFY(((SenderObject *)&s)->disconnect((ReceiverObject *)&r));
+ QCOMPARE(s.disconnectedSignals.size(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod());
+ QCOMPARE(s.connectedSignals.size(), 1);
// Test connectNotify when connecting by QMetaMethod
- s->clearNotifications();
- QVERIFY(QObject::connect((SenderObject*)s, signal, (ReceiverObject*)r, method));
- QCOMPARE(s->connectedSignals.size(), 1);
- QCOMPARE(s->connectedSignals.at(0), signal);
- QVERIFY(s->disconnectedSignals.isEmpty());
+ s.clearNotifications();
+ QVERIFY(QObject::connect((SenderObject *)&s, signal, (ReceiverObject *)&r, method));
+ QCOMPARE(s.connectedSignals.size(), 1);
+ QCOMPARE(s.connectedSignals.at(0), signal);
+ QVERIFY(s.disconnectedSignals.isEmpty());
// Test disconnectNotify when disconnecting by QMetaMethod
- QVERIFY(QObject::disconnect((SenderObject*)s, signal, (ReceiverObject*)r, method));
- QCOMPARE(s->disconnectedSignals.size(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), signal);
- QCOMPARE(s->connectedSignals.size(), 1);
+ QVERIFY(QObject::disconnect((SenderObject *)&s, signal, (ReceiverObject *)&r, method));
+ QCOMPARE(s.disconnectedSignals.size(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), signal);
+ QCOMPARE(s.connectedSignals.size(), 1);
// Reconnect
- s->clearNotifications();
- QVERIFY(QObject::connect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1()));
+ s.clearNotifications();
+ QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(),
+ (ReceiverObject *)&r, a_slot.toLatin1()));
// Test disconnectNotify for a complete disconnect by QMetaMethod
- QVERIFY(QObject::disconnect((SenderObject*)s, QMetaMethod(), 0, QMetaMethod()));
- QCOMPARE(s->disconnectedSignals.size(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod());
- QCOMPARE(s->connectedSignals.size(), 1);
+ QVERIFY(QObject::disconnect((SenderObject *)&s, QMetaMethod(), 0, QMetaMethod()));
+ QCOMPARE(s.disconnectedSignals.size(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod());
+ QCOMPARE(s.connectedSignals.size(), 1);
// Test connectNotify when connecting by index
- s->clearNotifications();
- QVERIFY(QMetaObject::connect((SenderObject*)s, signalIndx, (ReceiverObject*)r, methodIndx));
- QCOMPARE(s->connectedSignals.size(), 1);
- QCOMPARE(s->connectedSignals.at(0), signal);
- QVERIFY(s->disconnectedSignals.isEmpty());
+ s.clearNotifications();
+ QVERIFY(QMetaObject::connect((SenderObject *)&s, signalIndx, (ReceiverObject *)&r, methodIndx));
+ QCOMPARE(s.connectedSignals.size(), 1);
+ QCOMPARE(s.connectedSignals.at(0), signal);
+ QVERIFY(s.disconnectedSignals.isEmpty());
// Test disconnectNotify when disconnecting by index
- QVERIFY(QMetaObject::disconnect((SenderObject*)s, signalIndx, (ReceiverObject*)r, methodIndx));
- QCOMPARE(s->disconnectedSignals.size(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), signal);
- QCOMPARE(s->connectedSignals.size(), 1);
-
- delete s;
- delete r;
+ QVERIFY(QMetaObject::disconnect((SenderObject *)&s, signalIndx,
+ (ReceiverObject *)&r, methodIndx));
+ QCOMPARE(s.disconnectedSignals.size(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), signal);
+ QCOMPARE(s.connectedSignals.size(), 1);
}
static void connectDisconnectNotifyTestSlot() {}
void tst_QObject::connectDisconnectNotifyPMF()
{
- NotifyObject *s = new NotifyObject;
- NotifyObject *r = new NotifyObject;
+ NotifyObject s;
+ NotifyObject r;
QMetaMethod signal = QMetaMethod::fromSignal(&SenderObject::signal1);
// Test connectNotify
- QVERIFY(QObject::connect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, &ReceiverObject::slot1));
- QCOMPARE(s->connectedSignals.size(), 1);
- QCOMPARE(s->connectedSignals.at(0), signal);
- QVERIFY(s->disconnectedSignals.isEmpty());
+ QVERIFY(QObject::connect((SenderObject *)&s, &SenderObject::signal1,
+ (ReceiverObject *)&r, &ReceiverObject::slot1));
+ QCOMPARE(s.connectedSignals.size(), 1);
+ QCOMPARE(s.connectedSignals.at(0), signal);
+ QVERIFY(s.disconnectedSignals.isEmpty());
// Test disconnectNotify
- QVERIFY(QObject::disconnect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, &ReceiverObject::slot1));
- QCOMPARE(s->disconnectedSignals.size(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), signal);
- QCOMPARE(s->connectedSignals.size(), 1);
+ QVERIFY(QObject::disconnect((SenderObject *)&s, &SenderObject::signal1,
+ (ReceiverObject *)&r, &ReceiverObject::slot1));
+ QCOMPARE(s.disconnectedSignals.size(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), signal);
+ QCOMPARE(s.connectedSignals.size(), 1);
// Reconnect
- s->clearNotifications();
- QVERIFY(QObject::connect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, &ReceiverObject::slot1));
- QCOMPARE(s->connectedSignals.size(), 1);
- QCOMPARE(s->connectedSignals.at(0), signal);
- QVERIFY(s->disconnectedSignals.isEmpty());
+ s.clearNotifications();
+ QVERIFY(QObject::connect((SenderObject *)&s, &SenderObject::signal1,
+ (ReceiverObject *)&r, &ReceiverObject::slot1));
+ QCOMPARE(s.connectedSignals.size(), 1);
+ QCOMPARE(s.connectedSignals.at(0), signal);
+ QVERIFY(s.disconnectedSignals.isEmpty());
// Test disconnectNotify with wildcard slot
- QVERIFY(QObject::disconnect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, 0));
- QCOMPARE(s->disconnectedSignals.size(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), signal);
- QCOMPARE(s->connectedSignals.size(), 1);
+ QVERIFY(QObject::disconnect((SenderObject *)&s, &SenderObject::signal1,
+ (ReceiverObject *)&r, 0));
+ QCOMPARE(s.disconnectedSignals.size(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), signal);
+ QCOMPARE(s.connectedSignals.size(), 1);
// Reconnect
- s->clearNotifications();
- QMetaObject::Connection conn = connect((SenderObject*)s, &SenderObject::signal1,
- (ReceiverObject*)r, &ReceiverObject::slot1);
+ s.clearNotifications();
+ QMetaObject::Connection conn = connect((SenderObject *)&s, &SenderObject::signal1,
+ (ReceiverObject *)&r, &ReceiverObject::slot1);
QVERIFY(conn);
// Test disconnectNotify when disconnecting by QMetaObject::Connection
QVERIFY(QObject::disconnect(conn));
- QVERIFY(!s->disconnectedSignals.isEmpty());
+ QVERIFY(!s.disconnectedSignals.isEmpty());
// Test connectNotify when connecting by function pointer
- s->clearNotifications();
- QVERIFY(QObject::connect((SenderObject*)s, &SenderObject::signal1, connectDisconnectNotifyTestSlot));
- QCOMPARE(s->connectedSignals.size(), 1);
- QCOMPARE(s->connectedSignals.at(0), signal);
- QVERIFY(s->disconnectedSignals.isEmpty());
-
- delete s;
- delete r;
+ s.clearNotifications();
+ QVERIFY(QObject::connect((SenderObject *)&s, &SenderObject::signal1,
+ connectDisconnectNotifyTestSlot));
+ QCOMPARE(s.connectedSignals.size(), 1);
+ QCOMPARE(s.connectedSignals.at(0), signal);
+ QVERIFY(s.disconnectedSignals.isEmpty());
}
void tst_QObject::disconnectNotify_receiverDestroyed()
{
- NotifyObject *s = new NotifyObject;
- NotifyObject *r = new NotifyObject;
+ NotifyObject s;
- QVERIFY(QObject::connect((SenderObject*)s, SIGNAL(signal1()), (ReceiverObject*)r, SLOT(slot1())));
-
- delete r;
- QCOMPARE(s->disconnectedSignals.count(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1));
-
- s->disconnectedSignals.clear();
- r = new NotifyObject;
+ {
+ NotifyObject r;
+ QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(signal1()),
+ (ReceiverObject *)&r, SLOT(slot1())));
+ }
+ QCOMPARE(s.disconnectedSignals.count(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1));
- QVERIFY(QObject::connect((SenderObject*)s, SIGNAL(signal3()), (ReceiverObject*)r, SLOT(slot3())));
+ s.disconnectedSignals.clear();
- delete r;
- QCOMPARE(s->disconnectedSignals.count(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal3));
+ {
+ NotifyObject r;
+ QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(signal3()),
+ (ReceiverObject *)&r, SLOT(slot3())));
+ }
- s->disconnectedSignals.clear();
- r = new NotifyObject;
+ QCOMPARE(s.disconnectedSignals.count(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal3));
- QVERIFY(QObject::connect((SenderObject*)s, SIGNAL(destroyed()), (ReceiverObject*)r, SLOT(slot3())));
+ s.disconnectedSignals.clear();
- delete r;
- QCOMPARE(s->disconnectedSignals.count(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&QObject::destroyed));
+ {
+ NotifyObject r;
+ QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(destroyed()), (ReceiverObject *)&r, SLOT(slot3())));
+ }
- delete s;
+ QCOMPARE(s.disconnectedSignals.count(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&QObject::destroyed));
}
void tst_QObject::disconnectNotify_metaObjConnection()
{
- NotifyObject *s = new NotifyObject;
- NotifyObject *r = new NotifyObject;
-
- QMetaObject::Connection c = QObject::connect((SenderObject*)s, SIGNAL(signal1()),
- (ReceiverObject*)r, SLOT(slot1()));
- QVERIFY(c);
- QVERIFY(QObject::disconnect(c));
+ NotifyObject s;
+ {
+ NotifyObject r;
- QCOMPARE(s->disconnectedSignals.count(), 1);
- QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1));
+ QMetaObject::Connection c = QObject::connect((SenderObject *)&s, SIGNAL(signal1()),
+ (ReceiverObject *)&r, SLOT(slot1()));
+ QVERIFY(c);
+ QVERIFY(QObject::disconnect(c));
- delete r;
- QCOMPARE(s->disconnectedSignals.count(), 1);
+ QCOMPARE(s.disconnectedSignals.count(), 1);
+ QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1));
- delete s;
+ QCOMPARE(s.disconnectedSignals.count(), 1);
+ }
}
class ConnectByNameNotifySenderObject : public QObject
@@ -1032,18 +1034,16 @@ public Q_SLOTS:
void tst_QObject::connectNotify_connectSlotsByName()
{
ConnectByNameNotifyReceiverObject testObject;
- QList<ConnectByNameNotifySenderObject *> senders =
- qFindChildren<ConnectByNameNotifySenderObject *>(&testObject);
- for (int i = 0; i < senders.size(); ++i) {
- ConnectByNameNotifySenderObject *o = senders.at(i);
+ const QList<ConnectByNameNotifySenderObject *> senders =
+ testObject.findChildren<ConnectByNameNotifySenderObject *>();
+ for (ConnectByNameNotifySenderObject *o : senders) {
QVERIFY(o->connectedSignals.isEmpty());
QVERIFY(o->disconnectedSignals.isEmpty());
}
QMetaObject::connectSlotsByName(&testObject);
- for (int i = 0; i < senders.size(); ++i) {
- ConnectByNameNotifySenderObject *o = senders.at(i);
+ for (ConnectByNameNotifySenderObject *o : senders) {
QCOMPARE(o->connectedSignals.size(), 1);
QCOMPARE(o->connectedSignals.at(0), QMetaMethod::fromSignal(&ConnectByNameNotifySenderObject::signal1));
QVERIFY(o->disconnectedSignals.isEmpty());
@@ -1628,7 +1628,7 @@ void tst_QObject::thread()
QObject object;
// thread affinity for objects with no parent should be the
// current thread
- QVERIFY(object.thread() != 0);
+ QVERIFY(object.thread() != nullptr);
QCOMPARE(object.thread(), currentThread);
// children inherit their parent's thread
QObject child(&object);
@@ -1640,7 +1640,7 @@ void tst_QObject::thread()
{
TestThread thr;
- QVERIFY(thr.thread() != 0);
+ QVERIFY(thr.thread() != nullptr);
QCOMPARE(thr.thread(), currentThread);
thr.object = &object;
@@ -1799,8 +1799,8 @@ void tst_QObject::moveToThread()
QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
thread.wait();
- QVERIFY(opointer == 0);
- QVERIFY(cpointer == 0);
+ QVERIFY(opointer == nullptr);
+ QVERIFY(cpointer == nullptr);
}
{
@@ -2376,7 +2376,7 @@ void tst_QObject::testUserData()
for (int i=0; i<USER_DATA_COUNT; ++i) {
int id = user_data_ids[i];
CustomData *data = static_cast<CustomData *>(my_test_object.userData(id));
- QVERIFY(data != 0);
+ QVERIFY(data != nullptr);
QCOMPARE(data->id, id);
}
}
@@ -3408,12 +3408,11 @@ void tst_QObject::disconnectSelfInSlotAndDeleteAfterEmit()
void tst_QObject::dumpObjectInfo()
{
QObject a, b;
- QObject::connect(&a, SIGNAL(destroyed(QObject*)), &b, SLOT(deleteLater()));
- a.disconnect(&b);
+ QObject::connect(&a, &QObject::destroyed, &b, &QObject::deleteLater);
QTest::ignoreMessage(QtDebugMsg, "OBJECT QObject::unnamed");
QTest::ignoreMessage(QtDebugMsg, " SIGNALS OUT");
QTest::ignoreMessage(QtDebugMsg, " signal: destroyed(QObject*)");
- QTest::ignoreMessage(QtDebugMsg, " <Disconnected receiver>");
+ QTest::ignoreMessage(QtDebugMsg, " <functor or function pointer>");
QTest::ignoreMessage(QtDebugMsg, " SIGNALS IN");
QTest::ignoreMessage(QtDebugMsg, " <None>");
a.dumpObjectInfo(); // should not crash
@@ -3463,130 +3462,131 @@ void tst_QObject::qobjectConstCast()
void tst_QObject::uniqConnection()
{
- SenderObject *s = new SenderObject;
- ReceiverObject *r1 = new ReceiverObject;
- ReceiverObject *r2 = new ReceiverObject;
- r1->reset();
- r2->reset();
+ SenderObject s;
+ ReceiverObject r1;
+ ReceiverObject r2;
+ r1.reset();
+ r2.reset();
ReceiverObject::sequence = 0;
- QVERIFY( connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) , Qt::UniqueConnection) );
- QVERIFY( connect( s, SIGNAL(signal1()), r2, SLOT(slot1()) , Qt::UniqueConnection) );
- QVERIFY( connect( s, SIGNAL(signal1()), r1, SLOT(slot3()) , Qt::UniqueConnection) );
- QVERIFY( connect( s, SIGNAL(signal3()), r1, SLOT(slot3()) , Qt::UniqueConnection) );
+ QVERIFY(connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()) , Qt::UniqueConnection) );
+ QVERIFY(connect(&s, SIGNAL(signal1()), &r2, SLOT(slot1()) , Qt::UniqueConnection) );
+ QVERIFY(connect(&s, SIGNAL(signal1()), &r1, SLOT(slot3()) , Qt::UniqueConnection) );
+ QVERIFY(connect(&s, SIGNAL(signal3()), &r1, SLOT(slot3()) , Qt::UniqueConnection) );
- s->emitSignal1();
- s->emitSignal2();
- s->emitSignal3();
- s->emitSignal4();
-
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 0 );
- QCOMPARE( r1->count_slot3, 2 );
- QCOMPARE( r1->count_slot4, 0 );
- QCOMPARE( r2->count_slot1, 1 );
- QCOMPARE( r2->count_slot2, 0 );
- QCOMPARE( r2->count_slot3, 0 );
- QCOMPARE( r2->count_slot4, 0 );
- QCOMPARE( r1->sequence_slot1, 1 );
- QCOMPARE( r2->sequence_slot1, 2 );
- QCOMPARE( r1->sequence_slot3, 4 );
-
- r1->reset();
- r2->reset();
+ s.emitSignal1();
+ s.emitSignal2();
+ s.emitSignal3();
+ s.emitSignal4();
+
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 0);
+ QCOMPARE(r1.count_slot3, 2);
+ QCOMPARE(r1.count_slot4, 0);
+ QCOMPARE(r2.count_slot1, 1);
+ QCOMPARE(r2.count_slot2, 0);
+ QCOMPARE(r2.count_slot3, 0);
+ QCOMPARE(r2.count_slot4, 0);
+ QCOMPARE(r1.sequence_slot1, 1);
+ QCOMPARE(r2.sequence_slot1, 2);
+ QCOMPARE(r1.sequence_slot3, 4);
+
+ r1.reset();
+ r2.reset();
ReceiverObject::sequence = 0;
- QVERIFY( connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) , Qt::UniqueConnection) );
- QVERIFY( connect( s, SIGNAL(signal4()), r2, SLOT(slot4()) , Qt::UniqueConnection) );
- QVERIFY(!connect( s, SIGNAL(signal4()), r2, SLOT(slot4()) , Qt::UniqueConnection) );
- QVERIFY( connect( s, SIGNAL(signal1()), r2, SLOT(slot4()) , Qt::UniqueConnection) );
- QVERIFY(!connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) , Qt::UniqueConnection) );
+ QVERIFY( connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()) , Qt::UniqueConnection));
+ QVERIFY( connect(&s, SIGNAL(signal4()), &r2, SLOT(slot4()) , Qt::UniqueConnection));
+ QVERIFY(!connect(&s, SIGNAL(signal4()), &r2, SLOT(slot4()) , Qt::UniqueConnection));
+ QVERIFY( connect(&s, SIGNAL(signal1()), &r2, SLOT(slot4()) , Qt::UniqueConnection));
+ QVERIFY(!connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()) , Qt::UniqueConnection));
- s->emitSignal4();
- QCOMPARE( r1->count_slot4, 1 );
- QCOMPARE( r2->count_slot4, 1 );
- QCOMPARE( r1->sequence_slot4, 1 );
- QCOMPARE( r2->sequence_slot4, 2 );
+ s.emitSignal4();
+ QCOMPARE(r1.count_slot4, 1);
+ QCOMPARE(r2.count_slot4, 1);
+ QCOMPARE(r1.sequence_slot4, 1);
+ QCOMPARE(r2.sequence_slot4, 2);
- r1->reset();
- r2->reset();
+ r1.reset();
+ r2.reset();
ReceiverObject::sequence = 0;
- connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) );
+ connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()));
- s->emitSignal4();
- QCOMPARE( r1->count_slot4, 2 );
- QCOMPARE( r2->count_slot4, 1 );
- QCOMPARE( r1->sequence_slot4, 3 );
- QCOMPARE( r2->sequence_slot4, 2 );
-
- delete s;
- delete r1;
- delete r2;
+ s.emitSignal4();
+ QCOMPARE(r1.count_slot4, 2);
+ QCOMPARE(r2.count_slot4, 1);
+ QCOMPARE(r1.sequence_slot4, 3);
+ QCOMPARE(r2.sequence_slot4, 2);
}
void tst_QObject::uniqConnectionPtr()
{
- SenderObject *s = new SenderObject;
- ReceiverObject *r1 = new ReceiverObject;
- ReceiverObject *r2 = new ReceiverObject;
- r1->reset();
- r2->reset();
+ SenderObject s;
+ ReceiverObject r1;
+ ReceiverObject r2;
+ r1.reset();
+ r2.reset();
ReceiverObject::sequence = 0;
- QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 , Qt::UniqueConnection) );
- QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 , Qt::UniqueConnection) );
- QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) );
- QVERIFY( connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) );
+ QVERIFY(connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1 ,
+ Qt::UniqueConnection));
+ QVERIFY(connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot1 ,
+ Qt::UniqueConnection));
+ QVERIFY(connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot3 ,
+ Qt::UniqueConnection));
+ QVERIFY(connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot3 ,
+ Qt::UniqueConnection));
- s->emitSignal1();
- s->emitSignal2();
- s->emitSignal3();
- s->emitSignal4();
-
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 0 );
- QCOMPARE( r1->count_slot3, 2 );
- QCOMPARE( r1->count_slot4, 0 );
- QCOMPARE( r2->count_slot1, 1 );
- QCOMPARE( r2->count_slot2, 0 );
- QCOMPARE( r2->count_slot3, 0 );
- QCOMPARE( r2->count_slot4, 0 );
- QCOMPARE( r1->sequence_slot1, 1 );
- QCOMPARE( r2->sequence_slot1, 2 );
- QCOMPARE( r1->sequence_slot3, 4 );
-
- r1->reset();
- r2->reset();
+ s.emitSignal1();
+ s.emitSignal2();
+ s.emitSignal3();
+ s.emitSignal4();
+
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 0);
+ QCOMPARE(r1.count_slot3, 2);
+ QCOMPARE(r1.count_slot4, 0);
+ QCOMPARE(r2.count_slot1, 1);
+ QCOMPARE(r2.count_slot2, 0);
+ QCOMPARE(r2.count_slot3, 0);
+ QCOMPARE(r2.count_slot4, 0);
+ QCOMPARE(r1.sequence_slot1, 1);
+ QCOMPARE(r2.sequence_slot1, 2);
+ QCOMPARE(r1.sequence_slot3, 4);
+
+ r1.reset();
+ r2.reset();
ReceiverObject::sequence = 0;
- QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) );
- QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
- QVERIFY(!connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
- QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
- QVERIFY(!connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) );
+ QVERIFY( connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4 ,
+ Qt::UniqueConnection));
+ QVERIFY( connect(&s, &SenderObject::signal4, &r2, &ReceiverObject::slot4 ,
+ Qt::UniqueConnection));
+ QVERIFY(!connect(&s, &SenderObject::signal4, &r2, &ReceiverObject::slot4 ,
+ Qt::UniqueConnection));
+ QVERIFY( connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot4 ,
+ Qt::UniqueConnection));
+ QVERIFY(!connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4 ,
+ Qt::UniqueConnection));
- s->emitSignal4();
- QCOMPARE( r1->count_slot4, 1 );
- QCOMPARE( r2->count_slot4, 1 );
- QCOMPARE( r1->sequence_slot4, 1 );
- QCOMPARE( r2->sequence_slot4, 2 );
+ s.emitSignal4();
+ QCOMPARE(r1.count_slot4, 1);
+ QCOMPARE(r2.count_slot4, 1);
+ QCOMPARE(r1.sequence_slot4, 1);
+ QCOMPARE(r2.sequence_slot4, 2);
- r1->reset();
- r2->reset();
+ r1.reset();
+ r2.reset();
ReceiverObject::sequence = 0;
- connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 );
-
- s->emitSignal4();
- QCOMPARE( r1->count_slot4, 2 );
- QCOMPARE( r2->count_slot4, 1 );
- QCOMPARE( r1->sequence_slot4, 3 );
- QCOMPARE( r2->sequence_slot4, 2 );
+ connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4);
- delete s;
- delete r1;
- delete r2;
+ s.emitSignal4();
+ QCOMPARE(r1.count_slot4, 2);
+ QCOMPARE(r2.count_slot4, 1);
+ QCOMPARE(r1.sequence_slot4, 3);
+ QCOMPARE(r2.sequence_slot4, 2);
}
void tst_QObject::interfaceIid()
@@ -3624,7 +3624,7 @@ class OverloadObject : public QObject
void sig(int i, int j = 12);
void sig(QObject *o, QObject *p, QObject *q = 0, QObject *r = 0) const;
void other(int a = 0);
- void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = 0);
+ void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = nullptr);
void sig(double r = 0.5);
public slots:
void slo(int i, int j = 43)
@@ -3890,217 +3890,214 @@ void tst_QObject::isSignalConnectedAfterDisconnection()
void tst_QObject::qMetaObjectConnect()
{
- SenderObject *s = new SenderObject;
- ReceiverObject *r1 = new ReceiverObject;
- ReceiverObject *r2 = new ReceiverObject;
- r1->reset();
- r2->reset();
- ReceiverObject::sequence = 0;
-
- int signal1Index = s->metaObject()->indexOfSignal("signal1()");
- int signal3Index = s->metaObject()->indexOfSignal("signal3()");
- int slot1Index = r1->metaObject()->indexOfSlot("slot1()");
- int slot2Index = r1->metaObject()->indexOfSlot("slot2()");
- int slot3Index = r1->metaObject()->indexOfSlot("slot3()");
-
- QVERIFY(slot1Index > 0);
- QVERIFY(slot2Index > 0);
- QVERIFY(slot3Index > 0);
-
- QVERIFY( QMetaObject::connect( s, signal1Index, r1, slot1Index) );
- QVERIFY( QMetaObject::connect( s, signal3Index, r2, slot3Index) );
- QVERIFY( QMetaObject::connect( s, -1, r2, slot2Index) );
-
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 0 );
- QCOMPARE( r1->count_slot3, 0 );
- QCOMPARE( r2->count_slot1, 0 );
- QCOMPARE( r2->count_slot2, 0 );
- QCOMPARE( r2->count_slot3, 0 );
-
- s->emitSignal1();
-
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 0 );
- QCOMPARE( r1->count_slot3, 0 );
- QCOMPARE( r2->count_slot1, 0 );
- QCOMPARE( r2->count_slot2, 1 );
- QCOMPARE( r2->count_slot3, 0 );
-
- s->emitSignal2();
- s->emitSignal3();
- s->emitSignal4();
-
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 0 );
- QCOMPARE( r1->count_slot3, 0 );
- QCOMPARE( r2->count_slot1, 0 );
- QCOMPARE( r2->count_slot2, 4 );
- QCOMPARE( r2->count_slot3, 1 );
-
- QVERIFY( QMetaObject::disconnect( s, signal1Index, r1, slot1Index) );
- QVERIFY( QMetaObject::disconnect( s, signal3Index, r2, slot3Index) );
- QVERIFY( QMetaObject::disconnect( s, -1, r2, slot2Index) );
-
- s->emitSignal1();
- s->emitSignal2();
- s->emitSignal3();
- s->emitSignal4();
-
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 0 );
- QCOMPARE( r1->count_slot3, 0 );
- QCOMPARE( r2->count_slot1, 0 );
- QCOMPARE( r2->count_slot2, 4 );
- QCOMPARE( r2->count_slot3, 1 );
-
- //some "dynamic" signal
- QVERIFY( QMetaObject::connect( s, s->metaObject()->methodOffset() + 20, r1, slot3Index) );
- QVERIFY( QMetaObject::connect( s, s->metaObject()->methodOffset() + 35, r2, slot1Index) );
- QVERIFY( QMetaObject::connect( s, -1, r1, slot2Index) );
-
- r1->reset();
- r2->reset();
-
- void *args[] = { 0 , 0 };
- QMetaObject::activate(s, s->metaObject()->methodOffset() + 20, args);
- QMetaObject::activate(s, s->metaObject()->methodOffset() + 48, args);
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 2 );
- QCOMPARE( r1->count_slot3, 1 );
- QCOMPARE( r2->count_slot1, 0 );
- QCOMPARE( r2->count_slot2, 0 );
- QCOMPARE( r2->count_slot3, 0 );
-
- QMetaObject::activate(s, s->metaObject()->methodOffset() + 35, args);
- s->emitSignal1();
- s->emitSignal2();
-
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 5 );
- QCOMPARE( r1->count_slot3, 1 );
- QCOMPARE( r2->count_slot1, 1 );
- QCOMPARE( r2->count_slot2, 0 );
- QCOMPARE( r2->count_slot3, 0 );
+ ReceiverObject r1;
+ ReceiverObject r2;
+ int slot1Index, slot2Index, slot3Index;
+ {
+ SenderObject s;
+ r1.reset();
+ r2.reset();
+ ReceiverObject::sequence = 0;
+
+ int signal1Index = s.metaObject()->indexOfSignal("signal1()");
+ int signal3Index = s.metaObject()->indexOfSignal("signal3()");
+ slot1Index = r1.metaObject()->indexOfSlot("slot1()");
+ slot2Index = r1.metaObject()->indexOfSlot("slot2()");
+ slot3Index = r1.metaObject()->indexOfSlot("slot3()");
+
+ QVERIFY(slot1Index > 0);
+ QVERIFY(slot2Index > 0);
+ QVERIFY(slot3Index > 0);
+
+ QVERIFY(QMetaObject::connect(&s, signal1Index, &r1, slot1Index));
+ QVERIFY(QMetaObject::connect(&s, signal3Index, &r2, slot3Index));
+ QVERIFY(QMetaObject::connect(&s, -1, &r2, slot2Index));
+
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 0);
+ QCOMPARE(r1.count_slot3, 0);
+ QCOMPARE(r2.count_slot1, 0);
+ QCOMPARE(r2.count_slot2, 0);
+ QCOMPARE(r2.count_slot3, 0);
+
+ s.emitSignal1();
+
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 0);
+ QCOMPARE(r1.count_slot3, 0);
+ QCOMPARE(r2.count_slot1, 0);
+ QCOMPARE(r2.count_slot2, 1);
+ QCOMPARE(r2.count_slot3, 0);
+
+ s.emitSignal2();
+ s.emitSignal3();
+ s.emitSignal4();
+
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 0);
+ QCOMPARE(r1.count_slot3, 0);
+ QCOMPARE(r2.count_slot1, 0);
+ QCOMPARE(r2.count_slot2, 4);
+ QCOMPARE(r2.count_slot3, 1);
+
+ QVERIFY(QMetaObject::disconnect(&s, signal1Index, &r1, slot1Index));
+ QVERIFY(QMetaObject::disconnect(&s, signal3Index, &r2, slot3Index));
+ QVERIFY(QMetaObject::disconnect(&s, -1, &r2, slot2Index));
+
+ s.emitSignal1();
+ s.emitSignal2();
+ s.emitSignal3();
+ s.emitSignal4();
+
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 0);
+ QCOMPARE(r1.count_slot3, 0);
+ QCOMPARE(r2.count_slot1, 0);
+ QCOMPARE(r2.count_slot2, 4);
+ QCOMPARE(r2.count_slot3, 1);
+
+ //some "dynamic" signal
+ QVERIFY(QMetaObject::connect(&s, s.metaObject()->methodOffset() + 20, &r1, slot3Index));
+ QVERIFY(QMetaObject::connect(&s, s.metaObject()->methodOffset() + 35, &r2, slot1Index));
+ QVERIFY(QMetaObject::connect(&s, -1, &r1, slot2Index));
+
+ r1.reset();
+ r2.reset();
+
+ void *args[] = { 0 , 0 };
+ QMetaObject::activate(&s, s.metaObject()->methodOffset() + 20, args);
+ QMetaObject::activate(&s, s.metaObject()->methodOffset() + 48, args);
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 2);
+ QCOMPARE(r1.count_slot3, 1);
+ QCOMPARE(r2.count_slot1, 0);
+ QCOMPARE(r2.count_slot2, 0);
+ QCOMPARE(r2.count_slot3, 0);
+
+ QMetaObject::activate(&s, s.metaObject()->methodOffset() + 35, args);
+ s.emitSignal1();
+ s.emitSignal2();
+
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 5);
+ QCOMPARE(r1.count_slot3, 1);
+ QCOMPARE(r2.count_slot1, 1);
+ QCOMPARE(r2.count_slot2, 0);
+ QCOMPARE(r2.count_slot3, 0);
+ }
- delete s;
- r1->reset();
- r2->reset();
+ r1.reset();
+ r2.reset();
#define SIGNAL_INDEX(S) obj1.metaObject()->indexOfSignal(QMetaObject::normalizedSignature(#S))
OverloadObject obj1;
QObject obj2, obj3;
- QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int)) , r1, slot1Index);
- QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *)) , r2, slot1Index);
+ QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int)) , &r1, slot1Index);
+ QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *)) ,
+ &r2, slot1Index);
- QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *, QObject *)) , r1, slot2Index);
- QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *)) , r2, slot2Index);
- QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int, int)) , r1, slot3Index);
+ QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *, QObject *)) ,
+ &r1, slot2Index);
+ QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *)) , &r2, slot2Index);
+ QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int, int)) , &r1, slot3Index);
emit obj1.sig(0.5); //connected to nothing
emit obj1.sig(1, 'a'); //connected to nothing
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 0 );
- QCOMPARE( r1->count_slot3, 0 );
- QCOMPARE( r2->count_slot1, 0 );
- QCOMPARE( r2->count_slot2, 0 );
- QCOMPARE( r2->count_slot3, 0 );
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 0);
+ QCOMPARE(r1.count_slot3, 0);
+ QCOMPARE(r2.count_slot1, 0);
+ QCOMPARE(r2.count_slot2, 0);
+ QCOMPARE(r2.count_slot3, 0);
emit obj1.sig(1); //this signal is connected
emit obj1.sig(&obj2);
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 0 );
- QCOMPARE( r1->count_slot3, 1 );
- QCOMPARE( r2->count_slot1, 0 );
- QCOMPARE( r2->count_slot2, 1 );
- QCOMPARE( r2->count_slot3, 0 );
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 0);
+ QCOMPARE(r1.count_slot3, 1);
+ QCOMPARE(r2.count_slot1, 0);
+ QCOMPARE(r2.count_slot2, 1);
+ QCOMPARE(r2.count_slot3, 0);
emit obj1.sig(&obj2, &obj3); //this signal is connected
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 1 );
- QCOMPARE( r1->count_slot3, 1 );
- QCOMPARE( r2->count_slot1, 1 );
- QCOMPARE( r2->count_slot2, 1 );
- QCOMPARE( r2->count_slot3, 0 );
-
- delete r1;
- delete r2;
-
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 1);
+ QCOMPARE(r1.count_slot3, 1);
+ QCOMPARE(r2.count_slot1, 1);
+ QCOMPARE(r2.count_slot2, 1);
+ QCOMPARE(r2.count_slot3, 0);
}
void tst_QObject::qMetaObjectDisconnectOne()
{
- SenderObject *s = new SenderObject;
- ReceiverObject *r1 = new ReceiverObject;
+ SenderObject s;
+ ReceiverObject r1;
- int signal1Index = s->metaObject()->indexOfSignal("signal1()");
- int signal3Index = s->metaObject()->indexOfSignal("signal3()");
- int slot1Index = r1->metaObject()->indexOfSlot("slot1()");
- int slot2Index = r1->metaObject()->indexOfSlot("slot2()");
+ int signal1Index = s.metaObject()->indexOfSignal("signal1()");
+ int signal3Index = s.metaObject()->indexOfSignal("signal3()");
+ int slot1Index = r1.metaObject()->indexOfSlot("slot1()");
+ int slot2Index = r1.metaObject()->indexOfSlot("slot2()");
QVERIFY(signal1Index > 0);
QVERIFY(signal3Index > 0);
QVERIFY(slot1Index > 0);
QVERIFY(slot2Index > 0);
- QVERIFY( QMetaObject::connect(s, signal1Index, r1, slot1Index) );
- QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) );
- QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) );
- QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) );
-
- r1->reset();
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 0 );
+ QVERIFY(QMetaObject::connect(&s, signal1Index, &r1, slot1Index));
+ QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index));
+ QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index));
+ QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index));
- s->emitSignal1();
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 0 );
+ r1.reset();
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 0);
- s->emitSignal3();
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 3 );
+ s.emitSignal1();
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 0);
- r1->reset();
- QVERIFY( QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) );
- QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) );
+ s.emitSignal3();
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 3);
- s->emitSignal1();
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 0 );
+ r1.reset();
+ QVERIFY(QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index));
+ QVERIFY(QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index));
- s->emitSignal3();
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 2 );
+ s.emitSignal1();
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 0);
- r1->reset();
- QVERIFY( false == QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) );
- QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) );
+ s.emitSignal3();
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 2);
- s->emitSignal1();
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 0 );
+ r1.reset();
+ QVERIFY(!QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index));
+ QVERIFY( QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index));
- s->emitSignal3();
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 1 );
+ s.emitSignal1();
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 0);
- r1->reset();
- QVERIFY( false == QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) );
- QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) );
+ s.emitSignal3();
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 1);
- s->emitSignal1();
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 0 );
+ r1.reset();
+ QVERIFY(!QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index));
+ QVERIFY( QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index));
- s->emitSignal3();
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 0 );
+ s.emitSignal1();
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 0);
- delete s;
- delete r1;
+ s.emitSignal3();
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 0);
}
class ConfusingObject : public SenderObject
@@ -4222,106 +4219,95 @@ void tst_QObject::connectConstructorByMetaMethod()
void tst_QObject::disconnectByMetaMethod()
{
- SenderObject *s = new SenderObject;
- ReceiverObject *r1 = new ReceiverObject;
- ReceiverObject *r2 = new ReceiverObject;
-
- QMetaMethod signal1 = s->metaObject()->method(
- s->metaObject()->indexOfMethod("signal1()"));
- QMetaMethod signal2 = s->metaObject()->method(
- s->metaObject()->indexOfMethod("signal2()"));
- QMetaMethod signal3 = s->metaObject()->method(
- s->metaObject()->indexOfMethod("signal3()"));
-
- QMetaMethod slot1 = r1->metaObject()->method(
- r1->metaObject()->indexOfMethod("slot1()"));
- QMetaMethod slot2 = r1->metaObject()->method(
- r1->metaObject()->indexOfMethod("slot2()"));
- QMetaMethod slot3 = r1->metaObject()->method(
- r1->metaObject()->indexOfMethod("slot3()"));
- QMetaMethod slot4 = r1->metaObject()->method(
- r1->metaObject()->indexOfMethod("slot4()"));
-
- connect(s, signal1, r1, slot1);
+ SenderObject s;
+ ReceiverObject r1;
+ ReceiverObject r2;
- s->emitSignal1();
+ QMetaMethod signal1 = s.metaObject()->method(s.metaObject()->indexOfMethod("signal1()"));
+ QMetaMethod signal2 = s.metaObject()->method(s.metaObject()->indexOfMethod("signal2()"));
+ QMetaMethod signal3 = s.metaObject()->method(s.metaObject()->indexOfMethod("signal3()"));
+
+ QMetaMethod slot1 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot1()"));
+ QMetaMethod slot2 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot2()"));
+ QMetaMethod slot3 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot3()"));
+ QMetaMethod slot4 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot4()"));
+
+ connect(&s, signal1, &r1, slot1);
+
+ s.emitSignal1();
- QVERIFY(r1->called(1));
- r1->reset();
+ QVERIFY(r1.called(1));
+ r1.reset();
// usual disconnect with all parameters given
- bool ret = QObject::disconnect(s, signal1, r1, slot1);
+ bool ret = QObject::disconnect(&s, signal1, &r1, slot1);
- s->emitSignal1();
+ s.emitSignal1();
- QVERIFY(!r1->called(1));
- r1->reset();
+ QVERIFY(!r1.called(1));
+ r1.reset();
QVERIFY(ret);
- ret = QObject::disconnect(s, signal1, r1, slot1);
+ ret = QObject::disconnect(&s, signal1, &r1, slot1);
QVERIFY(!ret);
- r1->reset();
+ r1.reset();
- connect( s, signal1, r1, slot1 );
- connect( s, signal1, r1, slot2 );
- connect( s, signal1, r1, slot3 );
- connect( s, signal2, r1, slot4 );
+ connect(&s, signal1, &r1, slot1);
+ connect(&s, signal1, &r1, slot2);
+ connect(&s, signal1, &r1, slot3);
+ connect(&s, signal2, &r1, slot4);
// disconnect s's signal1() from all slots of r1
- QObject::disconnect(s, signal1, r1, QMetaMethod());
+ QObject::disconnect(&s, signal1, &r1, QMetaMethod());
- s->emitSignal1();
- s->emitSignal2();
+ s.emitSignal1();
+ s.emitSignal2();
- QVERIFY(!r1->called(1));
- QVERIFY(!r1->called(2));
- QVERIFY(!r1->called(3));
- QVERIFY(r1->called(4));
- r1->reset();
+ QVERIFY(!r1.called(1));
+ QVERIFY(!r1.called(2));
+ QVERIFY(!r1.called(3));
+ QVERIFY(r1.called(4));
+ r1.reset();
// make sure all is disconnected again
- QObject::disconnect(s, 0, r1, 0);
+ QObject::disconnect(&s, 0, &r1, 0);
- connect(s, signal1, r1, slot1);
- connect(s, signal1, r2, slot1);
- connect(s, signal2, r1, slot2);
- connect(s, signal2, r2, slot2);
- connect(s, signal3, r1, slot3);
- connect(s, signal3, r2, slot3);
+ connect(&s, signal1, &r1, slot1);
+ connect(&s, signal1, &r2, slot1);
+ connect(&s, signal2, &r1, slot2);
+ connect(&s, signal2, &r2, slot2);
+ connect(&s, signal3, &r1, slot3);
+ connect(&s, signal3, &r2, slot3);
// disconnect signal1() from all receivers
- QObject::disconnect(s, signal1, 0, QMetaMethod());
- s->emitSignal1();
- s->emitSignal2();
- s->emitSignal3();
+ QObject::disconnect(&s, signal1, 0, QMetaMethod());
+ s.emitSignal1();
+ s.emitSignal2();
+ s.emitSignal3();
- QVERIFY(!r1->called(1));
- QVERIFY(!r2->called(1));
- QVERIFY(r1->called(2));
- QVERIFY(r2->called(2));
- QVERIFY(r1->called(2));
- QVERIFY(r2->called(2));
+ QVERIFY(!r1.called(1));
+ QVERIFY(!r2.called(1));
+ QVERIFY(r1.called(2));
+ QVERIFY(r2.called(2));
+ QVERIFY(r1.called(2));
+ QVERIFY(r2.called(2));
- r1->reset();
- r2->reset();
+ r1.reset();
+ r2.reset();
// disconnect all signals of s from all receivers
- QObject::disconnect( s, 0, 0, 0 );
+ QObject::disconnect(&s, 0, 0, 0);
- connect( s, signal1, r1, slot1 );
- connect( s, signal1, r2, slot1 );
+ connect(&s, signal1, &r1, slot1);
+ connect(&s, signal1, &r2, slot1);
// disconnect all signals from slot1 of r1
- QObject::disconnect(s, QMetaMethod(), r1, slot1);
+ QObject::disconnect(&s, QMetaMethod(), &r1, slot1);
- s->emitSignal1();
-
- QVERIFY(!r1->called(1));
- QVERIFY(r2->called(1));
+ s.emitSignal1();
- delete r2;
- delete r1;
- delete s;
+ QVERIFY(!r1.called(1));
+ QVERIFY(r2.called(1));
}
void tst_QObject::disconnectNotSignalMetaMethod()
@@ -4459,63 +4445,64 @@ void tst_QObject::baseDestroyed()
void tst_QObject::pointerConnect()
{
- SenderObject *s = new SenderObject;
- ReceiverObject *r1 = new ReceiverObject;
- ReceiverObject *r2 = new ReceiverObject;
- r1->reset();
- r2->reset();
+ SenderObject s;
+ ReceiverObject r1;
+ ReceiverObject r2;
+ r1.reset();
+ r2.reset();
ReceiverObject::sequence = 0;
QTimer timer;
- QVERIFY( connect( s, &SenderObject::signal1 , r1, &ReceiverObject::slot1 ) );
- QVERIFY( connect( s, &SenderObject::signal1 , r2, &ReceiverObject::slot1 ) );
- QVERIFY( connect( s, &SenderObject::signal1 , r1, &ReceiverObject::slot3 ) );
- QVERIFY( connect( s, &SenderObject::signal3 , r1, &ReceiverObject::slot3 ) );
- QVERIFY2( connect( &timer, &QTimer::timeout, r1, &ReceiverObject::deleteLater ),
- "Signal connection failed most likely due to failing comparison of pointers to member functions caused by problems with -reduce-relocations on this platform.");
+ QVERIFY(connect(&s, &SenderObject::signal1 , &r1, &ReceiverObject::slot1));
+ QVERIFY(connect(&s, &SenderObject::signal1 , &r2, &ReceiverObject::slot1));
+ QVERIFY(connect(&s, &SenderObject::signal1 , &r1, &ReceiverObject::slot3));
+ QVERIFY(connect(&s, &SenderObject::signal3 , &r1, &ReceiverObject::slot3));
+ QVERIFY2(connect(&timer, &QTimer::timeout, &r1, &ReceiverObject::deleteLater),
+ "Signal connection failed most likely due to failing comparison of pointers to member "
+ "functions caused by problems with -reduce-relocations on this platform.");
- s->emitSignal1();
- s->emitSignal2();
- s->emitSignal3();
- s->emitSignal4();
-
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 0 );
- QCOMPARE( r1->count_slot3, 2 );
- QCOMPARE( r1->count_slot4, 0 );
- QCOMPARE( r2->count_slot1, 1 );
- QCOMPARE( r2->count_slot2, 0 );
- QCOMPARE( r2->count_slot3, 0 );
- QCOMPARE( r2->count_slot4, 0 );
- QCOMPARE( r1->sequence_slot1, 1 );
- QCOMPARE( r2->sequence_slot1, 2 );
- QCOMPARE( r1->sequence_slot3, 4 );
-
- r1->reset();
- r2->reset();
+ s.emitSignal1();
+ s.emitSignal2();
+ s.emitSignal3();
+ s.emitSignal4();
+
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 0);
+ QCOMPARE(r1.count_slot3, 2);
+ QCOMPARE(r1.count_slot4, 0);
+ QCOMPARE(r2.count_slot1, 1);
+ QCOMPARE(r2.count_slot2, 0);
+ QCOMPARE(r2.count_slot3, 0);
+ QCOMPARE(r2.count_slot4, 0);
+ QCOMPARE(r1.sequence_slot1, 1);
+ QCOMPARE(r2.sequence_slot1, 2);
+ QCOMPARE(r1.sequence_slot3, 4);
+
+ r1.reset();
+ r2.reset();
ReceiverObject::sequence = 0;
- QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 ) );
- QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 ) );
- QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 ) );
+ QVERIFY(connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4));
+ QVERIFY(connect(&s, &SenderObject::signal4, &r2, &ReceiverObject::slot4));
+ QVERIFY(connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot4));
- s->emitSignal4();
- QCOMPARE( r1->count_slot4, 1 );
- QCOMPARE( r2->count_slot4, 1 );
- QCOMPARE( r1->sequence_slot4, 1 );
- QCOMPARE( r2->sequence_slot4, 2 );
+ s.emitSignal4();
+ QCOMPARE(r1.count_slot4, 1);
+ QCOMPARE(r2.count_slot4, 1);
+ QCOMPARE(r1.sequence_slot4, 1);
+ QCOMPARE(r2.sequence_slot4, 2);
- r1->reset();
- r2->reset();
+ r1.reset();
+ r2.reset();
ReceiverObject::sequence = 0;
- connect( s, &SenderObject::signal4 , r1, &ReceiverObject::slot4 );
+ connect(&s, &SenderObject::signal4 , &r1, &ReceiverObject::slot4);
- s->emitSignal4();
- QCOMPARE( r1->count_slot4, 2 );
- QCOMPARE( r2->count_slot4, 1 );
- QCOMPARE( r1->sequence_slot4, 3 );
- QCOMPARE( r2->sequence_slot4, 2 );
+ s.emitSignal4();
+ QCOMPARE(r1.count_slot4, 2);
+ QCOMPARE(r2.count_slot4, 1);
+ QCOMPARE(r1.sequence_slot4, 3);
+ QCOMPARE(r2.sequence_slot4, 2);
QMetaObject::Connection con;
QVERIFY(!con);
@@ -4523,116 +4510,107 @@ void tst_QObject::pointerConnect()
//connect a slot to a signal (== error)
QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in ReceiverObject");
- con = connect(r1, &ReceiverObject::slot4 , s, &SenderObject::signal4 );
+ con = connect(&r1, &ReceiverObject::slot4 , &s, &SenderObject::signal4);
QVERIFY(!con);
QVERIFY(!QObject::disconnect(con));
-
- delete s;
- delete r1;
- delete r2;
}
void tst_QObject::pointerDisconnect()
{
- SenderObject *s = new SenderObject;
- ReceiverObject *r1 = new ReceiverObject;
- ReceiverObject *r2 = new ReceiverObject;
+ SenderObject s;
+ ReceiverObject r1;
+ ReceiverObject r2;
- connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
+ connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1);
- connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 );
- connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 );
- connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 );
+ connect(&s, &SenderObject::signal2, &r1, &ReceiverObject::slot2);
+ connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot3);
+ connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4);
- s->emitSignal1();
- s->emitSignal2();
- s->emitSignal3();
- s->emitSignal4();
+ s.emitSignal1();
+ s.emitSignal2();
+ s.emitSignal3();
+ s.emitSignal4();
- QVERIFY(r1->called(1));
- QVERIFY(r1->called(2));
- QVERIFY(r1->called(3));
- QVERIFY(r1->called(4));
- r1->reset();
+ QVERIFY(r1.called(1));
+ QVERIFY(r1.called(2));
+ QVERIFY(r1.called(3));
+ QVERIFY(r1.called(4));
+ r1.reset();
// usual disconnect with all parameters given
- bool ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
+ bool ret = QObject::disconnect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1);
- s->emitSignal1();
+ s.emitSignal1();
- QVERIFY(!r1->called(1));
- r1->reset();
+ QVERIFY(!r1.called(1));
+ r1.reset();
QVERIFY(ret);
- ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
+ ret = QObject::disconnect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1);
QVERIFY(!ret);
// disconnect all signals from s from all slots from r1
- QObject::disconnect( s, 0, r1, 0 );
+ QObject::disconnect(&s, 0, &r1, 0);
- s->emitSignal2();
- s->emitSignal3();
- s->emitSignal4();
+ s.emitSignal2();
+ s.emitSignal3();
+ s.emitSignal4();
- QVERIFY(!r1->called(2));
- QVERIFY(!r1->called(3));
- QVERIFY(!r1->called(4));
- r1->reset();
+ QVERIFY(!r1.called(2));
+ QVERIFY(!r1.called(3));
+ QVERIFY(!r1.called(4));
+ r1.reset();
- connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
- connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot2 );
- connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 );
- connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot4 );
+ connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1);
+ connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot2);
+ connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot3);
+ connect(&s, &SenderObject::signal2, &r1, &ReceiverObject::slot4);
// disconnect s's signal1() from all slots of r1
- QObject::disconnect( s, &SenderObject::signal1, r1, 0 );
+ QObject::disconnect(&s, &SenderObject::signal1, &r1, 0);
- s->emitSignal1();
- s->emitSignal2();
+ s.emitSignal1();
+ s.emitSignal2();
- QVERIFY(!r1->called(1));
- QVERIFY(!r1->called(2));
- QVERIFY(!r1->called(3));
- QVERIFY(r1->called(4));
- r1->reset();
+ QVERIFY(!r1.called(1));
+ QVERIFY(!r1.called(2));
+ QVERIFY(!r1.called(3));
+ QVERIFY(r1.called(4));
+ r1.reset();
// make sure all is disconnected again
- QObject::disconnect( s, 0, r1, 0 );
+ QObject::disconnect(&s, 0, &r1, 0);
- connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
- connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 );
- connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 );
- connect( s, &SenderObject::signal2, r2, &ReceiverObject::slot2 );
- connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 );
- connect( s, &SenderObject::signal3, r2, &ReceiverObject::slot3 );
+ connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1);
+ connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot1);
+ connect(&s, &SenderObject::signal2, &r1, &ReceiverObject::slot2);
+ connect(&s, &SenderObject::signal2, &r2, &ReceiverObject::slot2);
+ connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot3);
+ connect(&s, &SenderObject::signal3, &r2, &ReceiverObject::slot3);
// disconnect signal1() from all receivers
- QObject::disconnect( s, &SenderObject::signal1, 0, 0 );
- s->emitSignal1();
- s->emitSignal2();
- s->emitSignal3();
+ QObject::disconnect(&s, &SenderObject::signal1, 0, 0);
+ s.emitSignal1();
+ s.emitSignal2();
+ s.emitSignal3();
- QVERIFY(!r1->called(1));
- QVERIFY(!r2->called(1));
- QVERIFY(r1->called(2));
- QVERIFY(r2->called(2));
- QVERIFY(r1->called(2));
- QVERIFY(r2->called(2));
+ QVERIFY(!r1.called(1));
+ QVERIFY(!r2.called(1));
+ QVERIFY(r1.called(2));
+ QVERIFY(r2.called(2));
+ QVERIFY(r1.called(2));
+ QVERIFY(r2.called(2));
- r1->reset();
- r2->reset();
+ r1.reset();
+ r2.reset();
// disconnect all signals of s from all receivers
- QObject::disconnect( s, 0, 0, 0 );
-
- QVERIFY(!r1->called(2));
- QVERIFY(!r2->called(2));
- QVERIFY(!r1->called(2));
- QVERIFY(!r2->called(2));
-
- delete r2;
- delete r1;
- delete s;
+ QObject::disconnect(&s, 0, 0, 0);
+ QVERIFY(!r1.called(2));
+ QVERIFY(!r2.called(2));
+ QVERIFY(!r1.called(2));
+ QVERIFY(!r2.called(2));
}
@@ -4756,35 +4734,32 @@ void tst_QObject::customTypesPointer()
void tst_QObject::connectCxx0x()
{
- SenderObject *s = new SenderObject;
- ReceiverObject *r1 = new ReceiverObject;
+ SenderObject s;
+ ReceiverObject r1;
- QObject::connect(s, &SenderObject::signal1, r1, &ReceiverObject::slot1);
- QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2);
- QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2);
- QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2);
+ QObject::connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1);
+ QObject::connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot2);
+ QObject::connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot2);
+ QObject::connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot2);
- r1->reset();
- QCOMPARE( r1->count_slot1, 0 );
- QCOMPARE( r1->count_slot2, 0 );
+ r1.reset();
+ QCOMPARE(r1.count_slot1, 0);
+ QCOMPARE(r1.count_slot2, 0);
- s->emitSignal1();
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 0 );
+ s.emitSignal1();
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 0);
- s->emitSignal3();
- QCOMPARE( r1->count_slot1, 1 );
- QCOMPARE( r1->count_slot2, 3 );
+ s.emitSignal3();
+ QCOMPARE(r1.count_slot1, 1);
+ QCOMPARE(r1.count_slot2, 3);
// connect signal to signal
- QObject::connect(s, &SenderObject::signal2, s, &SenderObject::signal1);
-
- r1->reset();
- s->emitSignal2();
- QCOMPARE( r1->count_slot1, 1 );
+ QObject::connect(&s, &SenderObject::signal2, &s, &SenderObject::signal1);
- delete s;
- delete r1;
+ r1.reset();
+ s.emitSignal2();
+ QCOMPARE(r1.count_slot1, 1);
}
int receivedCount;
@@ -4816,13 +4791,13 @@ class LotsOfSignalsAndSlots: public QObject
public slots:
void slot_v() {}
- void slot_v_noexcept() Q_DECL_NOTHROW {}
+ void slot_v_noexcept() noexcept {}
void slot_vi(int) {}
- void slot_vi_noexcept() Q_DECL_NOTHROW {}
+ void slot_vi_noexcept() noexcept {}
void slot_vii(int, int) {}
void slot_viii(int, int, int) {}
int slot_i() { return 0; }
- int slot_i_noexcept() Q_DECL_NOTHROW { return 0; }
+ int slot_i_noexcept() noexcept { return 0; }
int slot_ii(int) { return 0; }
int slot_iii(int, int) { return 0; }
int slot_iiii(int, int, int) { return 0; }
@@ -4836,18 +4811,18 @@ class LotsOfSignalsAndSlots: public QObject
void slot_vPFvvE(fptr) {}
void const_slot_v() const {};
- void const_slot_v_noexcept() const Q_DECL_NOTHROW {}
+ void const_slot_v_noexcept() const noexcept {}
void const_slot_vi(int) const {};
- void const_slot_vi_noexcept(int) const Q_DECL_NOTHROW {}
+ void const_slot_vi_noexcept(int) const noexcept {}
static void static_slot_v() {}
- static void static_slot_v_noexcept() Q_DECL_NOTHROW {}
+ static void static_slot_v_noexcept() noexcept {}
static void static_slot_vi(int) {}
- static void static_slot_vi_noexcept(int) Q_DECL_NOTHROW {}
+ static void static_slot_vi_noexcept(int) noexcept {}
static void static_slot_vii(int, int) {}
static void static_slot_viii(int, int, int) {}
static int static_slot_i() { return 0; }
- static int static_slot_i_noexcept() Q_DECL_NOTHROW { return 0; }
+ static int static_slot_i_noexcept() noexcept { return 0; }
static int static_slot_ii(int) { return 0; }
static int static_slot_iii(int, int) { return 0; }
static int static_slot_iiii(int, int, int) { return 0; }
@@ -5010,11 +4985,11 @@ void tst_QObject::connectCxx0xTypeMatching()
}
-void receiverFunction_noexcept() Q_DECL_NOTHROW {}
-struct Functor_noexcept { void operator()() Q_DECL_NOTHROW {} };
+void receiverFunction_noexcept() noexcept {}
+struct Functor_noexcept { void operator()() noexcept {} };
void tst_QObject::connectCxx17Noexcept()
{
- // this is about connecting signals to slots with the Q_DECL_NOTHROW qualifier
+ // this is about connecting signals to slots with the noexcept qualifier
// as semantics changed due to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html
typedef LotsOfSignalsAndSlots Foo;
Foo obj;
@@ -6004,7 +5979,7 @@ void ConnectToPrivateSlot::test(SenderObject* obj1) {
obj1->signal1();
QCOMPARE(d->receivedCount, 1);
QCOMPARE(d->receivedValue, QVariant());
- obj1->signal7(666, QLatin1Literal("_"));
+ obj1->signal7(666, QLatin1String("_"));
QCOMPARE(d->receivedCount, 2);
QCOMPARE(d->receivedValue, QVariant(666));
QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection));
@@ -6051,7 +6026,6 @@ void tst_QObject::connectFunctorArgDifference()
QStringListModel model;
connect(&model, &QStringListModel::rowsInserted, SlotFunctor());
-#if defined(Q_COMPILER_LAMBDA)
connect(&timer, &QTimer::timeout, [=](){});
connect(&timer, &QTimer::objectNameChanged, [=](const QString &){});
connect(qApp, &QCoreApplication::aboutToQuit, [=](){});
@@ -6059,7 +6033,6 @@ void tst_QObject::connectFunctorArgDifference()
connect(&timer, &QTimer::objectNameChanged, [=](){});
connect(&model, &QStringListModel::rowsInserted, [=](){});
connect(&model, &QStringListModel::rowsInserted, [=](const QModelIndex &){});
-#endif
QVERIFY(true);
}
@@ -6097,7 +6070,6 @@ void tst_QObject::connectFunctorQueued()
e.exec();
QCOMPARE(status, 2);
-#if defined(Q_COMPILER_LAMBDA)
status = 1;
connect(&obj, &SenderObject::signal1, this, [&status] { status = 2; }, Qt::QueuedConnection);
@@ -6105,7 +6077,6 @@ void tst_QObject::connectFunctorQueued()
QCOMPARE(status, 1);
e.exec();
QCOMPARE(status, 2);
-#endif
}
void tst_QObject::connectFunctorWithContext()
@@ -6139,7 +6110,6 @@ void tst_QObject::connectFunctorWithContext()
e.exec();
QCOMPARE(status, 2);
-#if defined(Q_COMPILER_LAMBDA)
status = 1;
connect(&obj, &SenderObject::signal1, this, [this, &status, &obj] { status = 2; QCOMPARE(sender(), &obj); }, Qt::QueuedConnection);
@@ -6147,7 +6117,6 @@ void tst_QObject::connectFunctorWithContext()
QCOMPARE(status, 1);
e.exec();
QCOMPARE(status, 2);
-#endif
// Free
context->deleteLater();
@@ -6457,7 +6426,7 @@ void connectFunctorOverload_impl(Signal signal, int expOverload, QList<QVariant>
void tst_QObject::connectFunctorOverloads()
{
-#if defined (Q_COMPILER_DECLTYPE) && defined (Q_COMPILER_VARIADIC_TEMPLATES)
+#if defined (Q_COMPILER_VARIADIC_TEMPLATES)
connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_ii, 1,
(QList<QVariant>() << 1 << 2));
connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_iiS, 1,
@@ -6631,7 +6600,6 @@ void tst_QObject::disconnectDoesNotLeakFunctor()
}
QCOMPARE(countedStructObjectsCount, 0);
{
-#if defined(Q_COMPILER_LAMBDA)
CountedStruct s;
QCOMPARE(countedStructObjectsCount, 1);
QTimer timer;
@@ -6641,7 +6609,6 @@ void tst_QObject::disconnectDoesNotLeakFunctor()
QCOMPARE(countedStructObjectsCount, 2);
QVERIFY(QObject::disconnect(c));
QCOMPARE(countedStructObjectsCount, 1);
-#endif // Q_COMPILER_LAMBDA
}
QCOMPARE(countedStructObjectsCount, 0);
}
@@ -6689,7 +6656,6 @@ void tst_QObject::contextDoesNotLeakFunctor()
}
QCOMPARE(countedStructObjectsCount, 0);
{
-#if defined(Q_COMPILER_LAMBDA)
CountedStruct s;
QEventLoop e;
ContextObject *context = new ContextObject;
@@ -6702,7 +6668,6 @@ void tst_QObject::contextDoesNotLeakFunctor()
context->deleteLater();
e.exec();
QCOMPARE(countedStructObjectsCount, 1);
-#endif // Q_COMPILER_LAMBDA
}
QCOMPARE(countedStructObjectsCount, 0);
}
@@ -7510,6 +7475,167 @@ void tst_QObject::nullReceiver()
QVERIFY(!connect(&o, SIGNAL(destroyed()), nullObj, SLOT(deleteLater())));
}
+void tst_QObject::functorReferencesConnection()
+{
+ countedStructObjectsCount = 0;
+ QMetaObject::Connection globalCon;
+ {
+ GetSenderObject obj;
+ CountedStruct counted(&obj);
+ QCOMPARE(countedStructObjectsCount, 1);
+ auto c = QSharedPointer<QMetaObject::Connection>::create();
+ int slotCalled = 0;
+ *c = connect(&obj, &GetSenderObject::aSignal, &obj, [&slotCalled, c, counted] {
+ QObject::disconnect(*c);
+ slotCalled++;
+ });
+ globalCon = *c; // keep a handle to the connection somewhere;
+ QVERIFY(globalCon);
+ QCOMPARE(countedStructObjectsCount, 2);
+ obj.triggerSignal();
+ QCOMPARE(slotCalled, 1);
+ QCOMPARE(countedStructObjectsCount, 1);
+ QVERIFY(!globalCon);
+ obj.triggerSignal();
+ QCOMPARE(slotCalled, 1);
+ QCOMPARE(countedStructObjectsCount, 1);
+ }
+ QCOMPARE(countedStructObjectsCount, 0);
+
+ {
+ GetSenderObject obj;
+ CountedStruct counted(&obj);
+ QCOMPARE(countedStructObjectsCount, 1);
+ auto *rec = new QObject;
+ int slotCalled = 0;
+ globalCon = connect(&obj, &GetSenderObject::aSignal, rec, [&slotCalled, rec, counted] {
+ delete rec;
+ slotCalled++;
+ });
+ QCOMPARE(countedStructObjectsCount, 2);
+ obj.triggerSignal();
+ QCOMPARE(slotCalled, 1);
+ QCOMPARE(countedStructObjectsCount, 1);
+ QVERIFY(!globalCon);
+ obj.triggerSignal();
+ QCOMPARE(slotCalled, 1);
+ QCOMPARE(countedStructObjectsCount, 1);
+ }
+ QCOMPARE(countedStructObjectsCount, 0);
+ {
+ int slotCalled = 0;
+ QEventLoop eventLoop;
+ {
+ // Sender will be destroyed when the labda goes out of scope lambda, so it will exit the event loop
+ auto sender = QSharedPointer<GetSenderObject>::create();
+ connect(sender.data(), &QObject::destroyed, &eventLoop, &QEventLoop::quit, Qt::QueuedConnection);
+ globalCon = connect(sender.data(), &GetSenderObject::aSignal, this, [&slotCalled, sender, &globalCon, this] {
+ ++slotCalled;
+ // This signal will be connected, but should never be called as the sender will be destroyed before
+ auto c2 = connect(sender.data(), &GetSenderObject::aSignal, [] { QFAIL("Should not be called"); });
+ QVERIFY(c2);
+ QVERIFY(QObject::disconnect(sender.data(), nullptr, this, nullptr));
+ QVERIFY(!globalCon); // this connection has been disconnected
+ QVERIFY(c2); // sender should not have been deleted yet, only after the emission is done
+ });
+ QMetaObject::invokeMethod(sender.data(), &GetSenderObject::triggerSignal, Qt::QueuedConnection);
+ QMetaObject::invokeMethod(sender.data(), &GetSenderObject::triggerSignal, Qt::QueuedConnection);
+ QMetaObject::invokeMethod(sender.data(), &GetSenderObject::triggerSignal, Qt::QueuedConnection);
+ }
+ eventLoop.exec();
+ QCOMPARE(slotCalled, 1);
+ }
+
+ {
+ GetSenderObject obj;
+ CountedStruct counted(&obj);
+ QCOMPARE(countedStructObjectsCount, 1);
+ auto c1 = QSharedPointer<QMetaObject::Connection>::create();
+ auto c2 = QSharedPointer<QMetaObject::Connection>::create();
+ int slot1Called = 0;
+ int slot3Called = 0;
+ *c1 = connect(&obj, &GetSenderObject::aSignal, &obj, [&slot1Called, &slot3Called, &obj, c1, c2, counted] {
+ auto c3 = connect(&obj, &GetSenderObject::aSignal, [counted, &slot3Called] {
+ slot3Called++;
+ });
+ // top-level + the one in the 3 others lambdas
+ QCOMPARE(countedStructObjectsCount, 4);
+ QObject::disconnect(*c2);
+ slot1Called++;
+ });
+ connect(&obj, &GetSenderObject::aSignal, [] {}); // just a dummy signal to fill the connection list
+ *c2 = connect(&obj, &GetSenderObject::aSignal, [counted, c2] { QFAIL("should not be called"); });
+ QVERIFY(c1 && c2);
+ QCOMPARE(countedStructObjectsCount, 3); // top-level + c1 + c2
+ obj.triggerSignal();
+ QCOMPARE(slot1Called, 1);
+ QCOMPARE(slot3Called, 0);
+ QCOMPARE(countedStructObjectsCount, 3); // top-level + c1 + c3
+ QObject::disconnect(*c1);
+ QCOMPARE(countedStructObjectsCount, 2); // top-level + c3
+ obj.triggerSignal();
+ QCOMPARE(slot1Called, 1);
+ QCOMPARE(slot3Called, 1);
+ }
+ {
+ struct DestroyEmit {
+ Q_DISABLE_COPY(DestroyEmit);
+ explicit DestroyEmit(SenderObject *obj) : obj(obj) {}
+ SenderObject *obj;
+ ~DestroyEmit() {
+ obj->emitSignal1();
+ }
+ };
+ SenderObject obj;
+ int slot1Called = 0;
+ int slot2Called = 0;
+ int slot3Called = 0;
+ auto c1 = QSharedPointer<QMetaObject::Connection>::create();
+ auto de = QSharedPointer<DestroyEmit>::create(&obj);
+ *c1 = connect(&obj, &SenderObject::signal1, [&slot1Called, &slot3Called, de, c1, &obj] {
+ connect(&obj, &SenderObject::signal1, [&slot3Called] { slot3Called++; });
+ slot1Called++;
+ QObject::disconnect(*c1);
+ });
+ de.clear();
+ connect(&obj, &SenderObject::signal1, [&slot2Called] { slot2Called++; });
+ obj.emitSignal1();
+ QCOMPARE(slot1Called, 1);
+ QCOMPARE(slot2Called, 2); // because also called from ~DestroyEmit
+ QCOMPARE(slot3Called, 1);
+ }
+}
+
+void tst_QObject::disconnectDisconnects()
+{
+ // Test what happens if the destructor of an functor slot also disconnects more slot;
+
+ SenderObject s1;
+ QScopedPointer<QObject> receiver(new QObject);
+
+ auto s2 = QSharedPointer<SenderObject>::create();
+ QPointer<QObject> s2_tracker = s2.data();
+ int count = 0;
+ connect(&s1, &SenderObject::signal1, [&count] { count++; }); // α
+ connect(&s1, &SenderObject::signal1, receiver.data(), [s2] { QFAIL("!!"); }); // β
+ connect(s2.data(), &SenderObject::signal1, receiver.data(), [] { QFAIL("!!"); });
+ connect(&s1, &SenderObject::signal2, receiver.data(), [] { QFAIL("!!"); });
+ connect(s2.data(), &SenderObject::signal2, receiver.data(), [] { QFAIL("!!"); });
+ connect(&s1, &SenderObject::signal1, [&count] { count++; }); // γ
+ connect(&s1, &SenderObject::signal2, [&count] { count++; }); // δ
+ s2.clear();
+
+ QVERIFY(s2_tracker);
+ receiver
+ .reset(); // this will delete the receiver which must also delete s2 as β is disconnected
+ QVERIFY(!s2_tracker);
+ // test that the data structures are still in order
+ s1.emitSignal1();
+ QCOMPARE(count, 2); // α + γ
+ s1.emitSignal2();
+ QCOMPARE(count, 3); // + δ
+}
+
// Test for QtPrivate::HasQ_OBJECT_Macro
Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro<tst_QObject>::Value);
Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro<SiblingDeleter>::Value);
diff --git a/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
index 55deb8eb1a..fa2d5e3723 100644
--- a/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
+++ b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
@@ -34,6 +34,7 @@
#include <QSharedMemory>
#include <QTest>
#include <QThread>
+#include <QElapsedTimer>
#define EXISTING_SHARE "existing"
#define EXISTING_SIZE 1024
@@ -645,7 +646,7 @@ public:
char *memory = (char*)producer.data();
memory[1] = '0';
- QTime timer;
+ QElapsedTimer timer;
timer.start();
int i = 0;
while (i < 5 && timer.elapsed() < 5000) {
diff --git a/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp b/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp
index fd18f00cd0..39b03ade61 100644
--- a/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp
+++ b/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp
@@ -66,7 +66,6 @@ void tst_QSignalBlocker::signalBlocking()
void tst_QSignalBlocker::moveAssignment()
{
-#ifdef Q_COMPILER_RVALUE_REFS
QObject o1, o2;
// move-assignment: both block other objects
@@ -157,10 +156,6 @@ void tst_QSignalBlocker::moveAssignment()
QVERIFY(!o1.signalsBlocked());
QVERIFY(!o2.signalsBlocked());
-
-#else
- QSKIP("This compiler is not in C++11 mode or doesn't support move semantics");
-#endif // Q_COMPILER_RVALUE_REFS
}
QTEST_MAIN(tst_QSignalBlocker)
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index 8d194dafc1..262dbea913 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -38,6 +38,7 @@
#include <qtimer.h>
#include <qthread.h>
+#include <qelapsedtimer.h>
#if defined Q_OS_UNIX
#include <unistd.h>
@@ -51,6 +52,8 @@ private slots:
void singleShotTimeout();
void timeout();
void remainingTime();
+ void remainingTimeInitial_data();
+ void remainingTimeInitial();
void remainingTimeDuringActivation_data();
void remainingTimeDuringActivation();
void basic_chrono();
@@ -71,7 +74,12 @@ private slots:
void recurseOnTimeoutAndStopTimer();
void singleShotToFunctors();
void singleShot_chrono();
+ void singleShot_static();
void crossThreadSingleShotToFunctor();
+ void timerOrder();
+ void timerOrder_data();
+ void timerOrderBackgroundThread();
+ void timerOrderBackgroundThread_data() { timerOrder_data(); }
void dontBlockEvents();
void postedEventsShouldNotStarveTimers();
@@ -133,14 +141,41 @@ void tst_QTimer::remainingTime()
QCOMPARE(timeoutSpy.count(), 0);
int remainingTime = timer.remainingTime();
- QVERIFY2(qAbs(remainingTime - 150) < 50, qPrintable(QString::number(remainingTime)));
+ QVERIFY2(remainingTime >= 50 && remainingTime <= 200, qPrintable(QString::number(remainingTime)));
QVERIFY(timeoutSpy.wait());
QCOMPARE(timeoutSpy.count(), 1);
// the timer is still active, so it should have a non-zero remaining time
remainingTime = timer.remainingTime();
- QVERIFY2(remainingTime > 150, qPrintable(QString::number(remainingTime)));
+ QVERIFY2(remainingTime >= 50, qPrintable(QString::number(remainingTime)));
+}
+
+void tst_QTimer::remainingTimeInitial_data()
+{
+ QTest::addColumn<int>("startTimeMs");
+ QTest::addColumn<Qt::TimerType>("timerType");
+
+ QTest::addRow("precise time 0ms") << 0 << Qt::PreciseTimer;
+ QTest::addRow("precise time 1ms") << 1 << Qt::PreciseTimer;
+ QTest::addRow("precise time 10ms") << 10 << Qt::PreciseTimer;
+
+ QTest::addRow("coarse time 0ms") << 0 << Qt::CoarseTimer;
+ QTest::addRow("coarse time 1ms") << 1 << Qt::CoarseTimer;
+ QTest::addRow("coarse time 10ms") << 10 << Qt::CoarseTimer;
+}
+
+void tst_QTimer::remainingTimeInitial()
+{
+ QFETCH(int, startTimeMs);
+ QFETCH(Qt::TimerType, timerType);
+
+ QTimer timer;
+ timer.setTimerType(timerType);
+ timer.start(startTimeMs);
+
+ const int rt = timer.remainingTime();
+ QVERIFY2(rt >= 0 && rt <= startTimeMs, qPrintable(QString::number(rt)));
}
void tst_QTimer::remainingTimeDuringActivation_data()
@@ -228,7 +263,7 @@ void tst_QTimer::basic_chrono()
QCOMPARE(timeoutSpy.count(), 0);
milliseconds rt = timer.remainingTimeAsDuration();
- QVERIFY2(qAbs(rt.count() - 150) < 50, qPrintable(QString::number(rt.count())));
+ QVERIFY2(rt.count() >= 50 && rt.count() <= 200, qPrintable(QString::number(rt.count())));
timeoutSpy.clear();
timer.setSingleShot(true);
@@ -492,7 +527,7 @@ public:
QBasicTimer m_timer;
int m_interval;
- QTime m_startedTime;
+ QElapsedTimer m_elapsedTimer;
QEventLoop eventLoop;
inline RestartedTimerFiresTooSoonObject()
@@ -504,7 +539,7 @@ public:
static int interval = 1000;
m_interval = interval;
- m_startedTime.start();
+ m_elapsedTimer.start();
m_timer.start(interval, this);
// alternate between single-shot and 1 sec
@@ -518,7 +553,7 @@ public:
m_timer.stop();
- int elapsed = m_startedTime.elapsed();
+ int elapsed = m_elapsedTimer.elapsed();
if (elapsed < m_interval / 2) {
// severely too early!
@@ -556,10 +591,10 @@ public:
public slots:
void longLastingSlot()
{
- // Don't use timers for this, because we are testing them.
- QTime time;
- time.start();
- while (time.elapsed() < 200) {
+ // Don't use QTimer for this, because we are testing it.
+ QElapsedTimer control;
+ control.start();
+ while (control.elapsed() < 200) {
for (int c = 0; c < 100000; c++) {} // Mindless looping.
}
if (++count >= 2) {
@@ -739,7 +774,7 @@ public:
quitEventLoop_noexcept();
}
- static void quitEventLoop_noexcept() Q_DECL_NOTHROW
+ static void quitEventLoop_noexcept() noexcept
{
QVERIFY(!_e.isNull());
_e->quit();
@@ -1004,5 +1039,121 @@ void tst_QTimer::callOnTimeout()
QVERIFY(!connection);
}
-QTEST_MAIN(tst_QTimer)
+class OrderHelper : public QObject
+{
+ Q_OBJECT
+public:
+ enum CallType
+ {
+ String,
+ PMF,
+ Functor,
+ FunctorNoCtx
+ };
+ Q_ENUM(CallType)
+ QVector<CallType> calls;
+
+ void triggerCall(CallType callType)
+ {
+ switch (callType)
+ {
+ case String:
+ QTimer::singleShot(0, this, SLOT(stringSlot()));
+ break;
+ case PMF:
+ QTimer::singleShot(0, this, &OrderHelper::pmfSlot);
+ break;
+ case Functor:
+ QTimer::singleShot(0, this, [this]() { functorSlot(); });
+ break;
+ case FunctorNoCtx:
+ QTimer::singleShot(0, [this]() { functorNoCtxSlot(); });
+ break;
+ }
+ }
+
+public slots:
+ void stringSlot() { calls << String; }
+ void pmfSlot() { calls << PMF; }
+ void functorSlot() { calls << Functor; }
+ void functorNoCtxSlot() { calls << FunctorNoCtx; }
+};
+
+Q_DECLARE_METATYPE(OrderHelper::CallType)
+
+void tst_QTimer::timerOrder()
+{
+ QFETCH(QVector<OrderHelper::CallType>, calls);
+
+ OrderHelper helper;
+
+ for (const auto call : calls)
+ helper.triggerCall(call);
+
+ QTRY_COMPARE(helper.calls, calls);
+}
+
+void tst_QTimer::timerOrder_data()
+{
+ QTest::addColumn<QVector<OrderHelper::CallType>>("calls");
+
+ QVector<OrderHelper::CallType> calls = {
+ OrderHelper::String, OrderHelper::PMF,
+ OrderHelper::Functor, OrderHelper::FunctorNoCtx
+ };
+ std::sort(calls.begin(), calls.end());
+
+ int permutation = 0;
+ do {
+ QTest::addRow("permutation=%d", permutation) << calls;
+ ++permutation;
+ } while (std::next_permutation(calls.begin(), calls.end()));
+}
+
+void tst_QTimer::timerOrderBackgroundThread()
+{
+#if !QT_CONFIG(cxx11_future)
+ QSKIP("This test requires QThread::create");
+#else
+ auto *thread = QThread::create([this]() { timerOrder(); });
+ thread->start();
+ QVERIFY(thread->wait());
+ delete thread;
+#endif
+}
+
+struct StaticSingleShotUser
+{
+ StaticSingleShotUser()
+ {
+ for (auto call : calls())
+ helper.triggerCall(call);
+ }
+ OrderHelper helper;
+
+ static QVector<OrderHelper::CallType> calls()
+ {
+ return {OrderHelper::String, OrderHelper::PMF,
+ OrderHelper::Functor, OrderHelper::FunctorNoCtx};
+ }
+};
+
+static StaticSingleShotUser *s_staticSingleShotUser = nullptr;
+
+void tst_QTimer::singleShot_static()
+{
+ QCoreApplication::processEvents();
+ QCOMPARE(s_staticSingleShotUser->helper.calls, s_staticSingleShotUser->calls());
+}
+
+// NOTE: to prevent any static initialization order fiasco, we handle QTEST_MAIN
+// ourselves, but instantiate the staticSingleShotUser before qApp
+
+int main(int argc, char *argv[])
+{
+ StaticSingleShotUser staticSingleShotUser;
+ s_staticSingleShotUser = &staticSingleShotUser;
+ QTEST_MAIN_IMPL(tst_QTimer)
+}
+
#include "tst_qtimer.moc"
diff --git a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
index 40a29c723c..b3efa97dbd 100644
--- a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
+++ b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
@@ -310,7 +310,7 @@ struct TranslateThread : public QThread
void run() {
bool startSignalled = false;
- while (terminate.load() == 0) {
+ while (terminate.loadRelaxed() == 0) {
const QString result = QCoreApplication::translate("QPushButton", "Hello %n world(s)!", 0, 0);
if (!startSignalled) {
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index 4da34c407e..c75e4ef035 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -59,12 +59,6 @@
class CustomNonQObject;
-#if defined(Q_COMPILER_CLASS_ENUM)
-#define ENUM_SIZE(X) : X
-#else
-#define ENUM_SIZE(X)
-#endif
-
class tst_QVariant : public QObject
{
Q_OBJECT
@@ -82,15 +76,15 @@ public:
enum MetaEnumTest_Enum1 : qint64 { MetaEnumTest_Enum1_value = 42, MetaEnumTest_Enum1_bigValue = (Q_INT64_C(1) << 33) + 50 };
Q_ENUM(MetaEnumTest_Enum1)
- enum MetaEnumTest_Enum3 ENUM_SIZE(qint64) { MetaEnumTest_Enum3_value = -47, MetaEnumTest_Enum3_bigValue = (Q_INT64_C(1) << 56) + 5, MetaEnumTest_Enum3_bigNegValue = -(Q_INT64_C(1) << 56) - 3 };
+ enum MetaEnumTest_Enum3 : qint64 { MetaEnumTest_Enum3_value = -47, MetaEnumTest_Enum3_bigValue = (Q_INT64_C(1) << 56) + 5, MetaEnumTest_Enum3_bigNegValue = -(Q_INT64_C(1) << 56) - 3 };
Q_ENUM(MetaEnumTest_Enum3)
- enum MetaEnumTest_Enum4 ENUM_SIZE(quint64) { MetaEnumTest_Enum4_value = 47, MetaEnumTest_Enum4_bigValue = (Q_INT64_C(1) << 52) + 45 };
+ enum MetaEnumTest_Enum4 : quint64 { MetaEnumTest_Enum4_value = 47, MetaEnumTest_Enum4_bigValue = (Q_INT64_C(1) << 52) + 45 };
Q_ENUM(MetaEnumTest_Enum4)
- enum MetaEnumTest_Enum5 ENUM_SIZE(uint) { MetaEnumTest_Enum5_value = 47 };
+ enum MetaEnumTest_Enum5 : uint { MetaEnumTest_Enum5_value = 47 };
Q_ENUM(MetaEnumTest_Enum5)
- enum MetaEnumTest_Enum6 ENUM_SIZE(uchar) { MetaEnumTest_Enum6_value = 47 };
+ enum MetaEnumTest_Enum6 : uchar { MetaEnumTest_Enum6_value = 47 };
Q_ENUM(MetaEnumTest_Enum6)
- enum MetaEnumTest_Enum8 ENUM_SIZE(short) { MetaEnumTest_Enum8_value = 47 };
+ enum MetaEnumTest_Enum8 : short { MetaEnumTest_Enum8_value = 47 };
Q_ENUM(MetaEnumTest_Enum8)
private slots:
@@ -385,8 +379,10 @@ void tst_QVariant::isNull()
QString str1;
QVariant var1( str1 );
QVERIFY( var1.isNull() );
-
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QVariant var2( QString::null );
+QT_WARNING_POP
QVERIFY( var2.isNull() );
QVariant var3( QString( "blah" ) );
@@ -406,9 +402,15 @@ void tst_QVariant::isNull()
QVERIFY( var6.isNull() );
QVariant varLL( (qlonglong)0 );
QVERIFY( !varLL.isNull() );
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QVariant var7(QString::null);
+QT_WARNING_POP
QVERIFY(var7.isNull());
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
var7 = QVariant::fromValue<QString>(QString::null);
+QT_WARNING_POP
QVERIFY(var7.isNull());
QVariant var8(QMetaType::Nullptr, nullptr);
@@ -1728,281 +1730,281 @@ void tst_QVariant::compareNumbers_data() const
QTest::newRow("bool3") << QVariant(false) << QVariant(true) << -1;
QTest::newRow("bool4") << QVariant(true) << QVariant(false) << +1;
- QTest::newRow("char1") << qVariantFromValue(char(0)) << qVariantFromValue(char(0)) << 0;
- QTest::newRow("char2") << qVariantFromValue(CHAR_MAX) << qVariantFromValue(CHAR_MAX) << 0;
- QTest::newRow("char3") << qVariantFromValue(CHAR_MIN) << qVariantFromValue(CHAR_MIN) << 0;
- QTest::newRow("char4") << qVariantFromValue(CHAR_MIN) << qVariantFromValue(CHAR_MAX) << -1;
- QTest::newRow("char5") << qVariantFromValue(CHAR_MAX) << qVariantFromValue(CHAR_MIN) << +1;
-
- QTest::newRow("schar1") << qVariantFromValue(schar(0)) << qVariantFromValue(schar(0)) << 0;
- QTest::newRow("schar2") << qVariantFromValue(SCHAR_MAX) << qVariantFromValue(SCHAR_MAX) << 0;
- QTest::newRow("schar3") << qVariantFromValue(SCHAR_MIN) << qVariantFromValue(SCHAR_MIN) << 0;
- QTest::newRow("schar4") << qVariantFromValue(SCHAR_MIN) << qVariantFromValue(SCHAR_MAX) << -1;
- QTest::newRow("schar5") << qVariantFromValue(SCHAR_MAX) << qVariantFromValue(SCHAR_MIN) << +1;
-
- QTest::newRow("uchar1") << qVariantFromValue(uchar(0)) << qVariantFromValue(uchar(0)) << 0;
- QTest::newRow("uchar2") << qVariantFromValue(UCHAR_MAX) << qVariantFromValue(UCHAR_MAX) << 0;
- QTest::newRow("uchar3") << qVariantFromValue(uchar(0)) << qVariantFromValue(UCHAR_MAX) << -1;
- QTest::newRow("uchar4") << qVariantFromValue(UCHAR_MAX) << qVariantFromValue(uchar(0)) << +1;
-
- QTest::newRow("short1") << qVariantFromValue(short(0)) << qVariantFromValue(short(0)) << 0;
- QTest::newRow("short2") << qVariantFromValue(SHRT_MAX) << qVariantFromValue(SHRT_MAX) << 0;
- QTest::newRow("short3") << qVariantFromValue(SHRT_MIN) << qVariantFromValue(SHRT_MIN) << 0;
- QTest::newRow("short4") << qVariantFromValue(SHRT_MIN) << qVariantFromValue(SHRT_MAX) << -1;
- QTest::newRow("short5") << qVariantFromValue(SHRT_MAX) << qVariantFromValue(SHRT_MIN) << +1;
-
- QTest::newRow("ushort1") << qVariantFromValue(ushort(0)) << qVariantFromValue(ushort(0)) << 0;
- QTest::newRow("ushort2") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(USHRT_MAX) << 0;
- QTest::newRow("ushort3") << qVariantFromValue(ushort(0)) << qVariantFromValue(USHRT_MAX) << -1;
- QTest::newRow("ushort4") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(ushort(0)) << +1;
-
- QTest::newRow("int1") << qVariantFromValue(int(0)) << qVariantFromValue(int(0)) << 0;
- QTest::newRow("int2") << qVariantFromValue(INT_MAX) << qVariantFromValue(INT_MAX) << 0;
- QTest::newRow("int3") << qVariantFromValue(INT_MIN) << qVariantFromValue(INT_MIN) << 0;
- QTest::newRow("int4") << qVariantFromValue(INT_MIN) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("int5") << qVariantFromValue(INT_MAX) << qVariantFromValue(INT_MIN) << +1;
-
- QTest::newRow("uint1") << qVariantFromValue(uint(0)) << qVariantFromValue(uint(0)) << 0;
- QTest::newRow("uint2") << qVariantFromValue(UINT_MAX) << qVariantFromValue(UINT_MAX) << 0;
- QTest::newRow("uint3") << qVariantFromValue(uint(0)) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("uint4") << qVariantFromValue(UINT_MAX) << qVariantFromValue(uint(0)) << +1;
-
- QTest::newRow("long1") << qVariantFromValue(long(0)) << qVariantFromValue(long(0)) << 0;
- QTest::newRow("long2") << qVariantFromValue(LONG_MAX) << qVariantFromValue(LONG_MAX) << 0;
- QTest::newRow("long3") << qVariantFromValue(LONG_MIN) << qVariantFromValue(LONG_MIN) << 0;
- QTest::newRow("long4") << qVariantFromValue(LONG_MIN) << qVariantFromValue(LONG_MAX) << -1;
- QTest::newRow("long5") << qVariantFromValue(LONG_MAX) << qVariantFromValue(LONG_MIN) << +1;
-
- QTest::newRow("ulong1") << qVariantFromValue(ulong(0)) << qVariantFromValue(ulong(0)) << 0;
- QTest::newRow("ulong2") << qVariantFromValue(ULONG_MAX) << qVariantFromValue(ULONG_MAX) << 0;
- QTest::newRow("ulong3") << qVariantFromValue(ulong(0)) << qVariantFromValue(ULONG_MAX) << -1;
- QTest::newRow("ulong4") << qVariantFromValue(ULONG_MAX) << qVariantFromValue(ulong(0)) << +1;
-
- QTest::newRow("llong1") << qVariantFromValue(qlonglong(0)) << qVariantFromValue(qlonglong(0)) << 0;
- QTest::newRow("llong2") << qVariantFromValue(LLONG_MAX) << qVariantFromValue(LLONG_MAX) << 0;
- QTest::newRow("llong3") << qVariantFromValue(LLONG_MIN) << qVariantFromValue(LLONG_MIN) << 0;
- QTest::newRow("llong4") << qVariantFromValue(LLONG_MIN) << qVariantFromValue(LLONG_MAX) << -1;
- QTest::newRow("llong5") << qVariantFromValue(LLONG_MAX) << qVariantFromValue(LLONG_MIN) << +1;
-
- QTest::newRow("ullong1") << qVariantFromValue(qulonglong(0)) << qVariantFromValue(qulonglong(0)) << 0;
- QTest::newRow("ullong2") << qVariantFromValue(ULLONG_MAX) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("ullong3") << qVariantFromValue(qulonglong(0)) << qVariantFromValue(ULLONG_MAX) << -1;
- QTest::newRow("ullong4") << qVariantFromValue(ULLONG_MAX) << qVariantFromValue(qulonglong(0)) << +1;
-
- QTest::newRow("float1") << qVariantFromValue(0.f) << qVariantFromValue(0.f) << 0;
- QTest::newRow("float2") << qVariantFromValue(-1.f) << qVariantFromValue(0.f) << -1;
- QTest::newRow("float3") << qVariantFromValue(0.f) << qVariantFromValue(-1.f) << +1;
- QTest::newRow("float4") << qVariantFromValue(-float(qInf())) << qVariantFromValue(0.f) << -1;
- QTest::newRow("float5") << qVariantFromValue(0.f) << qVariantFromValue(-float(qInf())) << +1;
- QTest::newRow("float6") << qVariantFromValue(-float(qInf())) << qVariantFromValue(-float(qInf())) << 0;
- QTest::newRow("float7") << qVariantFromValue(float(qInf())) << qVariantFromValue(float(qInf())) << 0;
-
- QTest::newRow("double1") << qVariantFromValue(0.) << qVariantFromValue(0.) << 0;
- QTest::newRow("double2") << qVariantFromValue(-1.) << qVariantFromValue(0.) << -1;
- QTest::newRow("double3") << qVariantFromValue(0.) << qVariantFromValue(-1.) << +1;
- QTest::newRow("double4") << qVariantFromValue(-qInf()) << qVariantFromValue(0.) << -1;
- QTest::newRow("double5") << qVariantFromValue(0.) << qVariantFromValue(-qInf()) << +1;
- QTest::newRow("double6") << qVariantFromValue(-double(qInf())) << qVariantFromValue(-qInf()) << 0;
- QTest::newRow("double7") << qVariantFromValue(qInf()) << qVariantFromValue(qInf()) << 0;
- QTest::newRow("double8") << qVariantFromValue(-qInf()) << qVariantFromValue(qInf()) << -1;
- QTest::newRow("double9") << qVariantFromValue(qQNaN()) << qVariantFromValue(0.) << INT_MAX;
- QTest::newRow("double10") << qVariantFromValue(0.) << qVariantFromValue(qQNaN()) << INT_MAX;
- QTest::newRow("double11") << qVariantFromValue(qQNaN()) << qVariantFromValue(qQNaN()) << INT_MAX;
+ QTest::newRow("char1") << QVariant::fromValue(char(0)) << QVariant::fromValue(char(0)) << 0;
+ QTest::newRow("char2") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(CHAR_MAX) << 0;
+ QTest::newRow("char3") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(CHAR_MIN) << 0;
+ QTest::newRow("char4") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(CHAR_MAX) << -1;
+ QTest::newRow("char5") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(CHAR_MIN) << +1;
+
+ QTest::newRow("schar1") << QVariant::fromValue(schar(0)) << QVariant::fromValue(schar(0)) << 0;
+ QTest::newRow("schar2") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(SCHAR_MAX) << 0;
+ QTest::newRow("schar3") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(SCHAR_MIN) << 0;
+ QTest::newRow("schar4") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(SCHAR_MAX) << -1;
+ QTest::newRow("schar5") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(SCHAR_MIN) << +1;
+
+ QTest::newRow("uchar1") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(uchar(0)) << 0;
+ QTest::newRow("uchar2") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(UCHAR_MAX) << 0;
+ QTest::newRow("uchar3") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(UCHAR_MAX) << -1;
+ QTest::newRow("uchar4") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(uchar(0)) << +1;
+
+ QTest::newRow("short1") << QVariant::fromValue(short(0)) << QVariant::fromValue(short(0)) << 0;
+ QTest::newRow("short2") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(SHRT_MAX) << 0;
+ QTest::newRow("short3") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(SHRT_MIN) << 0;
+ QTest::newRow("short4") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(SHRT_MAX) << -1;
+ QTest::newRow("short5") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(SHRT_MIN) << +1;
+
+ QTest::newRow("ushort1") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(ushort(0)) << 0;
+ QTest::newRow("ushort2") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(USHRT_MAX) << 0;
+ QTest::newRow("ushort3") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(USHRT_MAX) << -1;
+ QTest::newRow("ushort4") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(ushort(0)) << +1;
+
+ QTest::newRow("int1") << QVariant::fromValue(int(0)) << QVariant::fromValue(int(0)) << 0;
+ QTest::newRow("int2") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(INT_MAX) << 0;
+ QTest::newRow("int3") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(INT_MIN) << 0;
+ QTest::newRow("int4") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("int5") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(INT_MIN) << +1;
+
+ QTest::newRow("uint1") << QVariant::fromValue(uint(0)) << QVariant::fromValue(uint(0)) << 0;
+ QTest::newRow("uint2") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(UINT_MAX) << 0;
+ QTest::newRow("uint3") << QVariant::fromValue(uint(0)) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("uint4") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(uint(0)) << +1;
+
+ QTest::newRow("long1") << QVariant::fromValue(long(0)) << QVariant::fromValue(long(0)) << 0;
+ QTest::newRow("long2") << QVariant::fromValue(LONG_MAX) << QVariant::fromValue(LONG_MAX) << 0;
+ QTest::newRow("long3") << QVariant::fromValue(LONG_MIN) << QVariant::fromValue(LONG_MIN) << 0;
+ QTest::newRow("long4") << QVariant::fromValue(LONG_MIN) << QVariant::fromValue(LONG_MAX) << -1;
+ QTest::newRow("long5") << QVariant::fromValue(LONG_MAX) << QVariant::fromValue(LONG_MIN) << +1;
+
+ QTest::newRow("ulong1") << QVariant::fromValue(ulong(0)) << QVariant::fromValue(ulong(0)) << 0;
+ QTest::newRow("ulong2") << QVariant::fromValue(ULONG_MAX) << QVariant::fromValue(ULONG_MAX) << 0;
+ QTest::newRow("ulong3") << QVariant::fromValue(ulong(0)) << QVariant::fromValue(ULONG_MAX) << -1;
+ QTest::newRow("ulong4") << QVariant::fromValue(ULONG_MAX) << QVariant::fromValue(ulong(0)) << +1;
+
+ QTest::newRow("llong1") << QVariant::fromValue(qlonglong(0)) << QVariant::fromValue(qlonglong(0)) << 0;
+ QTest::newRow("llong2") << QVariant::fromValue(LLONG_MAX) << QVariant::fromValue(LLONG_MAX) << 0;
+ QTest::newRow("llong3") << QVariant::fromValue(LLONG_MIN) << QVariant::fromValue(LLONG_MIN) << 0;
+ QTest::newRow("llong4") << QVariant::fromValue(LLONG_MIN) << QVariant::fromValue(LLONG_MAX) << -1;
+ QTest::newRow("llong5") << QVariant::fromValue(LLONG_MAX) << QVariant::fromValue(LLONG_MIN) << +1;
+
+ QTest::newRow("ullong1") << QVariant::fromValue(qulonglong(0)) << QVariant::fromValue(qulonglong(0)) << 0;
+ QTest::newRow("ullong2") << QVariant::fromValue(ULLONG_MAX) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("ullong3") << QVariant::fromValue(qulonglong(0)) << QVariant::fromValue(ULLONG_MAX) << -1;
+ QTest::newRow("ullong4") << QVariant::fromValue(ULLONG_MAX) << QVariant::fromValue(qulonglong(0)) << +1;
+
+ QTest::newRow("float1") << QVariant::fromValue(0.f) << QVariant::fromValue(0.f) << 0;
+ QTest::newRow("float2") << QVariant::fromValue(-1.f) << QVariant::fromValue(0.f) << -1;
+ QTest::newRow("float3") << QVariant::fromValue(0.f) << QVariant::fromValue(-1.f) << +1;
+ QTest::newRow("float4") << QVariant::fromValue(-float(qInf())) << QVariant::fromValue(0.f) << -1;
+ QTest::newRow("float5") << QVariant::fromValue(0.f) << QVariant::fromValue(-float(qInf())) << +1;
+ QTest::newRow("float6") << QVariant::fromValue(-float(qInf())) << QVariant::fromValue(-float(qInf())) << 0;
+ QTest::newRow("float7") << QVariant::fromValue(float(qInf())) << QVariant::fromValue(float(qInf())) << 0;
+
+ QTest::newRow("double1") << QVariant::fromValue(0.) << QVariant::fromValue(0.) << 0;
+ QTest::newRow("double2") << QVariant::fromValue(-1.) << QVariant::fromValue(0.) << -1;
+ QTest::newRow("double3") << QVariant::fromValue(0.) << QVariant::fromValue(-1.) << +1;
+ QTest::newRow("double4") << QVariant::fromValue(-qInf()) << QVariant::fromValue(0.) << -1;
+ QTest::newRow("double5") << QVariant::fromValue(0.) << QVariant::fromValue(-qInf()) << +1;
+ QTest::newRow("double6") << QVariant::fromValue(-double(qInf())) << QVariant::fromValue(-qInf()) << 0;
+ QTest::newRow("double7") << QVariant::fromValue(qInf()) << QVariant::fromValue(qInf()) << 0;
+ QTest::newRow("double8") << QVariant::fromValue(-qInf()) << QVariant::fromValue(qInf()) << -1;
+ QTest::newRow("double9") << QVariant::fromValue(qQNaN()) << QVariant::fromValue(0.) << INT_MAX;
+ QTest::newRow("double10") << QVariant::fromValue(0.) << QVariant::fromValue(qQNaN()) << INT_MAX;
+ QTest::newRow("double11") << QVariant::fromValue(qQNaN()) << QVariant::fromValue(qQNaN()) << INT_MAX;
// mixed comparisons
// fp + fp
- QTest::newRow("float+double1") << qVariantFromValue(0.f) << qVariantFromValue(0.) << 0;
- QTest::newRow("float+double2") << qVariantFromValue(-1.f) << qVariantFromValue(0.) << -1;
- QTest::newRow("float+double3") << qVariantFromValue(0.f) << qVariantFromValue(-1.) << +1;
- QTest::newRow("float+double4") << qVariantFromValue(-float(qInf())) << qVariantFromValue(0.) << -1;
- QTest::newRow("float+double5") << qVariantFromValue(0.f) << qVariantFromValue(-qInf()) << +1;
- QTest::newRow("float+double6") << qVariantFromValue(-float(qInf())) << qVariantFromValue(-qInf()) << 0;
- QTest::newRow("float+double7") << qVariantFromValue(float(qInf())) << qVariantFromValue(qInf()) << 0;
- QTest::newRow("float+double8") << qVariantFromValue(-float(qInf())) << qVariantFromValue(qInf()) << -1;
- QTest::newRow("float+double9") << qVariantFromValue(qQNaN()) << qVariantFromValue(0.) << INT_MAX;
- QTest::newRow("float+double10") << qVariantFromValue(0.) << qVariantFromValue(qQNaN()) << INT_MAX;
- QTest::newRow("float+double11") << qVariantFromValue(qQNaN()) << qVariantFromValue(qQNaN()) << INT_MAX;
+ QTest::newRow("float+double1") << QVariant::fromValue(0.f) << QVariant::fromValue(0.) << 0;
+ QTest::newRow("float+double2") << QVariant::fromValue(-1.f) << QVariant::fromValue(0.) << -1;
+ QTest::newRow("float+double3") << QVariant::fromValue(0.f) << QVariant::fromValue(-1.) << +1;
+ QTest::newRow("float+double4") << QVariant::fromValue(-float(qInf())) << QVariant::fromValue(0.) << -1;
+ QTest::newRow("float+double5") << QVariant::fromValue(0.f) << QVariant::fromValue(-qInf()) << +1;
+ QTest::newRow("float+double6") << QVariant::fromValue(-float(qInf())) << QVariant::fromValue(-qInf()) << 0;
+ QTest::newRow("float+double7") << QVariant::fromValue(float(qInf())) << QVariant::fromValue(qInf()) << 0;
+ QTest::newRow("float+double8") << QVariant::fromValue(-float(qInf())) << QVariant::fromValue(qInf()) << -1;
+ QTest::newRow("float+double9") << QVariant::fromValue(qQNaN()) << QVariant::fromValue(0.) << INT_MAX;
+ QTest::newRow("float+double10") << QVariant::fromValue(0.) << QVariant::fromValue(qQNaN()) << INT_MAX;
+ QTest::newRow("float+double11") << QVariant::fromValue(qQNaN()) << QVariant::fromValue(qQNaN()) << INT_MAX;
// fp + int
- QTest::newRow("float+int1") << qVariantFromValue(0.f) << qVariantFromValue(0) << 0;
- QTest::newRow("double+int1") << qVariantFromValue(0.) << qVariantFromValue(0) << 0;
- QTest::newRow("float+int2") << qVariantFromValue(-1.f) << qVariantFromValue(0) << -1;
- QTest::newRow("double+int2") << qVariantFromValue(-1.) << qVariantFromValue(0) << -1;
- QTest::newRow("float+int3") << qVariantFromValue(0.f) << qVariantFromValue(-1) << +1;
- QTest::newRow("double+int3") << qVariantFromValue(0.) << qVariantFromValue(-1) << +1;
- QTest::newRow("float+int4") << qVariantFromValue(1.5f) << qVariantFromValue(1) << +1;
- QTest::newRow("double+int4") << qVariantFromValue(1.5) << qVariantFromValue(1) << +1;
- QTest::newRow("double+int5") << qVariantFromValue(qInf()) << qVariantFromValue(1) << +1;
+ QTest::newRow("float+int1") << QVariant::fromValue(0.f) << QVariant::fromValue(0) << 0;
+ QTest::newRow("double+int1") << QVariant::fromValue(0.) << QVariant::fromValue(0) << 0;
+ QTest::newRow("float+int2") << QVariant::fromValue(-1.f) << QVariant::fromValue(0) << -1;
+ QTest::newRow("double+int2") << QVariant::fromValue(-1.) << QVariant::fromValue(0) << -1;
+ QTest::newRow("float+int3") << QVariant::fromValue(0.f) << QVariant::fromValue(-1) << +1;
+ QTest::newRow("double+int3") << QVariant::fromValue(0.) << QVariant::fromValue(-1) << +1;
+ QTest::newRow("float+int4") << QVariant::fromValue(1.5f) << QVariant::fromValue(1) << +1;
+ QTest::newRow("double+int4") << QVariant::fromValue(1.5) << QVariant::fromValue(1) << +1;
+ QTest::newRow("double+int5") << QVariant::fromValue(qInf()) << QVariant::fromValue(1) << +1;
// fp + uint
- QTest::newRow("float+uint1") << qVariantFromValue(0.f) << qVariantFromValue(0U) << 0;
- QTest::newRow("double+uint1") << qVariantFromValue(0.) << qVariantFromValue(0U) << 0;
- QTest::newRow("float+uint2") << qVariantFromValue(-1.f) << qVariantFromValue(0U) << -1;
- QTest::newRow("double+uint2") << qVariantFromValue(-1.) << qVariantFromValue(0U) << -1;
- QTest::newRow("float+uint3") << qVariantFromValue(0.f) << qVariantFromValue(1U) << -1;
- QTest::newRow("double+uint3") << qVariantFromValue(0.) << qVariantFromValue(1U) << -1;
- QTest::newRow("float+uint4") << qVariantFromValue(1.5f) << qVariantFromValue(1U) << +1;
- QTest::newRow("double+uint4") << qVariantFromValue(1.5) << qVariantFromValue(1U) << +1;
+ QTest::newRow("float+uint1") << QVariant::fromValue(0.f) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("double+uint1") << QVariant::fromValue(0.) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("float+uint2") << QVariant::fromValue(-1.f) << QVariant::fromValue(0U) << -1;
+ QTest::newRow("double+uint2") << QVariant::fromValue(-1.) << QVariant::fromValue(0U) << -1;
+ QTest::newRow("float+uint3") << QVariant::fromValue(0.f) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("double+uint3") << QVariant::fromValue(0.) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("float+uint4") << QVariant::fromValue(1.5f) << QVariant::fromValue(1U) << +1;
+ QTest::newRow("double+uint4") << QVariant::fromValue(1.5) << QVariant::fromValue(1U) << +1;
// lower ranked + int
- QTest::newRow("bool+int1") << qVariantFromValue(false) << qVariantFromValue(0) << 0;
- QTest::newRow("bool+int2") << qVariantFromValue(false) << qVariantFromValue(1) << -1;
- QTest::newRow("bool+int3") << qVariantFromValue(true) << qVariantFromValue(0) << +1;
- QTest::newRow("bool+int4") << qVariantFromValue(true) << qVariantFromValue(1) << 0;
- QTest::newRow("bool+int5") << qVariantFromValue(true) << qVariantFromValue(2) << -1;
-
- QTest::newRow("char+int1") << qVariantFromValue(char(0)) << qVariantFromValue(0) << 0;
- QTest::newRow("char+int2") << qVariantFromValue(char(0)) << qVariantFromValue(1) << -1;
- QTest::newRow("char+int3") << qVariantFromValue(char(1)) << qVariantFromValue(0) << +1;
- QTest::newRow("char+int4") << qVariantFromValue(char(1)) << qVariantFromValue(1) << 0;
+ QTest::newRow("bool+int1") << QVariant::fromValue(false) << QVariant::fromValue(0) << 0;
+ QTest::newRow("bool+int2") << QVariant::fromValue(false) << QVariant::fromValue(1) << -1;
+ QTest::newRow("bool+int3") << QVariant::fromValue(true) << QVariant::fromValue(0) << +1;
+ QTest::newRow("bool+int4") << QVariant::fromValue(true) << QVariant::fromValue(1) << 0;
+ QTest::newRow("bool+int5") << QVariant::fromValue(true) << QVariant::fromValue(2) << -1;
+
+ QTest::newRow("char+int1") << QVariant::fromValue(char(0)) << QVariant::fromValue(0) << 0;
+ QTest::newRow("char+int2") << QVariant::fromValue(char(0)) << QVariant::fromValue(1) << -1;
+ QTest::newRow("char+int3") << QVariant::fromValue(char(1)) << QVariant::fromValue(0) << +1;
+ QTest::newRow("char+int4") << QVariant::fromValue(char(1)) << QVariant::fromValue(1) << 0;
if (std::numeric_limits<char>::is_signed) {
- QTest::newRow("char+int5") << qVariantFromValue(char(-1)) << qVariantFromValue(0) << -1;
- QTest::newRow("char+int6") << qVariantFromValue(char(-1)) << qVariantFromValue(-1) << 0;
- }
-
- QTest::newRow("schar+int1") << qVariantFromValue(schar(0)) << qVariantFromValue(0) << 0;
- QTest::newRow("schar+int2") << qVariantFromValue(schar(0)) << qVariantFromValue(1) << -1;
- QTest::newRow("schar+int3") << qVariantFromValue(schar(1)) << qVariantFromValue(0) << +1;
- QTest::newRow("schar+int4") << qVariantFromValue(schar(1)) << qVariantFromValue(1) << 0;
- QTest::newRow("schar+int5") << qVariantFromValue(schar(-1)) << qVariantFromValue(0) << -1;
- QTest::newRow("schar+int6") << qVariantFromValue(schar(-1)) << qVariantFromValue(-1) << 0;
-
- QTest::newRow("uchar+int1") << qVariantFromValue(uchar(0)) << qVariantFromValue(0) << 0;
- QTest::newRow("uchar+int2") << qVariantFromValue(uchar(0)) << qVariantFromValue(1) << -1;
- QTest::newRow("uchar+int3") << qVariantFromValue(uchar(1)) << qVariantFromValue(0) << +1;
- QTest::newRow("uchar+int4") << qVariantFromValue(uchar(1)) << qVariantFromValue(1) << 0;
-
- QTest::newRow("short+int1") << qVariantFromValue(short(0)) << qVariantFromValue(0) << 0;
- QTest::newRow("short+int2") << qVariantFromValue(short(0)) << qVariantFromValue(1) << -1;
- QTest::newRow("short+int3") << qVariantFromValue(short(1)) << qVariantFromValue(0) << +1;
- QTest::newRow("short+int4") << qVariantFromValue(short(1)) << qVariantFromValue(1) << 0;
- QTest::newRow("short+int5") << qVariantFromValue(short(-1)) << qVariantFromValue(0) << -1;
- QTest::newRow("short+int6") << qVariantFromValue(short(-1)) << qVariantFromValue(-1) << 0;
-
- QTest::newRow("ushort+int1") << qVariantFromValue(ushort(0)) << qVariantFromValue(0) << 0;
- QTest::newRow("ushort+int2") << qVariantFromValue(ushort(0)) << qVariantFromValue(1) << -1;
- QTest::newRow("ushort+int3") << qVariantFromValue(ushort(1)) << qVariantFromValue(0) << +1;
- QTest::newRow("ushort+int4") << qVariantFromValue(ushort(1)) << qVariantFromValue(1) << 0;
+ QTest::newRow("char+int5") << QVariant::fromValue(char(-1)) << QVariant::fromValue(0) << -1;
+ QTest::newRow("char+int6") << QVariant::fromValue(char(-1)) << QVariant::fromValue(-1) << 0;
+ }
+
+ QTest::newRow("schar+int1") << QVariant::fromValue(schar(0)) << QVariant::fromValue(0) << 0;
+ QTest::newRow("schar+int2") << QVariant::fromValue(schar(0)) << QVariant::fromValue(1) << -1;
+ QTest::newRow("schar+int3") << QVariant::fromValue(schar(1)) << QVariant::fromValue(0) << +1;
+ QTest::newRow("schar+int4") << QVariant::fromValue(schar(1)) << QVariant::fromValue(1) << 0;
+ QTest::newRow("schar+int5") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(0) << -1;
+ QTest::newRow("schar+int6") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(-1) << 0;
+
+ QTest::newRow("uchar+int1") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(0) << 0;
+ QTest::newRow("uchar+int2") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(1) << -1;
+ QTest::newRow("uchar+int3") << QVariant::fromValue(uchar(1)) << QVariant::fromValue(0) << +1;
+ QTest::newRow("uchar+int4") << QVariant::fromValue(uchar(1)) << QVariant::fromValue(1) << 0;
+
+ QTest::newRow("short+int1") << QVariant::fromValue(short(0)) << QVariant::fromValue(0) << 0;
+ QTest::newRow("short+int2") << QVariant::fromValue(short(0)) << QVariant::fromValue(1) << -1;
+ QTest::newRow("short+int3") << QVariant::fromValue(short(1)) << QVariant::fromValue(0) << +1;
+ QTest::newRow("short+int4") << QVariant::fromValue(short(1)) << QVariant::fromValue(1) << 0;
+ QTest::newRow("short+int5") << QVariant::fromValue(short(-1)) << QVariant::fromValue(0) << -1;
+ QTest::newRow("short+int6") << QVariant::fromValue(short(-1)) << QVariant::fromValue(-1) << 0;
+
+ QTest::newRow("ushort+int1") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(0) << 0;
+ QTest::newRow("ushort+int2") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(1) << -1;
+ QTest::newRow("ushort+int3") << QVariant::fromValue(ushort(1)) << QVariant::fromValue(0) << +1;
+ QTest::newRow("ushort+int4") << QVariant::fromValue(ushort(1)) << QVariant::fromValue(1) << 0;
// lower ranked + uint (without sign change)
- QTest::newRow("bool+uint1") << qVariantFromValue(false) << qVariantFromValue(0U) << 0;
- QTest::newRow("bool+uint2") << qVariantFromValue(false) << qVariantFromValue(1U) << -1;
- QTest::newRow("bool+uint3") << qVariantFromValue(true) << qVariantFromValue(0U) << +1;
- QTest::newRow("bool+uint4") << qVariantFromValue(true) << qVariantFromValue(1U) << 0;
- QTest::newRow("bool+uint5") << qVariantFromValue(true) << qVariantFromValue(2U) << -1;
-
- QTest::newRow("char+uint1") << qVariantFromValue(char(0)) << qVariantFromValue(0U) << 0;
- QTest::newRow("char+uint2") << qVariantFromValue(char(0)) << qVariantFromValue(1U) << -1;
- QTest::newRow("char+uint3") << qVariantFromValue(char(1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("char+uint4") << qVariantFromValue(char(1)) << qVariantFromValue(1U) << 0;
-
- QTest::newRow("schar+uint1") << qVariantFromValue(schar(0)) << qVariantFromValue(0U) << 0;
- QTest::newRow("schar+uint2") << qVariantFromValue(schar(0)) << qVariantFromValue(1U) << -1;
- QTest::newRow("schar+uint3") << qVariantFromValue(schar(1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("schar+uint4") << qVariantFromValue(schar(1)) << qVariantFromValue(1U) << 0;
-
- QTest::newRow("uchar+uint1") << qVariantFromValue(uchar(0)) << qVariantFromValue(0U) << 0;
- QTest::newRow("uchar+uint2") << qVariantFromValue(uchar(0)) << qVariantFromValue(1U) << -1;
- QTest::newRow("uchar+uint3") << qVariantFromValue(uchar(1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("uchar+uint4") << qVariantFromValue(uchar(1)) << qVariantFromValue(1U) << 0;
-
- QTest::newRow("short+uint1") << qVariantFromValue(short(0)) << qVariantFromValue(0U) << 0;
- QTest::newRow("short+uint2") << qVariantFromValue(short(0)) << qVariantFromValue(1U) << -1;
- QTest::newRow("short+uint3") << qVariantFromValue(short(1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("short+uint4") << qVariantFromValue(short(1)) << qVariantFromValue(1U) << 0;
-
- QTest::newRow("ushort+uint1") << qVariantFromValue(ushort(0)) << qVariantFromValue(0U) << 0;
- QTest::newRow("ushort+uint2") << qVariantFromValue(ushort(0)) << qVariantFromValue(1U) << -1;
- QTest::newRow("ushort+uint3") << qVariantFromValue(ushort(1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("ushort+uint4") << qVariantFromValue(ushort(1)) << qVariantFromValue(1U) << 0;
+ QTest::newRow("bool+uint1") << QVariant::fromValue(false) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("bool+uint2") << QVariant::fromValue(false) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("bool+uint3") << QVariant::fromValue(true) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("bool+uint4") << QVariant::fromValue(true) << QVariant::fromValue(1U) << 0;
+ QTest::newRow("bool+uint5") << QVariant::fromValue(true) << QVariant::fromValue(2U) << -1;
+
+ QTest::newRow("char+uint1") << QVariant::fromValue(char(0)) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("char+uint2") << QVariant::fromValue(char(0)) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("char+uint3") << QVariant::fromValue(char(1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("char+uint4") << QVariant::fromValue(char(1)) << QVariant::fromValue(1U) << 0;
+
+ QTest::newRow("schar+uint1") << QVariant::fromValue(schar(0)) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("schar+uint2") << QVariant::fromValue(schar(0)) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("schar+uint3") << QVariant::fromValue(schar(1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("schar+uint4") << QVariant::fromValue(schar(1)) << QVariant::fromValue(1U) << 0;
+
+ QTest::newRow("uchar+uint1") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("uchar+uint2") << QVariant::fromValue(uchar(0)) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("uchar+uint3") << QVariant::fromValue(uchar(1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("uchar+uint4") << QVariant::fromValue(uchar(1)) << QVariant::fromValue(1U) << 0;
+
+ QTest::newRow("short+uint1") << QVariant::fromValue(short(0)) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("short+uint2") << QVariant::fromValue(short(0)) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("short+uint3") << QVariant::fromValue(short(1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("short+uint4") << QVariant::fromValue(short(1)) << QVariant::fromValue(1U) << 0;
+
+ QTest::newRow("ushort+uint1") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("ushort+uint2") << QVariant::fromValue(ushort(0)) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("ushort+uint3") << QVariant::fromValue(ushort(1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("ushort+uint4") << QVariant::fromValue(ushort(1)) << QVariant::fromValue(1U) << 0;
// int + qlonglong
- QTest::newRow("int+qlonglong1") << qVariantFromValue(0) << qVariantFromValue(Q_INT64_C(0)) << 0;
- QTest::newRow("int+qlonglong2") << qVariantFromValue(1) << qVariantFromValue(Q_INT64_C(0)) << +1;
- QTest::newRow("int+qlonglong3") << qVariantFromValue(0) << qVariantFromValue(Q_INT64_C(1)) << -1;
- QTest::newRow("int+qlonglong4") << qVariantFromValue(1) << qVariantFromValue(Q_INT64_C(1)) << 0;
- QTest::newRow("int+qlonglong5") << qVariantFromValue(0) << qVariantFromValue(Q_INT64_C(-1)) << +1;
- QTest::newRow("int+qlonglong6") << qVariantFromValue(-1) << qVariantFromValue(Q_INT64_C(0)) << -1;
- QTest::newRow("int+qlonglong7") << qVariantFromValue(-1) << qVariantFromValue(Q_INT64_C(-1)) << 0;
+ QTest::newRow("int+qlonglong1") << QVariant::fromValue(0) << QVariant::fromValue(Q_INT64_C(0)) << 0;
+ QTest::newRow("int+qlonglong2") << QVariant::fromValue(1) << QVariant::fromValue(Q_INT64_C(0)) << +1;
+ QTest::newRow("int+qlonglong3") << QVariant::fromValue(0) << QVariant::fromValue(Q_INT64_C(1)) << -1;
+ QTest::newRow("int+qlonglong4") << QVariant::fromValue(1) << QVariant::fromValue(Q_INT64_C(1)) << 0;
+ QTest::newRow("int+qlonglong5") << QVariant::fromValue(0) << QVariant::fromValue(Q_INT64_C(-1)) << +1;
+ QTest::newRow("int+qlonglong6") << QVariant::fromValue(-1) << QVariant::fromValue(Q_INT64_C(0)) << -1;
+ QTest::newRow("int+qlonglong7") << QVariant::fromValue(-1) << QVariant::fromValue(Q_INT64_C(-1)) << 0;
// uint + qulonglong
- QTest::newRow("uint+qulonglong1") << qVariantFromValue(0U) << qVariantFromValue(Q_UINT64_C(0)) << 0;
- QTest::newRow("uint+qulonglong2") << qVariantFromValue(1U) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("uint+qulonglong3") << qVariantFromValue(0U) << qVariantFromValue(Q_UINT64_C(1)) << -1;
- QTest::newRow("uint+qulonglong4") << qVariantFromValue(1U) << qVariantFromValue(Q_UINT64_C(1)) << 0;
+ QTest::newRow("uint+qulonglong1") << QVariant::fromValue(0U) << QVariant::fromValue(Q_UINT64_C(0)) << 0;
+ QTest::newRow("uint+qulonglong2") << QVariant::fromValue(1U) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("uint+qulonglong3") << QVariant::fromValue(0U) << QVariant::fromValue(Q_UINT64_C(1)) << -1;
+ QTest::newRow("uint+qulonglong4") << QVariant::fromValue(1U) << QVariant::fromValue(Q_UINT64_C(1)) << 0;
// int + uint (without sign change)
- QTest::newRow("int+uint1") << qVariantFromValue(0) << qVariantFromValue(0U) << 0;
- QTest::newRow("int+uint2") << qVariantFromValue(1) << qVariantFromValue(0U) << +1;
- QTest::newRow("int+uint3") << qVariantFromValue(0) << qVariantFromValue(1U) << -1;
- QTest::newRow("int+uint4") << qVariantFromValue(1) << qVariantFromValue(1U) << 0;
+ QTest::newRow("int+uint1") << QVariant::fromValue(0) << QVariant::fromValue(0U) << 0;
+ QTest::newRow("int+uint2") << QVariant::fromValue(1) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("int+uint3") << QVariant::fromValue(0) << QVariant::fromValue(1U) << -1;
+ QTest::newRow("int+uint4") << QVariant::fromValue(1) << QVariant::fromValue(1U) << 0;
// uint + qlonglong
- QTest::newRow("uint+qlonglong1") << qVariantFromValue(0U) << qVariantFromValue(Q_INT64_C(0)) << 0;
- QTest::newRow("uint+qlonglong2") << qVariantFromValue(1U) << qVariantFromValue(Q_INT64_C(0)) << +1;
- QTest::newRow("uint+qlonglong3") << qVariantFromValue(0U) << qVariantFromValue(Q_INT64_C(1)) << -1;
- QTest::newRow("uint+qlonglong4") << qVariantFromValue(1U) << qVariantFromValue(Q_INT64_C(1)) << 0;
- QTest::newRow("uint+qlonglong5") << qVariantFromValue(0U) << qVariantFromValue(Q_INT64_C(-1)) << +1;
+ QTest::newRow("uint+qlonglong1") << QVariant::fromValue(0U) << QVariant::fromValue(Q_INT64_C(0)) << 0;
+ QTest::newRow("uint+qlonglong2") << QVariant::fromValue(1U) << QVariant::fromValue(Q_INT64_C(0)) << +1;
+ QTest::newRow("uint+qlonglong3") << QVariant::fromValue(0U) << QVariant::fromValue(Q_INT64_C(1)) << -1;
+ QTest::newRow("uint+qlonglong4") << QVariant::fromValue(1U) << QVariant::fromValue(Q_INT64_C(1)) << 0;
+ QTest::newRow("uint+qlonglong5") << QVariant::fromValue(0U) << QVariant::fromValue(Q_INT64_C(-1)) << +1;
// boundary conditions
- QTest::newRow("charmax+intmax") << qVariantFromValue(CHAR_MAX) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("charmax+uintmax") << qVariantFromValue(CHAR_MAX) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("scharmax+intmax") << qVariantFromValue(SCHAR_MAX) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("scharmax+uintmax") << qVariantFromValue(SCHAR_MAX) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("ucharmax+intmax") << qVariantFromValue(UCHAR_MAX) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("ucharmax+uintmax") << qVariantFromValue(UCHAR_MAX) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("shortmax+intmax") << qVariantFromValue(SHRT_MAX) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("shortmax+uintmax") << qVariantFromValue(SHRT_MAX) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("ushortmax+intmax") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(INT_MAX) << -1;
- QTest::newRow("ushortmax+uintmax") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(UINT_MAX) << -1;
-
- QTest::newRow("intmin+qlonglongmin") << qVariantFromValue(INT_MIN) << qVariantFromValue(LLONG_MIN) << +1;
- QTest::newRow("intmax+uintmax") << qVariantFromValue(INT_MAX) << qVariantFromValue(UINT_MAX) << -1;
- QTest::newRow("intmax+qlonglongmax") << qVariantFromValue(INT_MAX) << qVariantFromValue(LLONG_MAX) << -1;
- QTest::newRow("uintmax+qlonglongmax") << qVariantFromValue(UINT_MAX) << qVariantFromValue(LLONG_MAX) << -1;
- QTest::newRow("intmax+qulonglongmax") << qVariantFromValue(INT_MAX) << qVariantFromValue(ULLONG_MAX) << -1;
- QTest::newRow("qlonglongmax+qulonglongmax") << qVariantFromValue(LLONG_MAX) << qVariantFromValue(ULLONG_MAX) << -1;
- QTest::newRow("uintmax+qlonglongmin") << qVariantFromValue(UINT_MAX) << qVariantFromValue(LLONG_MIN) << +1;
+ QTest::newRow("charmax+intmax") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("charmax+uintmax") << QVariant::fromValue(CHAR_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("scharmax+intmax") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("scharmax+uintmax") << QVariant::fromValue(SCHAR_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("ucharmax+intmax") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("ucharmax+uintmax") << QVariant::fromValue(UCHAR_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("shortmax+intmax") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("shortmax+uintmax") << QVariant::fromValue(SHRT_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("ushortmax+intmax") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(INT_MAX) << -1;
+ QTest::newRow("ushortmax+uintmax") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+
+ QTest::newRow("intmin+qlonglongmin") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(LLONG_MIN) << +1;
+ QTest::newRow("intmax+uintmax") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(UINT_MAX) << -1;
+ QTest::newRow("intmax+qlonglongmax") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(LLONG_MAX) << -1;
+ QTest::newRow("uintmax+qlonglongmax") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(LLONG_MAX) << -1;
+ QTest::newRow("intmax+qulonglongmax") << QVariant::fromValue(INT_MAX) << QVariant::fromValue(ULLONG_MAX) << -1;
+ QTest::newRow("qlonglongmax+qulonglongmax") << QVariant::fromValue(LLONG_MAX) << QVariant::fromValue(ULLONG_MAX) << -1;
+ QTest::newRow("uintmax+qlonglongmin") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(LLONG_MIN) << +1;
// check for no sign-extension issues
- QTest::newRow("ushortmax+intzero") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(0) << +1;
- QTest::newRow("ushortmax+qlonglongzero") << qVariantFromValue(USHRT_MAX) << qVariantFromValue(Q_INT64_C(0)) << +1;
- QTest::newRow("uintmax+qlonglongzero") << qVariantFromValue(UINT_MAX) << qVariantFromValue(Q_INT64_C(0)) << +1;
+ QTest::newRow("ushortmax+intzero") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(0) << +1;
+ QTest::newRow("ushortmax+qlonglongzero") << QVariant::fromValue(USHRT_MAX) << QVariant::fromValue(Q_INT64_C(0)) << +1;
+ QTest::newRow("uintmax+qlonglongzero") << QVariant::fromValue(UINT_MAX) << QVariant::fromValue(Q_INT64_C(0)) << +1;
// sign changes
// the tests below check that a signed negative number sign-changes to a non-zero unsigned number and that
// signed -1 sign-changes to unsigned maximum (all bits set, ~0). This works on two's complement machines
// (all that Qt supports), and would also work on one's complement.
if (std::numeric_limits<char>::is_signed) {
- QTest::newRow("signchange-char+uint") << qVariantFromValue(char(-1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-char+uintmax") << qVariantFromValue(char(-1)) << qVariantFromValue(UINT_MAX) << 0;
- QTest::newRow("signchange-charmin+uint") << qVariantFromValue(CHAR_MIN) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-char+qulonglong") << qVariantFromValue(char(-1)) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-char+qulonglongmax") << qVariantFromValue(char(-1)) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("signchange-charmin+qulonglong") << qVariantFromValue(CHAR_MIN) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- }
- QTest::newRow("signchange-schar+uint") << qVariantFromValue(schar(-1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-schar+uintmax") << qVariantFromValue(schar(-1)) << qVariantFromValue(UINT_MAX) << 0;
- QTest::newRow("signchange-scharmin+uint") << qVariantFromValue(SCHAR_MIN) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-schar+qulonglong") << qVariantFromValue(schar(-1)) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-schar+qulonglongmax") << qVariantFromValue(schar(-1)) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("signchange-scharmin+qulonglong") << qVariantFromValue(SCHAR_MIN) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-short+uint") << qVariantFromValue(short(-1)) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-short+uintmax") << qVariantFromValue(short(-1)) << qVariantFromValue(UINT_MAX) << 0;
- QTest::newRow("signchange-shortmin+uint") << qVariantFromValue(SHRT_MIN) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-short+qulonglong") << qVariantFromValue(short(-1)) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-short+qulonglongmax") << qVariantFromValue(short(-1)) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("signchange-shortmin+qulonglong") << qVariantFromValue(SHRT_MIN) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-int+uint") << qVariantFromValue(-1) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-int+uintmax") << qVariantFromValue(-1) << qVariantFromValue(UINT_MAX) << 0;
- QTest::newRow("signchange-intmin+uint") << qVariantFromValue(INT_MIN) << qVariantFromValue(0U) << +1;
- QTest::newRow("signchange-int+qulonglong") << qVariantFromValue(-1) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-int+qulonglongmax") << qVariantFromValue(-1) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("signchange-intmin+qulonglong") << qVariantFromValue(INT_MIN) << qVariantFromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-char+uint") << QVariant::fromValue(char(-1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-char+uintmax") << QVariant::fromValue(char(-1)) << QVariant::fromValue(UINT_MAX) << 0;
+ QTest::newRow("signchange-charmin+uint") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-char+qulonglong") << QVariant::fromValue(char(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-char+qulonglongmax") << QVariant::fromValue(char(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("signchange-charmin+qulonglong") << QVariant::fromValue(CHAR_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ }
+ QTest::newRow("signchange-schar+uint") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-schar+uintmax") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(UINT_MAX) << 0;
+ QTest::newRow("signchange-scharmin+uint") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-schar+qulonglong") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-schar+qulonglongmax") << QVariant::fromValue(schar(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("signchange-scharmin+qulonglong") << QVariant::fromValue(SCHAR_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-short+uint") << QVariant::fromValue(short(-1)) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-short+uintmax") << QVariant::fromValue(short(-1)) << QVariant::fromValue(UINT_MAX) << 0;
+ QTest::newRow("signchange-shortmin+uint") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-short+qulonglong") << QVariant::fromValue(short(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-short+qulonglongmax") << QVariant::fromValue(short(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("signchange-shortmin+qulonglong") << QVariant::fromValue(SHRT_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-int+uint") << QVariant::fromValue(-1) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-int+uintmax") << QVariant::fromValue(-1) << QVariant::fromValue(UINT_MAX) << 0;
+ QTest::newRow("signchange-intmin+uint") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(0U) << +1;
+ QTest::newRow("signchange-int+qulonglong") << QVariant::fromValue(-1) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-int+qulonglongmax") << QVariant::fromValue(-1) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("signchange-intmin+qulonglong") << QVariant::fromValue(INT_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
// no qlonglong+uint, since that should promote to qlonglong and then the comparison is signed (tested above)
- QTest::newRow("signchange-qlonglong+qulonglong") << qVariantFromValue(Q_INT64_C(-1)) << qVariantFromValue(Q_UINT64_C(0)) << +1;
- QTest::newRow("signchange-qlonglong+qulonglongmax") << qVariantFromValue(Q_INT64_C(-1)) << qVariantFromValue(ULLONG_MAX) << 0;
- QTest::newRow("signchange-qlonglongmin+qulonglong") << qVariantFromValue(LLONG_MIN) << qVariantFromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-qlonglong+qulonglong") << QVariant::fromValue(Q_INT64_C(-1)) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
+ QTest::newRow("signchange-qlonglong+qulonglongmax") << QVariant::fromValue(Q_INT64_C(-1)) << QVariant::fromValue(ULLONG_MAX) << 0;
+ QTest::newRow("signchange-qlonglongmin+qulonglong") << QVariant::fromValue(LLONG_MIN) << QVariant::fromValue(Q_UINT64_C(0)) << +1;
}
void tst_QVariant::compareNumbers() const
@@ -2761,6 +2763,14 @@ void tst_QVariant::qvariant_cast_QObject_derived()
QCOMPARE(data.value<CustomQObjectDerived *>(), object);
QCOMPARE(data.value<CustomQObject *>(), object);
}
+ {
+ QObject *object = new CustomQObjectDerivedNoMetaType(this);
+ QVariant data = QVariant::fromValue(object);
+ QVERIFY(data.canConvert<CustomQObjectDerivedNoMetaType*>());
+ QVERIFY(data.convert(qMetaTypeId<CustomQObjectDerivedNoMetaType*>()));
+ QCOMPARE(data.value<CustomQObjectDerivedNoMetaType*>(), object);
+ QCOMPARE(data.isNull(), false);
+ }
}
struct QObjectWrapper
@@ -2863,7 +2873,10 @@ void tst_QVariant::qvariant_cast_QObject_wrapper()
}
{
QFile *f = new QFile(this);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QWeakPointer<QFile> sp(f);
+QT_WARNING_POP
QVariant spVar = QVariant::fromValue(sp);
QVERIFY(spVar.canConvert<QObject*>());
QCOMPARE(f, spVar.value<QObject*>());
@@ -3943,7 +3956,7 @@ void tst_QVariant::userConversion()
QVERIFY(!(QMetaType::hasRegisteredConverterFunction<QString, Convertible>()));
Convertible c = { 123 };
- QVariant v = qVariantFromValue(c);
+ QVariant v = QVariant::fromValue(c);
bool ok;
v.toInt(&ok);
@@ -3977,7 +3990,7 @@ void tst_QVariant::userConversion()
QVERIFY(!(QMetaType::hasRegisteredConverterFunction<QString, BigConvertible>()));
BigConvertible c = { 123, 0, 0 };
- QVariant v = qVariantFromValue(c);
+ QVariant v = QVariant::fromValue(c);
bool ok;
v.toInt(&ok);
@@ -4692,7 +4705,6 @@ Q_DECLARE_METATYPE(EnumTest_Enum0)
enum EnumTest_Enum1 : qint64 { EnumTest_Enum1_value = 42, EnumTest_Enum1_bigValue = (Q_INT64_C(1) << 33) + 50 };
Q_DECLARE_METATYPE(EnumTest_Enum1)
-#if defined(Q_COMPILER_CLASS_ENUM)
enum EnumTest_Enum3 : qint64 { EnumTest_Enum3_value = -47, EnumTest_Enum3_bigValue = (Q_INT64_C(1) << 56) + 5 };
Q_DECLARE_METATYPE(EnumTest_Enum3)
enum EnumTest_Enum4 : quint64 { EnumTest_Enum4_value = 47, EnumTest_Enum4_bigValue = (Q_INT64_C(1) << 52) + 45 };
@@ -4705,7 +4717,6 @@ enum class EnumTest_Enum7 { EnumTest_Enum7_value = 47, ensureSignedEnum7 = -1 };
Q_DECLARE_METATYPE(EnumTest_Enum7)
enum EnumTest_Enum8 : short { EnumTest_Enum8_value = 47 };
Q_DECLARE_METATYPE(EnumTest_Enum8)
-#endif
template<typename Enum> void testVariant(Enum value, bool *ok)
{
@@ -4764,7 +4775,6 @@ void tst_QVariant::enums()
QVERIFY(ok);
testVariant(EnumTest_Enum1_bigValue, &ok);
QVERIFY(ok);
-#if defined(Q_COMPILER_CLASS_ENUM)
testVariant(EnumTest_Enum3::EnumTest_Enum3_value, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum3::EnumTest_Enum3_bigValue, &ok);
@@ -4783,7 +4793,6 @@ void tst_QVariant::enums()
QVERIFY(ok);
testVariant(EnumTest_Enum3::EnumTest_Enum3_value, &ok);
QVERIFY(ok);
-#endif
}
template<typename Enum> void testVariantMeta(Enum value, bool *ok, const char *string)
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
index 9df52887f7..fd3cc18af5 100644
--- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
@@ -73,12 +73,12 @@ static inline QString testSuiteWarning()
str << "\nCannot find the shared-mime-info test suite\nstarting from: "
<< QDir::toNativeSeparators(QDir::currentPath()) << "\n"
"cd " << QDir::toNativeSeparators(QStringLiteral("tests/auto/corelib/mimetypes/qmimedatabase")) << "\n"
- "wget http://cgit.freedesktop.org/xdg/shared-mime-info/snapshot/Release-1-8.zip\n"
- "unzip Release-1-8.zip\n";
+ "wget http://cgit.freedesktop.org/xdg/shared-mime-info/snapshot/Release-1-10.zip\n"
+ "unzip Release-1-10.zip\n";
#ifdef Q_OS_WIN
- str << "mkdir testfiles\nxcopy /s Release-1-8 s-m-i\n";
+ str << "mkdir testfiles\nxcopy /s Release-1-10 s-m-i\n";
#else
- str << "ln -s Release-1-8 s-m-i\n";
+ str << "ln -s Release-1-10 s-m-i\n";
#endif
return result;
}
@@ -611,7 +611,7 @@ void tst_QMimeDatabase::allMimeTypes()
QVERIFY(!lst.isEmpty());
// Hardcoding this is the only way to check both providers find the same number of mimetypes.
- QCOMPARE(lst.count(), 749);
+ QCOMPARE(lst.count(), 779);
foreach (const QMimeType &mime, lst) {
const QString name = mime.name();
@@ -640,7 +640,7 @@ void tst_QMimeDatabase::suffixes_data()
QTest::newRow("mimetype with multiple patterns") << "text/plain" << "*.asc;*.txt;*,v" << "txt";
QTest::newRow("mimetype with uncommon pattern") << "text/x-readme" << "README*" << QString();
QTest::newRow("mimetype with no patterns") << "application/x-ole-storage" << QString() << QString();
- QTest::newRow("default_mimetype") << "application/octet-stream" << "*.bin" << QString();
+ QTest::newRow("default_mimetype") << "application/octet-stream" << QString() << QString();
}
void tst_QMimeDatabase::suffixes()
diff --git a/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp b/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp
index c74bce3b5b..e1357245f3 100644
--- a/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp
+++ b/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp
@@ -91,11 +91,7 @@ static QStringList qMimeTypeGlobPatterns()
// ------------------------------------------------------------------------------------------------
-#ifndef Q_COMPILER_RVALUE_REFS
-QMIMETYPE_BUILDER
-#else
QMIMETYPE_BUILDER_FROM_RVALUE_REFS
-#endif
// ------------------------------------------------------------------------------------------------
diff --git a/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp b/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
index c9c9202a80..e0d09b0813 100644
--- a/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
+++ b/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
@@ -30,7 +30,7 @@
#include <QtTest/QtTest>
#include <qdir.h>
#include <qlibrary.h>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
// Helper macros to let us know if some suffixes and prefixes are valid
@@ -414,10 +414,12 @@ void tst_QLibrary::errorString()
QFAIL(qPrintable(QString("Unknown operation: %1").arg(operation)));
break;
}
- QRegExp re(errorString);
+#if QT_CONFIG(regularexpression)
+ QRegularExpression re(QRegularExpression::anchoredPattern(errorString));
QString libErrorString = lib.errorString();
+ QVERIFY2(re.match(libErrorString).hasMatch(), qPrintable(libErrorString));
+#endif
QVERIFY(!lib.isLoaded() || lib.unload());
- QVERIFY2(re.exactMatch(libErrorString), qPrintable(libErrorString));
QCOMPARE(ok, success);
}
diff --git a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro
index 3745782dfc..18c9c8d198 100644
--- a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro
+++ b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro
@@ -3,6 +3,7 @@ TEMPLATE = subdirs
tst.depends = lib theplugin
SUBDIRS = lib \
+ staticplugin \
theplugin \
tst
!android:!win32:!darwin {
diff --git a/tests/auto/corelib/plugin/qpluginloader/staticplugin/.gitignore b/tests/auto/corelib/plugin/qpluginloader/staticplugin/.gitignore
new file mode 100644
index 0000000000..26f7ecd506
--- /dev/null
+++ b/tests/auto/corelib/plugin/qpluginloader/staticplugin/.gitignore
@@ -0,0 +1,3 @@
+*staticplugin.prl
+libstaticplugin.a
+staticplugin.lib
diff --git a/src/tools/uic/globaldefs.h b/tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp
index 5ad193c29a..6d163ea336 100644
--- a/src/tools/uic/globaldefs.h
+++ b/tests/auto/corelib/plugin/qpluginloader/staticplugin/main.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the tools applications of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
@@ -25,17 +25,15 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+#include <QtPlugin>
+#include <QObject>
-#ifndef GLOBALDEFS_H
-#define GLOBALDEFS_H
+class StaticPlugin : public QObject
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "SomeIID" URI "qt.test.pluginloader.staticplugin")
+public:
+ StaticPlugin() {}
+};
-#include <qglobal.h>
-
-QT_BEGIN_NAMESPACE
-
-enum { BOXLAYOUT_DEFAULT_MARGIN = 11 };
-enum { BOXLAYOUT_DEFAULT_SPACING = 6 };
-
-QT_END_NAMESPACE
-
-#endif // GLOBALDEFS_H
+#include "main.moc"
diff --git a/tests/auto/corelib/plugin/qpluginloader/staticplugin/staticplugin.pro b/tests/auto/corelib/plugin/qpluginloader/staticplugin/staticplugin.pro
new file mode 100644
index 0000000000..ff65ab728c
--- /dev/null
+++ b/tests/auto/corelib/plugin/qpluginloader/staticplugin/staticplugin.pro
@@ -0,0 +1,7 @@
+TEMPLATE = lib
+CONFIG += plugin static
+SOURCES = main.cpp
+QT = core
+
+# Add extra metadata to the plugin
+QMAKE_MOC_OPTIONS += -M ExtraMetaData=StaticPlugin -M ExtraMetaData=foo
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro b/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro
index c20e56ba4c..a3885f4134 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro
+++ b/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro
@@ -8,9 +8,14 @@ HEADERS = ../theplugin/plugininterface.h
win32 {
CONFIG(debug, debug|release) {
TARGET = ../../debug/tst_qpluginloader
+ LIBS += -L../staticplugin/debug
} else {
TARGET = ../../release/tst_qpluginloader
+ LIBS += -L../staticplugin/release
}
+} else {
+ LIBS += -L../staticplugin
}
+LIBS += -lstaticplugin
TESTDATA += ../elftest ../machtest
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
index c517c0809a..b06000d9c4 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
+++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -121,8 +121,11 @@ private slots:
void reloadPlugin();
void preloadedPlugin_data();
void preloadedPlugin();
+ void staticPlugins();
};
+Q_IMPORT_PLUGIN(StaticPlugin)
+
void tst_QPluginLoader::cleanup()
{
// check if the library/plugin was leaked
@@ -520,5 +523,38 @@ void tst_QPluginLoader::preloadedPlugin()
QVERIFY(lib.unload());
}
+void tst_QPluginLoader::staticPlugins()
+{
+ const QObjectList instances = QPluginLoader::staticInstances();
+ QVERIFY(instances.size());
+
+ bool found = false;
+ for (QObject *obj : instances) {
+ found = obj->metaObject()->className() == QLatin1String("StaticPlugin");
+ if (found)
+ break;
+ }
+ QVERIFY(found);
+
+ const auto plugins = QPluginLoader::staticPlugins();
+ QCOMPARE(plugins.size(), instances.size());
+
+ // find the metadata
+ QJsonObject metaData;
+ for (const auto &p : plugins) {
+ metaData = p.metaData();
+ found = metaData.value("className").toString() == QLatin1String("StaticPlugin");
+ if (found)
+ break;
+ }
+ QVERIFY(found);
+
+ QCOMPARE(metaData.value("version").toInt(), QT_VERSION);
+ QCOMPARE(metaData.value("IID").toString(), "SomeIID");
+ QCOMPARE(metaData.value("ExtraMetaData"), QJsonArray({ "StaticPlugin", "foo" }));
+ QCOMPARE(metaData.value("URI").toString(), "qt.test.pluginloader.staticplugin");
+}
+
+
QTEST_MAIN(tst_QPluginLoader)
#include "tst_qpluginloader.moc"
diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp
index 4651258ef3..1cbe0cae48 100644
--- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp
+++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp
@@ -153,6 +153,18 @@ private Q_SLOTS:
void implicitValueType();
void implicitDocumentType();
+ void streamSerializationQJsonDocument_data();
+ void streamSerializationQJsonDocument();
+ void streamSerializationQJsonArray_data();
+ void streamSerializationQJsonArray();
+ void streamSerializationQJsonObject_data();
+ void streamSerializationQJsonObject();
+ void streamSerializationQJsonValue_data();
+ void streamSerializationQJsonValue();
+ void streamSerializationQJsonValueEmpty();
+ void streamVariantSerialization();
+ void escapeSurrogateCodePoints_data();
+ void escapeSurrogateCodePoints();
private:
QString testDataDir;
};
@@ -2743,9 +2755,6 @@ void tst_QtJson::testJsonValueRefDefault()
void tst_QtJson::arrayInitializerList()
{
-#ifndef Q_COMPILER_INITIALIZER_LISTS
- QSKIP("initializer_list is enabled only with c++11 support");
-#else
QVERIFY(QJsonArray{}.isEmpty());
QCOMPARE(QJsonArray{"one"}.count(), 1);
QCOMPARE(QJsonArray{1}.count(), 1);
@@ -2791,14 +2800,10 @@ void tst_QtJson::arrayInitializerList()
QCOMPARE(QJsonValue(a43["one"]), QJsonValue(1));
}
}
-#endif
}
void tst_QtJson::objectInitializerList()
{
-#ifndef Q_COMPILER_INITIALIZER_LISTS
- QSKIP("initializer_list is enabled only with c++11 support");
-#else
QVERIFY(QJsonObject{}.isEmpty());
{ // one property
@@ -2838,7 +2843,6 @@ void tst_QtJson::objectInitializerList()
QCOMPARE(QJsonValue(nested[0]), QJsonValue("innerValue"));
QCOMPARE(QJsonValue(nested[1]), QJsonValue(2.1));
}
-#endif
}
void tst_QtJson::unicodeKeys()
@@ -3011,5 +3015,188 @@ void tst_QtJson::implicitDocumentType()
QCOMPARE(arrayDocument[-1].toInt(123), 123);
}
+void tst_QtJson::streamSerializationQJsonDocument_data()
+{
+ QTest::addColumn<QJsonDocument>("document");
+ QTest::newRow("empty") << QJsonDocument();
+ QTest::newRow("object") << QJsonDocument(QJsonObject{{"value", 42}});
+}
+
+void tst_QtJson::streamSerializationQJsonDocument()
+{
+ // Check interface only, implementation is tested through to and from
+ // json functions.
+ QByteArray buffer;
+ QFETCH(QJsonDocument, document);
+ QJsonDocument output;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << document;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output, document);
+}
+
+void tst_QtJson::streamSerializationQJsonArray_data()
+{
+ QTest::addColumn<QJsonArray>("array");
+ QTest::newRow("empty") << QJsonArray();
+ QTest::newRow("values") << QJsonArray{665, 666, 667};
+}
+
+void tst_QtJson::streamSerializationQJsonArray()
+{
+ // Check interface only, implementation is tested through to and from
+ // json functions.
+ QByteArray buffer;
+ QFETCH(QJsonArray, array);
+ QJsonArray output;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << array;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output, array);
+}
+
+void tst_QtJson::streamSerializationQJsonObject_data()
+{
+ QTest::addColumn<QJsonObject>("object");
+ QTest::newRow("empty") << QJsonObject();
+ QTest::newRow("non-empty") << QJsonObject{{"foo", 665}, {"bar", 666}};
+}
+
+void tst_QtJson::streamSerializationQJsonObject()
+{
+ // Check interface only, implementation is tested through to and from
+ // json functions.
+ QByteArray buffer;
+ QFETCH(QJsonObject, object);
+ QJsonObject output;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << object;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output, object);
+}
+
+void tst_QtJson::streamSerializationQJsonValue_data()
+{
+ QTest::addColumn<QJsonValue>("value");
+ QTest::newRow("double") << QJsonValue{665};
+ QTest::newRow("bool") << QJsonValue{true};
+ QTest::newRow("string") << QJsonValue{QStringLiteral("bum")};
+ QTest::newRow("array") << QJsonValue{QJsonArray{12,1,5,6,7}};
+ QTest::newRow("object") << QJsonValue{QJsonObject{{"foo", 665}, {"bar", 666}}};
+ // test json escape sequence
+ QTest::newRow("array with 0xD800") << QJsonValue(QJsonArray{QString(0xD800)});
+ QTest::newRow("array with 0xDF06,0xD834") << QJsonValue(QJsonArray{QString(0xDF06).append(0xD834)});
+}
+
+void tst_QtJson::streamSerializationQJsonValue()
+{
+ QByteArray buffer;
+ QFETCH(QJsonValue, value);
+ QJsonValue output;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << value;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output, value);
+}
+
+void tst_QtJson::streamSerializationQJsonValueEmpty()
+{
+ QByteArray buffer;
+ {
+ QJsonValue undef{QJsonValue::Undefined};
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << undef;
+ QDataStream load(buffer);
+ QJsonValue output;
+ load >> output;
+ QVERIFY(output.isUndefined());
+ }
+ {
+ QJsonValue null{QJsonValue::Null};
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << null;
+ QDataStream load(buffer);
+ QJsonValue output;
+ load >> output;
+ QVERIFY(output.isNull());
+ }
+}
+
+void tst_QtJson::streamVariantSerialization()
+{
+ // Check interface only, implementation is tested through to and from
+ // json functions.
+ QByteArray buffer;
+ {
+ QJsonDocument objectDoc(QJsonArray{665, 666, 667});
+ QVariant output;
+ QVariant variant(objectDoc);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QJsonDocument);
+ QCOMPARE(output.toJsonDocument(), objectDoc);
+ }
+ {
+ QJsonArray array{665, 666, 667};
+ QVariant output;
+ QVariant variant(array);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QJsonArray);
+ QCOMPARE(output.toJsonArray(), array);
+ }
+ {
+ QJsonObject obj{{"foo", 42}};
+ QVariant output;
+ QVariant variant(obj);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QJsonObject);
+ QCOMPARE(output.toJsonObject(), obj);
+ }
+ {
+ QJsonValue value{42};
+ QVariant output;
+ QVariant variant(value);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QJsonValue);
+ QCOMPARE(output.toJsonValue(), value);
+ }
+}
+
+void tst_QtJson::escapeSurrogateCodePoints_data()
+{
+ QTest::addColumn<QString>("str");
+ QTest::addColumn<QByteArray>("escStr");
+ QTest::newRow("0xD800") << QString(0xD800) << QByteArray("\\ud800");
+ QTest::newRow("0xDF06,0xD834") << QString(0xDF06).append(0xD834) << QByteArray("\\udf06\\ud834");
+}
+
+void tst_QtJson::escapeSurrogateCodePoints()
+{
+ QFETCH(QString, str);
+ QFETCH(QByteArray, escStr);
+ QJsonArray array;
+ array.append(str);
+ QByteArray buffer;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << array;
+ // verify the buffer has escaped values
+ QVERIFY(buffer.contains(escStr));
+}
+
QTEST_MAIN(tst_QtJson)
#include "tst_qtjson.moc"
diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
index 4b753eab6b..f69ce4120d 100644
--- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
+++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
@@ -97,6 +97,10 @@ private slots:
void validation();
void toDiagnosticNotation_data();
void toDiagnosticNotation();
+
+ void datastreamSerialization_data();
+ void datastreamSerialization();
+ void streamVariantSerialization();
};
// Get the validation data from TinyCBOR (see src/3rdparty/tinycbor/tests/parser/data.cpp)
@@ -380,11 +384,17 @@ void tst_QCborValue::arrayDefaultInitialization()
QVERIFY(v.isArray());
QVERIFY(!v.isMap());
QVERIFY(!v.isTag());
- QVERIFY(v[0].isUndefined());
QCborArray a2 = v.toArray();
QVERIFY(a2.isEmpty());
QCOMPARE(a2, a);
+ auto front = v[0];
+ QVERIFY(front.isUndefined());
+ front = 1;
+ QCOMPARE(v[0], 1);
+ QVERIFY(a2.isEmpty());
+ a2 = v.toArray();
+ QCOMPARE(a2.size(), 1);
}
void tst_QCborValue::mapDefaultInitialization()
@@ -421,7 +431,7 @@ void tst_QCborValue::mapDefaultInitialization()
QVERIFY(m == QCborMap{});
QVERIFY(QCborMap{} == m);
- QCborValue v(m);
+ const QCborValue v(m);
QVERIFY(v.isMap());
QVERIFY(!v.isArray());
QVERIFY(!v.isTag());
@@ -723,6 +733,31 @@ void tst_QCborValue::arrayMutation()
QCOMPARE(a.at(1), QCborValue(-1));
QCOMPARE(a2.at(1), QCborValue(nullptr));
QCOMPARE(++it, end);
+
+ // Array accessed via value:
+ QCborValue val(a);
+ val[2] = QCborArray{2, 3, 5, 7};
+ QCOMPARE(a.size(), 2); // Unchanged
+ QVERIFY(val.isArray());
+ QCOMPARE(val.toArray().size(), 3);
+ val[2][4] = 17;
+ QVERIFY(val.isArray());
+ QVERIFY(val[2].isArray());
+ QCOMPARE(val[2].toArray().size(), 5);
+ QCOMPARE(val[2][4], 17);
+ QCOMPARE(val.toArray().size(), 3);
+ val[3] = 42;
+ QVERIFY(val.isArray());
+ QCOMPARE(val.toArray().size(), 4);
+ QCOMPARE(val[3], 42);
+
+ // Coerce to map on string key:
+ const QLatin1String any("any");
+ val[any] = any;
+ QVERIFY(val.isMap());
+ QCOMPARE(val.toMap().size(), 5);
+ QVERIFY(val[2].isArray());
+ QCOMPARE(val[2].toArray().size(), 5);
}
void tst_QCborValue::mapMutation()
@@ -778,6 +813,30 @@ void tst_QCborValue::mapMutation()
QCOMPARE((m.end() - 1)->toInteger(), -1);
QVERIFY((m2.end() - 1)->isNull());
QCOMPARE(++it, end);
+
+ // Map accessed via value:
+ QCborValue val(m);
+ val[7] = QCborMap({{0, 2}, {1, 3}, {2, 5}});
+ QCOMPARE(m.size(), 2); // Unchanged
+ QVERIFY(val.isMap());
+ QCOMPARE(val.toMap().size(), 3);
+ val[7][3] = 11;
+ QVERIFY(val.isMap());
+ QVERIFY(val[7].isMap());
+ QCOMPARE(val[7].toMap().size(), 4);
+ val[14] = 42;
+ QVERIFY(val.isMap());
+ QCOMPARE(val.toMap().size(), 4);
+
+ const QLatin1String any("any");
+ const QString hello(QStringLiteral("Hello World"));
+ val[any][3][hello] = any;
+ QVERIFY(val.isMap());
+ QCOMPARE(val.toMap().size(), 5);
+ QVERIFY(val[any].isMap());
+ QCOMPARE(val[any].toMap().size(), 1);
+ QVERIFY(val[any][3].isMap());
+ QCOMPARE(val[any][3].toMap().size(), 1);
}
void tst_QCborValue::arrayPrepend()
@@ -1690,6 +1749,83 @@ void tst_QCborValue::toDiagnosticNotation()
QCOMPARE(result, expected);
}
+
+void tst_QCborValue::datastreamSerialization_data()
+{
+ addCommonCborData();
+}
+
+void tst_QCborValue::datastreamSerialization()
+{
+ QFETCH(QCborValue, v);
+ QByteArray buffer;
+ {
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << v;
+ QDataStream load(buffer);
+ QCborValue output;
+ load >> output;
+ QCOMPARE(output, v);
+ }
+ if (v.isArray()) {
+ QCborArray array = v.toArray();
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << array;
+ QDataStream load(buffer);
+ QCborValue output;
+ load >> output;
+ QCOMPARE(output, array);
+ } else if (v.isMap()) {
+ QCborMap map = v.toMap();
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << map;
+ QDataStream load(buffer);
+ QCborValue output;
+ load >> output;
+ QCOMPARE(output, map);
+ }
+}
+
+void tst_QCborValue::streamVariantSerialization()
+{
+ // Check interface only, implementation is tested through to and from
+ // cbor functions.
+ QByteArray buffer;
+ {
+ QCborArray array{665, 666, 667};
+ QVariant output;
+ QVariant variant = QVariant::fromValue(array);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QCborArray);
+ QCOMPARE(qvariant_cast<QCborArray>(output), array);
+ }
+ {
+ QCborMap obj{{"foo", 42}};
+ QVariant output;
+ QVariant variant = QVariant::fromValue(obj);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QCborMap);
+ QCOMPARE(qvariant_cast<QCborMap>(output), obj);
+ }
+ {
+ QCborValue value{42};
+ QVariant output;
+ QVariant variant = QVariant::fromValue(value);
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << variant;
+ QDataStream load(buffer);
+ load >> output;
+ QCOMPARE(output.userType(), QMetaType::QCborValue);
+ QCOMPARE(qvariant_cast<QCborValue>(output), value);
+ }
+}
+
QTEST_MAIN(tst_QCborValue)
#include "tst_qcborvalue.moc"
diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
index 041d9d7a09..b8778e4e98 100644
--- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
+++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
@@ -113,6 +113,11 @@ private slots:
void stream_QRegExp_data();
void stream_QRegExp();
+#if QT_CONFIG(regularexpression)
+ void stream_QRegularExpression_data();
+ void stream_QRegularExpression();
+#endif
+
void stream_Map_data();
void stream_Map();
@@ -135,6 +140,15 @@ private slots:
void stream_QByteArray2();
+ void stream_QJsonDocument();
+ void stream_QJsonArray();
+ void stream_QJsonObject();
+ void stream_QJsonValue();
+
+ void stream_QCborArray();
+ void stream_QCborMap();
+ void stream_QCborValue();
+
void setVersion_data();
void setVersion();
@@ -172,6 +186,8 @@ private slots:
void streamRealDataTypes();
+ void enumTest();
+
void floatingPointPrecision();
void compatibility_Qt5();
@@ -210,6 +226,9 @@ private:
void writeQSize(QDataStream *s);
void writeQString(QDataStream* dev);
void writeQRegExp(QDataStream* dev);
+#if QT_CONFIG(regularexpression)
+ void writeQRegularExpression(QDataStream *dev);
+#endif
void writeMap(QDataStream* dev);
void writeHash(QDataStream* dev);
void writeqint64(QDataStream *s);
@@ -239,6 +258,9 @@ private:
void readQSize(QDataStream *s);
void readQString(QDataStream *s);
void readQRegExp(QDataStream *s);
+#if QT_CONFIG(regularexpression)
+ void readQRegularExpression(QDataStream *s);
+#endif
void readMap(QDataStream *s);
void readHash(QDataStream *s);
void readqint64(QDataStream *s);
@@ -550,6 +572,69 @@ void tst_QDataStream::readQRegExp(QDataStream *s)
// ************************************
+#if QT_CONFIG(regularexpression)
+static QRegularExpression QRegularExpressionData(int index)
+{
+ switch (index) {
+ case 0: return QRegularExpression();
+ case 1: return QRegularExpression("");
+ case 2: return QRegularExpression("A", QRegularExpression::CaseInsensitiveOption);
+ case 3: return QRegularExpression(QRegularExpression::wildcardToRegularExpression("ABCDE FGHI"));
+ case 4: return QRegularExpression(QRegularExpression::anchoredPattern("This is a long string"), QRegularExpression::CaseInsensitiveOption);
+ case 5: return QRegularExpression("And again a string with a \nCRLF", QRegularExpression::CaseInsensitiveOption);
+ case 6: return QRegularExpression("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRESTUVWXYZ 1234567890 ~`!@#$%^&*()_-+={[}]|\\:;\"'<,>.?/", QRegularExpression::InvertedGreedinessOption);
+ }
+ return QRegularExpression("foo");
+}
+#define MAX_QREGULAREXPRESSION_DATA 7
+
+void tst_QDataStream::stream_QRegularExpression_data()
+{
+ stream_data(MAX_QREGULAREXPRESSION_DATA);
+}
+
+void tst_QDataStream::stream_QRegularExpression()
+{
+ STREAM_IMPL(QRegularExpression);
+}
+
+void tst_QDataStream::writeQRegularExpression(QDataStream* s)
+{
+ QRegularExpression test(QRegularExpressionData(dataIndex(QTest::currentDataTag())));
+ *s << test;
+ *s << QString("Her er det noe tekst");
+ *s << test;
+ *s << QString("nonempty");
+ *s << test;
+ *s << QVariant(test);
+}
+
+void tst_QDataStream::readQRegularExpression(QDataStream *s)
+{
+ QRegularExpression R;
+ QString S;
+ QVariant V;
+ QRegularExpression test(QRegularExpressionData(dataIndex(QTest::currentDataTag())));
+
+ *s >> R;
+
+ QCOMPARE(R, test);
+ *s >> S;
+ QCOMPARE(S, QString("Her er det noe tekst"));
+ *s >> R;
+ QCOMPARE(R, test);
+ *s >> S;
+ QCOMPARE(S, QString("nonempty"));
+ *s >> R;
+ QCOMPARE(R, test);
+ *s >> V;
+ QCOMPARE(V.type(), QVariant::RegularExpression);
+ QCOMPARE(V.toRegularExpression(), test);
+}
+#endif //QT_CONFIG(regularexpression)
+
+// ************************************
+
typedef QMap<int, QString> Map;
static Map MapData(int index)
@@ -2096,6 +2181,138 @@ void tst_QDataStream::stream_QByteArray2()
}
}
+void tst_QDataStream::stream_QJsonDocument()
+{
+ QByteArray buffer;
+ {
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << QByteArrayLiteral("invalidJson");
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QJsonDocument doc;
+ load >> doc;
+ QVERIFY(doc.isEmpty());
+ QVERIFY(load.status() != QDataStream::Ok);
+ QCOMPARE(load.status(), QDataStream::ReadCorruptData);
+ }
+ {
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ QJsonDocument docSave(QJsonArray{1,2,3});
+ save << docSave;
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QJsonDocument docLoad;
+ load >> docLoad;
+ QCOMPARE(docLoad, docSave);
+ }
+}
+
+void tst_QDataStream::stream_QJsonArray()
+{
+ QByteArray buffer;
+ {
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << QByteArrayLiteral("invalidJson");
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QJsonArray array;
+ load >> array;
+ QVERIFY(array.isEmpty());
+ QVERIFY(load.status() != QDataStream::Ok);
+ QCOMPARE(load.status(), QDataStream::ReadCorruptData);
+ }
+ {
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ QJsonArray arraySave(QJsonArray{1,2,3});
+ save << arraySave;
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QJsonArray arrayLoad;
+ load >> arrayLoad;
+ QCOMPARE(arrayLoad, arraySave);
+ }
+}
+
+void tst_QDataStream::stream_QJsonObject()
+{
+ QByteArray buffer;
+ {
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << QByteArrayLiteral("invalidJson");
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QJsonObject object;
+ load >> object;
+ QVERIFY(object.isEmpty());
+ QVERIFY(load.status() != QDataStream::Ok);
+ QCOMPARE(load.status(), QDataStream::ReadCorruptData);
+ }
+ {
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ QJsonObject objSave{{"foo", 1}, {"bar", 2}};
+ save << objSave;
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QJsonObject objLoad;
+ load >> objLoad;
+ QCOMPARE(objLoad, objSave);
+ }
+}
+
+void tst_QDataStream::stream_QJsonValue()
+{
+ QByteArray buffer;
+ {
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ save << quint8(42);
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QJsonValue value;
+ load >> value;
+ QVERIFY(value.isUndefined());
+ QVERIFY(load.status() != QDataStream::Ok);
+ QCOMPARE(load.status(), QDataStream::ReadCorruptData);
+ }
+ {
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ QJsonValue valueSave{42};
+ save << valueSave;
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QJsonValue valueLoad;
+ load >> valueLoad;
+ QCOMPARE(valueLoad, valueSave);
+ }
+}
+
+void tst_QDataStream::stream_QCborArray()
+{
+ QByteArray buffer;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ QCborArray arraySave({1, 2, 3});
+ save << arraySave;
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QCborArray arrayLoad;
+ load >> arrayLoad;
+ QCOMPARE(arrayLoad, arraySave);
+}
+
+void tst_QDataStream::stream_QCborMap()
+{
+ QByteArray buffer;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ QCborMap objSave{{"foo", 1}, {"bar", 2}};
+ save << objSave;
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QCborMap objLoad;
+ load >> objLoad;
+ QCOMPARE(objLoad, objSave);
+}
+
+void tst_QDataStream::stream_QCborValue()
+{
+ QByteArray buffer;
+ QDataStream save(&buffer, QIODevice::WriteOnly);
+ QCborValue valueSave{42};
+ save << valueSave;
+ QDataStream load(&buffer, QIODevice::ReadOnly);
+ QCborValue valueLoad;
+ load >> valueLoad;
+ QCOMPARE(valueLoad, valueSave);
+}
+
void tst_QDataStream::setVersion_data()
{
QTest::addColumn<int>("vers");
@@ -3300,6 +3517,90 @@ void tst_QDataStream::floatingPointNaN()
}
}
+void tst_QDataStream::enumTest()
+{
+ QByteArray ba;
+
+ enum class E1 : qint8
+ {
+ A,
+ B,
+ C
+ };
+ {
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << E1::A;
+ QCOMPARE(ba.size(), int(sizeof(E1)));
+ }
+ {
+ QDataStream stream(ba);
+ E1 e;
+ stream >> e;
+ QCOMPARE(e, E1::A);
+ }
+ ba.clear();
+
+ enum class E2 : qint16
+ {
+ A,
+ B,
+ C
+ };
+ {
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << E2::B;
+ QCOMPARE(ba.size(), int(sizeof(E2)));
+ }
+ {
+ QDataStream stream(ba);
+ E2 e;
+ stream >> e;
+ QCOMPARE(e, E2::B);
+ }
+ ba.clear();
+
+ enum class E4 : qint32
+ {
+ A,
+ B,
+ C
+ };
+ {
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << E4::C;
+ QCOMPARE(ba.size(), int(sizeof(E4)));
+ }
+ {
+ QDataStream stream(ba);
+ E4 e;
+ stream >> e;
+ QCOMPARE(e, E4::C);
+ }
+ ba.clear();
+
+
+ enum E
+ {
+ A,
+ B,
+ C,
+ D
+ };
+ {
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << E::D;
+ QCOMPARE(ba.size(), 4);
+ }
+ {
+ QDataStream stream(ba);
+ E e;
+ stream >> e;
+ QCOMPARE(e, E::D);
+ }
+ ba.clear();
+
+}
+
void tst_QDataStream::floatingPointPrecision()
{
QByteArray ba;
diff --git a/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp b/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp
index 41ea5e56f0..2d4aa452ca 100644
--- a/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp
+++ b/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp
@@ -41,7 +41,7 @@ int main(int argc, char **argv)
do {
line = qin.readLine();
if (!line.isNull())
- qerr << line << flush;
+ qerr << line << Qt::flush;
} while (!line.isNull());
return 0;
}
diff --git a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
index 159fbd7b03..32306e8003 100644
--- a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
+++ b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
@@ -35,6 +35,7 @@
#include <QBuffer>
#include <QByteArray>
#include <QDebug>
+#include <QElapsedTimer>
#include <QFile>
#include <QTcpSocket>
#include <QTemporaryDir>
@@ -245,7 +246,7 @@ private:
void runOnExit()
{
QByteArray buffer;
- QTextStream(&buffer) << "This will try to use QTextCodec::codecForLocale" << endl;
+ QTextStream(&buffer) << "This will try to use QTextCodec::codecForLocale" << Qt::endl;
}
Q_DESTRUCTOR_FUNCTION(runOnExit)
@@ -996,7 +997,7 @@ struct CompareIndicesForArray
void tst_QTextStream::performance()
{
// Phase #1 - test speed of reading a huge text file with QFile.
- QTime stopWatch;
+ QElapsedTimer stopWatch;
const int N = 3;
const char * readMethods[N] = {
@@ -1102,7 +1103,7 @@ void tst_QTextStream::hexTest()
QByteArray array;
QTextStream stream(&array);
- stream << showbase << hex << number;
+ stream << Qt::showbase << Qt::hex << number;
stream.flush();
QCOMPARE(array, data);
}
@@ -1132,7 +1133,7 @@ void tst_QTextStream::binTest()
QByteArray array;
QTextStream stream(&array);
- stream << showbase << bin << number;
+ stream << Qt::showbase << Qt::bin << number;
stream.flush();
QCOMPARE(array.constData(), data.constData());
}
@@ -1155,7 +1156,7 @@ void tst_QTextStream::octTest()
QByteArray array;
QTextStream stream(&array);
- stream << showbase << oct << number;
+ stream << Qt::showbase << Qt::oct << number;
stream.flush();
QCOMPARE(array, data);
}
@@ -1196,7 +1197,7 @@ void tst_QTextStream::ws_manipulator()
QTextStream stream(&string);
char a, b, c, d;
- stream >> a >> ws >> b >> ws >> c >> ws >> d;
+ stream >> a >> Qt::ws >> b >> Qt::ws >> c >> Qt::ws >> d;
QCOMPARE(a, 'a');
QCOMPARE(b, 'b');
QCOMPARE(c, 'c');
@@ -1506,9 +1507,9 @@ void tst_QTextStream::readStdin()
stdinProcess.setReadChannel(QProcess::StandardError);
QTextStream stream(&stdinProcess);
- stream << "1" << endl;
- stream << "2" << endl;
- stream << "3" << endl;
+ stream << "1" << Qt::endl;
+ stream << "2" << Qt::endl;
+ stream << "3" << Qt::endl;
stdinProcess.closeWriteChannel();
@@ -1534,7 +1535,7 @@ void tst_QTextStream::readAllFromStdin()
QTextStream stream(&stdinProcess);
stream.setCodec("ISO-8859-1");
- stream << "hello world" << flush;
+ stream << "hello world" << Qt::flush;
stdinProcess.closeWriteChannel();
@@ -1623,18 +1624,18 @@ void tst_QTextStream::forcePoint()
{
QString str;
QTextStream stream(&str);
- stream << fixed << forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
+ stream << Qt::fixed << Qt::forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
QCOMPARE(str, QString("1.000000 1 0 -1.000000 -1"));
str.clear();
stream.seek(0);
- stream << scientific << forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
+ stream << Qt::scientific << Qt::forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
QCOMPARE(str, QString("1.000000e+00 1 0 -1.000000e+00 -1"));
str.clear();
stream.seek(0);
stream.setRealNumberNotation(QTextStream::SmartNotation);
- stream << forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
+ stream << Qt::forcepoint << 1.0 << ' ' << 1 << ' ' << 0 << ' ' << -1.0 << ' ' << -1;
QCOMPARE(str, QString("1.00000 1 0 -1.00000 -1"));
}
@@ -1644,7 +1645,7 @@ void tst_QTextStream::forceSign()
{
QString str;
QTextStream stream(&str);
- stream << forcesign << 1.2 << ' ' << -1.2 << ' ' << 0;
+ stream << Qt::forcesign << 1.2 << ' ' << -1.2 << ' ' << 0;
QCOMPARE(str, QString("+1.2 -1.2 +0"));
}
@@ -1663,19 +1664,22 @@ void tst_QTextStream::read0d0d0a()
Q_DECLARE_METATYPE(QTextStreamFunction);
+// Also tests that we can have namespaces that conflict with our QTextStream constants.
+namespace ws {
QTextStream &noop(QTextStream &s) { return s; }
+}
void tst_QTextStream::numeralCase_data()
{
- QTextStreamFunction noop_ = noop;
- QTextStreamFunction bin_ = bin;
- QTextStreamFunction oct_ = oct;
- QTextStreamFunction hex_ = hex;
- QTextStreamFunction base = showbase;
- QTextStreamFunction ucb = uppercasebase;
- QTextStreamFunction lcb = lowercasebase;
- QTextStreamFunction ucd = uppercasedigits;
- QTextStreamFunction lcd = lowercasedigits;
+ QTextStreamFunction noop_ = ws::noop;
+ QTextStreamFunction bin = Qt::bin;
+ QTextStreamFunction oct = Qt::oct;
+ QTextStreamFunction hex = Qt::hex;
+ QTextStreamFunction base = Qt::showbase;
+ QTextStreamFunction ucb = Qt::uppercasebase;
+ QTextStreamFunction lcb = Qt::lowercasebase;
+ QTextStreamFunction ucd = Qt::uppercasedigits;
+ QTextStreamFunction lcd = Qt::lowercasedigits;
QTest::addColumn<QTextStreamFunction>("func1");
QTest::addColumn<QTextStreamFunction>("func2");
@@ -1686,30 +1690,30 @@ void tst_QTextStream::numeralCase_data()
QTest::newRow("dec 1") << noop_ << noop_ << noop_ << noop_ << 31 << "31";
QTest::newRow("dec 2") << noop_ << base << noop_ << noop_ << 31 << "31";
- QTest::newRow("hex 1") << hex_ << noop_ << noop_ << noop_ << 31 << "1f";
- QTest::newRow("hex 2") << hex_ << noop_ << noop_ << lcd << 31 << "1f";
- QTest::newRow("hex 3") << hex_ << noop_ << ucb << noop_ << 31 << "1f";
- QTest::newRow("hex 4") << hex_ << noop_ << noop_ << ucd << 31 << "1F";
- QTest::newRow("hex 5") << hex_ << noop_ << lcb << ucd << 31 << "1F";
- QTest::newRow("hex 6") << hex_ << noop_ << ucb << ucd << 31 << "1F";
- QTest::newRow("hex 7") << hex_ << base << noop_ << noop_ << 31 << "0x1f";
- QTest::newRow("hex 8") << hex_ << base << lcb << lcd << 31 << "0x1f";
- QTest::newRow("hex 9") << hex_ << base << ucb << noop_ << 31 << "0X1f";
- QTest::newRow("hex 10") << hex_ << base << ucb << lcd << 31 << "0X1f";
- QTest::newRow("hex 11") << hex_ << base << noop_ << ucd << 31 << "0x1F";
- QTest::newRow("hex 12") << hex_ << base << lcb << ucd << 31 << "0x1F";
- QTest::newRow("hex 13") << hex_ << base << ucb << ucd << 31 << "0X1F";
-
- QTest::newRow("bin 1") << bin_ << noop_ << noop_ << noop_ << 31 << "11111";
- QTest::newRow("bin 2") << bin_ << base << noop_ << noop_ << 31 << "0b11111";
- QTest::newRow("bin 3") << bin_ << base << lcb << noop_ << 31 << "0b11111";
- QTest::newRow("bin 4") << bin_ << base << ucb << noop_ << 31 << "0B11111";
- QTest::newRow("bin 5") << bin_ << base << noop_ << ucd << 31 << "0b11111";
- QTest::newRow("bin 6") << bin_ << base << lcb << ucd << 31 << "0b11111";
- QTest::newRow("bin 7") << bin_ << base << ucb << ucd << 31 << "0B11111";
-
- QTest::newRow("oct 1") << oct_ << noop_ << noop_ << noop_ << 31 << "37";
- QTest::newRow("oct 2") << oct_ << base << noop_ << noop_ << 31 << "037";
+ QTest::newRow("hex 1") << hex << noop_ << noop_ << noop_ << 31 << "1f";
+ QTest::newRow("hex 2") << hex << noop_ << noop_ << lcd << 31 << "1f";
+ QTest::newRow("hex 3") << hex << noop_ << ucb << noop_ << 31 << "1f";
+ QTest::newRow("hex 4") << hex << noop_ << noop_ << ucd << 31 << "1F";
+ QTest::newRow("hex 5") << hex << noop_ << lcb << ucd << 31 << "1F";
+ QTest::newRow("hex 6") << hex << noop_ << ucb << ucd << 31 << "1F";
+ QTest::newRow("hex 7") << hex << base << noop_ << noop_ << 31 << "0x1f";
+ QTest::newRow("hex 8") << hex << base << lcb << lcd << 31 << "0x1f";
+ QTest::newRow("hex 9") << hex << base << ucb << noop_ << 31 << "0X1f";
+ QTest::newRow("hex 10") << hex << base << ucb << lcd << 31 << "0X1f";
+ QTest::newRow("hex 11") << hex << base << noop_ << ucd << 31 << "0x1F";
+ QTest::newRow("hex 12") << hex << base << lcb << ucd << 31 << "0x1F";
+ QTest::newRow("hex 13") << hex << base << ucb << ucd << 31 << "0X1F";
+
+ QTest::newRow("bin 1") << bin << noop_ << noop_ << noop_ << 31 << "11111";
+ QTest::newRow("bin 2") << bin << base << noop_ << noop_ << 31 << "0b11111";
+ QTest::newRow("bin 3") << bin << base << lcb << noop_ << 31 << "0b11111";
+ QTest::newRow("bin 4") << bin << base << ucb << noop_ << 31 << "0B11111";
+ QTest::newRow("bin 5") << bin << base << noop_ << ucd << 31 << "0b11111";
+ QTest::newRow("bin 6") << bin << base << lcb << ucd << 31 << "0b11111";
+ QTest::newRow("bin 7") << bin << base << ucb << ucd << 31 << "0B11111";
+
+ QTest::newRow("oct 1") << oct << noop_ << noop_ << noop_ << 31 << "37";
+ QTest::newRow("oct 2") << oct << base << noop_ << noop_ << 31 << "037";
}
void tst_QTextStream::numeralCase()
@@ -1782,9 +1786,9 @@ void tst_QTextStream::nanInf()
QString s;
QTextStream out(&s);
out << qInf() << ' ' << -qInf() << ' ' << qQNaN()
- << uppercasedigits << ' '
+ << Qt::uppercasedigits << ' '
<< qInf() << ' ' << -qInf() << ' ' << qQNaN()
- << flush;
+ << Qt::flush;
QCOMPARE(s, QString("inf -inf nan INF -INF NAN"));
}
@@ -1821,7 +1825,7 @@ void tst_QTextStream::utf8IncompleteAtBufferBoundary()
out.setFieldWidth(3);
for (int i = 0; i < 1000; ++i) {
- out << i << lineContents << endl;
+ out << i << lineContents << Qt::endl;
}
}
data.close();
@@ -1859,9 +1863,9 @@ void tst_QTextStream::writeSeekWriteNoBOM()
int number = 0;
QString sizeStr = QLatin1String("Size=")
+ QString::number(number).rightJustified(10, QLatin1Char('0'));
- stream << sizeStr << endl;
- stream << "Version=" << QString::number(14) << endl;
- stream << "blah blah blah" << endl;
+ stream << sizeStr << Qt::endl;
+ stream << "Version=" << QString::number(14) << Qt::endl;
+ stream << "blah blah blah" << Qt::endl;
stream.flush();
QCOMPARE(out.buffer().constData(), "Size=0000000000\nVersion=14\nblah blah blah\n");
@@ -1871,7 +1875,7 @@ void tst_QTextStream::writeSeekWriteNoBOM()
stream.seek(0);
sizeStr = QLatin1String("Size=")
+ QString::number(number).rightJustified(10, QLatin1Char('0'));
- stream << sizeStr << endl;
+ stream << sizeStr << Qt::endl;
stream.flush();
// Check buffer is still OK
@@ -2665,28 +2669,30 @@ void tst_QTextStream::useCase2()
// ------------------------------------------------------------------------------
void tst_QTextStream::manipulators_data()
{
- QTest::addColumn<int>("flags");
+ QTest::addColumn<int>("base");
+ QTest::addColumn<int>("alignFlag");
+ QTest::addColumn<int>("numberFlag");
QTest::addColumn<int>("width");
QTest::addColumn<double>("realNumber");
QTest::addColumn<int>("intNumber");
QTest::addColumn<QString>("textData");
QTest::addColumn<QByteArray>("result");
- QTest::newRow("no flags") << 0 << 0 << 5.0 << 5 << QString("five") << QByteArray("55five");
- QTest::newRow("rightadjust") << 0 << 10 << 5.0 << 5 << QString("five") << QByteArray(" 5 5 five");
-
- // ### FIX
-// QTest::newRow("leftadjust") << int(QTextStream::left) << 10 << 5.0 << 5 << QString("five") << QByteArray("5 5 five ");
-// QTest::newRow("showpos") << int(QTextStream::showpos) << 10 << 5.0 << 5 << QString("five") << QByteArray(" +5 +5 five");
-// QTest::newRow("showpos2") << int(QTextStream::showpos) << 5 << 3.14 << -5 << QString("five") << QByteArray("+3.14 -5 five");
-// QTest::newRow("hex") << int(QTextStream::hex | QTextStream::showbase) << 5 << 3.14 << -5 << QString("five") << QByteArray(" 3.14 -0x5 five");
-// QTest::newRow("hex uppercase") << int(QTextStream::hex | QTextStream::uppercase | QTextStream::showbase) << 5 << 3.14 << -5 << QString("five") << QByteArray(" 3.14 -0X5 five");
+ QTest::newRow("no flags") << 10 << 0 << 0 << 0 << 5.0 << 5 << QString("five") << QByteArray("55five");
+ QTest::newRow("rightadjust") << 10 << int(QTextStream::AlignRight) << 0 << 10 << 5.0 << 5 << QString("five") << QByteArray(" 5 5 five");
+ QTest::newRow("leftadjust") << 10 << int(QTextStream::AlignLeft) << 0 << 10 << 5.0 << 5 << QString("five") << QByteArray("5 5 five ");
+ QTest::newRow("showpos") << 10 << int(QTextStream::AlignRight) << int(QTextStream::ForceSign) << 10 << 5.0 << 5 << QString("five") << QByteArray(" +5 +5 five");
+ QTest::newRow("showpos2") << 10 << int(QTextStream::AlignRight) << int(QTextStream::ForceSign) << 5 << 3.14 << -5 << QString("five") << QByteArray("+3.14 -5 five");
+ QTest::newRow("hex") << 16 << int(QTextStream::AlignRight) << int(QTextStream::ShowBase) << 5 << 3.14 << -5 << QString("five") << QByteArray(" 3.14 -0x5 five");
+ QTest::newRow("hex") << 16 << int(QTextStream::AlignRight) << int(QTextStream::ShowBase | QTextStream::UppercaseBase) << 5 << 3.14 << -5 << QString("five") << QByteArray(" 3.14 -0X5 five");
}
// ------------------------------------------------------------------------------
void tst_QTextStream::manipulators()
{
-// QFETCH(int, flags);
+ QFETCH(int, base);
+ QFETCH(int, alignFlag);
+ QFETCH(int, numberFlag);
QFETCH(int, width);
QFETCH(double, realNumber);
QFETCH(int, intNumber);
@@ -2700,14 +2706,16 @@ void tst_QTextStream::manipulators()
stream.setCodec(QTextCodec::codecForName("ISO-8859-1"));
stream.setAutoDetectUnicode(true);
-// stream.setFlags(flags);
+ stream.setIntegerBase(base);
+ stream.setFieldAlignment(QTextStream::FieldAlignment(alignFlag));
+ stream.setNumberFlags(QTextStream::NumberFlag(numberFlag));
stream.setFieldWidth(width);
stream << realNumber;
stream << intNumber;
stream << textData;
stream.flush();
- QCOMPARE(buffer.data().constData(), result.constData());
+ QCOMPARE(buffer.data(), result);
}
void tst_QTextStream::generateBOM()
@@ -2719,7 +2727,7 @@ void tst_QTextStream::generateBOM()
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-16LE"));
- stream << "Hello" << endl;
+ stream << "Hello" << Qt::endl;
file.close();
QVERIFY(file.open(QFile::ReadOnly));
@@ -2733,7 +2741,7 @@ void tst_QTextStream::generateBOM()
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-16LE"));
- stream << bom << "Hello" << endl;
+ stream << Qt::bom << "Hello" << Qt::endl;
file.close();
QVERIFY(file.open(QFile::ReadOnly));
diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
index 8fdf91b090..92a0d8bbfa 100644
--- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
@@ -115,7 +115,7 @@ static QByteArray makeCanonical(const QString &filename,
writeDtd << "<!DOCTYPE ";
writeDtd << docType;
writeDtd << " [";
- writeDtd << endl;
+ writeDtd << Qt::endl;
for (const QXmlStreamNotationDeclaration &notation : sorted_by_name(notationDeclarations)) {
writeDtd << "<!NOTATION ";
writeDtd << notation.name().toString();
@@ -134,11 +134,11 @@ static QByteArray makeCanonical(const QString &filename,
}
}
writeDtd << '>';
- writeDtd << endl;
+ writeDtd << Qt::endl;
}
writeDtd << "]>";
- writeDtd << endl;
+ writeDtd << Qt::endl;
writer.writeDTD(dtd);
}
} else if (reader.isStartElement()) {
@@ -253,7 +253,7 @@ public:
qFatal("%s: aId must not be an empty string", Q_FUNC_INFO);
}
- void swap(MissedBaseline &other) Q_DECL_NOTHROW
+ void swap(MissedBaseline &other) noexcept
{
qSwap(id, other.id);
qSwap(expected, other.expected);
@@ -740,7 +740,7 @@ QByteArray tst_QXmlStream::readFile(const QString &filename)
const auto attributes = reader.attributes();
if (attributes.size()) {
for (const QXmlStreamAttribute &attribute : attributes) {
- writer << endl << " Attribute(";
+ writer << Qt::endl << " Attribute(";
if (!attribute.name().isEmpty())
writer << " name=\"" << attribute.name().toString() << '"';
if (!attribute.namespaceUri().isEmpty())
@@ -751,37 +751,37 @@ QByteArray tst_QXmlStream::readFile(const QString &filename)
writer << " prefix=\"" << attribute.prefix().toString() << '"';
if (!attribute.value().isEmpty())
writer << " value=\"" << attribute.value().toString() << '"';
- writer << " )" << endl;
+ writer << " )" << Qt::endl;
}
}
const auto namespaceDeclarations = reader.namespaceDeclarations();
if (namespaceDeclarations.size()) {
for (const QXmlStreamNamespaceDeclaration &namespaceDeclaration : namespaceDeclarations) {
- writer << endl << " NamespaceDeclaration(";
+ writer << Qt::endl << " NamespaceDeclaration(";
if (!namespaceDeclaration.prefix().isEmpty())
writer << " prefix=\"" << namespaceDeclaration.prefix().toString() << '"';
if (!namespaceDeclaration.namespaceUri().isEmpty())
writer << " namespaceUri=\"" << namespaceDeclaration.namespaceUri().toString() << '"';
- writer << " )" << endl;
+ writer << " )" << Qt::endl;
}
}
const auto notationDeclarations = reader.notationDeclarations();
if (notationDeclarations.size()) {
for (const QXmlStreamNotationDeclaration &notationDeclaration : notationDeclarations) {
- writer << endl << " NotationDeclaration(";
+ writer << Qt::endl << " NotationDeclaration(";
if (!notationDeclaration.name().isEmpty())
writer << " name=\"" << notationDeclaration.name().toString() << '"';
if (!notationDeclaration.systemId().isEmpty())
writer << " systemId=\"" << notationDeclaration.systemId().toString() << '"';
if (!notationDeclaration.publicId().isEmpty())
writer << " publicId=\"" << notationDeclaration.publicId().toString() << '"';
- writer << " )" << endl;
+ writer << " )" << Qt::endl;
}
}
const auto entityDeclarations = reader.entityDeclarations();
if (entityDeclarations.size()) {
for (const QXmlStreamEntityDeclaration &entityDeclaration : entityDeclarations) {
- writer << endl << " EntityDeclaration(";
+ writer << Qt::endl << " EntityDeclaration(";
if (!entityDeclaration.name().isEmpty())
writer << " name=\"" << entityDeclaration.name().toString() << '"';
if (!entityDeclaration.notationName().isEmpty())
@@ -792,13 +792,13 @@ QByteArray tst_QXmlStream::readFile(const QString &filename)
writer << " publicId=\"" << entityDeclaration.publicId().toString() << '"';
if (!entityDeclaration.value().isEmpty())
writer << " value=\"" << entityDeclaration.value().toString() << '"';
- writer << " )" << endl;
+ writer << " )" << Qt::endl;
}
}
- writer << " )" << endl;
+ writer << " )" << Qt::endl;
}
if (reader.hasError())
- writer << "ERROR: " << reader.errorString() << endl;
+ writer << "ERROR: " << reader.errorString() << Qt::endl;
return outarray;
}
@@ -1169,7 +1169,7 @@ int main(int argc, char *argv[])
bool error = false;
QByteArray canonical = makeCanonical(argv[2], "doc", error);
QTextStream myStdOut(stdout);
- myStdOut << canonical << endl;
+ myStdOut << canonical << Qt::endl;
exit(0);
}
diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
index 810698fb4e..72a6f0360d 100644
--- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
@@ -336,7 +336,9 @@ void tst_QStateMachine::transitionToRootState()
TEST_ACTIVE_CHANGED(initialState, 1);
machine.postEvent(new QEvent(QEvent::User));
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 'initial'");
+ QTest::ignoreMessage(QtWarningMsg,
+ "Unrecoverable error detected in running state machine: "
+ "Child mode of state machine 'machine' is not 'ExclusiveStates'!");
QCoreApplication::processEvents();
QVERIFY(machine.configuration().isEmpty());
QVERIFY(!machine.isRunning());
@@ -1061,7 +1063,8 @@ void tst_QStateMachine::transitionToStateNotInGraph()
initialState->addTransition(&independentState);
machine.start();
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 'initialState'");
+ QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: "
+ "Child mode of state machine '' is not 'ExclusiveStates'!");
QCoreApplication::processEvents();
QCOMPARE(machine.isRunning(), false);
@@ -1734,13 +1737,13 @@ protected:
if (e->type() != QEvent::Type(QEvent::User+2))
return false;
StringEvent *se = static_cast<StringEvent*>(e);
- return (m_value == se->value) && (!m_cond.isValid() || (m_cond.indexIn(m_value) != -1));
+ return (m_value == se->value) && (!m_cond.isValid() || m_cond.match(m_value).hasMatch());
}
virtual void onTransition(QEvent *) {}
private:
QString m_value;
- QRegExp m_cond;
+ QRegularExpression m_cond;
};
class StringEventPoster : public QState
@@ -2099,6 +2102,8 @@ void tst_QStateMachine::parallelRootState()
QSignalSpy finishedSpy(&machine, &QStateMachine::finished);
QVERIFY(finishedSpy.isValid());
machine.start();
+ QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: "
+ "Child mode of state machine '' is not 'ExclusiveStates'!");
QTRY_COMPARE(startedSpy.count(), 1);
QCOMPARE(machine.configuration().size(), 4);
QVERIFY(machine.configuration().contains(s1));
@@ -3310,14 +3315,15 @@ void tst_QStateMachine::targetStateWithNoParent()
QVERIFY(runningSpy.isValid());
machine.start();
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 's1'");
+ QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: "
+ "Child mode of state machine '' is not 'ExclusiveStates'!");
TEST_ACTIVE_CHANGED(s1, 2);
QTRY_COMPARE(startedSpy.count(), 1);
QCOMPARE(machine.isRunning(), false);
QCOMPARE(stoppedSpy.count(), 1);
QCOMPARE(finishedSpy.count(), 0);
TEST_RUNNING_CHANGED_STARTED_STOPPED;
- QCOMPARE(machine.error(), QStateMachine::NoCommonAncestorForTransitionError);
+ QCOMPARE(machine.error(), QStateMachine::StateMachineChildModeSetToParallelError);
}
void tst_QStateMachine::targetStateDeleted()
@@ -6680,13 +6686,13 @@ void tst_QStateMachine::dontProcessSlotsWhenMachineIsNotRunning()
} emitter;
initialState.addTransition(&emitter, &Emitter::signalWithNoArg, &finalState);
- QTimer::singleShot(0, [&]() {
- metaObject()->invokeMethod(&emitter, "emitSignalWithNoArg");
- metaObject()->invokeMethod(&emitter, "emitSignalWithNoArg");
- });
machine.addState(&initialState);
machine.addState(&finalState);
machine.setInitialState(&initialState);
+ connect(&machine, &QStateMachine::started, &emitter, [&]() {
+ metaObject()->invokeMethod(&emitter, "emitSignalWithNoArg");
+ metaObject()->invokeMethod(&emitter, "emitSignalWithNoArg");
+ });
connect(&machine, &QStateMachine::finished, &emitter.thread, &QThread::quit);
machine.start();
QSignalSpy emittedSpy(&emitter, &SignalEmitter::signalWithNoArg);
diff --git a/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp b/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp
index cc197cabba..bef491d5f0 100644
--- a/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp
+++ b/tests/auto/corelib/thread/qatomicint/tst_qatomicint.cpp
@@ -31,6 +31,7 @@
#include <QAtomicInt>
#include <QCoreApplication>
+#include <QElapsedTimer>
#include <limits.h>
@@ -104,12 +105,12 @@ static void warningFreeHelperTemplate()
assemblyMarker<1>(&i);
// the loads sometimes generate no assembly output
- i.load();
+ i.loadRelaxed();
assemblyMarker<11>(&i);
i.loadAcquire();
assemblyMarker<12>(&i);
- i.store(newValue);
+ i.storeRelaxed(newValue);
assemblyMarker<21>(&i);
i.storeRelease(newValue);
assemblyMarker<22>(&i);
@@ -281,9 +282,9 @@ void tst_QAtomicInt::constructor()
{
QFETCH(int, value);
QAtomicInt atomic1(value);
- QCOMPARE(atomic1.load(), value);
+ QCOMPARE(atomic1.loadRelaxed(), value);
QAtomicInt atomic2 = value;
- QCOMPARE(atomic2.load(), value);
+ QCOMPARE(atomic2.loadRelaxed(), value);
}
void tst_QAtomicInt::copy_constructor_data()
@@ -293,16 +294,16 @@ void tst_QAtomicInt::copy_constructor()
{
QFETCH(int, value);
QAtomicInt atomic1(value);
- QCOMPARE(atomic1.load(), value);
+ QCOMPARE(atomic1.loadRelaxed(), value);
QAtomicInt atomic2(atomic1);
- QCOMPARE(atomic2.load(), value);
+ QCOMPARE(atomic2.loadRelaxed(), value);
QAtomicInt atomic3 = atomic1;
- QCOMPARE(atomic3.load(), value);
+ QCOMPARE(atomic3.loadRelaxed(), value);
QAtomicInt atomic4(atomic2);
- QCOMPARE(atomic4.load(), value);
+ QCOMPARE(atomic4.loadRelaxed(), value);
QAtomicInt atomic5 = atomic2;
- QCOMPARE(atomic5.load(), value);
+ QCOMPARE(atomic5.loadRelaxed(), value);
}
void tst_QAtomicInt::assignment_operator_data()
@@ -326,13 +327,13 @@ void tst_QAtomicInt::assignment_operator()
{
QAtomicInt atomic1 = value;
atomic1 = newval;
- QCOMPARE(atomic1.load(), newval);
+ QCOMPARE(atomic1.loadRelaxed(), newval);
atomic1 = value;
- QCOMPARE(atomic1.load(), value);
+ QCOMPARE(atomic1.loadRelaxed(), value);
QAtomicInt atomic2 = newval;
atomic1 = atomic2;
- QCOMPARE(atomic1.load(), atomic2.load());
+ QCOMPARE(atomic1.loadRelaxed(), atomic2.loadRelaxed());
}
}
@@ -400,7 +401,7 @@ void tst_QAtomicInt::ref()
QFETCH(int, value);
QAtomicInt x = value;
QTEST(x.ref() ? 1 : 0, "result");
- QTEST(x.load(), "expected");
+ QTEST(x.loadRelaxed(), "expected");
}
void tst_QAtomicInt::deref_data()
@@ -419,7 +420,7 @@ void tst_QAtomicInt::deref()
QFETCH(int, value);
QAtomicInt x = value;
QTEST(x.deref() ? 1 : 0, "result");
- QTEST(x.load(), "expected");
+ QTEST(x.loadRelaxed(), "expected");
}
void tst_QAtomicInt::isTestAndSetNative()
@@ -635,25 +636,25 @@ void tst_QAtomicInt::fetchAndStore()
{
QAtomicInt atomic = value;
QCOMPARE(atomic.fetchAndStoreRelaxed(newval), value);
- QCOMPARE(atomic.load(), newval);
+ QCOMPARE(atomic.loadRelaxed(), newval);
}
{
QAtomicInt atomic = value;
QCOMPARE(atomic.fetchAndStoreAcquire(newval), value);
- QCOMPARE(atomic.load(), newval);
+ QCOMPARE(atomic.loadRelaxed(), newval);
}
{
QAtomicInt atomic = value;
QCOMPARE(atomic.fetchAndStoreRelease(newval), value);
- QCOMPARE(atomic.load(), newval);
+ QCOMPARE(atomic.loadRelaxed(), newval);
}
{
QAtomicInt atomic = value;
QCOMPARE(atomic.fetchAndStoreOrdered(newval), value);
- QCOMPARE(atomic.load(), newval);
+ QCOMPARE(atomic.loadRelaxed(), newval);
}
}
@@ -772,28 +773,28 @@ void tst_QAtomicInt::fetchAndAdd()
QAtomicInt atomic = value1;
result = atomic.fetchAndAddRelaxed(value2);
QCOMPARE(result, value1);
- QCOMPARE(atomic.load(), value1 + value2);
+ QCOMPARE(atomic.loadRelaxed(), value1 + value2);
}
{
QAtomicInt atomic = value1;
result = atomic.fetchAndAddAcquire(value2);
QCOMPARE(result, value1);
- QCOMPARE(atomic.load(), value1 + value2);
+ QCOMPARE(atomic.loadRelaxed(), value1 + value2);
}
{
QAtomicInt atomic = value1;
result = atomic.fetchAndAddRelease(value2);
QCOMPARE(result, value1);
- QCOMPARE(atomic.load(), value1 + value2);
+ QCOMPARE(atomic.loadRelaxed(), value1 + value2);
}
{
QAtomicInt atomic = value1;
result = atomic.fetchAndAddOrdered(value2);
QCOMPARE(result, value1);
- QCOMPARE(atomic.load(), value1 + value2);
+ QCOMPARE(atomic.loadRelaxed(), value1 + value2);
}
}
@@ -851,14 +852,14 @@ void tst_QAtomicInt::operators()
void tst_QAtomicInt::testAndSet_loop()
{
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
int iterations = 10000000;
QAtomicInt val=0;
for (int i = 0; i < iterations; ++i) {
- int v = val.load();
+ int v = val.loadRelaxed();
QVERIFY(val.testAndSetRelaxed(v, v+1));
if ((i % 1000) == 999) {
if (stopWatch.elapsed() > 60 * 1000) {
@@ -881,7 +882,7 @@ void tst_QAtomicInt::fetchAndAdd_loop()
QAtomicInt val=0;
for (int i = 0; i < iterations; ++i) {
const int prev = val.fetchAndAddRelaxed(1);
- QCOMPARE(prev, val.load() -1);
+ QCOMPARE(prev, val.loadRelaxed() -1);
}
}
@@ -919,7 +920,7 @@ void tst_QAtomicInt::fetchAndAdd_threadedLoop()
t1.wait();
t2.wait();
- QCOMPARE(val.load(), 0);
+ QCOMPARE(val.loadRelaxed(), 0);
}
QTEST_MAIN(tst_QAtomicInt)
diff --git a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
index 32e5b8ee56..bfe2a60088 100644
--- a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
+++ b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp
@@ -270,13 +270,13 @@ void tst_QAtomicIntegerXX::constructor()
QFETCH(LargeInt, value);
QAtomicInteger<T> atomic(value);
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QAtomicInteger<T> atomic2 = value;
- QCOMPARE(atomic2.load(), T(value));
+ QCOMPARE(atomic2.loadRelaxed(), T(value));
- QVERIFY(atomic.load() >= std::numeric_limits<T>::min());
- QVERIFY(atomic.load() <= std::numeric_limits<T>::max());
+ QVERIFY(atomic.loadRelaxed() >= std::numeric_limits<T>::min());
+ QVERIFY(atomic.loadRelaxed() <= std::numeric_limits<T>::max());
}
void tst_QAtomicIntegerXX::copy()
@@ -285,17 +285,17 @@ void tst_QAtomicIntegerXX::copy()
QAtomicInteger<T> atomic(value);
QAtomicInteger<T> copy(atomic);
- QCOMPARE(copy.load(), atomic.load());
+ QCOMPARE(copy.loadRelaxed(), atomic.loadRelaxed());
QAtomicInteger<T> copy2 = atomic;
- QCOMPARE(copy2.load(), atomic.load());
+ QCOMPARE(copy2.loadRelaxed(), atomic.loadRelaxed());
// move
- QAtomicInteger<T> copy3(qMove(copy));
- QCOMPARE(copy3.load(), atomic.load());
+ QAtomicInteger<T> copy3(std::move(copy));
+ QCOMPARE(copy3.loadRelaxed(), atomic.loadRelaxed());
- QAtomicInteger<T> copy4 = qMove(copy2);
- QCOMPARE(copy4.load(), atomic.load());
+ QAtomicInteger<T> copy4 = std::move(copy2);
+ QCOMPARE(copy4.loadRelaxed(), atomic.loadRelaxed());
}
void tst_QAtomicIntegerXX::assign()
@@ -305,24 +305,24 @@ void tst_QAtomicIntegerXX::assign()
QAtomicInteger<T> atomic(value);
QAtomicInteger<T> copy;
copy = atomic;
- QCOMPARE(copy.load(), atomic.load());
+ QCOMPARE(copy.loadRelaxed(), atomic.loadRelaxed());
QAtomicInteger<T> copy2;
copy2 = atomic; // operator=(const QAtomicInteger &)
- QCOMPARE(copy2.load(), atomic.load());
+ QCOMPARE(copy2.loadRelaxed(), atomic.loadRelaxed());
QAtomicInteger<T> copy2bis;
- copy2bis = atomic.load(); // operator=(T)
- QCOMPARE(copy2bis.load(), atomic.load());
+ copy2bis = atomic.loadRelaxed(); // operator=(T)
+ QCOMPARE(copy2bis.loadRelaxed(), atomic.loadRelaxed());
// move
QAtomicInteger<T> copy3;
- copy3 = qMove(copy);
- QCOMPARE(copy3.load(), atomic.load());
+ copy3 = std::move(copy);
+ QCOMPARE(copy3.loadRelaxed(), atomic.loadRelaxed());
QAtomicInteger<T> copy4;
- copy4 = qMove(copy2);
- QCOMPARE(copy4.load(), atomic.load());
+ copy4 = std::move(copy2);
+ QCOMPARE(copy4.loadRelaxed(), atomic.loadRelaxed());
}
void tst_QAtomicIntegerXX::operatorInteger()
@@ -331,7 +331,7 @@ void tst_QAtomicIntegerXX::operatorInteger()
QAtomicInteger<T> atomic(value);
T val2 = atomic;
- QCOMPARE(val2, atomic.load());
+ QCOMPARE(val2, atomic.loadRelaxed());
QCOMPARE(val2, T(value));
}
@@ -346,7 +346,7 @@ void tst_QAtomicIntegerXX::loadAcquireStoreRelease()
QCOMPARE(atomic.loadAcquire(), T(~value));
atomic.storeRelease(value);
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
}
void tst_QAtomicIntegerXX::refDeref()
@@ -364,16 +364,16 @@ void tst_QAtomicIntegerXX::refDeref()
QAtomicInteger<T> atomic(value);
if (!needToPreventOverflow) {
QCOMPARE(atomic.ref(), (nextValue != 0));
- QCOMPARE(atomic.load(), nextValue);
+ QCOMPARE(atomic.loadRelaxed(), nextValue);
QCOMPARE(atomic.deref(), (value != 0));
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventUnderflow) {
QCOMPARE(atomic.deref(), (prevValue != 0));
- QCOMPARE(atomic.load(), prevValue);
+ QCOMPARE(atomic.loadRelaxed(), prevValue);
QCOMPARE(atomic.ref(), (value != 0));
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventOverflow) {
QCOMPARE(++atomic, nextValue);
@@ -392,7 +392,7 @@ void tst_QAtomicIntegerXX::refDeref()
QCOMPARE(atomic--, T(value));
QCOMPARE(atomic++, prevValue);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
}
void tst_QAtomicIntegerXX::testAndSet()
@@ -402,16 +402,16 @@ void tst_QAtomicIntegerXX::testAndSet()
QAtomicInteger<T> atomic(value);
QVERIFY(atomic.testAndSetRelaxed(value, newValue));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QVERIFY(!atomic.testAndSetRelaxed(value, newValue));
QVERIFY(atomic.testAndSetRelaxed(newValue, value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QVERIFY(atomic.testAndSetAcquire(value, newValue));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QVERIFY(!atomic.testAndSetAcquire(value, newValue));
QVERIFY(atomic.testAndSetAcquire(newValue, value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QVERIFY(atomic.testAndSetRelease(value, newValue));
QCOMPARE(atomic.loadAcquire(), newValue);
@@ -434,18 +434,18 @@ void tst_QAtomicIntegerXX::testAndSet3()
QAtomicInteger<T> atomic(value);
QVERIFY(atomic.testAndSetRelaxed(value, newValue, oldValue));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QVERIFY(!atomic.testAndSetRelaxed(value, newValue, oldValue));
QCOMPARE(oldValue, newValue);
QVERIFY(atomic.testAndSetRelaxed(newValue, value, oldValue));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QVERIFY(atomic.testAndSetAcquire(value, newValue, oldValue));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QVERIFY(!atomic.testAndSetAcquire(value, newValue, oldValue));
QCOMPARE(oldValue, newValue);
QVERIFY(atomic.testAndSetAcquire(newValue, value, oldValue));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QVERIFY(atomic.testAndSetRelease(value, newValue, oldValue));
QCOMPARE(atomic.loadAcquire(), newValue);
@@ -469,14 +469,14 @@ void tst_QAtomicIntegerXX::fetchAndStore()
QAtomicInteger<T> atomic(value);
QCOMPARE(atomic.fetchAndStoreRelaxed(newValue), T(value));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QCOMPARE(atomic.fetchAndStoreRelaxed(value), newValue);
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndStoreAcquire(newValue), T(value));
- QCOMPARE(atomic.load(), newValue);
+ QCOMPARE(atomic.loadRelaxed(), newValue);
QCOMPARE(atomic.fetchAndStoreAcquire(value), newValue);
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndStoreRelease(newValue), T(value));
QCOMPARE(atomic.loadAcquire(), newValue);
@@ -509,29 +509,29 @@ void tst_QAtomicIntegerXX::fetchAndAdd()
if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), T(value));
- QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), newValue1);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndAddRelaxed(parcel2), T(value));
- QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndAddRelaxed(parcel1), newValue2);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndAddAcquire(parcel1), T(value));
- QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndAddAcquire(parcel2), newValue1);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndAddAcquire(parcel2), T(value));
- QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndAddAcquire(parcel1), newValue2);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndAddRelease(parcel1), T(value));
@@ -590,29 +590,29 @@ void tst_QAtomicIntegerXX::fetchAndSub()
if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), T(value));
- QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), newValue1);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndSubRelaxed(parcel2), T(value));
- QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndSubRelaxed(parcel1), newValue2);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndSubAcquire(parcel1), T(value));
- QCOMPARE(atomic.load(), newValue1);
+ QCOMPARE(atomic.loadRelaxed(), newValue1);
QCOMPARE(atomic.fetchAndSubAcquire(parcel2), newValue1);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventOverflow) {
QCOMPARE(atomic.fetchAndSubAcquire(parcel2), T(value));
- QCOMPARE(atomic.load(), newValue2);
+ QCOMPARE(atomic.loadRelaxed(), newValue2);
QCOMPARE(atomic.fetchAndSubAcquire(parcel1), newValue2);
}
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
if (!needToPreventUnderflow) {
QCOMPARE(atomic.fetchAndSubRelease(parcel1), T(value));
@@ -662,32 +662,32 @@ void tst_QAtomicIntegerXX::fetchAndOr()
QCOMPARE(atomic.fetchAndOrRelaxed(zero), T(value));
QCOMPARE(atomic.fetchAndOrRelaxed(one), T(value));
- QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.loadRelaxed(), T(value | 1));
QCOMPARE(atomic.fetchAndOrRelaxed(minusOne), T(value | 1));
- QCOMPARE(atomic.load(), minusOne);
+ QCOMPARE(atomic.loadRelaxed(), minusOne);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndOrAcquire(zero), T(value));
QCOMPARE(atomic.fetchAndOrAcquire(one), T(value));
- QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.loadRelaxed(), T(value | 1));
QCOMPARE(atomic.fetchAndOrAcquire(minusOne), T(value | 1));
- QCOMPARE(atomic.load(), minusOne);
+ QCOMPARE(atomic.loadRelaxed(), minusOne);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndOrRelease(zero), T(value));
QCOMPARE(atomic.fetchAndOrRelease(one), T(value));
- QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.loadRelaxed(), T(value | 1));
QCOMPARE(atomic.fetchAndOrRelease(minusOne), T(value | 1));
- QCOMPARE(atomic.load(), minusOne);
+ QCOMPARE(atomic.loadRelaxed(), minusOne);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndOrOrdered(zero), T(value));
QCOMPARE(atomic.fetchAndOrOrdered(one), T(value));
- QCOMPARE(atomic.load(), T(value | 1));
+ QCOMPARE(atomic.loadRelaxed(), T(value | 1));
QCOMPARE(atomic.fetchAndOrOrdered(minusOne), T(value | 1));
- QCOMPARE(atomic.load(), minusOne);
+ QCOMPARE(atomic.loadRelaxed(), minusOne);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic |= zero, T(value));
QCOMPARE(atomic |= one, T(value | 1));
QCOMPARE(atomic |= minusOne, minusOne);
@@ -703,37 +703,37 @@ void tst_QAtomicIntegerXX::fetchAndAnd()
T minusOne = T(~0);
QCOMPARE(atomic.fetchAndAndRelaxed(minusOne), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndAndRelaxed(f), T(value));
- QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.loadRelaxed(), T(value & 0xf));
QCOMPARE(atomic.fetchAndAndRelaxed(zero), T(value & 0xf));
- QCOMPARE(atomic.load(), zero);
+ QCOMPARE(atomic.loadRelaxed(), zero);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndAndAcquire(minusOne), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndAndAcquire(f), T(value));
- QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.loadRelaxed(), T(value & 0xf));
QCOMPARE(atomic.fetchAndAndAcquire(zero), T(value & 0xf));
- QCOMPARE(atomic.load(), zero);
+ QCOMPARE(atomic.loadRelaxed(), zero);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndAndRelease(minusOne), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndAndRelease(f), T(value));
- QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.loadRelaxed(), T(value & 0xf));
QCOMPARE(atomic.fetchAndAndRelease(zero), T(value & 0xf));
- QCOMPARE(atomic.load(), zero);
+ QCOMPARE(atomic.loadRelaxed(), zero);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic.fetchAndAndOrdered(minusOne), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndAndOrdered(f), T(value));
- QCOMPARE(atomic.load(), T(value & 0xf));
+ QCOMPARE(atomic.loadRelaxed(), T(value & 0xf));
QCOMPARE(atomic.fetchAndAndOrdered(zero), T(value & 0xf));
- QCOMPARE(atomic.load(), zero);
+ QCOMPARE(atomic.loadRelaxed(), zero);
- atomic.store(value);
+ atomic.storeRelaxed(value);
QCOMPARE(atomic &= minusOne, T(value));
QCOMPARE(atomic &= f, T(value & 0xf));
QCOMPARE(atomic &= zero, zero);
@@ -749,48 +749,48 @@ void tst_QAtomicIntegerXX::fetchAndXor()
T minusOne = T(~0);
QCOMPARE(atomic.fetchAndXorRelaxed(zero), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorRelaxed(pattern), T(value));
- QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.loadRelaxed(), T(value ^ pattern));
QCOMPARE(atomic.fetchAndXorRelaxed(pattern), T(value ^ pattern));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorRelaxed(minusOne), T(value));
- QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.loadRelaxed(), T(~value));
QCOMPARE(atomic.fetchAndXorRelaxed(minusOne), T(~value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorAcquire(zero), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorAcquire(pattern), T(value));
- QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.loadRelaxed(), T(value ^ pattern));
QCOMPARE(atomic.fetchAndXorAcquire(pattern), T(value ^ pattern));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorAcquire(minusOne), T(value));
- QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.loadRelaxed(), T(~value));
QCOMPARE(atomic.fetchAndXorAcquire(minusOne), T(~value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorRelease(zero), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorRelease(pattern), T(value));
- QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.loadRelaxed(), T(value ^ pattern));
QCOMPARE(atomic.fetchAndXorRelease(pattern), T(value ^ pattern));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorRelease(minusOne), T(value));
- QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.loadRelaxed(), T(~value));
QCOMPARE(atomic.fetchAndXorRelease(minusOne), T(~value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorOrdered(zero), T(value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorOrdered(pattern), T(value));
- QCOMPARE(atomic.load(), T(value ^ pattern));
+ QCOMPARE(atomic.loadRelaxed(), T(value ^ pattern));
QCOMPARE(atomic.fetchAndXorOrdered(pattern), T(value ^ pattern));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic.fetchAndXorOrdered(minusOne), T(value));
- QCOMPARE(atomic.load(), T(~value));
+ QCOMPARE(atomic.loadRelaxed(), T(~value));
QCOMPARE(atomic.fetchAndXorOrdered(minusOne), T(~value));
- QCOMPARE(atomic.load(), T(value));
+ QCOMPARE(atomic.loadRelaxed(), T(value));
QCOMPARE(atomic ^= zero, T(value));
QCOMPARE(atomic ^= pattern, T(value ^ pattern));
diff --git a/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp b/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp
index 0200473cae..a699cf6202 100644
--- a/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp
+++ b/tests/auto/corelib/thread/qatomicpointer/tst_qatomicpointer.cpp
@@ -75,7 +75,7 @@ void tst_QAtomicPointer::warningFreeHelper()
QBasicAtomicPointer<WFHC> p = Q_BASIC_ATOMIC_INITIALIZER(0);
- p.load()->bar();
+ p.loadRelaxed()->bar();
WFHC *expectedValue = 0;
WFHC *newValue = 0;
@@ -119,15 +119,15 @@ void tst_QAtomicPointer::constructor()
{
void *one = this;
QAtomicPointer<void> atomic1 = one;
- QCOMPARE(atomic1.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), one);
void *two = &one;
QAtomicPointer<void> atomic2 = two;
- QCOMPARE(atomic2.load(), two);
+ QCOMPARE(atomic2.loadRelaxed(), two);
void *three = &two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic3.loadRelaxed(), three);
}
void tst_QAtomicPointer::copy_constructor()
@@ -135,20 +135,20 @@ void tst_QAtomicPointer::copy_constructor()
void *one = this;
QAtomicPointer<void> atomic1 = one;
QAtomicPointer<void> atomic1_copy = atomic1;
- QCOMPARE(atomic1_copy.load(), one);
- QCOMPARE(atomic1_copy.load(), atomic1.load());
+ QCOMPARE(atomic1_copy.loadRelaxed(), one);
+ QCOMPARE(atomic1_copy.loadRelaxed(), atomic1.loadRelaxed());
void *two = &one;
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic2_copy = atomic2;
- QCOMPARE(atomic2_copy.load(), two);
- QCOMPARE(atomic2_copy.load(), atomic2.load());
+ QCOMPARE(atomic2_copy.loadRelaxed(), two);
+ QCOMPARE(atomic2_copy.loadRelaxed(), atomic2.loadRelaxed());
void *three = &two;
QAtomicPointer<void> atomic3 = three;
QAtomicPointer<void> atomic3_copy = atomic3;
- QCOMPARE(atomic3_copy.load(), three);
- QCOMPARE(atomic3_copy.load(), atomic3.load());
+ QCOMPARE(atomic3_copy.loadRelaxed(), three);
+ QCOMPARE(atomic3_copy.loadRelaxed(), atomic3.loadRelaxed());
}
void tst_QAtomicPointer::assignment_operator()
@@ -161,17 +161,17 @@ void tst_QAtomicPointer::assignment_operator()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
atomic1 = two;
atomic2 = three;
atomic3 = one;
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
void tst_QAtomicPointer::isTestAndSetNative()
@@ -234,17 +234,17 @@ void tst_QAtomicPointer::testAndSet()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QVERIFY(atomic1.testAndSetRelaxed(one, two));
QVERIFY(atomic2.testAndSetRelaxed(two, three));
QVERIFY(atomic3.testAndSetRelaxed(three, one));
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -252,17 +252,17 @@ void tst_QAtomicPointer::testAndSet()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QVERIFY(atomic1.testAndSetAcquire(one, two));
QVERIFY(atomic2.testAndSetAcquire(two, three));
QVERIFY(atomic3.testAndSetAcquire(three, one));
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -270,17 +270,17 @@ void tst_QAtomicPointer::testAndSet()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QVERIFY(atomic1.testAndSetRelease(one, two));
QVERIFY(atomic2.testAndSetRelease(two, three));
QVERIFY(atomic3.testAndSetRelease(three, one));
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -288,17 +288,17 @@ void tst_QAtomicPointer::testAndSet()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QVERIFY(atomic1.testAndSetOrdered(one, two));
QVERIFY(atomic2.testAndSetOrdered(two, three));
QVERIFY(atomic3.testAndSetOrdered(three, one));
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
}
@@ -362,17 +362,17 @@ void tst_QAtomicPointer::fetchAndStore()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QCOMPARE(atomic1.fetchAndStoreRelaxed(two), one);
QCOMPARE(atomic2.fetchAndStoreRelaxed(three), two);
QCOMPARE(atomic3.fetchAndStoreRelaxed(one), three);
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -380,17 +380,17 @@ void tst_QAtomicPointer::fetchAndStore()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QCOMPARE(atomic1.fetchAndStoreAcquire(two), one);
QCOMPARE(atomic2.fetchAndStoreAcquire(three), two);
QCOMPARE(atomic3.fetchAndStoreAcquire(one), three);
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -398,17 +398,17 @@ void tst_QAtomicPointer::fetchAndStore()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QCOMPARE(atomic1.fetchAndStoreRelease(two), one);
QCOMPARE(atomic2.fetchAndStoreRelease(three), two);
QCOMPARE(atomic3.fetchAndStoreRelease(one), three);
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
{
@@ -416,17 +416,17 @@ void tst_QAtomicPointer::fetchAndStore()
QAtomicPointer<void> atomic2 = two;
QAtomicPointer<void> atomic3 = three;
- QCOMPARE(atomic1.load(), one);
- QCOMPARE(atomic2.load(), two);
- QCOMPARE(atomic3.load(), three);
+ QCOMPARE(atomic1.loadRelaxed(), one);
+ QCOMPARE(atomic2.loadRelaxed(), two);
+ QCOMPARE(atomic3.loadRelaxed(), three);
QCOMPARE(atomic1.fetchAndStoreOrdered(two), one);
QCOMPARE(atomic2.fetchAndStoreOrdered(three), two);
QCOMPARE(atomic3.fetchAndStoreOrdered(one), three);
- QCOMPARE(atomic1.load(), two);
- QCOMPARE(atomic2.load(), three);
- QCOMPARE(atomic3.load(), one);
+ QCOMPARE(atomic1.loadRelaxed(), two);
+ QCOMPARE(atomic2.loadRelaxed(), three);
+ QCOMPARE(atomic3.loadRelaxed(), one);
}
}
@@ -530,60 +530,60 @@ void tst_QAtomicPointer::fetchAndAdd()
// cast to void* in order to avoid QCOMPARE to compare string content of the char*
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddRelaxed(valueToAdd)), static_cast<void*>(pc));
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddRelaxed(-valueToAdd)), static_cast<void*>(pc + valueToAdd));
- QCOMPARE(static_cast<void*>(pointer1.load()), static_cast<void*>(pc));
+ QCOMPARE(static_cast<void*>(pointer1.loadRelaxed()), static_cast<void*>(pc));
QAtomicPointer<short> pointer2 = ps;
QCOMPARE(pointer2.fetchAndAddRelaxed(valueToAdd), ps);
QCOMPARE(pointer2.fetchAndAddRelaxed(-valueToAdd), ps + valueToAdd);
- QCOMPARE(pointer2.load(), ps);
+ QCOMPARE(pointer2.loadRelaxed(), ps);
QAtomicPointer<int> pointer3 = pi;
QCOMPARE(pointer3.fetchAndAddRelaxed(valueToAdd), pi);
QCOMPARE(pointer3.fetchAndAddRelaxed(-valueToAdd), pi + valueToAdd);
- QCOMPARE(pointer3.load(), pi);
+ QCOMPARE(pointer3.loadRelaxed(), pi);
}
{
QAtomicPointer<char> pointer1 = pc;
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddAcquire(valueToAdd)), static_cast<void*>(pc));
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddAcquire(-valueToAdd)), static_cast<void*>(pc + valueToAdd));
- QCOMPARE(static_cast<void*>(pointer1.load()), static_cast<void*>(pc));
+ QCOMPARE(static_cast<void*>(pointer1.loadRelaxed()), static_cast<void*>(pc));
QAtomicPointer<short> pointer2 = ps;
QCOMPARE(pointer2.fetchAndAddAcquire(valueToAdd), ps);
QCOMPARE(pointer2.fetchAndAddAcquire(-valueToAdd), ps + valueToAdd);
- QCOMPARE(pointer2.load(), ps);
+ QCOMPARE(pointer2.loadRelaxed(), ps);
QAtomicPointer<int> pointer3 = pi;
QCOMPARE(pointer3.fetchAndAddAcquire(valueToAdd), pi);
QCOMPARE(pointer3.fetchAndAddAcquire(-valueToAdd), pi + valueToAdd);
- QCOMPARE(pointer3.load(), pi);
+ QCOMPARE(pointer3.loadRelaxed(), pi);
}
{
QAtomicPointer<char> pointer1 = pc;
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddRelease(valueToAdd)), static_cast<void*>(pc));
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddRelease(-valueToAdd)), static_cast<void*>(pc + valueToAdd));
- QCOMPARE(static_cast<void*>(pointer1.load()), static_cast<void*>(pc));
+ QCOMPARE(static_cast<void*>(pointer1.loadRelaxed()), static_cast<void*>(pc));
QAtomicPointer<short> pointer2 = ps;
QCOMPARE(pointer2.fetchAndAddRelease(valueToAdd), ps);
QCOMPARE(pointer2.fetchAndAddRelease(-valueToAdd), ps + valueToAdd);
- QCOMPARE(pointer2.load(), ps);
+ QCOMPARE(pointer2.loadRelaxed(), ps);
QAtomicPointer<int> pointer3 = pi;
QCOMPARE(pointer3.fetchAndAddRelease(valueToAdd), pi);
QCOMPARE(pointer3.fetchAndAddRelease(-valueToAdd), pi + valueToAdd);
- QCOMPARE(pointer3.load(), pi);
+ QCOMPARE(pointer3.loadRelaxed(), pi);
}
{
QAtomicPointer<char> pointer1 = pc;
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddOrdered(valueToAdd)), static_cast<void*>(pc));
QCOMPARE(static_cast<void*>(pointer1.fetchAndAddOrdered(-valueToAdd)), static_cast<void*>(pc + valueToAdd));
- QCOMPARE(static_cast<void*>(pointer1.load()), static_cast<void*>(pc));
+ QCOMPARE(static_cast<void*>(pointer1.loadRelaxed()), static_cast<void*>(pc));
QAtomicPointer<short> pointer2 = ps;
QCOMPARE(pointer2.fetchAndAddOrdered(valueToAdd), ps);
QCOMPARE(pointer2.fetchAndAddOrdered(-valueToAdd), ps + valueToAdd);
- QCOMPARE(pointer2.load(), ps);
+ QCOMPARE(pointer2.loadRelaxed(), ps);
QAtomicPointer<int> pointer3 = pi;
QCOMPARE(pointer3.fetchAndAddOrdered(valueToAdd), pi);
QCOMPARE(pointer3.fetchAndAddOrdered(-valueToAdd), pi + valueToAdd);
- QCOMPARE(pointer3.load(), pi);
+ QCOMPARE(pointer3.loadRelaxed(), pi);
}
}
@@ -598,34 +598,34 @@ template <typename T> void constAndVolatile_helper()
QAtomicPointer<T> atomic2 = two;
QAtomicPointer<T> atomic3 = three;
- QVERIFY(atomic1.load() == one);
- QVERIFY(atomic2.load() == two);
- QVERIFY(atomic3.load() == three);
+ QVERIFY(atomic1.loadRelaxed() == one);
+ QVERIFY(atomic2.loadRelaxed() == two);
+ QVERIFY(atomic3.loadRelaxed() == three);
QVERIFY(atomic1.fetchAndStoreRelaxed(two) == one);
QVERIFY(atomic2.fetchAndStoreRelaxed(three) == two);
QVERIFY(atomic3.fetchAndStoreRelaxed(one) == three);
- QVERIFY(atomic1.load() == two);
- QVERIFY(atomic2.load() == three);
- QVERIFY(atomic3.load() == one);
+ QVERIFY(atomic1.loadRelaxed() == two);
+ QVERIFY(atomic2.loadRelaxed() == three);
+ QVERIFY(atomic3.loadRelaxed() == one);
}
{
QAtomicPointer<T> atomic1 = one;
QAtomicPointer<T> atomic2 = two;
QAtomicPointer<T> atomic3 = three;
- QVERIFY(atomic1.load() == one);
- QVERIFY(atomic2.load() == two);
- QVERIFY(atomic3.load() == three);
+ QVERIFY(atomic1.loadRelaxed() == one);
+ QVERIFY(atomic2.loadRelaxed() == two);
+ QVERIFY(atomic3.loadRelaxed() == three);
QVERIFY(atomic1.testAndSetRelaxed(one, two));
QVERIFY(atomic2.testAndSetRelaxed(two, three));
QVERIFY(atomic3.testAndSetRelaxed(three, one));
- QVERIFY(atomic1.load() == two);
- QVERIFY(atomic2.load() == three);
- QVERIFY(atomic3.load() == one);
+ QVERIFY(atomic1.loadRelaxed() == two);
+ QVERIFY(atomic2.loadRelaxed() == three);
+ QVERIFY(atomic3.loadRelaxed() == one);
}
}
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index b8c82c2ea0..a42454124e 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -49,6 +49,24 @@ struct ResultStoreInt : QtPrivate::ResultStoreBase
~ResultStoreInt() { clear<int>(); }
};
+class LambdaThread : public QThread
+{
+public:
+ LambdaThread(std::function<void ()> fn)
+ :m_fn(fn)
+ {
+
+ }
+
+ void run() override
+ {
+ m_fn();
+ }
+
+private:
+ std::function<void ()> m_fn;
+};
+
class tst_QFuture: public QObject
{
Q_OBJECT
@@ -67,6 +85,7 @@ private slots:
void resultsAsList();
void implicitConversions();
void iterators();
+ void iteratorsThread();
void pause();
void throttling();
void voidConversions();
@@ -1144,6 +1163,54 @@ void tst_QFuture::iterators()
}
}
}
+void tst_QFuture::iteratorsThread()
+{
+ const int expectedResultCount = 10;
+ const int delay = 10;
+ QFutureInterface<int> futureInterface;
+
+ // Create result producer thread. The results are
+ // produced with delays in order to make the consumer
+ // wait.
+ QSemaphore sem;
+ LambdaThread thread = {[=, &futureInterface, &sem](){
+ for (int i = 1; i <= expectedResultCount; i += 2) {
+ int result = i;
+ futureInterface.reportResult(&result);
+ result = i + 1;
+ futureInterface.reportResult(&result);
+ }
+
+ sem.acquire(2);
+ futureInterface.reportFinished();
+ }};
+
+ futureInterface.reportStarted();
+ QFuture<int> future = futureInterface.future();
+
+ // Iterate over results while the thread is producing them.
+ thread.start();
+ int resultCount = 0;
+ int resultSum = 0;
+ for (int result : future) {
+ sem.release();
+ ++resultCount;
+ resultSum += result;
+ }
+ thread.wait();
+
+ QCOMPARE(resultCount, expectedResultCount);
+ QCOMPARE(resultSum, expectedResultCount * (expectedResultCount + 1) / 2);
+
+ // Reverse iterate
+ resultSum = 0;
+ QFutureIterator<int> it(future);
+ it.toBack();
+ while (it.hasPrevious())
+ resultSum += it.previous();
+
+ QCOMPARE(resultSum, expectedResultCount * (expectedResultCount + 1) / 2);
+}
class SignalSlotObject : public QObject
{
diff --git a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp
index b2ef516b4e..a322a1c11d 100644
--- a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp
+++ b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include <QCoreApplication>
#include <QDebug>
+#include <QElapsedTimer>
#include <QtTest/QtTest>
#include <QtConcurrent>
@@ -878,7 +879,7 @@ void tst_QFutureWatcher::incrementalFilterResults()
void tst_QFutureWatcher::qfutureSynchronizer()
{
int taskCount = 1000;
- QTime t;
+ QElapsedTimer t;
t.start();
{
diff --git a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
index 7fb9a861d7..37c5874c02 100644
--- a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
+++ b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
@@ -1132,7 +1132,7 @@ void tst_QMutex::stressTest()
for (int i = 1; i < threadCount; ++i)
QVERIFY(threads[i].wait(10000));
QCOMPARE(StressTestThread::errorCount, 0);
- qDebug("locked %d times", int(StressTestThread::lockCount.load()));
+ qDebug("locked %d times", int(StressTestThread::lockCount.loadRelaxed()));
}
class TryLockRaceThread : public QThread
@@ -1286,28 +1286,28 @@ public:
quint64 i = 0;
while (t.elapsed() < one_minute) {
i++;
- uint nb = (i * 9 + lockCount.load() * 13) % threadCount;
+ uint nb = (i * 9 + lockCount.loadRelaxed() * 13) % threadCount;
QMutexLocker locker(&mutex[nb]);
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
if (sentinel[nb].fetchAndAddRelaxed(5)) errorCount.ref();
if (!sentinel[nb].testAndSetRelaxed(5, 0)) errorCount.ref();
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
lockCount.ref();
- nb = (nb * 17 + i * 5 + lockCount.load() * 3) % threadCount;
+ nb = (nb * 17 + i * 5 + lockCount.loadRelaxed() * 3) % threadCount;
if (mutex[nb].tryLock()) {
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
if (sentinel[nb].fetchAndAddRelaxed(16)) errorCount.ref();
if (!sentinel[nb].testAndSetRelaxed(16, 0)) errorCount.ref();
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
lockCount.ref();
mutex[nb].unlock();
}
- nb = (nb * 15 + i * 47 + lockCount.load() * 31) % threadCount;
+ nb = (nb * 15 + i * 47 + lockCount.loadRelaxed() * 31) % threadCount;
if (mutex[nb].tryLock(2)) {
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
if (sentinel[nb].fetchAndAddRelaxed(53)) errorCount.ref();
if (!sentinel[nb].testAndSetRelaxed(53, 0)) errorCount.ref();
- if (sentinel[nb].load()) errorCount.ref();
+ if (sentinel[nb].loadRelaxed()) errorCount.ref();
lockCount.ref();
mutex[nb].unlock();
}
@@ -1327,8 +1327,8 @@ void tst_QMutex::moreStress()
QVERIFY(threads[0].wait(one_minute + 10000));
for (int i = 1; i < threadCount; ++i)
QVERIFY(threads[i].wait(10000));
- qDebug("locked %d times", MoreStressTestThread::lockCount.load());
- QCOMPARE(MoreStressTestThread::errorCount.load(), 0);
+ qDebug("locked %d times", MoreStressTestThread::lockCount.loadRelaxed());
+ QCOMPARE(MoreStressTestThread::errorCount.loadRelaxed(), 0);
}
diff --git a/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp b/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
index 8e97229752..47bae585a1 100644
--- a/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
+++ b/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <qcoreapplication.h>
#include <qreadwritelock.h>
+#include <qelapsedtimer.h>
#include <qmutex.h>
#include <qthread.h>
#include <qwaitcondition.h>
@@ -237,7 +238,7 @@ void tst_QReadWriteLock::tryReadLock()
testsTurn.release();
threadsTurn.acquire();
- QTime timer;
+ QElapsedTimer timer;
timer.start();
QVERIFY(!readWriteLock.tryLockForRead(1000));
QVERIFY(timer.elapsed() >= 1000);
@@ -457,7 +458,7 @@ public:
void run()
{
testRwlock.lockForWrite();
- while(release.load()==false) {
+ while (release.loadRelaxed() == false) {
RWTESTSLEEP
}
testRwlock.unlock();
@@ -477,7 +478,7 @@ public:
void run()
{
testRwlock.lockForRead();
- while(release.load()==false) {
+ while (release.loadRelaxed() == false) {
RWTESTSLEEP
}
testRwlock.unlock();
@@ -500,7 +501,7 @@ public:
int holdTime;
int waitTime;
bool print;
- QTime t;
+ QElapsedTimer t;
inline ReadLockLoopThread(QReadWriteLock &l, int runTime, int holdTime=0, int waitTime=0, bool print=false)
:testRwlock(l)
,runTime(runTime)
@@ -536,7 +537,7 @@ public:
int holdTime;
int waitTime;
bool print;
- QTime t;
+ QElapsedTimer t;
inline WriteLockLoopThread(QReadWriteLock &l, int runTime, int holdTime=0, int waitTime=0, bool print=false)
:testRwlock(l)
,runTime(runTime)
@@ -574,7 +575,7 @@ public:
int runTime;
int waitTime;
int maxval;
- QTime t;
+ QElapsedTimer t;
inline WriteLockCountThread(QReadWriteLock &l, int runTime, int waitTime, int maxval)
:testRwlock(l)
,runTime(runTime)
@@ -615,7 +616,7 @@ public:
QReadWriteLock &testRwlock;
int runTime;
int waitTime;
- QTime t;
+ QElapsedTimer t;
inline ReadLockCountThread(QReadWriteLock &l, int runTime, int waitTime)
:testRwlock(l)
,runTime(runTime)
@@ -676,7 +677,7 @@ void tst_QReadWriteLock::multipleReadersBlockRelease()
{
QReadWriteLock testLock;
- release.store(false);
+ release.storeRelaxed(false);
threadDone=false;
ReadLockReleasableThread rlt1(testLock);
ReadLockReleasableThread rlt2(testLock);
@@ -686,7 +687,7 @@ void tst_QReadWriteLock::multipleReadersBlockRelease()
WriteLockThread wlt(testLock);
wlt.start();
sleep(1);
- release.store(true);
+ release.storeRelaxed(true);
wlt.wait();
rlt1.wait();
rlt2.wait();
@@ -873,7 +874,7 @@ void tst_QReadWriteLock::deleteOnUnlock()
DeleteOnUnlockThread thread2(&lock, &startup, &waitMutex);
- QTime t;
+ QElapsedTimer t;
t.start();
while(t.elapsed() < 4000) {
lock = new QReadWriteLock();
@@ -899,7 +900,7 @@ void tst_QReadWriteLock::uncontendedLocks()
uint count=0;
int millisecs=1000;
{
- QTime t;
+ QElapsedTimer t;
t.start();
while(t.elapsed() <millisecs)
{
@@ -908,7 +909,7 @@ void tst_QReadWriteLock::uncontendedLocks()
}
{
QReadWriteLock rwlock;
- QTime t;
+ QElapsedTimer t;
t.start();
while(t.elapsed() <millisecs)
{
@@ -919,7 +920,7 @@ void tst_QReadWriteLock::uncontendedLocks()
}
{
QReadWriteLock rwlock;
- QTime t;
+ QElapsedTimer t;
t.start();
while(t.elapsed() <millisecs)
{
diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
index d73dcc1b6d..baec4a22a5 100644
--- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp
+++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
@@ -29,7 +29,7 @@
#include <QtTest/QtTest>
#include <qcoreapplication.h>
-#include <qdatetime.h>
+#include <qelapsedtimer.h>
#include <qmutex.h>
#include <qthread.h>
#include <qtimer.h>
@@ -121,7 +121,7 @@ public:
{ }
bool wasActivated()
- { return activationCount.load() > 0; }
+ { return activationCount.loadRelaxed() > 0; }
public slots:
void slot();
@@ -244,8 +244,8 @@ public:
QMutexLocker locker(&mutex);
elapsed = 0;
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
switch (sleepType) {
case Second:
sleep(interval);
@@ -257,7 +257,7 @@ public:
usleep(interval);
break;
}
- elapsed = time.elapsed();
+ elapsed = timer.elapsed();
cond.wakeOne();
}
@@ -601,8 +601,7 @@ void tst_QThread::msleep()
thread.interval = 120;
thread.start();
QVERIFY(thread.wait(five_minutes));
-#if defined (Q_OS_WIN)
- // Since the resolution of QTime is so coarse...
+#if defined (Q_OS_WIN) // May no longer be needed
QVERIFY(thread.elapsed >= 100);
#else
QVERIFY(thread.elapsed >= 120);
@@ -616,8 +615,7 @@ void tst_QThread::usleep()
thread.interval = 120000;
thread.start();
QVERIFY(thread.wait(five_minutes));
-#if defined (Q_OS_WIN)
- // Since the resolution of QTime is so coarse...
+#if defined (Q_OS_WIN) // May no longer be needed
QVERIFY(thread.elapsed >= 100);
#else
QVERIFY(thread.elapsed >= 120);
@@ -902,7 +900,7 @@ void tst_QThread::adoptMultipleThreads()
QTestEventLoop::instance().enterLoop(5);
QVERIFY(!QTestEventLoop::instance().timeout());
- QCOMPARE(recorder.activationCount.load(), numThreads);
+ QCOMPARE(recorder.activationCount.loadRelaxed(), numThreads);
}
void tst_QThread::adoptMultipleThreadsOverlap()
@@ -939,7 +937,7 @@ void tst_QThread::adoptMultipleThreadsOverlap()
QTestEventLoop::instance().enterLoop(5);
QVERIFY(!QTestEventLoop::instance().timeout());
- QCOMPARE(recorder.activationCount.load(), numThreads);
+ QCOMPARE(recorder.activationCount.loadRelaxed(), numThreads);
}
// Disconnects on WinCE
@@ -948,9 +946,9 @@ void tst_QThread::stressTest()
if (EmulationDetector::isRunningArmOnX86())
QSKIP("Qemu uses too much memory for each thread. Test would run out of memory.");
- QTime t;
- t.start();
- while (t.elapsed() < one_minute) {
+ QElapsedTimer timer;
+ timer.start();
+ while (timer.elapsed() < one_minute) {
Current_Thread t;
t.start();
t.wait(one_minute);
@@ -1210,7 +1208,7 @@ class DummyEventDispatcher : public QAbstractEventDispatcher {
public:
DummyEventDispatcher() : QAbstractEventDispatcher() {}
bool processEvents(QEventLoop::ProcessEventsFlags) {
- visited.store(true);
+ visited.storeRelaxed(true);
emit awake();
QCoreApplication::sendPostedEvents();
return false;
@@ -1272,7 +1270,7 @@ void tst_QThread::customEventDispatcher()
QMetaObject::invokeMethod(&obj, "visit", Qt::QueuedConnection);
loop.exec();
// test that the ED has really been used
- QVERIFY(ed->visited.load());
+ QVERIFY(ed->visited.loadRelaxed());
QPointer<DummyEventDispatcher> weak_ed(ed);
QVERIFY(!weak_ed.isNull());
@@ -1330,6 +1328,8 @@ void tst_QThread::quitLock()
QCOMPARE(job->thread(), &thread);
loop.exec();
QVERIFY(exitThreadCalled);
+
+ delete job;
}
void tst_QThread::create()
diff --git a/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp b/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp
index a9af182ed8..710288af9e 100644
--- a/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp
+++ b/tests/auto/corelib/thread/qthreadonce/tst_qthreadonce.cpp
@@ -56,7 +56,7 @@ class SingletonObject: public QObject
Q_OBJECT
public:
static int runCount;
- SingletonObject() { val.store(42); ++runCount; }
+ SingletonObject() { val.storeRelaxed(42); ++runCount; }
~SingletonObject() { }
QBasicAtomicInt val;
@@ -112,7 +112,7 @@ void tst_QThreadOnce::sameThread()
QCOMPARE(controlVariable, 1);
static QSingleton<SingletonObject> s;
- QTEST((int)s->val.load(), "expectedValue");
+ QTEST((int)s->val.loadRelaxed(), "expectedValue");
s->val.ref();
QCOMPARE(SingletonObject::runCount, 1);
@@ -134,7 +134,7 @@ void tst_QThreadOnce::multipleThreads()
QCOMPARE(controlVariable, 0); // nothing must have set them yet
SingletonObject::runCount = 0;
- IncrementThread::runCount.store(0);
+ IncrementThread::runCount.storeRelaxed(0);
// wait for all of them to be ready
sem2.acquire(NumberOfThreads);
@@ -145,7 +145,7 @@ void tst_QThreadOnce::multipleThreads()
delete parent;
QCOMPARE(controlVariable, 1);
- QCOMPARE((int)IncrementThread::runCount.load(), NumberOfThreads);
+ QCOMPARE((int)IncrementThread::runCount.loadRelaxed(), NumberOfThreads);
QCOMPARE(SingletonObject::runCount, 1);
}
diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
index 838431cd5a..112c36952c 100644
--- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
+++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
@@ -27,7 +27,7 @@
**
****************************************************************************/
#include <QtTest/QtTest>
-#include <qdatetime.h>
+#include <qelapsedtimer.h>
#include <qthreadpool.h>
#include <qstring.h>
#include <qmutex.h>
@@ -220,16 +220,16 @@ class TestTask : public QRunnable
public:
void run()
{
- ran.store(true);
+ ran.storeRelaxed(true);
}
};
void tst_QThreadPool::runTask()
{
QThreadPool manager;
- ran.store(false);
+ ran.storeRelaxed(false);
manager.start(new TestTask());
- QTRY_VERIFY(ran.load());
+ QTRY_VERIFY(ran.loadRelaxed());
}
/*
@@ -237,9 +237,9 @@ void tst_QThreadPool::runTask()
*/
void tst_QThreadPool::singleton()
{
- ran.store(false);
+ ran.storeRelaxed(false);
QThreadPool::globalInstance()->start(new TestTask());
- QTRY_VERIFY(ran.load());
+ QTRY_VERIFY(ran.loadRelaxed());
}
QAtomicInt *value = 0;
@@ -344,7 +344,7 @@ void tst_QThreadPool::expiryTimeout()
// run the task
threadPool.start(&task);
QVERIFY(task.semaphore.tryAcquire(1, 10000));
- QCOMPARE(task.runCount.load(), 1);
+ QCOMPARE(task.runCount.loadRelaxed(), 1);
QVERIFY(!task.thread->wait(100));
// thread should expire
QThread *firstThread = task.thread;
@@ -353,7 +353,7 @@ void tst_QThreadPool::expiryTimeout()
// run task again, thread should be restarted
threadPool.start(&task);
QVERIFY(task.semaphore.tryAcquire(1, 10000));
- QCOMPARE(task.runCount.load(), 2);
+ QCOMPARE(task.runCount.loadRelaxed(), 2);
QVERIFY(!task.thread->wait(100));
// thread should expire again
QVERIFY(task.thread->wait(10000));
@@ -382,7 +382,7 @@ void tst_QThreadPool::expiryTimeoutRace() // QTBUG-3786
QThread::msleep(50); // exactly the same as the expiry timeout
}
QVERIFY(task.semaphore.tryAcquire(numTasks, 10000));
- QCOMPARE(task.runCount.load(), numTasks);
+ QCOMPARE(task.runCount.loadRelaxed(), numTasks);
QVERIFY(threadPool.waitForDone(2000));
}
@@ -685,7 +685,7 @@ void tst_QThreadPool::reserveAndStart() // QTBUG-21051
QCOMPARE(threadpool->activeThreadCount(), 2);
task->waitForStarted.acquire();
task->waitBeforeDone.release();
- QTRY_COMPARE(task->count.load(), 1);
+ QTRY_COMPARE(task->count.loadRelaxed(), 1);
QTRY_COMPARE(threadpool->activeThreadCount(), 1);
// now the thread is waiting, but tryStart() will fail since activeThreadCount() >= maxThreadCount()
@@ -698,7 +698,7 @@ void tst_QThreadPool::reserveAndStart() // QTBUG-21051
QTRY_COMPARE(threadpool->activeThreadCount(), 2);
task->waitForStarted.acquire();
task->waitBeforeDone.release();
- QTRY_COMPARE(task->count.load(), 2);
+ QTRY_COMPARE(task->count.loadRelaxed(), 2);
QTRY_COMPARE(threadpool->activeThreadCount(), 1);
threadpool->releaseThread();
@@ -721,14 +721,14 @@ class CountingRunnable : public QRunnable
void tst_QThreadPool::start()
{
const int runs = 1000;
- count.store(0);
+ count.storeRelaxed(0);
{
QThreadPool threadPool;
for (int i = 0; i< runs; ++i) {
threadPool.start(new CountingRunnable());
}
}
- QCOMPARE(count.load(), runs);
+ QCOMPARE(count.loadRelaxed(), runs);
}
void tst_QThreadPool::tryStart()
@@ -747,7 +747,7 @@ void tst_QThreadPool::tryStart()
}
};
- count.store(0);
+ count.storeRelaxed(0);
WaitingTask task;
QThreadPool threadPool;
@@ -757,7 +757,7 @@ void tst_QThreadPool::tryStart()
QVERIFY(!threadPool.tryStart(&task));
task.semaphore.release(threadPool.maxThreadCount());
threadPool.waitForDone();
- QCOMPARE(count.load(), threadPool.maxThreadCount());
+ QCOMPARE(count.loadRelaxed(), threadPool.maxThreadCount());
}
QMutex mutex;
@@ -775,7 +775,7 @@ void tst_QThreadPool::tryStartPeakThreadCount()
{
QMutexLocker lock(&mutex);
activeThreads.ref();
- peakActiveThreads.store(qMax(peakActiveThreads.load(), activeThreads.load()));
+ peakActiveThreads.storeRelaxed(qMax(peakActiveThreads.loadRelaxed(), activeThreads.loadRelaxed()));
}
QTest::qWait(100);
@@ -793,13 +793,13 @@ void tst_QThreadPool::tryStartPeakThreadCount()
if (threadPool.tryStart(&task) == false)
QTest::qWait(10);
}
- QCOMPARE(peakActiveThreads.load(), QThread::idealThreadCount());
+ QCOMPARE(peakActiveThreads.loadRelaxed(), QThread::idealThreadCount());
for (int i = 0; i < 20; ++i) {
if (threadPool.tryStart(&task) == false)
QTest::qWait(10);
}
- QCOMPARE(peakActiveThreads.load(), QThread::idealThreadCount());
+ QCOMPARE(peakActiveThreads.loadRelaxed(), QThread::idealThreadCount());
}
void tst_QThreadPool::tryStartCount()
@@ -877,27 +877,27 @@ void tst_QThreadPool::priorityStart()
sem.release();
QVERIFY(threadPool.waitForDone());
- QCOMPARE(firstStarted.load(), expected);
+ QCOMPARE(firstStarted.loadRelaxed(), expected);
}
void tst_QThreadPool::waitForDone()
{
- QTime total, pass;
+ QElapsedTimer total, pass;
total.start();
QThreadPool threadPool;
while (total.elapsed() < 10000) {
int runs;
- count.store(runs = 0);
+ count.storeRelaxed(runs = 0);
pass.restart();
while (pass.elapsed() < 100) {
threadPool.start(new CountingRunnable());
++runs;
}
threadPool.waitForDone();
- QCOMPARE(count.load(), runs);
+ QCOMPARE(count.loadRelaxed(), runs);
- count.store(runs = 0);
+ count.storeRelaxed(runs = 0);
pass.restart();
while (pass.elapsed() < 100) {
threadPool.start(new CountingRunnable());
@@ -905,7 +905,7 @@ void tst_QThreadPool::waitForDone()
runs += 2;
}
threadPool.waitForDone();
- QCOMPARE(count.load(), runs);
+ QCOMPARE(count.loadRelaxed(), runs);
}
}
@@ -953,14 +953,14 @@ void tst_QThreadPool::clear()
QThreadPool threadPool;
threadPool.setMaxThreadCount(10);
int runs = 2 * threadPool.maxThreadCount();
- count.store(0);
+ count.storeRelaxed(0);
for (int i = 0; i <= runs; i++) {
threadPool.start(new BlockingRunnable(sem));
}
threadPool.clear();
sem.release(threadPool.maxThreadCount());
threadPool.waitForDone();
- QCOMPARE(count.load(), threadPool.maxThreadCount());
+ QCOMPARE(count.loadRelaxed(), threadPool.maxThreadCount());
}
void tst_QThreadPool::cancel()
@@ -1008,7 +1008,7 @@ void tst_QThreadPool::cancel()
// and cause an early return:
const QSemaphoreReleaser semReleaser(sem, runs);
- count.store(0);
+ count.storeRelaxed(0);
QAtomicInt dtorCounter = 0;
QAtomicInt runCounter = 0;
for (int i = 0; i < runs; i++) {
@@ -1025,12 +1025,12 @@ void tst_QThreadPool::cancel()
}
runnables[0]->dummy = 0; //valgrind will catch this if cancel() is crazy enough to delete currently running jobs
runnables[runs-1]->dummy = 0;
- QCOMPARE(dtorCounter.load(), runs - threadPool.maxThreadCount() - 1);
+ QCOMPARE(dtorCounter.loadRelaxed(), runs - threadPool.maxThreadCount() - 1);
sem.release(threadPool.maxThreadCount());
threadPool.waitForDone();
- QCOMPARE(runCounter.load(), threadPool.maxThreadCount());
- QCOMPARE(count.load(), threadPool.maxThreadCount());
- QCOMPARE(dtorCounter.load(), runs - 2);
+ QCOMPARE(runCounter.loadRelaxed(), threadPool.maxThreadCount());
+ QCOMPARE(count.loadRelaxed(), threadPool.maxThreadCount());
+ QCOMPARE(dtorCounter.loadRelaxed(), runs - 2);
delete runnables[0]; //if the pool deletes them then we'll get double-free crash
delete runnables[runs-1];
}
@@ -1080,7 +1080,7 @@ void tst_QThreadPool::tryTake()
// and cause an early return:
const QSemaphoreReleaser semReleaser(sem, Runs);
- count.store(0);
+ count.storeRelaxed(0);
QAtomicInt dtorCounter = 0;
QAtomicInt runCounter = 0;
for (int i = 0; i < Runs; i++) {
@@ -1102,23 +1102,23 @@ void tst_QThreadPool::tryTake()
}
runnables[0]->dummy = 0; // valgrind will catch this if tryTake() is crazy enough to delete currently running jobs
- QCOMPARE(dtorCounter.load(), int(Runs - MaxThreadCount));
+ QCOMPARE(dtorCounter.loadRelaxed(), int(Runs - MaxThreadCount));
sem.release(MaxThreadCount);
threadPool.waitForDone();
- QCOMPARE(runCounter.load(), int(MaxThreadCount));
- QCOMPARE(count.load(), int(MaxThreadCount));
- QCOMPARE(dtorCounter.load(), int(Runs - 1));
+ QCOMPARE(runCounter.loadRelaxed(), int(MaxThreadCount));
+ QCOMPARE(count.loadRelaxed(), int(MaxThreadCount));
+ QCOMPARE(dtorCounter.loadRelaxed(), int(Runs - 1));
delete runnables[0]; // if the pool deletes them then we'll get double-free crash
}
void tst_QThreadPool::destroyingWaitsForTasksToFinish()
{
- QTime total, pass;
+ QElapsedTimer total, pass;
total.start();
while (total.elapsed() < 10000) {
int runs;
- count.store(runs = 0);
+ count.storeRelaxed(runs = 0);
{
QThreadPool threadPool;
pass.restart();
@@ -1127,9 +1127,9 @@ void tst_QThreadPool::destroyingWaitsForTasksToFinish()
++runs;
}
}
- QCOMPARE(count.load(), runs);
+ QCOMPARE(count.loadRelaxed(), runs);
- count.store(runs = 0);
+ count.storeRelaxed(runs = 0);
{
QThreadPool threadPool;
pass.restart();
@@ -1139,7 +1139,7 @@ void tst_QThreadPool::destroyingWaitsForTasksToFinish()
runs += 2;
}
}
- QCOMPARE(count.load(), runs);
+ QCOMPARE(count.loadRelaxed(), runs);
}
}
@@ -1204,7 +1204,7 @@ void tst_QThreadPool::stressTest()
}
};
- QTime total;
+ QElapsedTimer total;
total.start();
while (total.elapsed() < 30000) {
Task t;
@@ -1322,6 +1322,7 @@ void tst_QThreadPool::waitForDoneAfterTake()
QRunnable *runnable = createTask(emptyFunct);
manager.start(runnable);
QVERIFY(manager.tryTake(runnable));
+ delete runnable;
}
// Add another runnable that will not be removed
diff --git a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
index ef5d3452d5..3538d90803 100644
--- a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
+++ b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
@@ -359,7 +359,7 @@ void tst_QThreadStorage::leakInDestructor()
QVERIFY(tls.hasLocalData());
}
};
- int c = SPointer::count.load();
+ int c = SPointer::count.loadRelaxed();
QThreadStorage<ThreadStorageLocalDataTester *> tls;
@@ -383,7 +383,7 @@ void tst_QThreadStorage::leakInDestructor()
QVERIFY(t3.wait());
//check all the constructed things have been destructed
- QCOMPARE(int(SPointer::count.load()), c);
+ QCOMPARE(int(SPointer::count.loadRelaxed()), c);
}
class ThreadStorageResetLocalDataTester {
@@ -411,7 +411,7 @@ void tst_QThreadStorage::resetInDestructor()
QVERIFY(ThreadStorageResetLocalDataTesterTls()->hasLocalData());
}
};
- int c = SPointer::count.load();
+ int c = SPointer::count.loadRelaxed();
Thread t1;
Thread t2;
@@ -424,7 +424,7 @@ void tst_QThreadStorage::resetInDestructor()
QVERIFY(t3.wait());
//check all the constructed things have been destructed
- QCOMPARE(int(SPointer::count.load()), c);
+ QCOMPARE(int(SPointer::count.loadRelaxed()), c);
}
@@ -475,7 +475,7 @@ void tst_QThreadStorage::valueBased()
QThreadStorage<QString> tlsString;
QThreadStorage<int> tlsInt;
- int c = SPointer::count.load();
+ int c = SPointer::count.loadRelaxed();
Thread t1(tlsSPointer, tlsString, tlsInt);
Thread t2(tlsSPointer, tlsString, tlsInt);
@@ -495,7 +495,7 @@ void tst_QThreadStorage::valueBased()
QVERIFY(t2.wait());
QVERIFY(t3.wait());
- QCOMPARE(c, int(SPointer::count.load()));
+ QCOMPARE(c, int(SPointer::count.loadRelaxed()));
}
diff --git a/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp b/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp
index 126cb6b180..5363231895 100644
--- a/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp
+++ b/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp
@@ -481,7 +481,7 @@ void tst_QWaitCondition::wakeOne()
}
mutex.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; ++x) {
@@ -502,10 +502,10 @@ void tst_QWaitCondition::wakeOne()
}
QCOMPARE(exited, 1);
- QCOMPARE(count.load(), ThreadCount - (x + 1));
+ QCOMPARE(count.loadRelaxed(), ThreadCount - (x + 1));
}
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
// QReadWriteLock
QReadWriteLock readWriteLock;
@@ -530,7 +530,7 @@ void tst_QWaitCondition::wakeOne()
}
readWriteLock.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; ++x) {
@@ -551,10 +551,10 @@ void tst_QWaitCondition::wakeOne()
}
QCOMPARE(exited, 1);
- QCOMPARE(count.load(), ThreadCount - (x + 1));
+ QCOMPARE(count.loadRelaxed(), ThreadCount - (x + 1));
}
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
}
// wake up threads, two at a time
@@ -585,7 +585,7 @@ void tst_QWaitCondition::wakeOne()
}
mutex.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; x += 2) {
@@ -608,10 +608,10 @@ void tst_QWaitCondition::wakeOne()
}
QCOMPARE(exited, 2);
- QCOMPARE(count.load(), ThreadCount - (x + 2));
+ QCOMPARE(count.loadRelaxed(), ThreadCount - (x + 2));
}
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
// QReadWriteLock
QReadWriteLock readWriteLock;
@@ -636,7 +636,7 @@ void tst_QWaitCondition::wakeOne()
}
readWriteLock.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up threads one at a time
for (x = 0; x < ThreadCount; x += 2) {
@@ -659,10 +659,10 @@ void tst_QWaitCondition::wakeOne()
}
QCOMPARE(exited, 2);
- QCOMPARE(count.load(), ThreadCount - (x + 2));
+ QCOMPARE(count.loadRelaxed(), ThreadCount - (x + 2));
}
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
}
}
@@ -692,7 +692,7 @@ void tst_QWaitCondition::wakeAll()
}
mutex.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up all threads at once
mutex.lock();
@@ -707,7 +707,7 @@ void tst_QWaitCondition::wakeAll()
}
QCOMPARE(exited, ThreadCount);
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
// QReadWriteLock
QReadWriteLock readWriteLock;
@@ -728,7 +728,7 @@ void tst_QWaitCondition::wakeAll()
}
readWriteLock.unlock();
- QCOMPARE(count.load(), ThreadCount);
+ QCOMPARE(count.loadRelaxed(), ThreadCount);
// wake up all threads at once
readWriteLock.lockForWrite();
@@ -743,7 +743,7 @@ void tst_QWaitCondition::wakeAll()
}
QCOMPARE(exited, ThreadCount);
- QCOMPARE(count.load(), 0);
+ QCOMPARE(count.loadRelaxed(), 0);
}
}
diff --git a/tests/auto/corelib/tools/qdate/.gitignore b/tests/auto/corelib/time/qdate/.gitignore
index 70945d4a86..70945d4a86 100644
--- a/tests/auto/corelib/tools/qdate/.gitignore
+++ b/tests/auto/corelib/time/qdate/.gitignore
diff --git a/tests/auto/corelib/tools/qdate/qdate.pro b/tests/auto/corelib/time/qdate/qdate.pro
index dd7c6cb888..925c3b4c78 100644
--- a/tests/auto/corelib/tools/qdate/qdate.pro
+++ b/tests/auto/corelib/time/qdate/qdate.pro
@@ -1,4 +1,4 @@
CONFIG += testcase
TARGET = tst_qdate
-QT = core testlib
+QT = core-private testlib
SOURCES = tst_qdate.cpp
diff --git a/tests/auto/corelib/tools/qdate/tst_qdate.cpp b/tests/auto/corelib/time/qdate/tst_qdate.cpp
index ce1e5730dd..0ef494b229 100644
--- a/tests/auto/corelib/tools/qdate/tst_qdate.cpp
+++ b/tests/auto/corelib/time/qdate/tst_qdate.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -27,6 +27,7 @@
**
****************************************************************************/
+#include <private/qglobal_p.h> // for the icu feature test
#include <QtTest/QtTest>
#include <qdatetime.h>
#include <qlocale.h>
@@ -54,6 +55,13 @@ private slots:
void weekNumber_invalid();
void weekNumber_data();
void weekNumber();
+#if QT_CONFIG(timezone)
+ void startOfDay_endOfDay_data();
+ void startOfDay_endOfDay();
+#endif
+ void startOfDay_endOfDay_fixed_data();
+ void startOfDay_endOfDay_fixed();
+ void startOfDay_endOfDay_bounds();
void julianDaysLimits();
void addDays_data();
void addDays();
@@ -83,6 +91,7 @@ private slots:
void negativeYear() const;
void printNegativeYear() const;
void roundtripGermanLocale() const;
+#if QT_CONFIG(textdate)
void shortDayName() const;
void standaloneShortDayName() const;
void longDayName() const;
@@ -91,6 +100,7 @@ private slots:
void standaloneShortMonthName() const;
void longMonthName() const;
void standaloneLongMonthName() const;
+#endif // textdate
void roundtrip() const;
void qdebug() const;
private:
@@ -456,6 +466,164 @@ void tst_QDate::weekNumber_invalid()
QCOMPARE( dt.weekNumber( &yearNumber ), 0 );
}
+#if QT_CONFIG(timezone)
+void tst_QDate::startOfDay_endOfDay_data()
+{
+ QTest::addColumn<QDate>("date"); // Typically a spring-forward.
+ // A zone in which that date's start and end are worth checking:
+ QTest::addColumn<QByteArray>("zoneName");
+ // The start and end times in that zone:
+ QTest::addColumn<QTime>("start");
+ QTest::addColumn<QTime>("end");
+
+ const QTime initial(0, 0), final(23, 59, 59, 999), invalid(QDateTime().time());
+
+ QTest::newRow("epoch")
+ << QDate(1970, 1, 1) << QByteArray("UTC")
+ << initial << final;
+ QTest::newRow("Brazil")
+ << QDate(2008, 10, 19) << QByteArray("America/Sao_Paulo")
+ << QTime(1, 0) << final;
+#if QT_CONFIG(icu) || !defined(Q_OS_WIN) // MS's TZ APIs lack data
+ QTest::newRow("Sofia")
+ << QDate(1994, 3, 27) << QByteArray("Europe/Sofia")
+ << QTime(1, 0) << final;
+#endif
+ QTest::newRow("Kiritimati")
+ << QDate(1994, 12, 31) << QByteArray("Pacific/Kiritimati")
+ << invalid << invalid;
+ QTest::newRow("Samoa")
+ << QDate(2011, 12, 30) << QByteArray("Pacific/Apia")
+ << invalid << invalid;
+ // TODO: find other zones with transitions at/crossing midnight.
+}
+
+void tst_QDate::startOfDay_endOfDay()
+{
+ QFETCH(QDate, date);
+ QFETCH(QByteArray, zoneName);
+ QFETCH(QTime, start);
+ QFETCH(QTime, end);
+ const QTimeZone zone(zoneName);
+ const bool isSystem = QTimeZone::systemTimeZone() == zone;
+ QDateTime front(date.startOfDay(zone)), back(date.endOfDay(zone));
+ if (end.isValid())
+ QCOMPARE(date.addDays(1).startOfDay(zone).addMSecs(-1), back);
+ if (start.isValid())
+ QCOMPARE(date.addDays(-1).endOfDay(zone).addMSecs(1), front);
+ do { // Avoids duplicating these tests for local-time when it *is* zone:
+ if (start.isValid()) {
+ QCOMPARE(front.date(), date);
+ QCOMPARE(front.time(), start);
+ }
+ if (end.isValid()) {
+ QCOMPARE(back.date(), date);
+ QCOMPARE(back.time(), end);
+ }
+ if (front.timeSpec() == Qt::LocalTime)
+ break;
+ front = date.startOfDay(Qt::LocalTime);
+ back = date.endOfDay(Qt::LocalTime);
+ } while (isSystem);
+ if (end.isValid())
+ QCOMPARE(date.addDays(1).startOfDay(Qt::LocalTime).addMSecs(-1), back);
+ if (start.isValid())
+ QCOMPARE(date.addDays(-1).endOfDay(Qt::LocalTime).addMSecs(1), front);
+ if (!isSystem) {
+ // These might fail if system zone coincides with zone; but only if it
+ // did something similarly unusual on the date picked for this test.
+ if (start.isValid()) {
+ QCOMPARE(front.date(), date);
+ QCOMPARE(front.time(), QTime(0, 0));
+ }
+ if (end.isValid()) {
+ QCOMPARE(back.date(), date);
+ QCOMPARE(back.time(), QTime(23, 59, 59, 999));
+ }
+ }
+}
+#endif // timezone
+
+void tst_QDate::startOfDay_endOfDay_fixed_data()
+{
+ const qint64 kilo(1000);
+ using Bounds = std::numeric_limits<qint64>;
+ const QDateTime
+ first(QDateTime::fromMSecsSinceEpoch(Bounds::min() + 1, Qt::UTC)),
+ start32sign(QDateTime::fromMSecsSinceEpoch(-0x80000000L * kilo, Qt::UTC)),
+ end32sign(QDateTime::fromMSecsSinceEpoch(0x80000000L * kilo, Qt::UTC)),
+ end32unsign(QDateTime::fromMSecsSinceEpoch(0x100000000L * kilo, Qt::UTC)),
+ last(QDateTime::fromMSecsSinceEpoch(Bounds::max(), Qt::UTC));
+
+ const struct {
+ const char *name;
+ QDate date;
+ } data[] = {
+ { "epoch", QDate(1970, 1, 1) },
+ { "y2k-leap-day", QDate(2000, 2, 29) },
+ // Just outside the start and end of 32-bit time_t:
+ { "pre-sign32", QDate(start32sign.date().year(), 1, 1) },
+ { "post-sign32", QDate(end32sign.date().year(), 12, 31) },
+ { "post-uint32", QDate(end32unsign.date().year(), 12, 31) },
+ // Just inside the start and end of QDateTime's range:
+ { "first-full", first.date().addDays(1) },
+ { "last-full", last.date().addDays(-1) }
+ };
+
+ QTest::addColumn<QDate>("date");
+ for (const auto &r : data)
+ QTest::newRow(r.name) << r.date;
+}
+
+void tst_QDate::startOfDay_endOfDay_fixed()
+{
+ const QTime early(0, 0), late(23, 59, 59, 999);
+ QFETCH(QDate, date);
+
+ QDateTime start(date.startOfDay(Qt::UTC));
+ QDateTime end(date.endOfDay(Qt::UTC));
+ QCOMPARE(start.date(), date);
+ QCOMPARE(end.date(), date);
+ QCOMPARE(start.time(), early);
+ QCOMPARE(end.time(), late);
+ QCOMPARE(date.addDays(1).startOfDay(Qt::UTC).addMSecs(-1), end);
+ QCOMPARE(date.addDays(-1).endOfDay(Qt::UTC).addMSecs(1), start);
+ for (int offset = -60 * 16; offset <= 60 * 16; offset += 65) {
+ start = date.startOfDay(Qt::OffsetFromUTC, offset);
+ end = date.endOfDay(Qt::OffsetFromUTC, offset);
+ QCOMPARE(start.date(), date);
+ QCOMPARE(end.date(), date);
+ QCOMPARE(start.time(), early);
+ QCOMPARE(end.time(), late);
+ QCOMPARE(date.addDays(1).startOfDay(Qt::OffsetFromUTC, offset).addMSecs(-1), end);
+ QCOMPARE(date.addDays(-1).endOfDay(Qt::OffsetFromUTC, offset).addMSecs(1), start);
+ }
+}
+
+void tst_QDate::startOfDay_endOfDay_bounds()
+{
+ // Check the days in which QDateTime's range starts and ends:
+ using Bounds = std::numeric_limits<qint64>;
+ const QDateTime
+ first(QDateTime::fromMSecsSinceEpoch(Bounds::min(), Qt::UTC)),
+ last(QDateTime::fromMSecsSinceEpoch(Bounds::max(), Qt::UTC)),
+ epoch(QDateTime::fromMSecsSinceEpoch(0, Qt::UTC));
+ // First, check these *are* the start and end of QDateTime's range:
+ QVERIFY(first.isValid());
+ QVERIFY(last.isValid());
+ QVERIFY(first < epoch);
+ QVERIFY(last > epoch);
+ // QDateTime's addMSecs doesn't check against {und,ov}erflow ...
+ QVERIFY(!first.addMSecs(-1).isValid() || first.addMSecs(-1) > first);
+ QVERIFY(!last.addMSecs(1).isValid() || last.addMSecs(1) < last);
+
+ // Now test start/end methods with them:
+ QCOMPARE(first.date().endOfDay(Qt::UTC).time(), QTime(23, 59, 59, 999));
+ QCOMPARE(last.date().startOfDay(Qt::UTC).time(), QTime(0, 0));
+ QVERIFY(!first.date().startOfDay(Qt::UTC).isValid());
+ QVERIFY(!last.date().endOfDay(Qt::UTC).isValid());
+}
+
void tst_QDate::julianDaysLimits()
{
qint64 min = std::numeric_limits<qint64>::min();
@@ -1038,18 +1206,18 @@ void tst_QDate::fromStringFormat_data()
// Undo this (inline the C-locale versions) for ### Qt 6
// Get localized names:
- QString january = QDate::longMonthName(1);
- QString february = QDate::longMonthName(2);
- QString march = QDate::longMonthName(3);
- QString august = QDate::longMonthName(8);
- QString mon = QDate::shortDayName(1);
- QString monday = QDate::longDayName(1);
- QString tuesday = QDate::longDayName(2);
- QString wednesday = QDate::longDayName(3);
- QString thursday = QDate::longDayName(4);
- QString friday = QDate::longDayName(5);
- QString saturday = QDate::longDayName(6);
- QString sunday = QDate::longDayName(7);
+ QString january = QLocale::system().monthName(1, QLocale::LongFormat);
+ QString february = QLocale::system().monthName(2, QLocale::LongFormat);
+ QString march = QLocale::system().monthName(3, QLocale::LongFormat);
+ QString august = QLocale::system().monthName(8, QLocale::LongFormat);
+ QString mon = QLocale::system().dayName(1, QLocale::ShortFormat);
+ QString monday = QLocale::system().dayName(1, QLocale::LongFormat);
+ QString tuesday = QLocale::system().dayName(2, QLocale::LongFormat);
+ QString wednesday = QLocale::system().dayName(3, QLocale::LongFormat);
+ QString thursday = QLocale::system().dayName(4, QLocale::LongFormat);
+ QString friday = QLocale::system().dayName(5, QLocale::LongFormat);
+ QString saturday = QLocale::system().dayName(6, QLocale::LongFormat);
+ QString sunday = QLocale::system().dayName(7, QLocale::LongFormat);
QTest::newRow("data0") << QString("") << QString("") << defDate();
QTest::newRow("data1") << QString(" ") << QString("") << invalidDate();
@@ -1305,6 +1473,10 @@ void tst_QDate::roundtripGermanLocale() const
theDateTime.fromString(theDateTime.toString(Qt::TextDate), Qt::TextDate);
}
+#if QT_CONFIG(textdate)
+QT_WARNING_PUSH // the methods tested here are all deprecated
+QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
+
void tst_QDate::shortDayName() const
{
QCOMPARE(QDate::shortDayName(0), QString());
@@ -1432,6 +1604,8 @@ void tst_QDate::standaloneLongMonthName() const
QCOMPARE(QDate::longMonthName(i, QDate::StandaloneFormat), locale.standaloneMonthName(i, QLocale::LongFormat));
}
}
+QT_WARNING_POP
+#endif // textdate
void tst_QDate::roundtrip() const
{
diff --git a/tests/auto/corelib/tools/qdatetime/.gitignore b/tests/auto/corelib/time/qdatetime/.gitignore
index 7784f3a3eb..7784f3a3eb 100644
--- a/tests/auto/corelib/tools/qdatetime/.gitignore
+++ b/tests/auto/corelib/time/qdatetime/.gitignore
diff --git a/tests/auto/corelib/tools/qdatetime/BLACKLIST b/tests/auto/corelib/time/qdatetime/BLACKLIST
index 3a42ee066b..3a42ee066b 100644
--- a/tests/auto/corelib/tools/qdatetime/BLACKLIST
+++ b/tests/auto/corelib/time/qdatetime/BLACKLIST
diff --git a/tests/auto/corelib/tools/qdatetime/qdatetime.pro b/tests/auto/corelib/time/qdatetime/qdatetime.pro
index 742eb47075..742eb47075 100644
--- a/tests/auto/corelib/tools/qdatetime/qdatetime.pro
+++ b/tests/auto/corelib/time/qdatetime/qdatetime.pro
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
index b128ccebc5..6f0aebb071 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -37,9 +37,6 @@
#ifdef Q_OS_WIN
# include <qt_windows.h>
-# if defined(Q_OS_WINRT)
-# define tzset()
-# endif
#endif
class tst_QDateTime : public QObject
@@ -81,9 +78,11 @@ private slots:
void toString_isoDate_data();
void toString_isoDate();
void toString_isoDate_extra();
+#if QT_CONFIG(datestring)
void toString_textDate_data();
void toString_textDate();
void toString_textDate_extra();
+#endif
void toString_rfcDate_data();
void toString_rfcDate();
void toString_enumformat();
@@ -145,9 +144,7 @@ private slots:
void isDaylightTime() const;
void daylightTransitions() const;
void timeZones() const;
-#if defined(Q_OS_UNIX)
void systemTimeZoneChange() const;
-#endif
void invalid() const;
@@ -174,7 +171,7 @@ private:
void reset(const QByteArray &zone)
{
qputenv("TZ", zone.constData());
- tzset();
+ qTzSet();
}
~TimeZoneRollback()
{
@@ -182,7 +179,7 @@ private:
qunsetenv("TZ");
else
qputenv("TZ", prior.constData());
- tzset();
+ qTzSet();
}
};
};
@@ -805,11 +802,11 @@ void tst_QDateTime::toString_isoDate_data()
QTest::newRow("positive OffsetFromUTC")
<< dt << Qt::ISODate
<< QString("1978-11-09T13:28:34+05:30");
- dt.setUtcOffset(-7200);
+ dt.setOffsetFromUtc(-7200);
QTest::newRow("negative OffsetFromUTC")
<< dt << Qt::ISODate
<< QString("1978-11-09T13:28:34-02:00");
- dt.setUtcOffset(-900);
+ dt.setOffsetFromUtc(-900);
QTest::newRow("negative non-integral OffsetFromUTC")
<< dt << Qt::ISODate
<< QString("1978-11-09T13:28:34-00:15");
@@ -845,7 +842,7 @@ void tst_QDateTime::toString_isoDate()
QCOMPARE(resultDatetime.date(), datetime.date());
QCOMPARE(resultDatetime.time(), datetime.time());
QCOMPARE(resultDatetime.timeSpec(), datetime.timeSpec());
- QCOMPARE(resultDatetime.utcOffset(), datetime.utcOffset());
+ QCOMPARE(resultDatetime.offsetFromUtc(), datetime.offsetFromUtc());
} else {
QCOMPARE(resultDatetime, QDateTime());
}
@@ -875,12 +872,14 @@ void tst_QDateTime::toString_isoDate_extra()
#endif // timezone
}
+#if QT_CONFIG(datestring)
void tst_QDateTime::toString_textDate_data()
{
QTest::addColumn<QDateTime>("datetime");
QTest::addColumn<QString>("expected");
- QString wednesdayJanuary = QDate::shortDayName(3) + ' ' + QDate::shortMonthName(1);
+ QString wednesdayJanuary = QLocale::system().dayName(3, QLocale::ShortFormat)
+ + ' ' + QLocale::system().monthName(1, QLocale::ShortFormat);
QTest::newRow("localtime") << QDateTime(QDate(2013, 1, 2), QTime(1, 2, 3), Qt::LocalTime)
<< wednesdayJanuary + QString(" 2 01:02:03 2013");
@@ -909,7 +908,7 @@ void tst_QDateTime::toString_textDate()
QCOMPARE(resultDatetime.date(), datetime.date());
QCOMPARE(resultDatetime.time(), datetime.time());
QCOMPARE(resultDatetime.timeSpec(), datetime.timeSpec());
- QCOMPARE(resultDatetime.utcOffset(), datetime.utcOffset());
+ QCOMPARE(resultDatetime.offsetFromUtc(), datetime.offsetFromUtc());
}
void tst_QDateTime::toString_textDate_extra()
@@ -958,6 +957,7 @@ void tst_QDateTime::toString_textDate_extra()
dt = QDateTime::fromMSecsSinceEpoch(0, Qt::UTC);
QVERIFY(dt.toString().endsWith(GMT));
}
+#endif // datestring
void tst_QDateTime::toString_rfcDate_data()
{
@@ -973,11 +973,11 @@ void tst_QDateTime::toString_rfcDate_data()
<< QDateTime(QDate(1978, 11, 9), QTime(13, 28, 34), Qt::UTC)
<< QString("09 Nov 1978 13:28:34 +0000");
QDateTime dt(QDate(1978, 11, 9), QTime(13, 28, 34));
- dt.setUtcOffset(19800);
+ dt.setOffsetFromUtc(19800);
QTest::newRow("positive OffsetFromUTC")
<< dt
<< QString("09 Nov 1978 13:28:34 +0530");
- dt.setUtcOffset(-7200);
+ dt.setOffsetFromUtc(-7200);
QTest::newRow("negative OffsetFromUTC")
<< dt
<< QString("09 Nov 1978 13:28:34 -0200");
@@ -1005,7 +1005,6 @@ void tst_QDateTime::toString_enumformat()
{
QDateTime dt1(QDate(1995, 5, 20), QTime(12, 34, 56));
-
QString str1 = dt1.toString(Qt::TextDate);
QVERIFY(!str1.isEmpty()); // It's locale dependent everywhere
@@ -2776,9 +2775,9 @@ void tst_QDateTime::getDate()
int y = -33, m = -44, d = -55;
QDate date;
date.getDate(&y, &m, &d);
- QVERIFY(date.year() == y);
- QVERIFY(date.month() == m);
- QVERIFY(date.day() == d);
+ QCOMPARE(date.year(), y);
+ QCOMPARE(date.month(), m);
+ QCOMPARE(date.day(), d);
date.getDate(0, 0, 0);
}
@@ -2790,9 +2789,9 @@ void tst_QDateTime::getDate()
date.getDate(&y, 0, 0);
date.getDate(0, 0, &d);
- QVERIFY(date.year() == y);
- QVERIFY(date.month() == m);
- QVERIFY(date.day() == d);
+ QCOMPARE(date.year(), y);
+ QCOMPARE(date.month(), m);
+ QCOMPARE(date.day(), d);
}
}
@@ -3425,33 +3424,10 @@ void tst_QDateTime::timeZones() const
QCOMPARE(future.offsetFromUtc(), 28800);
}
-#if defined(Q_OS_UNIX)
-// Currently disabled on Windows as adjusting the timezone
-// requires additional privileges that aren't normally
-// enabled for a process. This can be achieved by calling
-// AdjustTokenPrivileges() and then SetTimeZoneInformation(),
-// which will require linking to a different library to access that API.
-static void setTimeZone(const QByteArray &tz)
-{
- qputenv("TZ", tz);
- ::tzset();
-
-// following left for future reference, see comment above
-// #if defined(Q_OS_WIN32)
-// ::_tzset();
-// #endif
-}
-
void tst_QDateTime::systemTimeZoneChange() const
{
- struct ResetTZ {
- QByteArray original;
- ResetTZ() : original(qgetenv("TZ")) {}
- ~ResetTZ() { setTimeZone(original); }
- } scopedReset;
-
// Set the timezone to Brisbane time
- setTimeZone(QByteArray("AEST-10:00"));
+ TimeZoneRollback useZone(QByteArray("AEST-10:00"));
QDateTime localDate = QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::LocalTime);
QDateTime utcDate = QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::UTC);
@@ -3464,16 +3440,18 @@ void tst_QDateTime::systemTimeZoneChange() const
QVERIFY(tzDate.timeZone().isValid());
// Change to Indian time
- setTimeZone(QByteArray("IST-05:30"));
+ useZone.reset(QByteArray("IST-05:30"));
QCOMPARE(localDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::LocalTime));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "WinRT gets this wrong, QTBUG-71185", Continue);
+#endif
QVERIFY(localMsecs != localDate.toMSecsSinceEpoch());
QCOMPARE(utcDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::UTC));
QCOMPARE(utcDate.toMSecsSinceEpoch(), utcMsecs);
QCOMPARE(tzDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), QTimeZone("Australia/Brisbane")));
QCOMPARE(tzDate.toMSecsSinceEpoch(), tzMsecs);
}
-#endif
void tst_QDateTime::invalid() const
{
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm b/tests/auto/corelib/time/qdatetime/tst_qdatetime_mac.mm
index f73c7b9d5d..f73c7b9d5d 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm
+++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime_mac.mm
diff --git a/tests/auto/corelib/tools/qtime/.gitignore b/tests/auto/corelib/time/qtime/.gitignore
index 26a4c65cc2..26a4c65cc2 100644
--- a/tests/auto/corelib/tools/qtime/.gitignore
+++ b/tests/auto/corelib/time/qtime/.gitignore
diff --git a/tests/auto/corelib/tools/qtime/qtime.pro b/tests/auto/corelib/time/qtime/qtime.pro
index 0973b7a9ef..0973b7a9ef 100644
--- a/tests/auto/corelib/tools/qtime/qtime.pro
+++ b/tests/auto/corelib/time/qtime/qtime.pro
diff --git a/tests/auto/corelib/tools/qtime/tst_qtime.cpp b/tests/auto/corelib/time/qtime/tst_qtime.cpp
index 3e5724213e..3403c5bf7f 100644
--- a/tests/auto/corelib/tools/qtime/tst_qtime.cpp
+++ b/tests/auto/corelib/time/qtime/tst_qtime.cpp
@@ -95,8 +95,9 @@ void tst_QTime::addSecs_data()
QTest::newRow("Data0") << QTime(0,0,0) << 200 << QTime(0,3,20);
QTest::newRow("Data1") << QTime(0,0,0) << 20 << QTime(0,0,20);
- QTest::newRow("overflow") << QTime(0,0,0) << (INT_MAX / 1000 + 1)
- << QTime(0,0,0).addSecs((INT_MAX / 1000 + 1) % 86400);
+ QTest::newRow("overflow")
+ << QTime(0,0,0) << (INT_MAX / 1000 + 1)
+ << QTime::fromMSecsSinceStartOfDay(((INT_MAX / 1000 + 1) % 86400) * 1000);
}
void tst_QTime::addSecs()
diff --git a/tests/auto/corelib/tools/qtimezone/BLACKLIST b/tests/auto/corelib/time/qtimezone/BLACKLIST
index 840c3b1181..840c3b1181 100644
--- a/tests/auto/corelib/tools/qtimezone/BLACKLIST
+++ b/tests/auto/corelib/time/qtimezone/BLACKLIST
diff --git a/tests/auto/corelib/tools/qtimezone/qtimezone.pro b/tests/auto/corelib/time/qtimezone/qtimezone.pro
index 5ec8d008e7..5ec8d008e7 100644
--- a/tests/auto/corelib/tools/qtimezone/qtimezone.pro
+++ b/tests/auto/corelib/time/qtimezone/qtimezone.pro
diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
index bb6c48a2ed..9904719f7c 100644
--- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
+++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp
@@ -480,11 +480,10 @@ void tst_QTimeZone::transitionEachZone_data()
{ 1288488600, -4, 8, 2010 } // 2010-10-31 01:30 UTC; Europe, Russia
};
- QString name;
const auto zones = QTimeZone::availableTimeZoneIds();
for (int k = sizeof(table) / sizeof(table[0]); k-- > 0; ) {
for (const QByteArray &zone : zones) {
- name.sprintf("%s@%d", zone.constData(), table[k].year);
+ const QString name = QString::asprintf("%s@%d", zone.constData(), table[k].year);
QTest::newRow(name.toUtf8().constData())
<< zone
<< table[k].baseSecs
@@ -916,6 +915,14 @@ void tst_QTimeZone::tzTest()
QTzTimeZonePrivate tzp("Europe/Berlin");
QVERIFY(tzp.isValid());
+ // Test POSIX-format value for $TZ:
+ QTzTimeZonePrivate tzposix("MET-1METDST-2,M3.5.0/02:00:00,M10.5.0/03:00:00");
+ QVERIFY(tzposix.isValid());
+
+ QTimeZone tzBrazil("BRT+3"); // parts of Northern Brazil, as a POSIX rule
+ QVERIFY(tzBrazil.isValid());
+ QCOMPARE(tzBrazil.offsetFromUtc(QDateTime(QDate(1111, 11, 11).startOfDay())), -10800);
+
// Test display names by type, either ICU or abbreviation only
QLocale enUS("en_US");
// Only test names in debug mode, names used can vary by ICU version installed
diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm b/tests/auto/corelib/time/qtimezone/tst_qtimezone_darwin.mm
index de801e55d0..de801e55d0 100644
--- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm
+++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone_darwin.mm
diff --git a/tests/auto/corelib/time/time.pro b/tests/auto/corelib/time/time.pro
new file mode 100644
index 0000000000..6f9ff038db
--- /dev/null
+++ b/tests/auto/corelib/time/time.pro
@@ -0,0 +1,6 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ qdate \
+ qdatetime \
+ qtime \
+ qtimezone
diff --git a/tests/auto/corelib/tools/collections/tst_collections.cpp b/tests/auto/corelib/tools/collections/tst_collections.cpp
index b40b1f0624..b911be3ffb 100644
--- a/tests/auto/corelib/tools/collections/tst_collections.cpp
+++ b/tests/auto/corelib/tools/collections/tst_collections.cpp
@@ -76,7 +76,7 @@ void foo()
#include "qlist.h"
#include "qmap.h"
#include "qpair.h"
-#include "qregexp.h"
+#include "qregularexpression.h"
#include "qset.h"
#include "qstack.h"
#include "qstring.h"
@@ -105,7 +105,9 @@ private slots:
void map();
void bitArray();
void cache();
+#if QT_CONFIG(regularexpression)
void regexp();
+#endif
void pair();
void sharableQList();
void sharableQLinkedList();
@@ -580,73 +582,73 @@ void tst_Collections::list()
list1 << 0 << 1 << 2 << 3;
list1.removeFirst();
- list1.swap(0, 0);
+ list1.swapItemsAt(0, 0);
QVERIFY(list1 == QList<int>() << 1 << 2 << 3);
- list1.swap(1, 1);
+ list1.swapItemsAt(1, 1);
QVERIFY(list1 == QList<int>() << 1 << 2 << 3);
- list1.swap(2, 2);
+ list1.swapItemsAt(2, 2);
QVERIFY(list1 == QList<int>() << 1 << 2 << 3);
- list1.swap(0, 1);
+ list1.swapItemsAt(0, 1);
QVERIFY(list1 == QList<int>() << 2 << 1 << 3);
- list1.swap(0, 2);
+ list1.swapItemsAt(0, 2);
QVERIFY(list1 == QList<int>() << 3 << 1 << 2);
- list1.swap(1, 2);
+ list1.swapItemsAt(1, 2);
QVERIFY(list1 == QList<int>() << 3 << 2 << 1);
- list1.swap(1, 2);
+ list1.swapItemsAt(1, 2);
QVERIFY(list1 == QList<int>() << 3 << 1 << 2);
QList<QString> list2;
list2 << "1" << "2" << "3";
- list2.swap(0, 0);
+ list2.swapItemsAt(0, 0);
QVERIFY(list2 == QList<QString>() << "1" << "2" << "3");
- list2.swap(1, 1);
+ list2.swapItemsAt(1, 1);
QVERIFY(list2 == QList<QString>() << "1" << "2" << "3");
- list2.swap(2, 2);
+ list2.swapItemsAt(2, 2);
QVERIFY(list2 == QList<QString>() << "1" << "2" << "3");
- list2.swap(0, 1);
+ list2.swapItemsAt(0, 1);
QVERIFY(list2 == QList<QString>() << "2" << "1" << "3");
- list2.swap(0, 2);
+ list2.swapItemsAt(0, 2);
QVERIFY(list2 == QList<QString>() << "3" << "1" << "2");
- list2.swap(1, 2);
+ list2.swapItemsAt(1, 2);
QVERIFY(list2 == QList<QString>() << "3" << "2" << "1");
- list2.swap(1, 2);
+ list2.swapItemsAt(1, 2);
QVERIFY(list2 == QList<QString>() << "3" << "1" << "2");
QList<double> list3;
list3 << 1.0 << 2.0 << 3.0;
- list3.swap(0, 0);
+ list3.swapItemsAt(0, 0);
QVERIFY(list3 == QList<double>() << 1.0 << 2.0 << 3.0);
- list3.swap(1, 1);
+ list3.swapItemsAt(1, 1);
QVERIFY(list3 == QList<double>() << 1.0 << 2.0 << 3.0);
- list3.swap(2, 2);
+ list3.swapItemsAt(2, 2);
QVERIFY(list3 == QList<double>() << 1.0 << 2.0 << 3.0);
- list3.swap(0, 1);
+ list3.swapItemsAt(0, 1);
QVERIFY(list3 == QList<double>() << 2.0 << 1.0 << 3.0);
- list3.swap(0, 2);
+ list3.swapItemsAt(0, 2);
QVERIFY(list3 == QList<double>() << 3.0 << 1.0 << 2.0);
- list3.swap(1, 2);
+ list3.swapItemsAt(1, 2);
QVERIFY(list3 == QList<double>() << 3.0 << 2.0 << 1.0);
- list3.swap(1, 2);
+ list3.swapItemsAt(1, 2);
QVERIFY(list3 == QList<double>() << 3.0 << 1.0 << 2.0);
}
@@ -2285,13 +2287,15 @@ void tst_Collections::cache()
}
+#if QT_CONFIG(regularexpression)
void tst_Collections::regexp()
{
- QRegExp rx("^\\d\\d?$");
- QVERIFY(rx.indexIn("123") == -1);
- QVERIFY(rx.indexIn("-6") == -1);
- QVERIFY(rx.indexIn("6") == 0) ;
+ QRegularExpression rx("^\\d\\d?$");
+ QVERIFY(!rx.match("123").hasMatch());
+ QVERIFY(!rx.match("-6").hasMatch());
+ QVERIFY(rx.match("6").hasMatch()) ;
}
+#endif
void tst_Collections::pair()
{
@@ -2425,7 +2429,7 @@ void testContainer()
c1 = newInstance<Container>();
QVERIFY(c1.size() == 4);
QVERIFY(c1 == newInstance<Container>());
- Container c2 = qMove(c1);
+ Container c2 = std::move(c1);
QVERIFY(c2.size() == 4);
QVERIFY(c2 == newInstance<Container>());
}
@@ -2531,14 +2535,18 @@ void tst_Collections::conversions()
QCOMPARE(list2.size(), 4);
QVERIFY(list2 == (QList<QString>() << STUFF));
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QSet<QString> set1 = list1.toSet();
+#else
+ QSet<QString> set1(list1.begin(), list1.end());
+#endif
QCOMPARE(set1.size(), 3);
QVERIFY(set1.contains("A"));
QVERIFY(set1.contains("B"));
QVERIFY(set1.contains("C"));
QVERIFY(!set1.contains("D"));
- QList<QString> list3 = set1.toList();
+ QList<QString> list3 = set1.values();
QCOMPARE(list3.size(), 3);
QVERIFY(list3.contains("A"));
QVERIFY(list3.contains("B"));
@@ -2546,9 +2554,11 @@ void tst_Collections::conversions()
QVERIFY(!list3.contains("D"));
QVERIFY(QList<int>().toVector().isEmpty());
- QVERIFY(QList<int>().toSet().isEmpty());
QVERIFY(QVector<int>().toList().isEmpty());
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ QVERIFY(QList<int>().toSet().isEmpty());
QVERIFY(QSet<int>().toList().isEmpty());
+#endif
}
{
@@ -2563,14 +2573,22 @@ void tst_Collections::conversions()
QCOMPARE(list2.size(), 4);
QVERIFY(list2 == (QList<QString>() << STUFF));
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QSet<QString> set1 = QSet<QString>::fromList(list1);
+#else
+ QSet<QString> set1(list1.begin(), list1.end());
+#endif
QCOMPARE(set1.size(), 3);
QVERIFY(set1.contains("A"));
QVERIFY(set1.contains("B"));
QVERIFY(set1.contains("C"));
QVERIFY(!set1.contains("D"));
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QList<QString> list3 = QList<QString>::fromSet(set1);
+#else
+ QList<QString> list3 = set1.values();
+#endif
QCOMPARE(list3.size(), 3);
QVERIFY(list3.contains("A"));
QVERIFY(list3.contains("B"));
@@ -2578,9 +2596,11 @@ void tst_Collections::conversions()
QVERIFY(!list3.contains("D"));
QVERIFY(QVector<int>::fromList(QList<int>()).isEmpty());
- QVERIFY(QSet<int>::fromList(QList<int>()).isEmpty());
QVERIFY(QList<int>::fromVector(QVector<int>()).isEmpty());
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ QVERIFY(QSet<int>::fromList(QList<int>()).isEmpty());
QVERIFY(QList<int>::fromSet(QSet<int>()).isEmpty());
+#endif
}
#undef STUFF
}
@@ -2776,15 +2796,21 @@ void tst_Collections::vector_stl()
for (int i = 0; i < elements.count(); ++i)
vector << elements.at(i);
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
std::vector<QString> stdVector = vector.toStdVector();
-
+#else
+ std::vector<QString> stdVector(vector.begin(), vector.end());
+#endif
QCOMPARE(int(stdVector.size()), elements.size());
std::vector<QString>::const_iterator it = stdVector.begin();
for (uint j = 0; j < stdVector.size() && it != stdVector.end(); ++j, ++it)
QCOMPARE(*it, vector[j]);
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QCOMPARE(QVector<QString>::fromStdVector(stdVector), vector);
+#endif
+ QCOMPARE(QVector<QString>(stdVector.begin(), stdVector.end()), vector);
}
void tst_Collections::linkedlist_stl_data()
@@ -2830,7 +2856,11 @@ void tst_Collections::list_stl()
for (int i = 0; i < elements.count(); ++i)
list << elements.at(i);
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
std::list<QString> stdList = list.toStdList();
+#else
+ std::list<QString> stdList(list.begin(), list.end());
+#endif
QCOMPARE(int(stdList.size()), elements.size());
@@ -2838,7 +2868,10 @@ void tst_Collections::list_stl()
for (uint j = 0; j < stdList.size() && it != stdList.end(); ++j, ++it)
QCOMPARE(*it, list[j]);
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QCOMPARE(QList<QString>::fromStdList(stdList), list);
+#endif
+ QCOMPARE(QList<QString>(stdList.begin(), stdList.end()), list);
}
template <typename T>
diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
index 3b8111f1a3..4b085d387d 100644
--- a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
+++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
@@ -34,13 +34,446 @@
#include "qstring.h"
#include "qvarlengtharray.h"
#include "qvector.h"
+#include "qhash.h"
+#include "qdebug.h"
+#include <algorithm>
+#include <functional>
#include <vector> // for reference
+#include <list>
+#include <set>
+#include <map>
+
+// MSVC has these containers from the Standard Library, but it lacks
+// a __has_include mechanism (that we need to use for other stdlibs).
+// For the sake of increasing our test coverage, work around the issue.
+
+#ifdef Q_CC_MSVC
+#define COMPILER_HAS_STDLIB_INCLUDE(x) 1
+#else
+#define COMPILER_HAS_STDLIB_INCLUDE(x) QT_HAS_INCLUDE(x)
+#endif
+
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+#include <forward_list>
+#endif
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+#include <unordered_set>
+#endif
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+#include <unordered_map>
+#endif
+
+struct Movable
+{
+ explicit Movable(int i = 0) Q_DECL_NOTHROW
+ : i(i)
+ {
+ ++instanceCount;
+ }
+
+ Movable(const Movable &m)
+ : i(m.i)
+ {
+ ++instanceCount;
+ }
+
+ ~Movable()
+ {
+ --instanceCount;
+ }
+
+ int i;
+ static int instanceCount;
+};
+
+int Movable::instanceCount = 0;
+bool operator==(Movable lhs, Movable rhs) Q_DECL_NOTHROW { return lhs.i == rhs.i; }
+bool operator!=(Movable lhs, Movable rhs) Q_DECL_NOTHROW { return lhs.i != rhs.i; }
+bool operator<(Movable lhs, Movable rhs) Q_DECL_NOTHROW { return lhs.i < rhs.i; }
+
+uint qHash(Movable m, uint seed = 0) Q_DECL_NOTHROW { return qHash(m.i, seed); }
+QDebug &operator<<(QDebug &d, Movable m)
+{
+ const QDebugStateSaver saver(d);
+ return d.nospace() << "Movable(" << m.i << ")";
+}
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
+
+struct Complex
+{
+ explicit Complex(int i = 0) Q_DECL_NOTHROW
+ : i(i)
+ {
+ ++instanceCount;
+ }
+
+ Complex(const Complex &c)
+ : i(c.i)
+ {
+ ++instanceCount;
+ }
+
+ ~Complex()
+ {
+ --instanceCount;
+ }
+
+ int i;
+ static int instanceCount;
+};
+
+int Complex::instanceCount = 0;
+bool operator==(Complex lhs, Complex rhs) Q_DECL_NOTHROW { return lhs.i == rhs.i; }
+bool operator!=(Complex lhs, Complex rhs) Q_DECL_NOTHROW { return lhs.i != rhs.i; }
+bool operator<(Complex lhs, Complex rhs) Q_DECL_NOTHROW { return lhs.i < rhs.i; }
+
+uint qHash(Complex c, uint seed = 0) Q_DECL_NOTHROW { return qHash(c.i, seed); }
+QDebug &operator<<(QDebug &d, Complex c)
+{
+ const QDebugStateSaver saver(d);
+ return d.nospace() << "Complex(" << c.i << ")";
+}
+
+
+struct DuplicateStrategyTestType
+{
+ explicit DuplicateStrategyTestType(int i = 0) Q_DECL_NOTHROW
+ : i(i),
+ j(++counter)
+ {
+ }
+
+ int i;
+ int j;
+
+ static int counter;
+};
+
+int DuplicateStrategyTestType::counter = 0;
+
+// only look at the i member, not j. j allows us to identify which instance
+// gets inserted in containers that don't allow for duplicates
+bool operator==(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW
+{
+ return lhs.i == rhs.i;
+}
+
+bool operator!=(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW
+{
+ return lhs.i != rhs.i;
+}
+
+bool operator<(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW
+{
+ return lhs.i < rhs.i;
+}
+
+uint qHash(DuplicateStrategyTestType c, uint seed = 0) Q_DECL_NOTHROW
+{
+ return qHash(c.i, seed);
+}
+
+bool reallyEqual(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW
+{
+ return lhs.i == rhs.i && lhs.j == rhs.j;
+}
+
+QDebug &operator<<(QDebug &d, DuplicateStrategyTestType c)
+{
+ const QDebugStateSaver saver(d);
+ return d.nospace() << "DuplicateStrategyTestType(" << c.i << "," << c.j << ")";
+}
+
+
+namespace std {
+template<>
+struct hash<Movable>
+{
+ std::size_t operator()(Movable m) const Q_DECL_NOTHROW
+ {
+ return hash<int>()(m.i);
+ }
+};
+
+template<>
+struct hash<Complex>
+{
+ std::size_t operator()(Complex m) const Q_DECL_NOTHROW
+ {
+ return hash<int>()(m.i);
+ }
+};
+
+template<>
+struct hash<DuplicateStrategyTestType>
+{
+ std::size_t operator()(DuplicateStrategyTestType m) const Q_DECL_NOTHROW
+ {
+ return hash<int>()(m.i);
+ }
+};
+}
+
+// work around the fact that QVarLengthArray has a non-type
+// template parameter, and that breaks non_associative_container_duplicates_strategy
+template<typename T>
+class VarLengthArray : public QVarLengthArray<T>
+{
+public:
+#ifdef Q_COMPILER_INHERITING_CONSTRUCTORS
+ using QVarLengthArray<T>::QVarLengthArray;
+#else
+ template<typename InputIterator>
+ VarLengthArray(InputIterator first, InputIterator last)
+ : QVarLengthArray<T>(first, last)
+ {
+ }
+
+ VarLengthArray(std::initializer_list<T> args)
+ : QVarLengthArray<T>(args)
+ {
+ }
+#endif
+};
class tst_ContainerApiSymmetry : public QObject
{
Q_OBJECT
+ int m_movableInstanceCount;
+ int m_complexInstanceCount;
+
+private Q_SLOTS:
+ void init();
+ void cleanup();
+
+private:
+ template <typename Container>
+ void ranged_ctor_non_associative_impl() const;
+
+ template<template<typename ... T> class Container>
+ void non_associative_container_duplicates_strategy() const;
+
+ template <typename Container>
+ void ranged_ctor_associative_impl() const;
+
+private Q_SLOTS:
+ // non associative
+ void ranged_ctor_std_vector_int() { ranged_ctor_non_associative_impl<std::vector<int>>(); }
+ void ranged_ctor_std_vector_char() { ranged_ctor_non_associative_impl<std::vector<char>>(); }
+ void ranged_ctor_std_vector_QChar() { ranged_ctor_non_associative_impl<std::vector<QChar>>(); }
+ void ranged_ctor_std_vector_Movable() { ranged_ctor_non_associative_impl<std::vector<Movable>>(); }
+ void ranged_ctor_std_vector_Complex() { ranged_ctor_non_associative_impl<std::vector<Complex>>(); }
+ void ranged_ctor_std_vector_duplicates_strategy() { non_associative_container_duplicates_strategy<std::vector>(); }
+
+ void ranged_ctor_QVector_int() { ranged_ctor_non_associative_impl<QVector<int>>(); }
+ void ranged_ctor_QVector_char() { ranged_ctor_non_associative_impl<QVector<char>>(); }
+ void ranged_ctor_QVector_QChar() { ranged_ctor_non_associative_impl<QVector<QChar>>(); }
+ void ranged_ctor_QVector_Movable() { ranged_ctor_non_associative_impl<QVector<Movable>>(); }
+ void ranged_ctor_QVector_Complex() { ranged_ctor_non_associative_impl<QVector<Complex>>(); }
+ void ranged_ctor_QVector_duplicates_strategy() { non_associative_container_duplicates_strategy<QVector>(); }
+
+ void ranged_ctor_QVarLengthArray_int() { ranged_ctor_non_associative_impl<QVarLengthArray<int>>(); }
+ void ranged_ctor_QVarLengthArray_Movable() { ranged_ctor_non_associative_impl<QVarLengthArray<Movable>>(); }
+ void ranged_ctor_QVarLengthArray_Complex() { ranged_ctor_non_associative_impl<QVarLengthArray<Complex>>(); }
+ void ranged_ctor_QVarLengthArray_duplicates_strategy() { non_associative_container_duplicates_strategy<VarLengthArray>(); } // note the VarLengthArray passed
+
+ void ranged_ctor_QList_int() { ranged_ctor_non_associative_impl<QList<int>>(); }
+ void ranged_ctor_QList_Movable() { ranged_ctor_non_associative_impl<QList<Movable>>(); }
+ void ranged_ctor_QList_Complex() { ranged_ctor_non_associative_impl<QList<Complex>>(); }
+ void ranged_ctor_QList_duplicates_strategy() { non_associative_container_duplicates_strategy<QList>(); }
+
+ void ranged_ctor_std_list_int() { ranged_ctor_non_associative_impl<std::list<int>>(); }
+ void ranged_ctor_std_list_Movable() { ranged_ctor_non_associative_impl<std::list<Movable>>(); }
+ void ranged_ctor_std_list_Complex() { ranged_ctor_non_associative_impl<std::list<Complex>>(); }
+ void ranged_ctor_std_list_duplicates_strategy() { non_associative_container_duplicates_strategy<std::list>(); }
+
+ void ranged_ctor_std_forward_list_int() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+ ranged_ctor_non_associative_impl<std::forward_list<int>>();
+#else
+ QSKIP("<forward_list> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_forward_list_Movable() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+ ranged_ctor_non_associative_impl<std::forward_list<Movable>>();
+#else
+ QSKIP("<forward_list> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_forward_list_Complex() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+ ranged_ctor_non_associative_impl<std::forward_list<Complex>>();
+#else
+ QSKIP("<forward_list> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_forward_list_duplicates_strategy() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+ non_associative_container_duplicates_strategy<std::forward_list>();
+#else
+ QSKIP("<forward_list> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_QLinkedList_int() { ranged_ctor_non_associative_impl<QLinkedList<int>>(); }
+ void ranged_ctor_QLinkedList_Movable() { ranged_ctor_non_associative_impl<QLinkedList<Movable>>(); }
+ void ranged_ctor_QLinkedList_Complex() { ranged_ctor_non_associative_impl<QLinkedList<Complex>>(); }
+ void ranged_ctor_QLinkedList_duplicates_strategy() { non_associative_container_duplicates_strategy<QLinkedList>(); }
+
+ void ranged_ctor_std_set_int() { ranged_ctor_non_associative_impl<std::set<int>>(); }
+ void ranged_ctor_std_set_Movable() { ranged_ctor_non_associative_impl<std::set<Movable>>(); }
+ void ranged_ctor_std_set_Complex() { ranged_ctor_non_associative_impl<std::set<Complex>>(); }
+ void ranged_ctor_std_set_duplicates_strategy() { non_associative_container_duplicates_strategy<std::set>(); }
+
+ void ranged_ctor_std_multiset_int() { ranged_ctor_non_associative_impl<std::multiset<int>>(); }
+ void ranged_ctor_std_multiset_Movable() { ranged_ctor_non_associative_impl<std::multiset<Movable>>(); }
+ void ranged_ctor_std_multiset_Complex() { ranged_ctor_non_associative_impl<std::multiset<Complex>>(); }
+ void ranged_ctor_std_multiset_duplicates_strategy() { non_associative_container_duplicates_strategy<std::multiset>(); }
+
+ void ranged_ctor_std_unordered_set_int() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_set<int>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_unordered_set_Movable() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_set<Movable>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_unordered_set_Complex() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_set<Complex>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_unordered_set_duplicates_strategy() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ non_associative_container_duplicates_strategy<std::unordered_set>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+
+ void ranged_ctor_std_unordered_multiset_int() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_multiset<int>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_unordered_multiset_Movable() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_multiset<Movable>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_unordered_multiset_Complex() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ ranged_ctor_non_associative_impl<std::unordered_multiset<Complex>>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_std_unordered_multiset_duplicates_strategy() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+ non_associative_container_duplicates_strategy<std::unordered_multiset>();
+#else
+ QSKIP("<unordered_set> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_QSet_int() { ranged_ctor_non_associative_impl<QSet<int>>(); }
+ void ranged_ctor_QSet_Movable() { ranged_ctor_non_associative_impl<QSet<Movable>>(); }
+ void ranged_ctor_QSet_Complex() { ranged_ctor_non_associative_impl<QSet<Complex>>(); }
+ void ranged_ctor_QSet_duplicates_strategy() { non_associative_container_duplicates_strategy<QSet>(); }
+
+ // associative
+ void ranged_ctor_std_map_int() { ranged_ctor_associative_impl<std::map<int, int>>(); }
+ void ranged_ctor_std_map_Movable() { ranged_ctor_associative_impl<std::map<Movable, int>>(); }
+ void ranged_ctor_std_map_Complex() { ranged_ctor_associative_impl<std::map<Complex, int>>(); }
+
+ void ranged_ctor_std_multimap_int() { ranged_ctor_associative_impl<std::multimap<int, int>>(); }
+ void ranged_ctor_std_multimap_Movable() { ranged_ctor_associative_impl<std::multimap<Movable, int>>(); }
+ void ranged_ctor_std_multimap_Complex() { ranged_ctor_associative_impl<std::multimap<Complex, int>>(); }
+
+ void ranged_ctor_unordered_map_int() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_map<int, int>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_unordered_map_Movable() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_map<Movable, Movable>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_unordered_map_Complex() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_map<Complex, Complex>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_QHash_int() { ranged_ctor_associative_impl<QHash<int, int>>(); }
+ void ranged_ctor_QHash_Movable() { ranged_ctor_associative_impl<QHash<Movable, int>>(); }
+ void ranged_ctor_QHash_Complex() { ranged_ctor_associative_impl<QHash<Complex, int>>(); }
+
+ void ranged_ctor_unordered_multimap_int() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_multimap<int, int>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_unordered_multimap_Movable() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_multimap<Movable, Movable>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_unordered_multimap_Complex() {
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_map>)
+ ranged_ctor_associative_impl<std::unordered_multimap<Complex, Complex>>();
+#else
+ QSKIP("<unordered_map> is needed for this test");
+#endif
+ }
+
+ void ranged_ctor_QMultiHash_int() { ranged_ctor_associative_impl<QMultiHash<int, int>>(); }
+ void ranged_ctor_QMultiHash_Movable() { ranged_ctor_associative_impl<QMultiHash<Movable, int>>(); }
+ void ranged_ctor_QMultiHash_Complex() { ranged_ctor_associative_impl<QMultiHash<Complex, int>>(); }
+
private:
template <typename Container>
void front_back_impl() const;
@@ -58,6 +491,296 @@ private Q_SLOTS:
void front_back_QByteArray() { front_back_impl<QByteArray>(); }
};
+void tst_ContainerApiSymmetry::init()
+{
+ m_movableInstanceCount = Movable::instanceCount;
+ m_complexInstanceCount = Complex::instanceCount;
+}
+
+void tst_ContainerApiSymmetry::cleanup()
+{
+ // very simple leak check
+ QCOMPARE(Movable::instanceCount, m_movableInstanceCount);
+ QCOMPARE(Complex::instanceCount, m_complexInstanceCount);
+}
+
+template <typename Container>
+Container createContainerReference()
+{
+ using V = typename Container::value_type;
+
+ return {V(0), V(1), V(2), V(0)};
+}
+
+template <typename Container>
+void tst_ContainerApiSymmetry::ranged_ctor_non_associative_impl() const
+{
+ using V = typename Container::value_type;
+
+ // the double V(0) is deliberate
+ const auto reference = createContainerReference<Container>();
+
+ // plain array
+ const V values1[] = { V(0), V(1), V(2), V(0) };
+
+ const Container c1(values1, values1 + sizeof(values1)/sizeof(values1[0]));
+
+ // from QList
+ QList<V> l2;
+ l2 << V(0) << V(1) << V(2) << V(0);
+
+ const Container c2a(l2.begin(), l2.end());
+ const Container c2b(l2.cbegin(), l2.cend());
+
+ // from std::list
+ std::list<V> l3;
+ l3.push_back(V(0));
+ l3.push_back(V(1));
+ l3.push_back(V(2));
+ l3.push_back(V(0));
+ const Container c3a(l3.begin(), l3.end());
+
+ // from const std::list
+ const std::list<V> l3c = l3;
+ const Container c3b(l3c.begin(), l3c.end());
+
+ // from itself
+ const Container c4(reference.begin(), reference.end());
+
+ QCOMPARE(c1, reference);
+ QCOMPARE(c2a, reference);
+ QCOMPARE(c2b, reference);
+ QCOMPARE(c3a, reference);
+ QCOMPARE(c3b, reference);
+ QCOMPARE(c4, reference);
+}
+
+
+// type traits for detecting whether a non-associative container
+// accepts duplicated values, and if it doesn't, whether construction/insertion
+// prefer the new values (overwriting) or the old values (rejecting)
+
+struct ContainerAcceptsDuplicateValues {};
+struct ContainerOverwritesDuplicateValues {};
+struct ContainerRejectsDuplicateValues {};
+
+template<typename Container>
+struct ContainerDuplicatedValuesStrategy {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::vector<T...>> : ContainerAcceptsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<QVector<T...>> : ContainerAcceptsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<QVarLengthArray<T...>> : ContainerAcceptsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<VarLengthArray<T...>> : ContainerAcceptsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<QList<T...>> : ContainerAcceptsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::list<T...>> : ContainerAcceptsDuplicateValues {};
+
+#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::forward_list<T...>> : ContainerAcceptsDuplicateValues {};
+#endif
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<QLinkedList<T...>> : ContainerAcceptsDuplicateValues {};
+
+// assuming https://cplusplus.github.io/LWG/lwg-active.html#2844 resolution
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::set<T...>> : ContainerRejectsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::multiset<T...>> : ContainerAcceptsDuplicateValues {};
+
+#if COMPILER_HAS_STDLIB_INCLUDE(<unordered_set>)
+// assuming https://cplusplus.github.io/LWG/lwg-active.html#2844 resolution
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::unordered_set<T...>> : ContainerRejectsDuplicateValues {};
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<std::unordered_multiset<T...>> : ContainerAcceptsDuplicateValues {};
+#endif
+
+template<typename ... T>
+struct ContainerDuplicatedValuesStrategy<QSet<T...>> : ContainerRejectsDuplicateValues {};
+
+template<typename Container>
+void non_associative_container_check_duplicates_impl(const std::initializer_list<DuplicateStrategyTestType> &reference, const Container &c, ContainerAcceptsDuplicateValues)
+{
+ // do a deep check for equality, not ordering
+ QVERIFY(std::distance(reference.begin(), reference.end()) == std::distance(c.begin(), c.end()));
+ QVERIFY(std::is_permutation(reference.begin(), reference.end(), c.begin(), &reallyEqual));
+}
+
+enum class IterationOnReference
+{
+ ForwardIteration,
+ ReverseIteration
+};
+
+template<typename Container>
+void non_associative_container_check_duplicates_impl_no_duplicates(const std::initializer_list<DuplicateStrategyTestType> &reference, const Container &c, IterationOnReference ior)
+{
+ std::vector<DuplicateStrategyTestType> valuesAlreadySeen;
+
+ // iterate on reference forward or backwards, depending on ior. this will give
+ // us the expected semantics when checking for duplicated values into c
+ auto it = [&reference, ior]() {
+ switch (ior) {
+ case IterationOnReference::ForwardIteration: return reference.begin();
+ case IterationOnReference::ReverseIteration: return reference.end() - 1;
+ };
+ return std::initializer_list<DuplicateStrategyTestType>::const_iterator();
+ }();
+
+ const auto &end = [&reference, ior]() {
+ switch (ior) {
+ case IterationOnReference::ForwardIteration: return reference.end();
+ case IterationOnReference::ReverseIteration: return reference.begin() - 1;
+ };
+ return std::initializer_list<DuplicateStrategyTestType>::const_iterator();
+ }();
+
+ while (it != end) {
+ const auto &value = *it;
+
+ // check that there is indeed the same value in the container (using operator==)
+ const auto &valueInContainerIterator = std::find(c.begin(), c.end(), value);
+ QVERIFY(valueInContainerIterator != c.end());
+ QVERIFY(value == *valueInContainerIterator);
+
+ // if the value is a duplicate, we don't expect to find it in the container
+ // (when doing a deep comparison). otherwise it should be there
+
+ const auto &valuesAlreadySeenIterator = std::find(valuesAlreadySeen.cbegin(), valuesAlreadySeen.cend(), value);
+ const bool valueIsDuplicated = (valuesAlreadySeenIterator != valuesAlreadySeen.cend());
+
+ const auto &reallyEqualCheck = [&value](const DuplicateStrategyTestType &v) { return reallyEqual(value, v); };
+ QCOMPARE(std::find_if(c.begin(), c.end(), reallyEqualCheck) == c.end(), valueIsDuplicated);
+
+ valuesAlreadySeen.push_back(value);
+
+ switch (ior) {
+ case IterationOnReference::ForwardIteration:
+ ++it;
+ break;
+ case IterationOnReference::ReverseIteration:
+ --it;
+ break;
+ };
+ }
+
+}
+
+template<typename Container>
+void non_associative_container_check_duplicates_impl(const std::initializer_list<DuplicateStrategyTestType> &reference, const Container &c, ContainerRejectsDuplicateValues)
+{
+ non_associative_container_check_duplicates_impl_no_duplicates(reference, c, IterationOnReference::ForwardIteration);
+}
+
+template<typename Container>
+void non_associative_container_check_duplicates_impl(const std::initializer_list<DuplicateStrategyTestType> &reference, const Container &c, ContainerOverwritesDuplicateValues)
+{
+ non_associative_container_check_duplicates_impl_no_duplicates(reference, c, IterationOnReference::ReverseIteration);
+}
+
+template<typename Container>
+void non_associative_container_check_duplicates(const std::initializer_list<DuplicateStrategyTestType> &reference, const Container &c)
+{
+ non_associative_container_check_duplicates_impl(reference, c, ContainerDuplicatedValuesStrategy<Container>());
+}
+
+template<template<class ... T> class Container>
+void tst_ContainerApiSymmetry::non_associative_container_duplicates_strategy() const
+{
+ // first and last are "duplicates" -- they compare equal for operator==,
+ // but they differ when using reallyEqual
+ const std::initializer_list<DuplicateStrategyTestType> reference{ DuplicateStrategyTestType{0},
+ DuplicateStrategyTestType{1},
+ DuplicateStrategyTestType{2},
+ DuplicateStrategyTestType{0} };
+ Container<DuplicateStrategyTestType> c1{reference};
+ non_associative_container_check_duplicates(reference, c1);
+
+ Container<DuplicateStrategyTestType> c2{reference.begin(), reference.end()};
+ non_associative_container_check_duplicates(reference, c2);
+}
+
+template <typename Container>
+void tst_ContainerApiSymmetry::ranged_ctor_associative_impl() const
+{
+ using K = typename Container::key_type;
+ using V = typename Container::mapped_type;
+
+ // The double K(0) is deliberate. The order of the elements matters:
+ // * for unique-key STL containers, the first one should be the one inserted (cf. LWG 2844)
+ // * for unique-key Qt containers, the last one should be the one inserted
+ // * for multi-key sorted containers, the order of insertion of identical keys is also the
+ // iteration order (which establishes the equality of the containers)
+ // (although nothing of this is being tested here, that deserves its own testing)
+ const Container reference{
+ { K(0), V(1000) },
+ { K(1), V(1001) },
+ { K(2), V(1002) },
+ { K(0), V(1003) }
+ };
+
+ // Note that using anything not convertible to std::pair doesn't work for
+ // std containers. Their ranged construction is defined in terms of
+ // insert(value_type), which for std associative containers is
+ // std::pair<const K, T>.
+
+ // plain array
+ const std::pair<K, V> values1[] = {
+ std::make_pair(K(0), V(1000)),
+ std::make_pair(K(1), V(1001)),
+ std::make_pair(K(2), V(1002)),
+ std::make_pair(K(0), V(1003))
+ };
+
+ const Container c1(values1, values1 + sizeof(values1)/sizeof(values1[0]));
+
+ // from QList
+ QList<std::pair<K, V>> l2;
+ l2 << std::make_pair(K(0), V(1000))
+ << std::make_pair(K(1), V(1001))
+ << std::make_pair(K(2), V(1002))
+ << std::make_pair(K(0), V(1003));
+
+ const Container c2a(l2.begin(), l2.end());
+ const Container c2b(l2.cbegin(), l2.cend());
+
+ // from std::list
+ std::list<std::pair<K, V>> l3;
+ l3.push_back(std::make_pair(K(0), V(1000)));
+ l3.push_back(std::make_pair(K(1), V(1001)));
+ l3.push_back(std::make_pair(K(2), V(1002)));
+ l3.push_back(std::make_pair(K(0), V(1003)));
+ const Container c3a(l3.begin(), l3.end());
+
+ // from const std::list
+ const std::list<std::pair<K, V>> l3c = l3;
+ const Container c3b(l3c.begin(), l3c.end());
+
+ // from itself
+ const Container c4(reference.begin(), reference.end());
+
+ QCOMPARE(c1, reference);
+ QCOMPARE(c2a, reference);
+ QCOMPARE(c2b, reference);
+ QCOMPARE(c3a, reference);
+ QCOMPARE(c3b, reference);
+ QCOMPARE(c4, reference);
+}
+
template <typename Container>
Container make(int size)
{
diff --git a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp
index 72299402f0..06db0e8546 100644
--- a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp
+++ b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp
@@ -208,7 +208,7 @@ void printHeader(QStringList &headers)
for (int h = 0; h < headers.count(); ++h) {
cout << setw(20) << setiosflags(ios_base::left) << headers.at(h).toLatin1().constData();
}
- cout << endl;
+ cout << Qt::endl;
}
template <typename ContainerType>
@@ -220,7 +220,7 @@ void print(ContainerType testContainer)
cout << value << " ";
}
- cout << endl;
+ cout << Qt::endl;
}
template <typename Algorithm, typename DataType>
@@ -252,7 +252,7 @@ void testAlgorithm(Algorithm algorithm, QStringList &dataSetTypes)
lessThan << setiosflags(ios_base::left) << setw(10) << result.lessThanRefCount / result.numSorts;
cout << numSorts.str() << lessThan.str();
}
- cout << endl;
+ cout << Qt::endl;
}
}
#endif
@@ -765,21 +765,21 @@ public:
#if Q_TEST_PERFORMANCE
void tst_QAlgorithms::performance()
{
- cout << endl << "Quick sort" << endl;
+ cout << Qt::endl << "Quick sort" << Qt::endl;
testAlgorithm<QuickSortHelper<TestInt>, TestInt>(QuickSortHelper<TestInt>(), dataSetTypes);
- cout << endl << "stable sort" << endl;
+ cout << Qt::endl << "stable sort" << Qt::endl;
testAlgorithm<StableSortHelper<TestInt>, TestInt>(StableSortHelper<TestInt>(), dataSetTypes);
- cout << endl << "std::sort" << endl;
+ cout << Qt::endl << "std::sort" << Qt::endl;
testAlgorithm<StlSortHelper<TestInt>, TestInt>(StlSortHelper<TestInt>(), dataSetTypes);
- cout << endl << "std::stable_sort" << endl;
+ cout << Qt::endl << "std::stable_sort" << Qt::endl;
testAlgorithm<StlStableSortHelper<TestInt>, TestInt>(StlStableSortHelper<TestInt>(), dataSetTypes);
/*
- cout << endl << "Sorting lists of ints" << endl;
- cout << endl << "Quick sort" << endl;
+ cout << Qt::endl << "Sorting lists of ints" << Qt::endl;
+ cout << Qt::endl << "Quick sort" << Qt::endl;
testAlgorithm<QuickSortHelper<int>, int>(QuickSortHelper<int>(), dataSetTypes);
- cout << endl << "std::sort" << endl;
+ cout << Qt::endl << "std::sort" << Qt::endl;
testAlgorithm<StlSortHelper<int>, int>(StlSortHelper<int>(), dataSetTypes);
- cout << endl << "std::stable_sort" << endl;
+ cout << Qt::endl << "std::stable_sort" << Qt::endl;
testAlgorithm<StlStableSortHelper<int>, int>(StlStableSortHelper<int>(), dataSetTypes);
*/
}
diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
index a00c962510..7db7d71b1f 100644
--- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
+++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
@@ -78,12 +78,8 @@ private slots:
void fromRawData_data();
void fromRawData();
void literals();
-#if defined(Q_COMPILER_VARIADIC_MACROS) && defined(Q_COMPILER_LAMBDA)
void variadicLiterals();
-#endif
-#ifdef Q_COMPILER_RVALUE_REFS
void rValueReferences();
-#endif
void grow();
};
@@ -95,7 +91,7 @@ void tst_QArrayData::referenceCounting()
// Reference counting initialized to 1 (owned)
QArrayData array = { { Q_BASIC_ATOMIC_INITIALIZER(1) }, 0, 0, 0, 0 };
- QCOMPARE(array.ref.atomic.load(), 1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 1);
QVERIFY(!array.ref.isStatic());
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
@@ -103,19 +99,19 @@ void tst_QArrayData::referenceCounting()
#endif
QVERIFY(array.ref.ref());
- QCOMPARE(array.ref.atomic.load(), 2);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 2);
QVERIFY(array.ref.deref());
- QCOMPARE(array.ref.atomic.load(), 1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 1);
QVERIFY(array.ref.ref());
- QCOMPARE(array.ref.atomic.load(), 2);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 2);
QVERIFY(array.ref.deref());
- QCOMPARE(array.ref.atomic.load(), 1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 1);
QVERIFY(!array.ref.deref());
- QCOMPARE(array.ref.atomic.load(), 0);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 0);
// Now would be a good time to free/release allocated data
}
@@ -125,17 +121,17 @@ void tst_QArrayData::referenceCounting()
// Reference counting initialized to 0 (non-sharable)
QArrayData array = { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, 0 };
- QCOMPARE(array.ref.atomic.load(), 0);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 0);
QVERIFY(!array.ref.isStatic());
QVERIFY(!array.ref.isSharable());
QVERIFY(!array.ref.ref());
// Reference counting fails, data should be copied
- QCOMPARE(array.ref.atomic.load(), 0);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 0);
QVERIFY(!array.ref.deref());
- QCOMPARE(array.ref.atomic.load(), 0);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), 0);
// Free/release data
}
@@ -145,7 +141,7 @@ void tst_QArrayData::referenceCounting()
// Reference counting initialized to -1 (static read-only data)
QArrayData array = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, 0 };
- QCOMPARE(array.ref.atomic.load(), -1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), -1);
QVERIFY(array.ref.isStatic());
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
@@ -153,10 +149,10 @@ void tst_QArrayData::referenceCounting()
#endif
QVERIFY(array.ref.ref());
- QCOMPARE(array.ref.atomic.load(), -1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), -1);
QVERIFY(array.ref.deref());
- QCOMPARE(array.ref.atomic.load(), -1);
+ QCOMPARE(array.ref.atomic.loadRelaxed(), -1);
}
}
@@ -172,8 +168,8 @@ void tst_QArrayData::sharedNullEmpty()
QVERIFY(empty->ref.isStatic());
QVERIFY(empty->ref.isShared());
- QCOMPARE(null->ref.atomic.load(), -1);
- QCOMPARE(empty->ref.atomic.load(), -1);
+ QCOMPARE(null->ref.atomic.loadRelaxed(), -1);
+ QCOMPARE(empty->ref.atomic.loadRelaxed(), -1);
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
QVERIFY(null->ref.isSharable());
@@ -183,14 +179,14 @@ void tst_QArrayData::sharedNullEmpty()
QVERIFY(null->ref.ref());
QVERIFY(empty->ref.ref());
- QCOMPARE(null->ref.atomic.load(), -1);
- QCOMPARE(empty->ref.atomic.load(), -1);
+ QCOMPARE(null->ref.atomic.loadRelaxed(), -1);
+ QCOMPARE(empty->ref.atomic.loadRelaxed(), -1);
QVERIFY(null->ref.deref());
QVERIFY(empty->ref.deref());
- QCOMPARE(null->ref.atomic.load(), -1);
- QCOMPARE(empty->ref.atomic.load(), -1);
+ QCOMPARE(null->ref.atomic.loadRelaxed(), -1);
+ QCOMPARE(empty->ref.atomic.loadRelaxed(), -1);
QVERIFY(null != empty);
@@ -1618,9 +1614,7 @@ void tst_QArrayData::literals()
QCOMPARE(v.size(), size_t(11));
// v.capacity() is unspecified, for now
-#if defined(Q_COMPILER_VARIADIC_MACROS) && defined(Q_COMPILER_LAMBDA)
QVERIFY(v.isStatic());
-#endif
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
QVERIFY(v.isSharable());
@@ -1633,7 +1627,6 @@ void tst_QArrayData::literals()
}
}
-#if defined(Q_COMPILER_VARIADIC_MACROS) && defined(Q_COMPILER_LAMBDA)
// Variadic Q_ARRAY_LITERAL need to be available in the current configuration.
void tst_QArrayData::variadicLiterals()
{
@@ -1682,9 +1675,7 @@ void tst_QArrayData::variadicLiterals()
QCOMPARE(const_(v)[i], i);
}
}
-#endif
-#ifdef Q_COMPILER_RVALUE_REFS
// std::remove_reference is in C++11, but requires library support
template <class T> struct RemoveReference { typedef T Type; };
template <class T> struct RemoveReference<T &> { typedef T Type; };
@@ -1767,7 +1758,6 @@ void tst_QArrayData::rValueReferences()
QCOMPARE(v3.size(), size_t(1));
QCOMPARE(v3.front(), 42);
}
-#endif
void tst_QArrayData::grow()
{
diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
index 1ed41793dc..90dfcaef25 100644
--- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
+++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
@@ -138,9 +138,7 @@ private slots:
void reserveExtended();
void movablity_data();
void movablity();
-#if defined(Q_COMPILER_LAMBDA)
void literals();
-#endif
void toUpperLower_data();
void toUpperLower();
void isUpper();
@@ -1361,6 +1359,9 @@ void tst_QByteArray::toDouble_data()
QTest::newRow("trailing spaces") << QByteArray("1.2345 \n\r\t") << 1.2345 << true;
QTest::newRow("leading junk") << QByteArray("x1.2345") << 0.0 << false;
QTest::newRow("trailing junk") << QByteArray("1.2345x") << 0.0 << false;
+
+ QTest::newRow("raw, null plus junk") << QByteArray::fromRawData("1.2\0 junk", 9) << 0.0 << false;
+ QTest::newRow("raw, null-terminator not included") << QByteArray::fromRawData("2.3", 3) << 2.3 << true;
}
void tst_QByteArray::toDouble()
@@ -1934,7 +1935,7 @@ void tst_QByteArray::repeatedSignature() const
{
/* repated() should be a const member. */
const QByteArray string;
- string.repeated(3);
+ (void)string.repeated(3);
}
void tst_QByteArray::repeated() const
@@ -2126,7 +2127,7 @@ void tst_QByteArray::movablity()
{
QFETCH(QByteArray, array);
- QVERIFY(!QTypeInfo<QByteArray>::isStatic);
+ Q_STATIC_ASSERT(!QTypeInfo<QByteArray>::isStatic);
const int size = array.size();
const bool isEmpty = array.isEmpty();
@@ -2138,7 +2139,7 @@ void tst_QByteArray::movablity()
// we need only memory space not the instance
memSpace.~QByteArray();
// move array -> memSpace
- memcpy(&memSpace, &array, sizeof(QByteArray));
+ memcpy((void *)&memSpace, (const void *)&array, sizeof(QByteArray));
// reconstruct empty QByteArray
new (&array) QByteArray;
@@ -2148,8 +2149,8 @@ void tst_QByteArray::movablity()
QCOMPARE(memSpace.capacity(), capacity);
// try to not crash
- memSpace.toLower();
- memSpace.toUpper();
+ (void)memSpace.toLower();
+ (void)memSpace.toUpper();
memSpace.prepend('a');
memSpace.append("b", 1);
memSpace.squeeze();
@@ -2165,7 +2166,7 @@ void tst_QByteArray::movablity()
// move back memSpace -> array
array.~QByteArray();
- memcpy(&array, &memSpace, sizeof(QByteArray));
+ memcpy((void *)&array, (const void *)&memSpace, sizeof(QByteArray));
// reconstruct empty QByteArray
new (&memSpace) QByteArray;
@@ -2189,7 +2190,6 @@ void tst_QByteArray::movablity()
QVERIFY(true);
}
-#if defined(Q_COMPILER_LAMBDA)
// Only tested on c++0x compliant compiler or gcc
void tst_QByteArray::literals()
{
@@ -2210,7 +2210,6 @@ void tst_QByteArray::literals()
QVERIFY(str2.constData() == s);
QVERIFY(str2.data() != s);
}
-#endif
void tst_QByteArray::toUpperLower_data()
{
@@ -2242,28 +2241,28 @@ void tst_QByteArray::toUpperLower()
QCOMPARE(input.toLower(), lower);
QByteArray copy = input;
- QCOMPARE(qMove(copy).toUpper(), upper);
+ QCOMPARE(std::move(copy).toUpper(), upper);
copy = input;
copy.detach();
- QCOMPARE(qMove(copy).toUpper(), upper);
+ QCOMPARE(std::move(copy).toUpper(), upper);
copy = input;
- QCOMPARE(qMove(copy).toLower(), lower);
+ QCOMPARE(std::move(copy).toLower(), lower);
copy = input;
copy.detach();
- QCOMPARE(qMove(copy).toLower(), lower);
+ QCOMPARE(std::move(copy).toLower(), lower);
copy = lower;
- QCOMPARE(qMove(copy).toLower(), lower);
+ QCOMPARE(std::move(copy).toLower(), lower);
copy = lower;
copy.detach();
- QCOMPARE(qMove(copy).toLower(), lower);
+ QCOMPARE(std::move(copy).toLower(), lower);
copy = upper;
- QCOMPARE(qMove(copy).toUpper(), upper);
+ QCOMPARE(std::move(copy).toUpper(), upper);
copy = upper;
copy.detach();
- QCOMPARE(qMove(copy).toUpper(), upper);
+ QCOMPARE(std::move(copy).toUpper(), upper);
}
void tst_QByteArray::isUpper()
diff --git a/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp b/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp
index 85b4c4bfb7..09ce41337e 100644
--- a/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp
+++ b/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp
@@ -49,6 +49,9 @@ private slots:
void operator_plus() const;
void operator_plus_data() const;
+ void indexOf_data() const;
+ void indexOf() const;
+
void initializerList() const;
};
@@ -191,22 +194,22 @@ void tst_QByteArrayList::operator_plus() const
{
QByteArrayList bal1 = lhs;
const QByteArrayList bal2 = rhs;
- QCOMPARE(qMove(bal1) + bal2, expectedResult);
+ QCOMPARE(std::move(bal1) + bal2, expectedResult);
}
{
QList<QByteArray> lba1 = lhs;
const QByteArrayList bal2 = rhs;
- QCOMPARE(qMove(lba1) + bal2, expectedResult);
+ QCOMPARE(std::move(lba1) + bal2, expectedResult);
}
{
QByteArrayList bal1 = lhs;
const QList<QByteArray> lba2 = rhs;
- QCOMPARE(qMove(bal1) + lba2, expectedResult);
+ QCOMPARE(std::move(bal1) + lba2, expectedResult);
}
{
QList<QByteArray> lba1 = lhs;
const QList<QByteArray> lba2 = rhs;
- QCOMPARE(qMove(lba1) + lba2, QList<QByteArray>(expectedResult)); // check we don't mess with old code
+ QCOMPARE(std::move(lba1) + lba2, QList<QByteArray>(expectedResult)); // check we don't mess with old code
}
// operator += for const lvalues
@@ -229,7 +232,7 @@ void tst_QByteArrayList::operator_plus() const
QByteArrayList t1 = lhs;
QByteArrayList t2 = rhs;
- QCOMPARE(qMove(t1) + t2, expectedResult);
+ QCOMPARE(std::move(t1) + t2, expectedResult);
}
void tst_QByteArrayList::operator_plus_data() const
@@ -259,9 +262,31 @@ void tst_QByteArrayList::operator_plus_data() const
<< ( QByteArrayList() << "a" << "" << "c" );
}
+void tst_QByteArrayList::indexOf_data() const
+{
+ QTest::addColumn<QByteArrayList>("list");
+ QTest::addColumn<QByteArray>("item");
+ QTest::addColumn<int>("expectedResult");
+
+ QTest::newRow("empty") << QByteArrayList() << QByteArray("a") << -1;
+ QTest::newRow("found_1") << ( QByteArrayList() << "a" ) << QByteArray("a") << 0;
+ QTest::newRow("not_found_1") << ( QByteArrayList() << "a" ) << QByteArray("b") << -1;
+ QTest::newRow("found_2") << ( QByteArrayList() << "hello" << "world" ) << QByteArray("world") << 1;
+ QTest::newRow("returns_first") << ( QByteArrayList() << "hello" << "world" << "hello" << "again" ) << QByteArray("hello") << 0;
+}
+
+void tst_QByteArrayList::indexOf() const
+{
+ QFETCH(QByteArrayList, list);
+ QFETCH(QByteArray, item);
+ QFETCH(int, expectedResult);
+
+ QCOMPARE(list.indexOf(item), expectedResult);
+ QCOMPARE(list.indexOf(item.constData()), expectedResult);
+}
+
void tst_QByteArrayList::initializerList() const
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
// constructor
QByteArrayList v1 = {QByteArray("hello"),"world",QByteArray("plop")};
QCOMPARE(v1, (QByteArrayList() << "hello" << "world" << "plop"));
@@ -270,9 +295,6 @@ void tst_QByteArrayList::initializerList() const
QByteArrayList v2;
v2 = {QByteArray("hello"),"world",QByteArray("plop")};
QCOMPARE(v2, v1);
-#else
- QSKIP("This test requires C++11 initializer_list support in the compiler.");
-#endif
}
QTEST_APPLESS_MAIN(tst_QByteArrayList)
diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp
index 72f88a235d..2ae9c6e159 100644
--- a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp
+++ b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp
@@ -47,7 +47,6 @@ private Q_SLOTS:
void state();
};
-#ifdef Q_COMPILER_RVALUE_REFS
static bool dpointer_is_null(QCollator &c)
{
char mem[sizeof c];
@@ -58,11 +57,9 @@ static bool dpointer_is_null(QCollator &c)
return false;
return true;
}
-#endif
void tst_QCollator::moveSemantics()
{
-#ifdef Q_COMPILER_RVALUE_REFS
const QLocale de_AT(QLocale::German, QLocale::Austria);
QCollator c1(de_AT);
@@ -78,9 +75,6 @@ void tst_QCollator::moveSemantics()
c1 = std::move(c2);
QCOMPARE(c1.locale(), de_AT);
QVERIFY(dpointer_is_null(c2));
-#else
- QSKIP("The compiler is not in C++11 mode or does not support move semantics.");
-#endif
}
diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
index 62c29229e1..1e87c76d2f 100644
--- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
+++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
@@ -44,6 +44,7 @@ private slots:
// In-process tests
void testInvalidOptions();
+ void testDuplicateOption();
void testPositionalArguments();
void testBooleanOption_data();
void testBooleanOption();
@@ -74,6 +75,9 @@ private slots:
void testHelpOption_data();
void testHelpOption();
void testQuoteEscaping();
+ void testUnknownOption();
+ void testHelpAll_data();
+ void testHelpAll();
};
static char *empty_argv[] = { 0 };
@@ -103,6 +107,15 @@ void tst_QCommandLineParser::testInvalidOptions()
QVERIFY(!parser.addOption(QCommandLineOption(QStringLiteral("-v"), QStringLiteral("Displays version information."))));
}
+void tst_QCommandLineParser::testDuplicateOption()
+{
+ QCoreApplication app(empty_argc, empty_argv);
+ QCommandLineParser parser;
+ QVERIFY(parser.addOption(QCommandLineOption(QStringLiteral("h"), QStringLiteral("Hostname."), QStringLiteral("hostname"))));
+ QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: already having an option named \"h\"");
+ parser.addHelpOption();
+}
+
void tst_QCommandLineParser::testPositionalArguments()
{
QCoreApplication app(empty_argc, empty_argv);
@@ -488,7 +501,7 @@ void tst_QCommandLineParser::testSingleDashWordOptionModes()
void tst_QCommandLineParser::testCpp11StyleInitialization()
{
-#if defined(Q_COMPILER_INITIALIZER_LISTS) && defined(Q_COMPILER_UNIFORM_INIT)
+#if defined(Q_COMPILER_UNIFORM_INIT)
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
@@ -531,7 +544,8 @@ void tst_QCommandLineParser::testVersionOption()
static const char expectedOptionsHelp[] =
"Options:\n"
- " -h, --help Displays this help.\n"
+ " -h, --help Displays help on commandline options.\n"
+ " --help-all Displays help including Qt specific options.\n"
" -v, --version Displays version information.\n"
" --load <url> Load file from URL.\n"
" -o, --output <file> Set output file.\n"
@@ -565,8 +579,8 @@ void tst_QCommandLineParser::testHelpOption_data()
" parsingMode The parsing mode to test.\n"
" command The command to execute.\n");
#ifdef Q_OS_WIN
- expectedOutput.replace(" -h, --help Displays this help.\n",
- " -?, -h, --help Displays this help.\n");
+ expectedOutput.replace(" -h, --help Displays help on commandline options.\n",
+ " -?, -h, --help Displays help on commandline options.\n");
expectedOutput.replace("testhelper/", "testhelper\\");
#endif
@@ -614,8 +628,8 @@ void tst_QCommandLineParser::testHelpOption()
"Arguments:\n"
" resize Resize the object to a new size.\n";
#ifdef Q_OS_WIN
- expectedResizeHelp.replace(" -h, --help Displays this help.\n",
- " -?, -h, --help Displays this help.\n");
+ expectedResizeHelp.replace(" -h, --help Displays help on commandline options.\n",
+ " -?, -h, --help Displays help on commandline options.\n");
expectedResizeHelp.replace("testhelper/", "testhelper\\");
#endif
QCOMPARE(output, QString(expectedResizeHelp));
@@ -648,6 +662,81 @@ void tst_QCommandLineParser::testQuoteEscaping()
#endif // QT_CONFIG(process)
}
+void tst_QCommandLineParser::testUnknownOption()
+{
+#if !QT_CONFIG(process)
+ QSKIP("This test requires QProcess support");
+#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+ QSKIP("Deploying executable applications to file system on Android not supported.");
+#else
+ QCoreApplication app(empty_argc, empty_argv);
+ QProcess process;
+ process.start("testhelper/qcommandlineparser_test_helper", QStringList() <<
+ QString::number(QCommandLineParser::ParseAsLongOptions) <<
+ "-unknown-option");
+ QVERIFY(process.waitForFinished(5000));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ process.setReadChannel(QProcess::StandardError);
+ QString output = process.readAll();
+ QVERIFY2(output.contains("qcommandlineparser_test_helper"), qPrintable(output)); // separate in case of .exe extension
+ QVERIFY2(output.contains(": Unknown option 'unknown-option'"), qPrintable(output));
+#endif // QT_CONFIG(process)
+}
+
+void tst_QCommandLineParser::testHelpAll_data()
+{
+ QTest::addColumn<QCommandLineParser::SingleDashWordOptionMode>("parsingMode");
+ QTest::addColumn<QString>("expectedHelpOutput");
+
+ QString expectedOutput = QString::fromLatin1(
+ "Usage: testhelper/qcommandlineparser_test_helper [options] parsingMode command\n"
+ "Test helper\n"
+ "\n")
+ + QString::fromLatin1(expectedOptionsHelp) +
+ QString::fromLatin1(
+ " --qmljsdebugger <value> Activates the QML/JS debugger with a specified\n"
+ " port. The value must be of format\n"
+ " port:1234[,block]. \"block\" makes the application\n"
+ " wait for a connection.\n"
+ "\n"
+ "Arguments:\n"
+ " parsingMode The parsing mode to test.\n"
+ " command The command to execute.\n");
+#ifdef Q_OS_WIN
+ expectedOutput.replace(" -h, --help Displays help on commandline options.\n",
+ " -?, -h, --help Displays help on commandline options.\n");
+ expectedOutput.replace("testhelper/", "testhelper\\");
+#endif
+
+ QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << expectedOutput;
+ QTest::newRow("long") << QCommandLineParser::ParseAsLongOptions << expectedOutput;
+}
+
+void tst_QCommandLineParser::testHelpAll()
+{
+#if !QT_CONFIG(process)
+ QSKIP("This test requires QProcess support");
+#else
+#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+ QSKIP("Deploying executable applications to file system on Android not supported.");
+#endif
+
+ QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode);
+ QFETCH(QString, expectedHelpOutput);
+ QCoreApplication app(empty_argc, empty_argv);
+ QProcess process;
+ process.start("testhelper/qcommandlineparser_test_helper", QStringList() << QString::number(parsingMode) << "--help-all");
+ QVERIFY(process.waitForFinished(5000));
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QString output = process.readAll();
+#ifdef Q_OS_WIN
+ output.replace(QStringLiteral("\r\n"), QStringLiteral("\n"));
+#endif
+ QCOMPARE(output.split('\n'), expectedHelpOutput.split('\n')); // easier to debug than the next line, on failure
+ QCOMPARE(output, expectedHelpOutput);
+#endif // QT_CONFIG(process)
+}
+
QTEST_APPLESS_MAIN(tst_QCommandLineParser)
#include "tst_qcommandlineparser.moc"
diff --git a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
index 31a5f93822..f305d63d46 100644
--- a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
+++ b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
@@ -68,7 +68,7 @@ void tst_QContiguousCache::assignment()
// copy:
cc1 = cc2;
// move:
- cc1 = qMove(cc2);
+ cc1 = std::move(cc2);
}
void tst_QContiguousCache::empty()
@@ -244,7 +244,7 @@ public:
return *this;
}
- int refCount() const { return d->ref.load(); }
+ int refCount() const { return d->ref.loadRelaxed(); }
private:
RefCountingClassData *d;
};
diff --git a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
index 0196dd2d23..3af6132695 100644
--- a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
+++ b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
@@ -30,9 +30,7 @@
#include <qeasingcurve.h>
-#ifdef Q_COMPILER_RVALUE_REFS // cpp11() slot
-# include <utility> // for std::move()
-#endif
+#include <utility> // for std::move()
class tst_QEasingCurve : public QObject
{
@@ -55,6 +53,8 @@ private slots:
void testCbrtFloat();
void cpp11();
void quadraticEquation();
+ void streamInOut_data();
+ void streamInOut();
};
void tst_QEasingCurve::type()
@@ -792,7 +792,6 @@ void tst_QEasingCurve::testCbrtFloat()
void tst_QEasingCurve::cpp11()
{
-#ifdef Q_COMPILER_RVALUE_REFS
{
QEasingCurve ec( QEasingCurve::InOutBack );
QEasingCurve copy = std::move(ec); // move ctor
@@ -807,7 +806,6 @@ void tst_QEasingCurve::cpp11()
QCOMPARE( copy.type(), QEasingCurve::InOutBack );
QCOMPARE( ec.type(), type );
}
-#endif
}
void tst_QEasingCurve::quadraticEquation() {
@@ -879,5 +877,36 @@ void tst_QEasingCurve::quadraticEquation() {
}
}
+void tst_QEasingCurve::streamInOut_data()
+{
+ QTest::addColumn<int>("version");
+ QTest::addColumn<bool>("equality");
+
+ QTest::newRow("5.11") << int(QDataStream::Qt_5_11) << false;
+ QTest::newRow("5.13") << int(QDataStream::Qt_5_13) << true;
+}
+
+void tst_QEasingCurve::streamInOut()
+{
+ QFETCH(int, version);
+ QFETCH(bool, equality);
+
+ QEasingCurve orig;
+ orig.addCubicBezierSegment(QPointF(0.43, 0.0025), QPointF(0.38, 0.51), QPointF(0.57, 0.99));
+
+ QEasingCurve copy;
+
+ QByteArray data;
+ QDataStream dsw(&data,QIODevice::WriteOnly);
+ QDataStream dsr(&data,QIODevice::ReadOnly);
+
+ dsw.setVersion(version);
+ dsr.setVersion(version);
+ dsw << orig;
+ dsr >> copy;
+
+ QCOMPARE(copy == orig, equality);
+}
+
QTEST_MAIN(tst_QEasingCurve)
#include "tst_qeasingcurve.moc"
diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
index 0015efacfa..d70d488e96 100644
--- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp
+++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
@@ -1480,7 +1480,6 @@ void tst_QHash::twoArguments_qHash()
void tst_QHash::initializerList()
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QHash<int, QString> hash = {{1, "bar"}, {1, "hello"}, {2, "initializer_list"}};
QCOMPARE(hash.count(), 2);
QCOMPARE(hash[1], QString("hello"));
@@ -1507,9 +1506,6 @@ void tst_QHash::initializerList()
QMultiHash<int, float> emptyPairs2{{}, {}};
QVERIFY(!emptyPairs2.isEmpty());
-#else
- QSKIP("Compiler doesn't support initializer lists");
-#endif
}
void tst_QHash::eraseValidIteratorOnSharedHash()
diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
index 124e3cdf00..f76f3aa0c6 100644
--- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
+++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
@@ -34,6 +34,8 @@
#include <sstream>
#include <algorithm>
+#include <unordered_set>
+
class tst_QHashFunctions : public QObject
{
Q_OBJECT
@@ -59,6 +61,8 @@ private Q_SLOTS:
void range();
void rangeCommutative();
+ void stdHash();
+
void setGlobalQHashSeed();
};
@@ -281,6 +285,38 @@ void tst_QHashFunctions::rangeCommutative()
(void)qHashRangeCommutative(hashables, hashables + numHashables, seed);
}
+void tst_QHashFunctions::stdHash()
+{
+ {
+ std::unordered_set<QString> s = {QStringLiteral("Hello"), QStringLiteral("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QStringLiteral("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+ {
+ std::unordered_set<QStringView> s = {QStringLiteral("Hello"), QStringLiteral("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QStringLiteral("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+ {
+ std::unordered_set<QLatin1String> s = {QLatin1String("Hello"), QLatin1String("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QLatin1String("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+ {
+ std::unordered_set<QByteArray> s = {QByteArrayLiteral("Hello"), QByteArrayLiteral("World")};
+ QCOMPARE(s.size(), 2UL);
+ s.insert(QByteArray("Hello"));
+ QCOMPARE(s.size(), 2UL);
+ }
+
+}
+
void tst_QHashFunctions::setGlobalQHashSeed()
{
// Setter works as advertised
diff --git a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp b/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
index dcfb0aa042..cf46159251 100644
--- a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
+++ b/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
@@ -45,6 +45,7 @@ class tst_QLatin1String : public QObject
private Q_SLOTS:
void at();
+ void arg() const;
void midLeftRight();
void nullString();
void emptyString();
@@ -63,6 +64,47 @@ void tst_QLatin1String::at()
QCOMPARE(l1[l1.size() - 1], QLatin1Char('d'));
}
+void tst_QLatin1String::arg() const
+{
+#define CHECK1(pattern, arg1, expected) \
+ do { \
+ auto p = QLatin1String(pattern); \
+ QCOMPARE(p.arg(QLatin1String(arg1)), expected); \
+ QCOMPARE(p.arg(QStringViewLiteral(arg1)), expected); \
+ QCOMPARE(p.arg(QStringLiteral(arg1)), expected); \
+ QCOMPARE(p.arg(QString(QLatin1String(arg1))), expected); \
+ } while (false) \
+ /*end*/
+#define CHECK2(pattern, arg1, arg2, expected) \
+ do { \
+ auto p = QLatin1String(pattern); \
+ QCOMPARE(p.arg(QLatin1String(arg1), QLatin1String(arg2)), expected); \
+ QCOMPARE(p.arg(QStringViewLiteral(arg1), QLatin1String(arg2)), expected); \
+ QCOMPARE(p.arg(QLatin1String(arg1), QStringViewLiteral(arg2)), expected); \
+ QCOMPARE(p.arg(QStringViewLiteral(arg1), QStringViewLiteral(arg2)), expected); \
+ } while (false) \
+ /*end*/
+
+ CHECK1("", "World", "");
+ CHECK1("%1", "World", "World");
+ CHECK1("!%1?", "World", "!World?");
+ CHECK1("%1%1", "World", "WorldWorld");
+ CHECK1("%1%2", "World", "World%2");
+ CHECK1("%2%1", "World", "%2World");
+
+ CHECK2("", "Hello", "World", "");
+ CHECK2("%1", "Hello", "World", "Hello");
+ CHECK2("!%1, %2?", "Hello", "World", "!Hello, World?");
+ CHECK2("%1%1", "Hello", "World", "HelloHello");
+ CHECK2("%1%2", "Hello", "World", "HelloWorld");
+ CHECK2("%2%1", "Hello", "World", "WorldHello");
+
+#undef CHECK2
+#undef CHECK1
+
+ QCOMPARE(QLatin1String(" %2 %2 %1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, u'C'), " \r \r c C ");
+}
+
void tst_QLatin1String::midLeftRight()
{
const QLatin1String l1("Hello World");
diff --git a/tests/auto/corelib/tools/qline/tst_qline.cpp b/tests/auto/corelib/tools/qline/tst_qline.cpp
index ae65d8f697..915a24a1f6 100644
--- a/tests/auto/corelib/tools/qline/tst_qline.cpp
+++ b/tests/auto/corelib/tools/qline/tst_qline.cpp
@@ -205,7 +205,7 @@ void tst_QLine::testIntersection()
QPointF ip;
- QLineF::IntersectType itype = a.intersect(b, &ip);
+ QLineF::IntersectionType itype = a.intersect(b, &ip);
QCOMPARE(int(itype), type);
if (type != QLineF::NoIntersection) {
diff --git a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp
index f17d6695f0..deb3b68c5c 100644
--- a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp
+++ b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp
@@ -1005,7 +1005,6 @@ void tst_QLinkedList::testSTLIteratorsComplex() const
void tst_QLinkedList::initializeList() const
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QLinkedList<int> v1 { 2, 3, 4 };
QCOMPARE(v1, QLinkedList<int>() << 2 << 3 << 4);
QCOMPARE(v1, (QLinkedList<int> { 2, 3, 4}));
@@ -1014,7 +1013,6 @@ void tst_QLinkedList::initializeList() const
QLinkedList<QLinkedList<int>> v3;
v3 << v1 << (QLinkedList<int>() << 1) << QLinkedList<int>() << v1;
QCOMPARE(v3, v2);
-#endif
}
diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
index b3f8130d27..5a485e88d2 100644
--- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp
+++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
@@ -364,12 +364,14 @@ private slots:
void takeLastOptimal() const;
void takeLastMovable() const;
void takeLastComplex() const;
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
void toSetOptimal() const;
void toSetMovable() const;
void toSetComplex() const;
void toStdListOptimal() const;
void toStdListMovable() const;
void toStdListComplex() const;
+#endif
void toVectorOptimal() const;
void toVectorMovable() const;
void toVectorComplex() const;
@@ -426,8 +428,10 @@ private:
template<typename T> void takeAt() const;
template<typename T> void takeFirst() const;
template<typename T> void takeLast() const;
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
template<typename T> void toSet() const;
template<typename T> void toStdList() const;
+#endif
template<typename T> void toVector() const;
template<typename T> void value() const;
@@ -1457,11 +1461,11 @@ void tst_QList::swap() const
list << T_FOO << T_BAR << T_BAZ;
// swap
- list.swap(0, 2);
+ list.swapItemsAt(0, 2);
QCOMPARE(list, QList<T>() << T_BAZ << T_BAR << T_FOO);
// swap again
- list.swap(1, 2);
+ list.swapItemsAt(1, 2);
QCOMPARE(list, QList<T>() << T_BAZ << T_FOO << T_BAR);
QList<T> list2;
@@ -1595,6 +1599,7 @@ void tst_QList::takeLastComplex() const
QCOMPARE(liveCount, Complex::getLiveCount());
}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
template<typename T>
void tst_QList::toSet() const
{
@@ -1669,6 +1674,7 @@ void tst_QList::toStdListComplex() const
toStdList<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
+#endif
template<typename T>
void tst_QList::toVector() const
@@ -1871,7 +1877,6 @@ void tst_QList::testSTLIteratorsComplex() const
void tst_QList::initializeList() const
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QList<int> v1{2,3,4};
QCOMPARE(v1, QList<int>() << 2 << 3 << 4);
QCOMPARE(v1, (QList<int>{2,3,4}));
@@ -1880,7 +1885,6 @@ void tst_QList::initializeList() const
QList<QList<int>> v3;
v3 << v1 << (QList<int>() << 1) << QList<int>() << v1;
QCOMPARE(v3, v2);
-#endif
}
template<typename T>
diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
index 230ae4d8aa..ec8f2fc047 100644
--- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
@@ -423,6 +423,7 @@ void tst_QLocale::defaulted_ctor()
}
QLocale::setDefault(QLocale(QLocale::C));
+ const QString empty;
TEST_CTOR("C", C, AnyCountry)
TEST_CTOR("bla", C, AnyCountry)
@@ -431,7 +432,7 @@ void tst_QLocale::defaulted_ctor()
TEST_CTOR("zz...", C, AnyCountry)
TEST_CTOR("", C, AnyCountry)
TEST_CTOR("en/", C, AnyCountry)
- TEST_CTOR(QString::null, C, AnyCountry)
+ TEST_CTOR(empty, C, AnyCountry)
TEST_CTOR("en", English, UnitedStates)
TEST_CTOR("en", English, UnitedStates)
TEST_CTOR("en.", English, UnitedStates)
@@ -2002,9 +2003,11 @@ static void setWinLocaleInfo(LCTYPE type, const QString &value)
# define LOCALE_SSHORTTIME 0x00000079
#endif
-class RestoreLocaleHelper {
+class RestoreLocaleHelper
+{
public:
- RestoreLocaleHelper() {
+ RestoreLocaleHelper()
+ {
m_decimal = getWinLocaleInfo(LOCALE_SDECIMAL);
m_thousand = getWinLocaleInfo(LOCALE_STHOUSAND);
m_sdate = getWinLocaleInfo(LOCALE_SSHORTDATE);
@@ -2012,7 +2015,8 @@ public:
m_time = getWinLocaleInfo(LOCALE_SSHORTTIME);
}
- ~RestoreLocaleHelper() {
+ ~RestoreLocaleHelper()
+ {
// restore these, or the user will get a surprise
setWinLocaleInfo(LOCALE_SDECIMAL, m_decimal);
setWinLocaleInfo(LOCALE_STHOUSAND, m_thousand);
@@ -2020,12 +2024,10 @@ public:
setWinLocaleInfo(LOCALE_SLONGDATE, m_ldate);
setWinLocaleInfo(LOCALE_SSHORTTIME, m_time);
- // make sure QLocale::system() gets updated
- QLocalePrivate::updateSystemPrivate();
+ QSystemLocale dummy; // to provoke a refresh of the system locale
}
QString m_decimal, m_thousand, m_sdate, m_ldate, m_time;
-
};
void tst_QLocale::windowsDefaultLocale()
@@ -2041,8 +2043,7 @@ void tst_QLocale::windowsDefaultLocale()
const QString shortTimeFormat = QStringLiteral("h^m^s");
setWinLocaleInfo(LOCALE_SSHORTTIME, shortTimeFormat);
- // make sure QLocale::system() gets updated
- QLocalePrivate::updateSystemPrivate();
+ QSystemLocale dummy; // to provoke a refresh of the system locale
QLocale locale = QLocale::system();
// make sure we are seeing the system's format strings
@@ -2783,9 +2784,11 @@ void tst_QLocale::textDirection_data()
case QLocale::Sabaean:
case QLocale::Samaritan:
case QLocale::Sindhi:
+ case QLocale::SouthernKurdish:
case QLocale::Syriac:
case QLocale::Uighur:
case QLocale::Urdu:
+ case QLocale::WesternBalochi:
case QLocale::Yiddish:
// false if there is no locale data for language:
rightToLeft = (QLocale(QLocale::Language(language)).language()
diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp
index b39444e76f..d66fd28779 100644
--- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp
+++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp
@@ -1319,7 +1319,6 @@ void tst_QMap::checkMostLeftNode()
void tst_QMap::initializerList()
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QMap<int, QString> map = {{1, "bar"}, {1, "hello"}, {2, "initializer_list"}};
QCOMPARE(map.count(), 2);
QCOMPARE(map[1], QString("hello"));
@@ -1346,9 +1345,6 @@ void tst_QMap::initializerList()
QMultiMap<float, float> emptyPairs2{{}, {}};
QVERIFY(!emptyPairs2.isEmpty());
-#else
- QSKIP("Compiler doesn't support initializer lists");
-#endif
}
void tst_QMap::testInsertWithHint()
diff --git a/tests/auto/corelib/tools/qoffsetstringarray/qoffsetstringarray.pro b/tests/auto/corelib/tools/qoffsetstringarray/qoffsetstringarray.pro
new file mode 100644
index 0000000000..c8e6a8e05a
--- /dev/null
+++ b/tests/auto/corelib/tools/qoffsetstringarray/qoffsetstringarray.pro
@@ -0,0 +1,6 @@
+CONFIG += testcase
+TARGET = tst_qoffsetstringarray
+QT = core testlib core-private
+CONFIG += c++11
+CONFIG += strict_c++
+SOURCES = $$PWD/tst_qoffsetstringarray.cpp
diff --git a/tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp b/tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp
new file mode 100644
index 0000000000..dfa0450b18
--- /dev/null
+++ b/tests/auto/corelib/tools/qoffsetstringarray/tst_qoffsetstringarray.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <private/qoffsetstringarray_p.h>
+
+
+class tst_QOffsetStringArray : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void init();
+ void access();
+};
+
+
+constexpr const auto messages = qOffsetStringArray(
+ "level - 0",
+ "level - 1",
+ "level - 2",
+ "level - 3",
+ "level - 4",
+ ""
+);
+
+constexpr const auto messages257 = qOffsetStringArray(
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "end"
+);
+
+constexpr const auto messagesBigOffsets = qOffsetStringArray(
+ " 10 20 30 40 50 60 70 80 90",
+ " 10 20 30 40 50 60 70 80 90",
+ " 10 20 30 40 50 60 70 80 90",
+ " 10 20 30 40 50 60 70 80 90"
+);
+
+void tst_QOffsetStringArray::init()
+{
+ static_assert(messages.sizeString == 51, "message.sizeString");
+ static_assert(messages.sizeOffsets == 6, "message.sizeOffsets");
+ static_assert(std::is_same<decltype(messages)::Type, quint8>::value, "messages::Type != quint8");
+
+ static_assert(messages257.sizeOffsets == 257, "messages257.sizeOffsets");
+ static_assert(messages257.sizeString == 260, "messages257.sizeString");
+ static_assert(std::is_same<decltype(messages257)::Type, quint16>::value,
+ "messages257::Type != quint16");
+
+ static_assert(messagesBigOffsets.sizeOffsets == 4, "messagesBigOffsets.sizeOffsets");
+ static_assert(messagesBigOffsets.sizeString == 364, "messagesBigOffsets.sizeString");
+ static_assert(std::is_same<decltype(messagesBigOffsets)::Type, quint16>::value,
+ "messagesBigOffsets::Type != quint16");
+}
+
+void tst_QOffsetStringArray::access()
+{
+ QCOMPARE(messages[0], "level - 0");
+ QCOMPARE(messages[1], "level - 1");
+ QCOMPARE(messages[2], "level - 2");
+ QCOMPARE(messages[3], "level - 3");
+ QCOMPARE(messages[4], "level - 4");
+ QCOMPARE(messages[5], "");
+ QCOMPARE(messages[6], "");
+}
+
+
+QTEST_APPLESS_MAIN(tst_QOffsetStringArray)
+#include "tst_qoffsetstringarray.moc"
diff --git a/tests/auto/corelib/tools/qpair/qpair.pro b/tests/auto/corelib/tools/qpair/qpair.pro
index 659be887d3..d684a24a57 100644
--- a/tests/auto/corelib/tools/qpair/qpair.pro
+++ b/tests/auto/corelib/tools/qpair/qpair.pro
@@ -2,3 +2,6 @@ CONFIG += testcase
TARGET = tst_qpair
QT = core testlib
SOURCES = tst_qpair.cpp
+
+# Force C++17 if available (needed due to Q_COMPILER_DEDUCTION_GUIDES)
+contains(QT_CONFIG, c++1z): CONFIG += c++1z
diff --git a/tests/auto/corelib/tools/qpair/tst_qpair.cpp b/tests/auto/corelib/tools/qpair/tst_qpair.cpp
index 1d5f7536c8..3c972329bc 100644
--- a/tests/auto/corelib/tools/qpair/tst_qpair.cpp
+++ b/tests/auto/corelib/tools/qpair/tst_qpair.cpp
@@ -39,10 +39,11 @@ private Q_SLOTS:
void testConstexpr();
void testConversions();
void taskQTBUG_48780_pairContainingCArray();
+ void testDeducationRules();
};
-class C { char _[4]; };
-class M { char _[4]; };
+class C { C() {} char _[4]; };
+class M { M() {} char _[4]; };
class P { char _[4]; };
QT_BEGIN_NAMESPACE
@@ -202,5 +203,30 @@ void tst_QPair::taskQTBUG_48780_pairContainingCArray()
Q_UNUSED(pair);
}
+void tst_QPair::testDeducationRules()
+{
+#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
+ QPair p1{1, 2};
+ static_assert(std::is_same<decltype(p1)::first_type, decltype(1)>::value);
+ static_assert(std::is_same<decltype(p1)::second_type, decltype(2)>::value);
+ QCOMPARE(p1.first, 1);
+ QCOMPARE(p1.second, 2);
+
+ QPair p2{QString("string"), 2};
+ static_assert(std::is_same<decltype(p2)::first_type, QString>::value);
+ static_assert(std::is_same<decltype(p2)::second_type, decltype(2)>::value);
+ QCOMPARE(p2.first, "string");
+ QCOMPARE(p2.second, 2);
+
+ QPair p3(p2);
+ static_assert(std::is_same<decltype(p3)::first_type, decltype(p2)::first_type>::value);
+ static_assert(std::is_same<decltype(p3)::second_type, decltype(p2)::second_type>::value);
+ QCOMPARE(p3.first, "string");
+ QCOMPARE(p3.second, 2);
+#else
+ QSKIP("Unsupported");
+#endif
+}
+
QTEST_APPLESS_MAIN(tst_QPair)
#include "tst_qpair.moc"
diff --git a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
index b943b04e23..ea94cc2999 100644
--- a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
+++ b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
@@ -327,7 +327,7 @@ struct RefCounted
~RefCounted()
{
- QVERIFY( ref.load() == 0 );
+ QVERIFY( ref.loadRelaxed() == 0 );
instanceCount.deref();
}
@@ -369,13 +369,13 @@ void scopedPointerComparisonTest(const A1 &a1, const A2 &a2, const B &b)
void tst_QScopedPointer::comparison()
{
- QCOMPARE( RefCounted::instanceCount.load(), 0 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 0 );
{
RefCounted *a = new RefCounted;
RefCounted *b = new RefCounted;
- QCOMPARE( RefCounted::instanceCount.load(), 2 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 2 );
QScopedPointer<RefCounted> pa1(a);
QScopedPointer<RefCounted> pa2(a);
@@ -387,16 +387,16 @@ void tst_QScopedPointer::comparison()
pa2.take();
- QCOMPARE( RefCounted::instanceCount.load(), 2 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 2 );
}
- QCOMPARE( RefCounted::instanceCount.load(), 0 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 0 );
{
RefCounted *a = new RefCounted[42];
RefCounted *b = new RefCounted[43];
- QCOMPARE( RefCounted::instanceCount.load(), 85 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 85 );
QScopedArrayPointer<RefCounted> pa1(a);
QScopedArrayPointer<RefCounted> pa2(a);
@@ -406,10 +406,10 @@ void tst_QScopedPointer::comparison()
pa2.take();
- QCOMPARE( RefCounted::instanceCount.load(), 85 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 85 );
}
- QCOMPARE( RefCounted::instanceCount.load(), 0 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 0 );
{
// QScopedSharedPointer is an internal helper class -- it is unsupported!
@@ -417,42 +417,42 @@ void tst_QScopedPointer::comparison()
RefCounted *a = new RefCounted;
RefCounted *b = new RefCounted;
- QCOMPARE( RefCounted::instanceCount.load(), 2 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 2 );
QSharedDataPointer<RefCounted> pa1(a);
QSharedDataPointer<RefCounted> pa2(a);
QSharedDataPointer<RefCounted> pb(b);
- QCOMPARE( a->ref.load(), 2 );
- QCOMPARE( b->ref.load(), 1 );
- QCOMPARE( RefCounted::instanceCount.load(), 2 );
+ QCOMPARE( a->ref.loadRelaxed(), 2 );
+ QCOMPARE( b->ref.loadRelaxed(), 1 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 2 );
scopedPointerComparisonTest(pa1, pa2, pb);
- QCOMPARE( RefCounted::instanceCount.load(), 2 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 2 );
}
- QCOMPARE( RefCounted::instanceCount.load(), 0 );
+ QCOMPARE( RefCounted::instanceCount.loadRelaxed(), 0 );
}
void tst_QScopedPointer::array()
{
- int instCount = RefCounted::instanceCount.load();
+ int instCount = RefCounted::instanceCount.loadRelaxed();
{
QScopedArrayPointer<RefCounted> array;
array.reset(new RefCounted[42]);
- QCOMPARE(instCount + 42, RefCounted::instanceCount.load());
+ QCOMPARE(instCount + 42, RefCounted::instanceCount.loadRelaxed());
}
- QCOMPARE(instCount, RefCounted::instanceCount.load());
+ QCOMPARE(instCount, RefCounted::instanceCount.loadRelaxed());
{
QScopedArrayPointer<RefCounted> array(new RefCounted[42]);
- QCOMPARE(instCount + 42, RefCounted::instanceCount.load());
+ QCOMPARE(instCount + 42, RefCounted::instanceCount.loadRelaxed());
array.reset(new RefCounted[28]);
- QCOMPARE(instCount + 28, RefCounted::instanceCount.load());
+ QCOMPARE(instCount + 28, RefCounted::instanceCount.loadRelaxed());
array.reset(0);
- QCOMPARE(instCount, RefCounted::instanceCount.load());
+ QCOMPARE(instCount, RefCounted::instanceCount.loadRelaxed());
}
- QCOMPARE(instCount, RefCounted::instanceCount.load());
+ QCOMPARE(instCount, RefCounted::instanceCount.loadRelaxed());
}
diff --git a/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp b/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp
index 656dd6a6e3..9b607db608 100644
--- a/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp
+++ b/tests/auto/corelib/tools/qscopedvaluerollback/tst_qscopedvaluerollback.cpp
@@ -46,6 +46,7 @@ private Q_SLOTS:
void rollbackToPreviousCommit();
void exceptions();
void earlyExitScope();
+ void moveOnly();
private:
void earlyExitScope_helper(int exitpoint, int &member);
};
@@ -190,5 +191,17 @@ void tst_QScopedValueRollback::earlyExitScope_helper(int exitpoint, int& member)
r.commit();
}
+void tst_QScopedValueRollback::moveOnly()
+{
+ std::unique_ptr<int> uniquePtr;
+ std::unique_ptr<int> newVal(new int(5));
+ QVERIFY(!uniquePtr);
+ {
+ QScopedValueRollback<std::unique_ptr<int>> r(uniquePtr, std::move(newVal));
+ QVERIFY(uniquePtr);
+ }
+ QVERIFY(!uniquePtr);
+}
+
QTEST_MAIN(tst_QScopedValueRollback)
#include "tst_qscopedvaluerollback.moc"
diff --git a/tests/auto/corelib/tools/qset/tst_qset.cpp b/tests/auto/corelib/tools/qset/tst_qset.cpp
index 0b60350380..31b4c0449e 100644
--- a/tests/auto/corelib/tools/qset/tst_qset.cpp
+++ b/tests/auto/corelib/tools/qset/tst_qset.cpp
@@ -955,7 +955,6 @@ void tst_QSet::makeSureTheComfortFunctionsCompile()
void tst_QSet::initializerList()
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QSet<int> set = {1, 1, 2, 3, 4, 5};
QCOMPARE(set.count(), 5);
QVERIFY(set.contains(1));
@@ -976,9 +975,6 @@ void tst_QSet::initializerList()
QSet<int> set3{{}, {}, {}};
QVERIFY(!set3.isEmpty());
-#else
- QSKIP("Compiler doesn't support initializer lists");
-#endif
}
void tst_QSet::qhash()
@@ -1011,15 +1007,7 @@ void tst_QSet::qhash()
// check that sets of sets work:
//
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QSet<QSet<int> > intSetSet = { { 0, 1, 2 }, { 0, 1 }, { 1, 2 } };
-#else
- QSet<QSet<int> > intSetSet;
- QSet<int> intSet01, intSet12;
- intSet01 << 0 << 1;
- intSet12 << 1 << 2;
- intSetSet << intSet01 << intSet12 << (intSet01|intSet12);
-#endif
QCOMPARE(intSetSet.size(), 3);
}
}
diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
index ade9c5e754..187b73eeec 100644
--- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
+++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
@@ -40,6 +40,7 @@
#include "nontracked.h"
#include "wrapper.h"
+#include <memory>
#include <stdlib.h>
#include <time.h>
@@ -78,6 +79,7 @@ private slots:
void sharedPointerFromQObjectWithWeak();
void weakQObjectFromSharedPointer();
void objectCast();
+ void objectCastStdSharedPtr();
void differentPointers();
void virtualBaseDifferentPointers();
#ifndef QTEST_NO_RTTI
@@ -89,9 +91,7 @@ private slots:
#endif
void constCorrectness();
void customDeleter();
-#ifdef Q_COMPILER_LAMBDA
void lambdaCustomDeleter();
-#endif
void creating();
void creatingCvQualified();
void creatingVariadic();
@@ -226,13 +226,17 @@ struct NoDefaultConstructorConstRef2
NoDefaultConstructorConstRef2(const QByteArray &ba, int i = 42) : str(QString::fromLatin1(ba)), i(i) {}
};
-#ifdef Q_COMPILER_RVALUE_REFS
struct NoDefaultConstructorRRef1
{
int &i;
NoDefaultConstructorRRef1(int &&i) : i(i) {}
};
-#endif
+
+struct NoDefaultConstructorRRef2
+{
+ std::unique_ptr<int> i;
+ NoDefaultConstructorRRef2(std::unique_ptr<int> &&i) : i(std::move(i)) {}
+};
void tst_QSharedPointer::basics_data()
{
@@ -290,8 +294,8 @@ void tst_QSharedPointer::basics()
QVERIFY(! (ptr == otherData));
QVERIFY(! (otherData == ptr));
}
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1);
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
{
// create another object:
@@ -303,8 +307,8 @@ void tst_QSharedPointer::basics()
// otherData is deleted here
}
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1);
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
{
// create a copy:
@@ -321,8 +325,8 @@ void tst_QSharedPointer::basics()
QCOMPARE(copy.get(), aData);
QVERIFY(copy == aData);
}
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1);
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
{
// create a weak reference:
@@ -354,8 +358,8 @@ void tst_QSharedPointer::basics()
QCOMPARE(strong.data(), aData);
QCOMPARE(strong.get(), aData);
}
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1);
- QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
+ QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
// aData is deleted here
}
@@ -501,7 +505,6 @@ void tst_QSharedPointer::swap()
void tst_QSharedPointer::moveSemantics()
{
-#ifdef Q_COMPILER_RVALUE_REFS
QSharedPointer<int> p1, p2(new int(42)), control = p2;
QVERIFY(p1 != control);
QVERIFY(p1.isNull());
@@ -554,9 +557,6 @@ void tst_QSharedPointer::moveSemantics()
QVERIFY(w1.isNull());
QVERIFY(w2.isNull());
QVERIFY(w3.isNull());
-#else
- QSKIP("This test requires C++11 rvalue/move semantics support in the compiler.");
-#endif
}
void tst_QSharedPointer::useOfForwardDeclared()
@@ -573,10 +573,10 @@ void tst_QSharedPointer::useOfForwardDeclared()
// move assignment:
QSharedPointer<ForwardDeclared> sp4;
- sp4 = qMove(sp);
+ sp4 = std::move(sp);
// and move constuction:
- QSharedPointer<ForwardDeclared> sp5 = qMove(sp2);
+ QSharedPointer<ForwardDeclared> sp5 = std::move(sp2);
// swapping:
sp4.swap(sp3);
@@ -843,15 +843,15 @@ void tst_QSharedPointer::upCast()
QVERIFY(baseptr == derivedptr);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QWeakPointer<DerivedData> derivedptr = qWeakPointerCast<DerivedData>(baseptr);
QVERIFY(baseptr == derivedptr);
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QWeakPointer<Data> weakptr = baseptr;
@@ -859,16 +859,16 @@ void tst_QSharedPointer::upCast()
QVERIFY(baseptr == derivedptr);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QSharedPointer<DerivedData> derivedptr = baseptr.staticCast<DerivedData>();
QVERIFY(baseptr == derivedptr);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
}
class OtherObject: public QObject
@@ -1115,6 +1115,60 @@ void tst_QSharedPointer::objectCast()
safetyCheck();
}
+
+void tst_QSharedPointer::objectCastStdSharedPtr()
+{
+ {
+ OtherObject *data = new OtherObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform successful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(baseptr);
+ QVERIFY(ptr.get());
+ QVERIFY(ptr.get() == data);
+
+ QVERIFY(baseptr.get() == data);
+ }
+
+ {
+ OtherObject *data = new OtherObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform successful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(std::move(baseptr));
+ QVERIFY(ptr.get());
+ QVERIFY(ptr.get() == data);
+
+ QVERIFY(!baseptr.get());
+ }
+
+ {
+ QObject *data = new QObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform unsuccessful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(baseptr);
+ QVERIFY(!ptr.get());
+
+ QVERIFY(baseptr.get() == data);
+ }
+
+ {
+ QObject *data = new QObject;
+ std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
+ QVERIFY(baseptr.get() == data);
+
+ // perform unsuccessful object cast
+ std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(std::move(baseptr));
+ QVERIFY(!ptr.get());
+
+ QVERIFY(baseptr.get() == data);
+ }
+}
+
void tst_QSharedPointer::differentPointers()
{
{
@@ -1243,8 +1297,8 @@ void tst_QSharedPointer::dynamicCast()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QWeakPointer<Data> weakptr = baseptr;
@@ -1253,8 +1307,8 @@ void tst_QSharedPointer::dynamicCast()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>();
@@ -1262,8 +1316,8 @@ void tst_QSharedPointer::dynamicCast()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
}
void tst_QSharedPointer::dynamicCastDifferentPointers()
@@ -1278,8 +1332,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QWeakPointer<Data> weakptr = baseptr;
@@ -1288,8 +1342,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QSharedPointer<DiffPtrDerivedData> derivedptr = baseptr.dynamicCast<DiffPtrDerivedData>();
@@ -1297,8 +1351,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
Stuffing *nakedptr = dynamic_cast<Stuffing *>(baseptr.data());
@@ -1323,8 +1377,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QWeakPointer<Data> weakptr = baseptr;
@@ -1333,8 +1387,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QSharedPointer<VirtualDerived> derivedptr = baseptr.dynamicCast<VirtualDerived>();
@@ -1342,8 +1396,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase()
QCOMPARE(derivedptr.data(), aData);
QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
}
void tst_QSharedPointer::dynamicCastFailure()
@@ -1355,15 +1409,15 @@ void tst_QSharedPointer::dynamicCastFailure()
QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(baseptr);
QVERIFY(derivedptr.isNull());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
{
QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>();
QVERIFY(derivedptr.isNull());
}
- QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1);
- QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1);
+ QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
+ QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
}
void tst_QSharedPointer::dynamicCastFailureNoLeak()
@@ -1670,7 +1724,6 @@ void tst_QSharedPointer::customDeleter()
safetyCheck();
}
-#ifdef Q_COMPILER_LAMBDA
// The compiler needs to be in C++11 mode and to support lambdas
void tst_QSharedPointer::lambdaCustomDeleter()
{
@@ -1698,7 +1751,6 @@ void tst_QSharedPointer::lambdaCustomDeleter()
}
safetyCheck();
}
-#endif
void customQObjectDeleterFn(QObject *obj)
{
@@ -1734,8 +1786,8 @@ void tst_QSharedPointer::creating()
QCOMPARE(Data::destructorCounter, 1);
// valgrind will complain here if something happened to the pointer
- QVERIFY(d->weakref.load() == 1);
- QVERIFY(d->strongref.load() == 0);
+ QVERIFY(d->weakref.loadRelaxed() == 1);
+ QVERIFY(d->strongref.loadRelaxed() == 0);
}
safetyCheck();
@@ -1820,15 +1872,20 @@ void tst_QSharedPointer::creatingVariadic()
QCOMPARE(&ptr->i, &i);
}
{
- NoDefaultConstructorRRef1(1); // control check
- QSharedPointer<NoDefaultConstructorRRef1> ptr = QSharedPointer<NoDefaultConstructorRRef1>::create(1);
- QCOMPARE(ptr->i, 1);
-
NoDefaultConstructorRRef1(std::move(i)); // control check
- ptr = QSharedPointer<NoDefaultConstructorRRef1>::create(std::move(i));
+ QSharedPointer<NoDefaultConstructorRRef1> ptr = QSharedPointer<NoDefaultConstructorRRef1>::create(std::move(i));
QCOMPARE(ptr->i, i);
}
{
+ NoDefaultConstructorRRef2(std::unique_ptr<int>(new int(1))); // control check
+ QSharedPointer<NoDefaultConstructorRRef2> ptr = QSharedPointer<NoDefaultConstructorRRef2>::create(std::unique_ptr<int>(new int(1)));
+ QCOMPARE(*ptr->i, 1);
+
+ std::unique_ptr<int> p(new int(i));
+ ptr = QSharedPointer<NoDefaultConstructorRRef2>::create(std::move(p));
+ QCOMPARE(*ptr->i, i);
+ }
+ {
QString text("Hello, World");
NoDefaultConstructorRef2(text, 1); // control check
QSharedPointer<NoDefaultConstructorRef2> ptr = QSharedPointer<NoDefaultConstructorRef2>::create(text, 1);
@@ -1965,7 +2022,7 @@ void tst_QSharedPointer::threadStressTest()
for (int r = 0; r < 5; ++r) {
QVector<QThread*> allThreads(6 * qMax(strongThreadCount, weakThreadCount) + 3, 0);
QSharedPointer<ThreadData> base = QSharedPointer<ThreadData>(new ThreadData(&counter));
- counter.store(0);
+ counter.storeRelaxed(0);
// set the pointers
for (int i = 0; i < strongThreadCount; ++i) {
@@ -1999,8 +2056,8 @@ void tst_QSharedPointer::threadStressTest()
// verify that the count is the right range
int minValue = strongThreadCount;
int maxValue = strongThreadCount + weakThreadCount;
- QVERIFY(counter.load() >= minValue);
- QVERIFY(counter.load() <= maxValue);
+ QVERIFY(counter.loadRelaxed() >= minValue);
+ QVERIFY(counter.loadRelaxed() <= maxValue);
}
}
@@ -2233,11 +2290,9 @@ void tst_QSharedPointer::invalidConstructs_data()
<< &QTest::QExternalTest::tryCompileFail
<< "struct IncompatibleCustomDeleter { void operator()(int *); };\n"
"QSharedPointer<Data> ptr(new Data, IncompatibleCustomDeleter());\n";
-#ifdef Q_COMPILER_LAMBDA
QTest::newRow("incompatible-custom-lambda-deleter")
<< &QTest::QExternalTest::tryCompileFail
<< "QSharedPointer<Data> ptr(new Data, [](int *) {});\n";
-#endif
}
void tst_QSharedPointer::invalidConstructs()
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index e8ed22e427..79f5a8c46d 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -482,8 +482,8 @@ private slots:
void indexOf2();
void indexOf3_data();
// void indexOf3();
- void sprintf();
- void sprintfS();
+ void asprintf();
+ void asprintfS();
void fill();
void truncate();
void chop_data();
@@ -578,7 +578,7 @@ private slots:
#ifdef QT_USE_ICU
void toUpperLower_icu();
#endif
-#if !defined(QT_NO_UNICODE_LITERAL) && defined(Q_COMPILER_LAMBDA)
+#if !defined(QT_NO_UNICODE_LITERAL)
void literals();
#endif
void eightBitLiterals_data();
@@ -612,7 +612,7 @@ QString verifyZeroTermination(const QString &str)
int strSize = str.size();
QChar strTerminator = str.constData()[strSize];
if (QChar('\0') != strTerminator)
- return QString::fromAscii(
+ return QString::fromLatin1(
"*** Result ('%1') not null-terminated: 0x%2 ***").arg(str)
.arg(strTerminator.unicode(), 4, 16, QChar('0'));
@@ -625,11 +625,11 @@ QString verifyZeroTermination(const QString &str)
const_cast<QChar *>(strData)[strSize] = QChar('x');
if (QChar('x') != str.constData()[strSize]) {
- return QString::fromAscii("*** Failed to replace null-terminator in "
+ return QString::fromLatin1("*** Failed to replace null-terminator in "
"result ('%1') ***").arg(str);
}
if (str != strCopy) {
- return QString::fromAscii( "*** Result ('%1') differs from its copy "
+ return QString::fromLatin1( "*** Result ('%1') differs from its copy "
"after null-terminator was replaced ***").arg(str);
}
const_cast<QChar *>(strData)[strSize] = QChar('\0'); // Restore sanity
@@ -1075,9 +1075,8 @@ void tst_QString::isNull()
QString a;
QVERIFY(a.isNull());
- const char *zero = 0;
- a.sprintf( zero );
- QVERIFY(!a.isNull());
+ const char *zero = nullptr;
+ QVERIFY(!QString::asprintf(zero).isNull());
}
QT_WARNING_POP
@@ -1263,75 +1262,66 @@ static inline const void *ptrValue(quintptr v)
return reinterpret_cast<const void *>(v);
}
-void tst_QString::sprintf()
+void tst_QString::asprintf()
{
QString a;
- a.sprintf("COMPARE");
- QCOMPARE(a, QLatin1String("COMPARE"));
- a.sprintf("%%%d",1);
- QCOMPARE(a, QLatin1String("%1"));
- QCOMPARE(a.sprintf("X%dY",2), QLatin1String("X2Y"));
- QCOMPARE(a.sprintf("X%9iY", 50000 ), QLatin1String("X 50000Y"));
- QCOMPARE(a.sprintf("X%-9sY","hello"), QLatin1String("Xhello Y"));
- QCOMPARE(a.sprintf("X%-9iY", 50000 ), QLatin1String("X50000 Y"));
- QCOMPARE(a.sprintf("%lf", 1.23), QLatin1String("1.230000"));
- QCOMPARE(a.sprintf("%lf", 1.23456789), QLatin1String("1.234568"));
- QCOMPARE(a.sprintf("%p", ptrValue(0xbfffd350)), QLatin1String("0xbfffd350"));
- QCOMPARE(a.sprintf("%p", ptrValue(0)), QLatin1String("0x0"));
+ QCOMPARE(QString::asprintf("COMPARE"), QLatin1String("COMPARE"));
+ QCOMPARE(QString::asprintf("%%%d", 1), QLatin1String("%1"));
+ QCOMPARE(QString::asprintf("X%dY",2), QLatin1String("X2Y"));
+ QCOMPARE(QString::asprintf("X%9iY", 50000 ), QLatin1String("X 50000Y"));
+ QCOMPARE(QString::asprintf("X%-9sY","hello"), QLatin1String("Xhello Y"));
+ QCOMPARE(QString::asprintf("X%-9iY", 50000 ), QLatin1String("X50000 Y"));
+ QCOMPARE(QString::asprintf("%lf", 1.23), QLatin1String("1.230000"));
+ QCOMPARE(QString::asprintf("%lf", 1.23456789), QLatin1String("1.234568"));
+ QCOMPARE(QString::asprintf("%p", ptrValue(0xbfffd350)), QLatin1String("0xbfffd350"));
+ QCOMPARE(QString::asprintf("%p", ptrValue(0)), QLatin1String("0x0"));
int i = 6;
long l = -2;
float f = 4.023f;
- QString S1;
- S1.sprintf("%d %ld %f",i,l,f);
- QCOMPARE(S1, QLatin1String("6 -2 4.023000"));
+ QCOMPARE(QString::asprintf("%d %ld %f", i, l, f), QLatin1String("6 -2 4.023000"));
double d = -514.25683;
- S1.sprintf("%f",d);
- QCOMPARE(S1, QLatin1String("-514.256830"));
+ QCOMPARE(QString::asprintf("%f", d), QLatin1String("-514.256830"));
}
-void tst_QString::sprintfS()
+void tst_QString::asprintfS()
{
- QString a;
- QCOMPARE(a.sprintf("%.3s", "Hello" ), QLatin1String("Hel"));
- QCOMPARE(a.sprintf("%10.3s", "Hello" ), QLatin1String(" Hel"));
- QCOMPARE(a.sprintf("%.10s", "Hello" ), QLatin1String("Hello"));
- QCOMPARE(a.sprintf("%10.10s", "Hello" ), QLatin1String(" Hello"));
- QCOMPARE(a.sprintf("%-10.10s", "Hello" ), QLatin1String("Hello "));
- QCOMPARE(a.sprintf("%-10.3s", "Hello" ), QLatin1String("Hel "));
- QCOMPARE(a.sprintf("%-5.5s", "Hello" ), QLatin1String("Hello"));
+ QCOMPARE(QString::asprintf("%.3s", "Hello" ), QLatin1String("Hel"));
+ QCOMPARE(QString::asprintf("%10.3s", "Hello" ), QLatin1String(" Hel"));
+ QCOMPARE(QString::asprintf("%.10s", "Hello" ), QLatin1String("Hello"));
+ QCOMPARE(QString::asprintf("%10.10s", "Hello" ), QLatin1String(" Hello"));
+ QCOMPARE(QString::asprintf("%-10.10s", "Hello" ), QLatin1String("Hello "));
+ QCOMPARE(QString::asprintf("%-10.3s", "Hello" ), QLatin1String("Hel "));
+ QCOMPARE(QString::asprintf("%-5.5s", "Hello" ), QLatin1String("Hello"));
// Check utf8 conversion for %s
- QCOMPARE(a.sprintf("%s", "\303\266\303\244\303\274\303\226\303\204\303\234\303\270\303\246\303\245\303\230\303\206\303\205"), QString::fromLatin1("\366\344\374\326\304\334\370\346\345\330\306\305"));
+ QCOMPARE(QString::asprintf("%s", "\303\266\303\244\303\274\303\226\303\204\303\234\303\270\303\246\303\245\303\230\303\206\303\205"), QString::fromLatin1("\366\344\374\326\304\334\370\346\345\330\306\305"));
int n1;
- a.sprintf("%s%n%s", "hello", &n1, "goodbye");
+ QCOMPARE(QString::asprintf("%s%n%s", "hello", &n1, "goodbye"), QString("hellogoodbye"));
QCOMPARE(n1, 5);
- QCOMPARE(a, QString("hellogoodbye"));
qlonglong n2;
- a.sprintf("%s%s%lln%s", "foo", "bar", &n2, "whiz");
+ QCOMPARE(QString::asprintf("%s%s%lln%s", "foo", "bar", &n2, "whiz"), QString("foobarwhiz"));
QCOMPARE((int)n2, 6);
- QCOMPARE(a, QString("foobarwhiz"));
{ // %ls
- QCOMPARE(a.sprintf("%.3ls", qUtf16Printable("Hello")), QLatin1String("Hel"));
- QCOMPARE(a.sprintf("%10.3ls", qUtf16Printable("Hello")), QLatin1String(" Hel"));
- QCOMPARE(a.sprintf("%.10ls", qUtf16Printable("Hello")), QLatin1String("Hello"));
- QCOMPARE(a.sprintf("%10.10ls", qUtf16Printable("Hello")), QLatin1String(" Hello"));
- QCOMPARE(a.sprintf("%-10.10ls", qUtf16Printable("Hello")), QLatin1String("Hello "));
- QCOMPARE(a.sprintf("%-10.3ls", qUtf16Printable("Hello")), QLatin1String("Hel "));
- QCOMPARE(a.sprintf("%-5.5ls", qUtf16Printable("Hello")), QLatin1String("Hello"));
+ QCOMPARE(QString::asprintf("%.3ls", qUtf16Printable("Hello")), QLatin1String("Hel"));
+ QCOMPARE(QString::asprintf("%10.3ls", qUtf16Printable("Hello")), QLatin1String(" Hel"));
+ QCOMPARE(QString::asprintf("%.10ls", qUtf16Printable("Hello")), QLatin1String("Hello"));
+ QCOMPARE(QString::asprintf("%10.10ls", qUtf16Printable("Hello")), QLatin1String(" Hello"));
+ QCOMPARE(QString::asprintf("%-10.10ls", qUtf16Printable("Hello")), QLatin1String("Hello "));
+ QCOMPARE(QString::asprintf("%-10.3ls", qUtf16Printable("Hello")), QLatin1String("Hel "));
+ QCOMPARE(QString::asprintf("%-5.5ls", qUtf16Printable("Hello")), QLatin1String("Hello"));
// Check utf16 is preserved for %ls
- QCOMPARE(a.sprintf("%ls",
+ QCOMPARE(QString::asprintf("%ls",
qUtf16Printable("\303\266\303\244\303\274\303\226\303\204\303\234\303\270\303\246\303\245\303\230\303\206\303\205")),
QLatin1String("\366\344\374\326\304\334\370\346\345\330\306\305"));
int n;
- a.sprintf("%ls%n%s", qUtf16Printable("hello"), &n, "goodbye");
+ QCOMPARE(QString::asprintf("%ls%n%s", qUtf16Printable("hello"), &n, "goodbye"), QLatin1String("hellogoodbye"));
QCOMPARE(n, 5);
- QCOMPARE(a, QLatin1String("hellogoodbye"));
}
}
@@ -2212,12 +2202,12 @@ void tst_QString::toUpper()
// call rvalue-ref while shared (the original mustn't change)
QString copy = s;
- QCOMPARE(qMove(copy).toUpper(), QString("GROSSSTRASSE"));
+ QCOMPARE(std::move(copy).toUpper(), QString("GROSSSTRASSE"));
QCOMPARE(s, QString::fromUtf8("Gro\xc3\x9fstra\xc3\x9f""e"));
// call rvalue-ref version on detached case
copy.clear();
- QCOMPARE(qMove(s).toUpper(), QString("GROSSSTRASSE"));
+ QCOMPARE(std::move(s).toUpper(), QString("GROSSSTRASSE"));
}
QString lower, upper;
@@ -2427,11 +2417,11 @@ void tst_QString::trimmed()
QCOMPARE(a.trimmed(), QLatin1String("a"));
a="Text";
- QCOMPARE(qMove(a).trimmed(), QLatin1String("Text"));
+ QCOMPARE(std::move(a).trimmed(), QLatin1String("Text"));
a=" ";
- QCOMPARE(qMove(a).trimmed(), QLatin1String(""));
+ QCOMPARE(std::move(a).trimmed(), QLatin1String(""));
a=" a ";
- QCOMPARE(qMove(a).trimmed(), QLatin1String("a"));
+ QCOMPARE(std::move(a).trimmed(), QLatin1String("a"));
}
void tst_QString::simplified_data()
@@ -2486,13 +2476,13 @@ void tst_QString::simplified()
// without detaching:
QString copy1 = full;
- QCOMPARE(qMove(full).simplified(), simple);
+ QCOMPARE(std::move(full).simplified(), simple);
QCOMPARE(full, orig_full);
// force a detach
if (!full.isEmpty())
full[0] = full[0];
- QCOMPARE(qMove(full).simplified(), simple);
+ QCOMPARE(std::move(full).simplified(), simple);
}
void tst_QString::insert_data(bool emptyIsNoop)
@@ -3789,7 +3779,7 @@ void tst_QString::startsWith()
QVERIFY( !a.startsWith("C") );
QVERIFY( !a.startsWith("ABCDEF") );
QVERIFY( a.startsWith("") );
- QVERIFY( a.startsWith(QString::null) );
+ QVERIFY( a.startsWith(QString()) );
QVERIFY( a.startsWith('A') );
QVERIFY( a.startsWith(QLatin1Char('A')) );
QVERIFY( a.startsWith(QChar('A')) );
@@ -3816,7 +3806,7 @@ void tst_QString::startsWith()
QVERIFY( !a.startsWith("c", Qt::CaseInsensitive) );
QVERIFY( !a.startsWith("abcdef", Qt::CaseInsensitive) );
QVERIFY( a.startsWith("", Qt::CaseInsensitive) );
- QVERIFY( a.startsWith(QString::null, Qt::CaseInsensitive) );
+ QVERIFY( a.startsWith(QString(), Qt::CaseInsensitive) );
QVERIFY( a.startsWith('a', Qt::CaseInsensitive) );
QVERIFY( a.startsWith('A', Qt::CaseInsensitive) );
QVERIFY( a.startsWith(QLatin1Char('a'), Qt::CaseInsensitive) );
@@ -3855,7 +3845,7 @@ void tst_QString::startsWith()
a = "";
QVERIFY( a.startsWith("") );
- QVERIFY( a.startsWith(QString::null) );
+ QVERIFY( a.startsWith(QString()) );
QVERIFY( !a.startsWith("ABC") );
QVERIFY( a.startsWith(QLatin1String("")) );
@@ -3868,7 +3858,7 @@ void tst_QString::startsWith()
a = QString();
QVERIFY( !a.startsWith("") );
- QVERIFY( a.startsWith(QString::null) );
+ QVERIFY( a.startsWith(QString()) );
QVERIFY( !a.startsWith("ABC") );
QVERIFY( !a.startsWith(QLatin1String("")) );
@@ -3897,7 +3887,7 @@ void tst_QString::endsWith()
QVERIFY( !a.endsWith("C") );
QVERIFY( !a.endsWith("ABCDEF") );
QVERIFY( a.endsWith("") );
- QVERIFY( a.endsWith(QString::null) );
+ QVERIFY( a.endsWith(QString()) );
QVERIFY( a.endsWith('B') );
QVERIFY( a.endsWith(QLatin1Char('B')) );
QVERIFY( a.endsWith(QChar('B')) );
@@ -3924,7 +3914,7 @@ void tst_QString::endsWith()
QVERIFY( !a.endsWith("c", Qt::CaseInsensitive) );
QVERIFY( !a.endsWith("abcdef", Qt::CaseInsensitive) );
QVERIFY( a.endsWith("", Qt::CaseInsensitive) );
- QVERIFY( a.endsWith(QString::null, Qt::CaseInsensitive) );
+ QVERIFY( a.endsWith(QString(), Qt::CaseInsensitive) );
QVERIFY( a.endsWith('b', Qt::CaseInsensitive) );
QVERIFY( a.endsWith('B', Qt::CaseInsensitive) );
QVERIFY( a.endsWith(QLatin1Char('b'), Qt::CaseInsensitive) );
@@ -3966,7 +3956,7 @@ void tst_QString::endsWith()
a = "";
QVERIFY( a.endsWith("") );
- QVERIFY( a.endsWith(QString::null) );
+ QVERIFY( a.endsWith(QString()) );
QVERIFY( !a.endsWith("ABC") );
QVERIFY( !a.endsWith(QLatin1Char(0)) );
QVERIFY( !a.endsWith(QLatin1Char('x')) );
@@ -3978,7 +3968,7 @@ void tst_QString::endsWith()
a = QString();
QVERIFY( !a.endsWith("") );
- QVERIFY( a.endsWith(QString::null) );
+ QVERIFY( a.endsWith(QString()) );
QVERIFY( !a.endsWith("ABC") );
QVERIFY( !a.endsWith(QLatin1String("")) );
@@ -4534,7 +4524,7 @@ void tst_QString::toLatin1Roundtrip()
// try the rvalue version of toLatin1()
QString s = unicodesrc;
- QCOMPARE(qMove(s).toLatin1(), latin1);
+ QCOMPARE(std::move(s).toLatin1(), latin1);
// and verify that the moved-from object can still be used
s = "foo";
@@ -4838,7 +4828,7 @@ void tst_QString::arg()
QCOMPARE( QString("%1").arg("hello", 10), QLatin1String(" hello") );
QCOMPARE( QString("%1%1").arg("hello"), QLatin1String("hellohello") );
QCOMPARE( QString("%2%1").arg("hello"), QLatin1String("%2hello") );
- QCOMPARE( QString("%1%1").arg(QString::null), QLatin1String("") );
+ QCOMPARE( QString("%1%1").arg(QString()), QLatin1String("") );
QCOMPARE( QString("%2%1").arg(""), QLatin1String("%2") );
QCOMPARE( QString("%2 %L1").arg(12345.6789).arg(12345.6789),
@@ -4934,9 +4924,7 @@ void tst_QString::doubleOut()
QCOMPARE(QString::number(micro), expect);
QCOMPARE(QString("%1").arg(micro), expect);
{
- QString text;
- text.sprintf("%g", micro);
- QCOMPARE(text, expect);
+ QCOMPARE(QString::asprintf("%g", micro), expect);
}
{
QString text;
@@ -5480,8 +5468,6 @@ void tst_QString::tortureSprintfDouble()
{
const SprintfDoubleData *data = g_sprintf_double_data;
- QString s;
-
for (; data->fmt != 0; ++data) {
double d;
char *buff = (char *)&d;
@@ -5496,7 +5482,7 @@ void tst_QString::tortureSprintfDouble()
for (uint i = 0; i < 8; ++i)
buff[7 - i] = data->bytes[i];
# endif
- s.sprintf(data->fmt, d);
+ const QString s = QString::asprintf(data->fmt, d);
#ifdef QT_NO_FPU // reduced precision when running with hardfloats in qemu
if (d - 0.1 < 1e12)
QSKIP("clib sprintf doesn't fill with 0's on this platform");
@@ -6450,32 +6436,24 @@ void tst_QString::QCharRefDetaching() const
void tst_QString::sprintfZU() const
{
{
- QString string;
size_t s = 6;
- string.sprintf("%zu", s);
- QCOMPARE(string, QString::fromLatin1("6"));
+ QCOMPARE(QString::asprintf("%zu", s), QString::fromLatin1("6"));
}
{
- QString string;
- string.sprintf("%s\n", "foo");
- QCOMPARE(string, QString::fromLatin1("foo\n"));
+ QCOMPARE(QString::asprintf("%s\n", "foo"), QString::fromLatin1("foo\n"));
}
{
/* This code crashed. I don't know how to reduce it further. In other words,
* both %zu and %s needs to be present. */
size_t s = 6;
- QString string;
- string.sprintf("%zu%s", s, "foo");
- QCOMPARE(string, QString::fromLatin1("6foo"));
+ QCOMPARE(QString::asprintf("%zu%s", s, "foo"), QString::fromLatin1("6foo"));
}
{
size_t s = 6;
- QString string;
- string.sprintf("%zu %s\n", s, "foo");
- QCOMPARE(string, QString::fromLatin1("6 foo\n"));
+ QCOMPARE(QString::asprintf("%zu %s\n", s, "foo"), QString::fromLatin1("6 foo\n"));
}
}
@@ -6643,7 +6621,7 @@ void tst_QString::toUpperLower_icu()
}
#endif
-#if !defined(QT_NO_UNICODE_LITERAL) && defined(Q_COMPILER_LAMBDA)
+#if !defined(QT_NO_UNICODE_LITERAL)
// Only tested on c++0x compliant compiler or gcc
void tst_QString::literals()
{
diff --git a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp
index cb1fd9eb7d..24382a2b61 100644
--- a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp
+++ b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Copyright (C) 2019 Mail.ru Group.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -48,6 +49,14 @@ QString toQString(const T &t) { return QString(t); }
QString toQString(const QStringRef &ref) { return ref.toString(); }
QString toQString(QStringView view) { return view.toString(); }
+template <typename Iterable>
+QStringList toQStringList(const Iterable &i) {
+ QStringList result;
+ for (auto &e : i)
+ result.push_back(toQString(e));
+ return result;
+}
+
// FIXME: these are missing at the time of writing, add them, then remove the dummies here:
#define MAKE_RELOP(op, A1, A2) \
static bool operator op (A1 lhs, A2 rhs) \
@@ -293,6 +302,26 @@ private Q_SLOTS:
void endsWith_QLatin1String_QChar() { endsWith_impl<QLatin1String, QChar>(); }
private:
+ void split_data(bool rhsHasVariableLength = true);
+ template <typename Haystack, typename Needle> void split_impl() const;
+
+private Q_SLOTS:
+ // test all combinations of {QString, QStringRef} x {QString, QLatin1String, QChar}:
+ void split_QString_QString_data() { split_data(); }
+ void split_QString_QString() { split_impl<QString, QString>(); }
+ void split_QString_QLatin1String_data() { split_data(); }
+ void split_QString_QLatin1String() { split_impl<QString, QLatin1String>(); }
+ void split_QString_QChar_data() { split_data(false); }
+ void split_QString_QChar() { split_impl<QString, QChar>(); }
+
+ void split_QStringRef_QString_data() { split_data(); }
+ void split_QStringRef_QString() { split_impl<QStringRef, QString>(); }
+ void split_QStringRef_QLatin1String_data() { split_data(); }
+ void split_QStringRef_QLatin1String() { split_impl<QStringRef, QLatin1String>(); }
+ void split_QStringRef_QChar_data() { split_data(false); }
+ void split_QStringRef_QChar() { split_impl<QStringRef, QChar>(); }
+
+private:
void mid_data();
template <typename String> void mid_impl();
@@ -416,6 +445,129 @@ private Q_SLOTS:
void toUcs4_QStringRef() { toUcs4_impl<QStringRef>(); }
void toUcs4_QStringView_data() { toUcs4_data(); }
void toUcs4_QStringView() { toUcs4_impl<QStringView>(); }
+
+private:
+ template <typename Haystack, typename Needle> void indexOf_impl() const;
+ void indexOf_data();
+
+private Q_SLOTS:
+ void indexOf_QString_QString_data() { indexOf_data(); }
+ void indexOf_QString_QString() { indexOf_impl<QString, QString>(); }
+ void indexOf_QString_QLatin1String_data() { indexOf_data(); }
+ void indexOf_QString_QLatin1String() { indexOf_impl<QString, QLatin1String>(); }
+ void indexOf_QString_QStringRef_data() { indexOf_data(); }
+ void indexOf_QString_QStringRef() { indexOf_impl<QString, QStringRef>(); }
+ void indexOf_QString_QStringView_data() { indexOf_data(); }
+ void indexOf_QString_QStringView() { indexOf_impl<QString, QStringView>(); }
+
+ void indexOf_QLatin1String_QString_data() { indexOf_data(); }
+ void indexOf_QLatin1String_QString() { indexOf_impl<QLatin1String, QString>(); }
+ void indexOf_QLatin1String_QLatin1String_data() { indexOf_data(); }
+ void indexOf_QLatin1String_QLatin1String() { indexOf_impl<QLatin1String, QLatin1String>(); }
+ void indexOf_QLatin1String_QStringRef_data() { indexOf_data(); }
+ void indexOf_QLatin1String_QStringRef() { indexOf_impl<QLatin1String, QStringRef>(); }
+ void indexOf_QLatin1String_QStringView_data() { indexOf_data(); }
+ void indexOf_QLatin1String_QStringView() { indexOf_impl<QLatin1String, QStringView>(); }
+
+ void indexOf_QStringRef_QString_data() { indexOf_data(); }
+ void indexOf_QStringRef_QString() { indexOf_impl<QStringRef, QString>(); }
+ void indexOf_QStringRef_QLatin1String_data() { indexOf_data(); }
+ void indexOf_QStringRef_QLatin1String() { indexOf_impl<QStringRef, QLatin1String>(); }
+ void indexOf_QStringRef_QStringRef_data() { indexOf_data(); }
+ void indexOf_QStringRef_QStringRef() { indexOf_impl<QStringRef, QStringRef>(); }
+ void indexOf_QStringRef_QStringView_data() { indexOf_data(); }
+ void indexOf_QStringRef_QStringView() { indexOf_impl<QStringRef, QStringView>(); }
+
+ void indexOf_QStringView_QString_data() { indexOf_data(); }
+ void indexOf_QStringView_QString() { indexOf_impl<QStringView, QString>(); }
+ void indexOf_QStringView_QLatin1String_data() { indexOf_data(); }
+ void indexOf_QStringView_QLatin1String() { indexOf_impl<QStringView, QLatin1String>(); }
+ void indexOf_QStringView_QStringRef_data() { indexOf_data(); }
+ void indexOf_QStringView_QStringRef() { indexOf_impl<QStringView, QStringRef>(); }
+ void indexOf_QStringView_QStringView_data() { indexOf_data(); }
+ void indexOf_QStringView_QStringView() { indexOf_impl<QStringView, QStringView>(); }
+
+private:
+ template <typename Haystack, typename Needle> void contains_impl() const;
+ void contains_data();
+
+private Q_SLOTS:
+ void contains_QString_QString_data() { contains_data(); }
+ void contains_QString_QString() { contains_impl<QString, QString>(); }
+ void contains_QString_QLatin1String_data() { contains_data(); }
+ void contains_QString_QLatin1String() { contains_impl<QString, QLatin1String>(); }
+ void contains_QString_QStringRef_data() { contains_data(); }
+ void contains_QString_QStringRef() { contains_impl<QString, QStringRef>(); }
+ void contains_QString_QStringView_data() { contains_data(); }
+ void contains_QString_QStringView() { contains_impl<QString, QStringView>(); }
+
+ void contains_QLatin1String_QString_data() { contains_data(); }
+ void contains_QLatin1String_QString() { contains_impl<QLatin1String, QString>(); }
+ void contains_QLatin1String_QLatin1String_data() { contains_data(); }
+ void contains_QLatin1String_QLatin1String() { contains_impl<QLatin1String, QLatin1String>(); }
+ void contains_QLatin1String_QStringRef_data() { contains_data(); }
+ void contains_QLatin1String_QStringRef() { contains_impl<QLatin1String, QStringRef>(); }
+ void contains_QLatin1String_QStringView_data() { contains_data(); }
+ void contains_QLatin1String_QStringView() { contains_impl<QLatin1String, QStringView>(); }
+
+ void contains_QStringRef_QString_data() { contains_data(); }
+ void contains_QStringRef_QString() { contains_impl<QStringRef, QString>(); }
+ void contains_QStringRef_QLatin1String_data() { contains_data(); }
+ void contains_QStringRef_QLatin1String() { contains_impl<QStringRef, QLatin1String>(); }
+ void contains_QStringRef_QStringRef_data() { contains_data(); }
+ void contains_QStringRef_QStringRef() { contains_impl<QStringRef, QStringRef>(); }
+ void contains_QStringRef_QStringView_data() { contains_data(); }
+ void contains_QStringRef_QStringView() { contains_impl<QStringRef, QStringView>(); }
+
+ void contains_QStringView_QString_data() { contains_data(); }
+ void contains_QStringView_QString() { contains_impl<QStringView, QString>(); }
+ void contains_QStringView_QLatin1String_data() { contains_data(); }
+ void contains_QStringView_QLatin1String() { contains_impl<QStringView, QLatin1String>(); }
+ void contains_QStringView_QStringRef_data() { contains_data(); }
+ void contains_QStringView_QStringRef() { contains_impl<QStringView, QStringRef>(); }
+ void contains_QStringView_QStringView_data() { contains_data(); }
+ void contains_QStringView_QStringView() { contains_impl<QStringView, QStringView>(); }
+
+private:
+ template <typename Haystack, typename Needle> void lastIndexOf_impl() const;
+ void lastIndexOf_data();
+
+private Q_SLOTS:
+ void lastIndexOf_QString_QString_data() { lastIndexOf_data(); }
+ void lastIndexOf_QString_QString() { lastIndexOf_impl<QString, QString>(); }
+ void lastIndexOf_QString_QLatin1String_data() { lastIndexOf_data(); }
+ void lastIndexOf_QString_QLatin1String() { lastIndexOf_impl<QString, QLatin1String>(); }
+ void lastIndexOf_QString_QStringRef_data() { lastIndexOf_data(); }
+ void lastIndexOf_QString_QStringRef() { lastIndexOf_impl<QString, QStringRef>(); }
+ void lastIndexOf_QString_QStringView_data() { lastIndexOf_data(); }
+ void lastIndexOf_QString_QStringView() { lastIndexOf_impl<QString, QStringView>(); }
+
+ void lastIndexOf_QLatin1String_QString_data() { lastIndexOf_data(); }
+ void lastIndexOf_QLatin1String_QString() { lastIndexOf_impl<QLatin1String, QString>(); }
+ void lastIndexOf_QLatin1String_QLatin1String_data() { lastIndexOf_data(); }
+ void lastIndexOf_QLatin1String_QLatin1String() { lastIndexOf_impl<QLatin1String, QLatin1String>(); }
+ void lastIndexOf_QLatin1String_QStringRef_data() { lastIndexOf_data(); }
+ void lastIndexOf_QLatin1String_QStringRef() { lastIndexOf_impl<QLatin1String, QStringRef>(); }
+ void lastIndexOf_QLatin1String_QStringView_data() { lastIndexOf_data(); }
+ void lastIndexOf_QLatin1String_QStringView() { lastIndexOf_impl<QLatin1String, QStringView>(); }
+
+ void lastIndexOf_QStringRef_QString_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringRef_QString() { lastIndexOf_impl<QStringRef, QString>(); }
+ void lastIndexOf_QStringRef_QLatin1String_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringRef_QLatin1String() { lastIndexOf_impl<QStringRef, QLatin1String>(); }
+ void lastIndexOf_QStringRef_QStringRef_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringRef_QStringRef() { lastIndexOf_impl<QStringRef, QStringRef>(); }
+ void lastIndexOf_QStringRef_QStringView_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringRef_QStringView() { lastIndexOf_impl<QStringRef, QStringView>(); }
+
+ void lastIndexOf_QStringView_QString_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringView_QString() { lastIndexOf_impl<QStringView, QString>(); }
+ void lastIndexOf_QStringView_QLatin1String_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringView_QLatin1String() { lastIndexOf_impl<QStringView, QLatin1String>(); }
+ void lastIndexOf_QStringView_QStringRef_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringView_QStringRef() { lastIndexOf_impl<QStringView, QStringRef>(); }
+ void lastIndexOf_QStringView_QStringView_data() { lastIndexOf_data(); }
+ void lastIndexOf_QStringView_QStringView() { lastIndexOf_impl<QStringView, QStringView>(); }
};
void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
@@ -540,6 +692,7 @@ void tst_QStringApiSymmetry::compare_impl() const
}
static QString empty = QLatin1String("");
+static QString null;
// the tests below rely on the fact that these objects' names match their contents:
static QString a = QStringLiteral("a");
static QString A = QStringLiteral("A");
@@ -547,6 +700,14 @@ static QString b = QStringLiteral("b");
static QString B = QStringLiteral("B");
static QString c = QStringLiteral("c");
static QString C = QStringLiteral("C");
+static QString d = QStringLiteral("d");
+static QString D = QStringLiteral("D");
+static QString e = QStringLiteral("e");
+static QString E = QStringLiteral("E");
+static QString f = QStringLiteral("f");
+static QString F = QStringLiteral("F");
+static QString g = QStringLiteral("g");
+static QString G = QStringLiteral("G");
static QString ab = QStringLiteral("ab");
static QString aB = QStringLiteral("aB");
static QString Ab = QStringLiteral("Ab");
@@ -738,6 +899,119 @@ void tst_QStringApiSymmetry::endsWith_impl() const
QCOMPARE(haystack.endsWith(needle, Qt::CaseInsensitive), resultCIS);
}
+void tst_QStringApiSymmetry::split_data(bool rhsHasVariableLength)
+{
+ QTest::addColumn<QStringRef>("haystackU16");
+ QTest::addColumn<QLatin1String>("haystackL1");
+ QTest::addColumn<QStringRef>("needleU16");
+ QTest::addColumn<QLatin1String>("needleL1");
+ QTest::addColumn<QStringList>("resultCS");
+ QTest::addColumn<QStringList>("resultCIS");
+
+ if (rhsHasVariableLength) {
+ QTest::addRow("null ~= null$") << QStringRef{} << QLatin1String{}
+ << QStringRef{} << QLatin1String{}
+ << QStringList{{}, {}} << QStringList{{}, {}};
+ QTest::addRow("empty ~= null$") << QStringRef{&empty} << QLatin1String("")
+ << QStringRef{} << QLatin1String{}
+ << QStringList{empty, empty} << QStringList{empty, empty};
+ QTest::addRow("a ~= null$") << QStringRef{&a} << QLatin1String{"a"}
+ << QStringRef{} << QLatin1String{}
+ << QStringList{empty, a, empty} << QStringList{empty, a, empty};
+ QTest::addRow("null ~= empty$") << QStringRef{} << QLatin1String{}
+ << QStringRef{&empty} << QLatin1String{""}
+ << QStringList{{}, {}} << QStringList{{}, {}};
+ QTest::addRow("a ~= empty$") << QStringRef{&a} << QLatin1String{"a"}
+ << QStringRef{&empty} << QLatin1String{""}
+ << QStringList{empty, a, empty} << QStringList{empty, a, empty};
+ QTest::addRow("empty ~= empty$") << QStringRef{&empty} << QLatin1String{""}
+ << QStringRef{&empty} << QLatin1String{""}
+ << QStringList{empty, empty} << QStringList{empty, empty};
+ }
+ QTest::addRow("null ~= a$") << QStringRef{} << QLatin1String{}
+ << QStringRef{&a} << QLatin1String{"a"}
+ << QStringList{{}} << QStringList{{}};
+ QTest::addRow("empty ~= a$") << QStringRef{&empty} << QLatin1String{""}
+ << QStringRef{&a} << QLatin1String{"a"}
+ << QStringList{empty} << QStringList{empty};
+
+#define ROW(h, n, cs, cis) \
+ QTest::addRow("%s ~= %s$", #h, #n) << QStringRef(&h) << QLatin1String(#h) \
+ << QStringRef(&n) << QLatin1String(#n) \
+ << QStringList cs << QStringList cis
+ ROW(a, a, ({empty, empty}), ({empty, empty}));
+ ROW(a, A, {a}, ({empty, empty}));
+ ROW(a, b, {a}, {a});
+
+ if (rhsHasVariableLength)
+ ROW(b, ab, {b}, {b});
+
+ ROW(ab, b, ({a, empty}), ({a, empty}));
+ if (rhsHasVariableLength) {
+ ROW(ab, ab, ({empty, empty}), ({empty, empty}));
+ ROW(ab, aB, {ab}, ({empty, empty}));
+ ROW(ab, Ab, {ab}, ({empty, empty}));
+ }
+ ROW(ab, c, {ab}, {ab});
+
+ if (rhsHasVariableLength)
+ ROW(bc, abc, {bc}, {bc});
+
+ ROW(Abc, c, ({Ab, empty}), ({Ab, empty}));
+#if 0
+ if (rhsHasVariableLength) {
+ ROW(Abc, bc, 1, 1);
+ ROW(Abc, bC, 0, 1);
+ ROW(Abc, Bc, 0, 1);
+ ROW(Abc, BC, 0, 1);
+ ROW(aBC, bc, 0, 1);
+ ROW(aBC, bC, 0, 1);
+ ROW(aBC, Bc, 0, 1);
+ ROW(aBC, BC, 1, 1);
+ }
+#endif
+ ROW(ABC, b, {ABC}, ({A, C}));
+ ROW(ABC, a, {ABC}, ({empty, BC}));
+#undef ROW
+}
+
+static QStringList skipped(const QStringList &sl)
+{
+ QStringList result;
+ result.reserve(sl.size());
+ for (const QString &s : sl) {
+ if (!s.isEmpty())
+ result.push_back(s);
+ }
+ return result;
+}
+
+template <typename Haystack, typename Needle>
+void tst_QStringApiSymmetry::split_impl() const
+{
+ QFETCH(const QStringRef, haystackU16);
+ QFETCH(const QLatin1String, haystackL1);
+ QFETCH(const QStringRef, needleU16);
+ QFETCH(const QLatin1String, needleL1);
+ QFETCH(const QStringList, resultCS);
+ QFETCH(const QStringList, resultCIS);
+
+ const QStringList skippedResultCS = skipped(resultCS);
+ const QStringList skippedResultCIS = skipped(resultCIS);
+
+ const auto haystackU8 = haystackU16.toUtf8();
+ const auto needleU8 = needleU16.toUtf8();
+
+ const auto haystack = make<Haystack>(haystackU16, haystackL1, haystackU8);
+ const auto needle = make<Needle>(needleU16, needleL1, needleU8);
+
+ QCOMPARE(toQStringList(haystack.split(needle)), resultCS);
+ QCOMPARE(toQStringList(haystack.split(needle, Qt::KeepEmptyParts, Qt::CaseSensitive)), resultCS);
+ QCOMPARE(toQStringList(haystack.split(needle, Qt::KeepEmptyParts, Qt::CaseInsensitive)), resultCIS);
+ QCOMPARE(toQStringList(haystack.split(needle, Qt::SkipEmptyParts, Qt::CaseSensitive)), skippedResultCS);
+ QCOMPARE(toQStringList(haystack.split(needle, Qt::SkipEmptyParts, Qt::CaseInsensitive)), skippedResultCIS);
+}
+
void tst_QStringApiSymmetry::mid_data()
{
QTest::addColumn<QStringRef>("unicode");
@@ -1020,7 +1294,7 @@ void tst_QStringApiSymmetry::trimmed_data()
for (int len = 0; len < latin1Whitespace.size(); ++len) {
for (int pos = 0; pos < latin1Whitespace.size() - len; ++pos) {
const QString unicode = latin1Whitespace.mid(pos, len) + str + latin1Whitespace.mid(pos, len);
- const QScopedPointer<const char> escaped(QTest::toString(unicode));
+ const QScopedArrayPointer<const char> escaped(QTest::toString(unicode));
QTest::addRow("%s", escaped.data()) << unicode << QStringRef(&str);
}
}
@@ -1216,6 +1490,296 @@ void tst_QStringApiSymmetry::toUcs4_impl()
QCOMPARE(unicode.isEmpty(), ucs4.isEmpty());
}
+void tst_QStringApiSymmetry::indexOf_data()
+{
+ QTest::addColumn<QString>("haystackU16");
+ QTest::addColumn<QLatin1String>("haystackL1");
+ QTest::addColumn<QString>("needleU16");
+ QTest::addColumn<QLatin1String>("needleL1");
+ QTest::addColumn<qsizetype>("startpos");
+ QTest::addColumn<qsizetype>("resultCS");
+ QTest::addColumn<qsizetype>("resultCIS");
+
+ constexpr qsizetype zeroPos = 0;
+ constexpr qsizetype minus1Pos = -1;
+
+ QTest::addRow("haystack: null, needle: null") << null << QLatin1String()
+ << null << QLatin1String() << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
+ << null << QLatin1String() << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
+ << null << QLatin1String() << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
+ << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
+ << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
+ << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos;
+ QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
+ << a << QLatin1String("a") << zeroPos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
+ << a << QLatin1String("a") << zeroPos << minus1Pos << minus1Pos;
+
+
+#define ROW(h, n, st, cs, cis) \
+ QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \
+ << n << QLatin1String(#n) \
+ << qsizetype(st) << qsizetype(cs) << qsizetype(cis)
+
+ ROW(abc, a, 0, 0, 0);
+ ROW(abc, A, 0, -1, 0);
+ ROW(abc, a, 1, -1, -1);
+ ROW(abc, A, 1, -1, -1);
+ ROW(abc, b, 0, 1, 1);
+ ROW(abc, B, 0, -1, 1);
+ ROW(abc, b, 1, 1, 1);
+ ROW(abc, B, 1, -1, 1);
+ ROW(abc, B, 2, -1, -1);
+
+ ROW(ABC, A, 0, 0, 0);
+ ROW(ABC, a, 0, -1, 0);
+ ROW(ABC, A, 1, -1, -1);
+ ROW(ABC, a, 1, -1, -1);
+ ROW(ABC, B, 0, 1, 1);
+ ROW(ABC, b, 0, -1, 1);
+ ROW(ABC, B, 1, 1, 1);
+ ROW(ABC, b, 1, -1, 1);
+ ROW(ABC, B, 2, -1, -1);
+
+ ROW(aBc, bc, 0, -1, 1);
+ ROW(aBc, Bc, 0, 1, 1);
+ ROW(aBc, bC, 0, -1, 1);
+ ROW(aBc, BC, 0, -1, 1);
+
+ ROW(AbC, bc, 0, -1, 1);
+ ROW(AbC, Bc, 0, -1, 1);
+ ROW(AbC, bC, 0, 1, 1);
+ ROW(AbC, BC, 0, -1, 1);
+ ROW(AbC, BC, 1, -1, 1);
+ ROW(AbC, BC, 2, -1, -1);
+#undef ROW
+
+}
+
+template <typename Haystack, typename Needle>
+void tst_QStringApiSymmetry::indexOf_impl() const
+{
+ QFETCH(const QString, haystackU16);
+ QFETCH(const QLatin1String, haystackL1);
+ QFETCH(const QString, needleU16);
+ QFETCH(const QLatin1String, needleL1);
+ QFETCH(const qsizetype, startpos);
+ QFETCH(const qsizetype, resultCS);
+ QFETCH(const qsizetype, resultCIS);
+
+ const auto haystackU8 = haystackU16.toUtf8();
+ const auto needleU8 = needleU16.toUtf8();
+
+ const auto haystack = make<Haystack>(QStringRef(&haystackU16), haystackL1, haystackU8);
+ const auto needle = make<Needle>(QStringRef(&needleU16), needleL1, needleU8);
+
+ using size_type = typename Haystack::size_type;
+
+ QCOMPARE(haystack.indexOf(needle, startpos), size_type(resultCS));
+ QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS));
+ QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS));
+
+ if (needle.size() == 1)
+ {
+ QCOMPARE(haystack.indexOf(needle[0], startpos), size_type(resultCS));
+ QCOMPARE(haystack.indexOf(needle[0], startpos, Qt::CaseSensitive), size_type(resultCS));
+ QCOMPARE(haystack.indexOf(needle[0], startpos, Qt::CaseInsensitive), size_type(resultCIS));
+ }
+}
+
+static QString ABCDEFGHIEfGEFG = QStringLiteral("ABCDEFGHIEfGEFG");
+static QString EFG = QStringLiteral("EFG");
+static QString efg = QStringLiteral("efg");
+static QString asd = QStringLiteral("asd");
+static QString asdf = QStringLiteral("asdf");
+static QString Z = QStringLiteral("Z");
+
+void tst_QStringApiSymmetry::contains_data()
+{
+ QTest::addColumn<QString>("haystackU16");
+ QTest::addColumn<QLatin1String>("haystackL1");
+ QTest::addColumn<QString>("needleU16");
+ QTest::addColumn<QLatin1String>("needleL1");
+ QTest::addColumn<bool>("resultCS");
+ QTest::addColumn<bool>("resultCIS");
+
+ QTest::addRow("haystack: null, needle: null") << null << QLatin1String()
+ << null << QLatin1String() << true << true;
+ QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
+ << null << QLatin1String() << true << true;
+ QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
+ << null << QLatin1String() << true << true;
+ QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
+ << empty << QLatin1String("") << true << true;
+ QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
+ << empty << QLatin1String("") << true << true;;
+ QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
+ << empty << QLatin1String("") << true << true;
+ QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
+ << a << QLatin1String("a") << false << false;
+ QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
+ << a << QLatin1String("a") << false << false;
+
+#define ROW(h, n, cs, cis) \
+ QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \
+ << n << QLatin1String(#n) \
+ << cs << cis
+
+ ROW(ABCDEFGHIEfGEFG, A, true, true);
+ ROW(ABCDEFGHIEfGEFG, a, false, true);
+ ROW(ABCDEFGHIEfGEFG, Z, false, false);
+ ROW(ABCDEFGHIEfGEFG, EFG, true, true);
+ ROW(ABCDEFGHIEfGEFG, efg, false, true);
+ ROW(ABCDEFGHIEfGEFG, E, true, true);
+ ROW(ABCDEFGHIEfGEFG, e, false, true);
+#undef ROW
+}
+
+template <typename Haystack, typename Needle>
+void tst_QStringApiSymmetry::contains_impl() const
+{
+ QFETCH(const QString, haystackU16);
+ QFETCH(const QLatin1String, haystackL1);
+ QFETCH(const QString, needleU16);
+ QFETCH(const QLatin1String, needleL1);
+ QFETCH(const bool, resultCS);
+ QFETCH(const bool, resultCIS);
+
+ const auto haystackU8 = haystackU16.toUtf8();
+ const auto needleU8 = needleU16.toUtf8();
+
+ const auto haystack = make<Haystack>(QStringRef(&haystackU16), haystackL1, haystackU8);
+ const auto needle = make<Needle>(QStringRef(&needleU16), needleL1, needleU8);
+
+ QCOMPARE(haystack.contains(needle), resultCS);
+ QCOMPARE(haystack.contains(needle, Qt::CaseSensitive), resultCS);
+ QCOMPARE(haystack.contains(needle, Qt::CaseInsensitive), resultCIS);
+
+ if (needle.size() == 1)
+ {
+ QCOMPARE(haystack.contains(needle[0]), resultCS);
+ QCOMPARE(haystack.contains(needle[0], Qt::CaseSensitive), resultCS);
+ QCOMPARE(haystack.contains(needle[0], Qt::CaseInsensitive), resultCIS);
+ }
+}
+
+void tst_QStringApiSymmetry::lastIndexOf_data()
+{
+ QTest::addColumn<QString>("haystackU16");
+ QTest::addColumn<QLatin1String>("haystackL1");
+ QTest::addColumn<QString>("needleU16");
+ QTest::addColumn<QLatin1String>("needleL1");
+ QTest::addColumn<qsizetype>("startpos");
+ QTest::addColumn<qsizetype>("resultCS");
+ QTest::addColumn<qsizetype>("resultCIS");
+
+ constexpr qsizetype zeroPos = 0;
+ constexpr qsizetype minus1Pos = -1;
+
+ QTest::addRow("haystack: null, needle: null") << null << QLatin1String()
+ << null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
+ << null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
+ << null << QLatin1String() << minus1Pos << zeroPos << zeroPos;
+ QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
+ << empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
+ << empty << QLatin1String("") << minus1Pos << zeroPos << zeroPos;
+ QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
+ << empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
+ << a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
+ << a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos;
+
+ QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
+ << null << QLatin1String() << qsizetype(1) << qsizetype(1) << qsizetype(1);
+ QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
+ << empty << QLatin1String("") << qsizetype(1) << qsizetype(1) << qsizetype(1);
+ QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
+ << null << QLatin1String() << qsizetype(2) << minus1Pos << minus1Pos;
+ QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
+ << empty << QLatin1String("") << qsizetype(2) << minus1Pos << minus1Pos;
+
+#define ROW(h, n, st, cs, cis) \
+ QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \
+ << n << QLatin1String(#n) \
+ << qsizetype(st) << qsizetype(cs) << qsizetype(cis)
+
+ ROW(asd, asdf, -1, -1, -1);
+
+ ROW(ABCDEFGHIEfGEFG, G, -1, 14, 14);
+ ROW(ABCDEFGHIEfGEFG, g, -1, -1, 14);
+ ROW(ABCDEFGHIEfGEFG, G, -3, 11, 11);
+ ROW(ABCDEFGHIEfGEFG, g, -3, -1, 11);
+ ROW(ABCDEFGHIEfGEFG, G, -5, 6, 6);
+ ROW(ABCDEFGHIEfGEFG, g, -5, -1, 6);
+ ROW(ABCDEFGHIEfGEFG, G, 14, 14, 14);
+ ROW(ABCDEFGHIEfGEFG, g, 14, -1, 14);
+ ROW(ABCDEFGHIEfGEFG, G, 13, 11, 11);
+ ROW(ABCDEFGHIEfGEFG, g, 13, -1, 11);
+ ROW(ABCDEFGHIEfGEFG, G, 15, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, g, 15, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, B, 14, 1, 1);
+ ROW(ABCDEFGHIEfGEFG, b, 14, -1, 1);
+ ROW(ABCDEFGHIEfGEFG, B, -1, 1, 1);
+ ROW(ABCDEFGHIEfGEFG, b, -1, -1, 1);
+ ROW(ABCDEFGHIEfGEFG, B, 1, 1, 1);
+ ROW(ABCDEFGHIEfGEFG, b, 1, -1, 1);
+ ROW(ABCDEFGHIEfGEFG, B, 0, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, b, 0, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, A, 0, 0, 0);
+ ROW(ABCDEFGHIEfGEFG, a, 0, -1, 0);
+ ROW(ABCDEFGHIEfGEFG, A, -15, 0, 0);
+ ROW(ABCDEFGHIEfGEFG, a, -15, -1, 0);
+
+ ROW(ABCDEFGHIEfGEFG, efg, 0, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, efg, 15, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, efg, -15, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, efg, 14, -1, 12);
+ ROW(ABCDEFGHIEfGEFG, efg, 12, -1, 12);
+ ROW(ABCDEFGHIEfGEFG, efg, -12, -1, -1);
+ ROW(ABCDEFGHIEfGEFG, efg, 11, -1, 9);
+#undef ROW
+}
+
+template <typename Haystack, typename Needle>
+void tst_QStringApiSymmetry::lastIndexOf_impl() const
+{
+ QFETCH(const QString, haystackU16);
+ QFETCH(const QLatin1String, haystackL1);
+ QFETCH(const QString, needleU16);
+ QFETCH(const QLatin1String, needleL1);
+ QFETCH(const qsizetype, startpos);
+ QFETCH(const qsizetype, resultCS);
+ QFETCH(const qsizetype, resultCIS);
+
+ const auto haystackU8 = haystackU16.toUtf8();
+ const auto needleU8 = needleU16.toUtf8();
+
+ const auto haystack = make<Haystack>(QStringRef(&haystackU16), haystackL1, haystackU8);
+ const auto needle = make<Needle>(QStringRef(&needleU16), needleL1, needleU8);
+
+ using size_type = typename Haystack::size_type;
+
+ QCOMPARE(haystack.lastIndexOf(needle, startpos), size_type(resultCS));
+ QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS));
+ QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS));
+
+ if (needle.size() == 1)
+ {
+ QCOMPARE(haystack.lastIndexOf(needle[0], startpos), size_type(resultCS));
+ QCOMPARE(haystack.lastIndexOf(needle[0], startpos, Qt::CaseSensitive), size_type(resultCS));
+ QCOMPARE(haystack.lastIndexOf(needle[0], startpos, Qt::CaseInsensitive), size_type(resultCIS));
+ }
+}
+
QTEST_APPLESS_MAIN(tst_QStringApiSymmetry)
#include "tst_qstringapisymmetry.moc"
diff --git a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
index a3aec4c299..2b5aa8e98b 100644
--- a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
+++ b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
@@ -30,20 +30,26 @@
#include <qregexp.h>
#include <qregularexpression.h>
#include <qstringlist.h>
+#include <qvector.h>
#include <locale.h>
+#include <algorithm>
+
class tst_QStringList : public QObject
{
Q_OBJECT
private slots:
+ void constructors();
void sort();
void filter();
void replaceInStrings();
void removeDuplicates();
void removeDuplicates_data();
void contains();
+ void indexOf_data();
void indexOf();
+ void lastIndexOf_data();
void lastIndexOf();
void indexOf_regExp();
@@ -57,13 +63,44 @@ private slots:
void joinChar() const;
void joinChar_data() const;
-#ifdef Q_COMPILER_INITIALIZER_LISTS
void initializeList() const;
-#endif
};
extern const char email[];
+void tst_QStringList::constructors()
+{
+ {
+ QStringList list;
+ QVERIFY(list.isEmpty());
+ QCOMPARE(list.size(), 0);
+ QVERIFY(list == QStringList());
+ }
+ {
+ QString str = "abc";
+ QStringList list(str);
+ QVERIFY(!list.isEmpty());
+ QCOMPARE(list.size(), 1);
+ QCOMPARE(list.at(0), str);
+ }
+ {
+ QStringList list{ "a", "b", "c" };
+ QVERIFY(!list.isEmpty());
+ QCOMPARE(list.size(), 3);
+ QCOMPARE(list.at(0), "a");
+ QCOMPARE(list.at(1), "b");
+ QCOMPARE(list.at(2), "c");
+ }
+ {
+ const QVector<QString> reference{ "a", "b", "c" };
+ QCOMPARE(reference.size(), 3);
+
+ QStringList list(reference.cbegin(), reference.cend());
+ QCOMPARE(list.size(), reference.size());
+ QVERIFY(std::equal(list.cbegin(), list.cend(), reference.cbegin()));
+ }
+}
+
void tst_QStringList::indexOf_regExp()
{
QStringList list;
@@ -141,20 +178,52 @@ void tst_QStringList::lastIndexOf_regExp()
}
+void tst_QStringList::indexOf_data()
+{
+ QTest::addColumn<QString>("search");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("expectedResult");
+
+ QTest::newRow("harald") << "harald" << 0 << 0;
+ QTest::newRow("trond") << "trond" << 0 << 1;
+ QTest::newRow("vohi") << "vohi" << 0 << 2;
+ QTest::newRow("harald-1") << "harald" << 1 << 3;
+
+ QTest::newRow("hans") << "hans" << 0 << -1;
+ QTest::newRow("trond-1") << "trond" << 2 << -1;
+ QTest::newRow("harald-2") << "harald" << -1 << 3;
+ QTest::newRow("vohi-1") << "vohi" << -3 << 2;
+}
+
void tst_QStringList::indexOf()
{
QStringList list;
list << "harald" << "trond" << "vohi" << "harald";
- QCOMPARE(list.indexOf("harald"), 0);
- QCOMPARE(list.indexOf("trond"), 1);
- QCOMPARE(list.indexOf("vohi"), 2);
- QCOMPARE(list.indexOf("harald", 1), 3);
+ QFETCH(QString, search);
+ QFETCH(int, from);
+ QFETCH(int, expectedResult);
+
+ QCOMPARE(list.indexOf(search, from), expectedResult);
+ QCOMPARE(list.indexOf(QStringView(search), from), expectedResult);
+ QCOMPARE(list.indexOf(QLatin1String(search.toLatin1()), from), expectedResult);
+}
- QCOMPARE(list.indexOf("hans"), -1);
- QCOMPARE(list.indexOf("trond", 2), -1);
- QCOMPARE(list.indexOf("harald", -1), 3);
- QCOMPARE(list.indexOf("vohi", -3), 2);
+void tst_QStringList::lastIndexOf_data()
+{
+ QTest::addColumn<QString>("search");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("expectedResult");
+
+ QTest::newRow("harald") << "harald" << -1 << 3;
+ QTest::newRow("trond") << "trond" << -1 << 1;
+ QTest::newRow("vohi") << "vohi" << -1 << 2;
+ QTest::newRow("harald-1") << "harald" << 2 << 0;
+
+ QTest::newRow("hans") << "hans" << -1 << -1;
+ QTest::newRow("vohi-1") << "vohi" << 1 << -1;
+ QTest::newRow("vohi-2") << "vohi" << -1 << 2;
+ QTest::newRow("vohi-3") << "vohi" << -3 << -1;
}
void tst_QStringList::lastIndexOf()
@@ -162,15 +231,13 @@ void tst_QStringList::lastIndexOf()
QStringList list;
list << "harald" << "trond" << "vohi" << "harald";
- QCOMPARE(list.lastIndexOf("harald"), 3);
- QCOMPARE(list.lastIndexOf("trond"), 1);
- QCOMPARE(list.lastIndexOf("vohi"), 2);
- QCOMPARE(list.lastIndexOf("harald", 2), 0);
+ QFETCH(QString, search);
+ QFETCH(int, from);
+ QFETCH(int, expectedResult);
- QCOMPARE(list.lastIndexOf("hans"), -1);
- QCOMPARE(list.lastIndexOf("vohi", 1), -1);
- QCOMPARE(list.lastIndexOf("vohi", -1), 2);
- QCOMPARE(list.lastIndexOf("vohi", -3), -1);
+ QCOMPARE(list.lastIndexOf(search, from), expectedResult);
+ QCOMPARE(list.lastIndexOf(QStringView(search), from), expectedResult);
+ QCOMPARE(list.lastIndexOf(QLatin1String(search.toLatin1()), from), expectedResult);
}
void tst_QStringList::filter()
@@ -450,8 +517,6 @@ void tst_QStringList::joinEmptiness() const
QVERIFY(string.isNull());
}
-#ifdef Q_COMPILER_INITIALIZER_LISTS
-// C++0x support is required
void tst_QStringList::initializeList() const
{
@@ -459,7 +524,6 @@ void tst_QStringList::initializeList() const
QCOMPARE(v1, (QStringList() << "hello" << "world" << "plop"));
QCOMPARE(v1, (QStringList{"hello","world","plop"}));
}
-#endif
QTEST_APPLESS_MAIN(tst_QStringList)
#include "tst_qstringlist.moc"
diff --git a/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp b/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp
index 8a55f54449..2d577bb0ab 100644
--- a/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp
+++ b/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp
@@ -100,6 +100,11 @@ void tst_QStringMatcher::indexIn()
matcher.setPattern(needle);
QCOMPARE(matcher.indexIn(haystack, from), indexIn);
+
+ const auto needleSV = QStringView(needle);
+ QStringMatcher matcherSV(needleSV);
+
+ QCOMPARE(matcherSV.indexIn(QStringView(haystack), from), indexIn);
}
void tst_QStringMatcher::setCaseSensitivity_data()
@@ -128,6 +133,7 @@ void tst_QStringMatcher::setCaseSensitivity()
matcher.setCaseSensitivity(static_cast<Qt::CaseSensitivity> (cs));
QCOMPARE(matcher.indexIn(haystack, from), indexIn);
+ QCOMPARE(matcher.indexIn(QStringView(haystack), from), indexIn);
}
void tst_QStringMatcher::assignOperator()
diff --git a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
index e800a0d794..794f39708a 100644
--- a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
+++ b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
@@ -134,6 +134,8 @@ private Q_SLOTS:
void literals() const;
void at() const;
+ void arg() const;
+
void fromQString() const;
void fromQStringRef() const;
@@ -425,6 +427,47 @@ void tst_QStringView::at() const
QCOMPARE(sv.at(4), QChar('o')); QCOMPARE(sv[4], QChar('o'));
}
+void tst_QStringView::arg() const
+{
+#define CHECK1(pattern, arg1, expected) \
+ do { \
+ auto p = QStringViewLiteral(pattern); \
+ QCOMPARE(p.arg(QLatin1String(arg1)), expected); \
+ QCOMPARE(p.arg(QStringViewLiteral(arg1)), expected); \
+ QCOMPARE(p.arg(QStringLiteral(arg1)), expected); \
+ QCOMPARE(p.arg(QString(QLatin1String(arg1))), expected); \
+ } while (false) \
+ /*end*/
+#define CHECK2(pattern, arg1, arg2, expected) \
+ do { \
+ auto p = QStringViewLiteral(pattern); \
+ QCOMPARE(p.arg(QLatin1String(arg1), QLatin1String(arg2)), expected); \
+ QCOMPARE(p.arg(QStringViewLiteral(arg1), QLatin1String(arg2)), expected); \
+ QCOMPARE(p.arg(QLatin1String(arg1), QStringViewLiteral(arg2)), expected); \
+ QCOMPARE(p.arg(QStringViewLiteral(arg1), QStringViewLiteral(arg2)), expected); \
+ } while (false) \
+ /*end*/
+
+ CHECK1("", "World", "");
+ CHECK1("%1", "World", "World");
+ CHECK1("!%1?", "World", "!World?");
+ CHECK1("%1%1", "World", "WorldWorld");
+ CHECK1("%1%2", "World", "World%2");
+ CHECK1("%2%1", "World", "%2World");
+
+ CHECK2("", "Hello", "World", "");
+ CHECK2("%1", "Hello", "World", "Hello");
+ CHECK2("!%1, %2?", "Hello", "World", "!Hello, World?");
+ CHECK2("%1%1", "Hello", "World", "HelloHello");
+ CHECK2("%1%2", "Hello", "World", "HelloWorld");
+ CHECK2("%2%1", "Hello", "World", "WorldHello");
+
+#undef CHECK2
+#undef CHECK1
+
+ QCOMPARE(QStringViewLiteral(" %2 %2 %1 %3 ").arg(QLatin1Char('c'), QChar::CarriageReturn, u'C'), " \r \r c C ");
+}
+
void tst_QStringView::fromQString() const
{
QString null;
diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
index 5737db760c..fff8c75a90 100644
--- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
+++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
@@ -908,7 +908,6 @@ void tst_QVarLengthArray::initializeListComplex()
template<typename T>
void tst_QVarLengthArray::initializeList()
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
T val1(110);
T val2(105);
T val3(101);
@@ -945,9 +944,6 @@ void tst_QVarLengthArray::initializeList()
v6 = {}; // assign empty
QCOMPARE(v6.size(), 0);
-#else
- QSKIP("This tests requires a compiler that supports initializer lists.");
-#endif
}
void tst_QVarLengthArray::insertMove()
diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
index a7faeb5ca5..3256130472 100644
--- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp
+++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
@@ -206,6 +206,9 @@ private slots:
void assignmentInt() const;
void assignmentMovable() const;
void assignmentCustom() const;
+ void assignFromInitializerListInt() const;
+ void assignFromInitializerListMovable() const;
+ void assignFromInitializerListCustom() const;
void addInt() const;
void addMovable() const;
void addCustom() const;
@@ -254,7 +257,6 @@ private slots:
void fromListInt() const;
void fromListMovable() const;
void fromListCustom() const;
- void fromStdVector() const;
void indexOf() const;
void insertInt() const;
void insertMovable() const;
@@ -293,7 +295,10 @@ private slots:
void swapMovable() const;
void swapCustom() const;
void toList() const;
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ void fromStdVector() const;
void toStdVector() const;
+#endif
void value() const;
void testOperators() const;
@@ -326,10 +331,13 @@ private slots:
void insertMove() const;
+ void swapItemsAt() const;
+
private:
template<typename T> void copyConstructor() const;
template<typename T> void add() const;
template<typename T> void append() const;
+ template<typename T> void assignFromInitializerList() const;
template<typename T> void capacity() const;
template<typename T> void clear() const;
template<typename T> void count() const;
@@ -543,6 +551,40 @@ void tst_QVector::assignmentCustom() const
}
template<typename T>
+void tst_QVector::assignFromInitializerList() const
+{
+ T val1(SimpleValue<T>::at(1));
+ T val2(SimpleValue<T>::at(2));
+ T val3(SimpleValue<T>::at(3));
+
+ QVector<T> v1 = {val1, val2, val3};
+ QCOMPARE(v1, QVector<T>() << val1 << val2 << val3);
+ QCOMPARE(v1, (QVector<T> {val1, val2, val3}));
+
+ v1 = {};
+ QCOMPARE(v1.size(), 0);
+}
+
+void tst_QVector::assignFromInitializerListInt() const
+{
+ assignFromInitializerList<int>();
+}
+
+void tst_QVector::assignFromInitializerListMovable() const
+{
+ const int instancesCount = Movable::counter.loadAcquire();
+ assignFromInitializerList<Movable>();
+ QCOMPARE(instancesCount, Movable::counter.loadAcquire());
+}
+
+void tst_QVector::assignFromInitializerListCustom() const
+{
+ const int instancesCount = Custom::counter.loadAcquire();
+ assignFromInitializerList<Custom>();
+ QCOMPARE(instancesCount, Custom::counter.loadAcquire());
+}
+
+template<typename T>
void tst_QVector::add() const
{
{
@@ -667,7 +709,6 @@ void tst_QVector::appendCustom() const
void tst_QVector::appendRvalue() const
{
-#ifdef Q_COMPILER_RVALUE_REFS
QVector<QString> v;
v.append("hello");
QString world = "world";
@@ -675,9 +716,6 @@ void tst_QVector::appendRvalue() const
QVERIFY(world.isEmpty());
QCOMPARE(v.front(), QString("hello"));
QCOMPARE(v.back(), QString("world"));
-#else
- QSKIP("This test requires that C++11 move semantics support is enabled in the compiler");
-#endif
}
void tst_QVector::at() const
@@ -1392,6 +1430,7 @@ void tst_QVector::fromListCustom() const
QCOMPARE(instancesCount, Custom::counter.loadAcquire());
}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
void tst_QVector::fromStdVector() const
{
// stl = :(
@@ -1405,6 +1444,7 @@ void tst_QVector::fromStdVector() const
// test it converts ok
QCOMPARE(myvec, QVector<QString>() << "aaa" << "bbb" << "ninjas" << "pirates");
}
+#endif
void tst_QVector::indexOf() const
{
@@ -2297,6 +2337,7 @@ void tst_QVector::toList() const
QCOMPARE(myvec, QVector<QString>() << "A" << "B" << "C");
}
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
void tst_QVector::toStdVector() const
{
QVector<QString> myvec;
@@ -2309,6 +2350,7 @@ void tst_QVector::toStdVector() const
QCOMPARE(myvec, QVector<QString>() << "A" << "B" << "C");
}
+#endif
void tst_QVector::value() const
{
@@ -2515,7 +2557,6 @@ void tst_QVector::reallocAfterCopy()
template<typename T>
void tst_QVector::initializeList()
{
-#ifdef Q_COMPILER_INITIALIZER_LISTS
T val1(SimpleValue<T>::at(1));
T val2(SimpleValue<T>::at(2));
T val3(SimpleValue<T>::at(3));
@@ -2532,7 +2573,6 @@ void tst_QVector::initializeList()
QVector<T> v4({});
QCOMPARE(v4.size(), 0);
-#endif
}
void tst_QVector::initializeListInt()
@@ -2842,7 +2882,7 @@ void tst_QVector::detachThreadSafety() const
struct : QThread {
void run() override
{
- QVector<T> copy(*detachThreadSafetyData<T>()->load());
+ QVector<T> copy(*detachThreadSafetyData<T>()->loadRelaxed());
QVERIFY(!copy.isDetached());
detachThreadSafetyLock.release();
detachThreadSafetyLock.acquire(100);
@@ -2952,5 +2992,22 @@ void tst_QVector::insertMove() const
QCOMPARE(Movable::counter.loadAcquire(), instancesCount);
}
+void tst_QVector::swapItemsAt() const
+{
+ QVector<int> v;
+ v << 0 << 1 << 2 << 3;
+
+ v.swapItemsAt(0, 2);
+ QCOMPARE(v.at(0), 2);
+ QCOMPARE(v.at(2), 0);
+
+ auto copy = v;
+ copy.swapItemsAt(0, 2);
+ QCOMPARE(v.at(0), 2);
+ QCOMPARE(v.at(2), 0);
+ QCOMPARE(copy.at(0), 0);
+ QCOMPARE(copy.at(2), 2);
+}
+
QTEST_MAIN(tst_QVector)
#include "tst_qvector.moc"
diff --git a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
index 05579dce6e..7c4d1071ce 100644
--- a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
+++ b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
@@ -260,12 +260,10 @@ void tst_QVersionNumber::constructorExplicit()
QCOMPARE(v5.segments(), v6.segments());
-#ifdef Q_COMPILER_INITIALIZER_LISTS
QVersionNumber v7(4, 5, 6);
QVersionNumber v8 = {4, 5, 6};
QCOMPARE(v7.segments(), v8.segments());
-#endif
}
void tst_QVersionNumber::constructorCopy_data()
@@ -436,7 +434,7 @@ void tst_QVersionNumber::normalized()
QFETCH(QVersionNumber, expected);
QCOMPARE(version.normalized(), expected);
- QCOMPARE(qMove(version).normalized(), expected);
+ QCOMPARE(std::move(version).normalized(), expected);
}
void tst_QVersionNumber::isNormalized_data()
@@ -586,30 +584,28 @@ void tst_QVersionNumber::serialize()
void tst_QVersionNumber::moveSemantics()
{
-#ifdef Q_COMPILER_RVALUE_REFS
// QVersionNumber(QVersionNumber &&)
{
QVersionNumber v1(1, 2, 3);
- QVersionNumber v2 = qMove(v1);
+ QVersionNumber v2 = std::move(v1);
QCOMPARE(v2, QVersionNumber(1, 2, 3));
}
// QVersionNumber &operator=(QVersionNumber &&)
{
QVersionNumber v1(1, 2, 3);
QVersionNumber v2;
- v2 = qMove(v1);
+ v2 = std::move(v1);
QCOMPARE(v2, QVersionNumber(1, 2, 3));
}
// QVersionNumber(QVector<int> &&)
{
QVector<int> segments = QVector<int>() << 1 << 2 << 3;
QVersionNumber v1(segments);
- QVersionNumber v2(qMove(segments));
+ QVersionNumber v2(std::move(segments));
QVERIFY(!v1.isNull());
QVERIFY(!v2.isNull());
QCOMPARE(v1, v2);
}
-#endif
#ifdef Q_COMPILER_REF_QUALIFIERS
// normalized()
{
@@ -620,7 +616,7 @@ void tst_QVersionNumber::moveSemantics()
QVERIFY(!v.isNull());
QVERIFY(!nv.isNull());
QVERIFY(nv.isNormalized());
- nv = qMove(v).normalized();
+ nv = std::move(v).normalized();
QVERIFY(!nv.isNull());
QVERIFY(nv.isNormalized());
}
@@ -632,13 +628,10 @@ void tst_QVersionNumber::moveSemantics()
segments = v.segments();
QVERIFY(!v.isNull());
QVERIFY(!segments.empty());
- segments = qMove(v).segments();
+ segments = std::move(v).segments();
QVERIFY(!segments.empty());
}
#endif
-#if !defined(Q_COMPILER_RVALUE_REFS) && !defined(Q_COMPILER_REF_QUALIFIERS)
- QSKIP("This test requires C++11 move semantics support in the compiler.");
-#endif
}
void tst_QVersionNumber::qtVersion()
diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro
index f28cf21b8b..243e7e96f5 100644
--- a/tests/auto/corelib/tools/tools.pro
+++ b/tests/auto/corelib/tools/tools.pro
@@ -16,8 +16,6 @@ SUBDIRS=\
qcommandlineparser \
qcontiguouscache \
qcryptographichash \
- qdate \
- qdatetime \
qeasingcurve \
qexplicitlyshareddatapointer \
qfreelist \
@@ -35,6 +33,7 @@ SUBDIRS=\
qmap_strictiterators \
qmargins \
qmessageauthenticationcode \
+ qoffsetstringarray \
qpair \
qpoint \
qpointf \
@@ -45,6 +44,7 @@ SUBDIRS=\
qringbuffer \
qscopedpointer \
qscopedvaluerollback \
+ qscopeguard \
qset \
qsharedpointer \
qsize \
@@ -60,8 +60,6 @@ SUBDIRS=\
qstringref \
qstringview \
qtextboundaryfinder \
- qtime \
- qtimezone \
qtimeline \
qvarlengtharray \
qvector \
diff --git a/tests/auto/dbus/qdbusservicewatcher/tst_qdbusservicewatcher.cpp b/tests/auto/dbus/qdbusservicewatcher/tst_qdbusservicewatcher.cpp
index b79f3ea5e3..1ba7ee51b1 100644
--- a/tests/auto/dbus/qdbusservicewatcher/tst_qdbusservicewatcher.cpp
+++ b/tests/auto/dbus/qdbusservicewatcher/tst_qdbusservicewatcher.cpp
@@ -34,22 +34,27 @@
class tst_QDBusServiceWatcher: public QObject
{
Q_OBJECT
- QString serviceName;
int testCounter;
public:
tst_QDBusServiceWatcher();
private slots:
void initTestCase();
- void init();
-
+ void watchForCreation_data();
void watchForCreation();
+ void watchForDisappearance_data();
void watchForDisappearance();
void watchForDisappearanceUniqueConnection();
+ void watchForOwnerChange_data();
void watchForOwnerChange();
+ void modeChange_data();
void modeChange();
void disconnectedConnection();
+ void setConnection_data();
void setConnection();
+
+private:
+ QString generateServiceName();
};
tst_QDBusServiceWatcher::tst_QDBusServiceWatcher()
@@ -63,18 +68,45 @@ void tst_QDBusServiceWatcher::initTestCase()
QVERIFY(con.isConnected());
}
-void tst_QDBusServiceWatcher::init()
+QString tst_QDBusServiceWatcher::generateServiceName() {
+ return "com.example.TestService" + QString::number(testCounter++);
+}
+
+void tst_QDBusServiceWatcher::watchForCreation_data()
{
- // change the service name from test to test
- serviceName = "com.example.TestService" + QString::number(testCounter++);
+ QTest::addColumn<QString>("watchedName");
+ QTest::addColumn<QString>("registeredName");
+
+ //com.example.TestService5 matches com.example.TestService5
+ QString name = generateServiceName();
+ QTest::newRow("normal") << name << name;
+
+ //com.example* matches com.example.TestService5
+ name = generateServiceName();
+ QTest::newRow("wildcard") << "com.example*" << name;
+
+ //com.example.TestService5* matches com.example.TestService5
+ name = generateServiceName();
+ QTest::newRow("wildcard_exact") << name+"*" << name;
+
+ //com.example.TestService5* matches com.example.TestService5.Foo
+ name = generateServiceName();
+ QTest::newRow("wildcard_subdomain") << name+"*" << name + ".Foo";
+
+ //com.example.TestService5* matches com.example.TestService5.Foo.Bar
+ name = generateServiceName();
+ QTest::newRow("wildcard_subsubdomain") << name+"*" << name + ".Foo.Bar";
}
void tst_QDBusServiceWatcher::watchForCreation()
{
+ QFETCH(QString, watchedName);
+ QFETCH(QString, registeredName);
+
QDBusConnection con = QDBusConnection::sessionBus();
QVERIFY(con.isConnected());
- QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration);
+ QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForRegistration);
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
@@ -82,18 +114,18 @@ void tst_QDBusServiceWatcher::watchForCreation()
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop()));
// register a name
- QVERIFY(con.registerService(serviceName));
+ QVERIFY(con.registerService(registeredName));
QTestEventLoop::instance().enterLoop(1);
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(spyR.count(), 1);
- QCOMPARE(spyR.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyR.at(0).at(0).toString(), registeredName);
QCOMPARE(spyU.count(), 0);
QCOMPARE(spyO.count(), 1);
- QCOMPARE(spyO.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyO.at(0).at(0).toString(), registeredName);
QVERIFY(spyO.at(0).at(1).toString().isEmpty());
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
@@ -102,31 +134,39 @@ void tst_QDBusServiceWatcher::watchForCreation()
spyO.clear();
// unregister it:
- con.unregisterService(serviceName);
+ con.unregisterService(registeredName);
// and register again
- QVERIFY(con.registerService(serviceName));
+ QVERIFY(con.registerService(registeredName));
QTestEventLoop::instance().enterLoop(1);
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(spyR.count(), 1);
- QCOMPARE(spyR.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyR.at(0).at(0).toString(), registeredName);
QCOMPARE(spyU.count(), 0);
QCOMPARE(spyO.count(), 1);
- QCOMPARE(spyO.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyO.at(0).at(0).toString(), registeredName);
QVERIFY(spyO.at(0).at(1).toString().isEmpty());
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
}
+void tst_QDBusServiceWatcher::watchForDisappearance_data()
+{
+ tst_QDBusServiceWatcher::watchForCreation_data();
+}
+
void tst_QDBusServiceWatcher::watchForDisappearance()
{
+ QFETCH(QString, watchedName);
+ QFETCH(QString, registeredName);
+
QDBusConnection con = QDBusConnection::sessionBus();
QVERIFY(con.isConnected());
- QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForUnregistration);
+ QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForUnregistration);
watcher.setObjectName("watcher for disappearance");
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
@@ -135,10 +175,10 @@ void tst_QDBusServiceWatcher::watchForDisappearance()
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop()));
// register a name
- QVERIFY(con.registerService(serviceName));
+ QVERIFY(con.registerService(registeredName));
// unregister it:
- con.unregisterService(serviceName);
+ con.unregisterService(registeredName);
QTestEventLoop::instance().enterLoop(1);
QVERIFY(!QTestEventLoop::instance().timeout());
@@ -146,10 +186,10 @@ void tst_QDBusServiceWatcher::watchForDisappearance()
QCOMPARE(spyR.count(), 0);
QCOMPARE(spyU.count(), 1);
- QCOMPARE(spyU.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyU.at(0).at(0).toString(), registeredName);
QCOMPARE(spyO.count(), 1);
- QCOMPARE(spyO.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyO.at(0).at(0).toString(), registeredName);
QCOMPARE(spyO.at(0).at(1).toString(), con.baseService());
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
}
@@ -188,12 +228,20 @@ void tst_QDBusServiceWatcher::watchForDisappearanceUniqueConnection()
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
}
+void tst_QDBusServiceWatcher::watchForOwnerChange_data()
+{
+ watchForCreation_data();
+}
+
void tst_QDBusServiceWatcher::watchForOwnerChange()
{
+ QFETCH(QString, watchedName);
+ QFETCH(QString, registeredName);
+
QDBusConnection con = QDBusConnection::sessionBus();
QVERIFY(con.isConnected());
- QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForOwnerChange);
+ QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForOwnerChange);
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
@@ -201,18 +249,18 @@ void tst_QDBusServiceWatcher::watchForOwnerChange()
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop()));
// register a name
- QVERIFY(con.registerService(serviceName));
+ QVERIFY(con.registerService(registeredName));
QTestEventLoop::instance().enterLoop(1);
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(spyR.count(), 1);
- QCOMPARE(spyR.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyR.at(0).at(0).toString(), registeredName);
QCOMPARE(spyU.count(), 0);
QCOMPARE(spyO.count(), 1);
- QCOMPARE(spyO.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyO.at(0).at(0).toString(), registeredName);
QVERIFY(spyO.at(0).at(1).toString().isEmpty());
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
@@ -221,35 +269,43 @@ void tst_QDBusServiceWatcher::watchForOwnerChange()
spyO.clear();
// unregister it:
- con.unregisterService(serviceName);
+ con.unregisterService(registeredName);
// and register again
- QVERIFY(con.registerService(serviceName));
+ QVERIFY(con.registerService(registeredName));
QTestEventLoop::instance().enterLoop(1);
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(spyR.count(), 1);
- QCOMPARE(spyR.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyR.at(0).at(0).toString(), registeredName);
QCOMPARE(spyU.count(), 1);
- QCOMPARE(spyU.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyU.at(0).at(0).toString(), registeredName);
QCOMPARE(spyO.count(), 2);
- QCOMPARE(spyO.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyO.at(0).at(0).toString(), registeredName);
QCOMPARE(spyO.at(0).at(1).toString(), con.baseService());
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
- QCOMPARE(spyO.at(1).at(0).toString(), serviceName);
+ QCOMPARE(spyO.at(1).at(0).toString(), registeredName);
QVERIFY(spyO.at(1).at(1).toString().isEmpty());
QCOMPARE(spyO.at(1).at(2).toString(), con.baseService());
}
+void tst_QDBusServiceWatcher::modeChange_data()
+{
+ watchForCreation_data();
+}
+
void tst_QDBusServiceWatcher::modeChange()
{
+ QFETCH(QString, watchedName);
+ QFETCH(QString, registeredName);
+
QDBusConnection con = QDBusConnection::sessionBus();
QVERIFY(con.isConnected());
- QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration);
+ QDBusServiceWatcher watcher(watchedName, con, QDBusServiceWatcher::WatchForRegistration);
QSignalSpy spyR(&watcher, SIGNAL(serviceRegistered(QString)));
QSignalSpy spyU(&watcher, SIGNAL(serviceUnregistered(QString)));
@@ -257,18 +313,18 @@ void tst_QDBusServiceWatcher::modeChange()
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceRegistered(QString)), SLOT(exitLoop()));
// register a name
- QVERIFY(con.registerService(serviceName));
+ QVERIFY(con.registerService(registeredName));
QTestEventLoop::instance().enterLoop(1);
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(spyR.count(), 1);
- QCOMPARE(spyR.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyR.at(0).at(0).toString(), registeredName);
QCOMPARE(spyU.count(), 0);
QCOMPARE(spyO.count(), 1);
- QCOMPARE(spyO.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyO.at(0).at(0).toString(), registeredName);
QVERIFY(spyO.at(0).at(1).toString().isEmpty());
QCOMPARE(spyO.at(0).at(2).toString(), con.baseService());
@@ -279,7 +335,7 @@ void tst_QDBusServiceWatcher::modeChange()
watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
// unregister it:
- con.unregisterService(serviceName);
+ con.unregisterService(registeredName);
QTestEventLoop::instance().connect(&watcher, SIGNAL(serviceUnregistered(QString)), SLOT(exitLoop()));
QTestEventLoop::instance().enterLoop(1);
@@ -288,10 +344,10 @@ void tst_QDBusServiceWatcher::modeChange()
QCOMPARE(spyR.count(), 0);
QCOMPARE(spyU.count(), 1);
- QCOMPARE(spyU.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyU.at(0).at(0).toString(), registeredName);
QCOMPARE(spyO.count(), 1);
- QCOMPARE(spyO.at(0).at(0).toString(), serviceName);
+ QCOMPARE(spyO.at(0).at(0).toString(), registeredName);
QCOMPARE(spyO.at(0).at(1).toString(), con.baseService());
QVERIFY(spyO.at(0).at(2).toString().isEmpty());
}
@@ -301,7 +357,7 @@ void tst_QDBusServiceWatcher::disconnectedConnection()
QDBusConnection con("");
QVERIFY(!con.isConnected());
- QDBusServiceWatcher watcher(serviceName, con, QDBusServiceWatcher::WatchForRegistration);
+ QDBusServiceWatcher watcher(generateServiceName(), con, QDBusServiceWatcher::WatchForRegistration);
watcher.addWatchedService("com.example.somethingelse");
watcher.addWatchedService("org.freedesktop.DBus");
@@ -311,8 +367,15 @@ void tst_QDBusServiceWatcher::disconnectedConnection()
watcher.setWatchedServices(QStringList());
}
+void tst_QDBusServiceWatcher::setConnection_data()
+{
+ QTest::addColumn<QString>("serviceName");
+ QTest::newRow("normal") << generateServiceName();
+}
+
void tst_QDBusServiceWatcher::setConnection()
{
+ QFETCH(QString, serviceName);
// begin with a disconnected connection
QDBusConnection con("");
QVERIFY(!con.isConnected());
diff --git a/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp b/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp
index 018b7c2a35..b4690268c8 100644
--- a/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp
+++ b/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp
@@ -197,8 +197,8 @@ tst_QDBusThreading::tst_QDBusThreading()
void tst_QDBusThreading::joinThreads()
{
- threadJoin.acquire(threadJoinCount.load());
- threadJoinCount.store(0);
+ threadJoin.acquire(threadJoinCount.loadRelaxed());
+ threadJoinCount.storeRelaxed(0);
}
bool tst_QDBusThreading::waitForSignal(QObject *obj, const char *signal, int delay)
diff --git a/tests/auto/gui/gui.pro b/tests/auto/gui/gui.pro
index e0c8123f26..c90fc48251 100644
--- a/tests/auto/gui/gui.pro
+++ b/tests/auto/gui/gui.pro
@@ -13,6 +13,7 @@ SUBDIRS = \
text \
util \
itemmodels \
+ rhi
!qtConfig(opengl)|winrt: SUBDIRS -= qopengl qopenglconfig
diff --git a/tests/auto/gui/image/qimage/qimage.pro b/tests/auto/gui/image/qimage/qimage.pro
index b40866892e..0593cfbc23 100644
--- a/tests/auto/gui/image/qimage/qimage.pro
+++ b/tests/auto/gui/image/qimage/qimage.pro
@@ -7,7 +7,7 @@ qtConfig(c++11): CONFIG += c++11
android:!android-embedded: RESOURCES += qimage.qrc
-win32:!winrt: LIBS += -lgdi32 -luser32
+win32:!winrt: QMAKE_USE += user32 gdi32
darwin: LIBS += -framework CoreGraphics
TESTDATA += images/*
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index bb81b9f61f..441ec17412 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -301,6 +301,8 @@ static QLatin1String formatToString(QImage::Format format)
return QLatin1String("RGBA64");
case QImage::Format_RGBA64_Premultiplied:
return QLatin1String("RGBA64pm");
+ case QImage::Format_Grayscale16:
+ return QLatin1String("Grayscale16");
default:
break;
};
@@ -1850,7 +1852,9 @@ void tst_QImage::smoothScale4_data()
QTest::addColumn<QImage::Format>("format");
QTest::newRow("RGB32") << QImage::Format_RGB32;
+#if QT_CONFIG(raster_64bit)
QTest::newRow("RGBx64") << QImage::Format_RGBX64;
+#endif
}
void tst_QImage::smoothScale4()
@@ -2369,8 +2373,11 @@ void tst_QImage::rgbSwapped_data()
QTest::addColumn<QImage::Format>("format");
for (int i = QImage::Format_Indexed8; i < QImage::NImageFormats; ++i) {
- if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
+ if (i == QImage::Format_Alpha8
+ || i == QImage::Format_Grayscale8
+ || i == QImage::Format_Grayscale16) {
continue;
+ }
QTest::addRow("%s", formatToString(QImage::Format(i)).data()) << QImage::Format(i);
}
}
@@ -2615,8 +2622,11 @@ void tst_QImage::inplaceMirrored_data()
QTest::addColumn<bool>("swap_horizontal");
for (int i = QImage::Format_Mono; i < QImage::NImageFormats; ++i) {
- if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
+ if (i == QImage::Format_Alpha8
+ || i == QImage::Format_Grayscale8
+ || i == QImage::Format_Grayscale16) {
continue;
+ }
if (i == QImage::Format_RGB444 || i == QImage::Format_ARGB4444_Premultiplied)
continue;
const auto fmt = formatToString(QImage::Format(i));
@@ -2788,11 +2798,11 @@ void tst_QImage::genericRgbConversion_data()
QTest::addColumn<QImage::Format>("dest_format");
for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) {
- if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
+ if (i == QImage::Format_Alpha8)
continue;
const QLatin1String formatI = formatToString(QImage::Format(i));
for (int j = QImage::Format_RGB32; j < QImage::NImageFormats; ++j) {
- if (j == QImage::Format_Alpha8 || j == QImage::Format_Grayscale8)
+ if (j == QImage::Format_Alpha8)
continue;
if (i == j)
continue;
@@ -2808,6 +2818,9 @@ void tst_QImage::genericRgbConversion()
QFETCH(QImage::Format, format);
QFETCH(QImage::Format, dest_format);
+ bool srcGrayscale = format == QImage::Format_Grayscale8 || format == QImage::Format_Grayscale16;
+ bool dstGrayscale = dest_format == QImage::Format_Grayscale8 || dest_format == QImage::Format_Grayscale16;
+
QImage image(16, 16, format);
for (int i = 0; i < image.height(); ++i)
@@ -2819,8 +2832,12 @@ void tst_QImage::genericRgbConversion()
for (int i = 0; i < imageConverted.height(); ++i) {
for (int j = 0; j < imageConverted.width(); ++j) {
QRgb convertedColor = imageConverted.pixel(j,i);
- QCOMPARE(qRed(convertedColor) & 0xF0, j * 16);
- QCOMPARE(qGreen(convertedColor) & 0xF0, i * 16);
+ if (srcGrayscale || dstGrayscale) {
+ QVERIFY(qAbs(qGray(convertedColor) - qGray(qRgb(j*16, i*16, 0))) < 15);
+ } else {
+ QCOMPARE(qRed(convertedColor) & 0xF0, j * 16);
+ QCOMPARE(qGreen(convertedColor) & 0xF0, i * 16);
+ }
}
}
}
@@ -2831,11 +2848,17 @@ void tst_QImage::inplaceRgbConversion_data()
QTest::addColumn<QImage::Format>("dest_format");
for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) {
- if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
+ if (i == QImage::Format_Alpha8
+ || i == QImage::Format_Grayscale8
+ || i == QImage::Format_Grayscale16) {
continue;
+ }
for (int j = QImage::Format_RGB32; j < QImage::NImageFormats; ++j) {
- if (j == QImage::Format_Alpha8 || j == QImage::Format_Grayscale8)
+ if (j == QImage::Format_Alpha8
+ || j == QImage::Format_Grayscale8
+ || j == QImage::Format_Grayscale16) {
continue;
+ }
if (i == j)
continue;
QTest::addRow("%s -> %s", formatToString(QImage::Format(i)).data(), formatToString(QImage::Format(j)).data())
@@ -3005,8 +3028,11 @@ void tst_QImage::invertPixelsRGB_data()
QTest::addColumn<QImage::Format>("image_format");
for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) {
- if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
+ if (i == QImage::Format_Alpha8
+ || i == QImage::Format_Grayscale8
+ || i == QImage::Format_Grayscale16) {
continue;
+ }
QTest::addRow("%s", formatToString(QImage::Format(i)).data()) << QImage::Format(i);
}
}
@@ -3379,7 +3405,7 @@ void tst_QImage::ditherGradient_data()
QTest::newRow("rgb32 -> rgb666 (dithering)") << rgb32 << QImage::Format_RGB666 << int(Qt::PreferDither | Qt::OrderedDither) << 129;
// Test we get the same results for opaque input in the ARGBPM implementation.
- rgb32 = qMove(rgb32).convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ rgb32 = std::move(rgb32).convertToFormat(QImage::Format_ARGB32_Premultiplied);
QTest::newRow("argb32pm -> argb4444pm (no dither)") << rgb32 << QImage::Format_ARGB4444_Premultiplied << 0 << 16;
QTest::newRow("argb32pm -> rgb444 (dithering)") << rgb32 << QImage::Format_RGB444 << int(Qt::PreferDither | Qt::OrderedDither) << 33;
QTest::newRow("argb32pm -> argb4444pm (dithering)") << rgb32 << QImage::Format_ARGB4444_Premultiplied << int(Qt::PreferDither | Qt::OrderedDither) << 33;
@@ -3388,6 +3414,7 @@ void tst_QImage::ditherGradient_data()
QTest::newRow("argb32pm -> argb6666pm (no dither)") << rgb32 << QImage::Format_ARGB6666_Premultiplied << 0 << 64;
QTest::newRow("argb32pm -> argb6666pm (dithering)") << rgb32 << QImage::Format_ARGB6666_Premultiplied << int(Qt::PreferDither | Qt::OrderedDither) << 129;
+#if QT_CONFIG(raster_64bit)
QImage rgb30(1024, 16, QImage::Format_RGB30);
QLinearGradient gradient30(QRectF(rgb30.rect()).topLeft(), QRectF(rgb30.rect()).topRight());
gradient30.setColorAt(0.0, QColor(0, 0, 0));
@@ -3400,6 +3427,7 @@ void tst_QImage::ditherGradient_data()
QTest::newRow("rgb30 -> rgb32 (dithering)") << rgb30 << QImage::Format_RGB32 << int(Qt::PreferDither | Qt::OrderedDither) << 513;
QTest::newRow("rgb30 -> rgb888 (no dither)") << rgb30 << QImage::Format_RGB888 << 0 << 256;
QTest::newRow("rgb30 -> rgb888 (dithering)") << rgb30 << QImage::Format_RGB888 << int(Qt::PreferDither | Qt::OrderedDither) << 513;
+#endif
}
void tst_QImage::ditherGradient()
diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
index 1eee2f273e..d17a171728 100644
--- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
+++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
@@ -528,7 +528,7 @@ void tst_QImageReader::imageFormat_data()
QTest::newRow("png") << QString("kollada.png") << QByteArray("png") << QImage::Format_ARGB32;
QTest::newRow("png-2") << QString("YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32;
QTest::newRow("png-3") << QString("kollada-16bpc.png") << QByteArray("png") << QImage::Format_RGBA64;
- QTest::newRow("png-4") << QString("basn0g16.png") << QByteArray("png") << QImage::Format_RGBX64; // Grayscale16
+ QTest::newRow("png-4") << QString("basn0g16.png") << QByteArray("png") << QImage::Format_Grayscale16;
QTest::newRow("png-5") << QString("basn2c16.png") << QByteArray("png") << QImage::Format_RGBX64;
QTest::newRow("png-6") << QString("basn4a16.png") << QByteArray("png") << QImage::Format_RGBA64; // Grayscale16Alpha16
QTest::newRow("png-7") << QString("basn6a16.png") << QByteArray("png") << QImage::Format_RGBA64;
diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
index 77851cd7d0..aaa8475c74 100644
--- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
+++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
@@ -239,7 +239,7 @@ void tst_QImageWriter::writeImage2_data()
// QLatin1String("jpeg"),
};
- QImage image0(70, 70, QImage::Format_ARGB32);
+ QImage image0(70, 70, QImage::Format_RGB32);
image0.fill(QColor(Qt::red).rgb());
QImage::Format imgFormat = QImage::Format_Mono;
@@ -304,10 +304,10 @@ void tst_QImageWriter::writeImage2()
if (!equalImageContents(written, image)) {
qDebug() << "image" << image.format() << image.width()
<< image.height() << image.depth()
- << hex << image.pixel(0, 0);
+ << image.pixelColor(0, 0);
qDebug() << "written" << written.format() << written.width()
<< written.height() << written.depth()
- << hex << written.pixel(0, 0);
+ << written.pixelColor(0, 0);
}
QVERIFY(equalImageContents(written, image));
diff --git a/tests/auto/gui/image/qpixmap/qpixmap.pro b/tests/auto/gui/image/qpixmap/qpixmap.pro
index e6a020af1a..c9219dad1d 100644
--- a/tests/auto/gui/image/qpixmap/qpixmap.pro
+++ b/tests/auto/gui/image/qpixmap/qpixmap.pro
@@ -5,7 +5,7 @@ QT += core-private gui-private testlib
qtHaveModule(widgets): QT += widgets widgets-private
SOURCES += tst_qpixmap.cpp
-win32:!winrt:LIBS += -lgdi32 -luser32
+win32:!winrt: QMAKE_USE += user32 gdi32
RESOURCES += qpixmap.qrc
TESTDATA += convertFromImage/* convertFromToHICON/* loadFromData/* images/*
diff --git a/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp b/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp
index d19aa9b54f..2deb84fa5f 100644
--- a/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp
+++ b/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp
@@ -202,9 +202,7 @@ void tst_QStandardItem::getSetData()
QCOMPARE(qvariant_cast<QSize>(item.data(Qt::SizeHintRole)), sizeHint);
QCOMPARE(qvariant_cast<QFont>(item.data(Qt::FontRole)), font);
QCOMPARE(qvariant_cast<int>(item.data(Qt::TextAlignmentRole)), int(textAlignment));
- QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::BackgroundColorRole)), QBrush(backgroundColor));
QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::BackgroundRole)), QBrush(backgroundColor));
- QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::TextColorRole)), QBrush(textColor));
QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::ForegroundRole)), QBrush(textColor));
QCOMPARE(qvariant_cast<int>(item.data(Qt::CheckStateRole)), int(checkState));
QCOMPARE(qvariant_cast<QString>(item.data(Qt::AccessibleTextRole)), accessibleText);
@@ -236,9 +234,7 @@ void tst_QStandardItem::getSetData()
QCOMPARE(item.data(Qt::SizeHintRole), QVariant());
QCOMPARE(item.data(Qt::FontRole), QVariant());
QCOMPARE(item.data(Qt::TextAlignmentRole), QVariant());
- QCOMPARE(item.data(Qt::BackgroundColorRole), QVariant());
QCOMPARE(item.data(Qt::BackgroundRole), QVariant());
- QCOMPARE(item.data(Qt::TextColorRole), QVariant());
QCOMPARE(item.data(Qt::ForegroundRole), QVariant());
QCOMPARE(item.data(Qt::CheckStateRole), QVariant());
QCOMPARE(item.data(Qt::AccessibleTextRole), QVariant());
diff --git a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
index e2d7a41bd1..bc8bc38da6 100644
--- a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
+++ b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
@@ -734,7 +734,7 @@ void tst_QStandardItemModel::data()
currentRoles.clear();
// bad args
m_model->setData(QModelIndex(), "bla", Qt::DisplayRole);
- QCOMPARE(currentRoles, {});
+ QCOMPARE(currentRoles, QVector<int>{});
QIcon icon;
for (int r=0; r < m_model->rowCount(); ++r) {
@@ -742,9 +742,9 @@ void tst_QStandardItemModel::data()
m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole);
QCOMPARE(currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
m_model->setData(m_model->index(r,c), "tooltip", Qt::ToolTipRole);
- QCOMPARE(currentRoles, {Qt::ToolTipRole});
+ QCOMPARE(currentRoles, QVector<int>{Qt::ToolTipRole});
m_model->setData(m_model->index(r,c), icon, Qt::DecorationRole);
- QCOMPARE(currentRoles, {Qt::DecorationRole});
+ QCOMPARE(currentRoles, QVector<int>{Qt::DecorationRole});
}
}
@@ -761,7 +761,7 @@ void tst_QStandardItemModel::clearItemData()
{
currentRoles.clear();
QVERIFY(!m_model->clearItemData(QModelIndex()));
- QCOMPARE(currentRoles, {});
+ QCOMPARE(currentRoles, QVector<int>{});
const QModelIndex idx = m_model->index(0, 0);
const QMap<int, QVariant> oldData = m_model->itemData(idx);
m_model->setData(idx, QLatin1String("initialitem"), Qt::DisplayRole);
@@ -773,7 +773,7 @@ void tst_QStandardItemModel::clearItemData()
QCOMPARE(idx.data(Qt::ToolTipRole), QVariant());
QCOMPARE(idx.data(Qt::DisplayRole), QVariant());
QCOMPARE(idx.data(Qt::EditRole), QVariant());
- QCOMPARE(currentRoles, {});
+ QCOMPARE(currentRoles, QVector<int>{});
m_model->setItemData(idx, oldData);
currentRoles.clear();
}
@@ -1160,7 +1160,7 @@ void tst_QStandardItemModel::getSetItemData()
QColor backgroundColor(Qt::blue);
roles.insert(Qt::BackgroundRole, backgroundColor);
QColor textColor(Qt::green);
- roles.insert(Qt::TextColorRole, textColor);
+ roles.insert(Qt::ForegroundRole, textColor);
Qt::CheckState checkState(Qt::PartiallyChecked);
roles.insert(Qt::CheckStateRole, int(checkState));
QLatin1String accessibleText("accessibleText");
diff --git a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro
index 7e98704aea..293a6a8581 100644
--- a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro
+++ b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro
@@ -5,4 +5,4 @@ QT += core-private network gui-private testlib
SOURCES += tst_noqteventloop.cpp
-qtConfig(dynamicgl):win32:!winrt: LIBS += -luser32
+qtConfig(dynamicgl):win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp
index 993ebbaac6..bff9f7d0e0 100644
--- a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp
+++ b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp
@@ -215,7 +215,7 @@ static bool runHelper(const QString &program, const QStringList &arguments, QByt
{
#if QT_CONFIG(process)
QProcess process;
- process.setReadChannelMode(QProcess::ForwardedChannels);
+ process.setProcessChannelMode(QProcess::ForwardedChannels);
process.start(program, arguments);
if (!process.waitForStarted()) {
*errorMessage = "Unable to start '" + program.toLocal8Bit() + " ': "
diff --git a/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro b/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro
index 895c2a0307..34b75a8397 100644
--- a/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro
+++ b/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro
@@ -6,6 +6,7 @@ INCLUDEPATH += $$CORE_TEST_PATH
TARGET = tst_qguiapplication
QT += gui-private
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050E00
SOURCES += tst_qguiapplication.cpp
RESOURCES = tst_qguiapplication.qrc
diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
index a304981cd1..5ee25677bf 100644
--- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
+++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
@@ -184,7 +184,7 @@ void tst_QGuiApplication::windowIcon()
class DummyWindow : public QWindow
{
public:
- DummyWindow() : m_focusObject(0) {}
+ DummyWindow() : m_focusObject(nullptr) {}
virtual QObject *focusObject() const
{
@@ -204,7 +204,7 @@ public:
void tst_QGuiApplication::focusObject()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("QWindow::requestActivate() is not supported.");
@@ -271,15 +271,15 @@ void tst_QGuiApplication::focusObject()
void tst_QGuiApplication::allWindows()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
QWindow *window1 = new QWindow;
QWindow *window2 = new QWindow(window1);
QVERIFY(app.allWindows().contains(window1));
QVERIFY(app.allWindows().contains(window2));
QCOMPARE(app.allWindows().count(), 2);
delete window1;
- window1 = 0;
- window2 = 0;
+ window1 = nullptr;
+ window2 = nullptr;
QVERIFY(!app.allWindows().contains(window2));
QVERIFY(!app.allWindows().contains(window1));
QCOMPARE(app.allWindows().count(), 0);
@@ -288,15 +288,15 @@ void tst_QGuiApplication::allWindows()
void tst_QGuiApplication::topLevelWindows()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
QWindow *window1 = new QWindow;
QWindow *window2 = new QWindow(window1);
QVERIFY(app.topLevelWindows().contains(window1));
QVERIFY(!app.topLevelWindows().contains(window2));
QCOMPARE(app.topLevelWindows().count(), 1);
delete window1;
- window1 = 0;
- window2 = 0;
+ window1 = nullptr;
+ window2 = nullptr;
QVERIFY(!app.topLevelWindows().contains(window2));
QVERIFY(!app.topLevelWindows().contains(window1));
QCOMPARE(app.topLevelWindows().count(), 0);
@@ -306,7 +306,7 @@ class ShowCloseShowWindow : public QWindow
{
Q_OBJECT
public:
- ShowCloseShowWindow(bool showAgain, QWindow *parent = 0)
+ ShowCloseShowWindow(bool showAgain, QWindow *parent = nullptr)
: QWindow(parent), showAgain(showAgain)
{
QTimer::singleShot(0, this, SLOT(doClose()));
@@ -331,7 +331,7 @@ private:
void tst_QGuiApplication::abortQuitOnShow()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QScopedPointer<QWindow> window1(new ShowCloseShowWindow(false));
@@ -366,7 +366,7 @@ protected:
}
public:
- FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(0), windowDuringFocusOut(0) {}
+ FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(nullptr), windowDuringFocusOut(nullptr) {}
QWindow *windowDuringFocusAboutToChange;
QWindow *windowDuringFocusOut;
@@ -378,7 +378,7 @@ void tst_QGuiApplication::changeFocusWindow()
QSKIP("WinRt does not support multiple native windows.");
#endif
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("QWindow::requestActivate() is not supported.");
@@ -430,7 +430,7 @@ void tst_QGuiApplication::changeFocusWindow()
void tst_QGuiApplication::keyboardModifiers()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QScopedPointer<QWindow> window(new QWindow);
@@ -564,7 +564,7 @@ public:
int leaves;
int enters;
- inline explicit BlockableWindow(QWindow *parent = 0)
+ inline explicit BlockableWindow(QWindow *parent = nullptr)
: QWindow(parent), blocked(false), leaves(0), enters(0) {}
bool event(QEvent *e)
@@ -601,7 +601,7 @@ void tst_QGuiApplication::modalWindow()
QSKIP("WinRt does not support multiple native windows.");
#endif
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
int x = screenGeometry.left() + spacing;
@@ -654,7 +654,7 @@ void tst_QGuiApplication::modalWindow()
window2->show();
QVERIFY(QTest::qWaitForWindowExposed(window1.data()));
QVERIFY(QTest::qWaitForWindowExposed(window2.data()));
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(childWindow1->blocked, 0);
QCOMPARE(window2->blocked, 0);
@@ -698,7 +698,7 @@ void tst_QGuiApplication::modalWindow()
// everything is unblocked when applicationModalWindow1 is hidden
applicationModalWindow1->hide();
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(childWindow1->blocked, 0); // QTBUG-32242, blocked status needs to be set on children as well.
QCOMPARE(window2->blocked, 0);
@@ -750,7 +750,7 @@ void tst_QGuiApplication::modalWindow()
// hide windowModalWindow2, windowModalWindow1 and window1 are unblocked
windowModalWindow2->hide();
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(window2->blocked, 0);
QCOMPARE(windowModalWindow1->blocked, 0);
@@ -815,7 +815,7 @@ void tst_QGuiApplication::modalWindow()
// hide windowModalWindow1, everything is unblocked
windowModalWindow1->hide();
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(window2->blocked, 0);
QCOMPARE(windowModalWindow1->blocked, 0);
@@ -829,7 +829,7 @@ void tst_QGuiApplication::modalWindow()
void tst_QGuiApplication::quitOnLastWindowClosed()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QTimer timer;
@@ -869,7 +869,7 @@ void tst_QGuiApplication::quitOnLastWindowClosed()
void tst_QGuiApplication::quitOnLastWindowClosedMulti()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QTimer timer;
@@ -909,7 +909,7 @@ void tst_QGuiApplication::quitOnLastWindowClosedMulti()
void tst_QGuiApplication::dontQuitOnLastWindowClosed()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
app.setQuitOnLastWindowClosed(false);
QTimer timer;
@@ -959,7 +959,7 @@ public:
{
if (key == "testplugin")
return new TestPlugin;
- return 0;
+ return nullptr;
}
};
@@ -989,9 +989,13 @@ void tst_QGuiApplication::genericPluginsAndWindowSystemEvents()
QCoreApplication::postEvent(&testReceiver, new QEvent(QEvent::User));
QCOMPARE(testReceiver.customEvents, 0);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ QStaticPlugin testPluginInfo(qt_plugin_instance, qt_plugin_query_metadata);
+#else
QStaticPlugin testPluginInfo;
testPluginInfo.instance = qt_plugin_instance;
testPluginInfo.rawMetaData = qt_plugin_query_metadata;
+#endif
qRegisterStaticPluginFunction(testPluginInfo);
int argc = 3;
char *argv[] = { const_cast<char*>(QTest::currentAppName()), const_cast<char*>("-plugin"), const_cast<char*>("testplugin") };
@@ -1065,7 +1069,7 @@ void tst_QGuiApplication::testSetPaletteAttribute()
QVERIFY(!QCoreApplication::testAttribute(Qt::AA_SetPalette));
QPalette palette;
- palette.setColor(QPalette::Foreground, Qt::red);
+ palette.setColor(QPalette::WindowText, Qt::red);
QGuiApplication::setPalette(palette);
QVERIFY(QCoreApplication::testAttribute(Qt::AA_SetPalette));
@@ -1122,7 +1126,7 @@ void tst_QGuiApplication::settableStyleHints()
int argc = 0;
QScopedPointer<QGuiApplication> app;
if (appInstance)
- app.reset(new QGuiApplication(argc, 0));
+ app.reset(new QGuiApplication(argc, nullptr));
const int keyboardInputInterval = 555;
QGuiApplication::styleHints()->setKeyboardInputInterval(keyboardInputInterval);
diff --git a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
index cca0e95c29..b2572188b9 100644
--- a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
+++ b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp
@@ -49,6 +49,8 @@ private slots:
void construct();
void constructCopy_data();
void constructCopy();
+ void saveAndLoadBuiltin_data();
+ void saveAndLoadBuiltin();
};
#define FOR_EACH_GUI_METATYPE_BASE(F) \
@@ -442,5 +444,49 @@ FOR_EACH_GUI_METATYPE(RETURN_CONSTRUCT_COPY_FUNCTION)
TypeTestFunctionGetter::get(type)();
}
+template <typename T>
+struct StreamingTraits
+{
+ // Streamable by default, as currently all gui built-in types are streamable
+ enum { isStreamable = 1 };
+};
+
+void tst_QGuiMetaType::saveAndLoadBuiltin_data()
+{
+ QTest::addColumn<int>("type");
+ QTest::addColumn<bool>("isStreamable");
+
+#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
+ QTest::newRow(#RealType) << MetaTypeId << bool(StreamingTraits<RealType>::isStreamable);
+ QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW)
+#undef ADD_METATYPE_TEST_ROW
+}
+
+void tst_QGuiMetaType::saveAndLoadBuiltin()
+{
+ QFETCH(int, type);
+ QFETCH(bool, isStreamable);
+
+ void *value = QMetaType::create(type);
+
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::ReadWrite);
+ QCOMPARE(QMetaType::save(stream, type, value), isStreamable);
+ QCOMPARE(stream.status(), QDataStream::Ok);
+
+ if (isStreamable)
+ QVERIFY(QMetaType::load(stream, type, value));
+
+ stream.device()->seek(0);
+ stream.resetStatus();
+ QCOMPARE(QMetaType::load(stream, type, value), isStreamable);
+ QCOMPARE(stream.status(), QDataStream::Ok);
+
+ if (isStreamable)
+ QVERIFY(QMetaType::load(stream, type, value));
+
+ QMetaType::destroy(type, value);
+}
+
QTEST_MAIN(tst_QGuiMetaType)
#include "tst_qguimetatype.moc"
diff --git a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp
index bad021c3b0..9a4c560a08 100644
--- a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp
+++ b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp
@@ -121,7 +121,7 @@ static QByteArray modifiersTestRowName(const QString &keySequence)
if (uc > 32 && uc < 128)
str << '"' << c << '"';
else
- str << "U+" << hex << uc << dec;
+ str << "U+" << Qt::hex << uc << Qt::dec;
if (i < size - 1)
str << ',';
}
diff --git a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
index a0ac1b3631..6ce6422f48 100644
--- a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
+++ b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
@@ -37,6 +37,7 @@ class tst_QPalette : public QObject
private Q_SLOTS:
void roleValues_data();
void roleValues();
+ void resolve();
void copySemantics();
void moveSemantics();
void setBrush();
@@ -80,6 +81,43 @@ void tst_QPalette::roleValues()
QCOMPARE(role, value);
}
+void tst_QPalette::resolve()
+{
+ QPalette p1;
+ p1.setBrush(QPalette::WindowText, Qt::green);
+ p1.setBrush(QPalette::Button, Qt::green);
+
+ QVERIFY(p1.isBrushSet(QPalette::Active, QPalette::WindowText));
+ QVERIFY(p1.isBrushSet(QPalette::Active, QPalette::Button));
+
+ QPalette p2;
+ p2.setBrush(QPalette::WindowText, Qt::red);
+
+ QVERIFY(p2.isBrushSet(QPalette::Active, QPalette::WindowText));
+ QVERIFY(!p2.isBrushSet(QPalette::Active, QPalette::Button));
+
+ QPalette p1ResolvedTo2 = p1.resolve(p2);
+ // p1ResolvedTo2 gets everything from p1 and nothing copied from p2 because
+ // it already has a WindowText. That is two brushes, and to the same value
+ // as p1.
+ QCOMPARE(p1ResolvedTo2, p1);
+ QVERIFY(p1ResolvedTo2.isBrushSet(QPalette::Active, QPalette::WindowText));
+ QCOMPARE(p1.windowText(), p1ResolvedTo2.windowText());
+ QVERIFY(p1ResolvedTo2.isBrushSet(QPalette::Active, QPalette::Button));
+ QCOMPARE(p1.button(), p1ResolvedTo2.button());
+
+ QPalette p2ResolvedTo1 = p2.resolve(p1);
+ // p2ResolvedTo1 gets the WindowText set, and to the same value as the
+ // original p2, however, Button gets set from p1.
+ QVERIFY(p2ResolvedTo1.isBrushSet(QPalette::Active, QPalette::WindowText));
+ QCOMPARE(p2.windowText(), p2ResolvedTo1.windowText());
+ QVERIFY(p2ResolvedTo1.isBrushSet(QPalette::Active, QPalette::Button));
+ QCOMPARE(p1.button(), p2ResolvedTo1.button());
+
+ QVERIFY(p2ResolvedTo1 != p1);
+ QVERIFY(p2ResolvedTo1 != p2);
+}
+
void tst_QPalette::copySemantics()
{
QPalette src(Qt::red), dst;
@@ -103,21 +141,20 @@ void tst_QPalette::copySemantics()
void tst_QPalette::moveSemantics()
{
-#ifdef Q_COMPILER_RVALUE_REFS
QPalette src(Qt::red), dst;
const QPalette control = src;
QVERIFY(src != dst);
QCOMPARE(src, control);
QVERIFY(!dst.isCopyOf(src));
QVERIFY(!dst.isCopyOf(control));
- dst = qMove(src); // move assignment
+ dst = std::move(src); // move assignment
QVERIFY(!dst.isCopyOf(src)); // isCopyOf() works on moved-from palettes, too
QVERIFY(dst.isCopyOf(control));
QCOMPARE(dst, control);
src = control; // check moved-from 'src' can still be assigned to (doesn't crash)
QVERIFY(src.isCopyOf(dst));
QVERIFY(src.isCopyOf(control));
- QPalette dst2(qMove(src)); // move construction
+ QPalette dst2(std::move(src)); // move construction
QVERIFY(!src.isCopyOf(dst));
QVERIFY(!src.isCopyOf(dst2));
QVERIFY(!src.isCopyOf(control));
@@ -125,9 +162,6 @@ void tst_QPalette::moveSemantics()
QVERIFY(dst2.isCopyOf(dst));
QVERIFY(dst2.isCopyOf(control));
// check moved-from 'src' can still be destroyed (doesn't crash)
-#else
- QSKIP("Compiler doesn't support C++11 move semantics");
-#endif
}
void tst_QPalette::setBrush()
diff --git a/tests/auto/gui/kernel/qwindow/qwindow.pro b/tests/auto/gui/kernel/qwindow/qwindow.pro
index 844b3e8507..e7931ca773 100644
--- a/tests/auto/gui/kernel/qwindow/qwindow.pro
+++ b/tests/auto/gui/kernel/qwindow/qwindow.pro
@@ -5,4 +5,4 @@ QT += core-private gui-private testlib
SOURCES += tst_qwindow.cpp
-qtConfig(dynamicgl):win32:!winrt: LIBS += -luser32
+qtConfig(dynamicgl):win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/gui/painting/painting.pro b/tests/auto/gui/painting/painting.pro
index 831fffab30..26e84c1b15 100644
--- a/tests/auto/gui/painting/painting.pro
+++ b/tests/auto/gui/painting/painting.pro
@@ -3,6 +3,7 @@ SUBDIRS=\
qpainterpath \
qpainterpathstroker \
qcolor \
+ qcolorspace \
qbrush \
qregion \
qpagelayout \
diff --git a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
index ce6ce15767..f35d4f330b 100644
--- a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
+++ b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
@@ -338,9 +338,9 @@ void tst_QBrush::gradientPresets()
QCOMPARE(lg->finalStop(), QPointF(1, 0));
QCOMPARE(lg->stops().size(), 3);
- QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1Literal("#ff9a9e"))));
- QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1Literal("#fad0c4"))));
- QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1Literal("#fad0c4"))));
+ QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1String("#ff9a9e"))));
+ QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1String("#fad0c4"))));
+ QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1String("#fad0c4"))));
QGradient invalidPreset(QGradient::Preset(-1));
diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
index 17289e0b85..90a216e14a 100644
--- a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
+++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
@@ -33,7 +33,7 @@
#include <qcolor.h>
#include <qdebug.h>
-#include <private/qcolorprofile_p.h>
+#include <private/qcolortrclut_p.h>
#include <private/qdrawingprimitive_sse2_p.h>
#include <qrgba64.h>
@@ -70,6 +70,7 @@ private slots:
void setBlue();
void setRgb();
+ void setRgbF();
void setRgba();
void setHsv();
void setCmyk();
@@ -93,8 +94,8 @@ private slots:
void convertTo();
- void light();
- void dark();
+ void lighter();
+ void darker();
void specConstructor_data();
void specConstructor();
@@ -187,28 +188,28 @@ void tst_QColor::getSetCheck()
// void QColor::setRedF(qreal)
obj1.setRedF(0.0);
QCOMPARE(obj1.redF(), qreal(0.0));
- obj1.setRedF(-0.2);
- QCOMPARE(obj1.redF(), qreal(0.0)); // range<0.0, 1.0
- obj1.setRedF(1.1);
- QCOMPARE(obj1.redF(), qreal(1.0)); // range<0.0, 1.0
+ obj1.setRedF(-0.25);
+ QCOMPARE(obj1.redF(), qreal(-0.25));
+ obj1.setRedF(1.25);
+ QCOMPARE(obj1.redF(), qreal(1.25));
// qreal QColor::greenF()
// void QColor::setGreenF(qreal)
obj1.setGreenF(0.0);
QCOMPARE(obj1.greenF(), qreal(0.0));
- obj1.setGreenF(-0.2);
- QCOMPARE(obj1.greenF(), qreal(0.0)); // range<0.0, 1.0
- obj1.setGreenF(1.1);
- QCOMPARE(obj1.greenF(), qreal(1.0)); // range<0.0, 1.0
+ obj1.setGreenF(-0.25);
+ QCOMPARE(obj1.greenF(), qreal(-0.25));
+ obj1.setGreenF(1.5);
+ QCOMPARE(obj1.greenF(), qreal(1.5));
// qreal QColor::blueF()
// void QColor::setBlueF(qreal)
obj1.setBlueF(0.0);
QCOMPARE(obj1.blueF(), qreal(0.0));
- obj1.setBlueF(-0.2);
- QCOMPARE(obj1.blueF(), qreal(0.0)); // range<0.0, 1.0
- obj1.setBlueF(1.1);
- QCOMPARE(obj1.blueF(), qreal(1.0)); // range<0.0, 1.0
+ obj1.setBlueF(-0.5);
+ QCOMPARE(obj1.blueF(), qreal(-0.5));
+ obj1.setBlueF(2.0);
+ QCOMPARE(obj1.blueF(), qreal(2.0));
// QRgb QColor::rgba()
// void QColor::setRgba(QRgb)
@@ -677,30 +678,81 @@ void tst_QColor::setRgb()
{
QColor color;
- for (int A = 0; A <= USHRT_MAX; ++A) {
- {
- // 0-255
- int a = A >> 8;
- QRgb rgb = qRgba(0, 0, 0, a);
+ for (int a = 0; a <= 255; ++a) {
+ QRgb rgb = qRgba(0, 0, 0, a);
- color.setRgb(0, 0, 0, a);
- QCOMPARE(color.alpha(), a);
- QCOMPARE(color.rgb(), qRgb(0, 0, 0));
+ color.setRgb(0, 0, 0, a);
+ QCOMPARE(color.alpha(), a);
+ QCOMPARE(color.rgb(), qRgb(0, 0, 0));
- color.setRgb(rgb);
- QCOMPARE(color.alpha(), 255);
- QCOMPARE(color.rgb(), qRgb(0, 0, 0));
+ color.setRgb(rgb);
+ QCOMPARE(color.alpha(), 255);
+ QCOMPARE(color.rgb(), qRgb(0, 0, 0));
- int r, g, b, a2;
- color.setRgb(0, 0, 0, a);
- color.getRgb(&r, &g, &b, &a2);
- QCOMPARE(a2, a);
+ int r, g, b, a2;
+ color.setRgb(0, 0, 0, a);
+ color.getRgb(&r, &g, &b, &a2);
+ QCOMPARE(a2, a);
- QColor c(0, 0, 0);
- c.setAlpha(a);
- QCOMPARE(c.alpha(), a);
- }
+ QColor c(0, 0, 0);
+ c.setAlpha(a);
+ QCOMPARE(c.alpha(), a);
+ }
+ for (int r = 0; r <= 255; ++r) {
+ QRgb rgb = qRgb(r, 0, 0);
+
+ color.setRgb(r, 0, 0);
+ QCOMPARE(color.red(), r);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.red(), r);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r2, g, b, a;
+ color.getRgb(&r2, &g, &b, &a);
+ QCOMPARE(r2, r);
+ }
+
+ for (int g = 0; g <= 255; ++g) {
+ QRgb rgb = qRgb(0, g, 0);
+
+ color.setRgb(0, g, 0);
+ QCOMPARE(color.green(), g);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.green(), g);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r, g2, b, a;
+ color.getRgb(&r, &g2, &b, &a);
+ QCOMPARE(g2, g);
+ }
+
+ for (int b = 0; b <= 255; ++b) {
+ QRgb rgb = qRgb(0, 0, b);
+
+ color.setRgb(0, 0, b);
+ QCOMPARE(color.blue(), b);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.blue(), b);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r, g, b2, a;
+ color.getRgb(&r, &g, &b2, &a);
+ QCOMPARE(b2, b);
+ }
+}
+
+void tst_QColor::setRgbF()
+{
+ QColor color;
+
+ for (int A = 0; A <= USHRT_MAX; ++A) {
{
// 0.0-1.0
qreal a = A / qreal(USHRT_MAX);
@@ -720,24 +772,6 @@ void tst_QColor::setRgb()
for (int R = 0; R <= USHRT_MAX; ++R) {
{
- // 0-255
- int r = R >> 8;
- QRgb rgb = qRgb(r, 0, 0);
-
- color.setRgb(r, 0, 0);
- QCOMPARE(color.red(), r);
- QCOMPARE(color.rgb(), rgb);
-
- color.setRgb(rgb);
- QCOMPARE(color.red(), r);
- QCOMPARE(color.rgb(), rgb);
-
- int r2, g, b, a;
- color.getRgb(&r2, &g, &b, &a);
- QCOMPARE(r2, r);
- }
-
- {
// 0.0-1.0
qreal r = R / qreal(USHRT_MAX);
color.setRgbF(r, 0.0, 0.0);
@@ -751,24 +785,6 @@ void tst_QColor::setRgb()
for (int G = 0; G <= USHRT_MAX; ++G) {
{
- // 0-255
- int g = G >> 8;
- QRgb rgb = qRgb(0, g, 0);
-
- color.setRgb(0, g, 0);
- QCOMPARE(color.green(), g);
- QCOMPARE(color.rgb(), rgb);
-
- color.setRgb(rgb);
- QCOMPARE(color.green(), g);
- QCOMPARE(color.rgb(), rgb);
-
- int r, g2, b, a;
- color.getRgb(&r, &g2, &b, &a);
- QCOMPARE(g2, g);
- }
-
- {
// 0.0-1.0
qreal g = G / qreal(USHRT_MAX);
color.setRgbF(0.0, g, 0.0);
@@ -782,32 +798,53 @@ void tst_QColor::setRgb()
for (int B = 0; B <= USHRT_MAX; ++B) {
{
- // 0-255
- int b = B >> 8;
- QRgb rgb = qRgb(0, 0, b);
+ // 0.0-1.0
+ qreal b = B / qreal(USHRT_MAX);
+ color.setRgbF(0.0, 0.0, b);
+ QCOMPARE(color.blueF(), b);
- color.setRgb(0, 0, b);
- QCOMPARE(color.blue(), b);
- QCOMPARE(color.rgb(), rgb);
+ qreal r, g, b2, a;
+ color.getRgbF(&r, &g, &b2, &a);
+ QCOMPARE(b2, b);
+ }
+ }
- color.setRgb(rgb);
- QCOMPARE(color.blue(), b);
- QCOMPARE(color.rgb(), rgb);
+ for (int R = -128; R <= 512; ++R) {
+ {
+ // extended RGB
+ qreal r = R / qreal(256);
+ color.setRgbF(r, 0.0, 0.0);
+ QCOMPARE(qfloat16(color.redF()), qfloat16(r));
- int r, g, b2, a;
- color.getRgb(&r, &g, &b2, &a);
- QCOMPARE(b2, b);
+ qreal r2, g, b, a;
+ color.getRgbF(&r2, &g, &b, &a);
+ QCOMPARE(qfloat16(r2), qfloat16(r));
}
+ }
+ for (int G = -128; G <= 512; ++G) {
{
- // 0.0-1.0
- qreal b = B / qreal(USHRT_MAX);
+ // extended RGB
+ qreal g = G / qreal(256);
+ color.setRgbF(0.0, g, 0.0);
+ QCOMPARE(qfloat16(color.greenF()), qfloat16(g));
+
+ qreal r, g2, b, a;
+ color.getRgbF(&r, &g2, &b, &a);
+ QCOMPARE(qfloat16(g2), qfloat16(g));
+ }
+ }
+
+ for (int B = -128; B <= 512; ++B) {
+ {
+ // extended RGB
+ qreal b = B / qreal(256);
color.setRgbF(0.0, 0.0, b);
- QCOMPARE(color.blueF(), b);
+ QCOMPARE(qfloat16(color.blueF()), qfloat16(b));
qreal r, g, b2, a;
color.getRgbF(&r, &g, &b2, &a);
- QCOMPARE(b2, b);
+ QCOMPARE(qfloat16(b2), qfloat16(b));
}
}
}
@@ -1382,17 +1419,17 @@ void tst_QColor::convertTo()
QCOMPARE(invalid.spec(), QColor::Invalid);
}
-void tst_QColor::light()
+void tst_QColor::lighter()
{
QColor gray(Qt::gray);
- QColor lighter = gray.light();
+ QColor lighter = gray.lighter();
QVERIFY(lighter.value() > gray.value());
}
-void tst_QColor::dark()
+void tst_QColor::darker()
{
QColor gray(Qt::gray);
- QColor darker = gray.dark();
+ QColor darker = gray.darker();
QVERIFY(darker.value() < gray.value());
}
@@ -1632,14 +1669,13 @@ void tst_QColor::qcolorprofile_data()
QTest::newRow("gamma=1.7") << qreal(1.7) << 2;
QTest::newRow("gamma=2.0") << qreal(2.0) << 8;
QTest::newRow("gamma=2.31") << qreal(2.31) << 33;
- QTest::newRow("SRgb") << qreal(0.0) << 7;
}
void tst_QColor::qcolorprofile()
{
QFETCH(qreal, gammaC);
QFETCH(int, tolerance);
- QColorProfile *cp = (gammaC == 0) ? QColorProfile::fromSRgb(): QColorProfile::fromGamma(gammaC);
+ QColorTrcLut *cp = QColorTrcLut::fromGamma(gammaC);
// Test we are accurate for most values after converting through gamma-correction.
int error = 0;
diff --git a/tests/auto/gui/painting/qcolorspace/qcolorspace.pro b/tests/auto/gui/painting/qcolorspace/qcolorspace.pro
new file mode 100644
index 0000000000..14bd699bf7
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/qcolorspace.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+QT += testlib gui-private core-private
+
+TARGET = tst_qcolorspace
+SOURCES += tst_qcolorspace.cpp
+
+RESOURCES += $$files(resources/*)
+
+TESTDATA += resources/*
diff --git a/tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpg b/tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpg
new file mode 100644
index 0000000000..481d35ca8e
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpg
Binary files differ
diff --git a/tests/auto/gui/painting/qcolorspace/resources/sRGB2014.icc b/tests/auto/gui/painting/qcolorspace/resources/sRGB2014.icc
new file mode 100644
index 0000000000..49afbfef10
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/resources/sRGB2014.icc
Binary files differ
diff --git a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp
new file mode 100644
index 0000000000..7a88eb18b2
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp
@@ -0,0 +1,361 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcolorspace.h>
+#include <qimage.h>
+#include <qimagereader.h>
+
+#include <private/qcolorspace_p.h>
+
+Q_DECLARE_METATYPE(QColorSpace::ColorSpaceId)
+Q_DECLARE_METATYPE(QColorSpace::Gamut)
+Q_DECLARE_METATYPE(QColorSpace::TransferFunction)
+
+class tst_QColorSpace : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QColorSpace();
+
+private slots:
+ void namedColorSpaces_data();
+ void namedColorSpaces();
+
+ void toIccProfile_data();
+ void toIccProfile();
+
+ void fromIccProfile();
+
+ void imageConversion_data();
+ void imageConversion();
+
+ void loadImage();
+
+ void gamut();
+ void primariesXyz();
+ void primaries2_data();
+ void primaries2();
+ void invalidPrimaries();
+};
+
+tst_QColorSpace::tst_QColorSpace()
+{ }
+
+
+void tst_QColorSpace::namedColorSpaces_data()
+{
+ QTest::addColumn<QColorSpace::ColorSpaceId>("colorSpaceId");
+ QTest::addColumn<QColorSpace::Gamut>("gamutId");
+ QTest::addColumn<QColorSpace::TransferFunction>("transferFunctionId");
+
+ QTest::newRow("sRGB") << QColorSpace::SRgb
+ << QColorSpace::Gamut::SRgb
+ << QColorSpace::TransferFunction::SRgb;
+ QTest::newRow("sRGB Linear") << QColorSpace::SRgbLinear
+ << QColorSpace::Gamut::SRgb
+ << QColorSpace::TransferFunction::Linear;
+ QTest::newRow("Adobe RGB") << QColorSpace::AdobeRgb
+ << QColorSpace::Gamut::AdobeRgb
+ << QColorSpace::TransferFunction::Gamma;
+ QTest::newRow("Display-P3") << QColorSpace::DisplayP3
+ << QColorSpace::Gamut::DciP3D65
+ << QColorSpace::TransferFunction::SRgb;
+ QTest::newRow("ProPhoto RGB") << QColorSpace::ProPhotoRgb
+ << QColorSpace::Gamut::ProPhotoRgb
+ << QColorSpace::TransferFunction::ProPhotoRgb;
+ QTest::newRow("BT.2020") << QColorSpace::Bt2020
+ << QColorSpace::Gamut::Bt2020
+ << QColorSpace::TransferFunction::Bt2020;
+}
+
+void tst_QColorSpace::namedColorSpaces()
+{
+ QFETCH(QColorSpace::ColorSpaceId, colorSpaceId);
+ QFETCH(QColorSpace::Gamut, gamutId);
+ QFETCH(QColorSpace::TransferFunction, transferFunctionId);
+
+ QColorSpace colorSpace = colorSpaceId;
+
+ QVERIFY(colorSpace.isValid());
+
+ QCOMPARE(colorSpace.colorSpaceId(), colorSpaceId);
+ QCOMPARE(colorSpace.gamut(), gamutId);
+ QCOMPARE(colorSpace.transferFunction(), transferFunctionId);
+}
+
+
+void tst_QColorSpace::toIccProfile_data()
+{
+ namedColorSpaces_data();
+}
+
+void tst_QColorSpace::toIccProfile()
+{
+ QFETCH(QColorSpace::ColorSpaceId, colorSpaceId);
+ QFETCH(QColorSpace::Gamut, gamutId);
+ QFETCH(QColorSpace::TransferFunction, transferFunctionId);
+
+ Q_UNUSED(gamutId);
+ Q_UNUSED(transferFunctionId);
+
+ QColorSpace colorSpace = colorSpaceId;
+ QByteArray iccProfile = colorSpace.iccProfile();
+ QVERIFY(!iccProfile.isEmpty());
+
+ QColorSpace colorSpace2 = QColorSpace::fromIccProfile(iccProfile);
+ QVERIFY(colorSpace2.isValid());
+
+ QCOMPARE(colorSpace2, colorSpace);
+
+ QByteArray iccProfile2 = colorSpace2.iccProfile();
+ QVERIFY(!iccProfile2.isEmpty());
+
+ QCOMPARE(iccProfile2, iccProfile);
+}
+
+void tst_QColorSpace::fromIccProfile()
+{
+ // Read the official sRGB ICCv2 profile:
+ QString prefix = QFINDTESTDATA("resources/");
+ QFile file(prefix + "sRGB2014.icc");
+ file.open(QIODevice::ReadOnly);
+ QByteArray iccProfile = file.readAll();
+ QColorSpace stdSRgb = QColorSpace::fromIccProfile(iccProfile);
+ QVERIFY(stdSRgb.isValid());
+
+ QCOMPARE(stdSRgb.gamut(), QColorSpace::Gamut::SRgb);
+ QCOMPARE(stdSRgb.transferFunction(), QColorSpace::TransferFunction::SRgb);
+ QCOMPARE(stdSRgb.colorSpaceId(), QColorSpace::SRgb);
+
+ QCOMPARE(stdSRgb, QColorSpace(QColorSpace::SRgb));
+}
+
+void tst_QColorSpace::imageConversion_data()
+{
+ QTest::addColumn<QColorSpace::ColorSpaceId>("fromColorSpace");
+ QTest::addColumn<QColorSpace::ColorSpaceId>("toColorSpace");
+ QTest::addColumn<int>("tolerance");
+
+ QTest::newRow("sRGB -> Display-P3") << QColorSpace::SRgb << QColorSpace::DisplayP3 << 0;
+ QTest::newRow("sRGB -> Adobe RGB") << QColorSpace::SRgb << QColorSpace::AdobeRgb << 2;
+ QTest::newRow("Display-P3 -> sRGB") << QColorSpace::DisplayP3 << QColorSpace::SRgb << 0;
+ QTest::newRow("Adobe RGB -> sRGB") << QColorSpace::AdobeRgb << QColorSpace::SRgb << 2;
+ QTest::newRow("Display-P3 -> Adobe RGB") << QColorSpace::DisplayP3 << QColorSpace::AdobeRgb << 2;
+ QTest::newRow("Display-P3 -> BT.2020") << QColorSpace::DisplayP3 << QColorSpace::Bt2020 << 4;
+ QTest::newRow("sRGB -> sRGB Linear") << QColorSpace::SRgb << QColorSpace::SRgbLinear << 0;
+}
+
+void tst_QColorSpace::imageConversion()
+{
+ QFETCH(QColorSpace::ColorSpaceId, fromColorSpace);
+ QFETCH(QColorSpace::ColorSpaceId, toColorSpace);
+ QFETCH(int, tolerance);
+
+ QImage testImage(256, 1, QImage::Format_RGB32);
+
+ for (int i = 0; i < 256; ++i)
+ testImage.setPixel(i, 0, qRgb(i, i, i));
+
+ testImage.setColorSpace(fromColorSpace);
+ QCOMPARE(testImage.colorSpace(), QColorSpace(fromColorSpace));
+
+ testImage.convertToColorSpace(toColorSpace);
+ QCOMPARE(testImage.colorSpace(), QColorSpace(toColorSpace));
+
+ int lastRed = 0;
+ int lastGreen = 0;
+ int lastBlue = 0;
+ for (int i = 0; i < 256; ++i) {
+ QRgb p = testImage.pixel(i, 0);
+ QVERIFY(qRed(p) >= lastRed);
+ QVERIFY(qGreen(p) >= lastGreen);
+ QVERIFY(qBlue(p) >= lastBlue);
+ lastRed = qRed(p);
+ lastGreen = qGreen(p);
+ lastBlue = qBlue(p);
+ }
+
+ lastRed = 0;
+ lastGreen = 0;
+ lastBlue = 0;
+ testImage.convertToColorSpace(fromColorSpace);
+ QCOMPARE(testImage.colorSpace(), QColorSpace(fromColorSpace));
+ for (int i = 0; i < 256; ++i) {
+ QRgb p = testImage.pixel(i, 0);
+ QVERIFY(qAbs(qRed(p) - qGreen(p)) <= tolerance);
+ QVERIFY(qAbs(qRed(p) - qBlue(p)) <= tolerance);
+ QVERIFY((lastRed - qRed(p)) <= (tolerance / 2));
+ QVERIFY((lastGreen - qGreen(p)) <= (tolerance / 2));
+ QVERIFY((lastBlue - qBlue(p)) <= (tolerance / 2));
+ lastRed = qRed(p);
+ lastGreen = qGreen(p);
+ lastBlue = qBlue(p);
+ }
+}
+
+
+void tst_QColorSpace::loadImage()
+{
+ QString prefix = QFINDTESTDATA("resources/");
+ QImageReader reader(prefix + "ProPhoto.jpg");
+ QImage image = reader.read();
+
+ QVERIFY(!image.isNull());
+ QVERIFY(image.colorSpace().isValid());
+ QCOMPARE(image.colorSpace().colorSpaceId(), QColorSpace::ProPhotoRgb);
+ QVERIFY(!image.colorSpace().iccProfile().isEmpty());
+
+ QColorSpace defaultProPhotoRgb = QColorSpace::ProPhotoRgb;
+ QVERIFY(!defaultProPhotoRgb.iccProfile().isEmpty());
+
+ // Test the iccProfile getter returns the ICC profile from the image
+ // which since we didn't write it, isn't identical to our defaults.
+ QVERIFY(defaultProPhotoRgb.iccProfile() != image.colorSpace().iccProfile());
+
+ QColorTransform transform = image.colorSpace().transformationToColorSpace(QColorSpace::SRgb);
+ qreal maxRed = 0;
+ qreal maxBlue = 0;
+ qreal maxRed2 = 0;
+ qreal maxBlue2 = 0;
+ for (int y = 0; y < image.height(); ++y) {
+ for (int x = 0; x < image.width(); ++x) {
+ QColor p = image.pixelColor(x, y);
+ maxRed = std::max(maxRed, p.redF());
+ maxBlue = std::max(maxBlue, p.blueF());
+ p = transform.map(p);
+ maxRed2 = std::max(maxRed2, p.redF());
+ maxBlue2 = std::max(maxBlue2, p.blueF());
+
+ }
+ }
+ // ProPhotoRgb can be a lot more red and blue than SRgb can, so it will have lower values.
+ QVERIFY(maxRed2 > maxRed);
+ QVERIFY(maxBlue2 > maxBlue);
+}
+
+void tst_QColorSpace::gamut()
+{
+ QColor black = QColor::fromRgbF(0.0, 0.0, 0.0);
+ QColor white = QColor::fromRgbF(1.0, 1.0, 1.0);
+ QColor red = QColor::fromRgbF(1.0, 0.0, 0.0);
+ QColor green = QColor::fromRgbF(0.0, 1.0, 0.0);
+ QColor blue = QColor::fromRgbF(0.0, 0.0, 1.0);
+
+ QColorTransform toAdobeRgb = QColorSpace(QColorSpace::SRgb).transformationToColorSpace(QColorSpace::AdobeRgb);
+
+ QColor tblack = toAdobeRgb.map(black);
+ QColor twhite = toAdobeRgb.map(white);
+ QColor tred = toAdobeRgb.map(red);
+ QColor tgreen = toAdobeRgb.map(green);
+ QColor tblue = toAdobeRgb.map(blue);
+
+ // Black is black
+ QCOMPARE(tblack, black);
+
+ // This white hasn't changed
+ QCOMPARE(twhite, white);
+
+ // Adobe's red and blue gamut corners are the same as sRGB's
+ // So, a color in the red corner, will stay in the red corner
+ // the same for blue, but not for green.
+ QVERIFY(tred.greenF() < 0.001);
+ QVERIFY(tred.blueF() < 0.001);
+ QVERIFY(tblue.redF() < 0.001);
+ QVERIFY(tblue.greenF() < 0.001);
+ QVERIFY(tgreen.redF() > 0.2);
+ QVERIFY(tgreen.blueF() > 0.2);
+}
+
+void tst_QColorSpace::primariesXyz()
+{
+ QColorSpace sRgb = QColorSpace::SRgb;
+ QColorSpace adobeRgb = QColorSpace::AdobeRgb;
+ QColorSpace displayP3 = QColorSpace::DisplayP3;
+ QColorSpace proPhotoRgb = QColorSpace::ProPhotoRgb;
+ QColorSpace bt2020 = QColorSpace::Bt2020;
+
+ // Check if our calculated matrices, match the precalculated ones.
+ QCOMPARE(sRgb.d_func()->toXyz, QColorMatrix::toXyzFromSRgb());
+ QCOMPARE(adobeRgb.d_func()->toXyz, QColorMatrix::toXyzFromAdobeRgb());
+ QCOMPARE(displayP3.d_func()->toXyz, QColorMatrix::toXyzFromDciP3D65());
+ QCOMPARE(proPhotoRgb.d_func()->toXyz, QColorMatrix::toXyzFromProPhotoRgb());
+ QCOMPARE(bt2020.d_func()->toXyz, QColorMatrix::toXyzFromBt2020());
+}
+
+void tst_QColorSpace::primaries2_data()
+{
+ QTest::addColumn<QColorSpace::Gamut>("gamut");
+
+ QTest::newRow("sRGB") << QColorSpace::Gamut::SRgb;
+ QTest::newRow("DCI-P3 (D65)") << QColorSpace::Gamut::DciP3D65;
+ QTest::newRow("Adobe RGB (1998)") << QColorSpace::Gamut::AdobeRgb;
+ QTest::newRow("ProPhoto RGB") << QColorSpace::Gamut::ProPhotoRgb;
+ QTest::newRow("BT.2020") << QColorSpace::Gamut::Bt2020;
+}
+
+void tst_QColorSpace::primaries2()
+{
+ QFETCH(QColorSpace::Gamut, gamut);
+ QColorSpacePrimaries primaries(gamut);
+
+ QColorSpace original(gamut, QColorSpace::TransferFunction::Linear);
+ QColorSpace custom1(primaries.whitePoint, primaries.redPoint,
+ primaries.greenPoint, primaries.bluePoint, QColorSpace::TransferFunction::Linear);
+ QCOMPARE(original, custom1);
+
+ // A custom color swizzled color-space:
+ QColorSpace custom2(primaries.whitePoint, primaries.bluePoint,
+ primaries.greenPoint, primaries.redPoint, QColorSpace::TransferFunction::Linear);
+
+ QVERIFY(custom1 != custom2);
+ QColor color1(255, 127, 63);
+ QColor color2 = custom1.transformationToColorSpace(custom2).map(color1);
+ QCOMPARE(color2.red(), color1.blue());
+ QCOMPARE(color2.green(), color1.green());
+ QCOMPARE(color2.blue(), color1.red());
+ QCOMPARE(color2.alpha(), color1.alpha());
+ QColor color3 = custom2.transformationToColorSpace(custom1).map(color2);
+ QCOMPARE(color3.red(), color1.red());
+ QCOMPARE(color3.green(), color1.green());
+ QCOMPARE(color3.blue(), color1.blue());
+ QCOMPARE(color3.alpha(), color1.alpha());
+}
+
+void tst_QColorSpace::invalidPrimaries()
+{
+ QColorSpace custom(QPointF(), QPointF(), QPointF(), QPointF(), QColorSpace::TransferFunction::Linear);
+ QVERIFY(!custom.isValid());
+ QCOMPARE(custom.colorSpaceId(), QColorSpace::Undefined);
+}
+
+QTEST_MAIN(tst_QColorSpace)
+#include "tst_qcolorspace.moc"
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
index bc0baed15c..2b53169a45 100644
--- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
@@ -185,10 +185,12 @@ private slots:
void gradientPixelFormat_data();
void gradientPixelFormat();
+#if QT_CONFIG(raster_64bit)
void linearGradientRgb30_data();
void linearGradientRgb30();
void radialGradientRgb30_data();
void radialGradientRgb30();
+#endif
void fpe_pixmapTransform();
void fpe_zeroLengthLines();
@@ -368,10 +370,10 @@ void tst_QPainter::getSetCheck()
// bool QPainter::matrixEnabled()
// void QPainter::setMatrixEnabled(bool)
- obj1.setMatrixEnabled(false);
- QCOMPARE(false, obj1.matrixEnabled());
- obj1.setMatrixEnabled(true);
- QCOMPARE(true, obj1.matrixEnabled());
+ obj1.setWorldMatrixEnabled(false);
+ QCOMPARE(false, obj1.worldMatrixEnabled());
+ obj1.setWorldMatrixEnabled(true);
+ QCOMPARE(true, obj1.worldMatrixEnabled());
// bool QPainter::viewTransformEnabled()
// void QPainter::setViewTransformEnabled(bool)
@@ -697,7 +699,7 @@ void tst_QPainter::initFrom()
QCOMPARE(p.font(), font);
QCOMPARE(p.pen().color(), pal.color(QPalette::Foreground));
- QCOMPARE(p.background(), pal.background());
+ QCOMPARE(p.background(), pal.window());
delete widget;
}
@@ -3195,7 +3197,7 @@ void tst_QPainter::largeImagePainting()
p.translate(4, 0);
}
- p.resetMatrix();
+ p.resetTransform();
for (int i = 4; i < img.height(); i += 4) {
p.translate(0, 4);
@@ -3946,6 +3948,7 @@ void tst_QPainter::gradientInterpolation()
}
}
+#if QT_CONFIG(raster_64bit)
void tst_QPainter::linearGradientRgb30_data()
{
QTest::addColumn<QColor>("stop0");
@@ -4004,6 +4007,7 @@ void tst_QPainter::radialGradientRgb30()
QVERIFY(qGray(p1.rgb()) >= qGray(p2.rgb()));
}
}
+#endif
void tst_QPainter::drawPolygon()
{
@@ -4884,14 +4888,18 @@ void tst_QPainter::blendARGBonRGB_data()
<< QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB_PM over RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_SourceOver << qRgba(85, 0, 0, 85) << 85;
+#if QT_CONFIG(raster_64bit)
QTest::newRow("ARGB source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_Source << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_Source << qRgba(255, 0, 0, 120) << 85;
+#endif
QTest::newRow("ARGB_PM source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_Source << qRgba(85, 0, 0, 85) << 85;
+#if QT_CONFIG(raster_64bit)
QTest::newRow("ARGB_PM source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_Source << qRgba(180, 0, 0, 180) << 170;
+#endif
QTest::newRow("ARGB source-in RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB_PM source-in RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
index 16215714f3..69c961c1a1 100644
--- a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
+++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp
@@ -43,6 +43,8 @@ public slots:
void cleanupTestCase();
private slots:
void getSetCheck();
+ void clear();
+ void reserveAndCapacity();
void swap();
void contains_QPointF_data();
@@ -148,6 +150,47 @@ void tst_QPainterPath::swap()
QCOMPARE(p2.boundingRect().toRect(), QRect( 0, 0,10,10));
}
+void tst_QPainterPath::clear()
+{
+ QPainterPath p1;
+ QPainterPath p2;
+ p1.clear();
+ QCOMPARE(p1, p2);
+
+ p1.addRect(0, 0, 10, 10);
+ p1.clear();
+ QCOMPARE(p1, p2);
+
+ QCOMPARE(p1.fillRule(), Qt::OddEvenFill);
+ p1.setFillRule(Qt::WindingFill);
+ p1.clear();
+ QCOMPARE(p1.fillRule(), Qt::WindingFill);
+}
+
+void tst_QPainterPath::reserveAndCapacity()
+{
+ QPainterPath p;
+ QVERIFY(p.capacity() == 0);
+
+ p.addRect(0, 0, 10, 10);
+ QVERIFY(p.capacity() > 0);
+
+ p.clear();
+ QVERIFY(p.capacity() > 0);
+
+ p = QPainterPath{};
+ QVERIFY(p.capacity() == 0);
+
+ p.moveTo(100, 100);
+ QVERIFY(p.capacity() > 1);
+
+ p.reserve(1000);
+ QVERIFY(p.capacity() >= 1000);
+
+ p.reserve(0);
+ QVERIFY(p.capacity() >= 1000);
+}
+
Q_DECLARE_METATYPE(QPainterPath)
void tst_QPainterPath::currentPosition()
diff --git a/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp b/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp
index c1a8f7f0de..9e9b0db366 100644
--- a/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp
+++ b/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp
@@ -154,12 +154,7 @@ void tst_QPdfWriter::testPageMetrics()
if (setMargins) {
// Setup the given margins
- QPdfWriter::Margins margins;
- margins.left = leftMMf;
- margins.right = rightMMf;
- margins.top = topMMf;
- margins.bottom = bottomMMf;
- writer.setMargins(margins);
+ writer.setPageMargins({leftMMf, topMMf, rightMMf, bottomMMf}, QPageLayout::Millimeter);
QCOMPARE(writer.margins().left, leftMMf);
QCOMPARE(writer.margins().right, rightMMf);
QCOMPARE(writer.margins().top, topMMf);
@@ -169,7 +164,7 @@ void tst_QPdfWriter::testPageMetrics()
// Set the given size, in Portrait mode
if (pageSize < 0) {
- writer.setPageSizeMM(sizeMMf);
+ writer.setPageSize(QPageSize(sizeMMf, QPageSize::Millimeter));
QCOMPARE(writer.pageSize(), QPdfWriter::Custom);
QCOMPARE(writer.pageLayout().pageSize().id(), QPageSize::Custom);
} else {
@@ -221,7 +216,7 @@ void tst_QPdfWriter::testPageMetrics()
// Now while in Landscape mode, set the size again, results should be the same
if (pageSize < 0) {
- writer.setPageSizeMM(sizeMMf);
+ writer.setPageSize(QPageSize(sizeMMf, QPageSize::Millimeter));
QCOMPARE(writer.pageSize(), QPdfWriter::Custom);
QCOMPARE(writer.pageLayout().pageSize().id(), QPageSize::Custom);
} else {
@@ -255,7 +250,7 @@ void tst_QPdfWriter::qtbug59443()
QTemporaryFile file;
QVERIFY2(file.open(), qPrintable(file.errorString()));
QPdfWriter writer(file.fileName());
- writer.setPageSize(QPdfWriter::A4);
+ writer.setPageSize(QPageSize(QPageSize::A4));
QTextDocument doc;
doc.documentLayout()->setPaintDevice(&writer);
diff --git a/tests/auto/gui/painting/qpen/tst_qpen.cpp b/tests/auto/gui/painting/qpen/tst_qpen.cpp
index ef65d653ce..295ae27d17 100644
--- a/tests/auto/gui/painting/qpen/tst_qpen.cpp
+++ b/tests/auto/gui/painting/qpen/tst_qpen.cpp
@@ -95,7 +95,7 @@ void tst_QPen::move()
QPen p1(Qt::black);
// check that moving does the right thing:
- QPen p2 = qMove(p1); // could be move or copy construction, so don't check p1's state
+ QPen p2 = std::move(p1); // could be move or copy construction, so don't check p1's state
QCOMPARE(p2.color(), QColor(Qt::black));
// this, executed ehre, would crash:
@@ -110,7 +110,7 @@ void tst_QPen::move()
QCOMPARE(p1.color(), QColor(Qt::yellow));
// check that moved-from QPens p2, p3 can still be safely destroyed:
- QPen p5 = qMove(p2);
+ QPen p5 = std::move(p2);
// intentionally no more statements beyond this point
}
@@ -120,7 +120,7 @@ void tst_QPen::move_assign()
QPen p1(Qt::black), p2(Qt::white);
// check that moving does the right thing:
- p2 = qMove(p1); // could be move or copy assignment, so don't check p1's state
+ p2 = std::move(p1); // could be move or copy assignment, so don't check p1's state
QCOMPARE(p2.color(), QColor(Qt::black));
// check that move-assigned-from QPen p1 can still be used, albeit
@@ -137,7 +137,7 @@ void tst_QPen::move_assign()
// check that moved-from QPens p2, p3 can still be safely destroyed:
QPen p5;
- p5 = qMove(p2);
+ p5 = std::move(p2);
// intentionally no more statements beyond this point
}
diff --git a/tests/auto/gui/painting/qregion/tst_qregion.cpp b/tests/auto/gui/painting/qregion/tst_qregion.cpp
index 5256fbd1dc..24c4583819 100644
--- a/tests/auto/gui/painting/qregion/tst_qregion.cpp
+++ b/tests/auto/gui/painting/qregion/tst_qregion.cpp
@@ -84,6 +84,8 @@ private slots:
#endif
void regionFromPath();
+ void scaleRegions_data();
+ void scaleRegions();
#ifdef QT_BUILD_INTERNAL
void regionToPath_data();
@@ -973,6 +975,59 @@ void tst_QRegion::regionFromPath()
}
}
+void tst_QRegion::scaleRegions_data()
+{
+ QTest::addColumn<qreal>("scale");
+ QTest::addColumn<QVector<QRect>>("inputRects");
+ QTest::addColumn<QVector<QRect>>("expectedRects");
+
+ QTest::newRow("1.0 single") << 1.0
+ << QVector<QRect>{ QRect(10, 10, 20, 20) }
+ << QVector<QRect>{ QRect(10, 10, 20, 20) };
+ QTest::newRow("1.0 multi") << 1.0
+ << QVector<QRect>{ QRect(10, 10, 20, 20), QRect(40, 10, 20, 20) }
+ << QVector<QRect>{ QRect(10, 10, 20, 20), QRect(40, 10, 20, 20) };
+ QTest::newRow("2.0 single") << 2.0
+ << QVector<QRect>{ QRect(10, 10, 20, 20) }
+ << QVector<QRect>{ QRect(20, 20, 40, 40) };
+ QTest::newRow("2.0 multi") << 2.0
+ << QVector<QRect>{ QRect(10, 10, 20, 20), QRect(40, 10, 20, 20) }
+ << QVector<QRect>{ QRect(20, 20, 40, 40), QRect(80, 20, 40, 40) };
+ QTest::newRow("-1.0 single") << -1.0
+ << QVector<QRect>{ QRect(10, 10, 20, 20) }
+ << QVector<QRect>{ QRect(-30, -30, 20, 20) };
+ QTest::newRow("-1.0 multi") << -1.0
+ << QVector<QRect>{ QRect(10, 10, 20, 20), QRect(40, 10, 20, 20) }
+ << QVector<QRect>{ QRect(-60, -30, 20, 20), QRect(-30, -30, 20, 20) };
+ QTest::newRow("-2.0 single") << -2.0
+ << QVector<QRect>{ QRect(10, 10, 20, 20) }
+ << QVector<QRect>{ QRect(-60, -60, 40, 40) };
+ QTest::newRow("-2.0 multi") << -2.0
+ << QVector<QRect>{ QRect(10, 10, 20, 20), QRect(40, 10, 20, 20) }
+ << QVector<QRect>{ QRect(-120, -60, 40, 40), QRect(-60, -60, 40, 40) };
+}
+
+void tst_QRegion::scaleRegions()
+{
+ QFETCH(qreal, scale);
+ QFETCH(QVector<QRect>, inputRects);
+ QFETCH(QVector<QRect>, expectedRects);
+
+ QRegion region;
+ region.setRects(inputRects.constData(), inputRects.size());
+
+ QRegion expected(expectedRects.first());
+ expected.setRects(expectedRects.constData(), expectedRects.size());
+
+ QTransform t;
+ t.scale(scale, scale);
+
+ auto result = t.map(region);
+
+ QCOMPARE(result.rectCount(), expectedRects.size());
+ QCOMPARE(result, expected);
+}
+
Q_DECLARE_METATYPE(QPainterPath)
#ifdef QT_BUILD_INTERNAL
diff --git a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp
index f8dfdbd3b0..b82b277781 100644
--- a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp
+++ b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp
@@ -200,7 +200,7 @@ static void dumpGlConfiguration(QOpenGLContext &context, QTextStream &str)
<< "\nShading language : " << reinterpret_cast<const char *>(functions.glGetString(GL_SHADING_LANGUAGE_VERSION))
<< "\nFormat : " << context.format();
- QList<QByteArray> extensionList = context.extensions().toList();
+ QList<QByteArray> extensionList = context.extensions().values();
std::sort(extensionList.begin(), extensionList.end());
const int extensionCount = extensionList.size();
str << "\n\nFound " << extensionCount << " extensions:\n";
@@ -233,9 +233,9 @@ void tst_QOpenGlConfig::testGlConfiguration()
static inline QByteArray msgSetMismatch(const QSet<QString> &expected,
const QSet<QString> &actual)
{
- const QString result = QStringList(expected.toList()).join(QLatin1Char(','))
+ const QString result = QStringList(expected.values()).join(QLatin1Char(','))
+ QLatin1String(" != ")
- + QStringList(actual.toList()).join(QLatin1Char(','));
+ + QStringList(actual.values()).join(QLatin1Char(','));
return result.toLatin1();
}
diff --git a/tests/auto/gui/rhi/qrhi/data/texture.frag b/tests/auto/gui/rhi/qrhi/data/texture.frag
new file mode 100644
index 0000000000..e6021fe905
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/data/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/tests/auto/gui/rhi/qrhi/data/texture.vert b/tests/auto/gui/rhi/qrhi/data/texture.vert
new file mode 100644
index 0000000000..de486cb772
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/data/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/tests/auto/gui/rhi/qrhi/qrhi.pro b/tests/auto/gui/rhi/qrhi/qrhi.pro
new file mode 100644
index 0000000000..58000ed514
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/qrhi.pro
@@ -0,0 +1,8 @@
+TARGET = tst_qrhi
+CONFIG += testcase
+
+QT += testlib gui-private
+
+SOURCES += tst_qrhi.cpp
+
+RESOURCES += qrhi.qrc
diff --git a/tests/auto/gui/rhi/qrhi/qrhi.qrc b/tests/auto/gui/rhi/qrhi/qrhi.qrc
new file mode 100644
index 0000000000..f161d8aad6
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/qrhi.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
new file mode 100644
index 0000000000..897613d525
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QThread>
+#include <QFile>
+#include <QOffscreenSurface>
+#include <QtGui/private/qrhi_p.h>
+#include <QtGui/private/qrhinull_p.h>
+
+#if QT_CONFIG(opengl)
+# include <QtGui/private/qrhigles2_p.h>
+# define TST_GL
+#endif
+
+#if QT_CONFIG(vulkan)
+# include <QVulkanInstance>
+# include <QtGui/private/qrhivulkan_p.h>
+# define TST_VK
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+# define TST_D3D11
+#endif
+
+#ifdef Q_OS_DARWIN
+# include <QtGui/private/qrhimetal_p.h>
+# define TST_MTL
+#endif
+
+Q_DECLARE_METATYPE(QRhi::Implementation)
+Q_DECLARE_METATYPE(QRhiInitParams *)
+
+class tst_QRhi : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void create_data();
+ void create();
+
+private:
+ struct {
+ QRhiNullInitParams null;
+#ifdef TST_GL
+ QRhiGles2InitParams gl;
+#endif
+#ifdef TST_VK
+ QRhiVulkanInitParams vk;
+#endif
+#ifdef TST_D3D11
+ QRhiD3D11InitParams d3d;
+#endif
+#ifdef TST_MTL
+ QRhiMetalInitParams mtl;
+#endif
+ } initParams;
+
+#ifdef TST_VK
+ QVulkanInstance vulkanInstance;
+#endif
+ QOffscreenSurface *fallbackSurface = nullptr;
+};
+
+void tst_QRhi::initTestCase()
+{
+#ifdef TST_GL
+ fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ initParams.gl.fallbackSurface = fallbackSurface;
+#endif
+
+#ifdef TST_VK
+ vulkanInstance.create();
+ initParams.vk.inst = &vulkanInstance;
+#endif
+}
+
+void tst_QRhi::cleanupTestCase()
+{
+#ifdef TST_VK
+ vulkanInstance.destroy();
+#endif
+
+ delete fallbackSurface;
+}
+
+void tst_QRhi::create_data()
+{
+ QTest::addColumn<QRhi::Implementation>("impl");
+ QTest::addColumn<QRhiInitParams *>("initParams");
+
+ QTest::newRow("Null") << QRhi::Null << static_cast<QRhiInitParams *>(&initParams.null);
+#ifdef TST_GL
+ QTest::newRow("OpenGL") << QRhi::OpenGLES2 << static_cast<QRhiInitParams *>(&initParams.gl);
+#endif
+#ifdef TST_VK
+ if (vulkanInstance.isValid())
+ QTest::newRow("Vulkan") << QRhi::Vulkan << static_cast<QRhiInitParams *>(&initParams.vk);
+#endif
+#ifdef TST_D3D11
+ QTest::newRow("Direct3D 11") << QRhi::D3D11 << static_cast<QRhiInitParams *>(&initParams.d3d);
+#endif
+#ifdef TST_MTL
+ QTest::newRow("Metal") << QRhi::Metal << static_cast<QRhiInitParams *>(&initParams.mtl);
+#endif
+}
+
+static int aligned(int v, int a)
+{
+ return (v + a - 1) & ~(a - 1);
+}
+
+void tst_QRhi::create()
+{
+ // Merely attempting to create a QRhi should survive, with an error when
+ // not supported. (of course, there is always a chance we encounter a crash
+ // due to some random graphics stack...)
+
+ QFETCH(QRhi::Implementation, impl);
+ QFETCH(QRhiInitParams *, initParams);
+
+ QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
+
+ if (rhi) {
+ QCOMPARE(rhi->backend(), impl);
+ QCOMPARE(rhi->thread(), QThread::currentThread());
+
+ int cleanupOk = 0;
+ QRhi *rhiPtr = rhi.data();
+ auto cleanupFunc = [rhiPtr, &cleanupOk](QRhi *dyingRhi) {
+ if (rhiPtr == dyingRhi)
+ cleanupOk += 1;
+ };
+ rhi->addCleanupCallback(cleanupFunc);
+ rhi->runCleanup();
+ QCOMPARE(cleanupOk, 1);
+ cleanupOk = 0;
+ rhi->addCleanupCallback(cleanupFunc);
+
+ QRhiResourceUpdateBatch *resUpd = rhi->nextResourceUpdateBatch();
+ QVERIFY(resUpd);
+ resUpd->release();
+
+ QVERIFY(!rhi->supportedSampleCounts().isEmpty());
+ QVERIFY(rhi->supportedSampleCounts().contains(1));
+
+ QVERIFY(rhi->ubufAlignment() > 0);
+ QCOMPARE(rhi->ubufAligned(123), aligned(123, rhi->ubufAlignment()));
+
+ QCOMPARE(rhi->mipLevelsForSize(QSize(512, 300)), 10);
+ QCOMPARE(rhi->sizeForMipLevel(0, QSize(512, 300)), QSize(512, 300));
+ QCOMPARE(rhi->sizeForMipLevel(1, QSize(512, 300)), QSize(256, 150));
+ QCOMPARE(rhi->sizeForMipLevel(2, QSize(512, 300)), QSize(128, 75));
+ QCOMPARE(rhi->sizeForMipLevel(9, QSize(512, 300)), QSize(1, 1));
+
+ const bool fbUp = rhi->isYUpInFramebuffer();
+ const bool ndcUp = rhi->isYUpInNDC();
+ const bool d0to1 = rhi->isClipDepthZeroToOne();
+ const QMatrix4x4 corrMat = rhi->clipSpaceCorrMatrix();
+ if (impl == QRhi::OpenGLES2) {
+ QVERIFY(fbUp);
+ QVERIFY(ndcUp);
+ QVERIFY(!d0to1);
+ QVERIFY(corrMat.isIdentity());
+ } else if (impl == QRhi::Vulkan) {
+ QVERIFY(!fbUp);
+ QVERIFY(!ndcUp);
+ QVERIFY(d0to1);
+ QVERIFY(!corrMat.isIdentity());
+ } else if (impl == QRhi::D3D11) {
+ QVERIFY(!fbUp);
+ QVERIFY(ndcUp);
+ QVERIFY(d0to1);
+ QVERIFY(!corrMat.isIdentity());
+ } else if (impl == QRhi::Metal) {
+ QVERIFY(!fbUp);
+ QVERIFY(ndcUp);
+ QVERIFY(d0to1);
+ QVERIFY(!corrMat.isIdentity());
+ }
+
+ const int texMin = rhi->resourceLimit(QRhi::TextureSizeMin);
+ const int texMax = rhi->resourceLimit(QRhi::TextureSizeMax);
+ const int maxAtt = rhi->resourceLimit(QRhi::MaxColorAttachments);
+ QVERIFY(texMin >= 1);
+ QVERIFY(texMax >= texMin);
+ QVERIFY(maxAtt >= 1);
+
+ QVERIFY(rhi->nativeHandles());
+ QVERIFY(rhi->profiler());
+
+ const QRhi::Feature features[] = {
+ QRhi::MultisampleTexture,
+ QRhi::MultisampleRenderBuffer,
+ QRhi::DebugMarkers,
+ QRhi::Timestamps,
+ QRhi::Instancing,
+ QRhi::CustomInstanceStepRate,
+ QRhi::PrimitiveRestart,
+ QRhi::NonDynamicUniformBuffers,
+ QRhi::NonFourAlignedEffectiveIndexBufferOffset,
+ QRhi::NPOTTextureRepeat,
+ QRhi::RedOrAlpha8IsRed,
+ QRhi::ElementIndexUint
+ };
+ for (size_t i = 0; i <sizeof(features) / sizeof(QRhi::Feature); ++i)
+ rhi->isFeatureSupported(features[i]);
+
+ QVERIFY(rhi->isTextureFormatSupported(QRhiTexture::RGBA8));
+
+ rhi.reset();
+ QCOMPARE(cleanupOk, 1);
+ }
+}
+
+#include <tst_qrhi.moc>
+QTEST_MAIN(tst_QRhi)
diff --git a/tests/auto/gui/rhi/qshader/data/color.vert b/tests/auto/gui/rhi/qshader/data/color.vert
new file mode 100644
index 0000000000..c92f71b9e1
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/data/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;
+ float opacity;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/auto/gui/rhi/qshader/data/color.vert.qsb b/tests/auto/gui/rhi/qshader/data/color.vert.qsb
new file mode 100644
index 0000000000..7d02d823d2
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/data/color.vert.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qshader/data/color_simple.vert.qsb b/tests/auto/gui/rhi/qshader/data/color_simple.vert.qsb
new file mode 100644
index 0000000000..c82ba7e8e7
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/data/color_simple.vert.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qshader/qshader.pro b/tests/auto/gui/rhi/qshader/qshader.pro
new file mode 100644
index 0000000000..5d9ef8304d
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/qshader.pro
@@ -0,0 +1,8 @@
+TARGET = tst_qshader
+CONFIG += testcase
+
+QT += testlib gui-private
+
+SOURCES += tst_qshader.cpp
+
+RESOURCES += qshader.qrc
diff --git a/tests/auto/gui/rhi/qshader/qshader.qrc b/tests/auto/gui/rhi/qshader/qshader.qrc
new file mode 100644
index 0000000000..f161d8aad6
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/qshader.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/rhi/qshader/tst_qshader.cpp b/tests/auto/gui/rhi/qshader/tst_qshader.cpp
new file mode 100644
index 0000000000..21f0cc7895
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/tst_qshader.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QFile>
+#include <QtGui/private/qshaderdescription_p_p.h>
+#include <QtGui/private/qshader_p_p.h>
+
+class tst_QShader : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void simpleCompileCheckResults();
+ void genVariants();
+ void shaderDescImplicitSharing();
+ void bakedShaderImplicitSharing();
+};
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+void tst_QShader::simpleCompileCheckResults()
+{
+ QShader s = getShader(QLatin1String(":/data/color_simple.vert.qsb"));
+ QVERIFY(s.isValid());
+ QCOMPARE(s.availableShaders().count(), 1);
+
+ const QShaderCode shader = s.shader(QShaderKey(QShader::SpirvShader,
+ QShaderVersion(100)));
+ QVERIFY(!shader.shader().isEmpty());
+ QCOMPARE(shader.entryPoint(), QByteArrayLiteral("main"));
+
+ const QShaderDescription desc = s.description();
+ QVERIFY(desc.isValid());
+ QCOMPARE(desc.inputVariables().count(), 2);
+ for (const QShaderDescription::InOutVariable &v : desc.inputVariables()) {
+ switch (v.location) {
+ case 0:
+ QCOMPARE(v.name, QLatin1String("position"));
+ QCOMPARE(v.type, QShaderDescription::Vec4);
+ break;
+ case 1:
+ QCOMPARE(v.name, QLatin1String("color"));
+ QCOMPARE(v.type, QShaderDescription::Vec3);
+ break;
+ default:
+ QVERIFY(false);
+ break;
+ }
+ }
+ QCOMPARE(desc.outputVariables().count(), 1);
+ for (const QShaderDescription::InOutVariable &v : desc.outputVariables()) {
+ switch (v.location) {
+ case 0:
+ QCOMPARE(v.name, QLatin1String("v_color"));
+ QCOMPARE(v.type, QShaderDescription::Vec3);
+ break;
+ default:
+ QVERIFY(false);
+ break;
+ }
+ }
+ QCOMPARE(desc.uniformBlocks().count(), 1);
+ const QShaderDescription::UniformBlock blk = desc.uniformBlocks().first();
+ QCOMPARE(blk.blockName, QLatin1String("buf"));
+ QCOMPARE(blk.structName, QLatin1String("ubuf"));
+ QCOMPARE(blk.size, 68);
+ QCOMPARE(blk.binding, 0);
+ QCOMPARE(blk.descriptorSet, 0);
+ QCOMPARE(blk.members.count(), 2);
+ for (int i = 0; i < blk.members.count(); ++i) {
+ const QShaderDescription::BlockVariable v = blk.members[i];
+ switch (i) {
+ case 0:
+ QCOMPARE(v.offset, 0);
+ QCOMPARE(v.size, 64);
+ QCOMPARE(v.name, QLatin1String("mvp"));
+ QCOMPARE(v.type, QShaderDescription::Mat4);
+ QCOMPARE(v.matrixStride, 16);
+ break;
+ case 1:
+ QCOMPARE(v.offset, 64);
+ QCOMPARE(v.size, 4);
+ QCOMPARE(v.name, QLatin1String("opacity"));
+ QCOMPARE(v.type, QShaderDescription::Float);
+ break;
+ default:
+ QVERIFY(false);
+ break;
+ }
+ }
+}
+
+void tst_QShader::genVariants()
+{
+ QShader s = getShader(QLatin1String(":/data/color.vert.qsb"));
+ // spirv, glsl 100, glsl 330, glsl 120, hlsl 50, msl 12
+ // + batchable variants
+ QVERIFY(s.isValid());
+ QCOMPARE(s.availableShaders().count(), 2 * 6);
+
+ int batchableVariantCount = 0;
+ int batchableGlslVariantCount = 0;
+ for (const QShaderKey &key : s.availableShaders()) {
+ if (key.sourceVariant() == QShader::BatchableVertexShader) {
+ ++batchableVariantCount;
+ if (key.source() == QShader::GlslShader) {
+ ++batchableGlslVariantCount;
+ const QByteArray src = s.shader(key).shader();
+ QVERIFY(src.contains(QByteArrayLiteral("_qt_order * ")));
+ }
+ }
+ }
+ QCOMPARE(batchableVariantCount, 6);
+ QCOMPARE(batchableGlslVariantCount, 3);
+}
+
+void tst_QShader::shaderDescImplicitSharing()
+{
+ QShader s = getShader(QLatin1String(":/data/color_simple.vert.qsb"));
+ QVERIFY(s.isValid());
+ QCOMPARE(s.availableShaders().count(), 1);
+ QVERIFY(s.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+
+ QShaderDescription d0 = s.description();
+ QVERIFY(d0.isValid());
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+
+ QShaderDescription d1 = d0;
+ QVERIFY(QShaderDescriptionPrivate::get(&d0) == QShaderDescriptionPrivate::get(&d1));
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+ QCOMPARE(d1.inputVariables().count(), 2);
+ QCOMPARE(d1.outputVariables().count(), 1);
+ QCOMPARE(d1.uniformBlocks().count(), 1);
+
+ d1.detach();
+ QVERIFY(QShaderDescriptionPrivate::get(&d0) != QShaderDescriptionPrivate::get(&d1));
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+ QCOMPARE(d1.inputVariables().count(), 2);
+ QCOMPARE(d1.outputVariables().count(), 1);
+ QCOMPARE(d1.uniformBlocks().count(), 1);
+}
+
+void tst_QShader::bakedShaderImplicitSharing()
+{
+ QShader s0 = getShader(QLatin1String(":/data/color_simple.vert.qsb"));
+ QVERIFY(s0.isValid());
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+
+ {
+ QShader s1 = s0;
+ QVERIFY(QShaderPrivate::get(&s0) == QShaderPrivate::get(&s1));
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s1.availableShaders().count(), 1);
+ QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s0.stage(), s1.stage());
+ QCOMPARE(s0, s1);
+
+ s1.detach();
+ QVERIFY(QShaderPrivate::get(&s0) != QShaderPrivate::get(&s1));
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s1.availableShaders().count(), 1);
+ QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s0.stage(), s1.stage());
+ QCOMPARE(s0, s1);
+ }
+
+ {
+ QShader s1 = s0;
+ QVERIFY(QShaderPrivate::get(&s0) == QShaderPrivate::get(&s1));
+ QCOMPARE(s0.stage(), s1.stage());
+
+ s1.setStage(QShader::FragmentStage); // call a setter to trigger a detach
+ QVERIFY(QShaderPrivate::get(&s0) != QShaderPrivate::get(&s1));
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s1.availableShaders().count(), 1);
+ QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QShaderDescription d0 = s0.description();
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+ QShaderDescription d1 = s1.description();
+ QCOMPARE(d1.inputVariables().count(), 2);
+ QCOMPARE(d1.outputVariables().count(), 1);
+ QCOMPARE(d1.uniformBlocks().count(), 1);
+ QVERIFY(s0 != s1);
+ }
+}
+
+#include <tst_qshader.moc>
+QTEST_MAIN(tst_QShader)
diff --git a/tests/auto/gui/rhi/rhi.pro b/tests/auto/gui/rhi/rhi.pro
new file mode 100644
index 0000000000..cc548b7b8a
--- /dev/null
+++ b/tests/auto/gui/rhi/rhi.pro
@@ -0,0 +1,4 @@
+TEMPLATE=subdirs
+SUBDIRS= \
+ qshader \
+ qrhi
diff --git a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
index cfd24a8701..7dbeb13aa7 100644
--- a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
+++ b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
@@ -835,17 +835,32 @@ void tst_QCssParser::colorValue_data()
QTest::newRow("hexcolor") << "color: #12af0e" << QColor(0x12, 0xaf, 0x0e);
QTest::newRow("functional1") << "color: rgb(21, 45, 73)" << QColor(21, 45, 73);
QTest::newRow("functional2") << "color: rgb(100%, 0%, 100%)" << QColor(0xff, 0, 0xff);
+ QTest::newRow("rgb") << "color: rgb(10, 20, 30)" << QColor(10, 20, 30);
QTest::newRow("rgba") << "color: rgba(10, 20, 30, 40)" << QColor(10, 20, 30, 40);
QTest::newRow("rgbaf") << "color: rgba(10, 20, 30, 0.5)" << QColor(10, 20, 30, 127);
- QTest::newRow("rgb") << "color: rgb(10, 20, 30, 40)" << QColor(10, 20, 30, 40);
- QTest::newRow("hsl") << "color: hsv(10, 20, 30)" << QColor::fromHsv(10, 20, 30, 255);
- QTest::newRow("hsla") << "color: hsva(10, 20, 30, 40)" << QColor::fromHsv(10, 20, 30, 40);
+ QTest::newRow("hsv") << "color: hsv(10, 20, 30)" << QColor::fromHsv(10, 20, 30);
+ QTest::newRow("hsva") << "color: hsva(10, 20, 30, 40)" << QColor::fromHsv(10, 20, 30, 40);
+ // the percent and float values are well chosen to not get in trouble due to rounding errors
+ QTest::newRow("hsva-percent") << "color: hsva(100%, 20%, 40%, 60%)" << QColor::fromHsv(359, 51, 102, 153);
+ QTest::newRow("hsva-float") << "color: hsva(180, 20%, 40%, 0.6)" << QColor::fromHsvF(0.5, 0.2, 0.4, 0.6);
+ QTest::newRow("hsl") << "color: hsl(60, 100%, 50%)" << QColor::fromHsl(60., 255, 127);
+ QTest::newRow("hsla") << "color: hsla(240, 255, 127, 192)" << QColor::fromHsl(240, 255, 127, 192);
+ QTest::newRow("hsla-percent") << "color: hsla(100%, 80%, 40%, 0%)" << QColor::fromHsl(359, 204, 102, 0);
+ QTest::newRow("hsla-float") << "color: hsla(252, 40%, 60%, 0.2)" << QColor::fromHslF(0.7, 0.4, 0.6, 0.2);
QTest::newRow("invalid1") << "color: rgb(why, does, it, always, rain, on, me)" << QColor();
QTest::newRow("invalid2") << "color: rgba(i, meant, norway)" << QColor();
QTest::newRow("invalid3") << "color: rgb(21)" << QColor();
+ QTest::newRow("invalid4") << "color: rgbx(1, 2, 3)" << QColor();
+ QTest::newRow("invalid5") << "color: rgbax(1, 2, 3, 4)" << QColor();
+ QTest::newRow("invalid6") << "color: hsv(360, 0, 0)" << QColor();
+ QTest::newRow("invalid7") << "color: hsla(1, a, 1, 21)" << QColor();
QTest::newRow("role") << "color: palette(base)" << qApp->palette().color(QPalette::Base);
QTest::newRow("role2") << "color: palette( window-text ) " << qApp->palette().color(QPalette::WindowText);
QTest::newRow("transparent") << "color: transparent" << QColor(Qt::transparent);
+
+ // ### Qt6: no longer valid
+ QTest::newRow("rgb-invalid") << "color: rgb(10, 20, 30, 40)" << QColor(10, 20, 30, 40);
+ QTest::newRow("rgba-invalid") << "color: rgba(10, 20, 30)" << QColor(10, 20, 30, 255);
}
void tst_QCssParser::colorValue()
diff --git a/tests/auto/gui/text/qfont/qfont.pro b/tests/auto/gui/text/qfont/qfont.pro
index 048d952faf..96cd4cfdab 100644
--- a/tests/auto/gui/text/qfont/qfont.pro
+++ b/tests/auto/gui/text/qfont/qfont.pro
@@ -4,3 +4,4 @@ QT += testlib
QT += core-private gui-private
qtHaveModule(widgets): QT += widgets
SOURCES += tst_qfont.cpp
+RESOURCES += testfont.qrc
diff --git a/tests/auto/gui/text/qfont/testfont.qrc b/tests/auto/gui/text/qfont/testfont.qrc
new file mode 100644
index 0000000000..cf51e4a2b4
--- /dev/null
+++ b/tests/auto/gui/text/qfont/testfont.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>weirdfont.otf</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/text/qfont/tst_qfont.cpp b/tests/auto/gui/text/qfont/tst_qfont.cpp
index 8090f38a2c..901284e131 100644
--- a/tests/auto/gui/text/qfont/tst_qfont.cpp
+++ b/tests/auto/gui/text/qfont/tst_qfont.cpp
@@ -66,6 +66,12 @@ private slots:
void fromStringWithoutStyleName();
void sharing();
+ void familyNameWithCommaQuote_data();
+ void familyNameWithCommaQuote();
+ void setFamilies_data();
+ void setFamilies();
+ void setFamiliesAndFamily_data();
+ void setFamiliesAndFamily();
};
// Testing get/set functions
@@ -116,6 +122,14 @@ void tst_QFont::exactMatch()
QVERIFY(!QFont("sans-serif").exactMatch());
QVERIFY(!QFont("serif").exactMatch());
QVERIFY(!QFont("monospace").exactMatch());
+
+ font.setFamilies(QStringList() << "BogusFont");
+ QVERIFY(!font.exactMatch());
+ QVERIFY(!QFont("sans").exactMatch());
+ QVERIFY(!QFont("sans-serif").exactMatch());
+ QVERIFY(!QFont("serif").exactMatch());
+ QVERIFY(!QFont("monospace").exactMatch());
+
}
void tst_QFont::italicOblique()
@@ -277,6 +291,12 @@ void tst_QFont::resolve()
QCOMPARE(f4.pointSize(), 45);
f4 = f4.resolve(f3);
QCOMPARE(f4.pointSize(), 55);
+
+ QFont font5, font6;
+ const QStringList fontFamilies = { QStringLiteral("Arial") };
+ font5.setFamilies(fontFamilies);
+ font6 = font6.resolve(font5);
+ QCOMPARE(font6.families(), fontFamilies);
}
#ifndef QT_NO_WIDGETS
@@ -589,40 +609,143 @@ void tst_QFont::sharing()
QFont f;
f.setStyleHint(QFont::Serif);
f.exactMatch(); // loads engine
- QCOMPARE(QFontPrivate::get(f)->ref.load(), 1);
+ QCOMPARE(QFontPrivate::get(f)->ref.loadRelaxed(), 1);
QVERIFY(QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f)->engineData->ref.load(), 1 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f)->engineData->ref.loadRelaxed(), 1 + refs_by_cache);
QFont f2(f);
QCOMPARE(QFontPrivate::get(f2), QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 2);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 2);
QVERIFY(QFontPrivate::get(f2)->engineData);
QCOMPARE(QFontPrivate::get(f2)->engineData, QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 1 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.loadRelaxed(), 1 + refs_by_cache);
f2.setKerning(!f.kerning());
QVERIFY(QFontPrivate::get(f2) != QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 1);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 1);
QVERIFY(QFontPrivate::get(f2)->engineData);
QCOMPARE(QFontPrivate::get(f2)->engineData, QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 2 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.loadRelaxed(), 2 + refs_by_cache);
f2 = f;
QCOMPARE(QFontPrivate::get(f2), QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 2);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 2);
QVERIFY(QFontPrivate::get(f2)->engineData);
QCOMPARE(QFontPrivate::get(f2)->engineData, QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 1 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.loadRelaxed(), 1 + refs_by_cache);
if (f.pointSize() > 0)
f2.setPointSize(f.pointSize() * 2 / 3);
else
f2.setPixelSize(f.pixelSize() * 2 / 3);
QVERIFY(QFontPrivate::get(f2) != QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 1);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 1);
QVERIFY(!QFontPrivate::get(f2)->engineData);
QVERIFY(QFontPrivate::get(f2)->engineData != QFontPrivate::get(f)->engineData);
}
+void tst_QFont::familyNameWithCommaQuote_data()
+{
+ QTest::addColumn<QString>("familyName");
+ QTest::addColumn<QString>("chosenFamilyName");
+
+ const QString standardFont(QFont().defaultFamily());
+ if (standardFont.isEmpty())
+ QSKIP("No default font available on the system");
+ const QString weirdFont(QLatin1String("'My, weird'' font name',"));
+ const QString commaSeparated(standardFont + QLatin1String(",Times New Roman"));
+ const QString commaSeparatedWeird(weirdFont + QLatin1String(",") + standardFont);
+ const QString commaSeparatedBogus(QLatin1String("BogusFont,") + standardFont);
+
+ QTest::newRow("standard") << standardFont << standardFont;
+ QTest::newRow("weird") << weirdFont << weirdFont;
+ QTest::newRow("commaSeparated") << commaSeparated << standardFont;
+ QTest::newRow("commaSeparatedWeird") << commaSeparatedWeird << weirdFont;
+ QTest::newRow("commaSeparatedBogus") << commaSeparatedBogus << standardFont;
+}
+
+void tst_QFont::familyNameWithCommaQuote()
+{
+ QFETCH(QString, familyName);
+ QFETCH(QString, chosenFamilyName);
+
+ const int weirdFontId = QFontDatabase::addApplicationFont(":/weirdfont.otf");
+
+ QVERIFY(weirdFontId != -1);
+ QFont f(familyName);
+ QCOMPARE(f.family(), familyName);
+ QCOMPARE(QFontInfo(f).family(), chosenFamilyName);
+
+ QFontDatabase::removeApplicationFont(weirdFontId);
+}
+
+void tst_QFont::setFamilies_data()
+{
+ QTest::addColumn<QStringList>("families");
+ QTest::addColumn<QString>("chosenFamilyName");
+
+ const QString weirdFont(QLatin1String("'My, weird'' font name',"));
+ const QString standardFont(QFont().defaultFamily());
+ if (standardFont.isEmpty())
+ QSKIP("No default font available on the system");
+
+ QTest::newRow("standard") << (QStringList() << standardFont) << standardFont;
+ QTest::newRow("weird") << (QStringList() << weirdFont) << weirdFont;
+ QTest::newRow("standard-weird") << (QStringList() << standardFont << weirdFont) << standardFont;
+ QTest::newRow("weird-standard") << (QStringList() << weirdFont << standardFont) << weirdFont;
+ QTest::newRow("nonexist-weird") << (QStringList() << "NonExistentFont" << weirdFont) << weirdFont;
+}
+
+void tst_QFont::setFamilies()
+{
+ QFETCH(QStringList, families);
+ QFETCH(QString, chosenFamilyName);
+
+ const int weirdFontId = QFontDatabase::addApplicationFont(":/weirdfont.otf");
+
+ QVERIFY(weirdFontId != -1);
+ QFont f;
+ f.setFamilies(families);
+ QCOMPARE(QFontInfo(f).family(), chosenFamilyName);
+
+ QFontDatabase::removeApplicationFont(weirdFontId);
+}
+
+void tst_QFont::setFamiliesAndFamily_data()
+{
+ QTest::addColumn<QStringList>("families");
+ QTest::addColumn<QString>("family");
+ QTest::addColumn<QString>("chosenFamilyName");
+
+ const QString weirdFont(QLatin1String("'My, weird'' font name',"));
+ const QString defaultFont(QFont().defaultFamily());
+ if (defaultFont.isEmpty())
+ QSKIP("No default font available on the system");
+
+ const QString timesFont(QLatin1String("Times"));
+ const QString nonExistFont(QLatin1String("NonExistentFont"));
+
+ QTest::newRow("firstInFamilies") << (QStringList() << defaultFont << timesFont) << weirdFont << defaultFont;
+ QTest::newRow("secondInFamilies") << (QStringList() << nonExistFont << weirdFont) << defaultFont << weirdFont;
+ QTest::newRow("family") << (QStringList() << nonExistFont) << defaultFont << defaultFont;
+}
+
+void tst_QFont::setFamiliesAndFamily()
+{
+ QFETCH(QStringList, families);
+ QFETCH(QString, family);
+ QFETCH(QString, chosenFamilyName);
+
+ const int weirdFontId = QFontDatabase::addApplicationFont(":/weirdfont.otf");
+
+ QVERIFY(weirdFontId != -1);
+ QFont f;
+ f.setFamilies(families);
+ f.setFamily(family);
+ QCOMPARE(QFontInfo(f).family(), chosenFamilyName);
+
+ QFontDatabase::removeApplicationFont(weirdFontId);
+}
+
QTEST_MAIN(tst_QFont)
#include "tst_qfont.moc"
diff --git a/tests/auto/gui/text/qfont/weirdfont.otf b/tests/auto/gui/text/qfont/weirdfont.otf
new file mode 100644
index 0000000000..b91c559f5b
--- /dev/null
+++ b/tests/auto/gui/text/qfont/weirdfont.otf
Binary files differ
diff --git a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
index fbca313ea3..3d3211c7a2 100644
--- a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
+++ b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
@@ -45,6 +45,8 @@ public:
private slots:
void engineData_data();
void engineData();
+ void engineDataFamilies_data();
+ void engineDataFamilies();
void clear();
};
@@ -109,6 +111,49 @@ void tst_QFontCache::engineData()
QCOMPARE(engineData, QFontPrivate::get(f)->engineData);
}
+void tst_QFontCache::engineDataFamilies_data()
+{
+ QTest::addColumn<QStringList>("families");
+
+ const QStringList multiple = { QLatin1String("invalid"), QLatin1String("Times New Roman") };
+ const QStringList multipleQuotes = { QLatin1String("'invalid'"), QLatin1String("Times New Roman") };
+ const QStringList multiple2 = { QLatin1String("invalid"), QLatin1String("Times New Roman"),
+ QLatin1String("foobar"), QLatin1String("'baz'") };
+
+ QTest::newRow("unquoted-family-name") << QStringList(QLatin1String("Times New Roman"));
+ QTest::newRow("quoted-family-name") << QStringList(QLatin1String("Times New Roman"));
+ QTest::newRow("invalid") << QStringList(QLatin1String("invalid"));
+ QTest::newRow("multiple") << multiple;
+ QTest::newRow("multiple spaces quotes") << multipleQuotes;
+ QTest::newRow("multiple2") << multiple2;
+}
+
+void tst_QFontCache::engineDataFamilies()
+{
+ QFETCH(QStringList, families);
+
+ QFont f;
+ f.setFamily(QString()); // Unset the family as taken from the QGuiApplication default
+ f.setFamilies(families);
+ f.exactMatch(); // loads engine
+ QFontPrivate *d = QFontPrivate::get(f);
+
+ QFontDef req = d->request;
+ // copy-pasted from QFontDatabase::load(), to engineer the cache key
+ if (req.pixelSize == -1) {
+ req.pixelSize = std::floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100;
+ req.pixelSize = qRound(req.pixelSize);
+ }
+ if (req.pointSize < 0)
+ req.pointSize = req.pixelSize*72.0/d->dpi;
+
+ req.families = families;
+
+ QFontEngineData *engineData = QFontCache::instance()->findEngineData(req);
+
+ QCOMPARE(engineData, QFontPrivate::get(f)->engineData);
+}
+
void tst_QFontCache::clear()
{
#ifdef QT_BUILD_INTERNAL
@@ -172,7 +217,7 @@ void tst_QFontCache::clear()
#ifdef QT_BUILD_INTERNAL
QList<QFontEngine *> leakedEngines = QFontEngine_stopCollectingEngines();
-for (int i = 0; i < leakedEngines.size(); ++i) qWarning() << i << leakedEngines.at(i) << leakedEngines.at(i)->ref.load();
+for (int i = 0; i < leakedEngines.size(); ++i) qWarning() << i << leakedEngines.at(i) << leakedEngines.at(i)->ref.loadRelaxed();
// and we are not leaking!
QCOMPARE(leakedEngines.size(), 0);
#endif
diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
index 064e37f73c..2b69801b59 100644
--- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
+++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
@@ -211,8 +211,8 @@ void tst_QFontDatabase::widthTwoTimes()
f.setPixelSize(pixelSize);
QFontMetrics fm(f);
- int w1 = fm.charWidth(text, 0);
- int w2 = fm.charWidth(text, 0);
+ int w1 = fm.horizontalAdvance(text, 0);
+ int w2 = fm.horizontalAdvance(text, 0);
QCOMPARE(w1, w2);
}
diff --git a/tests/auto/gui/text/qglyphrun/BLACKLIST b/tests/auto/gui/text/qglyphrun/BLACKLIST
index 57f32c683d..d8dbdabb4b 100644
--- a/tests/auto/gui/text/qglyphrun/BLACKLIST
+++ b/tests/auto/gui/text/qglyphrun/BLACKLIST
@@ -1,3 +1,4 @@
[mixedScripts]
ubuntu-18.04
b2qt
+windows
diff --git a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
index b7f014d0e2..1429e4cb7f 100644
--- a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
+++ b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
@@ -491,10 +491,6 @@ void tst_QGlyphRun::drawMultiScriptText2()
drawGlyphs.save("drawMultiScriptText2_drawGlyphIndexes.png");
#endif
-#ifdef Q_OS_OSX
- if (drawGlyphs.toImage() != textLayoutDraw.toImage())
- QEXPECT_FAIL("", "See QTBUG-32690", Continue);
-#endif // Q_OS_OSX
QCOMPARE(drawGlyphs, textLayoutDraw);
}
diff --git a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
index d00dc251d8..b091edb64d 100644
--- a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
+++ b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
@@ -681,7 +681,7 @@ static bool checkPixels(const QImage &image,
if (pixel != expectedRgb1 && pixel != expectedRgb2) {
QString message;
QDebug(&message) << "Color mismatch in image" << image
- << "at" << x << ',' << y << ':' << showbase << hex << pixel
+ << "at" << x << ',' << y << ':' << Qt::showbase << Qt::hex << pixel
<< "(expected: " << expectedRgb1 << ',' << expectedRgb2 << ')';
*errorMessage = message.toLocal8Bit();
return false;
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
index 32131352c3..a07181c199 100644
--- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -1137,7 +1137,7 @@ void tst_QTextDocument::toHtml_data()
QTextCharFormat fmt;
fmt.setAnchor(true);
- fmt.setAnchorName("blub");
+ fmt.setAnchorNames({"blub"});
cursor.insertText("Blah", fmt);
QTest::newRow("named anchor") << QTextDocumentFragment(&doc)
diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
index d652bb066d..664ca98a3f 100644
--- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
+++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
@@ -34,6 +34,7 @@
#include <qtextdocumentfragment.h>
#include <qtexttable.h>
#include <qtextlist.h>
+#include <qregularexpression.h>
#include <qdebug.h>
#include <private/qtextdocument_p.h>
@@ -159,6 +160,7 @@ private slots:
void nonZeroMarginOnImport();
void html_charFormatPropertiesUnset();
void html_headings();
+ void html_quotedFontFamily_data();
void html_quotedFontFamily();
void html_spanBackgroundColor();
void defaultFont();
@@ -943,7 +945,7 @@ void tst_QTextDocumentFragment::namedAnchorFragments3()
QCOMPARE(it.fragment().text(), QString::fromLatin1("T"));
QVERIFY(it.fragment().charFormat().isAnchor());
- QCOMPARE(it.fragment().charFormat().anchorName(), QString("target"));
+ QCOMPARE(it.fragment().charFormat().anchorNames().constFirst(), QLatin1String("target"));
QStringList targets; targets << "target" << "target2";
QCOMPARE(it.fragment().charFormat().anchorNames(), targets);
@@ -1924,7 +1926,7 @@ void tst_QTextDocumentFragment::html_nobr()
QString text = doc->begin().begin().fragment().text();
QString expectedText = input;
- expectedText.replace(QRegExp("\\s+"), QString(QChar::Nbsp));
+ expectedText.replace(QRegularExpression("\\s+"), QString(QChar::Nbsp));
QCOMPARE(text, expectedText);
}
@@ -2206,23 +2208,45 @@ void tst_QTextDocumentFragment::html_headings()
QCOMPARE(doc->blockCount(), 2);
}
-void tst_QTextDocumentFragment::html_quotedFontFamily()
+void tst_QTextDocumentFragment::html_quotedFontFamily_data()
{
- setHtml("<div style=\"font-family: 'Foo Bar';\">Test</div>");
- QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
-
- setHtml("<div style='font-family: \"Foo Bar\";'>Test</div>");
- QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
-
- setHtml("<div style='font-family: \"Foo Bar\";'>Test</div>");
- QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
-
- setHtml("<div style='font-family: Foo\n Bar;'>Test</div>");
- QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar"));
+ QTest::addColumn<QString>("html");
+ QTest::addColumn<QString>("fontFamily");
+ QTest::addColumn<QStringList>("fontFamilies");
+
+ const QString fooFamily = QLatin1String("Foo Bar");
+ const QString weirdFamily = QLatin1String("'Weird, & font '' name',");
+
+ QTest::newRow("data1") << QString("<div style=\"font-family: 'Foo Bar';\">Test</div>")
+ << fooFamily << QStringList(fooFamily);
+ QTest::newRow("data2") << QString("<div style='font-family: \"Foo Bar\";'>Test</div>")
+ << QString("Foo Bar") << QStringList("Foo Bar");
+ QTest::newRow("data3") << QString("<div style='font-family: Foo\n Bar;'>Test</div>")
+ << fooFamily << QStringList(fooFamily);
+ QTest::newRow("data4") << QString("<div style='font-family: Foo\n Bar, serif, \"bar foo\";'>Test"
+ "</div>")
+ << fooFamily << (QStringList() << "Foo Bar" << "serif" << "bar foo");
+ QTest::newRow("data5") << QString("<div style='font-family: \"\\'Weird, & font \\'\\' name\\',"
+ "\";'>Test</div>")
+ << weirdFamily << QStringList(weirdFamily);
+ QTest::newRow("data6") << QString("<div style='font-family: \"\\'Weird, & font \\'\\' name\\',"
+ "\";'>Test</div>")
+ << weirdFamily << QStringList(weirdFamily);
+ QTest::newRow("data7") << QString("<div style='font-family: \"\\'Weird, & font \\'\\' name\\',\", "
+ "serif, \"bar foo\";'>Test</div>")
+ << weirdFamily
+ << (QStringList() << weirdFamily << "serif" << "bar foo");
+}
- setHtml("<div style='font-family: Foo\n Bar, serif, \"bar foo\";'>Test</div>");
- QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), QString("Foo Bar,serif,bar foo"));
+void tst_QTextDocumentFragment::html_quotedFontFamily()
+{
+ QFETCH(QString, html);
+ QFETCH(QString, fontFamily);
+ QFETCH(QStringList, fontFamilies);
+ setHtml(html);
+ QCOMPARE(doc->begin().begin().fragment().charFormat().fontFamily(), fontFamily);
+ QCOMPARE(doc->begin().begin().fragment().charFormat().font().families(), fontFamilies);
}
void tst_QTextDocumentFragment::defaultFont()
diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
index 9c477589f9..aee2f970fe 100644
--- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
@@ -138,6 +138,7 @@ private slots:
void noModificationOfInputString();
void superscriptCrash_qtbug53911();
void showLineAndParagraphSeparatorsCrash();
+ void koreanWordWrap();
private:
QFont testFont;
@@ -2227,7 +2228,6 @@ void tst_QTextLayout::superscriptCrash_qtbug53911()
for (int j = 0; j < 4; ++j) {
QTextLayout* newTextLayout = new QTextLayout();
newTextLayout->setText(layoutText);
- QList<QTextLayout::FormatRange> formatRanges;
QTextLayout::FormatRange formatRange;
formatRange.format.setFont(QFont());
@@ -2256,8 +2256,7 @@ void tst_QTextLayout::superscriptCrash_qtbug53911()
formatRange.start = 0;
formatRange.length = layoutText.size();
- formatRanges << formatRange;
- newTextLayout->setAdditionalFormats(formatRanges);
+ newTextLayout->setFormats({formatRange});
textLayouts.push_front(newTextLayout);
}
@@ -2288,10 +2287,7 @@ void tst_QTextLayout::nbspWithFormat()
formatRange.length = 1;
formatRange.format.setFontUnderline(true);
- QList<QTextLayout::FormatRange> overrides;
- overrides.append(formatRange);
-
- layout.setAdditionalFormats(overrides);
+ layout.setFormats({formatRange});
layout.beginLayout();
forever {
@@ -2309,5 +2305,30 @@ void tst_QTextLayout::nbspWithFormat()
QCOMPARE(layout.lineAt(1).textLength(), s2.length() + 1 + s3.length());
}
+void tst_QTextLayout::koreanWordWrap()
+{
+ QString s = QString::fromUtf8("안녕하세요 여러분!");
+ QTextLayout layout;
+ QTextOption option = layout.textOption();
+ option.setWrapMode(QTextOption::WordWrap);
+ option.setFlags(QTextOption::Flag(QTextOption::IncludeTrailingSpaces));
+ layout.setTextOption(option);
+ layout.setText(s);
+
+ QFontMetrics metrics(layout.font());
+
+ layout.beginLayout();
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+ line.setLineWidth(metrics.horizontalAdvance(s) * 0.8);
+ }
+ layout.endLayout();
+ QCOMPARE(layout.lineCount(), 2);
+ QCOMPARE(layout.lineAt(0).textLength(), 6);
+ QCOMPARE(layout.lineAt(1).textLength(), 4);
+}
+
QTEST_MAIN(tst_QTextLayout)
#include "tst_qtextlayout.moc"
diff --git a/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp b/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
index d623ce4044..93e40e7f23 100644
--- a/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
+++ b/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
@@ -314,7 +314,7 @@ void tst_QTextList::partialRemoval()
selection.deleteChar(); // deletes the second list
QVERIFY(!secondList);
- QVERIFY(!firstList->isEmpty());
+ QVERIFY(firstList->count() > 0);
doc->undo();
}
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md b/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md
new file mode 100644
index 0000000000..99eb633d17
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md
@@ -0,0 +1,28 @@
+# heading
+- bullet 1
+ continuation line 1, indented via tab
+- bullet 2
+ continuation line 2, indented via 4 spaces
+- bullet 3
+
+ continuation paragraph 3, indented via tab
+
+ - bullet 3.1
+
+ continuation paragraph 3.1, indented via 4 spaces
+
+ - bullet 3.2
+ continuation line, indented via 2 tabs
+- bullet 4
+
+ continuation paragraph 4, indented via 4 spaces
+ and continuing onto another line too
+
+- bullet 5
+
+ continuation paragraph 5, indented via 2 spaces and continuing onto another
+ line too
+
+- bullet 6
+
+plain old paragraph at the end
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md b/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md
new file mode 100644
index 0000000000..7a0d5388ad
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md
@@ -0,0 +1,17 @@
+Heading
+-------
+***
+stars
+- bullet
+ ** not a bullet or a rule, just two stars
+- [ ] unchecked
+
+ --- indented too far, so not a rule
+* * *
+stars with tabs between
+***
+stars with whitespace after
+---
+hyphens with whitespace after
+_____
+underscores with whitespace after
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
new file mode 100644
index 0000000000..7b7fb61244
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_qtextmarkdownimporter
+QT += core-private gui-private testlib
+SOURCES += tst_qtextmarkdownimporter.cpp
+TESTDATA += \
+ data/thematicBreaks.md \
+ data/headingBulletsContinuations.md \
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
new file mode 100644
index 0000000000..8f51a7a474
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QTextDocument>
+#include <QTextCursor>
+#include <QTextBlock>
+#include <QTextList>
+#include <QTextTable>
+#include <QBuffer>
+#include <QDebug>
+
+#include <private/qtextmarkdownimporter_p.h>
+
+// #define DEBUG_WRITE_HTML
+
+Q_LOGGING_CATEGORY(lcTests, "qt.text.tests")
+
+static const QChar LineBreak = QChar(0x2028);
+static const QChar Tab = QLatin1Char('\t');
+static const QChar Space = QLatin1Char(' ');
+static const QChar Period = QLatin1Char('.');
+
+class tst_QTextMarkdownImporter : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void headingBulletsContinuations();
+ void thematicBreaks();
+};
+
+void tst_QTextMarkdownImporter::headingBulletsContinuations()
+{
+ const QStringList expectedBlocks = QStringList() <<
+ "" << // we could do without this blank line before the heading, but currently it happens
+ "heading" <<
+ "bullet 1 continuation line 1, indented via tab" <<
+ "bullet 2 continuation line 2, indented via 4 spaces" <<
+ "bullet 3" <<
+ "continuation paragraph 3, indented via tab" <<
+ "bullet 3.1" <<
+ "continuation paragraph 3.1, indented via 4 spaces" <<
+ "bullet 3.2 continuation line, indented via 2 tabs" <<
+ "bullet 4" <<
+ "continuation paragraph 4, indented via 4 spaces and continuing onto another line too" <<
+ "bullet 5" <<
+ // indenting by only 2 spaces is perhaps non-standard but currently is OK
+ "continuation paragraph 5, indented via 2 spaces and continuing onto another line too" <<
+ "bullet 6" <<
+ "plain old paragraph at the end";
+
+ QFile f(QFINDTESTDATA("data/headingBulletsContinuations.md"));
+ QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
+ QString md = QString::fromUtf8(f.readAll());
+ f.close();
+
+ QTextDocument doc;
+ QTextMarkdownImporter(QTextMarkdownImporter::DialectGitHub).import(&doc, md);
+ QTextFrame::iterator iterator = doc.rootFrame()->begin();
+ QTextFrame *currentFrame = iterator.currentFrame();
+ QStringList::const_iterator expectedIt = expectedBlocks.constBegin();
+ int i = 0;
+ while (!iterator.atEnd()) {
+ // There are no child frames
+ QCOMPARE(iterator.currentFrame(), currentFrame);
+ // Check whether we got the right child block
+ QTextBlock block = iterator.currentBlock();
+ QCOMPARE(block.text().contains(LineBreak), false);
+ QCOMPARE(block.text().contains(Tab), false);
+ QVERIFY(!block.text().startsWith(Space));
+ int expectedIndentation = 0;
+ if (block.text().contains(QLatin1String("continuation paragraph")))
+ expectedIndentation = (block.text().contains(Period) ? 2 : 1);
+ qCDebug(lcTests) << i << "child block" << block.text() << "indentation" << block.blockFormat().indent();
+ QVERIFY(expectedIt != expectedBlocks.constEnd());
+ QCOMPARE(block.text(), *expectedIt);
+ if (i > 2)
+ QCOMPARE(block.blockFormat().indent(), expectedIndentation);
+ ++iterator;
+ ++expectedIt;
+ ++i;
+ }
+ QCOMPARE(expectedIt, expectedBlocks.constEnd());
+
+#ifdef DEBUG_WRITE_HTML
+ {
+ QFile out("/tmp/headingBulletsContinuations.html");
+ out.open(QFile::WriteOnly);
+ out.write(doc.toHtml().toLatin1());
+ out.close();
+ }
+#endif
+}
+
+void tst_QTextMarkdownImporter::thematicBreaks()
+{
+ int horizontalRuleCount = 0;
+ int textLinesCount = 0;
+
+ QFile f(QFINDTESTDATA("data/thematicBreaks.md"));
+ QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
+ QString md = QString::fromUtf8(f.readAll());
+ f.close();
+
+ QTextDocument doc;
+ QTextMarkdownImporter(QTextMarkdownImporter::DialectGitHub).import(&doc, md);
+ QTextFrame::iterator iterator = doc.rootFrame()->begin();
+ QTextFrame *currentFrame = iterator.currentFrame();
+ int i = 0;
+ while (!iterator.atEnd()) {
+ // There are no child frames
+ QCOMPARE(iterator.currentFrame(), currentFrame);
+ // Check whether the block is text or a horizontal rule
+ QTextBlock block = iterator.currentBlock();
+ if (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth))
+ ++horizontalRuleCount;
+ else if (!block.text().isEmpty())
+ ++textLinesCount;
+ qCDebug(lcTests) << i << (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth) ? QLatin1String("- - -") : block.text());
+ ++iterator;
+ ++i;
+ }
+ QCOMPARE(horizontalRuleCount, 5);
+ QCOMPARE(textLinesCount, 9);
+
+#ifdef DEBUG_WRITE_HTML
+ {
+ QFile out("/tmp/thematicBreaks.html");
+ out.open(QFile::WriteOnly);
+ out.write(doc.toHtml().toLatin1());
+ out.close();
+ }
+#endif
+}
+
+QTEST_MAIN(tst_QTextMarkdownImporter)
+#include "tst_qtextmarkdownimporter.moc"
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST b/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST
new file mode 100644
index 0000000000..fc9e5a9efe
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST
@@ -0,0 +1,3 @@
+[rewriteDocument]
+winrt # QTBUG-54623
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
new file mode 100644
index 0000000000..6336d0219f
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
@@ -0,0 +1,62 @@
+In 1958, Mahatma Gandhi was quoted as follows:
+
+> The Earth provides enough to satisfy every man's need but not for every man's
+> greed.
+
+In [The CommonMark Specification](https://spec.commonmark.org/0.29/) John
+MacFarlane writes:
+
+> What distinguishes Markdown from many other lightweight markup syntaxes,
+> which are often easier to write, is its readability. As Gruber writes:
+
+> > The overriding design goal for Markdown's formatting syntax is to make it
+> > as readable as possible. The idea is that a Markdown-formatted document should
+> > be publishable as-is, as plain text, without looking like it's been marked up
+> > with tags or formatting instructions. (
+> > [http://daringfireball.net/projects/markdown/](http://daringfireball.net/projects/markdown/)
+> > )
+
+> The point can be illustrated by comparing a sample of AsciiDoc with an
+> equivalent sample of Markdown. Here is a sample of AsciiDoc from the AsciiDoc
+> manual:
+
+> ``` AsciiDoc
+> 1. List item one.
+> +
+> List item one continued with a second paragraph followed by an
+> Indented block.
+> +
+> .................
+> $ ls *.sh
+> $ mv *.sh ~/tmp
+> .................
+> +
+> List item continued with a third paragraph.
+>
+> 2. List item two continued with an open block.
+> ...
+> ```
+The quotation includes an embedded quotation and a code quotation and ends with
+an ellipsis due to being incomplete.
+
+Now let's have an indented code block:
+
+ #include <stdio.h>
+
+ int main(void)
+ {
+ printf("# hello markdown\n");
+ return 0;
+ }
+
+and end with a fenced code block:
+~~~ pseudocode
+#include <something.h>
+#include <else.h>
+
+a block {
+ a statement;
+ another statement;
+}
+~~~
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/example.md b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md
new file mode 100644
index 0000000000..0c3f34e09d
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md
@@ -0,0 +1,95 @@
+# QTextEdit
+
+The QTextEdit widget is an advanced editor that supports formatted rich text.
+It can be used to display HTML and other rich document formats. Internally,
+QTextEdit uses the QTextDocument class to describe both the high-level
+structure of each document and the low-level formatting of paragraphs.
+
+If you are viewing this document in the textedit example, you can edit this
+document to explore Qt's rich text editing features. We have included some
+comments in each of the following sections to encourage you to experiment.
+
+## Font and Paragraph Styles
+
+QTextEdit supports **bold**, *italic*, and ~~strikethrough~~ font styles, and can
+display multicolored text. Font families such as Times New Roman and `Courier`
+can also be used directly. *If you place the cursor in a region of styled text,
+the controls in the tool bars will change to reflect the current style.*
+
+Paragraphs can be formatted so that the text is left-aligned, right-aligned,
+centered, or fully justified.
+
+*Try changing the alignment of some text and resize the editor to see how the
+text layout changes.*
+
+## Lists
+
+Different kinds of lists can be included in rich text documents. Standard
+bullet lists can be nested, using different symbols for each level of the list:
+
+- Disc symbols are typically used for top-level list items.
+ * Circle symbols can be used to distinguish between items in lower-level
+ lists.
+ + Square symbols provide a reasonable alternative to discs and circles.
+
+Ordered lists can be created that can be used for tables of contents. Different
+characters can be used to enumerate items, and we can use both Roman and Arabic
+numerals in the same list structure:
+
+1. Introduction
+2. Qt Tools
+ 1) Qt Assistant
+ 2) Qt Designer
+ 1. Form Editor
+ 2. Component Architecture
+ 3) Qt Linguist
+
+The list will automatically be renumbered if you add or remove items. *Try
+adding new sections to the above list or removing existing item to see the
+numbers change.*
+
+## Images
+
+Inline images are treated like ordinary ranges of characters in the text
+editor, so they flow with the surrounding text. Images can also be selected in
+the same way as text, making it easy to cut, copy, and paste them.
+
+![image](images/logo32.png) *Try to select this image by clicking and dragging
+over it with the mouse, or use the text cursor to select it by holding down
+Shift and using the arrow keys. You can then cut or copy it, and paste it into
+different parts of this document.*
+
+## Tables
+
+QTextEdit can arrange and format tables, supporting features such as row and
+column spans, text formatting within cells, and size constraints for columns.
+
+
+| |Development Tools |Programming Techniques |Graphical User Interfaces|
+|-------------|------------------------------------|---------------------------|-------------------------|
+|9:00 - 11:00 |Introduction to Qt |||
+|11:00 - 13:00|Using qmake |Object-oriented Programming|Layouts in Qt |
+|13:00 - 15:00|Qt Designer Tutorial |Extreme Programming |Writing Custom Styles |
+|15:00 - 17:00|Qt Linguist and Internationalization|  |  |
+
+*Try adding text to the cells in the table and experiment with the alignment of
+the paragraphs.*
+
+## Hyperlinks
+
+QTextEdit is designed to support hyperlinks between documents, and this feature
+is used extensively in
+[Qt Assistant](http://doc.qt.io/qt-5/qtassistant-index.html). Hyperlinks are
+automatically created when an HTML file is imported into an editor. Since the
+rich text framework supports hyperlinks natively, they can also be created
+programatically.
+
+## Undo and Redo
+
+Full support for undo and redo operations is built into QTextEdit and the
+underlying rich text framework. Operations on a document can be packaged
+together to make editing a more comfortable experience for the user.
+
+*Try making changes to this document and press `Ctrl+Z` to undo them. You can
+always recover the original contents of the document.*
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md b/tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md
new file mode 100644
index 0000000000..d5d14fb168
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md
@@ -0,0 +1,12 @@
+# heading 1
+
+- list item 1
+- list item 2
+
+## heading 2
+
+1) list item 1
+2) list item 2
+
+the end paragraph
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md b/tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md
new file mode 100644
index 0000000000..dacb0acf77
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md
@@ -0,0 +1,13 @@
+[The CommonMark Specification](https://spec.commonmark.org/0.29/) is the
+conservative formal specification of the Markdown format, while
+[GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown)
+adds extra features such as task lists and tables.
+
+Qt owes thanks to the authors of the [MD4C parser](https://github.com/mity/md4c)
+for making markdown import possible. The QTextMarkdownWriter class does not
+have such dependencies, and also has not yet been tested as extensively, so we
+do not yet guarantee that we are able to rewrite every Markdown document that
+you are able to read and display with Text or QTextEdit. But you are free to
+write [bugs](https://bugreports.qt.io) about any troublesome cases that you
+encounter.
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro
new file mode 100644
index 0000000000..6144710b99
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_qtextmarkdownwriter
+QT += core-private gui-private testlib
+SOURCES += tst_qtextmarkdownwriter.cpp
+TESTDATA += \
+ data/example.md \
+ data/blockquotes.md \
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
new file mode 100644
index 0000000000..8d38cbb18a
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
@@ -0,0 +1,464 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QTextDocument>
+#include <QTextCursor>
+#include <QTextBlock>
+#include <QTextList>
+#include <QTextTable>
+#include <QBuffer>
+#include <QDebug>
+
+#include <private/qtextmarkdownwriter_p.h>
+
+// #define DEBUG_WRITE_OUTPUT
+
+class tst_QTextMarkdownWriter : public QObject
+{
+ Q_OBJECT
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void testWriteParagraph_data();
+ void testWriteParagraph();
+ void testWriteList();
+ void testWriteNestedBulletLists_data();
+ void testWriteNestedBulletLists();
+ void testWriteNestedNumericLists();
+ void testWriteTable();
+ void rewriteDocument_data();
+ void rewriteDocument();
+ void fromHtml_data();
+ void fromHtml();
+
+private:
+ QString documentToUnixMarkdown();
+
+private:
+ QTextDocument *document;
+};
+
+void tst_QTextMarkdownWriter::init()
+{
+ document = new QTextDocument();
+}
+
+void tst_QTextMarkdownWriter::cleanup()
+{
+ delete document;
+}
+
+void tst_QTextMarkdownWriter::testWriteParagraph_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("output");
+
+ QTest::newRow("empty") << "" <<
+ "";
+ QTest::newRow("spaces") << "foobar word" <<
+ "foobar word\n\n";
+ QTest::newRow("starting spaces") << " starting spaces" <<
+ " starting spaces\n\n";
+ QTest::newRow("trailing spaces") << "trailing spaces " <<
+ "trailing spaces \n\n";
+ QTest::newRow("tab") << "word\ttab x" <<
+ "word\ttab x\n\n";
+ QTest::newRow("tab2") << "word\t\ttab\tx" <<
+ "word\t\ttab\tx\n\n";
+ QTest::newRow("misc") << "foobar word\ttab x" <<
+ "foobar word\ttab x\n\n";
+ QTest::newRow("misc2") << "\t \tFoo" <<
+ "\t \tFoo\n\n";
+}
+
+void tst_QTextMarkdownWriter::testWriteParagraph()
+{
+ QFETCH(QString, input);
+ QFETCH(QString, output);
+
+ QTextCursor cursor(document);
+ cursor.insertText(input);
+
+ QCOMPARE(documentToUnixMarkdown(), output);
+}
+
+void tst_QTextMarkdownWriter::testWriteList()
+{
+ QTextCursor cursor(document);
+ QTextList *list = cursor.createList(QTextListFormat::ListDisc);
+ cursor.insertText("ListItem 1");
+ list->add(cursor.block());
+ cursor.insertBlock();
+ cursor.insertText("ListItem 2");
+ list->add(cursor.block());
+
+ QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1(
+ "- ListItem 1\n- ListItem 2\n"));
+}
+
+void tst_QTextMarkdownWriter::testWriteNestedBulletLists_data()
+{
+ QTest::addColumn<bool>("checkbox");
+ QTest::addColumn<bool>("checked");
+ QTest::addColumn<bool>("continuationLine");
+ QTest::addColumn<bool>("continuationParagraph");
+ QTest::addColumn<QString>("expectedOutput");
+
+ QTest::newRow("plain bullets") << false << false << false << false <<
+ "- ListItem 1\n * ListItem 2\n + ListItem 3\n- ListItem 4\n * ListItem 5\n";
+ QTest::newRow("bullets with continuation lines") << false << false << true << false <<
+ "- ListItem 1\n * ListItem 2\n + ListItem 3 with text that won't fit on one line and thus needs a\n continuation\n- ListItem 4\n * ListItem 5 with text that won't fit on one line and thus needs a\n continuation\n";
+ QTest::newRow("bullets with continuation paragraphs") << false << false << false << true <<
+ "- ListItem 1\n\n * ListItem 2\n + ListItem 3\n\n continuation\n\n- ListItem 4\n\n * ListItem 5\n\n continuation\n\n";
+ QTest::newRow("unchecked") << true << false << false << false <<
+ "- [ ] ListItem 1\n * [ ] ListItem 2\n + [ ] ListItem 3\n- [ ] ListItem 4\n * [ ] ListItem 5\n";
+ QTest::newRow("checked") << true << true << false << false <<
+ "- [x] ListItem 1\n * [x] ListItem 2\n + [x] ListItem 3\n- [x] ListItem 4\n * [x] ListItem 5\n";
+ QTest::newRow("checked with continuation lines") << true << true << true << false <<
+ "- [x] ListItem 1\n * [x] ListItem 2\n + [x] ListItem 3 with text that won't fit on one line and thus needs a\n continuation\n- [x] ListItem 4\n * [x] ListItem 5 with text that won't fit on one line and thus needs a\n continuation\n";
+ QTest::newRow("checked with continuation paragraphs") << true << true << false << true <<
+ "- [x] ListItem 1\n\n * [x] ListItem 2\n + [x] ListItem 3\n\n continuation\n\n- [x] ListItem 4\n\n * [x] ListItem 5\n\n continuation\n\n";
+}
+
+void tst_QTextMarkdownWriter::testWriteNestedBulletLists()
+{
+ QFETCH(bool, checkbox);
+ QFETCH(bool, checked);
+ QFETCH(bool, continuationParagraph);
+ QFETCH(bool, continuationLine);
+ QFETCH(QString, expectedOutput);
+
+ QTextCursor cursor(document);
+ QTextBlockFormat blockFmt = cursor.blockFormat();
+ if (checkbox) {
+ blockFmt.setMarker(checked ? QTextBlockFormat::Checked : QTextBlockFormat::Unchecked);
+ cursor.setBlockFormat(blockFmt);
+ }
+
+ QTextList *list1 = cursor.createList(QTextListFormat::ListDisc);
+ cursor.insertText("ListItem 1");
+ list1->add(cursor.block());
+
+ QTextListFormat fmt2;
+ fmt2.setStyle(QTextListFormat::ListCircle);
+ fmt2.setIndent(2);
+ QTextList *list2 = cursor.insertList(fmt2);
+ cursor.insertText("ListItem 2");
+
+ QTextListFormat fmt3;
+ fmt3.setStyle(QTextListFormat::ListSquare);
+ fmt3.setIndent(3);
+ cursor.insertList(fmt3);
+ cursor.insertText(continuationLine ?
+ "ListItem 3 with text that won't fit on one line and thus needs a continuation" :
+ "ListItem 3");
+ if (continuationParagraph) {
+ QTextBlockFormat blockFmt;
+ blockFmt.setIndent(2);
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("continuation");
+ }
+
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("ListItem 4");
+ list1->add(cursor.block());
+
+ cursor.insertBlock();
+ cursor.insertText(continuationLine ?
+ "ListItem 5 with text that won't fit on one line and thus needs a continuation" :
+ "ListItem 5");
+ list2->add(cursor.block());
+ if (continuationParagraph) {
+ QTextBlockFormat blockFmt;
+ blockFmt.setIndent(2);
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("continuation");
+ }
+
+ QString output = documentToUnixMarkdown();
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".md");
+ out.open(QFile::WriteOnly);
+ out.write(output.toUtf8());
+ out.close();
+ }
+#endif
+ QCOMPARE(documentToUnixMarkdown(), expectedOutput);
+}
+
+void tst_QTextMarkdownWriter::testWriteNestedNumericLists()
+{
+ QTextCursor cursor(document);
+
+ QTextList *list1 = cursor.createList(QTextListFormat::ListDecimal);
+ cursor.insertText("ListItem 1");
+ list1->add(cursor.block());
+
+ QTextListFormat fmt2;
+ fmt2.setStyle(QTextListFormat::ListLowerAlpha);
+ fmt2.setNumberSuffix(QLatin1String(")"));
+ fmt2.setIndent(2);
+ QTextList *list2 = cursor.insertList(fmt2);
+ cursor.insertText("ListItem 2");
+
+ QTextListFormat fmt3;
+ fmt3.setStyle(QTextListFormat::ListDecimal);
+ fmt3.setIndent(3);
+ cursor.insertList(fmt3);
+ cursor.insertText("ListItem 3");
+
+ cursor.insertBlock();
+ cursor.insertText("ListItem 4");
+ list1->add(cursor.block());
+
+ cursor.insertBlock();
+ cursor.insertText("ListItem 5");
+ list2->add(cursor.block());
+
+ // There's no QTextList API to set the starting number so we hard-coded all lists to start at 1 (QTBUG-65384)
+ QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1(
+ "1. ListItem 1\n 1) ListItem 2\n 1. ListItem 3\n2. ListItem 4\n 2) ListItem 5\n"));
+}
+
+void tst_QTextMarkdownWriter::testWriteTable()
+{
+ QTextCursor cursor(document);
+ QTextTable * table = cursor.insertTable(4, 3);
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+ // valid Markdown tables need headers, but QTextTable doesn't make that distinction
+ // so QTextMarkdownWriter assumes the first row of any table is a header
+ cursor.insertText("one");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("two");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("three");
+ cursor.movePosition(QTextCursor::NextCell);
+
+ cursor.insertText("alice");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("bob");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("carl");
+ cursor.movePosition(QTextCursor::NextCell);
+
+ cursor.insertText("dennis");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("eric");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("fiona");
+ cursor.movePosition(QTextCursor::NextCell);
+
+ cursor.insertText("gina");
+ /*
+ |one |two |three|
+ |------|----|-----|
+ |alice |bob |carl |
+ |dennis|eric|fiona|
+ |gina | | |
+ */
+
+ QString md = documentToUnixMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/table.md");
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+ }
+#endif
+
+ QString expected = QString::fromLatin1(
+ "\n|one |two |three|\n|------|----|-----|\n|alice |bob |carl |\n|dennis|eric|fiona|\n|gina | | |\n\n");
+ QCOMPARE(md, expected);
+
+ // create table with merged cells
+ document->clear();
+ cursor = QTextCursor(document);
+ table = cursor.insertTable(3, 3);
+ table->mergeCells(0, 0, 1, 2);
+ table->mergeCells(1, 1, 1, 2);
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+ cursor.insertText("a");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("b");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("c");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("d");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("e");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("f");
+ /*
+ +---+-+
+ |a |b|
+ +---+-+
+ |c| d|
+ +-+-+-+
+ |e|f| |
+ +-+-+-+
+
+ generates
+
+ |a ||b|
+ |-|-|-|
+ |c|d ||
+ |e|f| |
+
+ */
+
+ md = documentToUnixMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/table-merged-cells.md");
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+ }
+#endif
+
+ QCOMPARE(md, QString::fromLatin1("\n|a ||b|\n|-|-|-|\n|c|d ||\n|e|f| |\n\n"));
+}
+
+void tst_QTextMarkdownWriter::rewriteDocument_data()
+{
+ QTest::addColumn<QString>("inputFile");
+
+ QTest::newRow("block quotes") << "blockquotes.md";
+ QTest::newRow("example") << "example.md";
+ QTest::newRow("list items after headings") << "headingsAndLists.md";
+ QTest::newRow("word wrap") << "wordWrap.md";
+}
+
+void tst_QTextMarkdownWriter::rewriteDocument()
+{
+ QFETCH(QString, inputFile);
+ QTextDocument doc;
+ QFile f(QFINDTESTDATA("data/" + inputFile));
+ QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
+ QString orig = QString::fromUtf8(f.readAll());
+ f.close();
+ doc.setMarkdown(orig);
+ QString md = doc.toMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ QFile out("/tmp/rewrite-" + inputFile);
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+#endif
+
+ QCOMPARE(md, orig);
+}
+
+void tst_QTextMarkdownWriter::fromHtml_data()
+{
+ QTest::addColumn<QString>("expectedInput");
+ QTest::addColumn<QString>("expectedOutput");
+
+ QTest::newRow("long URL") <<
+ "<span style=\"font-style:italic;\">https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/</span>" <<
+ "*https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/*\n\n";
+ QTest::newRow("non-emphasis inline asterisk") << "3 * 4" << "3 * 4\n\n";
+ QTest::newRow("arithmetic") << "(2 * a * x + b)^2 = b^2 - 4 * a * c" << "(2 * a * x + b)^2 = b^2 - 4 * a * c\n\n";
+ QTest::newRow("escaped asterisk after newline") <<
+ "The first sentence of this paragraph holds 80 characters, then there's a star. * This is wrapped, but is <em>not</em> a bullet point." <<
+ "The first sentence of this paragraph holds 80 characters, then there's a star.\n\\* This is wrapped, but is *not* a bullet point.\n\n";
+ QTest::newRow("escaped plus after newline") <<
+ "The first sentence of this paragraph holds 80 characters, then there's a plus. + This is wrapped, but is <em>not</em> a bullet point." <<
+ "The first sentence of this paragraph holds 80 characters, then there's a plus.\n\\+ This is wrapped, but is *not* a bullet point.\n\n";
+ QTest::newRow("escaped hyphen after newline") <<
+ "The first sentence of this paragraph holds 80 characters, then there's a minus. - This is wrapped, but is <em>not</em> a bullet point." <<
+ "The first sentence of this paragraph holds 80 characters, then there's a minus.\n\\- This is wrapped, but is *not* a bullet point.\n\n";
+ QTest::newRow("list items with indented continuations") <<
+ "<ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li></ul>" <<
+ "- bullet\n\n continuation paragraph\n\n- another bullet\n continuation line\n";
+ QTest::newRow("nested list items with continuations") <<
+ "<ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li><ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li></ul></ul>" <<
+ "- bullet\n\n continuation paragraph\n\n- another bullet\n continuation line\n\n - bullet\n\n continuation paragraph\n\n - another bullet\n continuation line\n";
+ QTest::newRow("nested ordered list items with continuations") <<
+ "<ol><li>item<p>continuation paragraph</p></li><li>another item<br/>continuation line</li><ol><li>item<p>continuation paragraph</p></li><li>another item<br/>continuation line</li></ol><li>another</li><li>another</li></ol>" <<
+ "1. item\n\n continuation paragraph\n\n2. another item\n continuation line\n\n 1. item\n\n continuation paragraph\n\n 2. another item\n continuation line\n\n3. another\n4. another\n";
+ QTest::newRow("thematic break") <<
+ "something<hr/>something else" <<
+ "something\n\n- - -\nsomething else\n\n";
+ QTest::newRow("block quote") <<
+ "<p>In 1958, Mahatma Gandhi was quoted as follows:</p><blockquote>The Earth provides enough to satisfy every man's need but not for every man's greed.</blockquote>" <<
+ "In 1958, Mahatma Gandhi was quoted as follows:\n\n> The Earth provides enough to satisfy every man's need but not for every man's\n> greed.\n\n";
+ QTest::newRow("image") <<
+ "<img src=\"/url\" alt=\"foo\" title=\"title\"/>" <<
+ "![foo](/url \"title\")\n\n";
+ QTest::newRow("code") <<
+ "<pre class=\"language-pseudocode\">\n#include \"foo.h\"\n\nblock {\n statement();\n}\n\n</pre>" <<
+ "``` pseudocode\n#include \"foo.h\"\n\nblock {\n statement();\n}\n```\n\n";
+ // TODO
+// QTest::newRow("escaped number and paren after double newline") <<
+// "<p>(The first sentence of this paragraph is a line, the next paragraph has a number</p>13) but that's not part of an ordered list" <<
+// "(The first sentence of this paragraph is a line, the next paragraph has a number\n\n13\\) but that's not part of an ordered list\n\n";
+// QTest::newRow("preformats with embedded backticks") <<
+// "<pre>none `one` ``two``</pre><pre>```three``` ````four````</pre>plain" <<
+// "``` none `one` ``two`` ```\n\n````` ```three``` ````four```` `````\n\nplain\n\n";
+}
+
+void tst_QTextMarkdownWriter::fromHtml()
+{
+ QFETCH(QString, expectedInput);
+ QFETCH(QString, expectedOutput);
+
+ document->setHtml(expectedInput);
+ QString output = documentToUnixMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".md");
+ out.open(QFile::WriteOnly);
+ out.write(output.toUtf8());
+ out.close();
+ }
+#endif
+
+ QCOMPARE(output, expectedOutput);
+}
+
+QString tst_QTextMarkdownWriter::documentToUnixMarkdown()
+{
+ QString ret;
+ QTextStream ts(&ret, QIODevice::WriteOnly);
+ QTextMarkdownWriter writer(ts, QTextDocument::MarkdownDialectGitHub);
+ writer.writeAll(document);
+ return ret;
+}
+
+QTEST_MAIN(tst_QTextMarkdownWriter)
+#include "tst_qtextmarkdownwriter.moc"
diff --git a/tests/auto/gui/text/text.pro b/tests/auto/gui/text/text.pro
index 6b033fb506..794d9ea8d3 100644
--- a/tests/auto/gui/text/text.pro
+++ b/tests/auto/gui/text/text.pro
@@ -28,12 +28,16 @@ SUBDIRS=\
win32:SUBDIRS -= qtextpiecetable
+qtConfig(textmarkdownreader): SUBDIRS += qtextmarkdownimporter
+qtConfig(textmarkdownwriter): SUBDIRS += qtextmarkdownwriter
+
!qtConfig(private_tests): SUBDIRS -= \
qfontcache \
qcssparser \
qtextlayout \
qtextpiecetable \
qzip \
+ qtextmarkdownwriter \
qtextodfwriter
!qtHaveModule(xml): SUBDIRS -= \
diff --git a/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc b/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc
index ab882b5db2..8aab86e1ff 100644
--- a/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc
+++ b/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc
@@ -3,5 +3,7 @@
<file>texturefiles/car.ktx</file>
<file>texturefiles/pattern.pkm</file>
<file>texturefiles/car_mips.ktx</file>
+ <file>texturefiles/newlogo_srgb.astc</file>
+ <file>texturefiles/newlogo.astc</file>
</qresource>
</RCC>
diff --git a/tests/auto/gui/util/qtexturefilereader/texturefiles/newlogo.astc b/tests/auto/gui/util/qtexturefilereader/texturefiles/newlogo.astc
new file mode 100644
index 0000000000..39bf3f1734
--- /dev/null
+++ b/tests/auto/gui/util/qtexturefilereader/texturefiles/newlogo.astc
Binary files differ
diff --git a/tests/auto/gui/util/qtexturefilereader/texturefiles/newlogo_srgb.astc b/tests/auto/gui/util/qtexturefilereader/texturefiles/newlogo_srgb.astc
new file mode 100644
index 0000000000..38e876829b
--- /dev/null
+++ b/tests/auto/gui/util/qtexturefilereader/texturefiles/newlogo_srgb.astc
Binary files differ
diff --git a/tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp b/tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp
index 9ff4f0ccf2..9b78d18954 100644
--- a/tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp
+++ b/tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp
@@ -49,33 +49,55 @@ void tst_qtexturefilereader::checkHandlers_data()
QTest::addColumn<QList<int>>("dataOffsets");
QTest::addColumn<QList<int>>("dataLengths");
- QTest::addRow("pattern.pkm") << QStringLiteral(":/texturefiles/pattern.pkm")
- << QSize(64, 64)
- << quint32(0x0)
- << quint32(0x8d64)
- << quint32(0x0)
- << 1
- << (QList<int>() << 16)
- << (QList<int>() << 2048);
+ QTest::addRow("pattern.pkm")
+ << QStringLiteral(":/texturefiles/pattern.pkm")
+ << QSize(64, 64)
+ << quint32(0x0)
+ << quint32(0x8d64)
+ << quint32(0x0)
+ << 1
+ << (QList<int>() << 16)
+ << (QList<int>() << 2048);
- QTest::addRow("car.ktx") << QStringLiteral(":/texturefiles/car.ktx")
- << QSize(146, 80)
- << quint32(0x0)
- << quint32(0x9278)
- << quint32(0x1908)
- << 1
- << (QList<int>() << 68)
- << (QList<int>() << 11840);
+ QTest::addRow("car.ktx")
+ << QStringLiteral(":/texturefiles/car.ktx")
+ << QSize(146, 80)
+ << quint32(0x0)
+ << quint32(0x9278)
+ << quint32(0x1908)
+ << 1
+ << (QList<int>() << 68)
+ << (QList<int>() << 11840);
- QTest::addRow("car_mips.ktx") << QStringLiteral(":/texturefiles/car_mips.ktx")
- << QSize(146, 80)
- << quint32(0x0)
- << quint32(0x9274)
- << quint32(0x1907)
- << 8
- << (QList<int>() << 68 << 5992 << 7516 << 7880 << 8004 << 8056 << 8068 << 8080)
- << (QList<int>() << 5920 << 1520 << 360 << 120 << 48 << 8 << 8 << 8);
+ QTest::addRow("car_mips.ktx")
+ << QStringLiteral(":/texturefiles/car_mips.ktx")
+ << QSize(146, 80)
+ << quint32(0x0)
+ << quint32(0x9274)
+ << quint32(0x1907)
+ << 8
+ << (QList<int>() << 68 << 5992 << 7516 << 7880 << 8004 << 8056 << 8068 << 8080)
+ << (QList<int>() << 5920 << 1520 << 360 << 120 << 48 << 8 << 8 << 8);
+ QTest::addRow("newlogo.astc")
+ << QStringLiteral(":/texturefiles/newlogo.astc")
+ << QSize(111, 78)
+ << quint32(0x0)
+ << quint32(0x93b9)
+ << quint32(0x0)
+ << 1
+ << (QList<int>() << 16)
+ << (QList<int>() << 2496);
+
+ QTest::addRow("newlogo_srgb.astc")
+ << QStringLiteral(":/texturefiles/newlogo_srgb.astc")
+ << QSize(111, 78)
+ << quint32(0x0)
+ << quint32(0x93d9)
+ << quint32(0x0)
+ << 1
+ << (QList<int>() << 16)
+ << (QList<int>() << 2496);
}
void tst_qtexturefilereader::checkHandlers()
diff --git a/tests/auto/network-settings.h b/tests/auto/network-settings.h
index a3c318420f..77298342af 100644
--- a/tests/auto/network-settings.h
+++ b/tests/auto/network-settings.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -72,15 +72,20 @@ public:
}
#ifdef QT_NETWORK_LIB
- static QHostAddress serverIP()
+ static QHostAddress getServerIpImpl(const QString &serverName)
{
- const QHostInfo info = QHostInfo::fromName(serverName());
+ const QHostInfo info = QHostInfo::fromName(serverName);
if (info.error()) {
QTest::qFail(qPrintable(info.errorString()), __FILE__, __LINE__);
return QHostAddress();
}
return info.addresses().constFirst();
}
+
+ static QHostAddress serverIP()
+ {
+ return getServerIpImpl(serverName());
+ }
#endif
static bool compareReplyIMAP(QByteArray const& actual)
@@ -104,8 +109,8 @@ public:
static bool compareReplyFtp(QByteArray const& actual)
{
// output would be e.g. "220 (vsFTPd 2.3.5)\r\n221 Goodbye.\r\n"
- QRegExp ftpVersion(QStringLiteral("220 \\(vsFTPd \\d+\\.\\d+.\\d+\\)\\r\\n221 Goodbye.\\r\\n"));
- return ftpVersion.exactMatch(actual);
+ QRegularExpression ftpVersion(QRegularExpression::anchoredPattern(QStringLiteral("220 \\(vsFTPd \\d+\\.\\d+.\\d+\\)\\r\\n221 Goodbye.\\r\\n")));
+ return ftpVersion.match(actual).hasMatch();
}
static bool hasIPv6()
@@ -143,7 +148,7 @@ public:
return true;
}
- static bool verifyConnection(QString serverName, quint16 port, quint32 retry = 10)
+ static bool verifyConnection(QString serverName, quint16 port, quint32 retry = 60)
{
QTcpSocket socket;
for (quint32 i = 1; i < retry; i++) {
@@ -176,7 +181,7 @@ public:
static QString ftpServerName()
{
-#ifdef QT_TEST_SERVER
+#ifdef QT_TEST_SERVER_NAME
return QString("vsftpd.") % serverDomainName();
#else
return serverName();
@@ -184,7 +189,7 @@ public:
}
static QString ftpProxyServerName()
{
-#ifdef QT_TEST_SERVER
+#ifdef QT_TEST_SERVER_NAME
return QString("ftp-proxy.") % serverDomainName();
#else
return serverName();
@@ -192,7 +197,7 @@ public:
}
static QString httpServerName()
{
-#ifdef QT_TEST_SERVER
+#ifdef QT_TEST_SERVER_NAME
return QString("apache2.") % serverDomainName();
#else
return serverName();
@@ -200,7 +205,7 @@ public:
}
static QString httpProxyServerName()
{
-#ifdef QT_TEST_SERVER
+#ifdef QT_TEST_SERVER_NAME
return QString("squid.") % serverDomainName();
#else
return serverName();
@@ -208,10 +213,73 @@ public:
}
static QString socksProxyServerName()
{
-#ifdef QT_TEST_SERVER
+#ifdef QT_TEST_SERVER_NAME
return QString("danted.") % serverDomainName();
#else
return serverName();
#endif
}
+ static QString imapServerName()
+ {
+#ifdef QT_TEST_SERVER_NAME
+ return QString("cyrus.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
+
+ static QString echoServerName()
+ {
+#ifdef QT_TEST_SERVER_NAME
+ return QString("echo.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
+
+ static QString firewallServerName()
+ {
+#ifdef QT_TEST_SERVER_NAME
+ return QString("iptables.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
+
+#ifdef QT_NETWORK_LIB
+ static QHostAddress imapServerIp()
+ {
+ return getServerIpImpl(imapServerName());
+ }
+
+ static QHostAddress httpServerIp()
+ {
+ return getServerIpImpl(httpServerName());
+ }
+
+ static QHostAddress httpProxyServerIp()
+ {
+ return getServerIpImpl(httpProxyServerName());
+ }
+
+ static QHostAddress socksProxyServerIp()
+ {
+ return getServerIpImpl(socksProxyServerName());
+ }
+
+ static QHostAddress ftpProxyServerIp()
+ {
+ return getServerIpImpl(ftpProxyServerName());
+ }
+
+ static QHostAddress ftpServerIp()
+ {
+ return getServerIpImpl(ftpServerName());
+ }
+
+ static QHostAddress firewallServerIp()
+ {
+ return getServerIpImpl(firewallServerName());
+ }
+#endif
};
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
index 76eb431af6..e24370fc87 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -50,7 +50,8 @@
#include "emulationdetector.h"
-#if !defined(QT_NO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT)
+#if (!defined(QT_NO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT)) \
+ || QT_CONFIG(schannel)
// HTTP/2 over TLS requires ALPN/NPN to negotiate the protocol version.
const bool clearTextHTTP2 = false;
#else
diff --git a/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro b/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro
index 1874f001ab..c722100ead 100644
--- a/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro
+++ b/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro
@@ -5,3 +5,5 @@ SOURCES += tst_qabstractnetworkcache.cpp
TESTDATA += tests/*
+CONFIG += unsupported/testserver
+QT_TEST_SERVER_LIST = apache2
diff --git a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
index b8d9adf7a1..182e3e9547 100644
--- a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
+++ b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
@@ -39,7 +39,7 @@
#include <algorithm>
-#define TESTFILE QLatin1String("http://") + QtNetworkSettings::serverName() + QLatin1String("/qtest/cgi-bin/")
+#define TESTFILE QLatin1String("http://") + QtNetworkSettings::httpServerName() + QLatin1String("/qtest/cgi-bin/")
class tst_QAbstractNetworkCache : public QObject
{
@@ -127,8 +127,13 @@ Q_DECLARE_METATYPE(QNetworkRequest::CacheLoadControl)
void tst_QAbstractNetworkCache::initTestCase()
{
+#if defined(QT_TEST_SERVER)
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
+#else
if (!QtNetworkSettings::verifyTestNetworkSettings())
QSKIP("No network test server available");
+#endif
+
#ifndef QT_NO_BEARERMANAGEMENT
netConfMan = new QNetworkConfigurationManager(this);
networkConfiguration = netConfMan->defaultConfiguration();
diff --git a/tests/auto/network/access/qftp/qftp.pro b/tests/auto/network/access/qftp/qftp.pro
index 1959c1acac..c78020c5f8 100644
--- a/tests/auto/network/access/qftp/qftp.pro
+++ b/tests/auto/network/access/qftp/qftp.pro
@@ -4,3 +4,6 @@ SOURCES += tst_qftp.cpp
requires(qtConfig(private_tests))
QT = core network network-private testlib
+
+CONFIG += unsupported/testserver
+QT_TEST_SERVER_LIST = vsftpd ftp-proxy squid danted
diff --git a/tests/auto/network/access/qftp/tst_qftp.cpp b/tests/auto/network/access/qftp/tst_qftp.cpp
index 1a8f264c28..a04c2ae01d 100644
--- a/tests/auto/network/access/qftp/tst_qftp.cpp
+++ b/tests/auto/network/access/qftp/tst_qftp.cpp
@@ -43,6 +43,7 @@
#include <QtNetwork/private/qnetworksession_p.h>
#include <QTcpServer>
#include <QHostInfo>
+#include <QElapsedTimer>
#include <QTcpSocket>
#include "../../../network-settings.h"
@@ -133,8 +134,8 @@ private:
bool fileExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &file, const QString &cdDir = QString() );
bool dirExists( const QString &host, quint16 port, const QString &user, const QString &password, const QString &cdDir, const QString &dirToCreate );
- void renameInit( const QString &host, const QString &user, const QString &password, const QString &createFile );
- void renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete );
+ void renameInit( bool &isSuccess, const QString &host, const QString &user, const QString &password, const QString &createFile );
+ void renameCleanup( bool &isSuccess, const QString &host, const QString &user, const QString &password, const QString &fileToDelete );
QFtp *ftp;
#ifndef QT_NO_BEARERMANAGEMENT
@@ -208,7 +209,14 @@ void tst_QFtp::initTestCase_data()
void tst_QFtp::initTestCase()
{
+#if defined(QT_TEST_SERVER)
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpServerName(), 21));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif
#ifndef QT_NO_BEARERMANAGEMENT
QNetworkConfigurationManager manager;
networkSessionImplicit = QSharedPointer<QNetworkSession>::create(manager.defaultConfiguration());
@@ -235,9 +243,9 @@ void tst_QFtp::init()
if (setProxy) {
#ifndef QT_NO_NETWORKPROXY
if (proxyType == QNetworkProxy::Socks5Proxy) {
- QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080));
} else if (proxyType == QNetworkProxy::HttpProxy) {
- QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128));
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128));
}
#else // !QT_NO_NETWORKPROXY
Q_UNUSED(proxyType);
@@ -316,8 +324,8 @@ void tst_QFtp::connectToHost_data()
QTest::addColumn<uint>("port");
QTest::addColumn<int>("state");
- QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << (int)QFtp::Connected;
- QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)2222 << (int)QFtp::Unconnected;
+ QTest::newRow( "ok01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << (int)QFtp::Connected;
+ QTest::newRow( "error01" ) << QtNetworkSettings::ftpServerName() << (uint)2222 << (int)QFtp::Unconnected;
QTest::newRow( "error02" ) << QString("foo.bar") << (uint)21 << (int)QFtp::Unconnected;
}
@@ -328,7 +336,11 @@ static QByteArray msgTimedOut(const QString &host, quint16 port = 0)
result += ':';
result += QByteArray::number(port);
}
- return result;
+
+ if (host == QtNetworkSettings::ftpServerName())
+ return "(QTBUG-75549) Flaky results: " % result;
+ else
+ return result;
}
void tst_QFtp::connectToHost()
@@ -343,7 +355,7 @@ void tst_QFtp::connectToHost()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
QTEST( connectToHost_state, "state" );
@@ -402,13 +414,13 @@ void tst_QFtp::login_data()
QTest::addColumn<QString>("password");
QTest::addColumn<int>("success");
- QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << 1;
- QTest::newRow( "ok02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("") << 1;
- QTest::newRow( "ok03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << 1;
- QTest::newRow( "ok04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << 1;
+ QTest::newRow( "ok01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << 1;
+ QTest::newRow( "ok02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftp") << QString("") << 1;
+ QTest::newRow( "ok03" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftp") << QString("foo") << 1;
+ QTest::newRow( "ok04" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << 1;
- QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString("") << 0;
- QTest::newRow( "error02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString("bar") << 0;
+ QTest::newRow( "error01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("foo") << QString("") << 0;
+ QTest::newRow( "error02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("foo") << QString("bar") << 0;
}
void tst_QFtp::login()
@@ -426,7 +438,7 @@ void tst_QFtp::login()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
ResMapIt it = resultMap.find( QFtp::Login );
QVERIFY( it != resultMap.end() );
@@ -448,12 +460,12 @@ void tst_QFtp::close_data()
QTest::addColumn<QString>("password");
QTest::addColumn<bool>("login");
- QTest::newRow( "login01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << true;
- QTest::newRow( "login02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString() << true;
- QTest::newRow( "login03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << true;
- QTest::newRow( "login04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << true;
+ QTest::newRow( "login01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << true;
+ QTest::newRow( "login02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftp") << QString() << true;
+ QTest::newRow( "login03" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftp") << QString("foo") << true;
+ QTest::newRow( "login04" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << true;
- QTest::newRow( "no-login01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("") << QString("") << false;
+ QTest::newRow( "no-login01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("") << QString("") << false;
}
void tst_QFtp::close()
@@ -474,7 +486,7 @@ void tst_QFtp::close()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
QCOMPARE( close_state, (int)QFtp::Unconnected );
@@ -503,17 +515,17 @@ void tst_QFtp::list_data()
flukeQtest << "rfc3252.txt";
flukeQtest << "upload";
- QTest::newRow( "workDir01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString() << 1 << flukeRoot;
- QTest::newRow( "workDir02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString() << 1 << flukeRoot;
+ QTest::newRow( "workDir01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString() << 1 << flukeRoot;
+ QTest::newRow( "workDir02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString() << 1 << flukeRoot;
- QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
- QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
- QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 1 << QStringList();
- QTest::newRow( "nonExist02" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 1 << QStringList();
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("foo") << 1 << QStringList();
+ QTest::newRow( "nonExist02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/foo") << 1 << QStringList();
// ### The microsoft server does not seem to work properly at the moment --
// I am also not able to open a data connection with other, non-Qt FTP
// clients to it.
@@ -542,7 +554,7 @@ void tst_QFtp::list()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
ResMapIt it = resultMap.find( QFtp::List );
QVERIFY( it != resultMap.end() );
@@ -573,14 +585,14 @@ void tst_QFtp::cd_data()
flukeQtest << "rfc3252.txt";
flukeQtest << "upload";
- QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
- QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
- QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
- QTest::newRow( "nonExist03" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
+ QTest::newRow( "nonExist03" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
}
void tst_QFtp::cd()
@@ -603,7 +615,7 @@ void tst_QFtp::cd()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() ) {
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
}
ResMapIt it = resultMap.find( QFtp::Cd );
@@ -635,19 +647,19 @@ void tst_QFtp::get_data()
// test the two get() overloads in one routine
for ( int i=0; i<2; i++ ) {
const QByteArray iB = QByteArray::number(i);
- QTest::newRow(("relPath01_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow(("relPath01_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
- QTest::newRow(("relPath02_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow(("relPath02_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< "qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
- QTest::newRow(("absPath01_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow(("absPath01_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "/qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
- QTest::newRow(("absPath02_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow(("absPath02_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< "/var/ftp/qtest/rfc3252" << 1 << rfc3252 << (bool)(i==1);
- QTest::newRow(("nonExist01_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow(("nonExist01_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< QString("foo") << 0 << QByteArray() << (bool)(i==1);
- QTest::newRow(("nonExist02_" + iB).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow(("nonExist02_" + iB).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< QString("/foo") << 0 << QByteArray() << (bool)(i==1);
}
}
@@ -680,7 +692,7 @@ void tst_QFtp::get()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
ResMapIt it = resultMap.find( QFtp::Get );
QVERIFY( it != resultMap.end() );
@@ -727,31 +739,31 @@ void tst_QFtp::put_data()
// test the two put() overloads in one routine with a file name containing
// U+0x00FC (latin small letter u with diaeresis) for QTBUG-52303, testing UTF-8
for ( int i=0; i<2; i++ ) {
- QTest::newRow(("relPath01_" + QByteArray::number(i)).constData()) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow(("relPath01_" + QByteArray::number(i)).constData()) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< (QLatin1String("qtest/upload/rel01_") + QChar(0xfc) + QLatin1String("%1")) << rfc3252
<< (bool)(i==1) << 1;
/*
- QTest::newRow( QString("relPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( QString("relPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< QString("qtest/upload/rel02_%1") << rfc3252
<< (bool)(i==1) << 1;
- QTest::newRow( QString("relPath03_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( QString("relPath03_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< QString("qtest/upload/rel03_%1") << QByteArray()
<< (bool)(i==1) << 1;
- QTest::newRow( QString("relPath04_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( QString("relPath04_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< QString("qtest/upload/rel04_%1") << bigData
<< (bool)(i==1) << 1;
- QTest::newRow( QString("absPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( QString("absPath01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< QString("/qtest/upload/abs01_%1") << rfc3252
<< (bool)(i==1) << 1;
- QTest::newRow( QString("absPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( QString("absPath02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< QString("/srv/ftp/qtest/upload/abs02_%1") << rfc3252
<< (bool)(i==1) << 1;
- QTest::newRow( QString("nonExist01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( QString("nonExist01_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< QString("foo") << QByteArray()
<< (bool)(i==1) << 0;
- QTest::newRow( QString("nonExist02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( QString("nonExist02_%1").arg(i).toLatin1().constData() ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< QString("/foo") << QByteArray()
<< (bool)(i==1) << 0;
*/
@@ -807,7 +819,7 @@ void tst_QFtp::put()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
it = resultMap.find( QFtp::Put );
QVERIFY( it != resultMap.end() );
@@ -840,7 +852,7 @@ void tst_QFtp::put()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
QCOMPARE( done_success, 1 );
QTEST( buf.buffer(), "fileData" );
@@ -858,7 +870,7 @@ void tst_QFtp::put()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
it = resultMap.find( QFtp::Remove );
QVERIFY( it != resultMap.end() );
@@ -877,22 +889,22 @@ void tst_QFtp::mkdir_data()
QTest::addColumn<QString>("dirToCreate");
QTest::addColumn<int>("success");
- QTest::newRow( "relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( "relPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "qtest/upload" << QString("rel01_%1") << 1;
- QTest::newRow( "relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( "relPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< "qtest/upload" << QString("rel02_%1") << 1;
- QTest::newRow( "relPath03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( "relPath03" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< "qtest/upload" << QString("rel03_%1") << 1;
- QTest::newRow( "absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( "absPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "." << QString("/qtest/upload/abs01_%1") << 1;
- QTest::newRow( "absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password")
+ QTest::newRow( "absPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password")
<< "." << QString("/var/ftp/qtest/upload/abs02_%1") << 1;
- // QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0;
- QTest::newRow( "nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ // QTest::newRow( "nonExist01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("foo") << 0;
+ QTest::newRow( "nonExist01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "." << QString("foo") << 0;
- QTest::newRow( "nonExist02" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString()
+ QTest::newRow( "nonExist02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString()
<< "." << QString("/foo") << 0;
}
@@ -922,7 +934,7 @@ void tst_QFtp::mkdir()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
ResMapIt it = resultMap.find( QFtp::Mkdir );
QVERIFY( it != resultMap.end() );
@@ -947,7 +959,7 @@ void tst_QFtp::mkdir()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
it = resultMap.find( QFtp::Mkdir );
QVERIFY( it != resultMap.end() );
@@ -967,7 +979,7 @@ void tst_QFtp::mkdir()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
it = resultMap.find( QFtp::Rmdir );
QVERIFY( it != resultMap.end() );
@@ -979,7 +991,7 @@ void tst_QFtp::mkdir()
void tst_QFtp::mkdir2()
{
ftp = new QFtp;
- ftp->connectToHost(QtNetworkSettings::serverName());
+ ftp->connectToHost(QtNetworkSettings::ftpServerName());
ftp->login();
current_id = ftp->cd("kake/test");
@@ -1026,47 +1038,48 @@ void tst_QFtp::rename_data()
QTest::addColumn<QString>("renamedFile");
QTest::addColumn<int>("success");
- QTest::newRow("relPath01") << QtNetworkSettings::serverName() << QString() << QString()
+ QTest::newRow("relPath01") << QtNetworkSettings::ftpServerName() << QString() << QString()
<< "qtest/upload"
<< QString("rel_old01_%1") << QString("rel_new01_%1")
<< QString("qtest/upload/rel_old01_%1") << QString("qtest/upload/rel_new01_%1")
<< 1;
- QTest::newRow("relPath02") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ QTest::newRow("relPath02") << QtNetworkSettings::ftpServerName() << QString("ftptest") << "password"
<< "qtest/upload"
<< QString("rel_old02_%1") << QString("rel_new02_%1")
<< QString("qtest/upload/rel_old02_%1") << QString("qtest/upload/rel_new02_%1")
<< 1;
- QTest::newRow("relPath03") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ QTest::newRow("relPath03") << QtNetworkSettings::ftpServerName() << QString("ftptest") << "password"
<< "qtest/upload"
<< QString("rel_old03_%1")<< QString("rel_new03_%1")
<< QString("qtest/upload/rel_old03_%1") << QString("qtest/upload/rel_new03_%1")
<< 1;
- QTest::newRow("absPath01") << QtNetworkSettings::serverName() << QString() << QString()
+ QTest::newRow("absPath01") << QtNetworkSettings::ftpServerName() << QString() << QString()
<< QString()
<< QString("/qtest/upload/abs_old01_%1") << QString("/qtest/upload/abs_new01_%1")
<< QString("/qtest/upload/abs_old01_%1") << QString("/qtest/upload/abs_new01_%1")
<< 1;
- QTest::newRow("absPath02") << QtNetworkSettings::serverName() << QString("ftptest") << "password"
+ QTest::newRow("absPath02") << QtNetworkSettings::ftpServerName() << QString("ftptest") << "password"
<< QString()
<< QString("/var/ftp/qtest/upload/abs_old02_%1") << QString("/var/ftp/qtest/upload/abs_new02_%1")
<< QString("/var/ftp/qtest/upload/abs_old02_%1") << QString("/var/ftp/qtest/upload/abs_new02_%1")
<< 1;
- QTest::newRow("nonExist01") << QtNetworkSettings::serverName() << QString() << QString()
+ QTest::newRow("nonExist01") << QtNetworkSettings::ftpServerName() << QString() << QString()
<< QString()
<< QString("foo") << "new_foo"
<< QString() << QString()
<< 0;
- QTest::newRow("nonExist02") << QtNetworkSettings::serverName() << QString() << QString()
+ QTest::newRow("nonExist02") << QtNetworkSettings::ftpServerName() << QString() << QString()
<< QString()
<< QString("/foo") << QString("/new_foo")
<< QString() << QString()
<< 0;
}
-void tst_QFtp::renameInit( const QString &host, const QString &user, const QString &password, const QString &createFile )
+void tst_QFtp::renameInit( bool &isSuccess, const QString &host, const QString &user, const QString &password, const QString &createFile )
{
+ isSuccess = false;
if ( !createFile.isNull() ) {
// upload the file
init();
@@ -1080,7 +1093,7 @@ void tst_QFtp::renameInit( const QString &host, const QString &user, const QStri
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host) );
+ QSKIP( msgTimedOut(host) );
ResMapIt it = resultMap.find( QFtp::Put );
QVERIFY( it != resultMap.end() );
@@ -1088,10 +1101,12 @@ void tst_QFtp::renameInit( const QString &host, const QString &user, const QStri
QVERIFY( fileExists( host, 21, user, password, createFile ) );
}
+ isSuccess = true;
}
-void tst_QFtp::renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete )
+void tst_QFtp::renameCleanup( bool &isSuccess, const QString &host, const QString &user, const QString &password, const QString &fileToDelete )
{
+ isSuccess = false;
if ( !fileToDelete.isNull() ) {
// cleanup (i.e. remove the file)
init();
@@ -1105,7 +1120,7 @@ void tst_QFtp::renameCleanup( const QString &host, const QString &user, const QS
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host) );
+ QSKIP( msgTimedOut(host) );
ResMapIt it = resultMap.find( QFtp::Remove );
QVERIFY( it != resultMap.end() );
@@ -1113,6 +1128,7 @@ void tst_QFtp::renameCleanup( const QString &host, const QString &user, const QS
QVERIFY( !fileExists( host, 21, user, password, fileToDelete ) );
}
+ isSuccess = true;
}
void tst_QFtp::rename()
@@ -1135,7 +1151,10 @@ void tst_QFtp::rename()
if(renamedFile.contains('%'))
renamedFile = renamedFile.arg(uniqueExtension);
- renameInit( host, user, password, createFile );
+ bool isSuccess = true;
+ renameInit(isSuccess, host, user, password, createFile);
+ if (!isSuccess)
+ QSKIP("(QTBUG-75549) abort test when there is an error in helper functions");
init();
ftp = newFtp();
@@ -1150,7 +1169,7 @@ void tst_QFtp::rename()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host) );
+ QSKIP( msgTimedOut(host) );
ResMapIt it = resultMap.find( QFtp::Rename );
QVERIFY( it != resultMap.end() );
@@ -1165,7 +1184,9 @@ void tst_QFtp::rename()
QVERIFY( !fileExists( host, 21, user, password, renamedFile ) );
}
- renameCleanup( host, user, password, renamedFile );
+ renameCleanup(isSuccess, host, user, password, renamedFile);
+ if (!isSuccess)
+ QSKIP("(QTBUG-75549) abort test when there is an error in helper functions");
}
/*
@@ -1220,7 +1241,7 @@ void tst_QFtp::commandSequence_data()
{
// some "constants"
QStringList argConnectToHost01;
- argConnectToHost01 << QtNetworkSettings::serverName() << "21";
+ argConnectToHost01 << QtNetworkSettings::ftpServerName() << "21";
QStringList argLogin01, argLogin02, argLogin03, argLogin04;
argLogin01 << QString() << QString();
@@ -1339,7 +1360,7 @@ void tst_QFtp::commandSequence()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host) );
+ QSKIP( msgTimedOut(host) );
QTEST( commandSequence_success, "success" );
}
@@ -1351,13 +1372,13 @@ void tst_QFtp::abort_data()
QTest::addColumn<QString>("file");
QTest::addColumn<QByteArray>("uploadData");
- QTest::newRow( "get_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/bigfile") << QByteArray();
- QTest::newRow( "get_fluke02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/rfc3252") << QByteArray();
+ QTest::newRow( "get_fluke01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("qtest/bigfile") << QByteArray();
+ QTest::newRow( "get_fluke02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("qtest/rfc3252") << QByteArray();
// Qt/CE test environment has too little memory for this test
QByteArray bigData( 10*1024*1024, 0 );
bigData.fill( 'B' );
- QTest::newRow( "put_fluke01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("qtest/upload/abort_put") << bigData;
+ QTest::newRow( "put_fluke01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("qtest/upload/abort_put") << bigData;
}
void tst_QFtp::abort()
@@ -1394,7 +1415,7 @@ void tst_QFtp::abort()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
ResMapIt it = resultMap.find( cmd );
QVERIFY( it != resultMap.end() );
@@ -1402,7 +1423,7 @@ void tst_QFtp::abort()
if ( it.value().success ) {
// The FTP server on fluke is sadly returning a success, even when
// the operation was aborted. So we have to use some heuristics.
- if ( host == QtNetworkSettings::serverName() ) {
+ if ( host == QtNetworkSettings::ftpServerName() ) {
if ( cmd == QFtp::Get ) {
QVERIFY2(bytesDone <= bytesTotal, msgComparison(bytesDone, "<=", bytesTotal));
} else {
@@ -1432,7 +1453,7 @@ void tst_QFtp::abort()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
it = resultMap.find( QFtp::Remove );
QVERIFY( it != resultMap.end() );
@@ -1449,11 +1470,11 @@ void tst_QFtp::bytesAvailable_data()
QTest::addColumn<qlonglong>("bytesAvailFinished");
QTest::addColumn<qlonglong>("bytesAvailDone");
- QTest::newRow( "fluke01" ) << QtNetworkSettings::serverName() << QString("qtest/bigfile") << 0 << (qlonglong)519240 << (qlonglong)519240 << (qlonglong)519240;
- QTest::newRow( "fluke02" ) << QtNetworkSettings::serverName() << QString("qtest/rfc3252") << 0 << (qlonglong)25962 << (qlonglong)25962 << (qlonglong)25962;
+ QTest::newRow( "fluke01" ) << QtNetworkSettings::ftpServerName() << QString("qtest/bigfile") << 0 << (qlonglong)519240 << (qlonglong)519240 << (qlonglong)519240;
+ QTest::newRow( "fluke02" ) << QtNetworkSettings::ftpServerName() << QString("qtest/rfc3252") << 0 << (qlonglong)25962 << (qlonglong)25962 << (qlonglong)25962;
- QTest::newRow( "fluke03" ) << QtNetworkSettings::serverName() << QString("qtest/bigfile") << 1 << (qlonglong)519240 << (qlonglong)0 << (qlonglong)0;
- QTest::newRow( "fluke04" ) << QtNetworkSettings::serverName() << QString("qtest/rfc3252") << 1 << (qlonglong)25962 << (qlonglong)0 << (qlonglong)0;
+ QTest::newRow( "fluke03" ) << QtNetworkSettings::ftpServerName() << QString("qtest/bigfile") << 1 << (qlonglong)519240 << (qlonglong)0 << (qlonglong)0;
+ QTest::newRow( "fluke04" ) << QtNetworkSettings::ftpServerName() << QString("qtest/rfc3252") << 1 << (qlonglong)25962 << (qlonglong)0 << (qlonglong)0;
}
void tst_QFtp::bytesAvailable()
@@ -1470,8 +1491,11 @@ void tst_QFtp::bytesAvailable()
addCommand( QFtp::Close, ftp->close() );
QTestEventLoop::instance().enterLoop( 40 );
- if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(host) );
+ if ( QTestEventLoop::instance().timeout() ) {
+ delete ftp;
+ ftp = 0;
+ QSKIP( msgTimedOut(host) );
+ }
ResMapIt it = resultMap.find( QFtp::Get );
QVERIFY( it != resultMap.end() );
@@ -1498,7 +1522,7 @@ void tst_QFtp::activeMode()
file.open(QIODevice::ReadWrite);
QFtp ftp;
ftp.setTransferMode(QFtp::Active);
- ftp.connectToHost(QtNetworkSettings::serverName(), 21);
+ ftp.connectToHost(QtNetworkSettings::ftpServerName(), 21);
ftp.login();
ftp.list();
ftp.get("/qtest/rfc3252.txt", &file);
@@ -1534,14 +1558,14 @@ void tst_QFtp::proxy_data()
flukeQtest << "rfc3252.txt";
flukeQtest << "upload";
- QTest::newRow( "proxy_relPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "proxy_relPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_relPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_relPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("qtest") << 1 << flukeQtest;
- QTest::newRow( "proxy_absPath01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
- QTest::newRow( "proxy_absPath02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_absPath01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/qtest") << 1 << flukeQtest;
+ QTest::newRow( "proxy_absPath02" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString("ftptest") << QString("password") << QString("/var/ftp/qtest") << 1 << flukeQtest;
- QTest::newRow( "proxy_nonExist01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
- QTest::newRow( "proxy_nonExist03" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
+ QTest::newRow( "proxy_nonExist01" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("foo") << 0 << QStringList();
+ QTest::newRow( "proxy_nonExist03" ) << QtNetworkSettings::ftpServerName() << (uint)21 << QString() << QString() << QString("/foo") << 0 << QStringList();
}
void tst_QFtp::proxy()
@@ -1553,7 +1577,7 @@ void tst_QFtp::proxy()
QFETCH( QString, dir );
ftp = newFtp();
- addCommand( QFtp::SetProxy, ftp->setProxy( QtNetworkSettings::serverName(), 2121 ) );
+ addCommand( QFtp::SetProxy, ftp->setProxy( QtNetworkSettings::ftpProxyServerName(), 2121 ) );
addCommand( QFtp::ConnectToHost, ftp->connectToHost( host, port ) );
addCommand( QFtp::Login, ftp->login( user, password ) );
addCommand( QFtp::Cd, ftp->cd( dir ) );
@@ -1564,7 +1588,7 @@ void tst_QFtp::proxy()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() ) {
- QFAIL( msgTimedOut(host, port) );
+ QSKIP( msgTimedOut(host, port) );
}
ResMapIt it = resultMap.find( QFtp::Cd );
@@ -1589,7 +1613,7 @@ void tst_QFtp::binaryAscii()
init();
ftp = newFtp();
- addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::ftpServerName(), 21));
addCommand(QFtp::Login, ftp->login("ftptest", "password"));
addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
addCommand(QFtp::Put, ftp->put(putData, file, QFtp::Ascii));
@@ -1599,7 +1623,7 @@ void tst_QFtp::binaryAscii()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(QtNetworkSettings::serverName()) );
+ QSKIP( msgTimedOut(QtNetworkSettings::ftpServerName()) );
ResMapIt it = resultMap.find(QFtp::Put);
QVERIFY(it != resultMap.end());
@@ -1611,7 +1635,7 @@ void tst_QFtp::binaryAscii()
init();
ftp = newFtp();
- addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::ftpServerName(), 21));
addCommand(QFtp::Login, ftp->login("ftptest", "password"));
addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
addCommand(QFtp::Get, ftp->get(file, &getBuf, QFtp::Binary));
@@ -1621,7 +1645,7 @@ void tst_QFtp::binaryAscii()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(QtNetworkSettings::serverName()) );
+ QSKIP( msgTimedOut(QtNetworkSettings::ftpServerName()) );
ResMapIt it2 = resultMap.find(QFtp::Get);
QVERIFY(it2 != resultMap.end());
@@ -1634,7 +1658,7 @@ void tst_QFtp::binaryAscii()
// cleanup (i.e. remove the file) -- this also tests the remove command
init();
ftp = newFtp();
- addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::serverName(), 21));
+ addCommand(QFtp::ConnectToHost, ftp->connectToHost(QtNetworkSettings::ftpServerName(), 21));
addCommand(QFtp::Login, ftp->login("ftptest", "password"));
addCommand(QFtp::Cd, ftp->cd("qtest/upload"));
addCommand(QFtp::Remove, ftp->remove(file));
@@ -1644,13 +1668,13 @@ void tst_QFtp::binaryAscii()
delete ftp;
ftp = 0;
if ( QTestEventLoop::instance().timeout() )
- QFAIL( msgTimedOut(QtNetworkSettings::serverName()) );
+ QSKIP( msgTimedOut(QtNetworkSettings::ftpServerName()) );
it = resultMap.find( QFtp::Remove );
QVERIFY( it != resultMap.end() );
QCOMPARE( it.value().success, 1 );
- QVERIFY(!fileExists(QtNetworkSettings::serverName(), 21, "ftptest", "password", file));
+ QVERIFY(!fileExists(QtNetworkSettings::ftpServerName(), 21, "ftptest", "password", file));
}
@@ -2067,7 +2091,7 @@ void tst_QFtp::doneSignal()
QFtp ftp;
QSignalSpy spy(&ftp, SIGNAL(done(bool)));
- ftp.connectToHost(QtNetworkSettings::serverName());
+ ftp.connectToHost(QtNetworkSettings::ftpServerName());
ftp.login("anonymous");
ftp.list();
ftp.close();
@@ -2076,7 +2100,7 @@ void tst_QFtp::doneSignal()
connect(&ftp, SIGNAL(done(bool)), &(QTestEventLoop::instance()), SLOT(exitLoop()));
QTestEventLoop::instance().enterLoop(61);
if (QTestEventLoop::instance().timeout())
- QFAIL("Network operation timed out");
+ QSKIP( msgTimedOut(QtNetworkSettings::ftpServerName()) );
QCOMPARE(spy.count(), 1);
QCOMPARE(spy.first().first().toBool(), false);
@@ -2137,7 +2161,7 @@ void tst_QFtp::qtbug7359Crash()
QFtp ftp;
ftp.connectToHost("127.0.0.1");
- QTime t;
+ QElapsedTimer t;
int elapsed;
t.start();
diff --git a/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro
index d32b651b86..84e6f857a1 100644
--- a/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro
+++ b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro
@@ -4,3 +4,6 @@ SOURCES += tst_qhttpnetworkconnection.cpp
requires(qtConfig(private_tests))
QT = core-private network-private testlib
+
+CONFIG += unsupported/testserver
+QT_TEST_SERVER_LIST = apache2
diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
index 84766f5484..0a9320118d 100644
--- a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
+++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
@@ -50,6 +50,7 @@ private:
bool finishedCalled;
bool finishedWithErrorCalled;
QNetworkReply::NetworkError netErrorCode;
+ QString (*httpServerName)() = QtNetworkSettings::httpServerName;
private Q_SLOTS:
void initTestCase();
@@ -101,7 +102,11 @@ private Q_SLOTS:
void tst_QHttpNetworkConnection::initTestCase()
{
+#if defined(QT_TEST_SERVER)
+ QVERIFY(QtNetworkSettings::verifyConnection(httpServerName(), 80));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif
}
void tst_QHttpNetworkConnection::options_data()
@@ -126,10 +131,9 @@ void tst_QHttpNetworkConnection::head_data()
QTest::addColumn<QString>("statusString");
QTest::addColumn<int>("contentLength");
- QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962;
-
- QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1;
- QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1;
+ QTest::newRow("success-internal") << "http://" << httpServerName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962;
+ QTest::newRow("failure-path") << "http://" << httpServerName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1;
+ QTest::newRow("failure-protocol") << "" << httpServerName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1;
}
void tst_QHttpNetworkConnection::head()
@@ -175,10 +179,10 @@ void tst_QHttpNetworkConnection::get_data()
QTest::addColumn<int>("contentLength");
QTest::addColumn<int>("downloadSize");
- QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962;
+ QTest::newRow("success-internal") << "http://" << httpServerName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962;
- QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << -1;
- QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << -1;
+ QTest::newRow("failure-path") << "http://" << httpServerName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << -1;
+ QTest::newRow("failure-protocol") << "" << httpServerName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << -1;
}
void tst_QHttpNetworkConnection::get()
@@ -244,8 +248,8 @@ void tst_QHttpNetworkConnection::put_data()
QTest::addColumn<QString>("data");
QTest::addColumn<bool>("succeed");
- QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/dav/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<true;
- QTest::newRow("fail-internal") << "http://" << QtNetworkSettings::serverName() << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
+ QTest::newRow("success-internal") << "http://" << httpServerName() << "/dav/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<true;
+ QTest::newRow("fail-internal") << "http://" << httpServerName() << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
QTest::newRow("fail-host") << "http://" << "invalid.test.qt-project.org" << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
}
@@ -324,8 +328,8 @@ void tst_QHttpNetworkConnection::post_data()
QTest::addColumn<int>("contentLength");
QTest::addColumn<int>("downloadSize");
- QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/cgi-bin/echo.cgi" << ushort(80) << false << "7 bytes" << 200 << "OK" << 7 << 7;
- QTest::newRow("failure-internal") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << -1;
+ QTest::newRow("success-internal") << "http://" << httpServerName() << "/qtest/cgi-bin/echo.cgi" << ushort(80) << false << "7 bytes" << 200 << "OK" << 7 << 7;
+ QTest::newRow("failure-internal") << "http://" << httpServerName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << -1;
}
void tst_QHttpNetworkConnection::post()
@@ -449,11 +453,11 @@ void tst_QHttpNetworkConnection::get401_data()
QTest::addColumn<QString>("password");
QTest::addColumn<int>("statusCode");
- QTest::newRow("no-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << false << "" << ""<<401;
- QTest::newRow("invalid-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "test" << "test"<<401;
- QTest::newRow("valid-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
- QTest::newRow("digest-authentication-invalid") << "http://" << QtNetworkSettings::serverName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "wrong" << "wrong"<<401;
- QTest::newRow("digest-authentication-valid") << "http://" << QtNetworkSettings::serverName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
+ QTest::newRow("no-credentials") << "http://" << httpServerName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << false << "" << ""<<401;
+ QTest::newRow("invalid-credentials") << "http://" << httpServerName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "test" << "test"<<401;
+ QTest::newRow("valid-credentials") << "http://" << httpServerName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
+ QTest::newRow("digest-authentication-invalid") << "http://" << httpServerName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "wrong" << "wrong"<<401;
+ QTest::newRow("digest-authentication-valid") << "http://" << httpServerName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
}
void tst_QHttpNetworkConnection::get401()
@@ -508,9 +512,9 @@ void tst_QHttpNetworkConnection::compression_data()
QTest::addColumn<bool>("autoCompress");
QTest::addColumn<QString>("contentCoding");
- QTest::newRow("success-autogzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << -1 << 418321 << true << "";
- QTest::newRow("success-nogzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << 418321 << 418321 << false << "identity";
- QTest::newRow("success-manualgzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/deflate/rfc2616.html" << ushort(80) << false << 200 << "OK" << 119124 << 119124 << false << "gzip";
+ QTest::newRow("success-autogzip-temp") << "http://" << httpServerName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << -1 << 418321 << true << "";
+ QTest::newRow("success-nogzip-temp") << "http://" << httpServerName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << 418321 << 418321 << false << "identity";
+ QTest::newRow("success-manualgzip-temp") << "http://" << httpServerName() << "/qtest/deflate/rfc2616.html" << ushort(80) << false << 200 << "OK" << 119124 << 119124 << false << "gzip";
}
@@ -586,9 +590,9 @@ void tst_QHttpNetworkConnection::ignoresslerror_data()
// fluke's certificate is signed by a non-standard authority.
// Since we don't introduce that CA into the SSL verification chain,
// connecting should fail.
- QTest::newRow("success-init") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << true << false << 200;
- QTest::newRow("success-fromSignal") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << false << true << 200;
- QTest::newRow("failure") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << false << false << 100;
+ QTest::newRow("success-init") << "https://" << httpServerName() << "/" << ushort(443) << true << true << false << 200;
+ QTest::newRow("success-fromSignal") << "https://" << httpServerName() << "/" << ushort(443) << true << false << true << 200;
+ QTest::newRow("failure") << "https://" << httpServerName() << "/" << ushort(443) << true << false << false << 100;
}
void tst_QHttpNetworkConnection::ignoresslerror()
@@ -635,7 +639,7 @@ void tst_QHttpNetworkConnection::nossl_data()
QTest::addColumn<bool>("encrypt");
QTest::addColumn<QNetworkReply::NetworkError>("networkError");
- QTest::newRow("protocol-error") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true <<QNetworkReply::ProtocolUnknownError;
+ QTest::newRow("protocol-error") << "https://" << httpServerName() << "/" << ushort(443) << true <<QNetworkReply::ProtocolUnknownError;
}
void tst_QHttpNetworkConnection::nossl()
@@ -696,7 +700,7 @@ void tst_QHttpNetworkConnection::getMultiple()
QFETCH(bool, pipeliningAllowed);
QFETCH(int, requestCount);
- QHttpNetworkConnection connection(connectionCount, QtNetworkSettings::serverName());
+ QHttpNetworkConnection connection(connectionCount, httpServerName());
QList<QHttpNetworkRequest*> requests;
QList<QHttpNetworkReply*> replies;
@@ -705,7 +709,7 @@ void tst_QHttpNetworkConnection::getMultiple()
// depending on what you use the results will vary.
// for the "real" results, use a URL that has "internet latency" for you. Then (6 connections, pipelining) will win.
// for LAN latency, you will possibly get that (1 connection, no pipelining) is the fastest
- QHttpNetworkRequest *request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QHttpNetworkRequest *request = new QHttpNetworkRequest("http://" + httpServerName() + "/qtest/rfc3252.txt");
if (pipeliningAllowed)
request->setPipeliningAllowed(true);
requests.append(request);
@@ -723,7 +727,7 @@ void tst_QHttpNetworkConnection::getMultipleWithPipeliningAndMultiplePriorities(
quint16 requestCount = 100;
// use 2 connections.
- QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+ QHttpNetworkConnection connection(2, httpServerName());
QList<QHttpNetworkRequest*> requests;
QList<QHttpNetworkReply*> replies;
@@ -731,9 +735,9 @@ void tst_QHttpNetworkConnection::getMultipleWithPipeliningAndMultiplePriorities(
for (int i = 0; i < requestCount; i++) {
QHttpNetworkRequest *request = 0;
if (i % 3)
- request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Get);
+ request = new QHttpNetworkRequest("http://" + httpServerName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Get);
else
- request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Head);
+ request = new QHttpNetworkRequest("http://" + httpServerName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Head);
if (i % 2 || i % 3)
request->setPipeliningAllowed(true);
@@ -800,9 +804,9 @@ void tst_QHttpNetworkConnection::getMultipleWithPriorities()
{
quint16 requestCount = 100;
// use 2 connections.
- QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+ QHttpNetworkConnection connection(2, httpServerName());
GetMultipleWithPrioritiesReceiver receiver(requestCount);
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QUrl url("http://" + httpServerName() + "/qtest/rfc3252.txt");
QList<QHttpNetworkRequest*> requests;
QList<QHttpNetworkReply*> replies;
@@ -854,10 +858,10 @@ void tst_QHttpNetworkConnection::getEmptyWithPipelining()
{
quint16 requestCount = 50;
// use 2 connections.
- QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+ QHttpNetworkConnection connection(2, httpServerName());
GetEmptyWithPipeliningReceiver receiver(requestCount);
- QUrl url("http://" + QtNetworkSettings::serverName() + "/cgi-bin/echo.cgi"); // a get on this = getting an empty file
+ QUrl url("http://" + httpServerName() + "/cgi-bin/echo.cgi"); // a get on this = getting an empty file
QList<QHttpNetworkRequest*> requests;
QList<QHttpNetworkReply*> replies;
@@ -901,8 +905,8 @@ void tst_QHttpNetworkConnection::getAndEverythingShouldBePipelined()
{
quint16 requestCount = 100;
// use 1 connection.
- QHttpNetworkConnection connection(1, QtNetworkSettings::serverName());
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QHttpNetworkConnection connection(1, httpServerName());
+ QUrl url("http://" + httpServerName() + "/qtest/rfc3252.txt");
QList<QHttpNetworkRequest*> requests;
QList<QHttpNetworkReply*> replies;
@@ -937,8 +941,8 @@ void tst_QHttpNetworkConnection::getAndThenDeleteObject_data()
void tst_QHttpNetworkConnection::getAndThenDeleteObject()
{
// yes, this will leak if the testcase fails. I don't care. It must not fail then :P
- QHttpNetworkConnection *connection = new QHttpNetworkConnection(QtNetworkSettings::serverName());
- QHttpNetworkRequest request("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile");
+ QHttpNetworkConnection *connection = new QHttpNetworkConnection(httpServerName());
+ QHttpNetworkRequest request("http://" + httpServerName() + "/qtest/bigfile");
QHttpNetworkReply *reply = connection->sendRequest(request);
reply->setDownstreamLimited(true);
diff --git a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
index 8b49679042..1ef2c118b9 100644
--- a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
+++ b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
@@ -35,7 +35,9 @@
#include <QtNetwork/QNetworkCookieJar>
#include <QtNetwork/QNetworkCookie>
#include <QtNetwork/QNetworkRequest>
+#if QT_CONFIG(topleveldomain)
#include "private/qtldurl_p.h"
+#endif
class tst_QNetworkCookieJar: public QObject
{
@@ -47,7 +49,7 @@ private slots:
void setCookiesFromUrl();
void cookiesForUrl_data();
void cookiesForUrl();
-#ifdef QT_BUILD_INTERNAL
+#if defined(QT_BUILD_INTERNAL) && QT_CONFIG(topleveldomain)
void effectiveTLDs_data();
void effectiveTLDs();
#endif
@@ -58,12 +60,13 @@ private slots:
class MyCookieJar: public QNetworkCookieJar
{
public:
- inline QList<QNetworkCookie> allCookies() const
- { return QNetworkCookieJar::allCookies(); }
- inline void setAllCookies(const QList<QNetworkCookie> &cookieList)
- { QNetworkCookieJar::setAllCookies(cookieList); }
+ ~MyCookieJar() override;
+ using QNetworkCookieJar::allCookies;
+ using QNetworkCookieJar::setAllCookies;
};
+MyCookieJar::~MyCookieJar() = default;
+
void tst_QNetworkCookieJar::getterSetter()
{
MyCookieJar jar;
@@ -398,7 +401,7 @@ void tst_QNetworkCookieJar::cookiesForUrl()
}
// This test requires private API.
-#ifdef QT_BUILD_INTERNAL
+#if defined(QT_BUILD_INTERNAL) && QT_CONFIG(topleveldomain)
void tst_QNetworkCookieJar::effectiveTLDs_data()
{
QTest::addColumn<QString>("domain");
diff --git a/tests/auto/network/access/qnetworkreply/certs/qt-test-server-host-network-cacert.pem b/tests/auto/network/access/qnetworkreply/certs/qt-test-server-host-network-cacert.pem
new file mode 100644
index 0000000000..5bdce3a3f9
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply/certs/qt-test-server-host-network-cacert.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIClzCCAgACCQDeuuUc2HkfKDANBgkqhkiG9w0BAQQFADCBjzELMAkGA1UEChMC
+UXQxGTAXBgNVBAsTEENvcmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5v
+Ym9keS5xdC5pbzENMAsGA1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UE
+BhMCTk8xHTAbBgNVBAMTFHF0LXRlc3Qtc2VydmVyLmxvY2FsMB4XDTE5MDEyNTE1
+NDE0N1oXDTQ5MDExNzE1NDE0N1owgY8xCzAJBgNVBAoTAlF0MRkwFwYDVQQLExBD
+b3JlIEFuZCBOZXR3b3JrMRswGQYJKoZIhvcNAQkBFgxub2JvZHkucXQuaW8xDTAL
+BgNVBAcTBE9zbG8xDTALBgNVBAgTBE9zbG8xCzAJBgNVBAYTAk5PMR0wGwYDVQQD
+ExRxdC10ZXN0LXNlcnZlci5sb2NhbDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAzarbb9Y0yafxwL7kQRgZ4gLJIuan1boDLp4oevRfGndfd6kRO49+8C7Gnus6
+2RLXwQxR6CRSPyPDQgwRxvIcoUL+tMJpg633cLEYFcwgKGIw8CwV5jMZr8PrHMCR
+9xFolFD4STcIMtc+dd+jvGkAFd7Nhw9cAmuCyAF9avAd3HMCAwEAATANBgkqhkiG
+9w0BAQQFAAOBgQB1dxK3Ia4sCpvSikKLaf1ZXu+9GKaNWKJe9bWex9/RmNOla9N2
+FIh6/CfaPFDy/OXCkyEiGg78iyg/DgqVoa9JJGV3diI6berisHMPJpv1syyz9YEU
+G3RQUClPcPV6EcedyqCdpbnIFtiSZbtJ0ZBGef4KzBN3rTmPucKb+bhMPg==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/access/qnetworkreply/test/test.pro b/tests/auto/network/access/qnetworkreply/test/test.pro
index 9d36352abc..4cc1f6431e 100644
--- a/tests/auto/network/access/qnetworkreply/test/test.pro
+++ b/tests/auto/network/access/qnetworkreply/test/test.pro
@@ -15,5 +15,5 @@ TESTDATA += ../empty ../rfc3252.txt ../resource ../bigfile ../*.jpg ../certs \
!android:!winrt: TEST_HELPER_INSTALLS = ../echo/echo
+CONFIG += unsupported/testserver
QT_TEST_SERVER_LIST = vsftpd apache2 ftp-proxy danted squid
-include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri)
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 3876621983..e85147095c 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -32,8 +32,11 @@
#include <QtCore/QDataStream>
#include <QtCore/QUrl>
#include <QtCore/QEventLoop>
+#include <QtCore/QElapsedTimer>
#include <QtCore/QFile>
#include <QtCore/QRandomGenerator>
+#include <QtCore/QRegularExpression>
+#include <QtCore/QRegularExpressionMatch>
#include <QtCore/QSharedPointer>
#include <QtCore/QScopedPointer>
#include <QtCore/QTemporaryFile>
@@ -123,7 +126,7 @@ class tst_QNetworkReply: public QObject
if (!seedCreated) {
seedCreated = true; // not thread-safe, but who cares
}
- return QString::number(QTime(0, 0, 0).msecsTo(QTime::currentTime()))
+ return QString::number(QTime::currentTime().msecsSinceStartOfDay())
+ QLatin1Char('-') + QString::number(QCoreApplication::applicationPid())
+ QLatin1Char('-') + QString::number(QRandomGenerator::global()->generate());
}
@@ -503,6 +506,11 @@ private Q_SLOTS:
void putWithServerClosingConnectionImmediately();
#endif
+ void autoDeleteRepliesAttribute_data();
+ void autoDeleteRepliesAttribute();
+ void autoDeleteReplies_data();
+ void autoDeleteReplies();
+
// NOTE: This test must be last!
void parentingRepliesToTheApp();
private:
@@ -550,8 +558,15 @@ static void setupSslServer(QSslSocket* serverSocket)
}
#ifdef QT_TEST_SERVER
+#ifdef QT_TEST_SERVER_NAME
+// In this case, each server is assigned a unique hostname. Use the wildcard SSL
+// certificate (*.test-net.qt.local).
const QString tst_QNetworkReply::certsFilePath = "/certs/qt-test-net-cacert.pem";
#else
+// Otherwise, select the single-name SSL certificate (qt-test-server.local) instead.
+const QString tst_QNetworkReply::certsFilePath = "/certs/qt-test-server-host-network-cacert.pem";
+#endif // QT_TEST_SERVER_NAME
+#else
const QString tst_QNetworkReply::certsFilePath = "/certs/qt-test-server-cacert.pem";
#endif
@@ -1135,7 +1150,7 @@ protected:
}
// now write in "blocking mode", this is where the rate measuring starts
- QTime timer;
+ QElapsedTimer timer;
timer.start();
//const qint64 writtenBefore = dataIndex;
//qint64 measuredTotalBytes = wantedSize - writtenBefore;
@@ -1234,7 +1249,7 @@ protected:
}
qint64 bytesRead = 0;
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
do {
if (device->bytesAvailable() == 0) {
@@ -1545,7 +1560,7 @@ void tst_QNetworkReply::initTestCase()
QDir::setSearchPaths("testdata", QStringList() << testDataDir);
#ifndef QT_NO_SSL
- QSslSocket::defaultCaCertificates(); //preload certificates
+ QSslConfiguration::defaultConfiguration().caCertificates(); //preload certificates
#endif
#ifndef QT_NO_BEARERMANAGEMENT
netConfMan = new QNetworkConfigurationManager(this);
@@ -1809,6 +1824,11 @@ void tst_QNetworkReply::getFromFileSpecial_data()
void tst_QNetworkReply::getFromFileSpecial()
{
+#if defined(QT_TEST_SERVER) && defined(Q_OS_WIN)
+ if (qstrcmp(QTest::currentDataTag(), "smb-path") == 0)
+ QSKIP("Docker-based test server doesn't support smb protocol yet");
+#endif
+
QFETCH(QString, fileName);
QFETCH(QString, url);
@@ -3202,6 +3222,11 @@ void tst_QNetworkReply::ioGetFromFileSpecial_data()
void tst_QNetworkReply::ioGetFromFileSpecial()
{
+#if defined(QT_TEST_SERVER) && defined(Q_OS_WIN)
+ if (qstrcmp(QTest::currentDataTag(), "smb-path") == 0)
+ QSKIP("Docker-based test server doesn't support smb protocol yet");
+#endif
+
QFETCH(QString, fileName);
QFETCH(QString, url);
@@ -4125,10 +4150,10 @@ void tst_QNetworkReply::ioGetFromHttpWithCache()
request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
QFETCH(QStringList, extraHttpHeaders);
- QStringListIterator it(extraHttpHeaders);
- while (it.hasNext()) {
- QString header = it.next();
- QString value = it.next();
+ QVERIFY(extraHttpHeaders.size() % 2 == 0);
+ for (auto it = extraHttpHeaders.cbegin(), end = extraHttpHeaders.cend(); it != end; /*double-stepping*/) {
+ QString header = *it++;
+ QString value = *it++;
request.setRawHeader(header.toLatin1(), value.toLatin1()); // To latin1? Deal with it!
}
@@ -5014,6 +5039,9 @@ public:
// very similar to ioPostToHttpUploadProgress but for SSL
void tst_QNetworkReply::ioPostToHttpsUploadProgress()
{
+#ifdef Q_OS_WIN
+ QSKIP("QTBUG-76157: get rid of locking in TLS handshake (QSslSocket)");
+#endif
//QFile sourceFile(testDataDir + "/bigfile");
//QVERIFY(sourceFile.open(QIODevice::ReadOnly));
qint64 wantedSize = 2*1024*1024; // 2 MB
@@ -5126,8 +5154,8 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp()
const int rate = 200; // in kB per sec
RateControlledReader reader(server, reply.data(), rate, bufferSize);
- QTime loopTime;
- loopTime.start();
+ QElapsedTimer loopTimer;
+ loopTimer.start();
const int result = waitForFinish(reply);
if (notEnoughDataForFastSender) {
@@ -5137,7 +5165,7 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp()
QVERIFY2(result == Success, msgWaitForFinished(reply));
- const int elapsedTime = loopTime.elapsed();
+ const int elapsedTime = loopTimer.elapsed();
server.wait();
reader.wrapUp();
@@ -5423,12 +5451,12 @@ void tst_QNetworkReply::rateControl()
RateControlledReader reader(sender, reply.data(), rate, 20);
// this test is designed to run for 25 seconds at most
- QTime loopTime;
- loopTime.start();
+ QElapsedTimer loopTimer;
+ loopTimer.start();
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
- int elapsedTime = loopTime.elapsed();
+ int elapsedTime = loopTimer.elapsed();
if (!errorSpy.isEmpty()) {
qDebug() << "ERROR!" << errorSpy[0][0] << reply->errorString();
@@ -6098,8 +6126,8 @@ void tst_QNetworkReply::httpConnectionCount()
}
int pendingConnectionCount = 0;
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
while(pendingConnectionCount <= 20) {
QTestEventLoop::instance().enterLoop(1);
@@ -6111,7 +6139,7 @@ void tst_QNetworkReply::httpConnectionCount()
}
// at max. wait 10 sec
- if (time.elapsed() > 10000)
+ if (timer.elapsed() > 10000)
break;
}
@@ -6395,6 +6423,10 @@ void tst_QNetworkReply::encrypted()
void tst_QNetworkReply::abortOnEncrypted()
{
+#ifdef Q_OS_WIN
+ QSKIP("QTBUG-76157: get rid of locking in TLS handshake (QSslSocket)");
+#endif
+
SslServer server;
server.listen();
if (!server.isListening())
@@ -7888,9 +7920,10 @@ void tst_QNetworkReply::synchronousAuthenticationCache()
"Content-Type: text/plain\r\n"
"\r\n"
"auth";
- QRegExp rx("Authorization: Basic ([^\r\n]*)\r\n");
- if (rx.indexIn(receivedData) > 0) {
- if (QByteArray::fromBase64(rx.cap(1).toLatin1()) == "login:password") {
+ QRegularExpression rx("Authorization: Basic ([^\r\n]*)\r\n");
+ QRegularExpressionMatch match = rx.match(receivedData);
+ if (match.hasMatch()) {
+ if (QByteArray::fromBase64(match.captured(1).toLatin1()) == "login:password") {
dataToTransmit =
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/plain\r\n"
@@ -8126,16 +8159,17 @@ void tst_QNetworkReply::backgroundRequest()
SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
#endif
- const QWeakPointer<const QNetworkSession> session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
- QVERIFY(session);
- QNetworkSession::UsagePolicies original = session.data()->usagePolicies();
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), QNetworkSession::UsagePolicies(policy));
+ const QWeakPointer<const QNetworkSession> sessionWeakPtr = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
+ QVERIFY(!sessionWeakPtr.isNull());
+ auto session = const_cast<QNetworkSession *>(sessionWeakPtr.toStrongRef().data());
+ QNetworkSession::UsagePolicies original = session->usagePolicies();
+ QNetworkSessionPrivate::setUsagePolicies(*session, QNetworkSession::UsagePolicies(policy));
QNetworkReplyPtr reply(manager.get(request));
QVERIFY(waitForFinish(reply) != Timeout);
if (session)
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), original);
+ QNetworkSessionPrivate::setUsagePolicies(*session, original);
QVERIFY(reply->isFinished());
QCOMPARE(reply->error(), error);
@@ -8190,10 +8224,11 @@ void tst_QNetworkReply::backgroundRequestInterruption()
SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
#endif
- const QWeakPointer<const QNetworkSession> session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
- QVERIFY(session);
- QNetworkSession::UsagePolicies original = session.data()->usagePolicies();
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), QNetworkSession::NoPolicy);
+ const QWeakPointer<const QNetworkSession> sessionWeakPtr = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
+ QVERIFY(!sessionWeakPtr.isNull());
+ auto session = const_cast<QNetworkSession *>(sessionWeakPtr.toStrongRef().data());
+ QNetworkSession::UsagePolicies original = session->usagePolicies();
+ QNetworkSessionPrivate::setUsagePolicies(*session, QNetworkSession::NoPolicy);
request.setAttribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute, 8192);
QNetworkReplyPtr reply(manager.get(request));
@@ -8202,14 +8237,14 @@ void tst_QNetworkReply::backgroundRequestInterruption()
QSignalSpy spy(reply.data(), SIGNAL(readyRead()));
QTRY_VERIFY(spy.count() > 0);
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), QNetworkSession::NoBackgroundTrafficPolicy);
+ QNetworkSessionPrivate::setUsagePolicies(*session, QNetworkSession::NoBackgroundTrafficPolicy);
// After we have changed the policy we can download at full speed.
reply->setReadBufferSize(0);
QVERIFY(waitForFinish(reply) != Timeout);
if (session)
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), original);
+ QNetworkSessionPrivate::setUsagePolicies(*session, original);
QVERIFY(reply->isFinished());
QCOMPARE(reply->error(), error);
@@ -8249,8 +8284,8 @@ void tst_QNetworkReply::backgroundRequestConnectInBackground()
QWeakPointer<const QNetworkSession> session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
//force QNAM to reopen the session.
- if (session && session.data()->isOpen()) {
- const_cast<QNetworkSession *>(session.data())->close();
+ if (session && session.toStrongRef().data()->isOpen()) {
+ const_cast<QNetworkSession *>(session.toStrongRef().data())->close();
QCoreApplication::processEvents(); //let signals propagate inside QNAM
}
@@ -8259,19 +8294,19 @@ void tst_QNetworkReply::backgroundRequestConnectInBackground()
session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
QVERIFY(session);
- QNetworkSession::UsagePolicies original = session.data()->usagePolicies();
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), QNetworkSession::NoPolicy);
+ QNetworkSession::UsagePolicies original = session.toStrongRef().data()->usagePolicies();
+ QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.toStrongRef().data()), QNetworkSession::NoPolicy);
QNetworkReplyPtr reply(manager.get(request));
QVERIFY(waitForFinish(reply) != Timeout);
session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
if (session) {
- QVariant cib = session.data()->sessionProperty(QStringLiteral("ConnectInBackground"));
+ QVariant cib = session.toStrongRef().data()->sessionProperty(QStringLiteral("ConnectInBackground"));
if (!cib.isValid())
QSKIP("inconclusive - ConnectInBackground session property not supported by the bearer plugin");
QCOMPARE(cib.toBool(), background);
- QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), original);
+ QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.toStrongRef().data()), original);
} else {
QSKIP("inconclusive - network session has been destroyed");
}
@@ -8472,7 +8507,9 @@ void tst_QNetworkReply::ioHttpRedirectErrors_data()
QTest::newRow("too-many-redirects") << "http://localhost" << tempRedirectReply << QNetworkReply::TooManyRedirectsError;
#if QT_CONFIG(ssl)
+#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("insecure-redirect") << "https://localhost" << tempRedirectReply << QNetworkReply::InsecureRedirectError;
+#endif // Q_OS_WIN
#endif
QTest::newRow("unknown-redirect") << "http://localhost"<< tempRedirectReply.replace("http", "bad_protocol") << QNetworkReply::ProtocolUnknownError;
}
@@ -8549,9 +8586,11 @@ void tst_QNetworkReply::ioHttpRedirectPolicy_data()
QTest::newRow("nolesssafe-nossl") << QNetworkRequest::NoLessSafeRedirectPolicy << false << 1 << 200;
QTest::newRow("same-origin-nossl") << QNetworkRequest::SameOriginRedirectPolicy << false << 1 << 200;
#if QT_CONFIG(ssl)
+#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("manual-ssl") << QNetworkRequest::ManualRedirectPolicy << true << 0 << 307;
QTest::newRow("nolesssafe-ssl") << QNetworkRequest::NoLessSafeRedirectPolicy << true << 1 << 200;
QTest::newRow("same-origin-ssl") << QNetworkRequest::SameOriginRedirectPolicy << true << 1 << 200;
+#endif // Q_OS_WIN
#endif
}
@@ -8605,33 +8644,41 @@ void tst_QNetworkReply::ioHttpRedirectPolicyErrors_data()
QTest::newRow("nolesssafe-nossl-nossl-too-many") << QNetworkRequest::NoLessSafeRedirectPolicy
<< false << QString("http://localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
#if QT_CONFIG(ssl)
+#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("nolesssafe-ssl-ssl-too-many") << QNetworkRequest::NoLessSafeRedirectPolicy
<< true << QString("https:/localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
QTest::newRow("nolesssafe-ssl-nossl-insecure-redirect") << QNetworkRequest::NoLessSafeRedirectPolicy
<< true << QString("http://localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
+#endif // Q_OS_WIN
#endif
// 2. SameOriginRedirectsPolicy
QTest::newRow("same-origin-nossl-nossl-too-many") << QNetworkRequest::SameOriginRedirectPolicy
<< false << QString("http://localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
#if QT_CONFIG(ssl)
+#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("same-origin-ssl-ssl-too-many") << QNetworkRequest::SameOriginRedirectPolicy
<< true << QString("https://localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
QTest::newRow("same-origin-https-http-wrong-protocol") << QNetworkRequest::SameOriginRedirectPolicy
<< true << QString("http://localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
+#endif // Q_OS_WIN
#endif
QTest::newRow("same-origin-http-https-wrong-protocol") << QNetworkRequest::SameOriginRedirectPolicy
<< false << QString("https://localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
QTest::newRow("same-origin-http-http-wrong-host") << QNetworkRequest::SameOriginRedirectPolicy
<< false << QString("http://not-so-localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
#if QT_CONFIG(ssl)
+#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("same-origin-https-https-wrong-host") << QNetworkRequest::SameOriginRedirectPolicy
<< true << QString("https://not-so-localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
+#endif // Q_OS_WIN
#endif
QTest::newRow("same-origin-http-http-wrong-port") << QNetworkRequest::SameOriginRedirectPolicy
<< false << QString("http://localhost/%1") << 50 << QNetworkReply::InsecureRedirectError;
#if QT_CONFIG(ssl)
+#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("same-origin-https-https-wrong-port") << QNetworkRequest::SameOriginRedirectPolicy
<< true << QString("https://localhost/%1") << 50 << QNetworkReply::InsecureRedirectError;
+#endif // Q_OS_WIN
#endif
}
@@ -9106,6 +9153,10 @@ void tst_QNetworkReply::putWithServerClosingConnectionImmediately()
for (int s = 0; s <= 1; s++) {
withSsl = (s == 1);
+#ifdef Q_OS_WIN
+ if (withSsl)
+ QSKIP("QTBUG-76157: get rid of locking in TLS handshake (QSslSocket)");
+#endif // Q_OS_WIN
// Test also needs to run several times because of 9c2ecf89
for (int j = 0; j < 20; j++) {
// emulate a minimal https server
@@ -9150,6 +9201,166 @@ void tst_QNetworkReply::putWithServerClosingConnectionImmediately()
#endif
+void tst_QNetworkReply::autoDeleteRepliesAttribute_data()
+{
+ QTest::addColumn<QUrl>("destination");
+
+ QTest::newRow("http") << QUrl("http://QInvalidDomain.qt/test");
+ QTest::newRow("https") << QUrl("https://QInvalidDomain.qt/test");
+ QTest::newRow("ftp") << QUrl("ftp://QInvalidDomain.qt/test");
+ QTest::newRow("file") << QUrl("file:///thisfolderdoesn'texist/probably.txt");
+#ifdef Q_OS_WIN
+ // Only supported on windows.
+ QTest::newRow("remote-file") << QUrl("file://QInvalidHost/thisfolderdoesn'texist/probably.txt");
+#endif
+ QTest::newRow("qrc") << QUrl("qrc:///path/to/nowhere");
+ QTest::newRow("data") << QUrl("data:,Some%20plaintext%20data");
+}
+
+void tst_QNetworkReply::autoDeleteRepliesAttribute()
+{
+ QFETCH(QUrl, destination);
+ {
+ // Get
+ QNetworkRequest request(destination);
+ request.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, true);
+ QNetworkReply *reply = manager.get(request);
+ QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply, &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QVERIFY(destroyedSpy.wait());
+ }
+ {
+ // Post
+ QNetworkRequest request(destination);
+ request.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, true);
+ QNetworkReply *reply = manager.post(request, QByteArrayLiteral("datastring"));
+ QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply, &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QVERIFY(destroyedSpy.wait());
+ }
+ // Now repeated, but without the attribute to make sure it does not get deleted automatically.
+ // We need two calls to processEvents to test that the QNetworkReply doesn't get deleted.
+ // The first call executes a metacall event which adds the deleteLater meta event which
+ // would be executed in the second call. But that shouldn't happen without the attribute.
+ {
+ // Get
+ QNetworkRequest request(destination);
+ QScopedPointer<QNetworkReply> reply(manager.get(request));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+ {
+ // Post
+ QNetworkRequest request(destination);
+ QScopedPointer<QNetworkReply> reply(manager.post(request, QByteArrayLiteral("datastring")));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+}
+
+void tst_QNetworkReply::autoDeleteReplies_data()
+{
+ autoDeleteRepliesAttribute_data();
+}
+
+void tst_QNetworkReply::autoDeleteReplies()
+{
+ QFETCH(QUrl, destination);
+ manager.setAutoDeleteReplies(true);
+ auto cleanup = qScopeGuard([this] { manager.setAutoDeleteReplies(false); });
+ {
+ // Get
+ QNetworkRequest request(destination);
+ QNetworkReply *reply = manager.get(request);
+ QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply, &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QVERIFY(destroyedSpy.wait());
+ }
+ {
+ // Post
+ QNetworkRequest request(destination);
+ QNetworkReply *reply = manager.post(request, QByteArrayLiteral("datastring"));
+ QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply, &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QVERIFY(destroyedSpy.wait());
+ }
+ // Here we repeat the test, but override the auto-deletion in the QNetworkRequest
+ // We need two calls to processEvents to test that the QNetworkReply doesn't get deleted.
+ // The first call executes a metacall event which adds the deleteLater meta event which
+ // would be executed in the second call. But that shouldn't happen in this case.
+ {
+ // Get
+ QNetworkRequest request(destination);
+ request.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, false);
+ QScopedPointer<QNetworkReply> reply(manager.get(request));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+ {
+ // Post
+ QNetworkRequest request(destination);
+ request.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, false);
+ QScopedPointer<QNetworkReply> reply(manager.post(request, QByteArrayLiteral("datastring")));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+ // Now we repeat the test with autoDeleteReplies set to false
+ cleanup.dismiss();
+ manager.setAutoDeleteReplies(false);
+ {
+ // Get
+ QNetworkRequest request(destination);
+ QScopedPointer<QNetworkReply> reply(manager.get(request));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+ {
+ // Post
+ QNetworkRequest request(destination);
+ QScopedPointer<QNetworkReply> reply(manager.post(request, QByteArrayLiteral("datastring")));
+ QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
+ QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
+ QVERIFY(finishedSpy.wait());
+ QCOMPARE(destroyedSpy.count(), 0);
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QCOMPARE(destroyedSpy.count(), 0);
+ }
+}
+
// NOTE: This test must be last testcase in tst_qnetworkreply!
void tst_QNetworkReply::parentingRepliesToTheApp()
{
diff --git a/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp b/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp
index 55053842dc..8cef351554 100644
--- a/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp
+++ b/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp
@@ -93,7 +93,7 @@ void tst_QAuthenticator::basicAuth()
QCOMPARE(priv->phase, QAuthenticatorPrivate::Start);
- QCOMPARE(priv->calculateResponse("GET", "/").constData(), QByteArray("Basic " + expectedReply).constData());
+ QCOMPARE(priv->calculateResponse("GET", "/", "").constData(), QByteArray("Basic " + expectedReply).constData());
}
void tst_QAuthenticator::ntlmAuth_data()
@@ -133,9 +133,9 @@ void tst_QAuthenticator::ntlmAuth()
headers << qMakePair<QByteArray, QByteArray>("WWW-Authenticate", "NTLM");
priv->parseHttpResponse(headers, /*isProxy = */ false);
if (sso)
- QVERIFY(priv->calculateResponse("GET", "/").startsWith("NTLM "));
+ QVERIFY(priv->calculateResponse("GET", "/", "").startsWith("NTLM "));
else
- QCOMPARE(priv->calculateResponse("GET", "/").constData(), "NTLM TlRMTVNTUAABAAAABYIIAAAAAAAAAAAAAAAAAAAAAAA=");
+ QCOMPARE(priv->calculateResponse("GET", "/", "").constData(), "NTLM TlRMTVNTUAABAAAABYIIAAAAAAAAAAAAAAAAAAAAAAA=");
// NTLM phase 2: challenge
headers.clear();
@@ -146,7 +146,7 @@ void tst_QAuthenticator::ntlmAuth()
QEXPECT_FAIL("with-realm-sso", "NTLM authentication code doesn't extract the realm", Continue);
QCOMPARE(auth.realm(), realm);
- QVERIFY(priv->calculateResponse("GET", "/").startsWith("NTLM "));
+ QVERIFY(priv->calculateResponse("GET", "/", "").startsWith("NTLM "));
}
void tst_QAuthenticator::equalityOperators()
diff --git a/tests/auto/network/kernel/qhostaddress/qhostaddress.pro b/tests/auto/network/kernel/qhostaddress/qhostaddress.pro
index b5d6ea6459..d170d879e6 100644
--- a/tests/auto/network/kernel/qhostaddress/qhostaddress.pro
+++ b/tests/auto/network/kernel/qhostaddress/qhostaddress.pro
@@ -4,4 +4,4 @@ SOURCES += tst_qhostaddress.cpp
QT = core network-private testlib
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
diff --git a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro
index 3d8457dd46..d358cdf52c 100644
--- a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro
+++ b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro
@@ -6,6 +6,6 @@ SOURCES += tst_qhostinfo.cpp
requires(qtConfig(private_tests))
QT = core-private network-private testlib
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
winrt: WINRT_MANIFEST.capabilities += internetClientServer
diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
index 0a130d363e..da6e02210b 100644
--- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
+++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
@@ -179,7 +179,6 @@ void tst_QHostInfo::staticInformation()
void tst_QHostInfo::initTestCase()
{
- QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
#ifndef QT_NO_BEARERMANAGEMENT
//start the default network
netConfMan = new QNetworkConfigurationManager(this);
@@ -240,8 +239,6 @@ void tst_QHostInfo::lookupIPv4_data()
QTest::addColumn<QString>("addresses");
QTest::addColumn<int>("err");
- // Test server lookup
- QTest::newRow("lookup_01") << QtNetworkSettings::serverName() << QtNetworkSettings::serverIP().toString() << int(QHostInfo::NoError);
QTest::newRow("empty") << "" << "" << int(QHostInfo::HostNotFound);
QTest::newRow("single_ip4") << "a-single" TEST_DOMAIN << "192.0.2.1" << int(QHostInfo::NoError);
diff --git a/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp b/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp
index 5eedd1043b..cd6019090f 100644
--- a/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp
+++ b/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp
@@ -131,7 +131,7 @@ void tst_QNetworkDatagram::makeReply()
QNetworkDatagram copy = dgram;
copy.setData(copy.data());
{
- QNetworkDatagram reply = qMove(copy).makeReply("World");
+ QNetworkDatagram reply = std::move(copy).makeReply("World");
QCOMPARE(reply.data(), QByteArray("World"));
QCOMPARE(reply.senderAddress(), QHostAddress(localAddress));
QCOMPARE(reply.senderPort(), localAddress.isEmpty() ? -1 : dgram.destinationPort());
diff --git a/tests/auto/network/socket/platformsocketengine/BLACKLIST b/tests/auto/network/socket/platformsocketengine/BLACKLIST
index 8e1a55995e..154c5cc5b2 100644
--- a/tests/auto/network/socket/platformsocketengine/BLACKLIST
+++ b/tests/auto/network/socket/platformsocketengine/BLACKLIST
@@ -1 +1,8 @@
+[tcpLoopbackPerformance]
+windows
+[receiveUrgentData]
+windows
+[serverTest]
+windows
+[tcpLoopbackPerformance]
windows
diff --git a/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri b/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri
index 46c722deba..868439de6a 100644
--- a/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri
+++ b/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri
@@ -4,7 +4,7 @@ QNETWORK_SRC = $$QT_SOURCE_TREE/src/network
INCLUDEPATH += $$QNETWORK_SRC
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
unix:qtConfig(reduce_exports) {
SOURCES += $$QNETWORK_SRC/socket/qnativesocketengine_unix.cpp
diff --git a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
index 01168cc0d6..ffc63ee46a 100644
--- a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
+++ b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
@@ -32,7 +32,7 @@
#include <qcoreapplication.h>
#include <qdatastream.h>
#include <qhostaddress.h>
-#include <qdatetime.h>
+#include <qelapsedtimer.h>
#ifdef Q_OS_UNIX
#include <unistd.h>
@@ -403,7 +403,7 @@ void tst_PlatformSocketEngine::udpLoopbackPerformance()
QHostAddress localhost = QHostAddress::LocalHost;
qlonglong readBytes = 0;
- QTime timer;
+ QElapsedTimer timer;
timer.start();
while (timer.elapsed() < 5000) {
udpSocket2.write(message1.data(), message1.size());
@@ -462,7 +462,7 @@ void tst_PlatformSocketEngine::tcpLoopbackPerformance()
QByteArray message1(messageSize, '@');
QByteArray answer(messageSize, '@');
- QTime timer;
+ QElapsedTimer timer;
timer.start();
qlonglong readBytes = 0;
while (timer.elapsed() < 5000) {
diff --git a/tests/auto/network/socket/qhttpsocketengine/BLACKLIST b/tests/auto/network/socket/qhttpsocketengine/BLACKLIST
index 8e1a55995e..991d01dd00 100644
--- a/tests/auto/network/socket/qhttpsocketengine/BLACKLIST
+++ b/tests/auto/network/socket/qhttpsocketengine/BLACKLIST
@@ -1 +1,6 @@
+[passwordAuth]
+windows
+[downloadBigFile]
+windows
+[ensureEofTriggersNotification]
windows
diff --git a/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro b/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro
index 56a4fb8aee..63f41f4eb7 100644
--- a/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro
+++ b/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro
@@ -10,3 +10,8 @@ MOC_DIR=tmp
requires(qtConfig(private_tests))
QT = core-private network-private testlib
+# TODO: For now linux-only, because cyrus is linux-only atm ...
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = squid danted cyrus apache2
+}
diff --git a/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp b/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp
index 68f3ea059b..64241014d7 100644
--- a/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp
+++ b/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp
@@ -38,6 +38,7 @@
#include <qhostaddress.h>
#include <qtcpsocket.h>
#include <qdebug.h>
+#include <qelapsedtimer.h>
#include <qtcpserver.h>
#include "../../../network-settings.h"
@@ -122,7 +123,14 @@ public slots:
void tst_QHttpSocketEngine::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif
}
void tst_QHttpSocketEngine::init()
@@ -171,7 +179,7 @@ void tst_QHttpSocketEngine::errorTest_data()
QTest::newRow("proxy-host-not-found") << "this-host-does-not-exist." << 1080 << QString()
<< QString()
<< int(QAbstractSocket::ProxyNotFoundError);
- QTest::newRow("proxy-connection-refused") << QtNetworkSettings::serverName() << 2 << QString()
+ QTest::newRow("proxy-connection-refused") << QtNetworkSettings::socksProxyServerName() << 2 << QString()
<< QString()
<< int(QAbstractSocket::ProxyConnectionRefusedError);
@@ -278,13 +286,12 @@ void tst_QHttpSocketEngine::simpleConnectToIMAP()
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128));
-
- QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
QVERIFY(socketDevice.waitForWrite());
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
- QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::serverIP());
+ QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::imapServerIp());
QVERIFY(!socketDevice.localAddress().isNull());
QVERIFY(socketDevice.localPort() > 0);
@@ -292,10 +299,10 @@ void tst_QHttpSocketEngine::simpleConnectToIMAP()
QVERIFY(socketDevice.waitForRead());
// Read the greeting
- qint64 available = socketDevice.bytesAvailable();
+ qint64 available = int(socketDevice.bytesAvailable());
QVERIFY(available > 0);
QByteArray array;
- array.resize(available);
+ array.resize(int(available));
QVERIFY(socketDevice.read(array.data(), array.size()) == available);
// Check that the greeting is what we expect it to be
@@ -310,9 +317,9 @@ void tst_QHttpSocketEngine::simpleConnectToIMAP()
// Wait for the response
QVERIFY(socketDevice.waitForRead());
- available = socketDevice.bytesAvailable();
+ available = int(socketDevice.bytesAvailable());
QVERIFY(available > 0);
- array.resize(available);
+ array.resize(int(available));
QVERIFY(socketDevice.read(array.data(), array.size()) == available);
// Check that the greeting is what we expect it to be
@@ -321,7 +328,7 @@ void tst_QHttpSocketEngine::simpleConnectToIMAP()
// Wait for the response
QVERIFY(socketDevice.waitForRead());
char c;
- QCOMPARE(socketDevice.read(&c, sizeof(c)), (qint64) -1);
+ QCOMPARE(socketDevice.read(&c, sizeof(c)), qint64(-1));
QCOMPARE(socketDevice.error(), QAbstractSocket::RemoteHostClosedError);
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
}
@@ -335,10 +342,10 @@ void tst_QHttpSocketEngine::simpleErrorsAndStates()
// Initialize device
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- QVERIFY(!socketDevice.connectToHost(QHostAddress(QtNetworkSettings::serverName()), 8088));
+ QVERIFY(!socketDevice.connectToHost(QHostAddress(QtNetworkSettings::socksProxyServerName()), 8088));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
if (socketDevice.waitForWrite(30000)) {
QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState ||
@@ -391,7 +398,7 @@ void tst_QHttpSocketEngine::tcpLoopbackPerformance()
QByteArray message1(messageSize, '@');
QByteArray answer(messageSize, '@');
- QTime timer;
+ QElapsedTimer timer;
timer.start();
qlonglong readBytes = 0;
while (timer.elapsed() < 30000) {
@@ -422,7 +429,7 @@ void tst_QHttpSocketEngine::tcpSocketBlockingTest()
QTcpSocket socket;
// Connect
- socket.connectToHost(QtNetworkSettings::serverName(), 143);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket.waitForConnected());
QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
@@ -479,7 +486,7 @@ void tst_QHttpSocketEngine::tcpSocketNonBlockingTest()
tcpSocketNonBlocking_socket = &socket;
// Connect
- socket.connectToHost(QtNetworkSettings::serverName(), 143);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket.state() == QTcpSocket::HostLookupState ||
socket.state() == QTcpSocket::ConnectingState);
@@ -607,13 +614,13 @@ void tst_QHttpSocketEngine::downloadBigFile()
connect(tmpSocket, SIGNAL(connected()), SLOT(exitLoopSlot()));
connect(tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot()));
- tmpSocket->connectToHost(QtNetworkSettings::serverName(), 80);
+ tmpSocket->connectToHost(QtNetworkSettings::httpServerName(), 80);
QTestEventLoop::instance().enterLoop(30);
if (QTestEventLoop::instance().timeout())
QFAIL("Network operation timed out");
- QByteArray hostName = QtNetworkSettings::serverName().toLatin1();
+ QByteArray hostName = QtNetworkSettings::httpServerName().toLatin1();
QCOMPARE(tmpSocket->state(), QAbstractSocket::ConnectedState);
QVERIFY(tmpSocket->write("GET /qtest/mediumfile HTTP/1.0\r\n") > 0);
QVERIFY(tmpSocket->write("Host: ") > 0);
@@ -623,7 +630,7 @@ void tst_QHttpSocketEngine::downloadBigFile()
bytesAvailable = 0;
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
QTestEventLoop::instance().enterLoop(60);
@@ -664,13 +671,13 @@ void tst_QHttpSocketEngine::passwordAuth()
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128, "qsockstest", "password"));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128, "qsockstest", "password"));
- QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
+ QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
QVERIFY(socketDevice.waitForWrite());
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
- QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::serverIP());
+ QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::imapServerIp());
// Wait for the greeting
QVERIFY(socketDevice.waitForRead());
diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
index 45ab275510..732f7eef00 100644
--- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
+++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
@@ -32,6 +32,7 @@
#include <qtextstream.h>
#include <qdatastream.h>
+#include <qelapsedtimer.h>
#include <QtNetwork/qlocalsocket.h>
#include <QtNetwork/qlocalserver.h>
@@ -552,7 +553,7 @@ void tst_QLocalSocket::sendData()
QCOMPARE(serverSocket->state(), QLocalSocket::ConnectedState);
QTextStream out(serverSocket);
QTextStream in(&socket);
- out << testLine << endl;
+ out << testLine << Qt::endl;
bool wrote = serverSocket->waitForBytesWritten(3000);
if (!socket.canReadLine()) {
@@ -877,7 +878,7 @@ public:
QLocalSocket *serverSocket = server.nextPendingConnection();
QVERIFY(serverSocket);
QTextStream out(serverSocket);
- out << testLine << endl;
+ out << testLine << Qt::endl;
QCOMPARE(serverSocket->state(), QLocalSocket::ConnectedState);
QVERIFY2(serverSocket->waitForBytesWritten(), serverSocket->errorString().toLatin1().constData());
QCOMPARE(serverSocket->errorString(), QString("Unknown error"));
@@ -1031,7 +1032,7 @@ void tst_QLocalSocket::waitForDisconnect()
QLocalSocket *serverSocket = server.nextPendingConnection();
QVERIFY(serverSocket);
socket.disconnectFromServer();
- QTime timer;
+ QElapsedTimer timer;
timer.start();
QVERIFY(serverSocket->waitForDisconnected(3000));
QVERIFY(timer.elapsed() < 2000);
diff --git a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
index 60526827bf..8af3cea8dc 100644
--- a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
+++ b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
@@ -2,6 +2,9 @@
*
[passwordAuth]
*
+# QTBUG-74162
+[passwordAuth2]
+*
[serverTest]
windows
[downloadBigFile]
diff --git a/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro b/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro
index 71ceafa133..243eab9480 100644
--- a/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro
+++ b/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro
@@ -11,3 +11,9 @@ MOC_DIR=tmp
QT = core-private network-private testlib
requires(qtConfig(private_tests))
+
+# Only on Linux until cyrus has been added to docker-compose-for-{windows,macOS}.yml and tested
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = danted apache2 cyrus
+}
diff --git a/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp b/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp
index 1212ea20e5..464054f8a6 100644
--- a/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp
+++ b/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp
@@ -137,7 +137,13 @@ private slots:
void tst_QSocks5SocketEngine::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif
}
//---------------------------------------------------------------------------
@@ -293,13 +299,13 @@ void tst_QSocks5SocketEngine::simpleConnectToIMAP()
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080));
- QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
+ QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
QVERIFY(socketDevice.waitForWrite());
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
- QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::serverIP());
+ QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::imapServerIp());
// Wait for the greeting
QVERIFY(socketDevice.waitForRead());
@@ -347,10 +353,10 @@ void tst_QSocks5SocketEngine::simpleErrorsAndStates()
// Initialize device
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- QVERIFY(!socketDevice.connectToHost(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first(), 8088));
+ QVERIFY(!socketDevice.connectToHost(QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses().first(), 8088));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
if (socketDevice.waitForWrite(15000)) {
QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState ||
@@ -433,7 +439,7 @@ void tst_QSocks5SocketEngine::serverTest()
// Initialize a Tcp socket
QVERIFY(server.initialize(QAbstractSocket::TcpSocket));
- QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
server.setProxy(proxy);
@@ -510,7 +516,7 @@ void tst_QSocks5SocketEngine::udpTest()
QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket));
QVERIFY(udpSocket.isValid());
- QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
udpSocket.setProxy(proxy);
@@ -564,7 +570,7 @@ void tst_QSocks5SocketEngine::tcpSocketBlockingTest()
QTcpSocket socket;
// Connect
- socket.connectToHost(QtNetworkSettings::serverName(), 143);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket.waitForConnected());
QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
@@ -635,7 +641,7 @@ void tst_QSocks5SocketEngine::tcpSocketNonBlockingTest()
});
// Connect
- socket.connectToHost(QtNetworkSettings::serverName(), 143);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket.state() == QTcpSocket::HostLookupState ||
socket.state() == QTcpSocket::ConnectingState);
@@ -754,13 +760,13 @@ void tst_QSocks5SocketEngine::downloadBigFile()
<< " (" << stopWatch.elapsed() << "ms)";
});
- socket.connectToHost(QtNetworkSettings::serverName(), 80);
+ socket.connectToHost(QtNetworkSettings::httpServerName(), 80);
QTestEventLoop::instance().enterLoop(30);
if (QTestEventLoop::instance().timeout())
QFAIL("Network operation timed out");
- QByteArray hostName = QtNetworkSettings::serverName().toLatin1();
+ QByteArray hostName = QtNetworkSettings::httpServerName().toLatin1();
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
QVERIFY(socket.write("GET /qtest/mediumfile HTTP/1.0\r\n") > 0);
QVERIFY(socket.write("HOST: ") > 0);
@@ -791,13 +797,13 @@ void tst_QSocks5SocketEngine::passwordAuth()
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080, "qsockstest", "password"));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080, "qsockstest", "password"));
// Connect to imap.trolltech.com's IP
- QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
+ QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
QVERIFY(socketDevice.waitForWrite());
- if (!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143)) {
+ if (!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143)) {
qDebug("%d, %s", socketDevice.error(), socketDevice.errorString().toLatin1().constData());
}
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
@@ -857,19 +863,19 @@ void tst_QSocks5SocketEngine::passwordAuth2()
QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
- socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081));
+ socketDevice.setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081));
socketDevice.setReceiver(this);
- QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143));
+ QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
while (socketDevice.state() == QAbstractSocket::ConnectingState) {
QVERIFY(socketDevice.waitForWrite());
- socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143);
+ socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143);
}
if (socketDevice.state() != QAbstractSocket::ConnectedState)
qDebug("%d, %s", socketDevice.error(), socketDevice.errorString().toLatin1().constData());
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
- QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::serverIP());
+ QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::imapServerIp());
// Wait for the greeting
QVERIFY(socketDevice.waitForRead());
diff --git a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
index 1a8e7920d3..5c66ef6520 100644
--- a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
+++ b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
@@ -29,14 +29,14 @@
#include <QtCore>
#include <QtNetwork>
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) && defined(Q_CC_MSVC)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && defined(Q_CC_MSVC)
# include <crtdbg.h>
#endif
int main(int argc, char *argv[])
{
// Windows: Suppress crash notification dialog.
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) && defined(Q_CC_MSVC)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && defined(Q_CC_MSVC)
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
#endif
QCoreApplication app(argc, argv);
diff --git a/tests/auto/network/socket/qtcpserver/test/test.pro b/tests/auto/network/socket/qtcpserver/test/test.pro
index 4491523383..7e2e60a1e3 100644
--- a/tests/auto/network/socket/qtcpserver/test/test.pro
+++ b/tests/auto/network/socket/qtcpserver/test/test.pro
@@ -1,7 +1,7 @@
CONFIG += testcase
SOURCES += ../tst_qtcpserver.cpp
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
TARGET = ../tst_qtcpserver
@@ -16,3 +16,9 @@ win32 {
QT = core network testlib
MOC_DIR=tmp
+
+# Only on Linux until cyrus has been added to docker-compose-for-{windows,macOS}.yml and tested
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = danted cyrus squid ftp-proxy
+}
diff --git a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
index 161d94d642..22ac9aa076 100644
--- a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
+++ b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
@@ -160,8 +160,15 @@ void tst_QTcpServer::initTestCase_data()
void tst_QTcpServer::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143));
+#else
if (!QtNetworkSettings::verifyTestNetworkSettings())
QSKIP("No network test server available");
+#endif
#ifndef QT_NO_BEARERMANAGEMENT
QNetworkConfigurationManager man;
networkSession = new QNetworkSession(man.defaultConfiguration(), this);
@@ -177,7 +184,7 @@ void tst_QTcpServer::init()
#ifndef QT_NO_NETWORKPROXY
QFETCH_GLOBAL(int, proxyType);
if (proxyType == QNetworkProxy::Socks5Proxy) {
- QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080));
}
#else // !QT_NO_NETWORKPROXY
QSKIP("No proxy support");
@@ -513,7 +520,7 @@ void tst_QTcpServer::waitForConnectionTest()
}
QTcpSocket findLocalIpSocket;
- findLocalIpSocket.connectToHost(QtNetworkSettings::serverName(), 143);
+ findLocalIpSocket.connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(findLocalIpSocket.waitForConnected(5000));
QTcpServer server;
@@ -668,16 +675,18 @@ void tst_QTcpServer::invalidProxy_data()
QTest::addColumn<int>("port");
QTest::addColumn<int>("expectedError");
- QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
- QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << fluke << 143
+ const QString imapIp = QtNetworkSettings::imapServerIp().toString();
+ const QString httpProxyIp = QtNetworkSettings::httpProxyServerIp().toString();
+ const QString socksIp = QtNetworkSettings::socksProxyServerIp().toString();
+ QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << imapIp << 143
<< int(QAbstractSocket::UnsupportedSocketOperationError);
- QTest::newRow("http-proxy") << int(QNetworkProxy::HttpProxy) << fluke << 3128
+ QTest::newRow("http-proxy") << int(QNetworkProxy::HttpProxy) << httpProxyIp << 3128
<< int(QAbstractSocket::UnsupportedSocketOperationError);
QTest::newRow("no-such-host") << int(QNetworkProxy::Socks5Proxy)
<< "invalid.test.qt-project.org" << 1080
<< int(QAbstractSocket::ProxyNotFoundError);
- QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << fluke << 3128
+ QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << httpProxyIp << 3128
<< int(QAbstractSocket::SocketTimeoutError);
}
@@ -740,48 +749,48 @@ void tst_QTcpServer::proxyFactory_data()
// tests that do get to listen
- proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
QTest::newRow("socks5")
<< proxyList << proxyList.at(0)
<< false << int(QAbstractSocket::UnknownSocketError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3128)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
QTest::newRow("cachinghttp+socks5")
<< proxyList << proxyList.at(1)
<< false << int(QAbstractSocket::UnknownSocketError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3128)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
QTest::newRow("ftp+cachinghttp+socks5")
<< proxyList << proxyList.at(2)
<< false << int(QAbstractSocket::UnknownSocketError);
// tests that fail to listen
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128);
QTest::newRow("http")
<< proxyList << proxyList.at(0)
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3128);
QTest::newRow("cachinghttp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
QTest::newRow("ftp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3128);
QTest::newRow("ftp+cachinghttp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
diff --git a/tests/auto/network/socket/qtcpsocket/test/test.pro b/tests/auto/network/socket/qtcpsocket/test/test.pro
index 337e75b372..4c07b1ec66 100644
--- a/tests/auto/network/socket/qtcpsocket/test/test.pro
+++ b/tests/auto/network/socket/qtcpsocket/test/test.pro
@@ -2,8 +2,8 @@ CONFIG += testcase
QT = core-private network-private testlib
SOURCES += ../tst_qtcpsocket.cpp
-win32:LIBS += -lws2_32
+win32: QMAKE_USE += ws2_32
TARGET = tst_qtcpsocket
win32 {
@@ -15,3 +15,9 @@ win32 {
} else {
DESTDIR = ../
}
+
+# Only on Linux until cyrus has been added to docker-compose-for-{windows,macOS}.yml and tested
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = danted squid apache2 ftp-proxy vsftpd iptables cyrus
+}
diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
index c473230246..c500c6b3c3 100644
--- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
+++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
@@ -66,7 +66,7 @@
#endif
#include <QTextStream>
#include <QThread>
-#include <QTime>
+#include <QElapsedTimer>
#include <QTimer>
#include <QDebug>
// RVCT compiles also unused inline methods
@@ -237,7 +237,6 @@ private:
qint64 bytesAvailable;
qint64 expectedLength;
bool readingBody;
- QTime timer;
QByteArray expectedReplyIMAP_cached;
@@ -317,7 +316,7 @@ tst_QTcpSocket::tst_QTcpSocket()
connect(earlyConstructedSockets->endPoints[1], SIGNAL(bytesWritten(qint64)), this, SLOT(earlySocketBytesSent(qint64)));
earlyConstructedSockets->endPoints[1]->write("hello work");
- firstFailInfo.setAddresses(QList<QHostAddress>() << QHostAddress("224.0.0.0") << QtNetworkSettings::serverIP());
+ firstFailInfo.setAddresses(QList<QHostAddress>() << QHostAddress("224.0.0.0") << QtNetworkSettings::httpServerIp());
}
void tst_QTcpSocket::initTestCase_data()
@@ -326,7 +325,6 @@ void tst_QTcpSocket::initTestCase_data()
QTest::addColumn<int>("proxyType");
QTest::addColumn<bool>("ssl");
- qDebug() << QtNetworkSettings::serverName();
QTest::newRow("WithoutProxy") << false << 0 << false;
//QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy) << false; ### temporarily disabled, QTBUG-38385
//QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic) << false; ### temporarily disabled, QTBUG-38385
@@ -352,7 +350,17 @@ void tst_QTcpSocket::initTestCase_data()
void tst_QTcpSocket::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143));
+ //QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::firewallServerName(), 1357));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpServerName(), 21));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif
}
void tst_QTcpSocket::init()
@@ -361,30 +369,33 @@ void tst_QTcpSocket::init()
if (setProxy) {
#ifndef QT_NO_NETWORKPROXY
QFETCH_GLOBAL(int, proxyType);
- QList<QHostAddress> addresses = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses();
- QVERIFY2(addresses.count() > 0, "failed to get ip address for test server");
- QString fluke = addresses.first().toString();
+ QList<QHostAddress> socks5Addresses = QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses();
+ QList<QHostAddress> httpProxyAddresses = QHostInfo::fromName(QtNetworkSettings::httpProxyServerName()).addresses();
+ QVERIFY2(socks5Addresses.count() > 0, "failed to get ip address for SOCKS5 proxy server");
+ QVERIFY2(httpProxyAddresses.count() > 0, "failed to get ip address for HTTP proxy server");
+ QString socks5Address = socks5Addresses.first().toString();
+ QString httpProxyAddress = httpProxyAddresses.first().toString();
QNetworkProxy proxy;
switch (proxyType) {
case Socks5Proxy:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socks5Address, 1080);
break;
case Socks5Proxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socks5Address, 1081);
break;
case HttpProxy | NoAuth:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddress, 3128);
break;
case HttpProxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddress, 3129);
break;
case HttpProxy | AuthNtlm:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddress, 3130);
break;
}
QNetworkProxy::setApplicationProxy(proxy);
@@ -644,8 +655,8 @@ void tst_QTcpSocket::bind()
void tst_QTcpSocket::bindThenResolveHost_data()
{
QTest::addColumn<QString>("hostName");
- QTest::newRow("ip-literal") << QtNetworkSettings::serverIP().toString();
- QTest::newRow("name") << QtNetworkSettings::serverName();
+ QTest::newRow("ip-literal") << QtNetworkSettings::httpServerIp().toString();
+ QTest::newRow("name") << QtNetworkSettings::httpServerName();
QTest::newRow("first-fail") << firstFailName;
}
@@ -715,7 +726,7 @@ void tst_QTcpSocket::setSocketDescriptor()
#ifdef Q_OS_WIN
// need the dummy to ensure winsock is started
QTcpSocket *dummy = newSocket();
- dummy->connectToHost(QtNetworkSettings::serverName(), 143);
+ dummy->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(dummy->waitForConnected());
SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -737,7 +748,7 @@ void tst_QTcpSocket::setSocketDescriptor()
QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
qt_qhostinfo_clear_cache(); //avoid the HostLookupState being skipped due to address being in cache from previous test.
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
QCOMPARE(socket->state(), QTcpSocket::HostLookupState);
QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
QVERIFY(socket->waitForConnected(10000));
@@ -758,7 +769,7 @@ void tst_QTcpSocket::socketDescriptor()
QTcpSocket *socket = newSocket();
QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->state() == QAbstractSocket::HostLookupState ||
socket->state() == QAbstractSocket::ConnectingState);
QVERIFY(socket->waitForConnected(10000));
@@ -775,7 +786,7 @@ void tst_QTcpSocket::blockingIMAP()
QTcpSocket *socket = newSocket();
// Connect
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(10000));
QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
QVERIFY(socket->isValid());
@@ -852,6 +863,14 @@ void tst_QTcpSocket::hostNotFound()
socket->connectToHost("nosuchserver.qt-project.org", 80);
QVERIFY(!socket->waitForConnected());
QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
+#ifdef QT_TEST_SERVER
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+ QEXPECT_FAIL("", "QTBUG-73953: The version of Squid in the docker container behaves "
+ "differently to the one in the network testing server, returning 503 "
+ "when we expect 404", Continue);
+ }
+#endif
QCOMPARE(int(socket->error()), int(QTcpSocket::HostNotFoundError));
delete socket;
@@ -861,8 +880,8 @@ void tst_QTcpSocket::hostNotFound()
void tst_QTcpSocket::timeoutConnect_data()
{
QTest::addColumn<QString>("address");
- QTest::newRow("host") << QtNetworkSettings::serverName();
- QTest::newRow("ip") << QtNetworkSettings::serverIP().toString();
+ QTest::newRow("host") << QtNetworkSettings::firewallServerName();
+ QTest::newRow("ip") << QtNetworkSettings::firewallServerIp().toString();
}
void tst_QTcpSocket::timeoutConnect()
@@ -910,7 +929,7 @@ void tst_QTcpSocket::nonBlockingIMAP()
nonBlockingIMAP_socket = socket;
// Connect
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->state() == QTcpSocket::HostLookupState ||
socket->state() == QTcpSocket::ConnectingState);
@@ -1036,7 +1055,7 @@ void tst_QTcpSocket::delayedClose()
connect(socket, SIGNAL(connected()), SLOT(nonBlockingIMAP_connected()));
connect(socket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
enterLoop(30);
if (timeout())
@@ -1082,7 +1101,7 @@ QByteArray tst_QTcpSocket::expectedReplyIMAP()
void tst_QTcpSocket::fetchExpectedReplyIMAP()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
QVERIFY2(socket->state() == QTcpSocket::ConnectedState, qPrintable(socket->errorString()));
@@ -1101,7 +1120,7 @@ void tst_QTcpSocket::fetchExpectedReplyIMAP()
void tst_QTcpSocket::partialRead()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(10000));
QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
char buf[512];
@@ -1125,7 +1144,7 @@ void tst_QTcpSocket::partialRead()
void tst_QTcpSocket::unget()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(10000));
QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
char buf[512];
@@ -1162,7 +1181,7 @@ void tst_QTcpSocket::readRegularFile_readyRead()
void tst_QTcpSocket::readAllAfterClose()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
connect(socket, SIGNAL(readyRead()), SLOT(readRegularFile_readyRead()));
enterLoop(10);
if (timeout())
@@ -1202,7 +1221,7 @@ void tst_QTcpSocket::openCloseOpenClose()
QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(10000));
socket->close();
}
@@ -1225,7 +1244,7 @@ void tst_QTcpSocket::connectDisconnectConnectDisconnect()
QCOMPARE(int(socket->peerPort()), 0);
QCOMPARE(socket->peerAddress(), QHostAddress());
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForReadyRead(10000));
QCOMPARE(QString::fromLatin1(socket->read(4)), QString("* OK"));
@@ -1429,7 +1448,7 @@ void tst_QTcpSocket::disconnectWhileLookingUp()
// just connect and disconnect, then make sure nothing weird happened
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 21);
+ socket->connectToHost(QtNetworkSettings::ftpServerName(), 21);
// check that connect is in progress
QVERIFY(socket->state() != QAbstractSocket::UnconnectedState);
@@ -1477,7 +1496,7 @@ void tst_QTcpSocket::downloadBigFile()
connect(tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot()));
connect(tmpSocket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
- tmpSocket->connectToHost(QtNetworkSettings::serverName(), 80);
+ tmpSocket->connectToHost(QtNetworkSettings::httpServerName(), 80);
enterLoop(30);
if (timeout()) {
@@ -1486,7 +1505,7 @@ void tst_QTcpSocket::downloadBigFile()
QFAIL("Network operation timed out");
}
- QByteArray hostName = QtNetworkSettings::serverName().toLatin1();
+ QByteArray hostName = QtNetworkSettings::httpServerName().toLatin1();
QCOMPARE(tmpSocket->state(), QAbstractSocket::ConnectedState);
QVERIFY(tmpSocket->write("GET /qtest/mediumfile HTTP/1.0\r\n") > 0);
QVERIFY(tmpSocket->write("HOST: ") > 0);
@@ -1498,7 +1517,7 @@ void tst_QTcpSocket::downloadBigFile()
expectedLength = 0;
readingBody = false;
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
enterLoop(600);
@@ -1552,7 +1571,7 @@ void tst_QTcpSocket::downloadBigFileSlot()
void tst_QTcpSocket::readLine()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(5000));
while (!socket->canReadLine())
@@ -1601,7 +1620,7 @@ void tst_QTcpSocket::readLine()
void tst_QTcpSocket::readLineString()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForReadyRead(10000));
QByteArray arr = socket->readLine();
@@ -1614,7 +1633,7 @@ void tst_QTcpSocket::readLineString()
void tst_QTcpSocket::readChunks()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(10000));
QVERIFY(socket->waitForReadyRead(5000));
@@ -1634,7 +1653,7 @@ void tst_QTcpSocket::readChunks()
void tst_QTcpSocket::waitForBytesWritten()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
QVERIFY(socket->waitForConnected(10000));
socket->write("GET / HTTP/1.0\r\n\r\n");
@@ -1652,7 +1671,7 @@ void tst_QTcpSocket::waitForBytesWrittenMinusOne()
QSKIP("QTBUG-24451 - indefinite wait may hang");
#endif
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
QVERIFY(socket->waitForConnected(10000));
socket->write("GET / HTTP/1.0\r\n\r\n");
@@ -1667,7 +1686,7 @@ void tst_QTcpSocket::waitForBytesWrittenMinusOne()
void tst_QTcpSocket::waitForReadyRead()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
socket->write("GET / HTTP/1.0\r\n\r\n");
QVERIFY(socket->waitForReadyRead(5000));
delete socket;
@@ -1680,7 +1699,7 @@ void tst_QTcpSocket::waitForReadyReadMinusOne()
QSKIP("QTBUG-24451 - indefinite wait may hang");
#endif
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
socket->write("GET / HTTP/1.0\r\n\r\n");
QVERIFY(socket->waitForReadyRead(-1));
delete socket;
@@ -1693,7 +1712,7 @@ void tst_QTcpSocket::flush()
socket->flush();
connect(socket, SIGNAL(connected()), SLOT(exitLoopSlot()));
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
enterLoop(60);
QVERIFY(socket->isOpen());
@@ -1710,7 +1729,7 @@ void tst_QTcpSocket::flush()
void tst_QTcpSocket::synchronousApi()
{
QTcpSocket *ftpSocket = newSocket();
- ftpSocket->connectToHost(QtNetworkSettings::serverName(), 21);
+ ftpSocket->connectToHost(QtNetworkSettings::ftpServerName(), 21);
ftpSocket->write("QUIT\r\n");
QVERIFY(ftpSocket->waitForDisconnected(10000));
QVERIFY(ftpSocket->bytesAvailable() > 0);
@@ -1757,10 +1776,10 @@ void tst_QTcpSocket::recursiveReadyRead()
QSignalSpy spy(testSocket, SIGNAL(readyRead()));
- testSocket->connectToHost(QtNetworkSettings::serverName(), 143);
+ testSocket->connectToHost(QtNetworkSettings::imapServerName(), 143);
enterLoop(30);
QVERIFY2(!timeout(),
- "Timed out when connecting to QtNetworkSettings::serverName().");
+ "Timed out when connecting to QtNetworkSettings::imapServerName().");
enterLoop(30);
QVERIFY2(!timeout(),
@@ -1794,7 +1813,7 @@ void tst_QTcpSocket::recursiveReadyReadSlot()
void tst_QTcpSocket::atEnd()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 21);
+ socket->connectToHost(QtNetworkSettings::ftpServerName(), 21);
QVERIFY(socket->waitForReadyRead(15000));
QTextStream stream(socket);
@@ -1802,9 +1821,15 @@ void tst_QTcpSocket::atEnd()
QString greeting = stream.readLine();
QVERIFY(stream.atEnd());
+#ifdef QT_TEST_SERVER
+ // Test server must use some vsFTPd 3.x.x version
+ QVERIFY2(greeting.length() == sizeof("220 (vsFTPd 3.x.x)")-1, qPrintable(greeting));
+ QVERIFY2(greeting.startsWith("220 (vsFTPd 3."), qPrintable(greeting));
+#else
// Test server must use some vsFTPd 2.x.x version
QVERIFY2(greeting.length() == sizeof("220 (vsFTPd 2.x.x)")-1, qPrintable(greeting));
QVERIFY2(greeting.startsWith("220 (vsFTPd 2."), qPrintable(greeting));
+#endif
QVERIFY2(greeting.endsWith(QLatin1Char(')')), qPrintable(greeting));
delete socket;
@@ -1835,7 +1860,7 @@ protected:
connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), Qt::DirectConnection);
- socket->connectToHost(QtNetworkSettings::serverName(), 21);
+ socket->connectToHost(QtNetworkSettings::ftpServerName(), 21);
socket->write("QUIT\r\n");
exec();
@@ -1909,7 +1934,7 @@ void tst_QTcpSocket::waitForReadyReadInASlot()
tmpSocket = socket;
connect(socket, SIGNAL(connected()), this, SLOT(waitForReadyReadInASlotSlot()));
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
socket->write("GET / HTTP/1.0\r\n\r\n");
enterLoop(30);
@@ -2073,7 +2098,7 @@ void tst_QTcpSocket::waitForConnectedInHostLookupSlot()
timer.start(15000);
connect(tmpSocket, SIGNAL(hostFound()), this, SLOT(hostLookupSlot()));
- tmpSocket->connectToHost(QtNetworkSettings::serverName(), 143);
+ tmpSocket->connectToHost(QtNetworkSettings::imapServerName(), 143);
// only execute the loop if not already connected
if (tmpSocket->state() != QAbstractSocket::ConnectedState)
@@ -2128,7 +2153,7 @@ public slots:
inline void doIt()
{
attemptedToConnect = true;
- sock->connectToHost(QtNetworkSettings::serverName(), 80);
+ sock->connectToHost(QtNetworkSettings::httpServerName(), 80);
#if defined(Q_OS_MAC)
pthread_yield_np();
@@ -2179,7 +2204,7 @@ void tst_QTcpSocket::readyReadSignalsAfterWaitForReadyRead()
QSignalSpy readyReadSpy(socket, SIGNAL(readyRead()));
// Connect
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
// Wait for the read
QVERIFY(socket->waitForReadyRead(10000));
@@ -2315,7 +2340,7 @@ void tst_QTcpSocket::localAddressEmptyOnBSD()
void tst_QTcpSocket::zeroAndMinusOneReturns()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 80);
socket->write("GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n");
QVERIFY(socket->waitForReadyRead(15000));
@@ -2376,7 +2401,7 @@ void tst_QTcpSocket::connectionRefused()
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
&QTestEventLoop::instance(), SLOT(exitLoop()));
- socket->connectToHost(QtNetworkSettings::serverName(), 144);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 144);
enterLoop(10);
disconnect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
@@ -2456,7 +2481,7 @@ void tst_QTcpSocket::suddenRemoteDisconnect()
QEventLoop loop;
connect(&serverProcess, SIGNAL(finished(int)), &loop, SLOT(quit()));
connect(&clientProcess, SIGNAL(finished(int)), &loop, SLOT(quit()));
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
QTimer::singleShot(20000, &loop, SLOT(quit()));
@@ -2496,7 +2521,7 @@ void tst_QTcpSocket::connectToMultiIP()
// rationale: this domain resolves to 3 A-records, 2 of them are
// invalid. QTcpSocket should never spend more than 30 seconds per IP, and
// 30s*2 = 60s.
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
socket->connectToHost("multi.dev.qt-project.org", 80);
QVERIFY(socket->waitForConnected(60500));
@@ -2523,7 +2548,7 @@ void tst_QTcpSocket::moveToThread0()
{
// Case 1: Moved after connecting, before waiting for connection.
QTcpSocket *socket = newSocket();;
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
socket->moveToThread(0);
QVERIFY(socket->waitForConnected(5000));
socket->write("XXX LOGOUT\r\n");
@@ -2535,7 +2560,7 @@ void tst_QTcpSocket::moveToThread0()
// Case 2: Moved before connecting
QTcpSocket *socket = newSocket();
socket->moveToThread(0);
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(5000));
socket->write("XXX LOGOUT\r\n");
QVERIFY(socket->waitForBytesWritten(5000));
@@ -2545,7 +2570,7 @@ void tst_QTcpSocket::moveToThread0()
{
// Case 3: Moved after writing, while waiting for bytes to be written.
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(5000));
socket->write("XXX LOGOUT\r\n");
socket->moveToThread(0);
@@ -2556,7 +2581,7 @@ void tst_QTcpSocket::moveToThread0()
{
// Case 4: Moved after writing, while waiting for response.
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
QVERIFY(socket->waitForConnected(5000));
socket->write("XXX LOGOUT\r\n");
QVERIFY(socket->waitForBytesWritten(5000));
@@ -2687,8 +2712,8 @@ void tst_QTcpSocket::taskQtBug5799ConnectionErrorWaitForConnected()
// use waitForConnected, e.g. this should use a synchronous select() on the OS level
QTcpSocket socket;
- socket.connectToHost(QtNetworkSettings::serverName(), 12346);
- QTime timer;
+ socket.connectToHost(QtNetworkSettings::httpServerName(), 12346);
+ QElapsedTimer timer;
timer.start();
socket.waitForConnected(10000);
QVERIFY2(timer.elapsed() < 9900, "Connection to closed port timed out instead of refusing, something is wrong");
@@ -2707,7 +2732,7 @@ void tst_QTcpSocket::taskQtBug5799ConnectionErrorEventLoop()
// This testcase uses an event loop
QTcpSocket socket;
connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), &QTestEventLoop::instance(), SLOT(exitLoop()));
- socket.connectToHost(QtNetworkSettings::serverName(), 12346);
+ socket.connectToHost(QtNetworkSettings::httpServerName(), 12346);
QTestEventLoop::instance().enterLoop(10);
QVERIFY2(!QTestEventLoop::instance().timeout(), "Connection to closed port timed out instead of refusing, something is wrong");
@@ -2720,7 +2745,7 @@ void tst_QTcpSocket::taskQtBug7054TimeoutErrorResetting()
{
QTcpSocket *socket = newSocket();
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY(socket->waitForConnected(5*1000));
QCOMPARE(socket->error(), QAbstractSocket::UnknownSocketError);
@@ -2749,10 +2774,12 @@ void tst_QTcpSocket::invalidProxy_data()
QTest::addColumn<bool>("failsAtConnect");
QTest::addColumn<int>("expectedError");
- QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
- QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << fluke << 21 << true
+ const QString ftpAddress = QtNetworkSettings::ftpServerIp().toString();
+ const QString httpProxyAddress = QtNetworkSettings::httpProxyServerIp().toString();
+ const QString socksProxyAddress = QtNetworkSettings::socksProxyServerIp().toString();
+ QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << ftpAddress << 21 << true
<< int(QAbstractSocket::UnsupportedSocketOperationError);
- QTest::newRow("http-caching-proxy") << int(QNetworkProxy::HttpCachingProxy) << fluke << 3128 << true
+ QTest::newRow("http-caching-proxy") << int(QNetworkProxy::HttpCachingProxy) << httpProxyAddress << 3128 << true
<< int(QAbstractSocket::UnsupportedSocketOperationError);
QTest::newRow("no-such-host-socks5") << int(QNetworkProxy::Socks5Proxy)
<< "this-host-will-never-exist.qt-project.org" << 1080 << false
@@ -2760,9 +2787,9 @@ void tst_QTcpSocket::invalidProxy_data()
QTest::newRow("no-such-host-http") << int(QNetworkProxy::HttpProxy)
<< "this-host-will-never-exist.qt-project.org" << 3128 << false
<< int(QAbstractSocket::ProxyNotFoundError);
- QTest::newRow("http-on-socks5") << int(QNetworkProxy::HttpProxy) << fluke << 1080 << false
+ QTest::newRow("http-on-socks5") << int(QNetworkProxy::HttpProxy) << socksProxyAddress << 1080 << false
<< int(QAbstractSocket::ProxyConnectionClosedError);
- QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << fluke << 3128 << false
+ QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << httpProxyAddress << 3128 << false
<< int(QAbstractSocket::SocketTimeoutError);
}
@@ -2781,7 +2808,7 @@ void tst_QTcpSocket::invalidProxy()
QTcpSocket *socket = newSocket();
socket->setProxy(proxy);
- socket->connectToHost(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(), 80);
+ socket->connectToHost(QtNetworkSettings::httpServerIp().toString(), 80);
if (failsAtConnect) {
QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
@@ -2833,48 +2860,48 @@ void tst_QTcpSocket::proxyFactory_data()
// tests that do connect
- proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("http")
<< proxyList << proxyList.at(0)
<< false << int(QAbstractSocket::UnknownSocketError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("socks5")
<< proxyList << proxyList.at(0)
<< false << int(QAbstractSocket::UnknownSocketError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("cachinghttp+socks5")
<< proxyList << proxyList.at(1)
<< false << int(QAbstractSocket::UnknownSocketError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("ftp+cachinghttp+socks5")
<< proxyList << proxyList.at(2)
<< false << int(QAbstractSocket::UnknownSocketError);
// tests that fail to connect
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("cachinghttp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
QTest::newRow("ftp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("ftp+cachinghttp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
@@ -2895,7 +2922,7 @@ void tst_QTcpSocket::proxyFactory()
QNetworkProxyFactory::setApplicationProxyFactory(factory);
QTcpSocket *socket = newSocket();
- QString host = QtNetworkSettings::serverName();
+ QString host = QtNetworkSettings::httpServerName();
socket->connectToHost(host, 80);
// Verify that the factory was called properly
diff --git a/tests/auto/network/socket/qudpsocket/test/test.pro b/tests/auto/network/socket/qudpsocket/test/test.pro
index e856776ddc..969e4d72cf 100644
--- a/tests/auto/network/socket/qudpsocket/test/test.pro
+++ b/tests/auto/network/socket/qudpsocket/test/test.pro
@@ -17,3 +17,9 @@ win32 {
}
TARGET = tst_qudpsocket
+
+# Only on Linux until 'echo' has been added to docker-compose-for-{windows,macOS}.yml and tested
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = danted echo
+}
diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
index 707c1acf48..0f419e9de4 100644
--- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
+++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
@@ -40,6 +40,7 @@
#include <qhostinfo.h>
#include <qtcpsocket.h>
#include <qmap.h>
+#include <qelapsedtimer.h>
#include <qnetworkdatagram.h>
#include <QNetworkProxy>
#include <QNetworkInterface>
@@ -235,6 +236,7 @@ void tst_QUdpSocket::initTestCase_data()
// hack: we only enable the Socks5 over UDP tests on the old
// test server, because they fail on the new one. See QTBUG-35490
bool newTestServer = true;
+#ifndef QT_TEST_SERVER
QTcpSocket socket;
socket.connectToHost(QtNetworkSettings::serverName(), 22);
if (socket.waitForConnected(10000)) {
@@ -244,6 +246,7 @@ void tst_QUdpSocket::initTestCase_data()
newTestServer = false;
socket.disconnectFromHost();
}
+#endif
QTest::addColumn<bool>("setProxy");
QTest::addColumn<int>("proxyType");
@@ -257,8 +260,13 @@ void tst_QUdpSocket::initTestCase_data()
void tst_QUdpSocket::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::echoServerName(), 7));
+#else
if (!QtNetworkSettings::verifyTestNetworkSettings())
QSKIP("No network test server available");
+#endif
allAddresses = QNetworkInterface::allAddresses();
m_skipUnsupportedIPv6Tests = shouldSkipIpv6TestsForBrokenSetsockopt();
@@ -300,7 +308,7 @@ void tst_QUdpSocket::init()
#if QT_CONFIG(socks5)
QFETCH_GLOBAL(int, proxyType);
if (proxyType == QNetworkProxy::Socks5Proxy) {
- QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080));
}
#else
QSKIP("No proxy support");
@@ -915,7 +923,7 @@ void tst_QUdpSocket::performance()
client.connectToHost(serverAddress, server.localPort());
QVERIFY(client.waitForConnected(10000));
- QTime stopWatch;
+ QElapsedTimer stopWatch;
stopWatch.start();
qint64 nbytes = 0;
@@ -981,7 +989,7 @@ void tst_QUdpSocket::writeDatagramToNonExistingPeer_data()
QTest::addColumn<bool>("bind");
QTest::addColumn<QHostAddress>("peerAddress");
QHostAddress localhost(QHostAddress::LocalHost);
- QList<QHostAddress> serverAddresses(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses());
+ QList<QHostAddress> serverAddresses(QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses());
if (serverAddresses.isEmpty())
return;
@@ -995,7 +1003,7 @@ void tst_QUdpSocket::writeDatagramToNonExistingPeer_data()
void tst_QUdpSocket::writeDatagramToNonExistingPeer()
{
- if (QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().isEmpty())
+ if (QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses().isEmpty())
QFAIL("Could not find test server address");
QFETCH(bool, bind);
QFETCH(QHostAddress, peerAddress);
@@ -1015,7 +1023,7 @@ void tst_QUdpSocket::writeToNonExistingPeer_data()
{
QTest::addColumn<QHostAddress>("peerAddress");
QHostAddress localhost(QHostAddress::LocalHost);
- QList<QHostAddress> serverAddresses(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses());
+ QList<QHostAddress> serverAddresses(QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses());
if (serverAddresses.isEmpty())
return;
@@ -1028,7 +1036,7 @@ void tst_QUdpSocket::writeToNonExistingPeer_data()
void tst_QUdpSocket::writeToNonExistingPeer()
{
QSKIP("Connected-mode UDP sockets and their behaviour are erratic");
- if (QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().isEmpty())
+ if (QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses().isEmpty())
QFAIL("Could not find test server address");
QFETCH(QHostAddress, peerAddress);
quint16 peerPort = 34534;
@@ -1551,7 +1559,7 @@ void tst_QUdpSocket::echo_data()
void tst_QUdpSocket::echo()
{
QFETCH(bool, connect);
- QHostInfo info = QHostInfo::fromName(QtNetworkSettings::serverName());
+ QHostInfo info = QHostInfo::fromName(QtNetworkSettings::echoServerName());
QVERIFY(info.addresses().count());
QHostAddress remote = info.addresses().first();
diff --git a/tests/auto/network/ssl/qocsp/certs/alice.crt b/tests/auto/network/ssl/qocsp/certs/alice.crt
new file mode 100644
index 0000000000..02df86a517
--- /dev/null
+++ b/tests/auto/network/ssl/qocsp/certs/alice.crt
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEGDCCAwCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBjjELMAkGA1UEBhMCTk8x
+DTALBgNVBAgMBE9zbG8xEjAQBgNVBAcMCU9zbG8gQ2l0eTETMBEGA1UECgwKVGhl
+IFF0IENBMTENMAsGA1UECwwEUVRDTjERMA8GA1UEAwwIY2ExcXQuaW8xJTAjBgkq
+hkiG9w0BCQEWFnRpbXVyLnBvY2hlcHRzb3ZAcXQuaW8wHhcNMTgxMTIyMTEwNjE4
+WhcNMjgxMTE5MTEwNjE4WjCBkjELMAkGA1UEBhMCTk8xDTALBgNVBAgMBE9zbG8x
+EjAQBgNVBAcMCU9zbG8gQ2l0eTEdMBsGA1UECgwUVGhlIEZhbW91cyBBbGljZSBM
+dGQxDTALBgNVBAsMBEdPQUExEjAQBgNVBAMMCWFsaWNlLm9yZzEeMBwGCSqGSIb3
+DQEJARYPYWxpY2VAYWxpY2Uub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAtuGDR9oIEkK57xlxq/xc3u7B1ni4pdoyhf9r+pkgmu591qp2kl3Xcq3W
+Ve5Z553orAUCAExPlKfFV+CYYAedSgsDYlKk8DN+f/n+hkG6Wl2qyFzHgl+mvPwa
+eDqdVMIcDHGhSljALi9AqsN4lbrUhSxiyuPhAwl82WB0EIucmBs1NxSSZgFPRBLG
+Uzy9WvtQFq1qtn795PVIUsNg68qZQ9BvRduOQAr3bg3anoYqytthWnzLWKri2QR4
+Z4Y0mvcbT/PZwhtcFZzDXG3Hvc7k3AroAbWoSghMEgok9TW9grKYkW2d5cpQTP+l
+ptkB6yZ06MY9/uCdYzhm8eu2RgVndwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCG
+SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E
+FgQUQz2PuE4VuqHtZYTvVLr4+0IuHTUwHwYDVR0jBBgwFoAUeBcnAkU7sTqm7i2Q
+vTxwgr0nQ0QwDQYJKoZIhvcNAQELBQADggEBABGGmo1vUAXKQm9kowvUtjDpEIIY
+TpT+KqiUBOgJg5fGn6a63vBn5GMA6eT948ywi9ZU2M9dIXJCM+bdqjXeOtt4bBPZ
+xz6DcBPW9CoTR4CV1muNa95WIXzAHatq3XYG041ddMf41WG7QIdQsojBYEG0IYlv
+PQx+B+m2cu7A04aI2tCS8aUh7Xc9wRilJ+h/FlYFFQzgyEKsd7CFgkyxG/sLyFNH
+skYYk/DLlmaWa+YScHYB5kAk8StoETeMI2LLs7rgJmchi8eAxjLroYDUhQclUjqz
+vlNM+4GvcF5RluyuEXFOZVdmQahkXcyu0Q3yxvsBbnDglmbb2YHPl/blB7w=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qocsp/certs/alice.key b/tests/auto/network/ssl/qocsp/certs/alice.key
new file mode 100644
index 0000000000..6f2666ebde
--- /dev/null
+++ b/tests/auto/network/ssl/qocsp/certs/alice.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC24YNH2ggSQrnv
+GXGr/Fze7sHWeLil2jKF/2v6mSCa7n3WqnaSXddyrdZV7lnnneisBQIATE+Up8VX
+4JhgB51KCwNiUqTwM35/+f6GQbpaXarIXMeCX6a8/Bp4Op1UwhwMcaFKWMAuL0Cq
+w3iVutSFLGLK4+EDCXzZYHQQi5yYGzU3FJJmAU9EEsZTPL1a+1AWrWq2fv3k9UhS
+w2DryplD0G9F245ACvduDdqehirK22FafMtYquLZBHhnhjSa9xtP89nCG1wVnMNc
+bce9zuTcCugBtahKCEwSCiT1Nb2CspiRbZ3lylBM/6Wm2QHrJnToxj3+4J1jOGbx
+67ZGBWd3AgMBAAECggEADbzU+sHDF3QRuYdExbGYXFq9DtpUrIi+gNhWCSYVj+3Y
+YBa//3CzLXcngZ78++wdvUZHBzS0SatspJRHffc0doprP6iLoUuM9hoWZ4lqcT1W
+BeUKS53ZzZp2do+Yn/RQ3RJwFkCidxWvmuRCG6VEL5jM9wa1MWA2E7IuJcwHAFny
+WIByosje5Qrd7eXDuVoqr1hjJ2UxIjIJ8Zgg3EE9wVUyJE3PU1HLz2AefonYRwbL
+XlzNgnj0c9Ti9ejfyon+jTnpslLKtPal2kxyGoKPAngadAhCzqSaCWggACm7R8Ge
+pZ0Y0pV7QReEgjfFd4D3qOqLRQZVJOMDb3vJu2/rsQKBgQDfKjfSpUweBM9li7GS
+xXbDpC3Y8zQ2VY+2SvgYoYiYU/Y6YenxhKM1XDbWZxhxS8GVfCUAESFDOTZcMvdi
+QEbG1uEmuCn1ksvrC2y54rtd8WDppcS0vJxCrU4nZG0v9IjVKp67B8EpBpAQeNb1
+tR6ByT2fLJu5+WU2S7OxqX7uLwKBgQDRyfKvrCQgdJOQlJlHOv1y1hN8WY51A8P/
+JbDXoun3PCPd+JczvFXCUh3ZLXqUEAX2qDOBD1pBM62EN6/A9ukO4mcMd8uYIet6
+nR4nVqXUjWuzXe6eo913lTDQrIOGWpViTc8fnvFlwBPfwzxbZNx38HZbw0L0nT7d
+8TE/JxLROQKBgQC4Kzo4b8vadjPGZLueGbICkQp5IXR0ZrYcRdBrW1vEAn6Q/d84
+PzMFxV1IIXrNfSx8NiC+5mQh+yQ+gJ0iC1OdoxXag1+1V3lMN3h6C4B/bcWB7Rjh
+40m9yRJXdgyZ59/Is8ydIzAosE7SGTelPNy5VR+yrfiySPxbC6x3MR8cZwKBgQCq
+PVTg1bIjXDZ7NvsDYI1XaP07BXmi30FnhXByLFPsOzNn51jbtNNq8zQhjtRP3ojY
+VjolWw4EpykBiCbpUfRiDbtN1NC0TaJHR8S2a4v6ZiCl123R8mu/pKOOUtAQcOWU
+dkvD/zkpNqtqA4axK7H06n9Bi7yDwC7J7/Xkp5KPkQKBgFDprXrXg4zvIsxbXYZ3
+2bCaxyhBXNKcGwtWbbLfJcOwHJPns/abGkYIJ0NbMZX1LwTDfQWmC+8YKKvIlbKG
+S2uk5H4qzupR4XN6YJ7SCHlGv2z0vxVjV7aWc1TME2iZQoBuO1urxPZwHd/euruo
+kluWh1KV5XnWjBSYjZpiXxWl
+-----END PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qocsp/certs/ca1.crt b/tests/auto/network/ssl/qocsp/certs/ca1.crt
new file mode 100644
index 0000000000..b5ae194fab
--- /dev/null
+++ b/tests/auto/network/ssl/qocsp/certs/ca1.crt
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID9DCCAtygAwIBAgIJAMQbE3657KDYMA0GCSqGSIb3DQEBCwUAMIGOMQswCQYD
+VQQGEwJOTzENMAsGA1UECAwET3NsbzESMBAGA1UEBwwJT3NsbyBDaXR5MRMwEQYD
+VQQKDApUaGUgUXQgQ0ExMQ0wCwYDVQQLDARRVENOMREwDwYDVQQDDAhjYTFxdC5p
+bzElMCMGCSqGSIb3DQEJARYWdGltdXIucG9jaGVwdHNvdkBxdC5pbzAeFw0xODEx
+MjIxMDIxMTNaFw0yODExMTkxMDIxMTNaMIGOMQswCQYDVQQGEwJOTzENMAsGA1UE
+CAwET3NsbzESMBAGA1UEBwwJT3NsbyBDaXR5MRMwEQYDVQQKDApUaGUgUXQgQ0Ex
+MQ0wCwYDVQQLDARRVENOMREwDwYDVQQDDAhjYTFxdC5pbzElMCMGCSqGSIb3DQEJ
+ARYWdGltdXIucG9jaGVwdHNvdkBxdC5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAOCs3AV7sDKHJUJcm7a0OqnShIvoB1qv6UcOmlBmUzGl5GzX90Jz
+7jYJoOPjxjNyRxMOsOReB1ZcSuIAjkdAEfFMaVe6j7qKTJ5ycTVY/fVoxyxsSNuI
+xOJ6RCEjLHcxONEbkN/xI8LMdVko3m4P10r5GxwrgyPvpa87Yq5+XJ1BPWJyKbD7
+Tqpn3dvZUj0/POsMUTT7Q7VXOfDlZj58XWAC6ECTqJauhGFMhiwgqOn2Qo1W0QjV
+DkGqRTdgIAM6Rv2cSRxgnflwW5QZ8kWUV81h/yx4cck/D9TcVxjr3Pvy6aJ/U41u
+d4XJQgwCj4LJi4msw1S0CvZWmz+2BKxcbRsCAwEAAaNTMFEwHQYDVR0OBBYEFHgX
+JwJFO7E6pu4tkL08cIK9J0NEMB8GA1UdIwQYMBaAFHgXJwJFO7E6pu4tkL08cIK9
+J0NEMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADp1kqDRcyVG
+BdMge+Il10IjbpzzSjAoZiqiw69V99LiHW9ePbxG4AmliE6Za60GE5PCXOLjJh/5
+efgnIbybbyIOIT9iK4TXWLw2XW+rMY51c0RAxp2h/sc+5CZ0F0I811F5VUHXg2qR
+U7C2zbzqAimN8TBm6FRe7NFQfqLCrsuFJjSc3obrqKQcpvRwxMk6NpkdoemzqLmY
+lrBrTaeVbZ4ix3srVPvXRm9TdiC+JuuFmvulMfe+/wwnhb+dwT3JUC+EIq/Uf5Wb
+g8lvB4ntitL8NLQ2hFGqYuoFNIGs6tRN71ohk+/ONqe9wJhcI9QAruPOvsg+8J0H
+uGooX7PUNHg=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qocsp/certs/ca1.key b/tests/auto/network/ssl/qocsp/certs/ca1.key
new file mode 100644
index 0000000000..4ee080f706
--- /dev/null
+++ b/tests/auto/network/ssl/qocsp/certs/ca1.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgrNwFe7AyhyVC
+XJu2tDqp0oSL6Adar+lHDppQZlMxpeRs1/dCc+42CaDj48YzckcTDrDkXgdWXEri
+AI5HQBHxTGlXuo+6ikyecnE1WP31aMcsbEjbiMTiekQhIyx3MTjRG5Df8SPCzHVZ
+KN5uD9dK+RscK4Mj76WvO2KuflydQT1icimw+06qZ93b2VI9PzzrDFE0+0O1Vznw
+5WY+fF1gAuhAk6iWroRhTIYsIKjp9kKNVtEI1Q5BqkU3YCADOkb9nEkcYJ35cFuU
+GfJFlFfNYf8seHHJPw/U3FcY69z78umif1ONbneFyUIMAo+CyYuJrMNUtAr2Vps/
+tgSsXG0bAgMBAAECggEBAL1RCwjXw42gEUZM8KzQS0pD6IpXVrMU3ZWReXhb8Kg6
+KDOK+3+UXlpMXLUKfj1lgvxM+cNEdBxSIoszerARDc1s3KseufOui4dL2ZbhSQVc
+Z9BH4lCSe4x3CCeAEvzQjhatirMY51BCpnMdm+fUE07KfwyKobNLQSpZ+Pod4f5i
+oQbOiZYfRfU2quaWIsVb/a5IiUD0gG0KS9O5wX6VigVeFRpOPHT4YCQ1qds4HqQq
+PKQtkLq0mo6beXCfXWrJ5Nc0QOIFlgSAHkeRR7zLK8MlaerwZ5YdeJIWuPM9l9H+
+34FVkHle1rPN6dJf7EPwWxn1PceFe3QYn1GHoiMmXfkCgYEA/U6iQypbLEKLmLbt
+XTvhV1FVDQM42BX+ATNQ8Wro0ybdyzM+d4271uAUGTF1Zvxndv22p+JOmldWveAR
+0iVK4mvrs25ACg27Bz3LiUaQB2OyYrj9M7TLgQ47gYEhwgnsSniFyrMcptNyIfW5
+GoB1N00EKiCvHyWo5LK6kRZt5QcCgYEA4xBOC/Otc9lTp24iSVA8Y7XJ+nlypFtc
+pehf262jH11wEkWskmc9aP/kpxt9fUrDxf3YIOqITR4mMNn184P1WywHAQF7Adfd
+3r5YBMVaanuaMsSuAZOJGyvuk2BE6328IKdE+3emndzXuQdDf0X2TUznwdKe9AzZ
+qadCBLfUpk0CgYAgDKbzIJTQkMrg06RMu5rTVXMRZmr2zDGLLVb8dK5oqO4/G4i3
+z7MIiOmCFoPoN99PauKFc1jGpm5PL96RXC6RX14/IZ/wpbQYQnVSNR9cD/0uCIHg
+3OsytP5KcHA5ANBoy78B2o+xe+dg7JozBDXQfWodem0t37Hy3bpFSTU2WQKBgETY
+qcFn9hydNYcblpvCDz1wXjhq4H7DENlhFseF42LcMuHnbEbLtMwEYrDkXe1CYQ/E
+QubgFcnELXI8dB2M0jT9qXX9m+1YJXanIgr4R8zngz6HcfcaY8TwUhsvYlZAvmzs
+KrdQdR2CW4pHkIijjuWrPs3+7aEz0D9nblX94yU1AoGATVCfQOwmEMFHg33luMMt
+0lTOHsar6g1O5vz0ZPZ1NjJF9Qe3+T7B4n4gq9pLwfi7Ohoa4CDmt0nKmy56dBha
+5LM8mzw+PaH9a3pP93caS6k/X68TLOp7fwvnzP6HTjtis2sdYzVma6ghEF0zRdQr
+6nWMI6Kx2kFaNdzKSHzxP5A=
+-----END PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qocsp/certs/infbob.key b/tests/auto/network/ssl/qocsp/certs/infbob.key
new file mode 100644
index 0000000000..7878339151
--- /dev/null
+++ b/tests/auto/network/ssl/qocsp/certs/infbob.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDkF2BuPlkQa3Ox
+JxnbQ+gy1mAxaGGzfnmGocraxVSKSssX3zSkeIrWB1kW3diOtIZ1jovYftHGsqoB
+F5k6fN9dr37mFIZnilF6Bq0seYjNUl6I0d7Cf3NJSf7TG5+P+dAyNLN8aXILctY8
+krlSe4ysb++9xgawt2DYL3I0LBd+W27hd2BlfcmB4g2X3zOasjZM8F5HSBxF5e7f
+fVaUmCC8S4jdXUQEbUNFk6HufDwDhP1gMtoGKHusWOdI5O6cQAfUUmRLSfi/jWoe
+KLPafbj7KIcA8+YojOvub2guNpO42h9fc83/gCkkBJhwXNdIQjRUnz6Lu05kDTG9
+X28gbX9TAgMBAAECggEBAN9xCxVUXJmaOb6ciFblIi3TFm6wS62zw0chbgB8eQH0
+nRoonYBVWeSrVBnzf7bkoCe/Wb3fFo+o7KOfQ4spUwOK7SxlhPkfZgu9SJ4d/Obu
+vw8XUTqF8iEkrM6P6/L2DX9xYzcIcSFIARlbvtJPmBJAocHtoRYyvltpt13mp6kt
+/LVYR4qFAWRpPR6rnjlXEjfrE9taHWgIJEjwMj+IcTjnGiS1rX1T/JNhjRxsRJwU
+qxqhYmeenNymyUJxS2B806EcG3UAJu63dK61VXN1dtPhS3FqjeR//GRlmy14n7RW
+ZQAuT9dPB/WzUZVzEcOgTwe/+XsPTSfz7gpaoffgMJECgYEA/43xZRi48Dfp3tdq
+qwwLf6Ya9pB2zb3XE8MUQhxsrygzL5ngZhmr2m0LgGCf5fXa983G6wzA6sOdpvve
+jFAlBZYbWaYnvog9QIFcTj0S6PahGTBaR7PSNzK0UzoHYexYVCkyzQl1O2hktazd
+Cankh/6IlAFkKbUSDqAwc07jNCkCgYEA5H0tNXpcDN6JTgKNe8YHM0GjZB+qGEoL
+7YZbFlANjO9pOPY6JMQ3+DbOoruIH97CIyVYokuH0qRAfjm5LNiVYECFVFZRnGFb
+BNPOPAnPJPISDF66zjW0KLMYCykJAHQ4SpHUPcJ6JnfBr76s/xSbNI9qnhpy3QYI
+ATkqOrP25xsCgYEAy3pjmJGEv5BloM942VSv2yWRFn2UeuELXWrYuIMVbqndh6tH
+50PNeA+XNtK4vktx3Bl2pzTybnrvDkRBwQsXT0lj4Y/Q2X509uWJb6plYiTtxLah
+S7I8UUMIHbR4qFmdQvXCw0sikvjeJ2HKZaVml3ntmZs5+5N3GzolGcrYUXECgYEA
+pPsBnsCoIJ66s7pCIKIfZtI5QT1f20P0EuDVemn5Ls9bwcaAuzV3WGFymKwiISj+
+MtRviFhTTTROYRYa8Be+3A4ad4gQS4M8bmLlYhKPIJUtlQL9jZHXcR/H9578ofhJ
+AQcFIkb/XjFQiC58yX4+hxgbGufsEk2dkAyPwm1ZlQsCgYBTjnraJbYSz1v3MQKx
+fHm9eHki/ODR3lWiCYYnnW3AwRa7AXS4ZiSw78wzkUX2XTJbE6JlEUH4M9DMzr4y
+QBwKmx+3u+Im4WcZ889jo6XrF0X9mXRmY25+gr2ypTbKZjT8FCYcXIgiOxITLXZh
+Bmn7KZcsdaPxSFn05ASEanLNqA==
+-----END PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qocsp/certs/infbobchain.crt b/tests/auto/network/ssl/qocsp/certs/infbobchain.crt
new file mode 100644
index 0000000000..7ed13c2856
--- /dev/null
+++ b/tests/auto/network/ssl/qocsp/certs/infbobchain.crt
@@ -0,0 +1,49 @@
+-----BEGIN CERTIFICATE-----
+MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQsFADCBjjELMAkGA1UEBhMCTk8x
+DTALBgNVBAgMBE9zbG8xEjAQBgNVBAcMCU9zbG8gQ2l0eTETMBEGA1UECgwKVGhl
+IFF0IENBMTENMAsGA1UECwwEUVRDTjERMA8GA1UEAwwIY2ExcXQuaW8xJTAjBgkq
+hkiG9w0BCQEWFnRpbXVyLnBvY2hlcHRzb3ZAcXQuaW8wHhcNMTgxMTIyMTAyOTM3
+WhcNMjgxMTE5MTAyOTM3WjCBmDELMAkGA1UEBhMCTk8xDTALBgNVBAgMBE9zbG8x
+EjAQBgNVBAcMCU9zbG8gQ2l0eTEkMCIGA1UECgwbVGhlIEluZmFtb3VzIFNuZWFr
+eSBCb2IgTHRkMQwwCgYDVQQLDANCREExEzARBgNVBAMMCmluZmJvYi5jb20xHTAb
+BgkqhkiG9w0BCQEWDmJvYkBpbmZib2IuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA5Bdgbj5ZEGtzsScZ20PoMtZgMWhhs355hqHK2sVUikrLF980
+pHiK1gdZFt3YjrSGdY6L2H7RxrKqAReZOnzfXa9+5hSGZ4pRegatLHmIzVJeiNHe
+wn9zSUn+0xufj/nQMjSzfGlyC3LWPJK5UnuMrG/vvcYGsLdg2C9yNCwXfltu4Xdg
+ZX3JgeINl98zmrI2TPBeR0gcReXu331WlJggvEuI3V1EBG1DRZOh7nw8A4T9YDLa
+Bih7rFjnSOTunEAH1FJkS0n4v41qHiiz2n24+yiHAPPmKIzr7m9oLjaTuNofX3PN
+/4ApJASYcFzXSEI0VJ8+i7tOZA0xvV9vIG1/UwIDAQABo3sweTAJBgNVHRMEAjAA
+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAd
+BgNVHQ4EFgQUloqk6Iihkkcxp85jAzeUPGVmapkwHwYDVR0jBBgwFoAUeBcnAkU7
+sTqm7i2QvTxwgr0nQ0QwDQYJKoZIhvcNAQELBQADggEBAGCdYFNskTzMilRtmw+v
+oJQM3mc6LdYYuADCuh8O/GKaqUnE7V2XnMBYWMN93eeN9VXmK2yAZaQU1J6ruP1S
+pLMzJ8hbQej+sm+XAHVxAtr34KmEC50gIn1cB/sRKxHMombbNl7EK44puFU7q58P
+zBz5lTXXTfA954D/ijEMMSDvIZ25me6vrGPMj1LX/wC6CWadSr9IxAO9HQVQQqwv
+AbbqrCvMSMv633/f1EYU8Q6jhUCTlnin4pXtriOnqi+6MZICaYRCUgV224Rs3OUS
+jmrbOeoaZUpmOVmuoYXWeexe229G2KGiEIgnSBEk5OLFHCeZ8++WJ5/SLHt8MBLc
+O0w=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIID9DCCAtygAwIBAgIJAMQbE3657KDYMA0GCSqGSIb3DQEBCwUAMIGOMQswCQYD
+VQQGEwJOTzENMAsGA1UECAwET3NsbzESMBAGA1UEBwwJT3NsbyBDaXR5MRMwEQYD
+VQQKDApUaGUgUXQgQ0ExMQ0wCwYDVQQLDARRVENOMREwDwYDVQQDDAhjYTFxdC5p
+bzElMCMGCSqGSIb3DQEJARYWdGltdXIucG9jaGVwdHNvdkBxdC5pbzAeFw0xODEx
+MjIxMDIxMTNaFw0yODExMTkxMDIxMTNaMIGOMQswCQYDVQQGEwJOTzENMAsGA1UE
+CAwET3NsbzESMBAGA1UEBwwJT3NsbyBDaXR5MRMwEQYDVQQKDApUaGUgUXQgQ0Ex
+MQ0wCwYDVQQLDARRVENOMREwDwYDVQQDDAhjYTFxdC5pbzElMCMGCSqGSIb3DQEJ
+ARYWdGltdXIucG9jaGVwdHNvdkBxdC5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAOCs3AV7sDKHJUJcm7a0OqnShIvoB1qv6UcOmlBmUzGl5GzX90Jz
+7jYJoOPjxjNyRxMOsOReB1ZcSuIAjkdAEfFMaVe6j7qKTJ5ycTVY/fVoxyxsSNuI
+xOJ6RCEjLHcxONEbkN/xI8LMdVko3m4P10r5GxwrgyPvpa87Yq5+XJ1BPWJyKbD7
+Tqpn3dvZUj0/POsMUTT7Q7VXOfDlZj58XWAC6ECTqJauhGFMhiwgqOn2Qo1W0QjV
+DkGqRTdgIAM6Rv2cSRxgnflwW5QZ8kWUV81h/yx4cck/D9TcVxjr3Pvy6aJ/U41u
+d4XJQgwCj4LJi4msw1S0CvZWmz+2BKxcbRsCAwEAAaNTMFEwHQYDVR0OBBYEFHgX
+JwJFO7E6pu4tkL08cIK9J0NEMB8GA1UdIwQYMBaAFHgXJwJFO7E6pu4tkL08cIK9
+J0NEMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADp1kqDRcyVG
+BdMge+Il10IjbpzzSjAoZiqiw69V99LiHW9ePbxG4AmliE6Za60GE5PCXOLjJh/5
+efgnIbybbyIOIT9iK4TXWLw2XW+rMY51c0RAxp2h/sc+5CZ0F0I811F5VUHXg2qR
+U7C2zbzqAimN8TBm6FRe7NFQfqLCrsuFJjSc3obrqKQcpvRwxMk6NpkdoemzqLmY
+lrBrTaeVbZ4ix3srVPvXRm9TdiC+JuuFmvulMfe+/wwnhb+dwT3JUC+EIq/Uf5Wb
+g8lvB4ntitL8NLQ2hFGqYuoFNIGs6tRN71ohk+/ONqe9wJhcI9QAruPOvsg+8J0H
+uGooX7PUNHg=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qocsp/certs/ss1-private.key b/tests/auto/network/ssl/qocsp/certs/ss1-private.key
new file mode 100644
index 0000000000..1c42daaf9f
--- /dev/null
+++ b/tests/auto/network/ssl/qocsp/certs/ss1-private.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC4bXcfIjweShLx
+6jBTKu/i5sXmlwTH9Z4PTzQ1VteKyEIDlnW5ocVWqRgBrvz3NlTFkDKkQXshkXyE
+JyVZFbAPCfGsroZVISpFhUmJbPMBNn3SyGEU+sxWIpOZOKmG5tel6B4Bt5TWsRHL
+mtU8Pv/APsz+i9JhgE25ksGhx16MqvdRv/xNGleF8qe+hDOeiNF3/lNv2hYb/MvD
+1F73FBoDVnqty/VXXOJFb7elLE4ArXsTN/hip42Lbl1guYvnqnTZFhCHwMzRu4qc
+3FTlemumfJpacpRnqVw2TURA5SdpTp9NYIxygEGNY201meNEjAEyg8GeFkAgu99R
+LPQT+rTNAgMBAAECggEAPQEIfCXo2OQLrDWY0onLW7SWFZYyoKngJJRAYrxdA60G
+GQW13zdhfS7ln/jv+B3ioI74EVkPj6T+GQCR3AvOdssFQ+dey93yi5hxIKIHJ4mM
+ySI66qOi34MEa5RQjyzgfCJxeoPtGa7sgfqvOgRkuISNbk11w4abLx0aK5c08TY0
+JdeoWWhATaFZXl782Aw2FwGPTwOIf7GB09BJS3qUqlMT9fowLmWO10jOKkNtvcnT
+2mAqT5cdZG1ffT5+f0JETPCbBPhhyE7VyYEVQfqTkRnEoz3hcZvjx91jD527+CSL
+Qhg7zZu2oakyJQvpHETZ6cgrs7uDEiol7ARANezwyQKBgQDmapxV/qIOd5WFDVXw
+lGt+dsELBBdMhvzr4A9eZdIZiXu48rdFG0XoECo5BKpXa1+ISr2od0U0YODrJrws
+OHxHhlxGjJFs8kFteUPHyEZv6/rvkbA+xc0Uw04NnDRHBLK8VvX7MBWfvTqLN4bK
+sZsMblscRBtEpFpN1fiJgnNASwKBgQDM56lBugtueBV9M4C/JF2is96d14ue3Y4i
+SgMnHY18D3ru+KDuxPYoIs5Yos2vDWK2k8754WZ+WNXokjRoYPiFbeBPpI9NudJs
+BUJz/sLJHjs3a4HrQs3hCuufczNxq9wQnALQHCMEqeBUTYCu/1+zYgwAu3Z/R8rJ
+jKgexl+gRwKBgGrLCNCWpze7VzKGvsk1kSjZE5nueHoAqqMMgzMGUD2DyjMrU6QV
+Au6O53Lr5aOE4Y9CzOqS9SFUsYprtpVsTLW94XDVX+W11ntN1At5mKPxJKn6xUwi
+022HI9sNBfHQjKLcTz/vxmX2B3dU8gVqEenOEC5mppjG8A/ZV0ssigxHAoGAfGsG
+OSSwoElGMxm8yVNZj9vMBufEnZhGH8f1FiE5seTsboKFpbXvCfvoc6WXYv2rvNUP
+TmdxBrMGYAu2ytJm1Q4cr/9qDHYSsQiYizpcKCa1KjebUbDktgsde1pGGHWUUHmK
+s7cCBGjqEAZnZtslzxRv2Vn639pF5hAEXXtywS0CgYAUIjhp43qgtbQdZMX7xbVR
+lT26aq7NguCtt7njpgkhqc0HThb3I8ImrhNSDcS0/T9dPU70vt0ceruyRXmwX5hA
+l28i5GzF5ufaRQdcsSR9u+P67nD5sTZBesbejXFySis5EC/97A4XZvkSfY4DQSZ+
+u8JJPZUlb2kGAHRpmxvpDA==
+-----END PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qocsp/certs/ss1.crt b/tests/auto/network/ssl/qocsp/certs/ss1.crt
new file mode 100644
index 0000000000..43ca8316c2
--- /dev/null
+++ b/tests/auto/network/ssl/qocsp/certs/ss1.crt
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEKzCCAxOgAwIBAgIJAOO/b5uLSmT8MA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD
+VQQGEwJOTzENMAsGA1UECAwET3NsbzENMAsGA1UEBwwET3NsbzESMBAGA1UECgwJ
+VGhlIFF0IENBMScwJQYDVQQLDB5SJkQgKGZha2UgY2VydGlmaWNhdGVzIGlzc3Vl
+cikxGTAXBgNVBAMMEFRpbXVyIFBvY2hlcHRzb3YxJTAjBgkqhkiG9w0BCQEWFnRp
+bXVyLnBvY2hlcHRzb3ZAcXQuaW8wIBcNMTgxMTE3MDUxNDA1WhgPMjExODEwMjQw
+NTE0MDVaMIGqMQswCQYDVQQGEwJOTzENMAsGA1UECAwET3NsbzENMAsGA1UEBwwE
+T3NsbzESMBAGA1UECgwJVGhlIFF0IENBMScwJQYDVQQLDB5SJkQgKGZha2UgY2Vy
+dGlmaWNhdGVzIGlzc3VlcikxGTAXBgNVBAMMEFRpbXVyIFBvY2hlcHRzb3YxJTAj
+BgkqhkiG9w0BCQEWFnRpbXVyLnBvY2hlcHRzb3ZAcXQuaW8wggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC4bXcfIjweShLx6jBTKu/i5sXmlwTH9Z4PTzQ1
+VteKyEIDlnW5ocVWqRgBrvz3NlTFkDKkQXshkXyEJyVZFbAPCfGsroZVISpFhUmJ
+bPMBNn3SyGEU+sxWIpOZOKmG5tel6B4Bt5TWsRHLmtU8Pv/APsz+i9JhgE25ksGh
+x16MqvdRv/xNGleF8qe+hDOeiNF3/lNv2hYb/MvD1F73FBoDVnqty/VXXOJFb7el
+LE4ArXsTN/hip42Lbl1guYvnqnTZFhCHwMzRu4qc3FTlemumfJpacpRnqVw2TURA
+5SdpTp9NYIxygEGNY201meNEjAEyg8GeFkAgu99RLPQT+rTNAgMBAAGjUDBOMB0G
+A1UdDgQWBBSyHPlJr6BrpwMY7Sxg2R3CpQR7UzAfBgNVHSMEGDAWgBSyHPlJr6Br
+pwMY7Sxg2R3CpQR7UzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBD
+o86xp1WwvX6mYzF94ifZlkq1aDN6/njj2B9fvJCtygfqq6b9BrQJ0hNeqRh8OaIh
+v2YmjbdUaoYguHmUxL+SeS67Sp8QBoSwdU5x0i8ygrigBrbb3myNqN6hGvpGy9E0
+B8PnVDt9DaOCunaMyGNPMLNPVGYULmberGtxV9wilcH4Q6WZrk9IhuyfqeBZtBYM
+IcjV3OKdUv/ggu2IZSN7njKcgr+uyPt0Ymo9GozJSTdnN/E4hsRgzcgzCMf2fxzj
+nGcsDRQ4L1R8p1zDlduxmmk42zGCGz3duFX7dijAxJWirS8Zsea4aooLgDQYT/zI
+8hKd3KC3knLhPcxFKiUg
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qocsp/qocsp.pro b/tests/auto/network/ssl/qocsp/qocsp.pro
new file mode 100644
index 0000000000..f4e846f39b
--- /dev/null
+++ b/tests/auto/network/ssl/qocsp/qocsp.pro
@@ -0,0 +1,15 @@
+CONFIG += testcase
+
+SOURCES += tst_qocsp.cpp
+QT = core network network-private testlib
+
+TARGET = tst_qocsp
+
+win32 {
+ CONFIG(debug, debug|release) {
+ DESTDIR = debug
+ } else {
+ DESTDIR = release
+ }
+}
+
diff --git a/tests/auto/network/ssl/qocsp/tst_qocsp.cpp b/tests/auto/network/ssl/qocsp/tst_qocsp.cpp
new file mode 100644
index 0000000000..9716c04bbb
--- /dev/null
+++ b/tests/auto/network/ssl/qocsp/tst_qocsp.cpp
@@ -0,0 +1,823 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2018 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the test suite of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and The Qt Company. For licensing terms
+ ** and conditions see https://www.qt.io/terms-conditions. For further
+ ** information use the contact form at https://www.qt.io/contact-us.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3 as published by the Free Software
+ ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+ ** included in the packaging of this file. Please review the following
+ ** information to ensure the GNU General Public License requirements will
+ ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <QtNetwork/private/qtnetworkglobal_p.h>
+
+#include <QtNetwork/private/qsslsocket_openssl_symbols_p.h>
+#include <QtNetwork/private/qsslsocket_openssl_p.h>
+
+#include <QtNetwork/qsslcertificate.h>
+#include <QtNetwork/qtcpserver.h>
+#include <QtNetwork/qsslerror.h>
+#include <QtNetwork/qsslkey.h>
+#include <QtNetwork/qssl.h>
+
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qdir.h>
+
+#include <openssl/ocsp.h>
+
+#include <algorithm>
+#include <utility>
+
+// NOTE: the word 'subject' in the code below means the subject of a status request,
+// so in general it's our peer's certificate we are asking about.
+
+using SslError = QT_PREPEND_NAMESPACE(QSslError);
+using VectorOfErrors = QT_PREPEND_NAMESPACE(QVector<SslError>);
+using Latin1String = QT_PREPEND_NAMESPACE(QLatin1String);
+
+Q_DECLARE_METATYPE(SslError)
+Q_DECLARE_METATYPE(VectorOfErrors)
+Q_DECLARE_METATYPE(Latin1String)
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+
+using OcspResponse = QSharedPointer<OCSP_RESPONSE>;
+using BasicResponse = QSharedPointer<OCSP_BASICRESP>;
+using SingleResponse = QSharedPointer<OCSP_SINGLERESP>;
+using CertId = QSharedPointer<OCSP_CERTID>;
+using EvpKey = QSharedPointer<EVP_PKEY>;
+using Asn1Time = QSharedPointer<ASN1_TIME>;
+using CertificateChain = QList<QSslCertificate>;
+
+using NativeX509Ptr = X509 *;
+
+class X509Stack {
+public:
+ explicit X509Stack(const QList<QSslCertificate> &chain);
+
+ ~X509Stack();
+
+ int size() const;
+ X509 *operator[](int index) const;
+ operator STACK_OF(X509) *() const;
+
+private:
+ OPENSSL_STACK *stack = nullptr;
+
+ Q_DISABLE_COPY(X509Stack)
+};
+
+X509Stack::X509Stack(const QList<QSslCertificate> &chain)
+{
+ if (!chain.size())
+ return;
+
+ stack = q_OPENSSL_sk_new_null();
+ if (!stack)
+ return;
+
+ for (const QSslCertificate &cert : chain) {
+ X509 *nativeCert = NativeX509Ptr(cert.handle());
+ if (!nativeCert)
+ continue;
+ q_OPENSSL_sk_push(stack, nativeCert);
+ q_X509_up_ref(nativeCert);
+ }
+}
+
+X509Stack::~X509Stack()
+{
+ if (stack)
+ q_OPENSSL_sk_pop_free(stack, reinterpret_cast<void(*)(void*)>(q_X509_free));
+}
+
+int X509Stack::size() const
+{
+ if (stack)
+ return q_OPENSSL_sk_num(stack);
+ return 0;
+}
+
+X509 *X509Stack::operator[](int index) const
+{
+ return NativeX509Ptr(q_OPENSSL_sk_value(stack, index));
+}
+
+X509Stack::operator STACK_OF(X509) *() const
+{
+ return reinterpret_cast<STACK_OF(X509)*>(stack);
+}
+
+struct OcspTimeStamp
+{
+ OcspTimeStamp() = default;
+ OcspTimeStamp(long secondsBeforeNow, long secondsAfterNow);
+
+ static Asn1Time timeToAsn1Time(long adjustment);
+
+ Asn1Time thisUpdate;
+ Asn1Time nextUpdate;
+};
+
+OcspTimeStamp::OcspTimeStamp(long secondsBeforeNow, long secondsAfterNow)
+{
+ Asn1Time start = timeToAsn1Time(secondsBeforeNow);
+ Asn1Time end = timeToAsn1Time(secondsAfterNow);
+ if (start.data() && end.data()) {
+ thisUpdate.swap(start);
+ nextUpdate.swap(end);
+ }
+}
+
+Asn1Time OcspTimeStamp::timeToAsn1Time(long adjustment)
+{
+ if (ASN1_TIME *adjusted = q_X509_gmtime_adj(nullptr, adjustment))
+ return Asn1Time(adjusted, q_ASN1_TIME_free);
+ return Asn1Time{};
+}
+
+struct OcspResponder
+{
+ OcspResponder(const OcspTimeStamp &stamp, const CertificateChain &subjs,
+ const CertificateChain &respChain, const QSslKey &respPKey);
+
+ QByteArray buildResponse(int responseStatus, int certificateStatus) const;
+ static EvpKey privateKeyToEVP_PKEY(const QSslKey &privateKey);
+ static CertId certificateToCertId(X509 *subject, X509 *issuer);
+ static QByteArray responseToDer(OCSP_RESPONSE *response);
+
+ OcspTimeStamp timeStamp;
+ // Plural, we can send a 'wrong' BasicResponse containing more than
+ // 1 SingleResponse.
+ X509Stack subjects;
+ X509Stack responderChain;
+ QSslKey responderKey;
+};
+
+OcspResponder::OcspResponder(const OcspTimeStamp &stamp, const CertificateChain &subjs,
+ const CertificateChain &respChain, const QSslKey &respPKey)
+ : timeStamp(stamp),
+ subjects(subjs),
+ responderChain(respChain),
+ responderKey(respPKey)
+{
+}
+
+QByteArray OcspResponder::buildResponse(int responseStatus, int certificateStatus) const
+{
+ if (responseStatus != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
+ OCSP_RESPONSE *response = q_OCSP_response_create(responseStatus, nullptr);
+ if (!response)
+ return {};
+ const OcspResponse rGuard(response, q_OCSP_RESPONSE_free);
+ return responseToDer(response);
+ }
+
+ Q_ASSERT(subjects.size() && responderChain.size() && responderKey.handle());
+
+ const EvpKey nativeKey = privateKeyToEVP_PKEY(responderKey);
+ if (!nativeKey.data())
+ return {};
+
+ OCSP_BASICRESP *basicResponse = q_OCSP_BASICRESP_new();
+ if (!basicResponse)
+ return {};
+ const BasicResponse brGuard(basicResponse, q_OCSP_BASICRESP_free);
+
+ for (int i = 0, e = subjects.size(); i < e; ++i) {
+ X509 *subject = subjects[i];
+ Q_ASSERT(subject);
+ CertId certId = certificateToCertId(subject, responderChain[0]);
+ if (!certId.data())
+ return {};
+
+ // NOTE: we do not own this 'singleResponse':
+ ASN1_TIME *revisionTime = certificateStatus == V_OCSP_CERTSTATUS_REVOKED ?
+ timeStamp.thisUpdate.data() : nullptr;
+
+ if (!q_OCSP_basic_add1_status(basicResponse, certId.data(), certificateStatus, 0, revisionTime,
+ timeStamp.thisUpdate.data(), timeStamp.nextUpdate.data())) {
+ return {};
+ }
+ }
+
+ if (q_OCSP_basic_sign(basicResponse, responderChain[0], nativeKey.data(), q_EVP_sha1(),
+ responderChain, 0) != 1) {
+ return {};
+ }
+
+ OCSP_RESPONSE *ocspResponse = q_OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, basicResponse);
+ if (!ocspResponse)
+ return {};
+ const OcspResponse rGuard(ocspResponse, q_OCSP_RESPONSE_free);
+ return responseToDer(ocspResponse);
+}
+
+EvpKey OcspResponder::privateKeyToEVP_PKEY(const QSslKey &privateKey)
+{
+ const EvpKey nullKey;
+ if (privateKey.isNull() || privateKey.algorithm() != QSsl::Rsa) {
+ // We use only RSA keys in this auto-test, since we test OCSP only,
+ // not handshake/TLS in general.
+ return nullKey;
+ }
+
+ EVP_PKEY *nativeKey = q_EVP_PKEY_new();
+ if (!nativeKey)
+ return nullKey;
+
+ const EvpKey keyGuard(nativeKey, q_EVP_PKEY_free);
+ if (!q_EVP_PKEY_set1_RSA(nativeKey, reinterpret_cast<RSA *>(privateKey.handle())))
+ return nullKey;
+
+ return keyGuard;
+}
+
+CertId OcspResponder::certificateToCertId(X509 *subject, X509 *issuer)
+{
+ const CertId nullId;
+ if (!subject || !issuer)
+ return nullId;
+
+ const EVP_MD *digest = q_EVP_sha1();
+ if (!digest)
+ return nullId;
+
+ OCSP_CERTID *certId = q_OCSP_cert_to_id(digest, subject, issuer);
+ if (!certId)
+ return nullId;
+
+ return CertId(certId, q_OCSP_CERTID_free);
+}
+
+QByteArray OcspResponder::responseToDer(OCSP_RESPONSE *response)
+{
+ if (!response)
+ return {};
+
+ const int derSize = q_i2d_OCSP_RESPONSE(response, nullptr);
+ if (derSize <= 0)
+ return {};
+
+ QByteArray derData(derSize, Qt::Uninitialized);
+ unsigned char *pData = reinterpret_cast<unsigned char *>(derData.data());
+ const int serializedSize = q_i2d_OCSP_RESPONSE(response, &pData);
+ if (serializedSize != derSize)
+ return {};
+
+ return derData;
+}
+
+// The QTcpServer capable of sending OCSP status responses.
+class OcspServer : public QTcpServer
+{
+ Q_OBJECT
+
+public:
+ OcspServer(const CertificateChain &serverChain, const QSslKey &privateKey);
+
+ void configureResponse(const QByteArray &responseDer);
+ QString hostName() const;
+ QString peerVerifyName() const;
+
+Q_SIGNALS:
+ void internalServerError();
+
+private:
+ void incomingConnection(qintptr descriptor) override;
+
+public:
+ QSslConfiguration serverConfig;
+ QSslSocket serverSocket;
+};
+
+OcspServer::OcspServer(const CertificateChain &serverChain, const QSslKey &privateKey)
+{
+ Q_ASSERT(serverChain.size());
+ Q_ASSERT(!privateKey.isNull());
+
+ serverConfig = QSslConfiguration::defaultConfiguration();
+ serverConfig.setLocalCertificateChain(serverChain);
+ serverConfig.setPrivateKey(privateKey);
+}
+
+void OcspServer::configureResponse(const QByteArray &responseDer)
+{
+ serverConfig.setBackendConfigurationOption("Qt-OCSP-response", responseDer);
+}
+
+QString OcspServer::hostName() const
+{
+ // It's 'name' and not 'address' to be consistent with QSslSocket's naming style,
+ // where it's connectToHostEncrypted(hostName, ...)
+ const QHostAddress &addr = serverAddress();
+ if (addr == QHostAddress::Any || addr == QHostAddress::AnyIPv4)
+ return QStringLiteral("127.0.0.1");
+ if (addr == QHostAddress::AnyIPv6)
+ return QStringLiteral("::1");
+ return addr.toString();
+}
+
+QString OcspServer::peerVerifyName() const
+{
+ const CertificateChain &localChain = serverConfig.localCertificateChain();
+ if (localChain.isEmpty())
+ return {};
+ const auto cert = localChain.first();
+ if (cert.isNull())
+ return {};
+
+ const QStringList &names = cert.subjectInfo(QSslCertificate::CommonName);
+ return names.isEmpty() ? QString{} : names.first();
+}
+
+void OcspServer::incomingConnection(qintptr socketDescriptor)
+{
+ close();
+
+ if (!serverSocket.setSocketDescriptor(socketDescriptor)) {
+ emit internalServerError();
+ return;
+ }
+
+ serverSocket.setSslConfiguration(serverConfig);
+ // Since we test a client, not a server, we don't care about any
+ // possible errors on the server (QAbstractSocket or QSslSocket-related).
+ // Thus, we don't connect to any error signal.
+ serverSocket.startServerEncryption();
+}
+
+} // unnamed namespace
+
+class tst_QOcsp : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+
+private slots:
+ void connectSelfSigned();
+ void badStatus_data();
+ void badStatus();
+ void multipleSingleResponses();
+ void malformedResponse();
+ void expiredResponse_data();
+ void expiredResponse();
+ void noNextUpdate();
+ void wrongCertificateInResponse_data();
+ void wrongCertificateInResponse();
+ void untrustedResponder();
+
+ // OCSPTODO: more tests in future ...
+
+private:
+ void setupOcspClient(QSslSocket &clientSocket, const CertificateChain &trustedCAs,
+ const QString &peerName);
+ bool containsOcspErrors(const QList<QSslError> &errorsFound) const;
+ static bool containsError(const QList<QSslError> &errors, QSslError::SslError code);
+ static QByteArray goodResponse(const CertificateChain &subject, const CertificateChain &responder,
+ const QSslKey &privateKey, long beforeNow = -1000, long afterNow = 1000);
+ static bool loadPrivateKey(const QString &keyName, QSslKey &key);
+ static CertificateChain issuerToChain(const CertificateChain &chain);
+ static CertificateChain subjectToChain(const CertificateChain &chain);
+
+ static QString certDirPath;
+
+ void (QSslSocket::*socketErrorSignal)(QAbstractSocket::SocketError) = &QAbstractSocket::error;
+ void (QSslSocket::*tlsErrorsSignal)(const QList<QSslError> &) = &QSslSocket::sslErrors;
+ void (QTestEventLoop::*exitLoopSlot)() = &QTestEventLoop::exitLoop;
+
+ const int handshakeTimeoutMS = 500;
+ QTestEventLoop loop;
+
+ std::vector<QSslError::SslError> ocspErrorCodes = {QSslError::OcspNoResponseFound,
+ QSslError::OcspMalformedRequest,
+ QSslError::OcspMalformedResponse,
+ QSslError::OcspInternalError,
+ QSslError::OcspTryLater,
+ QSslError::OcspSigRequred,
+ QSslError::OcspUnauthorized,
+ QSslError::OcspResponseCannotBeTrusted,
+ QSslError::OcspResponseCertIdUnknown,
+ QSslError::OcspResponseExpired,
+ QSslError::OcspStatusUnknown};
+};
+
+#define QCOMPARE_SINGLE_ERROR(sslSocket, expectedError) \
+ const auto &tlsErrors = sslSocket.sslErrors(); \
+ QCOMPARE(tlsErrors.size(), 1); \
+ QCOMPARE(tlsErrors[0].error(), expectedError)
+
+#define QVERIFY_HANDSHAKE_WITHOUT_ERRORS(sslSocket) \
+ QVERIFY(sslSocket.isEncrypted()); \
+ QCOMPARE(sslSocket.state(), QAbstractSocket::ConnectedState); \
+ QVERIFY(sslSocket.sslErrors().isEmpty())
+
+#define QDECLARE_CHAIN(object, chainFileName) \
+ CertificateChain object = QSslCertificate::fromPath(certDirPath + QLatin1String(chainFileName)); \
+ QVERIFY(object.size())
+
+#define QDECLARE_PRIVATE_KEY(key, keyFileName) \
+ QSslKey key; \
+ QVERIFY(loadPrivateKey(QLatin1String(keyFileName), key))
+
+QString tst_QOcsp::certDirPath;
+
+void tst_QOcsp::initTestCase()
+{
+ QVERIFY(QSslSocket::supportsSsl());
+
+ certDirPath = QFileInfo(QFINDTESTDATA("certs")).absolutePath();
+ QVERIFY(certDirPath.size() > 0);
+ certDirPath += QDir::separator() + QStringLiteral("certs") + QDir::separator();
+}
+
+void tst_QOcsp::connectSelfSigned()
+{
+ // This test may look a bit confusing, since we have essentially 1
+ // self-signed certificate, which we trust for the purpose of this test,
+ // but we also request its (the certificate's) status and then we sign
+ // the status response using the same certificate and the corresponding
+ // private key. Anyway, we test the very basic things here: we send
+ // an OCSP status request, we verify the response (if server has sent it),
+ // and detect errors (if any).
+ QDECLARE_CHAIN(subjectChain, "ss1.crt");
+ QDECLARE_CHAIN(responderChain, "ss1.crt");
+ QDECLARE_PRIVATE_KEY(privateKey, "ss1-private.key");
+ {
+ // This server ignores our status request:
+ const QSslError::SslError expectedError = QSslError::OcspNoResponseFound;
+
+ OcspServer server(subjectChain, privateKey);
+ QVERIFY(server.listen());
+ connect(&server, &OcspServer::internalServerError, &loop, exitLoopSlot);
+
+ QSslSocket clientSocket;
+ QSslConfiguration clientConfig = QSslConfiguration::defaultConfiguration();
+ auto roots = clientConfig.caCertificates();
+ setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
+ clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
+ loop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!clientSocket.isEncrypted());
+ QCOMPARE_SINGLE_ERROR(clientSocket, expectedError);
+ }
+ {
+ // Now the server will send a valid 'status: good' response.
+ OcspServer server(subjectChain, privateKey);
+ const QByteArray response(goodResponse(subjectChain, responderChain, privateKey));
+ QVERIFY(response.size());
+ server.configureResponse(response);
+ QVERIFY(server.listen());
+
+ QSslSocket clientSocket;
+ setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
+ clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
+ loop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY_HANDSHAKE_WITHOUT_ERRORS(clientSocket);
+ }
+}
+
+void tst_QOcsp::badStatus_data()
+{
+ QTest::addColumn<int>("responseStatus");
+ QTest::addColumn<int>("certificateStatus");
+ QTest::addColumn<QSslError>("expectedError");
+
+ QTest::addRow("malformed-request") << OCSP_RESPONSE_STATUS_MALFORMEDREQUEST << 1 << QSslError(QSslError::OcspMalformedRequest);
+ QTest::addRow("internal-error") << OCSP_RESPONSE_STATUS_INTERNALERROR << 2 << QSslError(QSslError::OcspInternalError);
+ QTest::addRow("try-later") << OCSP_RESPONSE_STATUS_TRYLATER << 3 << QSslError(QSslError::OcspTryLater);
+ QTest::addRow("signed-request-require") << OCSP_RESPONSE_STATUS_SIGREQUIRED << 2 << QSslError(QSslError::OcspSigRequred);
+ QTest::addRow("unauthorized-request") << OCSP_RESPONSE_STATUS_UNAUTHORIZED << 1 <<QSslError(QSslError::OcspUnauthorized);
+
+ QTest::addRow("certificate-revoked") << OCSP_RESPONSE_STATUS_SUCCESSFUL << V_OCSP_CERTSTATUS_REVOKED
+ << QSslError(QSslError::CertificateRevoked);
+ QTest::addRow("status-unknown") << OCSP_RESPONSE_STATUS_SUCCESSFUL << V_OCSP_CERTSTATUS_UNKNOWN
+ << QSslError(QSslError::OcspStatusUnknown);
+}
+
+void tst_QOcsp::badStatus()
+{
+ // This test works with two types of 'bad' responses:
+ // 1. 'Error messages' (the response's status is anything but SUCCESSFUL,
+ // no information about the certificate itself, no signature);
+ // 2. 'REVOKED' or 'UNKNOWN' status for a certificate in question.
+ QFETCH(const int, responseStatus);
+ QFETCH(const int, certificateStatus);
+ QFETCH(const QSslError, expectedError);
+
+ QDECLARE_CHAIN(subjectChain, "infbobchain.crt");
+ QCOMPARE(subjectChain.size(), 2);
+ QDECLARE_CHAIN(responderChain, "ca1.crt");
+ QDECLARE_PRIVATE_KEY(subjPrivateKey, "infbob.key");
+ QDECLARE_PRIVATE_KEY(respPrivateKey, "ca1.key");
+
+ OcspServer server(subjectChain, subjPrivateKey);
+ const OcspTimeStamp stamp(-1000, 1000);
+ OcspResponder builder(stamp, subjectToChain(subjectChain), responderChain, respPrivateKey);
+ const QByteArray response(builder.buildResponse(responseStatus, certificateStatus));
+ QVERIFY(response.size());
+ server.configureResponse(response);
+ QVERIFY(server.listen());
+ connect(&server, &OcspServer::internalServerError, &loop, exitLoopSlot);
+
+ QSslSocket clientSocket;
+ setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
+ clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
+ loop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!clientSocket.isEncrypted());
+ QCOMPARE_SINGLE_ERROR(clientSocket, expectedError.error());
+}
+
+void tst_QOcsp::multipleSingleResponses()
+{
+ // We handle a response with more than one SingleResponse as malformed:
+ const QSslError::SslError expectedError = QSslError::OcspMalformedResponse;
+
+ // Here we use subjectChain only to generate a response, the server
+ // is configured with the responder chain (it's the same cert after all).
+ QDECLARE_CHAIN(subjectChain, "ss1.crt");
+ QDECLARE_CHAIN(responderChain, "ss1.crt");
+ QDECLARE_PRIVATE_KEY(privateKey, "ss1-private.key");
+
+ // Let's have more than 1 certificate in a chain:
+ subjectChain.append(subjectChain[0]);
+
+ OcspServer server(responderChain, privateKey);
+ // Generate a BasicOCSPResponse containing 2 SingleResponses:
+ const QByteArray response(goodResponse(subjectChain, responderChain, privateKey));
+ QVERIFY(response.size());
+ server.configureResponse(response);
+ QVERIFY(server.listen());
+ connect(&server, &OcspServer::internalServerError, &loop, exitLoopSlot);
+
+ QSslSocket clientSocket;
+ setupOcspClient(clientSocket, issuerToChain(responderChain), server.peerVerifyName());
+ clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
+ loop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!clientSocket.isEncrypted());
+ QCOMPARE_SINGLE_ERROR(clientSocket, expectedError);
+}
+
+void tst_QOcsp::malformedResponse()
+{
+ QDECLARE_CHAIN(serverChain, "ss1.crt");
+ QDECLARE_PRIVATE_KEY(privateKey, "ss1-private.key");
+
+ OcspServer server(serverChain, privateKey);
+ // Let's send some arbitrary bytes instead of DER and see what happens next:
+ server.configureResponse("Sure, you can trust me, this cert was not revoked (I don't say it was issued at all)!");
+ QVERIFY(server.listen());
+ connect(&server, &OcspServer::internalServerError, &loop, exitLoopSlot);
+
+ QSslSocket clientSocket;
+ setupOcspClient(clientSocket, issuerToChain(serverChain), server.peerVerifyName());
+ clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
+ loop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!clientSocket.isEncrypted());
+ QCOMPARE(clientSocket.error(), QAbstractSocket::SslHandshakeFailedError);
+}
+
+void tst_QOcsp::expiredResponse_data()
+{
+ QTest::addColumn<long>("beforeNow");
+ QTest::addColumn<long>("afterNow");
+
+ QTest::addRow("expired") << -2000L << -1000L;
+ QTest::addRow("not-valid-yet") << 5000L << 10000L;
+ QTest::addRow("next-before-this") << -1000L << -2000L;
+}
+
+void tst_QOcsp::expiredResponse()
+{
+ // We report different kinds of problems with [thisUpdate, nextUpdate]
+ // as 'expired' (to keep it simple):
+ const QSslError::SslError expectedError = QSslError::OcspResponseExpired;
+
+ QFETCH(const long, beforeNow);
+ QFETCH(const long, afterNow);
+
+ QDECLARE_CHAIN(subjectChain, "ss1.crt");
+ QDECLARE_CHAIN(responderChain, "ss1.crt");
+ QDECLARE_PRIVATE_KEY(privateKey, "ss1-private.key");
+
+ OcspServer server(subjectChain, privateKey);
+ const QByteArray response(goodResponse(subjectChain, responderChain, privateKey, beforeNow, afterNow));
+ QVERIFY(response.size());
+ server.configureResponse(response);
+ QVERIFY(server.listen());
+ connect(&server, &OcspServer::internalServerError, &loop, exitLoopSlot);
+
+ QSslSocket clientSocket;
+ setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
+ clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
+ loop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!clientSocket.isEncrypted());
+ QCOMPARE_SINGLE_ERROR(clientSocket, expectedError);
+}
+
+void tst_QOcsp::noNextUpdate()
+{
+ // RFC2560, 2.4:
+ // "If nextUpdate is not set, the responder is indicating that newer
+ // revocation information is available all the time."
+ //
+ // This test is just to verify that we correctly handle such responses.
+ QDECLARE_CHAIN(subjectChain, "ss1.crt");
+ QDECLARE_CHAIN(responderChain, "ss1.crt");
+ QDECLARE_PRIVATE_KEY(privateKey, "ss1-private.key");
+
+ OcspServer server(subjectChain, privateKey);
+ OcspTimeStamp openRange(-1000, 0);
+ openRange.nextUpdate.clear();
+ const OcspResponder responder(openRange, subjectChain, responderChain, privateKey);
+ const QByteArray response(responder.buildResponse(OCSP_RESPONSE_STATUS_SUCCESSFUL,
+ V_OCSP_CERTSTATUS_GOOD));
+ QVERIFY(response.size());
+ server.configureResponse(response);
+ QVERIFY(server.listen());
+ connect(&server, &OcspServer::internalServerError, &loop, exitLoopSlot);
+
+ QSslSocket clientSocket;
+ setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
+ clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
+ loop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY_HANDSHAKE_WITHOUT_ERRORS(clientSocket);
+}
+
+void tst_QOcsp::wrongCertificateInResponse_data()
+{
+ QTest::addColumn<QLatin1String>("respChainName");
+ QTest::addColumn<QLatin1String>("respKeyName");
+ QTest::addColumn<QLatin1String>("wrongChainName");
+
+ QTest::addRow("same-CA-wrong-subject") << QLatin1String("ca1.crt") << QLatin1String("ca1.key")
+ << QLatin1String("alice.crt");
+ QTest::addRow("wrong-CA-same-subject") << QLatin1String("ss1.crt") << QLatin1String("ss1-private.key")
+ << QLatin1String("alice.crt");
+ QTest::addRow("wrong-CA-wrong-subject") << QLatin1String("ss1.crt") << QLatin1String("ss1-private.key")
+ << QLatin1String("ss1.crt");
+}
+
+void tst_QOcsp::wrongCertificateInResponse()
+{
+ QFETCH(const QLatin1String, respChainName);
+ QFETCH(const QLatin1String, respKeyName);
+ QFETCH(const QLatin1String, wrongChainName);
+ // In this test, the server will send a valid response (correctly signed
+ // by a trusted key/cert) but for a wrong certificate (not the one the
+ // server presented to the client in the server's 'Certificate' message).
+ const QSslError::SslError expectedError = QSslError::OcspResponseCertIdUnknown;
+
+ QDECLARE_CHAIN(subjectChain, "infbobchain.crt");
+ QDECLARE_PRIVATE_KEY(subjectKey, "infbob.key");
+ QDECLARE_CHAIN(responderChain, respChainName);
+ QDECLARE_PRIVATE_KEY(responderKey, respKeyName);
+
+ QDECLARE_CHAIN(wrongChain, wrongChainName);
+
+ OcspServer server(subjectToChain(subjectChain), subjectKey);
+ const QByteArray wrongResponse(goodResponse(wrongChain, responderChain, responderKey));
+ QVERIFY(wrongResponse.size());
+ server.configureResponse(wrongResponse);
+ QVERIFY(server.listen());
+ connect(&server, &OcspServer::internalServerError, &loop, exitLoopSlot);
+
+ QSslSocket clientSocket;
+ setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
+ clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
+ loop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!clientSocket.isEncrypted());
+ QVERIFY(containsError(clientSocket.sslErrors(), expectedError));
+}
+
+void tst_QOcsp::untrustedResponder()
+{
+ const QSslError::SslError expectedError = QSslError::OcspResponseCannotBeTrusted;
+
+ QDECLARE_CHAIN(subjectChain, "infbobchain.crt");
+ QDECLARE_PRIVATE_KEY(subjectKey, "infbob.key");
+ QDECLARE_CHAIN(responderChain, "ca1.crt");
+ QDECLARE_PRIVATE_KEY(responderKey, "ca1.key");
+
+ OcspServer server(subjectChain, subjectKey);
+ const QByteArray response(goodResponse(subjectToChain(subjectChain), responderChain, responderKey));
+ QVERIFY(response.size());
+ server.configureResponse(response);
+ QVERIFY(server.listen());
+ connect(&server, &OcspServer::internalServerError, &loop, exitLoopSlot);
+
+ QSslSocket clientSocket;
+ setupOcspClient(clientSocket, {}, server.peerVerifyName());
+ clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
+ loop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!clientSocket.isEncrypted());
+ QVERIFY(containsError(clientSocket.sslErrors(), expectedError));
+}
+
+void tst_QOcsp::setupOcspClient(QSslSocket &clientSocket, const CertificateChain &caCerts, const QString &name)
+{
+ QSslConfiguration clientConfig = QSslConfiguration::defaultConfiguration();
+ clientConfig.setOcspStaplingEnabled(true);
+
+ if (caCerts.size()) {
+ auto roots = clientConfig.caCertificates();
+ roots.append(caCerts);
+ clientConfig.setCaCertificates(roots);
+ }
+
+ clientSocket.setSslConfiguration(clientConfig);
+ clientSocket.setPeerVerifyName(name);
+
+ connect(&clientSocket, socketErrorSignal, &loop, exitLoopSlot);
+ connect(&clientSocket, tlsErrorsSignal, &loop, exitLoopSlot);
+ connect(&clientSocket, &QSslSocket::encrypted, &loop, exitLoopSlot);
+}
+
+bool tst_QOcsp::containsOcspErrors(const QList<QSslError> &errorsFound) const
+{
+ for (auto code : ocspErrorCodes) {
+ if (containsError(errorsFound, code))
+ return true;
+ }
+ return false;
+}
+
+bool tst_QOcsp::containsError(const QList<QSslError> &errors, QSslError::SslError code)
+{
+ const auto it = std::find_if(errors.begin(), errors.end(),
+ [&code](const QSslError &other){return other.error() == code;});
+ return it != errors.end();
+}
+
+QByteArray tst_QOcsp::goodResponse(const CertificateChain &subject, const CertificateChain &responder,
+ const QSslKey &privateKey, long beforeNow, long afterNow)
+{
+ const OcspResponder builder(OcspTimeStamp(beforeNow, afterNow), subject, responder, privateKey);
+ return builder.buildResponse(OCSP_RESPONSE_STATUS_SUCCESSFUL, V_OCSP_CERTSTATUS_GOOD);
+}
+
+bool tst_QOcsp::loadPrivateKey(const QString &keyFileName, QSslKey &key)
+{
+ QFile keyFile(certDirPath + keyFileName);
+ if (!keyFile.open(QIODevice::ReadOnly))
+ return false;
+ key = QSslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ return !key.isNull();
+}
+
+CertificateChain tst_QOcsp::issuerToChain(const CertificateChain &chain)
+{
+ // Here we presume that, if the chain isn't a single self-signed certificate, its second
+ // entry is the issuer.
+ const int length = chain.size();
+ Q_ASSERT(length > 0);
+ return CertificateChain() << chain[length > 1 ? 1 : 0];
+}
+
+CertificateChain tst_QOcsp::subjectToChain(const CertificateChain &chain)
+{
+ Q_ASSERT(chain.size());
+ return CertificateChain() << chain[0];
+}
+
+QT_END_NAMESPACE
+
+QTEST_MAIN(tst_QOcsp)
+
+#include "tst_qocsp.moc"
diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
index 7f8580ddd6..efc0c26076 100644
--- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
+++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
@@ -401,9 +401,7 @@ void tst_QSslCertificate::subjectAlternativeNames()
certificate.subjectAlternativeNames();
// verify that each entry in subjAltNames is present in fileContents
- QMapIterator<QSsl::AlternativeNameEntryType, QString> it(altSubjectNames);
- while (it.hasNext()) {
- it.next();
+ for (auto it = altSubjectNames.cbegin(), end = altSubjectNames.cend(); it != end; ++it) {
QByteArray type;
if (it.key() == QSsl::EmailEntry)
type = "email";
@@ -814,7 +812,7 @@ void tst_QSslCertificate::task256066toPem()
void tst_QSslCertificate::nulInCN()
{
-#if defined(QT_SECURETRANSPORT) || defined(Q_OS_WINRT)
+#if QT_CONFIG(securetransport) || defined(Q_OS_WINRT) || QT_CONFIG(schannel)
QSKIP("Generic QSslCertificatePrivate fails this test");
#endif
QList<QSslCertificate> certList =
@@ -833,7 +831,7 @@ void tst_QSslCertificate::nulInCN()
void tst_QSslCertificate::nulInSan()
{
-#if defined(QT_SECURETRANSPORT) || defined(Q_OS_WINRT)
+#if QT_CONFIG(securetransport) || defined(Q_OS_WINRT) || QT_CONFIG(schannel)
QSKIP("Generic QSslCertificatePrivate fails this test");
#endif
QList<QSslCertificate> certList =
@@ -968,7 +966,7 @@ void tst_QSslCertificate::subjectAndIssuerAttributes()
void tst_QSslCertificate::verify()
{
-#ifdef QT_SECURETRANSPORT
+#if QT_CONFIG(securetransport)
QSKIP("Not implemented in SecureTransport");
#endif
QList<QSslError> errors;
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pri-1024.der b/tests/auto/network/ssl/qsslkey/keys/dh-pri-1024.der
new file mode 100644
index 0000000000..687009e087
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pri-1024.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pri-1024.pem b/tests/auto/network/ssl/qsslkey/keys/dh-pri-1024.pem
new file mode 100644
index 0000000000..233e0dfb37
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pri-1024.pem
@@ -0,0 +1,9 @@
+-----BEGIN PRIVATE KEY-----
+MIIBIQIBADCBlQYJKoZIhvcNAQMBMIGHAoGBAIlk2YX0TJzfQ18ZzZroQoE5Nyjt
+bWxWRxBriG/c+JWhBwttVDb6lzLN+GVJxXVPfc6JJmDORVRxdxAlMqu++2Vqpsnl
+/H8xIXsxjuTcTjq8sXagGRa0LfeggkUD64tEhO4iZ8Q2TIdb3OHkAF0Sn+06b/0e
+iIz323Kywq0CsspTAgECBIGDAoGAQCo39UHP4s2ZVH4nOmWgNlb4JsHPX4EzqDBr
+ig46hvMLAFrILYnsCbqqD/+GNAUl1PV/nfEQoAk/HvtACqLFLG5/3jK2w6dVHGEo
+JnVOGz9vZpWUx+SCslHJRFaeE+6AAbbvrTr0lci29Ta4IesHlamRsj+ZaUrVX6k/
+/9OTGAo=
+-----END PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pri-2048.der b/tests/auto/network/ssl/qsslkey/keys/dh-pri-2048.der
new file mode 100644
index 0000000000..e193f25f07
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pri-2048.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pri-2048.pem b/tests/auto/network/ssl/qsslkey/keys/dh-pri-2048.pem
new file mode 100644
index 0000000000..32299b2b6c
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pri-2048.pem
@@ -0,0 +1,14 @@
+-----BEGIN PRIVATE KEY-----
+MIICJgIBADCCARcGCSqGSIb3DQEDATCCAQgCggEBAJsiReJxBjkC7Hy99AJATusq
+YsNQHhjoeTLPeHhsBuLtJK18Krk736V09efX6qeAEmvgMQbvbHqtrOaY3q6dut6C
+UTGVW+oVg3d/Y8qakkanvEnIlliaTIyWIz0JMjO2prC6AuU/QEzZcQVUS6bxyn3D
+iYFxCE6+7cJJpEH9HVbcrl+J6Ch6ax5rQGUyxpSMkmItLJx92upRxOnaxJMHR+ZF
+OSdDPfrkINpEzahnhteLszddyLasnE0or6ZnXYLvKsT1Uu6QwDc4EO1FJHScoeep
+zsK/VRcXzMpj/1Rl+F9E/AikCqHRrnvISt25wrK0Mwy854P2T7dJlBNewc6vE6MC
+AQIEggEEAoIBAGIctO30MoZ9DiuKbOBpqM9rl2bNH/I46GGcfEiSsO/zOw2V9WFC
+MxkjF0I1ilDfPY+Ag3bLB2n89DPcfXliYH9MFolehPTc1fWplhX3+ImdC6y95uXO
+FV5xtcEQCbPktnUtkUdcAT5831p9lu1QJo+DzMPrQa7axMLj8heBAi4VqAi+8Q31
+dpGKuhCUlgs+pLENx1o0QY2kui6Z5uR0YhmA547lwBWA4XEv5OV9ExmxytiatvOv
+PZKT1ID76LrL9bnnZvOEGczWLQvJ9VaaZSpoP+2QisRANWW4w57d+PIR1WR/FTSH
+F6xocElUoTzuiSPzRz60aw/KkisImBBKERQ=
+-----END PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pri-512.der b/tests/auto/network/ssl/qsslkey/keys/dh-pri-512.der
new file mode 100644
index 0000000000..42ddbaaae2
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pri-512.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pri-512.pem b/tests/auto/network/ssl/qsslkey/keys/dh-pri-512.pem
new file mode 100644
index 0000000000..d2c3170b16
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pri-512.pem
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIGcAgEAMFMGCSqGSIb3DQEDATBGAkEAvXx0QxJvIGA2ig8Je55R2rmeO4Ta2Esj
+ANLuyVIFRbtuLFsdhU+amUc8bs9RUQmkUNzS92jkpAfqtCv+mQ06EwIBAgRCAkBJ
+rDM0BTevOPIHpJzMtSQhw3e7Dr38HUfTn8zF3uYi1RCxjkTUukmzRLPTf0aqPgpd
+8dSldjG/11aZORl8/mXO
+-----END PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pub-1024.der b/tests/auto/network/ssl/qsslkey/keys/dh-pub-1024.der
new file mode 100644
index 0000000000..2805a67633
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pub-1024.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pub-1024.pem b/tests/auto/network/ssl/qsslkey/keys/dh-pub-1024.pem
new file mode 100644
index 0000000000..da4e327ac9
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pub-1024.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBHzCBlQYJKoZIhvcNAQMBMIGHAoGBAIlk2YX0TJzfQ18ZzZroQoE5NyjtbWxW
+RxBriG/c+JWhBwttVDb6lzLN+GVJxXVPfc6JJmDORVRxdxAlMqu++2Vqpsnl/H8x
+IXsxjuTcTjq8sXagGRa0LfeggkUD64tEhO4iZ8Q2TIdb3OHkAF0Sn+06b/0eiIz3
+23Kywq0CsspTAgECA4GEAAKBgA8pxU1sMDvRWKpvJKNs3jNhZPQWFf4Tszu/cMcb
+1qAQ/q0DRb41VvsUoMaCfef/plZleV4MG26owb574AJeC86wX5MbRDTPS4CzAn+I
+an92AZl3vlYRQ2sSo3ktkyhw6LV1iewi08Ky7J4rqvG0Oo335QGEZlK1OgwBsyh0
+FKLe
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pub-2048.der b/tests/auto/network/ssl/qsslkey/keys/dh-pub-2048.der
new file mode 100644
index 0000000000..9e749d8a41
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pub-2048.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pub-2048.pem b/tests/auto/network/ssl/qsslkey/keys/dh-pub-2048.pem
new file mode 100644
index 0000000000..f751157c87
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pub-2048.pem
@@ -0,0 +1,14 @@
+-----BEGIN PUBLIC KEY-----
+MIICJDCCARcGCSqGSIb3DQEDATCCAQgCggEBAJsiReJxBjkC7Hy99AJATusqYsNQ
+HhjoeTLPeHhsBuLtJK18Krk736V09efX6qeAEmvgMQbvbHqtrOaY3q6dut6CUTGV
+W+oVg3d/Y8qakkanvEnIlliaTIyWIz0JMjO2prC6AuU/QEzZcQVUS6bxyn3DiYFx
+CE6+7cJJpEH9HVbcrl+J6Ch6ax5rQGUyxpSMkmItLJx92upRxOnaxJMHR+ZFOSdD
+PfrkINpEzahnhteLszddyLasnE0or6ZnXYLvKsT1Uu6QwDc4EO1FJHScoeepzsK/
+VRcXzMpj/1Rl+F9E/AikCqHRrnvISt25wrK0Mwy854P2T7dJlBNewc6vE6MCAQID
+ggEFAAKCAQAUeWRuqjl7F84USogxJOM1M4y8yKtBYY2KLs5iIVhzV4UZ+9+cMNZA
+otLXJ/e8BH0diR0yk7tjxD6hjjqd+nyafIkJGPElDMnTbRPHg5zZYMmI5L/efdSm
+OPbM7QsodrYH5aoF4c7hjMb/cttYVG2Yupsy4tfORuDbwL70upqOo6rkVq55eOGS
+6pseEume/SD+7e3xIPJTkrMMzBFHG6H7bVHikT4O7yWV1iVzElj919yi+4Zy6TK8
+0hG6l31D5bsJpOduhHYZtN1yQpw+sGT6Yiepkjgt+1YkGFiiRs5vDl4DHeYHyAhL
+oH9uKcm3q4lhaOeT5ml765g87qQD6+vr
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pub-512.der b/tests/auto/network/ssl/qsslkey/keys/dh-pub-512.der
new file mode 100644
index 0000000000..8a75babb6d
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pub-512.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dh-pub-512.pem b/tests/auto/network/ssl/qsslkey/keys/dh-pub-512.pem
new file mode 100644
index 0000000000..1f4e5c9a47
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dh-pub-512.pem
@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MIGaMFMGCSqGSIb3DQEDATBGAkEAvXx0QxJvIGA2ig8Je55R2rmeO4Ta2EsjANLu
+yVIFRbtuLFsdhU+amUc8bs9RUQmkUNzS92jkpAfqtCv+mQ06EwIBAgNDAAJARGBh
+9FmRRZZAxBtXZmS8wIgDwWvjB63GQ+E1pDLtZPztvPQ2eqUjTgSuGKV5cDankAV1
+Pkj/IA0Xl+SuFhLLew==
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/genkeys.sh b/tests/auto/network/ssl/qsslkey/keys/genkeys.sh
index 6210b42ab4..0106953bff 100755
--- a/tests/auto/network/ssl/qsslkey/keys/genkeys.sh
+++ b/tests/auto/network/ssl/qsslkey/keys/genkeys.sh
@@ -88,6 +88,27 @@ do
openssl ec -in ec-pri-$size-$curve.pem -pubout -out ec-pub-$size-$curve.der -outform DER
done
+#--- DH ----------------------------------------------------------------------------
+for size in 512 1024 2048
+do
+ echo -e "\ngenerating DH parameters to PEM file ..."
+ openssl dhparam -out dhpar-$size.pem $size
+
+ echo -e "\ngenerating DH private key to PEM file ..."
+ openssl genpkey -paramfile dhpar-$size.pem -out dh-pri-$size.pem
+
+ /bin/rm dhpar-$size.pem
+
+ echo -e "\ngenerating DH private key to DER file ..."
+ openssl pkey -in dh-pri-$size.pem -out dh-pri-$size.der -outform DER
+
+ echo -e "\ngenerating DH public key to PEM file ..."
+ openssl pkey -in dh-pri-$size.pem -pubout -out dh-pub-$size.pem
+
+ echo -e "\ngenerating DH public key to DER file ..."
+ openssl pkey -in dh-pri-$size.pem -pubout -out dh-pub-$size.der -outform DER
+done
+
#--- PKCS#8 ------------------------------------------------------------------------
# Note: We'll just grab some of the keys generated earlier and convert those
# https://www.openssl.org/docs/manmaster/man1/pkcs8.html#PKCS-5-v1.5-and-PKCS-12-algorithms
diff --git a/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes128.pem b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes128.pem
new file mode 100644
index 0000000000..1a8751874e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes128.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,A2A6F6BA67CFB2A992BA4FD3A0984B59
+
+L5G1mwcXwW30lFty1HaEHlswFXAGk9+qf0TdYYNAAvVrsTMgfMq/6xM5XWo3IgbN
+gG4K6T57gQkAywn+upqMHobB+7qc3DRzYlrm89gb74gHOe95l/iUJp4ii+ROLcmY
+fg/vNmDSB/D0eM91WfwId7ticYD29+BUbbnqSYyY2S7K7DytYLpXqg3u335GYCdT
+JwOsgcgbOICytkgK6c9ZDF3IrkzvWospVuiG5IfpLQkUXlJO3YGJ/oGf1BXnRd/b
+kTzUiimUVunX62muHaUXKkAmXS8FCdB0puI+52pzLJ5FHdFxCcnwSG09TmoXbwwa
+KoNM+IshNHPBGM7QxflVbSDxDaF1FWLwWSb8+Fhb2fTpfEGMxRCQ8HB1ZeMV4E5W
+DSiNhih8ziC0k957ZYv8iuLanoM1YYIdToHeBwjyBJA836eIcq/ElY2QtKUq5PRw
++sU1BdG+f9rf4iAPHpgWZAKFmJ42ya71bEEVAmfysAOPuc4hpn3SsDTtihm9RKc9
+l7LWJHaTnTu6yJA+vMJwAmPWg+IdG5vntbb93X4cgl5ZadBySRtv37wWyQPnQcFh
+ytX8z2CJNIFJb0ik8bXc39zOxExoTu/o86IuVJ87jFdS1wz3PRek6dJdl15icx76
+yAT0YB2/ZlRcRrO9hSm0D6P+sLOh//dyhhFAlUrDxqrKngI3KF4kgIrSlva3wmx2
+t16SiUKu6FGQZk6/KYOV27Cy+8UJEqlrNJzy+wSFi26d6e6xWTIR2ItzQCxhYDmq
+Tpx0Mh0ml2+bgrKRoDAL5z6UNy0Pc6bYQjvMznIeiuGvL8bAKTDUFwbmrZqNScsl
+tW7yNZG9iSJnAZGMTxuOhSvJRpQkxIcLICd+lsUxWZ2YvFxtSORuRNSwaC7oxtTD
+gIXV08ayoDbDmcguqTXWuCxtguxNANjhsUOetNHL8iP8QFrzAd5Ith9FgASCIBJJ
+3X7vL2YGc3E6DlAJE01loqySU/cnu6/zQapLB9BIzdtoLliwdrJ7PS8FSsBDfZ2X
+i6/7gb1jxYkJAS1NqrUMJw6BphRAwF8ny+FtPJ23Oaf+1vRIGiHsh8qw6XBfwFw9
+vtsUUL19r+8zMpvIB6gf34TLuM7AW7idu3c/486EWgZBDL3mOTd3fsyADKv/HCk7
+c8M2dsafxI6QkTlWsB8G5vkZ8lCGKHjrmPWjfD7NXi+CvXIrDY+gOeVN3PlQCU/2
+zF2vIxKtR0CXuxLzIjFhIgTYR5G5ZnddMmHeVkZdPRl7szGtrxOA4QGJQ6ZT4W2e
+O1whVU2KB0aBYskhClimapM5ypRkcNQ97cUR6/iNgdgSLqxGHCGeMR9bEyLl7/wr
+M0XeDjdVfm/Tj548oHgb0SKLsfL6nnKwqB2viKj81moK9A/wO1Ec9RNaw0jtp2j3
+VIUnPj0GqEjnkHc2jWY2yt4SD6e2AZHwLyWi1q3pixZo1CFiEgFXxwNyYwyeJ6jV
+CJHPRzoNjZ8dkvgRjsXdnWwN316JBNVcH8k7CCmg/8Gq3yAojXG1z8VJZ06GHckd
+meCL1t89OgwIAmIsysKu7+DrKtSlhkQclZmdG6IrQzuPKaHzTPTDgg3ef3jQ4YQO
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes192.pem b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes192.pem
new file mode 100644
index 0000000000..db74877a5a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes192.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,B408346ADE790F8CF0C902A4F0712B34
+
+SwzPBGxmwW2JddOyug1LrWjlZn8siSp5yezjK1x/z2+J2r/vvH8OjGnA387tFtae
+WVTmhT1ixQXMDI1UJuKx0gzrG2449c+BUVe2VXFPLZ2ocSgoXbBpVkfhEqtLAn91
+MSOpQMxvobQKltKhxgXGvuBJwhwfT7yK5HamohFGbxLUh4Dh+NBXwoYH4Qt+kM7C
+kV8VIKvkr/QAL/SRxNoY8rVResPgYvUjdtiGSNZ6CZhNRu42Q2FqbH817cE0NDsN
+il/xvWu4T/6VY1KpwMad/v6BhO45EeKz7YjbF/3Y5jj2JV9r45uf79lM9htMBw0d
+L+Cc3YHeFffgU8NZo0+iUoroXcb7mjWNmgYksbkaZPbLG383YXAXwbkQS7zDMVIx
+QhXn9w+78hNmEV/7PQ8mGXHEFwnfSR05phXoj8IyL5v0grRMA2dsjfxCgfQjH+kc
+Miwr5pD/Flw175OpPFCb2qladdTKoIWiVShspbteoRC0EuiWHzkl5z6Tneyb/sam
+yduLmSYD+RA6OBgUPY95Xm4AowlFFsuV/fxYZ53rFf4cZn9Z6VBVmvIEmapV7CtB
+JzyIVclocwM0ag5u/esdEt/jndJq9chZlIsDS30y3gP6Rlqk5mj90DAs98l28FVG
+WY9jP0babk8mxjYCcnAy7ikUc0D+vJVO6OTmfO3dkGjLpMBM6OlvfhN/0qeXrMDI
+nU2qOshUrVna2kRe6FrcvosFTD8wvQ1/BjmCp1iWWsGdc/q1BqI3pgOlgq3TYfl6
+iUJoji3V2iexH+GPkHsrs+kii1clsO2tgIP7doIooSVkcTsRTHHxKeeHn3qL2028
+pTvieIFD/T4biLZ9Q8sX3XWiHNmXZlCx8lX8MDjTavWES8gY4H5Sr6FjRMy1qpZY
+5w1aAyJ9YZ0J/jLPmFxt8mWgqHPiPlrQkryBBE3l1MSQ/hCEwlf9dP8a+ayINfd7
+3yNkHKjZ5fuoA+TZUQb/fyVM5o1zJ8ML01PaXWrMEgr3b36QL+Ivo2Rpnp9FpwuH
+E405cwCEy5fNSyhHFqqatCbsPl80nkP8OpW6jdWvNy9u0Ap9PS+MbHGq/pfkaazl
+fbKGOckrENzEXi6Uj/yY/0sMtbTJuC70n09X3edHyhl/RJPPUoNnwDM5W1FHfS3r
+qqSOl/r3y5pEErRdBpR4wEgB7DCLBALGDPfXNAAga4ez/Z2X9Zj234+4ZbUzWoLN
+1ER0QYyxLN7oz1qMA15J7nRyRIhDXNlXjyISOqy26T6/d4X0M+6RhNWfT/MHAjJ8
+6ogoGlQUITV3gPO4R6+FGZMF4R6zZXuKVtOXyzRwWnCLfo4gzBHmq+5mmCjGWRq8
+rSSkc6334bYuZOaEoR5EM5sh6ewkjSDPRrKR7EHO02YbiscyT/99TwT5pdIOPK3u
+2T6/40fSmCWQyBLuWxV9CMD+rB/q8Ja5KisEseck7PgI2pMmHfiD5yQXhKR9eDrB
+sRqZxjgRYxup+/0CIBshL8s1R88xelhXyIKyqFfVudM09yAZxEJLQhpDZ27g45ea
+FMX2Ve+ah2NjYBgzAhwKouWg5RyWb6X99NsrCEU75fn/ek86LGs3FxRgB4Uv7Udv
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes256.pem b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes256.pem
new file mode 100644
index 0000000000..3d96b3166e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase-aes256.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,0F2F4695C8FFA35F4076FA0273A3A4E3
+
+GCnMcAhhGuNkJ7SSMBrgNOaDfRtG22J0mdf/0VbrMOJF40P13YBjN3Kd6LpTqBya
+TCIaxQqtfjH1ffhJk8qhwG7uJFGgcY9i0dkrEYklgThzTVqHp7FsQ2jjgJs5HKpc
+euuVD1bxtuc9qI2hq4miA7Z/uDe3M34n+3xcpqccWS1dLFNFZ+fIDwIazfDCu3ah
+fUQHDeWLwOqYiQxhUjjrHpZkI1FE2JYZFaf4zIagIIgzI2O+33fgbrTSoeN5meRs
+F7V2fhDpyEoIlchwAmp6HE6ngtKP4Ecju00yn99AO42fn097yEVwvGFClQTaIzur
+aPEtuKZ4kdc/lmzL2tqNcZckq28ZxpeMq0Fgdcpeg5sDcut811scOjQLFs551On1
+j3E1WfiLoBLKgd9cgmCrZb8hMO+UjcCaV7Jv3T9vDrbvhWs/YhTTwo8UFVplh7Vx
+R1h3cKfzlbtOC5WHXGNK5dBu7SnpEk0+pscY5cxTrzN0odjMbbsjZQmKDZXbmZON
+USzG3Qtafm6Nw/jwQeIjeqaxSho6xGdadTteGaURw6iGio3h0c6/dHayCsxye4tk
+vODa0ZdJASwVh1605qDk9n/iYUT5B46KJCYwO/iN2kUmOcUcZeBqEfV1GfRmepZJ
+bwM4sipzE15hOJ5DKSkHWnSlByRMAdSrMxZWraKUczn5frEBAqEFLlBAvf/FnjWa
+yZJitgryCI2Y2bww1DEMnTCX345kUQIFmmjbzTIXnM28gW+fR3Br9dCf2FAsLNKr
+tru1cYXocPaCUHEqS+XZqVb6BQVQ11YAAde0+x9RknJgsBc9Y7TLobaDBvrV5/nK
+T3vm8el08upum6qPTPh6Z0zBbjx4sp6DYT977N1dYeH4n+0JqcSwIeZg/VAdG0RL
+GzgZVADpiRlStmy65W95KExBjbO0tRTVk/nB1U1nfLbsswp9EKxXgwtpE/ECeTOi
+hzeJBSsXGZ/ZXu/y+NlIu0B/GasFbfrHKslSSrUPTjGEtaEbLNiOEu2Etu3lRcMZ
+oDtMxgNR0TUgCS5nte8lLauYYfB6IuxZXpvJdcI5ushqdOJvvYgJ9Yb2ZPlY8Bt5
+C92Ga69aPcMYk24BPpe15eBbXMsFF8RF+CprVoUPCc+PcuROtxdt+rqoqjQeZPmV
+WQqq+pT2bychpwD7U5jxQnu4u2m+zeBXyk80euBbwEld9BCgfk9mFj6CdBJSEiGV
+qL0ivxd3mDaIKPGd5tcbrOMK2uD7duZY7FrQpAYgryoQJoUHccL7cr9fDC75akHg
+AbrG1+vAYEla/y+SlOg5VTHhiuIl17ZGMViXSqh7iqnnD0dNsZ/HDvk3XouhNxQy
+RQmfdqyIqLuAcfWwQxCQ2E/oMUIHjNhyYmfLVLVGsfxuevMa1eJv7rZ5vIkD2Vpe
+4VveZkNDSpCCNqnvub8+bMW+UXyzbxEZbK5PLkRp7cvtKdA5CUbTlT4060IV0YZ1
+vfMtzXRw8JDD9c1F1WF14afk+y9kvZN88XOH12bSKj+Re06Xx7OzuYU8fclq/pZB
+UZVtRETFnLgb8neMuz3vCoPWK/DSHDZGAAicxq7vTljyoU/QP71Dw7UJIAuYx6Mc
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
index ddfe52c5e4..f94756ed73 100644
--- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
+++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
@@ -30,6 +30,7 @@
#include <QtTest/QtTest>
#include <qsslkey.h>
#include <qsslsocket.h>
+#include <QScopeGuard>
#include <QtNetwork/qhostaddress.h>
#include <QtNetwork/qnetworkproxy.h>
@@ -63,7 +64,7 @@ class tst_QSslKey : public QObject
QList<KeyInfo> keyInfoList;
- void createPlainTestRows(bool filter = false, QSsl::EncodingFormat format = QSsl::EncodingFormat::Pem);
+ void createPlainTestRows(bool pemOnly = false);
public slots:
void initTestCase();
@@ -111,13 +112,14 @@ void tst_QSslKey::initTestCase()
QDir dir(testDataDir + "keys");
const QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable);
- QRegExp rx(QLatin1String("^(rsa|dsa|ec)-(pub|pri)-(\\d+)-?[\\w-]*\\.(pem|der)$"));
+ QRegExp rx(QLatin1String("^(rsa|dsa|dh|ec)-(pub|pri)-(\\d+)-?[\\w-]*\\.(pem|der)$"));
for (const QFileInfo &fileInfo : fileInfoList) {
if (rx.indexIn(fileInfo.fileName()) >= 0) {
keyInfoList << KeyInfo(
fileInfo,
rx.cap(1) == QLatin1String("rsa") ? QSsl::Rsa :
- (rx.cap(1) == QLatin1String("dsa") ? QSsl::Dsa : QSsl::Ec),
+ rx.cap(1) == QLatin1String("dsa") ? QSsl::Dsa :
+ rx.cap(1) == QLatin1String("dh") ? QSsl::Dh : QSsl::Ec,
rx.cap(2) == QLatin1String("pub") ? QSsl::PublicKey : QSsl::PrivateKey,
rx.cap(3).toInt(),
rx.cap(4) == QLatin1String("pem") ? QSsl::Pem : QSsl::Der);
@@ -154,7 +156,7 @@ Q_DECLARE_METATYPE(QSsl::KeyAlgorithm)
Q_DECLARE_METATYPE(QSsl::KeyType)
Q_DECLARE_METATYPE(QSsl::EncodingFormat)
-void tst_QSslKey::createPlainTestRows(bool filter, QSsl::EncodingFormat format)
+void tst_QSslKey::createPlainTestRows(bool pemOnly)
{
QTest::addColumn<QString>("absFilePath");
QTest::addColumn<QSsl::KeyAlgorithm>("algorithm");
@@ -162,11 +164,11 @@ void tst_QSslKey::createPlainTestRows(bool filter, QSsl::EncodingFormat format)
QTest::addColumn<int>("length");
QTest::addColumn<QSsl::EncodingFormat>("format");
foreach (KeyInfo keyInfo, keyInfoList) {
- if (filter && keyInfo.format != format)
+ if (pemOnly && keyInfo.format != QSsl::EncodingFormat::Pem)
continue;
-#ifdef Q_OS_WINRT
+#if defined(Q_OS_WINRT) || QT_CONFIG(schannel)
if (keyInfo.fileInfo.fileName().contains("RC2-64"))
- continue; // WinRT treats RC2 as 128 bit
+ continue; // WinRT/Schannel treats RC2 as 128 bit
#endif
#if !defined(QT_NO_SSL) && defined(QT_NO_OPENSSL) // generic backend
if (keyInfo.fileInfo.fileName().contains(QRegularExpression("-aes\\d\\d\\d-")))
@@ -232,15 +234,50 @@ void tst_QSslKey::constructorHandle()
QByteArray passphrase;
if (QByteArray(QTest::currentDataTag()).contains("-pkcs8-"))
passphrase = "1234";
+
BIO* bio = q_BIO_new(q_BIO_s_mem());
q_BIO_write(bio, pem.constData(), pem.length());
- QSslKey key(func(bio, nullptr, nullptr, static_cast<void *>(passphrase.data())), type);
+ EVP_PKEY *origin = func(bio, nullptr, nullptr, static_cast<void *>(passphrase.data()));
+#if QT_CONFIG(opensslv11)
+ q_EVP_PKEY_up_ref(origin);
+#endif
+ QSslKey key(origin, type);
+#if !QT_CONFIG(opensslv11)
+ q_BIO_write(bio, pem.constData(), pem.length());
+ origin = func(bio, nullptr, nullptr, static_cast<void *>(passphrase.data()));
+#endif
q_BIO_free(bio);
+ EVP_PKEY *handle = q_EVP_PKEY_new();
+ switch (algorithm) {
+ case QSsl::Rsa:
+ q_EVP_PKEY_set1_RSA(handle, static_cast<RSA *>(key.handle()));
+ break;
+ case QSsl::Dsa:
+ q_EVP_PKEY_set1_DSA(handle, static_cast<DSA *>(key.handle()));
+ break;
+ case QSsl::Dh:
+ q_EVP_PKEY_set1_DH(handle, static_cast<DH *>(key.handle()));
+ break;
+#ifndef OPENSSL_NO_EC
+ case QSsl::Ec:
+ q_EVP_PKEY_set1_EC_KEY(handle, static_cast<EC_KEY *>(key.handle()));
+ break;
+#endif
+ default:
+ break;
+ }
+
+ auto cleanup = qScopeGuard([origin, handle] {
+ q_EVP_PKEY_free(origin);
+ q_EVP_PKEY_free(handle);
+ });
+
QVERIFY(!key.isNull());
QCOMPARE(key.algorithm(), algorithm);
QCOMPARE(key.type(), type);
QCOMPARE(key.length(), length);
+ QCOMPARE(q_EVP_PKEY_cmp(origin, handle), 1);
#endif
}
@@ -429,15 +466,25 @@ void tst_QSslKey::toEncryptedPemOrDer()
void tst_QSslKey::passphraseChecks_data()
{
QTest::addColumn<QString>("fileName");
-
- QTest::newRow("DES") << (testDataDir + "rsa-with-passphrase-des.pem");
- QTest::newRow("3DES") << (testDataDir + "rsa-with-passphrase-3des.pem");
- QTest::newRow("RC2") << (testDataDir + "rsa-with-passphrase-rc2.pem");
+ QTest::addColumn<QByteArray>("passphrase");
+
+ const QByteArray pass("123");
+ const QByteArray aesPass("1234");
+
+ QTest::newRow("DES") << QString(testDataDir + "rsa-with-passphrase-des.pem") << pass;
+ QTest::newRow("3DES") << QString(testDataDir + "rsa-with-passphrase-3des.pem") << pass;
+ QTest::newRow("RC2") << QString(testDataDir + "rsa-with-passphrase-rc2.pem") << pass;
+#if (!defined(QT_NO_OPENSSL) && !defined(OPENSSL_NO_AES)) || (defined(QT_NO_OPENSSL) && QT_CONFIG(ssl))
+ QTest::newRow("AES128") << QString(testDataDir + "rsa-with-passphrase-aes128.pem") << aesPass;
+ QTest::newRow("AES192") << QString(testDataDir + "rsa-with-passphrase-aes192.pem") << aesPass;
+ QTest::newRow("AES256") << QString(testDataDir + "rsa-with-passphrase-aes256.pem") << aesPass;
+#endif // (OpenSSL && AES) || generic backend
}
void tst_QSslKey::passphraseChecks()
{
QFETCH(QString, fileName);
+ QFETCH(QByteArray, passphrase);
QFile keyFile(fileName);
QVERIFY(keyFile.exists());
@@ -470,7 +517,7 @@ void tst_QSslKey::passphraseChecks()
keyFile.open(QIODevice::ReadOnly);
else
keyFile.reset();
- QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "123");
+ QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, passphrase);
QVERIFY(!key.isNull()); // correct passphrase
}
}
@@ -515,79 +562,135 @@ void tst_QSslKey::encrypt_data()
QTest::addColumn<QByteArray>("key");
QTest::addColumn<QByteArray>("plainText");
QTest::addColumn<QByteArray>("cipherText");
+ QTest::addColumn<QByteArray>("iv");
+ QByteArray iv("abcdefgh");
QTest::newRow("DES-CBC, length 0")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray()
- << QByteArray::fromHex("956585228BAF9B1F");
+ << QByteArray::fromHex("956585228BAF9B1F")
+ << iv;
QTest::newRow("DES-CBC, length 1")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(1, 'a')
- << QByteArray::fromHex("E6880AF202BA3C12");
+ << QByteArray::fromHex("E6880AF202BA3C12")
+ << iv;
QTest::newRow("DES-CBC, length 2")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(2, 'a')
- << QByteArray::fromHex("A82492386EED6026");
+ << QByteArray::fromHex("A82492386EED6026")
+ << iv;
QTest::newRow("DES-CBC, length 3")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(3, 'a')
- << QByteArray::fromHex("90B76D5B79519CBA");
+ << QByteArray::fromHex("90B76D5B79519CBA")
+ << iv;
QTest::newRow("DES-CBC, length 4")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(4, 'a')
- << QByteArray::fromHex("63E3DD6FED87052A");
+ << QByteArray::fromHex("63E3DD6FED87052A")
+ << iv;
QTest::newRow("DES-CBC, length 5")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(5, 'a')
- << QByteArray::fromHex("03ACDB0EACBDFA94");
+ << QByteArray::fromHex("03ACDB0EACBDFA94")
+ << iv;
QTest::newRow("DES-CBC, length 6")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(6, 'a')
- << QByteArray::fromHex("7D95024E42A3A88A");
+ << QByteArray::fromHex("7D95024E42A3A88A")
+ << iv;
QTest::newRow("DES-CBC, length 7")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(7, 'a')
- << QByteArray::fromHex("5003436B8A8E42E9");
+ << QByteArray::fromHex("5003436B8A8E42E9")
+ << iv;
QTest::newRow("DES-CBC, length 8")
<< QSslKeyPrivate::DesCbc << QByteArray("01234567")
<< QByteArray(8, 'a')
- << QByteArray::fromHex("E4C1F054BF5521C0A4A0FD4A2BC6C1B1");
+ << QByteArray::fromHex("E4C1F054BF5521C0A4A0FD4A2BC6C1B1")
+ << iv;
QTest::newRow("DES-EDE3-CBC, length 0")
<< QSslKeyPrivate::DesEde3Cbc << QByteArray("0123456789abcdefghijklmn")
<< QByteArray()
- << QByteArray::fromHex("3B2B4CD0B0FD495F");
+ << QByteArray::fromHex("3B2B4CD0B0FD495F")
+ << iv;
QTest::newRow("DES-EDE3-CBC, length 8")
<< QSslKeyPrivate::DesEde3Cbc << QByteArray("0123456789abcdefghijklmn")
<< QByteArray(8, 'a')
- << QByteArray::fromHex("F2A5A87763C54A72A3224103D90CDB03");
+ << QByteArray::fromHex("F2A5A87763C54A72A3224103D90CDB03")
+ << iv;
QTest::newRow("RC2-40-CBC, length 0")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("01234")
<< QByteArray()
- << QByteArray::fromHex("6D05D52392FF6E7A");
+ << QByteArray::fromHex("6D05D52392FF6E7A")
+ << iv;
QTest::newRow("RC2-40-CBC, length 8")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("01234")
<< QByteArray(8, 'a')
- << QByteArray::fromHex("75768E64C5749072A5D168F3AFEB0005");
+ << QByteArray::fromHex("75768E64C5749072A5D168F3AFEB0005")
+ << iv;
QTest::newRow("RC2-64-CBC, length 0")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("01234567")
<< QByteArray()
- << QByteArray::fromHex("ADAE6BF70F420130");
+ << QByteArray::fromHex("ADAE6BF70F420130")
+ << iv;
QTest::newRow("RC2-64-CBC, length 8")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("01234567")
<< QByteArray(8, 'a')
- << QByteArray::fromHex("C7BF5C80AFBE9FBEFBBB9FD935F6D0DF");
+ << QByteArray::fromHex("C7BF5C80AFBE9FBEFBBB9FD935F6D0DF")
+ << iv;
QTest::newRow("RC2-128-CBC, length 0")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("012345679abcdefg")
<< QByteArray()
- << QByteArray::fromHex("1E965D483A13C8FB");
+ << QByteArray::fromHex("1E965D483A13C8FB")
+ << iv;
QTest::newRow("RC2-128-CBC, length 8")
<< QSslKeyPrivate::Rc2Cbc << QByteArray("012345679abcdefg")
<< QByteArray(8, 'a')
- << QByteArray::fromHex("5AEC1A5B295660B02613454232F7DECE");
+ << QByteArray::fromHex("5AEC1A5B295660B02613454232F7DECE")
+ << iv;
+
+#if (!defined(QT_NO_OPENSSL) && !defined(OPENSSL_NO_AES)) || (defined(QT_NO_OPENSSL) && QT_CONFIG(ssl))
+ // AES needs a longer IV
+ iv = QByteArray("abcdefghijklmnop");
+ QTest::newRow("AES-128-CBC, length 0")
+ << QSslKeyPrivate::Aes128Cbc << QByteArray("012345679abcdefg")
+ << QByteArray()
+ << QByteArray::fromHex("28DE1A9AA26601C30DD2527407121D1A")
+ << iv;
+ QTest::newRow("AES-128-CBC, length 8")
+ << QSslKeyPrivate::Aes128Cbc << QByteArray("012345679abcdefg")
+ << QByteArray(8, 'a')
+ << QByteArray::fromHex("08E880B1BA916F061C1E801D7F44D0EC")
+ << iv;
+
+ QTest::newRow("AES-192-CBC, length 0")
+ << QSslKeyPrivate::Aes192Cbc << QByteArray("0123456789abcdefghijklmn")
+ << QByteArray()
+ << QByteArray::fromHex("E169E0E205CDC2BA895B7CF6097673B1")
+ << iv;
+ QTest::newRow("AES-192-CBC, length 8")
+ << QSslKeyPrivate::Aes192Cbc << QByteArray("0123456789abcdefghijklmn")
+ << QByteArray(8, 'a')
+ << QByteArray::fromHex("3A227D6A3A13237316D30AA17FF9B0A7")
+ << iv;
+
+ QTest::newRow("AES-256-CBC, length 0")
+ << QSslKeyPrivate::Aes256Cbc << QByteArray("0123456789abcdefghijklmnopqrstuv")
+ << QByteArray()
+ << QByteArray::fromHex("4BAACAA0D22199C97DE206C465B7B14A")
+ << iv;
+ QTest::newRow("AES-256-CBC, length 8")
+ << QSslKeyPrivate::Aes256Cbc << QByteArray("0123456789abcdefghijklmnopqrstuv")
+ << QByteArray(8, 'a')
+ << QByteArray::fromHex("879C8C25EC135CDF0B14490A0A7C2F67")
+ << iv;
+#endif // (OpenSSL && AES) || generic backend
}
void tst_QSslKey::encrypt()
@@ -596,13 +699,13 @@ void tst_QSslKey::encrypt()
QFETCH(QByteArray, key);
QFETCH(QByteArray, plainText);
QFETCH(QByteArray, cipherText);
- QByteArray iv("abcdefgh");
+ QFETCH(QByteArray, iv);
-#ifdef Q_OS_WINRT
- QEXPECT_FAIL("RC2-40-CBC, length 0", "WinRT treats RC2 as 128-bit", Abort);
- QEXPECT_FAIL("RC2-40-CBC, length 8", "WinRT treats RC2 as 128-bit", Abort);
- QEXPECT_FAIL("RC2-64-CBC, length 0", "WinRT treats RC2 as 128-bit", Abort);
- QEXPECT_FAIL("RC2-64-CBC, length 8", "WinRT treats RC2 as 128-bit", Abort);
+#if defined(Q_OS_WINRT) || QT_CONFIG(schannel)
+ QEXPECT_FAIL("RC2-40-CBC, length 0", "WinRT/Schannel treats RC2 as 128-bit", Abort);
+ QEXPECT_FAIL("RC2-40-CBC, length 8", "WinRT/Schannel treats RC2 as 128-bit", Abort);
+ QEXPECT_FAIL("RC2-64-CBC, length 0", "WinRT/Schannel treats RC2 as 128-bit", Abort);
+ QEXPECT_FAIL("RC2-64-CBC, length 8", "WinRT/Schannel treats RC2 as 128-bit", Abort);
#endif
QByteArray encrypted = QSslKeyPrivate::encrypt(cipher, plainText, key, iv);
QCOMPARE(encrypted, cipherText);
diff --git a/tests/auto/network/ssl/qsslsocket/BLACKLIST b/tests/auto/network/ssl/qsslsocket/BLACKLIST
index 555822d1e6..3ecd3d9dbb 100644
--- a/tests/auto/network/ssl/qsslsocket/BLACKLIST
+++ b/tests/auto/network/ssl/qsslsocket/BLACKLIST
@@ -1,7 +1,23 @@
+[abortOnSslErrors]
+windows
+[deprecatedProtocols]
+windows
+[disabledProtocols]
+windows
+[protocol]
+windows
+[qtbug18498_peek]
+windows
+[setReadBufferSize]
+windows
+[spontaneousWrite]
+windows
+[sslErrors]
windows
[connectToHostEncrypted]
osx-10.13
[setSslConfiguration]
+windows
osx-10.13
[connectToHostEncryptedWithVerificationPeerName]
osx-10.13
diff --git a/tests/auto/network/ssl/qsslsocket/certs/127-0-0-1-as-CN.crt b/tests/auto/network/ssl/qsslsocket/certs/127-0-0-1-as-CN.crt
new file mode 100644
index 0000000000..2253469392
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/certs/127-0-0-1-as-CN.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeagAwIBAgIJALBykhTMGxyEMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
+BAMMCTEyNy4wLjAuMTAeFw0xOTAxMjUyMjU5NDFaFw0xOTAyMjQyMjU5NDFaMBQx
+EjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBALMEo10Xd6e5ot4Rg99VejDV/WNdAhY6+2Ilzuc+1XdzDpEQCuqWY2hAGX9m
+QXyFSR+UcpJWoUFUtJLsArXgRnxT+seHuemrLZGZOkDStUhKNpxfwOmhIT+sLocw
+qXCwNf9oG4//3evGwGqJhLDpGUhTNVCAMaalb1yrcXskYEkWdelzCTMzoirVvbS2
+6PH3kE+WPaBehMFruLtp+v7btnVIA305DwFy4CLq+HHFq59BbxRWxhRSkfXM8w+d
+g05P3VNpEb8Apn4rQ+n/xRz7oZs0Aou4GZG5JAgiLOibbVBK+xnD/UW/txeFWfRZ
+1dzIi4yAKkdwIhPAg+pP1G6tgZMCAwEAAaNTMFEwHQYDVR0OBBYEFNGZZgb9dbVY
+FKkkoQp/oAQ2/B51MB8GA1UdIwQYMBaAFNGZZgb9dbVYFKkkoQp/oAQ2/B51MA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFvHy0RE96TDw6Q2pfCY
+aMz/X8dMAEMz5XqC7ImcztVg6VTRHpiw+QFQGqCLwNNuwkD9/pZ3IgVzSbRQw3oW
+HO7wD30NFl17LQMONBdcmR9FO5ruBh8G0Q1tmeKNtuwjzF3LAkj/J3tAn6eVmHi5
+75WEK/vQgy9XElN6EC6TgC/4B5/DPdZuEMdL7AP8ADLq9UVf8JC9c4QjU9G1Ce2R
+PzNwkhkLvtLlcxFcXciuc+oGhLENoJ2ZYHctT/ReOuBoRWEwIB1AeCWxitxjBZ6t
+lmZ+UewuzJ7y1X5maQZr7w3o8f6DwqwYrmMd45tS6jkHHAJlaCs/yCfVnLBwZ1l4
+NeM=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cert.pem b/tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cert.pem
new file mode 100644
index 0000000000..43c8794ce2
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cert.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIClTCCAf4CCQC2xMhNhwvATDANBgkqhkiG9w0BAQQFADCBjjELMAkGA1UEChMC
+UXQxGTAXBgNVBAsTEENvcmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5v
+Ym9keS5xdC5pbzENMAsGA1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UE
+BhMCTk8xHDAaBgNVBAMUEyoudGVzdC1uZXQucXQubG9jYWwwHhcNMTgwNzAxMTgz
+NjI3WhcNNDgwNjIzMTgzNjI3WjCBjjELMAkGA1UEChMCUXQxGTAXBgNVBAsTEENv
+cmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5vYm9keS5xdC5pbzENMAsG
+A1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UEBhMCTk8xHDAaBgNVBAMU
+EyoudGVzdC1uZXQucXQubG9jYWwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AM2q22/WNMmn8cC+5EEYGeICySLmp9W6Ay6eKHr0Xxp3X3epETuPfvAuxp7rOtkS
+18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt93CxGBXMIChiMPAsFeYzGa/D6xzAkfcR
+aJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJrgsgBfWrwHdxzAgMBAAEwDQYJKoZIhvcN
+AQEEBQADgYEAZu/lQPy8PXeyyYGamOVms/FZKJ48BH1y8KC3BeBU5FYnhvgG7pz8
+Wz9JKvt2t/r45wQeAkNL6HnGUBhPJsHMjPHl5KktqN+db3D+FQygBeS2V1+zmC0X
+UZNRE4aWiHvt1Lq+pTx89SOMOpfqWfh4qTQKiE5jC2V4DeCNQ3u7uI8=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslsocket/certs/subjectAltNameIP.crt b/tests/auto/network/ssl/qsslsocket/certs/subjectAltNameIP.crt
new file mode 100644
index 0000000000..1377fbbabb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/certs/subjectAltNameIP.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhigAwIBAgIURWaTvdnvU+Y+gPSONs61cMCH8JUwDQYJKoZIhvcNAQEL
+BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5vcmcwHhcNMTkwMTA4MTExMDMxWhcNMTkw
+MjA3MTExMDMxWjAWMRQwEgYDVQQDDAtleGFtcGxlLm9yZzCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBALf0qv9vl8RqvDHpEWfjum7DMrY8qrQnD77C/9f/
+Jl0Jo4UZiSBr1OYYVbiWJyodw8LpQQsKE+fQCo2STb5X9BldJpwpQvvVi6ygxdzN
+erJnB15G7xhUkGzDI2xhIJw3e6NGqf1PMB4CTNna6eN2cKYAxPfsWo5Pyh1YtU4s
+5h+B3+43ol32ccBiRo4YXagbYMELjspEf0AvObvMWSxZQoBHcJ5JGEApxcgvFu8i
+FBSALVy1IrYE3gXAv8TB0AK7IpuNIL48v5JXCA6JOGYbXFljj6aLFTzfrV3lzhQ0
+kqBVnQNqVfOUQNUhNT93bnEWVf911j/af5zuFtmr1kbMzucCAwEAAaN2MHQwHQYD
+VR0OBBYEFHZOtGQHV3roaj3nlQ1XRU0O+05TMB8GA1UdIwQYMBaAFHZOtGQHV3ro
+aj3nlQ1XRU0O+05TMA8GA1UdEwEB/wQFMAMBAf8wIQYDVR0RBBowGIcEwAUIEIcQ
+/oAAAAAAAAA8KS+h3UQHZTANBgkqhkiG9w0BAQsFAAOCAQEAcvqvtUSJ2JM3rrWj
+XjCOhosKY/cow4oDAVdn8AvI/Z4FJfcQZ1vA+ZM533/TaJStG4ThfjyX9t1Ej08M
+UzP4ZUyXJTv8o6C6j5e9ggEwo/cFp1iWP+xr2SXLJ2cabnu8db5FN5J75HjNsuVs
+PM95LYY9VlTm9W7JxMwkPEIG+wH5zu6Hj45UAAamwwjOKT1hJYumxdmLAp1oyG1p
+u86b8iVUjiHG+K6qr4hAKXhuSXE1s/pYqcn1feyk2SbkKvGFR6ad+gmdT4ZaiNYT
+nL8+t2wim/fRkV0CNdWrrJpWtLzjPq1al7g2eIopdLufSlqanouVpnzwuKGN5QC/
+MuDohA==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
index 1260dc9410..51fcff9a8d 100644
--- a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
+++ b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
@@ -18,3 +18,10 @@ TESTDATA += certs
DEFINES += SRCDIR=\\\"$$PWD/\\\"
requires(qtConfig(private_tests))
+
+# DOCKERTODO: it's 'linux' because it requires cyrus, which
+# is linux-only for now ...
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = squid danted cyrus apache2 echo
+}
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index 7420cd1296..b05f989b5c 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -29,6 +29,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qthread.h>
+#include <QtCore/qelapsedtimer.h>
#include <QtNetwork/qhostaddress.h>
#include <QtNetwork/qhostinfo.h>
#include <QtNetwork/qnetworkproxy.h>
@@ -74,6 +75,16 @@ typedef QSharedPointer<QSslSocket> QSslSocketPtr;
#endif
#endif // QT_NO_SSL
+// Detect ALPN (Application-Layer Protocol Negotiation) support
+#undef ALPN_SUPPORTED // Undef the variable first to be safe
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT)
+#define ALPN_SUPPORTED 1
+#endif
+
+#if QT_CONFIG(schannel) && !defined(Q_CC_MINGW)
+#define ALPN_SUPPORTED 1
+#endif
+
#if defined Q_OS_HPUX && defined Q_CC_GNU
// This error is delivered every time we try to use the fluke CA
// certificate. For now we work around this bug. Task 202317.
@@ -233,18 +244,22 @@ private slots:
void verifyClientCertificate();
void readBufferMaxSize();
+ void allowedProtocolNegotiation();
+
#ifndef QT_NO_OPENSSL
void simplePskConnect_data();
void simplePskConnect();
void ephemeralServerKey_data();
void ephemeralServerKey();
- void allowedProtocolNegotiation();
void pskServer();
void forwardReadChannelFinished();
void signatureAlgorithm_data();
void signatureAlgorithm();
#endif
+ void disabledProtocols_data();
+ void disabledProtocols();
+
void setEmptyDefaultConfiguration(); // this test should be last
protected slots:
@@ -296,6 +311,21 @@ Q_DECLARE_METATYPE(tst_QSslSocket::PskConnectTestType)
int tst_QSslSocket::loopLevel = 0;
+namespace {
+
+QString httpServerCertChainPath()
+{
+ // DOCKERTODO: note how we use CA certificate on the real server. The docker container
+ // is using a different cert with a "special" CN. Check if it's important!
+#ifdef QT_TEST_SERVER
+ return tst_QSslSocket::testDataDir + QStringLiteral("certs/qt-test-server-cert.pem");
+#else
+ return tst_QSslSocket::testDataDir + QStringLiteral("certs/qt-test-server-cacert.pem");
+#endif // QT_TEST_SERVER
+}
+
+} // unnamed namespace
+
tst_QSslSocket::tst_QSslSocket()
{
#ifndef QT_NO_SSL
@@ -349,8 +379,19 @@ void tst_QSslSocket::initTestCase()
qDebug("Using SSL library %s (%ld)",
qPrintable(QSslSocket::sslLibraryVersionString()),
QSslSocket::sslLibraryVersionNumber());
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1081));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3129));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3130));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 443));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 993));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::echoServerName(), 13));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
-#endif
+#endif // QT_TEST_SERVER
+#endif // QT_NO_SSL
}
void tst_QSslSocket::init()
@@ -359,28 +400,29 @@ void tst_QSslSocket::init()
if (setProxy) {
#ifndef QT_NO_NETWORKPROXY
QFETCH_GLOBAL(int, proxyType);
- QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
+ const QString socksProxyAddr = QtNetworkSettings::socksProxyServerIp().toString();
+ const QString httpProxyAddr = QtNetworkSettings::httpProxyServerIp().toString();
QNetworkProxy proxy;
switch (proxyType) {
case Socks5Proxy:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksProxyAddr, 1080);
break;
case Socks5Proxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksProxyAddr, 1081);
break;
case HttpProxy | NoAuth:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddr, 3128);
break;
case HttpProxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddr, 3129);
break;
case HttpProxy | AuthNtlm:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, httpProxyAddr, 3130);
break;
}
QNetworkProxy::setApplicationProxy(proxy);
@@ -541,7 +583,7 @@ void tst_QSslSocket::simpleConnect()
connect(&socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(exitLoop()));
// Start connecting
- socket.connectToHost(QtNetworkSettings::serverName(), 993);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 993);
QCOMPARE(socket.state(), QAbstractSocket::HostLookupState);
enterLoop(10);
@@ -596,7 +638,7 @@ void tst_QSslSocket::simpleConnectWithIgnore()
connect(&socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(exitLoop()));
// Start connecting
- socket.connectToHost(QtNetworkSettings::serverName(), 993);
+ socket.connectToHost(QtNetworkSettings::imapServerName(), 993);
QVERIFY(socket.state() != QAbstractSocket::UnconnectedState); // something must be in progress
enterLoop(10);
@@ -628,7 +670,7 @@ void tst_QSslSocket::sslErrors_data()
QString name = QtNetworkSettings::serverLocalName();
QTest::newRow(qPrintable(name)) << name << 993;
- name = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
+ name = QtNetworkSettings::httpServerIp().toString();
QTest::newRow(qPrintable(name)) << name << 443;
}
@@ -638,10 +680,27 @@ void tst_QSslSocket::sslErrors()
QFETCH(int, port);
QSslSocketPtr socket = newSocket();
+#if QT_CONFIG(schannel)
+ // Needs to be < 1.2 because of the old certificate and <= 1.0 because of the mail server
+ socket->setProtocol(QSsl::SslProtocol::TlsV1_0);
+#endif
QSignalSpy sslErrorsSpy(socket.data(), SIGNAL(sslErrors(QList<QSslError>)));
QSignalSpy peerVerifyErrorSpy(socket.data(), SIGNAL(peerVerifyError(QSslError)));
- socket->connectToHostEncrypted(host, port);
+#ifdef QT_TEST_SERVER
+ // On the old test server we had the same certificate on different services.
+ // The idea of this test is to fail with 'HostNameMismatch', when we're using
+ // either serverLocalName() or IP address directly. With Docker we connect
+ // to IMAP server, and we have to connect using imapServerName() and passing
+ // 'host' as peerVerificationName to the overload of connectToHostEncrypted().
+ if (port == 993) {
+ socket->connectToHostEncrypted(QtNetworkSettings::imapServerName(), port, host);
+ } else
+#endif // QT_TEST_SERVER
+ {
+ socket->connectToHostEncrypted(host, port);
+ }
+
if (!socket->waitForConnected())
QSKIP("Skipping flaky test - See QTBUG-29941");
socket->waitForEncrypted(10000);
@@ -717,14 +776,17 @@ void tst_QSslSocket::connectToHostEncrypted()
return;
QSslSocketPtr socket = newSocket();
+#if QT_CONFIG(schannel) // old certificate not supported with TLS 1.2
+ socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
+#endif
this->socket = socket.data();
- QVERIFY(socket->addCaCertificates(testDataDir + "certs/qt-test-server-cacert.pem"));
+ QVERIFY(socket->addCaCertificates(httpServerCertChainPath()));
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
connect(socket.data(), SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
#endif
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
// This should pass unconditionally when using fluke's CA certificate.
// or use untrusted certificate workaround
@@ -737,7 +799,7 @@ void tst_QSslSocket::connectToHostEncrypted()
QCOMPARE(socket->mode(), QSslSocket::SslClientMode);
- socket->connectToHost(QtNetworkSettings::serverName(), 13);
+ socket->connectToHost(QtNetworkSettings::echoServerName(), 13);
QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
@@ -750,16 +812,23 @@ void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName()
return;
QSslSocketPtr socket = newSocket();
+#if QT_CONFIG(schannel) // old certificate not supported with TLS 1.2
+ socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
+#endif
this->socket = socket.data();
- socket->addCaCertificates(testDataDir + "certs/qt-test-server-cacert.pem");
+ socket->addCaCertificates(httpServerCertChainPath());
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
connect(socket.data(), SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
#endif
- // connect to the server with its local name, but use the full name for verification.
- socket->connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443, QtNetworkSettings::serverName());
+#ifdef QT_TEST_SERVER
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443, QtNetworkSettings::httpServerName());
+#else
+ // Connect to the server with its local name, but use the full name for verification.
+ socket->connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443, QtNetworkSettings::httpServerName());
+#endif
// This should pass unconditionally when using fluke's CA certificate.
QFETCH_GLOBAL(bool, setProxy);
@@ -781,7 +850,7 @@ void tst_QSslSocket::sessionCipher()
this->socket = socket.data();
connect(socket.data(), SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
QVERIFY(socket->sessionCipher().isNull());
- socket->connectToHost(QtNetworkSettings::serverName(), 443 /* https */);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443 /* https */);
QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
QVERIFY(socket->sessionCipher().isNull());
socket->startClientEncryption();
@@ -816,12 +885,12 @@ void tst_QSslSocket::localCertificate()
// values. This test should just run the codepath inside qsslsocket_openssl.cpp
QSslSocketPtr socket = newSocket();
- QList<QSslCertificate> localCert = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> localCert = QSslCertificate::fromPath(httpServerCertChainPath());
socket->setCaCertificates(localCert);
socket->setLocalCertificate(testDataDir + "certs/fluke.cert");
socket->setPrivateKey(testDataDir + "certs/fluke.key");
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(10000))
QSKIP("Skipping flaky test - See QTBUG-29941");
@@ -844,8 +913,7 @@ void tst_QSslSocket::peerCertificateChain()
QSslSocketPtr socket = newSocket();
this->socket = socket.data();
-
- QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(httpServerCertChainPath());
QCOMPARE(caCertificates.count(), 1);
socket->addCaCertificates(caCertificates);
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
@@ -853,7 +921,7 @@ void tst_QSslSocket::peerCertificateChain()
this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
#endif
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
QVERIFY(socket->peerCertificateChain().isEmpty());
QFETCH_GLOBAL(bool, setProxy);
@@ -882,7 +950,7 @@ void tst_QSslSocket::peerCertificateChain()
QVERIFY(socket->waitForDisconnected());
// now do it again back to the original server
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
QVERIFY(socket->peerCertificateChain().isEmpty());
QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
@@ -921,13 +989,13 @@ void tst_QSslSocket::privateKeyOpaque()
// values. This test should just run the codepath inside qsslsocket_openssl.cpp
QSslSocketPtr socket = newSocket();
- QList<QSslCertificate> localCert = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> localCert = QSslCertificate::fromPath(httpServerCertChainPath());
socket->setCaCertificates(localCert);
socket->setLocalCertificate(testDataDir + "certs/fluke.cert");
socket->setPrivateKey(QSslKey(reinterpret_cast<Qt::HANDLE>(pkey)));
socket->setPeerVerifyMode(QSslSocket::QueryPeer);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(10000))
QSKIP("Skipping flaky test - See QTBUG-29941");
@@ -941,7 +1009,7 @@ void tst_QSslSocket::protocol()
QSslSocketPtr socket = newSocket();
this->socket = socket.data();
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(httpServerCertChainPath());
socket->setCaCertificates(certs);
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
@@ -952,34 +1020,16 @@ void tst_QSslSocket::protocol()
QCOMPARE(socket->protocol(), QSsl::SecureProtocols);
QFETCH_GLOBAL(bool, setProxy);
{
- // qt-test-server allows SSLv3.
- socket->setProtocol(QSsl::SslV3);
- QCOMPARE(socket->protocol(), QSsl::SslV3);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
- if (setProxy && !socket->waitForEncrypted())
- QSKIP("Skipping flaky test - See QTBUG-29941");
- QCOMPARE(socket->protocol(), QSsl::SslV3);
- socket->abort();
- QCOMPARE(socket->protocol(), QSsl::SslV3);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
- QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
- socket->startClientEncryption();
- if (setProxy && !socket->waitForEncrypted())
- QSKIP("Skipping flaky test - See QTBUG-29941");
- QCOMPARE(socket->protocol(), QSsl::SslV3);
- socket->abort();
- }
- {
// qt-test-server allows TLSV1.
socket->setProtocol(QSsl::TlsV1_0);
QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
@@ -992,13 +1042,13 @@ void tst_QSslSocket::protocol()
// qt-test-server probably doesn't allow TLSV1.1
socket->setProtocol(QSsl::TlsV1_1);
QCOMPARE(socket->protocol(), QSsl::TlsV1_1);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1_1);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1_1);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
@@ -1010,13 +1060,13 @@ void tst_QSslSocket::protocol()
// qt-test-server probably doesn't allows TLSV1.2
socket->setProtocol(QSsl::TlsV1_2);
QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
@@ -1030,13 +1080,13 @@ void tst_QSslSocket::protocol()
// qt-test-server probably doesn't allow TLSV1.3
socket->setProtocol(QSsl::TlsV1_3);
QCOMPARE(socket->protocol(), QSsl::TlsV1_3);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("TLS 1.3 is not supported by the test server or the test is flaky - see QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1_3);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1_3);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
@@ -1045,37 +1095,17 @@ void tst_QSslSocket::protocol()
socket->abort();
}
#endif // TLS1_3_VERSION
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- {
- // qt-test-server allows SSLV2.
- socket->setProtocol(QSsl::SslV2);
- QCOMPARE(socket->protocol(), QSsl::SslV2);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
- if (setProxy && !socket->waitForEncrypted())
- QSKIP("Skipping flaky test - See QTBUG-29941");
- QCOMPARE(socket->protocol(), QSsl::SslV2);
- socket->abort();
- QCOMPARE(socket->protocol(), QSsl::SslV2);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
- if (setProxy && !socket->waitForConnected())
- QSKIP("Skipping flaky test - See QTBUG-29941");
- socket->startClientEncryption();
- if (setProxy && !socket->waitForEncrypted())
- QSKIP("Skipping flaky test - See QTBUG-29941");
- socket->abort();
- }
-#endif
{
// qt-test-server allows SSLV3, so it allows AnyProtocol.
socket->setProtocol(QSsl::AnyProtocol);
QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
@@ -1084,16 +1114,16 @@ void tst_QSslSocket::protocol()
socket->abort();
}
{
- // qt-test-server allows SSLV3, so it allows NoSslV2
+ // qt-test-server allows TlsV1, so it allows TlsV1SslV3
socket->setProtocol(QSsl::TlsV1SslV3);
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
- socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ socket->connectToHost(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForConnected())
QSKIP("Skipping flaky test - See QTBUG-29941");
socket->startClientEncryption();
@@ -1207,120 +1237,38 @@ void tst_QSslSocket::protocolServerSide_data()
QTest::addColumn<QSsl::SslProtocol>("clientProtocol");
QTest::addColumn<bool>("works");
-#if QT_CONFIG(opensslv11)
-#if !defined(OPENSSL_NO_SSL2)
- // OpenSSL 1.1 has removed SSL2 support. But there is no OPENSSL_NO_SSL2 macro ...
-#define OPENSSL_NO_SSL2
-#endif // OPENSSL_NO_SSL2
-#endif // opensslv11
-
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("ssl2-ssl2") << QSsl::SslV2 << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2
-#endif
-#if !defined(OPENSSL_NO_SSL3)
- QTest::newRow("ssl3-ssl3") << QSsl::SslV3 << QSsl::SslV3 << true;
-#endif
QTest::newRow("tls1.0-tls1.0") << QSsl::TlsV1_0 << QSsl::TlsV1_0 << true;
QTest::newRow("tls1ssl3-tls1ssl3") << QSsl::TlsV1SslV3 << QSsl::TlsV1SslV3 << true;
QTest::newRow("any-any") << QSsl::AnyProtocol << QSsl::AnyProtocol << true;
QTest::newRow("secure-secure") << QSsl::SecureProtocols << QSsl::SecureProtocols << true;
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("ssl2-ssl3") << QSsl::SslV2 << QSsl::SslV3 << false;
- QTest::newRow("ssl2-tls1.0") << QSsl::SslV2 << QSsl::TlsV1_0 << false;
- QTest::newRow("ssl2-tls1ssl3") << QSsl::SslV2 << QSsl::TlsV1SslV3 << false;
- QTest::newRow("ssl2-secure") << QSsl::SslV2 << QSsl::SecureProtocols << false;
- QTest::newRow("ssl2-any") << QSsl::SslV2 << QSsl::AnyProtocol << false; // no idea why it does not work, but we don't care about SSL 2
-#endif
-
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) && !defined(OPENSSL_NO_SSL3)
- QTest::newRow("ssl3-ssl2") << QSsl::SslV3 << QSsl::SslV2 << false;
-#endif
-#if !defined(OPENSSL_NO_SSL3)
- QTest::newRow("ssl3-tls1.0") << QSsl::SslV3 << QSsl::TlsV1_0 << false;
- QTest::newRow("ssl3-tls1ssl3") << QSsl::SslV3 << QSsl::TlsV1SslV3 << true;
- QTest::newRow("ssl3-secure") << QSsl::SslV3 << QSsl::SecureProtocols << false;
-#endif
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) && !defined(OPENSSL_NO_SSL3)
- QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << false; // we won't set a SNI header here because we connect to a
- // numerical IP, so OpenSSL will send a SSL 2 handshake
-#elif !defined(OPENSSL_NO_SSL3)
- QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << true;
-#endif
-
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("tls1.0-ssl2") << QSsl::TlsV1_0 << QSsl::SslV2 << false;
-#endif
-#if !defined(OPENSSL_NO_SSL3)
- QTest::newRow("tls1.0-ssl3") << QSsl::TlsV1_0 << QSsl::SslV3 << false;
-#endif
QTest::newRow("tls1-tls1ssl3") << QSsl::TlsV1_0 << QSsl::TlsV1SslV3 << true;
QTest::newRow("tls1.0-secure") << QSsl::TlsV1_0 << QSsl::SecureProtocols << true;
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("tls1.0-any") << QSsl::TlsV1_0 << QSsl::AnyProtocol << false; // we won't set a SNI header here because we connect to a
- // numerical IP, so OpenSSL will send a SSL 2 handshake
-#else
QTest::newRow("tls1.0-any") << QSsl::TlsV1_0 << QSsl::AnyProtocol << true;
-#endif
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("tls1ssl3-ssl2") << QSsl::TlsV1SslV3 << QSsl::SslV2 << false;
-#endif
-#if !defined(OPENSSL_NO_SSL3)
- QTest::newRow("tls1ssl3-ssl3") << QSsl::TlsV1SslV3 << QSsl::SslV3 << true;
-#endif
QTest::newRow("tls1ssl3-tls1.0") << QSsl::TlsV1SslV3 << QSsl::TlsV1_0 << true;
QTest::newRow("tls1ssl3-secure") << QSsl::TlsV1SslV3 << QSsl::SecureProtocols << true;
QTest::newRow("tls1ssl3-any") << QSsl::TlsV1SslV3 << QSsl::AnyProtocol << true;
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("secure-ssl2") << QSsl::SecureProtocols << QSsl::SslV2 << false;
-#endif
-#if !defined(OPENSSL_NO_SSL3)
- QTest::newRow("secure-ssl3") << QSsl::SecureProtocols << QSsl::SslV3 << false;
-#endif
QTest::newRow("secure-tls1.0") << QSsl::SecureProtocols << QSsl::TlsV1_0 << true;
QTest::newRow("secure-tls1ssl3") << QSsl::SecureProtocols << QSsl::TlsV1SslV3 << true;
QTest::newRow("secure-any") << QSsl::SecureProtocols << QSsl::AnyProtocol << true;
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("any-ssl2") << QSsl::AnyProtocol << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2
-#endif
-#if !defined(OPENSSL_NO_SSL3)
- QTest::newRow("any-ssl3") << QSsl::AnyProtocol << QSsl::SslV3 << true;
-#endif
-
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("tls1.0orlater-ssl2") << QSsl::TlsV1_0OrLater << QSsl::SslV2 << false;
-#endif
-#if !defined(OPENSSL_NO_SSL3)
- QTest::newRow("tls1.0orlater-ssl3") << QSsl::TlsV1_0OrLater << QSsl::SslV3 << false;
-#endif
QTest::newRow("tls1.0orlater-tls1.0") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_0 << true;
QTest::newRow("tls1.0orlater-tls1.1") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_1 << true;
QTest::newRow("tls1.0orlater-tls1.2") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_2 << true;
#ifdef TLS1_3_VERSION
QTest::newRow("tls1.0orlater-tls1.3") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_3 << true;
#endif
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("tls1.1orlater-ssl2") << QSsl::TlsV1_1OrLater << QSsl::SslV2 << false;
-#endif
-#if !defined(OPENSSL_NO_SSL3)
- QTest::newRow("tls1.1orlater-ssl3") << QSsl::TlsV1_1OrLater << QSsl::SslV3 << false;
-#endif
QTest::newRow("tls1.1orlater-tls1.0") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_0 << false;
QTest::newRow("tls1.1orlater-tls1.1") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_1 << true;
QTest::newRow("tls1.1orlater-tls1.2") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_2 << true;
+
#ifdef TLS1_3_VERSION
QTest::newRow("tls1.1orlater-tls1.3") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_3 << true;
#endif
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("tls1.2orlater-ssl2") << QSsl::TlsV1_2OrLater << QSsl::SslV2 << false;
-#endif
-#if !defined(OPENSSL_NO_SSL3)
- QTest::newRow("tls1.2orlater-ssl3") << QSsl::TlsV1_2OrLater << QSsl::SslV3 << false;
-#endif
+
QTest::newRow("tls1.2orlater-tls1.0") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_0 << false;
QTest::newRow("tls1.2orlater-tls1.1") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_1 << false;
QTest::newRow("tls1.2orlater-tls1.2") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_2 << true;
@@ -1328,12 +1276,6 @@ void tst_QSslSocket::protocolServerSide_data()
QTest::newRow("tls1.2orlater-tls1.3") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_3 << true;
#endif
#ifdef TLS1_3_VERSION
-#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
- QTest::newRow("tls1.3orlater-ssl2") << QSsl::TlsV1_3OrLater << QSsl::SslV2 << false;
-#endif
-#if !defined(OPENSSL_NO_SSL3)
- QTest::newRow("tls1.3orlater-ssl3") << QSsl::TlsV1_3OrLater << QSsl::SslV3 << false;
-#endif
QTest::newRow("tls1.3orlater-tls1.0") << QSsl::TlsV1_3OrLater << QSsl::TlsV1_0 << false;
QTest::newRow("tls1.3orlater-tls1.1") << QSsl::TlsV1_3OrLater << QSsl::TlsV1_1 << false;
QTest::newRow("tls1.3orlater-tls1.2") << QSsl::TlsV1_3OrLater << QSsl::TlsV1_2 << false;
@@ -1389,10 +1331,10 @@ void tst_QSslSocket::protocolServerSide()
if (server.socket)
QVERIFY(server.socket->error() == QAbstractSocket::UnknownSocketError);
- QCOMPARE(int(client.state()), int(expectedState));
+ QCOMPARE(client.state(), expectedState);
} else if (server.socket->error() != QAbstractSocket::UnknownSocketError) {
QVERIFY(client.error() == QAbstractSocket::UnknownSocketError);
- QCOMPARE(int(server.socket->state()), int(expectedState));
+ QCOMPARE(server.socket->state(), expectedState);
}
QCOMPARE(client.isEncrypted(), works);
@@ -1536,6 +1478,11 @@ void tst_QSslSocket::setLocalCertificateChain()
loop.exec();
QList<QSslCertificate> chain = socket->peerCertificateChain();
+#if QT_CONFIG(schannel)
+ QEXPECT_FAIL("", "Schannel cannot send intermediate certificates not "
+ "located in a system certificate store",
+ Abort);
+#endif
QCOMPARE(chain.size(), 2);
QCOMPARE(chain[0].serialNumber(), QByteArray("10:a0:ad:77:58:f6:6e:ae:46:93:a3:43:f9:59:8a:9e"));
QCOMPARE(chain[1].serialNumber(), QByteArray("3b:eb:99:c5:ea:d8:0b:5d:0b:97:5d:4f:06:75:4b:e1"));
@@ -1588,7 +1535,7 @@ void tst_QSslSocket::setSslConfiguration_data()
QTest::newRow("empty") << QSslConfiguration() << false;
QSslConfiguration conf = QSslConfiguration::defaultConfiguration();
QTest::newRow("default") << conf << false; // does not contain test server cert
- QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(httpServerCertChainPath());
conf.setCaCertificates(testServerCert);
QTest::newRow("set-root-cert") << conf << true;
conf.setProtocol(QSsl::SecureProtocols);
@@ -1603,8 +1550,11 @@ void tst_QSslSocket::setSslConfiguration()
QSslSocketPtr socket = newSocket();
QFETCH(QSslConfiguration, configuration);
socket->setSslConfiguration(configuration);
+#if QT_CONFIG(schannel) // old certificate not supported with TLS 1.2
+ socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
+#endif
this->socket = socket.data();
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH(bool, works);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && (socket->waitForEncrypted(10000) != works))
@@ -1624,7 +1574,7 @@ void tst_QSslSocket::waitForEncrypted()
this->socket = socket.data();
connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(10000))
@@ -1643,7 +1593,7 @@ void tst_QSslSocket::waitForEncryptedMinusOne()
this->socket = socket.data();
connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(-1))
@@ -1659,7 +1609,7 @@ void tst_QSslSocket::waitForConnectedEncryptedReadyRead()
this->socket = socket.data();
connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+ socket->connectToHostEncrypted(QtNetworkSettings::imapServerName(), 993);
QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
QFETCH_GLOBAL(bool, setProxy);
@@ -1691,7 +1641,7 @@ void tst_QSslSocket::addDefaultCaCertificate()
// Reset the global CA chain
QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
- QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(httpServerCertChainPath());
QCOMPARE(flukeCerts.size(), 1);
QList<QSslCertificate> globalCerts = QSslSocket::defaultCaCertificates();
QVERIFY(!globalCerts.contains(flukeCerts.first()));
@@ -1815,6 +1765,25 @@ void tst_QSslSocket::isMatchingHostname()
QCOMPARE(QSslSocketPrivate::isMatchingHostname(cert, QString::fromUtf8("foo.foo.xn--schufele-2za.de")), false);
QCOMPARE(QSslSocketPrivate::isMatchingHostname(cert, QString::fromUtf8("www.schaufele.de")), false);
QCOMPARE(QSslSocketPrivate::isMatchingHostname(cert, QString::fromUtf8("www.schufele.de")), false);
+
+ /* Generated with the following command (only valid with openssl >= 1.1.1 due to "-addext"):
+ openssl req -x509 -nodes -subj "/CN=example.org" \
+ -addext "subjectAltName = IP:192.5.8.16, IP:fe80::3c29:2fa1:dd44:765" \
+ -newkey rsa:2048 -keyout /dev/null -out subjectAltNameIP.crt
+ */
+ certs = QSslCertificate::fromPath(testDataDir + "certs/subjectAltNameIP.crt");
+ QVERIFY(!certs.isEmpty());
+ cert = certs.first();
+ QCOMPARE(QSslSocketPrivate::isMatchingHostname(cert, QString::fromUtf8("192.5.8.16")), true);
+ QCOMPARE(QSslSocketPrivate::isMatchingHostname(cert, QString::fromUtf8("fe80::3c29:2fa1:dd44:765")), true);
+
+ /* openssl req -x509 -nodes -new -newkey rsa -keyout /dev/null -out 127-0-0-1-as-CN.crt \
+ -subj "/CN=127.0.0.1"
+ */
+ certs = QSslCertificate::fromPath(testDataDir + "certs/127-0-0-1-as-CN.crt");
+ QVERIFY(!certs.isEmpty());
+ cert = certs.first();
+ QCOMPARE(QSslSocketPrivate::isMatchingHostname(cert, QString::fromUtf8("127.0.0.1")), true);
}
void tst_QSslSocket::wildcard()
@@ -2021,7 +1990,7 @@ public slots:
QTestEventLoop::instance().exitLoop();
}
void waitSomeMore(QSslSocket *socket) {
- QTime t;
+ QElapsedTimer t;
t.start();
while (!socket->encryptedBytesAvailable()) {
QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 250);
@@ -2043,7 +2012,7 @@ void tst_QSslSocket::setReadBufferSize_task_250027()
QSslSocketPtr socket = newSocket();
socket->setReadBufferSize(1000); // limit to 1 kb/sec
socket->ignoreSslErrors();
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
socket->ignoreSslErrors();
QVERIFY2(socket->waitForConnected(10*1000), qPrintable(socket->errorString()));
if (setProxy && !socket->waitForEncrypted(10*1000))
@@ -2056,7 +2025,7 @@ void tst_QSslSocket::setReadBufferSize_task_250027()
// provoke a response by sending a request
socket->write("GET /qtest/fluke.gif HTTP/1.0\n"); // this file is 27 KB
socket->write("Host: ");
- socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData());
+ socket->write(QtNetworkSettings::httpServerName().toLocal8Bit().constData());
socket->write("\n");
socket->write("Connection: close\n");
socket->write("\n");
@@ -2297,6 +2266,9 @@ void tst_QSslSocket::verifyMode()
return;
QSslSocket socket;
+#if QT_CONFIG(schannel) // old certificate not supported with TLS 1.2
+ socket.setProtocol(QSsl::SslProtocol::TlsV1_1);
+#endif
QCOMPARE(socket.peerVerifyMode(), QSslSocket::AutoVerifyPeer);
socket.setPeerVerifyMode(QSslSocket::VerifyNone);
QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyNone);
@@ -2304,7 +2276,7 @@ void tst_QSslSocket::verifyMode()
socket.setPeerVerifyMode(QSslSocket::VerifyPeer);
QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyPeer);
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (socket.waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
@@ -2343,7 +2315,7 @@ void tst_QSslSocket::verifyDepth()
void tst_QSslSocket::disconnectFromHostWhenConnecting()
{
QSslSocketPtr socket = newSocket();
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+ socket->connectToHostEncrypted(QtNetworkSettings::imapServerName(), 993);
socket->ignoreSslErrors();
socket->write("XXXX LOGOUT\r\n");
QAbstractSocket::SocketState state = socket->state();
@@ -2372,7 +2344,7 @@ void tst_QSslSocket::disconnectFromHostWhenConnecting()
void tst_QSslSocket::disconnectFromHostWhenConnected()
{
QSslSocketPtr socket = newSocket();
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+ socket->connectToHostEncrypted(QtNetworkSettings::imapServerName(), 993);
socket->ignoreSslErrors();
if (!socket->waitForEncrypted(5000))
QSKIP("Skipping flaky test - See QTBUG-29941");
@@ -2459,13 +2431,13 @@ void tst_QSslSocket::resetProxy()
// make sure the connection works, and then set a nonsense proxy, and then
// make sure it does not work anymore
QSslSocket socket;
- socket.addCaCertificates(testDataDir + "certs/qt-test-server-cacert.pem");
+ socket.addCaCertificates(httpServerCertChainPath());
socket.setProxy(goodProxy);
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket.waitForConnected(10000), qPrintable(socket.errorString()));
socket.abort();
socket.setProxy(badProxy);
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QVERIFY(! socket.waitForConnected(10000));
// don't forget to login
@@ -2478,13 +2450,13 @@ void tst_QSslSocket::resetProxy()
// set the nonsense proxy and make sure the connection does not work,
// and then set the right proxy and make sure it works
QSslSocket socket2;
- socket2.addCaCertificates(testDataDir + "certs/qt-test-server-cacert.pem");
+ socket2.addCaCertificates(httpServerCertChainPath());
socket2.setProxy(badProxy);
- socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket2.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QVERIFY(! socket2.waitForConnected(10000));
socket2.abort();
socket2.setProxy(goodProxy);
- socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket2.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString()));
#endif // QT_NO_NETWORKPROXY
}
@@ -2497,7 +2469,7 @@ void tst_QSslSocket::ignoreSslErrorsList_data()
// construct the list of errors that we will get with the SSL handshake and that we will ignore
QList<QSslError> expectedSslErrors;
// fromPath gives us a list of certs, but it actually only contains one
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(httpServerCertChainPath());
QSslError rightError(FLUKE_CERTIFICATE_ERROR, certs.at(0));
QSslError wrongError(FLUKE_CERTIFICATE_ERROR);
@@ -2528,7 +2500,7 @@ void tst_QSslSocket::ignoreSslErrorsList()
QFETCH(int, expectedSslErrorSignalCount);
QSignalSpy sslErrorsSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
if (socket.waitForEncrypted(10000) != expectEncryptionSuccess)
@@ -2559,7 +2531,7 @@ void tst_QSslSocket::ignoreSslErrorsListWithSlot()
this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(&socket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(ignoreErrorListSlot(QList<QSslError>)));
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH(int, expectedSslErrorSignalCount);
bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
@@ -2597,15 +2569,18 @@ void tst_QSslSocket::abortOnSslErrors()
void tst_QSslSocket::readFromClosedSocket()
{
QSslSocketPtr socket = newSocket();
+#if QT_CONFIG(schannel) // old certificate not supported with TLS 1.2
+ socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
+#endif
socket->ignoreSslErrors();
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
socket->ignoreSslErrors();
socket->waitForConnected();
socket->waitForEncrypted();
// provoke a response by sending a request
socket->write("GET /qtest/fluke.gif HTTP/1.1\n");
socket->write("Host: ");
- socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData());
+ socket->write(QtNetworkSettings::httpServerName().toLocal8Bit().constData());
socket->write("\n");
socket->write("\n");
socket->waitForBytesWritten();
@@ -2629,7 +2604,7 @@ void tst_QSslSocket::writeBigChunk()
this->socket = socket.data();
connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QByteArray data;
data.resize(1024*1024*10); // 10 MB
@@ -2789,7 +2764,9 @@ void tst_QSslSocket::resume_data()
QTest::newRow("DoNotIgnoreErrors") << false << QList<QSslError>() << false;
QTest::newRow("ignoreAllErrors") << true << QList<QSslError>() << true;
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "certs/qt-test-server-cacert.pem");
+ // Note, httpServerCertChainPath() it's ... because we use the same certificate on
+ // different services. We'll be actually connecting to IMAP server.
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(httpServerCertChainPath());
QSslError rightError(FLUKE_CERTIFICATE_ERROR, certs.at(0));
QSslError wrongError(FLUKE_CERTIFICATE_ERROR);
errorsList.append(wrongError);
@@ -2822,7 +2799,7 @@ void tst_QSslSocket::resume()
this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), &QTestEventLoop::instance(), SLOT(exitLoop()));
- socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+ socket.connectToHostEncrypted(QtNetworkSettings::imapServerName(), 993);
QTestEventLoop::instance().enterLoop(10);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && QTestEventLoop::instance().timeout())
@@ -3317,22 +3294,22 @@ void tst_QSslSocket::verifyClientCertificate_data()
validCerts += QSslCertificate::fromPath(testDataDir + "certs/bogus-ca.crt");
QCOMPARE(validCerts.size(), 2);
- QTest::newRow("ValidClientCert:AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << validCerts << validKey << true;
- QTest::newRow("ValidClientCert:QueryPeer") << QSslSocket::QueryPeer << validCerts << validKey << true;
- QTest::newRow("ValidClientCert:VerifyNone") << QSslSocket::VerifyNone << validCerts << validKey << true;
- QTest::newRow("ValidClientCert:VerifyPeer") << QSslSocket::VerifyPeer << validCerts << validKey << true;
+ QTest::newRow("ValidChainedClientCert:AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << validCerts << validKey << true;
+ QTest::newRow("ValidChainedClientCert:QueryPeer") << QSslSocket::QueryPeer << validCerts << validKey << true;
+ QTest::newRow("ValidChainedClientCert:VerifyNone") << QSslSocket::VerifyNone << validCerts << validKey << true;
+ QTest::newRow("ValidChainedClientCert:VerifyPeer") << QSslSocket::VerifyPeer << validCerts << validKey << true;
}
void tst_QSslSocket::verifyClientCertificate()
{
-#ifdef QT_SECURETRANSPORT
+#if QT_CONFIG(securetransport)
// We run both client and server on the same machine,
// this means, client can update keychain with client's certificates,
// and server later will use the same certificates from the same
// keychain thus making tests fail (wrong number of certificates,
// success instead of failure etc.).
QSKIP("This test can not work with Secure Transport");
-#endif
+#endif // QT_CONFIG(securetransport)
#ifdef Q_OS_WINRT
QSKIP("Server-side encryption is not implemented on WinRT.");
#endif
@@ -3346,6 +3323,11 @@ void tst_QSslSocket::verifyClientCertificate()
return;
QFETCH(QSslSocket::PeerVerifyMode, peerVerifyMode);
+#if QT_CONFIG(schannel)
+ if (peerVerifyMode == QSslSocket::QueryPeer || peerVerifyMode == QSslSocket::AutoVerifyPeer)
+ QSKIP("Schannel doesn't tackle requesting a certificate and not receiving one.");
+#endif
+
SslServer server;
server.addCaCertificates = testDataDir + "certs/bogus-ca.crt";
server.ignoreSslErrors = false;
@@ -3376,7 +3358,15 @@ void tst_QSslSocket::verifyClientCertificate()
// check server socket
QVERIFY(server.socket);
- QCOMPARE(int(server.socket->state()), int(expectedState));
+#if QT_CONFIG(schannel)
+ // As additional info to the QEXPECT_FAIL below:
+ // This is because schannel treats it as an error (client side) if you don't have a certificate
+ // when asked for one.
+ QEXPECT_FAIL("NoCert:VerifyPeer",
+ "The client disconnects first, which causes the event "
+ "loop to quit before the server disconnects.", Continue);
+#endif
+ QCOMPARE(server.socket->state(), expectedState);
QCOMPARE(server.socket->isEncrypted(), works);
if (peerVerifyMode == QSslSocket::VerifyNone || clientCerts.isEmpty()) {
@@ -3384,17 +3374,24 @@ void tst_QSslSocket::verifyClientCertificate()
QVERIFY(server.socket->peerCertificateChain().isEmpty());
} else {
QCOMPARE(server.socket->peerCertificate(), clientCerts.first());
+#if QT_CONFIG(schannel)
+ if (clientCerts.count() == 1 && server.socket->peerCertificateChain().count() == 2) {
+ QEXPECT_FAIL("",
+ "Schannel includes the entire chain, not just the leaf and intermediates",
+ Continue);
+ }
+#endif
QCOMPARE(server.socket->peerCertificateChain(), clientCerts);
}
// check client socket
- QCOMPARE(int(client.state()), int(expectedState));
+ QCOMPARE(client.state(), expectedState);
QCOMPARE(client.isEncrypted(), works);
}
void tst_QSslSocket::readBufferMaxSize()
{
-#ifdef QT_SECURETRANSPORT
+#if QT_CONFIG(securetransport) || QT_CONFIG(schannel)
// QTBUG-55170:
// SecureTransport back-end was ignoring read-buffer
// size limit, resulting (potentially) in a constantly
@@ -3451,7 +3448,7 @@ void tst_QSslSocket::readBufferMaxSize()
QCOMPARE(client->bytesAvailable() + readSoFar, message.size());
#else
// Not needed, QSslSocket works correctly with other back-ends.
-#endif
+#endif // QT_CONFIG(securetransport) || QT_CONFIG(schannel)
}
void tst_QSslSocket::setEmptyDefaultConfiguration() // this test should be last, as it has some side effects
@@ -3468,12 +3465,57 @@ void tst_QSslSocket::setEmptyDefaultConfiguration() // this test should be last,
socket = client.data();
connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
- socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && socket->waitForEncrypted(4000))
QSKIP("Skipping flaky test - See QTBUG-29941");
}
+void tst_QSslSocket::allowedProtocolNegotiation()
+{
+#ifndef ALPN_SUPPORTED
+ QSKIP("ALPN is unsupported, skipping test");
+#endif
+
+#if QT_CONFIG(schannel)
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
+ QSKIP("ALPN is not supported on this version of Windows using Schannel.");
+#endif
+
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+
+ const QByteArray expectedNegotiated("cool-protocol");
+ QList<QByteArray> serverProtos;
+ serverProtos << expectedNegotiated << "not-so-cool-protocol";
+ QList<QByteArray> clientProtos;
+ clientProtos << "uber-cool-protocol" << expectedNegotiated << "not-so-cool-protocol";
+
+
+ SslServer server;
+ server.config.setAllowedNextProtocols(serverProtos);
+ QVERIFY(server.listen());
+
+ QSslSocket clientSocket;
+ auto configuration = clientSocket.sslConfiguration();
+ configuration.setAllowedNextProtocols(clientProtos);
+ clientSocket.setSslConfiguration(configuration);
+
+ clientSocket.connectToHostEncrypted("127.0.0.1", server.serverPort());
+ clientSocket.ignoreSslErrors();
+
+ QEventLoop loop;
+ QTimer::singleShot(5000, &loop, SLOT(quit()));
+ connect(&clientSocket, SIGNAL(encrypted()), &loop, SLOT(quit()));
+ loop.exec();
+
+ QVERIFY(server.socket->sslConfiguration().nextNegotiatedProtocol() ==
+ clientSocket.sslConfiguration().nextNegotiatedProtocol());
+ QVERIFY(server.socket->sslConfiguration().nextNegotiatedProtocol() == expectedNegotiated);
+}
+
#ifndef QT_NO_OPENSSL
class PskProvider : public QObject
{
@@ -3882,50 +3924,14 @@ void tst_QSslSocket::ephemeralServerKey()
QCOMPARE(client->sslConfiguration().ephemeralServerKey().isNull(), emptyKey);
}
-void tst_QSslSocket::allowedProtocolNegotiation()
-{
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT)
-
- QFETCH_GLOBAL(bool, setProxy);
- if (setProxy)
- return;
-
- const QByteArray expectedNegotiated("cool-protocol");
- QList<QByteArray> serverProtos;
- serverProtos << expectedNegotiated << "not-so-cool-protocol";
- QList<QByteArray> clientProtos;
- clientProtos << "uber-cool-protocol" << expectedNegotiated << "not-so-cool-protocol";
-
-
- SslServer server;
- server.config.setAllowedNextProtocols(serverProtos);
- QVERIFY(server.listen());
-
- QSslSocket clientSocket;
- auto configuration = clientSocket.sslConfiguration();
- configuration.setAllowedNextProtocols(clientProtos);
- clientSocket.setSslConfiguration(configuration);
-
- clientSocket.connectToHostEncrypted("127.0.0.1", server.serverPort());
- clientSocket.ignoreSslErrors();
-
- QEventLoop loop;
- QTimer::singleShot(5000, &loop, SLOT(quit()));
- connect(&clientSocket, SIGNAL(encrypted()), &loop, SLOT(quit()));
- loop.exec();
-
- QVERIFY(server.socket->sslConfiguration().nextNegotiatedProtocol() ==
- clientSocket.sslConfiguration().nextNegotiatedProtocol());
- QVERIFY(server.socket->sslConfiguration().nextNegotiatedProtocol() == expectedNegotiated);
-
-#endif // OPENSSL_VERSION_NUMBER
-}
-
void tst_QSslSocket::pskServer()
{
#ifdef Q_OS_WINRT
QSKIP("Server-side encryption is not implemented on WinRT.");
#endif
+#if QT_CONFIG(schannel)
+ QSKIP("Schannel does not have PSK support implemented.");
+#endif
QFETCH_GLOBAL(bool, setProxy);
if (!QSslSocket::supportsSsl() || setProxy)
return;
@@ -4158,13 +4164,81 @@ void tst_QSslSocket::forwardReadChannelFinished()
});
connect(&socket, &QSslSocket::readChannelFinished,
&QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
- socket.connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443);
+ socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
enterLoop(10);
QVERIFY(readChannelFinishedSpy.count());
}
#endif // QT_NO_OPENSSL
+void tst_QSslSocket::disabledProtocols_data()
+{
+ QTest::addColumn<QSsl::SslProtocol>("disabledProtocol");
+ QTest::newRow("SslV2") << QSsl::SslV2;
+ QTest::newRow("SslV3") << QSsl::SslV3;
+}
+
+void tst_QSslSocket::disabledProtocols()
+{
+ QFETCH_GLOBAL(const bool, setProxy);
+ if (setProxy)
+ return;
+
+ QFETCH(const QSsl::SslProtocol, disabledProtocol);
+ const int timeoutMS = 500;
+ // Test a client socket.
+ {
+ // 0. connectToHostEncrypted: client-side, non-blocking API, error is discovered
+ // early, preventing any real connection from ever starting.
+ QSslSocket socket;
+ socket.setProtocol(disabledProtocol);
+ QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
+ socket.connectToHostEncrypted(QStringLiteral("doesnotmatter.org"), 1010);
+ QCOMPARE(socket.error(), QAbstractSocket::SslInvalidUserDataError);
+ QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState);
+ }
+ {
+ // 1. startClientEncryption: client-side, non blocking API, but wants a socket in
+ // the 'connected' state (otherwise just returns false not setting any error code).
+ SslServer server;
+ QVERIFY(server.listen());
+
+ QSslSocket socket;
+ QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
+
+ socket.connectToHost(QHostAddress::LocalHost, server.serverPort());
+ QVERIFY(socket.waitForConnected(timeoutMS));
+
+ socket.setProtocol(disabledProtocol);
+ socket.startClientEncryption();
+ QCOMPARE(socket.error(), QAbstractSocket::SslInvalidUserDataError);
+ }
+ {
+ // 2. waitForEncrypted: client-side, blocking API plus requires from us
+ // to call ... connectToHostEncrypted(), which will notice an error and
+ // will prevent any connect at all. Nothing to test.
+ }
+
+ // Test a server side, relatively simple: server does not connect, it listens/accepts
+ // and then calls startServerEncryption() (which must fall).
+ {
+ SslServer server;
+ server.protocol = disabledProtocol;
+ QVERIFY(server.listen());
+
+ QTestEventLoop loop;
+ connect(&server, &SslServer::socketError, [&loop](QAbstractSocket::SocketError)
+ {loop.exitLoop();});
+
+ QTcpSocket client;
+ client.connectToHost(QHostAddress::LocalHost, server.serverPort());
+ loop.enterLoopMSecs(timeoutMS);
+ QVERIFY(!loop.timeout());
+ QVERIFY(server.socket);
+ QCOMPARE(server.socket->error(), QAbstractSocket::SslInvalidUserDataError);
+ }
+}
+
#endif // QT_NO_SSL
QTEST_MAIN(tst_QSslSocket)
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/BLACKLIST b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/BLACKLIST
deleted file mode 100644
index c9b628d79b..0000000000
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[onDemandRootCertLoadingMemberMethods]
-linux
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro
index 05755ff606..8585a3c861 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro
@@ -17,3 +17,9 @@ win32 {
DEFINES += SRCDIR=\\\"$$PWD/\\\"
requires(qtConfig(private_tests))
+
+# DOCKERTODO: linux, docker is disabled on macOS/Windows.
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = squid danted
+}
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
index 25c2701f69..4199c0f465 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
@@ -102,7 +102,15 @@ void tst_QSslSocket_onDemandCertificates_member::initTestCase_data()
void tst_QSslSocket_onDemandCertificates_member::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1081));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3129));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3130));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif // QT_TEST_SERVER
}
void tst_QSslSocket_onDemandCertificates_member::init()
@@ -110,28 +118,29 @@ void tst_QSslSocket_onDemandCertificates_member::init()
QFETCH_GLOBAL(bool, setProxy);
if (setProxy) {
QFETCH_GLOBAL(int, proxyType);
- QString testServer = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
+ const auto socksAddr = QtNetworkSettings::socksProxyServerIp().toString();
+ const auto squidAddr = QtNetworkSettings::httpProxyServerIp().toString();
QNetworkProxy proxy;
switch (proxyType) {
case Socks5Proxy:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, testServer, 1080);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksAddr, 1080);
break;
case Socks5Proxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, testServer, 1081);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksAddr, 1081);
break;
case HttpProxy | NoAuth:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3128);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3128);
break;
case HttpProxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3129);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3129);
break;
case HttpProxy | AuthNtlm:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3130);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3130);
break;
}
QNetworkProxy::setApplicationProxy(proxy);
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro
index c345d7379f..158ecbee37 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro
@@ -16,3 +16,9 @@ win32 {
DEFINES += SRCDIR=\\\"$$PWD/\\\"
requires(qtConfig(private_tests))
+
+#DOCKERTODO Linux, docker is disabled on macOS and Windows.
+linux {
+ CONFIG += unsupported/testserver
+ QT_TEST_SERVER_LIST = squid danted
+}
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp
index 503edc0bff..671a21b1c2 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp
@@ -98,7 +98,15 @@ void tst_QSslSocket_onDemandCertificates_static::initTestCase_data()
void tst_QSslSocket_onDemandCertificates_static::initTestCase()
{
+#ifdef QT_TEST_SERVER
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1081));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3129));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3130));
+#else
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
+#endif // QT_TEST_SERVER
}
void tst_QSslSocket_onDemandCertificates_static::init()
@@ -106,28 +114,30 @@ void tst_QSslSocket_onDemandCertificates_static::init()
QFETCH_GLOBAL(bool, setProxy);
if (setProxy) {
QFETCH_GLOBAL(int, proxyType);
- QString testServer = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
+ const auto socksAddr = QtNetworkSettings::socksProxyServerIp().toString();
+ const auto squidAddr = QtNetworkSettings::httpProxyServerIp().toString();
+
QNetworkProxy proxy;
switch (proxyType) {
case Socks5Proxy:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, testServer, 1080);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksAddr, 1080);
break;
case Socks5Proxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, testServer, 1081);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, socksAddr, 1081);
break;
case HttpProxy | NoAuth:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3128);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3128);
break;
case HttpProxy | AuthBasic:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3129);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3129);
break;
case HttpProxy | AuthNtlm:
- proxy = QNetworkProxy(QNetworkProxy::HttpProxy, testServer, 3130);
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, squidAddr, 3130);
break;
}
QNetworkProxy::setApplicationProxy(proxy);
diff --git a/tests/auto/network/ssl/ssl.pro b/tests/auto/network/ssl/ssl.pro
index e89443ef4e..169e9bce83 100644
--- a/tests/auto/network/ssl/ssl.pro
+++ b/tests/auto/network/ssl/ssl.pro
@@ -21,6 +21,8 @@ qtConfig(ssl) {
qdtlscookie \
qdtls
}
+
+ qtConfig(ocsp): SUBDIRS += qocsp
}
}
diff --git a/tests/auto/opengl/qglthreads/tst_qglthreads.cpp b/tests/auto/opengl/qglthreads/tst_qglthreads.cpp
index b7b5b505a0..8a38d0f517 100644
--- a/tests/auto/opengl/qglthreads/tst_qglthreads.cpp
+++ b/tests/auto/opengl/qglthreads/tst_qglthreads.cpp
@@ -33,6 +33,7 @@
#include <qpa/qplatformintegration.h>
#include <QtWidgets/QApplication>
#include <QtOpenGL/QtOpenGL>
+#include <qelapsedtimer.h>
#include "tst_qglthreads.h"
#ifndef QT_OPENGL_ES_2
@@ -74,9 +75,9 @@ public:
}
void run() {
- QTime time;
- time.start();
- while (time.elapsed() < RUNNING_TIME) {
+ QElapsedTimer timer;
+ timer.start();
+ while (timer.elapsed() < RUNNING_TIME) {
lock();
waitForReadyToSwap();
@@ -291,11 +292,11 @@ public:
}
void run() {
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
failure = false;
- while (time.elapsed() < RUNNING_TIME && !failure) {
+ while (timer.elapsed() < RUNNING_TIME && !failure) {
m_widget->makeCurrent();
@@ -466,13 +467,13 @@ public:
public slots:
void draw() {
bool beginFailed = false;
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
int rotAngle = 10;
device->prepareDevice();
QPaintDevice *paintDevice = device->realPaintDevice();
QSize s(paintDevice->width(), paintDevice->height());
- while (time.elapsed() < RUNNING_TIME) {
+ while (timer.elapsed() < RUNNING_TIME) {
QPainter p;
if (!p.begin(paintDevice)) {
beginFailed = true;
diff --git a/tests/auto/other/compiler/tst_compiler.cpp b/tests/auto/other/compiler/tst_compiler.cpp
index b2b45bb237..de15f4c62d 100644
--- a/tests/auto/other/compiler/tst_compiler.cpp
+++ b/tests/auto/other/compiler/tst_compiler.cpp
@@ -842,7 +842,7 @@ void tst_Compiler::cxx11_constexpr()
static constexpr QBasicAtomicInt atomic = Q_BASIC_ATOMIC_INITIALIZER(1);
static constexpr int i = constexprValue();
QCOMPARE(i, constexprValue());
- QCOMPARE(atomic.load(), 1);
+ QCOMPARE(atomic.loadRelaxed(), 1);
#endif
}
diff --git a/tests/auto/other/gestures/BLACKLIST b/tests/auto/other/gestures/BLACKLIST
index 269bac5750..c465ff316e 100644
--- a/tests/auto/other/gestures/BLACKLIST
+++ b/tests/auto/other/gestures/BLACKLIST
@@ -1,5 +1,6 @@
[]
rhel-7.4
+rhel-7.6
ubuntu-18.04
[customGesture]
# QTBUG-67254
diff --git a/tests/auto/other/lancelot/paintcommands.cpp b/tests/auto/other/lancelot/paintcommands.cpp
index 8aa3a035e3..8a2934049e 100644
--- a/tests/auto/other/lancelot/paintcommands.cpp
+++ b/tests/auto/other/lancelot/paintcommands.cpp
@@ -1200,7 +1200,10 @@ void PaintCommands::command_drawRoundRect(QRegularExpressionMatch re)
if (m_verboseMode)
printf(" -(lance) drawRoundRect(%d, %d, %d, %d, [%d, %d])\n", x, y, w, h, xs, ys);
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
m_painter->drawRoundRect(x, y, w, h, xs, ys);
+ QT_WARNING_POP
}
/***************************************************************************************************/
diff --git a/tests/auto/other/networkselftest/tst_networkselftest.cpp b/tests/auto/other/networkselftest/tst_networkselftest.cpp
index dc353d2090..1b125d8825 100644
--- a/tests/auto/other/networkselftest/tst_networkselftest.cpp
+++ b/tests/auto/other/networkselftest/tst_networkselftest.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <QtNetwork/QtNetwork>
#include <QtCore/QDateTime>
+#include <QtCore/QElapsedTimer>
#include <QtCore/QTextStream>
#include <QtCore/QRandomGenerator>
#include <QtCore/QStandardPaths>
@@ -195,7 +196,7 @@ static bool doSocketFlush(QTcpSocket *socket, int timeout = 4000)
#ifndef QT_NO_SSL
QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
#endif
- QTime timer;
+ QElapsedTimer timer;
timer.start();
int t = timeout;
forever {
@@ -421,7 +422,7 @@ void tst_NetworkSelfTest::serverReachability()
QTcpSocket socket;
socket.connectToHost(QtNetworkSettings::serverName(), 12346);
- QTime timer;
+ QElapsedTimer timer;
timer.start();
socket.waitForConnected(10000);
QVERIFY2(timer.elapsed() < 9900, "Connection to closed port timed out instead of refusing, something is wrong");
diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro
index 25ab62a1c3..c5426202e8 100644
--- a/tests/auto/other/other.pro
+++ b/tests/auto/other/other.pro
@@ -67,3 +67,8 @@ winrt|!qtHaveModule(gui)|!qtConfig(accessibility): SUBDIRS -= qaccessibility
android: SUBDIRS += \
android
+
+qtConfig(xkbcommon): {
+ SUBDIRS += \
+ xkbkeyboard
+}
diff --git a/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.cpp b/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.cpp
index fc979bce2d..c8698242d5 100644
--- a/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.cpp
+++ b/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.cpp
@@ -80,13 +80,9 @@ qint64 DynamicTreeModel::findParentId(qint64 searchId) const
if (searchId <= 0)
return -1;
- QHashIterator<qint64, QList<QList<qint64> > > i(m_childItems);
- while (i.hasNext()) {
- i.next();
- QListIterator<QList<qint64> > j(i.value());
- while (j.hasNext()) {
- QList<qint64> l = j.next();
- if (l.contains(searchId))
+ for (auto i = m_childItems.cbegin(), end = m_childItems.cend(); i != end; ++i) {
+ for (const auto &list : i.value()) {
+ if (list.contains(searchId))
return i.key();
}
}
@@ -163,13 +159,12 @@ ModelChangeCommand::ModelChangeCommand(DynamicTreeModel *model, QObject *parent)
{
}
-QModelIndex ModelChangeCommand::findIndex(QList<int> rows)
+QModelIndex ModelChangeCommand::findIndex(const QList<int> &rows) const
{
const int col = 0;
QModelIndex parent = QModelIndex();
- QListIterator<int> i(rows);
- while (i.hasNext()) {
- parent = m_model->index(i.next(), col, parent);
+ for (int row : rows) {
+ parent = m_model->index(row, col, parent);
if (!parent.isValid())
qFatal("%s: parent must be valid", Q_FUNC_INFO);
}
diff --git a/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.h b/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.h
index 709751dd27..0807ffbe94 100644
--- a/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.h
+++ b/tests/auto/other/qabstractitemmodelutils/dynamictreemodel.h
@@ -97,7 +97,7 @@ public:
m_rowNumbers = rowNumbers;
}
- QModelIndex findIndex(QList<int> rows);
+ QModelIndex findIndex(const QList<int> &rows) const;
void setStartRow(int row)
{
diff --git a/tests/auto/other/qaccessibility/qaccessibility.pro b/tests/auto/other/qaccessibility/qaccessibility.pro
index 3587c38e76..6f3740a24f 100644
--- a/tests/auto/other/qaccessibility/qaccessibility.pro
+++ b/tests/auto/other/qaccessibility/qaccessibility.pro
@@ -11,5 +11,6 @@ win32 {
!winrt {
QT += windowsuiautomation_support-private
}
- LIBS += -luuid -loleacc -loleaut32 -lole32
+ LIBS += -loleacc -loleaut32
+ QMAKE_USE += ole32 uuid
}
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index bc45487599..7d7fa6403b 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -2580,6 +2580,7 @@ void tst_QAccessibility::dialogButtonBoxTest()
case QDialogButtonBox::GnomeLayout:
case QDialogButtonBox::KdeLayout:
case QDialogButtonBox::MacLayout:
+ case QDialogButtonBox::AndroidLayout:
expectedOrder << QDialogButtonBox::tr("Help")
<< QDialogButtonBox::tr("Reset")
<< QDialogButtonBox::tr("OK");
diff --git a/tests/auto/other/qobjectrace/tst_qobjectrace.cpp b/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
index 0d656e223c..e09d304ff3 100644
--- a/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
+++ b/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
@@ -85,7 +85,7 @@ class RaceThread : public QThread
{
Q_OBJECT
RaceObject *object;
- QTime stopWatch;
+ QElapsedTimer stopWatch;
public:
RaceThread()
@@ -378,6 +378,10 @@ public:
connect(timer, &QTimer::timeout, this, &DeleteReceiverRaceReceiver::onTimeout);
timer->start(1);
}
+ ~DeleteReceiverRaceReceiver()
+ {
+ delete receiver;
+ }
void onTimeout()
{
@@ -410,7 +414,7 @@ void tst_QObjectRace::disconnectRace()
{
enum { ThreadCount = 20, TimeLimit = 3000 };
- QCOMPARE(countedStructObjectsCount.load(), 0u);
+ QCOMPARE(countedStructObjectsCount.loadRelaxed(), 0u);
{
QScopedPointer<DisconnectRaceSenderObject> sender(new DisconnectRaceSenderObject());
@@ -428,15 +432,15 @@ void tst_QObjectRace::disconnectRace()
for (int i = 0; i < ThreadCount; ++i) {
threads[i]->requestInterruption();
- QVERIFY(threads[i]->wait(300));
+ QVERIFY(threads[i]->wait());
delete threads[i];
}
senderThread->quit();
- QVERIFY(senderThread->wait(300));
+ QVERIFY(senderThread->wait());
}
- QCOMPARE(countedStructObjectsCount.load(), 0u);
+ QCOMPARE(countedStructObjectsCount.loadRelaxed(), 0u);
{
QScopedPointer<DisconnectRaceSenderObject> sender(new DisconnectRaceSenderObject());
@@ -453,16 +457,16 @@ void tst_QObjectRace::disconnectRace()
QTest::qWait(TimeLimit);
senderThread->requestInterruption();
- QVERIFY(senderThread->wait(300));
+ QVERIFY(senderThread->wait());
for (int i = 0; i < ThreadCount; ++i) {
threads[i]->quit();
- QVERIFY(threads[i]->wait(300));
+ QVERIFY(threads[i]->wait());
delete threads[i];
}
}
- QCOMPARE(countedStructObjectsCount.load(), 0u);
+ QCOMPARE(countedStructObjectsCount.loadRelaxed(), 0u);
}
QTEST_MAIN(tst_QObjectRace)
diff --git a/tests/auto/other/toolsupport/tst_toolsupport.cpp b/tests/auto/other/toolsupport/tst_toolsupport.cpp
index f31a755f9e..8c129adaf3 100644
--- a/tests/auto/other/toolsupport/tst_toolsupport.cpp
+++ b/tests/auto/other/toolsupport/tst_toolsupport.cpp
@@ -126,9 +126,9 @@ void tst_toolsupport::offsets_data()
#ifdef Q_PROCESSOR_X86
// x86 32-bit has weird alignment rules. Refer to QtPrivate::AlignOf in
// qglobal.h for more details.
- data << 168 << 248;
+ data << 152 << 224;
#else
- data << 172 << 248;
+ data << 156 << 224;
#endif
}
#endif
diff --git a/tests/auto/other/xkbkeyboard/tst_xkbkeyboard.cpp b/tests/auto/other/xkbkeyboard/tst_xkbkeyboard.cpp
new file mode 100644
index 0000000000..65364eddf4
--- /dev/null
+++ b/tests/auto/other/xkbkeyboard/tst_xkbkeyboard.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <QtGui>
+#include <QtTest>
+
+#include <qpa/qplatforminputcontextfactory_p.h>
+#include <qpa/qplatforminputcontext.h>
+
+class tst_XkbKeyboard : public QObject
+{
+ Q_OBJECT
+private slots:
+ void verifyComposeInputContextInterface();
+};
+
+void tst_XkbKeyboard::verifyComposeInputContextInterface()
+{
+ QPlatformInputContext *inputContext = QPlatformInputContextFactory::create(QStringLiteral("compose"));
+ QVERIFY(inputContext);
+
+ const char *const inputContextClassName = "QComposeInputContext";
+ const char *const normalizedSignature = "setXkbContext(xkb_context*)";
+
+ QVERIFY(inputContext->objectName() == QLatin1String(inputContextClassName));
+
+ int methodIndex = inputContext->metaObject()->indexOfMethod(normalizedSignature);
+ QMetaMethod method = inputContext->metaObject()->method(methodIndex);
+ Q_ASSERT(method.isValid());
+}
+
+QTEST_MAIN(tst_XkbKeyboard)
+#include "tst_xkbkeyboard.moc"
+
diff --git a/tests/auto/other/xkbkeyboard/xkbkeyboard.pro b/tests/auto/other/xkbkeyboard/xkbkeyboard.pro
new file mode 100644
index 0000000000..17396ee475
--- /dev/null
+++ b/tests/auto/other/xkbkeyboard/xkbkeyboard.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase
+TARGET = tst_xkbkeyboard
+
+SOURCES += tst_xkbkeyboard.cpp
+
+QT = core-private gui-private testlib
+
diff --git a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
index abe4325278..7529bad833 100644
--- a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
+++ b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
@@ -1315,7 +1315,9 @@ void tst_QPrinter::pageSize()
// Test set/get
QPrinter::PaperSize expected = QPrinter::A4;
QPrinterInfo info = QPrinterInfo::printerInfo(native.printerName());
- foreach (QPrinter::PaperSize supported, info.supportedPaperSizes()) {
+ const auto &pageSizes = info.supportedPageSizes();
+ for (const auto &pageSize : pageSizes) {
+ const QPrinter::PaperSize supported = QPrinter::PaperSize(pageSize.id());
if (supported != QPrinter::Custom && supported != native.paperSize()) {
expected = supported;
break;
@@ -1359,7 +1361,9 @@ void tst_QPrinter::paperSize()
// Test set/get
QPrinter::PaperSize expected = QPrinter::A4;
QPrinterInfo info = QPrinterInfo::printerInfo(native.printerName());
- foreach (QPrinter::PaperSize supported, info.supportedPaperSizes()) {
+ const auto &pageSizes = info.supportedPageSizes();
+ for (const auto &pageSize : pageSizes) {
+ const QPrinter::PaperSize supported = QPrinter::PaperSize(pageSize.id());
if (supported != QPrinter::Custom && supported != native.paperSize()) {
expected = supported;
break;
diff --git a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp
index 92a06cda00..d1b4ed8bcd 100644
--- a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp
+++ b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp
@@ -94,17 +94,16 @@ QString tst_QPrinterInfo::getDefaultPrinterFromSystem()
command << "lpstat" << "-d";
QString output = getOutputFromCommand(command);
- QRegExp noDefaultReg("[^:]*no .*default");
- int pos = noDefaultReg.indexIn(output);
- if (pos >= 0) {
+ QRegularExpression noDefaultReg("[^:]*no .*default");
+ QRegularExpressionMatch match;
+ match = noDefaultReg.match(output);
+ if (match.hasMatch())
return QString();
- }
- QRegExp defaultReg("default.*: *([a-zA-Z0-9_-]+)");
- defaultReg.indexIn(output);
- printer = defaultReg.cap(1);
+ QRegularExpression defaultReg("default.*: *([a-zA-Z0-9_-]+)");
+ match = defaultReg.match(output);
+ printer = match.captured(1);
#endif // Q_OS_UNIX
-
return printer;
}
@@ -121,10 +120,12 @@ QStringList tst_QPrinterInfo::getPrintersFromSystem()
QString output = getOutputFromCommand(command);
QStringList list = output.split(QChar::fromLatin1('\n'));
- QRegExp reg("^[Pp]rinter ([.a-zA-Z0-9-_@]+)");
+ QRegularExpression reg("^[Pp]rinter ([.a-zA-Z0-9-_@]+)");
+ QRegularExpressionMatch match;
for (int c = 0; c < list.size(); ++c) {
- if (reg.indexIn(list[c]) >= 0) {
- QString printer = reg.cap(1);
+ match = reg.match(list[c]);
+ if (match.hasMatch()) {
+ QString printer = match.captured(1);
ans << printer;
}
}
@@ -300,8 +301,11 @@ void tst_QPrinterInfo::testConstructors()
QCOMPARE(copy1.supportsCustomPageSizes(), printers.at(i).supportsCustomPageSizes());
QCOMPARE(copy1.minimumPhysicalPageSize(), printers.at(i).minimumPhysicalPageSize());
QCOMPARE(copy1.maximumPhysicalPageSize(), printers.at(i).maximumPhysicalPageSize());
- QCOMPARE(copy1.supportedPaperSizes(), printers.at(i).supportedPaperSizes());
+ QCOMPARE(copy1.supportedPageSizes(), printers.at(i).supportedPageSizes());
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(copy1.supportedSizesWithNames(), printers.at(i).supportedSizesWithNames());
+QT_WARNING_POP
QCOMPARE(copy1.supportedResolutions(), printers.at(i).supportedResolutions());
QCOMPARE(copy1.defaultDuplexMode(), printers.at(i).defaultDuplexMode());
QCOMPARE(copy1.supportedDuplexModes(), printers.at(i).supportedDuplexModes());
@@ -321,8 +325,11 @@ void tst_QPrinterInfo::testConstructors()
QCOMPARE(copy2.supportsCustomPageSizes(), printers.at(i).supportsCustomPageSizes());
QCOMPARE(copy2.minimumPhysicalPageSize(), printers.at(i).minimumPhysicalPageSize());
QCOMPARE(copy2.maximumPhysicalPageSize(), printers.at(i).maximumPhysicalPageSize());
- QCOMPARE(copy2.supportedPaperSizes(), printers.at(i).supportedPaperSizes());
+ QCOMPARE(copy2.supportedPageSizes(), printers.at(i).supportedPageSizes());
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
QCOMPARE(copy2.supportedSizesWithNames(), printers.at(i).supportedSizesWithNames());
+ QT_WARNING_POP
QCOMPARE(copy2.supportedResolutions(), printers.at(i).supportedResolutions());
QCOMPARE(copy2.defaultDuplexMode(), printers.at(i).defaultDuplexMode());
QCOMPARE(copy2.supportedDuplexModes(), printers.at(i).supportedDuplexModes());
diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h
index 97397e3159..55875359ff 100644
--- a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h
+++ b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h
@@ -79,14 +79,14 @@ inline QString fixupTableName(const QString &tableName, QSqlDatabase db)
return tbName;
}
-inline static QString qTableName(const QString& prefix, const char *sourceFileName, QSqlDatabase db)
+inline static QString qTableName(const QString &prefix, const char *sourceFileName,
+ QSqlDatabase db, bool escape = true)
{
- QString tableStr = QLatin1String("dbtst");
- if (db.driverName().toLower().contains("ODBC"))
- tableStr += QLatin1String("_odbc");
- return fixupTableName(QString(QLatin1String("dbtst") + db.driverName() +
- QString::number(qHash(QLatin1String(sourceFileName) +
- "_" + qGetHostName().replace( "-", "_" )), 16) + "_" + prefix), db);
+ const auto tableStr = fixupTableName(QString(QLatin1String("dbtst") + db.driverName() +
+ QString::number(qHash(QLatin1String(sourceFileName) +
+ "_" + qGetHostName().replace("-", "_")), 16) +
+ "_" + prefix), db);
+ return escape ? db.driver()->escapeIdentifier(tableStr, QSqlDriver::TableName) : tableStr;
}
inline static QString qTableName(const QString& prefix, QSqlDatabase db)
diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
index af6b6ca881..f309231b10 100644
--- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
+++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
@@ -199,6 +199,9 @@ private slots:
void sqlite_openError();
+ void sqlite_check_json1_data() { generic_data("QSQLITE"); }
+ void sqlite_check_json1();
+
private:
void createTestTables(QSqlDatabase db);
void dropTestTables(QSqlDatabase db);
@@ -311,10 +314,8 @@ void tst_QSqlDatabase::createTestTables(QSqlDatabase db)
" (id integer not null, t_varchar varchar(40) not null, "
"t_char char(40), t_numeric numeric(6, 3), primary key (id, t_varchar))"));
}
-
if (testWhiteSpaceNames(db.driverName())) {
- QString qry = "create table "
- + db.driver()->escapeIdentifier(tableName + " test", QSqlDriver::TableName)
+ QString qry = "create table " + qTableName("qtest test", __FILE__, db)
+ '('
+ db.driver()->escapeIdentifier(QLatin1String("test test"), QSqlDriver::FieldName)
+ " int not null primary key)";
@@ -338,6 +339,7 @@ void tst_QSqlDatabase::dropTestTables(QSqlDatabase db)
const QString qtestTable = qTableName("qtest", __FILE__, db);
QStringList tableNames;
tableNames << qtestTable
+ << qTableName("qtest test", __FILE__, db)
<< qTableName("qtestfields", __FILE__, db)
<< qTableName("qtestalter", __FILE__, db)
<< qTableName("qtest_temp", __FILE__, db)
@@ -510,7 +512,9 @@ void tst_QSqlDatabase::tables()
CHECK_DATABASE(db);
QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
- const QString qtest(qTableName("qtest", __FILE__, db)), qtest_view(qTableName("qtest_view", __FILE__, db)), temp_tab(qTableName("test_tab", __FILE__, db));
+ const auto qtest(qTableName("qtest", __FILE__, db, false)),
+ qtest_view(qTableName("qtest_view", __FILE__, db, false)),
+ temp_tab(qTableName("test_tab", __FILE__, db, false));
bool views = true;
bool tempTables = false;
@@ -575,10 +579,10 @@ void tst_QSqlDatabase::whitespaceInIdentifiers()
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (testWhiteSpaceNames(db.driverName())) {
- const QString tableName(qTableName("qtest", __FILE__, db) + " test");
+ const auto tableName(qTableName("qtest test", __FILE__, db, false));
QVERIFY(db.tables().contains(tableName, Qt::CaseInsensitive));
- QSqlRecord rec = db.record(db.driver()->escapeIdentifier(tableName, QSqlDriver::TableName));
+ QSqlRecord rec = db.record(tableName);
QCOMPARE(rec.count(), 1);
QCOMPARE(rec.fieldName(0), QString("test test"));
if (dbType == QSqlDriver::Oracle)
@@ -586,7 +590,7 @@ void tst_QSqlDatabase::whitespaceInIdentifiers()
else
QCOMPARE(rec.field(0).type(), QVariant::Int);
- QSqlIndex idx = db.primaryIndex(db.driver()->escapeIdentifier(tableName, QSqlDriver::TableName));
+ QSqlIndex idx = db.primaryIndex(tableName);
QCOMPARE(idx.count(), 1);
QCOMPARE(idx.fieldName(0), QString("test test"));
if (dbType == QSqlDriver::Oracle)
@@ -604,11 +608,12 @@ void tst_QSqlDatabase::alterTable()
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
const QString qtestalter(qTableName("qtestalter", __FILE__, db));
+ const auto noEscapeAlterTable = qTableName("qtestalter", __FILE__, db, false);
QSqlQuery q(db);
QVERIFY_SQL(q, exec("create table " + qtestalter + " (F1 char(20), F2 char(20), F3 char(20))"));
- QSqlRecord rec = db.record(qtestalter);
+ QSqlRecord rec = db.record(noEscapeAlterTable);
QCOMPARE((int)rec.count(), 3);
int i;
@@ -620,7 +625,7 @@ void tst_QSqlDatabase::alterTable()
QSKIP("DBMS doesn't support dropping columns in ALTER TABLE statement");
}
- rec = db.record(qtestalter);
+ rec = db.record(noEscapeAlterTable);
QCOMPARE((int)rec.count(), 2);
@@ -678,13 +683,16 @@ void tst_QSqlDatabase::testRecord(const FieldDef fieldDefs[], const QSqlRecord&
void tst_QSqlDatabase::commonFieldTest(const FieldDef fieldDefs[], QSqlDatabase db, const int fieldCount)
{
CHECK_DATABASE(db);
- const QString tableName = qTableName("qtestfields", __FILE__, db);
- QSqlRecord rec = db.record(tableName);
- QCOMPARE((int)rec.count(), fieldCount+1);
- testRecord(fieldDefs, rec, db);
-
+ const QStringList tableNames = { qTableName("qtestfields", __FILE__, db),
+ qTableName("qtestfields", __FILE__, db, false) };
+ for (const QString table : tableNames) {
+ QSqlRecord rec = db.record(table);
+ QCOMPARE(rec.count(), fieldCount + 1);
+ testRecord(fieldDefs, rec, db);
+ }
QSqlQuery q(db);
- QVERIFY_SQL(q, exec("select * from " + tableName));
+ // Only check the escaped entry
+ QVERIFY_SQL(q, exec("select * from " + tableNames.at(0)));
}
void tst_QSqlDatabase::recordTDS()
@@ -843,12 +851,8 @@ void tst_QSqlDatabase::recordPSQL()
QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
if (dbType == QSqlDriver::PostgreSQL)
QVERIFY_SQL( q, exec("set client_min_messages='warning'"));
- const QString tableName = qTableName("qtestfields", __FILE__, db);
- q.exec("drop sequence " + tableName + "_t_bigserial_seq");
- q.exec("drop sequence " + tableName + "_t_serial_seq");
- // older psql cut off the table name
- q.exec("drop sequence " + tableName + "_t_bigserial_seq");
- q.exec("drop sequence " + tableName + "_t_serial_seq");
+ q.exec("drop sequence " + qTableName("qtestfields_t_bigserial_seq", __FILE__, db));
+ q.exec("drop sequence " + qTableName("qtestfields_t_serial_seq", __FILE__, db));
const int fieldCount = createFieldTable(fieldDefs, db);
QVERIFY(fieldCount > 0);
@@ -1202,27 +1206,40 @@ void tst_QSqlDatabase::caseSensivity()
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
bool cs = false;
- if (dbType == QSqlDriver::MySqlServer || dbType == QSqlDriver::SQLite || dbType == QSqlDriver::Sybase
+ if (dbType == QSqlDriver::MySqlServer || dbType == QSqlDriver::SQLite
+ || dbType == QSqlDriver::Sybase || dbType == QSqlDriver::PostgreSQL
|| dbType == QSqlDriver::MSSqlServer || db.driverName().startsWith("QODBC"))
cs = true;
- QSqlRecord rec = db.record(qTableName("qtest", __FILE__, db));
+ QSqlRecord rec = db.record(qTableName("qtest", __FILE__, db, false));
QVERIFY((int)rec.count() > 0);
if (!cs) {
- rec = db.record(qTableName("QTEST", __FILE__, db).toUpper());
+ rec = db.record(qTableName("QTEST", __FILE__, db, false).toUpper());
QVERIFY((int)rec.count() > 0);
- rec = db.record(qTableName("qTesT", __FILE__, db));
+ rec = db.record(qTableName("qTesT", __FILE__, db, false));
QVERIFY((int)rec.count() > 0);
}
- rec = db.primaryIndex(qTableName("qtest", __FILE__, db));
+ rec = db.primaryIndex(qTableName("qtest", __FILE__, db, false));
QVERIFY((int)rec.count() > 0);
if (!cs) {
- rec = db.primaryIndex(qTableName("QTEST", __FILE__, db).toUpper());
+ rec = db.primaryIndex(qTableName("QTEST", __FILE__, db, false).toUpper());
QVERIFY((int)rec.count() > 0);
- rec = db.primaryIndex(qTableName("qTesT", __FILE__, db));
+ rec = db.primaryIndex(qTableName("qTesT", __FILE__, db, false));
QVERIFY((int)rec.count() > 0);
}
+
+ // Explicit test for case sensitive table creation without quoting
+ QSqlQuery qry(db);
+ const auto noQuotesTable = qTableName("NoQuotes", __FILE__, db, false);
+ tst_Databases::safeDropTable(db, noQuotesTable);
+ QVERIFY_SQL(qry, exec("CREATE TABLE " + noQuotesTable + " (id INTEGER)"));
+ QVERIFY_SQL(qry, exec("INSERT INTO " + noQuotesTable + " VALUES(1)"));
+ QVERIFY_SQL(qry, exec("SELECT * FROM " + noQuotesTable));
+ QVERIFY_SQL(qry, next());
+ QCOMPARE(qry.value(0).toInt(), 1);
+ rec = db.record(cs ? noQuotesTable.toLower() : noQuotesTable);
+ QVERIFY(rec.count() > 0);
}
void tst_QSqlDatabase::noEscapedFieldNamesInRecord()
@@ -1257,17 +1274,19 @@ void tst_QSqlDatabase::psql_schemas()
const QString schemaName = qTableName("qtestschema", __FILE__, db);
QVERIFY_SQL(q, exec("CREATE SCHEMA " + schemaName));
- QString table = schemaName + '.' + qTableName("qtesttable", __FILE__, db);
+ const auto table = schemaName + '.' + qTableName("qtesttable", __FILE__, db);
+ const auto noescapeTable = qTableName("qtestschema", __FILE__, db, false) + '.' +
+ qTableName("qtesttable", __FILE__, db, false);
QVERIFY_SQL(q, exec("CREATE TABLE " + table + " (id int primary key, name varchar(20))"));
- QVERIFY(db.tables().contains(table, Qt::CaseInsensitive));
+ QVERIFY(db.tables().contains(noescapeTable, Qt::CaseInsensitive));
- QSqlRecord rec = db.record(table);
+ QSqlRecord rec = db.record(noescapeTable);
QCOMPARE(rec.count(), 2);
QCOMPARE(rec.fieldName(0), QString("id"));
QCOMPARE(rec.fieldName(1), QString("name"));
- QSqlIndex idx = db.primaryIndex(table);
+ QSqlIndex idx = db.primaryIndex(noescapeTable);
QCOMPARE(idx.count(), 1);
QCOMPARE(idx.fieldName(0), QString("id"));
}
@@ -1285,18 +1304,21 @@ void tst_QSqlDatabase::psql_escapedIdentifiers()
QSqlQuery q(db);
QVERIFY_SQL( q, exec("set client_min_messages='warning'"));
- const QString schemaName(qTableName("qtestScHeMa", __FILE__, db)),
+ const char bumpyCase[] = "qtestScHeMa";
+ const QString schemaName(qTableName(bumpyCase, __FILE__, db)),
tableName(qTableName("qtest", __FILE__, db)),
field1Name(QLatin1String("fIeLdNaMe")),
field2Name(QLatin1String("ZuLu"));
- q.exec(QString("DROP SCHEMA \"%1\" CASCADE").arg(schemaName));
- QString createSchema = QString("CREATE SCHEMA \"%1\"").arg(schemaName);
+ q.exec(QString("DROP SCHEMA %1 CASCADE").arg(schemaName));
+ const auto createSchema = QString("CREATE SCHEMA %1").arg(schemaName);
QVERIFY_SQL(q, exec(createSchema));
- QString createTable = QString("CREATE TABLE \"%1\".\"%2\" (\"%3\" int PRIMARY KEY, \"%4\" varchar(20))").arg(schemaName).arg(tableName).arg(field1Name).arg(field2Name);
+ const auto createTable = QString("CREATE TABLE %1.%2 (\"%3\" int PRIMARY KEY, \"%4\" varchar(20))")
+ .arg(schemaName, tableName, field1Name, field2Name);
QVERIFY_SQL(q, exec(createTable));
- QVERIFY(db.tables().contains(schemaName + '.' + tableName, Qt::CaseSensitive));
+ QVERIFY(db.tables().contains(qTableName(bumpyCase, __FILE__, db, false) + '.' +
+ qTableName("qtest", __FILE__, db, false), Qt::CaseSensitive));
QSqlField fld1(field1Name, QVariant::Int);
QSqlField fld2(field2Name, QVariant::String);
@@ -1304,7 +1326,9 @@ void tst_QSqlDatabase::psql_escapedIdentifiers()
rec.append(fld1);
rec.append(fld2);
- QVERIFY_SQL(q, exec(drv->sqlStatement(QSqlDriver::SelectStatement, db.driver()->escapeIdentifier(schemaName, QSqlDriver::TableName) + '.' + db.driver()->escapeIdentifier(tableName, QSqlDriver::TableName), rec, false)));
+ QVERIFY_SQL(q, exec(drv->sqlStatement(QSqlDriver::SelectStatement,
+ schemaName + '.' + tableName,
+ rec, false)));
rec = q.record();
QCOMPARE(rec.count(), 2);
@@ -1312,7 +1336,7 @@ void tst_QSqlDatabase::psql_escapedIdentifiers()
QCOMPARE(rec.fieldName(1), field2Name);
QCOMPARE(rec.field(0).type(), QVariant::Int);
- q.exec(QString("DROP SCHEMA \"%1\" CASCADE").arg(schemaName));
+ q.exec(QString("DROP SCHEMA %1 CASCADE").arg(schemaName));
}
void tst_QSqlDatabase::psql_escapeBytea()
@@ -2143,7 +2167,7 @@ void tst_QSqlDatabase::eventNotificationPSQL()
CHECK_DATABASE(db);
QSqlQuery query(db);
- QString procedureName = qTableName("posteventProc", __FILE__, db);
+ const auto procedureName = qTableName("posteventProc", __FILE__, db, false);
QString payload = "payload";
QSqlDriver &driver=*(db.driver());
QVERIFY_SQL(driver, subscribeToNotification(procedureName));
@@ -2167,21 +2191,22 @@ void tst_QSqlDatabase::eventNotificationSQLite()
QSKIP("QSQLITE specific test");
}
const QString tableName(qTableName("sqlitnotifytest", __FILE__, db));
+ const auto noEscapeTableName(qTableName("sqlitnotifytest", __FILE__, db, false));
tst_Databases::safeDropTable(db, tableName);
QSignalSpy notificationSpy(db.driver(), SIGNAL(notification(QString)));
QSignalSpy notificationSpyExt(db.driver(), SIGNAL(notification(QString,QSqlDriver::NotificationSource,QVariant)));
QSqlQuery q(db);
QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + " (id INTEGER, realVal REAL)"));
- db.driver()->subscribeToNotification(tableName);
+ db.driver()->subscribeToNotification(noEscapeTableName);
QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id, realVal) VALUES (1, 2.3)"));
QTRY_COMPARE(notificationSpy.count(), 1);
QTRY_COMPARE(notificationSpyExt.count(), 1);
QList<QVariant> arguments = notificationSpy.takeFirst();
- QCOMPARE(arguments.at(0).toString(), tableName);
+ QCOMPARE(arguments.at(0).toString(), noEscapeTableName);
arguments = notificationSpyExt.takeFirst();
- QCOMPARE(arguments.at(0).toString(), tableName);
- db.driver()->unsubscribeFromNotification(tableName);
+ QCOMPARE(arguments.at(0).toString(), noEscapeTableName);
+ db.driver()->unsubscribeFromNotification(noEscapeTableName);
QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id, realVal) VALUES (1, 2.3)"));
QTRY_COMPARE(notificationSpy.count(), 0);
QTRY_COMPARE(notificationSpyExt.count(), 0);
@@ -2350,6 +2375,30 @@ void tst_QSqlDatabase::sqlite_openError()
QCOMPARE(error.databaseText(), "unable to open database file");
}
+void tst_QSqlDatabase::sqlite_check_json1()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
+ if (dbType != QSqlDriver::SQLite)
+ QSKIP("SQLite3 specific test");
+
+ QSqlQuery q(db);
+ const QString json1("{\"id\":1}");
+ const QString tableName(qTableName("sqlite_check_json1", __FILE__, db));
+ tst_Databases::safeDropTable(db, tableName);
+ QVERIFY_SQL(q, exec(QString("CREATE TABLE %1(text TEXT)").arg(tableName)));
+ QVERIFY_SQL(q, exec(QString("INSERT INTO %1 VALUES(json('%2'))").arg(tableName, json1)));
+ QVERIFY_SQL(q, prepare(QString("INSERT INTO %1 VALUES(?)").arg(tableName)));
+ q.addBindValue("json('{\"id\":2}')");
+ QVERIFY_SQL(q, prepare(QString("SELECT * from %1 WHERE text = json('%2')").arg(tableName, json1)));
+ QVERIFY_SQL(q, exec());
+ QVERIFY_SQL(q, next());
+ QCOMPARE(q.value(0).toString(), json1);
+ QFAIL_SQL(q, next());
+}
+
void tst_QSqlDatabase::cloneDatabase()
{
QFETCH(QString, dbName);
@@ -2395,6 +2444,16 @@ public slots:
QSqlDatabase invalidDb = QSqlDatabase::database("invalid");
QVERIFY(!invalidDb.isValid());
+
+ {
+ QSqlDatabase clonedDatabase = QSqlDatabase::cloneDatabase(dbName, "CloneDB");
+ QVERIFY(!clonedDatabase.isOpen());
+ QVERIFY(clonedDatabase.isValid());
+ QVERIFY(clonedDatabase.open());
+ QVERIFY(clonedDatabase.isOpen());
+ clonedDatabase.close();
+ }
+
QThread::currentThread()->exit();
}
private:
diff --git a/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp b/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp
index 08c6039e37..be0285537e 100644
--- a/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp
+++ b/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp
@@ -46,6 +46,7 @@ private slots:
void construction();
void moveOperator();
void operators();
+ void qtbug_74575();
};
tst_QSqlError::tst_QSqlError()
@@ -113,6 +114,7 @@ void tst_QSqlError::construction()
QVERIFY(!obj4.isValid());
QCOMPARE(obj4.driverText(), QString());
QCOMPARE(obj4.databaseText(), QString());
+ QCOMPARE(obj4.text(), QString());
QCOMPARE(obj4.type(), QSqlError::NoError);
QCOMPARE(obj4.number(), -1);
QCOMPARE(obj4.nativeErrorCode(), QString());
@@ -180,6 +182,28 @@ void tst_QSqlError::operators()
QVERIFY(error1 != error3);
}
+void tst_QSqlError::qtbug_74575()
+{
+ const QString driverText(QStringLiteral("drivertext"));
+ const QString databaseText(QStringLiteral("databasetext"));
+ const QString databaseTextNewline(QStringLiteral("databasetext\n"));
+
+ QSqlError error1(driverText, databaseText,
+ QSqlError::UnknownError, QStringLiteral("123"));
+ QCOMPARE(error1.text(), databaseText + QLatin1Char(' ') + driverText);
+
+ QSqlError error2(QString(), databaseText,
+ QSqlError::UnknownError, QStringLiteral("123"));
+ QCOMPARE(error2.text(), databaseText);
+
+ QSqlError error3(driverText, QString(),
+ QSqlError::UnknownError, QStringLiteral("123"));
+ QCOMPARE(error3.text(), driverText);
+
+ QSqlError error4(driverText, databaseTextNewline,
+ QSqlError::UnknownError, QStringLiteral("123"));
+ QCOMPARE(error4.text(), databaseTextNewline + driverText);
+}
QTEST_MAIN(tst_QSqlError)
#include "tst_qsqlerror.moc"
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index 710f26b72d..784d0a70d7 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -1098,7 +1098,7 @@ void tst_QSqlQuery::record()
for (int i = 0; i < 3; ++i)
QCOMPARE(q.record().field(i).tableName().toLower(), lowerQTest);
q.clear();
- const auto tst_record = qTableName("tst_record", __FILE__, db).toLower();
+ const auto tst_record = qTableName("tst_record", __FILE__, db, false).toLower();
SETUP_RECORD_TABLE;
CHECK_RECORD;
q.clear();
@@ -3763,15 +3763,13 @@ void tst_QSqlQuery::QTBUG_5251()
const QString timetest(qTableName("timetest", __FILE__, db));
tst_Databases::safeDropTable(db, timetest);
QSqlQuery q(db);
- QVERIFY_SQL(q, exec(QStringLiteral("CREATE TABLE \"") + timetest + QStringLiteral("\" (t TIME)")));
- QVERIFY_SQL(q, exec(QStringLiteral("INSERT INTO \"") + timetest +
- QStringLiteral("\" VALUES ('1:2:3.666')")));
+ QVERIFY_SQL(q, exec(QStringLiteral("CREATE TABLE ") + timetest + QStringLiteral(" (t TIME)")));
+ QVERIFY_SQL(q, exec(QStringLiteral("INSERT INTO ") + timetest +
+ QStringLiteral(" VALUES ('1:2:3.666')")));
QSqlTableModel timetestModel(0,db);
timetestModel.setEditStrategy(QSqlTableModel::OnManualSubmit);
timetestModel.setTable(timetest);
- if (tst_Databases::getDatabaseType(db) == QSqlDriver::PostgreSQL)
- QEXPECT_FAIL("", "Currently broken for PostgreSQL due to case sensitivity problems - see QTBUG-65788", Abort);
QVERIFY_SQL(timetestModel, select());
QCOMPARE(timetestModel.record(0).field(0).value().toTime().toString("HH:mm:ss.zzz"), QString("01:02:03.666"));
@@ -3780,8 +3778,8 @@ void tst_QSqlQuery::QTBUG_5251()
QVERIFY_SQL(timetestModel, submitAll());
QCOMPARE(timetestModel.record(0).field(0).value().toTime().toString("HH:mm:ss.zzz"), QString("00:12:34.500"));
- QVERIFY_SQL(q, exec(QStringLiteral("UPDATE \"") + timetest +
- QStringLiteral("\" SET t = '0:11:22.33'")));
+ QVERIFY_SQL(q, exec(QStringLiteral("UPDATE ") + timetest +
+ QStringLiteral(" SET t = '0:11:22.33'")));
QVERIFY_SQL(timetestModel, select());
QCOMPARE(timetestModel.record(0).field(0).value().toTime().toString("HH:mm:ss.zzz"), QString("00:11:22.330"));
diff --git a/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp b/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
index 09a842eb83..aa2cc05b56 100644
--- a/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
+++ b/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
@@ -345,7 +345,7 @@ void tst_QSqlThread::cleanupTestCase()
void tst_QSqlThread::init()
{
threadFinishedCount = 0;
- counter.store(4);
+ counter.storeRelaxed(4);
}
void tst_QSqlThread::cleanup()
diff --git a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
index e4a277e096..722ef9c570 100644
--- a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
+++ b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
@@ -122,13 +122,13 @@ void tst_QSqlRelationalTableModel::recreateTestTables(QSqlDatabase db)
QVERIFY_SQL( q, exec("insert into " + reltest5 + " values('mister', 'Mr')"));
if (testWhiteSpaceNames(db.driverName())) {
- QString reltest6 = db.driver()->escapeIdentifier(qTableName("rel", __FILE__, db) + " test6", QSqlDriver::TableName);
+ const auto reltest6 = qTableName("rel test6", __FILE__, db);
QVERIFY_SQL( q, exec("create table " + reltest6 + " (id int not null primary key, " + db.driver()->escapeIdentifier("city key", QSqlDriver::FieldName) +
" int, " + db.driver()->escapeIdentifier("extra field", QSqlDriver::FieldName) + " int)"));
QVERIFY_SQL( q, exec("insert into " + reltest6 + " values(1, 1,9)"));
QVERIFY_SQL( q, exec("insert into " + reltest6 + " values(2, 2,8)"));
- QString reltest7 = db.driver()->escapeIdentifier(qTableName("rel", __FILE__, db) + " test7", QSqlDriver::TableName);
+ const auto reltest7 = qTableName("rel test7", __FILE__, db);
QVERIFY_SQL( q, exec("create table " + reltest7 + " (" + db.driver()->escapeIdentifier("city id", QSqlDriver::TableName) + " int not null primary key, " + db.driver()->escapeIdentifier("city name", QSqlDriver::FieldName) + " varchar(20))"));
QVERIFY_SQL( q, exec("insert into " + reltest7 + " values(1, 'New York')"));
QVERIFY_SQL( q, exec("insert into " + reltest7 + " values(2, 'Washington')"));
@@ -170,8 +170,8 @@ void tst_QSqlRelationalTableModel::dropTestTables( QSqlDatabase db )
<< reltest3
<< reltest4
<< reltest5
- << (qTableName("rel", __FILE__, db) + " test6")
- << (qTableName( "rel", __FILE__, db) + " test7")
+ << qTableName("rel test6", __FILE__, db)
+ << qTableName("rel test7", __FILE__, db)
<< qTableName("CASETEST1", db)
<< qTableName("casetest1", db);
tst_Databases::safeDropTables( db, tableNames );
@@ -1379,9 +1379,9 @@ void tst_QSqlRelationalTableModel::whiteSpaceInIdentifiers()
if (!testWhiteSpaceNames(db.driverName()))
QSKIP("White space test irrelevant for driver");
QSqlRelationalTableModel model(0, db);
- model.setTable(db.driver()->escapeIdentifier(qTableName("rel", __FILE__, db) + " test6", QSqlDriver::TableName));
+ model.setTable(qTableName("rel test6", __FILE__, db));
model.setSort(0, Qt::DescendingOrder);
- model.setRelation(1, QSqlRelation(db.driver()->escapeIdentifier(qTableName("rel", __FILE__, db) + " test7", QSqlDriver::TableName),
+ model.setRelation(1, QSqlRelation(qTableName("rel test7", __FILE__, db),
db.driver()->escapeIdentifier("city id", QSqlDriver::FieldName),
db.driver()->escapeIdentifier("city name", QSqlDriver::FieldName)));
QVERIFY_SQL(model, select());
@@ -1547,8 +1547,6 @@ void tst_QSqlRelationalTableModel::relationOnFirstColumn()
//modify the model data
QVERIFY_SQL(model, setData(model.index(0, 0), 40));
- if (tst_Databases::getDatabaseType(db) == QSqlDriver::PostgreSQL)
- QEXPECT_FAIL("", "Currently broken for PostgreSQL due to case sensitivity problems - see QTBUG-65788", Abort);
QVERIFY_SQL(model, submit());
QVERIFY_SQL(model, setData(model.index(1, 0), 50));
QVERIFY_SQL(model, submit());
diff --git a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
index da31f437d9..44dd4a74cf 100644
--- a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
+++ b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
@@ -32,6 +32,7 @@
#include <QtSql>
#include <QtSql/private/qsqltablemodel_p.h>
#include <QThread>
+#include <QElapsedTimer>
const QString test(qTableName("test", __FILE__, QSqlDatabase())),
test2(qTableName("test2", __FILE__, QSqlDatabase())),
@@ -383,8 +384,6 @@ void tst_QSqlTableModel::selectRow()
q.exec("UPDATE " + tbl + " SET a = 'Qt' WHERE id = 1");
QCOMPARE(model.data(idx).toString(), QString("b"));
model.selectRow(1);
- if (tst_Databases::getDatabaseType(db) == QSqlDriver::PostgreSQL)
- QEXPECT_FAIL("", "Currently broken for PostgreSQL due to case sensitivity problems - see QTBUG-65788", Abort);
QCOMPARE(model.data(idx).toString(), QString("Qt"));
// Check if selectRow() refreshes a changed row.
@@ -441,8 +440,6 @@ void tst_QSqlTableModel::selectRowOverride()
// both rows should have changed
QCOMPARE(model.data(idx).toString(), QString("Qt"));
idx = model.index(2, 1);
- if (tst_Databases::getDatabaseType(db) == QSqlDriver::PostgreSQL)
- QEXPECT_FAIL("", "Currently broken for PostgreSQL due to case sensitivity problems - see QTBUG-65788", Abort);
QCOMPARE(model.data(idx).toString(), QString("Qt"));
q.exec("DELETE FROM " + tbl);
@@ -854,8 +851,6 @@ void tst_QSqlTableModel::insertRowFailure()
// populate 1 row
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
- if (dbType == QSqlDriver::PostgreSQL && submitpolicy != QSqlTableModel::OnManualSubmit)
- QEXPECT_FAIL("", "Currently broken for PostgreSQL due to case sensitivity problems - see QTBUG-65788", Abort);
QVERIFY_SQL(model, insertRecord(0, values));
QVERIFY_SQL(model, submitAll());
QVERIFY_SQL(model, select());
@@ -899,8 +894,6 @@ void tst_QSqlTableModel::insertRowFailure()
// restore empty table
model.revertAll();
QVERIFY_SQL(model, removeRow(0));
- if (dbType == QSqlDriver::PostgreSQL)
- QEXPECT_FAIL("", "Currently broken for PostgreSQL due to case sensitivity problems - see QTBUG-65788", Abort);
QVERIFY_SQL(model, submitAll());
QVERIFY_SQL(model, select());
QCOMPARE(model.rowCount(), 0);
@@ -1812,12 +1805,12 @@ void tst_QSqlTableModel::sqlite_bigTable()
QSqlQuery q(db);
QVERIFY_SQL( q, exec("create table "+bigtable+"(id int primary key, name varchar)"));
QVERIFY_SQL( q, prepare("insert into "+bigtable+"(id, name) values (?, ?)"));
- QTime startTime;
- startTime.start();
+ QElapsedTimer timing;
+ timing.start();
for (int i = 0; i < 10000; ++i) {
q.addBindValue(i);
q.addBindValue(QString::number(i));
- if(i%1000 == 0 && startTime.elapsed() > 5000)
+ if (i % 1000 == 0 && timing.elapsed() > 5000)
qDebug() << i << "records written";
QVERIFY_SQL( q, exec());
}
@@ -2009,8 +2002,6 @@ void tst_QSqlTableModel::tableModifyWithBlank()
//Should be equivalent to QSqlQuery INSERT INTO... command)
QVERIFY_SQL(model, insertRow(0));
QVERIFY_SQL(model, setData(model.index(0,0),timeString));
- if (tst_Databases::getDatabaseType(db) == QSqlDriver::PostgreSQL)
- QEXPECT_FAIL("", "Currently broken for PostgreSQL due to case sensitivity problems - see QTBUG-65788", Abort);
QVERIFY_SQL(model, submitAll());
//set a filter on the table so the only record we get is the one we just made
diff --git a/tests/auto/testlib/outformat/outformat.pro b/tests/auto/testlib/outformat/outformat.pro
new file mode 100644
index 0000000000..ea02f3167f
--- /dev/null
+++ b/tests/auto/testlib/outformat/outformat.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase
+QT = core testlib
+
+SOURCES += tst_outformat.cpp
+TARGET = outformat
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/outformat/tst_outformat.cpp b/tests/auto/testlib/outformat/tst_outformat.cpp
new file mode 100644
index 0000000000..5d131159a9
--- /dev/null
+++ b/tests/auto/testlib/outformat/tst_outformat.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+class tst_OutFormat : public QObject
+{
+ Q_OBJECT
+private slots:
+ void toHex_data() const;
+ void toHex() const;
+ // other formats of interest ?
+};
+
+void tst_OutFormat::toHex_data() const
+{
+ QTest::addColumn<QByteArray>("raw");
+ QTest::addColumn<QByteArray>("hex");
+
+ QTest::newRow("empty") << QByteArray("") << QByteArray("");
+ QTest::newRow("long")
+ << QByteArray("Truncates in ellipsis when more than fifty characters long")
+ << QByteArray("54 72 75 6E 63 61 74 65 73 20 69 6E 20 65 6C 6C "
+ "69 70 73 69 73 20 77 68 65 6E 20 6D 6F 72 65 20 "
+ "74 68 61 6E 20 66 69 66 74 79 20 63 68 61 72 61 "
+ "63 74 ...");
+ QTest::newRow("spaces")
+ << QByteArray(" \t\n\v\f\r") << QByteArray("20 09 0A 0B 0C 0D");
+ QTest::newRow("ASCII-escapes")
+ << QByteArray("\a\b\\\"'\177") << QByteArray("07 08 5C 22 27 7F");
+ // These are the ISO Latin-15 &nbsp;, pound, Euro, ..., y-umlaut
+ QTest::newRow("8-bit-sampler")
+ << QByteArray("\240\243\244\261\327\360\377") << QByteArray("A0 A3 A4 B1 D7 F0 FF");
+}
+
+void tst_OutFormat::toHex() const
+{
+ QFETCH(QByteArray, raw);
+ QFETCH(QByteArray, hex);
+ QScopedArrayPointer<char> repr(QTest::toHexRepresentation(raw.constData(), raw.size()));
+ QCOMPARE(repr.data(), hex);
+}
+
+QTEST_APPLESS_MAIN(tst_OutFormat)
+
+#include "tst_outformat.moc"
diff --git a/tests/auto/testlib/qabstractitemmodeltester/qabstractitemmodeltester.pro b/tests/auto/testlib/qabstractitemmodeltester/qabstractitemmodeltester.pro
index 306e8089f3..1aefc544d1 100644
--- a/tests/auto/testlib/qabstractitemmodeltester/qabstractitemmodeltester.pro
+++ b/tests/auto/testlib/qabstractitemmodeltester/qabstractitemmodeltester.pro
@@ -11,3 +11,5 @@ SOURCES += \
HEADERS += \
$${mtdir}/dynamictreemodel.h
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp b/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
index 0593ae74bf..b305eee0ec 100644
--- a/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
+++ b/tests/auto/testlib/qabstractitemmodeltester/tst_qabstractitemmodeltester.cpp
@@ -63,7 +63,7 @@ void tst_QAbstractItemModelTester::stringListModel()
model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c");
proxy.setDynamicSortFilter(true);
- proxy.setFilterRegExp(QRegExp("[^b]"));
+ proxy.setFilterRegularExpression(QRegularExpression("[^b]"));
}
void tst_QAbstractItemModelTester::treeWidgetModel()
@@ -79,9 +79,9 @@ void tst_QAbstractItemModelTester::treeWidgetModel()
root->removeChild(remove);
QTreeWidgetItem *parent = new QTreeWidgetItem(&widget, QStringList("parent"));
new QTreeWidgetItem(parent, QStringList("child"));
- widget.setItemHidden(parent, true);
+ parent->setHidden(true);
- widget.sortByColumn(0);
+ widget.sortByColumn(0, Qt::AscendingOrder);
}
void tst_QAbstractItemModelTester::standardItemModel()
diff --git a/tests/auto/testlib/qsignalspy/qsignalspy.pro b/tests/auto/testlib/qsignalspy/qsignalspy.pro
index 1578802bf8..5343a98c14 100644
--- a/tests/auto/testlib/qsignalspy/qsignalspy.pro
+++ b/tests/auto/testlib/qsignalspy/qsignalspy.pro
@@ -2,3 +2,5 @@ CONFIG += testcase
TARGET = tst_qsignalspy
SOURCES += tst_qsignalspy.cpp
QT = core testlib
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/alive/.gitignore b/tests/auto/testlib/selftests/alive/.gitignore
deleted file mode 100644
index 561285c5d0..0000000000
--- a/tests/auto/testlib/selftests/alive/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-tst_alive
diff --git a/tests/auto/testlib/selftests/alive/alive.pro b/tests/auto/testlib/selftests/alive/alive.pro
deleted file mode 100644
index d3df09b10d..0000000000
--- a/tests/auto/testlib/selftests/alive/alive.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-SOURCES += tst_alive.cpp
-QT = core testlib
-
-mac:CONFIG -= app_bundle
-CONFIG -= debug_and_release_target
-
-
-TARGET = alive
diff --git a/tests/auto/testlib/selftests/alive/qtestalive.cpp b/tests/auto/testlib/selftests/alive/qtestalive.cpp
deleted file mode 100644
index 0200f2a563..0000000000
--- a/tests/auto/testlib/selftests/alive/qtestalive.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include <qcoreapplication.h>
-#include <qcoreevent.h>
-#include <qthread.h>
-
-class QTestAliveEvent: public QEvent
-{
-public:
-
- enum { AliveEventType = QEvent::User + 422 };
-
- explicit inline QTestAliveEvent(int aSequenceId)
- : QEvent(QEvent::Type(AliveEventType)), seqId(aSequenceId)
- {}
- inline int sequenceId() const { return seqId; }
-
-private:
- int seqId;
-};
-
-class QTestAlivePinger: public QObject
-{
-public:
- QTestAlivePinger(QObject *receiver, QObject *parent = 0);
- bool event(QEvent *e);
-
-protected:
- void timerEvent(QTimerEvent *event);
-
-private:
- QObject *rec;
- int timerId;
- int currentSequenceId;
- int lastSequenceId;
-};
-
-QTestAlivePinger::QTestAlivePinger(QObject *receiver, QObject *parent)
- : QObject(parent), rec(receiver), currentSequenceId(0), lastSequenceId(0)
-{
- if (!rec)
- qFatal("Null receiver object passed to QTestAlivePinger::QTestAlivePinger()");
- timerId = startTimer(850);
-}
-
-bool QTestAlivePinger::event(QEvent *event)
-{
- // pong received
- if (int(event->type()) == QTestAliveEvent::AliveEventType) {
- QTestAliveEvent *e = static_cast<QTestAliveEvent *>(event);
- //qDebug("PONG %d received", e->sequenceId());
- // if the events are not delivered in order, we don't care.
- if (e->sequenceId() > lastSequenceId)
- lastSequenceId = e->sequenceId();
- return true;
- }
- return QObject::event(event);
-}
-
-void QTestAlivePinger::timerEvent(QTimerEvent *event)
-{
- if (event->timerId() != timerId)
- return;
-
- if (lastSequenceId < currentSequenceId - 2) {
- qWarning("TEST LAGS %d PINGS behind!", currentSequenceId - lastSequenceId);
- }
- ++currentSequenceId;
- //qDebug("PING %d", currentSequenceId);
- QCoreApplication::postEvent(rec, new QTestAliveEvent(currentSequenceId));
-}
-
-class QTestAlive: public QThread
-{
-public:
- QTestAlive(QObject *parent = 0);
- ~QTestAlive();
- void run();
-
- bool event(QEvent *e);
-
-private:
- QTestAlivePinger *pinger;
-};
-
-QTestAlive::QTestAlive(QObject *parent)
- : QThread(parent), pinger(0)
-{
-}
-
-QTestAlive::~QTestAlive()
-{
- quit();
- while (isRunning());
-}
-
-bool QTestAlive::event(QEvent *e)
-{
- if (int(e->type()) == QTestAliveEvent::AliveEventType && pinger) {
- // ping received, send back the pong
- //qDebug("PONG %d", static_cast<QTestAliveEvent *>(e)->sequenceId());
- QCoreApplication::postEvent(pinger,
- new QTestAliveEvent(static_cast<QTestAliveEvent *>(e)->sequenceId()));
- return true;
- }
- return QThread::event(e);
-}
-
-void QTestAlive::run()
-{
- if (!QCoreApplication::instance())
- qFatal("QTestAlive::run(): Cannot start QTestAlive without a QCoreApplication instance.");
-
- QTestAlivePinger p(this);
- pinger = &p;
- exec();
- pinger = 0;
-}
-
-
diff --git a/tests/auto/testlib/selftests/assert/assert.pro b/tests/auto/testlib/selftests/assert/assert.pro
index cfc6a0c6b3..0692b6bdf2 100644
--- a/tests/auto/testlib/selftests/assert/assert.pro
+++ b/tests/auto/testlib/selftests/assert/assert.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = assert
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/badxml/badxml.pro b/tests/auto/testlib/selftests/badxml/badxml.pro
index 7b3b0f701c..4e15886504 100644
--- a/tests/auto/testlib/selftests/badxml/badxml.pro
+++ b/tests/auto/testlib/selftests/badxml/badxml.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = badxml
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/benchlibcallgrind/benchlibcallgrind.pro b/tests/auto/testlib/selftests/benchlibcallgrind/benchlibcallgrind.pro
index 6cbefe518c..12f068843e 100644
--- a/tests/auto/testlib/selftests/benchlibcallgrind/benchlibcallgrind.pro
+++ b/tests/auto/testlib/selftests/benchlibcallgrind/benchlibcallgrind.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = benchlibcallgrind
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/benchlibcallgrind/tst_benchlibcallgrind.cpp b/tests/auto/testlib/selftests/benchlibcallgrind/tst_benchlibcallgrind.cpp
index 0d3e884a56..fe83ee6608 100644
--- a/tests/auto/testlib/selftests/benchlibcallgrind/tst_benchlibcallgrind.cpp
+++ b/tests/auto/testlib/selftests/benchlibcallgrind/tst_benchlibcallgrind.cpp
@@ -68,9 +68,9 @@ void tst_BenchlibCallgrind::twoHundredMillionInstructions()
QBENCHMARK {
__asm__ __volatile__(
"mov $100000000,%%eax \n"
- "LOOPTOP: \n"
+ "1: \n"
"dec %%eax \n"
- "jnz LOOPTOP \n"
+ "jnz 1b \n"
: /* no output */
: /* no input */
: /* clobber */ "eax"
diff --git a/tests/auto/testlib/selftests/benchlibcounting/benchlibcounting.pro b/tests/auto/testlib/selftests/benchlibcounting/benchlibcounting.pro
index b495995eac..786511d057 100644
--- a/tests/auto/testlib/selftests/benchlibcounting/benchlibcounting.pro
+++ b/tests/auto/testlib/selftests/benchlibcounting/benchlibcounting.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = benchlibcounting
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/benchlibeventcounter/benchlibeventcounter.pro b/tests/auto/testlib/selftests/benchlibeventcounter/benchlibeventcounter.pro
index 5e2b963491..98fa0e4567 100644
--- a/tests/auto/testlib/selftests/benchlibeventcounter/benchlibeventcounter.pro
+++ b/tests/auto/testlib/selftests/benchlibeventcounter/benchlibeventcounter.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = benchlibeventcounter
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/benchliboptions/benchliboptions.pro b/tests/auto/testlib/selftests/benchliboptions/benchliboptions.pro
index f4bcc92129..0b627ecb10 100644
--- a/tests/auto/testlib/selftests/benchliboptions/benchliboptions.pro
+++ b/tests/auto/testlib/selftests/benchliboptions/benchliboptions.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = benchliboptions
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/benchlibtickcounter/benchlibtickcounter.pro b/tests/auto/testlib/selftests/benchlibtickcounter/benchlibtickcounter.pro
index ce0ec7012c..f0741d5c26 100644
--- a/tests/auto/testlib/selftests/benchlibtickcounter/benchlibtickcounter.pro
+++ b/tests/auto/testlib/selftests/benchlibtickcounter/benchlibtickcounter.pro
@@ -6,3 +6,5 @@ CONFIG -= debug_and_release_target
TARGET = benchlibtickcounter
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/benchlibwalltime/benchlibwalltime.pro b/tests/auto/testlib/selftests/benchlibwalltime/benchlibwalltime.pro
index 0e689871ab..80d97a2422 100644
--- a/tests/auto/testlib/selftests/benchlibwalltime/benchlibwalltime.pro
+++ b/tests/auto/testlib/selftests/benchlibwalltime/benchlibwalltime.pro
@@ -6,3 +6,5 @@ CONFIG -= debug_and_release_target
TARGET = benchlibwalltime
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/blacklisted/BLACKLIST b/tests/auto/testlib/selftests/blacklisted/BLACKLIST
index 36b7699cbd..a923c11416 100644
--- a/tests/auto/testlib/selftests/blacklisted/BLACKLIST
+++ b/tests/auto/testlib/selftests/blacklisted/BLACKLIST
@@ -1,12 +1,20 @@
-[pass]
+obscure # no such platform; is ignored
*
+
+[pass]
+!*
+
[skip]
*
+
[fail]
*
-[xpass]
-*
+
[xfail]
*
+
+[xpass]
+*
+
[messages]
*
diff --git a/tests/auto/testlib/selftests/blacklisted/blacklisted.pro b/tests/auto/testlib/selftests/blacklisted/blacklisted.pro
index 5bd22910b1..a8602ee266 100644
--- a/tests/auto/testlib/selftests/blacklisted/blacklisted.pro
+++ b/tests/auto/testlib/selftests/blacklisted/blacklisted.pro
@@ -5,3 +5,5 @@ mac: CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = blacklisted
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp b/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
index b25489ca00..49c08982ad 100644
--- a/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
+++ b/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
@@ -45,7 +45,8 @@ private slots:
void messages();
};
-// All the tests below have been blacklisted in blacklisted/BLACKLIST
+// All the tests below except pass() have been blacklisted in blacklisted/BLACKLIST
+// Contrast with ../silent/, for the same tests without blacklisting but with -silent
void tst_Blacklisted::pass()
{
@@ -74,6 +75,17 @@ void tst_Blacklisted::xpass()
QVERIFY2(true, "This test should BXPASS");
}
+#ifndef Q_OS_WIN
+#include <signal.h>
+#include <setjmp.h>
+
+static jmp_buf state;
+static void abort_handler(int signal)
+{
+ longjmp(state, 1);
+}
+#endif
+
void tst_Blacklisted::messages()
{
qWarning("This is a warning that should not appear in silent test output");
@@ -82,7 +94,15 @@ void tst_Blacklisted::messages()
qCritical("This is a critical message that should not appear in silent test output");
qInfo("This is an info message that should not appear in silent test output");
QTestLog::info("This is an internal testlib info message that should not appear in silent test output", __FILE__, __LINE__);
- qFatal("This is a fatal error message that should still appear in silent test output");
+
+#ifndef Q_OS_WIN
+ // We're testing qFatal, but we don't want to actually std::abort() !
+ auto prior = signal(SIGABRT, abort_handler);
+ if (setjmp(state))
+ signal(SIGABRT, prior);
+ else
+#endif
+ qFatal("This is a fatal error message that should still appear in silent test output");
}
QTEST_MAIN(tst_Blacklisted)
diff --git a/tests/auto/testlib/selftests/cmptest/cmptest.pro b/tests/auto/testlib/selftests/cmptest/cmptest.pro
index 2d5dd071a9..f38f5ecce1 100644
--- a/tests/auto/testlib/selftests/cmptest/cmptest.pro
+++ b/tests/auto/testlib/selftests/cmptest/cmptest.pro
@@ -6,3 +6,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = cmptest
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
index 8e2c7694a5..467c53088e 100644
--- a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+++ b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
@@ -256,7 +256,7 @@ void tst_Cmptest::compare_boolfuncs()
namespace {
template <typename T>
-T *null() Q_DECL_NOTHROW { return nullptr; }
+T *null() noexcept { return nullptr; }
}
void tst_Cmptest::compare_to_nullptr()
diff --git a/tests/auto/testlib/selftests/commandlinedata/commandlinedata.pro b/tests/auto/testlib/selftests/commandlinedata/commandlinedata.pro
index 056388333a..8032ba5a02 100644
--- a/tests/auto/testlib/selftests/commandlinedata/commandlinedata.pro
+++ b/tests/auto/testlib/selftests/commandlinedata/commandlinedata.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = commandlinedata
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/counting/counting.pro b/tests/auto/testlib/selftests/counting/counting.pro
index 8aa2fe5753..be3a5339b0 100644
--- a/tests/auto/testlib/selftests/counting/counting.pro
+++ b/tests/auto/testlib/selftests/counting/counting.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = counting
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/crashes/crashes.pro b/tests/auto/testlib/selftests/crashes/crashes.pro
index 25e24243d1..00fa07a415 100644
--- a/tests/auto/testlib/selftests/crashes/crashes.pro
+++ b/tests/auto/testlib/selftests/crashes/crashes.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = crashes
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/datatable/datatable.pro b/tests/auto/testlib/selftests/datatable/datatable.pro
index 72fa851ae6..12a1f697b1 100644
--- a/tests/auto/testlib/selftests/datatable/datatable.pro
+++ b/tests/auto/testlib/selftests/datatable/datatable.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = datatable
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/datetime/datetime.pro b/tests/auto/testlib/selftests/datetime/datetime.pro
index d65c59354f..1524281090 100644
--- a/tests/auto/testlib/selftests/datetime/datetime.pro
+++ b/tests/auto/testlib/selftests/datetime/datetime.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = datetime
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/deleteLater/deleteLater.pro b/tests/auto/testlib/selftests/deleteLater/deleteLater.pro
index 6847238b1d..9a10096461 100644
--- a/tests/auto/testlib/selftests/deleteLater/deleteLater.pro
+++ b/tests/auto/testlib/selftests/deleteLater/deleteLater.pro
@@ -5,3 +5,5 @@ CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = tst_deleteLater
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/deleteLater_noApp/deleteLater_noApp.pro b/tests/auto/testlib/selftests/deleteLater_noApp/deleteLater_noApp.pro
index f860a767cd..6f2b253c14 100644
--- a/tests/auto/testlib/selftests/deleteLater_noApp/deleteLater_noApp.pro
+++ b/tests/auto/testlib/selftests/deleteLater_noApp/deleteLater_noApp.pro
@@ -5,3 +5,5 @@ CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = tst_deleteLater_noApp
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/differentexec/differentexec.pro b/tests/auto/testlib/selftests/differentexec/differentexec.pro
index 7f148ba996..339962f609 100644
--- a/tests/auto/testlib/selftests/differentexec/differentexec.pro
+++ b/tests/auto/testlib/selftests/differentexec/differentexec.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = differentexec
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/exceptionthrow/exceptionthrow.pro b/tests/auto/testlib/selftests/exceptionthrow/exceptionthrow.pro
index fe89f6f3cd..5473ec32c3 100644
--- a/tests/auto/testlib/selftests/exceptionthrow/exceptionthrow.pro
+++ b/tests/auto/testlib/selftests/exceptionthrow/exceptionthrow.pro
@@ -6,3 +6,5 @@ CONFIG -= debug_and_release_target
CONFIG += exceptions
TARGET = exceptionthrow
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/expected_blacklisted.tap b/tests/auto/testlib/selftests/expected_blacklisted.tap
index 7d3b2b0cc8..35f6d3df50 100644
--- a/tests/auto/testlib/selftests/expected_blacklisted.tap
+++ b/tests/auto/testlib/selftests/expected_blacklisted.tap
@@ -11,16 +11,16 @@ not ok 4 - fail() # TODO 'false' returned FALSE. (This test should BFAIL)
found: false (false)
expected: true (false)
actual: false (false)
- at: tst_Blacklisted::fail() (qtbase/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp:62)
+ at: tst_Blacklisted::fail() (qtbase/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp:63)
file: qtbase/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
- line: 62
+ line: 63
...
not ok 4 - xfail() # TODO This test should BXFAIL then BPASS
---
# This test should BXFAIL then BPASS
- at: tst_Blacklisted::xfail() (qtbase/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp:68)
+ at: tst_Blacklisted::xfail() (qtbase/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp:69)
file: qtbase/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
- line: 68
+ line: 69
...
ok 5 - xfail() # TODO
ok 6 - xpass() # TODO 'true' returned TRUE unexpectedly. (This test should BXPASS)
diff --git a/tests/auto/testlib/selftests/expected_crashes_5.txt b/tests/auto/testlib/selftests/expected_crashes_5.txt
new file mode 100644
index 0000000000..088b9c5324
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_crashes_5.txt
@@ -0,0 +1,5 @@
+********* Start testing of tst_Crashes *********
+Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@
+PASS : tst_Crashes::initTestCase()
+QFATAL : tst_Crashes::crash() Received signal 11
+ Function time: ms Total time: ms
diff --git a/tests/auto/testlib/selftests/expected_faildatatype.lightxml b/tests/auto/testlib/selftests/expected_faildatatype.lightxml
new file mode 100644
index 0000000000..24992b78af
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_faildatatype.lightxml
@@ -0,0 +1,22 @@
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="value">
+<Message type="qdebug" file="" line="0">
+ <Description><![CDATA[expected data of type 'QString', got 'bool' for element 0 of data with tag 'bool-as-string']]></Description>
+</Message>
+<Message type="qfatal" file="" line="0">
+ <Description><![CDATA[ASSERT: "false" in file qtbase/src/testlib/qtestdata.cpp, line 0]]></Description>
+</Message>
+<Incident type="fail" file="Unknown file" line="0">
+ <Description><![CDATA[Received a fatal error.]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_faildatatype.tap b/tests/auto/testlib/selftests/expected_faildatatype.tap
new file mode 100644
index 0000000000..684cea4126
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_faildatatype.tap
@@ -0,0 +1,16 @@
+TAP version 13
+# tst_FailDataType
+ok 1 - initTestCase()
+# expected data of type 'QString', got 'bool' for element 0 of data with tag 'bool-as-string'
+# ASSERT: "false" in file qtbase/src/testlib/qtestdata.cpp, line 0
+not ok 2 - value()
+ ---
+ # Received a fatal error.
+ at: tst_FailDataType::value() (Unknown file:0)
+ file: Unknown file
+ line: 0
+ ...
+1..2
+# tests 2
+# pass 1
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_faildatatype.teamcity b/tests/auto/testlib/selftests/expected_faildatatype.teamcity
new file mode 100644
index 0000000000..82731ae09e
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_faildatatype.teamcity
@@ -0,0 +1,8 @@
+##teamcity[testSuiteStarted name='tst_FailDataType' flowId='tst_FailDataType']
+##teamcity[testStarted name='initTestCase()' flowId='tst_FailDataType']
+##teamcity[testFinished name='initTestCase()' flowId='tst_FailDataType']
+##teamcity[testStarted name='value()' flowId='tst_FailDataType']
+##teamcity[testFailed name='value()' message='Failure! |[Loc: Unknown file(0)|]' details='Received a fatal error.' flowId='tst_FailDataType']
+##teamcity[testStdOut name='value()' out='QDEBUG: expected data of type |'QString|', got |'bool|' for element 0 of data with tag |'bool-as-string|'|nQFATAL: ASSERT: "false" in file qtbase/src/testlib/qtestdata.cpp, line 0' flowId='tst_FailDataType']
+##teamcity[testFinished name='value()' flowId='tst_FailDataType']
+##teamcity[testSuiteFinished name='tst_FailDataType' flowId='tst_FailDataType']
diff --git a/tests/auto/testlib/selftests/expected_faildatatype.txt b/tests/auto/testlib/selftests/expected_faildatatype.txt
new file mode 100644
index 0000000000..4cfe3b7654
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_faildatatype.txt
@@ -0,0 +1,9 @@
+********* Start testing of tst_FailDataType *********
+Config: Using QtTest library
+PASS : tst_FailDataType::initTestCase()
+QDEBUG : tst_FailDataType::value() expected data of type 'QString', got 'bool' for element 0 of data with tag 'bool-as-string'
+QFATAL : tst_FailDataType::value() ASSERT: "false" in file qtbase/src/testlib/qtestdata.cpp, line 0
+FAIL! : tst_FailDataType::value() Received a fatal error.
+ Loc: [Unknown file(0)]
+Totals: 1 passed, 1 failed, 0 skipped, 0 blacklisted, 0ms
+********* Finished testing of tst_FailDataType *********
diff --git a/tests/auto/testlib/selftests/expected_faildatatype.xml b/tests/auto/testlib/selftests/expected_faildatatype.xml
new file mode 100644
index 0000000000..8812bfab71
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_faildatatype.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestCase name="tst_FailDataType">
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="value">
+<Message type="qdebug" file="" line="0">
+ <Description><![CDATA[expected data of type 'QString', got 'bool' for element 0 of data with tag 'bool-as-string']]></Description>
+</Message>
+<Message type="qfatal" file="" line="0">
+ <Description><![CDATA[ASSERT: "false" in file qtbase/src/testlib/qtestdata.cpp, line 0]]></Description>
+</Message>
+<Incident type="fail" file="Unknown file" line="0">
+ <Description><![CDATA[Received a fatal error.]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
+</TestCase>
diff --git a/tests/auto/testlib/selftests/expected_faildatatype.xunitxml b/tests/auto/testlib/selftests/expected_faildatatype.xunitxml
new file mode 100644
index 0000000000..fcc0db3892
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_faildatatype.xunitxml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite errors="2" failures="1" tests="2" name="tst_FailDataType">
+ <properties>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
+ <property value="" name="QtBuild"/>
+ </properties>
+ <testcase result="pass" name="initTestCase"/>
+ <testcase result="fail" name="value">
+ <!-- message="expected data of type &apos;QString&apos;, got &apos;bool&apos; for element 0 of data with tag &apos;bool&#x002D;as&#x002D;string&apos;" type="qdebug" -->
+ <!-- message="ASSERT: &quot;false&quot; in file qtbase/src/testlib/qtestdata.cpp, line 92" type="qfatal" -->
+ <failure message="Received a fatal error." result="fail"/>
+ </testcase>
+ <system-err>
+<![CDATA[expected data of type 'QString', got 'bool' for element 0 of data with tag 'bool-as-string']]>
+<![CDATA[ASSERT: "false" in file qtbase/src/testlib/qtestdata.cpp, line 0]]>
+ </system-err>
+</testsuite>
diff --git a/tests/auto/testlib/selftests/expected_failfetchtype.lightxml b/tests/auto/testlib/selftests/expected_failfetchtype.lightxml
new file mode 100644
index 0000000000..f7c84a1876
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_failfetchtype.lightxml
@@ -0,0 +1,21 @@
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="fetch">
+<Message type="qfatal" file="" line="0">
+ <DataTag><![CDATA[bool]]></DataTag>
+ <Description><![CDATA[Requested type 'QString' does not match available type 'bool'.]]></Description>
+</Message>
+<Incident type="fail" file="Unknown file" line="0">
+ <DataTag><![CDATA[bool]]></DataTag>
+ <Description><![CDATA[Received a fatal error.]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_failfetchtype.tap b/tests/auto/testlib/selftests/expected_failfetchtype.tap
new file mode 100644
index 0000000000..94c3b6e1b2
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_failfetchtype.tap
@@ -0,0 +1,15 @@
+TAP version 13
+# tst_FailFetchType
+ok 1 - initTestCase()
+# Requested type 'QString' does not match available type 'bool'.
+not ok 2 - fetch(bool)
+ ---
+ # Received a fatal error.
+ at: tst_FailFetchType::fetch() (Unknown file:0)
+ file: Unknown file
+ line: 0
+ ...
+1..2
+# tests 2
+# pass 1
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_failfetchtype.teamcity b/tests/auto/testlib/selftests/expected_failfetchtype.teamcity
new file mode 100644
index 0000000000..91cf0c6ae8
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_failfetchtype.teamcity
@@ -0,0 +1,8 @@
+##teamcity[testSuiteStarted name='tst_FailFetchType' flowId='tst_FailFetchType']
+##teamcity[testStarted name='initTestCase()' flowId='tst_FailFetchType']
+##teamcity[testFinished name='initTestCase()' flowId='tst_FailFetchType']
+##teamcity[testStarted name='fetch(bool)' flowId='tst_FailFetchType']
+##teamcity[testFailed name='fetch(bool)' message='Failure! |[Loc: Unknown file(0)|]' details='Received a fatal error.' flowId='tst_FailFetchType']
+##teamcity[testStdOut name='fetch(bool)' out='QFATAL: Requested type |'QString|' does not match available type |'bool|'.' flowId='tst_FailFetchType']
+##teamcity[testFinished name='fetch(bool)' flowId='tst_FailFetchType']
+##teamcity[testSuiteFinished name='tst_FailFetchType' flowId='tst_FailFetchType']
diff --git a/tests/auto/testlib/selftests/expected_failfetchtype.txt b/tests/auto/testlib/selftests/expected_failfetchtype.txt
new file mode 100644
index 0000000000..d12cf0dc7d
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_failfetchtype.txt
@@ -0,0 +1,8 @@
+********* Start testing of tst_FailFetchType *********
+Config: Using QtTest library
+PASS : tst_FailFetchType::initTestCase()
+QFATAL : tst_FailFetchType::fetch(bool) Requested type 'QString' does not match available type 'bool'.
+FAIL! : tst_FailFetchType::fetch(bool) Received a fatal error.
+ Loc: [Unknown file(0)]
+Totals: 1 passed, 1 failed, 0 skipped, 0 blacklisted, 0ms
+********* Finished testing of tst_FailFetchType *********
diff --git a/tests/auto/testlib/selftests/expected_failfetchtype.xml b/tests/auto/testlib/selftests/expected_failfetchtype.xml
new file mode 100644
index 0000000000..a349baa710
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_failfetchtype.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestCase name="tst_FailFetchType">
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="fetch">
+<Message type="qfatal" file="" line="0">
+ <DataTag><![CDATA[bool]]></DataTag>
+ <Description><![CDATA[Requested type 'QString' does not match available type 'bool'.]]></Description>
+</Message>
+<Incident type="fail" file="Unknown file" line="0">
+ <DataTag><![CDATA[bool]]></DataTag>
+ <Description><![CDATA[Received a fatal error.]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
+</TestCase>
diff --git a/tests/auto/testlib/selftests/expected_failfetchtype.xunitxml b/tests/auto/testlib/selftests/expected_failfetchtype.xunitxml
new file mode 100644
index 0000000000..a54a37a913
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_failfetchtype.xunitxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite errors="1" failures="1" tests="2" name="tst_FailFetchType">
+ <properties>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
+ <property value="" name="QtBuild"/>
+ </properties>
+ <testcase result="pass" name="initTestCase"/>
+ <testcase result="fail" name="fetch">
+ <!-- tag="bool" message="Requested type &apos;QString&apos; does not match available type &apos;bool&apos;." type="qfatal" -->
+ <failure tag="bool" message="Received a fatal error." result="fail"/>
+ </testcase>
+ <system-err>
+<![CDATA[Requested type 'QString' does not match available type 'bool'.]]>
+ </system-err>
+</testsuite>
diff --git a/tests/auto/testlib/selftests/expected_float.lightxml b/tests/auto/testlib/selftests/expected_float.lightxml
index 79ce33627d..5f5114bb2e 100644
--- a/tests/auto/testlib/selftests/expected_float.lightxml
+++ b/tests/auto/testlib/selftests/expected_float.lightxml
@@ -8,15 +8,15 @@
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="doubleComparisons">
-<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[should PASS 1]]></DataTag>
-</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 1]]></DataTag>
<Description><![CDATA[Compared doubles are not the same (fuzzy compare)
Actual (operandLeft) : 1
Expected (operandRight): 3]]></Description>
</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 1]]></DataTag>
+</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 2]]></DataTag>
<Description><![CDATA[Compared doubles are not the same (fuzzy compare)
@@ -427,6 +427,216 @@
</Incident>
<Duration msecs="0"/>
</TestFunction>
+<TestFunction name="float16Comparisons">
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): 3]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 1]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 2]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0.0001
+ Expected (operandRight): 0.0003]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 2]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 3]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 98
+ Expected (operandRight): 99]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 3]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 4]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.93e-05
+ Expected (operandRight): 5.87e-05]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 4]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 5]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.94e+04
+ Expected (operandRight): 5.88e+04]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: NaN == NaN]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: NaN != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != NaN]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: NaN != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != NaN]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: inf == inf]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: -inf == -inf]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != nan]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: nan != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != nan]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: nan != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != -max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: max != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -max != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != -max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): -6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: max != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -max != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
<TestFunction name="compareFloatTests">
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[1e0]]></DataTag>
diff --git a/tests/auto/testlib/selftests/expected_float.tap b/tests/auto/testlib/selftests/expected_float.tap
index 1896bb2fb3..9da51b93b3 100644
--- a/tests/auto/testlib/selftests/expected_float.tap
+++ b/tests/auto/testlib/selftests/expected_float.tap
@@ -1,8 +1,7 @@
TAP version 13
# tst_float
ok 1 - initTestCase()
-ok 2 - doubleComparisons(should PASS 1)
-not ok 3 - doubleComparisons(should FAIL 1)
+not ok 2 - doubleComparisons(should FAIL 1)
---
type: QCOMPARE
message: Compared doubles are not the same (fuzzy compare)
@@ -10,10 +9,11 @@ not ok 3 - doubleComparisons(should FAIL 1)
found: 1 (operandLeft)
expected: 3 (operandRight)
actual: 1 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
+ok 3 - doubleComparisons(should PASS 1)
not ok 4 - doubleComparisons(should FAIL 2)
---
type: QCOMPARE
@@ -22,9 +22,9 @@ not ok 4 - doubleComparisons(should FAIL 2)
found: 1e-07 (operandLeft)
expected: 3e-07 (operandRight)
actual: 1e-07 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
ok 5 - doubleComparisons(should PASS 2)
not ok 6 - doubleComparisons(should FAIL 3)
@@ -35,9 +35,9 @@ not ok 6 - doubleComparisons(should FAIL 3)
found: 999999999999 (operandLeft)
expected: 999999999998 (operandRight)
actual: 999999999999 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
ok 7 - doubleComparisons(should PASS 3)
not ok 8 - doubleComparisons(should FAIL 4)
@@ -48,9 +48,9 @@ not ok 8 - doubleComparisons(should FAIL 4)
found: 9.99999999999e-311 (operandLeft)
expected: 9.99999999997e-311 (operandRight)
actual: 9.99999999999e-311 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
ok 9 - doubleComparisons(should PASS 4)
not ok 10 - doubleComparisons(should FAIL 5)
@@ -61,9 +61,9 @@ not ok 10 - doubleComparisons(should FAIL 5)
found: 9.99999999999e+306 (operandLeft)
expected: 9.99999999997e+306 (operandRight)
actual: 9.99999999999e+306 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
ok 11 - doubleComparisons(should PASS: NaN == NaN)
not ok 12 - doubleComparisons(should FAIL: NaN != 0)
@@ -74,9 +74,9 @@ not ok 12 - doubleComparisons(should FAIL: NaN != 0)
found: nan (operandLeft)
expected: 0 (operandRight)
actual: nan (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 13 - doubleComparisons(should FAIL: 0 != NaN)
---
@@ -86,9 +86,9 @@ not ok 13 - doubleComparisons(should FAIL: 0 != NaN)
found: 0 (operandLeft)
expected: nan (operandRight)
actual: 0 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 14 - doubleComparisons(should FAIL: NaN != 1)
---
@@ -98,9 +98,9 @@ not ok 14 - doubleComparisons(should FAIL: NaN != 1)
found: nan (operandLeft)
expected: 1 (operandRight)
actual: nan (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 15 - doubleComparisons(should FAIL: 1 != NaN)
---
@@ -110,9 +110,9 @@ not ok 15 - doubleComparisons(should FAIL: 1 != NaN)
found: 1 (operandLeft)
expected: nan (operandRight)
actual: 1 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
ok 16 - doubleComparisons(should PASS: inf == inf)
ok 17 - doubleComparisons(should PASS: -inf == -inf)
@@ -124,9 +124,9 @@ not ok 18 - doubleComparisons(should FAIL: inf != -inf)
found: inf (operandLeft)
expected: -inf (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 19 - doubleComparisons(should FAIL: -inf != inf)
---
@@ -136,9 +136,9 @@ not ok 19 - doubleComparisons(should FAIL: -inf != inf)
found: -inf (operandLeft)
expected: inf (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 20 - doubleComparisons(should FAIL: inf != nan)
---
@@ -148,9 +148,9 @@ not ok 20 - doubleComparisons(should FAIL: inf != nan)
found: inf (operandLeft)
expected: nan (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 21 - doubleComparisons(should FAIL: nan != inf)
---
@@ -160,9 +160,9 @@ not ok 21 - doubleComparisons(should FAIL: nan != inf)
found: nan (operandLeft)
expected: inf (operandRight)
actual: nan (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 22 - doubleComparisons(should FAIL: -inf != nan)
---
@@ -172,9 +172,9 @@ not ok 22 - doubleComparisons(should FAIL: -inf != nan)
found: -inf (operandLeft)
expected: nan (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 23 - doubleComparisons(should FAIL: nan != -inf)
---
@@ -184,9 +184,9 @@ not ok 23 - doubleComparisons(should FAIL: nan != -inf)
found: nan (operandLeft)
expected: -inf (operandRight)
actual: nan (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 24 - doubleComparisons(should FAIL: inf != 0)
---
@@ -196,9 +196,9 @@ not ok 24 - doubleComparisons(should FAIL: inf != 0)
found: inf (operandLeft)
expected: 0 (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 25 - doubleComparisons(should FAIL: 0 != inf)
---
@@ -208,9 +208,9 @@ not ok 25 - doubleComparisons(should FAIL: 0 != inf)
found: 0 (operandLeft)
expected: inf (operandRight)
actual: 0 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 26 - doubleComparisons(should FAIL: -inf != 0)
---
@@ -220,9 +220,9 @@ not ok 26 - doubleComparisons(should FAIL: -inf != 0)
found: -inf (operandLeft)
expected: 0 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 27 - doubleComparisons(should FAIL: 0 != -inf)
---
@@ -232,9 +232,9 @@ not ok 27 - doubleComparisons(should FAIL: 0 != -inf)
found: 0 (operandLeft)
expected: -inf (operandRight)
actual: 0 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 28 - doubleComparisons(should FAIL: inf != 1)
---
@@ -244,9 +244,9 @@ not ok 28 - doubleComparisons(should FAIL: inf != 1)
found: inf (operandLeft)
expected: 1 (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 29 - doubleComparisons(should FAIL: 1 != inf)
---
@@ -256,9 +256,9 @@ not ok 29 - doubleComparisons(should FAIL: 1 != inf)
found: 1 (operandLeft)
expected: inf (operandRight)
actual: 1 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 30 - doubleComparisons(should FAIL: -inf != 1)
---
@@ -268,9 +268,9 @@ not ok 30 - doubleComparisons(should FAIL: -inf != 1)
found: -inf (operandLeft)
expected: 1 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 31 - doubleComparisons(should FAIL: 1 != -inf)
---
@@ -280,9 +280,9 @@ not ok 31 - doubleComparisons(should FAIL: 1 != -inf)
found: 1 (operandLeft)
expected: -inf (operandRight)
actual: 1 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 32 - doubleComparisons(should FAIL: inf != max)
---
@@ -292,9 +292,9 @@ not ok 32 - doubleComparisons(should FAIL: inf != max)
found: inf (operandLeft)
expected: 1.79769313486e+308 (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 33 - doubleComparisons(should FAIL: inf != -max)
---
@@ -304,9 +304,9 @@ not ok 33 - doubleComparisons(should FAIL: inf != -max)
found: inf (operandLeft)
expected: -1.79769313486e+308 (operandRight)
actual: inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 34 - doubleComparisons(should FAIL: max != inf)
---
@@ -316,9 +316,9 @@ not ok 34 - doubleComparisons(should FAIL: max != inf)
found: 1.79769313486e+308 (operandLeft)
expected: inf (operandRight)
actual: 1.79769313486e+308 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 35 - doubleComparisons(should FAIL: -max != inf)
---
@@ -328,9 +328,9 @@ not ok 35 - doubleComparisons(should FAIL: -max != inf)
found: -1.79769313486e+308 (operandLeft)
expected: inf (operandRight)
actual: -1.79769313486e+308 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 36 - doubleComparisons(should FAIL: -inf != max)
---
@@ -340,9 +340,9 @@ not ok 36 - doubleComparisons(should FAIL: -inf != max)
found: -inf (operandLeft)
expected: 1.79769313486e+308 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 37 - doubleComparisons(should FAIL: -inf != -max)
---
@@ -352,9 +352,9 @@ not ok 37 - doubleComparisons(should FAIL: -inf != -max)
found: -inf (operandLeft)
expected: -1.79769313486e+308 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 38 - doubleComparisons(should FAIL: max != -inf)
---
@@ -364,9 +364,9 @@ not ok 38 - doubleComparisons(should FAIL: max != -inf)
found: 1.79769313486e+308 (operandLeft)
expected: -inf (operandRight)
actual: 1.79769313486e+308 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 39 - doubleComparisons(should FAIL: -max != -inf)
---
@@ -376,9 +376,9 @@ not ok 39 - doubleComparisons(should FAIL: -max != -inf)
found: -1.79769313486e+308 (operandLeft)
expected: -inf (operandRight)
actual: -1.79769313486e+308 (operandLeft)
- at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:51)
+ at: tst_float::doubleComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:103)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 51
+ line: 103
...
not ok 40 - floatComparisons(should FAIL 1)
---
@@ -388,9 +388,9 @@ not ok 40 - floatComparisons(should FAIL 1)
found: 1 (operandLeft)
expected: 3 (operandRight)
actual: 1 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
ok 41 - floatComparisons(should PASS 1)
not ok 42 - floatComparisons(should FAIL 2)
@@ -401,9 +401,9 @@ not ok 42 - floatComparisons(should FAIL 2)
found: 1e-07 (operandLeft)
expected: 3e-07 (operandRight)
actual: 1e-07 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
ok 43 - floatComparisons(should PASS 2)
not ok 44 - floatComparisons(should FAIL 3)
@@ -414,9 +414,9 @@ not ok 44 - floatComparisons(should FAIL 3)
found: 99999 (operandLeft)
expected: 99998 (operandRight)
actual: 99999 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
ok 45 - floatComparisons(should PASS 3)
not ok 46 - floatComparisons(should FAIL 4)
@@ -427,9 +427,9 @@ not ok 46 - floatComparisons(should FAIL 4)
found: 9.9999e-40 (operandLeft)
expected: 9.99971e-40 (operandRight)
actual: 9.9999e-40 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
ok 47 - floatComparisons(should PASS 4)
not ok 48 - floatComparisons(should FAIL 5)
@@ -440,9 +440,9 @@ not ok 48 - floatComparisons(should FAIL 5)
found: 9.9999e+37 (operandLeft)
expected: 9.9997e+37 (operandRight)
actual: 9.9999e+37 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
ok 49 - floatComparisons(should PASS: NaN == NaN)
not ok 50 - floatComparisons(should FAIL: NaN != 0)
@@ -453,9 +453,9 @@ not ok 50 - floatComparisons(should FAIL: NaN != 0)
found: nan (operandLeft)
expected: 0 (operandRight)
actual: nan (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 51 - floatComparisons(should FAIL: 0 != NaN)
---
@@ -465,9 +465,9 @@ not ok 51 - floatComparisons(should FAIL: 0 != NaN)
found: 0 (operandLeft)
expected: nan (operandRight)
actual: 0 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 52 - floatComparisons(should FAIL: NaN != 1)
---
@@ -477,9 +477,9 @@ not ok 52 - floatComparisons(should FAIL: NaN != 1)
found: nan (operandLeft)
expected: 1 (operandRight)
actual: nan (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 53 - floatComparisons(should FAIL: 1 != NaN)
---
@@ -489,9 +489,9 @@ not ok 53 - floatComparisons(should FAIL: 1 != NaN)
found: 1 (operandLeft)
expected: nan (operandRight)
actual: 1 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
ok 54 - floatComparisons(should PASS: inf == inf)
ok 55 - floatComparisons(should PASS: -inf == -inf)
@@ -503,9 +503,9 @@ not ok 56 - floatComparisons(should FAIL: inf != -inf)
found: inf (operandLeft)
expected: -inf (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 57 - floatComparisons(should FAIL: -inf != inf)
---
@@ -515,9 +515,9 @@ not ok 57 - floatComparisons(should FAIL: -inf != inf)
found: -inf (operandLeft)
expected: inf (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 58 - floatComparisons(should FAIL: inf != nan)
---
@@ -527,9 +527,9 @@ not ok 58 - floatComparisons(should FAIL: inf != nan)
found: inf (operandLeft)
expected: nan (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 59 - floatComparisons(should FAIL: nan != inf)
---
@@ -539,9 +539,9 @@ not ok 59 - floatComparisons(should FAIL: nan != inf)
found: nan (operandLeft)
expected: inf (operandRight)
actual: nan (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 60 - floatComparisons(should FAIL: -inf != nan)
---
@@ -551,9 +551,9 @@ not ok 60 - floatComparisons(should FAIL: -inf != nan)
found: -inf (operandLeft)
expected: nan (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 61 - floatComparisons(should FAIL: nan != -inf)
---
@@ -563,9 +563,9 @@ not ok 61 - floatComparisons(should FAIL: nan != -inf)
found: nan (operandLeft)
expected: -inf (operandRight)
actual: nan (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 62 - floatComparisons(should FAIL: inf != 0)
---
@@ -575,9 +575,9 @@ not ok 62 - floatComparisons(should FAIL: inf != 0)
found: inf (operandLeft)
expected: 0 (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 63 - floatComparisons(should FAIL: 0 != inf)
---
@@ -587,9 +587,9 @@ not ok 63 - floatComparisons(should FAIL: 0 != inf)
found: 0 (operandLeft)
expected: inf (operandRight)
actual: 0 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 64 - floatComparisons(should FAIL: -inf != 0)
---
@@ -599,9 +599,9 @@ not ok 64 - floatComparisons(should FAIL: -inf != 0)
found: -inf (operandLeft)
expected: 0 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 65 - floatComparisons(should FAIL: 0 != -inf)
---
@@ -611,9 +611,9 @@ not ok 65 - floatComparisons(should FAIL: 0 != -inf)
found: 0 (operandLeft)
expected: -inf (operandRight)
actual: 0 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 66 - floatComparisons(should FAIL: inf != 1)
---
@@ -623,9 +623,9 @@ not ok 66 - floatComparisons(should FAIL: inf != 1)
found: inf (operandLeft)
expected: 1 (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 67 - floatComparisons(should FAIL: 1 != inf)
---
@@ -635,9 +635,9 @@ not ok 67 - floatComparisons(should FAIL: 1 != inf)
found: 1 (operandLeft)
expected: inf (operandRight)
actual: 1 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 68 - floatComparisons(should FAIL: -inf != 1)
---
@@ -647,9 +647,9 @@ not ok 68 - floatComparisons(should FAIL: -inf != 1)
found: -inf (operandLeft)
expected: 1 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 69 - floatComparisons(should FAIL: 1 != -inf)
---
@@ -659,9 +659,9 @@ not ok 69 - floatComparisons(should FAIL: 1 != -inf)
found: 1 (operandLeft)
expected: -inf (operandRight)
actual: 1 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 70 - floatComparisons(should FAIL: inf != max)
---
@@ -671,9 +671,9 @@ not ok 70 - floatComparisons(should FAIL: inf != max)
found: inf (operandLeft)
expected: 3.40282e+38 (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 71 - floatComparisons(should FAIL: inf != -max)
---
@@ -683,9 +683,9 @@ not ok 71 - floatComparisons(should FAIL: inf != -max)
found: inf (operandLeft)
expected: -3.40282e+38 (operandRight)
actual: inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 72 - floatComparisons(should FAIL: max != inf)
---
@@ -695,9 +695,9 @@ not ok 72 - floatComparisons(should FAIL: max != inf)
found: 3.40282e+38 (operandLeft)
expected: inf (operandRight)
actual: 3.40282e+38 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 73 - floatComparisons(should FAIL: -max != inf)
---
@@ -707,9 +707,9 @@ not ok 73 - floatComparisons(should FAIL: -max != inf)
found: -3.40282e+38 (operandLeft)
expected: inf (operandRight)
actual: -3.40282e+38 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 74 - floatComparisons(should FAIL: -inf != max)
---
@@ -719,9 +719,9 @@ not ok 74 - floatComparisons(should FAIL: -inf != max)
found: -inf (operandLeft)
expected: 3.40282e+38 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 75 - floatComparisons(should FAIL: -inf != -max)
---
@@ -731,9 +731,9 @@ not ok 75 - floatComparisons(should FAIL: -inf != -max)
found: -inf (operandLeft)
expected: -3.40282e+38 (operandRight)
actual: -inf (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 76 - floatComparisons(should FAIL: max != -inf)
---
@@ -743,9 +743,9 @@ not ok 76 - floatComparisons(should FAIL: max != -inf)
found: 3.40282e+38 (operandLeft)
expected: -inf (operandRight)
actual: 3.40282e+38 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
not ok 77 - floatComparisons(should FAIL: -max != -inf)
---
@@ -755,11 +755,390 @@ not ok 77 - floatComparisons(should FAIL: -max != -inf)
found: -3.40282e+38 (operandLeft)
expected: -inf (operandRight)
actual: -3.40282e+38 (operandLeft)
- at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:124)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:137)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 124
+ line: 137
...
-not ok 78 - compareFloatTests(1e0)
+not ok 78 - float16Comparisons(should FAIL 1)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 3 (operandRight)
+ found: 1 (operandLeft)
+ expected: 3 (operandRight)
+ actual: 1 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+ok 79 - float16Comparisons(should PASS 1)
+not ok 80 - float16Comparisons(should FAIL 2)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 0.0003 (operandRight)
+ found: 0.0001 (operandLeft)
+ expected: 0.0003 (operandRight)
+ actual: 0.0001 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+ok 81 - float16Comparisons(should PASS 2)
+not ok 82 - float16Comparisons(should FAIL 3)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 99 (operandRight)
+ found: 98 (operandLeft)
+ expected: 99 (operandRight)
+ actual: 98 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+ok 83 - float16Comparisons(should PASS 3)
+not ok 84 - float16Comparisons(should FAIL 4)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 5.87e-05 (operandRight)
+ found: 5.93e-05 (operandLeft)
+ expected: 5.87e-05 (operandRight)
+ actual: 5.93e-05 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+ok 85 - float16Comparisons(should PASS 4)
+not ok 86 - float16Comparisons(should FAIL 5)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 5.88e+04 (operandRight)
+ found: 5.94e+04 (operandLeft)
+ expected: 5.88e+04 (operandRight)
+ actual: 5.94e+04 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+ok 87 - float16Comparisons(should PASS: NaN == NaN)
+not ok 88 - float16Comparisons(should FAIL: NaN != 0)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 0 (operandRight)
+ found: nan (operandLeft)
+ expected: 0 (operandRight)
+ actual: nan (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 89 - float16Comparisons(should FAIL: 0 != NaN)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: nan (operandRight)
+ found: 0 (operandLeft)
+ expected: nan (operandRight)
+ actual: 0 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 90 - float16Comparisons(should FAIL: NaN != 1)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 1 (operandRight)
+ found: nan (operandLeft)
+ expected: 1 (operandRight)
+ actual: nan (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 91 - float16Comparisons(should FAIL: 1 != NaN)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: nan (operandRight)
+ found: 1 (operandLeft)
+ expected: nan (operandRight)
+ actual: 1 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+ok 92 - float16Comparisons(should PASS: inf == inf)
+ok 93 - float16Comparisons(should PASS: -inf == -inf)
+not ok 94 - float16Comparisons(should FAIL: inf != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: inf (operandLeft)
+ expected: -inf (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 95 - float16Comparisons(should FAIL: -inf != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: -inf (operandLeft)
+ expected: inf (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 96 - float16Comparisons(should FAIL: inf != nan)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: nan (operandRight)
+ found: inf (operandLeft)
+ expected: nan (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 97 - float16Comparisons(should FAIL: nan != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: nan (operandLeft)
+ expected: inf (operandRight)
+ actual: nan (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 98 - float16Comparisons(should FAIL: -inf != nan)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: nan (operandRight)
+ found: -inf (operandLeft)
+ expected: nan (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 99 - float16Comparisons(should FAIL: nan != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: nan (operandLeft)
+ expected: -inf (operandRight)
+ actual: nan (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 100 - float16Comparisons(should FAIL: inf != 0)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 0 (operandRight)
+ found: inf (operandLeft)
+ expected: 0 (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 101 - float16Comparisons(should FAIL: 0 != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: 0 (operandLeft)
+ expected: inf (operandRight)
+ actual: 0 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 102 - float16Comparisons(should FAIL: -inf != 0)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 0 (operandRight)
+ found: -inf (operandLeft)
+ expected: 0 (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 103 - float16Comparisons(should FAIL: 0 != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: 0 (operandLeft)
+ expected: -inf (operandRight)
+ actual: 0 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 104 - float16Comparisons(should FAIL: inf != 1)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 1 (operandRight)
+ found: inf (operandLeft)
+ expected: 1 (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 105 - float16Comparisons(should FAIL: 1 != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: 1 (operandLeft)
+ expected: inf (operandRight)
+ actual: 1 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 106 - float16Comparisons(should FAIL: -inf != 1)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 1 (operandRight)
+ found: -inf (operandLeft)
+ expected: 1 (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 107 - float16Comparisons(should FAIL: 1 != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: 1 (operandLeft)
+ expected: -inf (operandRight)
+ actual: 1 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 108 - float16Comparisons(should FAIL: inf != max)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 6.55e+04 (operandRight)
+ found: inf (operandLeft)
+ expected: 6.55e+04 (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 109 - float16Comparisons(should FAIL: inf != -max)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -6.55e+04 (operandRight)
+ found: inf (operandLeft)
+ expected: -6.55e+04 (operandRight)
+ actual: inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 110 - float16Comparisons(should FAIL: max != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: 6.55e+04 (operandLeft)
+ expected: inf (operandRight)
+ actual: 6.55e+04 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 111 - float16Comparisons(should FAIL: -max != inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: inf (operandRight)
+ found: -6.55e+04 (operandLeft)
+ expected: inf (operandRight)
+ actual: -6.55e+04 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 112 - float16Comparisons(should FAIL: -inf != max)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: 6.55e+04 (operandRight)
+ found: -inf (operandLeft)
+ expected: 6.55e+04 (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 113 - float16Comparisons(should FAIL: -inf != -max)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -6.55e+04 (operandRight)
+ found: -inf (operandLeft)
+ expected: -6.55e+04 (operandRight)
+ actual: -inf (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 114 - float16Comparisons(should FAIL: max != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: 6.55e+04 (operandLeft)
+ expected: -inf (operandRight)
+ actual: 6.55e+04 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 115 - float16Comparisons(should FAIL: -max != -inf)
+ ---
+ type: QCOMPARE
+ message: Compared qfloat16s are not the same (fuzzy compare)
+ wanted: -inf (operandRight)
+ found: -6.55e+04 (operandLeft)
+ expected: -inf (operandRight)
+ actual: -6.55e+04 (operandLeft)
+ at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 171
+ ...
+not ok 116 - compareFloatTests(1e0)
---
type: QCOMPARE
message: Compared floats are not the same (fuzzy compare)
@@ -767,11 +1146,11 @@ not ok 78 - compareFloatTests(1e0)
found: 1 (t1)
expected: 3 (t3)
actual: 1 (t1)
- at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:206)
+ at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:210)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 206
+ line: 210
...
-not ok 79 - compareFloatTests(1e-7)
+not ok 117 - compareFloatTests(1e-7)
---
type: QCOMPARE
message: Compared floats are not the same (fuzzy compare)
@@ -779,11 +1158,11 @@ not ok 79 - compareFloatTests(1e-7)
found: 1e-07 (t1)
expected: 3e-07 (t3)
actual: 1e-07 (t1)
- at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:206)
+ at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:210)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 206
+ line: 210
...
-not ok 80 - compareFloatTests(1e+7)
+not ok 118 - compareFloatTests(1e+7)
---
type: QCOMPARE
message: Compared floats are not the same (fuzzy compare)
@@ -791,12 +1170,12 @@ not ok 80 - compareFloatTests(1e+7)
found: 1e+07 (t1)
expected: 3e+07 (t3)
actual: 1e+07 (t1)
- at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:206)
+ at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:210)
file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
- line: 206
+ line: 210
...
-ok 81 - cleanupTestCase()
-1..81
-# tests 81
-# pass 16
-# fail 65
+ok 119 - cleanupTestCase()
+1..119
+# tests 119
+# pass 23
+# fail 96
diff --git a/tests/auto/testlib/selftests/expected_float.teamcity b/tests/auto/testlib/selftests/expected_float.teamcity
index 9166f644af..af81296c42 100644
--- a/tests/auto/testlib/selftests/expected_float.teamcity
+++ b/tests/auto/testlib/selftests/expected_float.teamcity
@@ -1,11 +1,11 @@
##teamcity[testSuiteStarted name='tst_float' flowId='tst_float']
##teamcity[testStarted name='initTestCase()' flowId='tst_float']
##teamcity[testFinished name='initTestCase()' flowId='tst_float']
-##teamcity[testStarted name='doubleComparisons(should PASS 1)' flowId='tst_float']
-##teamcity[testFinished name='doubleComparisons(should PASS 1)' flowId='tst_float']
##teamcity[testStarted name='doubleComparisons(should FAIL 1)' flowId='tst_float']
##teamcity[testFailed name='doubleComparisons(should FAIL 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared doubles are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): 3' flowId='tst_float']
##teamcity[testFinished name='doubleComparisons(should FAIL 1)' flowId='tst_float']
+##teamcity[testStarted name='doubleComparisons(should PASS 1)' flowId='tst_float']
+##teamcity[testFinished name='doubleComparisons(should PASS 1)' flowId='tst_float']
##teamcity[testStarted name='doubleComparisons(should FAIL 2)' flowId='tst_float']
##teamcity[testFailed name='doubleComparisons(should FAIL 2)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared doubles are not the same (fuzzy compare)|n Actual (operandLeft) : 1e-07|n Expected (operandRight): 3e-07' flowId='tst_float']
##teamcity[testFinished name='doubleComparisons(should FAIL 2)' flowId='tst_float']
@@ -215,6 +215,113 @@
##teamcity[testStarted name='floatComparisons(should FAIL: -max != -inf)' flowId='tst_float']
##teamcity[testFailed name='floatComparisons(should FAIL: -max != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared floats are not the same (fuzzy compare)|n Actual (operandLeft) : -3.40282e+38|n Expected (operandRight): -inf' flowId='tst_float']
##teamcity[testFinished name='floatComparisons(should FAIL: -max != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL 1)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): 3' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL 1)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS 1)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS 1)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL 2)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL 2)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0.0001|n Expected (operandRight): 0.0003' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL 2)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS 2)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS 2)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL 3)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL 3)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 98|n Expected (operandRight): 99' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL 3)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS 3)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS 3)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL 4)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL 4)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 5.93e-05|n Expected (operandRight): 5.87e-05' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL 4)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS 4)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS 4)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL 5)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL 5)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 5.94e+04|n Expected (operandRight): 5.88e+04' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL 5)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS: NaN == NaN)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS: NaN == NaN)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: NaN != 0)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: NaN != 0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): 0' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: NaN != 0)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 0 != NaN)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 0 != NaN)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0|n Expected (operandRight): nan' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 0 != NaN)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: NaN != 1)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: NaN != 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): 1' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: NaN != 1)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 1 != NaN)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 1 != NaN)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): nan' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 1 != NaN)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS: inf == inf)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS: inf == inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should PASS: -inf == -inf)' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should PASS: -inf == -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != nan)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != nan)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): nan' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != nan)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: nan != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: nan != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: nan != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != nan)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != nan)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): nan' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != nan)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: nan != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: nan != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: nan != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != 0)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != 0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): 0' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != 0)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 0 != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 0 != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 0 != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != 0)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != 0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): 0' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != 0)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 0 != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 0 != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 0 != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != 1)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): 1' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != 1)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 1 != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 1 != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 1 != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != 1)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): 1' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != 1)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: 1 != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: 1 != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: 1 != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != max)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): 6.55e+04' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != max)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: inf != -max)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: inf != -max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): -6.55e+04' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: inf != -max)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: max != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: max != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 6.55e+04|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: max != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -max != inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -max != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -6.55e+04|n Expected (operandRight): inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -max != inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != max)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): 6.55e+04' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != max)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != -max)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != -max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): -6.55e+04' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != -max)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: max != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: max != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 6.55e+04|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: max != -inf)' flowId='tst_float']
+##teamcity[testStarted name='float16Comparisons(should FAIL: -max != -inf)' flowId='tst_float']
+##teamcity[testFailed name='float16Comparisons(should FAIL: -max != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -6.55e+04|n Expected (operandRight): -inf' flowId='tst_float']
+##teamcity[testFinished name='float16Comparisons(should FAIL: -max != -inf)' flowId='tst_float']
##teamcity[testStarted name='compareFloatTests(1e0)' flowId='tst_float']
##teamcity[testFailed name='compareFloatTests(1e0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared floats are not the same (fuzzy compare)|n Actual (t1): 1|n Expected (t3): 3' flowId='tst_float']
##teamcity[testFinished name='compareFloatTests(1e0)' flowId='tst_float']
diff --git a/tests/auto/testlib/selftests/expected_float.txt b/tests/auto/testlib/selftests/expected_float.txt
index 3134196a9c..d22a52a63d 100644
--- a/tests/auto/testlib/selftests/expected_float.txt
+++ b/tests/auto/testlib/selftests/expected_float.txt
@@ -1,11 +1,11 @@
********* Start testing of tst_float *********
Config: Using QtTest library
PASS : tst_float::initTestCase()
-PASS : tst_float::doubleComparisons(should PASS 1)
FAIL! : tst_float::doubleComparisons(should FAIL 1) Compared doubles are not the same (fuzzy compare)
Actual (operandLeft) : 1
Expected (operandRight): 3
Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::doubleComparisons(should PASS 1)
FAIL! : tst_float::doubleComparisons(should FAIL 2) Compared doubles are not the same (fuzzy compare)
Actual (operandLeft) : 1e-07
Expected (operandRight): 3e-07
@@ -263,6 +263,137 @@ FAIL! : tst_float::floatComparisons(should FAIL: -max != -inf) Compared floats
Actual (operandLeft) : -3.40282e+38
Expected (operandRight): -inf
Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL 1) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): 3
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS 1)
+FAIL! : tst_float::float16Comparisons(should FAIL 2) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0.0001
+ Expected (operandRight): 0.0003
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS 2)
+FAIL! : tst_float::float16Comparisons(should FAIL 3) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 98
+ Expected (operandRight): 99
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS 3)
+FAIL! : tst_float::float16Comparisons(should FAIL 4) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.93e-05
+ Expected (operandRight): 5.87e-05
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS 4)
+FAIL! : tst_float::float16Comparisons(should FAIL 5) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.94e+04
+ Expected (operandRight): 5.88e+04
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS: NaN == NaN)
+FAIL! : tst_float::float16Comparisons(should FAIL: NaN != 0) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 0
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 0 != NaN) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): nan
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: NaN != 1) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 1
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 1 != NaN) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): nan
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+PASS : tst_float::float16Comparisons(should PASS: inf == inf)
+PASS : tst_float::float16Comparisons(should PASS: -inf == -inf)
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != nan) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): nan
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: nan != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != nan) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): nan
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: nan != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != 0) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 0
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 0 != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != 0) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 0
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 0 != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != 1) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 1
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 1 != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != 1) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 1
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: 1 != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != max) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 6.55e+04
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: inf != -max) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -6.55e+04
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: max != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -max != inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != max) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 6.55e+04
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -inf != -max) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): -6.55e+04
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: max != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
+FAIL! : tst_float::float16Comparisons(should FAIL: -max != -inf) Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): -inf
+ Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
FAIL! : tst_float::compareFloatTests(1e0) Compared floats are not the same (fuzzy compare)
Actual (t1): 1
Expected (t3): 3
@@ -276,5 +407,5 @@ FAIL! : tst_float::compareFloatTests(1e+7) Compared floats are not the same (fu
Expected (t3): 3e+07
Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)]
PASS : tst_float::cleanupTestCase()
-Totals: 16 passed, 65 failed, 0 skipped, 0 blacklisted, 0ms
+Totals: 23 passed, 96 failed, 0 skipped, 0 blacklisted, 0ms
********* Finished testing of tst_float *********
diff --git a/tests/auto/testlib/selftests/expected_float.xml b/tests/auto/testlib/selftests/expected_float.xml
index da934eead3..247bce9577 100644
--- a/tests/auto/testlib/selftests/expected_float.xml
+++ b/tests/auto/testlib/selftests/expected_float.xml
@@ -10,15 +10,15 @@
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="doubleComparisons">
-<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[should PASS 1]]></DataTag>
-</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 1]]></DataTag>
<Description><![CDATA[Compared doubles are not the same (fuzzy compare)
Actual (operandLeft) : 1
Expected (operandRight): 3]]></Description>
</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 1]]></DataTag>
+</Incident>
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[should FAIL 2]]></DataTag>
<Description><![CDATA[Compared doubles are not the same (fuzzy compare)
@@ -429,6 +429,216 @@
</Incident>
<Duration msecs="0"/>
</TestFunction>
+<TestFunction name="float16Comparisons">
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): 3]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 1]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 2]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0.0001
+ Expected (operandRight): 0.0003]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 2]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 3]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 98
+ Expected (operandRight): 99]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 3]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 4]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.93e-05
+ Expected (operandRight): 5.87e-05]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS 4]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL 5]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.94e+04
+ Expected (operandRight): 5.88e+04]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: NaN == NaN]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: NaN != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != NaN]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: NaN != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != NaN]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: inf == inf]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[should PASS: -inf == -inf]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != nan]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: nan != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != nan]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): nan]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: nan != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != 0]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 0]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 0 != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != 1]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 1]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: 1 != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: inf != -max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): -6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: max != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -max != inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): 6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -inf != -max]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -inf
+ Expected (operandRight): -6.55e+04]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: max != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
+ <DataTag><![CDATA[should FAIL: -max != -inf]]></DataTag>
+ <Description><![CDATA[Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : -6.55e+04
+ Expected (operandRight): -inf]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
<TestFunction name="compareFloatTests">
<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/float/tst_float.cpp" line="0">
<DataTag><![CDATA[1e0]]></DataTag>
diff --git a/tests/auto/testlib/selftests/expected_float.xunitxml b/tests/auto/testlib/selftests/expected_float.xunitxml
index ba96b16fe6..602f9252a4 100644
--- a/tests/auto/testlib/selftests/expected_float.xunitxml
+++ b/tests/auto/testlib/selftests/expected_float.xunitxml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<testsuite errors="0" failures="65" tests="5" name="tst_float">
+<testsuite errors="0" failures="96" tests="6" name="tst_float">
<properties>
<property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
<property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
@@ -196,6 +196,101 @@
Actual (operandLeft) : &#x002D;3.40282e+38
Expected (operandRight): &#x002D;inf" result="fail"/>
</testcase>
+ <testcase result="fail" name="float16Comparisons">
+ <failure tag="should FAIL 1" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): 3" result="fail"/>
+ <failure tag="should FAIL 2" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0.0001
+ Expected (operandRight): 0.0003" result="fail"/>
+ <failure tag="should FAIL 3" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 98
+ Expected (operandRight): 99" result="fail"/>
+ <failure tag="should FAIL 4" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.93e&#x002D;05
+ Expected (operandRight): 5.87e&#x002D;05" result="fail"/>
+ <failure tag="should FAIL 5" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 5.94e+04
+ Expected (operandRight): 5.88e+04" result="fail"/>
+ <failure tag="should FAIL: NaN != 0" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 0" result="fail"/>
+ <failure tag="should FAIL: 0 != NaN" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): nan" result="fail"/>
+ <failure tag="should FAIL: NaN != 1" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): 1" result="fail"/>
+ <failure tag="should FAIL: 1 != NaN" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): nan" result="fail"/>
+ <failure tag="should FAIL: inf != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: inf != nan" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): nan" result="fail"/>
+ <failure tag="should FAIL: nan != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != nan" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): nan" result="fail"/>
+ <failure tag="should FAIL: nan != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : nan
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ <failure tag="should FAIL: inf != 0" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 0" result="fail"/>
+ <failure tag="should FAIL: 0 != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != 0" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): 0" result="fail"/>
+ <failure tag="should FAIL: 0 != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 0
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ <failure tag="should FAIL: inf != 1" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 1" result="fail"/>
+ <failure tag="should FAIL: 1 != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != 1" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): 1" result="fail"/>
+ <failure tag="should FAIL: 1 != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 1
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ <failure tag="should FAIL: inf != max" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): 6.55e+04" result="fail"/>
+ <failure tag="should FAIL: inf != &#x002D;max" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : inf
+ Expected (operandRight): &#x002D;6.55e+04" result="fail"/>
+ <failure tag="should FAIL: max != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;max != inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;6.55e+04
+ Expected (operandRight): inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != max" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): 6.55e+04" result="fail"/>
+ <failure tag="should FAIL: &#x002D;inf != &#x002D;max" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;inf
+ Expected (operandRight): &#x002D;6.55e+04" result="fail"/>
+ <failure tag="should FAIL: max != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : 6.55e+04
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ <failure tag="should FAIL: &#x002D;max != &#x002D;inf" message="Compared qfloat16s are not the same (fuzzy compare)
+ Actual (operandLeft) : &#x002D;6.55e+04
+ Expected (operandRight): &#x002D;inf" result="fail"/>
+ </testcase>
<testcase result="fail" name="compareFloatTests">
<failure tag="1e0" message="Compared floats are not the same (fuzzy compare)
Actual (t1): 1
diff --git a/tests/auto/testlib/selftests/expected_globaldata.lightxml b/tests/auto/testlib/selftests/expected_globaldata.lightxml
index f66c4c552d..1212e4b364 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.lightxml
+++ b/tests/auto/testlib/selftests/expected_globaldata.lightxml
@@ -12,174 +12,195 @@
</TestFunction>
<TestFunction name="testGlobal">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init testGlobal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[global: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init testGlobal local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[global: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[init testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init testGlobal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
<Description><![CDATA[global: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
<Description><![CDATA[local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[init testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init testGlobal local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[global: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skip">
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1]]></DataTag>
+ <DataTag><![CDATA[global=false]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skipLocal">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init skipLocal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init skipLocal local=false]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipLocal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init skipLocal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init skipLocal local=true]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipLocal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=true]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init skipLocal local=false]]></Description>
+</Message>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[skipping]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=false]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init skipLocal local=true]]></Description>
+</Message>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[skipping]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=true]]></Description>
</Message>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skipSingle">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init skipSingle local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[global: false local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init skipSingle local=true]]></Description>
</Message>
-<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[global: false local: true]]></Description>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[Skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=true]]></Description>
</Message>
-<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
-</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[init skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init skipSingle local=false]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[skipping]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[Skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[init skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init skipSingle local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[global: true local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
</Incident>
<Duration msecs="0"/>
</TestFunction>
diff --git a/tests/auto/testlib/selftests/expected_globaldata.tap b/tests/auto/testlib/selftests/expected_globaldata.tap
index 580cf3a7a8..4d61b7437b 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.tap
+++ b/tests/auto/testlib/selftests/expected_globaldata.tap
@@ -2,51 +2,56 @@ TAP version 13
# tst_globaldata
# initTestCase initTestCase (null)
ok 1 - initTestCase()
-# init testGlobal local 1
+# init testGlobal local=false
# global: false
# local: false
-# cleanup testGlobal local 1
-ok 2 - testGlobal(1:local 1)
-# init testGlobal local 2
+# cleanup testGlobal local=false
+ok 2 - testGlobal(global=false:local=false)
+# init testGlobal local=true
# global: false
# local: true
-# cleanup testGlobal local 2
-ok 3 - testGlobal(1:local 2)
-# init testGlobal local 1
+# cleanup testGlobal local=true
+ok 3 - testGlobal(global=false:local=true)
+# init testGlobal local=false
# global: true
# local: false
-# cleanup testGlobal local 1
-ok 4 - testGlobal(2:local 1)
-# init testGlobal local 2
+# cleanup testGlobal local=false
+ok 4 - testGlobal(global=true:local=false)
+# init testGlobal local=true
# global: true
# local: true
-# cleanup testGlobal local 2
-ok 5 - testGlobal(2:local 2)
-ok 6 - skip(1) # SKIP skipping
-# init skipLocal local 1
-ok 7 - skipLocal(1:local 1) # SKIP skipping
-# cleanup skipLocal local 1
-# init skipLocal local 2
-ok 8 - skipLocal(1:local 2) # SKIP skipping
-# cleanup skipLocal local 2
-# init skipSingle local 1
+# cleanup testGlobal local=true
+ok 5 - testGlobal(global=true:local=true)
+ok 6 - skip(global=false) # SKIP skipping
+# init skipLocal local=false
+ok 7 - skipLocal(global=false:local=false) # SKIP skipping
+# cleanup skipLocal local=false
+# init skipLocal local=true
+ok 8 - skipLocal(global=false:local=true) # SKIP skipping
+# cleanup skipLocal local=true
+# init skipLocal local=false
+ok 9 - skipLocal(global=true:local=false) # SKIP skipping
+# cleanup skipLocal local=false
+# init skipLocal local=true
+ok 10 - skipLocal(global=true:local=true) # SKIP skipping
+# cleanup skipLocal local=true
+# init skipSingle local=false
# global: false local: false
-# cleanup skipSingle local 1
-ok 9 - skipSingle(1:local 1)
-# init skipSingle local 2
-# global: false local: true
-# cleanup skipSingle local 2
-ok 10 - skipSingle(1:local 2)
-# init skipSingle local 1
-ok 11 - skipSingle(2:local 1) # SKIP skipping
-# cleanup skipSingle local 1
-# init skipSingle local 2
+# cleanup skipSingle local=false
+ok 11 - skipSingle(global=false:local=false)
+# init skipSingle local=true
+ok 12 - skipSingle(global=false:local=true) # SKIP Skipping
+# cleanup skipSingle local=true
+# init skipSingle local=false
+ok 13 - skipSingle(global=true:local=false) # SKIP Skipping
+# cleanup skipSingle local=false
+# init skipSingle local=true
# global: true local: true
-# cleanup skipSingle local 2
-ok 12 - skipSingle(2:local 2)
+# cleanup skipSingle local=true
+ok 14 - skipSingle(global=true:local=true)
# cleanupTestCase cleanupTestCase (null)
-ok 13 - cleanupTestCase()
-1..13
-# tests 13
-# pass 9
+ok 15 - cleanupTestCase()
+1..15
+# tests 15
+# pass 8
# fail 0
diff --git a/tests/auto/testlib/selftests/expected_globaldata.teamcity b/tests/auto/testlib/selftests/expected_globaldata.teamcity
index 5d623a3285..f76f6090ba 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.teamcity
+++ b/tests/auto/testlib/selftests/expected_globaldata.teamcity
@@ -2,30 +2,31 @@
##teamcity[testStarted name='initTestCase()' flowId='tst_globaldata']
##teamcity[testStdOut name='initTestCase()' out='QDEBUG: initTestCase initTestCase (null)' flowId='tst_globaldata']
##teamcity[testFinished name='initTestCase()' flowId='tst_globaldata']
-##teamcity[testStarted name='testGlobal(local 1)' flowId='tst_globaldata']
-##teamcity[testStdOut name='testGlobal(local 1)' out='QDEBUG: init testGlobal local 1|nQDEBUG: global: false|nQDEBUG: local: false|nQDEBUG: cleanup testGlobal local 1' flowId='tst_globaldata']
-##teamcity[testFinished name='testGlobal(local 1)' flowId='tst_globaldata']
-##teamcity[testStarted name='testGlobal(local 2)' flowId='tst_globaldata']
-##teamcity[testStdOut name='testGlobal(local 2)' out='QDEBUG: init testGlobal local 2|nQDEBUG: global: false|nQDEBUG: local: true|nQDEBUG: cleanup testGlobal local 2' flowId='tst_globaldata']
-##teamcity[testFinished name='testGlobal(local 2)' flowId='tst_globaldata']
-##teamcity[testStarted name='testGlobal(local 1)' flowId='tst_globaldata']
-##teamcity[testStdOut name='testGlobal(local 1)' out='QDEBUG: init testGlobal local 1|nQDEBUG: global: true|nQDEBUG: local: false|nQDEBUG: cleanup testGlobal local 1' flowId='tst_globaldata']
-##teamcity[testFinished name='testGlobal(local 1)' flowId='tst_globaldata']
-##teamcity[testStarted name='testGlobal(local 2)' flowId='tst_globaldata']
-##teamcity[testStdOut name='testGlobal(local 2)' out='QDEBUG: init testGlobal local 2|nQDEBUG: global: true|nQDEBUG: local: true|nQDEBUG: cleanup testGlobal local 2' flowId='tst_globaldata']
-##teamcity[testFinished name='testGlobal(local 2)' flowId='tst_globaldata']
+##teamcity[testStarted name='testGlobal(local=false)' flowId='tst_globaldata']
+##teamcity[testStdOut name='testGlobal(local=false)' out='QDEBUG: init testGlobal local=false|nQDEBUG: global: false|nQDEBUG: local: false|nQDEBUG: cleanup testGlobal local=false' flowId='tst_globaldata']
+##teamcity[testFinished name='testGlobal(local=false)' flowId='tst_globaldata']
+##teamcity[testStarted name='testGlobal(local=true)' flowId='tst_globaldata']
+##teamcity[testStdOut name='testGlobal(local=true)' out='QDEBUG: init testGlobal local=true|nQDEBUG: global: false|nQDEBUG: local: true|nQDEBUG: cleanup testGlobal local=true' flowId='tst_globaldata']
+##teamcity[testFinished name='testGlobal(local=true)' flowId='tst_globaldata']
+##teamcity[testStarted name='testGlobal(local=false)' flowId='tst_globaldata']
+##teamcity[testStdOut name='testGlobal(local=false)' out='QDEBUG: init testGlobal local=false|nQDEBUG: global: true|nQDEBUG: local: false|nQDEBUG: cleanup testGlobal local=false' flowId='tst_globaldata']
+##teamcity[testFinished name='testGlobal(local=false)' flowId='tst_globaldata']
+##teamcity[testStarted name='testGlobal(local=true)' flowId='tst_globaldata']
+##teamcity[testStdOut name='testGlobal(local=true)' out='QDEBUG: init testGlobal local=true|nQDEBUG: global: true|nQDEBUG: local: true|nQDEBUG: cleanup testGlobal local=true' flowId='tst_globaldata']
+##teamcity[testFinished name='testGlobal(local=true)' flowId='tst_globaldata']
##teamcity[testIgnored name='skip()' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
-##teamcity[testIgnored name='skipLocal(local 1)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
-##teamcity[testIgnored name='skipLocal(local 2)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
-##teamcity[testStarted name='skipSingle(local 1)' flowId='tst_globaldata']
-##teamcity[testStdOut name='skipSingle(local 1)' out='QDEBUG: init skipLocal local 1|nQDEBUG: cleanup skipLocal local 1|nQDEBUG: init skipLocal local 2|nQDEBUG: cleanup skipLocal local 2|nQDEBUG: init skipSingle local 1|nQDEBUG: global: false local: false|nQDEBUG: cleanup skipSingle local 1' flowId='tst_globaldata']
-##teamcity[testFinished name='skipSingle(local 1)' flowId='tst_globaldata']
-##teamcity[testStarted name='skipSingle(local 2)' flowId='tst_globaldata']
-##teamcity[testStdOut name='skipSingle(local 2)' out='QDEBUG: init skipSingle local 2|nQDEBUG: global: false local: true|nQDEBUG: cleanup skipSingle local 2' flowId='tst_globaldata']
-##teamcity[testFinished name='skipSingle(local 2)' flowId='tst_globaldata']
-##teamcity[testIgnored name='skipSingle(local 1)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
-##teamcity[testStdOut name='skipSingle(local 2)' out='QDEBUG: init skipSingle local 1|nQDEBUG: cleanup skipSingle local 1|nQDEBUG: init skipSingle local 2|nQDEBUG: global: true local: true|nQDEBUG: cleanup skipSingle local 2' flowId='tst_globaldata']
-##teamcity[testFinished name='skipSingle(local 2)' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipLocal(local=false)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipLocal(local=true)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipLocal(local=false)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipLocal(local=true)' message='skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testStarted name='skipSingle(local=false)' flowId='tst_globaldata']
+##teamcity[testStdOut name='skipSingle(local=false)' out='QDEBUG: init skipLocal local=false|nQDEBUG: cleanup skipLocal local=false|nQDEBUG: init skipLocal local=true|nQDEBUG: cleanup skipLocal local=true|nQDEBUG: init skipLocal local=false|nQDEBUG: cleanup skipLocal local=false|nQDEBUG: init skipLocal local=true|nQDEBUG: cleanup skipLocal local=true|nQDEBUG: init skipSingle local=false|nQDEBUG: global: false local: false|nQDEBUG: cleanup skipSingle local=false' flowId='tst_globaldata']
+##teamcity[testFinished name='skipSingle(local=false)' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipSingle(local=true)' message='Skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testIgnored name='skipSingle(local=false)' message='Skipping |[Loc: qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)|]' flowId='tst_globaldata']
+##teamcity[testStarted name='skipSingle(local=true)' flowId='tst_globaldata']
+##teamcity[testStdOut name='skipSingle(local=true)' out='QDEBUG: init skipSingle local=true|nQDEBUG: cleanup skipSingle local=true|nQDEBUG: init skipSingle local=false|nQDEBUG: cleanup skipSingle local=false|nQDEBUG: init skipSingle local=true|nQDEBUG: global: true local: true|nQDEBUG: cleanup skipSingle local=true' flowId='tst_globaldata']
+##teamcity[testFinished name='skipSingle(local=true)' flowId='tst_globaldata']
##teamcity[testStarted name='cleanupTestCase()' flowId='tst_globaldata']
##teamcity[testStdOut name='cleanupTestCase()' out='QDEBUG: cleanupTestCase cleanupTestCase (null)' flowId='tst_globaldata']
##teamcity[testFinished name='cleanupTestCase()' flowId='tst_globaldata']
diff --git a/tests/auto/testlib/selftests/expected_globaldata.txt b/tests/auto/testlib/selftests/expected_globaldata.txt
index b12f4a2a69..016b5e8299 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.txt
+++ b/tests/auto/testlib/selftests/expected_globaldata.txt
@@ -2,53 +2,61 @@
Config: Using QtTest library
QDEBUG : tst_globaldata::initTestCase() initTestCase initTestCase (null)
PASS : tst_globaldata::initTestCase()
-QDEBUG : tst_globaldata::testGlobal(1:local 1) init testGlobal local 1
-QDEBUG : tst_globaldata::testGlobal(1:local 1) global: false
-QDEBUG : tst_globaldata::testGlobal(1:local 1) local: false
-QDEBUG : tst_globaldata::testGlobal(1:local 1) cleanup testGlobal local 1
-PASS : tst_globaldata::testGlobal(1:local 1)
-QDEBUG : tst_globaldata::testGlobal(1:local 2) init testGlobal local 2
-QDEBUG : tst_globaldata::testGlobal(1:local 2) global: false
-QDEBUG : tst_globaldata::testGlobal(1:local 2) local: true
-QDEBUG : tst_globaldata::testGlobal(1:local 2) cleanup testGlobal local 2
-PASS : tst_globaldata::testGlobal(1:local 2)
-QDEBUG : tst_globaldata::testGlobal(2:local 1) init testGlobal local 1
-QDEBUG : tst_globaldata::testGlobal(2:local 1) global: true
-QDEBUG : tst_globaldata::testGlobal(2:local 1) local: false
-QDEBUG : tst_globaldata::testGlobal(2:local 1) cleanup testGlobal local 1
-PASS : tst_globaldata::testGlobal(2:local 1)
-QDEBUG : tst_globaldata::testGlobal(2:local 2) init testGlobal local 2
-QDEBUG : tst_globaldata::testGlobal(2:local 2) global: true
-QDEBUG : tst_globaldata::testGlobal(2:local 2) local: true
-QDEBUG : tst_globaldata::testGlobal(2:local 2) cleanup testGlobal local 2
-PASS : tst_globaldata::testGlobal(2:local 2)
-SKIP : tst_globaldata::skip(1) skipping
+QDEBUG : tst_globaldata::testGlobal(global=false:local=false) init testGlobal local=false
+QDEBUG : tst_globaldata::testGlobal(global=false:local=false) global: false
+QDEBUG : tst_globaldata::testGlobal(global=false:local=false) local: false
+QDEBUG : tst_globaldata::testGlobal(global=false:local=false) cleanup testGlobal local=false
+PASS : tst_globaldata::testGlobal(global=false:local=false)
+QDEBUG : tst_globaldata::testGlobal(global=false:local=true) init testGlobal local=true
+QDEBUG : tst_globaldata::testGlobal(global=false:local=true) global: false
+QDEBUG : tst_globaldata::testGlobal(global=false:local=true) local: true
+QDEBUG : tst_globaldata::testGlobal(global=false:local=true) cleanup testGlobal local=true
+PASS : tst_globaldata::testGlobal(global=false:local=true)
+QDEBUG : tst_globaldata::testGlobal(global=true:local=false) init testGlobal local=false
+QDEBUG : tst_globaldata::testGlobal(global=true:local=false) global: true
+QDEBUG : tst_globaldata::testGlobal(global=true:local=false) local: false
+QDEBUG : tst_globaldata::testGlobal(global=true:local=false) cleanup testGlobal local=false
+PASS : tst_globaldata::testGlobal(global=true:local=false)
+QDEBUG : tst_globaldata::testGlobal(global=true:local=true) init testGlobal local=true
+QDEBUG : tst_globaldata::testGlobal(global=true:local=true) global: true
+QDEBUG : tst_globaldata::testGlobal(global=true:local=true) local: true
+QDEBUG : tst_globaldata::testGlobal(global=true:local=true) cleanup testGlobal local=true
+PASS : tst_globaldata::testGlobal(global=true:local=true)
+SKIP : tst_globaldata::skip(global=false) skipping
Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
-QDEBUG : tst_globaldata::skipLocal(1:local 1) init skipLocal local 1
-SKIP : tst_globaldata::skipLocal(1:local 1) skipping
+QDEBUG : tst_globaldata::skipLocal(global=false:local=false) init skipLocal local=false
+SKIP : tst_globaldata::skipLocal(global=false:local=false) skipping
Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
-QDEBUG : tst_globaldata::skipLocal(1:local 1) cleanup skipLocal local 1
-QDEBUG : tst_globaldata::skipLocal(1:local 2) init skipLocal local 2
-SKIP : tst_globaldata::skipLocal(1:local 2) skipping
+QDEBUG : tst_globaldata::skipLocal(global=false:local=false) cleanup skipLocal local=false
+QDEBUG : tst_globaldata::skipLocal(global=false:local=true) init skipLocal local=true
+SKIP : tst_globaldata::skipLocal(global=false:local=true) skipping
Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
-QDEBUG : tst_globaldata::skipLocal(1:local 2) cleanup skipLocal local 2
-QDEBUG : tst_globaldata::skipSingle(1:local 1) init skipSingle local 1
-QDEBUG : tst_globaldata::skipSingle(1:local 1) global: false local: false
-QDEBUG : tst_globaldata::skipSingle(1:local 1) cleanup skipSingle local 1
-PASS : tst_globaldata::skipSingle(1:local 1)
-QDEBUG : tst_globaldata::skipSingle(1:local 2) init skipSingle local 2
-QDEBUG : tst_globaldata::skipSingle(1:local 2) global: false local: true
-QDEBUG : tst_globaldata::skipSingle(1:local 2) cleanup skipSingle local 2
-PASS : tst_globaldata::skipSingle(1:local 2)
-QDEBUG : tst_globaldata::skipSingle(2:local 1) init skipSingle local 1
-SKIP : tst_globaldata::skipSingle(2:local 1) skipping
+QDEBUG : tst_globaldata::skipLocal(global=false:local=true) cleanup skipLocal local=true
+QDEBUG : tst_globaldata::skipLocal(global=true:local=false) init skipLocal local=false
+SKIP : tst_globaldata::skipLocal(global=true:local=false) skipping
Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
-QDEBUG : tst_globaldata::skipSingle(2:local 1) cleanup skipSingle local 1
-QDEBUG : tst_globaldata::skipSingle(2:local 2) init skipSingle local 2
-QDEBUG : tst_globaldata::skipSingle(2:local 2) global: true local: true
-QDEBUG : tst_globaldata::skipSingle(2:local 2) cleanup skipSingle local 2
-PASS : tst_globaldata::skipSingle(2:local 2)
+QDEBUG : tst_globaldata::skipLocal(global=true:local=false) cleanup skipLocal local=false
+QDEBUG : tst_globaldata::skipLocal(global=true:local=true) init skipLocal local=true
+SKIP : tst_globaldata::skipLocal(global=true:local=true) skipping
+ Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
+QDEBUG : tst_globaldata::skipLocal(global=true:local=true) cleanup skipLocal local=true
+QDEBUG : tst_globaldata::skipSingle(global=false:local=false) init skipSingle local=false
+QDEBUG : tst_globaldata::skipSingle(global=false:local=false) global: false local: false
+QDEBUG : tst_globaldata::skipSingle(global=false:local=false) cleanup skipSingle local=false
+PASS : tst_globaldata::skipSingle(global=false:local=false)
+QDEBUG : tst_globaldata::skipSingle(global=false:local=true) init skipSingle local=true
+SKIP : tst_globaldata::skipSingle(global=false:local=true) Skipping
+ Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
+QDEBUG : tst_globaldata::skipSingle(global=false:local=true) cleanup skipSingle local=true
+QDEBUG : tst_globaldata::skipSingle(global=true:local=false) init skipSingle local=false
+SKIP : tst_globaldata::skipSingle(global=true:local=false) Skipping
+ Loc: [qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp(0)]
+QDEBUG : tst_globaldata::skipSingle(global=true:local=false) cleanup skipSingle local=false
+QDEBUG : tst_globaldata::skipSingle(global=true:local=true) init skipSingle local=true
+QDEBUG : tst_globaldata::skipSingle(global=true:local=true) global: true local: true
+QDEBUG : tst_globaldata::skipSingle(global=true:local=true) cleanup skipSingle local=true
+PASS : tst_globaldata::skipSingle(global=true:local=true)
QDEBUG : tst_globaldata::cleanupTestCase() cleanupTestCase cleanupTestCase (null)
PASS : tst_globaldata::cleanupTestCase()
-Totals: 9 passed, 0 failed, 4 skipped, 0 blacklisted, 0ms
+Totals: 8 passed, 0 failed, 7 skipped, 0 blacklisted, 0ms
********* Finished testing of tst_globaldata *********
diff --git a/tests/auto/testlib/selftests/expected_globaldata.xml b/tests/auto/testlib/selftests/expected_globaldata.xml
index 0f705ef352..9aa48c8f16 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.xml
+++ b/tests/auto/testlib/selftests/expected_globaldata.xml
@@ -14,174 +14,195 @@
</TestFunction>
<TestFunction name="testGlobal">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init testGlobal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[global: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init testGlobal local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[global: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[init testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init testGlobal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
<Description><![CDATA[global: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
<Description><![CDATA[local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[init testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init testGlobal local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[global: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[cleanup testGlobal local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup testGlobal local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skip">
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1]]></DataTag>
+ <DataTag><![CDATA[global=false]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skipLocal">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init skipLocal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init skipLocal local=false]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipLocal local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init skipLocal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init skipLocal local=true]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
<Description><![CDATA[skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipLocal local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=true]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init skipLocal local=false]]></Description>
+</Message>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[skipping]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=false]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init skipLocal local=true]]></Description>
+</Message>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[skipping]]></Description>
+</Message>
+<Message type="qdebug" file="" line="0">
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipLocal local=true]]></Description>
</Message>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="skipSingle">
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[init skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[init skipSingle local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
<Description><![CDATA[global: false local: false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=false]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 1]]></DataTag>
+ <DataTag><![CDATA[global=false:local=false]]></DataTag>
</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[init skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[init skipSingle local=true]]></Description>
</Message>
-<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[global: false local: true]]></Description>
+<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[Skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=false:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=true]]></Description>
</Message>
-<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[1:local 2]]></DataTag>
-</Incident>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[init skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[init skipSingle local=false]]></Description>
</Message>
<Message type="skip" file="qtbase/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[skipping]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[Skipping]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 1]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 1]]></Description>
+ <DataTag><![CDATA[global=true:local=false]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=false]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[init skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[init skipSingle local=true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
<Description><![CDATA[global: true local: true]]></Description>
</Message>
<Message type="qdebug" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
- <Description><![CDATA[cleanup skipSingle local 2]]></Description>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
+ <Description><![CDATA[cleanup skipSingle local=true]]></Description>
</Message>
<Incident type="pass" file="" line="0">
- <DataTag><![CDATA[2:local 2]]></DataTag>
+ <DataTag><![CDATA[global=true:local=true]]></DataTag>
</Incident>
<Duration msecs="0"/>
</TestFunction>
diff --git a/tests/auto/testlib/selftests/expected_globaldata.xunitxml b/tests/auto/testlib/selftests/expected_globaldata.xunitxml
index bdd7e3f00a..de184c2fdd 100644
--- a/tests/auto/testlib/selftests/expected_globaldata.xunitxml
+++ b/tests/auto/testlib/selftests/expected_globaldata.xunitxml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<testsuite errors="37" failures="0" tests="6" name="tst_globaldata">
+<testsuite errors="43" failures="0" tests="6" name="tst_globaldata">
<properties>
<property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
<property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
@@ -9,88 +9,100 @@
<!-- message="initTestCase initTestCase (null)" type="qdebug" -->
</testcase>
<testcase result="pass" name="testGlobal">
- <!-- tag="1:local 1" message="init testGlobal local 1" type="qdebug" -->
- <!-- tag="1:local 1" message="global: false" type="qdebug" -->
- <!-- tag="1:local 1" message="local: false" type="qdebug" -->
- <!-- tag="1:local 1" message="cleanup testGlobal local 1" type="qdebug" -->
- <!-- tag="1:local 2" message="init testGlobal local 2" type="qdebug" -->
- <!-- tag="1:local 2" message="global: false" type="qdebug" -->
- <!-- tag="1:local 2" message="local: true" type="qdebug" -->
- <!-- tag="1:local 2" message="cleanup testGlobal local 2" type="qdebug" -->
- <!-- tag="2:local 1" message="init testGlobal local 1" type="qdebug" -->
- <!-- tag="2:local 1" message="global: true" type="qdebug" -->
- <!-- tag="2:local 1" message="local: false" type="qdebug" -->
- <!-- tag="2:local 1" message="cleanup testGlobal local 1" type="qdebug" -->
- <!-- tag="2:local 2" message="init testGlobal local 2" type="qdebug" -->
- <!-- tag="2:local 2" message="global: true" type="qdebug" -->
- <!-- tag="2:local 2" message="local: true" type="qdebug" -->
- <!-- tag="2:local 2" message="cleanup testGlobal local 2" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="init testGlobal local=false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="global: false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="local: false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="cleanup testGlobal local=false" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="init testGlobal local=true" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="global: false" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="local: true" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="cleanup testGlobal local=true" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="init testGlobal local=false" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="global: true" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="local: false" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="cleanup testGlobal local=false" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="init testGlobal local=true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="global: true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="local: true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="cleanup testGlobal local=true" type="qdebug" -->
</testcase>
<testcase name="skip">
- <!-- tag="1" message="skipping" type="skip" -->
+ <!-- tag="global=false" message="skipping" type="skip" -->
</testcase>
<testcase name="skipLocal">
- <!-- tag="1:local 1" message="init skipLocal local 1" type="qdebug" -->
- <!-- tag="1:local 1" message="skipping" type="skip" -->
- <!-- tag="1:local 1" message="cleanup skipLocal local 1" type="qdebug" -->
- <!-- tag="1:local 2" message="init skipLocal local 2" type="qdebug" -->
- <!-- tag="1:local 2" message="skipping" type="skip" -->
- <!-- tag="1:local 2" message="cleanup skipLocal local 2" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="init skipLocal local=false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="skipping" type="skip" -->
+ <!-- tag="global=false:local=false" message="cleanup skipLocal local=false" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="init skipLocal local=true" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="skipping" type="skip" -->
+ <!-- tag="global=false:local=true" message="cleanup skipLocal local=true" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="init skipLocal local=false" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="skipping" type="skip" -->
+ <!-- tag="global=true:local=false" message="cleanup skipLocal local=false" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="init skipLocal local=true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="skipping" type="skip" -->
+ <!-- tag="global=true:local=true" message="cleanup skipLocal local=true" type="qdebug" -->
</testcase>
<testcase result="pass" name="skipSingle">
- <!-- tag="1:local 1" message="init skipSingle local 1" type="qdebug" -->
- <!-- tag="1:local 1" message="global: false local: false" type="qdebug" -->
- <!-- tag="1:local 1" message="cleanup skipSingle local 1" type="qdebug" -->
- <!-- tag="1:local 2" message="init skipSingle local 2" type="qdebug" -->
- <!-- tag="1:local 2" message="global: false local: true" type="qdebug" -->
- <!-- tag="1:local 2" message="cleanup skipSingle local 2" type="qdebug" -->
- <!-- tag="2:local 1" message="init skipSingle local 1" type="qdebug" -->
- <!-- tag="2:local 1" message="skipping" type="skip" -->
- <!-- tag="2:local 1" message="cleanup skipSingle local 1" type="qdebug" -->
- <!-- tag="2:local 2" message="init skipSingle local 2" type="qdebug" -->
- <!-- tag="2:local 2" message="global: true local: true" type="qdebug" -->
- <!-- tag="2:local 2" message="cleanup skipSingle local 2" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="init skipSingle local=false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="global: false local: false" type="qdebug" -->
+ <!-- tag="global=false:local=false" message="cleanup skipSingle local=false" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="init skipSingle local=true" type="qdebug" -->
+ <!-- tag="global=false:local=true" message="Skipping" type="skip" -->
+ <!-- tag="global=false:local=true" message="cleanup skipSingle local=true" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="init skipSingle local=false" type="qdebug" -->
+ <!-- tag="global=true:local=false" message="Skipping" type="skip" -->
+ <!-- tag="global=true:local=false" message="cleanup skipSingle local=false" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="init skipSingle local=true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="global: true local: true" type="qdebug" -->
+ <!-- tag="global=true:local=true" message="cleanup skipSingle local=true" type="qdebug" -->
</testcase>
<testcase result="pass" name="cleanupTestCase">
<!-- message="cleanupTestCase cleanupTestCase (null)" type="qdebug" -->
</testcase>
<system-err>
<![CDATA[initTestCase initTestCase (null)]]>
-<![CDATA[init testGlobal local 1]]>
+<![CDATA[init testGlobal local=false]]>
<![CDATA[global: false]]>
<![CDATA[local: false]]>
-<![CDATA[cleanup testGlobal local 1]]>
-<![CDATA[init testGlobal local 2]]>
+<![CDATA[cleanup testGlobal local=false]]>
+<![CDATA[init testGlobal local=true]]>
<![CDATA[global: false]]>
<![CDATA[local: true]]>
-<![CDATA[cleanup testGlobal local 2]]>
-<![CDATA[init testGlobal local 1]]>
+<![CDATA[cleanup testGlobal local=true]]>
+<![CDATA[init testGlobal local=false]]>
<![CDATA[global: true]]>
<![CDATA[local: false]]>
-<![CDATA[cleanup testGlobal local 1]]>
-<![CDATA[init testGlobal local 2]]>
+<![CDATA[cleanup testGlobal local=false]]>
+<![CDATA[init testGlobal local=true]]>
<![CDATA[global: true]]>
<![CDATA[local: true]]>
-<![CDATA[cleanup testGlobal local 2]]>
+<![CDATA[cleanup testGlobal local=true]]>
<![CDATA[skipping]]>
-<![CDATA[init skipLocal local 1]]>
+<![CDATA[init skipLocal local=false]]>
<![CDATA[skipping]]>
-<![CDATA[cleanup skipLocal local 1]]>
-<![CDATA[init skipLocal local 2]]>
+<![CDATA[cleanup skipLocal local=false]]>
+<![CDATA[init skipLocal local=true]]>
<![CDATA[skipping]]>
-<![CDATA[cleanup skipLocal local 2]]>
-<![CDATA[init skipSingle local 1]]>
-<![CDATA[global: false local: false]]>
-<![CDATA[cleanup skipSingle local 1]]>
-<![CDATA[init skipSingle local 2]]>
-<![CDATA[global: false local: true]]>
-<![CDATA[cleanup skipSingle local 2]]>
-<![CDATA[init skipSingle local 1]]>
+<![CDATA[cleanup skipLocal local=true]]>
+<![CDATA[init skipLocal local=false]]>
+<![CDATA[skipping]]>
+<![CDATA[cleanup skipLocal local=false]]>
+<![CDATA[init skipLocal local=true]]>
<![CDATA[skipping]]>
-<![CDATA[cleanup skipSingle local 1]]>
-<![CDATA[init skipSingle local 2]]>
+<![CDATA[cleanup skipLocal local=true]]>
+<![CDATA[init skipSingle local=false]]>
+<![CDATA[global: false local: false]]>
+<![CDATA[cleanup skipSingle local=false]]>
+<![CDATA[init skipSingle local=true]]>
+<![CDATA[Skipping]]>
+<![CDATA[cleanup skipSingle local=true]]>
+<![CDATA[init skipSingle local=false]]>
+<![CDATA[Skipping]]>
+<![CDATA[cleanup skipSingle local=false]]>
+<![CDATA[init skipSingle local=true]]>
<![CDATA[global: true local: true]]>
-<![CDATA[cleanup skipSingle local 2]]>
+<![CDATA[cleanup skipSingle local=true]]>
<![CDATA[cleanupTestCase cleanupTestCase (null)]]>
</system-err>
</testsuite>
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.lightxml b/tests/auto/testlib/selftests/expected_signaldumper.lightxml
new file mode 100644
index 0000000000..f68834e1a2
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.lightxml
@@ -0,0 +1,578 @@
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: QThread(_POINTER_) started ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="noConnections">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="oneSlot">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="oneSlotOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="twoSlots">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="twoSlotsOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="signalForwarding">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="signalForwardingOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="slotEmittingSignal">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="slotEmittingSignalOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) emitSecondSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="variousTypes">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: QThread(_POINTER_) finished ()]]></Description>
+</Message>
+<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.tap b/tests/auto/testlib/selftests/expected_signaldumper.tap
new file mode 100644
index 0000000000..04d7d94745
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.tap
@@ -0,0 +1,151 @@
+TAP version 13
+# tst_Signaldumper
+# Signal: QThread(_POINTER_) started ()
+ok 1 - initTestCase()
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+ok 2 - noConnections()
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 3 - oneSlot(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 4 - oneSlot(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 5 - oneSlotOldSyntax(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 6 - oneSlotOldSyntax(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 7 - twoSlots(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 8 - twoSlots(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+# Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 9 - twoSlotsOldSyntax(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 10 - twoSlotsOldSyntax(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 11 - signalForwarding(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+ok 12 - signalForwarding(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Slot: SignalSlotClass(_POINTER_) nestedSignal()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)
+# Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Slot: SignalSlotClass(_POINTER_) nestedSignal()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 13 - signalForwardingOldSyntax(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+# Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+ok 14 - signalForwardingOldSyntax(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 15 - slotEmittingSignal(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+ok 16 - slotEmittingSignal(queued)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Slot: SignalSlotClass(_POINTER_) emitSecondSignal()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+ok 17 - slotEmittingSignalOldSyntax(direct)
+# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+# Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+# Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+ok 18 - slotEmittingSignalOldSyntax(queued)
+# Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))
+# Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)
+# Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))
+# Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))
+# Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())
+# Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())
+# Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)
+# Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())
+# Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)
+# Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()
+# Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())
+# Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())
+ok 19 - variousTypes()
+ok 20 - cleanupTestCase()
+# Signal: QThread(_POINTER_) finished ()
+1..20
+# tests 20
+# pass 20
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.teamcity b/tests/auto/testlib/selftests/expected_signaldumper.teamcity
new file mode 100644
index 0000000000..3b8cf8c54f
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.teamcity
@@ -0,0 +1,61 @@
+##teamcity[testSuiteStarted name='tst_Signaldumper' flowId='tst_Signaldumper']
+##teamcity[testStarted name='initTestCase()' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='initTestCase()' out='INFO: Signal: QThread(_POINTER_) started ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='initTestCase()' flowId='tst_Signaldumper']
+##teamcity[testStarted name='noConnections()' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='noConnections()' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))' flowId='tst_Signaldumper']
+##teamcity[testFinished name='noConnections()' flowId='tst_Signaldumper']
+##teamcity[testStarted name='oneSlot(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='oneSlot(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='oneSlot(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='oneSlot(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='oneSlot(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='oneSlot(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='oneSlotOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='oneSlotOldSyntax(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='oneSlotOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='oneSlotOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='oneSlotOldSyntax(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='oneSlotOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='twoSlots(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='twoSlots(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='twoSlots(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='twoSlots(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='twoSlots(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='twoSlots(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='twoSlotsOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='twoSlotsOldSyntax(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='twoSlotsOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='twoSlotsOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='twoSlotsOldSyntax(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='twoSlotsOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='signalForwarding(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='signalForwarding(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='signalForwarding(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='signalForwarding(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='signalForwarding(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='signalForwarding(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='signalForwardingOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='signalForwardingOldSyntax(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Slot: SignalSlotClass(_POINTER_) nestedSignal()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Slot: SignalSlotClass(_POINTER_) nestedSignal()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='signalForwardingOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='signalForwardingOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='signalForwardingOldSyntax(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))|nINFO: Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='signalForwardingOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='slotEmittingSignal(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='slotEmittingSignal(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='slotEmittingSignal(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='slotEmittingSignal(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='slotEmittingSignal(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='slotEmittingSignal(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='slotEmittingSignalOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='slotEmittingSignalOldSyntax(direct)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Slot: SignalSlotClass(_POINTER_) emitSecondSignal()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='slotEmittingSignalOldSyntax(direct)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='slotEmittingSignalOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='slotEmittingSignalOldSyntax(queued)' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()|nINFO: Signal: QEventDispatcherPlatform(_POINTER_) awake ()|nINFO: Signal: SignalSlotClass(_POINTER_) nestedSignal ()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='slotEmittingSignalOldSyntax(queued)' flowId='tst_Signaldumper']
+##teamcity[testStarted name='variousTypes()' flowId='tst_Signaldumper']
+##teamcity[testStdOut name='variousTypes()' out='INFO: Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))|nINFO: Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)|nINFO: Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))|nINFO: Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))|nINFO: Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()|nINFO: Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())|nINFO: Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())' flowId='tst_Signaldumper']
+##teamcity[testFinished name='variousTypes()' flowId='tst_Signaldumper']
+##teamcity[testStarted name='cleanupTestCase()' flowId='tst_Signaldumper']
+##teamcity[testFinished name='cleanupTestCase()' flowId='tst_Signaldumper']
+##teamcity[testSuiteFinished name='tst_Signaldumper' flowId='tst_Signaldumper']
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.txt b/tests/auto/testlib/selftests/expected_signaldumper.txt
new file mode 100644
index 0000000000..f89c31afe5
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.txt
@@ -0,0 +1,149 @@
+********* Start testing of tst_Signaldumper *********
+Config: Using QtTest library
+INFO : tst_Signaldumper::initTestCase() Signal: QThread(_POINTER_) started ()
+PASS : tst_Signaldumper::initTestCase()
+INFO : tst_Signaldumper::noConnections() Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::noConnections() Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+PASS : tst_Signaldumper::noConnections()
+INFO : tst_Signaldumper::oneSlot(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::oneSlot(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlot(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlot(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlot(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlot(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::oneSlot(direct)
+INFO : tst_Signaldumper::oneSlot(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::oneSlot(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlot(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlot(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlot(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlot(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::oneSlot(queued)
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::oneSlotOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::oneSlotOldSyntax(direct)
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::oneSlotOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::oneSlotOldSyntax(queued)
+INFO : tst_Signaldumper::twoSlots(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::twoSlots(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlots(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlots(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlots(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlots(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::twoSlots(direct)
+INFO : tst_Signaldumper::twoSlots(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::twoSlots(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlots(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlots(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlots(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlots(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::twoSlots(queued)
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::twoSlotsOldSyntax(direct)
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::twoSlotsOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::twoSlotsOldSyntax(queued)
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwarding(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::signalForwarding(direct)
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwarding(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+PASS : tst_Signaldumper::signalForwarding(queued)
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) nestedSignal()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) nestedSignal()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::signalForwardingOldSyntax(direct)
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::signalForwardingOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+PASS : tst_Signaldumper::signalForwardingOldSyntax(queued)
+INFO : tst_Signaldumper::slotEmittingSignal(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::slotEmittingSignal(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::slotEmittingSignal(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::slotEmittingSignal(direct)
+INFO : tst_Signaldumper::slotEmittingSignal(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::slotEmittingSignal(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::slotEmittingSignal(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+PASS : tst_Signaldumper::slotEmittingSignal(queued)
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(direct) Slot: SignalSlotClass(_POINTER_) emitSecondSignal()
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(direct) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(direct) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+PASS : tst_Signaldumper::slotEmittingSignalOldSyntax(direct)
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(queued) Signal: QEventDispatcherPlatform(_POINTER_) awake ()
+INFO : tst_Signaldumper::slotEmittingSignalOldSyntax(queued) Signal: SignalSlotClass(_POINTER_) nestedSignal ()
+PASS : tst_Signaldumper::slotEmittingSignalOldSyntax(queued)
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())
+INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())
+PASS : tst_Signaldumper::variousTypes()
+PASS : tst_Signaldumper::cleanupTestCase()
+INFO : tst_Signaldumper::UnknownTestFunc() Signal: QThread(_POINTER_) finished ()
+Totals: 20 passed, 0 failed, 0 skipped, 0 blacklisted, 0ms
+********* Finished testing of tst_Signaldumper *********
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.xml b/tests/auto/testlib/selftests/expected_signaldumper.xml
new file mode 100644
index 0000000000..82959c62df
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.xml
@@ -0,0 +1,581 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestCase name="tst_Signaldumper">
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: QThread(_POINTER_) started ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="noConnections">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="oneSlot">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="oneSlotOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="twoSlots">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="twoSlotsOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="signalForwarding">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="signalForwardingOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="slotEmittingSignal">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="slotEmittingSignalOldSyntax">
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Slot: SignalSlotClass(_POINTER_) emitSecondSignal()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[direct]]></DataTag>
+</Incident>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]></Description>
+</Message>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[queued]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="variousTypes">
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]></Description>
+</Message>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]></Description>
+</Message>
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Message type="info" file="" line="0">
+ <Description><![CDATA[Signal: QThread(_POINTER_) finished ()]]></Description>
+</Message>
+<Duration msecs="0"/>
+</TestCase>
diff --git a/tests/auto/testlib/selftests/expected_signaldumper.xunitxml b/tests/auto/testlib/selftests/expected_signaldumper.xunitxml
new file mode 100644
index 0000000000..930dc97262
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_signaldumper.xunitxml
@@ -0,0 +1,284 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite errors="125" failures="0" tests="12" name="tst_Signaldumper">
+ <properties>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
+ <property value="" name="QtBuild"/>
+ </properties>
+ <testcase result="pass" name="initTestCase">
+ <!-- message="Signal: QThread(_POINTER_) started ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="noConnections">
+ <!-- message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ </testcase>
+ <testcase result="pass" name="oneSlot">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="oneSlotOldSyntax">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="twoSlots">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="twoSlotsOldSyntax">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="signalForwarding">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="signalForwardingOldSyntax">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) nestedSignal()" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) nestedSignal()" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="slotEmittingSignal">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="slotEmittingSignalOldSyntax">
+ <!-- tag="direct" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="direct" message=" Slot: SignalSlotClass(_POINTER_) emitSecondSignal()" type="info" -->
+ <!-- tag="direct" message=" Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ <!-- tag="direct" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()" type="info" -->
+ <!-- tag="queued" message="Signal: QEventDispatcherPlatform(_POINTER_) awake ()" type="info" -->
+ <!-- tag="queued" message="Signal: SignalSlotClass(_POINTER_) nestedSignal ()" type="info" -->
+ </testcase>
+ <testcase result="pass" name="variousTypes">
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&amp;)@_POINTER_)" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qListSignal (QList&lt;int&gt;())" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector&lt;int&gt;())" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector&lt;int&gt;&amp;)@_POINTER_)" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector&lt;int&gt;())" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector&lt;int&gt;*)_POINTER_)" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())" type="info" -->
+ <!-- message="Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())" type="info" -->
+ </testcase>
+ <testcase result="pass" name="cleanupTestCase">
+ <!-- message="Signal: QThread(_POINTER_) finished ()" type="info" -->
+ </testcase>
+ <system-err>
+<![CDATA[Signal: QThread(_POINTER_) started ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithParameters(int,char)]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) slotWithoutParameters()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignalWithParameters(int,char)]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) nestedSignal()]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithParameters (int(242), char(m))]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[ Slot: SignalSlotClass(_POINTER_) emitSecondSignal()]]>
+<![CDATA[ Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()]]>
+<![CDATA[Signal: QEventDispatcherPlatform(_POINTER_) awake ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) nestedSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qListSignal (QList<int>())]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector<int>())]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector<int>&)@_POINTER_)]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector<int>())]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector<int>*)_POINTER_)]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]>
+<![CDATA[Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())]]>
+<![CDATA[Signal: QThread(_POINTER_) finished ()]]>
+ </system-err>
+</testsuite>
diff --git a/tests/auto/testlib/selftests/expected_testlib.lightxml b/tests/auto/testlib/selftests/expected_testlib.lightxml
new file mode 100644
index 0000000000..47f5edc07d
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_testlib.lightxml
@@ -0,0 +1,45 @@
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="basics">
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/testlib/tst_testlib.cpp" line="0">
+ <Description><![CDATA[Compared pointers are not the same]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="delays">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="reals">
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[zero]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[self-qQNaN]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[self-qInf]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[infineg]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[Sin(turn/4)]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[Cos(turn/2)]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_testlib.tap b/tests/auto/testlib/selftests/expected_testlib.tap
new file mode 100644
index 0000000000..d85b23b7d4
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_testlib.tap
@@ -0,0 +1,22 @@
+TAP version 13
+# tst_TestLib
+ok 1 - initTestCase()
+not ok 2 - basics()
+ ---
+ # Compared pointers are not the same
+ at: tst_TestLib::basics() (qtbase/tests/auto/testlib/selftests/testlib/tst_testlib.cpp:54)
+ file: qtbase/tests/auto/testlib/selftests/testlib/tst_testlib.cpp
+ line: 54
+ ...
+ok 3 - delays()
+ok 4 - reals(zero)
+ok 5 - reals(self-qQNaN)
+ok 6 - reals(self-qInf)
+ok 7 - reals(infineg)
+ok 8 - reals(Sin(turn/4))
+ok 9 - reals(Cos(turn/2))
+ok 10 - cleanupTestCase()
+1..10
+# tests 10
+# pass 9
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_testlib.teamcity b/tests/auto/testlib/selftests/expected_testlib.teamcity
new file mode 100644
index 0000000000..11617121e2
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_testlib.teamcity
@@ -0,0 +1,23 @@
+##teamcity[testSuiteStarted name='tst_TestLib' flowId='tst_TestLib']
+##teamcity[testStarted name='initTestCase()' flowId='tst_TestLib']
+##teamcity[testFinished name='initTestCase()' flowId='tst_TestLib']
+##teamcity[testStarted name='basics()' flowId='tst_TestLib']
+##teamcity[testFailed name='basics()' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/testlib/tst_testlib.cpp(0)|]' details='Compared pointers are not the same' flowId='tst_TestLib']
+##teamcity[testFinished name='basics()' flowId='tst_TestLib']
+##teamcity[testStarted name='delays()' flowId='tst_TestLib']
+##teamcity[testFinished name='delays()' flowId='tst_TestLib']
+##teamcity[testStarted name='reals(zero)' flowId='tst_TestLib']
+##teamcity[testFinished name='reals(zero)' flowId='tst_TestLib']
+##teamcity[testStarted name='reals(self-qQNaN)' flowId='tst_TestLib']
+##teamcity[testFinished name='reals(self-qQNaN)' flowId='tst_TestLib']
+##teamcity[testStarted name='reals(self-qInf)' flowId='tst_TestLib']
+##teamcity[testFinished name='reals(self-qInf)' flowId='tst_TestLib']
+##teamcity[testStarted name='reals(infineg)' flowId='tst_TestLib']
+##teamcity[testFinished name='reals(infineg)' flowId='tst_TestLib']
+##teamcity[testStarted name='reals(Sin(turn/4))' flowId='tst_TestLib']
+##teamcity[testFinished name='reals(Sin(turn/4))' flowId='tst_TestLib']
+##teamcity[testStarted name='reals(Cos(turn/2))' flowId='tst_TestLib']
+##teamcity[testFinished name='reals(Cos(turn/2))' flowId='tst_TestLib']
+##teamcity[testStarted name='cleanupTestCase()' flowId='tst_TestLib']
+##teamcity[testFinished name='cleanupTestCase()' flowId='tst_TestLib']
+##teamcity[testSuiteFinished name='tst_TestLib' flowId='tst_TestLib']
diff --git a/tests/auto/testlib/selftests/expected_testlib.txt b/tests/auto/testlib/selftests/expected_testlib.txt
new file mode 100644
index 0000000000..a3f463e7d4
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_testlib.txt
@@ -0,0 +1,15 @@
+********* Start testing of tst_TestLib *********
+Config: Using QtTest library
+PASS : tst_TestLib::initTestCase()
+FAIL! : tst_TestLib::basics() Compared pointers are not the same
+ Loc: [qtbase/tests/auto/testlib/selftests/testlib/tst_testlib.cpp(0)]
+PASS : tst_TestLib::delays()
+PASS : tst_TestLib::reals(zero)
+PASS : tst_TestLib::reals(self-qQNaN)
+PASS : tst_TestLib::reals(self-qInf)
+PASS : tst_TestLib::reals(infineg)
+PASS : tst_TestLib::reals(Sin(turn/4))
+PASS : tst_TestLib::reals(Cos(turn/2))
+PASS : tst_TestLib::cleanupTestCase()
+Totals: 9 passed, 1 failed, 0 skipped, 0 blacklisted, 0ms
+********* Finished testing of tst_TestLib *********
diff --git a/tests/auto/testlib/selftests/expected_testlib.xml b/tests/auto/testlib/selftests/expected_testlib.xml
new file mode 100644
index 0000000000..3aca904ac1
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_testlib.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestCase name="tst_TestLib">
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="basics">
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/testlib/tst_testlib.cpp" line="0">
+ <Description><![CDATA[Compared pointers are not the same]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="delays">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="reals">
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[zero]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[self-qQNaN]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[self-qInf]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[infineg]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[Sin(turn/4)]]></DataTag>
+</Incident>
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[Cos(turn/2)]]></DataTag>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
+</TestCase>
diff --git a/tests/auto/testlib/selftests/expected_testlib.xunitxml b/tests/auto/testlib/selftests/expected_testlib.xunitxml
new file mode 100644
index 0000000000..c9c67c7c9a
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_testlib.xunitxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite errors="0" failures="1" tests="5" name="tst_TestLib">
+ <properties>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
+ <property value="" name="QtBuild"/>
+ </properties>
+ <testcase result="pass" name="initTestCase"/>
+ <testcase result="fail" name="basics">
+ <failure message="Compared pointers are not the same" result="fail"/>
+ </testcase>
+ <testcase result="pass" name="delays"/>
+ <testcase result="pass" name="reals"/>
+ <testcase result="pass" name="cleanupTestCase"/>
+ <system-err/>
+</testsuite>
diff --git a/tests/auto/testlib/selftests/expected_watchdog.lightxml b/tests/auto/testlib/selftests/expected_watchdog.lightxml
new file mode 100644
index 0000000000..1070324f2a
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_watchdog.lightxml
@@ -0,0 +1,19 @@
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="delay">
+<Message type="qfatal" file="" line="0">
+ <Description><![CDATA[Test function timed out]]></Description>
+</Message>
+<Incident type="fail" file="Unknown file" line="0">
+ <Description><![CDATA[Received a fatal error.]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_watchdog.tap b/tests/auto/testlib/selftests/expected_watchdog.tap
new file mode 100644
index 0000000000..3d4890b67e
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_watchdog.tap
@@ -0,0 +1,15 @@
+TAP version 13
+# tst_Watchdog
+ok 1 - initTestCase()
+# Test function timed out
+not ok 2 - delay()
+ ---
+ # Received a fatal error.
+ at: tst_Watchdog::delay() (Unknown file:0)
+ file: Unknown file
+ line: 0
+ ...
+1..2
+# tests 2
+# pass 1
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_watchdog.teamcity b/tests/auto/testlib/selftests/expected_watchdog.teamcity
new file mode 100644
index 0000000000..0d77bf70d5
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_watchdog.teamcity
@@ -0,0 +1,8 @@
+##teamcity[testSuiteStarted name='tst_Watchdog' flowId='tst_Watchdog']
+##teamcity[testStarted name='initTestCase()' flowId='tst_Watchdog']
+##teamcity[testFinished name='initTestCase()' flowId='tst_Watchdog']
+##teamcity[testStarted name='delay()' flowId='tst_Watchdog']
+##teamcity[testFailed name='delay()' message='Failure! |[Loc: Unknown file(0)|]' details='Received a fatal error.' flowId='tst_Watchdog']
+##teamcity[testStdOut name='delay()' out='QFATAL: Test function timed out' flowId='tst_Watchdog']
+##teamcity[testFinished name='delay()' flowId='tst_Watchdog']
+##teamcity[testSuiteFinished name='tst_Watchdog' flowId='tst_Watchdog']
diff --git a/tests/auto/testlib/selftests/expected_watchdog.txt b/tests/auto/testlib/selftests/expected_watchdog.txt
new file mode 100644
index 0000000000..4c9cde4ea2
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_watchdog.txt
@@ -0,0 +1,8 @@
+********* Start testing of tst_Watchdog *********
+Config: Using QtTest library
+PASS : tst_Watchdog::initTestCase()
+QFATAL : tst_Watchdog::delay() Test function timed out
+FAIL! : tst_Watchdog::delay() Received a fatal error.
+ Loc: [Unknown file(0)]
+Totals: 1 passed, 1 failed, 0 skipped, 0 blacklisted, 0ms
+********* Finished testing of tst_Watchdog *********
diff --git a/tests/auto/testlib/selftests/expected_watchdog.xml b/tests/auto/testlib/selftests/expected_watchdog.xml
new file mode 100644
index 0000000000..f1642fba79
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_watchdog.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestCase name="tst_Watchdog">
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="delay">
+<Message type="qfatal" file="" line="0">
+ <Description><![CDATA[Test function timed out]]></Description>
+</Message>
+<Incident type="fail" file="Unknown file" line="0">
+ <Description><![CDATA[Received a fatal error.]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
+</TestCase>
diff --git a/tests/auto/testlib/selftests/expected_watchdog.xunitxml b/tests/auto/testlib/selftests/expected_watchdog.xunitxml
new file mode 100644
index 0000000000..7e16ab2c34
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_watchdog.xunitxml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite errors="1" failures="1" tests="2" name="tst_Watchdog">
+ <properties>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
+ <property value="" name="QtBuild"/>
+ </properties>
+ <testcase result="pass" name="initTestCase"/>
+ <testcase result="fail" name="delay">
+ <!-- message="Test function timed out" type="qfatal" -->
+ <failure message="Received a fatal error." result="fail"/>
+ </testcase>
+ <system-err>
+<![CDATA[Test function timed out]]>
+ </system-err>
+</testsuite>
diff --git a/tests/auto/testlib/selftests/expectfail/expectfail.pro b/tests/auto/testlib/selftests/expectfail/expectfail.pro
index c1849990f2..db383bee6a 100644
--- a/tests/auto/testlib/selftests/expectfail/expectfail.pro
+++ b/tests/auto/testlib/selftests/expectfail/expectfail.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = expectfail
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/failcleanup/failcleanup.pro b/tests/auto/testlib/selftests/failcleanup/failcleanup.pro
index 426d7cc45b..12da5920fb 100644
--- a/tests/auto/testlib/selftests/failcleanup/failcleanup.pro
+++ b/tests/auto/testlib/selftests/failcleanup/failcleanup.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = failcleanup
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/faildatatype/BLACKLIST b/tests/auto/testlib/selftests/faildatatype/BLACKLIST
new file mode 100644
index 0000000000..bb1cae98e5
--- /dev/null
+++ b/tests/auto/testlib/selftests/faildatatype/BLACKLIST
@@ -0,0 +1,4 @@
+# See qtbase/src/testlib/qtestblacklist.cpp for format
+# Incidental test: exercise more of the blacklisting code
+[value:bool-as-string]
+*
diff --git a/tests/auto/testlib/selftests/faildatatype/faildatatype.pro b/tests/auto/testlib/selftests/faildatatype/faildatatype.pro
new file mode 100644
index 0000000000..4ff7352555
--- /dev/null
+++ b/tests/auto/testlib/selftests/faildatatype/faildatatype.pro
@@ -0,0 +1,9 @@
+SOURCES += tst_faildatatype.cpp
+QT = core testlib
+
+darwin: CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = faildatatype
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/faildatatype/tst_faildatatype.cpp b/tests/auto/testlib/selftests/faildatatype/tst_faildatatype.cpp
new file mode 100644
index 0000000000..b49c7723ef
--- /dev/null
+++ b/tests/auto/testlib/selftests/faildatatype/tst_faildatatype.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+class tst_FailDataType: public QObject
+{
+Q_OBJECT
+private slots:
+ void value_data() const;
+ void value() const;
+};
+
+void tst_FailDataType::value_data() const
+{
+ QTest::addColumn<QString>("value");
+
+ QTest::newRow("bool-as-string") << true; // assertion should fail here
+}
+
+/*! \internal
+ This function should never be run because its _data() fails.
+ */
+void tst_FailDataType::value() const
+{
+ QFAIL("ERROR: this function is NOT supposed to be run.");
+}
+
+QTEST_APPLESS_MAIN(tst_FailDataType)
+
+#include "tst_faildatatype.moc"
diff --git a/tests/auto/testlib/selftests/failfetchtype/BLACKLIST b/tests/auto/testlib/selftests/failfetchtype/BLACKLIST
new file mode 100644
index 0000000000..20a502724a
--- /dev/null
+++ b/tests/auto/testlib/selftests/failfetchtype/BLACKLIST
@@ -0,0 +1,4 @@
+# See qtbase/src/testlib/qtestblacklist.cpp for format
+# Incidental test: exercise more of the blacklisting code
+[fetch:no-such-dataset]
+*
diff --git a/tests/auto/testlib/selftests/failfetchtype/failfetchtype.pro b/tests/auto/testlib/selftests/failfetchtype/failfetchtype.pro
new file mode 100644
index 0000000000..5821018af4
--- /dev/null
+++ b/tests/auto/testlib/selftests/failfetchtype/failfetchtype.pro
@@ -0,0 +1,9 @@
+SOURCES += tst_failfetchtype.cpp
+QT = core testlib
+
+darwin: CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = failfetchtype
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/failfetchtype/tst_failfetchtype.cpp b/tests/auto/testlib/selftests/failfetchtype/tst_failfetchtype.cpp
new file mode 100644
index 0000000000..2dd32a5a5e
--- /dev/null
+++ b/tests/auto/testlib/selftests/failfetchtype/tst_failfetchtype.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+class tst_FailFetchType: public QObject
+{
+Q_OBJECT
+private slots:
+ void fetch_data() const;
+ void fetch() const;
+};
+
+void tst_FailFetchType::fetch_data() const
+{
+ QTest::addColumn<bool>("value");
+
+ QTest::newRow("bool") << true;
+}
+
+void tst_FailFetchType::fetch() const
+{
+ QFETCH(QString, value); // assertion should fail here
+ QFAIL("ERROR: this function is NOT supposed to be run.");
+}
+
+QTEST_APPLESS_MAIN(tst_FailFetchType)
+
+#include "tst_failfetchtype.moc"
diff --git a/tests/auto/testlib/selftests/failinit/failinit.pro b/tests/auto/testlib/selftests/failinit/failinit.pro
index 6a30a5af68..46b1c3a6c4 100644
--- a/tests/auto/testlib/selftests/failinit/failinit.pro
+++ b/tests/auto/testlib/selftests/failinit/failinit.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = failinit
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/failinitdata/failinitdata.pro b/tests/auto/testlib/selftests/failinitdata/failinitdata.pro
index b608c67dbb..63b32cb6d6 100644
--- a/tests/auto/testlib/selftests/failinitdata/failinitdata.pro
+++ b/tests/auto/testlib/selftests/failinitdata/failinitdata.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = failinitdata
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/fetchbogus/fetchbogus.pro b/tests/auto/testlib/selftests/fetchbogus/fetchbogus.pro
index 33b306ca75..0fbb5e4c00 100644
--- a/tests/auto/testlib/selftests/fetchbogus/fetchbogus.pro
+++ b/tests/auto/testlib/selftests/fetchbogus/fetchbogus.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = fetchbogus
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/findtestdata/findtestdata.pro b/tests/auto/testlib/selftests/findtestdata/findtestdata.pro
index f04a640c59..7fbdaea3a3 100644
--- a/tests/auto/testlib/selftests/findtestdata/findtestdata.pro
+++ b/tests/auto/testlib/selftests/findtestdata/findtestdata.pro
@@ -7,3 +7,5 @@ CONFIG -= debug_and_release_target
RESOURCES = findtestdata.qrc
TARGET = findtestdata
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/float/float.pro b/tests/auto/testlib/selftests/float/float.pro
index 95980eeac8..479eb152c5 100644
--- a/tests/auto/testlib/selftests/float/float.pro
+++ b/tests/auto/testlib/selftests/float/float.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = float
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/float/tst_float.cpp b/tests/auto/testlib/selftests/float/tst_float.cpp
index babb588f4b..cefd8a57c4 100644
--- a/tests/auto/testlib/selftests/float/tst_float.cpp
+++ b/tests/auto/testlib/selftests/float/tst_float.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include <QtCore/QCoreApplication>
+#include <QtCore/qfloat16.h>
#include <QtTest/QtTest>
#include <QDebug>
@@ -39,10 +40,61 @@ private slots:
void doubleComparisons_data() const;
void floatComparisons() const;
void floatComparisons_data() const;
+ void float16Comparisons() const;
+ void float16Comparisons_data() const;
void compareFloatTests() const;
void compareFloatTests_data() const;
};
+template<typename F>
+static void nonFinite_data(F zero, F one)
+{
+ using Bounds = std::numeric_limits<F>;
+
+ // QCOMPARE special-cases non-finite values
+ if (Bounds::has_quiet_NaN) {
+ const F nan = Bounds::quiet_NaN();
+ QTest::newRow("should PASS: NaN == NaN") << nan << nan;
+ QTest::newRow("should FAIL: NaN != 0") << nan << zero;
+ QTest::newRow("should FAIL: 0 != NaN") << zero << nan;
+ QTest::newRow("should FAIL: NaN != 1") << nan << one;
+ QTest::newRow("should FAIL: 1 != NaN") << one << nan;
+ }
+
+ if (Bounds::has_infinity) {
+ const F uge = Bounds::infinity();
+ QTest::newRow("should PASS: inf == inf") << uge << uge;
+ QTest::newRow("should PASS: -inf == -inf") << -uge << -uge;
+ QTest::newRow("should FAIL: inf != -inf") << uge << -uge;
+ QTest::newRow("should FAIL: -inf != inf") << -uge << uge;
+ if (Bounds::has_quiet_NaN) {
+ const F nan = Bounds::quiet_NaN();
+ QTest::newRow("should FAIL: inf != nan") << uge << nan;
+ QTest::newRow("should FAIL: nan != inf") << nan << uge;
+ QTest::newRow("should FAIL: -inf != nan") << -uge << nan;
+ QTest::newRow("should FAIL: nan != -inf") << nan << -uge;
+ }
+ QTest::newRow("should FAIL: inf != 0") << uge << zero;
+ QTest::newRow("should FAIL: 0 != inf") << zero << uge;
+ QTest::newRow("should FAIL: -inf != 0") << -uge << zero;
+ QTest::newRow("should FAIL: 0 != -inf") << zero << -uge;
+ QTest::newRow("should FAIL: inf != 1") << uge << one;
+ QTest::newRow("should FAIL: 1 != inf") << one << uge;
+ QTest::newRow("should FAIL: -inf != 1") << -uge << one;
+ QTest::newRow("should FAIL: 1 != -inf") << one << -uge;
+
+ const F big = Bounds::max();
+ QTest::newRow("should FAIL: inf != max") << uge << big;
+ QTest::newRow("should FAIL: inf != -max") << uge << -big;
+ QTest::newRow("should FAIL: max != inf") << big << uge;
+ QTest::newRow("should FAIL: -max != inf") << -big << uge;
+ QTest::newRow("should FAIL: -inf != max") << -uge << big;
+ QTest::newRow("should FAIL: -inf != -max") << -uge << -big;
+ QTest::newRow("should FAIL: max != -inf") << big << -uge;
+ QTest::newRow("should FAIL: -max != -inf") << -big << -uge;
+ }
+}
+
void tst_float::doubleComparisons() const
{
QFETCH(double, operandLeft);
@@ -55,65 +107,26 @@ void tst_float::doubleComparisons_data() const
{
QTest::addColumn<double>("operandLeft");
QTest::addColumn<double>("operandRight");
+ double zero(0.), one(1.);
- QTest::newRow("should PASS 1") << 0. << 0.;
- QTest::newRow("should FAIL 1") << 1.00000 << 3.00000;
- QTest::newRow("should FAIL 2") << 1.00000e-7 << 3.00000e-7;
+ QTest::newRow("should FAIL 1") << one << 3.;
+ QTest::newRow("should PASS 1") << zero << zero;
+ QTest::newRow("should FAIL 2") << 1.e-7 << 3.e-7;
// QCOMPARE for doubles uses qFuzzyCompare(), which succeeds if the numbers
// differ by no more than 1e-12 times the smaller value. Thus
// QCOMPARE(1e12-2, 1e12-1) should fail, while QCOMPARE(1e12+1, 1e12+2)
// should pass.
- QTest::newRow("should PASS 2") << 1e12 + 1. << 1e12 + 2.;
- QTest::newRow("should FAIL 3") << 1e12 - 1. << 1e12 - 2.;
+ QTest::newRow("should PASS 2") << 1e12 + one << 1e12 + 2.;
+ QTest::newRow("should FAIL 3") << 1e12 - one << 1e12 - 2.;
// ... but rounding makes that a bit unrelaible when scaled close to the bounds.
QTest::newRow("should PASS 3") << 1e-310 + 1e-322 << 1e-310 + 2e-322;
QTest::newRow("should FAIL 4") << 1e-310 - 1e-322 << 1e-310 - 3e-322;
QTest::newRow("should PASS 4") << 1e307 + 1e295 << 1e307 + 2e295;
QTest::newRow("should FAIL 5") << 1e307 - 1e295 << 1e307 - 3e295;
- // QCOMPARE special-cases non-finite values
- if (std::numeric_limits<double>::has_quiet_NaN) {
- const double nan = std::numeric_limits<double>::quiet_NaN();
- QTest::newRow("should PASS: NaN == NaN") << nan << nan;
- QTest::newRow("should FAIL: NaN != 0") << nan << 0.;
- QTest::newRow("should FAIL: 0 != NaN") << 0. << nan;
- QTest::newRow("should FAIL: NaN != 1") << nan << 1.;
- QTest::newRow("should FAIL: 1 != NaN") << 1. << nan;
- }
- if (std::numeric_limits<double>::has_infinity) {
- const double uge = std::numeric_limits<double>::infinity();
- QTest::newRow("should PASS: inf == inf") << uge << uge;
- QTest::newRow("should PASS: -inf == -inf") << -uge << -uge;
- QTest::newRow("should FAIL: inf != -inf") << uge << -uge;
- QTest::newRow("should FAIL: -inf != inf") << -uge << uge;
- if (std::numeric_limits<double>::has_quiet_NaN) {
- const double nan = std::numeric_limits<double>::quiet_NaN();
- QTest::newRow("should FAIL: inf != nan") << uge << nan;
- QTest::newRow("should FAIL: nan != inf") << nan << uge;
- QTest::newRow("should FAIL: -inf != nan") << -uge << nan;
- QTest::newRow("should FAIL: nan != -inf") << nan << -uge;
- }
- QTest::newRow("should FAIL: inf != 0") << uge << 0.;
- QTest::newRow("should FAIL: 0 != inf") << 0. << uge;
- QTest::newRow("should FAIL: -inf != 0") << -uge << 0.;
- QTest::newRow("should FAIL: 0 != -inf") << 0. << -uge;
- QTest::newRow("should FAIL: inf != 1") << uge << 1.;
- QTest::newRow("should FAIL: 1 != inf") << 1. << uge;
- QTest::newRow("should FAIL: -inf != 1") << -uge << 1.;
- QTest::newRow("should FAIL: 1 != -inf") << 1. << -uge;
-
- const double big = std::numeric_limits<double>::max();
- QTest::newRow("should FAIL: inf != max") << uge << big;
- QTest::newRow("should FAIL: inf != -max") << uge << -big;
- QTest::newRow("should FAIL: max != inf") << big << uge;
- QTest::newRow("should FAIL: -max != inf") << -big << uge;
- QTest::newRow("should FAIL: -inf != max") << -uge << big;
- QTest::newRow("should FAIL: -inf != -max") << -uge << -big;
- QTest::newRow("should FAIL: max != -inf") << big << -uge;
- QTest::newRow("should FAIL: -max != -inf") << -big << -uge;
- }
+ nonFinite_data(zero, one);
}
void tst_float::floatComparisons() const
@@ -128,65 +141,56 @@ void tst_float::floatComparisons_data() const
{
QTest::addColumn<float>("operandLeft");
QTest::addColumn<float>("operandRight");
+ float zero(0.f), one(1.f);
- QTest::newRow("should FAIL 1") << 1.00000f << 3.00000f;
- QTest::newRow("should PASS 1") << 0.f << 0.f;
- QTest::newRow("should FAIL 2") << 1.00000e-7f << 3.00000e-7f;
+ QTest::newRow("should FAIL 1") << one << 3.f;
+ QTest::newRow("should PASS 1") << zero << zero;
+ QTest::newRow("should FAIL 2") << 1.e-7f << 3.e-7f;
// QCOMPARE for floats uses qFuzzyCompare(), which succeeds if the numbers
// differ by no more than 1e-5 times the smaller value. Thus
// QCOMPARE(1e5-2, 1e5-1) should fail, while QCOMPARE(1e5+1, 1e5+2)
// should pass.
- QTest::newRow("should PASS 2") << 1e5f + 1.f << 1e5f + 2.f;
- QTest::newRow("should FAIL 3") << 1e5f - 1.f << 1e5f - 2.f;
+ QTest::newRow("should PASS 2") << 1e5f + one << 1e5f + 2.f;
+ QTest::newRow("should FAIL 3") << 1e5f - one << 1e5f - 2.f;
// ... but rounding makes that a bit unrelaible when scaled close to the bounds.
QTest::newRow("should PASS 3") << 1e-39f + 1e-44f << 1e-39f + 2e-44f;
QTest::newRow("should FAIL 4") << 1e-39f - 1e-44f << 1e-39f - 3e-44f;
QTest::newRow("should PASS 4") << 1e38f + 1e33f << 1e38f + 2e33f;
QTest::newRow("should FAIL 5") << 1e38f - 1e33f << 1e38f - 3e33f;
- // QCOMPARE special-cases non-finite values
- if (std::numeric_limits<float>::has_quiet_NaN) {
- const float nan = std::numeric_limits<float>::quiet_NaN();
- QTest::newRow("should PASS: NaN == NaN") << nan << nan;
- QTest::newRow("should FAIL: NaN != 0") << nan << 0.f;
- QTest::newRow("should FAIL: 0 != NaN") << 0.f << nan;
- QTest::newRow("should FAIL: NaN != 1") << nan << 1.f;
- QTest::newRow("should FAIL: 1 != NaN") << 1.f << nan;
- }
- if (std::numeric_limits<float>::has_infinity) {
- const float uge = std::numeric_limits<float>::infinity();
- QTest::newRow("should PASS: inf == inf") << uge << uge;
- QTest::newRow("should PASS: -inf == -inf") << -uge << -uge;
- QTest::newRow("should FAIL: inf != -inf") << uge << -uge;
- QTest::newRow("should FAIL: -inf != inf") << -uge << uge;
- if (std::numeric_limits<float>::has_quiet_NaN) {
- const float nan = std::numeric_limits<float>::quiet_NaN();
- QTest::newRow("should FAIL: inf != nan") << uge << nan;
- QTest::newRow("should FAIL: nan != inf") << nan << uge;
- QTest::newRow("should FAIL: -inf != nan") << -uge << nan;
- QTest::newRow("should FAIL: nan != -inf") << nan << -uge;
- }
- QTest::newRow("should FAIL: inf != 0") << uge << 0.f;
- QTest::newRow("should FAIL: 0 != inf") << 0.f << uge;
- QTest::newRow("should FAIL: -inf != 0") << -uge << 0.f;
- QTest::newRow("should FAIL: 0 != -inf") << 0.f << -uge;
- QTest::newRow("should FAIL: inf != 1") << uge << 1.f;
- QTest::newRow("should FAIL: 1 != inf") << 1.f << uge;
- QTest::newRow("should FAIL: -inf != 1") << -uge << 1.f;
- QTest::newRow("should FAIL: 1 != -inf") << 1.f << -uge;
-
- const float big = std::numeric_limits<float>::max();
- QTest::newRow("should FAIL: inf != max") << uge << big;
- QTest::newRow("should FAIL: inf != -max") << uge << -big;
- QTest::newRow("should FAIL: max != inf") << big << uge;
- QTest::newRow("should FAIL: -max != inf") << -big << uge;
- QTest::newRow("should FAIL: -inf != max") << -uge << big;
- QTest::newRow("should FAIL: -inf != -max") << -uge << -big;
- QTest::newRow("should FAIL: max != -inf") << big << -uge;
- QTest::newRow("should FAIL: -max != -inf") << -big << -uge;
- }
+ nonFinite_data(zero, one);
+}
+
+void tst_float::float16Comparisons() const
+{
+ QFETCH(qfloat16, operandLeft);
+ QFETCH(qfloat16, operandRight);
+
+ QCOMPARE(operandLeft, operandRight);
+}
+
+void tst_float::float16Comparisons_data() const
+{
+ QTest::addColumn<qfloat16>("operandLeft");
+ QTest::addColumn<qfloat16>("operandRight");
+ qfloat16 zero(0), one(1);
+
+ QTest::newRow("should FAIL 1") << one << qfloat16(3);
+ QTest::newRow("should PASS 1") << zero << zero;
+ QTest::newRow("should FAIL 2") << qfloat16(1e-4f) << qfloat16(3e-4f);
+
+ // QCOMPARE for qfloat16s uses qFuzzyCompare()
+ QTest::newRow("should PASS 2") << qfloat16(1001) << qfloat16(1002);
+ QTest::newRow("should FAIL 3") << qfloat16(98) << qfloat16(99);
+ // ... which gets a bit unreliable near to the type's bounds
+ QTest::newRow("should PASS 3") << qfloat16(6e-5f) + qfloat16(6e-7f) << qfloat16(6e-5f) + qfloat16(11e-7f);
+ QTest::newRow("should FAIL 4") << qfloat16(6e-5f) - qfloat16(7e-7f) << qfloat16(6e-5f) - qfloat16(13e-7f);
+ QTest::newRow("should PASS 4") << qfloat16(6e4) + qfloat16(700) << qfloat16(6e4) + qfloat16(1200);
+ QTest::newRow("should FAIL 5") << qfloat16(6e4) - qfloat16(600) << qfloat16(6e4) - qfloat16(1200);
+
+ nonFinite_data(zero, one);
}
void tst_float::compareFloatTests() const
diff --git a/tests/auto/testlib/selftests/generate_expected_output.py b/tests/auto/testlib/selftests/generate_expected_output.py
index 111870b3fb..48ecbf0289 100755
--- a/tests/auto/testlib/selftests/generate_expected_output.py
+++ b/tests/auto/testlib/selftests/generate_expected_output.py
@@ -92,6 +92,17 @@ class Cleaner (object):
(r'(Loc: \[[^[\]()]+)\(\d+\)', r'\1(0)'), # txt
(r'(\[Loc: [^[\]()]+)\(\d+\)', r'\1(0)'), # teamcity
(r'(<(?:Incident|Message)\b.*\bfile=.*\bline=)"\d+"', r'\1"0"'), # lightxml, xml
+ # Pointers printed by signal dumper:
+ (r'\(\b[a-f0-9]{8,}\b\)', r'(_POINTER_)'),
+ # Example/for reference:
+ # ((QString&)@55f5fbb8dd40)
+ # ((const QVector<int>*)7ffd671d4558)
+ (r'\((\((?:const )?\w+(?:<[^>]+>)?[*&]*\)@?)\b[a-f\d]{8,}\b\)', r'(\1_POINTER_)'),
+ # For xml output there is no '<', '>' or '&', so we need an alternate version for that:
+ # ((QVector&lt;int&gt;&amp;)@5608b455e640)
+ (r'\((\((?:const )?\w+(?:&lt;(?:[^&]|&(?!gt;))*&gt;)?(?:\*|&amp;)?\)@?)[a-z\d]+\b\)', r'(\1_POINTER_)'),
+ # QEventDispatcher{Glib,Win32,etc.}
+ (r'\bQEventDispatcher\w+\b', r'QEventDispatcherPlatform'),
),
precook = re.compile):
"""Private implementation details of __init__()."""
@@ -221,8 +232,71 @@ class Scanner (object):
print('tst_selftests.cpp names', d, "as a test, but it doesn't exist")
del re
+# Keep in sync with tst_selftests.cpp's processEnvironment():
+def baseEnv(platname=None,
+ keep=('PATH', 'QT_QPA_PLATFORM'),
+ posix=('HOME', 'USER', 'QEMU_SET_ENV', 'QEMU_LD_PREFIX'),
+ nonapple=('DISPLAY', 'XAUTHLOCALHOSTNAME'), # and XDG_*
+ # Don't actually know how to test for QNX, so this is ignored:
+ qnx=('GRAPHICS_ROOT', 'TZ'),
+ # Probably not actually relevant
+ preserveLib=('QT_PLUGIN_PATH', 'LD_LIBRARY_PATH'),
+ # Shall be modified on first call (a *copy* is returned):
+ cached={}):
+ """Lazily-evaluated standard environment for sub-tests to run in.
+
+ This prunes the parent process environment, selecting a only those
+ variables we chose to keep. The platname passed to the first call
+ helps select which variables to keep. The environment computed
+ then is cached: a copy of this is returned on that call and each
+ subsequent call.\n"""
+
+ if not cached:
+ xdg = False
+ # The platform module may be more apt for the platform tests here.
+ if os.name == 'posix':
+ keep += posix
+ if platname != 'darwin':
+ keep += nonapple
+ xdg = True
+ if 'QT_PRESERVE_TESTLIB_PATH' in os.environ:
+ keep += preserveLib
+
+ cached = dict(
+ LC_ALL = 'C', # Use standard locale
+ # Avoid interference from any qtlogging.ini files, e.g. in
+ # /etc/xdg/QtProject/, (must match tst_selftests.cpp's
+ # processEnvironment()'s value):
+ QT_LOGGING_RULES = '*.debug=true;qt.*=false')
+
+ for k, v in os.environ.items():
+ if k in keep or (xdg and k.startswith('XDG_')):
+ cached[k] = v
+
+ return cached.copy()
+
+def testEnv(testname,
+ # Make sure this matches tst_Selftests::doRunSubTest():
+ extraEnv = {
+ "crashers": { "QTEST_DISABLE_CORE_DUMP": "1",
+ "QTEST_DISABLE_STACK_DUMP": "1" },
+ "watchdog": { "QTEST_FUNCTION_TIMEOUT": "100" },
+ },
+ # Must match tst_Selftests::runSubTest_data():
+ crashers = ("assert", "blacklisted", "crashes", "crashedterminate",
+ "exceptionthrow", "faildatatype", "failfetchtype",
+ "fetchbogus", "silent", "watchdog")):
+ """Determine the environment in which to run a test."""
+ data = baseEnv()
+ if testname in crashers:
+ data.update(extraEnv["crashers"])
+ if testname in extraEnv:
+ data.update(extraEnv[testname])
+ return data
+
def generateTestData(testname, clean,
formats = ('xml', 'txt', 'xunitxml', 'lightxml', 'teamcity', 'tap'),
+ # Make sure this matches tst_Selftests::runSubTest_data():
extraArgs = {
"commandlinedata": "fiveTablePasses fiveTablePasses:fiveTablePasses_data1 -v2",
"benchlibcallgrind": "-callgrind",
@@ -233,6 +307,7 @@ def generateTestData(testname, clean,
"benchlibcounting": "-eventcounter",
"printdatatags": "-datatags",
"printdatatagswithglobaltags": "-datatags",
+ "signaldumper": "-vs",
"silent": "-silent",
"verbose1": "-v1",
"verbose2": "-v2",
@@ -249,26 +324,22 @@ def generateTestData(testname, clean,
print("Warning: directory", testname, "contains no test executable")
return
+ # Prepare environment in which to run tests:
+ env = testEnv(testname)
+
print(" running", testname)
for format in formats:
cmd = [path, '-' + format]
if testname in extraArgs:
cmd += extraArgs[testname].split()
- data = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ data = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env,
universal_newlines=True).communicate()[0]
with open('expected_' + testname + '.' + format, 'w') as out:
out.write('\n'.join(clean(data))) # write() appends a newline, too
def main(name, *args):
"""Minimal argument parsing and driver for the real work"""
- os.environ.update(
- LC_ALL = 'C', # Use standard locale
- # Avoid interference from any qtlogging.ini files, e.g. in
- # /etc/xdg/QtProject/, (must match tst_selftests.cpp's
- # processEnvironment()'s value):
- QT_LOGGING_RULES = '*.debug=true;qt.*=false')
-
herePath = os.getcwd()
cleaner = Cleaner(herePath, name)
@@ -280,6 +351,7 @@ def main(name, *args):
if __name__ == '__main__':
# Executed when script is run, not when imported (e.g. to debug)
import sys
+ baseEnv(sys.platform) # initializes its cache
if sys.platform.startswith('win'):
print("This script does not work on Windows.")
diff --git a/tests/auto/testlib/selftests/globaldata/globaldata.pro b/tests/auto/testlib/selftests/globaldata/globaldata.pro
index c0b1554c0f..621416c5b8 100644
--- a/tests/auto/testlib/selftests/globaldata/globaldata.pro
+++ b/tests/auto/testlib/selftests/globaldata/globaldata.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = globaldata
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp b/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp
index 6c0ae1f43c..3c5c2c8f37 100644
--- a/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp
+++ b/tests/auto/testlib/selftests/globaldata/tst_globaldata.cpp
@@ -66,9 +66,10 @@ void tst_globaldata::initTestCase()
void tst_globaldata::initTestCase_data()
{
- QTest::addColumn<bool>("booli");
- QTest::newRow("1") << false;
- QTest::newRow("2") << true;
+ // QFETCH_GLOBAL shall iterate these, for every test:
+ QTest::addColumn<bool>("global");
+ QTest::newRow("global=false") << false;
+ QTest::newRow("global=true") << true;
}
void tst_globaldata::cleanupTestCase()
@@ -94,41 +95,42 @@ void tst_globaldata::cleanup()
void tst_globaldata::testGlobal_data()
{
- QTest::addColumn<bool>("booll");
- QTest::newRow("local 1") << false;
- QTest::newRow("local 2") << true;
+ QTest::addColumn<bool>("local");
+ QTest::newRow("local=false") << false;
+ QTest::newRow("local=true") << true;
}
void tst_globaldata::testGlobal()
{
- QFETCH_GLOBAL(bool, booli);
- qDebug() << "global:" << booli;
- QFETCH(bool, booll);
- qDebug() << "local:" << booll;
+ QFETCH_GLOBAL(bool, global);
+ qDebug() << "global:" << global;
+ QFETCH(bool, local);
+ qDebug() << "local:" << local;
}
void tst_globaldata::skip_data()
{
- QTest::addColumn<bool>("booll");
- QTest::newRow("local 1") << false;
- QTest::newRow("local 2") << true;
-
+ testGlobal_data();
QSKIP("skipping");
}
void tst_globaldata::skip()
{
- qDebug() << "this line should never be reached";
+ // A skip in _data() causes the whole test to be skipped, for all global rows.
+ QVERIFY(!"This line should never be reached.");
}
void tst_globaldata::skipSingle()
{
- QFETCH_GLOBAL(bool, booli);
- QFETCH(bool, booll);
-
- if (booli && !booll)
- QSKIP("skipping");
- qDebug() << "global:" << booli << "local:" << booll;
+ QFETCH_GLOBAL(bool, global);
+ QFETCH(bool, local);
+
+ // A skip in the last run of one global row used to suppress the test in the
+ // next global row (where a skip in an earlier run of the first row did not).
+ if (global ^ local)
+ QSKIP("Skipping");
+ qDebug() << "global:" << global << "local:" << local;
+ QCOMPARE(global, local);
}
void tst_globaldata::skipLocal()
diff --git a/tests/auto/testlib/selftests/keyboard/keyboard.pro b/tests/auto/testlib/selftests/keyboard/keyboard.pro
index 0097318797..488c992e62 100644
--- a/tests/auto/testlib/selftests/keyboard/keyboard.pro
+++ b/tests/auto/testlib/selftests/keyboard/keyboard.pro
@@ -5,3 +5,5 @@ macos:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = keyboard
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/longstring/longstring.pro b/tests/auto/testlib/selftests/longstring/longstring.pro
index d16ba85095..d8961203f3 100644
--- a/tests/auto/testlib/selftests/longstring/longstring.pro
+++ b/tests/auto/testlib/selftests/longstring/longstring.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = longstring
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/maxwarnings/maxwarnings.pro b/tests/auto/testlib/selftests/maxwarnings/maxwarnings.pro
index 79451af1ec..bdca0225d3 100644
--- a/tests/auto/testlib/selftests/maxwarnings/maxwarnings.pro
+++ b/tests/auto/testlib/selftests/maxwarnings/maxwarnings.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = maxwarnings
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/mouse/mouse.pro b/tests/auto/testlib/selftests/mouse/mouse.pro
index 7c06b8aa64..e5701eee0f 100644
--- a/tests/auto/testlib/selftests/mouse/mouse.pro
+++ b/tests/auto/testlib/selftests/mouse/mouse.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = mouse
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/multiexec/multiexec.pro b/tests/auto/testlib/selftests/multiexec/multiexec.pro
index 2038acbd31..e9b2b7b587 100644
--- a/tests/auto/testlib/selftests/multiexec/multiexec.pro
+++ b/tests/auto/testlib/selftests/multiexec/multiexec.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = multiexec
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/pairdiagnostics/pairdiagnostics.pro b/tests/auto/testlib/selftests/pairdiagnostics/pairdiagnostics.pro
index 1c07c93e9d..25f5bfe809 100644
--- a/tests/auto/testlib/selftests/pairdiagnostics/pairdiagnostics.pro
+++ b/tests/auto/testlib/selftests/pairdiagnostics/pairdiagnostics.pro
@@ -4,3 +4,5 @@ QT = core testlib
CONFIG -= app_bundle debug_and_release_target
TARGET = pairdiagnostics
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/printdatatags/printdatatags.pro b/tests/auto/testlib/selftests/printdatatags/printdatatags.pro
index cd06384835..83f171aac5 100644
--- a/tests/auto/testlib/selftests/printdatatags/printdatatags.pro
+++ b/tests/auto/testlib/selftests/printdatatags/printdatatags.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = printdatatags
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/printdatatagswithglobaltags/printdatatagswithglobaltags.pro b/tests/auto/testlib/selftests/printdatatagswithglobaltags/printdatatagswithglobaltags.pro
index f1cf25d104..00ca4a0e62 100644
--- a/tests/auto/testlib/selftests/printdatatagswithglobaltags/printdatatagswithglobaltags.pro
+++ b/tests/auto/testlib/selftests/printdatatagswithglobaltags/printdatatagswithglobaltags.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = printdatatagswithglobaltags
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/qexecstringlist/qexecstringlist.pro b/tests/auto/testlib/selftests/qexecstringlist/qexecstringlist.pro
index bd967f32e6..4d7af8ab40 100644
--- a/tests/auto/testlib/selftests/qexecstringlist/qexecstringlist.pro
+++ b/tests/auto/testlib/selftests/qexecstringlist/qexecstringlist.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = qexecstringlist
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/selftests.pri b/tests/auto/testlib/selftests/selftests.pri
index 05ed6d9905..2cad0b7e17 100644
--- a/tests/auto/testlib/selftests/selftests.pri
+++ b/tests/auto/testlib/selftests/selftests.pri
@@ -1,5 +1,4 @@
SUBPROGRAMS = \
- #alive \
assert \
badxml \
benchlibcallgrind \
@@ -21,6 +20,8 @@ SUBPROGRAMS = \
exceptionthrow \
expectfail \
failcleanup \
+ faildatatype \
+ failfetchtype \
failinit \
failinitdata \
fetchbogus \
@@ -35,6 +36,7 @@ SUBPROGRAMS = \
printdatatagswithglobaltags \
qexecstringlist \
silent \
+ signaldumper \
singleskip \
skip \
skipcleanup \
@@ -43,11 +45,13 @@ SUBPROGRAMS = \
sleep \
strcmp \
subtest \
+ testlib \
tuplediagnostics \
verbose1 \
verbose2 \
verifyexceptionthrown \
warnings \
+ watchdog \
xunit
qtHaveModule(gui): SUBPROGRAMS += \
diff --git a/tests/auto/testlib/selftests/signaldumper/signaldumper.pro b/tests/auto/testlib/selftests/signaldumper/signaldumper.pro
new file mode 100644
index 0000000000..8780b18419
--- /dev/null
+++ b/tests/auto/testlib/selftests/signaldumper/signaldumper.pro
@@ -0,0 +1,9 @@
+SOURCES += tst_signaldumper.cpp
+QT = core testlib-private
+
+macos:CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = signaldumper
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp b/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp
new file mode 100644
index 0000000000..f6cd0d510e
--- /dev/null
+++ b/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp
@@ -0,0 +1,417 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QCoreApplication>
+#include <QtTest/QtTest>
+#include <private/qtestlog_p.h>
+
+class tst_Signaldumper : public QObject
+{
+ Q_OBJECT
+
+ void addConnectionTypeData();
+
+private slots:
+ void noConnections();
+ void oneSlot_data();
+ void oneSlot();
+ void oneSlotOldSyntax_data();
+ void oneSlotOldSyntax();
+ void twoSlots_data();
+ void twoSlots();
+ void twoSlotsOldSyntax_data();
+ void twoSlotsOldSyntax();
+ void signalForwarding_data();
+ void signalForwarding();
+ void signalForwardingOldSyntax_data();
+ void signalForwardingOldSyntax();
+ void slotEmittingSignal_data();
+ void slotEmittingSignal();
+ void slotEmittingSignalOldSyntax_data();
+ void slotEmittingSignalOldSyntax();
+
+ void variousTypes();
+};
+
+void tst_Signaldumper::addConnectionTypeData()
+{
+ QTest::addColumn<Qt::ConnectionType>("connectionType");
+ QTest::newRow("direct") << Qt::ConnectionType::DirectConnection;
+ QTest::newRow("queued") << Qt::ConnectionType::QueuedConnection;
+}
+
+/*
+ Simple class to keep the slots and signals separate from the test
+*/
+class SignalSlotClass : public QObject
+{
+ Q_OBJECT
+
+public:
+ SignalSlotClass();
+
+public slots:
+ void slotWithoutParameters() {}
+ void slotWithParameters(int i, char c) { Q_UNUSED(i); Q_UNUSED(c); }
+ void emitSecondSignal() { emit nestedSignal(); }
+
+signals:
+ void signalWithoutParameters();
+ void signalWithParameters(int i, char c);
+
+ void nestedSignal();
+ void nestedSignalWithParameters(int i, char c);
+
+ // For the "variousTypes" test
+ void qStringSignal(QString string);
+ void qStringRefSignal(QString &string);
+ void qStringConstRefSignal(const QString &string);
+ void qByteArraySignal(QByteArray byteArray);
+ void qListSignal(QList<int> list);
+ void qVectorSignal(QVector<int> vector);
+ void qVectorRefSignal(QVector<int> &vector);
+ void qVectorConstRefSignal(const QVector<int> &vector);
+ void qVectorConstPointerSignal(const QVector<int> *vector);
+ void qVectorPointerConstSignal(QVector<int> *const vector);
+ void qVariantSignal(QVariant variant);
+};
+
+SignalSlotClass::SignalSlotClass()
+{
+ // For printing signal argument in "variousTypes" test
+ qRegisterMetaType<QVector<int>>();
+ qRegisterMetaType<QList<int>>();
+}
+
+void tst_Signaldumper::noConnections()
+{
+ SignalSlotClass signalSlotOwner;
+
+ emit signalSlotOwner.signalWithoutParameters();
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+}
+
+void tst_Signaldumper::oneSlot_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::oneSlot()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+ // parameterless to parameterless
+ auto connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithoutParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameters to parameters
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithParameters, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameters to no parameters
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::oneSlotOldSyntax_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::oneSlotOldSyntax()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+ // parameterless to parameterless
+ auto connection = connect(&signalSlotOwner, SIGNAL(signalWithoutParameters()),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameters to parameters
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithParameters(int, char)), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameters to no parameters
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::twoSlots_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::twoSlots()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ // Now, instead of creating two slots or two objects, we will just do the same connection twice.
+ // The same slot will then be invoked twice.
+
+ SignalSlotClass signalSlotOwner;
+ // parameterless to parameterless
+ auto connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithoutParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ auto connection2 = connect(&signalSlotOwner, &SignalSlotClass::signalWithoutParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+
+ // parameters to parameters
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithParameters, connectionType);
+ connection2 = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithParameters, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+
+ // parameters to no parameters
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ connection2 = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::slotWithoutParameters, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+}
+
+void tst_Signaldumper::twoSlotsOldSyntax_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::twoSlotsOldSyntax()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ // Now, instead of creating two slots or two objects, we will just do the same connection twice.
+ // The same slot will then be invoked twice.
+
+ SignalSlotClass signalSlotOwner;
+ // parameterless to parameterless
+ auto connection = connect(&signalSlotOwner, SIGNAL(signalWithoutParameters()),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ auto connection2 = connect(&signalSlotOwner, SIGNAL(signalWithoutParameters()),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+
+ // parameters to parameters
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithParameters(int, char)), connectionType);
+ connection2 = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithParameters(int, char)), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+
+ // parameters to no parameters
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ connection2 = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+ disconnect(connection2);
+}
+
+void tst_Signaldumper::signalForwarding_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::signalForwarding()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+
+ // parameterless signal to parameterless signal
+ auto connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithoutParameters,
+ &signalSlotOwner, &SignalSlotClass::nestedSignal, connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameter(full) signal to parameter(full) signal
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::nestedSignalWithParameters, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameter(full) signal to parameterless signal
+ connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithParameters,
+ &signalSlotOwner, &SignalSlotClass::nestedSignal, connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::signalForwardingOldSyntax_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::signalForwardingOldSyntax()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+
+ // parameterless signal to parameterless signal
+ auto connection = connect(&signalSlotOwner, SIGNAL(signalWithoutParameters()),
+ &signalSlotOwner, SIGNAL(nestedSignal()), connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameter(full) signal to parameter(full) signal
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SIGNAL(nestedSignalWithParameters(int, char)), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+
+ // parameter(full) signal to parameterless signal
+ connection = connect(&signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
+ &signalSlotOwner, SIGNAL(nestedSignal()), connectionType);
+ emit signalSlotOwner.signalWithParameters(242, 'm');
+
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::slotEmittingSignal_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::slotEmittingSignal()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+
+ auto connection = connect(&signalSlotOwner, &SignalSlotClass::signalWithoutParameters,
+ &signalSlotOwner, &SignalSlotClass::emitSecondSignal, connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::slotEmittingSignalOldSyntax_data()
+{
+ addConnectionTypeData();
+}
+
+void tst_Signaldumper::slotEmittingSignalOldSyntax()
+{
+ QFETCH(Qt::ConnectionType, connectionType);
+
+ SignalSlotClass signalSlotOwner;
+
+ auto connection = connect(&signalSlotOwner, SIGNAL(signalWithoutParameters()),
+ &signalSlotOwner, SLOT(emitSecondSignal()), connectionType);
+ emit signalSlotOwner.signalWithoutParameters();
+ QCoreApplication::processEvents();
+ disconnect(connection);
+}
+
+void tst_Signaldumper::variousTypes()
+{
+ SignalSlotClass signalSlotOwner;
+ QString string = QString::fromLatin1("Test string");
+ emit signalSlotOwner.qStringSignal(string);
+ emit signalSlotOwner.qStringRefSignal(string);
+ emit signalSlotOwner.qStringConstRefSignal(string);
+ emit signalSlotOwner.qByteArraySignal(QByteArray("Test bytearray"));
+
+ QList<int> list{1, 2, 3, 242};
+ emit signalSlotOwner.qListSignal(list);
+
+ QVector<int> vector{1, 2, 3, 242};
+ emit signalSlotOwner.qVectorSignal(vector);
+ emit signalSlotOwner.qVectorRefSignal(vector);
+ emit signalSlotOwner.qVectorConstRefSignal(vector);
+ emit signalSlotOwner.qVectorConstPointerSignal(&vector);
+ emit signalSlotOwner.qVectorPointerConstSignal(&vector);
+
+ QVariant variant = 24;
+ emit signalSlotOwner.qVariantSignal(variant);
+ variant = QVariant(string);
+ emit signalSlotOwner.qVariantSignal(variant);
+}
+
+QTEST_MAIN(tst_Signaldumper)
+#include "tst_signaldumper.moc"
diff --git a/tests/auto/testlib/selftests/silent/silent.pro b/tests/auto/testlib/selftests/silent/silent.pro
index 3150f65a5e..3f6325a010 100644
--- a/tests/auto/testlib/selftests/silent/silent.pro
+++ b/tests/auto/testlib/selftests/silent/silent.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = silent
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/silent/tst_silent.cpp b/tests/auto/testlib/selftests/silent/tst_silent.cpp
index 97fbbfd30a..cf3c35dec4 100644
--- a/tests/auto/testlib/selftests/silent/tst_silent.cpp
+++ b/tests/auto/testlib/selftests/silent/tst_silent.cpp
@@ -72,6 +72,17 @@ void tst_Silent::xpass()
QVERIFY2(true, "This test should XPASS");
}
+#ifndef Q_OS_WIN
+#include <signal.h>
+#include <setjmp.h>
+
+static jmp_buf state;
+static void abort_handler(int signal)
+{
+ longjmp(state, 1);
+}
+#endif
+
void tst_Silent::messages()
{
qWarning("This is a warning that should not appear in silent test output");
@@ -80,7 +91,15 @@ void tst_Silent::messages()
qCritical("This is a critical message that should not appear in silent test output");
qInfo("This is an info message that should not appear in silent test output");
QTestLog::info("This is an internal testlib info message that should not appear in silent test output", __FILE__, __LINE__);
- qFatal("This is a fatal error message that should still appear in silent test output");
+
+#ifndef Q_OS_WIN
+ // We're testing qFatal, but we don't want to actually std::abort() !
+ auto prior = signal(SIGABRT, abort_handler);
+ if (setjmp(state))
+ signal(SIGABRT, prior);
+ else
+#endif
+ qFatal("This is a fatal error message that should still appear in silent test output");
}
QTEST_MAIN(tst_Silent)
diff --git a/tests/auto/testlib/selftests/singleskip/singleskip.pro b/tests/auto/testlib/selftests/singleskip/singleskip.pro
index 9f63e62747..a32c22c943 100644
--- a/tests/auto/testlib/selftests/singleskip/singleskip.pro
+++ b/tests/auto/testlib/selftests/singleskip/singleskip.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = singleskip
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/skip/skip.pro b/tests/auto/testlib/selftests/skip/skip.pro
index 8780d295cf..19a01908af 100644
--- a/tests/auto/testlib/selftests/skip/skip.pro
+++ b/tests/auto/testlib/selftests/skip/skip.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = skip
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/skipcleanup/skipcleanup.pro b/tests/auto/testlib/selftests/skipcleanup/skipcleanup.pro
index f98cda7596..059132b5a6 100644
--- a/tests/auto/testlib/selftests/skipcleanup/skipcleanup.pro
+++ b/tests/auto/testlib/selftests/skipcleanup/skipcleanup.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = skipcleanup
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/skipinit/skipinit.pro b/tests/auto/testlib/selftests/skipinit/skipinit.pro
index 7defce9a52..6605226993 100644
--- a/tests/auto/testlib/selftests/skipinit/skipinit.pro
+++ b/tests/auto/testlib/selftests/skipinit/skipinit.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = skipinit
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/skipinitdata/skipinitdata.pro b/tests/auto/testlib/selftests/skipinitdata/skipinitdata.pro
index cd806c2a43..176955500b 100644
--- a/tests/auto/testlib/selftests/skipinitdata/skipinitdata.pro
+++ b/tests/auto/testlib/selftests/skipinitdata/skipinitdata.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = skipinitdata
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/sleep/sleep.pro b/tests/auto/testlib/selftests/sleep/sleep.pro
index affcba22ee..b109bf6253 100644
--- a/tests/auto/testlib/selftests/sleep/sleep.pro
+++ b/tests/auto/testlib/selftests/sleep/sleep.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = sleep
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/sleep/tst_sleep.cpp b/tests/auto/testlib/selftests/sleep/tst_sleep.cpp
index b7b141afd0..95cb68521d 100644
--- a/tests/auto/testlib/selftests/sleep/tst_sleep.cpp
+++ b/tests/auto/testlib/selftests/sleep/tst_sleep.cpp
@@ -28,6 +28,7 @@
#include <QtCore/QCoreApplication>
+#include <QtCore/QElapsedTimer>
#include <QtTest/QtTest>
class tst_Sleep: public QObject
@@ -41,7 +42,7 @@ private slots:
void tst_Sleep::sleep()
{
- QTime t;
+ QElapsedTimer t;
t.start();
QTest::qSleep(100);
diff --git a/tests/auto/testlib/selftests/strcmp/strcmp.pro b/tests/auto/testlib/selftests/strcmp/strcmp.pro
index f5f6eecc88..35a4c5e858 100644
--- a/tests/auto/testlib/selftests/strcmp/strcmp.pro
+++ b/tests/auto/testlib/selftests/strcmp/strcmp.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = strcmp
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/subtest/subtest.pro b/tests/auto/testlib/selftests/subtest/subtest.pro
index 09dee1b1b9..b5c294aed6 100644
--- a/tests/auto/testlib/selftests/subtest/subtest.pro
+++ b/tests/auto/testlib/selftests/subtest/subtest.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = subtest
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/test/test.pro b/tests/auto/testlib/selftests/test/test.pro
index ec1633ebff..fce8e48ca2 100644
--- a/tests/auto/testlib/selftests/test/test.pro
+++ b/tests/auto/testlib/selftests/test/test.pro
@@ -19,3 +19,4 @@ RESOURCES += expected_files
include(../selftests.pri)
!android:!winrt: for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}"
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/testlib/testlib.pro b/tests/auto/testlib/selftests/testlib/testlib.pro
new file mode 100644
index 0000000000..8798f86b18
--- /dev/null
+++ b/tests/auto/testlib/selftests/testlib/testlib.pro
@@ -0,0 +1,9 @@
+SOURCES += tst_testlib.cpp
+QT = core testlib
+
+darwin: CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = testlib
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/testlib/tst_testlib.cpp b/tests/auto/testlib/selftests/testlib/tst_testlib.cpp
new file mode 100644
index 0000000000..38a71be732
--- /dev/null
+++ b/tests/auto/testlib/selftests/testlib/tst_testlib.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/QtMath>
+#include <QtCore/QtNumeric>
+
+/* Test QTest functions not covered by other parts of the selftest. Tests that
+ * involve crashing or exiting should be added as separate tests in their own
+ * right. Tests that form a coherent group on a related theme should also go in
+ * their own directory. Tests that fail in order to exercise QTest internals
+ * are fine.
+ */
+
+class tst_TestLib : public QObject
+{
+Q_OBJECT
+private slots:
+ void basics() const;
+ void delays() const;
+ void reals_data() const;
+ void reals() const;
+};
+
+void tst_TestLib::basics() const
+{
+ QVERIFY(QByteArray(QTest::currentAppName()).contains("testlib"));
+
+ QCOMPARE(QTest::testObject(), nullptr); // last, because it should fail
+}
+
+QT_BEGIN_NAMESPACE
+
+namespace QTest {
+ // Defined; not declared in the public header, but used by qtdeclarative.
+ int defaultKeyDelay();
+ int defaultMouseDelay();
+}
+
+QT_END_NAMESPACE
+
+void tst_TestLib::delays() const
+{
+ QVERIFY(QTest::defaultMouseDelay() >= 0);
+ QVERIFY(QTest::defaultKeyDelay() >= 0);
+}
+
+void tst_TestLib::reals_data() const
+{
+ QTest::addColumn<double>("actual");
+ QTest::addColumn<double>("expected");
+
+ QTest::newRow("zero") << 0.0 << 0.0;
+#define ADDROW(func) QTest::addRow("self-%s", #func) << func() << func()
+ ADDROW(qQNaN);
+ ADDROW(qInf);
+#undef ADDROW // Just used so as to exercise addRow()
+ QTest::newRow("infineg") << -qInf() << -qInf();
+ QTest::newRow("Sin(turn/4)") << qSin(9 * M_PI_2) << 1.0;
+ QTest::newRow("Cos(turn/2)") << qCos(15 * M_PI) << -1.0;
+}
+
+void tst_TestLib::reals() const
+{
+ QFETCH(double, actual);
+ QFETCH(double, expected);
+ QCOMPARE(actual, expected);
+}
+
+QTEST_APPLESS_MAIN(tst_TestLib)
+
+#include "tst_testlib.moc"
diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp
index 8baca5bdad..1326b96177 100644
--- a/tests/auto/testlib/selftests/tst_selftests.cpp
+++ b/tests/auto/testlib/selftests/tst_selftests.cpp
@@ -439,7 +439,6 @@ void tst_Selftests::runSubTest_data()
QTest::addColumn<bool>("crashes");
QStringList tests = QStringList()
-// << "alive" // timer dependent
#if !defined(Q_OS_WIN)
// On windows, assert does nothing in release mode and blocks execution
// with a popup window in debug mode.
@@ -468,10 +467,13 @@ void tst_Selftests::runSubTest_data()
#endif
<< "expectfail"
<< "failcleanup"
+#ifndef Q_OS_WIN // these assert, by design; so same problem as "assert"
+ << "faildatatype"
+ << "failfetchtype"
+#endif
<< "failinit"
<< "failinitdata"
-#if !defined(Q_OS_WIN)
- // Disable this test on Windows, as the run-time will popup dialogs with warnings
+#ifndef Q_OS_WIN // asserts, by design; so same problem as "assert"
<< "fetchbogus"
#endif
<< "findtestdata"
@@ -485,6 +487,7 @@ void tst_Selftests::runSubTest_data()
<< "printdatatags"
<< "printdatatagswithglobaltags"
<< "qexecstringlist"
+ << "signaldumper"
<< "silent"
<< "singleskip"
<< "skip"
@@ -494,6 +497,7 @@ void tst_Selftests::runSubTest_data()
<< "sleep"
<< "strcmp"
<< "subtest"
+ << "testlib"
<< "tuplediagnostics"
<< "verbose1"
<< "verbose2"
@@ -502,6 +506,7 @@ void tst_Selftests::runSubTest_data()
<< "verifyexceptionthrown"
#endif //!QT_NO_EXCEPTIONS
<< "warnings"
+ << "watchdog"
<< "xunit"
;
@@ -520,6 +525,7 @@ void tst_Selftests::runSubTest_data()
foreach (QString const& subtest, tests) {
QStringList arguments = loggerSet.arguments;
+ // Keep in sync with generateTestData()'s extraArgs in generate_expected_output.py:
if (subtest == "commandlinedata") {
arguments << QString("fiveTablePasses fiveTablePasses:fiveTablePasses_data1 -v2").split(' ');
}
@@ -547,6 +553,9 @@ void tst_Selftests::runSubTest_data()
else if (subtest == "printdatatagswithglobaltags") {
arguments << "-datatags";
}
+ else if (subtest == "signaldumper") {
+ arguments << "-vs";
+ }
else if (subtest == "silent") {
arguments << "-silent";
}
@@ -612,10 +621,12 @@ void tst_Selftests::runSubTest_data()
if (loggerSet.name.contains("teamcity") && subtest.startsWith("benchlib"))
continue; // Skip benchmark for TeamCity logger
+ // Keep in sync with generateTestData()'s crashers in generate_expected_output.py:
const bool crashes = subtest == QLatin1String("assert") || subtest == QLatin1String("exceptionthrow")
|| subtest == QLatin1String("fetchbogus") || subtest == QLatin1String("crashedterminate")
+ || subtest == QLatin1String("faildatatype") || subtest == QLatin1String("failfetchtype")
|| subtest == QLatin1String("crashes") || subtest == QLatin1String("silent")
- || subtest == QLatin1String("blacklisted");
+ || subtest == QLatin1String("blacklisted") || subtest == QLatin1String("watchdog");
QTest::newRow(qPrintable(QString("%1 %2").arg(subtest).arg(loggerSet.name)))
<< subtest
<< loggers
@@ -690,9 +701,12 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge
QProcess proc;
QProcessEnvironment environment = processEnvironment();
+ // Keep in sync with generateTestData()'s extraEnv in generate_expected_output.py:
if (crashes) {
environment.insert("QTEST_DISABLE_CORE_DUMP", "1");
environment.insert("QTEST_DISABLE_STACK_DUMP", "1");
+ if (subdir == QLatin1String("watchdog"))
+ environment.insert("QTEST_FUNCTION_TIMEOUT", "100");
}
proc.setProcessEnvironment(environment);
const QString path = subdir + QLatin1Char('/') + subdir;
@@ -735,6 +749,7 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge
if (subdir != QLatin1String("exceptionthrow")
&& subdir != QLatin1String("cmptest") // QImage comparison requires QGuiApplication
&& subdir != QLatin1String("fetchbogus")
+ && subdir != QLatin1String("watchdog")
&& subdir != QLatin1String("xunit")
#ifdef Q_CC_MINGW
&& subdir != QLatin1String("blacklisted") // calls qFatal()
@@ -742,11 +757,13 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge
#endif
#ifdef Q_OS_LINUX
// QEMU outputs to stderr about uncaught signals
- && (!EmulationDetector::isRunningArmOnX86() ||
- (subdir != QLatin1String("blacklisted")
- && subdir != QLatin1String("silent")
- && subdir != QLatin1String("assert")
- && subdir != QLatin1String("crashes")
+ && !(EmulationDetector::isRunningArmOnX86() &&
+ (subdir == QLatin1String("assert")
+ || subdir == QLatin1String("blacklisted")
+ || subdir == QLatin1String("crashes")
+ || subdir == QLatin1String("faildatatype")
+ || subdir == QLatin1String("failfetchtype")
+ || subdir == QLatin1String("silent")
)
)
#endif
@@ -887,16 +904,20 @@ bool tst_Selftests::compareLine(const QString &logger, const QString &subdir,
const QString &actualLine, const QString &expectedLine,
QString *errorMessage) const
{
- if (subdir == QLatin1String("assert") && actualLine.contains(QLatin1String("ASSERT: "))
- && expectedLine.contains(QLatin1String("ASSERT: ")) && actualLine != expectedLine) {
+ if (actualLine == expectedLine)
+ return true;
+
+ if ((subdir == QLatin1String("assert")
+ || subdir == QLatin1String("faildatatype") || subdir == QLatin1String("failfetchtype"))
+ && actualLine.contains(QLatin1String("ASSERT: "))
+ && expectedLine.contains(QLatin1String("ASSERT: "))) {
// Q_ASSERT uses __FILE__, the exact contents of which are
// undefined. If have we something that looks like a Q_ASSERT and we
// were expecting to see a Q_ASSERT, we'll skip the line.
return true;
}
- if (expectedLine.startsWith(QLatin1String("FAIL! : tst_Exception::throwException() Caught unhandled exce"))
- && actualLine != expectedLine) {
+ if (expectedLine.startsWith(QLatin1String("FAIL! : tst_Exception::throwException() Caught unhandled exce"))) {
// On some platforms we compile without RTTI, and as a result we never throw an exception
if (actualLine.simplified() != QLatin1String("tst_Exception::throwException()")) {
*errorMessage = QString::fromLatin1("'%1' != 'tst_Exception::throwException()'").arg(actualLine);
@@ -935,8 +956,28 @@ bool tst_Selftests::compareLine(const QString &logger, const QString &subdir,
if (actualLine.startsWith(QLatin1String("Totals:")) && expectedLine.startsWith(QLatin1String("Totals:")))
return true;
- if (actualLine == expectedLine)
+ const QLatin1String pointerPlaceholder("_POINTER_");
+ if (expectedLine.contains(pointerPlaceholder)
+ && (expectedLine.contains(QLatin1String("Signal: "))
+ || expectedLine.contains(QLatin1String("Slot: ")))) {
+ QString actual = actualLine;
+ // We don't care about the pointer of the object to whom the signal belongs, so we
+ // replace it with _POINTER_, e.g.:
+ // Signal: SignalSlotClass(7ffd72245410) signalWithoutParameters ()
+ // Signal: QThread(7ffd72245410) started ()
+ // After this instance pointer we may have further pointers and
+ // references (with an @ prefix) as parameters of the signal or
+ // slot being invoked.
+ // Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@55f5fbb8dd40)
+ actual.replace(QRegularExpression("\\b[a-f0-9]{8,}\\b"), pointerPlaceholder);
+ // Also change QEventDispatcher{Glib,Win32,etc.} to QEventDispatcherPlatform
+ actual.replace(QRegularExpression("\\b(QEventDispatcher)\\w+\\b"), QLatin1String("\\1Platform"));
+ if (actual != expectedLine) {
+ *errorMessage = msgMismatch(actual, expectedLine);
+ return false;
+ }
return true;
+ }
*errorMessage = msgMismatch(actualLine, expectedLine);
return false;
diff --git a/tests/auto/testlib/selftests/tuplediagnostics/tuplediagnostics.pro b/tests/auto/testlib/selftests/tuplediagnostics/tuplediagnostics.pro
index 7a29e0e5e1..f338170b81 100644
--- a/tests/auto/testlib/selftests/tuplediagnostics/tuplediagnostics.pro
+++ b/tests/auto/testlib/selftests/tuplediagnostics/tuplediagnostics.pro
@@ -4,3 +4,5 @@ QT = core testlib
CONFIG -= app_bundle debug_and_release_target
TARGET = tuplediagnostics
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/verbose1/verbose1.pro b/tests/auto/testlib/selftests/verbose1/verbose1.pro
index f00ae69d17..1f16d70d66 100644
--- a/tests/auto/testlib/selftests/verbose1/verbose1.pro
+++ b/tests/auto/testlib/selftests/verbose1/verbose1.pro
@@ -8,3 +8,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = verbose1
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/verbose2/verbose2.pro b/tests/auto/testlib/selftests/verbose2/verbose2.pro
index 796cdeb975..bf54904488 100644
--- a/tests/auto/testlib/selftests/verbose2/verbose2.pro
+++ b/tests/auto/testlib/selftests/verbose2/verbose2.pro
@@ -8,3 +8,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = verbose2
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/verifyexceptionthrown/verifyexceptionthrown.pro b/tests/auto/testlib/selftests/verifyexceptionthrown/verifyexceptionthrown.pro
index 51f108c9d7..198d35dc6c 100644
--- a/tests/auto/testlib/selftests/verifyexceptionthrown/verifyexceptionthrown.pro
+++ b/tests/auto/testlib/selftests/verifyexceptionthrown/verifyexceptionthrown.pro
@@ -6,3 +6,5 @@ CONFIG -= debug_and_release_target
CONFIG += exceptions
TARGET = verifyexceptionthrown
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/warnings/warnings.pro b/tests/auto/testlib/selftests/warnings/warnings.pro
index 0c6cddcefb..a0bd2c62ba 100644
--- a/tests/auto/testlib/selftests/warnings/warnings.pro
+++ b/tests/auto/testlib/selftests/warnings/warnings.pro
@@ -5,3 +5,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = warnings
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/watchdog/tst_watchdog.cpp b/tests/auto/testlib/selftests/watchdog/tst_watchdog.cpp
new file mode 100644
index 0000000000..2f29609f71
--- /dev/null
+++ b/tests/auto/testlib/selftests/watchdog/tst_watchdog.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+class tst_Watchdog : public QObject
+{
+ Q_OBJECT
+private slots:
+ void delay() const;
+};
+
+void tst_Watchdog::delay() const
+{
+ bool ok = false;
+ const int fiveMinutes = 5 * 60 * 1000;
+ // Use the same env.var as the watch-dog and add a little to it:
+ const int timeout = qEnvironmentVariableIntValue("QTEST_FUNCTION_TIMEOUT", &ok);
+ QTest::qSleep(5000 + (ok && timeout > 0 ? timeout : fiveMinutes));
+ // The watchdog timer should have interrupted us by now.
+ QFAIL("ERROR: this function should be interrupted.");
+}
+
+QTEST_APPLESS_MAIN(tst_Watchdog)
+
+#include "tst_watchdog.moc"
diff --git a/tests/auto/testlib/selftests/watchdog/watchdog.pro b/tests/auto/testlib/selftests/watchdog/watchdog.pro
new file mode 100644
index 0000000000..ddcc3f6ca2
--- /dev/null
+++ b/tests/auto/testlib/selftests/watchdog/watchdog.pro
@@ -0,0 +1,14 @@
+SOURCES += tst_watchdog.cpp
+QT = core testlib
+
+darwin: CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = watchdog
+
+# The test deliberately times out; so tell it to do so quickly
+checkenv.name = QTEST_FUNCTION_TIMEOUT
+checkenv.value = 100
+QT_TOOL_ENV += checkenv
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/selftests/xunit/xunit.pro b/tests/auto/testlib/selftests/xunit/xunit.pro
index b8c606e828..becb46ce8b 100644
--- a/tests/auto/testlib/selftests/xunit/xunit.pro
+++ b/tests/auto/testlib/selftests/xunit/xunit.pro
@@ -6,3 +6,5 @@ mac:CONFIG -= app_bundle
CONFIG -= debug_and_release_target
TARGET = xunit
+
+include($$QT_SOURCE_TREE/src/testlib/selfcover.pri)
diff --git a/tests/auto/testlib/testlib.pro b/tests/auto/testlib/testlib.pro
index 25ccc591d6..587c76a189 100644
--- a/tests/auto/testlib/testlib.pro
+++ b/tests/auto/testlib/testlib.pro
@@ -1,6 +1,7 @@
-TEMPLATE=subdirs
-SUBDIRS=\
+TEMPLATE = subdirs
+SUBDIRS = \
+ outformat \
qsignalspy \
selftests \
-qtHaveModule(widgets):SUBDIRS += qabstractitemmodeltester
+qtHaveModule(widgets): SUBDIRS += qabstractitemmodeltester
diff --git a/tests/auto/testserver.pri b/tests/auto/testserver.pri
deleted file mode 100644
index b2f593235f..0000000000
--- a/tests/auto/testserver.pri
+++ /dev/null
@@ -1,109 +0,0 @@
-# Integrating docker-based test servers into Qt Test framework
-#
-# This file adds support for docker-based test servers built by testcase
-# projects that need them. To enable this feature, any automated test can
-# include testserver.pri in its project file. This instructs qmake to insert
-# additional targets into the generated Makefile. The 'check' target then brings
-# up test servers before running the testcase, and shuts them down afterwards.
-#
-# TESTSERVER_COMPOSE_FILE
-# - Contains the path of docker-compose file
-# This configuration file defines the services used for autotests. It tells the
-# docker engine how to build up the docker images and containers. In qtbase, a
-# shared docker-compose file is located in the tests folder.
-# Example: TESTSERVER_COMPOSE_FILE = \
-# $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml
-#
-# The user must run the provisioning scripts in advance before attempting to
-# build the test servers. The docker_testserver.sh script is used to build up
-# the docker images into the docker-cache. It handles the immutable parts of the
-# server installation that rarely need adjustment, such as downloading packages.
-# Example: qt5/coin/provisioning/.../testserver/docker_testserver.sh
-#
-# QT_TEST_SERVER_LIST
-# - A list of test servers to bring up for this testcase
-# These test servers should be defined in $$TESTSERVER_COMPOSE_FILE. Each
-# testcase can define the test servers it depends on.
-# Example: QT_TEST_SERVER_LIST = apache2 squid vsftpd ftp-proxy danted
-#
-# Pre-processor defines needed for the application:
-# QT_TEST_SERVER
-# - A preprocessor macro used for testcase to change testing parameters at
-# compile time
-# This macro is predefined for docker-based test servers and is passed as a
-# compiler option (-DQT_TEST_SERVER). The testcase can then check whether
-# docker-based servers are in use and change the testing parameters, such as
-# host name or port number, at compile time. An example can be found in
-# network-settings.h.
-#
-# Example:
-# #if defined(QT_TEST_SERVER)
-# Change the testing parameters at compile time
-# #endif
-#
-# QT_TEST_SERVER_DOMAIN
-# - A preprocessor macro that holds the server domain name
-# Provided for the helper functions in network-settings.h. Use function
-# serverDomainName() in your application instead.
-#
-# Additional make targets:
-# 1. check_network - A renamed target from the check target of testcase feature.
-# 2. testserver_clean - Clean up server containers/images and tidy away related
-# files.
-
-TESTSERVER_COMPOSE_FILE = $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml
-TESTSERVER_VERSION = $$system(docker-compose --version)
-
-equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION) {
- # Make check with server "qt-test-server.qt-test-net" as a fallback
- message("testserver: qt-test-server.qt-test-net")
-} else {
- # Make check with test servers
- message("testserver:" $$TESTSERVER_VERSION)
-
- # Ensure that the docker-compose file is provided. It is a configuration
- # file which is mandatory for all docker-compose commands. You can get more
- # detail from the description of TESTSERVER_COMPOSE_FILE above. There is
- # also an example showing how to configure it manually.
- FILE_PRETEST_MSG = "Project variable 'TESTSERVER_COMPOSE_FILE' is not set"
- testserver_pretest.commands = $(if $$TESTSERVER_COMPOSE_FILE,,$(error $$FILE_PRETEST_MSG))
-
- # Before starting the test servers, it requires the user to run the setup
- # script (coin/provisioning/.../testserver/docker_testserver.sh) in advance.
- IMAGE_PRETEST_CMD = docker images -aq "qt-test-server-*"
- IMAGE_PRETEST_MSG = "Docker image qt-test-server-* not found"
- testserver_pretest.commands += $(if $(shell $$IMAGE_PRETEST_CMD),,$(error $$IMAGE_PRETEST_MSG))
-
- # The domain name is relevant to https keycert (qnetworkreply/crts/qt-test-net-cacert.pem).
- DNSDOMAIN = test-net.qt.local
- TEST_ENV += TESTSERVER_DOMAIN=$$DNSDOMAIN
- DEFINES += QT_TEST_SERVER QT_TEST_SERVER_DOMAIN=$$shell_quote(\"$${DNSDOMAIN}\")
-
- # There is no docker bridge on macOS. It is impossible to ping a container.
- # Docker docs recommends using port mapping to connect to a container.
- equals(QMAKE_HOST.os, Darwin): TEST_ENV += TESTSERVER_BIND_LOCAL=1
-
- # Rename the check target of testcase feature
- check.target = check_network
- testserver_test.target = check
-
- # Pretesting test servers environment
- testserver_test.depends = testserver_pretest
-
- # Bring up test servers and make sure the services are ready.
- testserver_test.commands = $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE up -d \
- --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} &&
-
- # Check test cases with docker-based test servers.
- testserver_test.commands += $(MAKE) check_network;
-
- # Stop and remove test servers after testing.
- testserver_test.commands += $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE down \
- --timeout 1
-
- # Destroy test servers and tidy away related files.
- testserver_clean.commands = $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE down \
- --rmi all
-
- QMAKE_EXTRA_TARGETS += testserver_pretest testserver_test testserver_clean
-}
diff --git a/tests/auto/tools/moc/cxx-attributes.h b/tests/auto/tools/moc/cxx-attributes.h
new file mode 100644
index 0000000000..eff6a3ec41
--- /dev/null
+++ b/tests/auto/tools/moc/cxx-attributes.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CXXATTRIBUTE_H
+#define CXXATTRIBUTE_H
+
+#include <QtCore/QObject>
+
+class CppAttribute : public QObject
+{
+ Q_OBJECT
+signals:
+ [[deprecated]] void deprecatedSignal();
+
+public slots:
+ [[deprecated]] void deprecatedSlot() {}
+ [[deprecated]] [[tst_moc::maybe_unused]] int deprecatedSlot2() { return 42; }
+ [[deprecated("reason")]] void deprecatedReason() {}
+ [[deprecated("reason[")]] void deprecatedReasonWithLBRACK() {}
+ [[deprecated("reason[[")]] void deprecatedReasonWith2LBRACK() {}
+ [[deprecated("reason]")]] void deprecatedReasonWithRBRACK() {}
+ [[deprecated("reason]]")]] void deprecatedReasonWith2RBRACK() {}
+ void slotWithArguments([[tst_moc::maybe_unused]] int) {}
+#if !defined(_MSC_VER) || _MSC_VER >= 1912
+ // On MSVC it causes:
+ // moc_cxx-attributes.cpp(133): fatal error C1001: An internal error has occurred in the compiler.
+ Q_INVOKABLE [[tst_moc::noreturn]] void noreturnSlot() { throw "unused"; }
+ [[tst_moc::noreturn]] Q_SCRIPTABLE void noreturnSlot2() { throw "unused"; }
+ [[deprecated]] int returnInt() { return 0; }
+ Q_SLOT [[tst_moc::noreturn]] [[deprecated]] void noreturnDeprecatedSlot() { throw "unused"; }
+ Q_INVOKABLE void noreturnSlot3() [[tst_moc::noreturn]] { throw "unused"; }
+#endif
+};
+
+#ifdef Q_MOC_RUN
+# define TEST_COMPILER_DEPRECATION [[deprecated]]
+# define TEST_COMPILER_DEPRECATION_X(x) [[deprecated(x)]]
+#else
+# define TEST_COMPILER_DEPRECATION Q_DECL_ENUMERATOR_DEPRECATED
+# define TEST_COMPILER_DEPRECATION_X(x) Q_DECL_ENUMERATOR_DEPRECATED_X(x)
+#endif
+
+namespace TestQNamespaceDeprecated {
+ Q_NAMESPACE
+ enum class TestEnum1 {
+ Key1 = 11,
+ Key2 TEST_COMPILER_DEPRECATION,
+ Key3 TEST_COMPILER_DEPRECATION_X("reason"),
+ Key4 TEST_COMPILER_DEPRECATION_X("reason["),
+ Key5 TEST_COMPILER_DEPRECATION_X("reason[["),
+ Key6 TEST_COMPILER_DEPRECATION_X("reason]"),
+ Key7 TEST_COMPILER_DEPRECATION_X("reason]]"),
+ };
+ Q_ENUM_NS(TestEnum1)
+
+ // try to dizzy moc by adding a struct in between
+ struct TestGadget {
+ Q_GADGET
+ public:
+ enum class TestGEnum1 {
+ Key1 = 13,
+ Key2 TEST_COMPILER_DEPRECATION,
+ Key3 TEST_COMPILER_DEPRECATION_X("reason")
+ };
+ Q_ENUM(TestGEnum1)
+ };
+
+ enum class TestFlag1 {
+ None = 0,
+ Flag1 = 1,
+ Flag2 TEST_COMPILER_DEPRECATION = 2,
+ Flag3 TEST_COMPILER_DEPRECATION_X("reason") = 3,
+ Any = Flag1 | Flag2 | Flag3
+ };
+ Q_FLAG_NS(TestFlag1)
+}
+
+#endif // CXXATTRIBUTE_H
diff --git a/tests/auto/tools/moc/cxx11-enums.h b/tests/auto/tools/moc/cxx11-enums.h
index cc14c0acda..d5bd228f12 100644
--- a/tests/auto/tools/moc/cxx11-enums.h
+++ b/tests/auto/tools/moc/cxx11-enums.h
@@ -30,7 +30,6 @@
#define CXX11_ENUMS_H
#include <QtCore/QObject>
-#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_MOC_RUN)
class CXX11Enums
{
Q_GADGET
@@ -73,21 +72,4 @@ public:
Q_FLAGS(ClassFlags)
};
-#else
-//workaround to get the moc compiled code to compile
-class CXX11Enums
-{
- Q_GADGET
-public:
- struct EnumClass { enum { A0, A1, A2, A3 }; };
- struct TypedEnumClass { enum { C0, C1, C2, C3 }; };
- enum NormalEnum { D2 = 2, D3, D0 =0 , D1 };
- enum TypedEnum { B0, B1 , B2, B3 };
-};
-
-class CXX11Enums2 : public CXX11Enums
-{
- Q_GADGET
-};
-#endif
#endif // CXX11_ENUMS_H
diff --git a/tests/auto/tools/moc/moc.pro b/tests/auto/tools/moc/moc.pro
index 3cbc9ebb5e..ad8c093add 100644
--- a/tests/auto/tools/moc/moc.pro
+++ b/tests/auto/tools/moc/moc.pro
@@ -29,7 +29,8 @@ HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-n
non-gadget-parent-class.h grand-parent-gadget-class.h \
related-metaobjects-in-gadget.h \
related-metaobjects-name-conflict.h \
- namespace.h cxx17-namespaces.h
+ namespace.h cxx17-namespaces.h \
+ cxx-attributes.h
if(*-g++*|*-icc*|*-clang*|*-llvm):!win32-*: HEADERS += os9-newlines.h win-newlines.h
diff --git a/tests/auto/tools/moc/parse-defines.h b/tests/auto/tools/moc/parse-defines.h
index 7b0fa29d7c..bd22b0b9af 100644
--- a/tests/auto/tools/moc/parse-defines.h
+++ b/tests/auto/tools/moc/parse-defines.h
@@ -51,7 +51,6 @@
#define PD_CLASSINFO Q_CLASSINFO
-#if defined(Q_COMPILER_VARIADIC_MACROS) || defined (Q_MOC_RUN)
#define PD_VARARG(x, ...) x(__VA_ARGS__)
#if defined(Q_CC_GNU) || defined(Q_MOC_RUN)
@@ -61,7 +60,6 @@
#define PD_VARARGEXT(x, ...) x(__VA_ARGS__)
#endif
-#endif
#define PD_ADD_SUFFIX(x) PD_DEFINE1(x,_SUFFIX)
#define PD_DEFINE_ITSELF PD_ADD_SUFFIX(PD_DEFINE_ITSELF)
@@ -100,7 +98,6 @@ public slots:
PD_TEST_IDENTIFIER_ARG(void, combined6()) {}
-#if defined(Q_COMPILER_VARIADIC_MACROS) || defined (Q_MOC_RUN)
PD_VARARG(void vararg1) {}
PD_VARARG(void vararg2, int) {}
PD_VARARG(void vararg3, int, int) {}
@@ -108,14 +105,6 @@ public slots:
PD_VARARGEXT(void vararg4) {}
PD_VARARGEXT(void vararg5, int) {}
PD_VARARGEXT(void vararg6, int, int) {}
-#else
- void vararg1() {}
- void vararg2(int) {}
- void vararg3(int,int) {}
- void vararg4() {}
- void vararg5(int) {}
- void vararg6(int,int) {}
-#endif
#define OUTERFUNCTION(x) x
#define INNERFUNCTION(x) OUTERFUNCTION(x)
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index 41bc4bc73b..ec4a44e672 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -71,6 +71,7 @@
#include "grand-parent-gadget-class.h"
#include "namespace.h"
#include "cxx17-namespaces.h"
+#include "cxx-attributes.h"
#ifdef Q_MOC_RUN
// check that moc can parse these constructs, they are being used in Windows winsock2.h header
@@ -683,6 +684,7 @@ private slots:
void finalClasses();
void explicitOverrideControl_data();
void explicitOverrideControl();
+ void overloadedAddressOperator();
void autoPropertyMetaTypeRegistration();
void autoMethodArgumentMetaTypeRegistration();
void autoSignalSpyMetaTypeRegistration();
@@ -703,6 +705,7 @@ private slots:
void optionsFileError();
void testQNamespace();
void cxx17Namespaces();
+ void cxxAttributes();
signals:
void sigWithUnsignedArg(unsigned foo);
@@ -1423,6 +1426,16 @@ void tst_Moc::environmentIncludePaths()
// plugin_metadata.h contains a plugin which we register here. Since we're not building this
// application as a plugin, we need top copy some of the initializer code found in qplugin.h:
extern "C" QObject *qt_plugin_instance();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+extern "C" QPluginMetaData qt_plugin_query_metadata();
+class StaticPluginInstance{
+public:
+ StaticPluginInstance() {
+ QStaticPlugin plugin(qt_plugin_instance, qt_plugin_query_metadata);
+ qRegisterStaticPluginFunction(plugin);
+ }
+};
+#else
extern "C" const char *qt_plugin_query_metadata();
class StaticPluginInstance{
public:
@@ -1431,6 +1444,7 @@ public:
qRegisterStaticPluginFunction(plugin);
}
};
+#endif
static StaticPluginInstance staticInstance;
void tst_Moc::specifyMetaTagsFromCmdline() {
@@ -2943,6 +2957,34 @@ void tst_Moc::explicitOverrideControl()
#endif
}
+class OverloadedAddressOperator : public QObject
+{
+ Q_OBJECT
+public:
+ void* operator&() { return nullptr; }
+signals:
+ void self(OverloadedAddressOperator&);
+public slots:
+ void assertSelf(OverloadedAddressOperator &o)
+ {
+ QCOMPARE(std::addressof(o), this);
+ testResult = (std::addressof(o) == this);
+ }
+public:
+ bool testResult = false;
+};
+
+void tst_Moc::overloadedAddressOperator()
+{
+ OverloadedAddressOperator o;
+ OverloadedAddressOperator *p = std::addressof(o);
+ QCOMPARE(&o, nullptr);
+ QVERIFY(p);
+ QObject::connect(p, &OverloadedAddressOperator::self, p, &OverloadedAddressOperator::assertSelf);
+ emit o.self(o);
+ QVERIFY(o.testResult);
+}
+
class CustomQObject : public QObject
{
Q_OBJECT
@@ -3819,6 +3861,14 @@ static void checkEnum(const QMetaEnum &enumerator, const QByteArray &name, const
}
}
+class EnumFromNamespaceClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(FooNamespace::Enum1 prop READ prop CONSTANT)
+public:
+ FooNamespace::Enum1 prop() { return FooNamespace::Enum1::Key2; }
+};
+
void tst_Moc::testQNamespace()
{
QCOMPARE(TestQNamespace::staticMetaObject.enumeratorCount(), 4);
@@ -3846,6 +3896,11 @@ void tst_Moc::testQNamespace()
QCOMPARE(FooNamespace::staticMetaObject.enumeratorCount(), 1);
QCOMPARE(FooNamespace::FooNestedNamespace::staticMetaObject.enumeratorCount(), 2);
QCOMPARE(FooNamespace::FooNestedNamespace::FooMoreNestedNamespace::staticMetaObject.enumeratorCount(), 1);
+
+ EnumFromNamespaceClass obj;
+ const QVariant prop = obj.property("prop");
+ QCOMPARE(prop.type(), QMetaType::Int);
+ QCOMPARE(prop.toInt(), int(FooNamespace::Enum1::Key2));
}
void tst_Moc::cxx17Namespaces()
@@ -3867,6 +3922,41 @@ void tst_Moc::cxx17Namespaces()
QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::ClassInNamespace::GadEn>().value(0), 3);
}
+void tst_Moc::cxxAttributes()
+{
+ auto so = CppAttribute::staticMetaObject;
+ QCOMPARE(so.className(), "CppAttribute");
+ QCOMPARE(so.enumeratorCount(), 0);
+ QVERIFY(so.indexOfSignal("deprecatedSignal") != 1);
+ for (auto a: {"deprecatedSlot", "deprecatedSlot2", "deprecatedReason", "deprecatedReasonWithLBRACK",
+ "deprecatedReasonWith2LBRACK", "deprecatedReasonWithRBRACK", "deprecatedReasonWith2RBRACK",
+ "slotWithArguments"
+#if !defined(_MSC_VER) || _MSC_VER >= 1912
+ , "noreturnSlot", "noreturnSlot2", "returnInt", "noreturnDeprecatedSlot",
+ "noreturnSlot3"
+#endif
+ }) {
+ QVERIFY(so.indexOfSlot(a) != 1);
+ }
+
+ QCOMPARE(TestQNamespaceDeprecated::staticMetaObject.enumeratorCount(), 2);
+ checkEnum(TestQNamespaceDeprecated::staticMetaObject.enumerator(0), "TestEnum1",
+ {{"Key1", 11}, {"Key2", 12}, {"Key3", 13}, {"Key4", 14}, {"Key5", 15}, {"Key6", 16},
+ {"Key7", 17}});
+ checkEnum(TestQNamespaceDeprecated::staticMetaObject.enumerator(1), "TestFlag1",
+ {{"None", 0}, {"Flag1", 1}, {"Flag2", 2}, {"Flag3", 3}, {"Any", 1 | 2 | 3}});
+
+ QCOMPARE(TestQNamespaceDeprecated::TestGadget::staticMetaObject.enumeratorCount(), 1);
+ checkEnum(TestQNamespaceDeprecated::TestGadget::staticMetaObject.enumerator(0), "TestGEnum1",
+ {{"Key1", 13}, {"Key2", 14}, {"Key3", 15}});
+
+ QMetaEnum meta = QMetaEnum::fromType<TestQNamespaceDeprecated::TestEnum1>();
+ QVERIFY(meta.isValid());
+ QCOMPARE(meta.name(), "TestEnum1");
+ QCOMPARE(meta.enclosingMetaObject(), &TestQNamespaceDeprecated::staticMetaObject);
+ QCOMPARE(meta.keyCount(), 7);
+}
+
QTEST_MAIN(tst_Moc)
// the generated code must compile with QT_NO_KEYWORDS
diff --git a/tests/auto/tools/qmakelib/qmakelib.pro b/tests/auto/tools/qmakelib/qmakelib.pro
index 29f17f6a14..5e9e9fe637 100644
--- a/tests/auto/tools/qmakelib/qmakelib.pro
+++ b/tests/auto/tools/qmakelib/qmakelib.pro
@@ -1,7 +1,7 @@
CONFIG += testcase
TARGET = tst_qmakelib
QT = core testlib
-win32: LIBS += -ladvapi32
+win32: QMAKE_USE += advapi32
INCLUDEPATH += ../../../../qmake/library
VPATH += ../../../../qmake/library
diff --git a/tests/auto/tools/rcc/data/images/images.expected b/tests/auto/tools/rcc/data/images/images.expected
index 45e96dccd0..2af071812e 100644
--- a/tests/auto/tools/rcc/data/images/images.expected
+++ b/tests/auto/tools/rcc/data/images/images.expected
@@ -115,7 +115,6 @@ namespace QT_NAMESPACE {
#endif
bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
-
bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
#ifdef QT_NAMESPACE
@@ -125,16 +124,18 @@ bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *,
int QT_RCC_MANGLE_NAMESPACE(qInitResources)();
int QT_RCC_MANGLE_NAMESPACE(qInitResources)()
{
+ int version = 3;
QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData)
- (0x2, qt_resource_struct, qt_resource_name, qt_resource_data);
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
return 1;
}
int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)();
int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)()
{
+ int version = 3;
QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData)
- (0x2, qt_resource_struct, qt_resource_name, qt_resource_data);
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
return 1;
}
diff --git a/tests/auto/tools/rcc/data/sizes/data/data-0.txt b/tests/auto/tools/rcc/data/sizes/data/data-0.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/data/data-0.txt
diff --git a/tests/auto/tools/rcc/data/sizes/data/data-1.txt b/tests/auto/tools/rcc/data/sizes/data/data-1.txt
new file mode 100644
index 0000000000..b516b2c489
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/data/data-1.txt
@@ -0,0 +1 @@
+@ \ No newline at end of file
diff --git a/tests/auto/tools/rcc/data/sizes/data/data-2.txt b/tests/auto/tools/rcc/data/sizes/data/data-2.txt
new file mode 100644
index 0000000000..a616ad491b
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/data/data-2.txt
@@ -0,0 +1 @@
+01 \ No newline at end of file
diff --git a/tests/auto/tools/rcc/data/sizes/data/data-35.txt b/tests/auto/tools/rcc/data/sizes/data/data-35.txt
new file mode 100644
index 0000000000..19a8036a15
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/data/data-35.txt
@@ -0,0 +1 @@
+0123456789 0123456789 0123456789 12 \ No newline at end of file
diff --git a/tests/auto/tools/rcc/data/sizes/size-0.expected b/tests/auto/tools/rcc/data/sizes/size-0.expected
new file mode 100644
index 0000000000..2f70a607ab
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/size-0.expected
@@ -0,0 +1,89 @@
+/****************************************************************************
+** Resource object code
+**
+IGNORE: ** Created by: The Resource Compiler for Qt version 5.11.2
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+static const unsigned char qt_resource_data[] = {
+IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-0.txt
+ 0x0,0x0,0x0,0x0,
+
+
+};
+
+static const unsigned char qt_resource_name[] = {
+ // data
+ 0x0,0x4,
+ 0x0,0x6,0xa8,0xa1,
+ 0x0,0x64,
+ 0x0,0x61,0x0,0x74,0x0,0x61,
+ // data-0.txt
+ 0x0,0xa,
+ 0x4,0xe,0xa,0xb4,
+ 0x0,0x64,
+ 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x30,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+
+};
+
+static const unsigned char qt_resource_struct[] = {
+ // :
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ // :/data
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ // :/data/data-0.txt
+ 0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
+TIMESTAMP:data/data-0.txt
+
+};
+
+#ifdef QT_NAMESPACE
+# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
+# define QT_RCC_MANGLE_NAMESPACE0(x) x
+# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b
+# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)
+# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \
+ QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))
+#else
+# define QT_RCC_PREPEND_NAMESPACE(name) name
+# define QT_RCC_MANGLE_NAMESPACE(name) name
+#endif
+
+#ifdef QT_NAMESPACE
+namespace QT_NAMESPACE {
+#endif
+
+bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
+bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
+
+#ifdef QT_NAMESPACE
+}
+#endif
+
+int QT_RCC_MANGLE_NAMESPACE(qInitResources)();
+int QT_RCC_MANGLE_NAMESPACE(qInitResources)()
+{
+ int version = 3;
+ QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData)
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)();
+int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)()
+{
+ int version = 3;
+ QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData)
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+namespace {
+ struct initializer {
+ initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources)(); }
+ ~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); }
+ } dummy;
+}
diff --git a/tests/auto/tools/rcc/data/sizes/size-0.qrc b/tests/auto/tools/rcc/data/sizes/size-0.qrc
new file mode 100644
index 0000000000..9f47732fe2
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/size-0.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>data/data-0.txt</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/tools/rcc/data/sizes/size-1.expected b/tests/auto/tools/rcc/data/sizes/size-1.expected
new file mode 100644
index 0000000000..d1717a9255
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/size-1.expected
@@ -0,0 +1,90 @@
+/****************************************************************************
+** Resource object code
+**
+IGNORE:** Created by: The Resource Compiler for Qt version 5.11.2
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+static const unsigned char qt_resource_data[] = {
+IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-1.txt
+ 0x0,0x0,0x0,0x1,
+ 0x40,
+
+
+};
+
+static const unsigned char qt_resource_name[] = {
+ // data
+ 0x0,0x4,
+ 0x0,0x6,0xa8,0xa1,
+ 0x0,0x64,
+ 0x0,0x61,0x0,0x74,0x0,0x61,
+ // data-1.txt
+ 0x0,0xa,
+ 0x4,0x11,0xa,0xb4,
+ 0x0,0x64,
+ 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x31,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+
+};
+
+static const unsigned char qt_resource_struct[] = {
+ // :
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ // :/data
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ // :/data/data-1.txt
+ 0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
+TIMESTAMP:data/data-1.txt
+
+};
+
+#ifdef QT_NAMESPACE
+# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
+# define QT_RCC_MANGLE_NAMESPACE0(x) x
+# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b
+# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)
+# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \
+ QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))
+#else
+# define QT_RCC_PREPEND_NAMESPACE(name) name
+# define QT_RCC_MANGLE_NAMESPACE(name) name
+#endif
+
+#ifdef QT_NAMESPACE
+namespace QT_NAMESPACE {
+#endif
+
+bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
+bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
+
+#ifdef QT_NAMESPACE
+}
+#endif
+
+int QT_RCC_MANGLE_NAMESPACE(qInitResources)();
+int QT_RCC_MANGLE_NAMESPACE(qInitResources)()
+{
+ int version = 3;
+ QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData)
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)();
+int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)()
+{
+ int version = 3;
+ QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData)
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+namespace {
+ struct initializer {
+ initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources)(); }
+ ~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); }
+ } dummy;
+}
diff --git a/tests/auto/tools/rcc/data/sizes/size-1.qrc b/tests/auto/tools/rcc/data/sizes/size-1.qrc
new file mode 100644
index 0000000000..9fde9a1722
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/size-1.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>data/data-1.txt</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.expected b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.expected
new file mode 100644
index 0000000000..7a7cc93df1
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.expected
@@ -0,0 +1,127 @@
+/****************************************************************************
+** Resource object code
+**
+IGNORE: ** Created by: The Resource Compiler for Qt version 5.11.2
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+static const unsigned char qt_resource_data[] = {
+IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-2.txt
+ 0x0,0x0,0x0,0x2,
+ 0x30,
+ 0x31,
+IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-35.txt
+ 0x0,0x0,0x0,0x23,
+ 0x30,
+ 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x20,0x30,0x31,0x32,0x33,0x34,0x35,
+ 0x36,0x37,0x38,0x39,0x20,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x20,
+ 0x31,0x32,
+IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-1.txt
+ 0x0,0x0,0x0,0x1,
+ 0x40,
+
+IGNORE: // /data/dev/qt-5/qtbase/tests/auto/tools/rcc/data/sizes/data/data-0.txt
+ 0x0,0x0,0x0,0x0,
+
+
+};
+
+static const unsigned char qt_resource_name[] = {
+ // data
+ 0x0,0x4,
+ 0x0,0x6,0xa8,0xa1,
+ 0x0,0x64,
+ 0x0,0x61,0x0,0x74,0x0,0x61,
+ // data-2.txt
+ 0x0,0xa,
+ 0x4,0x8,0xa,0xb4,
+ 0x0,0x64,
+ 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x32,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+ // data-35.txt
+ 0x0,0xb,
+ 0x0,0xb5,0x4f,0x74,
+ 0x0,0x64,
+ 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x33,0x0,0x35,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+ // data-1.txt
+ 0x0,0xa,
+ 0x4,0x11,0xa,0xb4,
+ 0x0,0x64,
+ 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x31,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+ // data-0.txt
+ 0x0,0xa,
+ 0x4,0xe,0xa,0xb4,
+ 0x0,0x64,
+ 0x0,0x61,0x0,0x74,0x0,0x61,0x0,0x2d,0x0,0x30,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+
+};
+
+static const unsigned char qt_resource_struct[] = {
+ // :
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ // :/data
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x2,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ // :/data/data-35.txt
+ 0x0,0x0,0x0,0x28,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x6,
+TIMESTAMP:data/data-35.txt
+ // :/data/data-2.txt
+ 0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
+TIMESTAMP:data/data-2.txt
+ // :/data/data-0.txt
+ 0x0,0x0,0x0,0x5e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x32,
+TIMESTAMP:data/data-0.txt
+ // :/data/data-1.txt
+ 0x0,0x0,0x0,0x44,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2d,
+TIMESTAMP:data/data-1.txt
+
+};
+
+#ifdef QT_NAMESPACE
+# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
+# define QT_RCC_MANGLE_NAMESPACE0(x) x
+# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b
+# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)
+# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \
+ QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))
+#else
+# define QT_RCC_PREPEND_NAMESPACE(name) name
+# define QT_RCC_MANGLE_NAMESPACE(name) name
+#endif
+
+#ifdef QT_NAMESPACE
+namespace QT_NAMESPACE {
+#endif
+
+bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
+bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
+
+#ifdef QT_NAMESPACE
+}
+#endif
+
+int QT_RCC_MANGLE_NAMESPACE(qInitResources)();
+int QT_RCC_MANGLE_NAMESPACE(qInitResources)()
+{
+ int version = 3;
+ QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData)
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)();
+int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)()
+{
+ int version = 3;
+ QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData)
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+namespace {
+ struct initializer {
+ initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources)(); }
+ ~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); }
+ } dummy;
+}
diff --git a/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.qrc b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.qrc
new file mode 100644
index 0000000000..039c9203ff
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>data/data-2.txt</file>
+ <file>data/data-0.txt</file>
+ <file>data/data-35.txt</file>
+ <file>data/data-1.txt</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/tools/rcc/data/sizes/size-2-0-35-1_python.expected b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1_python.expected
new file mode 100644
index 0000000000..9dcd131af5
--- /dev/null
+++ b/tests/auto/tools/rcc/data/sizes/size-2-0-35-1_python.expected
@@ -0,0 +1,68 @@
+# Resource object code (Python 3)
+# Created by: object code
+# Created by: The Resource Compiler for Qt version 5.14.0
+# WARNING! All changes made in this file will be lost!
+
+from PySide2 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x00\x02\
+0\
+1\
+\x00\x00\x00#\
+0\
+123456789 012345\
+6789 0123456789 \
+12\
+\x00\x00\x00\x01\
+@\
+\
+\x00\x00\x00\x00\
+\
+"
+
+qt_resource_name = b"\
+\x00\x04\
+\x00\x06\xa8\xa1\
+\x00d\
+\x00a\x00t\x00a\
+\x00\x0a\
+\x04\x08\x0a\xb4\
+\x00d\
+\x00a\x00t\x00a\x00-\x002\x00.\x00t\x00x\x00t\
+\x00\x0b\
+\x00\xb5Ot\
+\x00d\
+\x00a\x00t\x00a\x00-\x003\x005\x00.\x00t\x00x\x00t\
+\x00\x0a\
+\x04\x11\x0a\xb4\
+\x00d\
+\x00a\x00t\x00a\x00-\x001\x00.\x00t\x00x\x00t\
+\x00\x0a\
+\x04\x0e\x0a\xb4\
+\x00d\
+\x00a\x00t\x00a\x00-\x000\x00.\x00t\x00x\x00t\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00(\x00\x00\x00\x00\x00\x01\x00\x00\x00\x06\
+IGNORE: (time stamp)
+\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+IGNORE: (time stamp)
+\x00\x00\x00^\x00\x00\x00\x00\x00\x01\x00\x00\x002\
+IGNORE: (time stamp)
+\x00\x00\x00D\x00\x00\x00\x00\x00\x01\x00\x00\x00-\
+IGNORE: (time stamp)
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/tests/auto/tools/rcc/rcc.pro b/tests/auto/tools/rcc/rcc.pro
index 264b8ecc66..3fdc4132a7 100644
--- a/tests/auto/tools/rcc/rcc.pro
+++ b/tests/auto/tools/rcc/rcc.pro
@@ -3,3 +3,10 @@ QT = core testlib
TARGET = tst_rcc
SOURCES += tst_rcc.cpp
+
+RESOURCES += \
+ $$PWD/data/images/images.qrc \
+ $$PWD/data/sizes/size-0.qrc \
+ $$PWD/data/sizes/size-2-0-35-1.qrc \
+ $$PWD/data/sizes/size-1.qrc
+
diff --git a/tests/auto/tools/rcc/tst_rcc.cpp b/tests/auto/tools/rcc/tst_rcc.cpp
index 54a2854ede..24fd79cf19 100644
--- a/tests/auto/tools/rcc/tst_rcc.cpp
+++ b/tests/auto/tools/rcc/tst_rcc.cpp
@@ -46,6 +46,33 @@
typedef QMap<QString, QString> QStringMap;
Q_DECLARE_METATYPE(QStringMap)
+static QByteArray msgProcessStartFailed(const QProcess &p)
+{
+ const QString result = QLatin1String("Could not start \"")
+ + QDir::toNativeSeparators(p.program()) + QLatin1String("\": ")
+ + p.errorString();
+ return result.toLocal8Bit();
+}
+
+static QByteArray msgProcessTimeout(const QProcess &p)
+{
+ return '"' + QDir::toNativeSeparators(p.program()).toLocal8Bit()
+ + "\" timed out.";
+}
+
+static QByteArray msgProcessCrashed(QProcess &p)
+{
+ return '"' + QDir::toNativeSeparators(p.program()).toLocal8Bit()
+ + "\" crashed.\n" + p.readAllStandardError();
+}
+
+static QByteArray msgProcessFailed(QProcess &p)
+{
+ return '"' + QDir::toNativeSeparators(p.program()).toLocal8Bit()
+ + "\" returned " + QByteArray::number(p.exitCode()) + ":\n"
+ + p.readAllStandardError();
+}
+
class tst_rcc : public QObject
{
Q_OBJECT
@@ -55,13 +82,20 @@ private slots:
void rcc_data();
void rcc();
+
void binary_data();
void binary();
+ void readback_data();
+ void readback();
+
+ void python();
+
void cleanupTestCase();
private:
QString m_rcc;
+ QString m_dataPath;
};
void tst_rcc::initTestCase()
@@ -70,20 +104,19 @@ void tst_rcc::initTestCase()
// we must force a certain hash order when testing or tst_rcc will fail, see QTBUG-25078
QVERIFY(qputenv("QT_RCC_TEST", "1"));
m_rcc = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/rcc");
-}
-QString findExpectedFile(const QString &base)
-{
- QString expectedrccfile = base;
+ m_dataPath = QFINDTESTDATA("data");
+ QVERIFY(!m_dataPath.isEmpty());
+}
- // Must be updated with each minor release.
- if (QFileInfo(expectedrccfile + QLatin1String(".450")).exists())
- expectedrccfile += QLatin1String(".450");
- return expectedrccfile;
+static inline bool isPythonComment(const QString &line)
+{
+ return line.startsWith(QLatin1Char('#'));
}
-static QString doCompare(const QStringList &actual, const QStringList &expected)
+static QString doCompare(const QStringList &actual, const QStringList &expected,
+ const QString &timeStampPath)
{
if (actual.size() != expected.size()) {
return QString("Length count different: actual: %1, expected: %2")
@@ -91,13 +124,21 @@ static QString doCompare(const QStringList &actual, const QStringList &expected)
}
QByteArray ba;
+ const bool isPython = isPythonComment(expected.constFirst());
for (int i = 0, n = expected.size(); i != n; ++i) {
QString expectedLine = expected.at(i);
if (expectedLine.startsWith("IGNORE:"))
continue;
+ if (isPython && isPythonComment(expectedLine) && isPythonComment(actual.at(i)))
+ continue;
if (expectedLine.startsWith("TIMESTAMP:")) {
const QString relativePath = expectedLine.mid(strlen("TIMESTAMP:"));
- const quint64 timeStamp = QFileInfo(relativePath).lastModified().toMSecsSinceEpoch();
+ const QFileInfo fi(timeStampPath + QLatin1Char('/') + relativePath);
+ if (!fi.isFile()) {
+ ba.append("File " + fi.absoluteFilePath().toUtf8() + " does not exist!");
+ break;
+ }
+ const quint64 timeStamp = quint64(fi.lastModified().toMSecsSinceEpoch());
expectedLine.clear();
for (int shift = 56; shift >= 0; shift -= 8) {
expectedLine.append(QLatin1String("0x"));
@@ -106,7 +147,7 @@ static QString doCompare(const QStringList &actual, const QStringList &expected)
}
}
if (expectedLine != actual.at(i)) {
- qDebug() << "LINES" << i << "DIFFER";
+ qDebug() << "LINES" << (i + 1) << "DIFFER";
ba.append(
"\n<<<<<< actual\n" + actual.at(i) + "\n======\n" + expectedLine
+ "\n>>>>>> expected\n"
@@ -122,10 +163,27 @@ void tst_rcc::rcc_data()
QTest::addColumn<QString>("qrcfile");
QTest::addColumn<QString>("expected");
- QString dataPath = QFINDTESTDATA("data/images/");
- if (dataPath.isEmpty())
- QFAIL("data path not found");
- QTest::newRow("images") << dataPath << "images.qrc" << "images.expected";
+ const QString imagesPath = m_dataPath + QLatin1String("/images");
+ QTest::newRow("images") << imagesPath << "images.qrc" << "images.expected";
+
+ const QString sizesPath = m_dataPath + QLatin1String("/sizes");
+ QTest::newRow("size-0") << sizesPath << "size-0.qrc" << "size-0.expected";
+ QTest::newRow("size-1") << sizesPath << "size-1.qrc" << "size-1.expected";
+ QTest::newRow("size-2-0-35-1") << sizesPath << "size-2-0-35-1.qrc" << "size-2-0-35-1.expected";
+}
+
+static QStringList readLinesFromFile(const QString &fileName,
+ QString::SplitBehavior splitBehavior)
+{
+ QFile file(fileName);
+
+ bool ok = file.open(QIODevice::ReadOnly | QIODevice::Text);
+ if (!ok) {
+ QWARN(qPrintable(QString::fromLatin1("Could not open testdata file %1: %2")
+ .arg(fileName, file.errorString())));
+ }
+
+ return QString::fromUtf8(file.readAll()).split(QLatin1Char('\n'), splitBehavior);
}
void tst_rcc::rcc()
@@ -134,29 +192,24 @@ void tst_rcc::rcc()
QFETCH(QString, qrcfile);
QFETCH(QString, expected);
- if (!QDir::setCurrent(directory)) {
- QString message = QString::fromLatin1("Unable to cd from '%1' to '%2'").arg(QDir::currentPath(), directory);
- QFAIL(qPrintable(message));
- }
-
// If the file expectedoutput.txt exists, compare the
// console output with the content of that file
- const QString expected2 = findExpectedFile(expected);
- QFile expectedFile(expected2);
- if (!expectedFile.exists()) {
- qDebug() << "NO EXPECTATIONS? " << expected2;
- return;
- }
- // Launch
+ // Launch; force no compression, otherwise the output would be different
+ // depending on the compression algorithm we're using
QProcess process;
- process.start(m_rcc, QStringList(qrcfile));
+ process.setWorkingDirectory(directory);
+ process.start(m_rcc, { "-no-compress", qrcfile });
+ QVERIFY2(process.waitForStarted(), msgProcessStartFailed(process).constData());
if (!process.waitForFinished()) {
- const QString path = QString::fromLocal8Bit(qgetenv("PATH"));
- QString message = QString::fromLatin1("'%1' could not be found when run from '%2'. Path: '%3' ").
- arg(m_rcc, QDir::currentPath(), path);
- QFAIL(qPrintable(message));
+ process.kill();
+ QFAIL(msgProcessTimeout(process).constData());
}
+ QVERIFY2(process.exitStatus() == QProcess::NormalExit,
+ msgProcessCrashed(process).constData());
+ QVERIFY2(process.exitCode() == 0,
+ msgProcessFailed(process).constData());
+
const QChar cr = QLatin1Char('\r');
const QString err = QString::fromLocal8Bit(process.readAllStandardError()).remove(cr);
const QString out = QString::fromLatin1(process.readAllStandardOutput()).remove(cr);
@@ -169,62 +222,20 @@ void tst_rcc::rcc()
const QChar nl = QLatin1Char('\n');
const QStringList actualLines = out.split(nl);
- QVERIFY(expectedFile.open(QIODevice::ReadOnly|QIODevice::Text));
- const QStringList expectedLines = QString::fromLatin1(expectedFile.readAll()).split(nl);
+ const QStringList expectedLines =
+ readLinesFromFile(directory + QLatin1Char('/') + expected, QString::KeepEmptyParts);
+ QVERIFY(!expectedLines.isEmpty());
- const QString diff = doCompare(actualLines, expectedLines);
+ const QString diff = doCompare(actualLines, expectedLines, directory);
if (diff.size())
QFAIL(qPrintable(diff));
}
-
-
-static void createRccBinaryData(const QString &rcc, const QString &baseDir,
- const QString &qrcFileName, const QString &rccFileName)
-{
- QString currentDir = QDir::currentPath();
- QDir::setCurrent(baseDir);
-
- QProcess rccProcess;
- rccProcess.start(rcc, QStringList() << "-binary" << "-o" << rccFileName << qrcFileName);
- bool ok = rccProcess.waitForFinished();
- if (!ok) {
- QString errorString = QString::fromLatin1("Could not start rcc (is it in PATH?): %1").arg(rccProcess.errorString());
- QFAIL(qPrintable(errorString));
- }
-
- QByteArray output = rccProcess.readAllStandardOutput();
- if (!output.isEmpty()) {
- QString errorMessage = QString::fromLatin1("rcc stdout: %1").arg(QString::fromLocal8Bit(output));
- QWARN(qPrintable(errorMessage));
- }
-
- output = rccProcess.readAllStandardError();
- if (!output.isEmpty()) {
- QString errorMessage = QString::fromLatin1("rcc stderr: %1").arg(QString::fromLocal8Bit(output));
- QWARN(qPrintable(errorMessage));
- }
-
- QDir::setCurrent(currentDir);
-}
-
-static QStringList readLinesFromFile(const QString &fileName)
-{
- QFile file(fileName);
-
- bool ok = file.open(QIODevice::ReadOnly | QIODevice::Text);
- if (!ok)
- QWARN(qPrintable(QString::fromLatin1("Could not open testdata file %1: %2").arg(fileName, file.errorString())));
-
- QStringList lines = QString::fromUtf8(file.readAll()).split(QLatin1Char('\n'), QString::SkipEmptyParts);
- return lines;
-}
-
static QStringMap readExpectedFiles(const QString &fileName)
{
QStringMap expectedFiles;
- QStringList lines = readLinesFromFile(fileName);
+ QStringList lines = readLinesFromFile(fileName, QString::SkipEmptyParts);
foreach (const QString &line, lines) {
QString resourceFileName = line.section(QLatin1Char(' '), 0, 0, QString::SectionSkipEmpty);
QString actualFileName = line.section(QLatin1Char(' '), 1, 1, QString::SectionSkipEmpty);
@@ -255,9 +266,7 @@ void tst_rcc::binary_data()
QTest::addColumn<QString>("baseDirectory");
QTest::addColumn<QStringMap>("expectedFiles");
- QString dataPath = QFINDTESTDATA("data/binary/");
- if (dataPath.isEmpty())
- QFAIL("data path not found");
+ QString dataPath = m_dataPath + QLatin1String("/binary/");
QDirIterator iter(dataPath, QStringList() << QLatin1String("*.qrc"));
while (iter.hasNext())
@@ -266,12 +275,33 @@ void tst_rcc::binary_data()
QFileInfo qrcFileInfo = iter.fileInfo();
QString absoluteBaseName = QFileInfo(qrcFileInfo.absolutePath(), qrcFileInfo.baseName()).absoluteFilePath();
QString rccFileName = absoluteBaseName + QLatin1String(".rcc");
- createRccBinaryData(m_rcc, dataPath, qrcFileInfo.absoluteFilePath(), rccFileName);
+
+ // same as above: force no compression
+ QProcess rccProcess;
+ rccProcess.setWorkingDirectory(dataPath);
+ rccProcess.start(m_rcc, { "-binary", "-no-compress", "-o", rccFileName, qrcFileInfo.absoluteFilePath() });
+ QVERIFY2(rccProcess.waitForStarted(), msgProcessStartFailed(rccProcess).constData());
+ if (!rccProcess.waitForFinished()) {
+ rccProcess.kill();
+ QFAIL(msgProcessTimeout(rccProcess).constData());
+ }
+ QVERIFY2(rccProcess.exitStatus() == QProcess::NormalExit,
+ msgProcessCrashed(rccProcess).constData());
+ QVERIFY2(rccProcess.exitCode() == 0,
+ msgProcessFailed(rccProcess).constData());
+
+ QByteArray output = rccProcess.readAllStandardOutput();
+ if (!output.isEmpty())
+ qWarning("rcc stdout: %s", output.constData());
+
+ output = rccProcess.readAllStandardError();
+ if (!output.isEmpty())
+ qWarning("rcc stderr: %s", output.constData());
QString localeFileName = absoluteBaseName + QLatin1String(".locale");
QFile localeFile(localeFileName);
if (localeFile.exists()) {
- QStringList locales = readLinesFromFile(localeFileName);
+ QStringList locales = readLinesFromFile(localeFileName, QString::SkipEmptyParts);
foreach (const QString &locale, locales) {
QString expectedFileName = QString::fromLatin1("%1.%2.%3").arg(absoluteBaseName, locale, QLatin1String("expected"));
QStringMap expectedFiles = readExpectedFiles(expectedFileName);
@@ -353,13 +383,72 @@ void tst_rcc::binary()
QLocale::setDefault(oldDefaultLocale);
}
+void tst_rcc::readback_data()
+{
+ QTest::addColumn<QString>("resourceName");
+ QTest::addColumn<QString>("fileSystemName");
+
+ QTest::newRow("data-0") << ":data/data-0.txt" << "sizes/data/data-0.txt";
+ QTest::newRow("data-1") << ":data/data-1.txt" << "sizes/data/data-1.txt";
+ QTest::newRow("data-2") << ":data/data-2.txt" << "sizes/data/data-2.txt";
+ QTest::newRow("data-35") << ":data/data-35.txt" << "sizes/data/data-35.txt";
+ QTest::newRow("circle") << ":images/circle.png" << "images/images/circle.png";
+ QTest::newRow("square") << ":images/square.png" << "images/images/square.png";
+ QTest::newRow("triangle") << ":images/subdir/triangle.png"
+ << "images/images/subdir/triangle.png";
+}
+
+void tst_rcc::readback()
+{
+ QFETCH(QString, resourceName);
+ QFETCH(QString, fileSystemName);
+
+ QFile resourceFile(resourceName);
+ QVERIFY(resourceFile.open(QIODevice::ReadOnly));
+ QByteArray resourceData = resourceFile.readAll();
+ resourceFile.close();
+
+ QFile fileSystemFile(m_dataPath + QLatin1Char('/') + fileSystemName);
+ QVERIFY(fileSystemFile.open(QIODevice::ReadOnly));
+ QByteArray fileSystemData = fileSystemFile.readAll();
+ fileSystemFile.close();
+
+ QCOMPARE(resourceData, fileSystemData);
+}
+
+void tst_rcc::python()
+{
+ const QString path = m_dataPath + QLatin1String("/sizes");
+ const QString testFileRoot = path + QLatin1String("/size-2-0-35-1");
+ const QString qrcFile = testFileRoot + QLatin1String(".qrc");
+ const QString expectedFile = testFileRoot + QLatin1String("_python.expected");
+ const QString actualFile = testFileRoot + QLatin1String(".rcc");
+
+ QProcess process;
+ process.setWorkingDirectory(path);
+ process.start(m_rcc, { "-g", "python", "-o", actualFile, qrcFile});
+ QVERIFY2(process.waitForStarted(), msgProcessStartFailed(process).constData());
+ if (!process.waitForFinished()) {
+ process.kill();
+ QFAIL(msgProcessTimeout(process).constData());
+ }
+ QVERIFY2(process.exitStatus() == QProcess::NormalExit,
+ msgProcessCrashed(process).constData());
+ QVERIFY2(process.exitCode() == 0,
+ msgProcessFailed(process).constData());
+
+ const auto actualLines = readLinesFromFile(actualFile, QString::KeepEmptyParts);
+ QVERIFY(!actualLines.isEmpty());
+ const auto expectedLines = readLinesFromFile(expectedFile, QString::KeepEmptyParts);
+ QVERIFY(!expectedLines.isEmpty());
+ const QString diff = doCompare(actualLines, expectedLines, path);
+ if (!diff.isEmpty())
+ QFAIL(qPrintable(diff));
+}
void tst_rcc::cleanupTestCase()
{
- QString dataPath = QFINDTESTDATA("data/binary/");
- if (dataPath.isEmpty())
- return;
- QDir dataDir(dataPath);
+ QDir dataDir(m_dataPath + QLatin1String("/binary"));
QFileInfoList entries = dataDir.entryInfoList(QStringList() << QLatin1String("*.rcc"));
foreach (const QFileInfo &entry, entries)
QFile::remove(entry.absoluteFilePath());
diff --git a/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Bottom.ui.h b/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Bottom.ui.h
index 1f5004b2aa..8b17acc1cd 100644
--- a/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Bottom.ui.h
+++ b/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Bottom.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'Dialog_with_Buttons_Bottom.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -41,7 +41,7 @@ public:
void retranslateUi(QDialog *Dialog)
{
- Dialog->setWindowTitle(QApplication::translate("Dialog", "Dialog", nullptr));
+ Dialog->setWindowTitle(QCoreApplication::translate("Dialog", "Dialog", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Right.ui.h b/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Right.ui.h
index 8dd8b11b62..cdb12ec2b8 100644
--- a/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Right.ui.h
+++ b/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Right.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'Dialog_with_Buttons_Right.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -41,7 +41,7 @@ public:
void retranslateUi(QDialog *Dialog)
{
- Dialog->setWindowTitle(QApplication::translate("Dialog", "Dialog", nullptr));
+ Dialog->setWindowTitle(QCoreApplication::translate("Dialog", "Dialog", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/Dialog_without_Buttons.ui.h b/tests/auto/tools/uic/baseline/Dialog_without_Buttons.ui.h
index 95acabf3f8..abdeb5b823 100644
--- a/tests/auto/tools/uic/baseline/Dialog_without_Buttons.ui.h
+++ b/tests/auto/tools/uic/baseline/Dialog_without_Buttons.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'Dialog_without_Buttons.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -32,7 +32,7 @@ public:
void retranslateUi(QDialog *Dialog)
{
- Dialog->setWindowTitle(QApplication::translate("Dialog", "Dialog", nullptr));
+ Dialog->setWindowTitle(QCoreApplication::translate("Dialog", "Dialog", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/Main_Window.ui.h b/tests/auto/tools/uic/baseline/Main_Window.ui.h
index 9e59e9f2e5..b78a3df8af 100644
--- a/tests/auto/tools/uic/baseline/Main_Window.ui.h
+++ b/tests/auto/tools/uic/baseline/Main_Window.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'Main_Window.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -47,7 +47,7 @@ public:
void retranslateUi(QMainWindow *MainWindow)
{
- MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr));
+ MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/Widget.ui.h b/tests/auto/tools/uic/baseline/Widget.ui.h
index 4318c2262f..906f648533 100644
--- a/tests/auto/tools/uic/baseline/Widget.ui.h
+++ b/tests/auto/tools/uic/baseline/Widget.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'Widget.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -57,13 +57,13 @@ public:
void retranslateUi(QWidget *Form)
{
- Form->setWindowTitle(QApplication::translate("Form", "Form", nullptr));
- Alabel->setText(QApplication::translate("Form", "A label.\n"
+ Form->setWindowTitle(QCoreApplication::translate("Form", "Form", nullptr));
+ Alabel->setText(QCoreApplication::translate("Form", "A label.\n"
"One new line.\n"
"Another new line.\n"
"Last line.", nullptr));
- groupBox->setTitle(QApplication::translate("Form", "A Group Box", nullptr));
- pushButton->setText(QApplication::translate("Form", "PushButton", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("Form", "A Group Box", nullptr));
+ pushButton->setText(QCoreApplication::translate("Form", "PushButton", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/addlinkdialog.ui.h b/tests/auto/tools/uic/baseline/addlinkdialog.ui.h
index 17f51a92f8..2a0ef18fa7 100644
--- a/tests/auto/tools/uic/baseline/addlinkdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/addlinkdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'addlinkdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -97,9 +97,9 @@ public:
void retranslateUi(QDialog *AddLinkDialog)
{
- AddLinkDialog->setWindowTitle(QApplication::translate("AddLinkDialog", "Insert Link", nullptr));
- label->setText(QApplication::translate("AddLinkDialog", "Title:", nullptr));
- label_2->setText(QApplication::translate("AddLinkDialog", "URL:", nullptr));
+ AddLinkDialog->setWindowTitle(QCoreApplication::translate("AddLinkDialog", "Insert Link", nullptr));
+ label->setText(QCoreApplication::translate("AddLinkDialog", "Title:", nullptr));
+ label_2->setText(QCoreApplication::translate("AddLinkDialog", "URL:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/addtorrentform.ui.h b/tests/auto/tools/uic/baseline/addtorrentform.ui.h
index d259a011bf..b357d708d5 100644
--- a/tests/auto/tools/uic/baseline/addtorrentform.ui.h
+++ b/tests/auto/tools/uic/baseline/addtorrentform.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'addtorrentform.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -209,23 +209,23 @@ public:
void retranslateUi(QDialog *AddTorrentFile)
{
- AddTorrentFile->setWindowTitle(QApplication::translate("AddTorrentFile", "Add a torrent", nullptr));
- groupBox->setTitle(QApplication::translate("AddTorrentFile", "Select a torrent source", nullptr));
- label_4->setText(QApplication::translate("AddTorrentFile", "Destination:", nullptr));
- label_2->setText(QApplication::translate("AddTorrentFile", "Tracker URL:", nullptr));
- browseTorrents->setText(QApplication::translate("AddTorrentFile", "Browse", nullptr));
- label_5->setText(QApplication::translate("AddTorrentFile", "File(s):", nullptr));
- label_3->setText(QApplication::translate("AddTorrentFile", "Size:", nullptr));
- label_6->setText(QApplication::translate("AddTorrentFile", "Creator:", nullptr));
- announceUrl->setText(QApplication::translate("AddTorrentFile", "<none>", nullptr));
- label->setText(QApplication::translate("AddTorrentFile", "Torrent file:", nullptr));
- browseDestination->setText(QApplication::translate("AddTorrentFile", "Browse", nullptr));
- label_7->setText(QApplication::translate("AddTorrentFile", "Comment:", nullptr));
- commentLabel->setText(QApplication::translate("AddTorrentFile", "<none>", nullptr));
- creatorLabel->setText(QApplication::translate("AddTorrentFile", "<none>", nullptr));
- sizeLabel->setText(QApplication::translate("AddTorrentFile", "0", nullptr));
- okButton->setText(QApplication::translate("AddTorrentFile", "&OK", nullptr));
- cancelButton->setText(QApplication::translate("AddTorrentFile", "&Cancel", nullptr));
+ AddTorrentFile->setWindowTitle(QCoreApplication::translate("AddTorrentFile", "Add a torrent", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("AddTorrentFile", "Select a torrent source", nullptr));
+ label_4->setText(QCoreApplication::translate("AddTorrentFile", "Destination:", nullptr));
+ label_2->setText(QCoreApplication::translate("AddTorrentFile", "Tracker URL:", nullptr));
+ browseTorrents->setText(QCoreApplication::translate("AddTorrentFile", "Browse", nullptr));
+ label_5->setText(QCoreApplication::translate("AddTorrentFile", "File(s):", nullptr));
+ label_3->setText(QCoreApplication::translate("AddTorrentFile", "Size:", nullptr));
+ label_6->setText(QCoreApplication::translate("AddTorrentFile", "Creator:", nullptr));
+ announceUrl->setText(QCoreApplication::translate("AddTorrentFile", "<none>", nullptr));
+ label->setText(QCoreApplication::translate("AddTorrentFile", "Torrent file:", nullptr));
+ browseDestination->setText(QCoreApplication::translate("AddTorrentFile", "Browse", nullptr));
+ label_7->setText(QCoreApplication::translate("AddTorrentFile", "Comment:", nullptr));
+ commentLabel->setText(QCoreApplication::translate("AddTorrentFile", "<none>", nullptr));
+ creatorLabel->setText(QCoreApplication::translate("AddTorrentFile", "<none>", nullptr));
+ sizeLabel->setText(QCoreApplication::translate("AddTorrentFile", "0", nullptr));
+ okButton->setText(QCoreApplication::translate("AddTorrentFile", "&OK", nullptr));
+ cancelButton->setText(QCoreApplication::translate("AddTorrentFile", "&Cancel", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/authenticationdialog.ui.h b/tests/auto/tools/uic/baseline/authenticationdialog.ui.h
index 16c9ce16a8..f8378b9a4e 100644
--- a/tests/auto/tools/uic/baseline/authenticationdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/authenticationdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'authenticationdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -103,12 +103,12 @@ public:
void retranslateUi(QDialog *Dialog)
{
- Dialog->setWindowTitle(QApplication::translate("Dialog", "Http authentication required", nullptr));
- label->setText(QApplication::translate("Dialog", "You need to supply a Username and a Password to access this site", nullptr));
- label_2->setText(QApplication::translate("Dialog", "Username:", nullptr));
- label_3->setText(QApplication::translate("Dialog", "Password:", nullptr));
- label_4->setText(QApplication::translate("Dialog", "Site:", nullptr));
- siteDescription->setText(QApplication::translate("Dialog", "%1 at %2", nullptr));
+ Dialog->setWindowTitle(QCoreApplication::translate("Dialog", "Http authentication required", nullptr));
+ label->setText(QCoreApplication::translate("Dialog", "You need to supply a Username and a Password to access this site", nullptr));
+ label_2->setText(QCoreApplication::translate("Dialog", "Username:", nullptr));
+ label_3->setText(QCoreApplication::translate("Dialog", "Password:", nullptr));
+ label_4->setText(QCoreApplication::translate("Dialog", "Site:", nullptr));
+ siteDescription->setText(QCoreApplication::translate("Dialog", "%1 at %2", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/backside.ui.h b/tests/auto/tools/uic/baseline/backside.ui.h
index e7053c632f..7f2b3662f3 100644
--- a/tests/auto/tools/uic/baseline/backside.ui.h
+++ b/tests/auto/tools/uic/baseline/backside.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'backside.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -144,40 +144,40 @@ public:
void retranslateUi(QWidget *BackSide)
{
- BackSide->setWindowTitle(QApplication::translate("BackSide", "BackSide", nullptr));
- groupBox->setTitle(QApplication::translate("BackSide", "Settings", nullptr));
- label->setText(QApplication::translate("BackSide", "Title:", nullptr));
- hostName->setText(QApplication::translate("BackSide", "Pad Navigator Example", nullptr));
- label_2->setText(QApplication::translate("BackSide", "Modified:", nullptr));
- label_3->setText(QApplication::translate("BackSide", "Extent", nullptr));
- groupBox_2->setTitle(QApplication::translate("BackSide", "Other input", nullptr));
+ BackSide->setWindowTitle(QCoreApplication::translate("BackSide", "BackSide", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("BackSide", "Settings", nullptr));
+ label->setText(QCoreApplication::translate("BackSide", "Title:", nullptr));
+ hostName->setText(QCoreApplication::translate("BackSide", "Pad Navigator Example", nullptr));
+ label_2->setText(QCoreApplication::translate("BackSide", "Modified:", nullptr));
+ label_3->setText(QCoreApplication::translate("BackSide", "Extent", nullptr));
+ groupBox_2->setTitle(QCoreApplication::translate("BackSide", "Other input", nullptr));
QTreeWidgetItem *___qtreewidgetitem = treeWidget->headerItem();
- ___qtreewidgetitem->setText(0, QApplication::translate("BackSide", "Widgets On Graphics View", nullptr));
+ ___qtreewidgetitem->setText(0, QCoreApplication::translate("BackSide", "Widgets On Graphics View", nullptr));
const bool __sortingEnabled = treeWidget->isSortingEnabled();
treeWidget->setSortingEnabled(false);
QTreeWidgetItem *___qtreewidgetitem1 = treeWidget->topLevelItem(0);
- ___qtreewidgetitem1->setText(0, QApplication::translate("BackSide", "QGraphicsProxyWidget", nullptr));
+ ___qtreewidgetitem1->setText(0, QCoreApplication::translate("BackSide", "QGraphicsProxyWidget", nullptr));
QTreeWidgetItem *___qtreewidgetitem2 = ___qtreewidgetitem1->child(0);
- ___qtreewidgetitem2->setText(0, QApplication::translate("BackSide", "QGraphicsWidget", nullptr));
+ ___qtreewidgetitem2->setText(0, QCoreApplication::translate("BackSide", "QGraphicsWidget", nullptr));
QTreeWidgetItem *___qtreewidgetitem3 = ___qtreewidgetitem2->child(0);
- ___qtreewidgetitem3->setText(0, QApplication::translate("BackSide", "QObject", nullptr));
+ ___qtreewidgetitem3->setText(0, QCoreApplication::translate("BackSide", "QObject", nullptr));
QTreeWidgetItem *___qtreewidgetitem4 = ___qtreewidgetitem2->child(1);
- ___qtreewidgetitem4->setText(0, QApplication::translate("BackSide", "QGraphicsItem", nullptr));
+ ___qtreewidgetitem4->setText(0, QCoreApplication::translate("BackSide", "QGraphicsItem", nullptr));
QTreeWidgetItem *___qtreewidgetitem5 = ___qtreewidgetitem2->child(2);
- ___qtreewidgetitem5->setText(0, QApplication::translate("BackSide", "QGraphicsLayoutItem", nullptr));
+ ___qtreewidgetitem5->setText(0, QCoreApplication::translate("BackSide", "QGraphicsLayoutItem", nullptr));
QTreeWidgetItem *___qtreewidgetitem6 = treeWidget->topLevelItem(1);
- ___qtreewidgetitem6->setText(0, QApplication::translate("BackSide", "QGraphicsGridLayout", nullptr));
+ ___qtreewidgetitem6->setText(0, QCoreApplication::translate("BackSide", "QGraphicsGridLayout", nullptr));
QTreeWidgetItem *___qtreewidgetitem7 = ___qtreewidgetitem6->child(0);
- ___qtreewidgetitem7->setText(0, QApplication::translate("BackSide", "QGraphicsLayout", nullptr));
+ ___qtreewidgetitem7->setText(0, QCoreApplication::translate("BackSide", "QGraphicsLayout", nullptr));
QTreeWidgetItem *___qtreewidgetitem8 = ___qtreewidgetitem7->child(0);
- ___qtreewidgetitem8->setText(0, QApplication::translate("BackSide", "QGraphicsLayoutItem", nullptr));
+ ___qtreewidgetitem8->setText(0, QCoreApplication::translate("BackSide", "QGraphicsLayoutItem", nullptr));
QTreeWidgetItem *___qtreewidgetitem9 = treeWidget->topLevelItem(2);
- ___qtreewidgetitem9->setText(0, QApplication::translate("BackSide", "QGraphicsLinearLayout", nullptr));
+ ___qtreewidgetitem9->setText(0, QCoreApplication::translate("BackSide", "QGraphicsLinearLayout", nullptr));
QTreeWidgetItem *___qtreewidgetitem10 = ___qtreewidgetitem9->child(0);
- ___qtreewidgetitem10->setText(0, QApplication::translate("BackSide", "QGraphicsLayout", nullptr));
+ ___qtreewidgetitem10->setText(0, QCoreApplication::translate("BackSide", "QGraphicsLayout", nullptr));
QTreeWidgetItem *___qtreewidgetitem11 = ___qtreewidgetitem10->child(0);
- ___qtreewidgetitem11->setText(0, QApplication::translate("BackSide", "QGraphicsLayoutItem", nullptr));
+ ___qtreewidgetitem11->setText(0, QCoreApplication::translate("BackSide", "QGraphicsLayoutItem", nullptr));
treeWidget->setSortingEnabled(__sortingEnabled);
} // retranslateUi
diff --git a/tests/auto/tools/uic/baseline/batchtranslation.ui.h b/tests/auto/tools/uic/baseline/batchtranslation.ui.h
index 8a4dc7a677..5e7278a581 100644
--- a/tests/auto/tools/uic/baseline/batchtranslation.ui.h
+++ b/tests/auto/tools/uic/baseline/batchtranslation.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'batchtranslation.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -90,7 +90,7 @@ public:
vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(databaseTranslationDialog);
groupBox->setObjectName(QString::fromUtf8("groupBox"));
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(4));
+ QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(groupBox->sizePolicy().hasHeightForWidth());
@@ -120,7 +120,7 @@ public:
groupBox_2 = new QGroupBox(databaseTranslationDialog);
groupBox_2->setObjectName(QString::fromUtf8("groupBox_2"));
- QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(1));
+ QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Minimum);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(groupBox_2->sizePolicy().hasHeightForWidth());
@@ -213,16 +213,16 @@ public:
void retranslateUi(QDialog *databaseTranslationDialog)
{
- databaseTranslationDialog->setWindowTitle(QApplication::translate("databaseTranslationDialog", "Qt Linguist - Batch Translation", nullptr));
- groupBox->setTitle(QApplication::translate("databaseTranslationDialog", "Options", nullptr));
- ckOnlyUntranslated->setText(QApplication::translate("databaseTranslationDialog", "Only translate entries with no translation", nullptr));
- ckMarkFinished->setText(QApplication::translate("databaseTranslationDialog", "Set translated entries to finished", nullptr));
- groupBox_2->setTitle(QApplication::translate("databaseTranslationDialog", "Phrase book preference", nullptr));
- moveUpButton->setText(QApplication::translate("databaseTranslationDialog", "Move up", nullptr));
- moveDownButton->setText(QApplication::translate("databaseTranslationDialog", "Move down", nullptr));
- label->setText(QApplication::translate("databaseTranslationDialog", "The batch translator will search through the selected phrasebooks in the order given above.", nullptr));
- runButton->setText(QApplication::translate("databaseTranslationDialog", "&Run", nullptr));
- cancelButton->setText(QApplication::translate("databaseTranslationDialog", "&Cancel", nullptr));
+ databaseTranslationDialog->setWindowTitle(QCoreApplication::translate("databaseTranslationDialog", "Qt Linguist - Batch Translation", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("databaseTranslationDialog", "Options", nullptr));
+ ckOnlyUntranslated->setText(QCoreApplication::translate("databaseTranslationDialog", "Only translate entries with no translation", nullptr));
+ ckMarkFinished->setText(QCoreApplication::translate("databaseTranslationDialog", "Set translated entries to finished", nullptr));
+ groupBox_2->setTitle(QCoreApplication::translate("databaseTranslationDialog", "Phrase book preference", nullptr));
+ moveUpButton->setText(QCoreApplication::translate("databaseTranslationDialog", "Move up", nullptr));
+ moveDownButton->setText(QCoreApplication::translate("databaseTranslationDialog", "Move down", nullptr));
+ label->setText(QCoreApplication::translate("databaseTranslationDialog", "The batch translator will search through the selected phrasebooks in the order given above.", nullptr));
+ runButton->setText(QCoreApplication::translate("databaseTranslationDialog", "&Run", nullptr));
+ cancelButton->setText(QCoreApplication::translate("databaseTranslationDialog", "&Cancel", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/bookmarkdialog.ui.h b/tests/auto/tools/uic/baseline/bookmarkdialog.ui.h
index b5a44998be..11caa3f130 100644
--- a/tests/auto/tools/uic/baseline/bookmarkdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/bookmarkdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'bookmarkdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -148,13 +148,13 @@ public:
void retranslateUi(QDialog *BookmarkDialog)
{
- BookmarkDialog->setWindowTitle(QApplication::translate("BookmarkDialog", "Add Bookmark", nullptr));
- label->setText(QApplication::translate("BookmarkDialog", "Bookmark:", nullptr));
- label_2->setText(QApplication::translate("BookmarkDialog", "Add in Folder:", nullptr));
- toolButton->setText(QApplication::translate("BookmarkDialog", "+", nullptr));
+ BookmarkDialog->setWindowTitle(QCoreApplication::translate("BookmarkDialog", "Add Bookmark", nullptr));
+ label->setText(QCoreApplication::translate("BookmarkDialog", "Bookmark:", nullptr));
+ label_2->setText(QCoreApplication::translate("BookmarkDialog", "Add in Folder:", nullptr));
+ toolButton->setText(QCoreApplication::translate("BookmarkDialog", "+", nullptr));
QTreeWidgetItem *___qtreewidgetitem = bookmarkWidget->headerItem();
- ___qtreewidgetitem->setText(0, QApplication::translate("BookmarkDialog", "1", nullptr));
- newFolderButton->setText(QApplication::translate("BookmarkDialog", "New Folder", nullptr));
+ ___qtreewidgetitem->setText(0, QCoreApplication::translate("BookmarkDialog", "1", nullptr));
+ newFolderButton->setText(QCoreApplication::translate("BookmarkDialog", "New Folder", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/bookwindow.ui.h b/tests/auto/tools/uic/baseline/bookwindow.ui.h
index 8fe5f000e2..fbdcb17bd2 100644
--- a/tests/auto/tools/uic/baseline/bookwindow.ui.h
+++ b/tests/auto/tools/uic/baseline/bookwindow.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'bookwindow.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -157,15 +157,15 @@ public:
void retranslateUi(QMainWindow *BookWindow)
{
- BookWindow->setWindowTitle(QApplication::translate("BookWindow", "Books", nullptr));
- groupBox->setTitle(QApplication::translate("BookWindow", "Books", nullptr));
- groupBox_2->setTitle(QApplication::translate("BookWindow", "Details", nullptr));
- label_5->setText(QApplication::translate("BookWindow", "<b>Title:</b>", nullptr));
- label_2_2_2_2->setText(QApplication::translate("BookWindow", "<b>Author: </b>", nullptr));
- label_3->setText(QApplication::translate("BookWindow", "<b>Genre:</b>", nullptr));
- label_4->setText(QApplication::translate("BookWindow", "<b>Year:</b>", nullptr));
+ BookWindow->setWindowTitle(QCoreApplication::translate("BookWindow", "Books", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("BookWindow", "Books", nullptr));
+ groupBox_2->setTitle(QCoreApplication::translate("BookWindow", "Details", nullptr));
+ label_5->setText(QCoreApplication::translate("BookWindow", "<b>Title:</b>", nullptr));
+ label_2_2_2_2->setText(QCoreApplication::translate("BookWindow", "<b>Author: </b>", nullptr));
+ label_3->setText(QCoreApplication::translate("BookWindow", "<b>Genre:</b>", nullptr));
+ label_4->setText(QCoreApplication::translate("BookWindow", "<b>Year:</b>", nullptr));
yearEdit->setPrefix(QString());
- label->setText(QApplication::translate("BookWindow", "<b>Rating:</b>", nullptr));
+ label->setText(QCoreApplication::translate("BookWindow", "<b>Rating:</b>", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/browserwidget.ui.h b/tests/auto/tools/uic/baseline/browserwidget.ui.h
index 3db93c34cf..7dcfb290f7 100644
--- a/tests/auto/tools/uic/baseline/browserwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/browserwidget.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'browserwidget.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -62,7 +62,7 @@ public:
vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
splitter_2 = new QSplitter(Browser);
splitter_2->setObjectName(QString::fromUtf8("splitter_2"));
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(7));
+ QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(splitter_2->sizePolicy().hasHeightForWidth());
@@ -70,7 +70,7 @@ public:
splitter_2->setOrientation(Qt::Horizontal);
connectionWidget = new ConnectionWidget(splitter_2);
connectionWidget->setObjectName(QString::fromUtf8("connectionWidget"));
- QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(13), static_cast<QSizePolicy::Policy>(7));
+ QSizePolicy sizePolicy1(QSizePolicy::Ignored, QSizePolicy::Expanding);
sizePolicy1.setHorizontalStretch(1);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(connectionWidget->sizePolicy().hasHeightForWidth());
@@ -78,7 +78,7 @@ public:
splitter_2->addWidget(connectionWidget);
table = new QTableView(splitter_2);
table->setObjectName(QString::fromUtf8("table"));
- QSizePolicy sizePolicy2(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(7));
+ QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy2.setHorizontalStretch(2);
sizePolicy2.setVerticalStretch(0);
sizePolicy2.setHeightForWidth(table->sizePolicy().hasHeightForWidth());
@@ -91,7 +91,7 @@ public:
groupBox = new QGroupBox(Browser);
groupBox->setObjectName(QString::fromUtf8("groupBox"));
- QSizePolicy sizePolicy3(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(3));
+ QSizePolicy sizePolicy3(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
sizePolicy3.setHorizontalStretch(0);
sizePolicy3.setVerticalStretch(0);
sizePolicy3.setHeightForWidth(groupBox->sizePolicy().hasHeightForWidth());
@@ -107,7 +107,7 @@ public:
vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
sqlEdit = new QTextEdit(groupBox);
sqlEdit->setObjectName(QString::fromUtf8("sqlEdit"));
- QSizePolicy sizePolicy4(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(3));
+ QSizePolicy sizePolicy4(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
sizePolicy4.setHorizontalStretch(0);
sizePolicy4.setVerticalStretch(0);
sizePolicy4.setHeightForWidth(sqlEdit->sizePolicy().hasHeightForWidth());
@@ -155,18 +155,18 @@ public:
void retranslateUi(QWidget *Browser)
{
- Browser->setWindowTitle(QApplication::translate("Browser", "Qt SQL Browser", nullptr));
- insertRowAction->setText(QApplication::translate("Browser", "&Insert Row", nullptr));
-#ifndef QT_NO_STATUSTIP
- insertRowAction->setStatusTip(QApplication::translate("Browser", "Inserts a new Row", nullptr));
-#endif // QT_NO_STATUSTIP
- deleteRowAction->setText(QApplication::translate("Browser", "&Delete Row", nullptr));
-#ifndef QT_NO_STATUSTIP
- deleteRowAction->setStatusTip(QApplication::translate("Browser", "Deletes the current Row", nullptr));
-#endif // QT_NO_STATUSTIP
- groupBox->setTitle(QApplication::translate("Browser", "SQL Query", nullptr));
- clearButton->setText(QApplication::translate("Browser", "&Clear", nullptr));
- submitButton->setText(QApplication::translate("Browser", "&Submit", nullptr));
+ Browser->setWindowTitle(QCoreApplication::translate("Browser", "Qt SQL Browser", nullptr));
+ insertRowAction->setText(QCoreApplication::translate("Browser", "&Insert Row", nullptr));
+#if QT_CONFIG(statustip)
+ insertRowAction->setStatusTip(QCoreApplication::translate("Browser", "Inserts a new Row", nullptr));
+#endif // QT_CONFIG(statustip)
+ deleteRowAction->setText(QCoreApplication::translate("Browser", "&Delete Row", nullptr));
+#if QT_CONFIG(statustip)
+ deleteRowAction->setStatusTip(QCoreApplication::translate("Browser", "Deletes the current Row", nullptr));
+#endif // QT_CONFIG(statustip)
+ groupBox->setTitle(QCoreApplication::translate("Browser", "SQL Query", nullptr));
+ clearButton->setText(QCoreApplication::translate("Browser", "&Clear", nullptr));
+ submitButton->setText(QCoreApplication::translate("Browser", "&Submit", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/bug18156QTreeWidget.ui.h b/tests/auto/tools/uic/baseline/bug18156QTreeWidget.ui.h
index 47f8f22132..4e7186041e 100644
--- a/tests/auto/tools/uic/baseline/bug18156QTreeWidget.ui.h
+++ b/tests/auto/tools/uic/baseline/bug18156QTreeWidget.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'bug18156QTreeWidget.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -57,9 +57,9 @@ public:
void retranslateUi(QDialog *Dialog)
{
- Dialog->setWindowTitle(QApplication::translate("Dialog", "Dialog", nullptr));
+ Dialog->setWindowTitle(QCoreApplication::translate("Dialog", "Dialog", nullptr));
QTreeWidgetItem *___qtreewidgetitem = treeWidget->headerItem();
- ___qtreewidgetitem->setText(1, QApplication::translate("Dialog", "4", nullptr));
+ ___qtreewidgetitem->setText(1, QCoreApplication::translate("Dialog", "4", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/buttongroup.ui.h b/tests/auto/tools/uic/baseline/buttongroup.ui.h
index 87814dcba1..f48db1d593 100644
--- a/tests/auto/tools/uic/baseline/buttongroup.ui.h
+++ b/tests/auto/tools/uic/baseline/buttongroup.ui.h
@@ -195,14 +195,14 @@ public:
void retranslateUi(QWidget *Form)
{
- Form->setWindowTitle(QApplication::translate("Form", "Easing curves", nullptr));
- groupBox_2->setTitle(QApplication::translate("Form", "Path type", nullptr));
- lineRadio->setText(QApplication::translate("Form", "Line", nullptr));
- circleRadio->setText(QApplication::translate("Form", "Circle", nullptr));
- groupBox->setTitle(QApplication::translate("Form", "Properties", nullptr));
- label->setText(QApplication::translate("Form", "Period", nullptr));
- label_3->setText(QApplication::translate("Form", "Overshoot", nullptr));
- label_2->setText(QApplication::translate("Form", "Amplitude", nullptr));
+ Form->setWindowTitle(QCoreApplication::translate("Form", "Easing curves", nullptr));
+ groupBox_2->setTitle(QCoreApplication::translate("Form", "Path type", nullptr));
+ lineRadio->setText(QCoreApplication::translate("Form", "Line", nullptr));
+ circleRadio->setText(QCoreApplication::translate("Form", "Circle", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("Form", "Properties", nullptr));
+ label->setText(QCoreApplication::translate("Form", "Period", nullptr));
+ label_3->setText(QCoreApplication::translate("Form", "Overshoot", nullptr));
+ label_2->setText(QCoreApplication::translate("Form", "Amplitude", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/calculator.ui.h b/tests/auto/tools/uic/baseline/calculator.ui.h
index 0387ee472b..bfe272f8ea 100644
--- a/tests/auto/tools/uic/baseline/calculator.ui.h
+++ b/tests/auto/tools/uic/baseline/calculator.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'calculator.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -156,34 +156,34 @@ public:
void retranslateUi(QWidget *Calculator)
{
- Calculator->setWindowTitle(QApplication::translate("Calculator", "Calculator", nullptr));
- backspaceButton->setText(QApplication::translate("Calculator", "Backspace", nullptr));
- clearButton->setText(QApplication::translate("Calculator", "Clear", nullptr));
- clearAllButton->setText(QApplication::translate("Calculator", "Clear All", nullptr));
- clearMemoryButton->setText(QApplication::translate("Calculator", "MC", nullptr));
- readMemoryButton->setText(QApplication::translate("Calculator", "MR", nullptr));
- setMemoryButton->setText(QApplication::translate("Calculator", "MS", nullptr));
- addToMemoryButton->setText(QApplication::translate("Calculator", "M+", nullptr));
- sevenButton->setText(QApplication::translate("Calculator", "7", nullptr));
- eightButton->setText(QApplication::translate("Calculator", "8", nullptr));
- nineButton->setText(QApplication::translate("Calculator", "9", nullptr));
- fourButton->setText(QApplication::translate("Calculator", "4", nullptr));
- fiveButton->setText(QApplication::translate("Calculator", "5", nullptr));
- sixButton->setText(QApplication::translate("Calculator", "6", nullptr));
- oneButton->setText(QApplication::translate("Calculator", "1", nullptr));
- twoButton->setText(QApplication::translate("Calculator", "2", nullptr));
- threeButton->setText(QApplication::translate("Calculator", "3", nullptr));
- zeroButton->setText(QApplication::translate("Calculator", "0", nullptr));
- pointButton->setText(QApplication::translate("Calculator", ".", nullptr));
- changeSignButton->setText(QApplication::translate("Calculator", "+-", nullptr));
- plusButton->setText(QApplication::translate("Calculator", "+", nullptr));
- divisionButton->setText(QApplication::translate("Calculator", "/", nullptr));
- timesButton->setText(QApplication::translate("Calculator", "*", nullptr));
- minusButton->setText(QApplication::translate("Calculator", "-", nullptr));
- squareRootButton->setText(QApplication::translate("Calculator", "Sqrt", nullptr));
- powerButton->setText(QApplication::translate("Calculator", "x^2", nullptr));
- reciprocalButton->setText(QApplication::translate("Calculator", "1/x", nullptr));
- equalButton->setText(QApplication::translate("Calculator", "=", nullptr));
+ Calculator->setWindowTitle(QCoreApplication::translate("Calculator", "Calculator", nullptr));
+ backspaceButton->setText(QCoreApplication::translate("Calculator", "Backspace", nullptr));
+ clearButton->setText(QCoreApplication::translate("Calculator", "Clear", nullptr));
+ clearAllButton->setText(QCoreApplication::translate("Calculator", "Clear All", nullptr));
+ clearMemoryButton->setText(QCoreApplication::translate("Calculator", "MC", nullptr));
+ readMemoryButton->setText(QCoreApplication::translate("Calculator", "MR", nullptr));
+ setMemoryButton->setText(QCoreApplication::translate("Calculator", "MS", nullptr));
+ addToMemoryButton->setText(QCoreApplication::translate("Calculator", "M+", nullptr));
+ sevenButton->setText(QCoreApplication::translate("Calculator", "7", nullptr));
+ eightButton->setText(QCoreApplication::translate("Calculator", "8", nullptr));
+ nineButton->setText(QCoreApplication::translate("Calculator", "9", nullptr));
+ fourButton->setText(QCoreApplication::translate("Calculator", "4", nullptr));
+ fiveButton->setText(QCoreApplication::translate("Calculator", "5", nullptr));
+ sixButton->setText(QCoreApplication::translate("Calculator", "6", nullptr));
+ oneButton->setText(QCoreApplication::translate("Calculator", "1", nullptr));
+ twoButton->setText(QCoreApplication::translate("Calculator", "2", nullptr));
+ threeButton->setText(QCoreApplication::translate("Calculator", "3", nullptr));
+ zeroButton->setText(QCoreApplication::translate("Calculator", "0", nullptr));
+ pointButton->setText(QCoreApplication::translate("Calculator", ".", nullptr));
+ changeSignButton->setText(QCoreApplication::translate("Calculator", "+-", nullptr));
+ plusButton->setText(QCoreApplication::translate("Calculator", "+", nullptr));
+ divisionButton->setText(QCoreApplication::translate("Calculator", "/", nullptr));
+ timesButton->setText(QCoreApplication::translate("Calculator", "*", nullptr));
+ minusButton->setText(QCoreApplication::translate("Calculator", "-", nullptr));
+ squareRootButton->setText(QCoreApplication::translate("Calculator", "Sqrt", nullptr));
+ powerButton->setText(QCoreApplication::translate("Calculator", "x^2", nullptr));
+ reciprocalButton->setText(QCoreApplication::translate("Calculator", "1/x", nullptr));
+ equalButton->setText(QCoreApplication::translate("Calculator", "=", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/calculatorform.ui.h b/tests/auto/tools/uic/baseline/calculatorform.ui.h
index f4661c6237..ab55c8ad97 100644
--- a/tests/auto/tools/uic/baseline/calculatorform.ui.h
+++ b/tests/auto/tools/uic/baseline/calculatorform.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'calculatorform.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -45,7 +45,7 @@ public:
if (CalculatorForm->objectName().isEmpty())
CalculatorForm->setObjectName(QString::fromUtf8("CalculatorForm"));
CalculatorForm->resize(276, 98);
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(5));
+ QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(CalculatorForm->sizePolicy().hasHeightForWidth());
@@ -170,13 +170,13 @@ public:
void retranslateUi(QWidget *CalculatorForm)
{
- CalculatorForm->setWindowTitle(QApplication::translate("CalculatorForm", "Calculator Builder", nullptr));
- label->setText(QApplication::translate("CalculatorForm", "Input 1", nullptr));
- label_3->setText(QApplication::translate("CalculatorForm", "+", nullptr));
- label_2->setText(QApplication::translate("CalculatorForm", "Input 2", nullptr));
- label_3_2->setText(QApplication::translate("CalculatorForm", "=", nullptr));
- label_2_2_2->setText(QApplication::translate("CalculatorForm", "Output", nullptr));
- outputWidget->setText(QApplication::translate("CalculatorForm", "0", nullptr));
+ CalculatorForm->setWindowTitle(QCoreApplication::translate("CalculatorForm", "Calculator Builder", nullptr));
+ label->setText(QCoreApplication::translate("CalculatorForm", "Input 1", nullptr));
+ label_3->setText(QCoreApplication::translate("CalculatorForm", "+", nullptr));
+ label_2->setText(QCoreApplication::translate("CalculatorForm", "Input 2", nullptr));
+ label_3_2->setText(QCoreApplication::translate("CalculatorForm", "=", nullptr));
+ label_2_2_2->setText(QCoreApplication::translate("CalculatorForm", "Output", nullptr));
+ outputWidget->setText(QCoreApplication::translate("CalculatorForm", "0", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/certificateinfo.ui.h b/tests/auto/tools/uic/baseline/certificateinfo.ui.h
index 2aa47d40ad..4a70f86c3b 100644
--- a/tests/auto/tools/uic/baseline/certificateinfo.ui.h
+++ b/tests/auto/tools/uic/baseline/certificateinfo.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'certificateinfo.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -90,9 +90,9 @@ public:
void retranslateUi(QDialog *CertificateInfo)
{
- CertificateInfo->setWindowTitle(QApplication::translate("CertificateInfo", "Display Certificate Information", nullptr));
- groupBox->setTitle(QApplication::translate("CertificateInfo", "Certification Path", nullptr));
- groupBox_2->setTitle(QApplication::translate("CertificateInfo", "Certificate Information", nullptr));
+ CertificateInfo->setWindowTitle(QCoreApplication::translate("CertificateInfo", "Display Certificate Information", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("CertificateInfo", "Certification Path", nullptr));
+ groupBox_2->setTitle(QCoreApplication::translate("CertificateInfo", "Certificate Information", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/chatdialog.ui.h b/tests/auto/tools/uic/baseline/chatdialog.ui.h
index ace6951669..2a1ba2e84c 100644
--- a/tests/auto/tools/uic/baseline/chatdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/chatdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'chatdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -97,8 +97,8 @@ public:
void retranslateUi(QDialog *ChatDialog)
{
- ChatDialog->setWindowTitle(QApplication::translate("ChatDialog", "Chat", nullptr));
- label->setText(QApplication::translate("ChatDialog", "Message:", nullptr));
+ ChatDialog->setWindowTitle(QCoreApplication::translate("ChatDialog", "Chat", nullptr));
+ label->setText(QCoreApplication::translate("ChatDialog", "Message:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/chatmainwindow.ui.h b/tests/auto/tools/uic/baseline/chatmainwindow.ui.h
index 8d4ccd53ae..220d44300b 100644
--- a/tests/auto/tools/uic/baseline/chatmainwindow.ui.h
+++ b/tests/auto/tools/uic/baseline/chatmainwindow.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'chatmainwindow.ui'
**
-** Created by: Qt User Interface Compiler version 5.9.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -99,7 +99,7 @@ public:
sendButton = new QPushButton(centralwidget);
sendButton->setObjectName(QString::fromUtf8("sendButton"));
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(1), static_cast<QSizePolicy::Policy>(0));
+ QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(sendButton->sizePolicy().hasHeightForWidth());
@@ -125,9 +125,9 @@ public:
statusbar = new QStatusBar(ChatMainWindow);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
ChatMainWindow->setStatusBar(statusbar);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(messageLineEdit);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
QWidget::setTabOrder(chatHistory, messageLineEdit);
QWidget::setTabOrder(messageLineEdit, sendButton);
@@ -147,29 +147,29 @@ public:
void retranslateUi(QMainWindow *ChatMainWindow)
{
- ChatMainWindow->setWindowTitle(QApplication::translate("ChatMainWindow", "Qt D-Bus Chat", nullptr));
- actionQuit->setText(QApplication::translate("ChatMainWindow", "Quit", nullptr));
-#ifndef QT_NO_SHORTCUT
- actionQuit->setShortcut(QApplication::translate("ChatMainWindow", "Ctrl+Q", nullptr));
-#endif // QT_NO_SHORTCUT
- actionAboutQt->setText(QApplication::translate("ChatMainWindow", "About Qt...", nullptr));
- actionChangeNickname->setText(QApplication::translate("ChatMainWindow", "Change nickname...", nullptr));
-#ifndef QT_NO_SHORTCUT
- actionChangeNickname->setShortcut(QApplication::translate("ChatMainWindow", "Ctrl+N", nullptr));
-#endif // QT_NO_SHORTCUT
-#ifndef QT_NO_TOOLTIP
- chatHistory->setToolTip(QApplication::translate("ChatMainWindow", "Messages sent and received from other users", nullptr));
-#endif // QT_NO_TOOLTIP
- label->setText(QApplication::translate("ChatMainWindow", "Message:", nullptr));
-#ifndef QT_NO_TOOLTIP
- sendButton->setToolTip(QApplication::translate("ChatMainWindow", "Sends a message to other people", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_WHATSTHIS
+ ChatMainWindow->setWindowTitle(QCoreApplication::translate("ChatMainWindow", "Qt D-Bus Chat", nullptr));
+ actionQuit->setText(QCoreApplication::translate("ChatMainWindow", "Quit", nullptr));
+#if QT_CONFIG(shortcut)
+ actionQuit->setShortcut(QCoreApplication::translate("ChatMainWindow", "Ctrl+Q", nullptr));
+#endif // QT_CONFIG(shortcut)
+ actionAboutQt->setText(QCoreApplication::translate("ChatMainWindow", "About Qt...", nullptr));
+ actionChangeNickname->setText(QCoreApplication::translate("ChatMainWindow", "Change nickname...", nullptr));
+#if QT_CONFIG(shortcut)
+ actionChangeNickname->setShortcut(QCoreApplication::translate("ChatMainWindow", "Ctrl+N", nullptr));
+#endif // QT_CONFIG(shortcut)
+#if QT_CONFIG(tooltip)
+ chatHistory->setToolTip(QCoreApplication::translate("ChatMainWindow", "Messages sent and received from other users", nullptr));
+#endif // QT_CONFIG(tooltip)
+ label->setText(QCoreApplication::translate("ChatMainWindow", "Message:", nullptr));
+#if QT_CONFIG(tooltip)
+ sendButton->setToolTip(QCoreApplication::translate("ChatMainWindow", "Sends a message to other people", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(whatsthis)
sendButton->setWhatsThis(QString());
-#endif // QT_NO_WHATSTHIS
- sendButton->setText(QApplication::translate("ChatMainWindow", "Send", nullptr));
- menuQuit->setTitle(QApplication::translate("ChatMainWindow", "Help", nullptr));
- menuFile->setTitle(QApplication::translate("ChatMainWindow", "File", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ sendButton->setText(QCoreApplication::translate("ChatMainWindow", "Send", nullptr));
+ menuQuit->setTitle(QCoreApplication::translate("ChatMainWindow", "Help", nullptr));
+ menuFile->setTitle(QCoreApplication::translate("ChatMainWindow", "File", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/chatsetnickname.ui.h b/tests/auto/tools/uic/baseline/chatsetnickname.ui.h
index c73dfb2c6e..0e93828c90 100644
--- a/tests/auto/tools/uic/baseline/chatsetnickname.ui.h
+++ b/tests/auto/tools/uic/baseline/chatsetnickname.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'chatsetnickname.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -39,7 +39,7 @@ public:
if (NicknameDialog->objectName().isEmpty())
NicknameDialog->setObjectName(QString::fromUtf8("NicknameDialog"));
NicknameDialog->resize(396, 105);
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(1), static_cast<QSizePolicy::Policy>(1));
+ QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(NicknameDialog->sizePolicy().hasHeightForWidth());
@@ -112,10 +112,10 @@ public:
void retranslateUi(QDialog *NicknameDialog)
{
- NicknameDialog->setWindowTitle(QApplication::translate("NicknameDialog", "Set nickname", nullptr));
- label->setText(QApplication::translate("NicknameDialog", "New nickname:", nullptr));
- okButton->setText(QApplication::translate("NicknameDialog", "OK", nullptr));
- cancelButton->setText(QApplication::translate("NicknameDialog", "Cancel", nullptr));
+ NicknameDialog->setWindowTitle(QCoreApplication::translate("NicknameDialog", "Set nickname", nullptr));
+ label->setText(QCoreApplication::translate("NicknameDialog", "New nickname:", nullptr));
+ okButton->setText(QCoreApplication::translate("NicknameDialog", "OK", nullptr));
+ cancelButton->setText(QCoreApplication::translate("NicknameDialog", "Cancel", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/config.ui.h b/tests/auto/tools/uic/baseline/config.ui.h
index 8287e0b1ac..153718aca1 100644
--- a/tests/auto/tools/uic/baseline/config.ui.h
+++ b/tests/auto/tools/uic/baseline/config.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'config.ui'
**
-** Created by: Qt User Interface Compiler version 5.10.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -706,44 +706,44 @@ public:
void retranslateUi(QDialog *Config)
{
- Config->setWindowTitle(QApplication::translate("Config", "Configure", nullptr));
- ButtonGroup1->setTitle(QApplication::translate("Config", "Size", nullptr));
- size_176_220->setText(QApplication::translate("Config", "176x220 \"SmartPhone\"", nullptr));
- size_240_320->setText(QApplication::translate("Config", "240x320 \"PDA\"", nullptr));
- size_320_240->setText(QApplication::translate("Config", "320x240 \"TV\" / \"QVGA\"", nullptr));
- size_640_480->setText(QApplication::translate("Config", "640x480 \"VGA\"", nullptr));
- size_800_600->setText(QApplication::translate("Config", "800x600", nullptr));
- size_1024_768->setText(QApplication::translate("Config", "1024x768", nullptr));
- size_custom->setText(QApplication::translate("Config", "Custom", nullptr));
- ButtonGroup2->setTitle(QApplication::translate("Config", "Depth", nullptr));
- depth_1->setText(QApplication::translate("Config", "1 bit monochrome", nullptr));
- depth_4gray->setText(QApplication::translate("Config", "4 bit grayscale", nullptr));
- depth_8->setText(QApplication::translate("Config", "8 bit", nullptr));
- depth_12->setText(QApplication::translate("Config", "12 (16) bit", nullptr));
- depth_15->setText(QApplication::translate("Config", "15 bit", nullptr));
- depth_16->setText(QApplication::translate("Config", "16 bit", nullptr));
- depth_18->setText(QApplication::translate("Config", "18 bit", nullptr));
- depth_24->setText(QApplication::translate("Config", "24 bit", nullptr));
- depth_32->setText(QApplication::translate("Config", "32 bit", nullptr));
- depth_32_argb->setText(QApplication::translate("Config", "32 bit ARGB", nullptr));
- TextLabel1_3->setText(QApplication::translate("Config", "Skin", nullptr));
- skin->setItemText(0, QApplication::translate("Config", "None", nullptr));
-
- touchScreen->setText(QApplication::translate("Config", "Emulate touch screen (no mouse move)", nullptr));
- lcdScreen->setText(QApplication::translate("Config", "Emulate LCD screen (Only with fixed zoom of 3.0 times magnification)", nullptr));
- TextLabel1->setText(QApplication::translate("Config", "<p>Note that any applications using the virtual framebuffer will be terminated if you change the Size or Depth <i>above</i>. You may freely modify the Gamma <i>below</i>.", nullptr));
- GroupBox1->setTitle(QApplication::translate("Config", "Gamma", nullptr));
- TextLabel3->setText(QApplication::translate("Config", "Blue", nullptr));
- blabel->setText(QApplication::translate("Config", "1.0", nullptr));
- TextLabel2->setText(QApplication::translate("Config", "Green", nullptr));
- glabel->setText(QApplication::translate("Config", "1.0", nullptr));
- TextLabel7->setText(QApplication::translate("Config", "All", nullptr));
- TextLabel8->setText(QApplication::translate("Config", "1.0", nullptr));
- TextLabel1_2->setText(QApplication::translate("Config", "Red", nullptr));
- rlabel->setText(QApplication::translate("Config", "1.0", nullptr));
- PushButton3->setText(QApplication::translate("Config", "Set all to 1.0", nullptr));
- buttonOk->setText(QApplication::translate("Config", "&OK", nullptr));
- buttonCancel->setText(QApplication::translate("Config", "&Cancel", nullptr));
+ Config->setWindowTitle(QCoreApplication::translate("Config", "Configure", nullptr));
+ ButtonGroup1->setTitle(QCoreApplication::translate("Config", "Size", nullptr));
+ size_176_220->setText(QCoreApplication::translate("Config", "176x220 \"SmartPhone\"", nullptr));
+ size_240_320->setText(QCoreApplication::translate("Config", "240x320 \"PDA\"", nullptr));
+ size_320_240->setText(QCoreApplication::translate("Config", "320x240 \"TV\" / \"QVGA\"", nullptr));
+ size_640_480->setText(QCoreApplication::translate("Config", "640x480 \"VGA\"", nullptr));
+ size_800_600->setText(QCoreApplication::translate("Config", "800x600", nullptr));
+ size_1024_768->setText(QCoreApplication::translate("Config", "1024x768", nullptr));
+ size_custom->setText(QCoreApplication::translate("Config", "Custom", nullptr));
+ ButtonGroup2->setTitle(QCoreApplication::translate("Config", "Depth", nullptr));
+ depth_1->setText(QCoreApplication::translate("Config", "1 bit monochrome", nullptr));
+ depth_4gray->setText(QCoreApplication::translate("Config", "4 bit grayscale", nullptr));
+ depth_8->setText(QCoreApplication::translate("Config", "8 bit", nullptr));
+ depth_12->setText(QCoreApplication::translate("Config", "12 (16) bit", nullptr));
+ depth_15->setText(QCoreApplication::translate("Config", "15 bit", nullptr));
+ depth_16->setText(QCoreApplication::translate("Config", "16 bit", nullptr));
+ depth_18->setText(QCoreApplication::translate("Config", "18 bit", nullptr));
+ depth_24->setText(QCoreApplication::translate("Config", "24 bit", nullptr));
+ depth_32->setText(QCoreApplication::translate("Config", "32 bit", nullptr));
+ depth_32_argb->setText(QCoreApplication::translate("Config", "32 bit ARGB", nullptr));
+ TextLabel1_3->setText(QCoreApplication::translate("Config", "Skin", nullptr));
+ skin->setItemText(0, QCoreApplication::translate("Config", "None", nullptr));
+
+ touchScreen->setText(QCoreApplication::translate("Config", "Emulate touch screen (no mouse move)", nullptr));
+ lcdScreen->setText(QCoreApplication::translate("Config", "Emulate LCD screen (Only with fixed zoom of 3.0 times magnification)", nullptr));
+ TextLabel1->setText(QCoreApplication::translate("Config", "<p>Note that any applications using the virtual framebuffer will be terminated if you change the Size or Depth <i>above</i>. You may freely modify the Gamma <i>below</i>.", nullptr));
+ GroupBox1->setTitle(QCoreApplication::translate("Config", "Gamma", nullptr));
+ TextLabel3->setText(QCoreApplication::translate("Config", "Blue", nullptr));
+ blabel->setText(QCoreApplication::translate("Config", "1.0", nullptr));
+ TextLabel2->setText(QCoreApplication::translate("Config", "Green", nullptr));
+ glabel->setText(QCoreApplication::translate("Config", "1.0", nullptr));
+ TextLabel7->setText(QCoreApplication::translate("Config", "All", nullptr));
+ TextLabel8->setText(QCoreApplication::translate("Config", "1.0", nullptr));
+ TextLabel1_2->setText(QCoreApplication::translate("Config", "Red", nullptr));
+ rlabel->setText(QCoreApplication::translate("Config", "1.0", nullptr));
+ PushButton3->setText(QCoreApplication::translate("Config", "Set all to 1.0", nullptr));
+ buttonOk->setText(QCoreApplication::translate("Config", "&OK", nullptr));
+ buttonCancel->setText(QCoreApplication::translate("Config", "&Cancel", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/connectdialog.ui.h b/tests/auto/tools/uic/baseline/connectdialog.ui.h
index a470a6705d..1e91b498f4 100644
--- a/tests/auto/tools/uic/baseline/connectdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/connectdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'connectdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -126,12 +126,12 @@ public:
void retranslateUi(QDialog *ConnectDialog)
{
- ConnectDialog->setWindowTitle(QApplication::translate("ConnectDialog", "Configure Connection", nullptr));
- signalGroupBox->setTitle(QApplication::translate("ConnectDialog", "GroupBox", nullptr));
- editSignalsButton->setText(QApplication::translate("ConnectDialog", "Edit...", nullptr));
- slotGroupBox->setTitle(QApplication::translate("ConnectDialog", "GroupBox", nullptr));
- editSlotsButton->setText(QApplication::translate("ConnectDialog", "Edit...", nullptr));
- showAllCheckBox->setText(QApplication::translate("ConnectDialog", "Show signals and slots inherited from QWidget", nullptr));
+ ConnectDialog->setWindowTitle(QCoreApplication::translate("ConnectDialog", "Configure Connection", nullptr));
+ signalGroupBox->setTitle(QCoreApplication::translate("ConnectDialog", "GroupBox", nullptr));
+ editSignalsButton->setText(QCoreApplication::translate("ConnectDialog", "Edit...", nullptr));
+ slotGroupBox->setTitle(QCoreApplication::translate("ConnectDialog", "GroupBox", nullptr));
+ editSlotsButton->setText(QCoreApplication::translate("ConnectDialog", "Edit...", nullptr));
+ showAllCheckBox->setText(QCoreApplication::translate("ConnectDialog", "Show signals and slots inherited from QWidget", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/controller.ui.h b/tests/auto/tools/uic/baseline/controller.ui.h
index 72b0956472..3ebfad187f 100644
--- a/tests/auto/tools/uic/baseline/controller.ui.h
+++ b/tests/auto/tools/uic/baseline/controller.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'controller.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -75,12 +75,12 @@ public:
void retranslateUi(QWidget *Controller)
{
- Controller->setWindowTitle(QApplication::translate("Controller", "Controller", nullptr));
- label->setText(QApplication::translate("Controller", "Controller", nullptr));
- decelerate->setText(QApplication::translate("Controller", "Decelerate", nullptr));
- accelerate->setText(QApplication::translate("Controller", "Accelerate", nullptr));
- right->setText(QApplication::translate("Controller", "Right", nullptr));
- left->setText(QApplication::translate("Controller", "Left", nullptr));
+ Controller->setWindowTitle(QCoreApplication::translate("Controller", "Controller", nullptr));
+ label->setText(QCoreApplication::translate("Controller", "Controller", nullptr));
+ decelerate->setText(QCoreApplication::translate("Controller", "Decelerate", nullptr));
+ accelerate->setText(QCoreApplication::translate("Controller", "Accelerate", nullptr));
+ right->setText(QCoreApplication::translate("Controller", "Right", nullptr));
+ left->setText(QCoreApplication::translate("Controller", "Left", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/cookies.ui.h b/tests/auto/tools/uic/baseline/cookies.ui.h
index 144c306874..2cc21888b1 100644
--- a/tests/auto/tools/uic/baseline/cookies.ui.h
+++ b/tests/auto/tools/uic/baseline/cookies.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'cookies.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -91,9 +91,9 @@ public:
void retranslateUi(QDialog *CookiesDialog)
{
- CookiesDialog->setWindowTitle(QApplication::translate("CookiesDialog", "Cookies", nullptr));
- removeButton->setText(QApplication::translate("CookiesDialog", "&Remove", nullptr));
- removeAllButton->setText(QApplication::translate("CookiesDialog", "Remove &All Cookies", nullptr));
+ CookiesDialog->setWindowTitle(QCoreApplication::translate("CookiesDialog", "Cookies", nullptr));
+ removeButton->setText(QCoreApplication::translate("CookiesDialog", "&Remove", nullptr));
+ removeAllButton->setText(QCoreApplication::translate("CookiesDialog", "Remove &All Cookies", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/cookiesexceptions.ui.h b/tests/auto/tools/uic/baseline/cookiesexceptions.ui.h
index a3bf7a449e..77212cf2f3 100644
--- a/tests/auto/tools/uic/baseline/cookiesexceptions.ui.h
+++ b/tests/auto/tools/uic/baseline/cookiesexceptions.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'cookiesexceptions.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -158,15 +158,15 @@ public:
void retranslateUi(QDialog *CookiesExceptionsDialog)
{
- CookiesExceptionsDialog->setWindowTitle(QApplication::translate("CookiesExceptionsDialog", "Cookie Exceptions", nullptr));
- newExceptionGroupBox->setTitle(QApplication::translate("CookiesExceptionsDialog", "New Exception", nullptr));
- label->setText(QApplication::translate("CookiesExceptionsDialog", "Domain:", nullptr));
- blockButton->setText(QApplication::translate("CookiesExceptionsDialog", "Block", nullptr));
- allowForSessionButton->setText(QApplication::translate("CookiesExceptionsDialog", "Allow For Session", nullptr));
- allowButton->setText(QApplication::translate("CookiesExceptionsDialog", "Allow", nullptr));
- ExceptionsGroupBox->setTitle(QApplication::translate("CookiesExceptionsDialog", "Exceptions", nullptr));
- removeButton->setText(QApplication::translate("CookiesExceptionsDialog", "&Remove", nullptr));
- removeAllButton->setText(QApplication::translate("CookiesExceptionsDialog", "Remove &All", nullptr));
+ CookiesExceptionsDialog->setWindowTitle(QCoreApplication::translate("CookiesExceptionsDialog", "Cookie Exceptions", nullptr));
+ newExceptionGroupBox->setTitle(QCoreApplication::translate("CookiesExceptionsDialog", "New Exception", nullptr));
+ label->setText(QCoreApplication::translate("CookiesExceptionsDialog", "Domain:", nullptr));
+ blockButton->setText(QCoreApplication::translate("CookiesExceptionsDialog", "Block", nullptr));
+ allowForSessionButton->setText(QCoreApplication::translate("CookiesExceptionsDialog", "Allow For Session", nullptr));
+ allowButton->setText(QCoreApplication::translate("CookiesExceptionsDialog", "Allow", nullptr));
+ ExceptionsGroupBox->setTitle(QCoreApplication::translate("CookiesExceptionsDialog", "Exceptions", nullptr));
+ removeButton->setText(QCoreApplication::translate("CookiesExceptionsDialog", "&Remove", nullptr));
+ removeAllButton->setText(QCoreApplication::translate("CookiesExceptionsDialog", "Remove &All", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/default.ui.h b/tests/auto/tools/uic/baseline/default.ui.h
index fafff9d728..fbbe81d0b8 100644
--- a/tests/auto/tools/uic/baseline/default.ui.h
+++ b/tests/auto/tools/uic/baseline/default.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'default.ui'
**
-** Created by: Qt User Interface Compiler version 5.10.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -192,13 +192,13 @@ public:
statusbar = new QStatusBar(MainWindow);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
MainWindow->setStatusBar(statusbar);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
nameLabel->setBuddy(nameCombo);
ageLabel->setBuddy(ageSpinBox);
passwordLabel->setBuddy(passwordEdit);
label->setBuddy(professionList);
countryLabel->setBuddy(professionList);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
QWidget::setTabOrder(maleRadioButton, femaleRadioButton);
QWidget::setTabOrder(femaleRadioButton, ageSpinBox);
QWidget::setTabOrder(ageSpinBox, passwordEdit);
@@ -226,84 +226,84 @@ public:
void retranslateUi(QMainWindow *MainWindow)
{
- MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr));
- exitAction->setText(QApplication::translate("MainWindow", "&Exit", nullptr));
- aboutQtAction->setText(QApplication::translate("MainWindow", "About Qt", nullptr));
- editStyleAction->setText(QApplication::translate("MainWindow", "Edit &Style", nullptr));
- aboutAction->setText(QApplication::translate("MainWindow", "About", nullptr));
- nameLabel->setText(QApplication::translate("MainWindow", "&Name:", nullptr));
- nameCombo->setItemText(0, QApplication::translate("MainWindow", "Girish", nullptr));
- nameCombo->setItemText(1, QApplication::translate("MainWindow", "Jasmin", nullptr));
- nameCombo->setItemText(2, QApplication::translate("MainWindow", "Simon", nullptr));
- nameCombo->setItemText(3, QApplication::translate("MainWindow", "Zack", nullptr));
-
-#ifndef QT_NO_TOOLTIP
- nameCombo->setToolTip(QApplication::translate("MainWindow", "Specify your name", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- femaleRadioButton->setToolTip(QApplication::translate("MainWindow", "Check this if you are female", nullptr));
-#endif // QT_NO_TOOLTIP
- femaleRadioButton->setText(QApplication::translate("MainWindow", "&Female", nullptr));
-#ifndef QT_NO_TOOLTIP
- agreeCheckBox->setToolTip(QApplication::translate("MainWindow", "Please read the license before checking this", nullptr));
-#endif // QT_NO_TOOLTIP
- agreeCheckBox->setText(QApplication::translate("MainWindow", "I &accept the terms and conditions", nullptr));
-#ifndef QT_NO_TOOLTIP
- maleRadioButton->setToolTip(QApplication::translate("MainWindow", "Check this if you are male", nullptr));
-#endif // QT_NO_TOOLTIP
- maleRadioButton->setText(QApplication::translate("MainWindow", "&Male", nullptr));
- genderLabel->setText(QApplication::translate("MainWindow", "Gender:", nullptr));
-#ifndef QT_NO_TOOLTIP
- ageSpinBox->setToolTip(QApplication::translate("MainWindow", "Specify your age", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_STATUSTIP
- ageSpinBox->setStatusTip(QApplication::translate("MainWindow", "Specify your age here", nullptr));
-#endif // QT_NO_STATUSTIP
- ageLabel->setText(QApplication::translate("MainWindow", "&Age:", nullptr));
- passwordLabel->setText(QApplication::translate("MainWindow", "&Password:", nullptr));
-#ifndef QT_NO_TOOLTIP
- passwordEdit->setToolTip(QApplication::translate("MainWindow", "Specify your password", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_STATUSTIP
- passwordEdit->setStatusTip(QApplication::translate("MainWindow", "Specify your password here", nullptr));
-#endif // QT_NO_STATUSTIP
- passwordEdit->setText(QApplication::translate("MainWindow", "Password", nullptr));
- label->setText(QApplication::translate("MainWindow", "Profession", nullptr));
- countryLabel->setText(QApplication::translate("MainWindow", "&Country", nullptr));
+ MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr));
+ exitAction->setText(QCoreApplication::translate("MainWindow", "&Exit", nullptr));
+ aboutQtAction->setText(QCoreApplication::translate("MainWindow", "About Qt", nullptr));
+ editStyleAction->setText(QCoreApplication::translate("MainWindow", "Edit &Style", nullptr));
+ aboutAction->setText(QCoreApplication::translate("MainWindow", "About", nullptr));
+ nameLabel->setText(QCoreApplication::translate("MainWindow", "&Name:", nullptr));
+ nameCombo->setItemText(0, QCoreApplication::translate("MainWindow", "Girish", nullptr));
+ nameCombo->setItemText(1, QCoreApplication::translate("MainWindow", "Jasmin", nullptr));
+ nameCombo->setItemText(2, QCoreApplication::translate("MainWindow", "Simon", nullptr));
+ nameCombo->setItemText(3, QCoreApplication::translate("MainWindow", "Zack", nullptr));
+
+#if QT_CONFIG(tooltip)
+ nameCombo->setToolTip(QCoreApplication::translate("MainWindow", "Specify your name", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ femaleRadioButton->setToolTip(QCoreApplication::translate("MainWindow", "Check this if you are female", nullptr));
+#endif // QT_CONFIG(tooltip)
+ femaleRadioButton->setText(QCoreApplication::translate("MainWindow", "&Female", nullptr));
+#if QT_CONFIG(tooltip)
+ agreeCheckBox->setToolTip(QCoreApplication::translate("MainWindow", "Please read the license before checking this", nullptr));
+#endif // QT_CONFIG(tooltip)
+ agreeCheckBox->setText(QCoreApplication::translate("MainWindow", "I &accept the terms and conditions", nullptr));
+#if QT_CONFIG(tooltip)
+ maleRadioButton->setToolTip(QCoreApplication::translate("MainWindow", "Check this if you are male", nullptr));
+#endif // QT_CONFIG(tooltip)
+ maleRadioButton->setText(QCoreApplication::translate("MainWindow", "&Male", nullptr));
+ genderLabel->setText(QCoreApplication::translate("MainWindow", "Gender:", nullptr));
+#if QT_CONFIG(tooltip)
+ ageSpinBox->setToolTip(QCoreApplication::translate("MainWindow", "Specify your age", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(statustip)
+ ageSpinBox->setStatusTip(QCoreApplication::translate("MainWindow", "Specify your age here", nullptr));
+#endif // QT_CONFIG(statustip)
+ ageLabel->setText(QCoreApplication::translate("MainWindow", "&Age:", nullptr));
+ passwordLabel->setText(QCoreApplication::translate("MainWindow", "&Password:", nullptr));
+#if QT_CONFIG(tooltip)
+ passwordEdit->setToolTip(QCoreApplication::translate("MainWindow", "Specify your password", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(statustip)
+ passwordEdit->setStatusTip(QCoreApplication::translate("MainWindow", "Specify your password here", nullptr));
+#endif // QT_CONFIG(statustip)
+ passwordEdit->setText(QCoreApplication::translate("MainWindow", "Password", nullptr));
+ label->setText(QCoreApplication::translate("MainWindow", "Profession", nullptr));
+ countryLabel->setText(QCoreApplication::translate("MainWindow", "&Country", nullptr));
const bool __sortingEnabled = professionList->isSortingEnabled();
professionList->setSortingEnabled(false);
QListWidgetItem *___qlistwidgetitem = professionList->item(0);
- ___qlistwidgetitem->setText(QApplication::translate("MainWindow", "Developer", nullptr));
+ ___qlistwidgetitem->setText(QCoreApplication::translate("MainWindow", "Developer", nullptr));
QListWidgetItem *___qlistwidgetitem1 = professionList->item(1);
- ___qlistwidgetitem1->setText(QApplication::translate("MainWindow", "Student", nullptr));
+ ___qlistwidgetitem1->setText(QCoreApplication::translate("MainWindow", "Student", nullptr));
QListWidgetItem *___qlistwidgetitem2 = professionList->item(2);
- ___qlistwidgetitem2->setText(QApplication::translate("MainWindow", "Fisherman", nullptr));
+ ___qlistwidgetitem2->setText(QCoreApplication::translate("MainWindow", "Fisherman", nullptr));
professionList->setSortingEnabled(__sortingEnabled);
-#ifndef QT_NO_TOOLTIP
- professionList->setToolTip(QApplication::translate("MainWindow", "Select your profession", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_STATUSTIP
- professionList->setStatusTip(QApplication::translate("MainWindow", "Select your profession", nullptr));
-#endif // QT_NO_STATUSTIP
-#ifndef QT_NO_WHATSTHIS
- professionList->setWhatsThis(QApplication::translate("MainWindow", "Select your profession", nullptr));
-#endif // QT_NO_WHATSTHIS
- countryCombo->setItemText(0, QApplication::translate("MainWindow", "Germany", nullptr));
- countryCombo->setItemText(1, QApplication::translate("MainWindow", "India", nullptr));
- countryCombo->setItemText(2, QApplication::translate("MainWindow", "Norway", nullptr));
- countryCombo->setItemText(3, QApplication::translate("MainWindow", "United States Of America", nullptr));
- countryCombo->setItemText(4, QApplication::translate("MainWindow", "United Kingdom", nullptr));
-
-#ifndef QT_NO_TOOLTIP
- countryCombo->setToolTip(QApplication::translate("MainWindow", "Specify your country", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_STATUSTIP
- countryCombo->setStatusTip(QApplication::translate("MainWindow", "Specify your country here", nullptr));
-#endif // QT_NO_STATUSTIP
- menu_File->setTitle(QApplication::translate("MainWindow", "&File", nullptr));
- menu_Help->setTitle(QApplication::translate("MainWindow", "&Help", nullptr));
+#if QT_CONFIG(tooltip)
+ professionList->setToolTip(QCoreApplication::translate("MainWindow", "Select your profession", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(statustip)
+ professionList->setStatusTip(QCoreApplication::translate("MainWindow", "Select your profession", nullptr));
+#endif // QT_CONFIG(statustip)
+#if QT_CONFIG(whatsthis)
+ professionList->setWhatsThis(QCoreApplication::translate("MainWindow", "Select your profession", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ countryCombo->setItemText(0, QCoreApplication::translate("MainWindow", "Germany", nullptr));
+ countryCombo->setItemText(1, QCoreApplication::translate("MainWindow", "India", nullptr));
+ countryCombo->setItemText(2, QCoreApplication::translate("MainWindow", "Norway", nullptr));
+ countryCombo->setItemText(3, QCoreApplication::translate("MainWindow", "United States Of America", nullptr));
+ countryCombo->setItemText(4, QCoreApplication::translate("MainWindow", "United Kingdom", nullptr));
+
+#if QT_CONFIG(tooltip)
+ countryCombo->setToolTip(QCoreApplication::translate("MainWindow", "Specify your country", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(statustip)
+ countryCombo->setStatusTip(QCoreApplication::translate("MainWindow", "Specify your country here", nullptr));
+#endif // QT_CONFIG(statustip)
+ menu_File->setTitle(QCoreApplication::translate("MainWindow", "&File", nullptr));
+ menu_Help->setTitle(QCoreApplication::translate("MainWindow", "&Help", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/dialog.ui.h b/tests/auto/tools/uic/baseline/dialog.ui.h
index 2a159312b9..aeed71d058 100644
--- a/tests/auto/tools/uic/baseline/dialog.ui.h
+++ b/tests/auto/tools/uic/baseline/dialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'dialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -58,10 +58,10 @@ public:
void retranslateUi(QDialog *Dialog)
{
- Dialog->setWindowTitle(QApplication::translate("Dialog", "Dialog", nullptr));
- loadFromFileButton->setText(QApplication::translate("Dialog", "Load Image From File...", nullptr));
- label->setText(QApplication::translate("Dialog", "Launch two of these dialogs. In the first, press the top button and load an image from a file. In the second, press the bottom button and display the loaded image from shared memory.", nullptr));
- loadFromSharedMemoryButton->setText(QApplication::translate("Dialog", "Display Image From Shared Memory", nullptr));
+ Dialog->setWindowTitle(QCoreApplication::translate("Dialog", "Dialog", nullptr));
+ loadFromFileButton->setText(QCoreApplication::translate("Dialog", "Load Image From File...", nullptr));
+ label->setText(QCoreApplication::translate("Dialog", "Launch two of these dialogs. In the first, press the top button and load an image from a file. In the second, press the bottom button and display the loaded image from shared memory.", nullptr));
+ loadFromSharedMemoryButton->setText(QCoreApplication::translate("Dialog", "Display Image From Shared Memory", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/downloaditem.ui.h b/tests/auto/tools/uic/baseline/downloaditem.ui.h
index f0e8e88307..31d938f0eb 100644
--- a/tests/auto/tools/uic/baseline/downloaditem.ui.h
+++ b/tests/auto/tools/uic/baseline/downloaditem.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'downloaditem.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -124,13 +124,13 @@ public:
void retranslateUi(QWidget *DownloadItem)
{
- DownloadItem->setWindowTitle(QApplication::translate("DownloadItem", "Form", nullptr));
- fileIcon->setText(QApplication::translate("DownloadItem", "Ico", nullptr));
- fileNameLabel->setProperty("text", QVariant(QApplication::translate("DownloadItem", "Filename", nullptr)));
+ DownloadItem->setWindowTitle(QCoreApplication::translate("DownloadItem", "Form", nullptr));
+ fileIcon->setText(QCoreApplication::translate("DownloadItem", "Ico", nullptr));
+ fileNameLabel->setProperty("text", QVariant(QCoreApplication::translate("DownloadItem", "Filename", nullptr)));
downloadInfoLabel->setProperty("text", QVariant(QString()));
- tryAgainButton->setText(QApplication::translate("DownloadItem", "Try Again", nullptr));
- stopButton->setText(QApplication::translate("DownloadItem", "Stop", nullptr));
- openButton->setText(QApplication::translate("DownloadItem", "Open", nullptr));
+ tryAgainButton->setText(QCoreApplication::translate("DownloadItem", "Try Again", nullptr));
+ stopButton->setText(QCoreApplication::translate("DownloadItem", "Stop", nullptr));
+ openButton->setText(QCoreApplication::translate("DownloadItem", "Open", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/downloads.ui.h b/tests/auto/tools/uic/baseline/downloads.ui.h
index 1df992d30f..1b5b825792 100644
--- a/tests/auto/tools/uic/baseline/downloads.ui.h
+++ b/tests/auto/tools/uic/baseline/downloads.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'downloads.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -79,9 +79,9 @@ public:
void retranslateUi(QDialog *DownloadDialog)
{
- DownloadDialog->setWindowTitle(QApplication::translate("DownloadDialog", "Downloads", nullptr));
- cleanupButton->setText(QApplication::translate("DownloadDialog", "Clean up", nullptr));
- itemCount->setText(QApplication::translate("DownloadDialog", "0 Items", nullptr));
+ DownloadDialog->setWindowTitle(QCoreApplication::translate("DownloadDialog", "Downloads", nullptr));
+ cleanupButton->setText(QCoreApplication::translate("DownloadDialog", "Clean up", nullptr));
+ itemCount->setText(QCoreApplication::translate("DownloadDialog", "0 Items", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/embeddeddialog.ui.h b/tests/auto/tools/uic/baseline/embeddeddialog.ui.h
index 194ff578e8..20d6567576 100644
--- a/tests/auto/tools/uic/baseline/embeddeddialog.ui.h
+++ b/tests/auto/tools/uic/baseline/embeddeddialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'embeddeddialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.10.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -83,12 +83,12 @@ public:
formLayout->setWidget(3, QFormLayout::FieldRole, spacing);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(layoutDirection);
label_2->setBuddy(fontComboBox);
label_3->setBuddy(style);
label_4->setBuddy(spacing);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(embeddedDialog);
@@ -97,14 +97,14 @@ public:
void retranslateUi(QDialog *embeddedDialog)
{
- embeddedDialog->setWindowTitle(QApplication::translate("embeddedDialog", "Embedded Dialog", nullptr));
- label->setText(QApplication::translate("embeddedDialog", "Layout Direction:", nullptr));
- layoutDirection->setItemText(0, QApplication::translate("embeddedDialog", "Left to Right", nullptr));
- layoutDirection->setItemText(1, QApplication::translate("embeddedDialog", "Right to Left", nullptr));
-
- label_2->setText(QApplication::translate("embeddedDialog", "Select Font:", nullptr));
- label_3->setText(QApplication::translate("embeddedDialog", "Style:", nullptr));
- label_4->setText(QApplication::translate("embeddedDialog", "Layout spacing:", nullptr));
+ embeddedDialog->setWindowTitle(QCoreApplication::translate("embeddedDialog", "Embedded Dialog", nullptr));
+ label->setText(QCoreApplication::translate("embeddedDialog", "Layout Direction:", nullptr));
+ layoutDirection->setItemText(0, QCoreApplication::translate("embeddedDialog", "Left to Right", nullptr));
+ layoutDirection->setItemText(1, QCoreApplication::translate("embeddedDialog", "Right to Left", nullptr));
+
+ label_2->setText(QCoreApplication::translate("embeddedDialog", "Select Font:", nullptr));
+ label_3->setText(QCoreApplication::translate("embeddedDialog", "Style:", nullptr));
+ label_4->setText(QCoreApplication::translate("embeddedDialog", "Layout spacing:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/enumnostdset.ui.h b/tests/auto/tools/uic/baseline/enumnostdset.ui.h
index 233fc616ac..54ec7c4161 100644
--- a/tests/auto/tools/uic/baseline/enumnostdset.ui.h
+++ b/tests/auto/tools/uic/baseline/enumnostdset.ui.h
@@ -38,7 +38,7 @@ public:
void retranslateUi(QWidget *Form)
{
- Form->setWindowTitle(QApplication::translate("Form", "Form", nullptr));
+ Form->setWindowTitle(QCoreApplication::translate("Form", "Form", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/filespage.ui.h b/tests/auto/tools/uic/baseline/filespage.ui.h
index 29ed981a8a..327b2c571b 100644
--- a/tests/auto/tools/uic/baseline/filespage.ui.h
+++ b/tests/auto/tools/uic/baseline/filespage.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'filespage.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -80,10 +80,10 @@ public:
void retranslateUi(QWidget *FilesPage)
{
- FilesPage->setWindowTitle(QApplication::translate("FilesPage", "Form", nullptr));
- fileLabel->setText(QApplication::translate("FilesPage", "Files:", nullptr));
- removeButton->setText(QApplication::translate("FilesPage", "Remove", nullptr));
- removeAllButton->setText(QApplication::translate("FilesPage", "Remove All", nullptr));
+ FilesPage->setWindowTitle(QCoreApplication::translate("FilesPage", "Form", nullptr));
+ fileLabel->setText(QCoreApplication::translate("FilesPage", "Files:", nullptr));
+ removeButton->setText(QCoreApplication::translate("FilesPage", "Remove", nullptr));
+ removeAllButton->setText(QCoreApplication::translate("FilesPage", "Remove All", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/filternamedialog.ui.h b/tests/auto/tools/uic/baseline/filternamedialog.ui.h
index 716c291fdd..0098282d59 100644
--- a/tests/auto/tools/uic/baseline/filternamedialog.ui.h
+++ b/tests/auto/tools/uic/baseline/filternamedialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'filternamedialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -76,8 +76,8 @@ public:
void retranslateUi(QDialog *FilterNameDialogClass)
{
- FilterNameDialogClass->setWindowTitle(QApplication::translate("FilterNameDialogClass", "FilterNameDialog", nullptr));
- label->setText(QApplication::translate("FilterNameDialogClass", "Filter Name:", nullptr));
+ FilterNameDialogClass->setWindowTitle(QCoreApplication::translate("FilterNameDialogClass", "FilterNameDialog", nullptr));
+ label->setText(QCoreApplication::translate("FilterNameDialogClass", "Filter Name:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/filterpage.ui.h b/tests/auto/tools/uic/baseline/filterpage.ui.h
index f6610fdc4d..1581c6554d 100644
--- a/tests/auto/tools/uic/baseline/filterpage.ui.h
+++ b/tests/auto/tools/uic/baseline/filterpage.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'filterpage.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -103,14 +103,14 @@ public:
void retranslateUi(QWidget *FilterPage)
{
- FilterPage->setWindowTitle(QApplication::translate("FilterPage", "Form", nullptr));
- label->setText(QApplication::translate("FilterPage", "Filter attributes for current documentation (comma separated list):", nullptr));
- groupBox->setTitle(QApplication::translate("FilterPage", "Custom Filters", nullptr));
+ FilterPage->setWindowTitle(QCoreApplication::translate("FilterPage", "Form", nullptr));
+ label->setText(QCoreApplication::translate("FilterPage", "Filter attributes for current documentation (comma separated list):", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("FilterPage", "Custom Filters", nullptr));
QTreeWidgetItem *___qtreewidgetitem = customFilterWidget->headerItem();
- ___qtreewidgetitem->setText(1, QApplication::translate("FilterPage", "2", nullptr));
- ___qtreewidgetitem->setText(0, QApplication::translate("FilterPage", "1", nullptr));
- addButton->setText(QApplication::translate("FilterPage", "Add", nullptr));
- removeButton->setText(QApplication::translate("FilterPage", "Remove", nullptr));
+ ___qtreewidgetitem->setText(1, QCoreApplication::translate("FilterPage", "2", nullptr));
+ ___qtreewidgetitem->setText(0, QCoreApplication::translate("FilterPage", "1", nullptr));
+ addButton->setText(QCoreApplication::translate("FilterPage", "Add", nullptr));
+ removeButton->setText(QCoreApplication::translate("FilterPage", "Remove", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/finddialog.ui.h b/tests/auto/tools/uic/baseline/finddialog.ui.h
index a427be3614..f335eee2e4 100644
--- a/tests/auto/tools/uic/baseline/finddialog.ui.h
+++ b/tests/auto/tools/uic/baseline/finddialog.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'finddialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -172,9 +172,9 @@ public:
hboxLayout->addLayout(vboxLayout1);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
findWhat->setBuddy(led);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
QWidget::setTabOrder(led, findNxt);
QWidget::setTabOrder(findNxt, cancel);
QWidget::setTabOrder(cancel, comments);
@@ -193,40 +193,40 @@ public:
void retranslateUi(QDialog *FindDialog)
{
- FindDialog->setWindowTitle(QApplication::translate("FindDialog", "Find", nullptr));
-#ifndef QT_NO_WHATSTHIS
- FindDialog->setWhatsThis(QApplication::translate("FindDialog", "This window allows you to search for some text in the translation source file.", nullptr));
-#endif // QT_NO_WHATSTHIS
- findWhat->setText(QApplication::translate("FindDialog", "&Find what:", nullptr));
-#ifndef QT_NO_WHATSTHIS
- led->setWhatsThis(QApplication::translate("FindDialog", "Type in the text to search for.", nullptr));
-#endif // QT_NO_WHATSTHIS
- groupBox->setTitle(QApplication::translate("FindDialog", "Options", nullptr));
-#ifndef QT_NO_WHATSTHIS
- sourceText->setWhatsThis(QApplication::translate("FindDialog", "Source texts are searched when checked.", nullptr));
-#endif // QT_NO_WHATSTHIS
- sourceText->setText(QApplication::translate("FindDialog", "&Source texts", nullptr));
-#ifndef QT_NO_WHATSTHIS
- translations->setWhatsThis(QApplication::translate("FindDialog", "Translations are searched when checked.", nullptr));
-#endif // QT_NO_WHATSTHIS
- translations->setText(QApplication::translate("FindDialog", "&Translations", nullptr));
-#ifndef QT_NO_WHATSTHIS
- matchCase->setWhatsThis(QApplication::translate("FindDialog", "Texts such as 'TeX' and 'tex' are considered as different when checked.", nullptr));
-#endif // QT_NO_WHATSTHIS
- matchCase->setText(QApplication::translate("FindDialog", "&Match case", nullptr));
-#ifndef QT_NO_WHATSTHIS
- comments->setWhatsThis(QApplication::translate("FindDialog", "Comments and contexts are searched when checked.", nullptr));
-#endif // QT_NO_WHATSTHIS
- comments->setText(QApplication::translate("FindDialog", "&Comments", nullptr));
- ignoreAccelerators->setText(QApplication::translate("FindDialog", "Ignore &accelerators", nullptr));
-#ifndef QT_NO_WHATSTHIS
- findNxt->setWhatsThis(QApplication::translate("FindDialog", "Click here to find the next occurrence of the text you typed in.", nullptr));
-#endif // QT_NO_WHATSTHIS
- findNxt->setText(QApplication::translate("FindDialog", "Find Next", nullptr));
-#ifndef QT_NO_WHATSTHIS
- cancel->setWhatsThis(QApplication::translate("FindDialog", "Click here to close this window.", nullptr));
-#endif // QT_NO_WHATSTHIS
- cancel->setText(QApplication::translate("FindDialog", "Cancel", nullptr));
+ FindDialog->setWindowTitle(QCoreApplication::translate("FindDialog", "Find", nullptr));
+#if QT_CONFIG(whatsthis)
+ FindDialog->setWhatsThis(QCoreApplication::translate("FindDialog", "This window allows you to search for some text in the translation source file.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ findWhat->setText(QCoreApplication::translate("FindDialog", "&Find what:", nullptr));
+#if QT_CONFIG(whatsthis)
+ led->setWhatsThis(QCoreApplication::translate("FindDialog", "Type in the text to search for.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ groupBox->setTitle(QCoreApplication::translate("FindDialog", "Options", nullptr));
+#if QT_CONFIG(whatsthis)
+ sourceText->setWhatsThis(QCoreApplication::translate("FindDialog", "Source texts are searched when checked.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ sourceText->setText(QCoreApplication::translate("FindDialog", "&Source texts", nullptr));
+#if QT_CONFIG(whatsthis)
+ translations->setWhatsThis(QCoreApplication::translate("FindDialog", "Translations are searched when checked.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ translations->setText(QCoreApplication::translate("FindDialog", "&Translations", nullptr));
+#if QT_CONFIG(whatsthis)
+ matchCase->setWhatsThis(QCoreApplication::translate("FindDialog", "Texts such as 'TeX' and 'tex' are considered as different when checked.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ matchCase->setText(QCoreApplication::translate("FindDialog", "&Match case", nullptr));
+#if QT_CONFIG(whatsthis)
+ comments->setWhatsThis(QCoreApplication::translate("FindDialog", "Comments and contexts are searched when checked.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ comments->setText(QCoreApplication::translate("FindDialog", "&Comments", nullptr));
+ ignoreAccelerators->setText(QCoreApplication::translate("FindDialog", "Ignore &accelerators", nullptr));
+#if QT_CONFIG(whatsthis)
+ findNxt->setWhatsThis(QCoreApplication::translate("FindDialog", "Click here to find the next occurrence of the text you typed in.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ findNxt->setText(QCoreApplication::translate("FindDialog", "Find Next", nullptr));
+#if QT_CONFIG(whatsthis)
+ cancel->setWhatsThis(QCoreApplication::translate("FindDialog", "Click here to close this window.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ cancel->setText(QCoreApplication::translate("FindDialog", "Cancel", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/form.ui.h b/tests/auto/tools/uic/baseline/form.ui.h
index ecc63e339b..df8163f726 100644
--- a/tests/auto/tools/uic/baseline/form.ui.h
+++ b/tests/auto/tools/uic/baseline/form.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'form.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -123,9 +123,9 @@ public:
void retranslateUi(QWidget *WorldTimeForm)
{
- WorldTimeForm->setWindowTitle(QApplication::translate("WorldTimeForm", "World Time Clock", nullptr));
- label->setText(QApplication::translate("WorldTimeForm", "Current time:", nullptr));
- label_2->setText(QApplication::translate("WorldTimeForm", "Set time zone:", nullptr));
+ WorldTimeForm->setWindowTitle(QCoreApplication::translate("WorldTimeForm", "World Time Clock", nullptr));
+ label->setText(QCoreApplication::translate("WorldTimeForm", "Current time:", nullptr));
+ label_2->setText(QCoreApplication::translate("WorldTimeForm", "Set time zone:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/formwindowsettings.ui.h b/tests/auto/tools/uic/baseline/formwindowsettings.ui.h
index d2cfa03edb..17c301e959 100644
--- a/tests/auto/tools/uic/baseline/formwindowsettings.ui.h
+++ b/tests/auto/tools/uic/baseline/formwindowsettings.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'formwindowsettings.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -250,12 +250,12 @@ public:
gridLayout->addWidget(gridPanel, 1, 0, 1, 2);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label_2->setBuddy(defaultSpacingSpinBox);
label->setBuddy(defaultMarginSpinBox);
label_3->setBuddy(marginFunctionLineEdit);
label_3_2->setBuddy(spacingFunctionLineEdit);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
QWidget::setTabOrder(authorLineEdit, defaultMarginSpinBox);
QWidget::setTabOrder(defaultMarginSpinBox, defaultSpacingSpinBox);
QWidget::setTabOrder(defaultSpacingSpinBox, marginFunctionLineEdit);
@@ -271,17 +271,17 @@ public:
void retranslateUi(QDialog *FormWindowSettings)
{
- FormWindowSettings->setWindowTitle(QApplication::translate("FormWindowSettings", "Form Settings", nullptr));
- layoutDefaultGroupBox->setTitle(QApplication::translate("FormWindowSettings", "Layout &Default", nullptr));
- label_2->setText(QApplication::translate("FormWindowSettings", "&Spacing:", nullptr));
- label->setText(QApplication::translate("FormWindowSettings", "&Margin:", nullptr));
- layoutFunctionGroupBox->setTitle(QApplication::translate("FormWindowSettings", "&Layout Function", nullptr));
- label_3->setText(QApplication::translate("FormWindowSettings", "Ma&rgin:", nullptr));
- label_3_2->setText(QApplication::translate("FormWindowSettings", "Spa&cing:", nullptr));
- pixmapFunctionGroupBox_2->setTitle(QApplication::translate("FormWindowSettings", "&Author", nullptr));
- includeHintsGroupBox->setTitle(QApplication::translate("FormWindowSettings", "&Include Hints", nullptr));
- pixmapFunctionGroupBox->setTitle(QApplication::translate("FormWindowSettings", "&Pixmap Function", nullptr));
- gridPanel->setTitle(QApplication::translate("FormWindowSettings", "Grid", nullptr));
+ FormWindowSettings->setWindowTitle(QCoreApplication::translate("FormWindowSettings", "Form Settings", nullptr));
+ layoutDefaultGroupBox->setTitle(QCoreApplication::translate("FormWindowSettings", "Layout &Default", nullptr));
+ label_2->setText(QCoreApplication::translate("FormWindowSettings", "&Spacing:", nullptr));
+ label->setText(QCoreApplication::translate("FormWindowSettings", "&Margin:", nullptr));
+ layoutFunctionGroupBox->setTitle(QCoreApplication::translate("FormWindowSettings", "&Layout Function", nullptr));
+ label_3->setText(QCoreApplication::translate("FormWindowSettings", "Ma&rgin:", nullptr));
+ label_3_2->setText(QCoreApplication::translate("FormWindowSettings", "Spa&cing:", nullptr));
+ pixmapFunctionGroupBox_2->setTitle(QCoreApplication::translate("FormWindowSettings", "&Author", nullptr));
+ includeHintsGroupBox->setTitle(QCoreApplication::translate("FormWindowSettings", "&Include Hints", nullptr));
+ pixmapFunctionGroupBox->setTitle(QCoreApplication::translate("FormWindowSettings", "&Pixmap Function", nullptr));
+ gridPanel->setTitle(QCoreApplication::translate("FormWindowSettings", "Grid", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/generalpage.ui.h b/tests/auto/tools/uic/baseline/generalpage.ui.h
index bd04285d28..6488bfc061 100644
--- a/tests/auto/tools/uic/baseline/generalpage.ui.h
+++ b/tests/auto/tools/uic/baseline/generalpage.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'generalpage.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -73,9 +73,9 @@ public:
void retranslateUi(QWidget *GeneralPage)
{
- GeneralPage->setWindowTitle(QApplication::translate("GeneralPage", "Form", nullptr));
- label->setText(QApplication::translate("GeneralPage", "Namespace:", nullptr));
- label_2->setText(QApplication::translate("GeneralPage", "Virtual Folder:", nullptr));
+ GeneralPage->setWindowTitle(QCoreApplication::translate("GeneralPage", "Form", nullptr));
+ label->setText(QCoreApplication::translate("GeneralPage", "Namespace:", nullptr));
+ label_2->setText(QCoreApplication::translate("GeneralPage", "Virtual Folder:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/gridalignment.ui.h b/tests/auto/tools/uic/baseline/gridalignment.ui.h
index 421f257c9a..f85ed818f7 100644
--- a/tests/auto/tools/uic/baseline/gridalignment.ui.h
+++ b/tests/auto/tools/uic/baseline/gridalignment.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'gridalignment.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -61,11 +61,11 @@ public:
void retranslateUi(QWidget *Form)
{
- Form->setWindowTitle(QApplication::translate("Form", "Form", nullptr));
- pushButton->setText(QApplication::translate("Form", "Left", nullptr));
- pushButton_3->setText(QApplication::translate("Form", "Top", nullptr));
- pushButton_2->setText(QApplication::translate("Form", "Right", nullptr));
- pushButton_4->setText(QApplication::translate("Form", "Bottom", nullptr));
+ Form->setWindowTitle(QCoreApplication::translate("Form", "Form", nullptr));
+ pushButton->setText(QCoreApplication::translate("Form", "Left", nullptr));
+ pushButton_3->setText(QCoreApplication::translate("Form", "Top", nullptr));
+ pushButton_2->setText(QCoreApplication::translate("Form", "Right", nullptr));
+ pushButton_4->setText(QCoreApplication::translate("Form", "Bottom", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/gridpanel.ui.h b/tests/auto/tools/uic/baseline/gridpanel.ui.h
index 858b71d0cc..54c9a3b5de 100644
--- a/tests/auto/tools/uic/baseline/gridpanel.ui.h
+++ b/tests/auto/tools/uic/baseline/gridpanel.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'gridpanel.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -120,10 +120,10 @@ public:
vboxLayout->addWidget(m_gridGroupBox);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(m_deltaXSpinBox);
label_2->setBuddy(m_deltaYSpinBox);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(qdesigner_internal__GridPanel);
@@ -132,14 +132,14 @@ public:
void retranslateUi(QWidget *qdesigner_internal__GridPanel)
{
- qdesigner_internal__GridPanel->setWindowTitle(QApplication::translate("qdesigner_internal::GridPanel", "Form", nullptr));
- m_gridGroupBox->setTitle(QApplication::translate("qdesigner_internal::GridPanel", "Grid", nullptr));
- m_visibleCheckBox->setText(QApplication::translate("qdesigner_internal::GridPanel", "Visible", nullptr));
- label->setText(QApplication::translate("qdesigner_internal::GridPanel", "Grid &X", nullptr));
- m_snapXCheckBox->setText(QApplication::translate("qdesigner_internal::GridPanel", "Snap", nullptr));
- m_resetButton->setText(QApplication::translate("qdesigner_internal::GridPanel", "Reset", nullptr));
- label_2->setText(QApplication::translate("qdesigner_internal::GridPanel", "Grid &Y", nullptr));
- m_snapYCheckBox->setText(QApplication::translate("qdesigner_internal::GridPanel", "Snap", nullptr));
+ qdesigner_internal__GridPanel->setWindowTitle(QCoreApplication::translate("qdesigner_internal::GridPanel", "Form", nullptr));
+ m_gridGroupBox->setTitle(QCoreApplication::translate("qdesigner_internal::GridPanel", "Grid", nullptr));
+ m_visibleCheckBox->setText(QCoreApplication::translate("qdesigner_internal::GridPanel", "Visible", nullptr));
+ label->setText(QCoreApplication::translate("qdesigner_internal::GridPanel", "Grid &X", nullptr));
+ m_snapXCheckBox->setText(QCoreApplication::translate("qdesigner_internal::GridPanel", "Snap", nullptr));
+ m_resetButton->setText(QCoreApplication::translate("qdesigner_internal::GridPanel", "Reset", nullptr));
+ label_2->setText(QCoreApplication::translate("qdesigner_internal::GridPanel", "Grid &Y", nullptr));
+ m_snapYCheckBox->setText(QCoreApplication::translate("qdesigner_internal::GridPanel", "Snap", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/helpdialog.ui b/tests/auto/tools/uic/baseline/helpdialog.ui
index 8c3178183c..91b81c75d5 100644
--- a/tests/auto/tools/uic/baseline/helpdialog.ui
+++ b/tests/auto/tools/uic/baseline/helpdialog.ui
@@ -57,6 +57,9 @@
<string>Displays help topics organized by category, index or bookmarks. Another tab inherits the full text search.</string>
</property>
<widget class="QWidget" name="contentPage" >
+ <attribute name="icon">
+ <iconset theme="edit-copy"/>
+ </attribute>
<attribute name="title" >
<string>Con&amp;tents</string>
</attribute>
diff --git a/tests/auto/tools/uic/baseline/helpdialog.ui.h b/tests/auto/tools/uic/baseline/helpdialog.ui.h
index abcf280cf9..dd28041a3e 100644
--- a/tests/auto/tools/uic/baseline/helpdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/helpdialog.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'helpdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -124,7 +124,8 @@ public:
vboxLayout1->addWidget(listContents);
- tabWidget->addTab(contentPage, QString());
+ QIcon icon(QIcon::fromTheme(QString::fromUtf8("edit-copy")));
+ tabWidget->addTab(contentPage, icon, QString());
indexPage = new QWidget();
indexPage->setObjectName(QString::fromUtf8("indexPage"));
vboxLayout2 = new QVBoxLayout(indexPage);
@@ -273,11 +274,11 @@ public:
vboxLayout->addWidget(framePrepare);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
TextLabel1->setBuddy(editIndex);
TextLabel1_2->setBuddy(termsEdit);
TextLabel2->setBuddy(resultBox);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
QWidget::setTabOrder(tabWidget, listContents);
QWidget::setTabOrder(listContents, editIndex);
QWidget::setTabOrder(editIndex, listIndex);
@@ -296,77 +297,77 @@ public:
void retranslateUi(QWidget *HelpDialog)
{
- HelpDialog->setWindowTitle(QApplication::translate("HelpDialog", "Help", nullptr));
-#ifndef QT_NO_WHATSTHIS
- HelpDialog->setWhatsThis(QApplication::translate("HelpDialog", "<b>Help</b><p>Choose the topic you want help on from the contents list, or search the index for keywords.</p>", nullptr));
-#endif // QT_NO_WHATSTHIS
-#ifndef QT_NO_WHATSTHIS
- tabWidget->setWhatsThis(QApplication::translate("HelpDialog", "Displays help topics organized by category, index or bookmarks. Another tab inherits the full text search.", nullptr));
-#endif // QT_NO_WHATSTHIS
+ HelpDialog->setWindowTitle(QCoreApplication::translate("HelpDialog", "Help", nullptr));
+#if QT_CONFIG(whatsthis)
+ HelpDialog->setWhatsThis(QCoreApplication::translate("HelpDialog", "<b>Help</b><p>Choose the topic you want help on from the contents list, or search the index for keywords.</p>", nullptr));
+#endif // QT_CONFIG(whatsthis)
+#if QT_CONFIG(whatsthis)
+ tabWidget->setWhatsThis(QCoreApplication::translate("HelpDialog", "Displays help topics organized by category, index or bookmarks. Another tab inherits the full text search.", nullptr));
+#endif // QT_CONFIG(whatsthis)
QTreeWidgetItem *___qtreewidgetitem = listContents->headerItem();
- ___qtreewidgetitem->setText(0, QApplication::translate("HelpDialog", "column 1", nullptr));
-#ifndef QT_NO_WHATSTHIS
- listContents->setWhatsThis(QApplication::translate("HelpDialog", "<b>Help topics organized by category.</b><p>Double-click an item to see the topics in that category. To view a topic, just double-click it.</p>", nullptr));
-#endif // QT_NO_WHATSTHIS
- tabWidget->setTabText(tabWidget->indexOf(contentPage), QApplication::translate("HelpDialog", "Con&tents", nullptr));
- TextLabel1->setText(QApplication::translate("HelpDialog", "&Look For:", nullptr));
-#ifndef QT_NO_TOOLTIP
- editIndex->setToolTip(QApplication::translate("HelpDialog", "Enter keyword", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_WHATSTHIS
- editIndex->setWhatsThis(QApplication::translate("HelpDialog", "<b>Enter a keyword.</b><p>The list will select an item that matches the entered string best.</p>", nullptr));
-#endif // QT_NO_WHATSTHIS
-#ifndef QT_NO_WHATSTHIS
- listIndex->setWhatsThis(QApplication::translate("HelpDialog", "<b>List of available help topics.</b><p>Double-click on an item to open its help page. If more than one is found, you must specify which page you want.</p>", nullptr));
-#endif // QT_NO_WHATSTHIS
- tabWidget->setTabText(tabWidget->indexOf(indexPage), QApplication::translate("HelpDialog", "&Index", nullptr));
+ ___qtreewidgetitem->setText(0, QCoreApplication::translate("HelpDialog", "column 1", nullptr));
+#if QT_CONFIG(whatsthis)
+ listContents->setWhatsThis(QCoreApplication::translate("HelpDialog", "<b>Help topics organized by category.</b><p>Double-click an item to see the topics in that category. To view a topic, just double-click it.</p>", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ tabWidget->setTabText(tabWidget->indexOf(contentPage), QCoreApplication::translate("HelpDialog", "Con&tents", nullptr));
+ TextLabel1->setText(QCoreApplication::translate("HelpDialog", "&Look For:", nullptr));
+#if QT_CONFIG(tooltip)
+ editIndex->setToolTip(QCoreApplication::translate("HelpDialog", "Enter keyword", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(whatsthis)
+ editIndex->setWhatsThis(QCoreApplication::translate("HelpDialog", "<b>Enter a keyword.</b><p>The list will select an item that matches the entered string best.</p>", nullptr));
+#endif // QT_CONFIG(whatsthis)
+#if QT_CONFIG(whatsthis)
+ listIndex->setWhatsThis(QCoreApplication::translate("HelpDialog", "<b>List of available help topics.</b><p>Double-click on an item to open its help page. If more than one is found, you must specify which page you want.</p>", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ tabWidget->setTabText(tabWidget->indexOf(indexPage), QCoreApplication::translate("HelpDialog", "&Index", nullptr));
QTreeWidgetItem *___qtreewidgetitem1 = listBookmarks->headerItem();
- ___qtreewidgetitem1->setText(0, QApplication::translate("HelpDialog", "column 1", nullptr));
-#ifndef QT_NO_WHATSTHIS
- listBookmarks->setWhatsThis(QApplication::translate("HelpDialog", "Displays the list of bookmarks.", nullptr));
-#endif // QT_NO_WHATSTHIS
-#ifndef QT_NO_TOOLTIP
- buttonAdd->setToolTip(QApplication::translate("HelpDialog", "Add new bookmark", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_WHATSTHIS
- buttonAdd->setWhatsThis(QApplication::translate("HelpDialog", "Add the currently displayed page as a new bookmark.", nullptr));
-#endif // QT_NO_WHATSTHIS
- buttonAdd->setText(QApplication::translate("HelpDialog", "&New", nullptr));
-#ifndef QT_NO_TOOLTIP
- buttonRemove->setToolTip(QApplication::translate("HelpDialog", "Delete bookmark", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_WHATSTHIS
- buttonRemove->setWhatsThis(QApplication::translate("HelpDialog", "Delete the selected bookmark.", nullptr));
-#endif // QT_NO_WHATSTHIS
- buttonRemove->setText(QApplication::translate("HelpDialog", "&Delete", nullptr));
- tabWidget->setTabText(tabWidget->indexOf(bookmarkPage), QApplication::translate("HelpDialog", "&Bookmarks", nullptr));
- TextLabel1_2->setText(QApplication::translate("HelpDialog", "Searching f&or:", nullptr));
-#ifndef QT_NO_TOOLTIP
- termsEdit->setToolTip(QApplication::translate("HelpDialog", "Enter searchword(s).", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_WHATSTHIS
- termsEdit->setWhatsThis(QApplication::translate("HelpDialog", "<b>Enter search word(s).</b><p>Enter here the word(s) you are looking for. The words may contain wildcards (*). For a sequence of words quote them.</p>", nullptr));
-#endif // QT_NO_WHATSTHIS
-#ifndef QT_NO_WHATSTHIS
- resultBox->setWhatsThis(QApplication::translate("HelpDialog", "<b>Found documents</b><p>This list contains all found documents from the last search. The documents are ordered, i.e. the first document has the most matches.</p>", nullptr));
-#endif // QT_NO_WHATSTHIS
- TextLabel2->setText(QApplication::translate("HelpDialog", "Found &Documents:", nullptr));
-#ifndef QT_NO_TOOLTIP
- helpButton->setToolTip(QApplication::translate("HelpDialog", "Display the help page.", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_WHATSTHIS
- helpButton->setWhatsThis(QApplication::translate("HelpDialog", "Display the help page for the full text search.", nullptr));
-#endif // QT_NO_WHATSTHIS
- helpButton->setText(QApplication::translate("HelpDialog", "He&lp", nullptr));
-#ifndef QT_NO_TOOLTIP
- searchButton->setToolTip(QApplication::translate("HelpDialog", "Start searching.", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_WHATSTHIS
- searchButton->setWhatsThis(QApplication::translate("HelpDialog", "Pressing this button starts the search.", nullptr));
-#endif // QT_NO_WHATSTHIS
- searchButton->setText(QApplication::translate("HelpDialog", "&Search", nullptr));
- tabWidget->setTabText(tabWidget->indexOf(searchPage), QApplication::translate("HelpDialog", "&Search", nullptr));
- labelPrepare->setText(QApplication::translate("HelpDialog", "Preparing...", nullptr));
+ ___qtreewidgetitem1->setText(0, QCoreApplication::translate("HelpDialog", "column 1", nullptr));
+#if QT_CONFIG(whatsthis)
+ listBookmarks->setWhatsThis(QCoreApplication::translate("HelpDialog", "Displays the list of bookmarks.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+#if QT_CONFIG(tooltip)
+ buttonAdd->setToolTip(QCoreApplication::translate("HelpDialog", "Add new bookmark", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(whatsthis)
+ buttonAdd->setWhatsThis(QCoreApplication::translate("HelpDialog", "Add the currently displayed page as a new bookmark.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ buttonAdd->setText(QCoreApplication::translate("HelpDialog", "&New", nullptr));
+#if QT_CONFIG(tooltip)
+ buttonRemove->setToolTip(QCoreApplication::translate("HelpDialog", "Delete bookmark", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(whatsthis)
+ buttonRemove->setWhatsThis(QCoreApplication::translate("HelpDialog", "Delete the selected bookmark.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ buttonRemove->setText(QCoreApplication::translate("HelpDialog", "&Delete", nullptr));
+ tabWidget->setTabText(tabWidget->indexOf(bookmarkPage), QCoreApplication::translate("HelpDialog", "&Bookmarks", nullptr));
+ TextLabel1_2->setText(QCoreApplication::translate("HelpDialog", "Searching f&or:", nullptr));
+#if QT_CONFIG(tooltip)
+ termsEdit->setToolTip(QCoreApplication::translate("HelpDialog", "Enter searchword(s).", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(whatsthis)
+ termsEdit->setWhatsThis(QCoreApplication::translate("HelpDialog", "<b>Enter search word(s).</b><p>Enter here the word(s) you are looking for. The words may contain wildcards (*). For a sequence of words quote them.</p>", nullptr));
+#endif // QT_CONFIG(whatsthis)
+#if QT_CONFIG(whatsthis)
+ resultBox->setWhatsThis(QCoreApplication::translate("HelpDialog", "<b>Found documents</b><p>This list contains all found documents from the last search. The documents are ordered, i.e. the first document has the most matches.</p>", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ TextLabel2->setText(QCoreApplication::translate("HelpDialog", "Found &Documents:", nullptr));
+#if QT_CONFIG(tooltip)
+ helpButton->setToolTip(QCoreApplication::translate("HelpDialog", "Display the help page.", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(whatsthis)
+ helpButton->setWhatsThis(QCoreApplication::translate("HelpDialog", "Display the help page for the full text search.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ helpButton->setText(QCoreApplication::translate("HelpDialog", "He&lp", nullptr));
+#if QT_CONFIG(tooltip)
+ searchButton->setToolTip(QCoreApplication::translate("HelpDialog", "Start searching.", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(whatsthis)
+ searchButton->setWhatsThis(QCoreApplication::translate("HelpDialog", "Pressing this button starts the search.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ searchButton->setText(QCoreApplication::translate("HelpDialog", "&Search", nullptr));
+ tabWidget->setTabText(tabWidget->indexOf(searchPage), QCoreApplication::translate("HelpDialog", "&Search", nullptr));
+ labelPrepare->setText(QCoreApplication::translate("HelpDialog", "Preparing...", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/history.ui.h b/tests/auto/tools/uic/baseline/history.ui.h
index 715312d11a..7f48fb9f54 100644
--- a/tests/auto/tools/uic/baseline/history.ui.h
+++ b/tests/auto/tools/uic/baseline/history.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'history.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -91,9 +91,9 @@ public:
void retranslateUi(QDialog *HistoryDialog)
{
- HistoryDialog->setWindowTitle(QApplication::translate("HistoryDialog", "History", nullptr));
- removeButton->setText(QApplication::translate("HistoryDialog", "&Remove", nullptr));
- removeAllButton->setText(QApplication::translate("HistoryDialog", "Remove &All", nullptr));
+ HistoryDialog->setWindowTitle(QCoreApplication::translate("HistoryDialog", "History", nullptr));
+ removeButton->setText(QCoreApplication::translate("HistoryDialog", "&Remove", nullptr));
+ removeAllButton->setText(QCoreApplication::translate("HistoryDialog", "Remove &All", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/icontheme.ui.h b/tests/auto/tools/uic/baseline/icontheme.ui.h
index 936d6b5cf7..f1f6e42a02 100644
--- a/tests/auto/tools/uic/baseline/icontheme.ui.h
+++ b/tests/auto/tools/uic/baseline/icontheme.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'icontheme.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -75,10 +75,10 @@ public:
void retranslateUi(QWidget *Form)
{
- Form->setWindowTitle(QApplication::translate("Form", "Form", nullptr));
- fileicon->setText(QApplication::translate("Form", "fileicon", nullptr));
- fileandthemeicon->setText(QApplication::translate("Form", "PushButton", nullptr));
- themeicon->setText(QApplication::translate("Form", "PushButton", nullptr));
+ Form->setWindowTitle(QCoreApplication::translate("Form", "Form", nullptr));
+ fileicon->setText(QCoreApplication::translate("Form", "fileicon", nullptr));
+ fileandthemeicon->setText(QCoreApplication::translate("Form", "PushButton", nullptr));
+ themeicon->setText(QCoreApplication::translate("Form", "PushButton", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/idbased.ui.h b/tests/auto/tools/uic/baseline/idbased.ui.h
index e246313e11..0209895a3c 100644
--- a/tests/auto/tools/uic/baseline/idbased.ui.h
+++ b/tests/auto/tools/uic/baseline/idbased.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'idbased.ui'
**
-** Created by: Qt User Interface Compiler version 5.11.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -44,15 +44,15 @@ public:
void retranslateUi(QWidget *Form)
{
Form->setWindowTitle(qtTrId("windowTitleId"));
-#ifndef QT_NO_TOOLTIP
+#if QT_CONFIG(tooltip)
pushButton->setToolTip(qtTrId("buttonToolTipId"));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_STATUSTIP
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(statustip)
pushButton->setStatusTip(qtTrId("buttonStatusTipId"));
-#endif // QT_NO_STATUSTIP
-#ifndef QT_NO_WHATSTHIS
+#endif // QT_CONFIG(statustip)
+#if QT_CONFIG(whatsthis)
pushButton->setWhatsThis(qtTrId("buttonWhatsThisId"));
-#endif // QT_NO_WHATSTHIS
+#endif // QT_CONFIG(whatsthis)
pushButton->setText(qtTrId("buttonTextId"));
} // retranslateUi
diff --git a/tests/auto/tools/uic/baseline/identifierpage.ui.h b/tests/auto/tools/uic/baseline/identifierpage.ui.h
index 322a9cf30a..420d668fe9 100644
--- a/tests/auto/tools/uic/baseline/identifierpage.ui.h
+++ b/tests/auto/tools/uic/baseline/identifierpage.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'identifierpage.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -89,10 +89,10 @@ public:
void retranslateUi(QWidget *IdentifierPage)
{
- IdentifierPage->setWindowTitle(QApplication::translate("IdentifierPage", "Form", nullptr));
- identifierCheckBox->setText(QApplication::translate("IdentifierPage", "Create identifiers", nullptr));
- globalButton->setText(QApplication::translate("IdentifierPage", "Global prefix:", nullptr));
- fileNameButton->setText(QApplication::translate("IdentifierPage", "Inherit prefix from file names", nullptr));
+ IdentifierPage->setWindowTitle(QCoreApplication::translate("IdentifierPage", "Form", nullptr));
+ identifierCheckBox->setText(QCoreApplication::translate("IdentifierPage", "Create identifiers", nullptr));
+ globalButton->setText(QCoreApplication::translate("IdentifierPage", "Global prefix:", nullptr));
+ fileNameButton->setText(QCoreApplication::translate("IdentifierPage", "Inherit prefix from file names", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/imagedialog.ui.h b/tests/auto/tools/uic/baseline/imagedialog.ui.h
index e32e7639fa..eea8b6ee03 100644
--- a/tests/auto/tools/uic/baseline/imagedialog.ui.h
+++ b/tests/auto/tools/uic/baseline/imagedialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'imagedialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -86,7 +86,7 @@ public:
colorDepthCombo = new QComboBox(dialog);
colorDepthCombo->setObjectName(QString::fromUtf8("colorDepthCombo"));
colorDepthCombo->setGeometry(QRect(74, 83, 227, 22));
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(0));
+ QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(colorDepthCombo->sizePolicy().hasHeightForWidth());
@@ -98,7 +98,7 @@ public:
nameLineEdit = new QLineEdit(dialog);
nameLineEdit->setObjectName(QString::fromUtf8("nameLineEdit"));
nameLineEdit->setGeometry(QRect(74, 83, 227, 22));
- QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(0));
+ QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy1.setHorizontalStretch(1);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(nameLineEdit->sizePolicy().hasHeightForWidth());
@@ -196,14 +196,14 @@ public:
void retranslateUi(QDialog *dialog)
{
- dialog->setWindowTitle(QApplication::translate("ImageDialog", "Create Image", nullptr));
- widthLabel->setText(QApplication::translate("ImageDialog", "Width:", nullptr));
- heightLabel->setText(QApplication::translate("ImageDialog", "Height:", nullptr));
- nameLineEdit->setText(QApplication::translate("ImageDialog", "Untitled image", nullptr));
- nameLabel->setText(QApplication::translate("ImageDialog", "Name:", nullptr));
- colorDepthLabel->setText(QApplication::translate("ImageDialog", "Color depth:", nullptr));
- okButton->setText(QApplication::translate("ImageDialog", "OK", nullptr));
- cancelButton->setText(QApplication::translate("ImageDialog", "Cancel", nullptr));
+ dialog->setWindowTitle(QCoreApplication::translate("ImageDialog", "Create Image", nullptr));
+ widthLabel->setText(QCoreApplication::translate("ImageDialog", "Width:", nullptr));
+ heightLabel->setText(QCoreApplication::translate("ImageDialog", "Height:", nullptr));
+ nameLineEdit->setText(QCoreApplication::translate("ImageDialog", "Untitled image", nullptr));
+ nameLabel->setText(QCoreApplication::translate("ImageDialog", "Name:", nullptr));
+ colorDepthLabel->setText(QCoreApplication::translate("ImageDialog", "Color depth:", nullptr));
+ okButton->setText(QCoreApplication::translate("ImageDialog", "OK", nullptr));
+ cancelButton->setText(QCoreApplication::translate("ImageDialog", "Cancel", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/inputpage.ui.h b/tests/auto/tools/uic/baseline/inputpage.ui.h
index 9367dec6df..0cb4cce4f2 100644
--- a/tests/auto/tools/uic/baseline/inputpage.ui.h
+++ b/tests/auto/tools/uic/baseline/inputpage.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'inputpage.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -81,9 +81,9 @@ public:
void retranslateUi(QWidget *InputPage)
{
- InputPage->setWindowTitle(QApplication::translate("InputPage", "Form", nullptr));
- label->setText(QApplication::translate("InputPage", "File name:", nullptr));
- browseButton->setText(QApplication::translate("InputPage", "...", nullptr));
+ InputPage->setWindowTitle(QCoreApplication::translate("InputPage", "Form", nullptr));
+ label->setText(QCoreApplication::translate("InputPage", "File name:", nullptr));
+ browseButton->setText(QCoreApplication::translate("InputPage", "...", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/installdialog.ui.h b/tests/auto/tools/uic/baseline/installdialog.ui.h
index 3ec7f69b76..b452971f19 100644
--- a/tests/auto/tools/uic/baseline/installdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/installdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'installdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -120,13 +120,13 @@ public:
void retranslateUi(QDialog *InstallDialog)
{
- InstallDialog->setWindowTitle(QApplication::translate("InstallDialog", "Install Documentation", nullptr));
- label->setText(QApplication::translate("InstallDialog", "Available Documentation:", nullptr));
- installButton->setText(QApplication::translate("InstallDialog", "Install", nullptr));
- cancelButton->setText(QApplication::translate("InstallDialog", "Cancel", nullptr));
- closeButton->setText(QApplication::translate("InstallDialog", "Close", nullptr));
- label_4->setText(QApplication::translate("InstallDialog", "Installation Path:", nullptr));
- browseButton->setText(QApplication::translate("InstallDialog", "...", nullptr));
+ InstallDialog->setWindowTitle(QCoreApplication::translate("InstallDialog", "Install Documentation", nullptr));
+ label->setText(QCoreApplication::translate("InstallDialog", "Available Documentation:", nullptr));
+ installButton->setText(QCoreApplication::translate("InstallDialog", "Install", nullptr));
+ cancelButton->setText(QCoreApplication::translate("InstallDialog", "Cancel", nullptr));
+ closeButton->setText(QCoreApplication::translate("InstallDialog", "Close", nullptr));
+ label_4->setText(QCoreApplication::translate("InstallDialog", "Installation Path:", nullptr));
+ browseButton->setText(QCoreApplication::translate("InstallDialog", "...", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/languagesdialog.ui.h b/tests/auto/tools/uic/baseline/languagesdialog.ui.h
index cf2599fd07..f605d942d4 100644
--- a/tests/auto/tools/uic/baseline/languagesdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/languagesdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'languagesdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -108,39 +108,39 @@ public:
void retranslateUi(QDialog *LanguagesDialog)
{
- LanguagesDialog->setWindowTitle(QApplication::translate("LanguagesDialog", "Auxiliary Languages", nullptr));
+ LanguagesDialog->setWindowTitle(QCoreApplication::translate("LanguagesDialog", "Auxiliary Languages", nullptr));
QTreeWidgetItem *___qtreewidgetitem = languagesList->headerItem();
- ___qtreewidgetitem->setText(1, QApplication::translate("LanguagesDialog", "File", nullptr));
- ___qtreewidgetitem->setText(0, QApplication::translate("LanguagesDialog", "Locale", nullptr));
-#ifndef QT_NO_TOOLTIP
- upButton->setToolTip(QApplication::translate("LanguagesDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
+ ___qtreewidgetitem->setText(1, QCoreApplication::translate("LanguagesDialog", "File", nullptr));
+ ___qtreewidgetitem->setText(0, QCoreApplication::translate("LanguagesDialog", "Locale", nullptr));
+#if QT_CONFIG(tooltip)
+ upButton->setToolTip(QCoreApplication::translate("LanguagesDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Move selected language up</p></body></html>", nullptr));
-#endif // QT_NO_TOOLTIP
- upButton->setText(QApplication::translate("LanguagesDialog", "up", nullptr));
-#ifndef QT_NO_TOOLTIP
- downButton->setToolTip(QApplication::translate("LanguagesDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
+#endif // QT_CONFIG(tooltip)
+ upButton->setText(QCoreApplication::translate("LanguagesDialog", "up", nullptr));
+#if QT_CONFIG(tooltip)
+ downButton->setToolTip(QCoreApplication::translate("LanguagesDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;\">Move selected language down</p></body></html>", nullptr));
-#endif // QT_NO_TOOLTIP
- downButton->setText(QApplication::translate("LanguagesDialog", "down", nullptr));
-#ifndef QT_NO_TOOLTIP
- removeButton->setToolTip(QApplication::translate("LanguagesDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
+#endif // QT_CONFIG(tooltip)
+ downButton->setText(QCoreApplication::translate("LanguagesDialog", "down", nullptr));
+#if QT_CONFIG(tooltip)
+ removeButton->setToolTip(QCoreApplication::translate("LanguagesDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Remove selected language</p></body></html>", nullptr));
-#endif // QT_NO_TOOLTIP
- removeButton->setText(QApplication::translate("LanguagesDialog", "remove", nullptr));
-#ifndef QT_NO_TOOLTIP
- openFileButton->setToolTip(QApplication::translate("LanguagesDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
+#endif // QT_CONFIG(tooltip)
+ removeButton->setText(QCoreApplication::translate("LanguagesDialog", "remove", nullptr));
+#if QT_CONFIG(tooltip)
+ openFileButton->setToolTip(QCoreApplication::translate("LanguagesDialog", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Open auxiliary language files</p></body></html>", nullptr));
-#endif // QT_NO_TOOLTIP
- openFileButton->setText(QApplication::translate("LanguagesDialog", "...", nullptr));
- okButton->setText(QApplication::translate("LanguagesDialog", "OK", nullptr));
+#endif // QT_CONFIG(tooltip)
+ openFileButton->setText(QCoreApplication::translate("LanguagesDialog", "...", nullptr));
+ okButton->setText(QCoreApplication::translate("LanguagesDialog", "OK", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/listwidgeteditor.ui.h b/tests/auto/tools/uic/baseline/listwidgeteditor.ui.h
index 14067ced18..721d4c9950 100644
--- a/tests/auto/tools/uic/baseline/listwidgeteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/listwidgeteditor.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'listwidgeteditor.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -172,28 +172,28 @@ public:
void retranslateUi(QDialog *qdesigner_internal__ListWidgetEditor)
{
- qdesigner_internal__ListWidgetEditor->setWindowTitle(QApplication::translate("qdesigner_internal::ListWidgetEditor", "Dialog", nullptr));
- groupBox->setTitle(QApplication::translate("qdesigner_internal::ListWidgetEditor", "Items List", nullptr));
-#ifndef QT_NO_TOOLTIP
- listWidget->setToolTip(QApplication::translate("qdesigner_internal::ListWidgetEditor", "Items List", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- newItemButton->setToolTip(QApplication::translate("qdesigner_internal::ListWidgetEditor", "New Item", nullptr));
-#endif // QT_NO_TOOLTIP
- newItemButton->setText(QApplication::translate("qdesigner_internal::ListWidgetEditor", "&New", nullptr));
-#ifndef QT_NO_TOOLTIP
- deleteItemButton->setToolTip(QApplication::translate("qdesigner_internal::ListWidgetEditor", "Delete Item", nullptr));
-#endif // QT_NO_TOOLTIP
- deleteItemButton->setText(QApplication::translate("qdesigner_internal::ListWidgetEditor", "&Delete", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveItemUpButton->setToolTip(QApplication::translate("qdesigner_internal::ListWidgetEditor", "Move Item Up", nullptr));
-#endif // QT_NO_TOOLTIP
- moveItemUpButton->setText(QApplication::translate("qdesigner_internal::ListWidgetEditor", "U", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveItemDownButton->setToolTip(QApplication::translate("qdesigner_internal::ListWidgetEditor", "Move Item Down", nullptr));
-#endif // QT_NO_TOOLTIP
- moveItemDownButton->setText(QApplication::translate("qdesigner_internal::ListWidgetEditor", "D", nullptr));
- label->setText(QApplication::translate("qdesigner_internal::ListWidgetEditor", "Icon", nullptr));
+ qdesigner_internal__ListWidgetEditor->setWindowTitle(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "Dialog", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "Items List", nullptr));
+#if QT_CONFIG(tooltip)
+ listWidget->setToolTip(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "Items List", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ newItemButton->setToolTip(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "New Item", nullptr));
+#endif // QT_CONFIG(tooltip)
+ newItemButton->setText(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "&New", nullptr));
+#if QT_CONFIG(tooltip)
+ deleteItemButton->setToolTip(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "Delete Item", nullptr));
+#endif // QT_CONFIG(tooltip)
+ deleteItemButton->setText(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "&Delete", nullptr));
+#if QT_CONFIG(tooltip)
+ moveItemUpButton->setToolTip(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "Move Item Up", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveItemUpButton->setText(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "U", nullptr));
+#if QT_CONFIG(tooltip)
+ moveItemDownButton->setToolTip(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "Move Item Down", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveItemDownButton->setText(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "D", nullptr));
+ label->setText(QCoreApplication::translate("qdesigner_internal::ListWidgetEditor", "Icon", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/mainwindow.ui.h b/tests/auto/tools/uic/baseline/mainwindow.ui.h
index fe84d0baa3..df61d57ceb 100644
--- a/tests/auto/tools/uic/baseline/mainwindow.ui.h
+++ b/tests/auto/tools/uic/baseline/mainwindow.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -361,30 +361,30 @@ public:
void retranslateUi(QMainWindow *MainWindow)
{
- MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MakeQPF", nullptr));
- actionAdd_Custom_Font->setText(QApplication::translate("MainWindow", "&Add Custom Font...", nullptr));
- action_Exit->setText(QApplication::translate("MainWindow", "&Exit", nullptr));
- groupBox->setTitle(QApplication::translate("MainWindow", "Font Properties", nullptr));
- label->setText(QApplication::translate("MainWindow", "Family:", nullptr));
- label_2->setText(QApplication::translate("MainWindow", "Pixel Size:", nullptr));
- label_7->setText(QApplication::translate("MainWindow", "Weight:", nullptr));
- italic->setText(QApplication::translate("MainWindow", "Italic", nullptr));
- groupBox_2->setTitle(QApplication::translate("MainWindow", "Glyph Coverage", nullptr));
- chooseFromCodePoints->setText(QApplication::translate("MainWindow", "Choose from Unicode Codepoints:", nullptr));
- selectAll->setText(QApplication::translate("MainWindow", "Select &All", nullptr));
- deselectAll->setText(QApplication::translate("MainWindow", "&Deselect All", nullptr));
- invertSelection->setText(QApplication::translate("MainWindow", "&Invert Selection", nullptr));
- chooseFromSampleFile->setText(QApplication::translate("MainWindow", "Choose from Sample Text File (UTF-8 Encoded):", nullptr));
- label_5->setText(QApplication::translate("MainWindow", "Path:", nullptr));
- browseSampleFile->setText(QApplication::translate("MainWindow", "Browse...", nullptr));
- charCount->setText(QApplication::translate("MainWindow", "TextLabel", nullptr));
- groupBox_3->setTitle(QApplication::translate("MainWindow", "Preview", nullptr));
- groupBox_4->setTitle(QApplication::translate("MainWindow", "Output Options", nullptr));
- label_3->setText(QApplication::translate("MainWindow", "Path:", nullptr));
- browsePath->setText(QApplication::translate("MainWindow", "Browse...", nullptr));
- label_4->setText(QApplication::translate("MainWindow", "Filename:", nullptr));
- generate->setText(QApplication::translate("MainWindow", "Generate Pre-Rendered Font...", nullptr));
- menuFile->setTitle(QApplication::translate("MainWindow", "File", nullptr));
+ MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MakeQPF", nullptr));
+ actionAdd_Custom_Font->setText(QCoreApplication::translate("MainWindow", "&Add Custom Font...", nullptr));
+ action_Exit->setText(QCoreApplication::translate("MainWindow", "&Exit", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("MainWindow", "Font Properties", nullptr));
+ label->setText(QCoreApplication::translate("MainWindow", "Family:", nullptr));
+ label_2->setText(QCoreApplication::translate("MainWindow", "Pixel Size:", nullptr));
+ label_7->setText(QCoreApplication::translate("MainWindow", "Weight:", nullptr));
+ italic->setText(QCoreApplication::translate("MainWindow", "Italic", nullptr));
+ groupBox_2->setTitle(QCoreApplication::translate("MainWindow", "Glyph Coverage", nullptr));
+ chooseFromCodePoints->setText(QCoreApplication::translate("MainWindow", "Choose from Unicode Codepoints:", nullptr));
+ selectAll->setText(QCoreApplication::translate("MainWindow", "Select &All", nullptr));
+ deselectAll->setText(QCoreApplication::translate("MainWindow", "&Deselect All", nullptr));
+ invertSelection->setText(QCoreApplication::translate("MainWindow", "&Invert Selection", nullptr));
+ chooseFromSampleFile->setText(QCoreApplication::translate("MainWindow", "Choose from Sample Text File (UTF-8 Encoded):", nullptr));
+ label_5->setText(QCoreApplication::translate("MainWindow", "Path:", nullptr));
+ browseSampleFile->setText(QCoreApplication::translate("MainWindow", "Browse...", nullptr));
+ charCount->setText(QCoreApplication::translate("MainWindow", "TextLabel", nullptr));
+ groupBox_3->setTitle(QCoreApplication::translate("MainWindow", "Preview", nullptr));
+ groupBox_4->setTitle(QCoreApplication::translate("MainWindow", "Output Options", nullptr));
+ label_3->setText(QCoreApplication::translate("MainWindow", "Path:", nullptr));
+ browsePath->setText(QCoreApplication::translate("MainWindow", "Browse...", nullptr));
+ label_4->setText(QCoreApplication::translate("MainWindow", "Filename:", nullptr));
+ generate->setText(QCoreApplication::translate("MainWindow", "Generate Pre-Rendered Font...", nullptr));
+ menuFile->setTitle(QCoreApplication::translate("MainWindow", "File", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/mydialog.ui.h b/tests/auto/tools/uic/baseline/mydialog.ui.h
index 1a784d1b0a..e71927092f 100644
--- a/tests/auto/tools/uic/baseline/mydialog.ui.h
+++ b/tests/auto/tools/uic/baseline/mydialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'mydialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.9.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -56,12 +56,12 @@ public:
void retranslateUi(QDialog *MyDialog)
{
- MyDialog->setWindowTitle(QApplication::translate("MyDialog", "Mach 2!", nullptr));
- aLabel->setText(QApplication::translate("MyDialog", "Join the life in the fastlane; - PCH enable your project today! -", nullptr));
- aButton->setText(QApplication::translate("MyDialog", "&Quit", nullptr));
-#ifndef QT_NO_SHORTCUT
- aButton->setShortcut(QApplication::translate("MyDialog", "Alt+Q", nullptr));
-#endif // QT_NO_SHORTCUT
+ MyDialog->setWindowTitle(QCoreApplication::translate("MyDialog", "Mach 2!", nullptr));
+ aLabel->setText(QCoreApplication::translate("MyDialog", "Join the life in the fastlane; - PCH enable your project today! -", nullptr));
+ aButton->setText(QCoreApplication::translate("MyDialog", "&Quit", nullptr));
+#if QT_CONFIG(shortcut)
+ aButton->setShortcut(QCoreApplication::translate("MyDialog", "Alt+Q", nullptr));
+#endif // QT_CONFIG(shortcut)
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/myform.ui.h b/tests/auto/tools/uic/baseline/myform.ui.h
index d3a08e04c9..87d88e8246 100644
--- a/tests/auto/tools/uic/baseline/myform.ui.h
+++ b/tests/auto/tools/uic/baseline/myform.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'myform.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -120,17 +120,17 @@ public:
void retranslateUi(QWidget *Form)
{
- Form->setWindowTitle(QApplication::translate("Form", "Export Document", nullptr));
- groupBox->setTitle(QApplication::translate("Form", "Export Options", nullptr));
- radioButton_2->setText(QApplication::translate("Form", "&DocBook", nullptr));
- radioButton->setText(QApplication::translate("Form", "&LaTeX", nullptr));
- checkBox_2->setText(QApplication::translate("Form", "Include p&ictures", nullptr));
- checkBox->setText(QApplication::translate("Form", "&Compress", nullptr));
- radioButton_2_2->setText(QApplication::translate("Form", "&HTML", nullptr));
- radioButton_3->setText(QApplication::translate("Form", "&PostScript", nullptr));
- radioButton_4->setText(QApplication::translate("Form", "PD&F", nullptr));
- checkBox_3->setText(QApplication::translate("Form", "Include &metadata", nullptr));
- checkBox_4->setText(QApplication::translate("Form", "Create inde&x", nullptr));
+ Form->setWindowTitle(QCoreApplication::translate("Form", "Export Document", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("Form", "Export Options", nullptr));
+ radioButton_2->setText(QCoreApplication::translate("Form", "&DocBook", nullptr));
+ radioButton->setText(QCoreApplication::translate("Form", "&LaTeX", nullptr));
+ checkBox_2->setText(QCoreApplication::translate("Form", "Include p&ictures", nullptr));
+ checkBox->setText(QCoreApplication::translate("Form", "&Compress", nullptr));
+ radioButton_2_2->setText(QCoreApplication::translate("Form", "&HTML", nullptr));
+ radioButton_3->setText(QCoreApplication::translate("Form", "&PostScript", nullptr));
+ radioButton_4->setText(QCoreApplication::translate("Form", "PD&F", nullptr));
+ checkBox_3->setText(QCoreApplication::translate("Form", "Include &metadata", nullptr));
+ checkBox_4->setText(QCoreApplication::translate("Form", "Create inde&x", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/newactiondialog.ui.h b/tests/auto/tools/uic/baseline/newactiondialog.ui.h
index ca99ab8356..4b3b6bcf1a 100644
--- a/tests/auto/tools/uic/baseline/newactiondialog.ui.h
+++ b/tests/auto/tools/uic/baseline/newactiondialog.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'newactiondialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -143,11 +143,11 @@ public:
verticalLayout->addWidget(buttonBox);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(editActionText);
label_3->setBuddy(editObjectName);
label_2->setBuddy(iconSelector);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
QWidget::setTabOrder(editActionText, editObjectName);
retranslateUi(qdesigner_internal__NewActionDialog);
@@ -159,10 +159,10 @@ public:
void retranslateUi(QDialog *qdesigner_internal__NewActionDialog)
{
- qdesigner_internal__NewActionDialog->setWindowTitle(QApplication::translate("qdesigner_internal::NewActionDialog", "New Action...", nullptr));
- label->setText(QApplication::translate("qdesigner_internal::NewActionDialog", "&Text:", nullptr));
- label_3->setText(QApplication::translate("qdesigner_internal::NewActionDialog", "Object &name:", nullptr));
- label_2->setText(QApplication::translate("qdesigner_internal::NewActionDialog", "&Icon:", nullptr));
+ qdesigner_internal__NewActionDialog->setWindowTitle(QCoreApplication::translate("qdesigner_internal::NewActionDialog", "New Action...", nullptr));
+ label->setText(QCoreApplication::translate("qdesigner_internal::NewActionDialog", "&Text:", nullptr));
+ label_3->setText(QCoreApplication::translate("qdesigner_internal::NewActionDialog", "Object &name:", nullptr));
+ label_2->setText(QCoreApplication::translate("qdesigner_internal::NewActionDialog", "&Icon:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/newdynamicpropertydialog.ui.h b/tests/auto/tools/uic/baseline/newdynamicpropertydialog.ui.h
index f5fd6f1fa4..406f8bc1a3 100644
--- a/tests/auto/tools/uic/baseline/newdynamicpropertydialog.ui.h
+++ b/tests/auto/tools/uic/baseline/newdynamicpropertydialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'newdynamicpropertydialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -108,9 +108,9 @@ public:
void retranslateUi(QDialog *qdesigner_internal__NewDynamicPropertyDialog)
{
- qdesigner_internal__NewDynamicPropertyDialog->setWindowTitle(QApplication::translate("qdesigner_internal::NewDynamicPropertyDialog", "Create Dynamic Property", nullptr));
- label->setText(QApplication::translate("qdesigner_internal::NewDynamicPropertyDialog", "Property Name", nullptr));
- label_2->setText(QApplication::translate("qdesigner_internal::NewDynamicPropertyDialog", "Property Type", nullptr));
+ qdesigner_internal__NewDynamicPropertyDialog->setWindowTitle(QCoreApplication::translate("qdesigner_internal::NewDynamicPropertyDialog", "Create Dynamic Property", nullptr));
+ label->setText(QCoreApplication::translate("qdesigner_internal::NewDynamicPropertyDialog", "Property Name", nullptr));
+ label_2->setText(QCoreApplication::translate("qdesigner_internal::NewDynamicPropertyDialog", "Property Type", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/newform.ui.h b/tests/auto/tools/uic/baseline/newform.ui.h
index 80e70dcf66..e0b5baef81 100644
--- a/tests/auto/tools/uic/baseline/newform.ui.h
+++ b/tests/auto/tools/uic/baseline/newform.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'newform.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -93,7 +93,7 @@ public:
lblPreview = new QLabel(NewForm);
lblPreview->setObjectName(QString::fromUtf8("lblPreview"));
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(5));
+ QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(lblPreview->sizePolicy().hasHeightForWidth());
@@ -132,11 +132,11 @@ public:
void retranslateUi(QDialog *NewForm)
{
- NewForm->setWindowTitle(QApplication::translate("NewForm", "New Form", nullptr));
+ NewForm->setWindowTitle(QCoreApplication::translate("NewForm", "New Form", nullptr));
QTreeWidgetItem *___qtreewidgetitem = treeWidget->headerItem();
- ___qtreewidgetitem->setText(0, QApplication::translate("NewForm", "0", nullptr));
- lblPreview->setText(QApplication::translate("NewForm", "Choose a template for a preview", nullptr));
- chkShowOnStartup->setText(QApplication::translate("NewForm", "Show this Dialog on Startup", nullptr));
+ ___qtreewidgetitem->setText(0, QCoreApplication::translate("NewForm", "0", nullptr));
+ lblPreview->setText(QCoreApplication::translate("NewForm", "Choose a template for a preview", nullptr));
+ chkShowOnStartup->setText(QCoreApplication::translate("NewForm", "Show this Dialog on Startup", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/orderdialog.ui.h b/tests/auto/tools/uic/baseline/orderdialog.ui.h
index 0ee08257f4..532ec2d41c 100644
--- a/tests/auto/tools/uic/baseline/orderdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/orderdialog.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'orderdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -130,14 +130,14 @@ public:
void retranslateUi(QDialog *qdesigner_internal__OrderDialog)
{
- qdesigner_internal__OrderDialog->setWindowTitle(QApplication::translate("qdesigner_internal::OrderDialog", "Change Page Order", nullptr));
- groupBox->setTitle(QApplication::translate("qdesigner_internal::OrderDialog", "Page Order", nullptr));
-#ifndef QT_NO_TOOLTIP
- upButton->setToolTip(QApplication::translate("qdesigner_internal::OrderDialog", "Move page up", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- downButton->setToolTip(QApplication::translate("qdesigner_internal::OrderDialog", "Move page down", nullptr));
-#endif // QT_NO_TOOLTIP
+ qdesigner_internal__OrderDialog->setWindowTitle(QCoreApplication::translate("qdesigner_internal::OrderDialog", "Change Page Order", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("qdesigner_internal::OrderDialog", "Page Order", nullptr));
+#if QT_CONFIG(tooltip)
+ upButton->setToolTip(QCoreApplication::translate("qdesigner_internal::OrderDialog", "Move page up", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ downButton->setToolTip(QCoreApplication::translate("qdesigner_internal::OrderDialog", "Move page down", nullptr));
+#endif // QT_CONFIG(tooltip)
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/outputpage.ui.h b/tests/auto/tools/uic/baseline/outputpage.ui.h
index 00491bb3d8..9d2593dc77 100644
--- a/tests/auto/tools/uic/baseline/outputpage.ui.h
+++ b/tests/auto/tools/uic/baseline/outputpage.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'outputpage.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -87,9 +87,9 @@ public:
void retranslateUi(QWidget *OutputPage)
{
- OutputPage->setWindowTitle(QApplication::translate("OutputPage", "Form", nullptr));
- label->setText(QApplication::translate("OutputPage", "Project file name:", nullptr));
- label_2->setText(QApplication::translate("OutputPage", "Collection file name:", nullptr));
+ OutputPage->setWindowTitle(QCoreApplication::translate("OutputPage", "Form", nullptr));
+ label->setText(QCoreApplication::translate("OutputPage", "Project file name:", nullptr));
+ label_2->setText(QCoreApplication::translate("OutputPage", "Collection file name:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/pagefold.ui.h b/tests/auto/tools/uic/baseline/pagefold.ui.h
index c1ff03648d..a0594b7ec7 100644
--- a/tests/auto/tools/uic/baseline/pagefold.ui.h
+++ b/tests/auto/tools/uic/baseline/pagefold.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'pagefold.ui'
**
-** Created by: Qt User Interface Compiler version 5.10.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -213,13 +213,13 @@ public:
statusbar = new QStatusBar(MainWindow);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
MainWindow->setStatusBar(statusbar);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
ageLabel->setBuddy(ageSpinBox);
nameLabel->setBuddy(nameCombo);
passwordLabel->setBuddy(passwordEdit);
label->setBuddy(professionList);
countryLabel->setBuddy(professionList);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
menubar->addAction(menu_File->menuAction());
menubar->addAction(menu_Help->menuAction());
@@ -242,84 +242,84 @@ public:
void retranslateUi(QMainWindow *MainWindow)
{
- MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr));
- exitAction->setText(QApplication::translate("MainWindow", "&Exit", nullptr));
- aboutQtAction->setText(QApplication::translate("MainWindow", "About Qt", nullptr));
- editStyleAction->setText(QApplication::translate("MainWindow", "Edit &Style", nullptr));
- aboutAction->setText(QApplication::translate("MainWindow", "About", nullptr));
- nameCombo->setItemText(0, QApplication::translate("MainWindow", "Girish", nullptr));
- nameCombo->setItemText(1, QApplication::translate("MainWindow", "Jasmin", nullptr));
- nameCombo->setItemText(2, QApplication::translate("MainWindow", "Simon", nullptr));
- nameCombo->setItemText(3, QApplication::translate("MainWindow", "Zack", nullptr));
-
-#ifndef QT_NO_TOOLTIP
- nameCombo->setToolTip(QApplication::translate("MainWindow", "Specify your name", nullptr));
-#endif // QT_NO_TOOLTIP
- femaleRadioButton->setStyleSheet(QApplication::translate("MainWindow", "Check this if you are female", nullptr));
- femaleRadioButton->setText(QApplication::translate("MainWindow", "&Female", nullptr));
- genderLabel->setText(QApplication::translate("MainWindow", "Gender:", nullptr));
- ageLabel->setText(QApplication::translate("MainWindow", "&Age:", nullptr));
-#ifndef QT_NO_TOOLTIP
- maleRadioButton->setToolTip(QApplication::translate("MainWindow", "Check this if you are male", nullptr));
-#endif // QT_NO_TOOLTIP
- maleRadioButton->setText(QApplication::translate("MainWindow", "&Male", nullptr));
- nameLabel->setText(QApplication::translate("MainWindow", "&Name:", nullptr));
- passwordLabel->setText(QApplication::translate("MainWindow", "&Password:", nullptr));
-#ifndef QT_NO_TOOLTIP
- ageSpinBox->setToolTip(QApplication::translate("MainWindow", "Specify your age", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_STATUSTIP
- ageSpinBox->setStatusTip(QApplication::translate("MainWindow", "Specify your age", nullptr));
-#endif // QT_NO_STATUSTIP
-#ifndef QT_NO_TOOLTIP
- agreeCheckBox->setToolTip(QApplication::translate("MainWindow", "Please read the LICENSE file before checking", nullptr));
-#endif // QT_NO_TOOLTIP
- agreeCheckBox->setText(QApplication::translate("MainWindow", "I &accept the terms and &conditions", nullptr));
-#ifndef QT_NO_TOOLTIP
- passwordEdit->setToolTip(QApplication::translate("MainWindow", "Specify your password", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_STATUSTIP
- passwordEdit->setStatusTip(QApplication::translate("MainWindow", "Specify your password", nullptr));
-#endif // QT_NO_STATUSTIP
- passwordEdit->setText(QApplication::translate("MainWindow", "Password", nullptr));
+ MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr));
+ exitAction->setText(QCoreApplication::translate("MainWindow", "&Exit", nullptr));
+ aboutQtAction->setText(QCoreApplication::translate("MainWindow", "About Qt", nullptr));
+ editStyleAction->setText(QCoreApplication::translate("MainWindow", "Edit &Style", nullptr));
+ aboutAction->setText(QCoreApplication::translate("MainWindow", "About", nullptr));
+ nameCombo->setItemText(0, QCoreApplication::translate("MainWindow", "Girish", nullptr));
+ nameCombo->setItemText(1, QCoreApplication::translate("MainWindow", "Jasmin", nullptr));
+ nameCombo->setItemText(2, QCoreApplication::translate("MainWindow", "Simon", nullptr));
+ nameCombo->setItemText(3, QCoreApplication::translate("MainWindow", "Zack", nullptr));
+
+#if QT_CONFIG(tooltip)
+ nameCombo->setToolTip(QCoreApplication::translate("MainWindow", "Specify your name", nullptr));
+#endif // QT_CONFIG(tooltip)
+ femaleRadioButton->setStyleSheet(QCoreApplication::translate("MainWindow", "Check this if you are female", nullptr));
+ femaleRadioButton->setText(QCoreApplication::translate("MainWindow", "&Female", nullptr));
+ genderLabel->setText(QCoreApplication::translate("MainWindow", "Gender:", nullptr));
+ ageLabel->setText(QCoreApplication::translate("MainWindow", "&Age:", nullptr));
+#if QT_CONFIG(tooltip)
+ maleRadioButton->setToolTip(QCoreApplication::translate("MainWindow", "Check this if you are male", nullptr));
+#endif // QT_CONFIG(tooltip)
+ maleRadioButton->setText(QCoreApplication::translate("MainWindow", "&Male", nullptr));
+ nameLabel->setText(QCoreApplication::translate("MainWindow", "&Name:", nullptr));
+ passwordLabel->setText(QCoreApplication::translate("MainWindow", "&Password:", nullptr));
+#if QT_CONFIG(tooltip)
+ ageSpinBox->setToolTip(QCoreApplication::translate("MainWindow", "Specify your age", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(statustip)
+ ageSpinBox->setStatusTip(QCoreApplication::translate("MainWindow", "Specify your age", nullptr));
+#endif // QT_CONFIG(statustip)
+#if QT_CONFIG(tooltip)
+ agreeCheckBox->setToolTip(QCoreApplication::translate("MainWindow", "Please read the LICENSE file before checking", nullptr));
+#endif // QT_CONFIG(tooltip)
+ agreeCheckBox->setText(QCoreApplication::translate("MainWindow", "I &accept the terms and &conditions", nullptr));
+#if QT_CONFIG(tooltip)
+ passwordEdit->setToolTip(QCoreApplication::translate("MainWindow", "Specify your password", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(statustip)
+ passwordEdit->setStatusTip(QCoreApplication::translate("MainWindow", "Specify your password", nullptr));
+#endif // QT_CONFIG(statustip)
+ passwordEdit->setText(QCoreApplication::translate("MainWindow", "Password", nullptr));
const bool __sortingEnabled = professionList->isSortingEnabled();
professionList->setSortingEnabled(false);
QListWidgetItem *___qlistwidgetitem = professionList->item(0);
- ___qlistwidgetitem->setText(QApplication::translate("MainWindow", "Developer", nullptr));
+ ___qlistwidgetitem->setText(QCoreApplication::translate("MainWindow", "Developer", nullptr));
QListWidgetItem *___qlistwidgetitem1 = professionList->item(1);
- ___qlistwidgetitem1->setText(QApplication::translate("MainWindow", "Student", nullptr));
+ ___qlistwidgetitem1->setText(QCoreApplication::translate("MainWindow", "Student", nullptr));
QListWidgetItem *___qlistwidgetitem2 = professionList->item(2);
- ___qlistwidgetitem2->setText(QApplication::translate("MainWindow", "Fisherman", nullptr));
+ ___qlistwidgetitem2->setText(QCoreApplication::translate("MainWindow", "Fisherman", nullptr));
professionList->setSortingEnabled(__sortingEnabled);
-#ifndef QT_NO_TOOLTIP
- professionList->setToolTip(QApplication::translate("MainWindow", "Select your profession", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_STATUSTIP
- professionList->setStatusTip(QApplication::translate("MainWindow", "Specify your name here", nullptr));
-#endif // QT_NO_STATUSTIP
-#ifndef QT_NO_WHATSTHIS
- professionList->setWhatsThis(QApplication::translate("MainWindow", "Specify your name here", nullptr));
-#endif // QT_NO_WHATSTHIS
- label->setText(QApplication::translate("MainWindow", "Profession:", nullptr));
- countryCombo->setItemText(0, QApplication::translate("MainWindow", "Egypt", nullptr));
- countryCombo->setItemText(1, QApplication::translate("MainWindow", "France", nullptr));
- countryCombo->setItemText(2, QApplication::translate("MainWindow", "Germany", nullptr));
- countryCombo->setItemText(3, QApplication::translate("MainWindow", "India", nullptr));
- countryCombo->setItemText(4, QApplication::translate("MainWindow", "Italy", nullptr));
- countryCombo->setItemText(5, QApplication::translate("MainWindow", "Korea", nullptr));
- countryCombo->setItemText(6, QApplication::translate("MainWindow", "Norway", nullptr));
-
-#ifndef QT_NO_TOOLTIP
- countryCombo->setToolTip(QApplication::translate("MainWindow", "Specify country of origin", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_STATUSTIP
- countryCombo->setStatusTip(QApplication::translate("MainWindow", "Specify country of origin", nullptr));
-#endif // QT_NO_STATUSTIP
- countryLabel->setText(QApplication::translate("MainWindow", "Pro&fession", nullptr));
- menu_File->setTitle(QApplication::translate("MainWindow", "&File", nullptr));
- menu_Help->setTitle(QApplication::translate("MainWindow", "&Help", nullptr));
+#if QT_CONFIG(tooltip)
+ professionList->setToolTip(QCoreApplication::translate("MainWindow", "Select your profession", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(statustip)
+ professionList->setStatusTip(QCoreApplication::translate("MainWindow", "Specify your name here", nullptr));
+#endif // QT_CONFIG(statustip)
+#if QT_CONFIG(whatsthis)
+ professionList->setWhatsThis(QCoreApplication::translate("MainWindow", "Specify your name here", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ label->setText(QCoreApplication::translate("MainWindow", "Profession:", nullptr));
+ countryCombo->setItemText(0, QCoreApplication::translate("MainWindow", "Egypt", nullptr));
+ countryCombo->setItemText(1, QCoreApplication::translate("MainWindow", "France", nullptr));
+ countryCombo->setItemText(2, QCoreApplication::translate("MainWindow", "Germany", nullptr));
+ countryCombo->setItemText(3, QCoreApplication::translate("MainWindow", "India", nullptr));
+ countryCombo->setItemText(4, QCoreApplication::translate("MainWindow", "Italy", nullptr));
+ countryCombo->setItemText(5, QCoreApplication::translate("MainWindow", "Korea", nullptr));
+ countryCombo->setItemText(6, QCoreApplication::translate("MainWindow", "Norway", nullptr));
+
+#if QT_CONFIG(tooltip)
+ countryCombo->setToolTip(QCoreApplication::translate("MainWindow", "Specify country of origin", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(statustip)
+ countryCombo->setStatusTip(QCoreApplication::translate("MainWindow", "Specify country of origin", nullptr));
+#endif // QT_CONFIG(statustip)
+ countryLabel->setText(QCoreApplication::translate("MainWindow", "Pro&fession", nullptr));
+ menu_File->setTitle(QCoreApplication::translate("MainWindow", "&File", nullptr));
+ menu_Help->setTitle(QCoreApplication::translate("MainWindow", "&Help", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/paletteeditor.ui.h b/tests/auto/tools/uic/baseline/paletteeditor.ui.h
index 0061164960..eb1cad8c3a 100644
--- a/tests/auto/tools/uic/baseline/paletteeditor.ui.h
+++ b/tests/auto/tools/uic/baseline/paletteeditor.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'paletteeditor.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -81,7 +81,7 @@ public:
if (qdesigner_internal__PaletteEditor->objectName().isEmpty())
qdesigner_internal__PaletteEditor->setObjectName(QString::fromUtf8("qdesigner_internal__PaletteEditor"));
qdesigner_internal__PaletteEditor->resize(365, 409);
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(7));
+ QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(qdesigner_internal__PaletteEditor->sizePolicy().hasHeightForWidth());
@@ -108,7 +108,7 @@ public:
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
buildButton = new QtColorButton(advancedBox);
buildButton->setObjectName(QString::fromUtf8("buildButton"));
- QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(13));
+ QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Ignored);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(buildButton->sizePolicy().hasHeightForWidth());
@@ -143,7 +143,7 @@ public:
GroupBox126 = new QGroupBox(qdesigner_internal__PaletteEditor);
GroupBox126->setObjectName(QString::fromUtf8("GroupBox126"));
- QSizePolicy sizePolicy2(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(7));
+ QSizePolicy sizePolicy2(QSizePolicy::Preferred, QSizePolicy::Expanding);
sizePolicy2.setHorizontalStretch(0);
sizePolicy2.setVerticalStretch(0);
sizePolicy2.setHeightForWidth(GroupBox126->sizePolicy().hasHeightForWidth());
@@ -197,16 +197,16 @@ public:
void retranslateUi(QDialog *qdesigner_internal__PaletteEditor)
{
- qdesigner_internal__PaletteEditor->setWindowTitle(QApplication::translate("qdesigner_internal::PaletteEditor", "Edit Palette", nullptr));
- advancedBox->setTitle(QApplication::translate("qdesigner_internal::PaletteEditor", "Tune Palette", nullptr));
+ qdesigner_internal__PaletteEditor->setWindowTitle(QCoreApplication::translate("qdesigner_internal::PaletteEditor", "Edit Palette", nullptr));
+ advancedBox->setTitle(QCoreApplication::translate("qdesigner_internal::PaletteEditor", "Tune Palette", nullptr));
buildButton->setText(QString());
- detailsRadio->setText(QApplication::translate("qdesigner_internal::PaletteEditor", "Show Details", nullptr));
- computeRadio->setText(QApplication::translate("qdesigner_internal::PaletteEditor", "Compute Details", nullptr));
- label->setText(QApplication::translate("qdesigner_internal::PaletteEditor", "Quick", nullptr));
- GroupBox126->setTitle(QApplication::translate("qdesigner_internal::PaletteEditor", "Preview", nullptr));
- disabledRadio->setText(QApplication::translate("qdesigner_internal::PaletteEditor", "Disabled", nullptr));
- inactiveRadio->setText(QApplication::translate("qdesigner_internal::PaletteEditor", "Inactive", nullptr));
- activeRadio->setText(QApplication::translate("qdesigner_internal::PaletteEditor", "Active", nullptr));
+ detailsRadio->setText(QCoreApplication::translate("qdesigner_internal::PaletteEditor", "Show Details", nullptr));
+ computeRadio->setText(QCoreApplication::translate("qdesigner_internal::PaletteEditor", "Compute Details", nullptr));
+ label->setText(QCoreApplication::translate("qdesigner_internal::PaletteEditor", "Quick", nullptr));
+ GroupBox126->setTitle(QCoreApplication::translate("qdesigner_internal::PaletteEditor", "Preview", nullptr));
+ disabledRadio->setText(QCoreApplication::translate("qdesigner_internal::PaletteEditor", "Disabled", nullptr));
+ inactiveRadio->setText(QCoreApplication::translate("qdesigner_internal::PaletteEditor", "Inactive", nullptr));
+ activeRadio->setText(QCoreApplication::translate("qdesigner_internal::PaletteEditor", "Active", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/passworddialog.ui.h b/tests/auto/tools/uic/baseline/passworddialog.ui.h
index 9ab95c4de9..0542098ec2 100644
--- a/tests/auto/tools/uic/baseline/passworddialog.ui.h
+++ b/tests/auto/tools/uic/baseline/passworddialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'passworddialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -98,11 +98,11 @@ public:
void retranslateUi(QDialog *PasswordDialog)
{
- PasswordDialog->setWindowTitle(QApplication::translate("PasswordDialog", "Authentication Required", nullptr));
- iconLabel->setText(QApplication::translate("PasswordDialog", "DUMMY ICON", nullptr));
- introLabel->setText(QApplication::translate("PasswordDialog", "INTRO TEXT DUMMY", nullptr));
- label->setText(QApplication::translate("PasswordDialog", "Username:", nullptr));
- lblPassword->setText(QApplication::translate("PasswordDialog", "Password:", nullptr));
+ PasswordDialog->setWindowTitle(QCoreApplication::translate("PasswordDialog", "Authentication Required", nullptr));
+ iconLabel->setText(QCoreApplication::translate("PasswordDialog", "DUMMY ICON", nullptr));
+ introLabel->setText(QCoreApplication::translate("PasswordDialog", "INTRO TEXT DUMMY", nullptr));
+ label->setText(QCoreApplication::translate("PasswordDialog", "Username:", nullptr));
+ lblPassword->setText(QCoreApplication::translate("PasswordDialog", "Password:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/pathpage.ui.h b/tests/auto/tools/uic/baseline/pathpage.ui.h
index eb151f9550..bc9f254965 100644
--- a/tests/auto/tools/uic/baseline/pathpage.ui.h
+++ b/tests/auto/tools/uic/baseline/pathpage.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'pathpage.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -104,11 +104,11 @@ public:
void retranslateUi(QWidget *PathPage)
{
- PathPage->setWindowTitle(QApplication::translate("PathPage", "Form", nullptr));
- label_2->setText(QApplication::translate("PathPage", "File filters:", nullptr));
- label->setText(QApplication::translate("PathPage", "Documentation source file paths:", nullptr));
- addButton->setText(QApplication::translate("PathPage", "Add", nullptr));
- removeButton->setText(QApplication::translate("PathPage", "Remove", nullptr));
+ PathPage->setWindowTitle(QCoreApplication::translate("PathPage", "Form", nullptr));
+ label_2->setText(QCoreApplication::translate("PathPage", "File filters:", nullptr));
+ label->setText(QCoreApplication::translate("PathPage", "Documentation source file paths:", nullptr));
+ addButton->setText(QCoreApplication::translate("PathPage", "Add", nullptr));
+ removeButton->setText(QCoreApplication::translate("PathPage", "Remove", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/phrasebookbox.ui.h b/tests/auto/tools/uic/baseline/phrasebookbox.ui.h
index 27a0fa79ed..25989c4bd3 100644
--- a/tests/auto/tools/uic/baseline/phrasebookbox.ui.h
+++ b/tests/auto/tools/uic/baseline/phrasebookbox.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'phrasebookbox.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -165,11 +165,11 @@ public:
unnamed->addLayout(buttonLayout);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
target->setBuddy(targetLed);
source->setBuddy(sourceLed);
definition->setBuddy(definitionLed);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
QWidget::setTabOrder(sourceLed, targetLed);
QWidget::setTabOrder(targetLed, definitionLed);
QWidget::setTabOrder(definitionLed, newBut);
@@ -184,38 +184,38 @@ public:
void retranslateUi(QDialog *PhraseBookBox)
{
- PhraseBookBox->setWindowTitle(QApplication::translate("PhraseBookBox", "Edit Phrase Book", nullptr));
-#ifndef QT_NO_WHATSTHIS
- PhraseBookBox->setWhatsThis(QApplication::translate("PhraseBookBox", "This window allows you to add, modify, or delete phrases in a phrase book.", nullptr));
-#endif // QT_NO_WHATSTHIS
- target->setText(QApplication::translate("PhraseBookBox", "&Translation:", nullptr));
-#ifndef QT_NO_WHATSTHIS
- targetLed->setWhatsThis(QApplication::translate("PhraseBookBox", "This is the phrase in the target language corresponding to the source phrase.", nullptr));
-#endif // QT_NO_WHATSTHIS
- source->setText(QApplication::translate("PhraseBookBox", "S&ource phrase:", nullptr));
-#ifndef QT_NO_WHATSTHIS
- definitionLed->setWhatsThis(QApplication::translate("PhraseBookBox", "This is a definition for the source phrase.", nullptr));
-#endif // QT_NO_WHATSTHIS
-#ifndef QT_NO_WHATSTHIS
- sourceLed->setWhatsThis(QApplication::translate("PhraseBookBox", "This is the phrase in the source language.", nullptr));
-#endif // QT_NO_WHATSTHIS
- definition->setText(QApplication::translate("PhraseBookBox", "&Definition:", nullptr));
-#ifndef QT_NO_WHATSTHIS
- newBut->setWhatsThis(QApplication::translate("PhraseBookBox", "Click here to add the phrase to the phrase book.", nullptr));
-#endif // QT_NO_WHATSTHIS
- newBut->setText(QApplication::translate("PhraseBookBox", "&New Phrase", nullptr));
-#ifndef QT_NO_WHATSTHIS
- removeBut->setWhatsThis(QApplication::translate("PhraseBookBox", "Click here to remove the phrase from the phrase book.", nullptr));
-#endif // QT_NO_WHATSTHIS
- removeBut->setText(QApplication::translate("PhraseBookBox", "&Remove Phrase", nullptr));
-#ifndef QT_NO_WHATSTHIS
- saveBut->setWhatsThis(QApplication::translate("PhraseBookBox", "Click here to save the changes made.", nullptr));
-#endif // QT_NO_WHATSTHIS
- saveBut->setText(QApplication::translate("PhraseBookBox", "&Save", nullptr));
-#ifndef QT_NO_WHATSTHIS
- closeBut->setWhatsThis(QApplication::translate("PhraseBookBox", "Click here to close this window.", nullptr));
-#endif // QT_NO_WHATSTHIS
- closeBut->setText(QApplication::translate("PhraseBookBox", "Close", nullptr));
+ PhraseBookBox->setWindowTitle(QCoreApplication::translate("PhraseBookBox", "Edit Phrase Book", nullptr));
+#if QT_CONFIG(whatsthis)
+ PhraseBookBox->setWhatsThis(QCoreApplication::translate("PhraseBookBox", "This window allows you to add, modify, or delete phrases in a phrase book.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ target->setText(QCoreApplication::translate("PhraseBookBox", "&Translation:", nullptr));
+#if QT_CONFIG(whatsthis)
+ targetLed->setWhatsThis(QCoreApplication::translate("PhraseBookBox", "This is the phrase in the target language corresponding to the source phrase.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ source->setText(QCoreApplication::translate("PhraseBookBox", "S&ource phrase:", nullptr));
+#if QT_CONFIG(whatsthis)
+ definitionLed->setWhatsThis(QCoreApplication::translate("PhraseBookBox", "This is a definition for the source phrase.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+#if QT_CONFIG(whatsthis)
+ sourceLed->setWhatsThis(QCoreApplication::translate("PhraseBookBox", "This is the phrase in the source language.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ definition->setText(QCoreApplication::translate("PhraseBookBox", "&Definition:", nullptr));
+#if QT_CONFIG(whatsthis)
+ newBut->setWhatsThis(QCoreApplication::translate("PhraseBookBox", "Click here to add the phrase to the phrase book.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ newBut->setText(QCoreApplication::translate("PhraseBookBox", "&New Phrase", nullptr));
+#if QT_CONFIG(whatsthis)
+ removeBut->setWhatsThis(QCoreApplication::translate("PhraseBookBox", "Click here to remove the phrase from the phrase book.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ removeBut->setText(QCoreApplication::translate("PhraseBookBox", "&Remove Phrase", nullptr));
+#if QT_CONFIG(whatsthis)
+ saveBut->setWhatsThis(QCoreApplication::translate("PhraseBookBox", "Click here to save the changes made.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ saveBut->setText(QCoreApplication::translate("PhraseBookBox", "&Save", nullptr));
+#if QT_CONFIG(whatsthis)
+ closeBut->setWhatsThis(QCoreApplication::translate("PhraseBookBox", "Click here to close this window.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ closeBut->setText(QCoreApplication::translate("PhraseBookBox", "Close", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/pixmapfunction.ui.h b/tests/auto/tools/uic/baseline/pixmapfunction.ui.h
index 1644380c15..5a24aeeded 100644
--- a/tests/auto/tools/uic/baseline/pixmapfunction.ui.h
+++ b/tests/auto/tools/uic/baseline/pixmapfunction.ui.h
@@ -58,9 +58,9 @@ public:
void retranslateUi(QWidget *Form)
{
- Form->setWindowTitle(QApplication::translate("Form", "Form", nullptr));
+ Form->setWindowTitle(QCoreApplication::translate("Form", "Form", nullptr));
label->setText(QString());
- pushButton->setText(QApplication::translate("Form", "PushButton", nullptr));
+ pushButton->setText(QCoreApplication::translate("Form", "PushButton", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/plugindialog.ui.h b/tests/auto/tools/uic/baseline/plugindialog.ui.h
index 3634b8436f..72e4d22b78 100644
--- a/tests/auto/tools/uic/baseline/plugindialog.ui.h
+++ b/tests/auto/tools/uic/baseline/plugindialog.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'plugindialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -111,11 +111,11 @@ public:
void retranslateUi(QDialog *PluginDialog)
{
- PluginDialog->setWindowTitle(QApplication::translate("PluginDialog", "Plugin Information", nullptr));
- label->setText(QApplication::translate("PluginDialog", "TextLabel", nullptr));
+ PluginDialog->setWindowTitle(QCoreApplication::translate("PluginDialog", "Plugin Information", nullptr));
+ label->setText(QCoreApplication::translate("PluginDialog", "TextLabel", nullptr));
QTreeWidgetItem *___qtreewidgetitem = treeWidget->headerItem();
- ___qtreewidgetitem->setText(0, QApplication::translate("PluginDialog", "1", nullptr));
- message->setText(QApplication::translate("PluginDialog", "TextLabel", nullptr));
+ ___qtreewidgetitem->setText(0, QCoreApplication::translate("PluginDialog", "1", nullptr));
+ message->setText(QCoreApplication::translate("PluginDialog", "TextLabel", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/preferencesdialog.ui.h b/tests/auto/tools/uic/baseline/preferencesdialog.ui.h
index 289e6775b4..c4002eaff7 100644
--- a/tests/auto/tools/uic/baseline/preferencesdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/preferencesdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'preferencesdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -150,11 +150,11 @@ public:
void retranslateUi(QDialog *PreferencesDialog)
{
- PreferencesDialog->setWindowTitle(QApplication::translate("PreferencesDialog", "Preferences", nullptr));
- m_uiModeGroupBox->setTitle(QApplication::translate("PreferencesDialog", "User Interface Mode", nullptr));
- m_templatePathGroupBox->setTitle(QApplication::translate("PreferencesDialog", "Additional Template Paths", nullptr));
- m_addTemplatePathButton->setText(QApplication::translate("PreferencesDialog", "...", nullptr));
- m_removeTemplatePathButton->setText(QApplication::translate("PreferencesDialog", "...", nullptr));
+ PreferencesDialog->setWindowTitle(QCoreApplication::translate("PreferencesDialog", "Preferences", nullptr));
+ m_uiModeGroupBox->setTitle(QCoreApplication::translate("PreferencesDialog", "User Interface Mode", nullptr));
+ m_templatePathGroupBox->setTitle(QCoreApplication::translate("PreferencesDialog", "Additional Template Paths", nullptr));
+ m_addTemplatePathButton->setText(QCoreApplication::translate("PreferencesDialog", "...", nullptr));
+ m_removeTemplatePathButton->setText(QCoreApplication::translate("PreferencesDialog", "...", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/previewconfigurationwidget.ui.h b/tests/auto/tools/uic/baseline/previewconfigurationwidget.ui.h
index 3c729b9c65..71e8605832 100644
--- a/tests/auto/tools/uic/baseline/previewconfigurationwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/previewconfigurationwidget.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'previewconfigurationwidget.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -108,14 +108,14 @@ public:
void retranslateUi(QGroupBox *PreviewConfigurationWidget)
{
- PreviewConfigurationWidget->setWindowTitle(QApplication::translate("PreviewConfigurationWidget", "Form", nullptr));
- PreviewConfigurationWidget->setTitle(QApplication::translate("PreviewConfigurationWidget", "Print/Preview Configuration", nullptr));
- m_styleLabel->setText(QApplication::translate("PreviewConfigurationWidget", "Style", nullptr));
- m_appStyleSheetLabel->setText(QApplication::translate("PreviewConfigurationWidget", "Style sheet", nullptr));
- m_appStyleSheetChangeButton->setText(QApplication::translate("PreviewConfigurationWidget", "...", nullptr));
- m_appStyleSheetClearButton->setText(QApplication::translate("PreviewConfigurationWidget", "...", nullptr));
- m_skinLabel->setText(QApplication::translate("PreviewConfigurationWidget", "Device skin", nullptr));
- m_skinRemoveButton->setText(QApplication::translate("PreviewConfigurationWidget", "...", nullptr));
+ PreviewConfigurationWidget->setWindowTitle(QCoreApplication::translate("PreviewConfigurationWidget", "Form", nullptr));
+ PreviewConfigurationWidget->setTitle(QCoreApplication::translate("PreviewConfigurationWidget", "Print/Preview Configuration", nullptr));
+ m_styleLabel->setText(QCoreApplication::translate("PreviewConfigurationWidget", "Style", nullptr));
+ m_appStyleSheetLabel->setText(QCoreApplication::translate("PreviewConfigurationWidget", "Style sheet", nullptr));
+ m_appStyleSheetChangeButton->setText(QCoreApplication::translate("PreviewConfigurationWidget", "...", nullptr));
+ m_appStyleSheetClearButton->setText(QCoreApplication::translate("PreviewConfigurationWidget", "...", nullptr));
+ m_skinLabel->setText(QCoreApplication::translate("PreviewConfigurationWidget", "Device skin", nullptr));
+ m_skinRemoveButton->setText(QCoreApplication::translate("PreviewConfigurationWidget", "...", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/previewdialogbase.ui.h b/tests/auto/tools/uic/baseline/previewdialogbase.ui.h
index 8d4c0dae9f..5ff155de13 100644
--- a/tests/auto/tools/uic/baseline/previewdialogbase.ui.h
+++ b/tests/auto/tools/uic/baseline/previewdialogbase.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'previewdialogbase.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -70,7 +70,7 @@ public:
paperSizeCombo = new QComboBox(PreviewDialogBase);
paperSizeCombo->setObjectName(QString::fromUtf8("paperSizeCombo"));
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(1), static_cast<QSizePolicy::Policy>(0));
+ QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(paperSizeCombo->sizePolicy().hasHeightForWidth());
@@ -115,7 +115,7 @@ public:
previewArea = new QScrollArea(PreviewDialogBase);
previewArea->setObjectName(QString::fromUtf8("previewArea"));
- QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(5));
+ QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Preferred);
sizePolicy1.setHorizontalStretch(1);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(previewArea->sizePolicy().hasHeightForWidth());
@@ -135,7 +135,7 @@ public:
progressBar = new QProgressBar(PreviewDialogBase);
progressBar->setObjectName(QString::fromUtf8("progressBar"));
progressBar->setEnabled(false);
- QSizePolicy sizePolicy2(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(0));
+ QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed);
sizePolicy2.setHorizontalStretch(1);
sizePolicy2.setVerticalStretch(0);
sizePolicy2.setHeightForWidth(progressBar->sizePolicy().hasHeightForWidth());
@@ -156,10 +156,10 @@ public:
vboxLayout->addLayout(hboxLayout2);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(paperSizeCombo);
label_2->setBuddy(paperOrientationCombo);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(PreviewDialogBase);
QObject::connect(buttonBox, SIGNAL(accepted()), PreviewDialogBase, SLOT(accept()));
@@ -170,11 +170,11 @@ public:
void retranslateUi(QDialog *PreviewDialogBase)
{
- PreviewDialogBase->setWindowTitle(QApplication::translate("PreviewDialogBase", "Print Preview", nullptr));
- label->setText(QApplication::translate("PreviewDialogBase", "&Paper Size:", nullptr));
- label_2->setText(QApplication::translate("PreviewDialogBase", "&Orientation:", nullptr));
+ PreviewDialogBase->setWindowTitle(QCoreApplication::translate("PreviewDialogBase", "Print Preview", nullptr));
+ label->setText(QCoreApplication::translate("PreviewDialogBase", "&Paper Size:", nullptr));
+ label_2->setText(QCoreApplication::translate("PreviewDialogBase", "&Orientation:", nullptr));
QTreeWidgetItem *___qtreewidgetitem = pageList->headerItem();
- ___qtreewidgetitem->setText(0, QApplication::translate("PreviewDialogBase", "1", nullptr));
+ ___qtreewidgetitem->setText(0, QCoreApplication::translate("PreviewDialogBase", "1", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/previewwidget.ui.h b/tests/auto/tools/uic/baseline/previewwidget.ui.h
index 6e359416c8..47563587fb 100644
--- a/tests/auto/tools/uic/baseline/previewwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/previewwidget.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'previewwidget.ui'
**
-** Created by: Qt User Interface Compiler version 5.10.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -92,7 +92,7 @@ public:
if (qdesigner_internal__PreviewWidget->objectName().isEmpty())
qdesigner_internal__PreviewWidget->setObjectName(QString::fromUtf8("qdesigner_internal__PreviewWidget"));
qdesigner_internal__PreviewWidget->resize(471, 251);
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(1), static_cast<QSizePolicy::Policy>(1));
+ QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(qdesigner_internal__PreviewWidget->sizePolicy().hasHeightForWidth());
@@ -235,18 +235,18 @@ public:
void retranslateUi(QWidget *qdesigner_internal__PreviewWidget)
{
- qdesigner_internal__PreviewWidget->setWindowTitle(QApplication::translate("qdesigner_internal::PreviewWidget", "Preview Window", nullptr));
- LineEdit1->setText(QApplication::translate("qdesigner_internal::PreviewWidget", "LineEdit", nullptr));
- ComboBox1->setItemText(0, QApplication::translate("qdesigner_internal::PreviewWidget", "ComboBox", nullptr));
-
- PushButton1->setText(QApplication::translate("qdesigner_internal::PreviewWidget", "PushButton", nullptr));
- ButtonGroup2->setTitle(QApplication::translate("qdesigner_internal::PreviewWidget", "ButtonGroup2", nullptr));
- CheckBox1->setText(QApplication::translate("qdesigner_internal::PreviewWidget", "CheckBox1", nullptr));
- CheckBox2->setText(QApplication::translate("qdesigner_internal::PreviewWidget", "CheckBox2", nullptr));
- ButtonGroup1->setTitle(QApplication::translate("qdesigner_internal::PreviewWidget", "ButtonGroup", nullptr));
- RadioButton1->setText(QApplication::translate("qdesigner_internal::PreviewWidget", "RadioButton1", nullptr));
- RadioButton2->setText(QApplication::translate("qdesigner_internal::PreviewWidget", "RadioButton2", nullptr));
- RadioButton3->setText(QApplication::translate("qdesigner_internal::PreviewWidget", "RadioButton3", nullptr));
+ qdesigner_internal__PreviewWidget->setWindowTitle(QCoreApplication::translate("qdesigner_internal::PreviewWidget", "Preview Window", nullptr));
+ LineEdit1->setText(QCoreApplication::translate("qdesigner_internal::PreviewWidget", "LineEdit", nullptr));
+ ComboBox1->setItemText(0, QCoreApplication::translate("qdesigner_internal::PreviewWidget", "ComboBox", nullptr));
+
+ PushButton1->setText(QCoreApplication::translate("qdesigner_internal::PreviewWidget", "PushButton", nullptr));
+ ButtonGroup2->setTitle(QCoreApplication::translate("qdesigner_internal::PreviewWidget", "ButtonGroup2", nullptr));
+ CheckBox1->setText(QCoreApplication::translate("qdesigner_internal::PreviewWidget", "CheckBox1", nullptr));
+ CheckBox2->setText(QCoreApplication::translate("qdesigner_internal::PreviewWidget", "CheckBox2", nullptr));
+ ButtonGroup1->setTitle(QCoreApplication::translate("qdesigner_internal::PreviewWidget", "ButtonGroup", nullptr));
+ RadioButton1->setText(QCoreApplication::translate("qdesigner_internal::PreviewWidget", "RadioButton1", nullptr));
+ RadioButton2->setText(QCoreApplication::translate("qdesigner_internal::PreviewWidget", "RadioButton2", nullptr));
+ RadioButton3->setText(QCoreApplication::translate("qdesigner_internal::PreviewWidget", "RadioButton3", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/proxy.ui.h b/tests/auto/tools/uic/baseline/proxy.ui.h
index a1bc287190..1ecea389f3 100644
--- a/tests/auto/tools/uic/baseline/proxy.ui.h
+++ b/tests/auto/tools/uic/baseline/proxy.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'proxy.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -87,11 +87,11 @@ public:
void retranslateUi(QDialog *ProxyDialog)
{
- ProxyDialog->setWindowTitle(QApplication::translate("ProxyDialog", "Proxy Authentication", nullptr));
- iconLabel->setText(QApplication::translate("ProxyDialog", "ICON", nullptr));
- introLabel->setText(QApplication::translate("ProxyDialog", "Connect to proxy", nullptr));
- usernameLabel->setText(QApplication::translate("ProxyDialog", "Username:", nullptr));
- passwordLabel->setText(QApplication::translate("ProxyDialog", "Password:", nullptr));
+ ProxyDialog->setWindowTitle(QCoreApplication::translate("ProxyDialog", "Proxy Authentication", nullptr));
+ iconLabel->setText(QCoreApplication::translate("ProxyDialog", "ICON", nullptr));
+ introLabel->setText(QCoreApplication::translate("ProxyDialog", "Connect to proxy", nullptr));
+ usernameLabel->setText(QCoreApplication::translate("ProxyDialog", "Username:", nullptr));
+ passwordLabel->setText(QCoreApplication::translate("ProxyDialog", "Password:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qfiledialog.ui.h b/tests/auto/tools/uic/baseline/qfiledialog.ui.h
index 53607db449..9e51ee6a7c 100644
--- a/tests/auto/tools/uic/baseline/qfiledialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qfiledialog.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'qfiledialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -271,26 +271,26 @@ public:
void retranslateUi(QDialog *QFileDialog)
{
- lookInLabel->setText(QApplication::translate("QFileDialog", "Look in:", nullptr));
-#ifndef QT_NO_TOOLTIP
- backButton->setToolTip(QApplication::translate("QFileDialog", "Back", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- forwardButton->setToolTip(QApplication::translate("QFileDialog", "Forward", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- toParentButton->setToolTip(QApplication::translate("QFileDialog", "Parent Directory", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- newFolderButton->setToolTip(QApplication::translate("QFileDialog", "Create New Folder", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- listModeButton->setToolTip(QApplication::translate("QFileDialog", "List View", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- detailModeButton->setToolTip(QApplication::translate("QFileDialog", "Detail View", nullptr));
-#endif // QT_NO_TOOLTIP
- fileTypeLabel->setText(QApplication::translate("QFileDialog", "Files of type:", nullptr));
+ lookInLabel->setText(QCoreApplication::translate("QFileDialog", "Look in:", nullptr));
+#if QT_CONFIG(tooltip)
+ backButton->setToolTip(QCoreApplication::translate("QFileDialog", "Back", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ forwardButton->setToolTip(QCoreApplication::translate("QFileDialog", "Forward", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ toParentButton->setToolTip(QCoreApplication::translate("QFileDialog", "Parent Directory", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ newFolderButton->setToolTip(QCoreApplication::translate("QFileDialog", "Create New Folder", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ listModeButton->setToolTip(QCoreApplication::translate("QFileDialog", "List View", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ detailModeButton->setToolTip(QCoreApplication::translate("QFileDialog", "Detail View", nullptr));
+#endif // QT_CONFIG(tooltip)
+ fileTypeLabel->setText(QCoreApplication::translate("QFileDialog", "Files of type:", nullptr));
Q_UNUSED(QFileDialog);
} // retranslateUi
diff --git a/tests/auto/tools/uic/baseline/qpagesetupwidget.ui.h b/tests/auto/tools/uic/baseline/qpagesetupwidget.ui.h
index a5379bc468..d21d6da972 100644
--- a/tests/auto/tools/uic/baseline/qpagesetupwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/qpagesetupwidget.ui.h
@@ -290,12 +290,12 @@ public:
gridLayout_3->addItem(verticalSpacer, 6, 0, 1, 1);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
pageSizeLabel->setBuddy(pageSizeCombo);
widthLabel->setBuddy(pageWidth);
heightLabel->setBuddy(pageHeight);
paperSourceLabel->setBuddy(paperSource);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(QPageSetupWidget);
@@ -304,45 +304,45 @@ public:
void retranslateUi(QWidget *QPageSetupWidget)
{
- QPageSetupWidget->setWindowTitle(QApplication::translate("QPageSetupWidget", "Form", nullptr));
- groupBox_2->setTitle(QApplication::translate("QPageSetupWidget", "Paper", nullptr));
- pageSizeLabel->setText(QApplication::translate("QPageSetupWidget", "Page size:", nullptr));
- widthLabel->setText(QApplication::translate("QPageSetupWidget", "Width:", nullptr));
- heightLabel->setText(QApplication::translate("QPageSetupWidget", "Height:", nullptr));
- paperSourceLabel->setText(QApplication::translate("QPageSetupWidget", "Paper source:", nullptr));
- groupBox_3->setTitle(QApplication::translate("QPageSetupWidget", "Orientation", nullptr));
- portrait->setText(QApplication::translate("QPageSetupWidget", "Portrait", nullptr));
- landscape->setText(QApplication::translate("QPageSetupWidget", "Landscape", nullptr));
- reverseLandscape->setText(QApplication::translate("QPageSetupWidget", "Reverse landscape", nullptr));
- reversePortrait->setText(QApplication::translate("QPageSetupWidget", "Reverse portrait", nullptr));
- groupBox->setTitle(QApplication::translate("QPageSetupWidget", "Margins", nullptr));
-#ifndef QT_NO_TOOLTIP
- topMargin->setToolTip(QApplication::translate("QPageSetupWidget", "top margin", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_ACCESSIBILITY
- topMargin->setAccessibleName(QApplication::translate("QPageSetupWidget", "top margin", nullptr));
-#endif // QT_NO_ACCESSIBILITY
-#ifndef QT_NO_TOOLTIP
- leftMargin->setToolTip(QApplication::translate("QPageSetupWidget", "left margin", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_ACCESSIBILITY
- leftMargin->setAccessibleName(QApplication::translate("QPageSetupWidget", "left margin", nullptr));
-#endif // QT_NO_ACCESSIBILITY
-#ifndef QT_NO_TOOLTIP
- rightMargin->setToolTip(QApplication::translate("QPageSetupWidget", "right margin", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_ACCESSIBILITY
- rightMargin->setAccessibleName(QApplication::translate("QPageSetupWidget", "right margin", nullptr));
-#endif // QT_NO_ACCESSIBILITY
-#ifndef QT_NO_TOOLTIP
- bottomMargin->setToolTip(QApplication::translate("QPageSetupWidget", "bottom margin", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_ACCESSIBILITY
- bottomMargin->setAccessibleName(QApplication::translate("QPageSetupWidget", "bottom margin", nullptr));
-#endif // QT_NO_ACCESSIBILITY
- pagesPerSheetButtonGroup->setTitle(QApplication::translate("QPageSetupWidget", "Page Layout", nullptr));
- label->setText(QApplication::translate("QPageSetupWidget", "Page order:", nullptr));
- label_2->setText(QApplication::translate("QPageSetupWidget", "Pages per sheet:", nullptr));
+ QPageSetupWidget->setWindowTitle(QCoreApplication::translate("QPageSetupWidget", "Form", nullptr));
+ groupBox_2->setTitle(QCoreApplication::translate("QPageSetupWidget", "Paper", nullptr));
+ pageSizeLabel->setText(QCoreApplication::translate("QPageSetupWidget", "Page size:", nullptr));
+ widthLabel->setText(QCoreApplication::translate("QPageSetupWidget", "Width:", nullptr));
+ heightLabel->setText(QCoreApplication::translate("QPageSetupWidget", "Height:", nullptr));
+ paperSourceLabel->setText(QCoreApplication::translate("QPageSetupWidget", "Paper source:", nullptr));
+ groupBox_3->setTitle(QCoreApplication::translate("QPageSetupWidget", "Orientation", nullptr));
+ portrait->setText(QCoreApplication::translate("QPageSetupWidget", "Portrait", nullptr));
+ landscape->setText(QCoreApplication::translate("QPageSetupWidget", "Landscape", nullptr));
+ reverseLandscape->setText(QCoreApplication::translate("QPageSetupWidget", "Reverse landscape", nullptr));
+ reversePortrait->setText(QCoreApplication::translate("QPageSetupWidget", "Reverse portrait", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("QPageSetupWidget", "Margins", nullptr));
+#if QT_CONFIG(tooltip)
+ topMargin->setToolTip(QCoreApplication::translate("QPageSetupWidget", "top margin", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(accessibility)
+ topMargin->setAccessibleName(QCoreApplication::translate("QPageSetupWidget", "top margin", nullptr));
+#endif // QT_CONFIG(accessibility)
+#if QT_CONFIG(tooltip)
+ leftMargin->setToolTip(QCoreApplication::translate("QPageSetupWidget", "left margin", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(accessibility)
+ leftMargin->setAccessibleName(QCoreApplication::translate("QPageSetupWidget", "left margin", nullptr));
+#endif // QT_CONFIG(accessibility)
+#if QT_CONFIG(tooltip)
+ rightMargin->setToolTip(QCoreApplication::translate("QPageSetupWidget", "right margin", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(accessibility)
+ rightMargin->setAccessibleName(QCoreApplication::translate("QPageSetupWidget", "right margin", nullptr));
+#endif // QT_CONFIG(accessibility)
+#if QT_CONFIG(tooltip)
+ bottomMargin->setToolTip(QCoreApplication::translate("QPageSetupWidget", "bottom margin", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(accessibility)
+ bottomMargin->setAccessibleName(QCoreApplication::translate("QPageSetupWidget", "bottom margin", nullptr));
+#endif // QT_CONFIG(accessibility)
+ pagesPerSheetButtonGroup->setTitle(QCoreApplication::translate("QPageSetupWidget", "Page Layout", nullptr));
+ label->setText(QCoreApplication::translate("QPageSetupWidget", "Page order:", nullptr));
+ label_2->setText(QCoreApplication::translate("QPageSetupWidget", "Pages per sheet:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qprintpropertieswidget.ui.h b/tests/auto/tools/uic/baseline/qprintpropertieswidget.ui.h
index 8626a9fc3c..f0e06548b5 100644
--- a/tests/auto/tools/uic/baseline/qprintpropertieswidget.ui.h
+++ b/tests/auto/tools/uic/baseline/qprintpropertieswidget.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'qprintpropertieswidget.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -79,9 +79,9 @@ public:
void retranslateUi(QWidget *QPrintPropertiesWidget)
{
- QPrintPropertiesWidget->setWindowTitle(QApplication::translate("QPrintPropertiesWidget", "Form", nullptr));
- tabs->setTabText(tabs->indexOf(tabPage), QApplication::translate("QPrintPropertiesWidget", "Page", nullptr));
- tabs->setTabText(tabs->indexOf(cupsPropertiesPage), QApplication::translate("QPrintPropertiesWidget", "Advanced", nullptr));
+ QPrintPropertiesWidget->setWindowTitle(QCoreApplication::translate("QPrintPropertiesWidget", "Form", nullptr));
+ tabs->setTabText(tabs->indexOf(tabPage), QCoreApplication::translate("QPrintPropertiesWidget", "Page", nullptr));
+ tabs->setTabText(tabs->indexOf(cupsPropertiesPage), QCoreApplication::translate("QPrintPropertiesWidget", "Advanced", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qprintsettingsoutput.ui.h b/tests/auto/tools/uic/baseline/qprintsettingsoutput.ui.h
index 656b5f9deb..3d37a55548 100644
--- a/tests/auto/tools/uic/baseline/qprintsettingsoutput.ui.h
+++ b/tests/auto/tools/uic/baseline/qprintsettingsoutput.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'qprintsettingsoutput.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -260,9 +260,9 @@ public:
horizontalLayout_2->addWidget(tabs);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(copies);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(QPrintSettingsOutput);
QObject::connect(printRange, SIGNAL(toggled(bool)), from, SLOT(setEnabled(bool)));
@@ -276,25 +276,25 @@ public:
void retranslateUi(QWidget *QPrintSettingsOutput)
{
- QPrintSettingsOutput->setWindowTitle(QApplication::translate("QPrintSettingsOutput", "Form", nullptr));
- gbPrintRange->setTitle(QApplication::translate("QPrintSettingsOutput", "Print range", nullptr));
- printAll->setText(QApplication::translate("QPrintSettingsOutput", "Print all", nullptr));
- printRange->setText(QApplication::translate("QPrintSettingsOutput", "Pages from", nullptr));
- label_3->setText(QApplication::translate("QPrintSettingsOutput", "to", nullptr));
- printSelection->setText(QApplication::translate("QPrintSettingsOutput", "Selection", nullptr));
- groupBox->setTitle(QApplication::translate("QPrintSettingsOutput", "Output Settings", nullptr));
- label->setText(QApplication::translate("QPrintSettingsOutput", "Copies:", nullptr));
- collate->setText(QApplication::translate("QPrintSettingsOutput", "Collate", nullptr));
- reverse->setText(QApplication::translate("QPrintSettingsOutput", "Reverse", nullptr));
- tabs->setTabText(tabs->indexOf(copiesTab), QApplication::translate("QPrintSettingsOutput", "Copies", nullptr));
- colorMode->setTitle(QApplication::translate("QPrintSettingsOutput", "Color Mode", nullptr));
- color->setText(QApplication::translate("QPrintSettingsOutput", "Color", nullptr));
- grayscale->setText(QApplication::translate("QPrintSettingsOutput", "Grayscale", nullptr));
- duplex->setTitle(QApplication::translate("QPrintSettingsOutput", "Duplex Printing", nullptr));
- noDuplex->setText(QApplication::translate("QPrintSettingsOutput", "None", nullptr));
- duplexLong->setText(QApplication::translate("QPrintSettingsOutput", "Long side", nullptr));
- duplexShort->setText(QApplication::translate("QPrintSettingsOutput", "Short side", nullptr));
- tabs->setTabText(tabs->indexOf(optionsTab), QApplication::translate("QPrintSettingsOutput", "Options", nullptr));
+ QPrintSettingsOutput->setWindowTitle(QCoreApplication::translate("QPrintSettingsOutput", "Form", nullptr));
+ gbPrintRange->setTitle(QCoreApplication::translate("QPrintSettingsOutput", "Print range", nullptr));
+ printAll->setText(QCoreApplication::translate("QPrintSettingsOutput", "Print all", nullptr));
+ printRange->setText(QCoreApplication::translate("QPrintSettingsOutput", "Pages from", nullptr));
+ label_3->setText(QCoreApplication::translate("QPrintSettingsOutput", "to", nullptr));
+ printSelection->setText(QCoreApplication::translate("QPrintSettingsOutput", "Selection", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("QPrintSettingsOutput", "Output Settings", nullptr));
+ label->setText(QCoreApplication::translate("QPrintSettingsOutput", "Copies:", nullptr));
+ collate->setText(QCoreApplication::translate("QPrintSettingsOutput", "Collate", nullptr));
+ reverse->setText(QCoreApplication::translate("QPrintSettingsOutput", "Reverse", nullptr));
+ tabs->setTabText(tabs->indexOf(copiesTab), QCoreApplication::translate("QPrintSettingsOutput", "Copies", nullptr));
+ colorMode->setTitle(QCoreApplication::translate("QPrintSettingsOutput", "Color Mode", nullptr));
+ color->setText(QCoreApplication::translate("QPrintSettingsOutput", "Color", nullptr));
+ grayscale->setText(QCoreApplication::translate("QPrintSettingsOutput", "Grayscale", nullptr));
+ duplex->setTitle(QCoreApplication::translate("QPrintSettingsOutput", "Duplex Printing", nullptr));
+ noDuplex->setText(QCoreApplication::translate("QPrintSettingsOutput", "None", nullptr));
+ duplexLong->setText(QCoreApplication::translate("QPrintSettingsOutput", "Long side", nullptr));
+ duplexShort->setText(QCoreApplication::translate("QPrintSettingsOutput", "Short side", nullptr));
+ tabs->setTabText(tabs->indexOf(optionsTab), QCoreApplication::translate("QPrintSettingsOutput", "Options", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qprintwidget.ui.h b/tests/auto/tools/uic/baseline/qprintwidget.ui.h
index 04b05143c6..5b1d921173 100644
--- a/tests/auto/tools/uic/baseline/qprintwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/qprintwidget.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'qprintwidget.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -128,10 +128,10 @@ public:
horizontalLayout_2->addWidget(printerGroup);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(printers);
lOutput->setBuddy(filename);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(QPrintWidget);
@@ -140,15 +140,15 @@ public:
void retranslateUi(QWidget *QPrintWidget)
{
- QPrintWidget->setWindowTitle(QApplication::translate("QPrintWidget", "Form", nullptr));
- printerGroup->setTitle(QApplication::translate("QPrintWidget", "Printer", nullptr));
- label->setText(QApplication::translate("QPrintWidget", "&Name:", nullptr));
- properties->setText(QApplication::translate("QPrintWidget", "P&roperties", nullptr));
- label_2->setText(QApplication::translate("QPrintWidget", "Location:", nullptr));
- preview->setText(QApplication::translate("QPrintWidget", "Preview", nullptr));
- label_3->setText(QApplication::translate("QPrintWidget", "Type:", nullptr));
- lOutput->setText(QApplication::translate("QPrintWidget", "Output &file:", nullptr));
- fileBrowser->setText(QApplication::translate("QPrintWidget", "...", nullptr));
+ QPrintWidget->setWindowTitle(QCoreApplication::translate("QPrintWidget", "Form", nullptr));
+ printerGroup->setTitle(QCoreApplication::translate("QPrintWidget", "Printer", nullptr));
+ label->setText(QCoreApplication::translate("QPrintWidget", "&Name:", nullptr));
+ properties->setText(QCoreApplication::translate("QPrintWidget", "P&roperties", nullptr));
+ label_2->setText(QCoreApplication::translate("QPrintWidget", "Location:", nullptr));
+ preview->setText(QCoreApplication::translate("QPrintWidget", "Preview", nullptr));
+ label_3->setText(QCoreApplication::translate("QPrintWidget", "Type:", nullptr));
+ lOutput->setText(QCoreApplication::translate("QPrintWidget", "Output &file:", nullptr));
+ fileBrowser->setText(QCoreApplication::translate("QPrintWidget", "...", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h b/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h
index 2131bc6d9b..681c1f97da 100644
--- a/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'qsqlconnectiondialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -179,14 +179,14 @@ public:
vboxLayout->addLayout(hboxLayout1);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
textLabel4->setBuddy(editUsername);
textLabel2->setBuddy(comboDriver);
textLabel3->setBuddy(editDatabase);
textLabel5->setBuddy(editHostname);
textLabel5_2->setBuddy(portSpinBox);
textLabel4_2->setBuddy(editPassword);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
QWidget::setTabOrder(comboDriver, editDatabase);
QWidget::setTabOrder(editDatabase, editUsername);
QWidget::setTabOrder(editUsername, editPassword);
@@ -206,18 +206,18 @@ public:
void retranslateUi(QDialog *QSqlConnectionDialogUi)
{
- QSqlConnectionDialogUi->setWindowTitle(QApplication::translate("QSqlConnectionDialogUi", "Connect...", nullptr));
- connGroupBox->setTitle(QApplication::translate("QSqlConnectionDialogUi", "Connection settings", nullptr));
- textLabel4->setText(QApplication::translate("QSqlConnectionDialogUi", "&Username:", nullptr));
- textLabel2->setText(QApplication::translate("QSqlConnectionDialogUi", "D&river", nullptr));
- portSpinBox->setSpecialValueText(QApplication::translate("QSqlConnectionDialogUi", "Default", nullptr));
- textLabel3->setText(QApplication::translate("QSqlConnectionDialogUi", "Database Name:", nullptr));
- textLabel5->setText(QApplication::translate("QSqlConnectionDialogUi", "&Hostname:", nullptr));
- textLabel5_2->setText(QApplication::translate("QSqlConnectionDialogUi", "P&ort:", nullptr));
- textLabel4_2->setText(QApplication::translate("QSqlConnectionDialogUi", "&Password:", nullptr));
- dbCheckBox->setText(QApplication::translate("QSqlConnectionDialogUi", "Us&e predefined in-memory database", nullptr));
- okButton->setText(QApplication::translate("QSqlConnectionDialogUi", "&OK", nullptr));
- cancelButton->setText(QApplication::translate("QSqlConnectionDialogUi", "&Cancel", nullptr));
+ QSqlConnectionDialogUi->setWindowTitle(QCoreApplication::translate("QSqlConnectionDialogUi", "Connect...", nullptr));
+ connGroupBox->setTitle(QCoreApplication::translate("QSqlConnectionDialogUi", "Connection settings", nullptr));
+ textLabel4->setText(QCoreApplication::translate("QSqlConnectionDialogUi", "&Username:", nullptr));
+ textLabel2->setText(QCoreApplication::translate("QSqlConnectionDialogUi", "D&river", nullptr));
+ portSpinBox->setSpecialValueText(QCoreApplication::translate("QSqlConnectionDialogUi", "Default", nullptr));
+ textLabel3->setText(QCoreApplication::translate("QSqlConnectionDialogUi", "Database Name:", nullptr));
+ textLabel5->setText(QCoreApplication::translate("QSqlConnectionDialogUi", "&Hostname:", nullptr));
+ textLabel5_2->setText(QCoreApplication::translate("QSqlConnectionDialogUi", "P&ort:", nullptr));
+ textLabel4_2->setText(QCoreApplication::translate("QSqlConnectionDialogUi", "&Password:", nullptr));
+ dbCheckBox->setText(QCoreApplication::translate("QSqlConnectionDialogUi", "Us&e predefined in-memory database", nullptr));
+ okButton->setText(QCoreApplication::translate("QSqlConnectionDialogUi", "&OK", nullptr));
+ cancelButton->setText(QCoreApplication::translate("QSqlConnectionDialogUi", "&Cancel", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qtgradientdialog.ui.h b/tests/auto/tools/uic/baseline/qtgradientdialog.ui.h
index 805f70e60d..5c09962572 100644
--- a/tests/auto/tools/uic/baseline/qtgradientdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qtgradientdialog.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'qtgradientdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -89,7 +89,7 @@ public:
void retranslateUi(QDialog *QtGradientDialog)
{
- QtGradientDialog->setWindowTitle(QApplication::translate("QtGradientDialog", "Edit Gradient", nullptr));
+ QtGradientDialog->setWindowTitle(QCoreApplication::translate("QtGradientDialog", "Edit Gradient", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qtgradienteditor.ui.h b/tests/auto/tools/uic/baseline/qtgradienteditor.ui.h
index 9db07f35ac..7ca14d6ef4 100644
--- a/tests/auto/tools/uic/baseline/qtgradienteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/qtgradienteditor.ui.h
@@ -583,119 +583,119 @@ public:
void retranslateUi(QWidget *QtGradientEditor)
{
- QtGradientEditor->setWindowTitle(QApplication::translate("QtGradientEditor", "Form", nullptr));
-#ifndef QT_NO_TOOLTIP
- gradientWidget->setToolTip(QApplication::translate("QtGradientEditor", "Gradient Editor", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_WHATSTHIS
- gradientWidget->setWhatsThis(QApplication::translate("QtGradientEditor", "This area shows a preview of the gradient being edited. It also allows you to edit parameters specific to the gradient's type such as start and final point, radius, etc. by drag & drop.", nullptr));
-#endif // QT_NO_WHATSTHIS
- label1->setText(QApplication::translate("QtGradientEditor", "1", nullptr));
- label2->setText(QApplication::translate("QtGradientEditor", "2", nullptr));
- label3->setText(QApplication::translate("QtGradientEditor", "3", nullptr));
- label4->setText(QApplication::translate("QtGradientEditor", "4", nullptr));
- label5->setText(QApplication::translate("QtGradientEditor", "5", nullptr));
-#ifndef QT_NO_TOOLTIP
- gradientStopsWidget->setToolTip(QApplication::translate("QtGradientEditor", "Gradient Stops Editor", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_WHATSTHIS
- gradientStopsWidget->setWhatsThis(QApplication::translate("QtGradientEditor", "This area allows you to edit gradient stops. Double click on the existing stop handle to duplicate it. Double click outside of the existing stop handles to create a new stop. Drag & drop the handle to reposition it. Use right mouse button to popup context menu with extra actions.", nullptr));
-#endif // QT_NO_WHATSTHIS
- zoomLabel->setText(QApplication::translate("QtGradientEditor", "Zoom", nullptr));
-#ifndef QT_NO_TOOLTIP
- zoomAllButton->setToolTip(QApplication::translate("QtGradientEditor", "Reset Zoom", nullptr));
-#endif // QT_NO_TOOLTIP
- zoomAllButton->setText(QApplication::translate("QtGradientEditor", "Reset Zoom", nullptr));
- positionLabel->setText(QApplication::translate("QtGradientEditor", "Position", nullptr));
-#ifndef QT_NO_TOOLTIP
- hLabel->setToolTip(QApplication::translate("QtGradientEditor", "Hue", nullptr));
-#endif // QT_NO_TOOLTIP
- hLabel->setText(QApplication::translate("QtGradientEditor", "H", nullptr));
-#ifndef QT_NO_TOOLTIP
- hueColorLine->setToolTip(QApplication::translate("QtGradientEditor", "Hue", nullptr));
-#endif // QT_NO_TOOLTIP
- hueLabel->setText(QApplication::translate("QtGradientEditor", "Hue", nullptr));
-#ifndef QT_NO_TOOLTIP
- sLabel->setToolTip(QApplication::translate("QtGradientEditor", "Saturation", nullptr));
-#endif // QT_NO_TOOLTIP
- sLabel->setText(QApplication::translate("QtGradientEditor", "S", nullptr));
-#ifndef QT_NO_TOOLTIP
- saturationColorLine->setToolTip(QApplication::translate("QtGradientEditor", "Saturation", nullptr));
-#endif // QT_NO_TOOLTIP
- saturationLabel->setText(QApplication::translate("QtGradientEditor", "Sat", nullptr));
-#ifndef QT_NO_TOOLTIP
- vLabel->setToolTip(QApplication::translate("QtGradientEditor", "Value", nullptr));
-#endif // QT_NO_TOOLTIP
- vLabel->setText(QApplication::translate("QtGradientEditor", "V", nullptr));
-#ifndef QT_NO_TOOLTIP
- valueColorLine->setToolTip(QApplication::translate("QtGradientEditor", "Value", nullptr));
-#endif // QT_NO_TOOLTIP
- valueLabel->setText(QApplication::translate("QtGradientEditor", "Val", nullptr));
-#ifndef QT_NO_TOOLTIP
- aLabel->setToolTip(QApplication::translate("QtGradientEditor", "Alpha", nullptr));
-#endif // QT_NO_TOOLTIP
- aLabel->setText(QApplication::translate("QtGradientEditor", "A", nullptr));
-#ifndef QT_NO_TOOLTIP
- alphaColorLine->setToolTip(QApplication::translate("QtGradientEditor", "Alpha", nullptr));
-#endif // QT_NO_TOOLTIP
- alphaLabel->setText(QApplication::translate("QtGradientEditor", "Alpha", nullptr));
-#ifndef QT_NO_TOOLTIP
- typeComboBox->setToolTip(QApplication::translate("QtGradientEditor", "Type", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- spreadComboBox->setToolTip(QApplication::translate("QtGradientEditor", "Spread", nullptr));
-#endif // QT_NO_TOOLTIP
- colorLabel->setText(QApplication::translate("QtGradientEditor", "Color", nullptr));
-#ifndef QT_NO_TOOLTIP
- colorButton->setToolTip(QApplication::translate("QtGradientEditor", "Current stop's color", nullptr));
-#endif // QT_NO_TOOLTIP
+ QtGradientEditor->setWindowTitle(QCoreApplication::translate("QtGradientEditor", "Form", nullptr));
+#if QT_CONFIG(tooltip)
+ gradientWidget->setToolTip(QCoreApplication::translate("QtGradientEditor", "Gradient Editor", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(whatsthis)
+ gradientWidget->setWhatsThis(QCoreApplication::translate("QtGradientEditor", "This area shows a preview of the gradient being edited. It also allows you to edit parameters specific to the gradient's type such as start and final point, radius, etc. by drag & drop.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ label1->setText(QCoreApplication::translate("QtGradientEditor", "1", nullptr));
+ label2->setText(QCoreApplication::translate("QtGradientEditor", "2", nullptr));
+ label3->setText(QCoreApplication::translate("QtGradientEditor", "3", nullptr));
+ label4->setText(QCoreApplication::translate("QtGradientEditor", "4", nullptr));
+ label5->setText(QCoreApplication::translate("QtGradientEditor", "5", nullptr));
+#if QT_CONFIG(tooltip)
+ gradientStopsWidget->setToolTip(QCoreApplication::translate("QtGradientEditor", "Gradient Stops Editor", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(whatsthis)
+ gradientStopsWidget->setWhatsThis(QCoreApplication::translate("QtGradientEditor", "This area allows you to edit gradient stops. Double click on the existing stop handle to duplicate it. Double click outside of the existing stop handles to create a new stop. Drag & drop the handle to reposition it. Use right mouse button to popup context menu with extra actions.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ zoomLabel->setText(QCoreApplication::translate("QtGradientEditor", "Zoom", nullptr));
+#if QT_CONFIG(tooltip)
+ zoomAllButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Reset Zoom", nullptr));
+#endif // QT_CONFIG(tooltip)
+ zoomAllButton->setText(QCoreApplication::translate("QtGradientEditor", "Reset Zoom", nullptr));
+ positionLabel->setText(QCoreApplication::translate("QtGradientEditor", "Position", nullptr));
+#if QT_CONFIG(tooltip)
+ hLabel->setToolTip(QCoreApplication::translate("QtGradientEditor", "Hue", nullptr));
+#endif // QT_CONFIG(tooltip)
+ hLabel->setText(QCoreApplication::translate("QtGradientEditor", "H", nullptr));
+#if QT_CONFIG(tooltip)
+ hueColorLine->setToolTip(QCoreApplication::translate("QtGradientEditor", "Hue", nullptr));
+#endif // QT_CONFIG(tooltip)
+ hueLabel->setText(QCoreApplication::translate("QtGradientEditor", "Hue", nullptr));
+#if QT_CONFIG(tooltip)
+ sLabel->setToolTip(QCoreApplication::translate("QtGradientEditor", "Saturation", nullptr));
+#endif // QT_CONFIG(tooltip)
+ sLabel->setText(QCoreApplication::translate("QtGradientEditor", "S", nullptr));
+#if QT_CONFIG(tooltip)
+ saturationColorLine->setToolTip(QCoreApplication::translate("QtGradientEditor", "Saturation", nullptr));
+#endif // QT_CONFIG(tooltip)
+ saturationLabel->setText(QCoreApplication::translate("QtGradientEditor", "Sat", nullptr));
+#if QT_CONFIG(tooltip)
+ vLabel->setToolTip(QCoreApplication::translate("QtGradientEditor", "Value", nullptr));
+#endif // QT_CONFIG(tooltip)
+ vLabel->setText(QCoreApplication::translate("QtGradientEditor", "V", nullptr));
+#if QT_CONFIG(tooltip)
+ valueColorLine->setToolTip(QCoreApplication::translate("QtGradientEditor", "Value", nullptr));
+#endif // QT_CONFIG(tooltip)
+ valueLabel->setText(QCoreApplication::translate("QtGradientEditor", "Val", nullptr));
+#if QT_CONFIG(tooltip)
+ aLabel->setToolTip(QCoreApplication::translate("QtGradientEditor", "Alpha", nullptr));
+#endif // QT_CONFIG(tooltip)
+ aLabel->setText(QCoreApplication::translate("QtGradientEditor", "A", nullptr));
+#if QT_CONFIG(tooltip)
+ alphaColorLine->setToolTip(QCoreApplication::translate("QtGradientEditor", "Alpha", nullptr));
+#endif // QT_CONFIG(tooltip)
+ alphaLabel->setText(QCoreApplication::translate("QtGradientEditor", "Alpha", nullptr));
+#if QT_CONFIG(tooltip)
+ typeComboBox->setToolTip(QCoreApplication::translate("QtGradientEditor", "Type", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ spreadComboBox->setToolTip(QCoreApplication::translate("QtGradientEditor", "Spread", nullptr));
+#endif // QT_CONFIG(tooltip)
+ colorLabel->setText(QCoreApplication::translate("QtGradientEditor", "Color", nullptr));
+#if QT_CONFIG(tooltip)
+ colorButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Current stop's color", nullptr));
+#endif // QT_CONFIG(tooltip)
colorButton->setText(QString());
-#ifndef QT_NO_TOOLTIP
- hsvRadioButton->setToolTip(QApplication::translate("QtGradientEditor", "Show HSV specification", nullptr));
-#endif // QT_NO_TOOLTIP
- hsvRadioButton->setText(QApplication::translate("QtGradientEditor", "HSV", nullptr));
-#ifndef QT_NO_TOOLTIP
- rgbRadioButton->setToolTip(QApplication::translate("QtGradientEditor", "Show RGB specification", nullptr));
-#endif // QT_NO_TOOLTIP
- rgbRadioButton->setText(QApplication::translate("QtGradientEditor", "RGB", nullptr));
-#ifndef QT_NO_TOOLTIP
- positionSpinBox->setToolTip(QApplication::translate("QtGradientEditor", "Current stop's position", nullptr));
-#endif // QT_NO_TOOLTIP
- zoomSpinBox->setSuffix(QApplication::translate("QtGradientEditor", "%", nullptr));
-#ifndef QT_NO_TOOLTIP
- zoomInButton->setToolTip(QApplication::translate("QtGradientEditor", "Zoom In", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- zoomOutButton->setToolTip(QApplication::translate("QtGradientEditor", "Zoom Out", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- detailsButton->setToolTip(QApplication::translate("QtGradientEditor", "Toggle details extension", nullptr));
-#endif // QT_NO_TOOLTIP
- detailsButton->setText(QApplication::translate("QtGradientEditor", ">", nullptr));
-#ifndef QT_NO_TOOLTIP
- linearButton->setToolTip(QApplication::translate("QtGradientEditor", "Linear Type", nullptr));
-#endif // QT_NO_TOOLTIP
- linearButton->setText(QApplication::translate("QtGradientEditor", "...", nullptr));
-#ifndef QT_NO_TOOLTIP
- radialButton->setToolTip(QApplication::translate("QtGradientEditor", "Radial Type", nullptr));
-#endif // QT_NO_TOOLTIP
- radialButton->setText(QApplication::translate("QtGradientEditor", "...", nullptr));
-#ifndef QT_NO_TOOLTIP
- conicalButton->setToolTip(QApplication::translate("QtGradientEditor", "Conical Type", nullptr));
-#endif // QT_NO_TOOLTIP
- conicalButton->setText(QApplication::translate("QtGradientEditor", "...", nullptr));
-#ifndef QT_NO_TOOLTIP
- padButton->setToolTip(QApplication::translate("QtGradientEditor", "Pad Spread", nullptr));
-#endif // QT_NO_TOOLTIP
- padButton->setText(QApplication::translate("QtGradientEditor", "...", nullptr));
-#ifndef QT_NO_TOOLTIP
- repeatButton->setToolTip(QApplication::translate("QtGradientEditor", "Repeat Spread", nullptr));
-#endif // QT_NO_TOOLTIP
- repeatButton->setText(QApplication::translate("QtGradientEditor", "...", nullptr));
-#ifndef QT_NO_TOOLTIP
- reflectButton->setToolTip(QApplication::translate("QtGradientEditor", "Reflect Spread", nullptr));
-#endif // QT_NO_TOOLTIP
- reflectButton->setText(QApplication::translate("QtGradientEditor", "...", nullptr));
+#if QT_CONFIG(tooltip)
+ hsvRadioButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Show HSV specification", nullptr));
+#endif // QT_CONFIG(tooltip)
+ hsvRadioButton->setText(QCoreApplication::translate("QtGradientEditor", "HSV", nullptr));
+#if QT_CONFIG(tooltip)
+ rgbRadioButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Show RGB specification", nullptr));
+#endif // QT_CONFIG(tooltip)
+ rgbRadioButton->setText(QCoreApplication::translate("QtGradientEditor", "RGB", nullptr));
+#if QT_CONFIG(tooltip)
+ positionSpinBox->setToolTip(QCoreApplication::translate("QtGradientEditor", "Current stop's position", nullptr));
+#endif // QT_CONFIG(tooltip)
+ zoomSpinBox->setSuffix(QCoreApplication::translate("QtGradientEditor", "%", nullptr));
+#if QT_CONFIG(tooltip)
+ zoomInButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Zoom In", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ zoomOutButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Zoom Out", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ detailsButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Toggle details extension", nullptr));
+#endif // QT_CONFIG(tooltip)
+ detailsButton->setText(QCoreApplication::translate("QtGradientEditor", ">", nullptr));
+#if QT_CONFIG(tooltip)
+ linearButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Linear Type", nullptr));
+#endif // QT_CONFIG(tooltip)
+ linearButton->setText(QCoreApplication::translate("QtGradientEditor", "...", nullptr));
+#if QT_CONFIG(tooltip)
+ radialButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Radial Type", nullptr));
+#endif // QT_CONFIG(tooltip)
+ radialButton->setText(QCoreApplication::translate("QtGradientEditor", "...", nullptr));
+#if QT_CONFIG(tooltip)
+ conicalButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Conical Type", nullptr));
+#endif // QT_CONFIG(tooltip)
+ conicalButton->setText(QCoreApplication::translate("QtGradientEditor", "...", nullptr));
+#if QT_CONFIG(tooltip)
+ padButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Pad Spread", nullptr));
+#endif // QT_CONFIG(tooltip)
+ padButton->setText(QCoreApplication::translate("QtGradientEditor", "...", nullptr));
+#if QT_CONFIG(tooltip)
+ repeatButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Repeat Spread", nullptr));
+#endif // QT_CONFIG(tooltip)
+ repeatButton->setText(QCoreApplication::translate("QtGradientEditor", "...", nullptr));
+#if QT_CONFIG(tooltip)
+ reflectButton->setToolTip(QCoreApplication::translate("QtGradientEditor", "Reflect Spread", nullptr));
+#endif // QT_CONFIG(tooltip)
+ reflectButton->setText(QCoreApplication::translate("QtGradientEditor", "...", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qtgradientview.ui.h b/tests/auto/tools/uic/baseline/qtgradientview.ui.h
index aa3c03b02f..494324b00f 100644
--- a/tests/auto/tools/uic/baseline/qtgradientview.ui.h
+++ b/tests/auto/tools/uic/baseline/qtgradientview.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'qtgradientview.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -105,11 +105,11 @@ public:
void retranslateUi(QWidget *QtGradientView)
{
- QtGradientView->setWindowTitle(QApplication::translate("QtGradientView", "Gradient View", nullptr));
- newButton->setText(QApplication::translate("QtGradientView", "New...", nullptr));
- editButton->setText(QApplication::translate("QtGradientView", "Edit...", nullptr));
- renameButton->setText(QApplication::translate("QtGradientView", "Rename", nullptr));
- removeButton->setText(QApplication::translate("QtGradientView", "Remove", nullptr));
+ QtGradientView->setWindowTitle(QCoreApplication::translate("QtGradientView", "Gradient View", nullptr));
+ newButton->setText(QCoreApplication::translate("QtGradientView", "New...", nullptr));
+ editButton->setText(QCoreApplication::translate("QtGradientView", "Edit...", nullptr));
+ renameButton->setText(QCoreApplication::translate("QtGradientView", "Rename", nullptr));
+ removeButton->setText(QCoreApplication::translate("QtGradientView", "Remove", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qtgradientviewdialog.ui.h b/tests/auto/tools/uic/baseline/qtgradientviewdialog.ui.h
index e6d98ed4f0..f6369c8c5f 100644
--- a/tests/auto/tools/uic/baseline/qtgradientviewdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qtgradientviewdialog.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'qtgradientviewdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -89,7 +89,7 @@ public:
void retranslateUi(QDialog *QtGradientViewDialog)
{
- QtGradientViewDialog->setWindowTitle(QApplication::translate("QtGradientViewDialog", "Select Gradient", nullptr));
+ QtGradientViewDialog->setWindowTitle(QCoreApplication::translate("QtGradientViewDialog", "Select Gradient", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qtresourceeditordialog.ui.h b/tests/auto/tools/uic/baseline/qtresourceeditordialog.ui.h
index 6a8c9c7172..7428778a9c 100644
--- a/tests/auto/tools/uic/baseline/qtresourceeditordialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qtresourceeditordialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'qtresourceeditordialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -141,25 +141,25 @@ public:
void retranslateUi(QDialog *QtResourceEditorDialog)
{
- QtResourceEditorDialog->setWindowTitle(QApplication::translate("QtResourceEditorDialog", "Dialog", nullptr));
-#ifndef QT_NO_TOOLTIP
- newQrcButton->setToolTip(QApplication::translate("QtResourceEditorDialog", "New File", nullptr));
-#endif // QT_NO_TOOLTIP
- newQrcButton->setText(QApplication::translate("QtResourceEditorDialog", "N", nullptr));
-#ifndef QT_NO_TOOLTIP
- removeQrcButton->setToolTip(QApplication::translate("QtResourceEditorDialog", "Remove File", nullptr));
-#endif // QT_NO_TOOLTIP
- removeQrcButton->setText(QApplication::translate("QtResourceEditorDialog", "R", nullptr));
- importQrcButton->setText(QApplication::translate("QtResourceEditorDialog", "I", nullptr));
-#ifndef QT_NO_TOOLTIP
- newResourceButton->setToolTip(QApplication::translate("QtResourceEditorDialog", "New Resource", nullptr));
-#endif // QT_NO_TOOLTIP
- newResourceButton->setText(QApplication::translate("QtResourceEditorDialog", "N", nullptr));
- addResourceButton->setText(QApplication::translate("QtResourceEditorDialog", "A", nullptr));
-#ifndef QT_NO_TOOLTIP
- removeResourceButton->setToolTip(QApplication::translate("QtResourceEditorDialog", "Remove Resource or File", nullptr));
-#endif // QT_NO_TOOLTIP
- removeResourceButton->setText(QApplication::translate("QtResourceEditorDialog", "R", nullptr));
+ QtResourceEditorDialog->setWindowTitle(QCoreApplication::translate("QtResourceEditorDialog", "Dialog", nullptr));
+#if QT_CONFIG(tooltip)
+ newQrcButton->setToolTip(QCoreApplication::translate("QtResourceEditorDialog", "New File", nullptr));
+#endif // QT_CONFIG(tooltip)
+ newQrcButton->setText(QCoreApplication::translate("QtResourceEditorDialog", "N", nullptr));
+#if QT_CONFIG(tooltip)
+ removeQrcButton->setToolTip(QCoreApplication::translate("QtResourceEditorDialog", "Remove File", nullptr));
+#endif // QT_CONFIG(tooltip)
+ removeQrcButton->setText(QCoreApplication::translate("QtResourceEditorDialog", "R", nullptr));
+ importQrcButton->setText(QCoreApplication::translate("QtResourceEditorDialog", "I", nullptr));
+#if QT_CONFIG(tooltip)
+ newResourceButton->setToolTip(QCoreApplication::translate("QtResourceEditorDialog", "New Resource", nullptr));
+#endif // QT_CONFIG(tooltip)
+ newResourceButton->setText(QCoreApplication::translate("QtResourceEditorDialog", "N", nullptr));
+ addResourceButton->setText(QCoreApplication::translate("QtResourceEditorDialog", "A", nullptr));
+#if QT_CONFIG(tooltip)
+ removeResourceButton->setToolTip(QCoreApplication::translate("QtResourceEditorDialog", "Remove Resource or File", nullptr));
+#endif // QT_CONFIG(tooltip)
+ removeResourceButton->setText(QCoreApplication::translate("QtResourceEditorDialog", "R", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/qttoolbardialog.ui.h b/tests/auto/tools/uic/baseline/qttoolbardialog.ui.h
index e893386d9b..bfaeb99af2 100644
--- a/tests/auto/tools/uic/baseline/qttoolbardialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qttoolbardialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'qttoolbardialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -178,40 +178,40 @@ public:
void retranslateUi(QDialog *QtToolBarDialog)
{
- QtToolBarDialog->setWindowTitle(QApplication::translate("QtToolBarDialog", "Customize Toolbars", nullptr));
+ QtToolBarDialog->setWindowTitle(QCoreApplication::translate("QtToolBarDialog", "Customize Toolbars", nullptr));
QTreeWidgetItem *___qtreewidgetitem = actionTree->headerItem();
- ___qtreewidgetitem->setText(0, QApplication::translate("QtToolBarDialog", "1", nullptr));
- label->setText(QApplication::translate("QtToolBarDialog", "Actions", nullptr));
- label_2->setText(QApplication::translate("QtToolBarDialog", "Toolbars", nullptr));
-#ifndef QT_NO_TOOLTIP
- newButton->setToolTip(QApplication::translate("QtToolBarDialog", "Add new toolbar", nullptr));
-#endif // QT_NO_TOOLTIP
- newButton->setText(QApplication::translate("QtToolBarDialog", "New", nullptr));
-#ifndef QT_NO_TOOLTIP
- removeButton->setToolTip(QApplication::translate("QtToolBarDialog", "Remove selected toolbar", nullptr));
-#endif // QT_NO_TOOLTIP
- removeButton->setText(QApplication::translate("QtToolBarDialog", "Remove", nullptr));
-#ifndef QT_NO_TOOLTIP
- renameButton->setToolTip(QApplication::translate("QtToolBarDialog", "Rename toolbar", nullptr));
-#endif // QT_NO_TOOLTIP
- renameButton->setText(QApplication::translate("QtToolBarDialog", "Rename", nullptr));
-#ifndef QT_NO_TOOLTIP
- upButton->setToolTip(QApplication::translate("QtToolBarDialog", "Move action up", nullptr));
-#endif // QT_NO_TOOLTIP
- upButton->setText(QApplication::translate("QtToolBarDialog", "Up", nullptr));
-#ifndef QT_NO_TOOLTIP
- leftButton->setToolTip(QApplication::translate("QtToolBarDialog", "Remove action from toolbar", nullptr));
-#endif // QT_NO_TOOLTIP
- leftButton->setText(QApplication::translate("QtToolBarDialog", "<-", nullptr));
-#ifndef QT_NO_TOOLTIP
- rightButton->setToolTip(QApplication::translate("QtToolBarDialog", "Add action to toolbar", nullptr));
-#endif // QT_NO_TOOLTIP
- rightButton->setText(QApplication::translate("QtToolBarDialog", "->", nullptr));
-#ifndef QT_NO_TOOLTIP
- downButton->setToolTip(QApplication::translate("QtToolBarDialog", "Move action down", nullptr));
-#endif // QT_NO_TOOLTIP
- downButton->setText(QApplication::translate("QtToolBarDialog", "Down", nullptr));
- label_3->setText(QApplication::translate("QtToolBarDialog", "Current Toolbar Actions", nullptr));
+ ___qtreewidgetitem->setText(0, QCoreApplication::translate("QtToolBarDialog", "1", nullptr));
+ label->setText(QCoreApplication::translate("QtToolBarDialog", "Actions", nullptr));
+ label_2->setText(QCoreApplication::translate("QtToolBarDialog", "Toolbars", nullptr));
+#if QT_CONFIG(tooltip)
+ newButton->setToolTip(QCoreApplication::translate("QtToolBarDialog", "Add new toolbar", nullptr));
+#endif // QT_CONFIG(tooltip)
+ newButton->setText(QCoreApplication::translate("QtToolBarDialog", "New", nullptr));
+#if QT_CONFIG(tooltip)
+ removeButton->setToolTip(QCoreApplication::translate("QtToolBarDialog", "Remove selected toolbar", nullptr));
+#endif // QT_CONFIG(tooltip)
+ removeButton->setText(QCoreApplication::translate("QtToolBarDialog", "Remove", nullptr));
+#if QT_CONFIG(tooltip)
+ renameButton->setToolTip(QCoreApplication::translate("QtToolBarDialog", "Rename toolbar", nullptr));
+#endif // QT_CONFIG(tooltip)
+ renameButton->setText(QCoreApplication::translate("QtToolBarDialog", "Rename", nullptr));
+#if QT_CONFIG(tooltip)
+ upButton->setToolTip(QCoreApplication::translate("QtToolBarDialog", "Move action up", nullptr));
+#endif // QT_CONFIG(tooltip)
+ upButton->setText(QCoreApplication::translate("QtToolBarDialog", "Up", nullptr));
+#if QT_CONFIG(tooltip)
+ leftButton->setToolTip(QCoreApplication::translate("QtToolBarDialog", "Remove action from toolbar", nullptr));
+#endif // QT_CONFIG(tooltip)
+ leftButton->setText(QCoreApplication::translate("QtToolBarDialog", "<-", nullptr));
+#if QT_CONFIG(tooltip)
+ rightButton->setToolTip(QCoreApplication::translate("QtToolBarDialog", "Add action to toolbar", nullptr));
+#endif // QT_CONFIG(tooltip)
+ rightButton->setText(QCoreApplication::translate("QtToolBarDialog", "->", nullptr));
+#if QT_CONFIG(tooltip)
+ downButton->setToolTip(QCoreApplication::translate("QtToolBarDialog", "Move action down", nullptr));
+#endif // QT_CONFIG(tooltip)
+ downButton->setText(QCoreApplication::translate("QtToolBarDialog", "Down", nullptr));
+ label_3->setText(QCoreApplication::translate("QtToolBarDialog", "Current Toolbar Actions", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/querywidget.ui.h b/tests/auto/tools/uic/baseline/querywidget.ui.h
index 81516722d5..a92c60f4fe 100644
--- a/tests/auto/tools/uic/baseline/querywidget.ui.h
+++ b/tests/auto/tools/uic/baseline/querywidget.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'querywidget.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -153,10 +153,10 @@ public:
void retranslateUi(QMainWindow *QueryWidget)
{
- QueryWidget->setWindowTitle(QApplication::translate("QueryWidget", "Recipes XQuery Example", nullptr));
- inputGroupBox->setTitle(QApplication::translate("QueryWidget", "Input Document", nullptr));
- queryGroupBox->setTitle(QApplication::translate("QueryWidget", "Select your query:", nullptr));
- outputGroupBox->setTitle(QApplication::translate("QueryWidget", "Output Document", nullptr));
+ QueryWidget->setWindowTitle(QCoreApplication::translate("QueryWidget", "Recipes XQuery Example", nullptr));
+ inputGroupBox->setTitle(QCoreApplication::translate("QueryWidget", "Input Document", nullptr));
+ queryGroupBox->setTitle(QCoreApplication::translate("QueryWidget", "Select your query:", nullptr));
+ outputGroupBox->setTitle(QCoreApplication::translate("QueryWidget", "Output Document", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/remotecontrol.ui.h b/tests/auto/tools/uic/baseline/remotecontrol.ui.h
index 5893ff42af..5b7c6c42c2 100644
--- a/tests/auto/tools/uic/baseline/remotecontrol.ui.h
+++ b/tests/auto/tools/uic/baseline/remotecontrol.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'remotecontrol.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -222,22 +222,22 @@ public:
void retranslateUi(QMainWindow *RemoteControlClass)
{
- RemoteControlClass->setWindowTitle(QApplication::translate("RemoteControlClass", "RemoteControl", nullptr));
- actionQuit->setText(QApplication::translate("RemoteControlClass", "Quit", nullptr));
- label->setText(QApplication::translate("RemoteControlClass", "Start URL:", nullptr));
- launchButton->setText(QApplication::translate("RemoteControlClass", "Launch Qt HelpViewer", nullptr));
- actionGroupBox->setTitle(QApplication::translate("RemoteControlClass", "Actions", nullptr));
- label_2->setText(QApplication::translate("RemoteControlClass", "Search in Index:", nullptr));
+ RemoteControlClass->setWindowTitle(QCoreApplication::translate("RemoteControlClass", "RemoteControl", nullptr));
+ actionQuit->setText(QCoreApplication::translate("RemoteControlClass", "Quit", nullptr));
+ label->setText(QCoreApplication::translate("RemoteControlClass", "Start URL:", nullptr));
+ launchButton->setText(QCoreApplication::translate("RemoteControlClass", "Launch Qt HelpViewer", nullptr));
+ actionGroupBox->setTitle(QCoreApplication::translate("RemoteControlClass", "Actions", nullptr));
+ label_2->setText(QCoreApplication::translate("RemoteControlClass", "Search in Index:", nullptr));
indexButton->setText(QString());
- label_4->setText(QApplication::translate("RemoteControlClass", "Identifier:", nullptr));
+ label_4->setText(QCoreApplication::translate("RemoteControlClass", "Identifier:", nullptr));
identifierButton->setText(QString());
- label_3->setText(QApplication::translate("RemoteControlClass", "Show URL:", nullptr));
+ label_3->setText(QCoreApplication::translate("RemoteControlClass", "Show URL:", nullptr));
urlButton->setText(QString());
- syncContentsButton->setText(QApplication::translate("RemoteControlClass", "Sync Contents", nullptr));
- contentsCheckBox->setText(QApplication::translate("RemoteControlClass", "Show Contents", nullptr));
- indexCheckBox->setText(QApplication::translate("RemoteControlClass", "Show Index", nullptr));
- bookmarksCheckBox->setText(QApplication::translate("RemoteControlClass", "Show Bookmarks", nullptr));
- menuFile->setTitle(QApplication::translate("RemoteControlClass", "File", nullptr));
+ syncContentsButton->setText(QCoreApplication::translate("RemoteControlClass", "Sync Contents", nullptr));
+ contentsCheckBox->setText(QCoreApplication::translate("RemoteControlClass", "Show Contents", nullptr));
+ indexCheckBox->setText(QCoreApplication::translate("RemoteControlClass", "Show Index", nullptr));
+ bookmarksCheckBox->setText(QCoreApplication::translate("RemoteControlClass", "Show Bookmarks", nullptr));
+ menuFile->setTitle(QCoreApplication::translate("RemoteControlClass", "File", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/saveformastemplate.ui.h b/tests/auto/tools/uic/baseline/saveformastemplate.ui.h
index 9ef6eedb4c..6829958463 100644
--- a/tests/auto/tools/uic/baseline/saveformastemplate.ui.h
+++ b/tests/auto/tools/uic/baseline/saveformastemplate.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'saveformastemplate.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -117,10 +117,10 @@ public:
vboxLayout->addWidget(buttonBox);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(templateNameEdit);
label_2->setBuddy(categoryCombo);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(SaveFormAsTemplate);
QObject::connect(buttonBox, SIGNAL(accepted()), SaveFormAsTemplate, SLOT(accept()));
@@ -131,10 +131,10 @@ public:
void retranslateUi(QDialog *SaveFormAsTemplate)
{
- SaveFormAsTemplate->setWindowTitle(QApplication::translate("SaveFormAsTemplate", "Save Form As Template", nullptr));
- label->setText(QApplication::translate("SaveFormAsTemplate", "&Name:", nullptr));
+ SaveFormAsTemplate->setWindowTitle(QCoreApplication::translate("SaveFormAsTemplate", "Save Form As Template", nullptr));
+ label->setText(QCoreApplication::translate("SaveFormAsTemplate", "&Name:", nullptr));
templateNameEdit->setText(QString());
- label_2->setText(QApplication::translate("SaveFormAsTemplate", "&Category:", nullptr));
+ label_2->setText(QCoreApplication::translate("SaveFormAsTemplate", "&Category:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/settings.ui.h b/tests/auto/tools/uic/baseline/settings.ui.h
index cc680c8033..6a1adb2d2c 100644
--- a/tests/auto/tools/uic/baseline/settings.ui.h
+++ b/tests/auto/tools/uic/baseline/settings.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'settings.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -182,13 +182,13 @@ public:
void retranslateUi(QDialog *Dialog)
{
- Dialog->setWindowTitle(QApplication::translate("Dialog", "Dialog", nullptr));
- label->setText(QApplication::translate("Dialog", "Audio device:", nullptr));
- label_6->setText(QApplication::translate("Dialog", "Audio effect:", nullptr));
- crossFadeLabel->setText(QApplication::translate("Dialog", "Cross fade:", nullptr));
- label_3->setText(QApplication::translate("Dialog", "-10 Sec", nullptr));
- label_5->setText(QApplication::translate("Dialog", "0", nullptr));
- label_4->setText(QApplication::translate("Dialog", "10 Sec", nullptr));
+ Dialog->setWindowTitle(QCoreApplication::translate("Dialog", "Dialog", nullptr));
+ label->setText(QCoreApplication::translate("Dialog", "Audio device:", nullptr));
+ label_6->setText(QCoreApplication::translate("Dialog", "Audio effect:", nullptr));
+ crossFadeLabel->setText(QCoreApplication::translate("Dialog", "Cross fade:", nullptr));
+ label_3->setText(QCoreApplication::translate("Dialog", "-10 Sec", nullptr));
+ label_5->setText(QCoreApplication::translate("Dialog", "0", nullptr));
+ label_4->setText(QCoreApplication::translate("Dialog", "10 Sec", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/signalslotdialog.ui.h b/tests/auto/tools/uic/baseline/signalslotdialog.ui.h
index 5833a25a8b..143e281a24 100644
--- a/tests/auto/tools/uic/baseline/signalslotdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/signalslotdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'signalslotdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -133,25 +133,25 @@ public:
void retranslateUi(QDialog *SignalSlotDialogClass)
{
- SignalSlotDialogClass->setWindowTitle(QApplication::translate("SignalSlotDialogClass", "Signals and slots", nullptr));
- slotGroupBox->setTitle(QApplication::translate("SignalSlotDialogClass", "Slots", nullptr));
-#ifndef QT_NO_TOOLTIP
- addSlotButton->setToolTip(QApplication::translate("SignalSlotDialogClass", "Add", nullptr));
-#endif // QT_NO_TOOLTIP
- addSlotButton->setText(QApplication::translate("SignalSlotDialogClass", "...", nullptr));
-#ifndef QT_NO_TOOLTIP
- removeSlotButton->setToolTip(QApplication::translate("SignalSlotDialogClass", "Delete", nullptr));
-#endif // QT_NO_TOOLTIP
- removeSlotButton->setText(QApplication::translate("SignalSlotDialogClass", "...", nullptr));
- signalGroupBox->setTitle(QApplication::translate("SignalSlotDialogClass", "Signals", nullptr));
-#ifndef QT_NO_TOOLTIP
- addSignalButton->setToolTip(QApplication::translate("SignalSlotDialogClass", "Add", nullptr));
-#endif // QT_NO_TOOLTIP
- addSignalButton->setText(QApplication::translate("SignalSlotDialogClass", "...", nullptr));
-#ifndef QT_NO_TOOLTIP
- removeSignalButton->setToolTip(QApplication::translate("SignalSlotDialogClass", "Delete", nullptr));
-#endif // QT_NO_TOOLTIP
- removeSignalButton->setText(QApplication::translate("SignalSlotDialogClass", "...", nullptr));
+ SignalSlotDialogClass->setWindowTitle(QCoreApplication::translate("SignalSlotDialogClass", "Signals and slots", nullptr));
+ slotGroupBox->setTitle(QCoreApplication::translate("SignalSlotDialogClass", "Slots", nullptr));
+#if QT_CONFIG(tooltip)
+ addSlotButton->setToolTip(QCoreApplication::translate("SignalSlotDialogClass", "Add", nullptr));
+#endif // QT_CONFIG(tooltip)
+ addSlotButton->setText(QCoreApplication::translate("SignalSlotDialogClass", "...", nullptr));
+#if QT_CONFIG(tooltip)
+ removeSlotButton->setToolTip(QCoreApplication::translate("SignalSlotDialogClass", "Delete", nullptr));
+#endif // QT_CONFIG(tooltip)
+ removeSlotButton->setText(QCoreApplication::translate("SignalSlotDialogClass", "...", nullptr));
+ signalGroupBox->setTitle(QCoreApplication::translate("SignalSlotDialogClass", "Signals", nullptr));
+#if QT_CONFIG(tooltip)
+ addSignalButton->setToolTip(QCoreApplication::translate("SignalSlotDialogClass", "Add", nullptr));
+#endif // QT_CONFIG(tooltip)
+ addSignalButton->setText(QCoreApplication::translate("SignalSlotDialogClass", "...", nullptr));
+#if QT_CONFIG(tooltip)
+ removeSignalButton->setToolTip(QCoreApplication::translate("SignalSlotDialogClass", "Delete", nullptr));
+#endif // QT_CONFIG(tooltip)
+ removeSignalButton->setText(QCoreApplication::translate("SignalSlotDialogClass", "...", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/sslclient.ui.h b/tests/auto/tools/uic/baseline/sslclient.ui.h
index 382889648e..755ea7827b 100644
--- a/tests/auto/tools/uic/baseline/sslclient.ui.h
+++ b/tests/auto/tools/uic/baseline/sslclient.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'sslclient.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -155,20 +155,20 @@ public:
void retranslateUi(QWidget *Form)
{
- Form->setWindowTitle(QApplication::translate("Form", "Secure Socket Client", nullptr));
- hostNameLabel->setText(QApplication::translate("Form", "Host name:", nullptr));
- hostNameEdit->setText(QApplication::translate("Form", "imap.example.com", nullptr));
- portLabel->setText(QApplication::translate("Form", "Port:", nullptr));
- connectButton->setText(QApplication::translate("Form", "Connect to host", nullptr));
- sessionBox->setTitle(QApplication::translate("Form", "Active session", nullptr));
- cipherText->setText(QApplication::translate("Form", "Cryptographic Cipher:", nullptr));
- cipherLabel->setText(QApplication::translate("Form", "<none>", nullptr));
- sessionOutput->setHtml(QApplication::translate("Form", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
+ Form->setWindowTitle(QCoreApplication::translate("Form", "Secure Socket Client", nullptr));
+ hostNameLabel->setText(QCoreApplication::translate("Form", "Host name:", nullptr));
+ hostNameEdit->setText(QCoreApplication::translate("Form", "imap.example.com", nullptr));
+ portLabel->setText(QCoreApplication::translate("Form", "Port:", nullptr));
+ connectButton->setText(QCoreApplication::translate("Form", "Connect to host", nullptr));
+ sessionBox->setTitle(QCoreApplication::translate("Form", "Active session", nullptr));
+ cipherText->setText(QCoreApplication::translate("Form", "Cryptographic Cipher:", nullptr));
+ cipherLabel->setText(QCoreApplication::translate("Form", "<none>", nullptr));
+ sessionOutput->setHtml(QCoreApplication::translate("Form", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"></p></body></html>", nullptr));
- sessionInputLabel->setText(QApplication::translate("Form", "Input:", nullptr));
- sendButton->setText(QApplication::translate("Form", "&Send", nullptr));
+ sessionInputLabel->setText(QCoreApplication::translate("Form", "Input:", nullptr));
+ sendButton->setText(QCoreApplication::translate("Form", "&Send", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/sslerrors.ui.h b/tests/auto/tools/uic/baseline/sslerrors.ui.h
index 04f21ded43..ac40fe8244 100644
--- a/tests/auto/tools/uic/baseline/sslerrors.ui.h
+++ b/tests/auto/tools/uic/baseline/sslerrors.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'sslerrors.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -86,14 +86,14 @@ public:
void retranslateUi(QDialog *SslErrors)
{
- SslErrors->setWindowTitle(QApplication::translate("SslErrors", "Unable To Validate The Connection", nullptr));
- label->setText(QApplication::translate("SslErrors", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
+ SslErrors->setWindowTitle(QCoreApplication::translate("SslErrors", "Unable To Validate The Connection", nullptr));
+ label->setText(QCoreApplication::translate("SslErrors", "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; color:#ff0000;\">Warning</span><span style=\" color:#ff0000;\">:</span><span style=\" color:#000000;\"> One or more errors with this connection prevent validating the authenticity of the host you are connecting to. Please review the following list of errors, and click </span><span style=\" color:#000000;\">Ignore</span><span style=\" color:#000000;\"> to continue, or </span><span style=\" color:#000000;\">Cancel</span><span style=\" color:#000000;\"> to abort the connection.</span></p></body></html>", nullptr));
- certificateChainButton->setText(QApplication::translate("SslErrors", "View Certificate Chain", nullptr));
- pushButton->setText(QApplication::translate("SslErrors", "Ignore", nullptr));
- pushButton_2->setText(QApplication::translate("SslErrors", "Cancel", nullptr));
+ certificateChainButton->setText(QCoreApplication::translate("SslErrors", "View Certificate Chain", nullptr));
+ pushButton->setText(QCoreApplication::translate("SslErrors", "Ignore", nullptr));
+ pushButton_2->setText(QCoreApplication::translate("SslErrors", "Cancel", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/statistics.ui.h b/tests/auto/tools/uic/baseline/statistics.ui.h
index 0b508836f2..6bbb6dbc32 100644
--- a/tests/auto/tools/uic/baseline/statistics.ui.h
+++ b/tests/auto/tools/uic/baseline/statistics.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'statistics.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -179,19 +179,19 @@ public:
void retranslateUi(QDialog *Statistics)
{
- Statistics->setWindowTitle(QApplication::translate("Statistics", "Statistics", nullptr));
- closeBtn->setText(QApplication::translate("Statistics", "&Close", nullptr));
- textLabel4->setText(QApplication::translate("Statistics", "Translation", nullptr));
- textLabel5->setText(QApplication::translate("Statistics", "Source", nullptr));
- untrWords->setText(QApplication::translate("Statistics", "0", nullptr));
- trWords->setText(QApplication::translate("Statistics", "0", nullptr));
- textLabel1->setText(QApplication::translate("Statistics", "Words:", nullptr));
- trChars->setText(QApplication::translate("Statistics", "0", nullptr));
- untrChars->setText(QApplication::translate("Statistics", "0", nullptr));
- textLabel3->setText(QApplication::translate("Statistics", "Characters:", nullptr));
- textLabel6->setText(QApplication::translate("Statistics", "Characters (with spaces):", nullptr));
- trCharsSpc->setText(QApplication::translate("Statistics", "0", nullptr));
- untrCharsSpc->setText(QApplication::translate("Statistics", "0", nullptr));
+ Statistics->setWindowTitle(QCoreApplication::translate("Statistics", "Statistics", nullptr));
+ closeBtn->setText(QCoreApplication::translate("Statistics", "&Close", nullptr));
+ textLabel4->setText(QCoreApplication::translate("Statistics", "Translation", nullptr));
+ textLabel5->setText(QCoreApplication::translate("Statistics", "Source", nullptr));
+ untrWords->setText(QCoreApplication::translate("Statistics", "0", nullptr));
+ trWords->setText(QCoreApplication::translate("Statistics", "0", nullptr));
+ textLabel1->setText(QCoreApplication::translate("Statistics", "Words:", nullptr));
+ trChars->setText(QCoreApplication::translate("Statistics", "0", nullptr));
+ untrChars->setText(QCoreApplication::translate("Statistics", "0", nullptr));
+ textLabel3->setText(QCoreApplication::translate("Statistics", "Characters:", nullptr));
+ textLabel6->setText(QCoreApplication::translate("Statistics", "Characters (with spaces):", nullptr));
+ trCharsSpc->setText(QCoreApplication::translate("Statistics", "0", nullptr));
+ untrCharsSpc->setText(QCoreApplication::translate("Statistics", "0", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/stringlisteditor.ui.h b/tests/auto/tools/uic/baseline/stringlisteditor.ui.h
index fd78ce91c1..91e7198793 100644
--- a/tests/auto/tools/uic/baseline/stringlisteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/stringlisteditor.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'stringlisteditor.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -201,9 +201,9 @@ public:
vboxLayout->addWidget(buttonBox);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(valueEdit);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(qdesigner_internal__Dialog);
QObject::connect(buttonBox, SIGNAL(accepted()), qdesigner_internal__Dialog, SLOT(accept()));
@@ -214,25 +214,25 @@ public:
void retranslateUi(QDialog *qdesigner_internal__Dialog)
{
- qdesigner_internal__Dialog->setWindowTitle(QApplication::translate("qdesigner_internal::Dialog", "Dialog", nullptr));
- groupBox->setTitle(QApplication::translate("qdesigner_internal::Dialog", "StringList", nullptr));
-#ifndef QT_NO_TOOLTIP
- newButton->setToolTip(QApplication::translate("qdesigner_internal::Dialog", "New String", nullptr));
-#endif // QT_NO_TOOLTIP
- newButton->setText(QApplication::translate("qdesigner_internal::Dialog", "&New", nullptr));
-#ifndef QT_NO_TOOLTIP
- deleteButton->setToolTip(QApplication::translate("qdesigner_internal::Dialog", "Delete String", nullptr));
-#endif // QT_NO_TOOLTIP
- deleteButton->setText(QApplication::translate("qdesigner_internal::Dialog", "&Delete", nullptr));
- label->setText(QApplication::translate("qdesigner_internal::Dialog", "&Value:", nullptr));
-#ifndef QT_NO_TOOLTIP
- upButton->setToolTip(QApplication::translate("qdesigner_internal::Dialog", "Move String Up", nullptr));
-#endif // QT_NO_TOOLTIP
- upButton->setText(QApplication::translate("qdesigner_internal::Dialog", "Up", nullptr));
-#ifndef QT_NO_TOOLTIP
- downButton->setToolTip(QApplication::translate("qdesigner_internal::Dialog", "Move String Down", nullptr));
-#endif // QT_NO_TOOLTIP
- downButton->setText(QApplication::translate("qdesigner_internal::Dialog", "Down", nullptr));
+ qdesigner_internal__Dialog->setWindowTitle(QCoreApplication::translate("qdesigner_internal::Dialog", "Dialog", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("qdesigner_internal::Dialog", "StringList", nullptr));
+#if QT_CONFIG(tooltip)
+ newButton->setToolTip(QCoreApplication::translate("qdesigner_internal::Dialog", "New String", nullptr));
+#endif // QT_CONFIG(tooltip)
+ newButton->setText(QCoreApplication::translate("qdesigner_internal::Dialog", "&New", nullptr));
+#if QT_CONFIG(tooltip)
+ deleteButton->setToolTip(QCoreApplication::translate("qdesigner_internal::Dialog", "Delete String", nullptr));
+#endif // QT_CONFIG(tooltip)
+ deleteButton->setText(QCoreApplication::translate("qdesigner_internal::Dialog", "&Delete", nullptr));
+ label->setText(QCoreApplication::translate("qdesigner_internal::Dialog", "&Value:", nullptr));
+#if QT_CONFIG(tooltip)
+ upButton->setToolTip(QCoreApplication::translate("qdesigner_internal::Dialog", "Move String Up", nullptr));
+#endif // QT_CONFIG(tooltip)
+ upButton->setText(QCoreApplication::translate("qdesigner_internal::Dialog", "Up", nullptr));
+#if QT_CONFIG(tooltip)
+ downButton->setToolTip(QCoreApplication::translate("qdesigner_internal::Dialog", "Move String Down", nullptr));
+#endif // QT_CONFIG(tooltip)
+ downButton->setText(QCoreApplication::translate("qdesigner_internal::Dialog", "Down", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h b/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h
index 5ae254ebab..ecca62c867 100644
--- a/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'stylesheeteditor.ui'
**
-** Created by: Qt User Interface Compiler version 5.10.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -73,7 +73,7 @@ public:
styleCombo = new QComboBox(StyleSheetEditor);
styleCombo->setObjectName(QString::fromUtf8("styleCombo"));
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(0));
+ QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(styleCombo->sizePolicy().hasHeightForWidth());
@@ -83,7 +83,7 @@ public:
label_7 = new QLabel(StyleSheetEditor);
label_7->setObjectName(QString::fromUtf8("label_7"));
- QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(0), static_cast<QSizePolicy::Policy>(5));
+ QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Preferred);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(label_7->sizePolicy().hasHeightForWidth());
@@ -130,14 +130,14 @@ public:
void retranslateUi(QWidget *StyleSheetEditor)
{
- StyleSheetEditor->setWindowTitle(QApplication::translate("StyleSheetEditor", "Style Editor", nullptr));
- styleSheetCombo->setItemText(0, QApplication::translate("StyleSheetEditor", "Default", nullptr));
- styleSheetCombo->setItemText(1, QApplication::translate("StyleSheetEditor", "Coffee", nullptr));
- styleSheetCombo->setItemText(2, QApplication::translate("StyleSheetEditor", "Pagefold", nullptr));
-
- label_7->setText(QApplication::translate("StyleSheetEditor", "Style:", nullptr));
- applyButton->setText(QApplication::translate("StyleSheetEditor", "&Apply", nullptr));
- label_8->setText(QApplication::translate("StyleSheetEditor", "Style Sheet:", nullptr));
+ StyleSheetEditor->setWindowTitle(QCoreApplication::translate("StyleSheetEditor", "Style Editor", nullptr));
+ styleSheetCombo->setItemText(0, QCoreApplication::translate("StyleSheetEditor", "Default", nullptr));
+ styleSheetCombo->setItemText(1, QCoreApplication::translate("StyleSheetEditor", "Coffee", nullptr));
+ styleSheetCombo->setItemText(2, QCoreApplication::translate("StyleSheetEditor", "Pagefold", nullptr));
+
+ label_7->setText(QCoreApplication::translate("StyleSheetEditor", "Style:", nullptr));
+ applyButton->setText(QCoreApplication::translate("StyleSheetEditor", "&Apply", nullptr));
+ label_8->setText(QCoreApplication::translate("StyleSheetEditor", "Style Sheet:", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/tabbedbrowser.ui.h b/tests/auto/tools/uic/baseline/tabbedbrowser.ui.h
index 09b230f5df..4be294af37 100644
--- a/tests/auto/tools/uic/baseline/tabbedbrowser.ui.h
+++ b/tests/auto/tools/uic/baseline/tabbedbrowser.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'tabbedbrowser.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -117,7 +117,7 @@ public:
editFind = new QLineEdit(frameFind);
editFind->setObjectName(QString::fromUtf8("editFind"));
- QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(0), static_cast<QSizePolicy::Policy>(0));
+ QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(editFind->sizePolicy().hasHeightForWidth());
@@ -181,14 +181,14 @@ public:
void retranslateUi(QWidget *TabbedBrowser)
{
- TabbedBrowser->setWindowTitle(QApplication::translate("TabbedBrowser", "TabbedBrowser", nullptr));
- tab->setTabText(tab->indexOf(frontpage), QApplication::translate("TabbedBrowser", "Untitled", nullptr));
+ TabbedBrowser->setWindowTitle(QCoreApplication::translate("TabbedBrowser", "TabbedBrowser", nullptr));
+ tab->setTabText(tab->indexOf(frontpage), QCoreApplication::translate("TabbedBrowser", "Untitled", nullptr));
toolClose->setText(QString());
- toolPrevious->setText(QApplication::translate("TabbedBrowser", "Previous", nullptr));
- toolNext->setText(QApplication::translate("TabbedBrowser", "Next", nullptr));
- checkCase->setText(QApplication::translate("TabbedBrowser", "Case Sensitive", nullptr));
- checkWholeWords->setText(QApplication::translate("TabbedBrowser", "Whole words", nullptr));
- labelWrapped->setText(QApplication::translate("TabbedBrowser", "<img src=\":/qt-project.org/assistant/images/wrap.png\">&nbsp;Search wrapped", nullptr));
+ toolPrevious->setText(QCoreApplication::translate("TabbedBrowser", "Previous", nullptr));
+ toolNext->setText(QCoreApplication::translate("TabbedBrowser", "Next", nullptr));
+ checkCase->setText(QCoreApplication::translate("TabbedBrowser", "Case Sensitive", nullptr));
+ checkWholeWords->setText(QCoreApplication::translate("TabbedBrowser", "Whole words", nullptr));
+ labelWrapped->setText(QCoreApplication::translate("TabbedBrowser", "<img src=\":/qt-project.org/assistant/images/wrap.png\">&nbsp;Search wrapped", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/tablewidgeteditor.ui.h b/tests/auto/tools/uic/baseline/tablewidgeteditor.ui.h
index e3ba00095e..4559bd910b 100644
--- a/tests/auto/tools/uic/baseline/tablewidgeteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/tablewidgeteditor.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'tablewidgeteditor.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -311,54 +311,54 @@ public:
void retranslateUi(QDialog *qdesigner_internal__TableWidgetEditor)
{
- qdesigner_internal__TableWidgetEditor->setWindowTitle(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Edit Table Widget", nullptr));
- itemsBox->setTitle(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Table Items", nullptr));
-#ifndef QT_NO_TOOLTIP
- tableWidget->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Table Items", nullptr));
-#endif // QT_NO_TOOLTIP
- label_3->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Icon", nullptr));
- columnsBox->setTitle(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Columns", nullptr));
-#ifndef QT_NO_TOOLTIP
- columnsListWidget->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Table Columns", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- newColumnButton->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "New Column", nullptr));
-#endif // QT_NO_TOOLTIP
- newColumnButton->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "New", nullptr));
-#ifndef QT_NO_TOOLTIP
- deleteColumnButton->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Delete Column", nullptr));
-#endif // QT_NO_TOOLTIP
- deleteColumnButton->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Delete", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveColumnUpButton->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Move Column Up", nullptr));
-#endif // QT_NO_TOOLTIP
- moveColumnUpButton->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "U", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveColumnDownButton->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Move Column Down", nullptr));
-#endif // QT_NO_TOOLTIP
- moveColumnDownButton->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "D", nullptr));
- label->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Icon", nullptr));
- rowsBox->setTitle(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Rows", nullptr));
-#ifndef QT_NO_TOOLTIP
- rowsListWidget->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Table Rows", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- newRowButton->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "New Row", nullptr));
-#endif // QT_NO_TOOLTIP
- newRowButton->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "New", nullptr));
-#ifndef QT_NO_TOOLTIP
- deleteRowButton->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Delete Row", nullptr));
-#endif // QT_NO_TOOLTIP
- deleteRowButton->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Delete", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveRowUpButton->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Move Row Up", nullptr));
-#endif // QT_NO_TOOLTIP
- moveRowUpButton->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "U", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveRowDownButton->setToolTip(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Move Row Down", nullptr));
-#endif // QT_NO_TOOLTIP
- moveRowDownButton->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "D", nullptr));
- label_2->setText(QApplication::translate("qdesigner_internal::TableWidgetEditor", "Icon", nullptr));
+ qdesigner_internal__TableWidgetEditor->setWindowTitle(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Edit Table Widget", nullptr));
+ itemsBox->setTitle(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Table Items", nullptr));
+#if QT_CONFIG(tooltip)
+ tableWidget->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Table Items", nullptr));
+#endif // QT_CONFIG(tooltip)
+ label_3->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Icon", nullptr));
+ columnsBox->setTitle(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Columns", nullptr));
+#if QT_CONFIG(tooltip)
+ columnsListWidget->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Table Columns", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ newColumnButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "New Column", nullptr));
+#endif // QT_CONFIG(tooltip)
+ newColumnButton->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "New", nullptr));
+#if QT_CONFIG(tooltip)
+ deleteColumnButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Delete Column", nullptr));
+#endif // QT_CONFIG(tooltip)
+ deleteColumnButton->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Delete", nullptr));
+#if QT_CONFIG(tooltip)
+ moveColumnUpButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Move Column Up", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveColumnUpButton->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "U", nullptr));
+#if QT_CONFIG(tooltip)
+ moveColumnDownButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Move Column Down", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveColumnDownButton->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "D", nullptr));
+ label->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Icon", nullptr));
+ rowsBox->setTitle(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Rows", nullptr));
+#if QT_CONFIG(tooltip)
+ rowsListWidget->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Table Rows", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ newRowButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "New Row", nullptr));
+#endif // QT_CONFIG(tooltip)
+ newRowButton->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "New", nullptr));
+#if QT_CONFIG(tooltip)
+ deleteRowButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Delete Row", nullptr));
+#endif // QT_CONFIG(tooltip)
+ deleteRowButton->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Delete", nullptr));
+#if QT_CONFIG(tooltip)
+ moveRowUpButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Move Row Up", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveRowUpButton->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "U", nullptr));
+#if QT_CONFIG(tooltip)
+ moveRowDownButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Move Row Down", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveRowDownButton->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "D", nullptr));
+ label_2->setText(QCoreApplication::translate("qdesigner_internal::TableWidgetEditor", "Icon", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/tetrixwindow.ui.h b/tests/auto/tools/uic/baseline/tetrixwindow.ui.h
index dc1033ce3a..340acbd9f2 100644
--- a/tests/auto/tools/uic/baseline/tetrixwindow.ui.h
+++ b/tests/auto/tools/uic/baseline/tetrixwindow.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'tetrixwindow.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -147,15 +147,15 @@ public:
void retranslateUi(QWidget *TetrixWindow)
{
- TetrixWindow->setWindowTitle(QApplication::translate("TetrixWindow", "Tetrix", nullptr));
- startButton->setText(QApplication::translate("TetrixWindow", "&Start", nullptr));
- linesRemovedLabel->setText(QApplication::translate("TetrixWindow", "LINES REMOVED", nullptr));
- pauseButton->setText(QApplication::translate("TetrixWindow", "&Pause", nullptr));
- levelLabel->setText(QApplication::translate("TetrixWindow", "LEVEL", nullptr));
- nextLabel->setText(QApplication::translate("TetrixWindow", "NEXT", nullptr));
- scoreLabel->setText(QApplication::translate("TetrixWindow", "SCORE", nullptr));
+ TetrixWindow->setWindowTitle(QCoreApplication::translate("TetrixWindow", "Tetrix", nullptr));
+ startButton->setText(QCoreApplication::translate("TetrixWindow", "&Start", nullptr));
+ linesRemovedLabel->setText(QCoreApplication::translate("TetrixWindow", "LINES REMOVED", nullptr));
+ pauseButton->setText(QCoreApplication::translate("TetrixWindow", "&Pause", nullptr));
+ levelLabel->setText(QCoreApplication::translate("TetrixWindow", "LEVEL", nullptr));
+ nextLabel->setText(QCoreApplication::translate("TetrixWindow", "NEXT", nullptr));
+ scoreLabel->setText(QCoreApplication::translate("TetrixWindow", "SCORE", nullptr));
nextPieceLabel->setText(QString());
- quitButton->setText(QApplication::translate("TetrixWindow", "&Quit", nullptr));
+ quitButton->setText(QCoreApplication::translate("TetrixWindow", "&Quit", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/textfinder.ui.h b/tests/auto/tools/uic/baseline/textfinder.ui.h
index 2f6bfebf98..38bdf756c2 100644
--- a/tests/auto/tools/uic/baseline/textfinder.ui.h
+++ b/tests/auto/tools/uic/baseline/textfinder.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'textfinder.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -81,9 +81,9 @@ public:
vboxLayout->addItem(spacerItem);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
searchLabel->setBuddy(lineEdit);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(Form);
QObject::connect(lineEdit, SIGNAL(returnPressed()), findButton, SLOT(animateClick()));
@@ -93,9 +93,9 @@ public:
void retranslateUi(QWidget *Form)
{
- Form->setWindowTitle(QApplication::translate("Form", "Find Text", nullptr));
- searchLabel->setText(QApplication::translate("Form", "&Keyword:", nullptr));
- findButton->setText(QApplication::translate("Form", "&Find", nullptr));
+ Form->setWindowTitle(QCoreApplication::translate("Form", "Find Text", nullptr));
+ searchLabel->setText(QCoreApplication::translate("Form", "&Keyword:", nullptr));
+ findButton->setText(QCoreApplication::translate("Form", "&Find", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/topicchooser.ui.h b/tests/auto/tools/uic/baseline/topicchooser.ui.h
index 90ec485e39..a89f62c4b5 100644
--- a/tests/auto/tools/uic/baseline/topicchooser.ui.h
+++ b/tests/auto/tools/uic/baseline/topicchooser.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'topicchooser.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -86,9 +86,9 @@ public:
vboxLayout->addWidget(Layout16);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(listWidget);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(TopicChooser);
@@ -100,10 +100,10 @@ public:
void retranslateUi(QDialog *TopicChooser)
{
- TopicChooser->setWindowTitle(QApplication::translate("TopicChooser", "Choose Topic", nullptr));
- label->setText(QApplication::translate("TopicChooser", "&Topics", nullptr));
- buttonDisplay->setText(QApplication::translate("TopicChooser", "&Display", nullptr));
- buttonCancel->setText(QApplication::translate("TopicChooser", "&Close", nullptr));
+ TopicChooser->setWindowTitle(QCoreApplication::translate("TopicChooser", "Choose Topic", nullptr));
+ label->setText(QCoreApplication::translate("TopicChooser", "&Topics", nullptr));
+ buttonDisplay->setText(QCoreApplication::translate("TopicChooser", "&Display", nullptr));
+ buttonCancel->setText(QCoreApplication::translate("TopicChooser", "&Close", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/translatedialog.ui.h b/tests/auto/tools/uic/baseline/translatedialog.ui.h
index 5bea11f9f2..10390c62df 100644
--- a/tests/auto/tools/uic/baseline/translatedialog.ui.h
+++ b/tests/auto/tools/uic/baseline/translatedialog.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'translatedialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -182,10 +182,10 @@ public:
hboxLayout->addLayout(vboxLayout2);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
findWhat->setBuddy(ledFindWhat);
translateTo->setBuddy(ledTranslateTo);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
QWidget::setTabOrder(ledFindWhat, ledTranslateTo);
QWidget::setTabOrder(ledTranslateTo, findNxt);
QWidget::setTabOrder(findNxt, translate);
@@ -205,34 +205,34 @@ public:
void retranslateUi(QDialog *TranslateDialog)
{
- TranslateDialog->setWindowTitle(QApplication::translate("TranslateDialog", "Qt Linguist", nullptr));
-#ifndef QT_NO_WHATSTHIS
- TranslateDialog->setWhatsThis(QApplication::translate("TranslateDialog", "This window allows you to search for some text in the translation source file.", nullptr));
-#endif // QT_NO_WHATSTHIS
-#ifndef QT_NO_WHATSTHIS
- ledTranslateTo->setWhatsThis(QApplication::translate("TranslateDialog", "Type in the text to search for.", nullptr));
-#endif // QT_NO_WHATSTHIS
- findWhat->setText(QApplication::translate("TranslateDialog", "Find &source text:", nullptr));
- translateTo->setText(QApplication::translate("TranslateDialog", "&Translate to:", nullptr));
-#ifndef QT_NO_WHATSTHIS
- ledFindWhat->setWhatsThis(QApplication::translate("TranslateDialog", "Type in the text to search for.", nullptr));
-#endif // QT_NO_WHATSTHIS
- groupBox->setTitle(QApplication::translate("TranslateDialog", "Search options", nullptr));
-#ifndef QT_NO_WHATSTHIS
- ckMatchCase->setWhatsThis(QApplication::translate("TranslateDialog", "Texts such as 'TeX' and 'tex' are considered as different when checked.", nullptr));
-#endif // QT_NO_WHATSTHIS
- ckMatchCase->setText(QApplication::translate("TranslateDialog", "Match &case", nullptr));
- ckMarkFinished->setText(QApplication::translate("TranslateDialog", "Mark new translation as &finished", nullptr));
-#ifndef QT_NO_WHATSTHIS
- findNxt->setWhatsThis(QApplication::translate("TranslateDialog", "Click here to find the next occurrence of the text you typed in.", nullptr));
-#endif // QT_NO_WHATSTHIS
- findNxt->setText(QApplication::translate("TranslateDialog", "Find Next", nullptr));
- translate->setText(QApplication::translate("TranslateDialog", "Translate", nullptr));
- translateAll->setText(QApplication::translate("TranslateDialog", "Translate All", nullptr));
-#ifndef QT_NO_WHATSTHIS
- cancel->setWhatsThis(QApplication::translate("TranslateDialog", "Click here to close this window.", nullptr));
-#endif // QT_NO_WHATSTHIS
- cancel->setText(QApplication::translate("TranslateDialog", "Cancel", nullptr));
+ TranslateDialog->setWindowTitle(QCoreApplication::translate("TranslateDialog", "Qt Linguist", nullptr));
+#if QT_CONFIG(whatsthis)
+ TranslateDialog->setWhatsThis(QCoreApplication::translate("TranslateDialog", "This window allows you to search for some text in the translation source file.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+#if QT_CONFIG(whatsthis)
+ ledTranslateTo->setWhatsThis(QCoreApplication::translate("TranslateDialog", "Type in the text to search for.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ findWhat->setText(QCoreApplication::translate("TranslateDialog", "Find &source text:", nullptr));
+ translateTo->setText(QCoreApplication::translate("TranslateDialog", "&Translate to:", nullptr));
+#if QT_CONFIG(whatsthis)
+ ledFindWhat->setWhatsThis(QCoreApplication::translate("TranslateDialog", "Type in the text to search for.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ groupBox->setTitle(QCoreApplication::translate("TranslateDialog", "Search options", nullptr));
+#if QT_CONFIG(whatsthis)
+ ckMatchCase->setWhatsThis(QCoreApplication::translate("TranslateDialog", "Texts such as 'TeX' and 'tex' are considered as different when checked.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ ckMatchCase->setText(QCoreApplication::translate("TranslateDialog", "Match &case", nullptr));
+ ckMarkFinished->setText(QCoreApplication::translate("TranslateDialog", "Mark new translation as &finished", nullptr));
+#if QT_CONFIG(whatsthis)
+ findNxt->setWhatsThis(QCoreApplication::translate("TranslateDialog", "Click here to find the next occurrence of the text you typed in.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ findNxt->setText(QCoreApplication::translate("TranslateDialog", "Find Next", nullptr));
+ translate->setText(QCoreApplication::translate("TranslateDialog", "Translate", nullptr));
+ translateAll->setText(QCoreApplication::translate("TranslateDialog", "Translate All", nullptr));
+#if QT_CONFIG(whatsthis)
+ cancel->setWhatsThis(QCoreApplication::translate("TranslateDialog", "Click here to close this window.", nullptr));
+#endif // QT_CONFIG(whatsthis)
+ cancel->setText(QCoreApplication::translate("TranslateDialog", "Cancel", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/translationsettings.ui.h b/tests/auto/tools/uic/baseline/translationsettings.ui.h
index 764e3a85b6..5e0f1520a0 100644
--- a/tests/auto/tools/uic/baseline/translationsettings.ui.h
+++ b/tests/auto/tools/uic/baseline/translationsettings.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'translationsettings.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -86,9 +86,9 @@ public:
vboxLayout->addWidget(buttonBox);
-#ifndef QT_NO_SHORTCUT
+#if QT_CONFIG(shortcut)
label->setBuddy(cbLanguageList);
-#endif // QT_NO_SHORTCUT
+#endif // QT_CONFIG(shortcut)
retranslateUi(TranslationSettings);
QObject::connect(buttonBox, SIGNAL(accepted()), TranslationSettings, SLOT(accept()));
@@ -99,10 +99,10 @@ public:
void retranslateUi(QDialog *TranslationSettings)
{
- TranslationSettings->setWindowTitle(QApplication::translate("TranslationSettings", "Qt Linguist - Translation file settings", nullptr));
- groupBox->setTitle(QApplication::translate("TranslationSettings", "Target language", nullptr));
- label->setText(QApplication::translate("TranslationSettings", "Language", nullptr));
- lblCountry->setText(QApplication::translate("TranslationSettings", "Country/Region", nullptr));
+ TranslationSettings->setWindowTitle(QCoreApplication::translate("TranslationSettings", "Qt Linguist - Translation file settings", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("TranslationSettings", "Target language", nullptr));
+ label->setText(QCoreApplication::translate("TranslationSettings", "Language", nullptr));
+ lblCountry->setText(QCoreApplication::translate("TranslationSettings", "Country/Region", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/treewidgeteditor.ui.h b/tests/auto/tools/uic/baseline/treewidgeteditor.ui.h
index d432195648..395d66a999 100644
--- a/tests/auto/tools/uic/baseline/treewidgeteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/treewidgeteditor.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'treewidgeteditor.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -276,63 +276,63 @@ public:
void retranslateUi(QDialog *qdesigner_internal__TreeWidgetEditor)
{
- qdesigner_internal__TreeWidgetEditor->setWindowTitle(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Edit Tree Widget", nullptr));
- itemsBox->setTitle(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Tree Items", nullptr));
+ qdesigner_internal__TreeWidgetEditor->setWindowTitle(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Edit Tree Widget", nullptr));
+ itemsBox->setTitle(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Tree Items", nullptr));
QTreeWidgetItem *___qtreewidgetitem = treeWidget->headerItem();
- ___qtreewidgetitem->setText(0, QApplication::translate("qdesigner_internal::TreeWidgetEditor", "1", nullptr));
-#ifndef QT_NO_TOOLTIP
- treeWidget->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Tree Items", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- newItemButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "New Item", nullptr));
-#endif // QT_NO_TOOLTIP
- newItemButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "&New", nullptr));
-#ifndef QT_NO_TOOLTIP
- newSubItemButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "New Subitem", nullptr));
-#endif // QT_NO_TOOLTIP
- newSubItemButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "New &Subitem", nullptr));
-#ifndef QT_NO_TOOLTIP
- deleteItemButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Delete Item", nullptr));
-#endif // QT_NO_TOOLTIP
- deleteItemButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "&Delete", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveItemLeftButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Item Left (before Parent Item)", nullptr));
-#endif // QT_NO_TOOLTIP
- moveItemLeftButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "L", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveItemRightButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Item Right (as a First Subitem of the Next Sibling Item)", nullptr));
-#endif // QT_NO_TOOLTIP
- moveItemRightButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "R", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveItemUpButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Item Up", nullptr));
-#endif // QT_NO_TOOLTIP
- moveItemUpButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "U", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveItemDownButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Item Down", nullptr));
-#endif // QT_NO_TOOLTIP
- moveItemDownButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "D", nullptr));
- label_2->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Icon", nullptr));
- columnsBox->setTitle(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Columns", nullptr));
-#ifndef QT_NO_TOOLTIP
- listWidget->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Tree Columns", nullptr));
-#endif // QT_NO_TOOLTIP
-#ifndef QT_NO_TOOLTIP
- newColumnButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "New Column", nullptr));
-#endif // QT_NO_TOOLTIP
- newColumnButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "New", nullptr));
-#ifndef QT_NO_TOOLTIP
- deleteColumnButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Delete Column", nullptr));
-#endif // QT_NO_TOOLTIP
- deleteColumnButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Delete", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveColumnUpButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Column Up", nullptr));
-#endif // QT_NO_TOOLTIP
- moveColumnUpButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "U", nullptr));
-#ifndef QT_NO_TOOLTIP
- moveColumnDownButton->setToolTip(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Column Down", nullptr));
-#endif // QT_NO_TOOLTIP
- moveColumnDownButton->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "D", nullptr));
- label->setText(QApplication::translate("qdesigner_internal::TreeWidgetEditor", "Icon", nullptr));
+ ___qtreewidgetitem->setText(0, QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "1", nullptr));
+#if QT_CONFIG(tooltip)
+ treeWidget->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Tree Items", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ newItemButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "New Item", nullptr));
+#endif // QT_CONFIG(tooltip)
+ newItemButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "&New", nullptr));
+#if QT_CONFIG(tooltip)
+ newSubItemButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "New Subitem", nullptr));
+#endif // QT_CONFIG(tooltip)
+ newSubItemButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "New &Subitem", nullptr));
+#if QT_CONFIG(tooltip)
+ deleteItemButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Delete Item", nullptr));
+#endif // QT_CONFIG(tooltip)
+ deleteItemButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "&Delete", nullptr));
+#if QT_CONFIG(tooltip)
+ moveItemLeftButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Item Left (before Parent Item)", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveItemLeftButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "L", nullptr));
+#if QT_CONFIG(tooltip)
+ moveItemRightButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Item Right (as a First Subitem of the Next Sibling Item)", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveItemRightButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "R", nullptr));
+#if QT_CONFIG(tooltip)
+ moveItemUpButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Item Up", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveItemUpButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "U", nullptr));
+#if QT_CONFIG(tooltip)
+ moveItemDownButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Item Down", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveItemDownButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "D", nullptr));
+ label_2->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Icon", nullptr));
+ columnsBox->setTitle(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Columns", nullptr));
+#if QT_CONFIG(tooltip)
+ listWidget->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Tree Columns", nullptr));
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(tooltip)
+ newColumnButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "New Column", nullptr));
+#endif // QT_CONFIG(tooltip)
+ newColumnButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "New", nullptr));
+#if QT_CONFIG(tooltip)
+ deleteColumnButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Delete Column", nullptr));
+#endif // QT_CONFIG(tooltip)
+ deleteColumnButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Delete", nullptr));
+#if QT_CONFIG(tooltip)
+ moveColumnUpButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Column Up", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveColumnUpButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "U", nullptr));
+#if QT_CONFIG(tooltip)
+ moveColumnDownButton->setToolTip(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Move Column Down", nullptr));
+#endif // QT_CONFIG(tooltip)
+ moveColumnDownButton->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "D", nullptr));
+ label->setText(QCoreApplication::translate("qdesigner_internal::TreeWidgetEditor", "Icon", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/trpreviewtool.ui.h b/tests/auto/tools/uic/baseline/trpreviewtool.ui.h
index 3fbf125a1f..612d7ad427 100644
--- a/tests/auto/tools/uic/baseline/trpreviewtool.ui.h
+++ b/tests/auto/tools/uic/baseline/trpreviewtool.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'trpreviewtool.ui'
**
-** Created by: Qt User Interface Compiler version 5.9.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -117,7 +117,7 @@ public:
mainToolBar = new QToolBar(TrPreviewToolClass);
mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
mainToolBar->setOrientation(Qt::Horizontal);
- TrPreviewToolClass->addToolBar(static_cast<Qt::ToolBarArea>(4), mainToolBar);
+ TrPreviewToolClass->addToolBar(Qt::TopToolBarArea, mainToolBar);
statusBar = new QStatusBar(TrPreviewToolClass);
statusBar->setObjectName(QString::fromUtf8("statusBar"));
TrPreviewToolClass->setStatusBar(statusBar);
@@ -138,7 +138,7 @@ public:
vboxLayout->addWidget(viewForms);
dwForms->setWidget(dockWidgetContents);
- TrPreviewToolClass->addDockWidget(static_cast<Qt::DockWidgetArea>(1), dwForms);
+ TrPreviewToolClass->addDockWidget(Qt::LeftDockWidgetArea, dwForms);
menuBar->addAction(menuFile->menuAction());
menuBar->addAction(menuView->menuAction());
@@ -162,21 +162,21 @@ public:
void retranslateUi(QMainWindow *TrPreviewToolClass)
{
- TrPreviewToolClass->setWindowTitle(QApplication::translate("TrPreviewToolClass", "Qt Translation Preview Tool", nullptr));
- actionOpenForm->setText(QApplication::translate("TrPreviewToolClass", "&Open Form...", nullptr));
- actionLoadTranslation->setText(QApplication::translate("TrPreviewToolClass", "&Load Translation...", nullptr));
- actionReloadTranslations->setText(QApplication::translate("TrPreviewToolClass", "&Reload Translations", nullptr));
-#ifndef QT_NO_SHORTCUT
- actionReloadTranslations->setShortcut(QApplication::translate("TrPreviewToolClass", "F5", nullptr));
-#endif // QT_NO_SHORTCUT
- actionClose->setText(QApplication::translate("TrPreviewToolClass", "&Close", nullptr));
- actionAbout->setText(QApplication::translate("TrPreviewToolClass", "About", nullptr));
- actionAbout_Qt->setText(QApplication::translate("TrPreviewToolClass", "About Qt", nullptr));
- menuView->setTitle(QApplication::translate("TrPreviewToolClass", "&View", nullptr));
- menuViewViews->setTitle(QApplication::translate("TrPreviewToolClass", "&Views", nullptr));
- menuHelp->setTitle(QApplication::translate("TrPreviewToolClass", "&Help", nullptr));
- menuFile->setTitle(QApplication::translate("TrPreviewToolClass", "&File", nullptr));
- dwForms->setWindowTitle(QApplication::translate("TrPreviewToolClass", "Forms", nullptr));
+ TrPreviewToolClass->setWindowTitle(QCoreApplication::translate("TrPreviewToolClass", "Qt Translation Preview Tool", nullptr));
+ actionOpenForm->setText(QCoreApplication::translate("TrPreviewToolClass", "&Open Form...", nullptr));
+ actionLoadTranslation->setText(QCoreApplication::translate("TrPreviewToolClass", "&Load Translation...", nullptr));
+ actionReloadTranslations->setText(QCoreApplication::translate("TrPreviewToolClass", "&Reload Translations", nullptr));
+#if QT_CONFIG(shortcut)
+ actionReloadTranslations->setShortcut(QCoreApplication::translate("TrPreviewToolClass", "F5", nullptr));
+#endif // QT_CONFIG(shortcut)
+ actionClose->setText(QCoreApplication::translate("TrPreviewToolClass", "&Close", nullptr));
+ actionAbout->setText(QCoreApplication::translate("TrPreviewToolClass", "About", nullptr));
+ actionAbout_Qt->setText(QCoreApplication::translate("TrPreviewToolClass", "About Qt", nullptr));
+ menuView->setTitle(QCoreApplication::translate("TrPreviewToolClass", "&View", nullptr));
+ menuViewViews->setTitle(QCoreApplication::translate("TrPreviewToolClass", "&Views", nullptr));
+ menuHelp->setTitle(QCoreApplication::translate("TrPreviewToolClass", "&Help", nullptr));
+ menuFile->setTitle(QCoreApplication::translate("TrPreviewToolClass", "&File", nullptr));
+ dwForms->setWindowTitle(QCoreApplication::translate("TrPreviewToolClass", "Forms", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/validators.ui.h b/tests/auto/tools/uic/baseline/validators.ui.h
index d0ae777f65..45d9c5aac6 100644
--- a/tests/auto/tools/uic/baseline/validators.ui.h
+++ b/tests/auto/tools/uic/baseline/validators.ui.h
@@ -375,22 +375,22 @@ public:
void retranslateUi(QWidget *ValidatorsForm)
{
- ValidatorsForm->setWindowTitle(QApplication::translate("ValidatorsForm", "Form", nullptr));
- groupBox->setTitle(QApplication::translate("ValidatorsForm", "QIntValidator", nullptr));
- label->setText(QApplication::translate("ValidatorsForm", "Min:", nullptr));
- label_2->setText(QApplication::translate("ValidatorsForm", "Max:", nullptr));
- label_7->setText(QApplication::translate("ValidatorsForm", "editingFinished()", nullptr));
- groupBox_2->setTitle(QApplication::translate("ValidatorsForm", "QDoubleValidator", nullptr));
- label_3->setText(QApplication::translate("ValidatorsForm", "Min:", nullptr));
- label_5->setText(QApplication::translate("ValidatorsForm", "Format:", nullptr));
- doubleFormat->setItemText(0, QApplication::translate("ValidatorsForm", "Standard", nullptr));
- doubleFormat->setItemText(1, QApplication::translate("ValidatorsForm", "Scientific", nullptr));
-
- label_4->setText(QApplication::translate("ValidatorsForm", "Max:", nullptr));
- label_6->setText(QApplication::translate("ValidatorsForm", "Decimals:", nullptr));
+ ValidatorsForm->setWindowTitle(QCoreApplication::translate("ValidatorsForm", "Form", nullptr));
+ groupBox->setTitle(QCoreApplication::translate("ValidatorsForm", "QIntValidator", nullptr));
+ label->setText(QCoreApplication::translate("ValidatorsForm", "Min:", nullptr));
+ label_2->setText(QCoreApplication::translate("ValidatorsForm", "Max:", nullptr));
+ label_7->setText(QCoreApplication::translate("ValidatorsForm", "editingFinished()", nullptr));
+ groupBox_2->setTitle(QCoreApplication::translate("ValidatorsForm", "QDoubleValidator", nullptr));
+ label_3->setText(QCoreApplication::translate("ValidatorsForm", "Min:", nullptr));
+ label_5->setText(QCoreApplication::translate("ValidatorsForm", "Format:", nullptr));
+ doubleFormat->setItemText(0, QCoreApplication::translate("ValidatorsForm", "Standard", nullptr));
+ doubleFormat->setItemText(1, QCoreApplication::translate("ValidatorsForm", "Scientific", nullptr));
+
+ label_4->setText(QCoreApplication::translate("ValidatorsForm", "Max:", nullptr));
+ label_6->setText(QCoreApplication::translate("ValidatorsForm", "Decimals:", nullptr));
doubleLedWidget->setText(QString());
- label_8->setText(QApplication::translate("ValidatorsForm", "editingFinished()", nullptr));
- pushButton->setText(QApplication::translate("ValidatorsForm", "Quit", nullptr));
+ label_8->setText(QCoreApplication::translate("ValidatorsForm", "editingFinished()", nullptr));
+ pushButton->setText(QCoreApplication::translate("ValidatorsForm", "Quit", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h b/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h
index d6f7ff5526..aa005593c0 100644
--- a/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'wateringconfigdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.10.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -250,34 +250,34 @@ public:
void retranslateUi(QDialog *WateringConfigDialog)
{
- WateringConfigDialog->setWindowTitle(QApplication::translate("WateringConfigDialog", "Watering Configuration", nullptr));
- label_3->setText(QApplication::translate("WateringConfigDialog", "Plant:", nullptr));
- plantComboBox->setItemText(0, QApplication::translate("WateringConfigDialog", "Squash", nullptr));
- plantComboBox->setItemText(1, QApplication::translate("WateringConfigDialog", "Bean", nullptr));
- plantComboBox->setItemText(2, QApplication::translate("WateringConfigDialog", "Carrot", nullptr));
- plantComboBox->setItemText(3, QApplication::translate("WateringConfigDialog", "Strawberry", nullptr));
- plantComboBox->setItemText(4, QApplication::translate("WateringConfigDialog", "Raspberry", nullptr));
- plantComboBox->setItemText(5, QApplication::translate("WateringConfigDialog", "Blueberry", nullptr));
-
- label_2->setText(QApplication::translate("WateringConfigDialog", "Water when:", nullptr));
- temperatureCheckBox->setText(QApplication::translate("WateringConfigDialog", "Temperature is higher than:", nullptr));
+ WateringConfigDialog->setWindowTitle(QCoreApplication::translate("WateringConfigDialog", "Watering Configuration", nullptr));
+ label_3->setText(QCoreApplication::translate("WateringConfigDialog", "Plant:", nullptr));
+ plantComboBox->setItemText(0, QCoreApplication::translate("WateringConfigDialog", "Squash", nullptr));
+ plantComboBox->setItemText(1, QCoreApplication::translate("WateringConfigDialog", "Bean", nullptr));
+ plantComboBox->setItemText(2, QCoreApplication::translate("WateringConfigDialog", "Carrot", nullptr));
+ plantComboBox->setItemText(3, QCoreApplication::translate("WateringConfigDialog", "Strawberry", nullptr));
+ plantComboBox->setItemText(4, QCoreApplication::translate("WateringConfigDialog", "Raspberry", nullptr));
+ plantComboBox->setItemText(5, QCoreApplication::translate("WateringConfigDialog", "Blueberry", nullptr));
+
+ label_2->setText(QCoreApplication::translate("WateringConfigDialog", "Water when:", nullptr));
+ temperatureCheckBox->setText(QCoreApplication::translate("WateringConfigDialog", "Temperature is higher than:", nullptr));
temperatureSpinBox->setSpecialValueText(QString());
- temperatureSpinBox->setSuffix(QApplication::translate("WateringConfigDialog", "C", nullptr));
- rainCheckBox->setText(QApplication::translate("WateringConfigDialog", "Rain less than:", nullptr));
+ temperatureSpinBox->setSuffix(QCoreApplication::translate("WateringConfigDialog", "C", nullptr));
+ rainCheckBox->setText(QCoreApplication::translate("WateringConfigDialog", "Rain less than:", nullptr));
rainSpinBox->setSpecialValueText(QString());
- rainSpinBox->setSuffix(QApplication::translate("WateringConfigDialog", "mm", nullptr));
- label->setText(QApplication::translate("WateringConfigDialog", "Starting Time:", nullptr));
- label_4->setText(QApplication::translate("WateringConfigDialog", "Amount:", nullptr));
- amountSpinBox->setSuffix(QApplication::translate("WateringConfigDialog", "l", nullptr));
- label_5->setText(QApplication::translate("WateringConfigDialog", "Source:", nullptr));
- sourceComboBox->setItemText(0, QApplication::translate("WateringConfigDialog", "Foundain", nullptr));
- sourceComboBox->setItemText(1, QApplication::translate("WateringConfigDialog", "River", nullptr));
- sourceComboBox->setItemText(2, QApplication::translate("WateringConfigDialog", "Lake", nullptr));
- sourceComboBox->setItemText(3, QApplication::translate("WateringConfigDialog", "Public Water System", nullptr));
-
- label_6->setText(QApplication::translate("WateringConfigDialog", "Filter:", nullptr));
+ rainSpinBox->setSuffix(QCoreApplication::translate("WateringConfigDialog", "mm", nullptr));
+ label->setText(QCoreApplication::translate("WateringConfigDialog", "Starting Time:", nullptr));
+ label_4->setText(QCoreApplication::translate("WateringConfigDialog", "Amount:", nullptr));
+ amountSpinBox->setSuffix(QCoreApplication::translate("WateringConfigDialog", "l", nullptr));
+ label_5->setText(QCoreApplication::translate("WateringConfigDialog", "Source:", nullptr));
+ sourceComboBox->setItemText(0, QCoreApplication::translate("WateringConfigDialog", "Foundain", nullptr));
+ sourceComboBox->setItemText(1, QCoreApplication::translate("WateringConfigDialog", "River", nullptr));
+ sourceComboBox->setItemText(2, QCoreApplication::translate("WateringConfigDialog", "Lake", nullptr));
+ sourceComboBox->setItemText(3, QCoreApplication::translate("WateringConfigDialog", "Public Water System", nullptr));
+
+ label_6->setText(QCoreApplication::translate("WateringConfigDialog", "Filter:", nullptr));
filterCheckBox->setText(QString());
- helpLabel->setText(QApplication::translate("WateringConfigDialog", "<a href=\"test\">Show Details</a>", nullptr));
+ helpLabel->setText(QCoreApplication::translate("WateringConfigDialog", "<a href=\"test\">Show Details</a>", nullptr));
} // retranslateUi
};
diff --git a/tests/auto/tools/uic/tst_uic.cpp b/tests/auto/tools/uic/tst_uic.cpp
index 85668c96d4..5b2f1f008b 100644
--- a/tests/auto/tools/uic/tst_uic.cpp
+++ b/tests/auto/tools/uic/tst_uic.cpp
@@ -36,12 +36,27 @@
#include <QtCore/QTemporaryDir>
#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
+#include <QtCore/QVector>
+
+#include <cstdio>
+
+static const char keepEnvVar[] = "UIC_KEEP_GENERATED_FILES";
+static const char diffToStderrEnvVar[] = "UIC_STDERR_DIFF";
+
+struct TestEntry
+{
+ QByteArray name;
+ QString baselineBaseName;
+ QString generatedFileName;
+};
class tst_uic : public QObject
{
Q_OBJECT
public:
+ using TestEntries = QVector<TestEntry>;
+
tst_uic();
private Q_SLOTS:
@@ -58,18 +73,25 @@ private Q_SLOTS:
void compare();
void compare_data() const;
+ void python();
+ void python_data() const;
+
void runCompare();
private:
+ void populateTestEntries();
+
const QString m_command;
QString m_baseline;
QTemporaryDir m_generated;
+ TestEntries m_testEntries;
QRegularExpression m_versionRegexp;
+ QString m_python;
};
tst_uic::tst_uic()
: m_command(QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/uic"))
- , m_versionRegexp(QLatin1String("\\*\\* Created by: Qt User Interface Compiler version \\d{1,2}\\.\\d{1,2}\\.\\d{1,2}"))
+ , m_versionRegexp(QLatin1String(R"(\*\* Created by: Qt User Interface Compiler version \d{1,2}\.\d{1,2}\.\d{1,2})"))
{
}
@@ -80,6 +102,32 @@ static QByteArray msgProcessStartFailed(const QString &command, const QString &w
return result.toLocal8Bit();
}
+// Locate Python and check whether PySide2 is installed
+static QString locatePython(QTemporaryDir &generatedDir)
+{
+ QString python = QStandardPaths::findExecutable(QLatin1String("python"));
+ if (python.isEmpty()) {
+ qWarning("Cannot locate python, skipping tests");
+ return QString();
+ }
+ QFile importTestFile(generatedDir.filePath(QLatin1String("import_test.py")));
+ if (!importTestFile.open(QIODevice::WriteOnly| QIODevice::Text))
+ return QString();
+ importTestFile.write("import PySide2.QtCore\n");
+ importTestFile.close();
+ QProcess process;
+ process.start(python, {importTestFile.fileName()});
+ if (!process.waitForStarted() || !process.waitForFinished())
+ return QString();
+ if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) {
+ const QString stdErr = QString::fromLocal8Bit(process.readAllStandardError()).simplified();
+ qWarning("PySide2 is not installed (%s)", qPrintable(stdErr));
+ return QString();
+ }
+ importTestFile.remove();
+ return python;
+}
+
void tst_uic::initTestCase()
{
QVERIFY2(m_generated.isValid(), qPrintable(m_generated.errorString()));
@@ -100,17 +148,43 @@ void tst_uic::initTestCase()
arg(QDir::currentPath());
if (!outLines.empty())
msg += outLines.front();
+ populateTestEntries();
+ QVERIFY(!m_testEntries.isEmpty());
qDebug("%s", qPrintable(msg));
+
+ m_python = locatePython(m_generated);
+}
+
+void tst_uic::populateTestEntries()
+{
+ const QString generatedPrefix = m_generated.path() + QLatin1Char('/');
+ QDir baseline(m_baseline);
+ const QString baseLinePrefix = baseline.path() + QLatin1Char('/');
+ const QFileInfoList baselineFiles =
+ baseline.entryInfoList(QStringList(QString::fromLatin1("*.ui")), QDir::Files);
+ m_testEntries.reserve(baselineFiles.size());
+ for (const QFileInfo &baselineFile : baselineFiles) {
+ const QString baseName = baselineFile.baseName();
+ const QString baselineBaseName = baseLinePrefix + baseName;
+ const QString generatedFile = generatedPrefix + baselineFile.fileName()
+ + QLatin1String(".h");
+ m_testEntries.append(TestEntry{baseName.toLocal8Bit(), baselineBaseName, generatedFile});
+ }
}
+static const char helpFormat[] = R"(
+Note: The environment variable '%s' can be set to keep the temporary files
+for error analysis.
+The environment variable '%s' can be set to redirect the diff output to
+stderr.)";
+
void tst_uic::cleanupTestCase()
{
- static const char envVar[] = "UIC_KEEP_GENERATED_FILES";
- if (qgetenv(envVar).isEmpty()) {
- qDebug("Note: The environment variable '%s' can be set to keep the temporary files for error analysis.", envVar);
- } else {
+ if (qEnvironmentVariableIsSet(keepEnvVar)) {
m_generated.setAutoRemove(false);
qDebug("Keeping generated files in '%s'", qPrintable(QDir::toNativeSeparators(m_generated.path())));
+ } else {
+ qDebug(helpFormat, keepEnvVar, diffToStderrEnvVar);
}
}
@@ -152,7 +226,7 @@ void tst_uic::run()
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
- QCOMPARE(QFileInfo(generatedFile).exists(), true);
+ QVERIFY(QFileInfo::exists(generatedFile));
}
void tst_uic::run_data() const
@@ -161,22 +235,12 @@ void tst_uic::run_data() const
QTest::addColumn<QString>("generatedFile");
QTest::addColumn<QStringList>("options");
- QDir generated(m_generated.path());
- QDir baseline(m_baseline);
- const QFileInfoList baselineFiles = baseline.entryInfoList(QStringList("*.ui"), QDir::Files);
- foreach (const QFileInfo &baselineFile, baselineFiles) {
- const QString generatedFile = generated.absolutePath()
- + QLatin1Char('/') + baselineFile.fileName()
- + QLatin1String(".h");
-
+ for (const TestEntry &te : m_testEntries) {
QStringList options;
- if (baselineFile.fileName() == QLatin1String("qttrid.ui"))
+ if (te.name == QByteArrayLiteral("qttrid"))
options << QStringList(QLatin1String("-idbased"));
-
- QTest::newRow(qPrintable(baselineFile.baseName()))
- << baselineFile.absoluteFilePath()
- << generatedFile
- << options;
+ QTest::newRow(te.name.constData()) << (te.baselineBaseName + QLatin1String(".ui"))
+ << te.generatedFileName << options;
}
}
@@ -212,6 +276,16 @@ static QByteArray msgCannotReadFile(const QFile &file)
return result.toLocal8Bit();
}
+static void outputDiff(const QString &diff)
+{
+ // Use patch -p3 < diff to apply the obtained diff output in the baseline directory.
+ static const bool diffToStderr = qEnvironmentVariableIsSet(diffToStderrEnvVar);
+ if (diffToStderr)
+ std::fputs(qPrintable(diff), stderr);
+ else
+ qWarning("Difference:\n%s", qPrintable(diff));
+}
+
void tst_uic::compare()
{
QFETCH(QString, originalFile);
@@ -233,7 +307,7 @@ void tst_uic::compare()
if (generatedFileContents != originalFileContents) {
const QString diff = generateDiff(originalFile, generatedFile);
if (!diff.isEmpty())
- qWarning().noquote().nospace() << "Difference:\n" << diff;
+ outputDiff(diff);
}
QCOMPARE(generatedFileContents, originalFileContents);
@@ -244,15 +318,9 @@ void tst_uic::compare_data() const
QTest::addColumn<QString>("originalFile");
QTest::addColumn<QString>("generatedFile");
- QDir generated(m_generated.path());
- QDir baseline(m_baseline);
- const QFileInfoList baselineFiles = baseline.entryInfoList(QStringList("*.h"), QDir::Files);
- foreach (const QFileInfo &baselineFile, baselineFiles) {
- const QString generatedFile = generated.absolutePath()
- + QLatin1Char('/') + baselineFile.fileName();
- QTest::newRow(qPrintable(baselineFile.baseName()))
- << baselineFile.absoluteFilePath()
- << generatedFile;
+ for (const TestEntry &te : m_testEntries) {
+ QTest::newRow(te.name.constData()) << (te.baselineBaseName + QLatin1String(".ui.h"))
+ << te.generatedFileName;
}
}
@@ -260,7 +328,7 @@ void tst_uic::runTranslation()
{
QProcess process;
- QDir baseline(m_baseline);
+ const QDir baseline(m_baseline);
QDir generated(m_generated.path());
generated.mkdir(QLatin1String("translation"));
@@ -274,7 +342,7 @@ void tst_uic::runTranslation()
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QCOMPARE(process.exitCode(), 0);
- QCOMPARE(QFileInfo(generatedFile).exists(), true);
+ QVERIFY(QFileInfo::exists(generatedFile));
}
@@ -301,11 +369,81 @@ void tst_uic::runCompare()
if (generatedFileContents != originalFileContents) {
const QString diff = generateDiff(originalFile, generatedFile);
if (!diff.isEmpty())
- qWarning().noquote().nospace() << "Difference:\n" << diff;
+ outputDiff(diff);
}
QCOMPARE(generatedFileContents, originalFileContents);
}
+// Let uic generate Python code and verify that it is syntactically
+// correct by compiling it into .pyc. This test is executed only
+// when python with an installed Qt for Python is detected (see locatePython()).
+
+static inline QByteArray msgCompilePythonFailed(const QByteArray &error)
+{
+ // If there is a line with blanks and caret indicating an error in the line
+ // above, insert the cursor into the offending line and remove the caret.
+ QByteArrayList lines = error.trimmed().split('\n');
+ for (int i = lines.size() - 1; i > 0; --i) {
+ const auto &line = lines.at(i);
+ const int caret = line.indexOf('^');
+ if (caret == 0 || (caret > 0 && line.at(caret - 1) == ' ')) {
+ lines.removeAt(i);
+ lines[i - 1].insert(caret, '|');
+ break;
+ }
+ }
+ return lines.join('\n');
+}
+
+void tst_uic::python_data() const
+{
+ QTest::addColumn<QString>("originalFile");
+ QTest::addColumn<QString>("generatedFile");
+
+ const int size = m_python.isEmpty()
+ ? qMin(1, m_testEntries.size()) : m_testEntries.size();
+ for (int i = 0; i < size; ++i) {
+ const TestEntry &te = m_testEntries.at(i);
+ // qprintsettingsoutput: variable named 'from' clashes with Python
+ if (!te.baselineBaseName.endsWith(QLatin1String("/qprintsettingsoutput"))) {
+ QString generatedFile = te.generatedFileName;
+ generatedFile.chop(1); // foo.h -> foo.py
+ generatedFile.append(QLatin1String("py"));
+ QTest::newRow(te.name.constData())
+ << (te.baselineBaseName + QLatin1String(".ui"))
+ << generatedFile;
+ }
+ }
+}
+
+void tst_uic::python()
+{
+ QFETCH(QString, originalFile);
+ QFETCH(QString, generatedFile);
+ if (m_python.isEmpty())
+ QSKIP("Python was not found");
+
+ QStringList uicArguments{QLatin1String("-g"), QLatin1String("python"),
+ originalFile, QLatin1String("-o"), generatedFile};
+ QProcess process;
+ process.setWorkingDirectory(m_generated.path());
+ process.start(m_command, uicArguments);
+ QVERIFY2(process.waitForStarted(), msgProcessStartFailed(m_command, process.errorString()));
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(process.exitCode(), 0);
+ QVERIFY(QFileInfo::exists(generatedFile));
+
+ // Test Python code generation by compiling the file
+ QStringList compileArguments{QLatin1String("-m"), QLatin1String("py_compile"), generatedFile};
+ process.start(m_python, compileArguments);
+ QVERIFY2(process.waitForStarted(), msgProcessStartFailed(m_command, process.errorString()));
+ QVERIFY(process.waitForFinished());
+ const bool compiled = process.exitStatus() == QProcess::NormalExit
+ && process.exitCode() == 0;
+ QVERIFY2(compiled, msgCompilePythonFailed(process.readAllStandardError()).constData());
+}
+
QTEST_MAIN(tst_uic)
#include "tst_uic.moc"
diff --git a/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
index 6a0ad4b3a4..413b865f04 100644
--- a/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
+++ b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
@@ -116,10 +116,10 @@ void tst_QColorDialog::testGetRgba()
#ifdef Q_OS_MAC
QEXPECT_FAIL("", "Sending QTest::keyClick to OSX color dialog helper fails, see QTBUG-24320", Continue);
#endif
- bool ok = false;
- QTimer::singleShot(500, this, SLOT(postKeyReturn()));
- QColorDialog::getRgba(0xffffffff, &ok);
- QVERIFY(ok);
+ QTimer::singleShot(500, this, &tst_QColorDialog::postKeyReturn);
+ const QColor color = QColorDialog::getColor(QColor::fromRgba(0xffffffff), nullptr, QString(),
+ QColorDialog::ShowAlphaChannel);
+ QVERIFY(color.isValid());
}
void tst_QColorDialog::defaultOkButton()
diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
index ae8e4f7e04..f7482bae45 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -620,13 +620,13 @@ void tst_QFiledialog::acceptMode()
void tst_QFiledialog::confirmOverwrite()
{
QFileDialog fd;
- QCOMPARE(fd.confirmOverwrite(), true);
- fd.setConfirmOverwrite(true);
- QCOMPARE(fd.confirmOverwrite(), true);
- fd.setConfirmOverwrite(false);
- QCOMPARE(fd.confirmOverwrite(), false);
- fd.setConfirmOverwrite(true);
- QCOMPARE(fd.confirmOverwrite(), true);
+ QCOMPARE(fd.testOption(QFileDialog::DontConfirmOverwrite), false);
+ fd.setOption(QFileDialog::DontConfirmOverwrite, false);
+ QCOMPARE(fd.testOption(QFileDialog::DontConfirmOverwrite), false);
+ fd.setOption(QFileDialog::DontConfirmOverwrite, true);
+ QCOMPARE(fd.testOption(QFileDialog::DontConfirmOverwrite), true);
+ fd.setOption(QFileDialog::DontConfirmOverwrite, false);
+ QCOMPARE(fd.testOption(QFileDialog::DontConfirmOverwrite), false);
}
void tst_QFiledialog::defaultSuffix()
@@ -808,8 +808,8 @@ void tst_QFiledialog::isReadOnly()
//QCOMPARE(renameAction && renameAction->isEnabled(), true);
//QCOMPARE(deleteAction && deleteAction->isEnabled(), true);
- fd.setReadOnly(true);
- QCOMPARE(fd.isReadOnly(), true);
+ fd.setOption(QFileDialog::ReadOnly, true);
+ QCOMPARE(fd.testOption(QFileDialog::ReadOnly), true);
QCOMPARE(newButton && newButton->isEnabled(), false);
QCOMPARE(renameAction && renameAction->isEnabled(), false);
@@ -853,11 +853,11 @@ void tst_QFiledialog::resolveSymlinks()
QFileDialog fd;
// default
- QCOMPARE(fd.resolveSymlinks(), true);
- fd.setResolveSymlinks(false);
- QCOMPARE(fd.resolveSymlinks(), false);
- fd.setResolveSymlinks(true);
- QCOMPARE(fd.resolveSymlinks(), true);
+ QCOMPARE(fd.testOption(QFileDialog::DontResolveSymlinks), false);
+ fd.setOption(QFileDialog::DontResolveSymlinks, true);
+ QCOMPARE(fd.testOption(QFileDialog::DontResolveSymlinks), true);
+ fd.setOption(QFileDialog::DontResolveSymlinks, false);
+ QCOMPARE(fd.testOption(QFileDialog::DontResolveSymlinks), false);
// the file dialog doesn't do anything based upon this, just passes it to the model
// the model should fully test it, don't test it here
@@ -1119,7 +1119,7 @@ void tst_QFiledialog::setNameFilter()
QFileDialog fd;
fd.setNameFilters(filters);
- fd.setNameFilterDetailsVisible(nameFilterDetailsVisible);
+ fd.setOption(QFileDialog::HideNameFilterDetails, !nameFilterDetailsVisible);
fd.selectNameFilter(selectFilter);
QCOMPARE(fd.selectedNameFilter(), expectedSelectedFilter);
}
@@ -1421,6 +1421,16 @@ void tst_QFiledialog::clearLineEdit()
QTRY_VERIFY(fd.directory().absolutePath() != workDirPath);
QVERIFY(lineEdit->text().isEmpty());
+
+ // QTBUG-71415: When pressing back, the selection (activated
+ // directory) should be restored.
+ QToolButton *backButton = fd.findChild<QToolButton*>("backButton");
+ QVERIFY(backButton);
+ QTreeView *treeView = fd.findChildren<QTreeView*>("treeView").value(0);
+ QVERIFY(treeView);
+ backButton->click();
+ QTRY_COMPARE(treeView->selectionModel()->selectedIndexes().value(0).data().toString(),
+ dirName);
}
void tst_QFiledialog::enableChooseButton()
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
index 24ce598279..869418371c 100644
--- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
@@ -252,7 +252,7 @@ void tst_QFileDialog2::showNameFilterDetails()
QFileDialog fd;
QComboBox *filters = fd.findChild<QComboBox*>("fileTypeCombo");
QVERIFY(filters);
- QVERIFY(fd.isNameFilterDetailsVisible());
+ QVERIFY(!fd.testOption(QFileDialog::HideNameFilterDetails));
QStringList filterChoices;
@@ -261,12 +261,12 @@ void tst_QFileDialog2::showNameFilterDetails()
<< "Any files (*.*)";
fd.setNameFilters(filterChoices);
- fd.setNameFilterDetailsVisible(false);
+ fd.setOption(QFileDialog::HideNameFilterDetails, true);
QCOMPARE(filters->itemText(0), QString("Image files"));
QCOMPARE(filters->itemText(1), QString("Text files"));
QCOMPARE(filters->itemText(2), QString("Any files"));
- fd.setNameFilterDetailsVisible(true);
+ fd.setOption(QFileDialog::HideNameFilterDetails, false);
QCOMPARE(filters->itemText(0), filterChoices.at(0));
QCOMPARE(filters->itemText(1), filterChoices.at(1));
QCOMPARE(filters->itemText(2), filterChoices.at(2));
@@ -486,7 +486,7 @@ protected:
parentIndex = source_parent;
QString path;
- path = parentIndex.child(source_row,0).data(Qt::DisplayRole).toString();
+ path = sourceModel()->index(source_row, 0, parentIndex).data(Qt::DisplayRole).toString();
do {
path = parentIndex.data(Qt::DisplayRole).toString() + QLatin1Char('/') + path;
diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST b/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST
index 01679eb6ee..f78d23c6b1 100644
--- a/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST
+++ b/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST
@@ -9,3 +9,5 @@ b2qt
ubuntu
b2qt
windows
+rhel
+suse-leap
diff --git a/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp
index 2ada4fedb6..6f527e7b6b 100644
--- a/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp
+++ b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp
@@ -252,7 +252,7 @@ class QTestTranslator : public QTranslator
{
const QString m_str;
public:
- explicit QTestTranslator(QString str) : m_str(qMove(str)) {}
+ explicit QTestTranslator(QString str) : m_str(std::move(str)) {}
QString translate(const char *, const char *sourceText, const char *, int) const override
{ return m_str + sourceText + m_str; }
@@ -265,7 +265,7 @@ class QTranslatorGuard {
Translator t;
public:
template <typename Arg>
- explicit QTranslatorGuard(Arg a) : t(qMove(a))
+ explicit QTranslatorGuard(Arg a) : t(std::move(a))
{ qApp->installTranslator(&t); }
~QTranslatorGuard()
{ qApp->removeTranslator(&t); }
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
index 67e1f9ce30..2f5fc597dc 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
@@ -91,7 +91,7 @@ public:
{
Q_UNUSED(option);
Q_UNUSED(widget);
- painter->drawRoundRect(rect());
+ painter->drawRoundedRect(rect(), 25, 25, Qt::RelativeSize);
painter->drawLine(rect().topLeft(), rect().bottomRight());
painter->drawLine(rect().bottomLeft(), rect().topRight());
}
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
index 34646a9074..2f0c43552f 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
@@ -125,7 +125,7 @@ public:
{
Q_UNUSED(option);
Q_UNUSED(widget);
- painter->drawRoundRect(rect());
+ painter->drawRoundedRect(rect(), 25, 25, Qt::RelativeSize);
painter->drawLine(rect().topLeft(), rect().bottomRight());
painter->drawLine(rect().bottomLeft(), rect().topRight());
}
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
index ae6de48195..16818a98f9 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
@@ -5,4 +5,4 @@ QT += core-private gui-private
SOURCES += tst_qgraphicsitem.cpp
DEFINES += QT_NO_CAST_TO_ASCII
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
index 9a75774927..0cfdecbcab 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -301,8 +301,8 @@ private slots:
void pos();
void scenePos();
void matrix();
- void sceneMatrix();
- void setMatrix();
+ void sceneTransform();
+ void setTransform();
void zValue();
void shape();
void contains();
@@ -552,8 +552,8 @@ void tst_QGraphicsItem::construction()
QVERIFY(!item->acceptHoverEvents());
QVERIFY(!item->hasFocus());
QCOMPARE(item->pos(), QPointF());
- QCOMPARE(item->matrix(), QMatrix());
- QCOMPARE(item->sceneMatrix(), QMatrix());
+ QCOMPARE(item->transform(), QTransform());
+ QCOMPARE(item->sceneTransform(), QTransform());
QCOMPARE(item->zValue(), qreal(0));
QCOMPARE(item->sceneBoundingRect(), QRectF());
QCOMPARE(item->shape(), QPainterPath());
@@ -2116,68 +2116,68 @@ void tst_QGraphicsItem::scenePos()
void tst_QGraphicsItem::matrix()
{
QGraphicsLineItem line;
- QCOMPARE(line.matrix(), QMatrix());
- line.setMatrix(QMatrix().rotate(90));
- QCOMPARE(line.matrix(), QMatrix().rotate(90));
- line.setMatrix(QMatrix().rotate(90));
- QCOMPARE(line.matrix(), QMatrix().rotate(90));
- line.setMatrix(QMatrix().rotate(90), true);
- QCOMPARE(line.matrix(), QMatrix().rotate(180));
- line.setMatrix(QMatrix().rotate(-90), true);
- QCOMPARE(line.matrix(), QMatrix().rotate(90));
- line.resetMatrix();
- QCOMPARE(line.matrix(), QMatrix());
+ QCOMPARE(line.transform(), QTransform());
+ line.setTransform(QTransform().rotate(90));
+ QCOMPARE(line.transform(), QTransform().rotate(90));
+ line.setTransform(QTransform().rotate(90));
+ QCOMPARE(line.transform(), QTransform().rotate(90));
+ line.setTransform(QTransform().rotate(90), true);
+ QCOMPARE(line.transform(), QTransform().rotate(180));
+ line.setTransform(QTransform().rotate(-90), true);
+ QCOMPARE(line.transform(), QTransform().rotate(90));
+ line.resetTransform();
+ QCOMPARE(line.transform(), QTransform());
line.setTransform(QTransform().rotate(90), true);
- QCOMPARE(line.matrix(), QMatrix().rotate(90));
+ QCOMPARE(line.transform(), QTransform().rotate(90));
line.setTransform(QTransform().rotate(90), true);
- QCOMPARE(line.matrix(), QMatrix().rotate(90).rotate(90));
- line.resetMatrix();
+ QCOMPARE(line.transform(), QTransform().rotate(90).rotate(90));
+ line.resetTransform();
line.setTransform(QTransform::fromScale(2, 4), true);
- QCOMPARE(line.matrix(), QMatrix().scale(2, 4));
+ QCOMPARE(line.transform(), QTransform::fromScale(2, 4));
line.setTransform(QTransform::fromScale(2, 4), true);
- QCOMPARE(line.matrix(), QMatrix().scale(2, 4).scale(2, 4));
- line.resetMatrix();
+ QCOMPARE(line.transform(), QTransform::fromScale(2, 4).scale(2, 4));
+ line.resetTransform();
line.setTransform(QTransform().shear(2, 4), true);
- QCOMPARE(line.matrix(), QMatrix().shear(2, 4));
+ QCOMPARE(line.transform(), QTransform().shear(2, 4));
line.setTransform(QTransform().shear(2, 4), true);
- QCOMPARE(line.matrix(), QMatrix().shear(2, 4).shear(2, 4));
- line.resetMatrix();
+ QCOMPARE(line.transform(), QTransform().shear(2, 4).shear(2, 4));
+ line.resetTransform();
line.setTransform(QTransform::fromTranslate(10, 10), true);
- QCOMPARE(line.matrix(), QMatrix().translate(10, 10));
+ QCOMPARE(line.transform(), QTransform::fromTranslate(10, 10));
line.setTransform(QTransform::fromTranslate(10, 10), true);
- QCOMPARE(line.matrix(), QMatrix().translate(10, 10).translate(10, 10));
- line.resetMatrix();
+ QCOMPARE(line.transform(), QTransform::fromTranslate(10, 10).translate(10, 10));
+ line.resetTransform();
}
-void tst_QGraphicsItem::sceneMatrix()
+void tst_QGraphicsItem::sceneTransform()
{
QGraphicsLineItem *parent = new QGraphicsLineItem;
QGraphicsLineItem *child = new QGraphicsLineItem(QLineF(), parent);
- QCOMPARE(parent->sceneMatrix(), QMatrix());
- QCOMPARE(child->sceneMatrix(), QMatrix());
+ QCOMPARE(parent->sceneTransform(), QTransform());
+ QCOMPARE(child->sceneTransform(), QTransform());
parent->setTransform(QTransform::fromTranslate(10, 10), true);
- QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
- QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10));
+ QCOMPARE(parent->sceneTransform(), QTransform().translate(10, 10));
+ QCOMPARE(child->sceneTransform(), QTransform().translate(10, 10));
child->setTransform(QTransform::fromTranslate(10, 10), true);
- QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
- QCOMPARE(child->sceneMatrix(), QMatrix().translate(20, 20));
+ QCOMPARE(parent->sceneTransform(), QTransform().translate(10, 10));
+ QCOMPARE(child->sceneTransform(), QTransform().translate(20, 20));
parent->setTransform(QTransform().rotate(90), true);
- QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10).rotate(90));
- QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10).rotate(90).translate(10, 10));
+ QCOMPARE(parent->sceneTransform(), QTransform().translate(10, 10).rotate(90));
+ QCOMPARE(child->sceneTransform(), QTransform().translate(10, 10).rotate(90).translate(10, 10));
delete child;
delete parent;
}
-void tst_QGraphicsItem::setMatrix()
+void tst_QGraphicsItem::setTransform()
{
QGraphicsScene scene;
QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
@@ -2190,7 +2190,7 @@ void tst_QGraphicsItem::setMatrix()
QCOMPARE(spy.count(), 1);
- item.setMatrix(QMatrix().rotate(qreal(12.34)));
+ item.setTransform(QTransform().rotate(qreal(12.34)));
QRectF rotatedRect = scene.sceneRect();
QVERIFY(unrotatedRect != rotatedRect);
scene.update(scene.sceneRect());
@@ -2198,7 +2198,7 @@ void tst_QGraphicsItem::setMatrix()
QCOMPARE(spy.count(), 2);
- item.setMatrix(QMatrix());
+ item.setTransform(QTransform());
scene.update(scene.sceneRect());
QApplication::instance()->processEvents();
@@ -2485,25 +2485,25 @@ void tst_QGraphicsItem::collidesWith_item()
void tst_QGraphicsItem::collidesWith_path_data()
{
QTest::addColumn<QPointF>("pos");
- QTest::addColumn<QMatrix>("matrix");
+ QTest::addColumn<QTransform>("transform");
QTest::addColumn<QPainterPath>("shape");
QTest::addColumn<bool>("rectCollides");
QTest::addColumn<bool>("ellipseCollides");
- QTest::newRow("nothing") << QPointF(0, 0) << QMatrix() << QPainterPath() << false << false;
+ QTest::newRow("nothing") << QPointF(0, 0) << QTransform() << QPainterPath() << false << false;
QPainterPath rect;
rect.addRect(0, 0, 20, 20);
- QTest::newRow("rect1") << QPointF(0, 0) << QMatrix() << rect << true << true;
- QTest::newRow("rect2") << QPointF(0, 0) << QMatrix().translate(21, 21) << rect << false << false;
- QTest::newRow("rect3") << QPointF(21, 21) << QMatrix() << rect << false << false;
+ QTest::newRow("rect1") << QPointF(0, 0) << QTransform() << rect << true << true;
+ QTest::newRow("rect2") << QPointF(0, 0) << QTransform::fromTranslate(21, 21) << rect << false << false;
+ QTest::newRow("rect3") << QPointF(21, 21) << QTransform() << rect << false << false;
}
void tst_QGraphicsItem::collidesWith_path()
{
QFETCH(QPointF, pos);
- QFETCH(QMatrix, matrix);
+ QFETCH(QTransform, transform);
QFETCH(QPainterPath, shape);
QFETCH(bool, rectCollides);
QFETCH(bool, ellipseCollides);
@@ -2512,12 +2512,12 @@ void tst_QGraphicsItem::collidesWith_path()
QGraphicsEllipseItem ellipse(QRectF(0, 0, 20, 20));
rect.setPos(pos);
- rect.setMatrix(matrix);
+ rect.setTransform(transform);
ellipse.setPos(pos);
- ellipse.setMatrix(matrix);
+ ellipse.setTransform(transform);
- QPainterPath mappedShape = rect.sceneMatrix().inverted().map(shape);
+ QPainterPath mappedShape = rect.sceneTransform().inverted().map(shape);
if (rectCollides)
QVERIFY(rect.collidesWithPath(mappedShape));
@@ -2742,35 +2742,35 @@ void tst_QGraphicsItem::mapFromToParent()
item4->setPos(10, 10);
for (int i = 0; i < 4; ++i) {
- QMatrix matrix;
- matrix.rotate(i * 90);
- matrix.translate(i * 100, -i * 100);
- matrix.scale(2, 4);
- item1->setMatrix(matrix);
+ QTransform transform;
+ transform.rotate(i * 90);
+ transform.translate(i * 100, -i * 100);
+ transform.scale(2, 4);
+ item1->setTransform(transform);
- QCOMPARE(item1->mapToParent(QPointF(0, 0)), item1->pos() + matrix.map(QPointF(0, 0)));
+ QCOMPARE(item1->mapToParent(QPointF(0, 0)), item1->pos() + transform.map(QPointF(0, 0)));
QCOMPARE(item2->mapToParent(QPointF(0, 0)), item2->pos());
QCOMPARE(item3->mapToParent(QPointF(0, 0)), item3->pos());
QCOMPARE(item4->mapToParent(QPointF(0, 0)), item4->pos());
- QCOMPARE(item1->mapToParent(QPointF(10, -10)), item1->pos() + matrix.map(QPointF(10, -10)));
+ QCOMPARE(item1->mapToParent(QPointF(10, -10)), item1->pos() + transform.map(QPointF(10, -10)));
QCOMPARE(item2->mapToParent(QPointF(10, -10)), item2->pos() + QPointF(10, -10));
QCOMPARE(item3->mapToParent(QPointF(10, -10)), item3->pos() + QPointF(10, -10));
QCOMPARE(item4->mapToParent(QPointF(10, -10)), item4->pos() + QPointF(10, -10));
- QCOMPARE(item1->mapToParent(QPointF(-10, 10)), item1->pos() + matrix.map(QPointF(-10, 10)));
+ QCOMPARE(item1->mapToParent(QPointF(-10, 10)), item1->pos() + transform.map(QPointF(-10, 10)));
QCOMPARE(item2->mapToParent(QPointF(-10, 10)), item2->pos() + QPointF(-10, 10));
QCOMPARE(item3->mapToParent(QPointF(-10, 10)), item3->pos() + QPointF(-10, 10));
QCOMPARE(item4->mapToParent(QPointF(-10, 10)), item4->pos() + QPointF(-10, 10));
- QCOMPARE(item1->mapFromParent(item1->pos()), matrix.inverted().map(QPointF(0, 0)));
+ QCOMPARE(item1->mapFromParent(item1->pos()), transform.inverted().map(QPointF(0, 0)));
QCOMPARE(item2->mapFromParent(item2->pos()), QPointF(0, 0));
QCOMPARE(item3->mapFromParent(item3->pos()), QPointF(0, 0));
QCOMPARE(item4->mapFromParent(item4->pos()), QPointF(0, 0));
QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(10, -10)),
- matrix.inverted().map(QPointF(10, -10)));
+ transform.inverted().map(QPointF(10, -10)));
QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(10, -10)), QPointF(10, -10));
QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(10, -10)), QPointF(10, -10));
QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(10, -10)), QPointF(10, -10));
QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(-10, 10)),
- matrix.inverted().map(QPointF(-10, 10)));
+ transform.inverted().map(QPointF(-10, 10)));
QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(-10, 10)), QPointF(-10, 10));
QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(-10, 10)), QPointF(-10, 10));
QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(-10, 10)), QPointF(-10, 10));
@@ -2820,8 +2820,8 @@ void tst_QGraphicsItem::mapFromToScene()
QCOMPARE(item4->mapFromScene(410, 400), QPointF(10, 0));
// Rotate item1 90 degrees clockwise
- QMatrix matrix; matrix.rotate(90);
- item1->setMatrix(matrix);
+ QTransform transform; transform.rotate(90);
+ item1->setTransform(transform);
QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
@@ -2848,7 +2848,7 @@ void tst_QGraphicsItem::mapFromToScene()
QCOMPARE(item4->mapFromScene(-200, 410), QPointF(10, 0));
// Rotate item2 90 degrees clockwise
- item2->setMatrix(matrix);
+ item2->setTransform(transform);
QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
@@ -2875,10 +2875,10 @@ void tst_QGraphicsItem::mapFromToScene()
QCOMPARE(item4->mapFromScene(-210, 0), QPointF(10, 0));
// Translate item3 50 points, then rotate 90 degrees counterclockwise
- QMatrix matrix2;
- matrix2.translate(50, 0);
- matrix2.rotate(-90);
- item3->setMatrix(matrix2);
+ QTransform transform2;
+ transform2.translate(50, 0);
+ transform2.rotate(-90);
+ item3->setTransform(transform2);
QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
QCOMPARE(item3->pos(), item3->mapToParent(0, 0) - QPointF(50, 0));
@@ -2928,9 +2928,9 @@ void tst_QGraphicsItem::mapFromToItem()
QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
- QMatrix matrix;
- matrix.translate(100, 100);
- item1->setMatrix(matrix);
+ QTransform transform;
+ transform.translate(100, 100);
+ item1->setTransform(transform);
QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(100, -100));
QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
@@ -2941,11 +2941,11 @@ void tst_QGraphicsItem::mapFromToItem()
QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
- matrix.rotate(90);
- item1->setMatrix(matrix);
- item2->setMatrix(matrix);
- item3->setMatrix(matrix);
- item4->setMatrix(matrix);
+ transform.rotate(90);
+ item1->setTransform(transform);
+ item2->setTransform(transform);
+ item3->setTransform(transform);
+ item4->setTransform(transform);
QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(0, -200));
QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(200, 0));
@@ -4433,9 +4433,12 @@ protected:
case QGraphicsItem::ItemPositionHasChanged:
break;
case QGraphicsItem::ItemMatrixChange: {
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QVariant variant;
variant.setValue<QMatrix>(matrix());
oldValues << variant;
+QT_WARNING_POP
}
break;
case QGraphicsItem::ItemTransformChange: {
@@ -4556,6 +4559,8 @@ void tst_QGraphicsItem::itemChange()
QCOMPARE(tester.isEnabled(), true);
}
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED // QDesktopWidget::screen()
// ItemMatrixChange / ItemTransformHasChanged
tester.itemChangeReturnValue.setValue<QMatrix>(QMatrix().rotate(90));
tester.setMatrix(QMatrix().translate(50, 0), true);
@@ -4570,6 +4575,7 @@ void tst_QGraphicsItem::itemChange()
variant.setValue<QMatrix>(QMatrix());
QCOMPARE(tester.oldValues.last(), variant);
QCOMPARE(tester.matrix(), QMatrix().rotate(90));
+QT_WARNING_POP
}
{
tester.resetTransform();
@@ -8380,7 +8386,7 @@ void tst_QGraphicsItem::focusProxy()
QString err;
QTextStream stream(&err);
stream << "QGraphicsItem::setFocusProxy: "
- << (void*)item << " is already in the focus proxy chain" << flush;
+ << (void*)item << " is already in the focus proxy chain" << Qt::flush;
QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
item2->setFocusProxy(item); // fails
QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp
index dfb2752ee0..ed79904ed8 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp
@@ -54,9 +54,9 @@ void tst_QGraphicsItemAnimation::construction()
QCOMPARE(animation.posAt(0), QPointF());
QCOMPARE(animation.posAt(0.5), QPointF());
QCOMPARE(animation.posAt(1), QPointF());
- QCOMPARE(animation.matrixAt(0), QMatrix());
- QCOMPARE(animation.matrixAt(0.5), QMatrix());
- QCOMPARE(animation.matrixAt(1), QMatrix());
+ QCOMPARE(animation.transformAt(0), QTransform());
+ QCOMPARE(animation.transformAt(0.5), QTransform());
+ QCOMPARE(animation.transformAt(1), QTransform());
QCOMPARE(animation.rotationAt(0), qreal(0.0));
QCOMPARE(animation.rotationAt(0.5), qreal(0.0));
QCOMPARE(animation.rotationAt(1), qreal(0.0));
diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
index f9b6fe3ebd..9369470ce5 100644
--- a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
@@ -150,7 +150,7 @@ public:
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setBrush(m_brush);
- painter->drawRoundRect(rect());
+ painter->drawRoundedRect(rect(), 25, 25, Qt::RelativeSize);
}
void setSizeHint(Qt::SizeHint which, const QSizeF &size) {
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
index 351cecd92e..2f648a2212 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
@@ -4,7 +4,7 @@ QT += widgets widgets-private testlib
QT += core-private gui-private
SOURCES += tst_qgraphicsscene.cpp
RESOURCES += images.qrc
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
DEFINES += SRCDIR=\\\"$$PWD\\\"
DEFINES += QT_NO_CAST_TO_ASCII
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
index 48488abfb8..46f1d5df5c 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
@@ -112,14 +112,14 @@ protected:
painter->setOpacity(0.75);
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::darkGray);
- painter->drawRoundRect(boundingRect().adjusted(3, 3, -3, -3), Qt::darkGray);
+ painter->drawRoundedRect(boundingRect().adjusted(3, 3, -3, -3), 25, 25, Qt::RelativeSize);
painter->setPen(Qt::black);
if (isHovered) {
- painter->setBrush(QColor(Qt::blue).light(120));
+ painter->setBrush(QColor(Qt::blue).lighter(120));
} else {
painter->setBrush(Qt::gray);
}
- painter->drawRoundRect(boundingRect().adjusted(0, 0, -5, -5));
+ painter->drawRoundedRect(boundingRect().adjusted(0, 0, -5, -5), 25, 25, Qt::RelativeSize);
}
};
@@ -233,7 +233,6 @@ private slots:
void tabFocus_sceneWithFocusWidgets();
void tabFocus_sceneWithNestedFocusWidgets();
void style();
- void sorting_data();
void sorting();
void insertionOrder();
void changedSignal_data();
@@ -459,41 +458,41 @@ void tst_QGraphicsScene::items()
void tst_QGraphicsScene::itemsBoundingRect_data()
{
QTest::addColumn<QList<QRectF> >("rects");
- QTest::addColumn<QMatrix>("matrix");
+ QTest::addColumn<QTransform>("transform");
QTest::addColumn<QRectF>("boundingRect");
- QMatrix transformationMatrix;
- transformationMatrix.translate(50, -50);
- transformationMatrix.scale(2, 2);
- transformationMatrix.rotate(90);
+ QTransform transformation;
+ transformation.translate(50, -50);
+ transformation.scale(2, 2);
+ transformation.rotate(90);
QTest::newRow("none")
<< QList<QRectF>()
- << QMatrix()
+ << QTransform()
<< QRectF();
QTest::newRow("{{0, 0, 10, 10}}")
<< (QList<QRectF>() << QRectF(0, 0, 10, 10))
- << QMatrix()
+ << QTransform()
<< QRectF(0, 0, 10, 10);
QTest::newRow("{{-10, -10, 10, 10}}")
<< (QList<QRectF>() << QRectF(-10, -10, 10, 10))
- << QMatrix()
+ << QTransform()
<< QRectF(-10, -10, 10, 10);
QTest::newRow("{{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}")
<< (QList<QRectF>() << QRectF(-1000, -1000, 1, 1) << QRectF(-10, -10, 10, 10))
- << QMatrix()
+ << QTransform()
<< QRectF(-1000, -1000, 1000, 1000);
QTest::newRow("transformed {{0, 0, 10, 10}}")
<< (QList<QRectF>() << QRectF(0, 0, 10, 10))
- << transformationMatrix
+ << transformation
<< QRectF(30, -50, 20, 20);
QTest::newRow("transformed {{-10, -10, 10, 10}}")
<< (QList<QRectF>() << QRectF(-10, -10, 10, 10))
- << transformationMatrix
+ << transformation
<< QRectF(50, -70, 20, 20);
QTest::newRow("transformed {{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}")
<< (QList<QRectF>() << QRectF(-1000, -1000, 1, 1) << QRectF(-10, -10, 10, 10))
- << transformationMatrix
+ << transformation
<< QRectF(50, -2050, 2000, 2000);
QList<QRectF> all;
@@ -501,18 +500,18 @@ void tst_QGraphicsScene::itemsBoundingRect_data()
all << QRectF(randomX[i], randomY[i], 10, 10);
QTest::newRow("all")
<< all
- << QMatrix()
+ << QTransform()
<< QRectF(-980, -994, 1988, 1983);
QTest::newRow("transformed all")
<< all
- << transformationMatrix
+ << transformation
<< QRectF(-1928, -2010, 3966, 3976);
}
void tst_QGraphicsScene::itemsBoundingRect()
{
QFETCH(QList<QRectF>, rects);
- QFETCH(QMatrix, matrix);
+ QFETCH(QTransform, transform);
QFETCH(QRectF, boundingRect);
QGraphicsScene scene;
@@ -522,7 +521,7 @@ void tst_QGraphicsScene::itemsBoundingRect()
path.addRect(rect);
QGraphicsPathItem *item = scene.addPath(path);
item->setPen(QPen(Qt::black, 0));
- item->setMatrix(matrix);
+ item->setTransform(transform);
}
QCOMPARE(scene.itemsBoundingRect(), boundingRect);
@@ -2502,7 +2501,7 @@ void tst_QGraphicsScene::render_data()
QTest::addColumn<QRectF>("targetRect");
QTest::addColumn<QRectF>("sourceRect");
QTest::addColumn<Qt::AspectRatioMode>("aspectRatioMode");
- QTest::addColumn<QMatrix>("matrix");
+ QTest::addColumn<QTransform>("transform");
QTest::addColumn<QPainterPath>("clip");
QPainterPath clip_rect;
@@ -2512,61 +2511,61 @@ void tst_QGraphicsScene::render_data()
clip_ellipse.addEllipse(100,50,150,200);
QTest::newRow("all-all-untransformed") << QRectF() << QRectF()
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("all-topleft-untransformed") << QRectF(0, 0, 150, 150)
- << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << QRectF() << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("all-topright-untransformed") << QRectF(150, 0, 150, 150)
- << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << QRectF() << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("all-bottomleft-untransformed") << QRectF(0, 150, 150, 150)
- << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << QRectF() << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("all-bottomright-untransformed") << QRectF(150, 150, 150, 150)
- << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << QRectF() << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("topleft-all-untransformed") << QRectF() << QRectF(-10, -10, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("topright-all-untransformed") << QRectF() << QRectF(0, -10, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("bottomleft-all-untransformed") << QRectF() << QRectF(-10, 0, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("bottomright-all-untransformed") << QRectF() << QRectF(0, 0, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("topleft-topleft-untransformed") << QRectF(0, 0, 150, 150) << QRectF(-10, -10, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("topright-topleft-untransformed") << QRectF(150, 0, 150, 150) << QRectF(-10, -10, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("bottomleft-topleft-untransformed") << QRectF(0, 150, 150, 150) << QRectF(-10, -10, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("bottomright-topleft-untransformed") << QRectF(150, 150, 150, 150) << QRectF(-10, -10, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("top-topleft-untransformed") << QRectF(0, 0, 300, 150) << QRectF(-10, -10, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("bottom-topleft-untransformed") << QRectF(0, 150, 300, 150) << QRectF(-10, -10, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("left-topleft-untransformed") << QRectF(0, 0, 150, 300) << QRectF(-10, -10, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("right-topleft-untransformed") << QRectF(150, 0, 150, 300) << QRectF(-10, -10, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("top-bottomright-untransformed") << QRectF(0, 0, 300, 150) << QRectF(0, 0, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("bottom-bottomright-untransformed") << QRectF(0, 150, 300, 150) << QRectF(0, 0, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("left-bottomright-untransformed") << QRectF(0, 0, 150, 300) << QRectF(0, 0, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("right-bottomright-untransformed") << QRectF(150, 0, 150, 300) << QRectF(0, 0, 10, 10)
- << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform() << QPainterPath();
QTest::newRow("all-all-45-deg-right") << QRectF() << QRectF()
- << Qt::IgnoreAspectRatio << QMatrix().rotate(-45) << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform().rotate(-45) << QPainterPath();
QTest::newRow("all-all-45-deg-left") << QRectF() << QRectF()
- << Qt::IgnoreAspectRatio << QMatrix().rotate(45) << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform().rotate(45) << QPainterPath();
QTest::newRow("all-all-scale-2x") << QRectF() << QRectF()
- << Qt::IgnoreAspectRatio << QMatrix().scale(2, 2) << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform::fromScale(2, 2) << QPainterPath();
QTest::newRow("all-all-translate-50-0") << QRectF() << QRectF()
- << Qt::IgnoreAspectRatio << QMatrix().translate(50, 0) << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform::fromTranslate(50, 0) << QPainterPath();
QTest::newRow("all-all-translate-0-50") << QRectF() << QRectF()
- << Qt::IgnoreAspectRatio << QMatrix().translate(0, 50) << QPainterPath();
+ << Qt::IgnoreAspectRatio << QTransform::fromTranslate(0, 50) << QPainterPath();
QTest::newRow("all-all-untransformed-clip-rect") << QRectF() << QRectF()
- << Qt::IgnoreAspectRatio << QMatrix() << clip_rect;
+ << Qt::IgnoreAspectRatio << QTransform() << clip_rect;
QTest::newRow("all-all-untransformed-clip-ellipse") << QRectF() << QRectF()
- << Qt::IgnoreAspectRatio << QMatrix() << clip_ellipse;
+ << Qt::IgnoreAspectRatio << QTransform() << clip_ellipse;
}
void tst_QGraphicsScene::render()
@@ -2574,7 +2573,7 @@ void tst_QGraphicsScene::render()
QFETCH(QRectF, targetRect);
QFETCH(QRectF, sourceRect);
QFETCH(Qt::AspectRatioMode, aspectRatioMode);
- QFETCH(QMatrix, matrix);
+ QFETCH(QTransform, transform);
QFETCH(QPainterPath, clip);
QPixmap pix(30, 30);
@@ -2602,7 +2601,7 @@ void tst_QGraphicsScene::render()
painter.setPen(QPen(Qt::darkGray, 2));
painter.drawLine(0, 150, 300, 150);
painter.drawLine(150, 0, 150, 300);
- painter.setMatrix(matrix);
+ painter.setTransform(transform);
if (!clip.isEmpty()) painter.setClipPath(clip);
scene.render(&painter, targetRect, sourceRect, aspectRatioMode);
painter.end();
@@ -3519,20 +3518,9 @@ void tst_QGraphicsScene::task250680_childClip()
QCOMPARE(scene.items(QRectF(320, 240, 5, 5)).size(), 2);
}
-void tst_QGraphicsScene::sorting_data()
-{
- QTest::addColumn<bool>("cache");
-
- QTest::newRow("Normal sorting") << false;
- QTest::newRow("Cached sorting") << true;
-}
-
void tst_QGraphicsScene::sorting()
{
- QFETCH(bool, cache);
-
QGraphicsScene scene;
- scene.setSortCacheEnabled(cache);
QGraphicsRectItem *t_1 = new QGraphicsRectItem(0, 0, 50, 50);
QGraphicsRectItem *c_1 = new QGraphicsRectItem(0, 0, 40, 40, t_1);
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST
index e3d968b4f2..ee13a37212 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST
@@ -4,6 +4,7 @@ xcb
xcb
[cursor2]
xcb
+windows
[rubberBandExtendSelection]
xcb
[rotated_rubberBand]
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index 28df3a3c38..6e42758122 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -2280,53 +2280,53 @@ void tst_QGraphicsView::cursor2()
QVERIFY(QTest::qWaitForWindowExposed(&view));
sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
sendMouseMove(view.viewport(), view.mapFromScene(-15, 0));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
view.setDragMode(QGraphicsView::ScrollHandDrag);
sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
view.setDragMode(QGraphicsView::NoDrag);
- QCOMPARE(view.viewport()->cursor().shape(), Qt::ArrowCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::ArrowCursor);
view.viewport()->setCursor(Qt::PointingHandCursor);
- QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
item2->setCursor(Qt::SizeAllCursor);
sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
view.setDragMode(QGraphicsView::ScrollHandDrag);
sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
- QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
}
#endif
@@ -4857,7 +4857,7 @@ void tst_QGraphicsView::QTBUG_16063_microFocusRect()
scene.setFocusItem(item);
view.setFocus();
- QRectF mfv = view.inputMethodQuery(Qt::ImMicroFocus).toRectF();
+ QRectF mfv = view.inputMethodQuery(Qt::ImCursorRectangle).toRectF();
QCOMPARE(mfv, IMItem::mf.translated(-view.mapToScene(view.sceneRect().toRect()).boundingRect().topLeft()));
}
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index 45c86800d6..6f7dca86eb 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -502,11 +502,6 @@ void tst_QAbstractItemView::basic_tests(QAbstractItemView *view)
view->commitData(0);
view->editorDestroyed(0);
- view->setHorizontalStepsPerItem(2);
- view->horizontalStepsPerItem();
- view->setVerticalStepsPerItem(2);
- view->verticalStepsPerItem();
-
// Will assert as it should
// view->setIndexWidget(QModelIndex(), 0);
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index 12e458c669..f247889d55 100644
--- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -85,7 +85,8 @@ class XResetModel : public QStandardItemModel
blockSignals(true);
bool r = QStandardItemModel::removeRows(row, count, parent);
blockSignals(false);
- emit reset();
+ beginResetModel();
+ endResetModel();
return r;
}
virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex())
@@ -93,7 +94,8 @@ class XResetModel : public QStandardItemModel
blockSignals(true);
bool r = QStandardItemModel::insertRows(row, count, parent);
blockSignals(false);
- emit reset();
+ beginResetModel();
+ endResetModel();
return r;
}
};
@@ -246,6 +248,7 @@ private slots:
void sizeHintCrash();
void testResetCachedSizeHint();
void statusTips();
+ void testRemovingColumnsViaLayoutChanged();
protected:
void setupTestData(bool use_reset_model = false);
@@ -253,11 +256,12 @@ protected:
void calculateAndCheck(int cppline, const int precalced_comparedata[]);
void testMinMaxSectionSize(bool stretchLastSection);
- QWidget *topLevel;
- QHeaderView *view;
- QStandardItemModel *model;
- QTableView *m_tableview;
- bool m_using_reset_model;
+ QWidget *topLevel = nullptr;
+ QHeaderView *view = nullptr;
+ QStandardItemModel *model = nullptr;
+ QTableView *m_tableview = nullptr;
+ bool m_using_reset_model = false;
+ bool m_special_prepare = false;
QElapsedTimer timer;
};
@@ -350,6 +354,7 @@ public:
void cleanup()
{
+ emit layoutAboutToBeChanged();
cols = 3;
rows = 3;
emit layoutChanged();
@@ -620,6 +625,27 @@ void tst_QHeaderView::hidden()
view->setSectionHidden(1, false);
QCOMPARE(view->isSectionHidden(0), false);
QCOMPARE(view->sectionSize(0), view->defaultSectionSize());
+
+ // d->hiddenSectionSize could go out of sync when a new model
+ // was set which has fewer sections than before and some of them
+ // were hidden
+ QStandardItemModel model2(model->rowCount() - 1, model->columnCount());
+
+ for (int i = 0; i < model->rowCount(); ++i)
+ view->setSectionHidden(i, true);
+ view->setModel(&model2);
+ QVERIFY(view->sectionsHidden());
+ for (int i = 0; i < model2.rowCount(); ++i) {
+ QVERIFY(view->isSectionHidden(i));
+ }
+
+ view->setModel(model);
+ for (int i = 0; i < model2.rowCount(); ++i) {
+ QVERIFY(view->isSectionHidden(i));
+ }
+ QCOMPARE(view->isSectionHidden(model->rowCount() - 1), false);
+ for (int i = 0; i < model->rowCount(); ++i)
+ view->setSectionHidden(i, false);
}
void tst_QHeaderView::stretch()
@@ -2833,6 +2859,7 @@ void tst_QHeaderView::additionalInit()
QFETCH(bool, reset_model);
m_using_reset_model = reset_model;
+ m_special_prepare = special_prepare;
if (m_using_reset_model) {
XResetModel *m = new XResetModel();
@@ -3046,18 +3073,34 @@ void tst_QHeaderView::mixedTests()
view->moveSection(0, 5);
for (int u = model->rowCount(); u >= 0; --u) {
- if (u % 5 != 0)
+ if (u % 5 != 0) {
view->hideSection(u);
- if (u % 3 != 0)
+ QVERIFY(view->isSectionHidden(u));
+ }
+ if (u % 3 != 0) {
view->showSection(u);
+ QVERIFY(!view->isSectionHidden(u));
+ }
}
model->insertRows(3, 7);
model->removeRows(8, 3);
model->setRowCount(model->rowCount() - 10);
+ // the upper is not visible (when m_using_reset_model is true)
+ // the lower 11 are modified due to insert/removeRows
+ for (int u = model->rowCount() - 1; u >= 11; --u) {
+ // when using reset, the hidden rows will *not* move
+ const int calcMod = m_using_reset_model ? u : u - 4; // 7 added, 3 removed
+ if (calcMod % 5 != 0 && calcMod % 3 == 0) {
+ QVERIFY(view->isSectionHidden(u));
+ }
+ if (calcMod % 3 != 0) {
+ QVERIFY(!view->isSectionHidden(u));
+ }
+ }
if (m_using_reset_model) {
- const int precalced_results[] = { 898296472, 337096378, -543340640, 1, -1251526424, -568618976, 9250 };
+ const int precalced_results[] = { 898296472, 337096378, -543340640, -1964432121, -1251526424, -568618976, 9250 };
calculateAndCheck(__LINE__, precalced_results);
} else {
const int precalced_results[] = { 1911338224, 1693514365, -613398968, -1912534953, 1582159424, -1851079000, 9300 };
@@ -3448,5 +3491,20 @@ void tst_QHeaderView::statusTips()
QCOMPARE(headerView.statusTipText, QLatin1String("[0,1,0] -- Header"));
}
+void tst_QHeaderView::testRemovingColumnsViaLayoutChanged()
+{
+ const int persistentSectionSize = 101;
+
+ QtTestModel model;
+ model.rows = model.cols = 5;
+ view->setModel(&model);
+ for (int i = 0; i < model.cols; ++i)
+ view->resizeSection(i, persistentSectionSize + i);
+ model.cleanup(); // down to 3 via layoutChanged (not columnsRemoved)
+ for (int j = 0; j < model.cols; ++j)
+ QCOMPARE(view->sectionSize(j), persistentSectionSize + j);
+ // The main point of this test is that the section-size restoring code didn't go out of bounds.
+}
+
QTEST_MAIN(tst_QHeaderView)
#include "tst_qheaderview.moc"
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
index 10cd1dcc54..916694fd0f 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
+++ b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
@@ -3,4 +3,4 @@ TARGET = tst_qitemdelegate
QT += widgets widgets-private testlib
SOURCES += tst_qitemdelegate.cpp
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
index 961c8aa4ad..dc246c0ebf 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
+++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
@@ -1233,7 +1233,7 @@ void tst_QItemDelegate::editorEvent()
option.checkState = Qt::CheckState(checkState);
const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
- QPoint pos = inCheck ? qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0) : QPoint(200,200);
+ QPoint pos = inCheck ? qApp->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0) : QPoint(200,200);
QEvent *event = new QMouseEvent((QEvent::Type)type,
pos,
@@ -1389,7 +1389,7 @@ void tst_QItemDelegate::QTBUG4435_keepSelectionOnCheck()
option.features = QStyleOptionViewItem::HasDisplay | QStyleOptionViewItem::HasCheckIndicator;
option.checkState = Qt::CheckState(model.index(0, 0).data(Qt::CheckStateRole).toInt());
const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
- QPoint pos = qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center()
+ QPoint pos = qApp->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &option, 0).center()
+ QPoint(checkMargin, 0);
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, pos);
QTRY_VERIFY(view.selectionModel()->isColumnSelected(0, QModelIndex()));
diff --git a/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp b/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
index bbdaac5c6f..071665a5e3 100644
--- a/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
+++ b/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
@@ -249,7 +249,7 @@ void tst_QItemView::populate()
for (int y = 0; y < treeModel->columnCount(); ++y) {
QModelIndex index = treeModel->index(x, y, parent);
treeModel->setData(index, xS + QLatin1Char('_') + QString::number(y) + QLatin1Char('_') + iS);
- treeModel->setData(index, QVariant(QColor(Qt::blue)), Qt::TextColorRole);
+ treeModel->setData(index, QVariant(QColor(Qt::blue)), Qt::ForegroundRole);
}
}
}
diff --git a/tests/auto/widgets/itemviews/qlistview/qlistview.pro b/tests/auto/widgets/itemviews/qlistview/qlistview.pro
index 75f45ab432..c3e19adc81 100644
--- a/tests/auto/widgets/itemviews/qlistview/qlistview.pro
+++ b/tests/auto/widgets/itemviews/qlistview/qlistview.pro
@@ -2,4 +2,4 @@ CONFIG += testcase
TARGET = tst_qlistview
QT += widgets gui-private widgets-private core-private testlib testlib-private
SOURCES += tst_qlistview.cpp
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
index 9511654110..0b828b8484 100644
--- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
+++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -891,6 +891,10 @@ void tst_QListView::setCurrentIndex()
}
}
}
+ while (model.rowCount()) {
+ view.setCurrentIndex(model.index(model.rowCount() - 1, 0));
+ model.removeRow(model.rowCount() - 1);
+ }
}
class PublicListView : public QListView
diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
index 98b44fe8aa..fe2ede4183 100644
--- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
@@ -31,6 +31,7 @@
#include <QtGui/QtGui>
#include <QtWidgets/QtWidgets>
#include <qlist.h>
+#include <QSignalSpy>
#include <qlistwidget.h>
#include <private/qlistwidget_p.h>
@@ -116,6 +117,14 @@ private slots:
void QTBUG14363_completerWithAnyKeyPressedEditTriggers();
void mimeData();
void QTBUG50891_ensureSelectionModelSignalConnectionsAreSet();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ void clearItemData();
+#endif
+
+ void moveRows_data();
+ void moveRows();
+ void moveRowsInvalid_data();
+ void moveRowsInvalid();
protected slots:
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
@@ -148,6 +157,108 @@ private:
};
+void tst_QListWidget::moveRowsInvalid_data()
+{
+ QTest::addColumn<QListWidget*>("baseWidget");
+ QTest::addColumn<QModelIndex>("startParent");
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<QModelIndex>("destinationParent");
+ QTest::addColumn<int>("destination");
+
+ const auto createWidget = []() -> QListWidget* {
+ QListWidget* result = new QListWidget;
+ result->addItems(QStringList{"A", "B", "C", "D", "E", "F"});
+ return result;
+ };
+
+ QTest::addRow("destination_equal_source") << createWidget() << QModelIndex() << 0 << 1 << QModelIndex() << 1;
+ QTest::addRow("count_equal_0") << createWidget() << QModelIndex() << 0 << 0 << QModelIndex() << 2;
+ QListWidget* tempWidget = createWidget();
+ QTest::addRow("move_child") << tempWidget << tempWidget->model()->index(0, 0) << 0 << 1 << QModelIndex() << 2;
+ tempWidget = createWidget();
+ QTest::addRow("move_to_child") << tempWidget << QModelIndex() << 0 << 1 << tempWidget->model()->index(0, 0) << 2;
+ QTest::addRow("negative_count") << createWidget() << QModelIndex() << 0 << -1 << QModelIndex() << 2;
+ QTest::addRow("negative_source_row") << createWidget() << QModelIndex() << -1 << 1 << QModelIndex() << 2;
+ QTest::addRow("negative_destination_row") << createWidget() << QModelIndex() << 0 << 1 << QModelIndex() << -1;
+ QTest::addRow("source_row_equal_rowCount") << createWidget() << QModelIndex() << 6 << 1 << QModelIndex() << 1;
+ QTest::addRow("destination_row_greater_rowCount") << createWidget() << QModelIndex() << 0 << 1 << QModelIndex() << 6 + 1;
+ QTest::addRow("move_row_within_source_range") << createWidget() << QModelIndex() << 0 << 3 << QModelIndex() << 2;
+ QTest::addRow("destination_row_before_0") << createWidget() << QModelIndex() << 1 << 1 << QModelIndex() << 0;
+}
+
+void tst_QListWidget::moveRowsInvalid()
+{
+ QFETCH(QListWidget* const, baseWidget);
+ QFETCH(const QModelIndex, startParent);
+ QFETCH(const int, startRow);
+ QFETCH(const int, count);
+ QFETCH(const QModelIndex, destinationParent);
+ QFETCH(const int, destination);
+ QAbstractItemModel *baseModel = baseWidget->model();
+ QSignalSpy rowMovedSpy(baseModel, &QAbstractItemModel::rowsMoved);
+ QSignalSpy rowAboutMovedSpy(baseModel, &QAbstractItemModel::rowsAboutToBeMoved);
+ QVERIFY(rowMovedSpy.isValid());
+ QVERIFY(rowAboutMovedSpy.isValid());
+ QVERIFY(!baseModel->moveRows(startParent, startRow, count, destinationParent, destination));
+ QCOMPARE(rowMovedSpy.size(), 0);
+ QCOMPARE(rowAboutMovedSpy.size(), 0);
+ delete baseWidget;
+}
+
+void tst_QListWidget::moveRows_data()
+{
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<int>("destination");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("1_Item_from_top_to_middle") << 0 << 1 << 3 << QStringList{"B", "C", "A", "D", "E", "F"};
+ QTest::newRow("1_Item_from_top_to_bottom") << 0 << 1 << 6 << QStringList{"B", "C", "D", "E", "F", "A"};
+ QTest::newRow("1_Item_from_middle_to_top") << 2 << 1 << 1 << QStringList{"C", "A", "B", "D", "E", "F"};
+ QTest::newRow("1_Item_from_bottom_to_middle") << 5 << 1 << 3 << QStringList{"A", "B", "F", "C", "D", "E"};
+ QTest::newRow("1_Item_from_bottom to_top") << 5 << 1 << 1 << QStringList{"F", "A", "B", "C", "D", "E"};
+ QTest::newRow("1_Item_from_middle_to_bottom") << 2 << 1 << 6 << QStringList{"A", "B", "D", "E", "F", "C"};
+ QTest::newRow("1_Item_from_middle_to_middle_before") << 2 << 1 << 1 << QStringList{"C", "A", "B", "D", "E", "F"};
+ QTest::newRow("1_Item_from_middle_to_middle_after") << 2 << 1 << 4 << QStringList{"A", "B", "D", "C", "E", "F"};
+
+ QTest::newRow("2_Items_from_top_to_middle") << 0 << 2 << 3 << QStringList{"C", "A", "B", "D", "E", "F"};
+ QTest::newRow("2_Items_from_top_to_bottom") << 0 << 2 << 6 << QStringList{"C", "D", "E", "F", "A", "B"};
+ QTest::newRow("2_Items_from_middle_to_top") << 2 << 2 << 1 << QStringList{"C", "D", "A", "B", "E", "F"};
+ QTest::newRow("2_Items_from_bottom_to_middle") << 4 << 2 << 3 << QStringList{"A", "B", "E", "F", "C", "D"};
+ QTest::newRow("2_Items_from_bottom_to_top") << 4 << 2 << 1 << QStringList{"E", "F", "A", "B", "C", "D"};
+ QTest::newRow("2_Items_from_middle_to_bottom") << 2 << 2 << 6 << QStringList{"A", "B", "E", "F", "C", "D"};
+ QTest::newRow("2_Items_from_middle_to_middle_before") << 3 << 2 << 2 << QStringList{"A", "D", "E", "B", "C", "F"};
+ QTest::newRow("2_Items_from_middle_to_middle_after") << 1 << 2 << 5 << QStringList{"A", "D", "E", "B", "C", "F"};
+}
+
+void tst_QListWidget::moveRows()
+{
+ QFETCH(const int, startRow);
+ QFETCH(const int, count);
+ QFETCH(const int, destination);
+ QFETCH(const QStringList, expected);
+ QListWidget baseWidget;
+ baseWidget.addItems(QStringList{"A", "B", "C", "D", "E", "F"});
+ QAbstractItemModel *baseModel = baseWidget.model();
+ QSignalSpy rowMovedSpy(baseModel, &QAbstractItemModel::rowsMoved);
+ QSignalSpy rowAboutMovedSpy(baseModel, &QAbstractItemModel::rowsAboutToBeMoved);
+ QVERIFY(baseModel->moveRows(QModelIndex(), startRow, count, QModelIndex(), destination));
+ QCOMPARE(baseModel->rowCount(), expected.size());
+ for (int i = 0; i < expected.size(); ++i)
+ QCOMPARE(baseModel->index(i, 0).data().toString(), expected.at(i));
+ QCOMPARE(rowMovedSpy.size(), 1);
+ QCOMPARE(rowAboutMovedSpy.size(), 1);
+ for (const QList<QVariant> &signalArgs : {rowMovedSpy.first(), rowAboutMovedSpy.first()}){
+ QVERIFY(!signalArgs.at(0).value<QModelIndex>().isValid());
+ QCOMPARE(signalArgs.at(1).toInt(), startRow);
+ QCOMPARE(signalArgs.at(2).toInt(), startRow + count - 1);
+ QVERIFY(!signalArgs.at(3).value<QModelIndex>().isValid());
+ QCOMPARE(signalArgs.at(4).toInt(), destination);
+ }
+}
+
+
typedef QList<int> IntList;
tst_QListWidget::tst_QListWidget(): testWidget(0), rcParent(8), rcFirst(8,0), rcLast(8,0)
@@ -156,6 +267,7 @@ tst_QListWidget::tst_QListWidget(): testWidget(0), rcParent(8), rcFirst(8,0), rc
void tst_QListWidget::initTestCase()
{
+ qRegisterMetaType<QListWidgetItem*>("QListWidgetItem*");
testWidget = new QListWidget();
testWidget->show();
@@ -233,7 +345,7 @@ void tst_QListWidget::addItem2()
testWidget->addItem(item);
QCOMPARE(testWidget->count(), ++count);
QCOMPARE(testWidget->item(testWidget->count()-1), item);
- QCOMPARE(testWidget->isItemHidden(item), false);
+ QCOMPARE(item->isHidden(), false);
}
void tst_QListWidget::addItems()
@@ -291,13 +403,18 @@ void tst_QListWidget::closePersistentEditor()
void tst_QListWidget::setItemHidden()
{
+#if QT_DEPRECATED_SINCE(5, 13)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
// Boundary checking
- testWidget->setItemHidden(0, true);
- testWidget->setItemHidden(0, false);
+ testWidget->setItemHidden(nullptr, true);
+ testWidget->setItemHidden(nullptr, false);
+QT_WARNING_POP
+#endif
int totalHidden = 0;
for (int i = 0; i < testWidget->model()->rowCount(); ++i)
- if (testWidget->isItemHidden(testWidget->item(i)))
+ if (testWidget->item(i)->isHidden())
totalHidden++;
QListWidgetItem *item = new QListWidgetItem(QString::number(testWidget->count()));
@@ -306,31 +423,31 @@ void tst_QListWidget::setItemHidden()
// Check that nothing else changed
int newTotal = 0;
for (int i = 0; i < testWidget->model()->rowCount(); ++i)
- if (testWidget->isItemHidden(testWidget->item(i)))
+ if (testWidget->item(i)->isHidden())
newTotal++;
QCOMPARE(newTotal, totalHidden);
- testWidget->setItemHidden(item, true);
- QCOMPARE(testWidget->isItemHidden(item), true);
+ item->setHidden(true);
+ QCOMPARE(item->isHidden(), true);
// Check that nothing else changed
newTotal = 0;
for (int i = 0; i < testWidget->model()->rowCount(); ++i)
- if (testWidget->isItemHidden(testWidget->item(i)))
+ if (testWidget->item(i)->isHidden())
newTotal++;
QCOMPARE(newTotal, totalHidden + 1);
- testWidget->setItemHidden(item, false);
- QCOMPARE(testWidget->isItemHidden(item), false);
+ item->setHidden(false);
+ QCOMPARE(item->isHidden(), false);
// Check that nothing else changed
newTotal = 0;
for (int i = 0; i < testWidget->model()->rowCount(); ++i)
- if (testWidget->isItemHidden(testWidget->item(i)))
+ if (testWidget->item(i)->isHidden())
newTotal++;
QCOMPARE(newTotal, totalHidden);
- testWidget->setItemHidden(item, true);
+ item->setHidden(true);
}
void tst_QListWidget::setCurrentItem_data()
@@ -547,6 +664,9 @@ void tst_QListWidget::insertItems()
QFETCH(int, rowCount);
QFETCH(int, insertType);
+ QSignalSpy itemChangedSpy(testWidget, &QListWidget::itemChanged);
+ QSignalSpy dataChangedSpy(testWidget->model(), &QAbstractItemModel::dataChanged);
+
if (insertType == 3) {
QStringList strings;
for (int i=0; i<rowCount; ++i)
@@ -584,6 +704,9 @@ void tst_QListWidget::insertItems()
// make sure all items have view set correctly
for (int i=0; i<testWidget->count(); ++i)
QCOMPARE(testWidget->item(i)->listWidget(), testWidget);
+
+ QCOMPARE(itemChangedSpy.count(), 0);
+ QCOMPARE(dataChangedSpy.count(), 0);
}
void tst_QListWidget::itemAssignment()
@@ -736,7 +859,7 @@ void tst_QListWidget::selectedItems()
testWidget->setSelectionMode(QListWidget::SingleSelection);
for (int i=0; i<itemCount; ++i) {
QListWidgetItem *item = testWidget->item(i);
- testWidget->setItemSelected(item, true);
+ item->setSelected(true);
QVERIFY(item->isSelected());
QCOMPARE(testWidget->selectedItems().count(), 1);
}
@@ -749,10 +872,10 @@ void tst_QListWidget::selectedItems()
QCOMPARE(testWidget->count(), itemCount);
// hide items
foreach (int row, hiddenRows)
- testWidget->setItemHidden(testWidget->item(row), true);
+ testWidget->item(row)->setHidden(true);
// select items
foreach (int row, selectedRows)
- testWidget->setItemSelected(testWidget->item(row), true);
+ testWidget->item(row)->setSelected(true);
// check that the correct number of items and the expected items are there
QList<QListWidgetItem *> selectedItems = testWidget->selectedItems();
@@ -763,7 +886,7 @@ void tst_QListWidget::selectedItems()
//check that isSelected agrees with selectedItems
for (int i=0; i<itemCount; ++i) {
QListWidgetItem *item = testWidget->item(i);
- if (testWidget->isItemSelected(item))
+ if (item->isSelected())
QVERIFY(selectedItems.contains(item));
}
}
@@ -1141,7 +1264,6 @@ void tst_QListWidget::setData()
QFETCH(IntList, roles);
QFETCH(QVariantList, values);
QFETCH(int, expectedSignalCount);
- qRegisterMetaType<QListWidgetItem *>("QListWidgetItem*");
QCOMPARE(roles.count(), values.count());
@@ -1403,11 +1525,11 @@ void tst_QListWidget::itemData()
item.setData(Qt::DisplayRole, QString("0"));
QCOMPARE(widget.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
item.setData(Qt::CheckStateRole, Qt::PartiallyChecked);
- QCOMPARE(widget.currentRoles, {Qt::CheckStateRole});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::CheckStateRole});
for (int i = 0; i < 4; ++i)
{
item.setData(Qt::UserRole + i, QString::number(i + 1));
- QCOMPARE(widget.currentRoles, {Qt::UserRole + i});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::UserRole + i});
}
QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
QCOMPARE(flags.count(), 6);
@@ -1599,7 +1721,6 @@ void tst_QListWidget::task258949_keypressHangup()
void tst_QListWidget::QTBUG8086_currentItemChangedOnClick()
{
- qRegisterMetaType<QListWidgetItem*>("QListWidgetItem*");
QWidget win;
QHBoxLayout layout(&win);
QListWidget list;
@@ -1721,7 +1842,6 @@ void tst_QListWidget::mimeData()
void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet()
{
- qRegisterMetaType<QListWidgetItem*>("QListWidgetItem*");
QListWidget list;
for (int i = 0 ; i < 4; ++i)
new QListWidgetItem(QString::number(i), &list);
@@ -1743,5 +1863,27 @@ void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet()
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+void tst_QListWidget::clearItemData()
+{
+ QListWidget list;
+ for (int i = 0 ; i < 4; ++i)
+ new QListWidgetItem(QString::number(i), &list);
+ QSignalSpy dataChangeSpy(list.model(), &QAbstractItemModel::dataChanged);
+ QVERIFY(dataChangeSpy.isValid());
+ QVERIFY(!list.model()->clearItemData(QModelIndex()));
+ QCOMPARE(dataChangeSpy.size(), 0);
+ QVERIFY(list.model()->clearItemData(list.model()->index(0, 0)));
+ QVERIFY(!list.model()->index(0, 0).data().isValid());
+ QCOMPARE(dataChangeSpy.size(), 1);
+ const QList<QVariant> dataChangeArgs = dataChangeSpy.takeFirst();
+ QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), list.model()->index(0, 0));
+ QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), list.model()->index(0, 0));
+ QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty());
+ QVERIFY(list.model()->clearItemData(list.model()->index(0, 0)));
+ QCOMPARE(dataChangeSpy.size(), 0);
+}
+#endif
+
QTEST_MAIN(tst_QListWidget)
#include "tst_qlistwidget.moc"
diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
index 1b95b5a3ca..bf87408056 100644
--- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -32,6 +32,9 @@
#include <private/qtablewidget_p.h>
#include <QtTest/QtTest>
#include "private/qapplication_p.h"
+#if QT_CONFIG(textmarkdownwriter)
+#include "private/qtextmarkdownwriter_p.h"
+#endif
#include <algorithm>
@@ -196,6 +199,10 @@ private slots:
void viewOptions();
void taskQTBUG_7232_AllowUserToControlSingleStep();
+
+#if QT_CONFIG(textmarkdownwriter)
+ void markdownWriter();
+#endif
};
// Testing get/set functions
@@ -2534,7 +2541,6 @@ void tst_QTableView::columnViewportPosition()
view.horizontalScrollBar()->setValue(horizontalScrollValue);
#ifdef Q_OS_WINRT
- QEXPECT_FAIL("column 1, scroll per item, 1", "Fails on WinRT - QTBUG-68297", Abort);
QEXPECT_FAIL("column 5, scroll per item, 5", "Fails on WinRT - QTBUG-68297", Abort);
QEXPECT_FAIL("column 9, scroll per item, 5", "Fails on WinRT - QTBUG-68297", Abort);
QEXPECT_FAIL("column 1, scroll per pixel 1", "Fails on WinRT - QTBUG-68297", Abort);
@@ -4254,7 +4260,7 @@ void tst_QTableView::task234926_setHeaderSorting()
QStringList sortedDataA = data;
QStringList sortedDataD = data;
std::sort(sortedDataA.begin(), sortedDataA.end());
- std::sort(sortedDataD.begin(), sortedDataD.end(), qGreater<QString>());
+ std::sort(sortedDataD.begin(), sortedDataD.end(), std::greater<QString>());
model.setStringList(data);
QTableView view;
view.setModel(&model);
@@ -4561,5 +4567,33 @@ void tst_QTableView::taskQTBUG_50171_selectRowAfterSwapColumns()
}
}
+// This has nothing to do with QTableView, but it's convenient to reuse the QtTestTableModel
+#if QT_CONFIG(textmarkdownwriter)
+
+// #define DEBUG_WRITE_OUTPUT
+
+void tst_QTableView::markdownWriter()
+{
+ QtTestTableModel model(2, 3);
+ QString md;
+ {
+ QTextStream stream(&md);
+ QTextMarkdownWriter writer(stream, QTextDocument::MarkdownDialectGitHub);
+ writer.writeTable(&model);
+ }
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/table.md");
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+ }
+#endif
+
+ QCOMPARE(md, QString::fromLatin1("|1 |2 |3 |\n|-------|-------|-------|\n|[0,0,0]|[0,1,0]|[0,2,0]|\n|[1,0,0]|[1,1,0]|[1,2,0]|\n"));
+}
+#endif
+
QTEST_MAIN(tst_QTableView)
#include "tst_qtableview.moc"
diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
index 4155ff1ec6..6184962d93 100644
--- a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
@@ -83,12 +83,18 @@ private slots:
void setItemData();
void cellWidget();
void cellWidgetGeometry();
+ void sizeHint_data();
+ void sizeHint();
void task231094();
void task219380_removeLastRow();
void task262056_sortDuplicate();
void itemWithHeaderItems();
void mimeData();
void selectedRowAfterSorting();
+ void search();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ void clearItemData();
+#endif
private:
QTableWidget *testWidget;
@@ -159,6 +165,7 @@ void tst_QTableWidget::initTestCase()
{
testWidget = new QTableWidget();
testWidget->show();
+ QApplication::setKeyboardInputInterval(100);
}
void tst_QTableWidget::cleanupTestCase()
@@ -191,10 +198,10 @@ void tst_QTableWidget::clear()
{
QTableWidgetItem *item = new QTableWidgetItem("foo");
testWidget->setItem(0, 0, item);
- testWidget->setItemSelected(item, true);
+ item->setSelected(true);
QVERIFY(testWidget->item(0, 0) == item);
- QVERIFY(testWidget->isItemSelected(item));
+ QVERIFY(item->isSelected());
QPointer<QObjectTableItem> bla = new QObjectTableItem();
@@ -578,7 +585,7 @@ void tst_QTableWidget::selectedItems()
continue;
QTableWidgetItem *item = testWidget->item(row, column);
- if (item && testWidget->isItemSelected(item))
+ if (item && item->isSelected())
QVERIFY(selectedItems.contains(item));
}
}
@@ -1376,11 +1383,11 @@ void tst_QTableWidget::itemData()
item->setData(Qt::DisplayRole, QString("0"));
QCOMPARE(widget.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
item->setData(Qt::CheckStateRole, Qt::PartiallyChecked);
- QCOMPARE(widget.currentRoles, {Qt::CheckStateRole});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::CheckStateRole});
for (int i = 0; i < 4; ++i)
{
item->setData(Qt::UserRole + i, QString::number(i + 1));
- QCOMPARE(widget.currentRoles, {Qt::UserRole + i});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::UserRole + i});
}
QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
QCOMPARE(flags.count(), 6);
@@ -1454,6 +1461,56 @@ void tst_QTableWidget::cellWidgetGeometry()
QCOMPARE(tw.visualItemRect(item).top(), le->geometry().top());
}
+void tst_QTableWidget::sizeHint_data()
+{
+ QTest::addColumn<int>("scrollBarPolicy");
+ QTest::addColumn<QSize>("viewSize");
+ QTest::newRow("ScrollBarAlwaysOn") << static_cast<int>(Qt::ScrollBarAlwaysOn) << QSize();
+ QTest::newRow("ScrollBarAlwaysOff") << static_cast<int>(Qt::ScrollBarAlwaysOff) << QSize();
+ // make sure the scrollbars are shown by resizing the view to 40x40
+ QTest::newRow("ScrollBarAsNeeded (40x40)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(40, 40);
+ QTest::newRow("ScrollBarAsNeeded (1000x1000)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(1000, 1000);
+}
+
+void tst_QTableWidget::sizeHint()
+{
+ QFETCH(int, scrollBarPolicy);
+ QFETCH(QSize, viewSize);
+
+ QTableWidget view(2, 2);
+ view.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
+ view.setVerticalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy));
+ view.setHorizontalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy));
+ for (int r = 0 ; r < view.rowCount(); ++r)
+ for (int c = 0 ; c < view.columnCount(); ++c)
+ view.setItem(r, c, new QTableWidgetItem(QString("%1/%2").arg(r).arg(c)));
+
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ if (viewSize.isValid()) {
+ view.resize(viewSize);
+ view.setColumnWidth(0, 100);
+ view.setRowHeight(0, 100);
+ QTRY_COMPARE(view.size(), viewSize);
+ }
+
+ auto sizeHint = view.sizeHint();
+ view.hide();
+ QCOMPARE(view.sizeHint(), sizeHint);
+
+ view.horizontalHeader()->hide();
+ view.show();
+ sizeHint = view.sizeHint();
+ view.hide();
+ QCOMPARE(view.sizeHint(), sizeHint);
+
+ view.verticalHeader()->hide();
+ view.show();
+ sizeHint = view.sizeHint();
+ view.hide();
+ QCOMPARE(view.sizeHint(), sizeHint);
+}
+
void tst_QTableWidget::task231094()
{
QTableWidget tw(5, 3);
@@ -1510,7 +1567,7 @@ void tst_QTableWidget::task262056_sortDuplicate()
}
testWidget->sortItems(0, Qt::AscendingOrder);
QSignalSpy layoutChangedSpy(testWidget->model(), SIGNAL(layoutChanged()));
- testWidget->item(3,0)->setBackgroundColor(Qt::red);
+ testWidget->item(3,0)->setBackground(Qt::red);
QCOMPARE(layoutChangedSpy.count(),0);
@@ -1543,6 +1600,7 @@ public:
using QTableWidget::mimeData;
using QTableWidget::indexFromItem;
+ using QTableWidget::keyPressEvent;
};
void tst_QTableWidget::mimeData()
@@ -1617,5 +1675,67 @@ void tst_QTableWidget::selectedRowAfterSorting()
}
}
+void tst_QTableWidget::search()
+{
+ auto createItem = [](const QString &txt)
+ {
+ auto item = new QTableWidgetItem(txt);
+ item->setFlags(item->flags().setFlag(Qt::ItemIsEditable, false));
+ return item;
+ };
+
+ auto checkSeries = [](TestTableWidget &tw, const QVector<QPair<QKeyEvent, int>> &series)
+ {
+ for (const auto &p : series) {
+ QKeyEvent e = p.first;
+ tw.keyPressEvent(&e);
+ QVERIFY(tw.selectionModel()->isSelected(tw.model()->index(p.second, 0)));
+ }
+ };
+ TestTableWidget tw(5, 1);
+ tw.setItem(0, 0, createItem("12"));
+ tw.setItem(1, 0, createItem("123"));
+ tw.setItem(2, 0, createItem("123 4"));
+ tw.setItem(3, 0, createItem("123 5"));
+ tw.setItem(4, 0, createItem(" "));
+ tw.show();
+
+ QKeyEvent evSpace(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier, " ");
+ QKeyEvent ev1(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier, "1");
+ QKeyEvent ev2(QEvent::KeyPress, Qt::Key_2, Qt::NoModifier, "2");
+ QKeyEvent ev3(QEvent::KeyPress, Qt::Key_3, Qt::NoModifier, "3");
+ QKeyEvent ev4(QEvent::KeyPress, Qt::Key_4, Qt::NoModifier, "4");
+ QKeyEvent ev5(QEvent::KeyPress, Qt::Key_5, Qt::NoModifier, "5");
+
+ checkSeries(tw, {{evSpace, 4}, {ev1, 4}});
+ QTest::qWait(QApplication::keyboardInputInterval() * 2);
+ checkSeries(tw, {{ev1, 0}, {ev2, 0}, {ev3, 1}, {evSpace, 2}, {ev5, 3}});
+ QTest::qWait(QApplication::keyboardInputInterval() * 2);
+ checkSeries(tw, {{ev1, 0}, {ev2, 0}, {ev3, 1}, {evSpace, 2}, {ev4, 2}});
+}
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+void tst_QTableWidget::clearItemData()
+{
+ QTableWidget table(3,3);
+ for (int r = 0; r < 3; r++)
+ for (int c = 0; c < 3; c++)
+ table.setItem(r,c,new QTableWidgetItem(QStringLiteral("0")));
+ QSignalSpy dataChangeSpy(table.model(), &QAbstractItemModel::dataChanged);
+ QVERIFY(dataChangeSpy.isValid());
+ QVERIFY(!table.model()->clearItemData(QModelIndex()));
+ QCOMPARE(dataChangeSpy.size(), 0);
+ QVERIFY(table.model()->clearItemData(table.model()->index(0, 0)));
+ QVERIFY(!table.model()->index(0, 0).data().isValid());
+ QCOMPARE(dataChangeSpy.size(), 1);
+ const QList<QVariant> dataChangeArgs = dataChangeSpy.takeFirst();
+ QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), table.model()->index(0, 0));
+ QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), table.model()->index(0, 0));
+ QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty());
+ QVERIFY(table.model()->clearItemData(table.model()->index(0, 0)));
+ QCOMPARE(dataChangeSpy.size(), 0);
+}
+#endif
+
QTEST_MAIN(tst_QTableWidget)
#include "tst_qtablewidget.moc"
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index a9858ae420..c31de2ba22 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -69,6 +69,7 @@ public slots:
void selectionOrderTest();
private slots:
+ void initTestCase() { QApplication::setKeyboardInputInterval(100); }
void getSetCheck();
// one test per QTreeView property
@@ -1648,50 +1649,96 @@ void tst_QTreeView::expandAndCollapse()
}
}
+static void checkExpandState(const QAbstractItemModel &model, const QTreeView &view,
+ const QModelIndex &startIdx, bool bIsExpanded, int *count)
+{
+ *count = 0;
+ QStack<QModelIndex> parents;
+ parents.push(startIdx);
+ if (startIdx.isValid()) {
+ QCOMPARE(view.isExpanded(startIdx), bIsExpanded);
+ *count += 1;
+ }
+ while (!parents.isEmpty()) {
+ const QModelIndex p = parents.pop();
+ const int rows = model.rowCount(p);
+ for (int r = 0; r < rows; ++r) {
+ const QModelIndex c = model.index(r, 0, p);
+ QCOMPARE(view.isExpanded(c), bIsExpanded);
+ parents.push(c);
+ }
+ *count += rows;
+ }
+}
+
void tst_QTreeView::expandAndCollapseAll()
{
- QtTestModel model(3, 2);
- model.levels = 2;
+ QStandardItemModel model;
+ // QtTestModel has a broken parent/child handling which will break the test
+ for (int i1 = 0; i1 < 3; ++i1) {
+ QStandardItem *s1 = new QStandardItem;
+ s1->setText(QString::number(i1));
+ model.appendRow(s1);
+ for (int i2 = 0; i2 < 3; ++i2) {
+ QStandardItem *s2 = new QStandardItem;
+ s2->setText(QStringLiteral("%1 - %2").arg(i1).arg(i2));
+ s1->appendRow(s2);
+ for (int i3 = 0; i3 < 3; ++i3) {
+ QStandardItem *s3 = new QStandardItem;
+ s3->setText(QStringLiteral("%1 - %2 - %3").arg(i1).arg(i2).arg(i3));
+ s2->appendRow(s3);
+ }
+ }
+ }
QTreeView view;
view.setUniformRowHeights(true);
view.setModel(&model);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
- QSignalSpy expandedSpy(&view, SIGNAL(expanded(QModelIndex)));
- QSignalSpy collapsedSpy(&view, SIGNAL(collapsed(QModelIndex)));
+ QSignalSpy expandedSpy(&view, &QTreeView::expanded);
+ QSignalSpy collapsedSpy(&view, &QTreeView::collapsed);
+ int count;
view.expandAll();
- view.show();
-
+ checkExpandState(model, view, QModelIndex(), true, &count);
QCOMPARE(collapsedSpy.count(), 0);
+ QCOMPARE(expandedSpy.count(), 39); // == 3 (first) + 9 (second) + 27 (third level)
+ QCOMPARE(count, 39);
- QStack<QModelIndex> parents;
- parents.push(QModelIndex());
- int count = 0;
- while (!parents.isEmpty()) {
- QModelIndex p = parents.pop();
- int rows = model.rowCount(p);
- for (int r = 0; r < rows; ++r)
- QVERIFY(view.isExpanded(model.index(r, 0, p)));
- count += rows;
- for (int r = 0; r < rows; ++r)
- parents.push(model.index(r, 0, p));
- }
- QCOMPARE(expandedSpy.count(), 12); // == (3+1)*(2+1) from QtTestModel model(3, 2);
-
+ collapsedSpy.clear();
+ expandedSpy.clear();
view.collapseAll();
-
- parents.push(QModelIndex());
- count = 0;
- while (!parents.isEmpty()) {
- QModelIndex p = parents.pop();
- int rows = model.rowCount(p);
- for (int r = 0; r < rows; ++r)
- QVERIFY(!view.isExpanded(model.index(r, 0, p)));
- count += rows;
- for (int r = 0; r < rows; ++r)
- parents.push(model.index(r, 0, p));
- }
- QCOMPARE(collapsedSpy.count(), 12);
+ checkExpandState(model, view, QModelIndex(), false, &count);
+ QCOMPARE(collapsedSpy.count(), 39);
+ QCOMPARE(expandedSpy.count(), 0);
+ QCOMPARE(count, 39);
+
+ collapsedSpy.clear();
+ expandedSpy.clear();
+ view.expandRecursively(model.index(0, 0));
+ QCOMPARE(expandedSpy.count(), 13); // 1 + 3 + 9
+
+ checkExpandState(model, view, model.index(0, 0), true, &count);
+ QCOMPARE(count, 13);
+ checkExpandState(model, view, model.index(1, 0), false, &count);
+ QCOMPARE(count, 13);
+ checkExpandState(model, view, model.index(2, 0), false, &count);
+ QCOMPARE(count, 13);
+
+ expandedSpy.clear();
+ view.collapseAll();
+ view.expandRecursively(model.index(0, 0), 1);
+ QCOMPARE(expandedSpy.count(), 4); // 1 + 3
+ view.expandRecursively(model.index(0, 0), 2);
+ QCOMPARE(expandedSpy.count(), 13); // (1 + 3) + 9
+
+ checkExpandState(model, view, model.index(0, 0), true, &count);
+ QCOMPARE(count, 13);
+ checkExpandState(model, view, model.index(1, 0), false, &count);
+ QCOMPARE(count, 13);
+ checkExpandState(model, view, model.index(2, 0), false, &count);
+ QCOMPARE(count, 13);
}
void tst_QTreeView::expandWithNoChildren()
@@ -1750,7 +1797,7 @@ void tst_QTreeView::keyboardNavigation()
case Qt::Key_Down:
if (view.isExpanded(index)) {
row = 0;
- index = index.child(row, column);
+ index = model.index(row, column, index);
} else {
row = qMin(rows - 1, row + 1);
index = index.sibling(row, column);
@@ -2436,6 +2483,8 @@ void tst_QTreeView::selection()
for (int i = 0;i < 10; ++i)
m.setData(m.index(i, 0), i);
treeView.setModel(&m);
+ treeView.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&treeView));
treeView.setSelectionBehavior(QAbstractItemView::SelectRows);
treeView.setSelectionMode(QAbstractItemView::ExtendedSelection);
@@ -2447,6 +2496,13 @@ void tst_QTreeView::selection()
QTest::mousePress(treeView.viewport(), Qt::LeftButton, 0, treeView.visualRect(m.index(1, 0)).center());
QTest::keyPress(treeView.viewport(), Qt::Key_Down);
+ auto selectedRows = treeView.selectionModel()->selectedRows();
+ QCOMPARE(selectedRows.size(), 1);
+ QCOMPARE(selectedRows.first(), m.index(2, 0, QModelIndex()));
+ QTest::keyPress(treeView.viewport(), Qt::Key_5);
+ selectedRows = treeView.selectionModel()->selectedRows();
+ QCOMPARE(selectedRows.size(), 1);
+ QCOMPARE(selectedRows.first(), m.index(5, 0, QModelIndex()));
}
//From task 151686 QTreeView ExtendedSelection selects hidden rows
@@ -2738,7 +2794,7 @@ void tst_QTreeView::sortByColumn()
view.setSortingEnabled(sortingEnabled);
view.setModel(&model);
- view.sortByColumn(1);
+ view.sortByColumn(1, Qt::DescendingOrder);
QCOMPARE(view.header()->sortIndicatorSection(), 1);
QCOMPARE(view.model()->data(view.model()->index(0,1)).toString(), QString::fromLatin1("h"));
QCOMPARE(view.model()->data(view.model()->index(1,1)).toString(), QString::fromLatin1("g"));
@@ -3048,7 +3104,7 @@ void tst_QTreeView::evilModel()
view.resizeColumnToContents(1);
model.change();
- view.sortByColumn(1);
+ view.sortByColumn(1, Qt::DescendingOrder);
model.change();
view.selectAll();
@@ -3892,7 +3948,7 @@ void tst_QTreeView::task254234_proxySort()
model.setItem(2,1,new QStandardItem("h"));
model.setItem(3,1,new QStandardItem("f"));
- view.sortByColumn(1);
+ view.sortByColumn(1, Qt::DescendingOrder);
view.setSortingEnabled(true);
QSortFilterProxyModel proxy;
@@ -4080,6 +4136,30 @@ void tst_QTreeView::keyboardNavigationWithDisabled()
QCOMPARE(view.currentIndex(), model.index(12, 0));
QTest::keyClick(view.viewport(), Qt::Key_Up);
QCOMPARE(view.currentIndex(), model.index(6, 0));
+ // QTBUG-44746 - when first/last item is disabled,
+ // Key_PageUp/Down/Home/End will not work as expected.
+ model.item(0)->setEnabled(false);
+ model.item(1)->setEnabled(true);
+ model.item(2)->setEnabled(true);
+ model.item(model.rowCount() - 1)->setEnabled(false);
+ model.item(model.rowCount() - 2)->setEnabled(true);
+ model.item(model.rowCount() - 3)->setEnabled(true);
+ // PageUp
+ view.setCurrentIndex(model.index(2, 0));
+ QCOMPARE(view.currentIndex(), model.index(2, 0));
+ QTest::keyClick(view.viewport(), Qt::Key_PageUp);
+ QCOMPARE(view.currentIndex(), model.index(1, 0));
+ // PageDown
+ view.setCurrentIndex(model.index(model.rowCount() - 3, 0));
+ QCOMPARE(view.currentIndex(), model.index(model.rowCount() - 3, 0));
+ QTest::keyClick(view.viewport(), Qt::Key_PageDown);
+ QCOMPARE(view.currentIndex(), model.index(model.rowCount() - 2, 0));
+ // Key_Home
+ QTest::keyClick(view.viewport(), Qt::Key_Home);
+ QCOMPARE(view.currentIndex(), model.index(1, 0));
+ // Key_End
+ QTest::keyClick(view.viewport(), Qt::Key_End);
+ QCOMPARE(view.currentIndex(), model.index(model.rowCount() - 2, 0));
}
class RemoveColumnOne : public QSortFilterProxyModel
diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
index adb2c54751..0d97974b90 100644
--- a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
@@ -99,6 +99,7 @@ private slots:
void insertTopLevelItems_data();
void insertTopLevelItems();
void keyboardNavigation();
+ void keyboardNavigationWithHidden();
void scrollToItem();
void setSortingEnabled();
void match();
@@ -115,6 +116,8 @@ private slots:
void changeDataWithSorting();
void changeDataWithStableSorting_data();
void changeDataWithStableSorting();
+ void sizeHint_data();
+ void sizeHint();
void sortedIndexOfChild_data();
void sortedIndexOfChild();
@@ -138,6 +141,7 @@ private slots:
void expandAndCallapse();
void itemData();
void setDisabled();
+ void setSpanned();
void removeSelectedItem();
void removeCurrentItem();
void removeCurrentItem_task186451();
@@ -161,6 +165,9 @@ private slots:
void getMimeDataWithInvalidItem();
void testVisualItemRect();
void reparentHiddenItem();
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ void clearItemData();
+#endif
public slots:
void itemSelectionChanged();
@@ -603,31 +610,31 @@ void tst_QTreeWidget::setItemHidden()
QVERIFY(testWidget->visualItemRect(child).isValid()
&& testWidget->viewport()->rect().intersects(testWidget->visualItemRect(child)));
- QVERIFY(!testWidget->isItemHidden(parent));
- QVERIFY(!testWidget->isItemHidden(child));
+ QVERIFY(!parent->isHidden());
+ QVERIFY(!child->isHidden());
- testWidget->setItemHidden(parent, true);
+ parent->setHidden(true);
QVERIFY(!(testWidget->visualItemRect(parent).isValid()
&& testWidget->viewport()->rect().intersects(testWidget->visualItemRect(parent))));
QVERIFY(!(testWidget->visualItemRect(child).isValid()
&& testWidget->viewport()->rect().intersects(testWidget->visualItemRect(child))));
- QVERIFY(testWidget->isItemHidden(parent));
- QVERIFY(!testWidget->isItemHidden(child));
+ QVERIFY(parent->isHidden());
+ QVERIFY(!child->isHidden());
// From task 78670 (This caused an core dump)
// Check if we can set an item visible if it already is visible.
- testWidget->setItemHidden(parent, false);
- testWidget->setItemHidden(parent, false);
- QVERIFY(!testWidget->isItemHidden(parent));
+ parent->setHidden(false);
+ parent->setHidden(false);
+ QVERIFY(!parent->isHidden());
// hide, hide and then unhide.
- testWidget->setItemHidden(parent, true);
- testWidget->setItemHidden(parent, true);
- testWidget->setItemHidden(parent, false);
- QVERIFY(!testWidget->isItemHidden(parent));
+ parent->setHidden(true);
+ parent->setHidden(true);
+ parent->setHidden(false);
+ QVERIFY(!parent->isHidden());
}
@@ -653,7 +660,7 @@ void tst_QTreeWidget::setItemHidden2()
if (testWidget->topLevelItemCount() > 0) {
top = testWidget->topLevelItem(0);
- testWidget->setItemExpanded(top, true);
+ top->setExpanded(true);
}
if (testWidget->topLevelItemCount() > 0) {
@@ -661,8 +668,8 @@ void tst_QTreeWidget::setItemHidden2()
for (int i = 0; i < top->childCount(); i++) {
leaf = top->child(i);
if (leaf->text(0).toInt() % 2 == 0) {
- if (!testWidget->isItemHidden(leaf)) {
- testWidget->setItemHidden(leaf, true);
+ if (!leaf->isHidden()) {
+ leaf->setHidden(true);
}
}
}
@@ -816,7 +823,7 @@ void tst_QTreeWidget::selectedItems()
else
item = item->child(index);
}
- testWidget->setItemSelected(item, true);
+ item->setSelected(true);
}
// hide rows
@@ -828,7 +835,7 @@ void tst_QTreeWidget::selectedItems()
else
item = item->child(index);
}
- testWidget->setItemHidden(item, true);
+ item->setHidden(true);
}
// open/close toplevel
@@ -857,18 +864,23 @@ void tst_QTreeWidget::selectedItems()
// compare isSelected
for (int t=0; t<testWidget->topLevelItemCount(); ++t) {
QTreeWidgetItem *top = testWidget->topLevelItem(t);
- if (testWidget->isItemSelected(top) && !testWidget->isItemHidden(top))
+ if (top->isSelected() && !top->isHidden())
QVERIFY(sel.contains(top));
for (int c=0; c<top->childCount(); ++c) {
QTreeWidgetItem *child = top->child(c);
- if (testWidget->isItemSelected(child) && !testWidget->isItemHidden(child))
+ if (child->isSelected() && !child->isHidden())
QVERIFY(sel.contains(child));
}
}
+#if QT_DEPRECATED_SINCE(5, 13)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
// Possible to select null without crashing?
- testWidget->setItemSelected(0, true);
- QVERIFY(!testWidget->isItemSelected(0));
+ testWidget->setItemSelected(nullptr, true);
+ QVERIFY(!testWidget->isItemSelected(nullptr));
+QT_WARNING_POP
+#endif
// unselect
foreach (IntList itemPath, selectedItems) {
@@ -879,7 +891,7 @@ void tst_QTreeWidget::selectedItems()
else
item = item->child(index);
}
- testWidget->setItemSelected(item, false);
+ item->setSelected(false);
}
QCOMPARE(testWidget->selectedItems().count(), 0);
}
@@ -1005,21 +1017,21 @@ void tst_QTreeWidget::expand()
QTreeWidgetItem *topLevelItem = testWidget->topLevelItem(topLevelIndex);
QTreeWidgetItem *childItem = topLevelItem->child(childIndex);
- QVERIFY(!testWidget->isItemExpanded(topLevelItem));
- testWidget->setItemExpanded(topLevelItem, true);
- QVERIFY(testWidget->isItemExpanded(topLevelItem));
+ QVERIFY(!topLevelItem->isExpanded());
+ topLevelItem->setExpanded(true);
+ QVERIFY(topLevelItem->isExpanded());
- QVERIFY(!testWidget->isItemExpanded(childItem));
- testWidget->setItemExpanded(childItem, true);
- QVERIFY(testWidget->isItemExpanded(childItem));
+ QVERIFY(!childItem->isExpanded());
+ childItem->setExpanded(true);
+ QVERIFY(childItem->isExpanded());
- QVERIFY(testWidget->isItemExpanded(topLevelItem));
- testWidget->setItemExpanded(topLevelItem, false);
- QVERIFY(!testWidget->isItemExpanded(topLevelItem));
+ QVERIFY(topLevelItem->isExpanded());
+ topLevelItem->setExpanded(false);
+ QVERIFY(!topLevelItem->isExpanded());
- QVERIFY(testWidget->isItemExpanded(childItem));
- testWidget->setItemExpanded(childItem, false);
- QVERIFY(!testWidget->isItemExpanded(childItem));
+ QVERIFY(childItem->isExpanded());
+ childItem->setExpanded(false);
+ QVERIFY(!childItem->isExpanded());
}
void tst_QTreeWidget::checkState_data()
@@ -1520,7 +1532,7 @@ void tst_QTreeWidget::keyboardNavigation()
}
break;
case Qt::Key_Down:
- if (testWidget->isItemExpanded(item)) {
+ if (item->isExpanded()) {
row = 0;
item = item->child(row);
} else {
@@ -1533,7 +1545,7 @@ void tst_QTreeWidget::keyboardNavigation()
break;
case Qt::Key_Left:
if (checkScroll) {
- QVERIFY(testWidget->isItemExpanded(item));
+ QVERIFY(item->isExpanded());
QCOMPARE(scrollBar->value(), valueBeforeClick - scrollBar->singleStep());
}
// windows style right will walk to the parent
@@ -1567,6 +1579,33 @@ void tst_QTreeWidget::keyboardNavigation()
}
}
+void tst_QTreeWidget::keyboardNavigationWithHidden()
+{
+ QTreeWidget tw;
+ for (int i = 0; i < 1000; ++i)
+ tw.addTopLevelItem(new QTreeWidgetItem({QString::number(i), QStringLiteral("second col")}));
+ // QTBUG-34832 - when first/last item is hidden,
+ // Key_PageUp/Down/Home/End will not work as expected.
+ tw.topLevelItem(0)->setHidden(true);
+ tw.topLevelItem(tw.model()->rowCount() - 1)->setHidden(true);
+ // PageUp
+ tw.setCurrentIndex(tw.model()->index(2, 0));
+ QCOMPARE(tw.currentIndex(), tw.model()->index(2, 0));
+ QTest::keyClick(tw.viewport(), Qt::Key_PageUp);
+ QCOMPARE(tw.currentIndex(), tw.model()->index(1, 0));
+ // PageDown
+ tw.setCurrentIndex(tw.model()->index(tw.model()->rowCount() - 3, 0));
+ QCOMPARE(tw.currentIndex(), tw.model()->index(tw.model()->rowCount() - 3, 0));
+ QTest::keyClick(tw.viewport(), Qt::Key_PageDown);
+ QCOMPARE(tw.currentIndex(), tw.model()->index(tw.model()->rowCount() - 2, 0));
+ // Key_Home
+ QTest::keyClick(tw.viewport(), Qt::Key_Home);
+ QCOMPARE(tw.currentIndex(), tw.model()->index(1, 0));
+ // Key_End
+ QTest::keyClick(tw.viewport(), Qt::Key_End);
+ QCOMPARE(tw.currentIndex(), tw.model()->index(tw.model()->rowCount() - 2, 0));
+}
+
void tst_QTreeWidget::scrollToItem()
{
// Check if all parent nodes of the item found are expanded.
@@ -1592,9 +1631,9 @@ void tst_QTreeWidget::scrollToItem()
QCOMPARE(search->text(0), QLatin1String("111"));
QTreeWidgetItem *par = search->parent();
- QVERIFY(testWidget->isItemExpanded(par));
+ QVERIFY(par->isExpanded());
par = par->parent();
- QVERIFY(testWidget->isItemExpanded(par));
+ QVERIFY(par->isExpanded());
}
// From task #85413
@@ -1840,14 +1879,14 @@ void tst_QTreeWidget::setData()
item->setBackground(j, backgroundColor);
QCOMPARE(itemChangedSpy.count(), 0);
- QColor textColor((i == 1) ? Qt::green : Qt::cyan);
- item->setTextColor(j, textColor);
- QCOMPARE(item->textColor(j), textColor);
+ const QColor foregroundColor((i == 1) ? Qt::green : Qt::cyan);
+ item->setForeground(j, foregroundColor);
+ QCOMPARE(item->foreground(j), foregroundColor);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
- item->setTextColor(j, textColor);
+ item->setForeground(j, foregroundColor);
QCOMPARE(itemChangedSpy.count(), 0);
Qt::CheckState checkState((i == 1) ? Qt::PartiallyChecked : Qt::Checked);
@@ -1869,7 +1908,7 @@ void tst_QTreeWidget::setData()
QCOMPARE(item->font(j), font);
QCOMPARE(item->textAlignment(j), int(textAlignment));
QCOMPARE(item->background(j).color(), backgroundColor);
- QCOMPARE(item->textColor(j), textColor);
+ QCOMPARE(item->foreground(j), foregroundColor);
QCOMPARE(item->checkState(j), checkState);
QCOMPARE(qvariant_cast<QString>(item->data(j, Qt::DisplayRole)), text);
@@ -1880,9 +1919,8 @@ void tst_QTreeWidget::setData()
QCOMPARE(qvariant_cast<QSize>(item->data(j, Qt::SizeHintRole)), sizeHint);
QCOMPARE(qvariant_cast<QFont>(item->data(j, Qt::FontRole)), font);
QCOMPARE(qvariant_cast<int>(item->data(j, Qt::TextAlignmentRole)), int(textAlignment));
- QCOMPARE(qvariant_cast<QBrush>(item->data(j, Qt::BackgroundColorRole)), QBrush(backgroundColor));
QCOMPARE(qvariant_cast<QBrush>(item->data(j, Qt::BackgroundRole)), QBrush(backgroundColor));
- QCOMPARE(qvariant_cast<QColor>(item->data(j, Qt::TextColorRole)), textColor);
+ QCOMPARE(qvariant_cast<QColor>(item->data(j, Qt::ForegroundRole)), foregroundColor);
QCOMPARE(qvariant_cast<int>(item->data(j, Qt::CheckStateRole)), int(checkState));
item->setBackground(j, pixmap);
@@ -1902,8 +1940,8 @@ void tst_QTreeWidget::setData()
item->setData(j, Qt::SizeHintRole, QVariant());
item->setData(j, Qt::FontRole, QVariant());
item->setData(j, Qt::TextAlignmentRole, QVariant());
- item->setData(j, Qt::BackgroundColorRole, QVariant());
- item->setData(j, Qt::TextColorRole, QVariant());
+ item->setData(j, Qt::BackgroundRole, QVariant());
+ item->setData(j, Qt::ForegroundRole, QVariant());
item->setData(j, Qt::CheckStateRole, QVariant());
QCOMPARE(itemChangedSpy.count(), 11);
itemChangedSpy.clear();
@@ -1916,9 +1954,8 @@ void tst_QTreeWidget::setData()
QCOMPARE(item->data(j, Qt::SizeHintRole), QVariant());
QCOMPARE(item->data(j, Qt::FontRole), QVariant());
QCOMPARE(item->data(j, Qt::TextAlignmentRole), QVariant());
- QCOMPARE(item->data(j, Qt::BackgroundColorRole), QVariant());
QCOMPARE(item->data(j, Qt::BackgroundRole), QVariant());
- QCOMPARE(item->data(j, Qt::TextColorRole), QVariant());
+ QCOMPARE(item->data(j, Qt::ForegroundRole), QVariant());
QCOMPARE(item->data(j, Qt::CheckStateRole), QVariant());
}
}
@@ -1962,10 +1999,10 @@ void tst_QTreeWidget::itemData()
item.setData(0, Qt::DisplayRole, QString("0"));
QCOMPARE(widget.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
item.setData(0, Qt::CheckStateRole, Qt::PartiallyChecked);
- QCOMPARE(widget.currentRoles, {Qt::CheckStateRole});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::CheckStateRole});
for (int i = 0; i < 4; ++i) {
item.setData(0, Qt::UserRole + i, QString::number(i + 1));
- QCOMPARE(widget.currentRoles, {Qt::UserRole + i});
+ QCOMPARE(widget.currentRoles, QVector<int>{Qt::UserRole + i});
}
QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
QCOMPARE(flags.count(), 6);
@@ -2618,6 +2655,50 @@ void tst_QTreeWidget::changeDataWithStableSorting()
QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0);
}
+void tst_QTreeWidget::sizeHint_data()
+{
+ QTest::addColumn<int>("scrollBarPolicy");
+ QTest::addColumn<QSize>("viewSize");
+ QTest::newRow("ScrollBarAlwaysOn") << static_cast<int>(Qt::ScrollBarAlwaysOn) << QSize();
+ QTest::newRow("ScrollBarAlwaysOff") << static_cast<int>(Qt::ScrollBarAlwaysOff) << QSize();
+ // make sure the scrollbars are shown by resizing the view to 40x40
+ QTest::newRow("ScrollBarAsNeeded (40x40)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(40, 40);
+ QTest::newRow("ScrollBarAsNeeded (1000x1000)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(1000, 1000);
+}
+
+void tst_QTreeWidget::sizeHint()
+{
+ QFETCH(int, scrollBarPolicy);
+ QFETCH(QSize, viewSize);
+
+ QTreeWidget view;
+ view.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
+ view.setVerticalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy));
+ view.setHorizontalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy));
+ view.setColumnCount(2);
+ for (int i = 0 ; i < view.columnCount(); ++i)
+ view.addTopLevelItem(new QTreeWidgetItem(QStringList{"foo","bar"}));
+
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ if (viewSize.isValid()) {
+ view.resize(viewSize);
+ view.setColumnWidth(0, 100);
+ QTRY_COMPARE(view.size(), viewSize);
+ }
+
+ auto sizeHint = view.sizeHint();
+ view.hide();
+ QCOMPARE(view.sizeHint(), sizeHint);
+
+ view.header()->hide();
+ view.show();
+ sizeHint = view.sizeHint();
+ view.hide();
+ QCOMPARE(view.sizeHint(), sizeHint);
+}
+
void tst_QTreeWidget::itemOperatorLessThan()
{
QTreeWidget tw;
@@ -2769,6 +2850,28 @@ void tst_QTreeWidget::setDisabled()
QCOMPARE(takenChildren.items[1]->isDisabled(), false);
}
+void tst_QTreeWidget::setSpanned()
+{
+ QTreeWidget w;
+ QTreeWidgetItem *i1 = new QTreeWidgetItem();
+ QScopedPointer<QTreeWidgetItem> i2(new QTreeWidgetItem());
+
+ QTreeWidgetItem *top = new QTreeWidgetItem(&w);
+ top->addChild(i1);
+
+ top->setFirstColumnSpanned(true);
+ QCOMPARE(top->isFirstColumnSpanned(), true);
+ QCOMPARE(i1->isFirstColumnSpanned(), false);
+ QCOMPARE(i2->isFirstColumnSpanned(), false);
+
+ top->setFirstColumnSpanned(false);
+ i1->setFirstColumnSpanned(true);
+ i2->setFirstColumnSpanned(true);
+ QCOMPARE(top->isFirstColumnSpanned(), false);
+ QCOMPARE(i1->isFirstColumnSpanned(), true);
+ QCOMPARE(i2->isFirstColumnSpanned(), false);
+}
+
void tst_QTreeWidget::removeSelectedItem()
{
const QScopedPointer <QTreeWidget> w(new QTreeWidget);
@@ -2870,14 +2973,14 @@ void tst_QTreeWidget::randomExpand()
QTreeWidgetItem *newItem1 = 0;
for (int i = 0; i < 100; i++) {
newItem1 = new QTreeWidgetItem(&tree, item1);
- tree.setItemExpanded(newItem1, true);
- QCOMPARE(tree.isItemExpanded(newItem1), true);
+ newItem1->setExpanded(true);
+ QCOMPARE(newItem1->isExpanded(), true);
QTreeWidgetItem *x = new QTreeWidgetItem();
- QCOMPARE(tree.isItemExpanded(newItem1), true);
+ QCOMPARE(newItem1->isExpanded(), true);
newItem1->addChild(x);
- QCOMPARE(tree.isItemExpanded(newItem1), true);
+ QCOMPARE(newItem1->isExpanded(), true);
}
}
@@ -2890,19 +2993,19 @@ void tst_QTreeWidget::crashTest()
QTreeWidgetItem *item1 = new QTreeWidgetItem(tree);
item1->setText(0, "item1");
- tree->setItemExpanded(item1, true);
+ item1->setExpanded(true);
QTreeWidgetItem *item2 = new QTreeWidgetItem(item1);
item2->setText(0, "item2");
QTreeWidgetItem *item3 = new QTreeWidgetItem(tree, item1);
item3->setText(0, "item3");
- tree->setItemExpanded(item3, true);
+ item3->setExpanded(true);
QTreeWidgetItem *item4 = new QTreeWidgetItem(item3);
item4->setText(0, "item4");
QTreeWidgetItem *item5 = new QTreeWidgetItem(tree, item3);
item5->setText(0, "item5");
- tree->setItemExpanded(item5, true);
+ item5->setExpanded(true);
QTreeWidgetItem *item6 = new QTreeWidgetItem(item5);
item6->setText(0, "item6");
@@ -3004,7 +3107,7 @@ void tst_QTreeWidget::task191552_rtl()
opt.features = QStyleOptionViewItem::HasDisplay | QStyleOptionViewItem::HasCheckIndicator;
opt.checkState = Qt::Checked;
opt.widget = &tw;
- const QRect checkRect = tw.style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, &tw);
+ const QRect checkRect = tw.style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &opt, &tw);
QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::NoModifier, checkRect.center());
QCOMPARE(item->checkState(0), Qt::Unchecked);
@@ -3218,7 +3321,7 @@ void tst_QTreeWidget::nonEditableTristate()
option.checkState = item->checkState(0);
const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
- QPoint pos = qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0);
+ QPoint pos = qApp->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0);
QTest::mouseClick(tree->viewport(), Qt::LeftButton, Qt::NoModifier, pos);
QCOMPARE(int(item->checkState(0)), int(Qt::Checked));
@@ -3530,5 +3633,43 @@ void tst_QTreeWidget::reparentHiddenItem()
QVERIFY(grandChild->isHidden());
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+void tst_QTreeWidget::clearItemData()
+{
+ QTreeWidget tree;
+ QAbstractItemModel* model = tree.model();
+ QVERIFY(model->insertColumn(0));
+ QVERIFY(model->insertRow(0));
+ const QModelIndex parentIdx = model->index(0, 0);
+ QVERIFY(model->insertColumn(0, parentIdx));
+ QVERIFY(model->insertRow(0, parentIdx));
+ const QModelIndex childIdx = model->index(0, 0, parentIdx);
+ model->setData(parentIdx, QStringLiteral("parent"));
+ model->setData(parentIdx, QStringLiteral("parent"), Qt::UserRole);
+ model->setData(childIdx, QStringLiteral("child"));
+ QSignalSpy dataChangeSpy(model, &QAbstractItemModel::dataChanged);
+ QVERIFY(dataChangeSpy.isValid());
+ QVERIFY(!model->clearItemData(QModelIndex()));
+ QCOMPARE(dataChangeSpy.size(), 0);
+ QVERIFY(model->clearItemData(parentIdx));
+ QVERIFY(!model->data(parentIdx).isValid());
+ QVERIFY(!model->data(parentIdx, Qt::UserRole).isValid());
+ QCOMPARE(dataChangeSpy.size(), 1);
+ QList<QVariant> dataChangeArgs = dataChangeSpy.takeFirst();
+ QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), parentIdx);
+ QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), parentIdx);
+ QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty());
+ QVERIFY(model->clearItemData(parentIdx));
+ QCOMPARE(dataChangeSpy.size(), 0);
+ QVERIFY(model->clearItemData(childIdx));
+ QVERIFY(!model->data(childIdx).isValid());
+ QCOMPARE(dataChangeSpy.size(), 1);
+ dataChangeArgs = dataChangeSpy.takeFirst();
+ QCOMPARE(dataChangeArgs.at(0).value<QModelIndex>(), childIdx);
+ QCOMPARE(dataChangeArgs.at(1).value<QModelIndex>(), childIdx);
+ QVERIFY(dataChangeArgs.at(2).value<QVector<int>>().isEmpty());
+}
+#endif
+
QTEST_MAIN(tst_QTreeWidget)
#include "tst_qtreewidget.moc"
diff --git a/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp
index c2c02f3766..76ca148d3f 100644
--- a/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp
+++ b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp
@@ -95,11 +95,11 @@ void tst_QTreeWidgetItemIterator::initTestCase()
const QString topS = QLatin1String("top") + QString::number(i);
top->setText(0, topS);
switch (i) {
- case 0: testWidget->setItemHidden(top, true);break;
- case 1: testWidget->setItemHidden(top, false);break;
+ case 0: top->setHidden(true);break;
+ case 1: top->setHidden(false);break;
- case 2: testWidget->setItemSelected(top, true);break;
- case 3: testWidget->setItemSelected(top, false);break;
+ case 2: top->setSelected(true);break;
+ case 3: top->setSelected(false);break;
case 4: top->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);break;
case 5: top->setFlags(Qt::ItemIsEnabled);break;
@@ -126,11 +126,11 @@ void tst_QTreeWidgetItemIterator::initTestCase()
QTreeWidgetItem *child = new QTreeWidgetItem(top);
child->setText(0, topS + QLatin1String(",child") + QString::number(j));
switch (j) {
- case 0: testWidget->setItemHidden(child, true);break;
- case 1: testWidget->setItemHidden(child, false);break;
+ case 0: child->setHidden(true);break;
+ case 1: child->setHidden(false);break;
- case 2: testWidget->setItemSelected(child, true);break;
- case 3: testWidget->setItemSelected(child, false);break;
+ case 2: child->setSelected(true);break;
+ case 3: child->setSelected(false);break;
case 4: child->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);break;
case 5: child->setFlags(Qt::ItemIsEnabled);break;
diff --git a/tests/auto/widgets/kernel/kernel.pro b/tests/auto/widgets/kernel/kernel.pro
index 73fd934502..af85a2bd13 100644
--- a/tests/auto/widgets/kernel/kernel.pro
+++ b/tests/auto/widgets/kernel/kernel.pro
@@ -22,5 +22,3 @@ SUBDIRS=\
darwin:SUBDIRS -= \ # Uses native recognizers
qgesturerecognizer \
-
-SUBDIRS -= qsound
diff --git a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
index 52ca10d31f..64e5b969e7 100644
--- a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
+++ b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
@@ -41,6 +41,7 @@ private slots:
void enabledPropagation();
void visiblePropagation();
void exclusive();
+ void exclusiveOptional();
void separators();
void testActionInTwoQActionGroup();
void unCheckCurrentAction();
@@ -151,6 +152,52 @@ void tst_QActionGroup::exclusive()
QVERIFY( !actThree->isChecked() );
}
+void tst_QActionGroup::exclusiveOptional()
+{
+ QActionGroup group(0);
+ group.setExclusive(true);
+ QVERIFY( group.isExclusive() );
+
+ QAction* actOne = new QAction( &group );
+ actOne->setCheckable( true );
+ QAction* actTwo = new QAction( &group );
+ actTwo->setCheckable( true );
+ QAction* actThree = new QAction( &group );
+ actThree->setCheckable( true );
+
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actOne->trigger();
+ QVERIFY( actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actOne->trigger();
+ QVERIFY( actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ group.setExclusionPolicy( QActionGroup::ExclusionPolicy::ExclusiveOptional );
+ QVERIFY( group.isExclusive() );
+
+ actOne->trigger();
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actTwo->trigger();
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actTwo->trigger();
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+}
+
void tst_QActionGroup::separators()
{
QMainWindow mw;
@@ -166,24 +213,22 @@ void tst_QActionGroup::separators()
separator->setSeparator(true);
actGroup.addAction(separator);
- QListIterator<QAction*> it(actGroup.actions());
- while (it.hasNext())
- menu.addAction(it.next());
+ menu.addActions(actGroup.actions());
QCOMPARE((int)menu.actions().size(), 2);
- it = QListIterator<QAction*>(actGroup.actions());
- while (it.hasNext())
- menu.removeAction(it.next());
+ const auto removeActions = [&menu](const QList<QAction *> &actions) {
+ for (QAction *action : actions)
+ menu.removeAction(action);
+ };
+ removeActions(actGroup.actions());
QCOMPARE((int)menu.actions().size(), 0);
action = new QAction(&actGroup);
action->setText("test two");
- it = QListIterator<QAction*>(actGroup.actions());
- while (it.hasNext())
- menu.addAction(it.next());
+ menu.addActions(actGroup.actions());
QCOMPARE((int)menu.actions().size(), 3);
}
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index 5b4a5d30a5..4f94e83c1c 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -200,6 +200,7 @@ void tst_QApplication::staticSetup()
QVERIFY(style);
QApplication::setStyle(style);
+ bool palette_changed = false;
QPalette pal;
QApplication::setPalette(pal);
@@ -208,6 +209,10 @@ void tst_QApplication::staticSetup()
int argc = 0;
QApplication app(argc, nullptr);
+ QObject::connect(&app, &QApplication::paletteChanged, [&palette_changed]{ palette_changed = true; });
+ QVERIFY(!palette_changed);
+ qApp->setPalette(QPalette(Qt::red));
+ QVERIFY(palette_changed);
}
@@ -885,7 +890,9 @@ void tst_QApplication::libraryPaths()
QStringList actual = QApplication::libraryPaths();
actual.sort();
- QStringList expected = QSet<QString>::fromList((QStringList() << testDir << appDirPath)).toList();
+ QStringList expected;
+ expected << testDir << appDirPath;
+ expected = QSet<QString>(expected.constBegin(), expected.constEnd()).values();
expected.sort();
QVERIFY2(isPathListIncluded(actual, expected),
@@ -902,7 +909,9 @@ void tst_QApplication::libraryPaths()
QStringList actual = QApplication::libraryPaths();
actual.sort();
- QStringList expected = QSet<QString>::fromList((QStringList() << installPathPlugins << appDirPath)).toList();
+ QStringList expected;
+ expected << installPathPlugins << appDirPath;
+ expected = QSet<QString>(expected.constBegin(), expected.constEnd()).values();
expected.sort();
#ifdef Q_OS_WINRT
@@ -2166,8 +2175,6 @@ void tst_QApplication::abortQuitOnShow()
void tst_QApplication::staticFunctions()
{
QApplication::setStyle(QStringLiteral("blub"));
- QApplication::colorSpec();
- QApplication::setColorSpec(42);
QApplication::allWidgets();
QApplication::topLevelWidgets();
QApplication::desktop();
diff --git a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
index b2650d1f32..8dd9d7c428 100644
--- a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
+++ b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
@@ -47,6 +47,7 @@ private slots:
void sizeConstraints();
void setGeometry();
void setStyleShouldChangeSpacing();
+ void widgetSurplus();
void testLayoutEngine_data();
void testLayoutEngine();
@@ -236,6 +237,69 @@ void tst_QBoxLayout::setStyleShouldChangeSpacing()
QTRY_COMPARE(spacing(), 10);
}
+class MarginEatingStyle : public QProxyStyle
+{
+public:
+ MarginEatingStyle() : QProxyStyle(QStyleFactory::create("windows"))
+ {
+ }
+
+ virtual QRect subElementRect(SubElement sr, const QStyleOption *opt,
+ const QWidget *widget) const
+ {
+ QRect rect = opt->rect;
+ switch (sr) {
+ case SE_GroupBoxLayoutItem:
+ // this is a simplifed version of what the macOS style does
+ rect.setTop(rect.top() + 20);
+ rect.setLeft(rect.left() + 20);
+ rect.setRight(rect.right() - 20);
+ rect.setBottom(rect.bottom() - 20);
+ break;
+ default:
+ return QProxyStyle::subElementRect(sr, opt, widget);
+ }
+
+ return rect;
+ }
+};
+
+void tst_QBoxLayout::widgetSurplus()
+{
+ // Test case for QTBUG-67608 - a style requests space in the margin
+
+ QDialog window;
+ QScopedPointer<MarginEatingStyle> marginEater(new MarginEatingStyle);
+ QVBoxLayout *vbox = new QVBoxLayout(&window);
+ vbox->setMargin(0);
+ vbox->setSpacing(0);
+
+ QLabel *hiddenLabel = new QLabel(tr("Invisible label"));
+ hiddenLabel->setVisible(false);
+
+ QGroupBox *groupBox = new QGroupBox(tr("Groupbox Title"));
+ groupBox->setStyle(marginEater.data());
+ groupBox->setObjectName("Test group box");
+ QPushButton *button1 = new QPushButton(tr("Button 1"));
+ QPushButton *button2 = new QPushButton(tr("Button 2"));
+ QVBoxLayout *groupLayout = new QVBoxLayout;
+ groupLayout->addWidget(button1);
+ groupLayout->addWidget(button2);
+ groupBox->setLayout(groupLayout);
+
+ QLabel *label = new QLabel(tr("Visible label"));
+
+ vbox->addWidget(hiddenLabel);
+ vbox->addWidget(groupBox);
+ vbox->addWidget(label);
+ window.setLayout(vbox);
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QCOMPARE(groupBox->y(), 0);
+ QCOMPARE(groupBox->x(), 0);
+}
+
void tst_QBoxLayout::taskQTBUG_7103_minMaxWidthNotRespected()
{
QLabel *label = new QLabel("Qt uses standard C++, but makes extensive use of the C pre-processor to enrich the language. Qt can also be used in several other programming languages via language bindings. It runs on all major platforms, and has extensive internationalization support. Non-GUI features include SQL database access, XML parsing, thread management, network support and a unified cross-platform API for file handling.");
@@ -507,6 +571,10 @@ void tst_QBoxLayout::replaceWidget()
QCOMPARE(boxLayout->indexOf(replaceFrom), 1);
QCOMPARE(boxLayout->indexOf(replaceTo), -1);
+ QCOMPARE(boxLayout->count(), 3);
+ boxLayout->replaceWidget(replaceFrom, replaceFrom);
+ QCOMPARE(boxLayout->count(), 3);
+
delete boxLayout->replaceWidget(replaceFrom, replaceTo);
QCOMPARE(boxLayout->indexOf(replaceFrom), -1);
diff --git a/tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp b/tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp
index 6f2847974f..90776dfcb2 100644
--- a/tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp
+++ b/tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp
@@ -32,6 +32,9 @@
#include <QtGui/QWindow>
#include <QDebug>
+// the complete class is deprecated
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
class tst_QDesktopWidget : public QObject
{
Q_OBJECT
@@ -163,7 +166,7 @@ void tst_QDesktopWidget::topLevels()
QCOMPARE(topLevelDesktopWidgets, 0);
QCOMPARE(topLevelDesktopWindows, 0);
}
+QT_WARNING_POP
QTEST_MAIN(tst_QDesktopWidget)
#include "tst_qdesktopwidget.moc"
-
diff --git a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
index cff3dad35e..ab32643061 100644
--- a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
+++ b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
@@ -52,7 +52,7 @@ using namespace QTestPrivate;
Q_CONSTEXPR QFormLayout::ItemRole invalidRole = QFormLayout::ItemRole(3);
struct QFormLayoutTakeRowResultHolder {
- QFormLayoutTakeRowResultHolder(QFormLayout::TakeRowResult result) Q_DECL_NOTHROW
+ QFormLayoutTakeRowResultHolder(QFormLayout::TakeRowResult result) noexcept
: labelItem(result.labelItem),
fieldItem(result.fieldItem)
{
@@ -66,20 +66,20 @@ struct QFormLayoutTakeRowResultHolder {
if (fieldItem)
disposer.setItem(0, QFormLayout::FieldRole, fieldItem);
}
- QFormLayoutTakeRowResultHolder(QFormLayoutTakeRowResultHolder &&other) Q_DECL_NOTHROW
+ QFormLayoutTakeRowResultHolder(QFormLayoutTakeRowResultHolder &&other) noexcept
: labelItem(other.labelItem),
fieldItem(other.fieldItem)
{
other.labelItem = nullptr;
other.fieldItem = nullptr;
}
- QFormLayoutTakeRowResultHolder &operator=(QFormLayoutTakeRowResultHolder &&other) Q_DECL_NOTHROW
+ QFormLayoutTakeRowResultHolder &operator=(QFormLayoutTakeRowResultHolder &&other) noexcept
{
swap(other);
return *this;
}
- void swap(QFormLayoutTakeRowResultHolder &other) Q_DECL_NOTHROW
+ void swap(QFormLayoutTakeRowResultHolder &other) noexcept
{
qSwap(labelItem, other.labelItem);
qSwap(fieldItem, other.fieldItem);
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index 1f68308bbe..03bec4286b 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -10,6 +10,7 @@ osx
ubuntu-16.04
ubuntu-18.04
rhel-7.4
+rhel-7.6
osx
[focusProxyAndInputMethods]
linux
@@ -45,3 +46,6 @@ osx
osx-10.12 ci
[multipleToplevelFocusCheck]
linux
+[windowState]
+# QTBUG-75270
+winrt
diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.pro b/tests/auto/widgets/kernel/qwidget/qwidget.pro
index c1908af2a2..d3fbd6d0d9 100644
--- a/tests/auto/widgets/kernel/qwidget/qwidget.pro
+++ b/tests/auto/widgets/kernel/qwidget/qwidget.pro
@@ -16,4 +16,4 @@ mac {
OBJECTIVE_SOURCES += tst_qwidget_mac_helpers.mm
}
-win32:!winrt: LIBS += -luser32 -lgdi32
+win32:!winrt: QMAKE_USE += user32 gdi32
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 489edb703c..fb40674d98 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -312,7 +312,9 @@ private slots:
void setMaskInResizeEvent();
void moveInResizeEvent();
- void immediateRepaintAfterInvalidateBuffer();
+#ifdef QT_BUILD_INTERNAL
+ void immediateRepaintAfterInvalidateBackingStore();
+#endif
void effectiveWinId();
void effectiveWinId2();
@@ -2478,8 +2480,8 @@ void tst_QWidget::showMinimizedKeepsFocus()
{
if (m_platform == QStringLiteral("xcb"))
QSKIP("QTBUG-26424");
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported.");
if (m_platform == QStringLiteral("offscreen"))
QSKIP("Platform offscreen does not support showMinimized()");
@@ -2690,8 +2692,8 @@ void tst_QWidget::icon()
void tst_QWidget::hideWhenFocusWidgetIsChild()
{
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported.");
QScopedPointer<QWidget> testWidget(new QWidget);
testWidget->setWindowTitle(__FUNCTION__);
@@ -5492,8 +5494,8 @@ void tst_QWidget::multipleToplevelFocusCheck()
QSKIP("QTBUG-52974");
#endif
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported");
else if (m_platform == QStringLiteral("winrt"))
QSKIP("Winrt: Sometimes crashes in QTextLayout. - QTBUG-68297");
TopLevelFocusCheck w1;
@@ -6207,7 +6209,11 @@ public:
return false;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool nativeEvent(const QByteArray &eventType, void *message, qintptr *) override
+#else
bool nativeEvent(const QByteArray &eventType, void *message, long *) override
+#endif
{
if (isMapNotify(eventType, message))
gotExpectedMapNotify = true;
@@ -6215,7 +6221,11 @@ public:
}
// QAbstractNativeEventFilter interface
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override
+#else
bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override
+#endif
{
if (isMapNotify(eventType, message))
gotExpectedGlobalEvent = true;
@@ -7742,9 +7752,6 @@ void tst_QWidget::updateWhileMinimized()
// Restore window.
widget.showNormal();
- QTest::qWait(30);
- if (m_platform == QStringLiteral("xcb"))
- QSKIP("QTBUG-26424");
QTRY_COMPARE(widget.numPaintEvents, 1);
QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50));
}
@@ -8296,7 +8303,7 @@ void tst_QWidget::resizeInPaintEvent()
widget.resizeInPaintEvent = true;
// This will call resize in the paintEvent, which in turn will call
- // invalidateBuffer() and a new update request should be posted.
+ // invalidateBackingStore() and a new update request should be posted.
widget.repaint();
QCOMPARE(widget.numPaintEvents, 1);
widget.numPaintEvents = 0;
@@ -8449,7 +8456,8 @@ void tst_QWidget::moveInResizeEvent()
QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
}
-void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
+#ifdef QT_BUILD_INTERNAL
+void tst_QWidget::immediateRepaintAfterInvalidateBackingStore()
{
if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
QSKIP("We don't support immediate repaint right after show on other platforms.");
@@ -8464,7 +8472,7 @@ void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
// Marks the area covered by the widget as dirty in the backing store and
// posts an UpdateRequest event.
- qt_widget_private(widget.data())->invalidateBuffer(widget->rect());
+ qt_widget_private(widget.data())->invalidateBackingStore(widget->rect());
QCOMPARE(widget->numPaintEvents, 0);
// The entire widget is already dirty, but this time we want to update immediately
@@ -8473,6 +8481,7 @@ void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
widget->repaint();
QCOMPARE(widget->numPaintEvents, 1);
}
+#endif
void tst_QWidget::effectiveWinId()
{
@@ -9530,7 +9539,7 @@ QWidgetBackingStore* backingStore(QWidget &widget)
void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
{
#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
+ QGuiApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
#endif
QWidget main(nullptr, Qt::FramelessWindowHint); //don't get confused by the size of the window frame
main.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
@@ -9568,7 +9577,7 @@ void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
QTRY_COMPARE(mainPixmap.toImage().convertToFormat(QImage::Format_RGB32),
correct.toImage().convertToFormat(QImage::Format_RGB32));
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
#endif
}
@@ -9620,8 +9629,8 @@ void tst_QWidget::setGraphicsEffect()
void tst_QWidget::activateWindow()
{
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported.");
// Test case for QTBUG-26711
@@ -9689,8 +9698,8 @@ void tst_QWidget::openModal_taskQTBUG_5804()
void tst_QWidget::focusProxyAndInputMethods()
{
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported.");
QScopedPointer<QWidget> toplevel(new QWidget(nullptr, Qt::X11BypassWindowManagerHint));
toplevel->setWindowTitle(QLatin1String(QTest::currentTestFunction()));
toplevel->resize(200, 200);
@@ -9727,7 +9736,7 @@ public:
{
if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
- static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
+ static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBackingStore(this->rect());
repaint();
}
}
diff --git a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
index 934f2e8025..381cf76c46 100644
--- a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
@@ -2,7 +2,6 @@
# QTBUG-66345
opensuse-42.3
ubuntu-16.04
-ubuntu-18.04
[setWindowState]
ubuntu-18.04
rhel
diff --git a/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp b/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp
index 077e8de328..06522b2bd3 100644
--- a/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp
+++ b/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp
@@ -41,6 +41,8 @@ public:
private slots:
void metaObject();
+ void saveAndLoadBuiltin_data();
+ void saveAndLoadBuiltin();
};
class CustomWidget : public QWidget
@@ -68,5 +70,50 @@ void tst_QWidgetMetaType::metaObject()
QCOMPARE(QMetaType::metaObjectForType(qMetaTypeId<QSizePolicy>()), &QSizePolicy::staticMetaObject);
}
+template <typename T>
+struct StreamingTraits
+{
+ // Streamable by default, as currently all widgets built-in types are streamable
+ enum { isStreamable = 1 };
+};
+
+void tst_QWidgetMetaType::saveAndLoadBuiltin_data()
+{
+ QTest::addColumn<int>("type");
+ QTest::addColumn<bool>("isStreamable");
+
+#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
+ QTest::newRow(#RealType) << MetaTypeId << bool(StreamingTraits<RealType>::isStreamable);
+ QT_FOR_EACH_STATIC_WIDGETS_CLASS(ADD_METATYPE_TEST_ROW)
+#undef ADD_METATYPE_TEST_ROW
+}
+
+void tst_QWidgetMetaType::saveAndLoadBuiltin()
+{
+ QFETCH(int, type);
+ QFETCH(bool, isStreamable);
+
+ void *value = QMetaType::create(type);
+
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::ReadWrite);
+ QCOMPARE(QMetaType::save(stream, type, value), isStreamable);
+ QCOMPARE(stream.status(), QDataStream::Ok);
+
+ if (isStreamable)
+ QVERIFY(QMetaType::load(stream, type, value));
+
+ stream.device()->seek(0);
+ stream.resetStatus();
+ QCOMPARE(QMetaType::load(stream, type, value), isStreamable);
+ QCOMPARE(stream.status(), QDataStream::Ok);
+
+ if (isStreamable)
+ QVERIFY(QMetaType::load(stream, type, value));
+
+ QMetaType::destroy(type, value);
+}
+
+
QTEST_MAIN(tst_QWidgetMetaType)
#include "tst_qwidgetmetatype.moc"
diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
index 587e8a080d..a552c91928 100644
--- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
+++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
@@ -197,7 +197,7 @@ void tst_QStyle::drawItemPixmap()
const QRgb green = QColor(Qt::green).rgb();
QVERIFY(image.reinterpretAsFormat(QImage::Format_RGB32));
const QRgb *bits = reinterpret_cast<const QRgb *>(image.constBits());
- const QRgb *end = bits + image.byteCount() / sizeof(QRgb);
+ const QRgb *end = bits + image.sizeInBytes() / sizeof(QRgb);
#ifdef Q_OS_WINRT
QEXPECT_FAIL("", "QWidget::resize does not work on WinRT", Continue);
#endif
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
index 8760ed0373..a671a6c4d8 100644
--- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
+++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
@@ -160,7 +160,7 @@ void tst_QStyleSheetStyle::numinstances()
QCOMPARE(QStyleSheetStyle::numinstances, 0);
qApp->setStyleSheet("* { color: red; }");
QCOMPARE(QStyleSheetStyle::numinstances, 1);
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QCOMPARE(QStyleSheetStyle::numinstances, 0);
// set and unset application stylesheet+widget
@@ -169,9 +169,9 @@ void tst_QStyleSheetStyle::numinstances()
QCOMPARE(QStyleSheetStyle::numinstances, 2);
w.setStyle(style);
QCOMPARE(QStyleSheetStyle::numinstances, 2);
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QCOMPARE(QStyleSheetStyle::numinstances, 1);
- w.setStyleSheet("");
+ w.setStyleSheet(QString());
QCOMPARE(QStyleSheetStyle::numinstances, 0);
// set and unset widget stylesheet
@@ -180,7 +180,7 @@ void tst_QStyleSheetStyle::numinstances()
QCOMPARE(QStyleSheetStyle::numinstances, 1);
c.setStyle(style);
QCOMPARE(QStyleSheetStyle::numinstances, 2);
- w.setStyleSheet("");
+ w.setStyleSheet(QString());
QCOMPARE(QStyleSheetStyle::numinstances, 0);
}
@@ -193,9 +193,9 @@ void tst_QStyleSheetStyle::widgetsBeforeAppStyleSheet()
QCOMPARE(COLOR(w1), red);
w1.setStyleSheet("color: white");
QCOMPARE(COLOR(w1), white);
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QCOMPARE(COLOR(w1), white);
- w1.setStyleSheet("");
+ w1.setStyleSheet(QString());
QCOMPARE(COLOR(w1), APPCOLOR(w1));
}
@@ -218,17 +218,17 @@ void tst_QStyleSheetStyle::widgetsAfterAppStyleSheet()
QCOMPARE(COLOR(w1), white);
QCOMPARE(COLOR(spin), red);
QCOMPARE(COLOR(*spin.lineEdit()), red);
- w1.setStyleSheet("");
+ w1.setStyleSheet(QString());
QCOMPARE(COLOR(w1), red);
QCOMPARE(COLOR(spin), red);
QCOMPARE(COLOR(*spin.lineEdit()), red);
w1.setStyleSheet("color: white");
QCOMPARE(COLOR(w1), white);
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QCOMPARE(COLOR(w1), white);
QCOMPARE(COLOR(spin), APPCOLOR(spin));
QCOMPARE(COLOR(*spin.lineEdit()), APPCOLOR(*spin.lineEdit()));
- w1.setStyleSheet("");
+ w1.setStyleSheet(QString());
QCOMPARE(COLOR(w1), APPCOLOR(w1));
// QCOMPARE(FONTSIZE(w1), APPFONTSIZE(w1)); //### task 244261
QCOMPARE(FONTSIZE(spin), APPFONTSIZE(spin));
@@ -244,7 +244,7 @@ void tst_QStyleSheetStyle::applicationStyleSheet()
QCOMPARE(COLOR(w1), red);
qApp->setStyleSheet("* { color: white; }");
QCOMPARE(COLOR(w1), white);
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QCOMPARE(COLOR(w1), APPCOLOR(w1));
qApp->setStyleSheet("* { color: red }");
QCOMPARE(COLOR(w1), red);
@@ -255,21 +255,21 @@ void tst_QStyleSheetStyle::windowStyleSheet()
const QColor red(Qt::red);
const QColor white(Qt::white);
QPushButton w1;
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
w1.setStyleSheet("* { color: red; }");
QCOMPARE(COLOR(w1), red);
w1.setStyleSheet("* { color: white; }");
QCOMPARE(COLOR(w1), white);
- w1.setStyleSheet("");
+ w1.setStyleSheet(QString());
QCOMPARE(COLOR(w1), APPCOLOR(w1));
w1.setStyleSheet("* { color: red }");
QCOMPARE(COLOR(w1), red);
qApp->setStyleSheet("* { color: green }");
QCOMPARE(COLOR(w1), red);
- w1.setStyleSheet("");
+ w1.setStyleSheet(QString());
QCOMPARE(COLOR(w1), QColor("green"));
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QCOMPARE(COLOR(w1), APPCOLOR(w1));
}
@@ -282,7 +282,7 @@ void tst_QStyleSheetStyle::widgetStyleSheet()
QPushButton *pb = new QPushButton(&w1);
QPushButton &w2 = *pb;
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
w1.setStyleSheet("* { color: red }");
QCOMPARE(COLOR(w1), red);
QCOMPARE(COLOR(w2), red);
@@ -294,11 +294,11 @@ void tst_QStyleSheetStyle::widgetStyleSheet()
QCOMPARE(COLOR(w1), blue);
QCOMPARE(COLOR(w2), white);
- w1.setStyleSheet("");
+ w1.setStyleSheet(QString());
QCOMPARE(COLOR(w1), APPCOLOR(w1));
QCOMPARE(COLOR(w2), white);
- w2.setStyleSheet("");
+ w2.setStyleSheet(QString());
QCOMPARE(COLOR(w1), APPCOLOR(w1));
QCOMPARE(COLOR(w2), APPCOLOR(w2));
}
@@ -312,7 +312,7 @@ void tst_QStyleSheetStyle::reparentWithNoChildStyleSheet()
QPushButton *pb = new QPushButton(&p1);
QPushButton &c1 = *pb; // child with no stylesheet
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
p1.setStyleSheet("* { color: red }");
QCOMPARE(COLOR(c1), red);
c1.setParent(&p2);
@@ -334,7 +334,7 @@ void tst_QStyleSheetStyle::reparentWithChildStyleSheet()
{
const QColor gray("gray");
const QColor white(Qt::white);
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QPushButton p1, p2;
QPushButton *pb = new QPushButton(&p1);
QPushButton &c1 = *pb;
@@ -354,7 +354,7 @@ void tst_QStyleSheetStyle::repolish()
{
const QColor red(Qt::red);
const QColor white(Qt::white);
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QPushButton p1;
p1.setStyleSheet("color: red; background: white");
QCOMPARE(BACKGROUND(p1), white);
@@ -363,7 +363,7 @@ void tst_QStyleSheetStyle::repolish()
p1.setStyleSheet("color: red");
QCOMPARE(COLOR(p1), red);
QCOMPARE(BACKGROUND(p1), APPBACKGROUND(p1));
- p1.setStyleSheet("");
+ p1.setStyleSheet(QString());
QCOMPARE(COLOR(p1), APPCOLOR(p1));
QCOMPARE(BACKGROUND(p1), APPBACKGROUND(p1));
}
@@ -390,7 +390,7 @@ void tst_QStyleSheetStyle::repolish_without_crashing()
void tst_QStyleSheetStyle::widgetStyle()
{
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QWidget *window1 = new QWidget;
window1->setObjectName("window1");
@@ -450,7 +450,7 @@ void tst_QStyleSheetStyle::widgetStyle()
// Remove the stylesheet
proxy = (QStyleSheetStyle *)window1->style();
- window1->setStyleSheet("");
+ window1->setStyleSheet(QString());
QVERIFY(proxy.isNull()); // should have disappeared
QCOMPARE(window1->style(), style1.data()); // its restored
@@ -478,7 +478,7 @@ void tst_QStyleSheetStyle::widgetStyle()
QCOMPARE(proxy->baseStyle(), style1.data());
// Style Sheet propagation on a child widget with a custom style already set
- window2->setStyleSheet("");
+ window2->setStyleSheet(QString());
QCOMPARE(window2->style(), style2.data());
QCOMPARE(widget2->style(), style1.data());
widget2->setStyle(0);
@@ -491,9 +491,9 @@ void tst_QStyleSheetStyle::widgetStyle()
// clean everything out
window1->setStyle(0);
- window1->setStyleSheet("");
+ window1->setStyleSheet(QString());
window2->setStyle(0);
- window2->setStyleSheet("");
+ window2->setStyleSheet(QString());
qApp->setStyle(0);
qApp->setStyleSheet("may_insanity_prevail { }"); // app has stylesheet
@@ -510,14 +510,14 @@ void tst_QStyleSheetStyle::widgetStyle()
QCOMPARE(proxy->baseStyle(), newStyle); // magic ;) the widget still follows the application
QCOMPARE(static_cast<QStyle *>(proxy), widget1->style()); // child still follows...
- window1->setStyleSheet(""); // remove stylesheet
+ window1->setStyleSheet(QString()); // remove stylesheet
QCOMPARE(window1->style(), qApp->style()); // is this cool or what
QCOMPARE(widget1->style(), qApp->style()); // annoying child follows...
QScopedPointer<QStyle> wndStyle(QStyleFactory::create("Windows"));
window1->setStyle(wndStyle.data());
QCOMPARE(window1->style()->metaObject()->className(), "QStyleSheetStyle"); // auto wraps it
QCOMPARE(widget1->style(), window1->style()); // and auto propagates to child
- qApp->setStyleSheet(""); // remove the app stylesheet
+ qApp->setStyleSheet(QString()); // remove the app stylesheet
QCOMPARE(window1->style(), wndStyle.data()); // auto dewrap
QCOMPARE(widget1->style(), qApp->style()); // and child state is restored
window1->setStyle(0); // let sanity prevail
@@ -532,7 +532,7 @@ void tst_QStyleSheetStyle::widgetStyle()
void tst_QStyleSheetStyle::appStyle()
{
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
// qApp style can never be 0
QVERIFY(QApplication::style() != 0);
QPointer<QStyle> style1 = QStyleFactory::create("Windows");
@@ -565,11 +565,11 @@ void tst_QStyleSheetStyle::appStyle()
QCOMPARE(sss->baseStyle(), style1.data());
// Revert the stylesheet
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QVERIFY(sss.isNull()); // should have disappeared
QCOMPARE(QApplication::style(), style1.data());
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QCOMPARE(QApplication::style(), style1.data());
}
@@ -765,7 +765,7 @@ void tst_QStyleSheetStyle::fontPropagation()
window.setStyleSheet("* { font-size: 9pt }");
pb.setParent(&window);
QCOMPARE(FONTSIZE(pb), 9);
- window.setStyleSheet("");
+ window.setStyleSheet(QString());
QCOMPARE(FONTSIZE(pb), buttonFontSize);
QTabWidget tw;
@@ -778,7 +778,7 @@ void tst_QStyleSheetStyle::fontPropagation()
void tst_QStyleSheetStyle::onWidgetDestroyed()
{
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
QLabel *l = new QLabel;
l->setStyleSheet("QLabel { color: red }");
QPointer<QStyleSheetStyle> ss = (QStyleSheetStyle *) l->style();
@@ -799,14 +799,14 @@ void tst_QStyleSheetStyle::fontPrecedence()
font.setPointSize(16);
edit.setFont(font);
QCOMPARE(FONTSIZE(edit), 22);
- edit.setStyleSheet("");
+ edit.setStyleSheet(QString());
QCOMPARE(FONTSIZE(edit), 16);
font.setPointSize(18);
edit.setFont(font);
QCOMPARE(FONTSIZE(edit), 18);
edit.setStyleSheet("QLineEdit { font-size: 20pt; }");
QCOMPARE(FONTSIZE(edit), 20);
- edit.setStyleSheet("");
+ edit.setStyleSheet(QString());
QCOMPARE(FONTSIZE(edit), 18);
edit.hide();
@@ -1210,7 +1210,7 @@ void tst_QStyleSheetStyle::transparent()
QPushButton *p3=new QPushButton(&w);
p1->setStyleSheet("background:transparent");
p2->setStyleSheet("background-color:transparent");
- p3->setStyleSheet("background:rgb(0,0,0,0)");
+ p3->setStyleSheet("background:rgba(0,0,0,0)");
QCOMPARE(BACKGROUND(*p1) , QColor(0,0,0,0));
QCOMPARE(BACKGROUND(*p2) , QColor(0,0,0,0));
QCOMPARE(BACKGROUND(*p3) , QColor(0,0,0,0));
@@ -2072,7 +2072,7 @@ void tst_QStyleSheetStyle::styleSheetTargetAttribute()
QCOMPARE(lb.testAttribute(Qt::WA_StyleSheetTarget), true);
QCOMPARE(pb.testAttribute(Qt::WA_StyleSheetTarget), false);
- qApp->setStyleSheet("");
+ qApp->setStyleSheet(QString());
gb.ensurePolished(); lb.ensurePolished(); pb.ensurePolished();
QCOMPARE(gb.testAttribute(Qt::WA_StyleSheetTarget), false);
@@ -2087,7 +2087,7 @@ void tst_QStyleSheetStyle::unpolish()
w.setStyleSheet("QWidget { min-width: 100; }");
w.ensurePolished();
QCOMPARE(w.minimumWidth(), 100);
- w.setStyleSheet("");
+ w.setStyleSheet(QString());
QCOMPARE(w.minimumWidth(), 0);
}
diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
index 22f29a5e29..5a51f15008 100644
--- a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
+++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
@@ -1602,27 +1602,16 @@ void tst_QCompleter::task247560_keyboardNavigation()
}
// Helpers for QTBUG_14292_filesystem: Recursion helper for below recurseTreeModel
-template <class Function>
-bool recurseTreeModelIndex(const QModelIndex &idx, Function f, int depth = 0)
-{
- if (f(idx, depth))
- return true;
- const int rowCount = idx.model()->rowCount(idx);
- for (int row = 0; row < rowCount; ++row)
- if (recurseTreeModelIndex(idx.child(row, 0), f, depth + 1))
- return true;
- return false;
-}
-
// Function to recurse over a tree model applying a function
// taking index and depth, returning true to terminate recursion.
-
template <class Function>
-bool recurseTreeModel(const QAbstractItemModel &m, Function f)
+bool recurseTreeModel(const QAbstractItemModel &m, const QModelIndex &idx, Function f, int depth = 0)
{
- const int rowCount = m.rowCount(QModelIndex());
+ if (idx.isValid() && f(idx, depth))
+ return true;
+ const int rowCount = m.rowCount(idx);
for (int row = 0; row < rowCount; ++row)
- if (recurseTreeModelIndex(m.index(row, 0, QModelIndex()), f))
+ if (recurseTreeModel(m, m.index(row, 0, idx), f, depth + 1))
return true;
return false;
}
@@ -1665,7 +1654,7 @@ QDebug operator<<(QDebug d, const QAbstractItemModel &m)
{
QDebug dns = d.nospace();
dns << '\n';
- recurseTreeModel(m, DebugFunction(dns));
+ recurseTreeModel(m, QModelIndex(), DebugFunction(dns));
return d;
}
@@ -1678,8 +1667,8 @@ static const char testDir2[] = "holla";
static inline bool testFileSystemReady(const QAbstractItemModel &model)
{
- return recurseTreeModel(model, SearchFunction(QLatin1String(testDir1), QFileSystemModel::FileNameRole))
- && recurseTreeModel(model, SearchFunction(QLatin1String(testDir2), QFileSystemModel::FileNameRole));
+ return recurseTreeModel(model, QModelIndex(), SearchFunction(QLatin1String(testDir1), QFileSystemModel::FileNameRole))
+ && recurseTreeModel(model, QModelIndex(), SearchFunction(QLatin1String(testDir2), QFileSystemModel::FileNameRole));
}
void tst_QCompleter::QTBUG_14292_filesystem()
diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
index 007825d39c..a17a9f6c33 100644
--- a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
+++ b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
@@ -124,13 +124,19 @@ void tst_QAbstractScrollArea::scrollBarWidgets()
QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), w2List);
+ auto sort = [](const QWidgetList l) {
+ QWidgetList list = l;
+ std::sort(list.begin(), list.end());
+ return list;
+ };
+
// two widgets at Bottom.
area.addScrollBarWidget(w3, Qt::AlignBottom);
- QCOMPARE(area.scrollBarWidgets(all).toSet(), allList.toSet());
+ QCOMPARE(sort(area.scrollBarWidgets(all)), sort(allList));
QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
- QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom).toSet(), (w2List + w3List).toSet());
+ QCOMPARE(sort(area.scrollBarWidgets(Qt::AlignBottom)), sort(w2List + w3List));
//delete
delete w1;
diff --git a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp
index 1a0d7a9289..d8fbb8e041 100644
--- a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp
+++ b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp
@@ -33,7 +33,7 @@
#include <QSlider>
#include <QStyle>
#include <QStyleOption>
-#include <QTime>
+#include <QElapsedTimer>
#include <QDebug>
#include <QtTest/private/qtesthelpers_p.h>
@@ -91,7 +91,7 @@ private slots:
void connectedSliders();
private:
- void waitUntilTimeElapsed(const QTime& t, int ms);
+ void waitUntilTimeElapsed(const QElapsedTimer &t, int ms);
QWidget *topLevel;
Slider *slider;
@@ -2053,11 +2053,11 @@ void tst_QAbstractSlider::setValue()
QVERIFY(sliderMovedTimeStamp < valueChangedTimeStamp);
}
-void tst_QAbstractSlider::waitUntilTimeElapsed(const QTime& t, int ms)
+void tst_QAbstractSlider::waitUntilTimeElapsed(const QElapsedTimer &t, int ms)
{
const int eps = 80;
while (t.elapsed() < ms + eps)
- QTest::qWait(qMax(ms - t.elapsed() + eps, 25));
+ QTest::qWait(qMax(int(ms - t.elapsed() + eps), 25));
}
void tst_QAbstractSlider::setRepeatAction()
@@ -2073,7 +2073,7 @@ void tst_QAbstractSlider::setRepeatAction()
QCOMPARE(spy.count(), 0);
QCOMPARE(slider->value(), 55);
- QTime t;
+ QElapsedTimer t;
t.start();
QTest::qWait(300);
QCOMPARE(spy.count(), 0);
diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
index 5b4761ba87..a576770811 100644
--- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
+++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -852,8 +852,8 @@ void tst_QComboBox::autoCompletionCaseSensitivity()
// case insensitive
testWidget->clearEditText();
QSignalSpy spyReturn(testWidget, SIGNAL(activated(int)));
- testWidget->setAutoCompletionCaseSensitivity(Qt::CaseInsensitive);
- QCOMPARE(testWidget->autoCompletionCaseSensitivity(), Qt::CaseInsensitive);
+ testWidget->completer()->setCaseSensitivity(Qt::CaseInsensitive);
+ QCOMPARE(testWidget->completer()->caseSensitivity(), Qt::CaseInsensitive);
QTest::keyClick(testWidget->lineEdit(), Qt::Key_A);
qApp->processEvents();
@@ -886,8 +886,8 @@ void tst_QComboBox::autoCompletionCaseSensitivity()
// case sensitive
testWidget->clearEditText();
- testWidget->setAutoCompletionCaseSensitivity(Qt::CaseSensitive);
- QCOMPARE(testWidget->autoCompletionCaseSensitivity(), Qt::CaseSensitive);
+ testWidget->completer()->setCaseSensitivity(Qt::CaseSensitive);
+ QCOMPARE(testWidget->completer()->caseSensitivity(), Qt::CaseSensitive);
QTest::keyClick(testWidget->lineEdit(), Qt::Key_A);
qApp->processEvents();
QCOMPARE(testWidget->currentText(), QString("aww"));
diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
index 20aad6ba97..c6f6900def 100644
--- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
+++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
@@ -307,19 +307,19 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
{
switch (modifier) {
case Qt::NoModifier:
- return QLatin1Literal("No");
+ return QLatin1String("No");
break;
case Qt::ControlModifier:
- return QLatin1Literal("Ctrl");
+ return QLatin1String("Ctrl");
break;
case Qt::ShiftModifier:
- return QLatin1Literal("Shift");
+ return QLatin1String("Shift");
break;
case Qt::AltModifier:
- return QLatin1Literal("Alt");
+ return QLatin1String("Alt");
break;
case Qt::MetaModifier:
- return QLatin1Literal("Meta");
+ return QLatin1String("Meta");
break;
default:
qFatal("Unexpected keyboard modifier");
@@ -331,17 +331,17 @@ static QLatin1String sectionToName(const QDateTimeEdit::Section section)
{
switch (section) {
case QDateTimeEdit::SecondSection:
- return QLatin1Literal("Second");
+ return QLatin1String("Second");
case QDateTimeEdit::MinuteSection:
- return QLatin1Literal("Minute");
+ return QLatin1String("Minute");
case QDateTimeEdit::HourSection:
- return QLatin1Literal("Hours");
+ return QLatin1String("Hours");
case QDateTimeEdit::DaySection:
- return QLatin1Literal("Day");
+ return QLatin1String("Day");
case QDateTimeEdit::MonthSection:
- return QLatin1Literal("Month");
+ return QLatin1String("Month");
case QDateTimeEdit::YearSection:
- return QLatin1Literal("Year");
+ return QLatin1String("Year");
default:
qFatal("Unexpected section");
return QLatin1String();
@@ -823,7 +823,7 @@ void tst_QDateTimeEdit::displayFormat_data()
<< QString("31 12 2999::59:59:03") << dt;
QTest::newRow("valid-2") << QString("hh-dd-mm-MM-yy") << true << QString("03-31-59-12-99") << dt;
QTest::newRow("valid-3") << QString("ddd MM d yyyy::ss:mm:hh") << true
- << QDate::shortDayName(2) + " 12 31 2999::59:59:03" << dt;
+ << QLocale::system().dayName(2, QLocale::ShortFormat) + " 12 31 2999::59:59:03" << dt;
QTest::newRow("valid-4") << QString("hh-dd-mm-MM-yyyy") << true << QString("03-31-59-12-2999") << dt;
QTest::newRow("invalid-0") << QString("yyyy.MM.yy") << true << QString("2999.12.99") << dt;
QTest::newRow("invalid-1") << QString("y") << false << QString() << dt;
@@ -2611,9 +2611,13 @@ void tst_QDateTimeEdit::weirdCase()
void tst_QDateTimeEdit::newCase()
{
- if (QDate::shortMonthName(6) != "Jun" || QDate::shortMonthName(7) != "Jul" ||
- QDate::longMonthName(6) != "June" || QDate::longMonthName(7) != "July")
+ const auto locale = QLocale::system();
+ if (locale.monthName(6, QLocale::ShortFormat) != "Jun" ||
+ locale.monthName(7, QLocale::ShortFormat) != "Jul" ||
+ locale.monthName(6, QLocale::LongFormat) != "June" ||
+ locale.monthName(7, QLocale::LongFormat) != "July") {
QSKIP("This test only works in English");
+ }
testWidget->setDisplayFormat("MMMM'a'MbMMMcMM");
testWidget->setDate(QDate(2005, 6, 1));
@@ -2656,12 +2660,12 @@ void tst_QDateTimeEdit::newCase2()
testWidget->setDate(QDate(2005, 8, 8));
QTest::keyClick(testWidget, Qt::Key_Return);
QTest::keyClick(testWidget, Qt::Key_Backspace);
- QCOMPARE(testWidget->text(), QString(" 2005-08-08 ") + QDate::longMonthName(8));
+ QCOMPARE(testWidget->text(), QString(" 2005-08-08 ") + QLocale::system().monthName(8, QLocale::LongFormat));
}
void tst_QDateTimeEdit::newCase3()
{
- if (!QDate::longMonthName(1).startsWith("Januar"))
+ if (!QLocale::system().monthName(1, QLocale::LongFormat).startsWith("Januar"))
QSKIP("This test does not work in this locale");
testWidget->setDisplayFormat("dd MMMM yyyy");
@@ -2681,7 +2685,7 @@ void tst_QDateTimeEdit::newCase3()
void tst_QDateTimeEdit::cursorPos()
{
- if (QDate::longMonthName(1) != "January")
+ if (QLocale::system().monthName(1, QLocale::LongFormat) != "January")
QSKIP("This test only works in English");
testWidget->setDisplayFormat("dd MMMM yyyy");
@@ -3017,7 +3021,7 @@ void tst_QDateTimeEdit::yyTest()
testWidget->setDate(testWidget->minimumDate());
testWidget->setCurrentSection(QDateTimeEdit::YearSection);
- QString jan = QDate::shortMonthName(1);
+ QString jan = QLocale::system().monthName(1, QLocale::ShortFormat);
QCOMPARE(testWidget->lineEdit()->displayText(), "01-" + jan + "-05");
QTest::keyClick(testWidget, Qt::Key_Up);
QCOMPARE(testWidget->lineEdit()->displayText(), "01-" + jan + "-06");
@@ -3130,7 +3134,7 @@ void tst_QDateTimeEdit::ddMMMMyyyy()
#ifdef Q_OS_MAC
QEXPECT_FAIL("", "QTBUG-23674", Abort);
#endif
- QCOMPARE(testWidget->lineEdit()->text(), "01." + QDate::longMonthName(1) + ".200");
+ QCOMPARE(testWidget->lineEdit()->text(), "01." + QLocale::system().monthName(1, QLocale::LongFormat) + ".200");
}
void tst_QDateTimeEdit::wheelEvent_data()
@@ -3213,16 +3217,16 @@ void tst_QDateTimeEdit::wheelEvent_data()
QLatin1String sourceName;
switch (source) {
case Qt::MouseEventNotSynthesized:
- sourceName = QLatin1Literal("NotSynthesized");
+ sourceName = QLatin1String("NotSynthesized");
break;
case Qt::MouseEventSynthesizedBySystem:
- sourceName = QLatin1Literal("SynthesizedBySystem");
+ sourceName = QLatin1String("SynthesizedBySystem");
break;
case Qt::MouseEventSynthesizedByQt:
- sourceName = QLatin1Literal("SynthesizedByQt");
+ sourceName = QLatin1String("SynthesizedByQt");
break;
case Qt::MouseEventSynthesizedByApplication:
- sourceName = QLatin1Literal("SynthesizedByApplication");
+ sourceName = QLatin1String("SynthesizedByApplication");
break;
default:
qFatal("Unexpected wheel event source");
diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
index 078a3215fd..625116654d 100644
--- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
+++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
@@ -71,6 +71,7 @@ private slots:
void restoreStateOfFloating();
void restoreDockWidget();
void restoreStateWhileStillFloating();
+ void setWindowTitle();
// task specific tests:
void task165177_deleteFocusWidget();
void task169808_setFloating();
@@ -669,7 +670,11 @@ void tst_QDockWidget::dockLocationChanged()
spy.clear();
dw.setFloating(true);
- QTest::qWait(100);
+ QTRY_COMPARE(spy.count(), 1);
+ QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
+ Qt::NoDockWidgetArea);
+ spy.clear();
+
dw.setFloating(false);
QTRY_COMPARE(spy.count(), 1);
QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)),
@@ -993,7 +998,54 @@ void tst_QDockWidget::taskQTBUG_9758_undockedGeometry()
QVERIFY(dock1.y() >= 0);
}
+void tst_QDockWidget::setWindowTitle()
+{
+ QMainWindow window;
+ QDockWidget dock1(&window);
+ QDockWidget dock2(&window);
+ const QString dock1Title = QStringLiteral("&Window");
+ const QString dock2Title = QStringLiteral("&Modifiable Window [*]");
+ dock1.setWindowTitle(dock1Title);
+ dock2.setWindowTitle(dock2Title);
+ window.addDockWidget(Qt::RightDockWidgetArea, &dock1);
+ window.addDockWidget(Qt::RightDockWidgetArea, &dock2);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ QCOMPARE(dock1.windowTitle(), dock1Title);
+ QCOMPARE(dock2.windowTitle(), dock2Title);
+
+ dock1.setFloating(true);
+ dock1.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&dock1));
+ QCOMPARE(dock1.windowTitle(), dock1Title);
+ dock1.setFloating(false);
+ QCOMPARE(dock1.windowTitle(), dock1Title);
+ dock1.setFloating(true);
+ dock1.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&dock1));
+ const QString changed = QStringLiteral("Changed ");
+ dock1.setWindowTitle(QString(changed + dock1Title));
+ QCOMPARE(dock1.windowTitle(), QString(changed + dock1Title));
+ dock1.setFloating(false);
+ QCOMPARE(dock1.windowTitle(), QString(changed + dock1Title));
+
+ dock2.setWindowModified(true);
+ QCOMPARE(dock2.windowTitle(), dock2Title);
+ dock2.setFloating(true);
+ dock2.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&dock2));
+ QCOMPARE(dock2.windowTitle(), dock2Title);
+ dock2.setWindowModified(false);
+ QCOMPARE(dock2.windowTitle(), dock2Title);
+ dock2.setFloating(false);
+ QCOMPARE(dock2.windowTitle(), dock2Title);
+ dock2.setFloating(true);
+ dock2.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&dock2));
+ QCOMPARE(dock2.windowTitle(), dock2Title);
+}
QTEST_MAIN(tst_QDockWidget)
#include "tst_qdockwidget.moc"
diff --git a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
index b1610c297d..a20b5568da 100644
--- a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
+++ b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
@@ -221,19 +221,19 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
{
switch (modifier) {
case Qt::NoModifier:
- return QLatin1Literal("No");
+ return QLatin1String("No");
break;
case Qt::ControlModifier:
- return QLatin1Literal("Ctrl");
+ return QLatin1String("Ctrl");
break;
case Qt::ShiftModifier:
- return QLatin1Literal("Shift");
+ return QLatin1String("Shift");
break;
case Qt::AltModifier:
- return QLatin1Literal("Alt");
+ return QLatin1String("Alt");
break;
case Qt::MetaModifier:
- return QLatin1Literal("Meta");
+ return QLatin1String("Meta");
break;
default:
qFatal("Unexpected keyboard modifier");
@@ -324,16 +324,30 @@ void tst_QDoubleSpinBox::setPrefixSuffix()
QFETCH(QString, expectedCleanText);
QFETCH(bool, show);
- QDoubleSpinBox spin(0);
+ QDoubleSpinBox spin;
+ if (show)
+ spin.show();
spin.setDecimals(decimals);
+ const QSize size1 = spin.sizeHint();
spin.setPrefix(prefix);
+ const QSize size2 = spin.sizeHint();
spin.setSuffix(suffix);
+ const QSize size3 = spin.sizeHint();
spin.setValue(value);
- if (show)
- spin.show();
QCOMPARE(spin.text(), expectedText);
QCOMPARE(spin.cleanText(), expectedCleanText);
+
+ if (!suffix.isEmpty()) {
+ QVERIFY(size2.width() < size3.width());
+ spin.setSuffix(QString());
+ QCOMPARE(spin.sizeHint(), size2);
+ }
+ if (!prefix.isEmpty()) {
+ QVERIFY(size1.width() < size2.width());
+ spin.setPrefix(QString());
+ QCOMPARE(spin.sizeHint(), size1);
+ }
}
void tst_QDoubleSpinBox::valueChangedHelper(const QString &text)
@@ -1434,16 +1448,16 @@ void tst_QDoubleSpinBox::wheelEvents_data()
QLatin1String sourceName;
switch (source) {
case Qt::MouseEventNotSynthesized:
- sourceName = QLatin1Literal("NotSynthesized");
+ sourceName = QLatin1String("NotSynthesized");
break;
case Qt::MouseEventSynthesizedBySystem:
- sourceName = QLatin1Literal("SynthesizedBySystem");
+ sourceName = QLatin1String("SynthesizedBySystem");
break;
case Qt::MouseEventSynthesizedByQt:
- sourceName = QLatin1Literal("SynthesizedByQt");
+ sourceName = QLatin1String("SynthesizedByQt");
break;
case Qt::MouseEventSynthesizedByApplication:
- sourceName = QLatin1Literal("SynthesizedByApplication");
+ sourceName = QLatin1String("SynthesizedByApplication");
break;
default:
qFatal("Unexpected wheel event source");
diff --git a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
index 1813e5ad5f..5392d36ae0 100644
--- a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
+++ b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp
@@ -108,7 +108,7 @@ void tst_QFontComboBox::currentFont()
QFont oldCurrentFont = box.currentFont();
box.setCurrentFont(currentFont);
- QRegExp foundry(" \\[.*\\]");
+ QRegularExpression foundry(" \\[.*\\]");
if (!box.currentFont().family().contains(foundry)) {
QCOMPARE(box.currentFont(), currentFont);
}
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index 95799905de..f1bc3e8dd4 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -3615,6 +3615,14 @@ void tst_QLineEdit::task174640_editingFinished()
le2->setFocus();
QTRY_VERIFY(le2->hasFocus());
+ // editingFinished will not be emitted anew because no editing happened
+ QCOMPARE(editingFinishedSpy.count(), 0);
+
+ le1->setFocus();
+ QTRY_VERIFY(le1->hasFocus());
+ QTest::keyPress(le1, Qt::Key_Plus);
+ le2->setFocus();
+ QTRY_VERIFY(le2->hasFocus());
QCOMPARE(editingFinishedSpy.count(), 1);
editingFinishedSpy.clear();
@@ -3632,6 +3640,8 @@ void tst_QLineEdit::task174640_editingFinished()
delete testMenu1;
QCOMPARE(editingFinishedSpy.count(), 0);
QTRY_VERIFY(le1->hasFocus());
+ // Ensure le1 has been edited
+ QTest::keyPress(le1, Qt::Key_Plus);
QMenu *testMenu2 = new QMenu(le2);
testMenu2->addAction("foo2");
@@ -3986,7 +3996,7 @@ void tst_QLineEdit::QTBUG7174_inputMaskCursorBlink()
edit.setFocus();
edit.setText(QLatin1String("AAAA"));
edit.show();
- QRect cursorRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect();
+ QRect cursorRect = edit.inputMethodQuery(Qt::ImCursorRectangle).toRect();
QVERIFY(QTest::qWaitForWindowExposed(&edit));
edit.updateRegion = QRegion();
QTest::qWait(QApplication::cursorFlashTime());
diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
index 6cc19051d2..046899ce05 100644
--- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
+++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
@@ -333,6 +333,7 @@ void tst_QMdiArea::subWindowActivated()
for ( i = 0; i < count; ++i ) {
QWidget *widget = new QWidget(workspace, 0);
widget->setAttribute(Qt::WA_DeleteOnClose);
+ widget->setFocus();
workspace->addSubWindow(widget)->show();
widget->show();
qApp->processEvents();
@@ -1689,14 +1690,16 @@ void tst_QMdiArea::tileSubWindows()
workspace.setActiveSubWindow(0);
QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
- // Make sure the active window is placed in top left corner regardless
+ // Make sure the active window does not move position after a tile regardless
// of whether we have any windows with staysOnTopHint or not.
+ workspace.tileSubWindows();
windows.at(3)->setWindowFlags(windows.at(3)->windowFlags() | Qt::WindowStaysOnTopHint);
QMdiSubWindow *activeSubWindow = windows.at(6);
workspace.setActiveSubWindow(activeSubWindow);
QCOMPARE(workspace.activeSubWindow(), activeSubWindow);
+ QPoint pos = activeSubWindow->geometry().topLeft();
workspace.tileSubWindows();
- QCOMPARE(activeSubWindow->geometry().topLeft(), QPoint(0, 0));
+ QCOMPARE(activeSubWindow->geometry().topLeft(), pos);
// Verify that we try to resize the area such that all sub-windows are visible.
// It's important that tiled windows are NOT overlapping.
@@ -1713,6 +1716,8 @@ void tst_QMdiArea::tileSubWindows()
// Prevent scrollbars from messing up the expected viewport calculation below
workspace.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
workspace.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ QCOMPARE(workspace.horizontalScrollBarPolicy(), Qt::ScrollBarAlwaysOff);
+ QCOMPARE(workspace.verticalScrollBarPolicy(), Qt::ScrollBarAlwaysOff);
workspace.tileSubWindows();
// The sub-windows are now tiled like this:
@@ -1731,9 +1736,11 @@ void tst_QMdiArea::tileSubWindows()
const QSize expectedViewportSize(3 * minSize.width() + spacing, 3 * minSize.height() + spacing);
QTRY_COMPARE(workspace.viewport()->rect().size(), expectedViewportSize);
- // Restore original scrollbar behavior for test below
+ // Enable scroll bar for test below (default property for QMdiArea is Qt::ScrollBarAlwaysOff)
workspace.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
workspace.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ QCOMPARE(workspace.horizontalScrollBarPolicy(), Qt::ScrollBarAsNeeded);
+ QCOMPARE(workspace.verticalScrollBarPolicy(), Qt::ScrollBarAsNeeded);
// Not enough space for all sub-windows to be visible -> provide scroll bars.
workspace.resize(160, 150);
@@ -1754,13 +1761,16 @@ void tst_QMdiArea::tileSubWindows()
QCOMPARE(vBar->value(), 0);
QCOMPARE(vBar->minimum(), 0);
+ // Tile windows with scroll bars enabled.
workspace.tileSubWindows();
QVERIFY(QTest::qWaitForWindowExposed(&workspace));
qApp->processEvents();
- QTRY_VERIFY(workspace.size() != QSize(150, 150));
- QTRY_VERIFY(!vBar->isVisible());
- QTRY_VERIFY(!hBar->isVisible());
+ // Workspace should not have changed size after tile.
+ QTRY_VERIFY(workspace.size() == QSize(160, 150));
+ // Scroll bars should be visible.
+ QTRY_VERIFY(vBar->isVisible());
+ QTRY_VERIFY(hBar->isVisible());
}
void tst_QMdiArea::cascadeAndTileSubWindows()
@@ -2180,7 +2190,7 @@ void tst_QMdiArea::setActivationOrder_data()
list << 2 << 1 << 0 << 1 << 2 << 3 << 4;
list2 << 0 << 1 << 2 << 3 << 4;
- list3 << 1 << 4 << 3 << 1 << 2 << 0;
+ list3 << 4 << 3 << 2 << 4 << 1 << 0; // Most recently created window is in top-left position
QTest::newRow("CreationOrder") << QMdiArea::CreationOrder << 5 << 3 << 1 << list << list2 << list3;
list = QList<int>();
@@ -2188,7 +2198,7 @@ void tst_QMdiArea::setActivationOrder_data()
list2 = QList<int>();
list2 << 0 << 2 << 4 << 1 << 3;
list3 = QList<int>();
- list3 << 1 << 3 << 4 << 1 << 2 << 0;
+ list3 << 3 << 1 << 4 << 3 << 2 << 0; // Window with "stays-on-top" flag set will be in the top-left position
QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 5 << 3 << 1 << list << list2 << list3;
list = QList<int>();
diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
index a88fd8d19c..3bfbe754ef 100644
--- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
+++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
@@ -1001,7 +1001,7 @@ void tst_QMenu::task258920_mouseBorder()
menu.setMouseTracking(true);
QAction *action = menu.addAction("test");
- const QPoint center = QApplication::desktop()->availableGeometry().center();
+ const QPoint center = QGuiApplication::primaryScreen()->availableGeometry().center();
menu.popup(center);
QVERIFY(QTest::qWaitForWindowExposed(&menu));
QRect actionRect = menu.actionGeometry(action);
@@ -1073,9 +1073,9 @@ void tst_QMenu::pushButtonPopulateOnAboutToShow()
QMenu *buttonMenu= new PopulateOnAboutToShowTestMenu(&b);
b.setMenu(buttonMenu);
- const int scrNumber = QApplication::desktop()->screenNumber(&b);
+ const QScreen *scr = QGuiApplication::screenAt(b.pos());
b.show();
- const QRect screen = QApplication::desktop()->screenGeometry(scrNumber);
+ const QRect screen = scr->geometry();
QRect desiredGeometry = b.geometry();
desiredGeometry.moveTopLeft(QPoint(screen.x() + 10, screen.bottom() - b.height() - 5));
@@ -1143,8 +1143,16 @@ void tst_QMenu::QTBUG7411_submenus_activate()
QTRY_VERIFY(sub1.isVisible());
}
+static bool isPlatformWayland()
+{
+ return !QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive);
+}
+
void tst_QMenu::QTBUG30595_rtl_submenu()
{
+ if (isPlatformWayland())
+ QSKIP("Creating xdg_popups on Wayland requires real input events. Positions would be off.");
+
QMenu menu("Test Menu");
menu.setLayoutDirection(Qt::RightToLeft);
QMenu sub("&sub");
@@ -1179,6 +1187,9 @@ void tst_QMenu::QTBUG20403_nested_popup_on_shortcut_trigger()
#ifndef Q_OS_MACOS
void tst_QMenu::click_while_dismissing_submenu()
{
+ if (isPlatformWayland())
+ QSKIP("Wayland: Creating (grabbing) popups requires real mouse events.");
+
QMenu menu("Test Menu");
QAction *action = menu.addAction("action");
QMenu sub("&sub");
@@ -1439,13 +1450,14 @@ void tst_QMenu::QTBUG_56917_wideMenuScreenNumber()
QString longString;
longString.fill(QLatin1Char('Q'), 3000);
- for (int i = 0; i < QApplication::desktop()->screenCount(); i++) {
+ const QList<QScreen *> screens = QGuiApplication::screens();
+ for (QScreen *screen : screens) {
QMenu menu;
menu.addAction(longString);
- menu.popup(QApplication::desktop()->screen(i)->geometry().center());
+ menu.popup(screen->geometry().center());
QVERIFY(QTest::qWaitForWindowExposed(&menu));
QVERIFY(menu.isVisible());
- QCOMPARE(QApplication::desktop()->screenNumber(&menu), i);
+ QCOMPARE(QGuiApplication::screenAt(menu.pos()), screen);
}
}
@@ -1457,19 +1469,20 @@ void tst_QMenu::QTBUG_56917_wideSubmenuScreenNumber()
QString longString;
longString.fill(QLatin1Char('Q'), 3000);
- for (int i = 0; i < QApplication::desktop()->screenCount(); i++) {
+ const QList<QScreen *> screens = QGuiApplication::screens();
+ for (QScreen *screen : screens) {
QMenu menu;
QMenu submenu("Submenu");
submenu.addAction(longString);
QAction *action = menu.addMenu(&submenu);
- menu.popup(QApplication::desktop()->screen(i)->geometry().center());
+ menu.popup(screen->geometry().center());
QVERIFY(QTest::qWaitForWindowExposed(&menu));
QVERIFY(menu.isVisible());
QTest::mouseClick(&menu, Qt::LeftButton, 0, menu.actionGeometry(action).center());
QTest::qWait(100);
QVERIFY(QTest::qWaitForWindowExposed(&submenu));
QVERIFY(submenu.isVisible());
- QCOMPARE(QApplication::desktop()->screenNumber(&submenu), i);
+ QCOMPARE(QGuiApplication::screenAt(submenu.pos()), screen);
}
}
@@ -1566,6 +1579,13 @@ void tst_QMenu::menuSize_Scrolling()
#ifdef Q_OS_WINRT
QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
#endif
+ if (!QGuiApplication::platformName().compare(QLatin1String("minimal"), Qt::CaseInsensitive)
+ || !QGuiApplication::platformName().compare(QLatin1String("offscreen"), Qt::CaseInsensitive)) {
+ QWARN("Skipping test on minimal/offscreen platforms - QTBUG-73522");
+ QMenu::showEvent(e);
+ return;
+ }
+
QCOMPARE( s.width(), lastItem.right() + fw + hmargin + rightMargin + 1);
QMenu::showEvent(e);
}
diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
index 3063d43aa6..d6ba85d61f 100644
--- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
+++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
@@ -113,10 +113,7 @@ private slots:
void check_escKey();
#endif
-#ifndef Q_OS_WINCE
void allowActiveAndDisabled();
-#endif
-
void taskQTBUG56860_focus();
void check_endKey();
void check_homeKey();
@@ -326,7 +323,7 @@ TestMenu tst_QMenuBar::initComplexMenuBar(QMenuBar *mb)
connect(action, SIGNAL(triggered()), this, SLOT(onComplexActionTriggered()));
result.actions << action;
- qFill(m_complexTriggerCount, m_complexTriggerCount + sizeof(m_complexTriggerCount) / sizeof(int), 0);
+ std::fill(m_complexTriggerCount, m_complexTriggerCount + sizeof(m_complexTriggerCount) / sizeof(int), 0);
return result;
}
diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
index cfa2ddc4cc..2ce75620cf 100644
--- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
+++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
@@ -140,6 +140,11 @@ private slots:
void findBackwardWithRegExp();
void findWithRegExpReturnsFalseIfNoMoreResults();
#endif
+#if QT_CONFIG(regularexpression)
+ void findWithRegularExpression();
+ void findBackwardWithRegularExpression();
+ void findWithRegularExpressionReturnsFalseIfNoMoreResults();
+#endif
void layoutAfterMultiLineRemove();
void undoCommandRemovesAndReinsertsBlock();
void taskQTBUG_43562_lineCountCrash();
@@ -147,6 +152,9 @@ private slots:
void contextMenu();
#endif
void inputMethodCursorRect();
+#if QT_CONFIG(scrollbar)
+ void updateAfterChangeCenterOnScroll();
+#endif
private:
void createSelection();
@@ -201,12 +209,12 @@ void tst_QPlainTextEdit::getSetCheck()
// int QPlainTextEdit::tabStopWidth()
// void QPlainTextEdit::setTabStopWidth(int)
- obj1.setTabStopWidth(0);
- QCOMPARE(0, obj1.tabStopWidth());
- obj1.setTabStopWidth(INT_MIN);
- QCOMPARE(0, obj1.tabStopWidth()); // Makes no sense to set a negative tabstop value
- obj1.setTabStopWidth(INT_MAX);
- QCOMPARE(INT_MAX, obj1.tabStopWidth());
+ obj1.setTabStopDistance(0);
+ QCOMPARE(0, obj1.tabStopDistance());
+ obj1.setTabStopDistance(-1);
+ QCOMPARE(0, obj1.tabStopDistance()); // Makes no sense to set a negative tabstop value
+ obj1.setTabStopDistance(std::numeric_limits<qreal>::max());
+ QCOMPARE(std::numeric_limits<qreal>::max(), obj1.tabStopDistance());
}
class QtTestDocumentLayout : public QAbstractTextDocumentLayout
@@ -1579,6 +1587,45 @@ void tst_QPlainTextEdit::findWithRegExpReturnsFalseIfNoMoreResults()
}
#endif
+#if QT_CONFIG(regularexpression)
+void tst_QPlainTextEdit::findWithRegularExpression()
+{
+ ed->setPlainText(QStringLiteral("arbitrary text"));
+ QRegularExpression rx("\\w{2}xt");
+
+ bool found = ed->find(rx);
+
+ QVERIFY(found);
+ QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("text"));
+}
+
+void tst_QPlainTextEdit::findBackwardWithRegularExpression()
+{
+ ed->setPlainText(QStringLiteral("arbitrary text"));
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::End);
+ ed->setTextCursor(cursor);
+ QRegularExpression rx("a\\w*t");
+
+ bool found = ed->find(rx, QTextDocument::FindBackward);
+
+ QVERIFY(found);
+ QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("arbit"));
+}
+
+void tst_QPlainTextEdit::findWithRegularExpressionReturnsFalseIfNoMoreResults()
+{
+ ed->setPlainText(QStringLiteral("arbitrary text"));
+ QRegularExpression rx("t.xt");
+ ed->find(rx);
+
+ bool found = ed->find(rx);
+
+ QVERIFY(!found);
+ QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("text"));
+}
+#endif
+
void tst_QPlainTextEdit::layoutAfterMultiLineRemove()
{
ed->setVisible(true); // The widget must be visible to reproduce this bug.
@@ -1727,5 +1774,20 @@ void tst_QPlainTextEdit::inputMethodCursorRect()
QCOMPARE(cursorRectV.toRect(), cursorRect.toRect());
}
+#if QT_CONFIG(scrollbar)
+// QTBUG-64730: Verify that the scrollbar is updated after center on scroll was set
+void tst_QPlainTextEdit::updateAfterChangeCenterOnScroll()
+{
+ ed->setPlainText("Line1\nLine2Line3\nLine3");
+ ed->show();
+ ed->setCenterOnScroll(true);
+ const int maxWithCenterOnScroll = ed->verticalScrollBar()->maximum();
+ ed->setCenterOnScroll(false);
+ const int maxWithoutCenterOnScroll = ed->verticalScrollBar()->maximum();
+ QVERIFY(maxWithCenterOnScroll > maxWithoutCenterOnScroll);
+}
+
+#endif
+
QTEST_MAIN(tst_QPlainTextEdit)
#include "tst_qplaintextedit.moc"
diff --git a/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp b/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
index d1923e4bb0..9f08bd337b 100644
--- a/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
+++ b/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp
@@ -87,7 +87,7 @@ public:
protected:
QVariant inputMethodQuery(Qt::InputMethodQuery query) const
{
- if (query == Qt::ImMicroFocus)
+ if (query == Qt::ImCursorRectangle)
return QRect(width() / 2, height() / 2, 5, 5);
return QWidget::inputMethodQuery(query);
}
@@ -110,7 +110,7 @@ void tst_QScrollArea::ensureMicroFocusVisible_Task_167838()
parent->resize(300, 300);
scrollArea.setWidget(parent);
scrollArea.ensureWidgetVisible(child, 10, 10);
- QRect microFocus = child->inputMethodQuery(Qt::ImMicroFocus).toRect();
+ QRect microFocus = child->inputMethodQuery(Qt::ImCursorRectangle).toRect();
QPoint p = child->mapTo(scrollArea.viewport(), microFocus.topLeft());
microFocus.translate(p - microFocus.topLeft());
QVERIFY(scrollArea.viewport()->rect().contains(microFocus));
diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
index 1d106f94f3..3dd29b0214 100644
--- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
+++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
@@ -206,7 +206,7 @@ private slots:
void stepModifierPressAndHold_data();
void stepModifierPressAndHold();
public slots:
- void valueChangedHelper(const QString &);
+ void textChangedHelper(const QString &);
void valueChangedHelper(int);
private:
QStringList actualTexts;
@@ -222,19 +222,19 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
{
switch (modifier) {
case Qt::NoModifier:
- return QLatin1Literal("No");
+ return QLatin1String("No");
break;
case Qt::ControlModifier:
- return QLatin1Literal("Ctrl");
+ return QLatin1String("Ctrl");
break;
case Qt::ShiftModifier:
- return QLatin1Literal("Shift");
+ return QLatin1String("Shift");
break;
case Qt::AltModifier:
- return QLatin1Literal("Alt");
+ return QLatin1String("Alt");
break;
case Qt::MetaModifier:
- return QLatin1Literal("Meta");
+ return QLatin1String("Meta");
break;
default:
qFatal("Unexpected keyboard modifier");
@@ -461,20 +461,36 @@ void tst_QSpinBox::setPrefixSuffix()
QFETCH(QString, expectedCleanText);
QFETCH(bool, show);
- QSpinBox spin(0);
+ QSpinBox spin;
+ if (show) {
+ spin.show();
+ spin.setPrefix(QString()); // trigger a recalc of sizeHint
+ }
+ const QSize size1 = spin.sizeHint();
spin.setPrefix(prefix);
+ const QSize size2 = spin.sizeHint();
spin.setSuffix(suffix);
+ const QSize size3 = spin.sizeHint();
spin.setValue(value);
- if (show)
- spin.show();
QCOMPARE(spin.prefix(), prefix);
QCOMPARE(spin.suffix(), suffix);
QCOMPARE(spin.text(), expectedText);
QCOMPARE(spin.cleanText(), expectedCleanText);
+
+ if (!suffix.isEmpty()) {
+ QVERIFY(size2.width() < size3.width());
+ spin.setSuffix(QString());
+ QCOMPARE(spin.sizeHint(), size2);
+ }
+ if (!prefix.isEmpty()) {
+ QVERIFY(size1.width() < size2.width());
+ spin.setPrefix(QString());
+ QCOMPARE(spin.sizeHint(), size1);
+ }
}
-void tst_QSpinBox::valueChangedHelper(const QString &text)
+void tst_QSpinBox::textChangedHelper(const QString &text)
{
actualTexts << text;
}
@@ -552,7 +568,7 @@ void tst_QSpinBox::setTracking()
QSpinBox spin(0);
spin.setKeyboardTracking(tracking);
spin.show();
- connect(&spin, SIGNAL(valueChanged(QString)), this, SLOT(valueChangedHelper(QString)));
+ connect(&spin, &QSpinBox::textChanged, this, &tst_QSpinBox::textChangedHelper);
keys.simulate(&spin);
QCOMPARE(actualTexts, texts);
@@ -1386,16 +1402,16 @@ void tst_QSpinBox::wheelEvents_data()
QLatin1String sourceName;
switch (source) {
case Qt::MouseEventNotSynthesized:
- sourceName = QLatin1Literal("NotSynthesized");
+ sourceName = QLatin1String("NotSynthesized");
break;
case Qt::MouseEventSynthesizedBySystem:
- sourceName = QLatin1Literal("SynthesizedBySystem");
+ sourceName = QLatin1String("SynthesizedBySystem");
break;
case Qt::MouseEventSynthesizedByQt:
- sourceName = QLatin1Literal("SynthesizedByQt");
+ sourceName = QLatin1String("SynthesizedByQt");
break;
case Qt::MouseEventSynthesizedByApplication:
- sourceName = QLatin1Literal("SynthesizedByApplication");
+ sourceName = QLatin1String("SynthesizedByApplication");
break;
default:
qFatal("Unexpected wheel event source");
diff --git a/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro b/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro
index 6523209c32..b61cc8fa13 100644
--- a/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro
+++ b/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro
@@ -8,4 +8,4 @@ INCLUDEPATH += ../
HEADERS +=
SOURCES += tst_qtabwidget.cpp
-win32:!winrt: LIBS += -luser32
+win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/widgets/widgets/qtextbrowser/heading.html b/tests/auto/widgets/widgets/qtextbrowser/heading.html
new file mode 100644
index 0000000000..8b23807f65
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/heading.html
@@ -0,0 +1,2 @@
+<h3>this is a heading</h3>
+<p>this is a paragraph</p>
diff --git a/tests/auto/widgets/widgets/qtextbrowser/markdown.md b/tests/auto/widgets/widgets/qtextbrowser/markdown.md
new file mode 100644
index 0000000000..be56aef234
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/markdown.md
@@ -0,0 +1,2 @@
+### this is a heading
+this is a paragraph
diff --git a/tests/auto/widgets/widgets/qtextbrowser/markdown.really b/tests/auto/widgets/widgets/qtextbrowser/markdown.really
new file mode 100644
index 0000000000..be56aef234
--- /dev/null
+++ b/tests/auto/widgets/widgets/qtextbrowser/markdown.really
@@ -0,0 +1,2 @@
+### this is a heading
+this is a paragraph
diff --git a/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro b/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
index 9680ffd871..dfdcf26497 100644
--- a/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
+++ b/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
@@ -4,6 +4,6 @@ SOURCES += tst_qtextbrowser.cpp
QT += widgets testlib
-TESTDATA += *.html subdir/*
+TESTDATA += *.html *.md markdown.really subdir/*
builtin_testdata: DEFINES += BUILTIN_TESTDATA
diff --git a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
index 8a1b228c71..083e297941 100644
--- a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
+++ b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -38,7 +38,7 @@
class TestBrowser : public QTextBrowser
{
public:
- inline TestBrowser() : htmlLoadAttempts(0) {
+ inline TestBrowser() {
show();
QApplication::setActiveWindow(this);
activateWindow();
@@ -47,11 +47,12 @@ public:
QVERIFY(hasFocus());
}
- virtual QVariant loadResource(int type, const QUrl &name);
+ QVariant loadResource(int type, const QUrl &name) override;
- int htmlLoadAttempts;
+ int htmlLoadAttempts = 0;
QUrl lastResource;
QUrl sourceInsideLoadResource;
+ QUrl baseInsideLoadResource;
};
QVariant TestBrowser::loadResource(int type, const QUrl &name)
@@ -60,6 +61,7 @@ QVariant TestBrowser::loadResource(int type, const QUrl &name)
htmlLoadAttempts++;
lastResource = name;
sourceInsideLoadResource = source();
+ baseInsideLoadResource = document()->baseUrl();
return QTextBrowser::loadResource(type, name);
}
@@ -90,6 +92,8 @@ private slots:
void focusIndicator();
void focusHistory();
void urlEncoding();
+ void sourceType_data();
+ void sourceType();
private:
TestBrowser *browser;
@@ -108,7 +112,7 @@ void tst_QTextBrowser::init()
void tst_QTextBrowser::cleanup()
{
delete browser;
- browser = 0;
+ browser = nullptr;
}
void tst_QTextBrowser::noReloadOnAnchorJump()
@@ -428,11 +432,18 @@ void tst_QTextBrowser::sourceInsideLoadResource()
#ifdef Q_OS_WINRT
QSKIP("Paths cannot be compared if applications are sandboxed.");
#endif
- QUrl url = QUrl::fromLocalFile("pagewithimage.html");
+ QUrl url = QUrl::fromLocalFile("pagewithimage.html"); // "file://pagewithimage.html"
browser->setSource(url);
QCOMPARE(browser->lastResource, QUrl::fromLocalFile(QDir::current().filePath("foobar.png")));
+ // baseUrl was not set because the source URL was a relative one
+ QCOMPARE(browser->baseInsideLoadResource, QUrl());
QEXPECT_FAIL("", "This is currently not supported", Continue);
QCOMPARE(browser->sourceInsideLoadResource.toString(), url.toString());
+ url = QUrl::fromLocalFile(QDir::current().filePath("pagewithimage.html")); // "file:///home/user/path/to/pagewithimage.html"
+ browser->setSource(url);
+ QCOMPARE(browser->lastResource, QUrl::fromLocalFile(QDir::current().filePath("foobar.png")));
+ // baseUrl has the full path, and that's where relative-path resources come from
+ QCOMPARE(browser->baseInsideLoadResource, QUrl::fromLocalFile(QDir::currentPath() + QLatin1Char('/')));
}
void tst_QTextBrowser::textInteractionFlags_vs_readOnly()
@@ -669,5 +680,46 @@ void tst_QTextBrowser::urlEncoding()
delete browser;
}
+void tst_QTextBrowser::sourceType_data()
+{
+ QTest::addColumn<QString>("sourceFile");
+ QTest::addColumn<QTextDocument::ResourceType>("sourceType");
+ QTest::addColumn<int>("expectedMaxHeadingLevel");
+ QTest::addColumn<QTextDocument::ResourceType>("expectedSourceType");
+
+#if QT_CONFIG(textmarkdownreader)
+ const int maxMdHeadingLevel = 3;
+ const QTextDocument::ResourceType mdExpectedType = QTextDocument::MarkdownResource;
+#else
+ // If Qt doesn't support markdown, and we read a MD document anyway, it won't have any H3's.
+ const int maxMdHeadingLevel = 0;
+ const QTextDocument::ResourceType mdExpectedType = QTextDocument::HtmlResource;
+#endif
+ QTest::newRow("markdown detected") << "markdown.md" << QTextDocument::UnknownResource << maxMdHeadingLevel << mdExpectedType;
+ QTest::newRow("markdown specified") << "markdown.really" << QTextDocument::MarkdownResource << maxMdHeadingLevel << mdExpectedType;
+ QTest::newRow("markdown not identified") << "markdown.really" << QTextDocument::UnknownResource << 0 << QTextDocument::HtmlResource;
+ QTest::newRow("html detected") << "heading.html" << QTextDocument::UnknownResource << 3 << QTextDocument::HtmlResource;
+ QTest::newRow("html specified") << "heading.html" << QTextDocument::HtmlResource << 3 << QTextDocument::HtmlResource;
+}
+
+void tst_QTextBrowser::sourceType()
+{
+ QFETCH(QString, sourceFile);
+ QFETCH(QTextDocument::ResourceType, sourceType);
+ QFETCH(int, expectedMaxHeadingLevel);
+ QFETCH(QTextDocument::ResourceType, expectedSourceType);
+ if (sourceType == QTextDocument::UnknownResource)
+ // verify that the property setter works, with its default parameter for sourceType
+ browser->setProperty("source", QUrl::fromLocalFile(QFINDTESTDATA(sourceFile)));
+ else
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA(sourceFile)), sourceType);
+ QCOMPARE(browser->sourceType(), expectedSourceType);
+ QTextFrame::iterator iterator = browser->document()->rootFrame()->begin();
+ int maxHeadingLevel = -1;
+ while (!iterator.atEnd())
+ maxHeadingLevel = qMax(iterator++.currentBlock().blockFormat().intProperty(QTextFormat::HeadingLevel), maxHeadingLevel);
+ QCOMPARE(maxHeadingLevel, expectedMaxHeadingLevel);
+}
+
QTEST_MAIN(tst_QTextBrowser)
#include "tst_qtextbrowser.moc"
diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
index 6a2ae4951b..81682dc027 100644
--- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
+++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
@@ -160,6 +160,7 @@ private slots:
void selectionChanged();
#ifndef QT_NO_CLIPBOARD
void copyPasteBackgroundImage();
+ void copyPasteForegroundImage();
#endif
void setText();
void cursorRect();
@@ -199,6 +200,12 @@ private slots:
void findWithRegExpReturnsFalseIfNoMoreResults();
#endif
+#if QT_CONFIG(regularexpression)
+ void findWithRegularExpression();
+ void findBackwardWithRegularExpression();
+ void findWithRegularExpressionReturnsFalseIfNoMoreResults();
+#endif
+
#if QT_CONFIG(wheelevent)
void wheelEvent();
#endif
@@ -276,12 +283,12 @@ void tst_QTextEdit::getSetCheck()
// int QTextEdit::tabStopWidth()
// void QTextEdit::setTabStopWidth(int)
- obj1.setTabStopWidth(0);
- QCOMPARE(0, obj1.tabStopWidth());
- obj1.setTabStopWidth(INT_MIN);
- QCOMPARE(0, obj1.tabStopWidth()); // Makes no sense to set a negative tabstop value
- obj1.setTabStopWidth(INT_MAX);
- QCOMPARE(INT_MAX, obj1.tabStopWidth());
+ obj1.setTabStopDistance(0);
+ QCOMPARE(0, obj1.tabStopDistance());
+ obj1.setTabStopDistance(-1);
+ QCOMPARE(0, obj1.tabStopDistance()); // Makes no sense to set a negative tabstop value
+ obj1.setTabStopDistance(std::numeric_limits<qreal>::max());
+ QCOMPARE(std::numeric_limits<qreal>::max(), obj1.tabStopDistance());
// bool QTextEdit::acceptRichText()
// void QTextEdit::setAcceptRichText(bool)
@@ -1898,6 +1905,36 @@ void tst_QTextEdit::copyPasteBackgroundImage()
ba.texture().cacheKey() == bb.texture().cacheKey());
QFile::remove(QLatin1String("foo.png"));
}
+
+void tst_QTextEdit::copyPasteForegroundImage()
+{
+ ed->clear();
+
+ QPixmap pix(20, 20);
+ pix.fill(Qt::blue);
+
+ QTextCharFormat fmt;
+ {
+ QBrush textureBrush;
+ {
+ textureBrush.setTexture(pix);
+ }
+ textureBrush.setStyle(Qt::TexturePattern);
+ fmt.setForeground(textureBrush);
+ }
+ ed->textCursor().insertText("Foobar", fmt);
+
+ ed->moveCursor(QTextCursor::Start);
+ ed->moveCursor(QTextCursor::End, QTextCursor::KeepAnchor);
+
+ ed->copy();
+ ed->clear();
+ ed->paste();
+
+ QBrush brush = ed->textCursor().charFormat().foreground();
+ QCOMPARE(brush.style(), Qt::TexturePattern);
+ QCOMPARE(brush.texture().cacheKey(), pix.cacheKey());
+}
#endif
void tst_QTextEdit::setText()
@@ -2572,6 +2609,45 @@ void tst_QTextEdit::findWithRegExpReturnsFalseIfNoMoreResults()
}
#endif
+#if QT_CONFIG(regularexpression)
+void tst_QTextEdit::findWithRegularExpression()
+{
+ ed->setHtml(QStringLiteral("arbitrary te<span style=\"color:#ff0000\">xt</span>"));
+ QRegularExpression rx("\\w{2}xt");
+
+ bool found = ed->find(rx);
+
+ QVERIFY(found);
+ QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("text"));
+}
+
+void tst_QTextEdit::findBackwardWithRegularExpression()
+{
+ ed->setPlainText(QStringLiteral("arbitrary text"));
+ QTextCursor cursor = ed->textCursor();
+ cursor.movePosition(QTextCursor::End);
+ ed->setTextCursor(cursor);
+ QRegularExpression rx("a\\w*t");
+
+ bool found = ed->find(rx, QTextDocument::FindBackward);
+
+ QVERIFY(found);
+ QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("arbit"));
+}
+
+void tst_QTextEdit::findWithRegularExpressionReturnsFalseIfNoMoreResults()
+{
+ ed->setPlainText(QStringLiteral("arbitrary text"));
+ QRegularExpression rx("t.xt");
+ ed->find(rx);
+
+ bool found = ed->find(rx);
+
+ QVERIFY(!found);
+ QCOMPARE(ed->textCursor().selectedText(), QStringLiteral("text"));
+}
+#endif
+
#if QT_CONFIG(wheelevent)
class TextEdit : public QTextEdit
diff --git a/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp b/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp
index 752e39c23f..d40c8c2fd6 100644
--- a/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp
+++ b/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp
@@ -34,6 +34,7 @@
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
+#include <QElapsedTimer>
#include <QtDebug>
#include <QtTest/QtTest>
#include <QXmlDefaultHandler>
@@ -259,7 +260,7 @@ public:
// Delibrately wait a maximum of 10 seconds for the sake
// of the test, so it doesn't unduly hang
const int waitTime = qMax(10000, msecs);
- QTime t;
+ QElapsedTimer t;
t.start();
while (t.elapsed() < waitTime) {
QCoreApplication::processEvents();
diff --git a/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp b/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp
index 15f10232bd..b5d9fea315 100644
--- a/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp
+++ b/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp
@@ -72,7 +72,7 @@ int main(int argc, const char *argv[])
QFile in_file(file_name);
if (!in_file.open(QIODevice::ReadOnly)) {
- qerr << "Could not open " << file_name << ": " << strerror(errno) << endl;
+ qerr << "Could not open " << file_name << ": " << strerror(errno) << Qt::endl;
return 1;
}
@@ -87,7 +87,7 @@ int main(int argc, const char *argv[])
} else {
_out_file.setFileName(out_file_name);
if (!_out_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- qerr << "Could not open " << out_file_name << ": " << strerror(errno) << endl;
+ qerr << "Could not open " << out_file_name << ": " << strerror(errno) << Qt::endl;
return 1;
}
_out_stream.setDevice(&_out_file);
diff --git a/tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp b/tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp
index 17351883c3..556603a681 100644
--- a/tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp
+++ b/tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp
@@ -28,7 +28,7 @@
#include <qxml.h>
-#include <qregexp.h>
+#include <qregularexpression.h>
#include "parser.h"
@@ -139,11 +139,11 @@ bool ContentHandler::startElement(const QString &namespaceURI,
QString ContentHandler::escapeStr(const QString &s)
{
QString result = s;
- result.replace(QRegExp("\""), "\\\"");
- result.replace(QRegExp("\\"), "\\\\");
- result.replace(QRegExp("\n"), "\\n");
- result.replace(QRegExp("\r"), "\\r");
- result.replace(QRegExp("\t"), "\\t");
+ result.replace(QRegularExpression("\""), "\\\"");
+ result.replace(QRegularExpression("\\"), "\\\\");
+ result.replace(QRegularExpression("\n"), "\\n");
+ result.replace(QRegularExpression("\r"), "\\r");
+ result.replace(QRegularExpression("\t"), "\\t");
return result;
}
diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak
deleted file mode 100644
index 2d80c8f3fb..0000000000
--- a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE doc [
-<!ENTITY e "&#x10000;&#x10FFFD;&#x10FFFF;">
-<!ELEMENT doc (#PCDATA)>
-]>
-<doc>&e;</doc>
diff --git a/tests/baselineserver/shared/baselineprotocol.cpp b/tests/baselineserver/shared/baselineprotocol.cpp
index c9f9cd9bd2..aa496d6c54 100644
--- a/tests/baselineserver/shared/baselineprotocol.cpp
+++ b/tests/baselineserver/shared/baselineprotocol.cpp
@@ -38,6 +38,7 @@
#include <QDir>
#include <QTime>
#include <QPointer>
+#include <QRegExp>
const QString PI_Project(QLS("Project"));
const QString PI_TestCase(QLS("TestCase"));
@@ -291,7 +292,8 @@ void ImageItem::writeImageToStream(QDataStream &out) const
out << quint8('Q') << quint8(image.format());
out << quint8(QSysInfo::ByteOrder) << quint8(0); // pad to multiple of 4 bytes
out << quint32(image.width()) << quint32(image.height()) << quint32(image.bytesPerLine());
- out << qCompress((const uchar *)image.constBits(), image.byteCount());
+ out << qCompress(reinterpret_cast<const uchar *>(image.constBits()),
+ int(image.sizeInBytes()));
//# can be followed by colormap for formats that use it
}
diff --git a/tests/benchmarks/corelib/corelib.pro b/tests/benchmarks/corelib/corelib.pro
index b5781ad49e..99af4c138f 100644
--- a/tests/benchmarks/corelib/corelib.pro
+++ b/tests/benchmarks/corelib/corelib.pro
@@ -5,6 +5,7 @@ SUBDIRS = \
mimetypes \
kernel \
thread \
+ time \
tools \
codecs \
plugin
diff --git a/tests/benchmarks/corelib/io/qfileinfo/main.cpp b/tests/benchmarks/corelib/io/qfileinfo/main.cpp
index 5180e7c29e..6cc96777a1 100644
--- a/tests/benchmarks/corelib/io/qfileinfo/main.cpp
+++ b/tests/benchmarks/corelib/io/qfileinfo/main.cpp
@@ -81,7 +81,7 @@ void qfileinfo::symLinkTargetPerformanceLNK()
QString linkTarget;
QBENCHMARK {
for(int i=0; i<100; i++)
- linkTarget = info.readLink();
+ linkTarget = info.symLinkTarget();
}
QVERIFY(QFile::remove("link.lnk"));
}
@@ -94,7 +94,9 @@ void qfileinfo::symLinkTargetPerformanceMounpoint()
QString rootVolume = QString::fromWCharArray(buffer);
QString mountpoint = "mountpoint";
rootVolume.replace("\\\\?\\","\\??\\");
- FileSystem::createNtfsJunction(rootVolume, mountpoint);
+ QString errorMessage;
+ QVERIFY2(FileSystem::createNtfsJunction(rootVolume, mountpoint, &errorMessage) == ERROR_SUCCESS,
+ qPrintable(errorMessage));
QFileInfo info(mountpoint);
info.setCaching(false);
@@ -102,7 +104,7 @@ void qfileinfo::symLinkTargetPerformanceMounpoint()
QString linkTarget;
QBENCHMARK {
for(int i=0; i<100; i++)
- linkTarget = info.readLink();
+ linkTarget = info.symLinkTarget();
}
QVERIFY(QDir().rmdir(mountpoint));
}
diff --git a/tests/benchmarks/corelib/io/qtextstream/qtextstream.pro b/tests/benchmarks/corelib/io/qtextstream/qtextstream.pro
index 758930c139..e8170319f2 100644
--- a/tests/benchmarks/corelib/io/qtextstream/qtextstream.pro
+++ b/tests/benchmarks/corelib/io/qtextstream/qtextstream.pro
@@ -1,5 +1,5 @@
TEMPLATE = app
-TARGET = tst_bench_qtemporaryfile
+TARGET = tst_bench_qtextstream
QT = core testlib
diff --git a/tests/benchmarks/corelib/kernel/kernel.pro b/tests/benchmarks/corelib/kernel/kernel.pro
index 02eeeaa254..92f7174419 100644
--- a/tests/benchmarks/corelib/kernel/kernel.pro
+++ b/tests/benchmarks/corelib/kernel/kernel.pro
@@ -5,7 +5,8 @@ SUBDIRS = \
qmetatype \
qobject \
qvariant \
- qcoreapplication
+ qcoreapplication \
+ qtimer_vs_qmetaobject
!qtHaveModule(widgets): SUBDIRS -= \
qmetaobject \
diff --git a/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp b/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp
index 66a29780f0..6af5b8d586 100644
--- a/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp
+++ b/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/tst_qtimer_vs_qmetaobject.cpp
@@ -28,6 +28,7 @@
#include <QtCore>
#include <QtTest/QtTest>
+#include <QThread>
#define INVOKE_COUNT 10000
@@ -35,8 +36,10 @@ class qtimer_vs_qmetaobject : public QObject
{
Q_OBJECT
private slots:
- void testZeroTimerSingleShot();
- void testQueuedInvokeMethod();
+ void bench();
+ void bench_data();
+ void benchBackgroundThread();
+ void benchBackgroundThread_data() { bench_data(); }
};
class InvokeCounter : public QObject {
@@ -47,36 +50,89 @@ public slots:
void invokeSlot() {
count++;
if (count == INVOKE_COUNT)
- QTestEventLoop::instance().exitLoop();
+ emit allInvoked();
}
+signals:
+ void allInvoked();
protected:
int count;
};
-void qtimer_vs_qmetaobject::testZeroTimerSingleShot()
+void qtimer_vs_qmetaobject::bench()
{
+ QFETCH(int, type);
+
+ std::function<void(InvokeCounter*)> invoke;
+ if (type == 0) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QTimer::singleShot(0, invokeCounter, SLOT(invokeSlot()));
+ };
+ } else if (type == 1) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QTimer::singleShot(0, invokeCounter, &InvokeCounter::invokeSlot);
+ };
+ } else if (type == 2) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QTimer::singleShot(0, invokeCounter, [invokeCounter]() {
+ invokeCounter->invokeSlot();
+ });
+ };
+ } else if (type == 3) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QTimer::singleShot(0, [invokeCounter]() {
+ invokeCounter->invokeSlot();
+ });
+ };
+ } else if (type == 4) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QMetaObject::invokeMethod(invokeCounter, "invokeSlot", Qt::QueuedConnection);
+ };
+ } else if (type == 5) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QMetaObject::invokeMethod(invokeCounter, &InvokeCounter::invokeSlot, Qt::QueuedConnection);
+ };
+ } else if (type == 6) {
+ invoke = [](InvokeCounter* invokeCounter) {
+ QMetaObject::invokeMethod(invokeCounter, [invokeCounter]() {
+ invokeCounter->invokeSlot();
+ }, Qt::QueuedConnection);
+ };
+ } else {
+ QFAIL("unhandled data tag");
+ }
+
QBENCHMARK {
InvokeCounter invokeCounter;
+ QSignalSpy spy(&invokeCounter, &InvokeCounter::allInvoked);
for(int i = 0; i < INVOKE_COUNT; ++i) {
- QTimer::singleShot(0, &invokeCounter, SLOT(invokeSlot()));
+ invoke(&invokeCounter);
}
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(spy.wait(10000));
}
}
-void qtimer_vs_qmetaobject::testQueuedInvokeMethod()
+void qtimer_vs_qmetaobject::bench_data()
{
- QBENCHMARK {
- InvokeCounter invokeCounter;
- for(int i = 0; i < INVOKE_COUNT; ++i) {
- QMetaObject::invokeMethod(&invokeCounter, "invokeSlot", Qt::QueuedConnection);
- }
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- }
+ QTest::addColumn<int>("type");
+ QTest::addRow("singleShot_slot") << 0;
+ QTest::addRow("singleShot_pmf") << 1;
+ QTest::addRow("singleShot_functor") << 2;
+ QTest::addRow("singleShot_functor_noctx") << 3;
+ QTest::addRow("invokeMethod_string") << 4;
+ QTest::addRow("invokeMethod_pmf") << 5;
+ QTest::addRow("invokeMethod_functor") << 6;
}
+void qtimer_vs_qmetaobject::benchBackgroundThread()
+{
+#if !QT_CONFIG(cxx11_future)
+ QSKIP("This test requires QThread::create");
+#else
+ QScopedPointer<QThread> thread(QThread::create([this]() { bench(); }));
+ thread->start();
+ QVERIFY(thread->wait());
+#endif
+}
QTEST_MAIN(qtimer_vs_qmetaobject)
diff --git a/tests/benchmarks/corelib/mimetypes/qmimedatabase/main.cpp b/tests/benchmarks/corelib/mimetypes/qmimedatabase/main.cpp
index 704119b921..1b432f3b3e 100644
--- a/tests/benchmarks/corelib/mimetypes/qmimedatabase/main.cpp
+++ b/tests/benchmarks/corelib/mimetypes/qmimedatabase/main.cpp
@@ -35,6 +35,7 @@ class tst_QMimeDatabase: public QObject
private slots:
void inheritsPerformance();
+ void benchMimeTypeForName();
};
void tst_QMimeDatabase::inheritsPerformance()
@@ -70,5 +71,15 @@ void tst_QMimeDatabase::inheritsPerformance()
// parsing XML, and then keeps being around 4.5 MB for all the in-memory hashes.
}
+void tst_QMimeDatabase::benchMimeTypeForName()
+{
+ QMimeDatabase db;
+
+ QBENCHMARK {
+ const auto s = db.mimeTypeForName(QStringLiteral("text/plain"));
+ QVERIFY(s.isValid());
+ }
+}
+
QTEST_MAIN(tst_QMimeDatabase)
#include "main.moc"
diff --git a/tests/benchmarks/corelib/time/qdate/qdate.pro b/tests/benchmarks/corelib/time/qdate/qdate.pro
new file mode 100644
index 0000000000..a655917135
--- /dev/null
+++ b/tests/benchmarks/corelib/time/qdate/qdate.pro
@@ -0,0 +1,4 @@
+TARGET = tst_bench_qdate
+QT = core testlib
+
+SOURCES += tst_bench_qdate.cpp
diff --git a/tests/benchmarks/corelib/time/qdate/tst_bench_qdate.cpp b/tests/benchmarks/corelib/time/qdate/tst_bench_qdate.cpp
new file mode 100644
index 0000000000..399ac44065
--- /dev/null
+++ b/tests/benchmarks/corelib/time/qdate/tst_bench_qdate.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDateTime>
+#include <QTest>
+
+class tst_QDate : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void monthLengths();
+};
+
+void tst_QDate::monthLengths()
+{
+ QBENCHMARK {
+ for (int year = 1900; year <= 2100; year++) {
+ bool check = true;
+ for (int month = 1; month <= 12; month++)
+ check &= QDate::isValid(year, month, QDate(year, month, 1).daysInMonth());
+ Q_UNUSED(check);
+ }
+ }
+}
+
+QTEST_MAIN(tst_QDate)
+#include "tst_bench_qdate.moc"
diff --git a/tests/benchmarks/corelib/tools/qdatetime/main.cpp b/tests/benchmarks/corelib/time/qdatetime/main.cpp
index 2c1e3d97ae..b693400376 100644
--- a/tests/benchmarks/corelib/tools/qdatetime/main.cpp
+++ b/tests/benchmarks/corelib/time/qdatetime/main.cpp
@@ -35,10 +35,7 @@ class tst_QDateTime : public QObject
{
Q_OBJECT
- enum
-#if defined(Q_COMPILER_CLASS_ENUM) || (defined(Q_CC_MSVC) && _MSC_VER >= 1700)
- : qint64
-#endif
+ enum : qint64
{
SECS_PER_DAY = 86400,
MSECS_PER_DAY = 86400000,
diff --git a/tests/benchmarks/corelib/tools/qdatetime/qdatetime.pro b/tests/benchmarks/corelib/time/qdatetime/qdatetime.pro
index a85e7346c6..a85e7346c6 100644
--- a/tests/benchmarks/corelib/tools/qdatetime/qdatetime.pro
+++ b/tests/benchmarks/corelib/time/qdatetime/qdatetime.pro
diff --git a/tests/benchmarks/corelib/tools/qtimezone/main.cpp b/tests/benchmarks/corelib/time/qtimezone/main.cpp
index 65455a7261..65455a7261 100644
--- a/tests/benchmarks/corelib/tools/qtimezone/main.cpp
+++ b/tests/benchmarks/corelib/time/qtimezone/main.cpp
diff --git a/tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro b/tests/benchmarks/corelib/time/qtimezone/qtimezone.pro
index d0531b568b..d0531b568b 100644
--- a/tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro
+++ b/tests/benchmarks/corelib/time/qtimezone/qtimezone.pro
diff --git a/tests/benchmarks/corelib/time/time.pro b/tests/benchmarks/corelib/time/time.pro
new file mode 100644
index 0000000000..b5184845d9
--- /dev/null
+++ b/tests/benchmarks/corelib/time/time.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ qdate \
+ qdatetime \
+ qtimezone
diff --git a/tests/benchmarks/corelib/tools/qmap/qmap.pro b/tests/benchmarks/corelib/tools/qmap/qmap.pro
index 6a0c8d62bd..6c9bf5e8d6 100644
--- a/tests/benchmarks/corelib/tools/qmap/qmap.pro
+++ b/tests/benchmarks/corelib/tools/qmap/qmap.pro
@@ -1,4 +1,4 @@
-TARGET = tst_qmap
+TARGET = tst_bench_qmap
QT = core testlib
INCLUDEPATH += .
SOURCES += main.cpp
diff --git a/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp b/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp
index d0dfe3b1a7..0de6d33846 100644
--- a/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp
+++ b/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp
@@ -401,7 +401,7 @@ private slots:
}
private:
- const QLatin1Literal l1literal;
+ const QLatin1String l1literal;
const QLatin1String l1string;
const QByteArray ba;
const QString string;
diff --git a/tests/benchmarks/corelib/tools/tools.pro b/tests/benchmarks/corelib/tools/tools.pro
index ca9c0a6f89..33cbe00438 100644
--- a/tests/benchmarks/corelib/tools/tools.pro
+++ b/tests/benchmarks/corelib/tools/tools.pro
@@ -5,7 +5,6 @@ SUBDIRS = \
qbytearray \
qcontiguouscache \
qcryptographichash \
- qdatetime \
qlist \
qlocale \
qmap \
@@ -15,7 +14,6 @@ SUBDIRS = \
qstring \
qstringbuilder \
qstringlist \
- qtimezone \
qvector \
qalgorithms
diff --git a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp
index e0f69bee11..570c7b59fa 100644
--- a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp
+++ b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp
@@ -200,6 +200,8 @@ void tst_QImageConversion::convertRgb32_data()
QTest::newRow("argb32 -> argb8565pm") << argb32 << QImage::Format_ARGB8565_Premultiplied;
QTest::newRow("argb32 -> argb4444pm") << argb32 << QImage::Format_ARGB4444_Premultiplied;
QTest::newRow("argb32 -> argb6666pm") << argb32 << QImage::Format_ARGB6666_Premultiplied;
+ QTest::newRow("argb32 -> rgba64") << argb32 << QImage::Format_RGBA64;
+ QTest::newRow("argb32 -> rgba64pm") << argb32 << QImage::Format_RGBA64_Premultiplied;
QTest::newRow("argb32pm -> rgb16") << argb32pm << QImage::Format_RGB16;
QTest::newRow("argb32pm -> rgb32") << argb32pm << QImage::Format_RGB32;
@@ -239,6 +241,7 @@ void tst_QImageConversion::convertGeneric_data()
QImage a2rgb30 = argb32.convertToFormat(QImage::Format_A2RGB30_Premultiplied);
QImage rgb666 = rgb32.convertToFormat(QImage::Format_RGB666);
QImage argb4444 = argb32.convertToFormat(QImage::Format_ARGB4444_Premultiplied);
+ QImage rgba64pm = argb32.convertToFormat(QImage::Format_RGBA64_Premultiplied);
QTest::newRow("indexed8 -> rgb32") << i8 << QImage::Format_RGB32;
QTest::newRow("indexed8 -> argb32") << i8 << QImage::Format_ARGB32;
@@ -289,6 +292,13 @@ void tst_QImageConversion::convertGeneric_data()
QTest::newRow("argb4444pm -> rgba8888pm") << argb4444 << QImage::Format_RGBA8888_Premultiplied;
QTest::newRow("argb4444pm -> rgb30") << argb4444 << QImage::Format_RGB30;
QTest::newRow("argb4444pm -> a2bgr30") << argb4444 << QImage::Format_A2BGR30_Premultiplied;
+
+ QTest::newRow("rgba64pm -> argb32") << rgba64pm << QImage::Format_ARGB32;
+ QTest::newRow("rgba64pm -> rgbx8888") << rgba64pm << QImage::Format_RGBX8888;
+ QTest::newRow("rgba64pm -> rgba8888pm") << rgba64pm << QImage::Format_RGBA8888_Premultiplied;
+ QTest::newRow("rgba64pm -> rgb30") << rgba64pm << QImage::Format_RGB30;
+ QTest::newRow("rgba64pm -> a2bgr30") << rgba64pm << QImage::Format_A2BGR30_Premultiplied;
+ QTest::newRow("rgba64pm -> rgba64") << rgba64pm << QImage::Format_RGBA64;
}
void tst_QImageConversion::convertGeneric()
@@ -347,10 +357,10 @@ void tst_QImageConversion::convertGenericInplace()
QFETCH(QImage::Format, outputFormat);
QImage::Format inputFormat = inputImage.format();
- QImage tmpImage = qMove(inputImage);
+ QImage tmpImage = std::move(inputImage);
QBENCHMARK {
- tmpImage = (qMove(tmpImage).convertToFormat(outputFormat)).convertToFormat(inputFormat);
+ tmpImage = (std::move(tmpImage).convertToFormat(outputFormat)).convertToFormat(inputFormat);
}
}
diff --git a/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp b/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp
index d7a7f383ac..12e85d4842 100644
--- a/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp
+++ b/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp
@@ -167,9 +167,7 @@ void tst_QTransform::func##_data() \
{ \
QTest::addColumn<QTransform>("transform"); \
QMap<const char *, QTransform> x = generateTransforms(); \
- QMapIterator<const char *, QTransform> it(x); \
- while (it.hasNext()) { \
- it.next(); \
+ for (auto it = x.begin(), end = x.end(); it != end; ++it) { \
QTest::newRow(it.key()) << it.value(); \
} \
}
@@ -180,14 +178,10 @@ void tst_QTransform::func##_data() \
QTest::addColumn<QTransform>("x1"); \
QTest::addColumn<QTransform>("x2"); \
QMap<const char *, QTransform> x = generateTransforms(); \
- QMapIterator<const char *, QTransform> it(x); \
- while (it.hasNext()) { \
- it.next(); \
+ for (auto it = x.cbegin(), end = x.cend(); it != end; ++it) { \
const char *key1 = it.key(); \
QTransform x1 = it.value(); \
- QMapIterator<const char *, QTransform> it2(x); \
- while (it2.hasNext()) { \
- it2.next(); \
+ for (auto it2 = x.cbegin(), end = x.cend(); it2 != end; ++it2) { \
QTest::newRow(QString("%1 + %2").arg(key1).arg(it2.key()).toLatin1().constData()) \
<< x1 << it2.value(); \
} \
diff --git a/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp
index c8ccb60dbb..8f7736010d 100644
--- a/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp
@@ -270,7 +270,6 @@ void MainView::construct()
// Turn off automatic background
setAttribute(Qt::WA_OpaquePaintEvent);
- setAttribute(Qt::WA_NoBackground);
setAttribute(Qt::WA_NoSystemBackground);
setAutoFillBackground(false);
diff --git a/tests/benchmarks/widgets/itemviews/itemviews.pro b/tests/benchmarks/widgets/itemviews/itemviews.pro
index a23cdf7b97..0c3256f307 100644
--- a/tests/benchmarks/widgets/itemviews/itemviews.pro
+++ b/tests/benchmarks/widgets/itemviews/itemviews.pro
@@ -1,4 +1,5 @@
TEMPLATE = subdirs
SUBDIRS = \
qtableview \
- qheaderview
+ qheaderview \
+ qlistview
diff --git a/tests/benchmarks/widgets/itemviews/qlistview/qlistview.pro b/tests/benchmarks/widgets/itemviews/qlistview/qlistview.pro
new file mode 100644
index 0000000000..68537d09ea
--- /dev/null
+++ b/tests/benchmarks/widgets/itemviews/qlistview/qlistview.pro
@@ -0,0 +1,7 @@
+QT += widgets testlib
+
+TEMPLATE = app
+TARGET = tst_bench_qlistview
+
+SOURCES += tst_qlistview.cpp
+
diff --git a/tests/auto/testlib/selftests/alive/tst_alive.cpp b/tests/benchmarks/widgets/itemviews/qlistview/tst_qlistview.cpp
index eeb77b18c0..01496743c2 100644
--- a/tests/auto/testlib/selftests/alive/tst_alive.cpp
+++ b/tests/benchmarks/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -26,59 +26,43 @@
**
****************************************************************************/
+#include <qtest.h>
+#include <QListView>
+#include <QStandardItemModel>
-#include <QtTest/QtTest>
-#include <QWidget>
-#include "qtestalive.cpp"
-
-class tst_Alive: public QObject
+class tst_QListView : public QObject
{
Q_OBJECT
+public:
+ tst_QListView() = default;
+ virtual ~tst_QListView() = default;
+
private slots:
- void alive();
- void addMouseDClick() const;
+ void benchSetCurrentIndex();
};
-void tst_Alive::alive()
+void tst_QListView::benchSetCurrentIndex()
{
- QTestAlive a;
- a.start();
+ QStandardItemModel sm(50000, 1);
+ QListView lv;
+ lv.setModel(&sm);
+ const int rc = lv.model()->rowCount();
+ for (int i = 0; i < rc; i+= 100)
+ lv.setRowHidden(i, true);
+ lv.setCurrentIndex(lv.model()->index(0, 0, QModelIndex()));
+ lv.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&lv));
- sleep(5);
- QCoreApplication::processEvents();
- qDebug("CUT");
- sleep(5);
+ QBENCHMARK_ONCE {
+ while (lv.currentIndex().row() < rc - 20)
+ lv.setCurrentIndex(lv.model()->index(lv.currentIndex().row() + 17,
+ lv.currentIndex().column(),
+ QModelIndex()));
+ }
}
-void tst_Alive::addMouseDClick() const
-{
- class DClickListener : public QWidget
- {
- public:
- DClickListener() : isTested(false)
- {
- }
-
- bool isTested;
- protected:
- virtual void mouseDoubleClickEvent(QMouseEvent * event)
- {
- isTested = true;
- QCOMPARE(event->type(), QEvent::MouseButtonDblClick);
- }
- };
-
- DClickListener listener;
-
- QTestEventList list;
- list.addMouseDClick(Qt::LeftButton);
-
- list.simulate(&listener);
- /* Check that we have been called at all. */
- QVERIFY(listener.isTested);
-}
-QTEST_MAIN(tst_Alive)
-#include "tst_alive.moc"
+QTEST_MAIN(tst_QListView)
+#include "tst_qlistview.moc"
diff --git a/tests/libfuzzer/README b/tests/libfuzzer/README
new file mode 100644
index 0000000000..7327e76eff
--- /dev/null
+++ b/tests/libfuzzer/README
@@ -0,0 +1,39 @@
+This directory contains tests to be run with clang's libFuzzer. It will generate data, pass this
+data to the function
+
+ LLVMFuzzerTestOneInput(const char *Data, size_t Size)
+
+of the test and track the code execution. Should the test crash, libFuzzer will provide you with the
+data which triggered the crash. You can then use this to debug and fix the called code.
+
+! Please note: The purpose of fuzz testing is to find unexpected code paths. Running fuzz tests may!
+! result in unforeseen bevavior, including loss of data. Consider running the tests in an isolated !
+! environment, e.g. on a virtual machine. You have been warned. !
+
+To run a test with libFuzzer:
+
+1. Install clang 5.0 or later, e.g. from the repositories of the Linux distribution you are using.
+ Depending on the version of clang and the source you are installing from, you might have to
+ install libFuzzer for this version of clang explicitly.
+2. Make sure clang and clang++ from this version of clang are found in PATH.
+3. Configure Qt with
+ -platform linux-clang -coverage trace-pc-guard
+ to add the needed code coverage instrumentation. Since speed of execution is crucial for fuzz
+ testing, it's recommendable to also use the switches
+ -release -static
+ It might also make sense to add sanitzers by passing
+ -sanitize <...>
+4. Build Qt.
+5. Build one of the tests using this Qt build.
+6. Execute the resulting executable.
+ Depending on the expected input format of the tested function, you will get results faster if
+ you:
+ * provide a set of interesting input data by passing the path of a directory which contains
+ these data, each in one file. You can find such datasets in the subdirectory "testcases".
+ * pass a so-called dictionary listing keywords of the input format using
+ -dict=<dictionary file>
+ A couple of such dictionaries are provided by AFL (http://lcamtuf.coredump.cx/afl/)
+ * tell libFuzzer to generate only ASCII data using
+ -only_ascii=1
+
+For further info, see https://llvm.org/docs/LibFuzzer.html
diff --git a/tests/libfuzzer/corelib/serialization/qxmlstream/qxmlstreamreader/readnext/main.cpp b/tests/libfuzzer/corelib/serialization/qxmlstream/qxmlstreamreader/readnext/main.cpp
new file mode 100644
index 0000000000..5a60c78cb5
--- /dev/null
+++ b/tests/libfuzzer/corelib/serialization/qxmlstream/qxmlstreamreader/readnext/main.cpp
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QXmlStreamReader>
+
+extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size) {
+ QXmlStreamReader reader(QByteArray(Data, Size));
+ while (!reader.atEnd())
+ reader.readNext();
+ return 0;
+}
diff --git a/tests/libfuzzer/corelib/serialization/qxmlstream/qxmlstreamreader/readnext/readnext.pro b/tests/libfuzzer/corelib/serialization/qxmlstream/qxmlstreamreader/readnext/readnext.pro
new file mode 100644
index 0000000000..2fda3ecefd
--- /dev/null
+++ b/tests/libfuzzer/corelib/serialization/qxmlstream/qxmlstreamreader/readnext/readnext.pro
@@ -0,0 +1,5 @@
+QT -= gui
+CONFIG += console
+CONFIG -= app_bundle
+SOURCES += main.cpp
+LIBS += -fsanitize=fuzzer
diff --git a/tests/libfuzzer/gui/text/qtextdocument/setHtml/main.cpp b/tests/libfuzzer/gui/text/qtextdocument/setHtml/main.cpp
new file mode 100644
index 0000000000..c9b33d0f88
--- /dev/null
+++ b/tests/libfuzzer/gui/text/qtextdocument/setHtml/main.cpp
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QTextDocument>
+
+extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size) {
+ static int c = 0;
+ static QApplication a(c, nullptr);
+ QTextDocument().setHtml(QByteArray(Data, Size));
+ return 0;
+}
diff --git a/tests/libfuzzer/gui/text/qtextdocument/setHtml/setHtml.pro b/tests/libfuzzer/gui/text/qtextdocument/setHtml/setHtml.pro
new file mode 100644
index 0000000000..c9b14f6caf
--- /dev/null
+++ b/tests/libfuzzer/gui/text/qtextdocument/setHtml/setHtml.pro
@@ -0,0 +1,3 @@
+QT += widgets
+SOURCES += main.cpp
+LIBS += -fsanitize=fuzzer
diff --git a/tests/manual/diaglib/diaglib.pri b/tests/manual/diaglib/diaglib.pri
index 9f10167136..b57ee75841 100644
--- a/tests/manual/diaglib/diaglib.pri
+++ b/tests/manual/diaglib/diaglib.pri
@@ -12,7 +12,7 @@ HEADERS += \
win32:!winrt: {
SOURCES += $$PWD/nativewindowdump_win.cpp
- LIBS *= -luser32
+ QMAKE_USE += user32
} else {
SOURCES += $$PWD/nativewindowdump.cpp
}
diff --git a/tests/manual/dialogs/filedialogpanel.cpp b/tests/manual/dialogs/filedialogpanel.cpp
index 62d03e735d..25c1e44b8c 100644
--- a/tests/manual/dialogs/filedialogpanel.cpp
+++ b/tests/manual/dialogs/filedialogpanel.cpp
@@ -438,9 +438,9 @@ void FileDialogPanel::restoreDefaults()
setComboBoxValue(m_viewMode, d.viewMode());
m_showDirsOnly->setChecked(d.testOption(QFileDialog::ShowDirsOnly));
m_allowedSchemes->setText(QString());
- m_confirmOverWrite->setChecked(d.confirmOverwrite());
- m_nameFilterDetailsVisible->setChecked(d.isNameFilterDetailsVisible());
- m_resolveSymLinks->setChecked(d.resolveSymlinks());
+ m_confirmOverWrite->setChecked(!d.testOption(QFileDialog::DontConfirmOverwrite));
+ m_nameFilterDetailsVisible->setChecked(!d.testOption(QFileDialog::HideNameFilterDetails));
+ m_resolveSymLinks->setChecked(!d.testOption(QFileDialog::DontResolveSymlinks));
m_readOnly->setChecked(d.isReadOnly());
m_native->setChecked(true);
m_customDirIcons->setChecked(d.testOption(QFileDialog::DontUseCustomDirectoryIcons));
diff --git a/tests/manual/dialogs/printdialogpanel.cpp b/tests/manual/dialogs/printdialogpanel.cpp
index d999dbc30c..8d64d2f6a6 100644
--- a/tests/manual/dialogs/printdialogpanel.cpp
+++ b/tests/manual/dialogs/printdialogpanel.cpp
@@ -55,6 +55,10 @@
#include <QTextStream>
#include <QDir>
+#if QT_VERSION >= 0x050000
+# include <QScreen>
+#endif
+
const FlagData printerModeComboData[] =
{
{"ScreenResolution", QPrinter::ScreenResolution},
@@ -705,7 +709,13 @@ void PrintDialogPanel::showPreviewDialog()
{
applySettings(m_printer.data());
PrintPreviewDialog dialog(m_printer.data(), this);
- dialog.resize(QApplication::desktop()->availableGeometry().size() * 4/ 5);
+#if QT_VERSION >= 0x050000
+ const int screenNumber = QApplication::desktop()->screenNumber(this);
+ const QSize availableSize = QGuiApplication::screens().at(screenNumber)->availableSize();
+#else
+ const QSize availableSize = QApplication::desktop()->availableGeometry().size();
+#endif
+ dialog.resize(availableSize * 4/ 5);
if (dialog.exec() == QDialog::Accepted)
retrieveSettings(m_printer.data());
}
diff --git a/tests/manual/foreignwindows/main.cpp b/tests/manual/foreignwindows/main.cpp
index 74c6d8c376..44aff54773 100644
--- a/tests/manual/foreignwindows/main.cpp
+++ b/tests/manual/foreignwindows/main.cpp
@@ -195,6 +195,9 @@ static QString description(const QString &appName)
"tests embedding foreign windows into Qt.\n\nUse cases:\n\n"
<< appName << " -a Dump a list of all native window ids.\n"
<< appName << " <winid> Dump information on the window.\n"
+ << appName << " -m <winid> Move window to top left corner\n"
+ << QByteArray(appName.size(), ' ')
+ << " (recover lost windows after changing monitor setups).\n"
<< appName << " -c <winid> Dump information on the window continuously.\n"
<< appName << " -e <winid> Embed window into a Qt widget.\n"
<< "\nOn Windows, class names of well known controls (EDIT, BUTTON...) can be\n"
@@ -245,6 +248,10 @@ int main(int argc, char *argv[])
parser.addOption(outputAllOption);
QCommandLineOption continuousOption(QStringList() << QStringLiteral("c") << QStringLiteral("continuous"),
QStringLiteral("Output continuously."));
+ parser.addOption(outputAllOption);
+ QCommandLineOption moveOption(QStringList() << QStringLiteral("m") << QStringLiteral("move"),
+ QStringLiteral("Move window to top left corner."));
+ parser.addOption(moveOption);
parser.addOption(continuousOption);
QCommandLineOption embedOption(QStringList() << QStringLiteral("e") << QStringLiteral("embed"),
QStringLiteral("Embed a foreign window into a Qt widget."));
@@ -274,8 +281,12 @@ int main(int argc, char *argv[])
return -1;
}
QWindow *foreignWindow = QWindow::fromWinId(wid);
+ if (!foreignWindow)
+ return -1;
foreignWindow->setObjectName("ForeignWindow" + QString::number(wid, 16));
windows.append(foreignWindow);
+ if (parser.isSet(moveOption))
+ foreignWindow->setFramePosition(QGuiApplication::primaryScreen()->availableGeometry().topLeft());
}
if (windows.isEmpty())
diff --git a/tests/manual/highdpi/dragwidget.cpp b/tests/manual/highdpi/dragwidget.cpp
index 46a8ea8090..11bbc1d127 100644
--- a/tests/manual/highdpi/dragwidget.cpp
+++ b/tests/manual/highdpi/dragwidget.cpp
@@ -110,7 +110,7 @@ void DragWidget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasText()) {
const QMimeData *mime = event->mimeData();
- QStringList pieces = mime->text().split(QRegExp("\\s+"),
+ QStringList pieces = mime->text().split(QRegularExpression("\\s+"),
QString::SkipEmptyParts);
QPoint position = event->pos();
QPoint hotSpot;
diff --git a/tests/manual/lance/interactivewidget.cpp b/tests/manual/lance/interactivewidget.cpp
index 8ac3881af7..d172fac900 100644
--- a/tests/manual/lance/interactivewidget.cpp
+++ b/tests/manual/lance/interactivewidget.cpp
@@ -45,7 +45,7 @@ InteractiveWidget::InteractiveWidget()
// create and populate the command toolbox
m_commandsToolBox = new QToolBox();
- QListWidget *currentListWidget = 0;
+ QListWidget *currentListWidget = nullptr;
foreach (PaintCommands::PaintCommandInfos paintCommandInfo, PaintCommands::s_commandInfoTable) {
if (paintCommandInfo.isSectionHeader()) {
currentListWidget = new QListWidget();
diff --git a/tests/manual/lance/main.cpp b/tests/manual/lance/main.cpp
index 749a4b1943..7f5af2d908 100644
--- a/tests/manual/lance/main.cpp
+++ b/tests/manual/lance/main.cpp
@@ -185,7 +185,7 @@ static void displayCommands()
" pixmap_load filename name_in_script\n"
" image_load filename name_in_script\n");
}
-static InteractiveWidget *interactive_widget = 0;
+static InteractiveWidget *interactive_widget = nullptr;
static void runInteractive()
{
@@ -350,15 +350,15 @@ int main(int argc, char **argv)
#endif
}
}
- scaledWidth = width * scalefactor;
- scaledHeight = height * scalefactor;
+ scaledWidth = int(width * scalefactor);
+ scaledHeight = int(height * scalefactor);
PaintCommands pcmd(QStringList(), 800, 800, imageFormat);
pcmd.setVerboseMode(verboseMode);
pcmd.setType(type);
pcmd.setCheckersBackground(checkers_background);
- QWidget *activeWidget = 0;
+ QWidget *activeWidget = nullptr;
if (interactive) {
runInteractive();
@@ -610,7 +610,7 @@ int main(int argc, char **argv)
QPrinter p(highres ? QPrinter::HighResolution : QPrinter::ScreenResolution);
if (printdlg) {
- QPrintDialog printDialog(&p, 0);
+ QPrintDialog printDialog(&p, nullptr);
if (printDialog.exec() != QDialog::Accepted)
break;
} else {
diff --git a/tests/manual/lance/widgets.h b/tests/manual/lance/widgets.h
index 583d9e2455..46c55f4c16 100644
--- a/tests/manual/lance/widgets.h
+++ b/tests/manual/lance/widgets.h
@@ -45,31 +45,12 @@
#include <QPaintEngine>
#include <QSignalMapper>
#include <QAction>
+#include <QDebug>
#include <qmath.h>
const int CP_RADIUS = 10;
-class StupidWorkaround : public QObject
-{
- Q_OBJECT
-public:
- StupidWorkaround(QWidget *widget, int *value)
- : QObject(widget), w(widget), mode(value)
- {
- }
-
-public slots:
- void setViewMode(int m) {
- *mode = m;
- w->update();
- }
-
-private:
- QWidget *w;
- int *mode;
-};
-
template <class T>
class OnScreenWidget : public T
{
@@ -81,7 +62,7 @@ public:
DifferenceView
};
- OnScreenWidget(const QString &file, QWidget *parent = 0)
+ OnScreenWidget(const QString &file, QWidget *parent = nullptr)
: T(parent),
m_filename(file),
m_view_mode(RenderView)
@@ -108,33 +89,20 @@ public:
} else {
T::setWindowTitle("Rendering: '" + file + "'. Shortcuts: 1=render, 2=baseline, 3=difference");
- StupidWorkaround *workaround = new StupidWorkaround(this, &m_view_mode);
-
- QSignalMapper *mapper = new QSignalMapper(this);
- T::connect(mapper, SIGNAL(mapped(int)), workaround, SLOT(setViewMode(int)));
- T::connect(mapper, SIGNAL(mapped(QString)), this, SLOT(setWindowTitle(QString)));
-
QAction *renderViewAction = new QAction("Render View", this);
renderViewAction->setShortcut(Qt::Key_1);
- T::connect(renderViewAction, SIGNAL(triggered()), mapper, SLOT(map()));
- mapper->setMapping(renderViewAction, RenderView);
- mapper->setMapping(renderViewAction, "Render View: " + file);
+ T::connect(renderViewAction, &QAction::triggered, [&] { setMode(RenderView); });
T::addAction(renderViewAction);
QAction *baselineAction = new QAction("Baseline", this);
baselineAction->setShortcut(Qt::Key_2);
- T::connect(baselineAction, SIGNAL(triggered()), mapper, SLOT(map()));
- mapper->setMapping(baselineAction, BaselineView);
- mapper->setMapping(baselineAction, "Baseline View: " + file);
+ T::connect(baselineAction, &QAction::triggered, [&] { setMode(BaselineView); });
T::addAction(baselineAction);
- QAction *differenceAction = new QAction("Differenfe View", this);
+ QAction *differenceAction = new QAction("Difference View", this);
differenceAction->setShortcut(Qt::Key_3);
- T::connect(differenceAction, SIGNAL(triggered()), mapper, SLOT(map()));
- mapper->setMapping(differenceAction, DifferenceView);
- mapper->setMapping(differenceAction, "Difference View" + file);
+ T::connect(differenceAction, &QAction::triggered, [&] { setMode(DifferenceView); });
T::addAction(differenceAction);
-
}
}
@@ -148,6 +116,18 @@ public:
settings.sync();
}
+ void setMode(ViewMode mode) {
+ m_view_mode = mode;
+ QString title;
+ switch (m_view_mode) {
+ case RenderView: title = "Render"; break;
+ case BaselineView: title = "Baseline"; break;
+ case DifferenceView: title = "Difference"; break;
+ }
+ T::setWindowTitle(title + " View: " + m_filename);
+ T::update();
+ }
+
void setVerboseMode(bool v) { m_verboseMode = v; }
void setCheckersBackground(bool b) { m_checkersBackground = b; }
void setType(DeviceType t) { m_deviceType = t; }
@@ -205,7 +185,7 @@ public:
pt.begin(this);
pt.setRenderHint(QPainter::Antialiasing);
pt.setFont(this->font());
- pt.resetMatrix();
+ pt.resetTransform();
pt.setPen(QColor(127, 127, 127, 191));
pt.setBrush(QColor(191, 191, 255, 63));
for (int i=0; i<m_controlPoints.size(); ++i) {
@@ -239,7 +219,7 @@ public:
p.drawPixmap(0, 0, m_baseline);
- p.setPen(QColor::fromRgb(0, 0, 0, 0.1));
+ p.setPen(QColor::fromRgbF(0, 0, 0, 0.1));
p.setFont(QFont("Arial", 128));
p.rotate(45);
p.drawText(100, 0, "BASELINE");
@@ -251,7 +231,7 @@ public:
img.fill(0);
QPainter p(&img);
- p.drawPixmap(0, 0, m_render_view);
+ p.drawImage(0, 0, m_image);
p.setCompositionMode(QPainter::RasterOp_SourceXorDestination);
p.drawPixmap(0, 0, m_baseline);
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index ab00a5ef60..63c8eb6538 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -53,7 +53,8 @@ shortcuts \
dialogs \
windowtransparency \
unc \
-qtabbar
+qtabbar \
+rhi
!qtConfig(openssl): SUBDIRS -= qssloptions
diff --git a/tests/manual/markdown/html2md.cpp b/tests/manual/markdown/html2md.cpp
new file mode 100644
index 0000000000..19d6ff06af
--- /dev/null
+++ b/tests/manual/markdown/html2md.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2019 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the test suite of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and The Qt Company. For licensing terms
+ ** and conditions see https://www.qt.io/terms-conditions. For further
+ ** information use the contact form at https://www.qt.io/contact-us.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3 as published by the Free Software
+ ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+ ** included in the packaging of this file. Please review the following
+ ** information to ensure the GNU General Public License requirements will
+ ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include <QCommandLineParser>
+#include <QDebug>
+#include <QFile>
+#include <QGuiApplication>
+#include <QTextDocument>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+ QGuiApplication::setApplicationVersion(QT_VERSION_STR);
+ QCommandLineParser parser;
+ parser.setApplicationDescription("Converts the Qt-supported subset of HTML to Markdown.");
+ parser.addHelpOption();
+ parser.addVersionOption();
+ parser.addPositionalArgument(QGuiApplication::translate("main", "input"),
+ QGuiApplication::translate("main", "input file"));
+ parser.addPositionalArgument(QGuiApplication::translate("main", "output"),
+ QGuiApplication::translate("main", "output file"));
+ parser.process(app);
+ if (parser.positionalArguments().count() != 2)
+ parser.showHelp(1);
+
+ QFile inFile(parser.positionalArguments().first());
+ if (!inFile.open(QIODevice::ReadOnly)) {
+ qFatal("failed to open %s for reading", parser.positionalArguments().first().toLocal8Bit().data());
+ exit(2);
+ }
+ QFile outFile(parser.positionalArguments().at(1));
+ if (!outFile.open(QIODevice::WriteOnly)) {
+ qFatal("failed to open %s for writing", parser.positionalArguments().at(1).toLocal8Bit().data());
+ exit(2);
+ }
+ QTextDocument doc;
+ doc.setHtml(QString::fromUtf8(inFile.readAll()));
+ outFile.write(doc.toMarkdown().toUtf8());
+}
diff --git a/tests/manual/markdown/html2md.pro b/tests/manual/markdown/html2md.pro
new file mode 100644
index 0000000000..4d6254e5a0
--- /dev/null
+++ b/tests/manual/markdown/html2md.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+TARGET = html2md
+INCLUDEPATH += .
+#QT += gui-private
+SOURCES += html2md.cpp
+
diff --git a/tests/manual/qcursor/grab_override/mainwindow.cpp b/tests/manual/qcursor/grab_override/mainwindow.cpp
index d2b7311846..087ee8d1d8 100644
--- a/tests/manual/qcursor/grab_override/mainwindow.cpp
+++ b/tests/manual/qcursor/grab_override/mainwindow.cpp
@@ -79,10 +79,10 @@ void MainWindow::toggleOverrideCursor()
{
switch (override) {
case 0:
- QApplication::setOverrideCursor(Qt::BusyCursor);
+ QGuiApplication::setOverrideCursor(Qt::BusyCursor);
break;
case 1:
- QApplication::restoreOverrideCursor();
+ QGuiApplication::restoreOverrideCursor();
break;
case 2:
ui->label->grabMouse(Qt::ForbiddenCursor);
diff --git a/tests/manual/qsslsocket/main.cpp b/tests/manual/qsslsocket/main.cpp
index b2cc1b5f23..58da520c07 100644
--- a/tests/manual/qsslsocket/main.cpp
+++ b/tests/manual/qsslsocket/main.cpp
@@ -91,21 +91,21 @@ void tst_QSslSocket::nextProtocolNegotiation_data()
<< QSslConfiguration::NextProtocolNegotiationNegotiated;
tag = host.toLocal8Bit();
- tag.append("-spdy/3");
+ tag.append("-h2");
QTest::newRow(tag)
<< true
<< host
- << (QList<QByteArray>() << QSslConfiguration::NextProtocolSpdy3_0)
- << QByteArray(QSslConfiguration::NextProtocolSpdy3_0)
+ << (QList<QByteArray>() << QSslConfiguration::ALPNProtocolHTTP2)
+ << QByteArray(QSslConfiguration::ALPNProtocolHTTP2)
<< QSslConfiguration::NextProtocolNegotiationNegotiated;
tag = host.toLocal8Bit();
- tag.append("-spdy/3-and-http/1.1");
+ tag.append("-h2-and-http/1.1");
QTest::newRow(tag)
<< true
<< host
- << (QList<QByteArray>() << QSslConfiguration::NextProtocolSpdy3_0 << QSslConfiguration::NextProtocolHttp1_1)
- << QByteArray(QSslConfiguration::NextProtocolSpdy3_0)
+ << (QList<QByteArray>() << QSslConfiguration::ALPNProtocolHTTP2 << QSslConfiguration::NextProtocolHttp1_1)
+ << QByteArray(QSslConfiguration::ALPNProtocolHTTP2)
<< QSslConfiguration::NextProtocolNegotiationNegotiated;
}
}
diff --git a/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.cpp b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.cpp
new file mode 100644
index 0000000000..d50e183096
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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/examplefw.h"
+#include "../shared/cube.h"
+#include "../shared/dds_bc1.h"
+
+struct {
+ QRhiBuffer *vbuf = nullptr;
+ bool vbufReady = false;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+
+ float rotation = 0;
+
+ QByteArrayList compressedData;
+} d;
+
+void Window::customInit()
+{
+ if (!m_r->isTextureFormatSupported(QRhiTexture::BC1))
+ qFatal("This backend does not support BC1");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ d.vbuf->build();
+ d.vbufReady = false;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+
+ QSize imageSize;
+ d.compressedData = loadBC1(QLatin1String(":/qt256_bc1_9mips.dds"), &imageSize);
+ qDebug() << d.compressedData.count() << imageSize << m_r->mipLevelsForSize(imageSize);
+
+ d.tex = m_r->newTexture(QRhiTexture::BC1, imageSize, 1, QRhiTexture::MipMapped);
+ d.tex->build();
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ d.ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ d.ps->setCullMode(QRhiGraphicsPipeline::Back);
+ d.ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ const QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ d.ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, vs },
+ { QRhiGraphicsShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+
+ d.ps->build();
+}
+
+void Window::customRelease()
+{
+ delete d.ps;
+ d.ps = nullptr;
+
+ delete d.srb;
+ d.srb = nullptr;
+
+ delete d.ubuf;
+ d.ubuf = nullptr;
+
+ delete d.vbuf;
+ d.vbuf = nullptr;
+
+ delete d.sampler;
+ d.sampler = nullptr;
+
+ delete d.tex;
+ d.tex = nullptr;
+}
+
+void Window::customRender()
+{
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (!d.vbufReady) {
+ d.vbufReady = true;
+ u->uploadStaticBuffer(d.vbuf, cube);
+ qint32 flip = 0;
+ u->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+ }
+ if (!d.compressedData.isEmpty()) {
+ QRhiTextureUploadDescription desc;
+ for (int i = 0; i < d.compressedData.count(); ++i) {
+ QRhiTextureSubresourceUploadDescription image(d.compressedData[i].constData(), d.compressedData[i].size());
+ desc.append({ 0, i, image });
+ }
+ u->uploadTexture(d.tex, desc);
+ d.compressedData.clear();
+ }
+ d.rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(0.5f);
+ mvp.rotate(d.rotation, 0, 1, 0);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { d.vbuf, 0 },
+ { d.vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.pro b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.pro
new file mode 100644
index 0000000000..d185aa6b9a
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ compressedtexture_bc1.cpp
+
+RESOURCES = compressedtexture_bc1.qrc
diff --git a/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.qrc b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.qrc
new file mode 100644
index 0000000000..a83259a7d3
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1/compressedtexture_bc1.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="qt256_bc1_9mips.dds">../shared/qt256_bc1_9mips.dds</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.cpp b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.cpp
new file mode 100644
index 0000000000..7ae5dd0d73
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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/examplefw.h"
+#include "../shared/cube.h"
+#include "../shared/dds_bc1.h"
+
+struct {
+ QRhiBuffer *vbuf = nullptr;
+ bool vbufReady = false;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+
+ float rotation = 0;
+
+ QByteArrayList compressedData;
+ QByteArrayList compressedData2;
+} d;
+
+void Window::customInit()
+{
+ if (!m_r->isTextureFormatSupported(QRhiTexture::BC1))
+ qFatal("This backend does not support BC1");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ d.vbuf->build();
+ d.vbufReady = false;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+
+ QSize imageSize;
+ d.compressedData = loadBC1(QLatin1String(":/qt256_bc1_9mips.dds"), &imageSize);
+ Q_ASSERT(imageSize == QSize(256, 256));
+
+ d.tex = m_r->newTexture(QRhiTexture::BC1, imageSize);
+ d.tex->build();
+
+ d.compressedData2 = loadBC1(QLatin1String(":/bwqt224_64_nomips.dds"), &imageSize);
+ Q_ASSERT(imageSize == QSize(224, 64));
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None, // no mipmapping here
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ d.ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ d.ps->setCullMode(QRhiGraphicsPipeline::Back);
+ d.ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ const QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ d.ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, vs },
+ { QRhiGraphicsShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+
+ d.ps->build();
+}
+
+void Window::customRelease()
+{
+ delete d.ps;
+ d.ps = nullptr;
+
+ delete d.srb;
+ d.srb = nullptr;
+
+ delete d.ubuf;
+ d.ubuf = nullptr;
+
+ delete d.vbuf;
+ d.vbuf = nullptr;
+
+ delete d.sampler;
+ d.sampler = nullptr;
+
+ delete d.tex;
+ d.tex = nullptr;
+}
+
+void Window::customRender()
+{
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (!d.vbufReady) {
+ d.vbufReady = true;
+ u->uploadStaticBuffer(d.vbuf, cube);
+ qint32 flip = 0;
+ u->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+ }
+ if (!d.compressedData.isEmpty()) {
+ {
+ QRhiTextureUploadDescription desc({ 0, 0, { d.compressedData[0].constData(), d.compressedData[0].size() } });
+ u->uploadTexture(d.tex, desc);
+ d.compressedData.clear();
+ }
+
+ // now exercise uploading a smaller compressed image into the same texture
+ {
+ QRhiTextureSubresourceUploadDescription image(d.compressedData2[0].constData(), d.compressedData2[0].size());
+ // positions and sizes must be multiples of 4 here (for BC1)
+ image.setDestinationTopLeft(QPoint(16, 32));
+ // the image is smaller than the subresource size (224x64 vs
+ // 256x256) so the size must be specified manually
+ image.setSourceSize(QSize(224, 64));
+ QRhiTextureUploadDescription desc({ 0, 0, image });
+ u->uploadTexture(d.tex, desc);
+ d.compressedData2.clear();
+ }
+ }
+ d.rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(0.5f);
+ mvp.rotate(d.rotation, 0, 1, 0);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { d.vbuf, 0 },
+ { d.vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.pro b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.pro
new file mode 100644
index 0000000000..a1184fc754
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ compressedtexture_bc1_subupload.cpp
+
+RESOURCES = compressedtexture_bc1_subupload.qrc
diff --git a/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.qrc b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.qrc
new file mode 100644
index 0000000000..859a0a79f6
--- /dev/null
+++ b/tests/manual/rhi/compressedtexture_bc1_subupload/compressedtexture_bc1_subupload.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="qt256_bc1_9mips.dds">../shared/qt256_bc1_9mips.dds</file>
+ <file alias="bwqt224_64_nomips.dds">../shared/bwqt224_64_nomips.dds</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/cubemap/buildshaders.bat b/tests/manual/rhi/cubemap/buildshaders.bat
new file mode 100644
index 0000000000..ebf673875d
--- /dev/null
+++ b/tests/manual/rhi/cubemap/buildshaders.bat
@@ -0,0 +1,2 @@
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c cubemap.vert -o cubemap.vert.qsb
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c cubemap.frag -o cubemap.frag.qsb
diff --git a/tests/manual/rhi/cubemap/c.png b/tests/manual/rhi/cubemap/c.png
new file mode 100644
index 0000000000..7b00455e53
--- /dev/null
+++ b/tests/manual/rhi/cubemap/c.png
Binary files differ
diff --git a/tests/manual/rhi/cubemap/cubemap.cpp b/tests/manual/rhi/cubemap/cubemap.cpp
new file mode 100644
index 0000000000..0420a38cbd
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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/examplefw.h"
+#include "../shared/cube.h"
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+} d;
+
+void Window::customInit()
+{
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ const QSize cubeMapSize(512, 512);
+ d.tex = m_r->newTexture(QRhiTexture::RGBA8, cubeMapSize, 1, QRhiTexture::CubeMap);
+ d.releasePool << d.tex;
+ d.tex->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, cube);
+
+ QImage img = QImage(":/c.png").mirrored().convertToFormat(QImage::Format_RGBA8888);
+ // just use the same image for all faces for now
+ QRhiTextureSubresourceUploadDescription subresDesc(img);
+ QRhiTextureUploadDescription desc({
+ { 0, 0, subresDesc }, // +X
+ { 1, 0, subresDesc }, // -X
+ { 2, 0, subresDesc }, // +Y
+ { 3, 0, subresDesc }, // -Y
+ { 4, 0, subresDesc }, // +Z
+ { 5, 0, subresDesc } // -Z
+ });
+ d.initialUpdates->uploadTexture(d.tex, desc);
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::Repeat, QRhiSampler::Repeat);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ d.ps->setDepthOp(QRhiGraphicsPipeline::LessOrEqual);
+
+ d.ps->setCullMode(QRhiGraphicsPipeline::Front); // we are inside the cube so cull front, not back
+ d.ps->setFrontFace(QRhiGraphicsPipeline::CCW); // front is ccw in the cube data
+
+ QShader vs = getShader(QLatin1String(":/cubemap.vert.qsb"));
+ Q_ASSERT(vs.isValid());
+ QShader fs = getShader(QLatin1String(":/cubemap.frag.qsb"));
+ Q_ASSERT(fs.isValid());
+ d.ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, vs },
+ { QRhiGraphicsShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 }
+ });
+
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+
+ d.ps->build();
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ QMatrix4x4 mvp = m_r->clipSpaceCorrMatrix();
+ mvp.perspective(90.0f, outputSizeInPixels.width() / (float) outputSizeInPixels.height(), 0.01f, 1000.0f);
+ // cube vertices go from -1..1
+ mvp.scale(10);
+ static float rx = 0;
+ mvp.rotate(rx, 1, 0, 0);
+ rx += 0.5f;
+ // no translation
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(36);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/cubemap/cubemap.frag b/tests/manual/rhi/cubemap/cubemap.frag
new file mode 100644
index 0000000000..13a365ed0c
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec3 v_coord;
+layout(location = 0) out vec4 fragColor;
+layout(binding = 1) uniform samplerCube tex;
+
+void main()
+{
+ fragColor = vec4(texture(tex, v_coord).rgb, 1.0);
+}
diff --git a/tests/manual/rhi/cubemap/cubemap.frag.qsb b/tests/manual/rhi/cubemap/cubemap.frag.qsb
new file mode 100644
index 0000000000..d7cc025554
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/cubemap/cubemap.pro b/tests/manual/rhi/cubemap/cubemap.pro
new file mode 100644
index 0000000000..61910ffe20
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ cubemap.cpp
+
+RESOURCES = cubemap.qrc
diff --git a/tests/manual/rhi/cubemap/cubemap.qrc b/tests/manual/rhi/cubemap/cubemap.qrc
new file mode 100644
index 0000000000..bacd15446c
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>cubemap.vert.qsb</file>
+ <file>cubemap.frag.qsb</file>
+ <file>c.png</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/cubemap/cubemap.vert b/tests/manual/rhi/cubemap/cubemap.vert
new file mode 100644
index 0000000000..65216dd6b0
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.vert
@@ -0,0 +1,15 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 0) out vec3 v_coord;
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_coord = position.xyz;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/cubemap/cubemap.vert.qsb b/tests/manual/rhi/cubemap/cubemap.vert.qsb
new file mode 100644
index 0000000000..fae136337c
--- /dev/null
+++ b/tests/manual/rhi/cubemap/cubemap.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/floattexture/floattexture.cpp b/tests/manual/rhi/floattexture/floattexture.cpp
new file mode 100644
index 0000000000..b62ef290f7
--- /dev/null
+++ b/tests/manual/rhi/floattexture/floattexture.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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/examplefw.h"
+#include <qmath.h>
+
+QByteArray loadHdr(const QString &fn, QSize *size)
+{
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to open %s", qPrintable(fn));
+ return QByteArray();
+ }
+
+ char sig[256];
+ f.read(sig, 11);
+ if (strncmp(sig, "#?RADIANCE\n", 11))
+ return QByteArray();
+
+ QByteArray buf = f.readAll();
+ const char *p = buf.constData();
+ const char *pEnd = p + buf.size();
+
+ // Process lines until the empty one.
+ QByteArray line;
+ while (p < pEnd) {
+ char c = *p++;
+ if (c == '\n') {
+ if (line.isEmpty())
+ break;
+ if (line.startsWith(QByteArrayLiteral("FORMAT="))) {
+ const QByteArray format = line.mid(7).trimmed();
+ if (format != QByteArrayLiteral("32-bit_rle_rgbe")) {
+ qWarning("HDR format '%s' is not supported", format.constData());
+ return QByteArray();
+ }
+ }
+ line.clear();
+ } else {
+ line.append(c);
+ }
+ }
+ if (p == pEnd) {
+ qWarning("Malformed HDR image data at property strings");
+ return QByteArray();
+ }
+
+ // Get the resolution string.
+ while (p < pEnd) {
+ char c = *p++;
+ if (c == '\n')
+ break;
+ line.append(c);
+ }
+ if (p == pEnd) {
+ qWarning("Malformed HDR image data at resolution string");
+ return QByteArray();
+ }
+
+ int w = 0, h = 0;
+ // We only care about the standard orientation.
+ if (!sscanf(line.constData(), "-Y %d +X %d", &h, &w)) {
+ qWarning("Unsupported HDR resolution string '%s'", line.constData());
+ return QByteArray();
+ }
+ if (w <= 0 || h <= 0) {
+ qWarning("Invalid HDR resolution");
+ return QByteArray();
+ }
+
+ // output is RGBA32F
+ const int blockSize = 4 * sizeof(float);
+ QByteArray data;
+ data.resize(w * h * blockSize);
+
+ typedef unsigned char RGBE[4];
+ RGBE *scanline = new RGBE[w];
+
+ for (int y = 0; y < h; ++y) {
+ if (pEnd - p < 4) {
+ qWarning("Unexpected end of HDR data");
+ delete[] scanline;
+ return QByteArray();
+ }
+
+ scanline[0][0] = *p++;
+ scanline[0][1] = *p++;
+ scanline[0][2] = *p++;
+ scanline[0][3] = *p++;
+
+ if (scanline[0][0] == 2 && scanline[0][1] == 2 && scanline[0][2] < 128) {
+ // new rle, the first pixel was a dummy
+ for (int channel = 0; channel < 4; ++channel) {
+ for (int x = 0; x < w && p < pEnd; ) {
+ unsigned char c = *p++;
+ if (c > 128) { // run
+ if (p < pEnd) {
+ int repCount = c & 127;
+ c = *p++;
+ while (repCount--)
+ scanline[x++][channel] = c;
+ }
+ } else { // not a run
+ while (c-- && p < pEnd)
+ scanline[x++][channel] = *p++;
+ }
+ }
+ }
+ } else {
+ // old rle
+ scanline[0][0] = 2;
+ int bitshift = 0;
+ int x = 1;
+ while (x < w && pEnd - p >= 4) {
+ scanline[x][0] = *p++;
+ scanline[x][1] = *p++;
+ scanline[x][2] = *p++;
+ scanline[x][3] = *p++;
+
+ if (scanline[x][0] == 1 && scanline[x][1] == 1 && scanline[x][2] == 1) { // run
+ int repCount = scanline[x][3] << bitshift;
+ while (repCount--) {
+ memcpy(scanline[x], scanline[x - 1], 4);
+ ++x;
+ }
+ bitshift += 8;
+ } else { // not a run
+ ++x;
+ bitshift = 0;
+ }
+ }
+ }
+
+ // adjust for -Y orientation
+ float *fp = reinterpret_cast<float *>(data.data() + (h - 1 - y) * blockSize * w);
+ for (int x = 0; x < w; ++x) {
+ float d = qPow(2.0f, float(scanline[x][3]) - 128.0f);
+ // r, g, b, a
+ *fp++ = scanline[x][0] / 256.0f * d;
+ *fp++ = scanline[x][1] / 256.0f * d;
+ *fp++ = scanline[x][2] / 256.0f * d;
+ *fp++ = 1.0f;
+ }
+ }
+
+ delete[] scanline;
+
+ if (size)
+ *size = QSize(w, h);
+
+ return data;
+}
+
+static float vertexData[] =
+{ // Y up, CCW
+ -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f
+};
+
+static quint16 indexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 winProj;
+} d;
+
+void Window::customInit()
+{
+ if (!m_r->isTextureFormatSupported(QRhiTexture::RGBA32F))
+ qWarning("RGBA32F texture format is not supported");
+
+ QSize size;
+ QByteArray floatData = loadHdr(QLatin1String(":/OpenfootageNET_fieldairport-512.hdr"), &size);
+ Q_ASSERT(!floatData.isEmpty());
+ qDebug() << size;
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData));
+ d.ibuf->build();
+ d.releasePool << d.ibuf;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ d.tex = m_r->newTexture(QRhiTexture::RGBA32F, size);
+ d.releasePool << d.tex;
+ d.tex->build();
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 4 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, vertexData);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, indexData);
+
+ qint32 flip = 1;
+ d.initialUpdates->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+
+ QRhiTextureUploadDescription desc({ 0, 0, { floatData.constData(), floatData.size() } });
+ d.initialUpdates->uploadTexture(d.tex, desc);
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(2.5f);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ }
+
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/floattexture/floattexture.pro b/tests/manual/rhi/floattexture/floattexture.pro
new file mode 100644
index 0000000000..e566da2b94
--- /dev/null
+++ b/tests/manual/rhi/floattexture/floattexture.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ floattexture.cpp
+
+RESOURCES = floattexture.qrc
diff --git a/tests/manual/rhi/floattexture/floattexture.qrc b/tests/manual/rhi/floattexture/floattexture.qrc
new file mode 100644
index 0000000000..fefb56b910
--- /dev/null
+++ b/tests/manual/rhi/floattexture/floattexture.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+ <file alias="OpenfootageNET_fieldairport-512.hdr">../shared/OpenfootageNET_fieldairport-512.hdr</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp
new file mode 100644
index 0000000000..a24b980173
--- /dev/null
+++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp
@@ -0,0 +1,554 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+
+// This is a compact, minimal, single-file demo of deciding the backend at
+// runtime while using the exact same shaders and rendering code without any
+// branching whatsoever once the QWindow is up and the RHI is initialized.
+
+#include <QGuiApplication>
+#include <QCommandLineParser>
+#include <QWindow>
+#include <QPlatformSurfaceEvent>
+#include <QElapsedTimer>
+
+#include <QtGui/private/qshader_p.h>
+#include <QFile>
+
+#include <QtGui/private/qrhinull_p.h>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#include <QOffscreenSurface>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QLoggingCategory>
+#include <QtGui/private/qrhivulkan_p.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+#endif
+
+#ifdef Q_OS_DARWIN
+#include <QtGui/private/qrhimetal_p.h>
+#endif
+
+static float vertexData[] = {
+ // Y up (note clipSpaceCorrMatrix in m_proj), CCW
+ 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 QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+enum GraphicsApi
+{
+ OpenGL,
+ Vulkan,
+ D3D11,
+ Metal,
+ Null
+};
+
+static GraphicsApi graphicsApi;
+
+static QString graphicsApiName()
+{
+ switch (graphicsApi) {
+ case OpenGL:
+ return QLatin1String("OpenGL 2.x");
+ case Vulkan:
+ return QLatin1String("Vulkan");
+ case D3D11:
+ return QLatin1String("Direct3D 11");
+ case Metal:
+ return QLatin1String("Metal");
+ case Null:
+ return QLatin1String("Null");
+ default:
+ break;
+ }
+ return QString();
+}
+
+class Window : public QWindow
+{
+public:
+ Window();
+ ~Window();
+
+ void init();
+ void releaseResources();
+ void resizeSwapChain();
+ void releaseSwapChain();
+ void render();
+
+ void exposeEvent(QExposeEvent *) override;
+ bool event(QEvent *) override;
+
+private:
+ bool m_running = false;
+ bool m_notExposed = false;
+ bool m_newlyExposed = false;
+
+ QRhi *m_r = nullptr;
+ bool m_hasSwapChain = false;
+ QRhiSwapChain *m_sc = nullptr;
+ QRhiRenderBuffer *m_ds = nullptr;
+ QRhiRenderPassDescriptor *m_rp = nullptr;
+ QRhiBuffer *m_vbuf = nullptr;
+ bool m_vbufReady = false;
+ QRhiBuffer *m_ubuf = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+ QVector<QRhiResource *> releasePool;
+
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ float m_opacity = 1;
+ int m_opacityDir = -1;
+
+ QElapsedTimer m_timer;
+ qint64 m_elapsedMs;
+ int m_elapsedCount;
+
+#ifndef QT_NO_OPENGL
+ QOffscreenSurface *m_fallbackSurface = nullptr;
+#endif
+};
+
+Window::Window()
+{
+ // Tell the platform plugin what we want.
+ switch (graphicsApi) {
+ case OpenGL:
+#if QT_CONFIG(opengl)
+ setSurfaceType(OpenGLSurface);
+ setFormat(QRhiGles2InitParams::adjustedFormat());
+#endif
+ break;
+ case Vulkan:
+ setSurfaceType(VulkanSurface);
+ break;
+ case D3D11:
+ setSurfaceType(OpenGLSurface); // not a typo
+ break;
+ case Metal:
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
+ setSurfaceType(MetalSurface);
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+Window::~Window()
+{
+ releaseResources();
+}
+
+void Window::exposeEvent(QExposeEvent *)
+{
+ // initialize and start rendering when the window becomes usable for graphics purposes
+ if (isExposed() && !m_running) {
+ m_running = true;
+ init();
+ resizeSwapChain();
+ }
+
+ // stop pushing frames when not exposed (or size is 0)
+ if ((!isExposed() || (m_hasSwapChain && m_sc->surfacePixelSize().isEmpty())) && m_running)
+ m_notExposed = true;
+
+ // continue when exposed again and the surface has a valid size.
+ // note that the surface size can be (0, 0) even though size() reports a valid one...
+ if (isExposed() && m_running && m_notExposed && !m_sc->surfacePixelSize().isEmpty()) {
+ m_notExposed = false;
+ m_newlyExposed = true;
+ }
+
+ // always render a frame on exposeEvent() (when exposed) in order to update
+ // immediately on window resize.
+ if (isExposed() && !m_sc->surfacePixelSize().isEmpty())
+ render();
+}
+
+bool Window::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::UpdateRequest:
+ render();
+ break;
+
+ case QEvent::PlatformSurface:
+ // this is the proper time to tear down the swapchain (while the native window and surface are still around)
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ releaseSwapChain();
+ break;
+
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
+
+void Window::init()
+{
+ if (graphicsApi == Null) {
+ QRhiNullInitParams params;
+ m_r = QRhi::create(QRhi::Null, &params);
+ }
+
+#ifndef QT_NO_OPENGL
+ if (graphicsApi == OpenGL) {
+ m_fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ QRhiGles2InitParams params;
+ params.fallbackSurface = m_fallbackSurface;
+ params.window = this;
+ m_r = QRhi::create(QRhi::OpenGLES2, &params);
+ }
+#endif
+
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan) {
+ QRhiVulkanInitParams params;
+ params.inst = vulkanInstance();
+ params.window = this;
+ m_r = QRhi::create(QRhi::Vulkan, &params);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (graphicsApi == D3D11) {
+ QRhiD3D11InitParams params;
+ m_r = QRhi::create(QRhi::D3D11, &params);
+ }
+#endif
+
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ QRhiMetalInitParams params;
+ m_r = QRhi::create(QRhi::Metal, &params);
+ }
+#endif
+
+ if (!m_r)
+ qFatal("Failed to create RHI backend");
+
+ // now onto the backend-independent init
+
+ m_sc = m_r->newSwapChain();
+ // allow depth-stencil, although we do not actually enable depth test/write for the triangle
+ m_ds = m_r->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
+ QSize(), // no need to set the size yet
+ 1,
+ QRhiRenderBuffer::UsedWithSwapChainOnly);
+ releasePool << m_ds;
+ m_sc->setWindow(this);
+ m_sc->setDepthStencil(m_ds);
+ m_rp = m_sc->newCompatibleRenderPassDescriptor();
+ releasePool << m_rp;
+ m_sc->setRenderPassDescriptor(m_rp);
+
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ releasePool << m_vbuf;
+ m_vbuf->build();
+ m_vbufReady = false;
+
+ m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ releasePool << m_ubuf;
+ m_ubuf->build();
+
+ m_srb = m_r->newShaderResourceBindings();
+ releasePool << m_srb;
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf)
+ });
+ m_srb->build();
+
+ m_ps = m_r->newGraphicsPipeline();
+ releasePool << m_ps;
+
+ QRhiGraphicsPipeline::TargetBlend premulAlphaBlend;
+ premulAlphaBlend.enable = true;
+ m_ps->setTargetBlends({ premulAlphaBlend });
+
+ const QShader vs = getShader(QLatin1String(":/color.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/color.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ m_ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, vs },
+ { QRhiGraphicsShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb);
+ m_ps->setRenderPassDescriptor(m_rp);
+
+ m_ps->build();
+}
+
+void Window::releaseResources()
+{
+ qDeleteAll(releasePool);
+ releasePool.clear();
+
+ delete m_sc; // native swapchain is likely released already
+ m_sc = nullptr;
+
+ delete m_r;
+
+#ifndef QT_NO_OPENGL
+ delete m_fallbackSurface;
+#endif
+}
+
+void Window::resizeSwapChain()
+{
+ const QSize outputSize = m_sc->surfacePixelSize();
+
+ m_ds->setPixelSize(outputSize);
+ m_ds->build(); // == m_ds->release(); m_ds->build();
+
+ m_hasSwapChain = m_sc->buildOrResize();
+
+ m_elapsedMs = 0;
+ m_elapsedCount = 0;
+
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void Window::releaseSwapChain()
+{
+ if (m_hasSwapChain) {
+ m_hasSwapChain = false;
+ m_sc->release();
+ }
+}
+
+void Window::render()
+{
+ if (!m_hasSwapChain || m_notExposed)
+ return;
+
+ // If the window got resized or got newly exposed, resize the swapchain.
+ // (the newly-exposed case is not actually required by some
+ // platforms/backends, but f.ex. Vulkan on Windows seems to need it)
+ if (m_sc->currentPixelSize() != m_sc->surfacePixelSize() || m_newlyExposed) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ m_newlyExposed = false;
+ }
+
+ // Start a new frame. This is where we block when too far ahead of
+ // GPU/present, and that's what throttles the thread to the refresh rate.
+ // (except for OpenGL where it happens either in endFrame or somewhere else
+ // depending on the GL implementation)
+ QRhi::FrameOpResult r = m_r->beginFrame(m_sc);
+ if (r == QRhi::FrameOpSwapChainOutOfDate) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ r = m_r->beginFrame(m_sc);
+ }
+ if (r != QRhi::FrameOpSuccess) {
+ requestUpdate();
+ return;
+ }
+
+ if (m_elapsedCount)
+ m_elapsedMs += m_timer.elapsed();
+ m_timer.restart();
+ m_elapsedCount += 1;
+ if (m_elapsedMs >= 4000) {
+ qDebug("%f", m_elapsedCount / 4.0f);
+ m_elapsedMs = 0;
+ m_elapsedCount = 0;
+ }
+
+ // Set up buffer updates.
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (!m_vbufReady) {
+ m_vbufReady = true;
+ u->uploadStaticBuffer(m_vbuf, vertexData);
+ }
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.rotate(m_rotation, 0, 1, 0);
+ u->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+ m_opacity += m_opacityDir * 0.005f;
+ if (m_opacity < 0.0f || m_opacity > 1.0f) {
+ m_opacityDir *= -1;
+ m_opacity = qBound(0.0f, m_opacity, 1.0f);
+ }
+ u->updateDynamicBuffer(m_ubuf, 64, 4, &m_opacity);
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+
+ // Apply buffer updates, clear, start the renderpass (where applicable).
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+
+ cb->setGraphicsPipeline(m_ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+
+ const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+
+ cb->endPass();
+
+ // Submit.
+ m_r->endFrame(m_sc);
+
+ requestUpdate(); // render continuously, throttled by the presentation rate (due to beginFrame above)
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ // Defaults.
+#if defined(Q_OS_WIN)
+ graphicsApi = D3D11;
+#elif defined(Q_OS_DARWIN)
+ graphicsApi = Metal;
+#elif QT_CONFIG(vulkan)
+ graphicsApi = Vulkan;
+#else
+ graphicsApi = OpenGL;
+#endif
+
+ // Allow overriding via the command line.
+ QCommandLineParser cmdLineParser;
+ cmdLineParser.addHelpOption();
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ cmdLineParser.addOption(glOption);
+ QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
+ cmdLineParser.addOption(vkOption);
+ QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
+ cmdLineParser.addOption(d3dOption);
+ QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
+ cmdLineParser.addOption(mtlOption);
+ QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null"));
+ cmdLineParser.addOption(nullOption);
+ cmdLineParser.process(app);
+ if (cmdLineParser.isSet(glOption))
+ graphicsApi = OpenGL;
+ if (cmdLineParser.isSet(vkOption))
+ graphicsApi = Vulkan;
+ if (cmdLineParser.isSet(d3dOption))
+ graphicsApi = D3D11;
+ if (cmdLineParser.isSet(mtlOption))
+ graphicsApi = Metal;
+ if (cmdLineParser.isSet(nullOption))
+ graphicsApi = Null;
+
+ // Vulkan setup.
+#if QT_CONFIG(vulkan)
+ QVulkanInstance inst;
+ if (graphicsApi == Vulkan) {
+ if (!inst.create()) {
+ qWarning("Failed to create Vulkan instance, switching to OpenGL");
+ graphicsApi = OpenGL;
+ }
+ }
+#endif
+
+ // Create and show the window.
+ Window w;
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan)
+ w.setVulkanInstance(&inst);
+#endif
+ w.resize(1280, 720);
+ w.setTitle(graphicsApiName());
+ w.show();
+
+ // Window::event() will not get invoked when the
+ // PlatformSurfaceAboutToBeDestroyed event is sent during the QWindow
+ // destruction. That happens only when exiting via app::quit() instead of
+ // the more common QWindow::close(). Take care of it: if the
+ // QPlatformWindow is still around (there was no close() yet), get rid of
+ // the swapchain while it's not too late.
+ if (w.handle())
+ w.releaseSwapChain();
+
+ return app.exec();
+}
diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro
new file mode 100644
index 0000000000..eeef33ff6a
--- /dev/null
+++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ hellominimalcrossgfxtriangle.cpp
+
+RESOURCES = hellominimalcrossgfxtriangle.qrc
diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.qrc b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.qrc
new file mode 100644
index 0000000000..8cec4fa9ec
--- /dev/null
+++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/mrt/buildshaders.bat b/tests/manual/rhi/mrt/buildshaders.bat
new file mode 100644
index 0000000000..75741448b1
--- /dev/null
+++ b/tests/manual/rhi/mrt/buildshaders.bat
@@ -0,0 +1,2 @@
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c mrt.vert -o mrt.vert.qsb
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c mrt.frag -o mrt.frag.qsb
diff --git a/tests/manual/rhi/mrt/mrt.cpp b/tests/manual/rhi/mrt/mrt.cpp
new file mode 100644
index 0000000000..2bbd879dc4
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.cpp
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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/examplefw.h"
+
+// Exercises MRT, by attaching 4 textures to a single QRhiTextureRenderTarget.
+// The fragment shader outputs to all four targets.
+// The textures are then used to render 4 quads, so their contents can be confirmed.
+
+const int ATTCOUNT = 4;
+
+static float quadVertexData[] =
+{ // Y up, CCW
+ -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f
+};
+
+static quint16 quadIndexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+static float triangleData[] =
+{ // Y up, CCW
+ 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,
+};
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTextureRenderTarget *rt = nullptr;
+ QRhiRenderPassDescriptor *rtRp = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 winProj;
+ struct PerColorBuffer {
+ QRhiTexture *tex = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ };
+ PerColorBuffer colData[ATTCOUNT];
+
+ QRhiBuffer *triUbuf = nullptr;
+ QRhiShaderResourceBindings *triSrb = nullptr;
+ QRhiGraphicsPipeline *triPs = nullptr;
+ float triRot = 0;
+ QMatrix4x4 triBaseMvp;
+} d;
+
+void Window::customInit()
+{
+ qDebug("Max color attachments: %d", m_r->resourceLimit(QRhi::MaxColorAttachments));
+ if (m_r->resourceLimit(QRhi::MaxColorAttachments) < 4)
+ qWarning("MRT is not supported");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(quadVertexData) + sizeof(triangleData));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(quadIndexData));
+ d.ibuf->build();
+ d.releasePool << d.ibuf;
+
+ const int oneRoundedUniformBlockSize = m_r->ubufAligned(68);
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, oneRoundedUniformBlockSize * ATTCOUNT);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ for (int i = 0; i < ATTCOUNT; ++i) {
+ QRhiTexture *tex = m_r->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
+ d.releasePool << tex;
+ tex->build();
+
+ QRhiShaderResourceBindings *srb = m_r->newShaderResourceBindings();
+ d.releasePool << srb;
+ srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage,
+ d.ubuf, i * oneRoundedUniformBlockSize, 68),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, tex, d.sampler)
+ });
+ srb->build();
+
+ d.colData[i].tex = tex;
+ d.colData[i].srb = srb;
+ }
+
+ QRhiTextureRenderTargetDescription rtDesc;
+ QVector<QRhiColorAttachment> att;
+ for (int i = 0; i < ATTCOUNT; ++i)
+ att.append(QRhiColorAttachment(d.colData[i].tex));
+ rtDesc.setColorAttachments(att);
+ d.rt = m_r->newTextureRenderTarget(rtDesc);
+ d.releasePool << d.rt;
+ d.rtRp = d.rt->newCompatibleRenderPassDescriptor();
+ d.releasePool << d.rtRp;
+ d.rt->setRenderPassDescriptor(d.rtRp);
+ d.rt->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 4 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.colData[0].srb); // all of them are layout-compatible
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(quadVertexData), quadVertexData);
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, sizeof(quadVertexData), sizeof(triangleData), triangleData);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, quadIndexData);
+
+ qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0;
+ for (int i = 0; i < ATTCOUNT; ++i)
+ d.initialUpdates->updateDynamicBuffer(d.ubuf, i * oneRoundedUniformBlockSize + 64, 4, &flip);
+
+ // triangle
+ d.triUbuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.releasePool << d.triUbuf;
+ d.triUbuf->build();
+
+ d.triSrb = m_r->newShaderResourceBindings();
+ d.releasePool << d.triSrb;
+ d.triSrb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.triUbuf)
+ });
+ d.triSrb->build();
+
+ d.triPs = m_r->newGraphicsPipeline();
+ d.releasePool << d.triPs;
+ d.triPs->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/mrt.vert.qsb")) },
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/mrt.frag.qsb")) }
+ });
+ QVector<QRhiGraphicsPipeline::TargetBlend> blends;
+ for (int i = 0; i < ATTCOUNT; ++i) {
+ QRhiGraphicsPipeline::TargetBlend blend;
+ blends.append(blend);
+ }
+ d.triPs->setTargetBlends(blends);
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+ d.triPs->setVertexInputLayout(inputLayout);
+ d.triPs->setShaderResourceBindings(d.triSrb);
+ d.triPs->setRenderPassDescriptor(d.rtRp);
+ d.triPs->build();
+
+ d.triBaseMvp = m_r->clipSpaceCorrMatrix();
+ d.triBaseMvp.perspective(45.0f, d.rt->pixelSize().width() / float(d.rt->pixelSize().height()), 0.01f, 1000.0f);
+ d.triBaseMvp.translate(0, 0, -2);
+ float opacity = 1.0f;
+ d.initialUpdates->updateDynamicBuffer(d.triUbuf, 64, 4, &opacity);
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ QMatrix4x4 triMvp = d.triBaseMvp;
+ triMvp.rotate(d.triRot, 0, 1, 0);
+ d.triRot += 1;
+ u->updateDynamicBuffer(d.triUbuf, 0, 64, triMvp.constData());
+
+ cb->beginPass(d.rt, QColor::fromRgbF(0.5f, 0.2f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.triPs);
+ cb->setViewport({ 0, 0, float(d.rt->pixelSize().width()), float(d.rt->pixelSize().height()) });
+ cb->setShaderResources();
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, sizeof(quadVertexData));
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+ cb->endPass();
+
+ u = m_r->nextResourceUpdateBatch();
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+ const int oneRoundedUniformBlockSize = m_r->ubufAligned(68);
+ for (int i = 0; i < ATTCOUNT; ++i) {
+ QMatrix4x4 mvp = m_proj;
+ switch (i) {
+ case 0:
+ mvp.translate(-2.0f, 0, 0);
+ break;
+ case 1:
+ mvp.translate(-0.8f, 0, 0);
+ break;
+ case 2:
+ mvp.translate(0.4f, 0, 0);
+ break;
+ case 3:
+ mvp.translate(1.6f, 0, 0);
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ u->updateDynamicBuffer(d.ubuf, i * oneRoundedUniformBlockSize, 64, mvp.constData());
+ }
+ }
+
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ vbufBinding.second = 0;
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ for (int i = 0; i < ATTCOUNT; ++i) {
+ cb->setShaderResources(d.colData[i].srb);
+ cb->drawIndexed(6);
+ }
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/mrt/mrt.frag b/tests/manual/rhi/mrt/mrt.frag
new file mode 100644
index 0000000000..9166b552b9
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.frag
@@ -0,0 +1,22 @@
+#version 440
+
+layout(location = 0) in vec3 v_color;
+
+layout(location = 0) out vec4 c0;
+layout(location = 1) out vec4 c1;
+layout(location = 2) out vec4 c2;
+layout(location = 3) out vec4 c3;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float opacity;
+} ubuf;
+
+void main()
+{
+ vec4 c = vec4(v_color * ubuf.opacity, ubuf.opacity);
+ c0 = vec4(c.r, 0, 0, c.a);
+ c1 = vec4(0, c.g, 0, c.a);
+ c2 = vec4(0, 0, c.b, c.a);
+ c3 = c;
+}
diff --git a/tests/manual/rhi/mrt/mrt.frag.qsb b/tests/manual/rhi/mrt/mrt.frag.qsb
new file mode 100644
index 0000000000..389b6affa3
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/mrt/mrt.pro b/tests/manual/rhi/mrt/mrt.pro
new file mode 100644
index 0000000000..7cde425488
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ mrt.cpp
+
+RESOURCES = mrt.qrc
diff --git a/tests/manual/rhi/mrt/mrt.qrc b/tests/manual/rhi/mrt/mrt.qrc
new file mode 100644
index 0000000000..275f476013
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+ <file>mrt.vert.qsb</file>
+ <file>mrt.frag.qsb</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/mrt/mrt.vert b/tests/manual/rhi/mrt/mrt.vert
new file mode 100644
index 0000000000..43af543f44
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.vert
@@ -0,0 +1,19 @@
+#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;
+ float opacity;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/mrt/mrt.vert.qsb b/tests/manual/rhi/mrt/mrt.vert.qsb
new file mode 100644
index 0000000000..ff8c0e50bb
--- /dev/null
+++ b/tests/manual/rhi/mrt/mrt.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.cpp b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.cpp
new file mode 100644
index 0000000000..b61fb91c6d
--- /dev/null
+++ b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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/examplefw.h"
+
+// Uses a multisample renderbuffer (whatever that may be on a given backend) to
+// render to and then resolves the samples into a non-multisample texture.
+
+static float vertexData[] =
+{ // Y up, CCW
+ -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f
+};
+
+static quint16 indexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+static float triangleData[] =
+{ // Y up, CCW
+ 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,
+};
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiRenderBuffer *rb = nullptr;
+ QRhiTextureRenderTarget *rt = nullptr;
+ QRhiRenderPassDescriptor *rtRp = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiBuffer *triUbuf = nullptr;
+ QRhiShaderResourceBindings *triSrb = nullptr;
+ QRhiGraphicsPipeline *triPs = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 triBaseMvp;
+ float triRot = 0;
+ QMatrix4x4 winProj;
+} d;
+
+void Window::customInit()
+{
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData) + sizeof(triangleData));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData));
+ d.ibuf->build();
+ d.releasePool << d.ibuf;
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ d.rb = m_r->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4); // 4x MSAA
+ d.rb->build();
+ d.releasePool << d.rb;
+
+ // the non-msaa texture that will be the destination in the resolve
+ d.tex = m_r->newTexture(QRhiTexture::RGBA8, d.rb->pixelSize(), 1, QRhiTexture::RenderTarget);
+ d.releasePool << d.tex;
+ d.tex->build();
+
+ // rb is multisample, instead of writing out the msaa data into it,
+ // resolve into d.tex at the end of each render pass
+ QRhiTextureRenderTargetDescription rtDesc;
+ QRhiColorAttachment rtAtt(d.rb);
+ rtAtt.setResolveTexture(d.tex);
+ rtDesc.setColorAttachments({ rtAtt });
+
+ d.rt = m_r->newTextureRenderTarget(rtDesc);
+ d.releasePool << d.rt;
+ d.rtRp = d.rt->newCompatibleRenderPassDescriptor();
+ d.releasePool << d.rtRp;
+ d.rt->setRenderPassDescriptor(d.rtRp);
+ d.rt->build();
+
+ d.triUbuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.releasePool << d.triUbuf;
+ d.triUbuf->build();
+
+ d.triSrb = m_r->newShaderResourceBindings();
+ d.releasePool << d.triSrb;
+ d.triSrb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.triUbuf)
+ });
+ d.triSrb->build();
+
+ d.triPs = m_r->newGraphicsPipeline();
+ d.releasePool << d.triPs;
+ d.triPs->setSampleCount(4); // must match the render target
+ d.triPs->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/color.vert.qsb")) },
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/color.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+ d.triPs->setVertexInputLayout(inputLayout);
+ d.triPs->setShaderResourceBindings(d.triSrb);
+ d.triPs->setRenderPassDescriptor(d.rtRp);
+ d.triPs->build();
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+ inputLayout.setBindings({
+ { 4 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(vertexData), vertexData);
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, sizeof(vertexData), sizeof(triangleData), triangleData);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, indexData);
+
+ d.triBaseMvp = m_r->clipSpaceCorrMatrix();
+ d.triBaseMvp.perspective(45.0f, d.rb->pixelSize().width() / float(d.rb->pixelSize().height()), 0.01f, 1000.0f);
+ d.triBaseMvp.translate(0, 0, -2);
+ float opacity = 1.0f;
+ d.initialUpdates->updateDynamicBuffer(d.triUbuf, 64, 4, &opacity);
+
+ qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0;
+ d.initialUpdates->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ QMatrix4x4 triMvp = d.triBaseMvp;
+ triMvp.rotate(d.triRot, 0, 1, 0);
+ d.triRot += 1;
+ u->updateDynamicBuffer(d.triUbuf, 0, 64, triMvp.constData());
+
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(2.5f);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ }
+
+ // offscreen (triangle, msaa)
+ cb->beginPass(d.rt, QColor::fromRgbF(0.5f, 0.2f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.triPs);
+ cb->setViewport({ 0, 0, float(d.rb->pixelSize().width()), float(d.rb->pixelSize().height()) });
+ cb->setShaderResources();
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, sizeof(vertexData));
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+ cb->endPass();
+
+ // onscreen (quad)
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ vbufBinding.second = 0;
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.pro b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.pro
new file mode 100644
index 0000000000..4b31e39e7d
--- /dev/null
+++ b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ msaarenderbuffer.cpp
+
+RESOURCES = msaarenderbuffer.qrc
diff --git a/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.qrc b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.qrc
new file mode 100644
index 0000000000..c7a2380a42
--- /dev/null
+++ b/tests/manual/rhi/msaarenderbuffer/msaarenderbuffer.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/msaatexture/msaatexture.cpp b/tests/manual/rhi/msaatexture/msaatexture.cpp
new file mode 100644
index 0000000000..1b652cce92
--- /dev/null
+++ b/tests/manual/rhi/msaatexture/msaatexture.cpp
@@ -0,0 +1,329 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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/examplefw.h"
+
+// Renders into a non-multisample and a multisample (4x) texture, and then uses
+// those textures to draw two quads. Note that this uses an MSAA sampler in the
+// shader, not resolves. Not supported on the GL(ES) backend atm.
+
+static float vertexData[] =
+{ // Y up, CCW
+ -0.5f, 0.5f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f
+};
+
+static quint16 indexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+static float triangleData[] =
+{ // Y up, CCW
+ 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,
+};
+
+const int UBUFSZ = 68;
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiTexture *msaaTex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srbLeft = nullptr;
+ QRhiShaderResourceBindings *srbRight = nullptr;
+ QRhiGraphicsPipeline *psLeft = nullptr;
+ QRhiGraphicsPipeline *psRight = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ int rightOfs;
+ QMatrix4x4 winProj;
+ QMatrix4x4 triBaseMvp;
+ float triRot = 0;
+
+ QRhiShaderResourceBindings *triSrb = nullptr;
+ QRhiGraphicsPipeline *msaaTriPs = nullptr;
+ QRhiGraphicsPipeline *triPs = nullptr;
+ QRhiBuffer *triUbuf = nullptr;
+ QRhiTextureRenderTarget *msaaRt = nullptr;
+ QRhiRenderPassDescriptor *msaaRtRp = nullptr;
+ QRhiTextureRenderTarget *rt = nullptr;
+ QRhiRenderPassDescriptor *rtRp = nullptr;
+} d;
+
+//#define NO_MSAA
+
+void Window::customInit()
+{
+ if (!m_r->isFeatureSupported(QRhi::MultisampleTexture))
+ qFatal("Multisample textures not supported by this backend");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData) + sizeof(triangleData));
+ d.releasePool << d.vbuf;
+ d.vbuf->build();
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData));
+ d.releasePool << d.ibuf;
+ d.ibuf->build();
+
+ d.rightOfs = m_r->ubufAligned(UBUFSZ);
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, d.rightOfs + UBUFSZ);
+ d.releasePool << d.ubuf;
+ d.ubuf->build();
+
+ d.tex = m_r->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
+ d.releasePool << d.tex;
+ d.tex->build();
+#ifndef NO_MSAA
+ d.msaaTex = m_r->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 4, QRhiTexture::RenderTarget);
+#else
+ d.msaaTex = m_r->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
+#endif
+ d.releasePool << d.msaaTex;
+ d.msaaTex->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(vertexData), vertexData);
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, sizeof(vertexData), sizeof(triangleData), triangleData);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, indexData);
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srbLeft = m_r->newShaderResourceBindings();
+ d.releasePool << d.srbLeft;
+ d.srbLeft->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf, 0, UBUFSZ),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srbLeft->build();
+
+ d.srbRight = m_r->newShaderResourceBindings();
+ d.releasePool << d.srbRight;
+ d.srbRight->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf, d.rightOfs, UBUFSZ),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.msaaTex, d.sampler)
+ });
+ d.srbRight->build();
+
+ d.psLeft = m_r->newGraphicsPipeline();
+ d.releasePool << d.psLeft;
+ d.psLeft->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({ { 4 * sizeof(float) } });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ d.psLeft->setVertexInputLayout(inputLayout);
+ d.psLeft->setShaderResourceBindings(d.srbLeft);
+ d.psLeft->setRenderPassDescriptor(m_rp);
+ d.psLeft->build();
+
+ d.psRight = m_r->newGraphicsPipeline();
+ d.releasePool << d.psRight;
+ d.psRight->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+#ifndef NO_MSAA
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/texture_ms4.frag.qsb")) }
+#else
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+#endif
+ });
+ d.psRight->setVertexInputLayout(d.psLeft->vertexInputLayout());
+ d.psRight->setShaderResourceBindings(d.srbRight);
+ d.psRight->setRenderPassDescriptor(m_rp);
+ d.psRight->build();
+
+ // set up the offscreen triangle that goes into tex and msaaTex
+ d.triUbuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.releasePool << d.triUbuf;
+ d.triUbuf->build();
+ d.triSrb = m_r->newShaderResourceBindings();
+ d.releasePool << d.triSrb;
+ d.triSrb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.triUbuf)
+ });
+ d.triSrb->build();
+ d.rt = m_r->newTextureRenderTarget({ d.tex });
+ d.releasePool << d.rt;
+ d.rtRp = d.rt->newCompatibleRenderPassDescriptor();
+ d.releasePool << d.rtRp;
+ d.rt->setRenderPassDescriptor(d.rtRp);
+ d.rt->build();
+ d.msaaRt = m_r->newTextureRenderTarget({ d.msaaTex });
+ d.releasePool << d.msaaRt;
+ d.msaaRtRp = d.msaaRt->newCompatibleRenderPassDescriptor();
+ d.releasePool << d.msaaRtRp;
+ d.msaaRt->setRenderPassDescriptor(d.msaaRtRp);
+ d.msaaRt->build();
+ d.triPs = m_r->newGraphicsPipeline();
+ d.releasePool << d.triPs;
+ d.triPs->setSampleCount(1);
+ d.triPs->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/color.vert.qsb")) },
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/color.frag.qsb")) }
+ });
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+ d.triPs->setVertexInputLayout(inputLayout);
+ d.triPs->setShaderResourceBindings(d.triSrb);
+ d.triPs->setRenderPassDescriptor(d.rtRp);
+ d.triPs->build();
+ d.msaaTriPs = m_r->newGraphicsPipeline();
+ d.releasePool << d.msaaTriPs;
+#ifndef NO_MSAA
+ d.msaaTriPs->setSampleCount(4);
+#else
+ d.msaaTriPs->setSampleCount(1);
+#endif
+ d.msaaTriPs->setShaderStages(d.triPs->shaderStages());
+ d.msaaTriPs->setVertexInputLayout(d.triPs->vertexInputLayout());
+ d.msaaTriPs->setShaderResourceBindings(d.triSrb);
+ d.msaaTriPs->setRenderPassDescriptor(d.msaaRtRp);
+ d.msaaTriPs->build();
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+
+ // onscreen ubuf
+ qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0;
+ u->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+ u->updateDynamicBuffer(d.ubuf, d.rightOfs + 64, 4, &flip);
+
+ // offscreen ubuf
+ d.triBaseMvp = m_r->clipSpaceCorrMatrix();
+ d.triBaseMvp.perspective(45.0f, d.msaaTex->pixelSize().width() / float(d.msaaTex->pixelSize().height()), 0.01f, 1000.0f);
+ d.triBaseMvp.translate(0, 0, -2);
+ float opacity = 1.0f;
+ u->updateDynamicBuffer(d.triUbuf, 64, 4, &opacity);
+ }
+
+ if (d.winProj != m_proj) {
+ // onscreen buf, window size dependent
+ d.winProj = m_proj;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(2);
+ mvp.translate(-0.8f, 0, 0);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ mvp.translate(1.6f, 0, 0);
+ u->updateDynamicBuffer(d.ubuf, d.rightOfs, 64, mvp.constData());
+ }
+
+ // offscreen buf, apply the rotation on every frame
+ QMatrix4x4 triMvp = d.triBaseMvp;
+ triMvp.rotate(d.triRot, 0, 1, 0);
+ d.triRot += 1;
+ u->updateDynamicBuffer(d.triUbuf, 0, 64, triMvp.constData());
+
+ cb->resourceUpdate(u); // could have passed u to beginPass but exercise this one too
+
+ // offscreen
+ cb->beginPass(d.rt, QColor::fromRgbF(0.5f, 0.2f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.triPs);
+ cb->setViewport({ 0, 0, float(d.msaaTex->pixelSize().width()), float(d.msaaTex->pixelSize().height()) });
+ cb->setShaderResources();
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, sizeof(vertexData));
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+ cb->endPass();
+
+ // offscreen msaa
+ cb->beginPass(d.msaaRt, QColor::fromRgbF(0.5f, 0.2f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.msaaTriPs);
+ cb->setViewport({ 0, 0, float(d.msaaTex->pixelSize().width()), float(d.msaaTex->pixelSize().height()) });
+ cb->setShaderResources();
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+ cb->endPass();
+
+ // onscreen
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.psLeft); // showing the non-msaa version
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ vbufBinding.second = 0;
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+ cb->setGraphicsPipeline(d.psRight); // showing the msaa version, resolved in the shader
+ cb->setShaderResources();
+ cb->drawIndexed(6);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/msaatexture/msaatexture.pro b/tests/manual/rhi/msaatexture/msaatexture.pro
new file mode 100644
index 0000000000..0467e4dc9d
--- /dev/null
+++ b/tests/manual/rhi/msaatexture/msaatexture.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ msaatexture.cpp
+
+RESOURCES = msaatexture.qrc
diff --git a/tests/manual/rhi/msaatexture/msaatexture.qrc b/tests/manual/rhi/msaatexture/msaatexture.qrc
new file mode 100644
index 0000000000..ecd968481c
--- /dev/null
+++ b/tests/manual/rhi/msaatexture/msaatexture.qrc
@@ -0,0 +1,9 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+ <file alias="texture_ms4.frag.qsb">../shared/texture_ms4.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/multiwindow/multiwindow.cpp b/tests/manual/rhi/multiwindow/multiwindow.cpp
new file mode 100644
index 0000000000..a5eed78b1d
--- /dev/null
+++ b/tests/manual/rhi/multiwindow/multiwindow.cpp
@@ -0,0 +1,644 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 <QWidget>
+#include <QLabel>
+#include <QPlainTextEdit>
+#include <QPushButton>
+#include <QCheckBox>
+#include <QVBoxLayout>
+
+#include <QCommandLineParser>
+#include <QWindow>
+#include <QPlatformSurfaceEvent>
+#include <QElapsedTimer>
+
+#include <QtGui/private/qshader_p.h>
+#include <QFile>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#include <QOffscreenSurface>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QLoggingCategory>
+#include <QtGui/private/qrhivulkan_p.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+#endif
+
+#ifdef Q_OS_DARWIN
+#include <QtGui/private/qrhimetal_p.h>
+#endif
+
+enum GraphicsApi
+{
+ OpenGL,
+ Vulkan,
+ D3D11,
+ Metal
+};
+
+static GraphicsApi graphicsApi;
+
+static QString graphicsApiName()
+{
+ switch (graphicsApi) {
+ case OpenGL:
+ return QLatin1String("OpenGL 2.x");
+ case Vulkan:
+ return QLatin1String("Vulkan");
+ case D3D11:
+ return QLatin1String("Direct3D 11");
+ case Metal:
+ return QLatin1String("Metal");
+ default:
+ break;
+ }
+ return QString();
+}
+
+static struct {
+#if QT_CONFIG(vulkan)
+ QVulkanInstance *instance = nullptr;
+#endif
+ QRhi *r = nullptr;
+#ifndef QT_NO_OPENGL
+ QOffscreenSurface *fallbackSurface = nullptr;
+#endif
+} r;
+
+void createRhi()
+{
+#ifndef QT_NO_OPENGL
+ if (graphicsApi == OpenGL) {
+ r.fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ QRhiGles2InitParams params;
+ params.fallbackSurface = r.fallbackSurface;
+ //params.window = this;
+ r.r = QRhi::create(QRhi::OpenGLES2, &params);
+ }
+#endif
+
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan) {
+ QRhiVulkanInitParams params;
+ params.inst = r.instance;
+ //params.window = this;
+ r.r = QRhi::create(QRhi::Vulkan, &params);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (graphicsApi == D3D11) {
+ QRhiD3D11InitParams params;
+ params.enableDebugLayer = true;
+ r.r = QRhi::create(QRhi::D3D11, &params);
+ }
+#endif
+
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ QRhiMetalInitParams params;
+ r.r = QRhi::create(QRhi::Metal, &params);
+ }
+#endif
+
+ if (!r.r)
+ qFatal("Failed to create RHI backend");
+}
+
+void destroyRhi()
+{
+ delete r.r;
+
+#ifndef QT_NO_OPENGL
+ delete r.fallbackSurface;
+#endif
+}
+
+struct {
+ QVector<QWindow *> windows;
+
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+} d;
+
+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 QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+// can use just one rpd from whichever window comes first since they are
+// actually compatible due to all windows using the same config (have
+// depth-stencil, sample count 1, same format). this means the same pso can be
+// reused too.
+void ensureSharedResources(QRhiRenderPassDescriptor *rp)
+{
+ if (!d.vbuf) {
+ d.vbuf = r.r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ d.vbuf->build();
+ d.initialUpdates = r.r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, vertexData);
+ }
+
+ if (!d.ubuf) {
+ d.ubuf = r.r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.ubuf->build();
+ }
+
+ if (!d.srb) {
+ d.srb = r.r->newShaderResourceBindings();
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf)
+ });
+ d.srb->build();
+ }
+
+ if (!d.ps) {
+ d.ps = r.r->newGraphicsPipeline();
+
+ QRhiGraphicsPipeline::TargetBlend premulAlphaBlend;
+ premulAlphaBlend.enable = true;
+ d.ps->setTargetBlends({ premulAlphaBlend });
+
+ const QShader vs = getShader(QLatin1String(":/color.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/color.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ d.ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, vs },
+ { QRhiGraphicsShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(rp);
+
+ d.ps->build();
+ }
+}
+
+void destroySharedResources()
+{
+ delete d.ps;
+ d.ps = nullptr;
+
+ delete d.srb;
+ d.srb = nullptr;
+
+ delete d.vbuf;
+ d.vbuf = nullptr;
+
+ delete d.ubuf;
+ d.ubuf = nullptr;
+}
+
+class Window : public QWindow
+{
+public:
+ Window(const QString &title, const QColor &bgColor, int axis, bool noVSync);
+ ~Window();
+
+protected:
+ void init();
+ void releaseResources();
+ void resizeSwapChain();
+ void releaseSwapChain();
+ void render();
+
+ void exposeEvent(QExposeEvent *) override;
+ bool event(QEvent *) override;
+
+ QColor m_bgColor;
+ int m_rotationAxis;
+ bool m_noVSync;
+
+ bool m_running = false;
+ bool m_notExposed = false;
+ bool m_newlyExposed = false;
+
+ QMatrix4x4 m_proj;
+ QVector<QRhiResource *> m_releasePool;
+
+ bool m_hasSwapChain = false;
+ QRhiSwapChain *m_sc = nullptr;
+ QRhiRenderBuffer *m_ds = nullptr;
+ QRhiRenderPassDescriptor *m_rp = nullptr;
+
+ float m_rotation = 0;
+ float m_opacity = 1;
+ int m_opacityDir = -1;
+};
+
+Window::Window(const QString &title, const QColor &bgColor, int axis, bool noVSync)
+ : m_bgColor(bgColor),
+ m_rotationAxis(axis),
+ m_noVSync(noVSync)
+{
+ switch (graphicsApi) {
+ case OpenGL:
+ {
+#if QT_CONFIG(opengl)
+ setSurfaceType(OpenGLSurface);
+ QSurfaceFormat fmt = QRhiGles2InitParams::adjustedFormat(); // default + depth/stencil
+ fmt.setSwapInterval(noVSync ? 0 : 1); // + swap interval
+ setFormat(fmt);
+#endif
+ }
+ break;
+ case Vulkan:
+#if QT_CONFIG(vulkan)
+ setSurfaceType(VulkanSurface);
+ setVulkanInstance(r.instance);
+#endif
+ break;
+ case D3D11:
+ setSurfaceType(OpenGLSurface); // not a typo
+ break;
+ case Metal:
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
+ setSurfaceType(MetalSurface);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ resize(800, 600);
+ setTitle(title);
+}
+
+Window::~Window()
+{
+ releaseResources();
+}
+
+void Window::exposeEvent(QExposeEvent *)
+{
+ // initialize and start rendering when the window becomes usable for graphics purposes
+ if (isExposed() && !m_running) {
+ m_running = true;
+ init();
+ resizeSwapChain();
+ }
+
+ // stop pushing frames when not exposed (or size is 0)
+ if ((!isExposed() || (m_hasSwapChain && m_sc->surfacePixelSize().isEmpty())) && m_running)
+ m_notExposed = true;
+
+ // continue when exposed again and the surface has a valid size.
+ // note that the surface size can be (0, 0) even though size() reports a valid one...
+ if (isExposed() && m_running && m_notExposed && !m_sc->surfacePixelSize().isEmpty()) {
+ m_notExposed = false;
+ m_newlyExposed = true;
+ }
+
+ // always render a frame on exposeEvent() (when exposed) in order to update
+ // immediately on window resize.
+ if (isExposed() && !m_sc->surfacePixelSize().isEmpty())
+ render();
+}
+
+bool Window::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::UpdateRequest:
+ render();
+ break;
+
+ case QEvent::PlatformSurface:
+ // this is the proper time to tear down the swapchain (while the native window and surface are still around)
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ releaseSwapChain();
+ break;
+
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
+
+void Window::init()
+{
+ m_sc = r.r->newSwapChain();
+ m_ds = r.r->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
+ QSize(), // no need to set the size yet
+ 1,
+ QRhiRenderBuffer::UsedWithSwapChainOnly);
+ m_releasePool << m_ds;
+ m_sc->setWindow(this);
+ m_sc->setDepthStencil(m_ds);
+ if (m_noVSync)
+ m_sc->setFlags(QRhiSwapChain::NoVSync);
+
+ m_rp = m_sc->newCompatibleRenderPassDescriptor();
+ m_releasePool << m_rp;
+ m_sc->setRenderPassDescriptor(m_rp);
+
+ ensureSharedResources(m_rp);
+}
+
+void Window::releaseResources()
+{
+ qDeleteAll(m_releasePool);
+ m_releasePool.clear();
+
+ delete m_sc;
+ m_sc = nullptr;
+}
+
+void Window::resizeSwapChain()
+{
+ const QSize outputSize = m_sc->surfacePixelSize();
+
+ m_ds->setPixelSize(outputSize);
+ m_ds->build();
+
+ m_hasSwapChain = m_sc->buildOrResize();
+
+ m_proj = r.r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void Window::releaseSwapChain()
+{
+ if (m_hasSwapChain) {
+ m_hasSwapChain = false;
+ m_sc->release();
+ }
+}
+
+void Window::render()
+{
+ if (!m_hasSwapChain || m_notExposed)
+ return;
+
+ // If the window got resized or got newly exposed, resize the swapchain.
+ // (the newly-exposed case is not actually required by some
+ // platforms/backends, but f.ex. Vulkan on Windows seems to need it)
+ if (m_sc->currentPixelSize() != m_sc->surfacePixelSize() || m_newlyExposed) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ m_newlyExposed = false;
+ }
+
+ QRhi::FrameOpResult result = r.r->beginFrame(m_sc);
+ if (result == QRhi::FrameOpSwapChainOutOfDate) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ result = r.r->beginFrame(m_sc);
+ }
+ if (result != QRhi::FrameOpSuccess) {
+ requestUpdate();
+ return;
+ }
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+
+ QRhiResourceUpdateBatch *u = r.r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.rotate(m_rotation, m_rotationAxis == 0 ? 1 : 0, m_rotationAxis == 1 ? 1 : 0, m_rotationAxis == 2 ? 1 : 0);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ m_opacity += m_opacityDir * 0.005f;
+ if (m_opacity < 0.0f || m_opacity > 1.0f) {
+ m_opacityDir *= -1;
+ m_opacity = qBound(0.0f, m_opacity, 1.0f);
+ }
+ u->updateDynamicBuffer(d.ubuf, 64, 4, &m_opacity);
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(),
+ QColor::fromRgbF(float(m_bgColor.redF()), float(m_bgColor.greenF()), float(m_bgColor.blueF()), 1.0f),
+ { 1.0f, 0 },
+ u);
+
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+
+ cb->endPass();
+
+ r.r->endFrame(m_sc);
+
+ requestUpdate();
+}
+
+void createWindow(bool noVSync)
+{
+ static QColor colors[] = { Qt::red, Qt::green, Qt::blue, Qt::yellow, Qt::cyan, Qt::gray };
+ const int n = d.windows.count();
+ d.windows.append(new Window(QString::asprintf("Window #%d%s", n, noVSync ? " (no vsync)" : ""), colors[n % 6], n % 3, noVSync));
+ d.windows.last()->show();
+}
+
+void closeWindow()
+{
+ delete d.windows.takeLast();
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QApplication app(argc, argv);
+
+#if defined(Q_OS_WIN)
+ graphicsApi = D3D11;
+#elif defined(Q_OS_DARWIN)
+ graphicsApi = Metal;
+#elif QT_CONFIG(vulkan)
+ graphicsApi = Vulkan;
+#else
+ graphicsApi = OpenGL;
+#endif
+
+ QCommandLineParser cmdLineParser;
+ cmdLineParser.addHelpOption();
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ cmdLineParser.addOption(glOption);
+ QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
+ cmdLineParser.addOption(vkOption);
+ QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
+ cmdLineParser.addOption(d3dOption);
+ QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
+ cmdLineParser.addOption(mtlOption);
+ cmdLineParser.process(app);
+ if (cmdLineParser.isSet(glOption))
+ graphicsApi = OpenGL;
+ if (cmdLineParser.isSet(vkOption))
+ graphicsApi = Vulkan;
+ if (cmdLineParser.isSet(d3dOption))
+ graphicsApi = D3D11;
+ if (cmdLineParser.isSet(mtlOption))
+ graphicsApi = Metal;
+
+ qDebug("Selected graphics API is %s", qPrintable(graphicsApiName()));
+ qDebug("This is a multi-api example, use command line arguments to override:\n%s", qPrintable(cmdLineParser.helpText()));
+
+#if QT_CONFIG(vulkan)
+ r.instance = new QVulkanInstance;
+ if (graphicsApi == Vulkan) {
+#ifndef Q_OS_ANDROID
+ r.instance->setLayers({ "VK_LAYER_LUNARG_standard_validation" });
+#else
+ r.instance->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 (!r.instance->create()) {
+ qWarning("Failed to create Vulkan instance, switching to OpenGL");
+ graphicsApi = OpenGL;
+ }
+ }
+#endif
+
+ createRhi();
+
+ int winCount = 0;
+ QWidget w;
+ w.resize(800, 600);
+ w.setWindowTitle(QCoreApplication::applicationName() + QLatin1String(" - ") + graphicsApiName());
+ QVBoxLayout *layout = new QVBoxLayout(&w);
+
+ QPlainTextEdit *info = new QPlainTextEdit(
+ QLatin1String("This application tests rendering with the same QRhi instance (and so the same Vulkan/Metal/D3D device or OpenGL context) "
+ "to multiple windows via multiple QRhiSwapChain objects, from the same one thread. Some resources are shared across all windows.\n"
+ "\nNote that the behavior may differ depending on the underlying graphics API implementation and the number of windows. "
+ "One challenge here is the vsync throttling: with the default vsync/fifo presentation mode the behavior may differ between "
+ "platforms, drivers, and APIs as we present different swapchains' images in a row on the same thread. As a potential solution, "
+ "setting NoVSync on the second, third, and later window swapchains is offered as an option.\n"
+ "\n\nUsing API: ") + graphicsApiName());
+ info->setReadOnly(true);
+ layout->addWidget(info);
+ QLabel *label = new QLabel(QLatin1String("Window count: 0"));
+ layout->addWidget(label);
+ QCheckBox *vsCb = new QCheckBox(QLatin1String("Set NoVSync on all swapchains except the first"));
+ vsCb->setChecked(false);
+ layout->addWidget(vsCb);
+ QPushButton *btn = new QPushButton(QLatin1String("New window"));
+ QObject::connect(btn, &QPushButton::clicked, btn, [label, vsCb, &winCount] {
+ winCount += 1;
+ label->setText(QString::asprintf("Window count: %d", winCount));
+ const bool noVSync = vsCb->isChecked() && winCount > 1;
+ createWindow(noVSync);
+ });
+ layout->addWidget(btn);
+ btn = new QPushButton(QLatin1String("Close window"));
+ QObject::connect(btn, &QPushButton::clicked, btn, [label, &winCount] {
+ if (winCount > 0) {
+ winCount -= 1;
+ label->setText(QString::asprintf("Window count: %d", winCount));
+ closeWindow();
+ }
+ });
+ layout->addWidget(btn);
+ w.show();
+
+ int result = app.exec();
+
+ qDeleteAll(d.windows);
+
+ destroySharedResources();
+ destroyRhi();
+
+#if QT_CONFIG(vulkan)
+ delete r.instance;
+#endif
+
+ return result;
+}
diff --git a/tests/manual/rhi/multiwindow/multiwindow.pro b/tests/manual/rhi/multiwindow/multiwindow.pro
new file mode 100644
index 0000000000..b9c3867bf8
--- /dev/null
+++ b/tests/manual/rhi/multiwindow/multiwindow.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private widgets
+
+SOURCES = \
+ multiwindow.cpp
+
+RESOURCES = multiwindow.qrc
diff --git a/tests/manual/rhi/multiwindow/multiwindow.qrc b/tests/manual/rhi/multiwindow/multiwindow.qrc
new file mode 100644
index 0000000000..8cec4fa9ec
--- /dev/null
+++ b/tests/manual/rhi/multiwindow/multiwindow.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp
new file mode 100644
index 0000000000..45818e91e9
--- /dev/null
+++ b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.cpp
@@ -0,0 +1,829 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 <QWidget>
+#include <QLabel>
+#include <QPlainTextEdit>
+#include <QPushButton>
+#include <QCheckBox>
+#include <QVBoxLayout>
+
+#include <QThread>
+#include <QMutex>
+#include <QWaitCondition>
+#include <QQueue>
+#include <QEvent>
+#include <QCommandLineParser>
+#include <QElapsedTimer>
+
+#include <QtGui/private/qshader_p.h>
+#include <QFile>
+#include <QtGui/private/qrhiprofiler_p.h>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#include <QOffscreenSurface>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QLoggingCategory>
+#include <QtGui/private/qrhivulkan_p.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+#endif
+
+#ifdef Q_OS_DARWIN
+#include <QtGui/private/qrhimetal_p.h>
+#endif
+
+#include "window.h"
+
+#include "../shared/cube.h"
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+static GraphicsApi graphicsApi;
+
+static QString graphicsApiName()
+{
+ switch (graphicsApi) {
+ case OpenGL:
+ return QLatin1String("OpenGL 2.x");
+ case Vulkan:
+ return QLatin1String("Vulkan");
+ case D3D11:
+ return QLatin1String("Direct3D 11");
+ case Metal:
+ return QLatin1String("Metal");
+ default:
+ break;
+ }
+ return QString();
+}
+
+#if QT_CONFIG(vulkan)
+QVulkanInstance *instance = nullptr;
+#endif
+
+// Window (main thread) emit signals -> Renderer::send* (main thread) -> event queue (add on main, process on render thread) -> Renderer::renderEvent (render thread)
+
+// event queue is taken from the Qt Quick scenegraph as-is
+// all this below is conceptually the same as the QSG threaded render loop
+class RenderThreadEventQueue : public QQueue<QEvent *>
+{
+public:
+ RenderThreadEventQueue()
+ : waiting(false)
+ {
+ }
+
+ void addEvent(QEvent *e) {
+ mutex.lock();
+ enqueue(e);
+ if (waiting)
+ condition.wakeOne();
+ mutex.unlock();
+ }
+
+ QEvent *takeEvent(bool wait) {
+ mutex.lock();
+ if (isEmpty() && wait) {
+ waiting = true;
+ condition.wait(&mutex);
+ waiting = false;
+ }
+ QEvent *e = dequeue();
+ mutex.unlock();
+ return e;
+ }
+
+ bool hasMoreEvents() {
+ mutex.lock();
+ bool has = !isEmpty();
+ mutex.unlock();
+ return has;
+ }
+
+private:
+ QMutex mutex;
+ QWaitCondition condition;
+ bool waiting;
+};
+
+struct Renderer;
+
+struct Thread : public QThread
+{
+ Thread(Renderer *renderer_)
+ : renderer(renderer_)
+ {
+ active = true;
+ start();
+ }
+ void run() override;
+
+ Renderer *renderer;
+ bool active;
+ RenderThreadEventQueue eventQueue;
+ bool sleeping = false;
+ bool stopEventProcessing = false;
+ bool pendingRender = false;
+ bool pendingRenderIsNewExpose = false;
+ // mutex and cond used to allow the main thread waiting until something completes on the render thread
+ QMutex mutex;
+ QWaitCondition cond;
+};
+
+class RenderThreadEvent : public QEvent
+{
+public:
+ RenderThreadEvent(QEvent::Type type) : QEvent(type) { }
+};
+
+class InitEvent : public RenderThreadEvent
+{
+public:
+ static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 1);
+ InitEvent() : RenderThreadEvent(TYPE)
+ { }
+};
+
+class RequestRenderEvent : public RenderThreadEvent
+{
+public:
+ static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 2);
+ RequestRenderEvent(bool newlyExposed_) : RenderThreadEvent(TYPE), newlyExposed(newlyExposed_)
+ { }
+ bool newlyExposed;
+};
+
+class SurfaceCleanupEvent : public RenderThreadEvent
+{
+public:
+ static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 3);
+ SurfaceCleanupEvent() : RenderThreadEvent(TYPE)
+ { }
+};
+
+class CloseEvent : public RenderThreadEvent
+{
+public:
+ static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 4);
+ CloseEvent() : RenderThreadEvent(TYPE)
+ { }
+};
+
+class SyncSurfaceSizeEvent : public RenderThreadEvent
+{
+public:
+ static const QEvent::Type TYPE = QEvent::Type(QEvent::User + 5);
+ SyncSurfaceSizeEvent() : RenderThreadEvent(TYPE)
+ { }
+};
+
+struct Renderer
+{
+ // ctor and dtor and send* are called main thread, rest on the render thread
+
+ Renderer(QWindow *w, const QColor &bgColor, int rotationAxis);
+ ~Renderer();
+
+ void sendInit();
+ void sendRender(bool newlyExposed);
+ void sendSurfaceGoingAway();
+ void sendSyncSurfaceSize();
+
+ QWindow *window;
+ Thread *thread;
+ QRhi *r = nullptr;
+#ifndef QT_NO_OPENGL
+ QOffscreenSurface *fallbackSurface = nullptr;
+#endif
+
+ void createRhi();
+ void destroyRhi();
+ void renderEvent(QEvent *e);
+ void init();
+ void releaseSwapChain();
+ void releaseResources();
+ void render(bool newlyExposed, bool wakeBeforePresent);
+
+ QColor m_bgColor;
+ int m_rotationAxis;
+
+ QVector<QRhiResource *> m_releasePool;
+ bool m_hasSwapChain = false;
+ QRhiSwapChain *m_sc = nullptr;
+ QRhiRenderBuffer *m_ds = nullptr;
+ QRhiRenderPassDescriptor *m_rp = nullptr;
+
+ QRhiBuffer *m_vbuf = nullptr;
+ QRhiBuffer *m_ubuf = nullptr;
+ QRhiTexture *m_tex = nullptr;
+ QRhiSampler *m_sampler = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+ QRhiResourceUpdateBatch *m_initialUpdates = nullptr;
+
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ int m_frameCount = 0;
+};
+
+void Thread::run()
+{
+ while (active) {
+ if (pendingRender) {
+ pendingRender = false;
+ renderer->render(pendingRenderIsNewExpose, false);
+ }
+
+ while (eventQueue.hasMoreEvents()) {
+ QEvent *e = eventQueue.takeEvent(false);
+ renderer->renderEvent(e);
+ delete e;
+ }
+
+ if (active && !pendingRender) {
+ sleeping = true;
+ stopEventProcessing = false;
+ while (!stopEventProcessing) {
+ QEvent *e = eventQueue.takeEvent(true);
+ renderer->renderEvent(e);
+ delete e;
+ }
+ sleeping = false;
+ }
+ }
+}
+
+Renderer::Renderer(QWindow *w, const QColor &bgColor, int rotationAxis)
+ : window(w),
+ m_bgColor(bgColor),
+ m_rotationAxis(rotationAxis)
+{ // main thread
+ thread = new Thread(this);
+
+#ifndef QT_NO_OPENGL
+ if (graphicsApi == OpenGL)
+ fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+#endif
+}
+
+Renderer::~Renderer()
+{ // main thread
+ thread->eventQueue.addEvent(new CloseEvent);
+ thread->wait();
+ delete thread;
+
+#ifndef QT_NO_OPENGL
+ delete fallbackSurface;
+#endif
+}
+
+void Renderer::createRhi()
+{
+ if (r)
+ return;
+
+ qDebug() << "renderer" << this << "creating rhi";
+ QRhi::Flags rhiFlags = QRhi::EnableProfiling;
+
+#ifndef QT_NO_OPENGL
+ if (graphicsApi == OpenGL) {
+ QRhiGles2InitParams params;
+ params.fallbackSurface = fallbackSurface;
+ params.window = window;
+ r = QRhi::create(QRhi::OpenGLES2, &params, rhiFlags);
+ }
+#endif
+
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan) {
+ QRhiVulkanInitParams params;
+ params.inst = instance;
+ params.window = window;
+ r = QRhi::create(QRhi::Vulkan, &params, rhiFlags);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (graphicsApi == D3D11) {
+ QRhiD3D11InitParams params;
+ params.enableDebugLayer = true;
+ r = QRhi::create(QRhi::D3D11, &params, rhiFlags);
+ }
+#endif
+
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ QRhiMetalInitParams params;
+ r = QRhi::create(QRhi::Metal, &params, rhiFlags);
+ }
+#endif
+
+ if (!r)
+ qFatal("Failed to create RHI backend");
+}
+
+void Renderer::destroyRhi()
+{
+ qDebug() << "renderer" << this << "destroying rhi";
+ delete r;
+ r = nullptr;
+}
+
+void Renderer::renderEvent(QEvent *e)
+{
+ Q_ASSERT(QThread::currentThread() == thread);
+
+ if (thread->sleeping)
+ thread->stopEventProcessing = true;
+
+ switch (int(e->type())) {
+ case InitEvent::TYPE:
+ qDebug() << "renderer" << this << "for window" << window << "is initializing";
+ createRhi();
+ init();
+ break;
+ case RequestRenderEvent::TYPE:
+ thread->pendingRender = true;
+ thread->pendingRenderIsNewExpose = static_cast<RequestRenderEvent *>(e)->newlyExposed;
+ break;
+ case SurfaceCleanupEvent::TYPE: // when the QWindow is closed, before QPlatformWindow goes away
+ thread->mutex.lock();
+ qDebug() << "renderer" << this << "for window" << window << "is destroying swapchain";
+ thread->pendingRender = false;
+ releaseSwapChain();
+ thread->cond.wakeOne();
+ thread->mutex.unlock();
+ break;
+ case CloseEvent::TYPE: // when destroying the window+renderer (NB not the same as hitting X on the window, that's just QWindow close)
+ qDebug() << "renderer" << this << "for window" << window << "is shutting down";
+ thread->pendingRender = false;
+ thread->active = false;
+ thread->stopEventProcessing = true;
+ releaseResources();
+ destroyRhi();
+ break;
+ case SyncSurfaceSizeEvent::TYPE:
+ thread->mutex.lock();
+ thread->pendingRender = false;
+ render(false, true);
+ break;
+ default:
+ break;
+ }
+}
+
+void Renderer::init()
+{
+ m_sc = r->newSwapChain();
+ m_ds = r->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
+ QSize(), // no need to set the size yet
+ 1,
+ QRhiRenderBuffer::UsedWithSwapChainOnly);
+ m_releasePool << m_ds;
+ m_sc->setWindow(window);
+ m_sc->setDepthStencil(m_ds);
+ m_rp = m_sc->newCompatibleRenderPassDescriptor();
+ m_releasePool << m_rp;
+ m_sc->setRenderPassDescriptor(m_rp);
+
+ m_vbuf = r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ m_releasePool << m_vbuf;
+ m_vbuf->build();
+
+ m_ubuf = r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 4);
+ m_releasePool << m_ubuf;
+ m_ubuf->build();
+
+ QImage image = QImage(QLatin1String(":/qt256.png")).convertToFormat(QImage::Format_RGBA8888);
+ m_tex = r->newTexture(QRhiTexture::RGBA8, image.size());
+ m_releasePool << m_tex;
+ m_tex->build();
+
+ m_sampler = r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ m_releasePool << m_sampler;
+ m_sampler->build();
+
+ m_srb = r->newShaderResourceBindings();
+ m_releasePool << m_srb;
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, m_tex, m_sampler)
+ });
+ m_srb->build();
+
+ m_ps = r->newGraphicsPipeline();
+ m_releasePool << m_ps;
+
+ m_ps->setDepthTest(true);
+ m_ps->setDepthWrite(true);
+ m_ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ m_ps->setCullMode(QRhiGraphicsPipeline::Back);
+ m_ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ m_ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) },
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb);
+ m_ps->setRenderPassDescriptor(m_rp);
+
+ m_ps->build();
+
+ m_initialUpdates = r->nextResourceUpdateBatch();
+
+ m_initialUpdates->uploadStaticBuffer(m_vbuf, cube);
+
+ qint32 flip = 0;
+ m_initialUpdates->updateDynamicBuffer(m_ubuf, 64, 4, &flip);
+
+ m_initialUpdates->uploadTexture(m_tex, image);
+}
+
+void Renderer::releaseSwapChain()
+{
+ if (m_hasSwapChain) {
+ m_hasSwapChain = false;
+ m_sc->release();
+ }
+}
+
+void Renderer::releaseResources()
+{
+ qDeleteAll(m_releasePool);
+ m_releasePool.clear();
+
+ delete m_sc;
+ m_sc = nullptr;
+}
+
+void Renderer::render(bool newlyExposed, bool wakeBeforePresent)
+{
+ // This function handles both resizing and rendering. Resizes have some
+ // complications due to the threaded model (check exposeEvent and
+ // sendSyncSurfaceSize) but don't have to worry about that in here.
+
+ auto buildOrResizeSwapChain = [this] {
+ qDebug() << "renderer" << this << "build or resize swapchain for window" << window;
+ const QSize outputSize = m_sc->surfacePixelSize();
+ qDebug() << " size is" << outputSize;
+ m_ds->setPixelSize(outputSize);
+ m_ds->build();
+ m_hasSwapChain = m_sc->buildOrResize();
+ m_proj = r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+ };
+
+ auto wakeUpIfNeeded = [wakeBeforePresent, this] {
+ // make sure the main/gui thread is not blocked when issuing the Present (or equivalent)
+ if (wakeBeforePresent) {
+ thread->cond.wakeOne();
+ thread->mutex.unlock();
+ }
+ };
+
+ const QSize surfaceSize = m_sc->surfacePixelSize();
+ if (surfaceSize.isEmpty()) {
+ wakeUpIfNeeded();
+ return;
+ }
+
+ if (newlyExposed || m_sc->currentPixelSize() != surfaceSize)
+ buildOrResizeSwapChain();
+
+ if (!m_hasSwapChain) {
+ wakeUpIfNeeded();
+ return;
+ }
+
+ QRhi::FrameOpResult result = r->beginFrame(m_sc);
+ if (result == QRhi::FrameOpSwapChainOutOfDate) {
+ buildOrResizeSwapChain();
+ if (!m_hasSwapChain) {
+ wakeUpIfNeeded();
+ return;
+ }
+ result = r->beginFrame(m_sc);
+ }
+ if (result != QRhi::FrameOpSuccess) {
+ wakeUpIfNeeded();
+ return;
+ }
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSize = m_sc->currentPixelSize();
+
+ QRhiResourceUpdateBatch *u = r->nextResourceUpdateBatch();
+ if (m_initialUpdates) {
+ u->merge(m_initialUpdates);
+ m_initialUpdates->release();
+ m_initialUpdates = nullptr;
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(0.5f);
+ mvp.rotate(m_rotation, m_rotationAxis == 0 ? 1 : 0, m_rotationAxis == 1 ? 1 : 0, m_rotationAxis == 2 ? 1 : 0);
+ u->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(),
+ QColor::fromRgbF(float(m_bgColor.redF()), float(m_bgColor.greenF()), float(m_bgColor.blueF()), 1.0f),
+ { 1.0f, 0 },
+ u);
+
+ cb->setGraphicsPipeline(m_ps);
+ cb->setViewport(QRhiViewport(0, 0, outputSize.width(), outputSize.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { m_vbuf, 0 },
+ { m_vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+
+ cb->endPass();
+
+ wakeUpIfNeeded();
+
+ r->endFrame(m_sc);
+
+ m_frameCount += 1;
+ if ((m_frameCount % 300) == 0) {
+ const QRhiProfiler::CpuTime ff = r->profiler()->frameToFrameTimes(m_sc);
+ const QRhiProfiler::CpuTime be = r->profiler()->frameBuildTimes(m_sc);
+ const QRhiProfiler::GpuTime gp = r->profiler()->gpuFrameTimes(m_sc);
+ if (r->isFeatureSupported(QRhi::Timestamps)) {
+ qDebug("[renderer %p] frame-to-frame: min %lld max %lld avg %f. "
+ "frame build: min %lld max %lld avg %f. "
+ "gpu frame time: min %f max %f avg %f",
+ this,
+ ff.minTime, ff.maxTime, ff.avgTime,
+ be.minTime, be.maxTime, be.avgTime,
+ gp.minTime, gp.maxTime, gp.avgTime);
+ } else {
+ qDebug("[renderer %p] frame-to-frame: min %lld max %lld avg %f. "
+ "frame build: min %lld max %lld avg %f. ",
+ this,
+ ff.minTime, ff.maxTime, ff.avgTime,
+ be.minTime, be.maxTime, be.avgTime);
+ }
+ }
+}
+
+void Renderer::sendInit()
+{ // main thread
+ InitEvent *e = new InitEvent;
+ thread->eventQueue.addEvent(e);
+}
+
+void Renderer::sendRender(bool newlyExposed)
+{ // main thread
+ RequestRenderEvent *e = new RequestRenderEvent(newlyExposed);
+ thread->eventQueue.addEvent(e);
+}
+
+void Renderer::sendSurfaceGoingAway()
+{ // main thread
+ SurfaceCleanupEvent *e = new SurfaceCleanupEvent;
+
+ // cannot let this thread to proceed with tearing down the native window
+ // before the render thread completes the swapchain release
+ thread->mutex.lock();
+
+ thread->eventQueue.addEvent(e);
+
+ thread->cond.wait(&thread->mutex);
+ thread->mutex.unlock();
+}
+
+void Renderer::sendSyncSurfaceSize()
+{ // main thread
+ SyncSurfaceSizeEvent *e = new SyncSurfaceSizeEvent;
+ // must block to prevent surface size mess. the render thread will do a
+ // full rendering round before it unlocks which is good since it can thus
+ // pick up and the surface (window) size atomically.
+ thread->mutex.lock();
+ thread->eventQueue.addEvent(e);
+ thread->cond.wait(&thread->mutex);
+ thread->mutex.unlock();
+}
+
+struct WindowAndRenderer
+{
+ QWindow *window;
+ Renderer *renderer;
+};
+
+QVector<WindowAndRenderer> windows;
+
+void createWindow()
+{
+ static QColor colors[] = { Qt::red, Qt::green, Qt::blue, Qt::yellow, Qt::cyan, Qt::gray };
+ const int n = windows.count();
+ Window *w = new Window(QString::asprintf("Window+Thread #%d (%s)", n, qPrintable(graphicsApiName())), graphicsApi);
+ Renderer *renderer = new Renderer(w, colors[n % 6], n % 3);;
+ QObject::connect(w, &Window::initRequested, w, [renderer] {
+ renderer->sendInit();
+ });
+ QObject::connect(w, &Window::renderRequested, w, [w, renderer](bool newlyExposed) {
+ renderer->sendRender(newlyExposed);
+ w->requestUpdate();
+ });
+ QObject::connect(w, &Window::surfaceGoingAway, w, [renderer] {
+ renderer->sendSurfaceGoingAway();
+ });
+ QObject::connect(w, &Window::syncSurfaceSizeRequested, w, [renderer] {
+ renderer->sendSyncSurfaceSize();
+ });
+ windows.append({ w, renderer });
+ w->show();
+}
+
+void closeWindow()
+{
+ WindowAndRenderer wr = windows.takeLast();
+ delete wr.renderer;
+ delete wr.window;
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QApplication app(argc, argv);
+
+#if defined(Q_OS_WIN)
+ graphicsApi = D3D11;
+#elif defined(Q_OS_DARWIN)
+ graphicsApi = Metal;
+#elif QT_CONFIG(vulkan)
+ graphicsApi = Vulkan;
+#else
+ graphicsApi = OpenGL;
+#endif
+
+ QCommandLineParser cmdLineParser;
+ cmdLineParser.addHelpOption();
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ cmdLineParser.addOption(glOption);
+ QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
+ cmdLineParser.addOption(vkOption);
+ QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
+ cmdLineParser.addOption(d3dOption);
+ QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
+ cmdLineParser.addOption(mtlOption);
+ cmdLineParser.process(app);
+ if (cmdLineParser.isSet(glOption))
+ graphicsApi = OpenGL;
+ if (cmdLineParser.isSet(vkOption))
+ graphicsApi = Vulkan;
+ if (cmdLineParser.isSet(d3dOption))
+ graphicsApi = D3D11;
+ if (cmdLineParser.isSet(mtlOption))
+ graphicsApi = Metal;
+
+ qDebug("Selected graphics API is %s", qPrintable(graphicsApiName()));
+ qDebug("This is a multi-api example, use command line arguments to override:\n%s", qPrintable(cmdLineParser.helpText()));
+
+#if QT_CONFIG(vulkan)
+ instance = new QVulkanInstance;
+ if (graphicsApi == Vulkan) {
+#ifndef Q_OS_ANDROID
+ instance->setLayers({ "VK_LAYER_LUNARG_standard_validation" });
+#else
+ instance->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 (!instance->create()) {
+ qWarning("Failed to create Vulkan instance, switching to OpenGL");
+ graphicsApi = OpenGL;
+ }
+ }
+#endif
+
+ int winCount = 0;
+ QWidget w;
+ w.resize(800, 600);
+ w.setWindowTitle(QCoreApplication::applicationName() + QLatin1String(" - ") + graphicsApiName());
+ QVBoxLayout *layout = new QVBoxLayout(&w);
+
+ QPlainTextEdit *info = new QPlainTextEdit(
+ QLatin1String("This application tests rendering on a separate thread per window, with dedicated QRhi instances and resources. "
+ "\n\nThis is the same concept as the Qt Quick Scenegraph's threaded render loop. This should allow rendering to the different windows "
+ "without unintentionally throttling each other's threads."
+ "\n\nUsing API: ") + graphicsApiName());
+ info->setReadOnly(true);
+ layout->addWidget(info);
+ QLabel *label = new QLabel(QLatin1String("Window and thread count: 0"));
+ layout->addWidget(label);
+ QPushButton *btn = new QPushButton(QLatin1String("New window"));
+ QObject::connect(btn, &QPushButton::clicked, btn, [label, &winCount] {
+ winCount += 1;
+ label->setText(QString::asprintf("Window count: %d", winCount));
+ createWindow();
+ });
+ layout->addWidget(btn);
+ btn = new QPushButton(QLatin1String("Close window"));
+ QObject::connect(btn, &QPushButton::clicked, btn, [label, &winCount] {
+ if (winCount > 0) {
+ winCount -= 1;
+ label->setText(QString::asprintf("Window count: %d", winCount));
+ closeWindow();
+ }
+ });
+ layout->addWidget(btn);
+ w.show();
+
+ int result = app.exec();
+
+ for (const WindowAndRenderer &wr : windows) {
+ delete wr.renderer;
+ delete wr.window;
+ }
+
+#if QT_CONFIG(vulkan)
+ delete instance;
+#endif
+
+ return result;
+}
diff --git a/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.pro b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.pro
new file mode 100644
index 0000000000..0b78518b9b
--- /dev/null
+++ b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+QT += gui-private widgets
+
+SOURCES = \
+ multiwindow_threaded.cpp \
+ window.cpp
+
+HEADERS = \
+ window.h
+
+RESOURCES = multiwindow_threaded.qrc
diff --git a/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.qrc b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.qrc
new file mode 100644
index 0000000000..742b2b77af
--- /dev/null
+++ b/tests/manual/rhi/multiwindow_threaded/multiwindow_threaded.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="qt256.png">../shared/qt256.png</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/multiwindow_threaded/window.cpp b/tests/manual/rhi/multiwindow_threaded/window.cpp
new file mode 100644
index 0000000000..aa7b479047
--- /dev/null
+++ b/tests/manual/rhi/multiwindow_threaded/window.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "window.h"
+#include <QPlatformSurfaceEvent>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#endif
+
+#if QT_CONFIG(vulkan)
+extern QVulkanInstance *instance;
+#endif
+
+Window::Window(const QString &title, GraphicsApi api)
+{
+ switch (api) {
+ case OpenGL:
+#if QT_CONFIG(opengl)
+ setSurfaceType(OpenGLSurface);
+ setFormat(QRhiGles2InitParams::adjustedFormat());
+#endif
+ break;
+ case Vulkan:
+#if QT_CONFIG(vulkan)
+ setSurfaceType(VulkanSurface);
+ setVulkanInstance(instance);
+#endif
+ break;
+ case D3D11:
+ setSurfaceType(OpenGLSurface); // not a typo
+ break;
+ case Metal:
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
+ setSurfaceType(MetalSurface);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ resize(800, 600);
+ setTitle(title);
+}
+
+Window::~Window()
+{
+}
+
+void Window::exposeEvent(QExposeEvent *)
+{
+ if (isExposed()) {
+ if (!m_running) {
+ // initialize and start rendering when the window becomes usable for graphics purposes
+ m_running = true;
+ m_notExposed = false;
+ emit initRequested();
+ emit renderRequested(true);
+ } else {
+ // continue when exposed again
+ if (m_notExposed) {
+ m_notExposed = false;
+ emit renderRequested(true);
+ } else {
+ // resize generates exposes - this is very important here (unlike in a single-threaded renderer)
+ emit syncSurfaceSizeRequested();
+ }
+ }
+ } else {
+ // stop pushing frames when not exposed (on some platforms this is essential, optional on others)
+ if (m_running)
+ m_notExposed = true;
+ }
+}
+
+bool Window::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::UpdateRequest:
+ if (!m_notExposed)
+ emit renderRequested(false);
+ break;
+
+ case QEvent::PlatformSurface:
+ // this is the proper time to tear down the swapchain (while the native window and surface are still around)
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ emit surfaceGoingAway();
+ break;
+
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
diff --git a/tests/manual/rhi/multiwindow_threaded/window.h b/tests/manual/rhi/multiwindow_threaded/window.h
new file mode 100644
index 0000000000..7810858d0a
--- /dev/null
+++ b/tests/manual/rhi/multiwindow_threaded/window.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 WINDOW_H
+#define WINDOW_H
+
+#include <QWindow>
+
+enum GraphicsApi
+{
+ OpenGL,
+ Vulkan,
+ D3D11,
+ Metal
+};
+
+class Window : public QWindow
+{
+ Q_OBJECT
+
+public:
+ Window(const QString &title, GraphicsApi api);
+ ~Window();
+
+ void exposeEvent(QExposeEvent *) override;
+ bool event(QEvent *) override;
+
+signals:
+ void initRequested();
+ void renderRequested(bool newlyExposed);
+ void surfaceGoingAway();
+ void syncSurfaceSizeRequested();
+
+protected:
+ bool m_running = false;
+ bool m_notExposed = true;
+};
+
+#endif
diff --git a/tests/manual/rhi/offscreen/offscreen.cpp b/tests/manual/rhi/offscreen/offscreen.cpp
new file mode 100644
index 0000000000..838dc9d2c8
--- /dev/null
+++ b/tests/manual/rhi/offscreen/offscreen.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 <QImage>
+#include <QFileInfo>
+#include <QFile>
+#include <QLoggingCategory>
+#include <QCommandLineParser>
+#include <QtGui/private/qshader_p.h>
+
+#include <QtGui/private/qrhinull_p.h>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#include <QOffscreenSurface>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QLoggingCategory>
+#include <QtGui/private/qrhivulkan_p.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+#endif
+
+#ifdef Q_OS_DARWIN
+#include <QtGui/private/qrhimetal_p.h>
+#endif
+
+//#define TEST_FINISH
+
+static float vertexData[] = { // Y up (note m_proj), CCW
+ 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 QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+enum GraphicsApi
+{
+ OpenGL,
+ Vulkan,
+ D3D11,
+ Metal,
+ Null
+};
+
+GraphicsApi graphicsApi;
+
+QString graphicsApiName()
+{
+ switch (graphicsApi) {
+ case OpenGL:
+ return QLatin1String("OpenGL 2.x");
+ case Vulkan:
+ return QLatin1String("Vulkan");
+ case D3D11:
+ return QLatin1String("Direct3D 11");
+ case Metal:
+ return QLatin1String("Metal");
+ case Null:
+ return QLatin1String("Null");
+ default:
+ break;
+ }
+ return QString();
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+#if defined(Q_OS_WIN)
+ graphicsApi = D3D11;
+#elif defined(Q_OS_DARWIN)
+ graphicsApi = Metal;
+#elif QT_CONFIG(vulkan)
+ graphicsApi = Vulkan;
+#else
+ graphicsApi = OpenGL;
+#endif
+
+ QCommandLineParser cmdLineParser;
+ cmdLineParser.addHelpOption();
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ cmdLineParser.addOption(glOption);
+ QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
+ cmdLineParser.addOption(vkOption);
+ QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
+ cmdLineParser.addOption(d3dOption);
+ QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
+ cmdLineParser.addOption(mtlOption);
+ QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null"));
+ cmdLineParser.addOption(nullOption);
+ cmdLineParser.process(app);
+ if (cmdLineParser.isSet(glOption))
+ graphicsApi = OpenGL;
+ if (cmdLineParser.isSet(vkOption))
+ graphicsApi = Vulkan;
+ if (cmdLineParser.isSet(d3dOption))
+ graphicsApi = D3D11;
+ if (cmdLineParser.isSet(mtlOption))
+ graphicsApi = Metal;
+ if (cmdLineParser.isSet(nullOption))
+ graphicsApi = Null;
+
+ qDebug("Selected graphics API is %s", qPrintable(graphicsApiName()));
+ qDebug("This is a multi-api example, use command line arguments to override:\n%s", qPrintable(cmdLineParser.helpText()));
+
+ QRhi *r = nullptr;
+
+ if (graphicsApi == Null) {
+ QRhiNullInitParams params;
+ r = QRhi::create(QRhi::Null, &params);
+ }
+
+#if QT_CONFIG(vulkan)
+ QVulkanInstance inst;
+ if (graphicsApi == Vulkan) {
+ 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()) {
+ QRhiVulkanInitParams params;
+ params.inst = &inst;
+ r = QRhi::create(QRhi::Vulkan, &params);
+ } else {
+ qWarning("Failed to create Vulkan instance, switching to OpenGL");
+ graphicsApi = OpenGL;
+ }
+ }
+#endif
+
+#ifndef QT_NO_OPENGL
+ QScopedPointer<QOffscreenSurface> offscreenSurface;
+ if (graphicsApi == OpenGL) {
+ offscreenSurface.reset(QRhiGles2InitParams::newFallbackSurface());
+ QRhiGles2InitParams params;
+ params.fallbackSurface = offscreenSurface.data();
+ r = QRhi::create(QRhi::OpenGLES2, &params);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (graphicsApi == D3D11) {
+ QRhiD3D11InitParams params;
+ params.enableDebugLayer = true;
+ r = QRhi::create(QRhi::D3D11, &params);
+ }
+#endif
+
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ QRhiMetalInitParams params;
+ r = QRhi::create(QRhi::Metal, &params);
+ }
+#endif
+
+ if (!r)
+ qFatal("Failed to initialize RHI");
+
+ QRhiTexture *tex = r->newTexture(QRhiTexture::RGBA8, QSize(1280, 720), 1, QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
+ tex->build();
+ QRhiTextureRenderTarget *rt = r->newTextureRenderTarget({ tex });
+ QRhiRenderPassDescriptor *rp = rt->newCompatibleRenderPassDescriptor();
+ rt->setRenderPassDescriptor(rp);
+ rt->build();
+
+ QMatrix4x4 proj = r->clipSpaceCorrMatrix();
+ proj.perspective(45.0f, 1280 / 720.f, 0.01f, 1000.0f);
+ proj.translate(0, 0, -4);
+
+ QRhiBuffer *vbuf = r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ vbuf->build();
+
+ QRhiBuffer *ubuf = r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ ubuf->build();
+
+ QRhiShaderResourceBindings *srb = r->newShaderResourceBindings();
+ srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
+ });
+ srb->build();
+
+ QRhiGraphicsPipeline *ps = r->newGraphicsPipeline();
+
+ QRhiGraphicsPipeline::TargetBlend premulAlphaBlend;
+ premulAlphaBlend.enable = true;
+ ps->setTargetBlends({ premulAlphaBlend });
+
+ const QShader vs = getShader(QLatin1String(":/color.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/color.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, vs },
+ { QRhiGraphicsShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+
+ ps->setVertexInputLayout(inputLayout);
+ ps->setShaderResourceBindings(srb);
+ ps->setRenderPassDescriptor(rp);
+ ps->build();
+
+ int frame = 0;
+ for (; frame < 20; ++frame) {
+ QRhiCommandBuffer *cb;
+ if (r->beginOffscreenFrame(&cb) != QRhi::FrameOpSuccess)
+ break;
+
+ qDebug("Generating offscreen frame %d", frame);
+ QRhiResourceUpdateBatch *u = r->nextResourceUpdateBatch();
+ if (frame == 0)
+ u->uploadStaticBuffer(vbuf, vertexData);
+
+ static float rotation = 0.0f;
+ QMatrix4x4 mvp = proj;
+ mvp.rotate(rotation, 0, 1, 0);
+ u->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
+ rotation += 5.0f;
+ static float opacity = 1.0f;
+ static int opacityDir= 1;
+ u->updateDynamicBuffer(ubuf, 64, 4, &opacity);
+ opacity += opacityDir * 0.005f;
+ if (opacity < 0.0f || opacity > 1.0f) {
+ opacityDir *= -1;
+ opacity = qBound(0.0f, opacity, 1.0f);
+ }
+
+ cb->beginPass(rt, { 0, 1, 0, 1 }, { 1, 0 }, u);
+ cb->setGraphicsPipeline(ps);
+ cb->setViewport({ 0, 0, 1280, 720 });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+
+ u = r->nextResourceUpdateBatch();
+ QRhiReadbackDescription rb(tex);
+ QRhiReadbackResult rbResult;
+ rbResult.completed = [frame] { qDebug(" - readback %d completed", frame); };
+ u->readBackTexture(rb, &rbResult);
+
+ cb->endPass(u);
+
+ qDebug("Submit and wait");
+#ifdef TEST_FINISH
+ r->finish();
+#else
+ r->endOffscreenFrame();
+#endif
+ // The data should be ready either because endOffscreenFrame() waits
+ // for completion or because finish() did.
+ if (!rbResult.data.isEmpty()) {
+ const uchar *p = reinterpret_cast<const uchar *>(rbResult.data.constData());
+ QImage image(p, rbResult.pixelSize.width(), rbResult.pixelSize.height(), QImage::Format_RGBA8888);
+ QString fn = QString::asprintf("frame%d.png", frame);
+ fn = QFileInfo(fn).absoluteFilePath();
+ qDebug("Saving into %s", qPrintable(fn));
+ if (r->isYUpInFramebuffer())
+ image.mirrored().save(fn);
+ else
+ image.save(fn);
+ } else {
+ qWarning("Readback failed!");
+ }
+#ifdef TEST_FINISH
+ r->endOffscreenFrame();
+#endif
+ }
+
+ delete ps;
+ delete srb;
+ delete ubuf;
+ delete vbuf;
+
+ delete rt;
+ delete rp;
+ delete tex;
+
+ delete r;
+
+ qDebug("\nRendered and read back %d frames using %s", frame, qPrintable(graphicsApiName()));
+
+ return 0;
+}
diff --git a/tests/manual/rhi/offscreen/offscreen.pro b/tests/manual/rhi/offscreen/offscreen.pro
new file mode 100644
index 0000000000..ae040a4b6c
--- /dev/null
+++ b/tests/manual/rhi/offscreen/offscreen.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+CONFIG += console
+
+QT += gui-private
+
+SOURCES = \
+ offscreen.cpp
+
+RESOURCES = offscreen.qrc
diff --git a/tests/manual/rhi/offscreen/offscreen.qrc b/tests/manual/rhi/offscreen/offscreen.qrc
new file mode 100644
index 0000000000..8cec4fa9ec
--- /dev/null
+++ b/tests/manual/rhi/offscreen/offscreen.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/qrhiprof/qrhiprof.cpp b/tests/manual/rhi/qrhiprof/qrhiprof.cpp
new file mode 100644
index 0000000000..7e3027a951
--- /dev/null
+++ b/tests/manual/rhi/qrhiprof/qrhiprof.cpp
@@ -0,0 +1,671 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+// Simple QRhiProfiler receiver app. Start it and then in a QRhi-based
+// application connect with a QTcpSocket to 127.0.0.1:30667 and set that as the
+// QRhiProfiler's device.
+
+#include <QTcpServer>
+#include <QTcpSocket>
+#include <QApplication>
+#include <QWidget>
+#include <QVBoxLayout>
+#include <QGroupBox>
+#include <QTextEdit>
+#include <QLabel>
+#include <QTime>
+#include <QtGui/private/qrhiprofiler_p.h>
+
+const int MIN_KNOWN_OP = 1;
+const int MAX_KNOWN_OP = 18;
+
+class Parser : public QObject
+{
+ Q_OBJECT
+
+public:
+ void feed(const QByteArray &line);
+
+ struct Event {
+ QRhiProfiler::StreamOp op;
+ qint64 timestamp;
+ quint64 resource;
+ QByteArray resourceName;
+
+ struct Param {
+ enum ValueType {
+ Int64,
+ Float
+ };
+ QByteArray key;
+ ValueType valueType;
+ union {
+ qint64 intValue;
+ float floatValue;
+ };
+ };
+
+ QVector<Param> params;
+
+ const Param *param(const char *key) const {
+ auto it = std::find_if(params.cbegin(), params.cend(), [key](const Param &p) {
+ return !strcmp(p.key.constData(), key);
+ });
+ return it == params.cend() ? nullptr : &*it;
+ }
+ };
+
+signals:
+ void eventReceived(const Event &e);
+};
+
+void Parser::feed(const QByteArray &line)
+{
+ const QList<QByteArray> elems = line.split(',');
+ if (elems.count() < 4) {
+ qWarning("Malformed line '%s'", line.constData());
+ return;
+ }
+ bool ok = false;
+ const int op = elems[0].toInt(&ok);
+ if (!ok) {
+ qWarning("Invalid op %s", elems[0].constData());
+ return;
+ }
+ if (op < MIN_KNOWN_OP || op > MAX_KNOWN_OP) {
+ qWarning("Unknown op %d", op);
+ return;
+ }
+
+ Event e;
+ e.op = QRhiProfiler::StreamOp(op);
+ e.timestamp = elems[1].toLongLong();
+ e.resource = elems[2].toULongLong();
+ e.resourceName = elems[3];
+
+ const int elemCount = elems.count();
+ for (int i = 4; i < elemCount; i += 2) {
+ if (i + 1 < elemCount && !elems[i].isEmpty() && !elems[i + 1].isEmpty()) {
+ QByteArray key = elems[i];
+ if (key.startsWith('F')) {
+ key = key.mid(1);
+ bool ok = false;
+ const float value = elems[i + 1].toFloat(&ok);
+ if (!ok) {
+ qWarning("Failed to parse float %s in line '%s'", elems[i + 1].constData(), line.constData());
+ continue;
+ }
+ Event::Param param;
+ param.key = key;
+ param.valueType = Event::Param::Float;
+ param.floatValue = value;
+ e.params.append(param);
+ } else {
+ const qint64 value = elems[i + 1].toLongLong();
+ Event::Param param;
+ param.key = key;
+ param.valueType = Event::Param::Int64;
+ param.intValue = value;
+ e.params.append(param);
+ }
+ }
+ }
+
+ emit eventReceived(e);
+}
+
+class Tracker : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void handleEvent(const Parser::Event &e);
+
+signals:
+ void buffersTouched();
+ void texturesTouched();
+ void swapchainsTouched();
+ void frameTimeTouched();
+ void gpuFrameTimeTouched();
+ void gpuMemAllocStatsTouched();
+
+public:
+ Tracker() {
+ reset();
+ }
+
+ static const int MAX_STAGING_SLOTS = 3;
+
+ struct Buffer {
+ Buffer()
+ {
+ memset(stagingExtraSize, 0, sizeof(stagingExtraSize));
+ }
+ quint64 lastTimestamp;
+ QByteArray resourceName;
+ qint64 effectiveSize = 0;
+ int backingGpuBufCount = 1;
+ qint64 stagingExtraSize[MAX_STAGING_SLOTS];
+ };
+ QHash<qint64, Buffer> m_buffers;
+ qint64 m_totalBufferApproxByteSize;
+ qint64 m_peakBufferApproxByteSize;
+ qint64 m_totalStagingBufferApproxByteSize;
+ qint64 m_peakStagingBufferApproxByteSize;
+
+ struct Texture {
+ Texture()
+ {
+ memset(stagingExtraSize, 0, sizeof(stagingExtraSize));
+ }
+ quint64 lastTimestamp;
+ QByteArray resourceName;
+ qint64 approxByteSize = 0;
+ bool ownsNativeResource = true;
+ qint64 stagingExtraSize[MAX_STAGING_SLOTS];
+ };
+ QHash<qint64, Texture> m_textures;
+ qint64 m_totalTextureApproxByteSize;
+ qint64 m_peakTextureApproxByteSize;
+ qint64 m_totalTextureStagingBufferApproxByteSize;
+ qint64 m_peakTextureStagingBufferApproxByteSize;
+
+ struct SwapChain {
+ quint64 lastTimestamp;
+ QByteArray resourceName;
+ qint64 approxByteSize = 0;
+ };
+ QHash<qint64, SwapChain> m_swapchains;
+ qint64 m_totalSwapChainApproxByteSize;
+ qint64 m_peakSwapChainApproxByteSize;
+
+ struct FrameTime {
+ qint64 framesSinceResize = 0;
+ int minDelta = 0;
+ int maxDelta = 0;
+ float avgDelta = 0;
+ };
+ FrameTime m_lastFrameTime;
+
+ struct GpuFrameTime {
+ float minTime = 0;
+ float maxTime = 0;
+ float avgTime = 0;
+ };
+ GpuFrameTime m_lastGpuFrameTime;
+
+ struct GpuMemAllocStats {
+ qint64 realAllocCount;
+ qint64 subAllocCount;
+ qint64 totalSize;
+ qint64 unusedSize;
+ };
+ GpuMemAllocStats m_lastGpuMemAllocStats;
+
+ void reset() {
+ m_buffers.clear();
+ m_textures.clear();
+ m_totalBufferApproxByteSize = 0;
+ m_peakBufferApproxByteSize = 0;
+ m_totalStagingBufferApproxByteSize = 0;
+ m_peakStagingBufferApproxByteSize = 0;
+ m_totalTextureApproxByteSize = 0;
+ m_peakTextureApproxByteSize = 0;
+ m_totalTextureStagingBufferApproxByteSize = 0;
+ m_peakTextureStagingBufferApproxByteSize = 0;
+ m_totalSwapChainApproxByteSize = 0;
+ m_peakSwapChainApproxByteSize = 0;
+ m_lastFrameTime = FrameTime();
+ m_lastGpuFrameTime = GpuFrameTime();
+ m_lastGpuMemAllocStats = GpuMemAllocStats();
+ emit buffersTouched();
+ emit texturesTouched();
+ emit swapchainsTouched();
+ emit frameTimeTouched();
+ emit gpuFrameTimeTouched();
+ emit gpuMemAllocStatsTouched();
+ }
+};
+
+Q_DECLARE_TYPEINFO(Tracker::Buffer, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracker::Texture, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracker::FrameTime, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracker::GpuFrameTime, Q_MOVABLE_TYPE);
+
+void Tracker::handleEvent(const Parser::Event &e)
+{
+ switch (e.op) {
+ case QRhiProfiler::NewBuffer:
+ {
+ Buffer b;
+ b.lastTimestamp = e.timestamp;
+ b.resourceName = e.resourceName;
+ // type,0,usage,1,logical_size,84,effective_size,84,backing_gpu_buf_count,1,backing_cpu_buf_count,0
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("effective_size"))
+ b.effectiveSize = p.intValue;
+ else if (p.key == QByteArrayLiteral("backing_gpu_buf_count"))
+ b.backingGpuBufCount = p.intValue;
+ }
+ m_totalBufferApproxByteSize += b.effectiveSize * b.backingGpuBufCount;
+ m_peakBufferApproxByteSize = qMax(m_peakBufferApproxByteSize, m_totalBufferApproxByteSize);
+ m_buffers.insert(e.resource, b);
+ emit buffersTouched();
+ }
+ break;
+ case QRhiProfiler::ReleaseBuffer:
+ {
+ auto it = m_buffers.find(e.resource);
+ if (it != m_buffers.end()) {
+ m_totalBufferApproxByteSize -= it->effectiveSize * it->backingGpuBufCount;
+ m_buffers.erase(it);
+ emit buffersTouched();
+ }
+ }
+ break;
+
+ case QRhiProfiler::NewBufferStagingArea:
+ {
+ qint64 slot = -1;
+ qint64 size = 0;
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("slot"))
+ slot = p.intValue;
+ else if (p.key == QByteArrayLiteral("size"))
+ size = p.intValue;
+ }
+ if (slot >= 0 && slot < MAX_STAGING_SLOTS) {
+ auto it = m_buffers.find(e.resource);
+ if (it != m_buffers.end()) {
+ it->stagingExtraSize[slot] = size;
+ m_totalStagingBufferApproxByteSize += size;
+ m_peakStagingBufferApproxByteSize = qMax(m_peakStagingBufferApproxByteSize, m_totalStagingBufferApproxByteSize);
+ emit buffersTouched();
+ }
+ }
+ }
+ break;
+ case QRhiProfiler::ReleaseBufferStagingArea:
+ {
+ qint64 slot = -1;
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("slot"))
+ slot = p.intValue;
+ }
+ if (slot >= 0 && slot < MAX_STAGING_SLOTS) {
+ auto it = m_buffers.find(e.resource);
+ if (it != m_buffers.end()) {
+ m_totalStagingBufferApproxByteSize -= it->stagingExtraSize[slot];
+ it->stagingExtraSize[slot] = 0;
+ emit buffersTouched();
+ }
+ }
+ }
+ break;
+
+ case QRhiProfiler::NewTexture:
+ {
+ Texture t;
+ t.lastTimestamp = e.timestamp;
+ t.resourceName = e.resourceName;
+ // width,256,height,256,format,1,owns_native_resource,1,mip_count,9,layer_count,1,effective_sample_count,1,approx_byte_size,349524
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("approx_byte_size"))
+ t.approxByteSize = p.intValue;
+ else if (p.key == QByteArrayLiteral("owns_native_resource"))
+ t.ownsNativeResource = p.intValue;
+ }
+ if (t.ownsNativeResource) {
+ m_totalTextureApproxByteSize += t.approxByteSize;
+ m_peakTextureApproxByteSize = qMax(m_peakTextureApproxByteSize, m_totalTextureApproxByteSize);
+ }
+ m_textures.insert(e.resource, t);
+ emit texturesTouched();
+ }
+ break;
+ case QRhiProfiler::ReleaseTexture:
+ {
+ auto it = m_textures.find(e.resource);
+ if (it != m_textures.end()) {
+ if (it->ownsNativeResource)
+ m_totalTextureApproxByteSize -= it->approxByteSize;
+ m_textures.erase(it);
+ emit texturesTouched();
+ }
+ }
+ break;
+
+ case QRhiProfiler::NewTextureStagingArea:
+ {
+ qint64 slot = -1;
+ qint64 size = 0;
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("slot"))
+ slot = p.intValue;
+ else if (p.key == QByteArrayLiteral("size"))
+ size = p.intValue;
+ }
+ if (slot >= 0 && slot < MAX_STAGING_SLOTS) {
+ auto it = m_textures.find(e.resource);
+ if (it != m_textures.end()) {
+ it->stagingExtraSize[slot] = size;
+ m_totalTextureStagingBufferApproxByteSize += size;
+ m_peakTextureStagingBufferApproxByteSize = qMax(m_peakTextureStagingBufferApproxByteSize, m_totalTextureStagingBufferApproxByteSize);
+ emit texturesTouched();
+ }
+ }
+ }
+ break;
+ case QRhiProfiler::ReleaseTextureStagingArea:
+ {
+ qint64 slot = -1;
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("slot"))
+ slot = p.intValue;
+ }
+ if (slot >= 0 && slot < MAX_STAGING_SLOTS) {
+ auto it = m_textures.find(e.resource);
+ if (it != m_textures.end()) {
+ m_totalTextureStagingBufferApproxByteSize -= it->stagingExtraSize[slot];
+ it->stagingExtraSize[slot] = 0;
+ emit texturesTouched();
+ }
+ }
+ }
+ break;
+
+ case QRhiProfiler::ResizeSwapChain:
+ {
+ auto it = m_swapchains.find(e.resource);
+ if (it != m_swapchains.end())
+ m_totalSwapChainApproxByteSize -= it->approxByteSize;
+
+ SwapChain s;
+ s.lastTimestamp = e.timestamp;
+ s.resourceName = e.resourceName;
+ // width,1280,height,720,buffer_count,2,msaa_buffer_count,0,effective_sample_count,1,approx_total_byte_size,7372800
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("approx_total_byte_size"))
+ s.approxByteSize = p.intValue;
+ }
+ m_totalSwapChainApproxByteSize += s.approxByteSize;
+ m_peakSwapChainApproxByteSize = qMax(m_peakSwapChainApproxByteSize, m_totalSwapChainApproxByteSize);
+ m_swapchains.insert(e.resource, s);
+ emit swapchainsTouched();
+ }
+ break;
+ case QRhiProfiler::ReleaseSwapChain:
+ {
+ auto it = m_swapchains.find(e.resource);
+ if (it != m_swapchains.end()) {
+ m_totalSwapChainApproxByteSize -= it->approxByteSize;
+ m_swapchains.erase(it);
+ emit swapchainsTouched();
+ }
+ }
+ break;
+
+ case QRhiProfiler::GpuFrameTime:
+ {
+ // Fmin_ms_gpu_frame_time,0.15488,Fmax_ms_gpu_frame_time,0.494592,Favg_ms_gpu_frame_time,0.33462
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("min_ms_gpu_frame_time"))
+ m_lastGpuFrameTime.minTime = p.floatValue;
+ else if (p.key == QByteArrayLiteral("max_ms_gpu_frame_time"))
+ m_lastGpuFrameTime.maxTime = p.floatValue;
+ else if (p.key == QByteArrayLiteral("avg_ms_gpu_frame_time"))
+ m_lastGpuFrameTime.avgTime = p.floatValue;
+ }
+ emit gpuFrameTimeTouched();
+ }
+ break;
+ case QRhiProfiler::FrameToFrameTime:
+ {
+ // frames_since_resize,121,min_ms_frame_delta,9,max_ms_frame_delta,33,Favg_ms_frame_delta,16.1167
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("frames_since_resize"))
+ m_lastFrameTime.framesSinceResize = p.intValue;
+ else if (p.key == QByteArrayLiteral("min_ms_frame_delta"))
+ m_lastFrameTime.minDelta = p.intValue;
+ else if (p.key == QByteArrayLiteral("max_ms_frame_delta"))
+ m_lastFrameTime.maxDelta = p.intValue;
+ else if (p.key == QByteArrayLiteral("avg_ms_frame_delta"))
+ m_lastFrameTime.avgDelta = p.floatValue;
+ }
+ emit frameTimeTouched();
+ }
+ break;
+
+ case QRhiProfiler::GpuMemAllocStats:
+ {
+ // real_alloc_count,2,sub_alloc_count,154,total_size,10752,unused_size,50320896
+ for (const Parser::Event::Param &p : e.params) {
+ if (p.key == QByteArrayLiteral("real_alloc_count"))
+ m_lastGpuMemAllocStats.realAllocCount = p.intValue;
+ else if (p.key == QByteArrayLiteral("sub_alloc_count"))
+ m_lastGpuMemAllocStats.subAllocCount = p.intValue;
+ else if (p.key == QByteArrayLiteral("total_size"))
+ m_lastGpuMemAllocStats.totalSize = p.intValue;
+ else if (p.key == QByteArrayLiteral("unused_size"))
+ m_lastGpuMemAllocStats.unusedSize = p.intValue;
+ }
+ emit gpuMemAllocStatsTouched();
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+class Server : public QTcpServer
+{
+ Q_OBJECT
+
+protected:
+ void incomingConnection(qintptr socketDescriptor) override;
+
+signals:
+ void clientConnected();
+ void clientDisconnected();
+ void receiveStarted();
+ void lineReceived(const QByteArray &line);
+
+private:
+ bool m_valid = false;
+ QTcpSocket m_socket;
+ QByteArray m_buf;
+};
+
+void Server::incomingConnection(qintptr socketDescriptor)
+{
+ if (m_valid)
+ return;
+
+ m_socket.setSocketDescriptor(socketDescriptor);
+ m_valid = true;
+ emit clientConnected();
+ connect(&m_socket, &QAbstractSocket::readyRead, this, [this] {
+ bool receiveStartedSent = false;
+ m_buf += m_socket.readAll();
+ while (m_buf.contains('\n')) {
+ const int lfpos = m_buf.indexOf('\n');
+ const QByteArray line = m_buf.left(lfpos).trimmed();
+ m_buf = m_buf.mid(lfpos + 1);
+ if (!receiveStartedSent) {
+ receiveStartedSent = true;
+ emit receiveStarted();
+ }
+ emit lineReceived(line);
+ }
+ });
+ connect(&m_socket, &QAbstractSocket::disconnected, this, [this] {
+ if (m_valid) {
+ m_valid = false;
+ emit clientDisconnected();
+ }
+ });
+}
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ Tracker tracker;
+ Parser parser;
+ QObject::connect(&parser, &Parser::eventReceived, &tracker, &Tracker::handleEvent);
+
+ Server server;
+ if (!server.listen(QHostAddress::Any, 30667))
+ qFatal("Failed to start server: %s", qPrintable(server.errorString()));
+
+ QVBoxLayout *layout = new QVBoxLayout;
+
+ QLabel *infoLabel = new QLabel(QLatin1String("<i>Launch a Qt Quick application with QSG_RHI_PROFILE=1 and QSG_RHI_PROFILE_HOST set to the IP address.<br>"
+ "(resource memory usage reporting works best with the Vulkan backend)</i>"));
+ layout->addWidget(infoLabel);
+
+ QGroupBox *groupBox = new QGroupBox(QLatin1String("RHI statistics"));
+ QVBoxLayout *groupLayout = new QVBoxLayout;
+
+ QLabel *buffersLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::buffersTouched, buffersLabel, [buffersLabel, &tracker] {
+ const QString msg = QString::asprintf("%d buffers with ca. %lld bytes of current memory (sub)allocations (peak %lld) + %lld bytes of known staging buffers (peak %lld)",
+ tracker.m_buffers.count(),
+ tracker.m_totalBufferApproxByteSize, tracker.m_peakBufferApproxByteSize,
+ tracker.m_totalStagingBufferApproxByteSize, tracker.m_peakStagingBufferApproxByteSize);
+ buffersLabel->setText(msg);
+ });
+ groupLayout->addWidget(buffersLabel);
+
+ QLabel *texturesLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::texturesTouched, texturesLabel, [texturesLabel, &tracker] {
+ const QString msg = QString::asprintf("%d textures with ca. %lld bytes of current memory (sub)allocations (peak %lld) + %lld bytes of known staging buffers (peak %lld)",
+ tracker.m_textures.count(),
+ tracker.m_totalTextureApproxByteSize, tracker.m_peakTextureApproxByteSize,
+ tracker.m_totalTextureStagingBufferApproxByteSize, tracker.m_peakTextureStagingBufferApproxByteSize);
+ texturesLabel->setText(msg);
+ });
+ groupLayout->addWidget(texturesLabel);
+
+ QLabel *swapchainsLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::swapchainsTouched, swapchainsLabel, [swapchainsLabel, &tracker] {
+ const QString msg = QString::asprintf("Estimated total swapchain color buffer size is %lld bytes (peak %lld)",
+ tracker.m_totalSwapChainApproxByteSize, tracker.m_peakSwapChainApproxByteSize);
+ swapchainsLabel->setText(msg);
+ });
+ groupLayout->addWidget(swapchainsLabel);
+
+ QLabel *frameTimeLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::frameTimeTouched, frameTimeLabel, [frameTimeLabel, &tracker] {
+ const QString msg = QString::asprintf("Frames since resize %lld Frame delta min %d ms max %d ms avg %f ms",
+ tracker.m_lastFrameTime.framesSinceResize,
+ tracker.m_lastFrameTime.minDelta,
+ tracker.m_lastFrameTime.maxDelta,
+ tracker.m_lastFrameTime.avgDelta);
+ frameTimeLabel->setText(msg);
+ });
+ groupLayout->addWidget(frameTimeLabel);
+
+ QLabel *gpuFrameTimeLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::gpuFrameTimeTouched, gpuFrameTimeLabel, [gpuFrameTimeLabel, &tracker] {
+ const QString msg = QString::asprintf("GPU frame time min %f ms max %f ms avg %f ms",
+ tracker.m_lastGpuFrameTime.minTime,
+ tracker.m_lastGpuFrameTime.maxTime,
+ tracker.m_lastGpuFrameTime.avgTime);
+ gpuFrameTimeLabel->setText(msg);
+ });
+ groupLayout->addWidget(gpuFrameTimeLabel);
+
+ QLabel *gpuMemAllocStatsLabel = new QLabel;
+ QObject::connect(&tracker, &Tracker::gpuMemAllocStatsTouched, gpuMemAllocStatsLabel, [gpuMemAllocStatsLabel, &tracker] {
+ const QString msg = QString::asprintf("GPU memory allocator status: %lld real allocations %lld sub-allocations %lld total bytes %lld unused bytes",
+ tracker.m_lastGpuMemAllocStats.realAllocCount,
+ tracker.m_lastGpuMemAllocStats.subAllocCount,
+ tracker.m_lastGpuMemAllocStats.totalSize,
+ tracker.m_lastGpuMemAllocStats.unusedSize);
+ gpuMemAllocStatsLabel->setText(msg);
+ });
+ groupLayout->addWidget(gpuMemAllocStatsLabel);
+
+ groupBox->setLayout(groupLayout);
+ layout->addWidget(groupBox);
+
+ QTextEdit *rawLog = new QTextEdit;
+ rawLog->setReadOnly(true);
+ layout->addWidget(rawLog);
+
+ QObject::connect(&server, &Server::clientConnected, rawLog, [rawLog] {
+ rawLog->append(QLatin1String("\nCONNECTED\n"));
+ });
+ QObject::connect(&server, &Server::clientDisconnected, rawLog, [rawLog, &tracker] {
+ rawLog->append(QLatin1String("\nDISCONNECTED\n"));
+ tracker.reset();
+ });
+ QObject::connect(&server, &Server::receiveStarted, rawLog, [rawLog] {
+ rawLog->setFontItalic(true);
+ rawLog->append(QLatin1String("[") + QTime::currentTime().toString() + QLatin1String("]"));
+ rawLog->setFontItalic(false);
+ });
+
+ QObject::connect(&server, &Server::lineReceived, rawLog, [rawLog, &parser](const QByteArray &line) {
+ rawLog->append(QString::fromUtf8(line));
+ parser.feed(line);
+ });
+
+ QWidget w;
+ w.resize(800, 600);
+ w.setLayout(layout);
+ w.show();
+
+ return app.exec();
+}
+
+#include "qrhiprof.moc"
diff --git a/tests/manual/rhi/qrhiprof/qrhiprof.pro b/tests/manual/rhi/qrhiprof/qrhiprof.pro
new file mode 100644
index 0000000000..2939dd7ce2
--- /dev/null
+++ b/tests/manual/rhi/qrhiprof/qrhiprof.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+
+QT += network widgets gui-private
+
+SOURCES = \
+ qrhiprof.cpp
diff --git a/tests/manual/rhi/rhi.pro b/tests/manual/rhi/rhi.pro
new file mode 100644
index 0000000000..1a65f84a89
--- /dev/null
+++ b/tests/manual/rhi/rhi.pro
@@ -0,0 +1,22 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ hellominimalcrossgfxtriangle \
+ compressedtexture_bc1 \
+ compressedtexture_bc1_subupload \
+ texuploads \
+ msaatexture \
+ msaarenderbuffer \
+ cubemap \
+ multiwindow \
+ multiwindow_threaded \
+ triquadcube \
+ offscreen \
+ floattexture \
+ mrt \
+ shadowmap
+
+qtConfig(widgets) {
+ SUBDIRS += \
+ qrhiprof
+}
diff --git a/tests/manual/rhi/shadowmap/buildshaders.bat b/tests/manual/rhi/shadowmap/buildshaders.bat
new file mode 100644
index 0000000000..7b84cc0952
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/buildshaders.bat
@@ -0,0 +1,4 @@
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 -c shadowmap.vert -o shadowmap.vert.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 -c shadowmap.frag -o shadowmap.frag.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 -c main.vert -o main.vert.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 -c main.frag -o main.frag.qsb
diff --git a/tests/manual/rhi/shadowmap/buildshaders.sh b/tests/manual/rhi/shadowmap/buildshaders.sh
new file mode 100755
index 0000000000..c4d17841e6
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/buildshaders.sh
@@ -0,0 +1,4 @@
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 shadowmap.vert -o shadowmap.vert.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 shadowmap.frag -o shadowmap.frag.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 main.vert -o main.vert.qsb
+qsb --glsl "120,300 es" --hlsl 50 --msl 12 main.frag -o main.frag.qsb
diff --git a/tests/manual/rhi/shadowmap/main.frag b/tests/manual/rhi/shadowmap/main.frag
new file mode 100644
index 0000000000..8fefe2bb42
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/main.frag
@@ -0,0 +1,30 @@
+#version 440
+
+layout(location = 0) in vec4 vLCVertPos;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2DShadow shadowMap;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ mat4 lightMvp;
+ mat4 shadowBias;
+ int useShadow;
+} ubuf;
+
+void main()
+{
+ vec4 adjustedLcVertPos = vLCVertPos;
+ adjustedLcVertPos.z -= 0.0001; // bias to avoid acne
+
+ // no textureProj, that seems to end up not doing the perspective divide for z (?)
+ vec3 v = adjustedLcVertPos.xyz / adjustedLcVertPos.w;
+ float sc = texture(shadowMap, v); // sampler is comparison enabled so compares to z
+
+ float shadowFactor = 0.2;
+ if (sc > 0 || ubuf.useShadow == 0)
+ shadowFactor = 1.0;
+
+ fragColor = vec4(0.5, 0.3 + ubuf.useShadow * 0.2, 0.7, 1.0) * shadowFactor;
+}
diff --git a/tests/manual/rhi/shadowmap/main.frag.qsb b/tests/manual/rhi/shadowmap/main.frag.qsb
new file mode 100644
index 0000000000..3001908b85
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/main.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/shadowmap/main.vert b/tests/manual/rhi/shadowmap/main.vert
new file mode 100644
index 0000000000..9d6cade634
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/main.vert
@@ -0,0 +1,20 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ mat4 lightMvp;
+ mat4 shadowBias;
+ int useShadow;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+layout(location = 0) out vec4 vLCVertPos;
+
+void main()
+{
+ vLCVertPos = ubuf.shadowBias * ubuf.lightMvp * position;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/shadowmap/main.vert.qsb b/tests/manual/rhi/shadowmap/main.vert.qsb
new file mode 100644
index 0000000000..8b81a93c00
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/main.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/shadowmap/shadowmap.cpp b/tests/manual/rhi/shadowmap/shadowmap.cpp
new file mode 100644
index 0000000000..c31674a520
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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/examplefw.h"
+#include "../shared/cube.h"
+
+// Depth texture / shadow sampler / shadow map example.
+// Not available on GLES 2.0.
+
+static float quadVertexData[] =
+{ // Y up, CCW, x-y-z
+ -0.5f, 0.5f, 0.0f,
+ -0.5f, -0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f,
+ 0.5f, 0.5f, 0.0f,
+};
+
+static quint16 quadIndexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiSampler *shadowSampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 winProj;
+ float cubeRot = 0;
+
+ QRhiTextureRenderTarget *rt = nullptr;
+ QRhiRenderPassDescriptor *rtRp = nullptr;
+ QRhiTexture *shadowMap = nullptr;
+ QRhiShaderResourceBindings *shadowSrb = nullptr;
+ QRhiGraphicsPipeline *shadowPs = nullptr;
+} d;
+
+const int UBLOCK_SIZE = 64 * 3 + 4;
+const int SHADOW_UBLOCK_SIZE = 64 * 1;
+const int UBUF_SLOTS = 4; // 2 objects * 2 passes with different cameras
+
+void Window::customInit()
+{
+ if (!m_r->isTextureFormatSupported(QRhiTexture::D32F))
+ qFatal("Depth texture is not supported");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(quadVertexData) + sizeof(cube));
+ d.vbuf->build();
+ d.releasePool << d.vbuf;
+
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(quadIndexData));
+ d.ibuf->build();
+ d.releasePool << d.ibuf;
+
+ const int oneRoundedUniformBlockSize = m_r->ubufAligned(UBLOCK_SIZE);
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, UBUF_SLOTS * oneRoundedUniformBlockSize);
+ d.ubuf->build();
+ d.releasePool << d.ubuf;
+
+ d.shadowMap = m_r->newTexture(QRhiTexture::D32F, QSize(1024, 1024), 1, QRhiTexture::RenderTarget);
+ d.releasePool << d.shadowMap;
+ d.shadowMap->build();
+
+ d.shadowSampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.shadowSampler;
+ d.shadowSampler->setTextureCompareOp(QRhiSampler::Less);
+ d.shadowSampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ const QRhiShaderResourceBinding::StageFlags stages = QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage;
+ d.srb->setBindings({ QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(0, stages, d.ubuf, UBLOCK_SIZE),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.shadowMap, d.shadowSampler) });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+ d.ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/main.vert.qsb")) },
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/main.frag.qsb")) }
+ });
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ // fits both the quad and cube vertex data
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->build();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(quadVertexData), quadVertexData);
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, sizeof(quadVertexData), sizeof(cube), cube);
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, quadIndexData);
+
+ QRhiTextureRenderTargetDescription rtDesc;
+ rtDesc.setDepthTexture(d.shadowMap);
+ d.rt = m_r->newTextureRenderTarget(rtDesc);
+ d.releasePool << d.rt;
+ d.rtRp = d.rt->newCompatibleRenderPassDescriptor();
+ d.releasePool << d.rtRp;
+ d.rt->setRenderPassDescriptor(d.rtRp);
+ d.rt->build();
+
+ d.shadowSrb = m_r->newShaderResourceBindings();
+ d.releasePool << d.shadowSrb;
+ d.shadowSrb->setBindings({ QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(0, stages, d.ubuf, SHADOW_UBLOCK_SIZE) });
+ d.shadowSrb->build();
+
+ d.shadowPs = m_r->newGraphicsPipeline();
+ d.releasePool << d.shadowPs;
+ d.shadowPs->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/shadowmap.vert.qsb")) },
+ { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/shadowmap.frag.qsb")) }
+ });
+ d.shadowPs->setDepthTest(true);
+ d.shadowPs->setDepthWrite(true);
+ inputLayout.setBindings({
+ { 3 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 }
+ });
+ d.shadowPs->setVertexInputLayout(inputLayout);
+ d.shadowPs->setShaderResourceBindings(d.shadowSrb);
+ d.shadowPs->setRenderPassDescriptor(d.rtRp);
+ d.shadowPs->build();
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+static void enqueueScene(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb, int oneRoundedUniformBlockSize, int firstUbufSlot)
+{
+ QRhiCommandBuffer::DynamicOffset ubufOffset(0, quint32(firstUbufSlot * oneRoundedUniformBlockSize));
+ // draw the ground (the quad)
+ cb->setShaderResources(srb, 1, &ubufOffset);
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+
+ // Draw the object (the cube). Both vertex and uniform data are in the same
+ // buffer, right after the quad's.
+ ubufOffset.second += oneRoundedUniformBlockSize;
+ cb->setShaderResources(srb, 1, &ubufOffset);
+ vbufBinding.second = sizeof(quadVertexData);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(36);
+}
+
+void Window::customRender()
+{
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ const int oneRoundedUniformBlockSize = m_r->ubufAligned(UBLOCK_SIZE);
+
+ QMatrix4x4 shadowBias;
+ // fill it in column-major order to keep our sanity (ctor would take row-major)
+ float *sbp = shadowBias.data();
+ if (m_r->isClipDepthZeroToOne()) {
+ // convert x, y [-1, 1] -> [0, 1]
+ *sbp++ = 0.5f; *sbp++ = 0.0f; *sbp++ = 0.0f; *sbp++ = 0.0f;
+ *sbp++ = 0.0f; *sbp++ = m_r->isYUpInNDC() ? -0.5f : 0.5f; *sbp++ = 0.0f; *sbp++ = 0.0f;
+ *sbp++ = 0.0f; *sbp++ = 0.0f; *sbp++ = 1.0f; *sbp++ = 0.0f;
+ *sbp++ = 0.5f; *sbp++ = 0.5f; *sbp++ = 0.0f; *sbp++ = 1.0f;
+ } else {
+ // convert x, y, z [-1, 1] -> [0, 1]
+ *sbp++ = 0.5f; *sbp++ = 0.0f; *sbp++ = 0.0f; *sbp++ = 0.0f;
+ *sbp++ = 0.0f; *sbp++ = 0.5f; *sbp++ = 0.0f; *sbp++ = 0.0f;
+ *sbp++ = 0.0f; *sbp++ = 0.0f; *sbp++ = 0.5f; *sbp++ = 0.0f;
+ *sbp++ = 0.5f; *sbp++ = 0.5f; *sbp++ = 0.5f; *sbp++ = 1.0f;
+ }
+
+ const QVector3D lightPos(5, 10, 10);
+ QMatrix4x4 lightViewProj = m_r->clipSpaceCorrMatrix();
+ lightViewProj.perspective(45.0f, 1, 0.1f, 100.0f);
+ lightViewProj.lookAt(lightPos, QVector3D(0, 0, 0), QVector3D(0, 1, 0));
+
+ // uniform data for the ground
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+
+ QMatrix4x4 m;
+ m.scale(4.0f);
+ m.rotate(-60, 1, 0, 0);
+
+ // for the main pass
+ const QMatrix4x4 mvp = m_proj * m; // m_proj is in fact projection * view
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+ const QMatrix4x4 shadowMvp = lightViewProj * m;
+ u->updateDynamicBuffer(d.ubuf, 64, 64, shadowMvp.constData());
+ u->updateDynamicBuffer(d.ubuf, 128, 64, shadowBias.constData());
+ qint32 useShadows = 1;
+ u->updateDynamicBuffer(d.ubuf, 192, 4, &useShadows);
+
+ // for the shadow pass
+ u->updateDynamicBuffer(d.ubuf, 2 * oneRoundedUniformBlockSize, 64, shadowMvp.constData());
+ }
+
+ // uniform data for the rotating cube
+ QMatrix4x4 m;
+ m.translate(0, 0.5f, 2);
+ m.scale(0.2f);
+ m.rotate(d.cubeRot, 0, 1, 0);
+ m.rotate(45, 1, 0, 0);
+ d.cubeRot += 1;
+
+ // for the main pass
+ const QMatrix4x4 mvp = m_proj * m;
+ u->updateDynamicBuffer(d.ubuf, oneRoundedUniformBlockSize, 64, mvp.constData());
+ const QMatrix4x4 shadowMvp = lightViewProj * m;
+ u->updateDynamicBuffer(d.ubuf, oneRoundedUniformBlockSize + 64, 64, shadowMvp.constData());
+ u->updateDynamicBuffer(d.ubuf, oneRoundedUniformBlockSize + 128, 64, shadowBias.constData());
+ qint32 useShadows = 0;
+ u->updateDynamicBuffer(d.ubuf, oneRoundedUniformBlockSize + 192, 4, &useShadows);
+
+ // for the shadow pass
+ u->updateDynamicBuffer(d.ubuf, 3 * oneRoundedUniformBlockSize, 64, shadowMvp.constData());
+
+ cb->resourceUpdate(u);
+
+ // shadow pass
+ const QSize shadowMapSize = d.shadowMap->pixelSize();
+ cb->beginPass(d.rt, QColor(), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.shadowPs);
+ cb->setViewport({ 0, 0, float(shadowMapSize.width()), float(shadowMapSize.height()) });
+ enqueueScene(cb, d.shadowSrb, oneRoundedUniformBlockSize, 2);
+ cb->endPass();
+
+ // main pass
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 });
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ enqueueScene(cb, d.srb, oneRoundedUniformBlockSize, 0);
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/shadowmap/shadowmap.frag b/tests/manual/rhi/shadowmap/shadowmap.frag
new file mode 100644
index 0000000000..fa868f31a2
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.frag
@@ -0,0 +1,5 @@
+#version 440
+
+void main()
+{
+}
diff --git a/tests/manual/rhi/shadowmap/shadowmap.frag.qsb b/tests/manual/rhi/shadowmap/shadowmap.frag.qsb
new file mode 100644
index 0000000000..3cad114cf4
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/shadowmap/shadowmap.pro b/tests/manual/rhi/shadowmap/shadowmap.pro
new file mode 100644
index 0000000000..baf740927c
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ shadowmap.cpp
+
+RESOURCES = shadowmap.qrc
diff --git a/tests/manual/rhi/shadowmap/shadowmap.qrc b/tests/manual/rhi/shadowmap/shadowmap.qrc
new file mode 100644
index 0000000000..8256d5ca25
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+ <file>shadowmap.vert.qsb</file>
+ <file>shadowmap.frag.qsb</file>
+ <file>main.vert.qsb</file>
+ <file>main.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/shadowmap/shadowmap.vert b/tests/manual/rhi/shadowmap/shadowmap.vert
new file mode 100644
index 0000000000..72b5370aec
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.vert
@@ -0,0 +1,14 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/shadowmap/shadowmap.vert.qsb b/tests/manual/rhi/shadowmap/shadowmap.vert.qsb
new file mode 100644
index 0000000000..37a5e6ecbf
--- /dev/null
+++ b/tests/manual/rhi/shadowmap/shadowmap.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/OpenfootageNET_fieldairport-512.hdr b/tests/manual/rhi/shared/OpenfootageNET_fieldairport-512.hdr
new file mode 100644
index 0000000000..abdebdb74b
--- /dev/null
+++ b/tests/manual/rhi/shared/OpenfootageNET_fieldairport-512.hdr
Binary files differ
diff --git a/tests/manual/rhi/shared/buildshaders.bat b/tests/manual/rhi/shared/buildshaders.bat
new file mode 100644
index 0000000000..dde5f7b3d2
--- /dev/null
+++ b/tests/manual/rhi/shared/buildshaders.bat
@@ -0,0 +1,5 @@
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c color.vert -o color.vert.qsb
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c color.frag -o color.frag.qsb
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c texture.vert -o texture.vert.qsb
+qsb --glsl "100 es,120" --hlsl 50 --msl 12 -c texture.frag -o texture.frag.qsb
+qsb --hlsl 50 --msl 12 -c texture_ms4.frag -o texture_ms4.frag.qsb
diff --git a/tests/manual/rhi/shared/bwqt224_64.png b/tests/manual/rhi/shared/bwqt224_64.png
new file mode 100644
index 0000000000..8020cbb2a8
--- /dev/null
+++ b/tests/manual/rhi/shared/bwqt224_64.png
Binary files differ
diff --git a/tests/manual/rhi/shared/bwqt224_64_nomips.dds b/tests/manual/rhi/shared/bwqt224_64_nomips.dds
new file mode 100644
index 0000000000..393cfec9db
--- /dev/null
+++ b/tests/manual/rhi/shared/bwqt224_64_nomips.dds
Binary files differ
diff --git a/tests/manual/rhi/shared/color.frag b/tests/manual/rhi/shared/color.frag
new file mode 100644
index 0000000000..bb94a5a605
--- /dev/null
+++ b/tests/manual/rhi/shared/color.frag
@@ -0,0 +1,15 @@
+#version 440
+
+layout(location = 0) in vec3 v_color;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float opacity;
+} ubuf;
+
+void main()
+{
+ fragColor = vec4(v_color * ubuf.opacity, ubuf.opacity);
+}
diff --git a/tests/manual/rhi/shared/color.frag.qsb b/tests/manual/rhi/shared/color.frag.qsb
new file mode 100644
index 0000000000..3a965682eb
--- /dev/null
+++ b/tests/manual/rhi/shared/color.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/color.vert b/tests/manual/rhi/shared/color.vert
new file mode 100644
index 0000000000..43af543f44
--- /dev/null
+++ b/tests/manual/rhi/shared/color.vert
@@ -0,0 +1,19 @@
+#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;
+ float opacity;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/shared/color.vert.qsb b/tests/manual/rhi/shared/color.vert.qsb
new file mode 100644
index 0000000000..e34eae79a0
--- /dev/null
+++ b/tests/manual/rhi/shared/color.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/cube.h b/tests/manual/rhi/shared/cube.h
new file mode 100644
index 0000000000..252e80c56c
--- /dev/null
+++ b/tests/manual/rhi/shared/cube.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Chia-I Wu <olv@lunarg.com>
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Ian Elliott <ian@LunarG.com>
+ * Author: Ian Elliott <ianelliott@google.com>
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Gwan-gyeong Mun <elongbug@gmail.com>
+ * Author: Tony Barbour <tony@LunarG.com>
+ * Author: Bill Hollings <bill.hollings@brenwill.com>
+ */
+
+#ifndef CUBE_H
+#define CUBE_H
+
+// clang-format off
+static const float cube[] = {
+ -1.0f,-1.0f,-1.0f, // -X side
+ -1.0f,-1.0f, 1.0f,
+ -1.0f, 1.0f, 1.0f,
+ -1.0f, 1.0f, 1.0f,
+ -1.0f, 1.0f,-1.0f,
+ -1.0f,-1.0f,-1.0f,
+
+ -1.0f,-1.0f,-1.0f, // -Z side
+ 1.0f, 1.0f,-1.0f,
+ 1.0f,-1.0f,-1.0f,
+ -1.0f,-1.0f,-1.0f,
+ -1.0f, 1.0f,-1.0f,
+ 1.0f, 1.0f,-1.0f,
+
+ -1.0f,-1.0f,-1.0f, // -Y side
+ 1.0f,-1.0f,-1.0f,
+ 1.0f,-1.0f, 1.0f,
+ -1.0f,-1.0f,-1.0f,
+ 1.0f,-1.0f, 1.0f,
+ -1.0f,-1.0f, 1.0f,
+
+ -1.0f, 1.0f,-1.0f, // +Y side
+ -1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f,
+ -1.0f, 1.0f,-1.0f,
+ 1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f,-1.0f,
+
+ 1.0f, 1.0f,-1.0f, // +X side
+ 1.0f, 1.0f, 1.0f,
+ 1.0f,-1.0f, 1.0f,
+ 1.0f,-1.0f, 1.0f,
+ 1.0f,-1.0f,-1.0f,
+ 1.0f, 1.0f,-1.0f,
+
+ -1.0f, 1.0f, 1.0f, // +Z side
+ -1.0f,-1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f,
+ -1.0f,-1.0f, 1.0f,
+ 1.0f,-1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f,
+
+ 0.0f, 1.0f, // -X side
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+
+ 1.0f, 1.0f, // -Z side
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+
+ 1.0f, 0.0f, // -Y side
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+
+ 1.0f, 0.0f, // +Y side
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+
+ 1.0f, 0.0f, // +X side
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+
+ 0.0f, 0.0f, // +Z side
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+};
+// clang-format on
+
+#endif
diff --git a/tests/manual/rhi/shared/dds_bc1.h b/tests/manual/rhi/shared/dds_bc1.h
new file mode 100644
index 0000000000..3c98a94cfc
--- /dev/null
+++ b/tests/manual/rhi/shared/dds_bc1.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+
+static const quint32 DDS_MAGIC = 0x20534444; // 'DDS '
+static const quint32 DDS_FOURCC = 4;
+
+#define FOURCC(c0, c1, c2, c3) ((c0) | ((c1) << 8) | ((c2) << 16) | ((c3 << 24)))
+
+struct DDS_PIXELFORMAT {
+ quint32 size;
+ quint32 flags;
+ quint32 fourCC;
+ quint32 rgbBitCount;
+ quint32 rBitMask;
+ quint32 gBitMask;
+ quint32 bBitMask;
+ quint32 aBitMask;
+};
+
+struct DDS_HEADER {
+ quint32 size;
+ quint32 flags;
+ quint32 height;
+ quint32 width;
+ quint32 pitch;
+ quint32 depth;
+ quint32 mipMapCount;
+ quint32 reserved1[11];
+ DDS_PIXELFORMAT pixelFormat;
+ quint32 caps;
+ quint32 caps2;
+ quint32 caps3;
+ quint32 caps4;
+ quint32 reserved2;
+};
+
+static quint32 bc1size(const QSize &size)
+{
+ static const quint32 blockSize = 8; // 8 bytes for BC1
+ const quint32 bytesPerLine = qMax<quint32>(1, (size.width() + 3) / 4) * blockSize;
+ const quint32 ySize = qMax<quint32>(1, (size.height() + 3) / 4);
+ return bytesPerLine * ySize;
+}
+
+static QByteArrayList loadBC1(const QString &filename, QSize *size)
+{
+ QFile f(filename);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to open %s", qPrintable(filename));
+ return QByteArrayList();
+ }
+
+ quint32 magic = 0;
+ f.read(reinterpret_cast<char *>(&magic), sizeof(magic));
+ if (magic != DDS_MAGIC) {
+ qWarning("%s is not a DDS file", qPrintable(filename));
+ return QByteArrayList();
+ }
+ DDS_HEADER header;
+ f.read(reinterpret_cast<char *>(&header), sizeof(header));
+ if (header.size != sizeof(DDS_HEADER)) {
+ qWarning("Invalid DDS header size");
+ return QByteArrayList();
+ }
+ if (header.pixelFormat.size != sizeof(DDS_PIXELFORMAT)) {
+ qWarning("Invalid DDS pixel format size");
+ return QByteArrayList();
+ }
+ if (!(header.pixelFormat.flags & DDS_FOURCC)) {
+ qWarning("Invalid DDS pixel format");
+ return QByteArrayList();
+ }
+ if (header.pixelFormat.fourCC != FOURCC('D', 'X', 'T', '1')) {
+ qWarning("Only DXT1 (BC1) is supported");
+ return QByteArrayList();
+ }
+
+ QByteArrayList data;
+ QSize sz(header.width, header.height);
+ for (quint32 level = 0; level < header.mipMapCount; ++level) {
+ data.append(f.read(bc1size(sz)));
+ sz.setWidth(qMax(1, sz.width() / 2));
+ sz.setHeight(qMax(1, sz.height() / 2));
+ }
+
+ if (size)
+ *size = QSize(header.width, header.height);
+
+ return data;
+}
diff --git a/tests/manual/rhi/shared/examplefw.h b/tests/manual/rhi/shared/examplefw.h
new file mode 100644
index 0000000000..450aa172c2
--- /dev/null
+++ b/tests/manual/rhi/shared/examplefw.h
@@ -0,0 +1,548 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+
+// Adapted from hellominimalcrossgfxtriangle with the frame rendering stripped out.
+// Include this file and implement Window::customInit, release and render.
+// Debug/validation layer is enabled for D3D and Vulkan.
+
+#include <QGuiApplication>
+#include <QCommandLineParser>
+#include <QWindow>
+#include <QPlatformSurfaceEvent>
+#include <QElapsedTimer>
+#include <QTimer>
+
+#include <QtGui/private/qshader_p.h>
+#include <QFile>
+#include <QtGui/private/qrhiprofiler_p.h>
+#include <QtGui/private/qrhinull_p.h>
+
+#ifndef QT_NO_OPENGL
+#include <QtGui/private/qrhigles2_p.h>
+#include <QOffscreenSurface>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QLoggingCategory>
+#include <QtGui/private/qrhivulkan_p.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+#endif
+
+#ifdef Q_OS_DARWIN
+#include <QtGui/private/qrhimetal_p.h>
+#endif
+
+QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+enum GraphicsApi
+{
+ Null,
+ OpenGL,
+ Vulkan,
+ D3D11,
+ Metal
+};
+
+GraphicsApi graphicsApi;
+
+QString graphicsApiName()
+{
+ switch (graphicsApi) {
+ case Null:
+ return QLatin1String("Null (no output)");
+ case OpenGL:
+ return QLatin1String("OpenGL 2.x");
+ case Vulkan:
+ return QLatin1String("Vulkan");
+ case D3D11:
+ return QLatin1String("Direct3D 11");
+ case Metal:
+ return QLatin1String("Metal");
+ default:
+ break;
+ }
+ return QString();
+}
+
+QRhi::Flags rhiFlags = QRhi::EnableDebugMarkers;
+int sampleCount = 1;
+QRhiSwapChain::Flags scFlags = 0;
+QRhi::EndFrameFlags endFrameFlags = 0;
+
+class Window : public QWindow
+{
+public:
+ Window();
+ ~Window();
+
+protected:
+ void init();
+ void releaseResources();
+ void resizeSwapChain();
+ void releaseSwapChain();
+ void render();
+
+ void customInit();
+ void customRelease();
+ void customRender();
+
+ void exposeEvent(QExposeEvent *) override;
+ bool event(QEvent *) override;
+
+ bool m_running = false;
+ bool m_notExposed = false;
+ bool m_newlyExposed = false;
+
+ QRhi *m_r = nullptr;
+ bool m_hasSwapChain = false;
+ QRhiSwapChain *m_sc = nullptr;
+ QRhiRenderBuffer *m_ds = nullptr;
+ QRhiRenderPassDescriptor *m_rp = nullptr;
+
+ QMatrix4x4 m_proj;
+
+ QElapsedTimer m_timer;
+ int m_frameCount;
+
+#ifndef QT_NO_OPENGL
+ QOffscreenSurface *m_fallbackSurface = nullptr;
+#endif
+
+ friend int main(int, char**);
+};
+
+Window::Window()
+{
+ // Tell the platform plugin what we want.
+ switch (graphicsApi) {
+ case OpenGL:
+#if QT_CONFIG(opengl)
+ setSurfaceType(OpenGLSurface);
+ setFormat(QRhiGles2InitParams::adjustedFormat());
+#endif
+ break;
+ case Vulkan:
+ setSurfaceType(VulkanSurface);
+ break;
+ case D3D11:
+ setSurfaceType(OpenGLSurface); // not a typo
+ break;
+ case Metal:
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
+ setSurfaceType(MetalSurface);
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+Window::~Window()
+{
+ releaseResources();
+}
+
+void Window::exposeEvent(QExposeEvent *)
+{
+ // initialize and start rendering when the window becomes usable for graphics purposes
+ if (isExposed() && !m_running) {
+ m_running = true;
+ init();
+ resizeSwapChain();
+ }
+
+ const QSize surfaceSize = m_hasSwapChain ? m_sc->surfacePixelSize() : QSize();
+
+ // stop pushing frames when not exposed (or size is 0)
+ if ((!isExposed() || (m_hasSwapChain && surfaceSize.isEmpty())) && m_running)
+ m_notExposed = true;
+
+ // continue when exposed again and the surface has a valid size.
+ // note that the surface size can be (0, 0) even though size() reports a valid one...
+ if (isExposed() && m_running && m_notExposed && !surfaceSize.isEmpty()) {
+ m_notExposed = false;
+ m_newlyExposed = true;
+ }
+
+ // always render a frame on exposeEvent() (when exposed) in order to update
+ // immediately on window resize.
+ if (isExposed() && !surfaceSize.isEmpty())
+ render();
+}
+
+bool Window::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::UpdateRequest:
+ render();
+ break;
+
+ case QEvent::PlatformSurface:
+ // this is the proper time to tear down the swapchain (while the native window and surface are still around)
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ releaseSwapChain();
+ break;
+
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
+
+void Window::init()
+{
+ if (graphicsApi == Null) {
+ QRhiNullInitParams params;
+ m_r = QRhi::create(QRhi::Null, &params, rhiFlags);
+ }
+
+#ifndef QT_NO_OPENGL
+ if (graphicsApi == OpenGL) {
+ m_fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ QRhiGles2InitParams params;
+ params.fallbackSurface = m_fallbackSurface;
+ params.window = this;
+ m_r = QRhi::create(QRhi::OpenGLES2, &params, rhiFlags);
+ }
+#endif
+
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan) {
+ QRhiVulkanInitParams params;
+ params.inst = vulkanInstance();
+ params.window = this;
+ m_r = QRhi::create(QRhi::Vulkan, &params, rhiFlags);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (graphicsApi == D3D11) {
+ QRhiD3D11InitParams params;
+ params.enableDebugLayer = true;
+ m_r = QRhi::create(QRhi::D3D11, &params, rhiFlags);
+ }
+#endif
+
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ QRhiMetalInitParams params;
+ m_r = QRhi::create(QRhi::Metal, &params, rhiFlags);
+ }
+#endif
+
+ if (!m_r)
+ qFatal("Failed to create RHI backend");
+
+ // now onto the backend-independent init
+
+ m_sc = m_r->newSwapChain();
+ // allow depth-stencil, although we do not actually enable depth test/write for the triangle
+ m_ds = m_r->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
+ QSize(), // no need to set the size yet
+ sampleCount,
+ QRhiRenderBuffer::UsedWithSwapChainOnly);
+ m_sc->setWindow(this);
+ m_sc->setDepthStencil(m_ds);
+ m_sc->setSampleCount(sampleCount);
+ m_sc->setFlags(scFlags);
+ m_rp = m_sc->newCompatibleRenderPassDescriptor();
+ m_sc->setRenderPassDescriptor(m_rp);
+
+ customInit();
+}
+
+void Window::releaseResources()
+{
+ customRelease();
+
+ delete m_rp;
+ m_rp = nullptr;
+
+ delete m_ds;
+ m_ds = nullptr;
+
+ delete m_sc;
+ m_sc = nullptr;
+
+ delete m_r;
+ m_r = nullptr;
+
+#ifndef QT_NO_OPENGL
+ delete m_fallbackSurface;
+ m_fallbackSurface = nullptr;
+#endif
+}
+
+void Window::resizeSwapChain()
+{
+ const QSize outputSize = m_sc->surfacePixelSize();
+
+ m_ds->setPixelSize(outputSize);
+ m_ds->build(); // == m_ds->release(); m_ds->build();
+
+ m_hasSwapChain = m_sc->buildOrResize();
+
+ m_frameCount = 0;
+ m_timer.restart();
+
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void Window::releaseSwapChain()
+{
+ if (m_hasSwapChain) {
+ m_hasSwapChain = false;
+ m_sc->release();
+ }
+}
+
+void Window::render()
+{
+ if (!m_hasSwapChain || m_notExposed)
+ return;
+
+ // If the window got resized or got newly exposed, resize the swapchain.
+ // (the newly-exposed case is not actually required by some
+ // platforms/backends, but f.ex. Vulkan on Windows seems to need it)
+ if (m_sc->currentPixelSize() != m_sc->surfacePixelSize() || m_newlyExposed) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ m_newlyExposed = false;
+ }
+
+ // Start a new frame. This is where we block when too far ahead of
+ // GPU/present, and that's what throttles the thread to the refresh rate.
+ // (except for OpenGL where it happens either in endFrame or somewhere else
+ // depending on the GL implementation)
+ QRhi::FrameOpResult r = m_r->beginFrame(m_sc);
+ if (r == QRhi::FrameOpSwapChainOutOfDate) {
+ resizeSwapChain();
+ if (!m_hasSwapChain)
+ return;
+ r = m_r->beginFrame(m_sc);
+ }
+ if (r != QRhi::FrameOpSuccess) {
+ requestUpdate();
+ return;
+ }
+
+ m_frameCount += 1;
+ if (m_timer.elapsed() > 1000) {
+ if (rhiFlags.testFlag(QRhi::EnableProfiling)) {
+ const QRhiProfiler::CpuTime ff = m_r->profiler()->frameToFrameTimes(m_sc);
+ const QRhiProfiler::CpuTime be = m_r->profiler()->frameBuildTimes(m_sc);
+ const QRhiProfiler::GpuTime gp = m_r->profiler()->gpuFrameTimes(m_sc);
+ if (m_r->isFeatureSupported(QRhi::Timestamps)) {
+ qDebug("ca. %d fps. "
+ "frame-to-frame: min %lld max %lld avg %f. "
+ "frame build: min %lld max %lld avg %f. "
+ "gpu frame time: min %f max %f avg %f",
+ m_frameCount,
+ ff.minTime, ff.maxTime, ff.avgTime,
+ be.minTime, be.maxTime, be.avgTime,
+ gp.minTime, gp.maxTime, gp.avgTime);
+ } else {
+ qDebug("ca. %d fps. "
+ "frame-to-frame: min %lld max %lld avg %f. "
+ "frame build: min %lld max %lld avg %f. ",
+ m_frameCount,
+ ff.minTime, ff.maxTime, ff.avgTime,
+ be.minTime, be.maxTime, be.avgTime);
+ }
+ } else {
+ qDebug("ca. %d fps", m_frameCount);
+ }
+
+ m_timer.restart();
+ m_frameCount = 0;
+ }
+
+ customRender();
+
+ m_r->endFrame(m_sc, endFrameFlags);
+
+ if (!scFlags.testFlag(QRhiSwapChain::NoVSync))
+ requestUpdate();
+ else // try prevent all delays when NoVSync
+ QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ // Defaults.
+#if defined(Q_OS_WIN)
+ graphicsApi = D3D11;
+#elif defined(Q_OS_DARWIN)
+ graphicsApi = Metal;
+#elif QT_CONFIG(vulkan)
+ graphicsApi = Vulkan;
+#else
+ graphicsApi = OpenGL;
+#endif
+
+ // Allow overriding via the command line.
+ QCommandLineParser cmdLineParser;
+ cmdLineParser.addHelpOption();
+ QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null"));
+ cmdLineParser.addOption(nullOption);
+ QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)"));
+ cmdLineParser.addOption(glOption);
+ QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
+ cmdLineParser.addOption(vkOption);
+ QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
+ cmdLineParser.addOption(d3dOption);
+ QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
+ cmdLineParser.addOption(mtlOption);
+ // Testing cleanup both with QWindow::close() (hitting X or Alt-F4) and
+ // QCoreApplication::quit() (e.g. what a menu widget would do) is important.
+ // Use this parameter for the latter.
+ QCommandLineOption sdOption({ "s", "self-destruct" }, QLatin1String("Self destruct after 5 seconds"));
+ cmdLineParser.addOption(sdOption);
+
+ cmdLineParser.process(app);
+ if (cmdLineParser.isSet(nullOption))
+ graphicsApi = Null;
+ if (cmdLineParser.isSet(glOption))
+ graphicsApi = OpenGL;
+ if (cmdLineParser.isSet(vkOption))
+ graphicsApi = Vulkan;
+ if (cmdLineParser.isSet(d3dOption))
+ graphicsApi = D3D11;
+ if (cmdLineParser.isSet(mtlOption))
+ graphicsApi = Metal;
+
+ qDebug("Selected graphics API is %s", qPrintable(graphicsApiName()));
+ qDebug("This is a multi-api example, use command line arguments to override:\n%s", qPrintable(cmdLineParser.helpText()));
+
+#ifdef EXAMPLEFW_PREINIT
+ void preInit();
+ preInit();
+#endif
+
+ // OpenGL specifics.
+ QSurfaceFormat fmt;
+ fmt.setDepthBufferSize(24);
+ fmt.setStencilBufferSize(8);
+ if (sampleCount > 1)
+ fmt.setSamples(sampleCount);
+ if (scFlags.testFlag(QRhiSwapChain::NoVSync))
+ fmt.setSwapInterval(0);
+ if (scFlags.testFlag(QRhiSwapChain::sRGB))
+ fmt.setColorSpace(QSurfaceFormat::sRGBColorSpace);
+ QSurfaceFormat::setDefaultFormat(fmt);
+
+ // Vulkan setup.
+#if QT_CONFIG(vulkan)
+ QVulkanInstance inst;
+ if (graphicsApi == Vulkan) {
+#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
+ inst.setExtensions(QByteArrayList()
+ << "VK_KHR_get_physical_device_properties2");
+ if (!inst.create()) {
+ qWarning("Failed to create Vulkan instance, switching to OpenGL");
+ graphicsApi = OpenGL;
+ }
+ }
+#endif
+
+ // Create and show the window.
+ Window w;
+#if QT_CONFIG(vulkan)
+ if (graphicsApi == Vulkan)
+ w.setVulkanInstance(&inst);
+#endif
+ w.resize(1280, 720);
+ w.setTitle(QCoreApplication::applicationName() + QLatin1String(" - ") + graphicsApiName());
+ w.show();
+
+ if (cmdLineParser.isSet(sdOption))
+ QTimer::singleShot(5000, qGuiApp, SLOT(quit()));
+
+ int ret = app.exec();
+
+ // Window::event() will not get invoked when the
+ // PlatformSurfaceAboutToBeDestroyed event is sent during the QWindow
+ // destruction. That happens only when exiting via app::quit() instead of
+ // the more common QWindow::close(). Take care of it: if the
+ // QPlatformWindow is still around (there was no close() yet), get rid of
+ // the swapchain while it's not too late.
+ if (w.handle())
+ w.releaseSwapChain();
+
+ return ret;
+}
diff --git a/tests/manual/rhi/shared/qt256.png b/tests/manual/rhi/shared/qt256.png
new file mode 100644
index 0000000000..30c621c9c6
--- /dev/null
+++ b/tests/manual/rhi/shared/qt256.png
Binary files differ
diff --git a/tests/manual/rhi/shared/qt256_bc1_9mips.dds b/tests/manual/rhi/shared/qt256_bc1_9mips.dds
new file mode 100644
index 0000000000..734a5d184f
--- /dev/null
+++ b/tests/manual/rhi/shared/qt256_bc1_9mips.dds
Binary files differ
diff --git a/tests/manual/rhi/shared/texture.frag b/tests/manual/rhi/shared/texture.frag
new file mode 100644
index 0000000000..5405444c68
--- /dev/null
+++ b/tests/manual/rhi/shared/texture.frag
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ int flip;
+} ubuf;
+
+layout(binding = 1) uniform sampler2D tex;
+
+void main()
+{
+ vec4 c = texture(tex, v_texcoord);
+ fragColor = vec4(c.rgb * c.a, c.a);
+}
diff --git a/tests/manual/rhi/shared/texture.frag.qsb b/tests/manual/rhi/shared/texture.frag.qsb
new file mode 100644
index 0000000000..31bcd7105e
--- /dev/null
+++ b/tests/manual/rhi/shared/texture.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/texture.vert b/tests/manual/rhi/shared/texture.vert
new file mode 100644
index 0000000000..ad7e783dfb
--- /dev/null
+++ b/tests/manual/rhi/shared/texture.vert
@@ -0,0 +1,21 @@
+#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;
+ int flip;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_texcoord = vec2(texcoord.x, texcoord.y);
+ if (ubuf.flip != 0)
+ v_texcoord.y = 1.0 - v_texcoord.y;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/manual/rhi/shared/texture.vert.qsb b/tests/manual/rhi/shared/texture.vert.qsb
new file mode 100644
index 0000000000..1b9e52890d
--- /dev/null
+++ b/tests/manual/rhi/shared/texture.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/shared/texture_ms4.frag b/tests/manual/rhi/shared/texture_ms4.frag
new file mode 100644
index 0000000000..d4f2bd3654
--- /dev/null
+++ b/tests/manual/rhi/shared/texture_ms4.frag
@@ -0,0 +1,20 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ int flip;
+} ubuf;
+
+layout(binding = 1) uniform sampler2DMS tex;
+
+void main()
+{
+ ivec2 tc = ivec2(floor(vec2(textureSize(tex)) * v_texcoord));
+ vec4 c = texelFetch(tex, tc, 0) + texelFetch(tex, tc, 1) + texelFetch(tex, tc, 2) + texelFetch(tex, tc, 3);
+ c /= 4.0;
+ fragColor = vec4(c.rgb * c.a, c.a);
+}
diff --git a/tests/manual/rhi/shared/texture_ms4.frag.qsb b/tests/manual/rhi/shared/texture_ms4.frag.qsb
new file mode 100644
index 0000000000..7f187ce7f0
--- /dev/null
+++ b/tests/manual/rhi/shared/texture_ms4.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/texuploads/texuploads.cpp b/tests/manual/rhi/texuploads/texuploads.cpp
new file mode 100644
index 0000000000..6576b763d5
--- /dev/null
+++ b/tests/manual/rhi/texuploads/texuploads.cpp
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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/examplefw.h"
+#include "../shared/cube.h"
+#include <QPainter>
+
+struct {
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiTexture *tex = nullptr;
+ QRhiSampler *sampler = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QVector<QRhiResource *> releasePool;
+
+ float rotation = 0;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ int frameCount = 0;
+ QImage customImage;
+ QRhiTexture *newTex = nullptr;
+ QRhiTexture *importedTex = nullptr;
+ int testStage = 0;
+} d;
+
+void Window::customInit()
+{
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ d.releasePool << d.vbuf;
+ d.vbuf->build();
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ d.releasePool << d.ubuf;
+ d.ubuf->build();
+
+ QImage baseImage(QLatin1String(":/qt256.png"));
+ d.tex = m_r->newTexture(QRhiTexture::RGBA8, baseImage.size(), 1, QRhiTexture::UsedAsTransferSource);
+ d.releasePool << d.tex;
+ d.tex->build();
+
+ // As an alternative to what some of the other examples do, prepare an
+ // update batch right here instead of relying on vbufReady and similar flags.
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, cube);
+ qint32 flip = 0;
+ d.initialUpdates->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
+ d.initialUpdates->uploadTexture(d.tex, baseImage);
+
+ d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ d.releasePool << d.sampler;
+ d.sampler->build();
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
+ });
+ d.srb->build();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ d.ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ d.ps->setCullMode(QRhiGraphicsPipeline::Back);
+ d.ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ const QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ d.ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, vs },
+ { QRhiGraphicsShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+
+ d.ps->build();
+
+ d.customImage = QImage(128, 64, QImage::Format_RGBA8888);
+ d.customImage.fill(Qt::red);
+ QPainter painter(&d.customImage);
+ // the text may look different on different platforms, so no guarantee the
+ // output on the screen will be identical everywhere
+ painter.drawText(5, 25, "Hello world");
+ painter.end();
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+
+ // take the initial set of updates, if this is the first frame
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+
+ d.rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.scale(0.5f);
+ mvp.rotate(d.rotation, 0, 1, 0);
+ u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
+
+ if (d.frameCount > 0 && (d.frameCount % 100) == 0) {
+ d.testStage += 1;
+ qDebug("testStage = %d", d.testStage);
+
+ // Partially change the texture.
+ if (d.testStage == 1) {
+ QRhiTextureSubresourceUploadDescription mipDesc(d.customImage);
+ // The image here is smaller than the original. Use a non-zero position
+ // to make it more interesting.
+ mipDesc.setDestinationTopLeft(QPoint(100, 20));
+ QRhiTextureUploadDescription desc({ 0, 0, mipDesc });
+ u->uploadTexture(d.tex, desc);
+ }
+
+ // Exercise image copying.
+ if (d.testStage == 2) {
+ const QSize sz = d.tex->pixelSize();
+ d.newTex = m_r->newTexture(QRhiTexture::RGBA8, sz);
+ d.releasePool << d.newTex;
+ d.newTex->build();
+
+ QImage empty(sz.width(), sz.height(), QImage::Format_RGBA8888);
+ empty.fill(Qt::blue);
+ u->uploadTexture(d.newTex, empty);
+
+ // Copy the left-half of tex to the right-half of newTex, while
+ // leaving the left-half of newTex blue. Keep a 20 pixel gap at
+ // the top.
+ QRhiTextureCopyDescription desc;
+ desc.setSourceTopLeft(QPoint(0, 20));
+ desc.setPixelSize(QSize(sz.width() / 2, sz.height() - 20));
+ desc.setDestinationTopLeft(QPoint(sz.width() / 2, 20));
+ u->copyTexture(d.newTex, d.tex, desc);
+
+ // Now replace d.tex with d.newTex as the shader resource.
+ auto bindings = d.srb->bindings();
+ bindings[1] = QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.newTex, d.sampler);
+ d.srb->setBindings(bindings);
+ // "rebuild", whatever that means for a given backend. This srb is
+ // already live as the ps in the setGraphicsPipeline references it,
+ // but that's fine. Changes will be picked up automatically.
+ d.srb->build();
+ }
+
+ // Exercise simple, full texture copy.
+ if (d.testStage == 4)
+ u->copyTexture(d.newTex, d.tex);
+
+ // Now again upload customImage but this time only a part of it.
+ if (d.testStage == 5) {
+ QRhiTextureSubresourceUploadDescription mipDesc(d.customImage);
+ mipDesc.setDestinationTopLeft(QPoint(10, 120));
+ mipDesc.setSourceSize(QSize(50, 40));
+ mipDesc.setSourceTopLeft(QPoint(20, 10));
+ QRhiTextureUploadDescription desc({ 0, 0, mipDesc });
+ u->uploadTexture(d.newTex, desc);
+ }
+
+ // Exercise texture object export/import.
+ if (d.testStage == 6) {
+ const QRhiNativeHandles *h = d.tex->nativeHandles();
+ if (h) {
+#ifdef Q_OS_DARWIN
+ if (graphicsApi == Metal) {
+ qDebug() << "Metal texture: " << static_cast<const QRhiMetalTextureNativeHandles *>(h)->texture;
+ // Now could cast to id<MTLTexture> and do something with
+ // it, keeping in mind that copy operations are only done
+ // in beginPass, while rendering into a texture may only
+ // have proper results in current_frame + 2, or after a
+ // finish(). The QRhiTexture still owns the native object.
+ }
+#endif
+ // omit for other backends, the idea is the same
+
+ d.importedTex = m_r->newTexture(QRhiTexture::RGBA8, d.tex->pixelSize());
+ d.releasePool << d.importedTex;
+ if (!d.importedTex->buildFrom(h))
+ qWarning("Texture import failed");
+
+ // now d.tex and d.importedTex use the same MTLTexture
+ // underneath (owned by d.tex)
+
+ // switch to showing d.importedTex
+ auto bindings = d.srb->bindings();
+ bindings[1] = QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.importedTex, d.sampler);
+ d.srb->setBindings(bindings);
+ d.srb->build();
+ } else {
+ qWarning("Accessing native texture object is not supported");
+ }
+ }
+
+ // Exercise uploading uncompressed data without a QImage.
+ if (d.testStage == 7) {
+ auto bindings = d.srb->bindings();
+ bindings[1] = QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.newTex, d.sampler);
+ d.srb->setBindings(bindings);
+ d.srb->build();
+
+ const QSize sz(221, 139);
+ QByteArray data;
+ data.resize(sz.width() * sz.height() * 4);
+ for (int y = 0; y < sz.height(); ++y) {
+ uchar *p = reinterpret_cast<uchar *>(data.data()) + y * sz.width() * 4;
+ for (int x = 0; x < sz.width(); ++x) {
+ *p++ = 0; *p++ = 0; *p++ = y * (255 / sz.height());
+ *p++ = 255;
+ }
+ }
+ QRhiTextureSubresourceUploadDescription mipDesc(data.constData(), data.size());
+ mipDesc.setSourceSize(sz);
+ mipDesc.setDestinationTopLeft(QPoint(5, 25));
+ QRhiTextureUploadDescription desc({ 0, 0, mipDesc });
+ u->uploadTexture(d.newTex, desc);
+ }
+ }
+
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { d.vbuf, 0 },
+ { d.vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+
+ cb->endPass();
+
+ d.frameCount += 1;
+}
diff --git a/tests/manual/rhi/texuploads/texuploads.pro b/tests/manual/rhi/texuploads/texuploads.pro
new file mode 100644
index 0000000000..64f204fb32
--- /dev/null
+++ b/tests/manual/rhi/texuploads/texuploads.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ texuploads.cpp
+
+RESOURCES = texuploads.qrc
diff --git a/tests/manual/rhi/texuploads/texuploads.qrc b/tests/manual/rhi/texuploads/texuploads.qrc
new file mode 100644
index 0000000000..742b2b77af
--- /dev/null
+++ b/tests/manual/rhi/texuploads/texuploads.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="qt256.png">../shared/qt256.png</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/rhi/triquadcube/quadrenderer.cpp b/tests/manual/rhi/triquadcube/quadrenderer.cpp
new file mode 100644
index 0000000000..6137fb1b9a
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/quadrenderer.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "quadrenderer.h"
+#include <QFile>
+#include <QtGui/private/qshader_p.h>
+
+// Renders a quad using indexed drawing. No QRhiGraphicsPipeline is created, it
+// expects to reuse the one created by TriangleRenderer. A separate
+// QRhiShaderResourceBindings is still needed, this will override the one the
+// QRhiGraphicsPipeline references.
+
+static float vertexData[] =
+{ // Y up (note m_proj), CCW
+ -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f
+};
+
+static quint16 indexData[] =
+{
+ 0, 1, 2, 0, 2, 3
+};
+
+void QuadRenderer::initResources(QRhiRenderPassDescriptor *)
+{
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ m_vbuf->build();
+ m_vbufReady = false;
+
+ m_ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData));
+ m_ibuf->build();
+
+ m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ m_ubuf->build();
+
+ m_srb = m_r->newShaderResourceBindings();
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf)
+ });
+ m_srb->build();
+}
+
+void QuadRenderer::setPipeline(QRhiGraphicsPipeline *ps)
+{
+ m_ps = ps;
+}
+
+void QuadRenderer::resize(const QSize &pixelSize)
+{
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, pixelSize.width() / (float) pixelSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void QuadRenderer::releaseResources()
+{
+ delete m_srb;
+ m_srb = nullptr;
+
+ delete m_ubuf;
+ m_ubuf = nullptr;
+
+ delete m_ibuf;
+ m_ibuf = nullptr;
+
+ delete m_vbuf;
+ m_vbuf = nullptr;
+}
+
+void QuadRenderer::queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
+{
+ if (!m_vbufReady) {
+ m_vbufReady = true;
+ resourceUpdates->uploadStaticBuffer(m_vbuf, vertexData);
+ resourceUpdates->uploadStaticBuffer(m_ibuf, indexData);
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.translate(m_translation);
+ mvp.rotate(m_rotation, 0, 1, 0);
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+
+ if (!m_opacityReady) {
+ m_opacityReady = true;
+ const float opacity = 1.0f;
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 64, 4, &opacity);
+ }
+}
+
+void QuadRenderer::queueDraw(QRhiCommandBuffer *cb, const QSize &/*outputSizeInPixels*/)
+{
+ cb->setGraphicsPipeline(m_ps);
+ //cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height()));
+ cb->setShaderResources(m_srb);
+ const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding, m_ibuf, 0, QRhiCommandBuffer::IndexUInt16);
+ cb->drawIndexed(6);
+}
diff --git a/tests/manual/rhi/triquadcube/quadrenderer.h b/tests/manual/rhi/triquadcube/quadrenderer.h
new file mode 100644
index 0000000000..79d5b8209d
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/quadrenderer.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QUADRENDERER_H
+#define QUADRENDERER_H
+
+#include <QtGui/private/qrhi_p.h>
+
+class QuadRenderer
+{
+public:
+ void setRhi(QRhi *r) { m_r = r; }
+ void setSampleCount(int samples) { m_sampleCount = samples; }
+ int sampleCount() const { return m_sampleCount; }
+ void setTranslation(const QVector3D &v) { m_translation = v; }
+ void initResources(QRhiRenderPassDescriptor *rp);
+ void releaseResources();
+ void setPipeline(QRhiGraphicsPipeline *ps);
+ void resize(const QSize &pixelSize);
+ void queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates);
+ void queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels);
+
+private:
+ QRhi *m_r;
+
+ QRhiBuffer *m_vbuf = nullptr;
+ bool m_vbufReady = false;
+ QRhiBuffer *m_ibuf = nullptr;
+ bool m_opacityReady = false;
+ QRhiBuffer *m_ubuf = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+
+ QVector3D m_translation;
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ int m_sampleCount = 1; // no MSAA by default
+};
+
+#endif
diff --git a/tests/manual/rhi/triquadcube/texturedcuberenderer.cpp b/tests/manual/rhi/triquadcube/texturedcuberenderer.cpp
new file mode 100644
index 0000000000..d2e1f99923
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/texturedcuberenderer.cpp
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "texturedcuberenderer.h"
+#include <QFile>
+#include <QtGui/private/qshader_p.h>
+
+#include "../shared/cube.h"
+
+const bool MIPMAP = true;
+const bool AUTOGENMIPMAP = true;
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+void TexturedCubeRenderer::initResources(QRhiRenderPassDescriptor *rp)
+{
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ m_vbuf->setName(QByteArrayLiteral("Cube vbuf (textured)"));
+ m_vbuf->build();
+ m_vbufReady = false;
+
+ m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 4);
+ m_ubuf->setName(QByteArrayLiteral("Cube ubuf (textured)"));
+ m_ubuf->build();
+
+ m_image = QImage(QLatin1String(":/qt256.png")).convertToFormat(QImage::Format_RGBA8888);
+ QRhiTexture::Flags texFlags = 0;
+ if (MIPMAP)
+ texFlags |= QRhiTexture::MipMapped;
+ if (AUTOGENMIPMAP)
+ texFlags |= QRhiTexture::UsedWithGenerateMips;
+ m_tex = m_r->newTexture(QRhiTexture::RGBA8, QSize(m_image.width(), m_image.height()), 1, texFlags);
+ m_tex->setName(QByteArrayLiteral("Qt texture"));
+ m_tex->build();
+
+ m_sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, MIPMAP ? QRhiSampler::Linear : QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ m_sampler->build();
+
+ m_srb = m_r->newShaderResourceBindings();
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, m_tex, m_sampler)
+ });
+ m_srb->build();
+
+ m_ps = m_r->newGraphicsPipeline();
+
+ // No blending but the texture has alpha which we do not want to write out.
+ // Be nice. (would not matter for an onscreen window but makes a difference
+ // when reading back and saving into image files f.ex.)
+ QRhiGraphicsPipeline::TargetBlend blend;
+ blend.colorWrite = QRhiGraphicsPipeline::R | QRhiGraphicsPipeline::G | QRhiGraphicsPipeline::B;
+ m_ps->setTargetBlends({ blend });
+
+ m_ps->setDepthTest(true);
+ m_ps->setDepthWrite(true);
+ m_ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ m_ps->setCullMode(QRhiGraphicsPipeline::Back);
+ m_ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ m_ps->setSampleCount(m_sampleCount);
+
+ QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ Q_ASSERT(vs.isValid());
+ QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ Q_ASSERT(fs.isValid());
+ m_ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, vs },
+ { QRhiGraphicsShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb);
+ m_ps->setRenderPassDescriptor(rp);
+
+ m_ps->build();
+}
+
+void TexturedCubeRenderer::resize(const QSize &pixelSize)
+{
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, pixelSize.width() / (float) pixelSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void TexturedCubeRenderer::releaseResources()
+{
+ delete m_ps;
+ m_ps = nullptr;
+
+ delete m_srb;
+ m_srb = nullptr;
+
+ delete m_sampler;
+ m_sampler = nullptr;
+
+ delete m_tex;
+ m_tex = nullptr;
+
+ delete m_ubuf;
+ m_ubuf = nullptr;
+
+ delete m_vbuf;
+ m_vbuf = nullptr;
+}
+
+void TexturedCubeRenderer::queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
+{
+ if (!m_vbufReady) {
+ m_vbufReady = true;
+ resourceUpdates->uploadStaticBuffer(m_vbuf, cube);
+ qint32 flip = 0;
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 64, 4, &flip);
+ }
+
+ if (!m_image.isNull()) {
+ if (MIPMAP) {
+ QRhiTextureUploadDescription desc;
+ if (!AUTOGENMIPMAP) {
+ // the ghetto mipmap generator...
+ for (int i = 0, ie = m_r->mipLevelsForSize(m_image.size()); i != ie; ++i) {
+ QImage image = m_image.scaled(m_r->sizeForMipLevel(i, m_image.size()));
+ desc.append({ 0, i, image });
+ }
+ } else {
+ desc.append({ 0, 0, m_image });
+ }
+ resourceUpdates->uploadTexture(m_tex, desc);
+ if (AUTOGENMIPMAP)
+ resourceUpdates->generateMips(m_tex);
+ } else {
+ resourceUpdates->uploadTexture(m_tex, m_image);
+ }
+ m_image = QImage();
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.translate(m_translation);
+ mvp.scale(0.5f);
+ mvp.rotate(m_rotation, 0, 1, 0);
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+}
+
+void TexturedCubeRenderer::queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels)
+{
+ cb->setGraphicsPipeline(m_ps);
+ cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { m_vbuf, 0 },
+ { m_vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+}
diff --git a/tests/manual/rhi/triquadcube/texturedcuberenderer.h b/tests/manual/rhi/triquadcube/texturedcuberenderer.h
new file mode 100644
index 0000000000..879f875209
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/texturedcuberenderer.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 TEXTUREDCUBERENDERER_H
+#define TEXTUREDCUBERENDERER_H
+
+#include <QtGui/private/qrhi_p.h>
+
+class TexturedCubeRenderer
+{
+public:
+ void setRhi(QRhi *r) { m_r = r; }
+ void setSampleCount(int samples) { m_sampleCount = samples; }
+ void setTranslation(const QVector3D &v) { m_translation = v; }
+ void initResources(QRhiRenderPassDescriptor *rp);
+ void releaseResources();
+ void resize(const QSize &pixelSize);
+ void queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates);
+ void queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels);
+
+private:
+ QRhi *m_r;
+
+ QRhiBuffer *m_vbuf = nullptr;
+ bool m_vbufReady = false;
+ QRhiBuffer *m_ubuf = nullptr;
+ QImage m_image;
+ QRhiTexture *m_tex = nullptr;
+ QRhiSampler *m_sampler = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+
+ QVector3D m_translation;
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ int m_sampleCount = 1; // no MSAA by default
+};
+
+#endif
diff --git a/tests/manual/rhi/triquadcube/triangleoncuberenderer.cpp b/tests/manual/rhi/triquadcube/triangleoncuberenderer.cpp
new file mode 100644
index 0000000000..40d9615aa1
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/triangleoncuberenderer.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "triangleoncuberenderer.h"
+#include <QFile>
+#include <QtGui/private/qshader_p.h>
+
+// toggle to test the preserved content (no clear) path
+const bool IMAGE_UNDER_OFFSCREEN_RENDERING = false;
+const bool UPLOAD_UNDERLAY_ON_EVERY_FRAME = false;
+
+const bool DS_ATT = false; // have a depth-stencil attachment for the offscreen pass
+
+const bool DEPTH_TEXTURE = false; // offscreen pass uses a depth texture (verify with renderdoc etc., ignore valid.layer about ps slot 0)
+const bool MRT = false; // two textures, the second is just cleared as the shader does not write anything (valid.layer may warn but for testing that's ok)
+
+#include "../shared/cube.h"
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+static const QSize OFFSCREEN_SIZE(512, 512);
+
+void TriangleOnCubeRenderer::initResources(QRhiRenderPassDescriptor *rp)
+{
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
+ m_vbuf->setName(QByteArrayLiteral("Cube vbuf (textured with offscreen)"));
+ m_vbuf->build();
+ m_vbufReady = false;
+
+ m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 4);
+ m_ubuf->setName(QByteArrayLiteral("Cube ubuf (textured with offscreen)"));
+ m_ubuf->build();
+
+ if (IMAGE_UNDER_OFFSCREEN_RENDERING) {
+ m_image = QImage(QLatin1String(":/qt256.png")).scaled(OFFSCREEN_SIZE).convertToFormat(QImage::Format_RGBA8888);
+ if (m_r->isYUpInFramebuffer())
+ m_image = m_image.mirrored(); // just cause we'll flip texcoord Y when y up so accommodate our static background image as well
+ }
+
+ m_tex = m_r->newTexture(QRhiTexture::RGBA8, OFFSCREEN_SIZE, 1, QRhiTexture::RenderTarget);
+ m_tex->setName(QByteArrayLiteral("Texture for offscreen content"));
+ m_tex->build();
+
+ if (MRT) {
+ m_tex2 = m_r->newTexture(QRhiTexture::RGBA8, OFFSCREEN_SIZE, 1, QRhiTexture::RenderTarget);
+ m_tex2->build();
+ }
+
+ if (DS_ATT) {
+ m_offscreenTriangle.setDepthWrite(true);
+ m_ds = m_r->newRenderBuffer(QRhiRenderBuffer::DepthStencil, m_tex->pixelSize());
+ m_ds->build();
+ }
+
+ if (DEPTH_TEXTURE) {
+ m_offscreenTriangle.setDepthWrite(true);
+ m_depthTex = m_r->newTexture(QRhiTexture::D32F, OFFSCREEN_SIZE, 1, QRhiTexture::RenderTarget);
+ m_depthTex->build();
+ }
+
+ m_sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None, QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
+ m_sampler->build();
+
+ m_srb = m_r->newShaderResourceBindings();
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, m_tex, m_sampler)
+ });
+ m_srb->build();
+
+ m_ps = m_r->newGraphicsPipeline();
+
+ m_ps->setDepthTest(true);
+ m_ps->setDepthWrite(true);
+ m_ps->setDepthOp(QRhiGraphicsPipeline::Less);
+
+ m_ps->setCullMode(QRhiGraphicsPipeline::Back);
+ m_ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+
+ m_ps->setSampleCount(m_sampleCount);
+
+ QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ Q_ASSERT(vs.isValid());
+ QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ Q_ASSERT(fs.isValid());
+ m_ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, vs },
+ { QRhiGraphicsShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 3 * sizeof(float) },
+ { 2 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 1, 1, QRhiVertexInputAttribute::Float2, 0 }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb);
+ m_ps->setRenderPassDescriptor(rp);
+
+ m_ps->build();
+
+ QRhiTextureRenderTarget::Flags rtFlags = 0;
+ if (IMAGE_UNDER_OFFSCREEN_RENDERING)
+ rtFlags |= QRhiTextureRenderTarget::PreserveColorContents;
+
+ if (DEPTH_TEXTURE) {
+ QRhiTextureRenderTargetDescription desc;
+ desc.setDepthTexture(m_depthTex);
+ m_rt = m_r->newTextureRenderTarget(desc, rtFlags);
+ } else {
+ QRhiTextureRenderTargetDescription desc;
+ QRhiColorAttachment color0 { m_tex };
+ if (DS_ATT)
+ desc.setDepthStencilBuffer(m_ds);
+ if (MRT) {
+ m_offscreenTriangle.setColorAttCount(2);
+ QRhiColorAttachment color1 { m_tex2 };
+ desc.setColorAttachments({ color0, color1 });
+ } else {
+ desc.setColorAttachments({ color0 });
+ }
+ m_rt = m_r->newTextureRenderTarget(desc, rtFlags);
+ }
+
+ m_rp = m_rt->newCompatibleRenderPassDescriptor();
+ m_rt->setRenderPassDescriptor(m_rp);
+
+ m_rt->build();
+
+ m_offscreenTriangle.setRhi(m_r);
+ m_offscreenTriangle.initResources(m_rp);
+ m_offscreenTriangle.setScale(2);
+ // m_tex and the offscreen triangle are never multisample
+}
+
+void TriangleOnCubeRenderer::resize(const QSize &pixelSize)
+{
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, pixelSize.width() / (float) pixelSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+
+ m_offscreenTriangle.resize(pixelSize);
+}
+
+void TriangleOnCubeRenderer::releaseResources()
+{
+ m_offscreenTriangle.releaseResources();
+
+ delete m_ps;
+ m_ps = nullptr;
+
+ delete m_srb;
+ m_srb = nullptr;
+
+ delete m_rt;
+ m_rt = nullptr;
+
+ delete m_rp;
+ m_rp = nullptr;
+
+ delete m_sampler;
+ m_sampler = nullptr;
+
+ delete m_depthTex;
+ m_depthTex = nullptr;
+
+ delete m_tex2;
+ m_tex2 = nullptr;
+
+ delete m_tex;
+ m_tex = nullptr;
+
+ delete m_ds;
+ m_ds = nullptr;
+
+ delete m_ubuf;
+ m_ubuf = nullptr;
+
+ delete m_vbuf;
+ m_vbuf = nullptr;
+}
+
+void TriangleOnCubeRenderer::queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
+{
+ if (!m_vbufReady) {
+ m_vbufReady = true;
+ resourceUpdates->uploadStaticBuffer(m_vbuf, cube);
+ qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0;
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 64, 4, &flip);
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.translate(m_translation);
+ mvp.scale(0.5f);
+ mvp.rotate(m_rotation, 1, 0, 0);
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+
+ // ###
+// if (DEPTH_TEXTURE) {
+// // m_tex is basically undefined here, be nice and transition the layout properly at least
+// resourceUpdates->prepareTextureForUse(m_tex, QRhiResourceUpdateBatch::TextureRead);
+// }
+}
+
+void TriangleOnCubeRenderer::queueOffscreenPass(QRhiCommandBuffer *cb)
+{
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ m_offscreenTriangle.queueResourceUpdates(u);
+
+ if (IMAGE_UNDER_OFFSCREEN_RENDERING && !m_image.isNull()) {
+ u->uploadTexture(m_tex, m_image);
+ if (!UPLOAD_UNDERLAY_ON_EVERY_FRAME)
+ m_image = QImage();
+ }
+
+ cb->beginPass(m_rt, QColor::fromRgbF(0.0f, 0.4f, 0.7f, 1.0f), { 1.0f, 0 }, u);
+ m_offscreenTriangle.queueDraw(cb, OFFSCREEN_SIZE);
+ cb->endPass();
+}
+
+void TriangleOnCubeRenderer::queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels)
+{
+ cb->setGraphicsPipeline(m_ps);
+ cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { m_vbuf, 0 },
+ { m_vbuf, 36 * 3 * sizeof(float) }
+ };
+ cb->setVertexInput(0, 2, vbufBindings);
+ cb->draw(36);
+}
diff --git a/tests/manual/rhi/triquadcube/triangleoncuberenderer.h b/tests/manual/rhi/triquadcube/triangleoncuberenderer.h
new file mode 100644
index 0000000000..5a56bf6bd1
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/triangleoncuberenderer.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 TRIANGLEONCUBERENDERER_H
+#define TRIANGLEONCUBERENDERER_H
+
+#include "trianglerenderer.h"
+
+class TriangleOnCubeRenderer
+{
+public:
+ void setRhi(QRhi *r) { m_r = r; }
+ void setSampleCount(int samples) { m_sampleCount = samples; }
+ void setTranslation(const QVector3D &v) { m_translation = v; }
+ void initResources(QRhiRenderPassDescriptor *rp);
+ void releaseResources();
+ void resize(const QSize &pixelSize);
+ void queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates);
+ void queueOffscreenPass(QRhiCommandBuffer *cb);
+ void queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels);
+
+private:
+ QRhi *m_r;
+
+ QRhiBuffer *m_vbuf = nullptr;
+ bool m_vbufReady = false;
+ QRhiBuffer *m_ubuf = nullptr;
+ QRhiTexture *m_tex = nullptr;
+ QRhiRenderBuffer *m_ds = nullptr;
+ QRhiTexture *m_tex2 = nullptr;
+ QRhiTexture *m_depthTex = nullptr;
+ QRhiSampler *m_sampler = nullptr;
+ QRhiTextureRenderTarget *m_rt = nullptr;
+ QRhiRenderPassDescriptor *m_rp = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+
+ QVector3D m_translation;
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ int m_sampleCount = 1; // no MSAA by default
+
+ TriangleRenderer m_offscreenTriangle;
+
+ QImage m_image;
+};
+
+#endif
diff --git a/tests/manual/rhi/triquadcube/trianglerenderer.cpp b/tests/manual/rhi/triquadcube/trianglerenderer.cpp
new file mode 100644
index 0000000000..aac76d4110
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/trianglerenderer.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 <QFile>
+#include <QtGui/private/qshader_p.h>
+
+//#define VBUF_IS_DYNAMIC
+
+static float vertexData[] = { // Y up (note m_proj), CCW
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f
+};
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+void TriangleRenderer::initResources(QRhiRenderPassDescriptor *rp)
+{
+#ifdef VBUF_IS_DYNAMIC
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+#else
+ m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+#endif
+ m_vbuf->setName(QByteArrayLiteral("Triangle vbuf"));
+ m_vbuf->build();
+ m_vbufReady = false;
+
+ m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
+ m_ubuf->setName(QByteArrayLiteral("Triangle ubuf"));
+ m_ubuf->build();
+
+ m_srb = m_r->newShaderResourceBindings();
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf)
+ });
+ m_srb->build();
+
+ m_ps = m_r->newGraphicsPipeline();
+
+ QRhiGraphicsPipeline::TargetBlend premulAlphaBlend; // convenient defaults...
+ premulAlphaBlend.enable = true;
+ QVector<QRhiGraphicsPipeline::TargetBlend> rtblends;
+ for (int i = 0; i < m_colorAttCount; ++i)
+ rtblends << premulAlphaBlend;
+
+ m_ps->setTargetBlends(rtblends);
+ m_ps->setSampleCount(m_sampleCount);
+
+ if (m_depthWrite) { // TriangleOnCube may want to exercise this
+ m_ps->setDepthTest(true);
+ m_ps->setDepthOp(QRhiGraphicsPipeline::Always);
+ m_ps->setDepthWrite(true);
+ }
+
+ QShader vs = getShader(QLatin1String(":/color.vert.qsb"));
+ Q_ASSERT(vs.isValid());
+ QShader fs = getShader(QLatin1String(":/color.frag.qsb"));
+ Q_ASSERT(fs.isValid());
+ m_ps->setShaderStages({
+ { QRhiGraphicsShaderStage::Vertex, vs },
+ { QRhiGraphicsShaderStage::Fragment, fs }
+ });
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 7 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb);
+ m_ps->setRenderPassDescriptor(rp);
+
+ m_ps->build();
+}
+
+void TriangleRenderer::resize(const QSize &pixelSize)
+{
+ m_proj = m_r->clipSpaceCorrMatrix();
+ m_proj.perspective(45.0f, pixelSize.width() / (float) pixelSize.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void TriangleRenderer::releaseResources()
+{
+ delete m_ps;
+ m_ps = nullptr;
+
+ delete m_srb;
+ m_srb = nullptr;
+
+ delete m_ubuf;
+ m_ubuf = nullptr;
+
+ delete m_vbuf;
+ m_vbuf = nullptr;
+}
+
+void TriangleRenderer::queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
+{
+#if 0
+ static int messWithBufferTrigger = 0;
+ // recreate the underlying VkBuffer every second frame
+ // to exercise setShaderResources' built-in smartness
+ if (!(messWithBufferTrigger & 1)) {
+ m_ubuf->release();
+ m_ubuf->build();
+ }
+ ++messWithBufferTrigger;
+#endif
+
+ if (!m_vbufReady) {
+ m_vbufReady = true;
+#ifdef VBUF_IS_DYNAMIC
+ resourceUpdates->updateDynamicBuffer(m_vbuf, 0, m_vbuf->size(), vertexData);
+#else
+ resourceUpdates->uploadStaticBuffer(m_vbuf, vertexData);
+#endif
+ }
+
+ m_rotation += 1.0f;
+ QMatrix4x4 mvp = m_proj;
+ mvp.translate(m_translation);
+ mvp.scale(m_scale);
+ mvp.rotate(m_rotation, 0, 1, 0);
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData());
+
+ m_opacity += m_opacityDir * 0.005f;
+ if (m_opacity < 0.0f || m_opacity > 1.0f) {
+ m_opacityDir *= -1;
+ m_opacity = qBound(0.0f, m_opacity, 1.0f);
+ }
+ resourceUpdates->updateDynamicBuffer(m_ubuf, 64, 4, &m_opacity);
+}
+
+void TriangleRenderer::queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels)
+{
+ cb->setGraphicsPipeline(m_ps);
+ cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf, 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+}
diff --git a/tests/manual/rhi/triquadcube/trianglerenderer.h b/tests/manual/rhi/triquadcube/trianglerenderer.h
new file mode 100644
index 0000000000..53d6926a62
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/trianglerenderer.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 TRIANGLERENDERER_H
+#define TRIANGLERENDERER_H
+
+#include <QtGui/private/qrhi_p.h>
+
+class TriangleRenderer
+{
+public:
+ void setRhi(QRhi *r) { m_r = r; }
+ void setSampleCount(int samples) { m_sampleCount = samples; }
+ int sampleCount() const { return m_sampleCount; }
+ void setTranslation(const QVector3D &v) { m_translation = v; }
+ void setScale(float f) { m_scale = f; }
+ void setDepthWrite(bool enable) { m_depthWrite = enable; }
+ void setColorAttCount(int count) { m_colorAttCount = count; }
+ QRhiGraphicsPipeline *pipeline() const { return m_ps; }
+ void initResources(QRhiRenderPassDescriptor *rp);
+ void releaseResources();
+ void resize(const QSize &pixelSize);
+ void queueResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates);
+ void queueDraw(QRhiCommandBuffer *cb, const QSize &outputSizeInPixels);
+
+private:
+ QRhi *m_r;
+
+ QRhiBuffer *m_vbuf = nullptr;
+ bool m_vbufReady = false;
+ QRhiBuffer *m_ubuf = nullptr;
+ QRhiShaderResourceBindings *m_srb = nullptr;
+ QRhiGraphicsPipeline *m_ps = nullptr;
+
+ QVector3D m_translation;
+ float m_scale = 1;
+ bool m_depthWrite = false;
+ int m_colorAttCount = 1;
+ QMatrix4x4 m_proj;
+ float m_rotation = 0;
+ float m_opacity = 1;
+ int m_opacityDir = -1;
+ int m_sampleCount = 1; // no MSAA by default
+};
+
+#endif
diff --git a/tests/manual/rhi/triquadcube/triquadcube.cpp b/tests/manual/rhi/triquadcube/triquadcube.cpp
new file mode 100644
index 0000000000..741e64be0a
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/triquadcube.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+
+// An example exercising more than a single feature. Enables profiling
+// (resource logging to a file) and inserts debug markers and sets some
+// object names. Can also be used to test MSAA swapchains, swapchain image
+// readback, requesting an sRGB swapchain, and some texture features.
+
+#define EXAMPLEFW_PREINIT
+#include "../shared/examplefw.h"
+#include "trianglerenderer.h"
+#include "quadrenderer.h"
+#include "texturedcuberenderer.h"
+#include "triangleoncuberenderer.h"
+
+#include <QFileInfo>
+#include <QFile>
+#include <QtGui/private/qrhiprofiler_p.h>
+
+#define PROFILE_TO_FILE
+//#define SKIP_PRESENT
+//#define USE_MSAA
+//#define USE_SRGB_SWAPCHAIN
+//#define READBACK_SWAPCHAIN
+//#define NO_VSYNC
+//#define USE_MIN_SWAPCHAIN_BUFFERS
+
+struct {
+ TriangleRenderer triRenderer;
+ QuadRenderer quadRenderer;
+ TexturedCubeRenderer cubeRenderer;
+ TriangleOnCubeRenderer liveTexCubeRenderer;
+ bool onScreenOnly = false;
+ bool triangleOnly = false;
+ QSize lastOutputSize;
+ int frameCount = 0;
+ QFile profOut;
+} d;
+
+void preInit()
+{
+#ifdef PROFILE_TO_FILE
+ rhiFlags |= QRhi::EnableProfiling;
+ const QString profFn = QFileInfo(QLatin1String("rhiprof.txt")).absoluteFilePath();
+ qDebug("Writing profiling output to %s", qPrintable(profFn));
+ d.profOut.setFileName(profFn);
+ d.profOut.open(QIODevice::WriteOnly);
+#endif
+
+#ifdef SKIP_PRESENT
+ endFrameFlags |= QRhi::SkipPresent;
+#endif
+
+#ifdef USE_MSAA
+ sampleCount = 4; // enable 4x MSAA (except for the render-to-texture pass)
+#endif
+
+#ifdef READBACK_SWAPCHAIN
+ scFlags |= QRhiSwapChain::UsedAsTransferSource;
+#endif
+
+#ifdef USE_SRGB_SWAPCHAIN
+ scFlags |= QRhiSwapChain::sRGB;
+#endif
+
+#ifdef NO_VSYNC
+ scFlags |= QRhiSwapChain::NoVSync;
+#endif
+
+#ifdef USE_MIN_SWAPCHAIN_BUFFERS
+ scFlags |= QRhiSwapChain::MinimalBufferCount;
+#endif
+
+ // For OpenGL some of these are incorporated into the QSurfaceFormat by
+ // examplefw.h after returning from here as that is out of the RHI's control.
+}
+
+void Window::customInit()
+{
+#ifdef PROFILE_TO_FILE
+ m_r->profiler()->setDevice(&d.profOut);
+#endif
+
+ d.triRenderer.setRhi(m_r);
+ d.triRenderer.setSampleCount(sampleCount);
+ d.triRenderer.initResources(m_rp);
+
+ if (!d.triangleOnly) {
+ d.triRenderer.setTranslation(QVector3D(0, 0.5f, 0));
+
+ d.quadRenderer.setRhi(m_r);
+ d.quadRenderer.setSampleCount(sampleCount);
+ d.quadRenderer.setPipeline(d.triRenderer.pipeline());
+ d.quadRenderer.initResources(m_rp);
+ d.quadRenderer.setTranslation(QVector3D(1.5f, -0.5f, 0));
+
+ d.cubeRenderer.setRhi(m_r);
+ d.cubeRenderer.setSampleCount(sampleCount);
+ d.cubeRenderer.initResources(m_rp);
+ d.cubeRenderer.setTranslation(QVector3D(0, -0.5f, 0));
+ }
+
+ if (!d.onScreenOnly) {
+ d.liveTexCubeRenderer.setRhi(m_r);
+ d.liveTexCubeRenderer.setSampleCount(sampleCount);
+ d.liveTexCubeRenderer.initResources(m_rp);
+ d.liveTexCubeRenderer.setTranslation(QVector3D(-2.0f, 0, 0));
+ }
+
+ // Put the gpu mem allocator statistics to the profiling stream after doing
+ // all the init. (where applicable)
+ m_r->profiler()->addVMemAllocatorStats();
+
+ // Check some features/limits.
+ qDebug("isFeatureSupported(MultisampleTexture): %d", m_r->isFeatureSupported(QRhi::MultisampleTexture));
+ qDebug("isFeatureSupported(MultisampleRenderBuffer): %d", m_r->isFeatureSupported(QRhi::MultisampleRenderBuffer));
+ qDebug("isFeatureSupported(DebugMarkers): %d", m_r->isFeatureSupported(QRhi::DebugMarkers));
+ qDebug("isFeatureSupported(Timestamps): %d", m_r->isFeatureSupported(QRhi::Timestamps));
+ qDebug("isFeatureSupported(Instancing): %d", m_r->isFeatureSupported(QRhi::Instancing));
+ qDebug("isFeatureSupported(CustomInstanceStepRate): %d", m_r->isFeatureSupported(QRhi::CustomInstanceStepRate));
+ qDebug("isFeatureSupported(PrimitiveRestart): %d", m_r->isFeatureSupported(QRhi::PrimitiveRestart));
+ qDebug("isFeatureSupported(NonDynamicUniformBuffers): %d", m_r->isFeatureSupported(QRhi::NonDynamicUniformBuffers));
+ qDebug("isFeatureSupported(NonFourAlignedEffectiveIndexBufferOffset): %d", m_r->isFeatureSupported(QRhi::NonFourAlignedEffectiveIndexBufferOffset));
+ qDebug("isFeatureSupported(NPOTTextureRepeat): %d", m_r->isFeatureSupported(QRhi::NPOTTextureRepeat));
+ qDebug("isFeatureSupported(RedOrAlpha8IsRed): %d", m_r->isFeatureSupported(QRhi::RedOrAlpha8IsRed));
+ qDebug("isFeatureSupported(ElementIndexUint): %d", m_r->isFeatureSupported(QRhi::ElementIndexUint));
+ qDebug("Min 2D texture width/height: %d", m_r->resourceLimit(QRhi::TextureSizeMin));
+ qDebug("Max 2D texture width/height: %d", m_r->resourceLimit(QRhi::TextureSizeMax));
+ qDebug("Max color attachment count: %d", m_r->resourceLimit(QRhi::MaxColorAttachments));
+}
+
+void Window::customRelease()
+{
+ d.triRenderer.releaseResources();
+
+ if (!d.triangleOnly) {
+ d.quadRenderer.releaseResources();
+ d.cubeRenderer.releaseResources();
+ }
+
+ if (!d.onScreenOnly)
+ d.liveTexCubeRenderer.releaseResources();
+}
+
+void Window::customRender()
+{
+ const QSize outputSize = m_sc->currentPixelSize();
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+
+ if (outputSize != d.lastOutputSize) {
+ d.triRenderer.resize(outputSize);
+ if (!d.triangleOnly) {
+ d.quadRenderer.resize(outputSize);
+ d.cubeRenderer.resize(outputSize);
+ }
+ if (!d.onScreenOnly)
+ d.liveTexCubeRenderer.resize(outputSize);
+ d.lastOutputSize = outputSize;
+ }
+
+ if (!d.onScreenOnly) {
+ cb->debugMarkBegin("Offscreen triangle pass");
+ d.liveTexCubeRenderer.queueOffscreenPass(cb);
+ cb->debugMarkEnd();
+ }
+
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ d.triRenderer.queueResourceUpdates(u);
+ if (!d.triangleOnly) {
+ d.quadRenderer.queueResourceUpdates(u);
+ d.cubeRenderer.queueResourceUpdates(u);
+ }
+ if (!d.onScreenOnly)
+ d.liveTexCubeRenderer.queueResourceUpdates(u);
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u);
+ cb->debugMarkBegin(QByteArrayLiteral("Triangle"));
+ d.triRenderer.queueDraw(cb, outputSize);
+ cb->debugMarkEnd();
+ if (!d.triangleOnly) {
+ cb->debugMarkMsg(QByteArrayLiteral("More stuff"));
+ cb->debugMarkBegin(QByteArrayLiteral("Quad"));
+ d.quadRenderer.queueDraw(cb, outputSize);
+ cb->debugMarkEnd();
+ cb->debugMarkBegin(QByteArrayLiteral("Cube"));
+ d.cubeRenderer.queueDraw(cb, outputSize);
+ cb->debugMarkEnd();
+ }
+ if (!d.onScreenOnly) {
+ cb->debugMarkMsg(QByteArrayLiteral("Even more stuff"));
+ cb->debugMarkBegin(QByteArrayLiteral("Cube with offscreen triangle"));
+ d.liveTexCubeRenderer.queueDraw(cb, outputSize);
+ cb->debugMarkEnd();
+ }
+
+ QRhiResourceUpdateBatch *passEndUpdates = nullptr;
+#ifdef READBACK_SWAPCHAIN
+ passEndUpdates = m_r->nextResourceUpdateBatch();
+ QRhiReadbackDescription rb; // no texture given -> backbuffer
+ QRhiReadbackResult *rbResult = new QRhiReadbackResult;
+ int frameNo = d.frameCount;
+ rbResult->completed = [this, rbResult, frameNo] {
+ {
+ QImage::Format fmt = rbResult->format == QRhiTexture::BGRA8 ? QImage::Format_ARGB32_Premultiplied
+ : QImage::Format_RGBA8888_Premultiplied;
+ const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
+ QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
+ QString fn = QString::asprintf("frame%d.png", frameNo);
+ fn = QFileInfo(fn).absoluteFilePath();
+ qDebug("Saving into %s", qPrintable(fn));
+ if (m_r->isYUpInFramebuffer())
+ image.mirrored().save(fn);
+ else
+ image.save(fn);
+ }
+ delete rbResult;
+ };
+ passEndUpdates->readBackTexture(rb, rbResult);
+#endif
+
+ cb->endPass(passEndUpdates);
+
+ d.frameCount += 1;
+}
diff --git a/tests/manual/rhi/triquadcube/triquadcube.pro b/tests/manual/rhi/triquadcube/triquadcube.pro
new file mode 100644
index 0000000000..0002b3cad1
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/triquadcube.pro
@@ -0,0 +1,18 @@
+TEMPLATE = app
+
+QT += gui-private
+
+SOURCES = \
+ triquadcube.cpp \
+ trianglerenderer.cpp \
+ quadrenderer.cpp \
+ texturedcuberenderer.cpp \
+ triangleoncuberenderer.cpp
+
+HEADERS = \
+ trianglerenderer.h \
+ quadrenderer.h \
+ texturedcuberenderer.h \
+ triangleoncuberenderer.h
+
+RESOURCES = triquadcube.qrc
diff --git a/tests/manual/rhi/triquadcube/triquadcube.qrc b/tests/manual/rhi/triquadcube/triquadcube.qrc
new file mode 100644
index 0000000000..41b72edc41
--- /dev/null
+++ b/tests/manual/rhi/triquadcube/triquadcube.qrc
@@ -0,0 +1,9 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color.vert.qsb">../shared/color.vert.qsb</file>
+ <file alias="color.frag.qsb">../shared/color.frag.qsb</file>
+ <file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
+ <file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
+ <file alias="qt256.png">../shared/qt256.png</file>
+</qresource>
+</RCC>
diff --git a/tests/manual/shortcuts/main.cpp b/tests/manual/shortcuts/main.cpp
index acc2a2525c..289e8526f0 100644
--- a/tests/manual/shortcuts/main.cpp
+++ b/tests/manual/shortcuts/main.cpp
@@ -108,6 +108,7 @@ void ShortcutTester::setupLayout()
Qt::ControlModifier + Qt::Key_5, Qt::AltModifier + Qt::Key_5,
Qt::ControlModifier + Qt::Key_Plus,
Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_Plus,
+ Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_Equal,
Qt::ControlModifier + Qt::Key_Y, Qt::ShiftModifier + Qt::Key_Comma,
Qt::ControlModifier + Qt::Key_Comma, Qt::ControlModifier + Qt::Key_Slash,
Qt::ControlModifier + Qt::Key_Backslash
@@ -121,6 +122,8 @@ void ShortcutTester::setupLayout()
const int keys3[] = {
Qt::MetaModifier + Qt::ShiftModifier + Qt::Key_A,
+ Qt::MetaModifier + Qt::Key_A,
+ Qt::MetaModifier + Qt::Key_Q,
Qt::MetaModifier + Qt::ShiftModifier + Qt::Key_5,
Qt::ControlModifier + Qt::Key_BracketRight,
Qt::ShiftModifier + Qt::Key_F3,
diff --git a/tests/manual/widgets/itemviews/itemviews.pro b/tests/manual/widgets/itemviews/itemviews.pro
index 53f658d54d..8884cc3aae 100644
--- a/tests/manual/widgets/itemviews/itemviews.pro
+++ b/tests/manual/widgets/itemviews/itemviews.pro
@@ -1,2 +1,8 @@
TEMPLATE = subdirs
-SUBDIRS = delegate qheaderview qtreeview qtreewidget tableview-span-navigation
+SUBDIRS = delegate \
+ qconcatenatetablesproxymodel \
+ qheaderview \
+ qtreeview \
+ qtreewidget \
+ tableview-span-navigation \
+
diff --git a/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/main.cpp b/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/main.cpp
new file mode 100644
index 0000000000..2c1825f29f
--- /dev/null
+++ b/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/main.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QConcatenateTablesProxyModel>
+#include <QStandardItemModel>
+#include <QTableView>
+#include <QTreeView>
+
+static void prepareModel(const QString &prefix, QStandardItemModel *model)
+{
+ for (int row = 0; row < model->rowCount(); ++row) {
+ for (int column = 0; column < model->columnCount(); ++column) {
+ QStandardItem *item = new QStandardItem(prefix + QString(" %1,%2").arg(row).arg(column));
+ item->setDragEnabled(true);
+ item->setDropEnabled(true);
+ model->setItem(row, column, item);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ QStandardItemModel firstModel(4, 4);
+ prepareModel("First", &firstModel);
+ QStandardItemModel secondModel(2, 2);
+
+ QConcatenateTablesProxyModel proxy;
+ proxy.addSourceModel(&firstModel);
+ proxy.addSourceModel(&secondModel);
+
+ prepareModel("Second", &secondModel);
+
+ QTableView tableView;
+ tableView.setWindowTitle("concat proxy, in QTableView");
+ tableView.setDragDropMode(QAbstractItemView::DragDrop);
+ tableView.setModel(&proxy);
+ tableView.show();
+
+ QTreeView treeView;
+ treeView.setWindowTitle("concat proxy, in QTreeView");
+ treeView.setDragDropMode(QAbstractItemView::DragDrop);
+ treeView.setModel(&proxy);
+ treeView.show();
+
+ // For comparison, views on top on QStandardItemModel
+
+ QTableView tableViewTest;
+ tableViewTest.setWindowTitle("first model, in QTableView");
+ tableViewTest.setDragDropMode(QAbstractItemView::DragDrop);
+ tableViewTest.setModel(&firstModel);
+ tableViewTest.show();
+
+ QTreeView treeViewTest;
+ treeViewTest.setWindowTitle("first model, in QTreeView");
+ treeViewTest.setDragDropMode(QAbstractItemView::DragDrop);
+ treeViewTest.setModel(&firstModel);
+ treeViewTest.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro b/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro
new file mode 100644
index 0000000000..19904212a7
--- /dev/null
+++ b/tests/manual/widgets/itemviews/qconcatenatetablesproxymodel/qconcatenatetablesproxymodel.pro
@@ -0,0 +1,8 @@
+
+TEMPLATE = app
+TARGET = qconcatenatetablesproxymodel
+INCLUDEPATH += .
+
+QT += widgets
+
+SOURCES += main.cpp
diff --git a/tests/manual/widgets/widgets/qmainwindow/saveStateSize/main.cpp b/tests/manual/widgets/widgets/qmainwindow/saveStateSize/main.cpp
new file mode 100644
index 0000000000..dbca6df454
--- /dev/null
+++ b/tests/manual/widgets/widgets/qmainwindow/saveStateSize/main.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2019 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the test suite of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and The Qt Company. For licensing terms
+ ** and conditions see https://www.qt.io/terms-conditions. For further
+ ** information use the contact form at https://www.qt.io/contact-us.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3 as published by the Free Software
+ ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+ ** included in the packaging of this file. Please review the following
+ ** information to ensure the GNU General Public License requirements will
+ ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+// Test that the size of the saved state bytearray does not change due to moving a
+// toolbar from one area to another. It should stay the same size as the first time
+// it had that toolbar in it
+
+#include <QApplication>
+#include <QMainWindow>
+#include <QToolBar>
+#include <QPushButton>
+#include <QLabel>
+#include <QVBoxLayout>
+#include <QMessageBox>
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ MainWindow() : QMainWindow()
+ {
+ auto *tb = new QToolBar(this);
+ tb->setObjectName("Toolbar");
+ tb->addAction("Test action");
+ tb->addAction("Test action");
+ addToolBar(Qt::TopToolBarArea, tb);
+ auto *movableTb = new QToolBar(this);
+ movableTb->setObjectName("Movable Toolbar");
+ movableTb->addAction("Test action");
+ movableTb->addAction("Test action");
+ addToolBar(Qt::TopToolBarArea, movableTb);
+ auto *widget = new QWidget;
+ auto *vbox = new QVBoxLayout;
+ auto *label = new QLabel;
+ label->setText("1. Click on check state size to save initial state\n"
+ "2. Drag the movable toolbar in the top dock area to the left area."
+ " Click on check state size to save moved state\n"
+ "3. Drag the movable toolbar from the left dock area to the top area."
+ " Click on check state size to compare the state sizes.\n"
+ "4. Drag the movable toolbar in the top dock area to the left area."
+ " Click on check state size to compare the state sizes.\n"
+ "5. Drag the movable toolbar from the left dock area to the top area."
+ " Click on check state size to compare the state sizes.\n");
+ vbox->addWidget(label);
+ auto *pushButton = new QPushButton("Check state size");
+ connect(pushButton, &QPushButton::clicked, this, &MainWindow::checkState);
+ vbox->addWidget(pushButton);
+ widget->setLayout(vbox);
+ setCentralWidget(widget);
+ }
+public slots:
+ void checkState()
+ {
+ stepCounter++;
+ QString messageText;
+ if (stepCounter == 1) {
+ beforeMoveStateData = saveState();
+ messageText = QLatin1String("Initial state saved");
+ } else if (stepCounter == 2) {
+ afterMoveStateData = saveState();
+ messageText = QLatin1String("Moved state saved");
+ } else {
+ const int currentSaveSize = saveState().size();
+ const int compareValue = (stepCounter == 4) ? afterMoveStateData.size() : beforeMoveStateData.size();
+ messageText = QString::fromLatin1("%1 step %2")
+ .arg((currentSaveSize == compareValue) ? QLatin1String("SUCCESS") : QLatin1String("FAIL"))
+ .arg(stepCounter);
+ }
+ QMessageBox::information(this, "Step done", messageText);
+ }
+private:
+ int stepCounter = 0;
+ QByteArray beforeMoveStateData;
+ QByteArray afterMoveStateData;
+};
+
+#include "main.moc"
+
+int main(int argc, char **argv)
+{
+ QApplication a(argc, argv);
+ MainWindow mw;
+ mw.show();
+ return a.exec();
+}
+
diff --git a/tests/manual/widgets/widgets/qmainwindow/saveStateSize/saveStateSize.pro b/tests/manual/widgets/widgets/qmainwindow/saveStateSize/saveStateSize.pro
new file mode 100644
index 0000000000..6ee128ed3b
--- /dev/null
+++ b/tests/manual/widgets/widgets/qmainwindow/saveStateSize/saveStateSize.pro
@@ -0,0 +1,4 @@
+QT += widgets
+TEMPLATE = app
+TARGET = saveStateSize
+SOURCES += main.cpp
diff --git a/tests/shared/filesystem.h b/tests/shared/filesystem.h
index 73d7d6523c..0e7e6ba867 100644
--- a/tests/shared/filesystem.h
+++ b/tests/shared/filesystem.h
@@ -79,8 +79,8 @@ public:
return file.isNull() ? qint64(-1) : file->write(relativeFileName.toUtf8());
}
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
- static void createNtfsJunction(QString target, QString linkName)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ static DWORD createNtfsJunction(QString target, QString linkName, QString *errorMessage)
{
typedef struct {
DWORD ReparseTag;
@@ -97,14 +97,22 @@ public:
DWORD returnedLength;
wchar_t fileSystem[MAX_PATH] = L"";
PREPARSE_MOUNTPOINT_DATA_BUFFER reparseInfo = (PREPARSE_MOUNTPOINT_DATA_BUFFER) reparseBuffer;
+ DWORD result = ERROR_SUCCESS;
QFileInfo junctionInfo(linkName);
linkName = QDir::toNativeSeparators(junctionInfo.absoluteFilePath());
-
- GetVolumeInformationW( (wchar_t*)linkName.left(3).utf16(), NULL, 0, NULL, NULL, NULL,
- fileSystem, sizeof(fileSystem)/sizeof(WCHAR));
- if(QString().fromWCharArray(fileSystem) != "NTFS")
- QSKIP("This seems not to be an NTFS volume. Junctions are not allowed.");
+ const QString drive = linkName.left(3);
+ if (GetVolumeInformationW(reinterpret_cast<const wchar_t *>(drive.utf16()),
+ NULL, 0, NULL, NULL, NULL,
+ fileSystem, sizeof(fileSystem)/sizeof(WCHAR)) == FALSE) {
+ result = GetLastError();
+ *errorMessage = "GetVolumeInformationW() failed: " + qt_error_string(int(result));
+ return result;
+ }
+ if (QString::fromWCharArray(fileSystem) != "NTFS") {
+ *errorMessage = "This seems not to be an NTFS volume. Junctions are not allowed.";
+ return ERROR_NOT_SUPPORTED;
+ }
if (!target.startsWith("\\??\\") && !target.startsWith("\\\\?\\")) {
QFileInfo targetInfo(target);
@@ -116,7 +124,11 @@ public:
QDir().mkdir(linkName);
hFile = CreateFileW( (wchar_t*)linkName.utf16(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL );
- QVERIFY(hFile != INVALID_HANDLE_VALUE );
+ if (hFile == INVALID_HANDLE_VALUE) {
+ result = GetLastError();
+ *errorMessage = "CreateFileW(" + linkName + ") failed: " + qt_error_string(int(result));
+ return result;
+ }
memset( reparseInfo, 0, sizeof( *reparseInfo ));
reparseInfo->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
@@ -128,8 +140,12 @@ public:
bool ioc = DeviceIoControl(hFile, FSCTL_SET_REPARSE_POINT, reparseInfo,
reparseInfo->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE,
NULL, 0, &returnedLength, NULL);
+ if (!ioc) {
+ result = GetLastError();
+ *errorMessage = "DeviceIoControl() failed: " + qt_error_string(int(result));
+ }
CloseHandle( hFile );
- QVERIFY(ioc);
+ return result;
}
#endif
diff --git a/tests/testserver/apache2/.gitattributes b/tests/testserver/apache2/.gitattributes
new file mode 100644
index 0000000000..67af4c73e8
--- /dev/null
+++ b/tests/testserver/apache2/.gitattributes
@@ -0,0 +1,2 @@
+* text eol=lf
+*.gif -text
diff --git a/tests/testserver/apache2/apache2.sh b/tests/testserver/apache2/apache2.sh
index 4b0c74e2c4..d5075c7096 100755
--- a/tests/testserver/apache2/apache2.sh
+++ b/tests/testserver/apache2/apache2.sh
@@ -73,5 +73,8 @@ touch -d "2007-05-22 12:04:57 GMT" /home/$USER/www/htdocs/fluke.gif
# Create 10MB file for use by tst_Q*::downloadBigFile and interruption tests:
su $USER -c "/bin/dd if=/dev/zero of=~/www/htdocs/mediumfile bs=1 count=0 seek=10000000"
+# Emulate test server's hierarchy:
+su $USER -c "ln -s ~/www/htdocs/rfcs/rfc2616.html ~/www/htdocs/deflate/"
+
# enable service with installed configurations
service apache2 restart
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol-expire.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol-expire.cgi
new file mode 100755
index 0000000000..7dc506fc1e
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol-expire.cgi
@@ -0,0 +1,7 @@
+#!/bin/bash
+# cache control takes precedence over expires
+echo "Cache-Control: max-age=-1"
+echo "Expires: Mon, 30 Oct 2028 14:19:41 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol.cgi
new file mode 100755
index 0000000000..f2edfc161f
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol.cgi
@@ -0,0 +1,13 @@
+#!/bin/bash
+if [ ! -z ${HTTP_IF_MODIFIED_SINCE} ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+cc=`echo "${QUERY_STRING}" | sed -e s/%20/\ /g`
+echo "Cache-Control: $cc"
+echo "Last-Modified: Sat, 31 Oct 1981 06:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol200.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol200.cgi
new file mode 100755
index 0000000000..e44d5ed570
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_cachecontrol200.cgi
@@ -0,0 +1,9 @@
+#!/bin/bash
+cc=`echo "${QUERY_STRING}" | sed -e s/%20/\ /g`
+echo "Status: 200"
+echo "Cache-Control: $cc"
+echo "Last-Modified: Sat, 31 Oct 1981 06:00:00 GMT"
+echo "Content-type: text/html";
+echo "X-Script: $0"
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag200.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag200.cgi
new file mode 100755
index 0000000000..0966abfdd1
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag200.cgi
@@ -0,0 +1,5 @@
+#!/bin/bash
+echo "ETag: foo"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag304.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag304.cgi
new file mode 100755
index 0000000000..91a4b922bd
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_etag304.cgi
@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ ! -z ${HTTP_IF_NONE_MATCH} ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+echo "ETag: foo"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires200.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires200.cgi
new file mode 100755
index 0000000000..e18ebc86ad
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires200.cgi
@@ -0,0 +1,5 @@
+#!/bin/bash
+echo "Expires: Sat, 31 Oct 1981 6:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires304.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires304.cgi
new file mode 100755
index 0000000000..1c7de1cd77
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires304.cgi
@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ ${HTTP_IF_MODIFIED_SINCE} == "Mon, 30 Oct 2028 14:19:41 GMT" ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+echo "Expires: Mon, 30 Oct 2028 14:19:41 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified200.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified200.cgi
new file mode 100755
index 0000000000..5dc219b1e7
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified200.cgi
@@ -0,0 +1,5 @@
+#!/bin/bash
+echo "Last-Modified: Sat, 31 Oct 1981 6:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified304.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified304.cgi
new file mode 100755
index 0000000000..bdf23bed2f
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_lastModified304.cgi
@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ ${HTTP_IF_MODIFIED_SINCE} == "Sat, 31 Oct 1981 06:00:00 GMT" ] ; then
+ echo "Status: 304"
+ echo ""
+ exit;
+fi
+
+echo "Last-Modified: Sat, 31 Oct 1981 06:00:00 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/htdocs/rfcs/.gitattributes b/tests/testserver/apache2/testdata/www/htdocs/rfcs/.gitattributes
new file mode 100644
index 0000000000..1d09ee726e
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/rfcs/.gitattributes
@@ -0,0 +1 @@
+rfc2616.html binary
diff --git a/tests/testserver/apache2/testdata/www/htdocs/rfcs/rfc2616.html b/tests/testserver/apache2/testdata/www/htdocs/rfcs/rfc2616.html
new file mode 100644
index 0000000000..0e3282fb8d
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/rfcs/rfc2616.html
@@ -0,0 +1,8380 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html><head><title>RFC 2616 (rfc2616) - Hypertext Transfer Protocol -- HTTP/1.1</title>
+
+
+
+<meta name="description" content="RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1">
+<meta name="obsoletes" content="RFC2068">
+<script language="JavaScript1.2">
+function erfc(s)
+{document.write("<A href=\"/rfccomment.php?rfcnum="+s+"\" target=\"_blank\" onclick=\"window.open('/rfccomment.php?rfcnum="+s+"','Popup','toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=680,height=530,left=30,top=43'); return false;\")>Comment on RFC "+s+"</A>\n");}
+//-->
+</script></head><body bgcolor="#ffffff" text="#000000">
+<p align="center"><img src="rfc2616_files/library.htm" alt="" align="middle" border="0" height="62" width="150"></p>
+<h1 align="center">RFC 2616 (RFC2616)</h1>
+<p align="center">Internet RFC/STD/FYI/BCP Archives</p>
+
+<div align="center">[ <a href="http://firefly.troll.no/rfcs/">RFC Index</a> | <a href="http://firefly.troll.no/rfcs/rfcsearch.html">RFC Search</a> | <a href="http://firefly.troll.no/faqs/">Usenet FAQs</a> | <a href="http://firefly.troll.no/contrib/">Web FAQs</a> | <a href="http://firefly.troll.no/docs/">Documents</a> | <a href="http://www.city-data.com/">Cities</a> ]
+<p>
+<strong>Alternate Formats:</strong>
+ <a href="http://firefly.troll.no/ftp/rfc/rfc2616.txt">rfc2616.txt</a> |
+ <a href="http://firefly.troll.no/ftp/rfc/rfc2616.ps">rfc2616.ps</a> |
+ <a href="http://firefly.troll.no/ftp/rfc/rfc2616.pdf">rfc2616.pdf</a></p></div>
+<p align="center"><script language="JavaScript"><!--
+erfc("2616");
+// --></script><a href="http://firefly.troll.no/rfccomment.php?rfcnum=2616" target="_blank" onclick="window.open('/rfccomment.php?rfcnum=2616','Popup','toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=680,height=530,left=30,top=43'); return false;" )="">Comment on RFC 2616</a>
+</p>
+<h3 align="center">RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1</h3>
+<hr noshade="noshade" size="2">
+<pre>
+Network Working Group R. Fielding
+Request for Comments: 2616 UC Irvine
+Obsoletes: 2068 J. Gettys
+Category: Standards Track Compaq/W3C
+ J. Mogul
+ Compaq
+ H. Frystyk
+ W3C/MIT
+ L. Masinter
+ Xerox
+ P. Leach
+ Microsoft
+ T. Berners-Lee
+ W3C/MIT
+ June 1999
+
+ Hypertext Transfer Protocol -- HTTP/1.1
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ The Hypertext Transfer Protocol (HTTP) is an application-level
+ protocol for distributed, collaborative, hypermedia information
+ systems. It is a generic, stateless, protocol which can be used for
+ many tasks beyond its use for hypertext, such as name servers and
+ distributed object management systems, through extension of its
+ request methods, error codes and headers [47]. A feature of HTTP is
+ the typing and negotiation of data representation, allowing systems
+ to be built independently of the data being transferred.
+
+ HTTP has been in use by the World-Wide Web global information
+ initiative since 1990. This specification defines the protocol
+ referred to as "HTTP/1.1", and is an update to <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> [33].
+
+Table of Contents
+
+ 1 Introduction ...................................................7
+ 1.1 Purpose......................................................7
+ 1.2 Requirements .................................................8
+ 1.3 Terminology ..................................................8
+ 1.4 Overall Operation ...........................................12
+ 2 Notational Conventions and Generic Grammar ....................14
+ 2.1 Augmented BNF ...............................................14
+ 2.2 Basic Rules .................................................15
+ 3 Protocol Parameters ...........................................17
+ 3.1 HTTP Version ................................................17
+ 3.2 Uniform Resource Identifiers ................................18
+ 3.2.1 General Syntax ...........................................19
+ 3.2.2 http URL .................................................19
+ 3.2.3 URI Comparison ...........................................20
+ 3.3 Date/Time Formats ...........................................20
+ 3.3.1 Full Date ................................................20
+ 3.3.2 Delta Seconds ............................................21
+ 3.4 Character Sets ..............................................21
+ 3.4.1 Missing Charset ..........................................22
+ 3.5 Content Codings .............................................23
+ 3.6 Transfer Codings ............................................24
+ 3.6.1 Chunked Transfer Coding ..................................25
+ 3.7 Media Types .................................................26
+ 3.7.1 Canonicalization and Text Defaults .......................27
+ 3.7.2 Multipart Types ..........................................27
+ 3.8 Product Tokens ..............................................28
+ 3.9 Quality Values ..............................................29
+ 3.10 Language Tags ...............................................29
+ 3.11 Entity Tags .................................................30
+ 3.12 Range Units .................................................30
+ 4 HTTP Message ..................................................31
+ 4.1 Message Types ...............................................31
+ 4.2 Message Headers .............................................31
+ 4.3 Message Body ................................................32
+ 4.4 Message Length ..............................................33
+ 4.5 General Header Fields .......................................34
+ 5 Request .......................................................35
+ 5.1 Request-Line ................................................35
+ 5.1.1 Method ...................................................36
+ 5.1.2 Request-URI ..............................................36
+ 5.2 The Resource Identified by a Request ........................38
+ 5.3 Request Header Fields .......................................38
+ 6 Response ......................................................39
+ 6.1 Status-Line .................................................39
+ 6.1.1 Status Code and Reason Phrase ............................39
+ 6.2 Response Header Fields ......................................41
+
+ 7 Entity ........................................................42
+ 7.1 Entity Header Fields ........................................42
+ 7.2 Entity Body .................................................43
+ 7.2.1 Type .....................................................43
+ 7.2.2 Entity Length ............................................43
+ 8 Connections ...................................................44
+ 8.1 Persistent Connections ......................................44
+ 8.1.1 Purpose ..................................................44
+ 8.1.2 Overall Operation ........................................45
+ 8.1.3 Proxy Servers ............................................46
+ 8.1.4 Practical Considerations .................................46
+ 8.2 Message Transmission Requirements ...........................47
+ 8.2.1 Persistent Connections and Flow Control ..................47
+ 8.2.2 Monitoring Connections for Error Status Messages .........48
+ 8.2.3 Use of the 100 (Continue) Status .........................48
+ 8.2.4 Client Behavior if Server Prematurely Closes Connection ..50
+ 9 Method Definitions ............................................51
+ 9.1 Safe and Idempotent Methods .................................51
+ 9.1.1 Safe Methods .............................................51
+ 9.1.2 Idempotent Methods .......................................51
+ 9.2 OPTIONS .....................................................52
+ 9.3 GET .........................................................53
+ 9.4 HEAD ........................................................54
+ 9.5 POST ........................................................54
+ 9.6 PUT .........................................................55
+ 9.7 DELETE ......................................................56
+ 9.8 TRACE .......................................................56
+ 9.9 CONNECT .....................................................57
+ 10 Status Code Definitions ......................................57
+ 10.1 Informational 1xx ...........................................57
+ 10.1.1 100 Continue .............................................58
+ 10.1.2 101 Switching Protocols ..................................58
+ 10.2 Successful 2xx ..............................................58
+ 10.2.1 200 OK ...................................................58
+ 10.2.2 201 Created ..............................................59
+ 10.2.3 202 Accepted .............................................59
+ 10.2.4 203 Non-Authoritative Information ........................59
+ 10.2.5 204 No Content ...........................................60
+ 10.2.6 205 Reset Content ........................................60
+ 10.2.7 206 Partial Content ......................................60
+ 10.3 Redirection 3xx .............................................61
+ 10.3.1 300 Multiple Choices .....................................61
+ 10.3.2 301 Moved Permanently ....................................62
+ 10.3.3 302 Found ................................................62
+ 10.3.4 303 See Other ............................................63
+ 10.3.5 304 Not Modified .........................................63
+ 10.3.6 305 Use Proxy ............................................64
+ 10.3.7 306 (Unused) .............................................64
+
+ 10.3.8 307 Temporary Redirect ...................................65
+ 10.4 Client Error 4xx ............................................65
+ 10.4.1 400 Bad Request .........................................65
+ 10.4.2 401 Unauthorized ........................................66
+ 10.4.3 402 Payment Required ....................................66
+ 10.4.4 403 Forbidden ...........................................66
+ 10.4.5 404 Not Found ...........................................66
+ 10.4.6 405 Method Not Allowed ..................................66
+ 10.4.7 406 Not Acceptable ......................................67
+ 10.4.8 407 Proxy Authentication Required .......................67
+ 10.4.9 408 Request Timeout .....................................67
+ 10.4.10 409 Conflict ............................................67
+ 10.4.11 410 Gone ................................................68
+ 10.4.12 411 Length Required .....................................68
+ 10.4.13 412 Precondition Failed .................................68
+ 10.4.14 413 Request Entity Too Large ............................69
+ 10.4.15 414 Request-URI Too Long ................................69
+ 10.4.16 415 Unsupported Media Type ..............................69
+ 10.4.17 416 Requested Range Not Satisfiable .....................69
+ 10.4.18 417 Expectation Failed ..................................70
+ 10.5 Server Error 5xx ............................................70
+ 10.5.1 500 Internal Server Error ................................70
+ 10.5.2 501 Not Implemented ......................................70
+ 10.5.3 502 Bad Gateway ..........................................70
+ 10.5.4 503 Service Unavailable ..................................70
+ 10.5.5 504 Gateway Timeout ......................................71
+ 10.5.6 505 HTTP Version Not Supported ...........................71
+ 11 Access Authentication ........................................71
+ 12 Content Negotiation ..........................................71
+ 12.1 Server-driven Negotiation ...................................72
+ 12.2 Agent-driven Negotiation ....................................73
+ 12.3 Transparent Negotiation .....................................74
+ 13 Caching in HTTP ..............................................74
+ 13.1.1 Cache Correctness ........................................75
+ 13.1.2 Warnings .................................................76
+ 13.1.3 Cache-control Mechanisms .................................77
+ 13.1.4 Explicit User Agent Warnings .............................78
+ 13.1.5 Exceptions to the Rules and Warnings .....................78
+ 13.1.6 Client-controlled Behavior ...............................79
+ 13.2 Expiration Model ............................................79
+ 13.2.1 Server-Specified Expiration ..............................79
+ 13.2.2 Heuristic Expiration .....................................80
+ 13.2.3 Age Calculations .........................................80
+ 13.2.4 Expiration Calculations ..................................83
+ 13.2.5 Disambiguating Expiration Values .........................84
+ 13.2.6 Disambiguating Multiple Responses ........................84
+ 13.3 Validation Model ............................................85
+ 13.3.1 Last-Modified Dates ......................................86
+
+ 13.3.2 Entity Tag Cache Validators ..............................86
+ 13.3.3 Weak and Strong Validators ...............................86
+ 13.3.4 Rules for When to Use Entity Tags and Last-Modified Dates.89
+ 13.3.5 Non-validating Conditionals ..............................90
+ 13.4 Response Cacheability .......................................91
+ 13.5 Constructing Responses From Caches ..........................92
+ 13.5.1 End-to-end and Hop-by-hop Headers ........................92
+ 13.5.2 Non-modifiable Headers ...................................92
+ 13.5.3 Combining Headers ........................................94
+ 13.5.4 Combining Byte Ranges ....................................95
+ 13.6 Caching Negotiated Responses ................................95
+ 13.7 Shared and Non-Shared Caches ................................96
+ 13.8 Errors or Incomplete Response Cache Behavior ................97
+ 13.9 Side Effects of GET and HEAD ................................97
+ 13.10 Invalidation After Updates or Deletions ...................97
+ 13.11 Write-Through Mandatory ...................................98
+ 13.12 Cache Replacement .........................................99
+ 13.13 History Lists .............................................99
+ 14 Header Field Definitions ....................................100
+ 14.1 Accept .....................................................100
+ 14.2 Accept-Charset .............................................102
+ 14.3 Accept-Encoding ............................................102
+ 14.4 Accept-Language ............................................104
+ 14.5 Accept-Ranges ..............................................105
+ 14.6 Age ........................................................106
+ 14.7 Allow ......................................................106
+ 14.8 Authorization ..............................................107
+ 14.9 Cache-Control ..............................................108
+ 14.9.1 What is Cacheable .......................................109
+ 14.9.2 What May be Stored by Caches ............................110
+ 14.9.3 Modifications of the Basic Expiration Mechanism .........111
+ 14.9.4 Cache Revalidation and Reload Controls ..................113
+ 14.9.5 No-Transform Directive ..................................115
+ 14.9.6 Cache Control Extensions ................................116
+ 14.10 Connection ...............................................117
+ 14.11 Content-Encoding .........................................118
+ 14.12 Content-Language .........................................118
+ 14.13 Content-Length ...........................................119
+ 14.14 Content-Location .........................................120
+ 14.15 Content-MD5 ..............................................121
+ 14.16 Content-Range ............................................122
+ 14.17 Content-Type .............................................124
+ 14.18 Date .....................................................124
+ 14.18.1 Clockless Origin Server Operation ......................125
+ 14.19 ETag .....................................................126
+ 14.20 Expect ...................................................126
+ 14.21 Expires ..................................................127
+ 14.22 From .....................................................128
+
+ 14.23 Host .....................................................128
+ 14.24 If-Match .................................................129
+ 14.25 If-Modified-Since ........................................130
+ 14.26 If-None-Match ............................................132
+ 14.27 If-Range .................................................133
+ 14.28 If-Unmodified-Since ......................................134
+ 14.29 Last-Modified ............................................134
+ 14.30 Location .................................................135
+ 14.31 Max-Forwards .............................................136
+ 14.32 Pragma ...................................................136
+ 14.33 Proxy-Authenticate .......................................137
+ 14.34 Proxy-Authorization ......................................137
+ 14.35 Range ....................................................138
+ 14.35.1 Byte Ranges ...........................................138
+ 14.35.2 Range Retrieval Requests ..............................139
+ 14.36 Referer ..................................................140
+ 14.37 Retry-After ..............................................141
+ 14.38 Server ...................................................141
+ 14.39 TE .......................................................142
+ 14.40 Trailer ..................................................143
+ 14.41 Transfer-Encoding..........................................143
+ 14.42 Upgrade ..................................................144
+ 14.43 User-Agent ...............................................145
+ 14.44 Vary .....................................................145
+ 14.45 Via ......................................................146
+ 14.46 Warning ..................................................148
+ 14.47 WWW-Authenticate .........................................150
+ 15 Security Considerations .......................................150
+ 15.1 Personal Information....................................151
+ 15.1.1 Abuse of Server Log Information .........................151
+ 15.1.2 Transfer of Sensitive Information .......................151
+ 15.1.3 Encoding Sensitive Information in URI's .................152
+ 15.1.4 Privacy Issues Connected to Accept Headers ..............152
+ 15.2 Attacks Based On File and Path Names .......................153
+ 15.3 DNS Spoofing ...............................................154
+ 15.4 Location Headers and Spoofing ..............................154
+ 15.5 Content-Disposition Issues .................................154
+ 15.6 Authentication Credentials and Idle Clients ................155
+ 15.7 Proxies and Caching ........................................155
+ 15.7.1 Denial of Service Attacks on Proxies....................156
+ 16 Acknowledgments .............................................156
+ 17 References ..................................................158
+ 18 Authors' Addresses ..........................................162
+ 19 Appendices ..................................................164
+ 19.1 Internet Media Type message/http and application/http ......164
+ 19.2 Internet Media Type multipart/byteranges ...................165
+ 19.3 Tolerant Applications ......................................166
+ 19.4 Differences Between HTTP Entities and <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a> Entities ....167
+
+ 19.4.1 MIME-Version ............................................167
+ 19.4.2 Conversion to Canonical Form ............................167
+ 19.4.3 Conversion of Date Formats ..............................168
+ 19.4.4 Introduction of Content-Encoding ........................168
+ 19.4.5 No Content-Transfer-Encoding ............................168
+ 19.4.6 Introduction of Transfer-Encoding .......................169
+ 19.4.7 MHTML and Line Length Limitations .......................169
+ 19.5 Additional Features ........................................169
+ 19.5.1 Content-Disposition .....................................170
+ 19.6 Compatibility with Previous Versions .......................170
+ 19.6.1 Changes from HTTP/1.0 ...................................171
+ 19.6.2 Compatibility with HTTP/1.0 Persistent Connections ......172
+ 19.6.3 Changes from <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> ...................................172
+ 20 Index .......................................................175
+ 21 Full Copyright Statement ....................................176
+
+1 Introduction
+
+1.1 Purpose
+
+ The Hypertext Transfer Protocol (HTTP) is an application-level
+ protocol for distributed, collaborative, hypermedia information
+ systems. HTTP has been in use by the World-Wide Web global
+ information initiative since 1990. The first version of HTTP,
+ referred to as HTTP/0.9, was a simple protocol for raw data transfer
+ across the Internet. HTTP/1.0, as defined by <a href="http://firefly.troll.no/rfcs/rfc1945.html">RFC 1945</a> [6], improved
+ the protocol by allowing messages to be in the format of MIME-like
+ messages, containing metainformation about the data transferred and
+ modifiers on the request/response semantics. However, HTTP/1.0 does
+ not sufficiently take into consideration the effects of hierarchical
+ proxies, caching, the need for persistent connections, or virtual
+ hosts. In addition, the proliferation of incompletely-implemented
+ applications calling themselves "HTTP/1.0" has necessitated a
+ protocol version change in order for two communicating applications
+ to determine each other's true capabilities.
+
+ This specification defines the protocol referred to as "HTTP/1.1".
+ This protocol includes more stringent requirements than HTTP/1.0 in
+ order to ensure reliable implementation of its features.
+
+ Practical information systems require more functionality than simple
+ retrieval, including search, front-end update, and annotation. HTTP
+ allows an open-ended set of methods and headers that indicate the
+ purpose of a request [47]. It builds on the discipline of reference
+ provided by the Uniform Resource Identifier (URI) [3], as a location
+ (URL) [4] or name (URN) [20], for indicating the resource to which a
+
+ method is to be applied. Messages are passed in a format similar to
+ that used by Internet mail [9] as defined by the Multipurpose
+ Internet Mail Extensions (MIME) [7].
+
+ HTTP is also used as a generic protocol for communication between
+ user agents and proxies/gateways to other Internet systems, including
+ those supported by the SMTP [16], NNTP [13], FTP [18], Gopher [2],
+ and WAIS [10] protocols. In this way, HTTP allows basic hypermedia
+ access to resources available from diverse applications.
+
+1.2 Requirements
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in <a href="http://firefly.troll.no/rfcs/rfc2119.html">RFC 2119</a> [34].
+
+ An implementation is not compliant if it fails to satisfy one or more
+ of the MUST or REQUIRED level requirements for the protocols it
+ implements. An implementation that satisfies all the MUST or REQUIRED
+ level and all the SHOULD level requirements for its protocols is said
+ to be "unconditionally compliant"; one that satisfies all the MUST
+ level requirements but not all the SHOULD level requirements for its
+ protocols is said to be "conditionally compliant."
+
+1.3 Terminology
+
+ This specification uses a number of terms to refer to the roles
+ played by participants in, and objects of, the HTTP communication.
+
+ connection
+ A transport layer virtual circuit established between two programs
+ for the purpose of communication.
+
+ message
+ The basic unit of HTTP communication, consisting of a structured
+ sequence of octets matching the syntax defined in section 4 and
+ transmitted via the connection.
+
+ request
+ An HTTP request message, as defined in section 5.
+
+ response
+ An HTTP response message, as defined in section 6.
+
+ resource
+ A network data object or service that can be identified by a URI,
+ as defined in section 3.2. Resources may be available in multiple
+ representations (e.g. multiple languages, data formats, size, and
+ resolutions) or vary in other ways.
+
+ entity
+ The information transferred as the payload of a request or
+ response. An entity consists of metainformation in the form of
+ entity-header fields and content in the form of an entity-body, as
+ described in section 7.
+
+ representation
+ An entity included with a response that is subject to content
+ negotiation, as described in section 12. There may exist multiple
+ representations associated with a particular response status.
+
+ content negotiation
+ The mechanism for selecting the appropriate representation when
+ servicing a request, as described in section 12. The
+ representation of entities in any response can be negotiated
+ (including error responses).
+
+ variant
+ A resource may have one, or more than one, representation(s)
+ associated with it at any given instant. Each of these
+ representations is termed a `varriant'. Use of the term `variant'
+ does not necessarily imply that the resource is subject to content
+ negotiation.
+
+ client
+ A program that establishes connections for the purpose of sending
+ requests.
+
+ user agent
+ The client which initiates a request. These are often browsers,
+ editors, spiders (web-traversing robots), or other end user tools.
+
+ server
+ An application program that accepts connections in order to
+ service requests by sending back responses. Any given program may
+ be capable of being both a client and a server; our use of these
+ terms refers only to the role being performed by the program for a
+ particular connection, rather than to the program's capabilities
+ in general. Likewise, any server may act as an origin server,
+ proxy, gateway, or tunnel, switching behavior based on the nature
+ of each request.
+
+ origin server
+ The server on which a given resource resides or is to be created.
+
+ proxy
+ An intermediary program which acts as both a server and a client
+ for the purpose of making requests on behalf of other clients.
+ Requests are serviced internally or by passing them on, with
+ possible translation, to other servers. A proxy MUST implement
+ both the client and server requirements of this specification. A
+ "transparent proxy" is a proxy that does not modify the request or
+ response beyond what is required for proxy authentication and
+ identification. A "non-transparent proxy" is a proxy that modifies
+ the request or response in order to provide some added service to
+ the user agent, such as group annotation services, media type
+ transformation, protocol reduction, or anonymity filtering. Except
+ where either transparent or non-transparent behavior is explicitly
+ stated, the HTTP proxy requirements apply to both types of
+ proxies.
+
+ gateway
+ A server which acts as an intermediary for some other server.
+ Unlike a proxy, a gateway receives requests as if it were the
+ origin server for the requested resource; the requesting client
+ may not be aware that it is communicating with a gateway.
+
+ tunnel
+ An intermediary program which is acting as a blind relay between
+ two connections. Once active, a tunnel is not considered a party
+ to the HTTP communication, though the tunnel may have been
+ initiated by an HTTP request. The tunnel ceases to exist when both
+ ends of the relayed connections are closed.
+
+ cache
+ A program's local store of response messages and the subsystem
+ that controls its message storage, retrieval, and deletion. A
+ cache stores cacheable responses in order to reduce the response
+ time and network bandwidth consumption on future, equivalent
+ requests. Any client or server may include a cache, though a cache
+ cannot be used by a server that is acting as a tunnel.
+
+ cacheable
+ A response is cacheable if a cache is allowed to store a copy of
+ the response message for use in answering subsequent requests. The
+ rules for determining the cacheability of HTTP responses are
+ defined in section 13. Even if a resource is cacheable, there may
+ be additional constraints on whether a cache can use the cached
+ copy for a particular request.
+
+ first-hand
+ A response is first-hand if it comes directly and without
+ unnecessary delay from the origin server, perhaps via one or more
+ proxies. A response is also first-hand if its validity has just
+ been checked directly with the origin server.
+
+ explicit expiration time
+ The time at which the origin server intends that an entity should
+ no longer be returned by a cache without further validation.
+
+ heuristic expiration time
+ An expiration time assigned by a cache when no explicit expiration
+ time is available.
+
+ age
+ The age of a response is the time since it was sent by, or
+ successfully validated with, the origin server.
+
+ freshness lifetime
+ The length of time between the generation of a response and its
+ expiration time.
+
+ fresh
+ A response is fresh if its age has not yet exceeded its freshness
+ lifetime.
+
+ stale
+ A response is stale if its age has passed its freshness lifetime.
+
+ semantically transparent
+ A cache behaves in a "semantically transparent" manner, with
+ respect to a particular response, when its use affects neither the
+ requesting client nor the origin server, except to improve
+ performance. When a cache is semantically transparent, the client
+ receives exactly the same response (except for hop-by-hop headers)
+ that it would have received had its request been handled directly
+ by the origin server.
+
+ validator
+ A protocol element (e.g., an entity tag or a Last-Modified time)
+ that is used to find out whether a cache entry is an equivalent
+ copy of an entity.
+
+ upstream/downstream
+ Upstream and downstream describe the flow of a message: all
+ messages flow from upstream to downstream.
+
+ inbound/outbound
+ Inbound and outbound refer to the request and response paths for
+ messages: "inbound" means "traveling toward the origin server",
+ and "outbound" means "traveling toward the user agent"
+
+1.4 Overall Operation
+
+ The HTTP protocol is a request/response protocol. A client sends a
+ request to the server in the form of a request method, URI, and
+ protocol version, followed by a MIME-like message containing request
+ modifiers, client information, and possible body content over a
+ connection with a server. The server responds with a status line,
+ including the message's protocol version and a success or error code,
+ followed by a MIME-like message containing server information, entity
+ metainformation, and possible entity-body content. The relationship
+ between HTTP and MIME is described in appendix 19.4.
+
+ Most HTTP communication is initiated by a user agent and consists of
+ a request to be applied to a resource on some origin server. In the
+ simplest case, this may be accomplished via a single connection (v)
+ between the user agent (UA) and the origin server (O).
+
+ request chain ------------------------&gt;
+ UA -------------------v------------------- O
+ &lt;----------------------- response chain
+
+ A more complicated situation occurs when one or more intermediaries
+ are present in the request/response chain. There are three common
+ forms of intermediary: proxy, gateway, and tunnel. A proxy is a
+ forwarding agent, receiving requests for a URI in its absolute form,
+ rewriting all or part of the message, and forwarding the reformatted
+ request toward the server identified by the URI. A gateway is a
+ receiving agent, acting as a layer above some other server(s) and, if
+ necessary, translating the requests to the underlying server's
+ protocol. A tunnel acts as a relay point between two connections
+ without changing the messages; tunnels are used when the
+ communication needs to pass through an intermediary (such as a
+ firewall) even when the intermediary cannot understand the contents
+ of the messages.
+
+ request chain --------------------------------------&gt;
+ UA -----v----- A -----v----- B -----v----- C -----v----- O
+ &lt;------------------------------------- response chain
+
+ The figure above shows three intermediaries (A, B, and C) between the
+ user agent and origin server. A request or response message that
+ travels the whole chain will pass through four separate connections.
+ This distinction is important because some HTTP communication options
+
+ may apply only to the connection with the nearest, non-tunnel
+ neighbor, only to the end-points of the chain, or to all connections
+ along the chain. Although the diagram is linear, each participant may
+ be engaged in multiple, simultaneous communications. For example, B
+ may be receiving requests from many clients other than A, and/or
+ forwarding requests to servers other than C, at the same time that it
+ is handling A's request.
+
+ Any party to the communication which is not acting as a tunnel may
+ employ an internal cache for handling requests. The effect of a cache
+ is that the request/response chain is shortened if one of the
+ participants along the chain has a cached response applicable to that
+ request. The following illustrates the resulting chain if B has a
+ cached copy of an earlier response from O (via C) for a request which
+ has not been cached by UA or A.
+
+ request chain ----------&gt;
+ UA -----v----- A -----v----- B - - - - - - C - - - - - - O
+ &lt;--------- response chain
+
+ Not all responses are usefully cacheable, and some requests may
+ contain modifiers which place special requirements on cache behavior.
+ HTTP requirements for cache behavior and cacheable responses are
+ defined in section 13.
+
+ In fact, there are a wide variety of architectures and configurations
+ of caches and proxies currently being experimented with or deployed
+ across the World Wide Web. These systems include national hierarchies
+ of proxy caches to save transoceanic bandwidth, systems that
+ broadcast or multicast cache entries, organizations that distribute
+ subsets of cached data via CD-ROM, and so on. HTTP systems are used
+ in corporate intranets over high-bandwidth links, and for access via
+ PDAs with low-power radio links and intermittent connectivity. The
+ goal of HTTP/1.1 is to support the wide diversity of configurations
+ already deployed while introducing protocol constructs that meet the
+ needs of those who build web applications that require high
+ reliability and, failing that, at least reliable indications of
+ failure.
+
+ HTTP communication usually takes place over TCP/IP connections. The
+ default port is TCP 80 [19], but other ports can be used. This does
+ not preclude HTTP from being implemented on top of any other protocol
+ on the Internet, or on other networks. HTTP only presumes a reliable
+ transport; any protocol that provides such guarantees can be used;
+ the mapping of the HTTP/1.1 request and response structures onto the
+ transport data units of the protocol in question is outside the scope
+ of this specification.
+
+ In HTTP/1.0, most implementations used a new connection for each
+ request/response exchange. In HTTP/1.1, a connection may be used for
+ one or more request/response exchanges, although connections may be
+ closed for a variety of reasons (see section 8.1).
+
+2 Notational Conventions and Generic Grammar
+
+2.1 Augmented BNF
+
+ All of the mechanisms specified in this document are described in
+ both prose and an augmented Backus-Naur Form (BNF) similar to that
+ used by <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9]. Implementors will need to be familiar with the
+ notation in order to understand this specification. The augmented BNF
+ includes the following constructs:
+
+ name = definition
+ The name of a rule is simply the name itself (without any
+ enclosing "&lt;" and "&gt;") and is separated from its definition by the
+ equal "=" character. White space is only significant in that
+ indentation of continuation lines is used to indicate a rule
+ definition that spans more than one line. Certain basic rules are
+ in uppercase, such as SP, LWS, HT, CRLF, DIGIT, ALPHA, etc. Angle
+ brackets are used within definitions whenever their presence will
+ facilitate discerning the use of rule names.
+
+ "literal"
+ Quotation marks surround literal text. Unless stated otherwise,
+ the text is case-insensitive.
+
+ rule1 | rule2
+ Elements separated by a bar ("|") are alternatives, e.g., "yes |
+ no" will accept yes or no.
+
+ (rule1 rule2)
+ Elements enclosed in parentheses are treated as a single element.
+ Thus, "(elem (foo | bar) elem)" allows the token sequences "elem
+ foo elem" and "elem bar elem".
+
+ *rule
+ The character "*" preceding an element indicates repetition. The
+ full form is "&lt;n&gt;*&lt;m&gt;element" indicating at least &lt;n&gt; and at most
+ &lt;m&gt; occurrences of element. Default values are 0 and infinity so
+ that "*(element)" allows any number, including zero; "1*element"
+ requires at least one; and "1*2element" allows one or two.
+
+ [rule]
+ Square brackets enclose optional elements; "[foo bar]" is
+ equivalent to "*1(foo bar)".
+
+ N rule
+ Specific repetition: "&lt;n&gt;(element)" is equivalent to
+ "&lt;n&gt;*&lt;n&gt;(element)"; that is, exactly &lt;n&gt; occurrences of (element).
+ Thus 2DIGIT is a 2-digit number, and 3ALPHA is a string of three
+ alphabetic characters.
+
+ #rule
+ A construct "#" is defined, similar to "*", for defining lists of
+ elements. The full form is "&lt;n&gt;#&lt;m&gt;element" indicating at least
+ &lt;n&gt; and at most &lt;m&gt; elements, each separated by one or more commas
+ (",") and OPTIONAL linear white space (LWS). This makes the usual
+ form of lists very easy; a rule such as
+ ( *LWS element *( *LWS "," *LWS element ))
+ can be shown as
+ 1#element
+ Wherever this construct is used, null elements are allowed, but do
+ not contribute to the count of elements present. That is,
+ "(element), , (element) " is permitted, but counts as only two
+ elements. Therefore, where at least one element is required, at
+ least one non-null element MUST be present. Default values are 0
+ and infinity so that "#element" allows any number, including zero;
+ "1#element" requires at least one; and "1#2element" allows one or
+ two.
+
+ ; comment
+ A semi-colon, set off some distance to the right of rule text,
+ starts a comment that continues to the end of line. This is a
+ simple way of including useful notes in parallel with the
+ specifications.
+
+ implied *LWS
+ The grammar described by this specification is word-based. Except
+ where noted otherwise, linear white space (LWS) can be included
+ between any two adjacent words (token or quoted-string), and
+ between adjacent words and separators, without changing the
+ interpretation of a field. At least one delimiter (LWS and/or
+
+ separators) MUST exist between any two tokens (for the definition
+ of "token" below), since they would otherwise be interpreted as a
+ single token.
+
+2.2 Basic Rules
+
+ The following rules are used throughout this specification to
+ describe basic parsing constructs. The US-ASCII coded character set
+ is defined by ANSI X3.4-1986 [21].
+
+ OCTET = &lt;any 8-bit sequence of data&gt;
+ CHAR = &lt;any US-ASCII character (octets 0 - 127)&gt;
+ UPALPHA = &lt;any US-ASCII uppercase letter "A".."Z"&gt;
+ LOALPHA = &lt;any US-ASCII lowercase letter "a".."z"&gt;
+ ALPHA = UPALPHA | LOALPHA
+ DIGIT = &lt;any US-ASCII digit "0".."9"&gt;
+ CTL = &lt;any US-ASCII control character
+ (octets 0 - 31) and DEL (127)&gt;
+ CR = &lt;US-ASCII CR, carriage return (13)&gt;
+ LF = &lt;US-ASCII LF, linefeed (10)&gt;
+ SP = &lt;US-ASCII SP, space (32)&gt;
+ HT = &lt;US-ASCII HT, horizontal-tab (9)&gt;
+ &lt;"&gt; = &lt;US-ASCII double-quote mark (34)&gt;
+
+ HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
+ protocol elements except the entity-body (see appendix 19.3 for
+ tolerant applications). The end-of-line marker within an entity-body
+ is defined by its associated media type, as described in section 3.7.
+
+ CRLF = CR LF
+
+ HTTP/1.1 header field values can be folded onto multiple lines if the
+ continuation line begins with a space or horizontal tab. All linear
+ white space, including folding, has the same semantics as SP. A
+ recipient MAY replace any linear white space with a single SP before
+ interpreting the field value or forwarding the message downstream.
+
+ LWS = [CRLF] 1*( SP | HT )
+
+ The TEXT rule is only used for descriptive field contents and values
+ that are not intended to be interpreted by the message parser. Words
+ of *TEXT MAY contain characters from character sets other than ISO-
+ 8859-1 [22] only when encoded according to the rules of <a href="http://firefly.troll.no/rfcs/rfc2047.html">RFC 2047</a>
+ [14].
+
+ TEXT = &lt;any OCTET except CTLs,
+ but including LWS&gt;
+
+ A CRLF is allowed in the definition of TEXT only as part of a header
+ field continuation. It is expected that the folding LWS will be
+ replaced with a single SP before interpretation of the TEXT value.
+
+ Hexadecimal numeric characters are used in several protocol elements.
+
+ HEX = "A" | "B" | "C" | "D" | "E" | "F"
+ | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT
+
+ Many HTTP/1.1 header field values consist of words separated by LWS
+ or special characters. These special characters MUST be in a quoted
+ string to be used within a parameter value (as defined in section
+ 3.6).
+
+ token = 1*&lt;any CHAR except CTLs or separators&gt;
+ separators = "(" | ")" | "&lt;" | "&gt;" | "@"
+ | "," | ";" | ":" | "\" | &lt;"&gt;
+ | "/" | "[" | "]" | "?" | "="
+ | "{" | "}" | SP | HT
+
+ Comments can be included in some HTTP header fields by surrounding
+ the comment text with parentheses. Comments are only allowed in
+ fields containing "comment" as part of their field value definition.
+ In all other fields, parentheses are considered part of the field
+ value.
+
+ comment = "(" *( ctext | quoted-pair | comment ) ")"
+ ctext = &lt;any TEXT excluding "(" and ")"&gt;
+
+ A string of text is parsed as a single word if it is quoted using
+ double-quote marks.
+
+ quoted-string = ( &lt;"&gt; *(qdtext | quoted-pair ) &lt;"&gt; )
+ qdtext = &lt;any TEXT except &lt;"&gt;&gt;
+
+ The backslash character ("\") MAY be used as a single-character
+ quoting mechanism only within quoted-string and comment constructs.
+
+ quoted-pair = "\" CHAR
+
+3 Protocol Parameters
+
+3.1 HTTP Version
+
+ HTTP uses a "&lt;major&gt;.&lt;minor&gt;" numbering scheme to indicate versions
+ of the protocol. The protocol versioning policy is intended to allow
+ the sender to indicate the format of a message and its capacity for
+ understanding further HTTP communication, rather than the features
+ obtained via that communication. No change is made to the version
+ number for the addition of message components which do not affect
+ communication behavior or which only add to extensible field values.
+ The &lt;minor&gt; number is incremented when the changes made to the
+ protocol add features which do not change the general message parsing
+ algorithm, but which may add to the message semantics and imply
+ additional capabilities of the sender. The &lt;major&gt; number is
+ incremented when the format of a message within the protocol is
+ changed. See <a href="http://firefly.troll.no/rfcs/rfc2145.html">RFC 2145</a> [36] for a fuller explanation.
+
+ The version of an HTTP message is indicated by an HTTP-Version field
+ in the first line of the message.
+
+ HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
+
+ Note that the major and minor numbers MUST be treated as separate
+ integers and that each MAY be incremented higher than a single digit.
+ Thus, HTTP/2.4 is a lower version than HTTP/2.13, which in turn is
+ lower than HTTP/12.3. Leading zeros MUST be ignored by recipients and
+ MUST NOT be sent.
+
+ An application that sends a request or response message that includes
+ HTTP-Version of "HTTP/1.1" MUST be at least conditionally compliant
+ with this specification. Applications that are at least conditionally
+ compliant with this specification SHOULD use an HTTP-Version of
+ "HTTP/1.1" in their messages, and MUST do so for any message that is
+ not compatible with HTTP/1.0. For more details on when to send
+ specific HTTP-Version values, see <a href="http://firefly.troll.no/rfcs/rfc2145.html">RFC 2145</a> [36].
+
+ The HTTP version of an application is the highest HTTP version for
+ which the application is at least conditionally compliant.
+
+ Proxy and gateway applications need to be careful when forwarding
+ messages in protocol versions different from that of the application.
+ Since the protocol version indicates the protocol capability of the
+ sender, a proxy/gateway MUST NOT send a message with a version
+ indicator which is greater than its actual version. If a higher
+ version request is received, the proxy/gateway MUST either downgrade
+ the request version, or respond with an error, or switch to tunnel
+ behavior.
+
+ Due to interoperability problems with HTTP/1.0 proxies discovered
+ since the publication of <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>[33], caching proxies MUST, gateways
+ MAY, and tunnels MUST NOT upgrade the request to the highest version
+ they support. The proxy/gateway's response to that request MUST be in
+ the same major version as the request.
+
+ Note: Converting between versions of HTTP may involve modification
+ of header fields required or forbidden by the versions involved.
+
+3.2 Uniform Resource Identifiers
+
+ URIs have been known by many names: WWW addresses, Universal Document
+ Identifiers, Universal Resource Identifiers [3], and finally the
+ combination of Uniform Resource Locators (URL) [4] and Names (URN)
+ [20]. As far as HTTP is concerned, Uniform Resource Identifiers are
+ simply formatted strings which identify--via name, location, or any
+ other characteristic--a resource.
+
+3.2.1 General Syntax
+
+ URIs in HTTP can be represented in absolute form or relative to some
+ known base URI [11], depending upon the context of their use. The two
+ forms are differentiated by the fact that absolute URIs always begin
+ with a scheme name followed by a colon. For definitive information on
+ URL syntax and semantics, see "Uniform Resource Identifiers (URI):
+ Generic Syntax and Semantics," <a href="http://firefly.troll.no/rfcs/rfc2396.html">RFC 2396</a> [42] (which replaces RFCs
+ 1738 [4] and <a href="http://firefly.troll.no/rfcs/rfc1808.html">RFC 1808</a> [11]). This specification adopts the
+ definitions of "URI-reference", "absoluteURI", "relativeURI", "port",
+ "host","abs_path", "rel_path", and "authority" from that
+ specification.
+
+ The HTTP protocol does not place any a priori limit on the length of
+ a URI. Servers MUST be able to handle the URI of any resource they
+ serve, and SHOULD be able to handle URIs of unbounded length if they
+ provide GET-based forms that could generate such URIs. A server
+ SHOULD return 414 (Request-URI Too Long) status if a URI is longer
+ than the server can handle (see section 10.4.15).
+
+ Note: Servers ought to be cautious about depending on URI lengths
+ above 255 bytes, because some older client or proxy
+ implementations might not properly support these lengths.
+
+3.2.2 http URL
+
+ The "http" scheme is used to locate network resources via the HTTP
+ protocol. This section defines the scheme-specific syntax and
+ semantics for http URLs.
+
+ http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
+
+ If the port is empty or not given, port 80 is assumed. The semantics
+ are that the identified resource is located at the server listening
+ for TCP connections on that port of that host, and the Request-URI
+ for the resource is abs_path (section 5.1.2). The use of IP addresses
+ in URLs SHOULD be avoided whenever possible (see <a href="http://firefly.troll.no/rfcs/rfc1900.html">RFC 1900</a> [24]). If
+ the abs_path is not present in the URL, it MUST be given as "/" when
+ used as a Request-URI for a resource (section 5.1.2). If a proxy
+ receives a host name which is not a fully qualified domain name, it
+ MAY add its domain to the host name it received. If a proxy receives
+ a fully qualified domain name, the proxy MUST NOT change the host
+ name.
+
+3.2.3 URI Comparison
+
+ When comparing two URIs to decide if they match or not, a client
+ SHOULD use a case-sensitive octet-by-octet comparison of the entire
+ URIs, with these exceptions:
+
+ - A port that is empty or not given is equivalent to the default
+ port for that URI-reference;
+
+ - Comparisons of host names MUST be case-insensitive;
+
+ - Comparisons of scheme names MUST be case-insensitive;
+
+ - An empty abs_path is equivalent to an abs_path of "/".
+
+ Characters other than those in the "reserved" and "unsafe" sets (see
+ <a href="http://firefly.troll.no/rfcs/rfc2396.html">RFC 2396</a> [42]) are equivalent to their ""%" HEX HEX" encoding.
+
+ For example, the following three URIs are equivalent:
+
+ <a href="http://abc.com/%7Esmith/home.html">http://abc.com:80/~smith/home.html</a>
+ <a href="http://abc.com/%7Esmith/home.html">http://ABC.com/%7Esmith/home.html</a>
+ <a href="http://firefly.troll.no/%3CA%20HREF=" ftp:="" abc.com="" %7esmith="" home.html="">/ABC.com:/%7esmith/home.html</a>"&gt;http:/<a href="ftp://abc.com/%7esmith/home.html%3C/A%3E">/ABC.com:/%7esmith/home.html</a>
+
+3.3 Date/Time Formats
+
+3.3.1 Full Date
+
+ HTTP applications have historically allowed three different formats
+ for the representation of date/time stamps:
+
+ Sun, 06 Nov 1994 08:49:37 GMT ; <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a>, updated by <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a>
+ Sunday, 06-Nov-94 08:49:37 GMT ; <a href="http://firefly.troll.no/rfcs/rfc850.html">RFC 850</a>, obsoleted by <a href="http://firefly.troll.no/rfcs/rfc1036.html">RFC 1036</a>
+ Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+
+ The first format is preferred as an Internet standard and represents
+ a fixed-length subset of that defined by <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a> [8] (an update to
+ <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9]). The second format is in common use, but is based on the
+ obsolete <a href="http://firefly.troll.no/rfcs/rfc850.html">RFC 850</a> [12] date format and lacks a four-digit year.
+ HTTP/1.1 clients and servers that parse the date value MUST accept
+ all three formats (for compatibility with HTTP/1.0), though they MUST
+ only generate the <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a> format for representing HTTP-date values
+ in header fields. See section 19.3 for further information.
+
+ Note: Recipients of date values are encouraged to be robust in
+ accepting date values that may have been sent by non-HTTP
+ applications, as is sometimes the case when retrieving or posting
+ messages via proxies/gateways to SMTP or NNTP.
+
+ All HTTP date/time stamps MUST be represented in Greenwich Mean Time
+ (GMT), without exception. For the purposes of HTTP, GMT is exactly
+ equal to UTC (Coordinated Universal Time). This is indicated in the
+ first two formats by the inclusion of "GMT" as the three-letter
+ abbreviation for time zone, and MUST be assumed when reading the
+ asctime format. HTTP-date is case sensitive and MUST NOT include
+ additional LWS beyond that specifically included as SP in the
+ grammar.
+
+ HTTP-date = <a href="http://firefly.troll.no/rfcs/rfc1123.html">rfc1123</a>-date | <a href="http://firefly.troll.no/rfcs/rfc850.html">rfc850</a>-date | asctime-date
+ <a href="http://firefly.troll.no/rfcs/rfc1123.html">rfc1123</a>-date = wkday "," SP date1 SP time SP "GMT"
+ <a href="http://firefly.troll.no/rfcs/rfc850.html">rfc850</a>-date = weekday "," SP date2 SP time SP "GMT"
+ asctime-date = wkday SP date3 SP time SP 4DIGIT
+ date1 = 2DIGIT SP month SP 4DIGIT
+ ; day month year (e.g., 02 Jun 1982)
+ date2 = 2DIGIT "-" month "-" 2DIGIT
+ ; day-month-year (e.g., 02-Jun-82)
+ date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
+ ; month day (e.g., Jun 2)
+ time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
+ ; 00:00:00 - 23:59:59
+ wkday = "Mon" | "Tue" | "Wed"
+ | "Thu" | "Fri" | "Sat" | "Sun"
+ weekday = "Monday" | "Tuesday" | "Wednesday"
+ | "Thursday" | "Friday" | "Saturday" | "Sunday"
+ month = "Jan" | "Feb" | "Mar" | "Apr"
+ | "May" | "Jun" | "Jul" | "Aug"
+ | "Sep" | "Oct" | "Nov" | "Dec"
+
+ Note: HTTP requirements for the date/time stamp format apply only
+ to their usage within the protocol stream. Clients and servers are
+ not required to use these formats for user presentation, request
+ logging, etc.
+
+3.3.2 Delta Seconds
+
+ Some HTTP header fields allow a time value to be specified as an
+ integer number of seconds, represented in decimal, after the time
+ that the message was received.
+
+ delta-seconds = 1*DIGIT
+
+3.4 Character Sets
+
+ HTTP uses the same definition of the term "character set" as that
+ described for MIME:
+
+ The term "character set" is used in this document to refer to a
+ method used with one or more tables to convert a sequence of octets
+ into a sequence of characters. Note that unconditional conversion in
+ the other direction is not required, in that not all characters may
+ be available in a given character set and a character set may provide
+ more than one sequence of octets to represent a particular character.
+ This definition is intended to allow various kinds of character
+ encoding, from simple single-table mappings such as US-ASCII to
+ complex table switching methods such as those that use ISO-2022's
+ techniques. However, the definition associated with a MIME character
+ set name MUST fully specify the mapping to be performed from octets
+ to characters. In particular, use of external profiling information
+ to determine the exact mapping is not permitted.
+
+ Note: This use of the term "character set" is more commonly
+ referred to as a "character encoding." However, since HTTP and
+ MIME share the same registry, it is important that the terminology
+ also be shared.
+
+ HTTP character sets are identified by case-insensitive tokens. The
+ complete set of tokens is defined by the IANA Character Set registry
+ [19].
+
+ charset = token
+
+ Although HTTP allows an arbitrary token to be used as a charset
+ value, any token that has a predefined value within the IANA
+ Character Set registry [19] MUST represent the character set defined
+ by that registry. Applications SHOULD limit their use of character
+ sets to those defined by the IANA registry.
+
+ Implementors should be aware of IETF character set requirements [38]
+ [41].
+
+3.4.1 Missing Charset
+
+ Some HTTP/1.0 software has interpreted a Content-Type header without
+ charset parameter incorrectly to mean "recipient should guess."
+ Senders wishing to defeat this behavior MAY include a charset
+ parameter even when the charset is ISO-8859-1 and SHOULD do so when
+ it is known that it will not confuse the recipient.
+
+ Unfortunately, some older HTTP/1.0 clients did not deal properly with
+ an explicit charset parameter. HTTP/1.1 recipients MUST respect the
+ charset label provided by the sender; and those user agents that have
+ a provision to "guess" a charset MUST use the charset from the
+
+ content-type field if they support that charset, rather than the
+ recipient's preference, when initially displaying a document. See
+ section 3.7.1.
+
+3.5 Content Codings
+
+ Content coding values indicate an encoding transformation that has
+ been or can be applied to an entity. Content codings are primarily
+ used to allow a document to be compressed or otherwise usefully
+ transformed without losing the identity of its underlying media type
+ and without loss of information. Frequently, the entity is stored in
+ coded form, transmitted directly, and only decoded by the recipient.
+
+ content-coding = token
+
+ All content-coding values are case-insensitive. HTTP/1.1 uses
+ content-coding values in the Accept-Encoding (section 14.3) and
+ Content-Encoding (section 14.11) header fields. Although the value
+ describes the content-coding, what is more important is that it
+ indicates what decoding mechanism will be required to remove the
+ encoding.
+
+ The Internet Assigned Numbers Authority (IANA) acts as a registry for
+ content-coding value tokens. Initially, the registry contains the
+ following tokens:
+
+ gzip An encoding format produced by the file compression program
+ "gzip" (GNU zip) as described in <a href="http://firefly.troll.no/rfcs/rfc1952.html">RFC 1952</a> [25]. This format is a
+ Lempel-Ziv coding (LZ77) with a 32 bit CRC.
+
+ compress
+ The encoding format produced by the common UNIX file compression
+ program "compress". This format is an adaptive Lempel-Ziv-Welch
+ coding (LZW).
+
+ Use of program names for the identification of encoding formats
+ is not desirable and is discouraged for future encodings. Their
+ use here is representative of historical practice, not good
+ design. For compatibility with previous implementations of HTTP,
+ applications SHOULD consider "x-gzip" and "x-compress" to be
+ equivalent to "gzip" and "compress" respectively.
+
+ deflate
+ The "zlib" format defined in <a href="http://firefly.troll.no/rfcs/rfc1950.html">RFC 1950</a> [31] in combination with
+ the "deflate" compression mechanism described in <a href="http://firefly.troll.no/rfcs/rfc1951.html">RFC 1951</a> [29].
+
+ identity
+ The default (identity) encoding; the use of no transformation
+ whatsoever. This content-coding is used only in the Accept-
+ Encoding header, and SHOULD NOT be used in the Content-Encoding
+ header.
+
+ New content-coding value tokens SHOULD be registered; to allow
+ interoperability between clients and servers, specifications of the
+ content coding algorithms needed to implement a new value SHOULD be
+ publicly available and adequate for independent implementation, and
+ conform to the purpose of content coding defined in this section.
+
+3.6 Transfer Codings
+
+ Transfer-coding values are used to indicate an encoding
+ transformation that has been, can be, or may need to be applied to an
+ entity-body in order to ensure "safe transport" through the network.
+ This differs from a content coding in that the transfer-coding is a
+ property of the message, not of the original entity.
+
+ transfer-coding = "chunked" | transfer-extension
+ transfer-extension = token *( ";" parameter )
+
+ Parameters are in the form of attribute/value pairs.
+
+ parameter = attribute "=" value
+ attribute = token
+ value = token | quoted-string
+
+ All transfer-coding values are case-insensitive. HTTP/1.1 uses
+ transfer-coding values in the TE header field (section 14.39) and in
+ the Transfer-Encoding header field (section 14.41).
+
+ Whenever a transfer-coding is applied to a message-body, the set of
+ transfer-codings MUST include "chunked", unless the message is
+ terminated by closing the connection. When the "chunked" transfer-
+ coding is used, it MUST be the last transfer-coding applied to the
+ message-body. The "chunked" transfer-coding MUST NOT be applied more
+ than once to a message-body. These rules allow the recipient to
+ determine the transfer-length of the message (section 4.4).
+
+ Transfer-codings are analogous to the Content-Transfer-Encoding
+ values of MIME [7], which were designed to enable safe transport of
+ binary data over a 7-bit transport service. However, safe transport
+ has a different focus for an 8bit-clean transfer protocol. In HTTP,
+ the only unsafe characteristic of message-bodies is the difficulty in
+ determining the exact body length (section 7.2.2), or the desire to
+ encrypt data over a shared transport.
+
+ The Internet Assigned Numbers Authority (IANA) acts as a registry for
+ transfer-coding value tokens. Initially, the registry contains the
+ following tokens: "chunked" (section 3.6.1), "identity" (section
+ 3.6.2), "gzip" (section 3.5), "compress" (section 3.5), and "deflate"
+ (section 3.5).
+
+ New transfer-coding value tokens SHOULD be registered in the same way
+ as new content-coding value tokens (section 3.5).
+
+ A server which receives an entity-body with a transfer-coding it does
+ not understand SHOULD return 501 (Unimplemented), and close the
+ connection. A server MUST NOT send transfer-codings to an HTTP/1.0
+ client.
+
+3.6.1 Chunked Transfer Coding
+
+ The chunked encoding modifies the body of a message in order to
+ transfer it as a series of chunks, each with its own size indicator,
+ followed by an OPTIONAL trailer containing entity-header fields. This
+ allows dynamically produced content to be transferred along with the
+ information necessary for the recipient to verify that it has
+ received the full message.
+
+ Chunked-Body = *chunk
+ last-chunk
+ trailer
+ CRLF
+
+ chunk = chunk-size [ chunk-extension ] CRLF
+ chunk-data CRLF
+ chunk-size = 1*HEX
+ last-chunk = 1*("0") [ chunk-extension ] CRLF
+
+ chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
+ chunk-ext-name = token
+ chunk-ext-val = token | quoted-string
+ chunk-data = chunk-size(OCTET)
+ trailer = *(entity-header CRLF)
+
+ The chunk-size field is a string of hex digits indicating the size of
+ the chunk. The chunked encoding is ended by any chunk whose size is
+ zero, followed by the trailer, which is terminated by an empty line.
+
+ The trailer allows the sender to include additional HTTP header
+ fields at the end of the message. The Trailer header field can be
+ used to indicate which header fields are included in a trailer (see
+ section 14.40).
+
+ A server using chunked transfer-coding in a response MUST NOT use the
+ trailer for any header fields unless at least one of the following is
+ true:
+
+ a)the request included a TE header field that indicates "trailers" is
+ acceptable in the transfer-coding of the response, as described in
+ section 14.39; or,
+
+ b)the server is the origin server for the response, the trailer
+ fields consist entirely of optional metadata, and the recipient
+ could use the message (in a manner acceptable to the origin server)
+ without receiving this metadata. In other words, the origin server
+ is willing to accept the possibility that the trailer fields might
+ be silently discarded along the path to the client.
+
+ This requirement prevents an interoperability failure when the
+ message is being received by an HTTP/1.1 (or later) proxy and
+ forwarded to an HTTP/1.0 recipient. It avoids a situation where
+ compliance with the protocol would have necessitated a possibly
+ infinite buffer on the proxy.
+
+ An example process for decoding a Chunked-Body is presented in
+ appendix 19.4.6.
+
+ All HTTP/1.1 applications MUST be able to receive and decode the
+ "chunked" transfer-coding, and MUST ignore chunk-extension extensions
+ they do not understand.
+
+3.7 Media Types
+
+ HTTP uses Internet Media Types [17] in the Content-Type (section
+ 14.17) and Accept (section 14.1) header fields in order to provide
+ open and extensible data typing and type negotiation.
+
+ media-type = type "/" subtype *( ";" parameter )
+ type = token
+ subtype = token
+
+ Parameters MAY follow the type/subtype in the form of attribute/value
+ pairs (as defined in section 3.6).
+
+ The type, subtype, and parameter attribute names are case-
+ insensitive. Parameter values might or might not be case-sensitive,
+ depending on the semantics of the parameter name. Linear white space
+ (LWS) MUST NOT be used between the type and subtype, nor between an
+ attribute and its value. The presence or absence of a parameter might
+ be significant to the processing of a media-type, depending on its
+ definition within the media type registry.
+
+ Note that some older HTTP applications do not recognize media type
+ parameters. When sending data to older HTTP applications,
+ implementations SHOULD only use media type parameters when they are
+ required by that type/subtype definition.
+
+ Media-type values are registered with the Internet Assigned Number
+ Authority (IANA [19]). The media type registration process is
+ outlined in <a href="http://firefly.troll.no/rfcs/rfc1590.html">RFC 1590</a> [17]. Use of non-registered media types is
+ discouraged.
+
+3.7.1 Canonicalization and Text Defaults
+
+ Internet media types are registered with a canonical form. An
+ entity-body transferred via HTTP messages MUST be represented in the
+ appropriate canonical form prior to its transmission except for
+ "text" types, as defined in the next paragraph.
+
+ When in canonical form, media subtypes of the "text" type use CRLF as
+ the text line break. HTTP relaxes this requirement and allows the
+ transport of text media with plain CR or LF alone representing a line
+ break when it is done consistently for an entire entity-body. HTTP
+ applications MUST accept CRLF, bare CR, and bare LF as being
+ representative of a line break in text media received via HTTP. In
+ addition, if the text is represented in a character set that does not
+ use octets 13 and 10 for CR and LF respectively, as is the case for
+ some multi-byte character sets, HTTP allows the use of whatever octet
+ sequences are defined by that character set to represent the
+ equivalent of CR and LF for line breaks. This flexibility regarding
+ line breaks applies only to text media in the entity-body; a bare CR
+ or LF MUST NOT be substituted for CRLF within any of the HTTP control
+ structures (such as header fields and multipart boundaries).
+
+ If an entity-body is encoded with a content-coding, the underlying
+ data MUST be in a form defined above prior to being encoded.
+
+ The "charset" parameter is used with some media types to define the
+ character set (section 3.4) of the data. When no explicit charset
+ parameter is provided by the sender, media subtypes of the "text"
+ type are defined to have a default charset value of "ISO-8859-1" when
+ received via HTTP. Data in character sets other than "ISO-8859-1" or
+ its subsets MUST be labeled with an appropriate charset value. See
+ section 3.4.1 for compatibility problems.
+
+3.7.2 Multipart Types
+
+ MIME provides for a number of "multipart" types -- encapsulations of
+ one or more entities within a single message-body. All multipart
+ types share a common syntax, as defined in section 5.1.1 of <a href="http://firefly.troll.no/rfcs/rfc2046.html">RFC 2046</a>
+
+ [40], and MUST include a boundary parameter as part of the media type
+ value. The message body is itself a protocol element and MUST
+ therefore use only CRLF to represent line breaks between body-parts.
+ Unlike in <a href="http://firefly.troll.no/rfcs/rfc2046.html">RFC 2046</a>, the epilogue of any multipart message MUST be
+ empty; HTTP applications MUST NOT transmit the epilogue (even if the
+ original multipart contains an epilogue). These restrictions exist in
+ order to preserve the self-delimiting nature of a multipart message-
+ body, wherein the "end" of the message-body is indicated by the
+ ending multipart boundary.
+
+ In general, HTTP treats a multipart message-body no differently than
+ any other media type: strictly as payload. The one exception is the
+ "multipart/byteranges" type (appendix 19.2) when it appears in a 206
+ (Partial Content) response, which will be interpreted by some HTTP
+ caching mechanisms as described in sections 13.5.4 and 14.16. In all
+ other cases, an HTTP user agent SHOULD follow the same or similar
+ behavior as a MIME user agent would upon receipt of a multipart type.
+ The MIME header fields within each body-part of a multipart message-
+ body do not have any significance to HTTP beyond that defined by
+ their MIME semantics.
+
+ In general, an HTTP user agent SHOULD follow the same or similar
+ behavior as a MIME user agent would upon receipt of a multipart type.
+ If an application receives an unrecognized multipart subtype, the
+ application MUST treat it as being equivalent to "multipart/mixed".
+
+ Note: The "multipart/form-data" type has been specifically defined
+ for carrying form data suitable for processing via the POST
+ request method, as described in <a href="http://firefly.troll.no/rfcs/rfc1867.html">RFC 1867</a> [15].
+
+3.8 Product Tokens
+
+ Product tokens are used to allow communicating applications to
+ identify themselves by software name and version. Most fields using
+ product tokens also allow sub-products which form a significant part
+ of the application to be listed, separated by white space. By
+ convention, the products are listed in order of their significance
+ for identifying the application.
+
+ product = token ["/" product-version]
+ product-version = token
+
+ Examples:
+
+ User-Agent: CERN-LineMode/2.15 libwww/2.17b3
+ Server: Apache/0.8.4
+
+ Product tokens SHOULD be short and to the point. They MUST NOT be
+ used for advertising or other non-essential information. Although any
+ token character MAY appear in a product-version, this token SHOULD
+ only be used for a version identifier (i.e., successive versions of
+ the same product SHOULD only differ in the product-version portion of
+ the product value).
+
+3.9 Quality Values
+
+ HTTP content negotiation (section 12) uses short "floating point"
+ numbers to indicate the relative importance ("weight") of various
+ negotiable parameters. A weight is normalized to a real number in
+ the range 0 through 1, where 0 is the minimum and 1 the maximum
+ value. If a parameter has a quality value of 0, then content with
+ this parameter is `not acceptable' for the client. HTTP/1.1
+ applications MUST NOT generate more than three digits after the
+ decimal point. User configuration of these values SHOULD also be
+ limited in this fashion.
+
+ qvalue = ( "0" [ "." 0*3DIGIT ] )
+ | ( "1" [ "." 0*3("0") ] )
+
+ "Quality values" is a misnomer, since these values merely represent
+ relative degradation in desired quality.
+
+3.10 Language Tags
+
+ A language tag identifies a natural language spoken, written, or
+ otherwise conveyed by human beings for communication of information
+ to other human beings. Computer languages are explicitly excluded.
+ HTTP uses language tags within the Accept-Language and Content-
+ Language fields.
+
+ The syntax and registry of HTTP language tags is the same as that
+ defined by <a href="http://firefly.troll.no/rfcs/rfc1766.html">RFC 1766</a> [1]. In summary, a language tag is composed of 1
+ or more parts: A primary language tag and a possibly empty series of
+ subtags:
+
+ language-tag = primary-tag *( "-" subtag )
+ primary-tag = 1*8ALPHA
+ subtag = 1*8ALPHA
+
+ White space is not allowed within the tag and all tags are case-
+ insensitive. The name space of language tags is administered by the
+ IANA. Example tags include:
+
+ en, en-US, en-cockney, i-cherokee, x-pig-latin
+
+ where any two-letter primary-tag is an ISO-639 language abbreviation
+ and any two-letter initial subtag is an ISO-3166 country code. (The
+ last three tags above are not registered tags; all but the last are
+ examples of tags which could be registered in future.)
+
+3.11 Entity Tags
+
+ Entity tags are used for comparing two or more entities from the same
+ requested resource. HTTP/1.1 uses entity tags in the ETag (section
+ 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and
+ If-Range (section 14.27) header fields. The definition of how they
+ are used and compared as cache validators is in section 13.3.3. An
+ entity tag consists of an opaque quoted string, possibly prefixed by
+ a weakness indicator.
+
+ entity-tag = [ weak ] opaque-tag
+ weak = "W/"
+ opaque-tag = quoted-string
+
+ A "strong entity tag" MAY be shared by two entities of a resource
+ only if they are equivalent by octet equality.
+
+ A "weak entity tag," indicated by the "W/" prefix, MAY be shared by
+ two entities of a resource only if the entities are equivalent and
+ could be substituted for each other with no significant change in
+ semantics. A weak entity tag can only be used for weak comparison.
+
+ An entity tag MUST be unique across all versions of all entities
+ associated with a particular resource. A given entity tag value MAY
+ be used for entities obtained by requests on different URIs. The use
+ of the same entity tag value in conjunction with entities obtained by
+ requests on different URIs does not imply the equivalence of those
+ entities.
+
+3.12 Range Units
+
+ HTTP/1.1 allows a client to request that only part (a range of) the
+ response entity be included within the response. HTTP/1.1 uses range
+ units in the Range (section 14.35) and Content-Range (section 14.16)
+ header fields. An entity can be broken down into subranges according
+ to various structural units.
+
+ range-unit = bytes-unit | other-range-unit
+ bytes-unit = "bytes"
+ other-range-unit = token
+
+ The only range unit defined by HTTP/1.1 is "bytes". HTTP/1.1
+ implementations MAY ignore ranges specified using other units.
+
+ HTTP/1.1 has been designed to allow implementations of applications
+ that do not depend on knowledge of ranges.
+
+4 HTTP Message
+
+4.1 Message Types
+
+ HTTP messages consist of requests from client to server and responses
+ from server to client.
+
+ HTTP-message = Request | Response ; HTTP/1.1 messages
+
+ Request (section 5) and Response (section 6) messages use the generic
+ message format of <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9] for transferring entities (the payload
+ of the message). Both types of message consist of a start-line, zero
+ or more header fields (also known as "headers"), an empty line (i.e.,
+ a line with nothing preceding the CRLF) indicating the end of the
+ header fields, and possibly a message-body.
+
+ generic-message = start-line
+ *(message-header CRLF)
+ CRLF
+ [ message-body ]
+ start-line = Request-Line | Status-Line
+
+ In the interest of robustness, servers SHOULD ignore any empty
+ line(s) received where a Request-Line is expected. In other words, if
+ the server is reading the protocol stream at the beginning of a
+ message and receives a CRLF first, it should ignore the CRLF.
+
+ Certain buggy HTTP/1.0 client implementations generate extra CRLF's
+ after a POST request. To restate what is explicitly forbidden by the
+ BNF, an HTTP/1.1 client MUST NOT preface or follow a request with an
+ extra CRLF.
+
+4.2 Message Headers
+
+ HTTP header fields, which include general-header (section 4.5),
+ request-header (section 5.3), response-header (section 6.2), and
+ entity-header (section 7.1) fields, follow the same generic format as
+ that given in Section 3.1 of <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9]. Each header field consists
+ of a name followed by a colon (":") and the field value. Field names
+ are case-insensitive. The field value MAY be preceded by any amount
+ of LWS, though a single SP is preferred. Header fields can be
+ extended over multiple lines by preceding each extra line with at
+ least one SP or HT. Applications ought to follow "common form", where
+ one is known or indicated, when generating HTTP constructs, since
+ there might exist some implementations that fail to accept anything
+
+ beyond the common forms.
+
+ message-header = field-name ":" [ field-value ]
+ field-name = token
+ field-value = *( field-content | LWS )
+ field-content = &lt;the OCTETs making up the field-value
+ and consisting of either *TEXT or combinations
+ of token, separators, and quoted-string&gt;
+
+ The field-content does not include any leading or trailing LWS:
+ linear white space occurring before the first non-whitespace
+ character of the field-value or after the last non-whitespace
+ character of the field-value. Such leading or trailing LWS MAY be
+ removed without changing the semantics of the field value. Any LWS
+ that occurs between field-content MAY be replaced with a single SP
+ before interpreting the field value or forwarding the message
+ downstream.
+
+ The order in which header fields with differing field names are
+ received is not significant. However, it is "good practice" to send
+ general-header fields first, followed by request-header or response-
+ header fields, and ending with the entity-header fields.
+
+ Multiple message-header fields with the same field-name MAY be
+ present in a message if and only if the entire field-value for that
+ header field is defined as a comma-separated list [i.e., #(values)].
+ It MUST be possible to combine the multiple header fields into one
+ "field-name: field-value" pair, without changing the semantics of the
+ message, by appending each subsequent field-value to the first, each
+ separated by a comma. The order in which header fields with the same
+ field-name are received is therefore significant to the
+ interpretation of the combined field value, and thus a proxy MUST NOT
+ change the order of these field values when a message is forwarded.
+
+4.3 Message Body
+
+ The message-body (if any) of an HTTP message is used to carry the
+ entity-body associated with the request or response. The message-body
+ differs from the entity-body only when a transfer-coding has been
+ applied, as indicated by the Transfer-Encoding header field (section
+ 14.41).
+
+ message-body = entity-body
+ | &lt;entity-body encoded as per Transfer-Encoding&gt;
+
+ Transfer-Encoding MUST be used to indicate any transfer-codings
+ applied by an application to ensure safe and proper transfer of the
+ message. Transfer-Encoding is a property of the message, not of the
+
+ entity, and thus MAY be added or removed by any application along the
+ request/response chain. (However, section 3.6 places restrictions on
+ when certain transfer-codings may be used.)
+
+ The rules for when a message-body is allowed in a message differ for
+ requests and responses.
+
+ The presence of a message-body in a request is signaled by the
+ inclusion of a Content-Length or Transfer-Encoding header field in
+ the request's message-headers. A message-body MUST NOT be included in
+ a request if the specification of the request method (section 5.1.1)
+ does not allow sending an entity-body in requests. A server SHOULD
+ read and forward a message-body on any request; if the request method
+ does not include defined semantics for an entity-body, then the
+ message-body SHOULD be ignored when handling the request.
+
+ For response messages, whether or not a message-body is included with
+ a message is dependent on both the request method and the response
+ status code (section 6.1.1). All responses to the HEAD request method
+ MUST NOT include a message-body, even though the presence of entity-
+ header fields might lead one to believe they do. All 1xx
+ (informational), 204 (no content), and 304 (not modified) responses
+ MUST NOT include a message-body. All other responses do include a
+ message-body, although it MAY be of zero length.
+
+4.4 Message Length
+
+ The transfer-length of a message is the length of the message-body as
+ it appears in the message; that is, after any transfer-codings have
+ been applied. When a message-body is included with a message, the
+ transfer-length of that body is determined by one of the following
+ (in order of precedence):
+
+ 1.Any response message which "MUST NOT" include a message-body (such
+ as the 1xx, 204, and 304 responses and any response to a HEAD
+ request) is always terminated by the first empty line after the
+ header fields, regardless of the entity-header fields present in
+ the message.
+
+ 2.If a Transfer-Encoding header field (section 14.41) is present and
+ has any value other than "identity", then the transfer-length is
+ defined by use of the "chunked" transfer-coding (section 3.6),
+ unless the message is terminated by closing the connection.
+
+ 3.If a Content-Length header field (section 14.13) is present, its
+ decimal value in OCTETs represents both the entity-length and the
+ transfer-length. The Content-Length header field MUST NOT be sent
+ if these two lengths are different (i.e., if a Transfer-Encoding
+
+ header field is present). If a message is received with both a
+ Transfer-Encoding header field and a Content-Length header field,
+ the latter MUST be ignored.
+
+ 4.If the message uses the media type "multipart/byteranges", and the
+ ransfer-length is not otherwise specified, then this self-
+ elimiting media type defines the transfer-length. This media type
+ UST NOT be used unless the sender knows that the recipient can arse
+ it; the presence in a request of a Range header with ultiple byte-
+ range specifiers from a 1.1 client implies that the lient can parse
+ multipart/byteranges responses.
+
+ A range header might be forwarded by a 1.0 proxy that does not
+ understand multipart/byteranges; in this case the server MUST
+ delimit the message using methods defined in items 1,3 or 5 of
+ this section.
+
+ 5.By the server closing the connection. (Closing the connection
+ cannot be used to indicate the end of a request body, since that
+ would leave no possibility for the server to send back a response.)
+
+ For compatibility with HTTP/1.0 applications, HTTP/1.1 requests
+ containing a message-body MUST include a valid Content-Length header
+ field unless the server is known to be HTTP/1.1 compliant. If a
+ request contains a message-body and a Content-Length is not given,
+ the server SHOULD respond with 400 (bad request) if it cannot
+ determine the length of the message, or with 411 (length required) if
+ it wishes to insist on receiving a valid Content-Length.
+
+ All HTTP/1.1 applications that receive entities MUST accept the
+ "chunked" transfer-coding (section 3.6), thus allowing this mechanism
+ to be used for messages when the message length cannot be determined
+ in advance.
+
+ Messages MUST NOT include both a Content-Length header field and a
+ non-identity transfer-coding. If the message does include a non-
+ identity transfer-coding, the Content-Length MUST be ignored.
+
+ When a Content-Length is given in a message where a message-body is
+ allowed, its field value MUST exactly match the number of OCTETs in
+ the message-body. HTTP/1.1 user agents MUST notify the user when an
+ invalid length is received and detected.
+
+4.5 General Header Fields
+
+ There are a few header fields which have general applicability for
+ both request and response messages, but which do not apply to the
+ entity being transferred. These header fields apply only to the
+
+ message being transmitted.
+
+ general-header = Cache-Control ; Section 14.9
+ | Connection ; Section 14.10
+ | Date ; Section 14.18
+ | Pragma ; Section 14.32
+ | Trailer ; Section 14.40
+ | Transfer-Encoding ; Section 14.41
+ | Upgrade ; Section 14.42
+ | Via ; Section 14.45
+ | Warning ; Section 14.46
+
+ General-header field names can be extended reliably only in
+ combination with a change in the protocol version. However, new or
+ experimental header fields may be given the semantics of general
+ header fields if all parties in the communication recognize them to
+ be general-header fields. Unrecognized header fields are treated as
+ entity-header fields.
+
+5 Request
+
+ A request message from a client to a server includes, within the
+ first line of that message, the method to be applied to the resource,
+ the identifier of the resource, and the protocol version in use.
+
+ Request = Request-Line ; Section 5.1
+ *(( general-header ; Section 4.5
+ | request-header ; Section 5.3
+ | entity-header ) CRLF) ; Section 7.1
+ CRLF
+ [ message-body ] ; Section 4.3
+
+5.1 Request-Line
+
+ The Request-Line begins with a method token, followed by the
+ Request-URI and the protocol version, and ending with CRLF. The
+ elements are separated by SP characters. No CR or LF is allowed
+ except in the final CRLF sequence.
+
+ Request-Line = Method SP Request-URI SP HTTP-Version CRLF
+
+5.1.1 Method
+
+ The Method token indicates the method to be performed on the
+ resource identified by the Request-URI. The method is case-sensitive.
+
+ Method = "OPTIONS" ; Section 9.2
+ | "GET" ; Section 9.3
+ | "HEAD" ; Section 9.4
+ | "POST" ; Section 9.5
+ | "PUT" ; Section 9.6
+ | "DELETE" ; Section 9.7
+ | "TRACE" ; Section 9.8
+ | "CONNECT" ; Section 9.9
+ | extension-method
+ extension-method = token
+
+ The list of methods allowed by a resource can be specified in an
+ Allow header field (section 14.7). The return code of the response
+ always notifies the client whether a method is currently allowed on a
+ resource, since the set of allowed methods can change dynamically. An
+ origin server SHOULD return the status code 405 (Method Not Allowed)
+ if the method is known by the origin server but not allowed for the
+ requested resource, and 501 (Not Implemented) if the method is
+ unrecognized or not implemented by the origin server. The methods GET
+ and HEAD MUST be supported by all general-purpose servers. All other
+ methods are OPTIONAL; however, if the above methods are implemented,
+ they MUST be implemented with the same semantics as those specified
+ in section 9.
+
+5.1.2 Request-URI
+
+ The Request-URI is a Uniform Resource Identifier (section 3.2) and
+ identifies the resource upon which to apply the request.
+
+ Request-URI = "*" | absoluteURI | abs_path | authority
+
+ The four options for Request-URI are dependent on the nature of the
+ request. The asterisk "*" means that the request does not apply to a
+ particular resource, but to the server itself, and is only allowed
+ when the method used does not necessarily apply to a resource. One
+ example would be
+
+ OPTIONS * HTTP/1.1
+
+ The absoluteURI form is REQUIRED when the request is being made to a
+ proxy. The proxy is requested to forward the request or service it
+ from a valid cache, and return the response. Note that the proxy MAY
+ forward the request on to another proxy or directly to the server
+
+ specified by the absoluteURI. In order to avoid request loops, a
+ proxy MUST be able to recognize all of its server names, including
+ any aliases, local variations, and the numeric IP address. An example
+ Request-Line would be:
+
+ GET <a href="http://www.w3.org/pub/WWW/TheProject.html">http://www.w3.org/pub/WWW/TheProject.html</a> HTTP/1.1
+
+ To allow for transition to absoluteURIs in all requests in future
+ versions of HTTP, all HTTP/1.1 servers MUST accept the absoluteURI
+ form in requests, even though HTTP/1.1 clients will only generate
+ them in requests to proxies.
+
+ The authority form is only used by the CONNECT method (section 9.9).
+
+ The most common form of Request-URI is that used to identify a
+ resource on an origin server or gateway. In this case the absolute
+ path of the URI MUST be transmitted (see section 3.2.1, abs_path) as
+ the Request-URI, and the network location of the URI (authority) MUST
+ be transmitted in a Host header field. For example, a client wishing
+ to retrieve the resource above directly from the origin server would
+ create a TCP connection to port 80 of the host "www.w3.org" and send
+ the lines:
+
+ GET /pub/WWW/TheProject.html HTTP/1.1
+ Host: www.w3.org
+
+ followed by the remainder of the Request. Note that the absolute path
+ cannot be empty; if none is present in the original URI, it MUST be
+ given as "/" (the server root).
+
+ The Request-URI is transmitted in the format specified in section
+ 3.2.1. If the Request-URI is encoded using the "% HEX HEX" encoding
+ [42], the origin server MUST decode the Request-URI in order to
+ properly interpret the request. Servers SHOULD respond to invalid
+ Request-URIs with an appropriate status code.
+
+ A transparent proxy MUST NOT rewrite the "abs_path" part of the
+ received Request-URI when forwarding it to the next inbound server,
+ except as noted above to replace a null abs_path with "/".
+
+ Note: The "no rewrite" rule prevents the proxy from changing the
+ meaning of the request when the origin server is improperly using
+ a non-reserved URI character for a reserved purpose. Implementors
+ should be aware that some pre-HTTP/1.1 proxies have been known to
+ rewrite the Request-URI.
+
+5.2 The Resource Identified by a Request
+
+ The exact resource identified by an Internet request is determined by
+ examining both the Request-URI and the Host header field.
+
+ An origin server that does not allow resources to differ by the
+ requested host MAY ignore the Host header field value when
+ determining the resource identified by an HTTP/1.1 request. (But see
+ section 19.6.1.1 for other requirements on Host support in HTTP/1.1.)
+
+ An origin server that does differentiate resources based on the host
+ requested (sometimes referred to as virtual hosts or vanity host
+ names) MUST use the following rules for determining the requested
+ resource on an HTTP/1.1 request:
+
+ 1. If Request-URI is an absoluteURI, the host is part of the
+ Request-URI. Any Host header field value in the request MUST be
+ ignored.
+
+ 2. If the Request-URI is not an absoluteURI, and the request includes
+ a Host header field, the host is determined by the Host header
+ field value.
+
+ 3. If the host as determined by rule 1 or 2 is not a valid host on
+ the server, the response MUST be a 400 (Bad Request) error message.
+
+ Recipients of an HTTP/1.0 request that lacks a Host header field MAY
+ attempt to use heuristics (e.g., examination of the URI path for
+ something unique to a particular host) in order to determine what
+ exact resource is being requested.
+
+5.3 Request Header Fields
+
+ The request-header fields allow the client to pass additional
+ information about the request, and about the client itself, to the
+ server. These fields act as request modifiers, with semantics
+ equivalent to the parameters on a programming language method
+ invocation.
+
+ request-header = Accept ; Section 14.1
+ | Accept-Charset ; Section 14.2
+ | Accept-Encoding ; Section 14.3
+ | Accept-Language ; Section 14.4
+ | Authorization ; Section 14.8
+ | Expect ; Section 14.20
+ | From ; Section 14.22
+ | Host ; Section 14.23
+ | If-Match ; Section 14.24
+
+ | If-Modified-Since ; Section 14.25
+ | If-None-Match ; Section 14.26
+ | If-Range ; Section 14.27
+ | If-Unmodified-Since ; Section 14.28
+ | Max-Forwards ; Section 14.31
+ | Proxy-Authorization ; Section 14.34
+ | Range ; Section 14.35
+ | Referer ; Section 14.36
+ | TE ; Section 14.39
+ | User-Agent ; Section 14.43
+
+ Request-header field names can be extended reliably only in
+ combination with a change in the protocol version. However, new or
+ experimental header fields MAY be given the semantics of request-
+ header fields if all parties in the communication recognize them to
+ be request-header fields. Unrecognized header fields are treated as
+ entity-header fields.
+
+6 Response
+
+ After receiving and interpreting a request message, a server responds
+ with an HTTP response message.
+
+ Response = Status-Line ; Section 6.1
+ *(( general-header ; Section 4.5
+ | response-header ; Section 6.2
+ | entity-header ) CRLF) ; Section 7.1
+ CRLF
+ [ message-body ] ; Section 7.2
+
+6.1 Status-Line
+
+ The first line of a Response message is the Status-Line, consisting
+ of the protocol version followed by a numeric status code and its
+ associated textual phrase, with each element separated by SP
+ characters. No CR or LF is allowed except in the final CRLF sequence.
+
+ Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
+
+6.1.1 Status Code and Reason Phrase
+
+ The Status-Code element is a 3-digit integer result code of the
+ attempt to understand and satisfy the request. These codes are fully
+ defined in section 10. The Reason-Phrase is intended to give a short
+ textual description of the Status-Code. The Status-Code is intended
+ for use by automata and the Reason-Phrase is intended for the human
+ user. The client is not required to examine or display the Reason-
+ Phrase.
+
+ The first digit of the Status-Code defines the class of response. The
+ last two digits do not have any categorization role. There are 5
+ values for the first digit:
+
+ - 1xx: Informational - Request received, continuing process
+
+ - 2xx: Success - The action was successfully received,
+ understood, and accepted
+
+ - 3xx: Redirection - Further action must be taken in order to
+ complete the request
+
+ - 4xx: Client Error - The request contains bad syntax or cannot
+ be fulfilled
+
+ - 5xx: Server Error - The server failed to fulfill an apparently
+ valid request
+
+ The individual values of the numeric status codes defined for
+ HTTP/1.1, and an example set of corresponding Reason-Phrase's, are
+ presented below. The reason phrases listed here are only
+ recommendations -- they MAY be replaced by local equivalents without
+ affecting the protocol.
+
+ Status-Code =
+ "100" ; Section 10.1.1: Continue
+ | "101" ; Section 10.1.2: Switching Protocols
+ | "200" ; Section 10.2.1: OK
+ | "201" ; Section 10.2.2: Created
+ | "202" ; Section 10.2.3: Accepted
+ | "203" ; Section 10.2.4: Non-Authoritative Information
+ | "204" ; Section 10.2.5: No Content
+ | "205" ; Section 10.2.6: Reset Content
+ | "206" ; Section 10.2.7: Partial Content
+ | "300" ; Section 10.3.1: Multiple Choices
+ | "301" ; Section 10.3.2: Moved Permanently
+ | "302" ; Section 10.3.3: Found
+ | "303" ; Section 10.3.4: See Other
+ | "304" ; Section 10.3.5: Not Modified
+ | "305" ; Section 10.3.6: Use Proxy
+ | "307" ; Section 10.3.8: Temporary Redirect
+ | "400" ; Section 10.4.1: Bad Request
+ | "401" ; Section 10.4.2: Unauthorized
+ | "402" ; Section 10.4.3: Payment Required
+ | "403" ; Section 10.4.4: Forbidden
+ | "404" ; Section 10.4.5: Not Found
+ | "405" ; Section 10.4.6: Method Not Allowed
+ | "406" ; Section 10.4.7: Not Acceptable
+
+ | "407" ; Section 10.4.8: Proxy Authentication Required
+ | "408" ; Section 10.4.9: Request Time-out
+ | "409" ; Section 10.4.10: Conflict
+ | "410" ; Section 10.4.11: Gone
+ | "411" ; Section 10.4.12: Length Required
+ | "412" ; Section 10.4.13: Precondition Failed
+ | "413" ; Section 10.4.14: Request Entity Too Large
+ | "414" ; Section 10.4.15: Request-URI Too Large
+ | "415" ; Section 10.4.16: Unsupported Media Type
+ | "416" ; Section 10.4.17: Requested range not satisfiable
+ | "417" ; Section 10.4.18: Expectation Failed
+ | "500" ; Section 10.5.1: Internal Server Error
+ | "501" ; Section 10.5.2: Not Implemented
+ | "502" ; Section 10.5.3: Bad Gateway
+ | "503" ; Section 10.5.4: Service Unavailable
+ | "504" ; Section 10.5.5: Gateway Time-out
+ | "505" ; Section 10.5.6: HTTP Version not supported
+ | extension-code
+
+ extension-code = 3DIGIT
+ Reason-Phrase = *&lt;TEXT, excluding CR, LF&gt;
+
+ HTTP status codes are extensible. HTTP applications are not required
+ to understand the meaning of all registered status codes, though such
+ understanding is obviously desirable. However, applications MUST
+ understand the class of any status code, as indicated by the first
+ digit, and treat any unrecognized response as being equivalent to the
+ x00 status code of that class, with the exception that an
+ unrecognized response MUST NOT be cached. For example, if an
+ unrecognized status code of 431 is received by the client, it can
+ safely assume that there was something wrong with its request and
+ treat the response as if it had received a 400 status code. In such
+ cases, user agents SHOULD present to the user the entity returned
+ with the response, since that entity is likely to include human-
+ readable information which will explain the unusual status.
+
+6.2 Response Header Fields
+
+ The response-header fields allow the server to pass additional
+ information about the response which cannot be placed in the Status-
+ Line. These header fields give information about the server and about
+ further access to the resource identified by the Request-URI.
+
+ response-header = Accept-Ranges ; Section 14.5
+ | Age ; Section 14.6
+ | ETag ; Section 14.19
+ | Location ; Section 14.30
+ | Proxy-Authenticate ; Section 14.33
+
+ | Retry-After ; Section 14.37
+ | Server ; Section 14.38
+ | Vary ; Section 14.44
+ | WWW-Authenticate ; Section 14.47
+
+ Response-header field names can be extended reliably only in
+ combination with a change in the protocol version. However, new or
+ experimental header fields MAY be given the semantics of response-
+ header fields if all parties in the communication recognize them to
+ be response-header fields. Unrecognized header fields are treated as
+ entity-header fields.
+
+7 Entity
+
+ Request and Response messages MAY transfer an entity if not otherwise
+ restricted by the request method or response status code. An entity
+ consists of entity-header fields and an entity-body, although some
+ responses will only include the entity-headers.
+
+ In this section, both sender and recipient refer to either the client
+ or the server, depending on who sends and who receives the entity.
+
+7.1 Entity Header Fields
+
+ Entity-header fields define metainformation about the entity-body or,
+ if no body is present, about the resource identified by the request.
+ Some of this metainformation is OPTIONAL; some might be REQUIRED by
+ portions of this specification.
+
+ entity-header = Allow ; Section 14.7
+ | Content-Encoding ; Section 14.11
+ | Content-Language ; Section 14.12
+ | Content-Length ; Section 14.13
+ | Content-Location ; Section 14.14
+ | Content-MD5 ; Section 14.15
+ | Content-Range ; Section 14.16
+ | Content-Type ; Section 14.17
+ | Expires ; Section 14.21
+ | Last-Modified ; Section 14.29
+ | extension-header
+
+ extension-header = message-header
+
+ The extension-header mechanism allows additional entity-header fields
+ to be defined without changing the protocol, but these fields cannot
+ be assumed to be recognizable by the recipient. Unrecognized header
+ fields SHOULD be ignored by the recipient and MUST be forwarded by
+ transparent proxies.
+
+7.2 Entity Body
+
+ The entity-body (if any) sent with an HTTP request or response is in
+ a format and encoding defined by the entity-header fields.
+
+ entity-body = *OCTET
+
+ An entity-body is only present in a message when a message-body is
+ present, as described in section 4.3. The entity-body is obtained
+ from the message-body by decoding any Transfer-Encoding that might
+ have been applied to ensure safe and proper transfer of the message.
+
+7.2.1 Type
+
+ When an entity-body is included with a message, the data type of that
+ body is determined via the header fields Content-Type and Content-
+ Encoding. These define a two-layer, ordered encoding model:
+
+ entity-body := Content-Encoding( Content-Type( data ) )
+
+ Content-Type specifies the media type of the underlying data.
+ Content-Encoding may be used to indicate any additional content
+ codings applied to the data, usually for the purpose of data
+ compression, that are a property of the requested resource. There is
+ no default encoding.
+
+ Any HTTP/1.1 message containing an entity-body SHOULD include a
+ Content-Type header field defining the media type of that body. If
+ and only if the media type is not given by a Content-Type field, the
+ recipient MAY attempt to guess the media type via inspection of its
+ content and/or the name extension(s) of the URI used to identify the
+ resource. If the media type remains unknown, the recipient SHOULD
+ treat it as type "application/octet-stream".
+
+7.2.2 Entity Length
+
+ The entity-length of a message is the length of the message-body
+ before any transfer-codings have been applied. Section 4.4 defines
+ how the transfer-length of a message-body is determined.
+
+8 Connections
+
+8.1 Persistent Connections
+
+8.1.1 Purpose
+
+ Prior to persistent connections, a separate TCP connection was
+ established to fetch each URL, increasing the load on HTTP servers
+ and causing congestion on the Internet. The use of inline images and
+ other associated data often require a client to make multiple
+ requests of the same server in a short amount of time. Analysis of
+ these performance problems and results from a prototype
+ implementation are available [26] [30]. Implementation experience and
+ measurements of actual HTTP/1.1 (<a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>) implementations show good
+ results [39]. Alternatives have also been explored, for example,
+ T/TCP [27].
+
+ Persistent HTTP connections have a number of advantages:
+
+ - By opening and closing fewer TCP connections, CPU time is saved
+ in routers and hosts (clients, servers, proxies, gateways,
+ tunnels, or caches), and memory used for TCP protocol control
+ blocks can be saved in hosts.
+
+ - HTTP requests and responses can be pipelined on a connection.
+ Pipelining allows a client to make multiple requests without
+ waiting for each response, allowing a single TCP connection to
+ be used much more efficiently, with much lower elapsed time.
+
+ - Network congestion is reduced by reducing the number of packets
+ caused by TCP opens, and by allowing TCP sufficient time to
+ determine the congestion state of the network.
+
+ - Latency on subsequent requests is reduced since there is no time
+ spent in TCP's connection opening handshake.
+
+ - HTTP can evolve more gracefully, since errors can be reported
+ without the penalty of closing the TCP connection. Clients using
+ future versions of HTTP might optimistically try a new feature,
+ but if communicating with an older server, retry with old
+ semantics after an error is reported.
+
+ HTTP implementations SHOULD implement persistent connections.
+
+8.1.2 Overall Operation
+
+ A significant difference between HTTP/1.1 and earlier versions of
+ HTTP is that persistent connections are the default behavior of any
+ HTTP connection. That is, unless otherwise indicated, the client
+ SHOULD assume that the server will maintain a persistent connection,
+ even after error responses from the server.
+
+ Persistent connections provide a mechanism by which a client and a
+ server can signal the close of a TCP connection. This signaling takes
+ place using the Connection header field (section 14.10). Once a close
+ has been signaled, the client MUST NOT send any more requests on that
+ connection.
+
+8.1.2.1 Negotiation
+
+ An HTTP/1.1 server MAY assume that a HTTP/1.1 client intends to
+ maintain a persistent connection unless a Connection header including
+ the connection-token "close" was sent in the request. If the server
+ chooses to close the connection immediately after sending the
+ response, it SHOULD send a Connection header including the
+ connection-token close.
+
+ An HTTP/1.1 client MAY expect a connection to remain open, but would
+ decide to keep it open based on whether the response from a server
+ contains a Connection header with the connection-token close. In case
+ the client does not want to maintain a connection for more than that
+ request, it SHOULD send a Connection header including the
+ connection-token close.
+
+ If either the client or the server sends the close token in the
+ Connection header, that request becomes the last one for the
+ connection.
+
+ Clients and servers SHOULD NOT assume that a persistent connection is
+ maintained for HTTP versions less than 1.1 unless it is explicitly
+ signaled. See section 19.6.2 for more information on backward
+ compatibility with HTTP/1.0 clients.
+
+ In order to remain persistent, all messages on the connection MUST
+ have a self-defined message length (i.e., one not defined by closure
+ of the connection), as described in section 4.4.
+
+8.1.2.2 Pipelining
+
+ A client that supports persistent connections MAY "pipeline" its
+ requests (i.e., send multiple requests without waiting for each
+ response). A server MUST send its responses to those requests in the
+ same order that the requests were received.
+
+ Clients which assume persistent connections and pipeline immediately
+ after connection establishment SHOULD be prepared to retry their
+ connection if the first pipelined attempt fails. If a client does
+ such a retry, it MUST NOT pipeline before it knows the connection is
+ persistent. Clients MUST also be prepared to resend their requests if
+ the server closes the connection before sending all of the
+ corresponding responses.
+
+ Clients SHOULD NOT pipeline requests using non-idempotent methods or
+ non-idempotent sequences of methods (see section 9.1.2). Otherwise, a
+ premature termination of the transport connection could lead to
+ indeterminate results. A client wishing to send a non-idempotent
+ request SHOULD wait to send that request until it has received the
+ response status for the previous request.
+
+8.1.3 Proxy Servers
+
+ It is especially important that proxies correctly implement the
+ properties of the Connection header field as specified in section
+ 14.10.
+
+ The proxy server MUST signal persistent connections separately with
+ its clients and the origin servers (or other proxy servers) that it
+ connects to. Each persistent connection applies to only one transport
+ link.
+
+ A proxy server MUST NOT establish a HTTP/1.1 persistent connection
+ with an HTTP/1.0 client (but see <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> [33] for information and
+ discussion of the problems with the Keep-Alive header implemented by
+ many HTTP/1.0 clients).
+
+8.1.4 Practical Considerations
+
+ Servers will usually have some time-out value beyond which they will
+ no longer maintain an inactive connection. Proxy servers might make
+ this a higher value since it is likely that the client will be making
+ more connections through the same server. The use of persistent
+ connections places no requirements on the length (or existence) of
+ this time-out for either the client or the server.
+
+ When a client or server wishes to time-out it SHOULD issue a graceful
+ close on the transport connection. Clients and servers SHOULD both
+ constantly watch for the other side of the transport close, and
+ respond to it as appropriate. If a client or server does not detect
+ the other side's close promptly it could cause unnecessary resource
+ drain on the network.
+
+ A client, server, or proxy MAY close the transport connection at any
+ time. For example, a client might have started to send a new request
+ at the same time that the server has decided to close the "idle"
+ connection. From the server's point of view, the connection is being
+ closed while it was idle, but from the client's point of view, a
+ request is in progress.
+
+ This means that clients, servers, and proxies MUST be able to recover
+ from asynchronous close events. Client software SHOULD reopen the
+ transport connection and retransmit the aborted sequence of requests
+ without user interaction so long as the request sequence is
+ idempotent (see section 9.1.2). Non-idempotent methods or sequences
+ MUST NOT be automatically retried, although user agents MAY offer a
+ human operator the choice of retrying the request(s). Confirmation by
+ user-agent software with semantic understanding of the application
+ MAY substitute for user confirmation. The automatic retry SHOULD NOT
+ be repeated if the second sequence of requests fails.
+
+ Servers SHOULD always respond to at least one request per connection,
+ if at all possible. Servers SHOULD NOT close a connection in the
+ middle of transmitting a response, unless a network or client failure
+ is suspected.
+
+ Clients that use persistent connections SHOULD limit the number of
+ simultaneous connections that they maintain to a given server. A
+ single-user client SHOULD NOT maintain more than 2 connections with
+ any server or proxy. A proxy SHOULD use up to 2*N connections to
+ another server or proxy, where N is the number of simultaneously
+ active users. These guidelines are intended to improve HTTP response
+ times and avoid congestion.
+
+8.2 Message Transmission Requirements
+
+8.2.1 Persistent Connections and Flow Control
+
+ HTTP/1.1 servers SHOULD maintain persistent connections and use TCP's
+ flow control mechanisms to resolve temporary overloads, rather than
+ terminating connections with the expectation that clients will retry.
+ The latter technique can exacerbate network congestion.
+
+8.2.2 Monitoring Connections for Error Status Messages
+
+ An HTTP/1.1 (or later) client sending a message-body SHOULD monitor
+ the network connection for an error status while it is transmitting
+ the request. If the client sees an error status, it SHOULD
+ immediately cease transmitting the body. If the body is being sent
+ using a "chunked" encoding (section 3.6), a zero length chunk and
+ empty trailer MAY be used to prematurely mark the end of the message.
+ If the body was preceded by a Content-Length header, the client MUST
+ close the connection.
+
+8.2.3 Use of the 100 (Continue) Status
+
+ The purpose of the 100 (Continue) status (see section 10.1.1) is to
+ allow a client that is sending a request message with a request body
+ to determine if the origin server is willing to accept the request
+ (based on the request headers) before the client sends the request
+ body. In some cases, it might either be inappropriate or highly
+ inefficient for the client to send the body if the server will reject
+ the message without looking at the body.
+
+ Requirements for HTTP/1.1 clients:
+
+ - If a client will wait for a 100 (Continue) response before
+ sending the request body, it MUST send an Expect request-header
+ field (section 14.20) with the "100-continue" expectation.
+
+ - A client MUST NOT send an Expect request-header field (section
+ 14.20) with the "100-continue" expectation if it does not intend
+ to send a request body.
+
+ Because of the presence of older implementations, the protocol allows
+ ambiguous situations in which a client may send "Expect: 100-
+ continue" without receiving either a 417 (Expectation Failed) status
+ or a 100 (Continue) status. Therefore, when a client sends this
+ header field to an origin server (possibly via a proxy) from which it
+ has never seen a 100 (Continue) status, the client SHOULD NOT wait
+ for an indefinite period before sending the request body.
+
+ Requirements for HTTP/1.1 origin servers:
+
+ - Upon receiving a request which includes an Expect request-header
+ field with the "100-continue" expectation, an origin server MUST
+ either respond with 100 (Continue) status and continue to read
+ from the input stream, or respond with a final status code. The
+ origin server MUST NOT wait for the request body before sending
+ the 100 (Continue) response. If it responds with a final status
+ code, it MAY close the transport connection or it MAY continue
+
+ to read and discard the rest of the request. It MUST NOT
+ perform the requested method if it returns a final status code.
+
+ - An origin server SHOULD NOT send a 100 (Continue) response if
+ the request message does not include an Expect request-header
+ field with the "100-continue" expectation, and MUST NOT send a
+ 100 (Continue) response if such a request comes from an HTTP/1.0
+ (or earlier) client. There is an exception to this rule: for
+ compatibility with <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>, a server MAY send a 100 (Continue)
+ status in response to an HTTP/1.1 PUT or POST request that does
+ not include an Expect request-header field with the "100-
+ continue" expectation. This exception, the purpose of which is
+ to minimize any client processing delays associated with an
+ undeclared wait for 100 (Continue) status, applies only to
+ HTTP/1.1 requests, and not to requests with any other HTTP-
+ version value.
+
+ - An origin server MAY omit a 100 (Continue) response if it has
+ already received some or all of the request body for the
+ corresponding request.
+
+ - An origin server that sends a 100 (Continue) response MUST
+ ultimately send a final status code, once the request body is
+ received and processed, unless it terminates the transport
+ connection prematurely.
+
+ - If an origin server receives a request that does not include an
+ Expect request-header field with the "100-continue" expectation,
+ the request includes a request body, and the server responds
+ with a final status code before reading the entire request body
+ from the transport connection, then the server SHOULD NOT close
+ the transport connection until it has read the entire request,
+ or until the client closes the connection. Otherwise, the client
+ might not reliably receive the response message. However, this
+ requirement is not be construed as preventing a server from
+ defending itself against denial-of-service attacks, or from
+ badly broken client implementations.
+
+ Requirements for HTTP/1.1 proxies:
+
+ - If a proxy receives a request that includes an Expect request-
+ header field with the "100-continue" expectation, and the proxy
+ either knows that the next-hop server complies with HTTP/1.1 or
+ higher, or does not know the HTTP version of the next-hop
+ server, it MUST forward the request, including the Expect header
+ field.
+
+ - If the proxy knows that the version of the next-hop server is
+ HTTP/1.0 or lower, it MUST NOT forward the request, and it MUST
+ respond with a 417 (Expectation Failed) status.
+
+ - Proxies SHOULD maintain a cache recording the HTTP version
+ numbers received from recently-referenced next-hop servers.
+
+ - A proxy MUST NOT forward a 100 (Continue) response if the
+ request message was received from an HTTP/1.0 (or earlier)
+ client and did not include an Expect request-header field with
+ the "100-continue" expectation. This requirement overrides the
+ general rule for forwarding of 1xx responses (see section 10.1).
+
+8.2.4 Client Behavior if Server Prematurely Closes Connection
+
+ If an HTTP/1.1 client sends a request which includes a request body,
+ but which does not include an Expect request-header field with the
+ "100-continue" expectation, and if the client is not directly
+ connected to an HTTP/1.1 origin server, and if the client sees the
+ connection close before receiving any status from the server, the
+ client SHOULD retry the request. If the client does retry this
+ request, it MAY use the following "binary exponential backoff"
+ algorithm to be assured of obtaining a reliable response:
+
+ 1. Initiate a new connection to the server
+
+ 2. Transmit the request-headers
+
+ 3. Initialize a variable R to the estimated round-trip time to the
+ server (e.g., based on the time it took to establish the
+ connection), or to a constant value of 5 seconds if the round-
+ trip time is not available.
+
+ 4. Compute T = R * (2**N), where N is the number of previous
+ retries of this request.
+
+ 5. Wait either for an error response from the server, or for T
+ seconds (whichever comes first)
+
+ 6. If no error response is received, after T seconds transmit the
+ body of the request.
+
+ 7. If client sees that the connection is closed prematurely,
+ repeat from step 1 until the request is accepted, an error
+ response is received, or the user becomes impatient and
+ terminates the retry process.
+
+ If at any point an error status is received, the client
+
+ - SHOULD NOT continue and
+
+ - SHOULD close the connection if it has not completed sending the
+ request message.
+
+9 Method Definitions
+
+ The set of common methods for HTTP/1.1 is defined below. Although
+ this set can be expanded, additional methods cannot be assumed to
+ share the same semantics for separately extended clients and servers.
+
+ The Host request-header field (section 14.23) MUST accompany all
+ HTTP/1.1 requests.
+
+9.1 Safe and Idempotent Methods
+
+9.1.1 Safe Methods
+
+ Implementors should be aware that the software represents the user in
+ their interactions over the Internet, and should be careful to allow
+ the user to be aware of any actions they might take which may have an
+ unexpected significance to themselves or others.
+
+ In particular, the convention has been established that the GET and
+ HEAD methods SHOULD NOT have the significance of taking an action
+ other than retrieval. These methods ought to be considered "safe".
+ This allows user agents to represent other methods, such as POST, PUT
+ and DELETE, in a special way, so that the user is made aware of the
+ fact that a possibly unsafe action is being requested.
+
+ Naturally, it is not possible to ensure that the server does not
+ generate side-effects as a result of performing a GET request; in
+ fact, some dynamic resources consider that a feature. The important
+ distinction here is that the user did not request the side-effects,
+ so therefore cannot be held accountable for them.
+
+9.1.2 Idempotent Methods
+
+ Methods can also have the property of "idempotence" in that (aside
+ from error or expiration issues) the side-effects of N &gt; 0 identical
+ requests is the same as for a single request. The methods GET, HEAD,
+ PUT and DELETE share this property. Also, the methods OPTIONS and
+ TRACE SHOULD NOT have side effects, and so are inherently idempotent.
+
+ However, it is possible that a sequence of several requests is non-
+ idempotent, even if all of the methods executed in that sequence are
+ idempotent. (A sequence is idempotent if a single execution of the
+ entire sequence always yields a result that is not changed by a
+ reexecution of all, or part, of that sequence.) For example, a
+ sequence is non-idempotent if its result depends on a value that is
+ later modified in the same sequence.
+
+ A sequence that never has side effects is idempotent, by definition
+ (provided that no concurrent operations are being executed on the
+ same set of resources).
+
+9.2 OPTIONS
+
+ The OPTIONS method represents a request for information about the
+ communication options available on the request/response chain
+ identified by the Request-URI. This method allows the client to
+ determine the options and/or requirements associated with a resource,
+ or the capabilities of a server, without implying a resource action
+ or initiating a resource retrieval.
+
+ Responses to this method are not cacheable.
+
+ If the OPTIONS request includes an entity-body (as indicated by the
+ presence of Content-Length or Transfer-Encoding), then the media type
+ MUST be indicated by a Content-Type field. Although this
+ specification does not define any use for such a body, future
+ extensions to HTTP might use the OPTIONS body to make more detailed
+ queries on the server. A server that does not support such an
+ extension MAY discard the request body.
+
+ If the Request-URI is an asterisk ("*"), the OPTIONS request is
+ intended to apply to the server in general rather than to a specific
+ resource. Since a server's communication options typically depend on
+ the resource, the "*" request is only useful as a "ping" or "no-op"
+ type of method; it does nothing beyond allowing the client to test
+ the capabilities of the server. For example, this can be used to test
+ a proxy for HTTP/1.1 compliance (or lack thereof).
+
+ If the Request-URI is not an asterisk, the OPTIONS request applies
+ only to the options that are available when communicating with that
+ resource.
+
+ A 200 response SHOULD include any header fields that indicate
+ optional features implemented by the server and applicable to that
+ resource (e.g., Allow), possibly including extensions not defined by
+ this specification. The response body, if any, SHOULD also include
+ information about the communication options. The format for such a
+
+ body is not defined by this specification, but might be defined by
+ future extensions to HTTP. Content negotiation MAY be used to select
+ the appropriate response format. If no response body is included, the
+ response MUST include a Content-Length field with a field-value of
+ "0".
+
+ The Max-Forwards request-header field MAY be used to target a
+ specific proxy in the request chain. When a proxy receives an OPTIONS
+ request on an absoluteURI for which request forwarding is permitted,
+ the proxy MUST check for a Max-Forwards field. If the Max-Forwards
+ field-value is zero ("0"), the proxy MUST NOT forward the message;
+ instead, the proxy SHOULD respond with its own communication options.
+ If the Max-Forwards field-value is an integer greater than zero, the
+ proxy MUST decrement the field-value when it forwards the request. If
+ no Max-Forwards field is present in the request, then the forwarded
+ request MUST NOT include a Max-Forwards field.
+
+9.3 GET
+
+ The GET method means retrieve whatever information (in the form of an
+ entity) is identified by the Request-URI. If the Request-URI refers
+ to a data-producing process, it is the produced data which shall be
+ returned as the entity in the response and not the source text of the
+ process, unless that text happens to be the output of the process.
+
+ The semantics of the GET method change to a "conditional GET" if the
+ request message includes an If-Modified-Since, If-Unmodified-Since,
+ If-Match, If-None-Match, or If-Range header field. A conditional GET
+ method requests that the entity be transferred only under the
+ circumstances described by the conditional header field(s). The
+ conditional GET method is intended to reduce unnecessary network
+ usage by allowing cached entities to be refreshed without requiring
+ multiple requests or transferring data already held by the client.
+
+ The semantics of the GET method change to a "partial GET" if the
+ request message includes a Range header field. A partial GET requests
+ that only part of the entity be transferred, as described in section
+ 14.35. The partial GET method is intended to reduce unnecessary
+ network usage by allowing partially-retrieved entities to be
+ completed without transferring data already held by the client.
+
+ The response to a GET request is cacheable if and only if it meets
+ the requirements for HTTP caching described in section 13.
+
+ See section 15.1.3 for security considerations when used for forms.
+
+9.4 HEAD
+
+ The HEAD method is identical to GET except that the server MUST NOT
+ return a message-body in the response. The metainformation contained
+ in the HTTP headers in response to a HEAD request SHOULD be identical
+ to the information sent in response to a GET request. This method can
+ be used for obtaining metainformation about the entity implied by the
+ request without transferring the entity-body itself. This method is
+ often used for testing hypertext links for validity, accessibility,
+ and recent modification.
+
+ The response to a HEAD request MAY be cacheable in the sense that the
+ information contained in the response MAY be used to update a
+ previously cached entity from that resource. If the new field values
+ indicate that the cached entity differs from the current entity (as
+ would be indicated by a change in Content-Length, Content-MD5, ETag
+ or Last-Modified), then the cache MUST treat the cache entry as
+ stale.
+
+9.5 POST
+
+ The POST method is used to request that the origin server accept the
+ entity enclosed in the request as a new subordinate of the resource
+ identified by the Request-URI in the Request-Line. POST is designed
+ to allow a uniform method to cover the following functions:
+
+ - Annotation of existing resources;
+
+ - Posting a message to a bulletin board, newsgroup, mailing list,
+ or similar group of articles;
+
+ - Providing a block of data, such as the result of submitting a
+ form, to a data-handling process;
+
+ - Extending a database through an append operation.
+
+ The actual function performed by the POST method is determined by the
+ server and is usually dependent on the Request-URI. The posted entity
+ is subordinate to that URI in the same way that a file is subordinate
+ to a directory containing it, a news article is subordinate to a
+ newsgroup to which it is posted, or a record is subordinate to a
+ database.
+
+ The action performed by the POST method might not result in a
+ resource that can be identified by a URI. In this case, either 200
+ (OK) or 204 (No Content) is the appropriate response status,
+ depending on whether or not the response includes an entity that
+ describes the result.
+
+ If a resource has been created on the origin server, the response
+ SHOULD be 201 (Created) and contain an entity which describes the
+ status of the request and refers to the new resource, and a Location
+ header (see section 14.30).
+
+ Responses to this method are not cacheable, unless the response
+ includes appropriate Cache-Control or Expires header fields. However,
+ the 303 (See Other) response can be used to direct the user agent to
+ retrieve a cacheable resource.
+
+ POST requests MUST obey the message transmission requirements set out
+ in section 8.2.
+
+ See section 15.1.3 for security considerations.
+
+9.6 PUT
+
+ The PUT method requests that the enclosed entity be stored under the
+ supplied Request-URI. If the Request-URI refers to an already
+ existing resource, the enclosed entity SHOULD be considered as a
+ modified version of the one residing on the origin server. If the
+ Request-URI does not point to an existing resource, and that URI is
+ capable of being defined as a new resource by the requesting user
+ agent, the origin server can create the resource with that URI. If a
+ new resource is created, the origin server MUST inform the user agent
+ via the 201 (Created) response. If an existing resource is modified,
+ either the 200 (OK) or 204 (No Content) response codes SHOULD be sent
+ to indicate successful completion of the request. If the resource
+ could not be created or modified with the Request-URI, an appropriate
+ error response SHOULD be given that reflects the nature of the
+ problem. The recipient of the entity MUST NOT ignore any Content-*
+ (e.g. Content-Range) headers that it does not understand or implement
+ and MUST return a 501 (Not Implemented) response in such cases.
+
+ If the request passes through a cache and the Request-URI identifies
+ one or more currently cached entities, those entries SHOULD be
+ treated as stale. Responses to this method are not cacheable.
+
+ The fundamental difference between the POST and PUT requests is
+ reflected in the different meaning of the Request-URI. The URI in a
+ POST request identifies the resource that will handle the enclosed
+ entity. That resource might be a data-accepting process, a gateway to
+ some other protocol, or a separate entity that accepts annotations.
+ In contrast, the URI in a PUT request identifies the entity enclosed
+ with the request -- the user agent knows what URI is intended and the
+ server MUST NOT attempt to apply the request to some other resource.
+ If the server desires that the request be applied to a different URI,
+
+ it MUST send a 301 (Moved Permanently) response; the user agent MAY
+ then make its own decision regarding whether or not to redirect the
+ request.
+
+ A single resource MAY be identified by many different URIs. For
+ example, an article might have a URI for identifying "the current
+ version" which is separate from the URI identifying each particular
+ version. In this case, a PUT request on a general URI might result in
+ several other URIs being defined by the origin server.
+
+ HTTP/1.1 does not define how a PUT method affects the state of an
+ origin server.
+
+ PUT requests MUST obey the message transmission requirements set out
+ in section 8.2.
+
+ Unless otherwise specified for a particular entity-header, the
+ entity-headers in the PUT request SHOULD be applied to the resource
+ created or modified by the PUT.
+
+9.7 DELETE
+
+ The DELETE method requests that the origin server delete the resource
+ identified by the Request-URI. This method MAY be overridden by human
+ intervention (or other means) on the origin server. The client cannot
+ be guaranteed that the operation has been carried out, even if the
+ status code returned from the origin server indicates that the action
+ has been completed successfully. However, the server SHOULD NOT
+ indicate success unless, at the time the response is given, it
+ intends to delete the resource or move it to an inaccessible
+ location.
+
+ A successful response SHOULD be 200 (OK) if the response includes an
+ entity describing the status, 202 (Accepted) if the action has not
+ yet been enacted, or 204 (No Content) if the action has been enacted
+ but the response does not include an entity.
+
+ If the request passes through a cache and the Request-URI identifies
+ one or more currently cached entities, those entries SHOULD be
+ treated as stale. Responses to this method are not cacheable.
+
+9.8 TRACE
+
+ The TRACE method is used to invoke a remote, application-layer loop-
+ back of the request message. The final recipient of the request
+ SHOULD reflect the message received back to the client as the
+ entity-body of a 200 (OK) response. The final recipient is either the
+
+ origin server or the first proxy or gateway to receive a Max-Forwards
+ value of zero (0) in the request (see section 14.31). A TRACE request
+ MUST NOT include an entity.
+
+ TRACE allows the client to see what is being received at the other
+ end of the request chain and use that data for testing or diagnostic
+ information. The value of the Via header field (section 14.45) is of
+ particular interest, since it acts as a trace of the request chain.
+ Use of the Max-Forwards header field allows the client to limit the
+ length of the request chain, which is useful for testing a chain of
+ proxies forwarding messages in an infinite loop.
+
+ If the request is valid, the response SHOULD contain the entire
+ request message in the entity-body, with a Content-Type of
+ "message/http". Responses to this method MUST NOT be cached.
+
+9.9 CONNECT
+
+ This specification reserves the method name CONNECT for use with a
+ proxy that can dynamically switch to being a tunnel (e.g. SSL
+ tunneling [44]).
+
+10 Status Code Definitions
+
+ Each Status-Code is described below, including a description of which
+ method(s) it can follow and any metainformation required in the
+ response.
+
+10.1 Informational 1xx
+
+ This class of status code indicates a provisional response,
+ consisting only of the Status-Line and optional headers, and is
+ terminated by an empty line. There are no required headers for this
+ class of status code. Since HTTP/1.0 did not define any 1xx status
+ codes, servers MUST NOT send a 1xx response to an HTTP/1.0 client
+ except under experimental conditions.
+
+ A client MUST be prepared to accept one or more 1xx status responses
+ prior to a regular response, even if the client does not expect a 100
+ (Continue) status message. Unexpected 1xx status responses MAY be
+ ignored by a user agent.
+
+ Proxies MUST forward 1xx responses, unless the connection between the
+ proxy and its client has been closed, or unless the proxy itself
+ requested the generation of the 1xx response. (For example, if a
+
+ proxy adds a "Expect: 100-continue" field when it forwards a request,
+ then it need not forward the corresponding 100 (Continue)
+ response(s).)
+
+10.1.1 100 Continue
+
+ The client SHOULD continue with its request. This interim response is
+ used to inform the client that the initial part of the request has
+ been received and has not yet been rejected by the server. The client
+ SHOULD continue by sending the remainder of the request or, if the
+ request has already been completed, ignore this response. The server
+ MUST send a final response after the request has been completed. See
+ section 8.2.3 for detailed discussion of the use and handling of this
+ status code.
+
+10.1.2 101 Switching Protocols
+
+ The server understands and is willing to comply with the client's
+ request, via the Upgrade message header field (section 14.42), for a
+ change in the application protocol being used on this connection. The
+ server will switch protocols to those defined by the response's
+ Upgrade header field immediately after the empty line which
+ terminates the 101 response.
+
+ The protocol SHOULD be switched only when it is advantageous to do
+ so. For example, switching to a newer version of HTTP is advantageous
+ over older versions, and switching to a real-time, synchronous
+ protocol might be advantageous when delivering resources that use
+ such features.
+
+10.2 Successful 2xx
+
+ This class of status code indicates that the client's request was
+ successfully received, understood, and accepted.
+
+10.2.1 200 OK
+
+ The request has succeeded. The information returned with the response
+ is dependent on the method used in the request, for example:
+
+ GET an entity corresponding to the requested resource is sent in
+ the response;
+
+ HEAD the entity-header fields corresponding to the requested
+ resource are sent in the response without any message-body;
+
+ POST an entity describing or containing the result of the action;
+
+ TRACE an entity containing the request message as received by the
+ end server.
+
+10.2.2 201 Created
+
+ The request has been fulfilled and resulted in a new resource being
+ created. The newly created resource can be referenced by the URI(s)
+ returned in the entity of the response, with the most specific URI
+ for the resource given by a Location header field. The response
+ SHOULD include an entity containing a list of resource
+ characteristics and location(s) from which the user or user agent can
+ choose the one most appropriate. The entity format is specified by
+ the media type given in the Content-Type header field. The origin
+ server MUST create the resource before returning the 201 status code.
+ If the action cannot be carried out immediately, the server SHOULD
+ respond with 202 (Accepted) response instead.
+
+ A 201 response MAY contain an ETag response header field indicating
+ the current value of the entity tag for the requested variant just
+ created, see section 14.19.
+
+10.2.3 202 Accepted
+
+ The request has been accepted for processing, but the processing has
+ not been completed. The request might or might not eventually be
+ acted upon, as it might be disallowed when processing actually takes
+ place. There is no facility for re-sending a status code from an
+ asynchronous operation such as this.
+
+ The 202 response is intentionally non-committal. Its purpose is to
+ allow a server to accept a request for some other process (perhaps a
+ batch-oriented process that is only run once per day) without
+ requiring that the user agent's connection to the server persist
+ until the process is completed. The entity returned with this
+ response SHOULD include an indication of the request's current status
+ and either a pointer to a status monitor or some estimate of when the
+ user can expect the request to be fulfilled.
+
+10.2.4 203 Non-Authoritative Information
+
+ The returned metainformation in the entity-header is not the
+ definitive set as available from the origin server, but is gathered
+ from a local or a third-party copy. The set presented MAY be a subset
+ or superset of the original version. For example, including local
+ annotation information about the resource might result in a superset
+ of the metainformation known by the origin server. Use of this
+ response code is not required and is only appropriate when the
+ response would otherwise be 200 (OK).
+
+10.2.5 204 No Content
+
+ The server has fulfilled the request but does not need to return an
+ entity-body, and might want to return updated metainformation. The
+ response MAY include new or updated metainformation in the form of
+ entity-headers, which if present SHOULD be associated with the
+ requested variant.
+
+ If the client is a user agent, it SHOULD NOT change its document view
+ from that which caused the request to be sent. This response is
+ primarily intended to allow input for actions to take place without
+ causing a change to the user agent's active document view, although
+ any new or updated metainformation SHOULD be applied to the document
+ currently in the user agent's active view.
+
+ The 204 response MUST NOT include a message-body, and thus is always
+ terminated by the first empty line after the header fields.
+
+10.2.6 205 Reset Content
+
+ The server has fulfilled the request and the user agent SHOULD reset
+ the document view which caused the request to be sent. This response
+ is primarily intended to allow input for actions to take place via
+ user input, followed by a clearing of the form in which the input is
+ given so that the user can easily initiate another input action. The
+ response MUST NOT include an entity.
+
+10.2.7 206 Partial Content
+
+ The server has fulfilled the partial GET request for the resource.
+ The request MUST have included a Range header field (section 14.35)
+ indicating the desired range, and MAY have included an If-Range
+ header field (section 14.27) to make the request conditional.
+
+ The response MUST include the following header fields:
+
+ - Either a Content-Range header field (section 14.16) indicating
+ the range included with this response, or a multipart/byteranges
+ Content-Type including Content-Range fields for each part. If a
+ Content-Length header field is present in the response, its
+ value MUST match the actual number of OCTETs transmitted in the
+ message-body.
+
+ - Date
+
+ - ETag and/or Content-Location, if the header would have been sent
+ in a 200 response to the same request
+
+ - Expires, Cache-Control, and/or Vary, if the field-value might
+ differ from that sent in any previous response for the same
+ variant
+
+ If the 206 response is the result of an If-Range request that used a
+ strong cache validator (see section 13.3.3), the response SHOULD NOT
+ include other entity-headers. If the response is the result of an
+ If-Range request that used a weak validator, the response MUST NOT
+ include other entity-headers; this prevents inconsistencies between
+ cached entity-bodies and updated headers. Otherwise, the response
+ MUST include all of the entity-headers that would have been returned
+ with a 200 (OK) response to the same request.
+
+ A cache MUST NOT combine a 206 response with other previously cached
+ content if the ETag or Last-Modified headers do not match exactly,
+ see 13.5.4.
+
+ A cache that does not support the Range and Content-Range headers
+ MUST NOT cache 206 (Partial) responses.
+
+10.3 Redirection 3xx
+
+ This class of status code indicates that further action needs to be
+ taken by the user agent in order to fulfill the request. The action
+ required MAY be carried out by the user agent without interaction
+ with the user if and only if the method used in the second request is
+ GET or HEAD. A client SHOULD detect infinite redirection loops, since
+ such loops generate network traffic for each redirection.
+
+ Note: previous versions of this specification recommended a
+ maximum of five redirections. Content developers should be aware
+ that there might be clients that implement such a fixed
+ limitation.
+
+10.3.1 300 Multiple Choices
+
+ The requested resource corresponds to any one of a set of
+ representations, each with its own specific location, and agent-
+ driven negotiation information (section 12) is being provided so that
+ the user (or user agent) can select a preferred representation and
+ redirect its request to that location.
+
+ Unless it was a HEAD request, the response SHOULD include an entity
+ containing a list of resource characteristics and location(s) from
+ which the user or user agent can choose the one most appropriate. The
+ entity format is specified by the media type given in the Content-
+ Type header field. Depending upon the format and the capabilities of
+
+ the user agent, selection of the most appropriate choice MAY be
+ performed automatically. However, this specification does not define
+ any standard for such automatic selection.
+
+ If the server has a preferred choice of representation, it SHOULD
+ include the specific URI for that representation in the Location
+ field; user agents MAY use the Location field value for automatic
+ redirection. This response is cacheable unless indicated otherwise.
+
+10.3.2 301 Moved Permanently
+
+ The requested resource has been assigned a new permanent URI and any
+ future references to this resource SHOULD use one of the returned
+ URIs. Clients with link editing capabilities ought to automatically
+ re-link references to the Request-URI to one or more of the new
+ references returned by the server, where possible. This response is
+ cacheable unless indicated otherwise.
+
+ The new permanent URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s).
+
+ If the 301 status code is received in response to a request other
+ than GET or HEAD, the user agent MUST NOT automatically redirect the
+ request unless it can be confirmed by the user, since this might
+ change the conditions under which the request was issued.
+
+ Note: When automatically redirecting a POST request after
+ receiving a 301 status code, some existing HTTP/1.0 user agents
+ will erroneously change it into a GET request.
+
+10.3.3 302 Found
+
+ The requested resource resides temporarily under a different URI.
+ Since the redirection might be altered on occasion, the client SHOULD
+ continue to use the Request-URI for future requests. This response
+ is only cacheable if indicated by a Cache-Control or Expires header
+ field.
+
+ The temporary URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s).
+
+ If the 302 status code is received in response to a request other
+ than GET or HEAD, the user agent MUST NOT automatically redirect the
+ request unless it can be confirmed by the user, since this might
+ change the conditions under which the request was issued.
+
+ Note: <a href="http://firefly.troll.no/rfcs/rfc1945.html">RFC 1945</a> and <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> specify that the client is not allowed
+ to change the method on the redirected request. However, most
+ existing user agent implementations treat 302 as if it were a 303
+ response, performing a GET on the Location field-value regardless
+ of the original request method. The status codes 303 and 307 have
+ been added for servers that wish to make unambiguously clear which
+ kind of reaction is expected of the client.
+
+10.3.4 303 See Other
+
+ The response to the request can be found under a different URI and
+ SHOULD be retrieved using a GET method on that resource. This method
+ exists primarily to allow the output of a POST-activated script to
+ redirect the user agent to a selected resource. The new URI is not a
+ substitute reference for the originally requested resource. The 303
+ response MUST NOT be cached, but the response to the second
+ (redirected) request might be cacheable.
+
+ The different URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s).
+
+ Note: Many pre-HTTP/1.1 user agents do not understand the 303
+ status. When interoperability with such clients is a concern, the
+ 302 status code may be used instead, since most user agents react
+ to a 302 response as described here for 303.
+
+10.3.5 304 Not Modified
+
+ If the client has performed a conditional GET request and access is
+ allowed, but the document has not been modified, the server SHOULD
+ respond with this status code. The 304 response MUST NOT contain a
+ message-body, and thus is always terminated by the first empty line
+ after the header fields.
+
+ The response MUST include the following header fields:
+
+ - Date, unless its omission is required by section 14.18.1
+
+ If a clockless origin server obeys these rules, and proxies and
+ clients add their own Date to any response received without one (as
+ already specified by [<a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>], section 14.19), caches will operate
+ correctly.
+
+ - ETag and/or Content-Location, if the header would have been sent
+ in a 200 response to the same request
+
+ - Expires, Cache-Control, and/or Vary, if the field-value might
+ differ from that sent in any previous response for the same
+ variant
+
+ If the conditional GET used a strong cache validator (see section
+ 13.3.3), the response SHOULD NOT include other entity-headers.
+ Otherwise (i.e., the conditional GET used a weak validator), the
+ response MUST NOT include other entity-headers; this prevents
+ inconsistencies between cached entity-bodies and updated headers.
+
+ If a 304 response indicates an entity not currently cached, then the
+ cache MUST disregard the response and repeat the request without the
+ conditional.
+
+ If a cache uses a received 304 response to update a cache entry, the
+ cache MUST update the entry to reflect any new field values given in
+ the response.
+
+10.3.6 305 Use Proxy
+
+ The requested resource MUST be accessed through the proxy given by
+ the Location field. The Location field gives the URI of the proxy.
+ The recipient is expected to repeat this single request via the
+ proxy. 305 responses MUST only be generated by origin servers.
+
+ Note: <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> was not clear that 305 was intended to redirect a
+ single request, and to be generated by origin servers only. Not
+ observing these limitations has significant security consequences.
+
+10.3.7 306 (Unused)
+
+ The 306 status code was used in a previous version of the
+ specification, is no longer used, and the code is reserved.
+
+10.3.8 307 Temporary Redirect
+
+ The requested resource resides temporarily under a different URI.
+ Since the redirection MAY be altered on occasion, the client SHOULD
+ continue to use the Request-URI for future requests. This response
+ is only cacheable if indicated by a Cache-Control or Expires header
+ field.
+
+ The temporary URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s) , since many pre-HTTP/1.1 user agents do not
+ understand the 307 status. Therefore, the note SHOULD contain the
+ information necessary for a user to repeat the original request on
+ the new URI.
+
+ If the 307 status code is received in response to a request other
+ than GET or HEAD, the user agent MUST NOT automatically redirect the
+ request unless it can be confirmed by the user, since this might
+ change the conditions under which the request was issued.
+
+10.4 Client Error 4xx
+
+ The 4xx class of status code is intended for cases in which the
+ client seems to have erred. Except when responding to a HEAD request,
+ the server SHOULD include an entity containing an explanation of the
+ error situation, and whether it is a temporary or permanent
+ condition. These status codes are applicable to any request method.
+ User agents SHOULD display any included entity to the user.
+
+ If the client is sending data, a server implementation using TCP
+ SHOULD be careful to ensure that the client acknowledges receipt of
+ the packet(s) containing the response, before the server closes the
+ input connection. If the client continues sending data to the server
+ after the close, the server's TCP stack will send a reset packet to
+ the client, which may erase the client's unacknowledged input buffers
+ before they can be read and interpreted by the HTTP application.
+
+10.4.1 400 Bad Request
+
+ The request could not be understood by the server due to malformed
+ syntax. The client SHOULD NOT repeat the request without
+ modifications.
+
+10.4.2 401 Unauthorized
+
+ The request requires user authentication. The response MUST include a
+ WWW-Authenticate header field (section 14.47) containing a challenge
+ applicable to the requested resource. The client MAY repeat the
+ request with a suitable Authorization header field (section 14.8). If
+ the request already included Authorization credentials, then the 401
+ response indicates that authorization has been refused for those
+ credentials. If the 401 response contains the same challenge as the
+ prior response, and the user agent has already attempted
+ authentication at least once, then the user SHOULD be presented the
+ entity that was given in the response, since that entity might
+ include relevant diagnostic information. HTTP access authentication
+ is explained in "HTTP Authentication: Basic and Digest Access
+ Authentication" [43].
+
+10.4.3 402 Payment Required
+
+ This code is reserved for future use.
+
+10.4.4 403 Forbidden
+
+ The server understood the request, but is refusing to fulfill it.
+ Authorization will not help and the request SHOULD NOT be repeated.
+ If the request method was not HEAD and the server wishes to make
+ public why the request has not been fulfilled, it SHOULD describe the
+ reason for the refusal in the entity. If the server does not wish to
+ make this information available to the client, the status code 404
+ (Not Found) can be used instead.
+
+10.4.5 404 Not Found
+
+ The server has not found anything matching the Request-URI. No
+ indication is given of whether the condition is temporary or
+ permanent. The 410 (Gone) status code SHOULD be used if the server
+ knows, through some internally configurable mechanism, that an old
+ resource is permanently unavailable and has no forwarding address.
+ This status code is commonly used when the server does not wish to
+ reveal exactly why the request has been refused, or when no other
+ response is applicable.
+
+10.4.6 405 Method Not Allowed
+
+ The method specified in the Request-Line is not allowed for the
+ resource identified by the Request-URI. The response MUST include an
+ Allow header containing a list of valid methods for the requested
+ resource.
+
+10.4.7 406 Not Acceptable
+
+ The resource identified by the request is only capable of generating
+ response entities which have content characteristics not acceptable
+ according to the accept headers sent in the request.
+
+ Unless it was a HEAD request, the response SHOULD include an entity
+ containing a list of available entity characteristics and location(s)
+ from which the user or user agent can choose the one most
+ appropriate. The entity format is specified by the media type given
+ in the Content-Type header field. Depending upon the format and the
+ capabilities of the user agent, selection of the most appropriate
+ choice MAY be performed automatically. However, this specification
+ does not define any standard for such automatic selection.
+
+ Note: HTTP/1.1 servers are allowed to return responses which are
+ not acceptable according to the accept headers sent in the
+ request. In some cases, this may even be preferable to sending a
+ 406 response. User agents are encouraged to inspect the headers of
+ an incoming response to determine if it is acceptable.
+
+ If the response could be unacceptable, a user agent SHOULD
+ temporarily stop receipt of more data and query the user for a
+ decision on further actions.
+
+10.4.8 407 Proxy Authentication Required
+
+ This code is similar to 401 (Unauthorized), but indicates that the
+ client must first authenticate itself with the proxy. The proxy MUST
+ return a Proxy-Authenticate header field (section 14.33) containing a
+ challenge applicable to the proxy for the requested resource. The
+ client MAY repeat the request with a suitable Proxy-Authorization
+ header field (section 14.34). HTTP access authentication is explained
+ in "HTTP Authentication: Basic and Digest Access Authentication"
+ [43].
+
+10.4.9 408 Request Timeout
+
+ The client did not produce a request within the time that the server
+ was prepared to wait. The client MAY repeat the request without
+ modifications at any later time.
+
+10.4.10 409 Conflict
+
+ The request could not be completed due to a conflict with the current
+ state of the resource. This code is only allowed in situations where
+ it is expected that the user might be able to resolve the conflict
+ and resubmit the request. The response body SHOULD include enough
+
+ information for the user to recognize the source of the conflict.
+ Ideally, the response entity would include enough information for the
+ user or user agent to fix the problem; however, that might not be
+ possible and is not required.
+
+ Conflicts are most likely to occur in response to a PUT request. For
+ example, if versioning were being used and the entity being PUT
+ included changes to a resource which conflict with those made by an
+ earlier (third-party) request, the server might use the 409 response
+ to indicate that it can't complete the request. In this case, the
+ response entity would likely contain a list of the differences
+ between the two versions in a format defined by the response
+ Content-Type.
+
+10.4.11 410 Gone
+
+ The requested resource is no longer available at the server and no
+ forwarding address is known. This condition is expected to be
+ considered permanent. Clients with link editing capabilities SHOULD
+ delete references to the Request-URI after user approval. If the
+ server does not know, or has no facility to determine, whether or not
+ the condition is permanent, the status code 404 (Not Found) SHOULD be
+ used instead. This response is cacheable unless indicated otherwise.
+
+ The 410 response is primarily intended to assist the task of web
+ maintenance by notifying the recipient that the resource is
+ intentionally unavailable and that the server owners desire that
+ remote links to that resource be removed. Such an event is common for
+ limited-time, promotional services and for resources belonging to
+ individuals no longer working at the server's site. It is not
+ necessary to mark all permanently unavailable resources as "gone" or
+ to keep the mark for any length of time -- that is left to the
+ discretion of the server owner.
+
+10.4.12 411 Length Required
+
+ The server refuses to accept the request without a defined Content-
+ Length. The client MAY repeat the request if it adds a valid
+ Content-Length header field containing the length of the message-body
+ in the request message.
+
+10.4.13 412 Precondition Failed
+
+ The precondition given in one or more of the request-header fields
+ evaluated to false when it was tested on the server. This response
+ code allows the client to place preconditions on the current resource
+ metainformation (header field data) and thus prevent the requested
+ method from being applied to a resource other than the one intended.
+
+10.4.14 413 Request Entity Too Large
+
+ The server is refusing to process a request because the request
+ entity is larger than the server is willing or able to process. The
+ server MAY close the connection to prevent the client from continuing
+ the request.
+
+ If the condition is temporary, the server SHOULD include a Retry-
+ After header field to indicate that it is temporary and after what
+ time the client MAY try again.
+
+10.4.15 414 Request-URI Too Long
+
+ The server is refusing to service the request because the Request-URI
+ is longer than the server is willing to interpret. This rare
+ condition is only likely to occur when a client has improperly
+ converted a POST request to a GET request with long query
+ information, when the client has descended into a URI "black hole" of
+ redirection (e.g., a redirected URI prefix that points to a suffix of
+ itself), or when the server is under attack by a client attempting to
+ exploit security holes present in some servers using fixed-length
+ buffers for reading or manipulating the Request-URI.
+
+10.4.16 415 Unsupported Media Type
+
+ The server is refusing to service the request because the entity of
+ the request is in a format not supported by the requested resource
+ for the requested method.
+
+10.4.17 416 Requested Range Not Satisfiable
+
+ A server SHOULD return a response with this status code if a request
+ included a Range request-header field (section 14.35), and none of
+ the range-specifier values in this field overlap the current extent
+ of the selected resource, and the request did not include an If-Range
+ request-header field. (For byte-ranges, this means that the first-
+ byte-pos of all of the byte-range-spec values were greater than the
+ current length of the selected resource.)
+
+ When this status code is returned for a byte-range request, the
+ response SHOULD include a Content-Range entity-header field
+ specifying the current length of the selected resource (see section
+ 14.16). This response MUST NOT use the multipart/byteranges content-
+ type.
+
+10.4.18 417 Expectation Failed
+
+ The expectation given in an Expect request-header field (see section
+ 14.20) could not be met by this server, or, if the server is a proxy,
+ the server has unambiguous evidence that the request could not be met
+ by the next-hop server.
+
+10.5 Server Error 5xx
+
+ Response status codes beginning with the digit "5" indicate cases in
+ which the server is aware that it has erred or is incapable of
+ performing the request. Except when responding to a HEAD request, the
+ server SHOULD include an entity containing an explanation of the
+ error situation, and whether it is a temporary or permanent
+ condition. User agents SHOULD display any included entity to the
+ user. These response codes are applicable to any request method.
+
+10.5.1 500 Internal Server Error
+
+ The server encountered an unexpected condition which prevented it
+ from fulfilling the request.
+
+10.5.2 501 Not Implemented
+
+ The server does not support the functionality required to fulfill the
+ request. This is the appropriate response when the server does not
+ recognize the request method and is not capable of supporting it for
+ any resource.
+
+10.5.3 502 Bad Gateway
+
+ The server, while acting as a gateway or proxy, received an invalid
+ response from the upstream server it accessed in attempting to
+ fulfill the request.
+
+10.5.4 503 Service Unavailable
+
+ The server is currently unable to handle the request due to a
+ temporary overloading or maintenance of the server. The implication
+ is that this is a temporary condition which will be alleviated after
+ some delay. If known, the length of the delay MAY be indicated in a
+ Retry-After header. If no Retry-After is given, the client SHOULD
+ handle the response as it would for a 500 response.
+
+ Note: The existence of the 503 status code does not imply that a
+ server must use it when becoming overloaded. Some servers may wish
+ to simply refuse the connection.
+
+10.5.5 504 Gateway Timeout
+
+ The server, while acting as a gateway or proxy, did not receive a
+ timely response from the upstream server specified by the URI (e.g.
+ HTTP, FTP, LDAP) or some other auxiliary server (e.g. DNS) it needed
+ to access in attempting to complete the request.
+
+ Note: Note to implementors: some deployed proxies are known to
+ return 400 or 500 when DNS lookups time out.
+
+10.5.6 505 HTTP Version Not Supported
+
+ The server does not support, or refuses to support, the HTTP protocol
+ version that was used in the request message. The server is
+ indicating that it is unable or unwilling to complete the request
+ using the same major version as the client, as described in section
+ 3.1, other than with this error message. The response SHOULD contain
+ an entity describing why that version is not supported and what other
+ protocols are supported by that server.
+
+11 Access Authentication
+
+ HTTP provides several OPTIONAL challenge-response authentication
+ mechanisms which can be used by a server to challenge a client
+ request and by a client to provide authentication information. The
+ general framework for access authentication, and the specification of
+ "basic" and "digest" authentication, are specified in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43]. This
+ specification adopts the definitions of "challenge" and "credentials"
+ from that specification.
+
+12 Content Negotiation
+
+ Most HTTP responses include an entity which contains information for
+ interpretation by a human user. Naturally, it is desirable to supply
+ the user with the "best available" entity corresponding to the
+ request. Unfortunately for servers and caches, not all users have the
+ same preferences for what is "best," and not all user agents are
+ equally capable of rendering all entity types. For that reason, HTTP
+ has provisions for several mechanisms for "content negotiation" --
+ the process of selecting the best representation for a given response
+ when there are multiple representations available.
+
+ Note: This is not called "format negotiation" because the
+ alternate representations may be of the same media type, but use
+ different capabilities of that type, be in different languages,
+ etc.
+
+ Any response containing an entity-body MAY be subject to negotiation,
+ including error responses.
+
+ There are two kinds of content negotiation which are possible in
+ HTTP: server-driven and agent-driven negotiation. These two kinds of
+ negotiation are orthogonal and thus may be used separately or in
+ combination. One method of combination, referred to as transparent
+ negotiation, occurs when a cache uses the agent-driven negotiation
+ information provided by the origin server in order to provide
+ server-driven negotiation for subsequent requests.
+
+12.1 Server-driven Negotiation
+
+ If the selection of the best representation for a response is made by
+ an algorithm located at the server, it is called server-driven
+ negotiation. Selection is based on the available representations of
+ the response (the dimensions over which it can vary; e.g. language,
+ content-coding, etc.) and the contents of particular header fields in
+ the request message or on other information pertaining to the request
+ (such as the network address of the client).
+
+ Server-driven negotiation is advantageous when the algorithm for
+ selecting from among the available representations is difficult to
+ describe to the user agent, or when the server desires to send its
+ "best guess" to the client along with the first response (hoping to
+ avoid the round-trip delay of a subsequent request if the "best
+ guess" is good enough for the user). In order to improve the server's
+ guess, the user agent MAY include request header fields (Accept,
+ Accept-Language, Accept-Encoding, etc.) which describe its
+ preferences for such a response.
+
+ Server-driven negotiation has disadvantages:
+
+ 1. It is impossible for the server to accurately determine what
+ might be "best" for any given user, since that would require
+ complete knowledge of both the capabilities of the user agent
+ and the intended use for the response (e.g., does the user want
+ to view it on screen or print it on paper?).
+
+ 2. Having the user agent describe its capabilities in every
+ request can be both very inefficient (given that only a small
+ percentage of responses have multiple representations) and a
+ potential violation of the user's privacy.
+
+ 3. It complicates the implementation of an origin server and the
+ algorithms for generating responses to a request.
+
+ 4. It may limit a public cache's ability to use the same response
+ for multiple user's requests.
+
+ HTTP/1.1 includes the following request-header fields for enabling
+ server-driven negotiation through description of user agent
+ capabilities and user preferences: Accept (section 14.1), Accept-
+ Charset (section 14.2), Accept-Encoding (section 14.3), Accept-
+ Language (section 14.4), and User-Agent (section 14.43). However, an
+ origin server is not limited to these dimensions and MAY vary the
+ response based on any aspect of the request, including information
+ outside the request-header fields or within extension header fields
+ not defined by this specification.
+
+ The Vary header field can be used to express the parameters the
+ server uses to select a representation that is subject to server-
+ driven negotiation. See section 13.6 for use of the Vary header field
+ by caches and section 14.44 for use of the Vary header field by
+ servers.
+
+12.2 Agent-driven Negotiation
+
+ With agent-driven negotiation, selection of the best representation
+ for a response is performed by the user agent after receiving an
+ initial response from the origin server. Selection is based on a list
+ of the available representations of the response included within the
+ header fields or entity-body of the initial response, with each
+ representation identified by its own URI. Selection from among the
+ representations may be performed automatically (if the user agent is
+ capable of doing so) or manually by the user selecting from a
+ generated (possibly hypertext) menu.
+
+ Agent-driven negotiation is advantageous when the response would vary
+ over commonly-used dimensions (such as type, language, or encoding),
+ when the origin server is unable to determine a user agent's
+ capabilities from examining the request, and generally when public
+ caches are used to distribute server load and reduce network usage.
+
+ Agent-driven negotiation suffers from the disadvantage of needing a
+ second request to obtain the best alternate representation. This
+ second request is only efficient when caching is used. In addition,
+ this specification does not define any mechanism for supporting
+ automatic selection, though it also does not prevent any such
+ mechanism from being developed as an extension and used within
+ HTTP/1.1.
+
+ HTTP/1.1 defines the 300 (Multiple Choices) and 406 (Not Acceptable)
+ status codes for enabling agent-driven negotiation when the server is
+ unwilling or unable to provide a varying response using server-driven
+ negotiation.
+
+12.3 Transparent Negotiation
+
+ Transparent negotiation is a combination of both server-driven and
+ agent-driven negotiation. When a cache is supplied with a form of the
+ list of available representations of the response (as in agent-driven
+ negotiation) and the dimensions of variance are completely understood
+ by the cache, then the cache becomes capable of performing server-
+ driven negotiation on behalf of the origin server for subsequent
+ requests on that resource.
+
+ Transparent negotiation has the advantage of distributing the
+ negotiation work that would otherwise be required of the origin
+ server and also removing the second request delay of agent-driven
+ negotiation when the cache is able to correctly guess the right
+ response.
+
+ This specification does not define any mechanism for transparent
+ negotiation, though it also does not prevent any such mechanism from
+ being developed as an extension that could be used within HTTP/1.1.
+
+13 Caching in HTTP
+
+ HTTP is typically used for distributed information systems, where
+ performance can be improved by the use of response caches. The
+ HTTP/1.1 protocol includes a number of elements intended to make
+ caching work as well as possible. Because these elements are
+ inextricable from other aspects of the protocol, and because they
+ interact with each other, it is useful to describe the basic caching
+ design of HTTP separately from the detailed descriptions of methods,
+ headers, response codes, etc.
+
+ Caching would be useless if it did not significantly improve
+ performance. The goal of caching in HTTP/1.1 is to eliminate the need
+ to send requests in many cases, and to eliminate the need to send
+ full responses in many other cases. The former reduces the number of
+ network round-trips required for many operations; we use an
+ "expiration" mechanism for this purpose (see section 13.2). The
+ latter reduces network bandwidth requirements; we use a "validation"
+ mechanism for this purpose (see section 13.3).
+
+ Requirements for performance, availability, and disconnected
+ operation require us to be able to relax the goal of semantic
+ transparency. The HTTP/1.1 protocol allows origin servers, caches,
+
+ and clients to explicitly reduce transparency when necessary.
+ However, because non-transparent operation may confuse non-expert
+ users, and might be incompatible with certain server applications
+ (such as those for ordering merchandise), the protocol requires that
+ transparency be relaxed
+
+ - only by an explicit protocol-level request when relaxed by
+ client or origin server
+
+ - only with an explicit warning to the end user when relaxed by
+ cache or client
+
+ Therefore, the HTTP/1.1 protocol provides these important elements:
+
+ 1. Protocol features that provide full semantic transparency when
+ this is required by all parties.
+
+ 2. Protocol features that allow an origin server or user agent to
+ explicitly request and control non-transparent operation.
+
+ 3. Protocol features that allow a cache to attach warnings to
+ responses that do not preserve the requested approximation of
+ semantic transparency.
+
+ A basic principle is that it must be possible for the clients to
+ detect any potential relaxation of semantic transparency.
+
+ Note: The server, cache, or client implementor might be faced with
+ design decisions not explicitly discussed in this specification.
+ If a decision might affect semantic transparency, the implementor
+ ought to err on the side of maintaining transparency unless a
+ careful and complete analysis shows significant benefits in
+ breaking transparency.
+
+13.1.1 Cache Correctness
+
+ A correct cache MUST respond to a request with the most up-to-date
+ response held by the cache that is appropriate to the request (see
+ sections 13.2.5, 13.2.6, and 13.12) which meets one of the following
+ conditions:
+
+ 1. It has been checked for equivalence with what the origin server
+ would have returned by revalidating the response with the
+ origin server (section 13.3);
+
+ 2. It is "fresh enough" (see section 13.2). In the default case,
+ this means it meets the least restrictive freshness requirement
+ of the client, origin server, and cache (see section 14.9); if
+ the origin server so specifies, it is the freshness requirement
+ of the origin server alone.
+
+ If a stored response is not "fresh enough" by the most
+ restrictive freshness requirement of both the client and the
+ origin server, in carefully considered circumstances the cache
+ MAY still return the response with the appropriate Warning
+ header (see section 13.1.5 and 14.46), unless such a response
+ is prohibited (e.g., by a "no-store" cache-directive, or by a
+ "no-cache" cache-request-directive; see section 14.9).
+
+ 3. It is an appropriate 304 (Not Modified), 305 (Proxy Redirect),
+ or error (4xx or 5xx) response message.
+
+ If the cache can not communicate with the origin server, then a
+ correct cache SHOULD respond as above if the response can be
+ correctly served from the cache; if not it MUST return an error or
+ warning indicating that there was a communication failure.
+
+ If a cache receives a response (either an entire response, or a 304
+ (Not Modified) response) that it would normally forward to the
+ requesting client, and the received response is no longer fresh, the
+ cache SHOULD forward it to the requesting client without adding a new
+ Warning (but without removing any existing Warning headers). A cache
+ SHOULD NOT attempt to revalidate a response simply because that
+ response became stale in transit; this might lead to an infinite
+ loop. A user agent that receives a stale response without a Warning
+ MAY display a warning indication to the user.
+
+13.1.2 Warnings
+
+ Whenever a cache returns a response that is neither first-hand nor
+ "fresh enough" (in the sense of condition 2 in section 13.1.1), it
+ MUST attach a warning to that effect, using a Warning general-header.
+ The Warning header and the currently defined warnings are described
+ in section 14.46. The warning allows clients to take appropriate
+ action.
+
+ Warnings MAY be used for other purposes, both cache-related and
+ otherwise. The use of a warning, rather than an error status code,
+ distinguish these responses from true failures.
+
+ Warnings are assigned three digit warn-codes. The first digit
+ indicates whether the Warning MUST or MUST NOT be deleted from a
+ stored cache entry after a successful revalidation:
+
+ 1xx Warnings that describe the freshness or revalidation status of
+ the response, and so MUST be deleted after a successful
+ revalidation. 1XX warn-codes MAY be generated by a cache only when
+ validating a cached entry. It MUST NOT be generated by clients.
+
+ 2xx Warnings that describe some aspect of the entity body or entity
+ headers that is not rectified by a revalidation (for example, a
+ lossy compression of the entity bodies) and which MUST NOT be
+ deleted after a successful revalidation.
+
+ See section 14.46 for the definitions of the codes themselves.
+
+ HTTP/1.0 caches will cache all Warnings in responses, without
+ deleting the ones in the first category. Warnings in responses that
+ are passed to HTTP/1.0 caches carry an extra warning-date field,
+ which prevents a future HTTP/1.1 recipient from believing an
+ erroneously cached Warning.
+
+ Warnings also carry a warning text. The text MAY be in any
+ appropriate natural language (perhaps based on the client's Accept
+ headers), and include an OPTIONAL indication of what character set is
+ used.
+
+ Multiple warnings MAY be attached to a response (either by the origin
+ server or by a cache), including multiple warnings with the same code
+ number. For example, a server might provide the same warning with
+ texts in both English and Basque.
+
+ When multiple warnings are attached to a response, it might not be
+ practical or reasonable to display all of them to the user. This
+ version of HTTP does not specify strict priority rules for deciding
+ which warnings to display and in what order, but does suggest some
+ heuristics.
+
+13.1.3 Cache-control Mechanisms
+
+ The basic cache mechanisms in HTTP/1.1 (server-specified expiration
+ times and validators) are implicit directives to caches. In some
+ cases, a server or client might need to provide explicit directives
+ to the HTTP caches. We use the Cache-Control header for this purpose.
+
+ The Cache-Control header allows a client or server to transmit a
+ variety of directives in either requests or responses. These
+ directives typically override the default caching algorithms. As a
+ general rule, if there is any apparent conflict between header
+ values, the most restrictive interpretation is applied (that is, the
+ one that is most likely to preserve semantic transparency). However,
+
+ in some cases, cache-control directives are explicitly specified as
+ weakening the approximation of semantic transparency (for example,
+ "max-stale" or "public").
+
+ The cache-control directives are described in detail in section 14.9.
+
+13.1.4 Explicit User Agent Warnings
+
+ Many user agents make it possible for users to override the basic
+ caching mechanisms. For example, the user agent might allow the user
+ to specify that cached entities (even explicitly stale ones) are
+ never validated. Or the user agent might habitually add "Cache-
+ Control: max-stale=3600" to every request. The user agent SHOULD NOT
+ default to either non-transparent behavior, or behavior that results
+ in abnormally ineffective caching, but MAY be explicitly configured
+ to do so by an explicit action of the user.
+
+ If the user has overridden the basic caching mechanisms, the user
+ agent SHOULD explicitly indicate to the user whenever this results in
+ the display of information that might not meet the server's
+ transparency requirements (in particular, if the displayed entity is
+ known to be stale). Since the protocol normally allows the user agent
+ to determine if responses are stale or not, this indication need only
+ be displayed when this actually happens. The indication need not be a
+ dialog box; it could be an icon (for example, a picture of a rotting
+ fish) or some other indicator.
+
+ If the user has overridden the caching mechanisms in a way that would
+ abnormally reduce the effectiveness of caches, the user agent SHOULD
+ continually indicate this state to the user (for example, by a
+ display of a picture of currency in flames) so that the user does not
+ inadvertently consume excess resources or suffer from excessive
+ latency.
+
+13.1.5 Exceptions to the Rules and Warnings
+
+ In some cases, the operator of a cache MAY choose to configure it to
+ return stale responses even when not requested by clients. This
+ decision ought not be made lightly, but may be necessary for reasons
+ of availability or performance, especially when the cache is poorly
+ connected to the origin server. Whenever a cache returns a stale
+ response, it MUST mark it as such (using a Warning header) enabling
+ the client software to alert the user that there might be a potential
+ problem.
+
+ It also allows the user agent to take steps to obtain a first-hand or
+ fresh response. For this reason, a cache SHOULD NOT return a stale
+ response if the client explicitly requests a first-hand or fresh one,
+ unless it is impossible to comply for technical or policy reasons.
+
+13.1.6 Client-controlled Behavior
+
+ While the origin server (and to a lesser extent, intermediate caches,
+ by their contribution to the age of a response) are the primary
+ source of expiration information, in some cases the client might need
+ to control a cache's decision about whether to return a cached
+ response without validating it. Clients do this using several
+ directives of the Cache-Control header.
+
+ A client's request MAY specify the maximum age it is willing to
+ accept of an unvalidated response; specifying a value of zero forces
+ the cache(s) to revalidate all responses. A client MAY also specify
+ the minimum time remaining before a response expires. Both of these
+ options increase constraints on the behavior of caches, and so cannot
+ further relax the cache's approximation of semantic transparency.
+
+ A client MAY also specify that it will accept stale responses, up to
+ some maximum amount of staleness. This loosens the constraints on the
+ caches, and so might violate the origin server's specified
+ constraints on semantic transparency, but might be necessary to
+ support disconnected operation, or high availability in the face of
+ poor connectivity.
+
+13.2 Expiration Model
+
+13.2.1 Server-Specified Expiration
+
+ HTTP caching works best when caches can entirely avoid making
+ requests to the origin server. The primary mechanism for avoiding
+ requests is for an origin server to provide an explicit expiration
+ time in the future, indicating that a response MAY be used to satisfy
+ subsequent requests. In other words, a cache can return a fresh
+ response without first contacting the server.
+
+ Our expectation is that servers will assign future explicit
+ expiration times to responses in the belief that the entity is not
+ likely to change, in a semantically significant way, before the
+ expiration time is reached. This normally preserves semantic
+ transparency, as long as the server's expiration times are carefully
+ chosen.
+
+ The expiration mechanism applies only to responses taken from a cache
+ and not to first-hand responses forwarded immediately to the
+ requesting client.
+
+ If an origin server wishes to force a semantically transparent cache
+ to validate every request, it MAY assign an explicit expiration time
+ in the past. This means that the response is always stale, and so the
+ cache SHOULD validate it before using it for subsequent requests. See
+ section 14.9.4 for a more restrictive way to force revalidation.
+
+ If an origin server wishes to force any HTTP/1.1 cache, no matter how
+ it is configured, to validate every request, it SHOULD use the "must-
+ revalidate" cache-control directive (see section 14.9).
+
+ Servers specify explicit expiration times using either the Expires
+ header, or the max-age directive of the Cache-Control header.
+
+ An expiration time cannot be used to force a user agent to refresh
+ its display or reload a resource; its semantics apply only to caching
+ mechanisms, and such mechanisms need only check a resource's
+ expiration status when a new request for that resource is initiated.
+ See section 13.13 for an explanation of the difference between caches
+ and history mechanisms.
+
+13.2.2 Heuristic Expiration
+
+ Since origin servers do not always provide explicit expiration times,
+ HTTP caches typically assign heuristic expiration times, employing
+ algorithms that use other header values (such as the Last-Modified
+ time) to estimate a plausible expiration time. The HTTP/1.1
+ specification does not provide specific algorithms, but does impose
+ worst-case constraints on their results. Since heuristic expiration
+ times might compromise semantic transparency, they ought to used
+ cautiously, and we encourage origin servers to provide explicit
+ expiration times as much as possible.
+
+13.2.3 Age Calculations
+
+ In order to know if a cached entry is fresh, a cache needs to know if
+ its age exceeds its freshness lifetime. We discuss how to calculate
+ the latter in section 13.2.4; this section describes how to calculate
+ the age of a response or cache entry.
+
+ In this discussion, we use the term "now" to mean "the current value
+ of the clock at the host performing the calculation." Hosts that use
+ HTTP, but especially hosts running origin servers and caches, SHOULD
+ use NTP [28] or some similar protocol to synchronize their clocks to
+ a globally accurate time standard.
+
+ HTTP/1.1 requires origin servers to send a Date header, if possible,
+ with every response, giving the time at which the response was
+ generated (see section 14.18). We use the term "date_value" to denote
+ the value of the Date header, in a form appropriate for arithmetic
+ operations.
+
+ HTTP/1.1 uses the Age response-header to convey the estimated age of
+ the response message when obtained from a cache. The Age field value
+ is the cache's estimate of the amount of time since the response was
+ generated or revalidated by the origin server.
+
+ In essence, the Age value is the sum of the time that the response
+ has been resident in each of the caches along the path from the
+ origin server, plus the amount of time it has been in transit along
+ network paths.
+
+ We use the term "age_value" to denote the value of the Age header, in
+ a form appropriate for arithmetic operations.
+
+ A response's age can be calculated in two entirely independent ways:
+
+ 1. now minus date_value, if the local clock is reasonably well
+ synchronized to the origin server's clock. If the result is
+ negative, the result is replaced by zero.
+
+ 2. age_value, if all of the caches along the response path
+ implement HTTP/1.1.
+
+ Given that we have two independent ways to compute the age of a
+ response when it is received, we can combine these as
+
+ corrected_received_age = max(now - date_value, age_value)
+
+ and as long as we have either nearly synchronized clocks or all-
+ HTTP/1.1 paths, one gets a reliable (conservative) result.
+
+ Because of network-imposed delays, some significant interval might
+ pass between the time that a server generates a response and the time
+ it is received at the next outbound cache or client. If uncorrected,
+ this delay could result in improperly low ages.
+
+ Because the request that resulted in the returned Age value must have
+ been initiated prior to that Age value's generation, we can correct
+ for delays imposed by the network by recording the time at which the
+ request was initiated. Then, when an Age value is received, it MUST
+ be interpreted relative to the time the request was initiated, not
+
+ the time that the response was received. This algorithm results in
+ conservative behavior no matter how much delay is experienced. So, we
+ compute:
+
+ corrected_initial_age = corrected_received_age
+ + (now - request_time)
+
+ where "request_time" is the time (according to the local clock) when
+ the request that elicited this response was sent.
+
+ Summary of age calculation algorithm, when a cache receives a
+ response:
+
+ /*
+ * age_value
+ * is the value of Age: header received by the cache with
+ * this response.
+ * date_value
+ * is the value of the origin server's Date: header
+ * request_time
+ * is the (local) time when the cache made the request
+ * that resulted in this cached response
+ * response_time
+ * is the (local) time when the cache received the
+ * response
+ * now
+ * is the current (local) time
+ */
+
+ apparent_age = max(0, response_time - date_value);
+ corrected_received_age = max(apparent_age, age_value);
+ response_delay = response_time - request_time;
+ corrected_initial_age = corrected_received_age + response_delay;
+ resident_time = now - response_time;
+ current_age = corrected_initial_age + resident_time;
+
+ The current_age of a cache entry is calculated by adding the amount
+ of time (in seconds) since the cache entry was last validated by the
+ origin server to the corrected_initial_age. When a response is
+ generated from a cache entry, the cache MUST include a single Age
+ header field in the response with a value equal to the cache entry's
+ current_age.
+
+ The presence of an Age header field in a response implies that a
+ response is not first-hand. However, the converse is not true, since
+ the lack of an Age header field in a response does not imply that the
+
+ response is first-hand unless all caches along the request path are
+ compliant with HTTP/1.1 (i.e., older HTTP caches did not implement
+ the Age header field).
+
+13.2.4 Expiration Calculations
+
+ In order to decide whether a response is fresh or stale, we need to
+ compare its freshness lifetime to its age. The age is calculated as
+ described in section 13.2.3; this section describes how to calculate
+ the freshness lifetime, and to determine if a response has expired.
+ In the discussion below, the values can be represented in any form
+ appropriate for arithmetic operations.
+
+ We use the term "expires_value" to denote the value of the Expires
+ header. We use the term "max_age_value" to denote an appropriate
+ value of the number of seconds carried by the "max-age" directive of
+ the Cache-Control header in a response (see section 14.9.3).
+
+ The max-age directive takes priority over Expires, so if max-age is
+ present in a response, the calculation is simply:
+
+ freshness_lifetime = max_age_value
+
+ Otherwise, if Expires is present in the response, the calculation is:
+
+ freshness_lifetime = expires_value - date_value
+
+ Note that neither of these calculations is vulnerable to clock skew,
+ since all of the information comes from the origin server.
+
+ If none of Expires, Cache-Control: max-age, or Cache-Control: s-
+ maxage (see section 14.9.3) appears in the response, and the response
+ does not include other restrictions on caching, the cache MAY compute
+ a freshness lifetime using a heuristic. The cache MUST attach Warning
+ 113 to any response whose age is more than 24 hours if such warning
+ has not already been added.
+
+ Also, if the response does have a Last-Modified time, the heuristic
+ expiration value SHOULD be no more than some fraction of the interval
+ since that time. A typical setting of this fraction might be 10%.
+
+ The calculation to determine if a response has expired is quite
+ simple:
+
+ response_is_fresh = (freshness_lifetime &gt; current_age)
+
+13.2.5 Disambiguating Expiration Values
+
+ Because expiration values are assigned optimistically, it is possible
+ for two caches to contain fresh values for the same resource that are
+ different.
+
+ If a client performing a retrieval receives a non-first-hand response
+ for a request that was already fresh in its own cache, and the Date
+ header in its existing cache entry is newer than the Date on the new
+ response, then the client MAY ignore the response. If so, it MAY
+ retry the request with a "Cache-Control: max-age=0" directive (see
+ section 14.9), to force a check with the origin server.
+
+ If a cache has two fresh responses for the same representation with
+ different validators, it MUST use the one with the more recent Date
+ header. This situation might arise because the cache is pooling
+ responses from other caches, or because a client has asked for a
+ reload or a revalidation of an apparently fresh cache entry.
+
+13.2.6 Disambiguating Multiple Responses
+
+ Because a client might be receiving responses via multiple paths, so
+ that some responses flow through one set of caches and other
+ responses flow through a different set of caches, a client might
+ receive responses in an order different from that in which the origin
+ server sent them. We would like the client to use the most recently
+ generated response, even if older responses are still apparently
+ fresh.
+
+ Neither the entity tag nor the expiration value can impose an
+ ordering on responses, since it is possible that a later response
+ intentionally carries an earlier expiration time. The Date values are
+ ordered to a granularity of one second.
+
+ When a client tries to revalidate a cache entry, and the response it
+ receives contains a Date header that appears to be older than the one
+ for the existing entry, then the client SHOULD repeat the request
+ unconditionally, and include
+
+ Cache-Control: max-age=0
+
+ to force any intermediate caches to validate their copies directly
+ with the origin server, or
+
+ Cache-Control: no-cache
+
+ to force any intermediate caches to obtain a new copy from the origin
+ server.
+
+ If the Date values are equal, then the client MAY use either response
+ (or MAY, if it is being extremely prudent, request a new response).
+ Servers MUST NOT depend on clients being able to choose
+ deterministically between responses generated during the same second,
+ if their expiration times overlap.
+
+13.3 Validation Model
+
+ When a cache has a stale entry that it would like to use as a
+ response to a client's request, it first has to check with the origin
+ server (or possibly an intermediate cache with a fresh response) to
+ see if its cached entry is still usable. We call this "validating"
+ the cache entry. Since we do not want to have to pay the overhead of
+ retransmitting the full response if the cached entry is good, and we
+ do not want to pay the overhead of an extra round trip if the cached
+ entry is invalid, the HTTP/1.1 protocol supports the use of
+ conditional methods.
+
+ The key protocol features for supporting conditional methods are
+ those concerned with "cache validators." When an origin server
+ generates a full response, it attaches some sort of validator to it,
+ which is kept with the cache entry. When a client (user agent or
+ proxy cache) makes a conditional request for a resource for which it
+ has a cache entry, it includes the associated validator in the
+ request.
+
+ The server then checks that validator against the current validator
+ for the entity, and, if they match (see section 13.3.3), it responds
+ with a special status code (usually, 304 (Not Modified)) and no
+ entity-body. Otherwise, it returns a full response (including
+ entity-body). Thus, we avoid transmitting the full response if the
+ validator matches, and we avoid an extra round trip if it does not
+ match.
+
+ In HTTP/1.1, a conditional request looks exactly the same as a normal
+ request for the same resource, except that it carries a special
+ header (which includes the validator) that implicitly turns the
+ method (usually, GET) into a conditional.
+
+ The protocol includes both positive and negative senses of cache-
+ validating conditions. That is, it is possible to request either that
+ a method be performed if and only if a validator matches or if and
+ only if no validators match.
+
+ Note: a response that lacks a validator may still be cached, and
+ served from cache until it expires, unless this is explicitly
+ prohibited by a cache-control directive. However, a cache cannot
+ do a conditional retrieval if it does not have a validator for the
+ entity, which means it will not be refreshable after it expires.
+
+13.3.1 Last-Modified Dates
+
+ The Last-Modified entity-header field value is often used as a cache
+ validator. In simple terms, a cache entry is considered to be valid
+ if the entity has not been modified since the Last-Modified value.
+
+13.3.2 Entity Tag Cache Validators
+
+ The ETag response-header field value, an entity tag, provides for an
+ "opaque" cache validator. This might allow more reliable validation
+ in situations where it is inconvenient to store modification dates,
+ where the one-second resolution of HTTP date values is not
+ sufficient, or where the origin server wishes to avoid certain
+ paradoxes that might arise from the use of modification dates.
+
+ Entity Tags are described in section 3.11. The headers used with
+ entity tags are described in sections 14.19, 14.24, 14.26 and 14.44.
+
+13.3.3 Weak and Strong Validators
+
+ Since both origin servers and caches will compare two validators to
+ decide if they represent the same or different entities, one normally
+ would expect that if the entity (the entity-body or any entity-
+ headers) changes in any way, then the associated validator would
+ change as well. If this is true, then we call this validator a
+ "strong validator."
+
+ However, there might be cases when a server prefers to change the
+ validator only on semantically significant changes, and not when
+ insignificant aspects of the entity change. A validator that does not
+ always change when the resource changes is a "weak validator."
+
+ Entity tags are normally "strong validators," but the protocol
+ provides a mechanism to tag an entity tag as "weak." One can think of
+ a strong validator as one that changes whenever the bits of an entity
+ changes, while a weak value changes whenever the meaning of an entity
+ changes. Alternatively, one can think of a strong validator as part
+ of an identifier for a specific entity, while a weak validator is
+ part of an identifier for a set of semantically equivalent entities.
+
+ Note: One example of a strong validator is an integer that is
+ incremented in stable storage every time an entity is changed.
+
+ An entity's modification time, if represented with one-second
+ resolution, could be a weak validator, since it is possible that
+ the resource might be modified twice during a single second.
+
+ Support for weak validators is optional. However, weak validators
+ allow for more efficient caching of equivalent objects; for
+ example, a hit counter on a site is probably good enough if it is
+ updated every few days or weeks, and any value during that period
+ is likely "good enough" to be equivalent.
+
+ A "use" of a validator is either when a client generates a request
+ and includes the validator in a validating header field, or when a
+ server compares two validators.
+
+ Strong validators are usable in any context. Weak validators are only
+ usable in contexts that do not depend on exact equality of an entity.
+ For example, either kind is usable for a conditional GET of a full
+ entity. However, only a strong validator is usable for a sub-range
+ retrieval, since otherwise the client might end up with an internally
+ inconsistent entity.
+
+ Clients MAY issue simple (non-subrange) GET requests with either weak
+ validators or strong validators. Clients MUST NOT use weak validators
+ in other forms of request.
+
+ The only function that the HTTP/1.1 protocol defines on validators is
+ comparison. There are two validator comparison functions, depending
+ on whether the comparison context allows the use of weak validators
+ or not:
+
+ - The strong comparison function: in order to be considered equal,
+ both validators MUST be identical in every way, and both MUST
+ NOT be weak.
+
+ - The weak comparison function: in order to be considered equal,
+ both validators MUST be identical in every way, but either or
+ both of them MAY be tagged as "weak" without affecting the
+ result.
+
+ An entity tag is strong unless it is explicitly tagged as weak.
+ Section 3.11 gives the syntax for entity tags.
+
+ A Last-Modified time, when used as a validator in a request, is
+ implicitly weak unless it is possible to deduce that it is strong,
+ using the following rules:
+
+ - The validator is being compared by an origin server to the
+ actual current validator for the entity and,
+
+ - That origin server reliably knows that the associated entity did
+ not change twice during the second covered by the presented
+ validator.
+
+ or
+
+ - The validator is about to be used by a client in an If-
+ Modified-Since or If-Unmodified-Since header, because the client
+ has a cache entry for the associated entity, and
+
+ - That cache entry includes a Date value, which gives the time
+ when the origin server sent the original response, and
+
+ - The presented Last-Modified time is at least 60 seconds before
+ the Date value.
+
+ or
+
+ - The validator is being compared by an intermediate cache to the
+ validator stored in its cache entry for the entity, and
+
+ - That cache entry includes a Date value, which gives the time
+ when the origin server sent the original response, and
+
+ - The presented Last-Modified time is at least 60 seconds before
+ the Date value.
+
+ This method relies on the fact that if two different responses were
+ sent by the origin server during the same second, but both had the
+ same Last-Modified time, then at least one of those responses would
+ have a Date value equal to its Last-Modified time. The arbitrary 60-
+ second limit guards against the possibility that the Date and Last-
+ Modified values are generated from different clocks, or at somewhat
+ different times during the preparation of the response. An
+ implementation MAY use a value larger than 60 seconds, if it is
+ believed that 60 seconds is too short.
+
+ If a client wishes to perform a sub-range retrieval on a value for
+ which it has only a Last-Modified time and no opaque validator, it
+ MAY do this only if the Last-Modified time is strong in the sense
+ described here.
+
+ A cache or origin server receiving a conditional request, other than
+ a full-body GET request, MUST use the strong comparison function to
+ evaluate the condition.
+
+ These rules allow HTTP/1.1 caches and clients to safely perform sub-
+ range retrievals on values that have been obtained from HTTP/1.0
+
+ servers.
+
+13.3.4 Rules for When to Use Entity Tags and Last-Modified Dates
+
+ We adopt a set of rules and recommendations for origin servers,
+ clients, and caches regarding when various validator types ought to
+ be used, and for what purposes.
+
+ HTTP/1.1 origin servers:
+
+ - SHOULD send an entity tag validator unless it is not feasible to
+ generate one.
+
+ - MAY send a weak entity tag instead of a strong entity tag, if
+ performance considerations support the use of weak entity tags,
+ or if it is unfeasible to send a strong entity tag.
+
+ - SHOULD send a Last-Modified value if it is feasible to send one,
+ unless the risk of a breakdown in semantic transparency that
+ could result from using this date in an If-Modified-Since header
+ would lead to serious problems.
+
+ In other words, the preferred behavior for an HTTP/1.1 origin server
+ is to send both a strong entity tag and a Last-Modified value.
+
+ In order to be legal, a strong entity tag MUST change whenever the
+ associated entity value changes in any way. A weak entity tag SHOULD
+ change whenever the associated entity changes in a semantically
+ significant way.
+
+ Note: in order to provide semantically transparent caching, an
+ origin server must avoid reusing a specific strong entity tag
+ value for two different entities, or reusing a specific weak
+ entity tag value for two semantically different entities. Cache
+ entries might persist for arbitrarily long periods, regardless of
+ expiration times, so it might be inappropriate to expect that a
+ cache will never again attempt to validate an entry using a
+ validator that it obtained at some point in the past.
+
+ HTTP/1.1 clients:
+
+ - If an entity tag has been provided by the origin server, MUST
+ use that entity tag in any cache-conditional request (using If-
+ Match or If-None-Match).
+
+ - If only a Last-Modified value has been provided by the origin
+ server, SHOULD use that value in non-subrange cache-conditional
+ requests (using If-Modified-Since).
+
+ - If only a Last-Modified value has been provided by an HTTP/1.0
+ origin server, MAY use that value in subrange cache-conditional
+ requests (using If-Unmodified-Since:). The user agent SHOULD
+ provide a way to disable this, in case of difficulty.
+
+ - If both an entity tag and a Last-Modified value have been
+ provided by the origin server, SHOULD use both validators in
+ cache-conditional requests. This allows both HTTP/1.0 and
+ HTTP/1.1 caches to respond appropriately.
+
+ An HTTP/1.1 origin server, upon receiving a conditional request that
+ includes both a Last-Modified date (e.g., in an If-Modified-Since or
+ If-Unmodified-Since header field) and one or more entity tags (e.g.,
+ in an If-Match, If-None-Match, or If-Range header field) as cache
+ validators, MUST NOT return a response status of 304 (Not Modified)
+ unless doing so is consistent with all of the conditional header
+ fields in the request.
+
+ An HTTP/1.1 caching proxy, upon receiving a conditional request that
+ includes both a Last-Modified date and one or more entity tags as
+ cache validators, MUST NOT return a locally cached response to the
+ client unless that cached response is consistent with all of the
+ conditional header fields in the request.
+
+ Note: The general principle behind these rules is that HTTP/1.1
+ servers and clients should transmit as much non-redundant
+ information as is available in their responses and requests.
+ HTTP/1.1 systems receiving this information will make the most
+ conservative assumptions about the validators they receive.
+
+ HTTP/1.0 clients and caches will ignore entity tags. Generally,
+ last-modified values received or used by these systems will
+ support transparent and efficient caching, and so HTTP/1.1 origin
+ servers should provide Last-Modified values. In those rare cases
+ where the use of a Last-Modified value as a validator by an
+ HTTP/1.0 system could result in a serious problem, then HTTP/1.1
+ origin servers should not provide one.
+
+13.3.5 Non-validating Conditionals
+
+ The principle behind entity tags is that only the service author
+ knows the semantics of a resource well enough to select an
+ appropriate cache validation mechanism, and the specification of any
+ validator comparison function more complex than byte-equality would
+ open up a can of worms. Thus, comparisons of any other headers
+ (except Last-Modified, for compatibility with HTTP/1.0) are never
+ used for purposes of validating a cache entry.
+
+13.4 Response Cacheability
+
+ Unless specifically constrained by a cache-control (section 14.9)
+ directive, a caching system MAY always store a successful response
+ (see section 13.8) as a cache entry, MAY return it without validation
+ if it is fresh, and MAY return it after successful validation. If
+ there is neither a cache validator nor an explicit expiration time
+ associated with a response, we do not expect it to be cached, but
+ certain caches MAY violate this expectation (for example, when little
+ or no network connectivity is available). A client can usually detect
+ that such a response was taken from a cache by comparing the Date
+ header to the current time.
+
+ Note: some HTTP/1.0 caches are known to violate this expectation
+ without providing any Warning.
+
+ However, in some cases it might be inappropriate for a cache to
+ retain an entity, or to return it in response to a subsequent
+ request. This might be because absolute semantic transparency is
+ deemed necessary by the service author, or because of security or
+ privacy considerations. Certain cache-control directives are
+ therefore provided so that the server can indicate that certain
+ resource entities, or portions thereof, are not to be cached
+ regardless of other considerations.
+
+ Note that section 14.8 normally prevents a shared cache from saving
+ and returning a response to a previous request if that request
+ included an Authorization header.
+
+ A response received with a status code of 200, 203, 206, 300, 301 or
+ 410 MAY be stored by a cache and used in reply to a subsequent
+ request, subject to the expiration mechanism, unless a cache-control
+ directive prohibits caching. However, a cache that does not support
+ the Range and Content-Range headers MUST NOT cache 206 (Partial
+ Content) responses.
+
+ A response received with any other status code (e.g. status codes 302
+ and 307) MUST NOT be returned in a reply to a subsequent request
+ unless there are cache-control directives or another header(s) that
+ explicitly allow it. For example, these include the following: an
+ Expires header (section 14.21); a "max-age", "s-maxage", "must-
+ revalidate", "proxy-revalidate", "public" or "private" cache-control
+ directive (section 14.9).
+
+13.5 Constructing Responses From Caches
+
+ The purpose of an HTTP cache is to store information received in
+ response to requests for use in responding to future requests. In
+ many cases, a cache simply returns the appropriate parts of a
+ response to the requester. However, if the cache holds a cache entry
+ based on a previous response, it might have to combine parts of a new
+ response with what is held in the cache entry.
+
+13.5.1 End-to-end and Hop-by-hop Headers
+
+ For the purpose of defining the behavior of caches and non-caching
+ proxies, we divide HTTP headers into two categories:
+
+ - End-to-end headers, which are transmitted to the ultimate
+ recipient of a request or response. End-to-end headers in
+ responses MUST be stored as part of a cache entry and MUST be
+ transmitted in any response formed from a cache entry.
+
+ - Hop-by-hop headers, which are meaningful only for a single
+ transport-level connection, and are not stored by caches or
+ forwarded by proxies.
+
+ The following HTTP/1.1 headers are hop-by-hop headers:
+
+ - Connection
+ - Keep-Alive
+ - Proxy-Authenticate
+ - Proxy-Authorization
+ - TE
+ - Trailers
+ - Transfer-Encoding
+ - Upgrade
+
+ All other headers defined by HTTP/1.1 are end-to-end headers.
+
+ Other hop-by-hop headers MUST be listed in a Connection header,
+ (section 14.10) to be introduced into HTTP/1.1 (or later).
+
+13.5.2 Non-modifiable Headers
+
+ Some features of the HTTP/1.1 protocol, such as Digest
+ Authentication, depend on the value of certain end-to-end headers. A
+ transparent proxy SHOULD NOT modify an end-to-end header unless the
+ definition of that header requires or specifically allows that.
+
+ A transparent proxy MUST NOT modify any of the following fields in a
+ request or response, and it MUST NOT add any of these fields if not
+ already present:
+
+ - Content-Location
+
+ - Content-MD5
+
+ - ETag
+
+ - Last-Modified
+
+ A transparent proxy MUST NOT modify any of the following fields in a
+ response:
+
+ - Expires
+
+ but it MAY add any of these fields if not already present. If an
+ Expires header is added, it MUST be given a field-value identical to
+ that of the Date header in that response.
+
+ A proxy MUST NOT modify or add any of the following fields in a
+ message that contains the no-transform cache-control directive, or in
+ any request:
+
+ - Content-Encoding
+
+ - Content-Range
+
+ - Content-Type
+
+ A non-transparent proxy MAY modify or add these fields to a message
+ that does not include no-transform, but if it does so, it MUST add a
+ Warning 214 (Transformation applied) if one does not already appear
+ in the message (see section 14.46).
+
+ Warning: unnecessary modification of end-to-end headers might
+ cause authentication failures if stronger authentication
+ mechanisms are introduced in later versions of HTTP. Such
+ authentication mechanisms MAY rely on the values of header fields
+ not listed here.
+
+ The Content-Length field of a request or response is added or deleted
+ according to the rules in section 4.4. A transparent proxy MUST
+ preserve the entity-length (section 7.2.2) of the entity-body,
+ although it MAY change the transfer-length (section 4.4).
+
+13.5.3 Combining Headers
+
+ When a cache makes a validating request to a server, and the server
+ provides a 304 (Not Modified) response or a 206 (Partial Content)
+ response, the cache then constructs a response to send to the
+ requesting client.
+
+ If the status code is 304 (Not Modified), the cache uses the entity-
+ body stored in the cache entry as the entity-body of this outgoing
+ response. If the status code is 206 (Partial Content) and the ETag or
+ Last-Modified headers match exactly, the cache MAY combine the
+ contents stored in the cache entry with the new contents received in
+ the response and use the result as the entity-body of this outgoing
+ response, (see 13.5.4).
+
+ The end-to-end headers stored in the cache entry are used for the
+ constructed response, except that
+
+ - any stored Warning headers with warn-code 1xx (see section
+ 14.46) MUST be deleted from the cache entry and the forwarded
+ response.
+
+ - any stored Warning headers with warn-code 2xx MUST be retained
+ in the cache entry and the forwarded response.
+
+ - any end-to-end headers provided in the 304 or 206 response MUST
+ replace the corresponding headers from the cache entry.
+
+ Unless the cache decides to remove the cache entry, it MUST also
+ replace the end-to-end headers stored with the cache entry with
+ corresponding headers received in the incoming response, except for
+ Warning headers as described immediately above. If a header field-
+ name in the incoming response matches more than one header in the
+ cache entry, all such old headers MUST be replaced.
+
+ In other words, the set of end-to-end headers received in the
+ incoming response overrides all corresponding end-to-end headers
+ stored with the cache entry (except for stored Warning headers with
+ warn-code 1xx, which are deleted even if not overridden).
+
+ Note: this rule allows an origin server to use a 304 (Not
+ Modified) or a 206 (Partial Content) response to update any header
+ associated with a previous response for the same entity or sub-
+ ranges thereof, although it might not always be meaningful or
+ correct to do so. This rule does not allow an origin server to use
+ a 304 (Not Modified) or a 206 (Partial Content) response to
+ entirely delete a header that it had provided with a previous
+ response.
+
+13.5.4 Combining Byte Ranges
+
+ A response might transfer only a subrange of the bytes of an entity-
+ body, either because the request included one or more Range
+ specifications, or because a connection was broken prematurely. After
+ several such transfers, a cache might have received several ranges of
+ the same entity-body.
+
+ If a cache has a stored non-empty set of subranges for an entity, and
+ an incoming response transfers another subrange, the cache MAY
+ combine the new subrange with the existing set if both the following
+ conditions are met:
+
+ - Both the incoming response and the cache entry have a cache
+ validator.
+
+ - The two cache validators match using the strong comparison
+ function (see section 13.3.3).
+
+ If either requirement is not met, the cache MUST use only the most
+ recent partial response (based on the Date values transmitted with
+ every response, and using the incoming response if these values are
+ equal or missing), and MUST discard the other partial information.
+
+13.6 Caching Negotiated Responses
+
+ Use of server-driven content negotiation (section 12.1), as indicated
+ by the presence of a Vary header field in a response, alters the
+ conditions and procedure by which a cache can use the response for
+ subsequent requests. See section 14.44 for use of the Vary header
+ field by servers.
+
+ A server SHOULD use the Vary header field to inform a cache of what
+ request-header fields were used to select among multiple
+ representations of a cacheable response subject to server-driven
+ negotiation. The set of header fields named by the Vary field value
+ is known as the "selecting" request-headers.
+
+ When the cache receives a subsequent request whose Request-URI
+ specifies one or more cache entries including a Vary header field,
+ the cache MUST NOT use such a cache entry to construct a response to
+ the new request unless all of the selecting request-headers present
+ in the new request match the corresponding stored request-headers in
+ the original request.
+
+ The selecting request-headers from two requests are defined to match
+ if and only if the selecting request-headers in the first request can
+ be transformed to the selecting request-headers in the second request
+
+ by adding or removing linear white space (LWS) at places where this
+ is allowed by the corresponding BNF, and/or combining multiple
+ message-header fields with the same field name following the rules
+ about message headers in section 4.2.
+
+ A Vary header field-value of "*" always fails to match and subsequent
+ requests on that resource can only be properly interpreted by the
+ origin server.
+
+ If the selecting request header fields for the cached entry do not
+ match the selecting request header fields of the new request, then
+ the cache MUST NOT use a cached entry to satisfy the request unless
+ it first relays the new request to the origin server in a conditional
+ request and the server responds with 304 (Not Modified), including an
+ entity tag or Content-Location that indicates the entity to be used.
+
+ If an entity tag was assigned to a cached representation, the
+ forwarded request SHOULD be conditional and include the entity tags
+ in an If-None-Match header field from all its cache entries for the
+ resource. This conveys to the server the set of entities currently
+ held by the cache, so that if any one of these entities matches the
+ requested entity, the server can use the ETag header field in its 304
+ (Not Modified) response to tell the cache which entry is appropriate.
+ If the entity-tag of the new response matches that of an existing
+ entry, the new response SHOULD be used to update the header fields of
+ the existing entry, and the result MUST be returned to the client.
+
+ If any of the existing cache entries contains only partial content
+ for the associated entity, its entity-tag SHOULD NOT be included in
+ the If-None-Match header field unless the request is for a range that
+ would be fully satisfied by that entry.
+
+ If a cache receives a successful response whose Content-Location
+ field matches that of an existing cache entry for the same Request-
+ ]URI, whose entity-tag differs from that of the existing entry, and
+ whose Date is more recent than that of the existing entry, the
+ existing entry SHOULD NOT be returned in response to future requests
+ and SHOULD be deleted from the cache.
+
+13.7 Shared and Non-Shared Caches
+
+ For reasons of security and privacy, it is necessary to make a
+ distinction between "shared" and "non-shared" caches. A non-shared
+ cache is one that is accessible only to a single user. Accessibility
+ in this case SHOULD be enforced by appropriate security mechanisms.
+ All other caches are considered to be "shared." Other sections of
+
+ this specification place certain constraints on the operation of
+ shared caches in order to prevent loss of privacy or failure of
+ access controls.
+
+13.8 Errors or Incomplete Response Cache Behavior
+
+ A cache that receives an incomplete response (for example, with fewer
+ bytes of data than specified in a Content-Length header) MAY store
+ the response. However, the cache MUST treat this as a partial
+ response. Partial responses MAY be combined as described in section
+ 13.5.4; the result might be a full response or might still be
+ partial. A cache MUST NOT return a partial response to a client
+ without explicitly marking it as such, using the 206 (Partial
+ Content) status code. A cache MUST NOT return a partial response
+ using a status code of 200 (OK).
+
+ If a cache receives a 5xx response while attempting to revalidate an
+ entry, it MAY either forward this response to the requesting client,
+ or act as if the server failed to respond. In the latter case, it MAY
+ return a previously received response unless the cached entry
+ includes the "must-revalidate" cache-control directive (see section
+ 14.9).
+
+13.9 Side Effects of GET and HEAD
+
+ Unless the origin server explicitly prohibits the caching of their
+ responses, the application of GET and HEAD methods to any resources
+ SHOULD NOT have side effects that would lead to erroneous behavior if
+ these responses are taken from a cache. They MAY still have side
+ effects, but a cache is not required to consider such side effects in
+ its caching decisions. Caches are always expected to observe an
+ origin server's explicit restrictions on caching.
+
+ We note one exception to this rule: since some applications have
+ traditionally used GETs and HEADs with query URLs (those containing a
+ "?" in the rel_path part) to perform operations with significant side
+ effects, caches MUST NOT treat responses to such URIs as fresh unless
+ the server provides an explicit expiration time. This specifically
+ means that responses from HTTP/1.0 servers for such URIs SHOULD NOT
+ be taken from a cache. See section 9.1.1 for related information.
+
+13.10 Invalidation After Updates or Deletions
+
+ The effect of certain methods performed on a resource at the origin
+ server might cause one or more existing cache entries to become non-
+ transparently invalid. That is, although they might continue to be
+ "fresh," they do not accurately reflect what the origin server would
+ return for a new request on that resource.
+
+ There is no way for the HTTP protocol to guarantee that all such
+ cache entries are marked invalid. For example, the request that
+ caused the change at the origin server might not have gone through
+ the proxy where a cache entry is stored. However, several rules help
+ reduce the likelihood of erroneous behavior.
+
+ In this section, the phrase "invalidate an entity" means that the
+ cache will either remove all instances of that entity from its
+ storage, or will mark these as "invalid" and in need of a mandatory
+ revalidation before they can be returned in response to a subsequent
+ request.
+
+ Some HTTP methods MUST cause a cache to invalidate an entity. This is
+ either the entity referred to by the Request-URI, or by the Location
+ or Content-Location headers (if present). These methods are:
+
+ - PUT
+
+ - DELETE
+
+ - POST
+
+ In order to prevent denial of service attacks, an invalidation based
+ on the URI in a Location or Content-Location header MUST only be
+ performed if the host part is the same as in the Request-URI.
+
+ A cache that passes through requests for methods it does not
+ understand SHOULD invalidate any entities referred to by the
+ Request-URI.
+
+13.11 Write-Through Mandatory
+
+ All methods that might be expected to cause modifications to the
+ origin server's resources MUST be written through to the origin
+ server. This currently includes all methods except for GET and HEAD.
+ A cache MUST NOT reply to such a request from a client before having
+ transmitted the request to the inbound server, and having received a
+ corresponding response from the inbound server. This does not prevent
+ a proxy cache from sending a 100 (Continue) response before the
+ inbound server has sent its final reply.
+
+ The alternative (known as "write-back" or "copy-back" caching) is not
+ allowed in HTTP/1.1, due to the difficulty of providing consistent
+ updates and the problems arising from server, cache, or network
+ failure prior to write-back.
+
+13.12 Cache Replacement
+
+ If a new cacheable (see sections 14.9.2, 13.2.5, 13.2.6 and 13.8)
+ response is received from a resource while any existing responses for
+ the same resource are cached, the cache SHOULD use the new response
+ to reply to the current request. It MAY insert it into cache storage
+ and MAY, if it meets all other requirements, use it to respond to any
+ future requests that would previously have caused the old response to
+ be returned. If it inserts the new response into cache storage the
+ rules in section 13.5.3 apply.
+
+ Note: a new response that has an older Date header value than
+ existing cached responses is not cacheable.
+
+13.13 History Lists
+
+ User agents often have history mechanisms, such as "Back" buttons and
+ history lists, which can be used to redisplay an entity retrieved
+ earlier in a session.
+
+ History mechanisms and caches are different. In particular history
+ mechanisms SHOULD NOT try to show a semantically transparent view of
+ the current state of a resource. Rather, a history mechanism is meant
+ to show exactly what the user saw at the time when the resource was
+ retrieved.
+
+ By default, an expiration time does not apply to history mechanisms.
+ If the entity is still in storage, a history mechanism SHOULD display
+ it even if the entity has expired, unless the user has specifically
+ configured the agent to refresh expired history documents.
+
+ This is not to be construed to prohibit the history mechanism from
+ telling the user that a view might be stale.
+
+ Note: if history list mechanisms unnecessarily prevent users from
+ viewing stale resources, this will tend to force service authors
+ to avoid using HTTP expiration controls and cache controls when
+ they would otherwise like to. Service authors may consider it
+ important that users not be presented with error messages or
+ warning messages when they use navigation controls (such as BACK)
+ to view previously fetched resources. Even though sometimes such
+ resources ought not to cached, or ought to expire quickly, user
+ interface considerations may force service authors to resort to
+ other means of preventing caching (e.g. "once-only" URLs) in order
+ not to suffer the effects of improperly functioning history
+ mechanisms.
+
+14 Header Field Definitions
+
+ This section defines the syntax and semantics of all standard
+ HTTP/1.1 header fields. For entity-header fields, both sender and
+ recipient refer to either the client or the server, depending on who
+ sends and who receives the entity.
+
+14.1 Accept
+
+ The Accept request-header field can be used to specify certain media
+ types which are acceptable for the response. Accept headers can be
+ used to indicate that the request is specifically limited to a small
+ set of desired types, as in the case of a request for an in-line
+ image.
+
+ Accept = "Accept" ":"
+ #( media-range [ accept-params ] )
+
+ media-range = ( "*/*"
+ | ( type "/" "*" )
+ | ( type "/" subtype )
+ ) *( ";" parameter )
+ accept-params = ";" "q" "=" qvalue *( accept-extension )
+ accept-extension = ";" token [ "=" ( token | quoted-string ) ]
+
+ The asterisk "*" character is used to group media types into ranges,
+ with "*/*" indicating all media types and "type/*" indicating all
+ subtypes of that type. The media-range MAY include media type
+ parameters that are applicable to that range.
+
+ Each media-range MAY be followed by one or more accept-params,
+ beginning with the "q" parameter for indicating a relative quality
+ factor. The first "q" parameter (if any) separates the media-range
+ parameter(s) from the accept-params. Quality factors allow the user
+ or user agent to indicate the relative degree of preference for that
+ media-range, using the qvalue scale from 0 to 1 (section 3.9). The
+ default value is q=1.
+
+ Note: Use of the "q" parameter name to separate media type
+ parameters from Accept extension parameters is due to historical
+ practice. Although this prevents any media type parameter named
+ "q" from being used with a media range, such an event is believed
+ to be unlikely given the lack of any "q" parameters in the IANA
+ media type registry and the rare usage of any media type
+ parameters in Accept. Future media types are discouraged from
+ registering any parameter named "q".
+
+ The example
+
+ Accept: audio/*; q=0.2, audio/basic
+
+ SHOULD be interpreted as "I prefer audio/basic, but send me any audio
+ type if it is the best available after an 80% mark-down in quality."
+
+ If no Accept header field is present, then it is assumed that the
+ client accepts all media types. If an Accept header field is present,
+ and if the server cannot send a response which is acceptable
+ according to the combined Accept field value, then the server SHOULD
+ send a 406 (not acceptable) response.
+
+ A more elaborate example is
+
+ Accept: text/plain; q=0.5, text/html,
+ text/x-dvi; q=0.8, text/x-c
+
+ Verbally, this would be interpreted as "text/html and text/x-c are
+ the preferred media types, but if they do not exist, then send the
+ text/x-dvi entity, and if that does not exist, send the text/plain
+ entity."
+
+ Media ranges can be overridden by more specific media ranges or
+ specific media types. If more than one media range applies to a given
+ type, the most specific reference has precedence. For example,
+
+ Accept: text/*, text/html, text/html;level=1, */*
+
+ have the following precedence:
+
+ 1) text/html;level=1
+ 2) text/html
+ 3) text/*
+ 4) */*
+
+ The media type quality factor associated with a given type is
+ determined by finding the media range with the highest precedence
+ which matches that type. For example,
+
+ Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
+ text/html;level=2;q=0.4, */*;q=0.5
+
+ would cause the following values to be associated:
+
+ text/html;level=1 = 1
+ text/html = 0.7
+ text/plain = 0.3
+
+ image/jpeg = 0.5
+ text/html;level=2 = 0.4
+ text/html;level=3 = 0.7
+
+ Note: A user agent might be provided with a default set of quality
+ values for certain media ranges. However, unless the user agent is
+ a closed system which cannot interact with other rendering agents,
+ this default set ought to be configurable by the user.
+
+14.2 Accept-Charset
+
+ The Accept-Charset request-header field can be used to indicate what
+ character sets are acceptable for the response. This field allows
+ clients capable of understanding more comprehensive or special-
+ purpose character sets to signal that capability to a server which is
+ capable of representing documents in those character sets.
+
+ Accept-Charset = "Accept-Charset" ":"
+ 1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
+
+ Character set values are described in section 3.4. Each charset MAY
+ be given an associated quality value which represents the user's
+ preference for that charset. The default value is q=1. An example is
+
+ Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
+
+ The special value "*", if present in the Accept-Charset field,
+ matches every character set (including ISO-8859-1) which is not
+ mentioned elsewhere in the Accept-Charset field. If no "*" is present
+ in an Accept-Charset field, then all character sets not explicitly
+ mentioned get a quality value of 0, except for ISO-8859-1, which gets
+ a quality value of 1 if not explicitly mentioned.
+
+ If no Accept-Charset header is present, the default is that any
+ character set is acceptable. If an Accept-Charset header is present,
+ and if the server cannot send a response which is acceptable
+ according to the Accept-Charset header, then the server SHOULD send
+ an error response with the 406 (not acceptable) status code, though
+ the sending of an unacceptable response is also allowed.
+
+14.3 Accept-Encoding
+
+ The Accept-Encoding request-header field is similar to Accept, but
+ restricts the content-codings (section 3.5) that are acceptable in
+ the response.
+
+ Accept-Encoding = "Accept-Encoding" ":"
+
+ 1#( codings [ ";" "q" "=" qvalue ] )
+ codings = ( content-coding | "*" )
+
+ Examples of its use are:
+
+ Accept-Encoding: compress, gzip
+ Accept-Encoding:
+ Accept-Encoding: *
+ Accept-Encoding: compress;q=0.5, gzip;q=1.0
+ Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
+
+ A server tests whether a content-coding is acceptable, according to
+ an Accept-Encoding field, using these rules:
+
+ 1. If the content-coding is one of the content-codings listed in
+ the Accept-Encoding field, then it is acceptable, unless it is
+ accompanied by a qvalue of 0. (As defined in section 3.9, a
+ qvalue of 0 means "not acceptable.")
+
+ 2. The special "*" symbol in an Accept-Encoding field matches any
+ available content-coding not explicitly listed in the header
+ field.
+
+ 3. If multiple content-codings are acceptable, then the acceptable
+ content-coding with the highest non-zero qvalue is preferred.
+
+ 4. The "identity" content-coding is always acceptable, unless
+ specifically refused because the Accept-Encoding field includes
+ "identity;q=0", or because the field includes "*;q=0" and does
+ not explicitly include the "identity" content-coding. If the
+ Accept-Encoding field-value is empty, then only the "identity"
+ encoding is acceptable.
+
+ If an Accept-Encoding field is present in a request, and if the
+ server cannot send a response which is acceptable according to the
+ Accept-Encoding header, then the server SHOULD send an error response
+ with the 406 (Not Acceptable) status code.
+
+ If no Accept-Encoding field is present in a request, the server MAY
+ assume that the client will accept any content coding. In this case,
+ if "identity" is one of the available content-codings, then the
+ server SHOULD use the "identity" content-coding, unless it has
+ additional information that a different content-coding is meaningful
+ to the client.
+
+ Note: If the request does not include an Accept-Encoding field,
+ and if the "identity" content-coding is unavailable, then
+ content-codings commonly understood by HTTP/1.0 clients (i.e.,
+
+ "gzip" and "compress") are preferred; some older clients
+ improperly display messages sent with other content-codings. The
+ server might also make this decision based on information about
+ the particular user-agent or client.
+
+ Note: Most HTTP/1.0 applications do not recognize or obey qvalues
+ associated with content-codings. This means that qvalues will not
+ work and are not permitted with x-gzip or x-compress.
+
+14.4 Accept-Language
+
+ The Accept-Language request-header field is similar to Accept, but
+ restricts the set of natural languages that are preferred as a
+ response to the request. Language tags are defined in section 3.10.
+
+ Accept-Language = "Accept-Language" ":"
+ 1#( language-range [ ";" "q" "=" qvalue ] )
+ language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
+
+ Each language-range MAY be given an associated quality value which
+ represents an estimate of the user's preference for the languages
+ specified by that range. The quality value defaults to "q=1". For
+ example,
+
+ Accept-Language: da, en-gb;q=0.8, en;q=0.7
+
+ would mean: "I prefer Danish, but will accept British English and
+ other types of English." A language-range matches a language-tag if
+ it exactly equals the tag, or if it exactly equals a prefix of the
+ tag such that the first tag character following the prefix is "-".
+ The special range "*", if present in the Accept-Language field,
+ matches every tag not matched by any other range present in the
+ Accept-Language field.
+
+ Note: This use of a prefix matching rule does not imply that
+ language tags are assigned to languages in such a way that it is
+ always true that if a user understands a language with a certain
+ tag, then this user will also understand all languages with tags
+ for which this tag is a prefix. The prefix rule simply allows the
+ use of prefix tags if this is the case.
+
+ The language quality factor assigned to a language-tag by the
+ Accept-Language field is the quality value of the longest language-
+ range in the field that matches the language-tag. If no language-
+ range in the field matches the tag, the language quality factor
+ assigned is 0. If no Accept-Language header is present in the
+ request, the server
+
+ SHOULD assume that all languages are equally acceptable. If an
+ Accept-Language header is present, then all languages which are
+ assigned a quality factor greater than 0 are acceptable.
+
+ It might be contrary to the privacy expectations of the user to send
+ an Accept-Language header with the complete linguistic preferences of
+ the user in every request. For a discussion of this issue, see
+ section 15.1.4.
+
+ As intelligibility is highly dependent on the individual user, it is
+ recommended that client applications make the choice of linguistic
+ preference available to the user. If the choice is not made
+ available, then the Accept-Language header field MUST NOT be given in
+ the request.
+
+ Note: When making the choice of linguistic preference available to
+ the user, we remind implementors of the fact that users are not
+ familiar with the details of language matching as described above,
+ and should provide appropriate guidance. As an example, users
+ might assume that on selecting "en-gb", they will be served any
+ kind of English document if British English is not available. A
+ user agent might suggest in such a case to add "en" to get the
+ best matching behavior.
+
+14.5 Accept-Ranges
+
+ The Accept-Ranges response-header field allows the server to
+ indicate its acceptance of range requests for a resource:
+
+ Accept-Ranges = "Accept-Ranges" ":" acceptable-ranges
+ acceptable-ranges = 1#range-unit | "none"
+
+ Origin servers that accept byte-range requests MAY send
+
+ Accept-Ranges: bytes
+
+ but are not required to do so. Clients MAY generate byte-range
+ requests without having received this header for the resource
+ involved. Range units are defined in section 3.12.
+
+ Servers that do not accept any kind of range request for a
+ resource MAY send
+
+ Accept-Ranges: none
+
+ to advise the client not to attempt a range request.
+
+14.6 Age
+
+ The Age response-header field conveys the sender's estimate of the
+ amount of time since the response (or its revalidation) was
+ generated at the origin server. A cached response is "fresh" if
+ its age does not exceed its freshness lifetime. Age values are
+ calculated as specified in section 13.2.3.
+
+ Age = "Age" ":" age-value
+ age-value = delta-seconds
+
+ Age values are non-negative decimal integers, representing time in
+ seconds.
+
+ If a cache receives a value larger than the largest positive
+ integer it can represent, or if any of its age calculations
+ overflows, it MUST transmit an Age header with a value of
+ 2147483648 (2^31). An HTTP/1.1 server that includes a cache MUST
+ include an Age header field in every response generated from its
+ own cache. Caches SHOULD use an arithmetic type of at least 31
+ bits of range.
+
+14.7 Allow
+
+ The Allow entity-header field lists the set of methods supported
+ by the resource identified by the Request-URI. The purpose of this
+ field is strictly to inform the recipient of valid methods
+ associated with the resource. An Allow header field MUST be
+ present in a 405 (Method Not Allowed) response.
+
+ Allow = "Allow" ":" #Method
+
+ Example of use:
+
+ Allow: GET, HEAD, PUT
+
+ This field cannot prevent a client from trying other methods.
+ However, the indications given by the Allow header field value
+ SHOULD be followed. The actual set of allowed methods is defined
+ by the origin server at the time of each request.
+
+ The Allow header field MAY be provided with a PUT request to
+ recommend the methods to be supported by the new or modified
+ resource. The server is not required to support these methods and
+ SHOULD include an Allow header in the response giving the actual
+ supported methods.
+
+ A proxy MUST NOT modify the Allow header field even if it does not
+ understand all the methods specified, since the user agent might
+ have other means of communicating with the origin server.
+
+14.8 Authorization
+
+ A user agent that wishes to authenticate itself with a server--
+ usually, but not necessarily, after receiving a 401 response--does
+ so by including an Authorization request-header field with the
+ request. The Authorization field value consists of credentials
+ containing the authentication information of the user agent for
+ the realm of the resource being requested.
+
+ Authorization = "Authorization" ":" credentials
+
+ HTTP access authentication is described in "HTTP Authentication:
+ Basic and Digest Access Authentication" [43]. If a request is
+ authenticated and a realm specified, the same credentials SHOULD
+ be valid for all other requests within this realm (assuming that
+ the authentication scheme itself does not require otherwise, such
+ as credentials that vary according to a challenge value or using
+ synchronized clocks).
+
+ When a shared cache (see section 13.7) receives a request
+ containing an Authorization field, it MUST NOT return the
+ corresponding response as a reply to any other request, unless one
+ of the following specific exceptions holds:
+
+ 1. If the response includes the "s-maxage" cache-control
+ directive, the cache MAY use that response in replying to a
+ subsequent request. But (if the specified maximum age has
+ passed) a proxy cache MUST first revalidate it with the origin
+ server, using the request-headers from the new request to allow
+ the origin server to authenticate the new request. (This is the
+ defined behavior for s-maxage.) If the response includes "s-
+ maxage=0", the proxy MUST always revalidate it before re-using
+ it.
+
+ 2. If the response includes the "must-revalidate" cache-control
+ directive, the cache MAY use that response in replying to a
+ subsequent request. But if the response is stale, all caches
+ MUST first revalidate it with the origin server, using the
+ request-headers from the new request to allow the origin server
+ to authenticate the new request.
+
+ 3. If the response includes the "public" cache-control directive,
+ it MAY be returned in reply to any subsequent request.
+
+14.9 Cache-Control
+
+ The Cache-Control general-header field is used to specify directives
+ that MUST be obeyed by all caching mechanisms along the
+ request/response chain. The directives specify behavior intended to
+ prevent caches from adversely interfering with the request or
+ response. These directives typically override the default caching
+ algorithms. Cache directives are unidirectional in that the presence
+ of a directive in a request does not imply that the same directive is
+ to be given in the response.
+
+ Note that HTTP/1.0 caches might not implement Cache-Control and
+ might only implement Pragma: no-cache (see section 14.32).
+
+ Cache directives MUST be passed through by a proxy or gateway
+ application, regardless of their significance to that application,
+ since the directives might be applicable to all recipients along the
+ request/response chain. It is not possible to specify a cache-
+ directive for a specific cache.
+
+ Cache-Control = "Cache-Control" ":" 1#cache-directive
+
+ cache-directive = cache-request-directive
+ | cache-response-directive
+
+ cache-request-directive =
+ "no-cache" ; Section 14.9.1
+ | "no-store" ; Section 14.9.2
+ | "max-age" "=" delta-seconds ; Section 14.9.3, 14.9.4
+ | "max-stale" [ "=" delta-seconds ] ; Section 14.9.3
+ | "min-fresh" "=" delta-seconds ; Section 14.9.3
+ | "no-transform" ; Section 14.9.5
+ | "only-if-cached" ; Section 14.9.4
+ | cache-extension ; Section 14.9.6
+
+ cache-response-directive =
+ "public" ; Section 14.9.1
+ | "private" [ "=" &lt;"&gt; 1#field-name &lt;"&gt; ] ; Section 14.9.1
+ | "no-cache" [ "=" &lt;"&gt; 1#field-name &lt;"&gt; ]; Section 14.9.1
+ | "no-store" ; Section 14.9.2
+ | "no-transform" ; Section 14.9.5
+ | "must-revalidate" ; Section 14.9.4
+ | "proxy-revalidate" ; Section 14.9.4
+ | "max-age" "=" delta-seconds ; Section 14.9.3
+ | "s-maxage" "=" delta-seconds ; Section 14.9.3
+ | cache-extension ; Section 14.9.6
+
+ cache-extension = token [ "=" ( token | quoted-string ) ]
+
+ When a directive appears without any 1#field-name parameter, the
+ directive applies to the entire request or response. When such a
+ directive appears with a 1#field-name parameter, it applies only to
+ the named field or fields, and not to the rest of the request or
+ response. This mechanism supports extensibility; implementations of
+ future versions of the HTTP protocol might apply these directives to
+ header fields not defined in HTTP/1.1.
+
+ The cache-control directives can be broken down into these general
+ categories:
+
+ - Restrictions on what are cacheable; these may only be imposed by
+ the origin server.
+
+ - Restrictions on what may be stored by a cache; these may be
+ imposed by either the origin server or the user agent.
+
+ - Modifications of the basic expiration mechanism; these may be
+ imposed by either the origin server or the user agent.
+
+ - Controls over cache revalidation and reload; these may only be
+ imposed by a user agent.
+
+ - Control over transformation of entities.
+
+ - Extensions to the caching system.
+
+14.9.1 What is Cacheable
+
+ By default, a response is cacheable if the requirements of the
+ request method, request header fields, and the response status
+ indicate that it is cacheable. Section 13.4 summarizes these defaults
+ for cacheability. The following Cache-Control response directives
+ allow an origin server to override the default cacheability of a
+ response:
+
+ public
+ Indicates that the response MAY be cached by any cache, even if it
+ would normally be non-cacheable or cacheable only within a non-
+ shared cache. (See also Authorization, section 14.8, for
+ additional details.)
+
+ private
+ Indicates that all or part of the response message is intended for
+ a single user and MUST NOT be cached by a shared cache. This
+ allows an origin server to state that the specified parts of the
+
+ response are intended for only one user and are not a valid
+ response for requests by other users. A private (non-shared) cache
+ MAY cache the response.
+
+ Note: This usage of the word private only controls where the
+ response may be cached, and cannot ensure the privacy of the
+ message content.
+
+ no-cache
+ If the no-cache directive does not specify a field-name, then a
+ cache MUST NOT use the response to satisfy a subsequent request
+ without successful revalidation with the origin server. This
+ allows an origin server to prevent caching even by caches that
+ have been configured to return stale responses to client requests.
+
+ If the no-cache directive does specify one or more field-names,
+ then a cache MAY use the response to satisfy a subsequent request,
+ subject to any other restrictions on caching. However, the
+ specified field-name(s) MUST NOT be sent in the response to a
+ subsequent request without successful revalidation with the origin
+ server. This allows an origin server to prevent the re-use of
+ certain header fields in a response, while still allowing caching
+ of the rest of the response.
+
+ Note: Most HTTP/1.0 caches will not recognize or obey this
+ directive.
+
+14.9.2 What May be Stored by Caches
+
+ no-store
+ The purpose of the no-store directive is to prevent the
+ inadvertent release or retention of sensitive information (for
+ example, on backup tapes). The no-store directive applies to the
+ entire message, and MAY be sent either in a response or in a
+ request. If sent in a request, a cache MUST NOT store any part of
+ either this request or any response to it. If sent in a response,
+ a cache MUST NOT store any part of either this response or the
+ request that elicited it. This directive applies to both non-
+ shared and shared caches. "MUST NOT store" in this context means
+ that the cache MUST NOT intentionally store the information in
+ non-volatile storage, and MUST make a best-effort attempt to
+ remove the information from volatile storage as promptly as
+ possible after forwarding it.
+
+ Even when this directive is associated with a response, users
+ might explicitly store such a response outside of the caching
+ system (e.g., with a "Save As" dialog). History buffers MAY store
+ such responses as part of their normal operation.
+
+ The purpose of this directive is to meet the stated requirements
+ of certain users and service authors who are concerned about
+ accidental releases of information via unanticipated accesses to
+ cache data structures. While the use of this directive might
+ improve privacy in some cases, we caution that it is NOT in any
+ way a reliable or sufficient mechanism for ensuring privacy. In
+ particular, malicious or compromised caches might not recognize or
+ obey this directive, and communications networks might be
+ vulnerable to eavesdropping.
+
+14.9.3 Modifications of the Basic Expiration Mechanism
+
+ The expiration time of an entity MAY be specified by the origin
+ server using the Expires header (see section 14.21). Alternatively,
+ it MAY be specified using the max-age directive in a response. When
+ the max-age cache-control directive is present in a cached response,
+ the response is stale if its current age is greater than the age
+ value given (in seconds) at the time of a new request for that
+ resource. The max-age directive on a response implies that the
+ response is cacheable (i.e., "public") unless some other, more
+ restrictive cache directive is also present.
+
+ If a response includes both an Expires header and a max-age
+ directive, the max-age directive overrides the Expires header, even
+ if the Expires header is more restrictive. This rule allows an origin
+ server to provide, for a given response, a longer expiration time to
+ an HTTP/1.1 (or later) cache than to an HTTP/1.0 cache. This might be
+ useful if certain HTTP/1.0 caches improperly calculate ages or
+ expiration times, perhaps due to desynchronized clocks.
+
+ Many HTTP/1.0 cache implementations will treat an Expires value that
+ is less than or equal to the response Date value as being equivalent
+ to the Cache-Control response directive "no-cache". If an HTTP/1.1
+ cache receives such a response, and the response does not include a
+ Cache-Control header field, it SHOULD consider the response to be
+ non-cacheable in order to retain compatibility with HTTP/1.0 servers.
+
+ Note: An origin server might wish to use a relatively new HTTP
+ cache control feature, such as the "private" directive, on a
+ network including older caches that do not understand that
+ feature. The origin server will need to combine the new feature
+ with an Expires field whose value is less than or equal to the
+ Date value. This will prevent older caches from improperly
+ caching the response.
+
+ s-maxage
+ If a response includes an s-maxage directive, then for a shared
+ cache (but not for a private cache), the maximum age specified by
+ this directive overrides the maximum age specified by either the
+ max-age directive or the Expires header. The s-maxage directive
+ also implies the semantics of the proxy-revalidate directive (see
+ section 14.9.4), i.e., that the shared cache must not use the
+ entry after it becomes stale to respond to a subsequent request
+ without first revalidating it with the origin server. The s-
+ maxage directive is always ignored by a private cache.
+
+ Note that most older caches, not compliant with this specification,
+ do not implement any cache-control directives. An origin server
+ wishing to use a cache-control directive that restricts, but does not
+ prevent, caching by an HTTP/1.1-compliant cache MAY exploit the
+ requirement that the max-age directive overrides the Expires header,
+ and the fact that pre-HTTP/1.1-compliant caches do not observe the
+ max-age directive.
+
+ Other directives allow a user agent to modify the basic expiration
+ mechanism. These directives MAY be specified on a request:
+
+ max-age
+ Indicates that the client is willing to accept a response whose
+ age is no greater than the specified time in seconds. Unless max-
+ stale directive is also included, the client is not willing to
+ accept a stale response.
+
+ min-fresh
+ Indicates that the client is willing to accept a response whose
+ freshness lifetime is no less than its current age plus the
+ specified time in seconds. That is, the client wants a response
+ that will still be fresh for at least the specified number of
+ seconds.
+
+ max-stale
+ Indicates that the client is willing to accept a response that has
+ exceeded its expiration time. If max-stale is assigned a value,
+ then the client is willing to accept a response that has exceeded
+ its expiration time by no more than the specified number of
+ seconds. If no value is assigned to max-stale, then the client is
+ willing to accept a stale response of any age.
+
+ If a cache returns a stale response, either because of a max-stale
+ directive on a request, or because the cache is configured to
+ override the expiration time of a response, the cache MUST attach a
+ Warning header to the stale response, using Warning 110 (Response is
+ stale).
+
+ A cache MAY be configured to return stale responses without
+ validation, but only if this does not conflict with any "MUST"-level
+ requirements concerning cache validation (e.g., a "must-revalidate"
+ cache-control directive).
+
+ If both the new request and the cached entry include "max-age"
+ directives, then the lesser of the two values is used for determining
+ the freshness of the cached entry for that request.
+
+14.9.4 Cache Revalidation and Reload Controls
+
+ Sometimes a user agent might want or need to insist that a cache
+ revalidate its cache entry with the origin server (and not just with
+ the next cache along the path to the origin server), or to reload its
+ cache entry from the origin server. End-to-end revalidation might be
+ necessary if either the cache or the origin server has overestimated
+ the expiration time of the cached response. End-to-end reload may be
+ necessary if the cache entry has become corrupted for some reason.
+
+ End-to-end revalidation may be requested either when the client does
+ not have its own local cached copy, in which case we call it
+ "unspecified end-to-end revalidation", or when the client does have a
+ local cached copy, in which case we call it "specific end-to-end
+ revalidation."
+
+ The client can specify these three kinds of action using Cache-
+ Control request directives:
+
+ End-to-end reload
+ The request includes a "no-cache" cache-control directive or, for
+ compatibility with HTTP/1.0 clients, "Pragma: no-cache". Field
+ names MUST NOT be included with the no-cache directive in a
+ request. The server MUST NOT use a cached copy when responding to
+ such a request.
+
+ Specific end-to-end revalidation
+ The request includes a "max-age=0" cache-control directive, which
+ forces each cache along the path to the origin server to
+ revalidate its own entry, if any, with the next cache or server.
+ The initial request includes a cache-validating conditional with
+ the client's current validator.
+
+ Unspecified end-to-end revalidation
+ The request includes "max-age=0" cache-control directive, which
+ forces each cache along the path to the origin server to
+ revalidate its own entry, if any, with the next cache or server.
+ The initial request does not include a cache-validating
+
+ conditional; the first cache along the path (if any) that holds a
+ cache entry for this resource includes a cache-validating
+ conditional with its current validator.
+
+ max-age
+ When an intermediate cache is forced, by means of a max-age=0
+ directive, to revalidate its own cache entry, and the client has
+ supplied its own validator in the request, the supplied validator
+ might differ from the validator currently stored with the cache
+ entry. In this case, the cache MAY use either validator in making
+ its own request without affecting semantic transparency.
+
+ However, the choice of validator might affect performance. The
+ best approach is for the intermediate cache to use its own
+ validator when making its request. If the server replies with 304
+ (Not Modified), then the cache can return its now validated copy
+ to the client with a 200 (OK) response. If the server replies with
+ a new entity and cache validator, however, the intermediate cache
+ can compare the returned validator with the one provided in the
+ client's request, using the strong comparison function. If the
+ client's validator is equal to the origin server's, then the
+ intermediate cache simply returns 304 (Not Modified). Otherwise,
+ it returns the new entity with a 200 (OK) response.
+
+ If a request includes the no-cache directive, it SHOULD NOT
+ include min-fresh, max-stale, or max-age.
+
+ only-if-cached
+ In some cases, such as times of extremely poor network
+ connectivity, a client may want a cache to return only those
+ responses that it currently has stored, and not to reload or
+ revalidate with the origin server. To do this, the client may
+ include the only-if-cached directive in a request. If it receives
+ this directive, a cache SHOULD either respond using a cached entry
+ that is consistent with the other constraints of the request, or
+ respond with a 504 (Gateway Timeout) status. However, if a group
+ of caches is being operated as a unified system with good internal
+ connectivity, such a request MAY be forwarded within that group of
+ caches.
+
+ must-revalidate
+ Because a cache MAY be configured to ignore a server's specified
+ expiration time, and because a client request MAY include a max-
+ stale directive (which has a similar effect), the protocol also
+ includes a mechanism for the origin server to require revalidation
+ of a cache entry on any subsequent use. When the must-revalidate
+ directive is present in a response received by a cache, that cache
+ MUST NOT use the entry after it becomes stale to respond to a
+
+ subsequent request without first revalidating it with the origin
+ server. (I.e., the cache MUST do an end-to-end revalidation every
+ time, if, based solely on the origin server's Expires or max-age
+ value, the cached response is stale.)
+
+ The must-revalidate directive is necessary to support reliable
+ operation for certain protocol features. In all circumstances an
+ HTTP/1.1 cache MUST obey the must-revalidate directive; in
+ particular, if the cache cannot reach the origin server for any
+ reason, it MUST generate a 504 (Gateway Timeout) response.
+
+ Servers SHOULD send the must-revalidate directive if and only if
+ failure to revalidate a request on the entity could result in
+ incorrect operation, such as a silently unexecuted financial
+ transaction. Recipients MUST NOT take any automated action that
+ violates this directive, and MUST NOT automatically provide an
+ unvalidated copy of the entity if revalidation fails.
+
+ Although this is not recommended, user agents operating under
+ severe connectivity constraints MAY violate this directive but, if
+ so, MUST explicitly warn the user that an unvalidated response has
+ been provided. The warning MUST be provided on each unvalidated
+ access, and SHOULD require explicit user confirmation.
+
+ proxy-revalidate
+ The proxy-revalidate directive has the same meaning as the must-
+ revalidate directive, except that it does not apply to non-shared
+ user agent caches. It can be used on a response to an
+ authenticated request to permit the user's cache to store and
+ later return the response without needing to revalidate it (since
+ it has already been authenticated once by that user), while still
+ requiring proxies that service many users to revalidate each time
+ (in order to make sure that each user has been authenticated).
+ Note that such authenticated responses also need the public cache
+ control directive in order to allow them to be cached at all.
+
+14.9.5 No-Transform Directive
+
+ no-transform
+ Implementors of intermediate caches (proxies) have found it useful
+ to convert the media type of certain entity bodies. A non-
+ transparent proxy might, for example, convert between image
+ formats in order to save cache space or to reduce the amount of
+ traffic on a slow link.
+
+ Serious operational problems occur, however, when these
+ transformations are applied to entity bodies intended for certain
+ kinds of applications. For example, applications for medical
+
+ imaging, scientific data analysis and those using end-to-end
+ authentication, all depend on receiving an entity body that is bit
+ for bit identical to the original entity-body.
+
+ Therefore, if a message includes the no-transform directive, an
+ intermediate cache or proxy MUST NOT change those headers that are
+ listed in section 13.5.2 as being subject to the no-transform
+ directive. This implies that the cache or proxy MUST NOT change
+ any aspect of the entity-body that is specified by these headers,
+ including the value of the entity-body itself.
+
+14.9.6 Cache Control Extensions
+
+ The Cache-Control header field can be extended through the use of one
+ or more cache-extension tokens, each with an optional assigned value.
+ Informational extensions (those which do not require a change in
+ cache behavior) MAY be added without changing the semantics of other
+ directives. Behavioral extensions are designed to work by acting as
+ modifiers to the existing base of cache directives. Both the new
+ directive and the standard directive are supplied, such that
+ applications which do not understand the new directive will default
+ to the behavior specified by the standard directive, and those that
+ understand the new directive will recognize it as modifying the
+ requirements associated with the standard directive. In this way,
+ extensions to the cache-control directives can be made without
+ requiring changes to the base protocol.
+
+ This extension mechanism depends on an HTTP cache obeying all of the
+ cache-control directives defined for its native HTTP-version, obeying
+ certain extensions, and ignoring all directives that it does not
+ understand.
+
+ For example, consider a hypothetical new response directive called
+ community which acts as a modifier to the private directive. We
+ define this new directive to mean that, in addition to any non-shared
+ cache, any cache which is shared only by members of the community
+ named within its value may cache the response. An origin server
+ wishing to allow the UCI community to use an otherwise private
+ response in their shared cache(s) could do so by including
+
+ Cache-Control: private, community="UCI"
+
+ A cache seeing this header field will act correctly even if the cache
+ does not understand the community cache-extension, since it will also
+ see and understand the private directive and thus default to the safe
+ behavior.
+
+ Unrecognized cache-directives MUST be ignored; it is assumed that any
+ cache-directive likely to be unrecognized by an HTTP/1.1 cache will
+ be combined with standard directives (or the response's default
+ cacheability) such that the cache behavior will remain minimally
+ correct even if the cache does not understand the extension(s).
+
+14.10 Connection
+
+ The Connection general-header field allows the sender to specify
+ options that are desired for that particular connection and MUST NOT
+ be communicated by proxies over further connections.
+
+ The Connection header has the following grammar:
+
+ Connection = "Connection" ":" 1#(connection-token)
+ connection-token = token
+
+ HTTP/1.1 proxies MUST parse the Connection header field before a
+ message is forwarded and, for each connection-token in this field,
+ remove any header field(s) from the message with the same name as the
+ connection-token. Connection options are signaled by the presence of
+ a connection-token in the Connection header field, not by any
+ corresponding additional header field(s), since the additional header
+ field may not be sent if there are no parameters associated with that
+ connection option.
+
+ Message headers listed in the Connection header MUST NOT include
+ end-to-end headers, such as Cache-Control.
+
+ HTTP/1.1 defines the "close" connection option for the sender to
+ signal that the connection will be closed after completion of the
+ response. For example,
+
+ Connection: close
+
+ in either the request or the response header fields indicates that
+ the connection SHOULD NOT be considered `persistent' (section 8.1)
+ after the current request/response is complete.
+
+ HTTP/1.1 applications that do not support persistent connections MUST
+ include the "close" connection option in every message.
+
+ A system receiving an HTTP/1.0 (or lower-version) message that
+ includes a Connection header MUST, for each connection-token in this
+ field, remove and ignore any header field(s) from the message with
+ the same name as the connection-token. This protects against mistaken
+ forwarding of such header fields by pre-HTTP/1.1 proxies. See section
+ 19.6.2.
+
+14.11 Content-Encoding
+
+ The Content-Encoding entity-header field is used as a modifier to the
+ media-type. When present, its value indicates what additional content
+ codings have been applied to the entity-body, and thus what decoding
+ mechanisms must be applied in order to obtain the media-type
+ referenced by the Content-Type header field. Content-Encoding is
+ primarily used to allow a document to be compressed without losing
+ the identity of its underlying media type.
+
+ Content-Encoding = "Content-Encoding" ":" 1#content-coding
+
+ Content codings are defined in section 3.5. An example of its use is
+
+ Content-Encoding: gzip
+
+ The content-coding is a characteristic of the entity identified by
+ the Request-URI. Typically, the entity-body is stored with this
+ encoding and is only decoded before rendering or analogous usage.
+ However, a non-transparent proxy MAY modify the content-coding if the
+ new coding is known to be acceptable to the recipient, unless the
+ "no-transform" cache-control directive is present in the message.
+
+ If the content-coding of an entity is not "identity", then the
+ response MUST include a Content-Encoding entity-header (section
+ 14.11) that lists the non-identity content-coding(s) used.
+
+ If the content-coding of an entity in a request message is not
+ acceptable to the origin server, the server SHOULD respond with a
+ status code of 415 (Unsupported Media Type).
+
+ If multiple encodings have been applied to an entity, the content
+ codings MUST be listed in the order in which they were applied.
+ Additional information about the encoding parameters MAY be provided
+ by other entity-header fields not defined by this specification.
+
+14.12 Content-Language
+
+ The Content-Language entity-header field describes the natural
+ language(s) of the intended audience for the enclosed entity. Note
+ that this might not be equivalent to all the languages used within
+ the entity-body.
+
+ Content-Language = "Content-Language" ":" 1#language-tag
+
+ Language tags are defined in section 3.10. The primary purpose of
+ Content-Language is to allow a user to identify and differentiate
+ entities according to the user's own preferred language. Thus, if the
+ body content is intended only for a Danish-literate audience, the
+ appropriate field is
+
+ Content-Language: da
+
+ If no Content-Language is specified, the default is that the content
+ is intended for all language audiences. This might mean that the
+ sender does not consider it to be specific to any natural language,
+ or that the sender does not know for which language it is intended.
+
+ Multiple languages MAY be listed for content that is intended for
+ multiple audiences. For example, a rendition of the "Treaty of
+ Waitangi," presented simultaneously in the original Maori and English
+ versions, would call for
+
+ Content-Language: mi, en
+
+ However, just because multiple languages are present within an entity
+ does not mean that it is intended for multiple linguistic audiences.
+ An example would be a beginner's language primer, such as "A First
+ Lesson in Latin," which is clearly intended to be used by an
+ English-literate audience. In this case, the Content-Language would
+ properly only include "en".
+
+ Content-Language MAY be applied to any media type -- it is not
+ limited to textual documents.
+
+14.13 Content-Length
+
+ The Content-Length entity-header field indicates the size of the
+ entity-body, in decimal number of OCTETs, sent to the recipient or,
+ in the case of the HEAD method, the size of the entity-body that
+ would have been sent had the request been a GET.
+
+ Content-Length = "Content-Length" ":" 1*DIGIT
+
+ An example is
+
+ Content-Length: 3495
+
+ Applications SHOULD use this field to indicate the transfer-length of
+ the message-body, unless this is prohibited by the rules in section
+ 4.4.
+
+ Any Content-Length greater than or equal to zero is a valid value.
+ Section 4.4 describes how to determine the length of a message-body
+ if a Content-Length is not given.
+
+ Note that the meaning of this field is significantly different from
+ the corresponding definition in MIME, where it is an optional field
+ used within the "message/external-body" content-type. In HTTP, it
+ SHOULD be sent whenever the message's length can be determined prior
+ to being transferred, unless this is prohibited by the rules in
+ section 4.4.
+
+14.14 Content-Location
+
+ The Content-Location entity-header field MAY be used to supply the
+ resource location for the entity enclosed in the message when that
+ entity is accessible from a location separate from the requested
+ resource's URI. A server SHOULD provide a Content-Location for the
+ variant corresponding to the response entity; especially in the case
+ where a resource has multiple entities associated with it, and those
+ entities actually have separate locations by which they might be
+ individually accessed, the server SHOULD provide a Content-Location
+ for the particular variant which is returned.
+
+ Content-Location = "Content-Location" ":"
+ ( absoluteURI | relativeURI )
+
+ The value of Content-Location also defines the base URI for the
+ entity.
+
+ The Content-Location value is not a replacement for the original
+ requested URI; it is only a statement of the location of the resource
+ corresponding to this particular entity at the time of the request.
+ Future requests MAY specify the Content-Location URI as the request-
+ URI if the desire is to identify the source of that particular
+ entity.
+
+ A cache cannot assume that an entity with a Content-Location
+ different from the URI used to retrieve it can be used to respond to
+ later requests on that Content-Location URI. However, the Content-
+ Location can be used to differentiate between multiple entities
+ retrieved from a single requested resource, as described in section
+ 13.6.
+
+ If the Content-Location is a relative URI, the relative URI is
+ interpreted relative to the Request-URI.
+
+ The meaning of the Content-Location header in PUT or POST requests is
+ undefined; servers are free to ignore it in those cases.
+
+14.15 Content-MD5
+
+ The Content-MD5 entity-header field, as defined in <a href="http://firefly.troll.no/rfcs/rfc1864.html">RFC 1864</a> [23], is
+ an MD5 digest of the entity-body for the purpose of providing an
+ end-to-end message integrity check (MIC) of the entity-body. (Note: a
+ MIC is good for detecting accidental modification of the entity-body
+ in transit, but is not proof against malicious attacks.)
+
+ Content-MD5 = "Content-MD5" ":" md5-digest
+ md5-digest = &lt;base64 of 128 bit MD5 digest as per <a href="http://firefly.troll.no/rfcs/rfc1864.html">RFC 1864</a>&gt;
+
+ The Content-MD5 header field MAY be generated by an origin server or
+ client to function as an integrity check of the entity-body. Only
+ origin servers or clients MAY generate the Content-MD5 header field;
+ proxies and gateways MUST NOT generate it, as this would defeat its
+ value as an end-to-end integrity check. Any recipient of the entity-
+ body, including gateways and proxies, MAY check that the digest value
+ in this header field matches that of the entity-body as received.
+
+ The MD5 digest is computed based on the content of the entity-body,
+ including any content-coding that has been applied, but not including
+ any transfer-encoding applied to the message-body. If the message is
+ received with a transfer-encoding, that encoding MUST be removed
+ prior to checking the Content-MD5 value against the received entity.
+
+ This has the result that the digest is computed on the octets of the
+ entity-body exactly as, and in the order that, they would be sent if
+ no transfer-encoding were being applied.
+
+ HTTP extends <a href="http://firefly.troll.no/rfcs/rfc1864.html">RFC 1864</a> to permit the digest to be computed for MIME
+ composite media-types (e.g., multipart/* and message/rfc822), but
+ this does not change how the digest is computed as defined in the
+ preceding paragraph.
+
+ There are several consequences of this. The entity-body for composite
+ types MAY contain many body-parts, each with its own MIME and HTTP
+ headers (including Content-MD5, Content-Transfer-Encoding, and
+ Content-Encoding headers). If a body-part has a Content-Transfer-
+ Encoding or Content-Encoding header, it is assumed that the content
+ of the body-part has had the encoding applied, and the body-part is
+ included in the Content-MD5 digest as is -- i.e., after the
+ application. The Transfer-Encoding header field is not allowed within
+ body-parts.
+
+ Conversion of all line breaks to CRLF MUST NOT be done before
+ computing or checking the digest: the line break convention used in
+ the text actually transmitted MUST be left unaltered when computing
+ the digest.
+
+ Note: while the definition of Content-MD5 is exactly the same for
+ HTTP as in <a href="http://firefly.troll.no/rfcs/rfc1864.html">RFC 1864</a> for MIME entity-bodies, there are several ways
+ in which the application of Content-MD5 to HTTP entity-bodies
+ differs from its application to MIME entity-bodies. One is that
+ HTTP, unlike MIME, does not use Content-Transfer-Encoding, and
+ does use Transfer-Encoding and Content-Encoding. Another is that
+ HTTP more frequently uses binary content types than MIME, so it is
+ worth noting that, in such cases, the byte order used to compute
+ the digest is the transmission byte order defined for the type.
+ Lastly, HTTP allows transmission of text types with any of several
+ line break conventions and not just the canonical form using CRLF.
+
+14.16 Content-Range
+
+ The Content-Range entity-header is sent with a partial entity-body to
+ specify where in the full entity-body the partial body should be
+ applied. Range units are defined in section 3.12.
+
+ Content-Range = "Content-Range" ":" content-range-spec
+
+ content-range-spec = byte-content-range-spec
+ byte-content-range-spec = bytes-unit SP
+ byte-range-resp-spec "/"
+ ( instance-length | "*" )
+
+ byte-range-resp-spec = (first-byte-pos "-" last-byte-pos)
+ | "*"
+ instance-length = 1*DIGIT
+
+ The header SHOULD indicate the total length of the full entity-body,
+ unless this length is unknown or difficult to determine. The asterisk
+ "*" character means that the instance-length is unknown at the time
+ when the response was generated.
+
+ Unlike byte-ranges-specifier values (see section 14.35.1), a byte-
+ range-resp-spec MUST only specify one range, and MUST contain
+ absolute byte positions for both the first and last byte of the
+ range.
+
+ A byte-content-range-spec with a byte-range-resp-spec whose last-
+ byte-pos value is less than its first-byte-pos value, or whose
+ instance-length value is less than or equal to its last-byte-pos
+ value, is invalid. The recipient of an invalid byte-content-range-
+ spec MUST ignore it and any content transferred along with it.
+
+ A server sending a response with status code 416 (Requested range not
+ satisfiable) SHOULD include a Content-Range field with a byte-range-
+ resp-spec of "*". The instance-length specifies the current length of
+
+ the selected resource. A response with status code 206 (Partial
+ Content) MUST NOT include a Content-Range field with a byte-range-
+ resp-spec of "*".
+
+ Examples of byte-content-range-spec values, assuming that the entity
+ contains a total of 1234 bytes:
+
+ . The first 500 bytes:
+ bytes 0-499/1234
+
+ . The second 500 bytes:
+ bytes 500-999/1234
+
+ . All except for the first 500 bytes:
+ bytes 500-1233/1234
+
+ . The last 500 bytes:
+ bytes 734-1233/1234
+
+ When an HTTP message includes the content of a single range (for
+ example, a response to a request for a single range, or to a request
+ for a set of ranges that overlap without any holes), this content is
+ transmitted with a Content-Range header, and a Content-Length header
+ showing the number of bytes actually transferred. For example,
+
+ HTTP/1.1 206 Partial content
+ Date: Wed, 15 Nov 1995 06:25:24 GMT
+ Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
+ Content-Range: bytes 21010-47021/47022
+ Content-Length: 26012
+ Content-Type: image/gif
+
+ When an HTTP message includes the content of multiple ranges (for
+ example, a response to a request for multiple non-overlapping
+ ranges), these are transmitted as a multipart message. The multipart
+ media type used for this purpose is "multipart/byteranges" as defined
+ in appendix 19.2. See appendix 19.6.3 for a compatibility issue.
+
+ A response to a request for a single range MUST NOT be sent using the
+ multipart/byteranges media type. A response to a request for
+ multiple ranges, whose result is a single range, MAY be sent as a
+ multipart/byteranges media type with one part. A client that cannot
+ decode a multipart/byteranges message MUST NOT ask for multiple
+ byte-ranges in a single request.
+
+ When a client requests multiple byte-ranges in one request, the
+ server SHOULD return them in the order that they appeared in the
+ request.
+
+ If the server ignores a byte-range-spec because it is syntactically
+ invalid, the server SHOULD treat the request as if the invalid Range
+ header field did not exist. (Normally, this means return a 200
+ response containing the full entity).
+
+ If the server receives a request (other than one including an If-
+ Range request-header field) with an unsatisfiable Range request-
+ header field (that is, all of whose byte-range-spec values have a
+ first-byte-pos value greater than the current length of the selected
+ resource), it SHOULD return a response code of 416 (Requested range
+ not satisfiable) (section 10.4.17).
+
+ Note: clients cannot depend on servers to send a 416 (Requested
+ range not satisfiable) response instead of a 200 (OK) response for
+ an unsatisfiable Range request-header, since not all servers
+ implement this request-header.
+
+14.17 Content-Type
+
+ The Content-Type entity-header field indicates the media type of the
+ entity-body sent to the recipient or, in the case of the HEAD method,
+ the media type that would have been sent had the request been a GET.
+
+ Content-Type = "Content-Type" ":" media-type
+
+ Media types are defined in section 3.7. An example of the field is
+
+ Content-Type: text/html; charset=ISO-8859-4
+
+ Further discussion of methods for identifying the media type of an
+ entity is provided in section 7.2.1.
+
+14.18 Date
+
+ The Date general-header field represents the date and time at which
+ the message was originated, having the same semantics as orig-date in
+ <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a>. The field value is an HTTP-date, as described in section
+ 3.3.1; it MUST be sent in <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a> [8]-date format.
+
+ Date = "Date" ":" HTTP-date
+
+ An example is
+
+ Date: Tue, 15 Nov 1994 08:12:31 GMT
+
+ Origin servers MUST include a Date header field in all responses,
+ except in these cases:
+
+ 1. If the response status code is 100 (Continue) or 101 (Switching
+ Protocols), the response MAY include a Date header field, at
+ the server's option.
+
+ 2. If the response status code conveys a server error, e.g. 500
+ (Internal Server Error) or 503 (Service Unavailable), and it is
+ inconvenient or impossible to generate a valid Date.
+
+ 3. If the server does not have a clock that can provide a
+ reasonable approximation of the current time, its responses
+ MUST NOT include a Date header field. In this case, the rules
+ in section 14.18.1 MUST be followed.
+
+ A received message that does not have a Date header field MUST be
+ assigned one by the recipient if the message will be cached by that
+ recipient or gatewayed via a protocol which requires a Date. An HTTP
+ implementation without a clock MUST NOT cache responses without
+ revalidating them on every use. An HTTP cache, especially a shared
+ cache, SHOULD use a mechanism, such as NTP [28], to synchronize its
+ clock with a reliable external standard.
+
+ Clients SHOULD only send a Date header field in messages that include
+ an entity-body, as in the case of the PUT and POST requests, and even
+ then it is optional. A client without a clock MUST NOT send a Date
+ header field in a request.
+
+ The HTTP-date sent in a Date header SHOULD NOT represent a date and
+ time subsequent to the generation of the message. It SHOULD represent
+ the best available approximation of the date and time of message
+ generation, unless the implementation has no means of generating a
+ reasonably accurate date and time. In theory, the date ought to
+ represent the moment just before the entity is generated. In
+ practice, the date can be generated at any time during the message
+ origination without affecting its semantic value.
+
+14.18.1 Clockless Origin Server Operation
+
+ Some origin server implementations might not have a clock available.
+ An origin server without a clock MUST NOT assign Expires or Last-
+ Modified values to a response, unless these values were associated
+ with the resource by a system or user with a reliable clock. It MAY
+ assign an Expires value that is known, at or before server
+ configuration time, to be in the past (this allows "pre-expiration"
+ of responses without storing separate Expires values for each
+ resource).
+
+14.19 ETag
+
+ The ETag response-header field provides the current value of the
+ entity tag for the requested variant. The headers used with entity
+ tags are described in sections 14.24, 14.26 and 14.44. The entity tag
+ MAY be used for comparison with other entities from the same resource
+ (see section 13.3.3).
+
+ ETag = "ETag" ":" entity-tag
+
+ Examples:
+
+ ETag: "xyzzy"
+ ETag: W/"xyzzy"
+ ETag: ""
+
+14.20 Expect
+
+ The Expect request-header field is used to indicate that particular
+ server behaviors are required by the client.
+
+ Expect = "Expect" ":" 1#expectation
+
+ expectation = "100-continue" | expectation-extension
+ expectation-extension = token [ "=" ( token | quoted-string )
+ *expect-params ]
+ expect-params = ";" token [ "=" ( token | quoted-string ) ]
+
+ A server that does not understand or is unable to comply with any of
+ the expectation values in the Expect field of a request MUST respond
+ with appropriate error status. The server MUST respond with a 417
+ (Expectation Failed) status if any of the expectations cannot be met
+ or, if there are other problems with the request, some other 4xx
+ status.
+
+ This header field is defined with extensible syntax to allow for
+ future extensions. If a server receives a request containing an
+ Expect field that includes an expectation-extension that it does not
+ support, it MUST respond with a 417 (Expectation Failed) status.
+
+ Comparison of expectation values is case-insensitive for unquoted
+ tokens (including the 100-continue token), and is case-sensitive for
+ quoted-string expectation-extensions.
+
+ The Expect mechanism is hop-by-hop: that is, an HTTP/1.1 proxy MUST
+ return a 417 (Expectation Failed) status if it receives a request
+ with an expectation that it cannot meet. However, the Expect
+ request-header itself is end-to-end; it MUST be forwarded if the
+ request is forwarded.
+
+ Many older HTTP/1.0 and HTTP/1.1 applications do not understand the
+ Expect header.
+
+ See section 8.2.3 for the use of the 100 (continue) status.
+
+14.21 Expires
+
+ The Expires entity-header field gives the date/time after which the
+ response is considered stale. A stale cache entry may not normally be
+ returned by a cache (either a proxy cache or a user agent cache)
+ unless it is first validated with the origin server (or with an
+ intermediate cache that has a fresh copy of the entity). See section
+ 13.2 for further discussion of the expiration model.
+
+ The presence of an Expires field does not imply that the original
+ resource will change or cease to exist at, before, or after that
+ time.
+
+ The format is an absolute date and time as defined by HTTP-date in
+ section 3.3.1; it MUST be in <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a> date format:
+
+ Expires = "Expires" ":" HTTP-date
+
+ An example of its use is
+
+ Expires: Thu, 01 Dec 1994 16:00:00 GMT
+
+ Note: if a response includes a Cache-Control field with the max-
+ age directive (see section 14.9.3), that directive overrides the
+ Expires field.
+
+ HTTP/1.1 clients and caches MUST treat other invalid date formats,
+ especially including the value "0", as in the past (i.e., "already
+ expired").
+
+ To mark a response as "already expired," an origin server sends an
+ Expires date that is equal to the Date header value. (See the rules
+ for expiration calculations in section 13.2.4.)
+
+ To mark a response as "never expires," an origin server sends an
+ Expires date approximately one year from the time the response is
+ sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one
+ year in the future.
+
+ The presence of an Expires header field with a date value of some
+ time in the future on a response that otherwise would by default be
+ non-cacheable indicates that the response is cacheable, unless
+ indicated otherwise by a Cache-Control header field (section 14.9).
+
+14.22 From
+
+ The From request-header field, if given, SHOULD contain an Internet
+ e-mail address for the human user who controls the requesting user
+ agent. The address SHOULD be machine-usable, as defined by "mailbox"
+ in <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9] as updated by <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a> [8]:
+
+ From = "From" ":" mailbox
+
+ An example is:
+
+ From: <a href="mailto:webmaster@w3.org">webmaster@w3.org</a>
+
+ This header field MAY be used for logging purposes and as a means for
+ identifying the source of invalid or unwanted requests. It SHOULD NOT
+ be used as an insecure form of access protection. The interpretation
+ of this field is that the request is being performed on behalf of the
+ person given, who accepts responsibility for the method performed. In
+ particular, robot agents SHOULD include this header so that the
+ person responsible for running the robot can be contacted if problems
+ occur on the receiving end.
+
+ The Internet e-mail address in this field MAY be separate from the
+ Internet host which issued the request. For example, when a request
+ is passed through a proxy the original issuer's address SHOULD be
+ used.
+
+ The client SHOULD NOT send the From header field without the user's
+ approval, as it might conflict with the user's privacy interests or
+ their site's security policy. It is strongly recommended that the
+ user be able to disable, enable, and modify the value of this field
+ at any time prior to a request.
+
+14.23 Host
+
+ The Host request-header field specifies the Internet host and port
+ number of the resource being requested, as obtained from the original
+ URI given by the user or referring resource (generally an HTTP URL,
+
+ as described in section 3.2.2). The Host field value MUST represent
+ the naming authority of the origin server or gateway given by the
+ original URL. This allows the origin server or gateway to
+ differentiate between internally-ambiguous URLs, such as the root "/"
+ URL of a server for multiple host names on a single IP address.
+
+ Host = "Host" ":" host [ ":" port ] ; Section 3.2.2
+
+ A "host" without any trailing port information implies the default
+ port for the service requested (e.g., "80" for an HTTP URL). For
+ example, a request on the origin server for
+ &lt;<a href="http://www.w3.org/pub/WWW/">http://www.w3.org/pub/WWW/</a>&gt; would properly include:
+
+ GET /pub/WWW/ HTTP/1.1
+ Host: www.w3.org
+
+ A client MUST include a Host header field in all HTTP/1.1 request
+ messages . If the requested URI does not include an Internet host
+ name for the service being requested, then the Host header field MUST
+ be given with an empty value. An HTTP/1.1 proxy MUST ensure that any
+ request message it forwards does contain an appropriate Host header
+ field that identifies the service being requested by the proxy. All
+ Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request)
+ status code to any HTTP/1.1 request message which lacks a Host header
+ field.
+
+ See sections 5.2 and 19.6.1.1 for other requirements relating to
+ Host.
+
+14.24 If-Match
+
+ The If-Match request-header field is used with a method to make it
+ conditional. A client that has one or more entities previously
+ obtained from the resource can verify that one of those entities is
+ current by including a list of their associated entity tags in the
+ If-Match header field. Entity tags are defined in section 3.11. The
+ purpose of this feature is to allow efficient updates of cached
+ information with a minimum amount of transaction overhead. It is also
+ used, on updating requests, to prevent inadvertent modification of
+ the wrong version of a resource. As a special case, the value "*"
+ matches any current entity of the resource.
+
+ If-Match = "If-Match" ":" ( "*" | 1#entity-tag )
+
+ If any of the entity tags match the entity tag of the entity that
+ would have been returned in the response to a similar GET request
+ (without the If-Match header) on that resource, or if "*" is given
+
+ and any current entity exists for that resource, then the server MAY
+ perform the requested method as if the If-Match header field did not
+ exist.
+
+ A server MUST use the strong comparison function (see section 13.3.3)
+ to compare the entity tags in If-Match.
+
+ If none of the entity tags match, or if "*" is given and no current
+ entity exists, the server MUST NOT perform the requested method, and
+ MUST return a 412 (Precondition Failed) response. This behavior is
+ most useful when the client wants to prevent an updating method, such
+ as PUT, from modifying a resource that has changed since the client
+ last retrieved it.
+
+ If the request would, without the If-Match header field, result in
+ anything other than a 2xx or 412 status, then the If-Match header
+ MUST be ignored.
+
+ The meaning of "If-Match: *" is that the method SHOULD be performed
+ if the representation selected by the origin server (or by a cache,
+ possibly using the Vary mechanism, see section 14.44) exists, and
+ MUST NOT be performed if the representation does not exist.
+
+ A request intended to update a resource (e.g., a PUT) MAY include an
+ If-Match header field to signal that the request method MUST NOT be
+ applied if the entity corresponding to the If-Match value (a single
+ entity tag) is no longer a representation of that resource. This
+ allows the user to indicate that they do not wish the request to be
+ successful if the resource has been changed without their knowledge.
+ Examples:
+
+ If-Match: "xyzzy"
+ If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
+ If-Match: *
+
+ The result of a request having both an If-Match header field and
+ either an If-None-Match or an If-Modified-Since header fields is
+ undefined by this specification.
+
+14.25 If-Modified-Since
+
+ The If-Modified-Since request-header field is used with a method to
+ make it conditional: if the requested variant has not been modified
+ since the time specified in this field, an entity will not be
+ returned from the server; instead, a 304 (not modified) response will
+ be returned without any message-body.
+
+ If-Modified-Since = "If-Modified-Since" ":" HTTP-date
+
+ An example of the field is:
+
+ If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+
+ A GET method with an If-Modified-Since header and no Range header
+ requests that the identified entity be transferred only if it has
+ been modified since the date given by the If-Modified-Since header.
+ The algorithm for determining this includes the following cases:
+
+ a) If the request would normally result in anything other than a
+ 200 (OK) status, or if the passed If-Modified-Since date is
+ invalid, the response is exactly the same as for a normal GET.
+ A date which is later than the server's current time is
+ invalid.
+
+ b) If the variant has been modified since the If-Modified-Since
+ date, the response is exactly the same as for a normal GET.
+
+ c) If the variant has not been modified since a valid If-
+ Modified-Since date, the server SHOULD return a 304 (Not
+ Modified) response.
+
+ The purpose of this feature is to allow efficient updates of cached
+ information with a minimum amount of transaction overhead.
+
+ Note: The Range request-header field modifies the meaning of If-
+ Modified-Since; see section 14.35 for full details.
+
+ Note: If-Modified-Since times are interpreted by the server, whose
+ clock might not be synchronized with the client.
+
+ Note: When handling an If-Modified-Since header field, some
+ servers will use an exact date comparison function, rather than a
+ less-than function, for deciding whether to send a 304 (Not
+ Modified) response. To get best results when sending an If-
+ Modified-Since header field for cache validation, clients are
+ advised to use the exact date string received in a previous Last-
+ Modified header field whenever possible.
+
+ Note: If a client uses an arbitrary date in the If-Modified-Since
+ header instead of a date taken from the Last-Modified header for
+ the same request, the client should be aware of the fact that this
+ date is interpreted in the server's understanding of time. The
+ client should consider unsynchronized clocks and rounding problems
+ due to the different encodings of time between the client and
+ server. This includes the possibility of race conditions if the
+ document has changed between the time it was first requested and
+ the If-Modified-Since date of a subsequent request, and the
+
+ possibility of clock-skew-related problems if the If-Modified-
+ Since date is derived from the client's clock without correction
+ to the server's clock. Corrections for different time bases
+ between client and server are at best approximate due to network
+ latency.
+
+ The result of a request having both an If-Modified-Since header field
+ and either an If-Match or an If-Unmodified-Since header fields is
+ undefined by this specification.
+
+14.26 If-None-Match
+
+ The If-None-Match request-header field is used with a method to make
+ it conditional. A client that has one or more entities previously
+ obtained from the resource can verify that none of those entities is
+ current by including a list of their associated entity tags in the
+ If-None-Match header field. The purpose of this feature is to allow
+ efficient updates of cached information with a minimum amount of
+ transaction overhead. It is also used to prevent a method (e.g. PUT)
+ from inadvertently modifying an existing resource when the client
+ believes that the resource does not exist.
+
+ As a special case, the value "*" matches any current entity of the
+ resource.
+
+ If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )
+
+ If any of the entity tags match the entity tag of the entity that
+ would have been returned in the response to a similar GET request
+ (without the If-None-Match header) on that resource, or if "*" is
+ given and any current entity exists for that resource, then the
+ server MUST NOT perform the requested method, unless required to do
+ so because the resource's modification date fails to match that
+ supplied in an If-Modified-Since header field in the request.
+ Instead, if the request method was GET or HEAD, the server SHOULD
+ respond with a 304 (Not Modified) response, including the cache-
+ related header fields (particularly ETag) of one of the entities that
+ matched. For all other request methods, the server MUST respond with
+ a status of 412 (Precondition Failed).
+
+ See section 13.3.3 for rules on how to determine if two entities tags
+ match. The weak comparison function can only be used with GET or HEAD
+ requests.
+
+ If none of the entity tags match, then the server MAY perform the
+ requested method as if the If-None-Match header field did not exist,
+ but MUST also ignore any If-Modified-Since header field(s) in the
+ request. That is, if no entity tags match, then the server MUST NOT
+ return a 304 (Not Modified) response.
+
+ If the request would, without the If-None-Match header field, result
+ in anything other than a 2xx or 304 status, then the If-None-Match
+ header MUST be ignored. (See section 13.3.4 for a discussion of
+ server behavior when both If-Modified-Since and If-None-Match appear
+ in the same request.)
+
+ The meaning of "If-None-Match: *" is that the method MUST NOT be
+ performed if the representation selected by the origin server (or by
+ a cache, possibly using the Vary mechanism, see section 14.44)
+ exists, and SHOULD be performed if the representation does not exist.
+ This feature is intended to be useful in preventing races between PUT
+ operations.
+
+ Examples:
+
+ If-None-Match: "xyzzy"
+ If-None-Match: W/"xyzzy"
+ If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
+ If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
+ If-None-Match: *
+
+ The result of a request having both an If-None-Match header field and
+ either an If-Match or an If-Unmodified-Since header fields is
+ undefined by this specification.
+
+14.27 If-Range
+
+ If a client has a partial copy of an entity in its cache, and wishes
+ to have an up-to-date copy of the entire entity in its cache, it
+ could use the Range request-header with a conditional GET (using
+ either or both of If-Unmodified-Since and If-Match.) However, if the
+ condition fails because the entity has been modified, the client
+ would then have to make a second request to obtain the entire current
+ entity-body.
+
+ The If-Range header allows a client to "short-circuit" the second
+ request. Informally, its meaning is `if the entity is unchanged, send
+ me the part(s) that I am missing; otherwise, send me the entire new
+ entity'.
+
+ If-Range = "If-Range" ":" ( entity-tag | HTTP-date )
+
+ If the client has no entity tag for an entity, but does have a Last-
+ Modified date, it MAY use that date in an If-Range header. (The
+ server can distinguish between a valid HTTP-date and any form of
+ entity-tag by examining no more than two characters.) The If-Range
+ header SHOULD only be used together with a Range header, and MUST be
+ ignored if the request does not include a Range header, or if the
+ server does not support the sub-range operation.
+
+ If the entity tag given in the If-Range header matches the current
+ entity tag for the entity, then the server SHOULD provide the
+ specified sub-range of the entity using a 206 (Partial content)
+ response. If the entity tag does not match, then the server SHOULD
+ return the entire entity using a 200 (OK) response.
+
+14.28 If-Unmodified-Since
+
+ The If-Unmodified-Since request-header field is used with a method to
+ make it conditional. If the requested resource has not been modified
+ since the time specified in this field, the server SHOULD perform the
+ requested operation as if the If-Unmodified-Since header were not
+ present.
+
+ If the requested variant has been modified since the specified time,
+ the server MUST NOT perform the requested operation, and MUST return
+ a 412 (Precondition Failed).
+
+ If-Unmodified-Since = "If-Unmodified-Since" ":" HTTP-date
+
+ An example of the field is:
+
+ If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+
+ If the request normally (i.e., without the If-Unmodified-Since
+ header) would result in anything other than a 2xx or 412 status, the
+ If-Unmodified-Since header SHOULD be ignored.
+
+ If the specified date is invalid, the header is ignored.
+
+ The result of a request having both an If-Unmodified-Since header
+ field and either an If-None-Match or an If-Modified-Since header
+ fields is undefined by this specification.
+
+14.29 Last-Modified
+
+ The Last-Modified entity-header field indicates the date and time at
+ which the origin server believes the variant was last modified.
+
+ Last-Modified = "Last-Modified" ":" HTTP-date
+
+ An example of its use is
+
+ Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
+
+ The exact meaning of this header field depends on the implementation
+ of the origin server and the nature of the original resource. For
+ files, it may be just the file system last-modified time. For
+ entities with dynamically included parts, it may be the most recent
+ of the set of last-modify times for its component parts. For database
+ gateways, it may be the last-update time stamp of the record. For
+ virtual objects, it may be the last time the internal state changed.
+
+ An origin server MUST NOT send a Last-Modified date which is later
+ than the server's time of message origination. In such cases, where
+ the resource's last modification would indicate some time in the
+ future, the server MUST replace that date with the message
+ origination date.
+
+ An origin server SHOULD obtain the Last-Modified value of the entity
+ as close as possible to the time that it generates the Date value of
+ its response. This allows a recipient to make an accurate assessment
+ of the entity's modification time, especially if the entity changes
+ near the time that the response is generated.
+
+ HTTP/1.1 servers SHOULD send Last-Modified whenever feasible.
+
+14.30 Location
+
+ The Location response-header field is used to redirect the recipient
+ to a location other than the Request-URI for completion of the
+ request or identification of a new resource. For 201 (Created)
+ responses, the Location is that of the new resource which was created
+ by the request. For 3xx responses, the location SHOULD indicate the
+ server's preferred URI for automatic redirection to the resource. The
+ field value consists of a single absolute URI.
+
+ Location = "Location" ":" absoluteURI
+
+ An example is:
+
+ Location: <a href="http://www.w3.org/pub/WWW/People.html">http://www.w3.org/pub/WWW/People.html</a>
+
+ Note: The Content-Location header field (section 14.14) differs
+ from Location in that the Content-Location identifies the original
+ location of the entity enclosed in the request. It is therefore
+ possible for a response to contain header fields for both Location
+ and Content-Location. Also see section 13.10 for cache
+ requirements of some methods.
+
+14.31 Max-Forwards
+
+ The Max-Forwards request-header field provides a mechanism with the
+ TRACE (section 9.8) and OPTIONS (section 9.2) methods to limit the
+ number of proxies or gateways that can forward the request to the
+ next inbound server. This can be useful when the client is attempting
+ to trace a request chain which appears to be failing or looping in
+ mid-chain.
+
+ Max-Forwards = "Max-Forwards" ":" 1*DIGIT
+
+ The Max-Forwards value is a decimal integer indicating the remaining
+ number of times this request message may be forwarded.
+
+ Each proxy or gateway recipient of a TRACE or OPTIONS request
+ containing a Max-Forwards header field MUST check and update its
+ value prior to forwarding the request. If the received value is zero
+ (0), the recipient MUST NOT forward the request; instead, it MUST
+ respond as the final recipient. If the received Max-Forwards value is
+ greater than zero, then the forwarded message MUST contain an updated
+ Max-Forwards field with a value decremented by one (1).
+
+ The Max-Forwards header field MAY be ignored for all other methods
+ defined by this specification and for any extension methods for which
+ it is not explicitly referred to as part of that method definition.
+
+14.32 Pragma
+
+ The Pragma general-header field is used to include implementation-
+ specific directives that might apply to any recipient along the
+ request/response chain. All pragma directives specify optional
+ behavior from the viewpoint of the protocol; however, some systems
+ MAY require that behavior be consistent with the directives.
+
+ Pragma = "Pragma" ":" 1#pragma-directive
+ pragma-directive = "no-cache" | extension-pragma
+ extension-pragma = token [ "=" ( token | quoted-string ) ]
+
+ When the no-cache directive is present in a request message, an
+ application SHOULD forward the request toward the origin server even
+ if it has a cached copy of what is being requested. This pragma
+ directive has the same semantics as the no-cache cache-directive (see
+ section 14.9) and is defined here for backward compatibility with
+ HTTP/1.0. Clients SHOULD include both header fields when a no-cache
+ request is sent to a server not known to be HTTP/1.1 compliant.
+
+ Pragma directives MUST be passed through by a proxy or gateway
+ application, regardless of their significance to that application,
+ since the directives might be applicable to all recipients along the
+ request/response chain. It is not possible to specify a pragma for a
+ specific recipient; however, any pragma directive not relevant to a
+ recipient SHOULD be ignored by that recipient.
+
+ HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client had
+ sent "Cache-Control: no-cache". No new Pragma directives will be
+ defined in HTTP.
+
+ Note: because the meaning of "Pragma: no-cache as a response
+ header field is not actually specified, it does not provide a
+ reliable replacement for "Cache-Control: no-cache" in a response
+
+14.33 Proxy-Authenticate
+
+ The Proxy-Authenticate response-header field MUST be included as part
+ of a 407 (Proxy Authentication Required) response. The field value
+ consists of a challenge that indicates the authentication scheme and
+ parameters applicable to the proxy for this Request-URI.
+
+ Proxy-Authenticate = "Proxy-Authenticate" ":" 1#challenge
+
+ The HTTP access authentication process is described in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43]. Unlike
+ WWW-Authenticate, the Proxy-Authenticate header field applies only to
+ the current connection and SHOULD NOT be passed on to downstream
+ clients. However, an intermediate proxy might need to obtain its own
+ credentials by requesting them from the downstream client, which in
+ some circumstances will appear as if the proxy is forwarding the
+ Proxy-Authenticate header field.
+
+14.34 Proxy-Authorization
+
+ The Proxy-Authorization request-header field allows the client to
+ identify itself (or its user) to a proxy which requires
+ authentication. The Proxy-Authorization field value consists of
+ credentials containing the authentication information of the user
+ agent for the proxy and/or realm of the resource being requested.
+
+ Proxy-Authorization = "Proxy-Authorization" ":" credentials
+
+ The HTTP access authentication process is described in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43] . Unlike
+ Authorization, the Proxy-Authorization header field applies only to
+ the next outbound proxy that demanded authentication using the Proxy-
+ Authenticate field. When multiple proxies are used in a chain, the
+
+ Proxy-Authorization header field is consumed by the first outbound
+ proxy that was expecting to receive credentials. A proxy MAY relay
+ the credentials from the client request to the next proxy if that is
+ the mechanism by which the proxies cooperatively authenticate a given
+ request.
+
+14.35 Range
+
+14.35.1 Byte Ranges
+
+ Since all HTTP entities are represented in HTTP messages as sequences
+ of bytes, the concept of a byte range is meaningful for any HTTP
+ entity. (However, not all clients and servers need to support byte-
+ range operations.)
+
+ Byte range specifications in HTTP apply to the sequence of bytes in
+ the entity-body (not necessarily the same as the message-body).
+
+ A byte range operation MAY specify a single range of bytes, or a set
+ of ranges within a single entity.
+
+ ranges-specifier = byte-ranges-specifier
+ byte-ranges-specifier = bytes-unit "=" byte-range-set
+ byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )
+ byte-range-spec = first-byte-pos "-" [last-byte-pos]
+ first-byte-pos = 1*DIGIT
+ last-byte-pos = 1*DIGIT
+
+ The first-byte-pos value in a byte-range-spec gives the byte-offset
+ of the first byte in a range. The last-byte-pos value gives the
+ byte-offset of the last byte in the range; that is, the byte
+ positions specified are inclusive. Byte offsets start at zero.
+
+ If the last-byte-pos value is present, it MUST be greater than or
+ equal to the first-byte-pos in that byte-range-spec, or the byte-
+ range-spec is syntactically invalid. The recipient of a byte-range-
+ set that includes one or more syntactically invalid byte-range-spec
+ values MUST ignore the header field that includes that byte-range-
+ set.
+
+ If the last-byte-pos value is absent, or if the value is greater than
+ or equal to the current length of the entity-body, last-byte-pos is
+ taken to be equal to one less than the current length of the entity-
+ body in bytes.
+
+ By its choice of last-byte-pos, a client can limit the number of
+ bytes retrieved without knowing the size of the entity.
+
+ suffix-byte-range-spec = "-" suffix-length
+ suffix-length = 1*DIGIT
+
+ A suffix-byte-range-spec is used to specify the suffix of the
+ entity-body, of a length given by the suffix-length value. (That is,
+ this form specifies the last N bytes of an entity-body.) If the
+ entity is shorter than the specified suffix-length, the entire
+ entity-body is used.
+
+ If a syntactically valid byte-range-set includes at least one byte-
+ range-spec whose first-byte-pos is less than the current length of
+ the entity-body, or at least one suffix-byte-range-spec with a non-
+ zero suffix-length, then the byte-range-set is satisfiable.
+ Otherwise, the byte-range-set is unsatisfiable. If the byte-range-set
+ is unsatisfiable, the server SHOULD return a response with a status
+ of 416 (Requested range not satisfiable). Otherwise, the server
+ SHOULD return a response with a status of 206 (Partial Content)
+ containing the satisfiable ranges of the entity-body.
+
+ Examples of byte-ranges-specifier values (assuming an entity-body of
+ length 10000):
+
+ - The first 500 bytes (byte offsets 0-499, inclusive): bytes=0-
+ 499
+
+ - The second 500 bytes (byte offsets 500-999, inclusive):
+ bytes=500-999
+
+ - The final 500 bytes (byte offsets 9500-9999, inclusive):
+ bytes=-500
+
+ - Or bytes=9500-
+
+ - The first and last bytes only (bytes 0 and 9999): bytes=0-0,-1
+
+ - Several legal but not canonical specifications of the second 500
+ bytes (byte offsets 500-999, inclusive):
+ bytes=500-600,601-999
+ bytes=500-700,601-999
+
+14.35.2 Range Retrieval Requests
+
+ HTTP retrieval requests using conditional or unconditional GET
+ methods MAY request one or more sub-ranges of the entity, instead of
+ the entire entity, using the Range request header, which applies to
+ the entity returned as the result of the request:
+
+ Range = "Range" ":" ranges-specifier
+
+ A server MAY ignore the Range header. However, HTTP/1.1 origin
+ servers and intermediate caches ought to support byte ranges when
+ possible, since Range supports efficient recovery from partially
+ failed transfers, and supports efficient partial retrieval of large
+ entities.
+
+ If the server supports the Range header and the specified range or
+ ranges are appropriate for the entity:
+
+ - The presence of a Range header in an unconditional GET modifies
+ what is returned if the GET is otherwise successful. In other
+ words, the response carries a status code of 206 (Partial
+ Content) instead of 200 (OK).
+
+ - The presence of a Range header in a conditional GET (a request
+ using one or both of If-Modified-Since and If-None-Match, or
+ one or both of If-Unmodified-Since and If-Match) modifies what
+ is returned if the GET is otherwise successful and the
+ condition is true. It does not affect the 304 (Not Modified)
+ response returned if the conditional is false.
+
+ In some cases, it might be more appropriate to use the If-Range
+ header (see section 14.27) in addition to the Range header.
+
+ If a proxy that supports ranges receives a Range request, forwards
+ the request to an inbound server, and receives an entire entity in
+ reply, it SHOULD only return the requested range to its client. It
+ SHOULD store the entire received response in its cache if that is
+ consistent with its cache allocation policies.
+
+14.36 Referer
+
+ The Referer[sic] request-header field allows the client to specify,
+ for the server's benefit, the address (URI) of the resource from
+ which the Request-URI was obtained (the "referrer", although the
+ header field is misspelled.) The Referer request-header allows a
+ server to generate lists of back-links to resources for interest,
+ logging, optimized caching, etc. It also allows obsolete or mistyped
+ links to be traced for maintenance. The Referer field MUST NOT be
+ sent if the Request-URI was obtained from a source that does not have
+ its own URI, such as input from the user keyboard.
+
+ Referer = "Referer" ":" ( absoluteURI | relativeURI )
+
+ Example:
+
+ Referer: <a href="http://www.w3.org/hypertext/DataSources/Overview.html">http://www.w3.org/hypertext/DataSources/Overview.html</a>
+
+ If the field value is a relative URI, it SHOULD be interpreted
+ relative to the Request-URI. The URI MUST NOT include a fragment. See
+ section 15.1.3 for security considerations.
+
+14.37 Retry-After
+
+ The Retry-After response-header field can be used with a 503 (Service
+ Unavailable) response to indicate how long the service is expected to
+ be unavailable to the requesting client. This field MAY also be used
+ with any 3xx (Redirection) response to indicate the minimum time the
+ user-agent is asked wait before issuing the redirected request. The
+ value of this field can be either an HTTP-date or an integer number
+ of seconds (in decimal) after the time of the response.
+
+ Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds )
+
+ Two examples of its use are
+
+ Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
+ Retry-After: 120
+
+ In the latter example, the delay is 2 minutes.
+
+14.38 Server
+
+ The Server response-header field contains information about the
+ software used by the origin server to handle the request. The field
+ can contain multiple product tokens (section 3.8) and comments
+ identifying the server and any significant subproducts. The product
+ tokens are listed in order of their significance for identifying the
+ application.
+
+ Server = "Server" ":" 1*( product | comment )
+
+ Example:
+
+ Server: CERN/3.0 libwww/2.17
+
+ If the response is being forwarded through a proxy, the proxy
+ application MUST NOT modify the Server response-header. Instead, it
+ SHOULD include a Via field (as described in section 14.45).
+
+ Note: Revealing the specific software version of the server might
+ allow the server machine to become more vulnerable to attacks
+ against software that is known to contain security holes. Server
+ implementors are encouraged to make this field a configurable
+ option.
+
+14.39 TE
+
+ The TE request-header field indicates what extension transfer-codings
+ it is willing to accept in the response and whether or not it is
+ willing to accept trailer fields in a chunked transfer-coding. Its
+ value may consist of the keyword "trailers" and/or a comma-separated
+ list of extension transfer-coding names with optional accept
+ parameters (as described in section 3.6).
+
+ TE = "TE" ":" #( t-codings )
+ t-codings = "trailers" | ( transfer-extension [ accept-params ] )
+
+ The presence of the keyword "trailers" indicates that the client is
+ willing to accept trailer fields in a chunked transfer-coding, as
+ defined in section 3.6.1. This keyword is reserved for use with
+ transfer-coding values even though it does not itself represent a
+ transfer-coding.
+
+ Examples of its use are:
+
+ TE: deflate
+ TE:
+ TE: trailers, deflate;q=0.5
+
+ The TE header field only applies to the immediate connection.
+ Therefore, the keyword MUST be supplied within a Connection header
+ field (section 14.10) whenever TE is present in an HTTP/1.1 message.
+
+ A server tests whether a transfer-coding is acceptable, according to
+ a TE field, using these rules:
+
+ 1. The "chunked" transfer-coding is always acceptable. If the
+ keyword "trailers" is listed, the client indicates that it is
+ willing to accept trailer fields in the chunked response on
+ behalf of itself and any downstream clients. The implication is
+ that, if given, the client is stating that either all
+ downstream clients are willing to accept trailer fields in the
+ forwarded response, or that it will attempt to buffer the
+ response on behalf of downstream recipients.
+
+ Note: HTTP/1.1 does not define any means to limit the size of a
+ chunked response such that a client can be assured of buffering
+ the entire response.
+
+ 2. If the transfer-coding being tested is one of the transfer-
+ codings listed in the TE field, then it is acceptable unless it
+ is accompanied by a qvalue of 0. (As defined in section 3.9, a
+ qvalue of 0 means "not acceptable.")
+
+ 3. If multiple transfer-codings are acceptable, then the
+ acceptable transfer-coding with the highest non-zero qvalue is
+ preferred. The "chunked" transfer-coding always has a qvalue
+ of 1.
+
+ If the TE field-value is empty or if no TE field is present, the only
+ transfer-coding is "chunked". A message with no transfer-coding is
+ always acceptable.
+
+14.40 Trailer
+
+ The Trailer general field value indicates that the given set of
+ header fields is present in the trailer of a message encoded with
+ chunked transfer-coding.
+
+ Trailer = "Trailer" ":" 1#field-name
+
+ An HTTP/1.1 message SHOULD include a Trailer header field in a
+ message using chunked transfer-coding with a non-empty trailer. Doing
+ so allows the recipient to know which header fields to expect in the
+ trailer.
+
+ If no Trailer header field is present, the trailer SHOULD NOT include
+ any header fields. See section 3.6.1 for restrictions on the use of
+ trailer fields in a "chunked" transfer-coding.
+
+ Message header fields listed in the Trailer header field MUST NOT
+ include the following header fields:
+
+ . Transfer-Encoding
+
+ . Content-Length
+
+ . Trailer
+
+14.41 Transfer-Encoding
+
+ The Transfer-Encoding general-header field indicates what (if any)
+ type of transformation has been applied to the message body in order
+ to safely transfer it between the sender and the recipient. This
+ differs from the content-coding in that the transfer-coding is a
+ property of the message, not of the entity.
+
+ Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-coding
+
+ Transfer-codings are defined in section 3.6. An example is:
+
+ Transfer-Encoding: chunked
+
+ If multiple encodings have been applied to an entity, the transfer-
+ codings MUST be listed in the order in which they were applied.
+ Additional information about the encoding parameters MAY be provided
+ by other entity-header fields not defined by this specification.
+
+ Many older HTTP/1.0 applications do not understand the Transfer-
+ Encoding header.
+
+14.42 Upgrade
+
+ The Upgrade general-header allows the client to specify what
+ additional communication protocols it supports and would like to use
+ if the server finds it appropriate to switch protocols. The server
+ MUST use the Upgrade header field within a 101 (Switching Protocols)
+ response to indicate which protocol(s) are being switched.
+
+ Upgrade = "Upgrade" ":" 1#product
+
+ For example,
+
+ Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
+
+ The Upgrade header field is intended to provide a simple mechanism
+ for transition from HTTP/1.1 to some other, incompatible protocol. It
+ does so by allowing the client to advertise its desire to use another
+ protocol, such as a later version of HTTP with a higher major version
+ number, even though the current request has been made using HTTP/1.1.
+ This eases the difficult transition between incompatible protocols by
+ allowing the client to initiate a request in the more commonly
+ supported protocol while indicating to the server that it would like
+ to use a "better" protocol if available (where "better" is determined
+ by the server, possibly according to the nature of the method and/or
+ resource being requested).
+
+ The Upgrade header field only applies to switching application-layer
+ protocols upon the existing transport-layer connection. Upgrade
+ cannot be used to insist on a protocol change; its acceptance and use
+ by the server is optional. The capabilities and nature of the
+ application-layer communication after the protocol change is entirely
+ dependent upon the new protocol chosen, although the first action
+ after changing the protocol MUST be a response to the initial HTTP
+ request containing the Upgrade header field.
+
+ The Upgrade header field only applies to the immediate connection.
+ Therefore, the upgrade keyword MUST be supplied within a Connection
+ header field (section 14.10) whenever Upgrade is present in an
+ HTTP/1.1 message.
+
+ The Upgrade header field cannot be used to indicate a switch to a
+ protocol on a different connection. For that purpose, it is more
+ appropriate to use a 301, 302, 303, or 305 redirection response.
+
+ This specification only defines the protocol name "HTTP" for use by
+ the family of Hypertext Transfer Protocols, as defined by the HTTP
+ version rules of section 3.1 and future updates to this
+ specification. Any token can be used as a protocol name; however, it
+ will only be useful if both the client and server associate the name
+ with the same protocol.
+
+14.43 User-Agent
+
+ The User-Agent request-header field contains information about the
+ user agent originating the request. This is for statistical purposes,
+ the tracing of protocol violations, and automated recognition of user
+ agents for the sake of tailoring responses to avoid particular user
+ agent limitations. User agents SHOULD include this field with
+ requests. The field can contain multiple product tokens (section 3.8)
+ and comments identifying the agent and any subproducts which form a
+ significant part of the user agent. By convention, the product tokens
+ are listed in order of their significance for identifying the
+ application.
+
+ User-Agent = "User-Agent" ":" 1*( product | comment )
+
+ Example:
+
+ User-Agent: CERN-LineMode/2.15 libwww/2.17b3
+
+14.44 Vary
+
+ The Vary field value indicates the set of request-header fields that
+ fully determines, while the response is fresh, whether a cache is
+ permitted to use the response to reply to a subsequent request
+ without revalidation. For uncacheable or stale responses, the Vary
+ field value advises the user agent about the criteria that were used
+ to select the representation. A Vary field value of "*" implies that
+ a cache cannot determine from the request headers of a subsequent
+ request whether this response is the appropriate representation. See
+ section 13.6 for use of the Vary header field by caches.
+
+ Vary = "Vary" ":" ( "*" | 1#field-name )
+
+ An HTTP/1.1 server SHOULD include a Vary header field with any
+ cacheable response that is subject to server-driven negotiation.
+ Doing so allows a cache to properly interpret future requests on that
+ resource and informs the user agent about the presence of negotiation
+
+ on that resource. A server MAY include a Vary header field with a
+ non-cacheable response that is subject to server-driven negotiation,
+ since this might provide the user agent with useful information about
+ the dimensions over which the response varies at the time of the
+ response.
+
+ A Vary field value consisting of a list of field-names signals that
+ the representation selected for the response is based on a selection
+ algorithm which considers ONLY the listed request-header field values
+ in selecting the most appropriate representation. A cache MAY assume
+ that the same selection will be made for future requests with the
+ same values for the listed field names, for the duration of time for
+ which the response is fresh.
+
+ The field-names given are not limited to the set of standard
+ request-header fields defined by this specification. Field names are
+ case-insensitive.
+
+ A Vary field value of "*" signals that unspecified parameters not
+ limited to the request-headers (e.g., the network address of the
+ client), play a role in the selection of the response representation.
+ The "*" value MUST NOT be generated by a proxy server; it may only be
+ generated by an origin server.
+
+14.45 Via
+
+ The Via general-header field MUST be used by gateways and proxies to
+ indicate the intermediate protocols and recipients between the user
+ agent and the server on requests, and between the origin server and
+ the client on responses. It is analogous to the "Received" field of
+ <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9] and is intended to be used for tracking message forwards,
+ avoiding request loops, and identifying the protocol capabilities of
+ all senders along the request/response chain.
+
+ Via = "Via" ":" 1#( received-protocol received-by [ comment ] )
+ received-protocol = [ protocol-name "/" ] protocol-version
+ protocol-name = token
+ protocol-version = token
+ received-by = ( host [ ":" port ] ) | pseudonym
+ pseudonym = token
+
+ The received-protocol indicates the protocol version of the message
+ received by the server or client along each segment of the
+ request/response chain. The received-protocol version is appended to
+ the Via field value when the message is forwarded so that information
+ about the protocol capabilities of upstream applications remains
+ visible to all recipients.
+
+ The protocol-name is optional if and only if it would be "HTTP". The
+ received-by field is normally the host and optional port number of a
+ recipient server or client that subsequently forwarded the message.
+ However, if the real host is considered to be sensitive information,
+ it MAY be replaced by a pseudonym. If the port is not given, it MAY
+ be assumed to be the default port of the received-protocol.
+
+ Multiple Via field values represents each proxy or gateway that has
+ forwarded the message. Each recipient MUST append its information
+ such that the end result is ordered according to the sequence of
+ forwarding applications.
+
+ Comments MAY be used in the Via header field to identify the software
+ of the recipient proxy or gateway, analogous to the User-Agent and
+ Server header fields. However, all comments in the Via field are
+ optional and MAY be removed by any recipient prior to forwarding the
+ message.
+
+ For example, a request message could be sent from an HTTP/1.0 user
+ agent to an internal proxy code-named "fred", which uses HTTP/1.1 to
+ forward the request to a public proxy at nowhere.com, which completes
+ the request by forwarding it to the origin server at www.ics.uci.edu.
+ The request received by www.ics.uci.edu would then have the following
+ Via header field:
+
+ Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
+
+ Proxies and gateways used as a portal through a network firewall
+ SHOULD NOT, by default, forward the names and ports of hosts within
+ the firewall region. This information SHOULD only be propagated if
+ explicitly enabled. If not enabled, the received-by host of any host
+ behind the firewall SHOULD be replaced by an appropriate pseudonym
+ for that host.
+
+ For organizations that have strong privacy requirements for hiding
+ internal structures, a proxy MAY combine an ordered subsequence of
+ Via header field entries with identical received-protocol values into
+ a single such entry. For example,
+
+ Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy
+
+ could be collapsed to
+
+ Via: 1.0 ricky, 1.1 mertz, 1.0 lucy
+
+ Applications SHOULD NOT combine multiple entries unless they are all
+ under the same organizational control and the hosts have already been
+ replaced by pseudonyms. Applications MUST NOT combine entries which
+ have different received-protocol values.
+
+14.46 Warning
+
+ The Warning general-header field is used to carry additional
+ information about the status or transformation of a message which
+ might not be reflected in the message. This information is typically
+ used to warn about a possible lack of semantic transparency from
+ caching operations or transformations applied to the entity body of
+ the message.
+
+ Warning headers are sent with responses using:
+
+ Warning = "Warning" ":" 1#warning-value
+
+ warning-value = warn-code SP warn-agent SP warn-text
+ [SP warn-date]
+
+ warn-code = 3DIGIT
+ warn-agent = ( host [ ":" port ] ) | pseudonym
+ ; the name or pseudonym of the server adding
+ ; the Warning header, for use in debugging
+ warn-text = quoted-string
+ warn-date = &lt;"&gt; HTTP-date &lt;"&gt;
+
+ A response MAY carry more than one Warning header.
+
+ The warn-text SHOULD be in a natural language and character set that
+ is most likely to be intelligible to the human user receiving the
+ response. This decision MAY be based on any available knowledge, such
+ as the location of the cache or user, the Accept-Language field in a
+ request, the Content-Language field in a response, etc. The default
+ language is English and the default character set is ISO-8859-1.
+
+ If a character set other than ISO-8859-1 is used, it MUST be encoded
+ in the warn-text using the method described in <a href="http://firefly.troll.no/rfcs/rfc2047.html">RFC 2047</a> [14].
+
+ Warning headers can in general be applied to any message, however
+ some specific warn-codes are specific to caches and can only be
+ applied to response messages. New Warning headers SHOULD be added
+ after any existing Warning headers. A cache MUST NOT delete any
+ Warning header that it received with a message. However, if a cache
+ successfully validates a cache entry, it SHOULD remove any Warning
+ headers previously attached to that entry except as specified for
+
+ specific Warning codes. It MUST then add any Warning headers received
+ in the validating response. In other words, Warning headers are those
+ that would be attached to the most recent relevant response.
+
+ When multiple Warning headers are attached to a response, the user
+ agent ought to inform the user of as many of them as possible, in the
+ order that they appear in the response. If it is not possible to
+ inform the user of all of the warnings, the user agent SHOULD follow
+ these heuristics:
+
+ - Warnings that appear early in the response take priority over
+ those appearing later in the response.
+
+ - Warnings in the user's preferred character set take priority
+ over warnings in other character sets but with identical warn-
+ codes and warn-agents.
+
+ Systems that generate multiple Warning headers SHOULD order them with
+ this user agent behavior in mind.
+
+ Requirements for the behavior of caches with respect to Warnings are
+ stated in section 13.1.2.
+
+ This is a list of the currently-defined warn-codes, each with a
+ recommended warn-text in English, and a description of its meaning.
+
+ 110 Response is stale
+ MUST be included whenever the returned response is stale.
+
+ 111 Revalidation failed
+ MUST be included if a cache returns a stale response because an
+ attempt to revalidate the response failed, due to an inability to
+ reach the server.
+
+ 112 Disconnected operation
+ SHOULD be included if the cache is intentionally disconnected from
+ the rest of the network for a period of time.
+
+ 113 Heuristic expiration
+ MUST be included if the cache heuristically chose a freshness
+ lifetime greater than 24 hours and the response's age is greater
+ than 24 hours.
+
+ 199 Miscellaneous warning
+ The warning text MAY include arbitrary information to be presented
+ to a human user, or logged. A system receiving this warning MUST
+ NOT take any automated action, besides presenting the warning to
+ the user.
+
+ 214 Transformation applied
+ MUST be added by an intermediate cache or proxy if it applies any
+ transformation changing the content-coding (as specified in the
+ Content-Encoding header) or media-type (as specified in the
+ Content-Type header) of the response, or the entity-body of the
+ response, unless this Warning code already appears in the response.
+
+ 299 Miscellaneous persistent warning
+ The warning text MAY include arbitrary information to be presented
+ to a human user, or logged. A system receiving this warning MUST
+ NOT take any automated action.
+
+ If an implementation sends a message with one or more Warning headers
+ whose version is HTTP/1.0 or lower, then the sender MUST include in
+ each warning-value a warn-date that matches the date in the response.
+
+ If an implementation receives a message with a warning-value that
+ includes a warn-date, and that warn-date is different from the Date
+ value in the response, then that warning-value MUST be deleted from
+ the message before storing, forwarding, or using it. (This prevents
+ bad consequences of naive caching of Warning header fields.) If all
+ of the warning-values are deleted for this reason, the Warning header
+ MUST be deleted as well.
+
+14.47 WWW-Authenticate
+
+ The WWW-Authenticate response-header field MUST be included in 401
+ (Unauthorized) response messages. The field value consists of at
+ least one challenge that indicates the authentication scheme(s) and
+ parameters applicable to the Request-URI.
+
+ WWW-Authenticate = "WWW-Authenticate" ":" 1#challenge
+
+ The HTTP access authentication process is described in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43]. User
+ agents are advised to take special care in parsing the WWW-
+ Authenticate field value as it might contain more than one challenge,
+ or if more than one WWW-Authenticate header field is provided, the
+ contents of a challenge itself can contain a comma-separated list of
+ authentication parameters.
+
+15 Security Considerations
+
+ This section is meant to inform application developers, information
+ providers, and users of the security limitations in HTTP/1.1 as
+ described by this document. The discussion does not include
+ definitive solutions to the problems revealed, though it does make
+ some suggestions for reducing security risks.
+
+15.1 Personal Information
+
+ HTTP clients are often privy to large amounts of personal information
+ (e.g. the user's name, location, mail address, passwords, encryption
+ keys, etc.), and SHOULD be very careful to prevent unintentional
+ leakage of this information via the HTTP protocol to other sources.
+ We very strongly recommend that a convenient interface be provided
+ for the user to control dissemination of such information, and that
+ designers and implementors be particularly careful in this area.
+ History shows that errors in this area often create serious security
+ and/or privacy problems and generate highly adverse publicity for the
+ implementor's company.
+
+15.1.1 Abuse of Server Log Information
+
+ A server is in the position to save personal data about a user's
+ requests which might identify their reading patterns or subjects of
+ interest. This information is clearly confidential in nature and its
+ handling can be constrained by law in certain countries. People using
+ the HTTP protocol to provide data are responsible for ensuring that
+ such material is not distributed without the permission of any
+ individuals that are identifiable by the published results.
+
+15.1.2 Transfer of Sensitive Information
+
+ Like any generic data transfer protocol, HTTP cannot regulate the
+ content of the data that is transferred, nor is there any a priori
+ method of determining the sensitivity of any particular piece of
+ information within the context of any given request. Therefore,
+ applications SHOULD supply as much control over this information as
+ possible to the provider of that information. Four header fields are
+ worth special mention in this context: Server, Via, Referer and From.
+
+ Revealing the specific software version of the server might allow the
+ server machine to become more vulnerable to attacks against software
+ that is known to contain security holes. Implementors SHOULD make the
+ Server header field a configurable option.
+
+ Proxies which serve as a portal through a network firewall SHOULD
+ take special precautions regarding the transfer of header information
+ that identifies the hosts behind the firewall. In particular, they
+ SHOULD remove, or replace with sanitized versions, any Via fields
+ generated behind the firewall.
+
+ The Referer header allows reading patterns to be studied and reverse
+ links drawn. Although it can be very useful, its power can be abused
+ if user details are not separated from the information contained in
+
+ the Referer. Even when the personal information has been removed, the
+ Referer header might indicate a private document's URI whose
+ publication would be inappropriate.
+
+ The information sent in the From field might conflict with the user's
+ privacy interests or their site's security policy, and hence it
+ SHOULD NOT be transmitted without the user being able to disable,
+ enable, and modify the contents of the field. The user MUST be able
+ to set the contents of this field within a user preference or
+ application defaults configuration.
+
+ We suggest, though do not require, that a convenient toggle interface
+ be provided for the user to enable or disable the sending of From and
+ Referer information.
+
+ The User-Agent (section 14.43) or Server (section 14.38) header
+ fields can sometimes be used to determine that a specific client or
+ server have a particular security hole which might be exploited.
+ Unfortunately, this same information is often used for other valuable
+ purposes for which HTTP currently has no better mechanism.
+
+15.1.3 Encoding Sensitive Information in URI's
+
+ Because the source of a link might be private information or might
+ reveal an otherwise private information source, it is strongly
+ recommended that the user be able to select whether or not the
+ Referer field is sent. For example, a browser client could have a
+ toggle switch for browsing openly/anonymously, which would
+ respectively enable/disable the sending of Referer and From
+ information.
+
+ Clients SHOULD NOT include a Referer header field in a (non-secure)
+ HTTP request if the referring page was transferred with a secure
+ protocol.
+
+ Authors of services which use the HTTP protocol SHOULD NOT use GET
+ based forms for the submission of sensitive data, because this will
+ cause this data to be encoded in the Request-URI. Many existing
+ servers, proxies, and user agents will log the request URI in some
+ place where it might be visible to third parties. Servers can use
+ POST-based form submission instead
+
+15.1.4 Privacy Issues Connected to Accept Headers
+
+ Accept request-headers can reveal information about the user to all
+ servers which are accessed. The Accept-Language header in particular
+ can reveal information the user would consider to be of a private
+ nature, because the understanding of particular languages is often
+
+ strongly correlated to the membership of a particular ethnic group.
+ User agents which offer the option to configure the contents of an
+ Accept-Language header to be sent in every request are strongly
+ encouraged to let the configuration process include a message which
+ makes the user aware of the loss of privacy involved.
+
+ An approach that limits the loss of privacy would be for a user agent
+ to omit the sending of Accept-Language headers by default, and to ask
+ the user whether or not to start sending Accept-Language headers to a
+ server if it detects, by looking for any Vary response-header fields
+ generated by the server, that such sending could improve the quality
+ of service.
+
+ Elaborate user-customized accept header fields sent in every request,
+ in particular if these include quality values, can be used by servers
+ as relatively reliable and long-lived user identifiers. Such user
+ identifiers would allow content providers to do click-trail tracking,
+ and would allow collaborating content providers to match cross-server
+ click-trails or form submissions of individual users. Note that for
+ many users not behind a proxy, the network address of the host
+ running the user agent will also serve as a long-lived user
+ identifier. In environments where proxies are used to enhance
+ privacy, user agents ought to be conservative in offering accept
+ header configuration options to end users. As an extreme privacy
+ measure, proxies could filter the accept headers in relayed requests.
+ General purpose user agents which provide a high degree of header
+ configurability SHOULD warn users about the loss of privacy which can
+ be involved.
+
+15.2 Attacks Based On File and Path Names
+
+ Implementations of HTTP origin servers SHOULD be careful to restrict
+ the documents returned by HTTP requests to be only those that were
+ intended by the server administrators. If an HTTP server translates
+ HTTP URIs directly into file system calls, the server MUST take
+ special care not to serve files that were not intended to be
+ delivered to HTTP clients. For example, UNIX, Microsoft Windows, and
+ other operating systems use ".." as a path component to indicate a
+ directory level above the current one. On such a system, an HTTP
+ server MUST disallow any such construct in the Request-URI if it
+ would otherwise allow access to a resource outside those intended to
+ be accessible via the HTTP server. Similarly, files intended for
+ reference only internally to the server (such as access control
+ files, configuration files, and script code) MUST be protected from
+ inappropriate retrieval, since they might contain sensitive
+ information. Experience has shown that minor bugs in such HTTP server
+ implementations have turned into security risks.
+
+15.3 DNS Spoofing
+
+ Clients using HTTP rely heavily on the Domain Name Service, and are
+ thus generally prone to security attacks based on the deliberate
+ mis-association of IP addresses and DNS names. Clients need to be
+ cautious in assuming the continuing validity of an IP number/DNS name
+ association.
+
+ In particular, HTTP clients SHOULD rely on their name resolver for
+ confirmation of an IP number/DNS name association, rather than
+ caching the result of previous host name lookups. Many platforms
+ already can cache host name lookups locally when appropriate, and
+ they SHOULD be configured to do so. It is proper for these lookups to
+ be cached, however, only when the TTL (Time To Live) information
+ reported by the name server makes it likely that the cached
+ information will remain useful.
+
+ If HTTP clients cache the results of host name lookups in order to
+ achieve a performance improvement, they MUST observe the TTL
+ information reported by DNS.
+
+ If HTTP clients do not observe this rule, they could be spoofed when
+ a previously-accessed server's IP address changes. As network
+ renumbering is expected to become increasingly common [24], the
+ possibility of this form of attack will grow. Observing this
+ requirement thus reduces this potential security vulnerability.
+
+ This requirement also improves the load-balancing behavior of clients
+ for replicated servers using the same DNS name and reduces the
+ likelihood of a user's experiencing failure in accessing sites which
+ use that strategy.
+
+15.4 Location Headers and Spoofing
+
+ If a single server supports multiple organizations that do not trust
+ one another, then it MUST check the values of Location and Content-
+ Location headers in responses that are generated under control of
+ said organizations to make sure that they do not attempt to
+ invalidate resources over which they have no authority.
+
+15.5 Content-Disposition Issues
+
+ <a href="http://firefly.troll.no/rfcs/rfc1806.html">RFC 1806</a> [35], from which the often implemented Content-Disposition
+ (see section 19.5.1) header in HTTP is derived, has a number of very
+ serious security considerations. Content-Disposition is not part of
+ the HTTP standard, but since it is widely implemented, we are
+ documenting its use and risks for implementors. See <a href="http://firefly.troll.no/rfcs/rfc2183.html">RFC 2183</a> [49]
+ (which updates <a href="http://firefly.troll.no/rfcs/rfc1806.html">RFC 1806</a>) for details.
+
+15.6 Authentication Credentials and Idle Clients
+
+ Existing HTTP clients and user agents typically retain authentication
+ information indefinitely. HTTP/1.1. does not provide a method for a
+ server to direct clients to discard these cached credentials. This is
+ a significant defect that requires further extensions to HTTP.
+ Circumstances under which credential caching can interfere with the
+ application's security model include but are not limited to:
+
+ - Clients which have been idle for an extended period following
+ which the server might wish to cause the client to reprompt the
+ user for credentials.
+
+ - Applications which include a session termination indication
+ (such as a `logout' or `commit' button on a page) after which
+ the server side of the application `knows' that there is no
+ further reason for the client to retain the credentials.
+
+ This is currently under separate study. There are a number of work-
+ arounds to parts of this problem, and we encourage the use of
+ password protection in screen savers, idle time-outs, and other
+ methods which mitigate the security problems inherent in this
+ problem. In particular, user agents which cache credentials are
+ encouraged to provide a readily accessible mechanism for discarding
+ cached credentials under user control.
+
+15.7 Proxies and Caching
+
+ By their very nature, HTTP proxies are men-in-the-middle, and
+ represent an opportunity for man-in-the-middle attacks. Compromise of
+ the systems on which the proxies run can result in serious security
+ and privacy problems. Proxies have access to security-related
+ information, personal information about individual users and
+ organizations, and proprietary information belonging to users and
+ content providers. A compromised proxy, or a proxy implemented or
+ configured without regard to security and privacy considerations,
+ might be used in the commission of a wide range of potential attacks.
+
+ Proxy operators should protect the systems on which proxies run as
+ they would protect any system that contains or transports sensitive
+ information. In particular, log information gathered at proxies often
+ contains highly sensitive personal information, and/or information
+ about organizations. Log information should be carefully guarded, and
+ appropriate guidelines for use developed and followed. (Section
+ 15.1.1).
+
+ Caching proxies provide additional potential vulnerabilities, since
+ the contents of the cache represent an attractive target for
+ malicious exploitation. Because cache contents persist after an HTTP
+ request is complete, an attack on the cache can reveal information
+ long after a user believes that the information has been removed from
+ the network. Therefore, cache contents should be protected as
+ sensitive information.
+
+ Proxy implementors should consider the privacy and security
+ implications of their design and coding decisions, and of the
+ configuration options they provide to proxy operators (especially the
+ default configuration).
+
+ Users of a proxy need to be aware that they are no trustworthier than
+ the people who run the proxy; HTTP itself cannot solve this problem.
+
+ The judicious use of cryptography, when appropriate, may suffice to
+ protect against a broad range of security and privacy attacks. Such
+ cryptography is beyond the scope of the HTTP/1.1 specification.
+
+15.7.1 Denial of Service Attacks on Proxies
+
+ They exist. They are hard to defend against. Research continues.
+ Beware.
+
+16 Acknowledgments
+
+ This specification makes heavy use of the augmented BNF and generic
+ constructs defined by David H. Crocker for <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a> [9]. Similarly, it
+ reuses many of the definitions provided by Nathaniel Borenstein and
+ Ned Freed for MIME [7]. We hope that their inclusion in this
+ specification will help reduce past confusion over the relationship
+ between HTTP and Internet mail message formats.
+
+ The HTTP protocol has evolved considerably over the years. It has
+ benefited from a large and active developer community--the many
+ people who have participated on the www-talk mailing list--and it is
+ that community which has been most responsible for the success of
+ HTTP and of the World-Wide Web in general. Marc Andreessen, Robert
+ Cailliau, Daniel W. Connolly, Bob Denny, John Franks, Jean-Francois
+ Groff, Phillip M. Hallam-Baker, Hakon W. Lie, Ari Luotonen, Rob
+ McCool, Lou Montulli, Dave Raggett, Tony Sanders, and Marc
+ VanHeyningen deserve special recognition for their efforts in
+ defining early aspects of the protocol.
+
+ This document has benefited greatly from the comments of all those
+ participating in the HTTP-WG. In addition to those already mentioned,
+ the following individuals have contributed to this specification:
+
+ Gary Adams Ross Patterson
+ Harald Tveit Alvestrand Albert Lunde
+ Keith Ball John C. Mallery
+ Brian Behlendorf Jean-Philippe Martin-Flatin
+ Paul Burchard Mitra
+ Maurizio Codogno David Morris
+ Mike Cowlishaw Gavin Nicol
+ Roman Czyborra Bill Perry
+ Michael A. Dolan Jeffrey Perry
+ David J. Fiander Scott Powers
+ Alan Freier Owen Rees
+ Marc Hedlund Luigi Rizzo
+ Greg Herlihy David Robinson
+ Koen Holtman Marc Salomon
+ Alex Hopmann Rich Salz
+ Bob Jernigan Allan M. Schiffman
+ Shel Kaphan Jim Seidman
+ Rohit Khare Chuck Shotton
+ John Klensin Eric W. Sink
+ Martijn Koster Simon E. Spero
+ Alexei Kosut Richard N. Taylor
+ David M. Kristol Robert S. Thau
+ Daniel LaLiberte Bill (BearHeart) Weinman
+ Ben Laurie Francois Yergeau
+ Paul J. Leach Mary Ellen Zurko
+ Daniel DuBois Josh Cohen
+
+ Much of the content and presentation of the caching design is due to
+ suggestions and comments from individuals including: Shel Kaphan,
+ Paul Leach, Koen Holtman, David Morris, and Larry Masinter.
+
+ Most of the specification of ranges is based on work originally done
+ by Ari Luotonen and John Franks, with additional input from Steve
+ Zilles.
+
+ Thanks to the "cave men" of Palo Alto. You know who you are.
+
+ Jim Gettys (the current editor of this document) wishes particularly
+ to thank Roy Fielding, the previous editor of this document, along
+ with John Klensin, Jeff Mogul, Paul Leach, Dave Kristol, Koen
+ Holtman, John Franks, Josh Cohen, Alex Hopmann, Scott Lawrence, and
+ Larry Masinter for their help. And thanks go particularly to Jeff
+ Mogul and Scott Lawrence for performing the "MUST/MAY/SHOULD" audit.
+
+ The Apache Group, Anselm Baird-Smith, author of Jigsaw, and Henrik
+ Frystyk implemented <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> early, and we wish to thank them for the
+ discovery of many of the problems that this document attempts to
+ rectify.
+
+17 References
+
+ [1] Alvestrand, H., "Tags for the Identification of Languages", RFC
+ 1766, March 1995.
+
+ [2] Anklesaria, F., McCahill, M., Lindner, P., Johnson, D., Torrey,
+ D. and B. Alberti, "The Internet Gopher Protocol (a distributed
+ document search and retrieval protocol)", <a href="http://firefly.troll.no/rfcs/rfc1436.html">RFC 1436</a>, March 1993.
+
+ [3] Berners-Lee, T., "Universal Resource Identifiers in WWW", RFC
+ 1630, June 1994.
+
+ [4] Berners-Lee, T., Masinter, L. and M. McCahill, "Uniform Resource
+ Locators (URL)", <a href="http://firefly.troll.no/rfcs/rfc1738.html">RFC 1738</a>, December 1994.
+
+ [5] Berners-Lee, T. and D. Connolly, "Hypertext Markup Language -
+ 2.0", <a href="http://firefly.troll.no/rfcs/rfc1866.html">RFC 1866</a>, November 1995.
+
+ [6] Berners-Lee, T., Fielding, R. and H. Frystyk, "Hypertext Transfer
+ Protocol -- HTTP/1.0", <a href="http://firefly.troll.no/rfcs/rfc1945.html">RFC 1945</a>, May 1996.
+
+ [7] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message Bodies",
+ <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a>, November 1996.
+
+ [8] Braden, R., "Requirements for Internet Hosts -- Communication
+ Layers", STD 3, <a href="http://firefly.troll.no/rfcs/rfc1123.html">RFC 1123</a>, October 1989.
+
+ [9] Crocker, D., "Standard for The Format of ARPA Internet Text
+ Messages", STD 11, <a href="http://firefly.troll.no/rfcs/rfc822.html">RFC 822</a>, August 1982.
+
+ [10] Davis, F., Kahle, B., Morris, H., Salem, J., Shen, T., Wang, R.,
+ Sui, J., and M. Grinbaum, "WAIS Interface Protocol Prototype
+ Functional Specification," (v1.5), Thinking Machines
+ Corporation, April 1990.
+
+ [11] Fielding, R., "Relative Uniform Resource Locators", <a href="http://firefly.troll.no/rfcs/rfc1808.html">RFC 1808</a>,
+ June 1995.
+
+ [12] Horton, M. and R. Adams, "Standard for Interchange of USENET
+ Messages", <a href="http://firefly.troll.no/rfcs/rfc1036.html">RFC 1036</a>, December 1987.
+
+ [13] Kantor, B. and P. Lapsley, "Network News Transfer Protocol", RFC
+ 977, February 1986.
+
+ [14] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part
+ Three: Message Header Extensions for Non-ASCII Text", <a href="http://firefly.troll.no/rfcs/rfc2047.html">RFC 2047</a>,
+ November 1996.
+
+ [15] Nebel, E. and L. Masinter, "Form-based File Upload in HTML", RFC
+ 1867, November 1995.
+
+ [16] Postel, J., "Simple Mail Transfer Protocol", STD 10, <a href="http://firefly.troll.no/rfcs/rfc821.html">RFC 821</a>,
+ August 1982.
+
+ [17] Postel, J., "Media Type Registration Procedure", <a href="http://firefly.troll.no/rfcs/rfc1590.html">RFC 1590</a>,
+ November 1996.
+
+ [18] Postel, J. and J. Reynolds, "File Transfer Protocol", STD 9, RFC
+ 959, October 1985.
+
+ [19] Reynolds, J. and J. Postel, "Assigned Numbers", STD 2, <a href="http://firefly.troll.no/rfcs/rfc1700.html">RFC 1700</a>,
+ October 1994.
+
+ [20] Sollins, K. and L. Masinter, "Functional Requirements for
+ Uniform Resource Names", <a href="http://firefly.troll.no/rfcs/rfc1737.html">RFC 1737</a>, December 1994.
+
+ [21] US-ASCII. Coded Character Set - 7-Bit American Standard Code for
+ Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.
+
+ [22] ISO-8859. International Standard -- Information Processing --
+ 8-bit Single-Byte Coded Graphic Character Sets --
+ Part 1: Latin alphabet No. 1, ISO-8859-1:1987.
+ Part 2: Latin alphabet No. 2, ISO-8859-2, 1987.
+ Part 3: Latin alphabet No. 3, ISO-8859-3, 1988.
+ Part 4: Latin alphabet No. 4, ISO-8859-4, 1988.
+ Part 5: Latin/Cyrillic alphabet, ISO-8859-5, 1988.
+ Part 6: Latin/Arabic alphabet, ISO-8859-6, 1987.
+ Part 7: Latin/Greek alphabet, ISO-8859-7, 1987.
+ Part 8: Latin/Hebrew alphabet, ISO-8859-8, 1988.
+ Part 9: Latin alphabet No. 5, ISO-8859-9, 1990.
+
+ [23] Meyers, J. and M. Rose, "The Content-MD5 Header Field", RFC
+ 1864, October 1995.
+
+ [24] Carpenter, B. and Y. Rekhter, "Renumbering Needs Work", RFC
+ 1900, February 1996.
+
+ [25] Deutsch, P., "GZIP file format specification version 4.3", RFC
+ 1952, May 1996.
+
+ [26] Venkata N. Padmanabhan, and Jeffrey C. Mogul. "Improving HTTP
+ Latency", Computer Networks and ISDN Systems, v. 28, pp. 25-35,
+ Dec. 1995. Slightly revised version of paper in Proc. 2nd
+ International WWW Conference '94: Mosaic and the Web, Oct. 1994,
+ which is available at
+ <a href="http://www.ncsa.uiuc.edu/SDG/IT94/Proceedings/DDay/mogul/HTTPLat">http://www.ncsa.uiuc.edu/SDG/IT94/Proceedings/DDay/mogul/HTTPLat</a>
+ ency.html.
+
+ [27] Joe Touch, John Heidemann, and Katia Obraczka. "Analysis of HTTP
+ Performance", &lt;URL: <a href="http://www.isi.edu/touch/pubs/http-perf96/">http://www.isi.edu/touch/pubs/http-perf96/</a>&gt;,
+ ISI Research Report ISI/RR-98-463, (original report dated Aug.
+ 1996), USC/Information Sciences Institute, August 1998.
+
+ [28] Mills, D., "Network Time Protocol (Version 3) Specification,
+ Implementation and Analysis", <a href="http://firefly.troll.no/rfcs/rfc1305.html">RFC 1305</a>, March 1992.
+
+ [29] Deutsch, P., "DEFLATE Compressed Data Format Specification
+ version 1.3", <a href="http://firefly.troll.no/rfcs/rfc1951.html">RFC 1951</a>, May 1996.
+
+ [30] S. Spero, "Analysis of HTTP Performance Problems,"
+ <a href="http://sunsite.unc.edu/mdma-release/http-prob.html">http://sunsite.unc.edu/mdma-release/http-prob.html</a>.
+
+ [31] Deutsch, P. and J. Gailly, "ZLIB Compressed Data Format
+ Specification version 3.3", <a href="http://firefly.troll.no/rfcs/rfc1950.html">RFC 1950</a>, May 1996.
+
+ [32] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P.,
+ Luotonen, A., Sink, E. and L. Stewart, "An Extension to HTTP:
+ Digest Access Authentication", <a href="http://firefly.troll.no/rfcs/rfc2069.html">RFC 2069</a>, January 1997.
+
+ [33] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T.
+ Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC
+ 2068, January 1997.
+
+ [34] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, <a href="http://firefly.troll.no/rfcs/rfc2119.html">RFC 2119</a>, March 1997.
+
+ [35] Troost, R. and Dorner, S., "Communicating Presentation
+ Information in Internet Messages: The Content-Disposition
+ Header", <a href="http://firefly.troll.no/rfcs/rfc1806.html">RFC 1806</a>, June 1995.
+
+ [36] Mogul, J., Fielding, R., Gettys, J. and H. Frystyk, "Use and
+ Interpretation of HTTP Version Numbers", <a href="http://firefly.troll.no/rfcs/rfc2145.html">RFC 2145</a>, May 1997.
+ [jg639]
+
+ [37] Palme, J., "Common Internet Message Headers", <a href="http://firefly.troll.no/rfcs/rfc2076.html">RFC 2076</a>, February
+ 1997. [jg640]
+
+ [38] Yergeau, F., "UTF-8, a transformation format of Unicode and
+ ISO-10646", <a href="http://firefly.troll.no/rfcs/rfc2279.html">RFC 2279</a>, January 1998. [jg641]
+
+ [39] Nielsen, H.F., Gettys, J., Baird-Smith, A., Prud'hommeaux, E.,
+ Lie, H., and C. Lilley. "Network Performance Effects of
+ HTTP/1.1, CSS1, and PNG," Proceedings of ACM SIGCOMM '97, Cannes
+ France, September 1997.[jg642]
+
+ [40] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", <a href="http://firefly.troll.no/rfcs/rfc2046.html">RFC 2046</a>, November
+ 1996. [jg643]
+
+ [41] Alvestrand, H., "IETF Policy on Character Sets and Languages",
+ BCP 18, <a href="http://firefly.troll.no/rfcs/rfc2277.html">RFC 2277</a>, January 1998. [jg644]
+
+ [42] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource
+ Identifiers (URI): Generic Syntax and Semantics", <a href="http://firefly.troll.no/rfcs/rfc2396.html">RFC 2396</a>,
+ August 1998. [jg645]
+
+ [43] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,
+ Leach, P., Luotonen, A., Sink, E. and L. Stewart, "HTTP
+ Authentication: Basic and Digest Access Authentication", RFC
+ 2617, June 1999. [jg646]
+
+ [44] Luotonen, A., "Tunneling TCP based protocols through Web proxy
+ servers," Work in Progress. [jg647]
+
+ [45] Palme, J. and A. Hopmann, "MIME E-mail Encapsulation of
+ Aggregate Documents, such as HTML (MHTML)", <a href="http://firefly.troll.no/rfcs/rfc2110.html">RFC 2110</a>, March
+ 1997.
+
+ [46] Bradner, S., "The Internet Standards Process -- Revision 3", BCP
+ 9, <a href="http://firefly.troll.no/rfcs/rfc2026.html">RFC 2026</a>, October 1996.
+
+ [47] Masinter, L., "Hyper Text Coffee Pot Control Protocol
+ (HTCPCP/1.0)", <a href="http://firefly.troll.no/rfcs/rfc2324.html">RFC 2324</a>, 1 April 1998.
+
+ [48] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Five: Conformance Criteria and Examples",
+ <a href="http://firefly.troll.no/rfcs/rfc2049.html">RFC 2049</a>, November 1996.
+
+ [49] Troost, R., Dorner, S. and K. Moore, "Communicating Presentation
+ Information in Internet Messages: The Content-Disposition Header
+ Field", <a href="http://firefly.troll.no/rfcs/rfc2183.html">RFC 2183</a>, August 1997.
+
+18 Authors' Addresses
+
+ Roy T. Fielding
+ Information and Computer Science
+ University of California, Irvine
+ Irvine, CA 92697-3425, USA
+
+ Fax: +1 (949) 824-1715
+ EMail: <a href="mailto:fielding@ics.uci.edu">fielding@ics.uci.edu</a>
+
+ James Gettys
+ World Wide Web Consortium
+ MIT Laboratory for Computer Science
+ 545 Technology Square
+ Cambridge, MA 02139, USA
+
+ Fax: +1 (617) 258 8682
+ EMail: <a href="mailto:jg@w3.org">jg@w3.org</a>
+
+ Jeffrey C. Mogul
+ Western Research Laboratory
+ Compaq Computer Corporation
+ 250 University Avenue
+ Palo Alto, California, 94305, USA
+
+ EMail: <a href="mailto:mogul@wrl.dec.com">mogul@wrl.dec.com</a>
+
+ Henrik Frystyk Nielsen
+ World Wide Web Consortium
+ MIT Laboratory for Computer Science
+ 545 Technology Square
+ Cambridge, MA 02139, USA
+
+ Fax: +1 (617) 258 8682
+ EMail: <a href="mailto:frystyk@w3.org">frystyk@w3.org</a>
+
+ Larry Masinter
+ Xerox Corporation
+ 3333 Coyote Hill Road
+ Palo Alto, CA 94034, USA
+
+ EMail: <a href="mailto:masinter@parc.xerox.com">masinter@parc.xerox.com</a>
+
+ Paul J. Leach
+ Microsoft Corporation
+ 1 Microsoft Way
+ Redmond, WA 98052, USA
+
+ EMail: <a href="mailto:paulle@microsoft.com">paulle@microsoft.com</a>
+
+ Tim Berners-Lee
+ Director, World Wide Web Consortium
+ MIT Laboratory for Computer Science
+ 545 Technology Square
+ Cambridge, MA 02139, USA
+
+ Fax: +1 (617) 258 8682
+ EMail: <a href="mailto:timbl@w3.org">timbl@w3.org</a>
+
+19 Appendices
+
+19.1 Internet Media Type message/http and application/http
+
+ In addition to defining the HTTP/1.1 protocol, this document serves
+ as the specification for the Internet media type "message/http" and
+ "application/http". The message/http type can be used to enclose a
+ single HTTP request or response message, provided that it obeys the
+ MIME restrictions for all "message" types regarding line length and
+ encodings. The application/http type can be used to enclose a
+ pipeline of one or more HTTP request or response messages (not
+ intermixed). The following is to be registered with IANA [17].
+
+ Media Type name: message
+ Media subtype name: http
+ Required parameters: none
+ Optional parameters: version, msgtype
+ version: The HTTP-Version number of the enclosed message
+ (e.g., "1.1"). If not present, the version can be
+ determined from the first line of the body.
+ msgtype: The message type -- "request" or "response". If not
+ present, the type can be determined from the first
+ line of the body.
+ Encoding considerations: only "7bit", "8bit", or "binary" are
+ permitted
+ Security considerations: none
+
+ Media Type name: application
+ Media subtype name: http
+ Required parameters: none
+ Optional parameters: version, msgtype
+ version: The HTTP-Version number of the enclosed messages
+ (e.g., "1.1"). If not present, the version can be
+ determined from the first line of the body.
+ msgtype: The message type -- "request" or "response". If not
+ present, the type can be determined from the first
+ line of the body.
+ Encoding considerations: HTTP messages enclosed by this type
+ are in "binary" format; use of an appropriate
+ Content-Transfer-Encoding is required when
+ transmitted via E-mail.
+ Security considerations: none
+
+19.2 Internet Media Type multipart/byteranges
+
+ When an HTTP 206 (Partial Content) response message includes the
+ content of multiple ranges (a response to a request for multiple
+ non-overlapping ranges), these are transmitted as a multipart
+ message-body. The media type for this purpose is called
+ "multipart/byteranges".
+
+ The multipart/byteranges media type includes two or more parts, each
+ with its own Content-Type and Content-Range fields. The required
+ boundary parameter specifies the boundary string used to separate
+ each body-part.
+
+ Media Type name: multipart
+ Media subtype name: byteranges
+ Required parameters: boundary
+ Optional parameters: none
+ Encoding considerations: only "7bit", "8bit", or "binary" are
+ permitted
+ Security considerations: none
+
+ For example:
+
+ HTTP/1.1 206 Partial Content
+ Date: Wed, 15 Nov 1995 06:25:24 GMT
+ Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
+ Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
+
+ --THIS_STRING_SEPARATES
+ Content-type: application/pdf
+ Content-range: bytes 500-999/8000
+
+ ...the first range...
+ --THIS_STRING_SEPARATES
+ Content-type: application/pdf
+ Content-range: bytes 7000-7999/8000
+
+ ...the second range
+ --THIS_STRING_SEPARATES--
+
+ Notes:
+
+ 1) Additional CRLFs may precede the first boundary string in the
+ entity.
+
+ 2) Although <a href="http://firefly.troll.no/rfcs/rfc2046.html">RFC 2046</a> [40] permits the boundary string to be
+ quoted, some existing implementations handle a quoted boundary
+ string incorrectly.
+
+ 3) A number of browsers and servers were coded to an early draft
+ of the byteranges specification to use a media type of
+ multipart/x-byteranges, which is almost, but not quite
+ compatible with the version documented in HTTP/1.1.
+
+19.3 Tolerant Applications
+
+ Although this document specifies the requirements for the generation
+ of HTTP/1.1 messages, not all applications will be correct in their
+ implementation. We therefore recommend that operational applications
+ be tolerant of deviations whenever those deviations can be
+ interpreted unambiguously.
+
+ Clients SHOULD be tolerant in parsing the Status-Line and servers
+ tolerant when parsing the Request-Line. In particular, they SHOULD
+ accept any amount of SP or HT characters between fields, even though
+ only a single SP is required.
+
+ The line terminator for message-header fields is the sequence CRLF.
+ However, we recommend that applications, when parsing such headers,
+ recognize a single LF as a line terminator and ignore the leading CR.
+
+ The character set of an entity-body SHOULD be labeled as the lowest
+ common denominator of the character codes used within that body, with
+ the exception that not labeling the entity is preferred over labeling
+ the entity with the labels US-ASCII or ISO-8859-1. See section 3.7.1
+ and 3.4.1.
+
+ Additional rules for requirements on parsing and encoding of dates
+ and other potential problems with date encodings include:
+
+ - HTTP/1.1 clients and caches SHOULD assume that an <a href="http://firefly.troll.no/rfcs/rfc850.html">RFC-850</a> date
+ which appears to be more than 50 years in the future is in fact
+ in the past (this helps solve the "year 2000" problem).
+
+ - An HTTP/1.1 implementation MAY internally represent a parsed
+ Expires date as earlier than the proper value, but MUST NOT
+ internally represent a parsed Expires date as later than the
+ proper value.
+
+ - All expiration-related calculations MUST be done in GMT. The
+ local time zone MUST NOT influence the calculation or comparison
+ of an age or expiration time.
+
+ - If an HTTP header incorrectly carries a date value with a time
+ zone other than GMT, it MUST be converted into GMT using the
+ most conservative possible conversion.
+
+19.4 Differences Between HTTP Entities and <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a> Entities
+
+ HTTP/1.1 uses many of the constructs defined for Internet Mail (RFC
+ 822 [9]) and the Multipurpose Internet Mail Extensions (MIME [7]) to
+ allow entities to be transmitted in an open variety of
+ representations and with extensible mechanisms. However, <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a>
+ discusses mail, and HTTP has a few features that are different from
+ those described in <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a>. These differences were carefully chosen
+ to optimize performance over binary connections, to allow greater
+ freedom in the use of new media types, to make date comparisons
+ easier, and to acknowledge the practice of some early HTTP servers
+ and clients.
+
+ This appendix describes specific areas where HTTP differs from RFC
+ 2045. Proxies and gateways to strict MIME environments SHOULD be
+ aware of these differences and provide the appropriate conversions
+ where necessary. Proxies and gateways from MIME environments to HTTP
+ also need to be aware of the differences because some conversions
+ might be required.
+
+19.4.1 MIME-Version
+
+ HTTP is not a MIME-compliant protocol. However, HTTP/1.1 messages MAY
+ include a single MIME-Version general-header field to indicate what
+ version of the MIME protocol was used to construct the message. Use
+ of the MIME-Version header field indicates that the message is in
+ full compliance with the MIME protocol (as defined in <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a>[7]).
+ Proxies/gateways are responsible for ensuring full compliance (where
+ possible) when exporting HTTP messages to strict MIME environments.
+
+ MIME-Version = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT
+
+ MIME version "1.0" is the default for use in HTTP/1.1. However,
+ HTTP/1.1 message parsing and semantics are defined by this document
+ and not the MIME specification.
+
+19.4.2 Conversion to Canonical Form
+
+ <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a> [7] requires that an Internet mail entity be converted to
+ canonical form prior to being transferred, as described in section 4
+ of <a href="http://firefly.troll.no/rfcs/rfc2049.html">RFC 2049</a> [48]. Section 3.7.1 of this document describes the forms
+ allowed for subtypes of the "text" media type when transmitted over
+ HTTP. <a href="http://firefly.troll.no/rfcs/rfc2046.html">RFC 2046</a> requires that content with a type of "text" represent
+ line breaks as CRLF and forbids the use of CR or LF outside of line
+
+ break sequences. HTTP allows CRLF, bare CR, and bare LF to indicate a
+ line break within text content when a message is transmitted over
+ HTTP.
+
+ Where it is possible, a proxy or gateway from HTTP to a strict MIME
+ environment SHOULD translate all line breaks within the text media
+ types described in section 3.7.1 of this document to the <a href="http://firefly.troll.no/rfcs/rfc2049.html">RFC 2049</a>
+ canonical form of CRLF. Note, however, that this might be complicated
+ by the presence of a Content-Encoding and by the fact that HTTP
+ allows the use of some character sets which do not use octets 13 and
+ 10 to represent CR and LF, as is the case for some multi-byte
+ character sets.
+
+ Implementors should note that conversion will break any cryptographic
+ checksums applied to the original content unless the original content
+ is already in canonical form. Therefore, the canonical form is
+ recommended for any content that uses such checksums in HTTP.
+
+19.4.3 Conversion of Date Formats
+
+ HTTP/1.1 uses a restricted set of date formats (section 3.3.1) to
+ simplify the process of date comparison. Proxies and gateways from
+ other protocols SHOULD ensure that any Date header field present in a
+ message conforms to one of the HTTP/1.1 formats and rewrite the date
+ if necessary.
+
+19.4.4 Introduction of Content-Encoding
+
+ <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a> does not include any concept equivalent to HTTP/1.1's
+ Content-Encoding header field. Since this acts as a modifier on the
+ media type, proxies and gateways from HTTP to MIME-compliant
+ protocols MUST either change the value of the Content-Type header
+ field or decode the entity-body before forwarding the message. (Some
+ experimental applications of Content-Type for Internet mail have used
+ a media-type parameter of ";conversions=&lt;content-coding&gt;" to perform
+ a function equivalent to Content-Encoding. However, this parameter is
+ not part of <a href="http://firefly.troll.no/rfcs/rfc2045.html">RFC 2045</a>.)
+
+19.4.5 No Content-Transfer-Encoding
+
+ HTTP does not use the Content-Transfer-Encoding (CTE) field of RFC
+ 2045. Proxies and gateways from MIME-compliant protocols to HTTP MUST
+ remove any non-identity CTE ("quoted-printable" or "base64") encoding
+ prior to delivering the response message to an HTTP client.
+
+ Proxies and gateways from HTTP to MIME-compliant protocols are
+ responsible for ensuring that the message is in the correct format
+ and encoding for safe transport on that protocol, where "safe
+
+ transport" is defined by the limitations of the protocol being used.
+ Such a proxy or gateway SHOULD label the data with an appropriate
+ Content-Transfer-Encoding if doing so will improve the likelihood of
+ safe transport over the destination protocol.
+
+19.4.6 Introduction of Transfer-Encoding
+
+ HTTP/1.1 introduces the Transfer-Encoding header field (section
+ 14.41). Proxies/gateways MUST remove any transfer-coding prior to
+ forwarding a message via a MIME-compliant protocol.
+
+ A process for decoding the "chunked" transfer-coding (section 3.6)
+ can be represented in pseudo-code as:
+
+ length := 0
+ read chunk-size, chunk-extension (if any) and CRLF
+ while (chunk-size &gt; 0) {
+ read chunk-data and CRLF
+ append chunk-data to entity-body
+ length := length + chunk-size
+ read chunk-size and CRLF
+ }
+ read entity-header
+ while (entity-header not empty) {
+ append entity-header to existing header fields
+ read entity-header
+ }
+ Content-Length := length
+ Remove "chunked" from Transfer-Encoding
+
+19.4.7 MHTML and Line Length Limitations
+
+ HTTP implementations which share code with MHTML [45] implementations
+ need to be aware of MIME line length limitations. Since HTTP does not
+ have this limitation, HTTP does not fold long lines. MHTML messages
+ being transported by HTTP follow all conventions of MHTML, including
+ line length limitations and folding, canonicalization, etc., since
+ HTTP transports all message-bodies as payload (see section 3.7.2) and
+ does not interpret the content or any MIME header lines that might be
+ contained therein.
+
+19.5 Additional Features
+
+ <a href="http://firefly.troll.no/rfcs/rfc1945.html">RFC 1945</a> and <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> document protocol elements used by some
+ existing HTTP implementations, but not consistently and correctly
+ across most HTTP/1.1 applications. Implementors are advised to be
+ aware of these features, but cannot rely upon their presence in, or
+ interoperability with, other HTTP/1.1 applications. Some of these
+
+ describe proposed experimental features, and some describe features
+ that experimental deployment found lacking that are now addressed in
+ the base HTTP/1.1 specification.
+
+ A number of other headers, such as Content-Disposition and Title,
+ from SMTP and MIME are also often implemented (see <a href="http://firefly.troll.no/rfcs/rfc2076.html">RFC 2076</a> [37]).
+
+19.5.1 Content-Disposition
+
+ The Content-Disposition response-header field has been proposed as a
+ means for the origin server to suggest a default filename if the user
+ requests that the content is saved to a file. This usage is derived
+ from the definition of Content-Disposition in <a href="http://firefly.troll.no/rfcs/rfc1806.html">RFC 1806</a> [35].
+
+ content-disposition = "Content-Disposition" ":"
+ disposition-type *( ";" disposition-parm )
+ disposition-type = "attachment" | disp-extension-token
+ disposition-parm = filename-parm | disp-extension-parm
+ filename-parm = "filename" "=" quoted-string
+ disp-extension-token = token
+ disp-extension-parm = token "=" ( token | quoted-string )
+
+ An example is
+
+ Content-Disposition: attachment; filename="fname.ext"
+
+ The receiving user agent SHOULD NOT respect any directory path
+ information present in the filename-parm parameter, which is the only
+ parameter believed to apply to HTTP implementations at this time. The
+ filename SHOULD be treated as a terminal component only.
+
+ If this header is used in a response with the application/octet-
+ stream content-type, the implied suggestion is that the user agent
+ should not display the response, but directly enter a `save response
+ as...' dialog.
+
+ See section 15.5 for Content-Disposition security issues.
+
+19.6 Compatibility with Previous Versions
+
+ It is beyond the scope of a protocol specification to mandate
+ compliance with previous versions. HTTP/1.1 was deliberately
+ designed, however, to make supporting previous versions easy. It is
+ worth noting that, at the time of composing this specification
+ (1996), we would expect commercial HTTP/1.1 servers to:
+
+ - recognize the format of the Request-Line for HTTP/0.9, 1.0, and
+ 1.1 requests;
+
+ - understand any valid request in the format of HTTP/0.9, 1.0, or
+ 1.1;
+
+ - respond appropriately with a message in the same major version
+ used by the client.
+
+ And we would expect HTTP/1.1 clients to:
+
+ - recognize the format of the Status-Line for HTTP/1.0 and 1.1
+ responses;
+
+ - understand any valid response in the format of HTTP/0.9, 1.0, or
+ 1.1.
+
+ For most implementations of HTTP/1.0, each connection is established
+ by the client prior to the request and closed by the server after
+ sending the response. Some implementations implement the Keep-Alive
+ version of persistent connections described in section 19.7.1 of RFC
+ 2068 [33].
+
+19.6.1 Changes from HTTP/1.0
+
+ This section summarizes major differences between versions HTTP/1.0
+ and HTTP/1.1.
+
+19.6.1.1 Changes to Simplify Multi-homed Web Servers and Conserve IP
+ Addresses
+
+ The requirements that clients and servers support the Host request-
+ header, report an error if the Host request-header (section 14.23) is
+ missing from an HTTP/1.1 request, and accept absolute URIs (section
+ 5.1.2) are among the most important changes defined by this
+ specification.
+
+ Older HTTP/1.0 clients assumed a one-to-one relationship of IP
+ addresses and servers; there was no other established mechanism for
+ distinguishing the intended server of a request than the IP address
+ to which that request was directed. The changes outlined above will
+ allow the Internet, once older HTTP clients are no longer common, to
+ support multiple Web sites from a single IP address, greatly
+ simplifying large operational Web servers, where allocation of many
+ IP addresses to a single host has created serious problems. The
+ Internet will also be able to recover the IP addresses that have been
+ allocated for the sole purpose of allowing special-purpose domain
+ names to be used in root-level HTTP URLs. Given the rate of growth of
+ the Web, and the number of servers already deployed, it is extremely
+
+ important that all implementations of HTTP (including updates to
+ existing HTTP/1.0 applications) correctly implement these
+ requirements:
+
+ - Both clients and servers MUST support the Host request-header.
+
+ - A client that sends an HTTP/1.1 request MUST send a Host header.
+
+ - Servers MUST report a 400 (Bad Request) error if an HTTP/1.1
+ request does not include a Host request-header.
+
+ - Servers MUST accept absolute URIs.
+
+19.6.2 Compatibility with HTTP/1.0 Persistent Connections
+
+ Some clients and servers might wish to be compatible with some
+ previous implementations of persistent connections in HTTP/1.0
+ clients and servers. Persistent connections in HTTP/1.0 are
+ explicitly negotiated as they are not the default behavior. HTTP/1.0
+ experimental implementations of persistent connections are faulty,
+ and the new facilities in HTTP/1.1 are designed to rectify these
+ problems. The problem was that some existing 1.0 clients may be
+ sending Keep-Alive to a proxy server that doesn't understand
+ Connection, which would then erroneously forward it to the next
+ inbound server, which would establish the Keep-Alive connection and
+ result in a hung HTTP/1.0 proxy waiting for the close on the
+ response. The result is that HTTP/1.0 clients must be prevented from
+ using Keep-Alive when talking to proxies.
+
+ However, talking to proxies is the most important use of persistent
+ connections, so that prohibition is clearly unacceptable. Therefore,
+ we need some other mechanism for indicating a persistent connection
+ is desired, which is safe to use even when talking to an old proxy
+ that ignores Connection. Persistent connections are the default for
+ HTTP/1.1 messages; we introduce a new keyword (Connection: close) for
+ declaring non-persistence. See section 14.10.
+
+ The original HTTP/1.0 form of persistent connections (the Connection:
+ Keep-Alive and Keep-Alive header) is documented in <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>. [33]
+
+19.6.3 Changes from <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>
+
+ This specification has been carefully audited to correct and
+ disambiguate key word usage; <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> had many problems in respect to
+ the conventions laid out in <a href="http://firefly.troll.no/rfcs/rfc2119.html">RFC 2119</a> [34].
+
+ Clarified which error code should be used for inbound server failures
+ (e.g. DNS failures). (Section 10.5.5).
+
+ CREATE had a race that required an Etag be sent when a resource is
+ first created. (Section 10.2.2).
+
+ Content-Base was deleted from the specification: it was not
+ implemented widely, and there is no simple, safe way to introduce it
+ without a robust extension mechanism. In addition, it is used in a
+ similar, but not identical fashion in MHTML [45].
+
+ Transfer-coding and message lengths all interact in ways that
+ required fixing exactly when chunked encoding is used (to allow for
+ transfer encoding that may not be self delimiting); it was important
+ to straighten out exactly how message lengths are computed. (Sections
+ 3.6, 4.4, 7.2.2, 13.5.2, 14.13, 14.16)
+
+ A content-coding of "identity" was introduced, to solve problems
+ discovered in caching. (section 3.5)
+
+ Quality Values of zero should indicate that "I don't want something"
+ to allow clients to refuse a representation. (Section 3.9)
+
+ The use and interpretation of HTTP version numbers has been clarified
+ by <a href="http://firefly.troll.no/rfcs/rfc2145.html">RFC 2145</a>. Require proxies to upgrade requests to highest protocol
+ version they support to deal with problems discovered in HTTP/1.0
+ implementations (Section 3.1)
+
+ Charset wildcarding is introduced to avoid explosion of character set
+ names in accept headers. (Section 14.2)
+
+ A case was missed in the Cache-Control model of HTTP/1.1; s-maxage
+ was introduced to add this missing case. (Sections 13.4, 14.8, 14.9,
+ 14.9.3)
+
+ The Cache-Control: max-age directive was not properly defined for
+ responses. (Section 14.9.3)
+
+ There are situations where a server (especially a proxy) does not
+ know the full length of a response but is capable of serving a
+ byterange request. We therefore need a mechanism to allow byteranges
+ with a content-range not indicating the full length of the message.
+ (Section 14.16)
+
+ Range request responses would become very verbose if all meta-data
+ were always returned; by allowing the server to only send needed
+ headers in a 206 response, this problem can be avoided. (Section
+ 10.2.7, 13.5.3, and 14.27)
+
+ Fix problem with unsatisfiable range requests; there are two cases:
+ syntactic problems, and range doesn't exist in the document. The 416
+ status code was needed to resolve this ambiguity needed to indicate
+ an error for a byte range request that falls outside of the actual
+ contents of a document. (Section 10.4.17, 14.16)
+
+ Rewrite of message transmission requirements to make it much harder
+ for implementors to get it wrong, as the consequences of errors here
+ can have significant impact on the Internet, and to deal with the
+ following problems:
+
+ 1. Changing "HTTP/1.1 or later" to "HTTP/1.1", in contexts where
+ this was incorrectly placing a requirement on the behavior of
+ an implementation of a future version of HTTP/1.x
+
+ 2. Made it clear that user-agents should retry requests, not
+ "clients" in general.
+
+ 3. Converted requirements for clients to ignore unexpected 100
+ (Continue) responses, and for proxies to forward 100 responses,
+ into a general requirement for 1xx responses.
+
+ 4. Modified some TCP-specific language, to make it clearer that
+ non-TCP transports are possible for HTTP.
+
+ 5. Require that the origin server MUST NOT wait for the request
+ body before it sends a required 100 (Continue) response.
+
+ 6. Allow, rather than require, a server to omit 100 (Continue) if
+ it has already seen some of the request body.
+
+ 7. Allow servers to defend against denial-of-service attacks and
+ broken clients.
+
+ This change adds the Expect header and 417 status code. The message
+ transmission requirements fixes are in sections 8.2, 10.4.18,
+ 8.1.2.2, 13.11, and 14.20.
+
+ Proxies should be able to add Content-Length when appropriate.
+ (Section 13.5.2)
+
+ Clean up confusion between 403 and 404 responses. (Section 10.4.4,
+ 10.4.5, and 10.4.11)
+
+ Warnings could be cached incorrectly, or not updated appropriately.
+ (Section 13.1.2, 13.2.4, 13.5.2, 13.5.3, 14.9.3, and 14.46) Warning
+ also needed to be a general header, as PUT or other methods may have
+ need for it in requests.
+
+ Transfer-coding had significant problems, particularly with
+ interactions with chunked encoding. The solution is that transfer-
+ codings become as full fledged as content-codings. This involves
+ adding an IANA registry for transfer-codings (separate from content
+ codings), a new header field (TE) and enabling trailer headers in the
+ future. Transfer encoding is a major performance benefit, so it was
+ worth fixing [39]. TE also solves another, obscure, downward
+ interoperability problem that could have occurred due to interactions
+ between authentication trailers, chunked encoding and HTTP/1.0
+ clients.(Section 3.6, 3.6.1, and 14.39)
+
+ The PATCH, LINK, UNLINK methods were defined but not commonly
+ implemented in previous versions of this specification. See <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a>
+ [33].
+
+ The Alternates, Content-Version, Derived-From, Link, URI, Public and
+ Content-Base header fields were defined in previous versions of this
+ specification, but not commonly implemented. See <a href="http://firefly.troll.no/rfcs/rfc2068.html">RFC 2068</a> [33].
+
+20 Index
+
+ Please see the PostScript version of this RFC for the INDEX.
+
+21. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+</pre>
+<p align="center"><script language="JavaScript"><!--
+erfc("2616");
+// --></script><a href="http://firefly.troll.no/rfccomment.php?rfcnum=2616" target="_blank" onclick="window.open('/rfccomment.php?rfcnum=2616','Popup','toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=680,height=530,left=30,top=43'); return false;" )="">Comment on RFC 2616</a>
+</p>
+&nbsp;<br>
+<div align="center">
+<center>
+<table border="0" cellpadding="4" cellspacing="4" width="100%">
+<tbody><tr><td bgcolor="#d6d6c0" width="100%">
+<p><font face="Arial">Comments about this RFC:</font></p>
+<ul>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-869.html">RFC 2616: Very basic HTTP Server written in Emacs Lisp: http://www.chez.com/emarsden/downl...</a> by Alex Schröder (5/12/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-539.html">RFC 2616: If someone has got sample code for a basic HTTP/1.1 Server please let me know......</a> by Mike (2/4/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-486.html">RFC 2616: I am seeking ladies for nothing but sex that is all i want from the lady sorry...</a> by treblav (1/16/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2360.html">RFC 2616: Hello.
+
+ I have realized that point 8.1.4 of the RFC 2616 is a big threat to...</a> by Doolyo (8/20/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1522.html">RFC 2616: êêêöïïäììóì::::::@::@"""@:&gt;c
+ :::@"$$%^^*^^*((((99(
+ &lt;&lt;&gt;:"? </a> by óäöóöóöóö (12/16/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2147.html">RFC 2616: Man Such a big and boring doc.. thats why ppl shy away from RFC stuff. Make it...</a> by AnurgaM (6/15/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2277.html">RFC 2616: igeve uo 100 dolars
+
+ iwant password
+
+ farh51@hotmail.com </a> by farh (7/24/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2349.html">RFC 2616: I have realized that point 8.1.4 of this RFC is a big threat to the load speed...</a> by Doolyo (8/15/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1230.html">RFC 2616: Would it possible to extend the
+ protocol to allow another GET,
+ HEAD, POST,...</a> by CCaldwell (9/15/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-692.html">RFC 2616: Wonder if he got his lady? </a> by SinJax (3/26/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2056.html">RFC 2616: it's for shareaza that the program go fasther </a> by sylle (5/24/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-2526.html">RFC 2616: Only 2 simultaneous connections is a big threat to the load speed of HTML...</a> by Doolyo (9/30/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-736.html">RFC 2616: yo to the southampton uni coursework massive </a> by anon (4/6/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1574.html">RFC 2616: If you know everything about HTTP this rfc will be helpful to you (as a recap...</a> by just a developer (1/5/2005)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1111.html">RFC 2616: Please note that section 3.6.2, referenced in section 3.5 (page 25)
+ may most...</a> by Patrick Powell (8/12/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1354.html">RFC 2616: gtu87t 86t8o;koip]0-n df bhvfjkhfgfter6ecvgjlhhjuhjioy uftyei vn bk.jljpoi
+ =- ...</a> by jkl (10/20/2004)</font></li>
+<li><font face="Arial"><a href="http://firefly.troll.no/qa/rfcc-1973.html">RFC 2616: I HOPE KNOW MANY OF SOME RFC </a> by MARRY (5/5/2005)</font></li>
+</ul>
+</td></tr></tbody></table> <br></center></div>
+<div align="center">
+<table border="0" cellpadding="3" cellspacing="3" width="100%">
+<tbody><tr><td width="45%">
+<p align="left">Previous: <a href="http://firefly.troll.no/rfcs/rfc2615.html">RFC 2615 - PPP over SONET/SDH</a>
+</p></td><td width="10%">&nbsp;</td><td width="45%">
+<p align="right">Next: <a href="http://firefly.troll.no/rfcs/rfc2617.html">RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication</a>
+</p></td></tr></tbody></table></div><p align="right">&nbsp;</p>
+<hr noshade="noshade" size="2">
+<div align="center">[ <a href="http://firefly.troll.no/rfcs/">RFC Index</a> | <a href="http://firefly.troll.no/rfcs/rfcsearch.html">RFC Search</a> | <a href="http://firefly.troll.no/faqs/">Usenet FAQs</a> | <a href="http://firefly.troll.no/contrib/">Web FAQs</a> | <a href="http://firefly.troll.no/docs/">Documents</a> | <a href="http://www.city-data.com/">Cities</a> ]
+<p>
+</p></div>
+ <a href="http://firefly.troll.no/ftp/rfc/rfc2616.pdf">rfc2616.pdf</a>
+<small>
+<address>
+<p align="center">
+
+</p>
+</address>
+</small>
+</body></html> \ No newline at end of file
diff --git a/tests/testserver/common/.gitattributes b/tests/testserver/common/.gitattributes
new file mode 100644
index 0000000000..21f6efbe14
--- /dev/null
+++ b/tests/testserver/common/.gitattributes
@@ -0,0 +1,2 @@
+*.sh text eol=lf
+*.conf text eol=lf
diff --git a/tests/testserver/common/ssl.sh b/tests/testserver/common/ssl.sh
index 8a4728ad4d..2593a22979 100755
--- a/tests/testserver/common/ssl.sh
+++ b/tests/testserver/common/ssl.sh
@@ -35,5 +35,6 @@ set -ex
# install ssl_certs and test data
su $USER -c "mkdir -p -m 700 ~/ssl-certs/private"
-su $USER -c "cp $CONFIG/ssl/qt-test-server-cert.pem ~/ssl-certs/"
+su $USER -c \
+ "cp $CONFIG/ssl/${test_cert:-qt-test-server-cert.pem} ~/ssl-certs/qt-test-server-cert.pem"
su $USER -c "cp $CONFIG/ssl/private/qt-test-server-key.pem ~/ssl-certs/private/"
diff --git a/tests/testserver/common/startup.sh b/tests/testserver/common/startup.sh
index 84d4003f86..1386314e38 100755
--- a/tests/testserver/common/startup.sh
+++ b/tests/testserver/common/startup.sh
@@ -34,7 +34,7 @@ set -ex
# export variables
export USER=qt-test-server
export PASS=password
-export CONFIG=common/testdata
+export CONFIG=service/testdata
export TESTDATA=service/testdata
# add users
@@ -43,15 +43,4 @@ useradd -m -s /bin/bash $USER; echo "$USER:$PASS" | chpasswd
# install configurations and test data
su $USER -c "cp $CONFIG/system/passwords ~/"
-# modules initialization (apache2.sh, ftp-proxy.sh ...)
-for RUN_CMD
-do $RUN_CMD
-done
-
-# start multicast DNS service discovery (mDNS)
-sed -i "s,#domain-name=local,domain-name=test-net.qt.local," /etc/avahi/avahi-daemon.conf
-service dbus restart
-service avahi-daemon restart
-
-# keep-alive in docker detach mode
-sleep infinity
+./startup.sh "$@"
diff --git a/tests/testserver/common/testdata/ssl/qt-test-server-host-network-cacert.pem b/tests/testserver/common/testdata/ssl/qt-test-server-host-network-cacert.pem
new file mode 100644
index 0000000000..5bdce3a3f9
--- /dev/null
+++ b/tests/testserver/common/testdata/ssl/qt-test-server-host-network-cacert.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIClzCCAgACCQDeuuUc2HkfKDANBgkqhkiG9w0BAQQFADCBjzELMAkGA1UEChMC
+UXQxGTAXBgNVBAsTEENvcmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5v
+Ym9keS5xdC5pbzENMAsGA1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UE
+BhMCTk8xHTAbBgNVBAMTFHF0LXRlc3Qtc2VydmVyLmxvY2FsMB4XDTE5MDEyNTE1
+NDE0N1oXDTQ5MDExNzE1NDE0N1owgY8xCzAJBgNVBAoTAlF0MRkwFwYDVQQLExBD
+b3JlIEFuZCBOZXR3b3JrMRswGQYJKoZIhvcNAQkBFgxub2JvZHkucXQuaW8xDTAL
+BgNVBAcTBE9zbG8xDTALBgNVBAgTBE9zbG8xCzAJBgNVBAYTAk5PMR0wGwYDVQQD
+ExRxdC10ZXN0LXNlcnZlci5sb2NhbDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAzarbb9Y0yafxwL7kQRgZ4gLJIuan1boDLp4oevRfGndfd6kRO49+8C7Gnus6
+2RLXwQxR6CRSPyPDQgwRxvIcoUL+tMJpg633cLEYFcwgKGIw8CwV5jMZr8PrHMCR
+9xFolFD4STcIMtc+dd+jvGkAFd7Nhw9cAmuCyAF9avAd3HMCAwEAATANBgkqhkiG
+9w0BAQQFAAOBgQB1dxK3Ia4sCpvSikKLaf1ZXu+9GKaNWKJe9bWex9/RmNOla9N2
+FIh6/CfaPFDy/OXCkyEiGg78iyg/DgqVoa9JJGV3diI6berisHMPJpv1syyz9YEU
+G3RQUClPcPV6EcedyqCdpbnIFtiSZbtJ0ZBGef4KzBN3rTmPucKb+bhMPg==
+-----END CERTIFICATE-----
diff --git a/tests/testserver/cyrus/cyrus.sh b/tests/testserver/cyrus/cyrus.sh
new file mode 100755
index 0000000000..92c3bfa703
--- /dev/null
+++ b/tests/testserver/cyrus/cyrus.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2019 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+echo "tls_cert_file: /home/qt-test-server/ssl-certs/qt-test-server-cert.pem" >> /etc/imapd.conf
+echo "tls_key_file: /home/qt-test-server/ssl-certs/private/qt-test-server-key.pem" >> /etc/imapd.conf
+chmod +3 /home/qt-test-server/ssl-certs/private/
+mkdir -m 007 -p /run/cyrus/proc
+sed -i 's/#imaps\t\tcmd="imapd/imaps\t\tcmd="imapd/' /etc/cyrus.conf
+
+service cyrus-imapd restart
diff --git a/tests/testserver/danted/.gitattributes b/tests/testserver/danted/.gitattributes
new file mode 100644
index 0000000000..21f6efbe14
--- /dev/null
+++ b/tests/testserver/danted/.gitattributes
@@ -0,0 +1,2 @@
+*.sh text eol=lf
+*.conf text eol=lf
diff --git a/tests/testserver/danted/danted.sh b/tests/testserver/danted/danted.sh
index bf3d154f33..97e2142401 100755
--- a/tests/testserver/danted/danted.sh
+++ b/tests/testserver/danted/danted.sh
@@ -39,6 +39,25 @@ useradd -d /dev/null -s /bin/false qsockstest; echo "qsockstest:$PASS" | chpassw
# install configurations and test data
cp $TESTDATA/danted{,-authenticating}.conf /etc/
+# Use the input environment variables to overwrite the default value of internal interfaces.
+if [ "$danted_internal" -a "$danted_internal" != eth0 ]
+then sed -i "s,internal: eth0 port = 1080,internal: $danted_internal port = 1080," /etc/danted.conf
+fi
+
+if [ "$danted_auth_internal" -a "$danted_auth_internal" != eth0 ]
+then sed -i "s,internal: eth0 port = 1081,internal: $danted_auth_internal port = 1081," \
+ /etc/danted-authenticating.conf
+fi
+
+# Use the input environment variables to overwrite the default value of external interfaces.
+if [ "$danted_external" -a "$danted_external" != eth0 ]
+then sed -i "s,external: eth0,external: $danted_external," /etc/danted.conf
+fi
+
+if [ "$danted_auth_external" -a "$danted_auth_external" != eth0 ]
+then sed -i "s,external: eth0,external: $danted_auth_external," /etc/danted-authenticating.conf
+fi
+
# enable service with installed configurations
service danted start
service danted-authenticating start
diff --git a/tests/testserver/docker-compose-for-macOS.yml b/tests/testserver/docker-compose-for-macOS.yml
new file mode 100644
index 0000000000..c5348e27b6
--- /dev/null
+++ b/tests/testserver/docker-compose-for-macOS.yml
@@ -0,0 +1,113 @@
+version: '3.4'
+
+# The tag of images is used by docker compose file to launch the corresponding
+# docker containers. The value of tag comes from the provisioning script
+# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
+# of each server context as the tag of docker images. If one of the server
+# contexts gets changes, please make sure to update this compose file as well.
+# You can run command 'docker images' to list all the tags of test server images.
+# For example:
+# REPOSITORY TAG
+# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
+
+services:
+ apache2:
+ container_name: qt-test-server-apache2
+ domainname: ${TEST_DOMAIN}
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
+ shareDir: ./common
+ serviceDir: ./apache2
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: [service/ssl.sh, service/apache2.sh]
+ network_mode: "host"
+ extra_hosts:
+ - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
+ environment:
+ - test_cert="qt-test-server-host-network-cacert.pem"
+
+ squid:
+ container_name: qt-test-server-squid
+ domainname: ${TEST_DOMAIN}
+ depends_on:
+ - apache2
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
+ shareDir: ./common
+ serviceDir: ./squid
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: service/squid.sh
+ network_mode: "host"
+ extra_hosts:
+ - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
+
+ vsftpd:
+ container_name: qt-test-server-vsftpd
+ domainname: ${TEST_DOMAIN}
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
+ shareDir: ./common
+ serviceDir: ./vsftpd
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: service/vsftpd.sh
+ network_mode: "host"
+ extra_hosts:
+ - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
+
+ ftp-proxy:
+ container_name: qt-test-server-ftp-proxy
+ domainname: ${TEST_DOMAIN}
+ depends_on:
+ - vsftpd
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
+ shareDir: ./common
+ serviceDir: ./ftp-proxy
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: service/ftp-proxy.sh
+ network_mode: "host"
+ extra_hosts:
+ - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
+
+ danted:
+ container_name: qt-test-server-danted
+ domainname: ${TEST_DOMAIN}
+ depends_on:
+ - apache2
+ - vsftpd
+ - ftp-proxy
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
+ shareDir: ./common
+ serviceDir: ./danted
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: service/danted.sh
+ network_mode: "host"
+ extra_hosts:
+ - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
+ environment:
+ - danted_internal=${MACHINE_IP}
+ - danted_external=${MACHINE_IP}
+ - danted_auth_internal=${MACHINE_IP}
+ - danted_auth_external=${MACHINE_IP}
+
diff --git a/tests/testserver/docker-compose-for-windows.yml b/tests/testserver/docker-compose-for-windows.yml
new file mode 100644
index 0000000000..c5348e27b6
--- /dev/null
+++ b/tests/testserver/docker-compose-for-windows.yml
@@ -0,0 +1,113 @@
+version: '3.4'
+
+# The tag of images is used by docker compose file to launch the corresponding
+# docker containers. The value of tag comes from the provisioning script
+# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
+# of each server context as the tag of docker images. If one of the server
+# contexts gets changes, please make sure to update this compose file as well.
+# You can run command 'docker images' to list all the tags of test server images.
+# For example:
+# REPOSITORY TAG
+# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
+
+services:
+ apache2:
+ container_name: qt-test-server-apache2
+ domainname: ${TEST_DOMAIN}
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
+ shareDir: ./common
+ serviceDir: ./apache2
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: [service/ssl.sh, service/apache2.sh]
+ network_mode: "host"
+ extra_hosts:
+ - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
+ environment:
+ - test_cert="qt-test-server-host-network-cacert.pem"
+
+ squid:
+ container_name: qt-test-server-squid
+ domainname: ${TEST_DOMAIN}
+ depends_on:
+ - apache2
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
+ shareDir: ./common
+ serviceDir: ./squid
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: service/squid.sh
+ network_mode: "host"
+ extra_hosts:
+ - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
+
+ vsftpd:
+ container_name: qt-test-server-vsftpd
+ domainname: ${TEST_DOMAIN}
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
+ shareDir: ./common
+ serviceDir: ./vsftpd
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: service/vsftpd.sh
+ network_mode: "host"
+ extra_hosts:
+ - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
+
+ ftp-proxy:
+ container_name: qt-test-server-ftp-proxy
+ domainname: ${TEST_DOMAIN}
+ depends_on:
+ - vsftpd
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
+ shareDir: ./common
+ serviceDir: ./ftp-proxy
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: service/ftp-proxy.sh
+ network_mode: "host"
+ extra_hosts:
+ - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
+
+ danted:
+ container_name: qt-test-server-danted
+ domainname: ${TEST_DOMAIN}
+ depends_on:
+ - apache2
+ - vsftpd
+ - ftp-proxy
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
+ shareDir: ./common
+ serviceDir: ./danted
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: service/danted.sh
+ network_mode: "host"
+ extra_hosts:
+ - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
+ environment:
+ - danted_internal=${MACHINE_IP}
+ - danted_external=${MACHINE_IP}
+ - danted_auth_internal=${MACHINE_IP}
+ - danted_auth_external=${MACHINE_IP}
+
diff --git a/tests/testserver/docker-compose.yml b/tests/testserver/docker-compose.yml
index a151d6bfb0..75e8a0fea2 100644
--- a/tests/testserver/docker-compose.yml
+++ b/tests/testserver/docker-compose.yml
@@ -7,77 +7,151 @@ version: '3.4'
# contexts gets changes, please make sure to update this compose file as well.
# You can run command 'docker images' to list all the tag of test server images.
# For example:
-# REPOSITORY TAG IMAGE ID
-# qt-test-server-apache2 e2a70c8b169c204e762b375885bd3a26cc40ba48 2ad5c8720317
+# REPOSITORY TAG
+# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
services:
apache2:
- image: qt-test-server-apache2:cc9ea678b92bdda33acb9fa0159bb4ad0f3cd947
container_name: qt-test-server-apache2
- domainname: test-net.qt.local
+ domainname: ${TEST_DOMAIN}
hostname: apache2
- volumes:
- - ./common:/common:ro
- - ./apache2:/service:ro
- entrypoint: common/startup.sh
- command: [common/ssl.sh, service/apache2.sh]
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
+ shareDir: ./common
+ serviceDir: ./apache2
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: [service/ssl.sh, service/apache2.sh]
squid:
- image: qt-test-server-squid:577d99307eea9a8cccfec944d25be2bce2fe99cc
container_name: qt-test-server-squid
- domainname: test-net.qt.local
+ domainname: ${TEST_DOMAIN}
hostname: squid
depends_on:
- apache2
external_links:
- - apache2:apache2.test-net.qt.local
- volumes:
- - ./common:/common:ro
- - ./squid:/service:ro
- entrypoint: common/startup.sh
+ - apache2:apache2.${TEST_DOMAIN}
+ - cyrus:cyrus.${TEST_DOMAIN}
+ - iptables:iptables.${TEST_DOMAIN}
+ - vsftpd:vsftpd.${TEST_DOMAIN}
+ - echo:echo.${TEST_DOMAIN}
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
+ shareDir: ./common
+ serviceDir: ./squid
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
command: service/squid.sh
vsftpd:
- image: qt-test-server-vsftpd:18896604c7e90b543e56d80c8a8aabdb65a590d0
container_name: qt-test-server-vsftpd
- domainname: test-net.qt.local
+ domainname: ${TEST_DOMAIN}
hostname: vsftpd
- volumes:
- - ./common:/common:ro
- - ./vsftpd:/service:ro
- entrypoint: common/startup.sh
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
+ shareDir: ./common
+ serviceDir: ./vsftpd
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
command: service/vsftpd.sh
ftp-proxy:
- image: qt-test-server-ftp-proxy:2c6c8f1ab6a364b540c43d705fb6f15a585cb2af
container_name: qt-test-server-ftp-proxy
- domainname: test-net.qt.local
+ domainname: ${TEST_DOMAIN}
hostname: ftp-proxy
depends_on:
- vsftpd
external_links:
- - vsftpd:vsftpd.test-net.qt.local
- volumes:
- - ./common:/common:ro
- - ./ftp-proxy:/service:ro
- entrypoint: common/startup.sh
+ - vsftpd:vsftpd.${TEST_DOMAIN}
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
+ shareDir: ./common
+ serviceDir: ./ftp-proxy
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
command: service/ftp-proxy.sh
danted:
- image: qt-test-server-danted:327dd56c3c35db85b26fac93213a5a1918475bc7
container_name: qt-test-server-danted
- domainname: test-net.qt.local
+ domainname: ${TEST_DOMAIN}
hostname: danted
depends_on:
- apache2
- vsftpd
- ftp-proxy
external_links:
- - apache2:apache2.test-net.qt.local
- - vsftpd:vsftpd.test-net.qt.local
- - ftp-proxy:ftp-proxy.test-net.qt.local
- volumes:
- - ./common:/common:ro
- - ./danted:/service:ro
- entrypoint: common/startup.sh
+ - apache2:apache2.${TEST_DOMAIN}
+ - vsftpd:vsftpd.${TEST_DOMAIN}
+ - ftp-proxy:ftp-proxy.${TEST_DOMAIN}
+ - cyrus:cyrus.${TEST_DOMAIN}
+ - echo:echo.${TEST_DOMAIN}
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
+ shareDir: ./common
+ serviceDir: ./danted
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
command: service/danted.sh
+
+ cyrus:
+ container_name: qt-test-server-cyrus
+ domainname: ${TEST_DOMAIN}
+ hostname: cyrus
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-cyrus:c8d72754abc0e501afd624ce838e4df35505abc9
+ shareDir: ./common
+ serviceDir: ./cyrus
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: [service/ssl.sh, service/cyrus.sh]
+
+ iptables:
+ container_name: qt-test-server-iptables
+ domainname: ${TEST_DOMAIN}
+ hostname: iptables
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-iptables:cb7a8bd6d28602085a88c8ced7d67e28e75781e2
+ shareDir: ./common
+ serviceDir: ./iptables
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: service/iptables.sh
+ cap_add:
+ - NET_ADMIN
+ - NET_RAW
+
+ echo:
+ container_name: qt-test-server-echo
+ domainname: ${TEST_DOMAIN}
+ hostname: echo
+ build:
+ context: .
+ dockerfile: ${SHARED_DATA}/Dockerfile
+ args:
+ provisioningImage: qt-test-server-echo:b29ad409e746a834c1055fd0f7a55fd5056da6ea
+ shareDir: ./common
+ serviceDir: ./echo
+ test_domain: ${TEST_DOMAIN}
+ entrypoint: service/startup.sh
+ command: service/echo.sh
diff --git a/tests/testserver/echo/echo.sh b/tests/testserver/echo/echo.sh
new file mode 100755
index 0000000000..f0da9627d5
--- /dev/null
+++ b/tests/testserver/echo/echo.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+# Disabled by default, enable it.
+sed -i 's/disable\t\t= yes/disable = no/' /etc/xinetd.d/echo
+sed -i 's/disable\t\t= yes/disable = no/' /etc/xinetd.d/daytime
+
+service xinetd restart
diff --git a/tests/testserver/ftp-proxy/.gitattributes b/tests/testserver/ftp-proxy/.gitattributes
new file mode 100644
index 0000000000..21f6efbe14
--- /dev/null
+++ b/tests/testserver/ftp-proxy/.gitattributes
@@ -0,0 +1,2 @@
+*.sh text eol=lf
+*.conf text eol=lf
diff --git a/tests/testserver/ftp-proxy/ftp-proxy.sh b/tests/testserver/ftp-proxy/ftp-proxy.sh
index 087a7b7bcc..e5b9631bbb 100755
--- a/tests/testserver/ftp-proxy/ftp-proxy.sh
+++ b/tests/testserver/ftp-proxy/ftp-proxy.sh
@@ -34,7 +34,9 @@ set -ex
# package ftp-proxy
# install configurations and test data
-sed -i 's/# AllowMagicUser\tno/AllowMagicUser\tyes/' /etc/proxy-suite/ftp-proxy.conf
+sed -i -e 's/# AllowMagicUser\tno/AllowMagicUser\tyes/' \
+ -e 's/# ForkLimit\t\t40/ForkLimit\t\t2000/' \
+ /etc/proxy-suite/ftp-proxy.conf
# enable service with installed configurations
ftp-proxy -d
diff --git a/tests/testserver/iptables/iptables.sh b/tests/testserver/iptables/iptables.sh
new file mode 100755
index 0000000000..9a48686d8b
--- /dev/null
+++ b/tests/testserver/iptables/iptables.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2019 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+iptables -A INPUT -p tcp --destination-port 1357 -j DROP
diff --git a/tests/testserver/squid/.gitattributes b/tests/testserver/squid/.gitattributes
new file mode 100644
index 0000000000..21f6efbe14
--- /dev/null
+++ b/tests/testserver/squid/.gitattributes
@@ -0,0 +1,2 @@
+*.sh text eol=lf
+*.conf text eol=lf
diff --git a/tests/testserver/vsftpd/.gitattributes b/tests/testserver/vsftpd/.gitattributes
new file mode 100644
index 0000000000..67af4c73e8
--- /dev/null
+++ b/tests/testserver/vsftpd/.gitattributes
@@ -0,0 +1,2 @@
+* text eol=lf
+*.gif -text
diff --git a/tests/testserver/vsftpd/testdata/vsftpd.conf b/tests/testserver/vsftpd/testdata/vsftpd.conf
index 6bdb186c9f..e67cccefcc 100644
--- a/tests/testserver/vsftpd/testdata/vsftpd.conf
+++ b/tests/testserver/vsftpd/testdata/vsftpd.conf
@@ -101,6 +101,10 @@ userlist_enable=YES
listen=YES
tcp_wrappers=YES
+# An internal setting used for testing the relative benefit of using the
+# sendfile() system call on your platform.
+use_sendfile=NO
+
# Enabling SFTP
#ssl_enable=YES
#allow_anon_ssl=YES
diff --git a/tests/testserver/vsftpd/vsftpd.sh b/tests/testserver/vsftpd/vsftpd.sh
index 1ba1a8c347..bd09ad3902 100755
--- a/tests/testserver/vsftpd/vsftpd.sh
+++ b/tests/testserver/vsftpd/vsftpd.sh
@@ -41,9 +41,10 @@ useradd -d "/home/$USER/ftp" -s /bin/bash ftptest; echo "ftptest:$PASS" | chpass
cp $TESTDATA/vsftpd.{conf,user_list} /etc/
# Resolve error message "vsftpd failed - probably invalid config" during boot
-command='start-stop-daemon --start --background -m --oknodo --pidfile /var/run/vsftpd/vsftpd.pid'
-command+=' --exec ${DAEMON}'
-sed -i "s,$command.*$,$command; sleep 1," /etc/init.d/vsftpd
+# This bug has been reported to Debian bug tracking system (ID #911396)
+command='ps -C vsftpd | grep -qs "${_PID}"'
+sed -i -e 's,while [ ${n} -le 5 ].*$,while true,' \
+ -e "s,\t\t\tif ! $command.*$,\t\t\tif $command," /etc/init.d/vsftpd
# Populate the FTP sites:
su $USER -c "cp -r $TESTDATA/ftp ~/ftp"
@@ -53,6 +54,10 @@ ln -s /home/$USER/ftp /var/ftp
su $USER -c "mkdir -p ~/ftp/qtest/"
su $USER -c "cp rfc3252.txt ~/ftp/qtest/"; rm rfc3252.txt
+# tst_QNetworkReply::proxy_data()
+su $USER -c "ln ~/ftp/qtest/rfc3252.txt ~/ftp/qtest/rfc3252"
+su $USER -c "mkdir -p ~/ftp/qtest/nonASCII/"
+
# Duplicate rfc3252.txt 20 times for bigfile tests:
su $USER -c "seq 20 | xargs -i cat ~/ftp/qtest/rfc3252.txt >> ~/ftp/qtest/bigfile"
diff --git a/util/corelib/qurl-generateTLDs/main.cpp b/util/corelib/qurl-generateTLDs/main.cpp
index 006eaf92b1..e458ea9d53 100644
--- a/util/corelib/qurl-generateTLDs/main.cpp
+++ b/util/corelib/qurl-generateTLDs/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the utils of the Qt Toolkit.
@@ -28,54 +28,93 @@
#include <QtCore>
+const QString quadQuote = QStringLiteral("\"\""); // Closes one string, opens a new one.
+
static QString utf8encode(const QByteArray &array) // turns e.g. tranøy.no to tran\xc3\xb8y.no
{
QString result;
result.reserve(array.length() + array.length() / 3);
+ bool wasHex = false;
for (int i = 0; i < array.length(); ++i) {
char c = array.at(i);
// if char is non-ascii, escape it
if (c < 0x20 || uchar(c) >= 0x7f) {
result += "\\x" + QString::number(uchar(c), 16);
+ wasHex = true;
} else {
// if previous char was escaped, we need to make sure the next char is not
// interpreted as part of the hex value, e.g. "äc.com" -> "\xabc.com"; this
// should be "\xab""c.com"
- QRegExp hexEscape("\\\\x[a-fA-F0-9][a-fA-F0-9]$");
bool isHexChar = ((c >= '0' && c <= '9') ||
- (c >= 'a' && c <= 'f') ||
- (c >= 'A' && c <= 'F'));
- if (result.contains(hexEscape) && isHexChar)
- result += "\"\"";
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F'));
+ if (wasHex && isHexChar)
+ result += quadQuote;
result += c;
+ wasHex = false;
}
}
return result;
}
-int main(int argc, char **argv) {
+/*
+ Digest public suffix data into efficiently-searchable form.
+
+ Takes the public suffix list (see usage message), a list of DNS domains
+ whose child domains should not be presumed to trust one another, and
+ converts it to a form that lets qtbase/src/corelib/io/qtldurl.cpp's query
+ functions find entries efficiently.
+
+ Each line of the suffix file (aside from comments and blanks) gives a suffix
+ (starting with a dot) with an optional prefix of '*' (to include every
+ immediate child) or of '!' (to exclude the suffix, e.g. from a '*' line for
+ a tail of it). A line with neither of these prefixes is an exact match.
+
+ Each line is hashed and the hash is reduced modulo the number of lines
+ (tldCount); lines are grouped by reduced hash and separated by '\0' bytes
+ within each group. Conceptually, the groups are then emitted to a single
+ huge string, along with a table (tldIndices[tldCount]) of indices into that
+ string of the starts of the the various groups.
+ However, that huge string would exceed the 64k limit at least one compiler
+ imposes on a single string literal, so we actually split up the huge string
+ into an array of chunks, each less than 64k in size. Each group is written
+ to a single chunk (so we start a new chunk if the next group would take the
+ present chunk over the limit). There are tldChunkCount chunks; their lengths
+ are saved in tldChunks[tldChunkCount]; the chunks themselves in
+ tldData[tldChunkCount]. See qtldurl.cpp's containsTLDEntry() for how to
+ search for a string in the resulting data.
+*/
+
+int main(int argc, char **argv)
+{
QCoreApplication app(argc, argv);
if (argc < 3) {
- printf("\nusage: %s inputFile outputFile\n\n", argv[0]);
+ printf("\nUsage: ./%s inputFile outputFile\n\n", argv[0]);
printf("'inputFile' should be a list of effective TLDs, one per line,\n");
- printf("as obtained from http://publicsuffix.org . To create indices and data file\n");
+ printf("as obtained from http://publicsuffix.org/. To create indices and data\n");
printf("file, do the following:\n\n");
- printf(" wget https://publicsuffix.org/list/effective_tld_names.dat -O effective_tld_names.dat\n");
- printf(" grep '^[^\\/\\/]' effective_tld_names.dat > effective_tld_names.dat.trimmed\n");
- printf(" %s effective_tld_names.dat.trimmed effective_tld_names.dat.qt\n\n", argv[0]);
- printf("Now copy the data from effective_tld_names.dat.qt to the file src/corelib/io/qurltlds_p.h in your Qt repo\n\n");
- exit(1);
+ printf(" wget https://publicsuffix.org/list/public_suffix_list.dat -O public_suffix_list.dat\n");
+ printf(" grep -v '^//' public_suffix_list.dat | grep . > public_suffix_list.dat.trimmed\n");
+ printf(" ./%s public_suffix_list.dat.trimmed public_suffix_list.cpp\n\n", argv[0]);
+ printf("Now replace the code in qtbase/src/corelib/io/qurltlds_p.h with public_suffix_list.cpp's contents\n\n");
+ return 1;
}
QFile file(argv[1]);
- QFile outFile(argv[2]);
- file.open(QIODevice::ReadOnly);
- outFile.open(QIODevice::WriteOnly);
+ if (!file.open(QIODevice::ReadOnly)) {
+ fprintf("Failed to open input file (%s); see %s -usage", argv[1], argv[0]);
+ return 1;
+ }
- QByteArray outIndicesBufferBA;
- QBuffer outIndicesBuffer(&outIndicesBufferBA);
- outIndicesBuffer.open(QIODevice::WriteOnly);
+ QFile outFile(argv[2]);
+ if (!outFile.open(QIODevice::WriteOnly)) {
+ file.close()
+ fprintf("Failed to open output file (%s); see %s -usage", argv[2], argv[0]);
+ return 1;
+ }
+ // Write tldData[] and tldIndices[] in one scan of the (input) file, but
+ // buffer tldData[] so we don'te interleave them in the outFile.
QByteArray outDataBufferBA;
QBuffer outDataBuffer(&outDataBufferBA);
outDataBuffer.open(QIODevice::WriteOnly);
@@ -85,74 +124,65 @@ int main(int argc, char **argv) {
file.readLine();
lineCount++;
}
+ outFile.write("static const quint16 tldCount = ");
+ outFile.write(QByteArray::number(lineCount));
+ outFile.write(";\n");
+
file.reset();
QVector<QString> strings(lineCount);
while (!file.atEnd()) {
- QString s = QString::fromUtf8(file.readLine());
- QString st = s.trimmed();
+ QString st = QString::fromUtf8(file.readLine()).trimmed();
int num = qt_hash(st) % lineCount;
+ QString &entry = strings[num];
+ st = utf8encode(st.toUtf8());
- QString utf8String = utf8encode(st.toUtf8());
-
- // for domain 1.com, we could get something like
- // a.com\01.com, which would be interpreted as octal 01,
- // so we need to separate those strings with quotes
- QRegExp regexpOctalEscape(QLatin1String("^[0-9]"));
- if (!strings.at(num).isEmpty() && st.contains(regexpOctalEscape))
- strings[num].append("\"\"");
+ // For domain 1.com, we could get something like a.com\01.com, which
+ // would be misinterpreted as octal 01, so we need to separate such
+ // strings with quotes:
+ if (!entry.isEmpty() && st.at(0).isDigit())
+ entry.append(quadQuote);
- strings[num].append(utf8String);
- strings[num].append("\\0");
+ entry.append(st);
+ entry.append("\\0");
}
-
- outIndicesBuffer.write("static const quint16 tldCount = ");
- outIndicesBuffer.write(QByteArray::number(lineCount));
- outIndicesBuffer.write(";\n");
- outIndicesBuffer.write("static const quint32 tldIndices[");
-// outIndicesBuffer.write(QByteArray::number(lineCount+1)); // not needed
- outIndicesBuffer.write("] = {\n");
+ outFile.write("static const quint32 tldIndices[] = {\n");
+ outDataBuffer.write("\nstatic const char *tldData[] = {");
int totalUtf8Size = 0;
- int chunkSize = 0;
- int stringUtf8Size = 0;
+ int chunkSize = 0; // strlen of the current chunk (sizeof is bigger by 1)
QStringList chunks;
for (int a = 0; a < lineCount; a++) {
- bool lineIsEmpty = strings.at(a).isEmpty();
- if (!lineIsEmpty) {
- strings[a].prepend("\"");
- strings[a].append("\"");
- }
- int zeroCount = strings.at(a).count(QLatin1String("\\0"));
- int utf8CharsCount = strings.at(a).count(QLatin1String("\\x"));
- int quoteCount = strings.at(a).count('"');
- stringUtf8Size = strings.at(a).count() - (zeroCount + quoteCount + utf8CharsCount * 3);
- chunkSize += stringUtf8Size;
- if (chunkSize > 65535) {
- static int chunkCount = 0;
- qWarning() << "chunk" << ++chunkCount << "has length" << chunkSize - stringUtf8Size;
- outDataBuffer.write(",\n\n");
- chunks.append(QByteArray::number(totalUtf8Size));
- chunkSize = 0;
+ outFile.write(QByteArray::number(totalUtf8Size));
+ outFile.write(",\n");
+ const QString &entry = strings.at(a);
+ if (!entry.isEmpty()) {
+ const int zeroCount = entry.count(QLatin1String("\\0"));
+ const int utf8CharsCount = entry.count(QLatin1String("\\x"));
+ const int quoteCount = entry.count('"');
+ const int stringUtf8Size = entry.count() - (zeroCount + quoteCount + utf8CharsCount * 3);
+ chunkSize += stringUtf8Size;
+ // MSVC 2015 chokes if sizeof(a single string) > 0xffff
+ if (chunkSize >= 0xffff) {
+ static int chunkCount = 0;
+ qWarning() << "chunk" << ++chunkCount << "has length" << chunkSize - stringUtf8Size;
+ outDataBuffer.write(",\n");
+ chunks.append(QString::number(totalUtf8Size));
+ chunkSize = 0;
+ }
+ totalUtf8Size += stringUtf8Size;
+
+ outDataBuffer.write("\n\"");
+ outDataBuffer.write(entry.toUtf8());
+ outDataBuffer.write("\"");
}
- outDataBuffer.write(strings.at(a).toUtf8());
- if (!lineIsEmpty)
- outDataBuffer.write("\n");
- outIndicesBuffer.write(QByteArray::number(totalUtf8Size));
- outIndicesBuffer.write(",\n");
- totalUtf8Size += stringUtf8Size;
}
- chunks.append(QByteArray::number(totalUtf8Size));
- outIndicesBuffer.write(QByteArray::number(totalUtf8Size));
- outIndicesBuffer.write("};\n");
- outIndicesBuffer.close();
- outFile.write(outIndicesBufferBA);
+ chunks.append(QString::number(totalUtf8Size));
+ outFile.write(QByteArray::number(totalUtf8Size));
+ outFile.write("\n};\n");
+ outDataBuffer.write("\n};\n");
outDataBuffer.close();
- outFile.write("\nstatic const char *tldData[");
-// outFile.write(QByteArray::number(charSize)); // not needed
- outFile.write("] = {\n");
outFile.write(outDataBufferBA);
- outFile.write("};\n");
// write chunk information
outFile.write("\nstatic const quint16 tldChunkCount = ");
@@ -161,6 +191,6 @@ int main(int argc, char **argv) {
outFile.write(chunks.join(", ").toLatin1());
outFile.write("};\n");
outFile.close();
- printf("data generated to %s . Now copy the data from this file to src/corelib/io/qurltlds_p.h in your Qt repo\n", argv[2]);
- exit(0);
+ printf("Data generated to %s - now revise qtbase/src/corelib/io/qurltlds_p.h to use this data.\n", argv[2]);
+ return 0;
}
diff --git a/util/lexgen/README b/util/lexgen/README
index 435c7f31ee..005b77b81c 100644
--- a/util/lexgen/README
+++ b/util/lexgen/README
@@ -11,6 +11,5 @@ you want. But I like that it generates code that operates on QChar and friends.
Use at your own risk ;-)
-
--
-Simon Hausmann <simon.hausmann@digia.com>
+Simon Hausmann <simon.hausmann@qt.io>
diff --git a/util/lexgen/css3-simplified.lexgen b/util/lexgen/css3-simplified.lexgen
index 99463d524e..d86a4786be 100644
--- a/util/lexgen/css3-simplified.lexgen
+++ b/util/lexgen/css3-simplified.lexgen
@@ -5,7 +5,7 @@ classname = QCssScanner_Generated
[Code Generator Options]
MapToCode[a-z] = (ch.unicode() >= 'a' && ch.unicode() <= 'z') || (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || ch.unicode() >= 256
TokenPrefix = QCss::
-FileHeader = ../../src/tools/moc/util/licenseheader.txt
+FileHeader = ../../header.LGPL
[Macros]
escape = \\[^\r\n\f0-9a-f]
diff --git a/util/lexgen/generator.cpp b/util/lexgen/generator.cpp
index edd2b603e7..481d586e73 100644
--- a/util/lexgen/generator.cpp
+++ b/util/lexgen/generator.cpp
@@ -29,6 +29,7 @@
#include "generator.h"
#include <QFile>
+#include <QDir>
void Function::printDeclaration(CodeBlock &block, const QString &funcNamePrefix) const
{
@@ -505,14 +506,16 @@ QString Generator::generate()
klass.addMember(Class::PublicMember, lexFunc);
QString header;
- QFile headerFile(headerFileName);
- if (!headerFileName.isEmpty()
- && headerFile.exists()
- && headerFile.open(QIODevice::ReadOnly)) {
- header = QString::fromUtf8(headerFile.readAll());
+ if (!headerFileName.isEmpty()) {
+ QString self(QDir::fromNativeSeparators(QStringLiteral(__FILE__)));
+ int lastSep = self.lastIndexOf(QChar('/'));
+ QDir here(lastSep < 0 ? QStringLiteral(".") : self.left(lastSep));
+ QFile headerFile(QDir::cleanPath(here.filePath(headerFileName)));
+ if (headerFile.exists() && headerFile.open(QIODevice::ReadOnly))
+ header = QString::fromUtf8(headerFile.readAll());
}
- header += QLatin1String("// auto generated. DO NOT EDIT.\n");
+ header += QLatin1String("// auto generated by qtbase/util/lexgen/. DO NOT EDIT.\n");
return header + klass.declaration() + klass.definition();
}
diff --git a/util/lexgen/main.cpp b/util/lexgen/main.cpp
index 22b99b633c..517629f4c1 100644
--- a/util/lexgen/main.cpp
+++ b/util/lexgen/main.cpp
@@ -256,7 +256,7 @@ int main(int argc, char **argv)
}
if (ruleFile.isEmpty()) {
- qWarning("usage: lexgen [-test rulefile");
+ qWarning("usage: lexgen [-debug] [-cache] [-test] rulefile");
qWarning(" ");
qWarning(" the -test option will cause lexgen to interpret standard input");
qWarning(" according to the specified rules and print out pairs of token and");
diff --git a/util/local_database/README b/util/local_database/README
deleted file mode 100644
index 23b6a33ad8..0000000000
--- a/util/local_database/README
+++ /dev/null
@@ -1 +0,0 @@
-local_database is used to generate qlocale data from the Common Locale Data Repository (The database for localized names (like date formats, country names etc)).
diff --git a/util/local_database/enumdata.py b/util/local_database/enumdata.py
deleted file mode 100644
index e24ac02b07..0000000000
--- a/util/local_database/enumdata.py
+++ /dev/null
@@ -1,873 +0,0 @@
-#!/usr/bin/env python
-#############################################################################
-##
-## Copyright (C) 2016 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of the test suite of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:GPL-EXCEPT$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 3 as published by the Free Software
-## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-# Each *_list reflects the current values of its enums in qlocale.h;
-# if new xml language files are available in CLDR, these languages and
-# countries need to be *appended* to this list (for compatibility
-# between versions). Include any spaces present in names (scripts
-# shall squish them out for the enum entries) in *_list, but use the
-# squished forms of names in the *_aliases mappings.
-
-### Qt 6: restore alphabetic order in each list.
-
-language_list = {
- 0 : ["AnyLanguage", " "],
- 1 : ["C", " "],
- 2 : ["Abkhazian", "ab"],
- 3 : ["Oromo", "om"], # macrolanguage
- 4 : ["Afar", "aa"],
- 5 : ["Afrikaans", "af"],
- 6 : ["Albanian", "sq"], # macrolanguage
- 7 : ["Amharic", "am"],
- 8 : ["Arabic", "ar"], # macrolanguage
- 9 : ["Armenian", "hy"],
- 10 : ["Assamese", "as"],
- 11 : ["Aymara", "ay"], # macrolanguage
- 12 : ["Azerbaijani", "az"], # macrolanguage
- 13 : ["Bashkir", "ba"],
- 14 : ["Basque", "eu"],
- 15 : ["Bengali", "bn"],
- 16 : ["Dzongkha", "dz"],
- 17 : ["Bihari", "bh"],
- 18 : ["Bislama", "bi"],
- 19 : ["Breton", "br"],
- 20 : ["Bulgarian", "bg"],
- 21 : ["Burmese", "my"],
- 22 : ["Belarusian", "be"],
- 23 : ["Khmer", "km"],
- 24 : ["Catalan", "ca"],
- 25 : ["Chinese", "zh"], # macrolanguage
- 26 : ["Corsican", "co"],
- 27 : ["Croatian", "hr"],
- 28 : ["Czech", "cs"],
- 29 : ["Danish", "da"],
- 30 : ["Dutch", "nl"],
- 31 : ["English", "en"],
- 32 : ["Esperanto", "eo"],
- 33 : ["Estonian", "et"], # macrolanguage
- 34 : ["Faroese", "fo"],
- 35 : ["Fijian", "fj"],
- 36 : ["Finnish", "fi"],
- 37 : ["French", "fr"],
- 38 : ["Western Frisian", "fy"],
- 39 : ["Gaelic", "gd"],
- 40 : ["Galician", "gl"],
- 41 : ["Georgian", "ka"],
- 42 : ["German", "de"],
- 43 : ["Greek", "el"],
- 44 : ["Greenlandic", "kl"],
- 45 : ["Guarani", "gn"], # macrolanguage
- 46 : ["Gujarati", "gu"],
- 47 : ["Hausa", "ha"],
- 48 : ["Hebrew", "he"],
- 49 : ["Hindi", "hi"],
- 50 : ["Hungarian", "hu"],
- 51 : ["Icelandic", "is"],
- 52 : ["Indonesian", "id"],
- 53 : ["Interlingua", "ia"],
- 54 : ["Interlingue", "ie"],
- 55 : ["Inuktitut", "iu"], # macrolanguage
- 56 : ["Inupiak", "ik"], # macrolanguage
- 57 : ["Irish", "ga"],
- 58 : ["Italian", "it"],
- 59 : ["Japanese", "ja"],
- 60 : ["Javanese", "jv"],
- 61 : ["Kannada", "kn"],
- 62 : ["Kashmiri", "ks"],
- 63 : ["Kazakh", "kk"],
- 64 : ["Kinyarwanda", "rw"],
- 65 : ["Kirghiz", "ky"],
- 66 : ["Korean", "ko"],
- 67 : ["Kurdish", "ku"], # macrolanguage
- 68 : ["Rundi", "rn"],
- 69 : ["Lao", "lo"],
- 70 : ["Latin", "la"],
- 71 : ["Latvian", "lv"], # macrolanguage
- 72 : ["Lingala", "ln"],
- 73 : ["Lithuanian", "lt"],
- 74 : ["Macedonian", "mk"],
- 75 : ["Malagasy", "mg"], # macrolanguage
- 76 : ["Malay", "ms"], # macrolanguage
- 77 : ["Malayalam", "ml"],
- 78 : ["Maltese", "mt"],
- 79 : ["Maori", "mi"],
- 80 : ["Marathi", "mr"],
- 81 : ["Marshallese", "mh"],
- 82 : ["Mongolian", "mn"], # macrolanguage
- 83 : ["Nauru", "na"],
- 84 : ["Nepali", "ne"], # macrolanguage
- 85 : ["Norwegian Bokmal", "nb"],
- 86 : ["Occitan", "oc"],
- 87 : ["Oriya", "or"], # macrolanguage
- 88 : ["Pashto", "ps"], # macrolanguage
- 89 : ["Persian", "fa"], # macrolanguage
- 90 : ["Polish", "pl"],
- 91 : ["Portuguese", "pt"],
- 92 : ["Punjabi", "pa"],
- 93 : ["Quechua", "qu"], # macrolanguage
- 94 : ["Romansh", "rm"],
- 95 : ["Romanian", "ro"],
- 96 : ["Russian", "ru"],
- 97 : ["Samoan", "sm"],
- 98 : ["Sango", "sg"],
- 99 : ["Sanskrit", "sa"],
- 100 : ["Serbian", "sr"],
- 101 : ["Ossetic", "os"],
- 102 : ["Southern Sotho", "st"],
- 103 : ["Tswana", "tn"],
- 104 : ["Shona", "sn"],
- 105 : ["Sindhi", "sd"],
- 106 : ["Sinhala", "si"],
- 107 : ["Swati", "ss"],
- 108 : ["Slovak", "sk"],
- 109 : ["Slovenian", "sl"],
- 110 : ["Somali", "so"],
- 111 : ["Spanish", "es"],
- 112 : ["Sundanese", "su"],
- 113 : ["Swahili", "sw"], # macrolanguage
- 114 : ["Swedish", "sv"],
- 115 : ["Sardinian", "sc"], # macrolanguage
- 116 : ["Tajik", "tg"],
- 117 : ["Tamil", "ta"],
- 118 : ["Tatar", "tt"],
- 119 : ["Telugu", "te"],
- 120 : ["Thai", "th"],
- 121 : ["Tibetan", "bo"],
- 122 : ["Tigrinya", "ti"],
- 123 : ["Tongan", "to"],
- 124 : ["Tsonga", "ts"],
- 125 : ["Turkish", "tr"],
- 126 : ["Turkmen", "tk"],
- 127 : ["Tahitian", "ty"],
- 128 : ["Uighur", "ug"],
- 129 : ["Ukrainian", "uk"],
- 130 : ["Urdu", "ur"],
- 131 : ["Uzbek", "uz"], # macrolanguage
- 132 : ["Vietnamese", "vi"],
- 133 : ["Volapuk", "vo"],
- 134 : ["Welsh", "cy"],
- 135 : ["Wolof", "wo"],
- 136 : ["Xhosa", "xh"],
- 137 : ["Yiddish", "yi"], # macrolanguage
- 138 : ["Yoruba", "yo"],
- 139 : ["Zhuang", "za"], # macrolanguage
- 140 : ["Zulu", "zu"],
- 141 : ["Norwegian Nynorsk", "nn"],
- 142 : ["Bosnian", "bs"],
- 143 : ["Divehi", "dv"],
- 144 : ["Manx", "gv"],
- 145 : ["Cornish", "kw"],
- 146 : ["Akan", "ak"], # macrolanguage
- 147 : ["Konkani", "kok"],
- 148 : ["Ga", "gaa"],
- 149 : ["Igbo", "ig" ],
- 150 : ["Kamba", "kam"],
- 151 : ["Syriac", "syr"],
- 152 : ["Blin", "byn"],
- 153 : ["Geez", "gez"],
- 154 : ["Koro", "kfo"],
- 155 : ["Sidamo", "sid"],
- 156 : ["Atsam", "cch"],
- 157 : ["Tigre", "tig"],
- 158 : ["Jju", "kaj"],
- 159 : ["Friulian", "fur"],
- 160 : ["Venda", "ve" ],
- 161 : ["Ewe", "ee" ],
- 162 : ["Walamo", "wal"],
- 163 : ["Hawaiian", "haw"],
- 164 : ["Tyap", "kcg"],
- 165 : ["Nyanja", "ny" ],
- 166 : ["Filipino", "fil"],
- 167 : ["Swiss German", "gsw"],
- 168 : ["Sichuan Yi", "ii" ],
- 169 : ["Kpelle", "kpe"],
- 170 : ["Low German", "nds"],
- 171 : ["South Ndebele", "nr" ],
- 172 : ["Northern Sotho", "nso"],
- 173 : ["Northern Sami", "se" ],
- 174 : ["Taroko", "trv"],
- 175 : ["Gusii", "guz"],
- 176 : ["Taita", "dav"],
- 177 : ["Fulah", "ff"], # macrolanguage
- 178 : ["Kikuyu", "ki"],
- 179 : ["Samburu", "saq"],
- 180 : ["Sena", "seh"],
- 181 : ["North Ndebele", "nd"],
- 182 : ["Rombo", "rof"],
- 183 : ["Tachelhit", "shi"],
- 184 : ["Kabyle", "kab"],
- 185 : ["Nyankole", "nyn"],
- 186 : ["Bena", "bez"],
- 187 : ["Vunjo", "vun"],
- 188 : ["Bambara", "bm"],
- 189 : ["Embu", "ebu"],
- 190 : ["Cherokee", "chr"],
- 191 : ["Morisyen", "mfe"],
- 192 : ["Makonde", "kde"],
- 193 : ["Langi", "lag"],
- 194 : ["Ganda", "lg"],
- 195 : ["Bemba", "bem"],
- 196 : ["Kabuverdianu", "kea"],
- 197 : ["Meru", "mer"],
- 198 : ["Kalenjin", "kln"],
- 199 : ["Nama", "naq"],
- 200 : ["Machame", "jmc"],
- 201 : ["Colognian", "ksh"],
- 202 : ["Masai", "mas"],
- 203 : ["Soga", "xog"],
- 204 : ["Luyia", "luy"],
- 205 : ["Asu", "asa"],
- 206 : ["Teso", "teo"],
- 207 : ["Saho", "ssy"],
- 208 : ["Koyra Chiini", "khq"],
- 209 : ["Rwa", "rwk"],
- 210 : ["Luo", "luo"],
- 211 : ["Chiga", "cgg"],
- 212 : ["Central Morocco Tamazight", "tzm"],
- 213 : ["Koyraboro Senni", "ses"],
- 214 : ["Shambala", "ksb"],
- 215 : ["Bodo", "brx"],
- 216 : ["Avaric", "av"],
- 217 : ["Chamorro", "ch"],
- 218 : ["Chechen", "ce"],
- 219 : ["Church", "cu"], # macrolanguage
- 220 : ["Chuvash", "cv"],
- 221 : ["Cree", "cr"], # macrolanguage
- 222 : ["Haitian", "ht"],
- 223 : ["Herero", "hz"],
- 224 : ["Hiri Motu", "ho"],
- 225 : ["Kanuri", "kr"], # macrolanguage
- 226 : ["Komi", "kv"], # macrolanguage
- 227 : ["Kongo", "kg"], # macrolanguage
- 228 : ["Kwanyama", "kj"],
- 229 : ["Limburgish", "li"],
- 230 : ["Luba Katanga", "lu"],
- 231 : ["Luxembourgish", "lb"],
- 232 : ["Navaho", "nv"],
- 233 : ["Ndonga", "ng"],
- 234 : ["Ojibwa", "oj"], # macrolanguage
- 235 : ["Pali", "pi"], # macrolanguage
- 236 : ["Walloon", "wa"],
- 237 : ["Aghem", "agq"],
- 238 : ["Basaa", "bas"],
- 239 : ["Zarma", "dje"],
- 240 : ["Duala", "dua"],
- 241 : ["Jola Fonyi", "dyo"],
- 242 : ["Ewondo", "ewo"],
- 243 : ["Bafia", "ksf"],
- 244 : ["Makhuwa Meetto", "mgh"],
- 245 : ["Mundang", "mua"],
- 246 : ["Kwasio", "nmg"],
- 247 : ["Nuer", "nus"],
- 248 : ["Sakha", "sah"],
- 249 : ["Sangu", "sbp"],
- 250 : ["Congo Swahili", "swc"],
- 251 : ["Tasawaq", "twq"],
- 252 : ["Vai", "vai"],
- 253 : ["Walser", "wae"],
- 254 : ["Yangben", "yav"],
- 255 : ["Avestan", "ae"],
- 256 : ["Asturian", "ast"],
- 257 : ["Ngomba", "jgo"],
- 258 : ["Kako", "kkj"],
- 259 : ["Meta", "mgo"],
- 260 : ["Ngiemboon", "nnh"],
- 261 : ["Aragonese", "an"],
- 262 : ["Akkadian", "akk"],
- 263 : ["Ancient Egyptian", "egy"],
- 264 : ["Ancient Greek", "grc"],
- 265 : ["Aramaic", "arc"],
- 266 : ["Balinese", "ban"],
- 267 : ["Bamun", "bax"],
- 268 : ["Batak Toba", "bbc"],
- 269 : ["Buginese", "bug"],
- 270 : ["Buhid", "bku"],
- 271 : ["Carian", "xcr"],
- 272 : ["Chakma", "ccp"],
- 273 : ["Classical Mandaic", "myz"],
- 274 : ["Coptic", "cop"],
- 275 : ["Dogri", "doi"], # macrolanguage
- 276 : ["Eastern Cham", "cjm"],
- 277 : ["Eastern Kayah", "eky"],
- 278 : ["Etruscan", "ett"],
- 279 : ["Gothic", "got"],
- 280 : ["Hanunoo", "hnn"],
- 281 : ["Ingush", "inh"],
- 282 : ["Large Flowery Miao", "hmd"],
- 283 : ["Lepcha", "lep"],
- 284 : ["Limbu", "lif"],
- 285 : ["Lisu", "lis"],
- 286 : ["Lu", "khb"],
- 287 : ["Lycian", "xlc"],
- 288 : ["Lydian", "xld"],
- 289 : ["Mandingo", "man"], # macrolanguage
- 290 : ["Manipuri", "mni"],
- 291 : ["Meroitic", "xmr"],
- 292 : ["Northern Thai", "nod"],
- 293 : ["Old Irish", "sga"],
- 294 : ["Old Norse", "non"],
- 295 : ["Old Persian", "peo"],
- 296 : ["Old Turkish", "otk"],
- 297 : ["Pahlavi", "pal"],
- 298 : ["Parthian", "xpr"],
- 299 : ["Phoenician", "phn"],
- 300 : ["Prakrit Language", "pra"],
- 301 : ["Rejang", "rej"],
- 302 : ["Sabaean", "xsa"],
- 303 : ["Samaritan", "smp"],
- 304 : ["Santali", "sat"],
- 305 : ["Saurashtra", "saz"],
- 306 : ["Sora", "srb"],
- 307 : ["Sylheti", "syl"],
- 308 : ["Tagbanwa", "tbw"],
- 309 : ["Tai Dam", "blt"],
- 310 : ["Tai Nua", "tdd"],
- 311 : ["Ugaritic", "uga"],
- 312 : ["Akoose", "bss"],
- 313 : ["Lakota", "lkt"],
- 314 : ["Standard Moroccan Tamazight", "zgh"],
- 315 : ["Mapuche", "arn"],
- 316 : ["Central Kurdish", "ckb"],
- 317 : ["Lower Sorbian", "dsb"],
- 318 : ["Upper Sorbian", "hsb"],
- 319 : ["Kenyang", "ken"],
- 320 : ["Mohawk", "moh"],
- 321 : ["Nko", "nqo"],
- 322 : ["Prussian", "prg"],
- 323 : ["Kiche", "quc"],
- 324 : ["Southern Sami", "sma"],
- 325 : ["Lule Sami", "smj"],
- 326 : ["Inari Sami", "smn"],
- 327 : ["Skolt Sami", "sms"],
- 328 : ["Warlpiri", "wbp"],
- 329 : ["Manichaean Middle Persian", "xmn"],
- 330 : ["Mende", "men"],
- 331 : ["Ancient North Arabian", "xna"],
- 332 : ["Linear A", "lab"],
- 333 : ["Hmong Njua", "hnj"],
- 334 : ["Ho", "hoc"],
- 335 : ["Lezghian", "lez"],
- 336 : ["Bassa", "bsq"],
- 337 : ["Mono", "mru"],
- 338 : ["Tedim Chin", "ctd"],
- 339 : ["Maithili", "mai"],
- 340 : ["Ahom", "aho"],
- 341 : ["American Sign Language", "ase"],
- 342 : ["Ardhamagadhi Prakrit", "pka"],
- 343 : ["Bhojpuri", "bho"],
- 344 : ["Hieroglyphic Luwian", "hlu"],
- 345 : ["Literary Chinese", "lzh"],
- 346 : ["Mazanderani", "mzn"],
- 347 : ["Mru", "mro"],
- 348 : ["Newari", "new"],
- 349 : ["Northern Luri", "lrc"],
- 350 : ["Palauan", "pau"],
- 351 : ["Papiamento", "pap"],
- 352 : ["Saraiki", "skr"],
- 353 : ["Tokelau", "tkl"],
- 354 : ["Tok Pisin", "tpi"],
- 355 : ["Tuvalu", "tvl"],
- 356 : ["Uncoded Languages", "mis"],
- 357 : ["Cantonese", "yue"],
- 358 : ["Osage", "osa"],
- 359 : ["Tangut", "txg"]
-}
-
-language_aliases = {
- # Legacy - should disappear at some point:
- 'Norwegian': 'NorwegianBokmal',
- 'Moldavian': 'Romanian',
- 'SerboCroatian': 'Serbian',
- 'Tagalog': 'Filipino',
- 'Twi': 'Akan',
- # Renamings:
- 'Afan': 'Oromo',
- 'Byelorussian': 'Belarusian',
- 'Bhutani': 'Dzongkha',
- 'Cambodian': 'Khmer',
- 'Kurundi': 'Rundi',
- 'RhaetoRomance': 'Romansh',
- 'Chewa': 'Nyanja',
- 'Frisian': 'WesternFrisian',
- 'Uigur': 'Uighur',
-}
-
-country_list = {
- 0 : ["AnyCountry", "ZZ"],
- 1 : ["Afghanistan", "AF"],
- 2 : ["Albania", "AL"],
- 3 : ["Algeria", "DZ"],
- 4 : ["American Samoa", "AS"],
- 5 : ["Andorra", "AD"],
- 6 : ["Angola", "AO"],
- 7 : ["Anguilla", "AI"],
- 8 : ["Antarctica", "AQ"],
- 9 : ["Antigua And Barbuda", "AG"],
- 10 : ["Argentina", "AR"],
- 11 : ["Armenia", "AM"],
- 12 : ["Aruba", "AW"],
- 13 : ["Australia", "AU"],
- 14 : ["Austria", "AT"],
- 15 : ["Azerbaijan", "AZ"],
- 16 : ["Bahamas", "BS"],
- 17 : ["Bahrain", "BH"],
- 18 : ["Bangladesh", "BD"],
- 19 : ["Barbados", "BB"],
- 20 : ["Belarus", "BY"],
- 21 : ["Belgium", "BE"],
- 22 : ["Belize", "BZ"],
- 23 : ["Benin", "BJ"],
- 24 : ["Bermuda", "BM"],
- 25 : ["Bhutan", "BT"],
- 26 : ["Bolivia", "BO"],
- 27 : ["Bosnia And Herzegowina", "BA"],
- 28 : ["Botswana", "BW"],
- 29 : ["Bouvet Island", "BV"],
- 30 : ["Brazil", "BR"],
- 31 : ["British Indian Ocean Territory", "IO"],
- 32 : ["Brunei", "BN"],
- 33 : ["Bulgaria", "BG"],
- 34 : ["Burkina Faso", "BF"],
- 35 : ["Burundi", "BI"],
- 36 : ["Cambodia", "KH"],
- 37 : ["Cameroon", "CM"],
- 38 : ["Canada", "CA"],
- 39 : ["Cape Verde", "CV"],
- 40 : ["Cayman Islands", "KY"],
- 41 : ["Central African Republic", "CF"],
- 42 : ["Chad", "TD"],
- 43 : ["Chile", "CL"],
- 44 : ["China", "CN"],
- 45 : ["Christmas Island", "CX"],
- 46 : ["Cocos Islands", "CC"],
- 47 : ["Colombia", "CO"],
- 48 : ["Comoros", "KM"],
- 49 : ["Congo Kinshasa", "CD"],
- 50 : ["Congo Brazzaville", "CG"],
- 51 : ["Cook Islands", "CK"],
- 52 : ["Costa Rica", "CR"],
- 53 : ["Ivory Coast", "CI"],
- 54 : ["Croatia", "HR"],
- 55 : ["Cuba", "CU"],
- 56 : ["Cyprus", "CY"],
- 57 : ["Czech Republic", "CZ"],
- 58 : ["Denmark", "DK"],
- 59 : ["Djibouti", "DJ"],
- 60 : ["Dominica", "DM"],
- 61 : ["Dominican Republic", "DO"],
- 62 : ["East Timor", "TL"],
- 63 : ["Ecuador", "EC"],
- 64 : ["Egypt", "EG"],
- 65 : ["El Salvador", "SV"],
- 66 : ["Equatorial Guinea", "GQ"],
- 67 : ["Eritrea", "ER"],
- 68 : ["Estonia", "EE"],
- 69 : ["Ethiopia", "ET"],
- 70 : ["Falkland Islands", "FK"],
- 71 : ["Faroe Islands", "FO"],
- 72 : ["Fiji", "FJ"],
- 73 : ["Finland", "FI"],
- 74 : ["France", "FR"],
- 75 : ["Guernsey", "GG"],
- 76 : ["French Guiana", "GF"],
- 77 : ["French Polynesia", "PF"],
- 78 : ["French Southern Territories", "TF"],
- 79 : ["Gabon", "GA"],
- 80 : ["Gambia", "GM"],
- 81 : ["Georgia", "GE"],
- 82 : ["Germany", "DE"],
- 83 : ["Ghana", "GH"],
- 84 : ["Gibraltar", "GI"],
- 85 : ["Greece", "GR"],
- 86 : ["Greenland", "GL"],
- 87 : ["Grenada", "GD"],
- 88 : ["Guadeloupe", "GP"],
- 89 : ["Guam", "GU"],
- 90 : ["Guatemala", "GT"],
- 91 : ["Guinea", "GN"],
- 92 : ["Guinea Bissau", "GW"],
- 93 : ["Guyana", "GY"],
- 94 : ["Haiti", "HT"],
- 95 : ["Heard And McDonald Islands", "HM"],
- 96 : ["Honduras", "HN"],
- 97 : ["Hong Kong", "HK"],
- 98 : ["Hungary", "HU"],
- 99 : ["Iceland", "IS"],
- 100 : ["India", "IN"],
- 101 : ["Indonesia", "ID"],
- 102 : ["Iran", "IR"],
- 103 : ["Iraq", "IQ"],
- 104 : ["Ireland", "IE"],
- 105 : ["Israel", "IL"],
- 106 : ["Italy", "IT"],
- 107 : ["Jamaica", "JM"],
- 108 : ["Japan", "JP"],
- 109 : ["Jordan", "JO"],
- 110 : ["Kazakhstan", "KZ"],
- 111 : ["Kenya", "KE"],
- 112 : ["Kiribati", "KI"],
- 113 : ["North Korea", "KP"],
- 114 : ["South Korea", "KR"],
- 115 : ["Kuwait", "KW"],
- 116 : ["Kyrgyzstan", "KG"],
- 117 : ["Laos", "LA"],
- 118 : ["Latvia", "LV"],
- 119 : ["Lebanon", "LB"],
- 120 : ["Lesotho", "LS"],
- 121 : ["Liberia", "LR"],
- 122 : ["Libya", "LY"],
- 123 : ["Liechtenstein", "LI"],
- 124 : ["Lithuania", "LT"],
- 125 : ["Luxembourg", "LU"],
- 126 : ["Macau", "MO"],
- 127 : ["Macedonia", "MK"],
- 128 : ["Madagascar", "MG"],
- 129 : ["Malawi", "MW"],
- 130 : ["Malaysia", "MY"],
- 131 : ["Maldives", "MV"],
- 132 : ["Mali", "ML"],
- 133 : ["Malta", "MT"],
- 134 : ["Marshall Islands", "MH"],
- 135 : ["Martinique", "MQ"],
- 136 : ["Mauritania", "MR"],
- 137 : ["Mauritius", "MU"],
- 138 : ["Mayotte", "YT"],
- 139 : ["Mexico", "MX"],
- 140 : ["Micronesia", "FM"],
- 141 : ["Moldova", "MD"],
- 142 : ["Monaco", "MC"],
- 143 : ["Mongolia", "MN"],
- 144 : ["Montserrat", "MS"],
- 145 : ["Morocco", "MA"],
- 146 : ["Mozambique", "MZ"],
- 147 : ["Myanmar", "MM"],
- 148 : ["Namibia", "NA"],
- 149 : ["Nauru", "NR"],
- 150 : ["Nepal", "NP"],
- 151 : ["Netherlands", "NL"],
- 152 : ["Cura Sao", "CW"],
- 153 : ["New Caledonia", "NC"],
- 154 : ["New Zealand", "NZ"],
- 155 : ["Nicaragua", "NI"],
- 156 : ["Niger", "NE"],
- 157 : ["Nigeria", "NG"],
- 158 : ["Niue", "NU"],
- 159 : ["Norfolk Island", "NF"],
- 160 : ["Northern Mariana Islands", "MP"],
- 161 : ["Norway", "NO"],
- 162 : ["Oman", "OM"],
- 163 : ["Pakistan", "PK"],
- 164 : ["Palau", "PW"],
- 165 : ["Palestinian Territories", "PS"],
- 166 : ["Panama", "PA"],
- 167 : ["Papua New Guinea", "PG"],
- 168 : ["Paraguay", "PY"],
- 169 : ["Peru", "PE"],
- 170 : ["Philippines", "PH"],
- 171 : ["Pitcairn", "PN"],
- 172 : ["Poland", "PL"],
- 173 : ["Portugal", "PT"],
- 174 : ["Puerto Rico", "PR"],
- 175 : ["Qatar", "QA"],
- 176 : ["Reunion", "RE"],
- 177 : ["Romania", "RO"],
- 178 : ["Russia", "RU"],
- 179 : ["Rwanda", "RW"],
- 180 : ["Saint Kitts And Nevis", "KN"],
- 181 : ["Saint Lucia", "LC"],
- 182 : ["Saint Vincent And The Grenadines", "VC"],
- 183 : ["Samoa", "WS"],
- 184 : ["San Marino", "SM"],
- 185 : ["Sao Tome And Principe", "ST"],
- 186 : ["Saudi Arabia", "SA"],
- 187 : ["Senegal", "SN"],
- 188 : ["Seychelles", "SC"],
- 189 : ["Sierra Leone", "SL"],
- 190 : ["Singapore", "SG"],
- 191 : ["Slovakia", "SK"],
- 192 : ["Slovenia", "SI"],
- 193 : ["Solomon Islands", "SB"],
- 194 : ["Somalia", "SO"],
- 195 : ["South Africa", "ZA"],
- 196 : ["South Georgia And The South Sandwich Islands", "GS"],
- 197 : ["Spain", "ES"],
- 198 : ["Sri Lanka", "LK"],
- 199 : ["Saint Helena", "SH"],
- 200 : ["Saint Pierre And Miquelon", "PM"],
- 201 : ["Sudan", "SD"],
- 202 : ["Suriname", "SR"],
- 203 : ["Svalbard And Jan Mayen Islands", "SJ"],
- 204 : ["Swaziland", "SZ"],
- 205 : ["Sweden", "SE"],
- 206 : ["Switzerland", "CH"],
- 207 : ["Syria", "SY"],
- 208 : ["Taiwan", "TW"],
- 209 : ["Tajikistan", "TJ"],
- 210 : ["Tanzania", "TZ"],
- 211 : ["Thailand", "TH"],
- 212 : ["Togo", "TG"],
- 213 : ["Tokelau", "TK"],
- 214 : ["Tonga", "TO"],
- 215 : ["Trinidad And Tobago", "TT"],
- 216 : ["Tunisia", "TN"],
- 217 : ["Turkey", "TR"],
- 218 : ["Turkmenistan", "TM"],
- 219 : ["Turks And Caicos Islands", "TC"],
- 220 : ["Tuvalu", "TV"],
- 221 : ["Uganda", "UG"],
- 222 : ["Ukraine", "UA"],
- 223 : ["United Arab Emirates", "AE"],
- 224 : ["United Kingdom", "GB"],
- 225 : ["United States", "US"],
- 226 : ["United States Minor Outlying Islands", "UM"],
- 227 : ["Uruguay", "UY"],
- 228 : ["Uzbekistan", "UZ"],
- 229 : ["Vanuatu", "VU"],
- 230 : ["Vatican City State", "VA"],
- 231 : ["Venezuela", "VE"],
- 232 : ["Vietnam", "VN"],
- 233 : ["British Virgin Islands", "VG"],
- 234 : ["United States Virgin Islands", "VI"],
- 235 : ["Wallis And Futuna Islands", "WF"],
- 236 : ["Western Sahara", "EH"],
- 237 : ["Yemen", "YE"],
- 238 : ["Canary Islands", "IC"],
- 239 : ["Zambia", "ZM"],
- 240 : ["Zimbabwe", "ZW"],
- 241 : ["Clipperton Island", "CP"],
- 242 : ["Montenegro", "ME"],
- 243 : ["Serbia", "RS"],
- 244 : ["Saint Barthelemy", "BL"],
- 245 : ["Saint Martin", "MF"],
- 246 : ["Latin America", "419"],
- 247 : ["Ascension Island", "AC"],
- 248 : ["Aland Islands", "AX"],
- 249 : ["Diego Garcia", "DG"],
- 250 : ["Ceuta And Melilla", "EA"],
- 251 : ["Isle Of Man", "IM"],
- 252 : ["Jersey", "JE"],
- 253 : ["Tristan Da Cunha", "TA"],
- 254 : ["South Sudan", "SS"],
- 255 : ["Bonaire", "BQ"],
- 256 : ["Sint Maarten", "SX"],
- 257 : ["Kosovo", "XK"],
- 258 : ["European Union", "EU"],
- 259 : ["Outlying Oceania", "QO"],
- 260 : ["World", "001"],
- 261 : ["Europe", "150"]
-}
-
-country_aliases = {
- # Deprecated:
- 'Tokelau': 'TokelauCountry',
- 'Tuvalu': 'TuvaluCountry',
- # Renamings:
- 'DemocraticRepublicOfCongo': 'CongoKinshasa',
- 'PeoplesRepublicOfCongo': 'CongoBrazzaville',
- 'DemocraticRepublicOfKorea': 'NorthKorea',
- 'RepublicOfKorea': 'SouthKorea',
- 'RussianFederation': 'Russia',
- 'SyrianArabRepublic': 'Syria',
- 'LatinAmericaAndTheCaribbean': 'LatinAmerica',
-}
-
-script_list = {
- 0 : ["AnyScript", "Zzzz"],
- 1 : ["Arabic", "Arab"],
- 2 : ["Cyrillic", "Cyrl"],
- 3 : ["Deseret", "Dsrt"],
- 4 : ["Gurmukhi", "Guru"],
- 5 : ["Simplified Han", "Hans"],
- 6 : ["Traditional Han", "Hant"],
- 7 : ["Latin", "Latn"],
- 8 : ["Mongolian", "Mong"],
- 9 : ["Tifinagh", "Tfng"],
- 10 : ["Armenian", "Armn"],
- 11 : ["Bengali", "Beng"],
- 12 : ["Cherokee", "Cher"],
- 13 : ["Devanagari", "Deva"],
- 14 : ["Ethiopic", "Ethi"],
- 15 : ["Georgian", "Geor"],
- 16 : ["Greek", "Grek"],
- 17 : ["Gujarati", "Gujr"],
- 18 : ["Hebrew", "Hebr"],
- 19 : ["Japanese", "Jpan"],
- 20 : ["Khmer", "Khmr"],
- 21 : ["Kannada", "Knda"],
- 22 : ["Korean", "Kore"],
- 23 : ["Lao", "Laoo"],
- 24 : ["Malayalam", "Mlym"],
- 25 : ["Myanmar", "Mymr"],
- 26 : ["Oriya", "Orya"],
- 27 : ["Tamil", "Taml"],
- 28 : ["Telugu", "Telu"],
- 29 : ["Thaana", "Thaa"],
- 30 : ["Thai", "Thai"],
- 31 : ["Tibetan", "Tibt"],
- 32 : ["Sinhala", "Sinh"],
- 33 : ["Syriac", "Syrc"],
- 34 : ["Yi", "Yiii"],
- 35 : ["Vai", "Vaii"],
- 36 : ["Avestan", "Avst"],
- 37 : ["Balinese", "Bali"],
- 38 : ["Bamum", "Bamu"],
- 39 : ["Batak", "Batk"],
- 40 : ["Bopomofo", "Bopo"],
- 41 : ["Brahmi", "Brah"],
- 42 : ["Buginese", "Bugi"],
- 43 : ["Buhid", "Buhd"],
- 44 : ["Canadian Aboriginal", "Cans"],
- 45 : ["Carian", "Cari"],
- 46 : ["Chakma", "Cakm"],
- 47 : ["Cham", "Cham"],
- 48 : ["Coptic", "Copt"],
- 49 : ["Cypriot", "Cprt"],
- 50 : ["Egyptian Hieroglyphs", "Egyp"],
- 51 : ["Fraser", "Lisu"],
- 52 : ["Glagolitic", "Glag"],
- 53 : ["Gothic", "Goth"],
- 54 : ["Han", "Hani"],
- 55 : ["Hangul", "Hang"],
- 56 : ["Hanunoo", "Hano"],
- 57 : ["Imperial Aramaic", "Armi"],
- 58 : ["Inscriptional Pahlavi", "Phli"],
- 59 : ["Inscriptional Parthian", "Prti"],
- 60 : ["Javanese", "Java"],
- 61 : ["Kaithi", "Kthi"],
- 62 : ["Katakana", "Kana"],
- 63 : ["Kayah Li", "Kali"],
- 64 : ["Kharoshthi", "Khar"],
- 65 : ["Lanna", "Lana"],
- 66 : ["Lepcha", "Lepc"],
- 67 : ["Limbu", "Limb"],
- 68 : ["Linear B", "Linb"],
- 69 : ["Lycian", "Lyci"],
- 70 : ["Lydian", "Lydi"],
- 71 : ["Mandaean", "Mand"],
- 72 : ["Meitei Mayek", "Mtei"],
- 73 : ["Meroitic", "Mero"],
- 74 : ["Meroitic Cursive", "Merc"],
- 75 : ["Nko", "Nkoo"],
- 76 : ["New Tai Lue", "Talu"],
- 77 : ["Ogham", "Ogam"],
- 78 : ["Ol Chiki", "Olck"],
- 79 : ["Old Italic", "Ital"],
- 80 : ["Old Persian", "Xpeo"],
- 81 : ["Old South Arabian", "Sarb"],
- 82 : ["Orkhon", "Orkh"],
- 83 : ["Osmanya", "Osma"],
- 84 : ["Phags Pa", "Phag"],
- 85 : ["Phoenician", "Phnx"],
- 86 : ["Pollard Phonetic", "Plrd"],
- 87 : ["Rejang", "Rjng"],
- 88 : ["Runic", "Runr"],
- 89 : ["Samaritan", "Samr"],
- 90 : ["Saurashtra", "Saur"],
- 91 : ["Sharada", "Shrd"],
- 92 : ["Shavian", "Shaw"],
- 93 : ["Sora Sompeng", "Sora"],
- 94 : ["Cuneiform", "Xsux"],
- 95 : ["Sundanese", "Sund"],
- 96 : ["Syloti Nagri", "Sylo"],
- 97 : ["Tagalog", "Tglg"],
- 98 : ["Tagbanwa", "Tagb"],
- 99 : ["Tai Le", "Tale"],
- 100 : ["Tai Viet", "Tavt"],
- 101 : ["Takri", "Takr"],
- 102 : ["Ugaritic", "Ugar"],
- 103 : ["Braille", "Brai"],
- 104 : ["Hiragana", "Hira"],
- 105 : ["Caucasian Albanian", "Aghb"],
- 106 : ["Bassa Vah", "Bass"],
- 107 : ["Duployan", "Dupl"],
- 108 : ["Elbasan", "Elba"],
- 109 : ["Grantha", "Gran"],
- 110 : ["Pahawh Hmong", "Hmng"],
- 111 : ["Khojki", "Khoj"],
- 112 : ["Linear A", "Lina"],
- 113 : ["Mahajani", "Mahj"],
- 114 : ["Manichaean", "Mani"],
- 115 : ["Mende Kikakui", "Mend"],
- 116 : ["Modi", "Modi"],
- 117 : ["Mro", "Mroo"],
- 118 : ["Old North Arabian", "Narb"],
- 119 : ["Nabataean", "Nbat"],
- 120 : ["Palmyrene", "Palm"],
- 121 : ["Pau Cin Hau", "Pauc"],
- 122 : ["Old Permic", "Perm"],
- 123 : ["Psalter Pahlavi", "Phlp"],
- 124 : ["Siddham", "Sidd"],
- 125 : ["Khudawadi", "Sind"],
- 126 : ["Tirhuta", "Tirh"],
- 127 : ["Varang Kshiti", "Wara"],
- 128 : ["Ahom", "Ahom"],
- 129 : ["Anatolian Hieroglyphs", "Hluw"],
- 130 : ["Hatran", "Hatr"],
- 131 : ["Multani", "Mult"],
- 132 : ["Old Hungarian", "Hung"],
- 133 : ["Sign Writing", "Sgnw"],
- 134 : ["Adlam", "Adlm"],
- 135 : ["Bhaiksuki", "Bhks"],
- 136 : ["Marchen", "Marc"],
- 137 : ["Newa", "Newa"],
- 138 : ["Osage", "Osge"],
- 139 : ["Tangut", "Tang"],
- 140 : ["Han with Bopomofo", "Hanb"],
- 141 : ["Jamo", "Jamo"]
-}
-
-script_aliases = {
- # Renamings:
- 'SimplifiedChineseScript': 'SimplifiedHanScript',
- 'TraditionalChineseScript': 'TraditionalHanScript',
-}
-
-def countryCodeToId(code):
- if not code:
- return 0
- for country_id in country_list:
- if country_list[country_id][1] == code:
- return country_id
- return -1
-
-def languageCodeToId(code):
- if not code:
- return 0
- for language_id in language_list:
- if language_list[language_id][1] == code:
- return language_id
- return -1
-
-def scriptCodeToId(code):
- if not code:
- return 0
- for script_id in script_list:
- if script_list[script_id][1] == code:
- return script_id
- return -1
diff --git a/util/locale_database/README b/util/locale_database/README
new file mode 100644
index 0000000000..8654968d66
--- /dev/null
+++ b/util/locale_database/README
@@ -0,0 +1,5 @@
+locale_database is used to generate qlocale data from CLDR.
+
+CLDR is the Common Locale Data Repository, a database for localized
+data (like date formats, country names etc). It is provided by the
+Unicode consortium.
diff --git a/util/local_database/cldr2qlocalexml.py b/util/locale_database/cldr2qlocalexml.py
index 7fba41e2c4..d75ef282f9 100755
--- a/util/local_database/cldr2qlocalexml.py
+++ b/util/locale_database/cldr2qlocalexml.py
@@ -51,6 +51,7 @@ order.
import os
import sys
import re
+import textwrap
import enumdata
import xpathlite
@@ -59,6 +60,10 @@ from dateconverter import convert_date
from localexml import Locale
findEntryInFile = xpathlite._findEntryInFile
+def wrappedwarn(prefix, tokens):
+ return sys.stderr.write(
+ '\n'.join(textwrap.wrap(prefix + ', '.join(tokens),
+ subsequent_indent=' ', width=80)) + '\n')
def parse_number_format(patterns, data):
# this is a very limited parsing of the number format for currency only.
@@ -90,6 +95,34 @@ def parse_number_format(patterns, data):
result.append(pattern)
return result
+def raiseUnknownCode(code, form, cache={}):
+ """Check whether an unknown code could be supported.
+
+ We declare a language, script or country code unknown if it's not
+ known to enumdata.py; however, if it's present in main/en.xml's
+ mapping of codes to names, we have the option of adding support.
+ This caches the necessary look-up (so we only read main/en.xml
+ once) and returns the name we should use if we do add support.
+
+ First parameter, code, is the unknown code. Second parameter,
+ form, is one of 'language', 'script' or 'country' to select the
+ type of code to look up. Do not pass further parameters (the next
+ will deprive you of the cache).
+
+ Raises xpathlite.Error with a suitable message, that includes the
+ unknown code's full name if found.
+
+ Relies on global cldr_dir being set before it's called; see tail
+ of this file.
+ """
+ if not cache:
+ cache.update(xpathlite.codeMapsFromFile(os.path.join(cldr_dir, 'en.xml')))
+ name = cache[form].get(code)
+ msg = 'unknown %s code "%s"' % (form, code)
+ if name:
+ msg += ' - could use "%s"' % name
+ raise xpathlite.Error(msg)
+
def parse_list_pattern_part_format(pattern):
# This is a very limited parsing of the format for list pattern part only.
return pattern.replace("{0}", "%1").replace("{1}", "%2").replace("{2}", "%3")
@@ -164,9 +197,9 @@ def getNumberSystems(cache={}):
entry = dict(ns[1])
name = entry[u'id']
if u'digits' in entry and ord(entry[u'digits'][0]) > 0xffff:
- # FIXME: make this redundant:
+ # FIXME, QTBUG-69324: make this redundant:
# omit number system if zero doesn't fit in single-char16 UTF-16 :-(
- sys.stderr.write('skipping number system "%s" [can\'t represent its zero, U+%X, QTBUG-69324]\n'
+ sys.stderr.write('skipping number system "%s" [can\'t represent its zero, U+%X]\n'
% (name, ord(entry[u'digits'][0])))
else:
cache[name] = entry
@@ -188,18 +221,18 @@ def _generateLocaleInfo(path, language_code, script_code, country_code, variant_
language_id = enumdata.languageCodeToId(language_code)
if language_id <= 0:
- raise xpathlite.Error('unknown language code "%s"' % language_code)
+ raiseUnknownCode(language_code, 'language')
script_id = enumdata.scriptCodeToId(script_code)
if script_id == -1:
- raise xpathlite.Error('unknown script code "%s"' % script_code)
+ raiseUnknownCode(script_code, 'script')
# we should handle fully qualified names with the territory
if not country_code:
return {}
country_id = enumdata.countryCodeToId(country_code)
if country_id <= 0:
- raise xpathlite.Error('unknown country code "%s"' % country_code)
+ raiseUnknownCode(country_code, 'country')
# So we say we accept only those values that have "contributed" or
# "approved" resolution. see http://www.unicode.org/cldr/process.html
@@ -243,7 +276,7 @@ def _generateLocaleInfo(path, language_code, script_code, country_code, variant_
numbering_system = None
try:
numbering_system = findEntry(path, "numbers/defaultNumberingSystem")
- except:
+ except xpathlite.Error:
pass
def findEntryDef(path, xpath, value=''):
try:
@@ -438,6 +471,38 @@ def integrateWeekData(filePath):
else:
locale.weekendEnd = weekendEndByCountryCode["001"]
+def splitLocale(name):
+ """Split name into (language, script, territory) triple as generator.
+
+ Ignores any trailing fields (with a warning), leaves script (a capitalised
+ four-letter token) or territory (either a number or an all-uppercase token)
+ empty if unspecified, returns a single-entry generator if name is a single
+ tag (i.e. contains no underscores). Always yields 1 or 3 values, never 2."""
+ tags = iter(name.split('_'))
+ yield tags.next() # Language
+ tag = tags.next()
+
+ # Script is always four letters, always capitalised:
+ if len(tag) == 4 and tag[0].isupper() and tag[1:].islower():
+ yield tag
+ try:
+ tag = tags.next()
+ except StopIteration:
+ tag = ''
+ else:
+ yield ''
+
+ # Territory is upper-case or numeric:
+ if tag and tag.isupper() or tag.isdigit():
+ yield tag
+ tag = ''
+ else:
+ yield ''
+
+ # If nothing is left, StopIteration will avoid the warning:
+ tag = (tag if tag else tags.next(),)
+ sys.stderr.write('Ignoring unparsed cruft %s in %s\n' % ('_'.join(tag + tuple(tags)), name))
+
if len(sys.argv) != 2:
usage()
@@ -451,34 +516,30 @@ cldr_files = os.listdir(cldr_dir)
locale_database = {}
# see http://www.unicode.org/reports/tr35/tr35-info.html#Default_Content
-defaultContent_locales = {}
+defaultContent_locales = []
for ns in findTagsInFile(os.path.join(cldr_dir, '..', 'supplemental',
'supplementalMetadata.xml'),
'metadata/defaultContent'):
for data in ns[1:][0]:
if data[0] == u"locales":
- defaultContent_locales = data[1].split()
+ defaultContent_locales += data[1].split()
+skips = []
for file in defaultContent_locales:
- items = file.split("_")
- if len(items) == 3:
- language_code = items[0]
- script_code = items[1]
- country_code = items[2]
- else:
- if len(items) != 2:
- sys.stderr.write('skipping defaultContent locale "' + file + '" [neither lang_script_country nor lang_country]\n')
- continue
- language_code = items[0]
- script_code = ""
- country_code = items[1]
- if len(country_code) == 4:
- sys.stderr.write('skipping defaultContent locale "' + file + '" [long country code]\n')
- continue
+ try:
+ language_code, script_code, country_code = splitLocale(file)
+ except ValueError:
+ sys.stderr.write('skipping defaultContent locale "' + file + '" [neither two nor three tags]\n')
+ continue
+
+ if not (script_code or country_code):
+ sys.stderr.write('skipping defaultContent locale "' + file + '" [second tag is neither script nor territory]\n')
+ continue
+
try:
l = _generateLocaleInfo(cldr_dir + "/" + file + ".xml", language_code, script_code, country_code)
if not l:
- sys.stderr.write('skipping defaultContent locale "' + file + '" [no locale info generated]\n')
+ skips.append(file)
continue
except xpathlite.Error as e:
sys.stderr.write('skipping defaultContent locale "%s" (%s)\n' % (file, str(e)))
@@ -486,11 +547,15 @@ for file in defaultContent_locales:
locale_database[(l.language_id, l.script_id, l.country_id, l.variant_code)] = l
+if skips:
+ wrappedwarn('skipping defaultContent locales [no locale info generated]: ', skips)
+ skips = []
+
for file in cldr_files:
try:
l = generateLocaleInfo(cldr_dir + "/" + file)
if not l:
- sys.stderr.write('skipping file "' + file + '" [no locale info generated]\n')
+ skips.append(file)
continue
except xpathlite.Error as e:
sys.stderr.write('skipping file "%s" (%s)\n' % (file, str(e)))
@@ -498,6 +563,9 @@ for file in cldr_files:
locale_database[(l.language_id, l.script_id, l.country_id, l.variant_code)] = l
+if skips:
+ wrappedwarn('skipping files [no locale info generated]: ', skips)
+
integrateWeekData(cldr_dir+"/../supplemental/supplementalData.xml")
locale_keys = locale_database.keys()
locale_keys.sort()
@@ -548,34 +616,35 @@ def _parseLocale(l):
if l == "und":
raise xpathlite.Error("we are treating unknown locale like C")
- items = l.split("_")
- language_code = items[0]
+ parsed = splitLocale(l)
+ language_code = parsed.next()
+ script_code = country_code = ''
+ try:
+ script_code, country_code = parsed
+ except ValueError:
+ pass
+
if language_code != "und":
language_id = enumdata.languageCodeToId(language_code)
if language_id == -1:
raise xpathlite.Error('unknown language code "%s"' % language_code)
language = enumdata.language_list[language_id][0]
- if len(items) > 1:
- script_code = items[1]
- country_code = ""
- if len(items) > 2:
- country_code = items[2]
- if len(script_code) == 4:
- script_id = enumdata.scriptCodeToId(script_code)
- if script_id == -1:
- raise xpathlite.Error('unknown script code "%s"' % script_code)
- script = enumdata.script_list[script_id][0]
- else:
- country_code = script_code
- if country_code:
- country_id = enumdata.countryCodeToId(country_code)
- if country_id == -1:
- raise xpathlite.Error('unknown country code "%s"' % country_code)
- country = enumdata.country_list[country_id][0]
+ if script_code:
+ script_id = enumdata.scriptCodeToId(script_code)
+ if script_id == -1:
+ raise xpathlite.Error('unknown script code "%s"' % script_code)
+ script = enumdata.script_list[script_id][0]
+
+ if country_code:
+ country_id = enumdata.countryCodeToId(country_code)
+ if country_id == -1:
+ raise xpathlite.Error('unknown country code "%s"' % country_code)
+ country = enumdata.country_list[country_id][0]
return (language, script, country)
+skips = []
print " <likelySubtags>"
for ns in findTagsInFile(cldr_dir + "/../supplemental/likelySubtags.xml", "likelySubtags"):
tmp = {}
@@ -583,14 +652,13 @@ for ns in findTagsInFile(cldr_dir + "/../supplemental/likelySubtags.xml", "likel
tmp[data[0]] = data[1]
try:
- (from_language, from_script, from_country) = _parseLocale(tmp[u"from"])
- except xpathlite.Error as e:
- sys.stderr.write('skipping likelySubtag "%s" -> "%s" (%s)\n' % (tmp[u"from"], tmp[u"to"], str(e)))
- continue
- try:
- (to_language, to_script, to_country) = _parseLocale(tmp[u"to"])
+ from_language, from_script, from_country = _parseLocale(tmp[u"from"])
+ to_language, to_script, to_country = _parseLocale(tmp[u"to"])
except xpathlite.Error as e:
- sys.stderr.write('skipping likelySubtag "%s" -> "%s" (%s)\n' % (tmp[u"from"], tmp[u"to"], str(e)))
+ if tmp[u'to'].startswith(tmp[u'from']) and str(e) == 'unknown language code "%s"' % tmp[u'from']:
+ skips.append(tmp[u'to'])
+ else:
+ sys.stderr.write('skipping likelySubtag "%s" -> "%s" (%s)\n' % (tmp[u"from"], tmp[u"to"], str(e)))
continue
# substitute according to http://www.unicode.org/reports/tr35/#Likely_Subtags
if to_country == "AnyCountry" and from_country != to_country:
@@ -611,7 +679,8 @@ for ns in findTagsInFile(cldr_dir + "/../supplemental/likelySubtags.xml", "likel
print " </to>"
print " </likelySubtag>"
print " </likelySubtags>"
-
+if skips:
+ wrappedwarn('skipping likelySubtags (for unknown language codes): ', skips)
print " <localeList>"
Locale.C().toXml()
diff --git a/util/local_database/cldr2qtimezone.py b/util/locale_database/cldr2qtimezone.py
index 7c10b1dfd2..0817435d40 100755
--- a/util/local_database/cldr2qtimezone.py
+++ b/util/locale_database/cldr2qtimezone.py
@@ -32,7 +32,7 @@ Script to parse the CLDR supplemental/windowsZones.xml file and encode
for use in QTimeZone. See ``./cldr2qlocalexml.py`` for where to get
the CLDR data. Pass its common/ directory as first parameter to this
script and the qtbase root directory as second parameter. It shall
-update qtbase's src/corelib/tools/qtimezoneprivate_data_p.h ready for
+update qtbase's src/corelib/time/qtimezoneprivate_data_p.h ready for
use.
The XML structure is as follows:
@@ -268,7 +268,7 @@ if not os.path.isdir(cldrPath) or not os.path.isdir(qtPath):
windowsZonesPath = cldrPath + "/supplemental/windowsZones.xml"
tempFileDir = qtPath
-dataFilePath = qtPath + "/src/corelib/tools/qtimezoneprivate_data_p.h"
+dataFilePath = qtPath + "/src/corelib/time/qtimezoneprivate_data_p.h"
if not os.path.isfile(windowsZonesPath):
usage()
@@ -343,7 +343,7 @@ newTempFile.write("""
http://www.unicode.org/cldr/
Do not edit this code: run cldr2qtimezone.py on updated (or
- edited) CLDR data; see qtbase/util/local_database/.
+ edited) CLDR data; see qtbase/util/locale_database/.
*/
""" % (str(datetime.date.today()), cldr_version, versionNumber) )
diff --git a/util/local_database/dateconverter.py b/util/locale_database/dateconverter.py
index 1990fe0c61..1990fe0c61 100755
--- a/util/local_database/dateconverter.py
+++ b/util/locale_database/dateconverter.py
diff --git a/util/locale_database/enumdata.py b/util/locale_database/enumdata.py
new file mode 100644
index 0000000000..0e40d8a9ee
--- /dev/null
+++ b/util/locale_database/enumdata.py
@@ -0,0 +1,880 @@
+#!/usr/bin/env python
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+# Each *_list reflects the current values of its enums in qlocale.h;
+# if new xml language files are available in CLDR, these languages and
+# countries need to be *appended* to this list (for compatibility
+# between versions). Include any spaces present in names (scripts
+# shall squish them out for the enum entries) in *_list, but use the
+# squished forms of names in the *_aliases mappings.
+
+### Qt 6: restore alphabetic order in each list.
+
+language_list = {
+ 0: ["AnyLanguage", " "],
+ 1: ["C", " "],
+ 2: ["Abkhazian", "ab"],
+ 3: ["Oromo", "om"], # macrolanguage
+ 4: ["Afar", "aa"],
+ 5: ["Afrikaans", "af"],
+ 6: ["Albanian", "sq"], # macrolanguage
+ 7: ["Amharic", "am"],
+ 8: ["Arabic", "ar"], # macrolanguage
+ 9: ["Armenian", "hy"],
+ 10: ["Assamese", "as"],
+ 11: ["Aymara", "ay"], # macrolanguage
+ 12: ["Azerbaijani", "az"], # macrolanguage
+ 13: ["Bashkir", "ba"],
+ 14: ["Basque", "eu"],
+ 15: ["Bengali", "bn"],
+ 16: ["Dzongkha", "dz"],
+ 17: ["Bihari", "bh"],
+ 18: ["Bislama", "bi"],
+ 19: ["Breton", "br"],
+ 20: ["Bulgarian", "bg"],
+ 21: ["Burmese", "my"],
+ 22: ["Belarusian", "be"],
+ 23: ["Khmer", "km"],
+ 24: ["Catalan", "ca"],
+ 25: ["Chinese", "zh"], # macrolanguage
+ 26: ["Corsican", "co"],
+ 27: ["Croatian", "hr"],
+ 28: ["Czech", "cs"],
+ 29: ["Danish", "da"],
+ 30: ["Dutch", "nl"],
+ 31: ["English", "en"],
+ 32: ["Esperanto", "eo"],
+ 33: ["Estonian", "et"], # macrolanguage
+ 34: ["Faroese", "fo"],
+ 35: ["Fijian", "fj"],
+ 36: ["Finnish", "fi"],
+ 37: ["French", "fr"],
+ 38: ["Western Frisian", "fy"],
+ 39: ["Gaelic", "gd"],
+ 40: ["Galician", "gl"],
+ 41: ["Georgian", "ka"],
+ 42: ["German", "de"],
+ 43: ["Greek", "el"],
+ 44: ["Greenlandic", "kl"],
+ 45: ["Guarani", "gn"], # macrolanguage
+ 46: ["Gujarati", "gu"],
+ 47: ["Hausa", "ha"],
+ 48: ["Hebrew", "he"],
+ 49: ["Hindi", "hi"],
+ 50: ["Hungarian", "hu"],
+ 51: ["Icelandic", "is"],
+ 52: ["Indonesian", "id"],
+ 53: ["Interlingua", "ia"],
+ 54: ["Interlingue", "ie"],
+ 55: ["Inuktitut", "iu"], # macrolanguage
+ 56: ["Inupiak", "ik"], # macrolanguage
+ 57: ["Irish", "ga"],
+ 58: ["Italian", "it"],
+ 59: ["Japanese", "ja"],
+ 60: ["Javanese", "jv"],
+ 61: ["Kannada", "kn"],
+ 62: ["Kashmiri", "ks"],
+ 63: ["Kazakh", "kk"],
+ 64: ["Kinyarwanda", "rw"],
+ 65: ["Kirghiz", "ky"],
+ 66: ["Korean", "ko"],
+ 67: ["Kurdish", "ku"], # macrolanguage
+ 68: ["Rundi", "rn"],
+ 69: ["Lao", "lo"],
+ 70: ["Latin", "la"],
+ 71: ["Latvian", "lv"], # macrolanguage
+ 72: ["Lingala", "ln"],
+ 73: ["Lithuanian", "lt"],
+ 74: ["Macedonian", "mk"],
+ 75: ["Malagasy", "mg"], # macrolanguage
+ 76: ["Malay", "ms"], # macrolanguage
+ 77: ["Malayalam", "ml"],
+ 78: ["Maltese", "mt"],
+ 79: ["Maori", "mi"],
+ 80: ["Marathi", "mr"],
+ 81: ["Marshallese", "mh"],
+ 82: ["Mongolian", "mn"], # macrolanguage
+ 83: ["Nauru", "na"],
+ 84: ["Nepali", "ne"], # macrolanguage
+ 85: ["Norwegian Bokmal", "nb"],
+ 86: ["Occitan", "oc"],
+ 87: ["Oriya", "or"], # macrolanguage
+ 88: ["Pashto", "ps"], # macrolanguage
+ 89: ["Persian", "fa"], # macrolanguage
+ 90: ["Polish", "pl"],
+ 91: ["Portuguese", "pt"],
+ 92: ["Punjabi", "pa"],
+ 93: ["Quechua", "qu"], # macrolanguage
+ 94: ["Romansh", "rm"],
+ 95: ["Romanian", "ro"],
+ 96: ["Russian", "ru"],
+ 97: ["Samoan", "sm"],
+ 98: ["Sango", "sg"],
+ 99: ["Sanskrit", "sa"],
+ 100: ["Serbian", "sr"],
+ 101: ["Ossetic", "os"],
+ 102: ["Southern Sotho", "st"],
+ 103: ["Tswana", "tn"],
+ 104: ["Shona", "sn"],
+ 105: ["Sindhi", "sd"],
+ 106: ["Sinhala", "si"],
+ 107: ["Swati", "ss"],
+ 108: ["Slovak", "sk"],
+ 109: ["Slovenian", "sl"],
+ 110: ["Somali", "so"],
+ 111: ["Spanish", "es"],
+ 112: ["Sundanese", "su"],
+ 113: ["Swahili", "sw"], # macrolanguage
+ 114: ["Swedish", "sv"],
+ 115: ["Sardinian", "sc"], # macrolanguage
+ 116: ["Tajik", "tg"],
+ 117: ["Tamil", "ta"],
+ 118: ["Tatar", "tt"],
+ 119: ["Telugu", "te"],
+ 120: ["Thai", "th"],
+ 121: ["Tibetan", "bo"],
+ 122: ["Tigrinya", "ti"],
+ 123: ["Tongan", "to"],
+ 124: ["Tsonga", "ts"],
+ 125: ["Turkish", "tr"],
+ 126: ["Turkmen", "tk"],
+ 127: ["Tahitian", "ty"],
+ 128: ["Uighur", "ug"],
+ 129: ["Ukrainian", "uk"],
+ 130: ["Urdu", "ur"],
+ 131: ["Uzbek", "uz"], # macrolanguage
+ 132: ["Vietnamese", "vi"],
+ 133: ["Volapuk", "vo"],
+ 134: ["Welsh", "cy"],
+ 135: ["Wolof", "wo"],
+ 136: ["Xhosa", "xh"],
+ 137: ["Yiddish", "yi"], # macrolanguage
+ 138: ["Yoruba", "yo"],
+ 139: ["Zhuang", "za"], # macrolanguage
+ 140: ["Zulu", "zu"],
+ 141: ["Norwegian Nynorsk", "nn"],
+ 142: ["Bosnian", "bs"],
+ 143: ["Divehi", "dv"],
+ 144: ["Manx", "gv"],
+ 145: ["Cornish", "kw"],
+ 146: ["Akan", "ak"], # macrolanguage
+ 147: ["Konkani", "kok"],
+ 148: ["Ga", "gaa"],
+ 149: ["Igbo", "ig" ],
+ 150: ["Kamba", "kam"],
+ 151: ["Syriac", "syr"],
+ 152: ["Blin", "byn"],
+ 153: ["Geez", "gez"],
+ 154: ["Koro", "kfo"],
+ 155: ["Sidamo", "sid"],
+ 156: ["Atsam", "cch"],
+ 157: ["Tigre", "tig"],
+ 158: ["Jju", "kaj"],
+ 159: ["Friulian", "fur"],
+ 160: ["Venda", "ve" ],
+ 161: ["Ewe", "ee" ],
+ 162: ["Walamo", "wal"],
+ 163: ["Hawaiian", "haw"],
+ 164: ["Tyap", "kcg"],
+ 165: ["Nyanja", "ny" ],
+ 166: ["Filipino", "fil"],
+ 167: ["Swiss German", "gsw"],
+ 168: ["Sichuan Yi", "ii" ],
+ 169: ["Kpelle", "kpe"],
+ 170: ["Low German", "nds"],
+ 171: ["South Ndebele", "nr" ],
+ 172: ["Northern Sotho", "nso"],
+ 173: ["Northern Sami", "se" ],
+ 174: ["Taroko", "trv"],
+ 175: ["Gusii", "guz"],
+ 176: ["Taita", "dav"],
+ 177: ["Fulah", "ff"], # macrolanguage
+ 178: ["Kikuyu", "ki"],
+ 179: ["Samburu", "saq"],
+ 180: ["Sena", "seh"],
+ 181: ["North Ndebele", "nd"],
+ 182: ["Rombo", "rof"],
+ 183: ["Tachelhit", "shi"],
+ 184: ["Kabyle", "kab"],
+ 185: ["Nyankole", "nyn"],
+ 186: ["Bena", "bez"],
+ 187: ["Vunjo", "vun"],
+ 188: ["Bambara", "bm"],
+ 189: ["Embu", "ebu"],
+ 190: ["Cherokee", "chr"],
+ 191: ["Morisyen", "mfe"],
+ 192: ["Makonde", "kde"],
+ 193: ["Langi", "lag"],
+ 194: ["Ganda", "lg"],
+ 195: ["Bemba", "bem"],
+ 196: ["Kabuverdianu", "kea"],
+ 197: ["Meru", "mer"],
+ 198: ["Kalenjin", "kln"],
+ 199: ["Nama", "naq"],
+ 200: ["Machame", "jmc"],
+ 201: ["Colognian", "ksh"],
+ 202: ["Masai", "mas"],
+ 203: ["Soga", "xog"],
+ 204: ["Luyia", "luy"],
+ 205: ["Asu", "asa"],
+ 206: ["Teso", "teo"],
+ 207: ["Saho", "ssy"],
+ 208: ["Koyra Chiini", "khq"],
+ 209: ["Rwa", "rwk"],
+ 210: ["Luo", "luo"],
+ 211: ["Chiga", "cgg"],
+ 212: ["Central Morocco Tamazight", "tzm"],
+ 213: ["Koyraboro Senni", "ses"],
+ 214: ["Shambala", "ksb"],
+ 215: ["Bodo", "brx"],
+ 216: ["Avaric", "av"],
+ 217: ["Chamorro", "ch"],
+ 218: ["Chechen", "ce"],
+ 219: ["Church", "cu"], # macrolanguage
+ 220: ["Chuvash", "cv"],
+ 221: ["Cree", "cr"], # macrolanguage
+ 222: ["Haitian", "ht"],
+ 223: ["Herero", "hz"],
+ 224: ["Hiri Motu", "ho"],
+ 225: ["Kanuri", "kr"], # macrolanguage
+ 226: ["Komi", "kv"], # macrolanguage
+ 227: ["Kongo", "kg"], # macrolanguage
+ 228: ["Kwanyama", "kj"],
+ 229: ["Limburgish", "li"],
+ 230: ["Luba Katanga", "lu"],
+ 231: ["Luxembourgish", "lb"],
+ 232: ["Navaho", "nv"],
+ 233: ["Ndonga", "ng"],
+ 234: ["Ojibwa", "oj"], # macrolanguage
+ 235: ["Pali", "pi"], # macrolanguage
+ 236: ["Walloon", "wa"],
+ 237: ["Aghem", "agq"],
+ 238: ["Basaa", "bas"],
+ 239: ["Zarma", "dje"],
+ 240: ["Duala", "dua"],
+ 241: ["Jola Fonyi", "dyo"],
+ 242: ["Ewondo", "ewo"],
+ 243: ["Bafia", "ksf"],
+ 244: ["Makhuwa Meetto", "mgh"],
+ 245: ["Mundang", "mua"],
+ 246: ["Kwasio", "nmg"],
+ 247: ["Nuer", "nus"],
+ 248: ["Sakha", "sah"],
+ 249: ["Sangu", "sbp"],
+ 250: ["Congo Swahili", "swc"],
+ 251: ["Tasawaq", "twq"],
+ 252: ["Vai", "vai"],
+ 253: ["Walser", "wae"],
+ 254: ["Yangben", "yav"],
+ 255: ["Avestan", "ae"],
+ 256: ["Asturian", "ast"],
+ 257: ["Ngomba", "jgo"],
+ 258: ["Kako", "kkj"],
+ 259: ["Meta", "mgo"],
+ 260: ["Ngiemboon", "nnh"],
+ 261: ["Aragonese", "an"],
+ 262: ["Akkadian", "akk"],
+ 263: ["Ancient Egyptian", "egy"],
+ 264: ["Ancient Greek", "grc"],
+ 265: ["Aramaic", "arc"],
+ 266: ["Balinese", "ban"],
+ 267: ["Bamun", "bax"],
+ 268: ["Batak Toba", "bbc"],
+ 269: ["Buginese", "bug"],
+ 270: ["Buhid", "bku"],
+ 271: ["Carian", "xcr"],
+ 272: ["Chakma", "ccp"],
+ 273: ["Classical Mandaic", "myz"],
+ 274: ["Coptic", "cop"],
+ 275: ["Dogri", "doi"], # macrolanguage
+ 276: ["Eastern Cham", "cjm"],
+ 277: ["Eastern Kayah", "eky"],
+ 278: ["Etruscan", "ett"],
+ 279: ["Gothic", "got"],
+ 280: ["Hanunoo", "hnn"],
+ 281: ["Ingush", "inh"],
+ 282: ["Large Flowery Miao", "hmd"],
+ 283: ["Lepcha", "lep"],
+ 284: ["Limbu", "lif"],
+ 285: ["Lisu", "lis"],
+ 286: ["Lu", "khb"],
+ 287: ["Lycian", "xlc"],
+ 288: ["Lydian", "xld"],
+ 289: ["Mandingo", "man"], # macrolanguage
+ 290: ["Manipuri", "mni"],
+ 291: ["Meroitic", "xmr"],
+ 292: ["Northern Thai", "nod"],
+ 293: ["Old Irish", "sga"],
+ 294: ["Old Norse", "non"],
+ 295: ["Old Persian", "peo"],
+ 296: ["Old Turkish", "otk"],
+ 297: ["Pahlavi", "pal"],
+ 298: ["Parthian", "xpr"],
+ 299: ["Phoenician", "phn"],
+ 300: ["Prakrit Language", "pra"],
+ 301: ["Rejang", "rej"],
+ 302: ["Sabaean", "xsa"],
+ 303: ["Samaritan", "smp"],
+ 304: ["Santali", "sat"],
+ 305: ["Saurashtra", "saz"],
+ 306: ["Sora", "srb"],
+ 307: ["Sylheti", "syl"],
+ 308: ["Tagbanwa", "tbw"],
+ 309: ["Tai Dam", "blt"],
+ 310: ["Tai Nua", "tdd"],
+ 311: ["Ugaritic", "uga"],
+ 312: ["Akoose", "bss"],
+ 313: ["Lakota", "lkt"],
+ 314: ["Standard Moroccan Tamazight", "zgh"],
+ 315: ["Mapuche", "arn"],
+ 316: ["Central Kurdish", "ckb"],
+ 317: ["Lower Sorbian", "dsb"],
+ 318: ["Upper Sorbian", "hsb"],
+ 319: ["Kenyang", "ken"],
+ 320: ["Mohawk", "moh"],
+ 321: ["Nko", "nqo"],
+ 322: ["Prussian", "prg"],
+ 323: ["Kiche", "quc"],
+ 324: ["Southern Sami", "sma"],
+ 325: ["Lule Sami", "smj"],
+ 326: ["Inari Sami", "smn"],
+ 327: ["Skolt Sami", "sms"],
+ 328: ["Warlpiri", "wbp"],
+ 329: ["Manichaean Middle Persian", "xmn"],
+ 330: ["Mende", "men"],
+ 331: ["Ancient North Arabian", "xna"],
+ 332: ["Linear A", "lab"],
+ 333: ["Hmong Njua", "hnj"],
+ 334: ["Ho", "hoc"],
+ 335: ["Lezghian", "lez"],
+ 336: ["Bassa", "bsq"],
+ 337: ["Mono", "mru"],
+ 338: ["Tedim Chin", "ctd"],
+ 339: ["Maithili", "mai"],
+ 340: ["Ahom", "aho"],
+ 341: ["American Sign Language", "ase"],
+ 342: ["Ardhamagadhi Prakrit", "pka"],
+ 343: ["Bhojpuri", "bho"],
+ 344: ["Hieroglyphic Luwian", "hlu"],
+ 345: ["Literary Chinese", "lzh"],
+ 346: ["Mazanderani", "mzn"],
+ 347: ["Mru", "mro"],
+ 348: ["Newari", "new"],
+ 349: ["Northern Luri", "lrc"],
+ 350: ["Palauan", "pau"],
+ 351: ["Papiamento", "pap"],
+ 352: ["Saraiki", "skr"],
+ 353: ["Tokelau", "tkl"],
+ 354: ["Tok Pisin", "tpi"],
+ 355: ["Tuvalu", "tvl"],
+ 356: ["Uncoded Languages", "mis"],
+ 357: ["Cantonese", "yue"],
+ 358: ["Osage", "osa"],
+ 359: ["Tangut", "txg"],
+ 360: ["Ido", "io"],
+ 361: ["Lojban", "jbo"],
+ 362: ["Sicilian", "scn"],
+ 363: ["Southern Kurdish", "sdh"],
+ 364: ["Western Balochi", "bgn"],
+ 365: ["Cebuano", "ceb"],
+ 366: ["Erzya", "myv"],
+}
+
+language_aliases = {
+ # Legacy - should disappear at some point:
+ 'Norwegian': 'NorwegianBokmal',
+ 'Moldavian': 'Romanian',
+ 'SerboCroatian': 'Serbian',
+ 'Tagalog': 'Filipino',
+ 'Twi': 'Akan',
+ # Renamings:
+ 'Afan': 'Oromo',
+ 'Byelorussian': 'Belarusian',
+ 'Bhutani': 'Dzongkha',
+ 'Cambodian': 'Khmer',
+ 'Kurundi': 'Rundi',
+ 'RhaetoRomance': 'Romansh',
+ 'Chewa': 'Nyanja',
+ 'Frisian': 'WesternFrisian',
+ 'Uigur': 'Uighur',
+}
+
+country_list = {
+ 0: ["AnyCountry", "ZZ"],
+ 1: ["Afghanistan", "AF"],
+ 2: ["Albania", "AL"],
+ 3: ["Algeria", "DZ"],
+ 4: ["American Samoa", "AS"],
+ 5: ["Andorra", "AD"],
+ 6: ["Angola", "AO"],
+ 7: ["Anguilla", "AI"],
+ 8: ["Antarctica", "AQ"],
+ 9: ["Antigua And Barbuda", "AG"],
+ 10: ["Argentina", "AR"],
+ 11: ["Armenia", "AM"],
+ 12: ["Aruba", "AW"],
+ 13: ["Australia", "AU"],
+ 14: ["Austria", "AT"],
+ 15: ["Azerbaijan", "AZ"],
+ 16: ["Bahamas", "BS"],
+ 17: ["Bahrain", "BH"],
+ 18: ["Bangladesh", "BD"],
+ 19: ["Barbados", "BB"],
+ 20: ["Belarus", "BY"],
+ 21: ["Belgium", "BE"],
+ 22: ["Belize", "BZ"],
+ 23: ["Benin", "BJ"],
+ 24: ["Bermuda", "BM"],
+ 25: ["Bhutan", "BT"],
+ 26: ["Bolivia", "BO"],
+ 27: ["Bosnia And Herzegowina", "BA"],
+ 28: ["Botswana", "BW"],
+ 29: ["Bouvet Island", "BV"],
+ 30: ["Brazil", "BR"],
+ 31: ["British Indian Ocean Territory", "IO"],
+ 32: ["Brunei", "BN"],
+ 33: ["Bulgaria", "BG"],
+ 34: ["Burkina Faso", "BF"],
+ 35: ["Burundi", "BI"],
+ 36: ["Cambodia", "KH"],
+ 37: ["Cameroon", "CM"],
+ 38: ["Canada", "CA"],
+ 39: ["Cape Verde", "CV"],
+ 40: ["Cayman Islands", "KY"],
+ 41: ["Central African Republic", "CF"],
+ 42: ["Chad", "TD"],
+ 43: ["Chile", "CL"],
+ 44: ["China", "CN"],
+ 45: ["Christmas Island", "CX"],
+ 46: ["Cocos Islands", "CC"],
+ 47: ["Colombia", "CO"],
+ 48: ["Comoros", "KM"],
+ 49: ["Congo Kinshasa", "CD"],
+ 50: ["Congo Brazzaville", "CG"],
+ 51: ["Cook Islands", "CK"],
+ 52: ["Costa Rica", "CR"],
+ 53: ["Ivory Coast", "CI"],
+ 54: ["Croatia", "HR"],
+ 55: ["Cuba", "CU"],
+ 56: ["Cyprus", "CY"],
+ 57: ["Czech Republic", "CZ"],
+ 58: ["Denmark", "DK"],
+ 59: ["Djibouti", "DJ"],
+ 60: ["Dominica", "DM"],
+ 61: ["Dominican Republic", "DO"],
+ 62: ["East Timor", "TL"],
+ 63: ["Ecuador", "EC"],
+ 64: ["Egypt", "EG"],
+ 65: ["El Salvador", "SV"],
+ 66: ["Equatorial Guinea", "GQ"],
+ 67: ["Eritrea", "ER"],
+ 68: ["Estonia", "EE"],
+ 69: ["Ethiopia", "ET"],
+ 70: ["Falkland Islands", "FK"],
+ 71: ["Faroe Islands", "FO"],
+ 72: ["Fiji", "FJ"],
+ 73: ["Finland", "FI"],
+ 74: ["France", "FR"],
+ 75: ["Guernsey", "GG"],
+ 76: ["French Guiana", "GF"],
+ 77: ["French Polynesia", "PF"],
+ 78: ["French Southern Territories", "TF"],
+ 79: ["Gabon", "GA"],
+ 80: ["Gambia", "GM"],
+ 81: ["Georgia", "GE"],
+ 82: ["Germany", "DE"],
+ 83: ["Ghana", "GH"],
+ 84: ["Gibraltar", "GI"],
+ 85: ["Greece", "GR"],
+ 86: ["Greenland", "GL"],
+ 87: ["Grenada", "GD"],
+ 88: ["Guadeloupe", "GP"],
+ 89: ["Guam", "GU"],
+ 90: ["Guatemala", "GT"],
+ 91: ["Guinea", "GN"],
+ 92: ["Guinea Bissau", "GW"],
+ 93: ["Guyana", "GY"],
+ 94: ["Haiti", "HT"],
+ 95: ["Heard And McDonald Islands", "HM"],
+ 96: ["Honduras", "HN"],
+ 97: ["Hong Kong", "HK"],
+ 98: ["Hungary", "HU"],
+ 99: ["Iceland", "IS"],
+ 100: ["India", "IN"],
+ 101: ["Indonesia", "ID"],
+ 102: ["Iran", "IR"],
+ 103: ["Iraq", "IQ"],
+ 104: ["Ireland", "IE"],
+ 105: ["Israel", "IL"],
+ 106: ["Italy", "IT"],
+ 107: ["Jamaica", "JM"],
+ 108: ["Japan", "JP"],
+ 109: ["Jordan", "JO"],
+ 110: ["Kazakhstan", "KZ"],
+ 111: ["Kenya", "KE"],
+ 112: ["Kiribati", "KI"],
+ 113: ["North Korea", "KP"],
+ 114: ["South Korea", "KR"],
+ 115: ["Kuwait", "KW"],
+ 116: ["Kyrgyzstan", "KG"],
+ 117: ["Laos", "LA"],
+ 118: ["Latvia", "LV"],
+ 119: ["Lebanon", "LB"],
+ 120: ["Lesotho", "LS"],
+ 121: ["Liberia", "LR"],
+ 122: ["Libya", "LY"],
+ 123: ["Liechtenstein", "LI"],
+ 124: ["Lithuania", "LT"],
+ 125: ["Luxembourg", "LU"],
+ 126: ["Macau", "MO"],
+ 127: ["Macedonia", "MK"],
+ 128: ["Madagascar", "MG"],
+ 129: ["Malawi", "MW"],
+ 130: ["Malaysia", "MY"],
+ 131: ["Maldives", "MV"],
+ 132: ["Mali", "ML"],
+ 133: ["Malta", "MT"],
+ 134: ["Marshall Islands", "MH"],
+ 135: ["Martinique", "MQ"],
+ 136: ["Mauritania", "MR"],
+ 137: ["Mauritius", "MU"],
+ 138: ["Mayotte", "YT"],
+ 139: ["Mexico", "MX"],
+ 140: ["Micronesia", "FM"],
+ 141: ["Moldova", "MD"],
+ 142: ["Monaco", "MC"],
+ 143: ["Mongolia", "MN"],
+ 144: ["Montserrat", "MS"],
+ 145: ["Morocco", "MA"],
+ 146: ["Mozambique", "MZ"],
+ 147: ["Myanmar", "MM"],
+ 148: ["Namibia", "NA"],
+ 149: ["Nauru", "NR"],
+ 150: ["Nepal", "NP"],
+ 151: ["Netherlands", "NL"],
+ 152: ["Cura Sao", "CW"],
+ 153: ["New Caledonia", "NC"],
+ 154: ["New Zealand", "NZ"],
+ 155: ["Nicaragua", "NI"],
+ 156: ["Niger", "NE"],
+ 157: ["Nigeria", "NG"],
+ 158: ["Niue", "NU"],
+ 159: ["Norfolk Island", "NF"],
+ 160: ["Northern Mariana Islands", "MP"],
+ 161: ["Norway", "NO"],
+ 162: ["Oman", "OM"],
+ 163: ["Pakistan", "PK"],
+ 164: ["Palau", "PW"],
+ 165: ["Palestinian Territories", "PS"],
+ 166: ["Panama", "PA"],
+ 167: ["Papua New Guinea", "PG"],
+ 168: ["Paraguay", "PY"],
+ 169: ["Peru", "PE"],
+ 170: ["Philippines", "PH"],
+ 171: ["Pitcairn", "PN"],
+ 172: ["Poland", "PL"],
+ 173: ["Portugal", "PT"],
+ 174: ["Puerto Rico", "PR"],
+ 175: ["Qatar", "QA"],
+ 176: ["Reunion", "RE"],
+ 177: ["Romania", "RO"],
+ 178: ["Russia", "RU"],
+ 179: ["Rwanda", "RW"],
+ 180: ["Saint Kitts And Nevis", "KN"],
+ 181: ["Saint Lucia", "LC"],
+ 182: ["Saint Vincent And The Grenadines", "VC"],
+ 183: ["Samoa", "WS"],
+ 184: ["San Marino", "SM"],
+ 185: ["Sao Tome And Principe", "ST"],
+ 186: ["Saudi Arabia", "SA"],
+ 187: ["Senegal", "SN"],
+ 188: ["Seychelles", "SC"],
+ 189: ["Sierra Leone", "SL"],
+ 190: ["Singapore", "SG"],
+ 191: ["Slovakia", "SK"],
+ 192: ["Slovenia", "SI"],
+ 193: ["Solomon Islands", "SB"],
+ 194: ["Somalia", "SO"],
+ 195: ["South Africa", "ZA"],
+ 196: ["South Georgia And The South Sandwich Islands", "GS"],
+ 197: ["Spain", "ES"],
+ 198: ["Sri Lanka", "LK"],
+ 199: ["Saint Helena", "SH"],
+ 200: ["Saint Pierre And Miquelon", "PM"],
+ 201: ["Sudan", "SD"],
+ 202: ["Suriname", "SR"],
+ 203: ["Svalbard And Jan Mayen Islands", "SJ"],
+ 204: ["Swaziland", "SZ"],
+ 205: ["Sweden", "SE"],
+ 206: ["Switzerland", "CH"],
+ 207: ["Syria", "SY"],
+ 208: ["Taiwan", "TW"],
+ 209: ["Tajikistan", "TJ"],
+ 210: ["Tanzania", "TZ"],
+ 211: ["Thailand", "TH"],
+ 212: ["Togo", "TG"],
+ 213: ["Tokelau", "TK"],
+ 214: ["Tonga", "TO"],
+ 215: ["Trinidad And Tobago", "TT"],
+ 216: ["Tunisia", "TN"],
+ 217: ["Turkey", "TR"],
+ 218: ["Turkmenistan", "TM"],
+ 219: ["Turks And Caicos Islands", "TC"],
+ 220: ["Tuvalu", "TV"],
+ 221: ["Uganda", "UG"],
+ 222: ["Ukraine", "UA"],
+ 223: ["United Arab Emirates", "AE"],
+ 224: ["United Kingdom", "GB"],
+ 225: ["United States", "US"],
+ 226: ["United States Minor Outlying Islands", "UM"],
+ 227: ["Uruguay", "UY"],
+ 228: ["Uzbekistan", "UZ"],
+ 229: ["Vanuatu", "VU"],
+ 230: ["Vatican City State", "VA"],
+ 231: ["Venezuela", "VE"],
+ 232: ["Vietnam", "VN"],
+ 233: ["British Virgin Islands", "VG"],
+ 234: ["United States Virgin Islands", "VI"],
+ 235: ["Wallis And Futuna Islands", "WF"],
+ 236: ["Western Sahara", "EH"],
+ 237: ["Yemen", "YE"],
+ 238: ["Canary Islands", "IC"],
+ 239: ["Zambia", "ZM"],
+ 240: ["Zimbabwe", "ZW"],
+ 241: ["Clipperton Island", "CP"],
+ 242: ["Montenegro", "ME"],
+ 243: ["Serbia", "RS"],
+ 244: ["Saint Barthelemy", "BL"],
+ 245: ["Saint Martin", "MF"],
+ 246: ["Latin America", "419"],
+ 247: ["Ascension Island", "AC"],
+ 248: ["Aland Islands", "AX"],
+ 249: ["Diego Garcia", "DG"],
+ 250: ["Ceuta And Melilla", "EA"],
+ 251: ["Isle Of Man", "IM"],
+ 252: ["Jersey", "JE"],
+ 253: ["Tristan Da Cunha", "TA"],
+ 254: ["South Sudan", "SS"],
+ 255: ["Bonaire", "BQ"],
+ 256: ["Sint Maarten", "SX"],
+ 257: ["Kosovo", "XK"],
+ 258: ["European Union", "EU"],
+ 259: ["Outlying Oceania", "QO"],
+ 260: ["World", "001"],
+ 261: ["Europe", "150"],
+}
+
+country_aliases = {
+ # Deprecated:
+ 'Tokelau': 'TokelauCountry',
+ 'Tuvalu': 'TuvaluCountry',
+ # Renamings:
+ 'DemocraticRepublicOfCongo': 'CongoKinshasa',
+ 'PeoplesRepublicOfCongo': 'CongoBrazzaville',
+ 'DemocraticRepublicOfKorea': 'NorthKorea',
+ 'RepublicOfKorea': 'SouthKorea',
+ 'RussianFederation': 'Russia',
+ 'SyrianArabRepublic': 'Syria',
+ 'LatinAmericaAndTheCaribbean': 'LatinAmerica',
+}
+
+script_list = {
+ 0: ["AnyScript", "Zzzz"],
+ 1: ["Arabic", "Arab"],
+ 2: ["Cyrillic", "Cyrl"],
+ 3: ["Deseret", "Dsrt"],
+ 4: ["Gurmukhi", "Guru"],
+ 5: ["Simplified Han", "Hans"],
+ 6: ["Traditional Han", "Hant"],
+ 7: ["Latin", "Latn"],
+ 8: ["Mongolian", "Mong"],
+ 9: ["Tifinagh", "Tfng"],
+ 10: ["Armenian", "Armn"],
+ 11: ["Bengali", "Beng"],
+ 12: ["Cherokee", "Cher"],
+ 13: ["Devanagari", "Deva"],
+ 14: ["Ethiopic", "Ethi"],
+ 15: ["Georgian", "Geor"],
+ 16: ["Greek", "Grek"],
+ 17: ["Gujarati", "Gujr"],
+ 18: ["Hebrew", "Hebr"],
+ 19: ["Japanese", "Jpan"],
+ 20: ["Khmer", "Khmr"],
+ 21: ["Kannada", "Knda"],
+ 22: ["Korean", "Kore"],
+ 23: ["Lao", "Laoo"],
+ 24: ["Malayalam", "Mlym"],
+ 25: ["Myanmar", "Mymr"],
+ 26: ["Oriya", "Orya"],
+ 27: ["Tamil", "Taml"],
+ 28: ["Telugu", "Telu"],
+ 29: ["Thaana", "Thaa"],
+ 30: ["Thai", "Thai"],
+ 31: ["Tibetan", "Tibt"],
+ 32: ["Sinhala", "Sinh"],
+ 33: ["Syriac", "Syrc"],
+ 34: ["Yi", "Yiii"],
+ 35: ["Vai", "Vaii"],
+ 36: ["Avestan", "Avst"],
+ 37: ["Balinese", "Bali"],
+ 38: ["Bamum", "Bamu"],
+ 39: ["Batak", "Batk"],
+ 40: ["Bopomofo", "Bopo"],
+ 41: ["Brahmi", "Brah"],
+ 42: ["Buginese", "Bugi"],
+ 43: ["Buhid", "Buhd"],
+ 44: ["Canadian Aboriginal", "Cans"],
+ 45: ["Carian", "Cari"],
+ 46: ["Chakma", "Cakm"],
+ 47: ["Cham", "Cham"],
+ 48: ["Coptic", "Copt"],
+ 49: ["Cypriot", "Cprt"],
+ 50: ["Egyptian Hieroglyphs", "Egyp"],
+ 51: ["Fraser", "Lisu"],
+ 52: ["Glagolitic", "Glag"],
+ 53: ["Gothic", "Goth"],
+ 54: ["Han", "Hani"],
+ 55: ["Hangul", "Hang"],
+ 56: ["Hanunoo", "Hano"],
+ 57: ["Imperial Aramaic", "Armi"],
+ 58: ["Inscriptional Pahlavi", "Phli"],
+ 59: ["Inscriptional Parthian", "Prti"],
+ 60: ["Javanese", "Java"],
+ 61: ["Kaithi", "Kthi"],
+ 62: ["Katakana", "Kana"],
+ 63: ["Kayah Li", "Kali"],
+ 64: ["Kharoshthi", "Khar"],
+ 65: ["Lanna", "Lana"],
+ 66: ["Lepcha", "Lepc"],
+ 67: ["Limbu", "Limb"],
+ 68: ["Linear B", "Linb"],
+ 69: ["Lycian", "Lyci"],
+ 70: ["Lydian", "Lydi"],
+ 71: ["Mandaean", "Mand"],
+ 72: ["Meitei Mayek", "Mtei"],
+ 73: ["Meroitic", "Mero"],
+ 74: ["Meroitic Cursive", "Merc"],
+ 75: ["Nko", "Nkoo"],
+ 76: ["New Tai Lue", "Talu"],
+ 77: ["Ogham", "Ogam"],
+ 78: ["Ol Chiki", "Olck"],
+ 79: ["Old Italic", "Ital"],
+ 80: ["Old Persian", "Xpeo"],
+ 81: ["Old South Arabian", "Sarb"],
+ 82: ["Orkhon", "Orkh"],
+ 83: ["Osmanya", "Osma"],
+ 84: ["Phags Pa", "Phag"],
+ 85: ["Phoenician", "Phnx"],
+ 86: ["Pollard Phonetic", "Plrd"],
+ 87: ["Rejang", "Rjng"],
+ 88: ["Runic", "Runr"],
+ 89: ["Samaritan", "Samr"],
+ 90: ["Saurashtra", "Saur"],
+ 91: ["Sharada", "Shrd"],
+ 92: ["Shavian", "Shaw"],
+ 93: ["Sora Sompeng", "Sora"],
+ 94: ["Cuneiform", "Xsux"],
+ 95: ["Sundanese", "Sund"],
+ 96: ["Syloti Nagri", "Sylo"],
+ 97: ["Tagalog", "Tglg"],
+ 98: ["Tagbanwa", "Tagb"],
+ 99: ["Tai Le", "Tale"],
+ 100: ["Tai Viet", "Tavt"],
+ 101: ["Takri", "Takr"],
+ 102: ["Ugaritic", "Ugar"],
+ 103: ["Braille", "Brai"],
+ 104: ["Hiragana", "Hira"],
+ 105: ["Caucasian Albanian", "Aghb"],
+ 106: ["Bassa Vah", "Bass"],
+ 107: ["Duployan", "Dupl"],
+ 108: ["Elbasan", "Elba"],
+ 109: ["Grantha", "Gran"],
+ 110: ["Pahawh Hmong", "Hmng"],
+ 111: ["Khojki", "Khoj"],
+ 112: ["Linear A", "Lina"],
+ 113: ["Mahajani", "Mahj"],
+ 114: ["Manichaean", "Mani"],
+ 115: ["Mende Kikakui", "Mend"],
+ 116: ["Modi", "Modi"],
+ 117: ["Mro", "Mroo"],
+ 118: ["Old North Arabian", "Narb"],
+ 119: ["Nabataean", "Nbat"],
+ 120: ["Palmyrene", "Palm"],
+ 121: ["Pau Cin Hau", "Pauc"],
+ 122: ["Old Permic", "Perm"],
+ 123: ["Psalter Pahlavi", "Phlp"],
+ 124: ["Siddham", "Sidd"],
+ 125: ["Khudawadi", "Sind"],
+ 126: ["Tirhuta", "Tirh"],
+ 127: ["Varang Kshiti", "Wara"],
+ 128: ["Ahom", "Ahom"],
+ 129: ["Anatolian Hieroglyphs", "Hluw"],
+ 130: ["Hatran", "Hatr"],
+ 131: ["Multani", "Mult"],
+ 132: ["Old Hungarian", "Hung"],
+ 133: ["Sign Writing", "Sgnw"],
+ 134: ["Adlam", "Adlm"],
+ 135: ["Bhaiksuki", "Bhks"],
+ 136: ["Marchen", "Marc"],
+ 137: ["Newa", "Newa"],
+ 138: ["Osage", "Osge"],
+ 139: ["Tangut", "Tang"],
+ 140: ["Han with Bopomofo", "Hanb"],
+ 141: ["Jamo", "Jamo"],
+}
+
+script_aliases = {
+ # Renamings:
+ 'SimplifiedChineseScript': 'SimplifiedHanScript',
+ 'TraditionalChineseScript': 'TraditionalHanScript',
+}
+
+def countryCodeToId(code):
+ if not code:
+ return 0
+ for country_id in country_list:
+ if country_list[country_id][1] == code:
+ return country_id
+ return -1
+
+def languageCodeToId(code):
+ if not code:
+ return 0
+ for language_id in language_list:
+ if language_list[language_id][1] == code:
+ return language_id
+ return -1
+
+def scriptCodeToId(code):
+ if not code:
+ return 0
+ for script_id in script_list:
+ if script_list[script_id][1] == code:
+ return script_id
+ return -1
diff --git a/util/local_database/formattags.txt b/util/locale_database/formattags.txt
index 5138c37a81..5138c37a81 100644
--- a/util/local_database/formattags.txt
+++ b/util/locale_database/formattags.txt
diff --git a/util/local_database/localexml.py b/util/locale_database/localexml.py
index e95b3aebcc..e95b3aebcc 100644
--- a/util/local_database/localexml.py
+++ b/util/locale_database/localexml.py
diff --git a/util/local_database/qlocalexml2cpp.py b/util/locale_database/qlocalexml2cpp.py
index fb5ae5ba54..2dad2dd57a 100755
--- a/util/local_database/qlocalexml2cpp.py
+++ b/util/locale_database/qlocalexml2cpp.py
@@ -370,7 +370,7 @@ def main():
Do not edit this section: instead regenerate it using
cldr2qlocalexml.py and qlocalexml2cpp.py on updated (or
- edited) CLDR data; see qtbase/util/local_database/.
+ edited) CLDR data; see qtbase/util/locale_database/.
*/
""" % (str(datetime.date.today()), cldr_version) )
diff --git a/util/local_database/testlocales/localemodel.cpp b/util/locale_database/testlocales/localemodel.cpp
index d380d01e09..d380d01e09 100644
--- a/util/local_database/testlocales/localemodel.cpp
+++ b/util/locale_database/testlocales/localemodel.cpp
diff --git a/util/local_database/testlocales/localemodel.h b/util/locale_database/testlocales/localemodel.h
index b24fc5f4c6..b24fc5f4c6 100644
--- a/util/local_database/testlocales/localemodel.h
+++ b/util/locale_database/testlocales/localemodel.h
diff --git a/util/local_database/testlocales/localewidget.cpp b/util/locale_database/testlocales/localewidget.cpp
index 3ff7f73a98..3ff7f73a98 100644
--- a/util/local_database/testlocales/localewidget.cpp
+++ b/util/locale_database/testlocales/localewidget.cpp
diff --git a/util/local_database/testlocales/localewidget.h b/util/locale_database/testlocales/localewidget.h
index 896a6e5229..896a6e5229 100644
--- a/util/local_database/testlocales/localewidget.h
+++ b/util/locale_database/testlocales/localewidget.h
diff --git a/util/local_database/testlocales/main.cpp b/util/locale_database/testlocales/main.cpp
index 0c3c45f989..0c3c45f989 100644
--- a/util/local_database/testlocales/main.cpp
+++ b/util/locale_database/testlocales/main.cpp
diff --git a/util/local_database/testlocales/testlocales.pro b/util/locale_database/testlocales/testlocales.pro
index a9a6247f96..a9a6247f96 100644
--- a/util/local_database/testlocales/testlocales.pro
+++ b/util/locale_database/testlocales/testlocales.pro
diff --git a/util/local_database/xpathlite.py b/util/locale_database/xpathlite.py
index a1ed42812d..97efaaab41 100644
--- a/util/local_database/xpathlite.py
+++ b/util/locale_database/xpathlite.py
@@ -78,14 +78,38 @@ def findChild(parent, tag_name, arg_name=None, arg_value=None, draft=None):
return node
return False
+def codeMapsFromFile(file):
+ """Extract mappings of language, script and country codes to names.
+
+ The file shall typically be common/main/en.xml, which contains a
+ localeDisplayNames element with children languages, scripts and
+ territories; each element in each of these has a code as its type
+ attribute and its name as element content. This returns a mapping
+ withe keys 'language', 'script' and 'country', each of which
+ has, as value, a mapping of the relevant codes to names.
+ """
+ parent = findChild(findChild(parseDoc(file), 'ldml'), 'localeDisplayNames')
+ keys, result = {'languages': 'language', 'scripts': 'script', 'territories': 'country'}, {}
+ for src, dst in keys.items():
+ child = findChild(parent, src)
+ data = result[dst] = {}
+ for elt in child.childNodes:
+ if elt.attributes and elt.attributes.has_key('type'):
+ key, value = elt.attributes['type'].value, elt.childNodes[0].wholeText
+ # Don't over-write previously-read data for an alt form:
+ if elt.attributes.has_key('alt') and data.has_key(key):
+ continue
+ data[key] = value
+
+ return result
+
def findTagsInFile(file, path):
doc = parseDoc(file)
elt = doc.documentElement
tag_spec_list = path.split("/")
last_entry = None
- for i in range(len(tag_spec_list)):
- tag_spec = tag_spec_list[i]
+ for tag_spec in tag_spec_list:
tag_name = tag_spec
arg_name = 'type'
arg_value = ''
@@ -213,12 +237,8 @@ def _fixedLookupChain(dirname, name):
return items
def _findEntry(base, path, draft=None, attribute=None):
- file = base
if base.endswith(".xml"):
- filename = base
base = base[:-4]
- else:
- file = base + ".xml"
(dirname, filename) = os.path.split(base)
items = _fixedLookupChain(dirname, filename)
@@ -261,7 +281,7 @@ def findEntry(base, path, draft=None, attribute=None):
if result:
return result
if not aliaspath:
- raise Error("findEntry: fatal error: %s: can not find key %s" % (filename, path))
+ raise Error("findEntry: fatal error: %s: cannot find key %s" % (filename, path))
path = aliaspath
return result
diff --git a/src/tools/qfloat16-tables/gen_qfloat16_tables.cpp b/util/qfloat16-tables/gen_qfloat16_tables.cpp
index f5051e25fc..faedb5073c 100644
--- a/src/tools/qfloat16-tables/gen_qfloat16_tables.cpp
+++ b/util/qfloat16-tables/gen_qfloat16_tables.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 by Southwest Research Institute (R)
+** Copyright (C) 2019 Intel Corporation.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -37,13 +38,25 @@
**
****************************************************************************/
-#include <qfile.h>
-#include <qdebug.h>
-
-quint32 convertmantissa(qint32 i)
+#include <stdint.h>
+#include <stdio.h>
+
+/*
+ * This tool generates the tables used by qfloat16 to implement a
+ * software-emulated version of IEEE 754 binary16. qfloat16 automatically uses
+ * CPU instructions to convert to and from float (IEEE 754 binary32), but if
+ * the CPU is not guaranteed to have those instructions available at compile
+ * time, then qfloat16 needs the tables to perform the conversion with
+ * reasonable performance.
+ *
+ * Because Qt requires float to be IEEE 754 binary32, these tables are
+ * platform-independent and will never change.
+ */
+
+uint32_t convertmantissa(int32_t i)
{
- quint32 m = i << 13; // Zero pad mantissa bits
- quint32 e = 0; // Zero exponent
+ uint32_t m = i << 13; // Zero pad mantissa bits
+ uint32_t e = 0; // Zero exponent
while (!(m & 0x00800000)) { // While not normalized
e -= 0x00800000; // Decrement exponent (1<<23)
@@ -56,59 +69,48 @@ quint32 convertmantissa(qint32 i)
// we first build these tables up and then print them out as a separate step in order
// to more closely map the implementation given in the paper.
-quint32 basetable[512];
-quint32 shifttable[512];
-
-#define PRINTHEX(a) "0x" + QByteArray::number(a,16).toUpper() + "U,\n"
+uint32_t basetable[512];
+uint32_t shifttable[512];
-qint32 main(qint32 argc, char **argv)
+int main()
{
- if (argc < 2) {
- qWarning() << "Must provide output filename as argument.";
- return -1;
- }
-
- QFile fid(argv[1]);
- if (!fid.open(QIODevice::WriteOnly | QIODevice::Text)) {
- qWarning() << "Abort: Failed to open/create file" << fid.fileName();
- return -1;
- }
- quint32 i;
+ uint32_t i;
- fid.write("/* This file was generated by gen_qfloat16_tables.cpp */\n\n");
- fid.write("#include <QtCore/qfloat16.h>\n\n");
+ printf("/* This file was generated by util/qfloat16-tables/gen_qfloat16_tables.cpp */\n\n");
+ printf("#include <QtCore/qfloat16.h>\n\n");
- fid.write("QT_BEGIN_NAMESPACE\n\n");
+ printf("QT_BEGIN_NAMESPACE\n\n");
+ printf("#if !defined(__F16C__) && !defined(__ARM_FP16_FORMAT_IEEE)\n\n");
- fid.write("const quint32 qfloat16::mantissatable[2048] = {\n");
- fid.write("0,\n");
+ printf("const quint32 qfloat16::mantissatable[2048] = {\n");
+ printf("0,\n");
for (i = 1; i < 1024; i++)
- fid.write(PRINTHEX(convertmantissa(i)));
+ printf("0x%XU,\n", convertmantissa(i));
for (i = 1024; i < 2048; i++)
- fid.write(PRINTHEX(0x38000000U + ((i - 1024) << 13)));
- fid.write("};\n\n");
+ printf("0x%XU,\n", 0x38000000U + ((i - 1024) << 13));
+ printf("};\n\n");
- fid.write("const quint32 qfloat16::exponenttable[64] = {\n");
- fid.write("0,\n");
+ printf("const quint32 qfloat16::exponenttable[64] = {\n");
+ printf("0,\n");
for (i = 1; i < 31; i++)
- fid.write(PRINTHEX(i << 23));
- fid.write("0x47800000U,\n"); // 31
- fid.write("0x80000000U,\n"); // 32
+ printf("0x%XU,\n", i << 23);
+ printf("0x47800000U,\n"); // 31
+ printf("0x80000000U,\n"); // 32
for (i = 33; i < 63; i++)
- fid.write(PRINTHEX(0x80000000U + ((i - 32) << 23)));
- fid.write("0xC7800000U,\n"); // 63
- fid.write("};\n\n");
+ printf("0x%XU,\n", 0x80000000U + ((i - 32) << 23));
+ printf("0xC7800000U,\n"); // 63
+ printf("};\n\n");
- fid.write("const quint32 qfloat16::offsettable[64] = {\n");
- fid.write("0,\n");
+ printf("const quint32 qfloat16::offsettable[64] = {\n");
+ printf("0,\n");
for (i = 1; i < 32; i++)
- fid.write("1024U,\n");
- fid.write("0,\n");
+ printf("1024U,\n");
+ printf("0,\n");
for (i = 33; i < 64; i++)
- fid.write("1024U,\n");
- fid.write("};\n\n");
+ printf("1024U,\n");
+ printf("};\n\n");
- qint32 e;
+ int32_t e;
for (i = 0; i < 256; ++i) {
e = i - 127;
if (e < -24) { // Very small numbers map to zero
@@ -143,19 +145,19 @@ qint32 main(qint32 argc, char **argv)
}
}
- fid.write("const quint32 qfloat16::basetable[512] = {\n");
+ printf("const quint32 qfloat16::basetable[512] = {\n");
for (i = 0; i < 512; i++)
- fid.write(PRINTHEX(basetable[i]));
+ printf("0x%XU,\n", basetable[i]);
- fid.write("};\n\n");
+ printf("};\n\n");
- fid.write("const quint32 qfloat16::shifttable[512] = {\n");
+ printf("const quint32 qfloat16::shifttable[512] = {\n");
for (i = 0; i < 512; i++)
- fid.write(PRINTHEX(shifttable[i]));
+ printf("0x%XU,\n", shifttable[i]);
- fid.write("};\n\n");
+ printf("};\n\n");
- fid.write("QT_END_NAMESPACE\n");
- fid.close();
+ printf("#endif // !__F16C__ && !__ARM_FP16_FORMAT_IEEE\n\n");
+ printf("QT_END_NAMESPACE\n");
return 0;
}
diff --git a/util/qfloat16-tables/qfloat16-tables.pro b/util/qfloat16-tables/qfloat16-tables.pro
new file mode 100644
index 0000000000..3c9a1e61a3
--- /dev/null
+++ b/util/qfloat16-tables/qfloat16-tables.pro
@@ -0,0 +1,2 @@
+QT = core
+SOURCES += gen_qfloat16_tables.cpp
diff --git a/util/unicode/main.cpp b/util/unicode/main.cpp
index 22a4405ca9..8576f00e35 100644
--- a/util/unicode/main.cpp
+++ b/util/unicode/main.cpp
@@ -818,8 +818,8 @@ static const char *property_string =
" ushort lineBreakClass : 6; /* 6 used */\n"
" ushort script : 8;\n"
"};\n\n"
- "Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4) Q_DECL_NOTHROW;\n"
- "Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2) Q_DECL_NOTHROW;\n"
+ "Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4) noexcept;\n"
+ "Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2) noexcept;\n"
"\n"
"struct LowercaseTraits\n"
"{\n"
@@ -855,20 +855,20 @@ static const char *property_string =
"\n";
static const char *methods =
- "Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(uint ucs4) Q_DECL_NOTHROW;\n"
- "inline GraphemeBreakClass graphemeBreakClass(QChar ch) Q_DECL_NOTHROW\n"
+ "Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(uint ucs4) noexcept;\n"
+ "inline GraphemeBreakClass graphemeBreakClass(QChar ch) noexcept\n"
"{ return graphemeBreakClass(ch.unicode()); }\n"
"\n"
- "Q_CORE_EXPORT WordBreakClass QT_FASTCALL wordBreakClass(uint ucs4) Q_DECL_NOTHROW;\n"
- "inline WordBreakClass wordBreakClass(QChar ch) Q_DECL_NOTHROW\n"
+ "Q_CORE_EXPORT WordBreakClass QT_FASTCALL wordBreakClass(uint ucs4) noexcept;\n"
+ "inline WordBreakClass wordBreakClass(QChar ch) noexcept\n"
"{ return wordBreakClass(ch.unicode()); }\n"
"\n"
- "Q_CORE_EXPORT SentenceBreakClass QT_FASTCALL sentenceBreakClass(uint ucs4) Q_DECL_NOTHROW;\n"
- "inline SentenceBreakClass sentenceBreakClass(QChar ch) Q_DECL_NOTHROW\n"
+ "Q_CORE_EXPORT SentenceBreakClass QT_FASTCALL sentenceBreakClass(uint ucs4) noexcept;\n"
+ "inline SentenceBreakClass sentenceBreakClass(QChar ch) noexcept\n"
"{ return sentenceBreakClass(ch.unicode()); }\n"
"\n"
- "Q_CORE_EXPORT LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4) Q_DECL_NOTHROW;\n"
- "inline LineBreakClass lineBreakClass(QChar ch) Q_DECL_NOTHROW\n"
+ "Q_CORE_EXPORT LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4) noexcept;\n"
+ "inline LineBreakClass lineBreakClass(QChar ch) noexcept\n"
"{ return lineBreakClass(ch.unicode()); }\n"
"\n";
@@ -2521,42 +2521,42 @@ static QByteArray createPropertyInfo()
out += "\n};\n\n";
- out += "Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(uint ucs4) Q_DECL_NOTHROW\n"
+ out += "Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(uint ucs4) noexcept\n"
"{\n"
" return uc_properties + GET_PROP_INDEX(ucs4);\n"
"}\n"
"\n"
- "Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(ushort ucs2) Q_DECL_NOTHROW\n"
+ "Q_DECL_CONST_FUNCTION static inline const Properties *qGetProp(ushort ucs2) noexcept\n"
"{\n"
" return uc_properties + GET_PROP_INDEX_UCS2(ucs2);\n"
"}\n"
"\n"
- "Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4) Q_DECL_NOTHROW\n"
+ "Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4) noexcept\n"
"{\n"
" return qGetProp(ucs4);\n"
"}\n"
"\n"
- "Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2) Q_DECL_NOTHROW\n"
+ "Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2) noexcept\n"
"{\n"
" return qGetProp(ucs2);\n"
"}\n\n";
- out += "Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(uint ucs4) Q_DECL_NOTHROW\n"
+ out += "Q_CORE_EXPORT GraphemeBreakClass QT_FASTCALL graphemeBreakClass(uint ucs4) noexcept\n"
"{\n"
" return static_cast<GraphemeBreakClass>(qGetProp(ucs4)->graphemeBreakClass);\n"
"}\n"
"\n"
- "Q_CORE_EXPORT WordBreakClass QT_FASTCALL wordBreakClass(uint ucs4) Q_DECL_NOTHROW\n"
+ "Q_CORE_EXPORT WordBreakClass QT_FASTCALL wordBreakClass(uint ucs4) noexcept\n"
"{\n"
" return static_cast<WordBreakClass>(qGetProp(ucs4)->wordBreakClass);\n"
"}\n"
"\n"
- "Q_CORE_EXPORT SentenceBreakClass QT_FASTCALL sentenceBreakClass(uint ucs4) Q_DECL_NOTHROW\n"
+ "Q_CORE_EXPORT SentenceBreakClass QT_FASTCALL sentenceBreakClass(uint ucs4) noexcept\n"
"{\n"
" return static_cast<SentenceBreakClass>(qGetProp(ucs4)->sentenceBreakClass);\n"
"}\n"
"\n"
- "Q_CORE_EXPORT LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4) Q_DECL_NOTHROW\n"
+ "Q_CORE_EXPORT LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4) noexcept\n"
"{\n"
" return static_cast<LineBreakClass>(qGetProp(ucs4)->lineBreakClass);\n"
"}\n"